2013年3月8日金曜日

[備忘録]USBデバイスの検索方法on Windows

Windows上でUSBデバイスを列挙したり、特定のUSBデバイスを探したりするのは非常に面倒です。というか、Windows上でデバイスを管理するの使われる用語がいろいろあって理解しずらいうえに、紛らわしいもので多いです。例えば、
  • device information set
  • device information element
  • device node (devnode)
  • device instance (DEVINST)
  • device instance ID
  • device interface
  • device interface path
とか…。他にもありそうですが、自分でもちゃんと理解しているかどうかは怪しいです。更に、SDKで定義されている構造体の種類とか含めると頭はバクハツ寸前です。

今回も、例のごとく学習能力が低い私のことですから過去の経験を思い出せずに、四苦八苦してWEBで調べまくって分かったことを備忘録として残しておきたいと思います。
WEBにはサンプルコードがいろいろ上がっていて非常に助かったのですが、結局コピペしてしまうと「何を」「どうやって」いるのかが把握できないままになってしまいますので、要点のみを残しておきます。

  1. USBデバイスの一覧を得るには

    SetupDiGetClassDevs()APIにGUID_DEVICEINTERFACE_USB_DEVICEを渡して呼び出す。もし自作ドライバなどで自前のデバイスインターフェースGUIDが定義されているなら、それを渡せば自分のUSBデバイスだけの一覧が得られる。

  2. USBデバイスにアクセスするためのデバイスインターフェースパスを得るには

    SetupDiGetInterfaceDeivceDetail()APIを呼び出す。

  3. USBデバイスがつながっているHUBのデバイスインターフェースパスを得るには

    SetupDiEnumDeviceInfo()APIで、デバイス一覧から一つのデバイスを取り出す。得られたdevice instanceをCM_Get_Parent()APIに渡して、親デバイスであるHUBデバイスのdevice instanceを得る。
    CM_Get_Device_ID()APIでHUBデバイスのdevice IDを得て、更にそれをCM_Get_Device_Interface_List()APIに渡すことで、HUBのデバイスインターフェースパスが得られる。
    これをCreateFile()APIに渡せばHUBデバイスを開くことができる。

  4. あるUSBデバイスが親であるHUBの何番目のポートに繋がっているかを知るには

    SetupDiEnumDeviceInfo()APIで特定のデバイスを取り出した後、それをSetupDiGetDeviceRegistryProperty()APIに渡す。このとき取り出すプロパティ値としてSPDRP_ADDRESSを指定すると、返される値はHUB中ののポート番号となっているようです。
    (どこにもそういう情報は見つけられませんでしたが、実験した限りではそういうことになっているようです)

  5. USBデバイスのデバイスディスクリプタを得るには

    上の3で得られた親HUBデバイスのデバイスインターフェースパスでHUBをCreateFileしたのち、そのデバイスにIOCTL_USB_GET_NODE_CONNECTION_INFORMATIONリクエストを投げます。このとき、4で得たポート番号を使います。
    このリクエストで渡したUSB_NODE_CONNECTION_INFORMATION構造体にはデバイスディスクリプタの内容が書き込まれて返されます。

特に3と4は今回発見した新しい方法でした。

0 件のコメント:

コメントを投稿