16

Android 3.2 の USB ホスト機能を利用するプロジェクトに取り組んでいます。私は USB/シリアル通信全般に関する知識と才能の嘆かわしい不足に苦しんでいます。また、何をする必要があるかについての良いサンプルコードも見つかりません。

USB 通信デバイスから読み取る必要があります。
例: Putty 経由で (PC 上で) 接続する場合、次のように入力します。

>GO

そして、デバイスは私のためにデータを吐き出し始めます。ピッチ/ロール/温度/チェックサム。

元:

$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

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 のさまざまな組み合わせを試してみましたが、うまくいきませんでした。

ありがとう。

以下に示すように、interface#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);
  }
4

1 に答える 1

13

私は自分の質問に答えるのが嫌いですが...私はそれを理解しました。読み取りと書き込みを混同していました。さらに、デバイスは、コマンドの最後に使用していた '\n' を気に入りませんでした。'\r' との相性が良いようです。

私は、読み取りと書き込みにAndroidのbulkTransferを使用することになりました。私の書き込みはこのように見えました。

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

そして、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);
  }

読み取りは類似していました。

    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);
    }

と:

@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;
  }

これはすべて、次のようなスレッドで開始されました。

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

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

    while (true) {
        String coords = read(); 
        }
}
}.start();

明らかに、これは単なる通信用のものであり、何かを行う必要があります (ハンドラーを使用して最上位の 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;
}
}

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 {
    }

}
于 2012-01-23T15:50:33.757 に答える