• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 The Android Open Source Project
3  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4  * Not a Contribution.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 /******************************************************************************
20  *
21  *  Filename:      bt_vendor_qcom.c
22  *
23  *  Description:   vendor specific library implementation
24  *
25  ******************************************************************************/
26 #define LOG_TAG "bt_vendor"
27 #define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
28 
29 #include <utils/Log.h>
30 #include <cutils/properties.h>
31 #include <fcntl.h>
32 #include <termios.h>
33 #include "bt_vendor_qcom.h"
34 #include "hci_uart.h"
35 #include "hci_smd.h"
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <cutils/sockets.h>
39 #include <linux/un.h>
40 #include "bt_vendor_persist.h"
41 #include "hw_rome.h"
42 #include "bt_vendor_lib.h"
43 #define WAIT_TIMEOUT 200000
44 #define BT_VND_OP_GET_LINESPEED 30
45 
46 #define STOP_WCNSS_FILTER 0xDD
47 #define STOP_WAIT_TIMEOUT   1000
48 
49 #define SOC_INIT_PROPERTY "wc_transport.soc_initialized"
50 
51 #define BT_VND_FILTER_START "wc_transport.start_hci"
52 
53 #define CMD_TIMEOUT  0x22
54 
55 static void wait_for_patch_download(bool is_ant_req);
56 static bool is_debug_force_special_bytes(void);
57 int connect_to_local_socket(char* name);
58 /******************************************************************************
59 **  Externs
60 ******************************************************************************/
61 extern int hw_config(int nState);
62 extern int is_hw_ready();
63 extern int chipset_ver;
64 
65 /******************************************************************************
66 **  Variables
67 ******************************************************************************/
68 struct bt_qcom_struct *q = NULL;
69 pthread_mutex_t q_lock = PTHREAD_MUTEX_INITIALIZER;
70 
71 int userial_clock_operation(int fd, int cmd);
72 int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti);
73 int userial_vendor_get_baud(void);
74 int readTrpState();
75 void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity);
76 bool is_download_progress();
77 
78 static const tUSERIAL_CFG userial_init_cfg =
79 {
80     (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
81     USERIAL_BAUD_115200
82 };
83 
84 #if (HW_NEED_END_WITH_HCI_RESET == TRUE)
85 void __hw_epilog_process(void);
86 #endif
87 
88 #ifdef WIFI_BT_STATUS_SYNC
89 #include <string.h>
90 #include <errno.h>
91 #include <dlfcn.h>
92 #include "cutils/properties.h"
93 
94 static const char WIFI_PROP_NAME[]    = "wlan.driver.status";
95 static const char SERVICE_PROP_NAME[]    = "bluetooth.hsic_ctrl";
96 static const char BT_STATUS_NAME[]    = "bluetooth.enabled";
97 static const char WIFI_SERVICE_PROP[] = "wlan.hsic_ctrl";
98 
99 #define WIFI_BT_STATUS_LOCK    "/data/connectivity/wifi_bt_lock"
100 int isInit=0;
101 #endif /* WIFI_BT_STATUS_SYNC */
102 bool is_soc_initialized(void);
103 
104 /******************************************************************************
105 **  Local type definitions
106 ******************************************************************************/
107 
108 /******************************************************************************
109 **  Functions
110 ******************************************************************************/
111 #ifdef WIFI_BT_STATUS_SYNC
bt_semaphore_create(void)112 int bt_semaphore_create(void)
113 {
114     int fd;
115 
116     fd = open(WIFI_BT_STATUS_LOCK, O_RDONLY);
117 
118     if (fd < 0)
119         ALOGE("can't create file\n");
120 
121     return fd;
122 }
123 
bt_semaphore_get(int fd)124 int bt_semaphore_get(int fd)
125 {
126     int ret;
127 
128     if (fd < 0)
129         return -1;
130 
131     ret = flock(fd, LOCK_EX);
132     if (ret != 0) {
133         ALOGE("can't hold lock: %s\n", strerror(errno));
134         return -1;
135     }
136 
137     return ret;
138 }
139 
bt_semaphore_release(int fd)140 int bt_semaphore_release(int fd)
141 {
142     int ret;
143 
144     if (fd < 0)
145         return -1;
146 
147     ret = flock(fd, LOCK_UN);
148     if (ret != 0) {
149         ALOGE("can't release lock: %s\n", strerror(errno));
150         return -1;
151     }
152 
153     return ret;
154 }
155 
bt_semaphore_destroy(int fd)156 int bt_semaphore_destroy(int fd)
157 {
158     if (fd < 0)
159         return -1;
160 
161     return close (fd);
162 }
163 
bt_wait_for_service_done(void)164 int bt_wait_for_service_done(void)
165 {
166     char service_status[PROPERTY_VALUE_MAX];
167     int count = 30;
168 
169     ALOGE("%s: check\n", __func__);
170 
171     /* wait for service done */
172     while (count-- > 0) {
173         property_get(WIFI_SERVICE_PROP, service_status, NULL);
174 
175         if (strcmp(service_status, "") != 0) {
176             usleep(200000);
177         } else {
178             break;
179         }
180     }
181 
182     return 0;
183 }
184 
185 #endif /* WIFI_BT_STATUS_SYNC */
186 
187 /** Get Bluetooth SoC type from system setting */
get_bt_soc_type()188 static int get_bt_soc_type()
189 {
190     int ret = 0;
191     char bt_soc_type[PROPERTY_VALUE_MAX];
192 
193     ALOGI("bt-vendor : get_bt_soc_type");
194 
195     ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
196     if (ret != 0) {
197         ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
198         if (!strncasecmp(bt_soc_type, "rome", sizeof("rome"))) {
199             return BT_SOC_ROME;
200         }
201         else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
202             return BT_SOC_CHEROKEE;
203         }
204         else if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) {
205             return BT_SOC_AR3K;
206         }
207         else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
208             return BT_SOC_CHEROKEE;
209         }
210         else {
211             ALOGI("qcom.bluetooth.soc not set, so using default.\n");
212             return BT_SOC_DEFAULT;
213         }
214     }
215     else {
216         ALOGE("%s: Failed to get soc type", __FUNCTION__);
217         ret = BT_SOC_DEFAULT;
218     }
219 
220     return ret;
221 }
222 
can_perform_action(char action)223 bool can_perform_action(char action) {
224     bool can_perform = false;
225     char ref_count[PROPERTY_VALUE_MAX];
226     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
227     int value, ret;
228 
229     property_get("wc_transport.ref_count", ref_count, "0");
230 
231     value = atoi(ref_count);
232     ALOGV("%s: ref_count: %s\n",__func__,  ref_count);
233 
234     if(action == '1') {
235         ALOGV("%s: on : value is: %d", __func__, value);
236         if(value == 1)
237         {
238             if ((is_soc_initialized() == true)
239                || is_download_progress() || get_bt_soc_type() == BT_SOC_CHEROKEE)
240           {
241             value++;
242             ALOGV("%s: on : value is incremented to : %d", __func__, value);
243           }
244         }
245         else
246         {
247              value++;
248         }
249 
250         if (value == 1)
251             can_perform = true;
252         else if (value > 3)
253             return false;
254     }
255     else {
256         ALOGV("%s: off : value is: %d", __func__, value);
257         if (--value <= 0) {
258             ALOGE("%s: BT turn off twice before BT On(ref_count=%d)\n",
259                     __func__, value);
260             value = 0;
261             can_perform = true;
262         }
263     }
264 
265     snprintf(ref_count, 3, "%d", value);
266     ALOGV("%s: updated ref_count is: %s", __func__, ref_count);
267 
268     ret  = property_set("wc_transport.ref_count", ref_count);
269     if (ret < 0) {
270         ALOGE("%s: Error while updating property: %d\n", __func__, ret);
271         return false;
272     }
273     ALOGV("%s returning %d", __func__, can_perform);
274     return can_perform;
275 }
276 
stop_hci_filter()277 void stop_hci_filter() {
278        char value[PROPERTY_VALUE_MAX] = {'\0'};
279        int retval, filter_ctrl, i;
280        char stop_val = STOP_WCNSS_FILTER;
281        int soc_type = BT_SOC_DEFAULT;
282 
283        ALOGV("%s: Entry ", __func__);
284 
285        if ((soc_type = get_bt_soc_type()) == BT_SOC_CHEROKEE) {
286            property_get("wc_transport.hci_filter_status", value, "0");
287            if (strcmp(value, "0") == 0) {
288                ALOGI("%s: hci_filter has been stopped already", __func__);
289            }
290            else {
291                filter_ctrl = connect_to_local_socket("wcnssfilter_ctrl");
292                if (filter_ctrl < 0) {
293                    ALOGI("%s: Error while connecting to CTRL_SOCK, filter should stopped: %d",
294                           __func__, filter_ctrl);
295                }
296                else {
297                    retval = write(filter_ctrl, &stop_val, 1);
298                    if (retval != 1) {
299                        ALOGI("%s: problem writing to CTRL_SOCK, ignore: %d", __func__, retval);
300                        //Ignore and fallback
301                    }
302 
303                    close(filter_ctrl);
304                }
305            }
306 
307            /* Ensure Filter is closed by checking the status before
308               RFKILL 0 operation. this should ideally comeout very
309               quick */
310            for(i=0; i<500; i++) {
311                property_get(BT_VND_FILTER_START, value, "false");
312                if (strcmp(value, "false") == 0) {
313                    ALOGI("%s: WCNSS_FILTER stopped", __func__);
314                    usleep(STOP_WAIT_TIMEOUT * 10);
315                    break;
316                } else {
317                    /*sleep of 1ms, This should give enough time for FILTER to
318                    exit with all necessary cleanup*/
319                    usleep(STOP_WAIT_TIMEOUT);
320                }
321            }
322 
323            /*Never use SIGKILL to stop the filter*/
324            /* Filter will be stopped by below two conditions
325             - by Itself, When it realizes there are no CONNECTED clients
326             - Or through STOP_WCNSS_FILTER byte on Control socket
327             both of these ensure clean shutdown of chip
328            */
329            //property_set(BT_VND_FILTER_START, "false");
330        } else if (soc_type == BT_SOC_ROME) {
331            property_set(BT_VND_FILTER_START, "false");
332        } else {
333            ALOGI("%s: Unknown soc type %d, Unexpected!", __func__, soc_type);
334        }
335 
336        ALOGV("%s: Exit ", __func__);
337 }
338 
start_hci_filter()339 int start_hci_filter() {
340        ALOGV("%s: Entry ", __func__);
341        int i, init_success = -1;
342        char value[PROPERTY_VALUE_MAX] = {'\0'};
343 
344        property_get(BT_VND_FILTER_START, value, false);
345 
346        if (strcmp(value, "true") == 0) {
347            ALOGI("%s: hci_filter has been started already", __func__);
348            //Filter should have been started OR in the process of initializing
349            //Make sure of hci_filter_status and return the state based on it
350        } else {
351 
352            property_set("wc_transport.hci_filter_status", "0");
353            property_set(BT_VND_FILTER_START, "true");
354            ALOGV("%s: %s set to true ", __func__, BT_VND_FILTER_START );
355        }
356 
357        /*If there are back to back ON requests from different clients,
358          All client should come and stuck in this while loop till FILTER
359          comesup and ready to accept the connections */
360        //sched_yield();
361        for(i=0; i<45; i++) {
362           property_get("wc_transport.hci_filter_status", value, "0");
363           if (strcmp(value, "1") == 0) {
364                init_success = 1;
365                break;
366            } else {
367                usleep(WAIT_TIMEOUT);
368            }
369         }
370         ALOGV("start_hcifilter status:%d after %f seconds \n", init_success, 0.2*i);
371 
372         ALOGV("%s: Exit ", __func__);
373         return init_success;
374 }
375 
376 /*
377  * Bluetooth Controller power up or shutdown, this function is called with
378  * q_lock held and q is non-NULL
379  */
bt_powerup(int en)380 static int bt_powerup(int en )
381 {
382     char rfkill_type[64], *enable_ldo_path = NULL;
383     char type[16], enable_ldo[6];
384     int fd = 0, size, i, ret, fd_ldo, fd_btpower;
385 
386     char disable[PROPERTY_VALUE_MAX];
387     char state;
388     char on = (en)?'1':'0';
389 
390 #ifdef WIFI_BT_STATUS_SYNC
391     char wifi_status[PROPERTY_VALUE_MAX];
392     int lock_fd;
393 #endif /*WIFI_BT_STATUS_SYNC*/
394 
395     ALOGI("bt_powerup: %c", on);
396 
397     /* Check if rfkill has been disabled */
398     ret = property_get("ro.rfkilldisabled", disable, "0");
399     if (!ret ){
400         ALOGE("Couldn't get ro.rfkilldisabled (%d)", ret);
401         return -1;
402     }
403     /* In case rfkill disabled, then no control power*/
404     if (strcmp(disable, "1") == 0) {
405         ALOGI("ro.rfkilldisabled : %s", disable);
406         return -1;
407     }
408 
409 #ifdef WIFI_BT_STATUS_SYNC
410     lock_fd = bt_semaphore_create();
411     bt_semaphore_get(lock_fd);
412     bt_wait_for_service_done();
413 #endif
414 
415     /* Assign rfkill_id and find bluetooth rfkill state path*/
416     for(i = 0; (q->rfkill_id == -1) && (q->rfkill_state == NULL); i++)
417     {
418         snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
419         if ((fd = open(rfkill_type, O_RDONLY)) < 0)
420         {
421             ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
422 
423 #ifdef WIFI_BT_STATUS_SYNC
424             bt_semaphore_release(lock_fd);
425             bt_semaphore_destroy(lock_fd);
426 #endif
427             return -1;
428         }
429 
430         size = read(fd, &type, sizeof(type));
431         close(fd);
432 
433         if ((size >= 9) && !memcmp(type, "bluetooth", 9))
434         {
435             asprintf(&q->rfkill_state, "/sys/class/rfkill/rfkill%d/state", q->rfkill_id = i);
436             break;
437         }
438     }
439 
440     /* Get rfkill State to control */
441     if (q->rfkill_state != NULL)
442     {
443         if ((fd = open(q->rfkill_state, O_RDWR)) < 0)
444         {
445             ALOGE("open(%s) for write failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
446 #ifdef WIFI_BT_STATUS_SYNC
447             bt_semaphore_release(lock_fd);
448             bt_semaphore_destroy(lock_fd);
449 #endif
450 
451             return -1;
452         }
453     }
454     if(can_perform_action(on) == false) {
455         ALOGE("%s:can't perform action as it is being used by other clients", __func__);
456 #ifdef WIFI_BT_STATUS_SYNC
457             bt_semaphore_release(lock_fd);
458             bt_semaphore_destroy(lock_fd);
459 #endif
460             goto done;
461     }
462     ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", q->rfkill_id);
463     if( (ret < 0 ) || (enable_ldo_path == NULL) )
464     {
465         ALOGE("Memory Allocation failure");
466         return -1;
467     }
468     if ((fd_ldo = open(enable_ldo_path, O_RDWR)) < 0) {
469         ALOGE("open(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
470         return -1;
471     }
472     size = read(fd_ldo, &enable_ldo, sizeof(enable_ldo));
473     close(fd_ldo);
474     if (size <= 0) {
475         ALOGE("read(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
476         return -1;
477     }
478     if (!memcmp(enable_ldo, "true", 4)) {
479         ALOGI("External LDO has been configured");
480         ret = property_set("wc_transport.extldo", "enabled");
481         if (ret < 0) {
482             ALOGI("%s: Not able to set property wc_transport.extldo\n", __func__);
483         }
484         q->enable_extldo = TRUE;
485     }
486 
487     if(on == '0'){
488         ALOGE("Stopping HCI filter as part of CTRL:OFF");
489         stop_hci_filter();
490         property_set("wc_transport.soc_initialized", "0");
491     }
492 
493     if (q->soc_type >= BT_SOC_CHEROKEE && q->soc_type < BT_SOC_RESERVED) {
494        ALOGI("open bt power devnode,send ioctl power op  :%d ",en);
495        fd_btpower = open(BT_PWR_CNTRL_DEVICE, O_RDWR, O_NONBLOCK);
496        if (fd_btpower < 0) {
497            ALOGE("\nfailed to open bt device error = (%s)\n",strerror(errno));
498 #ifdef WIFI_BT_STATUS_SYNC
499            bt_semaphore_release(lock_fd);
500            bt_semaphore_destroy(lock_fd);
501 #endif
502            return -1;
503        }
504        ret = ioctl(fd_btpower, BT_CMD_PWR_CTRL, (unsigned long)en);
505         if (ret < 0) {
506             ALOGE(" ioctl failed to power control:%d error =(%s)",ret,strerror(errno));
507         }
508         close(fd_btpower);
509     } else {
510        ALOGI("Write %c to rfkill\n", on);
511        /* Write value to control rfkill */
512        if(fd >= 0) {
513            if ((size = write(fd, &on, 1)) < 0) {
514                ALOGE("write(%s) failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
515 #ifdef WIFI_BT_STATUS_SYNC
516                bt_semaphore_release(lock_fd);
517                bt_semaphore_destroy(lock_fd);
518 #endif
519                return -1;
520            }
521        }
522    }
523 #ifdef WIFI_BT_STATUS_SYNC
524     /* query wifi status */
525     property_get(WIFI_PROP_NAME, wifi_status, "");
526 
527     ALOGE("bt get wifi status: %s, isInit: %d\n",  wifi_status, isInit);
528 
529     /* If wlan driver is not loaded, and bt is changed from off => on */
530     if (strncmp(wifi_status, "unloaded", strlen("unloaded")) == 0 || strlen(wifi_status) == 0) {
531         if (on == '1') {
532             ALOGI("%s: BT_VND_PWR_ON\n", __func__);
533             if(property_set(SERVICE_PROP_NAME, "load_wlan") < 0) {
534                 ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
535                 close(fd);
536                 bt_semaphore_release(lock_fd);
537                 bt_semaphore_destroy(lock_fd);
538                 return -1;
539             }
540         }
541         else if (isInit == 0 && on == '0') {
542             ALOGI("%s: BT_VND_PWR_OFF\n", __func__);
543             if(property_set(SERVICE_PROP_NAME, "unbind_hsic") < 0) {
544                 ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
545                 close(fd);
546                 bt_semaphore_release(lock_fd);
547                 bt_semaphore_destroy(lock_fd);
548                 return -1;
549             }
550        }
551     }
552 
553     if (isInit == 0 && on == '0')
554         property_set(BT_STATUS_NAME, "false");
555     else if (on == '1')
556         property_set(BT_STATUS_NAME, "true");
557 
558     bt_semaphore_release(lock_fd);
559     bt_semaphore_destroy(lock_fd);
560 #endif /* WIFI_BT_STATUS_SYNC */
561 
562 done:
563     if (fd >= 0)
564         close(fd);
565     return 0;
566 }
567 
soc_init(int soc_type)568 static inline void soc_init(int soc_type)
569 {
570     switch (soc_type)
571     {
572     case BT_SOC_CHEROKEE:
573     case BT_SOC_ROME:
574     case BT_SOC_AR3K:
575         ALOGI("bt-vendor : Initializing UART transport layer");
576         userial_vendor_init();
577         break;
578     case BT_SOC_DEFAULT:
579         break;
580     default:
581         ALOGE("Unknown soc yype: %d", soc_type);
582         break;
583     }
584 }
585 
586 /* Copy BD Address as little-endian byte order */
le2bd(unsigned char * src,unsigned char * dst)587 static inline void le2bd(unsigned char *src, unsigned char *dst)
588 {
589     int i;
590     for (i = 0; i < 6; i++)
591         dst[i] = src[5-i];
592 }
593 
print_bdaddr(unsigned char * addr)594 static inline void print_bdaddr(unsigned char *addr)
595 {
596     ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1],
597             addr[2], addr[3], addr[4], addr[5]);
598 }
599 
600 /*****************************************************************************
601 **
602 **   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
603 **
604 *****************************************************************************/
605 
init(const bt_vendor_callbacks_t * cb,unsigned char * bdaddr)606 static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
607 {
608     char prop[PROPERTY_VALUE_MAX] = {0};
609     struct bt_qcom_struct *temp = NULL;
610     int ret = BT_STATUS_SUCCESS, i;
611 
612     ALOGI("++%s", __FUNCTION__);
613 
614     if (!cb || !bdaddr) {
615         ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr);
616         ret = -BT_STATUS_INVAL;
617         goto out;
618     }
619 
620     temp = (struct bt_qcom_struct *) malloc(sizeof(*q));
621     if (!temp) {
622         ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno);
623         ret = -BT_STATUS_NOMEM;
624         goto out;
625     }
626     memset(temp, 0, sizeof(*temp));
627 
628     temp->rfkill_id = -1;
629     temp->enable_extldo = FALSE;
630     temp->cb = cb;
631     temp->ant_fd = -1;
632     temp->soc_type = get_bt_soc_type();
633     soc_init(temp->soc_type);
634 
635     le2bd(bdaddr, temp->bdaddr);
636     print_bdaddr(temp->bdaddr);
637     snprintf(prop, sizeof(prop), "%02x:%02x:%02x:%02x:%02x:%02x",
638              temp->bdaddr[0], temp->bdaddr[1], temp->bdaddr[2],
639              temp->bdaddr[3], temp->bdaddr[4], temp->bdaddr[5]);
640     ret = property_set("wc_transport.stack_bdaddr", prop);
641     if (ret < 0) {
642         ALOGE("Failed to set wc_transport.stack_bdaddr prop, ret = %d", ret);
643         ret = -BT_STATUS_PROP_FAILURE;
644         goto out;
645     }
646 
647 /* TODO: Move these fields inside bt_qcom context */
648 #ifdef WIFI_BT_STATUS_SYNC
649     isInit = 1;
650 #endif /* WIFI_BT_STATUS_SYNC */
651 
652     /* Everything successful */
653     q = temp;
654     return ret;
655 
656 out:
657     if (temp)
658         free(temp);
659     ALOGI("--%s ret %d", __FUNCTION__, ret);
660     return ret;
661 }
662 
663 #ifdef READ_BT_ADDR_FROM_PROP
validate_tok(char * bdaddr_tok)664 static bool validate_tok(char* bdaddr_tok) {
665     int i = 0;
666     bool ret;
667 
668     if (strlen(bdaddr_tok) != 2) {
669         ret = FALSE;
670         ALOGE("Invalid token length");
671     } else {
672         ret = TRUE;
673         for (i=0; i<2; i++) {
674             if ((bdaddr_tok[i] >= '0' && bdaddr_tok[i] <= '9') ||
675                 (bdaddr_tok[i] >= 'A' && bdaddr_tok[i] <= 'F') ||
676                 (bdaddr_tok[i] >= 'a' && bdaddr_tok[i] <= 'f')) {
677                 ret = TRUE;
678                 ALOGV("%s: tok %s @ %d is good", __func__, bdaddr_tok, i);
679              } else {
680                 ret = FALSE;
681                 ALOGE("invalid character in tok: %s at ind: %d", bdaddr_tok, i);
682                 break;
683              }
684         }
685     }
686     return ret;
687 }
688 #endif /*READ_BT_ADDR_FROM_PROP*/
689 
connect_to_local_socket(char * name)690 int connect_to_local_socket(char* name) {
691        socklen_t len; int sk = -1;
692 
693        ALOGE("%s: ACCEPT ", __func__);
694        sk  = socket(AF_LOCAL, SOCK_STREAM, 0);
695        if (sk < 0) {
696            ALOGE("Socket creation failure");
697            return -1;
698        }
699 
700         if(socket_local_client_connect(sk, name,
701             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
702         {
703              ALOGE("failed to connect (%s)", strerror(errno));
704              close(sk);
705              sk = -1;
706         } else {
707                 ALOGE("%s: Connection succeeded\n", __func__);
708         }
709         return sk;
710 }
711 
is_soc_initialized()712 bool is_soc_initialized() {
713     bool init = false;
714     char init_value[PROPERTY_VALUE_MAX];
715     int ret;
716 
717     ALOGI("bt-vendor : is_soc_initialized");
718 
719     ret = property_get(SOC_INIT_PROPERTY, init_value, NULL);
720     if (ret != 0) {
721         ALOGI("%s set to %s\n", SOC_INIT_PROPERTY, init_value);
722         if (!strncasecmp(init_value, "1", sizeof("1"))) {
723             init = true;
724         }
725     }
726     else {
727         ALOGE("%s: Failed to get %s", __FUNCTION__, SOC_INIT_PROPERTY);
728     }
729 
730     return init;
731 }
732 
733 /* flavor of op without locks */
__op(bt_vendor_opcode_t opcode,void * param)734 static int __op(bt_vendor_opcode_t opcode, void *param)
735 {
736     int retval = BT_STATUS_SUCCESS;
737     int nCnt = 0;
738     int nState = -1;
739     bool is_ant_req = false;
740     bool is_fm_req = false;
741     char wipower_status[PROPERTY_VALUE_MAX];
742     char emb_wp_mode[PROPERTY_VALUE_MAX];
743     char bt_version[PROPERTY_VALUE_MAX];
744     char lpm_config[PROPERTY_VALUE_MAX];
745     bool ignore_boot_prop = TRUE;
746 #ifdef READ_BT_ADDR_FROM_PROP
747     int i = 0;
748     static char bd_addr[PROPERTY_VALUE_MAX];
749     uint8_t local_bd_addr_from_prop[6];
750     char* tok;
751 #endif
752     bool skip_init = true;
753     int  opcode_init = opcode;
754     ALOGV("++%s opcode %d", __FUNCTION__, opcode);
755 
756     switch(opcode_init)
757     {
758 #ifdef FM_OVER_UART
759         case FM_VND_OP_POWER_CTRL:
760             {
761               is_fm_req = true;
762               if (is_soc_initialized()) {
763                   // add any FM specific actions  if needed in future
764                   break;
765               }
766             }
767 #endif
768         case BT_VND_OP_POWER_CTRL:
769             {
770                 if (!param) {
771                     ALOGE("opcode = %d: param is null", opcode_init);
772                     break;
773                 }
774                 nState = *(int *) param;
775                 ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
776                         (nState == BT_VND_PWR_ON)? "On" : "Off" );
777 
778                 switch(q->soc_type)
779                 {
780                     case BT_SOC_DEFAULT:
781                         if (readTrpState())
782                         {
783                            ALOGI("bt-vendor : resetting BT status");
784                            hw_config(BT_VND_PWR_OFF);
785                         }
786                         retval = hw_config(nState);
787                         if(nState == BT_VND_PWR_ON
788                            && retval == 0
789                            && is_hw_ready() == TRUE){
790                             retval = 0;
791                         }
792                         else {
793                             retval = -1;
794                         }
795                         break;
796                     case BT_SOC_ROME:
797                     case BT_SOC_AR3K:
798                     case BT_SOC_CHEROKEE:
799                         /* BT Chipset Power Control through Device Tree Node */
800                         retval = bt_powerup(nState);
801                     default:
802                         break;
803                 }
804             }
805             break;
806 
807         case BT_VND_OP_FW_CFG: {
808                 /* call hciattach to initalize the stack */
809                 if (q->soc_type == BT_SOC_ROME) {
810                     if (is_soc_initialized()) {
811                         ALOGI("Bluetooth FW and transport layer are initialized");
812                         q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
813                     } else {
814                         ALOGE("bt_vendor_cbacks is null or SoC not initialized");
815                         ALOGE("Error : hci, smd initialization Error");
816                         retval = -1;
817                     }
818                 } else {
819                     ALOGI("Bluetooth FW and transport layer are initialized");
820                     q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
821                 }
822         }
823             break;
824 
825         case BT_VND_OP_SCO_CFG:
826             q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
827             break;
828 #ifdef ENABLE_ANT
829         case BT_VND_OP_ANT_USERIAL_OPEN:
830                 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
831                 is_ant_req = true;
832                 goto userial_open;
833 #endif
834 #ifdef FM_OVER_UART
835         case BT_VND_OP_FM_USERIAL_OPEN:
836                 ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
837                 is_fm_req = true;
838                 goto userial_open;
839 #endif
840 userial_open:
841         case BT_VND_OP_USERIAL_OPEN:
842             {
843                 if (!param) {
844                     ALOGE("opcode = %d: param is null", opcode_init);
845                     break;
846                 }
847                 int (*fd_array)[] = (int (*)[]) param;
848                 int idx, fd = -1, fd_filter = -1;
849                 ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
850                 switch(q->soc_type)
851                 {
852                     case BT_SOC_DEFAULT:
853                         {
854                             if(bt_hci_init_transport(q->fd) != -1){
855                                 int (*fd_array)[] = (int (*) []) param;
856 
857                                     (*fd_array)[CH_CMD] = q->fd[0];
858                                     (*fd_array)[CH_EVT] = q->fd[0];
859                                     (*fd_array)[CH_ACL_OUT] = q->fd[1];
860                                     (*fd_array)[CH_ACL_IN] = q->fd[1];
861                             }
862                             else {
863                                 retval = -1;
864                                 break;
865                             }
866                             retval = 2;
867                         }
868                         break;
869                     case BT_SOC_AR3K:
870                         {
871                             fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
872                             if (fd != -1) {
873                                 for (idx=0; idx < CH_MAX; idx++)
874                                     (*fd_array)[idx] = fd;
875                                      retval = 1;
876                             }
877                             else {
878                                 retval = -1;
879                                 break;
880                             }
881 
882                             /* Vendor Specific Process should happened during userial_open process
883                                 After userial_open, rx read thread is running immediately,
884                                 so it will affect VS event read process.
885                             */
886                             if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
887                                 retval = -1;
888                         }
889                         break;
890                     case BT_SOC_ROME:
891                         {
892                             wait_for_patch_download(is_ant_req);
893                             property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
894                             if (!is_soc_initialized()) {
895                                 char* dlnd_inprog = is_ant_req ? "ant" : "bt";
896                                 if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
897                                     ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
898                                 }
899 
900                                 fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
901                                 if (fd < 0) {
902                                     ALOGE("userial_vendor_open returns err");
903                                     retval = -1;
904                                     break;
905                                 }
906 
907                                 /* Clock on */
908                                 userial_clock_operation(fd, USERIAL_OP_CLK_ON);
909 
910                                 if(strcmp(emb_wp_mode, "true") == 0) {
911                                     property_get("ro.bluetooth.wipower", wipower_status, false);
912                                     if(strcmp(wipower_status, "true") == 0) {
913                                         check_embedded_mode(fd);
914                                     } else {
915                                         ALOGI("Wipower not enabled");
916                                     }
917                                 }
918                                 ALOGV("rome_soc_init is started");
919                                 property_set("wc_transport.soc_initialized", "0");
920 #ifdef READ_BT_ADDR_FROM_PROP
921                                 /*Give priority to read BD address from boot property*/
922                                 ignore_boot_prop = FALSE;
923                                 if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
924                                     ALOGV("BD address read from Boot property: %s\n", bd_addr);
925                                     tok =  strtok(bd_addr, ":");
926                                     while (tok != NULL) {
927                                         ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
928                                         if (i>=6) {
929                                             ALOGE("bd property of invalid length");
930                                             ignore_boot_prop = TRUE;
931                                             break;
932                                         }
933                                         if (i == 6 && !ignore_boot_prop) {
934                                             ALOGV("Valid BD address read from prop");
935                                             memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
936                                             ignore_boot_prop = FALSE;
937                                         } else {
938                                             ALOGE("There are not enough tokens in BD addr");
939                                             ignore_boot_prop = TRUE;
940                                             break;
941                                         }
942                                         local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
943                                         tok = strtok(NULL, ":");
944                                         i++;
945                                     }
946                                     if (i == 6 && !ignore_boot_prop) {
947                                         ALOGV("Valid BD address read from prop");
948                                         memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
949                                         ignore_boot_prop = FALSE;
950                                     } else {
951                                         ALOGE("There are not enough tokens in BD addr");
952                                         ignore_boot_prop = TRUE;
953                                     }
954                                 }
955                                 else {
956                                      ALOGE("BD address boot property not set");
957                                      ignore_boot_prop = TRUE;
958                                 }
959 #endif //READ_BT_ADDR_FROM_PROP
960                                     /* Always read BD address from NV file */
961                                 if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
962                                 {
963                                    /* Since the BD address is configured in boot time We should not be here */
964                                    ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
965                                 }
966                                 if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
967                                     retval = -1;
968                                 } else {
969                                     ALOGV("rome_soc_init is completed");
970                                     property_set("wc_transport.soc_initialized", "1");
971                                     skip_init = false;
972                                 }
973                             }
974                             if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
975                                 ALOGE("%s: Failed to set property", __FUNCTION__);
976                             }
977 
978                             property_set("wc_transport.clean_up","0");
979                             if (retval != -1) {
980 
981                                 retval = start_hci_filter();
982                                 if (retval < 0) {
983                                     ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
984                                 } else {
985 #ifdef ENABLE_ANT
986                                     if (is_ant_req) {
987                                         ALOGI("%s: connect to ant channel", __func__);
988                                         q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
989                                     }
990                                     else
991 #endif
992                                     {
993                                         ALOGI("%s: connect to bt channel", __func__);
994                                         vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
995                                     }
996 
997                                     if (fd_filter != -1) {
998                                         ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
999                                                              __func__, fd_filter, is_ant_req,is_fm_req);
1000                                         if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
1001                                              if (chipset_ver >= ROME_VER_3_0) {
1002                                                 /* get rome supported feature request */
1003                                                 ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
1004                                                 rome_get_addon_feature_list(fd_filter);
1005                                             }
1006                                         }
1007                                         if (!skip_init) {
1008                                             /*Skip if already sent*/
1009                                             enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
1010                                             skip_init = true;
1011                                         }
1012                                         for (idx=0; idx < CH_MAX; idx++)
1013                                             (*fd_array)[idx] = fd_filter;
1014                                             retval = 1;
1015                                     }
1016                                     else {
1017                                         if (is_ant_req)
1018                                             ALOGE("Unable to connect to ANT Server Socket!!!");
1019                                         else
1020                                             ALOGE("Unable to connect to BT Server Socket!!!");
1021                                         retval = -1;
1022                                     }
1023                                 }
1024                             } else {
1025                                 if (q->soc_type == BT_SOC_ROME)
1026                                     ALOGE("Failed to initialize ROME Controller!!!");
1027                             }
1028 
1029                             if (fd >= 0) {
1030                                 userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
1031                                  /*Close the UART port*/
1032                                  close(fd);
1033                             }
1034                         }
1035                         break;
1036                     case BT_SOC_CHEROKEE:
1037                         {
1038                             property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
1039                             retval = start_hci_filter();
1040                             if (retval < 0) {
1041                                 ALOGE("WCNSS_FILTER wouldn't have started in time\n");
1042 
1043                             } else {
1044 #ifdef ENABLE_ANT
1045                                 if (is_ant_req) {
1046                                     ALOGI("%s: connect to ant channel", __func__);
1047                                     q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
1048                                 }
1049                                 else
1050 #endif
1051 #ifdef FM_OVER_UART
1052                                 if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
1053                                     ALOGI("%s: connect to fm channel", __func__);
1054                                     q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
1055                                 }
1056                                 else
1057 #endif
1058                                 {
1059                                     ALOGI("%s: connect to bt channel", __func__);
1060                                     vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
1061 
1062                                 }
1063                                 if (fd_filter != -1) {
1064                                     ALOGV("%s: received the socket fd: %d \n",
1065                                                              __func__, fd_filter);
1066 
1067                                     for (idx=0; idx < CH_MAX; idx++) {
1068                                         (*fd_array)[idx] = fd_filter;
1069                                     }
1070                                     retval = 1;
1071                                 }
1072                                 else {
1073 #ifdef ENABLE_ANT
1074                                     if (is_ant_req)
1075                                         ALOGE("Unable to connect to ANT Server Socket!!!");
1076                                     else
1077 #endif
1078 #ifdef FM_OVER_UART
1079                                     if (is_fm_req)
1080                                         ALOGE("Unable to connect to FM Server Socket!!!");
1081                                     else
1082 #endif
1083                                         ALOGE("Unable to connect to BT Server Socket!!!");
1084                                     retval = -1;
1085                                 }
1086                             }
1087                         }
1088                         break;
1089                     default:
1090                         ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1091                         break;
1092                   }
1093             } break;
1094 #ifdef ENABLE_ANT
1095         case BT_VND_OP_ANT_USERIAL_CLOSE:
1096             {
1097                 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
1098                 property_set("wc_transport.clean_up","1");
1099                 if (q->ant_fd != -1) {
1100                     ALOGE("closing ant_fd");
1101                     close(q->ant_fd);
1102                     q->ant_fd = -1;
1103                 }
1104             }
1105             break;
1106 #endif
1107 #ifdef FM_OVER_UART
1108         case BT_VND_OP_FM_USERIAL_CLOSE:
1109             {
1110                 ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
1111                 property_set("wc_transport.clean_up","1");
1112                 if (q->fm_fd != -1) {
1113                     ALOGE("closing fm_fd");
1114                     close(q->fm_fd);
1115                     q->fm_fd = -1;
1116                 }
1117                 break;
1118             }
1119 #endif
1120         case BT_VND_OP_USERIAL_CLOSE:
1121             {
1122                 ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
1123                 switch(q->soc_type)
1124                 {
1125                     case BT_SOC_DEFAULT:
1126                         bt_hci_deinit_transport(q->fd);
1127                         break;
1128                     case BT_SOC_ROME:
1129                     case BT_SOC_AR3K:
1130                     case BT_SOC_CHEROKEE:
1131                     {
1132                         property_set("wc_transport.clean_up","1");
1133                         userial_vendor_close();
1134                         break;
1135                     }
1136                     default:
1137                         ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1138                         break;
1139                 }
1140             }
1141             break;
1142 
1143         case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
1144             {
1145                 if (!param) {
1146                     ALOGE("opcode = %d: param is null", opcode_init);
1147                     break;
1148                 }
1149                 uint32_t *timeout_ms = (uint32_t *) param;
1150                 *timeout_ms = 1000;
1151             }
1152 
1153             break;
1154 
1155         case BT_VND_OP_LPM_SET_MODE:
1156             if (q->soc_type == BT_SOC_AR3K) {
1157                 if (!param) {
1158                     ALOGE("opcode = %d: param is null", opcode_init);
1159                     break;
1160                 }
1161                 uint8_t *mode = (uint8_t *) param;
1162 
1163                 if (*mode) {
1164                     lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1165                 }
1166                 else {
1167                     lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1168                 }
1169                 q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
1170             } else {
1171                 int lpm_result = BT_VND_OP_RESULT_SUCCESS;
1172 
1173                 property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
1174                 ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
1175                             __func__, lpm_config);
1176 
1177                 if (!strcmp(lpm_config, "all")) {
1178                     // respond with success since we want to hold wake lock through LPM
1179                     lpm_result = BT_VND_OP_RESULT_SUCCESS;
1180                 }
1181                 else {
1182                     lpm_result = BT_VND_OP_RESULT_FAIL;
1183                 }
1184 
1185                 q->cb->lpm_cb(lpm_result);
1186             }
1187             break;
1188 
1189         case BT_VND_OP_LPM_WAKE_SET_STATE: {
1190             switch(q->soc_type) {
1191             case BT_SOC_CHEROKEE:
1192             case BT_SOC_ROME: {
1193                 if (!param) {
1194                     ALOGE("opcode = %d: param is null", opcode_init);
1195                     break;
1196                 }
1197                 uint8_t *state = (uint8_t *) param;
1198                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1199                             BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
1200 
1201                 if (wake_assert == 0)
1202                     ALOGV("ASSERT: Waking up BT-Device");
1203                 else if (wake_assert == 1)
1204                     ALOGV("DEASSERT: Allowing BT-Device to Sleep");
1205 
1206 #ifdef QCOM_BT_SIBS_ENABLE
1207                 ALOGI("Invoking HCI H4 callback function");
1208                 q->cb->lpm_set_state_cb(wake_assert);
1209 #endif
1210             }
1211             break;
1212             case BT_SOC_AR3K: {
1213                 if (!param) {
1214                     ALOGE("opcode = %d: param is null", opcode_init);
1215                     break;
1216                 }
1217                 uint8_t *state = (uint8_t *) param;
1218                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1219                                                 UPIO_ASSERT : UPIO_DEASSERT;
1220                 lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
1221             }
1222             case BT_SOC_DEFAULT:
1223                 break;
1224             default:
1225                 ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1226                 break;
1227             }
1228         }
1229             break;
1230         case BT_VND_OP_EPILOG: {
1231 #if (HW_NEED_END_WITH_HCI_RESET == FALSE)
1232             q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1233 #else
1234                 switch(q->soc_type)
1235                 {
1236                   case BT_SOC_CHEROKEE:
1237                   case BT_SOC_ROME:
1238                        {
1239                            char value[PROPERTY_VALUE_MAX] = {'\0'};
1240                            property_get("wc_transport.hci_filter_status", value, "0");
1241                            if(is_soc_initialized()&& (strcmp(value,"1") == 0))
1242                            {
1243                               __hw_epilog_process();
1244                            }
1245                            else
1246                            {
1247                                 q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1248                            }
1249                        }
1250                        break;
1251                   default:
1252                        __hw_epilog_process();
1253                        break;
1254                 }
1255 #endif
1256             }
1257             break;
1258         case BT_VND_OP_GET_LINESPEED:
1259             {
1260                 retval = -1;
1261                 if(!is_soc_initialized()) {
1262                      ALOGE("BT_VND_OP_GET_LINESPEED: error"
1263                          " - transport driver not initialized!");
1264                      break;
1265                 }
1266 
1267                 switch(q->soc_type)
1268                 {
1269                     case BT_SOC_CHEROKEE:
1270                             retval = 3200000;
1271                         break;
1272                     case BT_SOC_ROME:
1273                             retval = 3000000;
1274                         break;
1275                     default:
1276                         retval = userial_vendor_get_baud();
1277                         break;
1278                  }
1279                 break;
1280             }
1281     }
1282 
1283 out:
1284     ALOGV("--%s", __FUNCTION__);
1285     return retval;
1286 }
1287 
op(bt_vendor_opcode_t opcode,void * param)1288 static int op(bt_vendor_opcode_t opcode, void *param)
1289 {
1290     int ret;
1291     ALOGV("++%s", __FUNCTION__);
1292     pthread_mutex_lock(&q_lock);
1293     if (!q) {
1294         ALOGE("op called with NULL context");
1295         ret = -BT_STATUS_INVAL;
1296         goto out;
1297     }
1298     ret = __op(opcode, param);
1299 out:
1300     pthread_mutex_unlock(&q_lock);
1301     ALOGV("--%s ret = 0x%x", __FUNCTION__, ret);
1302     return ret;
1303 }
1304 
ssr_cleanup(int reason)1305 static void ssr_cleanup(int reason)
1306 {
1307     int pwr_state = BT_VND_PWR_OFF;
1308     int ret;
1309     unsigned char trig_ssr = 0xEE;
1310 
1311     ALOGI("++%s", __FUNCTION__);
1312 
1313     pthread_mutex_lock(&q_lock);
1314     if (!q) {
1315         ALOGE("ssr_cleanup called with NULL context");
1316         goto out;
1317     }
1318     if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
1319         ALOGE("Failed to set property");
1320     }
1321 
1322     if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) {
1323 #ifdef ENABLE_ANT
1324         /*Indicate to filter by sending special byte */
1325         if (reason == CMD_TIMEOUT) {
1326             trig_ssr = 0xEE;
1327             ret = write (vnd_userial.fd, &trig_ssr, 1);
1328             ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s",
1329                         ret, strerror(errno));
1330 
1331             if (is_debug_force_special_bytes()) {
1332                 /*
1333                  * Then we should send special byte to crash SOC in
1334                  * WCNSS_Filter, so we do not need to power off UART here.
1335                  */
1336                 goto out;
1337             }
1338         }
1339 
1340         /* Close both ANT channel */
1341         __op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
1342 #endif
1343         /* Close both BT channel */
1344         __op(BT_VND_OP_USERIAL_CLOSE, NULL);
1345 
1346 #ifdef FM_OVER_UART
1347         __op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
1348 #endif
1349         /*CTRL OFF twice to make sure hw
1350          * turns off*/
1351 #ifdef ENABLE_ANT
1352         __op(BT_VND_OP_POWER_CTRL, &pwr_state);
1353 #endif
1354     }
1355     /*Generally switching of chip should be enough*/
1356     __op(BT_VND_OP_POWER_CTRL, &pwr_state);
1357 
1358 out:
1359     pthread_mutex_unlock(&q_lock);
1360     ALOGI("--%s", __FUNCTION__);
1361 }
1362 
1363 /** Closes the interface */
cleanup(void)1364 static void cleanup(void)
1365 {
1366     ALOGI("cleanup");
1367 
1368     pthread_mutex_lock(&q_lock);
1369     q->cb = NULL;
1370     free(q);
1371     q = NULL;
1372     pthread_mutex_unlock(&q_lock);
1373 
1374 #ifdef WIFI_BT_STATUS_SYNC
1375     isInit = 0;
1376 #endif /* WIFI_BT_STATUS_SYNC */
1377 }
1378 
1379 /* Check for one of the cients ANT/BT patch download is already in
1380 ** progress if yes wait till complete
1381 */
wait_for_patch_download(bool is_ant_req)1382 void wait_for_patch_download(bool is_ant_req) {
1383     ALOGV("%s:", __FUNCTION__);
1384     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1385     while (1) {
1386         property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1387 
1388         if(is_ant_req && !(strcmp(inProgress,"bt"))) {
1389            //ANT request, wait for BT to finish
1390            usleep(50000);
1391         }
1392         else if(!is_ant_req && !(strcmp(inProgress,"ant"))) {
1393           //BT request, wait for ANT to finish
1394            usleep(50000);
1395         }
1396         else {
1397            ALOGI("%s: patch download completed", __FUNCTION__);
1398            break;
1399         }
1400     }
1401 }
1402 
is_download_progress()1403 bool is_download_progress () {
1404     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1405     bool retval = false;
1406 
1407     ALOGV("%s:", __FUNCTION__);
1408 
1409     if ((q->soc_type = get_bt_soc_type()) < 0) {
1410         ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
1411         return -1;
1412     }
1413 
1414     switch(q->soc_type)
1415     {
1416         case BT_SOC_ROME:
1417             ALOGI("%s: ROME case", __func__);
1418             property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1419             if(strcmp(inProgress,"null") == 0) {
1420                 retval = false;
1421             } else {
1422                  retval = true;
1423             }
1424             break;
1425         case BT_SOC_CHEROKEE:
1426             ALOGI("%s: CHEROKEE case", __func__);
1427             break;
1428         case BT_SOC_DEFAULT:
1429             break;
1430         default:
1431             ALOGE("Unknown btSocType: 0x%x", q->soc_type);
1432             break;
1433     }
1434     return retval;
1435 }
1436 
is_debug_force_special_bytes()1437 static bool is_debug_force_special_bytes() {
1438     int ret = 0;
1439     char value[PROPERTY_VALUE_MAX] = {'\0'};
1440     bool enabled = false;
1441 #ifdef ENABLE_DBG_FLAGS
1442     enabled = true;
1443 #endif
1444 
1445     ret = property_get("wc_transport.force_special_byte", value, NULL);
1446 
1447     if (ret) {
1448         enabled = (strcmp(value, "false") ==0) ? false : true;
1449         ALOGV("%s: wc_transport.force_special_byte: %s, enabled: %d ",
1450             __func__, value, enabled);
1451     }
1452 
1453     return enabled;
1454 }
1455 
1456 // Entry point of DLib
1457 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
1458     sizeof(bt_vendor_interface_t),
1459     init,
1460     op,
1461     cleanup,
1462     ssr_cleanup
1463 };
1464