diff options
Diffstat (limited to 'btif/src/btif_core.c')
-rwxr-xr-x | btif/src/btif_core.c | 1431 |
1 files changed, 1431 insertions, 0 deletions
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c new file mode 100755 index 0000000..62339a9 --- /dev/null +++ b/btif/src/btif_core.c @@ -0,0 +1,1431 @@ +/****************************************************************************** + * + * 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: btif_core.c + * + * Description: Contains core functionality related to interfacing between + * Bluetooth HAL and BTE core stack. + * + ***********************************************************************************/ + +#include <stdlib.h> +#include <hardware/bluetooth.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <ctype.h> +#include <cutils/properties.h> + +#define LOG_TAG "BTIF_CORE" +#include "btif_api.h" +#include "bta_api.h" +#include "gki.h" +#include "btu.h" +#include "bte.h" +#include "bd.h" +#include "btif_av.h" +#include "btif_storage.h" +#include "btif_util.h" +#include "btif_sock.h" +#include "btif_pan.h" +#include "btif_profile_queue.h" +#include "btif_config.h" +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +#ifndef BTIF_TASK_STACK_SIZE +#define BTIF_TASK_STACK_SIZE 0x2000 /* In bytes */ +#endif + +#ifndef BTE_DID_CONF_FILE +#define BTE_DID_CONF_FILE "/etc/bluetooth/bt_did.conf" +#endif + +#define BTIF_TASK_STR ((INT8 *) "BTIF") + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/* These type definitions are used when passing data from the HAL to BTIF context +* in the downstream path for the adapter and remote_device property APIs */ + +typedef struct { + bt_bdaddr_t bd_addr; + bt_property_type_t type; +} btif_storage_read_t; + +typedef struct { + bt_bdaddr_t bd_addr; + bt_property_t prop; +} btif_storage_write_t; + +typedef union { + btif_storage_read_t read_req; + btif_storage_write_t write_req; +} btif_storage_req_t; + +typedef enum { + BTIF_CORE_STATE_DISABLED = 0, + BTIF_CORE_STATE_ENABLING, + BTIF_CORE_STATE_ENABLED, + BTIF_CORE_STATE_DISABLING +} btif_core_state_t; + +/************************************************************************************ +** Static variables +************************************************************************************/ + +bt_bdaddr_t btif_local_bd_addr; + +static UINT32 btif_task_stack[(BTIF_TASK_STACK_SIZE + 3) / 4]; + +/* holds main adapter state */ +static btif_core_state_t btif_core_state = BTIF_CORE_STATE_DISABLED; + +static int btif_shutdown_pending = 0; +static tBTA_SERVICE_MASK btif_enabled_services = 0; + +/* +* This variable should be set to 1, if the Bluedroid+BTIF libraries are to +* function in DUT mode. +* +* To set this, the btif_init_bluetooth needs to be called with argument as 1 +*/ +static UINT8 btif_dut_mode = 0; + +/************************************************************************************ +** Static functions +************************************************************************************/ +static bt_status_t btif_associate_evt(void); +static bt_status_t btif_disassociate_evt(void); + +/* sends message to btif task */ +static void btif_sendmsg(void *p_msg); + +/************************************************************************************ +** Externs +************************************************************************************/ +extern void bte_load_did_conf(const char *p_path); + +/** TODO: Move these to _common.h */ +void bte_main_boot_entry(void); +void bte_main_enable(uint8_t *local_addr); +void bte_main_disable(void); +void bte_main_shutdown(void); +#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) +void bte_main_enable_lpm(BOOLEAN enable); +#endif +void bte_main_postload_cfg(void); +void btif_dm_execute_service_request(UINT16 event, char *p_param); +#ifdef BTIF_DM_OOB_TEST +void btif_dm_load_local_oob(void); +#endif + +/************************************************************************************ +** Functions +************************************************************************************/ + + +/***************************************************************************** +** Context switching functions +*****************************************************************************/ + + +/******************************************************************************* +** +** Function btif_context_switched +** +** Description Callback used to execute transferred context callback +** +** p_msg : message to be executed in btif context +** +** Returns void +** +*******************************************************************************/ + +static void btif_context_switched(void *p_msg) +{ + tBTIF_CONTEXT_SWITCH_CBACK *p; + + BTIF_TRACE_VERBOSE0("btif_context_switched"); + + p = (tBTIF_CONTEXT_SWITCH_CBACK *) p_msg; + + /* each callback knows how to parse the data */ + if (p->p_cb) + p->p_cb(p->event, p->p_param); +} + + +/******************************************************************************* +** +** Function btif_transfer_context +** +** Description This function switches context to btif task +** +** p_cback : callback used to process message in btif context +** event : event id of message +** p_params : parameter area passed to callback (copied) +** param_len : length of parameter area +** p_copy_cback : If set this function will be invoked for deep copy +** +** Returns void +** +*******************************************************************************/ + +bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback) +{ + tBTIF_CONTEXT_SWITCH_CBACK *p_msg; + + BTIF_TRACE_VERBOSE2("btif_transfer_context event %d, len %d", event, param_len); + + /* allocate and send message that will be executed in btif context */ + if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL) + { + p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */ + p_msg->p_cb = p_cback; + + p_msg->event = event; /* callback event */ + + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) + { + p_copy_cback(event, p_msg->p_param, p_params); + } + else if (p_params) + { + memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data */ + } + + btif_sendmsg(p_msg); + return BT_STATUS_SUCCESS; + } + else + { + /* let caller deal with a failed allocation */ + return BT_STATUS_NOMEM; + } +} + +/******************************************************************************* +** +** Function btif_is_dut_mode +** +** Description checks if BTIF is currently in DUT mode +** +** Returns 1 if test mode, otherwize 0 +** +*******************************************************************************/ + +UINT8 btif_is_dut_mode(void) +{ + return (btif_dut_mode == 1); +} + +/******************************************************************************* +** +** Function btif_is_enabled +** +** Description checks if main adapter is fully enabled +** +** Returns 1 if fully enabled, otherwize 0 +** +*******************************************************************************/ + +int btif_is_enabled(void) +{ + return ((!btif_is_dut_mode()) && (btif_core_state == BTIF_CORE_STATE_ENABLED)); +} + +/******************************************************************************* +** +** Function btif_task +** +** Description BTIF task handler managing all messages being passed +** Bluetooth HAL and BTA. +** +** Returns void +** +*******************************************************************************/ + +static void btif_task(UINT32 params) +{ + UINT16 event; + BT_HDR *p_msg; + + BTIF_TRACE_DEBUG0("btif task starting"); + + btif_associate_evt(); + + for(;;) + { + /* wait for specified events */ + event = GKI_wait(0xFFFF, 0); + + /* + * Wait for the trigger to init chip and stack. This trigger will + * be received by btu_task once the UART is opened and ready + */ + if (event == BT_EVT_TRIGGER_STACK_INIT) + { + BTIF_TRACE_DEBUG0("btif_task: received trigger stack init event"); + BTA_EnableBluetooth(bte_dm_evt); + } + + if (event & EVENT_MASK(GKI_SHUTDOWN_EVT)) + break; + + if(event & TASK_MBOX_1_EVT_MASK) + { + while((p_msg = GKI_read_mbox(BTU_BTIF_MBOX)) != NULL) + { + BTIF_TRACE_VERBOSE1("btif task fetched event %x", p_msg->event); + + switch (p_msg->event) + { + case BT_EVT_CONTEXT_SWITCH_EVT: + btif_context_switched(p_msg); + break; + default: + BTIF_TRACE_ERROR1("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK); + break; + } + + GKI_freebuf(p_msg); + } + } + } + + btif_disassociate_evt(); + + BTIF_TRACE_DEBUG0("btif task exiting"); +} + + +/******************************************************************************* +** +** Function btif_sendmsg +** +** Description Sends msg to BTIF task +** +** Returns void +** +*******************************************************************************/ + +void btif_sendmsg(void *p_msg) +{ + GKI_send_msg(BTIF_TASK, BTU_BTIF_MBOX, p_msg); +} + +static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) +{ + char val[256]; + uint8_t valid_bda = FALSE; + int val_size = 0; + const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0}; + + /* Get local bdaddr storage path from property */ + if (property_get(PROPERTY_BT_BDADDR_PATH, val, NULL)) + { + int addr_fd; + + BTIF_TRACE_DEBUG1("local bdaddr is stored in %s", val); + + if ((addr_fd = open(val, O_RDONLY)) != -1) + { + memset(val, 0, sizeof(val)); + read(addr_fd, val, FACTORY_BT_BDADDR_STORAGE_LEN); + str2bd(val, local_addr); + /* If this is not a reserved/special bda, then use it */ + if (memcmp(local_addr->address, null_bdaddr, BD_ADDR_LEN) != 0) + { + valid_bda = TRUE; + BTIF_TRACE_DEBUG6("Got Factory BDA %02X:%02X:%02X:%02X:%02X:%02X", + local_addr->address[0], local_addr->address[1], local_addr->address[2], + local_addr->address[3], local_addr->address[4], local_addr->address[5]); + } + + close(addr_fd); + } + } + + if(!valid_bda) + { + val_size = sizeof(val); + if(btif_config_get_str("Local", "Adapter", "Address", val, &val_size)) + { + str2bd(val, local_addr); + BTIF_TRACE_DEBUG1("local bdaddr from bt_config.xml is %s", val); + return; + } + } + + /* No factory BDADDR found. Look for previously generated random BDA */ + if ((!valid_bda) && \ + (property_get(PERSIST_BDADDR_PROPERTY, val, NULL))) + { + str2bd(val, local_addr); + valid_bda = TRUE; + BTIF_TRACE_DEBUG6("Got prior random BDA %02X:%02X:%02X:%02X:%02X:%02X", + local_addr->address[0], local_addr->address[1], local_addr->address[2], + local_addr->address[3], local_addr->address[4], local_addr->address[5]); + } + + /* Generate new BDA if necessary */ + if (!valid_bda) + { + bdstr_t bdstr; + /* Seed the random number generator */ + srand((unsigned int) (time(0))); + + /* No autogen BDA. Generate one now. */ + local_addr->address[0] = 0x22; + local_addr->address[1] = 0x22; + local_addr->address[2] = (uint8_t) ((rand() >> 8) & 0xFF); + local_addr->address[3] = (uint8_t) ((rand() >> 8) & 0xFF); + local_addr->address[4] = (uint8_t) ((rand() >> 8) & 0xFF); + local_addr->address[5] = (uint8_t) ((rand() >> 8) & 0xFF); + + /* Convert to ascii, and store as a persistent property */ + bd2str(local_addr, &bdstr); + + BTIF_TRACE_DEBUG2("No preset BDA. Generating BDA: %s for prop %s", + (char*)bdstr, PERSIST_BDADDR_PROPERTY); + + if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0) + BTIF_TRACE_ERROR1("Failed to set random BDA in prop %s",PERSIST_BDADDR_PROPERTY); + } + + //save the bd address to config file + bdstr_t bdstr; + bd2str(local_addr, &bdstr); + val_size = sizeof(val); + if (btif_config_get_str("Local", "Adapter", "Address", val, &val_size)) + { + if (strcmp(bdstr, val) ==0) + { + // BDA is already present in the config file. + return; + } + } + btif_config_set_str("Local", "Adapter", "Address", bdstr); + btif_config_save(); +} + +/***************************************************************************** +** +** btif core api functions +** +*****************************************************************************/ + +/******************************************************************************* +** +** Function btif_init_bluetooth +** +** Description Creates BTIF task and prepares BT scheduler for startup +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_init_bluetooth() +{ + UINT8 status; + btif_config_init(); + bte_main_boot_entry(); + + /* As part of the init, fetch the local BD ADDR */ + memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t)); + btif_fetch_local_bdaddr(&btif_local_bd_addr); + + /* start btif task */ + status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR, + (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE), + sizeof(btif_task_stack)); + + if (status != GKI_SUCCESS) + return BT_STATUS_FAIL; + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_associate_evt +** +** Description Event indicating btif_task is up +** Attach btif_task to JVM +** +** Returns void +** +*******************************************************************************/ + +static bt_status_t btif_associate_evt(void) +{ + BTIF_TRACE_DEBUG1("%s: notify ASSOCIATE_JVM", __FUNCTION__); + HAL_CBACK(bt_hal_cbacks, thread_evt_cb, ASSOCIATE_JVM); + + return BT_STATUS_SUCCESS; +} + + +/******************************************************************************* +** +** Function btif_enable_bluetooth +** +** Description Performs chip power on and kickstarts OS scheduler +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_enable_bluetooth(void) +{ + BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH"); + + if (btif_core_state != BTIF_CORE_STATE_DISABLED) + { + ALOGD("not disabled\n"); + return BT_STATUS_DONE; + } + + btif_core_state = BTIF_CORE_STATE_ENABLING; + + /* Create the GKI tasks and run them */ + bte_main_enable(btif_local_bd_addr.address); + + return BT_STATUS_SUCCESS; +} + + +/******************************************************************************* +** +** Function btif_enable_bluetooth_evt +** +** Description Event indicating bluetooth enable is completed +** Notifies HAL user with updated adapter state +** +** Returns void +** +*******************************************************************************/ + +void btif_enable_bluetooth_evt(tBTA_STATUS status, BD_ADDR local_bd) +{ + bt_bdaddr_t bd_addr; + bdstr_t bdstr; + + bdcpy(bd_addr.address, local_bd); + BTIF_TRACE_DEBUG3("%s: status %d, local bd [%s]", __FUNCTION__, status, + bd2str(&bd_addr, &bdstr)); + + if (bdcmp(btif_local_bd_addr.address,local_bd)) + { + bdstr_t buf; + bt_property_t prop; + + /** + * The Controller's BDADDR does not match to the BTIF's initial BDADDR! + * This could be because the factory BDADDR was stored separatley in + * the Controller's non-volatile memory rather than in device's file + * system. + **/ + BTIF_TRACE_WARNING0("***********************************************"); + BTIF_TRACE_WARNING6("BTIF init BDA was %02X:%02X:%02X:%02X:%02X:%02X", + btif_local_bd_addr.address[0], btif_local_bd_addr.address[1], + btif_local_bd_addr.address[2], btif_local_bd_addr.address[3], + btif_local_bd_addr.address[4], btif_local_bd_addr.address[5]); + BTIF_TRACE_WARNING6("Controller BDA is %02X:%02X:%02X:%02X:%02X:%02X", + local_bd[0], local_bd[1], local_bd[2], + local_bd[3], local_bd[4], local_bd[5]); + BTIF_TRACE_WARNING0("***********************************************"); + + bdcpy(btif_local_bd_addr.address, local_bd); + + //save the bd address to config file + bd2str(&btif_local_bd_addr, &buf); + btif_config_set_str("Local", "Adapter", "Address", buf); + btif_config_save(); + + //fire HAL callback for property change + memcpy(buf, &btif_local_bd_addr, sizeof(bt_bdaddr_t)); + prop.type = BT_PROPERTY_BDADDR; + prop.val = (void*)buf; + prop.len = sizeof(bt_bdaddr_t); + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1, &prop); + } + + bte_main_postload_cfg(); +#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) + bte_main_enable_lpm(TRUE); +#endif + /* add passing up bd address as well ? */ + + /* callback to HAL */ + if (status == BTA_SUCCESS) + { + /* initialize a2dp service */ + btif_av_init(); + + /* init rfcomm & l2cap api */ + btif_sock_init(); + + /* init pan */ + btif_pan_init(); + + /* load did configuration */ + bte_load_did_conf(BTE_DID_CONF_FILE); + +#ifdef BTIF_DM_OOB_TEST + btif_dm_load_local_oob(); +#endif + /* now fully enabled, update state */ + btif_core_state = BTIF_CORE_STATE_ENABLED; + + HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON); + } + else + { + /* cleanup rfcomm & l2cap api */ + btif_sock_cleanup(); + + btif_pan_cleanup(); + + /* we failed to enable, reset state */ + btif_core_state = BTIF_CORE_STATE_DISABLED; + + HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF); + } +} + +/******************************************************************************* +** +** Function btif_disable_bluetooth +** +** Description Inititates shutdown of Bluetooth system. +** Any active links will be dropped and device entering +** non connectable/discoverable mode +** +** Returns void +** +*******************************************************************************/ +bt_status_t btif_disable_bluetooth(void) +{ + tBTA_STATUS status; + + if (!btif_is_enabled()) + { + BTIF_TRACE_ERROR0("btif_disable_bluetooth : not yet enabled"); + return BT_STATUS_NOT_READY; + } + + BTIF_TRACE_DEBUG0("BTIF DISABLE BLUETOOTH"); + + btif_dm_on_disable(); + btif_core_state = BTIF_CORE_STATE_DISABLING; + + /* cleanup rfcomm & l2cap api */ + btif_sock_cleanup(); + + btif_pan_cleanup(); + + status = BTA_DisableBluetooth(); + + btif_config_flush(); + + if (status != BTA_SUCCESS) + { + BTIF_TRACE_ERROR1("disable bt failed (%d)", status); + + /* reset the original state to allow attempting disable again */ + btif_core_state = BTIF_CORE_STATE_ENABLED; + + return BT_STATUS_FAIL; + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_disable_bluetooth_evt +** +** Description Event notifying BT disable is now complete. +** Terminates main stack tasks and notifies HAL +** user with updated BT state. +** +** Returns void +** +*******************************************************************************/ + +void btif_disable_bluetooth_evt(void) +{ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + +#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) + bte_main_enable_lpm(FALSE); +#endif + + bte_main_disable(); + + /* update local state */ + btif_core_state = BTIF_CORE_STATE_DISABLED; + + /* callback to HAL */ + HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF); + + if (btif_shutdown_pending) + { + BTIF_TRACE_DEBUG1("%s: calling btif_shutdown_bluetooth", __FUNCTION__); + btif_shutdown_bluetooth(); + } +} + + +/******************************************************************************* +** +** Function btif_shutdown_bluetooth +** +** Description Finalizes BT scheduler shutdown and terminates BTIF +** task. +** +** Returns void +** +*******************************************************************************/ + +bt_status_t btif_shutdown_bluetooth(void) +{ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + + if (btif_is_enabled()) + { + BTIF_TRACE_WARNING0("shutdown while still enabled, initiate disable"); + + /* shutdown called prior to disabling, initiate disable */ + btif_disable_bluetooth(); + btif_shutdown_pending = 1; + return BT_STATUS_NOT_READY; + } + + btif_shutdown_pending = 0; + + GKI_destroy_task(BTIF_TASK); + btif_queue_release(); + bte_main_shutdown(); + + btif_dut_mode = 0; + + BTIF_TRACE_DEBUG1("%s done", __FUNCTION__); + + return BT_STATUS_SUCCESS; +} + + +/******************************************************************************* +** +** Function btif_disassociate_evt +** +** Description Event indicating btif_task is going down +** Detach btif_task to JVM +** +** Returns void +** +*******************************************************************************/ + +static bt_status_t btif_disassociate_evt(void) +{ + BTIF_TRACE_DEBUG1("%s: notify DISASSOCIATE_JVM", __FUNCTION__); + + HAL_CBACK(bt_hal_cbacks, thread_evt_cb, DISASSOCIATE_JVM); + + /* shutdown complete, all events notified and we reset HAL callbacks */ + bt_hal_cbacks = NULL; + + return BT_STATUS_SUCCESS; +} + +/**************************************************************************** +** +** BTIF Test Mode APIs +** +*****************************************************************************/ +/******************************************************************************* +** +** Function btif_dut_mode_cback +** +** Description Callback invoked on completion of vendor specific test mode command +** +** Returns None +** +*******************************************************************************/ +static void btif_dut_mode_cback( tBTM_VSC_CMPL *p ) +{ + /* For now nothing to be done. */ +} + +/******************************************************************************* +** +** Function btif_dut_mode_configure +** +** Description Configure Test Mode - 'enable' to 1 puts the device in test mode and 0 exits +** test mode +** +** Returns BT_STATUS_SUCCESS on success +** +*******************************************************************************/ +bt_status_t btif_dut_mode_configure(uint8_t enable) +{ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + + if (btif_core_state != BTIF_CORE_STATE_ENABLED) { + BTIF_TRACE_ERROR0("btif_dut_mode_configure : Bluetooth not enabled"); + return BT_STATUS_NOT_READY; + } + + btif_dut_mode = enable; + if (enable == 1) { + BTA_EnableTestMode(); + } else { + BTA_DisableTestMode(); + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dut_mode_send +** +** Description Sends a HCI Vendor specific command to the controller +** +** Returns BT_STATUS_SUCCESS on success +** +*******************************************************************************/ +bt_status_t btif_dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len) +{ + /* TODO: Check that opcode is a vendor command group */ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + if (!btif_is_dut_mode()) { + BTIF_TRACE_ERROR0("Bluedroid HAL needs to be init with test_mode set to 1."); + return BT_STATUS_FAIL; + } + BTM_VendorSpecificCommand(opcode, len, buf, btif_dut_mode_cback); + return BT_STATUS_SUCCESS; +} +/***************************************************************************** +** +** btif api adapter property functions +** +*****************************************************************************/ + +static bt_status_t btif_in_get_adapter_properties(void) +{ + bt_property_t properties[6]; + uint32_t num_props; + + bt_bdaddr_t addr; + bt_bdname_t name; + bt_scan_mode_t mode; + uint32_t disc_timeout; + bt_bdaddr_t bonded_devices[BTM_SEC_MAX_DEVICE_RECORDS]; + bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS]; + num_props = 0; + + /* BD_ADDR */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDADDR, + sizeof(addr), &addr); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + /* BD_NAME */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDNAME, + sizeof(name), &name); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + /* SCAN_MODE */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_ADAPTER_SCAN_MODE, + sizeof(mode), &mode); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + /* DISC_TIMEOUT */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + sizeof(disc_timeout), &disc_timeout); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + /* BONDED_DEVICES */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_ADAPTER_BONDED_DEVICES, + sizeof(bonded_devices), bonded_devices); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + /* LOCAL UUIDs */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_UUIDS, + sizeof(local_uuids), local_uuids); + btif_storage_get_adapter_property(&properties[num_props]); + num_props++; + + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, + BT_STATUS_SUCCESS, num_props, properties); + + return BT_STATUS_SUCCESS; +} + +static bt_status_t btif_in_get_remote_device_properties(bt_bdaddr_t *bd_addr) +{ + bt_property_t remote_properties[8]; + uint32_t num_props = 0; + + bt_bdname_t name, alias; + uint32_t cod, devtype; + bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS]; + + memset(remote_properties, 0, sizeof(remote_properties)); + BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_BDNAME, + sizeof(name), &name); + btif_storage_get_remote_device_property(bd_addr, + &remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_REMOTE_FRIENDLY_NAME, + sizeof(alias), &alias); + btif_storage_get_remote_device_property(bd_addr, + &remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_CLASS_OF_DEVICE, + sizeof(cod), &cod); + btif_storage_get_remote_device_property(bd_addr, + &remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_TYPE_OF_DEVICE, + sizeof(devtype), &devtype); + btif_storage_get_remote_device_property(bd_addr, + &remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_FILL_PROPERTY(&remote_properties[num_props], BT_PROPERTY_UUIDS, + sizeof(remote_uuids), remote_uuids); + btif_storage_get_remote_device_property(bd_addr, + &remote_properties[num_props]); + num_props++; + + HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + BT_STATUS_SUCCESS, bd_addr, num_props, remote_properties); + + return BT_STATUS_SUCCESS; +} + + +/******************************************************************************* +** +** Function execute_storage_request +** +** Description Executes adapter storage request in BTIF context +** +** Returns bt_status_t +** +*******************************************************************************/ + +static void execute_storage_request(UINT16 event, char *p_param) +{ + uint8_t is_local; + int num_entries = 0; + bt_status_t status = BT_STATUS_SUCCESS; + + BTIF_TRACE_EVENT1("execute storage request event : %d", event); + + switch(event) + { + case BTIF_CORE_STORAGE_ADAPTER_WRITE: + { + btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; + bt_property_t *p_prop = &(p_req->write_req.prop); + BTIF_TRACE_EVENT3("type: %d, len %d, 0x%x", p_prop->type, + p_prop->len, p_prop->val); + + status = btif_storage_set_adapter_property(p_prop); + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, status, 1, p_prop); + } break; + + case BTIF_CORE_STORAGE_ADAPTER_READ: + { + btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; + char buf[512]; + bt_property_t prop; + prop.type = p_req->read_req.type; + prop.val = (void*)buf; + prop.len = sizeof(buf); + status = btif_storage_get_adapter_property(&prop); + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, status, 1, &prop); + } break; + + case BTIF_CORE_STORAGE_ADAPTER_READ_ALL: + { + status = btif_in_get_adapter_properties(); + } break; + + case BTIF_CORE_STORAGE_NOTIFY_STATUS: + { + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, status, 0, NULL); + } break; + + default: + BTIF_TRACE_ERROR2("%s invalid event id (%d)", __FUNCTION__, event); + break; + } +} + +static void execute_storage_remote_request(UINT16 event, char *p_param) +{ + bt_status_t status = BT_STATUS_FAIL; + bt_property_t prop; + + BTIF_TRACE_EVENT1("execute storage remote request event : %d", event); + + switch (event) + { + case BTIF_CORE_STORAGE_REMOTE_READ: + { + char buf[1024]; + btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; + prop.type = p_req->read_req.type; + prop.val = (void*) buf; + prop.len = sizeof(buf); + + status = btif_storage_get_remote_device_property(&(p_req->read_req.bd_addr), + &prop); + HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + status, &(p_req->read_req.bd_addr), 1, &prop); + }break; + case BTIF_CORE_STORAGE_REMOTE_WRITE: + { + btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; + status = btif_storage_set_remote_device_property(&(p_req->write_req.bd_addr), + &(p_req->write_req.prop)); + }break; + case BTIF_CORE_STORAGE_REMOTE_READ_ALL: + { + btif_storage_req_t *p_req = (btif_storage_req_t*)p_param; + btif_in_get_remote_device_properties(&p_req->read_req.bd_addr); + }break; + } +} + +void btif_adapter_properties_evt(bt_status_t status, uint32_t num_props, + bt_property_t *p_props) +{ + HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, + status, num_props, p_props); + +} +void btif_remote_properties_evt(bt_status_t status, bt_bdaddr_t *remote_addr, + uint32_t num_props, bt_property_t *p_props) +{ + HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + status, remote_addr, num_props, p_props); +} + +/******************************************************************************* +** +** Function btif_in_storage_request_copy_cb +** +** Description Switch context callback function to perform the deep copy for +** both the adapter and remote_device property API +** +** Returns None +** +*******************************************************************************/ +static void btif_in_storage_request_copy_cb(UINT16 event, + char *p_new_buf, char *p_old_buf) +{ + btif_storage_req_t *new_req = (btif_storage_req_t*)p_new_buf; + btif_storage_req_t *old_req = (btif_storage_req_t*)p_old_buf; + + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + switch (event) + { + case BTIF_CORE_STORAGE_REMOTE_WRITE: + case BTIF_CORE_STORAGE_ADAPTER_WRITE: + { + bdcpy(new_req->write_req.bd_addr.address, old_req->write_req.bd_addr.address); + /* Copy the member variables one at a time */ + new_req->write_req.prop.type = old_req->write_req.prop.type; + new_req->write_req.prop.len = old_req->write_req.prop.len; + + new_req->write_req.prop.val = (UINT8 *)(p_new_buf + sizeof(btif_storage_req_t)); + memcpy(new_req->write_req.prop.val, old_req->write_req.prop.val, + old_req->write_req.prop.len); + }break; + } +} + +/******************************************************************************* +** +** Function btif_get_adapter_properties +** +** Description Fetch all available properties (local & remote) +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_get_adapter_properties(void) +{ + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + return btif_transfer_context(execute_storage_request, + BTIF_CORE_STORAGE_ADAPTER_READ_ALL, + NULL, 0, NULL); +} + +/******************************************************************************* +** +** Function btif_get_adapter_property +** +** Description Fetches property value from local cache +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_get_adapter_property(bt_property_type_t type) +{ + btif_storage_req_t req; + + BTIF_TRACE_EVENT2("%s %d", __FUNCTION__, type); + + /* Allow get_adapter_property only for BDADDR and BDNAME if BT is disabled */ + if (!btif_is_enabled() && (type != BT_PROPERTY_BDADDR) && (type != BT_PROPERTY_BDNAME)) + return BT_STATUS_NOT_READY; + + memset(&(req.read_req.bd_addr), 0, sizeof(bt_bdaddr_t)); + req.read_req.type = type; + + return btif_transfer_context(execute_storage_request, + BTIF_CORE_STORAGE_ADAPTER_READ, + (char*)&req, sizeof(btif_storage_req_t), NULL); +} + +/******************************************************************************* +** +** Function btif_set_adapter_property +** +** Description Updates core stack with property value and stores it in +** local cache +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_set_adapter_property(const bt_property_t *property) +{ + btif_storage_req_t req; + bt_status_t status = BT_STATUS_SUCCESS; + int storage_req_id = BTIF_CORE_STORAGE_NOTIFY_STATUS; /* default */ + char bd_name[BTM_MAX_LOC_BD_NAME_LEN +1]; + UINT16 name_len = 0; + + BTIF_TRACE_EVENT3("btif_set_adapter_property type: %d, len %d, 0x%x", + property->type, property->len, property->val); + + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + switch(property->type) + { + case BT_PROPERTY_BDNAME: + { + name_len = property->len > BTM_MAX_LOC_BD_NAME_LEN ? BTM_MAX_LOC_BD_NAME_LEN: + property->len; + memcpy(bd_name,property->val, name_len); + bd_name[name_len] = '\0'; + + BTIF_TRACE_EVENT1("set property name : %s", (char *)bd_name); + + BTA_DmSetDeviceName((char *)bd_name); + + storage_req_id = BTIF_CORE_STORAGE_ADAPTER_WRITE; + } + break; + + case BT_PROPERTY_ADAPTER_SCAN_MODE: + { + bt_scan_mode_t mode = *(bt_scan_mode_t*)property->val; + tBTA_DM_DISC disc_mode; + tBTA_DM_CONN conn_mode; + + switch(mode) + { + case BT_SCAN_MODE_NONE: + disc_mode = BTA_DM_NON_DISC; + conn_mode = BTA_DM_NON_CONN; + break; + + case BT_SCAN_MODE_CONNECTABLE: + disc_mode = BTA_DM_NON_DISC; + conn_mode = BTA_DM_CONN; + break; + + case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: + disc_mode = BTA_DM_GENERAL_DISC; + conn_mode = BTA_DM_CONN; + break; + + default: + BTIF_TRACE_ERROR1("invalid scan mode (0x%x)", mode); + return BT_STATUS_PARM_INVALID; + } + + BTIF_TRACE_EVENT1("set property scan mode : %x", mode); + + BTA_DmSetVisibility(disc_mode, conn_mode, BTA_DM_IGNORE, BTA_DM_IGNORE); + + storage_req_id = BTIF_CORE_STORAGE_ADAPTER_WRITE; + } + break; + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + { + /* Nothing to do beside store the value in NV. Java + will change the SCAN_MODE property after setting timeout, + if required */ + storage_req_id = BTIF_CORE_STORAGE_ADAPTER_WRITE; + } + break; + case BT_PROPERTY_BDADDR: + case BT_PROPERTY_UUIDS: + case BT_PROPERTY_ADAPTER_BONDED_DEVICES: + case BT_PROPERTY_REMOTE_FRIENDLY_NAME: + /* no write support through HAL, these properties are only populated from BTA events */ + status = BT_STATUS_FAIL; + break; + default: + BTIF_TRACE_ERROR1("btif_get_adapter_property : invalid type %d", + property->type); + status = BT_STATUS_FAIL; + break; + } + + if (storage_req_id != BTIF_CORE_STORAGE_NO_ACTION) + { + int btif_status; + /* pass on to storage for updating local database */ + + memset(&(req.write_req.bd_addr), 0, sizeof(bt_bdaddr_t)); + memcpy(&(req.write_req.prop), property, sizeof(bt_property_t)); + + return btif_transfer_context(execute_storage_request, + storage_req_id, + (char*)&req, + sizeof(btif_storage_req_t)+property->len, + btif_in_storage_request_copy_cb); + } + + return status; + +} + +/******************************************************************************* +** +** Function btif_get_remote_device_property +** +** Description Fetches the remote device property from the NVRAM +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_get_remote_device_property(bt_bdaddr_t *remote_addr, + bt_property_type_t type) +{ + btif_storage_req_t req; + + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + memcpy(&(req.read_req.bd_addr), remote_addr, sizeof(bt_bdaddr_t)); + req.read_req.type = type; + return btif_transfer_context(execute_storage_remote_request, + BTIF_CORE_STORAGE_REMOTE_READ, + (char*)&req, sizeof(btif_storage_req_t), + NULL); +} + +/******************************************************************************* +** +** Function btif_get_remote_device_properties +** +** Description Fetches all the remote device properties from NVRAM +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_get_remote_device_properties(bt_bdaddr_t *remote_addr) +{ + btif_storage_req_t req; + + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + memcpy(&(req.read_req.bd_addr), remote_addr, sizeof(bt_bdaddr_t)); + return btif_transfer_context(execute_storage_remote_request, + BTIF_CORE_STORAGE_REMOTE_READ_ALL, + (char*)&req, sizeof(btif_storage_req_t), + NULL); +} + +/******************************************************************************* +** +** Function btif_set_remote_device_property +** +** Description Writes the remote device property to NVRAM. +** Currently, BT_PROPERTY_REMOTE_FRIENDLY_NAME is the only +** remote device property that can be set +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_set_remote_device_property(bt_bdaddr_t *remote_addr, + const bt_property_t *property) +{ + btif_storage_req_t req; + + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + memcpy(&(req.write_req.bd_addr), remote_addr, sizeof(bt_bdaddr_t)); + memcpy(&(req.write_req.prop), property, sizeof(bt_property_t)); + + return btif_transfer_context(execute_storage_remote_request, + BTIF_CORE_STORAGE_REMOTE_WRITE, + (char*)&req, + sizeof(btif_storage_req_t)+property->len, + btif_in_storage_request_copy_cb); +} + + +/******************************************************************************* +** +** Function btif_get_remote_service_record +** +** Description Looks up the service matching uuid on the remote device +** and fetches the SCN and service_name if the UUID is found +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_get_remote_service_record(bt_bdaddr_t *remote_addr, + bt_uuid_t *uuid) +{ + if (!btif_is_enabled()) + return BT_STATUS_NOT_READY; + + return btif_dm_get_remote_service_record(remote_addr, uuid); +} + + +/******************************************************************************* +** +** Function btif_get_enabled_services_mask +** +** Description Fetches currently enabled services +** +** Returns tBTA_SERVICE_MASK +** +*******************************************************************************/ + +tBTA_SERVICE_MASK btif_get_enabled_services_mask(void) +{ + return btif_enabled_services; +} + +/******************************************************************************* +** +** Function btif_enable_service +** +** Description Enables the service 'service_ID' to the service_mask. +** Upon BT enable, BTIF core shall invoke the BTA APIs to +** enable the profiles +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_enable_service(tBTA_SERVICE_ID service_id) +{ + tBTA_SERVICE_ID *p_id = &service_id; + + /* If BT is enabled, we need to switch to BTIF context and trigger the + * enable for that profile + * + * Otherwise, we just set the flag. On BT_Enable, the DM will trigger + * enable for the profiles that have been enabled */ + + btif_enabled_services |= (1 << service_id); + + BTIF_TRACE_ERROR2("%s: current services:0x%x", __FUNCTION__, btif_enabled_services); + + if (btif_is_enabled()) + { + btif_transfer_context(btif_dm_execute_service_request, + BTIF_DM_ENABLE_SERVICE, + (char*)p_id, sizeof(tBTA_SERVICE_ID), NULL); + } + + return BT_STATUS_SUCCESS; +} +/******************************************************************************* +** +** Function btif_disable_service +** +** Description Disables the service 'service_ID' to the service_mask. +** Upon BT disable, BTIF core shall invoke the BTA APIs to +** disable the profiles +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_disable_service(tBTA_SERVICE_ID service_id) +{ + tBTA_SERVICE_ID *p_id = &service_id; + + /* If BT is enabled, we need to switch to BTIF context and trigger the + * disable for that profile so that the appropriate uuid_property_changed will + * be triggerred. Otherwise, we just need to clear the service_id in the mask + */ + + btif_enabled_services &= (tBTA_SERVICE_MASK)(~(1<<service_id)); + + BTIF_TRACE_ERROR2("%s: Current Services:0x%x", __FUNCTION__, btif_enabled_services); + + if (btif_is_enabled()) + { + btif_transfer_context(btif_dm_execute_service_request, + BTIF_DM_DISABLE_SERVICE, + (char*)p_id, sizeof(tBTA_SERVICE_ID), NULL); + } + + return BT_STATUS_SUCCESS; +} |