![](http://static.blog.csdn.net/images/category_icon.jpg)
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录:
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实现
|
|
五、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等协议
以及socket接口定义和实现。 | ||||||
|
|
9驱动层
预备知识:1.Linux网络体系结构
1.Linux网络体系结构由以下五个部分组成,以及对应的网络模型关系
1)系统调用接口 | 应用层 | berkeley库:socket的基本操作
通过系统调用内陷到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)没有这一层 |
| 物理传输 | 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 |
|
|
|
|