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 /******************************************************************************
20 *
21 * Filename: bt_vendor_rtk.c
22 *
23 * Description: Realtek vendor specific library implementation
24 *
25 ******************************************************************************/
26
27 #undef NDEBUG
28 #define LOG_TAG "libbt_vendor"
29 #define RTKBT_RELEASE_NAME "20190717_BT_ANDROID_9.0"
30
31 #include "bt_vendor_rtk.h"
32
33 #include <string.h>
34 #include <utils/Log.h>
35
36 #include "upio.h"
37 #include "userial_vendor.h"
38
39 #ifndef BTVND_DBG
40 #define BTVND_DBG FALSE
41 #endif
42 #undef BTVNDDBG
43 #if (BTVND_DBG == TRUE)
44 #define BTVNDDBG(param, ...) \
45 { \
46 HILOGD(param, ##__VA_ARGS__); \
47 }
48 #else
49 #define BTVNDDBG(param, ...) \
50 { \
51 HILOGD(param, ##__VA_ARGS__); \
52 }
53 #endif
54
55 /******************************************************************************
56 ** Externs
57 ******************************************************************************/
58 extern unsigned int rtkbt_h5logfilter;
59 extern unsigned int h5_log_enable;
60 extern bool rtk_btsnoop_dump;
61 extern bool rtk_btsnoop_net_dump;
62 extern bool rtk_btsnoop_save_log;
63 extern char rtk_btsnoop_path[];
64 extern uint8_t coex_log_enable;
65 extern void hw_config_start(char transtype);
66 extern void hw_usb_config_start(char transtype, uint32_t val);
67 extern void RTK_btservice_init();
68 extern void hw_process_event(HC_BT_HDR *);
69
70 #if (HW_END_WITH_HCI_RESET == TRUE)
71 void hw_epilog_process(void);
72 #endif
73
74 /******************************************************************************
75 ** Variables
76 ******************************************************************************/
77 bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
78 uint8_t vnd_local_bd_addr[BD_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
79 bool rtkbt_auto_restart = false;
80
81 /******************************************************************************
82 ** Local type definitions
83 ******************************************************************************/
84 #define DEVICE_NODE_MAX_LEN 512
85 #define RTKBT_CONF_FILE "/vendor/etc/bluetooth/rtkbt.conf"
86 #define USB_DEVICE_DIR "/sys/bus/usb/devices"
87 #define DEBUG_SCAN_USB FALSE
88
89 /******************************************************************************
90 ** Static Variables
91 ******************************************************************************/
92 // transfer_type(4 bit) | transfer_interface(4 bit)
93 char rtkbt_transtype = 0;
94 static char rtkbt_device_node[DEVICE_NODE_MAX_LEN] = {0};
95
96 static const tUSERIAL_CFG userial_H5_cfg = {
97 (USERIAL_DATABITS_8 | USERIAL_PARITY_EVEN | USERIAL_STOPBITS_1),
98 USERIAL_BAUD_115200, USERIAL_HW_FLOW_CTRL_OFF};
99 static const tUSERIAL_CFG userial_H4_cfg = {
100 (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
101 USERIAL_BAUD_115200, USERIAL_HW_FLOW_CTRL_OFF};
102
103 /******************************************************************************
104 ** Functions
105 ******************************************************************************/
Check_Key_Value(char * path,char * key,int value)106 static int Check_Key_Value(char *path, char *key, int value)
107 {
108 FILE *fp;
109 char newpath[100];
110 char string_get[6];
111 int value_int = 0;
112 memset(newpath, 0, 100);
113 sprintf(newpath, "%s/%s", path, key);
114 if ((fp = fopen(newpath, "r")) != NULL)
115 {
116 memset(string_get, 0, 6);
117 if (fgets(string_get, 5, fp) != NULL)
118 if (DEBUG_SCAN_USB)
119 HILOGE("string_get %s =%s\n", key, string_get);
120 fclose(fp);
121 value_int = strtol(string_get, NULL, 16);
122 if (value_int == value)
123 return 1;
124 }
125 return 0;
126 }
127
Scan_Usb_Devices_For_RTK(char * path)128 static int Scan_Usb_Devices_For_RTK(char *path)
129 {
130 char newpath[100];
131 char subpath[100];
132 DIR *pdir;
133 DIR *newpdir;
134 struct dirent *ptr;
135 struct dirent *newptr;
136 struct stat filestat;
137 struct stat subfilestat;
138 if (stat(path, &filestat) != 0)
139 {
140 HILOGE("The file or path(%s) can not be get stat!\n", newpath);
141 return -1;
142 }
143 if ((filestat.st_mode & S_IFDIR) != S_IFDIR)
144 {
145 HILOGE("(%s) is not be a path!\n", path);
146 return -1;
147 }
148 pdir = opendir(path);
149 /*enter sub direc*/
150 while ((ptr = readdir(pdir)) != NULL)
151 {
152 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
153 continue;
154 memset(newpath, 0, 100);
155 sprintf(newpath, "%s/%s", path, ptr->d_name);
156 if (DEBUG_SCAN_USB)
157 HILOGE("The file or path(%s)\n", newpath);
158 if (stat(newpath, &filestat) != 0)
159 {
160 HILOGE("The file or path(%s) can not be get stat!\n", newpath);
161 continue;
162 }
163 /* Check if it is path. */
164 if ((filestat.st_mode & S_IFDIR) == S_IFDIR)
165 {
166 if (!Check_Key_Value(newpath, "idVendor", 0x0bda))
167 continue;
168 newpdir = opendir(newpath);
169 /*read sub directory*/
170 while ((newptr = readdir(newpdir)) != NULL)
171 {
172 if (strcmp(newptr->d_name, ".") == 0 ||
173 strcmp(newptr->d_name, "..") == 0)
174 continue;
175 memset(subpath, 0, 100);
176 sprintf(subpath, "%s/%s", newpath, newptr->d_name);
177 if (DEBUG_SCAN_USB)
178 HILOGE("The file or path(%s)\n", subpath);
179 if (stat(subpath, &subfilestat) != 0)
180 {
181 HILOGE("The file or path(%s) can not be get stat!\n", newpath);
182 continue;
183 }
184 /* Check if it is path. */
185 if ((subfilestat.st_mode & S_IFDIR) == S_IFDIR)
186 {
187 if (Check_Key_Value(subpath, "bInterfaceClass", 0xe0) &&
188 Check_Key_Value(subpath, "bInterfaceSubClass", 0x01) &&
189 Check_Key_Value(subpath, "bInterfaceProtocol", 0x01))
190 {
191 closedir(newpdir);
192 closedir(pdir);
193 return 1;
194 }
195 }
196 }
197 closedir(newpdir);
198 }
199 }
200 closedir(pdir);
201 return 0;
202 }
203
rtk_trim(char * str)204 static char *rtk_trim(char *str)
205 {
206 while (isspace(*str))
207 ++str;
208
209 if (!*str)
210 return str;
211
212 char *end_str = str + strlen(str) - 1;
213 while (end_str > str && isspace(*end_str))
214 --end_str;
215
216 end_str[1] = '\0';
217 return str;
218 }
219
load_rtkbt_conf()220 static void load_rtkbt_conf()
221 {
222 char *split;
223 memset(rtkbt_device_node, 0, sizeof(rtkbt_device_node));
224 FILE *fp = fopen(RTKBT_CONF_FILE, "rt");
225 if (!fp)
226 {
227 HILOGE("%s unable to open file '%s': %s", __func__, RTKBT_CONF_FILE,
228 strerror(errno));
229 strcpy(rtkbt_device_node, "/dev/rtkbt_dev");
230 return;
231 }
232
233 int line_num = 0;
234 char line[1024];
235 while (fgets(line, sizeof(line), fp))
236 {
237 char *line_ptr = rtk_trim(line);
238 ++line_num;
239
240 // Skip blank and comment lines.
241 if (*line_ptr == '\0' || *line_ptr == '#' || *line_ptr == '[')
242 continue;
243
244 split = strchr(line_ptr, '=');
245 if (!split)
246 {
247 HILOGE("%s no key/value separator found on line %d.", __func__, line_num);
248 strcpy(rtkbt_device_node, "/dev/rtkbt_dev");
249 fclose(fp);
250 return;
251 }
252
253 *split = '\0';
254 if (!strcmp(rtk_trim(line_ptr), "BtDeviceNode"))
255 {
256 strcpy(rtkbt_device_node, rtk_trim(split + 1));
257 }
258 }
259
260 fclose(fp);
261
262 rtkbt_transtype = 0;
263 if (rtkbt_device_node[0] == '?')
264 {
265 /*1.Scan_Usb_Device*/
266 if (Scan_Usb_Devices_For_RTK(USB_DEVICE_DIR) == 0x01)
267 {
268 strcpy(rtkbt_device_node, "/dev/rtkbt_dev");
269 }
270 else
271 {
272 int i = 0;
273 while (rtkbt_device_node[i] != '\0')
274 {
275 rtkbt_device_node[i] = rtkbt_device_node[i + 1];
276 i++;
277 }
278 }
279 }
280
281 if ((split = strchr(rtkbt_device_node, ':')) != NULL)
282 {
283 *split = '\0';
284 if (!strcmp(rtk_trim(split + 1), "H5"))
285 {
286 rtkbt_transtype |= RTKBT_TRANS_H5;
287 }
288 else if (!strcmp(rtk_trim(split + 1), "H4"))
289 {
290 rtkbt_transtype |= RTKBT_TRANS_H4;
291 }
292 }
293 else if (strcmp(rtkbt_device_node, "/dev/rtkbt_dev"))
294 {
295 // default use h5
296 rtkbt_transtype |= RTKBT_TRANS_H5;
297 }
298
299 if (strcmp(rtkbt_device_node, "/dev/rtkbt_dev"))
300 {
301 rtkbt_transtype |= RTKBT_TRANS_UART;
302 }
303 else
304 {
305 rtkbt_transtype |= RTKBT_TRANS_USB;
306 rtkbt_transtype |= RTKBT_TRANS_H4;
307 }
308 }
309
rtkbt_stack_conf_cleanup()310 static void rtkbt_stack_conf_cleanup()
311 {
312 rtkbt_h5logfilter = 0;
313 h5_log_enable = 0;
314 rtk_btsnoop_dump = false;
315 rtk_btsnoop_net_dump = false;
316 }
317
load_rtkbt_stack_conf()318 static void load_rtkbt_stack_conf()
319 {
320 char *split;
321 FILE *fp = fopen(RTKBT_CONF_FILE, "rt");
322 if (!fp)
323 {
324 HILOGE("%s unable to open file '%s': %s", __func__, RTKBT_CONF_FILE,
325 strerror(errno));
326 return;
327 }
328 int line_num = 0;
329 char line[1024];
330 // char value[1024];
331 while (fgets(line, sizeof(line), fp))
332 {
333 char *line_ptr = rtk_trim(line);
334 ++line_num;
335
336 // Skip blank and comment lines.
337 if (*line_ptr == '\0' || *line_ptr == '#' || *line_ptr == '[')
338 continue;
339
340 split = strchr(line_ptr, '=');
341 if (!split)
342 {
343 HILOGE("%s no key/value separator found on line %d.", __func__, line_num);
344 continue;
345 }
346
347 *split = '\0';
348 char *endptr;
349 if (!strcmp(rtk_trim(line_ptr), "RtkbtLogFilter"))
350 {
351 rtkbt_h5logfilter = strtol(rtk_trim(split + 1), &endptr, 0);
352 }
353 else if (!strcmp(rtk_trim(line_ptr), "H5LogOutput"))
354 {
355 h5_log_enable = strtol(rtk_trim(split + 1), &endptr, 0);
356 }
357 else if (!strcmp(rtk_trim(line_ptr), "RtkBtsnoopDump"))
358 {
359 if (!strcmp(rtk_trim(split + 1), "true"))
360 rtk_btsnoop_dump = true;
361 }
362 else if (!strcmp(rtk_trim(line_ptr), "RtkBtsnoopNetDump"))
363 {
364 if (!strcmp(rtk_trim(split + 1), "true"))
365 rtk_btsnoop_net_dump = true;
366 }
367 else if (!strcmp(rtk_trim(line_ptr), "BtSnoopFileName"))
368 {
369 sprintf(rtk_btsnoop_path, "%s_rtk", rtk_trim(split + 1));
370 }
371 else if (!strcmp(rtk_trim(line_ptr), "BtSnoopSaveLog"))
372 {
373 if (!strcmp(rtk_trim(split + 1), "true"))
374 rtk_btsnoop_save_log = true;
375 }
376 else if (!strcmp(rtk_trim(line_ptr), "BtCoexLogOutput"))
377 {
378 coex_log_enable = strtol(rtk_trim(split + 1), &endptr, 0);
379 }
380 else if (!strcmp(rtk_trim(line_ptr), "RtkBtAutoRestart"))
381 {
382 if (!strcmp(rtk_trim(split + 1), "true"))
383 rtkbt_auto_restart = true;
384 }
385 }
386
387 fclose(fp);
388 }
389
byte_reverse(unsigned char * data,int len)390 static void byte_reverse(unsigned char *data, int len)
391 {
392 int i;
393 int tmp;
394
395 for (i = 0; i < len / 2; i++)
396 {
397 tmp = len - i - 1;
398 data[i] ^= data[tmp];
399 data[tmp] ^= data[i];
400 data[i] ^= data[tmp];
401 }
402 }
403
init(const bt_vendor_callbacks_t * p_cb,unsigned char * local_bdaddr)404 static int init(const bt_vendor_callbacks_t *p_cb,
405 unsigned char *local_bdaddr)
406 {
407 int retval = -1;
408 HILOGD("init, bdaddr:%02x%02x:%02x%02x:%02x%02x", local_bdaddr[0],
409 local_bdaddr[1], local_bdaddr[2], local_bdaddr[3], local_bdaddr[4],
410 local_bdaddr[5]);
411
412 if (p_cb == NULL)
413 {
414 HILOGE("init failed with no user callbacks!");
415 return retval;
416 }
417
418 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
419 HILOGD("*****************************************************************");
420 HILOGD("*****************************************************************");
421 HILOGD("** Warning - BT Vendor Lib is loaded in debug tuning mode!");
422 HILOGD("**");
423 HILOGD("** If this is not intentional, rebuild libbt-vendor.so ");
424 HILOGD("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and ");
425 HILOGD("** check if any run-time tuning parameters needed to be");
426 HILOGD("** carried to the build-time configuration accordingly.");
427 HILOGD("*****************************************************************");
428 HILOGD("*****************************************************************");
429 #endif
430
431 load_rtkbt_conf();
432 load_rtkbt_stack_conf();
433 if (p_cb == NULL)
434 {
435 HILOGE("init failed with no user callbacks!");
436 return -1;
437 }
438
439 userial_vendor_init(rtkbt_device_node);
440
441 if (rtkbt_transtype & RTKBT_TRANS_UART)
442 {
443 upio_init();
444 HILOGE("bt_wake_up_host_mode_set(1)");
445 bt_wake_up_host_mode_set(1);
446 }
447
448 /* store reference to user callbacks */
449 bt_vendor_cbacks = (bt_vendor_callbacks_t *)p_cb;
450
451 /* This is handed over from the stack */
452 retval = memcpy_s(vnd_local_bd_addr, BD_ADDR_LEN, local_bdaddr, BD_ADDR_LEN);
453
454 byte_reverse(vnd_local_bd_addr, BD_ADDR_LEN);
455
456 if (rtk_btsnoop_dump)
457 rtk_btsnoop_open();
458 if (rtk_btsnoop_net_dump)
459 rtk_btsnoop_net_open();
460
461 return retval;
462 }
463
464 /** Requested operations */
op(bt_opcode_t opcode,void * param)465 static int op(bt_opcode_t opcode, void *param)
466 {
467 int retval = 0;
468
469 // BTVNDDBG("op for %d", opcode);
470
471 switch (opcode)
472 {
473 case BT_OP_POWER_ON: // Power on the BT Controller.
474 if (rtkbt_transtype & RTKBT_TRANS_UART)
475 {
476 upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
477 usleep(200000);
478 BTVNDDBG("set power off and delay 200ms");
479 upio_set_bluetooth_power(UPIO_BT_POWER_ON);
480 // usleep(200000);
481 BTVNDDBG("set power on and delay 00ms");
482 }
483 break;
484
485 case BT_OP_POWER_OFF: // Power off the BT Controller.
486 if (rtkbt_transtype & RTKBT_TRANS_UART)
487 {
488 upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
489 usleep(200000);
490 BTVNDDBG("set power off and delay 200ms");
491 }
492 break;
493
494 // Establish hci channels. it will be called after BT_OP_POWER_ON.
495 case BT_OP_HCI_CHANNEL_OPEN:
496 {
497 if ((rtkbt_transtype & RTKBT_TRANS_UART) &&
498 (rtkbt_transtype & RTKBT_TRANS_H5))
499 {
500 int fd, idx;
501 int(*fd_array)[] = (int(*)[])param;
502 if (userial_vendor_open((tUSERIAL_CFG *)&userial_H5_cfg) != -1)
503 {
504 retval = 1;
505 }
506
507 fd = userial_socket_open();
508 if (fd != -1)
509 {
510 for (idx = 0; idx < HCI_MAX_CHANNEL; idx++)
511 (*fd_array)[idx] = fd;
512 }
513 else
514 retval = 0;
515 }
516 else if ((rtkbt_transtype & RTKBT_TRANS_UART) &&
517 (rtkbt_transtype & RTKBT_TRANS_H4))
518 {
519 /* retval contains numbers of open fd of HCI channels */
520 int(*fd_array)[] = (int(*)[])param;
521 int fd, idx;
522 if (userial_vendor_open((tUSERIAL_CFG *)&userial_H4_cfg) != -1)
523 {
524 retval = 1;
525 }
526 fd = userial_socket_open();
527 if (fd != -1)
528 {
529 for (idx = 0; idx < HCI_MAX_CHANNEL; idx++)
530 (*fd_array)[idx] = fd;
531 }
532 else
533 retval = 0;
534 /* retval contains numbers of open fd of HCI channels */
535 }
536 else
537 {
538 BTVNDDBG("USB op for %d", opcode);
539 int fd, idx = 0;
540 int(*fd_array)[] = (int(*)[])param;
541 for (idx = 0; idx < 10; idx++)
542 {
543 if (userial_vendor_usb_open() != -1)
544 {
545 retval = 1;
546 break;
547 }
548 }
549 fd = userial_socket_open();
550 if (fd != -1)
551 {
552 for (idx = 0; idx < HCI_MAX_CHANNEL; idx++)
553 (*fd_array)[idx] = fd;
554 }
555 else
556 retval = 0;
557 }
558 }
559 break;
560
561 // Close all the hci channels which is opened.
562 case BT_OP_HCI_CHANNEL_CLOSE:
563 {
564 userial_vendor_close();
565 }
566 break;
567
568 // initialization the BT Controller. it will be called after
569 // BT_OP_HCI_CHANNEL_OPEN. Controller Must call init_cb to notify the host
570 // once it has been done.
571 case BT_OP_INIT:
572 {
573 if (rtkbt_transtype & RTKBT_TRANS_UART)
574 {
575 hw_config_start(rtkbt_transtype);
576 }
577 else
578 {
579 int usb_info = 0;
580 retval = userial_vendor_usb_ioctl(GET_USB_INFO, &usb_info);
581 if (retval == -1)
582 {
583 HILOGE("get usb info fail");
584 // bt_vendor_cbacks->fwcfg_cb(BTC_OP_RESULT_FAIL);
585 return retval;
586 }
587 else
588 hw_usb_config_start(RTKBT_TRANS_H4, usb_info);
589 }
590 RTK_btservice_init();
591 }
592 break;
593
594 // Get the LPM idle timeout in milliseconds.
595 case BT_OP_GET_LPM_TIMER:
596 {
597 }
598 break;
599
600 // Enable LPM mode on BT Controller.
601 case BT_OP_LPM_ENABLE:
602 {
603 }
604 break;
605
606 // Disable LPM mode on BT Controller.
607 case BT_OP_LPM_DISABLE:
608 {
609 }
610 break;
611
612 // Wakeup lock the BTC.
613 case BT_OP_WAKEUP_LOCK:
614 {
615 }
616 break;
617
618 // Wakeup unlock the BTC.
619 case BT_OP_WAKEUP_UNLOCK:
620 {
621 }
622 break;
623
624 // transmit event response to vendor lib.
625 case BT_OP_EVENT_CALLBACK:
626 {
627 hw_process_event((HC_BT_HDR *)param);
628 }
629 break;
630 }
631
632 return retval;
633 }
634
635 /** Closes the interface */
cleanup(void)636 static void cleanup(void)
637 {
638 BTVNDDBG("cleanup");
639
640 if (rtkbt_transtype & RTKBT_TRANS_UART)
641 {
642 upio_cleanup();
643 bt_wake_up_host_mode_set(0);
644 }
645 bt_vendor_cbacks = NULL;
646
647 if (rtk_btsnoop_dump)
648 rtk_btsnoop_close();
649 if (rtk_btsnoop_net_dump)
650 rtk_btsnoop_net_close();
651 rtkbt_stack_conf_cleanup();
652 }
653
654 // Entry point of DLib
655 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
656 sizeof(bt_vendor_interface_t), init, op, cleanup};
657