diff --git a/examples/ImprovedMouse/ImprovedMouse.ino b/examples/ImprovedMouse/ImprovedMouse.ino index 45fcb21..3789431 100644 --- a/examples/ImprovedMouse/ImprovedMouse.ino +++ b/examples/ImprovedMouse/ImprovedMouse.ino @@ -5,7 +5,7 @@ Mouse example Press a button to click or move the mouse. - You may also use BootMouse to enable a bios compatible mouse. + You may also use BootMouse to enable a bios compatible (single report) mouse. However this is very unusual and not recommended. Bios mice dont support wheels which can cause problems after a reboot. diff --git a/examples/NKROKeyboard/NKROKeyboard.ino b/examples/NKROKeyboard/NKROKeyboard.ino index 16cca5f..16cd17f 100644 --- a/examples/NKROKeyboard/NKROKeyboard.ino +++ b/examples/NKROKeyboard/NKROKeyboard.ino @@ -8,6 +8,8 @@ NKRO can push 113 keys at the same time, the other Keyboards only 6 keys + 8 modifiers! + You may also use SingleNKROKeyboard to enable a single report NKROKeyboard. + See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/Keyboard-API */ diff --git a/keywords.txt b/keywords.txt index ed8860a..0f9d4d4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -72,6 +72,7 @@ Gamepad3 KEYWORD1 Gamepad4 KEYWORD1 TeensyKeyboard KEYWORD1 NKROKeyboard KEYWORD1 +SingleNKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 ####################################### diff --git a/src/HID-APIs/NKROKeyboardAPI.h b/src/HID-APIs/NKROKeyboardAPI.h new file mode 100644 index 0000000..c5a9fec --- /dev/null +++ b/src/HID-APIs/NKROKeyboardAPI.h @@ -0,0 +1,78 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "HID-Settings.h" +#include "ImprovedKeylayouts.h" +#include "HID-Tables.h" //TODO + +// Max value for USB EP_SIZE 16 +// +1 reportID, +1 modifier, +1 custom key +#define NKRO_KEY_COUNT (8*13) + +typedef union{ + // Modifier + keymap + 1 custom key + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t key; + }; +} HID_NKROKeyboardReport_Data_t; + + +class NKROKeyboardAPI : public Print +{ +public: + inline NKROKeyboardAPI(void); + inline void begin(void); + inline void end(void); + inline size_t write(uint8_t k); + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline void releaseAll(void); + inline void send_now(void); + + inline size_t writeKeycode(uint8_t k); + inline size_t pressKeycode(uint8_t k); + inline size_t releaseKeycode(uint8_t k); + inline size_t addKeyToReport(uint8_t k); + inline size_t addKeycodeToReport(uint8_t k); + inline size_t removeKeyFromReport(uint8_t k); + inline size_t removeKeycodeFromReport(uint8_t k); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + +protected: + HID_NKROKeyboardReport_Data_t _keyReport; +}; + +// Implementation is inline +#include "NKROKeyboardAPI.hpp" + diff --git a/src/HID-APIs/NKROKeyboardAPI.hpp b/src/HID-APIs/NKROKeyboardAPI.hpp new file mode 100644 index 0000000..9d15ed7 --- /dev/null +++ b/src/HID-APIs/NKROKeyboardAPI.hpp @@ -0,0 +1,216 @@ +/* +Copyright (c) 2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +NKROKeyboardAPI::NKROKeyboardAPI(void) +{ + // Empty +} + +void NKROKeyboardAPI::begin(void) +{ + releaseAll(); +} + +void NKROKeyboardAPI::end(void) +{ + releaseAll(); +} + +void NKROKeyboardAPI::send_now(void){ + SendReport(&_keyReport, sizeof(_keyReport)); +} + +// press() adds the specified key (printing, non-printing, or modifier) +// to the persistent key report and sends the report. Because of the way +// USB HID works, the host acts like the key remains pressed until we +// call release(), releaseAll(), or otherwise clear the report and resend. +size_t NKROKeyboardAPI::press(uint8_t k) +{ + size_t ret = addKeyToReport(k); + if(ret){ + send_now(); + } + return ret; +} + +// release() takes the specified key out of the persistent key report and +// sends the report. This tells the OS the key is no longer pressed and that +// it shouldn't be repeated any more. +size_t NKROKeyboardAPI::release(uint8_t k) +{ + // it's a non-printing key (not a modifier) + if (k >= 136) + k = k - 136; + + // it's a modifier key + else if (k >= 128) + k = k - 128; + + // it's a printing key + else { + k = pgm_read_byte(_asciimap + k); + if (!k) + return 0; + + // it's a capital letter or other character reached with shift + if (k & SHIFT) { + // the left shift modifier + _keyReport.modifiers &= ~(0x02); + k = k ^ SHIFT; + } + } + + removeKeycodeFromReport(k); + send_now(); + + return 1; +} + +void NKROKeyboardAPI::releaseAll(void) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + send_now(); +} + +size_t NKROKeyboardAPI::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + + +// pressKeycode() adds the specified key (printing, non-printing, or modifier) +// to the persistent key report and sends the report. Because of the way +// USB HID works, the host acts like the key remains pressed until we +// call releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t NKROKeyboardAPI::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + send_now(); +} + +size_t NKROKeyboardAPI::addKeyToReport(uint8_t k) +{ + if (k >= 136) { // it's a non-printing key (not a modifier) + k = k - 136; + } else if (k >= 128) { // it's a modifier key + _keyReport.modifiers |= (1<<(k-128)); + k = 0; //TODO return 1?? + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + setWriteError(); + return 0; + } + if (k & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k = k ^ SHIFT; + } + } + + return addKeycodeToReport(k); +} + +size_t NKROKeyboardAPI::addKeycodeToReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] |= 1 << (k % 8); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = k; + + return 1; +} + + +// releaseKeycode() takes the specified key out of the persistent key report and +// sends the report. This tells the OS the key is no longer pressed and that +// it shouldn't be repeated any more. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t NKROKeyboardAPI::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + send_now(); +} + +size_t NKROKeyboardAPI::removeKeyFromReport(uint8_t k) +{ + if (k >= 136) { // it's a non-printing key (not a modifier) + k = k - 136; + } else if (k >= 128) { // it's a modifier key + _keyReport.modifiers &= ~(1<<(k-128)); + k = 0; + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + return 0; + } + if (k & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + return removeKeycodeFromReport(k); +} + +size_t NKROKeyboardAPI::removeKeycodeFromReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] &= ~(1 << (k % 8)); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers &= ~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = 0x00; + + return 1; +} + + +size_t NKROKeyboardAPI::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} diff --git a/src/HID-Project.h b/src/HID-Project.h index 25ac9f2..42f300c 100644 --- a/src/HID-Project.h +++ b/src/HID-Project.h @@ -53,5 +53,6 @@ THE SOFTWARE. #else #include "SingleReport/BootKeyboard.h" #include "MultiReport/ImprovedKeyboard.h" -//#include "NKROKeyboard.h" +#include "SingleReport/SingleNKROKeyboard.h" +#include "MultiReport/NKROKeyboard.h" #endif diff --git a/src/MultiReport/NKROKeyboard.cpp b/src/MultiReport/NKROKeyboard.cpp new file mode 100644 index 0000000..f635c9b --- /dev/null +++ b/src/MultiReport/NKROKeyboard.cpp @@ -0,0 +1,79 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "NKROKeyboard.h" + +static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { + // NKRO Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* 104 Keys as bitmap */ + 0x05, 0x07, /* Usage Page (Key Codes) TODO needed?*/ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* 1 Custom Keyboard key */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + /*0x05, 0x07, USAGE_PAGE (Keyboard) TODO */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xC0 /* End Collection */ +}; + +NKROKeyboard_::NKROKeyboard_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); + HID().AppendDescriptor(&node); +} + +void NKROKeyboard_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, data, length); +} + +NKROKeyboard_ NKROKeyboard; + diff --git a/src/MultiReport/NKROKeyboard.h b/src/MultiReport/NKROKeyboard.h new file mode 100644 index 0000000..7b94add --- /dev/null +++ b/src/MultiReport/NKROKeyboard.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/NKROKeyboardAPI.h" + + +class NKROKeyboard_ : public NKROKeyboardAPI +{ +public: + NKROKeyboard_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern NKROKeyboard_ NKROKeyboard; + diff --git a/src/SingleReport/SingleNKROKeyboard.cpp b/src/SingleReport/SingleNKROKeyboard.cpp new file mode 100644 index 0000000..381ecea --- /dev/null +++ b/src/SingleReport/SingleNKROKeyboard.cpp @@ -0,0 +1,161 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "SingleNKROKeyboard.h" + +static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { + // NKRO Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* Reserved 3 bits */ + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + + /* 104 Keys as bitmap */ + 0x05, 0x07, /* Usage Page (Key Codes) */ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* 1 Custom Keyboard key */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + /*0x05, 0x07, USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xC0 /* End Collection */ +}; + +SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleNKROKeyboard_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidReportDescriptorNKRO)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleNKROKeyboard_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorNKRO, sizeof(_hidReportDescriptorNKRO)); +} + +bool SingleNKROKeyboard_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + // Check if data has the correct length + auto length = setup.wLength; + if(length == sizeof(leds)){ + USB_RecvControl(&leds, length); + } + } + } + + return false; +} + +uint8_t SingleNKROKeyboard_::getLeds(void){ + return leds; +} + +void SingleNKROKeyboard_::SendReport(void* data, int length){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleNKROKeyboard_ SingleNKROKeyboard; + + diff --git a/src/SingleReport/SingleNKROKeyboard.h b/src/SingleReport/SingleNKROKeyboard.h new file mode 100644 index 0000000..299ed16 --- /dev/null +++ b/src/SingleReport/SingleNKROKeyboard.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/NKROKeyboardAPI.h" + + +class SingleNKROKeyboard_ : public PUSBListNode, public NKROKeyboardAPI +{ +public: + SingleNKROKeyboard_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; + + virtual void SendReport(void* data, int length) override; +}; +extern SingleNKROKeyboard_ SingleNKROKeyboard; + +