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