📄 usbbulkdevlib.c
字号:
/* usbBulkDevLib.c - USB Bulk Only Mass Storage class driver */
/* Copyright 2000-2001 Wind River Systems, Inc. */
/*
modification history
--------------------
01g,08aug01,dat Removing warnings
01f,25jul01,wef fixed spr #69285
01e,01may01,wef fixed incorrect declaration of usbBulkDevDestroy
01d,12apr01,wef added logic to do READ/WRITE 6 or 10 based on configlette
parameter - added a paramter to usbBulBlkDevCreate ()
for this purpose. added support for drives with partition
tables.
01c,02sep00,bri added support for multiple devices.
01b,04aug00,bri updated as per review.
01a,22may00,bri written.
*/
/*
DESCRIPTION
This 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. This driver implements external
APIs which would be expected of a standard block device driver.
This class driver restricts to Mass Storage class devices that follow bulk-only
transport. For bulk-only devices transport of command, data and status occurs
solely via bulk endpoints. The default control pipe is only used to set
configuration, clear STALL condition on endpoints and to issue class-specific
requests.
The class driver is a client of the Universal Serial Bus Driver (USBD). All
interaction with the USB buses and devices is handled through the USBD.
INITIALIZATION
The class driver must be initialized with usbBulkDevInit(). It is assumed that
USBD is already initialized and attached to atleast one USB Host Controller.
usbBulkDevInit() registers the class driver as a client module with USBD. It
also registers a callback routine to get notified whenever a USB MSC/SCSI/
BULK-ONLY device is attached or removed from the system. The callback routine
creates a USB_BULK_DEV structure to represent the USB device attached. It
also sets device configuration, interface settings and creates pipes for
BULK_IN and BULK_OUT transfers.
OTHER FUNCTIONS
usbBulkBlkDevCreate() is the entry point to define a logical block device.
This routine initializes the fields with in the vxWorks block device structure
BLK_DEV. This BLK_DEV structure is part of the USB_BULK_DEV structure.
Memory is allocated for USB_BULK_DEV by the dynamic attach notification
callback routine. So, this create routine just initializes the BLK_DEV
structure and returns a pointer to it, which is used during file system
initializtion call.
usbBulkDevIoctl() implements functions which are beyond basic file handling.
Class-specific requests, Descriptor show, are some of the functions. Function
code parameter identifies the IO operation requested.
DATA FLOW
For each USB MSC/SCSI/BULK-ONLY device detected, usbBulkPhysDevCreate() will
create pipes to BULK_IN and a BULK_OUT endpoints of the device. A pipe is a
channel between USBD client i,e usbBulkDevLib and a specific endpoint. All
SCSI commands are encapsulated with in a Command Block Wrapper (CBW) and
transferred across the BULK_OUT endpoint through the out pipe created.
This is followed by a data transfer phase. Depending on the SCSI command
sent to the device, the direction bit in the CBW will indicate whether data
is transferred to or from the device. This bit has no significance if no
data transfer is expected. Data is transferred to the device through BULK_OUT
endpoint and if the device is required to transfer data, it does through
the BULK_IN endpoint. The device shall send Command Status Wrapper (CSW) via
BULK_IN endpoint. This will indicate the success or failure of the CBW. The
data to be transferred to device will be pointed by the file system launched
on the device.
INCLUDE FILES: usbBulkDevLib.h, blkIo.h
SEE ALSO:
.I "USB Mass Storage Class - Bulk Only Transport Specification Version 1.0,"
.I "SCSI-2 Standard specification 10L - Direct Access device commands"
*/
/* 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" /* 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/usbBulkDevLib.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
/* typedefs */
/* USB_BULK_DEV Structure - used to describe USB MSC/SCSI/BULK-ONLY device */
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;
/* Attach request for user callback */
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);
/***************************************************************************
*
* usbBulkDevAttachCallback - called when BULK-ONLY/SCSI device is attached/
* removed
*
* This routine is called by USBD when a mass storage device with SCSI command
* set as interface sub-class and with bulk-only as interface protocol, is
* attached/detached.
*
* <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/SCSI/BULK-ONLY device.
* <deviceClass>, <deviceSubClass>, and <deviceProtocol> will identify a
* MSC/SCSI/BULK-ONLY device.
*
* NOTE: The USBD will invoke this function once for each configuration/
* interface which reports itself as a MSC/SCSI/BULK-ONLY. So, it is possible
* that a single device insertion/removal may trigger multiple callbacks.
*
*
* RETURNS: N/A
*/
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
*/
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);
}
/***************************************************************************
*
* usbBulkDevShutDown - shuts down the USB bulk-only class driver.
*
* This routine unregisters the driver from USBD and releases any resources
* allocated for the devices.
*
* RETURNS: OK or ERROR.
*/
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -