⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 massstorecommands.c

📁 LUFA (Lightweight USB Framework for AVRs) is my first foray into the world of USB. Originally based
💻 C
📖 第 1 页 / 共 2 页
字号:
					
			.SCSICommandData =
				{
					SCSI_CMD_REQUEST_SENSE,
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00,                   // Reserved
					sizeof(SCSI_Request_Sense_Response_t), // Allocation Length
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Wait until data received from the device */
	if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}

	/* Read the returned sense data into the buffer */
	if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)SensePtr)) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}	
	
	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

/** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the
 *  storage medium into a buffer.
 *
 *  \param LUNIndex      Index of the LUN inside the device the command is being addressed to
 *  \param BlockAddress  Start block address to read from
 *  \param Blocks        Number of blocks to read from the device
 *  \param BlockSize     Size in bytes of each block to read
 *  \param BufferPtr     Pointer to the buffer where the read data is to be written to
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,
                                  const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)
{
	uint8_t ReturnCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to read in the given blocks from the device */
	SCSICommandBlock = (CommandBlockWrapper_t)
		{
			.Header =
				{
					.Signature          = CBW_SIGNATURE,
					.Tag                = MassStore_Tag,
					.DataTransferLength = ((uint32_t)Blocks * BlockSize),
					.Flags              = COMMAND_DIRECTION_DATA_IN,
					.LUN                = LUNIndex,
					.SCSICommandLength  = 10
				},
					
			.SCSICommandData =
				{
					SCSI_CMD_READ_10,
					0x00,                   // Unused (control bits, all off)
					(BlockAddress >> 24),   // MSB of Block Address
					(BlockAddress >> 16),
					(BlockAddress >> 8),
					(BlockAddress & 0xFF),  // LSB of Block Address
					0x00,                   // Unused (reserved)
					0x00,                   // MSB of Total Blocks to Read
					Blocks,                 // LSB of Total Blocks to Read
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Wait until data received from the device */
	if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}

	/* Read the returned block data into the buffer */
	if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}	
	
	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

/** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the
 *  storage medium from a buffer.
 *
 *  \param LUNIndex      Index of the LUN inside the device the command is being addressed to
 *  \param BlockAddress  Start block address to write to
 *  \param Blocks        Number of blocks to write to in the device
 *  \param BlockSize     Size in bytes of each block to write
 *  \param BufferPtr     Pointer to the buffer where the write data is to be sourced from
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,
                                   const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)
{
	uint8_t ReturnCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to write the given blocks to the device */
	SCSICommandBlock = (CommandBlockWrapper_t)
		{
			.Header =
				{
					.Signature          = CBW_SIGNATURE,
					.Tag                = MassStore_Tag,
					.DataTransferLength = ((uint32_t)Blocks * BlockSize),
					.Flags              = COMMAND_DIRECTION_DATA_OUT,
					.LUN                = LUNIndex,
					.SCSICommandLength  = 10
				},
					
			.SCSICommandData =
				{
					SCSI_CMD_WRITE_10,
					0x00,                   // Unused (control bits, all off)
					(BlockAddress >> 24),   // MSB of Block Address
					(BlockAddress >> 16),
					(BlockAddress >> 8),
					(BlockAddress & 0xFF),  // LSB of Block Address
					0x00,                   // Unused (reserved)
					0x00,                   // MSB of Total Blocks to Write
					Blocks,                 // LSB of Total Blocks to Write
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Write the data to the device from the buffer */
	if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}	
	
	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

/** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept
 *  other commands.
 *
 *  \param LUNIndex      Index of the LUN inside the device the command is being addressed to
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)
{
	uint8_t ReturnCode = PIPE_RWSTREAM_NoError;	

	/* Create a CBW with a SCSI command to issue TEST UNIT READY command */
	SCSICommandBlock = (CommandBlockWrapper_t)
		{
			.Header =
				{
					.Signature          = CBW_SIGNATURE,
					.Tag                = MassStore_Tag,
					.DataTransferLength = 0,
					.Flags              = COMMAND_DIRECTION_DATA_IN,
					.LUN                = LUNIndex,
					.SCSICommandLength  = 6
				},
					
			.SCSICommandData =
				{
					SCSI_CMD_TEST_UNIT_READY,
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

/** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the
 *  given Logical Unit within the device.
 *
 *  \param LUNIndex     Index of the LUN inside the device the command is being addressed to
 *  \param CapacityPtr  Device capacity structure where the capacity data is to be stored
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)
{
	uint8_t ReturnCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to issue READ CAPACITY command */
	SCSICommandBlock = (CommandBlockWrapper_t)
		{
			.Header =
				{
					.Signature          = CBW_SIGNATURE,
					.Tag                = MassStore_Tag,
					.DataTransferLength = sizeof(SCSI_Capacity_t),
					.Flags              = COMMAND_DIRECTION_DATA_IN,
					.LUN                = LUNIndex,
					.SCSICommandLength  = 10
				},
					
			.SCSICommandData =
				{
					SCSI_CMD_READ_CAPACITY_10,
					0x00,                   // Reserved
					0x00,                   // MSB of Logical block address
					0x00,
					0x00,
					0x00,                   // LSB of Logical block address
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00,                   // Partial Medium Indicator
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Wait until data received from the device */
	if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}

	/* Read the returned capacity data into the buffer */
	if ((ReturnCode = MassStore_SendReceiveData(CapacityPtr)) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	  
	/* Endian-correct the read data */
	CapacityPtr->Blocks    = SwapEndian_32(CapacityPtr->Blocks);
	CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);
	
	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

/** Issues a SCSI Device Prevent/Allow Medium Removal command to the attached device, to lock the physical media from
 *  being removed. This is a legacy command for SCSI disks with removable storage (such as ZIP disks), but should still
 *  be issued before the first read or write command is sent.
 *
 *  \param LUNIndex        Index of the LUN inside the device the command is being addressed to
 *  \param PreventRemoval  Whether or not the LUN media should be locked to prevent removal or not
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval)
{
	uint8_t ReturnCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */
	SCSICommandBlock = (CommandBlockWrapper_t)
		{
			.Header =
				{
					.Signature          = CBW_SIGNATURE,
					.Tag                = MassStore_Tag,
					.DataTransferLength = 0,
					.Flags              = COMMAND_DIRECTION_DATA_OUT,
					.LUN                = LUNIndex,
					.SCSICommandLength  = 6
				},
					
			.SCSICommandData =
				{
					SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,
					0x00,                   // Reserved
					0x00,                   // Reserved
					PreventRemoval,         // Prevent flag
					0x00,                   // Reserved
					0x00                    // Unused (control)
				}
		};
	
	/* Send SCSI command to the attached device */
	MassStore_SendCommand();

	/* Read in the returned CSW from the device */
	if ((ReturnCode = MassStore_GetReturnedStatus()))
	{
		Pipe_Freeze();
		return ReturnCode;
	}
	
	return PIPE_RWSTREAM_NoError;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -