USB 设备没有返回数据
No Data Returned from USB device
我们有一个供应商特定的血压设备,我们想通过 Android 方便地配置
它是USB端口。
此外,我还为 Windows(按 WinUSB 处理)编写了与
设备,据我所知 Android 和 WinUSB api(当然)有很多
相似之处,它应该工作得很好。我还可以在 Android 上打开设备
并获取端点(批量端点)。该设备支持中断和批量 read/write 端点。
我还能够通过 controlTransfer 向设备成功写入命令,例如
private void tryGetDescriptor() {
byte[] buffer = new byte[18];
// https://www.beyondlogic.org/usbnutshell/usb6.shtml#SetupPacket standard device requests
int retVal = m_devCon.controlTransfer(0x80, 0x06, 0x0100, 0, buffer, 0x12, TIMEOUT);
if(retVal < 0) {
Debug("something failed");
} else {
Debug( "check buffer " + String.valueOf( retVal ) + " arr: " + Arrays.toString(buffer) );
}
}
或我在 Delphi 中的参考代码执行的一个 controlTransfer:
private void startPeripheral() {
int retVal = m_devCon.controlTransfer(0x40, 2, 0, m_readPkgSize, null, 0, 0);
if(retVal < 0) {
Debug("StartPeripheral failed!");
} else {
Debug("Control Transfer returned " + String.valueOf(retVal));
}
}
我现在面临的问题是,根据写入端点,我可能会向设备发送命令
但我没有得到 return 回复(设备至少应该回应命令)
这里是处理那个的线程(我知道同步的东西实际上不是 Java 这样的,请
对我有耐心...)
private UsbDeviceConnection m_devCon;
private UsbEndpoint m_epRead;
private UsbEndpoint m_epWrite;
private String m_command = "";
private boolean terminated = false;
public void sigTerminate(){
terminated = true;
m_command = "";
}
public void init( UsbDeviceConnection devCon, UsbEndpoint readEP, UsbEndpoint writeEP ) {
this.m_devCon = devCon;
this.m_epRead = readEP;
this.m_epWrite = writeEP;
}
public void asyncSendCmd( String cmd ) {
Debug("AsyncSendCmd: " + cmd);
m_command = new String(cmd);
}
private void sendRec() {
Debug("Run thread");
byte[] buffer = new byte[m_readPkgSize];
try {
//while( req.queue( rBuf ) ) {
while (true) {
try {
while (m_command == "" && !terminated)
sleep(10);
Debug("Something found" + m_command);
} catch (InterruptedException f) {
Thread.currentThread().interrupt();
Debug("Thread interruped: " + f.getMessage());
}
String cpyCmd = new String(BR102_RESET );
m_command = "";
if (!terminated && isConnected()) {
// not threadsave but what shels
Debug("Writing command: " + cpyCmd);
byte[] writeBuf = cpyCmd.getBytes();
//int lenWrite = m_devCon.bulkTransfer(m_epWrite, writeBuf, writeBuf.length, TIMEOUT);
//if (lenWrite != writeBuf.length)
// throw new IOException("Write failed with len: " + String.valueOf(lenWrite));
// sleep(48);
UsbRequest wreq = new UsbRequest();
wreq.initialize( m_devCon, m_epWrite);
ByteBuffer wBuf = ByteBuffer.wrap(writeBuf);
wreq.queue( wBuf );
final UsbRequest responsew = m_devCon.requestWait( TIMEOUT );
if(responsew == null) {
Debug("no write response");
break;
}
int lenWrite = wBuf.position();
Debug("Wrote: " + String.valueOf(lenWrite));
wreq.close();
UsbRequest req = new UsbRequest();
req.initialize(m_devCon, m_epRead);
ByteBuffer rBuf = ByteBuffer.wrap( buffer );
req.queue( rBuf );
//int lenRead = m_devCon.bulkTransfer(m_epRead, buffer, m_readPkgSize, TIMEOUT);
final UsbRequest response = m_devCon.requestWait(TIMEOUT);
if(response == null) {
Debug("No Resonse");
break;
}
int lenRead = rBuf.position();
if (lenRead > 0) Debug("lenRead: " + String.valueOf(lenRead));
else Debug("lenRead: " + String.valueOf(lenRead));
req.close();
}
//rBuf.rewind();
//req.close();
}
} catch (Exception e) {
Debug("Error in usb read thread: " + e.toString());// e.getMessage());
}
}
@Override
public void run() {
sendRec();
}
}
正如你所看到的,我尝试了很多东西。这是我想到的最复杂的一个。基本上
我的第一次尝试或多或少是 bulkTransfers,其行为相同...
请注意,"Reset\n" 命令可以发送 2 次,然后即使写入失败...
为了完整起见,这里是 usb 初始化例程:
private void startUSB(UsbDevice device) throws IllegalArgumentException {
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
if(!usbManager.hasPermission( device )) {
usbManager.requestPermission( device, m_permissionIntent );
return;
}
try {
if( usbReader != null) {
Debug("WTF usbReader already started!!!!");
usbReader.sigTerminate();
usbReader.join();
usbReader = null;
}
// ########################################################
// #### we the permission -> get the interfaces and check for the endpoints
m_device = device;
int numInterfaces = m_device.getInterfaceCount();
if(numInterfaces > 0) {
Debug("Number of interfaces: " + String.valueOf(numInterfaces));
m_devIntf = m_device.getInterface(0);
Debug(String.valueOf(m_devIntf.getInterfaceProtocol()));
Debug("Number of endpoints: " + m_devIntf.getEndpointCount());
m_epRead = null;
m_epWrite = null;
for (int i = 0; i < m_devIntf.getEndpointCount(); i++) {
UsbEndpoint endPoint = m_devIntf.getEndpoint(i);
Debug(String.valueOf(i + 1) + ": Endpoint " + endPoint.toString());
if (endPoint.getDirection() == UsbConstants.USB_DIR_IN && endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
m_epRead = endPoint;
}
if (endPoint.getDirection() == UsbConstants.USB_DIR_OUT && endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
m_epWrite = endPoint;
}
}
if (m_epRead == null || m_epWrite == null)
throw new IllegalArgumentException("No bulk read or write endpoint found");
Debug("Got endpoints");
// ############################################################################
// okidoki we have endpoints and we have an interface -> open the device
m_devCon = usbManager.openDevice(m_device);
Debug("Got device");
if (m_devCon == null)
throw new IllegalArgumentException("No Deviceconnection?!");
if (!m_devCon.claimInterface(m_devIntf, false))
throw new IllegalArgumentException("Claim failed");
Debug("All fine - now we can start the conversation");
m_readPkgSize = m_epRead.getMaxPacketSize();
m_writePkgSize = m_epWrite.getMaxPacketSize();
tryGetDescriptor();
// ############################################################################
// ### init reading and wrinting
usbReader = new UsbReadThread();
usbReader.init( m_devCon, m_epRead, m_epWrite );
usbReader.start();
startPeripheral();
} else {
Debug("No interfaces");
}
} catch(Exception e)
{
Debug( "Device connection failed with " + e.getMessage() );
// release
closeUSB();
return;
}
}
好的伙计们 - 在我有机会查看固件后我终于认识到 - 即使发布了 4 个 usb 端点 - 我只能在中断管道端点上写入并且只能从批量传输端点读取。
我们有一个供应商特定的血压设备,我们想通过 Android 方便地配置 它是USB端口。 此外,我还为 Windows(按 WinUSB 处理)编写了与 设备,据我所知 Android 和 WinUSB api(当然)有很多 相似之处,它应该工作得很好。我还可以在 Android 上打开设备 并获取端点(批量端点)。该设备支持中断和批量 read/write 端点。
我还能够通过 controlTransfer 向设备成功写入命令,例如
private void tryGetDescriptor() {
byte[] buffer = new byte[18];
// https://www.beyondlogic.org/usbnutshell/usb6.shtml#SetupPacket standard device requests
int retVal = m_devCon.controlTransfer(0x80, 0x06, 0x0100, 0, buffer, 0x12, TIMEOUT);
if(retVal < 0) {
Debug("something failed");
} else {
Debug( "check buffer " + String.valueOf( retVal ) + " arr: " + Arrays.toString(buffer) );
}
}
或我在 Delphi 中的参考代码执行的一个 controlTransfer:
private void startPeripheral() {
int retVal = m_devCon.controlTransfer(0x40, 2, 0, m_readPkgSize, null, 0, 0);
if(retVal < 0) {
Debug("StartPeripheral failed!");
} else {
Debug("Control Transfer returned " + String.valueOf(retVal));
}
}
我现在面临的问题是,根据写入端点,我可能会向设备发送命令 但我没有得到 return 回复(设备至少应该回应命令)
这里是处理那个的线程(我知道同步的东西实际上不是 Java 这样的,请 对我有耐心...)
private UsbDeviceConnection m_devCon;
private UsbEndpoint m_epRead;
private UsbEndpoint m_epWrite;
private String m_command = "";
private boolean terminated = false;
public void sigTerminate(){
terminated = true;
m_command = "";
}
public void init( UsbDeviceConnection devCon, UsbEndpoint readEP, UsbEndpoint writeEP ) {
this.m_devCon = devCon;
this.m_epRead = readEP;
this.m_epWrite = writeEP;
}
public void asyncSendCmd( String cmd ) {
Debug("AsyncSendCmd: " + cmd);
m_command = new String(cmd);
}
private void sendRec() {
Debug("Run thread");
byte[] buffer = new byte[m_readPkgSize];
try {
//while( req.queue( rBuf ) ) {
while (true) {
try {
while (m_command == "" && !terminated)
sleep(10);
Debug("Something found" + m_command);
} catch (InterruptedException f) {
Thread.currentThread().interrupt();
Debug("Thread interruped: " + f.getMessage());
}
String cpyCmd = new String(BR102_RESET );
m_command = "";
if (!terminated && isConnected()) {
// not threadsave but what shels
Debug("Writing command: " + cpyCmd);
byte[] writeBuf = cpyCmd.getBytes();
//int lenWrite = m_devCon.bulkTransfer(m_epWrite, writeBuf, writeBuf.length, TIMEOUT);
//if (lenWrite != writeBuf.length)
// throw new IOException("Write failed with len: " + String.valueOf(lenWrite));
// sleep(48);
UsbRequest wreq = new UsbRequest();
wreq.initialize( m_devCon, m_epWrite);
ByteBuffer wBuf = ByteBuffer.wrap(writeBuf);
wreq.queue( wBuf );
final UsbRequest responsew = m_devCon.requestWait( TIMEOUT );
if(responsew == null) {
Debug("no write response");
break;
}
int lenWrite = wBuf.position();
Debug("Wrote: " + String.valueOf(lenWrite));
wreq.close();
UsbRequest req = new UsbRequest();
req.initialize(m_devCon, m_epRead);
ByteBuffer rBuf = ByteBuffer.wrap( buffer );
req.queue( rBuf );
//int lenRead = m_devCon.bulkTransfer(m_epRead, buffer, m_readPkgSize, TIMEOUT);
final UsbRequest response = m_devCon.requestWait(TIMEOUT);
if(response == null) {
Debug("No Resonse");
break;
}
int lenRead = rBuf.position();
if (lenRead > 0) Debug("lenRead: " + String.valueOf(lenRead));
else Debug("lenRead: " + String.valueOf(lenRead));
req.close();
}
//rBuf.rewind();
//req.close();
}
} catch (Exception e) {
Debug("Error in usb read thread: " + e.toString());// e.getMessage());
}
}
@Override
public void run() {
sendRec();
}
}
正如你所看到的,我尝试了很多东西。这是我想到的最复杂的一个。基本上 我的第一次尝试或多或少是 bulkTransfers,其行为相同...
请注意,"Reset\n" 命令可以发送 2 次,然后即使写入失败...
为了完整起见,这里是 usb 初始化例程:
private void startUSB(UsbDevice device) throws IllegalArgumentException {
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
if(!usbManager.hasPermission( device )) {
usbManager.requestPermission( device, m_permissionIntent );
return;
}
try {
if( usbReader != null) {
Debug("WTF usbReader already started!!!!");
usbReader.sigTerminate();
usbReader.join();
usbReader = null;
}
// ########################################################
// #### we the permission -> get the interfaces and check for the endpoints
m_device = device;
int numInterfaces = m_device.getInterfaceCount();
if(numInterfaces > 0) {
Debug("Number of interfaces: " + String.valueOf(numInterfaces));
m_devIntf = m_device.getInterface(0);
Debug(String.valueOf(m_devIntf.getInterfaceProtocol()));
Debug("Number of endpoints: " + m_devIntf.getEndpointCount());
m_epRead = null;
m_epWrite = null;
for (int i = 0; i < m_devIntf.getEndpointCount(); i++) {
UsbEndpoint endPoint = m_devIntf.getEndpoint(i);
Debug(String.valueOf(i + 1) + ": Endpoint " + endPoint.toString());
if (endPoint.getDirection() == UsbConstants.USB_DIR_IN && endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
m_epRead = endPoint;
}
if (endPoint.getDirection() == UsbConstants.USB_DIR_OUT && endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
m_epWrite = endPoint;
}
}
if (m_epRead == null || m_epWrite == null)
throw new IllegalArgumentException("No bulk read or write endpoint found");
Debug("Got endpoints");
// ############################################################################
// okidoki we have endpoints and we have an interface -> open the device
m_devCon = usbManager.openDevice(m_device);
Debug("Got device");
if (m_devCon == null)
throw new IllegalArgumentException("No Deviceconnection?!");
if (!m_devCon.claimInterface(m_devIntf, false))
throw new IllegalArgumentException("Claim failed");
Debug("All fine - now we can start the conversation");
m_readPkgSize = m_epRead.getMaxPacketSize();
m_writePkgSize = m_epWrite.getMaxPacketSize();
tryGetDescriptor();
// ############################################################################
// ### init reading and wrinting
usbReader = new UsbReadThread();
usbReader.init( m_devCon, m_epRead, m_epWrite );
usbReader.start();
startPeripheral();
} else {
Debug("No interfaces");
}
} catch(Exception e)
{
Debug( "Device connection failed with " + e.getMessage() );
// release
closeUSB();
return;
}
}
好的伙计们 - 在我有机会查看固件后我终于认识到 - 即使发布了 4 个 usb 端点 - 我只能在中断管道端点上写入并且只能从批量传输端点读取。