直近の Mac OS X Mavericks アップデートの直後あたりから (これが直接の原因かはわからないけど)、例え HID デバイスではなくても chrome.usb を単体で動かすことができなくなった。

今まではデバイス接続後に Chrome 全体を再起動することで openDevice が成功するという挙動だったのだが、今ではデバイス接続後に他の libusb を使ったプログラムを走らせて一旦 device を OS に認識させ、そのプログラムを終了し Chrome を起動する、という手順が必要になった。

つまり単体で再起動を繰替えしたりしてなんとか動かすということが不可能になり外部プログラムへ依存が必要になった。Chrome はどのようなコンテキストでも外部プログラムを実行することはできないので、打つ手はなくなった。

chromium のイシュートラッカーを usb 関係で検索してみると


あたりが関係していそう。 Canary を入れたくないので 35.0.1916.153 でしか試してない。stable で動かないものは「ない」と同じ。


このほか以下のようなバグがありそう

  • コントロール転送で8バイト未満をデバイスから返すと、データが化ける (こちらから送ったリクエストのバイナリ列になってしまう。謎)
  • インタラプト転送でずっとレスポンスしないでいると、デバイスにアクセスできなくなる。定期的に必ずなにか返答しないとだめ。

それとバグではないが、コントロール転送を out する場合、何も data を送りたくなくても、data : new ArrayBuffer(0) を渡さないと実行されない。罠。

Chrome App は、chrome.usb という API を通じて低レベルなUSBデバイスドライバをJavaScriptで書くことが可能になっている。chrome.usb は libusb 相当の API を提供している。

つまり、自分で作った USB デバイスと通信して、ブラウザ(といっても App だけど)からそれのI/Oを操作でき、LED を HTML+CSS+JS で UI を作って操作したり、ミサイルも JavaScript で飛ばせる。

そこで、AVR (200円ぐらいのワンチップマイコン) とその上で動くソフトウェアUSB実装である V-USB でカスタムデバイスを作成し、Chrome App から呼んでみた。

デバイス側

だいぶ前に実験した結果、Mac OS においては HID デバイスとしてUSBデバイスを作ると OS の管理下におかれ、libusb などからアクセスする手段が殆どなくなってしまうことがわかっていた。libhid 的なものがあればいいのだけれど、すくなくともまともにメンテされているのは当時見当らなかったので諦めた。

今回は教訓をいかして最初からHIDではないカスタムクラスのUSBデバイスにすることとした。

デバイス側の実装及び V-USB の設定ファイルは以下の通り

AVR ATmega168、16MHz で動かして試している。

HID にしなくともデバイス側の実装はあまり大差ない。

USB_CFG_DEVICE_CLASS と USB_CFG_INTERFACE_CLASS を 0xff (vendor) にしておかないと claim_interface に失敗したので忘れずに変えておく必要がありそう。

ホスト側

ホスト側では、まず libusb + ruby における実装を書いて試した。

interrupt_transfer はブロックをとれるみたいなのだが、うまく呼ばれなかったので深追いせず普通に呼んでいる。

libusb を使うにしても USB のプロトコルの知識が必要になるのが面倒


そして Chrome App の実装も書いた。主な実装箇所は以下

最初どうしても openDevice が成功せず途方にくれていたが、Chrome 自体を再起動することで成功するようになった。諦めなくてよかった。

ちなみに公式?にある usb のサンプルは API が最新に追従していないので参考にしないほうがいい。

USB プロトコルまわり

知っておかなければいけないこと

  • USB は基本的に片方向の通信
    • CONTROL 転送は1度のトランザクションが双方向で Stop-and-wait ARQ みたいな感じになってる
    • 必ずホストから先に通信が始まる (つまりデバイス側からデータを push することはできない)
  • USB には転送方法がいくつかある・それぞれ再送があったりなかったりするので必要に応じて使う
    • CONTROL 転送
    • ISOCHRONOUS 転送
    • BULK 転送
    • INTERRUPT 転送


参照

  1. トップ
  2. tech
  3. Chrome App で USB デバイス (AVR V-USB) にアクセスする