bt_vendor_qcom.c revision 5f13e7bfe2779a609ff7990cced19d3911825aea
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
27#define LOG_TAG "bt_vendor"
28#define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
29
30#include <utils/Log.h>
31#include <cutils/properties.h>
32#include <fcntl.h>
33#include <termios.h>
34#include "bt_vendor_qcom.h"
35#include "hci_uart.h"
36#include "hci_smd.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 12
45
46#ifdef PANIC_ON_SOC_CRASH
47#define BT_VND_FILTER_START "wc_transport.start_root"
48#else
49#define BT_VND_FILTER_START "wc_transport.start_hci"
50#endif
51
52#define CMD_TIMEOUT  0x22
53
54static void wait_for_patch_download(bool is_ant_req);
55
56/******************************************************************************
57**  Externs
58******************************************************************************/
59extern int hw_config(int nState);
60
61extern int is_hw_ready();
62extern int rome_soc_init(int fd, char *bdaddr);
63extern int check_embedded_mode(int fd);
64extern int rome_get_addon_feature_list(int fd);
65extern int rome_ver;
66extern int enable_controller_log(int fd, unsigned char req);
67/******************************************************************************
68**  Variables
69******************************************************************************/
70int pFd[2] = {0,};
71#ifdef BT_SOC_TYPE_ROME
72int ant_fd;
73#endif
74bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
75uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
76static int btSocType = BT_SOC_DEFAULT;
77static int rfkill_id = -1;
78static char *rfkill_state = NULL;
79bool enable_extldo = FALSE;
80
81int userial_clock_operation(int fd, int cmd);
82int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti);
83int rome_soc_init(int fd, char *bdaddr);
84int userial_vendor_get_baud(void);
85int readTrpState();
86void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity);
87
88static const tUSERIAL_CFG userial_init_cfg =
89{
90    (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
91    USERIAL_BAUD_115200
92};
93
94#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
95void hw_epilog_process(void);
96#endif
97
98#ifdef WIFI_BT_STATUS_SYNC
99#include <string.h>
100#include <errno.h>
101#include <dlfcn.h>
102#include "cutils/properties.h"
103
104static const char WIFI_PROP_NAME[]    = "wlan.driver.status";
105static const char SERVICE_PROP_NAME[]    = "bluetooth.hsic_ctrl";
106static const char BT_STATUS_NAME[]    = "bluetooth.enabled";
107static const char WIFI_SERVICE_PROP[] = "wlan.hsic_ctrl";
108
109#define WIFI_BT_STATUS_LOCK    "/data/connectivity/wifi_bt_lock"
110int isInit=0;
111#endif /* WIFI_BT_STATUS_SYNC */
112bool is_soc_initialized(void);
113
114/******************************************************************************
115**  Local type definitions
116******************************************************************************/
117
118
119/******************************************************************************
120**  Functions
121******************************************************************************/
122#ifdef WIFI_BT_STATUS_SYNC
123int bt_semaphore_create(void)
124{
125    int fd;
126
127    fd = open(WIFI_BT_STATUS_LOCK, O_RDONLY);
128
129    if (fd < 0)
130        ALOGE("can't create file\n");
131
132    return fd;
133}
134
135int bt_semaphore_get(int fd)
136{
137    int ret;
138
139    if (fd < 0)
140        return -1;
141
142    ret = flock(fd, LOCK_EX);
143    if (ret != 0) {
144        ALOGE("can't hold lock: %s\n", strerror(errno));
145        return -1;
146    }
147
148    return ret;
149}
150
151int bt_semaphore_release(int fd)
152{
153    int ret;
154
155    if (fd < 0)
156        return -1;
157
158    ret = flock(fd, LOCK_UN);
159    if (ret != 0) {
160        ALOGE("can't release lock: %s\n", strerror(errno));
161        return -1;
162    }
163
164    return ret;
165}
166
167int bt_semaphore_destroy(int fd)
168{
169    if (fd < 0)
170        return -1;
171
172    return close (fd);
173}
174
175int bt_wait_for_service_done(void)
176{
177    char service_status[PROPERTY_VALUE_MAX];
178    int count = 30;
179
180    ALOGE("%s: check\n", __func__);
181
182    /* wait for service done */
183    while (count-- > 0) {
184        property_get(WIFI_SERVICE_PROP, service_status, NULL);
185
186        if (strcmp(service_status, "") != 0) {
187            usleep(200000);
188        } else {
189            break;
190        }
191    }
192
193    return 0;
194}
195
196#endif /* WIFI_BT_STATUS_SYNC */
197
198/** Get Bluetooth SoC type from system setting */
199static int get_bt_soc_type()
200{
201    int ret = 0;
202    char bt_soc_type[PROPERTY_VALUE_MAX];
203
204    ALOGI("bt-vendor : get_bt_soc_type");
205
206    ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
207    if (ret != 0) {
208        ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
209        if (!strncasecmp(bt_soc_type, "rome", sizeof("rome"))) {
210            return BT_SOC_ROME;
211        }
212        else if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) {
213            return BT_SOC_AR3K;
214        }
215        else {
216            ALOGI("qcom.bluetooth.soc not set, so using default.\n");
217            return BT_SOC_DEFAULT;
218        }
219    }
220    else {
221        ALOGE("%s: Failed to get soc type", __FUNCTION__);
222        ret = BT_SOC_DEFAULT;
223    }
224
225    return ret;
226}
227
228bool can_perform_action(char action) {
229    bool can_perform = false;
230    char ref_count[PROPERTY_VALUE_MAX];
231    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
232    int value, ret;
233
234    property_get("wc_transport.ref_count", ref_count, "0");
235
236    value = atoi(ref_count);
237    ALOGV("%s: ref_count: %s\n",__func__,  ref_count);
238
239    if(action == '1') {
240        ALOGV("%s: on : value is: %d", __func__, value);
241        if(value == 1)
242        {
243          property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
244          if((is_soc_initialized() == true) || (strcmp(inProgress,"null") != 0))
245          {
246            value++;
247            ALOGV("%s: on : value is incremented to : %d", __func__, value);
248          }
249        }
250        else
251        {
252             value++;
253        }
254
255        if (value == 1)
256           can_perform = true;
257        else if (value > 2)
258           return false;
259    }
260    else {
261        ALOGV("%s: off : value is: %d", __func__, value);
262        value--;
263        if (value == 0)
264           can_perform = true;
265        else if (value < 0)
266           return false;
267    }
268
269    snprintf(ref_count, 3, "%d", value);
270    ALOGV("%s: updated ref_count is: %s", __func__, ref_count);
271
272    ret  = property_set("wc_transport.ref_count", ref_count);
273    if (ret < 0) {
274        ALOGE("%s: Error while updating property: %d\n", __func__, ret);
275        return false;
276    }
277    ALOGV("%s returning %d", __func__, can_perform);
278    return can_perform;
279}
280
281void stop_hci_filter() {
282       char value[PROPERTY_VALUE_MAX] = {'\0'};
283       ALOGV("%s: Entry ", __func__);
284
285       property_get(BT_VND_FILTER_START, value, "false");
286
287       if (strcmp(value, "false") == 0) {
288           ALOGI("%s: hci_filter has been stopped already", __func__);
289//           return;
290       }
291
292       property_set(BT_VND_FILTER_START, "false");
293       property_set("wc_transport.hci_filter_status", "0");
294       ALOGV("%s: Exit ", __func__);
295}
296
297void start_hci_filter() {
298       ALOGV("%s: Entry ", __func__);
299       int i, init_success = 0;
300       char value[PROPERTY_VALUE_MAX] = {'\0'};
301
302       property_get(BT_VND_FILTER_START, value, false);
303
304       if (strcmp(value, "true") == 0) {
305           ALOGI("%s: hci_filter has been started already", __func__);
306           return;
307       }
308
309       property_set("wc_transport.hci_filter_status", "0");
310       property_set(BT_VND_FILTER_START, "true");
311
312       ALOGV("%s: %s set to true ", __func__, BT_VND_FILTER_START );
313
314       //sched_yield();
315       for(i=0; i<45; i++) {
316          property_get("wc_transport.hci_filter_status", value, "0");
317          if (strcmp(value, "1") == 0) {
318               init_success = 1;
319               break;
320           } else {
321               usleep(WAIT_TIMEOUT);
322           }
323        }
324        ALOGV("start_hcifilter status:%d after %f seconds \n", init_success, 0.2*i);
325
326        ALOGV("%s: Exit ", __func__);
327}
328
329/** Bluetooth Controller power up or shutdown */
330static int bt_powerup(int en )
331{
332    char rfkill_type[64], *enable_ldo_path = NULL;
333    char type[16], enable_ldo[6];
334    int fd, size, i, ret, fd_ldo;
335
336    char disable[PROPERTY_VALUE_MAX];
337    char state;
338    char on = (en)?'1':'0';
339
340#ifdef WIFI_BT_STATUS_SYNC
341    char wifi_status[PROPERTY_VALUE_MAX];
342    int lock_fd;
343#endif /*WIFI_BT_STATUS_SYNC*/
344
345    ALOGI("bt_powerup: %c", on);
346
347    /* Check if rfkill has been disabled */
348    ret = property_get("ro.rfkilldisabled", disable, "0");
349    if (!ret ){
350        ALOGE("Couldn't get ro.rfkilldisabled (%d)", ret);
351        return -1;
352    }
353    /* In case rfkill disabled, then no control power*/
354    if (strcmp(disable, "1") == 0) {
355        ALOGI("ro.rfkilldisabled : %s", disable);
356        return -1;
357    }
358
359#ifdef WIFI_BT_STATUS_SYNC
360    lock_fd = bt_semaphore_create();
361    bt_semaphore_get(lock_fd);
362    bt_wait_for_service_done();
363#endif
364
365    /* Assign rfkill_id and find bluetooth rfkill state path*/
366    for(i=0;(rfkill_id == -1) && (rfkill_state == NULL);i++)
367    {
368        snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
369        if ((fd = open(rfkill_type, O_RDONLY)) < 0)
370        {
371            ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
372
373#ifdef WIFI_BT_STATUS_SYNC
374            bt_semaphore_release(lock_fd);
375            bt_semaphore_destroy(lock_fd);
376#endif
377            return -1;
378        }
379
380        size = read(fd, &type, sizeof(type));
381        close(fd);
382
383        if ((size >= 9) && !memcmp(type, "bluetooth", 9))
384        {
385            asprintf(&rfkill_state, "/sys/class/rfkill/rfkill%d/state", rfkill_id = i);
386            break;
387        }
388    }
389
390    /* Get rfkill State to control */
391    if (rfkill_state != NULL)
392    {
393        if ((fd = open(rfkill_state, O_RDWR)) < 0)
394        {
395            ALOGE("open(%s) for write failed: %s (%d)",rfkill_state, strerror(errno), errno);
396#ifdef WIFI_BT_STATUS_SYNC
397            bt_semaphore_release(lock_fd);
398            bt_semaphore_destroy(lock_fd);
399#endif
400
401            return -1;
402        }
403    }
404#ifdef BT_SOC_TYPE_ROME
405    if(can_perform_action(on) == false) {
406        ALOGE("%s:can't perform action as it is being used by other clients", __func__);
407#ifdef WIFI_BT_STATUS_SYNC
408        bt_semaphore_release(lock_fd);
409        bt_semaphore_destroy(lock_fd);
410#endif
411        goto done;
412    }
413#endif
414    ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", rfkill_id);
415    if( (ret < 0 ) || (enable_ldo_path == NULL) )
416    {
417        ALOGE("Memory Allocation failure");
418        return -1;
419    }
420    if ((fd_ldo = open(enable_ldo_path, O_RDWR)) < 0) {
421        ALOGE("open(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
422        return -1;
423    }
424    size = read(fd_ldo, &enable_ldo, sizeof(enable_ldo));
425    close(fd_ldo);
426    if (size <= 0) {
427        ALOGE("read(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
428        return -1;
429    }
430    if (!memcmp(enable_ldo, "true", 4)) {
431        ALOGI("External LDO has been configured");
432        enable_extldo = TRUE;
433    }
434
435    ALOGE("Write %c to rfkill\n", on);
436
437    /* Write value to control rfkill */
438    if ((size = write(fd, &on, 1)) < 0) {
439        ALOGE("write(%s) failed: %s (%d)",rfkill_state, strerror(errno),errno);
440#ifdef WIFI_BT_STATUS_SYNC
441        bt_semaphore_release(lock_fd);
442        bt_semaphore_destroy(lock_fd);
443#endif
444        return -1;
445    }
446#ifdef BT_SOC_TYPE_ROME
447    if(on == '0'){
448        ALOGE("Stopping HCI filter as part of CTRL:OFF");
449        stop_hci_filter();
450        property_set("wc_transport.soc_initialized", "0");
451    }
452#endif
453#ifdef WIFI_BT_STATUS_SYNC
454    /* query wifi status */
455    property_get(WIFI_PROP_NAME, wifi_status, "");
456
457    ALOGE("bt get wifi status: %s, isInit: %d\n",  wifi_status, isInit);
458
459    /* If wlan driver is not loaded, and bt is changed from off => on */
460    if (strncmp(wifi_status, "unloaded", strlen("unloaded")) == 0 || strlen(wifi_status) == 0) {
461        if (on == '1') {
462            ALOGI("%s: BT_VND_PWR_ON\n", __func__);
463            if(property_set(SERVICE_PROP_NAME, "load_wlan") < 0) {
464                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
465                close(fd);
466                bt_semaphore_release(lock_fd);
467                bt_semaphore_destroy(lock_fd);
468                return -1;
469            }
470        }
471        else if (isInit == 0 && on == '0') {
472            ALOGI("%s: BT_VND_PWR_OFF\n", __func__);
473            if(property_set(SERVICE_PROP_NAME, "unbind_hsic") < 0) {
474                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
475                close(fd);
476                bt_semaphore_release(lock_fd);
477                bt_semaphore_destroy(lock_fd);
478                return -1;
479            }
480       }
481    }
482
483    if (isInit == 0 && on == '0')
484        property_set(BT_STATUS_NAME, "false");
485    else if (on == '1')
486        property_set(BT_STATUS_NAME, "true");
487
488    bt_semaphore_release(lock_fd);
489    bt_semaphore_destroy(lock_fd);
490#endif /* WIFI_BT_STATUS_SYNC */
491
492done:
493    if (fd >= 0)
494        close(fd);
495
496    return 0;
497}
498
499/*****************************************************************************
500**
501**   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
502**
503*****************************************************************************/
504
505static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
506{
507    int i;
508
509    ALOGI("bt-vendor : init");
510
511    if (p_cb == NULL)
512    {
513        ALOGE("init failed with no user callbacks!");
514        return -1;
515    }
516
517    if ((btSocType = get_bt_soc_type()) < 0) {
518        ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
519        return -1;
520    }
521
522    switch(btSocType)
523    {
524        case BT_SOC_ROME:
525        case BT_SOC_AR3K:
526            ALOGI("bt-vendor : Initializing UART transport layer");
527            userial_vendor_init();
528            break;
529        case BT_SOC_DEFAULT:
530            break;
531        default:
532            ALOGE("Unknown btSocType: 0x%x", btSocType);
533            break;
534    }
535
536    /* store reference to user callbacks */
537    bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;
538
539    /* Copy BD Address as little-endian byte order */
540    if(local_bdaddr)
541        for(i=0;i<6;i++)
542            vnd_local_bd_addr[i] = *(local_bdaddr + (5-i));
543
544    ALOGI("%s: Local BD Address : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", __FUNCTION__,
545                                                vnd_local_bd_addr[0],
546                                                vnd_local_bd_addr[1],
547                                                vnd_local_bd_addr[2],
548                                                vnd_local_bd_addr[3],
549                                                vnd_local_bd_addr[4],
550                                                vnd_local_bd_addr[5]);
551
552#ifdef WIFI_BT_STATUS_SYNC
553    isInit = 1;
554#endif /* WIFI_BT_STATUS_SYNC */
555
556    return 0;
557}
558
559#ifdef READ_BT_ADDR_FROM_PROP
560static bool validate_tok(char* bdaddr_tok) {
561    int i = 0;
562    bool ret;
563
564    if (strlen(bdaddr_tok) != 2) {
565        ret = FALSE;
566        ALOGE("Invalid token length");
567    } else {
568        ret = TRUE;
569        for (i=0; i<2; i++) {
570            if ((bdaddr_tok[i] >= '0' && bdaddr_tok[i] <= '9') ||
571                (bdaddr_tok[i] >= 'A' && bdaddr_tok[i] <= 'F') ||
572                (bdaddr_tok[i] >= 'a' && bdaddr_tok[i] <= 'f')) {
573                ret = TRUE;
574                ALOGV("%s: tok %s @ %d is good", __func__, bdaddr_tok, i);
575             } else {
576                ret = FALSE;
577                ALOGE("invalid character in tok: %s at ind: %d", bdaddr_tok, i);
578                break;
579             }
580        }
581    }
582    return ret;
583}
584#endif /*READ_BT_ADDR_FROM_PROP*/
585
586int connect_to_local_socket(char* name) {
587       socklen_t len; int sk = -1;
588
589       ALOGE("%s: ACCEPT ", __func__);
590       sk  = socket(AF_LOCAL, SOCK_STREAM, 0);
591       if (sk < 0) {
592           ALOGE("Socket creation failure");
593           return -1;
594       }
595
596        if(socket_local_client_connect(sk, name,
597            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
598        {
599             ALOGE("failed to connect (%s)", strerror(errno));
600             close(sk);
601             sk = -1;
602        } else {
603                ALOGE("%s: Connection succeeded\n", __func__);
604        }
605        return sk;
606}
607
608bool is_soc_initialized() {
609    bool init = false;
610    char init_value[PROPERTY_VALUE_MAX];
611    int ret;
612
613    ALOGI("bt-vendor : is_soc_initialized");
614
615    ret = property_get("wc_transport.soc_initialized", init_value, NULL);
616    if (ret != 0) {
617        ALOGI("wc_transport.soc_initialized set to %s\n", init_value);
618        if (!strncasecmp(init_value, "1", sizeof("1"))) {
619            init = true;
620        }
621    }
622    else {
623        ALOGE("%s: Failed to get wc_transport.soc_initialized", __FUNCTION__);
624    }
625
626    return init;
627}
628
629
630/** Requested operations */
631static int op(bt_vendor_opcode_t opcode, void *param)
632{
633    int retval = 0;
634    int nCnt = 0;
635    int nState = -1;
636    bool is_ant_req = false;
637    char wipower_status[PROPERTY_VALUE_MAX];
638    char emb_wp_mode[PROPERTY_VALUE_MAX];
639    char bt_version[PROPERTY_VALUE_MAX];
640    bool ignore_boot_prop = TRUE;
641#ifdef READ_BT_ADDR_FROM_PROP
642    int i = 0;
643    static char bd_addr[PROPERTY_VALUE_MAX];
644    uint8_t local_bd_addr_from_prop[6];
645    char* tok;
646#endif
647    bool skip_init = true;
648    ALOGV("bt-vendor : op for %d", opcode);
649
650    switch(opcode)
651    {
652        case BT_VND_OP_POWER_CTRL:
653            {
654                nState = *(int *) param;
655                ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
656                        (nState == BT_VND_PWR_ON)? "On" : "Off" );
657
658                switch(btSocType)
659                {
660                    case BT_SOC_DEFAULT:
661                        if (readTrpState())
662                        {
663                           ALOGI("bt-vendor : resetting BT status");
664                           hw_config(BT_VND_PWR_OFF);
665                        }
666                        retval = hw_config(nState);
667                        if(nState == BT_VND_PWR_ON
668                           && retval == 0
669                           && is_hw_ready() == TRUE){
670                            retval = 0;
671                        }
672                        else {
673                            retval = -1;
674                        }
675                        break;
676                    case BT_SOC_ROME:
677                    case BT_SOC_AR3K:
678                        /* BT Chipset Power Control through Device Tree Node */
679                        retval = bt_powerup(nState);
680                    default:
681                        break;
682                }
683            }
684            break;
685
686        case BT_VND_OP_FW_CFG:
687            {
688                // call hciattach to initalize the stack
689                if(bt_vendor_cbacks){
690                   if (btSocType ==  BT_SOC_ROME) {
691                       if (is_soc_initialized()) {
692                           ALOGI("Bluetooth FW and transport layer are initialized");
693                           bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
694                       } else {
695                           ALOGE("bt_vendor_cbacks is null or SoC not initialized");
696                           ALOGE("Error : hci, smd initialization Error");
697                           retval = -1;
698                       }
699                   } else {
700                       ALOGI("Bluetooth FW and transport layer are initialized");
701                       bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
702                   }
703                }
704                else{
705                   ALOGE("bt_vendor_cbacks is null");
706                   ALOGE("Error : hci, smd initialization Error");
707                   retval = -1;
708                }
709            }
710            break;
711
712        case BT_VND_OP_SCO_CFG:
713            {
714                if (bt_vendor_cbacks)
715                    bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
716            }
717            break;
718#ifdef BT_SOC_TYPE_ROME
719#ifdef ENABLE_ANT
720        case BT_VND_OP_ANT_USERIAL_OPEN:
721                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
722                is_ant_req = true;
723                //fall through
724#endif
725
726#endif
727        case BT_VND_OP_USERIAL_OPEN:
728            {
729                int (*fd_array)[] = (int (*)[]) param;
730                int idx, fd;
731                ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
732                switch(btSocType)
733                {
734                    case BT_SOC_DEFAULT:
735                        {
736                            if(bt_hci_init_transport(pFd) != -1){
737                                int (*fd_array)[] = (int (*) []) param;
738
739                                    (*fd_array)[CH_CMD] = pFd[0];
740                                    (*fd_array)[CH_EVT] = pFd[0];
741                                    (*fd_array)[CH_ACL_OUT] = pFd[1];
742                                    (*fd_array)[CH_ACL_IN] = pFd[1];
743                            }
744                            else {
745                                retval = -1;
746                                break;
747                            }
748                            retval = 2;
749                        }
750                        break;
751                    case BT_SOC_AR3K:
752                        {
753                            fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
754                            if (fd != -1) {
755                                for (idx=0; idx < CH_MAX; idx++)
756                                    (*fd_array)[idx] = fd;
757                                     retval = 1;
758                            }
759                            else {
760                                retval = -1;
761                                break;
762                            }
763
764                            /* Vendor Specific Process should happened during userial_open process
765                                After userial_open, rx read thread is running immediately,
766                                so it will affect VS event read process.
767                            */
768                            if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
769                                retval = -1;
770                        }
771                        break;
772                    case BT_SOC_ROME:
773                        {
774                            wait_for_patch_download(is_ant_req);
775                            property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
776                            if (!is_soc_initialized()) {
777                                char* dlnd_inprog = is_ant_req ? "ant" : "bt";
778                                if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
779                                    ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
780                                }
781
782                                fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
783                                if (fd < 0) {
784                                    ALOGE("userial_vendor_open returns err");
785                                    retval = -1;
786                                } else {
787                                    /* Clock on */
788                                    userial_clock_operation(fd, USERIAL_OP_CLK_ON);
789                                    ALOGD("userial clock on");
790                                    if(strcmp(emb_wp_mode, "true") == 0) {
791                                        property_get("ro.bluetooth.wipower", wipower_status, false);
792                                        if(strcmp(wipower_status, "true") == 0) {
793                                            check_embedded_mode(fd);
794                                        } else {
795                                            ALOGI("Wipower not enabled");
796                                        }
797                                    }
798                                    ALOGV("rome_soc_init is started");
799                                    property_set("wc_transport.soc_initialized", "0");
800#ifdef READ_BT_ADDR_FROM_PROP
801                                    /*Give priority to read BD address from boot property*/
802                                    ignore_boot_prop = FALSE;
803                                    if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
804                                        ALOGV("BD address read from Boot property: %s\n", bd_addr);
805                                        tok =  strtok(bd_addr, ":");
806                                        while (tok != NULL) {
807                                            ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
808                                            if (i>=6) {
809                                                ALOGE("bd property of invalid length");
810                                                ignore_boot_prop = TRUE;
811                                                break;
812                                            }
813                                            if (!validate_tok(tok)) {
814                                                ALOGE("Invalid token in BD address");
815                                                ignore_boot_prop = TRUE;
816                                                break;
817                                            }
818                                            local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
819                                            tok = strtok(NULL, ":");
820                                            i++;
821                                        }
822                                        if (i == 6 && !ignore_boot_prop) {
823                                            ALOGV("Valid BD address read from prop");
824                                            memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
825                                            ignore_boot_prop = FALSE;
826                                        } else {
827                                            ALOGE("There are not enough tokens in BD addr");
828                                            ignore_boot_prop = TRUE;
829                                        }
830                                    } else {
831                                        ALOGE("BD address boot property not set");
832                                        ignore_boot_prop = TRUE;
833                                    }
834#endif //READ_BT_ADDR_FROM_PROP
835                                    /* Always read BD address from NV file */
836                                    if(ignore_boot_prop && !bt_vendor_nv_read(1, vnd_local_bd_addr))
837                                    {
838                                       /* Since the BD address is configured in boot time We should not be here */
839                                       ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
840                                    }
841                                    if(rome_soc_init(fd,vnd_local_bd_addr)<0) {
842                                        retval = -1;
843                                        userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
844                                    } else {
845                                        ALOGV("rome_soc_init is completed");
846                                        property_set("wc_transport.soc_initialized", "1");
847                                        userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
848                                        skip_init = false;
849                                        /*Close the UART port*/
850                                        close(fd);
851                                    }
852                                }
853                            }
854                            if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
855                                ALOGE("%s: Failed to set property", __FUNCTION__);
856                            }
857
858                            property_set("wc_transport.clean_up","0");
859                            if (retval != -1) {
860#ifdef BT_SOC_TYPE_ROME
861                                 start_hci_filter();
862                                 if (is_ant_req) {
863                                     ALOGV("connect to ant channel");
864                                     ant_fd = fd = connect_to_local_socket("ant_sock");
865                                 }
866                                 else
867#endif
868                                 {
869                                     ALOGV("connect to bt channel");
870                                     vnd_userial.fd = fd = connect_to_local_socket("bt_sock");
871                                 }
872
873                                 if (fd != -1) {
874                                     ALOGV("%s: received the socket fd: %d is_ant_req: %d\n",
875                                                                 __func__, fd, is_ant_req);
876                                     if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req) {
877                                         if (rome_ver >= ROME_VER_3_0) {
878                                             /*  get rome supported feature request */
879                                             ALOGE("%s: %x08 %0x", __FUNCTION__,rome_ver, ROME_VER_3_0);
880                                             rome_get_addon_feature_list(fd);
881                                         }
882                                     }
883                                     if (!skip_init) {
884                                         /*Skip if already sent*/
885                                         enable_controller_log(fd, is_ant_req);
886                                         skip_init = true;
887                                     }
888                                     for (idx=0; idx < CH_MAX; idx++)
889                                          (*fd_array)[idx] = fd;
890                                          retval = 1;
891                                     }
892                                 else {
893                                     retval = -1;
894                                 }
895                             } else {
896                               if (fd >= 0)
897                                  close(fd);
898                             }
899                        }
900                        break;
901                    default:
902                        ALOGE("Unknown btSocType: 0x%x", btSocType);
903                        break;
904                }
905            }
906            break;
907#ifdef BT_SOC_TYPE_ROME
908#ifdef ENABLE_ANT
909        case BT_VND_OP_ANT_USERIAL_CLOSE:
910            {
911                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
912                property_set("wc_transport.clean_up","1");
913                if (ant_fd != -1) {
914                    ALOGE("closing ant_fd");
915                    close(ant_fd);
916                    ant_fd = -1;
917                }
918            }
919            break;
920#endif
921#endif
922        case BT_VND_OP_USERIAL_CLOSE:
923            {
924                ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE btSocType: %d", btSocType);
925                switch(btSocType)
926                {
927                    case BT_SOC_DEFAULT:
928                         bt_hci_deinit_transport(pFd);
929                         break;
930
931                     case BT_SOC_ROME:
932                     case BT_SOC_AR3K:
933                        property_set("wc_transport.clean_up","1");
934                        userial_vendor_close();
935                        break;
936                    default:
937                        ALOGE("Unknown btSocType: 0x%x", btSocType);
938                        break;
939                }
940            }
941            break;
942
943        case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
944            if (btSocType ==  BT_SOC_AR3K) {
945                uint32_t *timeout_ms = (uint32_t *) param;
946                *timeout_ms = 1000;
947            }
948            break;
949
950        case BT_VND_OP_LPM_SET_MODE:
951            if(btSocType ==  BT_SOC_AR3K) {
952                uint8_t *mode = (uint8_t *) param;
953
954                if (*mode) {
955                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
956                }
957                else {
958                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
959                }
960                if (bt_vendor_cbacks )
961                    bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
962            }
963            else {
964                // respond with failure as it's already handled by other mechanism
965                if (bt_vendor_cbacks)
966                    bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
967            }
968            break;
969
970        case BT_VND_OP_LPM_WAKE_SET_STATE:
971            {
972                switch(btSocType)
973                {
974                    case BT_SOC_ROME:
975                        {
976                            uint8_t *state = (uint8_t *) param;
977                            uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
978                                BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
979
980                            if (wake_assert == 0)
981                                ALOGV("ASSERT: Waking up BT-Device");
982                            else if (wake_assert == 1)
983                                ALOGV("DEASSERT: Allowing BT-Device to Sleep");
984
985#ifdef QCOM_BT_SIBS_ENABLE
986                            if(bt_vendor_cbacks){
987                                ALOGI("Invoking HCI H4 callback function");
988                               bt_vendor_cbacks->lpm_set_state_cb(wake_assert);
989                            }
990#endif
991                        }
992                        break;
993                    case BT_SOC_AR3K:
994                        {
995                            uint8_t *state = (uint8_t *) param;
996                            uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
997                                                        UPIO_ASSERT : UPIO_DEASSERT;
998                            lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
999                        }
1000                    case BT_SOC_DEFAULT:
1001                        break;
1002                    default:
1003                        ALOGE("Unknown btSocType: 0x%x", btSocType);
1004                        break;
1005                    }
1006            }
1007            break;
1008        case BT_VND_OP_EPILOG:
1009            {
1010#if (HW_NEED_END_WITH_HCI_RESET == FALSE)
1011                if (bt_vendor_cbacks)
1012                {
1013                    bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1014                }
1015#else
1016                switch(btSocType)
1017                {
1018                  case BT_SOC_ROME:
1019                       {
1020                           char value[PROPERTY_VALUE_MAX] = {'\0'};
1021                           property_get("wc_transport.hci_filter_status", value, "0");
1022                           if(is_soc_initialized()&& (strcmp(value,"1") == 0))
1023                           {
1024                              hw_epilog_process();
1025                           }
1026                           else
1027                           {
1028                             if (bt_vendor_cbacks)
1029                               {
1030                                 ALOGE("vendor lib epilog process aborted");
1031                                 bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1032                               }
1033                           }
1034                       }
1035                       break;
1036                  default:
1037                       hw_epilog_process();
1038                       break;
1039                }
1040#endif
1041            }
1042            break;
1043        case BT_VND_OP_GET_LINESPEED:
1044            {
1045                retval = -1;
1046                switch(btSocType)
1047                {
1048                    case BT_SOC_ROME:
1049                        if(!is_soc_initialized()) {
1050                            ALOGE("BT_VND_OP_GET_LINESPEED: error"
1051                            " - transport driver not initialized!");
1052                        }else {
1053                            retval = 3000000;
1054                        }
1055                        break;
1056                    default:
1057                        retval = userial_vendor_get_baud();
1058                        break;
1059                 }
1060                break;
1061            }
1062    }
1063
1064    return retval;
1065}
1066
1067static void ssr_cleanup(int reason) {
1068    int pwr_state=BT_VND_PWR_OFF;
1069    int ret;
1070    unsigned char trig_ssr = 0xEE;
1071    ALOGI("ssr_cleanup");
1072    if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
1073        ALOGE("%s: Failed to set property", __FUNCTION__);
1074    }
1075
1076    if ((btSocType = get_bt_soc_type()) < 0) {
1077        ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
1078        return -1;
1079    }
1080
1081    if (btSocType == BT_SOC_ROME) {
1082#ifdef BT_SOC_TYPE_ROME
1083#ifdef ENABLE_ANT
1084        //Indicate to filter by sending
1085        //special byte
1086        if (reason == CMD_TIMEOUT) {
1087            trig_ssr = 0xEE;
1088            ret = write (vnd_userial.fd, &trig_ssr, 1);
1089            ALOGI("Trig_ssr is being sent to BT socket, retval(%d) :errno:  %s", ret, strerror(errno));
1090            return;
1091        }
1092        /*Close both ANT channel*/
1093        op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
1094#endif
1095#endif
1096        /*Close both ANT channel*/
1097        op(BT_VND_OP_USERIAL_CLOSE, NULL);
1098        /*CTRL OFF twice to make sure hw
1099         * turns off*/
1100#ifdef ENABLE_ANT
1101        op(BT_VND_OP_POWER_CTRL, &pwr_state);
1102#endif
1103
1104    }
1105#ifdef BT_SOC_TYPE_ROME
1106    /*Generally switching of chip should be enough*/
1107    op(BT_VND_OP_POWER_CTRL, &pwr_state);
1108#endif
1109}
1110
1111
1112/** Closes the interface */
1113static void cleanup( void )
1114{
1115    ALOGI("cleanup");
1116    bt_vendor_cbacks = NULL;
1117
1118#ifdef WIFI_BT_STATUS_SYNC
1119    isInit = 0;
1120#endif /* WIFI_BT_STATUS_SYNC */
1121}
1122
1123/* Check for one of the cients ANT/BT patch download is already in
1124** progress if yes wait till complete
1125*/
1126void wait_for_patch_download(bool is_ant_req) {
1127    ALOGV("%s:", __FUNCTION__);
1128    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1129    while (1) {
1130        property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1131
1132        if(is_ant_req && !strcmp(inProgress,"bt") ) {
1133           //ANT request, wait for BT to finish
1134           usleep(50000);
1135        }
1136        else if(!is_ant_req && !strcmp(inProgress,"ant") ) {
1137           //BT request, wait for ANT to finish
1138           usleep(50000);
1139        }
1140        else {
1141           ALOGI("%s: patch download completed", __FUNCTION__);
1142           break;
1143        }
1144    }
1145}
1146
1147// Entry point of DLib
1148const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
1149    sizeof(bt_vendor_interface_t),
1150    init,
1151    op,
1152    cleanup,
1153    ssr_cleanup
1154};
1155