基本介绍
低功耗。速率:3Mbps(EDR, Extended Data Rate)(除EDR外,令外模式是BR(Basic Rate),AMP(Alternate MAC/PHY),速率BR<EDR<AMP);距离:100m以内(class1
官网:
http://developer.bluetooth.org
规范下载地址:
https://www.bluetooth.org/en-us/specification/adopted-specifications
技术介绍:
http://developer.bluetooth.org/TechnologyOverview/Pages/Technology-Overview.aspx
拓扑/分层
拓扑
一个蓝牙设备要与其它蓝牙设备通信,它必须和其它设备形成piconet(组)。一个piconent有且只有一个master,可有多个slave。一个piconet中的slave设备可以做其它piconet中的master,一个设备也可以加到多个piconet中都做slave设备(时分(time divided multiplexing)方式)。
分层
|-----------------------------------------------------------------------------------------| |A2DP, AVRCP, HID, |SPP, OPP, FTP |-------------|HFP, |------------------------| |SDP, HDP, FTP... |PBAP... |-------------|HSP... |------------------------|Profile/Protocol | |----------------------------------------------------------------------| | |RFCOMM |--------------------------------------------------|RFCOMM |-----------------------------------------------------------------------------------------| | L2CAP |-------------|-----------|------------------------|L2CAP |-----------------------------------------------------------------------------------------| | ACL-U |ACL-C |(e)Sco |------------------------|Logical Link | ACL |(e)Sco |------------------------|Logical Transport |-----------------------------------------------------------------------------------------| |Basic/Adapted |Inquiry Scan |Page Scan |Physical Link |Basic/Adapted |Inquiry Scan |Page Scan |Physical Channel |-----------------------------------------------------------------------------------------|
物理层
每个piconet中只有一个物理频道(Physical Channel),不同物理频道(意味着不同piconet)有不同时钟和调频序列(HFSS(frequency hopping spread spectrum)。ClassicBT中从2400MHz有79个宽为2MHz的小频道,某个时间内piconet的设备都在某个小频道内工作,在某个时点同时切换到另一个小频道。调频序列是指从一个小频道切换到另一个小频道时的选择中心频率的算法。HFSS的主要目的是避免干扰和安全考虑)。
如果要通信,piconet中每个master/slave对形成一个物理链接(Physical Link)。slave之间不能直接通信。个人理解是,从物理信号上说,piconet内一个设备发的包,其他设备都能收到,但是会根据其中的目标地址把不是给它的包丢弃。
物理层有四种类型物理频道(也就意味着同样的四种物理链接):Basic Piconet Channel,Adapted Piconet Channel,Inquiry Scan Channel,Page Scan Channel。Inquiry Scan用于扫描周围设备存在状况和设备信息,Page Scan用于扫描可连接设备,Basic/Adapted Piconet Channel用于支持其它目的的通信。piconet中的物理链接应该是按照时分方式在上述类型中切换。
链路层
L2CAP
RFCOMM
HCI
Host Controller Interface,主机和控制器之间的接口。在Core Spec的下面的章节中定义。
Volumn 2, Core System Package [Controller volumn] =>Part E, Host Controller Interface Functional Specification
BlueZ版
接口中有命令和事件。命令以OGF(OpCode Group Field, 6 bit)和OCF(OpCode Command Field, 10 bit)来区分。事件以Event Code来区分。各命令/事件的参数/格式在Spec中有定义。上述Field/Code在kernel/include/net/bluetooth/hci.h中定义。如:
#define HCI_OP_INQUIRY 0x0401 ...... #define HCI_EV_INQUIRY_COMPLETE 0x01 ......
比较新版的安卓代码中,一般不在用户空间中直接发送HCI命令或接收HCI事件,而是在bluez(具体是external/bluetooth/bluez/plugins/mgmtops.c)中往用socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)建出来的socket发管理命令,在kernel/net/bluetooth/mgmt.c中处理这些管理命令时,再调用hci_send_cmd()来发送HCI命令。同样,在kernel/net/bluetooth/hci_event.c接受到HCI事件时,它也不是直接往bluez上报,而是调kernel/net/bluetooth/mgmt.c的相关函数(如mgmt_inquiry_complete_evt())进行处理,在这些处理中可能往bluez上报管理事件(如MGMT_EV_DISCOVERING)。这些管理命令和事件在kernel/include/net/bluetooth/mgmt.h中定义。如:
#define MGMT_OP_START_DISCOVERY 0x001B ...... #define MGMT_EV_CMD_COMPLETE 0x0001 ......
在高通msm8960/fusion3/msm8974平台上,HCI命令最终通过SMD发到WCNSS,也是通过SMD从WCNSS接收HCI事件。
通过SMD发送HCI命令接收HCI事件调用过程
//enable BT BluetoothEnabler.onCheckedChanged()//in packages/apps/Settings
|LocalBluetoothAdapter.setBluetoothEnabled()
|BluetoothAdapter.enable()//in frameworks/base
|BluetoothService.enable()
|BluetoothAdapterStateMachine.prepareBluetooth()
|BluetoothService.enableNative()
|bt_enable()//in system/bluetooth/bluedroid
|property_set("ctl.start", hciattach_serv)//start hciattach service
|//run "/system/etc/init.qcom.bt.sh"
|//run "/system/bin/hci_qcomm_init"
|//run "echo 1 > /sys/module/hci_smd/parameters/hcismd_set"
|hcismd_set_enable()//in kernel
|hci_smd_register_smd()
|hsmd->hdev = hdev;
|hdev->open = hci_smd_open;
|hdev->send = hci_smd_send_frame;
|tasklet_init(&hsmd->rx_task, hci_smd_rx, (unsigned long) hsmd);
|smd_named_open_on_edge()//EVENT_CHANNEL, hci_smd_notify_event()
|smd_named_open_on_edge()//DATA_CHANNEL, hci_smd_notify_data()
-
//send HCI cmd hci_send_cmd()
|skb = bt_skb_alloc(len, GFP_ATOMIC); |skb_queue_tail(&hdev->cmd_q, skb); |tasklet_schedule(&hdev->cmd_task);//start hci_cmd_task()
hci_cmd_task()
|skb = skb_dequeue(&hdev->cmd_q); |hci_send_frame(skb); |hci_smd_send_frame() |smd_write(hs.event_channel, skb->data, skb->len);
//receive HCI event hci_smd_notify_event()
|len = smd_read_avail(hsmd->event_channel); |tasklet_hi_schedule(&hs.rx_task);//start hci_smd_rx()
hci_smd_rx()
|hci_smd_recv_event() |len = smd_read_avail(hsmd->event_channel); |//while len > 0 |rc = smd_read(hsmd->event_channel, skb_put(skb, len), len); |bt_cb(skb)->pkt_type = HCI_EVENT_PKT; |hci_recv_frame(skb) |skb_queue_tail(&hdev->rx_q, skb); |tasklet_schedule(&hdev->rx_task);//start hci_rx_task() |len = smd_read_avail(hsmd->event_channel);
hci_rx_task()
|//while(skb = skb_dequeue(&hdev->rx_q)) |hci_event_packet(hdev, skb); |//process each type of HCI event
BT扫描设备代码调用过程
//send command
LocalBluetoothAdapter.startScanning()
|BluetoothAdapter.startDiscovery()
|BluetoothService.startDiscovery()
|startDiscoveryNative()
|adapter_start_discovery()//adapter.c in bluez
|start_discovery()
|mgmt_start_discovery()//mgmtops.c in bluez
|write(mgmt_sock)//MGMT_OP_START_DISCOVERY
|syscall_write()//read_write.c in kernel
|sock_aio_write()//socket.c in kernel
|hci_sock_sendmsg()
|mgmt_control()//mgmt.c in kernel
|start_discovery()
|hci_send_cmd(HCI_OP_INQUIRY)//0x0401
//result
hci_event_packet()//hci_event.c in kernel
|hci_inquiry_complete_evt()
|hci_inquiry_result_evt()
|mgmt_device_found()
|mgmt_event(MGMT_EV_DEVICE_FOUND)
|mgmt_event()//mgmtops.c in bluez
|mgmt_device_found()
|btd_event_device_found()
|adapter_update_found_devices()
|adapter_emit_device_found()
|emit_device_found()
|event_filter()//Jni of BluetoothEventLoop
|BluetoothEventLoop.onDeviceFound()
|addDevice()
|//send Intent with action = BluetoothDevice.ACTION_FOUND
|BluetoothEventManager.DeviceFoundHandler.onReceive()
|CachedBluetoothDeviceManager.addDevice()
|dispatchDeviceAdded()
|BluetoothSettings.onDeviceAdded()
Bluedroid版
安全
GAP/SDP
Profile/Protocol
A2DP
依赖关系。
A2DP = Advanced Audio Distribution Profile => GAVDP = Generic Audio/Video Distribution Profile ==> AVDTP = Audio/Video Distribution Transport Protocol
A2DP
AVRCP
HFP
HID
HSP
PBAP
代码相关
用bluez的较新安卓版本中主要相关代码分布如下(从上到下)。
packages/apps/下的Bluetooth_msm(高通Fusion3平台)或Bluetooth(其它平台) packages/apps/Settings/src/com/android/settings/下的bluetooth_msm(高通Fusion3平台)或bluetooth(其它平台) packages/apps/Phone/src/com/android/phone/Bluetooth* frameworks/base/btobex frameworks/base/core/java/android/bluetooth frameworks/base/core/java/android/server frameworks/base/core/jni external/bluetooth/bluez system/bluetooth vendor/qcom/proprietary/bt kernel/net/bluetooth kernel/drivers/bluetooth
用bluedroid的版本的分布如下。
packages/apps/Bluetooth packages/apps/Settings/src/com/android/settings/bluetooth packages/apps/Phone/src/com/android/phone/Bluetooth* frameworks/base/core/java/android/bluetooth frameworks/base/core/java/android/server/BluetoothManagerService.java external/bluetooth/bluedroid vendor/qcom/proprietary/bt