Chinaunix首页 | 论坛 | 博客
  • 博客访问: 688373
  • 博文数量: 207
  • 博客积分: 1743
  • 博客等级: 上尉
  • 技术积分: 2044
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-20 14:36
文章分类

全部博文(207)

文章存档

2016年(24)

2015年(10)

2014年(50)

2013年(45)

2012年(78)

分类: Android平台

2016-01-26 16:35:21



http://blog.csdn.net/honour2sword/article/details/39897931
目录:

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文件联系CC++部分的代码,包括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桥接接口(与Bluetoothserver 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);

}

然后调用到A2dpServiceconnect(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 FrameworkBluetooth 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接口(也就是各个profileserver层):

---里自称为server层的profile接口。

----实现了关于蓝牙java应用profile的API代码,包括opp、hfp、hdp、a2dp、pan,gatt等等,而且也有部分server性质的代码(不同的profile,有不同的设计)

由两部分组成:

packages/apps/Bluetooth

android原生提供的profilea2dp,gatt,hdp,hfp,hid,map,opp,pan,pbap

生成bluetooth.apk

\mediatek\packages\apps\bluetooth\profiles

 

mtk增加的profile

MtkBt.apk

进程名:com.mediatek.bluetooth

“如果删除,则连接不上,提示pareiconnet错误等信息。

因为很多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和各种profileBT 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 APIsBTprocess调用的标准接口(所有的厂家都是按照这种接口定义来编写自己的底层协议栈,并且你必须实现这些接口来让你的BT hardware功能运行正常。BT HAL的的头文件位于hardware/libhardware/include/hardware/bluetooth.hhardware/libhardware/include/hardware/bt_*.h文件中。

 

JNIsBluetoothA2dpInterface是一个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----实现(中间协议+核心协议)。

一个完整的蓝牙协议栈按其功能又可划分为四层:

核心协议层:

BBLMP)、

硬件实现

 

中间协议层:

L2CAPSDP线缆替换协议层(RFCOMM)、电话控制协议层(TCS-BIN)、

软件实现

 

选用协议层:

PPPTCPTPUDPOBEXIrMCWAPWAE):由系统或者第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.cconnect方法。

 

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那个作用类似,是串联frameworkblueZ的工具。

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不是这样,mtkcombo芯片,中间的数据传输还通过STPSerial Transport Protocol)模块。

kernel\net\bluetooth

核心协议和中间层协议实现。包括hci,hidrfcomm,sco,SDP等协议

核心协议层:

BBLMPLCAPSDP)、

 

中间协议层:

线缆替换协议层(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

应用层

socketnet/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,红外就是这种标准的驱动模型。

蓝牙就不完全是,蓝牙只有模拟ethip设备时候走这标准。

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)没有这一层

  1. 蓝牙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/目录下的代码交互数据的接口。

  mtkcombo芯片,中间的数据传输还通过STPSerial Transport Protocol)模块。

 

2.如何(谁)操作该tty设备?通过应用/system/bin/6620_launcher

\mediatek\external\combo_tool\src

比如注册tty设备到hci corelist里面。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

 

 

 

阅读(5952) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~