📄 usbd.c
字号:
/******************************************************************************
*
* Copyright (c) 2008 Nuvoton Electronics Corp.
* All rights reserved.
*
* File name: usbd.c
*
*
******************************************************************************/
#include <string.h>
#include "platform.h"
#include "usbd.h"
#include "uprintf.h"
#if 1
#define MSG_DEBUG(...)
#define MSG_WARNING(...)
#define MSG_ERROR(...)
#else
#define MSG_DEBUG printf
#define MSG_WARNING printf
#define MSG_ERROR printf
#endif
typedef void (*fptr)(); // function pointer
//static fptr IRQ_HandlerTable[31];
extern fptr IRQ_HandlerTable[31];
#define USE_TOKEN 0
/* The interface number of mass storage interface */
#define MASS_INF_NUM 1
/* The endpoint number of mass storage interface's endpoint */
#define EP_NUM_ISO 1
#define EP_NUM_BKO 2
#define EP_NUM_INT 3
/* length of descriptors */
#define DEVICE_DSCPT_LEN 0x12
#define CONFIG_DSCPT_LEN 0x20
#define STR0_DSCPT_LEN 0x04
#define STR1_DSCPT_LEN 0x16
#define STR2_DSCPT_LEN 0x34
#define QUALIFIER_DSCPT_LEN 0x0a
#define OSCONFIG_DSCPT_LEN 0x20
/* Vitual_Com command base address */
#define Vitual_Com_Addr_Out 0x80400000
#define Vitual_Com_Addr_In 0x80200000
UINT8 volatile *Inptr;
UINT8 volatile USBModeFlag=0; //way
UINT32 volatile Bulk_Out_Transfer_Size=0;
UINT32 volatile Bulk_In_Transfer_Size=1;
UINT32 volatile Out_Count=0;
UINT32 volatile Compare_Length=0;
/* for USB */
USB_CMD_T _usb_cmd_pkt;
UINT32 volatile _usbd_remlen=0;
BOOL volatile _usbd_remlen_flag=0;
UINT16 *_usbd_ptr;
UINT8 volatile Bulk_First_Flag=0;
UINT8 volatile CLASS_CMD_Flag=0;
UINT8 volatile GET_DEV_Flag=0;
UINT8 volatile GET_CFG_Flag=0;
UINT8 volatile GET_QUL_Flag=0;
UINT8 volatile GET_OSCFG_Flag=0;
UINT8 volatile GET_STR_Flag=0;
UINT8 volatile GET_VEN_Flag=0;
UINT8 volatile GET_VENO_Flag=0;
UINT8 volatile usbdGetConfig=0;
UINT8 volatile usbdGetInterface=0;
UINT8 volatile usbdGetStatus=0;
// for DMA state flag
UINT8 volatile _usbd_DMA_Flag=0;
UINT8 volatile _usbd_Less_MPS=0;
UINT8 volatile _usbd_DMA_Dir;
UINT8 volatile bulkonlycmd=0;
UINT8 volatile ResetFlag=0;
UINT8 volatile _usbd_resume=0;
UINT32 volatile usbdMaxPacketSize;
// _usbd_devstate: 1.default state 2.addressed state 3.configured state
UINT32 _usbd_devstate;
UINT32 _usbd_address;
UINT32 _usbd_speedset;
UINT16 _usbd_confsel;
UINT16 _usbd_altsel;
INT _usbd_haltep=0;
INT _usbd_unhaltep;
INT remotewakeup=0;
INT enableremotewakeup;
INT enabletestmode;
INT disableremotewakeup;
INT testselector;
UINT32 usbdGetStatusData;
static UINT16 _DeviceDescriptor[10] =
{
0x0112, 0x0200, 0x0000, 0x4000, 0x0416, 0x5963, 0x0100, 0x0201, 0x0100, 0x0000
};
static UINT16 _QualifierDescriptor[6] =
{
0x060a, 0x0200, 0x0000, 0x4000, 0x0001, 0x0000
};
static UINT16 _ConfigurationBlock[16] =
{
0x0209, 0x0020, 0x0101, 0xC000, 0x0932, 0x0004, 0x0200, 0x0000, 0x0000, 0x0507,
0x0281, 0x0200, 0x0701, 0x0205, 0x0002, 0x0102
};
static UINT16 _ConfigurationBlockFull[16] =
{
0x0209, 0x0020, 0x0101, 0xc000, 0x0932, 0x0004, 0x0200, 0x0000, 0x0000, 0x0507,
0x0281, 0x0040, 0x0701, 0x0205, 0x4002, 0x0100
};
static UINT16 _OSConfigurationBlock[16] =
{
0x0709, 0x0020, 0x0101, 0xc000, 0x0932, 0x0004, 0x0200, 0x0000, 0x0000, 0x0507,
0x0281, 0x0040, 0x0701, 0x0205, 0x4002, 0x0100
};
static UINT16 _StringDescriptor0[2] =
{
0x0304, 0x0409
};
static UINT16 _StringDescriptor1[11] =
{
0x0316, 0x0055, 0x0053, 0x0042, 0x0020, 0x0044, 0x0065, 0x0076, 0x69, 0x0063, 0x0065
};
static UINT16 _StringDescriptor2[26] =
{
0x0334, 0x004E, 0x0075, 0x0076, 0x006F, 0x0074, 0x006F, 0x006E, 0x0020, 0x0041,
0x0052, 0x004D, 0x0020, 0x0039, 0x0032, 0x0036, 0x002D, 0x0042, 0x0061, 0x0073,
0x0065, 0x0064, 0x0020, 0x004D, 0x0043, 0x0055
};
void usbdClearAllFlags()
{
GET_VEN_Flag=0;
GET_VENO_Flag=0;
GET_DEV_Flag=0;
GET_CFG_Flag=0;
GET_QUL_Flag=0;
GET_OSCFG_Flag=0;
GET_STR_Flag=0;
usbdGetConfig=0;
usbdGetInterface=0;
usbdGetStatus=0;
}
void usbd_update_device()
{
//update this device for set requests
switch(_usb_cmd_pkt.bRequest)
{
case USBR_SET_ADDRESS:
outpw(REG_USBD_ADDR, _usbd_address);
break;
case USBR_SET_CONFIGURATION:
outpw(REG_USBD_EPA_RSP_SC, EP_TOGGLE);
outpw(REG_USBD_EPB_RSP_SC, EP_TOGGLE);
break;
case USBR_SET_INTERFACE:
break;
case USBR_SET_FEATURE:
if(_usbd_haltep == 0)
outpw(REG_USBD_CEP_CTRL_STAT, CEP_SEND_STALL);
else if(_usbd_haltep == 1)
outpw(REG_USBD_EPA_RSP_SC, EP_HALT);
else if(_usbd_haltep == 2)
outpw(REG_USBD_EPB_RSP_SC, EP_HALT);
else if(enableremotewakeup == 1)
{
enableremotewakeup = 0;
remotewakeup = 1;
}
else if(enabletestmode == 1)
{
enabletestmode = 0;
if(testselector == TEST_J)
outpw(REG_USBD_TEST, TEST_J);
else if(testselector==TEST_K)
outpw(REG_USBD_TEST, TEST_K);
else if(testselector==TEST_SE0_NAK)
outpw(REG_USBD_TEST, TEST_SE0_NAK);
else if(testselector==TEST_PACKET)
outpw(REG_USBD_TEST, TEST_PACKET);
else if(testselector==TEST_FORCE_ENABLE)
outpw(REG_USBD_TEST, TEST_FORCE_ENABLE);
}
break;
case USBR_CLEAR_FEATURE:
if(_usbd_unhaltep == 1 && _usbd_haltep == 1)
{
outpw(REG_USBD_EPA_RSP_SC, 0x0);
outpw(REG_USBD_EPA_RSP_SC, EP_TOGGLE);
_usbd_haltep = 4; // just for changing the haltep value
}
if(_usbd_unhaltep == 2 && _usbd_haltep == 2)
{
outpw(REG_USBD_EPB_RSP_SC, 0x0);
outpw(REG_USBD_EPB_RSP_SC, EP_TOGGLE);
_usbd_haltep = 4; // just for changing the haltep value
}
else if(disableremotewakeup == 1)
{
disableremotewakeup=0;
remotewakeup=0;
}
break;
default:
break;
}
}
void usbd_send_descriptor()
{
UINT32 temp_cnt;
int volatile i;
UINT16 *ptr;
if ((GET_DEV_Flag == 1) || (GET_QUL_Flag == 1) || (GET_CFG_Flag == 1) ||
(GET_OSCFG_Flag == 1) || (GET_STR_Flag == 1) || (CLASS_CMD_Flag == 1) ||
(usbdGetConfig == 1) || (usbdGetInterface == 1) || (usbdGetStatus == 1))
{
if (_usbd_remlen_flag == 0)
{
if (GET_DEV_Flag == 1)
ptr = _DeviceDescriptor;
else if (GET_QUL_Flag == 1)
ptr = _QualifierDescriptor;
else if (GET_CFG_Flag == 1)
{
if (_usbd_speedset == 2)
ptr = _ConfigurationBlock;
else if (_usbd_speedset == 1)
ptr = _ConfigurationBlockFull;
}
else if (GET_OSCFG_Flag == 1)
ptr = _OSConfigurationBlock;
else if (GET_STR_Flag == 1)
{
if ((_usb_cmd_pkt.wValue & 0xff) == 0)
ptr = _StringDescriptor0;
if ((_usb_cmd_pkt.wValue & 0xff) == 1)
ptr = _StringDescriptor1;
if ((_usb_cmd_pkt.wValue & 0xff) == 2)
ptr = _StringDescriptor2;
}
else if (CLASS_CMD_Flag == 1)
{
outpb(REG_USBD_CEP_DATA_BUF, 0x00);
outpw(REG_USBD_IN_TRNSFR_CNT, 1);
return;
}
else if (usbdGetConfig == 1)
{
outpb(REG_USBD_CEP_DATA_BUF, _usbd_confsel);
outpw(REG_USBD_IN_TRNSFR_CNT, 1);
return;
}
else if (usbdGetInterface == 1)
{
outpb(REG_USBD_CEP_DATA_BUF, _usbd_altsel);
outpw(REG_USBD_IN_TRNSFR_CNT, 1);
return;
}
else if (usbdGetStatus == 1)
{
outpw(REG_USBD_CEP_DATA_BUF, usbdGetStatusData);
outpw(REG_USBD_IN_TRNSFR_CNT, 2);
return;
}
}
else
ptr = _usbd_ptr;
if (_usb_cmd_pkt.wLength > 0x40)
{
_usbd_remlen_flag = 1;
_usbd_remlen = _usb_cmd_pkt.wLength - 0x40;
_usb_cmd_pkt.wLength = 0x40;
}
else if (_usbd_remlen != 0)
{
_usbd_remlen_flag = 0;
_usb_cmd_pkt.wLength = _usbd_remlen;
_usbd_remlen = 0;
}
else
{
_usbd_remlen_flag = 0;
_usbd_remlen = 0;
}
temp_cnt = _usb_cmd_pkt.wLength / 2;
for (i=0; i<temp_cnt; i++)
outpw(REG_USBD_CEP_DATA_BUF, *ptr++);
if ((_usb_cmd_pkt.wLength % 2) != 0)
outpb(REG_USBD_CEP_DATA_BUF, *ptr & 0xff);
if (_usbd_remlen_flag)
_usbd_ptr = ptr;
outpw(REG_USBD_IN_TRNSFR_CNT, _usb_cmd_pkt.wLength);
}
}
void usbd_control_packet()
{
UINT32 temp;
BOOL ReqErr;
temp = inpw(REG_USBD_SETUP1_0);
_usb_cmd_pkt.bmRequestType = (UINT8)temp & 0xff;
_usb_cmd_pkt.bRequest = (UINT8)(temp >> 8) & 0xff;
_usb_cmd_pkt.wValue = (UINT16)inpw(REG_USBD_SETUP3_2);
_usb_cmd_pkt.wIndex = (UINT16)inpw(REG_USBD_SETUP5_4);
_usb_cmd_pkt.wLength = (UINT16)inpw(REG_USBD_SETUP7_6);
// vendor command
if (_usb_cmd_pkt.bmRequestType == 0x40)
{
// uprintf("1");
// clear flags
usbdClearAllFlags();
GET_VENO_Flag=1;
Bulk_Out_Transfer_Size = 0;
if (_usb_cmd_pkt.bRequest == 0xa0)
{
if (_usb_cmd_pkt.wValue == 0x12)
{
// uprintf("--");
Bulk_Out_Transfer_Size = _usb_cmd_pkt.wIndex;
outpw(REG_USBD_CEP_CTRL_STAT, CEP_NAK_CLEAR); // clear nak so that sts stage is complete//lsshi
Bulk_First_Flag = 1;
}
else if (_usb_cmd_pkt.wValue == 0x13)
{
// uprintf("++");
// reset DMA
outpw(REG_USBD_DMA_CTRL_STS, 0x80);
outpw(REG_USBD_DMA_CTRL_STS, 0x00);
outpw(REG_USBD_EPA_RSP_SC, inpw(REG_USBD_EPA_RSP_SC)|0x01); // flush fifo
outpw(REG_USBD_EPB_RSP_SC, inpw(REG_USBD_EPB_RSP_SC)|0x01); // flush fifo
outpw(REG_USBD_EPA_RSP_SC, inpw(REG_USBD_EPA_RSP_SC)|0x00000008); // clear ep toggle
outpw(REG_USBD_CEP_CTRL_STAT, CEP_NAK_CLEAR); // clear nak so that sts stage is complete
Bulk_First_Flag = 0;
}
} else
// uprintf("==>%x<==", _usb_cmd_pkt.bRequest);
outpw(REG_USBD_CEP_IRQ_STAT, 0x400);
return;
}
if (_usb_cmd_pkt.bmRequestType == 0xc0)
{
// uprintf("2");
// clear flags
usbdClearAllFlags();
GET_VEN_Flag=1;
outpw(REG_USBD_CEP_IRQ_STAT, 0x408);
outpw(REG_USBD_CEP_IRQ_ENB, 0x408); //suppkt int ,status and in token
return;
}
// standard request
switch (_usb_cmd_pkt.bRequest)
{
// uprintf("3");
case USBR_GET_DESCRIPTOR:
//uprintf("\nUSBR_GET_DESCRIPTOR\n\n");
ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x80) && ((_usb_cmd_pkt.wValue & 0xf000) == 0)
&& ((_usb_cmd_pkt.wValue & 0x80) == 0)) ? 0 : 1;
if(ReqErr==1)
{
MSG_DEBUG("GET_DESCRIPTOR => 0[%x], 2[%x], 4[%x], 6[%x]\n", inpw(REG_USBD_SETUP1_0),
inpw(REG_USBD_SETUP3_2), inpw(REG_USBD_SETUP5_4), inpw(REG_USBD_SETUP7_6));
break; //break this switch loop
}
switch ((_usb_cmd_pkt.wValue & 0xf00) >> 8)
{ //high byte contains desc type so need to shift???
case USB_DT_DEVICE:
// clear flags
usbdClearAllFlags();
GET_DEV_Flag = 1;
if (_usb_cmd_pkt.wLength > DEVICE_DSCPT_LEN)
_usb_cmd_pkt.wLength = DEVICE_DSCPT_LEN;
break;
case USB_DT_CONFIG:
// clear flags
usbdClearAllFlags();
GET_CFG_Flag = 1;
if (_usb_cmd_pkt.wLength > CONFIG_DSCPT_LEN)
_usb_cmd_pkt.wLength = CONFIG_DSCPT_LEN;
break;
case USB_DT_QUALIFIER: // high-speed operation
// clear flags
usbdClearAllFlags();
GET_QUL_Flag = 1;
if (_usb_cmd_pkt.wLength > QUALIFIER_DSCPT_LEN)
_usb_cmd_pkt.wLength = QUALIFIER_DSCPT_LEN;
break;
case USB_DT_OSCONFIG: // other speed configuration
// clear flags
usbdClearAllFlags();
GET_OSCFG_Flag = 1;
if (_usb_cmd_pkt.wLength > OSCONFIG_DSCPT_LEN)
_usb_cmd_pkt.wLength = OSCONFIG_DSCPT_LEN;
break;
case USB_DT_STRING:
// clear flags
usbdClearAllFlags();
GET_STR_Flag = 1;
if ((_usb_cmd_pkt.wValue & 0xff) == 0)
{
if (_usb_cmd_pkt.wLength > STR0_DSCPT_LEN)
_usb_cmd_pkt.wLength = STR0_DSCPT_LEN;
}
else if ((_usb_cmd_pkt.wValue & 0xff) == 1)
{
if (_usb_cmd_pkt.wLength > STR1_DSCPT_LEN)
_usb_cmd_pkt.wLength = STR1_DSCPT_LEN;
}
else if ((_usb_cmd_pkt.wValue & 0xff) == 2)
{
if (_usb_cmd_pkt.wLength > STR2_DSCPT_LEN)
_usb_cmd_pkt.wLength = STR2_DSCPT_LEN;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -