Android USB OTG通信

USB相关概念:

简单来说,USB 是一个用于数据交换的总线(Bus)。发启(initiate)数据交换的一方称为主机 (host),另一方称为外设(peripheral),两者通过总线实现通信,由主机负责供电。一个 USB 系 统里只有一个主机,但可以有多个外设,外设的主要信息记录在描述符(descriptor)里。一个 外设就是一个单独的物理实体,但它却可能有多个逻辑上的设备功能(device function),比如 一个网络摄像头,除了有照相机,还可能有内置的麦克风,这种外接设备也被称为复合设备 (composite device)。

USB OTG:USB On-The-Go 通常缩写为 USB OTG,是 USB2.0 规格的补充标准。它可使 USB 设备,例如播放器或手机,从 USB 周边设备变为 USB 主机,与其他 USB 设备连接通信。在 正常情况下,这些支持 OTG 的 USB 设备和 USB 主机(如台式机或者手提电脑),仍然作为 USB 周边设备使用。
Android 平台下 USB 开发有以下两种模式:

USB Host Mode:

顾名思义,Android 设备作为主机,需要安卓设备支持 OTG 接头。常见应用场景诸如连接数 码相机、键盘、鼠标、游戏手柄等硬件。

USB Accessory Mode:

这种模式下 Android 设备承担外设的角色。应用场景诸如连接机器人控制器、音响、医疗器 材等,当然前提是这些设备支持与Android设备连接并且遵守Android accessory communication protocol。这种模式可以让不具有 host 能力的 Android 设备与其他硬件交互。


image.png

Android 开放配件协议(AOA)

Android 开放配件 (AOA) 支持功能可让外部 USB 硬件(Android USB 配件)与处于配件模 式下的 Android 设备进行交互。当某台 Android 设备处于配件模式时,所连接的配件会充 当 USB 主机(为总线供电并列举设备),而 Android 设备则充当 USB 配件。

1、协议 API USB Host Mode:

UsbManager:USB 设备管理类,提供获取 USB 设备相关 API。
UsbDevice:USB 设备实体类,定义设备的相关属性。
UsbInterface:表示 USB 设备的接口,它定义了设备的一组功能。设备可以具有一个或多个进 行通信的接口。
UsbEndpoint:表示接口端点,作为接口的通信通道。接口可以有一个或多个端点,并且通常 包括用于与设备进行双向通信的输入和输出端点。 UsbDeviceConnection:表示与设备的连接,通过端点传输数据。此类支持同步和异步两种方 式传输数据。
UsbRequest:通过 UsbDeviceConnection 与设备通信的异步请求。 UsbConstants:定义协议相关常量。
USB Accessory Mode: UsbManager:同上。
UsbAccessory:表示 USB 配件设备,包含相关的属性和 API。

2、协议使用

Host 端程序实现过程:
1、定义为 Host:在 AndroidManifest.xml 文件中添加如下代码 <uses-feature android:name=“android.hardware.usb.host"/>
2、监听广播:监听 USB 插入与拔出的广播。 UsbManager.ACTION_USB_DEVICE_ATTACHED UsbManager.ACTION_USB_DEVICE_DETACHED
3、获取设备:通过 UsbManager 获取连接的 USB 设备(注意权限申请) UsbManage 中 getDeviceList()方法
4、打开设备:将设备打开,获取连接(UsbConnection)。
通过 UsbManage 中 openDevice(UsbDevice device)方法获取 UsbConnection
5、让 USB 设备启动配件模式:通过 AOA 协议中定义的相关控制指令。
通过 UsbConnection 中 controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)方法发送指令。

5.1 发送 51 控制请求(“获取协议”)以确定设备是否支持 Android 配件协议。如果设备 支持协议,则返回一个非零数字,代表所支持的协议版本。该控制请求为端点 0 上的请求, 具有以下特征:


image.png

5.2 如果设备返回所支持的协议版本,则向设备发送含标识字符串信息的控制请求。该信息 让设备可以确定适合配件的应用(如果没有适合配件的应用,则向用户呈现一个网址)。该 控制请求为端点 0 上的请求(适用每个字符串 ID),具有以下特征:


image.png

支持以下字符串 ID,并且每个字符串的最大值为 256 个字节(必须以零结束,以 \0 结尾)。 index 值范围以及含义如下:


image.png

5.3 发送控制请求,要求设备以配件模式启动。该控制请求为端点 0 上的请求,具有以下特 征:

image.png

完成这些步骤后,主机应等待所连接的 USB 设备在配件模式下将其自身重新接入总线,然 后重新枚举所连接的设备。该算法通过检查供应商 ID 和产品 ID 来确定设备是否支持配件 模式,如果设备成功切换到配件模式,那么供应商 ID 和产品 ID 应该是正确的(例如,与 Google 的供应商 ID 和产品 ID 而不是设备制造商的 ID 相对应)。如果 ID 正确,配件 则进而与设备建立通信。当设备成功以配件模式启动后 ProductId 会成为 0x2D00 或 0x2D01。
• 0x2D00 有一个接口,该接口有两个批量端点,用于输入和输出通信。
• 0x2D01 有两个接口,每个接口有两个批量端点,用于输入和输出通信。第一个接口处理标 准通信,第二个接口则处理 ADB 通信。要使用接口,请找到第一个批量输入和输出端点, 使用 SET_CONFIGURATION (0x09) 设备请求将设备配置的值设为 1,然后使用端点进行 通信。

6、建立通信通道:获取输入和输出的 UsbEndPoint,使用 UsbConnection 的 bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)方法进行数据输入与输 出。bulkTransfer 方法用于读、写大量数据,需要使用 type 为 UsbConstants.USB_ENDPOINT_XFER_BULK 的 UsbEndPoint。

image.png

Host 端实现过程:

1、定义为 Accessory:在 AndroidManifest.xml 文件中添加如下代码

<uses-feature android:name="android.hardware.usb.accessory"/>
 ......
<activity android:name=".activity.MainActivity"> 
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"/>
</intent-filter> 
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter"/> 
</activity>
......

2、监听广播:监听配件插入与拔出的广播。 UsbManager. ACTION_USB_ACCESSORY_ATTACHED UsbManager. ACTION_USB_ACCESSORY_DETACHED
3、获取设备:通过 UsbManager 获取连接的配件设备(注意权限申请) UsbManage 中 getAccessoryList()方法。
4、打开设备:将配件打开,获取连接。
通过 UsbManage 中 openAccessory(UsbAccessory accessory)方法获取通信的文件描述符 ParcelFileDescriptor
5、建立通信通道:在不同线程中利用上述文件符创建输入、输入 IO 流用于读、写数据。

结束语

• AOA协议实现可以解决两台手机之间的消息通信。
• AOA 协议不适合大数据传输。虽然 USB Host、USB Accessory 模式支持多 线程并发读写,因为在 USB Host 模式一个 USB 下只有一个输入端点、一个输出端点,而 USB Accessory 模式下一个配件设备只有一个 ParcelFileDescriptor,无法使用多通道进行文 件传输,单通道下使用多线程并发传输和接收,会出现数据混乱而无法识别,若是单线程 传输文件则效率低下。


image.png

参考:
https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html

https://developer.android.com/guide/topics/connectivity/usb/index.html

https://source.android.com/devices/accessories/aoa

https://www.jianshu.com/p/7ec7539737ef

https://developer.android.com/guide/topics/connectivity/usb/accessory

https://developer.android.com/guide/topics/connectivity/usb/host

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容