Home | History | Annotate | Download | only in attrib
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2010  Nokia Corporation
      6  *  Copyright (C) 2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 /* GATT Profile Attribute types */
     26 #define GATT_PRIM_SVC_UUID		0x2800
     27 #define GATT_SND_SVC_UUID		0x2801
     28 #define GATT_INCLUDE_UUID		0x2802
     29 #define GATT_CHARAC_UUID		0x2803
     30 
     31 /* GATT Characteristic Types */
     32 #define GATT_CHARAC_DEVICE_NAME			0x2A00
     33 #define GATT_CHARAC_APPEARANCE			0x2A01
     34 #define GATT_CHARAC_PERIPHERAL_PRIV_FLAG	0x2A02
     35 #define GATT_CHARAC_RECONNECTION_ADDRESS	0x2A03
     36 #define GATT_CHARAC_PERIPHERAL_PREF_CONN	0x2A04
     37 #define GATT_CHARAC_SERVICE_CHANGED		0x2A05
     38 
     39 /* GATT Characteristic Descriptors */
     40 #define GATT_CHARAC_EXT_PROPER_UUID	0x2900
     41 #define GATT_CHARAC_USER_DESC_UUID	0x2901
     42 #define GATT_CLIENT_CHARAC_CFG_UUID	0x2902
     43 #define GATT_SERVER_CHARAC_CFG_UUID	0x2903
     44 #define GATT_CHARAC_FMT_UUID		0x2904
     45 #define GATT_CHARAC_AGREG_FMT_UUID	0x2905
     46 
     47 /* Attribute Protocol Opcodes */
     48 #define ATT_OP_ERROR			0x01
     49 #define ATT_OP_MTU_REQ			0x02
     50 #define ATT_OP_MTU_RESP			0x03
     51 #define ATT_OP_FIND_INFO_REQ		0x04
     52 #define ATT_OP_FIND_INFO_RESP		0x05
     53 #define ATT_OP_FIND_BY_TYPE_REQ		0x06
     54 #define ATT_OP_FIND_BY_TYPE_RESP	0x07
     55 #define ATT_OP_READ_BY_TYPE_REQ		0x08
     56 #define ATT_OP_READ_BY_TYPE_RESP	0x09
     57 #define ATT_OP_READ_REQ			0x0A
     58 #define ATT_OP_READ_RESP		0x0B
     59 #define ATT_OP_READ_BLOB_REQ		0x0C
     60 #define ATT_OP_READ_BLOB_RESP		0x0D
     61 #define ATT_OP_READ_MULTI_REQ		0x0E
     62 #define ATT_OP_READ_MULTI_RESP		0x0F
     63 #define ATT_OP_READ_BY_GROUP_REQ	0x10
     64 #define ATT_OP_READ_BY_GROUP_RESP	0x11
     65 #define ATT_OP_WRITE_REQ		0x12
     66 #define ATT_OP_WRITE_RESP		0x13
     67 #define ATT_OP_WRITE_CMD		0x52
     68 #define ATT_OP_PREP_WRITE_REQ		0x16
     69 #define ATT_OP_PREP_WRITE_RESP		0x17
     70 #define ATT_OP_EXEC_WRITE_REQ		0x18
     71 #define ATT_OP_EXEC_WRITE_RESP		0x19
     72 #define ATT_OP_HANDLE_NOTIFY		0x1B
     73 #define ATT_OP_HANDLE_IND		0x1D
     74 #define ATT_OP_HANDLE_CNF		0x1E
     75 #define ATT_OP_SIGNED_WRITE_CMD		0xD2
     76 
     77 /* Error codes for Error response PDU */
     78 #define ATT_ECODE_INVALID_HANDLE		0x01
     79 #define ATT_ECODE_READ_NOT_PERM			0x02
     80 #define ATT_ECODE_WRITE_NOT_PERM		0x03
     81 #define ATT_ECODE_INVALID_PDU			0x04
     82 #define ATT_ECODE_AUTHENTICATION		0x05
     83 #define ATT_ECODE_REQ_NOT_SUPP			0x06
     84 #define ATT_ECODE_INVALID_OFFSET		0x07
     85 #define ATT_ECODE_AUTHORIZATION			0x08
     86 #define ATT_ECODE_PREP_QUEUE_FULL		0x09
     87 #define ATT_ECODE_ATTR_NOT_FOUND		0x0A
     88 #define ATT_ECODE_ATTR_NOT_LONG			0x0B
     89 #define ATT_ECODE_INSUFF_ENCR_KEY_SIZE		0x0C
     90 #define ATT_ECODE_INVAL_ATTR_VALUE_LEN		0x0D
     91 #define ATT_ECODE_UNLIKELY			0x0E
     92 #define ATT_ECODE_INSUFF_ENC			0x0F
     93 #define ATT_ECODE_UNSUPP_GRP_TYPE		0x10
     94 #define ATT_ECODE_INSUFF_RESOURCES		0x11
     95 /* Application error */
     96 #define ATT_ECODE_IO				0xFF
     97 
     98 /* Characteristic Property bit field */
     99 #define ATT_CHAR_PROPER_BROADCAST		0x01
    100 #define ATT_CHAR_PROPER_READ			0x02
    101 #define ATT_CHAR_PROPER_WRITE_WITHOUT_RESP	0x04
    102 #define ATT_CHAR_PROPER_WRITE			0x08
    103 #define ATT_CHAR_PROPER_NOTIFY			0x10
    104 #define ATT_CHAR_PROPER_INDICATE		0x20
    105 #define ATT_CHAR_PROPER_AUTH			0x40
    106 #define ATT_CHAR_PROPER_EXT_PROPER		0x80
    107 
    108 
    109 #define ATT_MAX_MTU				256
    110 #define ATT_DEFAULT_L2CAP_MTU			48
    111 #define ATT_DEFAULT_LE_MTU			23
    112 
    113 #define ATT_CID					4
    114 #define ATT_PSM					31
    115 
    116 /* Requirements for read/write operations */
    117 enum {
    118 	ATT_NONE,		/* No restrictions */
    119 	ATT_AUTHENTICATION,	/* Authentication required */
    120 	ATT_AUTHORIZATION,	/* Authorization required */
    121 	ATT_NOT_PERMITTED,	/* Operation not permitted */
    122 };
    123 
    124 struct attribute {
    125 	uint16_t handle;
    126 	bt_uuid_t uuid;
    127 	int read_reqs;
    128 	int write_reqs;
    129 	uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
    130 	uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
    131 	gpointer cb_user_data;
    132 	int len;
    133 	uint8_t data[0];
    134 };
    135 
    136 struct att_data_list {
    137 	uint16_t num;
    138 	uint16_t len;
    139 	uint8_t **data;
    140 };
    141 
    142 struct att_range {
    143 	uint16_t start;
    144 	uint16_t end;
    145 };
    146 
    147 struct att_primary {
    148 	char uuid[MAX_LEN_UUID_STR + 1];
    149 	uint16_t start;
    150 	uint16_t end;
    151 };
    152 
    153 struct att_char {
    154 	char uuid[MAX_LEN_UUID_STR + 1];
    155 	uint16_t handle;
    156 	uint8_t properties;
    157 	uint16_t value_handle;
    158 };
    159 
    160 /* These functions do byte conversion */
    161 static inline uint8_t att_get_u8(const void *ptr)
    162 {
    163 	const uint8_t *u8_ptr = ptr;
    164 	return bt_get_unaligned(u8_ptr);
    165 }
    166 
    167 static inline uint16_t att_get_u16(const void *ptr)
    168 {
    169 	const uint16_t *u16_ptr = ptr;
    170 	return btohs(bt_get_unaligned(u16_ptr));
    171 }
    172 
    173 static inline uint32_t att_get_u32(const void *ptr)
    174 {
    175 	const uint32_t *u32_ptr = ptr;
    176 	return btohl(bt_get_unaligned(u32_ptr));
    177 }
    178 
    179 static inline uint128_t att_get_u128(const void *ptr)
    180 {
    181 	const uint128_t *u128_ptr = ptr;
    182 	uint128_t dst;
    183 
    184 	btoh128(u128_ptr, &dst);
    185 
    186 	return dst;
    187 }
    188 
    189 static inline void att_put_u8(uint8_t src, void *dst)
    190 {
    191 	bt_put_unaligned(src, (uint8_t *) dst);
    192 }
    193 
    194 static inline void att_put_u16(uint16_t src, void *dst)
    195 {
    196 	bt_put_unaligned(htobs(src), (uint16_t *) dst);
    197 }
    198 
    199 static inline void att_put_u32(uint32_t src, void *dst)
    200 {
    201 	bt_put_unaligned(htobl(src), (uint32_t *) dst);
    202 }
    203 
    204 static inline void att_put_u128(uint128_t src, void *dst)
    205 {
    206 	uint128_t *d128 = dst;
    207 
    208 	htob128(&src, d128);
    209 }
    210 
    211 static inline void att_put_uuid16(bt_uuid_t src, void *dst)
    212 {
    213 	att_put_u16(src.value.u16, dst);
    214 }
    215 
    216 static inline void att_put_uuid128(bt_uuid_t src, void *dst)
    217 {
    218 	att_put_u128(src.value.u128, dst);
    219 }
    220 
    221 static inline void att_put_uuid(bt_uuid_t src, void *dst)
    222 {
    223 	if (src.type == BT_UUID16)
    224 		att_put_uuid16(src, dst);
    225 	else
    226 		att_put_uuid128(src, dst);
    227 }
    228 
    229 static inline bt_uuid_t att_get_uuid16(const void *ptr)
    230 {
    231 	bt_uuid_t uuid;
    232 
    233 	bt_uuid16_create(&uuid, att_get_u16(ptr));
    234 
    235 	return uuid;
    236 }
    237 
    238 static inline bt_uuid_t att_get_uuid128(const void *ptr)
    239 {
    240 	bt_uuid_t uuid;
    241 	uint128_t value;
    242 
    243 	value  = att_get_u128(ptr);
    244 	bt_uuid128_create(&uuid, value);
    245 
    246 	return uuid;
    247 }
    248 
    249 struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len);
    250 void att_data_list_free(struct att_data_list *list);
    251 
    252 const char *att_ecode2str(uint8_t status);
    253 uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
    254 							uint8_t *pdu, int len);
    255 uint16_t dec_read_by_grp_req(const uint8_t *pdu, int len, uint16_t *start,
    256 						uint16_t *end, bt_uuid_t *uuid);
    257 uint16_t enc_read_by_grp_resp(struct att_data_list *list, uint8_t *pdu, int len);
    258 uint16_t enc_find_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
    259 			const uint8_t *value, int vlen, uint8_t *pdu, int len);
    260 uint16_t dec_find_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
    261 		uint16_t *end, bt_uuid_t *uuid, uint8_t *value, int *vlen);
    262 uint16_t enc_find_by_type_resp(GSList *ranges, uint8_t *pdu, int len);
    263 GSList *dec_find_by_type_resp(const uint8_t *pdu, int len);
    264 struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len);
    265 uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, bt_uuid_t *uuid,
    266 							uint8_t *pdu, int len);
    267 uint16_t dec_read_by_type_req(const uint8_t *pdu, int len, uint16_t *start,
    268 						uint16_t *end, bt_uuid_t *uuid);
    269 uint16_t enc_read_by_type_resp(struct att_data_list *list, uint8_t *pdu,
    270 								int len);
    271 uint16_t enc_write_cmd(uint16_t handle, const uint8_t *value, int vlen,
    272 							uint8_t *pdu, int len);
    273 uint16_t dec_write_cmd(const uint8_t *pdu, int len, uint16_t *handle,
    274 						uint8_t *value, int *vlen);
    275 struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len);
    276 uint16_t enc_write_req(uint16_t handle, const uint8_t *value, int vlen,
    277 							uint8_t *pdu, int len);
    278 uint16_t dec_write_req(const uint8_t *pdu, int len, uint16_t *handle,
    279 						uint8_t *value, int *vlen);
    280 uint16_t enc_write_resp(uint8_t *pdu, int len);
    281 uint16_t dec_write_resp(const uint8_t *pdu, int len);
    282 uint16_t enc_read_req(uint16_t handle, uint8_t *pdu, int len);
    283 uint16_t enc_read_blob_req(uint16_t handle, uint16_t offset, uint8_t *pdu,
    284 								int len);
    285 uint16_t dec_read_req(const uint8_t *pdu, int len, uint16_t *handle);
    286 uint16_t dec_read_blob_req(const uint8_t *pdu, int len, uint16_t *handle,
    287 							uint16_t *offset);
    288 uint16_t enc_read_resp(uint8_t *value, int vlen, uint8_t *pdu, int len);
    289 uint16_t enc_read_blob_resp(uint8_t *value, int vlen, uint16_t offset,
    290 							uint8_t *pdu, int len);
    291 uint16_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int *vlen);
    292 uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status,
    293 							uint8_t *pdu, int len);
    294 uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu, int len);
    295 uint16_t dec_find_info_req(const uint8_t *pdu, int len, uint16_t *start,
    296 								uint16_t *end);
    297 uint16_t enc_find_info_resp(uint8_t format, struct att_data_list *list,
    298 							uint8_t *pdu, int len);
    299 struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
    300 							uint8_t *format);
    301 uint16_t enc_notification(struct attribute *a, uint8_t *pdu, int len);
    302 uint16_t enc_indication(struct attribute *a, uint8_t *pdu, int len);
    303 struct attribute *dec_indication(const uint8_t *pdu, int len);
    304 uint16_t enc_confirmation(uint8_t *pdu, int len);
    305 
    306 uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len);
    307 uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu);
    308 uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len);
    309 uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu);
    310