Perl で Device::USB を試してみる。ターゲットは MC908JB8 基板。先日作成したファームウェアを使う。NetBSD では pkgsrc/develop/libusb を make install 後に CPAN からインストールするが、LIBS オプションに '-L/usr/pkg/lib' を設定しておく。FreeBSD や Linux でも 同様にできると思う。デバイスドライバは汎用 USB デバイスになるため、インストールは不要だ。Windows では ActiverPerl の ppm でインストールするが、ActiveState 社のリポジトリには含まれていないから http://www.bribes.org/perl/ppm/ を追加しておくこと。libusb も入るから、ターゲットとなる USB デバイスをインストールする際には、ここでインストールされた libusb0.sys を指定すること。デフォルトでは C:\Perl\site\lib\auto\Device\USB 以下にある筈だ。別のドライバをインストール済みの場合には削除して入れ換えること。.inf ファイルは http://libusb-win32.sourceforge.net/ で配布しているデバイスドライバ・バイナリパッケージに含まれる inf-wizard.exe コマンドで作成できる。[参考:EX908USB HOWTO (ISHIDA Engineering)]
dump_usb コマンドを実行すると、こんな結果が得られる。これは Windows XP での例。NetBSD ではホスト側ドライバなどに関わる部分が多少異なるが、ターゲット情報については基本的に同じだ。# 以下のコメントは後で付け加えたもの。
C:> perl dump_usb.pl
$VAR1 = [
bless( {
'location' => 0,
'dirname' => 'bus-0',
'devices' => [
bless( {
'descriptor' => {
'bcdUSB' => '1.10',
'iProduct' => 2,
'bDeviceSubClass' => 0,
'bDeviceClass' => 0,
'idProduct' => 0, # Product ID : 0x0000
'bcdDevice' => '1.00',
'iManufacturer' => 1,
'bMaxPacketSize0' => 8,
'iSerialNumber' => 0,
'bNumConfigurations' => 1,
'idVendor' => 3184, # Vendor ID : 0x0c70
'bDescriptorType' => 1,
'bDeviceProtocol' => 0
},
'filename' => '\\\\.\\libusb0-0000--0x0c70-0x0000',
'config' => [
{
'MaxPower' => 0,
'bmAttributes' => 192,
'bNumInterfaces' => 1,
'interfaces' => [
{
'bNumEndpoints ' => 2,
'bInterfaceSubClass' => 1,
'endpoints' => [
{
'bmAttributes' => 3, # 0x03 : Interrupt
'bSynchAddress' => 0,
'bRefresh' => 0,
'bEndpointAddress' => 129, # 0x81 'IN'
'bInterval' => 10,
'bDescriptorType' => 5,
'wMaxPacketSize ' => 8
},
{
'bmAttributes' => 3, # 0x03 : Interrupt
'bSynchAddress' => 0,
'bRefresh' => 0,
'bEndpointAddress' => 2, # 0x02 : OUT
'bInterval' => 10,
'bDescriptorType' => 5,
'wMaxPacketSize ' => 8
}
],
'bInterfaceProtocol' => 255,
'iInterface' => 0,
'num_altsetting' => 1,
'bInterfaceNumber' => 0,
'bDescriptorType' => 4,
'bAlternateSetting' => 0,
'bInterfaceClass' => 255
}
],
'iConfiguration' => 0,
'wTotalLength' => 32,
'bConfigurationValue' => 1,
'bDescriptorType' => 2
}
],
'device' => 25364440
}, 'Device::USB::Device' )
]
}, 'Device::USB::Bus' ),
];
C:> perl dump_usb.pl 3184 0
Device found: \\.\libusb0-0000--0x0c70-0x0000: ID 0c70:0000
MCT Elektronikladen: USB08 Evaluation Board
コマンドラインの "3184 0" はデバイスのベンダ ID と プロダクト ID (10 進表現)。で、適当にでっち上げたサンプルがこれ。
cmd.exe から "perl usbtest.pl" などとして実行すると LED が 1 秒間隔で点滅し、コンソールにはターゲットボードから読んだデータが次のように表示される。ターゲット側のファームウェアは送信した分だけ受信しないとバッファが詰まってしまうことに注意。Unix の場合は root で実行しなければならない。
# perl usbtest.pl
get string:
MCT Elektronikladen
USB08 Evaluation Board
write cmd[0]
8 bytes read
$VAR1 = [
1,
0,
0,
0,
0,
0,
0,
0
];
write cmd[1]
8 bytes read
$VAR1 = [
0,
0,
0,
0,
0,
0,
0,
0
];
endpoint は 'Interrupt' 型で bInterval (10ms) 周期での転送が期待されている。1 秒以下の周期にしたい場合には Time::HiRes::usleep() を使えばマイクロ秒単位で指定できる。Device::USB のインターフェースは libusb とほぼ同様だから C/C++ でも同じようにできるだろう。
Posted by masato at 08:45 PMむふふ、良いですね。
なんかもう、勝手にプロジェクトが成長しちゃっている感じで。
折角なのでこのまま進んで、7SEG LEDとか液晶に、今接続している人数とか、集計とか、REFERとか表示してしまうと言うのは!。
Posted by: せくすぃ部長 at 01/22, 2008 09:56 PMおそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。