diff options
Diffstat (limited to 'protocol/pjrc')
| -rw-r--r-- | protocol/pjrc/bootloader_teensy.c | 40 | ||||
| -rw-r--r-- | protocol/pjrc/main.c | 97 | ||||
| -rw-r--r-- | protocol/pjrc/pjrc.c | 76 | ||||
| -rw-r--r-- | protocol/pjrc/pjrc.h | 26 | ||||
| -rw-r--r-- | protocol/pjrc/usb.c | 962 | ||||
| -rw-r--r-- | protocol/pjrc/usb.h | 137 | ||||
| -rw-r--r-- | protocol/pjrc/usb_debug.c | 102 | ||||
| -rw-r--r-- | protocol/pjrc/usb_debug.h | 42 | ||||
| -rw-r--r-- | protocol/pjrc/usb_extra.c | 70 | ||||
| -rw-r--r-- | protocol/pjrc/usb_extra.h | 46 | ||||
| -rw-r--r-- | protocol/pjrc/usb_keyboard.c | 120 | ||||
| -rw-r--r-- | protocol/pjrc/usb_keyboard.h | 42 | ||||
| -rw-r--r-- | protocol/pjrc/usb_mouse.c | 81 | ||||
| -rw-r--r-- | protocol/pjrc/usb_mouse.h | 50 |
14 files changed, 1891 insertions, 0 deletions
diff --git a/protocol/pjrc/bootloader_teensy.c b/protocol/pjrc/bootloader_teensy.c new file mode 100644 index 000000000..9d34852f1 --- /dev/null +++ b/protocol/pjrc/bootloader_teensy.c | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* See http://www.pjrc.com/teensy/jump_to_bootloader.html */ | ||
| 2 | #include <avr/io.h> | ||
| 3 | #include <avr/interrupt.h> | ||
| 4 | #include <util/delay.h> | ||
| 5 | #include "bootloader.h" | ||
| 6 | |||
| 7 | void bootloader_jump(void) { | ||
| 8 | cli(); | ||
| 9 | // disable watchdog, if enabled | ||
| 10 | // disable all peripherals | ||
| 11 | UDCON = 1; | ||
| 12 | USBCON = (1<<FRZCLK); // disable USB | ||
| 13 | UCSR1B = 0; | ||
| 14 | _delay_ms(5); | ||
| 15 | #if defined(__AVR_AT90USB162__) // Teensy 1.0 | ||
| 16 | EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; | ||
| 17 | TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0; | ||
| 18 | DDRB = 0; DDRC = 0; DDRD = 0; | ||
| 19 | PORTB = 0; PORTC = 0; PORTD = 0; | ||
| 20 | asm volatile("jmp 0x3E00"); | ||
| 21 | #elif defined(__AVR_ATmega32U4__) // Teensy 2.0 | ||
| 22 | EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; | ||
| 23 | TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0; | ||
| 24 | DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0; | ||
| 25 | PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; | ||
| 26 | asm volatile("jmp 0x7E00"); | ||
| 27 | #elif defined(__AVR_AT90USB646__) // Teensy++ 1.0 | ||
| 28 | EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; | ||
| 29 | TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0; | ||
| 30 | DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; | ||
| 31 | PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; | ||
| 32 | asm volatile("jmp 0xFC00"); | ||
| 33 | #elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0 | ||
| 34 | EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0; | ||
| 35 | TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0; | ||
| 36 | DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; | ||
| 37 | PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0; | ||
| 38 | asm volatile("jmp 0x1FC00"); | ||
| 39 | #endif | ||
| 40 | } | ||
diff --git a/protocol/pjrc/main.c b/protocol/pjrc/main.c new file mode 100644 index 000000000..15f14920b --- /dev/null +++ b/protocol/pjrc/main.c | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | /* Keyboard example with debug channel, for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2008 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <stdbool.h> | ||
| 25 | #include <avr/io.h> | ||
| 26 | #include <avr/interrupt.h> | ||
| 27 | #include <util/delay.h> | ||
| 28 | #include "keyboard.h" | ||
| 29 | #include "usb.h" | ||
| 30 | #include "matrix.h" | ||
| 31 | #include "print.h" | ||
| 32 | #include "debug.h" | ||
| 33 | #include "util.h" | ||
| 34 | #include "bootloader.h" | ||
| 35 | #ifdef PS2_MOUSE_ENABLE | ||
| 36 | # include "ps2_mouse.h" | ||
| 37 | #endif | ||
| 38 | #include "host.h" | ||
| 39 | #include "pjrc.h" | ||
| 40 | |||
| 41 | |||
| 42 | #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) | ||
| 43 | |||
| 44 | |||
| 45 | bool debug_enable = false; | ||
| 46 | bool debug_matrix = false; | ||
| 47 | bool debug_keyboard = false; | ||
| 48 | bool debug_mouse = false; | ||
| 49 | |||
| 50 | |||
| 51 | int main(void) | ||
| 52 | { | ||
| 53 | DEBUG_LED_CONFIG; | ||
| 54 | DEBUG_LED_OFF; | ||
| 55 | |||
| 56 | // set for 16 MHz clock | ||
| 57 | CPU_PRESCALE(0); | ||
| 58 | |||
| 59 | // Initialize the USB, and then wait for the host to set configuration. | ||
| 60 | // If the Teensy is powered without a PC connected to the USB port, | ||
| 61 | // this will wait forever. | ||
| 62 | usb_init(); | ||
| 63 | while (!usb_configured()) /* wait */ ; | ||
| 64 | |||
| 65 | keyboard_init(); | ||
| 66 | matrix_scan(); | ||
| 67 | if (matrix_key_count() >= 3) { | ||
| 68 | #ifdef DEBUG_LED | ||
| 69 | for (int i = 0; i < 6; i++) { | ||
| 70 | DEBUG_LED_CONFIG; | ||
| 71 | DEBUG_LED_ON; | ||
| 72 | _delay_ms(500); | ||
| 73 | DEBUG_LED_OFF; | ||
| 74 | _delay_ms(500); | ||
| 75 | } | ||
| 76 | #else | ||
| 77 | _delay_ms(5000); | ||
| 78 | #endif | ||
| 79 | print_enable = true; | ||
| 80 | debug_enable = true; | ||
| 81 | debug_matrix = true; | ||
| 82 | debug_keyboard = true; | ||
| 83 | debug_mouse = true; | ||
| 84 | print("debug enabled.\n"); | ||
| 85 | } | ||
| 86 | if (matrix_key_count() >= 4) { | ||
| 87 | print("jump to bootloader...\n"); | ||
| 88 | _delay_ms(1000); | ||
| 89 | bootloader_jump(); // not return | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | host_set_driver(pjrc_driver()); | ||
| 94 | while (1) { | ||
| 95 | keyboard_proc(); | ||
| 96 | } | ||
| 97 | } | ||
diff --git a/protocol/pjrc/pjrc.c b/protocol/pjrc/pjrc.c new file mode 100644 index 000000000..0562a12ff --- /dev/null +++ b/protocol/pjrc/pjrc.c | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <stdint.h> | ||
| 19 | #include "usb_keyboard.h" | ||
| 20 | #include "usb_mouse.h" | ||
| 21 | #include "usb_extra.h" | ||
| 22 | #include "host_driver.h" | ||
| 23 | #include "pjrc.h" | ||
| 24 | |||
| 25 | |||
| 26 | /*------------------------------------------------------------------* | ||
| 27 | * Host driver | ||
| 28 | *------------------------------------------------------------------*/ | ||
| 29 | static uint8_t keyboard_leds(void); | ||
| 30 | static void send_keyboard(report_keyboard_t *report); | ||
| 31 | static void send_mouse(report_mouse_t *report); | ||
| 32 | static void send_system(uint16_t data); | ||
| 33 | static void send_consumer(uint16_t data); | ||
| 34 | |||
| 35 | static host_driver_t driver = { | ||
| 36 | keyboard_leds, | ||
| 37 | send_keyboard, | ||
| 38 | send_mouse, | ||
| 39 | send_system, | ||
| 40 | send_consumer | ||
| 41 | }; | ||
| 42 | |||
| 43 | host_driver_t *pjrc_driver(void) | ||
| 44 | { | ||
| 45 | return &driver; | ||
| 46 | } | ||
| 47 | |||
| 48 | static uint8_t keyboard_leds(void) { | ||
| 49 | return usb_keyboard_leds; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void send_keyboard(report_keyboard_t *report) | ||
| 53 | { | ||
| 54 | usb_keyboard_send_report(report); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void send_mouse(report_mouse_t *report) | ||
| 58 | { | ||
| 59 | #ifdef MOUSE_ENABLE | ||
| 60 | usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons); | ||
| 61 | #endif | ||
| 62 | } | ||
| 63 | |||
| 64 | static void send_system(uint16_t data) | ||
| 65 | { | ||
| 66 | #ifdef EXTRAKEY_ENABLE | ||
| 67 | usb_extra_system_send(data); | ||
| 68 | #endif | ||
| 69 | } | ||
| 70 | |||
| 71 | static void send_consumer(uint16_t data) | ||
| 72 | { | ||
| 73 | #ifdef EXTRAKEY_ENABLE | ||
| 74 | usb_extra_consumer_send(data); | ||
| 75 | #endif | ||
| 76 | } | ||
diff --git a/protocol/pjrc/pjrc.h b/protocol/pjrc/pjrc.h new file mode 100644 index 000000000..06e79626f --- /dev/null +++ b/protocol/pjrc/pjrc.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef PJRC_H | ||
| 19 | #define PJRC_H | ||
| 20 | |||
| 21 | #include "host_driver.h" | ||
| 22 | |||
| 23 | |||
| 24 | host_driver_t *pjrc_driver(void); | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/protocol/pjrc/usb.c b/protocol/pjrc/usb.c new file mode 100644 index 000000000..89087218f --- /dev/null +++ b/protocol/pjrc/usb.c | |||
| @@ -0,0 +1,962 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <stdint.h> | ||
| 25 | #include <stdbool.h> | ||
| 26 | #include <avr/io.h> | ||
| 27 | #include <avr/pgmspace.h> | ||
| 28 | #include <avr/interrupt.h> | ||
| 29 | #include "usb.h" | ||
| 30 | #include "usb_keyboard.h" | ||
| 31 | #include "usb_mouse.h" | ||
| 32 | #include "usb_debug.h" | ||
| 33 | #include "usb_extra.h" | ||
| 34 | #include "print.h" | ||
| 35 | #include "util.h" | ||
| 36 | |||
| 37 | |||
| 38 | /************************************************************************** | ||
| 39 | * | ||
| 40 | * Configurable Options | ||
| 41 | * | ||
| 42 | **************************************************************************/ | ||
| 43 | |||
| 44 | // You can change these to give your code its own name. | ||
| 45 | #ifndef MANUFACTURER | ||
| 46 | # define STR_MANUFACTURER L"t.m.k." | ||
| 47 | #else | ||
| 48 | # define STR_MANUFACTURER LSTR(MANUFACTURER) | ||
| 49 | #endif | ||
| 50 | #ifndef PRODUCT | ||
| 51 | # define STR_PRODUCT L"t.m.k. keyboard" | ||
| 52 | #else | ||
| 53 | # define STR_PRODUCT LSTR(PRODUCT) | ||
| 54 | #endif | ||
| 55 | |||
| 56 | |||
| 57 | // Mac OS-X and Linux automatically load the correct drivers. On | ||
| 58 | // Windows, even though the driver is supplied by Microsoft, an | ||
| 59 | // INF file is needed to load the driver. These numbers need to | ||
| 60 | // match the INF file. | ||
| 61 | #ifndef VENDOR_ID | ||
| 62 | # define VENDOR_ID 0xFEED | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #ifndef PRODUCT_ID | ||
| 66 | # define PRODUCT_ID 0xBABE | ||
| 67 | #endif | ||
| 68 | |||
| 69 | #ifndef DEVICE_VER | ||
| 70 | # define DEVICE_VER 0x0100 | ||
| 71 | #endif | ||
| 72 | |||
| 73 | |||
| 74 | // USB devices are supposed to implment a halt feature, which is | ||
| 75 | // rarely (if ever) used. If you comment this line out, the halt | ||
| 76 | // code will be removed, saving 102 bytes of space (gcc 4.3.0). | ||
| 77 | // This is not strictly USB compliant, but works with all major | ||
| 78 | // operating systems. | ||
| 79 | #define SUPPORT_ENDPOINT_HALT | ||
| 80 | |||
| 81 | |||
| 82 | |||
| 83 | /************************************************************************** | ||
| 84 | * | ||
| 85 | * Endpoint Buffer Configuration | ||
| 86 | * | ||
| 87 | **************************************************************************/ | ||
| 88 | |||
| 89 | #define ENDPOINT0_SIZE 32 | ||
| 90 | |||
| 91 | bool remote_wakeup = false; | ||
| 92 | bool suspend = false; | ||
| 93 | |||
| 94 | // 0:control endpoint is enabled automatically by controller. | ||
| 95 | static const uint8_t PROGMEM endpoint_config_table[] = { | ||
| 96 | // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) | ||
| 97 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1 | ||
| 98 | #ifdef MOUSE_ENABLE | ||
| 99 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 | ||
| 100 | #else | ||
| 101 | 0, // 2 | ||
| 102 | #endif | ||
| 103 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 | ||
| 104 | #ifdef EXTRAKEY_ENABLE | ||
| 105 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 | ||
| 106 | #else | ||
| 107 | 0, // 4 | ||
| 108 | #endif | ||
| 109 | #ifdef NKRO_ENABLE | ||
| 110 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5 | ||
| 111 | #else | ||
| 112 | 0, // 5 | ||
| 113 | #endif | ||
| 114 | 0, // 6 | ||
| 115 | }; | ||
| 116 | |||
| 117 | |||
| 118 | /************************************************************************** | ||
| 119 | * | ||
| 120 | * Descriptor Data | ||
| 121 | * | ||
| 122 | **************************************************************************/ | ||
| 123 | |||
| 124 | // Descriptors are the data that your computer reads when it auto-detects | ||
| 125 | // this USB device (called "enumeration" in USB lingo). The most commonly | ||
| 126 | // changed items are editable at the top of this file. Changing things | ||
| 127 | // in here should only be done by those who've read chapter 9 of the USB | ||
| 128 | // spec and relevant portions of any USB class specifications! | ||
| 129 | |||
| 130 | |||
| 131 | static uint8_t PROGMEM device_descriptor[] = { | ||
| 132 | 18, // bLength | ||
| 133 | 1, // bDescriptorType | ||
| 134 | 0x00, 0x02, // bcdUSB | ||
| 135 | 0, // bDeviceClass | ||
| 136 | 0, // bDeviceSubClass | ||
| 137 | 0, // bDeviceProtocol | ||
| 138 | ENDPOINT0_SIZE, // bMaxPacketSize0 | ||
| 139 | LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | ||
| 140 | LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | ||
| 141 | LSB(DEVICE_VER), MSB(DEVICE_VER), // bcdDevice | ||
| 142 | 1, // iManufacturer | ||
| 143 | 2, // iProduct | ||
| 144 | 0, // iSerialNumber | ||
| 145 | 1 // bNumConfigurations | ||
| 146 | }; | ||
| 147 | |||
| 148 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||
| 149 | static uint8_t PROGMEM keyboard_hid_report_desc[] = { | ||
| 150 | 0x05, 0x01, // Usage Page (Generic Desktop), | ||
| 151 | 0x09, 0x06, // Usage (Keyboard), | ||
| 152 | 0xA1, 0x01, // Collection (Application), | ||
| 153 | 0x75, 0x01, // Report Size (1), | ||
| 154 | 0x95, 0x08, // Report Count (8), | ||
| 155 | 0x05, 0x07, // Usage Page (Key Codes), | ||
| 156 | 0x19, 0xE0, // Usage Minimum (224), | ||
| 157 | 0x29, 0xE7, // Usage Maximum (231), | ||
| 158 | 0x15, 0x00, // Logical Minimum (0), | ||
| 159 | 0x25, 0x01, // Logical Maximum (1), | ||
| 160 | 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | ||
| 161 | 0x95, 0x01, // Report Count (1), | ||
| 162 | 0x75, 0x08, // Report Size (8), | ||
| 163 | 0x81, 0x03, // Input (Constant), ;Reserved byte | ||
| 164 | 0x95, 0x05, // Report Count (5), | ||
| 165 | 0x75, 0x01, // Report Size (1), | ||
| 166 | 0x05, 0x08, // Usage Page (LEDs), | ||
| 167 | 0x19, 0x01, // Usage Minimum (1), | ||
| 168 | 0x29, 0x05, // Usage Maximum (5), | ||
| 169 | 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report | ||
| 170 | 0x95, 0x01, // Report Count (1), | ||
| 171 | 0x75, 0x03, // Report Size (3), | ||
| 172 | 0x91, 0x03, // Output (Constant), ;LED report padding | ||
| 173 | 0x95, KBD_REPORT_KEYS, // Report Count (), | ||
| 174 | 0x75, 0x08, // Report Size (8), | ||
| 175 | 0x15, 0x00, // Logical Minimum (0), | ||
| 176 | 0x25, 0xFF, // Logical Maximum(255), | ||
| 177 | 0x05, 0x07, // Usage Page (Key Codes), | ||
| 178 | 0x19, 0x00, // Usage Minimum (0), | ||
| 179 | 0x29, 0xFF, // Usage Maximum (255), | ||
| 180 | 0x81, 0x00, // Input (Data, Array), | ||
| 181 | 0xc0 // End Collection | ||
| 182 | }; | ||
| 183 | #ifdef NKRO_ENABLE | ||
| 184 | static uint8_t PROGMEM keyboard2_hid_report_desc[] = { | ||
| 185 | 0x05, 0x01, // Usage Page (Generic Desktop), | ||
| 186 | 0x09, 0x06, // Usage (Keyboard), | ||
| 187 | 0xA1, 0x01, // Collection (Application), | ||
| 188 | // bitmap of modifiers | ||
| 189 | 0x75, 0x01, // Report Size (1), | ||
| 190 | 0x95, 0x08, // Report Count (8), | ||
| 191 | 0x05, 0x07, // Usage Page (Key Codes), | ||
| 192 | 0x19, 0xE0, // Usage Minimum (224), | ||
| 193 | 0x29, 0xE7, // Usage Maximum (231), | ||
| 194 | 0x15, 0x00, // Logical Minimum (0), | ||
| 195 | 0x25, 0x01, // Logical Maximum (1), | ||
| 196 | 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | ||
| 197 | // LED output report | ||
| 198 | 0x95, 0x05, // Report Count (5), | ||
| 199 | 0x75, 0x01, // Report Size (1), | ||
| 200 | 0x05, 0x08, // Usage Page (LEDs), | ||
| 201 | 0x19, 0x01, // Usage Minimum (1), | ||
| 202 | 0x29, 0x05, // Usage Maximum (5), | ||
| 203 | 0x91, 0x02, // Output (Data, Variable, Absolute), | ||
| 204 | 0x95, 0x01, // Report Count (1), | ||
| 205 | 0x75, 0x03, // Report Size (3), | ||
| 206 | 0x91, 0x03, // Output (Constant), | ||
| 207 | // bitmap of keys | ||
| 208 | 0x95, KBD2_REPORT_KEYS*8, // Report Count (), | ||
| 209 | 0x75, 0x01, // Report Size (1), | ||
| 210 | 0x15, 0x00, // Logical Minimum (0), | ||
| 211 | 0x25, 0x01, // Logical Maximum(1), | ||
| 212 | 0x05, 0x07, // Usage Page (Key Codes), | ||
| 213 | 0x19, 0x00, // Usage Minimum (0), | ||
| 214 | 0x29, KBD2_REPORT_KEYS*8-1, // Usage Maximum (), | ||
| 215 | 0x81, 0x02, // Input (Data, Variable, Absolute), | ||
| 216 | 0xc0 // End Collection | ||
| 217 | }; | ||
| 218 | #endif | ||
| 219 | |||
| 220 | #ifdef MOUSE_ENABLE | ||
| 221 | // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension | ||
| 222 | // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 | ||
| 223 | // http://www.keil.com/forum/15671/ | ||
| 224 | // http://www.microsoft.com/whdc/device/input/wheel.mspx | ||
| 225 | static uint8_t PROGMEM mouse_hid_report_desc[] = { | ||
| 226 | /* mouse */ | ||
| 227 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) | ||
| 228 | 0x09, 0x02, // USAGE (Mouse) | ||
| 229 | 0xa1, 0x01, // COLLECTION (Application) | ||
| 230 | //0x85, REPORT_ID_MOUSE, // REPORT_ID (1) | ||
| 231 | 0x09, 0x01, // USAGE (Pointer) | ||
| 232 | 0xa1, 0x00, // COLLECTION (Physical) | ||
| 233 | // ---------------------------- Buttons | ||
| 234 | 0x05, 0x09, // USAGE_PAGE (Button) | ||
| 235 | 0x19, 0x01, // USAGE_MINIMUM (Button 1) | ||
| 236 | 0x29, 0x05, // USAGE_MAXIMUM (Button 5) | ||
| 237 | 0x15, 0x00, // LOGICAL_MINIMUM (0) | ||
| 238 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) | ||
| 239 | 0x75, 0x01, // REPORT_SIZE (1) | ||
| 240 | 0x95, 0x05, // REPORT_COUNT (5) | ||
| 241 | 0x81, 0x02, // INPUT (Data,Var,Abs) | ||
| 242 | 0x75, 0x03, // REPORT_SIZE (3) | ||
| 243 | 0x95, 0x01, // REPORT_COUNT (1) | ||
| 244 | 0x81, 0x03, // INPUT (Cnst,Var,Abs) | ||
| 245 | // ---------------------------- X,Y position | ||
| 246 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) | ||
| 247 | 0x09, 0x30, // USAGE (X) | ||
| 248 | 0x09, 0x31, // USAGE (Y) | ||
| 249 | 0x15, 0x81, // LOGICAL_MINIMUM (-127) | ||
| 250 | 0x25, 0x7f, // LOGICAL_MAXIMUM (127) | ||
| 251 | 0x75, 0x08, // REPORT_SIZE (8) | ||
| 252 | 0x95, 0x02, // REPORT_COUNT (2) | ||
| 253 | 0x81, 0x06, // INPUT (Data,Var,Rel) | ||
| 254 | // ---------------------------- Vertical wheel | ||
| 255 | 0x09, 0x38, // USAGE (Wheel) | ||
| 256 | 0x15, 0x81, // LOGICAL_MINIMUM (-127) | ||
| 257 | 0x25, 0x7f, // LOGICAL_MAXIMUM (127) | ||
| 258 | 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical | ||
| 259 | 0x45, 0x00, // PHYSICAL_MAXIMUM (0) | ||
| 260 | 0x75, 0x08, // REPORT_SIZE (8) | ||
| 261 | 0x95, 0x01, // REPORT_COUNT (1) | ||
| 262 | 0x81, 0x06, // INPUT (Data,Var,Rel) | ||
| 263 | // ---------------------------- Horizontal wheel | ||
| 264 | 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) | ||
| 265 | 0x0a, 0x38, 0x02, // USAGE (AC Pan) | ||
| 266 | 0x15, 0x81, // LOGICAL_MINIMUM (-127) | ||
| 267 | 0x25, 0x7f, // LOGICAL_MAXIMUM (127) | ||
| 268 | 0x75, 0x08, // REPORT_SIZE (8) | ||
| 269 | 0x95, 0x01, // REPORT_COUNT (1) | ||
| 270 | 0x81, 0x06, // INPUT (Data,Var,Rel) | ||
| 271 | 0xc0, // END_COLLECTION | ||
| 272 | 0xc0, // END_COLLECTION | ||
| 273 | }; | ||
| 274 | #endif | ||
| 275 | |||
| 276 | static uint8_t PROGMEM debug_hid_report_desc[] = { | ||
| 277 | 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) | ||
| 278 | 0x09, 0x74, // Usage 0x74 | ||
| 279 | 0xA1, 0x53, // Collection 0x53 | ||
| 280 | 0x75, 0x08, // report size = 8 bits | ||
| 281 | 0x15, 0x00, // logical minimum = 0 | ||
| 282 | 0x26, 0xFF, 0x00, // logical maximum = 255 | ||
| 283 | 0x95, DEBUG_TX_SIZE, // report count | ||
| 284 | 0x09, 0x75, // usage | ||
| 285 | 0x81, 0x02, // Input (array) | ||
| 286 | 0xC0 // end collection | ||
| 287 | }; | ||
| 288 | |||
| 289 | #ifdef EXTRAKEY_ENABLE | ||
| 290 | // audio controls & system controls | ||
| 291 | // http://www.microsoft.com/whdc/archive/w2kbd.mspx | ||
| 292 | static uint8_t PROGMEM extra_hid_report_desc[] = { | ||
| 293 | /* system control */ | ||
| 294 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) | ||
| 295 | 0x09, 0x80, // USAGE (System Control) | ||
| 296 | 0xa1, 0x01, // COLLECTION (Application) | ||
| 297 | 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2) | ||
| 298 | 0x15, 0x01, // LOGICAL_MINIMUM (0x1) | ||
| 299 | 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7) | ||
| 300 | 0x19, 0x01, // USAGE_MINIMUM (0x1) | ||
| 301 | 0x29, 0xb7, // USAGE_MAXIMUM (0xb7) | ||
| 302 | 0x75, 0x10, // REPORT_SIZE (16) | ||
| 303 | 0x95, 0x01, // REPORT_COUNT (1) | ||
| 304 | 0x81, 0x00, // INPUT (Data,Array,Abs) | ||
| 305 | 0xc0, // END_COLLECTION | ||
| 306 | /* consumer */ | ||
| 307 | 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) | ||
| 308 | 0x09, 0x01, // USAGE (Consumer Control) | ||
| 309 | 0xa1, 0x01, // COLLECTION (Application) | ||
| 310 | 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3) | ||
| 311 | 0x15, 0x01, // LOGICAL_MINIMUM (0x1) | ||
| 312 | 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c) | ||
| 313 | 0x19, 0x01, // USAGE_MINIMUM (0x1) | ||
| 314 | 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c) | ||
| 315 | 0x75, 0x10, // REPORT_SIZE (16) | ||
| 316 | 0x95, 0x01, // REPORT_COUNT (1) | ||
| 317 | 0x81, 0x00, // INPUT (Data,Array,Abs) | ||
| 318 | 0xc0, // END_COLLECTION | ||
| 319 | }; | ||
| 320 | #endif | ||
| 321 | |||
| 322 | #define KBD_HID_DESC_NUM 0 | ||
| 323 | #define KBD_HID_DESC_OFFSET (9+(9+9+7)*KBD_HID_DESC_NUM+9) | ||
| 324 | |||
| 325 | #ifdef MOUSE_ENABLE | ||
| 326 | # define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1) | ||
| 327 | # define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*MOUSE_HID_DESC_NUM+9) | ||
| 328 | #else | ||
| 329 | # define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0) | ||
| 330 | #endif | ||
| 331 | |||
| 332 | #define DEBUG_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1) | ||
| 333 | #define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*DEBUG_HID_DESC_NUM+9) | ||
| 334 | |||
| 335 | #ifdef EXTRAKEY_ENABLE | ||
| 336 | # define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 1) | ||
| 337 | # define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9) | ||
| 338 | #else | ||
| 339 | # define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 0) | ||
| 340 | #endif | ||
| 341 | |||
| 342 | #ifdef NKRO_ENABLE | ||
| 343 | # define KBD2_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1) | ||
| 344 | # define KBD2_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9) | ||
| 345 | #else | ||
| 346 | # define KBD2_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0) | ||
| 347 | #endif | ||
| 348 | |||
| 349 | #define NUM_INTERFACES (KBD2_HID_DESC_NUM + 1) | ||
| 350 | #define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES) | ||
| 351 | static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | ||
| 352 | // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | ||
| 353 | 9, // bLength; | ||
| 354 | 2, // bDescriptorType; | ||
| 355 | LSB(CONFIG1_DESC_SIZE), // wTotalLength | ||
| 356 | MSB(CONFIG1_DESC_SIZE), | ||
| 357 | NUM_INTERFACES, // bNumInterfaces | ||
| 358 | 1, // bConfigurationValue | ||
| 359 | 0, // iConfiguration | ||
| 360 | 0xA0, // bmAttributes | ||
| 361 | 50, // bMaxPower | ||
| 362 | |||
| 363 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||
| 364 | 9, // bLength | ||
| 365 | 4, // bDescriptorType | ||
| 366 | KBD_INTERFACE, // bInterfaceNumber | ||
| 367 | 0, // bAlternateSetting | ||
| 368 | 1, // bNumEndpoints | ||
| 369 | 0x03, // bInterfaceClass (0x03 = HID) | ||
| 370 | 0x01, // bInterfaceSubClass (0x01 = Boot) | ||
| 371 | 0x01, // bInterfaceProtocol (0x01 = Keyboard) | ||
| 372 | 0, // iInterface | ||
| 373 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||
| 374 | 9, // bLength | ||
| 375 | 0x21, // bDescriptorType | ||
| 376 | 0x11, 0x01, // bcdHID | ||
| 377 | 0, // bCountryCode | ||
| 378 | 1, // bNumDescriptors | ||
| 379 | 0x22, // bDescriptorType | ||
| 380 | sizeof(keyboard_hid_report_desc), // wDescriptorLength | ||
| 381 | 0, | ||
| 382 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||
| 383 | 7, // bLength | ||
| 384 | 5, // bDescriptorType | ||
| 385 | KBD_ENDPOINT | 0x80, // bEndpointAddress | ||
| 386 | 0x03, // bmAttributes (0x03=intr) | ||
| 387 | KBD_SIZE, 0, // wMaxPacketSize | ||
| 388 | 10, // bInterval | ||
| 389 | |||
| 390 | #ifdef MOUSE_ENABLE | ||
| 391 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||
| 392 | 9, // bLength | ||
| 393 | 4, // bDescriptorType | ||
| 394 | MOUSE_INTERFACE, // bInterfaceNumber | ||
| 395 | 0, // bAlternateSetting | ||
| 396 | 1, // bNumEndpoints | ||
| 397 | 0x03, // bInterfaceClass (0x03 = HID) | ||
| 398 | // ThinkPad T23 BIOS doesn't work with boot mouse. | ||
| 399 | 0x00, // bInterfaceSubClass (0x01 = Boot) | ||
| 400 | 0x00, // bInterfaceProtocol (0x02 = Mouse) | ||
| 401 | /* | ||
| 402 | 0x01, // bInterfaceSubClass (0x01 = Boot) | ||
| 403 | 0x02, // bInterfaceProtocol (0x02 = Mouse) | ||
| 404 | */ | ||
| 405 | 0, // iInterface | ||
| 406 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||
| 407 | 9, // bLength | ||
| 408 | 0x21, // bDescriptorType | ||
| 409 | 0x11, 0x01, // bcdHID | ||
| 410 | 0, // bCountryCode | ||
| 411 | 1, // bNumDescriptors | ||
| 412 | 0x22, // bDescriptorType | ||
| 413 | sizeof(mouse_hid_report_desc), // wDescriptorLength | ||
| 414 | 0, | ||
| 415 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||
| 416 | 7, // bLength | ||
| 417 | 5, // bDescriptorType | ||
| 418 | MOUSE_ENDPOINT | 0x80, // bEndpointAddress | ||
| 419 | 0x03, // bmAttributes (0x03=intr) | ||
| 420 | MOUSE_SIZE, 0, // wMaxPacketSize | ||
| 421 | 1, // bInterval | ||
| 422 | #endif | ||
| 423 | |||
| 424 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||
| 425 | 9, // bLength | ||
| 426 | 4, // bDescriptorType | ||
| 427 | DEBUG_INTERFACE, // bInterfaceNumber | ||
| 428 | 0, // bAlternateSetting | ||
| 429 | 1, // bNumEndpoints | ||
| 430 | 0x03, // bInterfaceClass (0x03 = HID) | ||
| 431 | 0x00, // bInterfaceSubClass | ||
| 432 | 0x00, // bInterfaceProtocol | ||
| 433 | 0, // iInterface | ||
| 434 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||
| 435 | 9, // bLength | ||
| 436 | 0x21, // bDescriptorType | ||
| 437 | 0x11, 0x01, // bcdHID | ||
| 438 | 0, // bCountryCode | ||
| 439 | 1, // bNumDescriptors | ||
| 440 | 0x22, // bDescriptorType | ||
| 441 | sizeof(debug_hid_report_desc), // wDescriptorLength | ||
| 442 | 0, | ||
| 443 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||
| 444 | 7, // bLength | ||
| 445 | 5, // bDescriptorType | ||
| 446 | DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress | ||
| 447 | 0x03, // bmAttributes (0x03=intr) | ||
| 448 | DEBUG_TX_SIZE, 0, // wMaxPacketSize | ||
| 449 | 1, // bInterval | ||
| 450 | |||
| 451 | #ifdef EXTRAKEY_ENABLE | ||
| 452 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||
| 453 | 9, // bLength | ||
| 454 | 4, // bDescriptorType | ||
| 455 | EXTRA_INTERFACE, // bInterfaceNumber | ||
| 456 | 0, // bAlternateSetting | ||
| 457 | 1, // bNumEndpoints | ||
| 458 | 0x03, // bInterfaceClass (0x03 = HID) | ||
| 459 | 0x00, // bInterfaceSubClass | ||
| 460 | 0x00, // bInterfaceProtocol | ||
| 461 | 0, // iInterface | ||
| 462 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||
| 463 | 9, // bLength | ||
| 464 | 0x21, // bDescriptorType | ||
| 465 | 0x11, 0x01, // bcdHID | ||
| 466 | 0, // bCountryCode | ||
| 467 | 1, // bNumDescriptors | ||
| 468 | 0x22, // bDescriptorType | ||
| 469 | sizeof(extra_hid_report_desc), // wDescriptorLength | ||
| 470 | 0, | ||
| 471 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||
| 472 | 7, // bLength | ||
| 473 | 5, // bDescriptorType | ||
| 474 | EXTRA_ENDPOINT | 0x80, // bEndpointAddress | ||
| 475 | 0x03, // bmAttributes (0x03=intr) | ||
| 476 | EXTRA_SIZE, 0, // wMaxPacketSize | ||
| 477 | 10, // bInterval | ||
| 478 | #endif | ||
| 479 | |||
| 480 | #ifdef NKRO_ENABLE | ||
| 481 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||
| 482 | 9, // bLength | ||
| 483 | 4, // bDescriptorType | ||
| 484 | KBD2_INTERFACE, // bInterfaceNumber | ||
| 485 | 0, // bAlternateSetting | ||
| 486 | 1, // bNumEndpoints | ||
| 487 | 0x03, // bInterfaceClass (0x03 = HID) | ||
| 488 | 0x00, // bInterfaceSubClass (0x01 = Boot) | ||
| 489 | 0x00, // bInterfaceProtocol (0x01 = Keyboard) | ||
| 490 | 0, // iInterface | ||
| 491 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||
| 492 | 9, // bLength | ||
| 493 | 0x21, // bDescriptorType | ||
| 494 | 0x11, 0x01, // bcdHID | ||
| 495 | 0, // bCountryCode | ||
| 496 | 1, // bNumDescriptors | ||
| 497 | 0x22, // bDescriptorType | ||
| 498 | sizeof(keyboard2_hid_report_desc), // wDescriptorLength | ||
| 499 | 0, | ||
| 500 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||
| 501 | 7, // bLength | ||
| 502 | 5, // bDescriptorType | ||
| 503 | KBD2_ENDPOINT | 0x80, // bEndpointAddress | ||
| 504 | 0x03, // bmAttributes (0x03=intr) | ||
| 505 | KBD2_SIZE, 0, // wMaxPacketSize | ||
| 506 | 1, // bInterval | ||
| 507 | #endif | ||
| 508 | }; | ||
| 509 | |||
| 510 | // If you're desperate for a little extra code memory, these strings | ||
| 511 | // can be completely removed if iManufacturer, iProduct, iSerialNumber | ||
| 512 | // in the device desciptor are changed to zeros. | ||
| 513 | struct usb_string_descriptor_struct { | ||
| 514 | uint8_t bLength; | ||
| 515 | uint8_t bDescriptorType; | ||
| 516 | int16_t wString[]; | ||
| 517 | }; | ||
| 518 | static struct usb_string_descriptor_struct PROGMEM string0 = { | ||
| 519 | 4, | ||
| 520 | 3, | ||
| 521 | {0x0409} | ||
| 522 | }; | ||
| 523 | static struct usb_string_descriptor_struct PROGMEM string1 = { | ||
| 524 | sizeof(STR_MANUFACTURER), | ||
| 525 | 3, | ||
| 526 | STR_MANUFACTURER | ||
| 527 | }; | ||
| 528 | static struct usb_string_descriptor_struct PROGMEM string2 = { | ||
| 529 | sizeof(STR_PRODUCT), | ||
| 530 | 3, | ||
| 531 | STR_PRODUCT | ||
| 532 | }; | ||
| 533 | |||
| 534 | // This table defines which descriptor data is sent for each specific | ||
| 535 | // request from the host (in wValue and wIndex). | ||
| 536 | static struct descriptor_list_struct { | ||
| 537 | uint16_t wValue; // descriptor type | ||
| 538 | uint16_t wIndex; | ||
| 539 | const uint8_t *addr; | ||
| 540 | uint8_t length; | ||
| 541 | } PROGMEM descriptor_list[] = { | ||
| 542 | // DEVICE descriptor | ||
| 543 | {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | ||
| 544 | // CONFIGURATION descriptor | ||
| 545 | {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, | ||
| 546 | // HID/REPORT descriptors | ||
| 547 | {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9}, | ||
| 548 | {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, | ||
| 549 | #ifdef MOUSE_ENABLE | ||
| 550 | {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, | ||
| 551 | {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, | ||
| 552 | #endif | ||
| 553 | {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, | ||
| 554 | {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, | ||
| 555 | #ifdef EXTRAKEY_ENABLE | ||
| 556 | {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9}, | ||
| 557 | {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)}, | ||
| 558 | #endif | ||
| 559 | #ifdef NKRO_ENABLE | ||
| 560 | {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9}, | ||
| 561 | {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)}, | ||
| 562 | #endif | ||
| 563 | // STRING descriptors | ||
| 564 | {0x0300, 0x0000, (const uint8_t *)&string0, 4}, | ||
| 565 | {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, | ||
| 566 | {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)} | ||
| 567 | }; | ||
| 568 | #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) | ||
| 569 | |||
| 570 | |||
| 571 | /************************************************************************** | ||
| 572 | * | ||
| 573 | * Variables - these are the only non-stack RAM usage | ||
| 574 | * | ||
| 575 | **************************************************************************/ | ||
| 576 | |||
| 577 | // zero when we are not configured, non-zero when enumerated | ||
| 578 | static volatile uint8_t usb_configuration=0; | ||
| 579 | |||
| 580 | |||
| 581 | /************************************************************************** | ||
| 582 | * | ||
| 583 | * Public Functions - these are the API intended for the user | ||
| 584 | * | ||
| 585 | **************************************************************************/ | ||
| 586 | |||
| 587 | |||
| 588 | // initialize USB | ||
| 589 | void usb_init(void) | ||
| 590 | { | ||
| 591 | HW_CONFIG(); | ||
| 592 | USB_FREEZE(); // enable USB | ||
| 593 | PLL_CONFIG(); // config PLL | ||
| 594 | while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock | ||
| 595 | USB_CONFIG(); // start USB clock | ||
| 596 | UDCON = 0; // enable attach resistor | ||
| 597 | usb_configuration = 0; | ||
| 598 | UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE); | ||
| 599 | sei(); | ||
| 600 | } | ||
| 601 | |||
| 602 | // return 0 if the USB is not configured, or the configuration | ||
| 603 | // number selected by the HOST | ||
| 604 | uint8_t usb_configured(void) | ||
| 605 | { | ||
| 606 | return usb_configuration && !suspend; | ||
| 607 | } | ||
| 608 | |||
| 609 | void usb_remote_wakeup(void) | ||
| 610 | { | ||
| 611 | UDCON |= (1<<RMWKUP); | ||
| 612 | } | ||
| 613 | |||
| 614 | |||
| 615 | |||
| 616 | /************************************************************************** | ||
| 617 | * | ||
| 618 | * Private Functions - not intended for general user consumption.... | ||
| 619 | * | ||
| 620 | **************************************************************************/ | ||
| 621 | |||
| 622 | |||
| 623 | |||
| 624 | // USB Device Interrupt - handle all device-level events | ||
| 625 | // the transmit buffer flushing is triggered by the start of frame | ||
| 626 | // | ||
| 627 | ISR(USB_GEN_vect) | ||
| 628 | { | ||
| 629 | uint8_t intbits, t; | ||
| 630 | static uint8_t div4=0; | ||
| 631 | |||
| 632 | intbits = UDINT; | ||
| 633 | UDINT = 0; | ||
| 634 | if (intbits & (1<<SUSPI)) { | ||
| 635 | suspend = true; | ||
| 636 | } else { | ||
| 637 | suspend = false; | ||
| 638 | } | ||
| 639 | if (intbits & (1<<EORSTI)) { | ||
| 640 | UENUM = 0; | ||
| 641 | UECONX = 1; | ||
| 642 | UECFG0X = EP_TYPE_CONTROL; | ||
| 643 | UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER; | ||
| 644 | UEIENX = (1<<RXSTPE); | ||
| 645 | usb_configuration = 0; | ||
| 646 | } | ||
| 647 | if ((intbits & (1<<SOFI)) && usb_configuration) { | ||
| 648 | t = debug_flush_timer; | ||
| 649 | if (t) { | ||
| 650 | debug_flush_timer = -- t; | ||
| 651 | if (!t) { | ||
| 652 | UENUM = DEBUG_TX_ENDPOINT; | ||
| 653 | while ((UEINTX & (1<<RWAL))) { | ||
| 654 | UEDATX = 0; | ||
| 655 | } | ||
| 656 | UEINTX = 0x3A; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | /* TODO: should keep IDLE rate on each keyboard interface */ | ||
| 660 | #ifdef NKRO_ENABLE | ||
| 661 | if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) { | ||
| 662 | #else | ||
| 663 | if (usb_keyboard_idle_config && (++div4 & 3) == 0) { | ||
| 664 | #endif | ||
| 665 | UENUM = KBD_ENDPOINT; | ||
| 666 | if (UEINTX & (1<<RWAL)) { | ||
| 667 | usb_keyboard_idle_count++; | ||
| 668 | if (usb_keyboard_idle_count == usb_keyboard_idle_config) { | ||
| 669 | usb_keyboard_idle_count = 0; | ||
| 670 | /* TODO: fix keyboard_report inconsistency */ | ||
| 671 | /* To avoid Mac SET_IDLE behaviour. | ||
| 672 | UEDATX = keyboard_report_prev->mods; | ||
| 673 | UEDATX = 0; | ||
| 674 | uint8_t keys = usb_keyboard_protocol ? KBD_REPORT_KEYS : 6; | ||
| 675 | for (uint8_t i=0; i<keys; i++) { | ||
| 676 | UEDATX = keyboard_report_prev->keys[i]; | ||
| 677 | } | ||
| 678 | UEINTX = 0x3A; | ||
| 679 | */ | ||
| 680 | } | ||
| 681 | } | ||
| 682 | } | ||
| 683 | } | ||
| 684 | } | ||
| 685 | |||
| 686 | |||
| 687 | |||
| 688 | // Misc functions to wait for ready and send/receive packets | ||
| 689 | static inline void usb_wait_in_ready(void) | ||
| 690 | { | ||
| 691 | while (!(UEINTX & (1<<TXINI))) ; | ||
| 692 | } | ||
| 693 | static inline void usb_send_in(void) | ||
| 694 | { | ||
| 695 | UEINTX = ~(1<<TXINI); | ||
| 696 | } | ||
| 697 | static inline void usb_wait_receive_out(void) | ||
| 698 | { | ||
| 699 | while (!(UEINTX & (1<<RXOUTI))) ; | ||
| 700 | } | ||
| 701 | static inline void usb_ack_out(void) | ||
| 702 | { | ||
| 703 | UEINTX = ~(1<<RXOUTI); | ||
| 704 | } | ||
| 705 | |||
| 706 | |||
| 707 | |||
| 708 | // USB Endpoint Interrupt - endpoint 0 is handled here. The | ||
| 709 | // other endpoints are manipulated by the user-callable | ||
| 710 | // functions, and the start-of-frame interrupt. | ||
| 711 | // | ||
| 712 | ISR(USB_COM_vect) | ||
| 713 | { | ||
| 714 | uint8_t intbits; | ||
| 715 | const uint8_t *list; | ||
| 716 | const uint8_t *cfg; | ||
| 717 | uint8_t i, n, len, en; | ||
| 718 | uint8_t bmRequestType; | ||
| 719 | uint8_t bRequest; | ||
| 720 | uint16_t wValue; | ||
| 721 | uint16_t wIndex; | ||
| 722 | uint16_t wLength; | ||
| 723 | uint16_t desc_val; | ||
| 724 | const uint8_t *desc_addr; | ||
| 725 | uint8_t desc_length; | ||
| 726 | |||
| 727 | UENUM = 0; | ||
| 728 | intbits = UEINTX; | ||
| 729 | if (intbits & (1<<RXSTPI)) { | ||
| 730 | bmRequestType = UEDATX; | ||
| 731 | bRequest = UEDATX; | ||
| 732 | wValue = UEDATX; | ||
| 733 | wValue |= (UEDATX << 8); | ||
| 734 | wIndex = UEDATX; | ||
| 735 | wIndex |= (UEDATX << 8); | ||
| 736 | wLength = UEDATX; | ||
| 737 | wLength |= (UEDATX << 8); | ||
| 738 | UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); | ||
| 739 | if (bRequest == GET_DESCRIPTOR) { | ||
| 740 | list = (const uint8_t *)descriptor_list; | ||
| 741 | for (i=0; ; i++) { | ||
| 742 | if (i >= NUM_DESC_LIST) { | ||
| 743 | UECONX = (1<<STALLRQ)|(1<<EPEN); //stall | ||
| 744 | return; | ||
| 745 | } | ||
| 746 | desc_val = pgm_read_word(list); | ||
| 747 | if (desc_val != wValue) { | ||
| 748 | list += sizeof(struct descriptor_list_struct); | ||
| 749 | continue; | ||
| 750 | } | ||
| 751 | list += 2; | ||
| 752 | desc_val = pgm_read_word(list); | ||
| 753 | if (desc_val != wIndex) { | ||
| 754 | list += sizeof(struct descriptor_list_struct)-2; | ||
| 755 | continue; | ||
| 756 | } | ||
| 757 | list += 2; | ||
| 758 | desc_addr = (const uint8_t *)pgm_read_word(list); | ||
| 759 | list += 2; | ||
| 760 | desc_length = pgm_read_byte(list); | ||
| 761 | break; | ||
| 762 | } | ||
| 763 | len = (wLength < 256) ? wLength : 255; | ||
| 764 | if (len > desc_length) len = desc_length; | ||
| 765 | do { | ||
| 766 | // wait for host ready for IN packet | ||
| 767 | do { | ||
| 768 | i = UEINTX; | ||
| 769 | } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); | ||
| 770 | if (i & (1<<RXOUTI)) return; // abort | ||
| 771 | // send IN packet | ||
| 772 | n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; | ||
| 773 | for (i = n; i; i--) { | ||
| 774 | UEDATX = pgm_read_byte(desc_addr++); | ||
| 775 | } | ||
| 776 | len -= n; | ||
| 777 | usb_send_in(); | ||
| 778 | } while (len || n == ENDPOINT0_SIZE); | ||
| 779 | return; | ||
| 780 | } | ||
| 781 | if (bRequest == SET_ADDRESS) { | ||
| 782 | usb_send_in(); | ||
| 783 | usb_wait_in_ready(); | ||
| 784 | UDADDR = wValue | (1<<ADDEN); | ||
| 785 | return; | ||
| 786 | } | ||
| 787 | if (bRequest == SET_CONFIGURATION && bmRequestType == 0) { | ||
| 788 | usb_configuration = wValue; | ||
| 789 | usb_send_in(); | ||
| 790 | cfg = endpoint_config_table; | ||
| 791 | for (i=1; i<=MAX_ENDPOINT; i++) { | ||
| 792 | UENUM = i; | ||
| 793 | en = pgm_read_byte(cfg++); | ||
| 794 | if (en) { | ||
| 795 | UECONX = (1<<EPEN); | ||
| 796 | UECFG0X = pgm_read_byte(cfg++); | ||
| 797 | UECFG1X = pgm_read_byte(cfg++); | ||
| 798 | } else { | ||
| 799 | UECONX = 0; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | UERST = UERST_MASK; | ||
| 803 | UERST = 0; | ||
| 804 | return; | ||
| 805 | } | ||
| 806 | if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) { | ||
| 807 | usb_wait_in_ready(); | ||
| 808 | UEDATX = usb_configuration; | ||
| 809 | usb_send_in(); | ||
| 810 | return; | ||
| 811 | } | ||
| 812 | |||
| 813 | if (bRequest == GET_STATUS) { | ||
| 814 | usb_wait_in_ready(); | ||
| 815 | i = 0; | ||
| 816 | #ifdef SUPPORT_ENDPOINT_HALT | ||
| 817 | if (bmRequestType == 0x82) { | ||
| 818 | UENUM = wIndex; | ||
| 819 | if (UECONX & (1<<STALLRQ)) i = 1; | ||
| 820 | UENUM = 0; | ||
| 821 | } | ||
| 822 | #endif | ||
| 823 | UEDATX = i; | ||
| 824 | UEDATX = 0; | ||
| 825 | usb_send_in(); | ||
| 826 | return; | ||
| 827 | } | ||
| 828 | if (bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) { | ||
| 829 | #ifdef SUPPORT_ENDPOINT_HALT | ||
| 830 | if (bmRequestType == 0x02 && wValue == ENDPOINT_HALT) { | ||
| 831 | i = wIndex & 0x7F; | ||
| 832 | if (i >= 1 && i <= MAX_ENDPOINT) { | ||
| 833 | usb_send_in(); | ||
| 834 | UENUM = i; | ||
| 835 | if (bRequest == SET_FEATURE) { | ||
| 836 | UECONX = (1<<STALLRQ)|(1<<EPEN); | ||
| 837 | } else { | ||
| 838 | UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN); | ||
| 839 | UERST = (1 << i); | ||
| 840 | UERST = 0; | ||
| 841 | } | ||
| 842 | return; | ||
| 843 | } | ||
| 844 | } | ||
| 845 | #endif | ||
| 846 | if (bmRequestType == 0x00 && wValue == DEVICE_REMOTE_WAKEUP) { | ||
| 847 | if (bRequest == SET_FEATURE) { | ||
| 848 | remote_wakeup = true; | ||
| 849 | } else { | ||
| 850 | remote_wakeup = false; | ||
| 851 | } | ||
| 852 | usb_send_in(); | ||
| 853 | return; | ||
| 854 | } | ||
| 855 | } | ||
| 856 | if (wIndex == KBD_INTERFACE) { | ||
| 857 | if (bmRequestType == 0xA1) { | ||
| 858 | if (bRequest == HID_GET_REPORT) { | ||
| 859 | usb_wait_in_ready(); | ||
| 860 | UEDATX = keyboard_report->mods; | ||
| 861 | UEDATX = 0; | ||
| 862 | for (i=0; i<6; i++) { | ||
| 863 | UEDATX = keyboard_report->keys[i]; | ||
| 864 | } | ||
| 865 | usb_send_in(); | ||
| 866 | return; | ||
| 867 | } | ||
| 868 | if (bRequest == HID_GET_IDLE) { | ||
| 869 | usb_wait_in_ready(); | ||
| 870 | UEDATX = usb_keyboard_idle_config; | ||
| 871 | usb_send_in(); | ||
| 872 | return; | ||
| 873 | } | ||
| 874 | if (bRequest == HID_GET_PROTOCOL) { | ||
| 875 | usb_wait_in_ready(); | ||
| 876 | UEDATX = usb_keyboard_protocol; | ||
| 877 | usb_send_in(); | ||
| 878 | return; | ||
| 879 | } | ||
| 880 | } | ||
| 881 | if (bmRequestType == 0x21) { | ||
| 882 | if (bRequest == HID_SET_REPORT) { | ||
| 883 | usb_wait_receive_out(); | ||
| 884 | usb_keyboard_leds = UEDATX; | ||
| 885 | usb_ack_out(); | ||
| 886 | usb_send_in(); | ||
| 887 | return; | ||
| 888 | } | ||
| 889 | if (bRequest == HID_SET_IDLE) { | ||
| 890 | usb_keyboard_idle_config = (wValue >> 8); | ||
| 891 | usb_keyboard_idle_count = 0; | ||
| 892 | //usb_wait_in_ready(); | ||
| 893 | usb_send_in(); | ||
| 894 | return; | ||
| 895 | } | ||
| 896 | if (bRequest == HID_SET_PROTOCOL) { | ||
| 897 | usb_keyboard_protocol = wValue; | ||
| 898 | //usb_wait_in_ready(); | ||
| 899 | usb_send_in(); | ||
| 900 | return; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | } | ||
| 904 | #ifdef MOUSE_ENABLE | ||
| 905 | if (wIndex == MOUSE_INTERFACE) { | ||
| 906 | if (bmRequestType == 0xA1) { | ||
| 907 | if (bRequest == HID_GET_REPORT) { | ||
| 908 | if (wValue == HID_REPORT_INPUT) { | ||
| 909 | usb_wait_in_ready(); | ||
| 910 | UEDATX = 0; | ||
| 911 | UEDATX = 0; | ||
| 912 | UEDATX = 0; | ||
| 913 | UEDATX = 0; | ||
| 914 | usb_send_in(); | ||
| 915 | return; | ||
| 916 | } | ||
| 917 | if (wValue == HID_REPORT_FEATURE) { | ||
| 918 | usb_wait_in_ready(); | ||
| 919 | UEDATX = 0x05; | ||
| 920 | usb_send_in(); | ||
| 921 | return; | ||
| 922 | } | ||
| 923 | } | ||
| 924 | if (bRequest == HID_GET_PROTOCOL) { | ||
| 925 | usb_wait_in_ready(); | ||
| 926 | UEDATX = usb_mouse_protocol; | ||
| 927 | usb_send_in(); | ||
| 928 | return; | ||
| 929 | } | ||
| 930 | } | ||
| 931 | if (bmRequestType == 0x21) { | ||
| 932 | if (bRequest == HID_SET_PROTOCOL) { | ||
| 933 | usb_mouse_protocol = wValue; | ||
| 934 | usb_send_in(); | ||
| 935 | return; | ||
| 936 | } | ||
| 937 | } | ||
| 938 | } | ||
| 939 | #endif | ||
| 940 | if (wIndex == DEBUG_INTERFACE) { | ||
| 941 | if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) { | ||
| 942 | len = wLength; | ||
| 943 | do { | ||
| 944 | // wait for host ready for IN packet | ||
| 945 | do { | ||
| 946 | i = UEINTX; | ||
| 947 | } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); | ||
| 948 | if (i & (1<<RXOUTI)) return; // abort | ||
| 949 | // send IN packet | ||
| 950 | n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; | ||
| 951 | for (i = n; i; i--) { | ||
| 952 | UEDATX = 0; | ||
| 953 | } | ||
| 954 | len -= n; | ||
| 955 | usb_send_in(); | ||
| 956 | } while (len || n == ENDPOINT0_SIZE); | ||
| 957 | return; | ||
| 958 | } | ||
| 959 | } | ||
| 960 | } | ||
| 961 | UECONX = (1<<STALLRQ) | (1<<EPEN); // stall | ||
| 962 | } | ||
diff --git a/protocol/pjrc/usb.h b/protocol/pjrc/usb.h new file mode 100644 index 000000000..0eb58fc39 --- /dev/null +++ b/protocol/pjrc/usb.h | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef USB_H | ||
| 25 | #define USB_H 1 | ||
| 26 | |||
| 27 | #include <stdint.h> | ||
| 28 | #include <stdbool.h> | ||
| 29 | #include <avr/io.h> | ||
| 30 | |||
| 31 | |||
| 32 | extern bool remote_wakeup; | ||
| 33 | extern bool suspend; | ||
| 34 | |||
| 35 | void usb_init(void); // initialize everything | ||
| 36 | uint8_t usb_configured(void); // is the USB port configured | ||
| 37 | void usb_remote_wakeup(void); | ||
| 38 | |||
| 39 | |||
| 40 | #define EP_TYPE_CONTROL 0x00 | ||
| 41 | #define EP_TYPE_BULK_IN 0x81 | ||
| 42 | #define EP_TYPE_BULK_OUT 0x80 | ||
| 43 | #define EP_TYPE_INTERRUPT_IN 0xC1 | ||
| 44 | #define EP_TYPE_INTERRUPT_OUT 0xC0 | ||
| 45 | #define EP_TYPE_ISOCHRONOUS_IN 0x41 | ||
| 46 | #define EP_TYPE_ISOCHRONOUS_OUT 0x40 | ||
| 47 | |||
| 48 | #define EP_SINGLE_BUFFER 0x02 | ||
| 49 | #define EP_DOUBLE_BUFFER 0x06 | ||
| 50 | |||
| 51 | #define EP_SIZE(s) ((s) == 64 ? 0x30 : \ | ||
| 52 | ((s) == 32 ? 0x20 : \ | ||
| 53 | ((s) == 16 ? 0x10 : \ | ||
| 54 | 0x00))) | ||
| 55 | |||
| 56 | #if defined (__AVR_AT90USB162__) || defined (__AVR_AT90USB82__) | ||
| 57 | # define MAX_ENDPOINT 4 | ||
| 58 | # define UERST_MASK 0x1E | ||
| 59 | #else | ||
| 60 | # define MAX_ENDPOINT 6 | ||
| 61 | # define UERST_MASK 0x7E | ||
| 62 | #endif | ||
| 63 | |||
| 64 | #define LSB(n) (n & 255) | ||
| 65 | #define MSB(n) ((n >> 8) & 255) | ||
| 66 | |||
| 67 | #if defined(__AVR_AT90USB162__) | ||
| 68 | #define HW_CONFIG() | ||
| 69 | #define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0))) | ||
| 70 | #define USB_CONFIG() (USBCON = (1<<USBE)) | ||
| 71 | #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | ||
| 72 | #elif defined(__AVR_ATmega32U4__) | ||
| 73 | #define HW_CONFIG() (UHWCON = 0x01) | ||
| 74 | #define PLL_CONFIG() (PLLCSR = 0x12) | ||
| 75 | #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | ||
| 76 | #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | ||
| 77 | #elif defined(__AVR_AT90USB646__) | ||
| 78 | #define HW_CONFIG() (UHWCON = 0x81) | ||
| 79 | #define PLL_CONFIG() (PLLCSR = 0x1A) | ||
| 80 | #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | ||
| 81 | #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | ||
| 82 | #elif defined(__AVR_AT90USB1286__) | ||
| 83 | #define HW_CONFIG() (UHWCON = 0x81) | ||
| 84 | #define PLL_CONFIG() (PLLCSR = 0x16) | ||
| 85 | #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | ||
| 86 | #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | ||
| 87 | #endif | ||
| 88 | |||
| 89 | // standard control endpoint request types | ||
| 90 | #define GET_STATUS 0 | ||
| 91 | #define CLEAR_FEATURE 1 | ||
| 92 | #define SET_FEATURE 3 | ||
| 93 | #define SET_ADDRESS 5 | ||
| 94 | #define GET_DESCRIPTOR 6 | ||
| 95 | #define GET_CONFIGURATION 8 | ||
| 96 | #define SET_CONFIGURATION 9 | ||
| 97 | #define GET_INTERFACE 10 | ||
| 98 | #define SET_INTERFACE 11 | ||
| 99 | // HID (human interface device) | ||
| 100 | #define HID_GET_REPORT 1 | ||
| 101 | #define HID_GET_IDLE 2 | ||
| 102 | #define HID_GET_PROTOCOL 3 | ||
| 103 | #define HID_SET_REPORT 9 | ||
| 104 | #define HID_SET_IDLE 10 | ||
| 105 | #define HID_SET_PROTOCOL 11 | ||
| 106 | #define HID_REPORT_INPUT 1 | ||
| 107 | #define HID_REPORT_OUTPUT 2 | ||
| 108 | #define HID_REPORT_FEATURE 3 | ||
| 109 | // CDC (communication class device) | ||
| 110 | #define CDC_SET_LINE_CODING 0x20 | ||
| 111 | #define CDC_GET_LINE_CODING 0x21 | ||
| 112 | #define CDC_SET_CONTROL_LINE_STATE 0x22 | ||
| 113 | // HID feature selectors | ||
| 114 | #define DEVICE_REMOTE_WAKEUP 1 | ||
| 115 | #define ENDPOINT_HALT 0 | ||
| 116 | #define TEST_MODE 2 | ||
| 117 | |||
| 118 | |||
| 119 | /*------------------------------------------------------------------* | ||
| 120 | * Keyboard descriptor setting | ||
| 121 | *------------------------------------------------------------------*/ | ||
| 122 | #define KBD_INTERFACE 0 | ||
| 123 | #define KBD_ENDPOINT 1 | ||
| 124 | #define KBD_SIZE 8 | ||
| 125 | #define KBD_BUFFER EP_DOUBLE_BUFFER | ||
| 126 | #define KBD_REPORT_KEYS (KBD_SIZE - 2) | ||
| 127 | |||
| 128 | // secondary keyboard | ||
| 129 | #ifdef NKRO_ENABLE | ||
| 130 | #define KBD2_INTERFACE 4 | ||
| 131 | #define KBD2_ENDPOINT 5 | ||
| 132 | #define KBD2_SIZE 16 | ||
| 133 | #define KBD2_BUFFER EP_DOUBLE_BUFFER | ||
| 134 | #define KBD2_REPORT_KEYS (KBD2_SIZE - 1) | ||
| 135 | #endif | ||
| 136 | |||
| 137 | #endif | ||
diff --git a/protocol/pjrc/usb_debug.c b/protocol/pjrc/usb_debug.c new file mode 100644 index 000000000..c1e6f6544 --- /dev/null +++ b/protocol/pjrc/usb_debug.c | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <avr/interrupt.h> | ||
| 25 | #include "sendchar.h" | ||
| 26 | #include "usb_debug.h" | ||
| 27 | |||
| 28 | |||
| 29 | // the time remaining before we transmit any partially full | ||
| 30 | // packet, or send a zero length packet. | ||
| 31 | volatile uint8_t debug_flush_timer=0; | ||
| 32 | |||
| 33 | |||
| 34 | int8_t sendchar(uint8_t c) | ||
| 35 | { | ||
| 36 | static uint8_t previous_timeout=0; | ||
| 37 | uint8_t timeout, intr_state; | ||
| 38 | |||
| 39 | // if we're not online (enumerated and configured), error | ||
| 40 | if (!usb_configured()) return -1; | ||
| 41 | // interrupts are disabled so these functions can be | ||
| 42 | // used from the main program or interrupt context, | ||
| 43 | // even both in the same program! | ||
| 44 | intr_state = SREG; | ||
| 45 | cli(); | ||
| 46 | UENUM = DEBUG_TX_ENDPOINT; | ||
| 47 | // if we gave up due to timeout before, don't wait again | ||
| 48 | if (previous_timeout) { | ||
| 49 | if (!(UEINTX & (1<<RWAL))) { | ||
| 50 | SREG = intr_state; | ||
| 51 | return -1; | ||
| 52 | } | ||
| 53 | previous_timeout = 0; | ||
| 54 | } | ||
| 55 | // wait for the FIFO to be ready to accept data | ||
| 56 | timeout = UDFNUML + 4; | ||
| 57 | while (1) { | ||
| 58 | // are we ready to transmit? | ||
| 59 | if (UEINTX & (1<<RWAL)) break; | ||
| 60 | SREG = intr_state; | ||
| 61 | // have we waited too long? | ||
| 62 | if (UDFNUML == timeout) { | ||
| 63 | previous_timeout = 1; | ||
| 64 | return -1; | ||
| 65 | } | ||
| 66 | // has the USB gone offline? | ||
| 67 | if (!usb_configured()) return -1; | ||
| 68 | // get ready to try checking again | ||
| 69 | intr_state = SREG; | ||
| 70 | cli(); | ||
| 71 | UENUM = DEBUG_TX_ENDPOINT; | ||
| 72 | } | ||
| 73 | // actually write the byte into the FIFO | ||
| 74 | UEDATX = c; | ||
| 75 | // if this completed a packet, transmit it now! | ||
| 76 | if (!(UEINTX & (1<<RWAL))) { | ||
| 77 | UEINTX = 0x3A; | ||
| 78 | debug_flush_timer = 0; | ||
| 79 | } else { | ||
| 80 | debug_flush_timer = 2; | ||
| 81 | } | ||
| 82 | SREG = intr_state; | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | // immediately transmit any buffered output. | ||
| 87 | void usb_debug_flush_output(void) | ||
| 88 | { | ||
| 89 | uint8_t intr_state; | ||
| 90 | |||
| 91 | intr_state = SREG; | ||
| 92 | cli(); | ||
| 93 | if (debug_flush_timer) { | ||
| 94 | UENUM = DEBUG_TX_ENDPOINT; | ||
| 95 | while ((UEINTX & (1<<RWAL))) { | ||
| 96 | UEDATX = 0; | ||
| 97 | } | ||
| 98 | UEINTX = 0x3A; | ||
| 99 | debug_flush_timer = 0; | ||
| 100 | } | ||
| 101 | SREG = intr_state; | ||
| 102 | } | ||
diff --git a/protocol/pjrc/usb_debug.h b/protocol/pjrc/usb_debug.h new file mode 100644 index 000000000..e70f4ca3a --- /dev/null +++ b/protocol/pjrc/usb_debug.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef USB_DEBUG_H | ||
| 25 | #define USB_DEBUG_H 1 | ||
| 26 | |||
| 27 | #include <stdint.h> | ||
| 28 | #include "usb.h" | ||
| 29 | |||
| 30 | |||
| 31 | #define DEBUG_INTERFACE 2 | ||
| 32 | #define DEBUG_TX_ENDPOINT 3 | ||
| 33 | #define DEBUG_TX_SIZE 32 | ||
| 34 | #define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER | ||
| 35 | |||
| 36 | |||
| 37 | extern volatile uint8_t debug_flush_timer; | ||
| 38 | |||
| 39 | |||
| 40 | void usb_debug_flush_output(void); // immediately transmit any buffered output | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/protocol/pjrc/usb_extra.c b/protocol/pjrc/usb_extra.c new file mode 100644 index 000000000..fe1f422c0 --- /dev/null +++ b/protocol/pjrc/usb_extra.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <util/delay.h> | ||
| 25 | #include <avr/interrupt.h> | ||
| 26 | #include "host.h" | ||
| 27 | #include "usb_extra.h" | ||
| 28 | |||
| 29 | |||
| 30 | int8_t usb_extra_send(uint8_t report_id, uint16_t data) | ||
| 31 | { | ||
| 32 | uint8_t intr_state, timeout; | ||
| 33 | |||
| 34 | if (!usb_configured()) return -1; | ||
| 35 | intr_state = SREG; | ||
| 36 | cli(); | ||
| 37 | UENUM = EXTRA_ENDPOINT; | ||
| 38 | timeout = UDFNUML + 50; | ||
| 39 | while (1) { | ||
| 40 | // are we ready to transmit? | ||
| 41 | if (UEINTX & (1<<RWAL)) break; | ||
| 42 | SREG = intr_state; | ||
| 43 | // has the USB gone offline? | ||
| 44 | if (!usb_configured()) return -1; | ||
| 45 | // have we waited too long? | ||
| 46 | if (UDFNUML == timeout) return -1; | ||
| 47 | // get ready to try checking again | ||
| 48 | intr_state = SREG; | ||
| 49 | cli(); | ||
| 50 | UENUM = EXTRA_ENDPOINT; | ||
| 51 | } | ||
| 52 | |||
| 53 | UEDATX = report_id; | ||
| 54 | UEDATX = data&0xFF; | ||
| 55 | UEDATX = (data>>8)&0xFF; | ||
| 56 | |||
| 57 | UEINTX = 0x3A; | ||
| 58 | SREG = intr_state; | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | int8_t usb_extra_consumer_send(uint16_t bits) | ||
| 63 | { | ||
| 64 | return usb_extra_send(REPORT_ID_CONSUMER, bits); | ||
| 65 | } | ||
| 66 | |||
| 67 | int8_t usb_extra_system_send(uint16_t bits) | ||
| 68 | { | ||
| 69 | return usb_extra_send(REPORT_ID_SYSTEM, bits); | ||
| 70 | } | ||
diff --git a/protocol/pjrc/usb_extra.h b/protocol/pjrc/usb_extra.h new file mode 100644 index 000000000..042ac4837 --- /dev/null +++ b/protocol/pjrc/usb_extra.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef USB_EXTRA_H | ||
| 25 | #define USB_EXTRA_H 1 | ||
| 26 | /* | ||
| 27 | * Enhanced keyboard features for Windows: | ||
| 28 | * Audio control and System control | ||
| 29 | * | ||
| 30 | * http://www.microsoft.com/whdc/archive/w2kbd.mspx | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <stdint.h> | ||
| 34 | #include "usb.h" | ||
| 35 | |||
| 36 | |||
| 37 | #define EXTRA_INTERFACE 3 | ||
| 38 | #define EXTRA_ENDPOINT 4 | ||
| 39 | #define EXTRA_SIZE 8 | ||
| 40 | #define EXTRA_BUFFER EP_DOUBLE_BUFFER | ||
| 41 | |||
| 42 | |||
| 43 | int8_t usb_extra_consumer_send(uint16_t bits); | ||
| 44 | int8_t usb_extra_system_send(uint16_t bits); | ||
| 45 | |||
| 46 | #endif | ||
diff --git a/protocol/pjrc/usb_keyboard.c b/protocol/pjrc/usb_keyboard.c new file mode 100644 index 000000000..e057c77fa --- /dev/null +++ b/protocol/pjrc/usb_keyboard.c | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <avr/interrupt.h> | ||
| 25 | #include <avr/pgmspace.h> | ||
| 26 | #include "usb_keycodes.h" | ||
| 27 | #include "usb_keyboard.h" | ||
| 28 | #include "print.h" | ||
| 29 | #include "debug.h" | ||
| 30 | #include "util.h" | ||
| 31 | #include "host.h" | ||
| 32 | |||
| 33 | |||
| 34 | // protocol setting from the host. We use exactly the same report | ||
| 35 | // either way, so this variable only stores the setting since we | ||
| 36 | // are required to be able to report which setting is in use. | ||
| 37 | uint8_t usb_keyboard_protocol=1; | ||
| 38 | |||
| 39 | // the idle configuration, how often we send the report to the | ||
| 40 | // host (ms * 4) even when it hasn't changed | ||
| 41 | // Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request. | ||
| 42 | uint8_t usb_keyboard_idle_config=125; | ||
| 43 | |||
| 44 | // count until idle timeout | ||
| 45 | uint8_t usb_keyboard_idle_count=0; | ||
| 46 | |||
| 47 | // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | ||
| 48 | volatile uint8_t usb_keyboard_leds=0; | ||
| 49 | |||
| 50 | |||
| 51 | static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end); | ||
| 52 | |||
| 53 | |||
| 54 | int8_t usb_keyboard_send_report(report_keyboard_t *report) | ||
| 55 | { | ||
| 56 | int8_t result = 0; | ||
| 57 | |||
| 58 | #ifdef NKRO_ENABLE | ||
| 59 | if (keyboard_nkro) | ||
| 60 | result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS); | ||
| 61 | else | ||
| 62 | #endif | ||
| 63 | { | ||
| 64 | if (usb_keyboard_protocol) | ||
| 65 | result = send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS); | ||
| 66 | else | ||
| 67 | result = send_report(report, KBD_ENDPOINT, 0, 6); | ||
| 68 | } | ||
| 69 | |||
| 70 | if (result) return result; | ||
| 71 | usb_keyboard_idle_count = 0; | ||
| 72 | usb_keyboard_print_report(report); | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | void usb_keyboard_print_report(report_keyboard_t *report) | ||
| 77 | { | ||
| 78 | if (!debug_keyboard) return; | ||
| 79 | print("keys: "); | ||
| 80 | for (int i = 0; i < REPORT_KEYS; i++) { phex(report->keys[i]); print(" "); } | ||
| 81 | print(" mods: "); phex(report->mods); print("\n"); | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end) | ||
| 86 | { | ||
| 87 | uint8_t intr_state, timeout; | ||
| 88 | |||
| 89 | if (!usb_configured()) return -1; | ||
| 90 | intr_state = SREG; | ||
| 91 | cli(); | ||
| 92 | UENUM = endpoint; | ||
| 93 | timeout = UDFNUML + 50; | ||
| 94 | while (1) { | ||
| 95 | // are we ready to transmit? | ||
| 96 | if (UEINTX & (1<<RWAL)) break; | ||
| 97 | SREG = intr_state; | ||
| 98 | // has the USB gone offline? | ||
| 99 | if (!usb_configured()) return -1; | ||
| 100 | // have we waited too long? | ||
| 101 | if (UDFNUML == timeout) return -1; | ||
| 102 | // get ready to try checking again | ||
| 103 | intr_state = SREG; | ||
| 104 | cli(); | ||
| 105 | UENUM = endpoint; | ||
| 106 | } | ||
| 107 | UEDATX = report->mods; | ||
| 108 | #ifdef NKRO_ENABLE | ||
| 109 | if (!keyboard_nkro) | ||
| 110 | UEDATX = 0; | ||
| 111 | #else | ||
| 112 | UEDATX = 0; | ||
| 113 | #endif | ||
| 114 | for (uint8_t i = keys_start; i < keys_end; i++) { | ||
| 115 | UEDATX = report->keys[i]; | ||
| 116 | } | ||
| 117 | UEINTX = 0x3A; | ||
| 118 | SREG = intr_state; | ||
| 119 | return 0; | ||
| 120 | } | ||
diff --git a/protocol/pjrc/usb_keyboard.h b/protocol/pjrc/usb_keyboard.h new file mode 100644 index 000000000..c362ca3b8 --- /dev/null +++ b/protocol/pjrc/usb_keyboard.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_keyboard.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef USB_KEYBOARD_H | ||
| 25 | #define USB_KEYBOARD_H 1 | ||
| 26 | |||
| 27 | #include <stdint.h> | ||
| 28 | #include <stdbool.h> | ||
| 29 | #include "usb.h" | ||
| 30 | #include "host.h" | ||
| 31 | |||
| 32 | |||
| 33 | extern uint8_t usb_keyboard_protocol; | ||
| 34 | extern uint8_t usb_keyboard_idle_config; | ||
| 35 | extern uint8_t usb_keyboard_idle_count; | ||
| 36 | extern volatile uint8_t usb_keyboard_leds; | ||
| 37 | |||
| 38 | |||
| 39 | int8_t usb_keyboard_send_report(report_keyboard_t *report); | ||
| 40 | void usb_keyboard_print_report(report_keyboard_t *report); | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/protocol/pjrc/usb_mouse.c b/protocol/pjrc/usb_mouse.c new file mode 100644 index 000000000..d81db756f --- /dev/null +++ b/protocol/pjrc/usb_mouse.c | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | /* USB Mouse Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_mouse.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <avr/interrupt.h> | ||
| 25 | #include <util/delay.h> | ||
| 26 | #include "usb_mouse.h" | ||
| 27 | #include "print.h" | ||
| 28 | #include "debug.h" | ||
| 29 | |||
| 30 | |||
| 31 | uint8_t usb_mouse_protocol=1; | ||
| 32 | |||
| 33 | |||
| 34 | int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons) | ||
| 35 | { | ||
| 36 | uint8_t intr_state, timeout; | ||
| 37 | |||
| 38 | if (!usb_configured()) return -1; | ||
| 39 | if (x == -128) x = -127; | ||
| 40 | if (y == -128) y = -127; | ||
| 41 | if (wheel_v == -128) wheel_v = -127; | ||
| 42 | if (wheel_h == -128) wheel_h = -127; | ||
| 43 | intr_state = SREG; | ||
| 44 | cli(); | ||
| 45 | UENUM = MOUSE_ENDPOINT; | ||
| 46 | timeout = UDFNUML + 50; | ||
| 47 | while (1) { | ||
| 48 | // are we ready to transmit? | ||
| 49 | if (UEINTX & (1<<RWAL)) break; | ||
| 50 | SREG = intr_state; | ||
| 51 | // has the USB gone offline? | ||
| 52 | if (!usb_configured()) return -1; | ||
| 53 | // have we waited too long? | ||
| 54 | if (UDFNUML == timeout) return -1; | ||
| 55 | // get ready to try checking again | ||
| 56 | intr_state = SREG; | ||
| 57 | cli(); | ||
| 58 | UENUM = MOUSE_ENDPOINT; | ||
| 59 | } | ||
| 60 | UEDATX = buttons; | ||
| 61 | UEDATX = x; | ||
| 62 | UEDATX = y; | ||
| 63 | if (usb_mouse_protocol) { | ||
| 64 | UEDATX = wheel_v; | ||
| 65 | UEDATX = wheel_h; | ||
| 66 | } | ||
| 67 | |||
| 68 | UEINTX = 0x3A; | ||
| 69 | SREG = intr_state; | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons) { | ||
| 74 | if (!debug_mouse) return; | ||
| 75 | print("usb_mouse[btn|x y v h]: "); | ||
| 76 | phex(buttons); print("|"); | ||
| 77 | phex(x); print(" "); | ||
| 78 | phex(y); print(" "); | ||
| 79 | phex(wheel_v); print(" "); | ||
| 80 | phex(wheel_h); print("\n"); | ||
| 81 | } | ||
diff --git a/protocol/pjrc/usb_mouse.h b/protocol/pjrc/usb_mouse.h new file mode 100644 index 000000000..eb3056126 --- /dev/null +++ b/protocol/pjrc/usb_mouse.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /* USB Mouse Plus Debug Channel Example for Teensy USB Development Board | ||
| 2 | * http://www.pjrc.com/teensy/usb_mouse.html | ||
| 3 | * Copyright (c) 2009 PJRC.COM, LLC | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | * in the Software without restriction, including without limitation the rights | ||
| 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | * furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | * THE SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef USB_MOUSE_H | ||
| 25 | #define USB_MOUSE_H 1 | ||
| 26 | |||
| 27 | #include <stdint.h> | ||
| 28 | #include <stdbool.h> | ||
| 29 | #include "usb.h" | ||
| 30 | |||
| 31 | |||
| 32 | #define MOUSE_INTERFACE 1 | ||
| 33 | #define MOUSE_ENDPOINT 2 | ||
| 34 | #define MOUSE_SIZE 8 | ||
| 35 | #define MOUSE_BUFFER EP_DOUBLE_BUFFER | ||
| 36 | |||
| 37 | #define MOUSE_BTN1 (1<<0) | ||
| 38 | #define MOUSE_BTN2 (1<<1) | ||
| 39 | #define MOUSE_BTN3 (1<<2) | ||
| 40 | #define MOUSE_BTN4 (1<<3) | ||
| 41 | #define MOUSE_BTN5 (1<<4) | ||
| 42 | |||
| 43 | |||
| 44 | extern uint8_t usb_mouse_protocol; | ||
| 45 | |||
| 46 | |||
| 47 | int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons); | ||
| 48 | void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons); | ||
| 49 | |||
| 50 | #endif | ||
