📄 usbbulkdevlib.c
字号:
if ((pInEp = findEndpoint (pBfr, actLength, USB_ENDPOINT_IN)) == NULL)
goto errorExit;
pBulkDev->outEpAddress = pOutEp->endpointAddress;
pBulkDev->inEpAddress = pInEp->endpointAddress;
/* Set the device configuration corresponding to MSC/SCSI/BULK-ONLY */
if ((usbdConfigurationSet (usbdHandle,
pBulkDev->bulkDevId,
pBulkDev->configuration,
pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT))
!= OK )
{
USB_BULK_ERR ("usbBulkPhysDevCreate: Unable to set device "\
"configuration \n", 0, 0, 0, 0, 0, 0);
goto errorExit;
}
else
{
USB_BULK_DEBUG ("usbBulkPhysDevCreate: Configuration set to 0x%x \n",
pBulkDev->configuration, 0, 0, 0, 0, 0);
}
/* Select interface
*
* NOTE: Some devices may reject this command, and this does not represent
* a fatal error. Therefore, we ignore the return status.
*/
usbdInterfaceSet (usbdHandle,
pBulkDev->bulkDevId,
pBulkDev->interface,
pBulkDev->altSetting);
maxPacketSize = *((pUINT8) &pOutEp->maxPacketSize) |
(*(((pUINT8) &pOutEp->maxPacketSize) + 1) << 8);
/* Create a Bulk-out pipe for the MSC/SCSI/BULK-ONLY device */
if (usbdPipeCreate (usbdHandle,
pBulkDev->bulkDevId,
pOutEp->endpointAddress,
pBulkDev->configuration,
pBulkDev->interface,
USB_XFRTYPE_BULK,
USB_DIR_OUT,
maxPacketSize,
0,
0,
&(pBulkDev->outPipeHandle))
!= OK)
{
USB_BULK_ERR ("usbBulkPhysDevCreate: Error creating bulk out pipe\n",
0, 0, 0, 0, 0, 0);
goto errorExit;
}
maxPacketSize = *((pUINT8) &pInEp->maxPacketSize) |
(*(((pUINT8) &pInEp->maxPacketSize) + 1) << 8);
/* Create a Bulk-in pipe for the MSC/SCSI/BULK-ONLY device */
if (usbdPipeCreate (usbdHandle,
pBulkDev->bulkDevId,
pInEp->endpointAddress,
pBulkDev->configuration,
pBulkDev->interface,
USB_XFRTYPE_BULK,
USB_DIR_IN,
maxPacketSize,
0,
0,
&(pBulkDev->inPipeHandle))
!= OK)
{
USB_BULK_ERR ("usbBulkPhysDevCreate: Error creating bulk in pipe\n",
0, 0, 0, 0, 0, 0);
goto errorExit;
}
/* 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;
if (blkOffset<=0)
{
/*
* 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 write
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -