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