123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- //
- // Created by robin on 1/8/16.
- //
-
- UsbKeyboardDevice UsbKeyboard = UsbKeyboardDevice("us");
-
-
- /* 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.
- */
- PROGMEM const char usbHidReportDescriptor[35] = { /* 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, BUFFER_SIZE-1, // 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
- };
-
- UsbKeyboardDevice::UsbKeyboardDevice(const char* layout)
- : _layout(0)
- {
- PORTD = 0; // TODO: Only for USB pins?
- DDRD |= ~USBMASK;
-
- cli();
- usbDeviceDisconnect();
- 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));
- setLayout("us");
- }
-
- bool UsbKeyboardDevice::isUsbReady()
- {
- UsbKeyboard.update();
- return usbInterruptIsReady();
- }
-
- void UsbKeyboardDevice::setLayout(const char* layout)
- {
- delete _layout;
- _layout = new char[strlen(layout)];
- strcpy(_layout, layout);
- }
-
- int UsbKeyboardDevice::charModAltGr(char c, int* modifier)
- {
- *modifier = MOD_ALT_RIGHT;
- return c;
- }
-
- int UsbKeyboardDevice::charModShift(char c, int* modifier)
- {
- *modifier = MOD_SHIFT_LEFT;
- return c;
- }
-
- #ifdef ARD_USBKBD_AZERTY
- int UsbKeyboardDevice::charToKeyAzerty(int c, int* modifier)
- {
- *modifier = 0;
-
- if (c == '0')
- return charModShift(KEY_0, modifier);
- if (c >= '1' && c <= '9')
- return charModShift(KEY_1 + c - '1', modifier);
-
- if (c == '\n')
- return KEY_ENTER;
- if (c == ' ')
- return KEY_SPACE;
-
-
- if (c >= 'a' && c <= 'z')
- {
- if (c == 'a')
- c = 'q';
- else if (c == 'm')
- return KEY_SEMICOLON;
- else if (c == 'q')
- c = 'a';
- else if (c == 'w')
- c = 'z';
- else if (c == 'z')
- c = 'w';
- return KEY_A + c - 'a';
- }
- if (c >= 'A' && c <= 'Z')
- {
- if (c == 'A')
- c = 'Q';
- else if (c == 'M')
- return charModShift(KEY_SEMICOLON, modifier);
- else if (c == 'Q')
- c = 'A';
- else if (c == 'W')
- c = 'Z';
- else if (c == 'Z')
- c = 'W';
- return charModShift(KEY_A + c - 'A', modifier);
- }
-
- if (c == '~')
- return charModAltGr(KEY_2, modifier);
- if (c == '#')
- return charModAltGr(KEY_3, modifier);
- if (c == '{')
- return charModAltGr(KEY_4, modifier);
- if (c == '[')
- return charModAltGr(KEY_5, modifier);
- if (c == '|')
- return charModAltGr(KEY_6, modifier);
- if (c == '`')
- return charModAltGr(KEY_7, modifier);
- if (c == '\\')
- return charModAltGr(KEY_8, modifier);
- if (c == '^')
- return charModAltGr(KEY_9, modifier);
- if (c == '@')
- return charModAltGr(KEY_0, modifier);
- if (c == ']')
- return charModAltGr(KEY_HYPHEN, modifier);
- if (c == '}')
- return charModAltGr(KEY_EQUAL, modifier);
- if (c == -75)//µ
- return charModShift(KEY_BSLASH, modifier);
- if (c == '*')
- return KEY_BSLASH;
-
- if (c == '&')
- return KEY_1;
- if (c == -23)//é
- return KEY_2;
- if (c == '\"')
- return KEY_3;
- if (c == '\'')
- return KEY_4;
- if (c == '(')
- return KEY_5;
- if (c == '-')
- return KEY_6;
- if (c == -24)//è
- return KEY_7;
- if (c == '_')
- return KEY_8;
- if (c == -25)//ç
- return KEY_9;
- if (c == -32)//à
- return KEY_0;
- if (c == ')')
- return KEY_HYPHEN;
- if (c == '=')
- return KEY_EQUAL;
- if (c == '+')
- return charModShift(KEY_EQUAL, modifier);
-
- if (c == ',')
- return KEY_M;
- if (c == ';')
- return KEY_COMMA;
- if (c == ':')
- return KEY_DOT;
- if (c == '!')
- return KEY_SLASH;
- if (c == -7)//ù
- return KEY_QUOTE;
- if (c == '<')
- return KEYP_NUS_BSLASH;
-
- if (c == '?')
- return charModShift(KEY_M, modifier);
- if (c == '.')
- return charModShift(KEY_COMMA, modifier);
- if (c == '/')
- return charModShift(KEY_DOT, modifier);
- if (c == -89)//§
- return charModShift(KEY_SLASH, modifier);
- if (c == '%')
- return charModShift(KEY_QUOTE, modifier);
- if (c == '>')
- return charModShift(KEYP_NUS_BSLASH, modifier);
-
- return 0;
- }
- #endif
-
- #ifdef ARD_USBKBD_QWERTY
- int UsbKeyboardDevice::charToKeyQwerty(int c, int* modifier)
- {
- *modifier = 0;
- if (c == '0')
- return KEY_0;
- if (c >= '1' && c <= '9')
- return KEY_1 + c - '1';
- if (c >= 'a' && c <= 'z')
- return KEY_A + c - 'a';
- if (c >= 'A' && c <= 'Z')
- return charModShift(KEY_A + c - 'A', modifier);
-
- if (c == '\n')
- return KEY_ENTER;
- if (c == ' ')
- return KEY_SPACE;
-
-
- if (c == '.')
- return KEY_DOT;
- if (c == ',')
- return KEY_COMMA;
- if (c == '/')
- return KEY_SLASH;
- if (c == ';')
- return KEY_SEMICOLON;
- if (c == '`')
- return KEY_TILDE;
- if (c == '-')
- return KEY_HYPHEN;
- if (c == '=')
- return KEY_EQUAL;
- if (c == '\'')
- return KEY_QUOTE;
- if (c == '~')
- return charModShift(KEY_TILDE, modifier);
- if (c == '<')
- return charModShift(KEY_COMMA, modifier);
- if (c == '>')
- return charModShift(KEY_DOT, modifier);
- if (c == '?')
- return charModShift(KEY_SLASH, modifier);
- if (c == ':')
- return charModShift(KEY_SEMICOLON, modifier);
-
- if (c == '!')
- return charModShift(KEY_1, modifier);
- if (c == '@')
- return charModShift(KEY_2, modifier);
- if (c == '#')
- return charModShift(KEY_3, modifier);
- if (c == '$')
- return charModShift(KEY_4, modifier);
- if (c == '%')
- return charModShift(KEY_5, modifier);
- if (c == '^')
- return charModShift(KEY_6, modifier);
- if (c == '&')
- return charModShift(KEY_7, modifier);
- if (c == '*')
- return charModShift(KEY_8, modifier);
- if (c == '(')
- return charModShift(KEY_9, modifier);
- if (c == ')')
- return charModShift(KEY_0, modifier);
- if (c == '_')
- return charModShift(KEY_HYPHEN, modifier);
- if (c == '+')
- return charModShift(KEY_EQUAL, modifier);
- if (c == '"')
- return charModShift(KEY_QUOTE, modifier);
-
- if (c == '{')
- return charModShift(KEY_LBRACKET, modifier);
- if (c == '}')
- return charModShift(KEY_RBRACKET, modifier);
- if (c == '|')
- return charModShift(KEY_BSLASH, modifier);
-
- if (c == '[')
- return KEY_LBRACKET;
- if (c == ']')
- return KEY_RBRACKET;
- if (c == '\\')
- return KEY_BSLASH;
- return 0;
- }
- #endif
-
- void UsbKeyboardDevice::sendKeyStrokes(const char* str)
- {
- int (*charToKey)(int,int*) = 0;
- #ifdef ARD_USBKBD_AZERTY
- if (!strcmp(_layout, "fr"))
- {
- charToKey = charToKeyAzerty;
- }
- #endif
- #ifdef ARD_USBKBD_QWERTY
- if (!strcmp(_layout, "us"))
- {
- charToKey = charToKeyQwerty;
- }
- #endif
- if (!charToKey)
- {
- return;
- }
-
- while (*str)
- {
- int modifier = 0;
- int k = charToKey(*str, &modifier);
- /*if (!k)
- {
- k = KEY_SPACE;
- char buf[12];
- itoa((unsigned)*str, buf, 10);
- sendKeyStrokes(buf);
- }*/
- if (k)
- {
- UsbKeyboard.sendKeyStroke(k, modifier);
- }
- ++str;
- }
- }
-
- void UsbKeyboardDevice::sendKeyStroke(byte keyStroke, byte modifiers)
- {
-
- while (!usbInterruptIsReady()) {
- // Note: We wait until we can send keystroke
- // so we know the previous keystroke was
- // sent.
- }
-
- memset(reportBuffer, 0, sizeof(reportBuffer));
-
- reportBuffer[0] = modifiers;
- reportBuffer[1] = keyStroke;
-
- usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
-
- while (!usbInterruptIsReady()) {
- // Note: We wait until we can send keystroke
- // so we know the previous keystroke was
- // sent.
- }
-
- // This stops endlessly repeating keystrokes:
- memset(reportBuffer, 0, sizeof(reportBuffer));
- usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
-
- }
-
-
- uchar usbFunctionSetup(uchar data[8])
- {
- usbRequest_t *rq = (usbRequest_t *)((void *)data);
-
- usbMsgPtr = UsbKeyboard.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;
- }
|