]> git.donarmstrong.com Git - kiibohd-controller.git/commitdiff
Preparing from initial AVR USB NKRO support.
authorJacob Alexander <haata@kiibohd.com>
Tue, 10 Jun 2014 06:01:32 +0000 (23:01 -0700)
committerJacob Alexander <haata@kiibohd.com>
Tue, 10 Jun 2014 06:01:32 +0000 (23:01 -0700)
- Refactored pjrc USB (definitions to the .h file)

CMakeLists.txt
Output/pjrcUSB/avr/usb_keyboard_serial.c
Output/pjrcUSB/avr/usb_keyboard_serial.h
Output/pjrcUSB/output_com.c
Output/pjrcUSB/output_com.h

index 27aea4dd4d846ab48936f0012631e652f9978719..304fde5800ae19f9c1f04082950014e7c8b788e8 100644 (file)
@@ -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" )
index 6b1c1a61203535d631bec0ed1353d5b855e8b868..cbd9324573d6414b0336cfb490526646ac384ce9 100644 (file)
 #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
-};
-
-// <Configuration> + <Keyboard HID> + <Serial CDC>
-#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<<PLOCK))) ;       // wait for PLL lock
-        USB_CONFIG();                          // start USB clock
-        UDCON = 0;                             // enable attach resistor
-       usb_configuration = 0;
-        UDIEN = (1<<EORSTE)|(1<<SOFE);
-       sei();
+       uint8_t i;
 
-       // Disable watchdog timer after possible software reset
-       //wdt_init(); // XXX Not working...seems to be ok without this, not sure though
+       // Modifiers
+       UEDATX = USBKeys_Modifiers;
+
+       // Normal Keys
+       for ( i = 0; i < 6; i++)
+       {
+               UEDATX = USBKeys_Array[i];
+       }
+       UEINTX = 0x3A;
 }
 
-// return 0 if the USB is not configured, or the configuration
-// number selected by the HOST
-uint8_t usb_configured(void)
+// Sends NKRO keyboard out to host
+// NOTE: Make sure to match the descriptor
+void usb_nkrokeyboard_toHost()
 {
-       return usb_configuration;
+       uint8_t i;
+
+       // Modifiers
+       /*
+       UEDATX = 0x02;
+       UEDATX = USBKeys_Modifiers;
+       UEINTX = 0x3A;
+       */
+
+       // Media Keys
+       UEDATX = 0x03;
+       UEDATX = 0;
+       UEINTX = 0x3A;
+
+       // Normal Keys
+       UEDATX = 0x04;
+       for ( i = 0; i < 6; i++)
+       {
+               UEDATX = USBKeys_Array[i];
+       }
+       UEINTX = 0x3A;
 }
 
 // send the contents of USBKeys_Array and USBKeys_Modifiers
