📄 usbch9.c
字号:
/*
* usbch9.c
*
* USB device communications - "Standard Request" layer,
* conforming to the USB 2.0 specification, Chapter 9.
*
* Adapted from Philips PDIUSBD12 firmware library.
* MJB Nov 2005
*/
#include "gendef.h"
#include "usbdef.h"
#include "usbhal.h"
#include "usbci.h"
#include "usb200.h"
#include "usbch9.h"
#define NUM_ENDPOINTS 2 /* Number of endpoints (In + Out) required by the device */
/*
* Device descriptors need to be customised to suit the application.
*
* Endpoints defined for the device interface, excluding control endpoints (EP0 in/out):
* For CDC (Communications Device Class) devices:
* Bulk IN (EP2 in) + Bulk OUT (EP2 out) = 2 endpoints (mandatory).
* For USBTMC (Test and Measurment Class) devices:
* Bulk IN (EP2 in) + Bulk OUT (EP2 out) = 2 endpoints (mandatory).
* Interrupt IN (EP1 in) += 1 endpoint (required if device has "interrupt" capability).
*/
const USB_DEVICE_DESCRIPTOR DeviceDescr =
{
sizeof(USB_DEVICE_DESCRIPTOR), /* bLength ( =18 =0x12) */
USB_DEVICE_DESCRIPTOR_TYPE, /* descriptor type */
SWAP(0x0200), /* bcdUSB = 02.00 */
0x00, /* device class (see Interface Desc.) */
0x00, /* device subclass ( .. .. .. ) */
0x00, /* device protocol ( .. .. .. ) */
EP0_MAX_PACKET_SIZE, /* max packet size for EP0 (16) */
SWAP(0xABCD), /* vendor code (allocated by USB-IF) */
SWAP(0x1234), /* product code, BCD */
SWAP(0x0100), /* device release number, BCD */
MANUFACTURER_STR_ID, /* manufacturer string idx (0 if none) */
PRODUCT_NAME_STR_ID, /* product string idx (0 if none) */
SERIAL_NUM_STR_ID, /* serial number string idx (0 if none) */
1 /* number of configurations */
};
#if ( NUM_ENDPOINTS == 3 )
#define PACKED_USB_CONFIG_DESCR_LEN 39
#else
#define PACKED_USB_CONFIG_DESCR_LEN 32
#endif
/*
* The Configuration Descriptor must be bytewise packed (no alignment or stuff bytes).
* Interface class and subclass codes are defined according to the device usage.
* (Refer to relevant USB Class Specification for allocated codes.)
*/
const PACKED_USB_CONFIG_DESCR PackedConfigDescr =
{
9, /* bLength */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* descriptor type */
SWAP( PACKED_USB_CONFIG_DESCR_LEN ), /* length of packed config descr. (16b) */
0x01, /* number of interfaces */
0x01, /* configuration value */
0x00, /* configuration string index (none) */
0xC0, /* attributes (self-powered, no remote wakeup) */
0x01, /* max power */
9, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* descriptor type */
0x00, /* interface number */
0x00, /* alternate setting */
NUM_ENDPOINTS, /* number of endpoints (excl. EP0) */
0xFE, /* interface class (USBTMC=0xFE) */
0x03, /* interface subclass (USB488=0x03) */
0x01, /* interface protocol */
0x00, /* interface string index (none) */
7, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* descriptor type */
0x82, /* Endpoint dir'n (IN) & addr */
USB_ENDPOINT_TYPE_BULK, /* Endpoint type */
LO_BYTE( EP2_MAX_PACKET_SIZE ), /* Maximum pkt size (64) */
HI_BYTE( EP2_MAX_PACKET_SIZE ),
10, /* Interval - usually ignored for bulk */
7, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* descriptor type */
0x02, /* Endpoint dir'n (OUT) & addr */
USB_ENDPOINT_TYPE_BULK, /* Endpoint type */
LO_BYTE( EP2_MAX_PACKET_SIZE ), /* Maximum pkt size (64) */
HI_BYTE( EP2_MAX_PACKET_SIZE ),
10, /* Interval - usually ignored for bulk */
7, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* descriptor type */
0x81, /* Endpoint dir'n (IN) & addr */
USB_ENDPOINT_TYPE_INTERRUPT, /* Endpoint type */
LO_BYTE( EP1_MAX_PACKET_SIZE ), /* Maximum pkt size (4) */
HI_BYTE( EP1_MAX_PACKET_SIZE ),
10 /* Polling interval (unit=frame=1mS) */
};
/**************
* String Descriptors...
* NB: !! Ensure that bString[ ] sizes are defined correctly (in usbch9.h) !!
* The Language String Descriptor is mandatory for USB2.0 compliance;
* all the others are optional. (Put string index = 0 to disable string descriptor.)
* The Unicode strings are NOT NUL-terminated.
*/
const struct USB_STRING_DESCR_LANG stringDescLang =
{
sizeof(stringDescLang),
USB_STRING_DESCRIPTOR_TYPE,
SWAP( UNICODE_ENGLISH )
};
const struct USB_STRING_DESCR_MANU stringDescManu =
{
sizeof(stringDescManu),
USB_STRING_DESCRIPTOR_TYPE,
{ /*** Unicode string -- manufacturer name ***/ }
};
const struct USB_STRING_DESCR_PROD stringDescProd =
{
sizeof(stringDescProd),
USB_STRING_DESCRIPTOR_TYPE,
{ /*** Unicode string -- product name ***/ }
};
const struct USB_STRING_DESCR_SNUM stringDescSNum =
{
sizeof(stringDescSNum),
USB_STRING_DESCRIPTOR_TYPE,
{ /*** Unicode string -- serial number ***/ }
};
/************************************************************************** */
/* USB2.0 protocol standard device requests - function table */
/************************************************************************** */
const pfnvoid StandardDeviceRequest[] =
{
get_status, /* 0 */
clear_feature, /* 1 */
req_undefined, /* 2 reserved in USB2.0 */
set_feature, /* 3 */
req_undefined, /* 4 reserved in USB2.0 */
set_address, /* 5 */
get_descriptor, /* 6 */
req_undefined, /* 7 set_descriptor -- not supported */
get_configuration, /* 8 */
set_configuration, /* 9 */
get_interface, /* 10 */
set_interface, /* 11 */
req_undefined, /* 12 synch_frame -- not supported */
};
void get_status(void)
{
uchar endp, txdat[2];
uchar bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT_MASK;
uchar c;
if ( bRecipient == USB_RECIPIENT_DEVICE )
{
if ( USBflags.bits.remote_wakeup ) txdat[0] = 3;
else txdat[0] = 1;
txdat[1]=0;
single_transmit( txdat, 2 );
}
else if ( bRecipient == USB_RECIPIENT_INTERFACE )
{
txdat[0]=0;
txdat[1]=0;
single_transmit( txdat, 2 );
}
else if ( bRecipient == USB_RECIPIENT_ENDPOINT )
{
endp = (uchar)(ControlData.DeviceRequest.wIndex & MAX_EP_MASK);
if ( ControlData.DeviceRequest.wIndex & USB_ENDPOINT_DIRECTION_MASK )
c = D12_SelectEndpoint( endp*2 + 1 );
else
c = D12_SelectEndpoint( endp*2 );
if ( c & D12_STALL ) txdat[0] = 1;
else txdat[0] = 0;
txdat[1] = 0;
single_transmit( txdat, 2 );
}
else stall_ep0();
}
void clear_feature( void )
{
uchar endpointIndex;
uchar bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT_MASK;
if ( bRecipient == USB_RECIPIENT_DEVICE )
{
if ( ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP )
{
DISABLE_USB_IRQ;
USBflags.bits.remote_wakeup = FALSE; /* Disable Remote Wake-up */
RESTORE_USB_IRQ;
single_transmit( 0, 0 ); /* Ack */
}
else if ( ControlData.DeviceRequest.wValue == USB_FEATURE_TEST_MODE )
{
/* The TEST_MODE feature cannot be cleared by the CLEAR_FEATURE request... */
single_transmit( 0, 0 ); /* ... (Ref: USB 2.0 spec. $9.4.1) */
}
}
else if ( bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_HALT )
{
endpointIndex = 2 * (uchar)(ControlData.DeviceRequest.wIndex & MAX_EP_MASK);
if ( ControlData.DeviceRequest.wIndex & USB_ENDPOINT_DIRECTION_MASK )
endpointIndex++; /* Direction is IN (to host) */
D12_SetEndpointStatus( endpointIndex, 0 ); /* Clear specified endpoint */
debug_signal( BIT_10 );
/*** Perform here any specific Device Class requirements ***/
single_transmit( 0, 0 ); /* Ack */
}
else
{
stall_ep0();
}
}
void set_feature(void)
{
uchar endpointIndex;
uchar bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT_MASK;
if ( bRecipient == USB_RECIPIENT_DEVICE )
{
if ( ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
{
DISABLE_USB_IRQ;
USBflags.bits.remote_wakeup = TRUE; /* Enable Remote Wake-up */
RESTORE_USB_IRQ;
single_transmit(0, 0);
}
else if ( ControlData.DeviceRequest.wValue == USB_FEATURE_TEST_MODE )
{
DISABLE_USB_IRQ;
USBflags.bits.test_mode = TRUE; /* Enable TEST_MODE feature */
RESTORE_USB_IRQ;
single_transmit( 0, 0 );
}
}
else if ( bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_HALT)
{
endpointIndex = 2 * (uchar)(ControlData.DeviceRequest.wIndex & MAX_EP_MASK);
if ( ControlData.DeviceRequest.wIndex & USB_ENDPOINT_DIRECTION_MASK )
endpointIndex++; /* Direction is IN (to host) */
D12_SetEndpointStatus( endpointIndex, 1 ); /* Stall (halt) specified endpoint */
single_transmit( 0, 0 ); /* Ack */
}
else
{
stall_ep0();
}
}
void set_address(void)
{
uchar bAddr;
bAddr = (LO_BYTE(ControlData.DeviceRequest.wValue)) & DEVICE_ADDRESS_MASK;
D12_SetAddressEnable( bAddr, 1 );
single_transmit( 0, 0 ); /* Ack */
}
void get_descriptor(void)
{
uchar bDescriptorType = HI_BYTE(ControlData.DeviceRequest.wValue);
uchar bDescriptorIndex = LO_BYTE( ControlData.DeviceRequest.wValue );
ushort wIndex = ControlData.DeviceRequest.wIndex; /* Lang_ID or zero */
ushort wLength = ControlData.DeviceRequest.wLength;
ushort ReplyLen;
if ( bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE )
{
ReplyLen = LESSER_OF( sizeof(USB_DEVICE_DESCRIPTOR), wLength );
control_transmit( (const uchar *) &DeviceDescr, ReplyLen );
}
else if ( bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE )
{
ReplyLen = LESSER_OF( PACKED_USB_CONFIG_DESCR_LEN, wLength );
control_transmit( (const uchar *) &PackedConfigDescr, ReplyLen );
}
else if ( bDescriptorType == USB_STRING_DESCRIPTOR_TYPE )
{
switch( bDescriptorIndex )
{
case UNICODE_LANGUAGE_STR_ID: /* primary language code */
ReplyLen = LESSER_OF( sizeof(stringDescLang), wLength );
control_transmit( (const uchar *) &stringDescLang, ReplyLen );
break;
case MANUFACTURER_STR_ID: /* manufacturer string */
ReplyLen = LESSER_OF( sizeof(stringDescManu), wLength );
control_transmit( (const uchar *) &stringDescManu, ReplyLen );
break;
case PRODUCT_NAME_STR_ID: /* product name string */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -