由于开发项目的关系,最近一直在对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 (*enable)(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;
}
刚才传递的参数是BT_VND_OP_POWER_CTRLcase 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的帖子,希望能帮助大家。