この章の目次にもどる
前頁:第14章 ネットワークデバイスにもどる

第15章 USBマネージャ

15.1 USBマネージャの位置付け

USBマネージャは、USBホストコントローラに対応したドライバであり、 USBデバイスを対象とするデバイスドライバに対し、 デバイスとの通信手段を提供するものである。

15.2 USBマネージャの機能

USBマネージャは以下に示す機能を持つ。

デバイスの接続と解除の通知
デバイスの接続もしくは解除を検出し、 対応するドライバに対してランデブ呼び出しにより通知する。
デバイスに対する共通処理の実行
デバイスの接続時には、対応するドライバからのアクセスを可能とするために リセット処理、アドレスの設定、各種ディスクリプタの取得、 (必要がある場合のみ)コンフィギュレーションの設定を行う。
デバイスの解除時には、 デバイスへのアクセスを禁止するために必要な処理を行う。
デバイスとドライバの対応付け
デバイスが接続された場合、登録済みの複数のドライバに対して 接続されたデバイスが対象とするデバイスあるいはインターフェースかどうかを 問い合わせ、ドライバとの対応付けを行う。
デバイスとの通信機能
コントロール・バルク・インタラプト転送を行うための関数が用意されている。
ドライバへの各種サービス機能の提供

15.3 デバイスドライバに必要とされる機能

USBデバイスを対象とするデバイスドライバは、 通常のドライバ機能に加えて以下の機能が必要となる。

デバイスの接続・解除に伴う機能
USBデバイスは任意の時点で接続・解除が行われる。 どのような場合でも、 これらに対する処理を確実に行うことができなければならない。
対象とするデバイスかどうかを判断する機能
接続されたデバイスあるいはインターフェースが自分が対象とするものかどうかを デバイス・インターフェースディスクリプタ等を読み出して判断する機能。
対象とするデバイスの初期化機能
デバイスそのものの初期化はUSBマネージャが行うが、 ドライバが必要とするUSBデバイスの機能を利用できるようにするための設定は 各ドライバで行う必要がある。
デバイスとの通信機能
デバイスおよびインターフェースのクラスに応じ、 ディスクリプタの内容に従ってUSBデバイスとの通信を行う。

15.4 制限事項

USBマネージャの制限事項は以下の通りである。

15.5 データ定義 (usb.h)

/* イベント種別(USBマネージャ) */
#define	USB_MOUNT	1		/* デバイス接続		*/
#define	USB_UNMOUNT	2		/* デバイス切断		*/

/* 応答コード(USBマネージャ) */
#define	USB_NONE	0		/* 対象デバイスでない	*/
#define	USB_OWN		1		/* 対象デバイス		*/

/* USBデバイスリクエスト(USB規格) */
typedef	struct	{
	UB	bmRequestType;		/* 要求する対象の設定	*/
	UB	bRequest;		/* 要求コード		*/
	UH	wValue;			/* 設定する値		*/
	UH	wIndex;			/* 文字列index等の指定	*/
	UH	wLength;		/* 転送長		*/
} usbDeviceRequest;

/* bRequest:標準要求コード(USB規格) */
#define	USB_GET_STATUS		0
#define	USB_CLEAR_FEATURE	1
#define	USB_SET_FEATURE		3
#define	USB_SET_ADDRESS		5
#define	USB_GET_DESCRIPTOR	6
#define	USB_SET_DESCRIPTOR	7
#define	USB_GET_CONFIGURATION	8
#define	USB_SET_CONFIGURATION	9
#define	USB_GET_INTERFACE	10
#define	USB_SET_INTERFACE	11
#define	USB_SYNCH_FRAME		12

/* bmRequestType(USB規格) */
#define	bmR_DEVICE	0x00
#define	bmR_INTERFACE	0x01
#define	bmR_ENDPOINT	0x02
#define	bmR_OTHER	0x03

#define	bmR_STANDARD	0x00
#define	bmR_CLASS	0x20
#define	bmR_VENDOR	0x40

#define	bmR_OUT		0x00
#define	bmR_IN		0x80

/* bDescriptorType:ディスクリプタ種別(USB規格) */
#define	USB_DEVICE		1
#define	USB_CONFIGURATION	2
#define	USB_STRING		3
#define	USB_INTERFACE		4
#define	USB_ENDPOINT		5

/* USB デバイスディスクリプタ(USB規格) */
typedef	struct	{
	UB	bLength;		/* ディスクリプタ長	*/
	UB	bDescriptorType;	/* Device Descriptor(1)	*/
	UH	bcdUSB;			/* USB規格のバージョン	*/
	UB	bDeviceClass;		/* Device Class		*/
	UB	bDeviceSubClass;	/* Device SubClass	*/
	UB	bDeviceProtocol;	/* Device Protocol	*/
	UB	bMaxPacketSize0;	/* pipe#0のPacketSize	*/
	UH	idVendor;		/* 製造元ID(USB-IF)	*/
	UH	idProduct;		/* 製品ID		*/
	UH	bcdDevice;		/* 製品のバージョン	*/
	UB	iManufacturer;		/* 文字列index (Mfg.)	*/
	UB	iProduct;		/* 文字列index (Prod.)	*/
	UB	iSerialNumber;		/* 文字列index (Ser#)	*/
	UB	bNumConfigurations;	/* Configurationの数	*/
} usbDeviceDescriptor;

/* USB コンフィギュレーションディスクリプタ(USB規格) */
typedef	struct	{
	UB	bLength;		/* ディスクリプタ長	*/
	UB	bDescriptorType;	/* Cfg. Descriptor(2)	*/
	UH	wTotalLength;		/* Cfg+other desc size	*/
	UB	bNumInterfaces;		/* Interfaceの数	*/
	UB	bConfigurationValue;	/* このCfg.のID		*/
	UB	iConfiguration;		/* 文字列index (Cfg.)	*/
	UB	bmAttributes;		/* 電源などに関する属性	*/
	UB	MaxPower;		/* 消費電流(×2 mA)	*/
} usbConfigurationDescriptor;

/* USB インタフェースディスクリプタ(USB規格) */
typedef	struct	{
	UB	bLength;		/* ディスクリプタ長	*/
	UB	bDescriptorType;	/* I/F Descriptor(4)	*/
	UB	bInterfaceNumber;	/* このInterfaceのID	*/
	UB	bAlternateSetting;	/* 代替設定のID		*/
	UB	bNumEndpoints;		/* エンドポイントの数	*/
	UB	bInterfaceClass;	/* Interface Class	*/
	UB	bInterfaceSubClass;	/* Interface SubClass	*/
	UB	bInterfaceProtocol;	/* Interface Protocol	*/
	UB	iInterface;		/* 文字列index (I/F)	*/
} usbInterfaceDescriptor;

/* USB エンドポイントディスクリプタ(USB規格) */
typedef	struct	{
	UB	bLength;		/* ディスクリプタ長	*/
	UB	bDescriptorType;	/* E/P Descriptor(5)	*/
	UB	bEndpointAddress;	/* endpoint address	*/
	UB	bmAttributes;		/* 転送形式(Ctrl/Iso..)	*/
	UH	wMaxPacketSize;		/* パケットサイズ	*/
	UB	bInterval;		/* Iso/Int 転送周期(ms)	*/
} usbEndpointDescriptor;

/* エンドポイントディスクリプタのbmAttributesの定義(USB規格)	*/
#define	USB_CONTROL	0
#define	USB_ISOCHRONOUS	1
#define	USB_BULK	2
#define	USB_INTERRUPT	3

/* USB ストリングディスクリプタ(USB規格) */
typedef	struct	{
	UB	bLength;		/* ディスクリプタ長	*/
	UB	bDescriptorType;	/* Str. Descriptor(3)	*/
	UH	bString[1];		/* 文字列 (Unicode)	*/
} usbStringDescriptor;

/* USBイベント指定用構造体(USBマネージャ) */
typedef	struct	{
	UB	bClass;		/* Device/Interface Class */
	UB	bSubClass;	/* Device/Interface SubClass */
	UB	bProtocol;	/* Device/Interface Protocol */
	UB	mask;		/* bClass/bSubClass/bProtocol/devidの選択 */
} usbEventPattern;

/* nowaitモード時の応答メッセージ(USBマネージャ) */
typedef	struct	{
    W	pid;			/* pipe ID */
    W	datacnt;		/* データ数 */
    W	error;			/* エラーコード */
}	usbMsg;    

/* maskの値(USBマネージャ) */
#define	EVENT_CLASS	0x01
#define	EVENT_SUBCLASS	0x02
#define	EVENT_PROTOCOL	0x04
#define	EVENT_ANY	0x08

/* エラーコード (USBマネージャ) */
#define	USB_OK			 (EC_OK    << 16)
#define	USB_ERR_BUSY		((EC_BUSY  << 16) |  0)
#define	USB_ERR_PAR		((EC_PAR   << 16) |  0)
#define	USB_ERR_DEVICE		((EC_PAR   << 16) |  1)
#define	USB_ERR_INTERFACE	((EC_PAR   << 16) |  2)
#define	USB_ERR_ENDPOINT	((EC_PAR   << 16) |  3)
#define	USB_ERR_POWER		((EC_LIMIT << 16) |  0)
#define	USB_ERR_REQUEST		((EC_DEV   << 16) |  0)
#define	USB_ERR_SYSTEM		((EC_SYS   << 16) |  0)
#define	USB_ERR_NOMEM		((EC_NOMEM << 16) |  0)
#define	USB_ERR_STALL		((EC_IO    << 16) |  2)
#define	USB_ERR_ABORT		((EC_IO    << 16) |  3)
#define	USB_ERR_IO_NAK		((EC_IO    << 16) |  6)
#define	USB_ERR_IO_SHORT	((EC_IO    << 16) |  7)
#define	USB_ERR_IO_BUFERR	((EC_IO    << 16) |  9)
#define	USB_ERR_IO_BABBLE	((EC_IO    << 16) | 10)
#define	USB_ERR_IO_CRC		((EC_IO    << 16) | 11)
#define	USB_ERR_IO_BITSTUFF	((EC_IO    << 16) | 12)
#define	USB_ERR_IO_NORESP	((EC_IO    << 16) | 13)

/* usbIoPipe()での指定用(USBマネージャ) */
#define	USB_WAIT	0x00
#define	USB_SHORTNG	0x00

#define USB_NOWAIT      0x01
#define USB_SHORTOK     0x02

/* usbGetHubInfo()で使用する構造体(USBマネージャ) */
/* hub status構造体(USBマネージャ) */
typedef	union	{
    struct	{
	UH	level:3;	/* hubの段数 */
	UH	self_power:1;	/* self powered hubなら1 */
	UH	reserved:12;
    }	bmStatus;
    UH	status;
}	usbHubStatus;

/* device status (USBマネージャ) */
#define	PS_PORT_CONNECTION	0x0001
#define	PS_PORT_ENABLE		0x0002
#define	PS_PORT_SUSPEND		0x0004
#define	PS_PORT_OVER_CURRENT	0x0008
#define	PS_PORT_RESET		0x0010

#define	PS_PORT_POWER		0x0100
#define	PS_PORT_LOW_SPEED	0x0200

