• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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