Android USB OTG通信

USB相關(guān)概念:

簡(jiǎn)單來(lái)說(shuō),USB 是一個(gè)用于數(shù)據(jù)交換的總線(Bus)。發(fā)啟(initiate)數(shù)據(jù)交換的一方稱為主機(jī) (host),另一方稱為外設(shè)(peripheral),兩者通過(guò)總線實(shí)現(xiàn)通信,由主機(jī)負(fù)責(zé)供電。一個(gè) USB 系 統(tǒng)里只有一個(gè)主機(jī),但可以有多個(gè)外設(shè),外設(shè)的主要信息記錄在描述符(descriptor)里。一個(gè) 外設(shè)就是一個(gè)單獨(dú)的物理實(shí)體,但它卻可能有多個(gè)邏輯上的設(shè)備功能(device function),比如 一個(gè)網(wǎng)絡(luò)攝像頭,除了有照相機(jī),還可能有內(nèi)置的麥克風(fēng),這種外接設(shè)備也被稱為復(fù)合設(shè)備 (composite device)。

USB OTG:USB On-The-Go 通??s寫為 USB OTG,是 USB2.0 規(guī)格的補(bǔ)充標(biāo)準(zhǔn)。它可使 USB 設(shè)備,例如播放器或手機(jī),從 USB 周邊設(shè)備變?yōu)?USB 主機(jī),與其他 USB 設(shè)備連接通信。在 正常情況下,這些支持 OTG 的 USB 設(shè)備和 USB 主機(jī)(如臺(tái)式機(jī)或者手提電腦),仍然作為 USB 周邊設(shè)備使用。
Android 平臺(tái)下 USB 開(kāi)發(fā)有以下兩種模式:

USB Host Mode:

顧名思義,Android 設(shè)備作為主機(jī),需要安卓設(shè)備支持 OTG 接頭。常見(jiàn)應(yīng)用場(chǎng)景諸如連接數(shù) 碼相機(jī)、鍵盤、鼠標(biāo)、游戲手柄等硬件。

USB Accessory Mode:

這種模式下 Android 設(shè)備承擔(dān)外設(shè)的角色。應(yīng)用場(chǎng)景諸如連接機(jī)器人控制器、音響、醫(yī)療器 材等,當(dāng)然前提是這些設(shè)備支持與Android設(shè)備連接并且遵守Android accessory communication protocol。這種模式可以讓不具有 host 能力的 Android 設(shè)備與其他硬件交互。


image.png

Android 開(kāi)放配件協(xié)議(AOA)

Android 開(kāi)放配件 (AOA) 支持功能可讓外部 USB 硬件(Android USB 配件)與處于配件模 式下的 Android 設(shè)備進(jìn)行交互。當(dāng)某臺(tái) Android 設(shè)備處于配件模式時(shí),所連接的配件會(huì)充 當(dāng) USB 主機(jī)(為總線供電并列舉設(shè)備),而 Android 設(shè)備則充當(dāng) USB 配件。

1、協(xié)議 API USB Host Mode:

UsbManager:USB 設(shè)備管理類,提供獲取 USB 設(shè)備相關(guān) API。
UsbDevice:USB 設(shè)備實(shí)體類,定義設(shè)備的相關(guān)屬性。
UsbInterface:表示 USB 設(shè)備的接口,它定義了設(shè)備的一組功能。設(shè)備可以具有一個(gè)或多個(gè)進(jìn) 行通信的接口。
UsbEndpoint:表示接口端點(diǎn),作為接口的通信通道。接口可以有一個(gè)或多個(gè)端點(diǎn),并且通常 包括用于與設(shè)備進(jìn)行雙向通信的輸入和輸出端點(diǎn)。 UsbDeviceConnection:表示與設(shè)備的連接,通過(guò)端點(diǎn)傳輸數(shù)據(jù)。此類支持同步和異步兩種方 式傳輸數(shù)據(jù)。
UsbRequest:通過(guò) UsbDeviceConnection 與設(shè)備通信的異步請(qǐng)求。 UsbConstants:定義協(xié)議相關(guān)常量。
USB Accessory Mode: UsbManager:同上。
UsbAccessory:表示 USB 配件設(shè)備,包含相關(guān)的屬性和 API。

2、協(xié)議使用

Host 端程序?qū)崿F(xiàn)過(guò)程:
1、定義為 Host:在 AndroidManifest.xml 文件中添加如下代碼 <uses-feature android:name=“android.hardware.usb.host"/>
2、監(jiān)聽(tīng)廣播:監(jiān)聽(tīng) USB 插入與拔出的廣播。 UsbManager.ACTION_USB_DEVICE_ATTACHED UsbManager.ACTION_USB_DEVICE_DETACHED
3、獲取設(shè)備:通過(guò) UsbManager 獲取連接的 USB 設(shè)備(注意權(quán)限申請(qǐng)) UsbManage 中 getDeviceList()方法
4、打開(kāi)設(shè)備:將設(shè)備打開(kāi),獲取連接(UsbConnection)。
通過(guò) UsbManage 中 openDevice(UsbDevice device)方法獲取 UsbConnection
5、讓 USB 設(shè)備啟動(dòng)配件模式:通過(guò) AOA 協(xié)議中定義的相關(guān)控制指令。
通過(guò) UsbConnection 中 controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)方法發(fā)送指令。

5.1 發(fā)送 51 控制請(qǐng)求(“獲取協(xié)議”)以確定設(shè)備是否支持 Android 配件協(xié)議。如果設(shè)備 支持協(xié)議,則返回一個(gè)非零數(shù)字,代表所支持的協(xié)議版本。該控制請(qǐng)求為端點(diǎn) 0 上的請(qǐng)求, 具有以下特征:


image.png

5.2 如果設(shè)備返回所支持的協(xié)議版本,則向設(shè)備發(fā)送含標(biāo)識(shí)字符串信息的控制請(qǐng)求。該信息 讓設(shè)備可以確定適合配件的應(yīng)用(如果沒(méi)有適合配件的應(yīng)用,則向用戶呈現(xiàn)一個(gè)網(wǎng)址)。該 控制請(qǐng)求為端點(diǎn) 0 上的請(qǐng)求(適用每個(gè)字符串 ID),具有以下特征:


image.png

支持以下字符串 ID,并且每個(gè)字符串的最大值為 256 個(gè)字節(jié)(必須以零結(jié)束,以 \0 結(jié)尾)。 index 值范圍以及含義如下:


image.png

5.3 發(fā)送控制請(qǐng)求,要求設(shè)備以配件模式啟動(dòng)。該控制請(qǐng)求為端點(diǎn) 0 上的請(qǐng)求,具有以下特 征:

image.png

完成這些步驟后,主機(jī)應(yīng)等待所連接的 USB 設(shè)備在配件模式下將其自身重新接入總線,然 后重新枚舉所連接的設(shè)備。該算法通過(guò)檢查供應(yīng)商 ID 和產(chǎn)品 ID 來(lái)確定設(shè)備是否支持配件 模式,如果設(shè)備成功切換到配件模式,那么供應(yīng)商 ID 和產(chǎn)品 ID 應(yīng)該是正確的(例如,與 Google 的供應(yīng)商 ID 和產(chǎn)品 ID 而不是設(shè)備制造商的 ID 相對(duì)應(yīng))。如果 ID 正確,配件 則進(jìn)而與設(shè)備建立通信。當(dāng)設(shè)備成功以配件模式啟動(dòng)后 ProductId 會(huì)成為 0x2D00 或 0x2D01。
? 0x2D00 有一個(gè)接口,該接口有兩個(gè)批量端點(diǎn),用于輸入和輸出通信。
? 0x2D01 有兩個(gè)接口,每個(gè)接口有兩個(gè)批量端點(diǎn),用于輸入和輸出通信。第一個(gè)接口處理標(biāo) 準(zhǔn)通信,第二個(gè)接口則處理 ADB 通信。要使用接口,請(qǐng)找到第一個(gè)批量輸入和輸出端點(diǎn), 使用 SET_CONFIGURATION (0x09) 設(shè)備請(qǐng)求將設(shè)備配置的值設(shè)為 1,然后使用端點(diǎn)進(jìn)行 通信。

6、建立通信通道:獲取輸入和輸出的 UsbEndPoint,使用 UsbConnection 的 bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)方法進(jìn)行數(shù)據(jù)輸入與輸 出。bulkTransfer 方法用于讀、寫大量數(shù)據(jù),需要使用 type 為 UsbConstants.USB_ENDPOINT_XFER_BULK 的 UsbEndPoint。

image.png

Host 端實(shí)現(xiàn)過(guò)程:

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、監(jiān)聽(tīng)廣播:監(jiān)聽(tīng)配件插入與拔出的廣播。 UsbManager. ACTION_USB_ACCESSORY_ATTACHED UsbManager. ACTION_USB_ACCESSORY_DETACHED
3、獲取設(shè)備:通過(guò) UsbManager 獲取連接的配件設(shè)備(注意權(quán)限申請(qǐng)) UsbManage 中 getAccessoryList()方法。
4、打開(kāi)設(shè)備:將配件打開(kāi),獲取連接。
通過(guò) UsbManage 中 openAccessory(UsbAccessory accessory)方法獲取通信的文件描述符 ParcelFileDescriptor
5、建立通信通道:在不同線程中利用上述文件符創(chuàng)建輸入、輸入 IO 流用于讀、寫數(shù)據(jù)。

結(jié)束語(yǔ)

? AOA協(xié)議實(shí)現(xiàn)可以解決兩臺(tái)手機(jī)之間的消息通信。
? AOA 協(xié)議不適合大數(shù)據(jù)傳輸。雖然 USB Host、USB Accessory 模式支持多 線程并發(fā)讀寫,因?yàn)樵?USB Host 模式一個(gè) USB 下只有一個(gè)輸入端點(diǎn)、一個(gè)輸出端點(diǎn),而 USB Accessory 模式下一個(gè)配件設(shè)備只有一個(gè) ParcelFileDescriptor,無(wú)法使用多通道進(jìn)行文 件傳輸,單通道下使用多線程并發(fā)傳輸和接收,會(huì)出現(xiàn)數(shù)據(jù)混亂而無(wú)法識(shí)別,若是單線程 傳輸文件則效率低下。


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

http://www.itdecent.cn/p/7ec7539737ef

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容