usbmpc5200devlib.c

来自「MPC5200 BSP 支持ATA,USB, I2C,扩展网口」· C语言 代码 · 共 1,989 行 · 第 1/5 页

C
1,989
字号
/* 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 "dosFsLib.h"

#include "usb/usbPlatform.h"
#include "usb/ossLib.h"	            
#include "usb/usb.h"	            
#include "usb/usbListLib.h"         
#include "usb/usbdLib.h"           
#include "usb/usbLib.h"	           

#include "usbMpc5200DevLib.h"


/* defines */

#define USB_DEBUG_MSG        0x01
#define USB_DEBUG_ERR        0x02

#define USB_BULK_DEBUG                  \
        if (usbBulkDebug & USB_DEBUG_MSG)   \
            logMsg

#define USB_BULK_ERR                    \
        if (usbBulkDebug & USB_DEBUG_ERR)   \
            logMsg

#define USB_BULK_OFFS  1000

typedef struct usbBulkDev
    {
    BLK_DEV           blkDev;         /* Vxworks block device structure */
                                      /* Must be the first one          */
    USBD_NODE_ID      bulkDevId;      /* 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             */
    USBD_PIPE_HANDLE  outPipeHandle;  /* Pipe handle for Bulk out EP    */
    USBD_PIPE_HANDLE  inPipeHandle;   /* Pipe handle for Bulk in 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 reading status    */ 
    UINT8             maxLun;         /* Max. number of LUN supported   */
    USB_BULK_CBW      bulkCbw;        /* Structure for Command block    */
    USB_BULK_CSW      bulkCsw;        /* Structure for Command status   */
    UINT8 *           bulkInData;     /* Pointer for bulk-in data       */
    UINT8 *           bulkOutData;    /* Pointer for bulk-out data      */   
    UINT32            numBlks;	      /* Number of blocks on device     */	 
    UINT32            blkOffset;      /* Offset of the starting block   */
    UINT16            lockCount;      /* Count of times structure locked*/
    BOOL              connected;      /* TRUE if USB_BULK device connected */    
    LINK              bulkDevLink;    /* Link to other USB_BULK devices    */  
    BOOL              read10Able;     /* Which read/write command the device  */
				      /* supports.  If TRUE, the device uses  */
				      /* READ10/WRITE10, if FALSE uses READ6 / */
				      /* WRITE6 */
    } USB_BULK_DEV, *pUSB_BULK_DEV;    

typedef struct attach_request
    {
    LINK reqLink;                       /* linked list of requests */
    USB_BULK_ATTACH_CALLBACK callback;  /* client callback routine */
    pVOID callbackArg;                  /* client callback argument*/
    } ATTACH_REQUEST, *pATTACH_REQUEST;

/* globals */

BOOL usbBulkDebug =  0;

/* locals */

LOCAL UINT16 initCount = 0;           /* Count for Bulk device initialisation */

LOCAL USBD_CLIENT_HANDLE usbdHandle;  /* Handle for this class driver */

LOCAL LIST_HEAD bulkDevList;          /* linked list of USB_BULK_DEV */

LOCAL LIST_HEAD    reqList;           /* Attach callback request list */

MUTEX_HANDLE bulkDevMutex;      /* mutex used to protect internal structs */

SEM_HANDLE   bulkIrpSem;        /* Semaphore for IRP Synchronisation */

LOCAL UINT32 usbBulkIrpTimeOut = USB_BULK_IRP_TIME_OUT; /* Time out for IRP */

/* forward declarations */

LOCAL  STATUS usbBulkDescShow (USBD_NODE_ID nodeId);
LOCAL  STATUS usbBulkConfigDescShow  (USBD_NODE_ID nodeId, UINT8 index);
LOCAL  STATUS usbBulkPhysDevCreate (USBD_NODE_ID nodeId, UINT16 config, 
                                    UINT16 interface);
LOCAL  pUSB_BULK_DEV usbBulkDevFind (USBD_NODE_ID nodeId);
LOCAL  STATUS usbBulkDevBlkRd (BLK_DEV *blkDev, int offset, int num, 
			       char * buf);
LOCAL  STATUS usbBulkDevBlkWrt (BLK_DEV *blkDev, int offset, int num, 
				char * buf);
LOCAL  STATUS usbBulkDevStatusChk (BLK_DEV *blkDev);
LOCAL  STATUS usbBulkDevReset (BLK_DEV *blkDev);
LOCAL  void   usbBulkIrpCallback (pVOID p);
LOCAL  STATUS usbBulkFormScsiCmd (pUSB_BULK_DEV pBulkDev, UINT scsiCmd, 
                                  UINT cmdParam1, UINT cmdParam2);
                                   
LOCAL  USB_COMMAND_STATUS usbBulkCmdExecute (pUSB_BULK_DEV pBulkDev);
LOCAL  void   usbBulkDevDestroy (pUSB_BULK_DEV pBulkDev);
LOCAL  STATUS usbBulkDevResetRecovery (pUSB_BULK_DEV  pBulkDev);
LOCAL  VOID notifyAttach (USBD_NODE_ID nodeId, UINT16 attachCode);

LOCAL VOID usbBulkDevAttachCallback
    (
    USBD_NODE_ID nodeId,         /* USBD Node ID of the device attached */
    UINT16       attachAction,   /* Whether device attached / detached */
    UINT16       configuration,  /* Configur'n value for  MSC/SCSI/BULK-ONLY */
    UINT16       interface,      /* Interface number for  MSC/SCSI/BULK-ONLY */
    UINT16       deviceClass,    /* Interface class   - 0x8  for MSC */
    UINT16       deviceSubClass, /* Device sub-class  - 0x6  for SCSI 
				  * command 
				  */ 
    UINT16       deviceProtocol  /* Interfaceprotocol - 0x50 for Bulk only */ 
    )
    {
    pUSB_BULK_DEV  pBulkDev;     /* Pointer to bulk device,in case of 
				  * removal 
				  */
		USB_BULK_DEBUG ("usbBulkDevAttachCallback: deviceClass = %d, " \
                            "deviceSubClass = %d, deviceSubClass = %d \n", deviceClass,
                            deviceSubClass, deviceProtocol, 0, 0, 0); 

    OSS_MUTEX_TAKE (bulkDevMutex, OSS_BLOCK);
 
    switch (attachAction)
        { 
        case USBD_DYNA_ATTACH: 

            /* MSC/SCSI/BULK-ONLY Device attached */

            /* Check out whether we already have a structure for this device */

            if (usbBulkDevFind (nodeId) != NULL)
                break;

            USB_BULK_DEBUG ("usbBulkDevAttachCallback : New Bulk-only device "\
                            "attached\n", 0, 0, 0, 0, 0, 0);

            USB_BULK_DEBUG ("usbBulkDevAttachCallback: Configuration = %d, " \
                            "Interface = %d, Node Id = %d \n", configuration,
                            interface, (UINT)nodeId, 0, 0, 0); 

            /* create a USB_BULK_DEV structure for the device attached */
           
            if ( usbBulkPhysDevCreate (nodeId, configuration,interface) != OK )
                {
                USB_BULK_ERR ("usbBulkDevAttachCallback : Error creating Bulk"\
                              "device\n", 0, 0, 0, 0, 0, 0);
                break; 
                } 

            /* Notify registered callers that a USB_BULK_DEV has been added */

	    notifyAttach (nodeId, USB_BULK_ATTACH); 
 
            break;

        case USBD_DYNA_REMOVE:

            /* MSC/SCSI/BULK-ONLY Device detached */

            if ((pBulkDev = usbBulkDevFind (nodeId)) == NULL)
                break;

            /* Check the connected flag  */

            if (pBulkDev->connected == FALSE)
                break;
            
            pBulkDev->connected = FALSE;

	    /* Notify registered callers that the SCSI/BULK-ONLY device has 
             * been removed 
	     *
	     * NOTE: We temporarily increment the device's lock count
	     * to prevent usbBulkDevUnlock() from destroying the
	     * structure while we're still using it.
	     */

            pBulkDev->lockCount++; 

            notifyAttach (pBulkDev->bulkDevId, USB_BULK_REMOVE); 

            pBulkDev->lockCount--; 
           
            if (pBulkDev->lockCount == 0) 
                usbBulkDevDestroy (pBulkDev); 

            USB_BULK_DEBUG ("usbBulkDevAttachCallback : Bulk only Mass \
			     storage device detached\n", 0, 0, 0, 0, 0, 0);

            break;

        default :
            break; 
        }

    OSS_MUTEX_RELEASE (bulkDevMutex);  
    }


STATUS usbBulkDevShutDown 
    (
    int   errCode                /* Error code - reason for shutdown */
    )
    {

    pUSB_BULK_DEV pBulkDev;      /* Pointer to bulk device */
    pATTACH_REQUEST  pRequest;

    if (initCount == 0)
        return ossStatus (S_usbBulkDevLib_NOT_INITIALIZED);

    /* release any bulk devices */

    while ((pBulkDev = usbListFirst (&bulkDevList)) != NULL)
        usbBulkDevDestroy (pBulkDev); 

    /* 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.
     */

    if (usbdHandle != NULL)
        {
        usbdClientUnregister (usbdHandle);
        usbdHandle = NULL;
        USB_BULK_DEBUG ("usbBulkDevShutDown : Bulk Only class driver "\
                        "unregistered \n", 0, 0, 0, 0, 0, 0);
        }

    /* release resources */

    if (bulkDevMutex != NULL)
        {
        OSS_MUTEX_DESTROY (bulkDevMutex);
        bulkDevMutex = NULL;
        }

    if (bulkIrpSem != NULL)
        {
        OSS_SEM_DESTROY (bulkIrpSem);
        bulkIrpSem = NULL;
        }

    initCount--; 
   
    return ossStatus (errCode); 
    }


STATUS usbBulkDevInit (void)
    {

    /* 
     * Check whether already initilized. If not, then initialise the required
     * structures and register the class driver with USBD.
     */

    if (initCount == 0)
        {

        memset (&bulkDevList, 0, sizeof (bulkDevList));
        memset (&reqList, 0, sizeof (reqList));
        bulkDevMutex = NULL;
        bulkIrpSem   = NULL;
        usbdHandle   = NULL;


        if (OSS_MUTEX_CREATE (&bulkDevMutex) != OK)
            return (usbBulkDevShutDown (S_usbBulkDevLib_OUT_OF_RESOURCES));

        if (OSS_SEM_CREATE (1, 1 , &bulkIrpSem) != OK)
            return (usbBulkDevShutDown (S_usbBulkDevLib_OUT_OF_RESOURCES));

        /* Establish connection to USBD and register for attach callback */

        if (usbdClientRegister ("BULK_CLASS", &usbdHandle) != OK ||
            usbdDynamicAttachRegister (usbdHandle, USB_CLASS_MASS_STORAGE,
                                       USB_SUBCLASS_SCSI_COMMAND_SET, 
                                       USB_INTERFACE_PROTOCOL_BULK_ONLY,
                                       usbBulkDevAttachCallback) != OK)
            {
            USB_BULK_ERR ("usbBulkDevInit: Client Registration Failed \n",
                          0, 0, 0, 0, 0, 0); 
            return usbBulkDevShutDown (S_usbBulkDevLib_USBD_FAULT);
            }
        }

    initCount++;

    return (OK);
    }

STATUS usbBulkDevIoctl
    (
    BLK_DEV * pBlkDev,           /* pointer to bulk device       */
    int request,                 /* request type                 */
    int someArg                  /* arguments related to request */
    )
    {
    UINT16 actLen= 0xffff;       

    /* get a pointer to the bulk device */

    pUSB_BULK_DEV  pBulkDev = (USB_BULK_DEV *)pBlkDev;   

    if ( pBulkDev == (pUSB_BULK_DEV)NULL )
        return (ERROR);

    /* Check whether the device exists or not */

    if (usbBulkDevFind (pBulkDev->bulkDevId) != pBulkDev)
        {
        USB_BULK_ERR ("usbBulkDevIoctl: Bulk Device not found\n", 
                        0, 0, 0, 0, 0, 0);
        return (ERROR);
        }

    switch (request)
        {

        case FIODISKFORMAT: 

            /*  
             * This is the IO control function supported by file system,
             * but supplied by the device driver. Other IO control functions 
             * are directly handled by file system with out the use of this 
	     * routine.
             */

            if ( usbBulkFormScsiCmd (pBulkDev, 
				     USB_SCSI_FORMAT_UNIT, 
				     0, 
				     0) 
				   != OK )
                return (ERROR); 

            if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS )
                {
                USB_BULK_ERR ("usbBulkDevIoctl: FORMAT UNIT Command failed\n", 
                              0, 0, 0, 0, 0, 0);  
                return (ERROR); 
                }   
                
            return (OK);

        case USB_BULK_DESCRIPTOR_GET:

            /* invoke routine to display all descriptors */

            return (usbBulkDescShow (pBulkDev->bulkDevId));

        case USB_BULK_DEV_RESET:

            /* send a class-specific mass storage reset command */
             
            return (usbBulkDevResetRecovery (pBulkDev));

        case USB_BULK_EJECT_MEDIA:

            /* Only applicable if media is removable */

            if ( pBulkDev->blkDev.bd_removable  != TRUE )
                return (ERROR);  

            else
                {
                if ( usbBulkFormScsiCmd (pBulkDev, 
					 USB_SCSI_START_STOP_UNIT, 
					 USB_SCSI_START_STOP_LOEJ, 
					 0) 
					!= OK )
                    return (ERROR); 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?