# HG changeset patch # User Jacob Alexander # Date 1299739774 28800 # Node ID c3b2eaa4a89d6b59fbbb44a605a1e767a2b88a10 # Parent 0f88e9aad77a5e11a0b11cce6678399ab2ad0cae Significant progress made. - Only need to decode a bunch more of the matrix to get the proper key assignments - All of the infrastructure is in place for decoding like matrices for the teensy diff -r 0f88e9aad77a -r c3b2eaa4a89d Makefile --- a/Makefile Mon Mar 07 10:42:32 2011 -0800 +++ b/Makefile Wed Mar 09 22:49:34 2011 -0800 @@ -46,7 +46,9 @@ # List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c \ - usb_keyboard.c + print.c \ + usb_keyboard_debug.c \ + #usb_keyboard.c # MCU name, you MUST set this to match the board you are using diff -r 0f88e9aad77a -r c3b2eaa4a89d main.c --- a/main.c Mon Mar 07 10:42:32 2011 -0800 +++ b/main.c Wed Mar 09 22:49:34 2011 -0800 @@ -23,12 +23,17 @@ #include #include #include -#include "usb_keyboard.h" +//#include "usb_keyboard.h" + +// TEMP INCLUDES +#include "usb_keyboard_debug.h" +#include #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) -#define PRE_DRIVE_SLEEP -#define POST_DRIVE_SLEEP +// Sleep defined in milliseconds +#define PRE_DRIVE_SLEEP 50 +#define POST_DRIVE_SLEEP 50 #define DRIVE_reg_1 PORTB @@ -57,39 +62,67 @@ #define DRIVE_pin_11 #define DRIVE_pin_12 -#define DETECT_group_1 0 -#define DETECT_group_2 0 -#define DETECT_group_3 0 -#define DETECT_group_4 0 -#define DETECT_group_5 0 -#define DETECT_group_6 0 -#define DETECT_group_7 0 -#define DETECT_group_8 0 -#define DETECT_group_9 0 +#define DETECT_group_1 1 +#define DETECT_group_2 2 +#define DETECT_group_3 3 +#define DETECT_group_4 4 +#define DETECT_group_5 5 +#define DETECT_group_6 6 +#define DETECT_group_7 7 +#define DETECT_group_8 8 +#define DETECT_group_9 9 #define DETECT_group_10 #define DETECT_group_11 #define DETECT_group_12 -// Change number of ORDs if number of lines differ +#define DETECT_group_size_1 7 +#define DETECT_group_size_2 8 +#define DETECT_group_size_3 8 +#define DETECT_group_size_4 4 +#define DETECT_group_size_5 8 +#define DETECT_group_size_6 7 +#define DETECT_group_size_7 7 +#define DETECT_group_size_8 6 +#define DETECT_group_size_9 7 +#define DETECT_group_size_10 +#define DETECT_group_size_11 +#define DETECT_group_size_12 + +#define DETECT_group_array_1 {{KEY_SLASH,KEY_RIGHT_BRACE,KEY_ENTER,KEY_D,KEY_2,KEY_Q,KEY_C},{0,0,0,0,0,0,0}} +#define DETECT_group_array_2 {{KEY_TILDE,KEY_DELETE,KEY_LEFT,KEY_SPACE,KEY_X,KEY_S,KEY_TAB,KEY_1},{0,0,0,0,0,0,0,0}} +#define DETECT_group_array_3 {{KEY_BACKSPACE,KEY_UP,KEY_DOWN,KEY_A,KEY_INSERT,KEY_ALT,KEY_Z,KEY_RIGHT},{0,0,0,0,0,1,0,0}} +#define DETECT_group_array_4 {{KEY_ESC ,KEY_CTRL,KEY_CAPS_LOCK,KEY_SHIFT} ,{0,1,0,1}} +#define DETECT_group_array_5 0 +#define DETECT_group_array_6 0 +#define DETECT_group_array_7 {{KEY_L ,KEY_O ,KEY_0 ,KEY_N ,KEY_H,KEY_R,KEY_5},{0,0,0,0,0,0,0}} +#define DETECT_group_array_8 0 +#define DETECT_group_array_9 0 +#define DETECT_group_array_10 +#define DETECT_group_array_11 +#define DETECT_group_array_12 + + + + + + + +// XXX Change number of ORDs if number of lines differ #define DD_LOOP \ - for ( int c = 0;; c++ ) { \ + for ( int c = 1;; c++ ) { \ switch ( c ) { \ DD_CASE_ORD(1) \ DD_CASE_ORD(2) \ DD_CASE_ORD(3) \ - DD_CASE_ORD(4) \ - DD_CASE_ORD(5) \ - DD_CASE_ORD(6) \ - DD_CASE_ORD(7) \ - DD_CASE_ORD(8) \ - DD_CASE_END(9,c) \ + DD_CASE_END(4,c) \ } \ } #define DRIVE_DETECT(reg,pin,group) \ - reg |= (1 << pin);\ - detection(group);\ - reg &= (0 << pin); + reg &= ~(1 << pin); \ + detection(group); \ + reg |= (1 << pin); \ + _delay_ms(POST_DRIVE_SLEEP); #define DD_CASE(number) \ case number:\ @@ -101,18 +134,164 @@ #define DD_CASE_END(number,var) \ DD_CASE(number) \ - default: \ var = -1; \ break; -int main(void) +// Determine if key is either normal or a modifier +#define DET_GROUP_CHECK(index) \ + { \ + if ( groupArray[1][index] ) \ + curDetect.modifiers |= groupArray[0][index]; \ + else \ + curDetect.keyDetectArray[curDetect.keyDetectCount++] = groupArray[0][index]; \ + } + +// XXX - Detection Groups +// Checks each of the specified pins, and then if press detected, determine if the key is normal or a modifier +// Inverse logic applies for the PINs + +// Used for 1 detection group +#define DET_GROUP_1 \ + if ( !( PINB & (1 << 3) ) ) \ + DET_GROUP_CHECK(3) \ + if ( !( PINF & (1 << 1) ) ) \ + DET_GROUP_CHECK(2) \ + if ( !( PINF & (1 << 2) ) ) \ + DET_GROUP_CHECK(1) \ + if ( !( PINF & (1 << 3) ) ) \ + DET_GROUP_CHECK(0) + +// Used for 4 detection groups +#define DET_GROUP_2 \ + if ( !( PINC & (1 << 0) ) ) \ + DET_GROUP_CHECK(0) \ + if ( !( PINC & (1 << 1) ) ) \ + DET_GROUP_CHECK(1) \ + if ( !( PINC & (1 << 2) ) ) \ + DET_GROUP_CHECK(2) \ + if ( !( PINC & (1 << 3) ) ) \ + DET_GROUP_CHECK(3) \ + if ( !( PINC & (1 << 4) ) ) \ + DET_GROUP_CHECK(4) \ + if ( !( PINC & (1 << 5) ) ) \ + DET_GROUP_CHECK(5) \ + if ( !( PINC & (1 << 6) ) ) \ + DET_GROUP_CHECK(6) \ + +// Used for 1 detection group +#define DET_GROUP_3 \ + if ( !( PINC & (1 << 0) ) ) \ + DET_GROUP_CHECK(0) \ + if ( !( PINC & (1 << 1) ) ) \ + DET_GROUP_CHECK(1) \ + if ( !( PINC & (1 << 2) ) ) \ + DET_GROUP_CHECK(3) \ + if ( !( PINC & (1 << 4) ) ) \ + DET_GROUP_CHECK(4) \ + if ( !( PINC & (1 << 5) ) ) \ + DET_GROUP_CHECK(5) \ + if ( !( PINC & (1 << 6) ) ) \ + DET_GROUP_CHECK(6) \ + +// Used for 3 detection groups +#define DET_GROUP_4 \ + if ( !( PINC & (1 << 0) ) ) \ + DET_GROUP_CHECK(0) \ + if ( !( PINC & (1 << 1) ) ) \ + DET_GROUP_CHECK(1) \ + if ( !( PINC & (1 << 2) ) ) \ + DET_GROUP_CHECK(2) \ + if ( !( PINC & (1 << 3) ) ) \ + DET_GROUP_CHECK(3) \ + if ( !( PINC & (1 << 4) ) ) \ + DET_GROUP_CHECK(4) \ + if ( !( PINC & (1 << 5) ) ) \ + DET_GROUP_CHECK(5) \ + if ( !( PINC & (1 << 6) ) ) \ + DET_GROUP_CHECK(6) \ + if ( !( PINE & (1 << 1) ) ) \ + DET_GROUP_CHECK(7) \ + +// Combines the DET_GROUP_Xs above for the given groupArray +#define DET_GROUP(group,det_group) \ + case group: \ + { \ + uint8_t groupArray[2][DETECT_group_size##_##group] = DETECT_group_array##_##group; \ + DET_GROUP##_##det_group \ + } \ + break; + +struct keys { + uint8_t keyDetectCount; + uint8_t keyDetectArray[40]; + uint8_t modifiers; +} curDetect, prevDetect; + +void detection( int group ) +{ + _delay_ms(PRE_DRIVE_SLEEP); + curDetect.keyDetectCount = 0; + curDetect.modifiers = 0; + + // XXX Modify for different detection groups <-> groupArray mappings + switch ( group ) { + DET_GROUP(1,2) + DET_GROUP(2,4) + DET_GROUP(3,4) + DET_GROUP(4,1) + //DET_GROUP(5,4) + //DET_GROUP(6,2) + //DET_GROUP(7,2) + //DET_GROUP(8,3) + //DET_GROUP(9,2) + } + + + // Print out the current keys pressed + if ( curDetect.keyDetectCount > 0 ) { + print("Keys: "); + for ( int c = 0; c < curDetect.keyDetectCount; c++ ) { + phex( curDetect.keyDetectArray[c] ); + print(" "); + } + print("\n"); + } + if ( curDetect.modifiers ) { + print("Modifiers: "); + phex( curDetect.modifiers ); + print("\n"); + } +} + + + +// XXX This part is configurable +void pinSetup(void) +{ + // For each pin, 0=input, 1=output + DDRA = 0x00; + DDRB = 0x07; + DDRC = 0x80; + DDRD = 0x00; + DDRE = 0xC0; + DDRF = 0x31; + + // Setting pins to either high or pull-up resistor + PORTA = 0x00; + PORTB = 0xFF; + PORTC = 0xFF; + PORTD = 0x00; + PORTE = 0xFF; + PORTF = 0xFF; +} + +int main( void ) { // set for 16 MHz clock CPU_PRESCALE( 0 ); // Configuring Pins - - // TODO + pinSetup(); // Initialize the USB, and then wait for the host to set configuration. // If the Teensy is powered without a PC connected to the USB port, diff -r 0f88e9aad77a -r c3b2eaa4a89d print.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/print.c Wed Mar 09 22:49:34 2011 -0800 @@ -0,0 +1,62 @@ +/* Very basic print functions, intended to be used with usb_debug_only.c + * http://www.pjrc.com/teensy/ + * Copyright (c) 2008 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release + +#include +#include + +#include "print.h" + +void print_P(const char *s) +{ + char c; + + while (1) { + c = pgm_read_byte(s++); + if (!c) break; + if (c == '\n') usb_debug_putchar('\r'); + usb_debug_putchar(c); + } +} + +void phex1(unsigned char c) +{ + usb_debug_putchar(c + ((c < 10) ? '0' : 'A' - 10)); +} + +void phex(unsigned char c) +{ + phex1(c >> 4); + phex1(c & 15); +} + +void phex16(unsigned int i) +{ + phex(i >> 8); + phex(i); +} + + + + diff -r 0f88e9aad77a -r c3b2eaa4a89d print.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/print.h Wed Mar 09 22:49:34 2011 -0800 @@ -0,0 +1,16 @@ +#ifndef print_h__ +#define print_h__ + +#include +#include "usb_keyboard_debug.h" + +// this macro allows you to write print("some text") and +// the string is automatically placed into flash memory :) +#define print(s) print_P(PSTR(s)) +#define pchar(c) usb_debug_putchar(c) + +void print_P(const char *s); +void phex(unsigned char c); +void phex16(unsigned int i); + +#endif diff -r 0f88e9aad77a -r c3b2eaa4a89d usb_keyboard_debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usb_keyboard_debug.c Wed Mar 09 22:49:34 2011 -0800 @@ -0,0 +1,750 @@ +/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/usb_keyboard.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release +// Version 1.1: Add support for Teensy 2.0 + +#define USB_SERIAL_PRIVATE_INCLUDE +#include "usb_keyboard_debug.h" + +/************************************************************************** + * + * Configurable Options + * + **************************************************************************/ + +// You can change these to give your code its own name. +#define STR_MANUFACTURER L"MfgName" +#define STR_PRODUCT L"Keyboard" + + +// Mac OS-X and Linux automatically load the correct drivers. On +// Windows, even though the driver is supplied by Microsoft, an +// INF file is needed to load the driver. These numbers need to +// match the INF file. +#define VENDOR_ID 0x16C0 +#define PRODUCT_ID 0x047D + + +// 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 102 bytes of space (gcc 4.3.0). +// This is not strictly USB compliant, but works with all major +// operating systems. +#define SUPPORT_ENDPOINT_HALT + + + +/************************************************************************** + * + * Endpoint Buffer Configuration + * + **************************************************************************/ + +#define ENDPOINT0_SIZE 32 + +#define KEYBOARD_INTERFACE 0 +#define KEYBOARD_ENDPOINT 3 +#define KEYBOARD_SIZE 8 +#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER + +#define DEBUG_INTERFACE 1 +#define DEBUG_TX_ENDPOINT 4 +#define DEBUG_TX_SIZE 32 +#define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER + +static const uint8_t PROGMEM endpoint_config_table[] = { + 0, + 0, + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER +}; + + +/************************************************************************** + * + * 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 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 + 0, // iSerialNumber + 1 // bNumConfigurations +}; + +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static 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, 0x01, // Report Count (1), + 0x75, 0x08, // Report Size (8), + 0x81, 0x03, // Input (Constant), ;Reserved byte + 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, 0x68, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x68, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + 0xc0 // End Collection +}; + +static uint8_t PROGMEM debug_hid_report_desc[] = { + 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) + 0x09, 0x74, // Usage 0x74 + 0xA1, 0x53, // Collection 0x53 + 0x75, 0x08, // report size = 8 bits + 0x15, 0x00, // logical minimum = 0 + 0x26, 0xFF, 0x00, // logical maximum = 255 + 0x95, DEBUG_TX_SIZE, // report count + 0x09, 0x75, // usage + 0x81, 0x02, // Input (array) + 0xC0 // end collection +}; + +#define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7) +#define KEYBOARD_HID_DESC_OFFSET (9+9) +#define DEBUG_HID_DESC_OFFSET (9+9+9+7+9) +static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { + // 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), + 2, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0xC0, // bmAttributes + 50, // bMaxPower + // 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 + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(keyboard_hid_report_desc), // wDescriptorLength + 0, + // 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 + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + DEBUG_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0, // iInterface + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(debug_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + DEBUG_TX_SIZE, 0, // wMaxPacketSize + 1 // 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 struct usb_string_descriptor_struct PROGMEM string0 = { + 4, + 3, + {0x0409} +}; +static struct usb_string_descriptor_struct PROGMEM string1 = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +static struct usb_string_descriptor_struct PROGMEM string2 = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +static 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, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, + {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_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)} +}; +#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) + + +/************************************************************************** + * + * Variables - these are the only non-stack RAM usage + * + **************************************************************************/ + +// zero when we are not configured, non-zero when enumerated +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 debug_flush_timer=0; + +// which modifier keys are currently pressed +// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui +// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui +uint8_t keyboard_modifier_keys=0; + +// which keys are currently pressed, up to 6 keys may be down at once +uint8_t keyboard_keys[6]={0,0,0,0,0,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. +static uint8_t keyboard_protocol=1; + +// the idle configuration, how often we send the report to the +// host (ms * 4) even when it hasn't changed +static uint8_t keyboard_idle_config=125; + +// count until idle timeout +static uint8_t keyboard_idle_count=0; + +// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana +volatile uint8_t keyboard_leds=0; + + +/************************************************************************** + * + * Public Functions - these are the API intended for the user + * + **************************************************************************/ + + +// initialize USB +void usb_init(void) +{ + HW_CONFIG(); + USB_FREEZE(); // enable USB + PLL_CONFIG(); // config PLL + while (!(PLLCSR & (1<= NUM_DESC_LIST) { + UECONX = (1< desc_length) len = desc_length; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<= 1 && i <= MAX_ENDPOINT) { + usb_send_in(); + UENUM = i; + if (bRequest == SET_FEATURE) { + UECONX = (1<> 8); + keyboard_idle_count = 0; + //usb_wait_in_ready(); + usb_send_in(); + return; + } + if (bRequest == HID_SET_PROTOCOL) { + keyboard_protocol = wValue; + //usb_wait_in_ready(); + usb_send_in(); + return; + } + } + } + if (wIndex == DEBUG_INTERFACE) { + if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) { + len = wLength; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1< + +void usb_init(void); // initialize everything +uint8_t usb_configured(void); // is the USB port configured + +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier); +int8_t usb_keyboard_send(void); +extern uint8_t keyboard_modifier_keys; +extern uint8_t keyboard_keys[6]; +extern volatile uint8_t keyboard_leds; + +int8_t usb_debug_putchar(uint8_t c); // transmit a character +void usb_debug_flush_output(void); // immediately transmit any buffered output +#define USB_DEBUG_HID + +#define KEY_CTRL 0x01 +#define KEY_SHIFT 0x02 +#define KEY_ALT 0x04 +#define KEY_GUI 0x08 +#define KEY_LEFT_CTRL 0x01 +#define KEY_LEFT_SHIFT 0x02 +#define KEY_LEFT_ALT 0x04 +#define KEY_LEFT_GUI 0x08 +#define KEY_RIGHT_CTRL 0x10 +#define KEY_RIGHT_SHIFT 0x20 +#define KEY_RIGHT_ALT 0x40 +#define KEY_RIGHT_GUI 0x80 + +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_ENTER 40 +#define KEY_ESC 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUAL 46 +#define KEY_LEFT_BRACE 47 +#define KEY_RIGHT_BRACE 48 +#define KEY_BACKSLASH 49 +#define KEY_NUMBER 50 +#define KEY_SEMICOLON 51 +#define KEY_QUOTE 52 +#define KEY_TILDE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPS_LOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLL_LOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGE_UP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGE_DOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUM_LOCK 83 +#define KEYPAD_SLASH 84 +#define KEYPAD_ASTERIX 85 +#define KEYPAD_MINUS 86 +#define KEYPAD_PLUS 87 +#define KEYPAD_ENTER 88 +#define KEYPAD_1 89 +#define KEYPAD_2 90 +#define KEYPAD_3 91 +#define KEYPAD_4 92 +#define KEYPAD_5 93 +#define KEYPAD_6 94 +#define KEYPAD_7 95 +#define KEYPAD_8 96 +#define KEYPAD_9 97 +#define KEYPAD_0 98 +#define KEYPAD_PERIOD 99 + + + + +// Everything below this point is only intended for usb_serial.c +#ifdef USB_SERIAL_PRIVATE_INCLUDE +#include +#include +#include + +#define EP_TYPE_CONTROL 0x00 +#define EP_TYPE_BULK_IN 0x81 +#define EP_TYPE_BULK_OUT 0x80 +#define EP_TYPE_INTERRUPT_IN 0xC1 +#define EP_TYPE_INTERRUPT_OUT 0xC0 +#define EP_TYPE_ISOCHRONOUS_IN 0x41 +#define EP_TYPE_ISOCHRONOUS_OUT 0x40 + +#define EP_SINGLE_BUFFER 0x02 +#define EP_DOUBLE_BUFFER 0x06 + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +#define MAX_ENDPOINT 4 + +#define LSB(n) (n & 255) +#define MSB(n) ((n >> 8) & 255) + +#if defined(__AVR_AT90USB162__) +#define HW_CONFIG() +#define PLL_CONFIG() (PLLCSR = ((1<