从Android

时间:2015-10-27 09:40:29

标签: android usb

我有这个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};

帮助表示赞赏。

1 个答案:

答案 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);