高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先


テクニカル Q&A


USB05 - USB Error -6911 - (kUSBNotResponding) とは
(1998 年 11 月 16 日)


Q: ときおり USB error -6911 (kUSBNotResponding) が発生します。ドキュメンテーションによれば、このエラーはデバイスのハングを意味するようです。バス上で発生した問題に関してこのエラーは何を意味するのでしょうか。また、クラスドライバの中でこのエラーを処理するにはどうすればいいですか。

A: kUSBNotRespondingErr は、Macintosh 上のホストコントローラがデータ転送を 3 回試み、その結果として ACK または NAK パケットを受信しなかったことが原因で発生します。このエラーが返される前にホストは内部的に 3 回の試行を行いますが、USB は USB 仕様書 (リビジョン 1.0、セクション 4.5.2) で説明されているように、このエラーを呼び出し元に返します。パケットレベルの観点からすると、ホストコントローラは 3 つの IN または OUT PID (パケットID) を発行し、USB 関数から応答を受信しなかったということになります。

通常、このエラーはデバイスがハングしていることが原因で発生しますが、ときおり、一時的なエラーが原因で時間を要するリクエストの処理中にこの問題が発生する場合があります (NAK の数が多いと、状況が悪化する機会も多くなります)。

ただしこの場合は問題を解決することができます。まず、USBClearPipeStallByReference 関数を使ってパイプ上のストールをクリアする必要があります。さらに、ホストとデバイスを再度同期させる必要があります (通常は、Clear_Feature または Endpoint_Stall)。

次に、Clear_Feature リクエストを送信する例を示します。なお、このコードは USB v1.1 の USB.h ヘッダーファイルの使用を前提にしています。


    pb.pbLength = sizeof(pb);
    pb.usbReference = deviceRef;
    pb.usbCompletion = yourAsnchHandlerRoutine;
    pb.usbStatus = noErr;
    pb.pbVersion = kUSBCurrentPBVersion;
    pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
    pb.usb.cntl.BRequest = kUSBRqClearFeature;
    pb.usb.cntl.WValue = 0;                   // フィーチャーセレクタ - Endpoint ストール
    pb.usb.cntl.WIndex = endpointNumber;
    pb.usbReqCount = 0;
    pb.usbBuffer = nil;
    pb.usbFlags = 0;
    err = USBDeviceRequest(pb);

使用例 1  Clear_Feature リクエストのサンプル

USBDeviceRequest を使って Clear_Feature リクエストを送信するときは、usbWIndex フィールドに endpointNumber を設定しておく必要があります。通常、endpointNumber はデバイスを構成するときに取得されます。また、USBFindNextAssociatedDescriptor 呼び出しを使って endpointNumber を取得することもできます。たとえば、出力エンドポイントには 0x01、入力エンドポイントには 0x81 のような値を設定します。 USB v1.1 以降では、usbWIndex フィールドに endpointNumber を設定するという要件を簡略化するため若干の変更がインプリメントされました。usbWIndex フィールドを設定する代わりに、kUSBAddressRequest ビットをセットして usbFlags フィールドを設定します。USB Manager v1.1 以降では、usbFlags フィールドをチェックして kUSBAddressRequest ビットがセットされているかどうかを確認し、"usb.cntl.BMRequestType" フィールドがエンドポイントに対応しているかどうかをチェックします。また、これらの要件が整っていれば、usbReference フィールドで渡されたエンドポイント参照に対応する usbWIndex フィールドに endpointNumber を書き込みます。次のサンプルコードは、USB v1.1 以降に加えられたこのような変更を具体的に示しています。なお、使用例 1 に示したコードも USB v1.1 以降とともに正常に動作します。存在する Mac OS USB のバージョンを判定するには、Gestalt セレクタ 'usbv' を使用します。


    pb.pbLength = sizeof(pb);
    pb.usbReference = endpointRef;
    pb.usbCompletion = yourAsnchHandlerRoutine;
    pb.usbStatus = noErr;
    pb.pbVersion = kUSBCurrentPBVersion;
    pb.usb.cntl.BMRequestType =
         USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
    pb.usb.cntl.BRequest = kUSBRqClearFeature;
    pb.usb.cntl.WValue = 0;         // フィーチャーセレクタ - Endpoint ストール
    pb.usbReqCount = 0;
    pb.usbBuffer = nil;
    pb.usbFlags = kUSBAddressRequest;
    err = USBDeviceRequest(pb);

使用例 2  USB 1.1 以降に対応する代替 Clear_Feature request

なお、ホストがデバイスと通信を行っているときに USB ケーブルがはずれた場合にも kUSBNotRespondingErr が発生する可能性があります。このエラーが発生したときは、Clear_Feature リクエストを送信してください。デバイスのケーブルがはずれていると、USBDeviceRequest は別の -6911 エラーを返すことになります。


-- Rich Kubota
Worldwide Developer Technical Support