1 /** 2 **************************************************************************************** 3 * 4 * @file attm.h 5 * 6 * @brief Header file - ATTM. 7 * 8 * Copyright (C) RivieraWaves 2009-2016 9 * 10 * 11 **************************************************************************************** 12 */ 13 14 #ifndef ATTM_H_ 15 #define ATTM_H_ 16 17 /** 18 **************************************************************************************** 19 * @addtogroup ATTM Attribute Manager 20 * @ingroup ATT 21 * @brief Attribute Manager 22 * 23 * The ATTM is the attribute manager of the Attribute Profile block and 24 * is responsible for managing messages and providing generic attribute 25 * functionalities to @ref ATTC "ATTC" and @ref ATTS "ATTS". 26 * 27 * 28 * @{ 29 * 30 **************************************************************************************** 31 */ 32 33 34 /* 35 * INCLUDE FILES 36 **************************************************************************************** 37 */ 38 #include "rwip_config.h" 39 #include <string.h> 40 #include <stdbool.h> 41 42 #include "co_error.h" 43 #include "att.h" 44 #include "ke_task.h" 45 46 /* 47 * DEFINES 48 **************************************************************************************** 49 */ 50 51 /// update attribute permission on specific handle 52 #define ATTMDB_UPDATE_PERM(handle, access, right)\ 53 attm_att_update_perm(handle, (PERM_MASK_ ## access), PERM(access, right)) 54 55 #define ATTMDB_UPDATE_PERM_VAL(handle, access, val)\ 56 attm_att_update_perm(handle, (PERM_MASK_ ## access), ((val) << (PERM_POS_ ## access))) 57 58 59 60 /* 61 * DATA STRUCTURES 62 **************************************************************************************** 63 */ 64 65 /// Internal 16bits UUID service description 66 struct attm_desc 67 { 68 /// 16 bits UUID LSB First 69 uint16_t uuid; 70 /// Attribute Permissions (@see enum attm_perm_mask) 71 uint16_t perm; 72 /// Attribute Extended Permissions (@see enum attm_value_perm_mask) 73 uint16_t ext_perm; 74 /// Attribute Max Size 75 /// note: for characteristic declaration contains handle offset 76 /// note: for included service, contains target service handle 77 uint16_t max_size; 78 }; 79 80 81 /// Internal 128bits UUID service description 82 struct attm_desc_128 83 { 84 /// 128 bits UUID LSB First 85 uint8_t uuid[ATT_UUID_128_LEN]; 86 /// Attribute Permissions (@see enum attm_perm_mask) 87 uint16_t perm; 88 /// Attribute Extended Permissions (@see enum attm_value_perm_mask) 89 uint16_t ext_perm; 90 /// Attribute Max Size 91 /// note: for characteristic declaration contains handle offset 92 /// note: for included service, contains target service handle 93 uint16_t max_size; 94 }; 95 96 97 98 #if (BLE_CENTRAL || BLE_PERIPHERAL) 99 /* 100 * GLOBAL VARIABLE DECLARATIONS 101 **************************************************************************************** 102 */ 103 104 /* 105 * FUNCTION DECLARATIONS 106 **************************************************************************************** 107 */ 108 109 110 /** 111 **************************************************************************************** 112 * @brief Compare if two UUIDs matches 113 * 114 * @param[in] uuid_a UUID A value 115 * @param[in] uuid_a_len UUID A length 116 * @param[in] uuid_b UUID B value 117 * @param[in] uuid_b_len UUID B length 118 * 119 * @return true if UUIDs matches, false otherwise 120 **************************************************************************************** 121 */ 122 bool attm_uuid_comp(const uint8_t *uuid_a, uint8_t uuid_a_len, 123 const uint8_t *uuid_b, uint8_t uuid_b_len); 124 125 126 /** 127 **************************************************************************************** 128 * @brief Check if two UUIDs matches (2nd UUID is a 16 bits UUID with LSB First) 129 * 130 * @param[in] uuid_a UUID A value 131 * @param[in] uuid_a_len UUID A length 132 * @param[in] uuid_b UUID B 16 bit value 133 * 134 * @return true if UUIDs matches, false otherwise 135 **************************************************************************************** 136 */ 137 bool attm_uuid16_comp(uint8_t *uuid_a, uint8_t uuid_a_len, uint16_t uuid_b); 138 139 140 /** 141 **************************************************************************************** 142 * @brief Convert UUID value to 128 bit UUID 143 * 144 * @param[out] uuid128 converted 32-bit Bluetooth UUID to 128-bit UUID 145 * @param[in] uuid UUID to convert to 128-bit UUID 146 * @param[in] uuid_len UUID length 147 * 148 **************************************************************************************** 149 */ 150 void attm_convert_to128(uint8_t *uuid128, const uint8_t *uuid, uint8_t uuid_len); 151 152 /** 153 **************************************************************************************** 154 * @brief Check if it's a Bluetooth 16-bits UUID for 128-bit input 155 * 156 * @param[in] uuid 128-bit UUID 157 * 158 * @return true if uuid is a Bluetooth 16-bit UUID, false else. 159 **************************************************************************************** 160 */ 161 bool attm_is_bt16_uuid(uint8_t *uuid); 162 163 /** 164 **************************************************************************************** 165 * @brief Check if it's a Bluetooth 32 bits UUID for 128-bit input 166 * 167 * @param[in] uuid 128-bit UUID 168 * 169 * @return true if uuid is a Bluetooth 32-bits UUID, false else. 170 **************************************************************************************** 171 */ 172 bool attm_is_bt32_uuid(uint8_t *uuid); 173 174 175 #if (BLE_ATTS) 176 /** 177 **************************************************************************************** 178 * @brief Function use to ease service database creation. 179 * Use @see attmdb_add_service function of attmdb module to create service database, 180 * then use @see attmdb_add_attribute function of attmdb module to create attributes 181 * according to database description array given in parameter. 182 * 183 * @note: database description array shall be const to reduce memory consumption (only ROM) 184 * @note: It supports only 16 bits UUIDs 185 * 186 * @note: If shdl = 0, it return handle using first available handle (shdl is 187 * modified); else it verifies if start handle given can be used to allocates handle range. 188 * 189 * @param[in|out] shdl Service start handle. 190 * @param[in] uuid Service UUID 191 * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of 192 * att_db (Max: 32 attributes); if the bit is set to 1, the 193 * attribute will be added in the service. 194 * @param[in] max_nb_att Number of attributes in the service 195 * @param[in|out] att_tbl Array which will be fulfilled with the difference between 196 * each characteristic handle and the service start handle. 197 * This array is useful if several characteristics are optional 198 * within the service, can be set to NULL if not needed. 199 * @param[in] dest_id Task ID linked to the service. This task will be notified 200 * each time the service content is modified by a peer device. 201 * @param[in|out] att_db Table containing all attributes information 202 * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) 203 * 204 * @return Command status code: 205 * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. 206 * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override 207 * some existing services handles. 208 * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. 209 * or of new attribute cannot be added because all expected 210 * attributes already added or buffer overflow detected during 211 * allocation 212 **************************************************************************************** 213 */ 214 uint8_t attm_svc_create_db(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att, 215 uint8_t *att_tbl, ke_task_id_t const dest_id, 216 const struct attm_desc *att_db, uint8_t svc_perm); 217 218 219 220 /** 221 **************************************************************************************** 222 * @brief Function use to ease service database creation. 223 * Use @see attmdb_add_service function of attmdb module to create service database, 224 * then use @see attmdb_add_attribute function of attmdb module to create attributes 225 * according to database description array given in parameter. 226 * 227 * @note: database description array shall be const to reduce memory consumption (only ROM) 228 * @note: It supports 128, 32 and 16 bits UUIDs 229 * 230 * @note: If shdl = 0, it return handle using first available handle (shdl is 231 * modified); else it verifies if start handle given can be used to allocates handle range. 232 * 233 * @param[in|out] shdl Service start handle. 234 * @param[in] uuid Service UUID 235 * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of 236 * att_db (Max: 32 attributes); if the bit is set to 1, the 237 * attribute will be added in the service. 238 * @param[in] max_nb_att Number of attributes in the service 239 * @param[in|out] att_tbl Array which will be fulfilled with the difference between 240 * each characteristic handle and the service start handle. 241 * This array is useful if several characteristics are optional 242 * within the service, can be set to NULL if not needed. 243 * @param[in] dest_id Task ID linked to the service. This task will be notified 244 * each time the service content is modified by a peer device. 245 * @param[in|out] att_db Table containing all attributes information 246 * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) 247 * 248 * @return Command status code: 249 * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. 250 * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override 251 * some existing services handles. 252 * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. 253 * or of new attribute cannot be added because all expected 254 * attributes already added or buffer overflow detected during 255 * allocation 256 **************************************************************************************** 257 */ 258 uint8_t attm_svc_create_db_128(uint16_t *shdl, const uint8_t* uuid, uint8_t *cfg_flag, uint8_t max_nb_att, 259 uint8_t *att_tbl, ke_task_id_t const dest_id, 260 const struct attm_desc_128 *att_db, uint8_t svc_perm); 261 262 /** 263 **************************************************************************************** 264 * @brief Function use to verify if several services can be allocated on a contiguous 265 * handle range. If this command succeed, it means that service allocation will succeed. 266 * 267 * If start_hdl = 0, it return handle using first available handle (start_hdl is 268 * modified); else it verifies if start handle given can be used to allocates handle range. 269 * 270 * @param[in|out] start_hdl Service start handle. 271 * @param[in] nb_att Number of handle to allocate (containing service handles) 272 * 273 * @return Command status code: 274 * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. 275 * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid 276 **************************************************************************************** 277 */ 278 uint8_t attm_reserve_handle_range(uint16_t* start_hdl, uint8_t nb_att); 279 280 281 282 /** 283 **************************************************************************************** 284 * @brief Update attribute value 285 * 286 * Updating attribute value do not trigger any notification or indication, this shall be 287 * handled by GATT task. 288 * 289 * @param[in] handle Attribute handle. 290 * @param[in] length Size of new attribute value 291 * @param[in] offset Data offset of in the payload to set 292 * @param[in] value Attribute value payload 293 * 294 * @return Command status code: 295 * - @ref ATT_ERR_NO_ERROR: If attribute value update succeeds 296 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 297 * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database or 298 * cannot be modified 299 * - @ref ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN: If new value length exceeds maximum attribute 300 * value length. 301 * 302 **************************************************************************************** 303 */ 304 uint8_t attm_att_set_value(uint16_t handle, att_size_t length, att_size_t offset, uint8_t* value); 305 306 /** 307 **************************************************************************************** 308 * @brief Retrieve attribute value 309 310 * 311 * @param[in] handle Attribute handle. 312 * @param[out] length Size of attribute value 313 * @param[out] value Pointer to attribute value payload 314 * 315 * @return Command status code: 316 * - @ref ATT_ERR_NO_ERROR: If request succeeds 317 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 318 * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database 319 **************************************************************************************** 320 */ 321 uint8_t attm_get_value(uint16_t handle, att_size_t* length, uint8_t** value); 322 323 324 /** 325 **************************************************************************************** 326 * @brief Update attribute permission 327 * 328 * @param[in] handle Attribute handle. 329 * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database 330 * @param[in] perm New attribute permission 331 * @param[in] ext_perm New attribute extended permission 332 * 333 * @return Command status code: 334 * - @ref ATT_ERR_NO_ERROR: If request succeeds 335 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 336 * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed 337 **************************************************************************************** 338 */ 339 uint8_t attm_att_set_permission(uint16_t handle, uint16_t perm, uint16_t ext_perm); 340 341 342 /** 343 **************************************************************************************** 344 * @brief Reset some permissions bit in the Handle passed as parameter. 345 * 346 * @param[in] handle Attribute handle. 347 * @param[in] access_mask Access mask of permission to update 348 * @param[in] perm New value of the permission to update 349 * 350 * 351 * @return Command status code: 352 * - @ref ATT_ERR_NO_ERROR: If request succeeds 353 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 354 * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed 355 **************************************************************************************** 356 */ 357 uint8_t attm_att_update_perm(uint16_t handle, uint16_t access_mask, uint16_t perm); 358 359 /** 360 **************************************************************************************** 361 * @brief Update attribute service permission 362 * 363 * @param[in] handle Attribute handle. 364 * @param[in] perm New attribute permission 365 * 366 * @return Command status code: 367 * - @ref ATT_ERR_NO_ERROR: If request succeeds 368 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 369 **************************************************************************************** 370 */ 371 uint8_t attm_svc_set_permission(uint16_t handle, uint8_t perm); 372 373 374 /** 375 **************************************************************************************** 376 * @brief Retrieve attribute service permission 377 * 378 * @param[in] handle Attribute handle. 379 * @param[out] perm Permission value to return 380 * 381 * @return Command status code: 382 * - @ref ATT_ERR_NO_ERROR: If request succeeds 383 * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database 384 **************************************************************************************** 385 */ 386 uint8_t attm_svc_get_permission(uint16_t handle, uint8_t* perm); 387 388 389 /** 390 **************************************************************************************** 391 * @brief Clear database 392 * 393 * For debug purpose only, this function clear the database and unalloc all services 394 * within database. 395 * 396 * This function shall be used only for qualification and tests in order to manually 397 * change database without modifying software. 398 **************************************************************************************** 399 */ 400 void attmdb_destroy(void); 401 402 /** 403 **************************************************************************************** 404 * @brief Initialize Attribute Database (clear it) 405 * 406 * @param[in] reset true if it's requested by a reset; false if it's boot initialization 407 **************************************************************************************** 408 */ 409 void attm_init(bool reset); 410 #endif // (BLE_ATTS) 411 412 #endif // #if (BLE_CENTRAL || BLE_PERIPHERAL) 413 /// @} ATTM 414 #endif // ATTM_H_ 415