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 "custom_pair.h"
19
20 /**********************************************************************************
21 // proc user PAIR and UNPAIR
22 **********************************************************************************/
23
24 man_pair_t blm_manPair;
25
26 /* define pair slave max num,
27 if exceed this max num, two methods to process new slave pairing
28 method 1: overwrite the oldest one(telink demo use this method)
29 method 2: not allow pairing unless unfair happened */
30 #define USER_PAIR_SLAVE_MAX_NUM 4 // telink demo use max 4, you can change this value
31
32 typedef struct {
33 u8 bond_mark;
34 u8 adr_type;
35 u8 address[6];
36 } macAddr_t;
37
38 typedef struct {
39 u32 bond_flash_idx[USER_PAIR_SLAVE_MAX_NUM]; // mark paired slave mac address in flash
40 macAddr_t bond_device[USER_PAIR_SLAVE_MAX_NUM]; // macAddr_t alreay defined in ble stack
41 u8 curNum;
42 } user_salveMac_t;
43
44 /* flash erase strategy:
45 never erase flash when dongle is working, for flash sector erase takes too much time(20-100 ms)
46 this will lead to timing err
47 so we only erase flash at initiation, and with mark 0x00 for no use symbol
48 */
49
50 #define ADR_BOND_MARK 0x5A
51 #define ADR_ERASE_MARK 0x00
52 /* flash stored mac address struct:
53 every 8 bytes is a address area: first one is mark, second no use, third - eighth is 6 byte address
54 0 1 2 - 7
55 | mark | | mac_address |
56 mark = 0xff, current area is invalid, pair info end
57 mark = 0x01, current area is valid, load the following mac_address,
58 mark = 0x00, current area is invalid (previous valid address is erased)
59 */
60
61 int user_bond_slave_flash_cfg_idx; // new mac address stored flash idx
62
63 user_salveMac_t user_tbl_slaveMac; // slave mac bond table
64
65 /**
66 * @brief Delete slave MAC by index.
67 * !!! Note: only internal use
68 * @param index
69 * @return none.
70 */
user_tbl_slave_mac_delete_by_index(int index)71 void user_tbl_slave_mac_delete_by_index(int index) // remove the oldest adr in slave mac table
72 {
73 // erase the oldest with ERASE_MARK
74 u8 delete_mark = ADR_ERASE_MARK;
75 flash_write_page(FLASH_ADR_CUSTOM_PAIRING + user_tbl_slaveMac.bond_flash_idx[index], 1, &delete_mark);
76
77 for (int i = index; i < user_tbl_slaveMac.curNum - 1; i++) { // move data
78 user_tbl_slaveMac.bond_flash_idx[i] = user_tbl_slaveMac.bond_flash_idx[i + 1];
79 memcpy((u8 *)&user_tbl_slaveMac.bond_device[i], (u8 *)&user_tbl_slaveMac.bond_device[i + 1], 8);
80 }
81
82 user_tbl_slaveMac.curNum--;
83 }
84
85 /**
86 * @brief Store bonding info to flash.
87 * @param[in] adr_type address type
88 * @param[in] adr Pointer point to address buffer.
89 * @return none.
90 */
user_tbl_slave_mac_add(u8 adr_type,u8 * adr)91 int user_tbl_slave_mac_add(u8 adr_type, u8 *adr) // add new mac address to table
92 {
93 u8 add_new = 0;
94 if (user_tbl_slaveMac.curNum >= USER_PAIR_SLAVE_MAX_NUM) { // slave mac table is full
95 // slave mac max, telink use method 1: overwrite the oldest one
96 user_tbl_slave_mac_delete_by_index(0); // overwrite, delete index 0 (oldest) of table
97 add_new = 1; // add new
98 } else { // slave mac table not full
99 add_new = 1;
100 }
101
102 if (add_new) {
103 user_bond_slave_flash_cfg_idx += 8; // inc flash idx to get the new 8 bytes area
104
105 if (user_bond_slave_flash_cfg_idx >=
106 FLASH_CUSTOM_PAIRING_MAX_SIZE) { // pairing information exceed Flash sector 4K size
107 return 0; // add Fail
108 }
109
110 user_tbl_slaveMac.bond_device[user_tbl_slaveMac.curNum].bond_mark = ADR_BOND_MARK;
111 user_tbl_slaveMac.bond_device[user_tbl_slaveMac.curNum].adr_type = adr_type;
112 memcpy(user_tbl_slaveMac.bond_device[user_tbl_slaveMac.curNum].address, adr, 6);
113
114 flash_write_page(FLASH_ADR_CUSTOM_PAIRING + user_bond_slave_flash_cfg_idx, 8,
115 (u8 *)&user_tbl_slaveMac.bond_device[user_tbl_slaveMac.curNum]);
116
117 user_tbl_slaveMac.bond_flash_idx[user_tbl_slaveMac.curNum] = user_bond_slave_flash_cfg_idx; // mark flash idx
118 user_tbl_slaveMac.curNum++;
119
120 return 1; // add OK
121 }
122
123 return 0;
124 }
125
126 /**
127 * @brief search mac address in the bond slave mac table:
128 * when slave paired with dongle, add this addr to table
129 * re_poweron slave, dongle will search if this AdvA in slave adv pkt is in this table
130 * if in, it will connect slave directly
131 * this function must in ramcode
132 * @param[in] adr_type address type
133 * @param[in] adr Pointer point to address buffer.
134 * @return 0: invalid index
135 * others valid index
136 */
user_tbl_slave_mac_search(u8 adr_type,u8 * adr)137 int user_tbl_slave_mac_search(u8 adr_type, u8 *adr)
138 {
139 for (int i = 0; i < user_tbl_slaveMac.curNum; i++) {
140 if (user_tbl_slaveMac.bond_device[i].adr_type == adr_type &&
141 !memcmp(user_tbl_slaveMac.bond_device[i].address, adr, 6)) { // match
142 return (i + 1); // return index+1( 1 - USER_PAIR_SLAVE_MAX_NUM)
143 }
144 }
145
146 return 0;
147 }
148
149 /**
150 * @brief Delete bonding info.
151 * @param[in] adr_type address type
152 * @param[in] adr Pointer point to address buffer.
153 * @return 1: delete ok
154 * 0: no find
155 */
user_tbl_slave_mac_delete_by_adr(u8 adr_type,u8 * adr)156 int user_tbl_slave_mac_delete_by_adr(u8 adr_type, u8 *adr) // remove adr from slave mac table by adr
157 {
158 for (int i = 0; i < user_tbl_slaveMac.curNum; i++) {
159 if (user_tbl_slaveMac.bond_device[i].adr_type == adr_type &&
160 !memcmp(user_tbl_slaveMac.bond_device[i].address, adr, 6)) { // match
161 // erase the match adr
162 u8 delete_mark = ADR_ERASE_MARK;
163 flash_write_page(FLASH_ADR_CUSTOM_PAIRING + user_tbl_slaveMac.bond_flash_idx[i], 1, &delete_mark);
164
165 for (int j = i; j < user_tbl_slaveMac.curNum - 1; j++) { // move data
166 user_tbl_slaveMac.bond_flash_idx[j] = user_tbl_slaveMac.bond_flash_idx[j + 1];
167 memcpy((u8 *)&user_tbl_slaveMac.bond_device[j], (u8 *)&user_tbl_slaveMac.bond_device[j + 1], 8);
168 }
169
170 user_tbl_slaveMac.curNum--;
171 return 1; // delete OK
172 }
173 }
174
175 return 0;
176 }
177
178 /**
179 * @brief Delete all device bonding info.
180 * @param none.
181 * @return none.
182 */
user_tbl_slave_mac_delete_all(void)183 void user_tbl_slave_mac_delete_all(void) // delete all the adr in slave mac table
184 {
185 u8 delete_mark = ADR_ERASE_MARK;
186 for (int i = 0; i < user_tbl_slaveMac.curNum; i++) {
187 flash_write_page(FLASH_ADR_CUSTOM_PAIRING + user_tbl_slaveMac.bond_flash_idx[i], 1, &delete_mark);
188 memset((u8 *)&user_tbl_slaveMac.bond_device[i], 0, 8);
189 // user_tbl_slaveMac.bond_flash_idx[i] = 0; // do not concern
190 }
191
192 user_tbl_slaveMac.curNum = 0;
193 }
194
195 u8 adbg_flash_clean;
196 #define DBG_FLASH_CLEAN 0
197 // when flash stored too many addr, it may exceed a sector max(4096), so we must clean this sector
198 // and rewrite the valid addr at the beginning of the sector(0x11000)
199
200 /**
201 * @brief clean pair flash
202 * @param none.
203 * @return none.
204 */
user_bond_slave_flash_clean(void)205 void user_bond_slave_flash_clean(void)
206 {
207 #if DBG_FLASH_CLEAN
208 if (user_bond_slave_flash_cfg_idx < 8 * 8) // debug, max 8 area, then clean flash
209 #else
210 if (user_bond_slave_flash_cfg_idx <
211 (FLASH_CUSTOM_PAIRING_MAX_SIZE >> 1)) // max 2048/8 = 256,rest available sector is big enough, no need clean
212 #endif
213 {
214 return;
215 }
216
217 adbg_flash_clean = 1;
218
219 flash_erase_sector(FLASH_ADR_CUSTOM_PAIRING);
220
221 user_bond_slave_flash_cfg_idx = -8; // init value for no bond slave mac
222
223 // rewrite bond table at the beginning of 0x11000
224 for (int i = 0; i < user_tbl_slaveMac.curNum; i++) {
225 user_bond_slave_flash_cfg_idx += 8; // inc flash idx to get the new 8 bytes area
226 flash_write_page(FLASH_ADR_CUSTOM_PAIRING + user_bond_slave_flash_cfg_idx, 8,
227 (u8 *)&user_tbl_slaveMac.bond_device[i]);
228
229 user_tbl_slaveMac.bond_flash_idx[i] = user_bond_slave_flash_cfg_idx; // update flash idx
230 }
231 }
232
233 /**
234 * @brief initialize pair flash.
235 * @param none.
236 * @return none.
237 */
user_master_host_pairing_flash_init(void)238 void user_master_host_pairing_flash_init(void)
239 {
240 u8 flag;
241 for (user_bond_slave_flash_cfg_idx = 0; user_bond_slave_flash_cfg_idx < 4096;
242 user_bond_slave_flash_cfg_idx +=
243 8) { // traversing 8 bytes area in sector 0x11000 to find all the valid slave mac adr
244 flash_read_page(FLASH_ADR_CUSTOM_PAIRING + user_bond_slave_flash_cfg_idx, 1, &flag);
245 if (flag == ADR_BOND_MARK) { // valid adr
246 if (user_tbl_slaveMac.curNum < USER_PAIR_SLAVE_MAX_NUM) {
247 user_tbl_slaveMac.bond_flash_idx[user_tbl_slaveMac.curNum] = user_bond_slave_flash_cfg_idx;
248 flash_read_page(FLASH_ADR_CUSTOM_PAIRING + user_bond_slave_flash_cfg_idx, 8,
249 (u8 *)&user_tbl_slaveMac.bond_device[user_tbl_slaveMac.curNum]);
250 user_tbl_slaveMac.curNum++;
251 } else { // slave mac in flash more than max, we think it's code bug
252 irq_disable();
253 while (1) {
254 }
255 }
256 } else if (flag == 0xff) {
257 // end
258 break;
259 }
260 }
261
262 user_bond_slave_flash_cfg_idx -= 8;
263 // back to the newest addr 8 bytes area flash ixd(if no valid addr, will be -8)
264
265 user_bond_slave_flash_clean();
266 }
267
268 /**
269 * @brief Pair management initialization for master.
270 * @param none.
271 * @return none.
272 */
user_master_host_pairing_management_init(void)273 void user_master_host_pairing_management_init(void)
274 {
275 user_master_host_pairing_flash_init();
276 }
277