📄 usb.c
字号:
#include <cpu.h>
#include <kbd_desc.h>
#include <mouse_desc.h>
#include <joy_desc.h>
#include <version.h>
#include <usb.h>
#define USB_bmRequestType 0
#define USB_bRequest 1
#define USB_wValue 2
#define USB_wValueHi 3
#define USB_wIndex 4
#define USB_wIndexHi 5
#define USB_wLength 6
#define USB_wLengthHi 7
/* bmRequest constants */
#define HOST_TO_DEVICE 0x00
#define DEVICE_TO_HOST 0x80
#define CLASS_REQUEST 0x20
#define STANDARD_REQUEST 0x00
#define DEVICE_RECIPIENT 0x00
#define INTERFACE_RECIPIENT 0x01
#define ENDPOINT_RECIPIENT 0x02
#define OTHER_RECIPIENT 0x03
/* bRequest constants */
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
#define SYNCH_FRAME 12
#define INT_RESET 0x04
#define INT_SUSP 0x08
#define INT_ESUSP 0x10
typedef enum PORT_FEATURE_SELECTOR {
PORT_CONNECTION = 0,
PORT_ENABLE,
PORT_SUSPEND,
PORT_OVER_CURRENT,
PORT_RESET,
PORT_POWER = 8,
PORT_LOW_SPEED,
C_PORT_CONNECTION = 16,
C_PORT_ENABLE,
C_PORT_SUSPEND,
C_PORT_OVER_CURRENT,
C_PORT_RESET
} PORT_FEATURE_SELECTOR ;
BYTE RxBuffer[ NUMBER_OF_DEVICE][ MAX_PACKET_SIZE] ;
BYTE CurDevice ;
BYTE *CurRxBuffer ;
BYTE data_size[ NUMBER_OF_DEVICE] ;
BYTE *data_ptr ;
BYTE fsm_state[ NUMBER_OF_DEVICE] ;
BYTE address[ NUMBER_OF_DEVICE] ;
BYTE configuration_status[ NUMBER_OF_DEVICE] ;
BYTE remote_wakeup_status[ NUMBER_OF_DEVICE] ;
BYTE endpoint_stall[ NUMBER_OF_DEVICE] ;
static BYTE protocol_status ;
static BYTE ep1_tx_ready ;
#pragma register_file EP0TxAddr 0
extern volatile void *EP0TxAddr ;
#pragma register_file EP0TxCount 2
extern volatile WORD EP0TxCount ;
#pragma register_file EP0RxAddr 4
extern volatile void *EP0RxAddr ;
#pragma register_file EP0RxCount 6
extern volatile WORD EP0RxCount ;
#pragma register_file EP1TxAddr 8
extern volatile void *EP1TxAddr ;
#pragma register_file EP1TxCount 10
extern volatile WORD EP1TxCount ;
//#pragma register_file EP1RxAddr 12
//extern volatile void *EP1RxAddr ;
//#pragma register_file EP1RxCount 14
//extern volatile WORD EP1RxCount ;
#define HUB_SIZ_DEVICE_DESC 18
const BYTE HUB_DeviceDescriptor[ HUB_SIZ_DEVICE_DESC] = {
0x12, // bLength
0x01, // bDescriptorType
0x10, 0x01, // bcdUSB (spec release # 1.10)
0x09, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
0x08, // bMaxPacketSize0
0xB7, 0x0E, // idVendor
0x15, 0x00, // idProduct
V_MINOR, V_MAJOR, // bcdDevice ex: 2.02
1, // Index of string Descriptor describing manufacturer
2, // Index of string Descriptor describing product
0, // Index of string Descriptor describing the device's serial number
0x01 // bNumConfigurations (Only one config)
} ;
static const struct {
BYTE size ;
const BYTE *desc ;
} UsbDeviceDesc[] = {
{ sizeof HUB_DeviceDescriptor, HUB_DeviceDescriptor},
{ KEYBOARD_SIZ_DEVICE_DESC, KEYBOARD_DeviceDescriptor},
{ MOUSE_SIZ_DEVICE_DESC, MOUSE_DeviceDescriptor},
{ JOYSTICK_SIZ_DEVICE_DESC, JOYSTICK_DeviceDescriptor}
} ;
#define HUB_SIZ_CONFIG_DESC 25
const BYTE HUB_ConfigDescriptor[ HUB_SIZ_CONFIG_DESC] = {
// Configuration descriptor
0x09, // bLength: Configuration Descriptor size
0x02, // bDescriptorType: Configuration
HUB_SIZ_CONFIG_DESC, // Length of configuration descriptor.
0, // MSB Length of configuration descriptor.
0x01, // bNumInterfaces: 1 interfaces.
0x01, // bConfigurationValue: Configuration value = 1
0, // iConfiguration: Index of string descriptor describing the configuration (None)
0x80, // bmAttributes: Bus powered and NO Remote wakeup
// 0xA0, // bmAttributes: Bus powered and Remote wakeup
// 0xC0, // bmAttributes: Self powered and NO Remote wakeup
// 0xE0, // bmAttributes: Self powered and Remote wakeup
0x32, // MaxPower 100 mA
// Interface descriptor (Interface 0 = DemoKit)
0x09, // bLength: Interface Descriptor size
0x04, // bDescriptorType: Interface descriptor type
0x00, // bInterfaceNumber: Interface Number = 0
0x00, // bAlternateSetting: No Alternate setting
0x01, // bNumEndpoints: one endpoints used
0x09, // bInterfaceClass: HID
0x00, // bInterfaceSubClass: No subclass
0x00, // bInterfaceProtocol: none
0x00, // iInterface: Index of string descriptor (No string value)
// 0x02, // iInterface: Index of string descriptor (No string value)
// Endpoint 1 descriptor (Demokit)
0x07, // bLength: Endpoint Descriptor size
0x05, // bDescriptorType: Endpoint descriptor type
0x81, // bEndpointAddress: Endpoint 1 IN
0x03, // bmAttributes: Interrupt endpoint
0x01, // wMaxPacketSize(LSB): 1 Byte max (0x0001)
0x00, // wMaxPacketSize (MSB)
0xFF // bInterval: Polling Interval (10 ms = 0x0A)
} ;
static const struct {
BYTE size ;
const BYTE *desc ;
} UsbConfigDesc[] = {
{ sizeof HUB_ConfigDescriptor, HUB_ConfigDescriptor},
{ KEYBOARD_SIZ_CONFIG_DESC, KEYBOARD_ConfigDescriptor},
{ MOUSE_SIZ_CONFIG_DESC, MOUSE_ConfigDescriptor},
{ JOYSTICK_SIZ_CONFIG_DESC, JOYSTICK_ConfigDescriptor}
} ;
#define HUB_SIZ_REPORT_DESC 9
const BYTE HUB_ReportDescriptor[ HUB_SIZ_REPORT_DESC] = {
HUB_SIZ_REPORT_DESC, /* size */
0x29, /* Hub Descriptor */
0x03, /* Number of downstream ports */
0x14, /* LSB HUB Characteristic */
0x00, /* MSB */
0x10, /* PwrOn2PwrGood */
0x64, /* Max current */
0x0F, /* non removeable device on Port 1, 2 and 3 */
0xFF
} ;
static const struct {
BYTE size ;
const BYTE *desc ;
} UsbReportDesc[] = {
{ sizeof HUB_ReportDescriptor, HUB_ReportDescriptor},
{ KEYBOARD_SIZ_REPORT_DESC, KEYBOARD_ReportDescriptor},
{ MOUSE_SIZ_REPORT_DESC, MOUSE_ReportDescriptor},
{ JOYSTICK_SIZ_REPORT_DESC, JOYSTICK_ReportDescriptor}
} ;
static BYTE main_device = 0 ;
void HUB_reset( BYTE active)
{
EP0RxAddr = RxBuffer[ 0] ;
EP0RxCount = MAX_PACKET_SIZE ;
EP0TxAddr = 0 ; /* Insure there is a valid Tx address in case of a STATUS IN */
configuration_status[ 0] = 0 ;
spp( USB_EP0_PG) ;
EP0RA |= 0x02 ; /* EP0 is Control endpoint */
EP0RA &= ~0x30 ; /* EP0 TX STAT_DISABLED */
EP0RB |= 0x30 ; /* EP0 RX STAT_VALID */
ENDPR1_A &= ~0x30 ; /* EP1 TX STAT_DISABLED */
ENDPR1_B &= ~0x30 ; /* EP1 RX STAT_DISABLED */
ENDPR1_B |= 0x1 ; /* EP1 is Device 0 Endpoint 1 */
spp( USB_COMMON_PG) ;
DADDR0 = active ? (0 | 0x80) : 0 ; /* EP0 default address */
}
#pragma INTERRUPT usb_int
void usb_int( void)
{
spp( USB_COMMON_PG) ;
if( ISTR & IMR & INT_RESET)
{
if( main_device == 0)
HUB_reset( 1) ;
else
MOUSE_reset() ;
// KEYBOARD_reset() ;
// MOUSE_reset() ;
// JOYSTICK_reset() ;
spp( USB_COMMON_PG) ;
IMR = INT_RESET | INT_SUSP | INT_ESUSP ;
ISTR = 0 ;
}
else
{
if( (ISTR & IMR & (INT_SUSP | INT_ESUSP)) == (INT_SUSP | INT_ESUSP))
{
nop() ;
}
if( ISTR & IMR & INT_SUSP)
{
do
{
spp( EXINT_PG) ;
EIPR = 0x0 ; /* Clear pending bits */
spp( USB_COMMON_PG) ;
CTLR |= 0x40 ; /* set TIM_SUSP */
spp( WU_PG) ;
WU_WUPRH = 0 ; /* Clear pending bits */
WU_WUPRL = 0 ;
WU_WUTRH = 0x80 ; /* Trigger on raising edge */
WU_WUMRH = 0x80 ;
spp( USB_COMMON_PG) ;
CTLR |= 0x02 ; /* set LP_SUSP */
spp( WU_PG) ;
WU_CTLR = 0x05 ; /* Set STOP, IDS1 and WKUP-INT bits */
WU_CTLR = 0x01 ; /* Set IDS1 and WKUP-INT bit */
WU_CTLR = 0x05 ; /* Set STOP, IDS1 and WKUP-INT bits */
nop() ;
nop() ;
nop() ;
nop() ;
nop() ;
nop() ;
}
while( WU_CTLR & 0x04) ;
spp( RCCU_PG) ;
while( !( CLK_FLAG & 0x02)) ; /* Wait PLL is locked */
CLK_FLAG |= 0x1 ; /* Set PLL as INTCLK */
spp( WU_PG) ;
if( ValBit( WU_WUPRH, 7))
WU_WUPRH &= ~0x80 ; /* Clear pending bit */
else
nop() ;
spp( USB_COMMON_PG) ;
ISTR &= ~INT_SUSP ;
}
if( ISTR & IMR & INT_ESUSP)
{
spp( USB_COMMON_PG) ;
CTLR &= ~0x40 ; /* Clear TIM_SUSP */
spp( USB_COMMON_PG) ;
ISTR &= ~INT_ESUSP ;
}
}
}
static BYTE control_read( void)
{
if( ( CurRxBuffer[ USB_wLengthHi] == 0)
&& ( CurRxBuffer[ USB_wLength] != 0)
&& ( CurRxBuffer[ USB_wLength] < data_size[ CurDevice]))
{
data_size[ CurDevice] = CurRxBuffer[ USB_wLength] ;
}
return TX_N ;
}
#define LENGTH_STRING_DESCRIPTOR 4
static const BYTE Comm_StringDescriptor[ LENGTH_STRING_DESCRIPTOR] = {
LENGTH_STRING_DESCRIPTOR,
0x03,
0x09,
0x04 /* LangID = 0x0409: U.S. English */
};
#define LENGTH_STRING_VENDOR 16
static const BYTE StringVendor[ LENGTH_STRING_VENDOR] = {
LENGTH_STRING_VENDOR, /* Size of manufaturer string */
0x03, /* bDescriptorType = String descriptor */
/* Manufacturer: "Fanatec" */
'F', 0, 'a', 0, 'n', 0, 'a', 0, 't', 0, 'e', 0, 'c', 0
};
#define HUB_LENGTH_STRING_PRODUCT 28
static const BYTE HUB_StringProduct[ HUB_LENGTH_STRING_PRODUCT] = {
HUB_LENGTH_STRING_PRODUCT,
0x03,
/* Product name: "GameBoard Hub" */
'G', 0, 'a', 0, 'm', 0, 'e', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0,
'H', 0, 'u', 0, 'b', 0
} ;
#define KBD_LENGTH_STRING_PRODUCT 38
static const BYTE KBD_StringProduct[ KBD_LENGTH_STRING_PRODUCT] = {
KBD_LENGTH_STRING_PRODUCT,
0x03,
/* Product name: "GameBoard Keyboard" */
'G', 0, 'a', 0, 'm', 0, 'e', 0, 'B', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0,
'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0
} ;
#define MS_LENGTH_STRING_PRODUCT 32
static const BYTE MOUSE_StringProduct[ MS_LENGTH_STRING_PRODUCT] = {
MS_LENGTH_STRING_PRODUCT,
0x03,
/* Product name: "GameBoard Mouse" */
'G', 0, 'a', 0, 'm', 0, 'e', 0, 'B', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0,
'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0
} ;
#define JOY_LENGTH_STRING_PRODUCT 38
static const BYTE JOY_StringProduct[ JOY_LENGTH_STRING_PRODUCT] = {
JOY_LENGTH_STRING_PRODUCT,
0x03,
/* Product name: "GameBoard Joystick" */
'G', 0, 'a', 0, 'm', 0, 'e', 0, 'B', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0,
'J', 0, 'o', 0, 'y', 0, 's', 0, 't', 0, 'i', 0, 'c', 0, 'k', 0
} ;
static const struct {
BYTE size ;
const BYTE *string ;
} UsbString[] = {
{ sizeof Comm_StringDescriptor, Comm_StringDescriptor},
{ sizeof StringVendor, StringVendor},
{ sizeof HUB_StringProduct, HUB_StringProduct},
{ sizeof KBD_StringProduct, KBD_StringProduct},
{ sizeof MOUSE_StringProduct, MOUSE_StringProduct},
{ sizeof JOY_StringProduct, JOY_StringProduct}
} ;
static BYTE GetStringDescriptor( void)
{
BYTE val ;
val = CurRxBuffer[ USB_wValue] ;
if( val < (sizeof UsbString / sizeof UsbString[ 0]))
{
data_size[ CurDevice] = UsbString[ val].size ;
data_ptr = (BYTE *)UsbString[ val].string ;
return control_read() ;
}
else
{
return TX_STALL ;
}
}
static BYTE get_descriptor( void)
{
switch( CurRxBuffer[ USB_wValueHi])
{
case 0x01: /* USB_DEVICE */
data_size[ CurDevice] = UsbDeviceDesc[ CurDevice].size ;
data_ptr = (BYTE *) UsbDeviceDesc[ CurDevice].desc ;
return control_read() ;
break ;
case 2: /* USB_CONFIGURATION */
data_size[ CurDevice] = UsbConfigDesc[ CurDevice].size ;
data_ptr = (BYTE *) UsbConfigDesc[ CurDevice].desc ;
return control_read() ;
break ;
case 3: /* USB_STRING */
return GetStringDescriptor() ;
break ;
case 0x21: /* USB_HID (useless for HUB)*/
data_size[ CurDevice] = 9 ;
data_ptr = (BYTE *) &UsbConfigDesc[ CurDevice].desc[ 18] ;
return control_read() ;
break ;
case 0x22: /* USB_REPORT */
// data_size = sizeof hid_report_descriptor ;
// data_ptr = hid_report_descriptor ;
// control_read() ;
data_size[ CurDevice] = UsbReportDesc[ CurDevice].size ;
data_ptr = (BYTE *) UsbReportDesc[ CurDevice].desc ;
return control_read() ;
break ;
// case 0x23: /* USB_PHYSICAL */
// send_stall() ;
// break ;
default:
return TX_STALL ;
}
}
static BYTE GetConfiguration( void)
{
static const BYTE get_configuration_status_table[] =
{
0x00, /* not configured */
0x01 /* configured */
} ;
data_size[ CurDevice] = 1 ;
data_ptr = (BYTE *) &get_configuration_status_table[ configuration_status[ CurDevice]] ;
return control_read() ;
}
static BYTE GetEndpointStatus( void)
{
static const BYTE get_endpoint_status_table[] =
{
0x00, 0x00, /* not stalled */
0x01, 0x00 /* stalled */
} ;
data_size[ CurDevice] = 2 ;
data_ptr = (BYTE *) &get_endpoint_status_table[ endpoint_stall[ CurDevice] << 1] ;
return control_read() ;
}
static BYTE set_address()
{
address[ CurDevice] = CurRxBuffer[ USB_wValue] ; /* Save address value to be set after acknowledge */
return TX_ACK_ADDR ;
}
static BYTE GetDeviceStatus( void) {
static const char get_dev_status_table[] = {
0x00, 0x00, /* remote wakeup disabled, bus powered */
0x02, 0x00 /* remote wakeup enabled, bus powered */
} ;
data_size[ CurDevice] = 2 ;
data_ptr = (BYTE *) &get_dev_status_table[ remote_wakeup_status[ CurDevice]] ;
return control_read() ;
}
static void HUB_set_configuration( BYTE configuration_status)
{
if( configuration_status == 0)
{
/* device is not configured */
ENDPR1_A &= ~0x30 ; /* Disable Tx */
ep1_tx_ready = 0 ;
}
else
{
/* device is configured */
ENDPR1_A &= ~0x30 ;
ENDPR1_A |= 0x20 ; /* Tx STAT_NAK */
ep1_tx_ready = 1 ;
}
}
static BYTE set_configuration( void)
{
/* We have only one configuration per device */
if( ( CurRxBuffer[ USB_wValue] != 0) && (CurRxBuffer[ USB_wValue] != 1) )
{
return TX_STALL ;
}
else
{
configuration_status[ CurDevice] = CurRxBuffer[ USB_wValue] ;
endpoint_stall[ CurDevice] = 0 ;
switch( CurDevice)
{
extern void KEYBOARD_set_configuration( BYTE configuration_status) ;
extern void MOUSE_set_configuration( BYTE configuration_status) ;
extern void JOYSTICK_set_configuration( BYTE configuration_status) ;
case 0:
HUB_set_configuration( configuration_status[ CurDevice]) ;
break ;
case 1:
KEYBOARD_set_configuration( configuration_status[ CurDevice]) ;
break ;
case 2:
MOUSE_set_configuration( configuration_status[ CurDevice]) ;
break ;
case 3:
JOYSTICK_set_configuration( configuration_status[ CurDevice]) ;
break ;
default:
return TX_STALL ;
}
return TX_0 ;
}
}
static BYTE P_Status[ 3][ 4] /* = {
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0}
} */ ;
static BYTE HUB_SetPortFeature( void)
{
BYTE idx ;
idx = CurRxBuffer[ USB_wIndex] - 1 ;
if( idx > 2) /* Port 3 is idx == 2 */
{
return TX_STALL ;
}
switch( CurRxBuffer[ USB_wValue])
{
case PORT_POWER:
P_Status[ idx][ 1] |= 1 ; /* Powered */
P_Status[ idx][ 0] |= 1 ; /* Connected */
P_Status[ idx][ 2] |= 1 ; /* C_Connect */
break ;
case PORT_RESET:
P_Status[ idx][ 0] |= 0x02 ; /* Enable */
P_Status[ idx][ 2] |= 0x10 ; /* C_Reset */
P_Status[ idx][ 0] &= ~0x04 ; /* Clear Suspend */
switch( idx)
{
case 0:
KEYBOARD_reset() ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -