Android Usb的研究

USB爲什麼複雜,因爲USB標準內容太多了.

Android上的USB外圍設備.我見過指紋,鼠標,觸摸屏,U盤.大部分人用USB充充電.USB的介紹網上已經很多了,我以移植一個USB觸摸屏來說明我的理解.

Android上USB的API android.hardware.usb.UsbManager,函數也不多,就是不好用,一個涉及到權限,另外一個涉及到協議.

權限:

先解決表面上的問題,這和android權限機制有關係.

第一步:

在AndroidManifest.xml加入

 <uses-permission android:name="android.hardware.usb.host" />
 <uses-permission android:name="android.hardware.usb.accessory" />
第二步:

怎麼找到我的設備呢?

mManager = (UsbManager) c.getSystemService(Context.USB_SERVICE);		
HashMap<String, UsbDevice> list = mManager.getDeviceList();
for (UsbDevice usb : list.values()) {
    int pid = usb.getProductId();
    int vid = usb.getVendorId();
}
遍歷list,打印出pid和vid號,看和你實際對應pid,vid號是不是一樣呢?

如果你沒看到usb設備呢?我想大部分人會遇到,有人會說你沒把vid,pid號加入usbfilter.xml文件裏.不要被誤導,這隻和熱插拔設備彈出應用有關,系統檢測熱插拔,和getDeviceList無關,getDeviceList會獲取所有usb設備.

參考這篇文章基本能解決,因爲android很多版本都不完善.

http://blog.csdn.net/trbbadboy/article/details/8929673
第三步:

打開設備:

mDeviceIntf = mDevice.getInterface(0);
mDeviceConnect = mManager.openDevice(mDevice);
mDeviceConnect.claimInterface(mDeviceIntf, true);

初步完成.

第四步(可選):

google這點做的不厚道,什麼東西都要求權限,上個廁所都得申請,雖然可以記住用戶選擇,可別忘了usb是熱插拔設備,你拔完之後,從新插入又是一個新設備,又得申請權限,而且申請過程中遇到卡死的情況.怎麼避免requestPermission()帶來的提示呢?

答案在這裏,修改所有的申請都爲通過.

frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java
這是得修改系統源碼.

協議

協議是複雜的問題,controlTransfer參數搞不懂,什麼意思?所以得參考usb協議,不能自己瞎想.

一個命令格式:bmRequestType + bRequest + wValue + wIndex + wLength ,總共8個字節

當然命令+=數據

可以這麼簡單理解.

bmRequest代表方向,主機->從設備或者從設備到主機

bRequest 命令,參考表2

wValue 參數1,得仔細看協議標準,太多了

wIndex 參數2,得仔細看協議標準,太多了

wLength:接收或者發送數據的大小,不包括命令本身(8字節)

data;數據,根據實際情況

命令格式表9-2

命令表9-4


例子:

我拿一幀數據舉個例子,我用BusHound抓取獲取描述符的命令,IN是接收到的數據

命令格式:81 06 02 03 09 04 02 02

bmRequestType = 0x80; 從設備到主機

bRequest = 0x06; 參考表9-4,GET_DESCRIPTOR

wValue = 0x0302;參數1,高位代表類型(String類型),低位代表索引值

wIndex = 0x0409;參數2

wLength = 0x0202;接收長度0x0202字節

手冊裏抓出來的說明

那在android上怎麼用呢?這是UsbDeviceConnection的一個標準函數,這裏面的參數就是上面所說的參數.

* <p>
     * This method transfers data starting from index 0 in the buffer.
     * To specify a different offset, use
     * {@link #controlTransfer(int, int, int, int, byte[], int, int, int)}.
     * </p>
     *
     * @param requestType request type for this transaction
     * @param request request ID for this transaction
     * @param value value field for this transaction
     * @param index index field for this transaction
     * @param buffer buffer for data portion of transaction,
     * or null if no data needs to be sent or received
     * @param length the length of the data to send or receive
     * @param timeout in milliseconds
     * @return length of data transferred (or zero) for success,
     * or negative value for failure
     */
    public int controlTransfer(int requestType, int request, int value,
            int index, byte[] buffer, int length, int timeout) {
        return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);
    }
我們試着發送一下上面抓取的數據

void test() 
{
    byte [] rcv = new byte[0x0202];
    int r = mDeviceConnect.controlTransfer(
    0x80,
    0x06,
    0x3 << 8 | 0x2,
    0x4 << 8 | 0x9,
    rcv,
    0x0202,
    1000);

    ComFunc.log("is test log", rcv, 64);
}
得到結果:

/Timeline(  762): Timeline: Activity_windows_visible id: ActivityRecord{419df0c8 u0 com.ou.usbtp/com.ou.ui.DemoActivity
 t24} time:16355386
I/MLog    ( 4562): is test log{
I/MLog    ( 4562): 2c,03,49,00,6e,00,66,00,72,00,61,00,72,00,65,00,
I/MLog    ( 4562): 64,00,20,00,54,00,6f,00,75,00,63,00,68,00,20,00,
I/MLog    ( 4562): 53,00,63,00,72,00,65,00,65,00,6e,00,00,00,00,00,
I/MLog    ( 4562): 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,};
V/RenderScript( 4562): Application requested CPU execution
和bushound抓取結果一樣.
當然我們不會只做獲取描述符簡單的問題,我們還需要設計到配置信息和讀取信息的功能.

和上面類似,只是換了命令類型,
這是我配置USB觸摸屏使用到的配置信息片段,大家可以參考.

Device  Length    Phase  Data                                                Description       Cmd.Phase.Ofs(rep)  Time        
------  --------  -----  --------------------------------------------------  ----------------  ------------------  ------------
  37.0            CTL    21 09 05 03  02 00 40 00                            SET REPORT               1.1.0        10:08:02.852  
  37.0        64  OUT    05 03 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         1.2.0        10:08:02.852  
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         1.2.16                     
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         1.2.32                     
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         1.2.48                     
  37.0            CTL    a1 01 06 03  02 00 40 00                            GET REPORT               2.1.0        10:08:02.872  
  37.0        64  IN     06 03 00 00  fc 00 00 80  00 00 00 00  00 00 00 00  ................         2.2.0        10:08:02.872  
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         2.2.16                     
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         2.2.32                     
                         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................         2.2.48                    

另外一些相關涉及的方面

android usb-touchscreen驅動:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/input/touchscreen/usbtouchscreen.c?h=v4.12-rc4
usb 2.0協議標準(英文):

http://www.usb.org/developers/docs/usb20_docs/
有興趣一起討論.




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章