Sei sulla pagina 1di 135

1.1.

USB Developers Kit

Programmers Guide

EDITION 2

Copyright 2003 Wind River Systems, Inc. All rights reserved. No part of this publication may be reproduced or transmitted in any form or by any means without the prior written permission of Wind River Systems, Inc. Wind River, the Wind River logo, Tornado, and VxWorks are registered trademarks of Wind River Systems, Inc. Any third-party trademarks referenced are the property of their respective owners. For further information regarding Wind River trademarks, please see: http://www.windriver.com/company/terms/trademark.html

Corporate Headquarters Wind River Systems, Inc. 500 Wind River Way Alameda, CA 94501-1153 U.S.A. toll free (U.S.): (800) 545-WIND telephone: (510) 748-4100 facsimile: (510) 749-2010 For additional contact information, please visit the Wind River URL: http://www.windriver.com For information on how to contact Customer Support, please visit the following URL: http://www.windriver.com/support

USB Developers Kit Programmers Guide, 1.1.2 Edition 2 23 Apr 03 Part #: DOC-14516-ZD-02

Contents

USB Host Stack ........................................................................................................

1.1

Introduction ...................................................................................................... 1.1.1 1.1.2 System Requirements ........................................................................ Documentation ................................................................................... Reference Manual Entries ................................................................. Related Documentation ....................................................................

1 2 2 4 5 5 7 11 11 12 14 15 16 18 20 22 24 24 25

1.2

Architecture Overview .................................................................................... Host Module Roadmap .....................................................................

1.3

The USB Host Driver (USBD) ......................................................................... 1.3.1 Initializing the USBD ......................................................................... Attaching and Detaching HCDs ...................................................... Order of Initialization ........................................................................ Bus Tasks ............................................................................................. Registering Client Modules .............................................................. Dynamic Attachment Registration .................................................. Device Conguration ........................................................................ Data Flow ............................................................................................ 1.3.2 USBD Internals ................................................................................... Hub Management .............................................................................. New Device Connections ..................................................................

iii

USB Developers Kit 1.1.2 Programmers Guide

1.4

The USB Host Controller Driver (HCD) ....................................................... 1.4.1 1.4.2 1.4.3 HCD Header File ............................................................................... HCD Entry Point ............................................................................... Host Request Blocks (HRB) .............................................................. HCD_FNC_ATTACH ........................................................................ HCD_FNC_DETACH ....................................................................... HCD_FNC_BUS_RESET ................................................................... HCD_FNC_SET_BUS_STATE .......................................................... HCD_FNC_SOF_INTERVAL_GET and HCD_FNC_SOF_INTERVAL_SET ................................... HCD_FNC_PIPE_CREATE .............................................................. HCD_FNC_PIPE_DESTROY ........................................................... HCD_FNC_PIPE_MODIFY ............................................................. HCD_FNC_CURRENT_FRAME_GET ........................................... HCD_FNC_IRP_SUBMIT ................................................................. HCD_FNC_IRP_CANCEL ............................................................... 1.4.4 1.4.5 1.4.6 1.4.7 Management Events .......................................................................... HCD Error Reporting Conventions ................................................ Root Emulation .................................................................................. IRP Timeouts ......................................................................................

25 25 26 26 27 28 28 29 29 30 32 32 33 33 39 39 40 41 41 42 42 43 46 46 46 47 48 48 48 49

1.5

Keyboard Driver .............................................................................................. 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 SIO Driver Model .............................................................................. Dynamic Attachment ........................................................................ Initialization ....................................................................................... ioctl Functions .................................................................................... Data Flow ............................................................................................ Typematic Repeat ..............................................................................

1.6

Mouse Driver .................................................................................................... 1.6.1 1.6.2 1.6.3 SIO Driver Model .............................................................................. Dynamic Attachment ........................................................................ Initialization .......................................................................................

iv

Contents

1.6.4 1.6.5 1.7

ioctl Functions .................................................................................... Data Flow ............................................................................................

49 50 50 51 51 52 53 53 53 54 54 55 56 56 57 57 59 62 62 63 63 63 65 65 66 66 66 67

Printer Driver .................................................................................................... 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 SIO Driver Model ............................................................................... Dynamic Attachment ........................................................................ Initialization ........................................................................................ ioctl Functions .................................................................................... Data Flow ............................................................................................

1.8

Speaker Driver .................................................................................................. 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 SEQ_DEV Driver Model ................................................................... Dynamic Attachment ........................................................................ Initialization ........................................................................................ Recognizing and Handling USB Speakers ..................................... ioctl Functions .................................................................................... Data Flow ............................................................................................

1.9

Mass Storage Class Driver .............................................................................. 1.9.1 1.9.2 1.9.3 1.9.4 Block Device Driver Model .............................................................. Dynamic Attachment ........................................................................ Initialization ........................................................................................ Data Flow ............................................................................................

1.10

Communication Class Drivers ....................................................................... 1.10.1 Ethernet Networking Control Model Driver ................................. Enhanced Network Driver Model ................................................... Dynamic Attachment ........................................................................ Initialization ........................................................................................ Interrupt Behavior ............................................................................. ioctl Functions .................................................................................... Data Flow ............................................................................................

USB Developers Kit 1.1.2 Programmers Guide

1.10.2

Abstract Control Model Driver ....................................................... SIO Driver Model .............................................................................. Dynamic Attachment ........................................................................ Initialization ....................................................................................... Interrupt Behavior ............................................................................. ioctl Functions .................................................................................... Data Flow ............................................................................................ Modem Control: Hayes Commands ...............................................

67 67 68 69 69 69 69 70 70 73 73 73 73 74 74 75 75 76 76 77 81 84 85 85 86 87 88
91

1.11 1.12

Running the USB Kit ....................................................................................... Initialization ...................................................................................................... 1.12.1 1.12.2 Host Stack and Host Controller Initialization ............................... Device Initialization .......................................................................... Keyboard, Mouse, Printer, and Speaker Initialization ................. Mass Storage Class Device Initialization ....................................... Communication Class Device Initialization .................................. 1.12.3 1.12.4 usbAudio Initialization ..................................................................... usbTool Code Exerciser ..................................................................... Running usbTool from the Shell ...................................................... The usbTool Execution Sequence ....................................................

1.13 1.14 1.15

Booting VxWorks Through a Communication Class Driver ..................... Benchmarking Information ............................................................................ BSP Porting Issues ........................................................................................... 1.15.1 Conguring USB Hardware ............................................................. BSPs with pciAutoCongLib ........................................................... BSPs Without pciAutoCongLib ..................................................... 1.15.2 1.15.3 Conguring Memory Address Windows ...................................... Creating BSP-Specic Stub usbPciLib Files ...................................

USB Peripheral Stack ...............................................................................................

Tested Devices ....................................................................................

91

vi

Contents

2.1

Peripheral Stack Architecture ......................................................................... Peripheral Module Roadmap ...........................................................

92 93 97 97 98 99

2.2

USB Target Driver (usbTargLib) ..................................................................... 2.2.1 2.2.2 2.2.3 2.2.4 Initializing usbTargLib ...................................................................... Attaching and Detaching TCDs ....................................................... Enabling and Disabling TCDs ..........................................................

Target Application Callback Table ................................................... 100 mngmtFunc( ) Callback ..................................................................... 101 Control Pipe Request Callbacks ....................................................... 102

2.2.5 2.2.6

TCD Endpoints ................................................................................... 107 Data Transfer ...................................................................................... 109 Control Pipe Data Transfers ............................................................. 110 General Data Transfers ...................................................................... 111

2.2.7 2.2.8 2.2.9 2.3

Setting Endpoint Stall ........................................................................ 111 Bus Frame Number ............................................................................ 112 Resume Signaling ............................................................................... 112

USB Target Controller Driver ......................................................................... 112 2.3.1 2.3.2 2.3.3 TCD Header File ................................................................................ 113 TCD Entry Point ................................................................................. 113 Target Request Block (TRB) .............................................................. 113 TCD_FNC_ATTACH ......................................................................... TCD_FNC_DETACH ......................................................................... TCD_FNC_ENABLE ......................................................................... TCD_FNC_DISABLE ......................................................................... TCD_FNC_ADDRESS_SET .............................................................. TCD_FNC_ENDPOINT_ASSIGN ................................................... TCD_FNC_ENDPOINT_RELEASE ................................................ TCD_FNC_SIGNAL_RESUME ........................................................ TCD_FNC_ENDPOINT_STATE_SET ............................................. TCD_FNC_CURRENT_FRAME_GET ............................................ TCD_FNC_ERP_SUBMIT ................................................................. TCD_FNC_ERP_CANCEL ............................................................... 114 115 115 116 116 116 117 118 118 119 119 119

vii

USB Developers Kit 1.1.2 Programmers Guide

2.3.4 2.3.5 2.4 2.5

TCD Management Events ................................................................ 120 TCD Error Reporting Conventions ................................................. 120

Installing the USB Peripheral Stack ............................................................... 121 Running the USB Peripheral Stack ................................................................ 124 2.5.1 2.5.2 Creating a Downloadable VxWorks Image Including USB ......... 124 Creating a Downloadable USB Application .................................. 125

2.6

Working with usbTool ..................................................................................... 125 The usbTool Execution Sequence .................................................... 125

2.7

BSP-Specic Issues ........................................................................................... 127

viii

1
USB Host Stack
1.1 Introduction
The Universal Serial Bus (USB) provides hosts and devices with a versatile channel for communication at low to moderate speeds. The USB currently offers the following types of service at low (1.5 Mbps) and medium (12 Mbps) data transfer rates:
I I I I

control transfers bulk transfers interrupt transfers isochronous transfers

The USB also incorporates provisions for power management and for the dynamic attachment and removal of devices. This exibility allows the USB to be usedoften concurrentlyby a number of different kinds of devices, each requiring its own device driver support. It is desirable that these device drivers be written independent of each other and independent of the implementation of the host computers underlying USB host controller interface. Wind Rivers USB host driver stack meets these requirements, providing a complete set of services to operate the USB and a number of pre-built USB class drivers that handle specic kinds of USB devices. The USB Developers Kit, also referred to as the USB Kit, includes the following software and hardware items:
I

Source and object code for the USB host stack and drivers. The USB Developers Kit Programmers Guide (this document). The USB Developers Kit Release Notes.

USB Developers Kit 1.1.2 Programmers Guide

The USB Kit shows you how to write your own USB host controller driver and USB device drivers. It is designed to allow the following:
I

Easy portability to RTOSs other than VxWorks. Fast development of new host controller drivers. Easy portability to many BSPs.

1.1.1 System Requirements


Tornado 2.0 runs on PCs and Sun-4 workstations. Host systems must have the following resources:
I

64 MB RAM. 15 MB disk space for typical installation. A CD-ROM drive for installation. For Solaris, a SPARCstation 5 minimum; Ultra5 is recommended. For Windows, an Intel 80486 or better; Intel Pentium 90 or better is recommended.

1.1.2 Documentation
The USB Developers Kit Programmers Guide, 1.1.1 (this manual), describes the architecture and implementation of Wind Rivers USB host and peripheral stacks. The guide contains the following sections:
I

1.2 Architecture Overview, p.5, provides a high-level look at USB organization and introduces the various modules. 1.3 The USB Host Driver (USBD), p.11, includes important information for writing host client class drivers and other applications. 1.4 The USB Host Controller Driver (HCD), p.25, provides information needed to port the USB host stack to run on different host controllers. 1.5 Keyboard Driver, p.42, 1.6 Mouse Driver, p.48, 1.7 Printer Driver, p.50, 1.8 Speaker Driver, p.53, 1.9 Mass Storage Class Driver, p.57, 1.10.1 Ethernet Networking Control Model Driver, p.63, and 1.10.2 Abstract Control Model Driver, p.67, offer essential information if you are creating specic vertical applications using the USB stack.

1 USB Host Stack

1.11 Running the USB Kit, p.70, describes how to use the USB Kit with VxWorks and the Tornado Integrated Development Environment (IDE). 1.12 Initialization, p.73, contains instructions for initializing the host stack, host controllers, external devices, and sample applications, and for USB-UGL conguration. This section also includes information on the usbTool code exerciser. 1.13 Booting VxWorks Through a Communication Class Driver, p.77, describes how to boot VxWorks through a Communication Class driver. 1.14 Benchmarking Information, p.81, provides metrics from a sample system for comparing test results. 1.15 BSP Porting Issues, p.84, provides tips on porting the USB to other BSPs. 2.1 Peripheral Stack Architecture, p.92, provides a high-level look at USB peripheral stack organization and introduces the various associated modules. 2.2 USB Target Driver (usbTargLib), p.97, provides information about the USB target driver, usbTargLib. 2.3 USB Target Controller Driver, p.112, provides information essential to port the USB peripheral stack to run on different target controllers. 2.4 Installing the USB Peripheral Stack, p.121, describes the installation procedure and the locations of installed directories and les. 2.5 Running the USB Peripheral Stack, p.124, provides information for setting up your Tornado environment to use the peripheral stack.

This manual assumes that you are already familiar with the USB specication and Wind Rivers Tornado IDE and VxWorks operating system. The Wind River USB driver stack has been developed in compliance with the Universal Serial Bus Specication, Revision 1.1, generally referred to in this document as the USB specication. Where possible, this manual uses terminology similar to that used in the USB specication so that the correspondence between USB concepts and actions is readily apparent in the software interfaces described.

USB Developers Kit 1.1.2 Programmers Guide

Additional Documentation
I

PDIUSBD12 Evaluation Board (PC Kit) Users Manual, Rev. 2.1, which is included on the oppy disk distributed with the Philips evaluation kit. Firmware Programming Guide for PDIUSBD12, Version 1.0, which is included on the oppy disk distributed with the Philips evaluation kit.

Reference Manual Entries

Reference pages for the USB Kit libraries and subroutines can be accessed online in HTML from the Tornado Help>Manual Index menu command. Search the display box for USB-related libraries in the VxWorks Reference Manual, as in Figure 1-1.
Figure 1-1 Tornado Online Manuals Tree

1 USB Host Stack

Related Documentation
I

USB Developers Kit Release Notes, 1.1.1 Universal Serial Bus Specication, Revision 1.1, September 23, 1998. All USB specications are available at www.usb.org/developers/docs.html. USB device class specications. All USB specications are available at www.usb.org/developers/docs.html. OHCI and UHCI host controller specications: for OHCI: http://www.compaq.com/productinfo/development/openhci.html for UHCI: http://developer.intel.com/design/USB/UHCI11D.htm

Tornado Users Guide 2.0 VxWorks Programmers Guide 5.4 VxWorks Reference Manual 5.4

1.2 Architecture Overview


Figure 1-2 presents a simplied overview of the USB host driver stack architecture. At the bottom of the stack is the USB host controller (USB HC), the piece of hardware in the host system that controls each USB. Currently, there are two major families of USB host controllers on the market, those supporting the Universal Host Controller Interface (UHCI) originally put forth by Intel, and those supporting the Open Host Controller Interface (OHCI) designed by Microsoft, Compaq, and National Semiconductor. A number of hardware manufacturers have built USB HCs around one or the other of these specications. For each type of host controller there is a single, hardware-dependent USB host controller driver (HCD). For example, Wind River provides the source for two pre-built drivers: usbHcdUhciLib for UHCI HCs usbHcdOhciLib for OHCI HCs

USB Developers Kit 1.1.2 Programmers Guide

Figure 1-2

USB Host Driver Stack

USB Client Module (for example, USB Class Drivers)

USBD Interface

USB Host Driver (USBD)

USBD/HCD Interface

USB Host Controller Driver (HCD)

Software

Hardware
USB Host Controller (USB HC)

The interface between the USB host driver (USBD) and the HCD allows for each HCD to control one or more underlying HCs. Also, Wind Rivers USBD is capable of connecting to multiple USB HCDs simultaneously. These design features allow you to build a range of complex USB systems. The USBD is the hardware-independent module above the HCD(s). The USBD manages each USB connected to the host and provides the path through which higher layers communicate with the USB. Among its responsibilities, the USBD handles USB power management and USB bandwidth management automatically. Also, unique to the Wind River architecture, the USBD manages USB hubs. Hub functionality is critical to the proper operation of the USB, so the designers of the Wind River USBD concluded that hub functionality should be handled

1 USB Host Stack

transparently by the USBD. This means that the USBD also handles the dynamic attachment and removal of USB hubs and devices. Figure 1-2 shows the USB Client Module at the top of the stack. USB class drivers are typical examples of client modules. USB class drivers are responsible for managing individual types of devices that can be connected to the USB; they rely on the USBD to provide the communication path to the individual devices. Applications, diagnostics, and test programs are other examples of client modules that rely on the USBD to communicate with USB devices. For example, Wind River provides the test application/module usbTool, which gives you interactive control over the USB and USB devices.

Host Module Roadmap

The diagram in Figure 1-3 illustrates the functional relationships among the modules that comprise Wind Rivers USB host driver stack. Each module is further described in this section; for additional information on USB-related libraries and subroutines, see the associated reference pages in the online VxWorks Reference Manual: USB Libraries. usbTool This module is a test application that gives you interactive control of the USB host driver stack. The usbTool utility exports a single entry point, usbTool( ), that invokes a command-line-driven interactive environment in which the operator can initialize components of the USB driver stack, interrogate each USB connected to the system, send USB commands to individual USB devices, and test other elements of the USB stack. The usbTool test application is most useful during development and testing and does not need to be included in a shipped product.
NOTE: The usbTool module relies internally on static data; you should not run

multiple instances of usbTool simultaneously.


NOTE: The usbTool utility resides in target/cong/comps/src and is called

usrUsbTool.c. cmdParser This module provides generalized command-line parsing functions used by usbTool. The cmdParser module needs to be present only when usbTool is being used.

USB Developers Kit 1.1.2 Programmers Guide

Figure 1-3

Host Module Roadmap

cmdParser

usbTool USB Exerciser Utility usbSpeakerLib usbMouseLib ...

ossLib

Class Drivers

usbdLib

usbLib usbdCoreLib

usbHcdLib usbQueueLib usbHandleLib usbListLib usbdHcdOhciLib usbdHcdUhciLib HCD for UHCI

usbPciLib (usbPciStub.c) Software Hardware System Hardware (for example, PCI bus controller) UHCI or OHCI Host Controller

1 USB Host Stack

usbKeyboardLib This module is the USB class driver for USB keyboard devices; for more information, see 1.5 Keyboard Driver, p.42. usbMouseLib This module is the USB class driver for USB mouse devices; for more information, see 1.6 Mouse Driver, p.48. usbPrinterLib This module is the USB class driver for USB printer devices; for more information, see 1.7 Printer Driver, p.50. usbSpeakerLib This module is the USB class driver for USB speaker devices; for more information, see 1.8 Speaker Driver, p.53. usbBulkDevLib and usbCbiUDevLib These modules are the USB class drivers for USB Mass Storage Class devices; for more information, see 1.9 Mass Storage Class Driver, p.57. usbPegasusEndLib, usbKlsiEndLib, and usbNC1080EndLib These modules are the USB class drivers for USB Ethernet Networking Control Model Communication Class devices; for more information, see 1.10.1 Ethernet Networking Control Model Driver, p.63. usbAcmLib This module is the USB class driver for USB Abstract Control Model Communication Class devices; for more information, see 1.10.2 Abstract Control Model Driver, p.67. usbdLib and usbdCoreLib These modules contain the functionality of the Wind River USBD. The usbdLib module contains the USBD functions available to USB client modules; and usbdCoreLib exports a single entry point, usbdCoreEntry( ), which is used internally by usbdLib and is never called directly by other modules. usbHcdLib This module provides routines to invoke each of the services provided by a USB HCD. It is used by usbdCoreLib to communicate with underlying HCDs. The routines in usbHcdLib are not called directly by modules other than usbdCoreLib.

USB Developers Kit 1.1.2 Programmers Guide

usbHcdUhciLib and usbHcdOhciLib The usbHcdUhciLib and usbHcdOhciLib modules are the HCDs for UHCI and OHCI host controllers, respectively. All hardware-dependent code for a host controller is contained in the HCD. Each HCD exports a single entry point, generally with a name of the form usbHcdXxxxExec( ), and all communication with the HCD is performed through this routine. There is no direct link between the USBD and any underlying HCDs; that is, the USBD has no prior knowledge of which HCDs will be loaded in a given system. Each HCDs entry point is exposed to the USBD during a process called HCD attachment; for more information, see Attaching and Detaching HCDs, p.12. usbPciLib The module usbPciLib exists conceptually; however, it is available in the form of BSP-dependent les of the format target/cong/BSP/usbPciStub.c. This module provides HCDs with an abstracted view of the underlying PCI hardware and software in a system (both UHCI and OHCI host controllers are implemented with PCI interfaces). So, while different Wind River BSPs use the standard Wind River PCI libraries in different ways, the usbPciLib stub les shield the HCDs from variations among BSPs. This allows HCDs to be written independent of the underlying BSP and promotes portability of HCDs across BSP platforms. ossLib This module provides an abstracted and simplied view of VxWorks operating system services to the USB driver stack. It includes routines that manage tasks, mutexes, semaphores, memory allocation, and system time. usbLib This module provides a mixed collection of USB utility functions shared by various modules. The USBD, HCDs, and certain USB class drivers make use of one or more functions in this module. For example:
I

The usbLib module contains routines that the USBD and HCD use to determine the amount of bandwidth a specied pipe requires. Other usbLib routines provide the functionality that allows class drivers to issue commands to devices using the devices control pipe.

usbQueueLib This module provides an abstracted queue model used by several of the modules in the USB driver stack, principally usbdCoreLib. The usbdCoreLib module uses these queuing services to pass messages among internal usbdCoreLib tasks.

10

1 USB Host Stack

usbHandleLib This module provides an abstracted handle allocation and validation library used by several of the modules in the USB driver stack. The USB driver stack uses handles to prevent callers from passing invalid device and pipe references to the stack. The USB stack also uses the handle mechanism internally to prevent background usbdCoreLib tasks from performing operations on stale data structures. The handle validation mechanisms are optimized and introduce negligible overhead. usbListLib This module provides a generalized set of functions to operate on doubly-linked lists. These functions are used by most of the modules in the USB driver stack, and most data structures in the USB driver stack belong to one or more lists at any given time.

1.3 The USB Host Driver (USBD)


This section describes typical use of the USBD: activities such as initialization, client registration, dynamic attachment registration, device conguration, and data transfers. It also discusses key features of the USBDs internal design.

1.3.1 Initializing the USBD


Initializing the USBD is a two-step process. First, the USBDs entry point, usbdInitialize( ), must be called at least once. The usbdInitialize( ) routine initializes internal USBD data structures and, in turn, calls the initialization entry points of other modules in the USB driver stack. In a given system, it is acceptable to call usbdInitialize( ) once (perhaps during the boot sequence) or to call it many times (as during the initialization of each USBD client). The USBD maintains a usage count that is incremented for each successful call to usbdInitialize( ) and decremented for each corresponding call to usbdShutdown( ). The USBD only truly initializes itself when the usage count goes from zero to one, and it only truly shuts down when the usage count returns to zero.

11

USB Developers Kit 1.1.2 Programmers Guide

The following code fragment illustrates the proper initialization and shutdown of the USBD:
... /* Initialize the USBD. */ if (usbdInitialize () != OK) return ERROR; ... ... /* application code. */ ... ... /* Shut down the USBD. Note: we only execute this code if the return * code from usbdInitialize() was OK. Note also that theres really no * reason to check the result of usbdShutdown(). */ usbdShutdown ();

The second step of USBD initialization is to attach at least one HCD to the USBD, using the USBDs usbdHcdAttach( ) routine. Normally, the attachment of HCDs to the USBD happens during the VxWorks boot sequence. However, the USBD is designed to allow HCDs to be attached (and detached) at run-time. This exibility allows the USBD to support systems in which USB host controllers can be hotswapped without restarting the system.

Attaching and Detaching HCDs

You must decide when to attach HCDs to the USBD and when to detach them (if ever). Typically, USBD clients, such as USB class drivers, are not responsible for attaching HCDs to the USBD. When an HCD is attached to the USBD, the caller passes the HCDs execution entry point (of the form HCD_EXEC_FUNC) and an HCD-dened parameter (the HCD attachment parameter) to the usbdHcdAttach( ) routine. The USBD in turn invokes the HCDs execution entry point with an HCD_FNC_ATTACH service request, passing it the same HCD attachment parameter provided by the caller. Use of this HCD-dened parameter can vary; however, both HCDs provided by Wind River use the parameter in the same way. For the UHCI and OHCI HCDs provided by Wind River, the HCD attachment parameter is a pointer to a structure of type PCI_CFG_HEADER (dened in pciConstants.h). The structure has been initialized with the PCI conguration header for a UHCI or OCHI host controller. The HCD uses the information in this structure to locate and manage the specied host controller. Typically, the caller obtains the PCI conguration header for the desired host controller by calling the usbPciClassFind( ) and usbPciCongHeaderGet( )

12

1 USB Host Stack

routines in usbPciLib (that is, in various stubUsbArchPciLib.c les). If more than one UHCI or OHCI host controller is to be attached to the USBD, these routines should be used repeatedly to obtain the PCI_CFG_HEADER for each host controller, and usbdHcdAttach( ) should be invoked once for each host controller so identied. The following code fragment demonstrates how to attach a UHCI host controller to the USBD:
UINT8 busNo; UINT8 deviceNo; UINT8 funcNo; PCI_CFG_HEADER pciCfgHdr; pciConstants.h */ GENERIC_HANDLE uhciAttachToken; usbHandleLib.h */

/* PCI_CFG_HEADER defined in /* GENERIC_HANDLE defined in

/* Locate the first (0th) UHCI controller. UHCI_CLASS, etc., are defined * in usbUhci.h. The functions usbPciClassFind() and * usbPciConfigHeaderGet() are exported by usbPciLib. */ if (!usbPciClassFind (UHCI_CLASS, UHCI_SUBCLASS, UHCI_PGMIF, 0, &busNo, &deviceNo, &funcNo)) { /* No UHCI controller was found. */ return ERROR; } usbPciConfigHeaderGet (busNo, deviceNo, funcNo, &pciCfgHdr); /* Attach the UHCI HCD to the USBD. The function usbHcdUhciExec() is * exported by usbHcdUhciLib. */ if (usbdHcdAttach (usbHcdUhciExec, &pciCfgHdr, &uhciAttachToken) != OK) { /* USBD failed to attach to UHCI HCD. */ return ERROR; } /* Attachment is complete. */

Detaching an HCD from the USBD is even simpler, as demonstrated in the following code fragment:
/* Detach the UHCI HCD from the HCD. */ usbdHcdDetach (uhciAttachToken); /* Detach is complete! */

13

USB Developers Kit 1.1.2 Programmers Guide

CAUTION: While the USBD and Wind River HCDs are designed to support the

dynamic attachment and detachment of HCDs, certain Wind River BSPs may not support the disconnection of the USB HCD from the underlying PCI interrupt vector, which is essential to the detaching process. If the vector is subsequently re-enabled, the system may attempt to execute a stale interrupt service routine and will fault.

Order of Initialization

The usbdInitialize( ) routine must be called before all other USBD functions, including usbdHcdAttach( ). However, it is not necessary that all USBD clients call usbdInitialize( ) before one or more HCDs have been attached to the USBD. The following two scenarios for initialization sequences are both acceptable:
Scenario #1: Traditional boot time initialization

(1) Boot code calls usbdInitialize( ). (2) Boot code calls usbPciClassFind( ) to locate a USB host controller. (3) Boot code calls usbPciCongHeaderGet( ) to read the host controllers conguration header. (4) Boot code calls usbdHcdAttach( ) to attach the HCD for the identied host controller. (5) Boot code calls the USB class driver initialization entry point. (6) The USB class driver calls usbdInitialize( ).
Scenario #2: Hotswap-driven initialization

(1) Boot code calls the USB class driver initialization entry point. (2) The USB class driver calls usbdInitialize( ). (3) Hotswap code identies the presence or insertion of the USB host controller. (4) Hotswap code calls usbdInitialize( ).

14

1 USB Host Stack

(5) Hotswap code calls usbPciCongHeaderGet( ) to read the host controllers conguration header. (6) Hotswap code calls usbdHcdAttach( ) to attach the HCD for the identied host controller. Similarly, calls to usbdHcdDetach( ) can be made at any time to detach HCDs from the USBD. Outstanding requests to an HCD that is being detached are canceled, and detachment proceeds. To understand why these different scenarios work correctly, it is necessary to recognize that hot-plugging of USB devices can occur at any time. So, both the USBD and its clients must be written (using the dynamic attachment functions described in Dynamic Attachment Registration, p.18) to recognize the appearance and disappearance of USB devices at run-time. It is for this reason that the appearance and disappearance of host controllers can also be handled exibly. When a new host controller is attached to the system, the USBD automatically identies the devices connected to it and noties interested clients. Likewise, when a host controller is removed from the system, the USBD automatically noties interested clients that the devices attached to that host controller have disappeared. The key point here is that USBD clients, such as USB class drivers, never assume that a particular device is present when the client is rst initialized, and these drivers are always ready to accept devices connected to the system at other times.

Bus Tasks

For each host controller attached to the USBD, the USBD spawns a bus task responsible for monitoring bus events, such as the attachment and removal of devices. These tasks are normally dormantthat is, consuming no CPU time and they typically wake up only when a USB hub reports a change on one of its ports. Each USBD bus task has the VxWorks task name tUsbdBus. It is also possible, though not mandated by the design of the USBD, for the HCD itself to create tasks that monitor host controller events. For example, both the UHCI and OHCI HCDs provided by Wind River create such tasks. In the case of the Wind River UHCI module, usbHcdUhciLib, the background task wakes up periodically to poll the status of the UHCI root hub and to check for timed-out I/O request packets (IRPs). In the case of the Wind River OHCI module,

15

USB Developers Kit 1.1.2 Programmers Guide

usbHcdOhciLib, the background task wakes up periodically to check for timed-out IRPs only (OHCI root hub changes are reported by an interrupt).

Registering Client Modules

Client modules that intend to make use of the USBD to communicate with USB devices must, in addition to calling usbdInitialize( ), register with the USBD by calling usbdClientRegister( ). When a client registers with the USBD, the USBD allocates per-client data structures that are later used to track all requests made by that client. During client registration, the USBD also creates a callback task for each registered client (see Client Callback Tasks, p.16). After successfully registering a new client, the USBD returns a handle, USBD_CLIENT_HANDLE, that must be used by that client when making subsequent calls to the USBD. When a client no longer intends to use the USBD, it must call usbdClientUnregister( ) in order to release its per-client data and callback task. Any outstanding USB requests made by the client are canceled at that time. The following code fragment demonstrates the registration and unregistration of a USBD client:
USBD_CLIENT_HANDLE usbdClientHandle; /* Register a client named "USBD_TEST" with the USBD. */ if (usbdClientRegister ("USBD_TEST", &usbdClientHandle) != OK) { /* Attempt to register a new client failed. */ return ERROR; } /* Client is registered...application code follows. */ ... ... /* Unregister the client. */ usbdClientUnregister (usbdClientHandle);

Client Callback Tasks

USB operations can be time-critical. For example, both USB interrupt and isochronous transfers depend on timely servicing in order to work correctly. In a host system in which several different USBD clients are present, the possibility always exists for one client to interfere with the timely execution of other clients needing to service time-sensitive USB trafc. The Wind River USBD introduces per-client callback tasks to manage this problem.

16

1 USB Host Stack

Many USB events can result in callbacks to a USBD client. For example, whenever the USBD completes the execution of a USB IRP, the clients IRP callback routine is invoked. Similarly, whenever the USBD recognizes a dynamic attachment event, one or more clients dynamic attachment callback routines are invoked. Instead of invoking these callback routines immediately, the USBD schedules the callbacks to be performed by the callback task for the appropriate USBD client(s). Normally, the callback task for each client is dormant (in a blocked state). When the USBD schedules a callback for a specied client, the corresponding client callback task wakes up (unblocks) and performs the actual callback. This approach allows the USBD to process all outstanding USB events before the clients themselves obtain control of the CPU. The callback task for each client inherits the VxWorks task priority of the task that originally called usbdClientRegister( ). This ensures that callbacks are processed at the task priority level intended by each client and allows you to write clients to take advantage of task priorities as a means of ensuring proper scheduling of time-sensitive USB trafc. Because each client has its own callback task, clients have greater exibility in the amount of work they can do during the callback. For example, during callback, it is acceptable for executing code to block without hurting the performance of the USBD or other USBD clients. Client callback tasks have the VxWorks task name tUsbdCln.
USBD Internal Client

When rst initialized, the USBD registers an internal client that is used to track USB requests generated by the USBD itself. Only one such internal client is created, regardless of the number of calls to usbdInitialize( ). What types of USB requests can the USBD generate? All USBD communication with USB devices is made using the same calls available to USBD clients. For example, all control pipe requests to a device are made using a control pipe that the USBD creates automatically when a device is rst attached to the system. Just as a USBD client would use usbdPipeCreate( ) to create a pipe to talk to a USB device endpoint, the USBD itself creates a control pipe to talk to endpoint 0 (the default control endpoint) on each device. All internal USBD and external USBD client calls to routines like usbdDescriptorGet( ) or usbdFeatureSet( ) are routed through this pipe. So, the USBD is actually using its own entry points recursively, and the internal client is the USBDs mechanism for tracking these requests.

17

USB Developers Kit 1.1.2 Programmers Guide

Dynamic Attachment Registration

A typical USBD client wants to be notied whenever a device of a particular type is attached to or removed from the system. By calling the usbdDynamicAttachRegister( ) routine, a client can specify a callback routine to request such notication. USB device types are identied by a class, subclass, and protocol. Standard USB classes are dened in usb.h as USB_CLASS_xxxx. Subclass and protocol denitions depend on the class; therefore, these constants are generally dened in the header les associated with a specic class. Sometimes, a client is interested in a narrow range of devices. In this case, it species values for the class, subclass, and protocol when registering through usbdDynamicAttachRegister( ). For example, the USB keyboard class driver, usbKeyboardLib, registers for a Human Interface Device (HID) class of USB_CLASS_HID, a subclass of USB_SUBCLASS_HID_BOOT, and a protocol of USB_PROTOCOL_HID_BOOT_KEYBOARD (both the subclass and protocol are dened in usbHid.h). In response, by means of the callback mechanism, the USBD noties the keyboard class driver whenever a device matching exactly these criteria is attached to or removed from the system. In other cases, a clients interest is broader. In this case, the constant
USBD_NOTIFY_ALL (dened in usbdLib.h) can be substituted for any or all of the

class, subclass, and protocol match criteria. For example, the USB printer class driver, usbPrinterLib, registers for a class of USB_CLASS_PRINTER, subclass of USB_SUBCLASS_PRINTER (dened in usbPrinter.h), and a protocol of USBD_NOTIFY_ALL. While a typical client makes only a single call to usbdDynamicAttachRegister( ), there is no limit to the number of concurrent notication requests a client can have. A single client can register concurrently for attachment notication of as many device types as desired. The following code fragments demonstrate the correct use of the dynamic attachment registration functions:
/*************************************************************************** * * attachCallback - called by USBD when a device is attached/removed * * The USBD invokes this callback when a USB device is attached to or * removed from the system. <nodeId> is the USBD_NODE_ID of the node being * attached or removed. <attachAction> is USBD_DYNA_ATTACH or * USBD_DYNA_REMOVE. *

18

1 USB Host Stack

* RETURNS: N/A */ LOCAL VOID attachCallback ( USBD_NODE_ID nodeId, UINT16 attachAction, UINT16 configuration, UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol ) { /* Depending on the attachment code, add or remove a device. */ switch (attachAction) { case USBD_DYNA_ATTACH: /* A device is being attached. */ printf (New device attached to system.\n); break; case USBD_DYNA_REMOVE: /* A device is being detached. */ printf ("Device removed from system.\n"); break; } }

Somewhere in the initialization of the application, the following code fragment should also appear:
/* Register for dynamic notification when a USB device is attached to or * removed from the system. For the sake of demonstration, well request * notification for USB printers, though this same code could be used for * any other type of device. * * usbdClientHandle is the USBD_CLIENT_HANDLE for the client. * USB_CLASS_PRINTER is defined in usb.h. USB_SUBCLASS_PRINTER is * defined in usbPrinter.h. USBD_NOTIFY_ALL is a wild-card that * matches anything. In this case we use it to match any USB programming * interface. */ if (usbdDynamicAttachRegister (usbdClientHandle, USB_CLASS_PRINTER, USB_SUBCLASS_PRINTER, USBD_NOTIFY_ALL, attachCallback) != OK) { /* Attempt to register for dynamic attachment notification failed. */ return ERROR; } /* attachCallback() - above - is now called whenever a USB keyboard * is attached or removed from the system. */ ... ...

19

USB Developers Kit 1.1.2 Programmers Guide

/* Cancel the dynamic attachment registration. Each parameter must match * exactly those found in an earlier call to usbdDynamicAttachRegister(). */ usbdDynamicAttachUnRegister (usbdClientHandle, USB_CLASS_PRINTER, USB_SUBCLASS_PRINTER, USBD_NOTIFY_ALL, attachCallback);

Node IDs

USB devices are always identied using a USBD_NODE_ID. The USBD_NODE_ID is, in effect, a handle created by the USBD to track a device; it has no relationship to the devices actual USB address. This reects the fact that clients are usually not interested in knowing to which USB/host controller a device is physically attached. Because each device is referred to using the abstract concept of a node ID, the client can remain unconcerned with the details of physical device attachment and USB address assignment, and the USBD can manage these details internally. When a client is notied of the attachment or removal of a device, the USBD always identies the device in question using the USBD_NODE_ID. Likewise, when the client wishes to communicate through the USBD with a particular device, it must pass the USBD_NODE_ID for that device to the USBD.
Bus Enumeration Routines

The usbdLib module exports the routines usbdBusCountGet( ), usbdRootNodeIdGet( ), usbdHubPortCountGet( ), usbdNodeIdGet( ), and usbdNodeInfoGet( ). As a group, these are referred to as bus enumeration routines, and they allow USBD clients to enumerate the network of devices attached to each host controller. These routines are useful in the authoring of diagnostic tools and test programs such as usbTool. However, when the caller uses these routines, it has no way of knowing if the USB topology changes after enumeration or even mid-enumeration. Therefore, authors of traditional clients, such as USB class drivers, are advised not to use these routines.

Device Conguration

The USB specication denes a set of standard requests, a subset of which must be supported by all USB devices. Typically, a client uses these functions to interrogate a devices descriptorsthus determining the devices capabilitiesand to set a particular device conguration. The USBD itself takes care of certain USB conguration issues automatically. Most critically, the USBD internally implements the code necessary to manage USB hubs

20

1 USB Host Stack

and to set device addresses when new devices are added to the USB topology. Clients must not attempt to manage these functions themselves, for doing so is likely to cause the USBD to malfunction. The USBD also monitors so-called conguration events. When a USBD client invokes a USBD function that causes a conguration event, the USBD automatically resets the USB data toggles (DATA0 and DATA1) associated with the devices pipes and endpoints. For example, a call to the USB command usbdCongurationSet( ) issues the set conguration command to the device, and in the process resets the data toggle to DATA0. Because the USBD handles USB data toggles automatically, you do not typically need to concern yourself with resetting data toggles. For an explanation of pipes and endpoints in the USB environment, see Data Flow, p.22. For more information about USB data toggles, see the USB Specication. Device conguration depends heavily on the type of device being congured. The following code fragment demonstrates how to read and parse a typical device descriptor:
UINT8 bfr [USB_MAX_DESCR_LEN]; /* USB_MAX_DESCR_LEN defined in usb.h */ UINT16 actLen; pUSB_CONFIG_DESCR pCfgDescr; /* USB_CONFIG_DESCR defined in usb.h */ pUSB_INTERFACE_DESCR pIfDescr; /* USB_INTERFACE_DESCR is also in usb.h */ /* Read the configuration descriptor. In the following fragment it is * assumed that nodeId was initialized, probably in response to an * earlier call to the clients dynamic attachment notification callback * (see above). */ if (usbdDescriptorGet (usbdClientHandle, nodeId, USB_RT_STANDARD | USB_RT_DEVICE, USB_DESCR_CONFIGURATION, 0, 0, sizeof (bfr), bfr, &actLen) != OK) { /* We failed to read the devices configuration descriptor. */ return FALSE; } /* Use the function usbDescrParse() - exported by usbLib.h - to extract * the configuration descriptor and the first interface descriptor from * the buffer. */ if ((pCfgDescr = usbDescrParse (bfr, actLen, USB_DESCR_CONFIGURATION)) == NULL) { /* No configuration descriptor was found in the buffer. */ return FALSE; }

21

USB Developers Kit 1.1.2 Programmers Guide

if ((pIfDescr = usbDescrParse (bfr, actLen, USB_DESCR_INTERFACE)) == NULL) { /* No interface descriptor was found in the buffer. */ return FALSE; }

Data Flow

Once a client has completely congured a device, it can begin to exchange data with that device using the pipe and transfer functions provided by the USBD. Control, bulk, interrupt, and isochronous transfers are described using a single USB_IRP data structure (dened in usb.h). For more information about the USB_IRP mechanism, see HCD_FNC_IRP_SUBMIT, p.33. USB data transfers are addressed to specic endpoints within each device.1 The channel between a USBD client and a specic device endpoint is called a pipe. Each pipe has a number of characteristics, including:
I I I I I

the USBD_NODE_ID of the device the endpoint number on the device the direction of data transfer bandwidth requirements latency requirements

In order to exchange data with a device, a client must rst create a pipe. In response to a client request to create a new pipe, the USBD creates a USBD_PIPE_HANDLE, which the client must use for all subsequent operations on the pipe. When a client attempts to create a pipe, the USBD checks that sufcient bus bandwidth is available. Bandwidth limits are enforced for interrupt and isochronous pipes. The USBD does not allow more than 90% of the available bus bandwidth to be allocated to interrupt and isochronous pipes. For control and bulk pipes, there is no bandwidth limit. At the same time, there is no guarantee that more than 10% of the bus is available for control transfers, and there is no guarantee that any bus bandwidth is available for bulk transfers.

1. Unlike IEEE-1394, the USB treats an isochronous transfer as an exchange between the USB host and a specic USB device. In contrast, 1394 treats isochronous transfers as a broadcast to which any number of 1394 devices can listen simultaneously.

22

1 USB Host Stack

The following code fragment demonstrates the creation of a pipe for sending data to the bulk output endpoint on a printer:
USBD_PIPE_HANDLE outPipeHandle; /* Create a pipe for output to the printer. It is assumed that endpoint, * configValue, interface, and maxPacketSize were determined by reading * the appropriate descriptors from the device. */ if (usbdPipeCreate (usbdClientHandle, nodeId, endpoint, configValue, interface, USB_XFRTYPE_BULK, USB_DIR_OUT, maxPacketSize, 0, 0, &outPipeHandle) != OK) { /* We failed to create the pipe. */ return ERROR; }

The following fragment demonstrates sending data to the pipe that has just been created:
/*************************************************************************** * * ourIrpCallback - Invoked upon IRP completion/cancellation * * RETURNS: N/A */ LOCAL VOID ourIrpCallback ( pVOID p /* pointer to the completed IRP */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; /* Set status based on whether the IRP completed successfully or not. */ if (pIrp->result == OK) { /* IRP was successful. */ } else /* IRP failed. */ } }

23

USB Developers Kit 1.1.2 Programmers Guide

Then, elsewhere in the code, the following should appear:


UINT8 bfr [4096]; /* a buffer of arbitrary size. */ UINT16 bfrCount; /* amount of data in the buffer. */ USB_IRP irp; /* The code here would presumably put data into the buffer and initialize * bfrCount with the amount of data in the buffer. */ ... ... /* Send bfr to the printer. */ /* Initialize IRP. */ memset (irp, 0, sizeof (irp)); irp.userPtr = ourUserPtr; /* some value of use to our callback */ irp.irpLen = sizeof (*pIrp); /* the length of the IRP */ irp.userCallback = ourIrpCallback; /* our IRP completion callback */ irp.timeout = 30000; /* 30 second timeout */ irp.transferLen = bfrCount; irp.bfrCount = 1; irp.bfrList [0].pid = USB_PID_OUT; irp.bfrList [0].pBfr = bfr; irp.bfrList [0].bfrLen = count; /* Submit IRP */ if (usbdTransfer (usbdClientHandle, outPipeHandle, &irp) != OK) { /* An error here means that our IRP was malformed. */ return ERROR; } /* The IRP will complete asynchronously. ourIrpCallback() will be invoked * by the USBD when the IRP is complete. */

1.3.2 USBD Internals


Hub Management

The management of USB hubs is integral to the proper functioning of the Wind River USBD; therefore, USBD clients should not attempt to modify the conguration of a USB hub attached to the system. Doing so will likely cause the USBD to malfunction. When the USBD detects a hub, it checks to see whether the hubs power requirements can be metin other words, can the upstream hub to which the hub is connected provide enough power. If so, the USBD automatically congures the hub and creates a pipe to monitor the hubs status endpoint. If there is insufcient

24

1 USB Host Stack

power for the hub or insufcient bus bandwidth to create the pipe, the USBD refuses to recognize the hub.

New Device Connections

When a device is connected to one of a hubs ports, the USBD checks to see whether the attachment of the device exceeds the maximum topology depth allowed by the USB (six levels). Then the USBD tries to read the devices class information, rst by reading the devices device descriptor or, alternatively, by reading its conguration and interface descriptors, if the device descriptor does not declare the class information. If either of these steps fails, the USBD refuses to recognize the device. If the device is recognized successfully, the USBD automatically noties any clients registered for dynamic attachment notication that the new device has been attached to the system. If a device is not recognized for any reason, the USBD disables the port to which the device is connected. In this case, the USBD itself is unable to determine the type of device, and no dynamic attachment notication callbacks are invoked. If a USBD client calls usbdNodeIdGet( ) to query the hub port of an unrecognized device, the USBD indicates that no device is attached to the port.

1.4 The USB Host Controller Driver (HCD)


This section describes the interface and requirements for HCDs. This information is essential if you are creating an HCD for a host controller that Wind River does not already support.

1.4.1 HCD Header File


All HCDs implement the interface as dened in usbHcd.h.

25

USB Developers Kit 1.1.2 Programmers Guide

1.4.2 HCD Entry Point


Each HCD exports a single entry point, its execution entry point. This function takes the following form:
typedef STATUS (*HCD_EXEC_FUNC) (pVOID pHrb);

1.4.3 Host Request Blocks (HRB)


All requests to the HCD are made by constructing Host Request Blocks (HRBs) and passing them to the HCDs execution entry point for processing. HRBs begin with a common header, followed by parameters unique to the function being executed. The format of the header is as follows:
typedef struct hrb_header { HCD_CLIENT_HANDLE handle; UINT16 function; UINT16 hrbLength; } HRB_HEADER, *pHRB_HEADER;

/* I/O: caller's HCD client handle */ /* IN: HCD function code */ /* IN: Length of the total HRB */

When an HCD is attached, a handle to the host controller is created. That handle, stored in the handle eld, is used by all host controller driver functions; however, each time an HCD is attached, a new handle is created. The function eld in HRB_HEADER denes one of the following functions as the HCD function to be executed:
HCD_FNC_ATTACH HCD_FNC_BUS_RESET HCD_FNC_SOF_INTERVAL_GET HCD_FNC_PIPE_CREATE HCD_FNC_PIPE_MODIFY HCD_FNC_IRP_SUBMIT HCD_FNC_DETACH HCD_FNC_SET_BUS_STATE HCD_FNC_SOF_INTERVAL_SET HCD_FNC_PIPE_DESTROY HCD_FNC_CURRENT_FRAME_GET HCD_FNC_IRP_CANCEL

An HCD must implement all of these functions in order to perform properly. The hrbLength eld is set by the caller to be the total length of the HRB, including the header and any additional parameters that follow. Each HCD function, including any associated HRB, is described in the following sections.

26

1 USB Host Stack

HCD_FNC_ATTACH

This function is contained in the following HRB:


typedef struct hrb_attach { HRB_HEADER header; /* HRB header */ pVOID param; /* IN: HCD-specific parameter */ USB_HCD_MNGMT_CALLBACK mngmtCallback; /* IN: USBD's callback for mngmt events */ pVOID mngmtCallbackParam; /* IN: USBD-defined parameter to callback */ UINT16 busCount; /* OUT: number of buses managed by HCD */ } HRB_ATTACH, *pHRB_ATTACH;

In response to an HCD_FNC_ATTACH request, an HCD initializes one or more USB host controllers, thereby enabling the USB(s) attached to those host controller(s). The USBD invokes the HCDs HCD_FNC_ATTACH function when usbdHcdAttach( ) is called. Unlike other HCD functions, the USBD does not store an existing HCD_CLIENT_HANDLE in the HRB_HEADER.handle eld. Instead, upon successful completion of this routine, the HCD is expected to store a newly created HCD_CLIENT_HANDLE in the HRB_HEADER.handle eld so that the USBD can retrieve it. The USBD uses the newly created HCD_CLIENT_HANDLE to identify the indicated USB host controller in subsequent calls to the HCD. Typically, the HCD casts the newly created HCD_CLIENT_HANDLE as a pointer to an internal HCD data structure used to manage a specic host controller. The HCD-dened parameter passed to the usbdHcdAttach( ) routine is in turn passed in the param eld. The USBD makes no attempt to interpret the meaning of this parameter. The HCD can use the param eld as needed; for example, the UHCI and OHCI HCDs provided by Wind River cast this parameter to a pointer to a PCI_CFG_HEADER structure (dened in pciConstants.h). The UHCI and OHCI HCDs assume that this structure has already been initialized with the PCI conguration header of a USB host controller. The mngmtCallback parameter is a pointer to a function within the USBD that the HCD should call when it detects certain USB management events. This function takes the following form:
typedef VOID (*USB_HCD_MNGMT_CALLBACK) ( pVOID mngmtCallbackParam, /* caller-defined parameter */ HCD_CLIENT_HANDLE handle, /* handle to host controller */ UINT16 busNo, /* bus number */ UINT16 mngmtCode /* management code */ );

27

USB Developers Kit 1.1.2 Programmers Guide

Management events are described in 1.4.4 Management Events, p.39. The mngmtCallbackParam is a USBD-dened parameter that the HCD must pass to the USBD whenever the HCD calls the mngmtCallback function. Finally, the HCD must return the number of host controllers initialized in the busCount eld. The UHCI and OCHI HCDs provided by Wind River always return 1 in this eld. However, other HCDs can initialize multiple host controllers in response to a single HCD_FNC_ATTACH request. When a value greater than one is returned in busCount, the USBD identies individual host controllers using a combination of the HCD_CLIENT_HANDLE and a host controller index in the range 0..busCount - 1. When busCount is returned as 1, the USBD always passes a host controller index of 0 to the HCD.

HCD_FNC_DETACH

This function is contained in the following HRB:


typedef struct hrb_detach { HRB_HEADER header; } HRB_DETACH, *pHRB_DETACH;

/* HRB header */

The USBD invokes the HCD_FNC_DETACH function when the HCD must shut down the host controller(s) specied by HCD_CLIENT_HANDLE. Two conditions prompt the USBD to do this:
I

A call to the usbdHcdDetach( ) routine. Automatically, when the USBDs usage count goes to zero as a result of a call to usbdShutdown( ).

In response to this function, the HCD disables the specied host controller(s) and releases any memory and other resources allocated on behalf of the specied host controller(s).

HCD_FNC_BUS_RESET

This function is contained in the following HRB:


typedef struct hrb_bus_reset { HRB_HEADER header;

/* HRB header */

28

1 USB Host Stack

UINT16 busNo; /* IN: bus number to reset */ } HRB_BUS_RESET, *pHRB_BUS_RESET;

The USBD invokes the HCD_FNC_BUS_RESET function to reset a USB. The HCD_CLIENT_HANDLE passed in HRB.HRB_HEADER.handle species the USB to be reset, and the host controller index passed in busNo species the host controller to be reset. When driving the signaling of a USB reset, the HCD must ensure that USB reset timing requirements are met. That is, the reset width must be at least USB_TIME_RESET and the HCD should wait USB_TIME_RESET_RECOVERY after resetting the bus. Both of these time management constants are dened in usb.h.

HCD_FNC_SET_BUS_STATE

This function is contained in the following HRB:


typedef struct hrb_set_bus_state { HRB_HEADER header; /* HRB header */ UINT16 busNo; /* IN: bus number */ UINT16 busState; /* IN: new bus state, HCD_BUS_xxxx */ } HRB_SET_BUS_STATE, *pHRB_SET_BUS_STATE;

The USBD controls global SUSPEND and global RESUME states with the HCD_FNC_SET_BUS_STATE function. To place a host controller in the global SUSPEND state, the USBD invokes this function with the eld busState set to HCD_BUS_SUSPEND. To bring the host controller out of the SUSPEND state, the USBD invokes this function with busState set to HCD_BUS_RESUME. The HCD responds by placing the specied host controller, busNo, in the specied state.

HCD_FNC_SOF_INTERVAL_GET and HCD_FNC_SOF_INTERVAL_SET

These functions share the following HRB:


typedef struct hrb_sof_interval_get_set { HRB_HEADER header; /* HRB header */ UINT16 busNo; /* IN: bus index */ UINT16 sofInterval; /* I/O: SOF interval */ } HRB_SOF_INTERVAL_GET_SET, *pHRB_SOF_INTERVAL_GET_SET;

29

USB Developers Kit 1.1.2 Programmers Guide

Most USB host controllers can adjust start-of-frame (SOF) timing within a narrow range ( 1 bit-time). This adjustment allows time-sensitive applications to tune the real-time behavior of the USB to meet strict isochronous timing requirements. The entire frame is called an interval. The HCD responds to these functions by setting or requesting the current SOF interval for a specied host controller, busNo. It returns the current SOF interval in the sofInterval eld. The value returned is expressed as the current number of bit-times in each frame. The default value should always be 12,000.

HCD_FNC_PIPE_CREATE

This function is contained in the following HRB:


typedef struct hrb_pipe_create { HRB_HEADER header; /* HRB header */ UINT16 busNo; /* IN: bus index: 0, 1, ... */ UINT16 busAddress; /* IN: bus address of USB device */ UINT16 endpoint; /* IN: endpoint on device */ UINT16 transferType; /* IN: transfer type */ UINT16 direction; /* IN: transfer/pipe direction */ UINT16 speed; /* IN: transfer speed */ UINT16 maxPacketSize; /* IN: packet size */ UINT16 bytesPerFrame; /* IN: number of bytes per frame */ UINT16 interval; /* IN: service interval */ UINT32 time; /* OUT: calcd transfer time in nanosecs */ HCD_PIPE_HANDLE pipeHandle; /* OUT: pipe handle */ } HRB_PIPE_CREATE, *pHRB_PIPE_CREATE;

The USBD invokes the HCD_FNC_PIPE_CREATE function when creating a pipe. The structures elements specify a new pipes attributes as follows: busAddress Species the USB bus address of the device. endpoint Species the endpoint on the device. transferType Species the type of pipe as one of the following:
USB_XFRTYPE_CONTROL USB_XFRTYPE_BULK USB_XFRTYPE_INTERRUPT USB_XFRTYPE_ISOCH

30

1 USB Host Stack

direction (control pipes only) Species the direction of the control pipe as one of the following:
USB_DIR_IN USB_DIR_OUT USB_DIR_INOUT

speed Species the speed of the device as USB_SPEED_FULL (12 Mbps) or USB_SPEED_LOW (1.5 Mbps). maxPacketSize Species the maximum packet size supported by the endpoint. bytesPerFrame For periodic transfers (interrupt and isochronous), species the number of bytes to be transferred on the pipe in each 1 millisecond frame. interval Species the service interval for interrupt pipes. time Based on the values of transferType, direction, speed, maxPacketSize, and bytesPerFrame, the HCD calculates the worst-case recurring bandwidth required for the pipe and returns it in the time eld. This value is always 0 (zero) for control and bulk pipes because they do not involve recurring transfers and are not guaranteed bandwidth. The calculation for interrupt and isochronous pipes is greatly simplied by the usbRecurringTime( ) routine in usbLib. It uses the parameters of HCD_FNC_PIPE_CREATE and two hardware-specic parameters provided by the HCD to generate the value returned in time. For more information about these HCD parameters, see the reference entry for usbTransferTime( ). The HCD keeps track of the total amount of bandwidth allocated for each host controller it manages. If the amount of bandwidth requested exceeds the maximum amount of bus bandwidth available for interrupt and isochronous transfers (90% of total bus bandwidth), the HCD returns the error S_usbHcdLib_BANDWIDTH_FAULT. Finally, the HCD must return a non-NULL HCD_PIPE_HANDLE in pipeHandle. The USBD records this value and passes it to the HCD_FNC_IRP_SUBMIT function when subsequently submitting IRPs for execution on the pipe.

31

USB Developers Kit 1.1.2 Programmers Guide

HCD_FNC_PIPE_DESTROY

This function is contained in the following HRB:


typedef struct hrb_pipe_destroy { HRB_HEADER header; /* HRB header */ HCD_PIPE_HANDLE pipeHandle; /* IN: pipe to be destroyed */ } HRB_PIPE_DESTROY, *pHRB_PIPE_DESTROY;

The USBD invokes the HCD_FNC_PIPE_DESTROY function to notify the HCD that a specied pipe is being torn down and that the bandwidth associated with that pipe should be released. The HCD responds by releasing the amount of bandwidth originally allocated to the pipe and releasing any data structures and other resources allocated on behalf of the pipe. Before invoking this function, the USBD cancels any outstanding IRPs on the pipe.

HCD_FNC_PIPE_MODIFY

This function is contained in the following HRB:


typedef struct hrb_pipe_modify { HRB_HEADER header; /* HRB header */ HCD_PIPE_HANDLE pipeHandle; /* IN: pipe to modify */ UINT16 busAddress; /* IN: new bus address, or 0 if unchanged */ UINT16 maxPacketSize; /* IN: new max pkt size, or 0 if unchanged */ } HRB_PIPE_MODIFY, *pHRB_PIPE_MODIFY;

The HCD_FNC_PIPE_MODIFY function allows the USBD to modify pipe attributes after creating the default control pipe. When the USBD creates the default control pipe for a device, it must read the devices device descriptor before it can know the maximum packet size that the packet permits. Also, the USBD generally assigns a new USB address to a device after establishing communication with the devices default control pipe. By convention, when creating the default control pipe, the USBD species a device address of 0 and a maximum packet size of 8 (the minimum required by the USB Specication). Typically, after the host obtains the device descriptor, it issues the command to set a new, non-zero address for the device specied by pipeHandle. Then, after the device address has been changed, the USBD invokes HCD_FNC_PIPE_MODIFY to change the busAddress and maxPacketSize attributes.

32

1 USB Host Stack

HCD_FNC_CURRENT_FRAME_GET

This function is contained in the following HRB:


typedef struct hrb_current_frame_get { HRB_HEADER header; /* HRB header */ UINT16 busNo; /* IN: bus index: 0, 1, ... */ UINT16 frameNo; /* OUT: current frame number */ UINT16 frameWindow; /* OUT: frame window size */ } HRB_CURRENT_FRAME_GET, *pHRB_CURRENT_FRAME_GET;

USBD clients use this function to retrieve the current USB frame number for a specied host controller, busNo. In response to this function, the HCD stores the current USB frame number in the frameNo eld and the maximum number of unique frame numbers tracked by the host controller in the frameWindow eld. For example, most USB host controllers are capable of counting frame numbers from 0 to 1023 or from 0 to 2047. In such cases, frameWindow should be returned as 1024 or 2048, respectively.

HCD_FNC_IRP_SUBMIT

This function is contained in the following HRB:


typedef struct hrb_irp_submit { HRB_HEADER header; /* HRB header */ HCD_PIPE_HANDLE pipeHandle; /* IN: pipe to which IRP is directed */ pUSB_IRP pIrp; /* IN: pointer to IRP */ } HRB_IRP_SUBMIT, *pHRB_IRP_SUBMIT;

The USBD uses the HCD_FNC_IRP_SUBMIT function to pass a USB_IRP data structure to the HCD for execution on a specied pipe. IRPs are a mechanism for scheduling data transfers across the USB. See below for additional information about the USB_IRP structure. Use the pipeHandle parameter to specify the HCD_PIPE_HANDLE for a pipe previously created through the HCD_FNC_PIPE_CREATE function. In response, the HCD queues the IRP and returns immediately. The HCD noties the USBD when the IRP is complete by invoking the USBDs IRP callback function (identied in the usbdCallback eld of the IRP). After accepting an IRP for execution, an HCD must guarantee that it will invoke the USBDs IRP callback

33

USB Developers Kit 1.1.2 Programmers Guide

function when the IRP completes for any reason, including being canceled (see HCD_FNC_IRP_CANCEL, p.39). The HCD can omit the call to the USBDs IRP callback function if it detects a malformed HRB or IRP when the IRP is initially passed to the HCD_FNC_IRP_SUBMIT function. If this is the case, the HCD returns an error, indicating to the USBD that the HCD refused to accept the IRP.
USB_IRP Data Structure.

The structure of a USB_IRP takes the following form:


typedef struct usb_irp { LINK usbdLink; pVOID usbdPtr; LINK hcdLink; pVOID hcdPtr; pVOID userPtr; UINT16 irpLen; int result; IRP_CALLBACK usbdCallback; IRP_CALLBACK userCallback; UINT16 dataToggle; UINT16 flags; UINT32 timeout; UINT16 startFrame; UINT16 dataBlockSize; UINT32 transferLen; UINT16 bfrCount; USB_BFR_LIST bfrList [1]; } USB_IRP, *pUSB_IRP;

/* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /*

link field used internally by USBD */ pointer field for use by USBD */ link field used internally by USB HCD */ pointer field for use by USB HCD */ pointer field for use by client */ total length of IRP structure */ IRP completion result: S_usbHcdLib_xxxx */ USBD completion callback routine */ client's completion callback routine */ IRP should start with DATA0/DATA1. */ defines other IRP processing options */ IRP timeout in milliseconds */ start frame for isochronous transfer */ granularity of data for isoch. transfer */ total length of data to be transferred */ indicates count of buffers in BfrList */

The following elds comprise the IRP data structure: usbdLink This eld is used internally by the USBD. usbdPtr This eld is used internally by the USBD. hcdLink This eld is reserved for use only by the HCD, not other modules. Typically, the HCD uses the hcdLink eld to bind the USB_IRP to a linked list of USB_IRPs being managed by the HCD.

34

1 USB Host Stack

hcdPtr This eld is reserved for use only by the HCD, not other modules. Typically, the HCD uses the hcdPtr eld to store a pointer to HCD data related to the USB_IRP. userPtr This eld is reserved for use by the USBD client that initially created the USB_IRP and submitted it for execution. irpLen This eld is initialized by the USBD client with the total length, in bytes, of the USB_IRP structure. The last eld of the USB_IRP is an array of USB_BFR_LIST entries, so the total length of the IRP is not known in advance; however, the total length of the IRP equals the size of the USB_IRP structure plus the size of all the buffers associated with the IRP, as follows:
irpLen = sizeof (USB_IRP) + (sizeof (USB_BFR_LIST) x (bfrCount -1))

result This eld is used to pass the completion status of the IRP. For more information about the use of the result eld, see 1.4.5 HCD Error Reporting Conventions, p.40. usbdCallback This eld is a non-NULL pointer to a callback routine within the USBD. The HCD must call this routine upon IRP completion. userCallback This eld, if non-NULL, is the address of a USBD client callback routine. The USBD invokes this routine upon IRP completion. dataToggle This eld is initialized by the USBD as USB_DATA0 or USB_DATA1 and indicates the starting USB data toggle that the HCD uses when transferring data for the USB_IRP. The USBD automatically calculates the next data toggle value for each IRP; therefore, the USBD client and the HCD do not need to maintain this information across IRPs. The HCD can modify the value of dataToggle while executing the USB_IRP. Neither the USBD nor the USBD client examines the dataToggle eld upon IRP completion. ags This eld contains a bit mask of ags that control IRP execution. USB_FLAG_SHORT_OK (the default if no ag is specied) indicates that a data underrun on input buffers is acceptable. USB_FLAG_SHORT_FAIL indicates that a data underrun should be treated as a fatal error. USB_FLAG_ISO_ASAP

35

USB Developers Kit 1.1.2 Programmers Guide

is used only with USB_IRPs that describe isochronous transfers. If USB_FLAG_ISO_ASAP is specied, the HCD ignores the startFrame eld in the USB_IRP and instead schedules the isochronous transfer for the next available frame. If USB_FLAG_ISO_ASAP is not specied, startFrame must specify the starting frame number for an isochronous data transfer. timeout This eld species the USB_IRP timeout in milliseconds. A value of USB_TIMEOUT_NONE indicates that the USB_IRP should never time out. Typically, interrupt and isochronous USB_IRPs specify a timeout value of USB_TIMEOUT_NONE (no timeout); control and bulk USB_IRPs specify a timeout of USB_TIMEOUT_DEFAULT where USB_TIMEOUT_DEFAULT equals 5,000 (that is, ve seconds). A timeout value of zero (0) is interpreted as a request for the default timeout. startFrame This eld species the starting frame number for an isochronous data transfer. (See also the discussion of the ags eld above.) dataBlockSize This eld can be specied for isochronous transfers. If non-0, dataBlockSize denes the granularity of isochronous data being sent. When the underlying HCD breaks up the isochronous transfer into individual frames, it ensures that the amount of data transferred in each frame is a multiple of the value of dataBlockSize. transferLen This eld provides the total length of the data to be transferred by the USB_IRP. It is equal to the sum of the bfrLen elds in each USB_BFR_LIST entry (see below). bfrCount This eld species the number of USB_BFR_LIST entries that follow. Each USB_BFR_LIST can be thought of as a scatter-gather list entry, each specifying a different region of memory to be transferred and the type of transfer (SETUP, IN, or OUT). For more information on the USB_BFR_LIST structure, see below.
USB_BFR_LIST Structure and Conventions.

The structure of USB_BFR_LIST is as follows:


typedef struct usb_bfr_list { UINT16 pid; /* specifies packet type as USB_PID_xxxx */ pUINT8 pBfr; /* pointer to buffer */ UINT32 bfrLen; /* length of buffer */

36

1 USB Host Stack

UINT32 actLen; /* actual length transferred */ } USB_BFR_LIST, *pUSB_BFR_LIST;

The following elds comprise the USB buffer list structure: pid This eld species the type of transfers as USB_PID_SETUP, USB_PID_IN, or USB_PID_OUT. pBfr This eld species the location of the buffer. If pBfr is NULL and bfrLen is 0, the HCD transfers a 0-byte packet. bfrLen This eld species the length of the buffer. If pBfr is NULL and bfrLen is 0, the HCD transfers a 0-byte packet. actLen Upon completion of each USB_BFR_LIST entry, the HCD must store the actual length of data transferred in this eld. By convention, there are several additional limitations on the structure of USB_IRPs passed to the HCD:
I

USB_IRPs that describe control transfers must always have two or three bfrList

entries (bfrCount equals 2 or 3), depending on whether the setup transfer involves a data phase. The rst bfrList entry must have a pid value of USB_PID_SETUP and must describe the SETUP transaction. If the SETUP transfer involves a data phase, the second bfrList entry must have a pid value of USB_PID_IN or USB_PID_OUT and must describe the data phase. If there is a data phase, the third bfrList entry must have a pid value opposite to that of the data phase and must describe a 0-byte packet (pBfr equals NULL and bfrLen equals 0). If there is no data phase, the second bfrList entry must have a pid value of USB_PID_IN and must describe a 0-byte packet. Following these rules, a single USB_IRP always describes a complete SETUP transfer.
I

USB_IRPs describing interrupt transfers generally have only a single bfrList entry with a pid value of USB_PID_IN or USB_PID_OUT; however, this is

essentially a practical consideration because most interrupt transfers are smaller than the maximum size of the packet for a specied interrupt pipe. This is not a mandatory requirement.
I

USB_IRPs describing bulk transfers can have an unlimited number of bfrList

entries. Because USB bulk and interrupt pipes are uni-directional (one-way),

37

USB Developers Kit 1.1.2 Programmers Guide

the pid value of all bfrList entries must be the same and must correspond to the direction of the pipe.
I

USB_IRPs that describe isochronous transfers must have only one USB_BFR_LIST entry. In general, the buffer that the USB_BFR_LIST entry

describes should be large enough to span n frames, where n is comfortably larger than the interrupt latency of the target system (measured in milliseconds). The HCDs provided by Wind River automatically split the buffer into frames of the appropriate size to maintain the average transfer rate specied for the corresponding pipe.
USB_IRP Queuing Conventions

The USBD never submits more than one SETUP transfer for a particular device at one time. (The USBD internally serializes any attempts to schedule simultaneous control transfers to a single device.) By convention, when using the Wind River-provided UHCI and OHCI HCDs, USBD clients should never attempt to queue more than one bulk or interrupt transfer for a particular pipe at the same time. The Wind River HCDs make no attempt to serialize multiple USB_IRPs. Therefore, queuing multiple bulk transfers at the same time likely causes data to be exchanged with the device in an unpredictable order. (The USBD does not enforce this convention, so it is possible for third parties to create HCDs and USBD clients that do not adhere to this rule.) Similarly, Wind River HCDs do not serialize concurrent interrupt USB_IRPs directed at the same pipe; therefore, USBD clients should avoid queuing more than a single interrupt USB_IRP for a particular interrupt pipe at one time. (Again, the USBD does not enforce this convention, so third-party HCD/client combinations may be coded to behave differently.) On the contrary, USBD clients should maintain a queue of at least two USB_IRPs for each active isochronous pipe, if the isochronous data ow is to continue uninterrupted. Because isochronous USB_IRPs generally dene the startFrame eld for each isochronous transfer, the HCD has enough information to schedule each USB_IRP for execution at the correct time. Therefore, double-buffering USB_IRPs for isochronous transfers allows the HCD to eliminate dead-time, ensuring a continuous ow of time-sensitive data. The Wind River UHCI and OHCI HCDs are implemented to ensure continuous isochronous data transfer, provided the USBD client uses at least two USB_IRPs to maintain double-buffering.

38

1 USB Host Stack

HCD_FNC_IRP_CANCEL

This function is contained in the following HRB:


typedef struct hrb_irp_cancel { HRB_HEADER header; /* HRB header */ pUSB_IRP pIrp; /* IN: pointer to IPR to be canceled */ } HRB_IRP_CANCEL, *pHRB_IRP_CANCEL;

The USBD uses the HCD_FNC_IRP_CANCEL function to cancel an outstanding IRP previously passed to the HCD through the HCD_FNC_IRP_SUBMIT function. If the specied IRP is still outstanding (that is, it has not yet completed, either successfully or with an error), the HCD must cancel the IRP and set the USB_IRP.result eld to S_usbHcdLib_IRP_CANCELED. If the IRP has already completed, the HCD returns the error S_usbHcdLib_CANNOT_CANCEL in response to the HCD_FNC_IRP_CANCEL request.

1.4.4 Management Events


The management callback provided by the USBD to the HCD as part of the HCD_FNC_ATTACH request gives the HCD a way to notify the USBD when it detects asynchronous management events. The format of the callback is as follows:
typedef VOID (*USB_HCD_MNGMT_CALLBACK) ( pVOID mngmtCallbackParam, /* HCD_CLIENT_HANDLE handle, /* UINT16 busNo, /* UINT16 mngmtCode /* );

caller-defined parameter */ handle to host controller */ bus number */ management code */

The mngmtCallbackParam parameter passed to the callback is the HRB.mngmtCallbackParam value originally passed to the HCD during the HCD_FNC_ATTACH request. The handle parameter is the HCD-assigned HCD_CLIENT_HANDLE for the corresponding host controller(s), and the busNo parameter is the index of the specic host controller reporting the management event. At the present time, the USBD/HCD interface denes only one type of management event, HCD_MNGMT_RESUME. The management code is passed to the USBDs callback in the mngmtCode parameter.

39

USB Developers Kit 1.1.2 Programmers Guide

HCD_MNGMT_RESUME

Most available host controllers in the SUSPEND state can detect a request by a USB device to resume. This feature, called remote wakeup, can be used to bring a suspended bus back to normal operation. If the HCD detects that a USB device is driving RESUME signaling on the USB while the host controller is in the SUSPEND state, the HCD should invoke the USBDs management callback, passing the value HCD_MNGMT_RESUME in the mngmtCode parameter.

1.4.5 HCD Error Reporting Conventions


A number of standard HCD error codes are dened in usbHcd.h. You are encouraged to use the existing HCD error codes when creating new HCDs. These error codes are returned both in response to HCD function requests through the HCDs execution entry point, as well as in the result eld of each USB_IRP processed by the HCD. (For more information about the USB_IRP result eld, see HCD_FNC_IRP_SUBMIT, p.33.) To conform to Wind River conventions, the HCD should also set the system errno whenever returning an error. HCDs return the standard VxWorks constant OK when a function or IRP completes successfully. HCD error codes are dened as follows:
S_usbHcdLib_BAD_CLIENT S_usbHcdLib_BAD_HANDLE S_usbHcdLib_OUT_OF_RESOURCES S_usbHcdLib_GENERAL_FAULT S_usbHcdLib_INT_HOOK_FAILED S_usbHcdLib_HW_NOT_READY S_usbHcdLib_SHUTDOWN S_usbHcdLib_STALLED S_usbHcdLib_BABBLE S_usbHcdLib_TIMEOUT S_usbHcdLib_SHORT_PACKET S_usbHcdLib_BANDWIDTH_FAULT S_usbHcdLib_DATA_TOGGLE_FAULT S_usbHcdLib_ISOCH_FAULT S_usbHcdLib_BAD_PARAM S_usbHcdLib_OUT_OF_MEMORY S_usbHcdLib_NOT_IMPLEMENTED S_usbHcdLib_NOT_INITIALIZED S_usbHcdLib_STRUCT_SIZE_FAULT S_usbHcdLib_NOT_SUPPORTED S_usbHcdLib_IRP_CANCELED S_usbHcdLib_DATA_BFR_FAULT S_usbHcdLib_CRC_TIMEOUT S_usbHcdLib_BITSTUFF_FAULT S_usbHcdLib_CANNOT_CANCEL S_usbHcdLib_SOF_INTERVAL_FAULT S_usbHcdLib_PID_FAULT

In particular, HCDs must store the error code S_usbHcdLib_IRP_CANCELED in the result eld of USB_IRPs that have been canceled for any reason. Higher layers rely on this error code to recognize situations in which IRPs should not be retried. For their own convenience, HCDs can temporarily store other values in the
USB_IRP result eld while processing IRPs. For example, the UHCI and OHCI

40

1 USB Host Stack

HCDs provided by Wind River use this eld temporarily while executing the IRP, to store a value indicating that the IRP is pending. However, before invoking an IRPs completion callback routine, the HCD is required to store either the constant OK or one of the above error codes in the USB_IRP result eld.

1.4.6 Root Emulation


HCDs are required to emulate the behavior of the root hub. That is, HCDs must intercept transfer requests intended for the root hub and must synthesize standard USB responses to these requests. For example, when a host controller is rst initialized by the HCD_FNC_ATTACH request, the root hub must respond at the default USB address 0, and its downstream ports must be disabled. The USBD interrogates the root hub, just as it would other hubs, by issuing USB GET_DESCRIPTOR requests. The USBD then congures the root hub for operation by issuing a series of SET_ADDRESS, SET_CONFIGURATION, SET_FEATURE, and CLEAR_FEATURE requests. The HCD is responsible for recognizing which of these requests are intended for the root hub and must respond to them appropriately. After conguration, the USBD begins polling the root hubs interrupt status pipe to monitor changes on the root hubs downstream ports. The HCD must intercept IRPs directed to the root hubs interrupt endpoint and synthesize appropriate replies. Typically, the HCD queues USB_IRPs directed to the root hub separately from those that actually result in bus operations. For example, the UHCI and OHCI HCDs provided by Wind River queue the USB_IRPs sent to the root hub and spawn a background task to synthesize responses to these IRPs. The background task typically polls the host controller hardware several times per second to determine whether there has been a change in state on one of the root hubs downstream ports. The source les for the HCDs provided by Wind River include complete examples of the root hub emulation required of each. See the following source les:
I

for UHCI HCD: usbHcdUhciLib.c for OHCI HCD: usbHcdOhciLib.c

1.4.7 IRP Timeouts


Each HCD is responsible for determining whether a particular IRP has timed out, and when. The allowable execution time for each IRP is stored in the

41

USB Developers Kit 1.1.2 Programmers Guide

USB_IRP.timeout eld. Typically, IRPs have a default timeout of 5 seconds (dened as USB_TIMEOUT_DEFAULT in usb.h). However, certain IRPs, such as those used

to monitor interrupt status input from hubs, can have no timeout (dened as
USB_TIMEOUT_NONE in usb.h).

Typically, a background task spawned by the HCD during HCD_FNC_ATTACH processing is the mechanism used to detect when IRPs reach their timeouts. In the case of the Wind River UHCI HCD, this same background task periodically polls the root hub for port status changes (as described in 1.4.6 Root Emulation, p.41). This background task is named tUhciInt, whereas the background task spawned by the Wind River OHCI HCD is named tOhciInt.

1.5 Keyboard Driver


USB keyboards are described in Human Interface Device (HID) related specications. The Wind River implementation of the USB keyboard driver, usbKeyboardLib, is concerned only with USB devices claiming to be keyboards as set forth in the USB Specication; the driver ignores other types of human interface devices, such as printers.
NOTE: USB keyboards can operate according to either a boot protocol or a report

protocol; however, the usbKeyboardLib driver enables keyboards for operation using the boot protocol only.

1.5.1 SIO Driver Model


The USB keyboard class driver, usbKeyboardLib, follows the VxWorks serial I/O (SIO) driver model, with certain exceptions and extensions. As the SIO driver model presents a fairly limited, byte-stream-oriented view of a serial device, the keyboard driver maps USB keyboard scan codes into appropriate ASCII codes. Scan codes and combinations of scan codes that do not map to the ASCII character set are suppressed.

42

1 USB Host Stack

1.5.2 Dynamic Attachment


Unlike most SIO drivers, the usbKeyboardLib drivers number of supported channels is not xed. Rather, USB keyboards can be added or removed from the system at any time. Thus, the number of channels is dynamic, and clients of usbKeyboardLib must be made aware of the appearance and disappearance of channels. Therefore, this driver includes a set of routines that allows clients to register for notication upon the attachment and removal of USB keyboards, and the corresponding creation and deletion of channels. In order to be notied of the attachment and removal of USB keyboards, clients should register with usbKeyboardLib by calling usbKeyboardDynamicAttachRegister( ). Clients provide a callback function of the following form:
typedef VOID (*USB_KBD_ATTACH_CALLBACK) ( pVOID arg, /* caller-defined argument */ SIO_CHAN *pChan, /* pointer to the affected SIO_CHAN */ UINT16 attachCode /* defined as USB_KBD_xxxx */ );

When usbKeyboardLib detects a new USB keyboard, each registered callback is invoked with pChan pointing to a new SIO_CHAN structure and with attachCode set to the value USB_KBD_ATTACH. When keyboards are removed from the system, each registered callback is invoked with attachCode set to USB_KBD_REMOVE and with pChan pointing to the SIO_CHAN structure of the keyboard that has been removed. The usbKeyboardLib driver maintains a usage count for each SIO_CHAN structure. Callers can increase the usage count by calling usbKeyboardSioChanLock( ), or they can decrease it by calling usbKeyboardSioChanUnlock( ). Normally, if a keyboard is removed from the system when the usage count is zero (0), usbKeyboardLib automatically releases the SIO_CHAN structure formerly associated with the keyboard. However, clients that rely on this structure can use the locking mechanism to force the driver to retain the structure until it is no longer needed.
Example 1-1 SIO_CHAN Locking

Consider an application that periodically polls a keyboard by calling the pollInput( ) callback identied in a particular SIO_CHAN structure. This is an example where SIO_CHAN locking could be required.

43

USB Developers Kit 1.1.2 Programmers Guide

The task responsible for polling runs in the background and operates asynchronously with respect to the code that receives attachment or detachment notication from usbKeyboardLib. If usbKeyboardLib frees the memory associated with the SIO_CHAN structure as soon as the keyboard is unplugged, it is possible that the pollInput( ) function pointer may be corrupted. If that occurs, the applications asynchronous polling task would fail upon calling thenow corruptpollInput( ) function pointer, probably taking down the system. The application can use the SIO_CHAN locking mechanism to force the usbKeyboardLib to delay the release of the SIO_CHAN structure until after the application has canceled the background polling operation. The following code fragments demonstrate the typical use of the dynamic attachment and SIO_CHAN locking functions:
/* First, initialize the usbKeyboardLib. */ if (usbKeyboardDevInit () != OK) { /* We failed to initialize usbKeyboardLib. */ return ERROR; } /* Register for keyboard attachment/detachment notification. */ if (usbKeyboardDynamicAttachRegister (kbdAttachCallback, (pVOID) 1234) != OK) { /* We failed to register for attachment notification. */ return ERROR; } /* The kbdAttachCallback() function will now be called asynchronously * whenever a keyboard is attached to or detached from the system. */ ... ... /* Unregister for keyboard notification and shut down usbKeyboardLib. */ usbKeyboardDynamicAttachUnRegister (kbdAttachCallback, (pVOID) 1234); usbKeyboardDevShutdown ();

The keyboard attachment callback might resemble the following:


/************************************************************************* * * kbdAttachCallback - receives callbacks from USB keyboard SIO driver * * RETURNS: N/A */ LOCAL SIO_CHAN *pOurChan = NULL; LOCAL VOID kbdAttachCallback

44

1 USB Host Stack

( pVOID arg, SIO_CHAN *pChan, UINT16 attachCode )

/* caller-defined argument */ /* pointer to the affected SIO_CHAN */ /* defined as USB_KBD_xxxx */

{ UINT32 ourArg = (UINT32) arg; /* The argument is any arbitrary value that may be of use to this * callback. In this example, we just demonstrate that the value * originally passed to usbKeyboardDynamicAttachRegister() shows up here * as our argument. */ if (ourArg != 1234) { /* The argument never made it. */ ... } switch (attachCode) { case USB_KBD_ATTACH: /* Lock the SIO_CHAN structure so it doesnt disappear on us. */ if (usbKeyboardSioChanLock (pChan) != OK) { /* This really shouldnt be able to fail. */ ... } /* Do other initialization stuff. */ pOurChan = pChan; ... ... break; case USB_KBD_DETACH: /* Tear down any data structures we may have created. */ ... ... pOurChan = NULL; /* Allow usbKeyboardLib to release the SIO_CHAN structure. */ usbKeyboardSioChanUnlock (pChan); break; } }

45

USB Developers Kit 1.1.2 Programmers Guide

1.5.3 Initialization
As with standard SIO drivers, usbKeyboardLib must be initialized by calling usbKeyboardDevInit( ), which in turn initializes its connection to the USBD and other internal resources needed for operation. All interaction with the USB host controllers and devices is handled through the USBD. Unlike some SIO drivers, usbKeyboardLib does not include data structures that require initialization prior to calling usbKeyboardDevInit( ). However, before a call to usbKeyboardDevInit( ), the caller must ensure that the USBD has been properly initialized by calling, at a minimum, usbdInitialize( ). The caller must also conrm that at least one USB HCD is attached to the USBD, using usbdHcdAttach( ), before keyboard operation can begin; however, it is not necessary to call usbdHcdAttach( ) prior to initializing usbKeyboardLib. The usbKeyboardLib driver uses the USBD dynamic attachment services and recognizes USB keyboard attachment and removal on the y. Therefore, it is possible for USB HCDs to be attached to or detached from the USBD at run-time, as may be required (for example, in systems supporting hardware hotswap). Unlike traditional SIO drivers, the usbKeyboardLib driver does not export entry points for send, receive, and error interrupts. All interrupt-driven behavior is managed by the underlying USBD and USB HCD(s), so there is no need for a caller (or BSP) to connect interrupts on behalf of usbKeyboardLib. For the same reason, there is no post-interrupt-connect initialization code, and usbKeyboardLib therefore omits the devInit2 entry point.

1.5.4 ioctl Functions


The usbKeyboardLib driver supports the SIO ioctl interface. However, attempts to set parameters, such as baud rates and start or stop bits, have no meaning in the USB environment and return ENOSYS.

1.5.5 Data Flow


For each USB keyboard connected to the system, usbKeyboardLib sets up a USB pipe to monitor keyboard input. Input, in the form of scan codes, is translated to ASCII codes and placed in an input queue. If SIO callbacks have been installed and usbKeyboardLib has been placed in the SIO interrupt mode of operation, usbKeyboardLib invokes the character received callback for each character in the queue. When usbKeyboardLib has been placed in polled mode, callbacks are not

46

1 USB Host Stack

invoked and the caller must fetch keyboard input using the driver's pollInput( ) routine. The usbKeyboardLib driver does not support output to the keyboard; therefore, calls to the txStartup( )) and pollOutput( ) routines return errors. The only output supported is the control of the keyboard LEDs, which usbKeyboardLib handles internally. The caller should be aware that usbKeyboardLib is not capable of operating in a true polled mode, because the underlying USBD and USB HCD always operate in interrupt mode. The following code fragment demonstrates using usbKeyboardLib to display keystrokes typed by the user:
int i; char inChar; /* Display the next ten keystrokes typed by the user. This code * assumes that pOurChan was initialized as shown earlier and is * currently not NULL. */ for (i = 0; i < 10; i++) { /* Wait for a keystroke */ while ((*pOurChan->pDrvFuncs->pollInput) (pOurChan, &inChar) != OK) ; /* Display the keystroke. */ printf ("The user pressed %c.\n", inChar); }

1.5.6 Typematic Repeat


USB keyboards do not implement typematic repeat, a feature that causes a key to repeat if it is held down, typically for more than one-fourth or one-half second. If you want this feature, implement it with the host software. For this purpose, usbKeyboardLib creates a task, tUsbKbd, that monitors all open channels and injects characters into input queues at an appropriate repeat rate. For example, if a user presses and holds a key on a USB keyboard, a single report is sent from the keyboard to the host indicating the keypress. If no report is received within a pre-set interval indicating that the key has been released, the tUsbKbd thread automatically injects additional copies of the same key into the input queue at a pre-set rate. In the current implementation, the pre-set interval (delay) is one-half (1/2) second, and the repeat rate is 15 characters per second.

47

USB Developers Kit 1.1.2 Programmers Guide

1.6 Mouse Driver


USB mice are described in Human Interface Device (HID) related specications. The Wind River implementation of the USB mouse driver, usbMouseLib, concerns itself only with USB devices claiming to be mice as set forth in the USB Specication; the driver ignores other types of human interface devices, such as keyboards.
NOTE: USB mice operate according to either a boot protocol or a report protocol;

however, the usbMouseLib driver enables mice for operation using the boot protocol only.

1.6.1 SIO Driver Model


The USB mouse class driver, usbMouseLib, follows the VxWorks serial I/O (SIO) driver model, with certain exceptions and extensions. For example, ioctl functions have no effect.

1.6.2 Dynamic Attachment


As with the USB keyboard class driver, the number of channels supported by this driver is not xed. Rather, USB mice can be added or removed from the system at any time. Thus, the number of channels is dynamic, and clients of usbMouseLib must be made aware of the appearance and disappearance of channels. Therefore, this driver includes a set of routines that allows clients to register for notication upon the attachment and removal of USB mice, and the corresponding creation and deletion of channels. In order to be notied of the attachment and removal of USB mice, clients should register with usbMouseLib by calling usbMouseDynamicAttachRegister( ). Clients provide a callback function of the following form:
typedef VOID (*USB_MSE_ATTACH_CALLBACK) ( pVOID arg, /* caller-defined argument */ SIO_CHAN *pChan, /* pointer to the affected SIO_CHAN */ UINT16 attachCode /* defined as USB_MSE_xxxx */ );

When usbMouseLib detects a new USB mouse, each registered callback is invoked with pChan pointing to a new SIO_CHAN structure and with attachCode set to the value USB_MSE_ATTACH. When a mouse is removed from the system, each

48

1 USB Host Stack

registered callback is invoked with attachCode set to USB_MSE_REMOVE and with pChan pointing to the SIO_CHAN structure of the mouse that has been removed. As with usbKeyboardLib, usbMouseLib maintains a usage count for each SIO_CHAN structure. Callers can increment the usage count by calling usbMouseSioChanLock( ) and can decrement it by calling usbMouseSioChanUnlock( ). For more information on using the SIO_CHAN structure, see Example 1-1.

1.6.3 Initialization
As with standard SIO drivers, usbMouseLib must be initialized by calling usbMouseDevInit( ), which in turn initializes its connection to the USBD and other internal resources needed for operation. All interaction with the USB host controllers and devices is handled through the USBD. Unlike some SIO drivers, usbMouseLib does not include data structures that require initialization prior to calling usbMouseDevInit( ). However, before a call to usbMouseDevInit( ), the caller must ensure that the USBD has been properly initialized by calling, at a minimum, usbdInitialize( ). The caller must also conrm that at least one USB HCD is attached to the USBD, using usbdHcdAttach( ), before mouse operation can begin; however, it is not necessary to call usbdHcdAttach( ) prior to initializing usbMouseLib. The usbMouseLib driver uses the USBD dynamic attachment services and recognizes USB mouse attachment and removal on the y. Therefore, it is possible for USB HCDs to be attached to or detached from the USBD at run-time, as may be required (for example, in systems supporting hardware hotswap). Unlike traditional SIO drivers, the usbMouseLib driver does not export entry points for send, receive, and error interrupts. All interrupt-driven behavior is managed by the underlying USBD and USB HCD(s), so there is no need for a caller (or BSP) to connect interrupts on behalf of usbMouseLib. For the same reason, there is no post-interrupt-connect initialization code, and usbMouseLib therefore omits the devInit2 entry point.

1.6.4 ioctl Functions


The usbMouseLib driver supports the SIO ioctl interface. However, attempts to set parameters, such as baud rates and start or stop bits, have no meaning in the USB environment and return ENOSYS.

49

USB Developers Kit 1.1.2 Programmers Guide

1.6.5 Data Flow


For each USB mouse connected to the system, usbMouseLib sets up a USB pipe to monitor input from the mouse, in the form of HID boot reports. These mouse boot reports are of the following form (as dened in usbHid.h):
typedef struct hid_mse_boot_report { UINT8 buttonState; /* buttons */ char xDisplacement; /* signed x-displacement */ char yDisplacement; /* signed y-displacement */ } HID_MSE_BOOT_REPORT, *pHID_MSE_BOOT_REPORT;

In order to receive these reports, a client of usbMouseLib must install a special callback using the drivers callbackInstall( ) routine. The callback type is SIO_CALLBACK_PUT_MOUSE_REPORT, and the callback itself takes the following form:
VOID (*MSE_REPORT_CALLBACK) ( void *callbackArg, /* callback parameter specified by caller */ pHID_MSE_BOOT_REPORT pReport /* pointer to mouse boot report */ );

The client callback should interpret the report according to its needs, saving any data that might be required from the HID_MSE_BOOT_REPORT structure. The usbMouseLib driver does not support polled modes of operation; neither does it support the traditional SIO_CALLBACK_PUT_RCV_CHAR callback. Given the structured nature of the boot reports received from USB mice, character-by-character input of boot reports would be inefcient and could lead to report framing problems in the input stream.

1.7 Printer Driver


USB printers are described in Human Interface Device (HID) related specications. This class driver specication presents two kinds of printer: uni-directional printers (output only) and bi-directional printers (capable of both output and input). The usbPrinterLib driver is capable of handling both kinds of printers. If a printer is uni-directional, the driver only allows characters to be written to the

50

1 USB Host Stack

printer; if the printer is bi-directional, it allows both output and input streams to be written and read.

1.7.1 SIO Driver Model


The USB printer class driver, usbPrinterLib, follows the VxWorks serial I/O (SIO) driver model, with certain exceptions and extensions. This driver provides the external APIs expected of a standard multi-mode serial (SIO) driver and adds extensions that support the hot-plugging USB environment.

1.7.2 Dynamic Attachment


As with usbKeyboardLib, usbMouseLib maintains a usage count for each SIO_CHAN structure. Callers can increment the usage count by calling usbMouseSioChanLock( ) and can decrement it by calling usbMouseSioChanUnlock( ). These mechanisms are identical to those described in 1.5 Keyboard Driver, p.42. As with the USB keyboard class driver, the number of channels supported by this driver is not xed. Rather, USB printers can be added or removed from the system at any time. Thus, the number of channels is dynamic, and clients of usbPrinterLib must be made aware of the appearance and disappearance of channels. Therefore, this driver includes a set of routines that allows clients to register for notication upon the attachment and removal of USB printers, and the corresponding creation and deletion of channels. In order to be notied of the attachment and removal of USB printers, clients should register with usbPrinterLib through the routine usbPrinterDynamicAttachRegister( ). Clients provide a callback function of the following form:
typedef VOID (*USB_PRN_ATTACH_CALLBACK) ( pVOID arg, /* caller-defined argument */ SIO_CHAN *pChan, /* pointer to the affected SIO_CHAN */ UINT16 attachCode /* defined as USB_PRN_xxxx */ );

When usbPrinterLib detects a new USB printer, each registered callback is invoked with pChan pointing to a new SIO_CHAN structure and with attachCode set to the value USB_PRN_ATTACH. When printers are removed from the system, each

51

USB Developers Kit 1.1.2 Programmers Guide

registered callback is invoked with attachCode set to USB_PRN_REMOVE and with pChan pointing to the SIO_CHAN structure of the printer that has been removed. As with usbKeyboardLib, usbPrinterLib maintains a usage count for each SIO_CHAN structure. Callers can increment the usage count by calling usbPrinterSioChanLock( ) and can decrement it by calling usbPrinterSioChanUnlock( ). Normally, if a printer is removed from the system when the usage count is zero (0), usbPrinterLib automatically releases the SIO_CHAN structure formerly associated with the printer. However, clients that rely on this structure can use this locking mechanism to force the driver to retain the structure until it is no longer needed. For more information about using the SIO_CHAN structure, see Example 1-1.

1.7.3 Initialization
As with standard SIO drivers, usbPrinterLib must be initialized by calling usbPrinterDevInit( ), which in turn initializes its connection to the USBD and other internal resources needed for operation. All interaction with the USB host controllers and devices is handled through the USBD. Unlike some SIO drivers, usbPrinterLib does not include data structures that require initialization prior to calling usbPrinterDevInit( ). However, before a call to usbPrinterDevInit( ), the caller must ensure that the USBD has been properly initialized by calling, at a minimum, usbdInitialize( ). The caller must also conrm that at least one USB HCD is attached to the USBD, using usbdHcdAttach( ), before printer operation can begin; however, it is not necessary to call usbdHcdAttach( ) prior to initializing usbPrinterLib. The usbPrinterLib driver uses the USBD dynamic attachment services and recognizes USB printer attachment and removal on the y. Therefore, it is possible for USB HCDs to be attached to or detached from the USBD at run-time, as may be required (for example, in systems supporting hardware hotswap). Unlike traditional SIO drivers, the usbPrinterLib driver does not export entry points for send, receive, and error interrupts. All interrupt-driven behavior is managed by the underlying USBD and USB HCD(s), so there is no need for a caller (or BSP) to connect interrupts on behalf of usbPrinterLib. For the same reason, there is no post-interrupt-connect initialization code, and usbPrinterLib therefore omits the devInit2 entry point.

52

1 USB Host Stack

1.7.4 ioctl Functions


The usbPrinterLib driver supports the SIO ioctl interface. However, attempts to set parameters, such as baud rates and start or stop bits, have no meaning in the USB environment and are treated as no-ops. Additional ioctl functions have been added to allow the caller to retrieve the USB printer's device ID string, the type of printer (uni- or bi-directional), and the current printer status. The device ID string is discussed in more detail in the USB Specication and is based on the IEEE-1284 device ID string used by most 1284-compliant printers. The printer status function can be used to determine whether the printer has been selected, is out of paper, or has an error condition.

1.7.5 Data Flow


For each USB printer connected to the system, usbPrinterLib sets up a USB pipe to output bulk data to the printer. This is the pipe through which printer control and page description data are sent to the printer. Additionally, if the printer is bi-directional, usbPrinterLib sets up a USB pipe to receive bulk input data from the printer. The meaning of data received from a bi-directional printer depends on the particular printer make and model. The USB printer driver supports only SIO_MODE_INT, the SIO interrupt mode of operation. Any attempt to place the driver in polled mode returns an error.

1.8 Speaker Driver


USB speakers are described in the USB Device Class Denition for Audio Devices. The Wind River implementation of the USB speaker driver, usbSpeakerLib, supports only USB speakers as dened by this specication and ignores other types of USB audio devices, such as MPEG and MIDI devices.

53

USB Developers Kit 1.1.2 Programmers Guide

NOTE: Some models of USB speakers are implemented as compound devices, and

these compound devices often integrate a small number of physical audio controls, such as those for volume, bass, treble, and balance. These physical controls are presented as separate USB interfaces within the compound device and are implemented according to the HID specication. The usbSpeakerLib library ignores these non-audio interfaces. If the target application requires these HID controls to be enabled, you must implement additional logic to recognize the HID interface and map the HID functions to appropriate usbSpeakerLib ioctl functions (see 1.8.5 ioctl Functions, p.56).

1.8.1 SEQ_DEV Driver Model


The usbSpeakerLib driver provides a modied VxWorks SEQ_DEV interface to its callers. Among existing VxWorks driver models, the SEQ_DEV interface best supports the streaming data transfer model required by isochronous devices such as USB speakers. As with other VxWorks USB class drivers, the standard driver interface has been expanded to support features unique to the USB and to speakers in general. Functions have been added to allow callers to recognize the dynamic attachment and removal of speaker devices. ioctl functions have been added to retrieve and control additional settings related to speaker operation.

1.8.2 Dynamic Attachment


Like other USB devices, USB speakers can be attached to or detached from the system dynamically. The usbSpeakerLib driver uses the USBD's dynamic attachment services to recognize these events, and callers to usbSpeakerLib can use the usbSpeakerDynamicAttachRegister( ) routine to register with the driver to be notied when USB speakers are attached or removed. The caller must provide usbSpeakerDynamicAttachRegister( ) with a pointer to a callback routine of the following form:
typedef VOID (*USB_SPKR_ATTACH_CALLBACK) ( pVOID arg, /* caller-defined argument */ SEQ_DEV *pSeqDev, /* pointer to the affected SEQ_DEV */ UINT16 attachCode /* defined as USB_SPKR_xxxx */ );

54

1 USB Host Stack

When a USB speaker is attached or removed, usbSpeakerLib invokes each registered notication callback. The callback is passed a pointer to the affected SEQ_DEV structure, pSeqDev, and an attachment code, attachCode, indicating whether the speaker is being attached or removed. The usbSpeakerLib driver maintains a usage count for each SEQ_DEV structure. Callers can increment the usage count by calling usbSpeakerSeqDevLock( ) or can decrement the count by calling usbSpeakerSeqDevUnlock( ). If a USB speaker is removed from the system when its usage count is 0, usbSpeakerLib automatically removes all data structures, including the SEQ_DEV structure itself, that have been allocated on behalf of the device. Sometimes, however, callers rely on these data structures and must properly recognize the removal of the device before it is safe to destroy the underlying data structures. The lock and unlock routines provide a mechanism for callers to protect these data structures, as needed.

1.8.3 Initialization
As with standard SEQ_DEV drivers, this driver must be initialized by calling usbSpeakerDevInit( ). The usbSpeakerDevInit( ) routine, in turn, initializes its connection to the USBD and other internal resources needed for operation. Unlike some SEQ_DEV drivers, there are no usbSpeakerLib data structures that must be initialized before usbSpeakerDevInit( ) is called. Prior to calling usbSpeakerDevInit( ), the caller must ensure that the USBD has been properly initialized by, at a minimum, a call to usbdInitialize( ). It is also the caller's responsibility to ensure that at least one USB HCD is attached to the USBDusing the USBD function usbdHcdAttach( ) before speaker operation can begin. However, it is not necessary to call usbdHcdAttach( ) prior to initializing usbSpeakerLib. The usbSpeakerLib driver uses USBDs dynamic attachment services and can recognize USB speaker attachment and removal on the y. Therefore, it is possible for USB HCDs to be attached to or detached from the USBD at run-time, as may be required (for example, in systems supporting hardware hotswap).

55

USB Developers Kit 1.1.2 Programmers Guide

1.8.4 Recognizing and Handling USB Speakers


Speakers, loosely dened, are USB audio devices that provide an output terminal. For each USB audio device, usbSpeakerLib examines the descriptors that dene both the units and terminals contained within the device and how they are connected. If an output terminal is found, usbSpeakerLib traces the device's internal connections to determine which input terminal provides the audio stream for that output terminal, and which feature unit, if any, is responsible for controlling audio stream attributes such as volume. After building an internal map of the device, usbSpeakerLib congures the device and waits for a caller to provide a stream of audio data. If no output terminal is found, usbSpeakerLib ignores the audio device. After determining that the audio device contains an output terminal, usbSpeakerLib builds a list of the audio formats that the device supports. The usbSpeakerLib driver supports only AudioStreaming interfaces (no MIDIStreaming is supported). For each USB speaker attached to the system and properly recognized by usbSpeakerLib, usbSpeakerLib creates a SEQ_DEV structure to control the speaker. Each speaker is uniquely identied by the pointer to its corresponding SEQ_DEV structure.

1.8.5 ioctl Functions


The usbSpeakerLib driver implements a number of ioctl functions unique to the handling of audio data and devices. The driver uses ioctl functions to set the mute, volume, bass, mid-range, and treble controls. The driver provides ioctl functions for use by callers to interrogate a speaker's audio format capabilities or to specify the audio format for a subsequent data stream. The driver also provides ioctl functions to mark the beginning and end of audio data streams (see 1.8.6 Data Flow, p.57).

56

1 USB Host Stack

1.8.6 Data Flow


Before sending audio data to a speaker device, the caller must specify the data format (for example, PCM or MPEG) using an ioctl function (see 1.8.5 ioctl Functions, p.56). The USB speaker itself must support the specied data format or a similar one. USB speakers rely on an uninterrupted, time-critical stream of audio data. The data is sent to the speaker through an isochronous pipe. In order for the data ow to continue uninterrupted, usbSpeakerLib uses an internal double-buffering scheme. When the caller presents data to usbSpeakerLib's sd_seqWrt( ) routine, usbSpeakerLib copies the data into an internal buffer and immediately releases the caller's buffer. The caller should immediately try to pass the next buffer to usbSpeakerLib. When usbSpeakerLib's internal buffer is lled, it blocks the caller until it can accept new data. In this manner, the caller and usbSpeakerLib work together to ensure that an adequate supply of audio data is always available to continue isochronous transmission uninterrupted. Audio play begins after usbSpeakerLib has accepted a half-second of audio data or when the caller closes the audio stream, whichever happens rst. The caller must use ioctl functions to open and close each audio stream. The usbSpeakerLib driver relies on these open and close ioctl functions to manage its internal buffers correctly.

1.9 Mass Storage Class Driver


USB Mass Storage Class devices are described in the Mass Storage Class specication and can behave according to several different implementations. Wind River supplies drivers that adhere to the Bulk-Only and Control/Bulk/Interrupt (CBI) implementation methods. Each of these two drivers uses a command set from an existing protocol. The Wind River CBI driver wraps USB protocol around the commands documented in SCSI Primary Commands: 2 (SPC-2), Revision 3 or later.2 The Wind River Bulk-Only driver wraps USB protocol around the commands documented in Advanced Technology Attachment Packet Interface (ATAPI) for Floppies, SFF-8070i.3

2. Available from Global Engineering, 800-854-7179. 3. Also available from Global Engineering.

57

USB Developers Kit 1.1.2 Programmers Guide

A devices Subclass code, presented in its interface descriptor, indicates which of these command sets the device understands. Table 1-1, adapted from the Universal Serial Bus Mass Storage Class Specication Overview, shows the command set that corresponds to each Subclass code.
Table 1-1 Device Subclass Codes and Corresponding Command Sets Subclass Code Command Block Specication Comments

01h

Reduced Block Commands (RBC) T10 Project 1240-D SFF-8020i or MMC-2 (ATAPI) QIC-157 UFI SFF-8070i

Typically, a flash device uses RBCs. However, any Mass Storage device can use RBCs. Typically, a CD/DVD device uses SFF-8020i or MMC-2 command blocks for its Mass Storage interface. Typically, a tape device uses QIC-157 command blocks. Typically, a floppy disk drive (FDD) device uses UFI command blocks. Typically, a floppy disk drive (FDD) device uses SFF-8070i command blocks. However, an FDD device can belong to another Subclass (for example, RBC); likewise, other types of storage device can belong to the SFF-8070i Subclass.

02h

03h 04h 05h

06h 07h-FFh

SCSI transparent command set Reserved for future use

Wind Rivers CBI driver responds to devices with Subclass code 05h. Wind Rivers Bulk-Only driver responds to devices with Subclass code 06h. All references to the Mass Storage Class driver library take the form usbMSCxxx( ). References to Wind Rivers CBI driver take the form usbCbiUxxx( ); references to Wind Rivers Bulk-Only driver take the form usbBulkxxx( ).

58

1 USB Host Stack

1.9.1 Block Device Driver Model


A Mass Storage Class driver is a type of block device driver that provides generic direct access to a block device through VxWorks. Mass Storage Class drivers interact with the le system. The le system, in turn, interacts with the I/O system. A device driver for a block device must provide a means of creating a logical block device structure called BLK_DEV. This structure describes the USB Mass Storage device in a generic fashion, specifying only those common characteristics that must be known to the le system being used with the device (for example, read, write, and ioctl routines). After the device has been initialized with a particular le system, all I/O operations for the device are routed through that le system. The le system, in turn, calls the routines in the specied BLK_DEV structure. The BLK_DEV structure is initialized to point to the read/write routines described in this section. When the class driver creates the block device using usbMSCBlkDevCreate( ), the USB device does not have a name or a le system associated with it. In most cases, a le system is assigned during device initialization in the user code (through a routine such as dosFsDevInit( ) or rt11FsDevInit( )). File system initialization routines assign a specied name to the USB device and enter the device into the I/O system device table. The following code fragment shows a typical USB Mass Storage driver initialization sequence:
pBlkDev = usbMSCDevInit( ); dosFsMkfs("dev1:", pBlkDev)

The hierarchy diagram in Figure 1-4 illustrates where the USB Mass Storage Class driver ts into a VxWorks system.

59

USB Developers Kit 1.1.2 Programmers Guide

Figure 1-4

USB Block Driver Hierarchy in a VxWorks System

Application

I/O System

Non-Block Device Driver

File System (dosFs, rawFs)

USB Mass Storage Class Driver


(Block driver)

USBD Host Driver

VxWorks USB Stack

USB Host Controller

USB Devices

60

1 USB Host Stack

The USB Mass Storage Class device driver provides the following API functions to the le system: usbMSCDevInit( ) This routine is a general initialization routine. It performs all operations that are to be done one time only. It initializes required data structures and registers the mass storage class driver with the USBD. It also registers for notication when Mass Storage devices are dynamically attached. Traditionally, this function is called from the VxWorks boot code. usbMSCDevCreate( ) This routine creates a logical block device structure for a particular USB Mass Storage device. At least one mass storage device must exist on the USB when this routine is invoked. usbMSCBlkWrt( ) This routine writes to a specied physical block or blocks from a specied USB device. usbMSCBlkRd( ) This routine reads a specied physical block or blocks from a specied USB device. usbMSCDevIoctl( ) This routine performs any device-specic I/O control functions. For example, it sends commands that are not explicitly used by a typical le system, and it sets device conguration. usbMSCStatusChk( ) This routine checks for the status of the USB device. This is primarily for removable media such as USB oppy drives or Zip drives. A change in status is reported to the le system mounted, if any. usbMSCDevReset( ) This routine resets a specic Mass Storage device. It rst tries to perform a block reset command. If the block reset is not successful, the routine resorts to a port reset.

61

USB Developers Kit 1.1.2 Programmers Guide

1.9.2 Dynamic Attachment


A USB device driver must support the most important feature of a USB device: dynamic insertion and removal of the device. A USB Mass Storage Class device can be plugged into and out of the system at any time. This hotswap feature is supported by a callback mechanism. The USB Mass Storage Class driver provides the registration function usbMSCDynamicAttachRegister( ), which registers the client with the driver. When a USB Mass Storage Class device is attached to or removed from the system, all clients are notied through the USBDs call to a user-provided callback function. The callback function receives the USB_NODE_ID of the attached device and a ag that is set to either USB_MSC_ATTACH or USB_MSC_DETACH, indicating the attachment or removal of the device. The driver also provides the usbMSCDynamicAttachUnregister( ) function for deregistering a block device driver. The Mass Storage Class driver maintains a usage count of BLK_DEV structures. When a client uses the BLK_DEV structure, it informs the driver by calling usbMSCDevLock( ). For each usbMSCDevLock( ) call, the driver increments the usage count. When a client is nished with the BLK_DEV structure, it must notify the driver by calling usbMSCDevUnlock( ). The driver then decrements the usage count. Normally, if a Mass Storage Class device is removed from the system when the usage count is zero (0), the driver releases the corresponding BLK_DEV structure. However, clients that rely on this structure can use this locking mechanism to force the driver to retain the structure until it is no longer needed.

1.9.3 Initialization
The Mass Storage Class driver is initialized through the usbMSCDevInit( ) routine. This API call, in turn, initializes internal resources needed for its operation and registers a callback routine with the USBD. The callback routine is then invoked whenever a USB Mass Storage Class device is attached to or removed from the system. All interactions between the USB host controller and the Mass Storage Class device are handled through the USBD. Therefore, before calling usbMSCDevInit( ), the user must ensure that the USBD has been properly initialized with usbdInitialize( ). Also, before any operation with a block device driver, the caller must ensure that at least one host controller is attached to the USBD.

62

1 USB Host Stack

1.9.4 Data Flow


The Mass Storage Class drivers data read and write mechanism behaves like that of a standard block device driver. It uses the data read and write function pointers that are installed through the usbMSCBlkDevCreate( ) routine. Because most USB Mass Storage Class devices can implement 64-byte endpoints only, the driver must manage the transfer of the larger chunks (that is, 512-byte blocks) of data that are understood by the le system. To facilitate the multiple read/write transactions that are necessary to complete the block access, the USBD uses its IRP mechanism. This allows the user to specify a function, usbMSCIrpCallback( ), that is called when the block transaction is complete.

1.10 Communication Class Drivers


USB Communication Class devices can behave according to several different implementations. Wind River supplies drivers for Ethernet Networking Control Model devices, and for Abstract Control Model devices.

1.10.1 Ethernet Networking Control Model Driver


This section describes Wind Rivers USB Networking Control Model driver. The driver supports USB network adapter devices with Subclass code 06h (see Table 1-1), with certain exceptions and extensions. The Ethernet device presents two interfaces for transferring information to the device: a Communication Class interface and a Data Class interface. The Communication Class interface is a management interface and is required of all communication devices. The Data Class interface can be used to transport data across the USB wire. Ethernet data frames are encapsulated into USB packets and are then transferred using this Data Class interface. These Ethernet packets include an Ethernet destination address (DA), which is appended to the data eld. Ethernet packets in either direction over the USB do not include a CRC (cyclic redundancy check); error-checking is instead performed on the surrounding USB packet.

63

USB Developers Kit 1.1.2 Programmers Guide

The hierarchy diagram in Figure 1-5 illustrates where the USB Communication Class driver ts into a VxWorks system.
Figure 1-5 USB Communication Class Driver Hierarchy in a VxWorks System

Application

I/O System

Socket Library VxWorks Network Stack MUX Library

USB Communication Class Driver

VxWorks USBD Host Driver USB Stack

USB Host Controller

USB Devices

64

1 USB Host Stack

Enhanced Network Driver Model

Wind Rivers USB Networking Control Model driver conforms to the MUX Enhanced Network Driver (END) model, with certain variations. These differences are designed to accommodate the following features:
I I I

Hotswap of USB devices. Attaching multiple identical devices to one host. USB network devices with vendor-specic initialization requirements. For example, one of the supported devices, the KSLI adapter, requires new rmware to be downloaded before normal operation can begin. A dynamic insertion and removal callback mechanism.

In order to meet these requirements, Wind Rivers drivers include additional APIs, beyond those dened in the standard END specication. For detailed information on the END model, see the Tornado BSP Developers Kit for VxWorks Users Guide: Implementing a MUX-Based Network Interface Driver.

Dynamic Attachment

Because USB network adapters can be hotswapped to and from the system at any time, the number of devices is dynamic. Clients of usbXXXEndLib can be made aware of the attachment and removal of devices. The driver includes a set of API calls that allows clients to register for notication upon attachment or removal of a USB network adapter device. The attachment and removal of USB network adapters correspond, respectively, to the creation and deletion of USB_XXX_DEV structures. In order to be notied of the attachment or removal of USB network adapters, clients should register with usbXXXEndLib by calling usbXXXDynamicAttachRegister( ), providing a callback function. When usbXXXEndLib detects a new USB network adapter, each registered client callback function is invoked with callbackType set to USB_XXX_ATTACH. Similarly, when a USB network adapter is removed from the system, each registered client callback function is invoked with callbackType set to USB_XXX_DETACH. The usbXXXEndLib driver maintains a usage count for each USB_XXX_DEV structure. When a client uses the USB_XXX_DEV structure, it informs the driver by calling usbXXXDevLock( ). For each usbXXXDevLock( ) call, the driver increments the usage count. When a client is nished with the USB_XXX_DEV structure, it must notify the driver by calling usbXXXDevUnlock( ). The driver then decrements the usage count. Normally, if an adapter is removed from the

65

USB Developers Kit 1.1.2 Programmers Guide

system when the usage count is zero (0), the driver releases the corresponding USB_XXX_DEV structure. However, clients that rely on this structure can use this locking mechanism to force the driver to retain the structure until it is no longer needed.

Initialization

The usbXXXEndLib driver must be initialized through the usbXXXEndInit( ) routine, which in turn initializes its connection to the USBD and other internal resources needed for its operation. This API call also registers a callback routine with the USBD. The callback routine is then invoked whenever a USB networking device is attached to or removed from the system. All interactions between the USB host controller and the networking device are handled through the USBD. Therefore, before calling usbXXXEndInit( ), the user must ensure that the USBD has been properly initialized with usbdInitialize( ). Also, before any operation with a networking device driver, the caller must ensure that at least one host controller has been attached to the USBD through hcdAttach( ).

Interrupt Behavior

The usbXXXEndLib driver relies on the underlying USBD and HCD layers to communicate with the USB Ethernet Networking Control Model devices (network adapters). The USBD and HCD layers, in turn, use the host controller interrupt for this communication. In this way, all interrupt-driven behavior is managed by the underlying USBD and HCD layers. Therefore, there is no need for the caller (or BSP) to connect interrupts on behalf of usbXXXEndLib. For the same reason, there is no post-interrupt-connect initialization code and usbXXXEndLib omits the devInit2 entry point. The usbXXXEndLib driver inherently depends on the host controller interrupt for its communication with USB network adapters. Therefore, the driver supports only the interrupt mode of operation. Any attempt to place the driver in the polled mode returns an error.

ioctl Functions

The usbXXXEndLib driver supports the END ioctl interface. However, any attempt to place the driver in the polled mode returns an error.

66

1 USB Host Stack

Data Flow

The usbXXXEndLib drivers data transmission mechanism deviates slightly from the END standard in that all data is routed through the USBD. The XXXEndSend( ) routine lls in the pUSB_IRP structure and exports the structure to the USBD to send or receive the data. IRPs are a mechanism for scheduling data transfers across the USB. For example, for the host to receive data from a network device, an IRP using the bulk input pipe is formatted and submitted to the USBD by the driver. When data becomes available, XXXEndRecv( ) is invoked by the IRPs callback to process the incoming packet. Whenever data is transferred through the USBD using the pUSB_IRP structure, callback functions are passed to the USBD. These callback functions acknowledge the transmission of each packet of data. The execution of each callback function indicates that the corresponding data packet has been successfully transmitted.

1.10.2 Abstract Control Model Driver


All USB Abstract Control Model (ACM) devices (serial emulation devices) are modems. These devices are described in the USB Communication Class device specication document. These devices use the common AT commands (attention commands; also known as Hayes-compatible commands) to communicate with the devices that conform to the specication. In this section, Wind River uses the term USB modem driver interchangeably with the term USB ACM class driver.

SIO Driver Model

The USB ACM class driver follows the VxWorks serial I/O (SIO) driver model, with certain exceptions and extensions. The reason for these differences is that the modems, traditionally, interface with the host by means of an RS232 serial line and are controlled as serial devices. The USB ACM class driver, therefore, provides the external APIs expected of a standard multimode serial I/O driver and adds extensions that support USB hotswap. The driver lls in an SIO_CHAN structure with the additional API routines and extensions, and exports the structure to the upper layers of the USB stack for control of the modem devices.

67

USB Developers Kit 1.1.2 Programmers Guide

Dynamic Attachment

Because USB modems can be added to or deleted from the system at any time, the number of devices is dynamic. Clients of usbAcmLib can be made aware of the attachment and removal of devices. The driver includes a set of API calls that allows clients to register for notication upon the attachment or removal of USB modems. The attachment and removal of USB modems correspond, respectively, to the creation and deletion of SIO_CHAN structures. In order to be notied of the attachment or removal of USB modems, clients should register with usbAcmLib by calling usbAcmCallbackRegister( ), with a callback code of USB_ACM_CALLBACK_ATTACH. While registering, clients must provide a callback function of the following type:
typedef STATUS (*USB_ACM_CALLBACK) ( pVOID arg, /* caller-defined argument */ SIO_CHAN * pChan, /* pointer to the affected SIO_CHAN */ UINT16 callbackType, /* defined as USB_ACM_CALLBACK_XXXX */ UINT8 * pBuf, /* pointer to data buffer, if any data*/ /* transfer is involved. Otherwise NULL */ UINT16 count /* No. of bytes of data transferred if data */ /* transfer is involved. 0 otherwise. */ )

When usbAcmLib detects a new USB modem, each registered callback is invoked with pChan pointing to a new SIO_CHAN structure and with callbackType set to USB_ACM_CALLBACK_ATTACH. Similarly, when a USB modem is removed from the system, each registered callback is invoked with pChan pointing to the SIO_CHAN structure of the removed device, and callbackType set to USB_ACM_CALLBACK_DETACH. The usbAcmLib driver maintains a usage count for each SIO_CHAN structure. When a client uses the SIO_CHAN structure, it informs the driver by calling usbAcmLockSioChan( ). For each usbAcmLockSioChan( ) call, the driver increments the usage count. When a client is nished with the SIO_CHAN structure, it must notify the driver by calling usbAcmUnlockSioChan( ). The driver then decrements the usage count. Normally, if a modem is removed from the system when the usage count is zero (0), the driver releases the corresponding SIO_CHAN structure. However, clients that rely on this structure can use this locking mechanism to force the driver to retain the structure until it is no longer needed.

68

1 USB Host Stack

Initialization

The usbAcmLib driver is initialized through the usbAcmLibInit( ) routine. This API call, in turn, initializes internal resources needed for its operation and establishes its connection to the USBD. All interactions with the USB host controller and devices are handled through the USBD. Therefore, before calling usbAcmLibInit( ), the user must ensure that the USBD has been properly initialized with usbdInitialize( ). Also, before modem operation can begin, the caller must ensure that the host controller has been attached to the USBD.

Interrupt Behavior

The usbAcmLib driver relies on the underlying USBD and HCD layers to communicate with the USB ACM devices (modems). The USBD and HCD layers, in turn, use the host controller interrupt for this communication. In this way, all interrupt-driven behavior is managed by the underlying USBD and HCD layers. Therefore, there is no need for the caller (or BSP) to connect interrupts on behalf of usbAcmLib. For the same reason, there is no post-interrupt-connect initialization code and usbAcmLib omits the devInit2 entry point. The usbAcmLib driver inherently depends on the host controller interrupt for its communication with modems. Therefore, the driver supports only SIO_MODE_INT, the SIO interrupt mode of operation. Any attempt to place the driver in the polled mode returns an error.

ioctl Functions

The usbAcmLib driver supports the SIO ioctl interface. However, any attempt to place the driver in the polled mode returns an error. The driver supports additional ioctl functions in order to provide the ACM behavior detailed by the USB Communication Class devices specication.

Data Flow

The usbAcmLib exports the callback functions for the sending and receiving of data as required by the VxWorks SIO model. These callback functions provide data for transmission and accept any data received, character by character. This means that these callback functions are executed once for each character transmitted.

69

USB Developers Kit 1.1.2 Programmers Guide

The practice of sending or receiving a single character at a time is typically intended for a traditional serial I/O device that has no buffer or very little buffer. For USB ACM devices, data is transmitted over bulk I/O pipes, with a packet size in multiples of 8. For example, a typical value is 64 bytes per packet. In this case, it makes sense for the API to allow transmission of data in packets, leaving the packet size to be determined by the maximum packet size of the bulk I/O pipe. Therefore, the driver exports another set of routines for sending and receiving data in bulk quantities. The following ioctl command retrieves the maximum packet size of the I/O pipe (that is, the buffer size):
UINT size; usbAcmIoctl (ptr, USB_ACM_SIO_GET_MAX_BUF_SIZE, &size) ;

Modem Control: Hayes Commands

The USB ACM specication indicates that modems must support the common AT command set for controlling modem behavior. The usbAcmLib driver exports two functions to support this feature:
I

a transmit function a callback registration function. The user registers this callback function in order to be notied of the modems response to the AT command.

1.11 Running the USB Kit


The Tornado project facility is a key element of the Tornado Integrated Development Environment (IDE). It provides graphical and automated mechanisms for creating applications that can be downloaded to VxWorks, for conguring VxWorks with selected features, and for creating applications that can be linked with a VxWorks image and started when the target system boots. The project facility provides mechanisms for the following actions:
I

Organizing the les that make up a project. Grouping related projects into a workspace. Customizing and scaling VxWorks. Adding application initialization routines to VxWorks.

70

1 USB Host Stack

Dening varied sets of build options. Building applications and VxWorks images. Downloading application objects to the target.

For a tutorial introduction to the project facility, see the Tornado Getting Started Guide.
Creating a Downloadable VxWorks Image Including USB

From the Tornado project facility, start a downloadable VxWorks project based on your BSP. (For a list of BSPs supported with this release of the USB Kit, see the Release Notes.) The USB Kit software provides components that support USB functionality. USB components are located in the component tree under the hardware folder. The following components can be found in hardware>buses>USB Hosts:
I I I I I

OHCI OHCI Pci Init UHCI USB Host Stack usbTool

The following components can be found in hardware>peripherals>USB Devices:


I I I I I I I

End - Pegasus Keyboard Mass Storage - Bulk Mass Storage - CBI Mouse Printer Speaker

Under each of these folders there is also a sub-folder that contains the initialization components for the USB modules. For general instructions on using the project facility and creating projects, see the Tornado Users Guide: Projects. For a basic USB setup, you must include the USB host stack component and at least one of the two host controller components. If you intend to test a device, you must include one or more of the device components.

71

USB Developers Kit 1.1.2 Programmers Guide

Step 1:

Including the Host Stack

Selecting the USB host stack component includes support for the USBD.
Step 2: Including a Host Controller

Selecting either the UHCI or OHCI components includes modules for those types of host controllers, respectively. Either host controller component requires that the USB host stack component also be selected. Both host controllers can be present on the image at once.
NOTE: When you include the OHCI component, the OHCI Init component is required. If your BSP does not have pciAutoCong( ), use OHCI Pci Init as an

example of how the OHCI controller should be congured on the PCI bus. (For information about conguring the OHCI host controller on the PCI bus, see 1.15 BSP Porting Issues, p.84.) The OHCI Init component searches the PCI bus for an OHCI controller. The component searches through the list of supported host controllers. If it nds a match, it congures it and continues looking until it nds no more host controllers. If you are using a different OHCI controller, you must modify the conglette for the OHCI Init component. Add your Vendor ID (VID) and Product ID (PID) to the list of supported host controllers in the usrUsbPciOhciInit.c le. This conglette is located in target/cong/comps/src.
Step 3: Including Devices

Selecting any of the following USB device components includes the corresponding driver module. These components require that the USB stack be present on the image:
I I I I I I I

Keyboard Mouse Printer Speaker Mass Storage - Bulk Mass Storage - CBI END - Pegasus

72

1 USB Host Stack

1.12 Initialization
1.12.1 Host Stack and Host Controller Initialization
The USB Kit includes initialization conglettes for the USBD (host stack) and for both OHCI- and UHCI-type host controllers. In the initialization process, the USB initialization component makes a call to usbdInitialize( ). The host controller components then attach any host controllers existing in the system to the initialized USB stack.

1.12.2 Device Initialization


The USB Kit includes initialization components for all of the USB modules. !
CAUTION: When you use the initialization components, usbTool may not be

used. The components were derived from usbTool itself, and cause compile-time errors when used concurrently with usbTool.

Keyboard, Mouse, Printer, and Speaker Initialization

The keyboard, mouse, printer, and speaker drivers contain initialization routines that install standard open, close, read, write, and ioctl functions into the I/O system driver table. This allows an application to call these drivers using standard VxWorks system calls. For example, an application might want to monitor a keyboards input. First, the application opens the keyboard with the system call to open( ):
fileDescr = open ("/usbkb/0", 2, 0);

The application can now call the systems read( ) routine in a loop:
read (fileDescr, &inChar, 1);

These operations can be used for the mouse, printer, and speaker drivers as well.

73

USB Developers Kit 1.1.2 Programmers Guide

Mass Storage Class Device Initialization

The Bulk-Only and CBI Mass Storage Class driver conglettes install standard functions into a le system. As with the mouse, keyboard, speaker, and printer drivers, these functions allow an application to make standard VxWorks system calls such as copy, rm, and format (depending on which le system is attached) to access the Mass Storage Class device. After a USB block device has been created by means of usbMSCBlkDevCreate( ) (see 1.9 Mass Storage Class Driver, p.57, for the possible values of MSC in this API name), a le system can be attached to the device as follows:
/* attach DOS file system to the USB drive */ pBulkDosVol = dosFsDevCreate ("/usbDr0", pBulkBlkDev, MAX_NO_FILES, 0);

Now calls such as copy( ) can refer to the device as usbDr0. In the following code fragment, the le readme.txt is copied from a host to the USB drive usbDr0.
copy ("host:/readme.txt", "/usbDr0/readme.txt");

SCSI6 Commands

In internal testing, Wind River has found that one supported drive, the M-Systems FlashOnKey device, does not support SCSI6 commands. This may also be the case for some non-supported drives. Therefore, the Bulk-Only driver supports both SCSI-6 and SCSI-10 read/write commands. The user must congure the driver to use the appropriate command for communicating with the device. The fourth parameter of usbMSCBlkDevCreate( ) sets the SCSI transfer mode. It can take either of the following values:
USB_SCSI_FLAG_READ_WRITE10 USB_SCSI_FLAG_READ_WRITE6

Use SCSI read/write 10. Use SCSI read/write 6.

Communication Class Device Initialization

The USB Kit includes a conglette, called usrUsbPegasusEndInit.c, to initialize the Pegasus Communication Class driver. Upon device insertion, these routines connect a Pegasus device to the network stack, attaching an IP address to the device through a specied gateway address. The IP address, gateway, host name, and a net mask are all user-denable parameters of the component and must be set before communication with the Pegasus device can occur.

74

1 USB Host Stack

When a Communication Class device has been successfully connected, it can be used like any other network device. Like all USB devices, a Communication Class device can be inserted or removed at any time. If the device is unplugged, any resources devoted to it are freed, and the system node that was created for it is removed.
NOTE: In most cases, when support for a USB Communication Class device is

added, two network devices exist on the system as a result. To make this possible, you must increase the value of IP_MAX_UNITS to 2. This value is a parameter to the network buffer initialization component. This component is found under network components>basic network initialization components>network buffer initialization.

1.12.3 usbAudio Initialization


The USB Kit includes a sample application called usbAudio, which demonstrates how to use the USB stack and the speaker class driver. This application was designed to run on a pcPentium machine that contains both a host controller (OHCI or UHCI) and an ATA hard drive containing .wav les. The usbAudio program operates with any of the listed supported speakers.

1.12.4 usbTool Code Exerciser


The USB Kit includes a utility called usbTool which you can use to exercise the modules that comprise the USB stack. For example, if you were implementing a different device driver, you can use usbTool to exercise and debug your code. The usbTool utility provides a basic code skeleton that you can customize to suit your test needs.
NOTE: The usbTool module relies internally on static data; you should not run

multiple instances of usbTool simultaneously.

75

USB Developers Kit 1.1.2 Programmers Guide

Running usbTool from the Shell

1.

To use the tool from the shell, type the entry point of the tool at the shell prompt, as follows:
->usbTool

This produces a new prompt where commands can be entered:


usb>

2.

To get a list of all usbTool commands and their denitions, type the following:
usb>?

CAUTION: When running usbTool on a host shell, you may encounter a

redirection problem that prevents entered commands from being echoed back to the shell. You can avoid this issue by running usbTool on a target shell.

The usbTool Execution Sequence

The usbTool utility allows the user to see a typical execution sequence needed to get the USB up and running. When an image that includes USB components boots, it automatically executes a sequence of events similar to using the usbTool utility: (1) To initialize the USB host stack, enter the usbInit command at the usbTool prompt. (2) To initialize an OHCI or UHCI host controller, enter the attach uhci or attach ohci commands at the usbTool prompt. (3) If you plan to use a device driver, after initializing the host stack and host controller, enter the initialization command for that driver at the usbTool prompt. To test any included devices, enter the appropriate test command, for example:
usb>mouseTest

NOTE: Selecting any of the device driver components (keyboard, mouse, printer, speaker) includes the device test commands into usbTool. If the components are

not included, the commands are not available.

76

1 USB Host Stack

The following commands are available when their associated device components are included in your VxWorks image: mouse mouseTest keyboard kbdInit, kbdDown and kbdPoll printer prnInit, prnDown, print4k and print lename speaker spkrInit, spkrDown, spkrFmt, volume, and play lename For descriptions of these commands, invoke the help list from usbTool.
NOTE: Command names do not have to be fully entered to be executed. For

example, usbInit can be entered as usbi.

1.13 Booting VxWorks Through a Communication Class Driver


You can use the Pegasus USB Ethernet driver to build a bootable VxWorks image. At the time of this release, only the Pegasus driver supported booting. In order to make a USB boot ROM, you must modify several BSP les. However, it is not recommended that you alter the original BSP system les. Instead, make a copy of the les so that you can revert to the original BSP conguration if needed. The following conguration les must be altered in order to build a bootable VxWorks image:
I I I I

cong.h congNet.h sysLib.c bootCong.c

The sections below provide details on how to alter these les.

77

USB Developers Kit 1.1.2 Programmers Guide

In cong.h

In this le, you must dene the USB parts that are required. Because this method of booting VxWorks uses a USB networking device for booting, you must undene the default boot device. The following line undenes the default boot device for a pcPentium system:
#undef INCLUDE_FEI

The native network support component (in this case, FEI) conditionally includes the network stack type (in this case, END) as well as the network device connection type (in this case, PCI). Therefore, in addition to including the USB components, you must also re-include the components for network stack type and network device connection type. The following code fragment demonstrates how to include in cong.h the components necessary for booting:
#define INCLUDE_USB_PEGASUS_END #if defined(INCLUDE_USB_PEGASUS_END) #ifndef INCLUDE_USB #define INCLUDE_USB #endif #ifndef INCLUDE_OHCI # define INCLUDE_OHCI_PCI_INIT # define INCLUDE_OHCI #endif #ifndef INCLUDE_PCI # define INCLUDE_PCI #endif #ifndef INCLUDE_END # define INCLUDE_END #endif #endif #endif

In congNet.h

This le contains the denitions of the network load routine and other parameters that are to be included in the endDrvTbl[ ]. This table tells muxDevLoad( ) which network method should be called when the network stack is bringing up the network device.

78

1 USB Host Stack

1.

First, dene the load routine for the driver. The load routine for the Pegasus driver is contained in usrUsbPegasusInit.c under cong/comps/src. For example:
/* Define the Pegasus load routine */ #ifdef INCLUDE_USB_PEGASUS_END #define END_PEGASUS_LOAD_FUNC sysUsbPegasusEndLoad #define END_PEGASUS_BUFF_LOAN 1 #define END_PEGASUS_LOAD_STRING "" IMPORT END_OBJ * END_PEGASUS_LOAD_FUNC (char *, void*);

2.

Then add these denitions to the endDevTbl[ ] array. For example:


END_TBL_ENTRY endDevTbl [] = { /* Include the Pegasus load routine in the table */ #ifdef INCLUDE_USB_PEGASUS_END {0, END_PEGASUS_LOAD_FUNC, END_PEGASUS_LOAD_STRING, END_PEGASUS_BUFF_LOAN, NULL}, #endif /* INCLUDE_USB_PEGASUS_END */ ... ... ... { 0, END_TBL_END, NULL, 0, NULL, FALSE}, };

In sysLib.c

Add a section to this le to include the conglette les for the initialization of the USB stack and the network driver. For example, the following code includes the USB stack, the OHCI driver, and the Pegasus network driver initialization code:
/* Include USB stack initialization */ #ifdef INCLUDE_USB #include usrUsbInit.c #endif /* Include PCI enumeration of OHCI card */ #ifdef INCLUDE_OHCI_PCI_INIT #include usrUsbPciOhciInit.c #endif /* Include the OHCI driver initialization */ #ifdef INCLUDE_OHCI #include usrUsbHcdOhciInit.c #endif /* Include the Pegasus network driver initialization */ #ifdef INCLUDE_PEGASUS #include usrUsbPegasusInit.c #endif

79

USB Developers Kit 1.1.2 Programmers Guide

For more information on the les named in this example, see 1.12 Initialization, p.73.
In target/cong/all/bootCong.c

This le contains the calls to the USB routines. The boot ROM you make for booting VxWorks must do the following: (1) Initialize the USB host stack through a call to usbdInitialize( ). (2) Attach a host controller to the USBD. In the example below, an OHCI controller is attached. (3) Initialize the USB network driver. The example below uses the Pegasus driver, as it is the only device that supports USB booting. Create a routine like the one below. It should be called from usrRoot( ) after sysClkEnable( ).
/**************************************************************************** * * usbOhciInit - initialize the USB stack w/ OHCI controller * * RETURNS: Nothing. */ LOCAL void usbOhciInit ( ) { usbInit (); sysUsbPciOhciInit (); usrUsbHcdOhciAttach (); taskDelay (sysClkRateGet()*3); usbPegasusEndInit (); }

A call to your function should appear as follows:


sysClkEnable (); /* Begin USB initialization */ sysUsbPciOhciInit(); usbOhciInit(); taskDelay (sysClkRateGet()*5); /* End USB initialization */ /* initialize I/O and file system */ iosInit (NUM_DRIVERS, NUM_FILES, "/null"); /* start it */

/* /* /* /* /*

map OHCI card into PCI space */ initialize stack, attach HC, initialize */ network driver */ gratuitous delay to allow bus traffic */ to settle */

80

1 USB Host Stack

With these modications, you can build a boot ROM in the BSP with the following command:
make bootrom_uncmp

Now USB can be used as a boot parameter:


VxWorks System Boot Copyright 1984-1998 Wind River Systems, Inc. CPU: PCPENTIUM Version: 5.4.2 BSP version: 1.2/0 Creation date: Jun 14 2001, 10:03:12 Press any key to stop auto-boot... @2 boot device usb unit number 0 processor number 0 host name host file name path/vxWorks inet on ethernet (e)90.0.0.50 host inet (h) 90.0.0.3 user (u) target flags (f) 0x0

1.14 Benchmarking Information


This section provides information to help you benchmark your test results. The metrics shown in this section are derived using spyLib, a VxWorks library that displays information on task execution and CPU utilization. The sample test described in this section was performed on a project created with the following components included:
I I I I I I I

USB stack and its associated initialization components OHCI driver and its associated initialization components Speaker driver and its associated initialization components Mass Storage Class driver and its associated initialization components Speaker demo program spyLib Target shell

81

USB Developers Kit 1.1.2 Programmers Guide

This test was performed on a 400 MHz Pentium II machine with the following features:
I I I I

128 MB RAM Lucent Quadrabus 4-port OHCI card Philips USB speakers ORB 2.2 GB removable media USB drive

This test used the usbAudio demo programs play command to play a .wav le through the speakers. The Mass Storage Class driver initialization code was allowed use of the standard calls to the ORB drive, such as copy, rm, and format. To perform the test, a VxWorks image was built with all of the components listed above. Two host shells and a target shell were used for entering commands. Using one host shell, a large (~8 MB) le was copied from the host machine to the ORB drive. Immediately following, on the other host shell, a .wav le was played using the usbAudio tools play command. The .wav le was approximately 2 MB and had the following format: Size of Format: Format: Channels: Sample Rate: Bytes per Second: 16 Pulse Code Modulation (PCM) 1 22050 44100

While the .wav le was being transferred and sound was playing, spyLib was called, to display all tasks CPU usage. To invoke spyLib, give the following command through the target shell:
->spy 10, 200

This command to spyLib produces a report every 10 seconds, displaying data that was gathered at the rate of 200 times per second. The following 3 sample reports, Example 1-2, Example 1-3, and Example 1-4, were produced during the time the data transfers were in progress.
Example 1-2 spyLib Results Before USB Transfers NAME ENTRY ---------- -------tUsbdClnt tOhciInt tOhciInt tOhciInt tOhciInt tExcTask excTask tLogTask logTask tUsbdClnt TID ------3fd0604 3fb9da4 3f9fdb4 3f85da4 3f6bdf0 3f632d0 3f609cc 3f5cb38 PRI --0 0 0 0 0 0 0 0 total % (ticks) --------------0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) delta % (ticks) ---------------0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0)

82

1 USB Host Stack

tUsbdClnt tUsbdBus tUsbdBus tUsbdBus tUsbdBus tShel tWdbTask tPlay tBulkClnt tSpyTask tNetTask KERNEL INTERRUPT IDLE TOTAL

3f36e54 3fb595c 3f9b9a8 3f81998 3f679fc shell 3ea3c80 3ea4e14 36f4d88 3f327fc spyComTask 35a37f4 netTask 3ef0ed0

0 1 1 1 1 3 4 5 5 50

0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0%

( ( ( ( ( ( ( ( ( ( ( ( ( ( (

0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 1)

0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0% 0%

( ( ( ( ( ( ( ( ( ( ( ( ( ( (

0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 1)

Example 1-3 records when the data transfers begin to be logged.


Example 1-3 spyLib Results During USB Transfers NAME ENTRY ---------- -------tUsbdClnt tOhciInt tOhciInt tOhciInt tOhciInt tExcTask excTask tLogTask logTask tUsbdClnt tUsbdClnt tUsbdBus tUsbdBus tUsbdBus tUsbdBus tShell shell tWdbTask tPlay tBulkClnt tSpyTask spyComTask tNetTask netTask KERNEL INTERRUPT IDLE TOTAL TID ------3fd0604 3fb9da4 3f9fdb4 3f85da4 3f6bdf0 3f632d0 3f609cc 3f5cb38 3f36e54 3fb595c 3f9b9a8 3f81998 3f679fc 3ea3c80 3ea4e14 36f4d88 3f327fc 35a37f4 3ef0ed0 PRI --0 0 0 0 0 0 0 0 0 1 1 1 1 1 3 4 5 5 50 total % (ticks) --------------0% ( 0) 1% ( 24) 0% ( 2) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 3% ( 52) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 1) 0% ( 6) 0% ( 3) 0% ( 9) 93%( 1363) 97%( 1461) delta % (ticks) ---------------0% ( 0) 1% ( 12) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 3% ( 25) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 1) 0% ( 0) 0% ( 1) 0% ( 3) 94% ( 687) 98% ( 729)

Example 1-4

spyLib Results During USB Transfers NAME ENTRY ---------- -------tUsbdClnt tOhciInt TID ------3fd0604 3fb9da4 PRI --0 0 total % (ticks) --------------0% ( 0) 1% ( 30) delta % (ticks) ---------------0% ( 0) 0% ( 6)

83

USB Developers Kit 1.1.2 Programmers Guide

tOhciInt tOhciInt tOhciInt tExcTask tLogTask tUsbdClnt tUsbdClnt tUsbdBus tUsbdBus tUsbdBus tUsbdBus tShell tWdbTask tPlay tBulkClnt tSpyTask tNetTask KERNEL INTERRUPT IDLE TOTAL

excTask logTask

shell

spyComTask netTask

3f9fdb4 3f85da4 3f6bdf0 3f632d0 3f609cc 3f5cb38 3f36e54 3fb595c 3f9b9a8 3f81998 3f679fc 3ea3c80 3ea4e14 36f4d88 3f327fc 35a37f4 3ef0ed0

0 0 0 0 0 0 0 1 1 1 1 1 3 4 5 5 50

0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 3% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 0% ( 93%( 97%(

3) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 78) 0) 0) 0) 2) 7) 3) 17) 2048) 2189)

0% ( 1) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 0) 3% ( 26) 0% ( 0) 0% ( 0) 0% ( 0) 0% ( 1) 0% ( 1) 0% ( 0) 1% ( 8) 94% ( 685) 98% ( 728)

The OHCI task, which is responsible for handling the trafc, occupies a minimum amount of CPU time. (Four such tasks are shown in the reports above: one for each port on the Lucent card.) In addition to using spyLib, data throughput rates were determined using a CATC USB bus analyzer. The CATC is a bus sniffer that allows USB bus trafc to be monitored. The traces obtained from this hardware were used to calculate the bandwidth of this VxWorks host. These bandwidth calculations were obtained from the trafc during a le transfer to the ORB drive only. The ORB drive implements a 64-byte output endpoint for sending data to a host. It sends 512-byte chunks per transfer. The CATC trace showed transfers over a 499-millisecond period of time. Using the amount of raw data transferred in this interval, a throughput rate of 6 Mbps was calculated. This number most likely points to the device, not the host, as the bottleneck. Identical rates were also found using a Windows 98 Second Edition host.

1.15 BSP Porting Issues


The Wind River USB driver stack has been designed to ease porting across Wind River BSP platforms. At the source code level, the stack has been tested

84

1 USB Host Stack

successfully on both big and little-endian platforms and across several Wind River BSPs. (See USB Developers Kit Release Notes: Tested Devices.) You must address two key issues when porting the USB stack to a new BSP:
I

The BSP startup code must congure the USB hardware prior to the initialization of the USB stack. For UHCI and OHCI host stacks, the usbPciLib module (that is, the various usbPciStub.c les) must be modied to use the correct PCI functions in the underlying BSP.

The following sections discuss each of these issues in detail.

1.15.1 Conguring USB Hardware


As shipped, the Wind River USB stack supports both UHCI and OHCI USB host controllers. In all systems tested to date, both the UHCI and OHCI host controllers are implemented as PCI devices. As with any PCI device, the UHCI and OHCI host controllers need to be congured to use specic PCI resources. A PCI UHCI host controller, for example, uses a single I/O address range and one interrupt channel. A PCI OHCI controller, on the other hand, uses a single memory address range and one interrupt channel. Both types of controllers need to be assigned a unique address range and an interrupt channel, as well as enabled for bus master operation on the PCI bus; these activities are referred to in this manual as conguring the USB hardware. It is important to note that the Wind River USB stack itself makes no attempt to assign such PCI resources. Instead, the stack expects that the USB host controller(s) are already assigned resources and enabled before an attempt is made to attach the specic host controller to the USBD.

BSPs with pciAutoCongLib

Certain Wind River BSPs include the module pciAutoCongLib; in these BSPs, the conguration of each PCI device is handled automatically. The only PCI devices not congured automatically are those listed in the PCI auto-cong exclude list which is unique for each BSP. So, in order to congure a UHCI or OHCI host controller in these systems, you should ensure that the USB host controller is not in the exclude list. For more information about pciAutoCongLib, see your BSP documentation.

85

USB Developers Kit 1.1.2 Programmers Guide

BSPs Without pciAutoCongLib

In BSPs that do not include pciAutoCongLib, the assignment of PCI resources and enabling of each PCI device is generally handled in sysLib.c. You must write code that explicitly assigns certain PCI resources to each PCI device to be congured. That can be done in a conglette or by modifying sysLib.c directly.
NOTE: For this release, this functionality is provided by a conglette; see the

component description le (CDF) in target/cong/comps/vxWorks/src. The following example was written for the mtx604 BSP to enable an OPTi FireLink 82C861 OHCI host controller. Use this code in a conglette or add it directly to sysLib.c:
/**************************************************************************** * * sysUsbPciOhciInit - configures OHCI adapter * * This routine attempts to locate an OHCI controller. If found, it sets up * the controller's PCI configuration. * * RETURNS: N/A */ void sysUsbPciOhciInit (void) { int pciBus; int pciDevice; int pciFunc; /* Attempt to locate the OHCI controller. */ if (pciFindDevice (0x1045 /* OPTi */, 0xc861 /* 82c861 */, 0, &pciBus, &pciDevice, &pciFunc) != OK) return; /* Set up the base memory address for the controller. */ pciDevConfig (pciBus, pciDevice, pciFunc, NULL, PCI_MEM_ADRS, PCI_CMD_MASTER_ENABLE | PCI_CMD_MEM_ENABLE); /* Set up the controller's interrupt assignment. */ pciConfigOutByte (pciBus, pciDevice, pciFunc, PCI_CFG_DEV_INT_LINE, 0xb /* based on PCI "slot" number */); }

The sysUsbPciOhciInit( ) routine is called at the end of sysHwInit( ) in sysLib.c. In this example, the OHCI controller needs a memory address range through which usbHcdOhciLib reads and writes the controllers memory-mapped registers. The choice of the address, PCI_MEM_ADRS the fth parameter to

86

1 USB Host Stack

pciDevCong( )was appropriate for temporary testing on the mtx604 BSP. You should make a permanent selection for your particular BSP and create constants that document this assignment. Similarly, in this example, the interrupt channel 0xb is assigned to the OHCI controller. The mtx604 motherboard routes the physical PCI slot to interrupt channel 0xb. The interrupt channel number in your BSP or hardware environment is likely to be different, and your code should reect this. The choice of a specic address range or interrupt channel depends entirely on the underlying hardware conguration.

1.15.2 Conguring Memory Address Windows


When using PCI devices that require memory address windows, such as OHCI host controllers, you must make sure that a memory mapping has been created, allowing the processor to see the memory window assigned to the PCI device. In the sysUsbPciOhciInit( ) example in BSPs with pciAutoCongLib, p.85, the memory window beginning at PCI_MEM_ADRS already has a mapping on the mtx604 platform, and no code modications are required. However, other BSP platforms might require alterations, for example, the pcPentium platform. The following code fragment creates a CPU memory mapping entry for the pcPentium. Add this code at the end of sysHwInit( ) in sysLib.c, either through a conglette or by manually inserting it:
int pciBus; int pciDevice; int pciFunc; UINT32 membaseCsr; /* Find the OPTi controller. */ if (pciFindDevice (0x1045 /* OPTi */, 0xc861 /* 82C861 */, 0, &pciBus, &pciDevice, &pciFunc) != OK) return; /* get memory base address. * * NOTE: Were assuming here that the memory address range was assigned * elsewhere, perhaps by pciAutoConfigLib. */ pciConfigInLong (pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_0, &membaseCsr); membaseCsr &= PCI_MEMBASE_MASK; /* add the entry to sysPhysMemDesc[]. * * Note: This code must be executed before usrMmuInit(). */

87

USB Developers Kit 1.1.2 Programmers Guide

sysMmuMapAdd ((void *) membaseCsr, 0x1000 /* 4k window */, 0x3f /* memory attribute mask */, 0x5 /* memory attributes */);

The nal function call in the above code, sysMmuMapAdd( ), creates a memory mapping on the pcPentium platform. The mechanism for creating such a mapping will vary from BSP to BSP. For more information, check the relevant BSP documentation.

1.15.3 Creating BSP-Specic Stub usbPciLib Files


As noted earlier, the stubUsbArchPciLib.c les shield the UHCI and OHCI HCDs from variations among underlying BSPs. These les provide the following routines, however the underlying PCI functionality may vary from one BSP to the next. 8-bit, 16-bit, and 32-bit data I/O: usbPciByteIn( ) usbPciDwordIn( ) usbPciWordOut( ) usbPciWordIn( ) usbPciByteOut( ) usbPciDwordOut( )

Address range translation functions: usbPciMemOffset( ) usbMemToPci( ) usbPciToMem( ) Interrupt functions: usbPciIntConnect( ) usbPciIntRestore( )
NOTE: Certain Wind River BSPs do not support disconnection from the

underlying PCI interrupt vector. See USB Developers Kit Release Notes: BSP-Specic Issues. Internally, the stubUsbArchPciLib.c les implement the above routines by dening a series of macros. Denitions may vary from BSP to BSP. The following code excerpt from stubUsbPpcPciLib.c shows how the necessary macros are dened for the mcp750 and mtx604. Creating your own stub le for a new platform generally involves creating a comparable set of denitions customized for that platform.

88

1 USB Host Stack

/* Power PC 604 (e.g., mcp750) */ #include "mv2600.h" /* Mappings for I/O and memory address translation (values from mv2600.h) */ #define PCI_IO_OFFSET CPU_PCI_ISA_IO_ADRS #define PCI_MEM_OFFSET PCI2DRAM_BASE_ADRS #define PCI_MEMIO_OFFSET (CPU_PCI_MEM_ADRS - PCI_MEM_ADRS) /* The mcp750 doesnt define sysInWord, sysInLong, sysOutWord, and * sysOutLong. It includes the following entry points instead for which * there is no vxWorks function prototype. We include the following * definitions in order to suppress compiler warnings. */ extern USHORT sysIn16 (int port); extern ULONG sysIn32 (int port); extern void sysOut16 (int port, short data); extern void sysOut32 (int port, long data); /* Map the "standard" vxworks I/O functions to the mcp750 equivalents */ #define sysInWord(p) sysIn16(p) #define sysInLong(p) sysIn32(p) #define sysOutWord(p,d) sysOut16(p,d) #define sysOutLong(p,d) sysOut32(p,d) /* Interrupt enable/disable */ #ifdef MCP750 #define INTERRUPT_BASE ISA_INTERRUPT_BASE #else #define INTERRUPT_BASE EXT_INTERRUPT_BASE #endif #define IVEC(i) INUM_TO_IVEC ((int) ((i) + INTERRUPT_BASE))

#define INT_CONNECT(intNo, func, param) \ intConnect (IVEC (intNo), (VOIDFUNCPTR) func, (int) param) #define INT_DISCONNECT(intNo, func, param) #define INT_ENABLE(i) #define INT_DISABLE(i) intEnable ((i) + INTERRUPT_BASE) intDisable ((i) + INTERRUPT_BASE)

/* Map I/O functions to underlying system functions. */ #define OUR_PCI_IN_BYTE(a) sysInByte ((a) + PCI_IO_OFFSET) #define OUR_PCI_IN_WORD(a) sysInWord ((a) + PCI_IO_OFFSET) #define OUR_PCI_IN_DWORD(a) sysInLong ((a) + PCI_IO_OFFSET) #define OUR_PCI_OUT_BYTE(a,v) sysOutByte ((a) + PCI_IO_OFFSET, (v)) #define OUR_PCI_OUT_WORD(a,v) sysOutWord ((a) + PCI_IO_OFFSET, (v)) #define OUR_PCI_OUT_DWORD(a,v) sysOutLong ((a) + PCI_IO_OFFSET, (v))

89

USB Developers Kit 1.1.2 Programmers Guide

90

2
USB Peripheral Stack
This chapter documents the USB peripheral stack, which is an extension of the USB Developers Kit, also known as the USB Kit. The USB peripheral stack interprets USB commands on USB devices running VxWorks. The USB peripheral stack includes the source code for the USB peripheral stack and rmware emulators. This chapter shows you how to write your own USB target controller driver and USB target rmware. The USB peripheral stack is designed to allow:
I

easy portability to RTOSs other than VxWorks fast development of new target controller drivers fast development of new target rmware

Tested Devices

The following device has been tested with the Wind River USB peripheral stack: Philips PDIUSBD12 evaluation kit

91

USB Developers Kit 1.1.2 Programmers Guide

2.1 Peripheral Stack Architecture


Figure 2-1 presents an overview of the USB peripheral stack.
Figure 2-1 Peripheral Stack Overview

USB Target Application

usbTargLib Interface

USB Target Driver (usbTargLib)

usbTargLib/TCD Interface

USB Target Controller Driver (TCD)

Software

Hardware
USB Target Controller (USB TC)

At the bottom of the stack is the USB target controller (USB TC), the hardware part of the peripheral that connects to the USB. Many manufacturers build USB target controllers, which vary widely in implementation. The sample code provided by Wind River supports an evaluation kit from Philips based on the Philips PDIUSBD12 target chip. The PDIUSBD12 is a general purpose USB target chip that supports each of the four basic USB transfers: control, interrupt, bulk, and isochronous. In the evaluation kit, the PDIUSBD12 sits on a standalone printed circuit board; a separate ISA bus adapter card is used to connect the board to a standard PC system.

92

2 USB Peripheral Stack

For each type of target controller, there is a corresponding USB target controller driver (TCD). The TCD provides a consistent, abstract view of the target controller to the upper software layers. The source for the pre-built Wind River driver for the Philips PDIUSBD12 is contained in the library usbTcdPhilipsPdiusbd12EvalLib. However, given the range of USB target chips available, there is a good chance a customer does not use the Philips PDIUSBD12, and even less likely a customer uses the Philips evaluation kit as part of an actual product. You should be prepared to customize or replace the sample USB target controller driver provided with the USB peripheral stack. Above the TCD sits the usbTargLib library, a hardware-independent module that provides an abstract set of services for simplifying the job of writing USB target applications. This library incorporates automatic handling, where possible, for USB requests. When automatic processing is not possible, usbTargLib relies on the target application to complete USB transactions. At run-time, one or more TCDs are attached to usbTargLib. For each TCD, a single target application is also registered with usbTargLib; and usbTargLib becomes responsible for routing requests and responses between the TCD and the target application. Architecturally, usbTargLib is capable of handling multiple TCDs and their corresponding target applications. As a practical matter, however, few peripherals have more than one target controller, TCD, and target application. At the top of the peripheral stack sits the target application. The target application is the module that gives the peripheral its personality. In response to USB requests received by the TCD and routed through usbTargLib, it is the target applications responsibility to provide appropriate responses. For example, when a request is received to get a USB descriptor from the peripheral, it is the target applications responsibility to provide the contents of the descriptor.

Peripheral Module Roadmap

Figure 2-2 illustrates the functional relationships between the modules that comprise Wind Rivers USB peripheral driver stack. The peripheral stack shares a consistent architectural approach with the USB host driver stack, as well as a number of common libraries. (Compare Figure 2-2 in this supplement with the gures in 1.2 Architecture Overview, p.5.)

93

USB Developers Kit 1.1.2 Programmers Guide

Figure 2-2

Peripheral Module Roadmap

cmdParser

usbTool USB Exerciser Utility

usbTargPhilipsD12EvalLib usbTargPrnLib ossLib usbTargKbdLib USB Keyboard Emulator

usbTargLib

usbDescrCopyLib usbQueueLib usbHandleLib usbListLib

usbTcdLib

usbTcdPdiusbd12EvalLib Philips PDIUSBD12 Evaluation Kit

usbIsaLib or usbPciLib Software Hardware System Hardware (for example, ISA bus controller) Philips PDIUSBD 12 Evaluation Kit

94

2 USB Peripheral Stack

Modules that are unique to the USB peripheral stack are described in this section. For information on modules shared with the host stack, see 1.2 Architecture Overview, p.5. For additional information on USB-related libraries and subroutines, see the associated reference pages in the online VxWorks Reference Manual: USB Libraries. usbTool This module is a test application that exercises both the Wind River USB host and peripheral stacks. The usbTool functions that control the peripheral stack are independent of those that control the host stack. In fact, if a VxWorks target has both USB host and peripheral hardware, usbTool can be used to control both simultaneously and the two can talk to one another! usbTargPhilipsD12EvalLib The Philips PDIUSBD12 evaluation kit includes a reference rmware implementation. This rmware is implemented as a DOS application. When running, the rmware makes the PDIUSBD12 look like a test device recognizable by a Windows-based Philips test program. The Philips test program allows the user to exercise certain functions on the PDIUSBD12 evaluation board. The usbTargPhilipsD12EvalLib module is a target application that emulates the behavior of the Philips reference rmware. Thus, the Philips test program communicates with the PDIUSBD12 evaluation board when the PDIUSBD12 is under the control of the Wind River USB peripheral stack. usbTargPrnLib This module is a very simple (and incomplete) example of a target application that acts like a USB printer. This module was originally developed to test USB bulk transfers through the PDIUSBD12; its emulation of a printer is not complete enough to allow it to talk to a standard Windows host, for example. usbTargKbdLib Like usbTargPrnLib, this module is a very simple and incomplete example of a target application that acts like a USB keyboard. It was originally developed to test USB interrupt transfers through the PDIUSBD12. Taken together, the three libraries (usbTargPhilipsD12EvalLib, usbTargPrnLib, and usbTargKbdLib) are useful principally to demonstrate how simple it is to create a target application on top of the usbTargLib interface.

95

USB Developers Kit 1.1.2 Programmers Guide

usbTargLib This module is the core of the USB peripheral stack. It is responsible for routing requests between TCDs and their corresponding target applications. The usbTargLib module automatically manages the default control pipe for each TCD and provides default handlers, where meaningful, for each USB control request. This module also incorporates the necessary functions to allow target applications to transfer data across the USB, either in response to control requests or on other USB pipes. usbTcdLib This module provides functions to invoke each of the services provided by a USB TCD. It is used by usbTargLib to communicate with underlying HCDs. The functions in usbTcdLib are not called directly by modules other than usbTargLib. usbTcdPdiusbd12EvalLib This module is the TCD for the Philips PDIUSBD12 evaluation kit. All hardware-dependent code for a target controller is contained in the TCD. Each TCD exports a single entry point, generally with a name of the form usbTcdXxxxExec( ), and all communication with the TCD is performed through this function. There is no direct link between usbTargLib and any underlying TCD; that is, usbTargLib has no prior (compile-time) knowledge of which TCDs are to be loaded in a particular system. Each TCDs entry point is exposed to usbTargLib during a process called TCD attachment, described in 2.2.2 Attaching and Detaching TCDs, p.98. usbIsaLib or usbPciLib This module provides the TCD with an abstract set of ISA bus services, allowing the TCD to be written independent of variations in the underlying BSP. In the case of the pcPentium BSP, on which the Wind River USB peripheral stack was developed and tested, each of the usbIsaLib functions is redirected to a corresponding function in usbPciLib. For a description of usbPciLib, see 1.2 Architecture Overview, p.5. There is no requirement that a particular TCD be written to use usbIsaLib or even usbPciLib. These modules were designed to promote portability across BSP platforms. In systems where that is not an issue, developers can freely code directly to the hardware in the TCD itself.

96

2 USB Peripheral Stack

2.2 USB Target Driver (usbTargLib)


This section describes typical use of the usbTargLib, activities such as initialization, TCD attachment, and data transfers. It also discusses key features of modules internal design.
2

2.2.1 Initializing usbTargLib


Initializing usbTargLib is a two-step process. First, usbTargLibs entry point, usbTargInitialize( ), must be called at least once. The usbTargInitialize( ) routine initializes internal usbTargLib data structures and, in turn, calls the initialization entry points of other modules in the USB driver stack. For a given system, it is acceptable to call usbTargInitialize( ) once (perhaps during the boot sequence) or to call it many times (as during the initialization of each TCD or target application). The usbTargLib driver maintains a usage count that is incremented for each successful call to usbTargInitialize( ) and decremented for each corresponding call to usbTargShutdown( ). The driver only truly initializes itself when the usage count goes from zero to one, and it only truly shuts down when the usage count returns to zero. The following code fragment illustrates the proper initialization and shutdown of usbTargLib:
... /* Initialize usbTargLib. */ if (usbTargInitialize () != OK) return ERROR; ... ... /* target application code. */ ... ... /* Shut down usbTargLib. Note: we only execute this code if the return * code from usbTargInitialize() was OK. Note also that theres really no * reason to check the result of usbTargShutdown(). */ usbTargShutdown ();

The second step of usbTargLib initialization is to attach at least one TCD to the driver, using usbTargLibs usbTargTcdAttach( ) routine. Normally, the attachment of TCDs to usbTargLib happens during the VxWorks boot sequence.

97

USB Developers Kit 1.1.2 Programmers Guide

However, usbTargLib is designed to allow TCDs to be attached (and detached) at run-time. This exibility allows usbTargLib to support systems in which USB target controllers can be hot-swapped without restarting the system.

2.2.2 Attaching and Detaching TCDs


You decide when to attach TCDs to usbTargLib and when to detach them, if ever. In most peripheral applications, a single TCD and corresponding target application are attached to usbTargLib during the initial boot sequence and remain attached indenitely. In order to attach a TCD to usbTargLib, the caller passes the TCDs execution entry point and a TCD-dened parameter (the TCD attachment parameter) to the usbTargTcdAttach( ) routine. The caller must also provide the address of a callback table that identies key entry points in the target application. The target applications callback table is described more fully in 2.2.4 Target Application Callback Table, p.100. Finally, the caller provides pointers to variables that receive information about the TCD attachment, including a handle to the attached TCD and information about the USB endpoints supported by the TCD. In response to the usbTargTcdAttach( ) call, usbTargLib invokes the TCDs execution entry point with a TCD_FNC_ATTACH service request, passing it the same TCD attachment parameter provided by the caller. Use of this TCD-dened parameter can vary, however the Philips PDIUSBD12 example interprets this parameter as a pointer to a structure of the following form:
typedef struct usb_tcd_pdiusbd12_params { UINT32 ioBase; /* Base I/O address range */ UINT16 irq; /* IRQ channel (e.g., 5 = IRQ5) */ UINT16 dma; /* DMA channel (e.g., 3 = DMA3) */ } USB_TCD_PDIUSBD12_PARAMS, *pUSB_TCD_PDIUSBD12_PARAMS;

For the Philips evaluation kit, the caller must initialize this structure with settings corresponding to the Philips ISA bus board. For other target systems, these values can be hard-coded. The TCD uses the information in this structure to locate and manage the specied target controller. The following code fragment demonstrates how to attach the Philips evaluation kit to usbTargLib:
/* Attach the Philips PDIUSBD12 evaluation kit TCD to usbTargLib. */ USB_TCD_PDIUSBD12_PARAMS params; memset (&params, 0, sizeof (params));

98

2 USB Peripheral Stack

params.ioBase = (UINT32) 0x368; params.irq = (UINT16) 5; params.dma = (UINT16) 7; if (usbTargTcdAttach ( usbTcdPdiusbd12EvalExec, (pVOID) &params, callbackTable,

2
/* /* /* /* /* /* /* /* TCDs entry point */ TCD-specific parameter */ target apps callback table */ is defined elsewhere */ target app-specific parameter */ handle returned by usbTargLib */ nbr of endpoints supported by TCD */ an array of info about endpoints */)

callbackParam, &targChannel, &numEndpoints, &pEndpoints,) == OK) { /* TCD & target application were initialized successfully. */ /* Do post-attach processing. */ ... ... /* Now enable the TCD. */

if (usbTargEnable (targChannel) != OK) { /* Failed to enable TCD. */ } } else { /* Failed to attach the TCD & initialize the target application. */ }

CAUTION: While usbTargLib and the sample Philips TCD are designed to support

the dynamic attachment and detachment of TCDs, some Wind River BSPs do not support the disconnection of the USB TCD from the underlying interrupt vector, a function essential to the detaching process. If the vector is subsequently re-enabled, the system may attempt to execute a stale interrupt service routine and will fault.

2.2.3 Enabling and Disabling TCDs


In some situations, the target application may not be ready to begin handling USB requests as soon as it calls usbTargTcdAttach( ). For example, the target application may need to store and process the endpoint information returned by usbTargTcdAttach( ) rst. For this reason, usbTargLib provides two additional functions to enable and disable the TCD.

99

USB Developers Kit 1.1.2 Programmers Guide

The routine usbTargEnable( ) enables the specied TCD. The TCD, in turn, enables the underlying USB target controller. By convention, the target controller should not turn on its USB drivers until the TCD has been enabled by calling usbTargEnable( ). Thus, until usbTargEnable( ) has been called, the target controller, and thus the peripheral, is not visible on the USB. The routine usbTargDisable( ) disables the specied TCD and is generally called just before detaching a TCD. The previous code fragment in 2.2.2 Attaching and Detaching TCDs, p.98 illustrates one use of the usbTargEnable( ) function.

2.2.4 Target Application Callback Table


USB peripherals never initiate activity on the USB1. Instead, all USB activity is initiated by the USB host. The architecture of the USB peripheral stack reects this in the way communication is handled between usbTargLib and the target application. Once the TCD and its associated target application have been attached to usbTargLib, usbTargLib asynchronously calls back into the target application by way of the entry points exposed in the target applications callback table. The callback table takes the following form:
typedef struct usb_targ_callback_table { /* device management callbacks */ USB_TARG_MANAGEMENT_FUNC mngmtFunc; /* Control pipe callbacks */ USB_TARG_FEATURE_CLEAR_FUNC featureClear; USB_TARG_FEATURE_SET_FUNC featureSet; USB_TARG_CONFIGURATION_GET_FUNC configurationGet; USB_TARG_CONFIGURATION_SET_FUNC configurationSet; USB_TARG_DESCRIPTOR_GET_FUNC descriptorGet; USB_TARG_DESCRIPTOR_SET_FUNC descriptorSet; USB_TARG_INTERFACE_GET_FUNC interfaceGet; USB_TARG_INTERFACE_SET_FUNC interfaceSet; USB_TARG_STATUS_GET_FUNC statusGet; USB_TARG_ADDRESS_SET_FUNC addressSet; USB_TARG_SYNCH_FRAME_GET_FUNC synchFrameGet; USB_TARG_VENDOR_SPECIFIC_FUNC vendorSpecific; } USB_TARG_CALLBACK_TABLE, *pUSB_TARG_CALLBACK_TABLE;

1. There is one exception: When the USB is in the SUSPEND state, a USB peripheral can initiate RESUME signaling, as described in 2.2.9 Resume Signaling, p.112.

100

2 USB Peripheral Stack

Before calling the usbTargTcdAttach( ) routine, the function pointers in this table should be set to point to corresponding entry points in the target application. As soon as usbTargTcdAttach( ) is called, usbTargLib begins making asynchronous calls to the entry points in the callback table. (Some callbacks are immediate and occur during the attach process itself; others happen in response to activity on the USB.) The target application should provide pointers for each function whose requests need software processing. The usbTargLib driver provides default handling for any functions whose corresponding entry in the callback table is NULL. The prototypes for each of these callbacks are dened in usbTargLib.h. Two parameters are common to each of the callback functions:
pVOID param USB_TARG_CHANNEL targChannel

param The application-dened parameter originally passed to usbTargLib as part of the usbTargTcdAttach( ) function. Its value is not interpreted by usbTargLib, and it can take on any meaning dened by the target application. targChannel The handle assigned to the TCD by usbTargLib during attach processing. The following sections describe each callback in the callback table in more detail.

mngmtFunc( ) Callback

The target driver usbTargLib invokes the target applications mngmtFunc( ) callback to inform the application of changes that broadly affect the USBs operation. This callback takes the following form:
typedef STATUS (*USB_TARG_MANAGEMENT_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 mngmtCode /* management code */ );

101

USB Developers Kit 1.1.2 Programmers Guide

The mngmtCode parameter tells the target application what management event has happened. It takes the following values, as dened in usbTcd.h:
TCD_MNGMT_ATTACH TCD_MNGMT_DETACH TCD_MNGMT_VBUS_DETECT TCD_MNGMT_VBUS_LOST TCD_MNGMT_BUS_RESET TCD_MNGMT_SUSPEND TCD_MNGMT_RESUME initial TCD attachment TCD detach bus detected Vbus lost bus reset suspend signaling detected resume signaling detected

The target application can process or ignore these management codes as it sees t. In most cases, usbTargLib ignores the status returned by the mngmtFunc( ) callback. However, usbTargLib does examine the mngmtFunc( ) return code in response to the TCD_MNGMT_ATTACH code. In this case, if the mngmtFunc( ) returns ERROR, TCD attachment is aborted. The target driver provides default handling for the mngmtFunc( ) callback. The default handler always returns OK.

Control Pipe Request Callbacks

The target driver usbTargLib provides default processing for all standard requests received on the peripherals default control pipe (endpoint #0). For each of the standard USB control requests, usbTargLib provides some form of default processing. The following callbacks can be provided by the target application to modify default processing.
featureClear( ) and featureSet( ) Callbacks

The target driver usbTargLib invokes the target applications featureClear( ) and featureSet( ) callbacks in response to the USB CLEAR_FEATURE and SET_FEATURE requests, respectively. These callbacks take the following form:
typedef STATUS (*USB_TARG_FEATURE_CLEAR_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 requestType, UINT16 feature, UINT16 index );

102

2 USB Peripheral Stack

typedef STATUS (*USB_TARG_FEATURE_SET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 requestType, UINT16 feature, UINT16 index );

If the target application supports these functions, it should clear or set the feature identied by the requestType, feature, and index parameters. If the target application does not provide these callbacks, then usbTargLib returns an error in response to the corresponding requests. Similarly, if the callbacks return ERROR, usbTargLib returns an error in response to the corresponding request.
congurationGet( ) and congurationSet( ) Callbacks

The target driver usbTargLib invokes the target applications congurationGet( ) and congurationSet( ) callbacks in response to the USB GET_CONFIGURATION and SET_CONFIGURATION requests. These callbacks take the following form:
typedef STATUS (*USB_TARG_CONFIGURATION_GET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, pUINT8 pConfiguration ); typedef STATUS (*USB_TARG_CONFIGURATION_SET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 configuration );

For the congurationGet( ) callback, the target application should ll the pConguration buffer with the UINT8 value identifying the current conguration; usbTargLib transmits the response back to the USB host. For congurationSet( ), the target application should set the current conguration to the value indicated by conguration. If the target application does not provide these callbacks, then usbTargLib returns an error in response to the corresponding requests. Similarly, if the callbacks return ERROR, usbTargLib returns an error in response to the corresponding request.

103

USB Developers Kit 1.1.2 Programmers Guide

descriptorGet( ) and descriptorSet( ) Callbacks

The target driver usbTargLib invokes the target applications descriptorGet( ) and descriptorSet( ) callbacks in response to the USB GET_DESCRIPTOR and SET_DESCRIPTOR requests. These callbacks take the following form:
typedef STATUS (*USB_TARG_DESCRIPTOR_GET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 requestType, UINT8 descriptorType, UINT8 descriptorIndex, UINT16 languageId, UINT16 length, pUINT8 pBfr, pUINT16 pActLen ); typedef STATUS (*USB_TARG_DESCRIPTOR_SET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 requestType, UINT8 descriptorType, UINT8 descriptorIndex, UINT16 languageId, UINT16 length );

The requestType, descriptorType, descriptorIndex, and languageId parameters identify the descriptor requested by the USB host. For the descriptorGet( ) callback, the target application should ll the pBfr buffer with the requested descriptor (not to exceed the buffer size specied by length). The target application should also set the pActLen variable to the length of the descriptor placed in pBfr. The target driver transmits the descriptor back to the USB host. In the case of descriptorSet( ), the target application must use the usbTargControlPayloadRcv( ) routine (see Control Pipe Data Transfers, p.110) to receive the descriptor being sent by the USB host, then process it appropriately. If the target application does not provide these callbacks, usbTargLib returns an error in response to the corresponding requests. Similarly, if the callbacks return ERROR, usbTargLib returns an error in response to the corresponding request.

104

2 USB Peripheral Stack

interfaceGet( ) and interfaceSet( ) Callbacks

The target driver usbTargLib invokes the target applications interfaceGet( )) and interfaceSet( )) callbacks in response to the USB GET_DESCRIPTOR and SET_DESCRIPTOR requests. These callbacks take the following form:
typedef STATUS (*USB_TARG_INTERFACE_GET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 interfaceIndex, pUINT8 pAlternateSetting ); typedef STATUS (*USB_TARG_INTERFACE_SET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 interfaceIndex, UINT8 alternateSetting );

For the interfaceGet( ) callback, the target application should store its current interface setting in the variable pAlternateSetting, for the interface specied by interfaceIndex. For interfaceSet( ), the target application should set its interface according to the interfaceIndex and alternateSetting parameters. If the target application does not provide these callbacks, then usbTargLib returns an error in response to the corresponding requests. Similarly, if the callbacks return ERROR, usbTargLib returns an error in response to the corresponding request.
statusGet( ) Callback

The target driver usbTargLib invokes the target applications statusGet( ) callback in response to the USB GET_STATUS request. This callback takes the following form:
typedef STATUS (*USB_TARG_STATUS_GET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 requestType, UINT16 index, UINT16 length, pUINT8 pBfr, pUINT16 pActLen );

If the target application supports this callback, it should store the appropriate status in pBfr (not to exceed the length specied by length). It should also store the

105

USB Developers Kit 1.1.2 Programmers Guide

length of the status in pActLen. The target driver sends the status back to the USB host. If the target application does not provide this callback, usbTargLib returns an error in response to GET_STATUS requests. Similarly, if the statusGet( ) callback returns ERROR, then usbTargLib returns an error in response to the corresponding request.
addressSet( ) Callback

The target driver usbTargLib invokes the target applications addressSet( ) callback in response to the USB SET_ADDRESS request. This callback takes the following form:
typedef STATUS (*USB_TARG_ADDRESS_SET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 deviceAddress );

The target driver handles the SET_ADDRESS request automatically whether or not the target application supports this callback. The current implementation of usbTargLib ignores the STATUS returned by this callback.
synchFrameGet( ) Callback

The target driver usbTargLib invokes the target applications synchFrameGet( ) callback in response to the USB GET_SYNCH_FRAME request. This callback takes the following form:
typedef STATUS (*USB_TARG_SYNCH_FRAME_GET_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT16 endpoint, pUINT16 pFrameNo );

Typically, this function is used to synchronize isochronous data transfers. If the application supports it, then the callback should store the synch frame information in pFrameNo and return OK. The target driver sends the response to the USB host. If the target application does not provide this callback, usbTargLib returns an error in response to GET_SYNCH_FRAME requests. Similarly, if the synchFrameGet( )

106

2 USB Peripheral Stack

callback returns ERROR, usbTargLib returns an error in response to the corresponding request.
2 vendorSpecic( ) Callback

All requests received on the peripherals default control pipe and not recognized as standard requests are routed to the target applications vendorSpecic( ) callback, if one is provided. This callback takes the following form:
typedef STATUS (*USB_TARG_VENDOR_SPECIFIC_FUNC) ( pVOID param, USB_TARG_CHANNEL targChannel, UINT8 requestType, UINT8 request, UINT16 value, UINT16 index, UINT16 length );

The target applications handling of vendor-specic requests varies widely. Some vendor-specic requests can require additional data transfer, perhaps using usbTargLibs usbTargControlPayloadRcv( ) or usbTargControlResponseSend( ) for support. If the target application handles the vendor-specic request successfully, it should return OK. If the target application does not provide this callback, usbTargLib returns an error in response to a vendor-specic request. Similarly, if the vendorSpecic( ) callback returns ERROR, usbTargLib returns an error in response to the corresponding request.

2.2.5 TCD Endpoints


In response to the usbTargTcdAttach( ) routine, usbTargLib returns the number of endpoints supported by the target and a pointer to an array describing each endpoint. Each entry in this array takes the following form:
typedef struct usb_targ_endpoint_info { UINT16 endpointId; /* TCD-assigned endpoint ID */ UINT16 flags; /* endpoint characteristics */ UINT16 endpointNumMask; UINT32 ctlMaxPacketSize; UINT32 bulkInMaxPacketSize; UINT32 bulkOutMaxPacketSize; /* mask of allowed endpoint numbers */ /* max packet size in control mode */ /* max packet size in bulk IN mode */ /* max packet size in bulk OUT mode */

107

USB Developers Kit 1.1.2 Programmers Guide

UINT32 bulkInOutMaxPacketSize; UINT32 UINT32 UINT32 UINT32 UINT32 UINT32 UINT16 UINT16 UINT16 UINT16 UINT16 intInMaxPacketSize; intOutMaxPacketSize; intInOutMaxPacketSize; isochInMaxPacketSize; isochOutMaxPacketSize; isochInOutMaxPacketSize; endpointNum; configuration; interface; transferType; direction;

/* max packet size in bulk I/O mode */ /* /* /* /* /* /* /* /* /* /* /* max max max max max max packet packet packet packet packet packet size size size size size size in in in in in in intrpt IN mode */ intrpt OUT mode */ intrpt I/O mode */ isoch IN mode */ isoch OUT mode */ isoch I/O mode */

currently assigned endpoint num */ current configuration */ current interface */ current transfer type */ current direction */

UINT16 maxPacketSize;

/* max packet size as configured */

} USB_TARG_ENDPOINT_INFO, *pUSB_TARG_ENDPOINT_INFO;

The purpose of this structure is to give TCDs, and thus usbTargLib, a way to describe the endpoint capabilities of a particular TCD and target controller in a hardware-independent manner. The target application should treat this structure as read-only. Its elds are dened as follows: endpointId An arbitrary endpoint ID number assigned by the TCD to a particular endpoint. ags A description of the capabilities of the endpoint, as follows:
TCD_ENDPOINT_IN_OK TCD_ENDPOINT_OUT_OK TCD_ENDPOINT_CTRL_OK TCD_ENDPOINT_BULK_OK TCD_ENDPOINT_INT_OK TCD_ENDPOINT_ISOCH_OK TCD_ENDPOINT_IN_USE host->device capable device->host capable capable of control xfr capable of bulk xfr capable of interrupt xfr capable of isoch xfr endpoint has pipe

endpointNumMask A bit-vector identifying the endpoint numbers that can be supported by the endpoint. For example, if bit 0 is 1, the endpoint can be endpoint 0. If bit 1 is 1, the endpoint can be endpoint 1. And so on. xxxMaxPacketSize These elds dene the maximum packet size supported by the endpoint when enabled as a control, bulk, interrupt, or isochronous endpoint.

108

2 USB Peripheral Stack

endpointNum The endpoint number currently assigned to this endpoint. conguration interface The conguration and interface with which this endpoint is currently congured. transferType direction Similar to conguration and interface, the endpoints transfer type and direction, as USB_XFRTYPE_xxxx and USB_DIR_xxxx. maxPacketSize The maximum packet size as currently congured. While this abstract endpoint structure permits target applications to be written without prior knowledge of the capabilities of the underlying TCD and target controller, many target application developers are likely to bypass this abstraction and code their target applications to use specic endpoints based on their knowledge of the underlying hardwares capability.
2

2.2.6 Data Transfer


All data transfers on a USB are initiated by the USB host. In general, a host creates a pipein other words, a connectionto a specic endpoint on a given peripheral. In addition to the address of the peripheral and the endpoint number, the pipe has other characteristics, such as the data type (control, bulk, interrupt, or isochronous), direction, and perhaps information describing the bandwidth required by the pipe. Having created a pipe, the USB host application requests data transfers by formatting IRPs (I/O request packets) and submitting them to the USB driver (called the USBD in the Wind River USB host stack). The Wind River USB peripheral stack functions similarly. A target application creates pipes and attaches them to specic endpoints supported by the TCD and target controller. Pipes are created and destroyed using the routines usbTargPipeCreate( ) and usbTargPipeDestroy( ). As described further in Control Pipe Data Transfers, p.110, usbTargLib automatically creates the pipe for the default control endpoint (endpoint #0); so the target application itself omits the pipe creation step for the default control pipe.

109

USB Developers Kit 1.1.2 Programmers Guide

NOTE: By convention, the direction of a particular pipe is always viewed from the

USB hosts perspective; so, a pipe that transfers data from the host to the peripheral has a direction of USB_DIR_OUT (even though the peripheral sees the data as incoming). Similarly, a pipe that transfers data from the peripheral to the host has a direction of USB_DIR_IN. After creating the necessary pipes, the target application formats USB_ERPs (USB endpoint request packets) which describe data to be transferred. When the USB host requests a transfer to or from a specic target endpoint, the USB peripheral stack responds by transferring data to or from USB_ERPs provided by the target application. USB_ERPs take the following form:
typedef struct usb_erp { LINK targLink; pVOID targPtr; LINK tcdLink; pVOID tcdPtr; pVOID userPtr; UINT16 erpLen; int result; ERP_CALLBACK targCallback; ERP_CALLBACK userCallback; UINT16 endpointId; UINT16 transferType; UINT16 dataToggle; UINT16 bfrCount; USB_BFR_LIST bfrList [1]; } USB_ERP, *pUSB_ERP;

/* /* /* /* /* /* /* /* /* /* /* /* /*

link field used internally by usbTargLib */ ptr field for use by usbTargLib */ link field used internally by USB TCD */ ptr field for use by USB TCD */ ptr field for use by client */ total length of ERP structure */ ERP completion result: S_usbTcdLib_xxxx */ usbTargLib completion callback routine */ client's completion callback routine */ device endpoint */ type of ERP: control, bulk, etc. */ ERP should start with DATA0/DATA1. */ indicates count of buffers in BfrList */

There are numerous similarities between this data structure and the USB_IRP used by the Wind River USB host stack. The USB_BFR_LIST structure in the USB_ERP is identical to the one included as part of the USB_IRP. As with the USB host stack, the USB peripheral stack automatically manages the dataToggle for ERPs; thus, the target application is not required to keep track of the current state of DAT0 and DATA1 for each pipe.

Control Pipe Data Transfers

The usbTargLib driver automatically manages communication on the default control pipe (endpoint #0), making it unnecessary for the target application to create a pipe for this particular endpoint. However, this also means that the target application has no direct access to the default control pipe. For this reason,

110

2 USB Peripheral Stack

usbTargLib provides two routines that allow the target application to transfer data through the default control pipe: usbTargControlResponseSend( ) Send control pipe responses to the USB host. usbTargControlPayloadRcv( ) Receive additional control pipe payloads from the USB host. Unlike the general data transfer routines (see General Data Transfers, p.111), these routines take as parameters only the TCD handle and a pointer to a USB_ERP. The TCD handle uniquely identies the default control pipe, because there can only be one default control pipe for each TCD and target controller Target applications typically use these routines when servicing USB requests like GET_DESCRIPTOR and SET_DESCRIPTOR, or when servicing vendor-specic requests.
2

General Data Transfers

In order to perform data transfers that do not involve the default control pipe, the target application must rst create pipes as described 2.2.6 Data Transfer, p.109. In response to a request to create a pipe, usbTargLib returns a USB_TARG_PIPE handle to the target application. The target application must use this handle to identify the correct pipe in subsequent calls to usbTargTransfer( ) and usbTargTransferAbort( ). The target application passes a USB_TARG_PIPE handle and a formatted USB_ERP to usbTargTransfer( ) to request a data transfer. The usbTargTransferAbort( ) routine allows previously submitted transfers to be aborted.

2.2.7 Setting Endpoint Stall


When the target application detects certain error conditions, it may wish to set a particular endpoint to the STALLed state. The STALL state is an indication to the USB host that an error has been detected. The target driver usbTargLib provides the routine usbTargPipeStatusSet( ) which allows the target application to set the state of a pipe as STALLed or unSTALLed. In addition, this routine allows the target application to reset the next expected data toggle for the endpoint to DATA0, as may happen after the target receives other commands from the USB host, perhaps on the default control pipe.

111

USB Developers Kit 1.1.2 Programmers Guide

The target application cannot set the STALL or unSTALL state directly for the default control pipe. The usbTargLib driver automatically sets the default control pipe to the STALL state whenever an error is detected in the processing of a request on the default control pipe. The target driver automatically unSTALLs the default control pipe whenever a new SETUP packet is received, as required by the USB Specication. For more information on the STALL state, see the USB Specication.

2.2.8 Bus Frame Number


Certain target applications need to determine the current USB frame number generally those implementing isochronous data transfers. The usbTargLib driver provides the routine usbTargCurrentFrameGet( ) for this purpose.

2.2.9 Resume Signaling


Some target applications need to be able to drive USB RESUME signaling on the bus in order to wake up the USB host. In some systems, the USB is set to the SUSPEND state when the USB host enters a low-power mode; some devices (for example, keyboards) will want the ability to wake up the host from the low-power mode. The usbTargLib driver provides the usbTargSignalResume( ) routine which allows a peripheral to drive RESUME signaling. This routine has no effect if the bus is not in the SUSPEND state; and there is no guarantee that a particular host will respond to USB RESUME signaling.

2.3 USB Target Controller Driver


This section describes the TCD interface and its requirements, information essential for creating a TCD for a target controller not already supported by Wind River.

112

2 USB Peripheral Stack

2.3.1 TCD Header File


All TCDs implement the interface as dened in usbTcd.h.
2

2.3.2 TCD Entry Point


Each TCD exports a single entry point, its execution entry point. This function is of the following form:
typedef STATUS (*USB_TCD_EXEC_FUNC) (pVOID pTrb);

2.3.3 Target Request Block (TRB)


All requests to the TCD are made by constructing Target Request Blocks (TRB) and passing them to the TCDs execution entry point for processing. TRBs begin with a common header that is followed by parameters unique to the function being executed. The format of the header is:
typedef struct trb_header { TCD_HANDLE handle; UINT16 function; UINT16 trbLength; } TRB_HEADER, *pTRB_HEADER;

/* I/O: caller's TCD client handle */ /* IN: TCD function code */ /* IN: Length of the total TRB */

For the TCD_FNC_ATTACH request (see also TCD_FNC_ATTACH, p.114), the handle eld is returned by the TCD to usbTargLib. For all other TRB requests, the handle eld is passed by usbTargLib to the TCD. The function eld in TRB_HEADER denes one of the following functions as the TCD function to be executed:
TCD_FNC_ATTACH TCD_FNC_ENABLE TCD_FNC_ADDRESS_SET TCD_FNC_ENDPOINT_RELEASE TCD_FNC_ENDPOINT_STATE_SET TCD_FNC_ERP_SUBMIT TCD_FNC_DETACH TCD_FNC_DISABLE TCD_FNC_ENDPOINT_ASSIGN TCD_FNC_SIGNAL_RESUME TCD_FNC_CURRENT_FRAME_GET TCD_FNC_ERP_CANCEL

A TCD must implement all of the above functions in order to perform properly. The trbLength eld is set by the caller to be the total length of the TRB, including the header and any additional parameters that follow. Each of the TCD functions

113

USB Developers Kit 1.1.2 Programmers Guide

listed above, including any associated TRB, is described in the remainder of this section.

TCD_FNC_ATTACH

This function is contained in the following TRB:


typedef struct trb_attach { TRB_HEADER header; /* TRB header */ pVOID tcdParam; /* IN: TCD-specific parameter */ USB_TCD_MNGMT_CALLBACK mngmtCallback; /* IN: caller's management callback */ pVOID mngmtCallbackParam; /* IN: param to mngmt callback */ UINT16 speed; /* OUT: target speed: USB_SPEED_xxxx */ UINT16 numEndpoints; /* OUT: number of endpoints supported */ pUSB_TARG_ENDPOINT_INFO pEndpoints; /* OUT: ptr to array of endpoints */ } TRB_ATTACH, *pTRB_ATTACH;

In response to a TCD_FNC_ATTACH request, a TCD initializes a single USB target controller.


NOTE: The TCD should not enable the controller until usbTargLib invokes the TCDs TCD_FNC_ENABLE request (see TCD_FNC_ENABLE, p.115).

The usbTargLib driver invokes the TCDs TCD_FNC_ATTACH function when usbTargTcdAttach( ) is called. Unlike other TCD functions, usbTargLib does not store an existing TCD_HANDLE in the TRB_HEADER.handle eld. Instead, upon successful completion of this routine, the TCD is expected to store a newly created TCD_HANDLE in the TRB_HEADER.handle eld so it can be retrieved by usbTargLib. The usbTargLib driver uses the newly created TCD_HANDLE to identify the indicated target controller in subsequent calls to the TCD. Typically, the TCD casts the newly created TCD_HANDLE as a pointer to an internal TCD data structure used to manage a specic target controller. The TCD-dened parameteroriginally passed to the usbTargTcdAttach( ) routineis passed to the TCD in the tcdParam eld. The usbTargLib driver makes no attempt to interpret the meaning of this parameter. The TCD can use the tcdParam eld as needed; for example, the Philips PDIUSBD12 TCD provided by Wind River casts this parameter to a pointer to a USB_TCD_PDIUSBD12_PARAMS structure (dened in usbTcdPdiusbd12EvalLib.h). The mngmtCallback parameter is a pointer to a routine in usbTargLib that should be called asynchronously by the TCD when it detects certain USB management

114

2 USB Peripheral Stack

events. Each time the TCD invokes the routine pointed to by usbTargLibs mngmtCallback parameter, the TCD passes the value specied by mngmtCallbackParam. Upon completion, the TCD returns three values: speed The speed of the USB peripheral hardware, dened as USB_SPEED_xxxx. numEndpoints The number of endpoints supported by the target controller. pEndpoints A pointer to an array of USB_TARG_ENDPOINT_INFO structures, as discussed in 2.2.5 TCD Endpoints, p.107.

TCD_FNC_DETACH

This function is contained in the following TRB:


typedef struct trb_detach { TRB_HEADER header; } TRB_DETACH, *pTRB_DETACH;

/* TRB header */

In response to a TCD_FNC_DETACH request, the TCD disables the target controller hardware and release all resources allocated on behalf of the controller.

TCD_FNC_ENABLE

This function is contained in the following TRB:


typedef struct trb_enable_disable { TRB_HEADER header; /* TRB header */ } TRB_ENABLE_DISABLE, *pTRB_ENABLE_DISABLE;

As described in 2.2.3 Enabling and Disabling TCDs, p.99, usbTargLib separates the attachment and enabling of a target controller into two steps. In response to the TCD_FNC_ENABLE request, the TCD enables the target controllers I/O drivers, making the peripheral visible on the USB (assuming it is currently connected to a USB).

115

USB Developers Kit 1.1.2 Programmers Guide

By default, the target controller must respond to bus address 0 immediately after TCD_FNC_ENABLE.

TCD_FNC_DISABLE

This function shares the TRB used by TCD_FNC_ENABLE (see TCD_FNC_ENABLE, p.115). In response to the TCD_FNC_DISABLE, the TCD disables the target controllers I/O drivers, in effect making the peripheral disappear from the USB to which it is attached. This function is generally requested only if the target application is in the process of shutting down.

TCD_FNC_ADDRESS_SET

This function is contained in the following TRB:


typedef struct trb_address_set { TRB_HEADER header; /* TRB header */ UINT16 deviceAddress; /* IN: new device address */ } TRB_ADDRESS_SET, *pTRB_ADDRESS_SET;

In response to the TCD_FNC_ADDRESS_SET function, the TCD sets the target controller to begin responding to a new USB device address as specied by deviceAddress. Once the peripheral is enumerated by the USB host, the USB host assigns it a new address. The usbTargLib driver interprets the USB SET_ADDRESS request sent by the USB host and invokes the TCD_FNC_ADDRESS_SET request to change the target controllers address.

TCD_FNC_ENDPOINT_ASSIGN

This function is contained in the following TRB:


typedef struct trb_endpoint_assign { TRB_HEADER header; /* UINT16 endpointId; /* UINT16 endpointNum; /* UINT16 configuration; /* UINT16 interface; /* UINT16 transferType; /*

TRB IN: IN: IN: IN: IN:

header */ TCD-assigned endpoint ID */ newly assigned endpoint num */ new configuration */ new interface */ new transfer type */

116

2 USB Peripheral Stack

UINT16 direction; /* IN: new direction */ } TRB_ENDPOINT_ASSIGN, *pTRB_ENDPOINT_ASSIGN;

In response to the TCD_FNC_ENDPOINT_ASSIGN request, the TCD enables the indicated hardware point as specied: endpointId The TCD-assigned ID for the desired endpoint. This parameter should match the endpoint ID of an endpoint described in the TCDs endpoint arraya pointer to which was originally returned during TCD_FNC_ATTACH processing. endpointNum The USB endpoint number which should be assigned to this endpoint. Some USB target controllers have exibility in assigning endpoint numbers to physical endpoints, others do not. The number passed in endpointNum corresponds to one of the bits set in the endpointNumMask eld of the endpoints corresponding USB_TARG_ENDPOINT_INFO structure. conguration interface The conguration and interface associated with this endpoint. The TCD does not need to interpret these values, but they should be stored by the TCD in the USB_TARG_ENDPOINT_INFO structure corresponding to the endpoint. transferType direction The type of transfers that are performed on this endpoint and the direction of those transfers, as USB_XFRTYPE_xxxx and USB_DIR_xxxx, respectively. The usbTargLib driver invokes this request when creating new pipes.

TCD_FNC_ENDPOINT_RELEASE

This function is contained in the following TRB:


typedef struct trb_endpoint_release { TRB_HEADER header; /* TRB header */ UINT16 endpointId; /* IN: TCD-assigned endpoint Id */ } TRB_ENDPOINT_RELEASE, *pTRB_ENDPOINT_RELEASE;

In response to the TCD_FNC_ENDPOINT_RELEASE request, the TCD disables the endpoint specied by endpointId.

117

USB Developers Kit 1.1.2 Programmers Guide

The usbTargLib driver invokes this request when destroying pipes.

TCD_FNC_SIGNAL_RESUME

This function is contained in the following TRB:


typedef struct trb_signal_resume { TRB_HEADER header; /* TRB header */ } TRB_SIGNAL_RESUME, *pTRB_SIGNAL_RESUME;

In response to the TCD_FNC_SIGNAL_RESUME request, the TCD directs the target controller to begin driving RESUME signaling on the USB. If the USB is not currently in the SUSPEND state, this request has no effect.

TCD_FNC_ENDPOINT_STATE_SET

This function is contained in the following TRB:


typedef struct trb_endpoint_state_set { TRB_HEADER header; /* TRB header */ UINT16 endpointId; /* IN: endpoint Id */ UINT16 state; /* IN: TCD_ENDPOINT_xxxx bitmask */ } TRB_ENDPOINT_STATE_SET, *pTRB_ENDPOINT_STATE_SET;

In response to the TCD_FNC_ENDPOINT_STATE_SET function, the TCD sets the state of the endpoint, specied by endpointId. The state parameter is a bit mask of the following values:
TCD_ENDPOINT_STALL

Set the STALL state for a specied endpoint.


TCD_ENDPOINT_UNSTALL

Clear the STALL state for a specied endpoint.


TCD_ENDPOINT_DATA0

Direct the TCD to reset the target controller to DATA0 for a specied endpoint.

118

2 USB Peripheral Stack

TCD_FNC_CURRENT_FRAME_GET

This function is contained in the following TRB:


typedef struct trb_current_frame_get { TRB_HEADER header; /* TRB header */ UINT16 frameNo; /* OUT: current frame number */ } TRB_CURRENT_FRAME_GET, *pTRB_CURRENT_FRAME_GET;

In response to the TCD_FNC_CURRENT_FRAME_GET request, the TCD returns the current USB frame number in frameNo.

TCD_FNC_ERP_SUBMIT

This function is contained in the following TRB:


typedef struct trb_erp_submit { TRB_HEADER header; /* TRB header */ pUSB_ERP pErp; /* IN: ptr to IRP */ } TRB_ERP_SUBMIT, *pTRB_ERP_SUBMIT;

In response to the TCD_FNC_ERP_SUBMIT request, the TCD queues the specied USB_ERP for subsequent transfer on one of the target controllers endpoints. USB_ERPs are described in 2.2.6 Data Transfer, p.109.

TCD_FNC_ERP_CANCEL

This function is contained in the following TRB:


typedef struct trb_erp_cancel { TRB_HEADER header; /* TRB header */ pUSB_ERP pErp; /* IN: ptr to IPR to be canceled */ } TRB_ERP_CANCEL, *pTRB_ERP_CANCEL;

In response to the TCD_FNC_ERP_CANCEL request, the TCD attempts to cancel the specied USB_ERP. If the USB_ERP can be canceled, the TCD must set the ERPs result to S_usbTcdLib_ERP_CANCELED.

119

USB Developers Kit 1.1.2 Programmers Guide

2.3.4 TCD Management Events


The management callback to the TCD provided by usbTargLib as part of the TCD_FNC_ATTACH request gives the TCD a way to notify usbTargLib when the TCD detects asynchronous management events. The format of the callback is:
typedef VOID (*USB_TCD_MNGMT_CALLBACK) ( pVOID mngmtCallbackParam, TCD_HANDLE handle, UINT16 mngmtCode );

/* caller-defined param */ /* channel */ /* management code */

The mngmtCallbackParam parameter passed to the callback is the TRB.mngmtCallbackParam value originally passed to the TCD during the TCD_FNC_ATTACH request. The handle parameter is the TCD-assigned TCD_HANDLE for the corresponding target controller. The values for mngmtCode are the same as those introduced in the description of the mngmtFunc( ) callback in mngmtFunc( ) Callback, p.101. The usbTargLib driver processes some of these events internally. Generally, usbTargLib passes all management events up to the target application through the target applications mngmtFunc( ) callback.

2.3.5 TCD Error Reporting Conventions


A number of standard TCD error codes are dened in usbTcd.h. You are encouraged to use the existing TCD error codes when creating new TCDs. These error codes are returned both in response to TCD function requests through the TCDs execution entry point, as well as in the result eld of each USB_ERP processed by the TCD. To conform to Wind River conventions, the TCD should also set the system errno whenever returning an error. TCDs return the standard VxWorks constant, OK, when a function or ERP completes successfully. TCD error codes are as follows:
S_usbTcdLib_BAD_PARAM S_usbTcdLib_OUT_OF_MEMORY S_usbTcdLib_NOT_IMPLEMENTED S_usbTcdLib_NOT_INITIALIZED S_usbTcdLib_HW_NOT_READY S_usbTcdLib_ERP_CANCELED S_usbTcdLib_SHUTDOWN S_usbTcdLib_PID_MISMATCH S_usbTcdLib_NEW_SETUP_PACKET S_usbTcdLib_BAD_HANDLE S_usbTcdLib_OUT_OF_RESOURCES S_usbTcdLib_GENERAL_FAULT S_usbTcdLib_INT_HOOK_FAILED S_usbTcdLib_NOT_SUPPORTED S_usbTcdLib_CANNOT_CANCEL S_usbTcdLib_DATA_TOGGLE_FAULT S_usbTcdLib_COMM_FAULT

120

2 USB Peripheral Stack

In particular, TCDs must store the error code S_usbTcdLib_ERP_CANCELED in the result eld of USB_ERPs that have been canceled for any reason. Higher layers rely on this error code to recognize situations in which ERPs should not be retried. For their own convenience, TCDs can temporarily store other values in the USB_ERP result eld while processing ERPs (such as a value indicating that the ERP is pending). However, before invoking an ERPs completion callback routine, the TCD is required to store either the constant OK or one of the above error codes in the USB_ERP result eld.

2.4 Installing the USB Peripheral Stack


See the Tornado Getting Started Guide for general instructions on how to install the USB Kit, and all other Wind River products. The peripheral stack supplement to the USB Kit implements an example peripheral stack based on the Philips PDIUSBD12 USB controller chip. Included in the supplement are the rmware templates used to implement a rudimentary keyboard, a rudimentary printer, and a device called a PDIUSBD12 rmware emulator. This latter template was developed to utilize the Windows application included with the Philips PDIUSBD12 evaluation kit. The other two modules are designed as skeletons for creating either a printer or keyboard device. Together, the three modules demonstrate how three types of USB transfers (control, bulk, and interrupt) should be implemented. The PDIUSBD12 rmware emulator is tested with a Windows 98 USB host using the application included with the Philips evaluation kit. The printer and keyboard emulator are tested on a VxWorks USB host using the test application usbTool. Install the USB CD-ROM on top of your current Tornado installation. If you already have the USB Developers Kit for the host installed, you only have to install the peripheral stack supplement: USB Peripheral Library Source

If you are installing both the host stack source and libraries, as well as the peripheral stack supplement, you must install the above module and the following three parts: USB Library Source USB Support Library: i86 USB Support Library: ppc

121

USB Developers Kit 1.1.2 Programmers Guide

For additional information about installation of the USB host stack, see 1. USB Host Stack and the USB Developers Kit Release Notes. The remainder of this section contains information pertaining to installation of the peripheral stack only. Source les related to the peripheral stack are created in the Tornado tree as follows. The header les for both host and peripheral stacks are installed: target/h/usb Header les pertaining to the USBD and the OS abstraction module. target/h/drv/usb Header les pertaining to the device drivers (printer, mouse, keyboard) and host controller drivers (OHCI, UHCI). target/h/usb/target Header les pertaining to the target stack target/h/drv/usb/target Header les pertaining to the peripheral stack rmware templates (printer, keyboard, Philips PDIUSBD12 evaluation kit) and target controller drivers (Philips PDIUSBD12 evaluation kit). target/src/usb Source les pertaining to the OS abstraction module. target/src/usb/tools Source les pertaining to usbTool, a test utility that exercises the USB and supported devices. target/src/usb/target Source les pertaining to the target stack. target/src/drv/usb/target Source les pertaining to the peripheral stack rmware templates (printer, keyboard, Philips PDIUSBD12 evaluation kit) and target controller drivers (Philips PDIUSBD12 evaluation kit). target/cong/comps/src Source les (conglettes) for all Tornado components associated with the peripheral stack and requiring initialization, that is, stubs for BSP-specic PCI routines, and usbTool.

122

2 USB Peripheral Stack

target/cong/bsp The BSP-specic component description les (.cdf) are contained in the following directory: pcPentium

target/cong/comps/vxworks The component description le (.cdf) is contained here. For more information about components, see the Tornado BSP Developers Kit for VxWorks Users Guide, Tornado 2.0: Components. Because this is a source code product, object les are not created during installation. The CD-ROM image has no binaries on it. To be able to use the peripheral stack components mentioned above to create a bootable VxWorks image, you must build the .o les from the command line, as follows:
make CPU=PENTIUM release

The following directories must be built: tornado/target/src/usb/target tornado/target/src/usb/tools tornado/target/src/drv/usb/target tornado/target/src/usb The makeles put object modules in the following directories: target/lib/obj80386gnuvx target/lib/obj80486gnuvx target/lib/objPENTIUMgnuvx The object les are also linked into their corresponding archive (.a) les in the target/lib directory.

123

USB Developers Kit 1.1.2 Programmers Guide

2.5 Running the USB Peripheral Stack


After installing the USB peripheral stack, you can run it as a peripheral stack alone or in conjunction with the host stack. Regardless of whether you are running the peripheral stack independently or with the host stack, there are two ways to use the Tornado project facility to congure and download projects:
I

Create a downloadable VxWorks image with the USB peripheral stack built in. Create a downloadable application module for the USB peripheral stack that runs on top of an already loaded VxWorks image.

2.5.1 Creating a Downloadable VxWorks Image Including USB


From the Tornado project facility, start a downloadable VxWorks project based on your BSP. The peripheral stack supplement software provides components that support USB peripheral device functionalities. For general instructions on using the project facility and creating projects, see the Tornado Users Guide: Projects. The following steps congure a basic USB peripheral stack setup:
Step 1: Congure the Peripheral Stack

Select the USB Peripheral Stack component from the project facility component hierarchy to provide support for the Philips PDIUSBD12 target controller.
Step 2: Congure usbTool

Select the usbTool component to include the usbTool module, which allows you to exercise the peripheral stack and its features, as well as the USBs host functions. For information about using usbTool, see 2.6 Working with usbTool, p.125.
Step 3: Congure Peripheral Devices

Select any of the following peripheral stack device components to include their corresponding rmware modules. These components require the peripheral stack to be present on the image:
D12 Emulator Keyboard Emulator Printer Emulator

124

2 USB Peripheral Stack

NOTE: The keyboard rmware emulator requires two hosts for testing: a VxWorks host running the emulator (with or without the USB host stack congured) and a VxWorks/USB host. Whereas testing a printer can occur on a single machine running both a VxWorks/USB host stack and the USB peripheral stack (congured as a printer.)

2.5.2 Creating a Downloadable USB Application


To create a downloadable USB application module, follow the standard procedure described in the Tornado Users Guide: Projects. See that document for details.

2.6 Working with usbTool


The peripheral stack supplement includes a utility called usbTool, which you can use to exercise the modules comprising the USB peripheral stack. For example, if you are implementing a different rmware module, you can use usbTool to exercise and debug your code. The usbTool utility provides a code skeleton which you can customize to suit your test needs. There are two methods for running usbTool:
I

from the shell, on both UNIX and Windows hosts from the debugger, Windows only

For more information about how to run usbTool, see 1. USB Host Stack. This section focuses on using usbTool to exercise the USB peripheral stack.

The usbTool Execution Sequence NOTE: To test the keyboard and printer, you must use Wind Rivers

implementation of a USB host with usbTool.

125

USB Developers Kit 1.1.2 Programmers Guide

Use the usbTool utility to initialize and test peripheral stack devices: 1. To initialize the USB peripheral stack as a specic type of device, at the usbTool prompt, enter the targInit command followed by the emulator type (prn, kbd, D12). Depending on the type of device you emulate, you must also include the appropriate drivereither a Wind River USB host stack driver for the printer and keyboard, or a Windows 98 driver for the Philips PDIUSBD12 emulator. For more information about using printers and keyboards, see 1. USB Host Stack. For information on using the Philips PDIUSBD12 emulator, see the PDIUSBD12 Evaluation Board (PC Kit) Users Manual, Rev. 2.1. To test the printer and keyboard, use the usbTool commands in Table 2-1. To test the PDIUSBD12 emulator, you must use a Windows 98 host and the application included with the Philips PDIUSBD12 evaluation kit. Table 2-1 lists the usbTool commands available when their associated device components are included in your VxWorks image:
Table 2-1

2.

3.

usbTool Commands
Device Type Command Description

Keyboard emulator

kbdReport

Generate a keyboard report to send to the host. This command simulates a keypress on an actual keyboard. Typically the host uses the usbTool command print4k to send 4KB of arbitrary data to the printer. This command displays those bytes that have been sent to the printer.

Printer emulator

prnDump

NOTE: Selecting any of the peripheral device components (keyboard, printer, D12) includes the peripheral device test commands into usbTool. If the components are not included, the commands are not available. NOTE: Command names do not have to be fully entered to be executed. For

example, usbInit can be entered as usbi.

126

2 USB Peripheral Stack

2.7 BSP-Specic Issues


The following run-time issue has been encountered with the pcPentium BSP.
pcPentium 2

When using a serial connection to your target, the PC_CONSOLE component must be removed from your image. (Figure 2-3 shows the location of the PC_CONSOLE component.)
Figure 2-3

PC_CONSOLE Component Location

127

Potrebbero piacerti anche