www.pudn.com > usb.zip > usb.c
#include "drv_comm.h"
#include "stack_common.h"
#include "stack_msgs.h"
#include "app_ltlcom.h" /* Task message communiction */
#include "syscomp_config.h"
#include "task_config.h"
#include "stacklib.h"
#include "reg_base.h"
#include "drvsignals.h"
#include "app_buff_alloc.h"
#include "drvpdn.h"
#include "intrCtrl.h"
#include "gpio_sw.h"
#include "usb_comm.h"
#include "usb_drv.h"
#include "usb.h"
#include "usb_resource.h"
#include "usbms_drv.h"
#include "usbacm_drv.h"
#include "usbvideo_drv.h"
#include "usb_custom.h"
#include "fs_type.h"
#include "fs_func.h"
#ifdef __OTG_ENABLE__
#include "otg_drv.h"
#endif
#ifdef __MULTI_BOOT__
#include "multiboot_config.h"
#include "fctycomp_config.h"
#endif /* __MULTI_BOOT__ */
/* Device structure, handle usb level data */
Usb_Device gUsbDevice;
#ifndef __PRODUCTION_RELEASE__
kal_uint32 g_usb_reset_times; /* for debug information */
#endif
/* static fuctions */
static void USB_Reset(void);
static void USB_Initialize(void);
static kal_bool USB_Cmd_SetAddress(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static kal_bool USB_Cmd_GetDescriptor(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static kal_bool USB_Cmd_SetConfiguration(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static kal_bool USB_Cmd_GetConfiguration(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static kal_bool USB_Cmd_SetFeature(Usb_Command *pcmd, kal_bool bset);
static kal_bool USB_Cmd_GetStatus(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static void USB_Stdcmd(Usb_Ep0_Status *pep0state, Usb_Command *pcmd);
static void USB_Endpoint0_Idle (void);
static void USB_Endpoint0_Rx(void);
static void USB_Endpoint0_Tx(void);
static void USB_Endpoint0_Hdlr(void);
/************************************************************
gUsbDevice initialize and release functions
*************************************************************/
/* initialize the global variable gUsbDevice */
void USB_Init_Device_Status(void)
{
kal_uint8 index = 0;
kal_mem_set(&gUsbDevice.cfg_info, 0, sizeof(Usb_Config_Info));
for( index = 0; index < USB_MAX_INTERFACE; index++)
{
kal_mem_set(&gUsbDevice.if_info[index], 0, sizeof(Usb_Interface_Info));
}
for( index = 0; index < USB_MAX_EP_BULK_IN; index++)
{
kal_mem_set(&gUsbDevice.ep_bulkin_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_EP_BULK_OUT; index++)
{
kal_mem_set(&gUsbDevice.ep_bulkout_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_EP_INTR; index++)
{
kal_mem_set(&gUsbDevice.ep_intr_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_STRING; index++)
{
gUsbDevice.resource_string[index] = NULL;
}
gUsbDevice.conf = NULL;
gUsbDevice.device_type = USB_UNKOWN;
gUsbDevice.nDevState = DEVSTATE_DEFAULT;
gUsbDevice.remoteWk = KAL_FALSE;
gUsbDevice.self_powered = KAL_FALSE;
gUsbDevice.config_num = 0;
gUsbDevice.interface_num = 0;
gUsbDevice.ep0_rx_handler = NULL;
gUsbDevice.ep0_class_cmd_handler.b_enable = KAL_FALSE;
gUsbDevice.resource_ep_bulkin_number = 0;
gUsbDevice.resource_ep_bulkout_number = 0;
gUsbDevice.resource_ep_intr_number = 0;
gUsbDevice.resource_interface_number = 0;
gUsbDevice.resource_string_number = 0;
}
/* release the already get memory, and reset some parameter,
note that hisr should not be reset to NULL since it may already be created*/
void USB_Release_Device_Status(void)
{
kal_uint8 index = 0;
kal_mem_set(&gUsbDevice.cfg_info, 0, sizeof(Usb_Config_Info));
for( index = 0; index < USB_MAX_INTERFACE; index++)
{
kal_mem_set(&gUsbDevice.if_info[index], 0, sizeof(Usb_Interface_Info));
}
for( index = 0; index < USB_MAX_EP_BULK_IN; index++)
{
kal_mem_set(&gUsbDevice.ep_bulkin_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_EP_BULK_OUT; index++)
{
kal_mem_set(&gUsbDevice.ep_bulkout_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_EP_INTR; index++)
{
kal_mem_set(&gUsbDevice.ep_intr_info[index], 0, sizeof(Usb_Ep_Info));
}
for( index = 0; index < USB_MAX_STRING; index++)
{
gUsbDevice.resource_string[index] = NULL;
}
if(gUsbDevice.conf != NULL)
free_ctrl_buffer(gUsbDevice.conf);
gUsbDevice.conf = NULL;
gUsbDevice.nDevState = DEVSTATE_DEFAULT;
gUsbDevice.remoteWk = KAL_FALSE;
gUsbDevice.self_powered = KAL_FALSE;
gUsbDevice.config_num = 0;
gUsbDevice.interface_num = 0;
gUsbDevice.device_type = USB_UNKOWN;
gUsbDevice.ep0_rx_handler = NULL;
gUsbDevice.ep0_class_cmd_handler.b_enable = KAL_FALSE;
gUsbDevice.resource_ep_bulkin_number = 0;
gUsbDevice.resource_ep_bulkout_number = 0;
gUsbDevice.resource_ep_intr_number = 0;
gUsbDevice.resource_interface_number = 0;
gUsbDevice.resource_string_number = 0;
}
/************************************************************
EP0 functions
*************************************************************/
/* register EP0 rx OUT token data handler */
void USB_Register_EP0_RxHdlr(usb_ep0_rx_ptr handler)
{
gUsbDevice.ep0_rx_handler = handler;
}
void USB_Register_EP0_Class_CmdHdlr(kal_uint8 cmd, usb_ep0_cmd_ptr handler)
{
gUsbDevice.ep0_class_cmd_handler.cmd = cmd;
gUsbDevice.ep0_class_cmd_handler.ep0_cmd_hdlr = handler;
gUsbDevice.ep0_class_cmd_handler.b_enable = KAL_TRUE;
}
/* prepare TX data infomration for pep0state, data is actually sent out in TX state handler */
void USB_Generate_EP0Data(Usb_Ep0_Status*pep0state, Usb_Command*pcmd, void *data, kal_int32 len)
{
pep0state->nBytesLeft = len;
pep0state->pData = (void*)data;
/* only transmit at most command request */
if (pcmd->wLength < pep0state->nBytesLeft)
pep0state->nBytesLeft = pcmd->wLength;
/* EP0 go to TX state */
gUsbDevice.ep0_state = USB_EP0_TX;
}
/************************************************************
system ctrl functions
*************************************************************/
/* init function, called when user select usb type,
entry function for task , B_eanble is D+ detection enable */
void USB_Init(USB_DEVICE_TYPE type, kal_bool b_enable)
{
#ifndef __USB_ENABLE__
EXT_ASSERT(0, 0, 0, 0);
#endif
#if ( defined(MT6218) || defined(MT6218B) || defined(MT6219) )
#ifndef MCU_52M
EXT_ASSERT(0, 0, 0, 0); /* Must 52M */
#endif /* MCU_52M */
#endif /* MT6218||MT6218B||MT6219 */
USB_Init_Drv_Info(); /*initialize driver parameters*/
USB_Init_Device_Status(); /*initialize global variable gUsbDevice*/
if(type == USB_MASS_STORAGE)
{
USB_Init_Ms_Status();
}
else if(type == USB_CDC_ACM)
{
USB_Init_Acm_Status();
}
#ifdef WEBCAM_SUPPORT
else if(type == USB_VIDEO)
{
USB_Init_Video_Status();
}
#endif
else if(type == USB_COMPOSITE)
{
USB_Init_Ms_Status();
USB_Init_Acm_Status();
}
else
{
EXT_ASSERT(0, type, 0, 0);
}
gUsbDevice.device_type = type;
/* register reset and ep0 interrupt handler to driver info*/
USB_Register_Drv_Info(USB_DRV_HDLR_RESET, 0, USB_Reset);
USB_Register_Drv_Info(USB_DRV_HDLR_EP0, 0, USB_Endpoint0_Hdlr);
/* create descriptors */
USB_Software_Create();
#ifdef __USB_RAMDISK__
if (type != USB_CDC_ACM)
{
FAT_Init();
}
#endif /*__USB_RAMDISK__*/
if(b_enable == KAL_TRUE)
{
/* enable USB power, host can detect USB device*/
USB_PDNmode(KAL_FALSE);
}
/* reset and initialize system initial value and registers*/
USB_Reset_Drv(); /* reset hw power register */
USB_Initialize_Drv();
/* initailize according to application*/
USB_Initialize();
/* if __OTG_ENABLE__, only activate OTG ISR*/
#ifdef __OTG_ENABLE__
OTG_Drv_Activate_ISR();
if(b_enable == KAL_TRUE)
OTG_Enable_Device();
#else
/* LISR should be unmask after all initialize and enable any USB interrupt */
USB_Drv_Activate_ISR();
#endif /* __OTG_ENABLE__ */
}
void USB_Release(void)
{
USB_Release_Drv();
}
/* reset device, called when receive reset interrupt*/
static void USB_Reset(void)
{
kal_uint8 ep_num;
gUsbDevice.is_configured_now = KAL_FALSE;
#ifndef __PRODUCTION_RELEASE__
g_usb_reset_times++;
kal_prompt_trace(MOD_USB, "USB reset %d\n", g_usb_reset_times);
#endif /* __PRODUCTION_RELEASE__ */
// initialize driver info and system interrupt
USB_ResetDrv_Info();
USB_Initialize_Drv();
USB_Initialize(); /* call class reset function */
for(ep_num=0;ep_numbmRequestType != USB_CMD_STDDEVOUT)
{
bError = KAL_TRUE;
}
else
{
if (gUsbDevice.nDevState <= DEVSTATE_ADDRESS)
{
pep0state->byFAddr = (kal_uint8)pcmd->wValue;
if ((gUsbDevice.nDevState == DEVSTATE_DEFAULT) && (pep0state->byFAddr<=127))
{
gUsbDevice.nDevState = DEVSTATE_SET_ADDRESS;
USB_SetAddress(pep0state->byFAddr, USB_SET_ADDR_DATA);
}
else
{
gUsbDevice.nDevState = DEVSTATE_DEFAULT;
}
}
else
{
bError = KAL_TRUE;
}
}
return bError;
}
/* parse command Get Descriptor */
static kal_bool USB_Cmd_GetDescriptor(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
kal_uint8 byConfig;
kal_uint8 bystr;
Usb_Cfg_Dscr *pcfg;
/* Decode the required descriptor from the command */
if (pcmd->bmRequestType != USB_CMD_STDDEVIN)
{
bError = KAL_TRUE;
}
else
{
switch (pcmd->wValue & USB_CMD_DESCMASK)
{
case USB_CMD_DEVICE:
/* Prepare to return Standard Device Descriptor */
USB_Generate_EP0Data(pep0state, pcmd, &gUsbDevice.devdscr, sizeof(Usb_Dev_Dscr));
break;
case USB_CMD_CONFIG:
byConfig = (kal_uint8)(pcmd->wValue & 0x00FF);
if (byConfig >= gUsbDevice.devdscr.bNumConfigurations)
{
bError = KAL_TRUE;
}
else
{
/* Get pointer to requested configuration descriptor */
pcfg = (Usb_Cfg_Dscr*)gUsbDevice.conf;
#ifdef __USB_MULTI_CHARGE_CURRENT__
#if ( defined(MT6305) || defined(MT6318) )
/* memory copy to modify descriptor */
kal_mem_cpy( (kal_uint8*) &(pcfg->bConfigurationValue),
(kal_uint8*) &gUsbDevice.multi_configuration_value[byConfig] ,
1);
kal_mem_cpy( (kal_uint8*) &(pcfg->bMaxPower),
(kal_uint8*) &gUsbDevice.multi_Max_Power[byConfig] ,
1);
#endif
#endif
/* Prepare to return Configuration Descriptors */
USB_Generate_EP0Data(pep0state, pcmd, pcfg, pcfg->wTotalLength);
}
break;
case USB_CMD_STRING:
bystr = (kal_uint8)(pcmd->wValue & 0x00FF);
if (bystr >= gUsbDevice.resource_string_number)
{
bError = KAL_TRUE;
}
else
{
/* Get pointer to requested string descriptor */
USB_Generate_EP0Data(pep0state, pcmd, (void *)gUsbDevice.resource_string[bystr],
(*(kal_uint8 *)gUsbDevice.resource_string[bystr]));
}
break;
default:
bError = KAL_TRUE;
break;
}
}
return bError;
}
/* parse command Set Configuration */
static kal_bool USB_Cmd_SetConfiguration(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
kal_uint8 byConfig;
ilm_struct *ilm;
/* add for usb charging */
ilm_struct *ilm_charge;
bmt_usb_ind_struct *ind;
#ifndef __USB_MULTI_CHARGE_CURRENT__
kal_bool bConfirm = KAL_FALSE;
#endif
/* uart plug in ind*/
uart_plugin_ind_struct *ilm_uart_plug_in;
byConfig = (kal_uint8)(pcmd->wValue & 0x00FF);
if (gUsbDevice.nDevState == DEVSTATE_DEFAULT)
{
bError = KAL_TRUE;
}
/* Assumes configurations are numbered from 1 to NumConfigurations */
else
{
if (byConfig > gUsbDevice.devdscr.bNumConfigurations)
{
bError = KAL_TRUE;
}
else if (byConfig == 0)
{
gUsbDevice.nDevState = DEVSTATE_ADDRESS;
gUsbDevice.config_num = byConfig;
}
else
{
#ifndef __PRODUCTION_RELEASE__
kal_prompt_trace(MOD_USB, "USB config\n");
#endif /* __PRODUCTION_RELEASE__ */
gUsbDevice.nDevState = DEVSTATE_CONFIG;
gUsbDevice.is_configured_now = KAL_TRUE;
gUsbDevice.config_num = byConfig;
#ifndef __USB_MULTI_CHARGE_CURRENT__
bConfirm = KAL_TRUE;
#endif
}
}
if (INT_BootMode() != MTK_FACTORY_MODE)
{
/* add for usb charging */
ind = (bmt_usb_ind_struct*)construct_local_para(sizeof(bmt_usb_ind_struct), TD_CTRL);
#ifdef __USB_MULTI_CHARGE_CURRENT__
#if ( defined(MT6305) || defined(MT6318) )
if (byConfig ==0)
ind->usb_ind = (kal_uint8) (USB_DEVDSC_CONFIGS+1); /*usb not charging */
else
{
ind->usb_ind = (kal_uint8) (byConfig-1);
//ind->usb_ind = (USB_DEVDSC_CONFIGS+1); /* test with PC */
}
#else
ind->usb_ind = (byConfig ==0)?(USB_DEVDSC_CONFIGS+1):(byConfig-1);
#endif
#else
ind->usb_ind = (bConfirm == KAL_TRUE)?(BMT_USB_500):(BMT_USB_100);
#endif
DRV_BuildPrimitive( ilm_charge, MOD_DRV_HISR, MOD_BMT, MSG_ID_BMT_USB_IND, ind);
msg_send_ext_queue(ilm_charge);
}
else
{
/* meta mode, notify ft task */
DRV_BuildPrimitive(ilm, MOD_DRV_HISR, MOD_FT, MSG_ID_USB_FT_IND, NULL);
msg_send_ext_queue(ilm);
}
/* notify UART owner that virtual UART is plug in*/
if((gUsbDevice.nDevState == DEVSTATE_CONFIG) && (gUsbDevice.device_type == USB_CDC_ACM))
{
#ifdef __DSPIRDBG__
if(g_UsbACM.acm_owner == USB_ACM_OWNER_DSP)
{
/* notify usb task to start IRDBG*/
DRV_BuildPrimitive(ilm, MOD_DRV_HISR, MOD_USB, MSG_ID_USB_IRDGB_START_IND, NULL);
msg_send_ext_queue(ilm);
}
else
#endif /* __DSPIRDBG__ */
{
if(USB2UARTPort.ownerid != MOD_DRV_HISR)
{
ilm_uart_plug_in = (uart_plugin_ind_struct*)construct_local_para(sizeof(uart_plugin_ind_struct), TD_CTRL);
ilm_uart_plug_in->port = USB2UARTPort.port_no;
DRV_BuildPrimitive(ilm,
MOD_DRV_HISR,
USB2UARTPort.ownerid,
MSG_ID_UART_PLUGIN_IND,
ilm_uart_plug_in);
msg_send_ext_queue(ilm);
g_UsbACM.send_UARTilm = KAL_TRUE;
if (g_UsbACM.config_send_Txilm == KAL_TRUE )
{
g_UsbACM.send_Txilm = KAL_TRUE;
/* if someone PutBytes once, then issue ready-to-write message */
if(USB2UARTPort.tx_cb!=NULL)
USB2UARTPort.tx_cb(uart_port_usb);
}
else
{
g_UsbACM.send_Txilm = KAL_FALSE;
}
}
}
}
return bError;
}
/* parse command Get Configuration */
static kal_bool USB_Cmd_GetConfiguration(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
#ifdef __OTG_ENABLE__
/* Prepare to return configuration value */
USB_Generate_EP0Data(pep0state, pcmd, &gUsbDevice.config_num, 1);
#else
// Usb_Cfg_Dscr *pcfg;
if( (gUsbDevice.nDevState == DEVSTATE_ADDRESS) && (!pcmd->wValue))
{
/* Prepare to return zero */
USB_Generate_EP0Data(pep0state, pcmd, &pcmd->wValue, 1);
}
else if( gUsbDevice.nDevState == DEVSTATE_CONFIG)
{
/* Prepare to return configuration value */
//pcfg = (Usb_Cfg_Dscr *)gUsbDevice.pCurCfg;
//USB_Generate_EP0Data(pep0state, pcmd, &pcfg->bConfigurationValue, 1);
USB_Generate_EP0Data(pep0state, pcmd, &gUsbDevice.config_num, 1);
}
else
{
bError = KAL_TRUE;
}
#endif
return bError;
}
/* parse command Set Interface */
static kal_bool USB_Cmd_SetInterface(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
gUsbDevice.interface_num = pcmd->wValue & 0x00FF;
return bError;
}
/* parse command Get Interface */
static kal_bool USB_Cmd_GetInterface(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
USB_Generate_EP0Data(pep0state, pcmd, &gUsbDevice.interface_num, 1);
return bError;
}
/* parse command Set/Clear Feature */
/* bset true means command SET_FETURE, false means command CLEAR_FEATURE */
static kal_bool USB_Cmd_SetFeature(Usb_Command *pcmd, kal_bool bset)
{
kal_bool bError = KAL_FALSE;
switch (pcmd->bmRequestType)
{
/* device */
case USB_CMD_STDDEVOUT:
switch (pcmd->wValue)
{
case USB_FTR_DEVREMWAKE:
gUsbDevice.remoteWk = bset;
break;
#ifdef __OTG_ENABLE__
case USB_FTR_B_HNP_ENB:
OTG_B_EnDis_HNP(KAL_TRUE);
break;
case USB_FTR_A_HNP_SUPPORT:
case USB_FTR_A_ALT_HNP_SUPPORT:
break;
#endif
default:
bError = KAL_TRUE;
break;
}
break;
/* endpoint */
case USB_CMD_STDEPOUT:
switch (pcmd->wValue)
{
case USB_FTR_EPHALT:
if (pcmd->wIndex == 0)
{
/* endpoint 0 */
;
}
else
{
/* command EP direction zero indicate OUT EP */
if(pcmd->wIndex & 0x80)
{
/* In EP*/
if((pcmd->wIndex& 0x0f) > MAX_INTR_EP_NUM)
{
#ifdef __PRODUCTION_RELEASE__
bError = KAL_TRUE;
#else
EXT_ASSERT(0, (pcmd->wIndex& 0x0f), gUsbDevice.resource_ep_bulkin_number, 0)
#endif
}
else
{
USB_CtrlEPStall((pcmd->wIndex& 0x0f), USB_IN_EP_TYPE, bset, USB_CTRL_STALL_ENTRY_1);
}
}
else
{
/* Out EP*/
if((pcmd->wIndex& 0x0f) > MAX_INTR_EP_NUM)
{
#ifdef __PRODUCTION_RELEASE__
bError = KAL_TRUE;
#else
EXT_ASSERT(0, (pcmd->wIndex& 0x0f), gUsbDevice.resource_ep_bulkout_number, 0)
#endif
}
else
{
USB_CtrlEPStall((pcmd->wIndex& 0x0f), USB_OUT_EP_TYPE, bset, USB_CTRL_STALL_ENTRY_1);
}
}
}
break;
default:
bError = KAL_TRUE;
break;
}
break;
case USB_CMD_STDIFOUT:
default:
bError = KAL_TRUE;
break;
}
return bError;
}
/* parse command Get Status */
static kal_bool USB_Cmd_GetStatus(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
kal_uint16 status = 0;
switch (pcmd->bmRequestType)
{
case USB_CMD_STDDEVIN:
status = ( (kal_uint16)(gUsbDevice.remoteWk << 1) | (kal_uint16)(gUsbDevice.self_powered) );
USB_Generate_EP0Data( pep0state, pcmd, &status, 2);
break;
case USB_CMD_STDIFIN:
USB_Generate_EP0Data( pep0state, pcmd, &status, 2);
break;
case USB_CMD_STDEPIN:
if(pcmd->wIndex & 0x80)
{
/* In EP*/
status = (kal_uint16)USB_Get_EP_Stall_Status((pcmd->wIndex & 0x000f), USB_IN_EP_TYPE);
}
else
{
/* Out EP*/
status = (kal_uint16)USB_Get_EP_Stall_Status((pcmd->wIndex & 0x000f), USB_OUT_EP_TYPE);
}
USB_Generate_EP0Data( pep0state, pcmd, &status, 2);
break;
default:
bError = KAL_TRUE;
break;
}
return bError;
}
/* parse usb standard command */
static void USB_Stdcmd(Usb_Ep0_Status *pep0state, Usb_Command *pcmd)
{
kal_bool bError = KAL_FALSE;
switch (pcmd->bRequest)
{
case USB_SET_ADDRESS:
bError = USB_Cmd_SetAddress(pep0state, pcmd);
break;
case USB_GET_DESCRIPTOR:
bError = USB_Cmd_GetDescriptor(pep0state, pcmd);
break;
case USB_SET_CONFIGURATION:
bError = USB_Cmd_SetConfiguration(pep0state, pcmd);
break;
case USB_SET_INTERFACE:
bError = USB_Cmd_SetInterface(pep0state, pcmd);
break;
case USB_GET_CONFIGURATION:
bError = USB_Cmd_GetConfiguration(pep0state, pcmd);
break;
case USB_GET_INTERFACE:
bError = USB_Cmd_GetInterface(pep0state, pcmd);
break;
case USB_SET_FEATURE:
bError = USB_Cmd_SetFeature(pcmd, KAL_TRUE);
break;
case USB_CLEAR_FEATURE:
bError = USB_Cmd_SetFeature(pcmd, KAL_FALSE);
break;
case USB_GET_STATUS:
bError = USB_Cmd_GetStatus(pep0state, pcmd);
break;
/* Stall the command if an unrecognized request is received */
case USB_SYNCH_FRAME: /*Only support for Isoc traffic*/
case USB_SET_DESCRIPTOR:
default:
bError = KAL_TRUE;
ASSERT(0);
break;
}
if (gUsbDevice.ep0_state == USB_EP0_IDLE) /* no data to transmit */
{
gUsbDevice.ep0_state = USB_EP0_RX_STATUS;
USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, bError, KAL_TRUE);
if((gUsbDevice.ep0_class_cmd_handler.b_enable == KAL_TRUE) &&
(gUsbDevice.ep0_class_cmd_handler.cmd == pcmd->bRequest) )
{
gUsbDevice.ep0_class_cmd_handler.ep0_cmd_hdlr(pcmd);/* Besides standard cmd, still need to do extra this*/
}
}
else
USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, bError, KAL_FALSE);
}
/* parse EP0 requested command */
static void USB_Endpoint0_Idle (void)
{
/* read ep0 data*/
USB_EPFIFORead(0, 8, &gUsbDevice.cmd);
/* Check request type */
switch (gUsbDevice.cmd.bmRequestType & USB_CMD_TYPEMASK)
{
case USB_CMD_STDREQ:
/* standard request */
USB_Stdcmd(&gUsbDevice.ep0info, &gUsbDevice.cmd);
break;
case USB_CMD_CLASSREQ:
/* class specific request */
if((gUsbDevice.cmd.bmRequestType == USB_CMD_CLASSIFIN) || (gUsbDevice.cmd.bmRequestType == USB_CMD_CLASSIFOUT))
{
if(gUsbDevice.if_info[(gUsbDevice.cmd.wIndex & 0xff)].if_class_specific_hdlr != NULL)
{
gUsbDevice.if_info[(gUsbDevice.cmd.wIndex & 0xff)].if_class_specific_hdlr(&gUsbDevice.ep0info, &gUsbDevice.cmd);
}
else
{
#ifndef __PRODUCTION_RELEASE__
/* not support now*/
EXT_ASSERT(0, gUsbDevice.cmd.wIndex, 0, 0);
#endif
/* error occur, stall endpoint*/
USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, KAL_TRUE, KAL_FALSE);
}
}
else
{
#ifndef __PRODUCTION_RELEASE__
/* not support now*/
EXT_ASSERT(0, gUsbDevice.cmd.bmRequestType, 0, 0);
#endif
/* error occur, stall endpoint*/
USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, KAL_TRUE, KAL_FALSE);
}
break;
case USB_CMD_VENDREQ:
default:
/* Stall the command if a reserved request is received */
USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, KAL_TRUE, KAL_FALSE);
break;
}
}
/* EP0 RX handler, called when EP0 interrupt happened and in RX state */
static void USB_Endpoint0_Rx(void)
{
if (gUsbDevice.ep0_rx_handler != NULL)
{
/* called rx handler to get data*/
gUsbDevice.ep0_rx_handler(&gUsbDevice.ep0info);
}
else
{
/* this should not happened, user should register rx handler when set EP0 into RX state */
/* error occur, stall endpoint*/
ASSERT(0);
// USB_Update_EP0_State(USB_EP0_DRV_STATE_READ_END, KAL_TRUE, KAL_FALSE);
}
}
/* EP0 TX handler, called when EP0 interrupt happened and in TX state,
or EP0 just translate from IDLE to TX state */
static void USB_Endpoint0_Tx(void)
{
kal_int32 nBytes;
/* Determine number of bytes to send */
if (gUsbDevice.ep0info.nBytesLeft <= USB_EP0_MAXP)
{
nBytes = gUsbDevice.ep0info.nBytesLeft;
gUsbDevice.ep0info.nBytesLeft = 0;
}
else
{
nBytes = USB_EP0_MAXP;
gUsbDevice.ep0info.nBytesLeft -= USB_EP0_MAXP;
}
/* send out data */
USB_EPFIFOWrite (0, nBytes, gUsbDevice.ep0info.pData);
/* update data pointer and prepare for next transaction */
gUsbDevice.ep0info.pData = (kal_uint8 *)gUsbDevice.ep0info.pData + nBytes;
if (nBytes < USB_EP0_MAXP)
{
gUsbDevice.ep0_state = USB_EP0_IDLE;
/* last data, set end as true*/
USB_Update_EP0_State(USB_EP0_DRV_STATE_WRITE_RDY, KAL_FALSE, KAL_TRUE);
}
else
{
USB_Update_EP0_State(USB_EP0_DRV_STATE_WRITE_RDY, KAL_FALSE, KAL_FALSE);
}
}
/* EP0 interrupt handler called by USB_HISR */
static void USB_Endpoint0_Hdlr(void)
{
kal_bool b_transaction_end;
kal_bool b_sent_stall;
kal_uint32 nCount;
USB_Get_EP0_Status(&b_transaction_end, &b_sent_stall);
/* Check for SentStall */
/* SentStall && SetupEnd are impossible to occur together*/
if (b_sent_stall == KAL_TRUE)
{
USB_Update_EP0_State(USB_EP0_DRV_STATE_CLEAR_SENT_STALL, KAL_FALSE, KAL_FALSE);
gUsbDevice.ep0_state = USB_EP0_IDLE;
}
/* Check for SetupEnd */
if (b_transaction_end == KAL_TRUE)
{
USB_Update_EP0_State(USB_EP0_DRV_STATE_TRANSACTION_END, KAL_FALSE, KAL_FALSE);
gUsbDevice.ep0_state = USB_EP0_IDLE;
}
/* Call relevant routines for endpoint 0 state */
if (gUsbDevice.ep0_state == USB_EP0_IDLE)
{
/* receive command request */
nCount = USB_EP0_Pkt_Len();
if (nCount > 0)
{
/* idle state handler */
USB_Endpoint0_Idle();
}
}
else if (gUsbDevice.ep0_state == USB_EP0_RX)
{
/* Rx state handler */
USB_Endpoint0_Rx();
}
else if (gUsbDevice.ep0_state == USB_EP0_RX_STATUS)
{
/* Data stage is RX, status stage is TX*/
if(gUsbDevice.nDevState == DEVSTATE_SET_ADDRESS)
{
USB_SetAddress(gUsbDevice.ep0info.byFAddr, USB_SET_ADDR_STATUS);
gUsbDevice.nDevState = DEVSTATE_ADDRESS;
}
gUsbDevice.ep0_state = USB_EP0_IDLE;
/* In case next setup followed the previous status very fast and interrupt only happens once*/
/* receive command request */
nCount = USB_EP0_Pkt_Len();
if (nCount > 0)
{
/* idle state handler */
USB_Endpoint0_Idle();
}
}
/* must use if, not else if, EP0 may enter TX state in previous IDLE state handler */
if (gUsbDevice.ep0_state == USB_EP0_TX)
{
/* Tx state handler */
USB_Endpoint0_Tx();
}
return;
}