首页 文章

通过Android控制USB中继

提问于
浏览
5

我有这个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以获得基于中断的 endpoints . 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};

帮助赞赏 .

1 回答

  • 5

    所以,我想出了如何做到这一点 . 我会在这里写解决方案以防其他人遇到类似的问题 .

    我不得不窥探USB流量以了解实际发送的内容 . 事实证明,根本没有使用定义的中断终点 . 因此,与设备的通信不是基于中断的,而是使用 endpoints 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);
    

相关问题