Basic USB Device Driver Stack for OS/2 Warp Programmer’s Reference. Version 1.1

From EDM2
Jump to: navigation, search

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

Change History
Version Date Summary of Changes
1.0 02/22/2002 Initial version of document
1.1 01/20/2004 Updated to include USB 2.0 support details

About This Document

Purpose

This document briefly describes OS/2 USB stack implementation and gives guidelines for host controller driver and class/client driver implementation together with stack driver communication API specification.

Intended Audience

This programmers reference document could be used by host controller and client/Class driver developer and contains design requirements used for OS/2 base USB stack implementation.

Introduction

OS/2 USB driver stack consists of 3 layers 1) host controller driver layer; 2) USBD root layer; 3) class/client layer. Driver stack internally uses communication interface based on Inter Driver Communication (IDC) calls. Interface between the system and class/client drivers depends on particular driver and its application area.USBD driver acts as a root of USB driver stack and both other layer drivers must register themselves within USBD. Root layer driver manages all USB device attach/detach processes and serves USB Hub devices internally.

Host controller driver layer interacts with USB host hardware to execute requests received from USDB driver/layer and sends request complete messages (process IRQ requests) to USBD/Class/Client drivers.

Design Overview

3 USB driver stack layers are shown below:

USBDDKImage5.gif

All drivers must follow OS/2 driver implementation requirements and implement at least BASEDEVINIT (1Bh) or DEVINIT (00h) strategy call routines depending on driver type - base device driver or device driver. In order to avoid CONFIG.SYS file entry ordering requirements host controller and class/client drivers may implement also INITIALIZATION COMPLETE (1Fh) strategy routine.

USBD driver performs the following actions:

  • accepts registration/de-registration requests from all installed HCD layer drivers
  • accepts registration requests from all installed device class/client drivers
  • reset/initialize all host controllers via call to registered host controller drivers. This call starts enumeration process for particular host starting with device descriptor retrieval for controller root hub and then continuing root hub port processing as for regular hub device. Reset/Initialize call is executed as the latest at USBD driver INITIALIZATION COMPLETE strategy call or before if Complete Initialization IDC call is received from any class/client driver (see description below)
  • calls all registered class/client drivers when new non-HUB device is attached or when detached
  • passes I/O requests initiated by class/client drivers to appropriate HCD driver and processes request cancellation
  • manages Hub control pipes to process device attachment/detachment (including I/O request canceling for detached devices)
  • process set device configuration/set interface/clear stalled endpoint (reset endpoint) requests received from Class/Client drivers
  • processes APM events - received from host controller drivers or APM.SYS driverprocess reset port request from Class/Client drivers (this request will initiate device enumeration process for selected device again)
  • notify all registered Class/Client drivers about completed initial device enumeration.

Briefly device attach/detach processing in USBD driver is shown in diagram below:

USBDDKImage6.gif

Host Controller driver

Basic OS/2 USB Host Controller Driver processes only BASEDEVINIT (1Bh) and INITIALIZATION COMPLETE (1Fh) strategy calls. Processing of I/O requests and IRQ events (within USB stack requests completed by host/driver are called IRQ events) are handled by means of IDC calls to and from the USB Driver (or class client driver for IRQ processing calls). Host controller driver has to implement I/O request processing for all devices connected to corresponding host controller including root hub (in most cases implemented in host driver code).

BASEDEVINIT Strategy Command

Standard OS/2 USB host controller driver during initialization strategy call processing performs the following actions:

  • Processes CONFIG.SYS parameters. All stack drivers must process /V (verbose) parameter and display during initialization driver version/hardware information if initialization succeeds or error message(s) describing reason of failure. If /V parameter is not specified driver must initialize/fail to initialize quietly, without displaying any messages.
  • Locates host controller device(s)
  • Registers I/O resources within OS/2 Resource Manager
  • Tries to register all host controllers within USBD driver: a) get USBD driver IDC address via DevHelp_AttachDD call with driver name "USBD$ "; b) issue registration call if possible.

INITIALIZATION COMPLETE Strategy Command

OS/2 USB host controller reissues registration call if registration failed because USBD driver was not yet loaded at initialization time.

Request complete (IRQ) notification

Host controller driver notifies I/O request originator by calling IDC routine, address of this routine is stored in request block. Threads that process request and call notification routine must be separated, this is valid also for requests that could be executed immediately - like retrieving port status from I/O space or memory mapped registers.

IDC Processing

The host controller driver must accept several types of IDC calls (for parameter details see Chapter 5) from the USBD driver. Types of IDC calls include:

  • Accept an I/O request. HCD driver must implement software Root Hub support for host controller hardware
  • Cancel I/O requests for specific USB device
  • Reset Host controller
  • process power management suspend call (optional)

