📄 usbms_state.c
字号:
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2005
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*****************************************************************************
*
* Filename:
* ---------
* usbms_state.c
*
* Project:
* --------
* Maui_Software
*
* Description:
* ------------
* This file implements usb mass storage state machine
*
* Author:
* -------
* -------
* -------
*
*============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*============================================================================
****************************************************************************/
#include "drv_comm.h"
#include "stack_common.h"
#include "stack_msgs.h"
#include "app_ltlcom.h"
#include "drvsignals.h"
#include "usb_comm.h"
#include "usb_drv.h"
#include "usb.h"
#include "usbms_utils.h"
#include "usbms_drv.h"
#include "usbms_adap.h"
#include "usbms_state.h"
#include "usb_custom.h"
/* sense code */
static const kal_uint8 senseOk[] = {0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const kal_uint8 senseNoMedia[] = {0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00};
static const kal_uint8 senseMediaChanged[] = {0x70, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00};
static const kal_uint8 senseInvalidFieldInCDB[] = {0x70, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00};
#ifdef __P_PROPRIETARY_COPYRIGHT__
static const kal_uint8 senseDataProtect[] = {0x70, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
static USB_MS_ERROR USB_Ms_Recv_Data(local_para_struct *buf);
static USB_MS_ERROR USB_Ms_Transmit_Data(local_para_struct *buf);
static void USB_Ms_Generate_Csw(UsbMs_CSW *CSW, UsbMs_CBW *CBW);
static void USB_Ms_MemInverse(void *src, void *dst, kal_uint16 len);
static void USB_Ms_Cmd(void *data);
static void USB_Ms_Cmd_Format(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_State_Checkmedia_Exist(kal_uint8 LUN);
static void USB_Ms_Cmd_Inquiry(UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Test_Unit_Ready(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Prev_Media_Removal(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Read_Capacity(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Read_FormatCapacity(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_RequestSense(UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Verify(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_ModeSense6(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Unknown(UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Read(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Handle_Read(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Read_Fail_Handler(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Cmd_Write(kal_uint8 LUN, UsbMs_CBW *CBW);
static void USB_Ms_Handle_Write(kal_uint8 LUN, UsbMs_CBW *CBW, kal_uint8 sector_num);
#ifdef __P_PROPRIETARY_COPYRIGHT__
static kal_bool USB_Ms_Search_Item(kal_uint32* data_items, kal_uint32 data_size, kal_uint32 search_value, kal_uint32 *p_index);
static void USB_Ms_Sort_Index_Items(kal_uint32* items, kal_uint32 num);
static kal_bool USB_Ms_Check_Read_Protect(kal_uint8 LUN, kal_uint32 LBA, kal_uint32 sec_num);
static kal_bool USB_Ms_Check_Second_Read_Protect(kal_uint8 LUN, kal_uint32 LBA, kal_uint32 sec_num);
static void USB_Ms_Update_Read_Protect(kal_uint8 LUN, kal_uint32 LBA, kal_uint32 sec_num);
#endif
/************************************************************
Tx/Rx path state machine functions
*************************************************************/
void USB_Ms_State_Main(ilm_struct *p_recv_ilm)
{
USB_MS_ERROR ms_error;
switch(p_recv_ilm->msg_id)
{
case MSG_ID_USB_MSDRV_REC_DONE_CONF:
/* receive data from DMA callback*/
ms_error = USB_Ms_Recv_Data(p_recv_ilm->local_para_ptr);
if(ms_error != USB_MS_ERROR_OK)
{
EXT_ASSERT(0, (kal_uint32)ms_error, 0, 0 );
}
break;
case MSG_ID_USB_MSDRV_TRX_DONE_CONF:
/* transmitted data from DMA callback*/
ms_error =USB_Ms_Transmit_Data(p_recv_ilm->local_para_ptr);
if(ms_error != USB_MS_ERROR_OK)
{
EXT_ASSERT(0, (kal_uint32)ms_error, 0, 0);
}
break;
case MSG_ID_USB_RESET_IND:
/* reset from reset signal or class specific EP0 RESET command*/
g_UsbMS.nState = USBMS_IDLE;
USB_Ms_BuildRx(g_UsbMS.CBWdata, 31);
g_UsbMS.is_send_usb_reset_ilm = KAL_TRUE;
break;
}
}
/*receive path state machine*/
static USB_MS_ERROR USB_Ms_Recv_Data(local_para_struct *buf)
{
UsbMs_CBW *CBW;
kal_uint8 *CBWCB;
kal_uint8 sector_num;
usb_ms_rec_done_conf_struct *ptr=(usb_ms_rec_done_conf_struct *)buf;
USB_MS_ERROR re_value = USB_MS_ERROR_OK;
switch(g_UsbMS.nState)
{
case USBMS_IDLE:
if (ptr->nBytesRecv != 31)
{
EXT_ASSERT(0, ptr->nBytesRecv, 0, 0);
}
USB_Ms_Cmd(g_UsbMS.CBWdata);
break;
case USBMS_RX:
CBW = (UsbMs_CBW*)g_UsbMS.CBWdata;
CBWCB = (kal_uint8 *)CBW->CBWCB;
if (CBWCB[0] == USBMS_WRITE)
{
sector_num = ptr->nBytesRecv/512;
USB_Ms_Handle_Write(g_UsbMS.current_LUN, CBW, sector_num);
}
else /*if (CBWCB[0] == USBMS_CMD_Write)*/
{
EXT_ASSERT(0, (kal_uint32)CBW->CBWCB[0], 0, 0);
}
break;
case USBMS_GETNEXTCMD:
re_value = USB_MS_ERROR_RX_GETNEXTCMD;
break;
case USBMS_ACK:
re_value = USB_MS_ERROR_RX_ACK;
break;
case USBMS_TX:
re_value = USB_MS_ERROR_RX_TX;
break;
default:
EXT_ASSERT(0, (kal_uint32)g_UsbMS.nState, 0, 0);
break;
}
return re_value;
}
/*transmit path state machine*/
static USB_MS_ERROR USB_Ms_Transmit_Data(local_para_struct *buf)
{
UsbMs_CBW *CBW = (UsbMs_CBW*)g_UsbMS.CBWdata;
USB_MS_ERROR re_value = USB_MS_ERROR_OK;
switch(g_UsbMS.nState)
{
case USBMS_GETNEXTCMD:
g_UsbMS.nState = USBMS_IDLE;
USB_Ms_BuildRx(g_UsbMS.CBWdata, 31);
break;
case USBMS_ACK:
/*Send CSW*/
g_UsbMS.nState = USBMS_GETNEXTCMD;
USB_Ms_Generate_Csw(&g_UsbMS.CSW, CBW);
USB_Ms_BuildTx(&g_UsbMS.CSW, 13);
break;
case USBMS_TX:
if (CBW->CBWCB[0] == USBMS_READ)
{
USB_Ms_Handle_Read(g_UsbMS.current_LUN, CBW);
}
else
{
EXT_ASSERT(0, (kal_uint32)CBW->CBWCB[0], 0, 0);
}
break;
case USBMS_IDLE:
re_value = USB_MS_ERROR_TX_IDLE;
break;
case USBMS_RX:
re_value = USB_MS_ERROR_TX_RX;
break;
default:
EXT_ASSERT(0, (kal_uint32)g_UsbMS.nState, 0, 0);
break;
}
return re_value;
}
/************************************************************
utility functions
*************************************************************/
/* generate CSW element according to CBW and kept status */
static void USB_Ms_Generate_Csw(UsbMs_CSW *CSW, UsbMs_CBW *CBW)
{
// USB_Ms_Dbg_Trace(USB_DBG_GENERATE_CSW, 0);
CSW->dCSWSignature = 0x53425355;
CSW->dCSWTag = CBW->dCBWTag;
CSW->dCSWDataResidue = g_UsbMS.CSWDataResidue;
CSW->bmCSWStatus = g_UsbMS.CSWStatusError;
g_UsbMS.CSWStatusError = KAL_FALSE;
g_UsbMS.CSWDataResidue = 0;
}
/* inverse scr to dst, total len*/
static void USB_Ms_MemInverse(void *src, void *dst, kal_uint16 len)
{
kal_uint8 index;
kal_uint8 *li_data = (kal_uint8 *)src;
kal_uint8 *bi_data = (kal_uint8 *)dst;
li_data+=(len-1);
for(index =0; index<len; index++)
*(bi_data+index) = *(li_data-index);
}
/************************************************************
CBW parse command functions
*************************************************************/
/* parse CBW command */
static void USB_Ms_Cmd(void *data)
{
UsbMs_CBW *CBW = (UsbMs_CBW *)data;
kal_uint8 *CBWCB;
CBWCB = (kal_uint8*)CBW->CBWCB;
if( (CBW->dCBWSignature != 0x43425355) || (CBW->bCBWLUN > g_UsbMS.max_LUN) )
{
USB_CtrlEPStall(g_UsbMS.txpipe->byEP, USB_IN_EP_TYPE, KAL_TRUE, USB_CTRL_STALL_ENTRY_3);
USB_CtrlEPStall(g_UsbMS.rxpipe->byEP, USB_OUT_EP_TYPE, KAL_TRUE, USB_CTRL_STALL_ENTRY_3);
g_UsbMS.nState = USBMS_IDLE;
return;
}
/* keep current LUN */
g_UsbMS.current_LUN = CBW->bCBWLUN;
/* determine state */
if (CBW->dCBWDataTransferLength!=0)
{
if (CBW->bmCBWFlags & USBMS_DIR_IN)
g_UsbMS.nState = USBMS_TX;
else
g_UsbMS.nState = USBMS_RX;
}
// USB_Ms_Dbg_Trace(USB_DBG_CMD, CBWCB[0]);
/* parse command */
switch(CBWCB[0])
{
case USBMS_FORMAT_UNIT:
USB_Ms_Cmd_Format(CBW->bCBWLUN, CBW);
break;
case USBMS_INQUIRY:
USB_Ms_Cmd_Inquiry(CBW);
break;
case USBMS_TEST_UNIT_READY:
USB_Ms_Cmd_Test_Unit_Ready(CBW->bCBWLUN, CBW);
break;
case USBMS_PREVALLOW_MEDIA_REMOVL:
USB_Ms_Cmd_Prev_Media_Removal(CBW->bCBWLUN, CBW);
break;
case USBMS_WRITE:
USB_Ms_Cmd_Write(CBW->bCBWLUN,CBW);
break;
case USBMS_READ:
USB_Ms_Cmd_Read(CBW->bCBWLUN,CBW);
break;
case USBMS_READ_CAPACITY:
USB_Ms_Cmd_Read_Capacity(CBW->bCBWLUN, CBW);
break;
case USBMS_READ_FORMATCAPACITY:
USB_Ms_Cmd_Read_FormatCapacity(CBW->bCBWLUN, CBW);
break;
case USBMS_REQUESTSENSE:
USB_Ms_Cmd_RequestSense(CBW);
break;
case USBMS_VERIFY:
USB_Ms_Cmd_Verify(CBW->bCBWLUN, CBW);
break;
case USBMS_MODE_SENSE6: /*Mode Sense*/
USB_Ms_Cmd_ModeSense6(CBW->bCBWLUN, CBW);
break;
case USBMS_START_STOP_UNIT:
case USBMS_MODE_SENSE:
case USBMS_MODE_SELECT6:
default:
USB_Ms_Cmd_Unknown(CBW);
break;
}
}
/* handle CBW USBMS_FORMAT_UNIT command */
static void USB_Ms_Cmd_Format(kal_uint8 LUN, UsbMs_CBW *CBW)
{
kal_bool msdc_status;
// USB_Ms_Dbg_Trace(USB_DBG_USBMS_CMD_FORMAT, 0);
USB_Ms_State_Checkmedia_Exist(LUN);
if (g_UsbMS.CSWStatusError == KAL_FALSE)
{
msdc_status = USB_Ms_Format(LUN);
if (msdc_status == KAL_FALSE)
USB_Ms_State_Checkmedia_Exist(LUN);
}
g_UsbMS.nState = USBMS_GETNEXTCMD;
USB_Ms_Generate_Csw(&g_UsbMS.CSW,CBW);
USB_Ms_BuildTx(&g_UsbMS.CSW, 13);
}
/* check media status and generate correspongind status for CSW */
static void USB_Ms_State_Checkmedia_Exist(kal_uint8 LUN)
{
kal_uint8 msdc_status;
// USB_Ms_Dbg_Trace(USB_DBG_CHECKMEDIA_EXIST, 0);
msdc_status = USB_Ms_Checkmedia_Exist(LUN);
switch(msdc_status)
{
case USB_STORAGE_DEV_STATUS_OK:
case USB_STORAGE_DEV_STATUS_WP:
g_UsbMS.sensePtr = (kal_uint8 *)senseOk;
g_UsbMS.CSWStatusError = KAL_FALSE;
break;
case USB_STORAGE_DEV_STATUS_MEDIA_CHANGE:
g_UsbMS.sensePtr = (kal_uint8 *)senseMediaChanged;
g_UsbMS.CSWStatusError = KAL_TRUE;
break;
case USB_STORAGE_DEV_STATUS_NOMEDIA:
g_UsbMS.sensePtr = (kal_uint8 *)senseNoMedia;
g_UsbMS.CSWStatusError = KAL_TRUE;
break;
default:
ASSERT(0);
g_UsbMS.sensePtr = (kal_uint8 *)senseNoMedia;
g_UsbMS.CSWStatusError = KAL_TRUE;
break;
}
}
/* handle CBW USBMS_INQUIRY command */
static void USB_Ms_Cmd_Inquiry(UsbMs_CBW *CBW)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -