2013年3月23日土曜日

ドライブ名とディスクの対応関係を調べる方法

以前から少し気になっていたことを調べてみました。またすぐに忘れそうなので、記録として残しておきます。
おおざっぱには次のようになります。


  1. ディスクの一覧を取得して、それぞれのディスクに対して、そのディスクの下に繋がっているボリューム名一覧を得ます。
  2. 個々のボリューム名と、それに対応する物理デバイスオブジェクト名(SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)の対応関係を調べます。
  3. その一方で、個々のドライブレター(A~Z)とそれに対応する物理デバイスオブジェクト名の対応関係を調べます。
これで、ドライブレター<-->物理デバイスオブジェクト名<-->ボリューム名<-->ディスクまで繋がりました。もちろん、ボリューム名<-->ディスクの関係は一対一とは限りません。

具体的には次のようなAPIを使いました。
  1. SetupDiGetClassDevs()にGUID_DEVINTERFACE_DISKを渡して物理ディスクの一覧を得て、SetupDiEnumDeviceInfo()で個々のディスクに対して、そのディスクのDEVINSTをCM_Get_Device_ID_List()関数にCM_GETIDLIST_FILTER_REMOVALRELATIONSフラグ付きで渡すと、そのディスクの下にあるボリューム名の一覧が得られます。
  2. SetupDiGetClassDevs()にGUID_DEVINTERFACE_VOLUMEを渡してボリュームの一覧を得て、SetupDiEnumDeviceInfo()で個々のボリュームに対して、そのボリュームのSP_DEVINFO_DATAをSetupDiGetDeviceRegistryProperty()関数にSPDRP_PHYSICAL_DEVICE_OBJECT_NAMEフラグ付きで渡すと、物理デバイスオブジェクト名が得られます。
  3. A~Zまでのドライブレターに対して、QueryDosDevice()を実行することで、物理デバイスオブジェクト名が得られます。

「物理デバイスオブジェクト名」という名称は正しくないのかもしれませんが、上の1~3の説明の中で同じものであることを示すために便宜的にそう呼ぶことにしています。

またまたCPUファンが回らない現象が・・・

またこの現象が発生しました。
今度はWindows 8 Proで、前回この現象を確認したときからLenovo PM Deviceドライバを1.66.0.21→1.66.0.22にアップデートしていたのですが、そのアップデートではやはり改善されなかったようです(ドライバのリリースノートにも、それらしいことは書かれていなかった)。
そして、今回は休止状態からの復帰時でした。その後の再現性はありませんから、たまたまそのタイミングで起きたようで、休止状態からの復帰で起きるというわけでもないようです(以前はスリープからの復帰時だった)。

今回もまだ寒い季節で、CPUファンが回ってなくてもCPU温度は75℃~80℃くらいで安定していたので、すぐにはシャットダウンせずにしばらく様子を見ていました。
PowerShellを起動して、Get-WmiObjectコマンドレットあたりをつかえば、WMI経由でFANの関係のステータスが見られるのかな?と思っていろいろ試してみましたが、Win32_FANクラスは何も返してくれませんでした。可能であれば、FANの設定(ActiveCoolingプロパティ)とかをいじって、どうなるか様子を見たかったのですが・・・。

結局、問題はまだ解決しないままです。

2013年3月18日月曜日

[備忘録]Windows8でi-simが動かない件

Windows 8をインストールしたThinkPad Edge E430にFPGAの開発環境を入れる必要が出てきたので、XilinxのISE WebPacket 14.4をインストールしてみました。余談ですが、ISEはバージョンアップごとに肥大しますね。14.4では、15.5GByteもSSDを占有していました。

ISEをインストールした理由はISimを使ってシミュレーションをしたかったからです。が、ISimのコンパイラであるfuseが何故かエラーを出すので、調べてみたところ回避方法がありましたので、また忘れてしまわないように残しておこうと思います(要は、海外の掲示板にあった情報の受け売りなのですが、英語だとなかなか見つけにくいので・・・)

(エラー表示)
ERROR:Simulator:861 - Failed to link the design

(回避策)
ISEをインストールしたときに入るcollect2を使わないようにリネームする

具体的には、C:\Xilinx\14.4\ISE_DS\ISE\gnu\MinGW\5.0.0\nt\libexec\gcc\mingw32\3.4.2\にインストールされているcollect2.exeを適当な名前(collect2_.exeとか)にリネームしておきます。

fuseは、collect2が必要だから呼び出すものだと思うんですが、なぜかリネームして呼び出せないようにするとコンパイルが通ります。とりあえず、これでISimが起動して、波形の確認ができるようになったのでヨシとします。

P.S.持論「PCなんてダマシダマシ使うもの」



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は今回発見した新しい方法でした。

2013年3月6日水曜日

LogicoolのK230を購入

職場でもThinkPad Edge E430がメインPCになりつつあるので、これまでメインとして使ってきたデスクトップと切り替えて使うために、USB切替器とLogicoolのワイヤレスキーボードK230を買ってみました。
本当はUSB切替器だけ買うつもりだったのですが、ちょっとついでに見てみたらワイヤレスキーボードが本当に安くなっているので、つい衝動的に買ってしまいました。Logicoolはワイヤレスマウスで非常に満足しているので、キーボードも特に迷うことなく、「これでええやん!」的に・・・。

Amazonで注文して翌日には届きました。開けてみて驚いたのは、小さい!そして軽いということ。なるほど、これだったら1500円そこそこで売っているのも理解できる。とにかく机の上がすぐに散らかってしまうので、このくらい小さいキーボードはまさに求めていたもの。意外な収穫だと思いました。

キーボードのタッチは悪くないです。カタカタ安っぽい音はしないし、打鍵はちょっと重い気がしますがしっとりしているとも言えます。ファンクションキーは普通の大きさにしてほしかったけど、押しにくいということはないです。ネット上ではいろいろ言われているENTERキーもさほど押しにくくはないけれど、いまいちなのでやはり右SHIFTキーが小さいこと、それからENTERの横の鍵カッコ[と]キーが小さくされていること(C++でソフトを書く人間としては[と]キーは頻繁に使う)、それからカーソルキーが小さすぎること、この3点がNGなところだと思います。

それと、個人的意見ですけど、テンキーは要らないです。このテンキー部分にフルキーボードと同じサイズのカーソルキーとHOME&ENDキー、PgUp/PgDnキーがあると最高によかったんですけどね。そういうキーボードを探すとテンキー付のフルキーボードになってしまうんですよね・・・。

と、いいつつ探してみるとショックなことを発見。K230ではなくて、K270というワイヤレスのフルキーボードがあるじゃないですか!しかも、K230より安いorz。
とはいえ、K230のコンパクトさは捨てがたい。これまで何台ものノートPCを渡り歩いてきて、その都度ちょっとずつ違うキーボードに戸惑いつつも慣れで乗り切ってきたのだから、K230も慣れてくるでしょうか。
せっかく買ったので、もうちょっと使い込んでみようかと思います。