• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  ****************************************************************************************
3  *
4  * @file uds.c
5  *
6  * @brief User Data Service implementation.
7  *
8  ****************************************************************************************
9  * @attention
10   #####Copyright (c) 2019 GOODIX
11   All rights reserved.
12 
13     Redistribution and use in source and binary forms, with or without
14     modification, are permitted provided that the following conditions are met:
15   * Redistributions of source code must retain the above copyright
16     notice, this list of conditions and the following disclaimer.
17   * Redistributions in binary form must reproduce the above copyright
18     notice, this list of conditions and the following disclaimer in the
19     documentation and/or other materials provided with the distribution.
20   * Neither the name of GOODIX nor the names of its contributors may be used
21     to endorse or promote products derived from this software without
22     specific prior written permission.
23 
24   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34   POSSIBILITY OF SUCH DAMAGE.
35  *****************************************************************************************
36  */
37 
38 /*
39  * INCLUDE FILES
40  ****************************************************************************************
41  */
42 #include "uds.h"
43 #include "wss_db.h"
44 #include "ble_prf_types.h"
45 #include "ble_prf_utils.h"
46 #include "utility.h"
47 #include "app_log.h"
48 
49 #define HEIGHT_165 165
50 #define HEIGHT_1650 1650
51 #define YEAR_2000_2000 2000
52 #define MONTH_01 01
53 #define DAY_01 01
54 #define INDEX_2 2
55 #define INDEX_3 3
56 #define INDEX_5 5
57 #define AGE_18 18
58 #define YEAR_LOW 1582
59 #define YEAR_HIGHT 9999
60 #define ROLL_NUM 63
61 #define MONTH_12 12
62 #define DAY_31 31
63 #define HEIGHT_40 40
64 #define HEIGHT_250 250
65 #define USER_DATA_OFFSET 2
66 #define NAME_LEN_OFFSET 3
67 /*
68  * ENUMERATIONS
69  ****************************************************************************************
70  */
71 /**@brief User Data Service Attributes Indexes. */
72 enum {
73     // User Data Service
74     UDS_IDX_SVC,
75 
76     // Database Change Increment Characteristic
77     UDS_IDX_DB_CHANGE_INCR_CHAR,
78     UDS_IDX_DB_CHANGE_INCR_VAL,
79     UDS_IDX_DB_CHANGE_INCR_NTF_CFG,
80 
81     // User Index Characteristic
82     UDS_IDX_USER_INDEX_CHAR,
83     UDS_IDX_USER_INDEX_VAL,
84 
85     // User Control Point Characteristic
86     UDS_IDX_CTRL_POINT_CHAR,
87     UDS_IDX_CTRL_POINT_VAL,
88     UDS_IDX_CTRL_POINT_IND_CFG,
89 
90     // Age Characteristic
91     UDS_IDX_AGE_CHAR,
92     UDS_IDX_AGE_VAL,
93 
94     // Date of Birth Characteristics
95     UDS_IDX_DATE_OF_BIRTH_CHAR,
96     UDS_IDX_DATE_OF_BIRTH_VAL,
97 
98     // First Name Characteristic
99     UDS_IDX_FIRST_NAME_CHAR,
100     UDS_IDX_FIRST_NAME_VAL,
101 
102     // Height Characteristic
103     UDS_IDX_HEIGHT_CHAR,
104     UDS_IDX_HEIGHT_VAL,
105 
106     // Gender Characteristic
107     UDS_IDX_GENDER_CHAR,
108     UDS_IDX_GENDER_VAL,
109 
110     // Registered User Characteristic
111     UDS_IDX_REGIST_USER_CHAR,
112     UDS_IDX_REGIST_USER_VAL,
113     UDS_IDX_REGIST_USER_IND_CFG,
114 
115     UDS_IDX_NB
116 };
117 
118 /*
119  * STRUCTURES
120  *****************************************************************************************
121  */
122 /**@brief User Data Service environment variable. */
123 struct uds_env_t {
124     uds_init_t
125     uds_init;                                    /**< User Data Service initialization variables. */
126     uint16_t                 start_hdl;                                   /**< User Data Service start handle. */
127     bool
128     ucp_in_progress;                             /**< A previously triggered Control Point operationis
129                                                  still in progress. */
130     uint8_t
131     segm_head_roll_num;                          /**< Rolling Segment Number of Segmentation Header. */
132     uint8_t                  consent_try_num;                             /**< The number of consent tries. */
133     uint16_t
134     db_change_incr_ntf_cfg[UDS_CONNECTION_MAX];  /**< The configuration of Current Time Notification
135                                                  which is configured by the peer devices. */
136     uint16_t
137     ctrl_point_ind_cfg[UDS_CONNECTION_MAX];      /**< The configuration of SC Control Point Notification
138                                                  which is configured by the peer devices. */
139     uint16_t
140     regist_user_ind_cfg[UDS_CONNECTION_MAX];     /**< The configuration of SC Control Point Notification
141                                                  which is configured by the peer devices. */
142 };
143 
144 /*
145  * LOCAL FUNCTION DECLARATION
146  *****************************************************************************************
147  */
148 static sdk_err_t   uds_init(void);
149 static void        uds_disconnect_cb(uint8_t conn_idx, uint8_t reason);
150 
151 static void        uds_read_att_cb(uint8_t conidx, const gatts_read_req_cb_t *p_param);
152 static void        uds_write_att_cb(uint8_t conidx, const gatts_write_req_cb_t *p_param);
153 static void        uds_gatts_prep_write_cb(uint8_t conn_idx, const gatts_prep_write_req_cb_t *p_prep_req);
154 static void        uds_cccd_set_cb(uint8_t conn_idx, uint16_t handle, uint16_t cccd_value);
155 static void        uds_gatts_ntf_ind_cb(uint8_t conn_idx, uint8_t status, const ble_gatts_ntf_ind_t *p_ntf_ind);
156 static void        uds_age_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
157 static void        uds_date_of_birth_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
158 static void        uds_first_name_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
159 static void        uds_height_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
160 static void        uds_gender_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
161 static void        uds_db_change_incr_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm);
162 
163 static void        uds_receive_ucp_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length);
164 static void        uds_regist_user_value_encode(uint8_t conn_idx);
165 static sdk_err_t   uds_indicate_user_char_val_chunk(uint8_t conn_idx);
166 
167 /*
168  * LOCAL VARIABLE DEFINITIONS
169  *****************************************************************************************
170  */
171 static struct uds_env_t            s_uds_env;
172 static uds_regi_user_data_stream_t s_regi_user_char_val_stream;
173 
174 /**@brief Full UDS Database Description - Used to add attributes into the database. */
175 static const attm_desc_t uds_attr_tab[UDS_IDX_NB] = {
176     // User Data Service Declaration
177     [UDS_IDX_SVC]                    = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
178 
179     // Database Change Increment Characteristic - Declaration
180     [UDS_IDX_DB_CHANGE_INCR_CHAR]    = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
181     // Database Change Increment Characteristic - Value
182     [UDS_IDX_DB_CHANGE_INCR_VAL]     = {
183         BLE_ATT_CHAR_DATABASE_CHANGE_INCREMENT,
184         READ_PERM_UNSEC | NOTIFY_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
185         ATT_VAL_LOC_USER,
186         UDS_DB_CHANGE_INCR_VAL_LEN_MAX
187     },
188     // Database Change Increment Characteristic - Client Characteristic Configuration Descriptor
189     [UDS_IDX_DB_CHANGE_INCR_NTF_CFG] = {
190         BLE_ATT_DESC_CLIENT_CHAR_CFG,
191         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
192         0,
193         0
194     },
195 
196     // User Index Characteristic - Declaration
197     [UDS_IDX_USER_INDEX_CHAR]        = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
198     // User Index Characteristic - Value
199     [UDS_IDX_USER_INDEX_VAL]         = {
200         BLE_ATT_CHAR_USER_INDEX,
201         READ_PERM_UNSEC,
202         ATT_VAL_LOC_USER,
203         UDS_USER_INDEX_VAL_LEN_MAX
204     },
205 
206     // User Control Point Characteristic - Declaration
207     [UDS_IDX_CTRL_POINT_CHAR]        = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
208     // User Control Point Characteristic - Value
209     [UDS_IDX_CTRL_POINT_VAL]         = {
210         BLE_ATT_CHAR_USER_CONTROL_POINT,
211         WRITE_REQ_PERM_UNSEC | INDICATE_PERM(UNAUTH),
212         ATT_VAL_LOC_USER,
213         UDS_CTRL_PT_VAL_LEN_MAX
214     },
215     // User Control Point Characteristic - Client Characteristic Configuration Descriptor
216     [UDS_IDX_CTRL_POINT_IND_CFG]     = {
217         BLE_ATT_DESC_CLIENT_CHAR_CFG,
218         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
219         0,
220         0
221     },
222 
223     // Age Characteristic - Declaration
224     [UDS_IDX_AGE_CHAR]               = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
225     // Age Characteristic - Value
226     [UDS_IDX_AGE_VAL]                = {
227         BLE_ATT_CHAR_AGE,
228         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
229         ATT_VAL_LOC_USER,
230         UDS_AGE_VAL_LEN_MAX
231     },
232 
233     // Date of Birth Characteristic - Declaration
234     [UDS_IDX_DATE_OF_BIRTH_CHAR]     = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
235     // Date of Birth Characteristic - Value
236     [UDS_IDX_DATE_OF_BIRTH_VAL]      = {
237         BLE_ATT_CHAR_DATE_OF_BIRTH,
238         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
239         ATT_VAL_LOC_USER,
240         UDS_DATE_OF_BIRTH_VAL_LEN_MAX
241     },
242 
243     // First Name Characteristic - Declaration
244     [UDS_IDX_FIRST_NAME_CHAR]        = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
245     // First Name Characteristic - Value
246     [UDS_IDX_FIRST_NAME_VAL]         = {
247         BLE_ATT_CHAR_FIRST_NAME,
248         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
249         ATT_VAL_LOC_USER,
250         UDS_FIRST_NAME_VAL_LEN_MAX
251     },
252 
253     // Height Characteristic - Declaration
254     [UDS_IDX_HEIGHT_CHAR]            = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
255     // Height Characteristic - Value
256     [UDS_IDX_HEIGHT_VAL]             = {
257         BLE_ATT_CHAR_HEIGHT,
258         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
259         ATT_VAL_LOC_USER,
260         UDS_HEIGHT_VAL_LEN_MAX
261     },
262 
263     // Gender Characteristic - Declaration
264     [UDS_IDX_GENDER_CHAR]            = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
265     // Gender Characteristic - Value
266     [UDS_IDX_GENDER_VAL]             = {
267         BLE_ATT_CHAR_GENDER,
268         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
269         ATT_VAL_LOC_USER,
270         UDS_GENDER_VAL_LEN_MAX
271     },
272 
273     // Registered User Characteristic Declaration
274     [UDS_IDX_REGIST_USER_CHAR]       = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
275     // Registered User Characteristic Declaration value
276     [UDS_IDX_REGIST_USER_VAL]        = {
277         BLE_ATT_CHAR_REGISTERED_USER,
278         INDICATE_PERM_UNSEC,
279         ATT_VAL_LOC_USER,
280         UDS_REGI_USER_VAL_LEN_MAX
281     },
282     // Registered User Characteristic Declaration  - Client Characteristic Configuration Descriptor
283     [UDS_IDX_REGIST_USER_IND_CFG]    = {
284         BLE_ATT_DESC_CLIENT_CHAR_CFG,
285         READ_PERM_UNSEC | WRITE_REQ_PERM_UNSEC,
286         0,
287         0
288     },
289 };
290 
291 /**@brief UDS Task interface required by profile manager. */
292 static ble_prf_manager_cbs_t uds_task_cbs = {
293     (prf_init_func_t) uds_init,
294     NULL,
295     uds_disconnect_cb
296 };
297 
298 /**@brief UDS Task Callbacks. */
299 static gatts_prf_cbs_t uds_cb_func = {
300     uds_read_att_cb,
301     uds_write_att_cb,
302     uds_gatts_prep_write_cb,
303     uds_gatts_ntf_ind_cb,
304     uds_cccd_set_cb
305 };
306 
307 /**@brief UDS Information. */
308 static const prf_server_info_t uds_prf_info = {
309     .max_connection_nb = UDS_CONNECTION_MAX,
310     .manager_cbs       = &uds_task_cbs,
311     .gatts_prf_cbs     = &uds_cb_func
312 };
313 
314 /*
315  * LOCAL FUNCTION DEFINITIONS
316  *****************************************************************************************
317  */
318 /**
319  *****************************************************************************************
320  * @brief Initialize User Data service and create db in att
321  *
322  * @return Error code to know if profile initialization succeed or not.
323  *****************************************************************************************
324  */
uds_init(void)325 static sdk_err_t uds_init(void)
326 {
327     // The start handle must be set with PRF_INVALID_HANDLE to be allocated automatically by BLE Stack.
328     uint16_t          start_hdl      = PRF_INVALID_HANDLE;
329     const uint8_t     uds_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_USER_DATA);
330     sdk_err_t         error_code;
331     gatts_create_db_t gatts_db;
332 
333     error_code = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
334     if (error_code < 0) {
335         return error_code;
336     }
337 
338     gatts_db.shdl                 = &start_hdl;
339     gatts_db.uuid                 = uds_svc_uuid;
340     gatts_db.attr_tab_cfg         = (uint8_t *)&(s_uds_env.uds_init.char_mask);
341     gatts_db.max_nb_attr          = UDS_IDX_NB;
342     gatts_db.srvc_perm            = 0;
343     gatts_db.attr_tab_type        = SERVICE_TABLE_TYPE_16;
344     gatts_db.attr_tab.attr_tab_16 = uds_attr_tab;
345 
346     error_code = ble_gatts_srvc_db_create(&gatts_db);
347     if (SDK_SUCCESS == error_code) {
348         s_uds_env.start_hdl = *gatts_db.shdl;
349     }
350 
351     return error_code;
352 }
353 
354 /**
355  *****************************************************************************************
356  * @brief Handles reception of the disconnection event.
357  *
358  * @param[in] conn_idx: Connection index.
359  * @param[in] reason:   Reason of disconnection.
360  *****************************************************************************************
361  */
uds_disconnect_cb(uint8_t conn_idx,uint8_t reason)362 static void uds_disconnect_cb(uint8_t conn_idx, uint8_t reason)
363 {
364     s_uds_env.ucp_in_progress = false;
365 }
366 
367 /**
368  *****************************************************************************************
369  * @brief Handles reception of the attribute info request message.
370  *
371  * @param[in] conn_idx: Connection index
372  * @param[in] p_param:  Pointer to the parameters of the read request.
373  *****************************************************************************************
374  */
uds_read_att_cb(uint8_t conn_idx,const gatts_read_req_cb_t * p_param)375 static void uds_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param)
376 {
377     gatts_read_cfm_t  cfm;
378     uint8_t           handle    = p_param->handle;
379     uint8_t           tab_index = prf_find_idx_by_handle(handle,
380                                   s_uds_env.start_hdl,
381                                   UDS_IDX_NB,
382                                   (uint8_t *)&s_uds_env.uds_init.char_mask);
383     cfm.handle = handle;
384     cfm.status = BLE_SUCCESS;
385 
386     wss_rec_t loc_rec;
387 
388     switch (tab_index) {
389         case UDS_IDX_AGE_VAL: {
390             if (s_uds_env.uds_init.user_index == UDS_UNKNOWN_USER) {
391                 cfm.status = BLE_ATT_ERR_READ_NOT_PERMITTED;
392                 cfm.length = sizeof(uint8_t);
393                 cfm.value  = (uint8_t *)UDS_ERROR_UD_ACCESS_NOT_PERMIT;
394             } else {
395                 wss_db_record_get(s_uds_env.uds_init.user_index, &loc_rec);
396                 cfm.length = sizeof(uint8_t);
397                 cfm.value  = (uint8_t *)&loc_rec.age;
398             }
399             break;
400         }
401 
402         case UDS_IDX_DATE_OF_BIRTH_VAL: {
403             if (s_uds_env.uds_init.user_index == UDS_UNKNOWN_USER) {
404                 cfm.status = BLE_ATT_ERR_READ_NOT_PERMITTED;
405                 cfm.length = sizeof(uint8_t);
406                 cfm.value  = (uint8_t *)UDS_ERROR_UD_ACCESS_NOT_PERMIT;
407             } else {
408                 wss_db_record_get(s_uds_env.uds_init.user_index, &loc_rec);
409                 cfm.length = sizeof(birth_date_t);
410                 cfm.value  = (uint8_t *)&loc_rec.date_of_birth;
411             }
412             break;
413         }
414 
415         case UDS_IDX_FIRST_NAME_VAL: {
416             if (s_uds_env.uds_init.user_index == UDS_UNKNOWN_USER) {
417                 cfm.status = BLE_ATT_ERR_READ_NOT_PERMITTED;
418                 cfm.length = sizeof(uint8_t);
419                 cfm.value  = (uint8_t *)UDS_ERROR_UD_ACCESS_NOT_PERMIT;
420             } else {
421                 wss_db_record_get(s_uds_env.uds_init.user_index, &loc_rec);
422                 cfm.length = loc_rec.name_length;
423                 cfm.value  = (uint8_t *)loc_rec.first_name;
424             }
425             break;
426         }
427 
428         case UDS_IDX_HEIGHT_VAL: {
429             if (s_uds_env.uds_init.user_index == UDS_UNKNOWN_USER) {
430                 cfm.status = BLE_ATT_ERR_READ_NOT_PERMITTED;
431                 cfm.length = sizeof(uint8_t);
432                 cfm.value  = (uint8_t *)UDS_ERROR_UD_ACCESS_NOT_PERMIT;
433             } else {
434                 wss_db_record_get(s_uds_env.uds_init.user_index, &loc_rec);
435                 cfm.length = sizeof(uint16_t);
436                 cfm.value  = (uint8_t *)&loc_rec.height;
437             }
438             break;
439         }
440 
441         case UDS_IDX_GENDER_VAL: {
442             if (s_uds_env.uds_init.user_index == UDS_UNKNOWN_USER) {
443                 cfm.status = BLE_ATT_ERR_READ_NOT_PERMITTED;
444                 cfm.length = sizeof(uint8_t);
445                 cfm.value  = (uint8_t *)UDS_ERROR_UD_ACCESS_NOT_PERMIT;
446             } else {
447                 wss_db_record_get(s_uds_env.uds_init.user_index, &loc_rec);
448                 cfm.length = sizeof(uint8_t);
449                 cfm.value  = (uint8_t *)&loc_rec.gender;
450             }
451             break;
452         }
453 
454         case UDS_IDX_DB_CHANGE_INCR_VAL: {
455             uint8_t   user_index = s_uds_env.uds_init.user_index;
456             if (UDS_UNKNOWN_USER == user_index) {
457                 uint32_t db_change_incr_val = UDS_DB_CHANGE_INCR_DEFAULT_VAL;
458                 cfm.length = sizeof(uint32_t);
459                 cfm.value  = (uint8_t *)&db_change_incr_val;
460             } else {
461                 if (wss_db_record_get(user_index, &loc_rec)) {
462                     cfm.length = sizeof(uint32_t);
463                     cfm.value  = (uint8_t *)&loc_rec.db_change_incr_val;
464                 }
465             }
466             break;
467         }
468 
469         case UDS_IDX_DB_CHANGE_INCR_NTF_CFG:
470             cfm.length = sizeof(uint16_t);
471             cfm.value  = (uint8_t *)&s_uds_env.db_change_incr_ntf_cfg[conn_idx];
472             break;
473 
474         case UDS_IDX_USER_INDEX_VAL: {
475             cfm.length = sizeof(uint8_t);
476             cfm.value  = (uint8_t *)&s_uds_env.uds_init.user_index;
477             break;
478         }
479 
480         case UDS_IDX_REGIST_USER_IND_CFG: {
481             cfm.length = sizeof(uint16_t);
482             cfm.value  = (uint8_t *)&s_uds_env.regist_user_ind_cfg[conn_idx];
483             break;
484         }
485 
486         case UDS_IDX_CTRL_POINT_IND_CFG: {
487             cfm.length = sizeof(uint16_t);
488             cfm.value  = (uint8_t *)&s_uds_env.ctrl_point_ind_cfg[conn_idx];
489             break;
490         }
491 
492         default:
493             cfm.length = 0;
494             cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
495             break;
496     }
497 
498     ble_gatts_read_cfm(conn_idx, &cfm);
499 }
500 
501 /**
502  *****************************************************************************************
503  * @brief Handles reception of the write request.
504  *
505  * @param[in]: conn_idx: Connection index
506  * @param[in]: p_param:  Pointer to the parameters of the write request.
507  *****************************************************************************************
508  */
uds_write_att_cb(uint8_t conn_idx,const gatts_write_req_cb_t * p_param)509 static void uds_write_att_cb(uint8_t conn_idx, const gatts_write_req_cb_t *p_param)
510 {
511     uint16_t          handle      = p_param->handle;
512     uint16_t          tab_index   = 0;
513     uint16_t          cccd_value  = 0;
514     bool              ucp_evt     = false;
515     uds_evt_t         event;
516     gatts_write_cfm_t cfm;
517 
518     tab_index      = prf_find_idx_by_handle(handle,
519                                             s_uds_env.start_hdl,
520                                             UDS_IDX_NB,
521                                             (uint8_t *)&s_uds_env.uds_init.char_mask);
522     cfm.handle     = handle;
523     cfm.status     = BLE_SUCCESS;
524     event.evt_type = UDS_EVT_INVALID;
525     event.conn_idx = conn_idx;
526 
527     switch (tab_index) {
528         case UDS_IDX_AGE_VAL:
529             if (UDS_UNKNOWN_USER == s_uds_env.uds_init.user_index) {
530                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
531             }
532 
533             event.evt_type = UDS_EVT_AGE_SET_BY_PEER;
534             event.p_data   = p_param->value;
535             event.length   = p_param->length;
536             uds_age_write_handler(p_param->value, p_param->length, &cfm);
537             break;
538 
539         case UDS_IDX_DATE_OF_BIRTH_VAL:
540             if (UDS_UNKNOWN_USER  == s_uds_env.uds_init.user_index) {
541                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
542             }
543             event.evt_type = UDS_EVT_DATE_OF_BIRTH_SET_BY_PEER;
544             event.p_data   = p_param->value;
545             event.length   = p_param->length;
546             uds_date_of_birth_write_handler(p_param->value, p_param->length, &cfm);
547             break;
548 
549         case UDS_IDX_FIRST_NAME_VAL:
550             if (UDS_UNKNOWN_USER  == s_uds_env.uds_init.user_index) {
551                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
552             }
553             event.evt_type = UDS_EVT_FIRST_NAME_SET_BY_PEER;
554             event.p_data   = p_param->value;
555             event.length   = p_param->length;
556             uds_first_name_write_handler(p_param->value, p_param->length, &cfm);
557             break;
558 
559         case UDS_IDX_HEIGHT_VAL:
560             if (UDS_UNKNOWN_USER  == s_uds_env.uds_init.user_index) {
561                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
562             }
563             event.evt_type = UDS_EVT_HEIGHT_SET_BY_PEER;
564             event.p_data   = p_param->value;
565             event.length   = p_param->length;
566             uds_height_write_handler(p_param->value, p_param->length, &cfm);
567             break;
568 
569         case UDS_IDX_GENDER_VAL:
570             if (UDS_UNKNOWN_USER  == s_uds_env.uds_init.user_index) {
571                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
572             }
573             event.evt_type = UDS_EVT_GENDER_SET_BY_PEER;
574             event.p_data   = p_param->value;
575             event.length   = p_param->length;
576             uds_gender_write_handler(p_param->value, p_param->length, &cfm);
577             break;
578 
579         case UDS_IDX_DB_CHANGE_INCR_VAL:
580             if (UDS_UNKNOWN_USER  == s_uds_env.uds_init.user_index) {
581                 cfm.status = UDS_ERROR_UD_ACCESS_NOT_PERMIT;
582             }
583             event.evt_type = UDS_EVT_DB_CHANGE_INCR_SET_BY_PEER;
584             event.p_data   = p_param->value;
585             event.length   = p_param->length;
586             uds_db_change_incr_write_handler(p_param->value, p_param->length, &cfm);
587             break;
588 
589         case UDS_IDX_DB_CHANGE_INCR_NTF_CFG:
590             cccd_value     = le16toh(&p_param->value[0]);
591             event.evt_type = ((PRF_CLI_START_NTF == cccd_value) ? \
592                               UDS_EVT_DB_CHANGE_INCR_NOTIFICATION_ENABLE : \
593                               UDS_EVT_DB_CHANGE_INCR_NOTIFICATION_DISABLE);
594             s_uds_env.db_change_incr_ntf_cfg[conn_idx] = cccd_value;
595             break;
596 
597         case UDS_IDX_REGIST_USER_IND_CFG:
598             cccd_value     = le16toh(&p_param->value[0]);
599             event.evt_type = ((PRF_CLI_START_IND == cccd_value) ? \
600                               UDS_EVT_REGIST_USER_INDICATION_ENABLE : \
601                               UDS_EVT_REGIST_USER_INDICATION_DISABLE);
602             s_uds_env.regist_user_ind_cfg[conn_idx] = cccd_value;
603             break;
604 
605         case UDS_IDX_CTRL_POINT_VAL:
606             if (PRF_CLI_START_IND != s_uds_env.ctrl_point_ind_cfg[conn_idx]) {
607                 cfm.status = UDS_ERROR_CCCD_INVALID;
608                 break;
609             } else if (s_uds_env.ucp_in_progress) {
610                 cfm.status = UDS_ERROR_PROC_IN_PROGRESS;
611             } else if (PRF_CLI_START_IND == s_uds_env.ctrl_point_ind_cfg[conn_idx]) {
612                 ucp_evt = true;
613                 s_uds_env.ucp_in_progress = true;
614             }
615             break;
616 
617         case UDS_IDX_CTRL_POINT_IND_CFG:
618             cccd_value     = le16toh(&p_param->value[0]);
619             event.evt_type = ((PRF_CLI_START_IND == cccd_value) ? \
620                               UDS_EVT_CTRL_POINT_INDICATION_ENABLE : \
621                               UDS_EVT_CTRL_POINT_INDICATION_DISABLE);
622             s_uds_env.ctrl_point_ind_cfg[conn_idx] = cccd_value;
623             break;
624 
625         default:
626             cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
627             break;
628     }
629 
630     ble_gatts_write_cfm(conn_idx, &cfm);
631 
632     if (ucp_evt) {
633         uds_receive_ucp_handler(conn_idx, p_param->value, p_param->length);
634     }
635     if (BLE_ATT_ERR_INVALID_HANDLE != cfm.status && UDS_EVT_INVALID != event.evt_type &&
636         s_uds_env.uds_init.evt_handler) {
637         s_uds_env.uds_init.evt_handler(&event);
638     }
639 }
640 
641 /**
642  *****************************************************************************************
643  * @brief Handles Prepare write value callback function.
644  *
645  * @param[in]: conn_idx:      Connection index
646  * @param[in]: p_prep_req:    Pointer to the handle of cccd attribute.
647  *****************************************************************************************
648  */
uds_gatts_prep_write_cb(uint8_t conn_idx,const gatts_prep_write_req_cb_t * p_prep_req)649 static void uds_gatts_prep_write_cb(uint8_t conn_idx, const gatts_prep_write_req_cb_t *p_prep_req)
650 {
651     gatts_prep_write_cfm_t cfm;
652 
653     cfm.handle = p_prep_req->handle;
654     cfm.length = UDS_REGI_USER_VAL_LEN_MAX;
655     cfm.status = BLE_SUCCESS;
656 
657     ble_gatts_prepare_write_cfm(conn_idx, &cfm);
658 }
659 
660 /**
661  *****************************************************************************************
662  * @brief Handles reception of the cccd recover request.
663  *
664  * @param[in]: conn_idx:   Connection index
665  * @param[in]: handle:     The handle of cccd attribute.
666  * @param[in]: cccd_value: The value of cccd attribute.
667  *****************************************************************************************
668  */
uds_cccd_set_cb(uint8_t conn_idx,uint16_t handle,uint16_t cccd_value)669 static void uds_cccd_set_cb(uint8_t conn_idx, uint16_t handle, uint16_t cccd_value)
670 {
671     uint16_t          tab_index   = 0;
672     uds_evt_t         event;
673 
674     if (!prf_is_cccd_value_valid(cccd_value)) {
675         return;
676     }
677 
678     tab_index  = prf_find_idx_by_handle(handle,
679                                         s_uds_env.start_hdl,
680                                         UDS_IDX_NB,
681                                         (uint8_t *)&s_uds_env.uds_init.char_mask);
682 
683     event.evt_type = UDS_EVT_INVALID;
684     event.conn_idx = conn_idx;
685 
686     switch (tab_index) {
687         case UDS_IDX_DB_CHANGE_INCR_NTF_CFG:
688             event.evt_type = ((PRF_CLI_START_NTF == cccd_value) ? \
689                               UDS_EVT_DB_CHANGE_INCR_NOTIFICATION_ENABLE : \
690                               UDS_EVT_DB_CHANGE_INCR_NOTIFICATION_DISABLE);
691             s_uds_env.db_change_incr_ntf_cfg[conn_idx] = cccd_value;
692             break;
693 
694         case UDS_IDX_CTRL_POINT_IND_CFG:
695             event.evt_type = ((PRF_CLI_START_IND == cccd_value) ? \
696                               UDS_EVT_CTRL_POINT_INDICATION_ENABLE : \
697                               UDS_EVT_CTRL_POINT_INDICATION_DISABLE);
698             s_uds_env.ctrl_point_ind_cfg[conn_idx] = cccd_value;
699             break;
700 
701         case UDS_IDX_REGIST_USER_IND_CFG:
702             event.evt_type = ((PRF_CLI_START_IND == cccd_value) ? \
703                               UDS_EVT_REGIST_USER_INDICATION_ENABLE : \
704                               UDS_EVT_REGIST_USER_INDICATION_DISABLE);
705             s_uds_env.regist_user_ind_cfg[conn_idx] = cccd_value;
706             break;
707 
708         default:
709             break;
710     }
711 
712     if (UDS_EVT_INVALID != event.evt_type && s_uds_env.uds_init.evt_handler) {
713         s_uds_env.uds_init.evt_handler(&event);
714     }
715 }
716 
717 /**
718  *****************************************************************************************
719  * @brief Handles reception of the complete event.
720  *
721  * @param[in] conn_idx:   Connection index.
722  * @param[in] status:     Complete event status.
723  * @param[in] p_ntf_ind:  Pointer to the parameters of the complete event.
724  *****************************************************************************************
725  */
uds_gatts_ntf_ind_cb(uint8_t conn_idx,uint8_t status,const ble_gatts_ntf_ind_t * p_ntf_ind)726 static void uds_gatts_ntf_ind_cb(uint8_t conn_idx, uint8_t status, const ble_gatts_ntf_ind_t *p_ntf_ind)
727 {
728     uds_evt_t event;
729 
730     event.evt_type = UDS_EVT_INVALID;
731     event.conn_idx = conn_idx;
732 
733     uint8_t tab_index;
734     tab_index = prf_find_idx_by_handle(p_ntf_ind->handle,
735                                        s_uds_env.start_hdl,
736                                        UDS_IDX_NB,
737                                        (uint8_t *)&s_uds_env.uds_init.char_mask);
738 
739     if (BLE_GAP_ERR_TIMEOUT == status) {
740         ble_gap_disconnect(conn_idx);
741     }
742 
743     if (s_uds_env.uds_init.evt_handler && SDK_SUCCESS == status) {
744         if (BLE_GATT_NOTIFICATION == p_ntf_ind->type) {
745             event.evt_type = UDS_EVT_DB_CHANGE_INCR_SEND_CPLT;
746             s_uds_env.uds_init.evt_handler(&event);
747         } else if (BLE_GATT_INDICATION == p_ntf_ind->type && (UDS_IDX_REGIST_USER_VAL == tab_index)) {
748             uds_indicate_user_char_val_chunk(conn_idx);
749         } else if (BLE_GATT_INDICATION == p_ntf_ind->type && (UDS_IDX_CTRL_POINT_VAL == tab_index)) {
750             event.evt_type = UDS_EVT_CTRL_POINT_RSP_CPLT;
751             s_uds_env.ucp_in_progress = false;
752             s_uds_env.uds_init.evt_handler(&event);
753         }
754     }
755 }
756 
757 /**
758  *****************************************************************************************
759  * @brief Change the endian of Registered User Name.
760  *
761  * @param[in] user_index:  index.
762  * @param[in] p_param:     Pointer to the parameters of the complete event.
763  *****************************************************************************************
764  */
765 
766 /**
767  *****************************************************************************************
768  * @brief Handle Age Characteristic write event.
769  *
770  * @param[in]  p_data: Pointer to the age characteristic value.
771  * @param[in]  length: The length of data.
772  * @param[in]  p_cfm:  Pointer of the write confirmation.
773  *****************************************************************************************
774  */
uds_age_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)775 static void uds_age_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
776 {
777     if (length != 1 || p_data[0] > 100) {
778         p_cfm->status = BLE_GATT_ERR_WRITE;
779     } else {
780         uint8_t age        = p_data[0];
781         uint8_t user_index = s_uds_env.uds_init.user_index;
782 
783         wss_db_record_age_set(user_index, age);
784     }
785 }
786 
787 /**
788  *****************************************************************************************
789  * @brief Handle Date of Birth Characteristic write event.
790  *
791  * @param[in]  p_data: Pointer to Date of Birth Characteristic value.
792  * @param[in]  length: The length of data.
793  * @param[in]  p_cfm:  Pointer of the write confirmation.
794  *****************************************************************************************
795  */
uds_date_of_birth_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)796 static void uds_date_of_birth_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
797 {
798     if (length != 4) {
799         p_cfm->status = BLE_GATT_ERR_WRITE;
800     } else {
801         birth_date_t  date_of_birth;
802         date_of_birth.year  = BUILD_U16(p_data[0], p_data[1]);
803         date_of_birth.month = p_data[INDEX_2];
804         date_of_birth.day   = p_data[INDEX_3];
805 
806         if (date_of_birth.month > MONTH_12 || (date_of_birth.day > DAY_31) ||\
807                 ((date_of_birth.year < YEAR_LOW || date_of_birth.year > YEAR_HIGHT) && (date_of_birth.year != 0))) {
808             p_cfm->status = BLE_GATT_ERR_WRITE;
809         } else {
810             uint8_t user_index = s_uds_env.uds_init.user_index;
811             wss_db_record_date_of_birth_set(user_index, &date_of_birth);
812         }
813     }
814 }
815 
816 /**
817  *****************************************************************************************
818  * @brief Handle First Name Characteristic write event.
819  *
820  * @param[in]  p_data:  Pointer to First Name Characteristic value.
821  * @param[in]  length:  The length of data.
822  * @param[in]  p_cfm:   Pointer of the write confirmation.
823  *****************************************************************************************
824  */
uds_first_name_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)825 static void uds_first_name_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
826 {
827     uint8_t  user_index = s_uds_env.uds_init.user_index;
828     wss_db_record_first_name_set(user_index, p_data, length);
829 }
830 
831 /**
832  *****************************************************************************************
833  * @brief Handle Height Characteristic write event.
834  *
835  * @param[in]  p_data: Pointer to Height Characteristic value.
836  * @param[in]  length: The length of data.
837  * @param[in]  p_cfm:  Pointer of the write confirmation.
838  *****************************************************************************************
839  */
uds_height_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)840 static void uds_height_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
841 {
842     if (length != INDEX_2) {
843         p_cfm->status = BLE_GATT_ERR_WRITE;
844     } else {
845         uint16_t height = BUILD_U16(p_data[0], p_data[1]);
846         if (height < HEIGHT_40 || height > HEIGHT_250) {
847             p_cfm->status = BLE_GATT_ERR_WRITE;
848         } else {
849             uint8_t  user_index = s_uds_env.uds_init.user_index;
850             wss_db_record_height_set(user_index, height);
851         }
852     }
853 }
854 
855 /**
856  *****************************************************************************************
857  * @brief Handle Gender Characteristic write event.
858  *
859  * @param[in]  p_data: Pointer to Gender Characteristic value.
860  * @param[in]  length: The length of data.
861  * @param[in]  p_cfm:  Pointer of the write confirmation.
862  *****************************************************************************************
863  */
uds_gender_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)864 static void uds_gender_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
865 {
866     if (length != 1 || (p_data[0] > INDEX_2)) {
867         p_cfm->status = BLE_GATT_ERR_WRITE;
868     } else {
869         uint8_t gender     = p_data[0];
870         uint8_t user_index = s_uds_env.uds_init.user_index;
871 
872         wss_db_record_gender_set(user_index, gender);
873     }
874 }
875 
876 /**
877  *****************************************************************************************
878  * @brief Handle Database Change Increment value write event.
879  *
880  * @param[in]  p_data: Pointer to Database Change Increment Characteristic value.
881  * @param[in]  length: Length of Database Change Increment Characteristic value.
882  * @param[in]  p_cfm:  Pointer of the write confirmation.
883  *****************************************************************************************
884  */
uds_db_change_incr_write_handler(const uint8_t * p_data,uint16_t length,gatts_write_cfm_t * p_cfm)885 static void uds_db_change_incr_write_handler(const uint8_t *p_data, uint16_t length, gatts_write_cfm_t *p_cfm)
886 {
887     if (length != UDS_DB_CHANGE_INCR_VAL_LEN_MAX) {
888         p_cfm->status = BLE_GATT_ERR_WRITE;
889     } else {
890         uint8_t user_index = s_uds_env.uds_init.user_index;
891 
892         uint32_t db_change_incr_val = BUILD_U32(p_data[0], p_data[1], p_data[INDEX_2], p_data[INDEX_3]);
893         bool status = wss_db_record_db_change_incr_val_set(user_index, db_change_incr_val);
894     }
895 }
896 
897 /**
898  *****************************************************************************************
899  * @brief User Control Point Register New User handler.
900  *
901  * @param[in] conn_idx: Connection index.
902  * @param[in] p_data:   Pointer to data.
903  * @param[in] length:   Length of data.
904  *****************************************************************************************
905  */
uds_op_regist_new_user_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)906 static void uds_op_regist_new_user_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
907 {
908     uds_evt_t   event;
909     uint8_t     rsp[UDS_CTRL_PT_RSP_LEN_MAX];
910 
911     rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
912     rsp[1] = UDS_CTRL_PT_OP_REGIST_NEW_USER;
913     rsp[INDEX_2] = UDS_CTRL_PT_RSP_INVALID_PARAM;
914 
915     uint16_t consent_code = BUILD_U16(p_data[0], p_data[1]);
916     if ((sizeof(uint16_t) != length) || (UDS_CONSENT_CODE_VAL_MAX < consent_code)) {
917         uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
918     } else {
919         uds_chars_val_t uds_chars_val;
920         uint8_t         user_nums;
921         uint8_t         db_change_incr_val;
922         uint8_t         new_user_index;
923 
924         user_nums = (uint8_t)wss_db_records_num_get();
925         if (WSS_DB_RECORDS_MAX <= user_nums) {
926             wss_db_record_delete(1);
927             new_user_index = 0x01;
928         } else {
929             new_user_index = user_nums;
930         }
931 
932         uint8_t first_name[]              = "tom";
933         db_change_incr_val                = UDS_DB_CHANGE_INCR_DEFAULT_VAL;
934         uds_chars_val.age                 = AGE_18;
935         uds_chars_val.height              = HEIGHT_165;  // The unit is cm.
936         uds_chars_val.gender              = 0x00;
937         uds_chars_val.date_of_birth.year  = YEAR_2000;
938         uds_chars_val.date_of_birth.month = MONTH_01;
939         uds_chars_val.date_of_birth.day   = DAY_01;
940         uds_chars_val.p_first_name        = &first_name[0];
941         uds_chars_val.name_length         = sizeof(first_name);
942         rsp[INDEX_3]                            = new_user_index;
943 
944         if (wss_db_record_add(new_user_index, consent_code, db_change_incr_val, &uds_chars_val)
945                 && s_uds_env.uds_init.evt_handler) {
946             rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
947 
948             event.conn_idx = conn_idx;
949             event.evt_type = UDS_EVT_REGIST_NEW_USER;
950             event.p_data   = &new_user_index;
951             event.length   = length;
952             s_uds_env.uds_init.evt_handler(&event);
953             s_uds_env.uds_init.user_index = new_user_index;
954 
955             uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN + 1);
956         } else {
957             rsp[INDEX_2] = UDS_CTRL_PT_RSP_FAILED;
958             uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
959         }
960     }
961 }
962 
963 /**
964  *****************************************************************************************
965  * @brief User Control Point Consent handler.
966  *
967  * @param[in] conn_idx: Connection index.
968  * @param[in] p_data:   Pointer to data.
969  * @param[in] length:   Length of data.
970  *****************************************************************************************
971  */
uds_op_consent_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)972 static void uds_op_consent_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
973 {
974     uds_evt_t  event;
975     uint8_t    rsp[UDS_CTRL_PT_RSP_LEN_MIN];
976 
977     rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
978     rsp[1] = UDS_CTRL_PT_OP_CONSENT;
979     rsp[INDEX_2] = UDS_CTRL_PT_RSP_INVALID_PARAM;
980 
981     uint16_t consent_code = BUILD_U16(p_data[1], p_data[INDEX_2]);
982 
983     if (UDS_CONSENT_TRY_NUM_MAX <= s_uds_env.consent_try_num) {
984 #if defined(PTS_AUTO_TEST)
985         wss_db_record_clear();
986 #endif
987         rsp[INDEX_2] = UDS_CTRL_PT_RSP_FAILED;
988     } else if (((sizeof(uint16_t)+sizeof(uint8_t)) == length) && \
989                (UDS_UNKNOWN_USER > p_data[0]) && \
990                (UDS_CONSENT_CODE_VAL_MAX >= consent_code)) {
991         uint8_t   user_index   = p_data[0];
992         wss_rec_t loc_rec;
993 
994         bool status = wss_db_record_get(user_index, &loc_rec);
995         if (consent_code != loc_rec.consent_code || (!status)) {
996             rsp[INDEX_2] = UDS_CTRL_PT_RSP_USER_NOT_AUTH;
997             s_uds_env.consent_try_num++;
998 
999 #if defined(PTS_AUTO_TEST)
1000             wss_db_record_delete(s_uds_env.uds_init.user_index);
1001 #endif
1002         } else {
1003             rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
1004             event.conn_idx            = conn_idx;
1005             event.evt_type            = UDS_EVT_USER_GRANT_ACCESS;
1006             event.p_data              = p_data;
1007             event.length              = length;
1008 
1009             s_uds_env.uds_init.evt_handler(&event);
1010             s_uds_env.uds_init.user_index = user_index;
1011             s_uds_env.consent_try_num     = 0;
1012             s_uds_env.uds_init.evt_handler(&event);
1013         }
1014     }
1015     uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
1016 }
1017 
1018 /**
1019  *****************************************************************************************
1020  * @brief User Control Point Delete User Data handler.
1021  *
1022  * @param[in] conn_idx: Connection index.
1023  * @param[in] p_data:   Pointer to data.
1024  * @param[in] length:   Length of data.
1025  *****************************************************************************************
1026  */
uds_op_del_user_data_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)1027 static void uds_op_del_user_data_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
1028 {
1029     uds_evt_t  event;
1030     uint8_t    rsp[UDS_CTRL_PT_RSP_LEN_MAX];
1031 
1032     rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
1033     rsp[1] = UDS_CTRL_PT_OP_DEL_USER_DATA;
1034     rsp[INDEX_2] = UDS_CTRL_PT_RSP_INVALID_PARAM;
1035 
1036     if (UDS_UNKNOWN_USER == s_uds_env.uds_init.user_index) {
1037         rsp[INDEX_2] = UDS_CTRL_PT_RSP_USER_NOT_AUTH;
1038     } else {
1039         if (wss_db_record_delete(s_uds_env.uds_init.user_index)) {
1040             rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
1041 
1042             event.conn_idx           = conn_idx;
1043             event.evt_type           = UDS_EVT_DEL_USER_DATA;
1044             event.p_data             = p_data;
1045             event.length             = length;
1046             s_uds_env.uds_init.evt_handler(&event);
1047             s_uds_env.uds_init.user_index = UDS_UNKNOWN_USER;
1048         } else {
1049             rsp[INDEX_2] = UDS_CTRL_PT_RSP_FAILED;
1050         }
1051     }
1052     uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
1053 }
1054 
1055 /**
1056  *****************************************************************************************
1057  * @brief User Control Point List All Users handler.
1058  *
1059  * @param[in] conn_idx: Connection index.
1060  * @param[in] p_data:   Pointer to data.
1061  * @param[in] length:   Length of data.
1062  *****************************************************************************************
1063  */
uds_op_list_all_users_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)1064 static void uds_op_list_all_users_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
1065 {
1066     uds_evt_t  event;
1067     uint8_t    rsp[UDS_CTRL_PT_RSP_LEN_MAX];
1068 
1069     rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
1070     rsp[1] = UDS_CTRL_PT_OP_LIST_ALL_USERS;
1071     rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
1072 
1073     uint16_t user_num = wss_db_records_num_get();
1074     if (UDS_UNKNOWN_USER > user_num && 0 < user_num) {
1075         event.conn_idx = conn_idx;
1076         event.evt_type = UDS_EVT_CTRL_POINT_SET_BY_PEER;
1077         event.p_data   = p_data;
1078         event.length   = length;
1079         s_uds_env.uds_init.evt_handler(&event);
1080 
1081         s_uds_env.regist_user_ind_cfg[conn_idx] = UDS_EVT_CTRL_POINT_INDICATION_ENABLE;
1082 
1083         uds_regist_user_value_encode(0);  // start indicate the value of the registered user char.
1084         uds_indicate_user_char_val_chunk(conn_idx);
1085     } else if (user_num == 0) {
1086         rsp[INDEX_3] = user_num;
1087         uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN + 1);
1088     }
1089 }
1090 
1091 /**
1092  *****************************************************************************************
1093  * @brief User Control Point Delete User(s) handler.
1094  *
1095  * @param[in] conn_idx: Connection index.
1096  * @param[in] p_data:   Pointer to data.
1097  * @param[in] length:   Length of data.
1098  *****************************************************************************************
1099  */
uds_op_del_users_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)1100 static void uds_op_del_users_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
1101 {
1102     uds_evt_t  event;
1103     uint8_t    rsp[UDS_CTRL_PT_RSP_LEN_MIN+1];
1104 
1105     rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
1106     rsp[1] = UDS_CTRL_PT_OP_DEL_USERS;
1107     rsp[INDEX_2] = UDS_CTRL_PT_RSP_INVALID_PARAM;
1108 
1109     if (sizeof(uint8_t) != length || UDS_UNKNOWN_USER < p_data[0] || (s_uds_env.uds_init.user_index < p_data[0]
1110             && p_data[0] < UDS_UNKNOWN_USER)) {
1111         s_uds_env.uds_init.uds_regi_user_data_flag.regi_user_name_present = false;
1112         s_uds_env.uds_init.uds_regi_user_data_flag.user_name_truncated    = false;
1113         uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
1114     } else {
1115         rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
1116 
1117         uint8_t user_index = p_data[0];
1118         if (UDS_UNKNOWN_USER == user_index) {
1119             wss_db_record_clear();
1120             rsp[INDEX_3] = UDS_UNKNOWN_USER;
1121             s_uds_env.uds_init.user_index = UDS_UNKNOWN_USER;
1122         } else {
1123             if (!wss_db_record_delete(user_index)) {
1124                 rsp[INDEX_2] = UDS_CTRL_PT_RSP_FAILED;
1125             } else {
1126                 rsp[INDEX_3] = user_index;
1127             }
1128         }
1129 
1130         event.conn_idx = conn_idx;
1131         event.evt_type = UDS_EVT_DEL_USERS;
1132         event.p_data   = p_data;
1133         event.length   = length;
1134         if (s_uds_env.uds_init.user_index == p_data[0]) {
1135             s_uds_env.uds_init.user_index = UDS_UNKNOWN_USER;
1136         }
1137         s_uds_env.uds_init.evt_handler(&event);
1138         uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN+1);
1139     }
1140 }
1141 
1142 /**
1143  *****************************************************************************************
1144  * @brief User Control Point receive handler.
1145  *
1146  * @param[in] conn_idx: Connection index.
1147  * @param[in] p_data:   Pointer to data.
1148  * @param[in] length:   Length of data.
1149  *****************************************************************************************
1150  */
uds_receive_ucp_handler(uint8_t conn_idx,const uint8_t * p_data,uint16_t length)1151 static void uds_receive_ucp_handler(uint8_t conn_idx, const uint8_t *p_data, uint16_t length)
1152 {
1153     uint8_t rsp[UDS_CTRL_PT_RSP_LEN_MAX];
1154 
1155     switch (p_data[0]) {
1156         case UDS_CTRL_PT_OP_REGIST_NEW_USER:
1157             uds_op_regist_new_user_handler(conn_idx, &p_data[1], length - 1);
1158             break;
1159 
1160         case UDS_CTRL_PT_OP_CONSENT:
1161             uds_op_consent_handler(conn_idx, &p_data[1], length - 1);
1162             break;
1163 
1164         case UDS_CTRL_PT_OP_DEL_USER_DATA:
1165             uds_op_del_user_data_handler(conn_idx, &p_data[1], length - 1);
1166             break;
1167 
1168         case UDS_CTRL_PT_OP_LIST_ALL_USERS:
1169             uds_op_list_all_users_handler(conn_idx, &p_data[1], length - 1);
1170             break;
1171 
1172         case UDS_CTRL_PT_OP_DEL_USERS:
1173             uds_op_del_users_handler(conn_idx, &p_data[1], length - 1);
1174             break;
1175 
1176         default:
1177             rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
1178             rsp[1] = p_data[0];
1179             rsp[INDEX_2] = UDS_CTRL_PT_RSP_NOT_SUP;
1180             uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN);
1181             break;
1182     }
1183 }
1184 
1185 /**
1186  *****************************************************************************************
1187  * @brief Indicate the Registered User Characteristic value.
1188  *
1189  * @param[in] conn_idx:  Connection index.
1190  *****************************************************************************************
1191  */
uds_indicate_user_char_val_chunk(uint8_t conn_idx)1192 static sdk_err_t uds_indicate_user_char_val_chunk(uint8_t conn_idx)
1193 {
1194     uint8_t          chunk_len;
1195     gatts_noti_ind_t uds_ind;
1196     sdk_err_t        error_code;
1197 
1198     chunk_len = s_regi_user_char_val_stream.p_segm_length[s_regi_user_char_val_stream.segm_num -
1199                                                      s_regi_user_char_val_stream.segm_offset];
1200 
1201     if (s_regi_user_char_val_stream.segm_offset == 0) {
1202         s_regi_user_char_val_stream.p_data        = NULL;
1203         s_regi_user_char_val_stream.offset        = 0;
1204         s_regi_user_char_val_stream.length        = 0;
1205         s_regi_user_char_val_stream.p_segm_length = NULL;
1206         s_regi_user_char_val_stream.segm_num      = 0;
1207         s_regi_user_char_val_stream.segm_offset   = 0;
1208 
1209         uds_evt_t event;
1210         event.evt_type = UDS_EVT_REGIST_USER_RSP_CPLT;
1211         s_uds_env.uds_init.evt_handler(&event);
1212 
1213         // After indicating all users, then indicate the number of users.
1214         uint8_t   rsp[UDS_CTRL_PT_RSP_LEN_MIN+1];
1215         uint16_t  user_num = wss_db_records_num_get();
1216 
1217         rsp[0] = UDS_CTRL_PT_OP_RSP_CODE;
1218         rsp[1] = UDS_CTRL_PT_OP_LIST_ALL_USERS;
1219         rsp[INDEX_2] = UDS_CTRL_PT_RSP_SUCCESS;
1220         rsp[INDEX_3] = user_num;
1221         uds_ctrl_pt_rsp_send(conn_idx, rsp, UDS_CTRL_PT_RSP_LEN_MIN+1);
1222 
1223         return SDK_SUCCESS;
1224     }
1225 
1226     uds_ind.type   = BLE_GATT_INDICATION;
1227     uds_ind.handle = prf_find_handle_by_idx(UDS_IDX_REGIST_USER_VAL,
1228                                             s_uds_env.start_hdl,
1229                                             (uint8_t *)&s_uds_env.uds_init.char_mask);
1230     uds_ind.length = chunk_len;
1231     uds_ind.value  = (uint8_t *)s_regi_user_char_val_stream.p_data + s_regi_user_char_val_stream.offset;
1232 
1233     error_code     = ble_gatts_noti_ind(conn_idx, &uds_ind);
1234     if (SDK_SUCCESS == error_code) {
1235         s_regi_user_char_val_stream.offset += chunk_len;
1236         s_regi_user_char_val_stream.segm_offset--;
1237     }
1238 
1239     return error_code;
1240 }
1241 
1242 /**
1243  *****************************************************************************************
1244  * @brief Encode the Registered User Characteristic value.
1245  *
1246  * @param[in] conn_idx:  Connection index.
1247  *****************************************************************************************
1248  */
uds_regist_user_value_encode(uint8_t conn_idx)1249 static void uds_regist_user_value_encode(uint8_t conn_idx)
1250 {
1251     uint8_t ret;
1252     ret = memset_s(&s_regi_user_char_val_stream, sizeof(s_regi_user_char_val_stream),
1253                    0, sizeof(s_regi_user_char_val_stream));
1254     if (ret < 0) {
1255         return;
1256     }
1257 
1258     s_uds_env.segm_head_roll_num = 0;
1259 
1260     static uint8_t   local_buf[UDS_REGI_USER_VAL_LEN_MAX * INDEX_5 * INDEX_3] = {0};
1261     static uint16_t  local_segm_length[10] = {0};
1262     uint16_t  length = 0;
1263     uint16_t  chunk_len = 0;
1264     uint16_t  segm_total_num = 0;
1265     uint8_t   regi_users_num = wss_db_records_num_get();
1266     uint8_t   ret;
1267 
1268     for (uint8_t i = 0; i < regi_users_num; i++) {
1269         wss_rec_t loc_rec;
1270         uint16_t  segm_num_per_user = 0;
1271         uint16_t  name_offset_per_user = 0;
1272         if (wss_db_record_get(i, &loc_rec)) {
1273             continue;
1274         }
1275 
1276         do {
1277             chunk_len = loc_rec.name_length - name_offset_per_user;
1278 
1279             if (UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET >= chunk_len && segm_num_per_user == 0) {
1280                 uint8_t segm_header = 0;
1281 
1282                 if (UDS_UNKNOWN_USER == s_uds_env.uds_init.user_index) {
1283                     s_uds_env.uds_init.uds_regi_user_data_flag.regi_user_name_present = false;
1284                 }
1285 
1286                 uint8_t regi_user_data_flags = 0;
1287                 uint8_t regi_user_index;
1288 
1289                 segm_header |= (s_uds_env.segm_head_roll_num << USER_DATA_OFFSET);
1290                 segm_header |= UDS_ONLY_REGI_USER_SEGM;  // the only packet.
1291 
1292                 if (s_uds_env.uds_init.uds_regi_user_data_flag.regi_user_name_present) {
1293                     regi_user_data_flags |= UDS_REGI_USER_NAME_PRESENT;
1294                 }
1295 
1296                 if (s_uds_env.uds_init.uds_regi_user_data_flag.user_name_truncated) {
1297                     regi_user_data_flags |= UDS_USER_NAME_TRUNCATED;
1298                 }
1299 
1300                 regi_user_index = i;
1301 
1302                 local_buf[length++] = segm_header;
1303                 local_buf[length++] = regi_user_data_flags;
1304                 local_buf[length++] = regi_user_index;
1305 
1306                 ret = memcpy_s(&local_buf[length], loc_rec.name_length,
1307                                loc_rec.first_name, loc_rec.name_length);
1308                 if (ret < 0) {
1309                     return;
1310                 }
1311                 length += loc_rec.name_length;
1312 
1313                 local_segm_length[segm_total_num++] = loc_rec.name_length + NAME_LEN_OFFSET;
1314                 s_regi_user_char_val_stream.length += (loc_rec.name_length + NAME_LEN_OFFSET);
1315                 name_offset_per_user += loc_rec.name_length;
1316             } else if (UDS_REGI_USER_DATA_LEN_MAX >= chunk_len && segm_num_per_user != 0) {
1317                 uint8_t segm_header = 0;
1318                 segm_header |= (s_uds_env.segm_head_roll_num << USER_DATA_OFFSET);
1319                 segm_header |= UDS_LAST_REGI_USER_SEGM;  // the last packet.
1320                 local_buf[length++] = segm_header;
1321 
1322                 ret = memcpy_s(&local_buf[length], chunk_len, loc_rec.first_name + name_offset_per_user, chunk_len);
1323                 if (ret < 0) {
1324                     return;
1325                 }
1326                 length += chunk_len;
1327 
1328                 local_segm_length[segm_total_num++] = chunk_len + 1;
1329                 s_regi_user_char_val_stream.length += (chunk_len + 1);
1330                 name_offset_per_user += chunk_len;
1331             } else if (UDS_REGI_USER_DATA_LEN_MAX < chunk_len) {
1332                 if (segm_num_per_user == 0) {
1333                     uint8_t segm_header = 0;
1334                     if (UDS_UNKNOWN_USER == s_uds_env.uds_init.user_index) {
1335                         s_uds_env.uds_init.uds_regi_user_data_flag.regi_user_name_present = false;
1336                     }
1337                     uint8_t regi_user_data_flags = 0;
1338                     uint8_t regi_user_index;
1339 
1340                     segm_header |= (s_uds_env.segm_head_roll_num << USER_DATA_OFFSET);
1341                     segm_header |= UDS_FIRST_REGI_USER_SEGM;  // the first packet.
1342                     if (s_uds_env.uds_init.uds_regi_user_data_flag.regi_user_name_present) {
1343                         regi_user_data_flags |= UDS_REGI_USER_NAME_PRESENT;
1344                     }
1345 
1346                     if (s_uds_env.uds_init.uds_regi_user_data_flag.user_name_truncated) {
1347                         regi_user_data_flags |= UDS_USER_NAME_TRUNCATED;
1348                     }
1349 
1350                     regi_user_index = i;
1351 
1352                     local_buf[length++] = segm_header;
1353                     local_buf[length++] = regi_user_data_flags;
1354                     local_buf[length++] = regi_user_index;
1355 
1356                     ret = memcpy_s(&local_buf[length], UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET,
1357                                    loc_rec.first_name, UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET);
1358                     if (ret < 0) {
1359                         return;
1360                     }
1361                     length += UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET;
1362 
1363                     local_segm_length[segm_total_num++] = UDS_REGI_USER_VAL_LEN_MAX;
1364                     s_regi_user_char_val_stream.length += UDS_REGI_USER_VAL_LEN_MAX;
1365                     name_offset_per_user += UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET;
1366                 } else {
1367                     uint8_t segm_header = 0;
1368                     segm_header |= (s_uds_env.segm_head_roll_num << USER_DATA_OFFSET);
1369                     segm_header |= UDS_MIDDLE_REGI_USER_SEGM;  // the middle packet.
1370 
1371                     local_buf[length++] = segm_header;
1372                     ret = memcpy_s(&local_buf[length], UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET,
1373                                    loc_rec.first_name  + name_offset_per_user,
1374                                    UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET);
1375                     if (ret < 0) {
1376                         return;
1377                     }
1378                     length += UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET;
1379 
1380                     local_segm_length[segm_total_num++] = UDS_REGI_USER_VAL_LEN_MAX;
1381                     s_regi_user_char_val_stream.length += UDS_REGI_USER_VAL_LEN_MAX;
1382                     name_offset_per_user += UDS_REGI_USER_DATA_LEN_MAX - USER_DATA_OFFSET;
1383                 }
1384             }
1385             segm_num_per_user++;
1386             if (s_uds_env.segm_head_roll_num == ROLL_NUM) {
1387                 s_uds_env.segm_head_roll_num = 0;
1388             } else {
1389                 s_uds_env.segm_head_roll_num++;
1390             }
1391         } while (name_offset_per_user != loc_rec.name_length);
1392     }
1393 
1394     s_regi_user_char_val_stream.segm_offset   = segm_total_num;
1395     s_regi_user_char_val_stream.segm_num      = segm_total_num;
1396     s_regi_user_char_val_stream.p_segm_length = local_segm_length;
1397     s_regi_user_char_val_stream.p_data        = local_buf;
1398     s_regi_user_char_val_stream.offset        = 0;
1399 }
1400 
1401 /*
1402  * GLOBAL FUNCTION DEFINITIONS
1403  *****************************************************************************************
1404  */
uds_set_cur_user_index(uint8_t conn_idx,uint8_t user_index)1405 void uds_set_cur_user_index(uint8_t conn_idx, uint8_t user_index)
1406 {
1407     s_uds_env.uds_init.user_index = user_index;
1408 }
1409 
uds_get_cur_user_index(uint8_t conn_idx)1410 uint8_t uds_get_cur_user_index(uint8_t conn_idx)
1411 {
1412     return s_uds_env.uds_init.user_index;
1413 }
1414 
uds_regi_user_val_send(uint8_t conn_idx)1415 sdk_err_t uds_regi_user_val_send(uint8_t conn_idx)
1416 {
1417     uds_regist_user_value_encode(0);
1418     return uds_indicate_user_char_val_chunk(conn_idx);
1419 }
1420 
uds_db_change_incr_val_send(uint8_t conn_idx,uint8_t user_index)1421 sdk_err_t uds_db_change_incr_val_send(uint8_t conn_idx, uint8_t user_index)
1422 {
1423     sdk_err_t        error_code = SDK_ERR_NTF_DISABLED;
1424     uint16_t         length;
1425     gatts_noti_ind_t uds_ntf;
1426     wss_rec_t        loc_rec;
1427 
1428     if (UDS_UNKNOWN_USER != user_index) {
1429         if (wss_db_record_get(user_index, &loc_rec)) {
1430             length = sizeof(loc_rec.db_change_incr_val);
1431             if (PRF_CLI_START_NTF == s_uds_env.db_change_incr_ntf_cfg[conn_idx]) {
1432                 uds_ntf.type   = BLE_GATT_NOTIFICATION;
1433                 uds_ntf.handle = prf_find_handle_by_idx(UDS_IDX_DB_CHANGE_INCR_VAL,
1434                                                         s_uds_env.start_hdl,
1435                                                         (uint8_t *)&s_uds_env.uds_init.char_mask);
1436                 uds_ntf.length = length;
1437                 uds_ntf.value  = (uint8_t *)&loc_rec.db_change_incr_val;
1438                 error_code     = ble_gatts_noti_ind(conn_idx, &uds_ntf);
1439             }
1440         }
1441     }
1442     return error_code;
1443 }
1444 
uds_ctrl_pt_rsp_send(uint8_t conn_idx,uint8_t * p_data,uint16_t length)1445 sdk_err_t uds_ctrl_pt_rsp_send(uint8_t conn_idx, uint8_t *p_data, uint16_t length)
1446 {
1447     sdk_err_t        error_code = SDK_ERR_IND_DISABLED;
1448     gatts_noti_ind_t ctrl_pt_rsp;
1449 
1450     if (PRF_CLI_START_IND == s_uds_env.ctrl_point_ind_cfg[conn_idx]) {
1451         ctrl_pt_rsp.type   = BLE_GATT_INDICATION;
1452         ctrl_pt_rsp.handle = prf_find_handle_by_idx(UDS_IDX_CTRL_POINT_VAL,
1453             s_uds_env.start_hdl,
1454             (uint8_t *)&s_uds_env.uds_init.char_mask);
1455         ctrl_pt_rsp.length = length;
1456         ctrl_pt_rsp.value  = p_data;
1457         error_code         = ble_gatts_noti_ind(conn_idx, &ctrl_pt_rsp);
1458     }
1459 
1460     return error_code;
1461 }
1462 
uds_service_init(uds_init_t * p_uds_init)1463 sdk_err_t uds_service_init(uds_init_t *p_uds_init)
1464 {
1465     sdk_err_t ret;
1466     if (p_uds_init == NULL) {
1467         return SDK_ERR_POINTER_NULL;
1468     }
1469 
1470     ret = memset_s(&s_uds_env, sizeof(s_uds_env), 0, sizeof(s_uds_env));
1471     if (ret < 0) {
1472         return ret;
1473     }
1474     ret = memcpy_s(&s_uds_env.uds_init, sizeof(uds_init_t), p_uds_init, sizeof(uds_init_t));
1475     if (ret < 0) {
1476         return ret;
1477     }
1478 
1479     return ble_server_prf_add(&uds_prf_info);
1480 }
1481 
1482 #if defined(PTS_AUTO_TEST)
uds_regist_new_user(uint8_t conn_idx)1483 void uds_regist_new_user(uint8_t conn_idx)
1484 {
1485     uint16_t consent_code = 0x0001;
1486 
1487     uds_chars_val_t uds_chars_val;
1488     uint8_t         user_index;
1489     uint8_t         db_change_incr_val;
1490 
1491     user_index                        = (uint8_t)wss_db_records_num_get();
1492     s_uds_env.uds_init.user_index     = user_index;
1493     uint8_t first_name[]              = "tom";
1494     db_change_incr_val                = UDS_DB_CHANGE_INCR_DEFAULT_VAL;
1495     uds_chars_val.age                 = AGE_18;
1496     uds_chars_val.height              = HEIGHT_1650;
1497     uds_chars_val.gender              = 0x00;
1498     uds_chars_val.date_of_birth.year  = YEAR_2000;
1499     uds_chars_val.date_of_birth.month = MONTH_01;
1500     uds_chars_val.date_of_birth.day   = DAY_01;
1501     uds_chars_val.p_first_name        = &first_name[0];
1502     uds_chars_val.name_length         = sizeof(first_name);
1503 
1504     wss_db_record_add(user_index, consent_code, db_change_incr_val, &uds_chars_val);
1505 }
1506 
uds_del_users(uint8_t conn_idx)1507 void uds_del_users(uint8_t conn_idx)
1508 {
1509     uint8_t user_index = 0x00;
1510     wss_db_record_delete(user_index);
1511 }
1512 #endif
1513