📄 usbbulkdevlib.c
字号:
/* Clear HALT feauture on the endpoints */ if ((usbdFeatureClear (usbdHandle, pBulkDev->bulkDevId, USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, (pOutEp->endpointAddress & 0x0F))) != OK) { USB_BULK_ERR ("usbBulkPhysDevCreate: Failed to clear HALT feauture "\ "on bulk out Endpoint %x\n", 0, 0, 0, 0, 0, 0); } if ((usbdFeatureClear (usbdHandle, pBulkDev->bulkDevId, USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, (pOutEp->endpointAddress & 0x0F))) != OK) { USB_BULK_ERR ("usbBulkPhysDevCreate: Failed to clear HALT feauture "\ "on bulk in Endpoint %x\n", 0, 0, 0, 0, 0, 0); } /* Link the newly created structure. */ usbListLink (&bulkDevList, pBulkDev, &pBulkDev->bulkDevLink, LINK_TAIL); return (OK);errorExit: /* Error in creating a bulk device ..destroy */ usbBulkDevDestroy (pBulkDev); return (ERROR); }/***************************************************************************** usbBulkBlkDevCreate - create a block device.** This routine initializes a BLK_DEV structure, which describes a * logical partition on a USB_BULK_DEV device. A logical partition is an array * of contiguously addressed blocks; it can be completely described by the number* of blocks and the address of the first block in the partition. ** NOTE:* If `numBlocks' is 0, the rest of device is used.* * This routine supplies an additional parameter called <flags>. This bitfield * currently only uses bit 1. This bit determines whether the driver will use a* SCSI READ6 or SCSI READ10 for read access.** RETURNS: A pointer to the BLK_DEV, or NULL if parameters exceed* physical device boundaries, or if no bulk device exists.*/BLK_DEV * usbBulkBlkDevCreate ( USBD_NODE_ID nodeId, /* nodeId of the bulk-only device */ UINT32 numBlks, /* number of logical blocks on device */ UINT32 blkOffset, /* offset of the starting block */ UINT32 flags /* optional flags */ ) { UINT8 inquiry[36]; /* store for INQUIRY data */ DOS_PART_TBL *pPart; char blk0Buffer [512]; int offset=0; int ix; /* TODO : As of now only the first device is taken care */ pUSB_BULK_DEV pBulkDev = usbBulkDevFind (nodeId); /*pUSB_BULK_DEV pBulkDev = usbListFirst (&bulkDevList);*/ if (pBulkDev == NULL) { USB_BULK_ERR ("usbBulkBlkDevCreate: No MSC/SCSI/BULK-ONLY found\n", 0, 0, 0, 0, 0, 0); return (NULL); } OSS_MUTEX_TAKE (bulkDevMutex, OSS_BLOCK); /* Initialise the standard block device structure for use with file systems */ pBulkDev->blkDev.bd_blkRd = (FUNCPTR) usbBulkDevBlkRd; pBulkDev->blkDev.bd_blkWrt = (FUNCPTR) usbBulkDevBlkWrt; pBulkDev->blkDev.bd_ioctl = (FUNCPTR) usbBulkDevIoctl; pBulkDev->blkDev.bd_reset = (FUNCPTR) usbBulkDevReset; pBulkDev->blkDev.bd_statusChk = (FUNCPTR) usbBulkDevStatusChk; pBulkDev->blkDev.bd_retry = 1; pBulkDev->blkDev.bd_mode = O_RDWR; pBulkDev->blkDev.bd_readyChanged = TRUE; /* * Read out the standard INQUIRY information from the device, mainly to * check whether the media is removable or not. */ pBulkDev->bulkInData = inquiry; if ( usbBulkFormScsiCmd (pBulkDev, USB_SCSI_INQUIRY, NULL, NULL) != OK ) { USB_BULK_ERR ("usbBulkBlkDevCreate: Error forming command\n", 0, 0, 0, 0, 0, 0); OSS_MUTEX_RELEASE (bulkDevMutex); return (NULL); } if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS ) { USB_BULK_ERR ("usbBulkBlkDevCreate: Error executing USB_SCSI_INQUIRY "\ "command\n", 0, 0, 0, 0, 0, 0); OSS_MUTEX_RELEASE (bulkDevMutex); return (NULL); } /* Check the media type bit */ if (inquiry[1] & USB_SCSI_INQUIRY_RMB_BIT) { pBulkDev->blkDev.bd_removable = TRUE; } else { pBulkDev->blkDev.bd_removable = FALSE; } /* read the block size and capacity of device (in terms of blocks) */ if ( usbBulkFormScsiCmd (pBulkDev, USB_SCSI_READ_CAPACITY, NULL, NULL) != OK ) { OSS_MUTEX_RELEASE (bulkDevMutex); return (NULL); } /* * Read Capacity command will usually return CHECK CONDITION status * very first time, just try again. */ if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS ) { if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS ) { USB_BULK_ERR ("usbBulkBlkDevCreate: Read Capacity command failed\n", 0, 0, 0, 0, 0, 0); OSS_MUTEX_RELEASE (bulkDevMutex); return (NULL); } } /* SCSI response is in BIG endian format. Swap it to get correct value */ pBulkDev->numBlks = USB_SCSI_SWAP_32(*((UINT32 *)inquiry)); pBulkDev->blkOffset = blkOffset; if ( numBlks == NULL ) pBulkDev->blkDev.bd_nBlocks = (pBulkDev->numBlks - blkOffset); else pBulkDev->blkDev.bd_nBlocks = numBlks; pBulkDev->blkDev.bd_bytesPerBlk = USB_SCSI_SWAP_32(*((UINT32 *)(inquiry+4))); /* determine which type of SCSI read command is implemnted */ if ( (flags & USB_SCSI_FLAG_READ_WRITE10) == 1 ) pBulkDev->read10Able = TRUE; else pBulkDev->read10Able = FALSE; /* * Read the first block off the disk to determine where the logical * disk begins. This code was adapted from usrAta.c. It trys * to determine if the first block is a partition table. If so, it * pulls the offset into the logical disk and stores it in the BLK_DEVs * offset paramter. If not it assumes the first block (LBA = 0) is the * beginning of the logical disk. */ usbBulkDevBlkRd ((BLK_DEV *) pBulkDev, 0, /* read LBA #0 */ 1, /* read only this block */ blk0Buffer); /* get the offset into the partition table */ pPart = (DOS_PART_TBL *)&blk0Buffer[DOS_BOOT_PART_TBL]; for (ix = 0; ix < 4; ix++) /* active primary DOS partition */ { if (pPart->dospt_status == 0x80) if ((pPart->dospt_type == 0x01) || (pPart->dospt_type == 0x04) || (pPart->dospt_type == 0x06)) { offset = pPart->dospt_absSec; break; } pPart++; } pBulkDev->blkOffset = offset; if ( numBlks == NULL ) pBulkDev->blkDev.bd_nBlocks = (pBulkDev->numBlks - offset); else pBulkDev->blkDev.bd_nBlocks = numBlks; pBulkDev->blkDev.bd_bytesPerBlk = USB_SCSI_SWAP_32(*((UINT32 *)(inquiry+4))); OSS_MUTEX_RELEASE (bulkDevMutex); return (&pBulkDev->blkDev); } /***************************************************************************** usbBulkDevBlkRd - routine to read one or more blocks from the device.** This routine reads the specified physical sector(s) from a specified* physical device. Typically called by file system when data is to be* read from a particular device.** RETURNS: OK on success, or ERROR if failed to read from device*/LOCAL STATUS usbBulkDevBlkRd ( BLK_DEV * pBlkDev, /* pointer to bulk device */ int blkNum, /* logical block number */ int numBlks, /* number of blocks to read */ char * pBuf /* store for data */ ) { pUSB_BULK_DEV pBulkDev = (USB_BULK_DEV *)pBlkDev; UINT readType; /* Ensure that the device has not been removed during a transfer */ if ( pBulkDev->connected == FALSE ) return ERROR; USB_BULK_DEBUG ("usbBulkDevBlkRd: Number of blocks = %d, Starting blk = %d\n", numBlks, blkNum, 0, 0, 0, 0); OSS_MUTEX_TAKE (bulkDevMutex, OSS_BLOCK); /* intialise the pointer to store bulk in data */ pBulkDev->bulkInData = (UINT8 *)pBuf ; if (pBulkDev->read10Able) readType = USB_SCSI_READ10; else readType = USB_SCSI_READ6; if ( usbBulkFormScsiCmd (pBulkDev, readType, blkNum, numBlks) != OK ) { OSS_MUTEX_RELEASE (bulkDevMutex); return (ERROR); } if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS ) { OSS_MUTEX_RELEASE (bulkDevMutex); return (ERROR); } OSS_MUTEX_RELEASE (bulkDevMutex); return (OK); }/***************************************************************************** usbBulkDevBlkWrt - routine to write one or more blocks to the device.** This routine writes the specified physical sector(s) to a specified physical* device.** RETURNS: OK on success, or ERROR if failed to write to device*/LOCAL STATUS usbBulkDevBlkWrt ( BLK_DEV * pBlkDev, /* pointer to bulk device */ int blkNum, /* logical block number */ int numBlks, /* number of blocks to write */ char * pBuf /* data to be written */ ) { pUSB_BULK_DEV pBulkDev = (USB_BULK_DEV *)pBlkDev; UINT writeType; /* Ensure that the device has not been removed during a transfer */ if ( pBulkDev->connected == FALSE ) return ERROR; USB_BULK_DEBUG ("usbBulkDevBlkWrt: Number of blocks = %d, Starting blk = %d\n", numBlks, blkNum, 0, 0, 0, 0); OSS_MUTEX_TAKE (bulkDevMutex, OSS_BLOCK); /* initialise the pointer to fetch bulk out data */ pBulkDev->bulkOutData = (UINT8 *)pBuf; if (pBulkDev->read10Able) writeType = USB_SCSI_WRITE10; else writeType = USB_SCSI_WRITE6; if ( usbBulkFormScsiCmd (pBulkDev, writeType, blkNum, numBlks) != OK ) { OSS_MUTEX_RELEASE (bulkDevMutex); return (ERROR); } if ( usbBulkCmdExecute (pBulkDev) != USB_COMMAND_SUCCESS ) { OSS_MUTEX_RELEASE (bulkDevMutex); return (ERROR); } OSS_MUTEX_RELEASE (bulkDevMutex); return (OK); }/***************************************************************************** usbBulkIrpCallback - Invoked upon IRP completion** Examines the status of the IRP submitted. * ** RETURNS: N/A*/LOCAL void usbBulkIrpCallback ( pVOID p /* pointer to the IRP submitted */ ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSB_BULK_DEV pBulkDev = pIrp->userPtr; /* check whether the IRP was for bulk out/ bulk in / status transport */ if (pIrp == &(pBulkDev->outIrp)) { if (pIrp->result == OK) /* check the result of IRP */ { USB_BULK_DEBUG ("usbBulkIrpCallback: Num of Bytes transferred on "\ "out pipe %d\n", pIrp->bfrList[0].actLen, 0, 0, 0, 0, 0); } else { USB_BULK_ERR ("usbBulkIrpCallback: Irp failed on Bulk Out %x \n", pIrp->result, 0, 0, 0, 0, 0); /* Clear HALT Feature on Bulk out Endpoint */ if ((usbdFeatureClear (usbdHandle, pBulkDev->bulkDevId, USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, (pBulkDev->outEpAddress & 0x0F))) != OK) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -