/ 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