1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2018 Realtek Corporation
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
19 #define LOG_TAG "bt_hwcfg_usb"
20 #define RTKBT_RELEASE_NAME "20190717_BT_ANDROID_9.0"
21
22 #include <utils/Log.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <signal.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <dirent.h>
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <endian.h>
34 #include <byteswap.h>
35 #include <unistd.h>
36 #include "bt_hci_bdroid.h"
37 #include "bt_vendor_rtk.h"
38 #include "userial.h"
39 #include "userial_vendor.h"
40 #include "upio.h"
41
42 #include "bt_vendor_lib.h"
43 #include "hardware.h"
44 #include "rtk_common.h"
45
46 /******************************************************************************
47 ** Constants & Macros
48 ******************************************************************************/
49 void hw_usb_config_cback(HC_BT_HDR *p_evt_buf);
50
51 #define EXTRA_CONFIG_FILE "/vendor/etc/bluetooth/rtk_btconfig.txt"
52 static struct rtk_bt_vendor_config_entry *extra_extry;
53 static struct rtk_bt_vendor_config_entry *extra_entry_inx = NULL;
54
55 #define BT_VENDOR_CFG_TIMEDELAY_ 40
56
57 typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
58
OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)59 static timer_t OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)
60 {
61 struct sigevent sigev;
62 timer_t timerid;
63
64 (void)memset_s(&sigev, sizeof(struct sigevent), 0, sizeof(struct sigevent));
65 // Create the POSIX timer to generate signo
66 sigev.sigev_notify = SIGEV_THREAD;
67 sigev.sigev_notify_function = timer_callback;
68 sigev.sigev_value.sival_ptr = &timerid;
69
70 // Create the Timer using timer_create signal
71
72 if (timer_create(CLOCK_REALTIME, &sigev, &timerid) == 0) {
73 return timerid;
74 } else {
75 HILOGE("timer_create error!");
76 return (timer_t)-1;
77 }
78 }
79
OsFreeTimer(timer_t timerid)80 static int OsFreeTimer(timer_t timerid)
81 {
82 int ret = 0;
83 ret = timer_delete(timerid);
84 if (ret != 0) {
85 HILOGE("timer_delete fail with errno(%d)", errno);
86 }
87
88 return ret;
89 }
90
OsStartTimer(timer_t timerid,int msec,int mode)91 static int OsStartTimer(timer_t timerid, int msec, int mode)
92 {
93 struct itimerspec itval;
94
95 #define MSEC_1000 1000
96 itval.it_value.tv_sec = msec / MSEC_1000;
97 itval.it_value.tv_nsec = (long)(msec % MSEC_1000) * (1000000L);
98
99 if (mode == 1) {
100 itval.it_interval.tv_sec = itval.it_value.tv_sec;
101 itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
102 } else {
103 itval.it_interval.tv_sec = 0;
104 itval.it_interval.tv_nsec = 0;
105 }
106
107 // Set the Timer when to expire through timer_settime
108
109 if (timer_settime(timerid, 0, &itval, NULL) != 0) {
110 HILOGE("time_settime error!");
111 return -1;
112 }
113
114 return 0;
115 }
116
117 static timer_t localtimer = 0;
local_timer_handler(union sigval sigev_value)118 static void local_timer_handler(union sigval sigev_value)
119 {
120 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
121 OsFreeTimer(localtimer);
122 }
123
start_fwcfg_cbtimer(void)124 static void start_fwcfg_cbtimer(void)
125 {
126 if (localtimer == 0) {
127 localtimer = OsAllocateTimer(local_timer_handler);
128 }
129 OsStartTimer(localtimer, BT_VENDOR_CFG_TIMEDELAY_, 0);
130 }
131
132 /******************************************************************************
133 ** Static variables
134 ******************************************************************************/
135
136 typedef struct {
137 uint16_t vid;
138 uint16_t pid;
139 uint16_t lmp_sub_default;
140 uint16_t lmp_sub;
141 uint16_t eversion;
142 char *mp_patch_name;
143 char *patch_name;
144 char *config_name;
145 uint8_t *fw_cache;
146 int fw_len;
147 uint16_t mac_offset;
148 uint32_t max_patch_size;
149 } usb_patch_info;
150
151 static usb_patch_info usb_fw_patch_table[] = {
152 /* { vid, pid, lmp_sub_default, lmp_sub, everion, mp_fw_name,
153 fw_name, config_name, fw_cache, fw_len, mac_offset } */
154 {0x0BDA, 0xD723, 0x8723, 0, 0, "mp_rtl8723d_fw", "rtl8723d_fw", "rtl8723d_config", NULL, 0,
155 CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8723DU */
156 /* todo: RTL8703CU */
157
158 /* NOTE: must append patch entries above the null entry */
159 {0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0}};
160
161 uint16_t usb_project_id[] = {ROM_LMP_8723a, ROM_LMP_8723b, ROM_LMP_8821a, ROM_LMP_8761a, ROM_LMP_8703a, ROM_LMP_8763a,
162 ROM_LMP_8703b, ROM_LMP_8723c, ROM_LMP_8822b, ROM_LMP_8723d, ROM_LMP_8821c, ROM_LMP_NONE,
163 ROM_LMP_NONE, ROM_LMP_8822c, ROM_LMP_8761b, ROM_LMP_NONE};
164 // signature: realtech
165 static const uint8_t RTK_EPATCH_SIGNATURE[8] = {0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x63, 0x68};
166 // Extension Section IGNATURE:0x77FD0451
167 static const uint8_t EXTENSION_SECTION_SIGNATURE[4] = {0x51, 0x04, 0xFD, 0x77};
168
usb_line_process(char * buf,unsigned short * offset,int * t)169 static void usb_line_process(char *buf, unsigned short *offset, int *t)
170 {
171 char *head = buf;
172 char *ptr = buf;
173 char *argv[32];
174 int argc = 0;
175 unsigned char len = 0;
176 int i = 0;
177 static int alt_size = 0;
178
179 if (buf[0] == '\0' || buf[0] == '#' || buf[0] == '[') {
180 return;
181 }
182 if (alt_size > MAX_ALT_CONFIG_SIZE - 4L) {
183 HILOGW("Extra Config file is too large");
184 return;
185 }
186 if (extra_entry_inx == NULL) {
187 extra_entry_inx = extra_extry;
188 }
189 HILOGI("line_process:%s", buf);
190 while ((ptr = strsep(&head, ", \t")) != NULL) {
191 if (!ptr[0]) {
192 continue;
193 }
194 argv[argc++] = ptr;
195 if (argc >= 32L) {
196 HILOGW("Config item is too long");
197 break;
198 }
199 }
200 if (argc < 4L) {
201 HILOGE("Invalid Config item, ignore");
202 return;
203 }
204 offset[(*t)] = (unsigned short)((strtoul(argv[0], NULL, 16L)) |
205 (strtoul(argv[1], NULL, 16L) << 8L));
206 HILOGI("Extra Config offset %04x", offset[(*t)]);
207 extra_entry_inx->offset = offset[(*t)];
208 (*t)++;
209 len = (unsigned char)strtoul(argv[2L], NULL, 16L);
210 if (len != (unsigned char)(argc - 3L)) {
211 HILOGE("Extra Config item len %d is not match, we assume the actual len is %ld", len, (argc - 3L));
212 len = argc - 3L;
213 }
214 extra_entry_inx->entry_len = len;
215
216 alt_size += len + sizeof(struct rtk_bt_vendor_config_entry);
217 if (alt_size > MAX_ALT_CONFIG_SIZE) {
218 HILOGW("Extra Config file is too large");
219 extra_entry_inx->offset = 0;
220 extra_entry_inx->entry_len = 0;
221 alt_size -= (len + sizeof(struct rtk_bt_vendor_config_entry));
222 return;
223 }
224 for (i = 0; i < len; i++) {
225 extra_entry_inx->entry_data[i] = (uint8_t)strtoul(argv[3L + i], NULL, 16L);
226 HILOGI("data[%d]:%02x", i, extra_entry_inx->entry_data[i]);
227 }
228 extra_entry_inx = (struct rtk_bt_vendor_config_entry *)
229 ((uint8_t *)extra_entry_inx + len + sizeof(struct rtk_bt_vendor_config_entry));
230 }
231
usb_parse_extra_config(const char * path,usb_patch_info * patch_entry,unsigned short * offset,int * t)232 static void usb_parse_extra_config(const char *path, usb_patch_info *patch_entry, unsigned short *offset, int *t)
233 {
234 int fd, ret;
235 unsigned char buf[1024];
236
237 fd = open(path, O_RDONLY);
238 if (fd == -1) {
239 HILOGI("Couldn't open extra config %s, err:%s", path, strerror(errno));
240 return;
241 }
242
243 ret = read(fd, buf, sizeof(buf));
244 if (ret == -1) {
245 HILOGE("Couldn't read %s, err:%s", path, strerror(errno));
246 close(fd);
247 return;
248 } else if (ret == 0) {
249 HILOGE("%s is empty", path);
250 close(fd);
251 return;
252 }
253
254 #define USB_PARSE_EXTRA_CONFIG_RET_1022 1022
255 if (ret > USB_PARSE_EXTRA_CONFIG_RET_1022) {
256 HILOGE("Extra config file is too big");
257 close(fd);
258 return;
259 }
260 buf[ret++] = '\n';
261 buf[ret++] = '\0';
262 close(fd);
263 char *head = (void *)buf;
264 char *ptr = (void *)buf;
265 ptr = strsep(&head, "\n\r");
266 if (strncmp(ptr, patch_entry->config_name, strlen(ptr))) {
267 HILOGW("Extra config file not set for %s, ignore", patch_entry->config_name);
268 return;
269 }
270 while ((ptr = strsep(&head, "\n\r")) != NULL) {
271 if (!ptr[0]) {
272 continue;
273 }
274 usb_line_process(ptr, offset, t);
275 }
276 }
277
278 // (patch_info *patch_entry, unsigned short *offset, int max_group_cnt)
getUsbAltSettings(usb_patch_info * patch_entry,unsigned short * offset)279 static inline int getUsbAltSettings(usb_patch_info *patch_entry, unsigned short *offset)
280 {
281 int n = 0;
282 if (patch_entry) {
283 offset[n++] = patch_entry->mac_offset;
284 } else {
285 return n;
286 }
287 /*
288 //sample code, add special settings
289
290 offset[n++] = 0x15B;
291 */
292 if (extra_extry) {
293 usb_parse_extra_config(EXTRA_CONFIG_FILE, patch_entry, offset, &n);
294 }
295
296 return n;
297 }
298
299 #define USB_VAL_5 5
300 #define USB_VAL_4 4
301 #define USB_VAL_3 3
302 #define USB_VAL_2 2
303 #define USB_VAL_1 1
304 #define USB_VAL_0 0
305
getUsbAltSettingVal(usb_patch_info * patch_entry,unsigned short offset,unsigned char * val)306 static inline int getUsbAltSettingVal(usb_patch_info *patch_entry, unsigned short offset, unsigned char *val)
307 {
308 int res = 0;
309
310 int i = 0;
311 struct rtk_bt_vendor_config_entry *ptr = extra_extry;
312
313 while (ptr->offset) {
314 if (ptr->offset == offset) {
315 if (offset != patch_entry->mac_offset) {
316 (void)memcpy_s(val, ptr->entry_len, ptr->entry_data, ptr->entry_len);
317 res = ptr->entry_len;
318 HILOGI("Get Extra offset:%04x, val:", offset);
319 for (i = 0; i < ptr->entry_len; i++) {
320 HILOGI("%02x", ptr->entry_data[i]);
321 }
322 }
323 break;
324 }
325 ptr = (struct rtk_bt_vendor_config_entry *)((uint8_t *)ptr + ptr->entry_len +
326 sizeof(struct rtk_bt_vendor_config_entry));
327 }
328
329 /* switch(offset)
330 {
331 //sample code, add special settings
332 case 0x15B:
333 val[0] = 0x0B;
334 val[1] = 0x0B;
335 val[2] = 0x0B;
336 val[3] = 0x0B;
337 res = 4;
338 break;
339
340 default:
341 res = 0;
342 break;
343 }
344 */
345 if ((patch_entry) && (offset == patch_entry->mac_offset) && (res == 0)) {
346 if (getmacaddr(val) == 0) {
347 HILOGI("MAC: %02x:%02x:%02x:%02x:%02x:%02x", val[USB_VAL_5], val[USB_VAL_4], val[USB_VAL_3], val[USB_VAL_2],
348 val[USB_VAL_1], val[USB_VAL_0]);
349 res = 6L;
350 }
351 }
352 return res;
353 }
354
355 #define USB_CONFIG_BUF_PTR_15 15
356 #define USB_CONFIG_BUF_PTR_14 14
357 #define USB_CONFIG_BUF_PTR_13 13
358 #define USB_CONFIG_BUF_PTR_12 12
359 #define USB_CONFIG_BUF_PTR_11 11
360 #define USB_CONFIG_BUF_PTR_10 10
361 #define USB_CONFIG_BUF_PTR_9 9
362 #define USB_CONFIG_BUF_PTR_8 8
363 #define USB_CONFIG_BUF_PTR_7 7
364 #define USB_CONFIG_BUF_PTR_6 6
365 #define USB_CONFIG_BUF_PTR_5 5
366 #define USB_CONFIG_BUF_PTR_4 4
367 #define USB_CONFIG_BUF_PTR_3 3
368 #define USB_CONFIG_BUF_PTR_2 2
369 #define USB_CONFIG_BUF_PTR_1 1
370
rtk_usb_update_altsettings(usb_patch_info * patch_entry,unsigned char * config_buf_ptr,size_t * config_len_ptr)371 static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned char *config_buf_ptr,
372 size_t *config_len_ptr)
373 {
374 unsigned short offset[256], data_len;
375 unsigned char val[256];
376
377 struct rtk_bt_vendor_config *config = (struct rtk_bt_vendor_config *)config_buf_ptr;
378 struct rtk_bt_vendor_config_entry *entry = config->entry;
379 size_t config_len = *config_len_ptr;
380 unsigned int i = 0;
381 int count = 0, temp = 0, j;
382
383 if ((extra_extry = (struct rtk_bt_vendor_config_entry *)malloc(MAX_ALT_CONFIG_SIZE)) == NULL) {
384 HILOGE("malloc buffer for extra_extry failed");
385 } else {
386 (void)memset_s(extra_extry, MAX_ALT_CONFIG_SIZE, 0, MAX_ALT_CONFIG_SIZE);
387 }
388
389 HILOGI("ORG Config len=%08zx:\n", config_len);
390 for (i = 0; i <= config_len; i += 0x10) {
391 HILOGI("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
392 config_buf_ptr[i], config_buf_ptr[i + USB_CONFIG_BUF_PTR_1], config_buf_ptr[i + USB_CONFIG_BUF_PTR_2],
393 config_buf_ptr[i + USB_CONFIG_BUF_PTR_3], config_buf_ptr[i + USB_CONFIG_BUF_PTR_4],
394 config_buf_ptr[i + USB_CONFIG_BUF_PTR_5], config_buf_ptr[i + USB_CONFIG_BUF_PTR_6],
395 config_buf_ptr[i + USB_CONFIG_BUF_PTR_7], config_buf_ptr[i + USB_CONFIG_BUF_PTR_8],
396 config_buf_ptr[i + USB_CONFIG_BUF_PTR_9], config_buf_ptr[i + USB_CONFIG_BUF_PTR_10],
397 config_buf_ptr[i + USB_CONFIG_BUF_PTR_11], config_buf_ptr[i + USB_CONFIG_BUF_PTR_12],
398 config_buf_ptr[i + USB_CONFIG_BUF_PTR_13], config_buf_ptr[i + USB_CONFIG_BUF_PTR_14],
399 config_buf_ptr[i + USB_CONFIG_BUF_PTR_15]);
400 }
401
402 (void)memset_s(offset, sizeof(offset), 0, sizeof(offset));
403 (void)memset_s(val, sizeof(val), 0, sizeof(val));
404 data_len = le16_to_cpu(config->data_len);
405
406 count = getUsbAltSettings(patch_entry, offset);
407 if (count <= 0) {
408 HILOGI("rtk_update_altsettings: No AltSettings");
409 return;
410 } else {
411 HILOGI("rtk_update_altsettings: %d AltSettings", count);
412 }
413
414 if (data_len != config_len - sizeof(struct rtk_bt_vendor_config)) {
415 HILOGE("rtk_update_altsettings: config len(%x) is not right(%lx)", data_len,
416 (unsigned long)(config_len - sizeof(struct rtk_bt_vendor_config)));
417 return;
418 }
419
420 for (i = 0; i < data_len;) {
421 for (j = 0; j < count; j++) {
422 if (le16_to_cpu(entry->offset) == offset[j]) {
423 if (offset[j] == patch_entry->mac_offset) {
424 offset[j] = 0;
425 } else {
426 struct rtk_bt_vendor_config_entry *t = extra_extry;
427 while (t->offset) {
428 if (t->offset == le16_to_cpu(entry->offset)) {
429 if (t->entry_len == entry->entry_len) {
430 offset[j] = 0;
431 }
432 break;
433 }
434 t = (struct rtk_bt_vendor_config_entry *)((uint8_t *)t + t->entry_len +
435 sizeof(struct rtk_bt_vendor_config_entry));
436 }
437 }
438 }
439 }
440 if (getUsbAltSettingVal(patch_entry, le16_to_cpu(entry->offset), val) == entry->entry_len) {
441 HILOGI("rtk_update_altsettings: replace %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
442 (void)memcpy_s(entry->entry_data, entry->entry_len, val, entry->entry_len);
443 }
444 temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
445 i += temp;
446 entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);
447 }
448
449 for (j = 0; j < count; j++) {
450 if (offset[j] == 0) {
451 continue;
452 }
453 entry->entry_len = getUsbAltSettingVal(patch_entry, offset[j], val);
454 if (entry->entry_len <= 0) {
455 continue;
456 }
457 entry->offset = cpu_to_le16(offset[j]);
458 (void)memcpy_s(entry->entry_data, entry->entry_len, val, entry->entry_len);
459 HILOGI("rtk_update_altsettings: add %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
460 temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
461 i += temp;
462 entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);
463 }
464 config->data_len = cpu_to_le16(i);
465 *config_len_ptr = i + sizeof(struct rtk_bt_vendor_config);
466
467 if (extra_extry) {
468 free(extra_extry);
469 extra_extry = NULL;
470 extra_entry_inx = NULL;
471 }
472
473 HILOGI("NEW Config len=%08zx:\n", *config_len_ptr);
474 for (i = 0; i <= (*config_len_ptr); i += 0x10) {
475 HILOGI("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
476 config_buf_ptr[i], config_buf_ptr[i + USB_CONFIG_BUF_PTR_1], config_buf_ptr[i + USB_CONFIG_BUF_PTR_2],
477 config_buf_ptr[i + USB_CONFIG_BUF_PTR_3], config_buf_ptr[i + USB_CONFIG_BUF_PTR_4],
478 config_buf_ptr[i + USB_CONFIG_BUF_PTR_5], config_buf_ptr[i + USB_CONFIG_BUF_PTR_6],
479 config_buf_ptr[i + USB_CONFIG_BUF_PTR_7], config_buf_ptr[i + USB_CONFIG_BUF_PTR_8],
480 config_buf_ptr[i + USB_CONFIG_BUF_PTR_9], config_buf_ptr[i + USB_CONFIG_BUF_PTR_10],
481 config_buf_ptr[i + USB_CONFIG_BUF_PTR_11], config_buf_ptr[i + USB_CONFIG_BUF_PTR_12],
482 config_buf_ptr[i + USB_CONFIG_BUF_PTR_13], config_buf_ptr[i + USB_CONFIG_BUF_PTR_14],
483 config_buf_ptr[i + USB_CONFIG_BUF_PTR_15]);
484 }
485 return;
486 }
487
rtk_usb_parse_config_file(unsigned char ** config_buf,size_t * filelen,uint8_t bt_addr[6],uint16_t mac_offset)488 static void rtk_usb_parse_config_file(unsigned char **config_buf, size_t *filelen, uint8_t bt_addr[6],
489 uint16_t mac_offset)
490 {
491 struct rtk_bt_vendor_config *config = (struct rtk_bt_vendor_config *)*config_buf;
492 uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
493 struct rtk_bt_vendor_config_entry *entry = config->entry;
494 unsigned int i = 0;
495 uint8_t heartbeat_buf = 0;
496 uint8_t *p;
497
498 HILOGD("bt_addr = %x", bt_addr[0]);
499 if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC) {
500 HILOGE("config signature magic number(0x%x) is not set to RTK_VENDOR_CONFIG_MAGIC", config->signature);
501 return;
502 }
503
504 if (config_len != *filelen - sizeof(struct rtk_bt_vendor_config)) {
505 HILOGE("config len(0x%x) is not right(0x%zx)", config_len, *filelen - sizeof(struct rtk_bt_vendor_config));
506 return;
507 }
508
509 hw_cfg_cb.heartbeat = 0;
510 for (i = 0; i < config_len;) {
511 switch (le16_to_cpu(entry->offset)) {
512 case 0x017a: {
513 if (mac_offset == CONFIG_MAC_OFFSET_GEN_1_2) {
514 p = (uint8_t *)entry->entry_data;
515 STREAM_TO_UINT8(heartbeat_buf, p);
516 if ((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10)) {
517 hw_cfg_cb.heartbeat = 1;
518 } else {
519 hw_cfg_cb.heartbeat = 0;
520 }
521
522 HILOGI("config 0x017a heartbeat = %d", hw_cfg_cb.heartbeat);
523 }
524 break;
525 }
526 case 0x01be: {
527 if (mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS || mac_offset == CONFIG_MAC_OFFSET_GEN_4PLUS) {
528 p = (uint8_t *)entry->entry_data;
529 STREAM_TO_UINT8(heartbeat_buf, p);
530 if ((heartbeat_buf & 0x02) && (heartbeat_buf & 0x10)) {
531 hw_cfg_cb.heartbeat = 1;
532 } else {
533 hw_cfg_cb.heartbeat = 0;
534 }
535
536 HILOGI("config 0x01be heartbeat = %d", hw_cfg_cb.heartbeat);
537 }
538 break;
539 }
540 default:
541 HILOGI("config offset(0x%x),length(0x%x)", entry->offset, entry->entry_len);
542 break;
543 }
544 temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
545 i += temp;
546 entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);
547 }
548
549 return;
550 }
551
rtk_usb_get_bt_config(unsigned char ** config_buf,char * config_file_short_name,uint16_t mac_offset)552 static uint32_t rtk_usb_get_bt_config(unsigned char **config_buf, char *config_file_short_name, uint16_t mac_offset)
553 {
554 char bt_config_file_name[PATH_MAX] = {0};
555 struct stat st;
556 size_t filelen;
557 int fd;
558 uint8_t *p_vnd_local_bd_addr = get_vnd_local_bd_addr();
559
560 (void)sprintf_s(bt_config_file_name, sizeof(bt_config_file_name), BT_CONFIG_DIRECTORY, config_file_short_name);
561 HILOGI("BT config file: %s", bt_config_file_name);
562
563 if (stat(bt_config_file_name, &st) < 0) {
564 HILOGE("can't access bt config file:%s, errno:%d\n", bt_config_file_name, errno);
565 return 0;
566 }
567
568 filelen = st.st_size;
569 if (filelen > MAX_ORG_CONFIG_SIZE) {
570 HILOGE("bt config file is too large(>0x%04x)", MAX_ORG_CONFIG_SIZE);
571 return 0;
572 }
573
574 if ((fd = open(bt_config_file_name, O_RDONLY)) < 0) {
575 HILOGE("Can't open bt config file");
576 return 0;
577 }
578
579 if ((*config_buf = malloc(MAX_ORG_CONFIG_SIZE + MAX_ALT_CONFIG_SIZE)) == NULL) {
580 HILOGE("malloc buffer for config file fail(0x%zx)\n", filelen);
581 close(fd);
582 return 0;
583 }
584
585 if (read(fd, *config_buf, filelen) < (ssize_t)filelen) {
586 HILOGE("Can't load bt config file");
587 free(*config_buf);
588 close(fd);
589 return 0;
590 }
591
592 rtk_usb_parse_config_file(config_buf, &filelen, p_vnd_local_bd_addr, mac_offset);
593
594 close(fd);
595 return filelen;
596 }
597
rtk_usb_get_fw_table_entry(uint16_t vid,uint16_t pid)598 static usb_patch_info *rtk_usb_get_fw_table_entry(uint16_t vid, uint16_t pid)
599 {
600 usb_patch_info *patch_entry = usb_fw_patch_table;
601
602 uint32_t entry_size = sizeof(usb_fw_patch_table) / sizeof(usb_fw_patch_table[0]);
603 uint32_t i;
604
605 for (i = 0; i < entry_size; i++, patch_entry++) {
606 if ((vid == patch_entry->vid) && (pid == patch_entry->pid)) {
607 break;
608 }
609 }
610
611 if (i == entry_size) {
612 HILOGE("%s: No fw table entry found", __func__);
613 return NULL;
614 }
615
616 return patch_entry;
617 }
618
619 #define USB_MEMCPY_8 8
620 #define USB_MEMCPY_4 4
621 #define USB_MEMCPY_S_12 12
622 #define USB_MEMCPY_S_8 8
623 #define USB_MEMCPY_S_4 4
624 #define USB_LEN_5 5
625 #define USB_ENTRY_16 16
626 #define USB_ENTRY_27 27
627 #define USB_ENTRY_10000 10000
628
rtk_usb_get_bt_final_patch(bt_hw_cfg_cb_t * cfg_cb)629 static void rtk_usb_get_bt_final_patch(bt_hw_cfg_cb_t *cfg_cb)
630 {
631 uint8_t proj_id = 0;
632 struct rtk_epatch_entry *entry = NULL;
633 struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
634
635 if (cfg_cb->lmp_subversion == LMPSUBVERSION_8723a) {
636 if (memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, USB_MEMCPY_8) == 0) {
637 HILOGE("8723as check signature error!");
638 cfg_cb->dl_fw_flag = 0;
639 } else {
640 cfg_cb->total_len = cfg_cb->fw_len + cfg_cb->config_len;
641 if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len))) {
642 HILOGE("can't alloc memory for fw&config, errno:%d", errno);
643 cfg_cb->dl_fw_flag = 0;
644 if (cfg_cb->fw_len > 0) {
645 free(cfg_cb->fw_buf);
646 cfg_cb->fw_len = 0;
647 }
648
649 if (cfg_cb->config_len > 0) {
650 free(cfg_cb->config_buf);
651 cfg_cb->config_len = 0;
652 }
653
654 if (entry) {
655 free(entry);
656 }
657 return;
658 } else {
659 HILOGI("8723as, fw copy direct");
660 (void)memcpy_s(cfg_cb->total_buf, cfg_cb->fw_len, cfg_cb->fw_buf, cfg_cb->fw_len);
661 (void)memcpy_s(cfg_cb->total_buf + cfg_cb->fw_len,
662 cfg_cb->config_len, cfg_cb->config_buf, cfg_cb->config_len);
663 cfg_cb->dl_fw_flag = 1;
664 if (cfg_cb->fw_len > 0) {
665 free(cfg_cb->fw_buf);
666 cfg_cb->fw_len = 0;
667 }
668
669 if (cfg_cb->config_len > 0) {
670 free(cfg_cb->config_buf);
671 cfg_cb->config_len = 0;
672 }
673
674 if (entry) {
675 free(entry);
676 }
677 return;
678 }
679 }
680 }
681
682 if (memcmp(cfg_cb->fw_buf, RTK_EPATCH_SIGNATURE, USB_MEMCPY_8)) {
683 HILOGE("check signature error");
684 cfg_cb->dl_fw_flag = 0;
685 if (cfg_cb->fw_len > 0) {
686 free(cfg_cb->fw_buf);
687 cfg_cb->fw_len = 0;
688 }
689
690 if (cfg_cb->config_len > 0) {
691 free(cfg_cb->config_buf);
692 cfg_cb->config_len = 0;
693 }
694
695 if (entry) {
696 free(entry);
697 }
698 return;
699 }
700
701 /* check the extension section signature */
702 if (memcmp(cfg_cb->fw_buf + cfg_cb->fw_len - USB_MEMCPY_8, EXTENSION_SECTION_SIGNATURE, USB_MEMCPY_8)) {
703 HILOGE("check extension section signature error");
704 cfg_cb->dl_fw_flag = 0;
705 if (cfg_cb->fw_len > 0) {
706 free(cfg_cb->fw_buf);
707 cfg_cb->fw_len = 0;
708 }
709
710 if (cfg_cb->config_len > 0) {
711 free(cfg_cb->config_buf);
712 cfg_cb->config_len = 0;
713 }
714
715 if (entry) {
716 free(entry);
717 }
718 return;
719 }
720
721 proj_id = rtk_get_fw_project_id(cfg_cb->fw_buf + cfg_cb->fw_len - USB_LEN_5);
722 if (usb_project_id[proj_id] != hw_cfg_cb.lmp_subversion_default) {
723 HILOGE("usb_project_id is 0x%08x, fw project_id is %d, does not match!!!", usb_project_id[proj_id],
724 hw_cfg_cb.lmp_subversion);
725 cfg_cb->dl_fw_flag = 0;
726 if (cfg_cb->fw_len > 0) {
727 free(cfg_cb->fw_buf);
728 cfg_cb->fw_len = 0;
729 }
730
731 if (cfg_cb->config_len > 0) {
732 free(cfg_cb->config_buf);
733 cfg_cb->config_len = 0;
734 }
735
736 if (entry) {
737 free(entry);
738 }
739 return;
740 }
741
742 entry = rtk_get_patch_entry(cfg_cb);
743 if (entry) {
744 cfg_cb->total_len = entry->patch_length + cfg_cb->config_len;
745 } else {
746 cfg_cb->dl_fw_flag = 0;
747 if (cfg_cb->fw_len > 0) {
748 free(cfg_cb->fw_buf);
749 cfg_cb->fw_len = 0;
750 }
751
752 if (cfg_cb->config_len > 0) {
753 free(cfg_cb->config_buf);
754 cfg_cb->config_len = 0;
755 }
756
757 if (entry) {
758 free(entry);
759 }
760 return;
761 }
762
763 HILOGI("total_len = 0x%x", cfg_cb->total_len);
764
765 if (!(cfg_cb->total_buf = malloc(cfg_cb->total_len))) {
766 HILOGE("Can't alloc memory for multi fw&config, errno:%d", errno);
767 cfg_cb->dl_fw_flag = 0;
768 if (cfg_cb->fw_len > 0) {
769 free(cfg_cb->fw_buf);
770 cfg_cb->fw_len = 0;
771 }
772
773 if (cfg_cb->config_len > 0) {
774 free(cfg_cb->config_buf);
775 cfg_cb->config_len = 0;
776 }
777
778 if (entry) {
779 free(entry);
780 }
781 return;
782 } else {
783 (void)memcpy_s(cfg_cb->total_buf,
784 entry->patch_length, cfg_cb->fw_buf + entry->patch_offset, entry->patch_length);
785 (void)memcpy_s(cfg_cb->total_buf + entry->patch_length - USB_MEMCPY_S_4,
786 sizeof(cfg_cb->total_buf) + entry->patch_length, &patch->fw_version, USB_MEMCPY_S_4);
787 (void)memcpy_s(&entry->svn_version,
788 entry->patch_length, cfg_cb->total_buf + entry->patch_length - USB_MEMCPY_S_8, USB_MEMCPY_S_4);
789 (void)memcpy_s(&entry->coex_version,
790 entry->patch_length, cfg_cb->total_buf + entry->patch_length - USB_MEMCPY_S_12, USB_MEMCPY_S_4);
791
792 HILOGI("BTCOEX:20%06d-%04x svn_version:%d lmp_subversion:0x%x hci_version:0x%x hci_revision:0x%x chip_type:%d "
793 "Cut:%d libbt-vendor_uart version:%s, patch->fw_version = %x\n",
794 ((entry->coex_version >> USB_ENTRY_16) & 0x7ff) +
795 ((entry->coex_version >> USB_ENTRY_27) * USB_ENTRY_10000),
796 (entry->coex_version & 0xffff), entry->svn_version, cfg_cb->lmp_subversion, cfg_cb->hci_version,
797 cfg_cb->hci_revision, cfg_cb->chip_type, cfg_cb->eversion + 1, RTK_VERSION, patch->fw_version);
798 }
799
800 if (cfg_cb->config_len) {
801 (void)memcpy_s(cfg_cb->total_buf + entry->patch_length,
802 cfg_cb->config_len, cfg_cb->config_buf, cfg_cb->config_len);
803 }
804
805 cfg_cb->dl_fw_flag = 1;
806 HILOGI("Fw:%s exists, config file:%s exists", (cfg_cb->fw_len > 0) ? "" : "not",
807 (cfg_cb->config_len > 0) ? "" : "not");
808 }
809
usb_hci_download_patch_h4(HC_BT_HDR * p_buf,int index,uint8_t * data,int len)810 static int usb_hci_download_patch_h4(HC_BT_HDR *p_buf, int index, uint8_t *data, int len)
811 {
812 int retval = FALSE;
813 uint8_t *p = (uint8_t *)(p_buf + 1);
814
815 UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_FW_PATCH);
816 *p++ = 1 + len; /* parameter length */
817 *p++ = index;
818 (void)memcpy_s(p, len, data, len);
819 p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1 + len;
820
821 hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
822
823 retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_FW_PATCH, p_buf);
824 return retval;
825 }
826
rtk_usb_get_fw_version(bt_hw_cfg_cb_t * cfg_cb)827 static void rtk_usb_get_fw_version(bt_hw_cfg_cb_t *cfg_cb)
828 {
829 struct rtk_epatch *patch = (struct rtk_epatch *)cfg_cb->fw_buf;
830
831 if (cfg_cb->lmp_subversion == LMPSUBVERSION_8723a) {
832 cfg_cb->lmp_sub_current = 0;
833 } else {
834 cfg_cb->lmp_sub_current = (uint16_t)patch->fw_version;
835 }
836 }
837 /*******************************************************************************
838 **
839 ** Function hw_usb_config_cback
840 **
841 ** Description Callback function for controller configuration
842 **
843 ** Returns None
844 **
845 *******************************************************************************/
hw_usb_config_cback(HC_BT_HDR * p_evt_buf)846 void hw_usb_config_cback(HC_BT_HDR *p_evt_buf)
847 {
848 HC_BT_HDR *p_mem = NULL;
849 uint8_t *p = NULL; // , *pp=NULL;
850 uint8_t status = 0;
851 uint16_t opcode = 0;
852 HC_BT_HDR *p_buf = NULL;
853 int is_proceeding = FALSE;
854 uint8_t iIndexRx = 0;
855 usb_patch_info *prtk_usb_patch_file_info = NULL;
856
857 #if (USE_CONTROLLER_BDADDR == TRUE)
858 #endif
859
860 if (p_evt_buf != NULL) {
861 p_mem = (HC_BT_HDR *)p_evt_buf;
862 status = *((uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET);
863 p = (uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_OPCODE_OFFSET;
864 STREAM_TO_UINT16(opcode, p);
865 }
866
867 /* Ask a new buffer big enough to hold any HCI commands sent in here */
868 /* a cut fc6d status==1 */
869 if (((status == 0) || (opcode == HCI_VSC_READ_ROM_VERSION)) && bt_vendor_cbacks) {
870 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN);
871 }
872
873 if (p_buf != NULL) {
874 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
875 p_buf->offset = 0;
876 p_buf->len = 0;
877 p_buf->layer_specific = 0;
878
879 BTVNDDBG("hw_cfg_cb.state = %i", hw_cfg_cb.state);
880 switch (hw_cfg_cb.state) {
881 case HW_CFG_RESET_CHANNEL_CONTROLLER: {
882 #define USLEEP_300000 300000
883 usleep(USLEEP_300000);
884 hw_cfg_cb.state = HW_CFG_READ_LOCAL_VER;
885 p = (uint8_t *)(p_buf + 1);
886 UINT16_TO_STREAM(p, HCI_READ_LMP_VERSION);
887 *p++ = 0;
888 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
889 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LMP_VERSION, p_buf);
890 break;
891 }
892 case HW_CFG_READ_LOCAL_VER: {
893 if (status == 0 && p_mem) {
894 p = ((uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
895 STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
896 p = ((uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_REVISION_OFFSET);
897 STREAM_TO_UINT16(hw_cfg_cb.hci_revision, p);
898 p = (uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_OP1001_LMP_SUBVERSION_OFFSET;
899 STREAM_TO_UINT16(hw_cfg_cb.lmp_subversion, p);
900
901 prtk_usb_patch_file_info = rtk_usb_get_fw_table_entry(hw_cfg_cb.vid, hw_cfg_cb.pid);
902 if ((prtk_usb_patch_file_info == NULL) || (prtk_usb_patch_file_info->lmp_sub_default == 0)) {
903 HILOGE("get patch entry error");
904 is_proceeding = FALSE;
905 break;
906 }
907 hw_cfg_cb.config_len =
908 rtk_usb_get_bt_config(&hw_cfg_cb.config_buf, prtk_usb_patch_file_info->config_name,
909 prtk_usb_patch_file_info->mac_offset);
910 hw_cfg_cb.fw_len = rtk_get_bt_firmware(&hw_cfg_cb.fw_buf, prtk_usb_patch_file_info->patch_name);
911 rtk_usb_get_fw_version(&hw_cfg_cb);
912
913 hw_cfg_cb.lmp_subversion_default = prtk_usb_patch_file_info->lmp_sub_default;
914 BTVNDDBG("lmp_subversion = 0x%x hw_cfg_cb.hci_version = 0x%x hw_cfg_cb.hci_revision = 0x%x, "
915 "hw_cfg_cb.lmp_sub_current = 0x%x",
916 hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision,
917 hw_cfg_cb.lmp_sub_current);
918
919 if (prtk_usb_patch_file_info->lmp_sub_default == hw_cfg_cb.lmp_subversion) {
920 BTVNDDBG("%s: Cold BT controller startup", __func__);
921 hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
922 p = (uint8_t *)(p_buf + 1);
923 UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
924 *p++ = 0;
925 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
926 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf);
927 } else if (hw_cfg_cb.lmp_subversion != hw_cfg_cb.lmp_sub_current) {
928 BTVNDDBG("%s: Warm BT controller startup with updated lmp", __func__);
929 goto RESET_HW_CONTROLLER;
930 } else {
931 BTVNDDBG("%s: Warm BT controller startup with same lmp", __func__);
932 userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
933 free(hw_cfg_cb.total_buf);
934 hw_cfg_cb.total_len = 0;
935
936 bt_vendor_cbacks->dealloc(p_buf);
937 start_fwcfg_cbtimer();
938 hw_cfg_cb.state = 0;
939 is_proceeding = TRUE;
940 }
941 } else {
942 HILOGE("status = %d, or p_mem is NULL", status);
943 }
944 break;
945 }
946 RESET_HW_CONTROLLER:
947 case HW_RESET_CONTROLLER: {
948 if (status == 0) {
949 userial_vendor_usb_ioctl(RESET_CONTROLLER, NULL); // reset controller
950 hw_cfg_cb.state = HW_CFG_READ_ECO_VER;
951 p = (uint8_t *)(p_buf + 1);
952 UINT16_TO_STREAM(p, HCI_VSC_READ_ROM_VERSION);
953 *p++ = 0;
954 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
955 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf);
956 }
957 break;
958 }
959 case HW_CFG_READ_ECO_VER: {
960 if (status == 0 && p_mem) {
961 hw_cfg_cb.eversion = *((uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_OPFC6D_EVERSION_OFFSET);
962 BTVNDDBG("hw_usb_config_cback chip_id of the IC:%d", hw_cfg_cb.eversion + 1);
963 } else if (status == 1) {
964 hw_cfg_cb.eversion = 0;
965 } else {
966 is_proceeding = FALSE;
967 break;
968 }
969
970 hw_cfg_cb.state = HW_CFG_START;
971 goto CFG_USB_START;
972 }
973 CFG_USB_START:
974 case HW_CFG_START: {
975 // get efuse config file and patch code file
976 prtk_usb_patch_file_info = rtk_usb_get_fw_table_entry(hw_cfg_cb.vid, hw_cfg_cb.pid);
977 if ((prtk_usb_patch_file_info == NULL) || (prtk_usb_patch_file_info->lmp_sub_default == 0)) {
978 HILOGE("get patch entry error");
979 is_proceeding = FALSE;
980 break;
981 }
982 hw_cfg_cb.max_patch_size = prtk_usb_patch_file_info->max_patch_size;
983 hw_cfg_cb.config_len = rtk_usb_get_bt_config(
984 &hw_cfg_cb.config_buf, prtk_usb_patch_file_info->config_name, prtk_usb_patch_file_info->mac_offset);
985 if (hw_cfg_cb.config_len) {
986 HILOGE("update altsettings");
987 rtk_usb_update_altsettings(prtk_usb_patch_file_info, hw_cfg_cb.config_buf, &(hw_cfg_cb.config_len));
988 }
989
990 hw_cfg_cb.fw_len = rtk_get_bt_firmware(&hw_cfg_cb.fw_buf, prtk_usb_patch_file_info->patch_name);
991 if (hw_cfg_cb.fw_len < 0) {
992 HILOGE("Get BT firmware fail");
993 hw_cfg_cb.fw_len = 0;
994 is_proceeding = FALSE;
995 break;
996 } else {
997 rtk_usb_get_bt_final_patch(&hw_cfg_cb);
998 }
999
1000 BTVNDDBG("Check total_len(0x%08x) max_patch_size(0x%08x)", hw_cfg_cb.total_len,
1001 hw_cfg_cb.max_patch_size);
1002 if (hw_cfg_cb.total_len > hw_cfg_cb.max_patch_size) {
1003 HILOGE("total length of fw&config(0x%08x) larger than max_patch_size(0x%08x)", hw_cfg_cb.total_len,
1004 hw_cfg_cb.max_patch_size);
1005 is_proceeding = FALSE;
1006 break;
1007 }
1008
1009 if ((hw_cfg_cb.total_len > 0) && hw_cfg_cb.dl_fw_flag) {
1010 hw_cfg_cb.patch_frag_cnt = hw_cfg_cb.total_len / PATCH_DATA_FIELD_MAX_SIZE;
1011 hw_cfg_cb.patch_frag_tail = hw_cfg_cb.total_len % PATCH_DATA_FIELD_MAX_SIZE;
1012 if (hw_cfg_cb.patch_frag_tail) {
1013 hw_cfg_cb.patch_frag_cnt += 1;
1014 } else {
1015 hw_cfg_cb.patch_frag_tail = PATCH_DATA_FIELD_MAX_SIZE;
1016 }
1017 BTVNDDBG("patch fragment count %d, tail len %d", hw_cfg_cb.patch_frag_cnt,
1018 hw_cfg_cb.patch_frag_tail);
1019 } else {
1020 is_proceeding = FALSE;
1021 break;
1022 }
1023
1024 goto DOWNLOAD_USB_FW;
1025 }
1026 /* fall through intentionally */
1027 DOWNLOAD_USB_FW:
1028 case HW_CFG_DL_FW_PATCH:
1029 BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, opcode:0x%x", status, opcode);
1030
1031 // recv command complete event for patch code download command
1032 if (opcode == HCI_VSC_DOWNLOAD_FW_PATCH) {
1033 iIndexRx = *((uint8_t *)(p_mem + 1) + HCI_EVT_CMD_CMPL_STATUS_OFFSET + 1);
1034 BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
1035 hw_cfg_cb.patch_frag_idx++;
1036
1037 if (iIndexRx & 0x80) {
1038 BTVNDDBG("vendor lib fwcfg completed");
1039 userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
1040 free(hw_cfg_cb.total_buf);
1041 hw_cfg_cb.total_len = 0;
1042
1043 bt_vendor_cbacks->dealloc(p_buf);
1044 start_fwcfg_cbtimer();
1045
1046 hw_cfg_cb.state = 0;
1047 is_proceeding = TRUE;
1048 break;
1049 }
1050 }
1051
1052 if (hw_cfg_cb.patch_frag_idx < hw_cfg_cb.patch_frag_cnt) {
1053 iIndexRx = hw_cfg_cb.patch_frag_idx ? ((hw_cfg_cb.patch_frag_idx - 1) % 0x7f + 1) : 0;
1054 if (hw_cfg_cb.patch_frag_idx == hw_cfg_cb.patch_frag_cnt - 1) {
1055 BTVNDDBG("HW_CFG_DL_FW_PATCH: send last fw fragment");
1056 iIndexRx |= 0x80;
1057 hw_cfg_cb.patch_frag_len = hw_cfg_cb.patch_frag_tail;
1058 } else {
1059 iIndexRx &= 0x7F;
1060 hw_cfg_cb.patch_frag_len = PATCH_DATA_FIELD_MAX_SIZE;
1061 }
1062 }
1063
1064 is_proceeding = usb_hci_download_patch_h4(
1065 p_buf, iIndexRx, hw_cfg_cb.total_buf + (hw_cfg_cb.patch_frag_idx * PATCH_DATA_FIELD_MAX_SIZE),
1066 hw_cfg_cb.patch_frag_len);
1067 break;
1068 default:
1069 break;
1070 } // switch(hw_cfg_cb.state)
1071 } // if (p_buf != NULL)
1072
1073 if (is_proceeding == FALSE) {
1074 HILOGE("vendor lib fwcfg aborted!!!");
1075 if (bt_vendor_cbacks) {
1076 if (p_buf != NULL) {
1077 bt_vendor_cbacks->dealloc(p_buf);
1078 }
1079
1080 userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
1081
1082 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
1083 }
1084
1085 if (hw_cfg_cb.config_len) {
1086 free(hw_cfg_cb.config_buf);
1087 hw_cfg_cb.config_len = 0;
1088 }
1089
1090 if (hw_cfg_cb.fw_len) {
1091 free(hw_cfg_cb.fw_buf);
1092 hw_cfg_cb.fw_len = 0;
1093 }
1094
1095 if (hw_cfg_cb.total_len) {
1096 free(hw_cfg_cb.total_buf);
1097 hw_cfg_cb.total_len = 0;
1098 }
1099 hw_cfg_cb.state = 0;
1100 }
1101 }
1102
1103 /*******************************************************************************
1104 **
1105 ** Function hw__usb_config_start
1106 **
1107 ** Description Kick off controller initialization process
1108 **
1109 ** Returns None
1110 **
1111 *******************************************************************************/
hw_usb_config_start(char transtype,uint32_t usb_id)1112 void hw_usb_config_start(char transtype, uint32_t usb_id)
1113 {
1114 RTK_UNUSED(transtype);
1115 memset_s(&hw_cfg_cb, sizeof(bt_hw_cfg_cb_t), 0, sizeof(bt_hw_cfg_cb_t));
1116 hw_cfg_cb.dl_fw_flag = 1;
1117 hw_cfg_cb.chip_type = CHIPTYPE_NONE;
1118 hw_cfg_cb.pid = usb_id & 0x0000ffff;
1119 #define USB_ID_16 16
1120 hw_cfg_cb.vid = (usb_id >> USB_ID_16) & 0x0000ffff;
1121 BTVNDDBG("RTKBT_RELEASE_NAME: %s", RTKBT_RELEASE_NAME);
1122 BTVNDDBG("\nRealtek libbt-vendor_usb Version %s \n", RTK_VERSION);
1123 HC_BT_HDR *p_buf = NULL;
1124 uint8_t *p;
1125
1126 BTVNDDBG("hw_usb_config_start, transtype = 0x%x, pid = 0x%04x, vid = 0x%04x \n", transtype, hw_cfg_cb.pid,
1127 hw_cfg_cb.vid);
1128
1129 if (bt_vendor_cbacks) {
1130 /* Must allocate command buffer via HC's alloc API */
1131 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE);
1132 if (p_buf) {
1133 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1134 p_buf->offset = 0;
1135 p_buf->layer_specific = 0;
1136 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1137
1138 p = (uint8_t *)(p_buf + 1);
1139
1140 p = (uint8_t *)(p_buf + 1);
1141 UINT16_TO_STREAM(p, HCI_VENDOR_RESET);
1142 *p++ = 0;
1143 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1144
1145 hw_cfg_cb.state = HW_CFG_RESET_CHANNEL_CONTROLLER;
1146 bt_vendor_cbacks->xmit_cb(HCI_VENDOR_RESET, p_buf);
1147 } else {
1148 HILOGE("%s buffer alloc fail!", __func__);
1149 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
1150 }
1151 } else {
1152 HILOGE("%s call back is null", __func__);
1153 }
1154 }
1155