最近有个项目是关于Android应用与HID通过使用Usb Host模式通信。由于以前没做过Usb方面的开发,而且看见网上在这方面的资料也很少,所以就发一篇博文和大家共享经验。
回归正题,在Android Usb Host 开发中,对于发现设备、如何连接设备等等的都在官方API中说的清清楚楚了,我也不再详述了,反而在与HID通讯传输数据就重点说一下,想要正确的与HID进行通讯并且传输数据,就必须要了解Usb协议,弄清楚设备的相关参数,比如USB描述符,这个是必须的,不然就无法做任何事情了,这也是我血一般的教训。
在官方API中,它分别提供了有关数据传输的方法如下:
bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
除了以上两个方法可以进行数据传输以外,它还提供了一个UsbRequest类。
在与HID进行数据传输的时候,就要用到控制传输或中断传输了。对于controlTransfer这个方法,我想它里面的参数就难倒了很多人,在这里我就简略的说一下,我是以我自己的demo为例子(注意:我所说的例子是与HID通信的,如果不是HID设备的话,就要注意了),希望能给各位一个参考。
int requestType:确定数据流的方向、请求类型以及接收端;由于是与HID通信,所以它只能是00100001和100100001,再把它转为16进制(别告诉我不会16进制)填上去就可以了。对于这个参数,比特位7是指数据传输的方向:从主机到设备(OUT)为0,从设备到主机(IN)为1;比特位6到5是指请求类型:USB标准请求为00,USB类请求为01,厂商的自定义请求为10;比特位4到0是指接收端:指向设备(00000)、专属接口(00001)、端点(00010)、设备中的其它元件(00011)。
int request:这个参数是对应的请求号。在我的demo中,使用到的请求是Set Report(因为在我的demo中需要发送报表命令请求数据,所以才用Set Report;不同情况要不同请求),其对应的值就是0x09(查一下就知道了)了。
int value:可将请求专属星系传递给设备,有两个字节。对应于Set Preport,高字节是报告类型(02为输出,03为特征),低字节是报告ID(默认为0)。
int index:可将请求专属星系传递给设备,有两个字节。典型的应用是传递索引或者诸如接口或端点号的偏移量(这些需要查询自己的设备信息了,我这里的HID的接口索引值为0)。
主要最难搞的前四个参数都说了,我想后面的那些参数不用了吧,一看就知道它们是什么意思了。好了,现在说说我的情况吧,在我的demo中,我是使用了控制传输(controlTransfer)发送数据的,而接收数据则使用了中断传输(因为设备中有一个IN中断端点),主要代码如下:
//发送数据命令
sendCommand(connection, 0xF1);
int maxPacketSize = endpoint.getMaxPacketSize();
ByteBuffer bBuffer = ByteBuffer.allocate(maxPacketSize);
//使用中断传输接收数据
UsbRequest request = new UsbRequest();
//初始化请求,endpoint为IN中断端点
request.initialize(connection, endpoint);
//请求队列接收数据
request.queue(bBuffer, maxPacketSize);
if (connection.requestWait() == request) {
byte[] b = bBuffer.array();
...
以上代码需要开启一个线程
以下是使用控制传输的方法,在上面代码中调用:
private void sendCommand(UsbDeviceConnection connection, int command) {
byte[] buf = new byte[1];
buf[0] = (byte) command;
connection.controlTransfer(0x21, 0x09, 0x200, 0, buf, buf.length, 0);
}
加一些小备注:
我的是外置信息采集一类的usb设备,鼠标是没问题的。。。使用官方的方法,你要注意在手机配置一些东西也就是权限! 将android.hardware.usb.host.xml文件放到/system/etc/permissions下; 第二处是在同目录下的handheld_core_hardware.xml里面添加一句<feature name="android.hardware.usb.host">