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