Window CE 6.0 USB Driver implemention

来源:互联网 发布:科罗拉多矿业学院 知乎 编辑:程序博客网 时间:2024/05/01 11:52

OverView

SiRF USB OTG Driver Architecture:    

USB OTG Driver is a buid-in driver,which is loaded by device manager during system booting up. USB OTG driver is responsible for loading USB Host Controller Driver and USB Function Controller Driver.

image

USB Host Driver Architecture:

image

USB Function Driver Architecture:

image 

USB Host Driver:

Interfaces of each layer:

USB Host Client Driver—>USB Host Client Common Layer(Client driver should link this lib)--->USB Host Drivr (USBD)—>USB HCI layer.

1. USB Client Driver should implement below three functions for USBD call.

USBDeviceAttach

This function is a USB device attach routine. USB host client drivers must implement this function.

USBInstallDriver

This function installs a USB client driver. USB host client drivers must implement this function.

USBUnInstallDriver

This function uninstalls a USB client driver. USB host client drivers must implement this function.

 

2. Interface export by "USB Host Client Common Layer” to USB client driver. To use these functions please include Usbclient.h file.

Programming element

Description

AbortTransfer

This function aborts an active transfer.

AcquireRemoveLock

This function acquires a remove lock. It attempts to call InterlockedIncrement on Lock.

ClearOrSetFeature

This function sends a CLEAR_FEATURE or SET_FEATURE request to a USB device.

CloseTransferHandle

This function closes a USB transfer handle.

DefaultTransferComplete

This function signals the event passed in when USB signals that a transfer has completed.

GetSetKeyValues

This function gets or sets values under the HKEY_LOCAL_MACHINE/KeyName registry key.

GetStatus

This function sends a GET_STATUS request to a USB device.

GetTransferStatus

This function gets the status of an active transfer.

InitializeRemoveLock

This function creates a remove lock.

IssueBulkTransfer

This function initiates a bulk transfer to a USB device on the specified endpoint.

IssueInterruptTransfer

This function initiates an interrupt transfer with a USB device on the specified endpoint.

IssueVendorTransfer

This function sends a vendor-specific control transfer to a USB device.

ReleaseRemoveLock

This function releases the removal lock, decrements the lock count with InterlockedDecrement, and notifies the system that the device is safe to be removed with SetEvent.

ReleaseRemoveLockAndWait

This function closes the lock event handle so the same lock cannot be reentered. This is the final function called on the remove lock.

ResetBulkEndpoint

This function resets the pipe, and then checks the endpoint status on the device. If the endpoint is halted, this function sends a clear feature request through ClearOrSetFeature.

ResetDefaultEndpoint

This function attempts to reset the default endpoint zero.

ResetPipe

This function resets an open USB pipe.

 

3. Interfaces export to upper layer by USBD layer. These interfaces definition at Usbd.cpp as following.

static USB_FUNCS gc_UsbFuncs =
{
    sizeof(USB_FUNCS),      //DWORD                   dwCount;

    &GetUSBDVersion,                // LPGET_USBD_VERSION
    &OpenClientRegistryKey,         // LPOPEN_CLIENT_REGISTRY_KEY
    &RegisterNotificationRoutine,   // LPREGISTER_NOTIFICATION_ROUTINE
    &UnRegisterNotificationRoutine, // LPUN_REGISTER_NOTIFICATION_ROUTINE
    &LoadGenericInterfaceDriver,    // LPLOAD_GENERIC_INTERFACE_DRIVER
    &TranslateStringDescr,          // LPTRANSLATE_STRING_DESCR
    &FindInterface,                 // LPFIND_INTERFACE
    &GetFrameNumber,                // LPGET_FRAME_NUMBER
    &GetFrameLength,                // LPGET_FRAME_LENGTH
    &TakeFrameLengthControl,        // LPTAKE_FRAME_LENGTH_CONTROL
    &ReleaseFrameLengthControl,     // LPRELEASE_FRAME_LENGTH_CONTROL
    &SetFrameLength,                // LPSET_FRAME_LENGTH
    &GetDeviceInfo,                 // LPGET_DEVICE_INFO
    &IssueVendorTransfer,           // LPISSUE_VENDOR_TRANSFER
    &GetInterface,                  // LPGET_INTERFACE
    &SetInterface,                  // LPSET_INTERFACE
    &GetDescriptor,                 // LPGET_DESCRIPTOR
    &SetDescriptor,                 // LPSET_DESCRIPTOR
    &SetFeature,                    // LPSET_FEATURE
    &ClearFeature,                  // LPCLEAR_FEATURE
    &GetStatus,                     // LPGET_STATUS
    &SyncFrame,                     // LPSYNC_FRAME
    &OpenPipe,                      // LPOPEN_PIPE
    &AbortPipeTransfers,            // LPABORT_PIPE_TRANSFERS
    &ResetPipe,                     // LPRESET_PIPE
    &ClosePipe,                     // LPCLOSE_PIPE
    &IsPipeHalted,                  // LPIS_PIPE_HALTED
    &IssueControlTransfer,          // LPISSUE_CONTROL_TRANSFER
    &IssueBulkTransfer,             // LPISSUE_BULK_TRANSFER
    &IssueInterruptTransfer,        // LPISSUE_INTERRUPT_TRANSFER
    &IssueIsochTransfer,            // LPISSUE_ISOCH_TRANSFER
    &IsTransferComplete,            // LPIS_TRANSFER_COMPLETE
    &GetTransferStatus,             // LPGET_TRANSFER_STATUS
    &GetIsochResults,               // LPGET_ISOCH_RESULTS
    &AbortTransfer,                 // LPABORT_TRANSFER
    &CloseTransfer,                 // LPCLOSE_TRANSFER

    // These functions were added with USBDI version 1.1
    &ResetDefaultPipe,              // LPRESET_DEFAULT_PIPE
    &IsDefaultPipeHalted,            // LPIS_DEFAULT_PIPE_HALTED
    // This Function were added with USBDI version 1.2
    &DisableDevice,                 //LPDISABLE_DEVICE
    &SuspendDevice,                 //LPSUSPEND_DEVICE
    &ResumeDevice,                  //LPRESUME_DEVICE
    // This Function were added with USBDI version 1.3  
    &GetClientRegistryPath          // LPGET_CLIENT_REGISTRY_PATH
};

Programming element

Description

GetTransferError

This function returns an error value associated with a USB transfer.

LPABORT_PIPE_TRANSFERS

This function aborts all transfers on an open USB pipe.

LPABORT_TRANSFER

This function aborts an active transfer.

LPCLEAR_FEATURE

This function sends a CLEAR_FEATURE request to a USB device.

LPCLOSE_PIPE

This function closes an open pipe handle.

LPCLOSE_TRANSFER

This function closes a USB transfer handle.

LPDEVICE_NOTIFY_ROUTINE

This function receives device notifications. Client drivers register this function with the USBD to recieve device notifications.

LPDISABLE_DEVICE

This function disables an attached device by disabling the port on the USB hub. After the attached device is disabled, it can be optionally re-enabled by the USB host controller.

LPFIND_INTERFACE

This function searches for a specific interface on a USB device.

LPGET_DESCRIPTOR

This function sends a GET_DESCRIPTOR request to a USB device.

LPGET_DEVICE_INFO

This function gets a pointer to a device information structure.

LPGET_FRAME_LENGTH

This function gets a current USB frame length.

LPGET_FRAME_NUMBER

This function gets a current USB frame number.

LPGET_INTERFACE

This function sends a request to a USB device for information about alternate device settings.

LPGET_ISOCH_RESULTS

This function gets the status of an active isochronous transfer.

LPGET_STATUS

This function sends a GET_STATUS request to a USB device.

LPGET_TRANSFER_STATUS

This function gets the status of an active transfer.

LPGET_USBD_VERSION

This function retrieves the version number of the current USB driver interface.

LPIS_DEFAULT_PIPE_HALTED

This function is deprecated. It always returns FALSE. The default pipe never halts.

LPIS_PIPE_HALTED

This function checks if a USB pipe is in a halted state.

LPIS_TRANSFER_COMPLETE

This function checks whether a transfer has completed.

LPISSUE_BULK_TRANSFER

This function initiates a bulk transfer to a USB device on the specified endpoint.

LPISSUE_CONTROL_TRANSFER

This function initiates a control transfer with a USB device on the specified endpoint.

LPISSUE_INTERRUPT_TRANSFER

This function initiates an interrupt transfer with a USB device on the specified endpoint.

LPISSUE_ISOCH_TRANSFER

This function initiates an isochronous transfer with a USB device.

LPISSUE_VENDOR_TRANSFER

This function sends a vendor-specific control transfer to a USB device.

LPLOAD_GENERIC_INTERFACE_DRIVER

This function load drivers for other interfaces on a device. USB drivers call this function.

LPOPEN_CLIENT_REGISTRY_KEY

This function opens a registry key associated with a USB client driver.

LPOPEN_PIPE

This function opens a pipe for communication with a USB device.

LPREGISTER_CLIENT_DRIVER_ID

This function registers a unique string to identify a USB client driver.

LPREGISTER_CLIENT_SETTINGS

This function registers settings for loading a USB client driver.

LPREGISTER_NOTIFICATION_ROUTINE

This function registers a callback function for device notifications.

LPRELEASE_FRAME_LENGTH_CONTROL

This function releases exclusive access to USB frame-length control.

LPRESET_DEFAULT_PIPE

This function resets the default pipe to a USB device.

LPRESET_PIPE

This function resets an open USB pipe.

LPRESUME_DEVICE

This function resumes the attached device by resuming the port on the USB hub.

LPSET_DESCRIPTOR

This function sends a SET_DESCRIPTOR request to a USB device.

LPSET_FEATURE

This function sends a SET_FEATURE request to a USB device.

LPSET_FRAME_LENGTH

This function changes the USB frame length.

LPSET_INTERFACE

This function sends a SET_INTERFACE request to a USB device to change the device's settings.

LPSUSPEND_DEVICE

This function suspends an attached device by suspending the port on the USB hub. After being suspended, the device can be resumed by the LPRESUME_DEVICE function or by a global resume sent from the USB bus.

LPSYNC_FRAME

This function sends a SYNCH_FRAME request to a USB device.

LPTAKE_FRAME_LENGTH_CONTROL

This function registers for exclusive access to control the USB frame length.

LPTRANSFER_NOTIFY_ROUTINE

This function executes when a transfer completes.

LPTRANSLATE_STRING_DESCR

This function translates a USB string descriptor into a null-terminated string.

LPUN_REGISTER_CLIENT_DRIVER_ID

This function unregisters a client driver's unique driver identifier.

LPUN_REGISTER_CLIENT_SETTINGS

This function deregisters USB device driver settings.

LPUN_REGISTER_NOTIFICATION_ROUTINE

This function removes a device notification callback function.

      

4. Interfaces export by USBD layer to USB HCI layer

Programming element

Description

HcdAttachThis function will be called when USB HCI driver loading.It uses to pass USB HCI interface functions and USB HCI object pointer to USBD.HcdDetachThis function will be called when USB HCI driver unloading. It uses to tell USBD layer to release resource which allocated in HcdAttach.HcdDeviceAttachedThis function will be called  by USB HCI layer when detect a device insertion. It uses to load a client driver for the inserted device.HcdDeviceDetachedThis function will be called by USB HCI layer when a device removed. It uses to unload a client driver for the removed device.

 

5. Interfaces export by USB HCI layer to USBD layer.

extern HCD_FUNCS gc_HcdFuncs =
{
    sizeof(HCD_FUNCS),      //DWORD                   dwCount;

    &HcdGetFrameNumber,     //LPHCD_GET_FRAME_NUMBER      lpGetFrameNumber;
    &HcdGetFrameLength,     //LPHCD_GET_FRAME_LENGTH      lpGetFrameLength;
    &HcdSetFrameLength,     //LPHCD_SET_FRAME_LENGTH      lpSetFrameLength;
    &HcdStopAdjustingFrame, //LPHCD_STOP_ADJUSTING_FRAME  lpStopAdjustingFrame;
    &HcdOpenPipe,           //LPHCD_OPEN_PIPE             lpOpenPipe;
    &HcdClosePipe,          //LPHCD_CLOSE_PIPE            lpClosePipe;
    &HcdResetPipe,          //LPHCD_RESET_PIPE            lpResetPipe;
    &HcdIsPipeHalted,       //LPHCD_IS_PIPE_HALTED        lpIsPipeHalted;
    &HcdIssueTransfer,      //LPHCD_ISSUE_TRANSFER        lpIssueTransfer;
    &HcdAbortTransfer,      //LPHCD_ABORT_TRANSFER        lpAbortTransfer;
    &HcdDisableDevice,      //LPHCD_DISABLE_DEVICE        lpDisableDevice;
    &HcdSuspendResume       //LPHCD_SUSPEND_RESUME        lpSuspendResume;
};

USB HCI Driver Analyse:

USB EHCI Driver Archetecture:

In our system we use a similar enhanced host controller interface (EHCI) controller.So we developed our USB HCI driver based on EHCI driver.

The enhanced host controller interface (EHCI) driver simultaneously supports USB 2.0 and USB 1.1 protocols. The EHCI driver supports existing class drivers. The USB 2.0 common code uses the USB 1.1 common code as a base, with necessary changes to support USB 2.0. The EHCI driver attaches the same USB driver interface as the open host controller interface (OHCI) and the universal host controller interface (UHCI) do. 

The USB 2.0 implementation includes some code that is unique to the EHCI driver and some code that is common for all USB 2.0 drivers. It also includes code that is specific to the USB host controller.Microsoft has provided the EHCI driver implement,the source code locate at %_PUBLICROOT%/Common/OAK/Drivers/USB/HCD/USB20 directory.They are divided into three components as below.

 

 

Component

Directory

USB 2.0 Common Code Implemented by the EHCI Driver

USB20COM

EHCI-specific Code

EHCI

USB Host Controller-specific Code

EHCIPDD

 

USB 2.0 Common Code:

The USB 2.0 common code implements the hub, the interface to the USB driver interface, device attachment and removal, physical memory management with CPhysMem, and bandwidth allocation. USB 1.1 is a base for the USB 2.0 common code, except for extended hub support for USB 2.0 devices and bandwidth allocation.

Except for the root hub, the USB device module operates the hub and device with USB transfers. That means the USB device module(USBD) uses the CPipeAbs abstract class to send and receive transfers with pipes. For the root hub, the USB device uses the root hub abstract function in the host controller driver,do not need pips. The USB device module (USBD) detects device attachment and removal, assigns USB addresses, and gets device descriptors.

There are serval components in USB 2.0 common code,show as below table.

Component

Description

USB device

This component allows other host software to communicate with devices, hubs, and other USB devices.

This component is implemented by CDevice, CFunction, CHub, CRootHub, and CExternalHub.

CDevice connects to CFunction. The CDevice abstract class is hierarchically above CFunction and CHub, which are parallel to each other. CHub is an abstract class.

CHub is hierarchically above CRootHub and CExternalHub, which are parallel to each other.

 

 

 

 

Physical memory management

This component allocates, tracks, and frees memory.This component is implemented by CPhysMem.

HCD interface class

This component abstracts the hardware details of the host controller.This component is implemented by CHcd.

CHcd, is the interface between the USB device module and the USB driver interface. The CHcd class carries out USB driver interface requests. CHcd contains the reference pointer for the root hub. It propagates USB driver interface requests to the root hub. The hub uses recursion to locate the device that initialized the USB driver interface request, and then propagates the USBD request to the device.

 

 

USB 2.0 library

This component handles scheduling of USB transactions.This component is implemented in USB2lib.cpp.USB2lib.cpp contains bandwidth information that relates to the bus. It also contains transaction translation information and the related bandwidth information.

 

EHCI-specific Code:

EHCI-specific code and USB 2.0 common code interface show as below table.

USB 2.0 common code requires all host controller specific code to implement the virtual functions exposed by the HCD class.

Component

Description and hierarchy

HCD

HCD implements the host controller driver interface. This abstract class passes requests to other objects.

Above CHW and connects to CHW.

 

 

CHW

CHW implements all of the HCD virtual functions and interfaces with the hardware. There are two reference pointers in hardware that point to the structure to manage.

Below HCD and connects to HCD.

Above CEhcd and connects to CEhcd.

 

 

USB2lib

USB2lib handles scheduling of USB transactions.

Parallel to CHW and connects to CEhcd.

 

CEhcd

CEhcd contains USB2lib code that the pipe class utilizes.

Below CHW and connects to CHW.

Below USB2lib and connects to USB2lib.

 

 

 

EHCI-specific pipe clases:

The relationship of below classes shows like following picture.

image

Class

Description and hierarchy

CPipeAbs

The CPipeAbs abstract class connects to the CPipe abstract class.

CPipeAbs is at the top of the class hierarchy.

 

CPipe

The cPipe abstract class implements the common code between the queue pipe and the isochronous pipe. This class includes a split mask and a complete mask for a full speed endpoint. It also holds the transaction translation address and the speed of the pipe.

The CPipe abstract class is below and connects to the CPipeAbs abstract class.

The CPipe abstract class is above and connects to the CQueuedPipe abstract class.

The CPipe abstract class is above and connects to the CIsochronousPipe class.

 

 

 

 

CQueuedPipe

The CQueuedPipe abstract class is used for queue-type pipes, control, bulk, and interrupt common code. It holds the queue header class instance it used. It also holds the currently processing transfer instance and the outstanding queued transfer instance. A transfer class such as CIoschTransfer and CQTransfer manage the transfer.

CQueuedPipe handles queued transfers to the queue header. It also handles transfers to the queue header that are not queued. It also controls the state of the queue header through an instance of CQH, the queue header class.

CQueuedPipe abstract class is below and connects to the CPipe abstract class.

The CQueuedPipe abstract class is above and connects to the CControlPipe, CInterruptPipe, and CBulkPipe classes.

 

 

 

 

 

CIsochronousPipe

The CIsochronousPipe class is below and connects to the CPipe abstract class.

CIsochronousPipe cannot use CQueuePipe because CIsochronousPipe is not a queue based transfer. Instead, CQueuePipe extends CPipe. CQueuePipe has multiple transfers queued into the periodic schedule table to support the continuation of a transfer. CIsochronousPipe references only the header of those transfer lists. Those transfers might all have transfer descriptors inserted into the periodic schedule list table.

 

CControlPipe

The CControlPipe abstract class extends CQueuePipe for control pipes. It sets up the queue header according to the control type and it queues this queue header into the hardware asynchronous queue header list. It provides parameters and the ability to change the packet size at least once for this queue header.

The CControlPipe class is below and connects to the CQueuedPipe abstract class.

 

 

CInterruptPipe

The CInterruptPipe abstract class calls AllocateBusTime in the USB20 library for this endpoint and uses GetSMASK and GetCMASK with the bus bandwidth information as parameters to get the split and complete mask. This class processes high-speed and full-speed interrupt endpoints. It also queues this queue header into the periodic schedule list table.

CInterruptPipe extends CQueuePipe for interrupt pipes. It sets up the queue header according to the interrupt type. It also sets up the split and complete mask for its queue header.

The CInterruptPipe class is below and connects to the CQueuedPipe abstract class.

 

 

 

CBulkPipe

The CBulkPipe abstract class extends CQueuePipe for bulk pipes. It sets up the queue header according to the bulk type, and it queues this queue header into the hardware asynchronous queue header list. It also provides parameter checking functions for IssueTransfer.

The CBulkPipe class is below and connects to the CQueuedPipe abstract class.

 

 

EHCI-specific transfer clases

The relationship of below classes show like following picture.

image

Class

Description and hierarchy

CTransfer

The CTransfer abstract class allocates memory for the client, initializes transfer buffers for the client, and performs a callback when it is finished.

CTransfer is above CQTransfer and CIsochTransfer and connects to both.

 

 

CQTransfer

The CQTransfer abstract class implements the transfer descriptor list initialization with AddTransfer. It also implements checking for completion and transfer descriptor completion actions, and implements aborting actions if a transfer must terminate.

CQueuedPipe uses CQTransfer for queued pipe endpoints, control transfers, and bulk interrupt transfers. CQTransfer manages the queue transfer descriptor list and references it with the m_pCQTDList member.

CQTransfer is below and connects to CTransfer. CQTransfer is parallel to CIsochTransfer.

 

 

 

CIsochTransfer

The CIsochTransfer abstract class is the common interface between CITransfer and CSITransfer. With few exceptions, the CIsochronous class interfaces only with CIsochTransfer. CITransfer handles high-speed USB isochronous transfers. CSITransfer, which handles split isochronous transfers, handles full-speed isochronous transfers. CITransfer creates the isochronous transfer descriptors and CSITransfer creates the split isochronous transfer descriptors.

CIsochTransfer is below and connects to CTransfer. CIsochTransfer is above CITransfer and CSITransfer. CIsochTransfer is parallel to CQTransfer.

 

 

CITransfer

The CITransfer abstract class manages isochronous transfers.

The CITransfer abstract class is below and connects to CIsochTransfer. CITransfer is parallel to CSITransfer.

 

 

CSITransfer

The CSITransfer abstract class manages high-speed isochronous transfers.

CSITransfer abstract class is below and connects to CIsochTransfer. CSITransfer is parallel to CITransfer.

 

 

 

Partable Process Flow:

1. USB EHCI driver load process:

OTG_Init—>Call HCD_Init with host setting parameters,which get from registry.

Below figure shows the function call process.

image

 

2. USB Device Attachment/Removal process

RootHub HubStatusChange monitor thread monitor USB port change interrupt and load client driver. HubStatusChange monitor thread—>(WaitForPortStatusChange belongs to roothub class—>WaitForPortStatusChange belongs CHW class)—>Check port status and do relevant process,such as load client driver (call AttachDevice) when USB device inserted. The port change event trigger by HostInterruptHandler belongs CHW class,HostInterruptHandler trigger by physical USB controller interrupt.

AttachDevice process flow:(Note USB device dettach operation just is a reversal process.)

image

EnterOperationalState function in CFunction class:

image

原创粉丝点击