📄 usb_host_ms_drv.c
字号:
/* MODE SENSE6 All mode command (1ah)*/
USB_HOST_MS_RESULT USB_Host_Ms_Mode_Sense6_All_Mode(kal_uint8 lun)
{
kal_bool b_send_result;
kal_uint32 event_group;
USB_HOST_MS_MEDIA_STATE media_state = g_UsbHostMs.media_info[lun].state;
kal_mem_set(g_usb_ms_cmd, 0, USBMS_MAX_CMD_LEN);
g_usb_ms_cmd[0] = USBMS_MODE_SENSE6;
g_usb_ms_cmd[2] = 0x3f;
g_usb_ms_cmd[4] = USBMS_MODE_SENSE6_DATA_LEN;
g_UsbHostMs.ms_cmd_data.lun = lun;
g_UsbHostMs.ms_cmd_data.cmd_len = USBMS_MODE_SENSE6_CMD_LEN;
g_UsbHostMs.ms_cmd_data.cmd_buff = g_usb_ms_cmd;
g_UsbHostMs.ms_cmd_data.data_len = USBMS_MODE_SENSE6_DATA_LEN;
g_UsbHostMs.ms_cmd_data.data_buff = g_usb_ms_data;
g_UsbHostMs.ms_cmd_data.data_dir = USB_HOST_MS_DATA_RECV;
b_send_result = USB_Host_Ms_Send_Cmd(&g_UsbHostMs.ms_cmd_data);
if((b_send_result==KAL_TRUE)&&(g_UsbHostMs.dev_attatch == KAL_TRUE))
{
/* when event is retrived, result has been got in data buffer */
kal_retrieve_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE|EVENT_USB_MS_DETATCH,
KAL_OR_CONSUME, &event_group, KAL_SUSPEND);
if(g_UsbHostMs.result == USB_HOST_MS_RESULT_OK)
{
/* determine it is write protect or not */
if((g_usb_ms_data[2]&0x80)!=0)
g_UsbHostMs.media_info[lun].state = USB_HOST_MS_MEDIA_STATE_WR_PROTECT;
else
g_UsbHostMs.media_info[lun].state = USB_HOST_MS_MEDIA_STATE_READY;
}
else if(g_UsbHostMs.result == USB_HOST_MS_RESULT_CSW_FAIL)
{
/* translate result to request sense result */
/* application can treat it as result OK is request sense reault is OK */
g_UsbHostMs.result = USB_Host_Ms_Request_Sense(lun);
}
/* else USB_HOST_MS_RESULT_TIMEOUT and USB_HOST_MS_RESULT_STALL do not handle it */
if(media_state!=g_UsbHostMs.media_info[lun].state)
{
//g_UsbHostMs.b_state_change = KAL_TRUE;
g_UsbHostMs.media_state_change |= (1<<lun);
}
}
else
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
}
return g_UsbHostMs.result;
}
/* READ command (28h)*/
/* The received data will be stored in data parameter */
USB_HOST_MS_RESULT USB_Host_Ms_Read(kal_uint8 lun, kal_uint32 sec_start, kal_uint16 sec_num, kal_uint8* data)
{
kal_bool b_send_result;
kal_uint32 event_group;
kal_mem_set(g_usb_ms_cmd, 0, USBMS_MAX_CMD_LEN);
g_usb_ms_cmd[0] = USBMS_READ;
g_usb_ms_cmd[2] = (sec_start>>24)&0xff;
g_usb_ms_cmd[3] = (sec_start>>16)&0xff;
g_usb_ms_cmd[4] = (sec_start>>8)&0xff;
g_usb_ms_cmd[5] = sec_start&0xff;
g_usb_ms_cmd[7] = (sec_num>>8)&0xff;
g_usb_ms_cmd[8] = sec_num&0xff;
g_UsbHostMs.ms_cmd_data.lun = lun;
g_UsbHostMs.ms_cmd_data.cmd_len = USBMS_READ_CMD_LEN;
g_UsbHostMs.ms_cmd_data.cmd_buff = g_usb_ms_cmd;
g_UsbHostMs.ms_cmd_data.data_len = sec_num*g_UsbHostMs.media_info[lun].sec_size;
g_UsbHostMs.ms_cmd_data.data_buff = data;
g_UsbHostMs.ms_cmd_data.data_dir = USB_HOST_MS_DATA_RECV;
b_send_result = USB_Host_Ms_Send_Cmd(&g_UsbHostMs.ms_cmd_data);
if((b_send_result==KAL_TRUE)&&(g_UsbHostMs.dev_attatch == KAL_TRUE))
{
/* when event is retrived, result has been got in data buffer */
kal_retrieve_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE|EVENT_USB_MS_DETATCH,
KAL_OR_CONSUME, &event_group, KAL_SUSPEND);
g_UsbHostMs.b_rw_result = KAL_FALSE;
if(g_UsbHostMs.result == USB_HOST_MS_RESULT_OK)
{
/* In the application layer, result may be OK because of next request sense result is OK */
/* This is used to indicate whether the whole data are read back successfully */
g_UsbHostMs.b_rw_result = KAL_TRUE;
}
else if(g_UsbHostMs.result == USB_HOST_MS_RESULT_CSW_FAIL)
{
/* translate result to request sense result */
/* application can treat it as result OK is request sense reault is OK */
g_UsbHostMs.result = USB_Host_Ms_Request_Sense(lun);
}
/* else USB_HOST_MS_RESULT_TIMEOUT and USB_HOST_MS_RESULT_STALL do not handle it */
}
else
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
}
return g_UsbHostMs.result;
}
/* WRITE command (2ah)*/
/* The data parameter will be sent out */
USB_HOST_MS_RESULT USB_Host_Ms_Write(kal_uint8 lun, kal_uint32 sec_start, kal_uint16 sec_num, kal_uint8* data)
{
kal_bool b_send_result;
kal_uint32 event_group;
kal_mem_set(g_usb_ms_cmd, 0, USBMS_MAX_CMD_LEN);
g_usb_ms_cmd[0] = USBMS_WRITE;
g_usb_ms_cmd[2] = (sec_start>>24)&0xff;
g_usb_ms_cmd[3] = (sec_start>>16)&0xff;
g_usb_ms_cmd[4] = (sec_start>>8)&0xff;
g_usb_ms_cmd[5] = sec_start&0xff;
g_usb_ms_cmd[7] = (sec_num>>8)&0xff;
g_usb_ms_cmd[8] = sec_num&0xff;
g_UsbHostMs.ms_cmd_data.lun = lun;
g_UsbHostMs.ms_cmd_data.cmd_len = USBMS_WRITE_CMD_LEN;
g_UsbHostMs.ms_cmd_data.cmd_buff = g_usb_ms_cmd;
g_UsbHostMs.ms_cmd_data.data_len = sec_num*g_UsbHostMs.media_info[lun].sec_size;
g_UsbHostMs.ms_cmd_data.data_buff = data;
g_UsbHostMs.ms_cmd_data.data_dir = USB_HOST_MS_DATA_SEND;
b_send_result = USB_Host_Ms_Send_Cmd(&g_UsbHostMs.ms_cmd_data);
if((b_send_result==KAL_TRUE)&&(g_UsbHostMs.dev_attatch == KAL_TRUE))
{
/* when event is retrived, result has been got in data buffer */
kal_retrieve_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE|EVENT_USB_MS_DETATCH,
KAL_OR_CONSUME, &event_group, KAL_SUSPEND);
g_UsbHostMs.b_rw_result = KAL_FALSE;
if(g_UsbHostMs.result == USB_HOST_MS_RESULT_OK)
{
/* In the application layer, result may be OK because of next request sense result is OK */
/* This is used to indicate whether the whole data are written out successfully */
g_UsbHostMs.b_rw_result = KAL_TRUE;
}
else if(g_UsbHostMs.result == USB_HOST_MS_RESULT_CSW_FAIL)
{
/* translate result to request sense result */
/* application can treat it as result OK is request sense reault is OK */
g_UsbHostMs.result = USB_Host_Ms_Request_Sense(lun);
}
/* else USB_HOST_MS_RESULT_TIMEOUT and USB_HOST_MS_RESULT_STALL do not handle it */
}
else
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
}
return g_UsbHostMs.result;
}
/* Construct the CBW format, and send command to scheduling queue*/
static kal_bool USB_Host_Ms_Send_Cmd(USBH_Ms_Cmd_Struct *ms_cmd)
{
UsbMs_CBW *CBW = (UsbMs_CBW*)g_UsbHostMs.CBWdata;
/* construct CBW according to to the aommand request */
CBW->dCBWSignature = 0x43425355;
CBW->dCBWTag = g_UsbHostMs.CBWdata[1] +1; /* increment tag in each command */
CBW->dCBWDataTransferLength = ms_cmd->data_len;
if(ms_cmd->data_dir==USB_HOST_MS_DATA_RECV)
CBW->bmCBWFlags = USBMS_DIR_IN;
else
CBW->bmCBWFlags = USBMS_DIR_OUT;
CBW->bCBWLUN = ms_cmd->lun;
CBW->bCBWCBLength = ms_cmd->cmd_len;
/* the CBWCB comes from each command. ex READ, WRITE, TEST UNIT READY.*/
/* the format is different according to each command */
kal_mem_set(CBW->CBWCB, 0, USBMS_CBW_LENGTH);
kal_mem_cpy(CBW->CBWCB, ms_cmd->cmd_buff, ms_cmd->cmd_len);
/* assign the data buffer */
/* In OUT direction, the data will be sent during transfer */
/* In IN direction, the received data will be stored in this buffer */
g_UsbHostMs.data = ms_cmd->data_buff;
g_UsbHostMs.data_length = ms_cmd->data_len;
g_UsbHostMs.data_dir = ms_cmd->data_dir;
/* Note that in the recv direction, receive buffer must be pad to multiple of 4 */
if((g_UsbHostMs.data_dir==USB_HOST_MS_DATA_RECV)&&(g_UsbHostMs.data_length&0x3))
{
g_UsbHostMs.data_length = g_UsbHostMs.data_length
+ (4-(USBMS_REQUESTSENSE_DATA_LEN & 0x3));;
}
g_UsbHostMs.ms_state = USB_HOST_MS_CBW;
/* Queue command to scheduling buffer*/
/* Note that CBW, DATA, CSW transfer is handled in HISR level,
And when the transfer complete, it will retrive the event to wake up waiting task */
return USB_HCD_Send_Req(g_UsbHostMs.ep_out_index, USBMS_CBW_LENGTH, CBW);
}
/************************************************************
ms class handler. Note that it is executed in OTG HIST context
*************************************************************/
/* This is callback function for both control EP and bulk EP */
/* The control EP part handles class specific EP0 command
The bulk EP part handles CBW, DATA, CSW state machine */
static void USB_Host_Ms_Hdlr(USB_HCD_STATUS result, kal_uint32 param)
{
if(g_UsbHostMs.ms_cmd != USB_HOST_MS_EP0_CMD_NONE)
{
USB_Host_Ms_Ctrl_EP_Hdlr(result, param);
}
else
{
USB_Host_Ms_Bulk_EP_Hdlr(result, param);
}
}
/* handler for control endpoint */
/* It handles both standard and class specific EP0 command*/
static void USB_Host_Ms_Ctrl_EP_Hdlr(USB_HCD_STATUS result, kal_uint32 param)
{
/* store the command because it will be chaneg immediatly*/
USB_HOST_MS_EP0_CMD ms_cmd = g_UsbHostMs.ms_cmd;
kal_bool tr_result;
/* Unless another EP0 command is issued, the command should be set to NONE*/
g_UsbHostMs.ms_cmd = USB_HOST_MS_EP0_CMD_NONE;
if(result!=USB_HCD_OK)
{
/* translate the result */
/* for EP0 error, the handler dose not do error handling,
the error handling is done in the upper layer state */
if(result == USB_HCD_STALL)
g_UsbHostMs.result = USB_HOST_MS_RESULT_STALL;
else
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
}
else
{
/* result is OK */
switch(ms_cmd)
{
case USB_HOST_MS_EP0_CMD_RESET:
g_UsbHostMs.result = USB_HOST_MS_RESULT_OK;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
break;
case USB_HOST_MS_EP0_CMD_GET_LUN:
g_UsbHostMs.result = USB_HOST_MS_RESULT_OK;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
break;
case USB_HOST_MS_EP0_CMD_CLEAR_STALL_IN:
case USB_HOST_MS_EP0_CMD_CLEAR_STALL_OUT:
/* Clear IN or clear OUT stall are completed,
The next action is determined according to the previous state before STALL*/
if(g_UsbHostMs.ms_state==USB_HOST_MS_CBW_CLEAR_STALL)
{
/* The CBW is stalled. Do not issue DATA or CSW any more.
Return STALL result and let upper layer state machine handle it */
g_UsbHostMs.result = USB_HOST_MS_RESULT_STALL;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
}
else if(g_UsbHostMs.ms_state==USB_HOST_MS_DATA_CLEAR_STALL)
{
/* DATA is stalled. Clear STALL and attepmt to receive CSW */
/* Send CSW */
tr_result = USB_HCD_Recv_Req(g_UsbHostMs.ep_in_index, sizeof(g_UsbHostMs.CSW)/sizeof(kal_uint8), &g_UsbHostMs.CSW);
if(tr_result==KAL_TRUE)
{
g_UsbHostMs.ms_state = USB_HOST_MS_CSW;
}
else
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
}
}
else if(g_UsbHostMs.ms_state==USB_HOST_MS_CSW_CLEAR_STALL)
{
/* CSW is stalled. Clear STALL and attepmt to receive CSW */
/* send CSW */
tr_result = USB_HCD_Recv_Req(g_UsbHostMs.ep_in_index, sizeof(g_UsbHostMs.CSW)/sizeof(kal_uint8), &g_UsbHostMs.CSW);
if(tr_result==KAL_FALSE)
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
}
}
else
{
/* In all other states, it should not come to EP0 handler */
EXT_ASSERT(0, ms_cmd, g_UsbHostMs.ms_state, 0);
}
break;
}
}
}
/* handler for ctrl endpoint */
/* It handles CBW, DATA, CSW state machine */
static void USB_Host_Ms_Bulk_EP_Hdlr(USB_HCD_STATUS result, kal_uint32 param)
{
if(g_UsbHostMs.ms_state == USB_HOST_MS_CBW)
{
USB_Host_Ms_CBW_Hdler(result, param);
}
else if(g_UsbHostMs.ms_state == USB_HOST_MS_DATA)
{
USB_Host_Ms_DATA_Hdler(result, param);
}
else if((g_UsbHostMs.ms_state == USB_HOST_MS_CSW) || (g_UsbHostMs.ms_state == USB_HOST_MS_CSW_CLEAR_STALL))
{
USB_Host_Ms_CSW_Hdler(result, param);
}
else
{
/* Note that in USB_HOST_MS_CBW_CLEAR_STALL and USB_HOST_MS_DATA_CLEAR_STALL state,
only ctrl EP handler should be called, but not enter this bulk EP handler*/
EXT_ASSERT(0, g_UsbHostMs.ms_state, 0, 0);
}
}
/* Ctrl EP CBW handler, handle the state mcahine */
static void USB_Host_Ms_CBW_Hdler(USB_HCD_STATUS result, kal_uint32 param)
{
kal_bool tr_result;
if(result==USB_HCD_OK)
{
/* chek the real sent out length */
if(param!=USBMS_CBW_LENGTH)
EXT_ASSERT(0, param, 0, 0);
if(g_UsbHostMs.data_length !=0)
{
/* DATA state should be the following state */
/* Since data length is not zero, data direction must not NONE */
if(g_UsbHostMs.data_dir == USB_HOST_MS_DATA_NONE)
EXT_ASSERT(0, g_UsbHostMs.data_dir, g_UsbHostMs.data_length, 0);
if(g_UsbHostMs.data_dir ==USB_HOST_MS_DATA_RECV)
{
/* Receive data */
if(g_UsbHostMs.data_length > USBMS_MAX_DATA_LENGTH)
{
/* DMA length has limit, so each transfer request should should have size limit */
tr_result = USB_HCD_Recv_Req(g_UsbHostMs.ep_in_index, USBMS_MAX_DATA_LENGTH, g_UsbHostMs.data);
if(tr_result==KAL_TRUE)
{
g_UsbHostMs.sending_data_length = USBMS_MAX_DATA_LENGTH;
g_UsbHostMs.remain_data_length = g_UsbHostMs.data_length - USBMS_MAX_DATA_LENGTH;
g_UsbHostMs.sent_data_length = 0;
}
else
{
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE, KAL_OR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -