USB3 host driver program structure

480 Views

November 10, 18

スライド概要

This presentation describes USB 3 host driver structure.
The host driver has 3 layers: host controller driver, bus driver, and class driver.
Recent days, hobby OS creators must implement USB host driver to support keyboard and mouse.

profile-image

サイボウズ・ラボ株式会社で教育向けのOSやCPU、コンパイラなどの研究開発をしています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

USB3ホストドライバのクラス構成 2018/11/10 Kernel/VM 北陸 4 @uchan_nos

2.

自己紹介 ● @uchan_nos ● 仕事1:サイボウズ SRE チーム ● 仕事2:東京工業大学 特任助教 ● 趣味:osdev-jp コアメンバー ←執筆 校正→

3.

モチベーション ● 最近のPCはレガシーサポートがない → PS/2エミュレーション機能がない → 自作OSでキーボードが扱えない! ● ということで… ● 自作OSでUSBデバイスを使いたい ● 移植は大変だし,勉強を兼ねて自作してみよう ● C++大好きだからC++っぽい書き方をしてみよう

4.

参考資料 ● ● カーネル/VM探検隊@関西 8回目 – 3:05 – 3:25 @liva_jy xHCI(USB3.0 HC)デバドラを自作してみよう – https://www.youtube.com/watch?v=dKUSUv2cxhg 『USB3.0ホストドライバ自作入門』 – https://uchan.booth.pm/items/1056355 ● 『eXtensible Host Controller Interface for Universal Serial Bus』 ● 『Universal Serial Bus 3.1 Specification』 ● 『Device Class Definition for Human Interface Devices (HID)』

5.

デバイス制御までの道のり xHCの初期化 xHCリセット,Command Ring設定, Primary Event Ring設定 デバイス検出 ポートへの挿入検知,ポートリセット デバイス初期化 スロット割り当て, DEVICE&CONFIGディスクリプタ取得 クラスドライバ エンドポイント有効化, クラス特有の処理の開始

6.

デバイス制御までの道のり xHCの初期化 xHCリセット,Command Ring設定, Primary Event Ring設定 デバイス検出 ポートへの挿入検知,ポートリセット デバイス初期化 今日のスコープ スロット割り当て, DEVICE&CONFIGディスクリプタ取得 クラスドライバ エンドポイント有効化, クラス特有の処理の開始

7.

USBホストドライバの構成 USBホストドライバ クラスドライバ 特定のUSBクラス のための処理 USBバスドライバ USB規格に従ったAPI を上位層に提供 ホストコントローラドライバ ホストコントローラの 詳細を隠蔽 ホストコントローラ(xHC) xHCI規格に準拠した ハードウェア実装

8.

USBホストドライバの構成 クラスドライバ 特定のUSBクラス のための処理 USBバスドライバ USB規格に従ったAPI を上位層に提供 ホストコントローラドライバ ホストコントローラの 詳細を隠蔽 ホストコントローラ(xHC) xHCI規格に準拠した ハードウェア実装

9.

USBバスドライバ USB規格に従ったAPIを上位層に提供 ● ● ● 例えばGET_DESCRIPTOR USBデバイスの種類や機能を判別するために デバイス自身が持っているディスクリプタを取得 DEVICE:デバイス全体の情報 – ● USBバージョン,EP0の最大パケット長, CONFIGURATIONの数,など CONFIGURATION:特定の機能構成 – インターフェース数,最大消費電力,など

10.

USB規格で規定されたAPI例 ● コントロール転送 – GET_DESCRIPTOR(D2H) ● – SET_CONFIGURATION(H2D) ● – コンフィグレーションの選択 GET_REPORT(D2H) ● ● DEVICE, CONFIGURATIONディスクリプタ等 HIDデバイスからのデータ入力 インタラプト転送,バルク転送,アイソクロナス転送

11.

USBホストドライバの構成 クラスドライバ 特定のUSBクラス のための処理 USBバスドライバ USB規格に従ったAPI を上位層に提供 ホストコントローラドライバ ホストコントローラの 詳細を隠蔽 ホストコントローラ(xHC) xHCI規格に準拠した ハードウェア実装

12.

ホストコントローラドライバ ホストコントローラの詳細を隠蔽 xHCのレジスタ DCBAAP Slot Ctx EP0 Ctx DCBA0 EP1 OUT Ctx DCBA1 EP15 IN Ctx … DCBAn ● メモリ上のデータ構造 Transfer Ring レジスタ構成,データ構造の詳 細などを隠蔽したい

13.

バスドライバとxHCドライバの境界 USBバスドライバ 具体的なデータ形式,各ビットの意味 Setup Stage Data Stage ホストコントローラドライバ Setup Stage データ転送のハコ ● 例えばコントロール転送は3ステージからなる ● 具体的なデータフォーマットはUSB規格のスコープ ● xHCI規格は3つのステージからなることだけを規定

14.

USBホストドライバの構成 クラスドライバ 特定のUSBクラス のための処理 USBバスドライバ USB規格に従ったAPI を上位層に提供 ホストコントローラドライバ ホストコントローラの 詳細を隠蔽 ホストコントローラ(xHC) xHCI規格に準拠した ハードウェア実装

15.

クラスドライバ 特定のUSBクラスのための処理 HID Human Interface Device ● Control パイプ 必須 Interrupt In パイプ 必須 Interrupt Out パイプ オプショナル HIDクラス(クラス番号3)は2つの必須パイプと 1つのオプショナルなパイプを規定

16.

HIDキーボードからの受信 初期状態取得 Interrupt In 発行 キーの押下状態を取得する キーの状態変化を検知するために, Interrupt In を発行しておく キー push / release Interrupt In 完了 キーの状態が変化すると Interrup In が完了してイベントが発行される (通常は割り込みとして検知する)

17.

クラスドライバとバスドライバの境界 ● バスドライバ – コントロール転送,インタラプト転送などの 仕組み(USB規格のAPI)を提供 – ● デバイスを識別し,適切なクラスドライバを 生成,割り当てるのはバスドライバの役目 クラスドライバ – バスドライバが提供するAPIを使って, – – クラスが規定するタイミングに従い, デバイスと具体的なデータ通信を主導する

18.

クラス図

19.

クラス図

20.

クラス図(USBバス& xHCドライバ) バスドライバ ホストコントローラドライバ

21.

クラス図

22.

クラス図(クラスドライバ)

23.

シーケンス(前半)

24.

シーケンス(後半)

25.

まとめ ● 今の時代,自作OSでもUSBドライバが必須 ● USBホスト側のドライバは3層で組むと良さげ – – – クラスドライバ バスドライバ ホストコントローラドライバ ● HIDキーボードの受信方法を紹介 ● 実際のクラス間相互作用を紹介 ● ソースコードはそのうち公開したい…

27.

usb::Device usb::ClassDriver 16 - buf_: uint8_t[256] class_drivers_ + + + + ControlIn(int, SetupData, void*, int) ControlOut(int, SetupData, const void*, int) InterruptIn(int, void*, int) InterruptOut(int, const void*, int) dev_ + + + + + + SetEndpoint(const EndpointConfig&) OnEndpointsConfigured() OnControlInCompleted(SetupData, const void*, int) OnControlOutCompleted(SetupData, const void*, int) OnInterruptInCompleted(const void*, int) OnInterruptOutCompleted(const void*, int) + StartInitialize() + IsInitialized(): bool + OnEndpointsConfigured() # # # # OnControlInCompleted(SetupData, const void*, int) OnControlOutCompleted(SetupData, const void*, int) OnInterruptInCompleted(const void*, int) OnInterruptOutCompleted(const void*, int) - InitializePhase1 - InitializePhase2 - InitializePhase3 usb::HIDKeyboardDriver - ep_interrupt_in_: int + + + + + + SetEndpoint(const EndpointConfig&) OnEndpointsConfigured() OnControlInCompleted(SetupData, const void*, int) OnControlOutCompleted(SetupData, const void*, int) OnInterruptInCompleted(const void*, int) OnInterruptOutCompleted(const void*, int) + SubscribeKeyPush(std::function<void (uint8_t)>) usb::xhci::Device - slot_id_: uint8_t + + + + ControlIn(int, SetupData, void*, int) ControlOut(int, SetupData, const void*, int) InterruptIn(int, void*, int) InterruptOut(int, const void*, int) + AllocTransferRing(DeviceContextIndex, size_t) + OnTransferEventReceived(const TransferEventTRB&) usb::xhci::Ring 31 transfer_rings_ - buf_: TRB* - cycle_bit_: bool - write_index_: size_t + Initialize(size_t) + Push(const TRB&): TRB*

28.

main usb::Device StartInitialize return usb::xhci::Device ControlIn[GET_DESC, DEVICE] return OnControlInCompleted xHC Push[Setup, Data, Status] OnTransferEventReceived InitializePhase1 DEVICEディスクリプタの処理 ControlIn[GET_DESC, CONFIG] Push[Setup, Data, Status] return return OnControlInCompleted return OnTransferEventReceived usb::<br>HIDKeyboardDriver InitializePhase2 CONFIGディスクリプタの処理 <span>new HIDKeyboardDriver</span> ControlOut[SET_CONFIG] return return OnControlOutCompleted Push[Setup, Status] return OnTransferEventReceived InitializePhase3 SET_CONFIG<br>完了後の処理 SetEndpoint return return return IsInitialized true AllocTransferRing Push[ConfigureEndpointCommand] エンドポイント有効化 Wait<br>CommandCompletionEvent return OnEndpointsConfigured OnEndpointsConfigured ControlIn[GET_REPORT, Input Report] Push[Setup, Data, Stage] return return OnControlInCompleted OnTransferEventReceived OnControlInCompleted キー入力の初期状態取得 NotifyKeyPush InterruptIn Push[Normal] Key Pushed OnInterruptInCompleted OnTransferEventReceived OnInterruptInCompleted