-int8_t usb_keyboard_send(void)
+int8_t usb_keyboard_send()
 {
-       uint8_t i, intr_state, timeout;
+       uint8_t intr_state, timeout;
 
-       if (!usb_configuration) return -1;
        intr_state = SREG;
-       cli();
-       UENUM = KEYBOARD_ENDPOINT;
        timeout = UDFNUML + 50;
-       while (1) {
-               // are we ready to transmit?
-               if (UEINTX & (1<<RWAL)) break;
+
+       // Ready to transmit keypresses?
+       do
+       {
                SREG = intr_state;
-               // has the USB gone offline?
-               if (!usb_configuration) return -1;
-               // have we waited too long?
-               if (UDFNUML == timeout) return -1;
+
+               // has the USB gone offline? or exceeded timeout?
+               if ( !usb_configuration || UDFNUML == timeout )
+                       return -1;
+
                // get ready to try checking again
                intr_state = SREG;
                cli();
-               UENUM = KEYBOARD_ENDPOINT;
-       }
-       UEDATX = USBKeys_Modifiers;
-       UEDATX = 0;
-       for (i=0; i<6; i++) {
-               UEDATX = USBKeys_Array[i];
+
+               // If not using Boot protocol, send NKRO
+               UENUM = USBKeys_Protocol ? KEYBOARD_NKRO_ENDPOINT : KEYBOARD_ENDPOINT;
+       } while ( !( UEINTX & (1 << RWAL) ) );
+
+       // Send normal keyboard interrupt packet(s)
+       switch ( USBKeys_Protocol )
+       {
        }
-       UEINTX = 0x3A;
+       usb_keyboard_toHost();
+
        USBKeys_Idle_Count = 0;
        SREG = intr_state;
        return 0;
 }
 
+
+
+// ----- USB Virtual Serial Port (CDC) Functions -----
+
 // get the next character, or -1 if nothing received
 int16_t usb_serial_getchar(void)
 {
@@ -827,55 +503,121 @@ int8_t usb_serial_set_control(uint8_t signals)
 
 
 
-/**************************************************************************
- *
- *  Private Functions - not intended for general user consumption....
- *
- **************************************************************************/
+// ----- General USB 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();
+}
+
+
+// initialize USB
+void usb_init(void)
+{
+       HW_CONFIG();
+       USB_FREEZE();                           // enable USB
+       PLL_CONFIG();                           // config PLL
+        while (!(PLLCSR & (1<<PLOCK))) ;       // wait for PLL lock
+        USB_CONFIG();                          // start USB clock
+        UDCON = 0;                             // enable attach resistor
+       usb_configuration = 0;
+        UDIEN = (1<<EORSTE) | (1<<SOFE);
+       sei();
+
+       // Disable watchdog timer after possible software reset
+       //wdt_init(); // XXX Not working...seems to be ok without this, not sure though
+}
+
+// return 0 if the USB is not configured, or the configuration
+// number selected by the HOST
+uint8_t usb_configured()
+{
+       return usb_configuration;
+}
 
 // USB Device Interrupt - handle all device-level events
 // the transmit buffer flushing is triggered by the start of frame
 //
-ISR(USB_GEN_vect)
+ISR( USB_GEN_vect )
 {
-       uint8_t intbits, t_cdc, i;
-       static uint8_t div4=0;
+       uint8_t intbits, t_cdc;
 
         intbits = UDINT;
         UDINT = 0;
-        if (intbits & (1<<EORSTI)) {
+        if ( intbits & (1 << EORSTI) )
+       {
                UENUM = 0;
                UECONX = 1;
                UECFG0X = EP_TYPE_CONTROL;
                UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
-               UEIENX = (1<<RXSTPE);
+               UEIENX = (1 << RXSTPE);
                usb_configuration = 0;
                cdc_line_rtsdtr = 0;
         }
-       if ((intbits & (1<<SOFI)) && usb_configuration) {
+       if ( (intbits & (1 << SOFI)) && usb_configuration )
+       {
                t_cdc = transmit_flush_timer;
-               if (t_cdc) {
+               if ( t_cdc )
+               {
                        transmit_flush_timer = --t_cdc;
-                       if (!t_cdc) {
+                       if ( !t_cdc )
+                       {
                                UENUM = CDC_TX_ENDPOINT;
                                UEINTX = 0x3A;
                        }
                }
-               if (USBKeys_Idle_Config && (++div4 & 3) == 0) {
-                       UENUM = KEYBOARD_ENDPOINT;
-                       if (UEINTX & (1<<RWAL)) {
-                               USBKeys_Idle_Count++;
-                               if (USBKeys_Idle_Count == USBKeys_Idle_Config) {
-                                       USBKeys_Idle_Count = 0;
-                                       UEDATX = USBKeys_Modifiers;
-                                       UEDATX = 0;
-                                       for (i=0; i<6; i++) {
-                                               UEDATX = USBKeys_Array[i];
-                                       }
-                                       UEINTX = 0x3A;
-                               }
+               static uint8_t div4 = 0;
+               if ( USBKeys_Idle_Config && (++div4 & 3) == 0 )
+               {
+                       USBKeys_Idle_Count++;
+                       if ( USBKeys_Idle_Count == USBKeys_Idle_Config )
+                       {
+                               // XXX TODO Is this even used? If so, when? -Jacob
+                               // From hasu's code, this section looks like it could fix the Mac SET_IDLE problem
+                               // Send normal keyboard interrupt packet(s)
+                               //usb_keyboard_toHost();
                        }
                }
        }
@@ -935,22 +677,28 @@ ISR(USB_COM_vect)
                 wLength = UEDATX;
                 wLength |= (UEDATX << 8);
                 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
-                if (bRequest == GET_DESCRIPTOR) {
+
+                if ( bRequest == GET_DESCRIPTOR )
+               {
                        list = (const uint8_t *)descriptor_list;
-                       for (i=0; ; i++) {
-                               if (i >= NUM_DESC_LIST) {
-                                       UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
+                       for ( i = 0; ; i++ )
+                       {
+                               if ( i >= 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<<ADDEN);
                        return;
                }
-               if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
+
+               if ( bRequest == SET_CONFIGURATION && bmRequestType == 0 )
+               {
                        usb_configuration = wValue;
                        cdc_line_rtsdtr = 0;
                        transmit_flush_timer = 0;
                        usb_send_in();
                        cfg = endpoint_config_table;
-                       for (i=1; i<6; i++) { // 4+1 of 7 endpoints are used // XXX Important to change if more endpoints are used
+                       // Setup each of the 6 additional endpoints (0th already configured)
+                       for ( i = 1; i < 6; i++ )
+                       {
                                UENUM = i;
                                en = pgm_read_byte(cfg++);
                                UECONX = en;
-                               if (en) {
+                               if (en)
+                               {
                                        UECFG0X = pgm_read_byte(cfg++);
                                        UECFG1X = pgm_read_byte(cfg++);
                                }
                        }
-                       UERST = 0x1E;
+                       UERST = 0x7E;
                        UERST = 0;
                        return;
                }
+
                if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
                        usb_wait_in_ready();
                        UEDATX = usb_configuration;
@@ -1009,6 +764,66 @@ ISR(USB_COM_vect)
                        return;
                }
 
+               //if ( wIndex == KEYBOARD_INTERFACE )
+               if ( wIndex == KEYBOARD_INTERFACE || wIndex == KEYBOARD_NKRO_INTERFACE )
+               {
+                       if ( bmRequestType == 0xA1)
+                       {
+                               if ( bRequest == HID_GET_REPORT )
+                               {
+                                       usb_wait_in_ready();
+
+                                       // XXX TODO Is this even used? If so, when? -Jacob
+                                       // Send normal keyboard interrupt packet(s)
+                                       //usb_keyboard_toHost();
+
+                                       usb_send_in();
+                                       return;
+                               }
+                               if ( bRequest == HID_GET_IDLE )
+                               {
+                                       usb_wait_in_ready();
+                                       UEDATX = USBKeys_Idle_Config;
+                                       usb_send_in();
+                                       return;
+                               }
+                               if ( bRequest == HID_GET_PROTOCOL )
+                               {
+                                       usb_wait_in_ready();
+                                       UEDATX = USBKeys_Protocol;
+                                       usb_send_in();
+                                       return;
+                               }
+                       USBKeys_Protocol = bRequest;
+                       }
+                       if ( bmRequestType == 0x21 )
+                       {
+                               if ( bRequest == HID_SET_REPORT )
+                               {
+                                       usb_wait_receive_out();
+                                       USBKeys_LEDs = UEDATX;
+                                       usb_ack_out();
+                                       usb_send_in();
+                                       return;
+                               }
+                               if ( bRequest == HID_SET_IDLE )
+                               {
+                                       USBKeys_Idle_Config = (wValue >> 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<<STALLRQ)) i = 1;
                                UENUM = 0;
                        }
-                       #endif
                        UEDATX = i;
                        UEDATX = 0;
                        usb_send_in();
                        return;
                }
 
-               #ifdef SUPPORT_ENDPOINT_HALT
                if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
                  && bmRequestType == 0x02 && wValue == 0) {
                        i = wIndex & 0x7F;
@@ -1070,57 +882,7 @@ ISR(USB_COM_vect)
                                return;
                        }
                }
-               #endif
-
-               if (wIndex == KEYBOARD_INTERFACE) {
-                       if (bmRequestType == 0xA1) {
-                               if (bRequest == HID_GET_REPORT) {
-                                       usb_wait_in_ready();
-                                       UEDATX = USBKeys_Modifiers;
-                                       UEDATX = 0;
-                                       for (i=0; i<6; i++) {
-                                               UEDATX = USBKeys_Array[i];
-                                       }
-                                       usb_send_in();
-                                       return;
-                               }
-                               if (bRequest == HID_GET_IDLE) {
-                                       usb_wait_in_ready();
-                                       UEDATX = USBKeys_Idle_Config;
-                                       usb_send_in();
-                                       return;
-                               }
-                               if (bRequest == HID_GET_PROTOCOL) {
-                                       usb_wait_in_ready();
-                                       UEDATX = USBKeys_Protocol;
-                                       usb_send_in();
-                                       return;
-                               }
-                       }
-                       if (bmRequestType == 0x21) {
-                               if (bRequest == HID_SET_REPORT) {
-                                       usb_wait_receive_out();
-                                       USBKeys_LEDs = UEDATX;
-                                       usb_ack_out();
-                                       usb_send_in();
-                                       return;
-                               }
-                               if (bRequest == HID_SET_IDLE) {
-                                       USBKeys_Idle_Config = (wValue >> 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<<STALLRQ) | (1<<EPEN);      // stall
+       UECONX = (1 << STALLRQ) | (1 << EPEN);  // stall
 }
 
index 4880c881461e03c0ff88cdfd423928730cef9a68..254830b1fceb5afb6ac943f665752b3fd71dc3e5 100644 (file)
@@ -79,10 +79,13 @@ int8_t usb_serial_set_control(uint8_t signals); // set DSR, DCD, RI, etc
 // Software reset the chip
 #define usb_debug_software_reset() do { wdt_enable( WDTO_15MS ); for(;;); } while(0)
 
-#define EP_SIZE(s)     ((s) == 64 ? 0x30 :     \
-                       ((s) == 32 ? 0x20 :     \
-                       ((s) == 16 ? 0x10 :     \
-                                    0x00)))
+// See EPSIZE -> 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
+};
+
+// <Configuration> + <Keyboard HID> + <NKRO Keyboard HID> + <Serial CDC>
+#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__
 
index 9575f2dc691446d251998afbfc8541442d5dcf81..03c0015995c3b5d27fc5de8f2b162f41ae2e06d0 100644 (file)
 
 // ----- 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
index d562a254868d5c7047e1c0b47d56cc93f44e298d..84b22ae0a00967597287fbdb97a7a8662f01d5e0 100644 (file)
@@ -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;