我有一个带按钮的USB设备。 我想要一个Android应用程序来捕获按钮的信号。 我找到了按钮的界面和端点号。 它似乎通常在星系S3和星系音符执行。 但后来,我发现它在其他手机上有延迟。
我能够在大约10%的时间内收到即时回复;通常有2秒的延迟,有些情况下整个反应都会丢失。
虽然我无法弄清楚具体原因,但我意识到响应延迟的手机是内核版本为3.4或更高版本的手机。
这是我最初使用的代码。
if(mConnection != null){
mConnection.claimInterface(mInterfaces.get(0), true);
final UsbEndpoint endpoint = mInterfaces.get(0).getEndpoint(0);
Thread getSignalThread = new Thread(new Runnable() {
@Override
public synchronized void run() {
byte[] buffer = new byte[8];
final ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
while(mConnection!=null){
int len = mConnection.bulkTransfer(endpoint, buffer, buffer.length, 0);
if( len>=0 ){
// do my own code
}
}
}
});
getSignalThread.setPriority(Thread.MAX_PRIORITY);
getSignalThread.start();
}
修改超时
当超时设置为50毫秒时,我无法在大多数时间收到回复。当超时为500毫秒时,我最初得到一些延迟响应;但是,在使用此设置多次尝试后,我丢失了所有回复。
使用UsbRequest
除了使用bulktransfer方法,我还尝试使用UsbRequest,下面是我使用的代码。
@Override
public synchronized void run() {
byte[] buffer = new byte[8];
final ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
UsbRequest inRequest = new UsbRequest();
inRequest.initialize(mConnection, endpoint);
while(mConnection!=null){
inRequest.queue( byteBuffer , buffer.length);
if( mConnection.requestWait() == inRequest ){
// do my own code
}
}
}
然而,即使使用UsbRequest也会发生同样的延迟。
使用libusb
我还尝试使用名为libusb的开源库中的libusb_interrupt_transfer。 然而,这也产生了与使用UsbDeviceConnection时相同类型的延迟。
unsigned char data_bt[8] = { 0, };
uint32_t out[2];
int transfered = 0;
while (devh_usb != NULL) {
libusb_interrupt_transfer(devh_usb, 0x83, data_bt, 8, &transfered, 0);
memcpy(out, data_bt, 8);
if (out[0] == PUSH) {
LOGI("button pushed!!!");
memset(data_bt, 0, 8);
//(env)->CallVoidMethod( thiz, mid);
}
}
在查看libusb_interrupt_transfer处理libusb的部分后,我能够找出interrupt_transfer的一般步骤: 1.制作类型中断的传输对象 2.创建一个指向传输对象的urb对象 3.将urb对象提交给设备的fd 4.通过urb对象检测fd对象中的任何更改 5.通过ioctl阅读urb
步骤3,4,5是关于文件i / o的步骤。 我能够发现,在第4步,程序在进入下一步之前等待按下按钮。
因此,我尝试将轮询更改为epoll,以检查轮询功能是否导致延迟;遗憾的是没有任何改变。
我还尝试将poll函数的超时设置为500ms,并使其始终通过ioctl获取fd的值,但只发现按下按钮后值改变了2~3秒。
总而言之,我觉得按下按钮后更新fd值的过程有延迟。如果有人可以帮我解决这个问题,请告诉我。谢谢。
感谢您阅读