During request processing driver performs:

  • parameter checking
  • bandwidth calculations
  • request execution and error / success condition processing
  • client notification about completed request.

The Cancel I/O request terminates all active (unprocessed) I/O requests belonging to the specified device.

Reset host controller call performs all required actions to complete hardware reset and turn host into running state. When reset call completes driver must accept default address requests as addressed for root hub.

The USB host controller driver sends several type of IDC calls (for parameter details see Chapter 5) to other drivers in the USB driver stack. Types of IDC calls originating from the host driver include:

  • Process IRQ
  • Register/Unregister HCD driver
  • Notify USBD driver on wake-up events

Root hub implementation

Any host controller driver must report its hardware configuration (number on downstream external ports) and port features/status according to USB specifications. This information is accumulated in virtual USB hub device called ‘root hub’. Root hub device can be accessed only after host reset call via default address. Host controller driver must support the following functions (list is limited to functions used by USBD driver) common to all USB devices for root hub:

  • retrieving root hub device descriptor
  • setting hub device address
  • retrieving hub device configuration structures
  • setting hub configuration

and functions specific to hub device class:

  • retrieving hub descriptor
  • retrieving hub/hub port status information
  • clearing hub/hub port features
  • setting hub/hub port features
  • retrieving hub "status changed" pipe data.

Host controller driver accepts I/O requests from topmost drivers for root hub in the same manner as for other devices - through IDC call.

Class/Client Driver

Class/client drivers serves specific USB device class or device giving access to hardware from client applications or operating system services (like file system, multimedia data streaming). Depending on device class, drivers are implemented as base device drivers or device driver and must process at least BASEDEVINIT (1Bh) or DEVINIT (00h) strategy calls. Support of INITIALIZATION COMPLETE (1Fh) strategy call is recommended to avoid problems with driver configuration string order in CONFIG.SYS file.

OS/2 USB stack assumes that if a separate client driver(s) must be used for particular class driver then client driver never communicates directly with USBD driver and all requests must be passed to class driver that forwards requests to USBD driver.

Class/Client driver must register within USBD driver. USBD calls class driver later to inform it about device/system status change.

OS/2 USB stack use device configuration value to perform device reservation on the level of device. 0 configuration value means that device is not used / claimed for service. Class/Client driver must set configuration value to desired configuration (non-zero number) value to reserve device. Sharing of devices with the same configuration value between several drivers will work only in case if installed set of drivers are designed to work simultaneously or have special reservation mechanisms.

BASEDEVINIT/DEVINIT Strategy Command

Standard OS/2 USB Class/Client driver during initialization strategy call processing performs the following actions:

  • Processes CONFIG.SYS parameters. All stack drivers must process /V (verbose) parameter and display during initialization driver version/hardware information if initialization succeeds or error message(s) describing reason of failure. If /V parameter is not specified driver must initialize/fail to initialize quietly, without displaying any messages.
  • Tries to register all host controllers within USBD driver: a) get USBD driver IDC address via DevHelp_AttachDD call with driver name "USBD$ "; b) issue registration call if possible (could not be done for BASE device drivers as registration call must be Ring0 call, but could be done later after initialization completes and driver starts normal request processing).

INITIALIZATION COMPLETE Strategy Command

OS/2 USB Class/Client driver reissues registration call if registration failed (or was not executed) at initialization time during initialization complete call.

IDC Processing

The Class/Client driver must accept several types of IDC calls (for parameter details see Chapter 5) from the USBD driver. Types of IDC calls include:

  • Accept/reject device for service (during this call device configuration value must be set to non-zero value in corresponding DeviceInfo structure)
  • Process detach device requests (this request must be passed to client driver if it works on the top of class driver)
  • process power management suspend/resume notifications (optional)
  • complete initialization call
  • Process IRQ notification calls
  • Process idle notification calls (to switch from BIOS support mode to native OS/2)

All class driver requests must be passed to client driver if it works on the top of class driver.

As a rule Class/client driver issues several IDC calls to USBD driver:

  • class driver registration call
  • I/O requests required for device initialization/functioning
  • configuration/interface setting calls
  • request cancel call
  • clear stalled endpoint call
  • complete initialization call (optional, may be response to adapter driver ‘complete initialization’ iorb request)

Stack does not define Class-Client driver interface but is seems reasonable to use similar IDC based interface.

Filter drivers

Several USB devices use vendor specific command/protocol sets, filter drivers converts this nonstandard behavior to standard class behavior. Filter design is similar to class/client driver design and the only formal difference is in accept/reject IDC request processing - filter driver must identify device to be filtered and set filter driver IDC information in request data structure and refuse device acceptation for service. After this any requests routed to USBD for this device (except registration/IRQ/complete initialization calls) will be passed to filter driver rather than directly to host controller driver. Filter may change request and data structures used by this call and/or process requests itself. Sometimes it may be useful to change IRQ processing routine address used in original request to filter routine - especially if data structures returned by device need to be changed to match specification requirements.

Filter driver submits requests to device through USBD driver using the same IDC mechanism as regular stack drivers, but uses CMDIOCTLW (0x0c) as command value in pRP_GENIOCTL->Cmd (see details in section 5).

Only single filter can be set for device, filter does not receive information about regular class/client driver that has accepted device for service. Client/class drivers are called to process device information in order drivers have been registered within USBD driver, therefore filtering may be started later or earlier depending on driver load sequence.

Component Externals

Both the host controller driver (HCD) and USBD driver use IDC calls to perform I/O on the USB devices. These call descriptions can be used to develop new HCD layer drivers and new Device Class drivers.

APIs

Drivers in USB driver stack communicate with each other via IDC routine calls using common parameter format:

void IDCRoutine( RPH_GENIOCTL FAR *pRP_GENIOCTL );

where pRP_GENIOCTL is a pointer to a standard OS/2 IOCTL request packet. All structure field usage are as for standard IOCTL request packet. pRP_GENIOCTL->Cmd must be set to 10h (generic IOCtl call). The USBUHCD and USBD drivers ignore the pRP_GENIOCTL->sfn field value.

The pRP_GENIOCTL->Category field is used to indicate which USB device driver is to process the request. Valid values include:

Definition Value Description
USB_IDC_CATEGORY_HOST 0x90 IDC to be processed by HCD driver
USB_IDC_CATEGORY_USB 0x91 IDC to be processed by USBD driver
USB_IDC_CATEGORY_CLASS 0x92 IDC to be processed by Device Class driver
USB_IDC_CATEGORY_CLIENT 0x93 IDC to be processed by Client driver

The pRP_GENIOCTL->Function field is used to indicate what type of functionality is to be performed. Value values include:

Definition Value Description
USB_IDC_FUNCTION_ACCIO 0x41 Add I/O request to schedule
USB_IDC_FUNCTION_CANCEL 0x42 Cancel I/O request for specified device
USB_IDC_FUNCTION_REGISTER 0x43 Register driver with USBD
USB_IDC_FUNCTION_PRCIRQ 0x44 Process IRQ request
USB_IDC_FUNCTION_CHKSERV 0x45 Accept/reject device for service
USB_IDC_FUNCTION_DETDEV 0x46 Detach device
USB_IDC_FUNCTION_RSTHOST 0x47 Reset host controller
USB_IDC_FUNCTION_SETCONF 0x48 Set device configuration
USB_IDC_FUNCTION_SETINTF 0x49 Set device interface
USB_IDC_FUNCTION_CLRSTALL 0x4a Clear stalled endpoint
USB_IDC_FUNCTION_CMPL_INI 0x4c Initialize all registered USB host controller drivers
USB_IDC_FUNCTION_APM 0x4d Power management state changes
USB_IDC_FUNCTION_UNREGISTER 0x4f Un-register driver
USB_IDC_FUNCTION_RESET_PORT 0x51 Initiate port reset for selected hub port
USB_IDC_FUNCTION_IDL 0x52 USBD driver has completed all hub configuration activities started at initialization time

The following table show which device drivers can originate and which driver process specified IDC function types.

HCD Driver USBD Driver Device Class Driver Client Driver
I/O Request Process Originate/Process Process/Originate Originate/Process
Cancel Process Originate/Process Originate n/a
Register Originate Process Originate/Process Originate
Process IRQ Originate Process Process Process
Accept/Reject device n/a Originate Process/Originate Process
Detach Device n/a Originate Process/Originate Process
Reset Host Controller Process Originate n/a n/a
Set Device Configuration n/a Process Originate n/a
Set interface n/a Process Originate n/a
Clear stalled n/a Process/Originate Originate/Process Originate
Complete initialization n/a Process Originate n/a
Power management Originate/Process Process/Originate Process n/a
Un-register Originate Process n/a n/a
Reset port n/a Process Originate n/a
Idle n/a Originate Process n/a

Upon successful completion, request packets in the USB driver stack set the STATUS_DONE bit as a return code in the pRP_GENIOCTL->Status field. On error conditions, the STATUS_DONE and STERR bits are set along with the appropriate error code value in the lower 7 bits in the pRP_GENIOCTL->Status field. Valid error status values in the USB stack include the following:

Definition Value Description
USB_IDC_WRONGCAT 0x10 wrong IDC call category
USB_IDC_WRONGFUNC 0x11 wrong IDC call function
USB_IDC_WFCATCOMB 0x12 wrong IDC call category/function combination
USB_IDC_PARMERR 0x13 parameter error
USB_IDC_ALLOCERR 0x14 failed to allocate internal data structures
USB_IDC_NOBANDWIDTH 0x15 not enough bandwidth to execute request
USB_IDC_EXCEEDSMAX 0x16 number of registered drivers exceeds maximum allowed
USB_IDC_CANCELED 0x17 I/O request canceled
USB_IDC_ADDRINV 0x18 device or endpoint not exists
USB_IDC_SERVREJCTD 0x19 device can't be served by driver
USB_IDC_IOFAILED 0x20 I/O request failed

The individual IDC routines set specific return codes describing the failed action (see below).

Host Controller driver IDC calls

The following calls must be processed by the Host Controller Driver (calls are issued by USBD driver).

Accept I/O request

This call is used to place a I/O request in USB Host Controller Schedule. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x90 // Processed by HCD
pRP_GENIOCTL->Function = 0x41 // IO Request
pRP_GENIOCTL->ParmPacket = &USBRb

The USBRb data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID (assigned by USBD driver during registration)
UCHAR deviceAddress USB device address. Valid range - [1,127], 0 are used for not configured devices. In most cases address 1 is used for root hub.
UCHAR endPointId device endpoint ID, valid range - [0,15]
UCHAR status device status on request complete (during IRQ processing)
x1xx xxxx - device stalled
xx1x xxxx - data buffer error
xxx1 xxxx – babble
xxxx 1xxx - NAK received
xxxx x1xx - CRC/Time Out Error
xxxx xx1x - bit stuff error
WORD flags Low order byte sets transfer type and several flags:
xxxx x001 - input request packet
xxxx x010 - output request packet
xxxx x100 - setup (control) request packet
xxxx 1xxx - variable frame length used for isochronous requests
xxx1 xxxx - high speed device (USB 2.0), set by USBD
xx1x xxxx - extended USB 2.0 request block*
1xxx xxxx - physical address specified for buffer
1x1xx xxxx - physical address specified for buffer2

High order byte gives packet/queuing/request completion details:

1xxx xxxx - isochronous request
x1xx xxxx - interrupt request
xx1x xxxx - bulk transfer request
xxx1 xxxx - low speed device, flag set by USBD
xxxx 1xxx - transfer data toggle on (set/cleared on request completion)
xxxx xx1x - alternate interface specified
xxxx xxx1 - HID report ID specified in isoFlags field, used by HID drivers only
PUCHAR buffer1 Virtual address of data buffer. Address is converted to physical address by HCD.
USHORT buffer1Length Buffer length in bytes. Value 0x7ff means zero length packet.
PUCHAR buffer2 Virtual address of second data buffer. Address is converted to physical address by HCD. This buffer is used only for SETUP requests to receive optional setup data and isochronous transfers with individual frame lengths.
USHORT buffer2Length Buffer length in bytes. Value 0x7ff means zero length packet.
USHORT serviceTime Required service frequency in ms for nonisochronous requests. Valid range - [0,255]. For isochronous request contains frame index request add to. Frame index can be relative or absolute (if "absolute frame index" flag is on flags field). This field is set to absolute index value when request is accepted or IRQ processed.
USHORT maxPacketSize maximum packet size to be used for specified endpoint, set to 0 to use maximum allowed for this device endpoint
PUSBIDC usbIDC Address of IRQ processing routine to be called for this request
USHORT usbDS data segment value for IRQ processing routine
UCHAR category category value used in IRQ call
ULONG requestData1 data to be stored within request
ULONG requestData2 data to be stored within request
ULONG requestData3 data to be stored within request
UCHAR maxErrorCount maximum retry count, valid range - [0,3]; 0 means no retry limit
_USBRb FAR * nextRb pointer to next request block, not used, must be set to NULL
UCHAR altInterface alternate interface index. The value of this field is used by USBD to locate endpoint descriptor if "alternate interface specified" flags is on in flags field. Otherwise 0 interface index value is used.
UCHAR isoFlags Field is used only for isochronous requests (when isochronous request flag is on in "flags" field) to specify requested service:
xxxx xxx1 - open isochronous request
xxxx xx1x - close request
xxxx x1xx - cancel isochronous buffer processing
xxxx 1xxx - retrieve buffer processing status
xxxx 0000 - accept data buffer for processing
USHORT isoFrameLength Field is used only for isochronous 'open' requests and specifies number of data bytes to be transferred during single host frame
USHORT isoBuffers Field is used only for isochronous 'open' requests and specifies number of buffers used for data transfer
UCHAR Mult Number of transactions per micro frame (USB 2.0)
UCHAR HubAddr Hub address for current device (USB 2.0)
UCHAR PortNumb Hub port number for current device (USB 2.0)
  • (*) If this flag is set, then request block contain Mult, HubAddr, PortNumb fields with valid values set and also isochronous request extension fields (values from these fields are used only if proper flag is set). USB2.0 flag is always on for host / USBD communication and extended request structure is used. Class/client drivers can issue requests using short structure form.

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request accepted
0x8113 request parameter error
0x8114 failed to allocate internal data structures
0x8115 not enough bandwidth to execute request
0x8118 device or endpoint not exists

