/ usb_serial_hid / usb_api.cpp
usb_api.cpp
  1  /* USB API for Teensy USB Development Board
  2   * http://www.pjrc.com/teensy/teensyduino.html
  3   * Copyright (c) 2008 PJRC.COM, LLC
  4   * 
  5   * Permission is hereby granted, free of charge, to any person obtaining a copy
  6   * of this software and associated documentation files (the "Software"), to deal
  7   * in the Software without restriction, including without limitation the rights
  8   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9   * copies of the Software, and to permit persons to whom the Software is
 10   * furnished to do so, subject to the following conditions:
 11   * 
 12   * The above copyright notice and this permission notice shall be included in
 13   * all copies or substantial portions of the Software.
 14   * 
 15   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 21   * THE SOFTWARE.
 22   */
 23  
 24  #include <avr/io.h>
 25  #include <stdint.h>
 26  #include "usb_common.h"
 27  #include "usb_private.h"
 28  #include "usb_api.h"
 29  #include "wiring.h"
 30  
 31  // Public Methods //////////////////////////////////////////////////////////////
 32  
 33  void usb_serial_class::begin(long speed)
 34  {
 35  	// make sure USB is initialized
 36  	peek_buf = -1;
 37  	usb_init();
 38  	uint16_t begin_wait = (uint16_t)millis();
 39  	while (1) {
 40  		// wait for the host to finish enumeration
 41  		if (usb_configuration) {
 42  			delay(200);  // a little time for host to load a driver
 43  			return;
 44  		}
 45  		// or for suspend mode (powered without USB)
 46  		if (usb_suspended) {
 47  			uint16_t begin_suspend = (uint16_t)millis();
 48  			while (usb_suspended) {
 49  				// must remain suspended for a while, because
 50  				// normal USB enumeration causes brief suspend
 51  				// states, typically under 0.1 second
 52  				if ((uint16_t)millis() - begin_suspend > 250) {
 53  					return;
 54  				}
 55  			}
 56  		}
 57  		// ... or a timout (powered by a USB power adaptor that
 58  		// wiggles the data lines to keep a USB device charging)
 59  		if ((uint16_t)millis() - begin_wait > 2500) return;
 60  	}
 61  }
 62  
 63  void usb_serial_class::end()
 64  {
 65  	usb_shutdown();
 66  	delay(25);
 67  }
 68  
 69  // number of bytes available in the receive buffer
 70  int usb_serial_class::available()
 71  {
 72          uint8_t n=0, i, intr_state;
 73  
 74          intr_state = SREG;
 75          cli();
 76          if (usb_configuration) {
 77                  UENUM = CDC_RX_ENDPOINT;
 78                  n = UEBCLX;
 79  		if (!n) {
 80  			i = UEINTX;
 81  			if (i & (1<<RXOUTI) && !(i & (1<<RWAL))) UEINTX = 0x6B;
 82  		}
 83          }
 84          SREG = intr_state;
 85  	if (peek_buf >= 0 && n < 255) n++;
 86          return n;
 87  }
 88  
 89  int usb_serial_class::peek()
 90  {
 91  	if (peek_buf < 0) peek_buf = read();
 92  	return peek_buf;
 93  }
 94  
 95  // get the next character, or -1 if nothing received
 96  int usb_serial_class::read(void)
 97  {
 98          uint8_t c, intr_state;
 99  
100  	if (peek_buf >= 0) {
101  		c = peek_buf;
102  		peek_buf = -1;
103  		return c;
104  	}
105          // interrupts are disabled so these functions can be
106          // used from the main program or interrupt context,
107          // even both in the same program!
108          intr_state = SREG;
109          cli();
110          if (!usb_configuration) {
111                  SREG = intr_state;
112                  return -1;
113          }
114          UENUM = CDC_RX_ENDPOINT;
115  	retry:
116  	c = UEINTX;
117          if (!(c & (1<<RWAL))) {
118                  // no data in buffer
119  		if (c & (1<<RXOUTI)) {
120  			UEINTX = 0x6B;
121  			goto retry;
122  		}
123                  SREG = intr_state;
124                  return -1;
125          }
126          // take one byte out of the buffer
127          c = UEDATX;
128          // if this drained the buffer, release it
129          if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
130          SREG = intr_state;
131          return c;
132  }
133  
134  // discard any buffered input
135  void usb_serial_class::flush()
136  {
137          uint8_t intr_state;
138  
139          if (usb_configuration) {
140                  intr_state = SREG;
141                  cli();
142                  UENUM = CDC_RX_ENDPOINT;
143                  while ((UEINTX & (1<<RWAL))) {
144                          UEINTX = 0x6B;
145                  }
146                  SREG = intr_state;
147          }
148  	peek_buf = -1;
149  }
150  #if 0
151  // transmit a character.
152  void usb_serial_class::write(uint8_t c)
153  {
154          uint8_t timeout, intr_state;
155  
156          // if we're not online (enumerated and configured), error
157          if (!usb_configuration) return;
158          // interrupts are disabled so these functions can be
159          // used from the main program or interrupt context,
160          // even both in the same program!
161          intr_state = SREG;
162          cli();
163          UENUM = CDC_TX_ENDPOINT;
164          // if we gave up due to timeout before, don't wait again
165          if (transmit_previous_timeout) {
166                  if (!(UEINTX & (1<<RWAL))) {
167                          SREG = intr_state;
168                          return;
169                  }
170                  transmit_previous_timeout = 0;
171          }
172          // wait for the FIFO to be ready to accept data
173          timeout = UDFNUML + TRANSMIT_TIMEOUT;
174          while (1) {
175                  // are we ready to transmit?
176                  if (UEINTX & (1<<RWAL)) break;
177                  SREG = intr_state;
178                  // have we waited too long?  This happens if the user
179                  // is not running an application that is listening
180                  if (UDFNUML == timeout) {
181                          transmit_previous_timeout = 1;
182                          return;
183                  }
184                  // has the USB gone offline?
185                  if (!usb_configuration) return;
186                  // get ready to try checking again
187                  intr_state = SREG;
188                  cli();
189                  UENUM = CDC_TX_ENDPOINT;
190          }
191          // actually write the byte into the FIFO
192          UEDATX = c;
193          // if this completed a packet, transmit it now!
194          if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
195          transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
196          SREG = intr_state;
197  }
198  #endif
199  
200  
201  // transmit a block of data
202  #if ARDUINO >= 100
203  size_t usb_serial_class::write(const uint8_t *buffer, uint16_t size)
204  #else
205  #define setWriteError() 
206  void usb_serial_class::write(const uint8_t *buffer, uint16_t size)
207  #endif
208  {
209  	uint8_t timeout, intr_state, write_size;
210  #if ARDUINO >= 100
211  	size_t count=0;
212  #endif
213  
214  	// if we're not online (enumerated and configured), error
215  	if (!usb_configuration) {
216  		setWriteError();
217  		goto end;
218  	}
219  	// interrupts are disabled so these functions can be
220  	// used from the main program or interrupt context,
221  	// even both in the same program!
222  	intr_state = SREG;
223  	cli();
224  	UENUM = CDC_TX_ENDPOINT;
225  	// if we gave up due to timeout before, don't wait again
226  	if (transmit_previous_timeout) {
227  		if (!(UEINTX & (1<<RWAL))) {
228  			SREG = intr_state;
229  			setWriteError();
230  			goto end;
231  		}
232  		transmit_previous_timeout = 0;
233  	}
234  	// each iteration of this loop transmits a packet
235  	while (size) {
236  		// wait for the FIFO to be ready to accept data
237  		timeout = UDFNUML + TRANSMIT_TIMEOUT;
238  		while (1) {
239  			// are we ready to transmit?
240  			if (UEINTX & (1<<RWAL)) break;
241  			SREG = intr_state;
242  			// have we waited too long?  This happens if the user
243  			// is not running an application that is listening
244  			if (UDFNUML == timeout) {
245  				transmit_previous_timeout = 1;
246  				setWriteError();
247  				goto end;
248  			}
249  			// has the USB gone offline?
250  			if (!usb_configuration) {
251  				setWriteError();
252  				goto end;
253  			}
254  			// get ready to try checking again
255  			intr_state = SREG;
256  			cli();
257  			UENUM = CDC_TX_ENDPOINT;
258  		}
259  
260  		// compute how many bytes will fit into the next packet
261  		write_size = CDC_TX_SIZE - UEBCLX;
262  		if (write_size > size) write_size = size;
263  		size -= write_size;
264  #if ARDUINO >= 100
265  		count += write_size;
266  #endif
267  
268  #define ASM_COPY1(src, dest, tmp) "ld " tmp ", " src "\n\t" "st " dest ", " tmp "\n\t"
269  #define ASM_COPY2(src, dest, tmp) ASM_COPY1(src, dest, tmp) ASM_COPY1(src, dest, tmp)
270  #define ASM_COPY4(src, dest, tmp) ASM_COPY2(src, dest, tmp) ASM_COPY2(src, dest, tmp)
271  #define ASM_COPY8(src, dest, tmp) ASM_COPY4(src, dest, tmp) ASM_COPY4(src, dest, tmp)
272  
273  #if 1
274  		// write the packet
275  		do {
276  			uint8_t tmp;
277  			asm volatile(
278  			"L%=begin:"					"\n\t"
279  				"ldi	r30, %4"			"\n\t"
280  				"sub	r30, %3"			"\n\t"
281  				"cpi	r30, %4"			"\n\t"
282  				"brsh	L%=err"				"\n\t"
283  				"lsl	r30"				"\n\t"
284  				"clr	r31"				"\n\t"
285  				"subi	r30, lo8(-(pm(L%=table)))"	"\n\t"
286  				"sbci	r31, hi8(-(pm(L%=table)))"	"\n\t"
287  				"ijmp"					"\n\t"
288  			"L%=err:"					"\n\t"
289  				"rjmp	L%=end"				"\n\t"
290  			"L%=table:"					"\n\t"
291  				#if (CDC_TX_SIZE == 64)
292  				ASM_COPY8("Y+", "X", "%1")
293  				ASM_COPY8("Y+", "X", "%1")
294  				ASM_COPY8("Y+", "X", "%1")
295  				ASM_COPY8("Y+", "X", "%1")
296  				#endif
297  				#if (CDC_TX_SIZE >= 32)
298  				ASM_COPY8("Y+", "X", "%1")
299  				ASM_COPY8("Y+", "X", "%1")
300  				#endif
301  				#if (CDC_TX_SIZE >= 16)
302  				ASM_COPY8("Y+", "X", "%1")
303  				#endif
304  				ASM_COPY8("Y+", "X", "%1")
305  			"L%=end:"					"\n\t"
306  				: "+y" (buffer), "=r" (tmp)
307  				: "x" (&UEDATX), "r" (write_size), "M" (CDC_TX_SIZE)
308  				: "r30", "r31"
309  			);
310  		} while (0);
311  #endif
312  		// if this completed a packet, transmit it now!
313  		if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
314  		transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
315  	}
316  	SREG = intr_state;
317  end:
318  #if ARDUINO >= 100
319  	return count;
320  #else
321  	return;
322  #endif
323  }
324  
325  // transmit a string
326  /*
327  void usb_serial_class::write(const char *str)
328  {
329  	uint16_t size=0;
330  	const char *p=str;
331  
332  	while (*p++) size++;
333  	if (size) write((const uint8_t *)str, size);
334  }
335  */
336  
337  // These are Teensy-specific extensions to the Serial object
338  
339  // immediately transmit any buffered output.
340  // This doesn't actually transmit the data - that is impossible!
341  // USB devices only transmit when the host allows, so the best
342  // we can do is release the FIFO buffer for when the host wants it
343  void usb_serial_class::send_now(void)
344  {
345          uint8_t intr_state;
346  
347          intr_state = SREG;
348          cli();
349          if (usb_configuration && transmit_flush_timer) {
350                  UENUM = CDC_TX_ENDPOINT;
351                  UEINTX = 0x3A;
352                  transmit_flush_timer = 0;
353          }
354          SREG = intr_state;
355  }
356  
357  uint32_t usb_serial_class::baud(void)
358  {
359  	return *(uint32_t *)cdc_line_coding;
360  }
361  
362  uint8_t usb_serial_class::stopbits(void)
363  {
364  	return cdc_line_coding[4];
365  }
366  
367  uint8_t usb_serial_class::paritytype(void)
368  {
369  	return cdc_line_coding[5];
370  }
371  
372  uint8_t usb_serial_class::numbits(void)
373  {
374  	return cdc_line_coding[6];
375  }
376  
377  uint8_t usb_serial_class::dtr(void)
378  {
379  	return (cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0;
380  }
381  
382  uint8_t usb_serial_class::rts(void)
383  {
384  	return (cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0;
385  }
386  
387  usb_serial_class::operator bool()
388  {
389  	if (usb_configuration &&
390  	  (cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS))) {
391  		return true;
392  	}
393  	return false;
394  }
395  
396  
397  
398  
399  // Step #1, decode UTF8 to Unicode code points
400  //
401  #if ARDUINO >= 100
402  size_t usb_keyboard_class::write(uint8_t c)
403  #else
404  void usb_keyboard_class::write(uint8_t c)
405  #endif
406  {
407  	if (c < 0x80) {
408  		// single byte encoded, 0x00 to 0x7F
409  		utf8_state = 0;
410  		write_unicode(c);
411  	} else if (c < 0xC0) {
412  		// 2nd, 3rd or 4th byte, 0x80 to 0xBF
413  		c &= 0x3F;
414  		if (utf8_state == 1) {
415  			utf8_state = 0;
416  			write_unicode(unicode_wchar | c);
417  		} else if (utf8_state == 2) {
418  			unicode_wchar |= ((uint16_t)c << 6);
419  			utf8_state = 1;
420  		}
421  	} else if (c < 0xE0) {
422  		// begin 2 byte sequence, 0xC2 to 0xDF
423  		// or illegal 2 byte sequence, 0xC0 to 0xC1
424  		unicode_wchar = (uint16_t)(c & 0x1F) << 6;
425  		utf8_state = 1;
426  	} else if (c < 0xF0) {
427  		// begin 3 byte sequence, 0xE0 to 0xEF
428  		unicode_wchar = (uint16_t)(c & 0x0F) << 12;
429  		utf8_state = 2;
430  	} else {
431  		// begin 4 byte sequence (not supported), 0xF0 to 0xF4
432  		// or illegal, 0xF5 to 0xFF
433  		utf8_state = 255;
434  	}
435  #if ARDUINO >= 100
436  	return 1;
437  #endif
438  }
439  
440  
441  // Step #2: translate Unicode code point to keystroke sequence
442  //
443  KEYCODE_TYPE usb_keyboard_class::unicode_to_keycode(uint16_t cpoint)
444  {
445  	// Unicode code points beyond U+FFFF are not supported
446  	// technically this input should probably be called UCS-2
447  	if (cpoint < 32) {
448  		if (cpoint == 10) return KEY_ENTER & 0x3FFF;
449  		return 0;
450  	}
451  	if (cpoint < 128) {
452  		if (sizeof(KEYCODE_TYPE) == 1) {
453  			return pgm_read_byte(keycodes_ascii + (cpoint - 0x20));
454  		} else if (sizeof(KEYCODE_TYPE) == 2) {
455  			return pgm_read_word(keycodes_ascii + (cpoint - 0x20));
456  		}
457  		return 0;
458  	}
459  	#ifdef ISO_8859_1_A0
460  	if (cpoint <= 0xA0) return 0;
461  	if (cpoint < 0x100) {
462  		if (sizeof(KEYCODE_TYPE) == 1) {
463  			return pgm_read_byte(keycodes_iso_8859_1 + (cpoint - 0xA0));
464  		} else if (sizeof(KEYCODE_TYPE) == 2) {
465  			return pgm_read_word(keycodes_iso_8859_1 + (cpoint - 0xA0));
466  		}
467  		return 0;
468  	}
469  	#endif
470  	//#ifdef UNICODE_20AC
471  	//if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF;
472  	//#endif
473  	#ifdef KEYCODE_EXTRA00
474  	if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF;
475  	#endif
476  	#ifdef KEYCODE_EXTRA01
477  	if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF;
478  	#endif
479  	#ifdef KEYCODE_EXTRA02
480  	if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF;
481  	#endif
482  	#ifdef KEYCODE_EXTRA03
483  	if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF;
484  	#endif
485  	#ifdef KEYCODE_EXTRA04
486  	if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF;
487  	#endif
488  	#ifdef KEYCODE_EXTRA05
489  	if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF;
490  	#endif
491  	#ifdef KEYCODE_EXTRA06
492  	if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF;
493  	#endif
494  	#ifdef KEYCODE_EXTRA07
495  	if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF;
496  	#endif
497  	#ifdef KEYCODE_EXTRA08
498  	if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF;
499  	#endif
500  	#ifdef KEYCODE_EXTRA09
501  	if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF;
502  	#endif
503  	return 0;
504  }
505  
506  // Step #3: execute keystroke sequence
507  //
508  void usb_keyboard_class::write_keycode(KEYCODE_TYPE keycode)
509  {
510  	if (!keycode) return;
511  	#ifdef DEADKEYS_MASK
512  	KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode);
513  	if (deadkeycode) write_key(deadkeycode);
514  	#endif
515  	write_key(keycode);
516  }
517  
518  KEYCODE_TYPE usb_keyboard_class::deadkey_to_keycode(KEYCODE_TYPE keycode)
519  {
520  	#ifdef DEADKEYS_MASK
521  	keycode &= DEADKEYS_MASK;
522  	if (keycode == 0) return 0;
523  	#ifdef ACUTE_ACCENT_BITS
524  	if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT;
525  	#endif
526  	#ifdef CEDILLA_BITS
527  	if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA;
528  	#endif
529  	#ifdef CIRCUMFLEX_BITS
530  	if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX;
531  	#endif
532  	#ifdef DIAERESIS_BITS
533  	if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS;
534  	#endif
535  	#ifdef GRAVE_ACCENT_BITS
536  	if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT;
537  	#endif
538  	#ifdef TILDE_BITS
539  	if (keycode == TILDE_BITS) return DEADKEY_TILDE;
540  	#endif
541  	#ifdef RING_ABOVE_BITS
542  	if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE;
543  	#endif
544  	#endif // DEADKEYS_MASK
545  	return 0;
546  }
547  
548  // Step #4: do each keystroke
549  //
550  void usb_keyboard_class::write_key(KEYCODE_TYPE keycode)
551  {
552  	keyboard_report_data[0] = keycode_to_modifier(keycode);
553  	keyboard_report_data[1] = 0;
554  	keyboard_report_data[2] = keycode_to_key(keycode);
555  	keyboard_report_data[3] = 0;
556  	keyboard_report_data[4] = 0;
557  	keyboard_report_data[5] = 0;
558  	keyboard_report_data[6] = 0;
559  	keyboard_report_data[7] = 0;
560  	send_now();
561  	keyboard_report_data[0] = 0;
562  	keyboard_report_data[2] = 0;
563  	send_now();
564  }
565  
566  uint8_t usb_keyboard_class::keycode_to_modifier(KEYCODE_TYPE keycode)
567  {
568  	uint8_t modifier=0;
569  
570  	#ifdef SHIFT_MASK
571  	if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT;
572  	#endif
573  	#ifdef ALTGR_MASK
574  	if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT;
575  	#endif
576  	#ifdef RCTRL_MASK
577  	if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL;
578  	#endif
579  	return modifier;
580  }
581  
582  uint8_t usb_keyboard_class::keycode_to_key(KEYCODE_TYPE keycode)
583  {
584  	uint8_t key = keycode & 0x3F;
585  	#ifdef KEY_NON_US_100
586  	if (key == KEY_NON_US_100) key = 100;
587  	#endif
588  	return key;
589  }
590  
591  
592  
593  void usb_keyboard_class::set_modifier(uint8_t c)
594  {
595  	keyboard_report_data[0] = c;
596  }
597  void usb_keyboard_class::set_key1(uint8_t c)
598  {
599  	keyboard_report_data[2] = c;
600  }
601  void usb_keyboard_class::set_key2(uint8_t c)
602  {
603  	keyboard_report_data[3] = c;
604  }
605  void usb_keyboard_class::set_key3(uint8_t c)
606  {
607  	keyboard_report_data[4] = c;
608  }
609  void usb_keyboard_class::set_key4(uint8_t c)
610  {
611  	keyboard_report_data[5] = c;
612  }
613  void usb_keyboard_class::set_key5(uint8_t c)
614  {
615  	keyboard_report_data[6] = c;
616  }
617  void usb_keyboard_class::set_key6(uint8_t c)
618  {
619  	keyboard_report_data[7] = c;
620  }
621  void usb_keyboard_class::set_media(uint8_t c)
622  {
623  	keyboard_report_data[1] = c;
624  }
625  
626  
627  void usb_keyboard_class::send_now(void)
628  {
629          uint8_t intr_state, timeout;
630  
631          if (!usb_configuration) return;
632          intr_state = SREG;
633          cli();
634          UENUM = KEYBOARD_ENDPOINT;
635          timeout = UDFNUML + 50;
636          while (1) {
637                  // are we ready to transmit?
638                  if (UEINTX & (1<<RWAL)) break;
639                  SREG = intr_state;
640                  // has the USB gone offline?
641                  if (!usb_configuration) return;
642                  // have we waited too long?
643                  if (UDFNUML == timeout) return;
644                  // get ready to try checking again
645                  intr_state = SREG;
646                  cli();
647                  UENUM = KEYBOARD_ENDPOINT;
648          }
649          UEDATX = keyboard_report_data[0];
650          UEDATX = keyboard_report_data[1];
651          UEDATX = keyboard_report_data[2];
652          UEDATX = keyboard_report_data[3];
653          UEDATX = keyboard_report_data[4];
654          UEDATX = keyboard_report_data[5];
655          UEDATX = keyboard_report_data[6];
656          UEDATX = keyboard_report_data[7];
657          UEINTX = 0x3A;
658          keyboard_idle_count = 0;
659          SREG = intr_state;
660  }
661  
662  
663  void usb_keyboard_class::press(uint16_t n)
664  {
665  	uint8_t key, mod, msb, modrestore=0;
666  
667  	msb = n >> 8;
668  	if (msb >= 0xC2 && msb <= 0xDF) {
669  		n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6);
670  	} else
671  	if (msb == 0x80) {
672  		presskey(0, n);
673  		return;
674  	} else
675  	if (msb == 0x40) {
676  		presskey(n, 0);
677  		return;
678  	}
679  	KEYCODE_TYPE keycode = unicode_to_keycode(n);
680  	if (!keycode) return;
681  	#ifdef DEADKEYS_MASK
682  	KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode);
683  	if (deadkeycode) {
684  		modrestore = keyboard_report_data[0];
685  		if (modrestore) {
686  			keyboard_report_data[0] = 0;
687  			send_now();
688  		}
689  		// TODO: test if operating systems recognize
690  		// deadkey sequences when other keys are held
691  		mod = keycode_to_modifier(deadkeycode);
692  		key = keycode_to_key(deadkeycode);
693  		presskey(key, mod);
694  		releasekey(key, mod);
695  	}
696  	#endif
697  	mod = keycode_to_modifier(keycode);
698  	key = keycode_to_key(keycode);
699  	presskey(key, mod | modrestore);
700  }
701  
702  void usb_keyboard_class::release(uint16_t n)
703  {
704  	uint8_t key, mod, msb;
705  
706  	msb = n >> 8;
707  	if (msb >= 0xC2 && msb <= 0xDF) {
708  		n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6);
709  	} else
710  	if (msb == 0x80) {
711  		releasekey(0, n);
712  		return;
713  	} else
714  	if (msb == 0x40) {
715  		releasekey(n, 0);
716  		return;
717  	}
718  	KEYCODE_TYPE keycode = unicode_to_keycode(n);
719  	if (!keycode) return;
720  	mod = keycode_to_modifier(keycode);
721  	key = keycode_to_key(keycode);
722  	releasekey(key, mod);
723  }
724  
725  void usb_keyboard_class::presskey(uint8_t key, uint8_t modifier)
726  {
727  	bool send_required = false;
728  	uint8_t i;
729  
730  	if (modifier) {
731  		if ((keyboard_report_data[0] & modifier) != modifier) {
732  			keyboard_report_data[0] |= modifier;
733  			send_required = true;
734  		}
735  	}
736  	if (key) {
737  		for (i=2; i < 8; i++) {
738  			if (keyboard_report_data[i] == key) goto end;
739  		}
740  		for (i=2; i < 8; i++) {
741  			if (keyboard_report_data[i] == 0) {
742  				keyboard_report_data[i] = key;
743  				send_required = true;
744  				goto end;
745  			}
746  		}
747  	}
748  	end:
749  	if (send_required) send_now();
750  }
751  
752  void usb_keyboard_class::releasekey(uint8_t key, uint8_t modifier)
753  {
754  	bool send_required = false;
755  	uint8_t i;
756  
757  	if (modifier) {
758  		if ((keyboard_report_data[0] & modifier) != 0) {
759  			keyboard_report_data[0] &= ~modifier;
760  			send_required = true;
761  		}
762  	}
763  	if (key) {
764  		for (i=2; i < 8; i++) {
765  			if (keyboard_report_data[i] == key) {
766  				keyboard_report_data[i] = 0;
767  				send_required = true;
768  			}
769  		}
770  	}
771  	if (send_required) send_now();
772  }
773  
774  void usb_keyboard_class::releaseAll(void)
775  {
776  	uint8_t i, anybits;
777  
778  	anybits = keyboard_report_data[0];
779  	for (i=2; i < 8; i++) {
780  		anybits |= keyboard_report_data[i];
781  		keyboard_report_data[i] = 0;
782  	}
783  	if (!anybits) return;
784  	keyboard_report_data[0] = 0;
785  	send_now();
786  }
787  
788  
789  
790  
791  
792  
793  void usb_mouse_class::move(int8_t x, int8_t y, int8_t wheel)
794  {
795          uint8_t intr_state, timeout;
796  
797          if (!usb_configuration) return;
798          if (x == -128) x = -127;
799          if (y == -128) y = -127;
800          if (wheel == -128) wheel = -127;
801          intr_state = SREG;
802          cli();
803          UENUM = MOUSE_ENDPOINT;
804          timeout = UDFNUML + 50;
805          while (1) {
806                  // are we ready to transmit?
807                  if (UEINTX & (1<<RWAL)) break;
808                  SREG = intr_state;
809                  // has the USB gone offline?
810                  if (!usb_configuration) return;
811                  // have we waited too long?
812                  if (UDFNUML == timeout) return;
813                  // get ready to try checking again
814                  intr_state = SREG;
815                  cli();
816                  UENUM = MOUSE_ENDPOINT;
817          }
818          UEDATX = mouse_buttons;
819          UEDATX = x;
820          UEDATX = y;
821          UEDATX = wheel;
822          UEINTX = 0x3A;
823          SREG = intr_state;
824  }
825  
826  void usb_mouse_class::click(uint8_t b)
827  {
828          mouse_buttons = (b & 7);
829          move(0, 0);
830          mouse_buttons = 0;
831          move(0, 0);
832  }
833  
834  void usb_mouse_class::scroll(int8_t wheel)
835  {
836          move(0, 0, wheel);
837  }
838  
839  void usb_mouse_class::set_buttons(uint8_t left, uint8_t middle, uint8_t right)
840  {
841          uint8_t mask=0;
842  
843          if (left) mask |= 1;
844          if (middle) mask |= 4;
845          if (right) mask |= 2;
846          mouse_buttons = mask;
847          move(0, 0);
848  }
849  
850  void usb_mouse_class::press(uint8_t b)
851  {
852          uint8_t prev = mouse_buttons;
853          mouse_buttons |= (b & 7);
854          if (mouse_buttons != prev) move(0, 0);
855  }
856  
857  void usb_mouse_class::release(uint8_t b)
858  {
859          uint8_t prev = mouse_buttons;
860          mouse_buttons &= ~(b & 7);
861          if (mouse_buttons != prev) move(0, 0);
862  }
863  
864  bool usb_mouse_class::isPressed(uint8_t b)
865  {
866          return ((mouse_buttons & (b & 7)) != 0);
867  }
868  
869  
870  
871  void usb_joystick_class::send_now(void)
872  {
873          uint8_t intr_state, timeout;
874  
875          if (!usb_configuration) return;
876          intr_state = SREG;
877          cli();
878          UENUM = JOYSTICK_ENDPOINT;
879          timeout = UDFNUML + 50;
880          while (1) {
881                  // are we ready to transmit?
882                  if (UEINTX & (1<<RWAL)) break;
883                  SREG = intr_state;
884                  // has the USB gone offline?
885                  if (!usb_configuration) return;
886                  // have we waited too long?
887                  if (UDFNUML == timeout) return;
888                  // get ready to try checking again
889                  intr_state = SREG;
890                  cli();
891                  UENUM = JOYSTICK_ENDPOINT;
892          }
893          UEDATX = joystick_report_data[0];
894          UEDATX = joystick_report_data[1];
895          UEDATX = joystick_report_data[2];
896          UEDATX = joystick_report_data[3];
897          UEDATX = joystick_report_data[4];
898          UEDATX = joystick_report_data[5];
899          UEDATX = joystick_report_data[6];
900          UEDATX = joystick_report_data[7];
901          UEDATX = joystick_report_data[8];
902          UEDATX = joystick_report_data[9];
903          UEDATX = joystick_report_data[10];
904          UEDATX = joystick_report_data[11];
905          UEINTX = 0x3A;
906          SREG = intr_state;
907  }
908  
909  
910  
911  
912  
913  
914  
915  // Preinstantiate Objects //////////////////////////////////////////////////////
916  
917  usb_serial_class        Serial = usb_serial_class();
918  usb_keyboard_class      Keyboard = usb_keyboard_class();
919  usb_mouse_class         Mouse = usb_mouse_class();
920  usb_joystick_class      Joystick = usb_joystick_class();
921