Created
July 30, 2019 23:52
-
-
Save bryanjhv/2a9a5936fe82b2bdd4090b86ce52cbb6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Based on Obdev's AVRUSB code and under the same license. | |
* | |
* TODO: Make a proper file header. :-) | |
* Modified for Digispark by Digistump | |
*/ | |
#ifndef __DigiKeyboard_h__ | |
#define __DigiKeyboard_h__ | |
#include <Arduino.h> | |
#include <avr/pgmspace.h> | |
#include <avr/interrupt.h> | |
#include <avr/delay.h> | |
#include <string.h> | |
#include "usbdrv.h" | |
// TODO: Work around Arduino 12 issues better. | |
//#include <WConstants.h> | |
//#undef int() | |
typedef uint8_t byte; | |
#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke | |
static uchar idleRate; // in 4 ms units | |
/* We use a simplifed keyboard report descriptor which does not support the | |
* boot protocol. We don't allow setting status LEDs and but we do allow | |
* simultaneous key presses. | |
* The report descriptor has been created with usb.org's "HID Descriptor Tool" | |
* which can be downloaded from http://www.usb.org/developers/hidpage/. | |
* Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted | |
* for the second INPUT item. | |
*/ | |
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */ | |
0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
0x09, 0x06, // USAGE (Keyboard) | |
0xa1, 0x01, // COLLECTION (Application) | |
0x05, 0x07, // USAGE_PAGE (Keyboard) | |
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) | |
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) | |
0x15, 0x00, // LOGICAL_MINIMUM (0) | |
0x25, 0x01, // LOGICAL_MAXIMUM (1) | |
0x75, 0x01, // REPORT_SIZE (1) | |
0x95, 0x08, // REPORT_COUNT (8) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes) | |
0x75, 0x08, // REPORT_SIZE (8) | |
0x25, 0x65, // LOGICAL_MAXIMUM (101) | |
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) | |
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) | |
0x81, 0x00, // INPUT (Data,Ary,Abs) | |
0xc0 // END_COLLECTION | |
}; | |
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter | |
* 10 Keyboard/Keypad Page for more codes. | |
*/ | |
#define MOD_CONTROL_LEFT (1<<0) | |
#define MOD_SHIFT_LEFT (1<<1) | |
#define MOD_ALT_LEFT (1<<2) | |
#define MOD_GUI_LEFT (1<<3) | |
#define MOD_CONTROL_RIGHT (1<<4) | |
#define MOD_SHIFT_RIGHT (1<<5) | |
#define MOD_ALT_RIGHT (1<<6) | |
#define MOD_GUI_RIGHT (1<<7) | |
#define KEY_A 4 | |
#define KEY_B 5 | |
#define KEY_C 6 | |
#define KEY_D 7 | |
#define KEY_E 8 | |
#define KEY_F 9 | |
#define KEY_G 10 | |
#define KEY_H 11 | |
#define KEY_I 12 | |
#define KEY_J 13 | |
#define KEY_K 14 | |
#define KEY_L 15 | |
#define KEY_M 16 | |
#define KEY_N 17 | |
#define KEY_O 18 | |
#define KEY_P 19 | |
#define KEY_Q 20 | |
#define KEY_R 21 | |
#define KEY_S 22 | |
#define KEY_T 23 | |
#define KEY_U 24 | |
#define KEY_V 25 | |
#define KEY_W 26 | |
#define KEY_X 27 | |
#define KEY_Y 28 | |
#define KEY_Z 29 | |
#define KEY_1 30 | |
#define KEY_2 31 | |
#define KEY_3 32 | |
#define KEY_4 33 | |
#define KEY_5 34 | |
#define KEY_6 35 | |
#define KEY_7 36 | |
#define KEY_8 37 | |
#define KEY_9 38 | |
#define KEY_0 39 | |
#define KEY_ENTER 40 | |
#define KEY_SPACE 44 | |
#define KEY_F1 58 | |
#define KEY_F2 59 | |
#define KEY_F3 60 | |
#define KEY_F4 61 | |
#define KEY_F5 62 | |
#define KEY_F6 63 | |
#define KEY_F7 64 | |
#define KEY_F8 65 | |
#define KEY_F9 66 | |
#define KEY_F10 67 | |
#define KEY_F11 68 | |
#define KEY_F12 69 | |
#define KEY_ARROW_LEFT 0x50 | |
#include "scancode-ascii-table2.h" | |
class DigiKeyboardDevice : public Print { | |
public: | |
DigiKeyboardDevice () { | |
cli(); | |
usbDeviceDisconnect(); | |
_delay_ms(250); | |
usbDeviceConnect(); | |
usbInit(); | |
sei(); | |
// TODO: Remove the next two lines once we fix | |
// missing first keystroke bug properly. | |
memset(reportBuffer, 0, sizeof(reportBuffer)); | |
usbSetInterrupt(reportBuffer, sizeof(reportBuffer)); | |
} | |
void update() { | |
usbPoll(); | |
} | |
// delay while updating until we are finished delaying | |
void delay(long milli) { | |
unsigned long last = millis(); | |
while (milli > 0) { | |
unsigned long now = millis(); | |
milli -= now - last; | |
last = now; | |
update(); | |
} | |
} | |
//sendKeyStroke: sends a key press AND release | |
void sendKeyStroke(byte keyStroke) { | |
sendKeyStroke(keyStroke, 0); | |
} | |
//sendKeyStroke: sends a key press AND release with modifiers | |
void sendKeyStroke(byte keyStroke, byte modifiers) { | |
sendKeyPress(keyStroke, modifiers); | |
// This stops endlessly repeating keystrokes: | |
sendKeyPress(0,0); | |
} | |
//sendKeyPress: sends a key press only - no release | |
//to release the key, send again with keyPress=0 | |
void sendKeyPress(byte keyPress) { | |
sendKeyPress(keyPress, 0); | |
} | |
//sendKeyPress: sends a key press only, with modifiers - no release | |
//to release the key, send again with keyPress=0 | |
void sendKeyPress(byte keyPress, byte modifiers) { | |
while (!usbInterruptIsReady()) { | |
// Note: We wait until we can send keyPress | |
// so we know the previous keyPress was | |
// sent. | |
usbPoll(); | |
_delay_ms(5); | |
} | |
memset(reportBuffer, 0, sizeof(reportBuffer)); | |
reportBuffer[0] = modifiers; | |
reportBuffer[1] = keyPress; | |
usbSetInterrupt(reportBuffer, sizeof(reportBuffer)); | |
} | |
size_t write(uint8_t chr) { | |
if (chr == '<') { | |
sendKeyStroke(0x64); | |
} else if (chr == '>') { | |
sendKeyStroke(0x64, MOD_SHIFT_RIGHT); | |
} else { | |
uint8_t data = pgm_read_byte_near(ascii_to_scan_code_table + (chr - 8)); | |
sendKeyStroke(data & 0b00111111, data >> 7 ? MOD_SHIFT_RIGHT : 0 | (data << 1) >> 7 ? MOD_ALT_RIGHT : 0); | |
if (chr == '^' || chr == '`') { | |
sendKeyStroke(0x2c); | |
} | |
} | |
return 1; | |
} | |
//private: TODO: Make friend? | |
uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes] | |
using Print::write; | |
}; | |
DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice(); | |
#ifdef __cplusplus | |
extern "C"{ | |
#endif | |
// USB_PUBLIC uchar usbFunctionSetup | |
uchar usbFunctionSetup(uchar data[8]) { | |
usbRequest_t *rq = (usbRequest_t *)((void *)data); | |
usbMsgPtr = DigiKeyboard.reportBuffer; // | |
if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { | |
/* class request type */ | |
if (rq->bRequest == USBRQ_HID_GET_REPORT) { | |
/* wValue: ReportType (highbyte), ReportID (lowbyte) */ | |
/* we only have one report type, so don't look at wValue */ | |
// TODO: Ensure it's okay not to return anything here? | |
return 0; | |
} else if (rq->bRequest == USBRQ_HID_GET_IDLE) { | |
//usbMsgPtr = &idleRate; | |
//return 1; | |
return 0; | |
} else if (rq->bRequest == USBRQ_HID_SET_IDLE) { | |
idleRate = rq->wValue.bytes[1]; | |
} | |
} else { | |
/* no vendor specific requests implemented */ | |
} | |
return 0; | |
} | |
#ifdef __cplusplus | |
} // extern "C" | |
#endif | |
#endif // __DigiKeyboard_h__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/pgmspace.h> | |
// Lookup table to convert ascii characters in to keyboard scan codes | |
// Format: most signifficant bit indicates if scan code should be sent with shift modifier | |
// remaining 7 bits are to be used as scan code number. | |
#define SHIFT 0x80 | |
#define ALTGR 0x40 | |
const unsigned char ascii_to_scan_code_table[] PROGMEM = { | |
0x2a, // BS (backspace) | |
0x2b, // TAB (horizontal tab) | |
KEY_ENTER, // LF (NL line feed, new line) | |
0x00, // VT (vertical tab) | |
0x00, // FF (NP form feed, new page) | |
0x00, // CR (carriage return) | |
0x00, // SO (shift out) | |
0x00, // SI (shift in) | |
0x00, // DLE (data link escape) | |
0x00, // DC1 (device control 1) | |
0x00, // DC2 (device control 2) | |
0x00, // DC3 (device control 3) | |
0x00, // DC4 (device control 4) | |
0x00, // NAK (negative acknowledge) | |
0x00, // SYN (synchronous idle) | |
0x00, // ETB (end of trans. block) | |
0x00, // CAN (cancel) | |
0x00, // EM (end of medium) | |
0x00, // SUB (substitute) | |
0x29, // ESC (escape) | |
0x00, // FS (file separator) | |
0x00, // GS (group separator) | |
0x00, // RS (record separator) | |
0x00, // US (unit separator) | |
#ifdef kbd_en_us | |
KEY_SPACE, // Space | |
KEY_1|SHIFT, // ! | |
0x34|SHIFT, // " | |
KEY_3|SHIFT, // # | |
KEY_4|SHIFT, // $ | |
KEY_5|SHIFT, // % | |
KEY_7|SHIFT, // & | |
0x34, // ' | |
KEY_9|SHIFT, // ( | |
KEY_0|SHIFT, // ) | |
KEY_8|SHIFT, // * | |
0x2e|SHIFT, // + | |
0x36, // , | |
0x2d, // - | |
0x37, // . | |
0x38, // / | |
KEY_0, // 0 | |
KEY_1, // 1 | |
KEY_2, // 2 | |
KEY_3, // 3 | |
KEY_4, // 4 | |
KEY_5, // 5 | |
KEY_6, // 6 | |
KEY_7, // 7 | |
KEY_8, // 8 | |
KEY_9, // 9 | |
0x33|SHIFT, // : | |
0x33, // ; | |
0x36|SHIFT, // < | |
0x2e, // = | |
0x37|SHIFT, // > | |
0x38|SHIFT, // ? | |
KEY_2|SHIFT, // @ | |
KEY_A|SHIFT, // A | |
KEY_B|SHIFT, // B | |
KEY_C|SHIFT, // C | |
KEY_D|SHIFT, // D | |
KEY_E|SHIFT, // E | |
KEY_F|SHIFT, // F | |
KEY_G|SHIFT, // G | |
KEY_H|SHIFT, // H | |
KEY_I|SHIFT, // I | |
KEY_J|SHIFT, // J | |
KEY_K|SHIFT, // K | |
KEY_L|SHIFT, // L | |
KEY_M|SHIFT, // M | |
KEY_N|SHIFT, // N | |
KEY_O|SHIFT, // O | |
KEY_P|SHIFT, // P | |
KEY_Q|SHIFT, // Q | |
KEY_R|SHIFT, // R | |
KEY_S|SHIFT, // S | |
KEY_T|SHIFT, // T | |
KEY_U|SHIFT, // U | |
KEY_V|SHIFT, // V | |
KEY_W|SHIFT, // W | |
KEY_X|SHIFT, // X | |
KEY_Y|SHIFT, // Y | |
KEY_Z|SHIFT, // Z | |
0x2f, // [ | |
0x31, // Backslash | |
0x30, // ] | |
KEY_6|SHIFT, // ^ | |
0x2d|SHIFT, // _ | |
0x35, // ` | |
KEY_A, // a | |
KEY_B, // b | |
KEY_C, // c | |
KEY_D, // d | |
KEY_E, // e | |
KEY_F, // f | |
KEY_G, // g | |
KEY_H, // h | |
KEY_I, // i | |
KEY_J, // j | |
KEY_K, // k | |
KEY_L, // l | |
KEY_M, // m | |
KEY_N, // n | |
KEY_O, // o | |
KEY_P, // p | |
KEY_Q, // q | |
KEY_R, // r | |
KEY_S, // s | |
KEY_T, // t | |
KEY_U, // u | |
KEY_V, // v | |
KEY_W, // w | |
KEY_X, // x | |
KEY_Y, // y | |
KEY_Z, // z | |
0x2f|SHIFT, // { | |
0x31|SHIFT, // | | |
0x30|SHIFT, // } | |
0x35|SHIFT, // ~ | |
#endif | |
#ifdef kbd_es_es | |
KEY_SPACE, // Space | |
KEY_1|SHIFT, // ! | |
KEY_2|SHIFT, // " | |
KEY_3|ALTGR, // # | |
KEY_4|SHIFT, // $ | |
KEY_5|SHIFT, // % | |
KEY_6|SHIFT, // & | |
0x2d, // ' | |
KEY_8|SHIFT, // ( | |
KEY_9|SHIFT, // ) | |
0x30|SHIFT, // * | |
0x30, // + | |
0x36, // , | |
0x38, // - | |
0x37, // . | |
KEY_7|SHIFT, // / | |
KEY_0, // 0 | |
KEY_1, // 1 | |
KEY_2, // 2 | |
KEY_3, // 3 | |
KEY_4, // 4 | |
KEY_5, // 5 | |
KEY_6, // 6 | |
KEY_7, // 7 | |
KEY_8, // 8 | |
KEY_9, // 9 | |
0x37|SHIFT, // : | |
0x36|SHIFT, // ; | |
0x03, // < KEY100 | |
KEY_0|SHIFT, // = | |
0x03|SHIFT, // > KEY100|SHIFT | |
0x2d|SHIFT, // ? | |
KEY_2|ALTGR, // @ | |
KEY_A|SHIFT, // A | |
KEY_B|SHIFT, // B | |
KEY_C|SHIFT, // C | |
KEY_D|SHIFT, // D | |
KEY_E|SHIFT, // E | |
KEY_F|SHIFT, // F | |
KEY_G|SHIFT, // G | |
KEY_H|SHIFT, // H | |
KEY_I|SHIFT, // I | |
KEY_J|SHIFT, // J | |
KEY_K|SHIFT, // K | |
KEY_L|SHIFT, // L | |
KEY_M|SHIFT, // M | |
KEY_N|SHIFT, // N | |
KEY_O|SHIFT, // O | |
KEY_P|SHIFT, // P | |
KEY_Q|SHIFT, // Q | |
KEY_R|SHIFT, // R | |
KEY_S|SHIFT, // S | |
KEY_T|SHIFT, // T | |
KEY_U|SHIFT, // U | |
KEY_V|SHIFT, // V | |
KEY_W|SHIFT, // W | |
KEY_X|SHIFT, // X | |
KEY_Y|SHIFT, // Y | |
KEY_Z|SHIFT, // Z | |
0x2f|ALTGR, // [ | |
0x35|ALTGR, // Backslash | |
0x30|ALTGR, // ] | |
0x2f|SHIFT, // ^ KEY+SPACE | |
0x38|SHIFT, // _ | |
0x2f, // ` KEY+SPACE | |
KEY_A, // a | |
KEY_B, // b | |
KEY_C, // c | |
KEY_D, // d | |
KEY_E, // e | |
KEY_F, // f | |
KEY_G, // g | |
KEY_H, // h | |
KEY_I, // i | |
KEY_J, // j | |
KEY_K, // k | |
KEY_L, // l | |
KEY_M, // m | |
KEY_N, // n | |
KEY_O, // o | |
KEY_P, // p | |
KEY_Q, // q | |
KEY_R, // r | |
KEY_S, // s | |
KEY_T, // t | |
KEY_U, // u | |
KEY_V, // v | |
KEY_W, // w | |
KEY_X, // x | |
KEY_Y, // y | |
KEY_Z, // z | |
0x34|ALTGR, // { | |
KEY_1|ALTGR, // | | |
0x32|ALTGR, // } | |
KEY_4|ALTGR, // ~ | |
#endif | |
}; |
- Added full Keyboard usage values by Danjovic, February 2016
- Report Buffer extended up to 6 keytrokes simultaneous by Danjovic, March 2016
- Added LED control by Danjovic, January 2019
https://github.com/Danjovic/DigistumpArduino/blob/master/digistump-avr/libraries/DigisparkKeyboard/DigiKeyboard.h
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Please Add support hotkey BIOS https://github.com/bkgarry/DigikeyboardBIOS