我有这个USB Relay,我想通过Android手机控制。
(有一个类似的帖子here,但它解释了如何从Linux shell。通过查看该代码,我认为我能够解决它 - 显然不是。)
设备列在lsusb中:
Bus 002 Device 011: ID 16c0:05df VOTI Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x16c0 VOTI idProduct 0x05df bcdDevice 1.00 iManufacturer 1 iProduct 2 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 34 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 20mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 0 No Subclass bInterfaceProtocol 0 None iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.01 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 22 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 20
我觉得奇怪的是,终点被定义为“EP IN”。在我看来它应该是“EP OUT”,因为方向应该是“host-> device”。
无论如何,我使用Android USB管理器创建连接,然后初始化USbRequest以获得基于中断的终点。 Android权限和所有处理权限,以便设备成功连接。
用于发送数据的代码段。它遵循Android准则在单独的线程中运行:
UsbRequest request = new UsbRequest();
synchronized (mUsbLock) {
if (mUsbConnection != null && mUsbEndPointIn != null) {
if (!request.initialize(mUsbConnection, mUsbEndPointIn)) {
Log.e(TAG, "Unable to initialize UsbRequest. Thread exits");
return;
} else {
if (DEBUG) {
Log.d(TAG, String.format("Usb request is initialized"));
}
}
} else {
Log.e(TAG, "Usb communication is not up and running. The worker thread should never be started.");
return;
}
}
mRunning.set(true);
while (mRunning.get()) {
if (DEBUG) {
Log.d(TAG, String.format("Waiting for data to be sent to end point"));
}
WorkPackage wp = mWorkQueue.take();
// send the package.
byte[] data = wp.getData();
if (!request.queue(ByteBuffer.wrap(data), data.length)) {
Log.e(TAG, "Unable to queue to send data on UsbRequest.");
continue;
} else {
if (DEBUG) {
Log.d(TAG, String.format("Usb request is queued on end point, ep=%s", printUsbEndpoint(mUsbEndPointIn)));
}
}
}
似乎一切都很好,没有错误发生,请求在终点排队,但后来什么都没发生。我没有得到任何消息,说明请求已被处理。
由于供应商不会发布开/关命令,我尝试了基于Linux帖子的变种(上图)。似乎没有工作。供应商仅发布Windows二进制库。
发送8字节包(根据最大包):
public static byte[] SET_RELAY_ON = {(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
public static byte[] SET_RELAY_OFF = {(byte) 0xfd, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
帮助表示赞赏。
答案 0 :(得分:5)
所以,我想出了如何做到这一点。我会在这里写出解决方案,以防其他人遇到类似的问题。
我不得不窥探USB流量以了解实际发送的内容。事实证明,根本没有使用定义的中断终点。因此,与设备的通信不是基于中断的,而是使用端点0上的控制传输类型。
因此,使用Android USB API会转换为:
打开设备(设备 - >主机方向):
$.ajax({
url: "/register?userEmail=" + $('input[name="user_email"]').val(),
type: "GET",
success: function(data){
if(data.status = "OK"){
//All is good
}else{
//There was an error
}
}
error: function(xhr, ajaxOptions, thrownError){
//If something brakes
alert(xhr.status);
alert(thrownError);
}
});
开放中继' 1' (主机 - >设备方向)。
int r = mUsbConnection.controlTransfer(0xa1, 0x01, 0x0300, 0x00, buffer, buffer.length, 500);
注意,缓冲区中的第二个参数(0x01)是中继号(如果板上有> 1个中继)。我只有一个。
关闭接力' 1' (主机 - >设备方向):
byte[] buffer = {(byte) 0xff, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
int r = mUsbConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, buffer, buffer.length, 500);