Android 4.4.2 bluetooth解析(一)
開発プロジェクトの関係で、最近android 4に対してずっと4のbluedroidは研究を行い、ユーザー向けの応用を開発したが、実際に開発過程で出会った問題からandroid 4.4 bluedroidはまだ完璧ではありません.特に、bleが多く、ble bluetoothgattserver rolesを使用している場合です.
開発過程は実際に現在ネット上で最新のandroid 4について発見した.4 bleの紹介が少なく、自分ではあまり満足していないような気がします.だから自分でandroidを勉強したいと思っています.4 bleの皆さん参考にしてください.一部の部分はよく書けないので、指摘を歓迎します.さあ、今から始めます.
まず、Bluetoothの最初のステップは電源を入れることですが、android 4.4 Bluetoothの電源部分のコードは実際にandroid 4となっています.3違います.
android4.3 Bluetooth osはsystem/bluetoothですがandroid 4.4歩いているのはhardware/libhardwareとexternal/bluetooth/です.具体的には以下を見てください.
Bluetooth.h(hardware/libhardware/include/hardware/)---これは構造体で、主にenable関数を見ます.
Bluetooth.c (external\bluetooth\bluedroid\btif\src)
Btif_core.c (\external\bluetooth\bluedroid\btif\src)
関数の照合でBt_が見つかりますhci_bdroid.c(android 4.4externalbluetoothbluedroidhcisrc)、ここがset_Powerの実現.
bt_vendor_interface_tの構造体はBt_vendor_lib.h (\external\bluetooth\bluedroid\hci\include)
みんなは自分で調べてもいいです.私のところにも貼っていません.
この時、Bt_でop関数の実装を探します.vendor_brcm.c (\android4.4\hardware\broadcom\libbt\src)
開発過程は実際に現在ネット上で最新のandroid 4について発見した.4 bleの紹介が少なく、自分ではあまり満足していないような気がします.だから自分でandroidを勉強したいと思っています.4 bleの皆さん参考にしてください.一部の部分はよく書けないので、指摘を歓迎します.さあ、今から始めます.
まず、Bluetoothの最初のステップは電源を入れることですが、android 4.4 Bluetoothの電源部分のコードは実際にandroid 4となっています.3違います.
android4.3 Bluetooth osはsystem/bluetoothですがandroid 4.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
");
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(android 4.4externalbluetoothbluedroidhcisrc)、ここが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)
みんなは自分で調べてもいいです.私のところにも貼っていません.
この時、Bt_でop関数の実装を探します.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_CTRL 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)
", \
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 , 。