?? usbcbiufidevlib.c
字號:
/* usbCbiUfiDevLib.c - USB CBI Mass Storage class driver for UFI sub-class *//* Copyright 2000-2002 Wind River Systems, Inc. *//*modification history--------------------01r,26oct04,ami Debug Message Changes01q,21oct04,pdg IRP timeout handling01p,15oct04,ami Apigen Changes01o,07oct04,ami SPR #91732 Fix01n,07oct04,mta SPR 94016:If device unplugged during a transfer, a corruption (pagefault) may appear01m,07oct04,mta Merge from Integration branch01l,06oct04,mta SPR 97415:when addressing an endpoint, we omit the direction bit01k,06oct04,ami SPR #94684 Fix01j,26feb04,cfc Merge fixes for SPR 93986 and 94016 from adh01i,19sep03,cfc Fix for creating USB Interrupt Pipe w/USB2 Host Stack01h,30apr02,wef fix little endian swap problem in usbCbiUfiPhysDevCreate01g,05mar02,wef fix bug - sizeof a macro01f,19nov01,dee fix continuation line syntax error01e,06nov01,wef Remove automatic buffer creations and repalce with OSS_xALLOC remove more warnings, fix condition where no disk is in drive - SPR #69753.01d,08aug01,dat Removing warnings01c,02sep00,bri added support for multiple devices.01b,04aug00,bri updated as per review.01a,26jun00,bri written.*//*DESCRIPTIONThis module implements the USB Mass Storage class driver for the vxWorks operating system. This module presents an interface which is a superset of the vxWorks Block Device driver model. The driver implements external APIs which would be expected of a standard block device driver. This class driver restricts to Mass Storage class devices with UFI subclass,that follow CBI (Control/Bulk/Interrupt) transport. For CBI devices transport of command, data and status occurs via control, bulk and interrupt endpoints respectively. Interrupt endpoint is used to signal command completion.The class driver is a client of the Universal Serial Bus Driver (USBD). Allinteraction with the USB buses and devices is handled through the USBD.INITIALISATIONThe driver initialisation routine usbCbiUfiDevInit() must be invoked first prior to any other driver routines. It is assumed that USBD is already initialised and attached to atleast one USB Host Controller. usbCbiUfiDevInit() registers the class driver as a client module with USBD. It also registers a callback routine to get notified whenever a USB MSC/UFI/CBI device is attached or removed from the system. The callback routinecreates a USB_CBI_UFI_DEV structure to represent the USB device attached. Italso sets device configuration, interface settings and creates pipes for BULK_IN, BULK_OUT and INTERRUPT transfers.DATA FLOWFor every USB/CBI/UFI device detected, the device configuration is set to theconfiguration that follows the CBI/UFI command set. Pipes are created for bulkin, bulk out and interrupt endpoints. To initiate transactions, ADSC class specific request is used to send a command block on the control endpoint. Command blocks are formed as per the UFI command specifications. If the command requires transport of data to/from the device, it is done via bulk-out/bulk-in pipes using IRPs. This is followed by status transport via interrupt endpoint.OTHER FUNCTIONSNumber of USB CBI_UFI devices supported by this driver is not fixed. UFI devices may be added or removed from the USB system at any point of time. The user of this client driver must be aware of the device attachment and removal.To facilitate this, an user-specific callback routine may be registered, usingusbCbiUfiDynamicAttachRegister() routine. The USBD_NODE_ID assigned to the device being attached or removed, is passed on to the user callback routine. This unique ID may be used to create a block device using usbCbiUfiBlkDevCreate() and further launch file system.NOTE : The user callback routine is invoked from the USBD client task created for this class driver. The callback routine should not invoke any class driverfunction, which will further submit IRPs. For example, usbCbiUfiBlkDevCreate() should not be invoked from the user's callback. Typically, the user may create a task, as a client of UFI driver, and invokethe driver routines from the task's context. The user callback routine maybe used to notify device attachment and removal to the task. INCLUDE FILES: usbCbiUfiDevLib.h, blkIo.hSEE ALSO: '<USB Mass Storage Class - Control/Bulk/Interrupt Transport Specification Revision 1.0>' '<USB Mass Storage Class - UFI Command specification Revision 1.0>'*//* includes */#include "vxWorks.h"#include "string.h"#include "errno.h"#include "errnoLib.h"#include "ioLib.h"#include "blkIo.h"#include "stdio.h"#include "logLib.h"#include "taskLib.h"#include "drv/timer/timerDev.h"#include "usb/usbPlatform.h"#include "usb/ossLib.h" /* operations system srvcs */#include "usb/usb.h" /* general USB definitions */#include "usb/usbListLib.h" /* linked list functions */#include "usb/usbdLib.h" /* USBD interface */#include "usb/usbLib.h" /* USB utility functions */#include "drv/usb/usbCbiUfiDevLib.h"/* defines */#define USB_DEBUG_MSG 0x01#define USB_DEBUG_ERR 0x02extern void usbLogMsg (char *,int,int,int,int,int,int);#define USB_CBI_UFI_DEBUG \ if (usbCbiUfiDebug & USB_DEBUG_MSG) \ usbLogMsg#define USB_CBI_UFI_ERR \ if (usbCbiUfiDebug & USB_DEBUG_ERR) \ usbLogMsg#define CBI_TEST_READY_NOCHANGE 0 /* no media change detected */#define CBI_TEST_READY_CHANGED 1 /* media change detected */#define CBI_TEST_READY_FAILED 2 /* failed to checked ready status */#define CBI_TEST_READY_MXRETRIES 200 /* Retry count for testing unit ready *//* typedefs */typedef struct usbCbiUfiDev { BLK_DEV blkDev; /* Vxworks block device structure */ /* Must be the first one */ USBD_NODE_ID cbiUfiDevId; /* USBD node ID of the device */ UINT16 configuration; /* Configuration value */ UINT16 interface; /* Interface number */ UINT16 altSetting; /* Alternate setting of interface */ UINT16 outEpAddress; /* Bulk out EP address */ UINT16 inEpAddress; /* Bulk in EP address */ UINT16 intrEpAddress; /* Interrupt EP address */ USBD_PIPE_HANDLE outPipeHandle; /* Pipe handle for Bulk out EP */ USBD_PIPE_HANDLE inPipeHandle; /* Pipe handle for Bulk in EP */ USBD_PIPE_HANDLE intrPipeHandle; /* Pipe handle for interrupt EP */ USB_IRP inIrp; /* IRP used for bulk-in data */ USB_IRP outIrp; /* IRP used for bulk-out data */ USB_IRP statusIrp; /* IRP used for status data */ USB_UFI_CMD_BLOCK ufiCmdBlk; /* Store for UFI Command block */ UINT8 * bulkInData; /* Pointer for bulk-in data */ UINT8 * bulkOutData; /* Pointer for bulk-out data */ UINT8 intrStatus[2]; /* Store for Status bytes */ UINT16 lockCount; /* Count of times structure locked*/ UINT16 inEpAddressMaxPkt; /* Max In Pipe Packet size */ UINT16 outEpAddressMaxPkt; /* Max Out Pipe Packet size */ BOOL connected; /* TRUE if CBI_UFI device connected */ SEM_HANDLE cbiUfiIrpSem; /* Semaphore for IRP Synchronisation */ LINK cbiUfiDevLink; /* Link to other USB_CBI_UFI devices */ } USB_CBI_UFI_DEV, *pUSB_CBI_UFI_DEV;/* Attach request for user callback */typedef struct attach_request { LINK reqLink; /* linked list of requests */ USB_UFI_ATTACH_CALLBACK callback; /* client callback routine */ pVOID callbackArg; /* client callback argument*/ } ATTACH_REQUEST, *pATTACH_REQUEST;/* globals */BOOL usbCbiUfiDebug = 0;/* locals */LOCAL UINT16 initCount = 0; /* Count for UFI device initialisation */LOCAL USBD_CLIENT_HANDLE usbdHandle; /* Handle for this class driver */LOCAL LIST_HEAD cbiUfiDevList; /* Linked list of USB_CBI_UFI_DEV */LOCAL LIST_HEAD reqList; /* Attach callback request list */LOCAL MUTEX_HANDLE cbiUfiDevMutex; /* Mutex used to protect internal structs *//* forward declarations */LOCAL STATUS usbCbiUfiDescShow (USBD_NODE_ID nodeId);LOCAL STATUS usbCbiUfiConfigDescShow (USBD_NODE_ID nodeId, UINT8 index);LOCAL pUSB_CBI_UFI_DEV usbCbiUfiPhysDevCreate (USBD_NODE_ID nodeId, UINT16 config, UINT16 interface);LOCAL pUSB_CBI_UFI_DEV usbCbiUfiDevFind (USBD_NODE_ID nodeId);LOCAL STATUS usbCbiUfiDevBlkRd (BLK_DEV *blkDev, UINT32 offset, UINT32 num, char * buf);LOCAL STATUS usbCbiUfiDevBlkWrt (BLK_DEV *blkDev, UINT32 offset, UINT32 num, char * buf);LOCAL STATUS usbCbiUfiDevStChk (BLK_DEV *blkDev);LOCAL STATUS usbCbiUfiDevReset (BLK_DEV *blkDev);LOCAL VOID usbCbiUfiIrpCallback (pVOID p);LOCAL STATUS usbCbiUfiFormCmd (pUSB_CBI_UFI_DEV pCbiUfiDev, UINT ufiCmd, UINT cmdParam1, UINT cmdParam2);LOCAL USB_COMMAND_STATUS usbCbiUfiCmdExecute (pUSB_CBI_UFI_DEV pCbiUfiDev);LOCAL VOID usbCbiUfiDevDestroy (pUSB_CBI_UFI_DEV pCbiUfiDev); LOCAL VOID notifyAttach (USBD_NODE_ID nodeId, UINT16 attachCode);LOCAL STATUS usbCbiUfiDevUnitReady ( BLK_DEV *);LOCAL UINT8 usbCbiUfiDevTestReady ( BLK_DEV *); /***************************************************************************** usbCbiUfiAttachCallback - called by USBD when UFI device is attached/detached** This function is invoked by the USBD driver when a mass storage device, * following CBI protocol and UFI command set, is attached or removed. * * <nodeId> is the USBD_NODE_ID of the node being attached or removed. * <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.* <configuration> and <interface> indicate the configuration/interface* that reports itself as a MSC/CBI/UFI device. * <deviceClass>, <deviceSubClass>, and <deviceProtocol> will identify a * MSC/CBI/UFI device.** NOTE: The USBD will invoke this function once for each configuration/* interface which reports itself as a MSC/CBI/UFI. So, it is possible * that a single device insertion/removal may trigger multiple callbacks. *** RETURNS: N/A** ERRNO: none**\NOMANUAL*/LOCAL VOID usbCbiUfiAttachCallback ( USBD_NODE_ID nodeId, /* USBD Node ID of the device attached */ UINT16 attachAction, /* Whether device attached / detached */ UINT16 configuration, /* Configur'n value for MSC/CBI/UFI */ UINT16 interface, /* Interface number for MSC/CBI/UFI */ UINT16 deviceClass, /* Interface class - 0x8 for MSC */ UINT16 deviceSubClass, /* Device sub-class - 0x4 for UFI command */ UINT16 deviceProtocol /* Interfaceprotocol - 0x00 for CBI */ ) { pUSB_CBI_UFI_DEV pCbiUfiDev; OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK); switch (attachAction) { case USBD_DYNA_ATTACH: /* MSC/CBI/UFI Device attached */ USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback : New MSC/CBI/UFI device "\ "attached\n", 0, 0, 0, 0, 0, 0); /* Check out whether we already have a structure for this device */ USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback: Configuration = %d, " \ "Interface = %d, Node Id = %d \n", configuration, interface, (UINT)nodeId, 0, 0, 0); if (usbCbiUfiDevFind (nodeId) != NULL) break; /* create a USB_CBI_UFI_DEV structure for the device detected */ if ((pCbiUfiDev = usbCbiUfiPhysDevCreate (nodeId, configuration, interface)) ==NULL ) { USB_CBI_UFI_ERR ("usbCbiUfiAttachCallback : Error creating " \ "MSC/CBI/UFI device\n", 0, 0, 0, 0, 0, 0); break; } /* Notify registered callers that a CBI_UFI_DEV has been added */ notifyAttach (pCbiUfiDev->cbiUfiDevId, USB_UFI_ATTACH); break; case USBD_DYNA_REMOVE: /* MSC/CBI/UFI Device detached */ USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback : MSC/CBI/UFI Mass storage "\ "device detached\n", 0, 0, 0, 0, 0, 0); if ((pCbiUfiDev = usbCbiUfiDevFind (nodeId)) == NULL) break; /* Check the connected flag */ if (pCbiUfiDev->connected == FALSE) break; pCbiUfiDev->connected = FALSE; /* Notify registered callers that the CBI_UFI device has been * removed * * NOTE: We temporarily increment the device's lock count * to prevent usbCbiUfiDevUnlock() from destroying the * structure while we're still using it. */ pCbiUfiDev->lockCount++; notifyAttach (pCbiUfiDev->cbiUfiDevId, USB_UFI_REMOVE); pCbiUfiDev->lockCount--; if (pCbiUfiDev->lockCount == 0) usbCbiUfiDevDestroy (pCbiUfiDev); USB_CBI_UFI_DEBUG ("usbCbiUfiDevAttachCallback : CbiUfi Mass \ storage device detached\n", 0, 0, 0, 0, 0, 0); break; default : break; } OSS_MUTEX_RELEASE (cbiUfiDevMutex); }/***************************************************************************** usbCbiUfiDevShutDown - shuts down the USB CBI mass storage class driver* * This routine unregisters UFI driver from USBD and releases any resources * allocated for the devices.** RETURNS: OK or ERROR.** ERRNO:* \is* \i S_usbCbiUfiDevLib_NOT_INITIALIZED* CBI Device is not initialized * \ie */STATUS usbCbiUfiDevShutDown ( int errCode /* Error code - reason for shutdown */ ) { pUSB_CBI_UFI_DEV pCbiUfiDev; pATTACH_REQUEST pRequest; if (initCount == 0) return ossStatus (S_usbCbiUfiDevLib_NOT_INITIALIZED); /* release any UFI devices */ while ((pCbiUfiDev = usbListFirst (&cbiUfiDevList)) != NULL) usbCbiUfiDevDestroy (pCbiUfiDev); /* Dispose of any outstanding notification requests */ while ((pRequest = usbListFirst (&reqList)) != NULL) { usbListUnlink (&pRequest->reqLink); OSS_FREE (pRequest); } /* * Unregister with the USBD. USBD will automatically release any pending * IRPs or attach requests. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -