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