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/
有兴趣一起讨论.