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