Android Bluetooth HAL Interfaces について 概要編

# はじめに

AndroidのBluetooth機能のC言語用APIである Android Bluetooth HAL Interfaces と Bluetooth Profile HAL Interfaces について、これから何回かに分けて説明していきます。
説明するのはAndroid 5.0に対応したバージョンです。

個人的には現時点で自由に使えるBLEのAPIとしては一番マシなAPIだと思っています。ですが、まったくドキュメントが無いので直接叩く使い方をしている人は皆無です。

(自由に使えないAPIとは、自社チップ使用に限定したライセンスのチップベンダ各社のAPIや有償スタックのAPIなどのことです。)

ちなみに、Android Bluetooth HAL Interfaces を試すにはBlueZの最新版をインストールするのが楽です。

# Android Bluetooth HAL Interfaces の概要

* Android Bluetooth HAL InterfacesはGoogleがAndroidのために設計したハードウェア依存せずにBluetooth / BLE を取り扱うためのAPIです。
* HALはhardware abstraction layerと言ってハードウェアを抽象化して取り扱うためのレイヤーのことです。そのHALの層にアプリケーションからアクセスするためのAPIを定義しています。
* Google によるBluetoothのソフトウェア構成の説明が　https://source.android.com/devices/bluetooth.html にあります。そのページにあるAndroid Bluetooth HALの説明が下記です。

> The hardware abstraction layer defines the standard interface that the android.bluetooth APIs and Bluetooth process calls into and that you must implement to have your bluetooth hardware function correctly. The header files for the Bluetooth HAL is located in the hardware/libhardware/include/hardware/bluetooth.h and hardware/libhardware/include/hardware/bt_*.h files.

* APIの設計はGoogleが勝手に行っています。コミュニティベースの開発形態ではありません。(Bluetoothの機能の要望等をAndroidのバグトラッカーから行っている人もいますが…要望が採用されているかは不明です。下記リンクのチケットの状況を確認してください。)
 * https://code.google.com/p/android/issues/detail?id=9651
 * https://code.google.com/p/android/issues/detail?id=58164 
* APIの使い方に関するドキュメントはありません。
* APIの実装としてはBluedroidとBlueZの２種類があります。
* APIの採用例としてはAndroidとFirforx OSなどがあります。
* APIの動作を理解する手がかりとしては、Androidの実装と、BlueZに付属のサンプルが有用です。
* APIはC言語用でlibhardwareで定義されています。
* APIの特徴
 * コールバックを多用している。
 * 各Profileごとにインターフェイス用の関数ポインタの構造体を定義していいる。(これをAndroid Bluetooth Profile HAL Interfacesと呼ぶ)
* サポートしているプロファイル (APIから制御できるProfileです。)
 * A2DP
 * AVRCP
 * GAP
 * GATT
 * HFP
 * HID
 * PAN
 * SDP
 * RFCOMM

ちなみに、Androidは、OBEXプロファイルをRFCOMMの上にJAVAで実装しています。

# API説明

## ヘッダファイル
あとで書く。

## Bluetoothインターフェイスの取得

```c:hardware.h
int hw_get_module(const char *id, const struct hw_module_t **module);

int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);
```
```c:bluetooth.h
const bt_interface_t* (*get_bluetooth_interface)();
```

Bluetoothスタックを操作するためのインターフェイスを取得します。

## 初期化

```c:bluetooth.h
int (*init)(bt_callbacks_t* callbacks );
```
コールバック関数を登録します。

## 起動

```c:bluetooth.h
int (*enable)(void);
```

Bluetoothスタックを起動します。正常に起動するとadapter_state_changed_cbとadapter_properties_cbのコールバックが返ります。

## 停止

```c:bluetooth.h
int (*disable)(void);
```

Bluetoothスタックを停止します。

## 終了

```c:bluetooth.h
    void (*cleanup)(void);
```

initで登録したコールバック関数の設定をクリアします。


## 初期化から終了までのサンプルコード

上記で説明した、Bluetoothインターフェイス取得から終了までを行うサンプルコードです。
BlueZ付属のandroid/client/if-bt.cを説明のために改変しました。

```c

#include <hardware.h>
#include <bluetooth.h>

const hw_module_t *module;
static hw_device_t *bt_device;
const bt_interface_t *if_bluetooth;


static void adapter_state_changed_cb(bt_state_t state)
{
	printf("%s: state=%d\n", __func__, state);
}

static void adapter_properties_cb(bt_status_t status, int num_properties,
						bt_property_t *properties)
{
	printf("%s: status=%d num_properties=%d\n", __func__,status, num_properties);
}

static bt_callbacks_t bt_callbacks = {
	.size = sizeof(bt_callbacks),
	.adapter_state_changed_cb = adapter_state_changed_cb,
	.adapter_properties_cb = adapter_properties_cb,
	.remote_device_properties_cb = NULL,
	.device_found_cb = NULL,
	.discovery_state_changed_cb = NULL,
	.pin_request_cb = NULL,
	.ssp_request_cb = NULL,
	.bond_state_changed_cb = NULL,
	.acl_state_changed_cb = NULL,
	.thread_evt_cb = NULL,
	.dut_mode_recv_cb = NULL,
	.le_test_mode_cb = NULL,
	.energy_info_cb = NULL,
};

void bt_start_stop_test(void)
{
  hw_get_module(BT_HARDWARE_MODULE_ID, &module);

  module->methods->open(module, BT_HARDWARE_MODULE_ID, &bt_device);

  if_bluetooth = ((bluetooth_device_t *) bt_device)->get_bluetooth_interface();

  if_bluetooth->init(&bt_callbacks);

  if_bluetooth->enable();

  //10sec wait for callback

  if_bluetooth->disable();

  if_bluetooth->cleanup();
}
```

# 参考リンク
* https://source.android.com/devices/bluetooth.html
* https://android.googlesource.com/platform/hardware/libhardware/
* http://www.bluez.org/