Isochronous requests are processed in different manner than all other requests - isochronous requests require special initialization/de initialization actions before data transfer starts and after transfer is finished. HCD layer driver calls IRQ routine only once per buffer even if data are split between several frames. Isochronous request details are specified in 'isoFlags' field. Typical calling sequence is the following:

1) isochronous open request (isoFlags=00000001b) allocates data structures to serve request. HCD driver saves isoBuffers and isoFrameLength in these structures. Data block is identified by device address, target endpoint address and transfer direction. Open request will fail if:

there are already opened isochronous request for the same device, endpoint addresses and transfer direction (return code 0x8118);

not enough memory to allocate request data block (return code 0x8114);

not enough USB bandwidth to complete request (return code 0x8115);

requested frame size (number of bytes to be transferred during single host frame) exceeds maximal packet size for target endpoint (return code 0x8113).

Open call also saves caller identification data (IDC routine address, DS value, caller's category) and requestData1, requestData2, requestData3. Identification data is used in all IRQ calls, but requestData only for canceled request notification.

2) accept isochronous data buffer (isoFlags=00000000b) accepts buffer address and length from buffer1, buffer1Length fields and starts data transfer. In case if individual frame lengths are used then buffer2 and buffer2Length fields are used to pass this information. If constant frame length is used then both these fields must be set to 0. For detailed description of fixed/individual frame size transfers see note below. Buffer will be refused if:

no isochronous request is opened for specified device,endpoint and transfer direction (no previous open call) (return code 0x8118);

number of buffers exceeds number specified at open time (return code 0x8113).

Values specified in requestData1, requestData2, requestData3 fields are used in 'buffer processed' notification call.

3) isochronous close request (isoFlags=00000010b) releases data structures allocated for request. This request must be the last call in isochronous data transfer for specified device, endpoint and transfer direction. This request fails if there were no open call for the same target.

Cancel isochronous buffer processing call (isoFlags=00000100b) stops isochronous data processing, clears all the buffer information and returns in buffer1, buffer1Length fields last processed data buffer address and processed data length. Cancel request fails with return code 0x8118 if no isochronous request is opened for specified device,endpoint and transfer direction.

Retrieve request status information call (isoFlags=00000100b) returns in buffer1, buffer1Length fields last processed data buffer address and processed data length. Request fails with return code 0x8118 if no isochronous request is opened for specified device,endpoint and transfer direction.

The initial implementation supported only fixed frame size isochronous transfers. But it proved that for some clients (like USBAudio) this approach is not flexible enough and causes dropped samples due to fact that internal sampling frequency of device is not the exact multiple of USB internal 1000 Hz frame clock frequency. To allow clients to use explicit synchronization the API was extended to be able to specify the length of every frame individually. This information is passed in previously unused Buffer2 and Buffer2Length fields.

Variable Fixed frame size Individual frame size
Buffer1 pointer to data pointer to data
Buffer1Length number of bytes in data buffer number of bytes in data buffer
Buffer2 NULL pointer to ISO_FRAME_INFO array
Buffer2Length 0 number of bytes in ISO_FRAME_INFO array
isoFrameLength fixed frame size not used

There is possibility that device will not be able to send/receive as much information as caller requested. To allow host controller to report back the number of actually transferred bytes the Buffer2 and Buffer2Length fields are used in notification messages.

Variable Fixed frame size Individual frame size
Buffer1 pointer to data pointer to data
Buffer1Length number of bytes in data buffer number of bytes in data buffer
Buffer2 NULL pointer to updated ISO_FRAME_INFO array
Buffer2Length Number of actually transferred bytes number of bytes in ISO_FRAME_INFO array
If number of actually received (only for READ) bytes is less than asked for then buffer is compacted to avoid gaps. The missing bytes at the tail of buffer are set to 0. If number of actually received (only for READ) bytes is less than asked for then buffer is left in scattered state. Each ISO_FRAME_INFO entry specifies how many bytes in tail of frame are not received and thus have unknown values.

