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            property_set("wc_transport.clean_up","0");
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 = (bt_vendor_callbacks_t*)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 #ifdef BT_NV_SUPPORT
961                                     /* Always read BD address from NV file */
962                                 if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
963                                 {
964                                    /* Since the BD address is configured in boot time We should not be here */
965                                    ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
966                                 }
967 #endif //BT_NV_SUPPORT
968                                 if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
969                                     retval = -1;
970                                 } else {
971                                     ALOGV("rome_soc_init is completed");
972                                     property_set("wc_transport.soc_initialized", "1");
973                                     skip_init = false;
974                                 }
975                             }
976                             if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
977                                 ALOGE("%s: Failed to set property", __FUNCTION__);
978                             }
979 
980                             property_set("wc_transport.clean_up","0");
981                             if (retval != -1) {
982 
983                                 retval = start_hci_filter();
984                                 if (retval < 0) {
985                                     ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
986                                 } else {
987 #ifdef ENABLE_ANT
988                                     if (is_ant_req) {
989                                         ALOGI("%s: connect to ant channel", __func__);
990                                         q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
991                                     }
992                                     else
993 #endif
994                                     {
995                                         ALOGI("%s: connect to bt channel", __func__);
996                                         vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
997                                     }
998 
999                                     if (fd_filter != -1) {
1000                                         ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
1001                                                              __func__, fd_filter, is_ant_req,is_fm_req);
1002                                         if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
1003                                              if (chipset_ver >= ROME_VER_3_0) {
1004                                                 /* get rome supported feature request */
1005                                                 ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
1006                                                 rome_get_addon_feature_list(fd_filter);
1007                                             }
1008                                         }
1009                                         if (!skip_init) {
1010                                             /*Skip if already sent*/
1011                                             enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
1012                                             skip_init = true;
1013                                         }
1014                                         for (idx=0; idx < CH_MAX; idx++)
1015                                             (*fd_array)[idx] = fd_filter;
1016                                             retval = 1;
1017                                     }
1018                                     else {
1019                                         if (is_ant_req)
1020                                             ALOGE("Unable to connect to ANT Server Socket!!!");
1021                                         else
1022                                             ALOGE("Unable to connect to BT Server Socket!!!");
1023                                         retval = -1;
1024                                     }
1025                                 }
1026                             } else {
1027                                 if (q->soc_type == BT_SOC_ROME)
1028                                     ALOGE("Failed to initialize ROME Controller!!!");
1029                             }
1030 
1031                             if (fd >= 0) {
1032                                 userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
1033                                  /*Close the UART port*/
1034                                  close(fd);
1035                             }
1036                         }
1037                         break;
1038                     case BT_SOC_CHEROKEE:
1039                         {
1040                             property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
1041                             retval = start_hci_filter();
1042                             if (retval < 0) {
1043                                 ALOGE("WCNSS_FILTER wouldn't have started in time\n");
1044                                 /*
1045                                  Set the following property to -1 so that the SSR cleanup routine
1046                                  can reset SOC.
1047                                  */
1048                                 property_set("wc_transport.hci_filter_status", "-1");
1049                             } else {
1050 #ifdef ENABLE_ANT
1051                                 if (is_ant_req) {
1052                                     ALOGI("%s: connect to ant channel", __func__);
1053                                     q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
1054                                 }
1055                                 else
1056 #endif
1057 #ifdef FM_OVER_UART
1058                                 if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
1059                                     ALOGI("%s: connect to fm channel", __func__);
1060                                     q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
1061                                 }
1062                                 else
1063 #endif
1064                                 {
1065                                     ALOGI("%s: connect to bt channel", __func__);
1066                                     vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
1067 
1068                                 }
1069                                 if (fd_filter != -1) {
1070                                     ALOGV("%s: received the socket fd: %d \n",
1071                                                              __func__, fd_filter);
1072 
1073                                     for (idx=0; idx < CH_MAX; idx++) {
1074                                         (*fd_array)[idx] = fd_filter;
1075                                     }
1076                                     retval = 1;
1077                                 }
1078                                 else {
1079 #ifdef ENABLE_ANT
1080                                     if (is_ant_req)
1081                                         ALOGE("Unable to connect to ANT Server Socket!!!");
1082                                     else
1083 #endif
1084 #ifdef FM_OVER_UART
1085                                     if (is_fm_req)
1086                                         ALOGE("Unable to connect to FM Server Socket!!!");
1087                                     else
1088 #endif
1089                                         ALOGE("Unable to connect to BT Server Socket!!!");
1090                                     retval = -1;
1091                                 }
1092                             }
1093                         }
1094                         break;
1095                     default:
1096                         ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1097                         break;
1098                   }
1099             } break;
1100 #ifdef ENABLE_ANT
1101         case BT_VND_OP_ANT_USERIAL_CLOSE:
1102             {
1103                 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
1104                 property_set("wc_transport.clean_up","1");
1105                 if (q->ant_fd != -1) {
1106                     ALOGE("closing ant_fd");
1107                     close(q->ant_fd);
1108                     q->ant_fd = -1;
1109                 }
1110             }
1111             break;
1112 #endif
1113 #ifdef FM_OVER_UART
1114         case BT_VND_OP_FM_USERIAL_CLOSE:
1115             {
1116                 ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
1117                 property_set("wc_transport.clean_up","1");
1118                 if (q->fm_fd != -1) {
1119                     ALOGE("closing fm_fd");
1120                     close(q->fm_fd);
1121                     q->fm_fd = -1;
1122                 }
1123                 break;
1124             }
1125 #endif
1126         case BT_VND_OP_USERIAL_CLOSE:
1127             {
1128                 ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
1129                 switch(q->soc_type)
1130                 {
1131                     case BT_SOC_DEFAULT:
1132                         bt_hci_deinit_transport(q->fd);
1133                         break;
1134                     case BT_SOC_ROME:
1135                     case BT_SOC_AR3K:
1136                     case BT_SOC_CHEROKEE:
1137                     {
1138                         property_set("wc_transport.clean_up","1");
1139                         userial_vendor_close();
1140                         break;
1141                     }
1142                     default:
1143                         ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1144                         break;
1145                 }
1146             }
1147             break;
1148 
1149         case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
1150             {
1151                 if (!param) {
1152                     ALOGE("opcode = %d: param is null", opcode_init);
1153                     break;
1154                 }
1155                 uint32_t *timeout_ms = (uint32_t *) param;
1156                 *timeout_ms = 1000;
1157             }
1158 
1159             break;
1160 
1161         case BT_VND_OP_LPM_SET_MODE:
1162             if (q->soc_type == BT_SOC_AR3K) {
1163                 if (!param) {
1164                     ALOGE("opcode = %d: param is null", opcode_init);
1165                     break;
1166                 }
1167                 uint8_t *mode = (uint8_t *) param;
1168 
1169                 if (*mode) {
1170                     lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1171                 }
1172                 else {
1173                     lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1174                 }
1175                 q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
1176             } else {
1177                 int lpm_result = BT_VND_OP_RESULT_SUCCESS;
1178 
1179                 property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
1180                 ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
1181                             __func__, lpm_config);
1182 
1183                 if (!strcmp(lpm_config, "all")) {
1184                     // respond with success since we want to hold wake lock through LPM
1185                     lpm_result = BT_VND_OP_RESULT_SUCCESS;
1186                 }
1187                 else {
1188                     lpm_result = BT_VND_OP_RESULT_FAIL;
1189                 }
1190 
1191                 q->cb->lpm_cb(lpm_result);
1192             }
1193             break;
1194 
1195         case BT_VND_OP_LPM_WAKE_SET_STATE: {
1196             switch(q->soc_type) {
1197             case BT_SOC_CHEROKEE:
1198             case BT_SOC_ROME: {
1199                 if (!param) {
1200                     ALOGE("opcode = %d: param is null", opcode_init);
1201                     break;
1202                 }
1203                 uint8_t *state = (uint8_t *) param;
1204                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1205                             BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
1206 
1207                 if (wake_assert == 0)
1208                     ALOGV("ASSERT: Waking up BT-Device");
1209                 else if (wake_assert == 1)
1210                     ALOGV("DEASSERT: Allowing BT-Device to Sleep");
1211 
1212 #ifdef QCOM_BT_SIBS_ENABLE
1213                 ALOGI("Invoking HCI H4 callback function");
1214                 q->cb->lpm_set_state_cb(wake_assert);
1215 #endif
1216             }
1217             break;
1218             case BT_SOC_AR3K: {
1219                 if (!param) {
1220                     ALOGE("opcode = %d: param is null", opcode_init);
1221                     break;
1222                 }
1223                 uint8_t *state = (uint8_t *) param;
1224                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1225                                                 UPIO_ASSERT : UPIO_DEASSERT;
1226                 lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
1227             }
1228             case BT_SOC_DEFAULT:
1229                 break;
1230             default:
1231                 ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1232                 break;
1233             }
1234         }
1235             break;
1236         case BT_VND_OP_EPILOG: {
1237 #if (HW_NEED_END_WITH_HCI_RESET == FALSE)
1238             q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1239 #else
1240                 switch(q->soc_type)
1241                 {
1242                   case BT_SOC_CHEROKEE:
1243                   case BT_SOC_ROME:
1244                        {
1245                            char value[PROPERTY_VALUE_MAX] = {'\0'};
1246                            property_get("wc_transport.hci_filter_status", value, "0");
1247                            if(is_soc_initialized()&& (strcmp(value,"1") == 0))
1248                            {
1249                               __hw_epilog_process();
1250                            }
1251                            else
1252                            {
1253                                 q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1254                            }
1255                        }
1256                        break;
1257                   default:
1258                        __hw_epilog_process();
1259                        break;
1260                 }
1261 #endif
1262             }
1263             break;
1264         case BT_VND_OP_GET_LINESPEED:
1265             {
1266                 retval = -1;
1267                 if(!is_soc_initialized()) {
1268                      ALOGE("BT_VND_OP_GET_LINESPEED: error"
1269                          " - transport driver not initialized!");
1270                      break;
1271                 }
1272 
1273                 switch(q->soc_type)
1274                 {
1275                     case BT_SOC_CHEROKEE:
1276                             retval = 3200000;
1277                         break;
1278                     case BT_SOC_ROME:
1279                             retval = 3000000;
1280                         break;
1281                     default:
1282                         retval = userial_vendor_get_baud();
1283                         break;
1284                  }
1285                 break;
1286             }
1287     }
1288 
1289 out:
1290     ALOGV("--%s", __FUNCTION__);
1291     return retval;
1292 }
1293 
ssr_cleanup(int reason)1294 static void ssr_cleanup(int reason)
1295 {
1296     int pwr_state = BT_VND_PWR_OFF;
1297     int ret;
1298     unsigned char trig_ssr = 0xEE;
1299 #ifndef ENABLE_ANT
1300     (void)reason;  // unused
1301 #endif
1302 
1303     ALOGI("++%s", __FUNCTION__);
1304 
1305     pthread_mutex_lock(&q_lock);
1306     if (!q) {
1307         ALOGE("ssr_cleanup called with NULL context");
1308         goto out;
1309     }
1310     if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
1311         ALOGE("Failed to set property");
1312     }
1313 
1314     if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) {
1315 #ifdef ENABLE_ANT
1316         /*Indicate to filter by sending special byte */
1317         if (reason == CMD_TIMEOUT) {
1318             trig_ssr = 0xEE;
1319             ret = write (vnd_userial.fd, &trig_ssr, 1);
1320             ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s",
1321                         ret, strerror(errno));
1322 
1323             if (is_debug_force_special_bytes()) {
1324                 /*
1325                  * Then we should send special byte to crash SOC in
1326                  * WCNSS_Filter, so we do not need to power off UART here.
1327                  */
1328                 goto out;
1329             }
1330         }
1331 
1332         /* Close both ANT channel */
1333         op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
1334 #endif
1335         /* Close both BT channel */
1336         op(BT_VND_OP_USERIAL_CLOSE, NULL);
1337 
1338 #ifdef FM_OVER_UART
1339         op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
1340 #endif
1341         /*CTRL OFF twice to make sure hw
1342          * turns off*/
1343 #ifdef ENABLE_ANT
1344         op(BT_VND_OP_POWER_CTRL, &pwr_state);
1345 #endif
1346     }
1347     /*Generally switching of chip should be enough*/
1348     op(BT_VND_OP_POWER_CTRL, &pwr_state);
1349 
1350 out:
1351     pthread_mutex_unlock(&q_lock);
1352     ALOGI("--%s", __FUNCTION__);
1353 }
1354 
1355 /** Closes the interface */
cleanup(void)1356 static void cleanup(void)
1357 {
1358     ALOGI("cleanup");
1359 
1360     pthread_mutex_lock(&q_lock);
1361     q->cb = NULL;
1362     free(q);
1363     q = NULL;
1364     pthread_mutex_unlock(&q_lock);
1365 
1366 #ifdef WIFI_BT_STATUS_SYNC
1367     isInit = 0;
1368 #endif /* WIFI_BT_STATUS_SYNC */
1369 }
1370 
1371 /* Check for one of the cients ANT/BT patch download is already in
1372 ** progress if yes wait till complete
1373 */
wait_for_patch_download(bool is_ant_req)1374 void wait_for_patch_download(bool is_ant_req) {
1375     ALOGV("%s:", __FUNCTION__);
1376     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1377     while (1) {
1378         property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1379 
1380         if(is_ant_req && !(strcmp(inProgress,"bt"))) {
1381            //ANT request, wait for BT to finish
1382            usleep(50000);
1383         }
1384         else if(!is_ant_req && !(strcmp(inProgress,"ant"))) {
1385           //BT request, wait for ANT to finish
1386            usleep(50000);
1387         }
1388         else {
1389            ALOGI("%s: patch download completed", __FUNCTION__);
1390            break;
1391         }
1392     }
1393 }
1394 
is_download_progress()1395 bool is_download_progress () {
1396     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1397     bool retval = false;
1398 
1399     ALOGV("%s:", __FUNCTION__);
1400 
1401     if ((q->soc_type = get_bt_soc_type()) < 0) {
1402         ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
1403         return -1;
1404     }
1405 
1406     switch(q->soc_type)
1407     {
1408         case BT_SOC_ROME:
1409             ALOGI("%s: ROME case", __func__);
1410             property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1411             if(strcmp(inProgress,"null") == 0) {
1412                 retval = false;
1413             } else {
1414                  retval = true;
1415             }
1416             break;
1417         case BT_SOC_CHEROKEE:
1418             ALOGI("%s: CHEROKEE case", __func__);
1419             break;
1420         case BT_SOC_DEFAULT:
1421             break;
1422         default:
1423             ALOGE("Unknown btSocType: 0x%x", q->soc_type);
1424             break;
1425     }
1426     return retval;
1427 }
1428 
is_debug_force_special_bytes()1429 static bool is_debug_force_special_bytes() {
1430     int ret = 0;
1431     char value[PROPERTY_VALUE_MAX] = {'\0'};
1432     bool enabled = false;
1433 #ifdef ENABLE_DBG_FLAGS
1434     enabled = true;
1435 #endif
1436 
1437     ret = property_get("wc_transport.force_special_byte", value, NULL);
1438 
1439     if (ret) {
1440         enabled = (strcmp(value, "false") ==0) ? false : true;
1441         ALOGV("%s: wc_transport.force_special_byte: %s, enabled: %d ",
1442             __func__, value, enabled);
1443     }
1444 
1445     return enabled;
1446 }
1447 
1448 // Entry point of DLib
1449 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
1450     sizeof(bt_vendor_interface_t),
1451     init,
1452     op,
1453     cleanup
1454 };
1455