/****************************************************************************** * * Copyright (C) 2009-2012 Broadcom Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /****************************************************************************** * * Filename: bt_vendor_brcm.c * * Description: Broadcom vendor specific library implementation * ******************************************************************************/ #define LOG_TAG "bt_vendor" #include #include #include "bt_vendor_brcm.h" #include "upio.h" #include "userial_vendor.h" #ifndef BTVND_DBG #define BTVND_DBG FALSE #endif #if (BTVND_DBG == TRUE) #define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} #else #define BTVNDDBG(param, ...) {} #endif /****************************************************************************** ** Externs ******************************************************************************/ void hw_config_start(void); uint8_t hw_lpm_enable(uint8_t turn_on); uint32_t hw_lpm_get_idle_timeout(void); void hw_lpm_set_wake_state(uint8_t wake_assert); #if (SCO_CFG_INCLUDED == TRUE) void hw_sco_config(void); #endif void vnd_load_conf(const char *p_path); #if (HW_END_WITH_HCI_RESET == TRUE) void hw_epilog_process(void); #endif #if (BRCM_A2DP_OFFLOAD == TRUE) void brcm_vnd_a2dp_init(bt_vendor_callbacks_t *callback); int brcm_vnd_a2dp_execute(bt_vendor_opcode_t, void *ev_data); #endif /****************************************************************************** ** Variables ******************************************************************************/ bt_vendor_callbacks_t *bt_vendor_cbacks = NULL; uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /****************************************************************************** ** Local type definitions ******************************************************************************/ /****************************************************************************** ** Static Variables ******************************************************************************/ static const tUSERIAL_CFG userial_init_cfg = { (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1), USERIAL_BAUD_115200 }; /****************************************************************************** ** Functions ******************************************************************************/ /***************************************************************************** ** ** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS ** *****************************************************************************/ static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr) { ALOGI("init"); if (p_cb == NULL) { ALOGE("init failed with no user callbacks!"); return -1; } #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) ALOGW("*****************************************************************"); ALOGW("*****************************************************************"); ALOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!"); ALOGW("**"); ALOGW("** If this is not intentional, rebuild libbt-vendor.so "); ALOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and "); ALOGW("** check if any run-time tuning parameters needed to be"); ALOGW("** carried to the build-time configuration accordingly."); ALOGW("*****************************************************************"); ALOGW("*****************************************************************"); #endif userial_vendor_init(); upio_init(); vnd_load_conf(VENDOR_LIB_CONF_FILE); /* store reference to user callbacks */ bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb; /* This is handed over from the stack */ memcpy(vnd_local_bd_addr, local_bdaddr, 6); #if (BRCM_A2DP_OFFLOAD == TRUE) brcm_vnd_a2dp_init(bt_vendor_cbacks); #endif return 0; } /** Requested operations */ static int op(bt_vendor_opcode_t opcode, void *param) { int retval = 0; BTVNDDBG("op for %d", opcode); switch(opcode) { case BT_VND_OP_POWER_CTRL: { int *state = (int *) param; upio_set_bluetooth_power(UPIO_BT_POWER_OFF); if (*state == BT_VND_PWR_ON) { ALOGW("NOTE: BT_VND_PWR_ON now forces power-off first"); upio_set_bluetooth_power(UPIO_BT_POWER_ON); } else { /* Make sure wakelock is released */ hw_lpm_set_wake_state(false); } } break; case BT_VND_OP_FW_CFG: { hw_config_start(); } break; case BT_VND_OP_SCO_CFG: { #if (SCO_CFG_INCLUDED == TRUE) hw_sco_config(); #else retval = -1; #endif } break; case BT_VND_OP_USERIAL_OPEN: { int (*fd_array)[] = (int (*)[]) param; int fd, idx; fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg); if (fd != -1) { for (idx=0; idx < CH_MAX; idx++) (*fd_array)[idx] = fd; retval = 1; } /* retval contains numbers of open fd of HCI channels */ } break; case BT_VND_OP_USERIAL_CLOSE: { userial_vendor_close(); } break; case BT_VND_OP_GET_LPM_IDLE_TIMEOUT: { uint32_t *timeout_ms = (uint32_t *) param; *timeout_ms = hw_lpm_get_idle_timeout(); } break; case BT_VND_OP_LPM_SET_MODE: { uint8_t *mode = (uint8_t *) param; retval = hw_lpm_enable(*mode); } break; case BT_VND_OP_LPM_WAKE_SET_STATE: { uint8_t *state = (uint8_t *) param; uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ TRUE : FALSE; hw_lpm_set_wake_state(wake_assert); } break; case BT_VND_OP_SET_AUDIO_STATE: { retval = hw_set_audio_state((bt_vendor_op_audio_state_t *)param); } break; case BT_VND_OP_EPILOG: { #if (HW_END_WITH_HCI_RESET == FALSE) if (bt_vendor_cbacks) { bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); } #else hw_epilog_process(); #endif } break; #if (BRCM_A2DP_OFFLOAD == TRUE) case BT_VND_OP_A2DP_OFFLOAD_START: case BT_VND_OP_A2DP_OFFLOAD_STOP: retval = brcm_vnd_a2dp_execute(opcode, param); break; #endif } return retval; } /** Closes the interface */ static void cleanup( void ) { BTVNDDBG("cleanup"); upio_cleanup(); bt_vendor_cbacks = NULL; } // Entry point of DLib const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = { sizeof(bt_vendor_interface_t), init, op, cleanup };