ダウンロード
付録CD-ROMの修正
補足情報(2007/1/25までに掲載されたもの)に沿って修正を施したファイルを,以下からダウンロードできます(「list」「project」フォルダのみ。「usbtest」「baseproject」「usbtest」「testfile」については,CD-ROM収録のものをそのままお使いください)。
リスト3-17(P.256~P.257)のUSB_IsochronousTransfer関数について
本関数では引数packetsに転送パケット数を設定するようになっていますが,これは8の倍数で設定する必要があります。
「4-5-2 ターゲットPCへのデバイスドライバのインストール」でusbstor.infが見つからない場合について
Windows XPの場合,usbstor.infが存在するINFフォルダは,通常の設定ではユーザーからは見えないようになっています。これを表示するためには,以下のようにします。
日本語版の場合
- エクススプローラを起動する
- 「ツール」から「フォルダオプション」を選択する
- フォルダオプションの画面にある「表示」というタブを選択する
- 「ファイルとフォルダの表示」という部分にある「すべてのファイルとフォルダを表示する」にチェックを入れる
- 「OK」をクリックする
英語版の場合
- エクスプローラを起動する
- 「 Tools 」から「 Folder Options 」を選択する
- Folder Optionsの画面にある「View」というタブを選択する
- 「Hidden files and folders」という部分にある「Show hidden files and folders」にチェックを入れる
- "Hide protected operating system files[Recommanded]"という項目がチェックされているのであれば,それを解除する
- 「OK」をクリックする
usbccgp.sysが介在した際の,マルチインターフェースデバイスに対する初期化処理
Windows XP SP2などで,usbccgp.sys(注1)が介在した場合のマルチインターフェースデバイスに関しては,INFファイルおよび初期化処理の記述に注意が必要です。
注1:複数の機能を持ったデバイスと,複数のドライバとを関連付けて管理するイメージのドライバ。
また,インターフェースディスクリプタを複数持つデバイスのドライバを開発されている方は,本書の内容だけでなく,以下の点にも配慮が必要となります。
INFファイル
VIDとPIDのほかに,MIという識別子を追加する必要があります。MI_xxの“xx”には,IADのbFirstInterfaceフィールドの値を指定します(下記の例では00)。
[Manufacturer_Name]
%DeviceDesc%=hamada_multi_if, USB\VID_ffff&PID_0000&MI_00
初期化コード
初期化の手順は,以下のようになります。
- USBD_ParseConfigurationDescriptorExで処理を行うインターフェースディスクリプタをすべて検索して,インターフェースリスト構造体に付加する。
- USBD_CreateConfigurationRequestExでURBを作成し,IoCallDriverでコンフィギュレーションを行う。また,この結果得られる(URB)->UrbSelectConfiguration.ConfigurationHandleをメモする。
- UsbBuildSelectInterfaceRequest(詳細はDDKヘルプを参照)でURBを作成して,さらに以下の設定を行う。
(URB)->UrbSelectInterface.Interface.Length =
GET_SELECT_INTERFACE_REQUEST_SIZE(x); // x=エンドポイントの数
- また,必要ならば,エンドポイントごとの最大転送バイト数(MaximumTransferSize)の設定もここで行う。
- IoCallDriverでインターフェースを選択する。
お詫びと訂正(正誤表)
本書の以下の部分に誤りがありました。ここに訂正するとともに,ご迷惑をおかけしたことを深くお詫び申し上げます。
P.リスト1-12(P.83~P.84)
[Strings]セクションの下から2行目の記述が,一部間違っています。正しくは以下のとおりです(第2刷にて修正済み)。
誤 |
USB\VID_0644&PID_0000.DeviceDesc="USB Test Device Driver" |
正 |
USB\VID_0474&PID_0700.DeviceDesc="USB Test Device Driver" |
---|
また,このファイルで実際に動作をしない場合,"Class=USB"の下に,以下の記述を追加してください。多くの場合はこの記述がなくても動作しますが,本来は記述が必要となります。
ClassGUID={36fc9e60-c465-11cf-8056-444553540000}
P.図1-41およびリスト1-16(P.121~125)
システムパワー制御(電源管理)に関して,図1-41ではIoSkipCurrentIrpStackLocationでI/Oスタックロケーションを設定するように説明しておりますが,リスト1-16(P.125)ではIoCopyCurrentIrpStackLocationとなっています。実際の動作には影響ありませんが,図とリストの整合性をとるために,リストの該当箇所はIoSkipCurrentIrpStackLocationに読み替えてください。
なお,第4章のリスト4-63(P.441~445)にも同様の処理があります(第2刷にて修正済み)。
P.142
6行目付近の説明で参照しているリスト番号が異なります。
P.図1-45(P.142)
A(アクセスコード)の説明とTypeの説明が入れ替わっていました。また,ビットの定義も一部異なっていました。正しくは以下のようになります(第2刷にて修正済み)。
D15-14 A | デバイス側で指定するアプリケーションが持っていなければならないアクセス権。以下から選択する |
| FILE_ANY_ACCESS | いつでもアクセス可能 |
| FILE_READ_DATA | 読み出し可能 |
| FILE_WRITE_DATA | 書き込み可能 |
| FILE_READ_DATA | FILE_WRITE_DATA | 読み書き可能 |
D1-0 Type | 転送タイプ。以下から選択する |
| METHOD_BUFFERED | SystemBufferを作成する(バッファードI/O) |
| METHOD_IN_DIRECT | 入力用のMDLを作成(ダイレクトI/O) |
| METHOD_OUT_DIRECT | 出力用のMDLを作成(ダイレクトI/O) |
| METHOD_NEITHER | 特に新しくバッファなどを作成しない |
P.図2-5(P.155)
1.PIDの値が間違っているものがあります。正しくは以下のとおりです。(第2刷にて修正済み)
OUT(トークンパケットの部分)
SETUP(トークンパケットの部分)
NAK(ハンドシェークパケットの部分)
2. データパケットの最後のCRCが“CRC5”となっていますが,データパケットの最後のCRCは16bit長となります。
3. SYNCフィールドの長さですが,ハイスピードモードの場合には32bit長となります。
P.表2-11(P.177)
コンフィグレーションディスクリプタに関する記述に誤りがあります。正しくは以下のとおりです(第2刷にて修正済み)。
誤 | bmAttributesのD7ビットは0にする |
正 | bmAttributesのD7ビットは1にする |
---|
また,bIntervalの内容に誤りがあります。正しくは以下のとおりです。
誤 | 単位はミリ秒 |
正 | 単位は125μS(1マイクロフレーム長) |
---|
P.表2-12(P.187),表2-13,表2-16(P.192)
インターフェースディスクリプタの設定内容の表記に誤りがあります。
正しくは以下のとおりです(“bDevice”の部分が“bInterface”となります)(第3刷にて修正済み)。
誤 | bDeviceClass |
正 | bInterfaceClass |
誤 | bDeviceSubClass |
正 | bInterfaceSubClass |
誤 | bDeviceProtocol |
正 | bInterfaceProtocol |
同様に,表2-13のキャプションは「bInterfaceSubClassの仕様」となります。
P.187およびP.192の本文についても,“bDevice”を“bInterface”と読み替えてください(第3刷にて修正済み)。
P.リスト3-17(P256~P257)
コードの記述のうち,以下の部分が間違っています。
また,内部変数としてULONG UrbSizeを宣言する必要があります。
誤 |
ULONG usbFlags |
正 |
ULONG urbFlags
|
---|
誤 |
urb = (PURB) ExAllocatePool(NonPagedPool, UrbSize);
|
正 |
urb = (PURB) ExAllocatePool(NonPagedPool, UrbSize);
RtlZeroMemory(urb, UrbSize); // クリアを行わないとIoCallDriverの実行でエラーになる場合がある。 |
---|
誤(第1刷) |
urb->UrbIsochronousTransfer.Hdr.Length = length;
|
誤(第2刷) |
urb->UrbIsochronousTransfer.Hdr.Length = UrbSize;
|
正 |
urb->UrbIsochronousTransfer.Hdr.Length = (USHORT)UrbSize;
|
---|
誤 |
urb->UrbIsochronousTransfer.Flags
|
正 |
urb->UrbIsochronousTransfer.TransferFlags
|
---|
誤 |
USBD_START_ISO_TRANSFERASAP
|
正 |
USBD_START_ISO_TRANSFER_ASAP
|
---|
誤 |
USB_CallUSBD(DeviceObject,&urb);
|
正 |
USB_CallUSBD(DeviceObject,urb);
|
---|
誤 |
ntStatus=urb.UrbHeader
|
正 |
ntStatus=urb->UrbHeader
|
---|
P.リスト3-21(P.267)
25行目付近のコメント内で参照しているリスト番号が異なります。
P.337
4-7-3「AddDevice関数のコーディング」の2行目付近で参照しているリスト番号が異なります。
P.表4-5(P.337)
引数の説明の中で,ポインタと長さの説明が逆になっていました。
誤 |
LPVOID lpInBuffer パソコン→デバイスへのデータ長
DWORD nInBufferSize パソコン→デバイスへのデータ
LPVOID lpOutBuffer デバイス→パソコンへのデータ長
DWORD nOutBufferSize デバイス→パソコンへのデータ
|
正 |
LPVOID lpInBuffer パソコン→デバイスへのデータ
DWORD nInBufferSize パソコン→デバイスへのデータ長
LPVOID lpOutBuffer デバイス→パソコンへのデータ
DWORD nOutBufferSize デバイス→パソコンへのデータ長
|
---|
P.charポインタに関する記述について(第4,第5章)
本書中のソースコード内にて,ポインタを指定する際に不要な"&"を記述している箇所があります。ただし,"&"が記述されたままでも実際の動作に影響ありません。
なお,具体的な箇所は以下のとおりです。
リスト4-27(P.383~384)
誤 |
(LPVOID)&buffer,
|
正 |
(LPVOID)buffer,
|
---|
リスト4-33(P.392~393)
誤 |
if (! WriteFile(hUsbTest,&buffer,5,&nBytes,NULL) ) {
|
正 |
if (! WriteFile(hUsbTest,buffer,5,&nBytes,NULL) ) {
|
---|
リスト4-40(P.408~410)
・InquiryTest関数
誤 |
if (!SendAtapiCommandPacket((PUCHAR)&atapi,36)) {
|
正 |
if (!SendAtapiCommandPacket((PUCHAR)atapi,36)) {
|
---|
誤 |
if (!ReadFile(hUsbTest,&buffer,36,&nBytes,NULL) ) {
|
正 |
if (!ReadFile(hUsbTest,buffer,36,&nBytes,NULL) ) {
|
---|
・BulkOnlyCSWRead関数
誤 |
return ReadFile(hUsbTest,&buffer,13,&nBytes,NULL);
|
正 |
return ReadFile(hUsbTest,buffer,13,&nBytes,NULL);
|
---|
リスト4-43(P.415)
誤 |
if (!SendAtapiCommandPacket((PUCHAR)&atapi,8)) {
|
正 |
if (!SendAtapiCommandPacket((PUCHAR)atapi,8)) {
|
---|
誤 |
if (!ReadFile(hUsbTest,&buffer,8,&nBytes,NULL) ) {
|
正 |
if (!ReadFile(hUsbTest,buffer,8,&nBytes,NULL) ) {
|
---|
リスト5-9(P.469)
誤 |
(LPVOID)&ConfigurationDescriptor,
|
正 |
(LPVOID)ConfigurationDescriptor,
|
---|
リスト5-25(P.485~486)
誤 |
UsbStorageDevice->SendAtapiRequestPacket((PVOID)&atapi,
|
正 |
UsbStorageDevice->SendAtapiRequestPacket((PVOID)atapi,
|
---|
誤 |
UsbStorageDevice->TransferData(TRUE,36,&InquiryData,NULL);
|
正 |
UsbStorageDevice->TransferData(TRUE,36,InquiryData,NULL); |
---|
誤 |
memcpy(&product,&InquiryData[16],16);
|
正 |
memcpy(product,&InquiryData[16],16);
|
---|
誤 |
DumpData((PCHAR)&InquiryData,36);
|
正 |
DumpData((PCHAR)InquiryData,36);
|
---|
リスト5-29(P.492
誤 |
(PVOID)&AtapiRequest->AtapiRequestPacket,
|
正 |
(PVOID)AtapiRequest->AtapiRequestPacket,
|
---|
リスト5-35(P.497~499)
誤 |
m_ClassCode = (CHAR *)&buffer;
|
正 |
m_ClassCode = (CHAR *)buffer;
|
---|
誤 |
m_SubClassCode = (CHAR *)&buffer;
|
正 |
m_SubClassCode = (CHAR *)buffer;
|
---|
誤 |
m_ProtocolCode = (CHAR *)&buffer;
|
正 |
m_ProtocolCode = (CHAR *)buffer;
|
---|
誤 |
m_DeviceSpeed = (CHAR *)&buffer;
|
正 |
m_DeviceSpeed = (CHAR *)buffer;
|
---|
誤 |
m_ConsoleEditor = (CHAR *)&buffer;
|
正 |
m_ConsoleEditor = (CHAR *)buffer;
|
---|
誤 |
m_ConsoleEditor = (CHAR *)&buffer;
|
正 |
m_ConsoleEditor = (CHAR *)buffer;
|
---|
リスト5-36(P.499~500)
誤 |
&RecvCapacityData);
|
正 |
RecvCapacityData);
|
---|
リスト5-37(P.501~502)
誤 |
m_RequestSenseASC = (CHAR *)&EditBoxData;
|
正 |
m_RequestSenseASC = (CHAR *)EditBoxData;
|
---|
誤 |
m_RequestSenseASCQ = (CHAR *)&EditBoxData;
|
正 |
m_RequestSenseASCQ = (CHAR *)EditBoxData;
|
---|
リスト5-40(P.507~509)
誤 |
memset(&buffer,0,128);
|
正 |
memset(buffer,0,128);
|
---|
誤 |
m_AtapiPacket = (CHAR *)&buffer;
|
正 |
m_AtapiPacket = (CHAR *)buffer;
|
---|
P.4-8-2「USBデバイスの初期化処理の実装」
本書のコードでは,USB_StartDevice関数で確保した,deviceExtension->ConfigurationAllDescriptorを解放していません。そのため,これを解放する,以下のようなコードを追加する必要があります。
※USB_DispatchPnp関数のIRP_MN_REMOVE_DEVICE処理
IoDeleteDeviceの前に,以下のコードを追加する
:
// コンフィギュレーションディスクリプタのために
// 確保したメモリを解放する
if (deviceExtension->ConfigurationAllDescriptor)
ExFreePool(deviceExtension->ConfigurationAllDescriptor);
// デバイスオブジェクトを削除する
IoDeleteDevice (DeviceObject);
:
P.リスト5-1(P.480)
リストの名前が異なります。
誤 |
CCBIStorageDeviceクラスのヘッダ
|
正 |
CBulkOnlyStorageDeviceクラスのヘッダ |
---|
P.リストA-1(P.663)ObDereferenceObjectの引数
ObDereferenceObjectの引数はオブジェクトへのポインタなので,「&」は必要ありません。以下のように修正してください(第3刷にて修正済み)。
誤 |
ObDereferenceObject(&ThreadObjectPointer);
|
正 |
ObDereferenceObject(ThreadObjectPointer);
|
---|
誤(第1刷) |
urb->UrbIsochronousTransfer.Hdr.Length = length;
|
誤(第2刷) |
urb->UrbIsochronousTransfer.Hdr.Length = UrbSize;
|
正 |
urb->UrbIsochronousTransfer.Hdr.Length = (USHORT)UrbSize;
|
---|
誤 |
urb->UrbIsochronousTransfer.Flags
|
正 |
urb->UrbIsochronousTransfer.TransferFlags
|
---|
誤 |
USBD_START_ISO_TRANSFERASAP
|
正 |
USBD_START_ISO_TRANSFER_ASAP
|
---|
誤 |
USB_CallUSBD(DeviceObject,&urb);
|
正 |
USB_CallUSBD(DeviceObject,urb);
|
---|
誤 |
ntStatus=urb.UrbHeader
|
正 |
ntStatus=urb->UrbHeader
|
---|