📄 usbcbiufidevlib.c
字号:
if (usbdHandle != NULL) { usbdClientUnregister (usbdHandle); usbdHandle = NULL; USB_CBI_UFI_DEBUG ("usbCbiUfiDevShutDown : CBI Mass storage class driver "\ "for UFI devices unregistered \n", 0, 0, 0, 0, 0, 0); } /* release resources */ if (cbiUfiDevMutex != NULL) { OSS_MUTEX_DESTROY (cbiUfiDevMutex); cbiUfiDevMutex = NULL; } initCount--; return ossStatus (errCode); }/***************************************************************************** usbCbiUfiDevInit - registers USB CBI mass storage class driver for UFI devices** This routine registers the CBI mass storage class driver for UFI devices.* It also registers a callback routine to request notification whenever* USB/MSC/CBI/UFI devices are attached or removed. ** RETURNS: OK, or ERROR if unable to register with USBD.** ERRNO:* \is* \i S_usbCbiUfiDevLib_OUT_OF_RESOURCES* Resouces are not available** \i S_usbCbiUfiDevLib_USBD_FAULT* USBD Fault has occured* \ie*/STATUS usbCbiUfiDevInit (VOID) { /* * Check whether already initialised. If not, then initialise the required * structures and registers the class driver with USBD. */ if (initCount == 0) { memset (&cbiUfiDevList, 0, sizeof (cbiUfiDevList)); memset (&reqList, 0, sizeof (reqList)); cbiUfiDevMutex = NULL; usbdHandle = NULL; if (OSS_MUTEX_CREATE (&cbiUfiDevMutex) != OK) return (usbCbiUfiDevShutDown (S_usbCbiUfiDevLib_OUT_OF_RESOURCES)); /* Establish connection to USBD and register for attach callback */ if (usbdClientRegister ("CBI_UFI_CLASS", &usbdHandle) != OK || usbdDynamicAttachRegister (usbdHandle, USB_CLASS_MASS_STORAGE, USB_SUBCLASS_UFI_COMMAND_SET, USB_INTERFACE_PROTOCOL_CBI, usbCbiUfiAttachCallback) != OK) { USB_CBI_UFI_ERR ("usbCbiUfiDevInit: Client Registration Failed \n", 0, 0, 0, 0, 0, 0); return (usbCbiUfiDevShutDown (S_usbCbiUfiDevLib_USBD_FAULT)); } } initCount++; return (OK); }/***************************************************************************** usbCbiUfiDevIoctl - perform a device-specific control.** Typically called by file system to invoke device-specific functions beyond * file handling. The following control requests are supported** \is* \i 'FIODISKFORMAT (0x05)'* Formats the entire disk with appropriate hardware track and sector marks.* No file system is initialized on the disk by this request. This control* function is defined by the file system, but provided by the driver.** \i 'USB UFI ALL DESCRIPTOR GET (0xF0)'* Invokes show routine for displaying configuration, device and interface* descriptors.** \i 'USB UFI DEV RESET (0xF1)'* Issues a command block reset and clears stall condition on bulk-in and* bulk-out endpoints.* \ie** RETURNS: The status of the request, or ERROR if the request is unsupported.** ERRNO: none*/STATUS usbCbiUfiDevIoctl ( BLK_DEV * pBlkDev, /* pointer to MSC/CBI/UFI device */ UINT32 request, /* request type */ UINT32 someArg /* arguments related to request */ ) { /* get a pointer to the MSC/CBI/UFI device */ pUSB_CBI_UFI_DEV pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev; if ( pCbiUfiDev == (pUSB_CBI_UFI_DEV)NULL ) return (ERROR); /* Check whether the device exists or not */ if (usbCbiUfiDevFind (pCbiUfiDev->cbiUfiDevId) != pCbiUfiDev) { USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: MSC/CBI/UFI 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 ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_FORMAT_UNIT, 0, 0) != OK) { USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: Error forming command\n", 0, 0, 0, 0, 0, 0); return (ERROR); } if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS ) { USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: Error executing "\ "USB_UFI_FORMAT_UNIT command\n", 0, 0, 0, 0, 0, 0); return (ERROR); } break; case USB_UFI_ALL_DESCRIPTOR_GET: /* invoke routine to display all descriptors */ return (usbCbiUfiDescShow (pCbiUfiDev->cbiUfiDevId)); case USB_UFI_DEV_RESET: /* send a command block reset */ return (usbCbiUfiDevReset ((BLK_DEV *)pCbiUfiDev)); default: errnoSet (S_ioLib_UNKNOWN_REQUEST); USB_CBI_UFI_DEBUG ("usbCbiUfiDevIoctl: Unknown Request\n", 0, 0, 0, 0, 0, 0); return (ERROR); break; } return (OK); } /***************************************************************************** usbCbiUfiCmdExecute - Executes an UFI command block. ** This routine executes previously formed UFI Command as per the CBI protocol.* First, the command block formed by usbCbiUfiFormCmd() is sent to the device* via the control endpoint. This is done using Accept Device Specific Command* (ADSC) class specific request. If the command block requires any data * transfer to/from the device, then an IRP is submitted to perform the data* tranport via bulk in/out endpoints. Finally, status bytes are read from the* interrupt endpoint.** RETURNS: USB_COMMAND_STATUS, command execution status** ERRNO: * \is* \i USB_COMMAND_FAILED* Failed to execute the USB Command** \i USB_INTERNAL_ERROR* Internal error in USB Stack** \i USB_BULK_IO_ERROR* Bilk I/O Error* \ie**\NOMANUAL*/LOCAL USB_COMMAND_STATUS usbCbiUfiCmdExecute ( pUSB_CBI_UFI_DEV pCbiUfiDev /* pointer to cbi_ufi device */ ) { UINT16 actLen = 0xFFFF; /* Send the UFI Command block along with the ADSC request */ if ((usbdVendorSpecific (usbdHandle, pCbiUfiDev->cbiUfiDevId, USB_RT_HOST_TO_DEV | USB_RT_CLASS | USB_RT_INTERFACE, 0, 0, pCbiUfiDev->interface, USB_UFI_MAX_CMD_LEN, (UINT8 *)&(pCbiUfiDev->ufiCmdBlk.cmd), &actLen )) != OK ) { USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Failed to execute ADSC \n", 0, 0, 0, 0, 0, 0); return (USB_COMMAND_FAILED); } if ( pCbiUfiDev->ufiCmdBlk.dataXferLen > 0 ) { if ( OSS_SEM_TAKE (pCbiUfiDev->cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000) == ERROR ) { /* This should never occur unless the stack does'nt call * callback at all */ USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp in Use \n", 0, 0, 0, 0, 0, 0); return (USB_INTERNAL_ERROR); } if (pCbiUfiDev->ufiCmdBlk.direction == USB_UFI_DIR_IN) { /* data is expected from the device. read from BULK_IN pipe */ memset (&(pCbiUfiDev->inIrp), 0, sizeof (USB_IRP)); /* form an IRP to read from BULK_IN pipe */ pCbiUfiDev->inIrp.irpLen = sizeof(USB_IRP); pCbiUfiDev->inIrp.userCallback = usbCbiUfiIrpCallback; pCbiUfiDev->inIrp.timeout = USB_CBI_IRP_TIME_OUT; pCbiUfiDev->inIrp.transferLen = pCbiUfiDev->ufiCmdBlk.dataXferLen; pCbiUfiDev->inIrp.bfrCount = 0x01; pCbiUfiDev->inIrp.bfrList[0].pid = USB_PID_IN; pCbiUfiDev->inIrp.bfrList[0].pBfr = pCbiUfiDev->bulkInData; pCbiUfiDev->inIrp.bfrList[0].bfrLen = pCbiUfiDev->ufiCmdBlk.dataXferLen; pCbiUfiDev->inIrp.userPtr = pCbiUfiDev; /* Submit IRP */ if (usbdTransfer (usbdHandle, pCbiUfiDev->inPipeHandle, &(pCbiUfiDev->inIrp)) != OK) { USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Unable to submit IRP for "\ "BULK_IN data transfer\n", 0, 0, 0, 0, 0, 0); OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); return (USB_INTERNAL_ERROR); } /* * wait till the data transfer ends on bulk in pipe before reading * the command status */ if ( OSS_SEM_TAKE (pCbiUfiDev->cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000) == ERROR ) { USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out \n", 0, 0, 0, 0, 0, 0); /* Cancel the IRP */ usbdTransferAbort(usbdHandle, pCbiUfiDev->inPipeHandle, &(pCbiUfiDev->inIrp)); return (USB_INTERNAL_ERROR); } /* Check whether data transfer was complete or not */ if ( pCbiUfiDev->inIrp.result != OK) { USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Data transfer failed \n", 0, 0, 0, 0, 0, 0); OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); return (USB_COMMAND_FAILED); } } else if (pCbiUfiDev->ufiCmdBlk.direction == USB_UFI_DIR_OUT) { /* device is expecting data over BULK_OUT pipe. send it */ memset (&pCbiUfiDev->outIrp, 0, sizeof (USB_IRP)); /* form an IRP to write to BULK_OUT pipe */ pCbiUfiDev->outIrp.irpLen = sizeof(USB_IRP); pCbiUfiDev->outIrp.userCallback = usbCbiUfiIrpCallback; pCbiUfiDev->outIrp.timeout = USB_CBI_IRP_TIME_OUT; pCbiUfiDev->outIrp.transferLen = pCbiUfiDev->ufiCmdBlk.dataXferLen; pCbiUfiDev->outIrp.bfrCount = 0x01; pCbiUfiDev->outIrp.bfrList[0].pid = USB_PID_OUT; pCbiUfiDev->outIrp.bfrList[0].pBfr = pCbiUfiDev->bulkOutData; pCbiUfiDev->outIrp.bfrList[0].bfrLen = pCbiUfiDev->ufiCmdBlk.dataXferLen; pCbiUfiDev->outIrp.userPtr = pCbiUfiDev; /* Submit IRP */ if (usbdTransfer (usbdHandle, pCbiUfiDev->outPipeHandle, &(pCbiUfiDev->outIrp)) != OK) { USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Unable to submit IRP for "\ "BULK_OUT data transfer\n", 0, 0, 0, 0, 0, 0); OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); return (USB_INTERNAL_ERROR); } /* * wait till the data transfer ends on bulk out pipe before reading * the command status */ if ( OSS_SEM_TAKE (pCbiUfiDev->cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000) == ERROR ) { USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out \n", 0, 0, 0, 0, 0, 0); /* Cancel the IRP */ usbdTransferAbort(usbdHandle, pCbiUfiDev->outPipeHandle, &(pCbiUfiDev->outIrp)); return (USB_INTERNAL_ERROR); } /* Check whether data transfer was complete or not */ if (pCbiUfiDev->outIrp.result != OK) { USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Data transfer failed \n", 0, 0, 0, 0, 0, 0); OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); return (USB_COMMAND_FAILED); } } OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); } if ( OSS_SEM_TAKE (pCbiUfiDev->cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000) == ERROR ) { USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out \n", 0, 0, 0, 0, 0, 0); OSS_SEM_GIVE (pCbiUfiDev->cbiUfiIrpSem); return (USB_INTERNAL_ERROR); } /* Read the status from the interrupt endpoint */ memset (&(pCbiUfiDev->statusIrp), 0, sizeof (USB_IRP)); /* form an IRP to read status from interrupt endpoint */ pCbiUfiDev->statusIrp.irpLen = sizeof(USB_IRP); pCbiUfiDev->statusIrp.userCallback = usbCbiUfiIrpCallback;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -