Android 4.4.2 bluetooth解析(一)

来源:互联网 发布:手机振动器软件 编辑:程序博客网 时间:2024/06/05 03:16

由于开发项目的关系,最近一直在对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; 但是一定要细心奥:
bt_vendor_interface_t的结构体是在Bt_vendor_lib.h (\external\bluetooth\bluedroid\hci\include)大家可以自己去查一下,我这里也不贴了。

这个时候我们要去找op函数的实现在Bt_vendor_brcm.c (\android4.4\hardware\broadcom\libbt\src)

// Entry point of DLibconst 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;}

好的,我们终于找到rfkill的路径了,剩下的就是调用kernel bluetooth的sys设备符了。

后面我会陆续更新几篇scan和connect的帖子,希望能帮助大家。






0 0
原创粉丝点击