2018年03月04日

Raspberry Pi用ベアメタルUSBデバイスドライバ「csud」の調査(4)

ベアメタルRaspberry PiのUSBドライバの続きです。
csudで、Raspberry Pi Zero Wに直接接続したキーボードを取り外すと処理が正しく行えない問題を修正しました。
root hubからデバイスを取り外した際の「変更あり」フラグが設定できていなかったのが原因でした。

Raspberry Pi Zero WにUSBハブをつないで、そこに接続したキーボードを外したときは、正常に取り外し処理が行われます。
この処理は、概ね以下のような流れで行われています。

UsbCheckForChange
→HubCheckForChange
 →HubCheckConnection
  →HubPortGetStatus
   →UsbControlMessage
    →HcdSumbitControlMessage
     HcdChannelSendWait // Setup
     HcdChannelSendWait // Data
     HcdChannelSendWait // Status
   HubPortConnectionChanged
   →HubPortGetStatus
    HubChangePortFeature

HubPortGetStatusでデバイスの接続状況を確認しています。
この処理はデバイスへUSB経由でStatusコマンドを送ることで行われています。

一方、root hubからデバイスを取り外す場合はHcdSumbitControlMessageの内部で以下のように分岐しています。
この場合は、接続処理は正しく行われますが、取り外し処理が行われません。

    if (pipe.Device == RootHubDeviceNumber) {
return HcdProcessRootHubMessage(device, pipe, buffer, bufferLength, request);
}

この結果、HcdSumbitControlMessage以降の流れは以下のようになります。

    →HcdSumbitControlMessage //ここまでは同じ
     →HcdProcessRootHubMessage
      switch (request->Request) {
      case GetStatus:
       switch (request->Type) {
       case 0xa3:
        // Statusを取得
       }
      }

root hubのポート(Zero WではオンボードのUSBコネクタに相当)の接続状況のチェックはHcdProcessRootHubMessageで行っていますが、この処理はUSBでStatusメッセージを送る代わりに、USBコントローラのレジスタ(0x0440)の値を読み出しています。

詳しく見てみると、USBコントローラのレジスタには、USBポートの状況を表す2つのフラグ

・Port.Connect(bit 0; デバイスが接続されていればtrue)
・Port.ConnectDetected(bit 1; デバイスが新たに接続されたときにtrue)

があり、後者はデバイスが「なし→あり」のときはtrueになりますが「あり→なし」のときはtrueにならないようです。
しかし、csudの実装ではPort.ConnectDetectedのレジスタ値を「ポートの接続状況に変化があった」フラグとして用いているため、デバイスの取り外しが検出できていませんでした。

このあたり、ultiboのフォーラムの以下のやりとりが参考になりました。

usb keyboards not recognized on "Raspberry PI A+" - ultibo.org

この議論に対応する、ultiboのUSBドライバのパッチは以下のコミットと思われます。

Fixes for Raspberry Pi A/A+/Zero USB handling ・ ultibohub/Core@ba3c908

csudとはだいぶ構成が違うライブラリなので、csudへそのまま適用するのは無理そうですが、コメントを読むだけでもヒントになりそうです。

csudでの上記の不具合の解決方法ですが、HubPortGetStatusを呼ぶ前と呼んだ後とでPort.Connectの値の変化をチェックするようにしました。
パッチを当てたcsudは以下のリポジトリで公開しています。

boochow/csud: Chadderz's Simple USB Driver for Raspberry Pi

なお、時間がたつとハングアップする問題は、Pollループに少しウエイトを入れるようにしたら起こらなくなったので、デバイスへの過負荷が原因だったのかもしれません。

これで、Pi Zero WにUSBキーボードを直結しても問題なく動作するようになったと思われます。
ラベル:USB
posted by boochow at 13:38| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年03月02日

Raspberry Pi用ベアメタルUSBデバイスドライバ「csud」の調査(3)

前回の続きです。
以前にリストアップした中でちょっと触れていたcsudの64bit対応の派生版について、もう少し詳しく調べてみました。

下記のリポジトリにはコンパイル済みのバイナリがあり、マウスとキーボードの値が画面表示されます。

USB peripherals in bare metal? - Raspberry Pi Forums

Raspberry-Pi/Arm32_64_USB at master ・ LdB-ECM/Raspberry-Pi

以前調べたときはこのバイナリをそのまま動かして動作を確認しただけでした。
今回は、この中身を調べて、シリアルポートにキーコードを出力するサンプルを作ってみました。

このドライバは、完全に新規なドライバというわけではなく、csudを書き直して

・RPi2 / RPi3(32bit) / RPi3(64bit) 対応
・主なファイルを1つだけに

したもののようです。

実際、内部を見ると関数や全体の構造はかなり似ています。
一方で、csudのコードがそのまま残っているわけでもなく、大幅に整理されています。
csudでは個別のファイルに分かれていたUSBハブやHIDデバイスのためのコードも含まれています。
主なコードは「rpi-USB.[ch]」だけで、合わせて4300行足らずです。

csudよりもさらに行数は減っていますが、そのためか、USBキーボードなど個々のデバイスのサポート用関数などは減っています。

csudで作った、押されたキーのキーコードをシリアルポートに書き出すプログラムをrpi-USBで書き直したものを下記に置いておきます。

bare_matal_rpi_zero/usb_kbd2 at master ・ boochow/bare_matal_rpi_zero

Raspberry Pi Zero Wで動かす際にcsudにあった不具合は、そのまま引き継がれているようで、キーボードはUSBハブ経由で接続する必要があります。
ラベル:USB
posted by boochow at 01:21| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする
人気記事