diff --git a/CMakeLists.txt b/CMakeLists.txt index 27aea4d..304fde5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ include( Lib/CMake/initialize.cmake ) #| All of the modules must be specified, as they generate the sources list of files to compile #| Any modifications to this file will cause a complete rebuild of the project -#| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones +#| Please look at the {Scan,Macro,Output,Debug} for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index set( ScanModule "DPH" ) diff --git a/Output/pjrcUSB/avr/usb_keyboard_serial.c b/Output/pjrcUSB/avr/usb_keyboard_serial.c index 6b1c1a6..cbd9324 100644 --- a/Output/pjrcUSB/avr/usb_keyboard_serial.c +++ b/Output/pjrcUSB/avr/usb_keyboard_serial.c @@ -26,433 +26,109 @@ #include "usb_keyboard_serial.h" -// ----- Functions ----- - -// Set the avr into firmware reload mode -void usb_debug_reload() -{ - cli(); - // Disable watchdog, if enabled - // Disable all peripherals - - UDCON = 1; - USBCON = (1 << FRZCLK); // Disable USB - UCSR1B = 0; - _delay_ms( 5 ); - -#if defined(__AVR_AT90USB162__) // Teensy 1.0 - EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; - TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0; - DDRB = 0; DDRC = 0; DDRD = 0; - PORTB = 0; PORTC = 0; PORTD = 0; - asm volatile("jmp 0x3E00"); -#elif defined(__AVR_ATmega32U4__) // Teensy 2.0 - EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; - TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0; - DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0; - PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; - asm volatile("jmp 0x7E00"); -#elif defined(__AVR_AT90USB646__) // Teensy++ 1.0 - EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; - TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0; - DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; - PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; - asm volatile("jmp 0xFC00"); -#elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0 - EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; - TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0; - DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; - PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; - asm volatile("jmp 0x1FC00"); -#endif -} - - -// WDT Setup for software reset the chip -void wdt_init(void) -{ - MCUSR = 0; - wdt_disable(); -} - - -/************************************************************************** - * - * Configurable Options - * - **************************************************************************/ - -// When you write data, it goes into a USB endpoint buffer, which -// is transmitted to the PC when it becomes full, or after a timeout -// with no more writes. Even if you write in exactly packet-size -// increments, this timeout is used to send a "zero length packet" -// that tells the PC no more data is expected and it should pass -// any buffered data to the application that may be waiting. If -// you want data sent immediately, call usb_serial_flush_output(). -#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ - -// If the PC is connected but not "listening", this is the length -// of time before usb_serial_getchar() returns with an error. This -// is roughly equivilant to a real UART simply transmitting the -// bits on a wire where nobody is listening, except you get an error -// code which you can ignore for serial-like discard of data, or -// use to know your data wasn't sent. -#define TRANSMIT_TIMEOUT 25 /* in milliseconds */ - -// USB devices are supposed to implment a halt feature, which is -// rarely (if ever) used. If you comment this line out, the halt -// code will be removed, saving 116 bytes of space (gcc 4.3.0). -// This is not strictly USB compliant, but works with all major -// operating systems. -#define SUPPORT_ENDPOINT_HALT - - - -/************************************************************************** - * - * Descriptor Data - * - **************************************************************************/ - -// Descriptors are the data that your computer reads when it auto-detects -// this USB device (called "enumeration" in USB lingo). The most commonly -// changed items are editable at the top of this file. Changing things -// in here should only be done by those who've read chapter 9 of the USB -// spec and relevant portions of any USB class specifications! - - -static const uint8_t PROGMEM device_descriptor[] = { - 18, // bLength - 1, // bDescriptorType - 0x00, 0x02, // bcdUSB - 0, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - ENDPOINT0_SIZE, // bMaxPacketSize0 - LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor - LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct - 0x00, 0x01, // bcdDevice - 1, // iManufacturer - 2, // iProduct - 3, // iSerialNumber - 1 // bNumConfigurations -}; - -// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 -static const uint8_t PROGMEM keyboard_hid_report_desc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte - 0x95, 0x08, // Report Count (8), - 0x75, 0x01, // Report Size (1), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x05, 0x0C, // Usage Page (Consumer), - 0x09, 0xE9, // Usage (Volume Increment), - 0x09, 0xEA, // Usage (Volume Decrement), - 0x09, 0xE2, // Usage (Mute), - 0x09, 0xCD, // Usage (Play/Pause), - 0x09, 0xB5, // Usage (Scan Next Track), - 0x09, 0xB6, // Usage (Scan Previous Track), - 0x09, 0xB7, // Usage (Stop), - 0x09, 0xB8, // Usage (Eject), - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys - 0x95, 0x05, // Report Count (5), - 0x75, 0x01, // Report Size (1), - 0x05, 0x08, // Usage Page (LEDs), - 0x19, 0x01, // Usage Minimum (1), - 0x29, 0x05, // Usage Maximum (5), - 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report - 0x95, 0x01, // Report Count (1), - 0x75, 0x03, // Report Size (3), - 0x91, 0x03, // Output (Constant), ;LED report padding - 0x95, 0x06, // Report Count (6), - 0x75, 0x08, // Report Size (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x7F, // Logical Maximum(104), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x7F, // Usage Maximum (104), - 0x81, 0x00, // Input (Data, Array), ;Normal keys - 0xc0 // End Collection -}; - -// + + -#define CONFIG1_DESC_SIZE (9 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7) -#define KEYBOARD_HID_DESC_OFFSET (9 + 9) -#define SERIAL_CDC_DESC_OFFSET (9 + 9+9+7) -static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { -// --- Configuration --- -// - 9 bytes - - // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 - 9, // bLength; - 2, // bDescriptorType; - LSB(CONFIG1_DESC_SIZE), // wTotalLength - MSB(CONFIG1_DESC_SIZE), - 3, // bNumInterfaces - 1, // bConfigurationValue - 0, // iConfiguration - 0xC0, // bmAttributes - 50, // bMaxPower - -// --- Keyboard HID --- -// - 9 bytes - - // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - KEYBOARD_INTERFACE, // bInterfaceNumber - 0, // bAlternateSetting - 1, // bNumEndpoints - 0x03, // bInterfaceClass (0x03 = HID) - 0x01, // bInterfaceSubClass (0x01 = Boot) - 0x01, // bInterfaceProtocol (0x01 = Keyboard) - 0, // iInterface -// - 9 bytes - - // HID interface descriptor, HID 1.11 spec, section 6.2.1 - 9, // bLength - 0x21, // bDescriptorType - 0x11, 0x01, // bcdHID - 0, // bCountryCode - 1, // bNumDescriptors - 0x22, // bDescriptorType - LSB(sizeof(keyboard_hid_report_desc)), // wDescriptorLength - MSB(sizeof(keyboard_hid_report_desc)), -// - 7 bytes - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress - 0x03, // bmAttributes (0x03=intr) - KEYBOARD_SIZE, 0, // wMaxPacketSize - KEYBOARD_INTERVAL, // bInterval - -// --- Serial CDC --- -// - 8 bytes - - // interface association descriptor, USB ECN, Table 9-Z - 8, // bLength - 11, // bDescriptorType - CDC_STATUS_INTERFACE, // bFirstInterface - 2, // bInterfaceCount - 0x02, // bFunctionClass - 0x02, // bFunctionSubClass - 0x01, // bFunctionProtocol - 4, // iFunction -// - 9 bytes - - // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - CDC_STATUS_INTERFACE, // bInterfaceNumber - 0, // bAlternateSetting - 1, // bNumEndpoints - 0x02, // bInterfaceClass - 0x02, // bInterfaceSubClass - 0x01, // bInterfaceProtocol - 0, // iInterface -// - 5 bytes - - // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 - 5, // bFunctionLength - 0x24, // bDescriptorType - 0x00, // bDescriptorSubtype - 0x10, 0x01, // bcdCDC -// - 5 bytes - - // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 - 5, // bFunctionLength - 0x24, // bDescriptorType - 0x01, // bDescriptorSubtype - 0x01, // bmCapabilities - 1, // bDataInterface -// - 4 bytes - - // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 - 4, // bFunctionLength - 0x24, // bDescriptorType - 0x02, // bDescriptorSubtype - 0x06, // bmCapabilities -// - 5 bytes - - // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 - 5, // bFunctionLength - 0x24, // bDescriptorType - 0x06, // bDescriptorSubtype - CDC_STATUS_INTERFACE, // bMasterInterface - CDC_DATA_INTERFACE, // bSlaveInterface0 -// - 7 bytes - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress - 0x03, // bmAttributes (0x03=intr) - CDC_ACM_SIZE, 0, // wMaxPacketSize - 64, // bInterval -// - 9 bytes - - // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - CDC_DATA_INTERFACE, // bInterfaceNumber - 0, // bAlternateSetting - 2, // bNumEndpoints - 0x0A, // bInterfaceClass - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0, // iInterface -// - 7 bytes - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - CDC_RX_ENDPOINT, // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - CDC_RX_SIZE, 0, // wMaxPacketSize - 0, // bInterval -// - 7 bytes - - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - CDC_TX_ENDPOINT | 0x80, // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - CDC_TX_SIZE, 0, // wMaxPacketSize - 0, // bInterval -}; - -// If you're desperate for a little extra code memory, these strings -// can be completely removed if iManufacturer, iProduct, iSerialNumber -// in the device desciptor are changed to zeros. -struct usb_string_descriptor_struct { - uint8_t bLength; - uint8_t bDescriptorType; - int16_t wString[]; -}; -static const struct usb_string_descriptor_struct PROGMEM string0 = { - 4, - 3, - {0x0409} -}; -static const struct usb_string_descriptor_struct PROGMEM string1 = { - sizeof(STR_MANUFACTURER), - 3, - STR_MANUFACTURER -}; -static const struct usb_string_descriptor_struct PROGMEM string2 = { - sizeof(STR_PRODUCT), - 3, - STR_PRODUCT -}; -static const struct usb_string_descriptor_struct PROGMEM string3 = { - sizeof(STR_SERIAL), - 3, - STR_SERIAL -}; - -// This table defines which descriptor data is sent for each specific -// request from the host (in wValue and wIndex). -static const struct descriptor_list_struct { - uint16_t wValue; - uint16_t wIndex; - const uint8_t *addr; - uint8_t length; -} PROGMEM descriptor_list[] = { - {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, - {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, - {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, - {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, - {0x0300, 0x0000, (const uint8_t *)&string0, 4}, - {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, - {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, - {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)} -}; -#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) - - -/************************************************************************** - * - * Variables - these are the only non-stack RAM usage - * - **************************************************************************/ +// ----- Variables ----- // zero when we are not configured, non-zero when enumerated -static volatile uint8_t usb_configuration=0; +static volatile uint8_t usb_configuration = 0; // the time remaining before we transmit any partially full // packet, or send a zero length packet. -static volatile uint8_t transmit_flush_timer=0; -static uint8_t transmit_previous_timeout=0; +static volatile uint8_t transmit_flush_timer = 0; +static uint8_t transmit_previous_timeout = 0; // serial port settings (baud rate, control signals, etc) set // by the PC. These are ignored, but kept in RAM. -static uint8_t cdc_line_coding[7]={0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08}; -static uint8_t cdc_line_rtsdtr=0; +static uint8_t cdc_line_coding[7] = {0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08}; +static uint8_t cdc_line_rtsdtr = 0; -/************************************************************************** - * - * Public Functions - these are the API intended for the user - * - **************************************************************************/ +// ----- USB Keyboard Functions ----- -// initialize USB -void usb_init(void) +// Sends normal keyboard out to host +// NOTE: Make sure to match the descriptor +void usb_keyboard_toHost() { - HW_CONFIG(); - USB_FREEZE(); // enable USB - PLL_CONFIG(); // config PLL - while (!(PLLCSR & (1<= NUM_DESC_LIST) { - UECONX = (1<= NUM_DESC_LIST ) + { + UECONX = (1 << STALLRQ) | (1 << EPEN); //stall return; } desc_val = pgm_read_word(list); - if (desc_val != wValue) { - list += sizeof(struct descriptor_list_struct); + if ( desc_val != wValue ) + { + list += sizeof( struct descriptor_list_struct ); continue; } list += 2; desc_val = pgm_read_word(list); - if (desc_val != wIndex) { - list += sizeof(struct descriptor_list_struct)-2; + if ( desc_val != wIndex ) + { + list += sizeof(struct descriptor_list_struct) - 2; continue; } list += 2; @@ -977,31 +725,38 @@ ISR(USB_COM_vect) } while (len || n == ENDPOINT0_SIZE); return; } + if (bRequest == SET_ADDRESS) { usb_send_in(); usb_wait_in_ready(); UDADDR = wValue | (1<> 8); + USBKeys_Idle_Count = 0; + //usb_wait_in_ready(); + usb_send_in(); + return; + } + if ( bRequest == HID_SET_PROTOCOL ) + { + USBKeys_Protocol = wValue; // 0 - Boot Mode, 1 - NKRO Mode + //usb_wait_in_ready(); + usb_send_in(); + return; + } + } + } + if (bRequest == CDC_GET_LINE_CODING && bmRequestType == 0xA1) { usb_wait_in_ready(); p = cdc_line_coding; @@ -1040,20 +855,17 @@ ISR(USB_COM_vect) if (bRequest == GET_STATUS) { usb_wait_in_ready(); i = 0; - #ifdef SUPPORT_ENDPOINT_HALT if (bmRequestType == 0x82) { UENUM = wIndex; if (UECONX & (1<> 8); - USBKeys_Idle_Count = 0; - //usb_wait_in_ready(); - usb_send_in(); - return; - } - if (bRequest == HID_SET_PROTOCOL) { - USBKeys_Protocol = wValue; - //usb_wait_in_ready(); - usb_send_in(); - return; - } - } - } } - UECONX = (1< UECFG1X - 128 and 256 bytes are for endpoint 1 only +#define EP_SIZE(s) ((s) == 256 ? 0x50 : \ + ((s) == 128 ? 0x40 : \ + ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))))) #define LSB(n) (n & 255) #define MSB(n) ((n >> 8) & 255) @@ -172,50 +175,453 @@ int8_t usb_serial_set_control(uint8_t signals); // set DSR, DCD, RI, etc #define CDC_GET_LINE_CODING 0x21 #define CDC_SET_CONTROL_LINE_STATE 0x22 +// CDC Configuration +// When you write data, it goes into a USB endpoint buffer, which +// is transmitted to the PC when it becomes full, or after a timeout +// with no more writes. Even if you write in exactly packet-size +// increments, this timeout is used to send a "zero length packet" +// that tells the PC no more data is expected and it should pass +// any buffered data to the application that may be waiting. If +// you want data sent immediately, call usb_serial_flush_output(). +#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ + +// If the PC is connected but not "listening", this is the length +// of time before usb_serial_getchar() returns with an error. This +// is roughly equivilant to a real UART simply transmitting the +// bits on a wire where nobody is listening, except you get an error +// code which you can ignore for serial-like discard of data, or +// use to know your data wasn't sent. +#define TRANSMIT_TIMEOUT 25 /* in milliseconds */ + // ----- Endpoint Configuration ----- -#define ENDPOINT0_SIZE 32 +#define ENDPOINT0_SIZE 32 -#define KEYBOARD_INTERFACE 0 -#define KEYBOARD_ENDPOINT 2 -#define KEYBOARD_SIZE 8 -#define KEYBOARD_INTERVAL 1 -#define KEYBOARD_HID_BUFFER EP_DOUBLE_BUFFER +#define KEYBOARD_NKRO_INTERFACE 0 +#define KEYBOARD_NKRO_ENDPOINT 1 +#define KEYBOARD_NKRO_SIZE 16 +#define KEYBOARD_NKRO_HID_BUFFER EP_DOUBLE_BUFFER -#define CDC_IAD_DESCRIPTOR 1 -#define CDC_STATUS_INTERFACE 1 -#define CDC_DATA_INTERFACE 2 -#define CDC_ACM_ENDPOINT 3 -#define CDC_RX_ENDPOINT 4 -#define CDC_TX_ENDPOINT 5 +#define KEYBOARD_INTERFACE 1 +#define KEYBOARD_ENDPOINT 2 +#define KEYBOARD_SIZE 8 +#define KEYBOARD_HID_BUFFER EP_DOUBLE_BUFFER + +#define CDC_IAD_DESCRIPTOR 1 +#define CDC_STATUS_INTERFACE 2 +#define CDC_DATA_INTERFACE 3 +#define CDC_ACM_ENDPOINT 3 +#define CDC_RX_ENDPOINT 4 +#define CDC_TX_ENDPOINT 5 #if defined(__AVR_AT90USB162__) -#define CDC_ACM_SIZE 16 -#define CDC_ACM_BUFFER EP_SINGLE_BUFFER -#define CDC_RX_SIZE 32 -#define CDC_RX_BUFFER EP_DOUBLE_BUFFER -#define CDC_TX_SIZE 32 -#define CDC_TX_BUFFER EP_DOUBLE_BUFFER +#define CDC_ACM_SIZE 16 +#define CDC_ACM_BUFFER EP_SINGLE_BUFFER +#define CDC_RX_SIZE 32 +#define CDC_RX_BUFFER EP_DOUBLE_BUFFER +#define CDC_TX_SIZE 32 +#define CDC_TX_BUFFER EP_DOUBLE_BUFFER #else -#define CDC_ACM_SIZE 16 -#define CDC_ACM_BUFFER EP_SINGLE_BUFFER -#define CDC_RX_SIZE 64 -#define CDC_RX_BUFFER EP_DOUBLE_BUFFER -#define CDC_TX_SIZE 64 -#define CDC_TX_BUFFER EP_DOUBLE_BUFFER +#define CDC_ACM_SIZE 16 +#define CDC_ACM_BUFFER EP_SINGLE_BUFFER +#define CDC_RX_SIZE 64 +#define CDC_RX_BUFFER EP_DOUBLE_BUFFER +#define CDC_TX_SIZE 64 +#define CDC_TX_BUFFER EP_DOUBLE_BUFFER #endif // Endpoint 0 is reserved for the control endpoint // Endpoint 1 has a 256 byte buffer // Endpoints 2-6 have 64 byte buffers static const uint8_t PROGMEM endpoint_config_table[] = { - 0, // 256 byte - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_HID_BUFFER, // 64 byte - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(CDC_ACM_SIZE) | CDC_ACM_BUFFER, // 64 byte - 1, EP_TYPE_BULK_OUT, EP_SIZE(CDC_RX_SIZE) | CDC_RX_BUFFER, // 64 byte - 1, EP_TYPE_BULK_IN, EP_SIZE(CDC_TX_SIZE) | CDC_TX_BUFFER, // 64 byte + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_NKRO_SIZE) | KEYBOARD_NKRO_HID_BUFFER, // 256 byte + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_HID_BUFFER, // 64 byte + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(CDC_ACM_SIZE) | CDC_ACM_BUFFER, // 64 byte + 1, EP_TYPE_BULK_OUT, EP_SIZE(CDC_RX_SIZE) | CDC_RX_BUFFER, // 64 byte + 1, EP_TYPE_BULK_IN, EP_SIZE(CDC_TX_SIZE) | CDC_TX_BUFFER, // 64 byte + 0, // 64 byte }; + + +// ----- Descriptor Configuration ----- + +// Descriptors are the data that your computer reads when it auto-detects +// this USB device (called "enumeration" in USB lingo). The most commonly +// changed items are editable at the top of this file. Changing things +// in here should only be done by those who've read chapter 9 of the USB +// spec and relevant portions of any USB class specifications! + + +static const uint8_t PROGMEM device_descriptor[] = { + 18, // bLength + 1, // bDescriptorType + 0x00, 0x02, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + ENDPOINT0_SIZE, // bMaxPacketSize0 + LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor + LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct + 0x00, 0x01, // bcdDevice + 1, // iManufacturer + 2, // iProduct + 3, // iSerialNumber + 1 // bNumConfigurations +}; + +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static const uint8_t PROGMEM keyboard_hid_report_desc[] = { + // Keyboard Collection + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application) - Keyboard, + + // Modifier Byte + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), + + // LED Report + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), + + // LED Report Padding + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), + + // Normal Keys + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x7F, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x7F, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + 0xc0, // End Collection - Keyboard +}; + +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static const uint8_t PROGMEM keyboard_nkro_hid_report_desc[] = { + /* + // System Control Collection + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x80, // Usage (System Control), + 0xA1, 0x01, // Collection (Application), + 0x85, 0x01, // Report ID (1), + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x19, 0x81, // Usage Minimum (129), + 0x29, 0x83, // Usage Maximum (131), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x81, 0x03, // Input (Constant, Data, Variable, Absolute), + 0xc0, 0x00, // End Collection - System Control + */ + + // Keyboard Collection + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application) - Keyboard, + + // Modifier Byte + 0x75, 0x01, // Report Size (1), + 0x85, 0x02, // Report ID (2), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), + + // Media Keys + 0x95, 0x08, // Report Count (8), + 0x85, 0x03, // Report ID (3), + 0x75, 0x01, // Report Size (1), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x05, 0x0C, // Usage Page (Consumer), + 0x09, 0xE9, // Usage (Volume Increment), + 0x09, 0xEA, // Usage (Volume Decrement), + 0x09, 0xE2, // Usage (Mute), + 0x09, 0xCD, // Usage (Play/Pause), + 0x09, 0xB5, // Usage (Scan Next Track), + 0x09, 0xB6, // Usage (Scan Previous Track), + 0x09, 0xB7, // Usage (Stop), + 0x09, 0xB8, // Usage (Eject), + 0x81, 0x02, // Input (Data, Variable, Absolute), + + // LED Report + 0x95, 0x05, // Report Count (5), + 0x85, 0x01, // Report ID (1), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), + + // LED Report Padding + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), + + /* + // Misc Keys + 0x95, 0x06, // Report Count (6), + 0x75, 0x01, // Report Size (1), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x7F, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x7F, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + */ + + // Normal Keys + 0x95, 0x06, // Report Count (6), + 0x85, 0x04, // Report ID (4), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x7F, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x7F, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + 0xc0, // End Collection - Keyboard +}; + +// + + + +#define CONFIG1_DESC_SIZE (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7) +#define KEYBOARD_HID_DESC_OFFSET (9 + 9) +#define KEYBOARD_NKRO_HID_DESC_OFFSET (9 + 9+9+7 + 9) +#define SERIAL_CDC_DESC_OFFSET (9 + 9+9+7 + 9+9+7) +static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { +// --- Configuration --- +// - 9 bytes - + // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 + 9, // bLength; + 2, // bDescriptorType; + LSB(CONFIG1_DESC_SIZE), // wTotalLength + MSB(CONFIG1_DESC_SIZE), + 4, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0x80, // bmAttributes + 250, // bMaxPower + +// --- Keyboard HID --- +// - 9 bytes - + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + KEYBOARD_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) + 0x01, // bInterfaceProtocol (0x01 = Keyboard) + 0, // iInterface +// - 9 bytes - + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 33, // bCountryCode - Defaulting to US for now. TODO + 1, // bNumDescriptors + 0x22, // bDescriptorType + LSB(sizeof(keyboard_hid_report_desc)), // wDescriptorLength + MSB(sizeof(keyboard_hid_report_desc)), +// - 7 bytes - + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + KEYBOARD_SIZE, 0, // wMaxPacketSize + 1, // bInterval + +// --- NKRO Keyboard HID --- +// - 9 bytes - + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + KEYBOARD_NKRO_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) + 0x01, // bInterfaceProtocol (0x01 = Keyboard) + 0, // iInterface +// - 9 bytes - + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 33, // bCountryCode - Defaulting to US for now. TODO + 1, // bNumDescriptors + 0x22, // bDescriptorType + // wDescriptorLength + LSB(sizeof(keyboard_nkro_hid_report_desc)), + MSB(sizeof(keyboard_nkro_hid_report_desc)), +// - 7 bytes - + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + KEYBOARD_NKRO_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + KEYBOARD_NKRO_SIZE, 0, // wMaxPacketSize + 1, // bInterval + +// --- Serial CDC --- +// - 8 bytes - + // interface association descriptor, USB ECN, Table 9-Z + 8, // bLength + 11, // bDescriptorType + CDC_STATUS_INTERFACE, // bFirstInterface + 2, // bInterfaceCount + 0x02, // bFunctionClass + 0x02, // bFunctionSubClass + 0x01, // bFunctionProtocol + 4, // iFunction +// - 9 bytes - + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + CDC_STATUS_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x02, // bInterfaceClass + 0x02, // bInterfaceSubClass + 0x01, // bInterfaceProtocol + 0, // iInterface +// - 5 bytes - + // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 + 5, // bFunctionLength + 0x24, // bDescriptorType + 0x00, // bDescriptorSubtype + 0x10, 0x01, // bcdCDC +// - 5 bytes - + // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 + 5, // bFunctionLength + 0x24, // bDescriptorType + 0x01, // bDescriptorSubtype + 0x01, // bmCapabilities + 1, // bDataInterface +// - 4 bytes - + // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 + 4, // bFunctionLength + 0x24, // bDescriptorType + 0x02, // bDescriptorSubtype + 0x06, // bmCapabilities +// - 5 bytes - + // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 + 5, // bFunctionLength + 0x24, // bDescriptorType + 0x06, // bDescriptorSubtype + CDC_STATUS_INTERFACE, // bMasterInterface + CDC_DATA_INTERFACE, // bSlaveInterface0 +// - 7 bytes - + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + CDC_ACM_SIZE, 0, // wMaxPacketSize + 64, // bInterval +// - 9 bytes - + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + CDC_DATA_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 2, // bNumEndpoints + 0x0A, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0, // iInterface +// - 7 bytes - + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + CDC_RX_ENDPOINT, // bEndpointAddress + 0x02, // bmAttributes (0x02=bulk) + CDC_RX_SIZE, 0, // wMaxPacketSize + 0, // bInterval +// - 7 bytes - + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + CDC_TX_ENDPOINT | 0x80, // bEndpointAddress + 0x02, // bmAttributes (0x02=bulk) + CDC_TX_SIZE, 0, // wMaxPacketSize + 0, // bInterval +}; + + +// Configuration Endpoint (0) Descriptor +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + int16_t wString[]; +}; +static const struct usb_string_descriptor_struct PROGMEM string0 = { + 4, + 3, + {0x0409} +}; +static const struct usb_string_descriptor_struct PROGMEM string1 = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +static const struct usb_string_descriptor_struct PROGMEM string2 = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; +static const struct usb_string_descriptor_struct PROGMEM string3 = { + sizeof(STR_SERIAL), + 3, + STR_SERIAL +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +static const struct descriptor_list_struct { + uint16_t wValue; + uint16_t wIndex; + const uint8_t *addr; + uint8_t length; +} PROGMEM descriptor_list[] = { + {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, + {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, + {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, + {0x2100, KEYBOARD_INTERFACE, config1_descriptor + KEYBOARD_HID_DESC_OFFSET, 9}, + {0x2200, KEYBOARD_NKRO_INTERFACE, keyboard_nkro_hid_report_desc, sizeof(keyboard_nkro_hid_report_desc)}, + {0x2100, KEYBOARD_NKRO_INTERFACE, config1_descriptor + KEYBOARD_NKRO_HID_DESC_OFFSET, 9}, + {0x0300, 0x0000, (const uint8_t *)&string0, 4}, + {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, + {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, + {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)} +}; +#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) + + #endif // usb_keyboard_serial_h__ diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index 9575f2d..03c0015 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -45,23 +45,23 @@ // ----- Function Declarations ----- -void cliFunc_readLEDs ( char* args ); -void cliFunc_sendKeys ( char* args ); -void cliFunc_setKeys ( char* args ); -void cliFunc_setLEDs ( char* args ); -void cliFunc_setMod ( char* args ); +void cliFunc_kbdProtocol( char* args ); +void cliFunc_readLEDs ( char* args ); +void cliFunc_sendKeys ( char* args ); +void cliFunc_setKeys ( char* args ); +void cliFunc_setMod ( char* args ); // ----- Variables ----- // Output Module command dictionary -char* outputCLIDictName = "USB Module Commands (Not all commands fully work yet...)"; +char* outputCLIDictName = "USB Module Commands"; CLIDictItem outputCLIDict[] = { - { "readLEDs", "Read LED byte. See \033[35msetLEDs\033[0m.", cliFunc_readLEDs }, - { "sendKeys", "Send the prepared list of USB codes and modifier byte.", cliFunc_sendKeys }, - { "setKeys", "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m.", cliFunc_setKeys }, - { "setLEDs", "Set LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_setLEDs }, - { "setMod", "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, + { "kbdProtocol", "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode", cliFunc_kbdProtocol }, + { "readLEDs", "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_readLEDs }, + { "sendKeys", "Send the prepared list of USB codes and modifier byte.", cliFunc_sendKeys }, + { "setKeys", "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m.", cliFunc_setKeys }, + { "setMod", "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, { 0, 0, 0 } // Null entry for dictionary end }; @@ -83,10 +83,10 @@ CLIDictItem outputCLIDict[] = { // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana volatile uint8_t USBKeys_LEDs = 0; -// protocol setting from the host. We use exactly the same report -// either way, so this variable only stores the setting since we -// are required to be able to report which setting is in use. - uint8_t USBKeys_Protocol = 1; +// Protocol setting from the host. +// 0 - Boot Mode (Default, until set by the host) +// 1 - NKRO Mode +volatile uint8_t USBKeys_Protocol = 1; // the idle configuration, how often we send the report to the // host (ms * 4) even when it hasn't changed @@ -201,10 +201,18 @@ inline void Output_softReset() // ----- CLI Command Functions ----- +void cliFunc_kbdProtocol( char* args ) +{ + print( NL ); + info_msg("Keyboard Protocol: "); + printInt8( USBKeys_Protocol ); +} + + void cliFunc_readLEDs( char* args ) { print( NL ); - info_msg("LED State: "); + info_msg("LED State (This doesn't work yet...): "); printInt8( USBKeys_LEDs ); } @@ -245,18 +253,6 @@ void cliFunc_setKeys( char* args ) } -void cliFunc_setLEDs( char* args ) -{ - // Parse number from argument - // NOTE: Only first argument is used - char* arg1Ptr; - char* arg2Ptr; - CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); - - USBKeys_LEDs = decToInt( arg1Ptr ); -} - - void cliFunc_setMod( char* args ) { // Parse number from argument diff --git a/Output/pjrcUSB/output_com.h b/Output/pjrcUSB/output_com.h index d562a25..84b22ae 100644 --- a/Output/pjrcUSB/output_com.h +++ b/Output/pjrcUSB/output_com.h @@ -49,9 +49,9 @@ extern uint8_t USBKeys_Sent; extern volatile uint8_t USBKeys_LEDs; static const uint8_t USBKeys_MaxSize = USB_MAX_KEY_SEND; +extern volatile uint8_t USBKeys_Protocol; // 0 - Boot Mode, 1 - NKRO Mode // Misc variables (XXX Some are only properly utilized using AVR) -extern uint8_t USBKeys_Protocol; extern uint8_t USBKeys_Idle_Config; extern uint8_t USBKeys_Idle_Count;