📄 usb_host_ms_drv.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:
* ---------
* usb_host_ms_drv.c
*
* Project:
* --------
* Maui_Software
*
* Description:
* ------------
* This file implements host mass storage class driver
*
* 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!
*
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*============================================================================
****************************************************************************/
#include "drv_comm.h"
#include "gpt_sw.h"
#include "app_buff_alloc.h"
#include "usb_comm.h"
#include "usb.h"
#include "usb_custom.h"
#include "usbd.h"
#include "otg_drv.h"
#include "stack_common.h"
#include "stack_msgs.h"
#include "app_ltlcom.h" /* Task message communiction */
#include "usbms_state.h"
#include "usb_host_ms_drv.h"
#include "usb_host_ms_if.h"
#include "usb_host_ms_custom.h"
#include "usb_host_ms_adap.h"
/* for debig only*/
//#include "usb_hcd_pri.h"
//extern USB_HCD_Struct g_UsbHcdInfo;
#ifdef __OTG_ENABLE__
/* The command and data (exepct read and write use this shared buffer)*/
/* Only one command and one data will be executed at one time */
static kal_uint8 g_usb_ms_cmd[USBMS_MAX_CMD_LEN];
static kal_uint8 g_usb_ms_data[USBMS_MAX_DATA_LEN];
static kal_bool USB_Host_Ms_Match(USBD_Desc_Info *p_desc_info, kal_uint8 *p_cfg_num);
static void USB_Host_Ms_Startup(kal_uint8 cfg_num);
static void USB_Host_Ms_Detach(void);
static kal_bool USB_Host_Ms_Send_Cmd(USBH_Ms_Cmd_Struct *ms_cmd);
static void USB_Host_Ms_Hdlr(USB_HCD_STATUS result, kal_uint32 param);
static void USB_Host_Ms_Ctrl_EP_Hdlr(USB_HCD_STATUS result, kal_uint32 param);
static void USB_Host_Ms_Bulk_EP_Hdlr(USB_HCD_STATUS result, kal_uint32 param);
static void USB_Host_Ms_CBW_Hdler(USB_HCD_STATUS result, kal_uint32 param);
static void USB_Host_Ms_DATA_Hdler(USB_HCD_STATUS result, kal_uint32 param);
static void USB_Host_Ms_CSW_Hdler(USB_HCD_STATUS result, kal_uint32 param);
USB_Host_Ms_Struct g_UsbHostMs;
USBD_ClassDriver_Struct USB_Host_Ms_Drv =
{
USB_Host_Ms_Match,
USB_Host_Ms_Startup,
USB_Host_Ms_Detach
};
/************************************************************
ms class register functions (match, startup, detatch)
*************************************************************/
static kal_bool USB_Host_Ms_Match(USBD_Desc_Info *p_desc_info, kal_uint8 *p_cfg_num)
{
kal_bool b_match = KAL_FALSE;
kal_uint32 index = 0;
kal_uint32 index2 = 0;
kal_uint16 max_support_power = USBD_Get_Max_Power();
max_support_power = max_support_power/2;
*p_cfg_num = 0;
while(index < p_desc_info->cfg_number)
{
if((p_desc_info->dev_desc.bDeviceClass == USB_MS_DEVICE_CODE)
&& (p_desc_info->cfg_info[index].p_cfg_desc->bMaxPower<=max_support_power)
&& (p_desc_info->cfg_info[index].p_interface_info[0]->p_interface_desc->bInterfaceClass== USB_MS_INTERFACE_CLASS_CODE)
&& (p_desc_info->cfg_info[index].p_interface_info[0]->p_interface_desc->bInterfaceSubClass == USB_MS_INTERFACE_SUBCLASS_CODE)
&& (p_desc_info->cfg_info[index].p_interface_info[0]->p_interface_desc->bInterfaceProtocol == USB_MS_INTERFACE_PROTOCOL_CODE) )
{
b_match = KAL_TRUE;
for(index2 = 0; index2 < p_desc_info->cfg_info[index].p_interface_info[0]->ep_number; index2++)
{
if(((p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bEndpointAddress & USB_EP_DIR) == USB_EP_DIR_IN)
&& (p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bmAttributes == USB_EP_BULK))
{
g_UsbHostMs.ep_in_num = p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bEndpointAddress & (~USB_EP_DIR);
g_UsbHostMs.ep_in_max_pkt_size = p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->wMaxPacketSize[0]
+ (p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->wMaxPacketSize[1]<<8);
if(g_UsbHostMs.ep_in_max_pkt_size>USB_HCD_Get_FM_Pkt_Size())
b_match = KAL_FALSE;
}
else if(((p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bEndpointAddress & USB_EP_DIR) == USB_EP_DIR_OUT)
&& (p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bmAttributes == USB_EP_BULK))
{
g_UsbHostMs.ep_out_num = p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->bEndpointAddress & (~USB_EP_DIR);
g_UsbHostMs.ep_out_max_pkt_size = p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->wMaxPacketSize[0]
+ (p_desc_info->cfg_info[index].p_interface_info[0]->p_ep_info[index2]->p_stdep->wMaxPacketSize[1]<<8);
if(g_UsbHostMs.ep_in_max_pkt_size>USB_HCD_Get_FM_Pkt_Size())
b_match = KAL_FALSE;
}
}
}
if(b_match==KAL_TRUE)
{
*p_cfg_num = p_desc_info->cfg_info[index].p_cfg_desc->bConfigurationValue;
break;
}
index++;
}
return b_match;
}
static void USB_Host_Ms_Startup(kal_uint8 cfg_num)
{
kal_uint8 ep_index;
kal_uint8 index;
ilm_struct *usb_ilm;
kal_uint32 event_group;
ep_index = USB_HCD_Get_EP_Channel( );
USB_HCD_Set_EP_Max_Pkt(ep_index, g_UsbHostMs.ep_in_max_pkt_size);
g_UsbHostMs.ep_in_index = ep_index;
ep_index = USB_HCD_Get_EP_Channel( );
USB_HCD_Set_EP_Max_Pkt(ep_index, g_UsbHostMs.ep_out_max_pkt_size);
g_UsbHostMs.ep_out_index = ep_index;
g_UsbHostMs.total_lun = 0;
g_UsbHostMs.media_handle = USBHost_Get_Media_Hanle(&g_UsbHostMs.support_lun);
/* Initailize media handle */
for(index = 0; index < g_UsbHostMs.support_lun; index++)
g_UsbHostMs.media_handle[index] = index;
USB_Host_Ms_Get_Media_Resource();
if((g_UsbHostMs.support_lun==0) || (g_UsbHostMs.media_info==NULL) || (g_UsbHostMs.media_msg_array==NULL))
EXT_ASSERT(0, (kal_uint32)g_UsbHostMs.support_lun, (kal_uint32)g_UsbHostMs.media_info,
(kal_uint32)g_UsbHostMs.media_msg_array);
g_UsbHostMs.dev_error_count = 0;
g_UsbHostMs.dev_state = USB_HOST_MS_DEV_STATE_READY;
g_UsbHostMs.dev_attatch = KAL_TRUE;
USB_HCD_Register_Drv_Info(USB_HCD_HDLR_TOKEN_DONE, g_UsbHostMs.ep_in_index, USB_Host_Ms_Hdlr);
USB_HCD_Register_Drv_Info(USB_HCD_HDLR_TOKEN_DONE, g_UsbHostMs.ep_out_index, USB_Host_Ms_Hdlr);
if(g_UsbHostMs.ep_in_max_pkt_size==USB_HCD_Get_FM_Pkt_Size())
USB_HCD_InEPEn(g_UsbHostMs.ep_in_index, g_UsbHostMs.ep_in_num, USB_HCD_ENDPT_BULK, 100, KAL_TRUE);
else
USB_HCD_InEPEn(g_UsbHostMs.ep_in_index, g_UsbHostMs.ep_in_num, USB_HCD_ENDPT_BULK, 0xff, KAL_FALSE);
if(g_UsbHostMs.ep_out_max_pkt_size==USB_HCD_Get_FM_Pkt_Size())
USB_HCD_OutEPEn(g_UsbHostMs.ep_out_index, g_UsbHostMs.ep_out_num, USB_HCD_ENDPT_BULK, 100, KAL_TRUE);
else
USB_HCD_OutEPEn(g_UsbHostMs.ep_out_index, g_UsbHostMs.ep_out_num, USB_HCD_ENDPT_BULK, 0xff, KAL_FALSE);
USBD_Register_EP0_Callback(USB_Host_Ms_Hdlr);
//USBD_Register_EP0_Callback(USB_Host_Ms_EP0_Callback);
USB_HCD_Get_DMA_Channel();
if(g_UsbHostMs.event_id!=0)
{
/* rereive all events that may exist after previous detatch */
kal_retrieve_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DONE|EVENT_USB_MS_DETATCH,
KAL_OR_CONSUME, &event_group, KAL_NO_SUSPEND);
}
/* send msg to USB task, start ms state machine */
DRV_BuildPrimitive(usb_ilm, MOD_DRV_HISR,
MOD_USB, MSG_ID_USB_MSHOST_START_IND, NULL);
msg_send_ext_queue(usb_ilm);
USB_Host_Ms_SendInd(USB_HOST_MS_MSG_PLUG_IN);
}
static void USB_Host_Ms_Detach(void)
{
kal_uint32 index;
GPTI_StopItem(g_UsbHostMs.gpt_handle);
USB_HCD_Free_DMA_Channel();
USB_HCD_Free_EP_Channel();
for(index=0; index<g_UsbHostMs.total_lun; index++)
{
/* If original state is READY, set state change as true */
if(((g_UsbHostMs.media_info[index].state==USB_HOST_MS_MEDIA_STATE_WR_PROTECT)
||(g_UsbHostMs.media_info[index].state==USB_HOST_MS_MEDIA_STATE_READY))
&& (g_UsbHostMs.media_info[index].sec_size!=0))
{
g_UsbHostMs.media_state_change |= (1<<index);
}
/* Set all the media state to error */
g_UsbHostMs.media_info[index].state = USB_HOST_MS_MEDIA_STATE_ABSENT;
}
g_UsbHostMs.dev_attatch = KAL_FALSE;
/* wake up wating task */
g_UsbHostMs.result = USB_HOST_MS_RESULT_TIMEOUT;
kal_set_eg_events(g_UsbHostMs.event_id, EVENT_USB_MS_DETATCH, KAL_OR);
USB_Host_Ms_Dis_Device();
/* Notify FMT about media change */
if((g_UsbHostMs.media_state_change != 0) && (g_UsbHostMs.b_sending_change_ilm == KAL_FALSE))
{
for(index=0; index<g_UsbHostMs.total_lun; index++)
{
if((g_UsbHostMs.media_state_change&(1<<index))!=0)
g_UsbHostMs.media_msg_array[index] = (kal_uint32)&g_UsbHostMs.media_handle[index];
else
g_UsbHostMs.media_msg_array[index] = NULL;
}
g_UsbHostMs.media_state_change = 0;
USB_Host_Ms_SendInd(USB_HOST_MS_MSG_MEDIA_CHANGE);
}
USB_Host_Ms_SendInd(USB_HOST_MS_MSG_PLUG_OUT);
}
/************************************************************
ms utilities (send msg to FMT task. Indicate card status change)
*************************************************************/
#include "custom_config.h"
/* send card change indication to FMT task */
void USB_Host_Ms_SendInd(USB_HOST_MS_MSG_TYPE msg)
{
ilm_struct *usb_ilm;
usb_host_ms_media_struct *change_ind;
usb_host_ms_drive_struct *drive_ind;
switch(msg)
{
case USB_HOST_MS_MSG_MEDIA_CHANGE:
if(g_UsbHostMs.b_sending_change_ilm==KAL_TRUE)
ASSERT(0);
g_UsbHostMs.b_sending_change_ilm = KAL_TRUE;
change_ind = (usb_host_ms_media_struct*)construct_local_para(
sizeof(usb_host_ms_media_struct) + (sizeof(kal_uint32*)*g_UsbHostMs.support_lun-1) , TD_CTRL);
change_ind->media_size = g_UsbHostMs.support_lun;
kal_mem_cpy(&change_ind->media_array, g_UsbHostMs.media_msg_array, sizeof(kal_uint32*)*g_UsbHostMs.support_lun);
DRV_BuildPrimitive(usb_ilm,
MOD_DRV_HISR,
MOD_FMT,
MSG_ID_OTG_CARD_DETECT_IND,
change_ind);
msg_send_ext_queue(usb_ilm);
break;
case USB_HOST_MS_MSG_PLUG_IN:
drive_ind = (usb_host_ms_drive_struct*)construct_local_para(
sizeof(usb_host_ms_drive_struct), TD_CTRL);
drive_ind->drive = (void*)&FS_OTGDrv;
drive_ind->media_size = g_UsbHostMs.support_lun;
DRV_BuildPrimitive(usb_ilm,
MOD_DRV_HISR,
MOD_FMT,
MSG_ID_OTG_MS_INSERT_IND,
drive_ind);
msg_send_ext_queue(usb_ilm);
break;
case USB_HOST_MS_MSG_PLUG_OUT:
if(g_UsbHostMs.b_sending_plugout_ilm==KAL_TRUE)
ASSERT(0);
g_UsbHostMs.b_sending_plugout_ilm = KAL_TRUE;
drive_ind = (usb_host_ms_drive_struct*)construct_local_para(
sizeof(usb_host_ms_drive_struct), TD_CTRL);
drive_ind->drive = (void*)&FS_OTGDrv;
drive_ind->media_size = g_UsbHostMs.support_lun;
DRV_BuildPrimitive(usb_ilm,
MOD_DRV_HISR,
MOD_FMT,
MSG_ID_OTG_MS_REMOVE_IND,
drive_ind);
msg_send_ext_queue(usb_ilm);
break;
default:
EXT_ASSERT(0, msg, g_UsbHostMs.dev_state, 0);
break;
}
}
void USB_Host_Ms_Get_Media_Resource(void)
{
kal_uint8 index;
g_UsbHostMs.media_info = (USBH_Ms_Media_Struct*)get_ctrl_buffer(sizeof(USBH_Ms_Media_Struct)*g_UsbHostMs.support_lun);
g_UsbHostMs.media_msg_array = get_ctrl_buffer(sizeof(kal_uint32)*g_UsbHostMs.support_lun);
for(index = 0; index < g_UsbHostMs.support_lun; index++)
g_UsbHostMs.media_msg_array[index] = NULL;
}
void USB_Host_Ms_Free_Media_Resource(void)
{
free_ctrl_buffer((USBH_Ms_Media_Struct*)g_UsbHostMs.media_info);
g_UsbHostMs.media_info = NULL;
free_ctrl_buffer((kal_uint32*)g_UsbHostMs.media_msg_array);
g_UsbHostMs.media_msg_array = NULL;
}
void USB_Host_Ms_Dis_Device(void)
{
USB_HCD_Dis_Attach();
}
void USB_Host_Ms_En_Device(void)
{
USB_HCD_En_Attach();
}
/************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -