由于开发项目的关系,最近一直在对android4.4的bluedroid进行研究,并且开发了一个面向用户的应用,但是实际上从开发过程遇到的问题发现,android4.4 bluedroid做的还是不完善,特别是在ble一连多和使用ble bluetoothgattserver roles的情况下。
开发过程发现实际现在网上对于最新的android4.4 ble介绍很少,自己感觉不是很满意。所以就想自己写一个供大家想学习android4.4 ble的同仁们参考。有些部分写的不好的,欢迎指正。好了,现在开始了。
首先我们都知道蓝牙第一步是上电,但是android4.4蓝牙上电部分的代码实际已经和android4.3不一样了。
android4.3蓝牙os是走system/bluetooth,但是android4.4走的是hardware/libhardware和external/bluetooth/,具体请看下面:
Bluetooth.h(hardware/libhardware/include/hardware/)----这是结构体,主要是看enable函数。
typedef struct { /** set to sizeof(bt_interface_t) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ int (*init)(bt_callbacks_t* callbacks ); /** Enable Bluetooth. */ int (*<span style="color:#ff0000;">enable</span>)(void); /** Disable Bluetooth. */ int (*disable)(void); /** Closes the interface. */ void (*cleanup)(void); /** Get all Bluetooth Adapter properties at init */ int (*get_adapter_properties)(void); /** Get Bluetooth Adapter property of 'type' */ int (*get_adapter_property)(bt_property_type_t type); /** Set Bluetooth Adapter property of 'type' */ /* Based on the type, val shall be one of * bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc */ int (*set_adapter_property)(const bt_property_t *property); /** Get all Remote Device properties */ int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr); /** Get Remote Device property of 'type' */ int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, bt_property_type_t type); /** Set Remote Device property of 'type' */ int (*set_remote_device_property)(bt_bdaddr_t *remote_addr, const bt_property_t *property); /** Get Remote Device's service record for the given UUID */ int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid); /** Start SDP to get remote services */ int (*get_remote_services)(bt_bdaddr_t *remote_addr); /** Start Discovery */ int (*start_discovery)(void); /** Cancel Discovery */ int (*cancel_discovery)(void); /** Create Bluetooth Bonding */ int (*create_bond)(const bt_bdaddr_t *bd_addr); /** Remove Bond */ int (*remove_bond)(const bt_bdaddr_t *bd_addr); /** Cancel Bond */ int (*cancel_bond)(const bt_bdaddr_t *bd_addr); /** BT Legacy PinKey Reply */ /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */ int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept, uint8_t pin_len, bt_pin_code_t *pin_code); /** BT SSP Reply - Just Works, Numeric Comparison and Passkey * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON & * BT_SSP_VARIANT_CONSENT * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey * shall be zero */ int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant, uint8_t accept, uint32_t passkey); /** Get Bluetooth profile interface */ const void* (*get_profile_interface) (const char *profile_id); /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */ /* Configure DUT Mode - Use this mode to enter/exit DUT mode */ int (*dut_mode_configure)(uint8_t enable); /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */ int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len); /** BLE Test Mode APIs */ /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */ int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len); /* enable or disable bluetooth HCI snoop log */ int (*config_hci_snoop_log)(uint8_t enable); } bt_interface_t;有结构体就会要找结构体对照的函数实现:
Bluetooth.c (external\bluetooth\bluedroid\btif\src)
const bt_interface_t* bluetooth__get_bluetooth_interface () { /* fixme -- add property to disable bt interface ? */ return &bluetoothInterface; }
static const bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), 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, get_remote_services, start_discovery, cancel_discovery, create_bond, remove_bond, cancel_bond, pin_reply, ssp_reply, get_profile_interface, dut_mode_configure, dut_mode_send, #if BLE_INCLUDED == TRUE le_test_mode, #else NULL, #endif config_hci_snoop_log };找到enable函数了,那就要看看他的实现:
static int enable( void ) { ALOGI("enable"); /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_enable_bluetooth(); }接下来就是按照函数实现一步一步走了,但是btif_enable_bluetooth()是有声明函数的,一定要注意,在btif_api.h,这里就不贴代码了。继续:
Btif_core.c (\external\bluetooth\bluedroid\btif\src)
bt_status_t btif_enable_bluetooth(void) { BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH"); if (btif_core_state != BTIF_CORE_STATE_DISABLED) { ALOGD("not disabled\n"); return BT_STATUS_DONE; } btif_core_state = BTIF_CORE_STATE_ENABLING; /* Create the GKI tasks and run them */ bte_main_enable(); return BT_STATUS_SUCCESS; }接下来我们要去找bte_main_enable函数的实现了:
void bte_main_enable() { APPL_TRACE_DEBUG1("%s", __FUNCTION__); /* Initialize BTE control block */ BTE_Init(); lpm_enabled = FALSE; bte_hci_enable(); GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR, (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE), sizeof(bte_btu_stack)); GKI_run(0); }接下来是bte_hci_enable,当然有一些函数你可以看看,BTE_Init()和GKI-
static void bte_hci_enable(void) { APPL_TRACE_DEBUG1("%s", __FUNCTION__); preload_start_wait_timer(); if (bt_hc_if) { int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address); APPL_TRACE_EVENT1("libbt-hci init returns %d", result); assert(result == BT_HC_STATUS_SUCCESS); if (hci_logging_enabled == TRUE || hci_logging_config == TRUE) bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile); #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE) APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__); /* Do not power off the chip before powering on if BT_CLEAN_TURN_ON_DISABLED flag is defined and set to TRUE to avoid below mentioned issue. Wingray kernel driver maintains a combined counter to keep track of BT-Wifi state. Invoking set_power(BT_HC_CHIP_PWR_OFF) when the BT is already in OFF state causes this counter to be incorrectly decremented and results in undesired behavior of the chip. This is only a workaround and when the issue is fixed in the kernel this work around should be removed. */ #else /* toggle chip power to ensure we will reset chip in case a previous stack shutdown wasn't completed gracefully */ bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF); #endif bt_hc_if->set_power(BT_HC_CHIP_PWR_ON); bt_hc_if->preload(NULL); } }这个地方就要特别小心了,因为你会发现这里不是现实
static bt_hc_interface_t *bt_hc_if=NULL;具体的对照关系要去bt_hci_lib.h文件里去查bt_hc_interface_t结构体的内容,这里也不贴了。
通过函数对照你会找到Bt_hci_bdroid.c (\android4.4\external\bluetooth\bluedroid\hci\src),这里才是set_power的实现。
const bt_hc_interface_t *bt_hc_get_interface(void) { return &bluetoothHCLibInterface; }
static const bt_hc_interface_t bluetoothHCLibInterface = { sizeof(bt_hc_interface_t), init, set_power, lpm, preload, postload, transmit_buf, set_rxflow, logging, cleanup };这时候就可以去找set_power的实现了:
/** Chip power control */ static void set_power(bt_hc_chip_power_state_t state) { int pwr_state; BTHCDBG("set_power %d", state); /* Calling vendor-specific part */ pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF; if (bt_vnd_if) bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state); else ALOGE("vendor lib is missing!"); }这时候又要进行函数对照了,extern bt_vendor_interface_t *bt_vnd_if; 但是一定要细心奥:
这个时候我们要去找op函数的实现在Bt_vendor_brcm.c (\android4.4\hardware\broadcom\libbt\src)
// Entry point of DLib const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = { sizeof(bt_vendor_interface_t), init, op, cleanup };
static int op(bt_vendor_opcode_t opcode, void *param) { int retval = 0; BTVNDDBG("op for %d", opcode); switch(opcode) { case BT_VND_OP_POWER_CTRL: { int *state = (int *) param; if (*state == BT_VND_PWR_OFF) upio_set_bluetooth_power(UPIO_BT_POWER_OFF); else if (*state == BT_VND_PWR_ON) upio_set_bluetooth_power(UPIO_BT_POWER_ON); } break; case BT_VND_OP_FW_CFG: { hw_config_start(); } break; case BT_VND_OP_SCO_CFG: { #if (SCO_CFG_INCLUDED == TRUE) hw_sco_config(); #else retval = -1; #endif } break; case BT_VND_OP_USERIAL_OPEN: { int (*fd_array)[] = (int (*)[]) param; int fd, idx; fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg); if (fd != -1) { for (idx=0; idx < CH_MAX; idx++) (*fd_array)[idx] = fd; retval = 1; } /* retval contains numbers of open fd of HCI channels */ } break; case BT_VND_OP_USERIAL_CLOSE: { userial_vendor_close(); } break; case BT_VND_OP_GET_LPM_IDLE_TIMEOUT: { uint32_t *timeout_ms = (uint32_t *) param; *timeout_ms = hw_lpm_get_idle_timeout(); } break; case BT_VND_OP_LPM_SET_MODE: { uint8_t *mode = (uint8_t *) param; retval = hw_lpm_enable(*mode); } break; case BT_VND_OP_LPM_WAKE_SET_STATE: { uint8_t *state = (uint8_t *) param; uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ TRUE : FALSE; hw_lpm_set_wake_state(wake_assert); } break; case BT_VND_OP_EPILOG: { #if (HW_END_WITH_HCI_RESET == FALSE) if (bt_vendor_cbacks) { bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); } #else hw_epilog_process(); #endif } break; } return retval; }
</pre>刚才传递的参数是BT_VND_OP_POWER_CTRL<p></p><p></p><pre code_snippet_id="364689" snippet_file_name="blog_20140527_15_120503" name="code" class="cpp"> case BT_VND_OP_POWER_CTRL: { int *state = (int *) param; if (*state == BT_VND_PWR_OFF) upio_set_bluetooth_power(UPIO_BT_POWER_OFF); else if (*state == BT_VND_PWR_ON) upio_set_bluetooth_power(UPIO_BT_POWER_ON); } break;实际我们走的是upio_set_bluetooth_power(UPIO_BT_POWER_ON);所以:
接下来已经到Upio.c (android4.4\hardware\broadcom\libbt\src)
忽然发现,这个文件结构有点像android4.3以前的bluetooth.c,找到实现代码:
static int init_rfkill() { char path[64]; char buf[16]; int fd, sz, id; if (is_rfkill_disabled()) return -1; for (id = 0; ; id++) { snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); fd = open(path, O_RDONLY); if (fd < 0) { ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \ path, strerror(errno), errno); return -1; } sz = read(fd, &buf, sizeof(buf)); close(fd); if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) { rfkill_id = id; break; } } asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id); return 0; }
int upio_set_bluetooth_power(int on) { int sz; int fd = -1; int ret = -1; char buffer = '0'; switch(on) { case UPIO_BT_POWER_OFF: buffer = '0'; break; case UPIO_BT_POWER_ON: buffer = '1'; break; } if (is_emulator_context()) { /* if new value is same as current, return -1 */ if (bt_emul_enable == on) return ret; UPIODBG("set_bluetooth_power [emul] %d", on); bt_emul_enable = on; return 0; } /* check if we have rfkill interface */ if (is_rfkill_disabled()) return 0; if (rfkill_id == -1) { if (init_rfkill()) return ret; } fd = open(rfkill_state_path, O_WRONLY); if (fd < 0) { ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)", rfkill_state_path, strerror(errno), errno); return ret; } sz = write(fd, &buffer, 1); if (sz < 0) { ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),errno); } else ret = 0; if (fd >= 0) close(fd); return ret; }
后面我会陆续更新几篇scan和connect的帖子,希望能帮助大家。