]> git.donarmstrong.com Git - kiibohd-controller.git/blob - USB/pjrc/avr/usb_keyboard_debug.c
Completing CMake variable generation for USB parameters (AVR Support)
[kiibohd-controller.git] / USB / pjrc / avr / 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 // 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
40 // operating systems.
41 #define SUPPORT_ENDPOINT_HALT
42
43
44
45 /**************************************************************************
46  *
47  *  Endpoint Buffer Configuration
48  *
49  **************************************************************************/
50
51 #define ENDPOINT0_SIZE          32
52
53 #define KEYBOARD_INTERFACE      0
54 #define KEYBOARD_ENDPOINT       3
55 #define KEYBOARD_SIZE           8
56 #define KEYBOARD_BUFFER         EP_DOUBLE_BUFFER
57
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
62
63 static const uint8_t PROGMEM endpoint_config_table[] = {
64         0,
65         0,
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
68 };
69
70
71 /**************************************************************************
72  *
73  *  Descriptor Data
74  *
75  **************************************************************************/
76
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!
82
83
84 static const uint8_t PROGMEM device_descriptor[] = {
85         18,                                     // bLength
86         1,                                      // bDescriptorType
87         0x00, 0x02,                             // bcdUSB
88         0,                                      // bDeviceClass
89         0,                                      // bDeviceSubClass
90         0,                                      // bDeviceProtocol
91         ENDPOINT0_SIZE,                         // bMaxPacketSize0
92         LSB(VENDOR_ID), MSB(VENDOR_ID),         // idVendor
93         LSB(PRODUCT_ID), MSB(PRODUCT_ID),       // idProduct
94         0x00, 0x01,                             // bcdDevice
95         1,                                      // iManufacturer
96         2,                                      // iProduct
97         3,                                      // iSerialNumber
98         1                                       // bNumConfigurations
99 };
100
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
135 };
136
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
146         0x09, 0x75,                             // usage
147         0x81, 0x02,                             // Input (array)
148         0xC0                                    // end collection
149 };
150
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
156         9,                                      // bLength;
157         2,                                      // bDescriptorType;
158         LSB(CONFIG1_DESC_SIZE),                 // wTotalLength
159         MSB(CONFIG1_DESC_SIZE),
160         2,                                      // bNumInterfaces
161         1,                                      // bConfigurationValue
162         0,                                      // iConfiguration
163         0xC0,                                   // bmAttributes
164         50,                                     // bMaxPower
165         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
166         9,                                      // bLength
167         4,                                      // bDescriptorType
168         KEYBOARD_INTERFACE,                     // bInterfaceNumber
169         0,                                      // bAlternateSetting
170         1,                                      // bNumEndpoints
171         0x03,                                   // bInterfaceClass (0x03 = HID)
172         0x01,                                   // bInterfaceSubClass (0x01 = Boot)
173         0x01,                                   // bInterfaceProtocol (0x01 = Keyboard)
174         0,                                      // iInterface
175         // HID interface descriptor, HID 1.11 spec, section 6.2.1
176         9,                                      // bLength
177         0x21,                                   // bDescriptorType
178         0x11, 0x01,                             // bcdHID
179         0,                                      // bCountryCode
180         1,                                      // bNumDescriptors
181         0x22,                                   // bDescriptorType
182         sizeof(keyboard_hid_report_desc),       // wDescriptorLength
183         0,
184         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
185         7,                                      // bLength
186         5,                                      // bDescriptorType
187         KEYBOARD_ENDPOINT | 0x80,               // bEndpointAddress
188         0x03,                                   // bmAttributes (0x03=intr)
189         KEYBOARD_SIZE, 0,                       // wMaxPacketSize
190         1,                                      // bInterval
191         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
192         9,                                      // bLength
193         4,                                      // bDescriptorType
194         DEBUG_INTERFACE,                        // bInterfaceNumber
195         0,                                      // bAlternateSetting
196         1,                                      // bNumEndpoints
197         0x03,                                   // bInterfaceClass (0x03 = HID)
198         0x00,                                   // bInterfaceSubClass
199         0x00,                                   // bInterfaceProtocol
200         0,                                      // iInterface
201         // HID interface descriptor, HID 1.11 spec, section 6.2.1
202         9,                                      // bLength
203         0x21,                                   // bDescriptorType
204         0x11, 0x01,                             // bcdHID
205         0,                                      // bCountryCode
206         1,                                      // bNumDescriptors
207         0x22,                                   // bDescriptorType
208         sizeof(debug_hid_report_desc),          // wDescriptorLength
209         0,
210         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
211         7,                                      // bLength
212         5,                                      // bDescriptorType
213         DEBUG_TX_ENDPOINT | 0x80,               // bEndpointAddress
214         0x03,                                   // bmAttributes (0x03=intr)
215         DEBUG_TX_SIZE, 0,                       // wMaxPacketSize
216         1                                       // bInterval
217 };
218
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 {
223         uint8_t bLength;
224         uint8_t bDescriptorType;
225         int16_t wString[];
226 };
227 static const struct usb_string_descriptor_struct PROGMEM string0 = {
228         4,
229         3,
230         {0x0409}
231 };
232 static const struct usb_string_descriptor_struct PROGMEM string1 = {
233         sizeof(STR_MANUFACTURER),
234         3,
235         STR_MANUFACTURER
236 };
237 static const struct usb_string_descriptor_struct PROGMEM string2 = {
238         sizeof(STR_PRODUCT),
239         3,
240         STR_PRODUCT
241 };
242 static const struct usb_string_descriptor_struct PROGMEM string3 = {
243         sizeof(STR_SERIAL),
244         3,
245         STR_SERIAL
246 };
247
248 // This table defines which descriptor data is sent for each specific
249 // request from the host (in wValue and wIndex).
250 static const struct descriptor_list_struct {
251         uint16_t        wValue;
252         uint16_t        wIndex;
253         const uint8_t   *addr;
254         uint8_t         length;
255 } PROGMEM descriptor_list[] = {
256         {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
257         {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
258         {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
259         {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
260         {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
261         {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
262         {0x0300, 0x0000, (const uint8_t *)&string0, 4},
263         {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
264         {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)},
265         {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)}
266 };
267 #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
268
269
270 /**************************************************************************
271  *
272  *  Variables - these are the only non-stack RAM usage
273  *
274  **************************************************************************/
275
276 // zero when we are not configured, non-zero when enumerated
277 static volatile uint8_t usb_configuration=0;
278
279 // the time remaining before we transmit any partially full
280 // packet, or send a zero length packet.
281 static volatile uint8_t debug_flush_timer=0;
282
283
284 /**************************************************************************
285  *
286  *  Public Functions - these are the API intended for the user
287  *
288  **************************************************************************/
289
290
291 // initialize USB
292 void usb_init(void)
293 {
294         HW_CONFIG();
295         USB_FREEZE();                           // enable USB
296         PLL_CONFIG();                           // config PLL
297         while (!(PLLCSR & (1<<PLOCK))) ;        // wait for PLL lock
298         USB_CONFIG();                           // start USB clock
299         UDCON = 0;                              // enable attach resistor
300         usb_configuration = 0;
301         UDIEN = (1<<EORSTE)|(1<<SOFE);
302         sei();
303 }
304
305 // return 0 if the USB is not configured, or the configuration
306 // number selected by the HOST
307 uint8_t usb_configured(void)
308 {
309         return usb_configuration;
310 }
311
312 // send the contents of USBKeys_Array and USBKeys_Modifiers
313 int8_t usb_keyboard_send(void)
314 {
315         uint8_t i, intr_state, timeout;
316
317         if (!usb_configuration) return -1;
318         intr_state = SREG;
319         cli();
320         UENUM = KEYBOARD_ENDPOINT;
321         timeout = UDFNUML + 50;
322         while (1) {
323                 // are we ready to transmit?
324                 if (UEINTX & (1<<RWAL)) break;
325                 SREG = intr_state;
326                 // has the USB gone offline?
327                 if (!usb_configuration) return -1;
328                 // have we waited too long?
329                 if (UDFNUML == timeout) return -1;
330                 // get ready to try checking again
331                 intr_state = SREG;
332                 cli();
333                 UENUM = KEYBOARD_ENDPOINT;
334         }
335         UEDATX = USBKeys_Modifiers;
336         UEDATX = 0;
337         for (i=0; i<6; i++) {
338                 UEDATX = USBKeys_Array[i];
339         }
340         UEINTX = 0x3A;
341         USBKeys_Idle_Count = 0;
342         SREG = intr_state;
343         return 0;
344 }
345
346 // transmit a character.  0 returned on success, -1 on error
347 int8_t usb_debug_putchar(uint8_t c)
348 {
349         static uint8_t previous_timeout=0;
350         uint8_t timeout, intr_state;
351
352         // if we're not online (enumerated and configured), error
353         if (!usb_configuration) return -1;
354         // interrupts are disabled so these functions can be
355         // used from the main program or interrupt context,
356         // even both in the same program!
357         intr_state = SREG;
358         cli();
359         UENUM = DEBUG_TX_ENDPOINT;
360         // if we gave up due to timeout before, don't wait again
361         if (previous_timeout) {
362                 if (!(UEINTX & (1<<RWAL))) {
363                         SREG = intr_state;
364                         return -1;
365                 }
366                 previous_timeout = 0;
367         }
368         // wait for the FIFO to be ready to accept data
369         timeout = UDFNUML + 4;
370         while (1) {
371                 // are we ready to transmit?
372                 if (UEINTX & (1<<RWAL)) break;
373                 SREG = intr_state;
374                 // have we waited too long?
375                 if (UDFNUML == timeout) {
376                         previous_timeout = 1;
377                         return -1;
378                 }
379                 // has the USB gone offline?
380                 if (!usb_configuration) return -1;
381                 // get ready to try checking again
382                 intr_state = SREG;
383                 cli();
384                 UENUM = DEBUG_TX_ENDPOINT;
385         }
386         // actually write the byte into the FIFO
387         UEDATX = c;
388         // if this completed a packet, transmit it now!
389         if (!(UEINTX & (1<<RWAL))) {
390                 UEINTX = 0x3A;
391                 debug_flush_timer = 0;
392         } else {
393                 debug_flush_timer = 2;
394         }
395         SREG = intr_state;
396         return 0;
397 }
398
399
400 // immediately transmit any buffered output.
401 void usb_debug_flush_output(void)
402 {
403         uint8_t intr_state;
404
405         intr_state = SREG;
406         cli();
407         if (debug_flush_timer) {
408                 UENUM = DEBUG_TX_ENDPOINT;
409                 while ((UEINTX & (1<<RWAL))) {
410                         UEDATX = 0;
411                 }
412                 UEINTX = 0x3A;
413                 debug_flush_timer = 0;
414         }
415         SREG = intr_state;
416 }
417
418
419
420 /**************************************************************************
421  *
422  *  Private Functions - not intended for general user consumption....
423  *
424  **************************************************************************/
425
426
427
428 // USB Device Interrupt - handle all device-level events
429 // the transmit buffer flushing is triggered by the start of frame
430 //
431 ISR(USB_GEN_vect)
432 {
433         uint8_t intbits, t, i;
434         static uint8_t div4=0;
435
436         intbits = UDINT;
437         UDINT = 0;
438         if (intbits & (1<<EORSTI)) {
439                 UENUM = 0;
440                 UECONX = 1;
441                 UECFG0X = EP_TYPE_CONTROL;
442                 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
443                 UEIENX = (1<<RXSTPE);
444                 usb_configuration = 0;
445         }
446         if ((intbits & (1<<SOFI)) && usb_configuration) {
447                 t = debug_flush_timer;
448                 if (t) {
449                         debug_flush_timer = -- t;
450                         if (!t) {
451                                 UENUM = DEBUG_TX_ENDPOINT;
452                                 while ((UEINTX & (1<<RWAL))) {
453                                         UEDATX = 0;
454                                 }
455                                 UEINTX = 0x3A;
456                         }
457                 }
458                 if (USBKeys_Idle_Config && (++div4 & 3) == 0) {
459                         UENUM = KEYBOARD_ENDPOINT;
460                         if (UEINTX & (1<<RWAL)) {
461                                 USBKeys_Idle_Count++;
462                                 if (USBKeys_Idle_Count == USBKeys_Idle_Config) {
463                                         USBKeys_Idle_Count = 0;
464                                         UEDATX = USBKeys_Modifiers;
465                                         UEDATX = 0;
466                                         for (i=0; i<6; i++) {
467                                                 UEDATX = USBKeys_Array[i];
468                                         }
469                                         UEINTX = 0x3A;
470                                 }
471                         }
472                 }
473         }
474 }
475
476
477
478 // Misc functions to wait for ready and send/receive packets
479 static inline void usb_wait_in_ready(void)
480 {
481         while (!(UEINTX & (1<<TXINI))) ;
482 }
483 static inline void usb_send_in(void)
484 {
485         UEINTX = ~(1<<TXINI);
486 }
487 static inline void usb_wait_receive_out(void)
488 {
489         while (!(UEINTX & (1<<RXOUTI))) ;
490 }
491 static inline void usb_ack_out(void)
492 {
493         UEINTX = ~(1<<RXOUTI);
494 }
495
496
497
498 // USB Endpoint Interrupt - endpoint 0 is handled here.  The
499 // other endpoints are manipulated by the user-callable
500 // functions, and the start-of-frame interrupt.
501 //
502 ISR(USB_COM_vect)
503 {
504         uint8_t intbits;
505         const uint8_t *list;
506         const uint8_t *cfg;
507         uint8_t i, n, len, en;
508         uint8_t bmRequestType;
509         uint8_t bRequest;
510         uint16_t wValue;
511         uint16_t wIndex;
512         uint16_t wLength;
513         uint16_t desc_val;
514         const uint8_t *desc_addr;
515         uint8_t desc_length;
516
517         UENUM = 0;
518         intbits = UEINTX;
519         if (intbits & (1<<RXSTPI)) {
520                 bmRequestType = UEDATX;
521                 bRequest = UEDATX;
522                 wValue = UEDATX;
523                 wValue |= (UEDATX << 8);
524                 wIndex = UEDATX;
525                 wIndex |= (UEDATX << 8);
526                 wLength = UEDATX;
527                 wLength |= (UEDATX << 8);
528                 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
529                 if (bRequest == GET_DESCRIPTOR) {
530                         list = (const uint8_t *)descriptor_list;
531                         for (i=0; ; i++) {
532                                 if (i >= NUM_DESC_LIST) {
533                                         UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
534                                         return;
535                                 }
536                                 desc_val = pgm_read_word(list);
537                                 if (desc_val != wValue) {
538                                         list += sizeof(struct descriptor_list_struct);
539                                         continue;
540                                 }
541                                 list += 2;
542                                 desc_val = pgm_read_word(list);
543                                 if (desc_val != wIndex) {
544                                         list += sizeof(struct descriptor_list_struct)-2;
545                                         continue;
546                                 }
547                                 list += 2;
548                                 desc_addr = (const uint8_t *)pgm_read_word(list);
549                                 list += 2;
550                                 desc_length = pgm_read_byte(list);
551                                 break;
552                         }
553                         len = (wLength < 256) ? wLength : 255;
554                         if (len > desc_length) len = desc_length;
555                         do {
556                                 // wait for host ready for IN packet
557                                 do {
558                                         i = UEINTX;
559                                 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
560                                 if (i & (1<<RXOUTI)) return;    // abort
561                                 // send IN packet
562                                 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
563                                 for (i = n; i; i--) {
564                                         UEDATX = pgm_read_byte(desc_addr++);
565                                 }
566                                 len -= n;
567                                 usb_send_in();
568                         } while (len || n == ENDPOINT0_SIZE);
569                         return;
570                 }
571                 if (bRequest == SET_ADDRESS) {
572                         usb_send_in();
573                         usb_wait_in_ready();
574                         UDADDR = wValue | (1<<ADDEN);
575                         return;
576                 }
577                 if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
578                         usb_configuration = wValue;
579                         usb_send_in();
580                         cfg = endpoint_config_table;
581                         for (i=1; i<5; i++) {
582                                 UENUM = i;
583                                 en = pgm_read_byte(cfg++);
584                                 UECONX = en;
585                                 if (en) {
586                                         UECFG0X = pgm_read_byte(cfg++);
587                                         UECFG1X = pgm_read_byte(cfg++);
588                                 }
589                         }
590                         UERST = 0x1E;
591                         UERST = 0;
592                         return;
593                 }
594                 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
595                         usb_wait_in_ready();
596                         UEDATX = usb_configuration;
597                         usb_send_in();
598                         return;
599                 }
600
601                 if (bRequest == GET_STATUS) {
602                         usb_wait_in_ready();
603                         i = 0;
604                         #ifdef SUPPORT_ENDPOINT_HALT
605                         if (bmRequestType == 0x82) {
606                                 UENUM = wIndex;
607                                 if (UECONX & (1<<STALLRQ)) i = 1;
608                                 UENUM = 0;
609                         }
610                         #endif
611                         UEDATX = i;
612                         UEDATX = 0;
613                         usb_send_in();
614                         return;
615                 }
616                 #ifdef SUPPORT_ENDPOINT_HALT
617                 if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
618                   && bmRequestType == 0x02 && wValue == 0) {
619                         i = wIndex & 0x7F;
620                         if (i >= 1 && i <= MAX_ENDPOINT) {
621                                 usb_send_in();
622                                 UENUM = i;
623                                 if (bRequest == SET_FEATURE) {
624                                         UECONX = (1<<STALLRQ)|(1<<EPEN);
625                                 } else {
626                                         UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
627                                         UERST = (1 << i);
628                                         UERST = 0;
629                                 }
630                                 return;
631                         }
632                 }
633                 #endif
634                 if (wIndex == KEYBOARD_INTERFACE) {
635                         if (bmRequestType == 0xA1) {
636                                 if (bRequest == HID_GET_REPORT) {
637                                         usb_wait_in_ready();
638                                         UEDATX = USBKeys_Modifiers;
639                                         UEDATX = 0;
640                                         for (i=0; i<6; i++) {
641                                                 UEDATX = USBKeys_Array[i];
642                                         }
643                                         usb_send_in();
644                                         return;
645                                 }
646                                 if (bRequest == HID_GET_IDLE) {
647                                         usb_wait_in_ready();
648                                         UEDATX = USBKeys_Idle_Config;
649                                         usb_send_in();
650                                         return;
651                                 }
652                                 if (bRequest == HID_GET_PROTOCOL) {
653                                         usb_wait_in_ready();
654                                         UEDATX = USBKeys_Protocol;
655                                         usb_send_in();
656                                         return;
657                                 }
658                         }
659                         if (bmRequestType == 0x21) {
660                                 if (bRequest == HID_SET_REPORT) {
661                                         usb_wait_receive_out();
662                                         USBKeys_LEDs = UEDATX;
663                                         usb_ack_out();
664                                         usb_send_in();
665                                         return;
666                                 }
667                                 if (bRequest == HID_SET_IDLE) {
668                                         USBKeys_Idle_Config = (wValue >> 8);
669                                         USBKeys_Idle_Count = 0;
670                                         //usb_wait_in_ready();
671                                         usb_send_in();
672                                         return;
673                                 }
674                                 if (bRequest == HID_SET_PROTOCOL) {
675                                         USBKeys_Protocol = wValue;
676                                         //usb_wait_in_ready();
677                                         usb_send_in();
678                                         return;
679                                 }
680                         }
681                 }
682                 if (wIndex == DEBUG_INTERFACE) {
683                         if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
684                                 len = wLength;
685                                 do {
686                                         // wait for host ready for IN packet
687                                         do {
688                                                 i = UEINTX;
689                                         } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
690                                         if (i & (1<<RXOUTI)) return;    // abort
691                                         // send IN packet
692                                         n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
693                                         for (i = n; i; i--) {
694                                                 UEDATX = 0;
695                                         }
696                                         len -= n;
697                                         usb_send_in();
698                                 } while (len || n == ENDPOINT0_SIZE);
699                                 return;
700                         }
701                 }
702         }
703         UECONX = (1<<STALLRQ) | (1<<EPEN);      // stall
704 }
705