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