借り初めのひみつきちスマートフォン用の表示で見る借り初めのひみつきち仮ブログです。実装について軽く解説します。実装の解説がメインで、各レジスタやビットの意味などあまり詳細に解説すると本が書ける量になってしまうので省略ご了承ください。搭載されている基本的なデバイスだと思うのでこのような実装になっています。ベースアドレスを取得します。呼び出してメモリにマッピングします。非常にたくさんのバッファーを必要とするので各バッファーの確保と初期化もほとんどここで実行します。いう仕組みを利用します。割り込み通知専用の信号を使わずに特定のメモリアドレスに特定のデータを書き込んだ時に割り込みが発生する仕組みで、特定のデバイスに依存しないために実際に設定するアドレスなどの詳細仕様は決まっていません。レジスタによく似ています。ドライバから取得します。これ以降いくつかの設定レジスタにはアクセスできなくなります。開始したら全てのポートをスキャンしてポートリセットを実行します。リセットしないとイベントが発生しないのでこのような実装になっています。ここまでで初期化は終了します。割り込みハンドラはとてもシンプルで、イベントスレッドのセマフォにシグナルを送信するだけとなっていて、実際のイベント処理はイベントスレッドで行います。イベントを処理します。イベントは主に3種類ありますが、イベントスレッドはイベントを必要とするスレッドに通知するのみで具体的な処理はほとんどしません。ポートの状態が変化した時に発生するイベントです。ポート設定スレッドに通知します。コマンドコンプリーションイベントコマンドの実行結果を返すイベントです。コマンドを実行したスレッドに結果を通知します。トランスファーイベント転送コマンドの結果を返すイベントです。転送コマンドを実行したスレッドに結果を通知します。ポート設定スレッドポートステータスチェンジイベントを受け取ったポートの設定をするためのスレッドです。ポートリセット処理中に他のポートリセット操作が混在するとうまく動作しない機種があるらしいのでこのスレッドで1ポートずつ順番に処理します。コマンド実行待ちの間も別のイベントが発生するため、イベントスレッドとは別に処理します。初期化またはデバイスを接続した時にイベントが発生するのでそこでポートリセットします。デバイスにアドレスの割り当てをします。ドライバにデバイス接続したことを通知してデバイスのコンフィグレーションを行います。レイヤーの話になります。プラグアンドプレイを実現するために全てのデバイスは自分がどんなデバイスでどんな機能をサポートしているか記述された各種ディスクリプターを持っていて、ディスクリプターの内容にしたがってデバイスの初期化や適合するデバイスドライバを決定したりします。デバイスディスクリプタを読み出します。ドライバの設定したデフォルトのパケットサイズでは以降の処理がうまくできないので、デバイスディスクリプタに記述されている値でパケットサイズを設定し直します。次にコンフィグレーションディスクリプタを読み出します。バイトですが、インターフェースディスクリプタやエンドポイントディスクリプタもセットでくっついた不定長になるので、一度先頭だけ読み取って全体のサイズを取得してから改めて全体を読み直し、各ディスクリプタをパースしていきます。ディスクリプターをパースする最中にコンフィグレーションの有効化、インターフェースの列挙、エンドポイントの設定などをします。デバイスはコンフィグレーションはひとつしか存在しませんが、複数のインターフェースを持っている場合があります。デバイスなどは本質的にはコンポジットデバイスで、デバイスディスクリプタにはクラスコード000000が記述されているので、インターフェースディスクリプタに設定されているクラスコードで識別する必要があります。各ディスクリプタの処理が終わったらデバイスクラスやインターフェースクラスに適合するクラスドライバーを検索します。いう規格に則ったデバイスです。クラスドライバーを初期化します。実現する手段がないのでインターフェースごとにスレッドを作成しています。この方法はオーバーヘッドが大きいのでそのうち修正したいです。ここまできてやっとデバイスと単純なデータの通信ができる準備が整います。キーボードやマウスの読み取りキーボードやマウスに対してデータ読み込みコマンドを実行します。デバイスは読み込み用のエンドポイントを持っていて、読み込みを実行するとレポートという構造体を返します。向けに用途が固定されたブートプロトコルのキーボードとマウスのレポートのみ扱います。ディスクリプタのパースが面倒なので当面は対応しません。デバイスはとりあえず空読みしてデータが止まることがないようにしています。マネージャに渡すとパースしてキーボードやマウスのイベントに変換してくれます。