]> git.gir.st - tmk_keyboard.git/blob - usb_keyboard_debug.c
change file name.
[tmk_keyboard.git] / usb_keyboard_debug.c
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 // Version 1.0: Initial Release
25 // Version 1.1: Add support for Teensy 2.0
26
27 #define USB_SERIAL_PRIVATE_INCLUDE
28 #include "usb_keyboard_debug.h"
29
30 /**************************************************************************
31 *
32 * Configurable Options
33 *
34 **************************************************************************/
35
36 // You can change these to give your code its own name.
37 #define STR_MANUFACTURER L"MfgName"
38 #define STR_PRODUCT L"Keyboard"
39
40
41 // Mac OS-X and Linux automatically load the correct drivers. On
42 // Windows, even though the driver is supplied by Microsoft, an
43 // INF file is needed to load the driver. These numbers need to
44 // match the INF file.
45 #define VENDOR_ID 0x16C0
46 #define PRODUCT_ID 0x047D
47
48
49 // USB devices are supposed to implment a halt feature, which is
50 // rarely (if ever) used. If you comment this line out, the halt
51 // code will be removed, saving 102 bytes of space (gcc 4.3.0).
52 // This is not strictly USB compliant, but works with all major
53 // operating systems.
54 #define SUPPORT_ENDPOINT_HALT
55
56
57
58 /**************************************************************************
59 *
60 * Endpoint Buffer Configuration
61 *
62 **************************************************************************/
63
64 #define ENDPOINT0_SIZE 32
65
66 #define KEYBOARD_INTERFACE 0
67 #define KEYBOARD_ENDPOINT 3
68 #define KEYBOARD_SIZE 8
69 #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
70
71 #define DEBUG_INTERFACE 1
72 #define DEBUG_TX_ENDPOINT 4
73 #define DEBUG_TX_SIZE 32
74 #define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER
75
76 static const uint8_t PROGMEM endpoint_config_table[] = {
77 0,
78 0,
79 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
80 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER
81 };
82
83
84 /**************************************************************************
85 *
86 * Descriptor Data
87 *
88 **************************************************************************/
89
90 // Descriptors are the data that your computer reads when it auto-detects
91 // this USB device (called "enumeration" in USB lingo). The most commonly
92 // changed items are editable at the top of this file. Changing things
93 // in here should only be done by those who've read chapter 9 of the USB
94 // spec and relevant portions of any USB class specifications!
95
96
97 static uint8_t PROGMEM device_descriptor[] = {
98 18, // bLength
99 1, // bDescriptorType
100 0x00, 0x02, // bcdUSB
101 0, // bDeviceClass
102 0, // bDeviceSubClass
103 0, // bDeviceProtocol
104 ENDPOINT0_SIZE, // bMaxPacketSize0
105 LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
106 LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
107 0x00, 0x01, // bcdDevice
108 1, // iManufacturer
109 2, // iProduct
110 0, // iSerialNumber
111 1 // bNumConfigurations
112 };
113
114 // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
115 static uint8_t PROGMEM keyboard_hid_report_desc[] = {
116 0x05, 0x01, // Usage Page (Generic Desktop),
117 0x09, 0x06, // Usage (Keyboard),
118 0xA1, 0x01, // Collection (Application),
119 0x75, 0x01, // Report Size (1),
120 0x95, 0x08, // Report Count (8),
121 0x05, 0x07, // Usage Page (Key Codes),
122 0x19, 0xE0, // Usage Minimum (224),
123 0x29, 0xE7, // Usage Maximum (231),
124 0x15, 0x00, // Logical Minimum (0),
125 0x25, 0x01, // Logical Maximum (1),
126 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
127 0x95, 0x01, // Report Count (1),
128 0x75, 0x08, // Report Size (8),
129 0x81, 0x03, // Input (Constant), ;Reserved byte
130 0x95, 0x05, // Report Count (5),
131 0x75, 0x01, // Report Size (1),
132 0x05, 0x08, // Usage Page (LEDs),
133 0x19, 0x01, // Usage Minimum (1),
134 0x29, 0x05, // Usage Maximum (5),
135 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
136 0x95, 0x01, // Report Count (1),
137 0x75, 0x03, // Report Size (3),
138 0x91, 0x03, // Output (Constant), ;LED report padding
139 0x95, 0x06, // Report Count (6),
140 0x75, 0x08, // Report Size (8),
141 0x15, 0x00, // Logical Minimum (0),
142 0x25, 0x68, // Logical Maximum(104),
143 0x05, 0x07, // Usage Page (Key Codes),
144 0x19, 0x00, // Usage Minimum (0),
145 0x29, 0x68, // Usage Maximum (104),
146 0x81, 0x00, // Input (Data, Array),
147 0xc0 // End Collection
148 };
149
150 static uint8_t PROGMEM debug_hid_report_desc[] = {
151 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
152 0x09, 0x74, // Usage 0x74
153 0xA1, 0x53, // Collection 0x53
154 0x75, 0x08, // report size = 8 bits
155 0x15, 0x00, // logical minimum = 0
156 0x26, 0xFF, 0x00, // logical maximum = 255
157 0x95, DEBUG_TX_SIZE, // report count
158 0x09, 0x75, // usage
159 0x81, 0x02, // Input (array)
160 0xC0 // end collection
161 };
162
163 #define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7)
164 #define KEYBOARD_HID_DESC_OFFSET (9+9)
165 #define DEBUG_HID_DESC_OFFSET (9+9+9+7+9)
166 static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
167 // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
168 9, // bLength;
169 2, // bDescriptorType;
170 LSB(CONFIG1_DESC_SIZE), // wTotalLength
171 MSB(CONFIG1_DESC_SIZE),
172 2, // bNumInterfaces
173 1, // bConfigurationValue
174 0, // iConfiguration
175 0xC0, // bmAttributes
176 50, // bMaxPower
177 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
178 9, // bLength
179 4, // bDescriptorType
180 KEYBOARD_INTERFACE, // bInterfaceNumber
181 0, // bAlternateSetting
182 1, // bNumEndpoints
183 0x03, // bInterfaceClass (0x03 = HID)
184 0x01, // bInterfaceSubClass (0x01 = Boot)
185 0x01, // bInterfaceProtocol (0x01 = Keyboard)
186 0, // iInterface
187 // HID interface descriptor, HID 1.11 spec, section 6.2.1
188 9, // bLength
189 0x21, // bDescriptorType
190 0x11, 0x01, // bcdHID
191 0, // bCountryCode
192 1, // bNumDescriptors
193 0x22, // bDescriptorType
194 sizeof(keyboard_hid_report_desc), // wDescriptorLength
195 0,
196 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
197 7, // bLength
198 5, // bDescriptorType
199 KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
200 0x03, // bmAttributes (0x03=intr)
201 KEYBOARD_SIZE, 0, // wMaxPacketSize
202 1, // bInterval
203 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
204 9, // bLength
205 4, // bDescriptorType
206 DEBUG_INTERFACE, // bInterfaceNumber
207 0, // bAlternateSetting
208 1, // bNumEndpoints
209 0x03, // bInterfaceClass (0x03 = HID)
210 0x00, // bInterfaceSubClass
211 0x00, // bInterfaceProtocol
212 0, // iInterface
213 // HID interface descriptor, HID 1.11 spec, section 6.2.1
214 9, // bLength
215 0x21, // bDescriptorType
216 0x11, 0x01, // bcdHID
217 0, // bCountryCode
218 1, // bNumDescriptors
219 0x22, // bDescriptorType
220 sizeof(debug_hid_report_desc), // wDescriptorLength
221 0,
222 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
223 7, // bLength
224 5, // bDescriptorType
225 DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
226 0x03, // bmAttributes (0x03=intr)
227 DEBUG_TX_SIZE, 0, // wMaxPacketSize
228 1 // bInterval
229 };
230
231 // If you're desperate for a little extra code memory, these strings
232 // can be completely removed if iManufacturer, iProduct, iSerialNumber
233 // in the device desciptor are changed to zeros.
234 struct usb_string_descriptor_struct {
235 uint8_t bLength;
236 uint8_t bDescriptorType;
237 int16_t wString[];
238 };
239 static struct usb_string_descriptor_struct PROGMEM string0 = {
240 4,
241 3,
242 {0x0409}
243 };
244 static struct usb_string_descriptor_struct PROGMEM string1 = {
245 sizeof(STR_MANUFACTURER),
246 3,
247 STR_MANUFACTURER
248 };
249 static struct usb_string_descriptor_struct PROGMEM string2 = {
250 sizeof(STR_PRODUCT),
251 3,
252 STR_PRODUCT
253 };
254
255 // This table defines which descriptor data is sent for each specific
256 // request from the host (in wValue and wIndex).
257 static struct descriptor_list_struct {
258 uint16_t wValue;
259 uint16_t wIndex;
260 const uint8_t *addr;
261 uint8_t length;
262 } PROGMEM descriptor_list[] = {
263 {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
264 {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
265 {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
266 {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
267 {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
268 {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
269 {0x0300, 0x0000, (const uint8_t *)&string0, 4},
270 {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
271 {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
272 };
273 #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
274
275
276 /**************************************************************************
277 *
278 * Variables - these are the only non-stack RAM usage
279 *
280 **************************************************************************/
281
282 // zero when we are not configured, non-zero when enumerated
283 static volatile uint8_t usb_configuration=0;
284
285 // the time remaining before we transmit any partially full
286 // packet, or send a zero length packet.
287 static volatile uint8_t debug_flush_timer=0;
288
289 // which modifier keys are currently pressed
290 // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
291 // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
292 uint8_t keyboard_modifier_keys=0;
293
294 // which keys are currently pressed, up to 6 keys may be down at once
295 uint8_t keyboard_keys[6]={0,0,0,0,0,0};
296
297 // protocol setting from the host. We use exactly the same report
298 // either way, so this variable only stores the setting since we
299 // are required to be able to report which setting is in use.
300 static uint8_t keyboard_protocol=1;
301
302 // the idle configuration, how often we send the report to the
303 // host (ms * 4) even when it hasn't changed
304 static uint8_t keyboard_idle_config=125;
305
306 // count until idle timeout
307 static uint8_t keyboard_idle_count=0;
308
309 // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
310 volatile uint8_t keyboard_leds=0;
311
312
313 /**************************************************************************
314 *
315 * Public Functions - these are the API intended for the user
316 *
317 **************************************************************************/
318
319
320 // initialize USB
321 void usb_init(void)
322 {
323 HW_CONFIG();
324 USB_FREEZE(); // enable USB
325 PLL_CONFIG(); // config PLL
326 while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
327 USB_CONFIG(); // start USB clock
328 UDCON = 0; // enable attach resistor
329 usb_configuration = 0;
330 UDIEN = (1<<EORSTE)|(1<<SOFE);
331 sei();
332 }
333
334 // return 0 if the USB is not configured, or the configuration
335 // number selected by the HOST
336 uint8_t usb_configured(void)
337 {
338 return usb_configuration;
339 }
340
341
342 // perform a single keystroke
343 int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
344 {
345 int8_t r;
346
347 keyboard_modifier_keys = modifier;
348 keyboard_keys[0] = key;
349 r = usb_keyboard_send();
350 if (r) return r;
351 keyboard_modifier_keys = 0;
352 keyboard_keys[0] = 0;
353 return usb_keyboard_send();
354 }
355
356 // send the contents of keyboard_keys and keyboard_modifier_keys
357 int8_t usb_keyboard_send(void)
358 {
359 uint8_t i, intr_state, timeout;
360
361 if (!usb_configuration) return -1;
362 intr_state = SREG;
363 cli();
364 UENUM = KEYBOARD_ENDPOINT;
365 timeout = UDFNUML + 50;
366 while (1) {
367 // are we ready to transmit?
368 if (UEINTX & (1<<RWAL)) break;
369 SREG = intr_state;
370 // has the USB gone offline?
371 if (!usb_configuration) return -1;
372 // have we waited too long?
373 if (UDFNUML == timeout) return -1;
374 // get ready to try checking again
375 intr_state = SREG;
376 cli();
377 UENUM = KEYBOARD_ENDPOINT;
378 }
379 UEDATX = keyboard_modifier_keys;
380 UEDATX = 0;
381 for (i=0; i<6; i++) {
382 UEDATX = keyboard_keys[i];
383 }
384 UEINTX = 0x3A;
385 keyboard_idle_count = 0;
386 SREG = intr_state;
387 return 0;
388 }
389
390 // transmit a character. 0 returned on success, -1 on error
391 int8_t usb_debug_putchar(uint8_t c)
392 {
393 static uint8_t previous_timeout=0;
394 uint8_t timeout, intr_state;
395
396 // if we're not online (enumerated and configured), error
397 if (!usb_configuration) return -1;
398 // interrupts are disabled so these functions can be
399 // used from the main program or interrupt context,
400 // even both in the same program!
401 intr_state = SREG;
402 cli();
403 UENUM = DEBUG_TX_ENDPOINT;
404 // if we gave up due to timeout before, don't wait again
405 if (previous_timeout) {
406 if (!(UEINTX & (1<<RWAL))) {
407 SREG = intr_state;
408 return -1;
409 }
410 previous_timeout = 0;
411 }
412 // wait for the FIFO to be ready to accept data
413 timeout = UDFNUML + 4;
414 while (1) {
415 // are we ready to transmit?
416 if (UEINTX & (1<<RWAL)) break;
417 SREG = intr_state;
418 // have we waited too long?
419 if (UDFNUML == timeout) {
420 previous_timeout = 1;
421 return -1;
422 }
423 // has the USB gone offline?
424 if (!usb_configuration) return -1;
425 // get ready to try checking again
426 intr_state = SREG;
427 cli();
428 UENUM = DEBUG_TX_ENDPOINT;
429 }
430 // actually write the byte into the FIFO
431 UEDATX = c;
432 // if this completed a packet, transmit it now!
433 if (!(UEINTX & (1<<RWAL))) {
434 UEINTX = 0x3A;
435 debug_flush_timer = 0;
436 } else {
437 debug_flush_timer = 2;
438 }
439 SREG = intr_state;
440 return 0;
441 }
442
443
444 // immediately transmit any buffered output.
445 void usb_debug_flush_output(void)
446 {
447 uint8_t intr_state;
448
449 intr_state = SREG;
450 cli();
451 if (debug_flush_timer) {
452 UENUM = DEBUG_TX_ENDPOINT;
453 while ((UEINTX & (1<<RWAL))) {
454 UEDATX = 0;
455 }
456 UEINTX = 0x3A;
457 debug_flush_timer = 0;
458 }
459 SREG = intr_state;
460 }
461
462
463
464 /**************************************************************************
465 *
466 * Private Functions - not intended for general user consumption....
467 *
468 **************************************************************************/
469
470
471
472 // USB Device Interrupt - handle all device-level events
473 // the transmit buffer flushing is triggered by the start of frame
474 //
475 ISR(USB_GEN_vect)
476 {
477 uint8_t intbits, t, i;
478 static uint8_t div4=0;
479
480 intbits = UDINT;
481 UDINT = 0;
482 if (intbits & (1<<EORSTI)) {
483 UENUM = 0;
484 UECONX = 1;
485 UECFG0X = EP_TYPE_CONTROL;
486 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
487 UEIENX = (1<<RXSTPE);
488 usb_configuration = 0;
489 }
490 if ((intbits & (1<<SOFI)) && usb_configuration) {
491 t = debug_flush_timer;
492 if (t) {
493 debug_flush_timer = -- t;
494 if (!t) {
495 UENUM = DEBUG_TX_ENDPOINT;
496 while ((UEINTX & (1<<RWAL))) {
497 UEDATX = 0;
498 }
499 UEINTX = 0x3A;
500 }
501 }
502 if (keyboard_idle_config && (++div4 & 3) == 0) {
503 UENUM = KEYBOARD_ENDPOINT;
504 if (UEINTX & (1<<RWAL)) {
505 keyboard_idle_count++;
506 if (keyboard_idle_count == keyboard_idle_config) {
507 keyboard_idle_count = 0;
508 UEDATX = keyboard_modifier_keys;
509 UEDATX = 0;
510 for (i=0; i<6; i++) {
511 UEDATX = keyboard_keys[i];
512 }
513 UEINTX = 0x3A;
514 }
515 }
516 }
517 }
518 }
519
520
521
522 // Misc functions to wait for ready and send/receive packets
523 static inline void usb_wait_in_ready(void)
524 {
525 while (!(UEINTX & (1<<TXINI))) ;
526 }
527 static inline void usb_send_in(void)
528 {
529 UEINTX = ~(1<<TXINI);
530 }
531 static inline void usb_wait_receive_out(void)
532 {
533 while (!(UEINTX & (1<<RXOUTI))) ;
534 }
535 static inline void usb_ack_out(void)
536 {
537 UEINTX = ~(1<<RXOUTI);
538 }
539
540
541
542 // USB Endpoint Interrupt - endpoint 0 is handled here. The
543 // other endpoints are manipulated by the user-callable
544 // functions, and the start-of-frame interrupt.
545 //
546 ISR(USB_COM_vect)
547 {
548 uint8_t intbits;
549 const uint8_t *list;
550 const uint8_t *cfg;
551 uint8_t i, n, len, en;
552 uint8_t bmRequestType;
553 uint8_t bRequest;
554 uint16_t wValue;
555 uint16_t wIndex;
556 uint16_t wLength;
557 uint16_t desc_val;
558 const uint8_t *desc_addr;
559 uint8_t desc_length;
560
561 UENUM = 0;
562 intbits = UEINTX;
563 if (intbits & (1<<RXSTPI)) {
564 bmRequestType = UEDATX;
565 bRequest = UEDATX;
566 wValue = UEDATX;
567 wValue |= (UEDATX << 8);
568 wIndex = UEDATX;
569 wIndex |= (UEDATX << 8);
570 wLength = UEDATX;
571 wLength |= (UEDATX << 8);
572 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
573 if (bRequest == GET_DESCRIPTOR) {
574 list = (const uint8_t *)descriptor_list;
575 for (i=0; ; i++) {
576 if (i >= NUM_DESC_LIST) {
577 UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
578 return;
579 }
580 desc_val = pgm_read_word(list);
581 if (desc_val != wValue) {
582 list += sizeof(struct descriptor_list_struct);
583 continue;
584 }
585 list += 2;
586 desc_val = pgm_read_word(list);
587 if (desc_val != wIndex) {
588 list += sizeof(struct descriptor_list_struct)-2;
589 continue;
590 }
591 list += 2;
592 desc_addr = (const uint8_t *)pgm_read_word(list);
593 list += 2;
594 desc_length = pgm_read_byte(list);
595 break;
596 }
597 len = (wLength < 256) ? wLength : 255;
598 if (len > desc_length) len = desc_length;
599 do {
600 // wait for host ready for IN packet
601 do {
602 i = UEINTX;
603 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
604 if (i & (1<<RXOUTI)) return; // abort
605 // send IN packet
606 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
607 for (i = n; i; i--) {
608 UEDATX = pgm_read_byte(desc_addr++);
609 }
610 len -= n;
611 usb_send_in();
612 } while (len || n == ENDPOINT0_SIZE);
613 return;
614 }
615 if (bRequest == SET_ADDRESS) {
616 usb_send_in();
617 usb_wait_in_ready();
618 UDADDR = wValue | (1<<ADDEN);
619 return;
620 }
621 if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
622 usb_configuration = wValue;
623 usb_send_in();
624 cfg = endpoint_config_table;
625 for (i=1; i<5; i++) {
626 UENUM = i;
627 en = pgm_read_byte(cfg++);
628 UECONX = en;
629 if (en) {
630 UECFG0X = pgm_read_byte(cfg++);
631 UECFG1X = pgm_read_byte(cfg++);
632 }
633 }
634 UERST = 0x1E;
635 UERST = 0;
636 return;
637 }
638 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
639 usb_wait_in_ready();
640 UEDATX = usb_configuration;
641 usb_send_in();
642 return;
643 }
644
645 if (bRequest == GET_STATUS) {
646 usb_wait_in_ready();
647 i = 0;
648 #ifdef SUPPORT_ENDPOINT_HALT
649 if (bmRequestType == 0x82) {
650 UENUM = wIndex;
651 if (UECONX & (1<<STALLRQ)) i = 1;
652 UENUM = 0;
653 }
654 #endif
655 UEDATX = i;
656 UEDATX = 0;
657 usb_send_in();
658 return;
659 }
660 #ifdef SUPPORT_ENDPOINT_HALT
661 if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
662 && bmRequestType == 0x02 && wValue == 0) {
663 i = wIndex & 0x7F;
664 if (i >= 1 && i <= MAX_ENDPOINT) {
665 usb_send_in();
666 UENUM = i;
667 if (bRequest == SET_FEATURE) {
668 UECONX = (1<<STALLRQ)|(1<<EPEN);
669 } else {
670 UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
671 UERST = (1 << i);
672 UERST = 0;
673 }
674 return;
675 }
676 }
677 #endif
678 if (wIndex == KEYBOARD_INTERFACE) {
679 if (bmRequestType == 0xA1) {
680 if (bRequest == HID_GET_REPORT) {
681 usb_wait_in_ready();
682 UEDATX = keyboard_modifier_keys;
683 UEDATX = 0;
684 for (i=0; i<6; i++) {
685 UEDATX = keyboard_keys[i];
686 }
687 usb_send_in();
688 return;
689 }
690 if (bRequest == HID_GET_IDLE) {
691 usb_wait_in_ready();
692 UEDATX = keyboard_idle_config;
693 usb_send_in();
694 return;
695 }
696 if (bRequest == HID_GET_PROTOCOL) {
697 usb_wait_in_ready();
698 UEDATX = keyboard_protocol;
699 usb_send_in();
700 return;
701 }
702 }
703 if (bmRequestType == 0x21) {
704 if (bRequest == HID_SET_REPORT) {
705 usb_wait_receive_out();
706 keyboard_leds = UEDATX;
707 usb_ack_out();
708 usb_send_in();
709 return;
710 }
711 if (bRequest == HID_SET_IDLE) {
712 keyboard_idle_config = (wValue >> 8);
713 keyboard_idle_count = 0;
714 //usb_wait_in_ready();
715 usb_send_in();
716 return;
717 }
718 if (bRequest == HID_SET_PROTOCOL) {
719 keyboard_protocol = wValue;
720 //usb_wait_in_ready();
721 usb_send_in();
722 return;
723 }
724 }
725 }
726 if (wIndex == DEBUG_INTERFACE) {
727 if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
728 len = wLength;
729 do {
730 // wait for host ready for IN packet
731 do {
732 i = UEINTX;
733 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
734 if (i & (1<<RXOUTI)) return; // abort
735 // send IN packet
736 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
737 for (i = n; i; i--) {
738 UEDATX = 0;
739 }
740 len -= n;
741 usb_send_in();
742 } while (len || n == ENDPOINT0_SIZE);
743 return;
744 }
745 }
746 }
747 UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
748 }
749
750
Imprint / Impressum