15.6 USBイベント

登録したデバイスドライバに対しては、 デバイスドライバへの要求受け付けランデブポートに対して USBイベントの呼び出しが行われる。 このイベントは、デバイス単位あるいはインターフェース単位で得ることができる。

デバイスドライバは、 どのような時点でもUSBイベント呼び出しを速やかに受け付け、 対応した処理を行った後応答を戻さなくてはならない。

USBイベント呼び出しは、呼び出しが行われてから 30秒以内に受け付けられなければならない。受け付けられなかった場合は、 そのデバイスドライバはデバイスを使用しないものとみなす。

USBイベント呼び出し・応答は、 通常のデバイス要求・応答のデータ形式を使用して以下の内容で行われる。

呼び出し(デバイス接続時の要求):
DevReq:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     0
	cmd.cmd     = DC_USBEVENT
	datano      = USB_MOUNT
	datacnt     (bit 7〜 0) bDeviceClassの値
	            (bit 8〜15) bDeviceSubClassの値
	            (bit16〜23) bDeviceProtocolの値
	taskid      予約(0)
	memptr      予約(0)
応答(デバイス接続時の要求)
DevRsp:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     0
	cmd.cmd     = DC_USBEVENT
	datano      予約
	datacnt     予約
	error       応答コード(USB_OWN/USB_NONE)
呼び出し(デバイス解除時の要求):
DevReq:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     0
	cmd.cmd     = DC_USBEVENT
	datano      = USB_UNMOUNT
	datacnt     予約(0)
	taskid      予約(0)
	memptr      予約(0)
応答(デバイス解除時の要求)
DevRspに設定すべき値は無い。rpl_rdv()で応答するだけで良い。
呼び出し(インターフェース接続時の要求)
DevReq:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     1
	            (bit 8〜15) インターフェースディスクリプタのbInterfaceNumber
	cmd.cmd     = DC_USBEVENT
	datano      = USB_MOUNT
	datacnt     (bit 7〜 0) bInterfaceClassの値
	            (bit 8〜15) bInterfaceSubClassの値
	            (bit16〜23) bInterfaceProtocolの値
	taskid      予約(0)
	memptr      予約(0)
応答(インターフェース接続時の要求)
DevRsp:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     1
	            (bit 8〜15) インターフェースディスクリプタのbInterfaceNumber
	cmd.cmd     = DC_USBEVENT
	datano      予約
	datacnt     予約
	error       応答コード(USB_OWN/USB_NONE)
呼び出し(インターフェース解除時の要求):
DevReq:	devid       (bit 6〜 0) 接続されたデバイスのアドレス
	            (bit 7)     1
	            (bit 8〜15) インターフェースディスクリプタのbInterfaceNumber
	cmd.cmd     = DC_USBEVENT
	datano      = USB_UNMOUNT
	datacnt     予約(0)
	taskid      予約(0)
	memptr      予約(0)
応答(インターフェース解除時の要求)
DevRspに設定すべき値は無い。rpl_rdv()で応答するだけで良い。

USB_MOUNTイベント(デバイス・インターフェース接続)

USBデバイスが接続された時点で登録されているデバイスドライバのうち、 以下の条件を満たすドライバに対して順番に発行される。 ドライバからの応答コードとしてUSB_OWNが得られた場合、 そのドライバがデバイスに対応付けられて、イベントの発行が終了する。

デバイスに対応付けられるドライバが存在しない場合、 USBマネージャはコンフィギュレーションインデックスが0の内容で デバイスのコンフィギュレーションを行う。 そしてデバイスに対応付けられるドライバの検索を行うのと同様に インターフェースに対応するドライバの検索を行う。

デバイス・インターフェース接続イベントを発行する順番は ドライバを登録した順番と逆順に発行される。 つまり、一番最近に登録されたドライバが最初にイベントを受け取ることになる。

デバイスドライバの登録時点で既にデバイスが接続されており、 そのデバイスがまだドライバに対応付けられていない場合も USB_MOUNTイベントが発生する。

USB_MOUNTイベントを受け取ったドライバは、 そのデバイスあるいはインターフェースが自分が対象としているものかどうかを イベント呼び出しで得られるデバイス・インターフェースクラスや usbDescriptorDevice()等で得られるディスクリプタを使用して チェックする。

チェックの結果、対象とするデバイスでない場合は USB_NONEの応答コードを戻し、これ以降は そのデバイスに対するアクセスを行わないこと。

チェックの結果、対象とするデバイスである場合はUSB_OWNの 応答コードを戻す。 応答コードを戻すまでの間に、デバイスのコンフィギュレーション (これはデバイスに対応付けられるドライバの場合のみ必要となる)や、 ディスクリプタの解釈を行い、デバイスとの通信準備を行っても良い。

USB_UNMOUNTイベント(デバイス・インターフェース解除)

USBデバイスが解除された時点で、そのデバイスおよびインターフェースに 対応付けられたドライバに対してUSB_UNMOUNTイベントが発行される。

USB_UNMOUNTイベントを受けたドライバは 対象とするデバイスあるいはインターフェースが解除されたことに対応する 処理を行い、応答を戻す。 このイベントに対する応答コードは意味を持たない。
デバイスが解除されるとデバイスとドライバとの対応付けは解除され、 ドライバのデバイスに対する操作が禁止される。

サスペンド・レジューム処理

サスペンドに移行する際は、USBマネージャはデバイスの接続を解除する。 よってこの時は、USBデバイスを使用しているデバイスドライバに対して デバイス・インターフェース解除イベントが発生し、 サスペンド中はデバイスが存在しない状態となる。

逆にレジュームが行われる際は、USBマネージャはデバイスの接続を行う。 よって、USBデバイスを使用しているデバイスドライバに対しては デバイス・インターフェース接続イベントが発生する。

15.7 USBマネージャシステムコール

USBマネージャは、デバイスドライバに対して 以下のサービスを拡張システムコールとして提供する。

エラーコードの説明の中にあるUSB_ERR_IO_*は、 USBデバイスとの通信中に発生するエラーである。 このエラーに関する説明は次項で行っている。

usbRequestDevice
 
デバイスリクエストを発行

【形式】

ERR	usbRequestDevice(W did, UB *request, UB *data, W len, W *rlen)

【パラメータ】

didデバイスのアドレス
requestデバイスに対して送信するデバイスリクエストのポインタ
data送受信するデータを格納するメモリ領域の先頭ポインタ
len送受信するデータの大きさ
rlen実際に送受信を行ったデータの大きさを格納する領域のポインタ

【リターン値】

= 0 (USB_OK)デバイスリクエストの発行に成功した
< 0エラー(エラーコード)

【解説】

デバイスに対して、各種デバイスリクエストを発行する。 ただし、デバイスに対してデータを送信するような標準デバイスリクエスト (bmRequestTypeのbit5, 6, 7が全て0であるもの)は発行できない。

この関数は、デバイスのオープン・クローズに関係なく使用可能である。 同一デバイスに対するリクエストを複数のタスクから発行することが できるが、デバイスに対して送られるリクエストの順番は先着順である。 なお、複数のインターフェースを持つようなデバイスの場合、 複数のドライバが同一デバイスに対してリクエストを行うことがあるので リクエストの内容や順番に注意する必要がある。

ショートパケット(要求したデータ長より短いデータを受信した場合) による中断はエラーとならない。 よって、実際に転送を行ったデータ長を確認するのが望ましい。

デバイスリクエストの発行中は待ち状態となる。

dataにはNULLを指定することができるが,その際のlenは0を指定すること。 dataにNULLを指定した状態でlenが0以外の場合の動作は保証しない。

lenに指定できる値は,4088(4096 - デバイスリクエストの大きさ(8)) バイトが上限となる。

なお、マネージャ内部でlenで指定した値をwLengthとして設定するため、 デバイスリクエストのwLengthを指定する必要は無い。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
USB_ERR_REQUEST発行できないデバイスリクエストを発行しようとした
USB_ERR_PARrequestがNULLである
usbDescriptorDevice
usbDescriptorInterface
usbDescriptorEndpoint
 
デバイス/インターフェース/エンドポイントディスクリプタの取得

【形式】

ERR	usbDescriptorDevice(W did, UB *data, W len, W *rlen)
ERR	usbDescriptorInterface(W iid, UB *data, W len, W *rlen)
ERR	usbDescriptorEndpoint(W pid, UB *data, W len, W *rlen)

【パラメータ】

didデバイスのアドレス(usbDescriptorDevice())
iidインターフェースID(usbDescriptorInterface())
pidパイプID(usbDescriptorPipe())
data取得するデータを格納するメモリ領域の先頭ポインタ
len取得するデータの大きさ
rlenディスクリプタの大きさを格納する領域のポインタ

【リターン値】

= 0 (USB_OK)ディスクリプタの取得に成功した
< 0エラー(エラーコード)

【解説】

(usbDescriptorDevice()) didで指定したデバイスに含まれる、デバイスディスクリプタと コンフィギュレーションディスクリプタ (これにはインターフェースディスクリプタや エンドポイントディスクリプタ、各種クラスディスクリプタが含まれる) およびデバイスディスクリプタのiProductで示される ストリングディスクリプタを取得する。

(usbDescriptorInterface(), usbDescriptorEndpoint()) iidもしくはpidで指定したインターフェースもしくは エンドポイント(パイプ)のディスクリプタを取得する。 クラスディスクリプタが後に続いている場合は、それも一緒に取得できる。

この関数は、オープン・クローズに関係なく使用することができる。 usbRequestDevice()でインターフェース番号やエンドポイントアドレスが 必要になった場合、この関数で取得したディスクリプタの情報を 使用すれば良い。

この関数はデバイスに対する通信を行わず、USBマネージャ側が デバイス接続時に取得した情報をコピーするだけである。 使用する際は、data=NULL, len=0として呼び出し、rlenに得られた ディスクリプタサイズを使って十分な量のメモリを確保してから 再度呼び出すことになるだろう。

USB規格に定められた各種ディスクリプタを、 include/driver/usb.h中に定義している。 詳細については、USB 1.1の規格書を参照すること。

【エラーコード】

USB_ERR_DEVICEdidが不正(didで指定したデバイスは存在しない)
USB_ERR_INTERFACEiidが不正(iidで指定したインターフェースは存在しない)
USB_ERR_ENDPOINT pidが不正(pidで指定したエンドポイントは存在しない)
usbConfigDevice
 
デバイスのコンフィギュレーションの設定・取得

【形式】

WERR	usbConfigDevice(W did, W cfg)

【パラメータ】

didデバイスのアドレス
cfg0〜255コンフィギュレーションの選択(標準デバイスリクエストのSET_CONFIGURATIONを発行する)
-1現在設定されているコンフィギュレーションの取得(標準デバイスリクエストのGET_CONFIGURATIONを発行する)

【リターン値】

0〜255コンフィギュレーションの設定に成功した(cfgが0〜255の場合)
現在設定されているコンフィギュレーション(cfgが-1の場合)
< 0エラー(エラーコード)

【解説】

デバイスに対するコンフィギュレーションを行い、 使用するインターフェースを決定する。 また、現在設定されているコンフィギュレーションを デバイスから取り出すこともできる。

デバイスに属している全てのインターフェースが クローズの状態でないと実行できない。 cfg=0の場合、デバイスはコンフィギュレーションされていない状態になる。

usbOpenDeivce()でオープンしたばかりのデバイスは アドレスが割り振られただけの状態なので、 必ずこの関数でコンフィギュレーションを選択し、 使用するインターフェースを決定する必要がある。 使用するインターフェースが決定しても、 usbRegistInterface()で登録を行ったドライバに対して イベントが起こることはない。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
USB_ERR_BUSYクローズしていないインターフェースが存在している
USB_ERR_INTERFACE指定したコンフィギュレーションは存在しない
USB_ERR_POWERハブの電流容量不足のため、コンフィギュレーションが設定できない
USB_ERR_PARcfgの値が-1〜255以外である
usbConfigInterface
 
インターフェースの代替設定(alternate setting)の設定・取得

【形式】

WERR	usbConfigInterface(W iid, W alt)

【パラメータ】

iidインターフェースID
alt0〜255インターフェースの代替設定を選択する(SET_INTERFACEを発行する)
-1現在選択されている代替設定を取得する(GET_INTERFACEを発行する)

【リターン値】

0〜255代替設定を行った(altが0〜255の場合)
現在設定されている代替設定(altが-1の場合)
< 0エラー(エラーコード)

【解説】

デバイスのインターフェースに対し、 代替設定(alternate setting)を設定する。 また、インターフェースがどの設定を現在使用しているかという情報を 取り出すこともできる。

全てのパイプがクローズの状態でないと実行できない。

オープンしたばかりのデバイスは代替設定に0が指定された状態になっている。 主にプリンタデバイスのような、複数の代替設定を持つデバイスで使用する。

【エラーコード】

USB_ERR_DEVICEデバイスへの操作が禁止されている(デバイスがクローズされている)
USB_ERR_INTERFACEiidが不正(インターフェースが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
USB_ERR_BUSYクローズしていないパイプが存在している
USB_ERR_ENDPOINT指定した代替設定は存在しない
USB_ERR_PARaltの値が-1〜255以外である
usbStallPipe
 
エンドポイントのストールの設定・解除

【形式】

WERR	usbStallPipe(W pid, W stl)

【パラメータ】

pidパイプID(usbOpenPipe()で得る)
stl1SET_FEATURE(ENDPOINT_STALL)を発行する
0CLEAR_FEATURE(ENDPOINT_STALL)を発行する
-1GET_STATUS(ENDPOINT)を発行する
2SET_FEATURE(ENDPOINT_STALL)を発行した後、CLEAR_FEATURE(ENDPOINT_STALL)を発行する

【リターン値】

> 0エンドポイントの設定に成功した(stlが0, 1, 2の場合)
エンドポイントのステータス(stlが-1の場合)
< 0エラー(エラーコード)

【解説】

エンドポイントに対し、STALLの状態を設定・取得する。

USBではデータ転送を行う際、データの順番をトグルビット(toggle bit) という0と1の値を使用して決めている。 この値がデバイス側とホスト側で異なっている場合、 データの転送は正常に行われない。 このビットを初期化する目的でCLEAR_FEATURE(ENDPOINT_STALL)を 発行することがある。

【エラーコード】

USB_ERR_DEVICEデバイスへの操作が禁止されている
USB_ERR_INTERFACEインターフェースへの操作が禁止されている
USB_ERR_ENDPOINTpidが不正(パイプが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
USB_ERR_PARstlが -1, 0, 1, 2 以外である
usbSyncPipe
 
エンドポイントの同期

【形式】

WERR	usbSyncPipe(W pid)

【パラメータ】

pidパイプID(usbOpenPipe()で得る)

【リターン値】

>= 0デバイスが返してくるフレーム番号
< 0エラー(エラーコード)

【解説】

エンドポイントに対し、USB標準デバイスリクエストのSYNCH_FRAMEを 発行する。主にアイソクロナス転送を使用するパイプで使用する。

【エラーコード】

USB_ERR_DEVICEデバイスへの操作が禁止されている
USB_ERR_INTERFACEインターフェースへの操作が禁止されている
USB_ERR_ENDPOINTpidが不正(パイプが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
usbOpenDevice
 
デバイスのオープン

【形式】

ERR	usbOpenDevice(W did)

【パラメータ】

didデバイスのアドレス(デバイス接続時のイベントで取得できる)

【リターン値】

> 0デバイスのアドレス
< 0エラー(エラーコード)

【解説】

デバイスに対する操作の開始を宣言する。 デバイスの多重オープンはできない。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
USB_ERR_BUSYデバイスは既にオープンされている
usbCloseDevice
 
デバイスのクローズ

【形式】

ERR	usbCloseDevice(W did)

【パラメータ】

didデバイスのアドレス

【リターン値】

= 0 (USB_OK)デバイスをクローズした
< 0エラー(エラーコード)

【解説】

デバイスに対する操作の終了を宣言する。 デバイスをクローズすると、そのデバイスに属しているインターフェースや パイプなどもクローズされる。

オープンしたタスク以外からのタスクからもクローズを行うことができる。 よって、didに誤った値を指定しないように注意すること。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
usbOpenInterface
 
インターフェースのオープン

【形式】

WERR	usbOpenInterface(W did, W ifno)

【パラメータ】

didデバイスのアドレス(イベントから取得できる)
ifnoインターフェース番号(インターフェースディスクリプタのbInterfaceNumber)

【リターン値】

>= 0インターフェースID(iid)
< 0エラー(エラーコード)

【解説】

インターフェースに対する操作の開始を宣言する。 インターフェースに対する多重オープンはできない。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しないか、操作が禁止されている)
USB_ERR_INTERFACEifnoが不正(指定した番号のインターフェースは存在しない)
USB_ERR_BUSYインターフェースは既にオープンされている
USB_ERR_NOMEMこれ以上インターフェースをオープンすることができない
USB_ERR_SYSTEMUSBマネージャの内部エラー
usbCloseInterface
 
インターフェースのクローズ

【形式】

ERR	usbCloseInterface(W iid)

【パラメータ】

iidインターフェースID

【リターン値】

= 0 (USB_OK)インターフェースをクローズした
< 0エラー(エラーコード)

【解説】

インターフェースに対する操作の終了を宣言する。 インターフェースをクローズすると、そのインターフェースに属している エンドポイントは全てクローズされる。

オープンしたタスク以外からのタスクからもクローズを行うことができる。 よって、iidに誤った値を指定しないように注意すること。

【エラーコード】

USB_ERR_INTERFACEiidが不正(iidで指定したインターフェースは存在しない)
usbOpenPipe
 
エンドポイントのオープン(パイプの作成)

【形式】

WERR	usbOpenPipe(W iid, W epadr, usbIoMode mode, W mbfid)

【パラメータ】

iidインターフェースID(usbOpenInterface()で得る)
epadr操作の対象となるエンドポイントアドレス(エンドポイントディスクリプタのbEndpointAddress)
mode動作モード [USB_NOWAIT] | [USB_SHORTOK]
USB_NOWAITpipeへのread/write中、転送の完結を待たない(nowait mode)。指定しない場合はpipeへのread/writeの完結を待つ (wait mode)。
USB_SHORTOKusbIoPipe()での転送中、ショートパケット(要求したデータ長よりも短いデータ長で転送が終了した場合)を検出してもエラーとしない。指定しない場合はショートパケットを検出した場合にUSB_ERR_SHORTのエラーを返すようになる。
mbfidnowaitモード使用時に、ステータスを受け取るためのメッセージバッファID(負の値を指定した場合はステータスの受け取りを行わない)

【リターン値】

>= 0パイプをオープンした(パイプID)
< 0エラー(エラーコード)

【解説】

パイプ(エンドポイントに対する通信路)を作成し、 指定したエンドポイントに対する操作の開始を宣言する。 エンドポイントに対する多重オープンはできない。

nowaitモードを使用できるのはインタラプト転送を使用する エンドポイントに対してのみである。 それ以外の転送モードを使用するパイプでは指定しないこと。

waitモードを指定した場合、mbfidの値は無視される。

【エラーコード】

USB_ERR_DEVICEデバイスへの操作が禁止されている
USB_ERR_INTERFACEiidが不正(インターフェースが存在しない)
USB_ERR_ENDPOINTepadrが不正(指定したアドレスのエンドポイントは存在しない)
USB_ERR_BUSYパイプは既にオープンされている
USB_ERR_NOMEMこれ以上パイプをオープンすることができない
usbClosePipe
 
エンドポイントのクローズ(パイプの消去)

【形式】

ERR	usbClosePipe(W pid)

【パラメータ】

pidパイプID

【リターン値】

= 0 (USB_OK)パイプをクローズした
< 0エラー(エラーコード)

【解説】

エンドポイントに対する操作の終了を宣言する。 パイプを使用して行われている通信は全てキャンセルされる。

内部でusbCancelPipe()を発行するため、キャンセルが完了するまで待つ。

オープンしたタスク以外からのタスクからもクローズを行うことができる。 よって、pidに誤った値を指定しないように注意すること。

【エラーコード】

USB_ERR_ENDPOINTpidが不正(そのパイプは存在しない)
usbIoPipe
 
エンドポイントに対するデータの送受信

【形式】

ERR	usbIoPipe(W pid, UB *buf, W len, W *rlen)

【パラメータ】

pidパイプID
buf転送するデータの先頭ポインタ
len転送するデータの大きさ
rlen実際に転送を行ったデータ長を格納する領域のポインタ

【リターン値】

= 0 (USB_OK)転送は成功した
< 0エラー(エラーコード)

【解説】

パイプIDで指定したパイプに、 usbOpenPipe()で指定した転送方向でデータを流す。

usbOpenPipe()でnowaitモードを指定した場合を除き、 動作が完了するまでこの関数は終了しない。

nowaitモードの場合、rlenには0が格納される。 また、以下の点に注意する必要がある。

エンドポイントからデータを受信する際、datにNULLを指定するとlenで 指定したバイト数だけデータを読み捨てることができる。ただし、 この場合はlenをエンドポイントのwMaxPacketSizeの倍数にしないと 読み捨てた後のデータ転送が行えなくなってしまう。

送信する場合はdatにNULLを指定してはならない。

【エラーコード】

USB_ERR_DEVICEデバイスへの操作が禁止されている
USB_ERR_INTERFACEインターフェースへの操作が禁止されている
USB_ERR_ENDPOINT pidが不正(パイプが存在しない)
USB_ERR_STALLSTALLが発生した
USB_ERR_ABORT通信がキャンセルされた
USB_ERR_IO_*入出力エラーが発生した
USB_ERR_BUSY送信要求を受け付けることができない(帯域が不足した)
usbCancelDevice
usbCancelInterface
usbCancelPipe
 
通信のキャンセル(デバイス・インターフェース・エンドポイント単位)

【形式】

ERR	usbCancelDevice(W did)
ERR	usbCancelInterface(W iid)
ERR	usbCancelPipe(W pid)

【パラメータ】

didデバイスのアドレス(usbCancelDevice()の場合)
iidインターフェースID(usbCancelInterface()の場合)
pidパイプID(usbCancelPipe()の場合)

【リターン値】

= 0 (USB_OK)キャンセルに成功した
< 0エラー(エラーコード)

【解説】

usbCancelPipe()は、pidで指定したパイプを使用して行われている通信をキャンセルする。

usbCancelInterface()はiidで指定した インターフェースに含まれる全てのパイプの通信をキャンセルする。

usbCancelDevice()はdidで指定したデバイスに含まれる 全てのパイプの通信をキャンセルする。

waitモードのusbIoPipe()で通信を行っているタスクでは、 USB_ERR_ABORTのエラーコードが返る。 nowaitモードの場合、usbOpenPipe()で指定したメッセージバッファに メッセージが格納され、そのエラーコードはUSB_ERR_ABORTとなる。

また、対象とするパイプのwait/nowaitモードに関わらず、この関数は パイプの通信が中断されるまで待ち状態となる。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
USB_ERR_INTERFACEiidが不正(インターフェースが存在しない)
USB_ERR_ENDPOINTpidが不正(パイプが存在しない)
usbAlivePipe
 
パイプが使用できるかをチェック

【形式】

ERR	usbAlivePipe(W pid)

【パラメータ】

pidパイプID

【リターン値】

= 0 (USB_OK)パイプは使用可能である
< 0エラー(エラーコード)

【解説】

pidで指定したパイプが使用可能であるかどうかをチェックする。 通信が中断された際などで、それ以降のアクセスを行うことが できるかどうかを知る目的で使用される。

【エラーコード】

USB_ERR_DEVICEデバイスは存在しない
USB_ERR_INTERFACEインターフェースは存在しない
USB_ERR_ENDPOINTパイプは存在しない
usbRegistDevice
 
デバイス接続・解除イベントの通知先を登録

【形式】

ERR	usbRegistDevice(ID portid, usbEventPattern *pattern)

【パラメータ】

portidデバイスイベント受付用ランデブポートID
patternイベント通知条件のポインタ(pattern = NULLの場合は登録の解除になり、これ以降は指定したポートに対するイベントの通知を行わなくなる)

【リターン値】

= 0 (USB_OK)登録に成功した
< 0エラー(エラーコード)

【解説】

USBデバイスの接続・解除時に発生するイベント(デバイスイベント)の 送り先を指定する。デバイスイベントの受信条件はpatternで指定する。 一つのポートに複数の条件を登録することが可能だが、 消去する場合はポートに関連付けられた全ての条件が消去される。

通常は、後述のusbRegistInterface()を使用して インターフェース単位のドライバを作成する方が簡単だと思われる。

usbEventPattern構造体は以下の形をとる。この構造体は、後述の usbRegistInterface()でも使用する。

	typedef	struct	{
		UB	bClass;
		UB	bSubClass;
		UB	bProtocol;
		UB	mask;
	}	usbEventPattern;

usbRegistDevice()を使用する場合、 bClass, bSubClass, bProtocolの値はデバイスディスクリプタの bDeviceClass, bDeviceSubClass, bDeviceProtocolに対応する。 usbRegistInterface()を使用する場合、 bClass, bSubClass, bProtocolの値はインターフェースディスクリプタの bInterfaceClass, bInterfaceSubClass, bInterfaceProcotolに対応する。

maskは以下の4種類がある。EVENT_ANYを指定するか、または EVENT_CLASS, EVENT_SUBCLASS, EVENT_PROTOCOLの3つの組み合せで 対象とするデバイスに対するイベントを発生させる (ただし、maskに0は指定できない)。

EVENT_ANYデバイス・インターフェースの種類は問わない
EVENT_CLASSbClassを比較対象とする
EVENT_SUBCLASSbSubClassを比較対象とする
EVENT_PROTOCOLbProtocolを比較対象とする

【エラーコード】

USB_ERR_DEVICE指定したポートに対するデバイス接続イベントの登録が行われていない(pattern = NULLの時に発生)
USB_ERR_NOMEMこれ以上デバイスイベントを登録できない
USB_ERR_PARpattern.maskが0である
usbRegistInterface
 
インターフェース接続・解除イベントの通知先を登録

【形式】

ERR	usbRegistInterface(ID portid, usbEventPattern *pattern)

【パラメータ】

portidデバイスイベント受付用ランデブポートID
patternイベント通知条件のポインタ(pattern = NULLの場合は登録の解除になり、これ以降は指定したポートに対するイベントの通知を行わなくなる)

【リターン値】

= 0 (USB_OK)登録に成功した
< 0エラー(エラーコード)

【解説】

USBデバイスの接続が行われたものの、デバイスに対応するドライバが 存在しない場合はUSBマネージャ側でコンフィギュレーションを行う。 この際に使用されるコンフィギュレーションは、一番最初に読み出せる (コンフィギュレーションインデックスが0の) コンフィギュレーションディスクリプタを使用する。

USBマネージャによるコンフィギュレーションが終了し、 使用可能なインターフェースが決定した時に発生するイベント (インターフェースイベント)の送り先を指定する。 インターフェースイベントの受信条件はpatternで指定する。 なお、インターフェースクラスが合致していても、 bAlternateSettingが0でない場合はイベントの発生対象とはならない。

usbEventPattern構造体に関する説明は、 usbRegistDevice()の項にある。

【エラーコード】

USB_ERR_INTERFACE指定したポートに対するインターフェース接続イベントの登録が行われていない(pattern = NULLの時に発生)
USB_ERR_NOMEMこれ以上インターフェースイベントを登録できない
USB_ERR_PARpattern.maskが0である
usbSuspend
usbResume
 
USBマネージャのサスペンド・レジューム制御

【形式】

VOID	usbSuspend(Bool start)
VOID	usbResume(Bool start)

【パラメータ】

startTrueサスペンド移行処理を開始する(usbSuspend())
何もしない(usbResume())
False何もしない(usbSuspend())
レジューム移行処理を開始する(usbResume())

【リターン値】

なし

【解説】

システムのサスペンド・レジューム処理をUSBマネージャに通知する。

サスペンド中はデバイス接続・解除を検出することができなくなるため サスペンド中はデバイスを解除し、レジューム時にデバイスを接続する 処理を行っている。

よって、サスペンド処理中にデバイス・インターフェース解除イベントが、 レジューム処理中にデバイス・インターフェース接続イベントが発生する。 (デバイスドライバは、これらのイベントを受信できるよう、また 受信した後に然るべき措置をとれるようにしておく必要がある)

usbSuspend()もしくはusbResume()の どちらかの処理が終了するまでもう片方の処理を行った場合の動作は 保証しない。

usbResetDevice
 
デバイスのリセット(ソフトウェアによるデバイスの切り離し・再接続)

【形式】

ERR   usbResetDevice(W did)

【パラメータ】

didデバイスのアドレス

【リターン値】

= 0 (USB_OK)デバイスをリセットした
< 0エラー

【解説】

didで指定したデバイスをリセットする。

デバイスを一旦解除し、再度接続したの同じ効果があり、 リセットの対象になったデバイスに対応付けられているドライバには デバイス解除イベント→デバイス接続イベントの順にイベントが 送られる。

リセットを行った後のデバイスのアドレスはリセットを行う前と 同じとは限らない。 また、デバイスのリセットが完了するまでこの関数が待つことは無い。

【エラーコード】

USB_ERR_DEVICEdidが不正(デバイスが存在しない)
usbGetHubInfo
 
デバイス接続情報の取得

【形式】

WERR	usbGetHubInfo(W *report, W size)

【パラメータ】

report接続情報を格納する領域のポインタ
size接続情報を格納する領域の大きさ

【リターン値】

>= 0接続情報のサイズ(バイト)
< 0エラー

【解説】

USBハブデバイスの接続情報を取得する。 reportのフォーマットは以下の通りである。

	 bit 31                         16  15                           0
	+0 [[    hub deviceのアドレス     ][    hub deviceのステータス    ]]
	 bit 31                                    8  7                  0
	+4 [[               未使用(0)               ][hub deviceのポート数]]

	+8〜	(portの数だけ繰り返し)
	 bit 31                         16  15                           0
	   [[ 接続されているdeviceのaddr. ][       deviceのステータス     ]]

hub deviceのステータスは以下の構造体で表される。

	typedef union   {
	    struct      {
	        UH      level:3;        /* hubの段数 */
	        UH      self_power:1;   /* self powered hubなら1 */
	        UH      reserved:12;
	    }   bmStatus;
	    UH  status;
	}       usbHubStatus;
PS_PORT_CONNECTION0x0001デバイスが接続されている場合に設定される
PS_PORT_ENABLE0x0002デバイスがオープンされている場合に設定されている
PS_PORT_SUSPEND0x0004デバイスがサスペンド状態の場合に設定される(通常、この値が設定されることはない)
PS_PORT_OVER_CURRENT0x0008デバイスが過電流状態にある場合(bus-powered hubが2つ連続で接続された場合はホストから遠い側のhubに設定される)
PS_PORT_RESET0x0010デバイスはリセットを行っている(通常、この値が設定されることはない)
PS_PORT_POWER0x0100deviceに対して電源が供給されている場合に設定される(通常はこの値が設定されているが、ハブもしくはデバイスに何らかの異常が起こっている場合は設定されていないことがある)
PS_PORT_LOW_SPEED0x0200low speed device(キーボードやマウス等が挙げられる)が接続された場合に設定される

【エラーコード】

USB_ERR_NOMEMreportを格納するだけの領域が確保されていない

15.8 USBマネージャシステムコール・補足

本項目では、USBマネージャシステムコールの説明USB_ERR_IO_*のように書かれているエラー (USBデバイスとの通信中に発生するエラー)に関しての説明を行う。

USB_ERR_IO_NAK
デバイスからのNAK応答が一定時間(10秒)以上続いた場合に発生する。 ただし、インタラプト転送を使用するパイプではこのエラーは発生しない。
USB_ERR_IO_SHORT
usbOpenPipe()でUSB_SHORTOKを指定しない状態で usbIoPipe()でデータをやり取りした際に、 指定したデータ長より短いサイズでデータのやり取りが終了した場合に 発生する。
USB_ERR_IO_BABBLE
バブル(babble)が発生した場合にこのエラーコードが返される。
USB_ERR_IO_CRC
CRCエラーが発生した場合にこのエラーコードが返される。
USB_ERR_IO_BITSTUFF
ビットスタッフ(bit stuff)エラーが発生した場合に このエラーコードが返される。
USB_ERR_IO_BABBLE, USB_ERR_IO_CRC, USB_ERR_IO_BITSTUFFが 頻繁に発生する場合、USBデバイスに問題がある可能性が考えられる。
USB_ERR_IO_BUFERR
USBホストコントローラとメインメモリとの間の転送で 問題が発生した場合に起こるエラーである。 通常は発生しないが、 ホストコントローラの種類によっては発生することがある。
USB_ERR_IO_NORESP
デバイスが解除されてからUSBマネージャがデバイスの解除を検知する までの間には多少のタイムラグがあり、その間にデバイスに対して 通信を行った際に発生するエラーである。
このエラーが発生した場合、それ以降はデバイスに対する操作を 行うのを避けるべきである。

この章の目次にもどる
前頁:第14章 ネットワークデバイスにもどる