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