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