From a5eecb40555d5053393dd3d0916fa63bfa9a6b18 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 27 Nov 2012 17:51:59 +0700 Subject: [PATCH] added keyboard device demo --- demos/device/keyboard/cr_startup_lpc13u.c | 354 ++++++++++++++++++++ demos/device/keyboard/descriptors.c | 374 ++++++++++++++++++++++ demos/device/keyboard/descriptors.h | 184 +++++++++++ demos/device/keyboard/main.c | 25 ++ 4 files changed, 937 insertions(+) create mode 100644 demos/device/keyboard/cr_startup_lpc13u.c create mode 100644 demos/device/keyboard/descriptors.c create mode 100644 demos/device/keyboard/descriptors.h create mode 100644 demos/device/keyboard/main.c diff --git a/demos/device/keyboard/cr_startup_lpc13u.c b/demos/device/keyboard/cr_startup_lpc13u.c new file mode 100644 index 00000000..8b5d7eeb --- /dev/null +++ b/demos/device/keyboard/cr_startup_lpc13u.c @@ -0,0 +1,354 @@ +//***************************************************************************** +// +--+ +// | ++----+ +// +-++ | +// | | +// +-+--+ | +// | +--+--+ +// +----+ Copyright (c) 2012 Code Red Technologies Ltd. +// +// NXP LPC13U Microcontroller Startup code for use with Red Suite +// +// Version : 120202 +// +// Software License Agreement +// +// The software is owned by Code Red Technologies and/or its suppliers, and is +// protected under applicable copyright laws. All rights are reserved. Any +// use in violation of the foregoing restrictions may subject the user to criminal +// sanctions under applicable laws, as well as to civil liability for the breach +// of the terms and conditions of this license. +// +// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT +// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH +// CODE RED TECHNOLOGIES LTD. +// +//***************************************************************************** +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#else +//***************************************************************************** +// +// The entry point for the C++ library startup +// +//***************************************************************************** +extern "C" { + extern void __libc_init_array(void); +} +#endif +#endif + +#define WEAK __attribute__ ((weak)) +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +// Code Red - if CMSIS is being used, then SystemInit() routine +// will be called by startup code rather than in application's main() +#if defined (__USE_CMSIS) +#include "LPC13Uxx.h" +#endif + +//***************************************************************************** +#if defined (__cplusplus) +extern "C" { +#endif + +//***************************************************************************** +// +// Forward declaration of the default handlers. These are aliased. +// When the application defines a handler (with the same name), this will +// automatically take precedence over these weak definitions +// +//***************************************************************************** +void ResetISR(void); +WEAK void NMI_Handler(void); +WEAK void HardFault_Handler(void); +WEAK void MemManage_Handler(void); +WEAK void BusFault_Handler(void); +WEAK void UsageFault_Handler(void); +WEAK void SVC_Handler(void); +WEAK void DebugMon_Handler(void); +WEAK void PendSV_Handler(void); +WEAK void SysTick_Handler(void); +WEAK void IntDefaultHandler(void); +//***************************************************************************** +// +// Forward declaration of the specific IRQ handlers. These are aliased +// to the IntDefaultHandler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions +// +//***************************************************************************** +void PIN_INT0_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT1_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT2_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT3_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT4_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT5_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT6_IRQHandler(void) ALIAS(IntDefaultHandler); +void PIN_INT7_IRQHandler(void) ALIAS(IntDefaultHandler); +void GINT0_IRQHandler(void) ALIAS(IntDefaultHandler); +void GINT1_IRQHandler(void) ALIAS(IntDefaultHandler); +void OSTIMER_IRQHandler(void) ALIAS(IntDefaultHandler); +void SSP1_IRQHandler(void) ALIAS(IntDefaultHandler); +void I2C_IRQHandler(void) ALIAS(IntDefaultHandler); +void CT16B0_IRQHandler(void) ALIAS(IntDefaultHandler); +void CT16B1_IRQHandler(void) ALIAS(IntDefaultHandler); +void CT32B0_IRQHandler(void) ALIAS(IntDefaultHandler); +void CT32B1_IRQHandler(void) ALIAS(IntDefaultHandler); +void SSP0_IRQHandler(void) ALIAS(IntDefaultHandler); +void USART_IRQHandler(void) ALIAS(IntDefaultHandler); +void USB_IRQHandler(void) ALIAS(IntDefaultHandler); +void USB_FIQHandler(void) ALIAS(IntDefaultHandler); +void ADC_IRQHandler(void) ALIAS(IntDefaultHandler); +void WDT_IRQHandler(void) ALIAS(IntDefaultHandler); +void BOD_IRQHandler(void) ALIAS(IntDefaultHandler); +void FMC_IRQHandler(void) ALIAS(IntDefaultHandler); +void OSCFAIL_IRQHandler(void) ALIAS(IntDefaultHandler); +void PVTCIRCUIT_IRQHandler(void) ALIAS(IntDefaultHandler); +void USBWakeup_IRQHandler(void) ALIAS(IntDefaultHandler); + +//***************************************************************************** +// +// The entry point for the application. +// __main() is the entry point for Redlib based applications +// main() is the entry point for Newlib based applications +// +//***************************************************************************** +#if defined (__REDLIB__) +extern void __main(void); +#endif +extern int main(void); +//***************************************************************************** +// +// External declaration for the pointer to the stack top from the Linker Script +// +//***************************************************************************** +extern void _vStackTop(void); + +//***************************************************************************** +#if defined (__cplusplus) +} // extern "C" +#endif +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000. +// +//***************************************************************************** +extern void (* const g_pfnVectors[])(void); +__attribute__ ((section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = { + // Core Level - CM3 + &_vStackTop, // The initial stack pointer + ResetISR, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + MemManage_Handler, // The MPU fault handler + BusFault_Handler, // The bus fault handler + UsageFault_Handler, // The usage fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + DebugMon_Handler, // Debug monitor handler + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + // LPC13U External Interrupts + PIN_INT0_IRQHandler, // All GPIO pin can be routed to PIN_INTx + PIN_INT1_IRQHandler, + PIN_INT2_IRQHandler, + PIN_INT3_IRQHandler, + PIN_INT4_IRQHandler, + PIN_INT5_IRQHandler, + PIN_INT6_IRQHandler, + PIN_INT7_IRQHandler, + GINT0_IRQHandler, + GINT1_IRQHandler, // PIO0 (0:7) + 0, + 0, + OSTIMER_IRQHandler, + 0, + SSP1_IRQHandler, // SSP1 + I2C_IRQHandler, // I2C + CT16B0_IRQHandler, // 16-bit Timer0 + CT16B1_IRQHandler, // 16-bit Timer1 + CT32B0_IRQHandler, // 32-bit Timer0 + CT32B1_IRQHandler, // 32-bit Timer1 + SSP0_IRQHandler, // SSP0 + USART_IRQHandler, // USART + USB_IRQHandler, // USB IRQ + USB_FIQHandler, // USB FIQ + ADC_IRQHandler, // A/D Converter + WDT_IRQHandler, // Watchdog timer + BOD_IRQHandler, // Brown Out Detect + FMC_IRQHandler, // IP2111 Flash Memory Controller + OSCFAIL_IRQHandler, // OSC FAIL + PVTCIRCUIT_IRQHandler, // PVT CIRCUIT + USBWakeup_IRQHandler, // USB wake up + 0, + }; + +//***************************************************************************** +// Functions to carry out the initialization of RW and BSS data sections. These +// are written as separate functions rather than being inlined within the +// ResetISR() function in order to cope with MCUs with multiple banks of +// memory. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void data_init(unsigned int romstart, unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int *pulSrc = (unsigned int*) romstart; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = *pulSrc++; +} + +__attribute__ ((section(".after_vectors"))) +void bss_init(unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = 0; +} + +//***************************************************************************** +// The following symbols are constructs generated by the linker, indicating +// the location of various points in the "Global Section Table". This table is +// created by the linker via the Code Red managed linker script mechanism. It +// contains the load address, execution address and length of each RW data +// section and the execution and length of each BSS (zero initialized) section. +//***************************************************************************** +extern unsigned int __data_section_table; +extern unsigned int __data_section_table_end; +extern unsigned int __bss_section_table; +extern unsigned int __bss_section_table_end; + +//***************************************************************************** +// Reset entry point for your code. +// Sets up a simple runtime environment and initializes the C/C++ +// library. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void +ResetISR(void) { + + // + // Copy the data sections from flash to SRAM. + // + unsigned int LoadAddr, ExeAddr, SectionLen; + unsigned int *SectionTableAddr; + + // Load base address of Global Section Table + SectionTableAddr = &__data_section_table; + + // Copy the data sections from flash to SRAM. + while (SectionTableAddr < &__data_section_table_end) { + LoadAddr = *SectionTableAddr++; + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + data_init(LoadAddr, ExeAddr, SectionLen); + } + // At this point, SectionTableAddr = &__bss_section_table; + // Zero fill the bss segment + while (SectionTableAddr < &__bss_section_table_end) { + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + bss_init(ExeAddr, SectionLen); + } + +#ifdef __USE_CMSIS + SystemInit(); +#endif + +#if defined (__cplusplus) + // + // Call C++ library initialisation + // + __libc_init_array(); +#endif + +#if defined (__REDLIB__) + // Call the Redlib library, which in turn calls main() + __main() ; +#else + main(); +#endif + // + // main() shouldn't return, but if it does, we'll just enter an infinite loop + // + while (1) { + ; + } +} + +//***************************************************************************** +// Default exception handlers. Override the ones here by defining your own +// handler routines in your application code. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void NMI_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void HardFault_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void MemManage_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void BusFault_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void UsageFault_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void SVC_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void DebugMon_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void PendSV_Handler(void) { + while (1) { + } +} +__attribute__ ((section(".after_vectors"))) +void SysTick_Handler(void) { + while (1) { + } +} + +//***************************************************************************** +// +// Processor ends up here if an unexpected interrupt occurs or a handler +// is not present in the application code. +// +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void IntDefaultHandler(void) { + // + // Go into an infinite loop. + // + while (1) { + } +} diff --git a/demos/device/keyboard/descriptors.c b/demos/device/keyboard/descriptors.c new file mode 100644 index 00000000..ceb463af --- /dev/null +++ b/demos/device/keyboard/descriptors.c @@ -0,0 +1,374 @@ +/* + * descriptors.c + * + * Created on: Nov 26, 2012 + * Author: hathach (thachha@live.com) + */ + +/* + * Software License Agreement (BSD License) + * Copyright (c) 2012, hathach (thachha@live.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the tiny usb stack. + */ + +#include "descriptors.h" + +#ifdef CFG_USB_HID_KEYBOARD +ALIGNED(4) const uint8_t HID_KeyboardReportDescriptor[] = { + HID_UsagePage ( HID_USAGE_PAGE_GENERIC ), + HID_Usage ( HID_USAGE_GENERIC_KEYBOARD ), + HID_Collection ( HID_Application ), + HID_UsagePage (HID_USAGE_PAGE_KEYBOARD), + HID_UsageMin (224 ), + HID_UsageMax (231 ), + HID_LogicalMin ( 0 ), + HID_LogicalMax ( 1 ), + + HID_ReportCount ( 8 ), /* 8 bits */ + HID_ReportSize ( 1 ), + HID_Input ( HID_Data | HID_Variable | HID_Absolute ), /* maskable modifier key */ + + HID_ReportCount ( 1 ), + HID_ReportSize (8 ), + HID_Input (HID_Constant ), /* reserved */ + + HID_UsagePage ( HID_USAGE_PAGE_LED ), + HID_UsageMin (1 ), + HID_UsageMax (5 ), + HID_ReportCount (5 ), + HID_ReportSize (1 ), + HID_Output ( HID_Data | HID_Variable | HID_Absolute ), /* 5-bit Led report */ + + HID_ReportCount ( 1 ), + HID_ReportSize (3 ), /* led padding */ + HID_Output (HID_Constant ), + + HID_UsagePage (HID_USAGE_PAGE_KEYBOARD), + HID_UsageMin (0 ), + HID_UsageMax (101 ), + HID_LogicalMin (0 ), + HID_LogicalMax (101 ), + + HID_ReportCount (6 ), + HID_ReportSize (8 ), + HID_Input (HID_Data | HID_Array | HID_Absolute ), /* keycodes array 6 items */ + HID_EndCollection, +}; +#endif + +#ifdef CFG_USB_HID_MOUSE +ALIGNED(4) const uint8_t HID_MouseReportDescriptor[] = { + HID_UsagePage ( HID_USAGE_PAGE_GENERIC ), + HID_Usage ( HID_USAGE_GENERIC_MOUSE ), + HID_Collection ( HID_Application ), + HID_Usage (HID_USAGE_GENERIC_POINTER), + + HID_Collection ( HID_Physical ), + HID_UsagePage ( HID_USAGE_PAGE_BUTTON ), + HID_UsageMin ( 1 ), + HID_UsageMax ( 3 ), + HID_LogicalMin ( 0 ), + HID_LogicalMax ( 1 ), + + HID_ReportCount ( 3 ), /* Left, Right and Middle mouse*/ + HID_ReportSize ( 1 ), + HID_Input ( HID_Data | HID_Variable | HID_Absolute ), + + HID_ReportCount ( 1 ), + HID_ReportSize ( 5 ), + HID_Input (HID_Constant ), /* reserved */ + + HID_UsagePage ( HID_USAGE_PAGE_GENERIC ), + HID_Usage ( HID_USAGE_GENERIC_X ), + HID_Usage ( HID_USAGE_GENERIC_Y ), + HID_LogicalMin ( 0x81 ), /* -127 */ + HID_LogicalMax ( 0x7f ), /* 127 */ + + HID_ReportCount ( 2 ), /* X, Y position */ + HID_ReportSize ( 8 ), + HID_Input ( HID_Data | HID_Variable | HID_Relative ), /* relative values */ + + HID_EndCollection, + + HID_EndCollection, +}; +#endif + +/* USB Standard Device Descriptor */ +ALIGNED(4) const USB_DEVICE_DESCRIPTOR USB_DeviceDescriptor = +{ + .bLength = sizeof(USB_DEVICE_DESCRIPTOR), + .bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE, + .bcdUSB = 0x0200, + + #if IAD_DESC_REQUIRED + /* Multiple Interfaces Using Interface Association Descriptor (IAD) */ + .bDeviceClass = USB_DEVICE_CLASS_IAD, + .bDeviceSubClass = USB_DEVICE_SUBCLASS_IAD, + .bDeviceProtocol = USB_DEVICE_PROTOCOL_IAD, + #elif defined CFG_USB_CDC + .bDeviceClass = CDC_COMMUNICATION_INTERFACE_CLASS, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + #else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + #endif + + .bMaxPacketSize0 = USB_MAX_PACKET0, + + .idVendor = CFG_USB_VENDORID, + .idProduct = USB_PRODUCT_ID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +ALIGNED(4) const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor = +{ + .Config = + { + .bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR), + .bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE, + + .wTotalLength = sizeof(USB_FS_CONFIGURATION_DESCRIPTOR) - 1, // exclude termination + .bNumInterfaces = TOTAL_INTEFACES, + + .bConfigurationValue = 1, + .iConfiguration = 0x00, + .bmAttributes = USB_CONFIG_BUS_POWERED, + .bMaxPower = USB_CONFIG_POWER_MA(100) + }, + + #if IAD_DESC_REQUIRED + // IAD points to CDC Interfaces + .CDC_IAD = + { + .bLength = sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR), + .bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, + + .bFirstInterface = 0, + .bInterfaceCount = 2, + + .bFunctionClass = CDC_COMMUNICATION_INTERFACE_CLASS, + .bFunctionSubClass = CDC_ABSTRACT_CONTROL_MODEL, + .bFunctionProtocol = CDC_PROTOCOL_COMMON_AT_COMMANDS, + + .iFunction = 0 + }, + #endif + + #ifdef CFG_USB_CDC + // USB CDC Serial Interface + // CDC Control Interface + .CDC_CCI_Interface = + { + .bLength = sizeof(USB_INTERFACE_DESCRIPTOR), + .bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE, + .bInterfaceNumber = INTERFACE_INDEX_CDC, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = CDC_COMMUNICATION_INTERFACE_CLASS, + .bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL, + .bInterfaceProtocol = CDC_PROTOCOL_COMMON_AT_COMMANDS, + .iInterface = 0x00 + }, + + .CDC_Header = + { + .bFunctionLength = sizeof(CDC_HEADER_DESCRIPTOR), + .bDescriptorType = CDC_CS_INTERFACE, + .bDescriptorSubtype = CDC_HEADER, + .bcdCDC = 0x0120 + }, + + .CDC_ACM = + { + .bFunctionLength = sizeof(CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR), + .bDescriptorType = CDC_CS_INTERFACE, + .bDescriptorSubtype = CDC_ABSTRACT_CONTROL_MANAGEMENT, + .bmCapabilities = 0x06 // Support Send_Break and Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State + }, + + .CDC_Union = + { + .sUnion = + { + .bFunctionLength = sizeof(CDC_UNION_1SLAVE_DESCRIPTOR), + .bDescriptorType = CDC_CS_INTERFACE, + .bDescriptorSubtype = CDC_UNION, + .bMasterInterface = 0 + }, + .bSlaveInterfaces[0] = 1 + }, + + .CDC_NotificationEndpoint = + { + .bLength = sizeof(USB_ENDPOINT_DESCRIPTOR), + .bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = CDC_NOTIFICATION_EP, + .bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT, + .wMaxPacketSize = CDC_NOTIFICATION_EP_MAXPACKETSIZE, + .bInterval = 0xff // lowest polling rate + }, + + // CDC Data Interface + .CDC_DCI_Interface = + { + .bLength = sizeof(USB_INTERFACE_DESCRIPTOR), + .bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE, + .bInterfaceNumber = INTERFACE_INDEX_CDC+1, + .bAlternateSetting = 0x00, + .bNumEndpoints = 2, + .bInterfaceClass = CDC_DATA_INTERFACE_CLASS, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0x00 + }, + + .CDC_DataOutEndpoint = + { + .bLength = sizeof(USB_ENDPOINT_DESCRIPTOR), + .bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = CDC_DATA_EP_OUT, + .bmAttributes = USB_ENDPOINT_TYPE_BULK, + .wMaxPacketSize = CDC_DATA_EP_MAXPACKET_SIZE, + .bInterval = 0 + }, + + .CDC_DataInEndpoint = + { + .bLength = sizeof(USB_ENDPOINT_DESCRIPTOR), + .bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = CDC_DATA_EP_IN, + .bmAttributes = USB_ENDPOINT_TYPE_BULK, + .wMaxPacketSize = CDC_DATA_EP_MAXPACKET_SIZE, + .bInterval = 0 + }, + #endif + + #ifdef CFG_USB_HID_KEYBOARD + ///// USB HID Keyboard interface + .HID_KeyboardInterface = + { + .bLength = sizeof(USB_INTERFACE_DESCRIPTOR), + .bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE, + .bInterfaceNumber = INTERFACE_INDEX_HID_KEYBOARD, + .bAlternateSetting = 0x00, + .bNumEndpoints = 1, + .bInterfaceClass = USB_DEVICE_CLASS_HUMAN_INTERFACE, + .bInterfaceSubClass = HID_SUBCLASS_BOOT, + .bInterfaceProtocol = HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00 + }, + + .HID_KeyboardHID = + { + .bLength = sizeof(HID_DESCRIPTOR), + .bDescriptorType = HID_HID_DESCRIPTOR_TYPE, + .bcdHID = 0x0111, + .bCountryCode = HID_Local_NotSupported, + .bNumDescriptors = 1, + .DescriptorList[0] = + { + .bDescriptorType = HID_REPORT_DESCRIPTOR_TYPE, + .wDescriptorLength = sizeof(HID_KeyboardReportDescriptor) + }, + }, + + .HID_KeyboardEndpoint = + { + .bLength = sizeof(USB_ENDPOINT_DESCRIPTOR), + .bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = HID_KEYBOARD_EP_IN, + .bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT, + .wMaxPacketSize = 0x08, + .bInterval = 0x0A + }, + #endif + + #ifdef CFG_USB_HID_MOUSE + .HID_MouseInterface = + { + .bLength = sizeof(USB_INTERFACE_DESCRIPTOR), + .bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE, + .bInterfaceNumber = INTERFACE_INDEX_HID_MOUSE, + .bAlternateSetting = 0x00, + .bNumEndpoints = 1, + .bInterfaceClass = USB_DEVICE_CLASS_HUMAN_INTERFACE, + .bInterfaceSubClass = HID_SUBCLASS_BOOT, + .bInterfaceProtocol = HID_PROTOCOL_MOUSE, + .iInterface = 0x00 + }, + + .HID_MouseHID = + { + .bLength = sizeof(HID_DESCRIPTOR), + .bDescriptorType = HID_HID_DESCRIPTOR_TYPE, + .bcdHID = 0x0111, + .bCountryCode = HID_Local_NotSupported, + .bNumDescriptors = 1, + .DescriptorList[0] = + { + .bDescriptorType = HID_REPORT_DESCRIPTOR_TYPE, + .wDescriptorLength = sizeof(HID_MouseReportDescriptor) + }, + }, + + .HID_MouseEndpoint = + { + .bLength = sizeof(USB_ENDPOINT_DESCRIPTOR), + .bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE, + .bEndpointAddress = HID_MOUSE_EP_IN, + .bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT, + .wMaxPacketSize = 0x08, + .bInterval = 0x0A + }, + #endif + + .ConfigDescTermination = 0, +}; + +ALIGNED(4) const USB_STR_DESCRIPTOR USB_StringDescriptor = +{ + .LangID = { .bLength = 0x04, .bDescriptorType = USB_STRING_DESCRIPTOR_TYPE }, + .strLangID= {0x0409}, // US English + + .Manufacturer = { .bLength = USB_STRING_LEN(sizeof(CFG_USB_STRING_MANUFACTURER)-1), .bDescriptorType = USB_STRING_DESCRIPTOR_TYPE }, + .strManufacturer = {'t', 'i', 'n', 'y', 'U', 'S', 'B'}, + + .Product = { .bLength = USB_STRING_LEN(sizeof(CFG_USB_STRING_PRODUCT)-1), .bDescriptorType = USB_STRING_DESCRIPTOR_TYPE }, + .strProduct = {'D', 'e', 'v', 'i', 'c', ' ', 'e', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'}, + + .Serial = { .bLength = USB_STRING_LEN(USB_STRING_SERIAL_LEN), .bDescriptorType = USB_STRING_DESCRIPTOR_TYPE }, + .strSerial = {'1', '2', '3', '4'} +}; diff --git a/demos/device/keyboard/descriptors.h b/demos/device/keyboard/descriptors.h new file mode 100644 index 00000000..d73f34dc --- /dev/null +++ b/demos/device/keyboard/descriptors.h @@ -0,0 +1,184 @@ +/* + * descriptors.h + * + * Created on: Nov 26, 2012 + * Author: hathach (thachha@live.com) + */ + +/* + * Software License Agreement (BSD License) + * Copyright (c) 2012, hathach (thachha@live.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the tiny usb stack. + */ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + +#include "tusb.h" + +#define CFG_USB_STRING_MANUFACTURER "tinyUSB" +#define CFG_USB_STRING_PRODUCT "Device Keyboard" +#define CFG_USB_STRING_SERIAL "1234" +#define CFG_USB_VENDORID 0x1FC9 + +/* USB Serial uses the MCUs unique 128-bit chip ID via an IAP call = 32 hex chars */ +#define USB_STRING_SERIAL_LEN 32 + +#define USB_STRING_LEN(n) (2 + ((n)<<1)) + +typedef PRE_PACK struct POST_PACK _USB_STR_DESCRIPTOR +{ + USB_COMMON_DESCRIPTOR LangID; + uint16_t strLangID[1]; + + USB_COMMON_DESCRIPTOR Manufacturer; + uint16_t strManufacturer[sizeof(CFG_USB_STRING_MANUFACTURER)-1]; // exclude null-character + + USB_COMMON_DESCRIPTOR Product; + uint16_t strProduct[sizeof(CFG_USB_STRING_PRODUCT)-1]; // exclude null-character + + USB_COMMON_DESCRIPTOR Serial; + uint16_t strSerial[sizeof(CFG_USB_STRING_SERIAL)-1]; +} USB_STR_DESCRIPTOR; + +// USB Interface Assosication Descriptor +#define USB_DEVICE_CLASS_IAD USB_DEVICE_CLASS_MISCELLANEOUS +#define USB_DEVICE_SUBCLASS_IAD 0x02 +#define USB_DEVICE_PROTOCOL_IAD 0x01 + +// USB Interface Association Descriptor +typedef PRE_PACK struct POST_PACK _USB_INTERFACE_ASSOCIATION_DESCRIPTOR +{ + uint8_t bLength; /**< Size of descriptor*/ + uint8_t bDescriptorType; /**< Other_speed_Configuration Type*/ + + uint8_t bFirstInterface; /**< Index of the first associated interface. */ + uint8_t bInterfaceCount; /**< Total number of associated interfaces. */ + + uint8_t bFunctionClass; /**< Interface class ID. */ + uint8_t bFunctionSubClass; /**< Interface subclass ID. */ + uint8_t bFunctionProtocol; /**< Interface protocol ID. */ + + uint8_t iFunction; /**< Index of the string descriptor describing the interface association. */ +} USB_INTERFACE_ASSOCIATION_DESCRIPTOR; + +/////////////////////////////////////////////////////////////////////// +// Interface Assosication Descriptor if device is CDC + other class +#define IAD_DESC_REQUIRED ( defined(CFG_USB_CDC) && (defined(CFG_USB_HID_KEYBOARD) || defined(CFG_USB_HID_MOUSE)) ) + +#ifdef CFG_USB_CDC + #define INTERFACES_OF_CDC 2 +#else + #define INTERFACES_OF_CDC 0 +#endif + +#ifdef CFG_USB_HID_KEYBOARD + #define INTERFACES_OF_HID_KEYBOARD 1 +#else + #define INTERFACES_OF_HID_KEYBOARD 0 +#endif + +#ifdef CFG_USB_HID_MOUSE + #define INTERFACES_OF_HID_MOUSE 1 +#else + #define INTERFACES_OF_HID_MOUSE 0 +#endif + +#ifdef CFG_USB_HID_GENERIC + #define INTERFACES_OF_HID_GENERIC 1 +#else + #define INTERFACES_OF_HID_GENERIC 0 +#endif + +#ifdef CFG_USB_MASS_STORAGE + #define INTERFACES_OF_MASS_STORAGE 2 +#else + #define INTERFACES_OF_MASS_STORAGE 0 +#endif + +#define INTERFACE_INDEX_CDC 0 +#define INTERFACE_INDEX_HID_KEYBOARD (INTERFACE_INDEX_CDC + INTERFACES_OF_CDC ) +#define INTERFACE_INDEX_HID_MOUSE (INTERFACE_INDEX_HID_KEYBOARD + INTERFACES_OF_HID_KEYBOARD ) +#define INTERFACE_INDEX_HID_GENERIC (INTERFACE_INDEX_HID_MOUSE + INTERFACES_OF_HID_MOUSE ) +#define INTERFACE_INDEX_MASS_STORAGE (INTERFACE_INDEX_HID_GENERIC + INTERFACES_OF_HID_GENERIC ) + +#define TOTAL_INTEFACES (INTERFACES_OF_CDC + INTERFACES_OF_HID_KEYBOARD + INTERFACES_OF_HID_MOUSE + INTERFACES_OF_HID_GENERIC + INTERFACES_OF_MASS_STORAGE) + +// Bitmap: MassStorage | Generic | Mouse | Key | CDC +#define PRODUCTID_BITMAP(interface, n) ( (INTERFACES_OF_##interface ? 1 : 0) << (n) ) +#define USB_PRODUCT_ID (0x2000 | ( PRODUCTID_BITMAP(CDC, 0) | PRODUCTID_BITMAP(HID_KEYBOARD, 1) | PRODUCTID_BITMAP(HID_MOUSE, 2) | \ + PRODUCTID_BITMAP(HID_GENERIC, 3) | PRODUCTID_BITMAP(MASS_STORAGE, 4) ) ) + +/////////////////////////////////////////////////////////////////////// +typedef struct +{ + USB_CONFIGURATION_DESCRIPTOR Config; + +#if IAD_DESC_REQUIRED + USB_INTERFACE_ASSOCIATION_DESCRIPTOR CDC_IAD; +#endif + +#ifdef CFG_USB_CDC + //CDC - Serial + //CDC Control Interface + USB_INTERFACE_DESCRIPTOR CDC_CCI_Interface; + CDC_HEADER_DESCRIPTOR CDC_Header; + CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR CDC_ACM; + CDC_UNION_1SLAVE_DESCRIPTOR CDC_Union; + USB_ENDPOINT_DESCRIPTOR CDC_NotificationEndpoint; + + //CDC Data Interface + USB_INTERFACE_DESCRIPTOR CDC_DCI_Interface; + USB_ENDPOINT_DESCRIPTOR CDC_DataOutEndpoint; + USB_ENDPOINT_DESCRIPTOR CDC_DataInEndpoint; +#endif + +#ifdef CFG_USB_HID_KEYBOARD + //Keyboard HID Interface + USB_INTERFACE_DESCRIPTOR HID_KeyboardInterface; + HID_DESCRIPTOR HID_KeyboardHID; + USB_ENDPOINT_DESCRIPTOR HID_KeyboardEndpoint; +#endif + +#ifdef CFG_USB_HID_MOUSE + //Mouse HID Interface + USB_INTERFACE_DESCRIPTOR HID_MouseInterface; + HID_DESCRIPTOR HID_MouseHID; + USB_ENDPOINT_DESCRIPTOR HID_MouseEndpoint; +#endif + + unsigned char ConfigDescTermination; +} USB_FS_CONFIGURATION_DESCRIPTOR; + +extern const USB_DEVICE_DESCRIPTOR USB_DeviceDescriptor; +extern const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor; +extern const USB_STR_DESCRIPTOR USB_StringDescriptor; + +extern const uint8_t HID_KeyboardReportDescriptor[]; +extern const uint8_t HID_MouseReportDescriptor[]; + +#endif diff --git a/demos/device/keyboard/main.c b/demos/device/keyboard/main.c new file mode 100644 index 00000000..3011c82c --- /dev/null +++ b/demos/device/keyboard/main.c @@ -0,0 +1,25 @@ +#include +#include +#include + +#include +#include +#include "tusb.h" + +// Variable to store CRP value in. Will be placed automatically +// by the linker when "Enable Code Read Protect" selected. +// See crp.h header for more information +__CRP const unsigned int CRP_WORD = CRP_NO_CRP ; + +int main(void) +{ + SystemInit(); + tusb_init(); + + while (1) + { + + } + + return 0; +}