📄 usbbulkdevlib.c
字号:
* This routine unregisters the driver from USBD and releases any resources * allocated for the devices.** RETURNS: OK or ERROR depending on errCode** ERRNO:* \is * \i S_usbBulkDevLib_NOT_INITIALIZED* Not initialized* \ie*/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 (bulkMutex != NULL) { OSS_MUTEX_DESTROY (bulkMutex); bulkMutex = NULL; } initCount--; return ossStatus (errCode); }/***************************************************************************** usbBulkDevInit - registers USB Bulk only mass storage class driver** This routine registers the mass storage class driver with USB driver. It* also registers attach callback routine to get notified of the USB/MSC/BULK* ONLY devices. ** RETURNS: OK, or ERROR if unable to register with USBD.** ERRNO:* \is* \i S_usbbulkDevLib_OUT_OF_RESOURCES* Resources not available** \i S_usbbulkDevLib_USBD_FAULT* Error in USBD layer* \ie*/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)); bulkMutex = NULL; usbdHandle = NULL; if (OSS_MUTEX_CREATE (&bulkMutex) != 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); }/***************************************************************************** usbBulkDevIoctl - perform a device-specific control** Typically called to invoke device-specific functions which are not needed* by a file system. ** RETURNS: The status of the request, or ERROR if the request is unsupported.** ERRNO: none*/STATUS usbBulkDevIoctl ( BLK_DEV * pBlkDev, /* pointer to bulk device */ int request, /* request type */ int someArg /* arguments related to request */ ) { UINT16 actLen= 0xffff; USB_COMMAND_STATUS status; /* get a pointer to the bulk device */ pUSB_BULK_DEV_LUN pBulkDevLun = (pUSB_BULK_DEV_LUN)(pBlkDev); pUSB_BULK_DEV pBulkDev = (pUSB_BULK_DEV) (pBulkDevLun - pBulkDevLun->blkLun); UINT8 lun = pBulkDevLun->blkLun; 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); } /* Make sure that no one else is doing anything with this USB device */ OSS_MUTEX_TAKE(pBulkDev->bulkDevMutex, OSS_BLOCK); 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, lun, USB_SCSI_FORMAT_UNIT, 0, 0) != OK ) { OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } if ((status = usbBulkCmdExecute (pBulkDev)) != USB_COMMAND_SUCCESS ) { USB_BULK_ERR ("usbBulkDevIoctl: FORMAT UNIT Command failed\n", 0, 0, 0, 0, 0, 0); if (status == USB_COMMAND_FAILED) { /* Clear the error condition on the device */ usbBulkRequestSense(pBlkDev, &bulkSenseKey, &bulkAsc, &bulkAscq); } OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } return (OK); case USB_BULK_DESCRIPTOR_GET: OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); /* invoke routine to display all descriptors */ return (usbBulkDescShow (pBulkDev->bulkDevId)); case USB_BULK_DEV_RESET: OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); /* send a class-specific mass storage reset command */ return (usbBulkDevResetRecovery (pBulkDev)); case USB_BULK_EJECT_MEDIA: /* Only applicable if media is removable */ if ( pBlkDev->bd_removable != TRUE ) { OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } else { if ( usbBulkFormScsiCmd (pBulkDev, lun, USB_SCSI_START_STOP_START, USB_SCSI_START_STOP_LOEJ, 0) != OK ) { OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } if ( (status = usbBulkCmdExecute (pBulkDev)) != USB_COMMAND_SUCCESS ) { USB_BULK_ERR ("usbBulkDevIoctl: EJECT Command " \ "failed\n", 0, 0, 0, 0, 0, 0); if (status == USB_COMMAND_FAILED) { /* Clear the error condition on the device */ usbBulkRequestSense(pBlkDev, &bulkSenseKey, &bulkAsc, &bulkAscq); } OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } } OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (OK); case USB_BULK_MAX_LUN: /* May not be supported by devices having single LUN */ if (usbdVendorSpecific (usbdHandle, pBulkDev->bulkDevId, USB_RT_DEV_TO_HOST | USB_RT_CLASS | USB_RT_INTERFACE, USB_BULK_GET_MAX_LUN, 0, pBulkDev->interface, 1, &(pBulkDev->maxLun), &actLen) != OK ) { USB_BULK_ERR ("usbBulkDevIoctl: Failed to acquire max lun \n", 0, 0, 0, 0, 0, 0); pBulkDev->maxLun = 0; } else { USB_BULK_DEBUG ("usbBulkDevIoctl: Max Lun = %c \n", pBulkDev->maxLun, 0, 0, 0, 0, 0); } if (pBulkDev->maxLun > MAX_LUN-1) { USB_BULK_DEBUG ("USB Bulk Mass Storage Device Maximum LUN exceeded\n", 0,0,0,0,0,0); pBulkDev->maxLun = MAX_LUN-1; } OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (OK); default: errnoSet (S_ioLib_UNKNOWN_REQUEST); USB_BULK_DEBUG ("usbBulkDevIoctl: Unknown Request\n", 0, 0, 0, 0, 0, 0); OSS_MUTEX_RELEASE(pBulkDev->bulkDevMutex); return (ERROR); } }/***************************************************************************** usbBulkDevResetRecovery - performs reset recovery on the specified device** Reset recovery shall be done when device returns a phase error status * while executing a CBW. It is also done, when a stall condition is detected* on bulk-out endpoint during CBW transport. The following sequence is * performed on the device ** - BulkOnly Mass Storage Reset * - Clear HALT feature on the Bulk-in Endpoint* - Clear HALT feature on the Bulk-out Endpoint** RETURNS: OK, if reset sequence successful otherwise ERROR** ERRNO: none**\NOMANUAL*/LOCAL STATUS usbBulkDevResetRecovery ( pUSB_BULK_DEV pBulkDev /* pointer to bulk device */ ) { /* Verify the Bulk Pointer is valid */ if (pBulkDev == NULL) return ERROR; OSS_MUTEX_TAKE (pBulkDev->bulkDevMutex, OSS_BLOCK); /* issue bulk-only mass storage reset request on control End point */ if ((usbdVendorSpecific (usbdHandle, pBulkDev->bulkDevId, USB_RT_HOST_TO_DEV | USB_RT_CLASS | USB_RT_INTERFACE, USB_BULK_RESET, 0, pBulkDev->interface, 0, NULL, NULL)) != OK ) { USB_BULK_ERR ("usbBulkDevResetRecovery: Failed to reset %x\n", 0, 0, 0, 0, 0, 0); OSS_MUTEX_RELEASE (pBulkDev->bulkDevMutex); return (ERROR); } else { USB_BULK_DEBUG ("usbBulkDevResetRecovery: Reset...done\n", 0, 0, 0, 0, 0, 0); } /* clear HALT feature on bulk in and bulk out end points */ if ((usbdFeatureClear (usbdHandle, pBulkDev->bulkDevId, USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, (pBulkDev->inEpAddress & 0xFF))) != OK) { USB_BULK_ERR ("usbBulkDevResetRecovery: Failed to clear HALT feauture"\ " on bulk in Endpoint %x\n", 0, 0, 0, 0, 0, 0); } if ((usbdFeatureClear (usbdHandle, pBulkDev->bulkDevId, USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, (pBulkDev->outEpAddress & 0xFF))) != OK) { USB_BULK_ERR ("usbBulkDevResetRecovery: Failed to clear HALT feauture"\ " on bulk out Endpoint %x\n", 0, 0, 0, 0, 0, 0); } OSS_MUTEX_RELEASE (pBulkDev->bulkDevMutex); return (OK); }/***************************************************************************** usbBulkFormScsiCmd - forms command block wrapper(CBW) for requested SCSI command** This routine forms SCSI command blocks as per the Bulk-only command * specifications and SCSI protocol.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -