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