⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 用ST92163开发的鼠标
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -