Android USB主机通讯

K.R*_*.R. 16 io usb android serial-communication

我正在开发一个利用Android 3.2中的USB Host功能的项目.一般来说,我在USB /串行通信方面缺乏令人遗憾的缺乏知识和才能.我也无法找到任何我需要做的好示例代码.

我需要从USB通信设备上读取.
例如:当我通过Putty(在我的电脑上)连接时,我输入:

>GO
Run Code Online (Sandbox Code Playgroud)

设备开始为我喷出数据.俯仰/滚动/温度/校验.

例如:

$R1.217P-0.986T26.3*60
$R1.217P-0.986T26.3*60
$R1.217P-0.987T26.3*61
$R1.217P-0.986T26.3*60
$R1.217P-0.985T26.3*63
Run Code Online (Sandbox Code Playgroud)

我可以从Android设备发送初始'GO'命令,此时我收到'GO'的回音.

然后在任何后续读取上没有别的.

我该怎么做:1)发送'go'命令.2)读入结果数据流.

我正在使用的USB设备具有以下接口(端点).

设备类别:通讯设备(0x2)

接口:

接口#0类:通信设备(0x2)端点#0方向:入站(0x80)类型:中断(0x3)轮询间隔:255最大数据包大小:32属性:000000011

接口#1类:通信设备类(CDC)(0xa)端点#0地址:129编号:1方向:入站(0x80)类型:批量(0x2)轮询间隔(0)最大数据包大小:32属性:000000010

端点#1地址:2编号:2方向:出站(0x0)类型:批量(0x2)轮询间隔(0)最大数据包大小:32属性:000000010

我能够处理权限,连接到设备,找到正确的接口并分配端点.我只是想弄清楚使用哪种技术发送初始命令读取随后的数据.我尝试了bulkTransfer和controlTransfer的不同组合,没有运气.

谢谢.

我正在使用界面#1,如下所示:

public AcmDevice(UsbDeviceConnection usbDeviceConnection, UsbInterface usbInterface) {
    Preconditions.checkState(usbDeviceConnection.claimInterface(usbInterface, true));
    this.usbDeviceConnection = usbDeviceConnection;

    UsbEndpoint epOut = null;
    UsbEndpoint epIn = null;
    // look for our bulk endpoints
    for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
      UsbEndpoint ep = usbInterface.getEndpoint(i);
     Log.d(TAG, "EP " + i + ": " + ep.getType());
      if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
        if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
          epOut = ep;

        } else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
          epIn = ep;
        }

      }
    }
    if (epOut == null || epIn == null) {
      throw new IllegalArgumentException("Not all endpoints found.");
    }

    AcmReader acmReader = new AcmReader(usbDeviceConnection, epIn);
    AcmWriter acmWriter = new AcmWriter(usbDeviceConnection, epOut);
    reader = new BufferedReader(acmReader);
    writer = new BufferedWriter(acmWriter);
  }
Run Code Online (Sandbox Code Playgroud)

K.R*_*.R. 12

我讨厌回答我自己的问题,但是......我弄清楚了.我只是混淆了我的读写.此外,该设备不喜欢我在命令结束时使用的'\n'.它似乎与'\ r'相处得更好.

我最终使用android的bulkTransfer进行读写.我的写作看起来像这样.

    try {
            device.getWriter().write(command + "\r");
            device.getWriter().flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
Run Code Online (Sandbox Code Playgroud)

我为我的BufferedWriter重写了写入方法:

@覆盖

  public void write(char[] buf, int offset, int count) throws IOException {
    byte[] buffer = new String(buf, offset, count).getBytes(Charset.forName("US-ASCII"));
    int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
  }
Run Code Online (Sandbox Code Playgroud)

读取类似:

    char[] buffer = new char[BUF_SIZE];
    try {
        BufferedReader reader = device.getReader();

        int readBytes = reader.read(buffer);
        Log.d(TAG, "BYTES READ: " + readBytes);

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    String strBuf = new String(buffer).trim();
    if (DEBUG) {
        Log.d(TAG, "Read: " + strBuf);
    }
Run Code Online (Sandbox Code Playgroud)

和:

@Override
  public int read(char[] buf, int offset, int count) throws IOException {
    byte[] buffer = new byte[count];
    int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);

    if (byteCount < 0) {
      throw new IOException();
    }
    char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
    System.arraycopy(charBuffer, 0, buf, offset, byteCount);
    return byteCount;
  }
Run Code Online (Sandbox Code Playgroud)

这一切都只是在这样一个线程中开始:

new Thread() {
    @Override
public void run() {

    String command = "go";
    write(command);

    while (true) {
        String coords = read(); 
        }
}
}.start();
Run Code Online (Sandbox Code Playgroud)

显然这只是comm的东西,我现在需要用它做一些事情(把它放在一个可以使用处理程序报告回顶层UI活动的服务中).但是这一部分已经弄明白了.

非常感谢那些正在开发rosjava的人(http://code.google.com/p/rosjava/)......他们已经组建了很多很棒的项目,他们的代码非常有用.

添加我的设备类以帮助澄清事情.

import com.google.common.base.Preconditions;

import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;

/* This class represents a USB device that supports the adb protocol. */
public class BKDevice {

// private static final int TIMEOUT = 3000;

private final UsbDeviceConnection usbDeviceConnection;
private final BufferedReader reader;
private final BufferedWriter writer;
public static final String TAG = "AcmDevice";

public BKDevice(UsbDeviceConnection usbDeviceConnection,
        UsbInterface usbInterface) {
    Preconditions.checkState(usbDeviceConnection.claimInterface(
            usbInterface, true));
    this.usbDeviceConnection = usbDeviceConnection;

    UsbEndpoint epOut = null;
    UsbEndpoint epIn = null;
    // look for our bulk endpoints
    for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
        UsbEndpoint ep = usbInterface.getEndpoint(i);
        Log.d(TAG, "EP " + i + ": " + ep.getType());

        if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
            if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                epOut = ep;

            } else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
                epIn = ep;

            }
        }
    }
    if (epOut == null || epIn == null) {
        throw new IllegalArgumentException("Not all endpoints found.");
    }

    BKReader acmReader = new BKReader(usbDeviceConnection, epIn);
    BKWriter acmWriter = new BKWriter(usbDeviceConnection, epOut);

    reader = new BufferedReader(acmReader);
    writer = new BufferedWriter(acmWriter);
}

public BufferedReader getReader() {
    return reader;
}

public BufferedWriter getWriter() {
    return writer;
}
}
Run Code Online (Sandbox Code Playgroud)

添加BKReader代码:

import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.util.Log;

import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;

public class BKReader extends Reader {

    private static final int TIMEOUT = 1000;

    private final UsbDeviceConnection connection;
    private final UsbEndpoint endpoint;

    public BKReader(UsbDeviceConnection connection, UsbEndpoint endpoint) {
        this.connection = connection;
        this.endpoint = endpoint;
    }

    @Override
    public int read(char[] buf, int offset, int count) throws IOException {
        byte[] buffer = new byte[count];
        int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);

        if (byteCount < 0) {
          throw new IOException();
        }
        char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
        System.arraycopy(charBuffer, 0, buf, offset, byteCount);
        return byteCount;
    }

    @Override
    public void close() throws IOException {
    }

}
Run Code Online (Sandbox Code Playgroud)