diff options
author | Rupesh Tatiya <rtatiya@codeaurora.org> | 2016-07-20 15:17:01 +0530 |
---|---|---|
committer | Kamal Negi <kamaln@codeaurora.org> | 2016-08-23 12:21:33 +0530 |
commit | 574742a7fa955de8d32642c8061e2292698f5370 (patch) | |
tree | edc7643427193b95255a7a259a210e1ee7ac1b59 | |
parent | 2c5e7dcd7ff4d003479a2297e1caafceecbe0362 (diff) | |
download | android_hardware_qcom_sdm845_bt-574742a7fa955de8d32642c8061e2292698f5370.tar.gz android_hardware_qcom_sdm845_bt-574742a7fa955de8d32642c8061e2292698f5370.tar.bz2 android_hardware_qcom_sdm845_bt-574742a7fa955de8d32642c8061e2292698f5370.zip |
Make libbt-vendor thread-safe
The APIs provided to our clients can be called simultaneously resulting in
various race conditions. Make them thread-safe.
In addition, remove various global various and encapsulate them in a
context.
CRs-Fixed: 1010477
Change-Id: I8f145e3b2927ea75a0b65e0aa46b68d1b673d84e
-rw-r--r-- | libbt-vendor/include/bt_vendor_qcom.h | 25 | ||||
-rw-r--r-- | libbt-vendor/src/bt_vendor_qcom.c | 492 | ||||
-rw-r--r-- | libbt-vendor/src/hardware.c | 41 | ||||
-rw-r--r-- | libbt-vendor/src/hw_rome.c | 9 |
4 files changed, 299 insertions, 268 deletions
diff --git a/libbt-vendor/include/bt_vendor_qcom.h b/libbt-vendor/include/bt_vendor_qcom.h index fae931e..dd956cf 100644 --- a/libbt-vendor/include/bt_vendor_qcom.h +++ b/libbt-vendor/include/bt_vendor_qcom.h @@ -17,9 +17,8 @@ #ifndef BT_VENDOR_QCOM_H #define BT_VENDOR_QCOM_H +#include <stdbool.h> #include "bt_vendor_lib.h" -//#include "vnd_buildcfg.h" - #ifndef FALSE #define FALSE 0 @@ -48,7 +47,6 @@ typedef enum { BT_VND_OP_ANT_USERIAL_CLOSE }ant_serial; -extern bt_vendor_callbacks_t *bt_vendor_cbacks; /* HW_NEED_END_WITH_HCI_RESET code implementation of sending a HCI_RESET command during the epilog @@ -66,5 +64,26 @@ extern bt_vendor_callbacks_t *bt_vendor_cbacks; #define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 #define HCI_EVT_CMD_CMPL_OPCODE 3 +enum { + BT_STATUS_SUCCESS = 0, + BT_STATUS_FAIL, + BT_STATUS_INVAL, + BT_STATUS_NOMEM, +}; + +struct bt_qcom_struct { + int fd[2]; + int ant_fd; + int fm_fd; + bt_vendor_callbacks_t *cb; + uint8_t bdaddr[6]; + int soc_type; + int rfkill_id; + char *rfkill_state; + bool enable_extldo; +}; +extern struct bt_qcom_struct *q; +extern pthread_mutex_t q_lock; + #endif /* BT_VENDOR_QCOM_H */ diff --git a/libbt-vendor/src/bt_vendor_qcom.c b/libbt-vendor/src/bt_vendor_qcom.c index 36b9fee..09583d5 100644 --- a/libbt-vendor/src/bt_vendor_qcom.c +++ b/libbt-vendor/src/bt_vendor_qcom.c @@ -64,21 +64,8 @@ extern int chipset_ver; /****************************************************************************** ** Variables ******************************************************************************/ -int pFd[2] = {0,}; -#ifdef ENABLE_ANT -int ant_fd; -#endif -#ifdef FM_OVER_UART -int fm_fd; -#endif -bt_vendor_callbacks_t *bt_vendor_cbacks = NULL; - -uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -static int btSocType = BT_SOC_DEFAULT; -static int rfkill_id = -1; -static char *rfkill_state = NULL; -bool enable_extldo = FALSE; +struct bt_qcom_struct *q = NULL; +pthread_mutex_t q_lock = PTHREAD_MUTEX_INITIALIZER; int userial_clock_operation(int fd, int cmd); int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti); @@ -87,8 +74,6 @@ int readTrpState(); void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity); bool is_download_progress(); -pthread_mutex_t m_lock = PTHREAD_MUTEX_INITIALIZER; - static const tUSERIAL_CFG userial_init_cfg = { (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1), @@ -96,7 +81,7 @@ static const tUSERIAL_CFG userial_init_cfg = }; #if (HW_NEED_END_WITH_HCI_RESET == TRUE) -void hw_epilog_process(void); +void __hw_epilog_process(void); #endif #ifdef WIFI_BT_STATUS_SYNC @@ -383,7 +368,10 @@ int start_hci_filter() { return init_success; } -/** Bluetooth Controller power up or shutdown */ +/* + * Bluetooth Controller power up or shutdown, this function is called with + * q_lock held and q is non-NULL + */ static int bt_powerup(int en ) { char rfkill_type[64], *enable_ldo_path = NULL; @@ -420,7 +408,7 @@ static int bt_powerup(int en ) #endif /* Assign rfkill_id and find bluetooth rfkill state path*/ - for(i=0;(rfkill_id == -1) && (rfkill_state == NULL);i++) + for(i = 0; (q->rfkill_id == -1) && (q->rfkill_state == NULL); i++) { snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i); if ((fd = open(rfkill_type, O_RDONLY)) < 0) @@ -439,17 +427,17 @@ static int bt_powerup(int en ) if ((size >= 9) && !memcmp(type, "bluetooth", 9)) { - asprintf(&rfkill_state, "/sys/class/rfkill/rfkill%d/state", rfkill_id = i); + asprintf(&q->rfkill_state, "/sys/class/rfkill/rfkill%d/state", q->rfkill_id = i); break; } } /* Get rfkill State to control */ - if (rfkill_state != NULL) + if (q->rfkill_state != NULL) { - if ((fd = open(rfkill_state, O_RDWR)) < 0) + if ((fd = open(q->rfkill_state, O_RDWR)) < 0) { - ALOGE("open(%s) for write failed: %s (%d)",rfkill_state, strerror(errno), errno); + ALOGE("open(%s) for write failed: %s (%d)", q->rfkill_state, strerror(errno), errno); #ifdef WIFI_BT_STATUS_SYNC bt_semaphore_release(lock_fd); bt_semaphore_destroy(lock_fd); @@ -466,8 +454,7 @@ static int bt_powerup(int en ) #endif goto done; } - - ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", rfkill_id); + ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", q->rfkill_id); if( (ret < 0 ) || (enable_ldo_path == NULL) ) { ALOGE("Memory Allocation failure"); @@ -489,7 +476,7 @@ static int bt_powerup(int en ) if (ret < 0) { ALOGI("%s: Not able to set property wc_transport.extldo\n", __func__); } - enable_extldo = TRUE; + q->enable_extldo = TRUE; } if(on == '0'){ @@ -503,7 +490,7 @@ static int bt_powerup(int en ) /* Write value to control rfkill */ if(fd >= 0) { if ((size = write(fd, &on, 1)) < 0) { - ALOGE("write(%s) failed: %s (%d)",rfkill_state, strerror(errno),errno); + ALOGE("write(%s) failed: %s (%d)", q->rfkill_state, strerror(errno), errno); #ifdef WIFI_BT_STATUS_SYNC bt_semaphore_release(lock_fd); bt_semaphore_destroy(lock_fd); @@ -558,84 +545,89 @@ done: return 0; } +static inline void soc_init(int soc_type) +{ + switch (soc_type) + { + case BT_SOC_CHEROKEE: + case BT_SOC_ROME: + case BT_SOC_AR3K: + ALOGI("bt-vendor : Initializing UART transport layer"); + userial_vendor_init(); + break; + case BT_SOC_DEFAULT: + break; + default: + ALOGE("Unknown soc yype: %d", soc_type); + break; + } +} + +/* Copy BD Address as little-endian byte order */ +static inline void le2bd(unsigned char *src, unsigned char *dst) +{ + int i; + for (i = 0; i < 6; i++) + dst[i] = src[5-i]; +} + +static inline void print_bdaddr(unsigned char *addr) +{ + ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1], + addr[2], addr[3], addr[4], addr[5]); +} + /***************************************************************************** ** ** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS ** *****************************************************************************/ -static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr) +static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr) { - int i, ret; char address[PROPERTY_VALUE_MAX]; + struct bt_qcom_struct *temp = NULL; + int ret = BT_STATUS_SUCCESS, i; - ALOGI("bt-vendor : init"); - - if (p_cb == NULL) - { - ALOGE("init failed with no user callbacks!"); - return -1; - } - - if ((btSocType = get_bt_soc_type()) < 0) { - ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__); - return -1; - } + ALOGI("++%s", __FUNCTION__); - switch(btSocType) - { - case BT_SOC_ROME: - case BT_SOC_AR3K: - case BT_SOC_CHEROKEE: - ALOGI("bt-vendor : check soc initialized "); - if (!is_soc_initialized()) { - ALOGI("bt-vendor : Initializing UART transport layer"); - userial_vendor_init(); - } - break; - case BT_SOC_DEFAULT: - break; - default: - ALOGE("Unknown btSocType: 0x%x", btSocType); - break; + if (!cb || !bdaddr) { + ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr); + ret = -BT_STATUS_INVAL; + goto out; } - /* store reference to user callbacks */ - bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb; - - /* Copy BD Address as little-endian byte order */ - if(local_bdaddr) - for(i=0;i<6;i++) - vnd_local_bd_addr[i] = *(local_bdaddr + (5-i)); - - ALOGI("%s: Local BD Address : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", __FUNCTION__, - vnd_local_bd_addr[0], - vnd_local_bd_addr[1], - vnd_local_bd_addr[2], - vnd_local_bd_addr[3], - vnd_local_bd_addr[4], - vnd_local_bd_addr[5]); - - /*Update the property here so that It can be fetched at wcnss_filter*/ - snprintf(address, sizeof(address), "%02x:%02x:%02x:%02x:%02x:%02x", - vnd_local_bd_addr[0], - vnd_local_bd_addr[1], - vnd_local_bd_addr[2], - vnd_local_bd_addr[3], - vnd_local_bd_addr[4], - vnd_local_bd_addr[5]); - - ret = property_set("wc_transport.stack_bdaddr", address); - if (ret < 0) { - ALOGE("%s: Error while updating bd addr property: %d\n", __func__, ret); - return false; + temp = (struct bt_qcom_struct *) malloc(sizeof(*q)); + if (!temp) { + ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno); + ret = -BT_STATUS_NOMEM; + goto out; } - + memset(temp, 0, sizeof(*temp)); + + temp->rfkill_id = -1; + temp->enable_extldo = FALSE; + temp->cb = cb; + temp->ant_fd = -1; + temp->soc_type = get_bt_soc_type(); + soc_init(temp->soc_type); + le2bd(bdaddr, temp->bdaddr); + print_bdaddr(temp->bdaddr); + +/* TODO: Move these fields inside bt_qcom context */ #ifdef WIFI_BT_STATUS_SYNC isInit = 1; #endif /* WIFI_BT_STATUS_SYNC */ - return 0; + /* Everything successful */ + q = temp; + return ret; + +out: + if (temp) + free(temp); + ALOGI("--%s ret %d", __FUNCTION__, ret); + return ret; } #ifdef READ_BT_ADDR_FROM_PROP @@ -712,7 +704,7 @@ bool is_soc_initialized() { /** Requested operations */ static int op(bt_vendor_opcode_t opcode, void *param) { - int retval = 0; + int retval = BT_STATUS_SUCCESS; int nCnt = 0; int nState = -1; bool is_ant_req = false; @@ -729,7 +721,13 @@ static int op(bt_vendor_opcode_t opcode, void *param) #endif bool skip_init = true; int opcode_init = opcode; - ALOGV("bt-vendor : op for %d", opcode); + ALOGV("++%s opcode %d", __FUNCTION__, opcode); + pthread_mutex_lock(&q_lock); + if (!q) { + ALOGE("op called with NULL context"); + retval = -BT_STATUS_INVAL; + goto out; + } switch(opcode_init) { @@ -745,11 +743,15 @@ static int op(bt_vendor_opcode_t opcode, void *param) #endif case BT_VND_OP_POWER_CTRL: { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; + } nState = *(int *) param; ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s", (nState == BT_VND_PWR_ON)? "On" : "Off" ); - switch(btSocType) + switch(q->soc_type) { case BT_SOC_DEFAULT: if (readTrpState()) @@ -771,47 +773,33 @@ static int op(bt_vendor_opcode_t opcode, void *param) case BT_SOC_AR3K: case BT_SOC_CHEROKEE: /* BT Chipset Power Control through Device Tree Node */ - if(!pthread_mutex_lock(&m_lock)) { - retval = bt_powerup(nState); - pthread_mutex_unlock(&m_lock); - } + retval = bt_powerup(nState); default: break; } } break; - case BT_VND_OP_FW_CFG: - { - // call hciattach to initalize the stack - if(bt_vendor_cbacks){ - if (btSocType == BT_SOC_ROME) { - if (is_soc_initialized()) { - ALOGI("Bluetooth FW and transport layer are initialized"); - bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); - } else { - ALOGE("bt_vendor_cbacks is null or SoC not initialized"); - ALOGE("Error : hci, smd initialization Error"); - retval = -1; - } - } else { - ALOGI("Bluetooth FW and transport layer are initialized"); - bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); - } - } - else{ - ALOGE("bt_vendor_cbacks is null"); - ALOGE("Error : hci, smd initialization Error"); - retval = -1; + case BT_VND_OP_FW_CFG: { + /* call hciattach to initalize the stack */ + if (q->soc_type == BT_SOC_ROME) { + if (is_soc_initialized()) { + ALOGI("Bluetooth FW and transport layer are initialized"); + q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); + } else { + ALOGE("bt_vendor_cbacks is null or SoC not initialized"); + ALOGE("Error : hci, smd initialization Error"); + retval = -1; + } + } else { + ALOGI("Bluetooth FW and transport layer are initialized"); + q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); } - } + } break; case BT_VND_OP_SCO_CFG: - { - if (bt_vendor_cbacks) - bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy - } + q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy break; #ifdef ENABLE_ANT case BT_VND_OP_ANT_USERIAL_OPEN: @@ -828,20 +816,24 @@ static int op(bt_vendor_opcode_t opcode, void *param) userial_open: case BT_VND_OP_USERIAL_OPEN: { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; + } int (*fd_array)[] = (int (*)[]) param; int idx, fd = -1, fd_filter = -1; ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN"); - switch(btSocType) + switch(q->soc_type) { case BT_SOC_DEFAULT: { - if(bt_hci_init_transport(pFd) != -1){ + if(bt_hci_init_transport(q->fd) != -1){ int (*fd_array)[] = (int (*) []) param; - (*fd_array)[CH_CMD] = pFd[0]; - (*fd_array)[CH_EVT] = pFd[0]; - (*fd_array)[CH_ACL_OUT] = pFd[1]; - (*fd_array)[CH_ACL_IN] = pFd[1]; + (*fd_array)[CH_CMD] = q->fd[0]; + (*fd_array)[CH_EVT] = q->fd[0]; + (*fd_array)[CH_ACL_OUT] = q->fd[1]; + (*fd_array)[CH_ACL_IN] = q->fd[1]; } else { retval = -1; @@ -914,8 +906,12 @@ userial_open: ignore_boot_prop = TRUE; break; } - if (!validate_tok(tok)) { - ALOGE("Invalid token in BD address"); + if (i == 6 && !ignore_boot_prop) { + ALOGV("Valid BD address read from prop"); + memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr)); + ignore_boot_prop = FALSE; + } else { + ALOGE("There are not enough tokens in BD addr"); ignore_boot_prop = TRUE; break; } @@ -938,12 +934,12 @@ userial_open: } #endif //READ_BT_ADDR_FROM_PROP /* Always read BD address from NV file */ - if(ignore_boot_prop && !bt_vendor_nv_read(1, vnd_local_bd_addr)) + if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr)) { /* Since the BD address is configured in boot time We should not be here */ ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm"); } - if(rome_soc_init(fd, (char*)vnd_local_bd_addr)<0) { + if(rome_soc_init(fd, (char*)q->bdaddr)<0) { retval = -1; } else { ALOGV("rome_soc_init is completed"); @@ -965,7 +961,7 @@ userial_open: #ifdef ENABLE_ANT if (is_ant_req) { ALOGI("%s: connect to ant channel", __func__); - ant_fd = fd_filter = connect_to_local_socket("ant_sock"); + q->ant_fd = fd_filter = connect_to_local_socket("ant_sock"); } else #endif @@ -1002,7 +998,7 @@ userial_open: } } } else { - if (btSocType == BT_SOC_ROME) + if (q->soc_type == BT_SOC_ROME) ALOGE("Failed to initialize ROME Controller!!!"); } @@ -1024,14 +1020,14 @@ userial_open: #ifdef ENABLE_ANT if (is_ant_req) { ALOGI("%s: connect to ant channel", __func__); - ant_fd = fd_filter = connect_to_local_socket("ant_sock"); + q->ant_fd = fd_filter = connect_to_local_socket("ant_sock"); } else #endif #ifdef FM_OVER_UART - if (is_fm_req && (btSocType >=BT_SOC_ROME && btSocType < BT_SOC_RESERVED)) { + if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) { ALOGI("%s: connect to fm channel", __func__); - fm_fd = fd_filter = connect_to_local_socket("fm_sock"); + q->fm_fd = fd_filter = connect_to_local_socket("fm_sock"); } else #endif @@ -1067,7 +1063,7 @@ userial_open: } break; default: - ALOGE("Unknown btSocType: 0x%x", btSocType); + ALOGE("Unknown soc_type: 0x%x", q->soc_type); break; } } break; @@ -1075,52 +1071,46 @@ userial_open: case BT_VND_OP_ANT_USERIAL_CLOSE: { ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE"); - if(!pthread_mutex_lock(&m_lock)) { - property_set("wc_transport.clean_up","1"); - if (ant_fd != -1) { - ALOGE("closing ant_fd"); - close(ant_fd); - ant_fd = -1; - } - pthread_mutex_unlock(&m_lock); + property_set("wc_transport.clean_up","1"); + if (q->ant_fd != -1) { + ALOGE("closing ant_fd"); + close(q->ant_fd); + q->ant_fd = -1; } } - break; + break; #endif #ifdef FM_OVER_UART case BT_VND_OP_FM_USERIAL_CLOSE: { ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE"); property_set("wc_transport.clean_up","1"); - if (fm_fd != -1) { + if (q->fm_fd != -1) { ALOGE("closing fm_fd"); - close(fm_fd); - fm_fd = -1; + close(q->fm_fd); + q->fm_fd = -1; } break; - } + } #endif case BT_VND_OP_USERIAL_CLOSE: { - ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE btSocType: %d", btSocType); - switch(btSocType) + ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type); + switch(q->soc_type) { case BT_SOC_DEFAULT: - bt_hci_deinit_transport(pFd); + bt_hci_deinit_transport(q->fd); break; case BT_SOC_ROME: case BT_SOC_AR3K: case BT_SOC_CHEROKEE: { - if(!pthread_mutex_lock(&m_lock)) { - property_set("wc_transport.clean_up","1"); - userial_vendor_close(); - pthread_mutex_unlock(&m_lock); - } + property_set("wc_transport.clean_up","1"); + userial_vendor_close(); break; } default: - ALOGE("Unknown btSocType: 0x%x", btSocType); + ALOGE("Unknown soc_type: 0x%x", q->soc_type); break; } } @@ -1128,6 +1118,10 @@ userial_open: case BT_VND_OP_GET_LPM_IDLE_TIMEOUT: { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; + } uint32_t *timeout_ms = (uint32_t *) param; *timeout_ms = 1000; } @@ -1135,7 +1129,11 @@ userial_open: break; case BT_VND_OP_LPM_SET_MODE: - if(btSocType == BT_SOC_AR3K) { + if (q->soc_type == BT_SOC_AR3K) { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; + } uint8_t *mode = (uint8_t *) param; if (*mode) { @@ -1144,57 +1142,59 @@ userial_open: else { lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0); } - if (bt_vendor_cbacks ) - bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS); - } - else { - // respond with failure as it's already handled by other mechanism - if (bt_vendor_cbacks) - bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL); + q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS); + } else { + /* respond with failure as it's handled by other mechanism */ + q->cb->lpm_cb(BT_VND_OP_RESULT_FAIL); } break; - case BT_VND_OP_LPM_WAKE_SET_STATE: - { - switch(btSocType) - { - case BT_SOC_CHEROKEE: - case BT_SOC_ROME: - { - uint8_t *state = (uint8_t *) param; - uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ - BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT; - - if (wake_assert == 0) - ALOGV("ASSERT: Waking up BT-Device"); - else if (wake_assert == 1) - ALOGV("DEASSERT: Allowing BT-Device to Sleep"); - } - break; - case BT_SOC_AR3K: - { - uint8_t *state = (uint8_t *) param; - uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ - UPIO_ASSERT : UPIO_DEASSERT; - lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0); - } - case BT_SOC_DEFAULT: - break; - default: - ALOGE("Unknown btSocType: 0x%x", btSocType); - break; - } + case BT_VND_OP_LPM_WAKE_SET_STATE: { + switch(q->soc_type) { + case BT_SOC_CHEROKEE: + case BT_SOC_ROME: { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; + } + uint8_t *state = (uint8_t *) param; + uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ + BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT; + + if (wake_assert == 0) + ALOGV("ASSERT: Waking up BT-Device"); + else if (wake_assert == 1) + ALOGV("DEASSERT: Allowing BT-Device to Sleep"); + +#ifdef QCOM_BT_SIBS_ENABLE + ALOGI("Invoking HCI H4 callback function"); + q->cb->lpm_set_state_cb(wake_assert); +#endif } break; - case BT_VND_OP_EPILOG: - { -#if (HW_NEED_END_WITH_HCI_RESET == FALSE) - if (bt_vendor_cbacks) - { - bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); + case BT_SOC_AR3K: { + if (!param) { + ALOGE("opcode = %d: param is null", opcode_init); + break; } + uint8_t *state = (uint8_t *) param; + uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ + UPIO_ASSERT : UPIO_DEASSERT; + lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0); + } + case BT_SOC_DEFAULT: + break; + default: + ALOGE("Unknown soc_type: 0x%x", q->soc_type); + break; + } + } + break; + case BT_VND_OP_EPILOG: { +#if (HW_NEED_END_WITH_HCI_RESET == FALSE) + q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS); #else - switch(btSocType) + switch(q->soc_type) { case BT_SOC_CHEROKEE: case BT_SOC_ROME: @@ -1203,20 +1203,16 @@ userial_open: property_get("wc_transport.hci_filter_status", value, "0"); if(is_soc_initialized()&& (strcmp(value,"1") == 0)) { - hw_epilog_process(); + __hw_epilog_process(); } else { - if (bt_vendor_cbacks) - { - ALOGE("vendor lib epilog process aborted"); - bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); - } + q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS); } } break; default: - hw_epilog_process(); + __hw_epilog_process(); break; } #endif @@ -1231,7 +1227,7 @@ userial_open: break; } - switch(btSocType) + switch(q->soc_type) { case BT_SOC_CHEROKEE: retval = 3200000; @@ -1247,41 +1243,55 @@ userial_open: } } +out: + pthread_mutex_unlock(&q_lock); + ALOGV("--%s", __FUNCTION__); return retval; } -static void ssr_cleanup(int reason) { - int pwr_state=BT_VND_PWR_OFF; +static void ssr_cleanup(int reason) +{ + int pwr_state = BT_VND_PWR_OFF; int ret; unsigned char trig_ssr = 0xEE; - ALOGI("ssr_cleanup"); - if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) { - ALOGE("%s: Failed to set property", __FUNCTION__); - } - if ((btSocType = get_bt_soc_type()) < 0) { - ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__); + ALOGI("++%s", __FUNCTION__); + + pthread_mutex_lock(&q_lock); + if (!q) { + ALOGE("ssr_cleanup called with NULL context"); + pthread_mutex_unlock(&q_lock); + return; + } + if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) { + ALOGE("Failed to set property"); } - if (btSocType == BT_SOC_ROME || btSocType == BT_SOC_CHEROKEE) { - //Indicate to filter by sending - //special byte + if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) { +#ifdef ENABLE_ANT + /*Indicate to filter by sending special byte */ if (reason == CMD_TIMEOUT) { trig_ssr = 0xEE; ret = write (vnd_userial.fd, &trig_ssr, 1); - ALOGI("Trig_ssr is being sent to BT socket, retval(%d) :errno: %s", ret, strerror(errno)); + ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s", + ret, strerror(errno)); if (is_debug_force_special_bytes()) { - //Then we should send special byte to crash SOC in WCNSS_Filter, so we do not - //need to power off UART here. + /* + * Then we should send special byte to crash SOC in + * WCNSS_Filter, so we do not need to power off UART here. + */ + pthread_mutex_unlock(&q_lock); return; } } -#ifdef ENABLE_ANT - /*Close both ANT channel*/ + /* release lock here as op holds lock anyways */ + pthread_mutex_unlock(&q_lock); + + /* Close both ANT channel */ op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL); #endif - /*Close both BT channel*/ + /* Close both BT channel */ op(BT_VND_OP_USERIAL_CLOSE, NULL); #ifdef FM_OVER_UART @@ -1298,16 +1308,20 @@ static void ssr_cleanup(int reason) { } /*Generally switching of chip should be enough*/ op(BT_VND_OP_POWER_CTRL, &pwr_state); + + ALOGI("--%s", __FUNCTION__); } /** Closes the interface */ -static void cleanup( void ) +static void cleanup(void) { ALOGI("cleanup"); - if(!pthread_mutex_lock(&m_lock)) { - bt_vendor_cbacks = NULL; - pthread_mutex_unlock(&m_lock); - } + + pthread_mutex_lock(&q_lock); + q->cb = NULL; + free(q); + q = NULL; + pthread_mutex_unlock(&q_lock); #ifdef WIFI_BT_STATUS_SYNC isInit = 0; @@ -1344,12 +1358,12 @@ bool is_download_progress () { ALOGV("%s:", __FUNCTION__); - if ((btSocType = get_bt_soc_type()) < 0) { + if ((q->soc_type = get_bt_soc_type()) < 0) { ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__); return -1; } - switch(btSocType) + switch(q->soc_type) { case BT_SOC_ROME: ALOGI("%s: ROME case", __func__); @@ -1366,7 +1380,7 @@ bool is_download_progress () { case BT_SOC_DEFAULT: break; default: - ALOGE("Unknown btSocType: 0x%x", btSocType); + ALOGE("Unknown btSocType: 0x%x", q->soc_type); break; } return retval; diff --git a/libbt-vendor/src/hardware.c b/libbt-vendor/src/hardware.c index 496ebc1..ff421c2 100644 --- a/libbt-vendor/src/hardware.c +++ b/libbt-vendor/src/hardware.c @@ -132,26 +132,31 @@ void hw_epilog_cback(void *p_mem) ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status); - if (bt_vendor_cbacks) - { - /* Must free the RX event buffer */ - bt_vendor_cbacks->dealloc(p_evt_buf); - - /* Once epilog process is done, must call callback to notify caller */ - bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); + pthread_mutex_lock(&q_lock); + if (!q) { + ALOGE("hw_epilog_cback called with NULL context"); + goto out; } + /* Must free the RX event buffer */ + q->cb->dealloc(p_evt_buf); + + /* Once epilog process is done, must call callback to notify caller */ + q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS); +out: + pthread_mutex_unlock(&q_lock); } /******************************************************************************* ** ** Function hw_epilog_process ** -** Description Sample implementation of epilog process +** Description Sample implementation of epilog process. This process is +** called with q_lock held and q->cb is assumed to be valid. ** ** Returns None ** *******************************************************************************/ -void hw_epilog_process(void) +void __hw_epilog_process(void) { HC_BT_HDR *p_buf = NULL; uint8_t *p; @@ -159,13 +164,8 @@ void hw_epilog_process(void) ALOGI("hw_epilog_process"); /* Sending a HCI_RESET */ - if (bt_vendor_cbacks) - { - /* Must allocate command buffer via HC's alloc API */ - p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ - HCI_CMD_PREAMBLE_SIZE); - } - + /* Must allocate command buffer via HC's alloc API */ + p_buf = (HC_BT_HDR *) q->cb->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE); if (p_buf) { p_buf->event = MSG_STACK_TO_HC_HCI_CMD; @@ -178,15 +178,12 @@ void hw_epilog_process(void) *p = 0; /* parameter length */ /* Send command via HC's xmit_cb API */ - bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback); + q->cb->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback); } else { - if (bt_vendor_cbacks) - { - ALOGE("vendor lib epilog process aborted [no buffer]"); - bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL); - } + ALOGE("vendor lib epilog process aborted [no buffer]"); + q->cb->epilog_cb(BT_VND_OP_RESULT_FAIL); } } #endif // (HW_NEED_END_WITH_HCI_RESET == TRUE) diff --git a/libbt-vendor/src/hw_rome.c b/libbt-vendor/src/hw_rome.c index da1ccb1..56c3b9a 100644 --- a/libbt-vendor/src/hw_rome.c +++ b/libbt-vendor/src/hw_rome.c @@ -88,7 +88,6 @@ int dnld_fd = -1; /****************************************************************************** ** Extern variables ******************************************************************************/ -extern uint8_t vnd_local_bd_addr[6]; /***************************************************************************** ** Functions @@ -818,6 +817,7 @@ error: return err; } +/* This function is called with q_lock held and q is non-NULL */ int rome_get_tlv_file(char *file_path) { FILE * pFile; @@ -908,7 +908,7 @@ int rome_get_tlv_file(char *file_path) /* Write BD Address */ if(nvm_ptr->tag_id == TAG_NUM_2){ - memcpy(nvm_byte_ptr, vnd_local_bd_addr, 6); + memcpy(nvm_byte_ptr, q->bdaddr, 6); ALOGI("BD Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x", *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2), *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5)); @@ -1348,7 +1348,7 @@ int rome_1_0_nvm_tag_dnld(int fd) { /* Write BD Address */ if(cmds[i][TAG_NUM_OFFSET] == TAG_NUM_2){ - memcpy(&cmds[i][TAG_BDADDR_OFFSET], vnd_local_bd_addr, 6); + memcpy(&cmds[i][TAG_BDADDR_OFFSET], q->bdaddr, 6); ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", cmds[i][TAG_BDADDR_OFFSET ], cmds[i][TAG_BDADDR_OFFSET + 1], cmds[i][TAG_BDADDR_OFFSET + 2], cmds[i][TAG_BDADDR_OFFSET + 3], @@ -1781,10 +1781,11 @@ end: } +/* This function is called with q_lock held and q is non-NULL */ static int disable_internal_ldo(int fd) { int ret = 0; - if (enable_extldo) { + if (q->enable_extldo) { unsigned char cmd[5] = {0x01, 0x0C, 0xFC, 0x01, 0x32}; unsigned char rsp[HCI_MAX_EVENT_SIZE]; |