目录:
0 应用层设计相关 一、application Framework 二、Bluetooth server层:服务层 包括两部分--Bluetooth System service(部分)和Bluetooth profile; 2.1 mtk 封装的库(JNI和中间协议) 三、JNI 四、HAL 五、BT stack---- 实现(中间协议+核心协议)。 六、Vendor extension---也就是HCI驱动层的用户空间接口 七 system\bluetoothBluetooth (mtk removed it ) 八 内核层 九 驱动层
================================================================
0 应用层设计相关
kitkat_ibd\packages\apps\Settings\src\com\Android\settings\bluetooth
-----Android 4.4
谷歌原生的profile管理接口。包括opp、hfp、hdp、a2dp、pan,gatt等等,
这里自称为面向应用的profile接口。
一、application Framework
这个层的代码主要是利用android.bluetoothAPIS和 bluetooth hardware进行交互。也就是通过BinderIPC机制调用bluetooth进程;
Android原生的BTFramework代码位于framework/base/core/Java/android.bluetooth/下。
这个目录里的代码更像一个桥梁,里面有供Java层使用一些类,也有对应的aidl文件联系C、C++部分的代码,包括opp、hfp、hdp、a2dp、pan,gatt等等
MTK厂商客制化的修改代码位于
\mediatek\frameworks-ext\base\core\java\android\bluetooth
重写了原生部分的BT代码,而且各种profile API:是桥接application和server之间的接口:BluetoothFtp.java /BluetoothHealth.ajva /BluetoothHid.java…….
两者什么关系?增加了自己的相关profile server桥接接口(与Bluetooth的server层 profile对应的):如下:
LOCAL_SRC_FILES += \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBipi.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBipr.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothBpp.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothDun.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpCtrl.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpServer.aidl \
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothFtpServerCallback.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothProfileManager.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothSimap.aidl\
../../mediatek/frameworks-ext/base/core/java/android/bluetooth/IBluetoothSimapCallback.aidl\
../../mediatek/frameworks-ext/base/core/java/com/mediatek/bluetooth/service/IBluetoothPrxm.aidl\
../../mediatek/frameworks-ext/base/core/java/com/mediatek/bluetooth/service/IBluetoothPrxr.aidl\
../../mediatek/frameworks-ext/base/core/java/android/net/INetworkManagementIpv6EventObserver.aidl
如何编译?
通过\frameworks\base的Android,.mk包含include$(LOCAL_PATH)/../../mediatek/frameworks-ext/base/config.mk完成把:mtk客制化增加的framework和原生的BTFramework的整合->生成:framework.jar。
下面仅仅是原生的例子:
比如A2DP的连接:framework/base/core/java/android/bluetooth/BluetoothA2dp.java中的connect(Bluetoothevice)方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
通过Binder IPC通信机制,调用到packages/apps/Bluetooth/src/com.android.bluetooth.a2dp/A2dpService.java下一个内部私有类
A2dpService是一个继承于ProfileService的类,而类ProfileService是继承于Service类的。
private static class BluetoothA2dpBinder extendsIBluetoothA2dp.Stub{}的connect(BluetoothDevice)方法。
1
2
3
4
5
public boolean connect(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return false;
return service.connect(device);
}
然后调用到A2dpService的connect(BluetoothDevice)方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public boolean connect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
return false;
}
int connectionState = mStateMachine.getConnectionState(device);
if (connectionState == BluetoothProfile.STATE_CONNECTED ||
connectionState == BluetoothProfile.STATE_CONNECTING) {
return false;
}
mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
return true;
}
这个过程就是Bluetooth Application Framework与Bluetooth Process的调用过程。
二、Bluetooth server层:服务层 包括两部分--Bluetooth System service(部分)和Bluetoothprofile;
1.Bluetooth System service:
\mediatek\frameworks-ext\base\core\java\android\server
编译到framework.jar :mtk自增加的profilemanager server部分
2.Bluetooth profile API接口(也就是各个profile的server层):
---这里自称为server层的profile接口。
----实现了关于蓝牙java应用profile的API代码,包括opp、hfp、hdp、a2dp、pan,gatt等等,而且也有部分server性质的代码(不同的profile,有不同的设计)
由两部分组成:
packages/apps/Bluetooth
android原生提供的profile:a2dp,gatt,hdp,hfp,hid,map,opp,pan,pbap
生成bluetooth.apk
\mediatek\packages\apps\bluetooth\profiles
mtk增加的profile:
MtkBt.apk:
进程名:com.mediatek.bluetooth
“如果删除,则连接不上,提示parei,connet错误等信息。
因为很多pofile都连接不上。”
mtk增加的profile:
include$(MY_MODULE_PATH)/profiles/prxm/Android.mk
include$(MY_MODULE_PATH)/profiles/prxr/Android.mk
include$(MY_MODULE_PATH)/profiles/simap/Android.mk
include$(MY_MODULE_PATH)/profiles/ftp/Android.mk
include$(MY_MODULE_PATH)/profiles/bpp/Android.mk
include$(MY_MODULE_PATH)/profiles/bip/Android.mk
include$(MY_MODULE_PATH)/profiles/dun/Android.mk
src_list +=profiles/prxm profiles/prxr profiles/simap profiles/ftp profiles/bppprofiles/bip profiles/dun
Bluetooth System service位于packages/apps/Bluetooth目录下,它打包成一个android app包,并且在android framework 层实现BTservice和各种profile。BT app会通过JNI调用到HAL层。
A2dpService.java
的connect方法会发送一个StateMachine.sendMessage(A2dpStateMachine.CONNECT,device)的message,这个message会被A2dpStateMachine.java对象的processMessage(Message)方法接收到:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
case CONNECT:
BluetoothDevice device = (BluetoothDevice) message.obj;
broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
BluetoothProfile.STATE_DISCONNECTED);
if (!connectA2dpNative(getByteAddress(device)) ) {
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
BluetoothProfile.STATE_CONNECTING);
break;
}
synchronized (A2dpStateMachine.this) {
mTargetDevice = device;
transitionTo(mPending);
}
// TODO(BT) remove CONNECT_TIMEOUT when the stack
// sends back events consistently
sendMessageDelayed(CONNECT_TIMEOUT, 30000);
break;
最重要的一句:connectA2dpNative(getByteAddress(device);
即会通过JNI调用到Native:
Com_android_bluetooth_a2dp.cpp(kitkat_ibd\packages\apps\bluetooth\jni): {"connectA2dpNative"
server层就调用到JNI层----》
////////////////////////////////////////////////////////////////////////////
mtk封装的库(JNI和中间协议)
////////////////////////////////////////////////////////////////////
\build\target\product\common.mk定义:
ifeq ($(strip$(MTK_BT_SUPPORT)), yes)
PRODUCT_PROPERTY_OVERRIDES += \
ro.btstack=blueangel
PRODUCT_PACKAGES += MtkBt \
btconfig.xml \
auto_pair_blacklist.conf \
libbtcusttable \
libbtcust \
libmtkbtextadp \
libextpbap \
libextavrcp \
libextopp \
libextsys \
libextftp \
libmtkbtextadpa2dp \
libmtka2dp \
libextbip \
libextbpp \
libexthid \
libextsimap \
libextjsr82 \
libbtsession \
libmtkbtextpan \
libextmap \
libmtkbtextspp \
libexttestmode \
libpppbtdun \
libextopp_jni \
libexthid_jni \
libextpan_jni \
libextftp_jni \
libextbpp_jni \
libextbip_jni \
libextpbap_jni \
libextavrcp_jni \
libextsimap_jni \
libextdun_jni \
libextmap_jni \
libextsys_jni \
libextadvanced_jni \
btlogmask \
btconfig \
libbtpcm \
libbtsniff \
mtkbt \
bluetooth.blueangel \
audio.a2dp.blueangel
Endif
\vendor\mediatek\huaqin82_we_iba_jb5\artifacts\out\target\product\huaqin82_we_iba_jb5\system\lib
三、JNI
与android.bluetooth有关的JNI代码位于:分为两部分:
android原生的和mtk增加的:
\packages\apps\Bluetooth\jni,
原生的BT JNI代码:
com_android_bluetooth_btservice_AdapterService.cpp:
控制本地蓝牙芯片,加载蓝牙hal层:BT_STACK_MODULE_ID定义在bluetooth。c。
com_android_bluetooth_hfp.cpp \
com_android_bluetooth_a2dp.cpp \
com_android_bluetooth_avrcp.cpp \
com_android_bluetooth_hid.cpp \
com_android_bluetooth_hdp.cpp \
com_android_bluetooth_pan.cpp \
com_android_bluetooth_gatt.cpp
生成:libbluetooth_jni.so
实现:
本地设备的hal控制;
调起各种中间协议;
\mediatek\frameworks-ext\base\core\jni
mtk平台的BT jni代码所在路径
kitkat不使用
JNI的代码会调用到HAL层,并且在确信一些BT操作被触发时,会从HAL获取一些回调。比如当BT设备被发现时。
再回到A2dp连接的例子中来,BT System Service通过JNI会调用到com_android_bluetooth_a2dp.cpp中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
jbyte *addr;
bt_bdaddr_t * btAddr;
bt_status_t status;
ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface);
if (!sBluetoothA2dpInterface) return JNI_FALSE;
addr = env->GetByteArrayElements(address, NULL);
btAddr = (bt_bdaddr_t *) addr;
if (!addr) {
jniThrowIOException(env, EINVAL);
return JNI_FALSE;
}
if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
ALOGE("Failed HF connection, status: %d", status);
}
env->ReleaseByteArrayElements(address, addr, 0);
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
重点代码是:status= sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr);
这个sBluetoothA2dpInterface结构体对象是在initNative(JNIEnv *env, jobject object)方法时得到的。
1
2
3
4
5
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
return;
}
四、HAL
4.1硬件抽象层定义android.bluetooth APIs和BTprocess调用的标准接口(所有的厂家都是按照这种接口定义来编写自己的底层协议栈),并且你必须实现这些接口来让你的BT hardware功能运行正常。BT HAL的的头文件位于hardware/libhardware/include/hardware/bluetooth.h和hardware/libhardware/include/hardware/bt_*.h文件中。
JNI中sBluetoothA2dpInterface是一个btav_interface_t结构体,位于hardware/libhardware/include/hardware/bt_av.h中,定义为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct {
/** set to sizeof(btav_interface_t) */
size_t size;
/**
* Register the BtAv callbacks
*/
bt_status_t (*init)( btav_callbacks_t* callbacks );
/** connect to headset */
bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
/** dis-connect from headset */
bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
/** Closes the interface. */
void (*cleanup)( void );
} btav_interface_t;
就是定义好统一的协议栈接口,厂家按照该定义来实现自己的bt协议栈(与profile不是一个概念,这里定义的是中间协议+核心协议)。
4.2 HAL实现
\external\bluetooth\bluedroid\btif\
Bluetooth.c
生成在bluetooth.default.so以及提供各种profile interfaces供jni层调用,如:
sock_if{}(只支持BTSOCK_RFCOMM socket,不支持BTSOCK_SCO,BTSOCK_L2CAP);
bthfInterface{};//HFP接口
pan_if{} ;
bt_av_interface{}//a2dp协议接口
bthlInterface{};
….
五、BT stack----实现(中间协议+核心协议)。
一个完整的蓝牙协议栈按其功能又可划分为四层:
核心协议层:
(BB、LMP)、
硬件实现
中间协议层:
L2CAP、SDP线缆替换协议层(RFCOMM)、电话控制协议层(TCS-BIN)、
软件实现
选用协议层:
(PPP、TCP、TP、UDP、OBEX、IrMC、WAP、WAE):由系统或者第3方提供
软件实现
例如android的:OBEX
\frameworks\base\obex
javax.obex.jar
作为默认的BT stack,(4.2之前是bluez作为协议栈的)
代码位于:
external/bluetooth/bluedroid下,
这个stack实现了通用的BT HAL并且也可以通过扩展和改变配置来自定义。
生成libbt-brcm_stack.a.因为商业关系,谷歌把bluez的协议换成的bocom公司的,bluedroid里面的协议代码可以作为自己编写新的profile时候的参考。
vendor\mediatek\huaqin82_we_iba_jb5\artifacts\out\target\product\huaqin82_we_iba_jb5\obj\STATIC_LIBRARIES\libmtkbtstack2_intermediates
同上
mtk自定重新写了一套BT协议栈libmtkbtstack2.a
libmtkbtstack.a
增加了BLE支持所需要的gatt协议。
#ar -tlibmtkbtstack2.a列出其包含的.o
mele.o
rfc_ctl.o
rfc_fcs.o
rfc_sm.o
rfc_util.o
rfcomm.o
sdap.o
sdp.o
sdpclient.o
sdpserv.o
avc.o
avctp.o
avctp
l2cap等等
A2dp的连接会调用到external/bluetooth/bluedroid/btif/src/btif_av.c的connect方法。
1
2
3
4
5
6
7
static bt_status_t connect(bt_bdaddr_t *bd_addr)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
CHECK_BTAV_INIT();
return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
}
libbt-brcm_stack.a.与libmtkbtstack2.a两者什么关系???????
六、Vendor extension---也就是HCI驱动层的用户空间接口
为了追踪添加自定义拓展和一个HCI层,你可以创建一个libbt-vendor模块并且指定这些组件。
\external\bluetooth\bluedroid\hci
HCI驱动层的用户空间接口,完成dlopen("libbt-vendor.so", RTLD_NOW);
文件系统接口就是:bt_vnd_if。
七system\bluetoothBluetooth --mtk removed it
适配层代码,和framework那个作用类似,是串联framework与blueZ的工具。
BOARD_HAVE_BLUETOOTH没定义,mtk平台也是弃用,只是利用里面的标准蓝牙配置参数(EnableLE等等 有时间研究一下)
#ifeq($(BOARD_HAVE_BLUETOOTH),true)
include $(all-subdir-makefiles)
#endif
#ifeq($(MTK_BT_SUPPORT),true)
include $(LOCAL_PATH)/data/Android.mk
#endif
八内核层---
mtk平台android2.3以上的平台都不用blueZ,使用MTK自编写的blueangel,这里仅仅以blueZ为蓝本分析数据流程。
kernel\drivers\bluetooth
对各种接口的Bluetoothdevice的驱动实例(意思就是指导大家porting驱动的时候做一个参考设计)。例如:USB接口,串口,SDIO等,例如:
--Hci_ldis.c实现一个蓝牙专用的线路规程。但是mtk不是这样,mtk是combo芯片,中间的数据传输还通过STP(Serial Transport Protocol)模块。
kernel\net\bluetooth
核心协议和中间层协议实现。包括hci,hid,rfcomm,sco,SDP等协议
核心协议层:
(BB、LMP、LCAP、SDP)、
中间协议层:
线缆替换协议层(RFCOMM)、电话控制协议层(TCS-BIN)、
以及socket接口定义和实现。
9驱动层
预备知识:1.Linux网络体系结构
1.Linux网络体系结构由以下五个部分组成,以及对应的网络模型关系
1)系统调用接口
应用层
berkeley库:socket的基本操作
3.1、socket()函数 3.2、bind()函数 3.3、listen()、connect()函数 3.4、accept()函数 3.5、read()、write()函数等 3.6、close()函数 通过系统调用内陷到socket实现层,
比如:sys_socket()---》sock_creat()
2)协议无关接口socket
应用层
由socket(net/socket.c)来实现的。它提供了一组通用函数来支持各种不同协议。
操作接口是: file_operations socket_file_ops{}
如何与协议称通信?通过file ops。如下
通过sock->ops->recvmsg()//ops来自层注册好的接口
…...
3)网络协议
传输层+网络层
net_family实现各种协议的数据封装。
例如:
proto_ops hci_sock_ops 蓝牙的hci协议:hci_sock.c
proto_ops l2cap_sock_ops = { //l2cap_sock.c
proto_ops inet6_dgram_ops IPv6的协议
…….
4)设备无关接口
数据连路层
1.实现对netdevice的管理。包括设备驱动程序可能会通过调用register_netdevice 或 unregister_netdevice在内核中进行注册或注销
2.与协议层的数据(socket)的bufer缓冲;
不同的网络设备功能来决定,比如网卡,wifi,红外就是这种标准的驱动模型。
蓝牙就不完全是,蓝牙只有模拟eth,ip设备时候走这标准。
5)设备驱动程序。
数据链路层
1负责管理物理网络设备的设备驱动程序:net_device_ops和net_device的创建
。例如,包串口使用的 SLIP驱动程序以及以太网设备使用的以太网驱动程序都是这一层的设备。
读写数据的操作对象是:sk_buff
例如:
6lowpan.c (\kernel\net\ieee802154):static const struct net_device_opslowpan_netdev_ops
-----------------
Irda_framer.c (\mediatek\platform\mt6582\kernel\drivers\ldvt\irda):static const structnet_device_ops mt_irda_netdev_ops=
接受:mt_irda_irq()---》mt_irda_rx_one_skb()---》netif_rx()
发送:mt_irda_xmit()
-------------------
mtk蓝牙就是:bt_net_dev.c,实现模拟IP设备(蓝牙作为网关设备,实现对其他蓝牙设备的ip控制)和eth设备(就是蓝牙手机做网卡)
注意:蓝牙的一般通信(常规的profile)没有这一层
蓝牙HCI驱动 物理传输
stp_uart.c
mtk平台的设备驱动组成:
CONFIG_MTK_COMBO=m
CONFIG_MTK_COMBO_BT=m--------生成ko
CONFIG_MTK_COMBO_GPS=m
CONFIG_MTK_COMBO_WIFI=m
网络设备驱动层
bt_net_dev.c
注册网络设备驱动,实现了net_device_ops和创建net_device---kikat弃用
在alps\mediatek\config\mt65xx\autoconfig\kconfig\platform中添加下面定义:
CONFIG_MTK_BT_NET_DEV=y
1.功能:实现模拟IP设备(蓝牙作为网关设备,实现对其他蓝牙设备的ip控制)和eth设备(就是蓝牙手机做网卡)
net_device_ops和net_device的创建;
2应用范围:
2.1蓝牙共享网络(Bluetooth tethering),也就是Personal Area Networking Profile
通过tty串口驱动与蓝牙芯片交互
stp_uart.c
1.tty_register_ldisc注册tty驱动接口。
----线路ID(可以自定义):N_MTKSTP
---stp_uart_tty_read()++stp_uart_tty_write() +stp_uart_tty_poll()为空--》
所以上层就不能再通过读写tty设备的方式发送、接收HCI数据。取而代之的,N_MTKSTP中实现了对上层的socket接口,即与/net/bluetooth/目录下的代码交互数据的接口。
mtk是combo芯片,中间的数据传输还通过STP(Serial Transport Protocol)模块。
2.如何(谁)操作该tty设备?通过应用/system/bin/6620_launcher
\mediatek\external\combo_tool\src
比如注册tty设备到hci core的list里面。mtk这里什么也没有做,why?
一般都是在tty驱动里面通过HCIUARTSETPROTO完成tty设备注册到HCI core。
3.tty如何与hci socket之间通信?通过HCI core 。所以驱动需要alloc分配和注册hci设备到:hci_dev_list这样一个链表。
要hci_register_dev()(实例Hci_ldis里面的)来完成于socket的绑定。
”但是mtk不知道放到哪里无完成注册hci_register_dev。“--还与stp挂钩,这块先不跟进。
HCI socket通过hci_dev_list即可完成对tty驱动(也就是HCI设备驱动的)操作。
生成mtk_stp_bt.ko
编译命令:
./mk r k\mediatek\kernel\drivers\combo
蓝牙与STP之间
stp_chrdev_bt.c
生成
mtk_stp_bt.ko.
编译命令:
./mk r k\mediatek\kernel\drivers\combo
评论留言