Android Usb的研究

USB为什么复杂,因为USB标准内容太多了.

Android上的USB外围设备.我见过指纹,鼠标,触摸屏,U盘.大部分人用USB充充电.USB的介绍网上已经很多了,我以移植一个USB触摸屏来说明我的理解.

Android上USB的API android.hardware.usb.UsbManager,函数也不多,就是不好用,一个涉及到权限,另外一个涉及到协议.

权限:

先解决表面上的问题,这和android权限机制有关系.

第一步:

在AndroidManifest.xml加入

 
  1. <uses-permission android:name="android.hardware.usb.host" />

  2. <uses-permission android:name="android.hardware.usb.accessory" />

第二步:

怎么找到我的设备呢?

 
  1. mManager = (UsbManager) c.getSystemService(Context.USB_SERVICE);

  2. HashMap<String, UsbDevice> list = mManager.getDeviceList();

  3. for (UsbDevice usb : list.values()) {

  4. int pid = usb.getProductId();

  5. int vid = usb.getVendorId();

  6. }

遍历list,打印出pid和vid号,看和你实际对应pid,vid号是不是一样呢?

如果你没看到usb设备呢?我想大部分人会遇到,有人会说你没把vid,pid号加入usbfilter.xml文件里.不要被误导,这只和热插拔设备弹出应用有关,系统检测热插拔,和getDeviceList无关,getDeviceList会获取所有usb设备.

参考这篇文章基本能解决,因为android很多版本都不完善.

http://blog.csdn.net/trbbadboy/article/details/8929673

第三步:

打开设备:

 
  1. mDeviceIntf = mDevice.getInterface(0);

  2. mDeviceConnect = mManager.openDevice(mDevice);

  3. 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的一个标准函数,这里面的参数就是上面所说的参数.

 
  1. * <p>

  2. * This method transfers data starting from index 0 in the buffer.

  3. * To specify a different offset, use

  4. * {@link #controlTransfer(int, int, int, int, byte[], int, int, int)}.

  5. * </p>

  6. *

  7. * @param requestType request type for this transaction

  8. * @param request request ID for this transaction

  9. * @param value value field for this transaction

  10. * @param index index field for this transaction

  11. * @param buffer buffer for data portion of transaction,

  12. * or null if no data needs to be sent or received

  13. * @param length the length of the data to send or receive

  14. * @param timeout in milliseconds

  15. * @return length of data transferred (or zero) for success,

  16. * or negative value for failure

  17. */

  18. public int controlTransfer(int requestType, int request, int value,

  19. int index, byte[] buffer, int length, int timeout) {

  20. return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);

  21. }

我们试着发送一下上面抓取的数据

 
  1. void test()

  2. {

  3. byte [] rcv = new byte[0x0202];

  4. int r = mDeviceConnect.controlTransfer(

  5. 0x80,

  6. 0x06,

  7. 0x3 << 8 | 0x2,

  8. 0x4 << 8 | 0x9,

  9. rcv,

  10. 0x0202,

  11. 1000);

  12.  
  13. ComFunc.log("is test log", rcv, 64);

  14. }

得到结果:

 
  1. /Timeline( 762): Timeline: Activity_windows_visible id: ActivityRecord{419df0c8 u0 com.ou.usbtp/com.ou.ui.DemoActivity

  2. t24} time:16355386

  3. I/MLog ( 4562): is test log{

  4. I/MLog ( 4562): 2c,03,49,00,6e,00,66,00,72,00,61,00,72,00,65,00,

  5. I/MLog ( 4562): 64,00,20,00,54,00,6f,00,75,00,63,00,68,00,20,00,

  6. I/MLog ( 4562): 53,00,63,00,72,00,65,00,65,00,6e,00,00,00,00,00,

  7. I/MLog ( 4562): 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,};

  8. V/RenderScript( 4562): Application requested CPU execution

和bushound抓取结果一样.
当然我们不会只做获取描述符简单的问题,我们还需要设计到配置信息和读取信息的功能.

和上面类似,只是换了命令类型,
这是我配置USB触摸屏使用到的配置信息片段,大家可以参考.

 
  1. Device Length Phase Data Description Cmd.Phase.Ofs(rep) Time

  2. ------ -------- ----- -------------------------------------------------- ---------------- ------------------ ------------

  3. 37.0 CTL 21 09 05 03 02 00 40 00 SET REPORT 1.1.0 10:08:02.852

  4. 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

  5. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 1.2.16

  6. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 1.2.32

  7. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 1.2.48

  8. 37.0 CTL a1 01 06 03 02 00 40 00 GET REPORT 2.1.0 10:08:02.872

  9. 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

  10. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 2.2.16

  11. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 2.2.32

  12. 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/

有兴趣一起讨论.

猜你喜欢

转载自blog.csdn.net/LoongEmbedded/article/details/81808731