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