Files
firmware/right/usb_descriptor.c
László Monda 946de98ac5 Add source.
2016-02-01 00:53:35 +01:00

734 lines
23 KiB
C

#include "usb_device_config.h"
#include "usb.h"
#include "usb_device_stack_interface.h"
#include "usb_descriptor.h"
#include "mouse.h"
#include "composite_app.h"
///////////////////////////////// Keyboard endpoint and interface /////////////////////////////////
usb_ep_struct_t keyboard_endpoint[HID_DESC_ENDPOINT_COUNT] =
{
{
HID_ENDPOINT,
USB_INTERRUPT_PIPE,
USB_SEND,
FS_INTERRUPT_OUT_ENDP_PACKET_SIZE,
}
};
usb_endpoints_t keyboard_endpoints =
{
HID_DESC_ENDPOINT_COUNT,
keyboard_endpoint
};
static usb_if_struct_t keyboard_interface[1];
/////////////////////////////////// Mouse endpoint and interface ///////////////////////////////////
usb_ep_struct_t mouse_endpoint[HID_DESC_ENDPOINT_COUNT] =
{
{
HID_ENDPOINT,
USB_INTERRUPT_PIPE,
USB_SEND,
FS_INTERRUPT_OUT_ENDP_PACKET_SIZE,
}
};
usb_endpoints_t mouse_endpoints =
{
HID_DESC_ENDPOINT_COUNT,
mouse_endpoint
};
static usb_if_struct_t mouse_interface[1];
////////////////////////////////////// USB class descriptors //////////////////////////////////////
usb_class_struct_t usb_interfaces[2] =
{
{
USB_CLASS_HID,
{
1,
keyboard_interface
}
},
{
USB_CLASS_HID,
{
1,
mouse_interface
}
},
};
static usb_composite_info_struct_t usb_composite_info =
{
2,
usb_interfaces
};
uint8_t g_device_descriptor[DEVICE_DESCRIPTOR_SIZE] =
{
DEVICE_DESCRIPTOR_SIZE, /* "Device Descriptor Size */
USB_DEVICE_DESCRIPTOR, /* "Device" Type of descriptor */
0x00,0x02, /* BCD USB version */
0x00, /* Device Class is indicated in
the interface descriptors */
0x00, /* Device Subclass is indicated
in the interface descriptors */
0x00, /* Device Protocol */
CONTROL_MAX_PACKET_SIZE, /* Max Packet size */
0xa2,0x15, /* Vendor ID */
0x00, 0x02, /* Product ID */
0x00, 0x02, /* BCD Device version */
0x01, /* Manufacturer string index */
0x02, /* Product string index */
0x00, /* Serial number string index */
0x01 /* Number of configurations */
};
uint8_t g_config_descriptor[CONFIG_DESC_SIZE] =
{
CONFIG_ONLY_DESC_SIZE, /* Configuration Descriptor Size - always 9 bytes*/
USB_CONFIG_DESCRIPTOR, /* "Configuration" type of descriptor */
CONFIG_DESC_SIZE, 0x00, /* Total length of the Configuration descriptor */
0x02, /* NumInterfaces */
0x01, /* Configuration Value */
0, /* Configuration Description String Index*/
/* Attributes.support RemoteWakeup and self power */
(USB_DESC_CFG_ATTRIBUTES_D7_POS) | (USBCFG_DEV_SELF_POWER << USB_DESC_CFG_ATTRIBUTES_SELF_POWERED_SHIFT) | (USBCFG_DEV_REMOTE_WAKEUP << USB_DESC_CFG_ATTRIBUTES_REMOTE_WAKEUP_SHIFT),
/* S08/CFv1 are both self powered (its compulsory to set bus powered)*/
/*Attributes.support RemoteWakeup and self power*/
0x32, /* Current draw from bus */
/* Keyboard Interface Descriptor */
IFACE_ONLY_DESC_SIZE,
USB_IFACE_DESCRIPTOR,
0x00,
0x00,
HID_DESC_ENDPOINT_COUNT,
0x03,
0x01,
0x01, /* 0x01 for keyboard */
0x00,
/* Keyboard HID descriptor */
HID_ONLY_DESC_SIZE,
USB_HID_DESCRIPTOR,
0x00, 0x01,
0x00,
0x01,
0x22,
0x3F, 0x00,
/* Keyboard Endpoint descriptor */
ENDP_ONLY_DESC_SIZE,
USB_ENDPOINT_DESCRIPTOR,
HID_ENDPOINT |(USB_SEND << 7),
USB_INTERRUPT_PIPE,
FS_INTERRUPT_OUT_ENDP_PACKET_SIZE, 0x00,
FS_INTERRUPT_OUT_ENDP_INTERVAL,
/* Mouse Interface Descriptor */
IFACE_ONLY_DESC_SIZE,
USB_IFACE_DESCRIPTOR,
0x00,
0x00,
HID_DESC_ENDPOINT_COUNT,
0x03,
0x01,
0x02,
0x00,
/* Mouse HID descriptor */
HID_ONLY_DESC_SIZE,
USB_HID_DESCRIPTOR,
0x00,0x01,
0x00,
0x01,
0x22,
0x34,0x00,
/* Mouse Endpoint descriptor */
ENDP_ONLY_DESC_SIZE,
USB_ENDPOINT_DESCRIPTOR,
HID_ENDPOINT | (USB_SEND << 7),
USB_INTERRUPT_PIPE,
FS_INTERRUPT_OUT_ENDP_PACKET_SIZE, 0x00,
FS_INTERRUPT_OUT_ENDP_INTERVAL
};
uint8_t USB_STR_0[USB_STR_0_SIZE+USB_STR_DESC_SIZE] =
{
sizeof(USB_STR_0),
USB_STRING_DESCRIPTOR,
0x09,
0x04/*equivalent to 0x0409*/
};
uint8_t USB_STR_1[USB_STR_1_SIZE+USB_STR_DESC_SIZE] =
{
sizeof(USB_STR_1),
USB_STRING_DESCRIPTOR,
'F',0,
'R',0,
'E',0,
'E',0,
'S',0,
'C',0,
'A',0,
'L',0,
'E',0,
' ',0,
'S',0,
'E',0,
'M',0,
'I',0,
'C',0,
'O',0,
'N',0,
'D',0,
'U',0,
'C',0,
'T',0,
'O',0,
'R',0,
' ',0,
'I',0,
'N',0,
'C',0,
'.',0
};
uint8_t USB_STR_2[USB_STR_2_SIZE+USB_STR_DESC_SIZE] =
{
sizeof(USB_STR_2),
USB_STRING_DESCRIPTOR,
'U',0,
'S',0,
'B',0,
' ',0,
'A',0,
'U',0,
'D',0,
'I',0,
'O',0,
'+',0,
'H',0,
'I',0,
'D',0,
' ',0,
'D',0,
'E',0,
'M',0,
'O',0,
};
uint8_t USB_STR_n[USB_STR_n_SIZE+USB_STR_DESC_SIZE] =
{
sizeof(USB_STR_n),
USB_STRING_DESCRIPTOR,
'B',0,
'A',0,
'D',0,
' ',0,
'S',0,
'T',0,
'R',0,
'I',0,
'N',0,
'G',0,
' ',0,
'I',0,
'N',0,
'D',0,
'E',0,
'X',0
};
uint8_t keyboard_hid_report_descriptor[KEYBOARD_REPORT_DESC_SIZE] =
{
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
0x09, 0x06, /* USAGE (Keyboard) */
0xa1, 0x01, /* COLLECTION (Application) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x95, 0x08, /* REPORT_COUNT (8) */
0x81, 0x02, /* INPUT (Data,Var,Abs) modifier keys (CTRL, ALT, etc...*/
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x81, 0x01, /* INPUT (Cnst,Var,Abs) filupp to byte boundary */
0x95, 0x05, /* REPORT_COUNT (5) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x05, 0x08, /* USAGE_PAGE (LEDs) */
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
0x91, 0x02, /* OUTPUT (Data,Var,Abs) pc->kbd */
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x03, /* REPORT_SIZE (3 */
0x91, 0x01, /* OUTPUT (Cnst,Var,Abs) filupp to byte boundary */
0x95, 0x06, /* REPORT_COUNT (6) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */
0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
0x81, 0x00, /* INPUT (Data,Ary,Abs) array for pressed keys */
0xc0 /* END_COLLECTION */
};
uint8_t mouse_hid_report_descriptor[MOUSE_REPORT_DESC_SIZE] =
{
0x05, 0x01, /* Usage Page (Generic Desktop)*/
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Buttons) */
0x19, 0x01, /* Usage Minimum (01) */
0x29, 0x03, /* Usage Maximum (03) */
0x15, 0x00, /* logical Minimum (0) */
0x25, 0x01, /* logical Maximum (1) */
0x95, 0x03, /* Report Count (3) */
0x75, 0x01, /* Report Size (1) */
0x81, 0x02, /* Input(Data, Variable, Absolute) 3 button bits */
0x95, 0x01, /* Report count (1) */
0x75, 0x05, /* Report Size (5) */
0x81, 0x01, /* Input (Constant), 5 bit padding */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x09, 0x38, /* Usage (Z) */
0x15, 0x81, /* Logical Minimum (-127) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x03, /* Report Count (2) */
0x81, 0x06, /* Input(Data, Variable, Relative), 2 position bytes (X & Y)*/
0xC0, /* end collection */
0xC0 /* end collection */
};
uint32_t g_std_desc_size[USB_MAX_STD_DESCRIPTORS+1] =
{
0,
DEVICE_DESCRIPTOR_SIZE,
CONFIG_DESC_SIZE,
0, /* String */
0, /* Interface */
0, /* Endpoint */
0, /* Device Qualifier */
0 /* other speed config */
};
uint8_t *g_std_descriptors[USB_MAX_STD_DESCRIPTORS+1] =
{
NULL,
g_device_descriptor,
g_config_descriptor,
NULL, /* String */
NULL, /* Interface */
NULL, /* Endpoint */
NULL, /* Device Qualifier */
NULL /* Other speed config */
};
uint8_t g_string_desc_size[USB_MAX_STRING_DESCRIPTORS] =
{
sizeof(USB_STR_0),
sizeof(USB_STR_1),
sizeof(USB_STR_2),
sizeof(USB_STR_n)
};
uint8_t *g_string_descriptors[USB_MAX_STRING_DESCRIPTORS+1] =
{
USB_STR_0,
USB_STR_1,
USB_STR_2,
USB_STR_n
};
usb_language_t usb_lang[USB_MAX_SUPPORTED_LANGUAGES] =
{
{
(uint16_t)0x0409,
g_string_descriptors,
g_string_desc_size
}
};
usb_all_languages_t g_languages =
{
USB_STR_0, sizeof(USB_STR_0),
USB_MAX_SUPPORTED_LANGUAGES,
usb_lang
};
uint8_t g_valid_config_values[USB_MAX_CONFIG_SUPPORTED+1]={0,1};
/****************************************************************************
* Global Variables
****************************************************************************/
static uint8_t g_alternate_interface[USB_MAX_SUPPORTED_INTERFACES];
/**************************************************************************//*!
*
* @name USB_Desc_Get_Descriptor
*
* @brief The function returns the corresponding descriptor
*
* @param controller_ID : Controller ID
* @param type : Type of descriptor requested
* @param sub_type : String index for string descriptor
* @param index : String descriptor language Id
* @param descriptor : Output descriptor pointer
* @param size : Size of descriptor returned
*
* @return USB_OK When Success
* USBERR_INVALID_REQ_TYPE when Error
*****************************************************************************
* This function is used to pass the pointer of the requested descriptor
*****************************************************************************/
uint8_t USB_Desc_Get_Descriptor
(
uint32_t handle,
uint8_t type,
uint8_t str_num,
uint16_t index,
uint8_t** descriptor,
uint32_t* size
)
{
/* string descriptors are handled separately */
if (type == USB_STRING_DESCRIPTOR) {
if (index == 0) {
/* return the string and size of all languages */
*descriptor = (uint8_t *)g_languages.languages_supported_string;
*size = g_languages.languages_supported_size;
} else {
uint8_t lang_id=0;
uint8_t lang_index=USB_MAX_LANGUAGES_SUPPORTED;
for (; lang_id< USB_MAX_LANGUAGES_SUPPORTED; lang_id++) {
/* check whether we have a string for this language */
if (index == g_languages.usb_language[lang_id].language_id) {
/* check for max descriptors */
if (str_num < USB_MAX_STRING_DESCRIPTORS) {
/* setup index for the string to be returned */
lang_index = str_num;
}
break;
}
}
/* set return val for descriptor and size */
*descriptor = (uint8_t *)g_languages.usb_language[lang_id].lang_desc[str_num];
*size = g_languages.usb_language[lang_id].lang_desc_size[lang_index];
}
} else if (type < USB_MAX_STD_DESCRIPTORS+1) {
/* set return val for descriptor and size*/
*descriptor = (uint8_t *)g_std_descriptors[type];
/* if there is no descriptor then return error */
if (*descriptor == NULL) {
return USBERR_INVALID_REQ_TYPE;
}
*size = g_std_desc_size[type];
} else /* invalid descriptor */ {
if (type == USB_REPORT_DESCRIPTOR) {
type = USB_MAX_STD_DESCRIPTORS;
*descriptor = (uint8_t *)g_std_descriptors[type];
*size = g_std_desc_size[type];
} else {
return USBERR_INVALID_REQ_TYPE;
}
}
return USB_OK;
}
/**************************************************************************//*!
*
* @name USB_Desc_Get_Interface
*
* @brief The function returns the alternate interface
*
* @param controller_ID : Controller ID
* @param interface : Interface number
* @param alt_interface : Output alternate interface
*
* @return USB_OK When Success
* USBERR_INVALID_REQ_TYPE when Error
*****************************************************************************
*This function is called by the framework module to get the current interface
*****************************************************************************/
uint8_t USB_Desc_Get_Interface(uint32_t handle, uint8_t interface, uint8_t *alt_interface) {
if (interface < USB_MAX_SUPPORTED_INTERFACES) { /* if interface valid */
/* get alternate interface */
*alt_interface = g_alternate_interface[interface];
return USB_OK;
}
return USBERR_INVALID_REQ_TYPE;
}
/**************************************************************************//*!
*
* @name USB_Desc_Set_Interface
*
* @brief The function sets the alternate interface
*
* @param handle : handle
* @param interface : Interface number
* @param alt_interface : Input alternate interface
*
* @return USB_OK When Success
* USBERR_INVALID_REQ_TYPE when Error
*****************************************************************************
*This function is called by the framework module to set the interface
*****************************************************************************/
uint8_t USB_Desc_Set_Interface(uint32_t handle, uint8_t interface, uint8_t alt_interface) {
if (interface < USB_MAX_SUPPORTED_INTERFACES) { /* if interface valid */
/* set alternate interface*/
g_alternate_interface[interface] = alt_interface;
return USB_OK;
}
return USBERR_INVALID_REQ_TYPE;
}
/**************************************************************************//*!
*
* @name USB_Desc_Valid_Configation
*
* @brief The function checks whether the configuration parameter
* input is valid or not
*
* @param handle : handle
* @param config_val : Configuration value
*
* @return TRUE When Valid
* FALSE When Error
*****************************************************************************
* This function checks whether the configuration is valid or not
*****************************************************************************/
bool USB_Desc_Valid_Configation
(
uint32_t handle,/*[IN] Controller ID */
uint16_t config_val /*[IN] Configuration value */
)
{
uint8_t loop_index=0;
UNUSED_ARGUMENT(handle)
/* check with only supported val right now */
while(loop_index < (USB_MAX_CONFIG_SUPPORTED+1)) {
if(config_val == g_valid_config_values[loop_index]) {
return TRUE;
}
loop_index++;
}
return FALSE;
}
/**************************************************************************//*!
*
* @name USB_Desc_Valid_Interface
*
* @brief The function checks whether the interface parameter
* input is valid or not
*
* @param handle : handle
* @param interface : Target interface
*
* @return TRUE When Valid
* FALSE When Error
*****************************************************************************
* This function checks whether the interface is valid or not
*****************************************************************************/
bool USB_Desc_Valid_Interface
(
uint32_t handle, /*[IN] Controller ID */
uint8_t interface /*[IN] Target interface */
)
{
uint8_t loop_index=0;
UNUSED_ARGUMENT(handle)
/* check with only supported val right now */
while(loop_index < USB_MAX_SUPPORTED_INTERFACES) {
if(interface == g_alternate_interface[loop_index]) {
return TRUE;
}
loop_index++;
}
return FALSE;
}
/**************************************************************************//*!
*
* @name USB_Desc_Remote_Wakeup
*
* @brief The function checks whether the remote wakeup is supported or not
*
* @param handle : handle
*
* @return REMOTE_WAKEUP_SUPPORT (TRUE) - If remote wakeup supported
*****************************************************************************
* This function returns remote wakeup is supported or not
*****************************************************************************/
bool USB_Desc_Remote_Wakeup(uint32_t handle /* [IN] Controller ID */) {
return USBCFG_DEV_REMOTE_WAKEUP;
}
/* ****************************************************************************
* Local available
* Stock Array value of Parameter controller
******************************************************************************/
/**************************************************************************//*!
*
* @name USB_Set_Configuration
*
* @brief The function set the configuration value of device
*
*
* @param handle handle
* @param config_val configuration value
*
* @return TRUE When Valid
* FALSE When Error
*****************************************************************************/
uint8_t USB_Set_Configuration(audio_handle_t handle, uint8_t config) {
return USB_OK; /* It's that simple since the device only has one configuration. */
}
/**************************************************************************//*!
*
* @name USB_Desc_Get_Entity
*
* @brief The function retrieves the entity specified by type.
*
* @param handle handle
*
* @return USB_OK - if success
*****************************************************************************/
uint8_t USB_Desc_Get_Entity(audio_handle_t handle, entity_type type, uint32_t *object)
{
switch (type) {
case USB_CLASS_INFO:
break;
case USB_CLASS_INTERFACE_INDEX_INFO:
*object = 0xff;
if (handle == (uint32_t)g_composite_device.hid_keyboard.app_handle) {
*object = (uint32_t)HID_KEYBOARD_INTERFACE_INDEX;
break;
} else if (handle == (uint32_t)g_composite_device.hid_mouse.app_handle) {
*object = (uint32_t)HID_MOUSE_INTERFACE_INDEX;
break;
}
break;
case USB_COMPOSITE_INFO:
keyboard_interface[0].index = 0;
keyboard_interface[0].endpoints = keyboard_endpoints;
mouse_interface[0].index = 1;
mouse_interface[0].endpoints = mouse_endpoints;
*object = (unsigned long)&usb_composite_info;
break;
default:
break;
}
return USB_OK;
}
/**************************************************************************//*!
*
* @name USB_Desc_Set_Speed
*
* @brief The function is used to set device speed
*
* @param handle: handle
* @param speed: speed
*
* @return USB_OK When Success
* USBERR_INVALID_REQ_TYPE when Error
*****************************************************************************/
uint8_t USB_Desc_Set_Speed(uint32_t handle, uint16_t speed) {
descriptor_union_t ptr1, ptr2;
ptr1.pntr = g_config_descriptor;
ptr2.pntr = g_config_descriptor + sizeof(g_config_descriptor);
if (handle == g_composite_device.hid_keyboard.app_handle) {
while (ptr1.word < ptr2.word) {
if (ptr1.common->bDescriptorType == USB_DESC_TYPE_EP) {
if (USB_SPEED_HIGH == speed) {
ptr1.ndpt->iInterval = HS_INTERRUPT_OUT_ENDP_INTERVAL;
ptr1.ndpt->wMaxPacketSize[0] = USB_uint_16_low(HS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
ptr1.ndpt->wMaxPacketSize[1] = USB_uint_16_high(HS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
} else {
ptr1.ndpt->iInterval = FS_INTERRUPT_OUT_ENDP_INTERVAL;
ptr1.ndpt->wMaxPacketSize[0] = USB_uint_16_low(FS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
ptr1.ndpt->wMaxPacketSize[1] = USB_uint_16_high(FS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
}
}
ptr1.word += ptr1.common->bLength;
}
for (int i = 0; i < HID_DESC_ENDPOINT_COUNT; i++) {
if (USB_SPEED_HIGH == speed) {
keyboard_endpoint[i].size = HS_INTERRUPT_OUT_ENDP_PACKET_SIZE;
} else {
keyboard_endpoint[i].size = FS_INTERRUPT_OUT_ENDP_PACKET_SIZE;
}
}
} else if (handle == g_composite_device.hid_mouse.app_handle) {
while (ptr1.word < ptr2.word) {
if (ptr1.common->bDescriptorType == USB_DESC_TYPE_EP) {
if ((ptr1.ndpt->bmAttributes & 0x03) == USB_INTERRUPT_PIPE) {
if (USB_SPEED_HIGH == speed) {
ptr1.ndpt->iInterval = HS_INTERRUPT_OUT_ENDP_INTERVAL;
ptr1.ndpt->wMaxPacketSize[0] = USB_uint_16_low(HS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
ptr1.ndpt->wMaxPacketSize[1] = USB_uint_16_high(HS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
} else {
ptr1.ndpt->iInterval = FS_INTERRUPT_OUT_ENDP_INTERVAL;
ptr1.ndpt->wMaxPacketSize[0] = USB_uint_16_low(FS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
ptr1.ndpt->wMaxPacketSize[1] = USB_uint_16_high(FS_INTERRUPT_OUT_ENDP_PACKET_SIZE);
}
}
}
ptr1.word += ptr1.common->bLength;
}
for (int i = 0; i < HID_DESC_ENDPOINT_COUNT; i++) {
if (USB_SPEED_HIGH == speed) {
mouse_endpoint[i].size = HS_INTERRUPT_OUT_ENDP_PACKET_SIZE;
} else {
mouse_endpoint[i].size = FS_INTERRUPT_OUT_ENDP_PACKET_SIZE;
}
}
}
return USB_OK;
}
usb_desc_request_notify_struct_t desc_callback =
{
USB_Desc_Get_Descriptor,
USB_Desc_Get_Interface,
USB_Desc_Set_Interface,
USB_Set_Configuration,
USB_Desc_Get_Entity
};