Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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