上一篇写了CarPlay有线开发中的一些依赖,相比有线连接,无线连接的开发工作可能会比较简单一些, 主要的开发工作有如下内容
无线CarPlay连接开发
- 蓝牙协议栈扩展UUID
- 配件端蓝牙CarPlay EIR扩展
- 配件端蓝牙iAP2 EIR扩展
- 苹果设备端蓝牙EIR扩展
- hostapd添加IE信息
- 数据格式
- 无线iAP2
- 配置transport信息
- 无线CarPlay相关Session ID
- 数据传输通道
蓝牙协议栈扩展UUID
蓝牙协议栈扩展UUID的作用主要是让苹果手机端能够在设置应用的CarPlay设备列表中能够搜索到该车机,进而以进行CarPlay设备的方式进行通信; 以及车机端能够通过扫描蓝牙设备SDP中的128bit UUID来识别该设备支持CarPlay. 这里主要需要增加两个UUID,分别如下:
配件端蓝牙CarPlay EIR扩展
128-bit UUID:0xEC884348CD4140A29727575D50BF1FD3
配件端蓝牙iAP2 EIR扩展
128-bit UUID:0xFFCACADEAFDECADEDEFACADE00000000
苹果设备端蓝牙EIR扩展
128-bit UUID:0x2D8D2466E14D451C88BC7301ABEA291A
android平台中,蓝牙协议栈路径在源码的system/bt
目录下,蓝牙协议栈中需要改动的主要有两部分,一个是增加上述配件端的两个EIR,其中iAP2 EIR中的UUID需要同时定义在SDP跟EIR的包中,且iAP2的EIR中本地名称需要与iAP2协议中塞进0x1d00报文中的名称定义一致; 另外一个是需要扩展解析SDP中设备信息,并对扩展对128 bit的UUID的解析,原生协议栈是不支持的,需要自己新增。
hostapd添加IE信息
IE信息在14.5版本之后已经废弃了,但是为了兼容之前的老版本,这里还是介绍一下,主要是作用是在Beacon,Probe reponse, Association response, Re-Association response帧中扩展IE信息
数据格式
IE信息的全结构定义如下:
基本格式未element id + length + OUI + sub-type + elements, 其中的elements可以看成一个元素集合,集合中的每个element有自己的格式定义如下:
element ID定义如下表:
Element ID | Name | Format | Description |
---|---|---|---|
0x00 | Flags | n:bits | Flags about the accessory: b0-b7, b8-b15, etc. See Table 3-11 (page47).Eachflagisabit.Bitnumberingstartsfromtheleftmost bitofthefirstbyteandusestheminimumnumberofbytesneeded toencodethebits. Forexample: Ifonlybit1isset,itwouldbe0x40. Ifbit1(0x40)andbit7(0x01)areset,itwouldbe0x41. Ifbit1(0x40),bit7(0x01),andbit10(0x0020)areset,itwouldbe 0x41,0x20. Ifonlybit10(0x0020),itwouldbe0x00,0x20. |
0x01 | Name | UTF-8 | Deprecated: Friendly name of the accessory.This should only be provided if the user configured a custom name or the firmware of the accessory has reason to believe it can provide a name that is better than the default name the client software will provide for it based on the model. Due to localization issues,it often better to only provide this element if the user has configured a name. |
0x02 | Manufacturer | UTF-8 | 厂商 |
0x03 | Model | UTF-8 | 型号 |
0x04 | OUI | 3 bytes | 0x00 0xA0 0x40 |
0x06 | BluetoothMAC | 6 bytes | 蓝牙地址 |
0x07 | Device ID | 6 bytes | 设备唯一ID |
0xDD | Vendor-Specific | n bytes | vendor-specific IE element |
flags又有三种有效的定义,分别是
- 0x0020 支持无线carplay
- 0x0002 支持2.4G网络
- 0x0001 支持5G 网络
所以整个vendor-specific IE的格式为
[Element ID] 0xDD
[length] 0xXX
[OUI] 0x00,0xA0,0x40,
[Sub-Type] 0x00
[flags] 0x00,0x2,0x00,0x23 //支持无线CarPlay, 支持2.4G, 支持5G
[Name] 0X01, 0xXX, UTF-8 Bytes
...
android系统中,这部分的添加可以在hostapd的**hostapd_bss_config
**这个结构体里面的vendor_elements中填充即可。
无线iAP2
无线中的iAP2链路的建立,物理层是通过蓝牙来进行的,手机与车机通过蓝牙建立握手与证书,热点信息的交换,然后手机连上车机热点建立CarPlay连接
配置transport信息
要告知手机端当前连接的车机支持CarPlay,需要在iAP2握手阶段在发送0x1d01报文到手机端时,配置BluetoothTransportComponent与WirelessCarPlayTransportCompoenent两个消息参数。参数组格式如下:
通过0x1d01报文配置该参数组给到手机,手机端才会在鉴权完成后,发送无线AP信息请求的相关Session ID
无线CarPlay相关Session ID
//旧协议
0x5702 : 手机发送到车机,车机收到该报文后,需要回复0x5703报文给到手机
0x5703:车机发送给手机,主要是把车机的AP信息发给手机,让手机来连热点
//新协议
0x4300 : 手机发送到车机,告知车机CarPlay会话是否可用
0x4301:车机发送给手机,告知车机的AP信息,MAC地址等,建立CarPlay连接
数据传输通道
无线的iAP2鉴权的物理传输通道主要是通过蓝牙的Rfcomm协议来完成,车机端监听UUID为0xfecacadeafdecadedefacade00000000
, Android系统的BluetoothAdapter类提供了如下函数来实现监听
public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) throws IOException {
throw new RuntimeException("Stub!");
}
建立连接后,可以通过BluetoothServerSocket获取数据的IO流来进行数据的收发