]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Output/pjrcUSB/avr/usb_keyboard_serial.c
5c3e9d65e6dddbd21ec1229f0f2570f016217aa7
[kiibohd-controller.git] / Output / pjrcUSB / avr / usb_keyboard_serial.c
1 /* USB Keyboard and CDC Serial Device for Teensy USB Development Board
2  * Copyright (c) 2009 PJRC.COM, LLC
3  * Modifications by Jacob Alexander (2011-2014)
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
25 // Local Includes
26 #include "usb_keyboard_serial.h"
27 #include <print.h>
28
29
30 // ----- Variables -----
31
32 // zero when we are not configured, non-zero when enumerated
33 static volatile uint8_t usb_configuration = 0;
34
35 // the time remaining before we transmit any partially full
36 // packet, or send a zero length packet.
37 static volatile uint8_t transmit_flush_timer = 0;
38 static uint8_t transmit_previous_timeout = 0;
39
40 // serial port settings (baud rate, control signals, etc) set
41 // by the PC.  These are ignored, but kept in RAM.
42 static uint8_t cdc_line_coding[7] = {0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08};
43 static uint8_t cdc_line_rtsdtr = 0;
44
45
46
47 // ----- USB Keyboard Functions -----
48
49 // Sends normal keyboard out to host
50 // NOTE: Make sure to match the descriptor
51 void usb_keyboard_toHost()
52 {
53         uint8_t i;
54
55         // Modifiers
56         UEDATX = USBKeys_Modifiers;
57
58         // Reserved Byte
59         UEDATX = 0x00;
60
61         // Normal Keys, only supports 6 in Boot mode
62         for ( i = 0; i < 6; i++)
63         {
64                 UEDATX = USBKeys_Keys[i];
65         }
66         UEINTX = 0x00;
67 }
68
69 // send the contents of USBKeys_Keys and USBKeys_Modifiers
70 inline void usb_keyboard_send()
71 {
72         uint8_t intr_state, timeout;
73
74         intr_state = SREG;
75         timeout = UDFNUML + 50;
76
77         // Ready to transmit keypresses?
78         do
79         {
80                 SREG = intr_state;
81
82                 // has the USB gone offline? or exceeded timeout?
83                 if ( !usb_configuration || UDFNUML == timeout )
84                 {
85                         erro_print("USB Offline? Timeout?");
86                         return;
87                 }
88
89                 // get ready to try checking again
90                 intr_state = SREG;
91                 cli();
92
93                 // If not using Boot protocol, send NKRO
94                 UENUM = USBKeys_Protocol ? KEYBOARD_NKRO_ENDPOINT : KEYBOARD_ENDPOINT;
95         } while ( !( UEINTX & (1 << RWAL) ) );
96
97         switch ( USBKeys_Protocol )
98         {
99         // Send boot keyboard interrupt packet(s)
100         case 0:
101                 usb_keyboard_toHost();
102                 USBKeys_Changed = USBKeyChangeState_None;
103                 break;
104
105         // Send NKRO keyboard interrupts packet(s)
106         case 1:
107                 // Check modifiers
108                 if ( USBKeys_Changed & USBKeyChangeState_Modifiers )
109                 {
110                         UEDATX = 0x01; // ID
111                         UEDATX = USBKeys_Modifiers;
112                         UEINTX = 0; // Finished with ID
113
114                         USBKeys_Changed &= ~USBKeyChangeState_Modifiers; // Mark sent
115                 }
116                 // Check main key section
117                 else if ( USBKeys_Changed & USBKeyChangeState_MainKeys )
118                 {
119                         UEDATX = 0x03; // ID
120
121                         // 4-164 (first 20 bytes)
122                         for ( uint8_t byte = 0; byte < 20; byte++ )
123                                 UEDATX = USBKeys_Keys[ byte ];
124
125                         UEINTX = 0; // Finished with ID
126
127                         USBKeys_Changed &= ~USBKeyChangeState_MainKeys; // Mark sent
128                 }
129                 // Check secondary key section
130                 else if ( USBKeys_Changed & USBKeyChangeState_SecondaryKeys )
131                 {
132                         UEDATX = 0x04; // ID
133
134                         // 176-221 (last 6 bytes)
135                         for ( uint8_t byte = 20; byte < 26; byte++ )
136                                 UEDATX = USBKeys_Keys[ byte ];
137
138                         UEINTX = 0; // Finished with ID
139
140                         USBKeys_Changed &= ~USBKeyChangeState_SecondaryKeys; // Mark sent
141                 }
142                 // Check system control keys
143                 else if ( USBKeys_Changed & USBKeyChangeState_System )
144                 {
145                         UEDATX = 0x05; // ID
146                         UEDATX = USBKeys_SysCtrl;
147                         UEINTX = 0; // Finished with ID
148
149                         USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent
150                 }
151                 // Check consumer control keys
152                 else if ( USBKeys_Changed & USBKeyChangeState_Consumer )
153                 {
154                         UEDATX = 0x06; // ID
155                         UEDATX = (uint8_t)(USBKeys_ConsCtrl & 0x00FF);
156                         UEDATX = (uint8_t)(USBKeys_ConsCtrl >> 8);
157                         UEINTX = 0; // Finished with ID
158
159                         USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent
160                 }
161
162                 break;
163         }
164
165         USBKeys_Idle_Count = 0;
166         SREG = intr_state;
167 }
168
169
170
171 // ----- USB Virtual Serial Port (CDC) Functions -----
172
173 // get the next character, or -1 if nothing received
174 int16_t usb_serial_getchar(void)
175 {
176         uint8_t c, intr_state;
177
178         // interrupts are disabled so these functions can be
179         // used from the main program or interrupt context,
180         // even both in the same program!
181         intr_state = SREG;
182         cli();
183         if (!usb_configuration) {
184                 SREG = intr_state;
185                 return -1;
186         }
187         UENUM = CDC_RX_ENDPOINT;
188         retry:
189         c = UEINTX;
190         if (!(c & (1<<RWAL))) {
191                 // no data in buffer
192                 if (c & (1<<RXOUTI)) {
193                         UEINTX = 0x6B;
194                         goto retry;
195                 }
196                 SREG = intr_state;
197                 return -2;
198         }
199         // take one byte out of the buffer
200         c = UEDATX;
201         // if buffer completely used, release it
202         if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
203         SREG = intr_state;
204         return c;
205 }
206
207 // number of bytes available in the receive buffer
208 uint8_t usb_serial_available(void)
209 {
210         uint8_t n=0, i, intr_state;
211
212         intr_state = SREG;
213         cli();
214         if (usb_configuration) {
215                 UENUM = CDC_RX_ENDPOINT;
216                 n = UEBCLX;
217                 if (!n) {
218                         i = UEINTX;
219                         if (i & (1<<RXOUTI) && !(i & (1<<RWAL))) UEINTX = 0x6B;
220                 }
221         }
222         SREG = intr_state;
223         return n;
224 }
225
226 // discard any buffered input
227 void usb_serial_flush_input(void)
228 {
229         uint8_t intr_state;
230
231         if (usb_configuration) {
232                 intr_state = SREG;
233                 cli();
234                 UENUM = CDC_RX_ENDPOINT;
235                 while ((UEINTX & (1<<RWAL))) {
236                         UEINTX = 0x6B;
237                 }
238                 SREG = intr_state;
239         }
240 }
241
242 // transmit a character.  0 returned on success, -1 on error
243 int8_t usb_serial_putchar(uint8_t c)
244 {
245         uint8_t timeout, intr_state;
246
247         // if we're not online (enumerated and configured), error
248         if (!usb_configuration) return -1;
249         // interrupts are disabled so these functions can be
250         // used from the main program or interrupt context,
251         // even both in the same program!
252         intr_state = SREG;
253         cli();
254         UENUM = CDC_TX_ENDPOINT;
255         // if we gave up due to timeout before, don't wait again
256         if (transmit_previous_timeout) {
257                 if (!(UEINTX & (1<<RWAL))) {
258                         SREG = intr_state;
259                         return -1;
260                 }
261                 transmit_previous_timeout = 0;
262         }
263         // wait for the FIFO to be ready to accept data
264         timeout = UDFNUML + TRANSMIT_TIMEOUT;
265         while (1) {
266                 // are we ready to transmit?
267                 if (UEINTX & (1<<RWAL)) break;
268                 SREG = intr_state;
269                 // have we waited too long?  This happens if the user
270                 // is not running an application that is listening
271                 if (UDFNUML == timeout) {
272                         transmit_previous_timeout = 1;
273                         return -1;
274                 }
275                 // has the USB gone offline?
276                 if (!usb_configuration) return -1;
277                 // get ready to try checking again
278                 intr_state = SREG;
279                 cli();
280                 UENUM = CDC_TX_ENDPOINT;
281         }
282         // actually write the byte into the FIFO
283         UEDATX = c;
284         // if this completed a packet, transmit it now!
285         if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
286         transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
287         SREG = intr_state;
288         return 0;
289 }
290
291
292 // transmit a character, but do not wait if the buffer is full,
293 //   0 returned on success, -1 on buffer full or error
294 int8_t usb_serial_putchar_nowait(uint8_t c)
295 {
296         uint8_t intr_state;
297
298         if (!usb_configuration) return -1;
299         intr_state = SREG;
300         cli();
301         UENUM = CDC_TX_ENDPOINT;
302         if (!(UEINTX & (1<<RWAL))) {
303                 // buffer is full
304                 SREG = intr_state;
305                 return -2;
306         }
307         // actually write the byte into the FIFO
308         UEDATX = c;
309                 // if this completed a packet, transmit it now!
310         if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
311         transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
312         SREG = intr_state;
313         return 0;
314 }
315
316 // transmit a buffer.
317 //  0 returned on success, -1 on error
318 // This function is optimized for speed!  Each call takes approx 6.1 us overhead
319 // plus 0.25 us per byte.  12 Mbit/sec USB has 8.67 us per-packet overhead and
320 // takes 0.67 us per byte.  If called with 64 byte packet-size blocks, this function
321 // can transmit at full USB speed using 43% CPU time.  The maximum theoretical speed
322 // is 19 packets per USB frame, or 1216 kbytes/sec.  However, bulk endpoints have the
323 // lowest priority, so any other USB devices will likely reduce the speed.  Speed
324 // can also be limited by how quickly the PC-based software reads data, as the host
325 // controller in the PC will not allocate bandwitdh without a pending read request.
326 // (thanks to Victor Suarez for testing and feedback and initial code)
327
328 int8_t usb_serial_write(const char *buffer, uint16_t size)
329 {
330         uint8_t timeout, intr_state, write_size;
331
332         // if we're not online (enumerated and configured), error
333         if (!usb_configuration) return -1;
334         // interrupts are disabled so these functions can be
335         // used from the main program or interrupt context,
336         // even both in the same program!
337         intr_state = SREG;
338         cli();
339         UENUM = CDC_TX_ENDPOINT;
340         // if we gave up due to timeout before, don't wait again
341         /*
342         if (transmit_previous_timeout) {
343                 if (!(UEINTX & (1<<RWAL))) {
344                         SREG = intr_state;
345                         return -2;
346                 }
347                 transmit_previous_timeout = 0;
348         }
349         */
350         // each iteration of this loop transmits a packet
351         while (size) {
352                 // wait for the FIFO to be ready to accept data
353                 timeout = UDFNUML + TRANSMIT_TIMEOUT;
354                 while (1) {
355                         // are we ready to transmit?
356                         if (UEINTX & (1<<RWAL)) break;
357                         SREG = intr_state;
358                         // have we waited too long?  This happens if the user
359                         // is not running an application that is listening
360                         if (UDFNUML == timeout) {
361                                 transmit_previous_timeout = 1;
362                                 return -3;
363                         }
364                         // has the USB gone offline?
365                         if (!usb_configuration) return -4;
366                         // get ready to try checking again
367                         intr_state = SREG;
368                         cli();
369                         UENUM = CDC_TX_ENDPOINT;
370                 }
371
372                 // compute how many bytes will fit into the next packet
373                 write_size = CDC_TX_SIZE - UEBCLX;
374                 if (write_size > size) write_size = size;
375                 size -= write_size;
376
377                 // write the packet
378                 switch (write_size) {
379                         #if (CDC_TX_SIZE == 64)
380                         case 64: UEDATX = *buffer++;
381                         case 63: UEDATX = *buffer++;
382                         case 62: UEDATX = *buffer++;
383                         case 61: UEDATX = *buffer++;
384                         case 60: UEDATX = *buffer++;
385                         case 59: UEDATX = *buffer++;
386                         case 58: UEDATX = *buffer++;
387                         case 57: UEDATX = *buffer++;
388                         case 56: UEDATX = *buffer++;
389                         case 55: UEDATX = *buffer++;
390                         case 54: UEDATX = *buffer++;
391                         case 53: UEDATX = *buffer++;
392                         case 52: UEDATX = *buffer++;
393                         case 51: UEDATX = *buffer++;
394                         case 50: UEDATX = *buffer++;
395                         case 49: UEDATX = *buffer++;
396                         case 48: UEDATX = *buffer++;
397                         case 47: UEDATX = *buffer++;
398                         case 46: UEDATX = *buffer++;
399                         case 45: UEDATX = *buffer++;
400                         case 44: UEDATX = *buffer++;
401                         case 43: UEDATX = *buffer++;
402                         case 42: UEDATX = *buffer++;
403                         case 41: UEDATX = *buffer++;
404                         case 40: UEDATX = *buffer++;
405                         case 39: UEDATX = *buffer++;
406                         case 38: UEDATX = *buffer++;
407                         case 37: UEDATX = *buffer++;
408                         case 36: UEDATX = *buffer++;
409                         case 35: UEDATX = *buffer++;
410                         case 34: UEDATX = *buffer++;
411                         case 33: UEDATX = *buffer++;
412                         #endif
413                         #if (CDC_TX_SIZE >= 32)
414                         case 32: UEDATX = *buffer++;
415                         case 31: UEDATX = *buffer++;
416                         case 30: UEDATX = *buffer++;
417                         case 29: UEDATX = *buffer++;
418                         case 28: UEDATX = *buffer++;
419                         case 27: UEDATX = *buffer++;
420                         case 26: UEDATX = *buffer++;
421                         case 25: UEDATX = *buffer++;
422                         case 24: UEDATX = *buffer++;
423                         case 23: UEDATX = *buffer++;
424                         case 22: UEDATX = *buffer++;
425                         case 21: UEDATX = *buffer++;
426                         case 20: UEDATX = *buffer++;
427                         case 19: UEDATX = *buffer++;
428                         case 18: UEDATX = *buffer++;
429                         case 17: UEDATX = *buffer++;
430                         #endif
431                         #if (CDC_TX_SIZE >= 16)
432                         case 16: UEDATX = *buffer++;
433                         case 15: UEDATX = *buffer++;
434                         case 14: UEDATX = *buffer++;
435                         case 13: UEDATX = *buffer++;
436                         case 12: UEDATX = *buffer++;
437                         case 11: UEDATX = *buffer++;
438                         case 10: UEDATX = *buffer++;
439                         case  9: UEDATX = *buffer++;
440                         #endif
441                         case  8: UEDATX = *buffer++;
442                         case  7: UEDATX = *buffer++;
443                         case  6: UEDATX = *buffer++;
444                         case  5: UEDATX = *buffer++;
445                         case  4: UEDATX = *buffer++;
446                         case  3: UEDATX = *buffer++;
447                         case  2: UEDATX = *buffer++;
448                         default:
449                         case  1: UEDATX = *buffer++;
450                         case  0: break;
451                 }
452                 // if this completed a packet, transmit it now!
453                 if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
454                 transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
455                 SREG = intr_state;
456         }
457         return 0;
458 }
459
460 // immediately transmit any buffered output.
461 // This doesn't actually transmit the data - that is impossible!
462 // USB devices only transmit when the host allows, so the best
463 // we can do is release the FIFO buffer for when the host wants it
464 void usb_serial_flush_output(void)
465 {
466         uint8_t intr_state;
467
468         intr_state = SREG;
469         cli();
470         if (transmit_flush_timer) {
471                 UENUM = CDC_TX_ENDPOINT;
472                 UEINTX = 0x3A;
473                 transmit_flush_timer = 0;
474         }
475         SREG = intr_state;
476 }
477
478 // functions to read the various async serial settings.  These
479 // aren't actually used by USB at all (communication is always
480 // at full USB speed), but they are set by the host so we can
481 // set them properly if we're converting the USB to a real serial
482 // communication
483 uint32_t usb_serial_get_baud(void)
484 {
485         uint32_t *baud = (uint32_t*)cdc_line_coding;
486         return *baud;
487 }
488 uint8_t usb_serial_get_stopbits(void)
489 {
490         return cdc_line_coding[4];
491 }
492 uint8_t usb_serial_get_paritytype(void)
493 {
494         return cdc_line_coding[5];
495 }
496 uint8_t usb_serial_get_numbits(void)
497 {
498         return cdc_line_coding[6];
499 }
500 uint8_t usb_serial_get_control(void)
501 {
502         return cdc_line_rtsdtr;
503 }
504
505 // write the control signals, DCD, DSR, RI, etc
506 // There is no CTS signal.  If software on the host has transmitted
507 // data to you but you haven't been calling the getchar function,
508 // it remains buffered (either here or on the host) and can not be
509 // lost because you weren't listening at the right time, like it
510 // would in real serial communication.
511 int8_t usb_serial_set_control(uint8_t signals)
512 {
513         uint8_t intr_state;
514
515         intr_state = SREG;
516         cli();
517         if (!usb_configuration) {
518                 // we're not enumerated/configured
519                 SREG = intr_state;
520                 return -1;
521         }
522
523         UENUM = CDC_ACM_ENDPOINT;
524         if (!(UEINTX & (1<<RWAL))) {
525                 // unable to write
526                 // TODO; should this try to abort the previously
527                 // buffered message??
528                 SREG = intr_state;
529                 return -1;
530         }
531         UEDATX = 0xA1;
532         UEDATX = 0x20;
533         UEDATX = 0;
534         UEDATX = 0;
535         UEDATX = 0; // 0 seems to work nicely.  what if this is 1??
536         UEDATX = 0;
537         UEDATX = 1;
538         UEDATX = 0;
539         UEDATX = signals;
540         UEINTX = 0x3A;
541         SREG = intr_state;
542         return 0;
543 }
544
545
546
547 // ----- General USB Functions -----
548
549 // Set the avr into firmware reload mode
550 void usb_device_reload()
551 {
552         cli();
553         // Disable watchdog, if enabled
554         // Disable all peripherals
555
556         UDCON = 1;
557         USBCON = (1 << FRZCLK);  // Disable USB
558         UCSR1B = 0;
559         _delay_ms( 5 );
560
561 #if defined(__AVR_AT90USB162__)                // Teensy 1.0
562         EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
563         TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
564         DDRB = 0; DDRC = 0; DDRD = 0;
565         PORTB = 0; PORTC = 0; PORTD = 0;
566         asm volatile("jmp 0x3E00");
567 #elif defined(__AVR_ATmega32U4__)              // Teensy 2.0
568         EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
569         TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
570         DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
571         PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
572         asm volatile("jmp 0x7E00");
573 #elif defined(__AVR_AT90USB646__)              // Teensy++ 1.0
574         EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
575         TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
576         DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
577         PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
578         asm volatile("jmp 0xFC00");
579 #elif defined(__AVR_AT90USB1286__)             // Teensy++ 2.0
580         EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
581         TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
582         DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
583         PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
584         asm volatile("jmp 0x1FC00");
585 #endif
586 }
587
588
589 // WDT Setup for software reset the chip
590 void wdt_init(void)
591 {
592         MCUSR = 0;
593         wdt_disable();
594 }
595
596
597 // initialize USB
598 void usb_init(void)
599 {
600         HW_CONFIG();
601         USB_FREEZE();                           // enable USB
602         PLL_CONFIG();                           // config PLL
603         while (!(PLLCSR & (1<<PLOCK))) ;        // wait for PLL lock
604         USB_CONFIG();                           // start USB clock
605         UDCON = 0;                              // enable attach resistor
606         usb_configuration = 0;
607         UDIEN = (1<<EORSTE) | (1<<SOFE);
608         sei();
609
610         // Disable watchdog timer after possible software reset
611         //wdt_init(); // XXX Not working...seems to be ok without this, not sure though
612 }
613
614 // return 0 if the USB is not configured, or the configuration
615 // number selected by the HOST
616 uint8_t usb_configured()
617 {
618         return usb_configuration;
619 }
620
621 // USB Device Interrupt - handle all device-level events
622 // the transmit buffer flushing is triggered by the start of frame
623 //
624 ISR( USB_GEN_vect )
625 {
626         uint8_t intbits, t_cdc;
627
628         intbits = UDINT;
629         UDINT = 0;
630         if ( intbits & (1 << EORSTI) )
631         {
632                 UENUM = 0;
633                 UECONX = 1;
634                 UECFG0X = EP_TYPE_CONTROL;
635                 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
636                 UEIENX = (1 << RXSTPE);
637                 usb_configuration = 0;
638                 cdc_line_rtsdtr = 0;
639         }
640         if ( (intbits & (1 << SOFI)) && usb_configuration )
641         {
642                 t_cdc = transmit_flush_timer;
643                 if ( t_cdc )
644                 {
645                         transmit_flush_timer = --t_cdc;
646                         if ( !t_cdc )
647                         {
648                                 UENUM = CDC_TX_ENDPOINT;
649                                 UEINTX = 0x3A;
650                         }
651                 }
652                 static uint8_t div4 = 0;
653                 if ( USBKeys_Idle_Config && (++div4 & 3) == 0 )
654                 {
655                         USBKeys_Idle_Count++;
656                         if ( USBKeys_Idle_Count == USBKeys_Idle_Config )
657                         {
658                                 // XXX TODO Is this even used? If so, when? -Jacob
659                                 // From hasu's code, this section looks like it could fix the Mac SET_IDLE problem
660                                 // Send normal keyboard interrupt packet(s)
661                                 switch ( USBKeys_Protocol )
662                                 {
663                                 // Send boot keyboard interrupt packet(s)
664                                 case 0: usb_keyboard_toHost();     break;
665                                 // Send NKRO keyboard interrupts packet(s)
666                                 //case 1: usb_nkrokeyboard_toHost(); break; // XXX Not valid anymore
667                                 }
668                                 print("IDLE");
669                         }
670                 }
671         }
672 }
673
674
675
676 // Misc functions to wait for ready and send/receive packets
677 static inline void usb_wait_in_ready(void)
678 {
679         while (!(UEINTX & (1<<TXINI))) ;
680 }
681 static inline void usb_send_in(void)
682 {
683         UEINTX = ~(1<<TXINI);
684 }
685 static inline void usb_wait_receive_out(void)
686 {
687         while (!(UEINTX & (1<<RXOUTI))) ;
688 }
689 static inline void usb_ack_out(void)
690 {
691         UEINTX = ~(1<<RXOUTI);
692 }
693
694
695
696 // USB Endpoint Interrupt - endpoint 0 is handled here.  The
697 // other endpoints are manipulated by the user-callable
698 // functions, and the start-of-frame interrupt.
699 //
700 ISR(USB_COM_vect)
701 {
702         uint8_t intbits;
703         const uint8_t *list;
704         const uint8_t *cfg;
705         uint8_t i, n, len, en;
706         uint8_t *p;
707         uint8_t bmRequestType;
708         uint8_t bRequest;
709         uint16_t wValue;
710         uint16_t wIndex;
711         uint16_t wLength;
712         uint16_t desc_val;
713         const uint8_t *desc_addr;
714         uint8_t desc_length;
715
716         UENUM = 0;
717         intbits = UEINTX;
718         if (intbits & (1<<RXSTPI))
719         {
720                 bmRequestType = UEDATX;
721                 bRequest = UEDATX;
722                 wValue = UEDATX;
723                 wValue |= (UEDATX << 8);
724                 wIndex = UEDATX;
725                 wIndex |= (UEDATX << 8);
726                 wLength = UEDATX;
727                 wLength |= (UEDATX << 8);
728                 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
729
730                 if ( bRequest == GET_DESCRIPTOR )
731                 {
732                         list = (const uint8_t *)descriptor_list;
733                         for ( i = 0; ; i++ )
734                         {
735                                 if ( i >= NUM_DESC_LIST )
736                                 {
737                                         UECONX = (1 << STALLRQ) | (1 << EPEN);  //stall
738                                         return;
739                                 }
740                                 desc_val = pgm_read_word(list);
741                                 if ( desc_val != wValue )
742                                 {
743                                         list += sizeof( struct descriptor_list_struct );
744                                         continue;
745                                 }
746                                 list += 2;
747                                 desc_val = pgm_read_word(list);
748                                 if ( desc_val != wIndex )
749                                 {
750                                         list += sizeof(struct descriptor_list_struct) - 2;
751                                         continue;
752                                 }
753                                 list += 2;
754                                 desc_addr = (const uint8_t *)pgm_read_word(list);
755                                 list += 2;
756                                 desc_length = pgm_read_byte(list);
757                                 break;
758                         }
759                         len = (wLength < 256) ? wLength : 255;
760                         if (len > desc_length) len = desc_length;
761                         do {
762                                 // wait for host ready for IN packet
763                                 do {
764                                         i = UEINTX;
765                                 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
766                                 if (i & (1<<RXOUTI)) return;    // abort
767                                 // send IN packet
768                                 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
769                                 for (i = n; i; i--) {
770                                         UEDATX = pgm_read_byte(desc_addr++);
771                                 }
772                                 len -= n;
773                                 usb_send_in();
774                         } while (len || n == ENDPOINT0_SIZE);
775                         return;
776                 }
777
778                 if (bRequest == SET_ADDRESS) {
779                         usb_send_in();
780                         usb_wait_in_ready();
781                         UDADDR = wValue | (1<<ADDEN);
782                         return;
783                 }
784
785                 if ( bRequest == SET_CONFIGURATION && bmRequestType == 0 )
786                 {
787                         usb_configuration = wValue;
788                         cdc_line_rtsdtr = 0;
789                         transmit_flush_timer = 0;
790                         usb_send_in();
791                         cfg = endpoint_config_table;
792                         // Setup each of the 6 additional endpoints (0th already configured)
793                         for ( i = 1; i < 6; i++ )
794                         {
795                                 UENUM = i;
796                                 en = pgm_read_byte(cfg++);
797                                 UECONX = en;
798                                 if (en)
799                                 {
800                                         UECFG0X = pgm_read_byte(cfg++);
801                                         UECFG1X = pgm_read_byte(cfg++);
802                                 }
803                         }
804                         UERST = 0x7E;
805                         UERST = 0;
806                         return;
807                 }
808
809                 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
810                         usb_wait_in_ready();
811                         UEDATX = usb_configuration;
812                         usb_send_in();
813                         return;
814                 }
815
816                 if ( ( wIndex == KEYBOARD_INTERFACE      && USBKeys_Protocol == 0 )
817                   || ( wIndex == KEYBOARD_NKRO_INTERFACE && USBKeys_Protocol == 1 ) )
818                 {
819                         if ( bmRequestType == 0xA1)
820                         {
821                                 if ( bRequest == HID_GET_REPORT )
822                                 {
823                                         usb_wait_in_ready();
824
825                                         // Send normal keyboard interrupt packet(s)
826                                         switch ( USBKeys_Protocol )
827                                         {
828                                         // Send boot keyboard interrupt packet(s)
829                                         case 0: usb_keyboard_toHost();     break;
830                                         // Send NKRO keyboard interrupts packet(s)
831                                         //case 1: usb_nkrokeyboard_toHost(); break; // XXX Not valid anymore
832                                         }
833
834                                         usb_send_in();
835                                         return;
836                                 }
837                                 if ( bRequest == HID_GET_IDLE )
838                                 {
839                                         usb_wait_in_ready();
840                                         UEDATX = USBKeys_Idle_Config;
841                                         usb_send_in();
842                                         return;
843                                 }
844                                 if ( bRequest == HID_GET_PROTOCOL )
845                                 {
846                                         usb_wait_in_ready();
847                                         UEDATX = USBKeys_Protocol;
848                                         usb_send_in();
849                                         return;
850                                 }
851                         }
852                         if ( bmRequestType == 0x21 )
853                         {
854                                 if ( bRequest == HID_SET_REPORT )
855                                 {
856                                         usb_wait_receive_out();
857                                         USBKeys_LEDs = UEDATX;
858                                         usb_ack_out();
859                                         usb_send_in();
860                                         return;
861                                 }
862                                 if ( bRequest == HID_SET_IDLE )
863                                 {
864                                         usb_wait_in_ready();
865                                         USBKeys_Idle_Config = (wValue >> 8);
866                                         USBKeys_Idle_Count = 0;
867                                         usb_send_in();
868                                         print("HID IDLE");
869                                         return;
870                                 }
871                                 if ( bRequest == HID_SET_PROTOCOL )
872                                 {
873                                         usb_wait_in_ready();
874                                         USBKeys_Protocol = wValue; // 0 - Boot Mode, 1 - NKRO Mode
875                                         usb_send_in();
876                                         print("HID SET");
877                                         return;
878                                 }
879                         }
880                 }
881
882                 if (bRequest == CDC_GET_LINE_CODING && bmRequestType == 0xA1) {
883                         usb_wait_in_ready();
884                         p = cdc_line_coding;
885                         for (i=0; i<7; i++) {
886                                 UEDATX = *p++;
887                         }
888                         usb_send_in();
889                         return;
890                 }
891
892                 if (bRequest == CDC_SET_LINE_CODING && bmRequestType == 0x21) {
893                         usb_wait_receive_out();
894                         p = cdc_line_coding;
895                         for (i=0; i<7; i++) {
896                                 *p++ = UEDATX;
897                         }
898                         usb_ack_out();
899                         usb_send_in();
900                         return;
901                 }
902
903                 if (bRequest == CDC_SET_CONTROL_LINE_STATE && bmRequestType == 0x21) {
904                         cdc_line_rtsdtr = wValue;
905                         usb_wait_in_ready();
906                         usb_send_in();
907                         return;
908                 }
909
910                 if (bRequest == GET_STATUS) {
911                         usb_wait_in_ready();
912                         i = 0;
913                         if (bmRequestType == 0x82) {
914                                 UENUM = wIndex;
915                                 if (UECONX & (1<<STALLRQ)) i = 1;
916                                 UENUM = 0;
917                         }
918                         UEDATX = i;
919                         UEDATX = 0;
920                         usb_send_in();
921                         return;
922                 }
923
924                 if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
925                   && bmRequestType == 0x02 && wValue == 0) {
926                         i = wIndex & 0x7F;
927                         if (i >= 1 && i <= MAX_ENDPOINT) {
928                                 usb_send_in();
929                                 UENUM = i;
930                                 if (bRequest == SET_FEATURE) {
931                                         UECONX = (1<<STALLRQ)|(1<<EPEN);
932                                 } else {
933                                         UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
934                                         UERST = (1 << i);
935                                         UERST = 0;
936                                 }
937                                 return;
938                         }
939                 }
940         }
941         UECONX = (1 << STALLRQ) | (1 << EPEN);  // stall
942 }
943