To pass information about individual frame lengths the array of ISO_FRAME_INFO structures is used. There must be as many structures as number of frames to transfer. Structure contains only one member Length which specifies the number of bytes to transfer between host and device. In notification message the original values are replaced with number of actually transferred bytes.

Cancel I/O request(s)

This call is used to cancel all queued I/O requests for the specified USB device and endpoint. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x90 // Processed by HCD
pRP_GENIOCTL->Function = 0x42 // Cancel request
pRP_GENIOCTL->ParmPacket = &USBCancel

The USBCancel data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127], 0 are used for not configured devices
UCHAR endPointId endpoint ID. Valid range - [0,15], 0xff cancels requests for all the device endpoints

Reset host controller

This call is used to reset host controller and move it into ‘running’ state:

pRP_GENIOCTL->Category = 0x90 // Processed by HCD
pRP_GENIOCTL->Function = 0x42 // Cancel request
pRP_GENIOCTL->ParmPacket = &USBDetach

The USBDetach data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID to be reset
UCHAR deviceAddress Not used

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, host reset
0x8118 device or endpoint not exists

Notify about power management state changes

This call is used to notify host controller drivers about changes in APM power states. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x90 // Processed by HOST
pRP_GENIOCTL->Function = 0x4d // Power management notification
pRP_GENIOCTL->ParmPacket = &ulAPMState // Power state

ulAPMState is DWORD value which can contain these values:

Code value Description
USB_APM_SUSPEND (1L) Host will go to suspended state
USB_APM_RESUME (2L) Host will resume from suspended state

Return code is not analyzed by originator driver (USBD driver), host driver that processes this request can set it to any proper value.

USBD driver IDC calls

The following calls are processed by the USBD driver (calls may be issued by HCD and/or class driver depending on call type).

Cancel I/O request(s)

This call is used to cancel all queued I/O requests for the specified USB device and endpoint. USBD driver verifies host/device/endpoint and sends request to proper host controller driver. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x42 // Cancel request
pRP_GENIOCTL->ParmPacket = &USBCancel

The USBCancel data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127], 0 are used for not configured devices
UCHAR endPointId endpoint ID. Valid range - [0,15], 0xff cancels requests for all the device endpoints

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request(s) canceled
0x8118 device or endpoint not exists

Set device configuration request

This call is used by class/client drivers to set device configuration. USBD driver stores configuration value in device data structures that are passed to class/client drivers during attach request processing, configuration value could be used as flag to show that device will be used by class/client driver. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x48 // Set configuration
pRP_GENIOCTL->ParmPacket = &USBSetConf

The USBSetConf data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127]
USHORT classDriverDS data segment value for IRQ processing routine
UCHAR configurationValue desired configuration value
ULONG irqSwitchValue value used in class driver IRQ processor worker switch
UCHAR category category value used in IRQ call
SetupPacket FAR * setConfiguration far pointer to setup packet buffer used in clearing operation

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request(s) canceled
0x8118 device or endpoint not exists

Set interface request

This call is used by class/client drivers to select device Interface. USBD driver stores configuration value in device data structures that are passed to class/client drivers during attach request processing. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x49 // Set configuration
pRP_GENIOCTL->ParmPacket = &USBSetConf

The USBSetConf data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127]
USHORT classDriverDS data segment value for IRQ processing routine
UCHAR configurationValue desired configuration value
ULONG irqSwitchValue value used in class driver IRQ processor worker switch
UCHAR category category value used in IRQ call
SetupPacket FAR* setConfiguration far pointer to setup packet buffer used in clearing operation

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request(s) canceled
0x8118 device or endpoint not exists

Register HCD driver

This call is used to register a Host Controller Driver with the USBD driver. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x90 // Processed by USBD (!)
pRP_GENIOCTL->Function = 0x43 // Register HCD driver
pRP_GENIOCTL->ParmPacket = &USBHCD

The USBHCD data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
PUSBIDC usbIDC Address of HDC IDC routine
PUCHAR hcdID Pointer to store assigned by USBD controller Ids, hcdID points to area to store all hcdCount IDs
UCHAR hcdCount Number of served Host Controllers
HDRIVER hDriver RM driver handle
HADAPTER hAdapter RM adapter handle

Last 2 items (hDriver and hAdapter) are repeated hcdCount times.

Registration call is processed by USBD even if request category is set to host controller driver to distinguish between host and Client/Class registration requests. This is the only exception in request category processing.

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return, HCD registered
0x8116 number of registered drivers exceeds maximum allowed

Un-register HCD driver

This call is used to un-register a HCD from the USBD driver. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // USBD
pRP_GENIOCTL->Function = 0x4f // Register Device Class
pRP_GENIOCTL->ParmPacket = &USBHCD

