📄 msddriver.c
字号:
csw->dCSWDataResidue += commandState->length;
// STALL the endpoint waiting for data
if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0) {
// Stall the OUT endpoint : host to device
USBD_Halt(MSDDriverDescriptors_BULKOUT);
trace_LOG(trace_INFO, "StaOUT ");
}
else {
// Stall the IN endpoint : device to host
USBD_Halt(MSDDriverDescriptors_BULKIN);
trace_LOG(trace_INFO, "StaIN ");
}
}
// Reset command state
commandState->state = 0;
}
return isCommandComplete;
}
//------------------------------------------------------------------------------
//! \brief Resets the state of the BOT driver
//! \param pBot Pointer to a S_bot instance
//! \see S_bot
//------------------------------------------------------------------------------
void MSDDriver_Reset()
{
trace_LOG(trace_INFO, "MSDReset ");
msdDriver.state = MSDDriver_STATE_READ_CBW;
msdDriver.waitResetRecovery = 0;
msdDriver.commandState.state = 0;
}
//------------------------------------------------------------------------------
// Callback re-implementation
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Invoked when a new SETUP request is received from the host. Forwards the
/// request to the Mass Storage device driver handler function.
/// \param request Pointer to a USBGenericRequest instance.
//------------------------------------------------------------------------------
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
{
MSDDriver_RequestHandler(request);
}
//------------------------------------------------------------------------------
/// Invoked when the configuration of the device changes. Resets the mass
/// storage driver.
//------------------------------------------------------------------------------
void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
{
if (cfgnum > 0) {
MSDDriver_Reset();
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Initializes a BOT driver and the associated USB driver.
//! \param pBot Pointer to a S_bot instance
//! \param pUsb USB driver to use
//! \param lun Pointer to a list of LUNs
//! \param numLuns Number of LUN in list
//! \see S_bot
//! \see S_usb
//------------------------------------------------------------------------------
void MSDDriver_Initialize(MSDLun *luns, unsigned char numLuns)
{
trace_LOG(trace_INFO, "I: MSD init\n\r");
// Command state initialization
msdDriver.commandState.state = 0;
msdDriver.commandState.postprocess = 0;
msdDriver.commandState.length = 0;
msdDriver.commandState.transfer.semaphore = 0;
// LUNs
msdDriver.luns = luns;
msdDriver.maxLun = (unsigned char) (numLuns - 1);
// Reset BOT driver
MSDDriver_Reset();
// Init the USB driver
USBDDriver_Initialize(&usbdDriver, &msdDriverDescriptors, 0);
USBD_Init();
}
//------------------------------------------------------------------------------
//! \brief Handler for incoming SETUP requests on default Control endpoint 0.
//!
//! Standard requests are forwarded to the STD_RequestHandler method.
//! \param pBot Pointer to a S_bot instance
//------------------------------------------------------------------------------
void MSDDriver_RequestHandler(const USBGenericRequest *request)
{
trace_LOG(trace_INFO, "NewReq ");
// Handle requests
switch (USBGenericRequest_GetRequest(request)) {
//---------------------
case USBGenericRequest_CLEARFEATURE:
//---------------------
trace_LOG(trace_INFO, "ClrFeat ");
switch (USBFeatureRequest_GetFeatureSelector(request)) {
//---------------------
case USBFeatureRequest_ENDPOINTHALT:
//---------------------
trace_LOG(trace_INFO, "Hlt ");
// Do not clear the endpoint halt status if the device is waiting
// for a reset recovery sequence
if (!msdDriver.waitResetRecovery) {
// Forward the request to the standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
}
else {
trace_LOG(trace_INFO, "No ");
}
USBD_Write(0, 0, 0, 0, 0);
break;
//------
default:
//------
// Forward the request to the standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
}
break;
//-------------------
case MSD_GET_MAX_LUN:
//-------------------
trace_LOG(trace_INFO, "gMaxLun ");
// Check request parameters
if ((request->wValue == 0)
&& (request->wIndex == 0)
&& (request->wLength == 1)) {
USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
}
else {
trace_LOG(trace_WARNING, "W: MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
break;
//-----------------------
case MSD_BULK_ONLY_RESET:
//-----------------------
trace_LOG(trace_INFO, "Rst ");
// Check parameters
if ((request->wValue == 0)
&& (request->wIndex == 0)
&& (request->wLength == 0)) {
// Reset the MSD driver
MSDDriver_Reset();
USBD_Write(0, 0, 0, 0, 0);
}
else {
trace_LOG(trace_WARNING, "W: MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
break;
//------
default:
//------
// Forward request to standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
break;
}
}
//------------------------------------------------------------------------------
//! \brief State machine for the BOT driver
//! \param pBot Pointer to a S_bot instance
//------------------------------------------------------------------------------
void MSDDriver_StateMachine(void)
{
MSDCommandState *commandState = &(msdDriver.commandState);
MSCbw *cbw = &(commandState->cbw);
MSCsw *csw = &(commandState->csw);
MSDTransfer *transfer = &(commandState->transfer);
unsigned char status;
// Identify current driver state
switch (msdDriver.state) {
//----------------------
case MSDDriver_STATE_READ_CBW:
//----------------------
// Start the CBW read operation
transfer->semaphore = 0;
status = USBD_Read(MSDDriverDescriptors_BULKOUT,
cbw,
MSD_CBW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
// Check operation result code
if (status == USBD_STATUS_SUCCESS) {
// If the command was successful, wait for transfer
msdDriver.state = MSDDriver_STATE_WAIT_CBW;
}
break;
//----------------------
case MSDDriver_STATE_WAIT_CBW:
//----------------------
// Check transfer semaphore
if (transfer->semaphore > 0) {
// Take semaphore and terminate transfer
transfer->semaphore--;
// Check if transfer was successful
if (transfer->status == USBD_STATUS_SUCCESS) {
trace_LOG(trace_INFO, "------------------------------\n\r");
// Process received command
msdDriver.state = MSDDriver_STATE_PROCESS_CBW;
}
else if (transfer->status == USBD_STATUS_RESET) {
trace_LOG(trace_INFO, "I: MSDDriver_StateMachine: Endpoint resetted\n\r");
msdDriver.state = MSDDriver_STATE_READ_CBW;
}
else {
trace_LOG(trace_WARNING, "W: MSDDriver_StateMachine: Failed to read CBW\n\r");
msdDriver.state = MSDDriver_STATE_READ_CBW;
}
}
break;
//-------------------------
case MSDDriver_STATE_PROCESS_CBW:
//-------------------------
// Check if this is a new command
if (commandState->state == 0) {
// Copy the CBW tag
csw->dCSWTag = cbw->dCBWTag;
// Check that the CBW is 31 bytes long
if ((transfer->transferred != MSD_CBW_SIZE) ||
(transfer->remaining != 0)) {
trace_LOG(trace_WARNING, "W: MSDDriver_StateMachine: Invalid CBW (too short or too long)\n\r");
// Wait for a reset recovery
msdDriver.waitResetRecovery = 1;
// Halt the Bulk-IN and Bulk-OUT pipes
USBD_Halt(MSDDriverDescriptors_BULKOUT);
USBD_Halt(MSDDriverDescriptors_BULKIN);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
msdDriver.state = MSDDriver_STATE_READ_CBW;
}
// Check the CBW Signature
else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
trace_LOG(trace_WARNING, "W: MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");
// Wait for a reset recovery
msdDriver.waitResetRecovery = 1;
// Halt the Bulk-IN and Bulk-OUT pipes
USBD_Halt(MSDDriverDescriptors_BULKOUT);
USBD_Halt(MSDDriverDescriptors_BULKIN);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
msdDriver.state = MSDDriver_STATE_READ_CBW;
}
else {
// Pre-process command
MSDDriver_PreProcessCommand();
}
}
// Process command
if (csw->bCSWStatus == MSDDriver_STATUS_SUCCESS) {
if (MSDDriver_ProcessCommand()) {
// Post-process command if it is finished
MSDDriver_PostProcessCommand();
msdDriver.state = MSDDriver_STATE_SEND_CSW;
}
trace_LOG(trace_INFO, "\n\r");
}
break;
//----------------------
case MSDDriver_STATE_SEND_CSW:
//----------------------
// Set signature
csw->dCSWSignature = MSD_CSW_SIGNATURE;
// Start the CSW write operation
status = USBD_Write(MSDDriverDescriptors_BULKIN,
csw,
MSD_CSW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
// Check operation result code
if (status == USBD_STATUS_SUCCESS) {
trace_LOG(trace_INFO, "SendCSW ");
// Wait for end of transfer
msdDriver.state = MSDDriver_STATE_WAIT_CSW;
}
break;
//----------------------
case MSDDriver_STATE_WAIT_CSW:
//----------------------
// Check transfer semaphore
if (transfer->semaphore > 0) {
// Take semaphore and terminate transfer
transfer->semaphore--;
// Check if transfer was successful
if (transfer->status == USBD_STATUS_RESET) {
trace_LOG(trace_INFO, "MSDDriver_StateMachine: Endpoint resetted\n\r");
}
else if (transfer->status == USBD_STATUS_ABORTED) {
trace_LOG(trace_WARNING, "W: MSDDriver_StateMachine: Failed to send CSW\n\r");
}
else {
trace_LOG(trace_INFO, "ok");
}
// Read new CBW
msdDriver.state = MSDDriver_STATE_READ_CBW;
}
break;
}
}
//------------------------------------------------------------------------------
/// Starts a remote wake-up sequence if the host has explicitely enabled it
/// by sending the appropriate SET_FEATURE request.
//------------------------------------------------------------------------------
void MSDDriver_RemoteWakeUp(void)
{
// Remote wake-up has been enabled
if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
USBD_RemoteWakeUp();
}
// Remote wake-up NOT enabled
else {
trace_LOG(trace_WARNING, "-W- MSDDriver_RemoteWakeUp: Host has not enabled remote wake-up\n\r");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -