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
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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
24 // Version 1.0: Initial Release
25 // Version 1.1: Add support for Teensy 2.0
27 #define USB_SERIAL_PRIVATE_INCLUDE
28 #include "usb_keyboard_debug.h"
30 /**************************************************************************
32 * Configurable Options
34 **************************************************************************/
36 // USB devices are supposed to implment a halt feature, which is
37 // rarely (if ever) used. If you comment this line out, the halt
38 // code will be removed, saving 102 bytes of space (gcc 4.3.0).
39 // This is not strictly USB compliant, but works with all major
41 #define SUPPORT_ENDPOINT_HALT
45 /**************************************************************************
47 * Endpoint Buffer Configuration
49 **************************************************************************/
51 #define ENDPOINT0_SIZE 32
53 #define KEYBOARD_INTERFACE 0
54 #define KEYBOARD_ENDPOINT 3
55 #define KEYBOARD_SIZE 8
56 #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
58 #define DEBUG_INTERFACE 1
59 #define DEBUG_TX_ENDPOINT 4
60 #define DEBUG_TX_SIZE 32
61 #define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER
63 static const uint8_t PROGMEM endpoint_config_table[] = {
66 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
67 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER
71 /**************************************************************************
75 **************************************************************************/
77 // Descriptors are the data that your computer reads when it auto-detects
78 // this USB device (called "enumeration" in USB lingo). The most commonly
79 // changed items are editable at the top of this file. Changing things
80 // in here should only be done by those who've read chapter 9 of the USB
81 // spec and relevant portions of any USB class specifications!
84 static const uint8_t PROGMEM device_descriptor[] = {
91 ENDPOINT0_SIZE, // bMaxPacketSize0
92 LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
93 LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
94 0x00, 0x01, // bcdDevice
98 1 // bNumConfigurations
101 // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
102 static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
103 0x05, 0x01, // Usage Page (Generic Desktop),
104 0x09, 0x06, // Usage (Keyboard),
105 0xA1, 0x01, // Collection (Application),
106 0x75, 0x01, // Report Size (1),
107 0x95, 0x08, // Report Count (8),
108 0x05, 0x07, // Usage Page (Key Codes),
109 0x19, 0xE0, // Usage Minimum (224),
110 0x29, 0xE7, // Usage Maximum (231),
111 0x15, 0x00, // Logical Minimum (0),
112 0x25, 0x01, // Logical Maximum (1),
113 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
114 0x95, 0x01, // Report Count (1),
115 0x75, 0x08, // Report Size (8),
116 0x81, 0x03, // Input (Constant), ;Reserved byte
117 0x95, 0x05, // Report Count (5),
118 0x75, 0x01, // Report Size (1),
119 0x05, 0x08, // Usage Page (LEDs),
120 0x19, 0x01, // Usage Minimum (1),
121 0x29, 0x05, // Usage Maximum (5),
122 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
123 0x95, 0x01, // Report Count (1),
124 0x75, 0x03, // Report Size (3),
125 0x91, 0x03, // Output (Constant), ;LED report padding
126 0x95, 0x06, // Report Count (6),
127 0x75, 0x08, // Report Size (8),
128 0x15, 0x00, // Logical Minimum (0),
129 0x25, 0x68, // Logical Maximum(104),
130 0x05, 0x07, // Usage Page (Key Codes),
131 0x19, 0x00, // Usage Minimum (0),
132 0x29, 0x68, // Usage Maximum (104),
133 0x81, 0x00, // Input (Data, Array),
134 0xc0 // End Collection
137 static const uint8_t PROGMEM debug_hid_report_desc[] = {
138 0x06, 0x30, 0xFF, // Usage Page 0xFF31 (vendor defined)
139 //0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
140 0x09, 0x74, // Usage 0x74
141 0xA1, 0x53, // Collection 0x53
142 0x75, 0x08, // report size = 8 bits
143 0x15, 0x00, // logical minimum = 0
144 0x26, 0xFF, 0x00, // logical maximum = 255
145 0x95, DEBUG_TX_SIZE, // report count
147 0x81, 0x02, // Input (array)
148 0xC0 // end collection
151 #define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7)
152 #define KEYBOARD_HID_DESC_OFFSET (9+9)
153 #define DEBUG_HID_DESC_OFFSET (9+9+9+7+9)
154 static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
155 // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
157 2, // bDescriptorType;
158 LSB(CONFIG1_DESC_SIZE), // wTotalLength
159 MSB(CONFIG1_DESC_SIZE),
161 1, // bConfigurationValue
163 0xC0, // bmAttributes
165 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
167 4, // bDescriptorType
168 KEYBOARD_INTERFACE, // bInterfaceNumber
169 0, // bAlternateSetting
171 0x03, // bInterfaceClass (0x03 = HID)
172 0x01, // bInterfaceSubClass (0x01 = Boot)
173 0x01, // bInterfaceProtocol (0x01 = Keyboard)
175 // HID interface descriptor, HID 1.11 spec, section 6.2.1
177 0x21, // bDescriptorType
178 0x11, 0x01, // bcdHID
180 1, // bNumDescriptors
181 0x22, // bDescriptorType
182 sizeof(keyboard_hid_report_desc), // wDescriptorLength
184 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
186 5, // bDescriptorType
187 KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
188 0x03, // bmAttributes (0x03=intr)
189 KEYBOARD_SIZE, 0, // wMaxPacketSize
191 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
193 4, // bDescriptorType
194 DEBUG_INTERFACE, // bInterfaceNumber
195 0, // bAlternateSetting
197 0x03, // bInterfaceClass (0x03 = HID)
198 0x00, // bInterfaceSubClass
199 0x00, // bInterfaceProtocol
201 // HID interface descriptor, HID 1.11 spec, section 6.2.1
203 0x21, // bDescriptorType
204 0x11, 0x01, // bcdHID
206 1, // bNumDescriptors
207 0x22, // bDescriptorType
208 sizeof(debug_hid_report_desc), // wDescriptorLength
210 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
212 5, // bDescriptorType
213 DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
214 0x03, // bmAttributes (0x03=intr)
215 DEBUG_TX_SIZE, 0, // wMaxPacketSize
219 // If you're desperate for a little extra code memory, these strings
220 // can be completely removed if iManufacturer, iProduct, iSerialNumber
221 // in the device desciptor are changed to zeros.
222 struct usb_string_descriptor_struct {
224 uint8_t bDescriptorType;
227 static const struct usb_string_descriptor_struct PROGMEM string0 = {
232 static const struct usb_string_descriptor_struct PROGMEM string1 = {
233 sizeof(STR_MANUFACTURER),
237 static const struct usb_string_descriptor_struct PROGMEM string2 = {
243 // This table defines which descriptor data is sent for each specific
244 // request from the host (in wValue and wIndex).
245 static const struct descriptor_list_struct {
250 } PROGMEM descriptor_list[] = {
251 {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
252 {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
253 {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
254 {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
255 {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
256 {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
257 {0x0300, 0x0000, (const uint8_t *)&string0, 4},
258 {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
259 {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
261 #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
264 /**************************************************************************
266 * Variables - these are the only non-stack RAM usage
268 **************************************************************************/
270 // zero when we are not configured, non-zero when enumerated
271 static volatile uint8_t usb_configuration=0;
273 // the time remaining before we transmit any partially full
274 // packet, or send a zero length packet.
275 static volatile uint8_t debug_flush_timer=0;
277 // protocol setting from the host. We use exactly the same report
278 // either way, so this variable only stores the setting since we
279 // are required to be able to report which setting is in use.
280 static uint8_t keyboard_protocol=1;
282 // the idle configuration, how often we send the report to the
283 // host (ms * 4) even when it hasn't changed
284 static uint8_t keyboard_idle_config=125;
286 // count until idle timeout
287 static uint8_t keyboard_idle_count=0;
290 /**************************************************************************
292 * Public Functions - these are the API intended for the user
294 **************************************************************************/
301 USB_FREEZE(); // enable USB
302 PLL_CONFIG(); // config PLL
303 while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
304 USB_CONFIG(); // start USB clock
305 UDCON = 0; // enable attach resistor
306 usb_configuration = 0;
307 UDIEN = (1<<EORSTE)|(1<<SOFE);
311 // return 0 if the USB is not configured, or the configuration
312 // number selected by the HOST
313 uint8_t usb_configured(void)
315 return usb_configuration;
319 // perform a single keystroke
320 int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
324 USBKeys_Modifiers = modifier;
325 USBKeys_Array[0] = key;
326 r = usb_keyboard_send();
328 USBKeys_Modifiers = 0;
329 USBKeys_Array[0] = 0;
330 return usb_keyboard_send();
333 // send the contents of USBKeys_Array and USBKeys_Modifiers
334 int8_t usb_keyboard_send(void)
336 uint8_t i, intr_state, timeout;
338 if (!usb_configuration) return -1;
341 UENUM = KEYBOARD_ENDPOINT;
342 timeout = UDFNUML + 50;
344 // are we ready to transmit?
345 if (UEINTX & (1<<RWAL)) break;
347 // has the USB gone offline?
348 if (!usb_configuration) return -1;
349 // have we waited too long?
350 if (UDFNUML == timeout) return -1;
351 // get ready to try checking again
354 UENUM = KEYBOARD_ENDPOINT;
356 UEDATX = USBKeys_Modifiers;
358 for (i=0; i<6; i++) {
359 UEDATX = USBKeys_Array[i];
362 keyboard_idle_count = 0;
367 // transmit a character. 0 returned on success, -1 on error
368 int8_t usb_debug_putchar(uint8_t c)
370 static uint8_t previous_timeout=0;
371 uint8_t timeout, intr_state;
373 // if we're not online (enumerated and configured), error
374 if (!usb_configuration) return -1;
375 // interrupts are disabled so these functions can be
376 // used from the main program or interrupt context,
377 // even both in the same program!
380 UENUM = DEBUG_TX_ENDPOINT;
381 // if we gave up due to timeout before, don't wait again
382 if (previous_timeout) {
383 if (!(UEINTX & (1<<RWAL))) {
387 previous_timeout = 0;
389 // wait for the FIFO to be ready to accept data
390 timeout = UDFNUML + 4;
392 // are we ready to transmit?
393 if (UEINTX & (1<<RWAL)) break;
395 // have we waited too long?
396 if (UDFNUML == timeout) {
397 previous_timeout = 1;
400 // has the USB gone offline?
401 if (!usb_configuration) return -1;
402 // get ready to try checking again
405 UENUM = DEBUG_TX_ENDPOINT;
407 // actually write the byte into the FIFO
409 // if this completed a packet, transmit it now!
410 if (!(UEINTX & (1<<RWAL))) {
412 debug_flush_timer = 0;
414 debug_flush_timer = 2;
421 // immediately transmit any buffered output.
422 void usb_debug_flush_output(void)
428 if (debug_flush_timer) {
429 UENUM = DEBUG_TX_ENDPOINT;
430 while ((UEINTX & (1<<RWAL))) {
434 debug_flush_timer = 0;
441 /**************************************************************************
443 * Private Functions - not intended for general user consumption....
445 **************************************************************************/
449 // USB Device Interrupt - handle all device-level events
450 // the transmit buffer flushing is triggered by the start of frame
454 uint8_t intbits, t, i;
455 static uint8_t div4=0;
459 if (intbits & (1<<EORSTI)) {
462 UECFG0X = EP_TYPE_CONTROL;
463 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
464 UEIENX = (1<<RXSTPE);
465 usb_configuration = 0;
467 if ((intbits & (1<<SOFI)) && usb_configuration) {
468 t = debug_flush_timer;
470 debug_flush_timer = -- t;
472 UENUM = DEBUG_TX_ENDPOINT;
473 while ((UEINTX & (1<<RWAL))) {
479 if (keyboard_idle_config && (++div4 & 3) == 0) {
480 UENUM = KEYBOARD_ENDPOINT;
481 if (UEINTX & (1<<RWAL)) {
482 keyboard_idle_count++;
483 if (keyboard_idle_count == keyboard_idle_config) {
484 keyboard_idle_count = 0;
485 UEDATX = USBKeys_Modifiers;
487 for (i=0; i<6; i++) {
488 UEDATX = USBKeys_Array[i];
499 // Misc functions to wait for ready and send/receive packets
500 static inline void usb_wait_in_ready(void)
502 while (!(UEINTX & (1<<TXINI))) ;
504 static inline void usb_send_in(void)
506 UEINTX = ~(1<<TXINI);
508 static inline void usb_wait_receive_out(void)
510 while (!(UEINTX & (1<<RXOUTI))) ;
512 static inline void usb_ack_out(void)
514 UEINTX = ~(1<<RXOUTI);
519 // USB Endpoint Interrupt - endpoint 0 is handled here. The
520 // other endpoints are manipulated by the user-callable
521 // functions, and the start-of-frame interrupt.
528 uint8_t i, n, len, en;
529 uint8_t bmRequestType;
535 const uint8_t *desc_addr;
540 if (intbits & (1<<RXSTPI)) {
541 bmRequestType = UEDATX;
544 wValue |= (UEDATX << 8);
546 wIndex |= (UEDATX << 8);
548 wLength |= (UEDATX << 8);
549 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
550 if (bRequest == GET_DESCRIPTOR) {
551 list = (const uint8_t *)descriptor_list;
553 if (i >= NUM_DESC_LIST) {
554 UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
557 desc_val = pgm_read_word(list);
558 if (desc_val != wValue) {
559 list += sizeof(struct descriptor_list_struct);
563 desc_val = pgm_read_word(list);
564 if (desc_val != wIndex) {
565 list += sizeof(struct descriptor_list_struct)-2;
569 desc_addr = (const uint8_t *)pgm_read_word(list);
571 desc_length = pgm_read_byte(list);
574 len = (wLength < 256) ? wLength : 255;
575 if (len > desc_length) len = desc_length;
577 // wait for host ready for IN packet
580 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
581 if (i & (1<<RXOUTI)) return; // abort
583 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
584 for (i = n; i; i--) {
585 UEDATX = pgm_read_byte(desc_addr++);
589 } while (len || n == ENDPOINT0_SIZE);
592 if (bRequest == SET_ADDRESS) {
595 UDADDR = wValue | (1<<ADDEN);
598 if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
599 usb_configuration = wValue;
601 cfg = endpoint_config_table;
602 for (i=1; i<5; i++) {
604 en = pgm_read_byte(cfg++);
607 UECFG0X = pgm_read_byte(cfg++);
608 UECFG1X = pgm_read_byte(cfg++);
615 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
617 UEDATX = usb_configuration;
622 if (bRequest == GET_STATUS) {
625 #ifdef SUPPORT_ENDPOINT_HALT
626 if (bmRequestType == 0x82) {
628 if (UECONX & (1<<STALLRQ)) i = 1;
637 #ifdef SUPPORT_ENDPOINT_HALT
638 if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
639 && bmRequestType == 0x02 && wValue == 0) {
641 if (i >= 1 && i <= MAX_ENDPOINT) {
644 if (bRequest == SET_FEATURE) {
645 UECONX = (1<<STALLRQ)|(1<<EPEN);
647 UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
655 if (wIndex == KEYBOARD_INTERFACE) {
656 if (bmRequestType == 0xA1) {
657 if (bRequest == HID_GET_REPORT) {
659 UEDATX = USBKeys_Modifiers;
661 for (i=0; i<6; i++) {
662 UEDATX = USBKeys_Array[i];
667 if (bRequest == HID_GET_IDLE) {
669 UEDATX = keyboard_idle_config;
673 if (bRequest == HID_GET_PROTOCOL) {
675 UEDATX = keyboard_protocol;
680 if (bmRequestType == 0x21) {
681 if (bRequest == HID_SET_REPORT) {
682 usb_wait_receive_out();
683 USBKeys_LEDs = UEDATX;
688 if (bRequest == HID_SET_IDLE) {
689 keyboard_idle_config = (wValue >> 8);
690 keyboard_idle_count = 0;
691 //usb_wait_in_ready();
695 if (bRequest == HID_SET_PROTOCOL) {
696 keyboard_protocol = wValue;
697 //usb_wait_in_ready();
703 if (wIndex == DEBUG_INTERFACE) {
704 if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
707 // wait for host ready for IN packet
710 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
711 if (i & (1<<RXOUTI)) return; // abort
713 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
714 for (i = n; i; i--) {
719 } while (len || n == ENDPOINT0_SIZE);
724 UECONX = (1<<STALLRQ) | (1<<EPEN); // stall