The USBHCD data structure is defined in src\dev\usb\include\usbidc.h , see details in ‘Register HCD Driver’ request description.

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return, Device Class Driver registered
0x8118 Host driver not found

Register Device Class driver

This call is used to register a Device Class Driver with the USBD driver. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // USBD
pRP_GENIOCTL->Function = 0x43 // Register Device Class
pRP_GENIOCTL->ParmPacket = &USBDClass

The USBDClass data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
PUSBIDC usbIDC Address of Device Class driver IDC routine
USHORT usbDS Class driver data segment value

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return, Device Class Driver registered
0x8116 number of registered drivers exceeds maximum allowed

Process IRQ

This call is used to complete i/o request processing at the USBD level (to service hub status changed pipes, not configured device control pipe). Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x44 // Process IRQ
pRP_GENIOCTL->ParmPacket = &USBRb

The USBRb data structure is defined in src\dev\usb\include\usbidc.h. (see details in Process I/O request call description). USBRb structure returned by host controller driver may be different from one used in original request and differs depending on request type:

Request type Not restored fields Updated fields
non-isochronous
  1. flags - request type (isochronous/interrupt/bulk), altinterface, HID id flags are not restored;
  2. serviceTime is set to 0;
  3. altInterface value is not restored;
  1. status - indicates processing error details (see details in table below);
  2. buffer1Length, buffer2Length are set to actual number of bytes transferred;
  3. maxPacketSize - set to maximum transferred packet size for the last transfer;
  4. maxErrorCount is set to actual error count value
isochronous
  1. flags - iso request fag is restored;
  2. status, maxPacketSize, maxErrorCount - set to 0;
  1. buffer1Length is set to actual number of bytes transferred;
  2. buffer2Length are set to isochronous frame length array if requested;

Request status code values returned by host controller driver:

Status flags Description
0x40 STALLED
0x20 BUFFERR
0x10 BABBLE
0x08 NAK
0x04 CRC
0x02 BITSTUFF

One of the following return codes is set in the pRP_GENIOCTL->Status field before request is sent to driver for processing:

Code value Description
0x0100 normal return code, I/O request completed successfully
0x8017 Request has been canceled
0x8020 I/o request failed, see details in status field

Host controller driver does not process return code set by called driver.

Clear Stalled Endpoint request

This call is used to pass a I/O request to the HCD driver. All the device class drivers call the USBD driver to add their requests to appropriate HCD schedule. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x4a // Clear Stalled Request
pRP_GENIOCTL->ParmPacket = &USBClearStalled

The USBClearStalled data structure is defined in src\dev\usb\include\usbidc.h as:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127]
UCHAR endPointId device endpoint ID, valid range - [0,15]
PUSBIDCEntry clientIDCAddr Address of IRQ processing routine to be called for this request
USHORT clientDS data segment value for IRQ processing routine
ULONG irqSwitchValue switch used by IRQ processing routine
UCHAR category category value used in IRQ call
SetupPacket FAR * clearStalled far pointer to setup packet buffer used in clearing operation

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request passed to accepted
0x8115 not enough bandwidth to execute request
0x8118 device or endpoint not exists

Process I/O request

USBD driver accepts i/o requests in the same way as host drivers:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x41 // accept i/o Request
pRP_GENIOCTL->ParmPacket = &USBRb

The USBRb data structure is defined in src\dev\usb\include\usbidc.h , see details in host controller decryption section. USBD checks for controller/device/endpoint presence and set device dependent flags in request block: 1) device speed flags (low/high speed device); 2) 0 default service time is replaced with actual value from device descriptor; 3) 0 maxPacket size is replaced with actual value .

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request accepted
0x8113 request parameter error
0x8114 failed to allocate internal data structures
0x8115 not enough bandwidth to execute request
0x8118 device or endpoint not exists

Initialize registered USB host controllers

This call is used to start (move to running state) all registered USB host controller(s). This call could be used to start hosts earlier than all driver chain passes initialization complete phase, like during system boot when it is time to switch from BIOS support to native OS/2 driver support. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x4c // Complete initialization Request
pRP_GENIOCTL->ParmPacket = &pRP_GENIOCTL // not used, must be non-NULL
                                         // address to pass parameter check

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, host initialization process started

Notify about power management state changes

This call is used to notify USBD about changes in APM power states - host wake up. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x4d // Power management notification
pRP_GENIOCTL->ParmPacket = &ulAPMState // Power state

ulAPMState is DWORD value which can contain these values:

Code value Description
USB_APM_RESUME (2L) Host will resume from suspended state

Reset port

This call is used to request USBD driver to reset hub port for specified device, port reset will initiate device re-enumeration. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x91 // Processed by USBD
pRP_GENIOCTL->Function = 0x51 // reset port
pRP_GENIOCTL->ParmPacket = &USBRb // controller/device IDs

The USBRb data structure is defined in src\dev\usb\include\usbidc.h., USBD driver uses controllerId and deviceAddress fields to locate corresponding hub ID and port number to be reset.

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, port reset issued
0x8118 device or endpoint not exists (?)

Initial enumeration complete

USBD driver processes all hub devices/attached devices during initial device enumeration. Class/Client drivers are notified by sending IDLE message sent out by USBD when initial enumeration completes. This notification could be used to switch from system boot time environment to normal processing environment and is sent out only once during boot/operation session. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by CLASS
pRP_GENIOCTL->Function = 0x52 // idle
pRP_GENIOCTL->ParmPacket = (PVOID)1 // not used

Return code is not analyzed by USBD driver, Class/Client driver can set it to any proper value.

Class/client driver IDC calls

The following calls are processed by USB Class/Client drivers (calls may be issued by USBD or by HCD drivers depending on call type).

Initial enumeration complete

USBD driver processes all hub devices/attached devices during initial device enumeration. Class/Client drivers are notified by sending IDLE message sent out by USBD when initial enumeration completes. This notification could be used to switch from system boot time environment to normal processing environment and is sent out only once during boot/operation session. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by CLASS/Client
pRP_GENIOCTL->Function = 0x52 // idle
pRP_GENIOCTL->ParmPacket = (PVOID)1 // not used

Return code is not analyzed by USBD driver, Class/Client driver can set it to any proper value.

Process IRQ

This call is used to process an IRQ (request complete processing) at the Class/Client level. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by Class/Client
pRP_GENIOCTL->Function = 0x44 // Process IRQ
pRP_GENIOCTL->ParmPacket = &USBRb

The USBRb data structure is defined in src\dev\usb\include\usbidc.h., see details in USBD Process IRQ description.

Accept/reject device

This call is used to inform Class/Client drivers about new device that has completed enumeration process. Client/Class driver must analyze device description information and accept device for service or refuse service. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by Class/Client
pRP_GENIOCTL->Function = 0x45 // Process IRQ
pRP_GENIOCTL->ParmPacket = &USBCDServe

The USBCDServe data structure is defined in src\dev\usb\include\usbidc.h. And contains the following fields:

Data Type Variable Function
DeviceInfo FAR * pDeviceInfo Far pointer to device information structure
USBDClass FAR * pFilter Set on exit to Far pointer to filter driver IDC routine if current class/client driver is filter driver

The DeviceInfo data structure is defined in src\dev\usb\include\usbidc.h. and contains the following fields:

Data Type Variable Function
UCHAR ctrlID controller ID
UCHAR deviceAddress USB device address
UCHAR bConfigurationValue USB device configuration value
UCHAR bInterfaceNumber 0 based index in interface array for this item
UCHAR lowSpeedDevice 0 for full speed device, non zero - low speed device
UCHAR portNum port number to which device is attached
USHORT parentHubIndex index in hub table to parent hub, -1 for root hub device
HDEVICE rmDevHandle Resource Manager device handle
SetupPacket clearStalled setup packet for USBD internal use
DeviceDescriptor descriptor device descriptor
UCHAR configurationData[] device configuration data

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, device accepted for service
0x8019 Rejected - driver will not serve current device

Detach device

This call is used to process an IRQ (request complete processing) at the Class/Client level. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by Class/Client
pRP_GENIOCTL->Function = 0x46 // Process IRQ
pRP_GENIOCTL->ParmPacket = &USBDetach

The USBDetach data structure is defined in src\dev\usb\include\usbidc.h. and contains following fields:

Data Type Variable Function
UCHAR controllerId controller ID
UCHAR deviceAddress USB device address. Valid range - [1,127]

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request completed successfully

Upon completion one of the following return codes is set in the pRP_GENIOCTL->Status field:

Code value Description
0x0100 normal return code, I/O request completed successfully

Notify about power management state changes

This call is used to notify class/client drivers about changes in APM power states. Parameters for this request are defined as:

pRP_GENIOCTL->Category = 0x92 // Processed by CLASS
pRP_GENIOCTL->Function = 0x4d // Power management notification
pRP_GENIOCTL->ParmPacket = &ulAPMState // Power state

ulAPMState is DWORD value which can contain these values:

Code value Description
USB_APM_SUSPEND (1L) Host will go to suspended state
USB_APM_RESUME (2L) Host will resume from suspended state

Return code is not analyzed by USBD driver, class/client driver that processes this request can set it to any proper value.

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation