• 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 "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