• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 #include "drivers.h"
19 #include "stack/ble/ble.h"
20 #include "tl_common.h"
21 
22 #include "blt_common.h"
23 #include "device_manage.h"
24 #include "simple_sdp.h"
25 
26 #if (BLE_MASTER_SIMPLE_SDP_ENABLE)
27 
28 typedef struct {
29     u8 type;
30     u8 rf_len;
31     u16 l2capLen;
32     u16 chanId;
33     u8 opcode;
34     u8 format;
35     u8 data[1];  // character_handle / property / value_handle / value
36 } ble_att_findInfoRsp_t;
37 
38 int master_sdp_pending = 0;  // SDP: service discovery
39 
40 dev_char_info_t cur_sdp_device;  // current connected device which is in SDP flow
41 
42 main_service_t main_service = 0;
43 
44 static const u8 my_OtaUUID[16] = WRAPPING_BRACES(TELINK_SPP_DATA_OTA);
45 
46 ble_sts_t host_att_discoveryService(u16 handle, att_db_uuid16_t *p16, int n16, att_db_uuid128_t *p128, int n128);
47 
simple_sdp_loop(void)48 void simple_sdp_loop(void)
49 {
50     if (main_service) {
51         main_service();
52         main_service = 0;
53     }
54 }
55 
56 /**
57  * @brief   SDP handler.
58  *          !!! Note: This is a simple SDP processing implemented by telink.
59  * @param   none.
60  * @return  none.
61  */
app_service_discovery(void)62 void app_service_discovery(void)
63 {
64     att_db_uuid16_t db16[ATT_DB_UUID16_NUM];
65     att_db_uuid128_t db128[ATT_DB_UUID128_NUM];
66     memset(db16, 0, ATT_DB_UUID16_NUM * sizeof(att_db_uuid16_t));
67     memset(db128, 0, ATT_DB_UUID128_NUM * sizeof(att_db_uuid128_t));
68 
69     if (master_sdp_pending && host_att_discoveryService(master_sdp_pending, db16, ATT_DB_UUID16_NUM, db128,
70                                                         ATT_DB_UUID128_NUM) == BLE_SUCCESS) {
71         // service discovery OK
72         cur_sdp_device.char_handle[2] = blm_att_findHandleOfUuid128(db128, my_OtaUUID);  // OTA
73         cur_sdp_device.char_handle[3] = blm_att_findHandleOfUuid16(
74             db16, CHARACTERISTIC_UUID_HID_REPORT,
75             HID_REPORT_ID_CONSUME_CONTROL_INPUT | (HID_REPORT_TYPE_INPUT << 8));  // consume report(media key report)
76         cur_sdp_device.char_handle[4] = blm_att_findHandleOfUuid16(
77             db16, CHARACTERISTIC_UUID_HID_REPORT,
78             HID_REPORT_ID_KEYBOARD_INPUT | (HID_REPORT_TYPE_INPUT << 8));  // normal key report
79         /* add the peer device att_handle value to conn_dev_list after service discovery is correctly finished */
80         dev_char_info_add_peer_att_handle(&cur_sdp_device);
81 
82         /* peer device att_handle value store in flash */
83         dev_char_info_store_peer_att_handle(&cur_sdp_device);
84     }
85 
86     master_sdp_pending = 0;  // service discovery finish
87 }
88 
89 /**
90  * @brief       This function is used to register SDP handler.
91  * @param[in]   p       - Pointer point to SDP handler.
92  * @return      none.
93  */
app_register_service(void * p)94 void app_register_service(void *p)
95 {
96     main_service = p;
97 }
98 
99 u8 *p_att_response = 0;
100 
101 volatile u32 host_att_req_busy = 0;
102 
103 /**
104  * @brief       This function is used to process ATT packets related to SDP
105  * @param[in]   connHandle  - connection handle
106  * @param[in]   p           - Pointer point to ATT data buffer.
107  * @return
108  */
host_att_client_handler(u16 connHandle,u8 * p)109 int host_att_client_handler(u16 connHandle, u8 *p)
110 {
111     ble_att_readByTypeRsp_t *p_rsp = (ble_att_readByTypeRsp_t *)p;
112     if (p_att_response) {
113         if ((connHandle & 7) == (host_att_req_busy & 7) && p_rsp->chanId == 0x04 &&
114             (p_rsp->opcode == 0x01 || p_rsp->opcode == ((host_att_req_busy >> 16) | 1))) {
115             memcpy(p_att_response, p, 32);
116             host_att_req_busy = 0;
117         }
118     }
119     return 0;
120 }
121 
122 typedef int (*host_att_idle_func_t)(void);
123 host_att_idle_func_t host_att_idle_func = 0;
124 
125 /**
126  * @brief       This function is used to register ble stack mainloop function.
127  * @param[in]   p           - Pointer point to ble stack mainloop function.
128  * @return
129  */
host_att_register_idle_func(void * p)130 int host_att_register_idle_func(void *p)
131 {
132     if (host_att_idle_func)
133         return 1;
134 
135     host_att_idle_func = p;
136     return 0;
137 }
138 
host_att_response()139 int host_att_response()
140 {
141     return host_att_req_busy == 0;
142 }
143 
host_att_service_wait_event(u16 handle,u8 * p,u32 timeout)144 int host_att_service_wait_event(u16 handle, u8 *p, u32 timeout)
145 {
146     host_att_req_busy = handle | (p[6] << 16);
147     p_att_response = p;
148 
149     u32 t = clock_time();
150     while (!clock_time_exceed(t, timeout)) {
151         if (host_att_response()) {
152             return 0;
153         }
154         if (host_att_idle_func) {
155             if (host_att_idle_func()) {
156                 break;
157             }
158         }
159     }
160     return 1;
161 }
162 
163 // Gaoqiu add ------------------------------------------------------------------
app_char_discovery(u8 * reslut,u16 connHandle,u16 startAttHandle,u16 endAttHandle,u8 * uuid,u8 uuidLen)164 int app_char_discovery(u8 *reslut, u16 connHandle, u16 startAttHandle, u16 endAttHandle, u8 *uuid, u8 uuidLen)
165 {
166     blc_gatt_pushReadByTypeRequest(connHandle, startAttHandle, endAttHandle, uuid, uuidLen);
167 
168     return host_att_service_wait_event(connHandle, reslut, 1000000);
169 }
170 
app_read_char_value(u8 * reslut,u16 connHandle,u16 attHandle)171 int app_read_char_value(u8 *reslut, u16 connHandle, u16 attHandle)
172 {
173     blc_gatt_pushReadRequest(connHandle, attHandle);
174 
175     return host_att_service_wait_event(connHandle, reslut, 1000000);
176 }
177 
app_find_char_info(u8 * reslut,u16 connHandle,u16 startAttHandle,u16 endAttHandle)178 int app_find_char_info(u8 *reslut, u16 connHandle, u16 startAttHandle, u16 endAttHandle)
179 {
180     blc_gatt_pushFindInformationRequest(connHandle, startAttHandle, endAttHandle);
181 
182     return host_att_service_wait_event(connHandle, reslut, 1000000);
183 }
184 
blm_att_findHandleOfUuid16(att_db_uuid16_t * p,u16 uuid,u16 ref)185 u16 blm_att_findHandleOfUuid16(att_db_uuid16_t *p, u16 uuid, u16 ref)
186 {
187     for (int i = 0; i < p->num; i++) {
188         if (p[i].uuid == uuid && p[i].ref == ref) {
189             return p[i].handle;
190         }
191     }
192     return 0;
193 }
194 
blm_att_findHandleOfUuid128(att_db_uuid128_t * p,const u8 * uuid)195 u16 blm_att_findHandleOfUuid128(att_db_uuid128_t *p, const u8 *uuid)
196 {
197     for (int i = 0; i < p->num; i++) {
198         if (memcmp(p[i].uuid, uuid, 16) == 0) {
199             return p[i].handle;
200         }
201     }
202     return 0;
203 }
204 
host_att_discoveryService(u16 handle,att_db_uuid16_t * p16,int n16,att_db_uuid128_t * p128,int n128)205 ble_sts_t host_att_discoveryService(u16 handle, att_db_uuid16_t *p16, int n16, att_db_uuid128_t *p128, int n128)
206 {
207     att_db_uuid16_t *ps16 = p16;
208     att_db_uuid128_t *ps128 = p128;
209     int i16 = 0;
210     int i128 = 0;
211 
212     ps16->num = 0;
213     ps128->num = 0;
214 
215     // char discovery: att_read_by_type
216     // hid discovery: att_find_info
217     u8 dat[32];
218     u16 s = 1;
219     u16 uuid = GATT_UUID_CHARACTER;
220     do {
221         dat[6] = ATT_OP_READ_BY_TYPE_REQ;
222         if (app_char_discovery(dat, handle, s, 0xffff, (u8 *)&uuid, 2)) {
223             // 1s
224             return GATT_ERR_SERVICE_DISCOVERY_TIEMOUT;  // timeout
225         }
226 
227         // process response data
228         ble_att_readByTypeRsp_t *p_rsp = (ble_att_readByTypeRsp_t *)dat;
229         if (p_rsp->opcode != ATT_OP_READ_BY_TYPE_RSP) {
230             break;
231         }
232 
233         if (p_rsp->datalen == 21) {
234             // uuid128
235             s = p_rsp->data[3] + p_rsp->data[4] * 256;
236             if (i128 < n128) {
237                 p128->property = p_rsp->data[2];
238                 p128->handle = s;
239                 memcpy(p128->uuid, p_rsp->data + 5, 16);
240                 i128++;
241                 p128++;
242             }
243         } else if (p_rsp->datalen == 7) {
244             // uuid16
245             u8 *pd = p_rsp->data;
246             while (p_rsp->l2capLen > 7) {
247                 s = pd[3] + pd[4] * 256;
248                 if (i16 < n16) {
249                     p16->property = pd[2];
250                     p16->handle = s;
251                     p16->uuid = pd[5] | (pd[6] << 8);
252                     p16->ref = 0;
253                     i16++;
254                     p16++;
255                 }
256                 p_rsp->l2capLen -= 7;
257                 pd += 7;
258             }
259         }
260     } while (1);
261 
262     ps16->num = i16;
263     ps128->num = i128;
264 
265     // --------- use att_find_info to find the reference property for hid ----------
266     p16 = ps16;
267     for (int i = 0; i < i16; i++) {
268         if (p16->uuid == CHARACTERISTIC_UUID_HID_REPORT) {
269             // find reference
270             dat[6] = ATT_OP_FIND_INFORMATION_REQ;
271             if (app_find_char_info(dat, handle, p16->handle, 0xffff)) {
272                 // 1s
273                 return GATT_ERR_SERVICE_DISCOVERY_TIEMOUT;  // timeout
274             }
275 
276             ble_att_findInfoRsp_t *p_rsp = (ble_att_findInfoRsp_t *)dat;
277             if (p_rsp->opcode == ATT_OP_FIND_INFO_RSP && p_rsp->format == 1) {
278                 int n = p_rsp->l2capLen - 2;
279                 u8 *pd = p_rsp->data;
280                 while (n > 0) {
281                     if ((pd[2] == U16_LO(GATT_UUID_CHARACTER) && pd[3] == U16_HI(GATT_UUID_CHARACTER)) ||
282                         (pd[2] == U16_LO(GATT_UUID_PRIMARY_SERVICE) && pd[3] == U16_HI(GATT_UUID_PRIMARY_SERVICE))) {
283                         break;
284                     }
285 
286                     if (pd[2] == U16_LO(GATT_UUID_REPORT_REF) && pd[3] == U16_HI(GATT_UUID_REPORT_REF)) {
287                         // -----------		read attribute ----------------
288                         dat[6] = ATT_OP_READ_REQ;
289                         if (app_read_char_value(dat, handle, pd[0])) {
290                             return GATT_ERR_SERVICE_DISCOVERY_TIEMOUT;  // timeout
291                         }
292 
293                         ble_att_readRsp_t *pr = (ble_att_readRsp_t *)dat;
294                         if (pr->opcode == ATT_OP_READ_RSP) {
295                             p16->ref = pr->value[0] | (pr->value[1] << 8);
296                         }
297 
298                         break;
299                     }
300                     n -= 4;
301                     pd += 4;
302                 }
303             }
304         }  // ----- end for if CHARACTERISTIC_UUID_HID_REPORT
305 
306         p16++;
307     }
308 
309     return BLE_SUCCESS;
310 }
311 
312 /**
313  * @brief       Used for add peer device service ATThandle.
314  * @param[in]   dev_char_info       - Pointer point to data buffer.
315  * @return      0: success
316  *              1: failed
317  */
dev_char_info_add_peer_att_handle(dev_char_info_t * dev_char_info)318 int dev_char_info_add_peer_att_handle(dev_char_info_t *dev_char_info)
319 {
320     int i;
321     for (i = 0; i < conn_master_num; i++) {
322         if (conn_dev_list[i].conn_handle == dev_char_info->conn_handle) {
323             break;
324         }
325     }
326 
327     if (i < conn_master_num) {
328         for (int j = 0; j < CHAR_HANDLE_MAX; j++) {
329             conn_dev_list[i].char_handle[j] = dev_char_info->char_handle[j];
330         }
331 
332         conn_dev_list[i].char_handle_valid = 1;
333 
334         return 0;  // success
335     } else {
336         return 1;  // fail
337     }
338 }
339 
340 /**
341  * @brief       Use for store peer device att handle to flash.
342  * @param[in]   dev_char_info    Pointer point to peer device ATT handle info.
343  * @return      0: failed
344  *             !0: return falsh address
345  */
dev_char_info_store_peer_att_handle(dev_char_info_t * pdev_char)346 int dev_char_info_store_peer_att_handle(dev_char_info_t *pdev_char)
347 {
348     u8 mark;
349     u32 current_flash_adr;
350     for (current_flash_adr = FLASH_SDP_ATT_ADRRESS;
351          current_flash_adr < (FLASH_SDP_ATT_ADRRESS + FLASH_SDP_ATT_MAX_SIZE);
352          current_flash_adr += sizeof(dev_att_t)) {
353         flash_read_page(current_flash_adr, 1, &mark);
354 
355         if (mark == U8_MAX) {
356             flash_write_page(current_flash_adr + OFFSETOF(dev_att_t, adr_type), 7,
357                              (u8 *)&pdev_char->peer_adrType);  // peer_adrType(1)+peer_addr(6)
358 
359 #if (PEER_SLAVE_USE_RPA_EN)
360             if (IS_RESOLVABLE_PRIVATE_ADDR(pdev_char->peer_adrType, pdev_char->peer_addr)) {
361             }
362 #endif
363 
364             // char_handle[0] :  MIC
365             // char_handle[1] :  Speaker
366             // char_handle[2] :  OTA
367             // char_handle[3] :  Consume Report
368             // char_handle[4] :  Key Report
369             // char_handle[5] :
370             // char_handle[6] :  BLE Module, SPP Server to Client
371             // char_handle[7] :  BLE Module, SPP Client to Server
372             flash_write_page(current_flash_adr + OFFSETOF(dev_att_t, char_handle) + 2 * 2, 2,
373                              (u8 *)&pdev_char->char_handle[2]);  // save OTA att_handle
374             flash_write_page(current_flash_adr + OFFSETOF(dev_att_t, char_handle) + 3 * 2, 2,
375                              (u8 *)&pdev_char->char_handle[3]);  // save Consume Report att_handle
376             flash_write_page(current_flash_adr + OFFSETOF(dev_att_t, char_handle) + 4 * 2, 2,
377                              (u8 *)&pdev_char->char_handle[4]);  // save Key Report att_handle
378 
379             mark = ATT_BOND_MARK;
380             flash_write_page(current_flash_adr, 1, (u8 *)&mark);
381 
382             return current_flash_adr;  // Store Success
383         }
384     }
385 
386     return 0;  // Store Fail
387 }
388 
389 /**
390  * @brief       Get peer device att handle info by peer address
391  * @param[in]   adr_type         address type
392  * @param[in]   addr             Pointer point to peer address buffer
393  * @param[out]  dev_att          Pointer point to dev_att_t
394  * @return      0: failed
395  *             !0: return falsh address
396  */
dev_char_info_search_peer_att_handle_by_peer_mac(u8 adr_type,u8 * addr,dev_att_t * pdev_att)397 int dev_char_info_search_peer_att_handle_by_peer_mac(u8 adr_type, u8 *addr, dev_att_t *pdev_att)
398 {
399     u8 mark;
400     u32 current_flash_adr;
401     for (current_flash_adr = FLASH_SDP_ATT_ADRRESS;
402          current_flash_adr < (FLASH_SDP_ATT_ADRRESS + FLASH_SDP_ATT_MAX_SIZE);
403          current_flash_adr += sizeof(dev_att_t)) {
404         flash_read_page(current_flash_adr, 1, &mark);
405 
406         if (mark == U8_MAX) {
407             return 0;  // Search Fail
408         } else if (mark == ATT_ERASE_MARK) {
409             continue;  // Search for next unit
410         } else if (mark == ATT_BOND_MARK) {
411             flash_read_page(current_flash_adr, sizeof(dev_att_t), (u8 *)pdev_att);
412 
413             int addr_match = 0;
414 #if (PEER_SLAVE_USE_RPA_EN)
415             if (IS_RESOLVABLE_PRIVATE_ADDR(pdev_att->adr_type, pdev_att->addr)) {
416                 if (0) {
417                     addr_match = 1;
418                 }
419             } else
420 #endif
421             {
422                 if (adr_type == pdev_att->adr_type && !memcmp(addr, pdev_att->addr, 6)) {  // match
423                     addr_match = 1;
424                 }
425             }
426 
427             if (addr_match) {
428                 return current_flash_adr;
429             }
430         }
431     }
432 
433     return 0;  // Search Fail
434 }
435 
436 /**
437  * @brief       Delete peer device att handle info by peer address
438  * @param[in]   adr_type         address type
439  * @param[in]   addr             Pointer point to peer address buffer
440  * @return      0: success
441  *              1: not find
442  */
dev_char_info_delete_peer_att_handle_by_peer_mac(u8 addrType,u8 * addr)443 int dev_char_info_delete_peer_att_handle_by_peer_mac(u8 addrType, u8 *addr)
444 {
445     dev_att_t dev_info;
446 
447     for (u32 cur_flash_addr = FLASH_SDP_ATT_ADRRESS; cur_flash_addr < FLASH_SDP_ATT_ADRRESS + FLASH_SDP_ATT_MAX_SIZE;
448          cur_flash_addr += sizeof(dev_att_t)) {
449         u8 flag;
450         flash_read_page(cur_flash_addr, 1, &flag);
451 
452         // have no device information
453         if (flag == 0xff)
454             return 1;  // not find
455 
456         if (flag == ATT_BOND_MARK) {
457             // only read per device MAC address type and MAC address
458             flash_read_page(cur_flash_addr, 8, (u8 *)&dev_info);
459 #if (PEER_SLAVE_USE_RPA_EN)
460             if (IS_RESOLVABLE_PRIVATE_ADDR(addrType, addr)) {
461                 // todo: resolve private address using IRK
462             } else
463 #endif
464             {
465                 if (dev_info.adr_type == addrType && !memcmp(dev_info.addr, addr, 6)) {
466                     u8 temp = ATT_ERASE_MARK;
467                     flash_write_page(cur_flash_addr, 1, (u8 *)&temp);
468                     return 0;  // find
469                 }
470             }
471         }
472     }
473     return 1;  // not find
474 }
475 
476 #endif  // end of BLE_MASTER_SIMPLE_SDP_ENABLE
477