我有这个USB中继,我想从Android手机进行控制。
(这里有一个类似的帖子,但它解释了如何从Linux外壳中进行。通过查看代码,我认为我可以解决它——显然不是。)
设备列表在lsusb:中
总线002设备011:ID 16c0:05df VOTI设备描述符:b长度18b描述符类型1bcdUSB 1.10b设备类0(在接口级别定义)b设备子类0b设备协议0b最大数据包大小0 8id供应商0x16c0 VOTIidProduct 0x05dfbcdedit设备1.00iManufacturer 1iProduct 2iSerial 0bNumConfigurations 1配置描述符:b长度9b描述符类型2wTotalLength 34bNum接口1b配置值1iConfiguration 0bmAttributes 0x80(总线供电)最大功率20mA接口描述符:b长度9b描述符类型4b接口编号0b替代设置0bNumEndpoints 1b接口Class 3人机接口设备bInterface Subclass 0无子类b接口协议0无i接口0HID设备描述符:b长度9b描述符类型33bcdHID 1.01bCountryCode 0不受支持bNumDescriptors 1b描述符类型34报告wDescriptor长度22报告描述符:**不可用**终结点描述符:b长度7b描述符类型5b端点地址0x81 EP 1 INbmAttributes 3传输类型中断同步类型无使用类型数据wMaxPacketSize 0x0008 1x 8字节b间隔20
我觉得奇怪的是,终点被定义为"EP IN"。在我看来,它应该是"EP OUT",因为方向应该是"主机->设备"。
无论如何,我使用安卓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)));
}
}
}
看起来一切都很好,没有发生错误,请求在终点排队,但之后什么也没发生。我没有收到任何关于请求已被处理的消息。
由于供应商不会发布on/off命令,我尝试了基于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};
感谢您的帮助。
所以,我想出了如何做到这一点。我会在这里写下解决方案,以防其他人遇到类似的问题。
我不得不窥探USB流量,以了解实际发送的内容。事实证明,定义的中断终点根本没有被使用。因此,与设备的通信不是基于中断的,而是使用端点0上的控制传输类型。
因此,使用Android USB API,这转化为:
打开设备(设备->主机方向):
int r = mUsbConnection.controlTransfer(0xa1, 0x01, 0x0300, 0x00, buffer, buffer.length, 500);
打开继电器"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);
注意,缓冲器中的第二个参数(0x01)是继电器编号(如果板上有>1个继电器)。我只有一个。
闭合继电器"1"(主机->设备方向):
byte[] buffer = {(byte) 0xfd, (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);
我在Github中找到了与此类似的项目(对于谁在寻找它)https://github.com/gigacycle/AndroidHidUsbRelayControl
我已经测试了这个代码,我可以确认它与USB中继板配合得很好。