Android 3.1 の USB Host API を使ってFTDIシリアル通信してみた

現在↓でメンテしています。

https://github.com/ksksue/FTDriver
http://d.hatena.ne.jp/ksksue/20111106/1320589821

↑↑↑↑↑↑↑↑↑↑↑↑↑↑

以下は過去の記事です。

        • -


Android USBを用いてシリアル通信を行う方法(日本Androidの会 メーリングリスト)」
のスレッドがもりもり盛り上がってるようで
わりとAndroidでFTDI使うのって需要あるんじゃないかということで
ごにょごにょとやっていたところ、ようやく通信できたので記事うp


ただ、動作確認できたという程度なので、
ボーレートは9600固定だったり
受信と送信が同一スレッドだったりしています。
なのでちゃんと使えるようにするには真面目に書きなおす必要があります。


元にしているのはMLで本多さんが教えてくれた以下のページのソースコード
Creating a Serial to USB driver using the Android USB-Host API
http://android.serverbox.ch/?p=370
ただ、このサンプルコードにはAndroid→FTDIの通信はできるけど
FTDI→Androidの通信がないのでちょっと書き換えました。


以下


準備

  1. シリアル通信機器(2.とつないでシリアル通信させる)
  2. FTDIチップ搭載のUSB-シリアル変換モジュール(タブレット端末へつなぐ)
  3. タブレット端末(ICONIA A500で動作確認)
  4. ソースコード http://dl.dropbox.com/u/3858050/hatena/FTDI_USB.zip

USBを挿した状態でアプリを起動して、許可が求められたらOKを押す。


アプリ解説
基本的にLogCatで確認。
AndroidのUIはなにも変化しません。


LogCat内容

sent : Android → FTDIへ送ったデータ
recv length : recv ctrl のバイト数 + recv data のバイト数
recv ctrl : FTDI → Androidへ受け取った制御データ(とりあえず無視)
recv data : FTDI → Androidへ受け取ったデータ(ここにペイロード情報がくる)


このLogCatでは以下のデータが送受信されていることになります。
送信データ: 66(B)
受信データ: 97(a) 98(b) 99(c)



ソースコード解説
エンドポイントへつなぐ流れはサンプルコードによくある話なので省略。

まずFTDIチップの初期化。

conn.controlTransfer(0x40, 0, 0, 0, null, 0, 0);//reset
conn.controlTransfer(0x40, 0, 1, 0, null, 0, 0);//clear Rx
conn.controlTransfer(0x40, 0, 2, 0, null, 0, 0);//clear Tx
conn.controlTransfer(0x40, 0x02, 0x0000, 0, null, 0, 0);//flow control none
conn.controlTransfer(0x40, 0x03, 0x4138, 0, null, 0, 0);//baudrate 9600
conn.controlTransfer(0x40, 0x04, 0x0008, 0, null, 0, 0);//data bit 8, parity none, stop bit 1, tx off

初期化に必要な情報はLinuxドライバにあります。
ftdi_sio.hをのぞくとfmfmです。 http://lxr.free-electrons.com/source/drivers/usb/serial/ftdi_sio.h


Android → FTDI

conn.bulkTransfer(epOUT, new byte[]{counter}, 1, 0); // TX

counterが送信データ。カウントアップさせながら1byteずつ文字を送っています。
上のLogCatの例の場合、counterは 66(B) になっています。


FTDI → Android

len = conn.bulkTransfer(epIN, datain, 7, 0); // RX
len = conn.bulkTransfer(epIN, datain, 64, 0); // RX

エンドポイントへ 7byte 64byteのデータを要求。
受信データはdatain、受信データ長はlenに入ってきます。


datainは上のLogCatの例で言うと
制御信号 1 96
データ 97(a) 98(b) 99(c)
が乗ってきます。
lenは5。


7byte要求にしているのは、エンドポイントデスクリプタを見ると bLength のサイズが7だから。
(bLengthはエンドポイントデスクリプタの長さなのでデータパケットサイズとは無関係でした)
64byteにしているのはエンドポイントデスクリプタを見ると wMaxPacketSize のサイズが64byteだから。
(Androkunさん情報ありがとうございました。)


エンドポイントデスクリプタはLinuxだと
$ lsusb -v | less
なんかで見れます。


あとはdatainをLogCatへ書き出しているだけ。


以上
Androidとの通信はBluetooth,ADK,Microbridgeと方法はいくつかありますが
そこにFTDIシリアルが加わってくると、よりAndroidとデバイスの親和性がよくなりそうですね。


参考サイト