diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /btif/src | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'btif/src')
-rw-r--r-- | btif/src/bluetooth.c | 381 | ||||
-rw-r--r-- | btif/src/btif_core.c | 1038 | ||||
-rw-r--r-- | btif/src/btif_dm.c | 1159 | ||||
-rw-r--r-- | btif/src/btif_hf.c | 1010 | ||||
-rw-r--r-- | btif/src/btif_storage.c | 1027 | ||||
-rw-r--r-- | btif/src/btif_util.c | 359 |
6 files changed, 4974 insertions, 0 deletions
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c new file mode 100644 index 0000000..766f685 --- /dev/null +++ b/btif/src/bluetooth.c @@ -0,0 +1,381 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: bluetooth.c + * + * Description: Bluetooth HAL implementation + * + ***********************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <hardware/bluetooth.h> +#include <hardware/bt_hf.h> + +#define LOG_NDDEBUG 0 +#define LOG_TAG "bluedroid" + +#include "btif_api.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +#define is_profile(profile, str) ((strlen(str) == strlen(profile)) && strncmp((const char *)profile, str, strlen(str)) == 0) + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/************************************************************************************ +** Static variables +************************************************************************************/ + +bt_callbacks_t *bt_hal_cbacks = NULL; + +/************************************************************************************ +** Static functions +************************************************************************************/ + +/************************************************************************************ +** Externs +************************************************************************************/ + +/* list all extended interfaces here */ + +/* handsfree profile */ +extern bthf_interface_t *btif_hf_get_interface(); + +/************************************************************************************ +** Functions +************************************************************************************/ + +static uint8_t interface_ready(void) +{ + /* add checks here that would prevent API calls other than init to be executed */ + if (bt_hal_cbacks == NULL) + return FALSE; + + return TRUE; +} + + +/***************************************************************************** +** +** BLUETOOTH HAL INTERFACE FUNCTIONS +** +*****************************************************************************/ + +static int init(bt_callbacks_t* callbacks ) +{ + LOGI("init"); + + /* store reference to user callbacks */ + bt_hal_cbacks = callbacks; + + /* add checks for individual callbacks ? */ + + /* init btif */ + btif_init_bluetooth(); + + return BT_STATUS_SUCCESS; +} + +static int enable( void ) +{ + LOGI("enable"); + + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_enable_bluetooth(); +} + +static int disable(void) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_disable_bluetooth(); +} + +static void cleanup( void ) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return; + + btif_shutdown_bluetooth(); + + /* hal callbacks reset upon shutdown complete callback */ + + return; +} + +static int get_adapter_properties(void) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_get_adapter_properties(); +} + +static int get_adapter_property(bt_property_type_t type) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_get_adapter_property(type); +} + +static int set_adapter_property(const bt_property_t *property) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_set_adapter_property(property); +} + +int get_remote_device_properties(bt_bdaddr_t *remote_addr) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_get_remote_device_properties(remote_addr); +} + +int get_remote_device_property(bt_bdaddr_t *remote_addr, bt_property_type_t type) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_get_remote_device_property(remote_addr, type); +} + +int set_remote_device_property(bt_bdaddr_t *remote_addr, const bt_property_t *property) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_set_remote_device_property(remote_addr, property); +} + +int get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_get_remote_service_record(remote_addr, uuid); +} + +static int start_discovery(void) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_start_discovery(); +} + +static int cancel_discovery(void) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_cancel_discovery(); +} + +static int create_bond(const bt_bdaddr_t *bd_addr) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_create_bond(bd_addr); +} + +static int cancel_bond(const bt_bdaddr_t *bd_addr) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_cancel_bond(bd_addr); +} + +static int remove_bond(const bt_bdaddr_t *bd_addr) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_remove_bond(bd_addr); +} + +static int pin_reply(const bt_bdaddr_t *bd_addr, uint8_t accept, + uint8_t pin_len, bt_pin_code_t *pin_code) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_pin_reply(bd_addr, accept, pin_len, pin_code); +} + +static int passkey_reply(const bt_bdaddr_t *bd_addr, uint8_t accept, + uint32_t passkey) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_passkey_reply(bd_addr, accept, passkey); +} + +static int ssp_reply(const bt_bdaddr_t *bd_addr, uint8_t accept) +{ + /* sanity check */ + if (interface_ready() == FALSE) + return BT_STATUS_NOT_READY; + + return btif_dm_ssp_reply(bd_addr, accept); +} + +static const void* get_profile_interface (const char *profile_id) +{ + LOGI("get_profile_interface %s", profile_id); + + /* check for supported profile interfaces */ + if (is_profile(profile_id, BT_PROFILE_HANDSFREE_ID)) + return btif_hf_get_interface(); + + if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID)) + return NULL; + + return NULL; +} + +static const bt_interface_t bluetoothInterface = { + sizeof(bt_interface_t), + init, + enable, + disable, + cleanup, + get_adapter_properties, + get_adapter_property, + set_adapter_property, + get_remote_device_properties, + get_remote_device_property, + set_remote_device_property, + get_remote_service_record, + start_discovery, + cancel_discovery, + create_bond, + remove_bond, + cancel_bond, + pin_reply, + passkey_reply, + ssp_reply, + get_profile_interface +}; + +const bt_interface_t* bluetooth__get_bluetooth_interface () +{ + /* fixme -- add property to disable bt interface ? */ + + return &bluetoothInterface; +} + +static int close_bluetooth_stack(struct hw_device_t* device) +{ + cleanup(); + return 0; +} + +static int open_bluetooth_stack (const struct hw_module_t* module, char const* name, +struct hw_device_t** abstraction) +{ + bluetooth_device_t *stack = malloc(sizeof(bluetooth_device_t) ); + memset(stack, 0, sizeof(bluetooth_device_t) ); + stack->common.tag = HARDWARE_DEVICE_TAG; + stack->common.version = 0; + stack->common.module = (struct hw_module_t*)module; + stack->common.close = close_bluetooth_stack; + stack->get_bluetooth_interface = bluetooth__get_bluetooth_interface; + *abstraction = (struct hw_device_t*)stack; + return 0; +} + + +static struct hw_module_methods_t bt_stack_module_methods = { + .open = open_bluetooth_stack, +}; + +const struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = BT_HARDWARE_MODULE_ID, + .name = "Bluetooth Stack", + .author = "The Android Open Source Project", + .methods = &bt_stack_module_methods +}; + diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c new file mode 100644 index 0000000..570a7c5 --- /dev/null +++ b/btif/src/btif_core.c @@ -0,0 +1,1038 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_core.c + * + * Description: Contains core functionality related to interfacing between + * Bluetooth HAL and BTE core stack. + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <string.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_storage.h" +#include "btif_util.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +#ifndef BTIF_TASK_STACK_SIZE +#define BTIF_TASK_STACK_SIZE 0//0x2000 /* In bytes */ +#endif + +#define BTIF_TASK_STR ((INT8 *) "BTIF") + +static UINT32 btif_task_stack[(BTIF_TASK_STACK_SIZE + 3) / 4]; + +/* checks whether any HAL operation other than enable is permitted */ +static int btif_enabled = 0; +static int btif_shutdown_pending = 0; + +/************************************************************************************ +** 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; +/************************************************************************************ +** Static variables +************************************************************************************/ + +/************************************************************************************ +** Static functions +************************************************************************************/ +static bt_status_t btif_init_bluetooth_evt(void); +static bt_status_t btif_shutdown_bluetooth_evt(void); + +/* sends message to btif task */ +static void btif_sendmsg(void *p_msg); + +/************************************************************************************ +** Externs +************************************************************************************/ + +/** TODO: Move these to _common.h */ +void bte_main_boot_entry(void); +void bte_main_enable(void); +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); + +/************************************************************************************ +** 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_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_init_bluetooth_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_shutdown_bluetooth_evt(); +} + + +/******************************************************************************* +** +** 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); +} + +/***************************************************************************** +** +** 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(void) +{ + UINT8 status; + + bte_main_boot_entry(); + + /* Start the 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_init_bluetooth_evt +** +** Description Event indicating bluetooth init is completed +** Attach btif_task to JVM +** +** Returns void +** +*******************************************************************************/ + +static bt_status_t btif_init_bluetooth_evt(void) +{ + BTIF_TRACE_DEBUG1("%s: notify ASSOCIATE_JVM", __FUNCTION__); + CHECK_CALL_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) +{ + tBTA_STATUS status = BT_STATUS_SUCCESS; + + LOGI("btif_enable_bluetooth"); + + if (btif_enabled == 1) + { + LOGD("already enabled\n"); + return BT_STATUS_DONE; + } + + /* add return status for create tasks functions ? */ + + /* Create the GKI tasks and run them */ + bte_main_enable(); + + if (status != BTA_SUCCESS) + return BT_STATUS_FAIL; + + 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)); + + 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) + { + /* store state */ + btif_enabled = 1; + CHECK_CALL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON); + } + else + { + btif_enabled = 0; + CHECK_CALL_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_enabled == 0) + { + BTIF_TRACE_ERROR0("btif_disable_bluetooth : not yet enabled"); + return BT_STATUS_FAIL; + } + + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + + status = BTA_DisableBluetooth(); + + if (status != BTA_SUCCESS) + { + BTIF_TRACE_ERROR1("disable bt failed (%d)", status); + 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__); + + bte_main_disable(); + + /* callback to HAL */ + CHECK_CALL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF); + + /* update local state */ + btif_enabled = 0; + + if (btif_shutdown_pending) + { + 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_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_SUCCESS; + } + + btif_shutdown_pending = 0; + + GKI_destroy_task(BTIF_TASK); + + bte_main_shutdown(); + + return BT_STATUS_SUCCESS; +} + +static bt_status_t btif_shutdown_bluetooth_evt(void) +{ + BTIF_TRACE_DEBUG1("%s: notify DISASSOCIATE_JVM", __FUNCTION__); + + CHECK_CALL_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 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++; + + CHECK_CALL_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++; + + CHECK_CALL_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); + CHECK_CALL_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); + CHECK_CALL_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: + { + CHECK_CALL_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); + CHECK_CALL_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) +{ + CHECK_CALL_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) +{ + CHECK_CALL_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_enabled == 0) + return BT_STATUS_FAIL; + + 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); + + if (btif_enabled == 0) + return BT_STATUS_FAIL; + + 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 */ + + BTIF_TRACE_EVENT3("btif_set_adapter_property type: %d, len %d, 0x%x", + property->type, property->len, property->val); + + if (btif_enabled == 0) + return BT_STATUS_FAIL; + + switch(property->type) + { + case BT_PROPERTY_BDNAME: + { + BTIF_TRACE_EVENT1("set property name : %s", (char *)property->val); + + BTA_DmSetDeviceName((char *)property->val); + + 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_BDADDR: + case BT_PROPERTY_UUIDS: + case BT_PROPERTY_ADAPTER_BONDED_DEVICES: + case BT_PROPERTY_REMOTE_FRIENDLY_NAME: + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + /* 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_enabled == 0) + return BT_STATUS_FAIL; + + 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_enabled == 0) + return BT_STATUS_FAIL; + + 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_enabled == 0) + return BT_STATUS_FAIL; + + 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_enabled == 0) + return BT_STATUS_FAIL; + + return btif_dm_get_remote_service_record(remote_addr, uuid); +} + diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c new file mode 100644 index 0000000..ddd187a --- /dev/null +++ b/btif/src/btif_dm.c @@ -0,0 +1,1159 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_dm.c + * + * Description: Contains Device Management (DM) related functionality + * + * + ***********************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <hardware/bluetooth.h> + +#include <utils/Log.h> + +#include "gki.h" +#include "btu.h" +#include "bd.h" +#include "bta_api.h" +#include "btif_api.h" +#include "btif_util.h" +#include "btif_storage.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define COD_UNCLASSIFIED ((0x1F) << 8) + +#define BTIF_DM_DEFAULT_INQ_MAX_RESULTS 0 +#define BTIF_DM_DEFAULT_INQ_MAX_DURATION 10 + +typedef struct { + BD_ADDR bd_addr; + UINT8 is_temp; + UINT8 pin_code_len; +} btif_dm_pairing_cb_t; + +#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) + +/****************************************************************************** +** Static functions +******************************************************************************/ +static btif_dm_pairing_cb_t pairing_cb; +static bt_status_t btif_dm_get_remote_services(bt_bdaddr_t *remote_addr); + +/****************************************************************************** +** Externs +******************************************************************************/ +extern UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID]; + +/****************************************************************************** +** Functions +******************************************************************************/ + +/******************************************************************************* +** +** Function check_eir_remote_name +** +** Description Check if remote name is in the EIR data +** +** Returns TRUE if remote name found +** Populate p_remote_name, if provided and remote name found +** +*******************************************************************************/ +static BOOLEAN check_eir_remote_name(tBTA_DM_SEARCH *p_search_data, + UINT8 *p_remote_name, UINT8 *p_remote_name_len) +{ + UINT8 *p_eir_remote_name = NULL; + UINT8 remote_name_len = 0; + + /* Check EIR for remote name and services */ + if (p_search_data->inq_res.p_eir) + { + p_eir_remote_name = BTA_CheckEirData(p_search_data->inq_res.p_eir, + BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len); + if (!p_eir_remote_name) + { + p_eir_remote_name = BTA_CheckEirData(p_search_data->inq_res.p_eir, + BTM_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len); + } + + if (p_eir_remote_name) + { + if (remote_name_len > BD_NAME_LEN) + remote_name_len = BD_NAME_LEN; + + if (p_remote_name && p_remote_name_len) + { + memcpy(p_remote_name, p_eir_remote_name, remote_name_len); + *(p_remote_name + remote_name_len) = 0; + *p_remote_name_len = remote_name_len; + } + + return TRUE; + } + } + + return FALSE; + +} + +/******************************************************************************* +** +** Function check_cached_remote_name +** +** Description Check if remote name is in the NVRAM cache +** +** Returns TRUE if remote name found +** Populate p_remote_name, if provided and remote name found +** +*******************************************************************************/ +static BOOLEAN check_cached_remote_name(tBTA_DM_SEARCH *p_search_data, + UINT8 *p_remote_name, UINT8 *p_remote_name_len) +{ + bt_bdname_t bdname; + bt_bdaddr_t remote_bdaddr; + bt_property_t prop_name; + + /* check if we already have it in our btif_storage cache */ + bdcpy(remote_bdaddr.address, p_search_data->inq_res.bd_addr); + BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME, + sizeof(bt_bdname_t), &bdname); + if (btif_storage_get_remote_device_property( + &remote_bdaddr, &prop_name) == BT_STATUS_SUCCESS) + { + if (p_remote_name && p_remote_name_len) + { + strcpy((char *)p_remote_name, (char *)bdname.name); + *p_remote_name_len = strlen((char *)p_remote_name); + } + return TRUE; + } + + return FALSE; +} + +/******************************************************************************* +** +** Function search_devices_copy_cb +** +** Description Deep copy callback for search devices event +** +** Returns void +** +*******************************************************************************/ +static void search_devices_copy_cb(UINT16 event, char *p_dest, char *p_src) +{ + tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest; + tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src; + + if (!p_src) + return; + + BTIF_TRACE_DEBUG2("%s: event=%s", __FUNCTION__, dump_dm_search_event(event)); + memcpy(p_dest_data, p_src_data, sizeof(tBTA_DM_SEARCH)); + switch (event) + { + case BTA_DM_INQ_RES_EVT: + { + if (p_src_data->inq_res.p_eir) + { + p_dest_data->inq_res.p_eir = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->inq_res.p_eir, p_src_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN); + } + } + break; + + case BTA_DM_DISC_RES_EVT: + { + if (p_src_data->disc_res.raw_data_size && p_src_data->disc_res.p_raw_data) + { + p_dest_data->disc_res.p_raw_data = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->disc_res.p_raw_data, + p_src_data->disc_res.p_raw_data, p_src_data->disc_res.raw_data_size); + } + } + break; + } +} + +/****************************************************************************** +** +** BTIF DM callback events +** +*****************************************************************************/ + +/******************************************************************************* +** +** Function btif_dm_pin_req_evt +** +** Description Executes pin request event in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ *p_pin_req) +{ + bt_bdaddr_t bd_addr; + bt_bdname_t bd_name; + UINT32 cod; + + bdcpy(bd_addr.address, p_pin_req->bd_addr); + memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN); + + memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t)); + bdcpy(pairing_cb.bd_addr, p_pin_req->bd_addr); + + cod = devclass2uint(p_pin_req->dev_class); + + if ( cod == 0) { + LOGD("cod is 0, set as unclassified"); + cod = COD_UNCLASSIFIED; + } + + CHECK_CALL_CBACK(bt_hal_cbacks, pin_request_cb, + &bd_addr, &bd_name, cod); +} + +/******************************************************************************* +** +** Function btif_dm_ssp_cfm_req_evt +** +** Description Executes SSP confirm request event in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ *p_ssp_cfm_req) +{ + bt_bdaddr_t bd_addr; + bt_bdname_t bd_name; + UINT32 cod; + + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + bdcpy(bd_addr.address, p_ssp_cfm_req->bd_addr); + memcpy(bd_name.name, p_ssp_cfm_req->bd_name, BD_NAME_LEN); + + /* Set the pairing_cb based on the local & remote authentication requirements */ + memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t)); + bdcpy(pairing_cb.bd_addr, p_ssp_cfm_req->bd_addr); + + if ((p_ssp_cfm_req->loc_auth_req >= BTM_AUTH_AP_NO && p_ssp_cfm_req->rmt_auth_req >= BTM_AUTH_AP_NO) || + (p_ssp_cfm_req->loc_auth_req == BTM_AUTH_AP_NO || p_ssp_cfm_req->loc_auth_req == BTM_AUTH_AP_YES) || + (p_ssp_cfm_req->rmt_auth_req == BTM_AUTH_AP_NO || p_ssp_cfm_req->rmt_auth_req == BTM_AUTH_AP_YES)) + pairing_cb.is_temp = FALSE; + else + pairing_cb.is_temp = TRUE; + + /* If JustWorks auto-accept */ + if (p_ssp_cfm_req->just_works) + { + BTIF_TRACE_EVENT1("%s: Auto-accept JustWorks pairing", __FUNCTION__); + btif_dm_ssp_reply(&bd_addr, TRUE); + return; + } + + cod = devclass2uint(p_ssp_cfm_req->dev_class); + + if ( cod == 0) { + LOGD("cod is 0, set as unclassified"); + cod = COD_UNCLASSIFIED; + } + + /* TODO: pairing variant? */ + CHECK_CALL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name, + cod, BT_SSP_VARIANT_CONSENT, + p_ssp_cfm_req->num_val); +} + +/******************************************************************************* +** +** Function btif_dm_auth_cmpl_evt +** +** Description Executes authentication complete event in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) +{ + /* Save link key, if not temporary */ + bt_bdaddr_t bd_addr; + bt_status_t status = BT_STATUS_FAIL; + bt_bond_state_t state = BT_BOND_STATE_NONE; + + bdcpy(bd_addr.address, p_auth_cmpl->bd_addr); + if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) ) + { + if ((p_auth_cmpl->key_type < HCI_LKEY_TYPE_DEBUG_COMB) || (p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB) || + (p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) || (!pairing_cb.is_temp)) + { + bt_status_t ret; + BTIF_TRACE_DEBUG3("%s: Storing link key. key_type=0x%x, is_temp=%d", + __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.is_temp); + ret = btif_storage_add_bonded_device(&bd_addr, + p_auth_cmpl->key, p_auth_cmpl->key_type, + pairing_cb.pin_code_len); + ASSERTC(ret == BT_STATUS_SUCCESS, "storing link key failed", ret); + } + else + { + BTIF_TRACE_DEBUG3("%s: Temporary key. Not storing. key_type=0x%x, is_temp=%d", + __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.is_temp); + } + } + + if (p_auth_cmpl->success) + { + status = BT_STATUS_SUCCESS; + state = BT_BOND_STATE_BONDED; + + /* Trigger SDP on the device */ + btif_dm_get_remote_services(&bd_addr); + } + + CHECK_CALL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &bd_addr, state); + + memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t)); +} + +/****************************************************************************** +** +** Function btif_dm_search_devices_evt +** +** Description Executes search devices callback events in btif context +** +** Returns void +** +******************************************************************************/ +static void btif_dm_search_devices_evt (UINT16 event, char *p_param) +{ + tBTA_DM_SEARCH *p_search_data; + BTIF_TRACE_EVENT2("%s event=%s", __FUNCTION__, dump_dm_search_event(event)); + + switch (event) + { + case BTA_DM_DISC_RES_EVT: + { + p_search_data = (tBTA_DM_SEARCH *)p_param; + /* Remote name update */ + if (strlen((const char *) p_search_data->disc_res.bd_name)) + { + bt_property_t properties[1]; + bt_bdaddr_t bdaddr; + bt_status_t status; + + properties[0].type = BT_PROPERTY_BDNAME; + properties[0].val = p_search_data->disc_res.bd_name; + properties[0].len = strlen((char *)p_search_data->disc_res.bd_name)+1; + bdcpy(bdaddr.address, p_search_data->disc_res.bd_addr); + + status = btif_storage_set_remote_device_property(&bdaddr, &properties[0]); + ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device property", status); + CHECK_CALL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + status, &bdaddr, 1, properties); + } + /* TODO: Services? */ + } + break; + + case BTA_DM_INQ_RES_EVT: + { + /* inquiry result */ + UINT32 cod; + UINT8 *p_eir_remote_name = NULL; + bt_bdname_t bdname; + bt_bdaddr_t bdaddr; + UINT8 remote_name_len; + UINT8 *p_cached_name = NULL; + tBTA_SERVICE_MASK services = 0; + bdstr_t bdstr; + + p_search_data = (tBTA_DM_SEARCH *)p_param; + bdcpy(bdaddr.address, p_search_data->inq_res.bd_addr); + + BTIF_TRACE_DEBUG3("%s() %s device_type = 0x%x\n", __FUNCTION__, bd2str(&bdaddr, &bdstr), +#if (BLE_INCLUDED == TRUE) + p_search_data->inq_res.device_type); +#else + BT_DEVICE_TYPE_BREDR); +#endif + bdname.name[0] = 0; + + cod = devclass2uint (p_search_data->inq_res.dev_class); + + if ( cod == 0) { + LOGD("cod is 0, set as unclassified"); + cod = COD_UNCLASSIFIED; + } + + if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len)) + check_cached_remote_name(p_search_data, bdname.name, &remote_name_len); + + /* Check EIR for remote name and services */ + if (p_search_data->inq_res.p_eir) + { + BTA_GetEirService(p_search_data->inq_res.p_eir, &services); + BTIF_TRACE_DEBUG2("%s()EIR BTA services = %08X", __FUNCTION__, (UINT32)services); + /* TODO: Get the service list and check to see which uuids we got and send it back to the client. */ + } + + + { + bt_property_t properties[5]; + bt_device_type_t dev_type; + uint32_t num_properties = 0; + bt_status_t status; + + memset(properties, 0, sizeof(properties)); + /* BD_ADDR */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr); + num_properties++; + /* BD_NAME */ + /* Don't send BDNAME if it is empty */ + if (bdname.name[0]) { + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_BDNAME, + strlen((char *)bdname.name)+1, &bdname); + num_properties++; + } + + /* DEV_CLASS */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); + num_properties++; + /* DEV_TYPE */ +#if (BLE_INCLUDED == TRUE) + /* FixMe: Assumption is that bluetooth.h and BTE enums match */ + dev_type = p_search_data->inq_res.device_type; +#else + dev_type = BT_DEVICE_TYPE_BREDR; +#endif + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type); + num_properties++; + /* RSSI */ + BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], + BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t), + &(p_search_data->inq_res.rssi)); + num_properties++; + + status = btif_storage_add_remote_device(&bdaddr, num_properties, properties); + ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device (inquiry)", status); + + /* Callback to notify upper layer of device */ + CHECK_CALL_CBACK(bt_hal_cbacks, device_found_cb, + num_properties, properties); + } + } + break; + + case BTA_DM_INQ_CMPL_EVT: + { + } + break; + + case BTA_DM_DISC_CMPL_EVT: + case BTA_DM_SEARCH_CANCEL_CMPL_EVT: + { + CHECK_CALL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STOPPED); + } + break; + } +} + +/******************************************************************************* +** +** Function btif_dm_search_services_evt +** +** Description Executes search services event in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_search_services_evt(UINT16 event, char *p_param) +{ + tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH*)p_param; + + BTIF_TRACE_EVENT2("%s: event = %d", __FUNCTION__, event); + switch (event) + { + case BTA_DM_DISC_RES_EVT: + { + bt_uuid_t uuid_arr[BT_MAX_NUM_UUIDS]; /* Max 32 services */ + bt_property_t prop; + uint32_t i = 0, j = 0; + bt_bdaddr_t bd_addr; + bt_status_t ret; + + bdcpy(bd_addr.address, p_data->disc_res.bd_addr); + + BTIF_TRACE_DEBUG3("%s:(result=0x%x, services 0x%x)", __FUNCTION__, + p_data->disc_res.result, p_data->disc_res.services); + prop.type = BT_PROPERTY_UUIDS; + prop.val = (void*)uuid_arr; + prop.len = 0; + for (i=0; i < BTA_MAX_SERVICE_ID; i++) + { + if(p_data->disc_res.services + &(tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i))) + { + memset(&uuid_arr[j], 0, sizeof(bt_uuid_t)); + uuid16_to_uuid128(bta_service_id_to_uuid_lkup_tbl[i], &uuid_arr[j]); + prop.len += sizeof(bt_uuid_t); + j++; + } + } + /* Also write this to the NVRAM */ + ret = btif_storage_set_remote_device_property(&bd_addr, &prop); + ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", ret); + + /* Send the event to the BTIF */ + CHECK_CALL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + BT_STATUS_SUCCESS, &bd_addr, 1, &prop); + } + break; + + default: + { + ASSERTC(0, "unhandled search services event", event); + } + break; + } +} + +/******************************************************************************* +** +** Function btif_dm_remote_service_record_evt +** +** Description Executes search service record event in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_remote_service_record_evt(UINT16 event, char *p_param) +{ + tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH*)p_param; + + BTIF_TRACE_EVENT2("%s: event = %d", __FUNCTION__, event); + switch (event) + { + case BTA_DM_DISC_RES_EVT: + { + bt_service_record_t rec; + bt_property_t prop; + uint32_t i = 0; + bt_bdaddr_t bd_addr; + + memset(&rec, 0, sizeof(bt_service_record_t)); + bdcpy(bd_addr.address, p_data->disc_res.bd_addr); + + BTIF_TRACE_DEBUG3("%s:(result=0x%x, services 0x%x)", __FUNCTION__, + p_data->disc_res.result, p_data->disc_res.services); + prop.type = BT_PROPERTY_SERVICE_RECORD; + prop.val = (void*)&rec; + prop.len = sizeof(rec); + + /* disc_res.result is overloaded with SCN. Cannot check result */ + p_data->disc_res.services &= ~BTA_USER_SERVICE_MASK; + /* TODO: Get the UUID as well */ + rec.channel = p_data->disc_res.result - 3; + /* TODO: Need to get the service name using p_raw_data */ + rec.name[0] = 0; + + CHECK_CALL_CBACK(bt_hal_cbacks, remote_device_properties_cb, + BT_STATUS_SUCCESS, &bd_addr, 1, &prop); + } + break; + + default: + { + ASSERTC(0, "unhandled remote service record event", event); + } + break; + } +} + +/******************************************************************************* +** +** Function btif_dm_upstreams_cback +** +** Description Executes UPSTREAMS events in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_upstreams_evt(UINT16 event, char* p_param) +{ + tBTA_DM_SEC_EVT dm_event = (tBTA_DM_SEC_EVT)event; + tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param; + + BTIF_TRACE_EVENT1("btif_dm_upstreams_cback ev: %d", event); + + switch (event) + { + case BTA_DM_ENABLE_EVT: + { + BD_NAME bdname; + bt_status_t status; + bt_property_t prop; + prop.type = BT_PROPERTY_BDNAME; + prop.len = 0; + prop.val = (void*)bdname; + + status = btif_storage_get_adapter_property(&prop); + /* Storage does not have a name yet. + ** Use the default name and write it to the chip + */ + if (status != BT_STATUS_SUCCESS) + { + /* TODO: BTM_DEF_LOCAL_NAME should be configurable */ + BTA_DmSetDeviceName(BTM_DEF_LOCAL_NAME); + /* Hmmm...Should we store this too??? */ + } + else + { + /* A name exists in the storage. Make this the device name */ + BTA_DmSetDeviceName((char*)prop.val); + } + /* This function will also trigger the adapter_properties_cb + ** and bonded_devices_info_cb + */ + btif_storage_load_bonded_devices(); + btif_enable_bluetooth_evt(p_data->enable.status, p_data->enable.bd_addr); + } + break; + + case BTA_DM_DISABLE_EVT: + btif_disable_bluetooth_evt(); + break; + + case BTA_DM_PIN_REQ_EVT: + btif_dm_pin_req_evt(&p_data->pin_req); + break; + + case BTA_DM_AUTH_CMPL_EVT: + btif_dm_auth_cmpl_evt(&p_data->auth_cmpl); + break; + + case BTA_DM_SP_CFM_REQ_EVT: + btif_dm_ssp_cfm_req_evt(&p_data->cfm_req); + break; + + case BTA_DM_AUTHORIZE_EVT: + case BTA_DM_LINK_DOWN_EVT: + case BTA_DM_SIG_STRENGTH_EVT: + case BTA_DM_BUSY_LEVEL_EVT: + case BTA_DM_BOND_CANCEL_CMPL_EVT: + case BTA_DM_SP_KEY_NOTIF_EVT: + case BTA_DM_SP_RMT_OOB_EVT: + case BTA_DM_SP_KEYPRESS_EVT: + case BTA_DM_ROLE_CHG_EVT: + case BTA_DM_BLE_KEY_EVT: + case BTA_DM_BLE_SEC_REQ_EVT: + case BTA_DM_BLE_PASSKEY_NOTIF_EVT: + case BTA_DM_BLE_PASSKEY_REQ_EVT: + case BTA_DM_BLE_OOB_REQ_EVT: + case BTA_DM_BLE_LOCAL_IR_EVT: + case BTA_DM_BLE_LOCAL_ER_EVT: + case BTA_DM_BLE_AUTH_CMPL_EVT: + default: + BTIF_TRACE_WARNING1( "btif_dm_cback : unhandled event (%d)", event ); + break; + } +} /* btui_security_cback() */ + + +/******************************************************************************* +** +** Function btif_dm_generic_evt +** +** Description Executes non-BTA upstream events in BTIF context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_generic_evt(UINT16 event, char* p_param) +{ + BTIF_TRACE_EVENT2("%s: event=%d", __FUNCTION__, event); + switch(event) + { + case BTIF_DM_CB_DISCOVERY_STARTED: + { + CHECK_CALL_CBACK(bt_hal_cbacks, discovery_state_changed_cb, BT_DISCOVERY_STARTED); + } + break; + + case BTIF_DM_CB_REMOVED_BONDING: + { + bt_bdaddr_t *bd_addr = (bt_bdaddr_t*)p_param; + bt_status_t status; + + status = btif_storage_remove_bonded_device(bd_addr); + ASSERTC(status == BT_STATUS_SUCCESS, "failed to delete bonded device", status); + + CHECK_CALL_CBACK(bt_hal_cbacks, bond_state_changed_cb, + BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_NONE); + } + break; + + default: + { + BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event); + } + break; + } +} + +/******************************************************************************* +** +** Function bte_dm_evt +** +** Description Switches context from BTE to BTIF for all DM events +** +** Returns void +** +*******************************************************************************/ + +void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data) +{ + bt_status_t status; + + /* switch context to btif task context (copy full union size for convenience) */ + status = btif_transfer_context(btif_dm_upstreams_evt, (uint16_t)event, (void*)p_data, sizeof(tBTA_DM_SEC), NULL); + + /* catch any failed context transfers */ + ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status); +} + +/******************************************************************************* +** +** Function bte_search_devices_evt +** +** Description Switches context from BTE to BTIF for DM search events +** +** Returns void +** +*******************************************************************************/ +static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) +{ + UINT16 param_len = 0; + + if (p_data) + param_len += sizeof(tBTA_DM_SEARCH); + /* Allocate buffer to hold the pointers (deep copy). The pointers will point to the end of the tBTA_DM_SEARCH */ + switch (event) + { + case BTA_DM_INQ_RES_EVT: + { + if (p_data->inq_res.p_eir) + param_len += HCI_EXT_INQ_RESPONSE_LEN; + } + break; + + case BTA_DM_DISC_RES_EVT: + { + if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data) + param_len += p_data->disc_res.raw_data_size; + } + break; + } + BTIF_TRACE_DEBUG3("%s event=%s param_len=%d", __FUNCTION__, dump_dm_search_event(event), param_len); + + /* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */ + if (event == BTA_DM_INQ_RES_EVT) + p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL); + + btif_transfer_context (btif_dm_search_devices_evt , (UINT16) event, (void *)p_data, param_len, + (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL); +} + +/******************************************************************************* +** +** Function bte_dm_search_services_evt +** +** Description Switches context from BTE to BTIF for DM search services +** event +** +** Returns void +** +*******************************************************************************/ +static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) +{ + /* TODO: The only member that needs a deep copy is the p_raw_data. But not sure yet if this is needed. */ + btif_transfer_context(btif_dm_search_services_evt, event, (char*)p_data, sizeof(tBTA_DM_SEARCH), NULL); +} + +/******************************************************************************* +** +** Function bte_dm_remote_service_record_evt +** +** Description Switches context from BTE to BTIF for DM search service +** record event +** +** Returns void +** +*******************************************************************************/ +static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) +{ + /* TODO: The only member that needs a deep copy is the p_raw_data. But not sure yet if this is needed. */ + btif_transfer_context(btif_dm_remote_service_record_evt, event, (char*)p_data, sizeof(tBTA_DM_SEARCH), NULL); +} + +/***************************************************************************** +** +** btif api functions (no context switch) +** +*****************************************************************************/ + +/******************************************************************************* +** +** Function btif_dm_start_discovery +** +** Description Start device discovery/inquiry +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_start_discovery(void) +{ + tBTA_DM_INQ inq_params; + tBTA_SERVICE_MASK services = 0; + + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + /* TODO: Do we need to handle multiple inquiries at the same time? */ + + /* Set inquiry params and call API */ +#if (BLE_INCLUDED == TRUE) + inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_GENERAL_INQUIRY; +#else + inq_params.mode = BTA_DM_GENERAL_INQUIRY; +#endif + inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION; + + inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS; + inq_params.report_dup = TRUE; + + inq_params.filter_type = BTA_DM_INQ_CLR; + /* TODO: Filter device by BDA needs to be implemented here */ + + /* find nearby devices */ + BTA_DmSearch(&inq_params, services, bte_search_devices_evt); + + /* Invoke the discovery_started callback */ + btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_DISCOVERY_STARTED, NULL, 0, NULL); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_cancel_discovery +** +** Description Cancels search +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_cancel_discovery(void) +{ + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + BTA_DmSearchCancel(); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_create_bond +** +** Description Initiate bonding with the specified device +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr) +{ + bdstr_t bdstr; + + BTIF_TRACE_EVENT2("%s: bd_addr=%s", __FUNCTION__, bd2str((bt_bdaddr_t *) bd_addr, &bdstr)); + + /* TODO: + ** 1. Check if ACL is already up with this device + ** 2. Disable unpaired devices from connecting while we are bonding + ** 3. special handling for HID devices + */ + + BTA_DmBond ((UINT8 *)bd_addr->address); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_cancel_bond +** +** Description Initiate bonding with the specified device +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_dm_cancel_bond(const bt_bdaddr_t *bd_addr) +{ + bdstr_t bdstr; + + BTIF_TRACE_EVENT2("%s: bd_addr=%s", __FUNCTION__, bd2str((bt_bdaddr_t *)bd_addr, &bdstr)); + + /* TODO: + ** 1. Check if ACL is already up with this device + ** 2. Restore scan modes + ** 3. special handling for HID devices + */ + BTA_DmBondCancel ((UINT8 *)bd_addr->address); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_remove_bond +** +** Description Removes bonding with the specified device +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_dm_remove_bond(const bt_bdaddr_t *bd_addr) +{ + bdstr_t bdstr; + + BTIF_TRACE_EVENT2("%s: bd_addr=%s", __FUNCTION__, bd2str((bt_bdaddr_t *)bd_addr, &bdstr)); + + /* TODO: special handling for HID devices */ + if (BTA_DmRemoveDevice((UINT8 *)bd_addr->address) == BTA_SUCCESS) + { + BTIF_TRACE_DEBUG1("Successfully removed bonding with device: %s", + bd2str((bt_bdaddr_t *)bd_addr, &bdstr)); + + /* Device shall be removed from the storage in the btif context */ + btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_REMOVED_BONDING, + (char*)bd_addr, sizeof(bt_bdaddr_t), NULL); + } + else + { + /* TODO: ACL is already up with this device, disconnect and then issue RemoveBond */ + BTIF_TRACE_WARNING0("ACL connection exists with device. Disconnect and issue remove bonding"); + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_pin_reply +** +** Description BT legacy pairing - PIN code reply +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_dm_pin_reply( const bt_bdaddr_t *bd_addr, uint8_t accept, + uint8_t pin_len, bt_pin_code_t *pin_code) +{ + BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept); + + BTA_DmPinReply( (UINT8 *)bd_addr->address, accept, pin_len, pin_code->pin); + + if (accept) + pairing_cb.pin_code_len = pin_len; + else + memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t)); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_passkey_reply +** +** Description BT SSP passkey reply +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_dm_passkey_reply(const bt_bdaddr_t *bd_addr, + uint8_t accept, uint32_t passkey) +{ + /* This is not implemented in the stack. + ** For devices with display, this is not needed + */ + BTIF_TRACE_WARNING1("%s: Not implemented", __FUNCTION__); + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function btif_dm_ssp_reply +** +** Description BT SSP Reply - Just Works & Numeric Comparison +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_dm_ssp_reply(const bt_bdaddr_t *bd_addr, uint8_t accept) +{ + BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept); + BTA_DmConfirm( (UINT8 *)bd_addr->address, accept); + if (!accept) + memset(&pairing_cb, 0, sizeof(btif_dm_pairing_cb_t)); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_get_adapter_property +** +** Description Queries the BTA for the adapter property +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_get_adapter_property(bt_property_t *prop) +{ + bt_status_t status; + + BTIF_TRACE_EVENT2("%s: type=0x%x", __FUNCTION__, prop->type); + switch (prop->type) + { + case BT_PROPERTY_BDNAME: + { + bt_bdname_t *bd_name = (bt_bdname_t*)prop->val; + strcpy((char *)bd_name->name, BTM_DEF_LOCAL_NAME); + prop->len = strlen((char *)bd_name->name)+1; + } + break; + + case BT_PROPERTY_ADAPTER_SCAN_MODE: + { + /* if the storage does not have it. Most likely app never set it. Default is NONE */ + bt_scan_mode_t *mode = (bt_scan_mode_t*)prop->val; + *mode = BT_SCAN_MODE_NONE; + prop->len = sizeof(bt_scan_mode_t); + } + break; + + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + { + uint32_t *tmt = (uint32_t*)prop->val; + *tmt = 0; + prop->len = sizeof(uint32_t); + } + break; + + default: + prop->len = 0; + return BT_STATUS_FAIL; + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_get_remote_services +** +** Description Start SDP to get remote services +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_get_remote_services(bt_bdaddr_t *remote_addr) +{ + bdstr_t bdstr; + + BTIF_TRACE_EVENT2("%s: remote_addr=%s", __FUNCTION__, bd2str(remote_addr, &bdstr)); + + BTA_DmDiscover(remote_addr->address, BTA_ALL_SERVICE_MASK, + bte_dm_search_services_evt, TRUE); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_dm_get_remote_service_record +** +** Description Start SDP to get remote service record +** +** +** Returns bt_status_t +*******************************************************************************/ +bt_status_t btif_dm_get_remote_service_record(bt_bdaddr_t *remote_addr, + bt_uuid_t *uuid) +{ + tSDP_UUID sdp_uuid; + bdstr_t bdstr; + + BTIF_TRACE_EVENT2("%s: remote_addr=%s", __FUNCTION__, bd2str(remote_addr, &bdstr)); + + sdp_uuid.len = MAX_UUID_SIZE; + memcpy(sdp_uuid.uu.uuid128, uuid->uu, MAX_UUID_SIZE); + + BTA_DmDiscoverUUID(remote_addr->address, &sdp_uuid, + bte_dm_remote_service_record_evt, TRUE); + + return BT_STATUS_SUCCESS; +} diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c new file mode 100644 index 0000000..7f0e6bc --- /dev/null +++ b/btif/src/btif_hf.c @@ -0,0 +1,1010 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_hf.c + * + * Description: Handsfree Profile Bluetooth Interface + * + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <hardware/bt_hf.h> + +#define LOG_TAG "BTIF_HF" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" +#include "bta_ag_api.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ +/* TODO: Should these be moved to a conf file? */ +#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK) +#define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) +#define BTIF_HF_FEATURES (BTA_AG_FEAT_ECNR | \ + BTA_AG_FEAT_REJECT | \ + BTA_AG_FEAT_ECS | \ + BTA_AG_FEAT_ECC | \ + BTA_AG_FEAT_EXTERR | \ + BTA_AG_FEAT_BTRH | \ + BTA_AG_FEAT_VREC) +#define BTIF_HSAG_SERVICE_NAME ("Headset Gateway") +#define BTIF_HFAG_SERVICE_NAME ("Handsfree Gateway") + +#define BTIF_HF_ID_1 0 + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/************************************************************************************ +** Static variables +************************************************************************************/ +static bthf_callbacks_t *bt_hf_callbacks = NULL; + +#define CHECK_BTHF_INIT() if (bt_hf_callbacks == NULL)\ + {\ + BTIF_TRACE_WARNING1("BTHF: %s: BTHF not initialized", __FUNCTION__);\ + return BT_STATUS_NOT_READY;\ + }\ + else\ + {\ + BTIF_TRACE_EVENT1("BTHF: %s", __FUNCTION__);\ + } + + +/* BTIF-HF control block to map bdaddr to BTA handle */ +typedef struct _btif_hf_cb +{ + UINT16 handle; + bt_bdaddr_t connected_bda; + bthf_connection_state_t state; + bthf_vr_state_t vr_state; + tBTA_AG_PEER_FEAT peer_feat; + int num_active; + int num_held; + bthf_call_state_t call_setup_state; +} btif_hf_cb_t; + +static btif_hf_cb_t btif_hf_cb; + + +/************************************************************************************ +** Static functions +************************************************************************************/ + +/************************************************************************************ +** Externs +************************************************************************************/ + +/************************************************************************************ +** Functions +************************************************************************************/ + +/******************************************************************************* +** +** Function is_connected +** +** Description Internal function to check if HF is connected +** +** Returns TRUE if connected +** +*******************************************************************************/ +static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) +{ + if ((btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTED) && + ((bd_addr == NULL) || (bdcmp(bd_addr->address, btif_hf_cb.connected_bda.address) == 0))) + return TRUE; + else + return FALSE; +} + +/******************************************************************************* +** +** Function callstate_to_callsetup +** +** Description Converts HAL call state to BTA call setup indicator value +** +** Returns BTA call indicator value +** +*******************************************************************************/ +static UINT8 callstate_to_callsetup(bthf_call_state_t call_state) +{ + UINT8 call_setup = 0; + if (call_state == BTHF_CALL_STATE_INCOMING) + call_setup = 1; + if (call_state == BTHF_CALL_STATE_DIALING) + call_setup = 2; + if (call_state == BTHF_CALL_STATE_ALERTING) + call_setup = 3; + + return call_setup; +} + +/******************************************************************************* +** +** Function send_at_result +** +** Description Send AT result code (OK/ERROR) +** +** Returns void +** +*******************************************************************************/ +static void send_at_result(UINT8 ok_flag, UINT16 errcode) +{ + tBTA_AG_RES_DATA ag_res; + memset (&ag_res, 0, sizeof (ag_res)); + + ag_res.ok_flag = ok_flag; + if (ok_flag == BTA_AG_OK_ERROR) + { + ag_res.errcode = errcode; + } + + BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res); +} + +/******************************************************************************* +** +** Function send_indicator_update +** +** Description Send indicator update (CIEV) +** +** Returns void +** +*******************************************************************************/ +static void send_indicator_update (UINT16 indicator, UINT16 value) +{ + tBTA_AG_RES_DATA ag_res; + + memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); + ag_res.ind.id = indicator; + ag_res.ind.value = value; + + BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res); +} + +/***************************************************************************** +** Section name (Group of functions) +*****************************************************************************/ + +/***************************************************************************** +** +** btif hf api functions (no context switch) +** +*****************************************************************************/ + + +/******************************************************************************* +** +** Function btif_hf_upstreams_evt +** +** Description Executes HF UPSTREAMS events in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_hf_upstreams_evt(UINT16 event, char* p_param) +{ + tBTA_AG *p_data = (tBTA_AG *)p_param; + bdstr_t bdstr; + + BTIF_TRACE_DEBUG2("%s: event=%s", __FUNCTION__, dump_hf_event(event)); + + switch (event) + { + case BTA_AG_ENABLE_EVT: + case BTA_AG_DISABLE_EVT: + break; + + case BTA_AG_REGISTER_EVT: + btif_hf_cb.handle = p_data->reg.hdr.handle; + break; + + case BTA_AG_OPEN_EVT: + if (p_data->open.status == BTA_AG_SUCCESS) + { + bdcpy(btif_hf_cb.connected_bda.address, p_data->open.bd_addr); + btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTED; + btif_hf_cb.peer_feat = 0; + } + else if (btif_hf_cb.state == BTHF_CONNECTION_STATE_CONNECTING) + { + btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED; + } + else + { + BTIF_TRACE_WARNING4("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s", + __FUNCTION__, p_data->open.status, btif_hf_cb.state, bd2str(&btif_hf_cb.connected_bda, &bdstr)); + break; + } + + CHECK_CALL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda); + + if (p_data->open.status != BTA_AG_SUCCESS) + bdsetany(btif_hf_cb.connected_bda.address); + break; + + case BTA_AG_CLOSE_EVT: + btif_hf_cb.state = BTHF_CONNECTION_STATE_DISCONNECTED; + CHECK_CALL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb.state, &btif_hf_cb.connected_bda); + bdsetany(btif_hf_cb.connected_bda.address); + btif_hf_cb.peer_feat = 0; + break; + + case BTA_AG_CONN_EVT: + btif_hf_cb.peer_feat = p_data->conn.peer_feat; + break; + + case BTA_AG_AUDIO_OPEN_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED, &btif_hf_cb.connected_bda); + break; + + case BTA_AG_AUDIO_CLOSE_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED, &btif_hf_cb.connected_bda); + break; + + /* BTA auto-responds, silently discard */ + case BTA_AG_SPK_EVT: + case BTA_AG_MIC_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, volume_cmd_cb, + (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK : BTHF_VOLUME_TYPE_MIC, p_data->val.num); + break; + + case BTA_AG_AT_A_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, answer_call_cmd_cb); + break; + + /* Java needs to send OK/ERROR for these commands */ + case BTA_AG_AT_BLDN_EVT: + case BTA_AG_AT_D_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, dial_call_cmd_cb, + (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL); + break; + + case BTA_AG_AT_CHUP_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb); + break; + + case BTA_AG_AT_CIND_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, cind_cmd_cb); + break; + + case BTA_AG_AT_VTS_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0]); + break; + + case BTA_AG_AT_BVRA_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, vr_cmd_cb, + (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED : BTHF_VR_STATE_STOPPED); + break; + + case BTA_AG_AT_NREC_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, nrec_cmd_cb, + (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP); + break; + + /* TODO: Add a callback for CBC */ + case BTA_AG_AT_CBC_EVT: + break; + + case BTA_AG_AT_CKPD_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb); + break; + + /* Java needs to send OK/ERROR for these commands */ + case BTA_AG_AT_CHLD_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, chld_cmd_cb, p_data->val.num); + break; + + case BTA_AG_AT_CLCC_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, clcc_cmd_cb, p_data->val.num); + break; + + case BTA_AG_AT_COPS_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, cops_cmd_cb); + break; + + case BTA_AG_AT_UNAT_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, + p_data->val.str); + break; + + case BTA_AG_AT_CNUM_EVT: + CHECK_CALL_CBACK(bt_hf_callbacks, cnum_cmd_cb); + break; + + /* TODO: Some of these commands may need to be sent to app. For now respond with error */ + case BTA_AG_AT_BINP_EVT: + case BTA_AG_AT_BTRH_EVT: + send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED); + break; + + + default: + BTIF_TRACE_WARNING2("%s: Unhandled event: %d", __FUNCTION__, event); + break; + } +} + +/******************************************************************************* +** +** Function bte_hf_evt +** +** Description Switches context from BTE to BTIF for all HF events +** +** Returns void +** +*******************************************************************************/ + +static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *p_data) +{ + bt_status_t status; + int param_len = 0; + + /* TODO: BTA sends the union members and not tBTA_AG. If using param_len=sizeof(tBTA_AG), we get a crash on memcpy */ + if (BTA_AG_REGISTER_EVT == event) + param_len = sizeof(tBTA_AG_REGISTER); + else if (BTA_AG_OPEN_EVT == event) + param_len = sizeof(tBTA_AG_OPEN); + else if (BTA_AG_CONN_EVT == event) + param_len = sizeof(tBTA_AG_CONN); + else if ( (BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event)) + param_len = sizeof(tBTA_AG_HDR); + else if (p_data) + param_len = sizeof(tBTA_AG_VAL); + + /* switch context to btif task context (copy full union size for convenience) */ + status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL); + + /* catch any failed context transfers */ + ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status); +} + + +/******************************************************************************* +** +** Function btif_hf_init +** +** Description initializes the hf interface +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t init( bthf_callbacks_t* callbacks ) +{ + char * p_service_names[] = {BTIF_HSAG_SERVICE_NAME, BTIF_HFAG_SERVICE_NAME}; + + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + + bt_hf_callbacks = callbacks; + + /* Enable and register with BTA-AG */ + BTA_AgEnable (BTA_AG_PARSE, bte_hf_evt); + BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, BTIF_HF_FEATURES, + p_service_names, BTIF_HF_ID_1); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function connect +** +** Description connect to headset +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t connect( bt_bdaddr_t *bd_addr ) +{ + CHECK_BTHF_INIT(); + + if (!is_connected(bd_addr)) + { + btif_hf_cb.state = BTHF_CONNECTION_STATE_CONNECTING; + bdcpy(btif_hf_cb.connected_bda.address, bd_addr->address); + + BTA_AgOpen(btif_hf_cb.handle, btif_hf_cb.connected_bda.address, + BTIF_HF_SECURITY, BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_BUSY; +} + +/******************************************************************************* +** +** Function disconnect +** +** Description disconnect from headset +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t disconnect( bt_bdaddr_t *bd_addr ) +{ + CHECK_BTHF_INIT(); + + if (is_connected(bd_addr)) + { + BTA_AgClose(btif_hf_cb.handle); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function connect_audio +** +** Description create an audio connection +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t connect_audio( bt_bdaddr_t *bd_addr ) +{ + CHECK_BTHF_INIT(); + + if (is_connected(bd_addr)) + { + BTA_AgAudioOpen(btif_hf_cb.handle); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function disconnect_audio +** +** Description close the audio connection +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr ) +{ + CHECK_BTHF_INIT(); + + if (is_connected(bd_addr)) + { + BTA_AgAudioClose(btif_hf_cb.handle); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function start_voice_recognition +** +** Description start voice recognition +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t start_voice_recognition() +{ + CHECK_BTHF_INIT(); + if (is_connected(NULL)) + { + tBTA_AG_RES_DATA ag_res; + memset(&ag_res, 0, sizeof(ag_res)); + ag_res.state = 1; + BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function stop_voice_recognition +** +** Description stop voice recognition +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t stop_voice_recognition() +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + tBTA_AG_RES_DATA ag_res; + memset(&ag_res, 0, sizeof(ag_res)); + ag_res.state = 0; + BTA_AgResult (btif_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function volume_control +** +** Description volume control +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t volume_control(bthf_volume_type_t type, int volume) +{ + CHECK_BTHF_INIT(); + + tBTA_AG_RES_DATA ag_res; + memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); + if (is_connected(NULL)) + { + ag_res.num = volume; + BTA_AgResult(btif_hf_cb.handle, + (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES, + &ag_res); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function device_status_notification +** +** Description Combined device status change notification +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t device_status_notification(bthf_network_state_t ntk_state, + bthf_service_type_t svc_type, int signal, int batt_chg) +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + /* send all indicators to BTA. + ** BTA will make sure no duplicates are sent out + */ + send_indicator_update(BTA_AG_IND_SERVICE, + (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0); + send_indicator_update(BTA_AG_IND_ROAM, + (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1); + send_indicator_update(BTA_AG_IND_SIGNAL, signal); + send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function cops_response +** +** Description Response for COPS command +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t cops_response(const char *cops) +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + tBTA_AG_RES_DATA ag_res; + + /* Format the response */ + sprintf (ag_res.str, "0,0,\"%s\"", cops); + ag_res.ok_flag = BTA_AG_OK_DONE; + + BTA_AgResult (btif_hf_cb.handle, BTA_AG_COPS_RES, &ag_res); + return BT_STATUS_SUCCESS; + } + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function cind_response +** +** Description Response for CIND command +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t cind_response(int svc, int num_active, int num_held, + bthf_call_state_t call_setup_state, + int signal, int roam, int batt_chg) +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + tBTA_AG_RES_DATA ag_res; + + memset (&ag_res, 0, sizeof (ag_res)); + sprintf (ag_res.str, "%d,%d,%d,%d,%d,%d,%d", + (num_active ? 1 : 0), /* Call state */ + callstate_to_callsetup(call_setup_state), /* Callsetup state */ + svc, /* network service */ + signal, /* Signal strength */ + roam, /* Roaming indicator */ + batt_chg, /* Battery level */ + (num_held ? 1 : 0)); /* Call held */ + + BTA_AgResult (btif_hf_cb.handle, BTA_AG_CIND_RES, &ag_res); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function formatted_at_response +** +** Description Pre-formatted AT response, typically in response to unknown AT cmd +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t formatted_at_response(const char *rsp) +{ + CHECK_BTHF_INIT(); + tBTA_AG_RES_DATA ag_res; + + if (is_connected(NULL)) + { + /* Format the response and send */ + memset (&ag_res, 0, sizeof (ag_res)); + strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN); + BTA_AgResult (btif_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function at_response +** +** Description ok/error response +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t at_response(bthf_at_response_t response_code) +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + /* TODO: Fix the errcode */ + send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE + : BTA_AG_OK_ERROR, 0); + } + + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function clcc_response +** +** Description response for CLCC command +** Can be iteratively called for each call index. Call index +** of 0 will be treated as NULL termination (Completes response) +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t clcc_response(int index, bthf_call_direction_t dir, + bthf_call_state_t state, bthf_call_mode_t mode, + bthf_call_mpty_type_t mpty, const char *number, + bthf_call_addrtype_t type) +{ + CHECK_BTHF_INIT(); + + if (is_connected(NULL)) + { + tBTA_AG_RES_DATA ag_res; + int xx; + + memset (&ag_res, 0, sizeof (ag_res)); + + /* Format the response */ + if (index == 0) + { + ag_res.ok_flag = BTA_AG_OK_DONE; + } + else + { + BTIF_TRACE_EVENT6("clcc_response: [%d] dir %d state %d mode %d number = %s type = %d", + index, dir, state, mode, number, type); + xx = sprintf (ag_res.str, "%d,%d,%d,%d,%d", + index, dir, state, mode, mpty); + + if (number) + { + if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+')) + sprintf (&ag_res.str[xx], ",\"+%s\",%d", number, type); + else + sprintf (&ag_res.str[xx], ",\"%s\",%d", number, type); + } + } + BTA_AgResult (btif_hf_cb.handle, BTA_AG_CLCC_RES, &ag_res); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function phone_state_change +** +** Description notify of a call state change +** number & type: valid only for incoming & waiting call +** +** Returns bt_status_t +** +*******************************************************************************/ + +static bt_status_t phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state, + const char *number, bthf_call_addrtype_t type) +{ + tBTA_AG_RES res = 0xff; + tBTA_AG_RES_DATA ag_res; + bt_status_t status = BT_STATUS_SUCCESS; + + CHECK_BTHF_INIT(); + + BTIF_TRACE_DEBUG6("phone_state_change: num_active=%d[%d] num_held=%d[%d]"\ + " call_setup=%d [%d]", num_active, btif_hf_cb.num_active, + num_held, btif_hf_cb.num_held, + call_setup_state, btif_hf_cb.call_setup_state); + + /* Check what has changed and update the corresponding indicators. + ** In ad + */ + + /* if all indicators are 0, send end call and return */ + if (num_active == 0 && num_held == 0 && call_setup_state == BTHF_CALL_STATE_IDLE) + { + BTIF_TRACE_DEBUG1("%s: Phone on hook", __FUNCTION__); + BTA_AgResult (BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL); + goto update_call_states; + } + + /* Ringing call changed? */ + if (call_setup_state != btif_hf_cb.call_setup_state) + { + BTIF_TRACE_DEBUG3("%s: Call setup states changed. old: %s new: %s", + __FUNCTION__, dump_hf_call_state(btif_hf_cb.call_setup_state), + dump_hf_call_state(call_setup_state)); + memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA)); + + switch (call_setup_state) + { + case BTHF_CALL_STATE_IDLE: + { + switch (btif_hf_cb.call_setup_state) + { + case BTHF_CALL_STATE_INCOMING: + if (num_active > btif_hf_cb.num_active) + { + res = BTA_AG_IN_CALL_CONN_RES; + ag_res.audio_handle = btif_hf_cb.handle; + } + else if (num_held > btif_hf_cb.num_held) + res = BTA_AG_IN_CALL_HELD_RES; + else + res = BTA_AG_CALL_CANCEL_RES; + break; + case BTHF_CALL_STATE_DIALING: + case BTHF_CALL_STATE_ALERTING: + if (num_active > btif_hf_cb.num_active) + { + ag_res.audio_handle = btif_hf_cb.handle; + res = BTA_AG_OUT_CALL_CONN_RES; + } + else + res = BTA_AG_CALL_CANCEL_RES; + break; + default: + BTIF_TRACE_ERROR1("%s: Incorrect Call setup state transition", __FUNCTION__); + status = BT_STATUS_PARM_INVALID; + break; + } + } break; + + case BTHF_CALL_STATE_INCOMING: + if (num_active || num_held) + res = BTA_AG_CALL_WAIT_RES; + else + res = BTA_AG_IN_CALL_RES; + if (number) + { + strcpy(ag_res.str, number); + ag_res.num = type; + } + break; + case BTHF_CALL_STATE_DIALING: + ag_res.audio_handle = btif_hf_cb.handle; + res = BTA_AG_OUT_CALL_ORIG_RES; + break; + case BTHF_CALL_STATE_ALERTING: + ag_res.audio_handle = btif_hf_cb.handle; + res = BTA_AG_OUT_CALL_ALERT_RES; + break; + default: + BTIF_TRACE_ERROR1("%s: Incorrect new ringing call state", __FUNCTION__); + status = BT_STATUS_PARM_INVALID; + break; + } + BTIF_TRACE_DEBUG3("%s: Call setup state changed. res=%d, audio_handle=%d", __FUNCTION__, res, ag_res.audio_handle); + + if (res) + BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res); + + /* update the call states and return */ + goto update_call_states; + } + + /* Active Changed? */ + if (num_active != btif_hf_cb.num_active) + { + BTIF_TRACE_DEBUG3("%s: Active call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_active, num_active); + send_indicator_update(BTA_AG_IND_CALL, (num_active ? 1 : 0)); + } + + + /* Held Changed? */ + if (num_held != btif_hf_cb.num_held) + { + BTIF_TRACE_DEBUG3("%s: Held call states changed. old: %d new: %d", __FUNCTION__, btif_hf_cb.num_held, num_held); + send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); + } + + /* Calls Swapped? */ + if ( (call_setup_state == btif_hf_cb.call_setup_state) && + (num_active && num_held) && + (num_active == btif_hf_cb.num_active) && + (num_held == btif_hf_cb.num_held) ) + { + BTIF_TRACE_DEBUG1("%s: Calls swapped", __FUNCTION__); + send_indicator_update(BTA_AG_IND_CALLHELD, 1); + } + +update_call_states: + btif_hf_cb.num_active = num_active; + btif_hf_cb.num_held = num_held; + btif_hf_cb.call_setup_state = call_setup_state; + + return status; +} + +/******************************************************************************* +** +** Function cleanup +** +** Description Closes the HF interface +** +** Returns bt_status_t +** +*******************************************************************************/ +static void cleanup( void ) +{ + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + + if (bt_hf_callbacks) + { + /* De-register AG */ + BTA_AgDeregister(btif_hf_cb.handle); + /* Disable AG */ + BTA_AgDisable(); + bt_hf_callbacks = NULL; + } +} + +static const bthf_interface_t bthfInterface = { + sizeof(bt_interface_t), + init, + connect, + disconnect, + connect_audio, + disconnect_audio, + start_voice_recognition, + stop_voice_recognition, + volume_control, + device_status_notification, + cops_response, + cind_response, + formatted_at_response, + at_response, + clcc_response, + phone_state_change, + cleanup, +}; + +/******************************************************************************* +** +** Function btif_hf_get_interface +** +** Description Get the hf callback interface +** +** Returns bthf_interface_t +** +*******************************************************************************/ +const bthf_interface_t *btif_hf_get_interface() +{ + BTIF_TRACE_EVENT1("%s", __FUNCTION__); + return &bthfInterface; +} diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c new file mode 100644 index 0000000..a55821d --- /dev/null +++ b/btif/src/btif_storage.c @@ -0,0 +1,1027 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_storage.c + * + * Description: Stores the local BT adapter and remote device properties in + * NVRAM storage, typically as text files in the + * mobile's filesystem + * + * + * Data storage directory structure + * + * data + * `-- misc + * `-- bluedroid + * `-- LOCAL + * |-- adapter_info - Local adapter config + * |-- remote_devices - Remote devices and Timestamp + * |-- remote_devclass - Remote devices' COD + * |-- remote_devtype - Remote devices' type + * |-- remote_names - Remote devices' names + * |-- remote_aliases - Remote devices' Friendly names + * `-- remote_services - Remote devices' services + * + * + * adapter_info - Key/Value + * name <space> <Name of Local Bluetooth device> + * scan_mode <space> <Scan Mode> + * discovery_timeout <space> <Discovery Timeout in seconds> + * + * remote_devices - Key/Value + * <remote device bd_addr> <space> <Timestamp> + * + * remote_devclass - Key/Value + * <remote device bd_addr> <space> <Device class> + * + * remote_devtype - Key/Value + * <remote_device bd_addr><space> <Device Type> + * + * remote_names - Key/Value + * <remote_device bd_addr> <space> <Bluetooth device Name as reported by the controller> + * + * remote_linkkeys - Key/Value + * <remote device bd_addr > <space> <LinkKey> <space> <KeyType> <space> <PinLength> + * + * remote_aliases - Key/Value + * <remote device bd_addr> <space> <Friendy Name> + * + * remote_services - Key/Value + * <remote_device bd_addr> <space> <List of UUIDs separated by semicolons> + * + ***********************************************************************************/ +#include <stdlib.h> +#include <time.h> + +#include <hardware/bluetooth.h> + +#define LOG_TAG "BTIF_STORAGE" + +#include "btif_api.h" + +#include "btif_util.h" +#include "unv.h" +#include "bd.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +#define BTIF_STORAGE_PATH_BLUEDROID "/data/misc/bluedroid" + +#define BTIF_STORAGE_PATH_ADAPTER_INFO "adapter_info" +#define BTIF_STORAGE_PATH_REMOTE_DEVICES "remote_devices" +#define BTIF_STORAGE_PATH_REMOTE_DEVCLASSES "remote_devclasses" +#define BTIF_STORAGE_PATH_REMOTE_DEVTYPES "remote_devtypes" +#define BTIF_STORAGE_PATH_REMOTE_NAMES "remote_names" +#define BTIF_STORAGE_PATH_REMOTE_LINKKEYS "remote_linkkeys" +#define BTIF_STORAGE_PATH_REMOTE_ALIASES "remote_aliases" +#define BTIF_STORAGE_PATH_REMOTE_SERVICES "remote_services" + +#define BTIF_STORAGE_KEY_ADAPTER_NAME "name" +#define BTIF_STORAGE_KEY_ADAPTER_SCANMODE "scan_mode" +#define BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT "discovery_timeout" + +/* This is a local property to add a device found */ +#define BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP 0xFF + +#define BTIF_STORAGE_GET_ADAPTER_PROP(t,v,l,p) \ + {p.type=t;p.val=v;p.len=l; btif_storage_get_adapter_property(&p);} + +#define BTIF_STORAGE_GET_REMOTE_PROP(b,t,v,l,p) \ + {p.type=t;p.val=v;p.len=l;btif_storage_get_remote_device_property(b,&p);} + +#define STORAGE_BDADDR_STRING_SZ (18) /* 00:11:22:33:44:55 */ +#define STORAGE_UUID_STRING_SIZE (36+1) /* 00001200-0000-1000-8000-00805f9b34fb; */ +#define STORAGE_PINLEN_STRING_MAX_SIZE (2) /* ascii pinlen max chars */ +#define STORAGE_KEYTYPE_STRING_MAX_SIZE (1) /* ascii keytype max chars */ + +#define STORAGE_KEY_TYPE_MAX (10) + + +/* <18 char bd addr> <space> LIST< <36 char uuid> <;> > <keytype (dec)> <pinlen> */ +#define BTIF_REMOTE_SERVICES_ENTRY_SIZE_MAX (STORAGE_BDADDR_STRING_SZ + 1 +\ + STORAGE_UUID_STRING_SIZE*BT_MAX_NUM_UUIDS + \ + STORAGE_PINLEN_STRING_MAX_SIZE +\ + STORAGE_KEYTYPE_STRING_MAX_SIZE) + +#define STORAGE_REMOTE_LINKKEYS_ENTRY_SIZE (LINK_KEY_LEN*2 + 1 + 2 + 1 + 2) + +/* currently remote services is the potentially largest entry */ +#define BTIF_STORAGE_MAX_LINE_SZ BTIF_REMOTE_SERVICES_ENTRY_SIZE_MAX + +/* check against unv max entry size at compile time */ +#if (BTIF_STORAGE_ENTRY_MAX_SIZE > UNV_MAXLINE_LENGTH) +#error "btif storage entry size exceeds unv max line size" +#endif + +/************************************************************************************ +** Local type definitions +************************************************************************************/ +typedef struct { + uint32_t num_devices; + bt_bdaddr_t devices[BTM_SEC_MAX_DEVICE_RECORDS]; +} btif_bonded_devices_t; + +/************************************************************************************ +** Static variables +************************************************************************************/ + +/************************************************************************************ +** Static functions +************************************************************************************/ +/******************************************************************************* +** +** Function btif_in_make_filename +** +** Description Internal helper function to create NVRAM file path +** from address and filename +** +** Returns NVRAM file path if successfull, NULL otherwise +** +*******************************************************************************/ +static char* btif_in_make_filename(bt_bdaddr_t *bd_addr, char *fname) +{ + static char path[256]; + bdstr_t bdstr; + + if (fname == NULL)return NULL; + if (bd_addr) + { + sprintf(path, "%s/%s/%s", BTIF_STORAGE_PATH_BLUEDROID, + bd2str(bd_addr, &bdstr), fname); + } + else + { + /* local adapter */ + sprintf(path, "%s/LOCAL/%s", BTIF_STORAGE_PATH_BLUEDROID, fname); + } + + return (char*)path; +} + +/******************************************************************************* +** +** Function btif_in_adapter_key_from_type +** +** Description Internal helper function to map a property type +** to the NVRAM filename key +** +** Returns NVRAM filename key if successfull, 'NO_KEY' otherwise +** +*******************************************************************************/ +static const char *btif_in_get_adapter_key_from_type(bt_property_type_t type) +{ + switch (type) + { + case BT_PROPERTY_BDNAME: + return BTIF_STORAGE_KEY_ADAPTER_NAME; + case BT_PROPERTY_ADAPTER_SCAN_MODE: + return BTIF_STORAGE_KEY_ADAPTER_SCANMODE; + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + return BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT; + default: + /* return valid string to avoid passing NULL to NV RAM driver */ + return "NO_KEY"; + } +} + +/******************************************************************************* +** +** Function btif_in_split_uuids_string_to_list +** +** Description Internal helper function to split the string of UUIDs +** read from the NVRAM to an array +** +** Returns None +** +*******************************************************************************/ +static void btif_in_split_uuids_string_to_list(char *str, bt_uuid_t *p_uuid, + uint32_t *p_num_uuid) +{ + char buf[64]; + char *p_start = str; + char *p_needle; + uint32_t num = 0; + do + { + p_needle = strchr(p_start, ';'); + memset(buf, 0, sizeof(buf)); + strncpy(buf, p_start, (p_needle-p_start)); + string_to_uuid(buf, p_uuid + num); + num++; + p_start = ++p_needle; + + } while (*p_start != 0); + *p_num_uuid = num; +} + +/******************************************************************************* +** +** Function btif_in_str_to_property +** +** Description Internal helper function to convert the string read from +** NVRAM into a property->val. Also sets the property->len. +** Assumption is that property->val has enough memory to +** store the string fetched from NVRAM +** +** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +static bt_status_t btif_in_str_to_property(char *value, bt_property_t *property) +{ + bt_status_t status = BT_STATUS_SUCCESS; + property->len = 0; + + /* if Value is NULL, then just set the property->len to 0 and return. + This is possible if the entry does not exist */ + if (value == NULL) { + status = BT_STATUS_FAIL; + } + switch (property->type) + { + case BT_PROPERTY_BDNAME: + case BT_PROPERTY_REMOTE_FRIENDLY_NAME: + { + *((char*)property->val) = 0; + if (value) + { + property->len = strlen(value)+1; + strcpy((char*)property->val, value); + } + } break; + case BT_PROPERTY_ADAPTER_SCAN_MODE: + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + { + *((uint32_t *)property->val) = 0; + if (value) + { + uint32_t ival; + property->len = sizeof(uint32_t); + ival = atoi(value); + memcpy((uint32_t*)property->val, &ival, sizeof(uint32_t)); + } + } break; + case BT_PROPERTY_CLASS_OF_DEVICE: + case BT_PROPERTY_TYPE_OF_DEVICE: + { + *((uint32_t *)property->val) = 0; + if (value) + { + uint32_t ival; + property->len = sizeof(uint32_t); + ival = strtol(value, NULL, 16); + memcpy((uint32_t*)property->val, &ival, sizeof(uint32_t)); + } + } break; + case BT_PROPERTY_UUIDS: + { + if (value) + { + bt_uuid_t *p_uuid = (bt_uuid_t*)property->val; + uint32_t num_uuids = 0; + btif_in_split_uuids_string_to_list(value, p_uuid, &num_uuids); + property->len = num_uuids * sizeof(bt_uuid_t); + } + } break; + default: + { + break; + } + } + return status; +} + +/******************************************************************************* +** +** Function btif_in_property_to_str +** +** Description Internal helper function to convert the property->val +** to a string that can be written to the NVRAM +** +** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +static bt_status_t btif_in_property_to_str(bt_property_t *property, char *value) +{ + switch (property->type) + { + case BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP: + { + sprintf(value, "%d", (int)time(NULL)); + }break; + case BT_PROPERTY_BDNAME: + case BT_PROPERTY_REMOTE_FRIENDLY_NAME: + { + strcpy(value, (char*)property->val); + }break; + case BT_PROPERTY_ADAPTER_SCAN_MODE: + case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + { + sprintf(value, "%d", *((uint32_t*)property->val)); + }break; + case BT_PROPERTY_CLASS_OF_DEVICE: + case BT_PROPERTY_TYPE_OF_DEVICE: + { + sprintf(value, "0x%x", *((uint32_t*)property->val)); + }break; + case BT_PROPERTY_UUIDS: + { + uint32_t i; + char buf[64]; + value[0] = 0; + for (i=0; i < (property->len)/sizeof(bt_uuid_t); i++) + { + bt_uuid_t *p_uuid = (bt_uuid_t*)property->val + i; + memset(buf, 0, sizeof(buf)); + uuid_to_string(p_uuid, buf); + strcat(value, buf); + strcat(value, ";"); + } + value[strlen(value)] = 0; + }break; + default: + { + return BT_STATUS_FAIL; + } + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_in_get_remote_device_path_from_property +** +** Description Internal helper function to map a property type +** to the NVRAM filename key +** +** Returns NVRAM filename key if successfull, NULL otherwise +** +*******************************************************************************/ +static char* btif_in_get_remote_device_path_from_property(bt_property_type_t type) +{ + switch (type) + { + case BT_PROPERTY_BDADDR: + case BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP: + return BTIF_STORAGE_PATH_REMOTE_DEVICES; + case BT_PROPERTY_BDNAME: + return BTIF_STORAGE_PATH_REMOTE_NAMES; + case BT_PROPERTY_CLASS_OF_DEVICE: + return BTIF_STORAGE_PATH_REMOTE_DEVCLASSES; + case BT_PROPERTY_TYPE_OF_DEVICE: + return BTIF_STORAGE_PATH_REMOTE_DEVTYPES; + case BT_PROPERTY_REMOTE_FRIENDLY_NAME: + return BTIF_STORAGE_PATH_REMOTE_ALIASES; + case BT_PROPERTY_UUIDS: + return BTIF_STORAGE_PATH_REMOTE_SERVICES; + default: + return NULL; + } +} + +/******************************************************************************* +** +** Function btif_in_load_device_iter_cb +** +** Description Internal iterator callback from UNV when loading the +** link-keys +** +** Returns +** +*******************************************************************************/ + +int btif_in_load_device_iter_cb(char *key, char *value, void *userdata) +{ + btif_bonded_devices_t *p_bonded_devices = (btif_bonded_devices_t *)userdata; + DEV_CLASS dev_class = {0, 0, 0}; + bt_bdaddr_t bd_addr; + LINK_KEY link_key; + uint8_t key_type; + uint8_t pin_length; + int offset = 0; + int8_t temp[3]; + uint32_t i; + + memset(temp, 0, sizeof(temp)); + + BTIF_TRACE_DEBUG3("%s %s %s", __FUNCTION__, key, value); + + /* convert 32 char linkkey (fixed size) */ + for (i = 0; i < LINK_KEY_LEN; i++) + { + memcpy(temp, value + (i * 2), 2); + link_key[i] = (uint8_t) strtol((const char *)temp, NULL, 16); + offset+=2; + } + + /* skip space */ + offset++; + + /* convert decimal keytype (max 2 ascii chars) */ + memset(temp, 0, sizeof(temp)); + memcpy(temp, value + offset, 2); + key_type = (uint8_t)strtoul((const char *)temp, NULL, 10); + + /* value + space */ + offset+=2; + + /* convert decimal pinlen (max 2 ascii chars) */ + memset(temp, 0, sizeof(temp)); + memcpy(temp, value + offset, 2); + pin_length = (uint8_t)strtoul((const char *)temp, NULL, 10); + + /* convert bd address (keystring) */ + str2bd(key, &bd_addr); + + /* add extracted information to BTA security manager */ + BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0, key_type, 0); + + /* Fill in the bonded devices */ + memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t)); + + return 0; +} + +/******************************************************************************* +** +** Function btif_in_fetch_bonded_devices +** +** Description Internal helper function to fetch the bonded devices +** from NVRAM +** +** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +static bt_status_t btif_in_fetch_bonded_devices(btif_bonded_devices_t *p_bonded_devices) +{ + char *fname; + int ret; + + memset(p_bonded_devices, 0, sizeof(btif_bonded_devices_t)); + + fname = btif_in_make_filename(NULL, BTIF_STORAGE_PATH_REMOTE_LINKKEYS); + + if (fname == NULL) + return BT_STATUS_FAIL; + + ret = unv_read_key_iter(fname, btif_in_load_device_iter_cb, p_bonded_devices); + + if (ret < 0) + return BT_STATUS_FAIL; + + return BT_STATUS_SUCCESS; +} + +/************************************************************************************ +** Externs +************************************************************************************/ + +/************************************************************************************ +** Functions +************************************************************************************/ + +/** functions are synchronous. + * functions can be called by both internal modules such as BTIF_DM and by external entiries from HAL via BTIF_context_switch + * For OUT parameters, caller is expected to provide the memory. + * Caller is expected to provide a valid pointer to 'property->value' based on the property->type + */ +/******************************************************************************* +** +** Function btif_storage_get_adapter_property +** +** Description BTIF storage API - Fetches the adapter property->type +** from NVRAM and fills property->val. +** Caller should provide memory for property->val and +** set the property->val +** +** Returns BT_STATUS_SUCCESS if the fetch was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_get_adapter_property(bt_property_t *property) +{ + bt_status_t status; + char *fname; + char *value; + int ret; + char linebuf[BTIF_STORAGE_MAX_LINE_SZ]; + + /* initialize property->len */ + property->len = 0; + + /* Special handling for adapter BD_ADDR and BONDED_DEVICES */ + if (property->type == BT_PROPERTY_BDADDR) + { + BD_ADDR addr; + bt_bdaddr_t *bd_addr = (bt_bdaddr_t*)property->val; + BTM_GetLocalDeviceAddr(addr); + bdcpy(bd_addr->address, addr); + property->len = sizeof(bt_bdaddr_t); + + return BT_STATUS_SUCCESS; + } + else if (property->type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) + { + btif_bonded_devices_t bonded_devices; + + btif_in_fetch_bonded_devices(&bonded_devices); + + BTIF_TRACE_DEBUG2("%s: Number of bonded devices: %d", __FUNCTION__, bonded_devices.num_devices); + + if (bonded_devices.num_devices > 0) + { + property->len = bonded_devices.num_devices * sizeof(bt_bdaddr_t); + memcpy(property->val, bonded_devices.devices, property->len); + } + + /* if there are no bonded_devices, then length shall be 0 */ + return BT_STATUS_SUCCESS; + } + else if (property->type == BT_PROPERTY_UUIDS) + { + /* publish list of local supported services */ + bt_uuid_t *p_uuid = (bt_uuid_t*)property->val; + uint32_t num_uuids = 0; + +#if BTA_AG_INCLUDED == TRUE + uuid16_to_uuid128(UUID_SERVCLASS_AG_HANDSFREE, p_uuid + num_uuids); + num_uuids++; + uuid16_to_uuid128(UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, p_uuid + num_uuids); + num_uuids++; +#endif + + property->len = (num_uuids)*sizeof(bt_uuid_t); + return BT_STATUS_SUCCESS; + } + + /* fall through for other properties */ + + /* create filepath */ + fname = btif_in_make_filename(NULL, BTIF_STORAGE_PATH_ADAPTER_INFO); + + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + + ret = unv_create_file(fname); + + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + value = unv_read_key( fname, + btif_in_get_adapter_key_from_type(property->type), + linebuf, UNV_MAXLINE_LENGTH); + + if (value == NULL) + { + /* properties not yet existing, request default values from bta */ + return btif_dm_get_adapter_property(property); + } + else + { + /* convert to property_t data structure */ + status = btif_in_str_to_property(value, property); + } + + return status; +} + +/******************************************************************************* +** +** Function btif_storage_set_adapter_property +** +** Description BTIF storage API - Stores the adapter property +** to NVRAM +** +** Returns BT_STATUS_SUCCESS if the store was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_set_adapter_property(bt_property_t *property) +{ + char *fname; + char value[1200]; + int ret; + + fname = btif_in_make_filename(NULL, BTIF_STORAGE_PATH_ADAPTER_INFO); + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + ret = unv_create_file(fname); + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + if (btif_in_property_to_str(property, value) != BT_STATUS_SUCCESS) + { + return BT_STATUS_FAIL; + } + ret = unv_write_key(fname, btif_in_get_adapter_key_from_type(property->type), value); + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_storage_get_remote_device_property +** +** Description BTIF storage API - Fetches the remote device property->type +** from NVRAM and fills property->val. +** Caller should provide memory for property->val and +** set the property->val +** +** Returns BT_STATUS_SUCCESS if the fetch was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_get_remote_device_property(bt_bdaddr_t *remote_bd_addr, + bt_property_t *property) +{ + char linebuf[BTIF_STORAGE_MAX_LINE_SZ]; + char *fname; + char *value; + int ret; + bdstr_t bdstr; + + fname = btif_in_make_filename(NULL, + btif_in_get_remote_device_path_from_property(property->type)); + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + + ret = unv_create_file(fname); + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + value = unv_read_key(fname, bd2str(remote_bd_addr, &bdstr), linebuf, BTIF_STORAGE_MAX_LINE_SZ); + + return btif_in_str_to_property(value, property); +} + +/******************************************************************************* +** +** Function btif_storage_set_remote_device_property +** +** Description BTIF storage API - Stores the remote device property +** to NVRAM +** +** Returns BT_STATUS_SUCCESS if the store was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_set_remote_device_property(bt_bdaddr_t *remote_bd_addr, + bt_property_t *property) +{ + char value[1200]; + char *fname; + bdstr_t bdstr; + int ret; + + fname = btif_in_make_filename(NULL, + btif_in_get_remote_device_path_from_property(property->type)); + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + ret = unv_create_file(fname); + if (ret < 0) + { + return BT_STATUS_FAIL; + } + memset(value, 0, sizeof(value)); + + if (btif_in_property_to_str(property, value) != BT_STATUS_SUCCESS) + { + return BT_STATUS_FAIL; + } + + ret = unv_write_key(fname, bd2str(remote_bd_addr, &bdstr), value); + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_storage_add_remote_device +** +** Description BTIF storage API - Adds a newly discovered device to NVRAM +** along with the timestamp. Also, stores the various +** properties - RSSI, BDADDR, NAME (if found in EIR) +** +** Returns BT_STATUS_SUCCESS if the store was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr, + uint32_t num_properties, + bt_property_t *properties) +{ + uint32_t i = 0; + /* TODO: If writing a property, fails do we go back undo the earlier + * written properties? */ + for (i=0; i < num_properties; i++) + { + /* Ignore the RSSI as this is not stored in DB */ + if (properties[i].type == BT_PROPERTY_REMOTE_RSSI) + continue; + + /* BD_ADDR for remote device needs special handling as we also store timestamp */ + if (properties[i].type == BT_PROPERTY_BDADDR) + { + bt_property_t addr_prop; + memcpy(&addr_prop, &properties[i], sizeof(bt_property_t)); + addr_prop.type = BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP; + btif_storage_set_remote_device_property(remote_bdaddr, + &addr_prop); + } + else + { + btif_storage_set_remote_device_property(remote_bdaddr, + &properties[i]); + } + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_storage_add_bonded_device +** +** Description BTIF storage API - Adds the newly bonded device to NVRAM +** along with the link-key, Key type and Pin key length +** +** Returns BT_STATUS_SUCCESS if the store was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ + +bt_status_t btif_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr, + LINK_KEY link_key, + uint8_t key_type, + uint8_t pin_length) +{ + char value[STORAGE_REMOTE_LINKKEYS_ENTRY_SIZE]; + uint32_t i = 0; + char *fname; + bdstr_t bdstr; + int ret; + + fname = btif_in_make_filename(NULL, + BTIF_STORAGE_PATH_REMOTE_LINKKEYS); + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + ret = unv_create_file(fname); + + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + /* check ascii representations doesn't exceed max size */ + + if (key_type > STORAGE_KEY_TYPE_MAX) + return BT_STATUS_FAIL; + + if (pin_length > PIN_CODE_LEN) + return BT_STATUS_FAIL; + + memset(value, 0, sizeof(value)); + + for (i = 0; i < LINK_KEY_LEN; i++) + sprintf(value + (i * 2), "%2.2X", link_key[i]); + + sprintf(value + (LINK_KEY_LEN*2), " %d %d", key_type, pin_length); + + ret = unv_write_key(fname, bd2str(remote_bd_addr, &bdstr), value); + + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_storage_remove_bonded_device +** +** Description BTIF storage API - Deletes the bonded device from NVRAM +** +** Returns BT_STATUS_SUCCESS if the deletion was successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr) +{ + char *fname; + int ret; + bdstr_t bdstr; + + fname = btif_in_make_filename(NULL, + BTIF_STORAGE_PATH_REMOTE_LINKKEYS); + if (fname == NULL) + { + return BT_STATUS_FAIL; + } + ret = unv_create_file(fname); + + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + ret = unv_remove_key(fname, bd2str(remote_bd_addr, &bdstr)); + + if (ret < 0) + { + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_storage_load_bonded_devices +** +** Description BTIF storage API - Loads all the bonded devices from NVRAM +** and adds to the BTA. +** Additionally, this API also invokes the adaper_properties_cb +** and remote_device_properties_cb for each of the bonded devices. +** +** Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_storage_load_bonded_devices(void) +{ + char *fname; + btif_bonded_devices_t bonded_devices; + uint32_t i = 0; + bt_property_t adapter_props[6]; + uint32_t num_props = 0; + bt_property_t remote_properties[8]; + bt_bdaddr_t addr; + bt_bdname_t name, alias; + bt_scan_mode_t mode; + uint32_t disc_timeout; + bt_bdaddr_t *devices_list; + bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS]; + bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS]; + uint32_t cod, devtype; + + btif_in_fetch_bonded_devices(&bonded_devices); + + /* Now send the adapter_properties_cb with all adapter_properties */ + { + memset(adapter_props, 0, sizeof(adapter_props)); + + /* BD_ADDR */ + BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDADDR, &addr, sizeof(addr), + adapter_props[num_props]); + num_props++; + + /* BD_NAME */ + BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDNAME, &name, sizeof(name), + adapter_props[num_props]); + num_props++; + + /* SCAN_MODE */ + BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_ADAPTER_SCAN_MODE, &mode, sizeof(mode), + adapter_props[num_props]); + num_props++; + + /* DISC_TIMEOUT */ + BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + &disc_timeout, sizeof(disc_timeout), + adapter_props[num_props]); + num_props++; + + /* BONDED_DEVICES */ + devices_list = (bt_bdaddr_t*)malloc(sizeof(bt_bdaddr_t)*bonded_devices.num_devices); + adapter_props[num_props].type = BT_PROPERTY_ADAPTER_BONDED_DEVICES; + adapter_props[num_props].len = bonded_devices.num_devices * sizeof(bt_bdaddr_t); + adapter_props[num_props].val = devices_list; + for (i=0; i < bonded_devices.num_devices; i++) + { + memcpy(devices_list + i, &bonded_devices.devices[i], sizeof(bt_bdaddr_t)); + } + num_props++; + + /* LOCAL UUIDs */ + BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_UUIDS, + local_uuids, sizeof(local_uuids), + adapter_props[num_props]); + num_props++; + + btif_adapter_properties_evt(BT_STATUS_SUCCESS, num_props, adapter_props); + + free(devices_list); + } + + BTIF_TRACE_EVENT2("%s: %d bonded devices found", __FUNCTION__, bonded_devices.num_devices); + + { + for (i = 0; i < bonded_devices.num_devices; i++) + { + bt_bdaddr_t *p_remote_addr; + + num_props = 0; + p_remote_addr = &bonded_devices.devices[i]; + memset(remote_properties, 0, sizeof(remote_properties)); + BTIF_STORAGE_GET_REMOTE_PROP(p_remote_addr, BT_PROPERTY_BDNAME, + &name, sizeof(name), + remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_GET_REMOTE_PROP(p_remote_addr, BT_PROPERTY_REMOTE_FRIENDLY_NAME, + &alias, sizeof(alias), + remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_GET_REMOTE_PROP(p_remote_addr, BT_PROPERTY_CLASS_OF_DEVICE, + &cod, sizeof(cod), + remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_GET_REMOTE_PROP(p_remote_addr, BT_PROPERTY_TYPE_OF_DEVICE, + &devtype, sizeof(devtype), + remote_properties[num_props]); + num_props++; + + BTIF_STORAGE_GET_REMOTE_PROP(p_remote_addr, BT_PROPERTY_UUIDS, + remote_uuids, sizeof(remote_uuids), + remote_properties[num_props]); + num_props++; + + btif_remote_properties_evt(BT_STATUS_SUCCESS, p_remote_addr, + num_props, remote_properties); + } + } + return BT_STATUS_SUCCESS; +} diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c new file mode 100644 index 0000000..ad3ba86 --- /dev/null +++ b/btif/src/btif_util.c @@ -0,0 +1,359 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_util.c + * + * Description: Miscellaneous helper functions + * + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <hardware/bt_hf.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdlib.h> + +#define LOG_TAG "BTIF_UTIL" +#include "btif_common.h" +#include "bta_api.h" +#include "gki.h" +#include "btu.h" +#include "bte.h" +#include "bd.h" +#include "btif_dm.h" +#include "btif_util.h" +#include "bta_ag_api.h" + + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/************************************************************************************ +** Static variables +************************************************************************************/ + +/************************************************************************************ +** Static functions +************************************************************************************/ + +/************************************************************************************ +** Externs +************************************************************************************/ + +/************************************************************************************ +** Functions +************************************************************************************/ + +/***************************************************************************** +** Logging helper functions +*****************************************************************************/ + +int str2bd(char *str, bt_bdaddr_t *addr) +{ + int32_t i = 0; + for (i = 0; i < 6; i++) { + addr->address[i] = (uint8_t) strtoul(str, (char **)&str, 16); + str++; + } + return 0; +} + +char *bd2str(bt_bdaddr_t *bdaddr, bdstr_t *bdstr) +{ + char *addr = (char *) bdaddr->address; + + sprintf((char*)bdstr, "%02x:%02x:%02x:%02x:%02x:%02x", + (int)addr[0],(int)addr[1],(int)addr[2], + (int)addr[3],(int)addr[4],(int)addr[5]); + return (char *)bdstr; +} + +UINT32 devclass2uint(DEV_CLASS dev_class) +{ + UINT32 cod = 0; + + /* if COD is 0, irrespective of the device type set it to Unclassified device */ + cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16); + + return cod; +} + +static const UINT8 sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; + +void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t* uuid128) +{ + uint16_t uuid16_bo; + memset(uuid128, 0, sizeof(bt_uuid_t)); + + memcpy(uuid128->uu, sdp_base_uuid, MAX_UUID_SIZE); + uuid16_bo = ntohs(uuid16); + memcpy(uuid128->uu + 2, &uuid16_bo, sizeof(uint16_t)); +} + +void string_to_uuid(char *str, bt_uuid_t *p_uuid) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + sscanf(str, "%08x-%04hx-%04hx-%04hx-%08x%04hx", + &uuid0, &uuid1, &uuid2, &uuid3, &uuid4, &uuid5); + + uuid0 = htonl(uuid0); + uuid1 = htons(uuid1); + uuid2 = htons(uuid2); + uuid3 = htons(uuid3); + uuid4 = htonl(uuid4); + uuid5 = htons(uuid5); + + memcpy(&(p_uuid->uu[0]), &uuid0, 4); + memcpy(&(p_uuid->uu[4]), &uuid1, 2); + memcpy(&(p_uuid->uu[6]), &uuid2, 2); + memcpy(&(p_uuid->uu[8]), &uuid3, 2); + memcpy(&(p_uuid->uu[10]), &uuid4, 4); + memcpy(&(p_uuid->uu[14]), &uuid5, 2); + + return; + +} + +void uuid_to_string(bt_uuid_t *p_uuid, char *str) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + memcpy(&uuid0, &(p_uuid->uu[0]), 4); + memcpy(&uuid1, &(p_uuid->uu[4]), 2); + memcpy(&uuid2, &(p_uuid->uu[6]), 2); + memcpy(&uuid3, &(p_uuid->uu[8]), 2); + memcpy(&uuid4, &(p_uuid->uu[10]), 4); + memcpy(&uuid5, &(p_uuid->uu[14]), 2); + + sprintf((char *)str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + ntohl(uuid0), ntohs(uuid1), + ntohs(uuid2), ntohs(uuid3), + ntohl(uuid4), ntohs(uuid5)); + return; +} +const char* dump_dm_search_event(UINT16 event) +{ + switch(event) + { + CASE_RETURN_STR(BTA_DM_INQ_RES_EVT) + CASE_RETURN_STR(BTA_DM_INQ_CMPL_EVT) + CASE_RETURN_STR(BTA_DM_DISC_RES_EVT) + CASE_RETURN_STR(BTA_DM_DISC_BLE_RES_EVT) + CASE_RETURN_STR(BTA_DM_DISC_CMPL_EVT) + CASE_RETURN_STR(BTA_DM_DI_DISC_CMPL_EVT) + CASE_RETURN_STR(BTA_DM_SEARCH_CANCEL_CMPL_EVT) + + default: + return "UNKNOWN MSG ID"; + } +} + + +const char* dump_property_type(bt_property_type_t type) +{ + switch(type) + { + CASE_RETURN_STR(BT_PROPERTY_BDNAME) + CASE_RETURN_STR(BT_PROPERTY_BDADDR) + CASE_RETURN_STR(BT_PROPERTY_UUIDS) + CASE_RETURN_STR(BT_PROPERTY_CLASS_OF_DEVICE) + CASE_RETURN_STR(BT_PROPERTY_TYPE_OF_DEVICE) + CASE_RETURN_STR(BT_PROPERTY_REMOTE_RSSI) + CASE_RETURN_STR(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) + CASE_RETURN_STR(BT_PROPERTY_ADAPTER_BONDED_DEVICES) + CASE_RETURN_STR(BT_PROPERTY_ADAPTER_SCAN_MODE) + CASE_RETURN_STR(BT_PROPERTY_REMOTE_FRIENDLY_NAME) + + default: + return "UNKNOWN PROPERTY ID"; + } +} + + +const char* dump_hf_event(UINT16 event) +{ + switch(event) + { + CASE_RETURN_STR(BTA_AG_ENABLE_EVT) + CASE_RETURN_STR(BTA_AG_REGISTER_EVT) + CASE_RETURN_STR(BTA_AG_OPEN_EVT) + CASE_RETURN_STR(BTA_AG_CLOSE_EVT) + CASE_RETURN_STR(BTA_AG_CONN_EVT) + CASE_RETURN_STR(BTA_AG_AUDIO_OPEN_EVT) + CASE_RETURN_STR(BTA_AG_AUDIO_CLOSE_EVT) + CASE_RETURN_STR(BTA_AG_SPK_EVT) + CASE_RETURN_STR(BTA_AG_MIC_EVT) + CASE_RETURN_STR(BTA_AG_AT_CKPD_EVT) + CASE_RETURN_STR(BTA_AG_DISABLE_EVT) + + CASE_RETURN_STR(BTA_AG_AT_A_EVT) + CASE_RETURN_STR(BTA_AG_AT_D_EVT) + CASE_RETURN_STR(BTA_AG_AT_CHLD_EVT) + CASE_RETURN_STR(BTA_AG_AT_CHUP_EVT) + CASE_RETURN_STR(BTA_AG_AT_CIND_EVT) + CASE_RETURN_STR(BTA_AG_AT_VTS_EVT) + CASE_RETURN_STR(BTA_AG_AT_BINP_EVT) + CASE_RETURN_STR(BTA_AG_AT_BLDN_EVT) + CASE_RETURN_STR(BTA_AG_AT_BVRA_EVT) + CASE_RETURN_STR(BTA_AG_AT_NREC_EVT) + CASE_RETURN_STR(BTA_AG_AT_CNUM_EVT) + CASE_RETURN_STR(BTA_AG_AT_BTRH_EVT) + CASE_RETURN_STR(BTA_AG_AT_CLCC_EVT) + CASE_RETURN_STR(BTA_AG_AT_COPS_EVT) + CASE_RETURN_STR(BTA_AG_AT_UNAT_EVT) + CASE_RETURN_STR(BTA_AG_AT_CBC_EVT) + CASE_RETURN_STR(BTA_AG_AT_BAC_EVT) + CASE_RETURN_STR(BTA_AG_AT_BCS_EVT) + + default: + return "UNKNOWN MSG ID"; + } +} + + +const char* dump_hf_conn_state(UINT16 event) +{ + switch(event) + { + CASE_RETURN_STR(BTHF_CONNECTION_STATE_DISCONNECTED) + CASE_RETURN_STR(BTHF_CONNECTION_STATE_CONNECTING) + CASE_RETURN_STR(BTHF_CONNECTION_STATE_CONNECTED) + CASE_RETURN_STR(BTHF_CONNECTION_STATE_DISCONNECTING) + default: + return "UNKNOWN MSG ID"; + } +} + +const char* dump_hf_call_state(bthf_call_state_t call_state) +{ + switch(call_state) + { + CASE_RETURN_STR(BTHF_CALL_STATE_IDLE) + CASE_RETURN_STR(BTHF_CALL_STATE_ONHOLD) + CASE_RETURN_STR(BTHF_CALL_STATE_DIALING) + CASE_RETURN_STR(BTHF_CALL_STATE_ALERTING) + CASE_RETURN_STR(BTHF_CALL_STATE_INCOMING) + CASE_RETURN_STR(BTHF_CALL_STATE_WAITING) + CASE_RETURN_STR(BTHF_CALL_STATE_ACTIVE) + default: + return "UNKNOWN MSG ID"; + } +} + +const char* dump_thread_evt(bt_cb_thread_evt evt) +{ + switch(evt) + { + CASE_RETURN_STR(ASSOCIATE_JVM) + CASE_RETURN_STR(DISASSOCIATE_JVM) + + default: + return "unknown thread evt"; + } +} + + +const char* dump_hf_audio_state(UINT16 event) +{ + switch(event) + { + CASE_RETURN_STR(BTHF_AUDIO_STATE_DISCONNECTED) + CASE_RETURN_STR(BTHF_AUDIO_STATE_CONNECTING) + CASE_RETURN_STR(BTHF_AUDIO_STATE_CONNECTED) + CASE_RETURN_STR(BTHF_AUDIO_STATE_DISCONNECTING) + default: + return "UNKNOWN MSG ID"; + + } +} + + +const char* dump_adapter_scan_mode(bt_scan_mode_t mode) +{ + switch(mode) + { + CASE_RETURN_STR(BT_SCAN_MODE_NONE) + CASE_RETURN_STR(BT_SCAN_MODE_CONNECTABLE) + CASE_RETURN_STR(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) + + default: + return "unknown scan mode"; + } +} + +const char* dump_bt_status(bt_status_t status) +{ + switch(status) + { + CASE_RETURN_STR(BT_STATUS_SUCCESS) + CASE_RETURN_STR(BT_STATUS_FAIL) + CASE_RETURN_STR(BT_STATUS_NOT_READY) + CASE_RETURN_STR(BT_STATUS_NOMEM) + CASE_RETURN_STR(BT_STATUS_BUSY) + CASE_RETURN_STR(BT_STATUS_UNSUPPORTED) + + default: + return "unknown scan mode"; + } +} + + + |