• 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 "device_manage.h"
23 
24 /*
25  * Used for store information of connected devices.
26  *
27  * 0 ~ (MASTER_MAX_NUM - 1) is for master,  MASTER_MAX_NUM ~ (MASTER_MAX_NUM + SLAVE_MAX_NUM - 1) s for slave
28  *
29  * e.g.    MASTER_MAX_NUM	SLAVE_MAX_NUM			master					  slave
30  *                0				  1				     none				conn_dev_list[0]
31  *                0				  2					 none				conn_dev_list[0..1]
32  *                0				  3					 none				conn_dev_list[0..2]
33  *                0				  4					 none				conn_dev_list[0..3]
34  *
35  *                1				  0				conn_dev_list[0]			   none
36  *                1				  1				conn_dev_list[0]		conn_dev_list[1]
37  *                1				  2				conn_dev_list[0]		conn_dev_list[1..2]
38  *                1				  3				conn_dev_list[0]		conn_dev_list[1..3]
39  *                1				  4				conn_dev_list[0]		conn_dev_list[1..4]
40  *
41  *                2				  0				conn_dev_list[0..1]			   none
42  *                2				  1				conn_dev_list[0..1]		conn_dev_list[2]
43  *                2				  2				conn_dev_list[0..1]		conn_dev_list[2..3]
44  *                2				  3				conn_dev_list[0..1]		conn_dev_list[2..4]
45  *                2				  4				conn_dev_list[0..1]		conn_dev_list[2..5]
46  *
47  *                3				  0				conn_dev_list[0..2]			   none
48  *                3				  1				conn_dev_list[0..2]		conn_dev_list[3]
49  *                3				  2				conn_dev_list[0..2]		conn_dev_list[3..4]
50  *                3				  3				conn_dev_list[0..2]		conn_dev_list[3..5]
51  *                3				  4				conn_dev_list[0..2]		conn_dev_list[3..6]
52  *
53  *                4				  0				conn_dev_list[0..3]			   none
54  *                4				  1				conn_dev_list[0..3]		conn_dev_list[4]
55  *                4				  2				conn_dev_list[0..3]		conn_dev_list[4..5]
56  *                4				  3				conn_dev_list[0..3]		conn_dev_list[4..6]
57  *                4				  4				conn_dev_list[0..3]		conn_dev_list[4..7]
58  */
59 _attribute_ble_data_retention_ dev_char_info_t conn_dev_list[DEVICE_CHAR_INFO_MAX_NUM];
60 
61 _attribute_ble_data_retention_ int conn_master_num = 0;  // current master number in connection state
62 _attribute_ble_data_retention_ int conn_slave_num = 0;   // current slave number in connection state
63 
64 /**
65  * @brief       Used for add device information to conn_dev_list.
66  * @param[in]   dev_char_info       - Pointer point to data buffer.
67  * @return      0 ~ DEVICE_CHAR_INFO_MAX_NUM - 1: new connection index, insert success
68  *              0xFF: insert failed
69  */
dev_char_info_insert(dev_char_info_t * dev_char_info)70 int dev_char_info_insert(dev_char_info_t *dev_char_info)
71 {
72     int index = INVALID_CONN_IDX;
73     if (dev_char_info->conn_role == LL_ROLE_MASTER) {  // master
74         for (int i = 0; i < MASTER_MAX_NUM; i++) {
75             if (conn_dev_list[i].conn_state == 0) {
76                 index = i;
77                 conn_master_num++;
78                 break;
79             }
80         }
81     } else if (dev_char_info->conn_role == LL_ROLE_SLAVE) {  // slave
82         for (int i = MASTER_MAX_NUM; i < MASTER_MAX_NUM + SLAVE_MAX_NUM; i++) {
83             if (conn_dev_list[i].conn_state == 0) {
84                 index = i;
85                 conn_slave_num++;
86                 break;
87             }
88         }
89     }
90 
91     if (index != INVALID_CONN_IDX) {
92         memcpy(&conn_dev_list[index], dev_char_info, sizeof(dev_char_info_t));
93         conn_dev_list[index].conn_state = 1;
94     }
95 
96     return index;
97 }
98 
99 /**
100  * @brief       Used for add device information to conn_dev_list.
101  * @param[in]   pConnEvt - LE connection complete event data buffer address.
102  * @return      0 ~ DEVICE_CHAR_INFO_MAX_NUM - 1: new connection index, insert success
103  *              0xFF: insert failed
104  */
dev_char_info_insert_by_conn_event(hci_le_connectionCompleteEvt_t * pConnEvt)105 int dev_char_info_insert_by_conn_event(hci_le_connectionCompleteEvt_t *pConnEvt)
106 {
107     int index = INVALID_CONN_IDX;
108     if (pConnEvt->role == LL_ROLE_MASTER) {  // master
109         for (int i = 0; i < MASTER_MAX_NUM; i++) {
110             if (conn_dev_list[i].conn_state == 0) {
111                 index = i;
112                 conn_master_num++;
113                 break;
114             }
115         }
116     } else if (pConnEvt->role == LL_ROLE_SLAVE) {  // slave
117         for (int i = MASTER_MAX_NUM; i < MASTER_MAX_NUM + SLAVE_MAX_NUM; i++) {
118             if (conn_dev_list[i].conn_state == 0) {
119                 index = i;
120                 conn_slave_num++;
121                 break;
122             }
123         }
124     }
125 
126     if (index != INVALID_CONN_IDX) {
127         memset(&conn_dev_list[index], 0, sizeof(dev_char_info_t));
128 
129         conn_dev_list[index].conn_handle = pConnEvt->connHandle;
130         conn_dev_list[index].conn_role = pConnEvt->role;
131         conn_dev_list[index].conn_state = 1;
132         conn_dev_list[index].peer_adrType = pConnEvt->peerAddrType;
133         memcpy(conn_dev_list[index].peer_addr, pConnEvt->peerAddr, 6);
134     }
135 
136     return index;
137 }
138 
139 /**
140  * @brief       Used for add device information to conn_dev_list.
141  * @param[in]   pConnEvt - LE enhanced connection complete event data buffer address.
142  * @return      0 ~ DEVICE_CHAR_INFO_MAX_NUM - 1: new connection index, insert success
143  *              0xFF: insert failed
144  */
dev_char_info_insert_by_enhanced_conn_event(hci_le_enhancedConnCompleteEvt_t * pConnEvt)145 int dev_char_info_insert_by_enhanced_conn_event(hci_le_enhancedConnCompleteEvt_t *pConnEvt)
146 {
147     int index = INVALID_CONN_IDX;
148     if (pConnEvt->role == LL_ROLE_MASTER) {  // master
149         for (int i = 0; i < MASTER_MAX_NUM; i++) {
150             if (conn_dev_list[i].conn_state == 0) {
151                 index = i;
152                 conn_master_num++;
153                 break;
154             }
155         }
156     } else if (pConnEvt->role == LL_ROLE_SLAVE) {  // slave
157         for (int i = MASTER_MAX_NUM; i < MASTER_MAX_NUM + SLAVE_MAX_NUM; i++) {
158             if (conn_dev_list[i].conn_state == 0) {
159                 index = i;
160                 conn_slave_num++;
161                 break;
162             }
163         }
164     }
165 
166     if (index != INVALID_CONN_IDX) {
167         memset(&conn_dev_list[index], 0, sizeof(dev_char_info_t));
168 
169         conn_dev_list[index].conn_handle = pConnEvt->connHandle;
170         conn_dev_list[index].conn_role = pConnEvt->role;
171         conn_dev_list[index].conn_state = 1;
172         conn_dev_list[index].peer_adrType = pConnEvt->PeerAddrType;
173         memcpy(conn_dev_list[index].peer_addr, pConnEvt->PeerAddr, 6);
174     }
175 
176     return index;
177 }
178 
179 /**
180  * @brief       Used for delete device information from conn_dev_list by connHandle
181  * @param[in]   connhandle       - connection handle.
182  * @return      0: success
183  *              1: no find
184  */
dev_char_info_delete_by_connhandle(u16 connhandle)185 int dev_char_info_delete_by_connhandle(u16 connhandle)
186 {
187     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
188         if (conn_dev_list[i].conn_handle == connhandle && conn_dev_list[i].conn_state) {
189             // match
190             if (conn_dev_list[i].conn_role == LL_ROLE_MASTER) {  // master
191                 conn_master_num--;
192             } else {  // slave
193                 conn_slave_num--;
194             }
195 
196             memset(&conn_dev_list[i], 0, sizeof(dev_char_info_t));
197 
198             return 0;
199         }
200     }
201 
202     return 1;  // not find.
203 }
204 
205 /**
206  * @brief       Used for delete device information from conn_dev_list by peer mac_address
207  * @param[in]   adr_type       - peer address type.
208  * @param[in]   addr           - Pointer point to peer address.
209  * @return      0: success
210  *              1: no find
211  */
dev_char_info_delete_by_peer_mac_address(u8 adr_type,u8 * addr)212 int dev_char_info_delete_by_peer_mac_address(u8 adr_type, u8 *addr)
213 {
214     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
215         if (conn_dev_list[i].conn_state) {
216             int mac_match = 0;
217             if (IS_RESOLVABLE_PRIVATE_ADDR(adr_type, addr)) {
218             } else {
219                 if (adr_type == conn_dev_list[i].peer_adrType && (!memcmp(addr, conn_dev_list[i].peer_addr, 6))) {
220                     mac_match = 1;
221                 }
222             }
223             if (mac_match) {
224                 if (conn_dev_list[i].conn_role == LL_ROLE_MASTER) {  // master
225                     conn_master_num--;
226                 } else {  // slave
227                     conn_slave_num--;
228                 }
229 
230                 memset(&conn_dev_list[i], 0, sizeof(dev_char_info_t));
231 
232                 return 0;
233             }
234         }
235     }
236 
237     return 1;  // no find the peer device address.
238 }
239 
240 /**
241  * @brief       Get device information by connection handle.
242  * @param[in]   connhandle       - connection handle.
243  * @return      0: no find
244  *             !0: found
245  */
dev_char_info_search_by_connhandle(u16 connhandle)246 dev_char_info_t *dev_char_info_search_by_connhandle(u16 connhandle)
247 {
248     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
249         if (conn_dev_list[i].conn_handle == connhandle && conn_dev_list[i].conn_state) {
250             return &conn_dev_list[i];  // find the peer device
251         }
252     }
253 
254     return 0;  // no find the peer device
255 }
256 
257 /**
258  * @brief       Get device information by  peer device address.
259  * @param[in]   adr_type       - peer address type.
260  * @param[in]   addr           - Pointer point to peer address.
261  * @return      0: no find
262  *             !0: found
263  */
dev_char_info_search_by_peer_mac_address(u8 adr_type,u8 * addr)264 dev_char_info_t *dev_char_info_search_by_peer_mac_address(u8 adr_type, u8 *addr)
265 {
266     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
267         int mac_match = 0;
268         if (IS_RESOLVABLE_PRIVATE_ADDR(adr_type, addr)) {
269         } else {
270             if (adr_type == conn_dev_list[i].peer_adrType && (!memcmp(addr, conn_dev_list[i].peer_addr, 6))) {
271                 mac_match = 1;
272             }
273         }
274 
275         if (mac_match) {
276             return &conn_dev_list[i];  // find the peer device
277         }
278     }
279 
280     return 0;  // no find the peer device
281 }
282 
283 /**
284  * @brief       Get device information by connection handle.
285  * @param[in]   connhandle       - connection handle.
286  * @return      0: no find
287  *             !0: found
288  */
dev_char_info_is_connection_state_by_conn_handle(u16 connhandle)289 bool dev_char_info_is_connection_state_by_conn_handle(u16 connhandle)
290 {
291     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
292         if (conn_dev_list[i].conn_handle == connhandle && conn_dev_list[i].conn_state) {
293             return TRUE;
294         }
295     }
296 
297     return FALSE;
298 }
299 
300 /**
301  * @brief       Get ACL connection role by connection handle.
302  * @param[in]   connhandle       - connection handle.
303  * @return      0: LL_ROLE_MASTER
304  * 				1: LL_ROLE_SLAVE
305  * 				2: connection handle invalid
306  */
dev_char_get_conn_role_by_connhandle(u16 connhandle)307 int dev_char_get_conn_role_by_connhandle(u16 connhandle)
308 {
309     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
310         if (conn_dev_list[i].conn_handle == connhandle && conn_dev_list[i].conn_state) {
311             return conn_dev_list[i].conn_role;
312         }
313     }
314 
315     return 2;  // no connection match
316 }
317 
318 /**
319  * @brief       Get ACL connection index by connection handle.
320  * @param[in]   connhandle       - connection handle.
321  * @return      0xFF: 	  no connection index match
322  * 				others:   connection index
323  */
dev_char_get_conn_index_by_connhandle(u16 connhandle)324 int dev_char_get_conn_index_by_connhandle(u16 connhandle)
325 {
326     foreach (i, DEVICE_CHAR_INFO_MAX_NUM) {
327         if (conn_dev_list[i].conn_handle == connhandle && conn_dev_list[i].conn_state) {
328             return i;
329         }
330     }
331 
332     return INVALID_CONN_IDX;  // no connection index match
333 }
334