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