diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.cpp new file mode 100644 index 00000000..37720546 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.cpp @@ -0,0 +1,385 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "BootKeyboard.h" +#include "DescriptorPrimitives.h" +#include "HIDReportObserver.h" + +// See Appendix B of USB HID spec +static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { + // Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + + D_COLLECTION, D_APPLICATION, + // Modifiers + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0xe0, + D_USAGE_MAXIMUM, 0xe7, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0x1, + D_REPORT_SIZE, 0x1, + D_REPORT_COUNT, 0x8, + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + // Reserved byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x8, + D_INPUT, (D_CONSTANT), + + // LEDs + D_REPORT_COUNT, 0x5, + D_REPORT_SIZE, 0x1, + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x1, + D_USAGE_MAXIMUM, 0x5, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + // Pad LEDs up to a byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x3, + D_OUTPUT, (D_CONSTANT), + + // Non-modifiers + D_REPORT_COUNT, 0x6, + D_REPORT_SIZE, 0x8, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0xff, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0x0, + D_USAGE_MAXIMUM, 0xff, + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), + D_END_COLLECTION +}; + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES +static const uint8_t BOOT_KEYBOARD_EP_SIZE = 8; +#else +static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; +#endif + + +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES + epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif + PluggableUSB().plug(this); +} + +int BootKeyboard_::getInterface(uint8_t* interfaceCount) { + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), + D_HIDREPORT(sizeof(boot_keyboard_hid_descriptor_)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, BOOT_KEYBOARD_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int BootKeyboard_::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; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = default_protocol; + + return USB_SendControl(TRANSFER_PGM, boot_keyboard_hid_descriptor_, sizeof(boot_keyboard_hid_descriptor_)); +} + + +void BootKeyboard_::begin() { + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); +} + + +void BootKeyboard_::end() { + releaseAll(); + sendReport(); +} + + + +bool BootKeyboard_::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 improve +#ifdef __AVR__ + UEDATX = protocol; +#endif +#ifdef ARDUINO_ARCH_SAM + USBDevice.armSend(0, &protocol, 1); +#endif + return true; + } + if (request == HID_GET_IDLE) { + // TODO improve +#ifdef __AVR__ + UEDATX = idle; +#endif +#ifdef ARDUINO_ARCH_SAM + USBDevice.armSend(0, &idle, 1); +#endif + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing + // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we + // force this to zero, either. +#if 0 + idle = setup.wValueL; +#else + idle = 0; +#endif + return true; + } + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (length == sizeof(leds)) { + USB_RecvControl(&leds, length); + return true; + } + } + + // Input (set HID report) + else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { + if (length == sizeof(report_)) { + USB_RecvControl(&report_, length); + return true; + } + } + } + } + + return false; +} + +uint8_t BootKeyboard_::getLeds() { + return leds; +} + +uint8_t BootKeyboard_::getProtocol() { + return protocol; +} + +void BootKeyboard_::setProtocol(uint8_t protocol) { + this->protocol = protocol; +} + +int BootKeyboard_::sendReport() { + if (memcmp(&last_report_, &report_, sizeof(report_))) { + // if the two reports are different, send a report + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &report_, sizeof(report_)); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &report_, sizeof(report_), returnCode); + memcpy(&last_report_, &report_, sizeof(report_)); + return returnCode; + } + return -1; +} + +// 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 BootKeyboard_::press(uint8_t k) { + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + report_.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] != k) { // is k already in list? + if (0 == report_.keycodes[i]) { // have we found an empty slot? + report_.keycodes[i] = k; + done = 1; + break; + } + } else { + done = 1; + break; + } + } + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + return 0; + } + } + return 1; +} + + +// 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 BootKeyboard_::release(uint8_t k) { + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + report_.modifiers = report_.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); + } else { + // it's some other key: + // Test the key report to see if k is present. Clear it if it exists. + // Check all positions in case the key is present more than once (which it shouldn't be) + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] == k) { + report_.keycodes[i] = 0; + } + } + + // rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) + uint8_t current = 0, nextpos = 0; + + while (current < sizeof(report_.keycodes)) { + if (report_.keycodes[current]) { + uint8_t tmp = report_.keycodes[nextpos]; + report_.keycodes[nextpos] = report_.keycodes[current]; + report_.keycodes[current] = tmp; + ++nextpos; + } + ++current; + } + } + + return 1; +} + + +void BootKeyboard_::releaseAll() { + memset(&report_.bytes, 0x00, sizeof(report_.bytes)); +} + + +/* Returns true if the non-modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboard_::isKeyPressed(uint8_t k) { + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] == k) { + return true; + } + } + return false; +} + +/* Returns true if the non-modifer key passed in was sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboard_::wasKeyPressed(uint8_t k) { + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (last_report_.keycodes[i] == k) { + return true; + } + } + return false; +} + + + +/* Returns true if the modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboard_::isModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if the modifer key passed in was being sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboard_::wasModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(last_report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if any modifier key will be sent during this key report + * Returns false in all other cases + * */ +bool BootKeyboard_::isAnyModifierActive() { + return report_.modifiers > 0; +} + +/* Returns true if any modifier key was being sent during the previous key report + * Returns false in all other cases + * */ +bool BootKeyboard_::wasAnyModifierActive() { + return last_report_.modifiers > 0; +} + +__attribute__((weak)) +BootKeyboard_ BootKeyboard; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.h b/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.h new file mode 100644 index 00000000..d7cfeadb --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/BootKeyboard/BootKeyboard.h @@ -0,0 +1,83 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HIDTables.h" +#include "HIDAliases.h" + +typedef union { + // Low level key report: up to 6 keys and shift, ctrl etc at once + struct { + uint8_t modifiers; + uint8_t reserved; + uint8_t keycodes[6]; + }; + uint8_t bytes[8]; +} HID_BootKeyboardReport_Data_t; + + +class BootKeyboard_ : public PluggableUSBModule { + public: + BootKeyboard_(uint8_t protocol_ = HID_REPORT_PROTOCOL); + size_t press(uint8_t k); + void begin(); + void end(); + size_t release(uint8_t k); + void releaseAll(); + + int sendReport(); + + bool isModifierActive(uint8_t k); + bool wasModifierActive(uint8_t k); + bool isAnyModifierActive(); + bool wasAnyModifierActive(); + bool isKeyPressed(uint8_t k); + bool wasKeyPressed(uint8_t k); + + uint8_t getLeds(); + uint8_t getProtocol(); + void setProtocol(uint8_t protocol); + + uint8_t default_protocol; + + protected: + HID_BootKeyboardReport_Data_t report_, last_report_; + + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + EPTYPE_DESCRIPTOR_SIZE epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; +}; +extern BootKeyboard_ BootKeyboard; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/DescriptorPrimitives.h b/src/kaleidoscope/driver/hid/keyboardio/usb/DescriptorPrimitives.h new file mode 100644 index 00000000..857dd84b --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/DescriptorPrimitives.h @@ -0,0 +1,145 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + +#define D_MULTIBYTE(n) (n + 0x01) + +#define D_USAGE_PAGE 0x05 +#define D_USAGE 0x09 + + +#define D_REPORT_ID 0x85 + +#define D_USAGE_MINIMUM 0x19 +#define D_USAGE_MAXIMUM 0x29 + +#define D_LOGICAL_MINIMUM 0x15 +#define D_LOGICAL_MAXIMUM 0x25 + +#define D_PHYSICAL_MINIMUM 0x35 +#define D_PHYSICAL_MAXIMUM 0x45 + +#define D_REPORT_SIZE 0x75 +#define D_REPORT_COUNT 0x95 + +#define D_PUSH 0xa4 +#define D_POP 0xb4 + +// USB HID DCD 1.11 section 6.2.2.4 - Main items +// +// each of these are the type description + 0x01 for a single byte item +#define D_INPUT 0x81 +#define D_OUTPUT 0x91 +#define D_FEATURE 0xb1 +#define D_COLLECTION 0xa1 +#define D_END_COLLECTION 0xc0 + +// The bits that make up inputs, outputs and features + +// Bit 0 +#define D_DATA 0b00000000 +#define D_CONSTANT 0b00000001 +// Bit 1 +#define D_ARRAY 0b00000000 +#define D_VARIABLE 0b00000010 +// Bit 2 +#define D_ABSOLUTE 0b00000000 +#define D_RELATIVE 0b00000100 +// Bit 3 +#define D_NO_WRAP 0b00000000 +#define D_WRAP 0b00001000 +// Bit 4 +#define D_LINEAR 0b00000000 +#define D_NON_LINEAR 0b00010000 +// Bit 5 +#define D_PREFERRED_STATE 0b00000000 +#define D_NO_PREFERRED 0b00100000 +// Bit 6 +#define D_NO_NULL_POSITION 0b00000000 +#define D_NULL_STATE 0b01000000 +// Bit 7 +#define D_NON_VOLATILE 0b00000000 +#define D_VOLATILE 0b01000000 +// Bit 8 +#define D_BIT_FIELD 0b00000000 +#define D_BUFFERED_BYTES 0b10000000 + + + +// Collection types + + +#define D_PHYSICAL 0x00 // (group of axes) +#define D_APPLICATION 0x01 // (mouse, keyboard) +#define D_LOGICAL 0x02 // (interrelated data) +#define D_REPORT 0x03 +#define D_NAMED_ARRAY 0x04 +#define D_USAGE_SWITCH 0x05 +#define D_USAGE_MODIFIER 0x06 +// 0x07-0x7f - Reserved +// 0x80-0xff - Vendor define + + +#define D_PAGE_GENERIC_DESKTOP 0x01 +#define D_PAGE_SIMULATION 0x02 +#define D_PAGE_VR 0x03 +#define D_PAGE_SPORT 0x04 +#define D_PAGE_GAME 0x05 +#define D_PAGE_GENERIC_DEVICE 0x06 +#define D_PAGE_KEYBOARD 0x07 +#define D_PAGE_LEDS 0x08 +#define D_PAGE_BUTTON 0x09 +#define D_PAGE_ORDINAL 0x0A +#define D_PAGE_TELEPHONY 0x0B +#define D_PAGE_CONSUMER 0x0C +#define D_PAGE_DIGITIZER 0x0D +#define D_PAGE_RESERVED 0x0E +#define D_PAGE_PID 0x0F +#define D_PAGE_UNICODE 0x10 +// 0x11-13 RESERVED +#define D_PAGE_ALPHANUMERIC_DISPLAY 0x14 +#define D_PAGE_MEDICAL_INSTRUMENTS 0x40 +// 0x80-83 MONITOR +// 0x84-87 POWER +#define D_PAGE_BAR_CODE_SCANNER 0x8C +#define D_PAGE_SCALE 0x8D +#define D_PAGE_MSR 0x8E +// 0x8F RESERVED POINT OF SALE +#define D_PAGE_CAMERA_CONTROL 0x90 +#define D_PAGE_ARCADE 0x91 + + +// Generic Desktop Usages HUT Section 4 p27 + + +#define D_USAGE_POINTER 0x01 +#define D_USAGE_MOUSE 0x02 +// 0x03 is reserved +#define D_USAGE_JOYSTICK 0x04 +#define D_USAGE_GAMEPAD 0x05 +#define D_USAGE_KEYBOARD 0x06 +#define D_USAGE_KEYPAD 0x07 +#define D_USAGE_MULITAXIS 0x08 diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.h b/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.h new file mode 100644 index 00000000..a2150728 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.h @@ -0,0 +1,104 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" +#include "MouseButtons.h" +#include "DescriptorPrimitives.h" + + +#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ + /* 8 Buttons */ \ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + +# define DESCRIPTOR_ABS_MOUSE_XY \ + /* X, Y */ \ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ \ + D_USAGE, 0x30, /* USAGE (X) */ \ + D_USAGE, 0x31, /* USAGE (Y) */ \ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ \ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ \ + D_REPORT_SIZE, 0x10, /* Report Size (16), */ \ + D_REPORT_COUNT, 0x02, /* Report Count (2), */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ + +#define DESCRIPTOR_ABS_MOUSE_WHEEL \ + /* Wheel */ \ + D_USAGE, 0x38, /* USAGE (Wheel) */ \ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ \ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ \ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + +#pragma pack(push, 1) +typedef union { + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + struct { + uint8_t buttons; + uint16_t xAxis; + uint16_t yAxis; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; +#pragma pack(pop) + +class AbsoluteMouseAPI { + public: + inline AbsoluteMouseAPI(); + inline void begin(); + inline void end(); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(uint16_t x, uint16_t y, int8_t wheel = 0); + inline void move(int x, int y, int8_t wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length) {} + + protected: + uint16_t x_axis_; + uint16_t y_axis_; + uint8_t buttons_; + + inline void buttons(uint8_t b); + inline int16_t qadd16(int16_t base, int16_t increment); +}; + +#include "AbsoluteMouseAPI.hpp" diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.hpp b/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.hpp new file mode 100644 index 00000000..21bb1f58 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -0,0 +1,103 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + +AbsoluteMouseAPI::AbsoluteMouseAPI() + : x_axis_(0), y_axis_(0), buttons_(0) {} + +void AbsoluteMouseAPI::buttons(uint8_t b) { + if (b != buttons_) { + buttons_ = b; + moveTo(x_axis_, y_axis_, 0); + } +} + +int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; +} + +void AbsoluteMouseAPI::begin() { + // release all buttons + end(); +} + +void AbsoluteMouseAPI::end() { + buttons_ = 0; + moveTo(x_axis_, y_axis_, 0); +} + +void AbsoluteMouseAPI::click(uint8_t b) { + buttons_ = b; + moveTo(x_axis_, y_axis_, 0); + buttons_ = 0; + moveTo(x_axis_, y_axis_, 0); +} + +void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { + x_axis_ = x; + y_axis_ = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = buttons_; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + sendReport(&report, sizeof(report)); +} + +void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { + moveTo(qadd16(x_axis_, x), qadd16(y_axis_, y), wheel); +} + +void AbsoluteMouseAPI::press(uint8_t b) { + // press LEFT by default + buttons(buttons_ | b); +} + +void AbsoluteMouseAPI::release(uint8_t b) { + // release LEFT by default + buttons(buttons_ & ~b); +} + +bool AbsoluteMouseAPI::isPressed(uint8_t b) { + // check LEFT by default + if ((b & buttons_) > 0) + return true; + return false; +} diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HID-Settings.h b/src/kaleidoscope/driver/hid/keyboardio/usb/HID-Settings.h new file mode 100644 index 00000000..7eff1e09 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HID-Settings.h @@ -0,0 +1,152 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 + + +#define HID_REPORTID_NONE 0 + +#ifndef HID_REPORTID_MOUSE +#define HID_REPORTID_MOUSE 1 +#endif + +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif + +#ifndef HID_REPORTID_RAWHID +// This will not work properly in most cases. +// The number is just kept from the old number counting. +//#define HID_REPORTID_RAWHID 3 +#endif + +#ifndef HID_REPORTID_CONSUMERCONTROL +#define HID_REPORTID_CONSUMERCONTROL 4 +#endif + +#ifndef HID_REPORTID_SYSTEMCONTROL +#define HID_REPORTID_SYSTEMCONTROL 5 +#endif + +#ifndef HID_REPORTID_GAMEPAD +#define HID_REPORTID_GAMEPAD 6 +#endif + +#ifndef HID_REPORTID_MOUSE_ABSOLUTE +#define HID_REPORTID_MOUSE_ABSOLUTE 7 +#endif + +#ifndef HID_REPORTID_NKRO_KEYBOARD +#define HID_REPORTID_NKRO_KEYBOARD 8 +#endif + + +// Nico has submitted these definitions upstream, but they're not merged yet +// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 + +// Controls whether to pack messages or not. When set, any sends will be delayed +// until packing is toggled off, and sent then. This is a no-op on AVR, but is +// required for SAMD. We place a forward-declaration here to be able to avoid +// architecture-specific ifdefs elsewhere in the code. +void USB_PackMessages(bool pack); + +#if defined(ARDUINO_ARCH_AVR) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint8_t + +#elif defined(ARDUINO_ARCH_SAM) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPDIR_IN | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define USB_EP_SIZE EPX_SIZE +#define USB_SendControl USBD_SendControl +#define USB_Available USBD_Available +#define USB_Recv USBD_Recv +#define USB_Send USBD_Send +#define USB_Flush USBD_Flush + +#elif defined(ARDUINO_ARCH_SAMD) + +#include + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); +#define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); +#define USB_EP_SIZE EPX_SIZE +//#define USB_SendControl USBDevice.sendControl -> real C++ functions to take care of PGM overloading +#define USB_Available USBDevice.available +#define USB_Recv USBDevice.recv +#define USB_RecvControl USBDevice.recvControl +#define USB_Send USBDevice.send +#define USB_Flush USBDevice.flush + +int USB_SendControl(void* y, uint8_t z); +int USB_SendControl(uint8_t x, const void* y, uint8_t z); + +#define TRANSFER_PGM 0 +#define TRANSFER_RELEASE 0 + +#elif defined(ARDUINO_ARCH_GD32) + +#include "USBCore.h" + +#define EPTYPE_DESCRIPTOR_SIZE unsigned int + + +// Should eventually get defined upstream +#ifndef USB_DEVICE_CLASS_HUMAN_INTERFACE +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#endif + +#define ARCH_HAS_CONFIGURABLE_EP_SIZES + +constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; } +constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; } + + + +#else + +#error "Unsupported architecture" + +#endif diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HID.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/HID.cpp new file mode 100644 index 00000000..f3e2c730 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HID.cpp @@ -0,0 +1,194 @@ +/* + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted, provided that the + above copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR + BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + */ + +#ifndef KEYBOARDIOHID_BUILD_WITHOUT_HID + +#include "HID.h" +#include "HIDReportObserver.h" + +#if defined(USBCON) + +HID_& HID() { + static HID_ obj; + return obj; +} + +int HID_::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(descriptorSize), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int HID_::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; + } + + int total = 0; + HIDSubDescriptor* node; + USB_PackMessages(true); + for (node = rootNode; node; node = node->next) { + int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); + if (res == -1) + return -1; + total += res; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + USB_PackMessages(false); + return total; +} + +__attribute__((weak)) +uint8_t HID_::getShortName(char *name) { + name[0] = 'k'; + name[1] = 'b'; + name[2] = 'i'; + name[3] = 'o'; + name[4] = '0'; + name[5] = '1'; + return 6; +} + +void HID_::AppendDescriptor(HIDSubDescriptor *node) { + if (!rootNode) { + rootNode = node; + } else { + HIDSubDescriptor *current = rootNode; + while (current->next) { + current = current->next; + } + current->next = node; + } + descriptorSize += node->length; +} + +int HID_::SendReport(uint8_t id, const void* data, int len) { + auto result = SendReport_(id, data, len); + HIDReportObserver::observeReport(id, data, len, result); + return result; +} + +int HID_::SendReport_(uint8_t id, const void* data, int len) { + /* On SAMD, we need to send the whole report in one batch; sending the id, and + * the report itself separately does not work, the report never arrives. Due + * to this, we merge the two into a single buffer, and send that. + * + * While the same would work for other architectures, AVR included, doing so + * costs RAM, which is something scarce on AVR. So on that platform, we opt to + * send the id and the report separately instead. */ +#ifdef ARDUINO_ARCH_SAMD + uint8_t p[64]; + p[0] = id; + memcpy(&p[1], data, len); + return USB_Send(pluggedEndpoint, p, len + 1); +#else + auto ret = USB_Send(pluggedEndpoint, &id, 1); + if (ret < 0) return ret; + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); + if (ret2 < 0) return ret2; + return ret + ret2; +#endif +} + +bool HID_::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 (request == HID_GET_IDLE) { + // TODO: Send8(idle); + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + // The USB Host tells us if we are in boot or report mode. + // This only works with a real boot compatible device. + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueH; + return true; + } + if (request == HID_SET_REPORT) { + uint16_t length = setup.wLength; + + if (length == sizeof(setReportData)) { + USB_RecvControl(&setReportData, length); + } else if (length == sizeof(setReportData.leds)) { + USB_RecvControl(&setReportData.leds, length); + setReportData.reportId = 0; + } + } + } + + return false; +} + +HID_::HID_() : PluggableUSBModule(1, 1, epType), + rootNode(NULL), descriptorSize(0), + protocol(HID_REPORT_PROTOCOL), idle(1) { + setReportData.reportId = 0; + setReportData.leds = 0; + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES + epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif + + PluggableUSB().plug(this); +} + +int HID_::begin() { + return 0; +} + +#endif /* if defined(USBCON) */ + +#endif /* ifndef KEYBOARDIOHID_BUILD_WITHOUT_HID */ diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HID.h b/src/kaleidoscope/driver/hid/keyboardio/usb/HID.h new file mode 100644 index 00000000..8788e201 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HID.h @@ -0,0 +1,133 @@ +/* + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted, provided that the + above copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR + BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + */ + +#ifndef HID_h +#define HID_h + +#include +#include +#include "HID-Settings.h" + +#if defined(USBCON) + +#define _USING_HID + +// HID 'Driver' +// ------------ +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + +// HID subclass HID1.11 Page 8 4.2 Subclass +#define HID_SUBCLASS_NONE 0 +#define HID_SUBCLASS_BOOT_INTERFACE 1 + +// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols +#define HID_PROTOCOL_NONE 0 +#define HID_PROTOCOL_KEYBOARD 1 +#define HID_PROTOCOL_MOUSE 2 + +// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request +// "protocol" variable is used for this purpose. +#define HID_BOOT_PROTOCOL 0 +#define HID_REPORT_PROTOCOL 1 + +// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 + +#pragma pack(push, 1) +typedef struct { + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t addr; + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescDescriptor; + +typedef struct { + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; +#pragma pack(pop) + +class HIDSubDescriptor { + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } + + const void* data; + const uint16_t length; +}; + +class HID_ : public PluggableUSBModule { + public: + + HID_(); + int begin(); + int SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDSubDescriptor* node); + uint8_t getLEDs() { + return setReportData.leds; + }; + + protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + uint8_t getShortName(char* name); + + int SendReport_(uint8_t id, const void* data, int len); + private: + EPTYPE_DESCRIPTOR_SIZE epType[1]; + + HIDSubDescriptor* rootNode; + uint16_t descriptorSize; + + uint8_t protocol; + uint8_t idle; + struct { + uint8_t reportId; + uint8_t leds; + } setReportData; +}; + +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +HID_& HID(); + +#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } + +#endif // USBCON + +#endif // HID_h diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HIDAliases.h b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDAliases.h new file mode 100644 index 00000000..5cf2eef7 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDAliases.h @@ -0,0 +1,33 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + +#include "HIDTables.h" + +#define HID_FIRST_KEY HID_KEYBOARD_NO_EVENT +#define HID_LAST_KEY HID_KEYPAD_HEXADECIMAL +#define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL +#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.cpp new file mode 100644 index 00000000..8f0ec1d9 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.cpp @@ -0,0 +1,27 @@ +/* +Copyright (c) 2015-2019 Keyboard.io, Inc + +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 "HIDReportObserver.h" + +HIDReportObserver::SendReportHook HIDReportObserver::send_report_hook_ = nullptr; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.h b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.h new file mode 100644 index 00000000..23de6991 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDReportObserver.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2015-2019 Keyboard.io, Inc + +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. +*/ + +#pragma once + +#include + +class HIDReportObserver { + public: + + typedef void(*SendReportHook)(uint8_t id, const void* data, + int len, int result); + + static void observeReport(uint8_t id, const void* data, + int len, int result) { + if (send_report_hook_) { + (*send_report_hook_)(id, data, len, result); + } + } + + static SendReportHook currentHook() { + return send_report_hook_; + } + + static SendReportHook resetHook(SendReportHook new_hook) { + auto previous_hook = send_report_hook_; + send_report_hook_ = new_hook; + return previous_hook; + } + + private: + + static SendReportHook send_report_hook_; +}; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/HIDTables.h b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDTables.h new file mode 100644 index 00000000..168c687e --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/HIDTables.h @@ -0,0 +1,798 @@ +/* +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + + +// These mappings were extracted and transcribed from +// https://www.usb.org/sites/default/files/hut1_2.pdf +// +// In most cases, I've preserved the "official" USB Implementers forum +// "Usage Name", though I've standardized some abbreviations and spacing +// that were inconsistent in the original specification. Non alpha-numeric +// characters in symbol names were converted into those characters' names. +// +// To match Arduino code style, all hid usage names are fully upper case. +// +// Not every HID usage listed in this file is currently supported by Arduino +// In particular, any System Control or Consumer Control entry that doesn't +// have a comment indicating that it's "HID type OSC" may require additional +// code in the Arduino core to work, although // some keycodes with usage +// type RTC (Re-Trigger Control) and OOC (On/Off Control) are also functional. +// +// Non-working usages are listed here in the interest of not having to manually +// convert more usage names each and every time our HID stack gets a little bit +// better. +// +// +// -- Jesse Vincent , September 2020 + + + +// ============================================================================== +// System Control USB HID keycodes +// [Section 4: Generic Desktop Page (0x01)] + +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_SYSTEM_POWER_DOWN 0x81 // OSC +#define HID_SYSTEM_SLEEP 0x82 // OSC +#define HID_SYSTEM_WAKE_UP 0x83 // OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // OSC +#define HID_SYSTEM_APP_MENU 0x86 // OSC +#define HID_SYSTEM_MENU_HELP 0x87 // OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // RTC +#define HID_SYSTEM_MENU_UP 0x8C // RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // OSC +#define HID_D_PAD_UP 0x90 // OOC +#define HID_D_PAD_DOWN 0x91 // OOC +#define HID_D_PAD_RIGHT 0x92 // OOC +#define HID_D_PAD_LEFT 0x93 // OOC +#define HID_INDEX_TRIGGER 0x94 // MC/DV +#define HID_PALM_TRIGGER 0x95 // MC/DV +#define HID_THUMBSTICK 0x96 // CP +#define HID_SYSTEM_FUNCTION_SHIFT 0x97 // MC +#define HID_SYSTEM_FUNCTION_SHIFT_LOCK 0x98 // OOC +#define HID_SYSTEM_FUNCTION_SHIFT_LOCK_INDICATOR 0x99 // DV +#define HID_DISMISS_NOTIFICATION 0x9A // OSC +#define HID_DO_NOT_DISTURB 0x9B // OOC +// Reserved 0x9C-9F +#define HID_SYSTEM_DOCK 0xA0 // OSC +#define HID_SYSTEM_UNDOCK 0xA1 // OSC +#define HID_SYSTEM_SETUP 0xA2 // OSC +#define HID_SYSTEM_BREAK 0xA3 // OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // OSC +#define HID_APPLICATION_BREAK 0xA5 // OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // OSC +// Reserved 0xA9-AF +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // OSC +// Reserved 0xB8-BF + + +// ============================================================================== +// Keyboard USB HID keycodes +// [Section 10: Keyboard/Keypad Page (0x07)] + +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_KEYBOARD_NO_EVENT 0x00 // Sel +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 // Sel +#define HID_KEYBOARD_POST_FAIL 0x02 // Sel +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 // Sel +#define HID_KEYBOARD_A_AND_A 0x04 // Sel +#define HID_KEYBOARD_B_AND_B 0x05 // Sel +#define HID_KEYBOARD_C_AND_C 0x06 // Sel +#define HID_KEYBOARD_D_AND_D 0x07 // Sel +#define HID_KEYBOARD_E_AND_E 0x08 // Sel +#define HID_KEYBOARD_F_AND_F 0x09 // Sel +#define HID_KEYBOARD_G_AND_G 0x0A // Sel +#define HID_KEYBOARD_H_AND_H 0x0B // Sel +#define HID_KEYBOARD_I_AND_I 0x0C // Sel +#define HID_KEYBOARD_J_AND_J 0x0D // Sel +#define HID_KEYBOARD_K_AND_K 0x0E // Sel +#define HID_KEYBOARD_L_AND_L 0x0F // Sel +#define HID_KEYBOARD_M_AND_M 0x10 // Sel +#define HID_KEYBOARD_N_AND_N 0x11 // Sel +#define HID_KEYBOARD_O_AND_O 0x12 // Sel +#define HID_KEYBOARD_P_AND_P 0x13 // Sel +#define HID_KEYBOARD_Q_AND_Q 0x14 // Sel +#define HID_KEYBOARD_R_AND_R 0x15 // Sel +#define HID_KEYBOARD_S_AND_S 0x16 // Sel +#define HID_KEYBOARD_T_AND_T 0x17 // Sel +#define HID_KEYBOARD_U_AND_U 0x18 // Sel +#define HID_KEYBOARD_V_AND_V 0x19 // Sel +#define HID_KEYBOARD_W_AND_W 0x1A // Sel +#define HID_KEYBOARD_X_AND_X 0x1B // Sel +#define HID_KEYBOARD_Y_AND_Y 0x1C // Sel +#define HID_KEYBOARD_Z_AND_Z 0x1D // Sel +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E // Sel +#define HID_KEYBOARD_2_AND_AT 0x1F // Sel +#define HID_KEYBOARD_3_AND_POUND 0x20 // Sel +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 // Sel +#define HID_KEYBOARD_5_AND_PERCENT 0x22 // Sel +#define HID_KEYBOARD_6_AND_CARAT 0x23 // Sel +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 // Sel +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 // Sel +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 // Sel +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 // Sel +#define HID_KEYBOARD_ENTER 0x28 // Sel +//#define HID_KEYBOARD_ENTER HID_KEYBOARD_ENTER_SLASH_RETURN +#define HID_KEYBOARD_ESCAPE 0x29 // Sel +#define HID_KEYBOARD_DELETE 0x2A // Sel +//#define HID_KEYBOARD_BACKSPACE HID_KEYBOARD_DELETE +#define HID_KEYBOARD_TAB 0x2B // Sel +#define HID_KEYBOARD_SPACEBAR 0x2C // Sel +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // Sel +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E // Sel +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F // Sel +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 // Sel +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 // Sel +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 // Sel +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 // Sel +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 // Sel +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 // Sel +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 // Sel +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 // Sel +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 // Sel +#define HID_KEYBOARD_CAPS_LOCK 0x39 // Sel +#define HID_KEYBOARD_F1 0x3A // Sel +#define HID_KEYBOARD_F2 0x3B // Sel +#define HID_KEYBOARD_F3 0x3C // Sel +#define HID_KEYBOARD_F4 0x3D // Sel +#define HID_KEYBOARD_F5 0x3E // Sel +#define HID_KEYBOARD_F6 0x3F // Sel +#define HID_KEYBOARD_F7 0x40 // Sel +#define HID_KEYBOARD_F8 0x41 // Sel +#define HID_KEYBOARD_F9 0x42 // Sel +#define HID_KEYBOARD_F10 0x43 // Sel +#define HID_KEYBOARD_F11 0x44 // Sel +#define HID_KEYBOARD_F12 0x45 // Sel +#define HID_KEYBOARD_PRINTSCREEN 0x46 // Sel +#define HID_KEYBOARD_SCROLL_LOCK 0x47 // Sel +#define HID_KEYBOARD_PAUSE 0x48 // Sel +#define HID_KEYBOARD_INSERT 0x49 // Sel +#define HID_KEYBOARD_HOME 0x4A // Sel +#define HID_KEYBOARD_PAGE_UP 0x4B // Sel +#define HID_KEYBOARD_DELETE_FORWARD 0x4C // Sel +#define HID_KEYBOARD_END 0x4D // Sel +#define HID_KEYBOARD_PAGE_DOWN 0x4E // Sel +#define HID_KEYBOARD_RIGHT_ARROW 0x4F // Sel +#define HID_KEYBOARD_LEFT_ARROW 0x50 // Sel +#define HID_KEYBOARD_DOWN_ARROW 0x51 // Sel +#define HID_KEYBOARD_UP_ARROW 0x52 // Sel +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 // Sel +#define HID_KEYPAD_DIVIDE 0x54 // Sel +#define HID_KEYPAD_MULTIPLY 0x55 // Sel +#define HID_KEYPAD_SUBTRACT 0x56 // Sel +#define HID_KEYPAD_ADD 0x57 // Sel +#define HID_KEYPAD_ENTER 0x58 // Sel +#define HID_KEYPAD_1_AND_END 0x59 // Sel +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A // Sel +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B // Sel +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C // Sel +#define HID_KEYPAD_5 0x5D // Sel +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E // Sel +#define HID_KEYPAD_7_AND_HOME 0x5F // Sel +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 // Sel +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 // Sel +#define HID_KEYPAD_0_AND_INSERT 0x62 // Sel +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 // Sel +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 // Sel +#define HID_KEYBOARD_APPLICATION 0x65 // Sel +#define HID_KEYBOARD_POWER 0x66 // Sel +#define HID_KEYPAD_EQUALS 0x67 // Sel +#define HID_KEYBOARD_F13 0x68 // Sel +#define HID_KEYBOARD_F14 0x69 // Sel +#define HID_KEYBOARD_F15 0x6A // Sel +#define HID_KEYBOARD_F16 0x6B // Sel +#define HID_KEYBOARD_F17 0x6C // Sel +#define HID_KEYBOARD_F18 0x6D // Sel +#define HID_KEYBOARD_F19 0x6E // Sel +#define HID_KEYBOARD_F20 0x6F // Sel +#define HID_KEYBOARD_F21 0x70 // Sel +#define HID_KEYBOARD_F22 0x71 // Sel +#define HID_KEYBOARD_F23 0x72 // Sel +#define HID_KEYBOARD_F24 0x73 // Sel +#define HID_KEYBOARD_EXECUTE 0x74 // Sel +#define HID_KEYBOARD_HELP 0x75 // Sel +#define HID_KEYBOARD_MENU 0x76 // Sel +#define HID_KEYBOARD_SELECT 0x77 // Sel +#define HID_KEYBOARD_STOP 0x78 // Sel +#define HID_KEYBOARD_AGAIN 0x79 // Sel +#define HID_KEYBOARD_UNDO 0x7A // Sel +#define HID_KEYBOARD_CUT 0x7B // Sel +#define HID_KEYBOARD_COPY 0x7C // Sel +#define HID_KEYBOARD_PASTE 0x7D // Sel +#define HID_KEYBOARD_FIND 0x7E // Sel +#define HID_KEYBOARD_MUTE 0x7F // Sel +#define HID_KEYBOARD_VOLUME_UP 0x80 // Sel +#define HID_KEYBOARD_VOLUME_DOWN 0x81 // Sel +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 // Sel +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 // Sel +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 // Sel +#define HID_KEYPAD_COMMA 0x85 // Sel +#define HID_KEYPAD_EQUAL_SIGN 0x86 // Sel +#define HID_KEYBOARD_INTERNATIONAL1 0x87 // Sel +#define HID_KEYBOARD_INTERNATIONAL2 0x88 // Sel +#define HID_KEYBOARD_INTERNATIONAL3 0x89 // Sel +#define HID_KEYBOARD_INTERNATIONAL4 0x8A // Sel +#define HID_KEYBOARD_INTERNATIONAL5 0x8B // Sel +#define HID_KEYBOARD_INTERNATIONAL6 0x8C // Sel +#define HID_KEYBOARD_INTERNATIONAL7 0x8D // Sel +#define HID_KEYBOARD_INTERNATIONAL8 0x8E // Sel +#define HID_KEYBOARD_INTERNATIONAL9 0x8F // Sel +#define HID_KEYBOARD_LANG1 0x90 // Sel +#define HID_KEYBOARD_LANG2 0x91 // Sel +#define HID_KEYBOARD_LANG3 0x92 // Sel +#define HID_KEYBOARD_LANG4 0x93 // Sel +#define HID_KEYBOARD_LANG5 0x94 // Sel +#define HID_KEYBOARD_LANG6 0x95 // Sel +#define HID_KEYBOARD_LANG7 0x96 // Sel +#define HID_KEYBOARD_LANG8 0x97 // Sel +#define HID_KEYBOARD_LANG9 0x98 // Sel +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 // Sel +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A // Sel +#define HID_KEYBOARD_CANCEL 0x9B // Sel +#define HID_KEYBOARD_CLEAR 0x9C // Sel +#define HID_KEYBOARD_PRIOR 0x9D // Sel +#define HID_KEYBOARD_RETURN 0x9E // Sel +#define HID_KEYBOARD_SEPARATOR 0x9F // Sel +#define HID_KEYBOARD_OUT 0xA0 // Sel +#define HID_KEYBOARD_OPER 0xA1 // Sel +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 // Sel +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 // Sel +#define HID_KEYBOARD_EXSEL 0xA4 // Sel +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 // Sel +#define HID_KEYPAD_000 0xB1 // Sel +#define HID_THOUSANDS_SEPARATOR 0xB2 // Sel +#define HID_DECIMAL_SEPARATOR 0xB3 // Sel +#define HID_CURRENCY_UNIT 0xB4 // Sel +#define HID_CURRENCY_SUBUNIT 0xB5 // Sel +#define HID_KEYPAD_LEFT_PAREN 0xB6 // Sel +#define HID_KEYPAD_RIGHT_PAREN 0xB7 // Sel +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 // Sel +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 // Sel +#define HID_KEYPAD_TAB 0xBA // Sel +#define HID_KEYPAD_BACKSPACE 0xBB // Sel +#define HID_KEYPAD_A 0xBC // Sel +#define HID_KEYPAD_B 0xBD // Sel +#define HID_KEYPAD_C 0xBE // Sel +#define HID_KEYPAD_D 0xBF // Sel +#define HID_KEYPAD_E 0xC0 // Sel +#define HID_KEYPAD_F 0xC1 // Sel +#define HID_KEYPAD_XOR 0xC2 // Sel +#define HID_KEYPAD_CARAT 0xC3 // Sel +#define HID_KEYPAD_PERCENT 0xC4 // Sel +#define HID_KEYPAD_LESS_THAN 0xC5 // Sel +#define HID_KEYPAD_GREATER_THAN 0xC6 // Sel +#define HID_KEYPAD_AMPERSAND 0xC7 // Sel +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 // Sel +#define HID_KEYPAD_PIPE 0xC9 // Sel +#define HID_KEYPAD_DOUBLEPIPE 0xCA // Sel +#define HID_KEYPAD_COLON 0xCB // Sel +#define HID_KEYPAD_POUND_SIGN 0xCC // Sel +#define HID_KEYPAD_SPACE 0xCD // Sel +#define HID_KEYPAD_AT_SIGN 0xCE // Sel +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF // Sel +#define HID_KEYPAD_MEMORY_STORE 0xD0 // Sel +#define HID_KEYPAD_MEMORY_RECALL 0xD1 // Sel +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 // Sel +#define HID_KEYPAD_MEMORY_ADD 0xD3 // Sel +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 // Sel +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 // Sel +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 // Sel +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 // Sel +#define HID_KEYPAD_CLEAR 0xD8 // Sel +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 // Sel +#define HID_KEYPAD_BINARY 0xDA // Sel +#define HID_KEYPAD_OCTAL 0xDB // Sel +#define HID_KEYPAD_DECIMAL 0xDC // Sel +#define HID_KEYPAD_HEXADECIMAL 0xDD // Sel +// Reserved 0xDE-DF +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 // DV +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 // DV +#define HID_KEYBOARD_LEFT_ALT 0xE2 // DV +#define HID_KEYBOARD_LEFT_GUI 0xE3 // DV +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 // DV +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 // DV +#define HID_KEYBOARD_RIGHT_ALT 0xE6 // DV +#define HID_KEYBOARD_RIGHT_GUI 0xE7 // DV +// Reserved 0xE8-FFFF + + +// ============================================================================== +// Consumer Control USB HID keycodes +// [Section 15: Consumer Page (0x0C)] + +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_CONSUMER_CONSUMER_CONTROL_CA 0x01 // CA +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // NAry +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // NAry +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // OSC +#define HID_CONSUMER_PLUS_100 0x21 // OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // OOC +#define HID_CONSUMER_RESET 0x31 // OSC +#define HID_CONSUMER_SLEEP 0x32 // OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // NAry +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // OOC +#define HID_CONSUMER_MENU_PICK 0x41 // OSC +#define HID_CONSUMER_MENU_UP 0x42 // OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // OSC +#define HID_CONSUMER_STILL 0x66 // OSC +#define HID_CONSUMER_PICTURE_IN_PICTURE_TOGGLE 0x67 // OSC +#define HID_CONSUMER_PICTURE_IN_PICTURE_SWAP 0x68 // OSC +#define HID_CONSUMER_RED_MENU_BUTTON 0x69 // MC +#define HID_CONSUMER_GREEN_MENU_BUTTON 0x6A // MC +#define HID_CONSUMER_BLUE_MENU_BUTTON 0x6B // MC +#define HID_CONSUMER_YELLOW_MENU_BUTTON 0x6C // MC +#define HID_CONSUMER_ASPECT 0x6D // OSC +#define HID_CONSUMER_3D_MODE_SELECT 0x6E // OSC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS_INCREMENT 0x6F // RTC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS_DECREMENT 0x70 // RTC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS 0x71 // LC +#define HID_CONSUMER_DISPLAY_BACKLIGHT_TOGGLE 0x72 // OOC +#define HID_CONSUMER_DISPLAY_SET_BRIGHTNESS_TO_MINIMUM 0x73 // OSC +#define HID_CONSUMER_DISPLAY_SET_BRIGHTNESS_TO_MAXIMUM 0x74 // OSC +#define HID_CONSUMER_DISPLAY_SET_AUTO_BRIGHTNESS 0x75 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_ENABLED 0x76 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_DISABLED 0x77 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_TOGGLE 0x78 // OOC +#define HID_CONSUMER_KEYBOARD_BRIGHTNESS_INCREMENT 0x79 // OSC +#define HID_CONSUMER_KEYBOARD_BRIGHTNESS_DECREMENT 0x7A // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_LEVEL 0x7B // OC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_OOC 0x7C // OOC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_MINIMUM 0x7D // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_MAXIMUM 0x7E // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_AUTO 0x7F // OOC +#define HID_CONSUMER_SELECTION 0x80 // NAry +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // OSC +#define HID_CONSUMER_MODE_STEP 0x82 // OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // OSC +#define HID_CONSUMER_CHANNEL 0x86 // LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // NAry +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // Sel +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // Sel +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // Sel +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // Sel +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // Sel +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // Sel +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // Sel +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // Sel +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // Sel +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // Sel +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // Sel +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // Sel +#define HID_CONSUMER_QUIT 0x94 // OSC +#define HID_CONSUMER_HELP 0x95 // OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // Sel +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // Sel +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // Sel +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // Sel +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // Sel +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // Sel +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // Sel +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // OSC +#define HID_CONSUMER_ONCE 0xA1 // OSC +#define HID_CONSUMER_DAILY 0xA2 // OSC +#define HID_CONSUMER_WEEKLY 0xA3 // OSC +#define HID_CONSUMER_MONTHLY 0xA4 // OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // OOC +#define HID_CONSUMER_PAUSE 0xB1 // OOC +#define HID_CONSUMER_RECORD 0xB2 // OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // OOC +#define HID_CONSUMER_REWIND 0xB4 // OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // OSC +#define HID_CONSUMER_STOP 0xB7 // OSC +#define HID_CONSUMER_EJECT 0xB8 // OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // NAry +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // OSC +#define HID_CONSUMER_TRACKING 0xBD // LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // RTC +#define HID_CONSUMER_MARK 0xC2 // OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // OSC +#define HID_CONSUMER_VOICE_COMMAND 0xCF // Sel +#define HID_CONSUMER_INVOKE_CAPTURE_INTERFACE 0xD0 // Sel +#define HID_CONSUMER_START_OR_STOP_GAME_RECORDING 0xD1 // Sel +#define HID_CONSUMER_HISTORICAL_GAME_CAPTURE 0xD2 // Sel +#define HID_CONSUMER_CAPTURE_GAME_SCREENSHOT 0xD3 // Sel +#define HID_CONSUMER_SHOW_OR_HIDE_RECORDING_INDICATOR 0xD4 // Sel +#define HID_CONSUMER_START_OR_STOP_MICROPHONE_CAPTURE 0xD5 // Sel +#define HID_CONSUMER_START_OR_STOP_CAMERA_CAPTURE 0xD6 // Sel +#define HID_CONSUMER_START_OR_STOP_GAME_BROADCAST 0xD7 // Sel +// Reserved 0xD8-DF +#define HID_CONSUMER_VOLUME 0xE0 // LC +#define HID_CONSUMER_BALANCE 0xE1 // LC +#define HID_CONSUMER_MUTE 0xE2 // OOC +#define HID_CONSUMER_BASS 0xE3 // LC +#define HID_CONSUMER_TREBLE 0xE4 // LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // OOC +#define HID_CONSUMER_MPX 0xE8 // OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // NAry +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // Sel +#define HID_CONSUMER_LONG_PLAY 0xF3 // Sel +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // Sel +#define HID_CONSUMER_SLOW 0xF5 // OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // OSC +#define HID_CONSUMER_PROXIMITY 0x109 // LC +#define HID_CONSUMER_MOTION 0x10A // OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB_CHANNEL 0x170 // LC +#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // OSC +#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // NAry +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // Sel +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // Sel +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // Sel +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // Sel +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // Sel +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // Sel +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // Sel +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // Sel +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // Sel +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // Sel +#define HID_CONSUMER_AL_NEWSREADER 0x18B // Sel +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // Sel +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // Sel +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // Sel +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // Sel +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // Sel +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // Sel +#define HID_CONSUMER_AL_CALCULATOR 0x192 // Sel +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // Sel +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // Sel +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // Sel +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // Sel +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // Sel +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // Sel +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // Sel +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // Sel +#define HID_CONSUMER_AL_LOGON 0x19B // Sel +#define HID_CONSUMER_AL_LOGOFF 0x19C // Sel +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // Sel +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // Sel +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // Sel +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // Sel +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // Sel +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // Sel +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // Sel +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // Sel +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // Sel +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // Sel +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // Sel +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // Sel +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // Sel +#define HID_CONSUMER_AL_DESKTOP 0x1AA // Sel +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // Sel +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // Sel +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // Sel +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // Sel +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // Sel +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // Sel +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // Sel +#define HID_CONSUMER_AL_ALARMS 0x1B2 // Sel +#define HID_CONSUMER_AL_CLOCK 0x1B3 // Sel +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // Sel +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // Sel +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // Sel +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // Sel +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // Sel +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // Sel +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // Sel +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // Sel +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH_TIPS_SLASH_TUTORIAL_BROWSER \ + 0x1BD // Sel +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // Sel +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // Sel +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // Sel +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // Sel +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // Sel +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // Sel +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // Sel +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // Sel +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // Sel +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // Sel +#define HID_CONSUMER_AL_MESSAGE_STATUS 0x1C8 // Sel +#define HID_CONSUMER_AL_CONTACT_SYNC 0x1C9 // Sel +#define HID_CONSUMER_AL_NAVIGATION 0x1CA // Sel +#define HID_CONSUMER_AL_CONTEXT_AWARE_DESKTOP_ASSISTANT 0x1CB // Sel +// Reserved 0x1CC-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // NAry +#define HID_CONSUMER_AC_NEW 0x201 // Sel +#define HID_CONSUMER_AC_OPEN 0x202 // Sel +#define HID_CONSUMER_AC_CLOSE 0x203 // Sel +#define HID_CONSUMER_AC_EXIT 0x204 // Sel +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // Sel +#define HID_CONSUMER_AC_MINIMIZE 0x206 // Sel +#define HID_CONSUMER_AC_SAVE 0x207 // Sel +#define HID_CONSUMER_AC_PRINT 0x208 // Sel +#define HID_CONSUMER_AC_PROPERTIES 0x209 // Sel +// Reserved 0x20A-219 +#define HID_CONSUMER_AC_UNDO 0x21A // Sel +#define HID_CONSUMER_AC_COPY 0x21B // Sel +#define HID_CONSUMER_AC_CUT 0x21C // Sel +#define HID_CONSUMER_AC_PASTE 0x21D // Sel +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // Sel +#define HID_CONSUMER_AC_FIND 0x21F // Sel +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // Sel +#define HID_CONSUMER_AC_SEARCH 0x221 // Sel +#define HID_CONSUMER_AC_GO_TO 0x222 // Sel +#define HID_CONSUMER_AC_HOME 0x223 // Sel +#define HID_CONSUMER_AC_BACK 0x224 // Sel +#define HID_CONSUMER_AC_FORWARD 0x225 // Sel +#define HID_CONSUMER_AC_STOP 0x226 // Sel +#define HID_CONSUMER_AC_REFRESH 0x227 // Sel +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // Sel +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // Sel +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // Sel +#define HID_CONSUMER_AC_HISTORY 0x22B // Sel +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // Sel +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // Sel +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // Sel +#define HID_CONSUMER_AC_ZOOM 0x22F // LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // Sel +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // Sel +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // Sel +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // Sel +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // Sel +#define HID_CONSUMER_AC_SCROLL 0x235 // LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // Sel +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // Sel +#define HID_CONSUMER_AC_PAN 0x238 // LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // Sel +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // Sel +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // Sel +#define HID_CONSUMER_AC_FORMAT 0x23C // Sel +#define HID_CONSUMER_AC_EDIT 0x23D // Sel +#define HID_CONSUMER_AC_BOLD 0x23E // Sel +#define HID_CONSUMER_AC_ITALICS 0x23F // Sel +#define HID_CONSUMER_AC_UNDERLINE 0x240 // Sel +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // Sel +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // Sel +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // Sel +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // Sel +#define HID_CONSUMER_AC_ROTATE 0x245 // Sel +#define HID_CONSUMER_AC_RESIZE 0x246 // Sel +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // Sel +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // Sel +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // Sel +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // Sel +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // Sel +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // Sel +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // Sel +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // Sel +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // Sel +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // Sel +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // Sel +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // Sel +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // Sel +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // Sel +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // Sel +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // Sel +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // Sel +#define HID_CONSUMER_AC_PROMOTE 0x25B // Sel +#define HID_CONSUMER_AC_DEMOTE 0x25C // Sel +#define HID_CONSUMER_AC_YES 0x25D // Sel +#define HID_CONSUMER_AC_NO 0x25E // Sel +#define HID_CONSUMER_AC_CANCEL 0x25F // Sel +#define HID_CONSUMER_AC_CATALOG 0x260 // Sel +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // Sel +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // Sel +#define HID_CONSUMER_AC_EXPAND 0x263 // Sel +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // Sel +#define HID_CONSUMER_AC_COLLAPSE 0x265 // Sel +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // Sel +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // Sel +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // Sel +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // Sel +#define HID_CONSUMER_AC_DELETE 0x26A // Sel +#define HID_CONSUMER_AC_LOCK 0x26B // Sel +#define HID_CONSUMER_AC_UNLOCK 0x26C // Sel +#define HID_CONSUMER_AC_PROTECT 0x26D // Sel +#define HID_CONSUMER_AC_UNPROTECT 0x26E // Sel +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // Sel +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // Sel +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // Sel +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // Sel +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // Sel +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // Sel +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // Sel +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // Sel +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // Sel +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // Sel +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // Sel +#define HID_CONSUMER_AC_SORT 0x27A // Sel +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // Sel +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // Sel +#define HID_CONSUMER_AC_FILTER 0x27D // Sel +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // Sel +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // Sel +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // Sel +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // Sel +#define HID_CONSUMER_AC_SET_ALARM 0x282 // Sel +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // Sel +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // Sel +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // Sel +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // Sel +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // Sel +#define HID_CONSUMER_AC_SEND_TO 0x288 // Sel +#define HID_CONSUMER_AC_REPLY 0x289 // Sel +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // Sel +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // Sel +#define HID_CONSUMER_AC_SEND 0x28C // Sel +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // Sel +#define HID_CONSUMER_AC_UPLOAD 0x28E // Sel +#define HID_CONSUMER_AC_DOWNLOAD 0x28F // Sel +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // Sel +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // Sel +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // Sel +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // Sel +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // Sel +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // Sel +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // Sel +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // Sel +#define HID_CONSUMER_AC_RENAME 0x298 // Sel +#define HID_CONSUMER_AC_MERGE 0x299 // Sel +#define HID_CONSUMER_AC_SPLIT 0x29A // Sel +#define HID_CONSUMER_AC_DISTRIBUTE_HORIZONTALLY 0x29B // Sel +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // Sel +#define HID_CONSUMER_AC_NEXT_KEYBOARD_LAYOUT_SELECT 0x29D // Sel +#define HID_CONSUMER_AC_NAVIGATION_GUIDANCE 0x29E // Sel +#define HID_CONSUMER_AC_DESKTOP_SHOW_ALL_WINDOWS 0x29F // Sel +#define HID_CONSUMER_AC_SOFT_KEY_LEFT 0x2A0 // Sel +#define HID_CONSUMER_AC_SOFT_KEY_RIGHT 0x2A1 // Sel +#define HID_CONSUMER_AC_DESKTOP_SHOW_ALL_APPLICATIONS 0x2A2 // Sel +// Reserved 0x2A3-2AF +#define HID_CONSUMER_AC_IDLE_KEEP_ALIVE 0x2B0 // Sel +// Reserved 0x2B1-2BF +#define HID_CONSUMER_EXTENDED_KEYBOARD_ATTRIBUTES_COLLECTION 0x2C0 // CL +#define HID_CONSUMER_KEYBOARD_FORM_FACTOR 0x2C1 // SV +#define HID_CONSUMER_KEYBOARD_KEY_TYPE 0x2C2 // SV +#define HID_CONSUMER_KEYBOARD_PHYSICAL_LAYOUT 0x2C3 // SV +#define HID_CONSUMER_VENDOR_SPECIFIC_KEYBOARD_PHYSICAL_LAYOUT 0x2C4 // SV +#define HID_CONSUMER_KEYBOARD_IETF_LANGUAGE_TAG_INDEX 0x2C5 // SV +#define HID_CONSUMER_IMPLEMENTED_KEYBOARD_INPUT_ASSIST_CONTROLS 0x2C6 // SV +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_PREVIOUS 0x2C7 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_NEXT 0x2C8 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_PREVIOUS_GROUP 0x2C9 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_NEXT_GROUP 0x2CA // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_ACCEPT 0x2CB // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_CANCEL 0x2CC // Sel +// Reserved 0x2CD-2CF +#define HID_CONSUMER_PRIVACY_SCREEN_TOGGLE 0x2D0 // OOC +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_DECREMENT 0x2D1 +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_INCREMENT 0x2D2 +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_MINIMUM 0x2D3 // OSC +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_MAXIMUM 0x2D4 // OSC +// Reserved 0x2D5-4FF +// HID_CONTACT_* (not included here) 0x500-514 +// Reserved 0x515-FFFF diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/KeyboardioHID.h b/src/kaleidoscope/driver/hid/keyboardio/usb/KeyboardioHID.h new file mode 100644 index 00000000..7f68e208 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/KeyboardioHID.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 + +// Software version +#define HID_PROJECT_VERSION 241 + +#if ARDUINO < 10607 +#error HID Project requires Arduino IDE 1.6.7 or greater. Please update your IDE. +#endif + +#if !defined(USBCON) +#error HID Project can only be used with an USB MCU. +#endif + + +#include "LEDs.h" + + +// Include all HID libraries (.a linkage required to work) properly +#include "MultiReport/AbsoluteMouse.h" +#include "MultiReport/Mouse.h" +#include "MultiReport/ConsumerControl.h" +#include "MultiReport/Gamepad.h" +#include "MultiReport/SystemControl.h" +#include "MultiReport/Keyboard.h" + +#include "SingleReport/SingleAbsoluteMouse.h" + +#include "BootKeyboard/BootKeyboard.h" diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/LEDs.h b/src/kaleidoscope/driver/hid/keyboardio/usb/LEDs.h new file mode 100644 index 00000000..8469664d --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/LEDs.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + +// Keyboard Leds +enum KeyboardLeds : uint8_t { + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), +}; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MouseButtons.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MouseButtons.h new file mode 100644 index 00000000..ac94137a --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MouseButtons.h @@ -0,0 +1,35 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. +*/ + +#pragma once + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.cpp new file mode 100644 index 00000000..437ef915 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.cpp @@ -0,0 +1,54 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "AbsoluteMouse.h" +#include "DescriptorPrimitives.h" + +static const uint8_t absolute_mouse_hid_descriptor_[] PROGMEM = { + /* Mouse absolute */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL + + D_END_COLLECTION /* End */ +}; + +AbsoluteMouse_::AbsoluteMouse_() { + static HIDSubDescriptor node(absolute_mouse_hid_descriptor_, + sizeof(absolute_mouse_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + + +void AbsoluteMouse_::sendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); +} + +AbsoluteMouse_ AbsoluteMouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.h new file mode 100644 index 00000000..8dabd085 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/AbsoluteMouse.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" +#include "../DeviceAPIs/AbsoluteMouseAPI.h" + +class AbsoluteMouse_ : public AbsoluteMouseAPI { + public: + AbsoluteMouse_(); + + protected: + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length); +}; + +extern AbsoluteMouse_ AbsoluteMouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.cpp new file mode 100644 index 00000000..0cb4c2f5 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.cpp @@ -0,0 +1,109 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "ConsumerControl.h" +#include "DescriptorPrimitives.h" + +static const uint8_t consumer_control_hid_descriptor_[] PROGMEM = { + /* Consumer Control (Sound/Media keys) */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ + D_END_COLLECTION /* end collection */ +}; + +ConsumerControl_::ConsumerControl_() { + static HIDSubDescriptor node(consumer_control_hid_descriptor_, + sizeof(consumer_control_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + +void ConsumerControl_::begin() { + // release all buttons + end(); +} + +void ConsumerControl_::end() { + memset(&report_, 0, sizeof(report_)); + sendReport(); +} + +void ConsumerControl_::write(uint16_t m) { + press(m); + release(m); +} + +void ConsumerControl_::press(uint16_t m) { + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (report_.keys[i] == 0x00) { + report_.keys[i] = m; + break; + } + } +} + +void ConsumerControl_::release(uint16_t m) { + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (report_.keys[i] == m) { + report_.keys[i] = 0x00; + // no break to delete multiple keys + } + } +} + +void ConsumerControl_::releaseAll() { + memset(&report_, 0, sizeof(report_)); +} + +void ConsumerControl_::sendReportUnchecked() { + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &report_, sizeof(report_)); +} + +void ConsumerControl_::sendReport() { + // If the last report is different than the current report, then we need to + // send a report. We guard sendReport like this so that calling code doesn't + // end up spamming the host with empty reports if sendReport is called in a + // tight loop. + + // if the previous report is the same, return early without a new report. + if (memcmp(&last_report_, &report_, sizeof(report_)) == 0) + return; + + sendReportUnchecked(); + memcpy(&last_report_, &report_, sizeof(report_)); +} + +ConsumerControl_ ConsumerControl; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.h new file mode 100644 index 00000000..ed3ac03f --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/ConsumerControl.h @@ -0,0 +1,65 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" + +typedef union { + // Every usable Consumer key possible, up to 4 keys presses possible + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_ConsumerControlReport_Data_t; + + +class ConsumerControl_ { + public: + ConsumerControl_(); + void begin(); + void end(); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(); + + // Sending is public in the base class for advanced users. + void sendReport(); + + protected: + HID_ConsumerControlReport_Data_t report_; + HID_ConsumerControlReport_Data_t last_report_; + + private: + void sendReportUnchecked(); +}; +extern ConsumerControl_ ConsumerControl; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.cpp new file mode 100644 index 00000000..7b0774c0 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.cpp @@ -0,0 +1,149 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "Gamepad.h" +#include "DescriptorPrimitives.h" + +static const uint8_t gamepad_hid_descriptor_[] PROGMEM = { + /* Gamepad with 32 buttons and 6 axis*/ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ + /* 2 Hat Switches */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ +}; + +Gamepad_::Gamepad_() { + static HIDSubDescriptor node(gamepad_hid_descriptor_, + sizeof(gamepad_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + +void Gamepad_::begin() { + // release all buttons + end(); +} + +void Gamepad_::end() { + memset(&report_, 0x00, sizeof(report_)); + sendReport(&report_, sizeof(report_)); +} + +void Gamepad_::write() { + sendReport(&report_, sizeof(report_)); +} + +void Gamepad_::press(uint8_t b) { + report_.buttons |= (uint32_t)1 << (b - 1); +} + +void Gamepad_::release(uint8_t b) { + report_.buttons &= ~((uint32_t)1 << (b - 1)); +} + +void Gamepad_::releaseAll() { + memset(&report_, 0x00, sizeof(report_)); +} + +void Gamepad_::buttons(uint32_t b) { + report_.buttons = b; +} + +void Gamepad_::xAxis(int16_t a) { + report_.xAxis = a; +} + +void Gamepad_::yAxis(int16_t a) { + report_.yAxis = a; +} + +void Gamepad_::zAxis(int8_t a) { + report_.zAxis = a; +} + +void Gamepad_::rxAxis(int16_t a) { + report_.rxAxis = a; +} + +void Gamepad_::ryAxis(int16_t a) { + report_.ryAxis = a; +} + +void Gamepad_::rzAxis(int8_t a) { + report_.rzAxis = a; +} + +void Gamepad_::dPad1(int8_t d) { + report_.dPad1 = d; +} + +void Gamepad_::dPad2(int8_t d) { + report_.dPad2 = d; +} + +void Gamepad_::sendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); +} + +Gamepad_ Gamepad; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.h new file mode 100644 index 00000000..c2892d1d --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Gamepad.h @@ -0,0 +1,125 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" + +// Dpad directions +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 + + +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint32_t buttons; + + struct { + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; +} HID_GamepadReport_Data_t; + +class Gamepad_ { + public: + Gamepad_(); + + void begin(); + void end(); + void write(); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(); + + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void zAxis(int8_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + void sendReport(void* data, int length); + protected: + HID_GamepadReport_Data_t report_; +}; +extern Gamepad_ Gamepad; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.cpp new file mode 100644 index 00000000..b776bc8a --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.cpp @@ -0,0 +1,278 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "Keyboard.h" +#include "DescriptorPrimitives.h" + +static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { + // NKRO Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + /* Key modifier byte */ + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x01, + D_USAGE_MAXIMUM, 0x08, + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + /* NKRO Keyboard */ + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + // Padding 4 bits, to skip NO_EVENT & 3 error states. + D_REPORT_SIZE, 0x04, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + D_USAGE_MAXIMUM, HID_LAST_KEY, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + // Padding (3 bits) to round up the report to byte boundary. + D_REPORT_SIZE, 0x03, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_END_COLLECTION, +}; + +Keyboard_::Keyboard_() { + static HIDSubDescriptor node(nkro_keyboard_hid_descriptor_, + sizeof(nkro_keyboard_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + +void Keyboard_::begin() { + // Force API to send a clean report. This is important for and HID bridge + // where the receiver stays on, while the sender is resetted. + releaseAll(); + sendReportUnchecked(); +} + + +void Keyboard_::end() { + releaseAll(); + sendReportUnchecked(); +} + +int Keyboard_::sendReportUnchecked() { + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, + &last_report_, sizeof(last_report_)); +} + +// Sending the current HID report to the host: +// +// Depending on the differences between the current and previous HID reports, we +// might need to send one or two extra reports to guarantee that the host will +// process the changes in the correct order. There are two important scenarios +// to consider: +// +// 1. If a non-modifier keycode toggles off in the same report as a modifier +// changes, the host might process the modifier change first. For example, if +// both `shift` and `4` toggle off in the same report (most likely from a +// `LSHIFT(Key_4)` key being released), and that key has been held long enough +// to trigger character repeat, we could end up with a plain `4` in the output +// at the end of the repeat: `$$$$4` instead of `$$$$$`. +// +// 2. If a non-modifier keycode toggles on in the same report as a modifier +// changes, the host might process the non-modifer first. For example, pressing +// and holding an `LSHIFT(Key_4)` key might result in `4$$$` rather than `$$$$`. +// +// Therefore, each call to `sendReport()` must send (up to) three reports to the +// host to guarantee the correct order of processing: +// +// 1. A report with toggled-off non-modifiers removed. +// 2. A report with changes to modifiers. +// 3. A report with toggled-on non-modifiers added. + +int Keyboard_::sendReport() { + // If the new HID report differs from the previous one both in active modifier + // keycodes and non-modifier keycodes, we will need to send at least one extra + // report. First, we compare the modifiers bytes of the two reports. + const uint8_t old_modifiers = last_report_.modifiers; + const uint8_t new_modifiers = report_.modifiers; + + const uint8_t changed_modifiers = old_modifiers ^ new_modifiers; + + if (changed_modifiers != 0) { + // There was at least one modifier change (toggled on or off), remove any + // non-modifiers from the stored previous report that toggled off in the new + // report, and send it to the host. + bool non_modifiers_toggled_off = false; + for (uint8_t i = 0; i < KEY_BYTES; ++i) { + byte released_keycodes = last_report_.keys[i] & ~(report_.keys[i]); + if (released_keycodes != 0) { + last_report_.keys[i] &= ~released_keycodes; + non_modifiers_toggled_off = true; + } + } + if (non_modifiers_toggled_off) { + sendReportUnchecked(); + } + // Next, update the modifiers byte of the stored previous report, and send + // it. + last_report_.modifiers = new_modifiers; + sendReportUnchecked(); + } + + // Finally, copy the new report to the previous one, and send it. + if (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)) != 0) { + memcpy(last_report_.keys, report_.keys, sizeof(report_.keys)); + return sendReportUnchecked(); + } + // A note on return values: Kaleidoscope doesn't actually check the return + // value of `sendReport()`, so this function could be changed to return + // void. It would be nice if we could do something to recover from an error + // here, but it's not at all clear what that should be. Also note that if the + // extra reports above return an error, there's not much we can do to try to + // recover. We could try to send the report again, but that would be likely to + // fail as well. + return -1; +} + +/* Returns true if the modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool Keyboard_::isModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if the modifer key passed in was being sent during the previous key report + * Returns false in all other cases + * */ +bool Keyboard_::wasModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(last_report_.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if *any* modifier will be sent during this key report + * Returns false in all other cases + * */ +bool Keyboard_::isAnyModifierActive() { + return report_.modifiers > 0; +} + +/* Returns true if *any* modifier was being sent during the previous key report + * Returns false in all other cases + * */ +bool Keyboard_::wasAnyModifierActive() { + return last_report_.modifiers > 0; +} + + +/* Returns true if the non-modifier key passed in will be sent during this key report + * Returns false in all other cases + * */ +bool Keyboard_::isKeyPressed(uint8_t k) { + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(report_.keys[k / 8] & bit); + } + return false; +} + +/* Returns true if the non-modifer key passed in was sent during the previous key report + * Returns false in all other cases + * */ +bool Keyboard_::wasKeyPressed(uint8_t k) { + + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(last_report_.keys[k / 8] & bit); + } + return false; +} + + +size_t Keyboard_::press(uint8_t k) { + // If the key is in the range of 'printable' keys + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + report_.keys[k / 8] |= bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + report_.modifiers |= (1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; +} + +size_t Keyboard_::release(uint8_t k) { + // If we're releasing a printable key + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (k % 8); + report_.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + report_.modifiers &= ~(1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; +} + +void Keyboard_::releaseAll() { + // Release all keys + memset(&report_.allkeys, 0x00, sizeof(report_.allkeys)); +} + +Keyboard_ Keyboard; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.h new file mode 100644 index 00000000..799b1fd8 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Keyboard.h @@ -0,0 +1,76 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" + +#include "HIDTables.h" +#include "HIDAliases.h" + +#define KEY_BYTES 28 + +typedef union { + // Modifiers + keymap + struct { + uint8_t modifiers; + uint8_t keys[KEY_BYTES ]; + }; + uint8_t allkeys[1 + KEY_BYTES]; +} HID_KeyboardReport_Data_t; + + +class Keyboard_ { + public: + Keyboard_(); + void begin(); + void end(); + + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(); + int sendReport(); + + bool isKeyPressed(uint8_t k); + bool wasKeyPressed(uint8_t k); + bool isModifierActive(uint8_t k); + bool wasModifierActive(uint8_t k); + bool isAnyModifierActive(); + bool wasAnyModifierActive(); + + uint8_t getLEDs() { + return HID().getLEDs(); + }; + + private: + HID_KeyboardReport_Data_t report_; + HID_KeyboardReport_Data_t last_report_; + + int sendReportUnchecked(); +}; +extern Keyboard_ Keyboard; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.cpp new file mode 100644 index 00000000..dd3cec6e --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.cpp @@ -0,0 +1,143 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "Mouse.h" +#include "DescriptorPrimitives.h" + +static const uint8_t mouse_hid_descriptor_[] PROGMEM = { + /* Mouse relative */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) + + /* 8 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), // INPUT (Data,Var,Abs) + + /* X, Y, Wheel */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + + /* Horizontal wheel */ + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + + /* End */ + D_END_COLLECTION // END_COLLECTION +}; + +Mouse_::Mouse_() { + static HIDSubDescriptor node(mouse_hid_descriptor_, + sizeof(mouse_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + +void Mouse_::begin() { + end(); +} + +void Mouse_::end() { + releaseAll(); + sendReport(); +} + +void Mouse_::click(uint8_t b) { + // If one or more of the buttons to be clicked was already pressed, we need to + // send a report to release it first, to guarantee that this will be a "click" + // and not merely a release. + if (report_.buttons & b) { + release(b); + sendReport(); + } + // Next, send a report with the button(s) pressed: + press(b); + sendReport(); + // Finally, send the report with the button(s) released: + release(b); + sendReport(); +} + +void Mouse_::move(int8_t x, int8_t y, int8_t v_wheel, int8_t h_wheel) { + report_.xAxis = x; + report_.yAxis = y; + report_.vWheel = v_wheel; + report_.hWheel = h_wheel; +} + +void Mouse_::releaseAll() { + memset(&report_, 0, sizeof(report_)); +} + +void Mouse_::press(uint8_t b) { + report_.buttons |= b; +} + +void Mouse_::release(uint8_t b) { + report_.buttons &= ~b; +} + +bool Mouse_::isPressed(uint8_t b) { + if ((b & report_.buttons) > 0) + return true; + return false; +} + +void Mouse_::sendReportUnchecked() { + HID().SendReport(HID_REPORTID_MOUSE, &report_, sizeof(report_)); +} + +void Mouse_::sendReport() { + // If the button state has not changed, and neither the cursor nor the wheel + // is being told to move, there is no need to send a report. This check + // prevents us from sending lots of no-op reports if the caller is in a loop + // and not checking or buggy. + if (report_.buttons != prev_report_buttons_ || + report_.xAxis != 0 || report_.yAxis != 0 || + report_.vWheel != 0 || report_.hWheel != 0) { + sendReportUnchecked(); + prev_report_buttons_ = report_.buttons; + } +} + +Mouse_ Mouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.h new file mode 100644 index 00000000..469be1fd --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/Mouse.h @@ -0,0 +1,80 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" +#include "../MouseButtons.h" + +typedef union { + // Mouse report: 8 buttons, position, wheel + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t vWheel; + int8_t hWheel; + }; +} HID_MouseReport_Data_t; + + +class Mouse_ { + public: + Mouse_(); + void begin(); + void end(); + // Note: the following `click()` method is unlike the `move()`, `press()`, and + // `release()` methods, in that it doesn't merely modify the pending report, + // but also calls `sendReport()` at least twice. + void click(uint8_t b = MOUSE_LEFT); + void move(int8_t x, int8_t y, int8_t v_wheel = 0, int8_t h_wheel = 0); + void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default + + /** getReport returns the current report. + * + * The current report is the one to be send next time sendReport() is called. + * + * @returns A copy of the report. + */ + const HID_MouseReport_Data_t getReport() { + return report_; + } + void sendReport(); + + void releaseAll(); + + protected: + HID_MouseReport_Data_t report_; + uint8_t prev_report_buttons_ = 0; + + private: + void sendReportUnchecked(); +}; +extern Mouse_ Mouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.cpp new file mode 100644 index 00000000..c8cb7cf8 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.cpp @@ -0,0 +1,97 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "SystemControl.h" +#include "DescriptorPrimitives.h" + +static const uint8_t system_control_hid_descriptor_[] PROGMEM = { + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ +}; + +SystemControl_::SystemControl_() { + static HIDSubDescriptor node(system_control_hid_descriptor_, + sizeof(system_control_hid_descriptor_)); + HID().AppendDescriptor(&node); +} + +void SystemControl_::begin() { + // release all buttons + end(); +} + +void SystemControl_::end() { + uint8_t report = 0x00; + sendReport(&report, sizeof(report)); +} + +void SystemControl_::write(uint8_t s) { + press(s); + release(); +} + +void SystemControl_::release() { + begin(); +} + +void SystemControl_::releaseAll() { + begin(); +} + +void SystemControl_::press(uint8_t s) { + if (s == HID_SYSTEM_WAKE_UP) { +#ifdef __AVR__ + USBDevice.wakeupHost(); +#endif +#ifdef ARDUINO_ARCH_SAMD + // This is USBDevice_SAMD21G18x.wakeupHost(). But we can't include that + // header, because it redefines a few symbols, and causes linking + // errors. So we simply reimplement the same thing here. + USB->DEVICE.CTRLB.bit.UPRSM = 1; +#endif + } else { + sendReport(&s, sizeof(s)); + } +} + + +void SystemControl_::sendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); +} + +SystemControl_ SystemControl; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.h b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.h new file mode 100644 index 00000000..1b6fd1b1 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/MultiReport/SystemControl.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" +#include "HIDTables.h" + +typedef union { + // Every usable system control key possible + uint8_t key; +} HID_SystemControlReport_Data_t; + + +class SystemControl_ { + public: + void begin(); + void end(); + void write(uint8_t s); + void press(uint8_t s); + void release(); + void releaseAll(); + void sendReport(void* data, int length); + + SystemControl_(); + + protected: +}; + + + +extern SystemControl_ SystemControl; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.cpp new file mode 100644 index 00000000..05f5176c --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.cpp @@ -0,0 +1,131 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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 "SingleAbsoluteMouse.h" +#include "HIDReportObserver.h" +#include "HID-Settings.h" + +static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL + D_END_COLLECTION /* End */ +}; + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES +static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = 6; +#else +static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = USB_EP_SIZE; +#endif + + + +SingleAbsoluteMouse_::SingleAbsoluteMouse_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES + epType[0] = EP_TYPE_INTERRUPT_IN(SINGLE_ABSOLUTEMOUSE_EP_SIZE); +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif + + PluggableUSB().plug(this); +} + +int SingleAbsoluteMouse_::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(_hidSingleReportDescriptorAbsoluteMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, SINGLE_ABSOLUTEMOUSE_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleAbsoluteMouse_::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; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); +} + +bool SingleAbsoluteMouse_::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) { + } + } + + return false; +} + +void SingleAbsoluteMouse_::sendReport(void* data, int length) { + auto result = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); +} + +SingleAbsoluteMouse_ SingleAbsoluteMouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.h b/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.h new file mode 100644 index 00000000..7a59403e --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/SingleReport/SingleAbsoluteMouse.h @@ -0,0 +1,53 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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.h" +#include "HID-Settings.h" +#include "../DeviceAPIs/AbsoluteMouseAPI.h" + + +class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI { + public: + SingleAbsoluteMouse_(); + uint8_t getLeds(); + uint8_t getProtocol(); + + protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + EPTYPE_DESCRIPTOR_SIZE epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void sendReport(void* data, int length) override; +}; +extern SingleAbsoluteMouse_ SingleAbsoluteMouse; diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/arch/avr.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/avr.cpp new file mode 100644 index 00000000..9c0fcf2a --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/avr.cpp @@ -0,0 +1,8 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_AVR + +void USB_PackMessages(bool pack) { +} + +#endif diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/arch/gd32.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/gd32.cpp new file mode 100644 index 00000000..24599172 --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/gd32.cpp @@ -0,0 +1,8 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_GD32 + +void USB_PackMessages(bool pack) { +} + +#endif diff --git a/src/kaleidoscope/driver/hid/keyboardio/usb/arch/samd.cpp b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/samd.cpp new file mode 100644 index 00000000..6d79ad1b --- /dev/null +++ b/src/kaleidoscope/driver/hid/keyboardio/usb/arch/samd.cpp @@ -0,0 +1,17 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_SAMD + +int USB_SendControl(void* b, unsigned char c) { + USBDevice.sendControl(b, c); +} + +int USB_SendControl(uint8_t a, const void* b, uint8_t c) { + USBDevice.sendControl(b, c); +} + +void USB_PackMessages(bool pack) { + USBDevice.packMessages(pack); +} + +#endif