├── .gitignore ├── OnlyKey └── OnlyKey.ino ├── README.md ├── keylayouts.c ├── keylayouts.h ├── usb_desc.c ├── usb_desc.h ├── usb_dev.c ├── usb_dev.h ├── usb_keyboard.c ├── usb_rawhid.c └── usb_rawhid.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | OnlyKey_NOPIN/OnlyKey_NOPIN.ino 49 | -------------------------------------------------------------------------------- /OnlyKey/OnlyKey.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2022, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 15 | * 2. Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following 17 | * disclaimer in the documentation and/or other materials provided 18 | * with the distribution. 19 | * 20 | * 3. All advertising materials mentioning features or use of this 21 | * software must display the following acknowledgment: 22 | * "This product includes software developed by CryptoTrust LLC. for 23 | * the OnlyKey Project (https://crp.to/ok)" 24 | * 25 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 26 | * endorse or promote products derived from this software without 27 | * prior written permission. For written permission, please contact 28 | * admin@crp.to. 29 | * 30 | * 5. Products derived from this software may not be called "OnlyKey" 31 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 32 | * specific prior written permission. For written permission, please 33 | * contact admin@crp.to. 34 | * 35 | * 6. Redistributions of any form whatsoever must retain the following 36 | * acknowledgment: 37 | * "This product includes software developed by CryptoTrust LLC. for 38 | * the OnlyKey Project (https://crp.to/ok)" 39 | * 40 | * 7. Redistributions in any form must be accompanied by information on 41 | * how to obtain complete source code for this software and any 42 | * accompanying software that uses this software. The source code 43 | * must either be included in the distribution or be available for 44 | * no more than the cost of distribution plus a nominal fee, and must 45 | * be freely redistributable under reasonable conditions. For a 46 | * binary file, complete source code means the source code for all 47 | * modules it contains. 48 | * 49 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 50 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 51 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 52 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 53 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 54 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 55 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 56 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 57 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 58 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 59 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 60 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 61 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 62 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 63 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 64 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 65 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 66 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 67 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 68 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 69 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 70 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 71 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 72 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 73 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 74 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 75 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 76 | */ 77 | 78 | /*************************************/ 79 | //Firmware Build Options 80 | /*************************************/ 81 | #define DEBUG //Enable Serial Monitor, debug firmware 82 | #define STD_VERSION //Define for STD edition firmare, undefine for IN TRVL edition firmware 83 | #define OK_Color //Define for hardware with color LED 84 | //#define FACTORYKEYS2 // Attestation key and other keys encrypted using CHIP ID and RNG for unique per device 85 | #ifndef STD_VERSION 86 | #undef FACTORYKEYS2 87 | #endif 88 | /*************************************/ 89 | //Standard Libraries 90 | /*************************************/ 91 | #include "sha256.h" 92 | #include "EEPROM.h" 93 | #include "T3MacLib.h" 94 | #include "SoftTimer.h" 95 | #include "password.h" 96 | #include "sha1.h" 97 | #include "totp.h" 98 | #include "Time.h" 99 | #include "onlykey.h" 100 | #include "flashkinetis.h" 101 | #include "RNG.h" 102 | #include "base64.h" 103 | #include "ADC.h" 104 | #include "usb_dev.h" 105 | /*************************************/ 106 | //Color LED Libraries 107 | /*************************************/ 108 | #ifdef OK_Color 109 | #include "Adafruit_NeoPixel.h" 110 | #endif 111 | /*************************************/ 112 | //Additional Libraries to Load for STD firmware version 113 | //These libraries will only be used if STD_VERSION is defined 114 | /*************************************/ 115 | extern uint8_t profilemode; 116 | #ifdef STD_VERSION 117 | #define OKSOLO //Using FIDO2 from SOLO 118 | #include "yksim.h" 119 | #include "uECC.h" 120 | #include "ykcore.h" 121 | #include "AES.h" 122 | #include "GCM.h" 123 | #include "rsa.h" 124 | #include "tweetnacl.h" 125 | /*************************************/ 126 | //FIDO2 Libraries 127 | /*************************************/ 128 | #ifdef OKSOLO 129 | #include "ctap.h" 130 | #include "ctaphid.h" 131 | #include "cbor.h" 132 | #include "ctap_parse.h" 133 | #include "ctap_errors.h" 134 | #include "device.h" 135 | #include "storage.h" 136 | #include "wallet.h" 137 | #include "solo.h" 138 | #include "extensions.h" 139 | #include "ok_extension.h" 140 | #include "crypto.h" 141 | #include "u2f.h" 142 | #endif 143 | #endif 144 | /*************************************/ 145 | //LED Assignments 146 | /*************************************/ 147 | extern uint8_t NEO_Color; 148 | extern uint8_t NEO_Brightness[1]; 149 | extern uint8_t touchoffset; 150 | extern uint8_t Profile_Offset; 151 | /*************************************/ 152 | //RNG Assignments 153 | /*************************************/ 154 | bool calibrating = false; 155 | extern char ID[36]; 156 | /*************************************/ 157 | //PIN Assigment Variables 158 | /*************************************/ 159 | extern uint8_t BLINKPIN; 160 | extern uint8_t TOUCHPIN1; 161 | extern uint8_t TOUCHPIN2; 162 | extern uint8_t TOUCHPIN3; 163 | extern uint8_t TOUCHPIN4; 164 | extern uint8_t TOUCHPIN5; 165 | extern uint8_t TOUCHPIN6; 166 | extern uint8_t ANALOGPIN1; 167 | extern uint8_t ANALOGPIN2; 168 | extern unsigned int sumofall; 169 | /*************************************/ 170 | //Keypad / Password Assignments 171 | /*************************************/ 172 | extern int button_selected; //Key selected 1-6 173 | static int pass_keypress = 1; //The number key presses in current password attempt 174 | static int session_attempts = 0; //The number of password attempts this session 175 | static bool firsttime = true; 176 | extern Password password; 177 | extern uint8_t TIMEOUT[1]; 178 | extern uint8_t TYPESPEED[1]; 179 | extern uint8_t KeyboardLayout[1]; 180 | extern uint8_t mod_keys_enabled; 181 | /*************************************/ 182 | //Capacitive Touch Variables 183 | /*************************************/ 184 | extern unsigned int touchread1; 185 | extern unsigned int touchread2; 186 | extern unsigned int touchread3; 187 | extern unsigned int touchread4; 188 | extern unsigned int touchread5; 189 | extern unsigned int touchread6; 190 | extern unsigned int touchread1ref; 191 | extern unsigned int touchread2ref; 192 | extern unsigned int touchread3ref; 193 | extern unsigned int touchread4ref; 194 | extern unsigned int touchread5ref; 195 | extern unsigned int touchread6ref; 196 | /*************************************/ 197 | //Keys, Hashes, Integrity Counters 198 | /*************************************/ 199 | extern uint8_t profilekey[32]; 200 | extern uint8_t p1hash[32]; 201 | extern uint8_t sdhash[32]; 202 | extern uint8_t p2hash[32]; 203 | extern uint8_t nonce[32]; 204 | extern int initcheck; 205 | extern int integrityctr1; 206 | extern int integrityctr2; 207 | /*************************************/ 208 | //SoftTimer Tasks 209 | /*************************************/ 210 | #define TIME_POLL 50 // poll "key" every 50 ms 211 | Task taskKey(TIME_POLL, checkKey); 212 | Task taskKB(50, sendKey); // Default send kb codes every 50 ms 213 | Task taskInitialized(1000, sendInitialized); 214 | /*************************************/ 215 | //CRYPTO 216 | /*************************************/ 217 | extern uint8_t Challenge_button1; 218 | extern uint8_t Challenge_button2; 219 | extern uint8_t Challenge_button3; 220 | extern uint8_t CRYPTO_AUTH; 221 | extern int packet_buffer_offset; 222 | extern uint8_t packet_buffer_details[5]; 223 | extern uint8_t outputmode; 224 | extern uint8_t derived_key_challenge_mode; 225 | extern uint8_t stored_key_challenge_mode; 226 | /*************************************/ 227 | //Other 228 | /*************************************/ 229 | extern uint8_t recv_buffer[64]; 230 | char keybuffer[EElen_url+EElen_addchar+EElen_delay+EElen_addchar+EElen_username+EElen_delay+EElen_addchar+EElen_password+EElen_addchar+EElen_2FAtype+64+EElen_addchar+EElen_addchar+10]; //Buffer to hold all keystrokes 231 | char *pos; 232 | extern uint8_t isfade; 233 | #ifdef STD_VERSION 234 | extern uint8_t ctap_buffer[CTAPHID_BUFFER_SIZE]; 235 | #endif 236 | extern uint8_t pending_operation; 237 | uint8_t modkey; 238 | extern uint8_t onlykeyhw; 239 | extern uint8_t Duo_config[2]; 240 | 241 | extern "C" { 242 | int _getpid(){ return -1;} 243 | int _kill(int pid, int sig){ return -1; } 244 | int _write(){return -1;} 245 | } 246 | 247 | /*************************************/ 248 | //Arduino Setup 249 | /*************************************/ 250 | void setup() { 251 | // Delay may be needed for serial debug 252 | // delay(3000); 253 | analogReadResolution(16); 254 | #ifdef DEBUG 255 | Serial.begin(9600); 256 | #endif 257 | #ifdef STD_VERSION 258 | profilemode = STDPROFILE1; 259 | #else 260 | profilemode = NONENCRYPTEDPROFILE; 261 | #endif 262 | /*************************************/ 263 | //PIN Assigments 264 | /*************************************/ 265 | BLINKPIN=6; 266 | TOUCHPIN1=1; // #define CORE_PIN1_CONFIG PORTB_PCR17 267 | TOUCHPIN2=22; //#define CORE_PIN22_CONFIG PORTC_PCR1 268 | TOUCHPIN3=23; //#define CORE_PIN23_CONFIG PORTC_PCR2 OnlyKey DUO Button #1 269 | TOUCHPIN4=17; //#define CORE_PIN17_CONFIG PORTB_PCR1 270 | TOUCHPIN5=15; //#define CORE_PIN15_CONFIG PORTC_PCR0 OnlyKey DUO Button #2 271 | TOUCHPIN6=16; //#define CORE_PIN16_CONFIG PORTB_PCR0 272 | ANALOGPIN1=A0; //#define CORE_PIN14_CONFIG PORTD_PCR1 273 | ANALOGPIN2=A7; //#define CORE_PIN21_CONFIG PORTD_PCR6 274 | /*************************************/ 275 | initcheck = okcore_flashget_noncehash ((uint8_t*)nonce, 32); //Check if first time use 276 | CHIP_ID(); // Get Unique chip ID from ROM 277 | unsigned int analog1 = analogRead(ANALOGPIN1); 278 | unsigned int analog2 = analogRead(ANALOGPIN2); 279 | integrityctr1++; 280 | /* 281 | //dump flash storage, useful for verifying contents 282 | Serial.println(initcheck); 283 | char temp[32]; 284 | wipeEEPROM(); 285 | unsigned long readadr = flashstorestart; 286 | while (readadr <= flashend) { 287 | for(int i =0; i<=2048; i=i+4){ 288 | sprintf (temp, "%.8X", *((unsigned int*)readadr)); 289 | Serial.print(temp); 290 | readadr = readadr + 4; 291 | } 292 | Serial.println(); 293 | } 294 | */ 295 | //FSEC currently set to 0x44, everything disabled except mass erase https://forum.pjrc.com/threads/28783-Upload-Hex-file-from-Teensy-3-1 296 | if (FTFL_FSEC!=0x44) { 297 | // First time starting up, three steps to complete: 298 | // 1) Read factory loaded device keys and generate custom device keys 299 | // Get factory default flash contents 300 | #ifdef FACTORYKEYS2 301 | okcore_flashget_common(ctap_buffer, (unsigned long *)factorysectoradr, 1025); 302 | #ifdef DEBUG 303 | Serial.println("Factory Key Values"); 304 | byteprint(ctap_buffer, 1025); 305 | #endif 306 | if (ctap_buffer[480] != 0xFF) { // Attestation key loaded 307 | // Hash factory bytes with unique chip ID and random 308 | SHA256_CTX hash; 309 | for (int i=0; i<=14; i++) { 310 | analog1 = analogRead(ANALOGPIN1); 311 | analog2 = analogRead(ANALOGPIN1); 312 | sha256_init(&hash); 313 | sha256_update(&hash, ctap_buffer+(32*i), 32); 314 | sha256_update(&hash, ctap_buffer+(32*(i+1)), 32); 315 | sha256_update(&hash, (uint8_t*)ID, 36); 316 | sha256_update(&hash, (uint8_t*)&analog1, 4); 317 | sha256_update(&hash, (uint8_t*)&analog2, 4); 318 | sha256_final(&hash, ctap_buffer+(32*i)); 319 | } 320 | #ifdef DEBUG 321 | Serial.println("KDF Hashed Factory Values"); 322 | byteprint(ctap_buffer, 512); 323 | #endif 324 | // Write everything to flash 325 | if (*certified_hw != 1) { 326 | // Encrypt attestation key with generated KEK 327 | ctap_buffer[435]=3; 328 | //Write keys 329 | okcore_flashset_common(ctap_buffer, (unsigned long *)enckeysectoradr, 436); 330 | okcrypto_aes_gcm_encrypt2(ctap_buffer+480, ctap_buffer+436, ctap_buffer+448, 32, true); 331 | //Write encrypted contents to flash 332 | okcore_flashset_common(ctap_buffer, (unsigned long *)enckeysectoradr, 513); 333 | // Set write flag 334 | ctap_buffer[435]=1; 335 | // Write flag to flash 336 | okcore_flashset_common(ctap_buffer, (unsigned long *)enckeysectoradr, 513); 337 | } 338 | // Erase factory keys 339 | memset(ctap_buffer, 0, 2048); 340 | okcore_flashset_common(ctap_buffer, (unsigned long *)factorysectoradr, 512); 341 | } 342 | #endif // end FACTORYKEYS 343 | // 2) Store factory firmware hash for integrity verification 344 | //create hash of firmware in hash buffer 345 | #ifdef STD_VERSION 346 | fw_hash(ctap_buffer); 347 | for (int i = 0; i < crypto_hash_BYTES; i++) { //write 64byte hash to eeprom 348 | eeprom_write_byte((unsigned char*)(2+i), ctap_buffer[i]); // 2-65 used for fw integrity hash 349 | } 350 | memset(ctap_buffer, 0, 2048); 351 | #endif 352 | // 3) Enable flash security after writing 353 | int nn = 0; 354 | nn=flashSecurityLockBits(); 355 | #ifdef DEBUG 356 | Serial.print("Flash security bits "); 357 | if(nn) Serial.print("not "); 358 | Serial.println("written successfully"); 359 | #endif 360 | } 361 | if(!initcheck) { 362 | wipeEEPROM(); 363 | eeprom_write_byte((unsigned char *)1984, (OKversionmaj[0] - '0')); //write fwvermaj, prevents downgrade to previous majver 364 | okeeprom_eeset_timeout((uint8_t*)TIMEOUT); //Default lockout 30 min 365 | unlocked = true; //Flash is not protected, First time use 366 | initialized = false; 367 | #ifdef DEBUG 368 | Serial.println("UNLOCKED, NO PIN SET"); 369 | #endif 370 | } else if(FTFL_FSEC==0x44 && initcheck) { 371 | okcore_flashget_pinhashpublic ((uint8_t*)p1hash, 32); //store PIN hash 372 | okcore_flashget_selfdestructhash ((uint8_t*)sdhash); //store self destruct PIN hash 373 | okcore_flashget_2ndpinhashpublic ((uint8_t*)p2hash); //store plausible deniability PIN hash 374 | okeeprom_eeget_typespeed((uint8_t*)TYPESPEED, 0); 375 | okeeprom_eeget_modkey(&mod_keys_enabled); 376 | #ifdef DEBUG 377 | Serial.println("typespeed = "); 378 | Serial.println(TYPESPEED[0]); 379 | #endif 380 | if (TYPESPEED[0] == 0) { 381 | TYPESPEED[0] = 4; 382 | } else if (TYPESPEED[0] <= 10) { 383 | } 384 | okeeprom_eeget_ledbrightness((uint8_t*)NEO_Brightness); 385 | okeeprom_eeget_touchoffset(&touchoffset); 386 | okeeprom_eeget_timeout((uint8_t*)TIMEOUT); 387 | okeeprom_eeget_keyboardlayout((uint8_t*)KeyboardLayout); 388 | #ifdef DEBUG 389 | Serial.println("KeyboardLayout = "); 390 | Serial.println(KeyboardLayout[0]); 391 | #endif 392 | update_keyboard_layout(); 393 | unlocked = false; 394 | initialized = true; 395 | #ifdef DEBUG 396 | Serial.println("INITIALIZED"); 397 | #endif 398 | SoftTimer.add(&taskInitialized); 399 | } else { //Glitch detect, somehow device is initialized but flash security is not on 400 | CPU_RESTART(); 401 | } 402 | integrityctr2++; 403 | /*************************************/ 404 | //Initialize the random number generator with analog noise, stored NONCE, and chip ID 405 | /*************************************/ 406 | RNG.begin(OKversion, 2045); //Start RNG with the device version 407 | RNG.stir((uint8_t *)&analog1, 2, 4); 408 | RNG.stir((uint8_t *)&analog2, 2, 4); 409 | #ifdef DEBUG 410 | Serial.print("EEPROM Used "); 411 | Serial.println(EEpos_slottypespeed+12); 412 | Serial.println(FTFL_FSEC, HEX); 413 | #endif 414 | rngloop(); //Start RNG 415 | #ifdef OK_Color 416 | initColor(); 417 | rainbowCycle(); 418 | #else 419 | pinMode(BLINKPIN, OUTPUT); 420 | fadein();//Additional delay to make sure button is not pressed during plug into USB 421 | fadeout(); 422 | fadein(); 423 | fadeout(); 424 | #endif 425 | SoftTimer.add(&taskKey); 426 | 427 | if (!initcheck) { 428 | //Default set to no challenge code required for OnlyKey Agent 429 | //User can enable challenge code in OnlyKey app preferences 430 | derived_key_challenge_mode = 1; 431 | stored_key_challenge_mode = 1; 432 | okeeprom_eeset_derived_key_challenge_mode(&derived_key_challenge_mode); 433 | okeeprom_eeset_stored_key_challenge_mode(&stored_key_challenge_mode); 434 | } 435 | 436 | if (onlykeyhw==OK_HW_DUO) { 437 | if (initialized == true && password.profile1hashevaluate()) { 438 | payload(10); 439 | } 440 | } 441 | } 442 | 443 | extern elapsedMillis idletimer; 444 | 445 | /*************************************/ 446 | //Main Loop, Read Key Press Using Capacitive Touch 447 | //Called every 50ms 448 | /*************************************/ 449 | void checkKey(Task* me) { 450 | 451 | //Check for bootloader trigger 452 | if (!digitalRead(33)) { //Trigger bootloader to load firmware by PTA4 low for 3 sec 453 | elapsedMillis waiting; 454 | int jumptobootloader = 0; 455 | while (waiting < 3000) { 456 | delay(100); 457 | jumptobootloader = jumptobootloader + digitalRead(33); 458 | } 459 | if (jumptobootloader==0) { 460 | eeprom_write_byte(0x00, 1); //Go to bootloader 461 | eeprom_write_byte((unsigned char *)0x01, 1); //Firmware ready to load 462 | CPU_RESTART(); //Reboot 463 | } 464 | } 465 | 466 | #ifndef STD_VERSION 467 | // Disable OK_HW_DUO hardware for IN_TRVL firmware 468 | if (onlykeyhw==OK_HW_DUO) { 469 | eeprom_write_byte(0x00, 1); //Go to bootloader 470 | eeprom_write_byte((unsigned char *)0x01, 1); //Firmware ready to load 471 | CPU_RESTART(); //Reboot 472 | } 473 | #endif 474 | 475 | if (setBuffer[8] == 1 && (!isfade || configmode)) //Done receiving packets 476 | { 477 | if (outputmode != KEYBOARD_USB) changeoutputmode(KEYBOARD_USB); //Keyboard USB 478 | process_setreport(); 479 | } 480 | //Check integrity counters and recv usb data 481 | integrityctr1++; 482 | delay(sumofall % 6); //delay 0 - 5 ms 483 | if (unlocked) { 484 | integrityctr2++; 485 | recvmsg(0); 486 | if(initialized && initcheck) { 487 | #ifdef STD_VERSION 488 | yubikey_incr_time(); 489 | #endif 490 | if (TIMEOUT[0] && idletimer >= (TIMEOUT[0]*60000)) { 491 | unlocked = false; 492 | firsttime = true; 493 | password.reset(); //reset the guessed password to NULL 494 | pass_keypress=1; 495 | memset(profilekey, 0, 32); 496 | SoftTimer.add(&taskInitialized); 497 | CPU_RESTART(); 498 | } 499 | } 500 | } else{ 501 | integrityctr2++; 502 | } 503 | 504 | if(configmode && unlocked && !isfade) { 505 | #ifdef OK_Color 506 | NEO_Color = 1; //Red 507 | #endif 508 | fadeon(1); 509 | } 510 | 511 | #ifdef DEBUG 512 | // Auto set default PINs and passphrase for testing 513 | //if (!initialized) { 514 | // okeeprom_eeset_timeout(0); //Disable lockout 515 | // okcore_quick_setup(AUTO_PIN_SET); 516 | //} 517 | #endif 518 | 519 | 520 | int press_duration = touch_sense_loop(); 521 | if (pending_operation==0xF6 || pending_operation==0xF7) { //CTAP2_ERR_DATA_READY or CTAP2_ERR_DATA_WIPE 522 | setcolor(45); //yellow 523 | } else { 524 | if (press_duration) payload(press_duration); 525 | } 526 | 527 | } 528 | /*************************************/ 529 | //Type out on Keyboard the contents of Keybuffer 530 | /*************************************/ 531 | void sendKey(Task* me) { 532 | while ( isfade && NEO_Color == 170 && (uint8_t)*pos != 00 && (uint8_t)*pos != 9 ) { 533 | pos++; 534 | } 535 | int delay1 = (TYPESPEED[0]*TYPESPEED[0]/3)*8; 536 | int delay2 = ((TYPESPEED[0]*TYPESPEED[0])*2); 537 | if ((uint8_t)*pos == 00) { 538 | #ifdef DEBUG 539 | Serial.print(pos); 540 | #endif 541 | Keyboard.end(); 542 | SoftTimer.remove(&taskKB); 543 | SoftTimer.add(&taskKey); 544 | // Set back to default type speed 545 | okeeprom_eeget_typespeed((uint8_t*)TYPESPEED, 0); 546 | if (TYPESPEED[0]==0) TYPESPEED[0] = 4; 547 | return; 548 | } 549 | else if ((uint8_t)*pos == 1) { 550 | if (!isfade) { 551 | Keyboard.press(KEY_TAB); 552 | delay(delay1); 553 | Keyboard.releaseAll(); 554 | delay(delay2); 555 | } 556 | pos++; 557 | } 558 | else if ((uint8_t)*pos == 2) { 559 | if (!isfade) { 560 | Keyboard.press(KEY_RETURN); 561 | delay(delay1); 562 | Keyboard.releaseAll(); 563 | delay(delay2); 564 | } 565 | pos++; 566 | } 567 | else if ((uint8_t)*pos == 9) { 568 | if(profilemode==NONENCRYPTEDPROFILE) return; 569 | #ifdef STD_VERSION 570 | #ifdef DEBUG 571 | Serial.println("Starting U2F..."); 572 | #endif 573 | u2f_button = 1; 574 | unsigned long u2fwait = millis() + 4000; 575 | while(u2f_button && millis() < u2fwait) { 576 | recvmsg(0); 577 | } 578 | u2f_button = 0; 579 | Keyboard.end(); 580 | SoftTimer.remove(&taskKB); 581 | SoftTimer.add(&taskKey); 582 | #endif 583 | return; 584 | } 585 | else if ((uint8_t)*pos >= 10 && (uint8_t)*pos <= 31) { 586 | if (!isfade) { 587 | delay((*pos - 10)*1000); 588 | pos++; 589 | } 590 | } 591 | else if ((uint8_t)*pos == ' ' && (uint8_t)*(pos+1) == 0x5c) { 592 | pos++; 593 | if (!isfade) { 594 | while(*pos) { 595 | if ((uint8_t)*pos == 0x5c) { //modifier/special key comes next 596 | pos++; 597 | keymap_press(0); 598 | delay(delay1); 599 | } else { //regular key 600 | keymap_press(1); 601 | delay(delay1); 602 | } 603 | pos++; 604 | if ((uint8_t)*pos == ' ' || (uint8_t)*pos == 0) { 605 | if ((uint8_t)*pos == ' ') pos++; 606 | Keyboard.releaseAll(); 607 | delay(delay1); 608 | Keyboard.releaseAll(); 609 | resetkeys(); 610 | delay(delay2); 611 | return; 612 | } 613 | } 614 | } 615 | } 616 | else if (*pos){ 617 | if (!isfade) { 618 | Keyboard.press(*pos); 619 | delay(delay1); 620 | Keyboard.releaseAll(); 621 | delay(delay2); 622 | } 623 | pos++; 624 | } 625 | } 626 | /*************************************/ 627 | //Password Checking Loop 628 | /*************************************/ 629 | void payload(int duration) { 630 | if (!unlocked) { 631 | // OnlyKey Go has only 3 buttons, longer press to enter PIN of 4 - 6 632 | if (onlykeyhw==OK_HW_DUO && duration >= 21) { 633 | // <1 sec OK_HW_DUO buttons 1,2,3 = 4,5,6 634 | button_selected = button_selected + 3; 635 | } 636 | #ifdef OK_Color 637 | setcolor(45); // NEO Pixel ON Yellow 638 | #else 639 | analogWrite(BLINKPIN, 255); //LED ON 640 | #endif 641 | } 642 | else { 643 | #ifdef OK_Color 644 | setcolor(0); // NEO Pixel OFF 645 | #else 646 | analogWrite(BLINKPIN, 0); //LED OFF 647 | #endif 648 | } 649 | uint8_t pass_attempts[1]; 650 | uint8_t sincelastregularlogin[1]; 651 | if (session_attempts >= 3) { //Limit 3 password attempts per session to make sure that someone does not accidentally wipe device 652 | exceeded_login_attempts(); 653 | return; 654 | } 655 | integrityctr1++; 656 | if (firsttime) //Get failed login counter from eeprom and increment for new login attempt 657 | { 658 | okeeprom_eeget_failedlogins ((uint8_t*)pass_attempts); 659 | if (pass_attempts[0]) { 660 | okeeprom_eeget_sincelastregularlogin ((uint8_t*)sincelastregularlogin); 661 | if (sincelastregularlogin[0] >= 20) { 662 | for (int i =0; i<32; i++) { 663 | p1hash[i] = 0xFF; 664 | } 665 | okcore_flashset_pinhashpublic ((uint8_t*)p1hash); //permanently wipe pinhash 666 | okeeprom_eeset_sincelastregularlogin (0); 667 | } else { 668 | sincelastregularlogin[0]++; 669 | okeeprom_eeset_sincelastregularlogin ((uint8_t*)sincelastregularlogin); 670 | } 671 | #ifdef DEBUG 672 | Serial.println("Failed PIN attempts since last successful regular PIN entry"); 673 | Serial.println(sincelastregularlogin[0]); 674 | #endif 675 | } 676 | integrityctr2++; 677 | pass_attempts[0]++; 678 | integrityctr1++; 679 | if (pass_attempts[0] > 10) { 680 | #ifdef DEBUG 681 | Serial.println("Password attempts exhausted"); 682 | Serial.println(pass_attempts[0]); 683 | #endif 684 | factorydefault(); 685 | pass_attempts[0] = 0; 686 | return; 687 | } 688 | okeeprom_eeset_failedlogins ((uint8_t*)pass_attempts); 689 | firsttime = false; 690 | } 691 | integrityctr2++; 692 | password.append(button_selected); 693 | integrityctr1++; 694 | delay((sumofall % 4)+(sumofall % 3)); //delay 0 - 5 ms 695 | if (unlocked || password.profile1hashevaluate() || password.profile2hashevaluate()) { 696 | integrityctr2++; 697 | if (unlocked != true) { //A correct PIN was just entered do the following for first login 698 | okeeprom_eeset_failedlogins(0); //Set failed login counter to 0 699 | password.reset(); //reset the guessed password to NULL 700 | session_attempts=0; 701 | if (!configmode) hidprint(HW_MODEL(UNLOCKED)); 702 | SoftTimer.remove(&taskInitialized); 703 | #ifdef DEBUG 704 | Serial.println("UNLOCKED"); 705 | #endif 706 | fadeon(NEO_Color); 707 | fadeoff(85); 708 | if (profilemode!=NONENCRYPTEDPROFILE) { 709 | #ifdef STD_VERSION 710 | U2Finit(); 711 | okeeprom_eeset_sincelastregularlogin(0); //Set failed logins since last regular login to 0 712 | fw_version_changes(); 713 | #endif 714 | } 715 | idletimer=0; 716 | unlocked = true; 717 | if (configmode) { 718 | #ifdef OK_Color 719 | NEO_Color = 1; //Red 720 | #endif 721 | fadeon(1); 722 | } 723 | 724 | unsigned long wait = millis() + 200; 725 | while(millis() < wait) { //Process waiting messages 726 | recvmsg(0); 727 | } 728 | 729 | wipe_usb_buffer(); // Wipe old responses 730 | return; 731 | } else if (!initialized && duration >= 85 && button_selected=='1' && profilemode!=NONENCRYPTEDPROFILE) { 732 | if (onlykeyhw==OK_HW_DUO) okcore_quick_setup(KEYBOARD_ONLYKEY_DUO_NO_BACKUP); 733 | else okcore_quick_setup(KEYBOARD_MANUAL_PIN_SET); 734 | return; 735 | } else if (!initialized && duration >= 85 && button_selected=='2' && profilemode!=NONENCRYPTEDPROFILE) { 736 | if (onlykeyhw==OK_HW_DUO) okcore_quick_setup(KEYBOARD_ONLYKEY_DUO_BACKUP); 737 | else okcore_quick_setup(KEYBOARD_AUTO_PIN_SET); 738 | return; 739 | } else if (!initialized && duration >= 85 && button_selected=='3' && profilemode!=NONENCRYPTEDPROFILE) { 740 | okcore_quick_setup(0); //Setup with keyboard prompt 741 | return; 742 | } else if (pin_set==0 && !initcheck) { 743 | return; 744 | } 745 | else if (pin_set==0) { 746 | } 747 | else if (pin_set<=3) { 748 | #ifdef DEBUG 749 | Serial.print("password appended with "); 750 | Serial.println(button_selected-'0'); 751 | #endif 752 | if (configmode) { 753 | NEO_Color = 45; 754 | blink(1); 755 | NEO_Color = 1; 756 | } 757 | return; 758 | } 759 | else if (pin_set<=6) { 760 | #ifdef DEBUG 761 | Serial.print("SD password appended with "); 762 | Serial.println(button_selected-'0'); 763 | #endif 764 | if (configmode) { 765 | NEO_Color = 45; 766 | blink(1); 767 | NEO_Color = 1; 768 | } 769 | return; 770 | } 771 | else if (pin_set<=9) { 772 | if(profilemode!=NONENCRYPTEDPROFILE){ 773 | #ifdef STD_VERSION 774 | #ifdef DEBUG 775 | Serial.print("2nd profile password appended with "); 776 | Serial.println(button_selected-'0'); 777 | #endif 778 | #endif 779 | } 780 | if (configmode) { 781 | NEO_Color = 45; 782 | blink(1); 783 | NEO_Color = 1; 784 | } 785 | return; 786 | } else if (pin_set==10) { 787 | cancelfadeoffafter20(); 788 | if (button_selected=='1') okcore_quick_setup(KEYBOARD_MANUAL_PIN_SET); //Manual 789 | else okcore_quick_setup(KEYBOARD_AUTO_PIN_SET); //Manual 790 | return; 791 | } 792 | Keyboard.begin(); 793 | *keybuffer = '\0'; 794 | #ifdef DEBUG 795 | Serial.print("Button selected "); 796 | Serial.println(button_selected-'0'); 797 | #endif 798 | idletimer=0; 799 | if (profilemode!=NONENCRYPTEDPROFILE) { 800 | #ifdef STD_VERSION 801 | if (CRYPTO_AUTH == 1 && button_selected==Challenge_button1 && isfade) { 802 | #ifdef DEBUG 803 | Serial.print("Challenge1 entered"); 804 | Serial.println(button_selected-'0'); 805 | #endif 806 | CRYPTO_AUTH++; 807 | return; 808 | } else if (CRYPTO_AUTH == 2 && button_selected==Challenge_button2 && isfade) { 809 | #ifdef DEBUG 810 | Serial.print("Challenge2 entered"); 811 | Serial.println(button_selected-'0'); 812 | #endif 813 | CRYPTO_AUTH++; 814 | return; 815 | } else if ((CRYPTO_AUTH == 3 && button_selected==Challenge_button3 && isfade && packet_buffer_details[0]) || (derived_key_challenge_mode==1 && isfade && packet_buffer_details[0]) || (stored_key_challenge_mode==1 && isfade && packet_buffer_details[0]) || (CRYPTO_AUTH == 3 && packet_buffer_details[0] == OKHMAC && isfade) || (packet_buffer_details[0] == OKWEBAUTHN && isfade)) { 816 | #ifdef DEBUG 817 | Serial.print("Challenge3 entered"); 818 | Serial.println(button_selected-'0'); 819 | #endif 820 | CRYPTO_AUTH = 4; 821 | derived_key_challenge_mode = 0; 822 | stored_key_challenge_mode = 0; 823 | if(packet_buffer_details[0] == OKSIGN) { 824 | recv_buffer[4] = packet_buffer_details[0]; 825 | recv_buffer[5] = packet_buffer_details[1]; 826 | okcrypto_sign(recv_buffer); 827 | } else if (packet_buffer_details[0] == OKDECRYPT) { 828 | recv_buffer[4] = packet_buffer_details[0]; 829 | recv_buffer[5] = packet_buffer_details[1]; 830 | okcrypto_decrypt(recv_buffer); 831 | } else if (packet_buffer_details[0] == OKHMAC) { 832 | okcrypto_hmacsha1(); 833 | } else if (packet_buffer_details[0] == OKWEBAUTHN) { 834 | u2f_button = 1; 835 | unsigned long u2fwait = millis() + 4000; 836 | while(u2f_button && millis() < u2fwait) { 837 | recvmsg(0); 838 | } 839 | u2f_button = 0; 840 | } 841 | CRYPTO_AUTH = 0; 842 | packet_buffer_details[0]=0; 843 | fadeoff(0); 844 | return; 845 | } else if (CRYPTO_AUTH) { //Wrong challenge was entered 846 | CRYPTO_AUTH = 0; 847 | Challenge_button1 = 0; 848 | Challenge_button2 = 0; 849 | Challenge_button3 = 0; 850 | fadeoff(1); 851 | hidprint("Error incorrect challenge was entered"); 852 | analogWrite(BLINKPIN, 255); //LED ON 853 | return; 854 | } else if (duration < 180 && duration >= 72 && button_selected=='1' && !isfade) { 855 | // Backup <4 sec 856 | SoftTimer.remove(&taskKey); 857 | backup(); 858 | SoftTimer.add(&taskKey); 859 | return; 860 | } else if (onlykeyhw==OK_HW_DUO && duration >= 360 && button_selected=='2' && configmode==true) { 861 | factorydefault(); 862 | } else if (duration >= 72 && button_selected=='2' && !isfade) { 863 | // Slot Labels <4 sec 864 | get_slot_labels(1); 865 | if (duration >= 140) get_key_labels(1); 866 | return; 867 | } else if (duration >= 72 && button_selected=='3' && !isfade) { 868 | // Lock and/or switch profiles <4 sec 869 | if (onlykeyhw==OK_HW_DUO && duration < 180) { 870 | if (Duo_config[1] == 0){ // Profile 1 871 | Profile_Offset = 84; //Profile 2 Blue 872 | Duo_config[1] = 1; 873 | } else if (Duo_config[1] == 1){ // Profile 2 874 | Profile_Offset = -42; //Profile 3 Yellow 875 | Duo_config[1] = 2; 876 | } else if (Duo_config[1] == 2){ // Profile 3 877 | Profile_Offset = 128; //Profile 4 Purple 878 | Duo_config[1] = 3; 879 | } else if (Duo_config[1] == 3){ // Profile 4 880 | Profile_Offset = 0; //Profile 1 Green 881 | Duo_config[1] = 0; 882 | } 883 | return; 884 | } 885 | unlocked = false; 886 | firsttime = true; 887 | password.reset(); //reset the guessed password to NULL 888 | pass_keypress=1; 889 | memset(profilekey, 0, 32); 890 | SoftTimer.add(&taskInitialized); 891 | button_selected=0; 892 | CPU_RESTART(); 893 | return; 894 | } 895 | else if (((onlykeyhw==OK_HW_DUO && duration >= 180 && button_selected=='1') || (onlykeyhw!=OK_HW_DUO && duration >= 72 && button_selected=='6')) && !isfade) { 896 | // Config mode 897 | integrityctr1++; 898 | configmode=true; 899 | if (Duo_config[0]!=1) { 900 | unlocked = false; 901 | firsttime = true; 902 | password.reset(); //reset the guessed password to NULL 903 | pass_keypress=1; 904 | SoftTimer.add(&taskInitialized); 905 | } 906 | integrityctr2++; 907 | return; 908 | } 909 | #endif 910 | } 911 | #ifdef OK_Color 912 | setcolor(0); // NEO Pixel OFF 913 | #else 914 | analogWrite(BLINKPIN, 0); //LED OFF 915 | #endif 916 | 917 | if (duration <= 20 && !configmode) { 918 | gen_press(); 919 | } 920 | else if (duration >= 21 && duration < 90 && !configmode) { 921 | gen_hold(); 922 | } 923 | else if (duration >= 90 && !configmode) { 924 | NEO_Color = 1; 925 | blink(2); 926 | } 927 | pos = keybuffer; 928 | SoftTimer.remove(&taskKey); 929 | SoftTimer.add(&taskKB, (unsigned long)TYPESPEED[0]); 930 | return; 931 | } 932 | else if (password.sdhashevaluate()) { 933 | #ifdef DEBUG 934 | Serial.println("Self Destruct PIN entered"); 935 | #endif 936 | factorydefault(); 937 | } 938 | else { 939 | integrityctr2++; 940 | if (pass_keypress < 10) { 941 | #ifdef DEBUG 942 | Serial.print("password appended with "); 943 | Serial.println(button_selected-'0'); 944 | Serial.print("Number of keys entered for this passcode = "); 945 | Serial.println(pass_keypress); 946 | #endif 947 | pass_keypress++; 948 | return; 949 | } else { 950 | firsttime = true; 951 | session_attempts++; 952 | #ifdef OK_Color 953 | NEO_Color = 1; 954 | #endif 955 | blink(3); 956 | #ifdef DEBUG 957 | Serial.print("Login Failed, there are "); 958 | #endif 959 | okeeprom_eeget_failedlogins ((uint8_t*)pass_attempts); 960 | #ifdef DEBUG 961 | Serial.print(10 - pass_attempts[0]); 962 | Serial.println(" remaining attempts before a factory reset will occur"); 963 | Serial.println("WARNING: This will render all device information unrecoverable"); 964 | #endif 965 | password.reset(); //reset the guessed password to NULL 966 | pass_keypress=1; 967 | if (session_attempts >= 3) { //Limit 3 password attempts per session to make sure that someone does not accidentally wipe device 968 | exceeded_login_attempts(); 969 | } 970 | return; 971 | } 972 | } 973 | } 974 | /*************************************/ 975 | //Trigger on short button press 976 | /*************************************/ 977 | void gen_press(void) { 978 | int slot; 979 | 980 | if (profilemode || Duo_config[1] == 2) { 981 | slot=(button_selected-'0')+12; 982 | } else if (Duo_config[1] == 1) { 983 | slot=(button_selected-'0')+6; 984 | } else if (Duo_config[1] == 3) { 985 | slot=(button_selected-'0')+18; 986 | } else { 987 | slot=button_selected-'0'; 988 | } 989 | process_slot(slot); 990 | } 991 | /*************************************/ 992 | //Trigger on long button press 993 | /*************************************/ 994 | void gen_hold(void) { 995 | int slot; 996 | if (profilemode || Duo_config[1] == 2) { 997 | slot=(button_selected-'0')+12; 998 | } else if (Duo_config[1] == 1) { 999 | slot=(button_selected-'0')+6; 1000 | } else if (Duo_config[1] == 3) { 1001 | slot=(button_selected-'0')+18; 1002 | } else { 1003 | slot=button_selected-'0'; 1004 | } 1005 | 1006 | if (onlykeyhw==OK_HW_DUO){ 1007 | process_slot(slot+3); 1008 | } else { 1009 | process_slot(slot+6); 1010 | } 1011 | 1012 | } 1013 | /*************************************/ 1014 | //Load Set Values to Keybuffer 1015 | /*************************************/ 1016 | void process_slot(int s) { 1017 | long GMT; 1018 | char* newcode; 1019 | static uint8_t index; 1020 | uint8_t temp[64]; 1021 | int urllength; 1022 | int usernamelength; 1023 | int passwordlength; 1024 | int otplength; 1025 | uint8_t addchar1; 1026 | uint8_t addchar2; 1027 | uint8_t addchar3; 1028 | uint8_t addchar4; 1029 | uint8_t addchar5; 1030 | uint8_t addchar6; 1031 | uint8_t autolockslot; 1032 | int delay1 = 0; 1033 | int delay2 = 0; 1034 | int delay3 = 0; 1035 | uint8_t *ptr; 1036 | int slot=s; 1037 | bool scripted_mode = false; 1038 | index = 0; 1039 | 1040 | okeeprom_eeget_autolockslot(&autolockslot); 1041 | if ((profilemode==STDPROFILE1 && (slot==(autolockslot & 0xF))) || (profilemode==STDPROFILE2 && slot==((autolockslot >> 4) & 0xF)+12)) { 1042 | lock_ok_and_screen (); 1043 | return; 1044 | } 1045 | okeeprom_eeget_typespeed((uint8_t*)TYPESPEED, slot); 1046 | if (TYPESPEED[0]==0) okeeprom_eeget_typespeed((uint8_t*)TYPESPEED, 0); 1047 | if (TYPESPEED[0]==0) TYPESPEED[0] = 4; 1048 | 1049 | okeeprom_eeget_addchar(&addchar5, slot); 1050 | #ifdef DEBUG 1051 | Serial.println("Additional Character"); 1052 | Serial.println(addchar5); 1053 | #endif 1054 | addchar1 = addchar5 & 0x3; //After Username 1055 | addchar2 = (addchar5 >> 4) & 0x3; //After Password 1056 | addchar3 = (addchar5 >> 6) & 0x1; //After OTP 1057 | addchar6 = (addchar5 >> 7) & 0x1; //After OTP 2 1058 | addchar4 = (addchar5 >> 2) & 0x1; //Before Username 1059 | addchar5 = (addchar5 >> 3) & 0x1; //Before OTP 1060 | 1061 | if (isfade) return; 1062 | #ifdef DEBUG 1063 | Serial.print("Slot Number "); 1064 | Serial.println(button_selected-'0'); 1065 | #endif 1066 | memset(temp, 0, 64); //Wipe all data from buffer 1067 | memset(keybuffer, 0, sizeof(keybuffer)); //Wipe all data from keybuffer 1068 | ptr = temp; 1069 | urllength = okcore_flashget_url(ptr, slot); 1070 | if(urllength > 0) 1071 | { 1072 | #ifdef DEBUG 1073 | Serial.println("Reading URL from Flash..."); 1074 | Serial.print("URL Length = "); 1075 | Serial.println(urllength); 1076 | #endif 1077 | #ifdef DEBUG 1078 | Serial.println("Encrypted"); 1079 | byteprint(temp, urllength); 1080 | #endif 1081 | okcore_aes_gcm_decrypt(temp, slot, 15, profilekey, urllength); 1082 | if (temp[0]==0x08) { // Scripted Mode 1083 | scripted_mode=true; 1084 | ByteToChar2(temp+1, keybuffer, urllength-1, index); 1085 | index=urllength-1; 1086 | } else { 1087 | ByteToChar2(temp, keybuffer, urllength, index); 1088 | index=urllength; 1089 | keybuffer[index] = 2; 1090 | index++; 1091 | #ifdef DEBUG 1092 | Serial.println("Unencrypted"); 1093 | byteprint(temp, urllength); 1094 | Serial.println("Setting RETURN after URL"); 1095 | #endif 1096 | } 1097 | } 1098 | memset(temp, 0, 64); //Wipe all data from buffer 1099 | okeeprom_eeget_delay1(ptr, slot); 1100 | if(temp[0] > 0 && !scripted_mode) 1101 | { 1102 | #ifdef DEBUG 1103 | Serial.println("Reading Delay1 from EEPROM..."); 1104 | Serial.print("Delay "); 1105 | Serial.print(temp[0]); 1106 | Serial.println(" Seconds before entering username"); 1107 | #endif 1108 | if (temp[0] <= 30) 1109 | { 1110 | delay1=temp[0]; 1111 | keybuffer[index] = temp[0] + 10; 1112 | index++; 1113 | } 1114 | } 1115 | if(addchar4 && !scripted_mode) 1116 | { 1117 | #ifdef DEBUG 1118 | Serial.println("Reading before Username addchar..."); 1119 | #endif 1120 | keybuffer[index] = 1; 1121 | #ifdef DEBUG 1122 | Serial.println("TAB"); 1123 | #endif 1124 | index++; 1125 | } 1126 | usernamelength = okcore_flashget_username(ptr, slot); 1127 | if(usernamelength > 0) 1128 | { 1129 | #ifdef DEBUG 1130 | Serial.println("Reading Username from Flash..."); 1131 | Serial.print("Username Length = "); 1132 | Serial.println(usernamelength); 1133 | byteprint(temp, usernamelength); 1134 | #endif 1135 | okcore_aes_gcm_decrypt(temp, slot, 2, profilekey, usernamelength); 1136 | 1137 | ByteToChar2(temp, keybuffer, usernamelength, index); 1138 | #ifdef DEBUG 1139 | byteprint(temp, usernamelength); 1140 | #endif 1141 | index=usernamelength+index; 1142 | } 1143 | memset(temp, 0, 64); //Wipe all data from buffer 1144 | if(addchar1 && !scripted_mode) 1145 | { 1146 | if(addchar1 == 1) { 1147 | #ifdef DEBUG 1148 | Serial.println("Reading after username addchar..."); 1149 | #endif 1150 | keybuffer[index] = 1; 1151 | #ifdef DEBUG 1152 | Serial.println("TAB"); 1153 | #endif 1154 | index++; 1155 | } 1156 | else if(addchar1 == 2) { 1157 | #ifdef DEBUG 1158 | Serial.println("Reading after username addchar..."); 1159 | #endif 1160 | keybuffer[index] = 2; 1161 | #ifdef DEBUG 1162 | Serial.println("RETURN"); 1163 | #endif 1164 | index++; 1165 | } 1166 | } 1167 | memset(temp, 0, 64); //Wipe all data from buffer 1168 | okeeprom_eeget_delay2(ptr, slot); 1169 | if(temp[0] > 0 && !scripted_mode) 1170 | { 1171 | #ifdef DEBUG 1172 | Serial.println("Reading Delay2 from EEPROM..."); 1173 | Serial.print("Delay "); 1174 | Serial.print(temp[0]); 1175 | Serial.println(" Seconds before entering password"); 1176 | #endif 1177 | if (temp[0] <= 30) 1178 | { 1179 | delay2=temp[0]; 1180 | keybuffer[index] = temp[0] + 10; 1181 | index++; 1182 | } 1183 | } 1184 | passwordlength = okeeprom_eeget_password(ptr, slot); 1185 | if(passwordlength > 0) 1186 | { 1187 | #ifdef DEBUG 1188 | Serial.println("Reading Password from EEPROM..."); 1189 | Serial.print("Password Length = "); 1190 | Serial.println(passwordlength); 1191 | Serial.println("Encrypted"); 1192 | byteprint(temp, passwordlength); 1193 | #endif 1194 | okcore_aes_gcm_decrypt(temp, slot, 5, profilekey, passwordlength); 1195 | ByteToChar2(temp, keybuffer, passwordlength, index); 1196 | #ifdef DEBUG 1197 | Serial.println("Unencrypted"); 1198 | byteprint(temp, passwordlength); 1199 | #endif 1200 | index=passwordlength+index; 1201 | } 1202 | memset(temp, 0, 64); //Wipe all data from buffer 1203 | if(addchar2 && !scripted_mode) 1204 | { 1205 | #ifdef DEBUG 1206 | Serial.println("Reading after password addchar..."); 1207 | #endif 1208 | if(addchar2 == 1) { 1209 | keybuffer[index] = 1; 1210 | #ifdef DEBUG 1211 | Serial.println("TAB"); 1212 | #endif 1213 | index++; 1214 | } 1215 | else if(addchar2 == 2) { 1216 | keybuffer[index] = 2; 1217 | #ifdef DEBUG 1218 | Serial.println("RETURN"); 1219 | #endif 1220 | index++; 1221 | } 1222 | } 1223 | memset(temp, 0, 64); //Wipe all data from buffer 1224 | okeeprom_eeget_delay3(ptr, slot); 1225 | if(temp[0] > 0 && !scripted_mode) 1226 | { 1227 | #ifdef DEBUG 1228 | Serial.println("Reading Delay3 from EEPROM..."); 1229 | Serial.print("Delay "); 1230 | Serial.print(temp[0]); 1231 | Serial.println(" Seconds before entering 2FA"); 1232 | #endif 1233 | if (temp[0] <= 30) 1234 | { 1235 | delay3=temp[0]; 1236 | keybuffer[index] = temp[0] + 10; 1237 | index++; 1238 | } 1239 | } 1240 | memset(temp, 0, 64); //Wipe all data from buffer 1241 | if(addchar5 && !scripted_mode) 1242 | { 1243 | #ifdef DEBUG 1244 | Serial.println("Reading before OTP addchar..."); 1245 | #endif 1246 | keybuffer[index] = 1; 1247 | #ifdef DEBUG 1248 | Serial.println("TAB"); 1249 | #endif 1250 | index++; 1251 | } 1252 | otplength = okeeprom_eeget_2FAtype(ptr, slot); 1253 | if(temp[0] > 0) 1254 | { 1255 | if(temp[0] == MFAGOOGLEAUTH) { //Google Auth 1256 | #ifdef DEBUG 1257 | Serial.println("Reading TOTP Key from Flash..."); 1258 | #endif 1259 | otplength = okcore_flashget_2fa_key(ptr, slot); 1260 | #ifdef DEBUG 1261 | Serial.println("Encrypted"); 1262 | byteprint(temp, otplength); 1263 | Serial.print("TOTP Key Length = "); 1264 | Serial.println(otplength); 1265 | #endif 1266 | okcore_aes_gcm_decrypt(temp, slot, 9, profilekey, otplength); 1267 | ByteToChar2(temp, keybuffer, otplength, index); 1268 | #ifdef DEBUG 1269 | Serial.println("Unencrypted"); 1270 | byteprint(temp, otplength); 1271 | #endif 1272 | TOTP totp1 = TOTP(temp, otplength); 1273 | GMT = now(); 1274 | GMT = GMT + delay1 + delay2 + delay3; 1275 | #ifdef DEBUG 1276 | Serial.println(GMT); 1277 | #endif 1278 | newcode = totp1.getCode(GMT); 1279 | if (timeStatus() == timeNotSet) { 1280 | keybuffer[index]='N'; 1281 | keybuffer[index+1]='O'; 1282 | keybuffer[index+2]='T'; 1283 | keybuffer[index+3]='S'; 1284 | keybuffer[index+4]='E'; 1285 | keybuffer[index+5]='T'; 1286 | } else { 1287 | keybuffer[index]=*newcode; 1288 | keybuffer[index+1]=*(newcode+1); 1289 | keybuffer[index+2]=*(newcode+2); 1290 | keybuffer[index+3]=*(newcode+3); 1291 | keybuffer[index+4]=*(newcode+4); 1292 | keybuffer[index+5]=*(newcode+5); 1293 | } 1294 | index=index+6; 1295 | memset(temp, 0, 64); //Wipe all data from buffer 1296 | } 1297 | if(temp[0] == MFAOLDYUBIOTP && profilemode!=NONENCRYPTEDPROFILE) { 1298 | #ifdef DEBUG 1299 | Serial.println("Generating Yubico OTP Legacy..."); 1300 | #endif 1301 | #ifdef STD_VERSION 1302 | yubikeysim(keybuffer + index, 0); 1303 | index=index+44; 1304 | #endif 1305 | } 1306 | if((temp[0] == MFAYUBIOTPandHMACSHA1 || temp[0] == MFAYUBIOTP) && profilemode!=NONENCRYPTEDPROFILE) { 1307 | #ifdef DEBUG 1308 | Serial.println("Generating Yubico OTP..."); 1309 | #endif 1310 | #ifdef STD_VERSION 1311 | int publen; 1312 | publen = yubikeysim(keybuffer + index, slot); 1313 | index=index+32+(publen*2); 1314 | #endif 1315 | } 1316 | if(temp[0] == MFAOLDU2F && profilemode!=NONENCRYPTEDPROFILE) { //U2F 1317 | keybuffer[index] = 9; 1318 | index++; 1319 | } 1320 | } 1321 | if(addchar6) 1322 | { 1323 | #ifdef DEBUG 1324 | Serial.println("Reading after OTP addchar..."); 1325 | #endif 1326 | keybuffer[index] = 1; 1327 | #ifdef DEBUG 1328 | Serial.println("TAB"); 1329 | #endif 1330 | index++; 1331 | } 1332 | if(addchar3) 1333 | { 1334 | #ifdef DEBUG 1335 | Serial.println("Reading after OTP addchar..."); 1336 | #endif 1337 | keybuffer[index] = 2; 1338 | #ifdef DEBUG 1339 | Serial.println("RETURN"); 1340 | #endif 1341 | index++; 1342 | } 1343 | keybuffer[index] = 0; 1344 | #ifdef DEBUG 1345 | Serial.println("Displaying Full Keybuffer"); 1346 | for (int i=0; keybuffer[i]!=0x00; i++) { 1347 | Serial.print 1348 | (keybuffer[i]); 1349 | } 1350 | #endif 1351 | } 1352 | 1353 | void sendInitialized(Task* me) { 1354 | if (onlykeyhw==OK_HW_DUO){ 1355 | int n = RawHID.recv(recv_buffer, 0); // 0 timeout = do not wait 1356 | if (n && recv_buffer[4] == OKPIN && recv_buffer[5]>='0' && initialized == true && unlocked == false && onlykeyhw==OK_HW_DUO) { 1357 | unlocked = false; 1358 | firsttime = true; 1359 | password.reset(); //reset the guessed password to NULL 1360 | okcore_pin_login(); // Received PIN Login Attempt for OnlyKey Duo 1361 | pass_keypress=10; 1362 | button_selected=0; 1363 | payload(10); // Try the PIN 1364 | memset(recv_buffer, 0, sizeof(recv_buffer)); 1365 | if (unlocked == true) { 1366 | hidprint(HW_MODEL(UNLOCKED)); 1367 | } 1368 | } else { 1369 | hidprint("INITIALIZED-D"); 1370 | } 1371 | } else hidprint("INITIALIZED"); 1372 | #ifdef DEBUG 1373 | Serial.println("INITIALIZED"); 1374 | #endif 1375 | } 1376 | 1377 | void resetkeys () { 1378 | delay(200); 1379 | Keyboard.set_key1(0); 1380 | Keyboard.set_key2(0); 1381 | Keyboard.set_key3(0); 1382 | Keyboard.set_key4(0); 1383 | Keyboard.set_key5(0); 1384 | Keyboard.set_key6(0); 1385 | Keyboard.set_modifier(0); 1386 | Keyboard.set_media(0); 1387 | Keyboard.send_now(); 1388 | } 1389 | 1390 | void ctrl_alt_del () { 1391 | //Keyboard.set_modifier(MODIFIERKEY_CTRL); 1392 | // Keyboard.send_now(); 1393 | // Keyboard.set_modifier(MODIFIERKEY_CTRL | MODIFIERKEY_ALT); 1394 | Keyboard.send_now(); 1395 | // Keyboard.set_key1(KEY_DELETE); 1396 | Keyboard.send_now(); 1397 | resetkeys(); 1398 | // Keyboard.set_key1(KEY_ESC); 1399 | Keyboard.send_now(); 1400 | resetkeys(); 1401 | } 1402 | 1403 | void lock_ok_and_screen () { 1404 | unlocked = false; 1405 | firsttime = true; 1406 | password.reset(); //reset the guessed password to NULL 1407 | pass_keypress=1; 1408 | memset(profilekey, 0, 32); 1409 | //Lock Windows and Linux (Gnome Super+L to lock) 1410 | Keyboard.set_modifier(MODIFIERKEY_GUI); 1411 | Keyboard.send_now(); 1412 | Keyboard.set_key1(KEY_L); 1413 | Keyboard.send_now(); 1414 | resetkeys(); 1415 | //Lock Mac 1416 | Keyboard.set_modifier(MODIFIERKEY_CTRL); 1417 | Keyboard.send_now(); 1418 | Keyboard.set_modifier(MODIFIERKEY_CTRL | MODIFIERKEY_GUI); 1419 | Keyboard.send_now(); 1420 | Keyboard.set_key1(KEY_Q); 1421 | Keyboard.send_now(); 1422 | delay(500); // Mac OS-X will not recognize a very short eject press 1423 | Keyboard.set_media(0); 1424 | Keyboard.send_now(); 1425 | resetkeys(); 1426 | CPU_RESTART(); 1427 | } 1428 | 1429 | void fw_hash(unsigned char* hashptr) { 1430 | #ifdef STD_VERSION 1431 | unsigned char smesg[17000]; 1432 | unsigned long adr = fwstartadr; 1433 | //Hash current fw in hashptr 1434 | while (adr <= 0x36060) { //13 blocks of 16384 bytes, last block 0x36060 - 0x3A060 1435 | okcore_flashget_common (smesg, (unsigned long*)adr, 16384); //Read each block 1436 | if (adr == (unsigned long)fwstartadr) { 1437 | crypto_hash(hashptr,smesg,16384); //hash this block 1438 | } 1439 | else { //if not first block, hash with previous block hash 1440 | memcpy(smesg + 16384, hashptr, crypto_hash_BYTES); 1441 | crypto_hash(hashptr,smesg,(16384+crypto_hash_BYTES)); 1442 | } 1443 | adr = adr + 16384; 1444 | } 1445 | return; 1446 | #endif 1447 | } 1448 | 1449 | void keymap_press (char key) { 1450 | extern uint8_t keyboard_modifier_keys; 1451 | extern uint8_t keyboard_keys[6]; 1452 | if ((uint8_t)*pos>'0' && (uint8_t)*pos<='9') { 1453 | delay((*(pos)-'0')*1000); 1454 | } else if ((uint8_t)*pos=='t' || (uint8_t)*pos=='r') { 1455 | if (key) { 1456 | Keyboard.press(*pos); 1457 | key=0; 1458 | } 1459 | else if ((uint8_t)*pos=='t') { 1460 | key = KEY_TAB; 1461 | } 1462 | else if ((uint8_t)*pos=='r') { 1463 | key = KEY_RETURN; 1464 | } 1465 | } else if (mod_keys_enabled) { 1466 | if (key) { 1467 | Keyboard.press(*pos); 1468 | key=0; 1469 | } else { 1470 | if ((uint8_t)*pos=='p') key = KEY_PRINTSCREEN; 1471 | else if ((uint8_t)*pos=='h') key = KEY_HOME; 1472 | else if ((uint8_t)*pos=='u') key = KEY_PAGE_UP; 1473 | else if ((uint8_t)*pos=='o') key = KEY_PAGE_DOWN; 1474 | else if ((uint8_t)*pos=='e') key = KEY_END; 1475 | else if ((uint8_t)*pos=='d') key = KEY_DELETE; 1476 | else if ((uint8_t)*pos=='b') key = KEY_BACKSPACE; 1477 | else if ((uint8_t)*pos=='L') key = KEY_LEFT; 1478 | else if ((uint8_t)*pos=='R') key = KEY_RIGHT; 1479 | else if ((uint8_t)*pos=='U') key = KEY_UP; 1480 | else if ((uint8_t)*pos=='D') key = KEY_DOWN; 1481 | else if ((uint8_t)*pos=='E') key = KEY_ESC; 1482 | 1483 | if ((uint8_t)*pos=='c') keyboard_modifier_keys |= MODIFIERKEY_CTRL; 1484 | else if ((uint8_t)*pos=='s') keyboard_modifier_keys |= MODIFIERKEY_SHIFT; 1485 | else if ((uint8_t)*pos=='a') keyboard_modifier_keys |= MODIFIERKEY_ALT; 1486 | else if ((uint8_t)*pos=='g') keyboard_modifier_keys |= MODIFIERKEY_GUI; 1487 | } 1488 | } 1489 | 1490 | if (keyboard_keys[0] == 0) keyboard_keys[0] = key; 1491 | else if (keyboard_keys[1] == 0) keyboard_keys[1] = key; 1492 | else if (keyboard_keys[2] == 0) keyboard_keys[2] = key; 1493 | else if (keyboard_keys[3] == 0) keyboard_keys[3] = key; 1494 | else if (keyboard_keys[4] == 0) keyboard_keys[4] = key; 1495 | else if (keyboard_keys[5] == 0) keyboard_keys[5] = key; 1496 | Keyboard.send_now(); 1497 | } 1498 | 1499 | void exceeded_login_attempts() { 1500 | #ifdef DEBUG 1501 | Serial.print("password attempts for this session exceeded, remove OnlyKey and reinsert to attempt login"); 1502 | #endif 1503 | while(1==1) 1504 | { 1505 | hidprint("Error password attempts for this session exceeded, remove OnlyKey and reinsert to attempt login"); 1506 | #ifdef OK_Color 1507 | NEO_Color = 1; //Red 1508 | #endif 1509 | blink(5); 1510 | } 1511 | } 1512 | 1513 | 1514 | 1515 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OnlyKey Firmware 2 | 3 | This is the official firmware for **OnlyKey** 4 | 5 | OnlyKey can be purchased here: [OnlyKey order](https://onlykey.io) 6 | 7 | ## Getting Started 8 | 9 | Just getting started with OnlyKey? 10 | 11 | [Start here](https://onlykey.io/start) 12 | 13 | ## About 14 | 15 | The firmware is the software that runs on the OnlyKey itself. In order to load firmware follow the instructions in the [User's Guide here](https://docs.crp.to/usersguide.html#loading-onlykey-firmware) 16 | 17 | ## Development 18 | 19 | OnlyKey firmware is open source and new features are added with each firmware release. A list of of supported features are available [here](https://docs.crp.to/features.html) 20 | 21 | ## Support 22 | 23 | Check out the [OnlyKey Support Forum](https://forum.onlykey.io) 24 | 25 | Check out the [OnlyKey Documentation](https://docs.crp.to) 26 | 27 | ## Libraries 28 | 29 | OnlyKey firmware uses additional libraries that are available [here](https://github.com/trustcrypto/libraries). 30 | 31 | # Legal things 32 | ## Cryptography Notice 33 | 34 | This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. 35 | BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. 36 | See for more information. 37 | 38 | The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms. 39 | The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code. 40 | 41 | The following cryptographic software is included in this distribution: 42 | 43 | "MBED TLS PROJECT" - https://github.com/ARMmbed/mbedtls 44 | "MICRO-ECC PROJECT" - https://github.com/kmackay/micro-ecc 45 | "ARDUINOLIBS PROJECT" - https://rweather.github.io/arduinolibs/crypto.html 46 | "YUBICO-C PROJECT" - https://github.com/Yubico/yubico-c 47 | 48 | For more information on export restrictions see: http://www.apache.org/licenses/exports/ 49 | 50 | ## Source 51 | 52 | [OnlyKey Firmware on Github](https://github.com/trustcrypto/OnlyKey-Firmware) 53 | -------------------------------------------------------------------------------- /keylayouts.h: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #ifndef KEYLAYOUTS_H__ 108 | #define KEYLAYOUTS_H__ 109 | 110 | #include 111 | #include 112 | 113 | 114 | 115 | #ifdef __cplusplus 116 | extern "C"{ 117 | #endif 118 | 119 | #define LAYOUT_USA_ENGLISH 0x01 120 | #define LAYOUT_CANADIAN_FRENCH 0x02 121 | #define LAYOUT_CANADIAN_MULTILINGUAL 0x03 122 | #define LAYOUT_DANISH 0x04 123 | #define LAYOUT_FINNISH 0x05 124 | #define LAYOUT_FRENCH 0x06 125 | #define LAYOUT_FRENCH_BELGIAN 0x07 126 | #define LAYOUT_FRENCH_SWISS 0x08 127 | #define LAYOUT_GERMAN 0x09 128 | #define LAYOUT_GERMAN_MAC 0x0A 129 | #define LAYOUT_GERMAN_SWISS 0x0B 130 | #define LAYOUT_ICELANDIC 0x0C 131 | #define LAYOUT_IRISH 0x0D 132 | #define LAYOUT_ITALIAN 0x0E 133 | #define LAYOUT_NORWEGIAN 0x0F 134 | #define LAYOUT_PORTUGUESE 0x10 135 | #define LAYOUT_PORTUGUESE_BRAZILIAN 0x11 136 | #define LAYOUT_SPANISH 0x12 137 | #define LAYOUT_SPANISH_LATIN_AMERICA 0x13 138 | #define LAYOUT_SWEDISH 0x14 139 | #define LAYOUT_TURKISH 0x15 140 | #define LAYOUT_UNITED_KINGDOM 0x16 141 | #define LAYOUT_US_INTERNATIONAL 0x17 142 | #define LAYOUT_CZECH 0x18 143 | #define LAYOUT_SERBIAN_LATIN_ONLY 0x19 144 | #define LAYOUT_HUNGARIAN 0x1A 145 | #define LAYOUT_DANISH_MAC 0x1B 146 | #define LAYOUT_DVORAK 0x1C 147 | 148 | 149 | // http://en.wikipedia.org/wiki/Keyboard_layout 150 | 151 | 152 | #define MODIFIERKEY_CTRL ( 0x01 | 0xE000 ) 153 | #define MODIFIERKEY_SHIFT ( 0x02 | 0xE000 ) 154 | #define MODIFIERKEY_ALT ( 0x04 | 0xE000 ) 155 | #define MODIFIERKEY_GUI ( 0x08 | 0xE000 ) 156 | #define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0xE000 ) 157 | #define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0xE000 ) 158 | #define MODIFIERKEY_LEFT_ALT ( 0x04 | 0xE000 ) 159 | #define MODIFIERKEY_LEFT_GUI ( 0x08 | 0xE000 ) 160 | #define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0xE000 ) 161 | #define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0xE000 ) 162 | #define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0xE000 ) 163 | #define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0xE000 ) 164 | 165 | #define KEY_SYSTEM_POWER_DOWN ( 0x81 | 0xE200 ) 166 | #define KEY_SYSTEM_SLEEP ( 0x82 | 0xE200 ) 167 | #define KEY_SYSTEM_WAKE_UP ( 0x83 | 0xE200 ) 168 | 169 | #define KEY_MEDIA_EJECT 0x80 170 | #define KEY_MEDIA_VOLUME_INC 0x01 171 | 172 | #define KEY_A ( 4 | 0xF000 ) 173 | #define KEY_B ( 5 | 0xF000 ) 174 | #define KEY_C ( 6 | 0xF000 ) 175 | #define KEY_D ( 7 | 0xF000 ) 176 | #define KEY_E ( 8 | 0xF000 ) 177 | #define KEY_F ( 9 | 0xF000 ) 178 | #define KEY_G ( 10 | 0xF000 ) 179 | #define KEY_H ( 11 | 0xF000 ) 180 | #define KEY_I ( 12 | 0xF000 ) 181 | #define KEY_J ( 13 | 0xF000 ) 182 | #define KEY_K ( 14 | 0xF000 ) 183 | #define KEY_L ( 15 | 0xF000 ) 184 | #define KEY_M ( 16 | 0xF000 ) 185 | #define KEY_N ( 17 | 0xF000 ) 186 | #define KEY_O ( 18 | 0xF000 ) 187 | #define KEY_P ( 19 | 0xF000 ) 188 | #define KEY_Q ( 20 | 0xF000 ) 189 | #define KEY_R ( 21 | 0xF000 ) 190 | #define KEY_S ( 22 | 0xF000 ) 191 | #define KEY_T ( 23 | 0xF000 ) 192 | #define KEY_U ( 24 | 0xF000 ) 193 | #define KEY_V ( 25 | 0xF000 ) 194 | #define KEY_W ( 26 | 0xF000 ) 195 | #define KEY_X ( 27 | 0xF000 ) 196 | #define KEY_Y ( 28 | 0xF000 ) 197 | #define KEY_Z ( 29 | 0xF000 ) 198 | #define KEY_1 ( 30 | 0xF000 ) 199 | #define KEY_2 ( 31 | 0xF000 ) 200 | #define KEY_3 ( 32 | 0xF000 ) 201 | #define KEY_4 ( 33 | 0xF000 ) 202 | #define KEY_5 ( 34 | 0xF000 ) 203 | #define KEY_6 ( 35 | 0xF000 ) 204 | #define KEY_7 ( 36 | 0xF000 ) 205 | #define KEY_8 ( 37 | 0xF000 ) 206 | #define KEY_9 ( 38 | 0xF000 ) 207 | #define KEY_0 ( 39 | 0xF000 ) 208 | #define KEY_ENTER ( 40 | 0xF000 ) 209 | #define KEY_ESC ( 41 | 0xF000 ) 210 | #define KEY_BACKSPACE ( 42 | 0xF000 ) 211 | #define KEY_TAB ( 43 | 0xF000 ) 212 | #define KEY_SPACE ( 44 | 0xF000 ) 213 | #define KEY_MINUS ( 45 | 0xF000 ) 214 | #define KEY_EQUAL ( 46 | 0xF000 ) 215 | #define KEY_LEFT_BRACE ( 47 | 0xF000 ) 216 | #define KEY_RIGHT_BRACE ( 48 | 0xF000 ) 217 | #define KEY_BACKSLASH ( 49 | 0xF000 ) 218 | #define KEY_NON_US_NUM ( 50 | 0xF000 ) 219 | #define KEY_SEMICOLON ( 51 | 0xF000 ) 220 | #define KEY_QUOTE ( 52 | 0xF000 ) 221 | #define KEY_TILDE ( 53 | 0xF000 ) 222 | #define KEY_COMMA ( 54 | 0xF000 ) 223 | #define KEY_PERIOD ( 55 | 0xF000 ) 224 | #define KEY_SLASH ( 56 | 0xF000 ) 225 | #define KEY_CAPS_LOCK ( 57 | 0xF000 ) 226 | #define KEY_F1 ( 58 | 0xF000 ) 227 | #define KEY_F2 ( 59 | 0xF000 ) 228 | #define KEY_F3 ( 60 | 0xF000 ) 229 | #define KEY_F4 ( 61 | 0xF000 ) 230 | #define KEY_F5 ( 62 | 0xF000 ) 231 | #define KEY_F6 ( 63 | 0xF000 ) 232 | #define KEY_F7 ( 64 | 0xF000 ) 233 | #define KEY_F8 ( 65 | 0xF000 ) 234 | #define KEY_F9 ( 66 | 0xF000 ) 235 | #define KEY_F10 ( 67 | 0xF000 ) 236 | #define KEY_F11 ( 68 | 0xF000 ) 237 | #define KEY_F12 ( 69 | 0xF000 ) 238 | #define KEY_PRINTSCREEN ( 70 | 0xF000 ) 239 | #define KEY_SCROLL_LOCK ( 71 | 0xF000 ) 240 | #define KEY_PAUSE ( 72 | 0xF000 ) 241 | #define KEY_INSERT ( 73 | 0xF000 ) 242 | #define KEY_HOME ( 74 | 0xF000 ) 243 | #define KEY_PAGE_UP ( 75 | 0xF000 ) 244 | #define KEY_DELETE ( 76 | 0xF000 ) 245 | #define KEY_END ( 77 | 0xF000 ) 246 | #define KEY_PAGE_DOWN ( 78 | 0xF000 ) 247 | #define KEY_RIGHT ( 79 | 0xF000 ) 248 | #define KEY_LEFT ( 80 | 0xF000 ) 249 | #define KEY_DOWN ( 81 | 0xF000 ) 250 | #define KEY_UP ( 82 | 0xF000 ) 251 | #define KEY_NUM_LOCK ( 83 | 0xF000 ) 252 | #define KEYPAD_SLASH ( 84 | 0xF000 ) 253 | #define KEYPAD_ASTERIX ( 85 | 0xF000 ) 254 | #define KEYPAD_MINUS ( 86 | 0xF000 ) 255 | #define KEYPAD_PLUS ( 87 | 0xF000 ) 256 | #define KEYPAD_ENTER ( 88 | 0xF000 ) 257 | #define KEYPAD_1 ( 89 | 0xF000 ) 258 | #define KEYPAD_2 ( 90 | 0xF000 ) 259 | #define KEYPAD_3 ( 91 | 0xF000 ) 260 | #define KEYPAD_4 ( 92 | 0xF000 ) 261 | #define KEYPAD_5 ( 93 | 0xF000 ) 262 | #define KEYPAD_6 ( 94 | 0xF000 ) 263 | #define KEYPAD_7 ( 95 | 0xF000 ) 264 | #define KEYPAD_8 ( 96 | 0xF000 ) 265 | #define KEYPAD_9 ( 97 | 0xF000 ) 266 | #define KEYPAD_0 ( 98 | 0xF000 ) 267 | #define KEYPAD_PERIOD ( 99 | 0xF000 ) 268 | #define KEY_NON_US_BS ( 100 | 0xF000 ) 269 | #define KEY_MENU ( 101 | 0xF000 ) 270 | #define KEY_F13 ( 104 | 0xF000 ) 271 | #define KEY_F14 ( 105 | 0xF000 ) 272 | #define KEY_F15 ( 106 | 0xF000 ) 273 | #define KEY_F16 ( 107 | 0xF000 ) 274 | #define KEY_F17 ( 108 | 0xF000 ) 275 | #define KEY_F18 ( 109 | 0xF000 ) 276 | #define KEY_F19 ( 110 | 0xF000 ) 277 | #define KEY_F20 ( 111 | 0xF000 ) 278 | #define KEY_F21 ( 112 | 0xF000 ) 279 | #define KEY_F22 ( 113 | 0xF000 ) 280 | #define KEY_F23 ( 114 | 0xF000 ) 281 | #define KEY_F24 ( 115 | 0xF000 ) 282 | 283 | 284 | // for compatibility with Leonardo's slightly different names 285 | #define KEY_UP_ARROW KEY_UP 286 | #define KEY_DOWN_ARROW KEY_DOWN 287 | #define KEY_LEFT_ARROW KEY_LEFT 288 | #define KEY_RIGHT_ARROW KEY_RIGHT 289 | #define KEY_RETURN KEY_ENTER 290 | #define KEY_LEFT_CTRL MODIFIERKEY_LEFT_CTRL 291 | #define KEY_LEFT_SHIFT MODIFIERKEY_LEFT_SHIFT 292 | #define KEY_LEFT_ALT MODIFIERKEY_LEFT_ALT 293 | #define KEY_LEFT_GUI MODIFIERKEY_LEFT_GUI 294 | #define KEY_RIGHT_CTRL MODIFIERKEY_RIGHT_CTRL 295 | #define KEY_RIGHT_SHIFT MODIFIERKEY_RIGHT_SHIFT 296 | #define KEY_RIGHT_ALT MODIFIERKEY_RIGHT_ALT 297 | #define KEY_RIGHT_GUI MODIFIERKEY_RIGHT_GUI 298 | 299 | #define KEYCODE_TYPE uint16_t 300 | 301 | extern void update_keyboard_layout(); 302 | extern KEYCODE_TYPE keycodes_ascii[]; 303 | extern KEYCODE_TYPE keycodes_iso_8859_1[]; 304 | 305 | #ifdef __cplusplus 306 | } // extern "C" 307 | #endif 308 | 309 | #endif 310 | -------------------------------------------------------------------------------- /usb_desc.h: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #ifndef _usb_desc_h_ 108 | #define _usb_desc_h_ 109 | 110 | // This header is NOT meant to be included when compiling 111 | // user sketches in Arduino. The low-level functions 112 | // provided by usb_dev.c are meant to be called only by 113 | // code which provides higher-level interfaces to the user. 114 | 115 | #include 116 | #include 117 | 118 | #define ENDPOINT_UNUSED 0x00 119 | #define ENDPOINT_TRANSIMIT_ONLY 0x15 120 | #define ENDPOINT_RECEIVE_ONLY 0x19 121 | #define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D 122 | 123 | /* 124 | Each group of #define lines below corresponds to one of the 125 | settings in the Tools > USB Type menu. This file defines what 126 | type of USB device is actually created for each of those menu 127 | options. 128 | Each "interface" is a set of functionality your PC or Mac will 129 | use and treat as if it is a unique device. Within each interface, 130 | the "endpoints" are the actual communication channels. Most 131 | interfaces use 1, 2 or 3 endpoints. By editing only this file, 132 | you can customize the USB Types to be any collection of interfaces. 133 | To modify a USB Type, delete the XYZ_INTERFACE lines for any 134 | interfaces you wish to remove, and copy them from another USB Type 135 | for any you want to add. 136 | Give each interface a unique number, and edit NUM_INTERFACE to 137 | reflect the total number of interfaces. 138 | Next, assign unique endpoint numbers to all the endpoints across 139 | all the interfaces your device has. You can reuse an endpoint 140 | number for transmit and receive, but the same endpoint number must 141 | not be used twice to transmit, or twice to receive. 142 | Most endpoints also require their maximum size, and some also 143 | need an interval specification (the number of milliseconds the 144 | PC will check for data from that endpoint). For existing 145 | interfaces, usually these other settings should not be changed. 146 | Edit NUM_ENDPOINTS to be at least the largest endpoint number used. 147 | Edit NUM_USB_BUFFERS to control how much memory the USB stack will 148 | allocate. At least 2 should be used for each endpoint. More 149 | memory will allow higher throughput for user programs that have 150 | high latency (eg, spending time doing things other than interacting 151 | with the USB). 152 | Edit the ENDPOINT*_CONFIG lines so each endpoint is configured 153 | the proper way (transmit, receive, or both). 154 | If you are using existing interfaces (making your own device with 155 | a different set of interfaces) the code in all other files should 156 | automatically adapt to the new endpoints you specify here. 157 | If you need to create a new type of interface, you'll need to write 158 | the code which sends and receives packets, and presents an API to 159 | the user. Usually, a pair of files are added for the actual code, 160 | and code is also added in usb_dev.c for any control transfers, 161 | interrupt-level code, or other very low-level stuff not possible 162 | from the packet send/receive functons. Code also is added in 163 | usb_inst.c to create an instance of your C++ object. 164 | You may edit the Vendor and Product ID numbers, and strings. If 165 | the numbers are changed, Teensyduino may not be able to automatically 166 | find and reboot your board when you click the Upload button in 167 | the Arduino IDE. You will need to press the Program button on 168 | Teensy to initiate programming. 169 | Some operating systems, especially Windows, may cache USB device 170 | info. Changes to the device name may not update on the same 171 | computer unless the vendor or product ID numbers change, or the 172 | "bcdDevice" revision code is increased. 173 | If these instructions are missing steps or could be improved, please 174 | let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports 175 | */ 176 | 177 | #if defined(USB_SERIAL) 178 | #define VENDOR_ID 0x16C0 179 | #define PRODUCT_ID 0x0483 180 | #define DEVICE_CLASS 2 // 2 = Communication Class 181 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 182 | #define MANUFACTURER_NAME_LEN 11 183 | #define PRODUCT_NAME {'U','S','B',' ','S','e','r','i','a','l'} 184 | #define PRODUCT_NAME_LEN 10 185 | #define EP0_SIZE 64 186 | #define NUM_ENDPOINTS 4 187 | #define NUM_USB_BUFFERS 12 188 | #define NUM_INTERFACE 2 189 | #define CDC_STATUS_INTERFACE 0 190 | #define CDC_DATA_INTERFACE 1 191 | #define CDC_ACM_ENDPOINT 2 192 | #define CDC_RX_ENDPOINT 3 193 | #define CDC_TX_ENDPOINT 4 194 | #define CDC_ACM_SIZE 16 195 | #define CDC_RX_SIZE 64 196 | #define CDC_TX_SIZE 64 197 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY 198 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 199 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY 200 | 201 | #elif defined(USB_HID) 202 | #define VENDOR_ID 0x16C0 203 | #define PRODUCT_ID 0x0482 204 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 205 | #define MANUFACTURER_NAME_LEN 11 206 | #define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} 207 | #define PRODUCT_NAME_LEN 23 208 | #define EP0_SIZE 64 209 | #define NUM_ENDPOINTS 5 210 | #define NUM_USB_BUFFERS 24 211 | #define NUM_INTERFACE 4 212 | #define SEREMU_INTERFACE 2 // Serial emulation 213 | #define SEREMU_TX_ENDPOINT 1 214 | #define SEREMU_TX_SIZE 64 215 | #define SEREMU_TX_INTERVAL 1 216 | #define SEREMU_RX_ENDPOINT 2 217 | #define SEREMU_RX_SIZE 32 218 | #define SEREMU_RX_INTERVAL 2 219 | #define KEYBOARD_INTERFACE 0 // Keyboard 220 | #define KEYBOARD_ENDPOINT 3 221 | #define KEYBOARD_SIZE 8 222 | #define KEYBOARD_INTERVAL 1 223 | #define MOUSE_INTERFACE 1 // Mouse 224 | #define MOUSE_ENDPOINT 5 225 | #define MOUSE_SIZE 8 226 | #define MOUSE_INTERVAL 1 227 | #define JOYSTICK_INTERFACE 3 // Joystick 228 | #define JOYSTICK_ENDPOINT 4 229 | #define JOYSTICK_SIZE 16 230 | #define JOYSTICK_INTERVAL 2 231 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 232 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 233 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY 234 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY 235 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY 236 | 237 | #elif defined(USB_SERIAL_HID) 238 | #define VENDOR_ID 0x16C0 239 | #define PRODUCT_ID 0x0487 240 | #define DEVICE_CLASS 0xEF 241 | #define DEVICE_SUBCLASS 0x02 242 | #define DEVICE_PROTOCOL 0x01 243 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 244 | #define MANUFACTURER_NAME_LEN 11 245 | #define PRODUCT_NAME {'S','e','r','i','a','l','/','K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'} 246 | #define PRODUCT_NAME_LEN 30 247 | #define EP0_SIZE 64 248 | #define NUM_ENDPOINTS 6 249 | #define NUM_USB_BUFFERS 30 250 | #define NUM_INTERFACE 5 251 | #define CDC_IAD_DESCRIPTOR 1 252 | #define CDC_STATUS_INTERFACE 0 253 | #define CDC_DATA_INTERFACE 1 // Serial 254 | #define CDC_ACM_ENDPOINT 2 255 | #define CDC_RX_ENDPOINT 3 256 | #define CDC_TX_ENDPOINT 4 257 | #define CDC_ACM_SIZE 16 258 | #define CDC_RX_SIZE 64 259 | #define CDC_TX_SIZE 64 260 | #define KEYBOARD_INTERFACE 2 // Keyboard 261 | #define KEYBOARD_ENDPOINT 1 262 | #define KEYBOARD_SIZE 8 263 | #define KEYBOARD_INTERVAL 1 264 | #define MOUSE_INTERFACE 3 // Mouse 265 | #define MOUSE_ENDPOINT 5 266 | #define MOUSE_SIZE 8 267 | #define MOUSE_INTERVAL 2 268 | #define JOYSTICK_INTERFACE 4 // Joystick 269 | #define JOYSTICK_ENDPOINT 6 270 | #define JOYSTICK_SIZE 16 271 | #define JOYSTICK_INTERVAL 1 272 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 273 | #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY 274 | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY 275 | #define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY 276 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY 277 | #define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY 278 | 279 | #elif defined(USB_MIDI) 280 | #define VENDOR_ID 0x16C0 281 | #define PRODUCT_ID 0x0485 282 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 283 | #define MANUFACTURER_NAME_LEN 11 284 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I'} 285 | #define PRODUCT_NAME_LEN 11 286 | #define EP0_SIZE 64 287 | #define NUM_ENDPOINTS 4 288 | #define NUM_USB_BUFFERS 16 289 | #define NUM_INTERFACE 2 290 | #define SEREMU_INTERFACE 1 // Serial emulation 291 | #define SEREMU_TX_ENDPOINT 1 292 | #define SEREMU_TX_SIZE 64 293 | #define SEREMU_TX_INTERVAL 1 294 | #define SEREMU_RX_ENDPOINT 2 295 | #define SEREMU_RX_SIZE 32 296 | #define SEREMU_RX_INTERVAL 2 297 | #define MIDI_INTERFACE 0 // MIDI 298 | #define MIDI_TX_ENDPOINT 3 299 | #define MIDI_TX_SIZE 64 300 | #define MIDI_RX_ENDPOINT 4 301 | #define MIDI_RX_SIZE 64 302 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 303 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 304 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY 305 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 306 | 307 | 308 | #elif defined(USB_RAWHID) 309 | #define VENDOR_ID 0x1d50 310 | #define PRODUCT_ID 0x60fc 311 | #define RAWHID_USAGE_PAGE 0xf1d0 // Changed for FIDO support 312 | #define RAWHID_USAGE 0x01 // Changed for FIDO support 313 | #define RAWHID_USAGE_PAGE2 0xffab 314 | #define RAWHID_USAGE2 0x02 315 | #define MANUFACTURER_NAME {'C','R','Y','P','T','O','T','R','U','S','T'} 316 | #define MANUFACTURER_NAME_LEN 11 317 | #define PRODUCT_NAME {'O','N','L','Y','K','E','Y'} 318 | #define PRODUCT_NAME_LEN 7 319 | #define EP0_SIZE 64 320 | #define NUM_ENDPOINTS 7 321 | #define NUM_USB_BUFFERS 30 322 | #define NUM_INTERFACE 4 323 | #define RAWHID_INTERFACE 1 // RawHID 324 | #define RAWHID_TX_ENDPOINT 3 325 | #define RAWHID_TX_SIZE 64 326 | #define RAWHID_TX_INTERVAL 5 327 | #define RAWHID_RX_ENDPOINT 4 328 | #define RAWHID_RX_SIZE 64 329 | #define RAWHID_RX_INTERVAL 5 330 | #define RAWHID_INTERFACE2 2 // RawHID2 331 | #define RAWHID_TX_ENDPOINT2 5 332 | #define RAWHID_RX_ENDPOINT2 6 333 | #define SEREMU_INTERFACE 3 // Serial emulation 334 | #define SEREMU_TX_ENDPOINT 1 335 | #define SEREMU_TX_SIZE 64 336 | #define SEREMU_TX_INTERVAL 5 337 | #define SEREMU_RX_ENDPOINT 2 338 | #define SEREMU_RX_SIZE 32 339 | #define SEREMU_RX_INTERVAL 2 340 | #define KEYBOARD_INTERFACE 0 // Keyboard 341 | #define KEYBOARD_ENDPOINT 7 342 | #define KEYBOARD_SIZE 8 343 | #define KEYBOARD_INTERVAL 5 344 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 345 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 346 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY 347 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 348 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY 349 | #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY 350 | #define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY 351 | 352 | /* 353 | #define VENDOR_ID 0x1d50 354 | #define PRODUCT_ID 0x60fc 355 | #define RAWHID_USAGE_PAGE 0xf1d0 // Changed for FIDO support 356 | #define RAWHID_USAGE 0x01 // Changed for FIDO support 357 | #define RAWHID_USAGE_PAGE2 0xffab 358 | #define RAWHID_USAGE2 0x02 359 | #define MANUFACTURER_NAME {'C','R','Y','P','T','O','T','R','U','S','T'} 360 | #define MANUFACTURER_NAME_LEN 11 361 | #define PRODUCT_NAME {'O','N','L','Y','K','E','Y'} 362 | #define PRODUCT_NAME_LEN 7 363 | #define EP0_SIZE 64 364 | #define NUM_ENDPOINTS 5 365 | #define NUM_USB_BUFFERS 30 366 | #define NUM_INTERFACE 3 367 | #define RAWHID_INTERFACE 1 // RawHID 368 | #define RAWHID_TX_ENDPOINT 1 369 | #define RAWHID_TX_SIZE 64 370 | #define RAWHID_TX_INTERVAL 1 371 | #define RAWHID_RX_ENDPOINT 2 372 | #define RAWHID_RX_SIZE 64 373 | #define RAWHID_RX_INTERVAL 1 374 | #define RAWHID_INTERFACE2 2 // RawHID2 375 | #define RAWHID_TX_ENDPOINT2 3 376 | #define RAWHID_RX_ENDPOINT2 4 377 | #define KEYBOARD_INTERFACE 0 // Keyboard 378 | #define KEYBOARD_ENDPOINT 5 379 | #define KEYBOARD_SIZE 8 380 | #define KEYBOARD_INTERVAL 1 381 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 382 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 383 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY 384 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 385 | #define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY 386 | */ 387 | 388 | 389 | 390 | #elif defined(USB_FLIGHTSIM) 391 | #define VENDOR_ID 0x16C0 392 | #define PRODUCT_ID 0x0488 393 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 394 | #define MANUFACTURER_NAME_LEN 11 395 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'} 396 | #define PRODUCT_NAME_LEN 26 397 | #define EP0_SIZE 64 398 | #define NUM_ENDPOINTS 4 399 | #define NUM_USB_BUFFERS 20 400 | #define NUM_INTERFACE 2 401 | #define FLIGHTSIM_INTERFACE 0 // Flight Sim Control 402 | #define FLIGHTSIM_TX_ENDPOINT 3 403 | #define FLIGHTSIM_TX_SIZE 64 404 | #define FLIGHTSIM_TX_INTERVAL 1 405 | #define FLIGHTSIM_RX_ENDPOINT 4 406 | #define FLIGHTSIM_RX_SIZE 64 407 | #define FLIGHTSIM_RX_INTERVAL 1 408 | #define SEREMU_INTERFACE 1 // Serial emulation 409 | #define SEREMU_TX_ENDPOINT 1 410 | #define SEREMU_TX_SIZE 64 411 | #define SEREMU_TX_INTERVAL 1 412 | #define SEREMU_RX_ENDPOINT 2 413 | #define SEREMU_RX_SIZE 32 414 | #define SEREMU_RX_INTERVAL 2 415 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 416 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 417 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY 418 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 419 | 420 | #elif defined(USB_MTPDISK) 421 | #define VENDOR_ID 0x16C0 422 | #define PRODUCT_ID 0x0489 423 | #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} 424 | #define MANUFACTURER_NAME_LEN 11 425 | #define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','T','P',' ','D','i','s','k'} 426 | #define PRODUCT_NAME_LEN 15 427 | #define EP0_SIZE 64 428 | #define NUM_ENDPOINTS 4 429 | #define NUM_USB_BUFFERS 20 430 | #define NUM_INTERFACE 2 431 | #define MTP_INTERFACE 0 // MTP Disk 432 | #define MTP_TX_ENDPOINT 3 433 | #define MTP_TX_SIZE 64 434 | #define MTP_RX_ENDPOINT 3 435 | #define MTP_RX_SIZE 64 436 | #define MTP_EVENT_ENDPOINT 4 437 | #define MTP_EVENT_SIZE 16 438 | #define MTP_EVENT_INTERVAL 10 439 | #define SEREMU_INTERFACE 1 // Serial emulation 440 | #define SEREMU_TX_ENDPOINT 1 441 | #define SEREMU_TX_SIZE 64 442 | #define SEREMU_TX_INTERVAL 1 443 | #define SEREMU_RX_ENDPOINT 2 444 | #define SEREMU_RX_SIZE 32 445 | #define SEREMU_RX_INTERVAL 2 446 | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY 447 | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY 448 | #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE 449 | #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY 450 | 451 | #endif 452 | 453 | #ifdef USB_DESC_LIST_DEFINE 454 | #if defined(NUM_ENDPOINTS) && NUM_ENDPOINTS > 0 455 | // NUM_ENDPOINTS = number of non-zero endpoints (0 to 15) 456 | extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS]; 457 | 458 | typedef struct { 459 | uint16_t wValue; 460 | uint16_t wIndex; 461 | const uint8_t *addr; 462 | uint16_t length; 463 | } usb_descriptor_list_t; 464 | 465 | extern const usb_descriptor_list_t usb_descriptor_list[]; 466 | #endif // NUM_ENDPOINTS 467 | #endif // USB_DESC_LIST_DEFINE 468 | 469 | #endif 470 | -------------------------------------------------------------------------------- /usb_dev.c: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #include "usb_dev.h" 108 | #if F_CPU >= 20000000 && defined(NUM_ENDPOINTS) 109 | 110 | #include "kinetis.h" 111 | //#include "HardwareSerial.h" 112 | #include "usb_mem.h" 113 | 114 | // buffer descriptor table 115 | 116 | typedef struct { 117 | uint32_t desc; 118 | void * addr; 119 | } bdt_t; 120 | 121 | __attribute__ ((section(".usbdescriptortable"), used)) 122 | static bdt_t table[(NUM_ENDPOINTS+1)*4]; 123 | 124 | static usb_packet_t *rx_first[NUM_ENDPOINTS]; 125 | static usb_packet_t *rx_last[NUM_ENDPOINTS]; 126 | static usb_packet_t *tx_first[NUM_ENDPOINTS]; 127 | static usb_packet_t *tx_last[NUM_ENDPOINTS]; 128 | uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; 129 | 130 | static uint8_t tx_state[NUM_ENDPOINTS]; 131 | #define TX_STATE_BOTH_FREE_EVEN_FIRST 0 132 | #define TX_STATE_BOTH_FREE_ODD_FIRST 1 133 | #define TX_STATE_EVEN_FREE 2 134 | #define TX_STATE_ODD_FREE 3 135 | #define TX_STATE_NONE_FREE_EVEN_FIRST 4 136 | #define TX_STATE_NONE_FREE_ODD_FIRST 5 137 | 138 | #define BDT_OWN 0x80 139 | #define BDT_DATA1 0x40 140 | #define BDT_DATA0 0x00 141 | #define BDT_DTS 0x08 142 | #define BDT_STALL 0x04 143 | #define BDT_PID(n) (((n) >> 2) & 15) 144 | 145 | #define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \ 146 | | ((data) ? BDT_DATA1 : BDT_DATA0) \ 147 | | ((count) << 16)) 148 | 149 | #define TX 1 150 | #define RX 0 151 | #define ODD 1 152 | #define EVEN 0 153 | #define DATA0 0 154 | #define DATA1 1 155 | #define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) 156 | #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 157 | 158 | 159 | static union { 160 | struct { 161 | union { 162 | struct { 163 | uint8_t bmRequestType; 164 | uint8_t bRequest; 165 | }; 166 | uint16_t wRequestAndType; 167 | }; 168 | uint16_t wValue; 169 | uint16_t wIndex; 170 | uint16_t wLength; 171 | }; 172 | struct { 173 | uint32_t word1; 174 | uint32_t word2; 175 | }; 176 | } setup; 177 | 178 | 179 | #define GET_STATUS 0 180 | #define CLEAR_FEATURE 1 181 | #define SET_FEATURE 3 182 | #define SET_ADDRESS 5 183 | #define GET_DESCRIPTOR 6 184 | #define SET_DESCRIPTOR 7 185 | #define GET_CONFIGURATION 8 186 | #define SET_CONFIGURATION 9 187 | #define GET_INTERFACE 10 188 | #define SET_INTERFACE 11 189 | #define SYNCH_FRAME 12 190 | 191 | // SETUP always uses a DATA0 PID for the data field of the SETUP transaction. 192 | // transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1) 193 | // Status stage uses a DATA1 PID. 194 | 195 | static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4))); 196 | static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4))); 197 | static const uint8_t *ep0_tx_ptr = NULL; 198 | static uint16_t ep0_tx_len; 199 | static uint8_t ep0_tx_bdt_bank = 0; 200 | static uint8_t ep0_tx_data_toggle = 0; 201 | //Added from https://forum.pjrc.com/archive/index.php/t-24256.html 202 | static uint8_t *ep0_rx_ptr = NULL; 203 | static uint16_t ep0_rx_len; 204 | static uint8_t ep0_rx_bdt_bank = 0; 205 | static uint8_t ep0_rx_data_toggle = 0; 206 | // 207 | uint8_t usb_rx_memory_needed = 0; 208 | 209 | volatile uint8_t usb_configuration = 0; 210 | volatile uint8_t usb_reboot_timer = 0; 211 | 212 | 213 | static void endpoint0_stall(void) 214 | { 215 | USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 216 | } 217 | 218 | static uint8_t endpoint0_receive(uint8_t *data) { 219 | //9,26,46,f7,56 220 | 221 | uint8_t *inc=table[index(0,RX,ep0_rx_bdt_bank)].addr; 222 | uint32_t desc=table[index(0,RX,ep0_rx_bdt_bank)].desc; 223 | 224 | uint8_t size=(desc>>16); 225 | uint8_t origsize=size; 226 | 227 | while (size--) {*data++=*inc++;} 228 | 229 | table[index(0,RX,ep0_rx_bdt_bank)].desc=BDT_DESC(EP0_SIZE,ep0_rx_data_toggle); 230 | ep0_rx_data_toggle ^= 1; 231 | ep0_rx_bdt_bank ^= 1; 232 | return origsize; 233 | } 234 | 235 | 236 | 237 | static void endpoint0_transmit(const void *data, uint32_t len) 238 | { 239 | #if 0 240 | serial_print("tx0:"); 241 | serial_phex32((uint32_t)data); 242 | serial_print(","); 243 | serial_phex16(len); 244 | serial_print(ep0_tx_bdt_bank ? ", odd" : ", even"); 245 | serial_print(ep0_tx_data_toggle ? ", d1\n" : ", d0\n"); 246 | #endif 247 | table[index(0, TX, ep0_tx_bdt_bank)].addr = (void *)data; 248 | table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle); 249 | ep0_tx_data_toggle ^= 1; 250 | ep0_tx_bdt_bank ^= 1; 251 | } 252 | 253 | static uint8_t reply_buffer[8]; 254 | 255 | static void endpoint0_ack(void) 256 | { 257 | table[index(0,TX,ep0_tx_bdt_bank)].addr=0; 258 | table[index(0,TX,ep0_tx_bdt_bank)].desc=BDT_DESC(0,ep0_tx_data_toggle); 259 | ep0_tx_data_toggle ^= 1; 260 | ep0_tx_bdt_bank ^= 1; 261 | } 262 | 263 | 264 | void wipe_usb_buffer() { 265 | volatile uint8_t *reg; 266 | uint8_t epconf; 267 | const uint8_t *cfg; 268 | reg = &USB0_ENDPT1; 269 | cfg = usb_endpoint_config_table; 270 | int i; 271 | for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) { 272 | if (table[i].desc & BDT_OWN) { 273 | usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8)); 274 | } 275 | } 276 | // free all queued packets 277 | for (i=0; i < NUM_ENDPOINTS; i++) { 278 | usb_packet_t *p, *n; 279 | p = rx_first[i]; 280 | while (p) { 281 | n = p->next; 282 | usb_free(p); 283 | p = n; 284 | } 285 | rx_first[i] = NULL; 286 | rx_last[i] = NULL; 287 | p = tx_first[i]; 288 | while (p) { 289 | n = p->next; 290 | usb_free(p); 291 | p = n; 292 | } 293 | tx_first[i] = NULL; 294 | tx_last[i] = NULL; 295 | usb_rx_byte_count_data[i] = 0; 296 | switch (tx_state[i]) { 297 | case TX_STATE_EVEN_FREE: 298 | case TX_STATE_NONE_FREE_EVEN_FIRST: 299 | tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST; 300 | break; 301 | case TX_STATE_ODD_FREE: 302 | case TX_STATE_NONE_FREE_ODD_FIRST: 303 | tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST; 304 | break; 305 | default: 306 | break; 307 | } 308 | } 309 | usb_rx_memory_needed = 0; 310 | for (i=1; i <= NUM_ENDPOINTS; i++) { 311 | epconf = *cfg++; 312 | *reg = epconf; 313 | reg += 4; 314 | if (epconf & USB_ENDPT_EPRXEN) { 315 | usb_packet_t *p; 316 | p = usb_malloc(); 317 | if (p) { 318 | table[index(i, RX, EVEN)].addr = p->buf; 319 | table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); 320 | } else { 321 | table[index(i, RX, EVEN)].desc = 0; 322 | usb_rx_memory_needed++; 323 | } 324 | p = usb_malloc(); 325 | if (p) { 326 | table[index(i, RX, ODD)].addr = p->buf; 327 | table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); 328 | } else { 329 | table[index(i, RX, ODD)].desc = 0; 330 | usb_rx_memory_needed++; 331 | } 332 | } 333 | table[index(i, TX, EVEN)].desc = 0; 334 | table[index(i, TX, ODD)].desc = 0; 335 | } 336 | } 337 | 338 | static void usb_setup(void) 339 | { 340 | const uint8_t *data = NULL; 341 | uint32_t datalen = 0; 342 | const usb_descriptor_list_t *list; 343 | uint32_t size; 344 | volatile uint8_t *reg; 345 | uint8_t epconf; 346 | const uint8_t *cfg; 347 | int i; 348 | 349 | switch (setup.wRequestAndType) { 350 | case 0x0500: // SET_ADDRESS 351 | break; 352 | case 0x0900: // SET_CONFIGURATION 353 | //serial_print("configure\n"); 354 | usb_configuration = setup.wValue; 355 | reg = &USB0_ENDPT1; 356 | cfg = usb_endpoint_config_table; 357 | // clear all BDT entries, free any allocated memory... 358 | for (i=4; i < (NUM_ENDPOINTS+1)*4; i++) { 359 | if (table[i].desc & BDT_OWN) { 360 | usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8)); 361 | } 362 | } 363 | // free all queued packets 364 | for (i=0; i < NUM_ENDPOINTS; i++) { 365 | usb_packet_t *p, *n; 366 | p = rx_first[i]; 367 | while (p) { 368 | n = p->next; 369 | usb_free(p); 370 | p = n; 371 | } 372 | rx_first[i] = NULL; 373 | rx_last[i] = NULL; 374 | p = tx_first[i]; 375 | while (p) { 376 | n = p->next; 377 | usb_free(p); 378 | p = n; 379 | } 380 | tx_first[i] = NULL; 381 | tx_last[i] = NULL; 382 | usb_rx_byte_count_data[i] = 0; 383 | switch (tx_state[i]) { 384 | case TX_STATE_EVEN_FREE: 385 | case TX_STATE_NONE_FREE_EVEN_FIRST: 386 | tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST; 387 | break; 388 | case TX_STATE_ODD_FREE: 389 | case TX_STATE_NONE_FREE_ODD_FIRST: 390 | tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST; 391 | break; 392 | default: 393 | break; 394 | } 395 | } 396 | usb_rx_memory_needed = 0; 397 | for (i=1; i <= NUM_ENDPOINTS; i++) { 398 | epconf = *cfg++; 399 | *reg = epconf; 400 | reg += 4; 401 | if (epconf & USB_ENDPT_EPRXEN) { 402 | usb_packet_t *p; 403 | p = usb_malloc(); 404 | if (p) { 405 | table[index(i, RX, EVEN)].addr = p->buf; 406 | table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); 407 | } else { 408 | table[index(i, RX, EVEN)].desc = 0; 409 | usb_rx_memory_needed++; 410 | } 411 | p = usb_malloc(); 412 | if (p) { 413 | table[index(i, RX, ODD)].addr = p->buf; 414 | table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); 415 | } else { 416 | table[index(i, RX, ODD)].desc = 0; 417 | usb_rx_memory_needed++; 418 | } 419 | } 420 | table[index(i, TX, EVEN)].desc = 0; 421 | table[index(i, TX, ODD)].desc = 0; 422 | } 423 | break; 424 | case 0x0880: // GET_CONFIGURATION 425 | reply_buffer[0] = usb_configuration; 426 | datalen = 1; 427 | data = reply_buffer; 428 | break; 429 | case 0x0080: // GET_STATUS (device) 430 | reply_buffer[0] = 0; 431 | reply_buffer[1] = 0; 432 | datalen = 2; 433 | data = reply_buffer; 434 | break; 435 | case 0x0082: // GET_STATUS (endpoint) 436 | if (setup.wIndex > NUM_ENDPOINTS) { 437 | // TODO: do we need to handle IN vs OUT here? 438 | endpoint0_stall(); 439 | return; 440 | } 441 | reply_buffer[0] = 0; 442 | reply_buffer[1] = 0; 443 | if (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02) reply_buffer[0] = 1; 444 | data = reply_buffer; 445 | datalen = 2; 446 | break; 447 | case 0x0102: // CLEAR_FEATURE (endpoint) 448 | i = setup.wIndex & 0x7F; 449 | if (i > NUM_ENDPOINTS || setup.wValue != 0) { 450 | // TODO: do we need to handle IN vs OUT here? 451 | endpoint0_stall(); 452 | return; 453 | } 454 | (*(uint8_t *)(&USB0_ENDPT0 + i * 4)) &= ~0x02; 455 | // TODO: do we need to clear the data toggle here? 456 | break; 457 | case 0x0302: // SET_FEATURE (endpoint) 458 | i = setup.wIndex & 0x7F; 459 | if (i > NUM_ENDPOINTS || setup.wValue != 0) { 460 | // TODO: do we need to handle IN vs OUT here? 461 | endpoint0_stall(); 462 | return; 463 | } 464 | (*(uint8_t *)(&USB0_ENDPT0 + i * 4)) |= 0x02; 465 | // TODO: do we need to clear the data toggle here? 466 | break; 467 | case 0x0680: // GET_DESCRIPTOR 468 | case 0x0681: 469 | //serial_print("desc:"); 470 | //serial_phex16(setup.wValue); 471 | //serial_print("\n"); 472 | for (list = usb_descriptor_list; 1; list++) { 473 | if (list->addr == NULL) break; 474 | //if (setup.wValue == list->wValue && 475 | //(setup.wIndex == list->wIndex) || ((setup.wValue >> 8) == 3)) { 476 | if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) { 477 | data = list->addr; 478 | if ((setup.wValue >> 8) == 3) { 479 | // for string descriptors, use the descriptor's 480 | // length field, allowing runtime configured 481 | // length. 482 | datalen = *(list->addr); 483 | } else { 484 | datalen = list->length; 485 | } 486 | #if 0 487 | serial_print("Desc found, "); 488 | serial_phex32((uint32_t)data); 489 | serial_print(","); 490 | serial_phex16(datalen); 491 | serial_print(","); 492 | serial_phex(data[0]); 493 | serial_phex(data[1]); 494 | serial_phex(data[2]); 495 | serial_phex(data[3]); 496 | serial_phex(data[4]); 497 | serial_phex(data[5]); 498 | serial_print("\n"); 499 | #endif 500 | goto send; 501 | } 502 | } 503 | //serial_print("desc: not found\n"); 504 | endpoint0_stall(); 505 | return; 506 | #if defined(CDC_STATUS_INTERFACE) 507 | case 0x2221: // CDC_SET_CONTROL_LINE_STATE 508 | usb_cdc_line_rtsdtr_millis = systick_millis_count; 509 | usb_cdc_line_rtsdtr = setup.wValue; 510 | //serial_print("set control line state\n"); 511 | break; 512 | case 0x2321: // CDC_SEND_BREAK 513 | break; 514 | case 0x2021: // CDC_SET_LINE_CODING 515 | //serial_print("set coding, waiting...\n"); 516 | return; 517 | #endif 518 | 519 | #if defined(MTP_INTERFACE) 520 | case 0x2164: // Cancel Request (PTP spec, 5.2.1, page 8) 521 | // TODO: required by PTP spec 522 | endpoint0_stall(); 523 | return; 524 | case 0x2166: // Device Reset (PTP spec, 5.2.3, page 10) 525 | // TODO: required by PTP spec 526 | endpoint0_stall(); 527 | return; 528 | case 0x2167: // Get Device Statis (PTP spec, 5.2.4, page 10) 529 | // TODO: required by PTP spec 530 | endpoint0_stall(); 531 | return; 532 | #endif 533 | 534 | // TODO: this does not work... why? 535 | #if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE) 536 | case 0x0921: // HID SET_REPORT 537 | if (setup.wLength) { 538 | ep0_rx_ptr=setBuffer; 539 | ep0_rx_len=8; 540 | } 541 | break; 542 | case 0x0A21: // HID SET_IDLE 543 | break; 544 | case 0x0B21: // ? 545 | break; 546 | case 0x01a1: // HID GET_REPORT 547 | data = getBuffer; 548 | 549 | if (setBuffer[7] >= 0x80 && setBuffer[7] <= 0x89) { 550 | for(i=0; i<7; i++) { 551 | keyboard_buffer[i+((setBuffer[7]-0x80)*7)]=setBuffer[i]; 552 | } 553 | } 554 | // HMACSHA1 Message Types 555 | // Default Report = RD 00 00 02 02 03 03 03 05 00 556 | // Reset/Done/ACK - Operation complete 557 | if (setBuffer[7] == 0x8f || (setBuffer[7] < 0x89 && setBuffer[7] > 0x80)) { 558 | getBuffer[1] = 0x02; 559 | getBuffer[2] = 0x02; 560 | getBuffer[3] = 0x03; 561 | getBuffer[4] = sess_counter; //slot 1 and 2 configured 562 | getBuffer[5] = 0x03; 563 | getBuffer[6] = may_block; 564 | getBuffer[7] = 0x00; 565 | getBuffer[8] = 0x00; 566 | if (setBuffer[7] == 0x8f) { 567 | for(i=0; i<80; i++) { 568 | keyboard_buffer[i]=0; 569 | } 570 | } 571 | setBuffer[7] = 0; 572 | } 573 | // Get Serial Number - https://github.com/Yubico/yubikey-personalization/blob/7b1d7130617d652359a2226de3734f0b99edd550/ykcore/ykcore.c#L154 574 | else if (setBuffer[1] == 0x10 && setBuffer[2] == 0x6b && setBuffer[3] == 0x5b) { 575 | getBuffer[1] = 0x10; //10C8DF = Serial number 1099999 576 | getBuffer[2] = 0xbf; 577 | getBuffer[3] = 0x91; 578 | getBuffer[4] = 0xed; 579 | getBuffer[5] = 0x45; 580 | getBuffer[6] = 0x00; 581 | getBuffer[7] = 0xc0; 582 | setBuffer[7] = 0; 583 | } 584 | else if (getBuffer[7] >= 0xa1) { // Waiting for button press 585 | if (getBuffer[8] == 0x43 || getBuffer[8] == 0xA9) { 586 | getBuffer[8]++; 587 | data = keyboard_buffer; // Send second C0 588 | //Reset getBuffer 589 | getBuffer[1] = 0x02; 590 | getBuffer[2] = 0x02; 591 | getBuffer[3] = 0x03; 592 | getBuffer[4] = sess_counter; 593 | getBuffer[5] = 0x03; 594 | getBuffer[6] = may_block; 595 | getBuffer[7] = 0x00; 596 | getBuffer[8] = 0x00; 597 | setBuffer[7] = 0x8f; 598 | } 599 | else if (getBuffer[8]) { // Already sent first C0 600 | getBuffer[8]++; 601 | data = keyboard_buffer + ((getBuffer[8]&0x0F)*8); 602 | } 603 | else if (keyboard_buffer[79] == 0xC9) { 604 | getBuffer[8] = 0xA0; // 10 messages to send 605 | data = keyboard_buffer; // Send 1st message (C0) 606 | } 607 | else if (keyboard_buffer[31] == 0xC3) { 608 | getBuffer[8] = 0x40; // 4 messages to send 609 | data = keyboard_buffer; // Send 1st message (C0) 610 | } 611 | } 612 | else if (setBuffer[7] == 0x89 && (getBuffer[6] == 0x05 || getBuffer[6] == 0x07)) { //Received all packets 613 | getBuffer[7] = 0x89; 614 | setBuffer[8] = 1; // Process packets 615 | } 616 | datalen = 8; 617 | goto send; 618 | endpoint0_stall(); 619 | return; 620 | // case 0xC940: 621 | #endif 622 | default: 623 | endpoint0_stall(); 624 | return; 625 | } 626 | send: 627 | //serial_print("setup send "); 628 | //serial_phex32(data); 629 | //serial_print(","); 630 | //serial_phex16(datalen); 631 | //serial_print("\n"); 632 | 633 | if (datalen > setup.wLength) datalen = setup.wLength; 634 | size = datalen; 635 | if (size > EP0_SIZE) size = EP0_SIZE; 636 | endpoint0_transmit(data, size); 637 | data += size; 638 | datalen -= size; 639 | if (datalen == 0 && size < EP0_SIZE) return; 640 | 641 | size = datalen; 642 | if (size > EP0_SIZE) size = EP0_SIZE; 643 | endpoint0_transmit(data, size); 644 | data += size; 645 | datalen -= size; 646 | if (datalen == 0 && size < EP0_SIZE) return; 647 | 648 | ep0_tx_ptr = data; 649 | ep0_tx_len = datalen; 650 | } 651 | 652 | 653 | 654 | //A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint 655 | //experiences any configuration event (configuration events are explained in 656 | //Sections 9.1.1.5 and 9.4.5). 657 | 658 | //Configuring a device or changing an alternate setting causes all of the status 659 | //and configuration values associated with endpoints in the affected interfaces 660 | //to be set to their default values. This includes setting the data toggle of 661 | //any endpoint using data toggles to the value DATA0. 662 | 663 | //For endpoints using data toggle, regardless of whether an endpoint has the 664 | //Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the 665 | //data toggle being reinitialized to DATA0. 666 | 667 | 668 | 669 | // #define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 670 | 671 | static void usb_control(uint32_t stat) 672 | { 673 | bdt_t *b; 674 | uint32_t pid, size; 675 | uint8_t *buf; 676 | const uint8_t *data; 677 | 678 | b = stat2bufferdescriptor(stat); 679 | pid = BDT_PID(b->desc); 680 | //count = b->desc >> 16; 681 | buf = b->addr; 682 | //serial_print("pid:"); 683 | //serial_phex(pid); 684 | //serial_print(", count:"); 685 | //serial_phex(count); 686 | //serial_print("\n"); 687 | 688 | switch (pid) { 689 | case 0x0D: // Setup received from host 690 | //serial_print("PID=Setup\n"); 691 | //if (count != 8) ; // panic? 692 | // grab the 8 byte setup info 693 | setup.word1 = *(uint32_t *)(buf); 694 | setup.word2 = *(uint32_t *)(buf + 4); 695 | 696 | // give the buffer back 697 | if ((!(setup.bmRequestType & 0x80)) && (setup.wLength>0)) { 698 | ep0_rx_bdt_bank = (stat&0x04)?0:1; 699 | table[index(0, RX, ep0_rx_bdt_bank)].desc = BDT_DESC(EP0_SIZE,DATA1); 700 | table[index(0, RX, ep0_rx_bdt_bank^1)].desc = BDT_DESC(EP0_SIZE,DATA0); 701 | ep0_rx_data_toggle = 1; 702 | } else { 703 | b->desc = BDT_DESC(EP0_SIZE, DATA1); 704 | //table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 1); 705 | //table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 1); 706 | 707 | // clear any leftover pending IN transactions 708 | } 709 | ep0_rx_ptr = NULL; 710 | 711 | if (ep0_tx_data_toggle) { 712 | } 713 | //if (table[index(0, TX, EVEN)].desc & 0x80) { 714 | //serial_print("leftover tx even\n"); 715 | //} 716 | //if (table[index(0, TX, ODD)].desc & 0x80) { 717 | //serial_print("leftover tx odd\n"); 718 | //} 719 | table[index(0, TX, EVEN)].desc = 0; 720 | table[index(0, TX, ODD)].desc = 0; 721 | // first IN after Setup is always DATA1 722 | ep0_tx_data_toggle = 1; 723 | 724 | #if 0 725 | serial_print("bmRequestType:"); 726 | serial_phex(setup.bmRequestType); 727 | serial_print(", bRequest:"); 728 | serial_phex(setup.bRequest); 729 | serial_print(", wValue:"); 730 | serial_phex16(setup.wValue); 731 | serial_print(", wIndex:"); 732 | serial_phex16(setup.wIndex); 733 | serial_print(", len:"); 734 | serial_phex16(setup.wLength); 735 | serial_print("\n"); 736 | #endif 737 | // actually "do" the setup request 738 | usb_setup(); 739 | // unfreeze the USB, now that we're ready 740 | USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit 741 | break; 742 | case 0x01: // OUT transaction received from host 743 | if (ep0_rx_ptr) { //if there is a pending OUT transfer 744 | uint8_t size=endpoint0_receive(ep0_rx_ptr); //receives current packet 745 | ep0_rx_ptr+=size; //moves pointer ahead by received byte count 746 | ep0_rx_len-=size; //decreases remaining transaction size by received byte count 747 | if (!ep0_rx_len) { //if we've got the whole thing 748 | //do whatever you need to here 749 | } 750 | } else { 751 | b->desc = BDT_DESC(EP0_SIZE, DATA1); //if no pending transfer we just free the buffer, same as we used to 752 | } 753 | break; 754 | case 0x02: 755 | //serial_print("PID=OUT\n"); 756 | #ifdef CDC_STATUS_INTERFACE 757 | if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) { 758 | int i; 759 | uint8_t *dst = (uint8_t *)usb_cdc_line_coding; 760 | //serial_print("set line coding "); 761 | for (i=0; i<7; i++) { 762 | //serial_phex(*buf); 763 | *dst++ = *buf++; 764 | } 765 | //serial_phex32(usb_cdc_line_coding[0]); 766 | //serial_print("\n"); 767 | if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15; 768 | endpoint0_transmit(NULL, 0); 769 | } 770 | #endif 771 | #ifdef KEYBOARD_INTERFACE 772 | if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) { 773 | keyboard_leds = buf[0]; 774 | endpoint0_transmit(NULL, 0); 775 | } 776 | #endif 777 | #ifdef SEREMU_INTERFACE 778 | if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE) 779 | && buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) { 780 | usb_reboot_timer = 5; 781 | endpoint0_transmit(NULL, 0); 782 | } 783 | #endif 784 | // give the buffer back 785 | b->desc = BDT_DESC(EP0_SIZE, DATA1); 786 | break; 787 | 788 | case 0x09: // IN transaction completed to host 789 | //serial_print("PID=IN:"); 790 | //serial_phex(stat); 791 | //serial_print("\n"); 792 | 793 | // send remaining data, if any... 794 | data = ep0_tx_ptr; 795 | if (data) { 796 | size = ep0_tx_len; 797 | if (size > EP0_SIZE) size = EP0_SIZE; 798 | endpoint0_transmit(data, size); 799 | data += size; 800 | ep0_tx_len -= size; 801 | ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL; 802 | } 803 | 804 | if (setup.bRequest == 5 && setup.bmRequestType == 0) { 805 | setup.bRequest = 0; 806 | //serial_print("set address: "); 807 | //serial_phex16(setup.wValue); 808 | //serial_print("\n"); 809 | USB0_ADDR = setup.wValue; 810 | } 811 | 812 | break; 813 | //default: 814 | //serial_print("PID=unknown:"); 815 | //serial_phex(pid); 816 | //serial_print("\n"); 817 | } 818 | USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit 819 | } 820 | 821 | 822 | 823 | 824 | 825 | 826 | usb_packet_t *usb_rx(uint32_t endpoint) 827 | { 828 | usb_packet_t *ret; 829 | endpoint--; 830 | if (endpoint >= NUM_ENDPOINTS) return NULL; 831 | __disable_irq(); 832 | ret = rx_first[endpoint]; 833 | if (ret) { 834 | rx_first[endpoint] = ret->next; 835 | usb_rx_byte_count_data[endpoint] -= ret->len; 836 | } 837 | __enable_irq(); 838 | //serial_print("rx, epidx="); 839 | //serial_phex(endpoint); 840 | //serial_print(", packet="); 841 | //serial_phex32(ret); 842 | //serial_print("\n"); 843 | return ret; 844 | } 845 | 846 | static uint32_t usb_queue_byte_count(const usb_packet_t *p) 847 | { 848 | uint32_t count=0; 849 | 850 | __disable_irq(); 851 | for ( ; p; p = p->next) { 852 | count += p->len; 853 | } 854 | __enable_irq(); 855 | return count; 856 | } 857 | 858 | // TODO: make this an inline function... 859 | /* 860 | uint32_t usb_rx_byte_count(uint32_t endpoint) 861 | { 862 | endpoint--; 863 | if (endpoint >= NUM_ENDPOINTS) return 0; 864 | return usb_rx_byte_count_data[endpoint]; 865 | //return usb_queue_byte_count(rx_first[endpoint]); 866 | } 867 | */ 868 | 869 | uint32_t usb_tx_byte_count(uint32_t endpoint) 870 | { 871 | endpoint--; 872 | if (endpoint >= NUM_ENDPOINTS) return 0; 873 | return usb_queue_byte_count(tx_first[endpoint]); 874 | } 875 | 876 | uint32_t usb_tx_packet_count(uint32_t endpoint) 877 | { 878 | const usb_packet_t *p; 879 | uint32_t count=0; 880 | 881 | endpoint--; 882 | if (endpoint >= NUM_ENDPOINTS) return 0; 883 | __disable_irq(); 884 | for (p = tx_first[endpoint]; p; p = p->next) count++; 885 | __enable_irq(); 886 | return count; 887 | } 888 | 889 | 890 | // Called from usb_free, but only when usb_rx_memory_needed > 0, indicating 891 | // receive endpoints are starving for memory. The intention is to give 892 | // endpoints needing receive memory priority over the user's code, which is 893 | // likely calling usb_malloc to obtain memory for transmitting. When the 894 | // user is creating data very quickly, their consumption could starve reception 895 | // without this prioritization. The packet buffer (input) is assigned to the 896 | // first endpoint needing memory. 897 | // 898 | void usb_rx_memory(usb_packet_t *packet) 899 | { 900 | unsigned int i; 901 | const uint8_t *cfg; 902 | 903 | cfg = usb_endpoint_config_table; 904 | //serial_print("rx_mem:"); 905 | __disable_irq(); 906 | for (i=1; i <= NUM_ENDPOINTS; i++) { 907 | if (*cfg++ & USB_ENDPT_EPRXEN) { 908 | if (table[index(i, RX, EVEN)].desc == 0) { 909 | table[index(i, RX, EVEN)].addr = packet->buf; 910 | table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0); 911 | usb_rx_memory_needed--; 912 | __enable_irq(); 913 | //serial_phex(i); 914 | //serial_print(",even\n"); 915 | return; 916 | } 917 | if (table[index(i, RX, ODD)].desc == 0) { 918 | table[index(i, RX, ODD)].addr = packet->buf; 919 | table[index(i, RX, ODD)].desc = BDT_DESC(64, 1); 920 | usb_rx_memory_needed--; 921 | __enable_irq(); 922 | //serial_phex(i); 923 | //serial_print(",odd\n"); 924 | return; 925 | } 926 | } 927 | } 928 | __enable_irq(); 929 | // we should never reach this point. If we get here, it means 930 | // usb_rx_memory_needed was set greater than zero, but no memory 931 | // was actually needed. 932 | usb_rx_memory_needed = 0; 933 | usb_free(packet); 934 | return; 935 | } 936 | 937 | //#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd)) 938 | //#define stat2bufferdescriptor(stat) (table + ((stat) >> 2)) 939 | 940 | void usb_tx(uint32_t endpoint, usb_packet_t *packet) 941 | { 942 | bdt_t *b = &table[index(endpoint, TX, EVEN)]; 943 | uint8_t next; 944 | endpoint--; 945 | if (endpoint >= NUM_ENDPOINTS) return; 946 | __disable_irq(); 947 | //serial_print("txstate="); 948 | //serial_phex(tx_state[endpoint]); 949 | //serial_print("\n"); 950 | switch (tx_state[endpoint]) { 951 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 952 | next = TX_STATE_ODD_FREE; 953 | break; 954 | case TX_STATE_BOTH_FREE_ODD_FIRST: 955 | b++; 956 | next = TX_STATE_EVEN_FREE; 957 | break; 958 | case TX_STATE_EVEN_FREE: 959 | next = TX_STATE_NONE_FREE_ODD_FIRST; 960 | break; 961 | case TX_STATE_ODD_FREE: 962 | b++; 963 | next = TX_STATE_NONE_FREE_EVEN_FIRST; 964 | break; 965 | default: 966 | if (tx_first[endpoint] == NULL) { 967 | tx_first[endpoint] = packet; 968 | } else { 969 | tx_last[endpoint]->next = packet; 970 | } 971 | tx_last[endpoint] = packet; 972 | __enable_irq(); 973 | return; 974 | } 975 | tx_state[endpoint] = next; 976 | b->addr = packet->buf; 977 | b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); 978 | __enable_irq(); 979 | } 980 | 981 | 982 | 983 | 984 | 985 | 986 | void _reboot_Teensyduino_(void) 987 | { 988 | // TODO: initialize R0 with a code.... 989 | __asm__ volatile("bkpt"); 990 | } 991 | 992 | 993 | 994 | void usb_isr(void) 995 | { 996 | uint8_t status, stat, t; 997 | 998 | //serial_print("isr"); 999 | //status = USB0_ISTAT; 1000 | //serial_phex(status); 1001 | //serial_print("\n"); 1002 | restart: 1003 | status = USB0_ISTAT; 1004 | 1005 | if ((status & USB_ISTAT_SOFTOK /* 04 */ )) { 1006 | if (usb_configuration) { 1007 | t = usb_reboot_timer; 1008 | if (t) { 1009 | usb_reboot_timer = --t; 1010 | if (!t) _reboot_Teensyduino_(); 1011 | } 1012 | #ifdef CDC_DATA_INTERFACE 1013 | t = usb_cdc_transmit_flush_timer; 1014 | if (t) { 1015 | usb_cdc_transmit_flush_timer = --t; 1016 | if (t == 0) usb_serial_flush_callback(); 1017 | } 1018 | #endif 1019 | #ifdef SEREMU_INTERFACE 1020 | t = usb_seremu_transmit_flush_timer; 1021 | if (t) { 1022 | usb_seremu_transmit_flush_timer = --t; 1023 | if (t == 0) usb_seremu_flush_callback(); 1024 | } 1025 | #endif 1026 | #ifdef MIDI_INTERFACE 1027 | usb_midi_flush_output(); 1028 | #endif 1029 | #ifdef FLIGHTSIM_INTERFACE 1030 | usb_flightsim_flush_callback(); 1031 | #endif 1032 | } 1033 | USB0_ISTAT = USB_ISTAT_SOFTOK; 1034 | } 1035 | 1036 | if ((status & USB_ISTAT_TOKDNE /* 08 */ )) { 1037 | uint8_t endpoint; 1038 | stat = USB0_STAT; 1039 | //serial_print("token: ep="); 1040 | //serial_phex(stat >> 4); 1041 | //serial_print(stat & 0x08 ? ",tx" : ",rx"); 1042 | //serial_print(stat & 0x04 ? ",odd\n" : ",even\n"); 1043 | endpoint = stat >> 4; 1044 | if (endpoint == 0) { 1045 | usb_control(stat); 1046 | } else { 1047 | bdt_t *b = stat2bufferdescriptor(stat); 1048 | usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8); 1049 | #if 0 1050 | serial_print("ep:"); 1051 | serial_phex(endpoint); 1052 | serial_print(", pid:"); 1053 | serial_phex(BDT_PID(b->desc)); 1054 | serial_print(((uint32_t)b & 8) ? ", odd" : ", even"); 1055 | serial_print(", count:"); 1056 | serial_phex(b->desc >> 16); 1057 | serial_print("\n"); 1058 | #endif 1059 | endpoint--; // endpoint is index to zero-based arrays 1060 | 1061 | if (stat & 0x08) { // transmit 1062 | usb_free(packet); 1063 | packet = tx_first[endpoint]; 1064 | if (packet) { 1065 | //serial_print("tx packet\n"); 1066 | tx_first[endpoint] = packet->next; 1067 | b->addr = packet->buf; 1068 | switch (tx_state[endpoint]) { 1069 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 1070 | tx_state[endpoint] = TX_STATE_ODD_FREE; 1071 | break; 1072 | case TX_STATE_BOTH_FREE_ODD_FIRST: 1073 | tx_state[endpoint] = TX_STATE_EVEN_FREE; 1074 | break; 1075 | case TX_STATE_EVEN_FREE: 1076 | tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST; 1077 | break; 1078 | case TX_STATE_ODD_FREE: 1079 | tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST; 1080 | break; 1081 | default: 1082 | break; 1083 | } 1084 | b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); 1085 | } else { 1086 | //serial_print("tx no packet\n"); 1087 | switch (tx_state[endpoint]) { 1088 | case TX_STATE_BOTH_FREE_EVEN_FIRST: 1089 | case TX_STATE_BOTH_FREE_ODD_FIRST: 1090 | break; 1091 | case TX_STATE_EVEN_FREE: 1092 | tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST; 1093 | break; 1094 | case TX_STATE_ODD_FREE: 1095 | tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST; 1096 | break; 1097 | default: 1098 | tx_state[endpoint] = ((uint32_t)b & 8) ? 1099 | TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE; 1100 | break; 1101 | } 1102 | } 1103 | } else { // receive 1104 | packet->len = b->desc >> 16; 1105 | if (packet->len > 0) { 1106 | packet->index = 0; 1107 | packet->next = NULL; 1108 | if (rx_first[endpoint] == NULL) { 1109 | //serial_print("rx 1st, epidx="); 1110 | //serial_phex(endpoint); 1111 | //serial_print(", packet="); 1112 | //serial_phex32((uint32_t)packet); 1113 | //serial_print("\n"); 1114 | rx_first[endpoint] = packet; 1115 | } else { 1116 | //serial_print("rx Nth, epidx="); 1117 | //serial_phex(endpoint); 1118 | //serial_print(", packet="); 1119 | //serial_phex32((uint32_t)packet); 1120 | //serial_print("\n"); 1121 | rx_last[endpoint]->next = packet; 1122 | } 1123 | rx_last[endpoint] = packet; 1124 | usb_rx_byte_count_data[endpoint] += packet->len; 1125 | // TODO: implement a per-endpoint maximum # of allocated packets 1126 | // so a flood of incoming data on 1 endpoint doesn't starve 1127 | // the others if the user isn't reading it regularly 1128 | packet = usb_malloc(); 1129 | if (packet) { 1130 | b->addr = packet->buf; 1131 | b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); 1132 | } else { 1133 | //serial_print("starving "); 1134 | //serial_phex(endpoint + 1); 1135 | //serial_print(((uint32_t)b & 8) ? ",odd\n" : ",even\n"); 1136 | b->desc = 0; 1137 | usb_rx_memory_needed++; 1138 | } 1139 | } else { 1140 | b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); 1141 | } 1142 | } 1143 | 1144 | 1145 | 1146 | 1147 | } 1148 | USB0_ISTAT = USB_ISTAT_TOKDNE; 1149 | goto restart; 1150 | } 1151 | 1152 | 1153 | 1154 | if (status & USB_ISTAT_USBRST /* 01 */ ) { 1155 | //serial_print("reset\n"); 1156 | 1157 | // initialize BDT toggle bits 1158 | USB0_CTL = USB_CTL_ODDRST; 1159 | ep0_tx_bdt_bank = 0; 1160 | 1161 | // set up buffers to receive Setup and OUT packets 1162 | table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0); 1163 | table[index(0, RX, EVEN)].addr = ep0_rx0_buf; 1164 | table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0); 1165 | table[index(0, RX, ODD)].addr = ep0_rx1_buf; 1166 | table[index(0, TX, EVEN)].desc = 0; 1167 | table[index(0, TX, ODD)].desc = 0; 1168 | 1169 | // activate endpoint 0 1170 | USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 1171 | 1172 | // clear all ending interrupts 1173 | USB0_ERRSTAT = 0xFF; 1174 | USB0_ISTAT = 0xFF; 1175 | 1176 | // set the address to zero during enumeration 1177 | USB0_ADDR = 0; 1178 | 1179 | // enable other interrupts 1180 | USB0_ERREN = 0xFF; 1181 | USB0_INTEN = USB_INTEN_TOKDNEEN | 1182 | USB_INTEN_SOFTOKEN | 1183 | USB_INTEN_STALLEN | 1184 | USB_INTEN_ERROREN | 1185 | USB_INTEN_USBRSTEN | 1186 | USB_INTEN_SLEEPEN; 1187 | 1188 | // is this necessary? 1189 | USB0_CTL = USB_CTL_USBENSOFEN; 1190 | return; 1191 | } 1192 | 1193 | 1194 | if ((status & USB_ISTAT_STALL /* 80 */ )) { 1195 | //serial_print("stall:\n"); 1196 | USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; 1197 | USB0_ISTAT = USB_ISTAT_STALL; 1198 | } 1199 | if ((status & USB_ISTAT_ERROR /* 02 */ )) { 1200 | uint8_t err = USB0_ERRSTAT; 1201 | USB0_ERRSTAT = err; 1202 | //serial_print("err:"); 1203 | //serial_phex(err); 1204 | //serial_print("\n"); 1205 | USB0_ISTAT = USB_ISTAT_ERROR; 1206 | } 1207 | 1208 | if ((status & USB_ISTAT_SLEEP /* 10 */ )) { 1209 | //serial_print("sleep\n"); 1210 | USB0_ISTAT = USB_ISTAT_SLEEP; 1211 | } 1212 | 1213 | } 1214 | 1215 | 1216 | 1217 | void usb_init(void) 1218 | { 1219 | int i; 1220 | 1221 | //serial_begin(BAUD2DIV(115200)); 1222 | //serial_print("usb_init\n"); 1223 | 1224 | usb_init_serialnumber(); 1225 | 1226 | for (i=0; i <= NUM_ENDPOINTS*4; i++) { 1227 | table[i].desc = 0; 1228 | table[i].addr = 0; 1229 | } 1230 | 1231 | // this basically follows the flowchart in the Kinetis 1232 | // Quick Reference User Guide, Rev. 1, 03/2012, page 141 1233 | 1234 | // assume 48 MHz clock already running 1235 | // SIM - enable clock 1236 | SIM_SCGC4 |= SIM_SCGC4_USBOTG; 1237 | #ifdef HAS_KINETIS_MPU 1238 | MPU_RGDAAC0 |= 0x03000000; 1239 | #endif 1240 | 1241 | // reset USB module 1242 | //USB0_USBTRC0 = USB_USBTRC_USBRESET; 1243 | //while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end 1244 | 1245 | // set desc table base addr 1246 | USB0_BDTPAGE1 = ((uint32_t)table) >> 8; 1247 | USB0_BDTPAGE2 = ((uint32_t)table) >> 16; 1248 | USB0_BDTPAGE3 = ((uint32_t)table) >> 24; 1249 | 1250 | // clear all ISR flags 1251 | USB0_ISTAT = 0xFF; 1252 | USB0_ERRSTAT = 0xFF; 1253 | USB0_OTGISTAT = 0xFF; 1254 | 1255 | //USB0_USBTRC0 |= 0x40; // undocumented bit 1256 | 1257 | // enable USB 1258 | USB0_CTL = USB_CTL_USBENSOFEN; 1259 | USB0_USBCTRL = 0; 1260 | 1261 | // enable reset interrupt 1262 | USB0_INTEN = USB_INTEN_USBRSTEN; 1263 | 1264 | // enable interrupt in NVIC... 1265 | NVIC_SET_PRIORITY(IRQ_USBOTG, 112); 1266 | NVIC_ENABLE_IRQ(IRQ_USBOTG); 1267 | 1268 | // enable d+ pullup 1269 | USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; 1270 | } 1271 | 1272 | 1273 | #else // F_CPU < 20 MHz && defined(NUM_ENDPOINTS) 1274 | 1275 | void usb_init(void) 1276 | { 1277 | } 1278 | 1279 | #endif // F_CPU >= 20 MHz && defined(NUM_ENDPOINTS) 1280 | -------------------------------------------------------------------------------- /usb_dev.h: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #ifndef _usb_dev_h_ 108 | #define _usb_dev_h_ 109 | 110 | #define USB_DESC_LIST_DEFINE 111 | #include "usb_desc.h" 112 | 113 | #if F_CPU >= 20000000 && !defined(USB_DISABLED) 114 | 115 | // This header is NOT meant to be included when compiling 116 | // user sketches in Arduino. The low-level functions 117 | // provided by usb_dev.c are meant to be called only by 118 | // code which provides higher-level interfaces to the user. 119 | 120 | #include "usb_mem.h" 121 | 122 | #ifdef __cplusplus 123 | extern "C" { 124 | #endif 125 | 126 | extern uint8_t setBuffer[9]; 127 | extern uint8_t getBuffer[9]; 128 | extern uint8_t keyboard_buffer[80]; 129 | extern uint8_t sess_counter; 130 | extern uint8_t may_block; 131 | 132 | 133 | extern void wipe_usb_buffer(); 134 | void usb_init(void); 135 | void usb_init_serialnumber(void); 136 | void usb_isr(void); 137 | usb_packet_t *usb_rx(uint32_t endpoint); 138 | uint32_t usb_tx_byte_count(uint32_t endpoint); 139 | uint32_t usb_tx_packet_count(uint32_t endpoint); 140 | void usb_tx(uint32_t endpoint, usb_packet_t *packet); 141 | void usb_tx_isr(uint32_t endpoint, usb_packet_t *packet); 142 | 143 | extern volatile uint8_t usb_configuration; 144 | 145 | extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS]; 146 | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline)); 147 | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) 148 | { 149 | endpoint--; 150 | if (endpoint >= NUM_ENDPOINTS) return 0; 151 | return usb_rx_byte_count_data[endpoint]; 152 | } 153 | 154 | #ifdef CDC_DATA_INTERFACE 155 | extern uint32_t usb_cdc_line_coding[2]; 156 | extern volatile uint32_t usb_cdc_line_rtsdtr_millis; 157 | extern volatile uint32_t systick_millis_count; 158 | extern volatile uint8_t usb_cdc_line_rtsdtr; 159 | extern volatile uint8_t usb_cdc_transmit_flush_timer; 160 | extern void usb_serial_flush_callback(void); 161 | #endif 162 | 163 | #ifdef SEREMU_INTERFACE 164 | extern volatile uint8_t usb_seremu_transmit_flush_timer; 165 | extern void usb_seremu_flush_callback(void); 166 | #endif 167 | 168 | #ifdef KEYBOARD_INTERFACE 169 | extern uint8_t keyboard_modifier_keys; 170 | extern uint8_t keyboard_keys[6]; 171 | extern uint8_t keyboard_protocol; 172 | extern uint8_t keyboard_idle_config; 173 | extern uint8_t keyboard_idle_count; 174 | extern volatile uint8_t keyboard_leds; 175 | #endif 176 | 177 | #ifdef MIDI_INTERFACE 178 | extern void usb_midi_flush_output(void); 179 | #endif 180 | 181 | #ifdef FLIGHTSIM_INTERFACE 182 | extern void usb_flightsim_flush_callback(void); 183 | #endif 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | 189 | #else // F_CPU < 20000000 190 | 191 | #ifdef __cplusplus 192 | extern "C" { 193 | #endif 194 | 195 | void usb_init(void); 196 | 197 | #ifdef __cplusplus 198 | } 199 | #endif 200 | 201 | 202 | #endif // F_CPU 203 | 204 | #endif -------------------------------------------------------------------------------- /usb_keyboard.c: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #include "usb_dev.h" 108 | #include "usb_keyboard.h" 109 | #include "core_pins.h" // for yield() 110 | #include "keylayouts.h" 111 | //#include "HardwareSerial.h" 112 | #include // for memcpy() 113 | 114 | #ifdef KEYBOARD_INTERFACE // defined by usb_dev.h -> usb_desc.h 115 | #if F_CPU >= 20000000 116 | 117 | // which modifier keys are currently pressed 118 | // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui 119 | // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui 120 | uint8_t keyboard_modifier_keys=0; 121 | 122 | // which media keys are currently pressed 123 | uint8_t keyboard_media_keys=0; 124 | 125 | // which keys are currently pressed, up to 6 keys may be down at once 126 | uint8_t keyboard_keys[6]={0,0,0,0,0,0}; 127 | 128 | // protocol setting from the host. We use exactly the same report 129 | // either way, so this variable only stores the setting since we 130 | // are required to be able to report which setting is in use. 131 | uint8_t keyboard_protocol=1; 132 | 133 | // the idle configuration, how often we send the report to the 134 | // host (ms * 4) even when it hasn't changed 135 | uint8_t keyboard_idle_config=125; 136 | 137 | // count until idle timeout 138 | uint8_t keyboard_idle_count=0; 139 | 140 | // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana 141 | volatile uint8_t keyboard_leds=0; 142 | 143 | 144 | 145 | static KEYCODE_TYPE unicode_to_keycode(uint16_t cpoint); 146 | static void write_key(KEYCODE_TYPE keycode); 147 | static uint8_t keycode_to_modifier(KEYCODE_TYPE keycode); 148 | static uint8_t keycode_to_key(KEYCODE_TYPE keycode); 149 | static void usb_keyboard_press_key(uint8_t key, uint8_t modifier); 150 | static void usb_keyboard_release_key(uint8_t key, uint8_t modifier); 151 | static KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode); 152 | 153 | extern uint16_t SHIFT_MASK; 154 | extern uint16_t ALTGR_MASK; 155 | extern uint16_t RCTRL_MASK; 156 | extern uint16_t KEY_NON_US_100; 157 | extern uint16_t DEADKEYS_MASK; 158 | extern uint16_t CIRCUMFLEX_BITS; 159 | extern uint16_t ACUTE_ACCENT_BITS; 160 | extern uint16_t GRAVE_ACCENT_BITS; 161 | extern uint16_t TILDE_BITS; 162 | extern uint16_t DIAERESIS_BITS; 163 | extern uint16_t DEADKEY_CIRCUMFLEX; 164 | extern uint16_t DEADKEY_ACUTE_ACCENT; 165 | extern uint16_t DEADKEY_GRAVE_ACCENT; 166 | extern uint16_t DEADKEY_TILDE; 167 | extern uint16_t DEADKEY_DIAERESIS; 168 | extern uint16_t UNICODE_20AC; 169 | extern uint16_t CEDILLA_BITS; 170 | extern uint16_t DEADKEY_CEDILLA; 171 | extern uint16_t RING_ABOVE_BITS; 172 | extern uint16_t DEADKEY_RING_ABOVE; 173 | extern uint16_t DEGREE_SIGN_BITS; 174 | extern uint16_t CARON_BITS; 175 | extern uint16_t BREVE_BITS; 176 | extern uint16_t OGONEK_BITS; 177 | extern uint16_t DOT_ABOVE_BITS; 178 | extern uint16_t DOUBLE_ACUTE_BITS; 179 | extern uint16_t DEADKEY_DEGREE_SIGN; 180 | extern uint16_t DEADKEY_CARON; 181 | extern uint16_t DEADKEY_BREVE; 182 | extern uint16_t DEADKEY_OGONEK; 183 | extern uint16_t DEADKEY_DOT_ABOVE; 184 | extern uint16_t DEADKEY_DOUBLE_ACUTE; 185 | extern uint16_t UNICODE_EXTRA0A; 186 | extern uint16_t KEYCODE_EXTRA0A; 187 | extern uint16_t ISO_8859_1_A0; 188 | extern uint16_t UNICODE_EXTRA00; 189 | extern uint16_t UNICODE_EXTRA01; 190 | extern uint16_t UNICODE_EXTRA02; 191 | extern uint16_t UNICODE_EXTRA03; 192 | extern uint16_t UNICODE_EXTRA04; 193 | extern uint16_t UNICODE_EXTRA05; 194 | extern uint16_t UNICODE_EXTRA06; 195 | extern uint16_t UNICODE_EXTRA07; 196 | extern uint16_t UNICODE_EXTRA08; 197 | extern uint16_t UNICODE_EXTRA09; 198 | extern uint16_t KEYCODE_EXTRA00; 199 | extern uint16_t KEYCODE_EXTRA01; 200 | extern uint16_t KEYCODE_EXTRA02; 201 | extern uint16_t KEYCODE_EXTRA03; 202 | extern uint16_t KEYCODE_EXTRA04; 203 | extern uint16_t KEYCODE_EXTRA05; 204 | extern uint16_t KEYCODE_EXTRA06; 205 | extern uint16_t KEYCODE_EXTRA07; 206 | extern uint16_t KEYCODE_EXTRA08; 207 | extern uint16_t KEYCODE_EXTRA09; 208 | extern uint16_t KEYCODE_MASK; 209 | 210 | 211 | // Step #1, decode UTF8 to Unicode code points 212 | // 213 | void usb_keyboard_write(uint8_t c) 214 | { 215 | static int utf8_state=0; 216 | static uint16_t unicode_wchar=0; 217 | 218 | if (c < 0x80) { 219 | // single byte encoded, 0x00 to 0x7F 220 | utf8_state = 0; 221 | usb_keyboard_write_unicode(c); 222 | } else if (c < 0xC0) { 223 | // 2nd, 3rd or 4th byte, 0x80 to 0xBF 224 | c &= 0x3F; 225 | if (utf8_state == 1) { 226 | utf8_state = 0; 227 | usb_keyboard_write_unicode(unicode_wchar | c); 228 | } else if (utf8_state == 2) { 229 | unicode_wchar |= ((uint16_t)c << 6); 230 | utf8_state = 1; 231 | } 232 | } else if (c < 0xE0) { 233 | // begin 2 byte sequence, 0xC2 to 0xDF 234 | // or illegal 2 byte sequence, 0xC0 to 0xC1 235 | unicode_wchar = (uint16_t)(c & 0x1F) << 6; 236 | utf8_state = 1; 237 | } else if (c < 0xF0) { 238 | // begin 3 byte sequence, 0xE0 to 0xEF 239 | unicode_wchar = (uint16_t)(c & 0x0F) << 12; 240 | utf8_state = 2; 241 | } else { 242 | // begin 4 byte sequence (not supported), 0xF0 to 0xF4 243 | // or illegal, 0xF5 to 0xFF 244 | utf8_state = 255; 245 | } 246 | } 247 | 248 | 249 | // Step #2: translate Unicode code point to keystroke sequence 250 | // 251 | static KEYCODE_TYPE unicode_to_keycode(uint16_t cpoint) 252 | { 253 | // Unicode code points beyond U+FFFF are not supported 254 | // technically this input should probably be called UCS-2 255 | if (cpoint < 32) { 256 | if (cpoint == 10) return KEY_ENTER & KEYCODE_MASK; 257 | if (cpoint == 11) return KEY_TAB & KEYCODE_MASK; 258 | return 0; 259 | } 260 | if (cpoint < 128) { 261 | return keycodes_ascii[cpoint - 0x20]; 262 | } 263 | if (ISO_8859_1_A0) { 264 | if (cpoint >= 0xA0 && cpoint < 0x100) { 265 | return keycodes_iso_8859_1[cpoint - 0xA0]; 266 | } 267 | } 268 | //#ifdef UNICODE_20AC 269 | //if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF; 270 | //#endif 271 | if (KEYCODE_EXTRA00) if (cpoint == UNICODE_EXTRA00) return (KEYCODE_EXTRA00) & 0x3FFF; 272 | if (KEYCODE_EXTRA01) if (cpoint == UNICODE_EXTRA01) return (KEYCODE_EXTRA01) & 0x3FFF; 273 | if (KEYCODE_EXTRA02) if (cpoint == UNICODE_EXTRA02) return (KEYCODE_EXTRA02) & 0x3FFF; 274 | if (KEYCODE_EXTRA03) if (cpoint == UNICODE_EXTRA03) return (KEYCODE_EXTRA03) & 0x3FFF; 275 | if (KEYCODE_EXTRA04) if (cpoint == UNICODE_EXTRA04) return (KEYCODE_EXTRA04) & 0x3FFF; 276 | if (KEYCODE_EXTRA05) if (cpoint == UNICODE_EXTRA05) return (KEYCODE_EXTRA05) & 0x3FFF; 277 | if (KEYCODE_EXTRA06) if (cpoint == UNICODE_EXTRA06) return (KEYCODE_EXTRA06) & 0x3FFF; 278 | if (KEYCODE_EXTRA07) if (cpoint == UNICODE_EXTRA07) return (KEYCODE_EXTRA07) & 0x3FFF; 279 | if (KEYCODE_EXTRA08) if (cpoint == UNICODE_EXTRA08) return (KEYCODE_EXTRA08) & 0x3FFF; 280 | if (KEYCODE_EXTRA09) if (cpoint == UNICODE_EXTRA09) return (KEYCODE_EXTRA09) & 0x3FFF; 281 | if (KEYCODE_EXTRA0A) if (cpoint == UNICODE_EXTRA0A) return (KEYCODE_EXTRA0A) & 0x3FFF; 282 | return 0; 283 | } 284 | 285 | // Step #3: execute keystroke sequence 286 | // 287 | 288 | static KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode) 289 | { 290 | if(DEADKEYS_MASK) { 291 | keycode &= DEADKEYS_MASK; 292 | if (keycode == 0) return 0; 293 | if(ACUTE_ACCENT_BITS) if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT; 294 | if(CEDILLA_BITS) if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA; 295 | if(CIRCUMFLEX_BITS) if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX; 296 | if(DIAERESIS_BITS) if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS; 297 | if(GRAVE_ACCENT_BITS) if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT; 298 | if(TILDE_BITS) if (keycode == TILDE_BITS) return DEADKEY_TILDE; 299 | if(RING_ABOVE_BITS) if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE; 300 | if(DEGREE_SIGN_BITS) if (keycode == DEGREE_SIGN_BITS) return DEADKEY_DEGREE_SIGN; 301 | if(CARON_BITS) if (keycode == CARON_BITS) return DEADKEY_CARON; 302 | if(BREVE_BITS) if (keycode == BREVE_BITS) return DEADKEY_BREVE; 303 | if(OGONEK_BITS) if (keycode == OGONEK_BITS) return DEADKEY_OGONEK; 304 | if(DOT_ABOVE_BITS) if (keycode == DOT_ABOVE_BITS) return DEADKEY_DOT_ABOVE; 305 | if(DOUBLE_ACUTE_BITS) if (keycode == DOUBLE_ACUTE_BITS) return DEADKEY_DOUBLE_ACUTE; 306 | } 307 | return 0; 308 | } 309 | 310 | 311 | void usb_keyboard_write_unicode(uint16_t cpoint) 312 | { 313 | KEYCODE_TYPE keycode; 314 | 315 | keycode = unicode_to_keycode(cpoint); 316 | if (keycode) { 317 | if(DEADKEYS_MASK) { 318 | KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); 319 | if (deadkeycode) write_key(deadkeycode); 320 | } 321 | write_key(keycode); 322 | } 323 | } 324 | 325 | 326 | // Step #4: do each keystroke 327 | // 328 | static void write_key(KEYCODE_TYPE keycode) 329 | { 330 | /* 331 | uint8_t key, modifier=0; 332 | 333 | #ifdef SHIFT_MASK 334 | if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; 335 | #endif 336 | #ifdef ALTGR_MASK 337 | if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; 338 | #endif 339 | #ifdef RCTRL_MASK 340 | if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; 341 | #endif 342 | key = keycode & 0x3F; 343 | #ifdef KEY_NON_US_100 344 | if (key == KEY_NON_US_100) key = 100; 345 | #endif 346 | usb_keyboard_press(key, modifier); 347 | */ 348 | usb_keyboard_press(keycode_to_key(keycode), keycode_to_modifier(keycode)); 349 | } 350 | 351 | static uint8_t keycode_to_modifier(KEYCODE_TYPE keycode) 352 | { 353 | uint8_t modifier=0; 354 | 355 | if (SHIFT_MASK) if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; 356 | 357 | if (ALTGR_MASK) if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; 358 | 359 | if (RCTRL_MASK) if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; 360 | 361 | return modifier; 362 | } 363 | 364 | static uint8_t keycode_to_key(KEYCODE_TYPE keycode) 365 | { 366 | uint8_t key = keycode & 0x3F; 367 | if (KEY_NON_US_100) if (key == KEY_NON_US_100) key = 100; 368 | return key; 369 | } 370 | 371 | // Input can be: 372 | // 32 - 127 ASCII direct (U+0020 to U+007F) <-- uses layout 373 | // 128 - 0xC1FF Unicode direct (U+0080 to U+C1FF) <-- uses layout 374 | // 0xC200 - 0xDFFF Unicode UTF8 packed (U+0080 to U+07FF) <-- uses layout 375 | // 0xE000 - 0xE0FF Modifier key (bitmap, 8 keys, shift/ctrl/alt/gui) 376 | // 0xE200 - 0xE2FF System key (HID usage code, within usage page 1) 377 | // 0xE400 - 0xE7FF Media/Consumer key (HID usage code, within usage page 12) 378 | // 0xF000 - 0xFFFF Normal key (HID usage code, within usage page 7) 379 | 380 | void usb_keyboard_press_keycode(uint16_t n) 381 | { 382 | uint8_t key, mod, msb, modrestore=0; 383 | KEYCODE_TYPE keycode; 384 | KEYCODE_TYPE deadkeycode; 385 | 386 | msb = n >> 8; 387 | if (msb >= 0xC2) { 388 | if (msb <= 0xDF) { 389 | n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); 390 | } else if (msb == 0xF0) { 391 | usb_keyboard_press_key(n, 0); 392 | return; 393 | } else if (msb == 0xE0) { 394 | usb_keyboard_press_key(0, n); 395 | return; 396 | #ifdef KEYMEDIA_INTERFACE 397 | } else if (msb == 0xE2) { 398 | // TODO: system keys 399 | return; 400 | } else if (msb >= 0xE4 && msb <= 0xE7) { 401 | // TODO: media/consumer keys 402 | return; 403 | #endif 404 | } else { 405 | return; 406 | } 407 | } 408 | keycode = unicode_to_keycode(n); 409 | if (!keycode) return; 410 | if (DEADKEYS_MASK) { 411 | deadkeycode = deadkey_to_keycode(keycode); 412 | if (deadkeycode) { 413 | modrestore = keyboard_modifier_keys; 414 | if (modrestore) { 415 | keyboard_modifier_keys = 0; 416 | usb_keyboard_send(); 417 | } 418 | // TODO: test if operating systems recognize 419 | // deadkey sequences when other keys are held 420 | mod = keycode_to_modifier(deadkeycode); 421 | key = keycode_to_key(deadkeycode); 422 | usb_keyboard_press_key(key, mod); 423 | usb_keyboard_release_key(key, mod); 424 | } 425 | } 426 | mod = keycode_to_modifier(keycode); 427 | key = keycode_to_key(keycode); 428 | usb_keyboard_press_key(key, mod | modrestore); 429 | } 430 | 431 | 432 | void usb_keyboard_release_keycode(uint16_t n) 433 | { 434 | uint8_t key, mod, msb; 435 | 436 | msb = n >> 8; 437 | if (msb >= 0xC2) { 438 | if (msb <= 0xDF) { 439 | n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); 440 | } else if (msb == 0xF0) { 441 | usb_keyboard_release_key(n, 0); 442 | return; 443 | } else if (msb == 0xE0) { 444 | usb_keyboard_release_key(0, n); 445 | return; 446 | #ifdef KEYMEDIA_INTERFACE 447 | } else if (msb == 0xE2) { 448 | // TODO: system keys 449 | return; 450 | } else if (msb >= 0xE4 && msb <= 0xE7) { 451 | // TODO: media/consumer keys 452 | return; 453 | #endif 454 | } else { 455 | return; 456 | } 457 | } 458 | KEYCODE_TYPE keycode = unicode_to_keycode(n); 459 | if (!keycode) return; 460 | mod = keycode_to_modifier(keycode); 461 | key = keycode_to_key(keycode); 462 | usb_keyboard_release_key(key, mod); 463 | } 464 | 465 | 466 | static void usb_keyboard_press_key(uint8_t key, uint8_t modifier) 467 | { 468 | int i, send_required = 0; 469 | 470 | if (modifier) { 471 | if ((keyboard_modifier_keys & modifier) != modifier) { 472 | keyboard_modifier_keys |= modifier; 473 | send_required = 1; 474 | usb_keyboard_send(); 475 | // SEND MODKEY MULTIPLE TIMES, FIXES RDP ISSUE 476 | usb_keyboard_send(); 477 | usb_keyboard_send(); 478 | usb_keyboard_send(); 479 | usb_keyboard_send(); 480 | } 481 | } 482 | if (key) { 483 | for (i=0; i < 6; i++) { 484 | if (keyboard_keys[i] == key) goto end; 485 | } 486 | for (i=0; i < 6; i++) { 487 | if (keyboard_keys[i] == 0) { 488 | keyboard_keys[i] = key; 489 | send_required = 1; 490 | goto end; 491 | } 492 | } 493 | } 494 | end: 495 | if (send_required) usb_keyboard_send(); 496 | } 497 | 498 | 499 | static void usb_keyboard_release_key(uint8_t key, uint8_t modifier) 500 | { 501 | int i, send_required = 0; 502 | 503 | if (modifier) { 504 | if ((keyboard_modifier_keys & modifier) != 0) { 505 | keyboard_modifier_keys &= ~modifier; 506 | send_required = 1; 507 | usb_keyboard_send(); 508 | // SEND MODKEY MULTIPLE TIMES 509 | usb_keyboard_send(); 510 | usb_keyboard_send(); 511 | usb_keyboard_send(); 512 | usb_keyboard_send(); 513 | } 514 | } 515 | if (key) { 516 | for (i=0; i < 6; i++) { 517 | if (keyboard_keys[i] == key) { 518 | keyboard_keys[i] = 0; 519 | send_required = 1; 520 | } 521 | } 522 | } 523 | if (send_required) usb_keyboard_send(); 524 | } 525 | 526 | void usb_keyboard_release_all(void) 527 | { 528 | uint8_t i, anybits; 529 | 530 | anybits = keyboard_modifier_keys; 531 | keyboard_modifier_keys = 0; 532 | anybits |= keyboard_media_keys; 533 | keyboard_media_keys = 0; 534 | for (i=0; i < 6; i++) { 535 | anybits |= keyboard_keys[i]; 536 | keyboard_keys[i] = 0; 537 | } 538 | if (anybits) usb_keyboard_send(); 539 | } 540 | 541 | 542 | int usb_keyboard_press(uint8_t key, uint8_t modifier) 543 | { 544 | int r; 545 | keyboard_modifier_keys = modifier; 546 | keyboard_keys[0] = key; 547 | keyboard_keys[1] = 0; 548 | keyboard_keys[2] = 0; 549 | keyboard_keys[3] = 0; 550 | keyboard_keys[4] = 0; 551 | keyboard_keys[5] = 0; 552 | r = usb_keyboard_send(); 553 | if (r) return r; 554 | keyboard_modifier_keys = 0; 555 | keyboard_keys[0] = 0; 556 | return usb_keyboard_send(); 557 | } 558 | 559 | 560 | // Maximum number of transmit packets to queue so we don't starve other endpoints for memory 561 | #define TX_PACKET_LIMIT 4 562 | 563 | static uint8_t transmit_previous_timeout=0; 564 | 565 | // When the PC isn't listening, how long do we wait before discarding data? 566 | #define TX_TIMEOUT_MSEC 50 567 | 568 | #if F_CPU == 168000000 569 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100) 570 | #elif F_CPU == 144000000 571 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932) 572 | #elif F_CPU == 120000000 573 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764) 574 | #elif F_CPU == 96000000 575 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) 576 | #elif F_CPU == 72000000 577 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512) 578 | #elif F_CPU == 48000000 579 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) 580 | #elif F_CPU == 24000000 581 | #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) 582 | #endif 583 | 584 | 585 | // send the contents of keyboard_keys and keyboard_modifier_keys 586 | int usb_keyboard_send(void) 587 | { 588 | #if 0 589 | serial_print("Send:"); 590 | serial_phex(keyboard_modifier_keys); 591 | serial_phex(keyboard_keys[0]); 592 | serial_phex(keyboard_keys[1]); 593 | serial_phex(keyboard_keys[2]); 594 | serial_phex(keyboard_keys[3]); 595 | serial_phex(keyboard_keys[4]); 596 | serial_phex(keyboard_keys[5]); 597 | serial_print("\n"); 598 | #endif 599 | #if 1 600 | uint32_t wait_count=0; 601 | usb_packet_t *tx_packet; 602 | 603 | while (1) { 604 | if (!usb_configuration) { 605 | return -1; 606 | } 607 | if (usb_tx_packet_count(KEYBOARD_ENDPOINT) < TX_PACKET_LIMIT) { 608 | tx_packet = usb_malloc(); 609 | if (tx_packet) break; 610 | } 611 | if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { 612 | transmit_previous_timeout = 1; 613 | return -1; 614 | } 615 | yield(); 616 | } 617 | *(tx_packet->buf) = keyboard_modifier_keys; 618 | *(tx_packet->buf + 1) = keyboard_media_keys; 619 | memcpy(tx_packet->buf + 2, keyboard_keys, 6); 620 | tx_packet->len = 8; 621 | usb_tx(KEYBOARD_ENDPOINT, tx_packet); 622 | #endif 623 | return 0; 624 | } 625 | 626 | 627 | #endif // F_CPU 628 | #endif // KEYBOARD_INTERFACE 629 | -------------------------------------------------------------------------------- /usb_rawhid.c: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | #include "usb_dev.h" 108 | #include "usb_rawhid.h" 109 | #include "core_pins.h" // for yield(), millis() 110 | #include // for memcpy() 111 | //#include "HardwareSerial.h" 112 | 113 | #ifdef RAWHID_INTERFACE // defined by usb_dev.h -> usb_desc.h 114 | #if F_CPU >= 20000000 115 | 116 | 117 | int usb_rawhid_recv(void *buffer, uint32_t timeout) 118 | { 119 | usb_packet_t *rx_packet; 120 | uint32_t begin = millis(); 121 | uint8_t useinterface = 0; 122 | 123 | while (1) { 124 | if (!usb_configuration) return -1; 125 | rx_packet = usb_rx(RAWHID_RX_ENDPOINT); 126 | if (rx_packet) { 127 | useinterface=1; 128 | break; 129 | } 130 | rx_packet = usb_rx(RAWHID_RX_ENDPOINT2); 131 | if (rx_packet) { 132 | useinterface=2; 133 | break; 134 | } 135 | if (millis() - begin > timeout || !timeout) return 0; 136 | yield(); 137 | } 138 | memcpy(buffer, rx_packet->buf, RAWHID_RX_SIZE); 139 | usb_free(rx_packet); 140 | return useinterface; 141 | } 142 | 143 | int usb_rawhid_available(void) 144 | { 145 | uint32_t count; 146 | 147 | if (!usb_configuration) return 0; 148 | count = usb_rx_byte_count(RAWHID_RX_ENDPOINT); 149 | return count; 150 | } 151 | 152 | // Maximum number of transmit packets to queue so we don't starve other endpoints for memory 153 | #define TX_PACKET_LIMIT 4 154 | 155 | int usb_rawhid_send(const void *buffer, uint32_t timeout) 156 | { 157 | usb_packet_t *tx_packet; 158 | uint32_t begin = millis(); 159 | 160 | while (1) { 161 | if (!usb_configuration) return -1; 162 | if (usb_tx_packet_count(RAWHID_TX_ENDPOINT) < TX_PACKET_LIMIT) { 163 | tx_packet = usb_malloc(); 164 | if (tx_packet) break; 165 | } 166 | if (millis() - begin > timeout) return 0; 167 | yield(); 168 | } 169 | memcpy(tx_packet->buf, buffer, RAWHID_TX_SIZE); 170 | tx_packet->len = RAWHID_TX_SIZE; 171 | usb_tx(RAWHID_TX_ENDPOINT, tx_packet); 172 | return RAWHID_TX_SIZE; 173 | } 174 | 175 | int usb_rawhid_send2(const void *buffer, uint32_t timeout) 176 | { 177 | usb_packet_t *tx_packet; 178 | uint32_t begin = millis(); 179 | 180 | while (1) { 181 | if (!usb_configuration) return -1; 182 | if (usb_tx_packet_count(RAWHID_TX_ENDPOINT2) < TX_PACKET_LIMIT) { 183 | tx_packet = usb_malloc(); 184 | if (tx_packet) break; 185 | } 186 | if (millis() - begin > timeout) return 0; 187 | yield(); 188 | } 189 | memcpy(tx_packet->buf, buffer, RAWHID_TX_SIZE); 190 | tx_packet->len = RAWHID_TX_SIZE; 191 | usb_tx(RAWHID_TX_ENDPOINT2, tx_packet); 192 | return RAWHID_TX_SIZE; 193 | } 194 | 195 | #endif // F_CPU 196 | #endif // RAWHID_INTERFACE 197 | -------------------------------------------------------------------------------- /usb_rawhid.h: -------------------------------------------------------------------------------- 1 | /* Modifications 2 | * Copyright (c) 2015-2020, CryptoTrust LLC. 3 | * All rights reserved. 4 | * 5 | * Author : Tim Steiner 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * 3. All advertising materials mentioning features or use of this 20 | * software must display the following acknowledgment: 21 | * "This product includes software developed by CryptoTrust LLC. for 22 | * the OnlyKey Project (https://www.crp.to/ok)" 23 | * 24 | * 4. The names "OnlyKey" and "CryptoTrust" must not be used to 25 | * endorse or promote products derived from this software without 26 | * prior written permission. For written permission, please contact 27 | * admin@crp.to. 28 | * 29 | * 5. Products derived from this software may not be called "OnlyKey" 30 | * nor may "OnlyKey" or "CryptoTrust" appear in their names without 31 | * specific prior written permission. For written permission, please 32 | * contact admin@crp.to. 33 | * 34 | * 6. Redistributions of any form whatsoever must retain the following 35 | * acknowledgment: 36 | * "This product includes software developed by CryptoTrust LLC. for 37 | * the OnlyKey Project (https://www.crp.to/ok)" 38 | * 39 | * 7. Redistributions in any form must be accompanied by information on 40 | * how to obtain complete source code for this software and any 41 | * accompanying software that uses this software. The source code 42 | * must either be included in the distribution or be available for 43 | * no more than the cost of distribution plus a nominal fee, and must 44 | * be freely redistributable under reasonable conditions. For a 45 | * binary file, complete source code means the source code for all 46 | * modules it contains. 47 | * 48 | * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS 49 | * ARE GRANTED BY THIS LICENSE. IF SOFTWARE RECIPIENT INSTITUTES PATENT 50 | * LITIGATION AGAINST ANY ENTITY (INCLUDING A CROSS-CLAIM OR COUNTERCLAIM 51 | * IN A LAWSUIT) ALLEGING THAT THIS SOFTWARE (INCLUDING COMBINATIONS OF THE 52 | * SOFTWARE WITH OTHER SOFTWARE OR HARDWARE) INFRINGES SUCH SOFTWARE 53 | * RECIPIENT'S PATENT(S), THEN SUCH SOFTWARE RECIPIENT'S RIGHTS GRANTED BY 54 | * THIS LICENSE SHALL TERMINATE AS OF THE DATE SUCH LITIGATION IS FILED. IF 55 | * ANY PROVISION OF THIS AGREEMENT IS INVALID OR UNENFORCEABLE UNDER 56 | * APPLICABLE LAW, IT SHALL NOT AFFECT THE VALIDITY OR ENFORCEABILITY OF THE 57 | * REMAINDER OF THE TERMS OF THIS AGREEMENT, AND WITHOUT FURTHER ACTION 58 | * BY THE PARTIES HERETO, SUCH PROVISION SHALL BE REFORMED TO THE MINIMUM 59 | * EXTENT NECESSARY TO MAKE SUCH PROVISION VALID AND ENFORCEABLE. ALL 60 | * SOFTWARE RECIPIENT'S RIGHTS UNDER THIS AGREEMENT SHALL TERMINATE IF IT 61 | * FAILS TO COMPLY WITH ANY OF THE MATERIAL TERMS OR CONDITIONS OF THIS 62 | * AGREEMENT AND DOES NOT CURE SUCH FAILURE IN A REASONABLE PERIOD OF 63 | * TIME AFTER BECOMING AWARE OF SUCH NONCOMPLIANCE. THIS SOFTWARE IS 64 | * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 68 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 69 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 70 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 71 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 72 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 73 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 74 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 | */ 76 | 77 | /* Original Teensyduino Core Library 78 | * http://www.pjrc.com/teensy/ 79 | * Copyright (c) 2013 PJRC.COM, LLC. 80 | * 81 | * Permission is hereby granted, free of charge, to any person obtaining 82 | * a copy of this software and associated documentation files (the 83 | * "Software"), to deal in the Software without restriction, including 84 | * without limitation the rights to use, copy, modify, merge, publish, 85 | * distribute, sublicense, and/or sell copies of the Software, and to 86 | * permit persons to whom the Software is furnished to do so, subject to 87 | * the following conditions: 88 | * 89 | * 1. The above copyright notice and this permission notice shall be 90 | * included in all copies or substantial portions of the Software. 91 | * 92 | * 2. If the Software is incorporated into a build system that allows 93 | * selection among a list of target devices, then similar target 94 | * devices manufactured by PJRC.COM must be included in the list of 95 | * target devices and selectable in the same manner. 96 | * 97 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 98 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 99 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 100 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 101 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 102 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 103 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 104 | * SOFTWARE. 105 | */ 106 | 107 | 108 | #ifndef USBrawhid_h_ 109 | #define USBrawhid_h_ 110 | 111 | #include "usb_desc.h" 112 | 113 | #if defined(RAWHID_INTERFACE) 114 | 115 | #include 116 | 117 | // C language implementation 118 | #ifdef __cplusplus 119 | extern "C" { 120 | #endif 121 | int usb_rawhid_recv(void *buffer, uint32_t timeout); 122 | int usb_rawhid_available(void); 123 | int usb_rawhid_send(const void *buffer, uint32_t timeout); 124 | int usb_rawhid_send2(const void *buffer, uint32_t timeout); 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | 130 | // C++ interface 131 | #ifdef __cplusplus 132 | class usb_rawhid_class 133 | { 134 | public: 135 | int available(void) {return usb_rawhid_available(); } 136 | int recv(void *buffer, uint16_t timeout) { return usb_rawhid_recv(buffer, timeout); } 137 | int send(const void *buffer, uint16_t timeout) { return usb_rawhid_send(buffer, timeout); } 138 | int send2(const void *buffer, uint16_t timeout) { return usb_rawhid_send2(buffer, timeout); } 139 | }; 140 | 141 | extern usb_rawhid_class RawHID; 142 | 143 | #endif // __cplusplus 144 | 145 | #endif // RAWHID_INTERFACE 146 | 147 | #endif // USBrawhid_h_ --------------------------------------------------------------------------------