From b8bdc23208b6bbae788f5f90ed76b53fbde30586 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 23:09:56 +0100 Subject: [PATCH 01/19] bumped version number to 2.5 --- Readme.md | 4 ++- library.properties | 2 +- package_NicoHood_HID_index.json | 45 --------------------------------- src/HID-Project.h | 2 +- 4 files changed, 5 insertions(+), 48 deletions(-) delete mode 100644 package_NicoHood_HID_index.json diff --git a/Readme.md b/Readme.md index 84ac634..da5c97d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -Arduino HID Project 2.4 +Arduino HID Project 2.5 ======================= ![Header Picture](header.jpg) @@ -49,6 +49,8 @@ www.nicohood.de Version History =============== ``` +2.5 Release (xx.xx.2015) + 2.4 Release (06.11.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID * Improved Pluggable HID (see Arduyuino changelog for my improvements) diff --git a/library.properties b/library.properties index d984e65..7c0c59e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=HID-Project -version=2.4 +version=2.5 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino diff --git a/package_NicoHood_HID_index.json b/package_NicoHood_HID_index.json deleted file mode 100644 index d172297..0000000 --- a/package_NicoHood_HID_index.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "packages": [ - { - "name": "HID", - "maintainer": "NicoHood", - "websiteURL": "https://github.com/NicoHood/HID", - "email": "", - "help": { - "online": "" - }, - "platforms": [ - { - "name": "HID Project", - "architecture": "avr", - "version": "2.2", - "category": "HID", - "help": { - "online": "" - }, - "url": "https://github.com/NicoHood/HID/releases/download/2.2/2.2-boards_manager.zip", - "archiveFileName": "2.2-boards_manager.zip", - "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9", - "size": "351303", - "boards": [ - {"name": "Arduino Leonardo"}, - {"name": "Arduino Micro"} - ], - "toolsDependencies": [ - { - "packager": "arduino", - "name": "avr-gcc", - "version": "4.8.1-arduino5" - }, - { - "packager": "arduino", - "name": "avrdude", - "version": "6.0.1-arduino5" - } - ] - } - ], - "tools": [] - } - ] -} diff --git a/src/HID-Project.h b/src/HID-Project.h index 1e7414b..ff592d3 100644 --- a/src/HID-Project.h +++ b/src/HID-Project.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once // Software version -#define HID_PROJECT_VERSION 240 +#define HID_PROJECT_VERSION 250 // TODO remove https://github.com/arduino/arduino-builder/issues/33 #include From 186c2c432c2ba896e921f1ad4ff436a6466560b3 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 10:54:50 +0100 Subject: [PATCH 02/19] Added sequence ID (aka num) to RawHID --- examples/RawHID/RawHID.ino | 2 +- src/SingleReport/RawHID.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/RawHID/RawHID.ino b/examples/RawHID/RawHID.ino index 04ff209..24677ce 100644 --- a/examples/RawHID/RawHID.ino +++ b/examples/RawHID/RawHID.ino @@ -82,7 +82,7 @@ void loop() { } } -void RawHIDEvent(void) { +void RawHIDEvent(uint8_t num) { // This event is called via interrupt. // Do not use print inside, or other long function calls! // If you not use this event function, diff --git a/src/SingleReport/RawHID.cpp b/src/SingleReport/RawHID.cpp index 3cafe96..2f81830 100644 --- a/src/SingleReport/RawHID.cpp +++ b/src/SingleReport/RawHID.cpp @@ -48,8 +48,8 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { }; // Weak implementation of the Event function -void RawHIDEvent(void) __attribute__ ((weak)); -void RawHIDEvent(void){ +void RawHIDEvent(uint8_t num) __attribute__ ((weak)); +void RawHIDEvent(uint8_t num){ // Empty } @@ -122,6 +122,7 @@ bool RawHID_::setup(USBSetup& setup) { // Get the data length information and the corresponding bytes int length = setup.wLength; + uint8_t num = 0; while(length) { // Dont receive more than the USB EP has to offer @@ -143,7 +144,7 @@ bool RawHID_::setup(USBSetup& setup) // Write data to fit to the end (not the beginning) of the array USB_RecvControl(data + (sizeof(data) - recvLength), recvLength); dataLength = recvLength; - RawHIDEvent(); + RawHIDEvent(num++); } // Do not read the data, flag an error to the USB Host // TODO always return no error, even if data was discarded? -> use break then From febc714df5212b5ba0daa12ddd48e7ac3ed46c9c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 11:09:51 +0100 Subject: [PATCH 03/19] Improved library.properties --- library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index 7c0c59e..1bfd8b4 100644 --- a/library.properties +++ b/library.properties @@ -3,8 +3,8 @@ version=2.5 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino -paragraph=Includes Consumer, System and Gamepad. Also compatible with Arduino Uno/Mega via HoodLoader2. -category=Device Control +paragraph=Includes BootKeyboard/Mouse, Consumer, System, Gamepad, RawHID and more features. Also compatible with Arduino Uno/Mega via HoodLoader2. +category=Communication url=https://github.com/NicoHood/HID -architectures=* +architectures=avr dot_a_linkage=true From a8c292a7bd08b30a6d26183ee28ca73b53c0363a Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:32:02 +0100 Subject: [PATCH 04/19] Added Feature Report function to BootKeyboard This may be added to other HID Devices as well, but Keyboard makes the most sense. --- src/SingleReport/BootKeyboard.cpp | 38 +++++++++++++++++++++++++++---- src/SingleReport/BootKeyboard.h | 25 ++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/SingleReport/BootKeyboard.cpp b/src/SingleReport/BootKeyboard.cpp index debadb3..8d63c3c 100644 --- a/src/SingleReport/BootKeyboard.cpp +++ b/src/SingleReport/BootKeyboard.cpp @@ -120,10 +120,12 @@ bool BootKeyboard_::setup(USBSetup& setup) return true; } if (request == HID_GET_PROTOCOL) { + // TODO improve UEDATX = protocol; return true; } if (request == HID_GET_IDLE) { + // TODO improve UEDATX = idle; return true; } @@ -141,10 +143,38 @@ bool BootKeyboard_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - // Check if data has the correct length - auto length = setup.wLength; - if(length == sizeof(leds)){ - USB_RecvControl(&leds, length); + // Check if data has the correct length afterwards + int length = setup.wLength; + + // Feature (set feature report) + if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; + } + } + + // Output (set led states) + else 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(_keyReport)){ + USB_RecvControl(&_keyReport, length); + return true; + } } } } diff --git a/src/SingleReport/BootKeyboard.h b/src/SingleReport/BootKeyboard.h index 4d83e72..221272d 100644 --- a/src/SingleReport/BootKeyboard.h +++ b/src/SingleReport/BootKeyboard.h @@ -38,6 +38,28 @@ public: uint8_t getLeds(void); uint8_t getProtocol(void); void wakeupHost(void); + + void setFeatureReport(void* report, int length){ + if(length > 0){ + featureReport = (uint8_t*)report; + featureLength = length; + } + } + + int availableFeatureReport(void){ + if(featureLength < 0){ + return featureLength & ~0x8000; + } + return 0; + } + + void enableFeatureReport(void){ + featureLength &= ~0x8000; + } + + void disableFeatureReport(void){ + featureLength |= 0x8000; + } protected: // Implementation of the PUSBListNode @@ -51,6 +73,9 @@ protected: uint8_t leds; + uint8_t* featureReport; + int featureLength; + virtual int send(void) override; }; extern BootKeyboard_ BootKeyboard; From 6a93f83c467baed8a86e4844335de2670f865913 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:35:23 +0100 Subject: [PATCH 05/19] Updated Keyboard keywords.txt --- keywords.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/keywords.txt b/keywords.txt index a6e5bf0..e5ce279 100644 --- a/keywords.txt +++ b/keywords.txt @@ -22,13 +22,10 @@ moveTo KEYWORD2 isPressed KEYWORD2 getLeds KEYWORD2 -pressKeycode KEYWORD2 -releaseKeycode KEYWORD2 -writeKeycode KEYWORD2 -addKeyToReport KEYWORD2 -addKeycodeToReport KEYWORD2 -removeKeyFromReport KEYWORD2 -removeKeycodeFromReport KEYWORD2 +setFeatureReport KEYWORD2 +availableFeatureReport KEYWORD2 +enableFeatureReport KEYWORD2 +disableFeatureReport KEYWORD2 write_unicode KEYWORD2 set_modifier KEYWORD2 From 0487754e109a9f45ad671927544f1861e6dffb07 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:46:58 +0100 Subject: [PATCH 06/19] Added Feature Report example + disabled by default --- .../KeyboardFeatureReport.ino | 80 +++++++++++++++++++ src/SingleReport/BootKeyboard.h | 3 + 2 files changed, 83 insertions(+) create mode 100644 examples/KeyboardFeatureReport/KeyboardFeatureReport.ino diff --git a/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino new file mode 100644 index 0000000..f7148ea --- /dev/null +++ b/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino @@ -0,0 +1,80 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + KeyboardFeatureReport example + + Shows how to use BootKeyboard with a modified Hyperion Lightpack device. + Might only work under linux. + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/RawHID-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; + + +// FastLED +#include "FastLED.h" + +#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN +#define COLOR_ORDER RGB +#define CHIPSET WS2801 // WS2811, LPD8806, etc +#define NUM_LEDS 25 + +#define BRIGHTNESS 255 // Reduce power consumption +#define LED_DITHER 255 // Try 0 to disable flickering +#define CORRECTION TypicalLEDStrip + +CRGB leds[NUM_LEDS]; // Define the array of leds + +void setup() { + // FastLED setup + FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); + FastLED.setBrightness(BRIGHTNESS); + FastLED.setDither(LED_DITHER); + + // Startup animation + fill_solid(leds, NUM_LEDS, CRGB::Red); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Green); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Blue); + FastLED.show(); + delay(500); + FastLED.clear(); + FastLED.show(); + + pinMode(pinLed, OUTPUT); + + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); + + // Let the feature report data directly point at the led array + BootKeyboard.setFeatureReport(leds, sizeof(leds)); + BootKeyboard.enableFeatureReport(); +} + +void loop() { + // Check if there is new feature request data from the keyboard + if (BootKeyboard.availableFeatureReport()) + { + digitalWrite(pinLed, HIGH); + + // Update leds, do not update in the loop, to avoid corrupted data. + // For example if you write (0, 0, 0) and the interrupt + // changes the data to (255, 255, 255) you might get (0, 255, 255). + // Using a duplicated led array in cli() context would also work. + FastLED.show(); + + // Release data to let the USB interrupt overwrite it again + BootKeyboard.enableFeatureReport(); + + digitalWrite(pinLed, LOW); + } +} diff --git a/src/SingleReport/BootKeyboard.h b/src/SingleReport/BootKeyboard.h index 221272d..d5c9ff0 100644 --- a/src/SingleReport/BootKeyboard.h +++ b/src/SingleReport/BootKeyboard.h @@ -43,6 +43,9 @@ public: if(length > 0){ featureReport = (uint8_t*)report; featureLength = length; + + // Disable feature report by default + disableFeatureReport(); } } From eed1098a218496051973968712af2d0921e69c1a Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 00:13:42 +0100 Subject: [PATCH 07/19] Added featureReport data to constructor --- src/SingleReport/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SingleReport/BootKeyboard.cpp b/src/SingleReport/BootKeyboard.cpp index 8d63c3c..c132503 100644 --- a/src/SingleReport/BootKeyboard.cpp +++ b/src/SingleReport/BootKeyboard.cpp @@ -71,7 +71,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); From 626be8413719a94937a95e4d52ceabf87ffb6cff Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 19:09:23 +0100 Subject: [PATCH 08/19] Fixed RawHID linux send function. --- extras/rawhid/hid_LINUX.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/rawhid/hid_LINUX.c b/extras/rawhid/hid_LINUX.c index 8e98113..799797e 100644 --- a/extras/rawhid/hid_LINUX.c +++ b/extras/rawhid/hid_LINUX.c @@ -144,7 +144,7 @@ int rawhid_send(int num, void *buf, int len, int timeout) if (hid->ep_out) { return usb_interrupt_write(hid->usb, hid->ep_out, buf, len, timeout); } else { - return usb_control_msg(hid->usb, 0x21, 9, 0, hid->iface, buf, len, timeout); + return usb_control_msg(hid->usb, 0x21, 9, 0x0200, hid->iface, buf, len, timeout); } } From c197491272e7da56d659b8342c9c21602e7e4bfb Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:05:53 +0100 Subject: [PATCH 09/19] Updated RawHID with new, more intuitive API --- examples/RawHID/RawHID.ino | 70 +++++++++---------------------- src/SingleReport/RawHID.cpp | 69 +++++++++++------------------- src/SingleReport/RawHID.h | 83 ++++++++++++++++++++++++------------- 3 files changed, 98 insertions(+), 124 deletions(-) diff --git a/examples/RawHID/RawHID.ino b/examples/RawHID/RawHID.ino index 24677ce..0ab8c45 100644 --- a/examples/RawHID/RawHID.ino +++ b/examples/RawHID/RawHID.ino @@ -7,11 +7,7 @@ Shows how to send bytes via RawHID. Press a button to send some example values. - Every received data is mirrored to the host. - The use of the RawHIDEvent() function is shown too. - - This sketch only tries to show the possiblities - and is not perfect.You might want to use RawHID differently. + Every received data is mirrored to the host via Serial. See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API @@ -22,14 +18,22 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; -uint8_t data[255]; -volatile size_t len = 0; +// Buffer to hold RawHID data. +// If host tries to send more data than this, +// it will respond with an error. +// If the data is not read until the host sends the next data +// it will also respond with an error and the data will be lost. +uint8_t rawhidData[255]; void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // No begin/end function required for RawHID + Serial.begin(115200); + + // Set the RawHID OUT report array. + // Feature reports are also (parallel) possible, see the other example for this. + RawHID.begin(rawhidData, sizeof(rawhidData)); } void loop() { @@ -50,54 +54,18 @@ void loop() { } - // This will miss longer RawHID data transmissions - // and return an error to the host if data was missed. - // Only use this for non changing/less important data. - // Or you can use this if the event aborted on a full buffer. - // Please note, that all data after this full buffer is missed anyways. + // Check if there is new data from the RawHID device auto bytesAvailable = RawHID.available(); - while (bytesAvailable--) { - if (len < sizeof(data)) { - data[len++] = RawHID.read(); - } - } - - // Process data from the host - if (len) { + if (bytesAvailable) + { digitalWrite(pinLed, HIGH); - // Disable interrupts while processing the data - uint8_t oldSREG = SREG; - cli(); + // Mirror data via Serial + while (bytesAvailable--) { + Serial.println(RawHID.read()); + } - // Mirror the incoming data from the host back - RawHID.write(data, len); - len = 0; - - SREG = oldSREG; - - // Simple debounce for led - delay(300); digitalWrite(pinLed, LOW); } } -void RawHIDEvent(uint8_t num) { - // This event is called via interrupt. - // Do not use print inside, or other long function calls! - // If you not use this event function, - // you might miss some data in the loop, - // if the host sends too fast or too much data at once. - - auto bytesAvailable = RawHID.available(); - while (bytesAvailable--) { - // Only add data to the buffer if its not full. - // If it is, no more event will occur - // and the data should be discarded - // or read (as shown) in the loop above. - if (len < sizeof(data)) { - data[len++] = RawHID.read(); - } - } -} - diff --git a/src/SingleReport/RawHID.cpp b/src/SingleReport/RawHID.cpp index 2f81830..d4aa4d1 100644 --- a/src/SingleReport/RawHID.cpp +++ b/src/SingleReport/RawHID.cpp @@ -47,13 +47,7 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { 0xC0 /* end collection */ }; -// Weak implementation of the Event function -void RawHIDEvent(uint8_t num) __attribute__ ((weak)); -void RawHIDEvent(uint8_t num){ - // Empty -} - -RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0) +RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0), dataAvailable(0), featureReport(NULL), featureLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -120,51 +114,36 @@ bool RawHID_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - // Get the data length information and the corresponding bytes + // Check if data has the correct length afterwards int length = setup.wLength; - uint8_t num = 0; - while(length) - { - // Dont receive more than the USB EP has to offer - // TODO use fixed 64 because control EP always have 64 bytes even on 16 u2. Test! - auto recvLength = length; - if(recvLength > USB_EP_SIZE){ - recvLength = USB_EP_SIZE; - } - if(recvLength > int(sizeof(data))){ - recvLength = int(sizeof(data)); - } - length -= recvLength; - - // Only receive data if the last one was read fully. - // Discard data if it wasnt read yet. - // To not miss any data you can use the (weak) event function. - if(!dataLength) - { - // Write data to fit to the end (not the beginning) of the array - USB_RecvControl(data + (sizeof(data) - recvLength), recvLength); - dataLength = recvLength; - RawHIDEvent(num++); - } - // Do not read the data, flag an error to the USB Host - // TODO always return no error, even if data was discarded? -> use break then - else{ - return false; + + // Feature (set feature report) + if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; + } + } + + // Output (set out report) + else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT){ + if(!dataAvailable && length <= dataLength){ + // Write data to fit to the end (not the beginning) of the array + USB_RecvControl(data + dataLength - length, length); + dataAvailable = length; + return true; } } - - // Flag no error - // TODO this is required to get hyperion working - // however this blocks the CDC serial!? - return true; } } return false; } -void RawHID_::SendReport(void* data, int length){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - RawHID_ RawHID; diff --git a/src/SingleReport/RawHID.h b/src/SingleReport/RawHID.h index 5f2249c..9ccc43e 100644 --- a/src/SingleReport/RawHID.h +++ b/src/SingleReport/RawHID.h @@ -73,32 +73,73 @@ class RawHID_ : public PluggableUSBModule, public Stream public: RawHID_(void); - void begin(void){ - // empty + void setFeatureReport(void* report, int length){ + if(length > 0){ + featureReport = (uint8_t*)report; + featureLength = length; + + // Disable feature report by default + disableFeatureReport(); + } + } + + int availableFeatureReport(void){ + if(featureLength < 0){ + return featureLength & ~0x8000; + } + return 0; + } + + void enableFeatureReport(void){ + featureLength &= ~0x8000; + } + + void disableFeatureReport(void){ + featureLength |= 0x8000; + } + + void begin(void* report, int length){ + if(length > 0){ + data = (uint8_t*)report; + dataLength = length; + dataAvailable = 0; + } } void end(void){ - // empty + disable(); + dataLength = 0; + } + + void enable(void){ + dataAvailable = 0; + } + + void disable(void){ + dataAvailable = -1; } virtual int available(void){ - return dataLength; + if(dataAvailable < 0){ + return 0; + } + return dataAvailable; } virtual int read(){ // Check if we have data available - if(dataLength) + if(dataAvailable > 0) { // Get next data byte (from the start to the end) - return data[sizeof(data) - dataLength--]; + return data[dataLength - dataAvailable--]; } return -1; } virtual int peek(){ // Check if we have data available - if(dataLength){ - return data[sizeof(data) - dataLength]; + if(dataAvailable > 0){ + return data[dataLength - dataAvailable]; } return -1; } @@ -114,27 +155,9 @@ public: } virtual size_t write(uint8_t *buffer, size_t size){ - // TODO this will split the data into proper USB_EP_SIZE packets already - SendReport(buffer, size); - return size; - - size_t bytesleft = size; - // First work through the buffer thats already there - while (bytesleft >= RAWHID_TX_SIZE){ - SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE); - bytesleft -= RAWHID_TX_SIZE; - } - - // Write down the leftover bytes and fill with zeros - if (bytesleft){ - SendReport(&buffer[size - bytesleft], bytesleft); - } - - return size; + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, buffer, size); } - void SendReport(void* data, int length); - protected: // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); @@ -147,7 +170,11 @@ protected: // Buffer pointers to hold the received data int dataLength; - uint8_t data[RAWHID_RX_SIZE]; + int dataAvailable; + uint8_t* data; + + uint8_t* featureReport; + int featureLength; }; extern RawHID_ RawHID; From fcb32a5cf09a44292ceb2a2bda0c6e52b22c0282 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:06:17 +0100 Subject: [PATCH 10/19] minor keyboard feature request fixes --- examples/KeyboardFeatureReport/KeyboardFeatureReport.ino | 4 ++++ src/SingleReport/BootKeyboard.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino index f7148ea..5946924 100644 --- a/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino +++ b/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino @@ -5,7 +5,11 @@ KeyboardFeatureReport example Shows how to use BootKeyboard with a modified Hyperion Lightpack device. + This example also works with RawHID. Might only work under linux. + https://github.com/tvdzwan/hyperion/pull/407 + https://github.com/tvdzwan/hyperion/wiki + https://github.com/FastLED/FastLED See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API diff --git a/src/SingleReport/BootKeyboard.cpp b/src/SingleReport/BootKeyboard.cpp index c132503..0261b41 100644 --- a/src/SingleReport/BootKeyboard.cpp +++ b/src/SingleReport/BootKeyboard.cpp @@ -158,6 +158,7 @@ bool BootKeyboard_::setup(USBSetup& setup) disableFeatureReport(); return true; } + // TODO fake clear data? } // Output (set led states) From 4c90e0b90dc4cabdcb74f85fed1301d71633e104 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:06:46 +0100 Subject: [PATCH 11/19] Added RawHID Hyperion Paintpack example --- examples/RawHIDPaintpack/RawHIDPaintpack.ino | 92 ++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 examples/RawHIDPaintpack/RawHIDPaintpack.ino diff --git a/examples/RawHIDPaintpack/RawHIDPaintpack.ino b/examples/RawHIDPaintpack/RawHIDPaintpack.ino new file mode 100644 index 0000000..40e540d --- /dev/null +++ b/examples/RawHIDPaintpack/RawHIDPaintpack.ino @@ -0,0 +1,92 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + RawHIDPaintpack example + + Shows how to use RawHID with the Hyperion Lightpack device. + https://github.com/tvdzwan/hyperion/wiki + https://github.com/FastLED/FastLED + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/RawHID-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; + + +// FastLED +#include "FastLED.h" + +#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN +#define COLOR_ORDER RGB +#define CHIPSET WS2801 // WS2811, LPD8806, etc +#define NUM_LEDS 25 + +#define BRIGHTNESS 255 // Reduce power consumption +#define LED_DITHER 255 // Try 0 to disable flickering +#define CORRECTION TypicalLEDStrip + +CRGB leds[NUM_LEDS]; // Define the array of leds +uint8_t rawhidData[sizeof(leds) + 2]; + +void setup() { + // FastLED setup + FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); + FastLED.setBrightness(BRIGHTNESS); + FastLED.setDither(LED_DITHER); + + // Startup animation + fill_solid(leds, NUM_LEDS, CRGB::Red); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Green); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Blue); + FastLED.show(); + delay(500); + FastLED.clear(); + FastLED.show(); + + pinMode(pinLed, OUTPUT); + + // Set the RawHID OUT report array. + // Feature reports are also (parallel) possible, see the other example for this. + RawHID.begin(rawhidData, sizeof(rawhidData)); +} + +void loop() { + // Check if there is new data from the RawHID device + auto bytesAvailable = RawHID.available(); + if (bytesAvailable == sizeof(rawhidData)) + { + digitalWrite(pinLed, HIGH); + + // Check header for errors + if (RawHID.read() != 3) { + return; + } + if (RawHID.read() != 0) { + return; + } + + // Write data to led array + uint8_t* ptr = (uint8_t*)leds; + for (int i = 0; i < sizeof(leds); i++) { + *ptr = RawHID.read(); + ptr++; + } + + // Update leds, do not update in the loop, to avoid corrupted data. + // For example if you write (0, 0, 0) and the interrupt + // changes the data to (255, 255, 255) you might get (0, 255, 255). + // Using a duplicated led array in cli() context would also work. + FastLED.show(); + + digitalWrite(pinLed, LOW); + } +} From 86ed8a146b0d743e6be4003b226fad96617ae688 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:09:45 +0100 Subject: [PATCH 12/19] Moved some examples into separate folder --- examples/{ => Keyboard}/BootKeyboard/BootKeyboard.ino | 0 examples/{ => Keyboard}/ImprovedKeyboard/ImprovedKeyboard.ino | 0 examples/{ => Keyboard}/KeyboardLed/KeyboardLed.ino | 0 examples/{ => Keyboard}/NKROKeyboard/NKROKeyboard.ino | 0 examples/{ => Keyboard}/TeensyKeyboard/TeensyKeyboard.ino | 0 examples/{ => Mouse}/AbsoluteMouse/AbsoluteMouse.ino | 0 examples/{ => Mouse}/ImprovedMouse/ImprovedMouse.ino | 0 .../{ => RawHID}/KeyboardFeatureReport/KeyboardFeatureReport.ino | 0 examples/RawHID/{ => RawHID}/RawHID.ino | 0 examples/{ => RawHID}/RawHIDPaintpack/RawHIDPaintpack.ino | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => Keyboard}/BootKeyboard/BootKeyboard.ino (100%) rename examples/{ => Keyboard}/ImprovedKeyboard/ImprovedKeyboard.ino (100%) rename examples/{ => Keyboard}/KeyboardLed/KeyboardLed.ino (100%) rename examples/{ => Keyboard}/NKROKeyboard/NKROKeyboard.ino (100%) rename examples/{ => Keyboard}/TeensyKeyboard/TeensyKeyboard.ino (100%) rename examples/{ => Mouse}/AbsoluteMouse/AbsoluteMouse.ino (100%) rename examples/{ => Mouse}/ImprovedMouse/ImprovedMouse.ino (100%) rename examples/{ => RawHID}/KeyboardFeatureReport/KeyboardFeatureReport.ino (100%) rename examples/RawHID/{ => RawHID}/RawHID.ino (100%) rename examples/{ => RawHID}/RawHIDPaintpack/RawHIDPaintpack.ino (100%) diff --git a/examples/BootKeyboard/BootKeyboard.ino b/examples/Keyboard/BootKeyboard/BootKeyboard.ino similarity index 100% rename from examples/BootKeyboard/BootKeyboard.ino rename to examples/Keyboard/BootKeyboard/BootKeyboard.ino diff --git a/examples/ImprovedKeyboard/ImprovedKeyboard.ino b/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino similarity index 100% rename from examples/ImprovedKeyboard/ImprovedKeyboard.ino rename to examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino diff --git a/examples/KeyboardLed/KeyboardLed.ino b/examples/Keyboard/KeyboardLed/KeyboardLed.ino similarity index 100% rename from examples/KeyboardLed/KeyboardLed.ino rename to examples/Keyboard/KeyboardLed/KeyboardLed.ino diff --git a/examples/NKROKeyboard/NKROKeyboard.ino b/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino similarity index 100% rename from examples/NKROKeyboard/NKROKeyboard.ino rename to examples/Keyboard/NKROKeyboard/NKROKeyboard.ino diff --git a/examples/TeensyKeyboard/TeensyKeyboard.ino b/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino similarity index 100% rename from examples/TeensyKeyboard/TeensyKeyboard.ino rename to examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino diff --git a/examples/AbsoluteMouse/AbsoluteMouse.ino b/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino similarity index 100% rename from examples/AbsoluteMouse/AbsoluteMouse.ino rename to examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino diff --git a/examples/ImprovedMouse/ImprovedMouse.ino b/examples/Mouse/ImprovedMouse/ImprovedMouse.ino similarity index 100% rename from examples/ImprovedMouse/ImprovedMouse.ino rename to examples/Mouse/ImprovedMouse/ImprovedMouse.ino diff --git a/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino similarity index 100% rename from examples/KeyboardFeatureReport/KeyboardFeatureReport.ino rename to examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino diff --git a/examples/RawHID/RawHID.ino b/examples/RawHID/RawHID/RawHID.ino similarity index 100% rename from examples/RawHID/RawHID.ino rename to examples/RawHID/RawHID/RawHID.ino diff --git a/examples/RawHIDPaintpack/RawHIDPaintpack.ino b/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino similarity index 100% rename from examples/RawHIDPaintpack/RawHIDPaintpack.ino rename to examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino From 214802a3b626f67bd57f33aefe982b60f635505f Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Nov 2015 07:25:40 +0100 Subject: [PATCH 13/19] Delete .development --- .development | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .development diff --git a/.development b/.development deleted file mode 100644 index e69de29..0000000 From a95361043b4dde35407cb9e1135d28c5a73a5e32 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 17:55:27 +0100 Subject: [PATCH 14/19] Removed unnecessary Arduino include --- src/HID-Project.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/HID-Project.h b/src/HID-Project.h index ff592d3..1858f0b 100644 --- a/src/HID-Project.h +++ b/src/HID-Project.h @@ -27,9 +27,6 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 250 -// TODO remove https://github.com/arduino/arduino-builder/issues/33 -#include - #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. #endif From e632912905285a871bb00caf11c702a7a118ae78 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 17:59:50 +0100 Subject: [PATCH 15/19] Fix NKRO example issue #64 --- keywords.txt | 4 +++- src/MultiReport/ImprovedKeyboard.h | 3 +-- src/MultiReport/NKROKeyboard.h | 3 +-- src/SingleReport/BootKeyboard.h | 4 ++-- src/SingleReport/SingleNKROKeyboard.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/keywords.txt b/keywords.txt index e5ce279..873224a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -13,6 +13,8 @@ begin KEYWORD2 end KEYWORD2 press KEYWORD2 +add KEYWORD2 +remove KEYWORD2 release KEYWORD2 releaseAll KEYWORD2 @@ -36,7 +38,7 @@ set_key4 KEYWORD2 set_key5 KEYWORD2 set_key6 KEYWORD2 set_media KEYWORD2 -send_now KEYWORD2 +send KEYWORD2 buttons KEYWORD2 xAxis KEYWORD2 diff --git a/src/MultiReport/ImprovedKeyboard.h b/src/MultiReport/ImprovedKeyboard.h index d9185cf..d59486c 100644 --- a/src/MultiReport/ImprovedKeyboard.h +++ b/src/MultiReport/ImprovedKeyboard.h @@ -37,8 +37,7 @@ public: Keyboard_(void); void wakeupHost(void); -protected: - virtual inline int send(void) override; + virtual inline int send(void) final; }; extern Keyboard_ Keyboard; diff --git a/src/MultiReport/NKROKeyboard.h b/src/MultiReport/NKROKeyboard.h index 933c127..ef5c9b4 100644 --- a/src/MultiReport/NKROKeyboard.h +++ b/src/MultiReport/NKROKeyboard.h @@ -36,8 +36,7 @@ class NKROKeyboard_ : public NKROKeyboardAPI public: NKROKeyboard_(void); -protected: - virtual inline int send(void) override; + virtual int send(void) final; }; extern NKROKeyboard_ NKROKeyboard; diff --git a/src/SingleReport/BootKeyboard.h b/src/SingleReport/BootKeyboard.h index d5c9ff0..cd28a8f 100644 --- a/src/SingleReport/BootKeyboard.h +++ b/src/SingleReport/BootKeyboard.h @@ -63,6 +63,8 @@ public: void disableFeatureReport(void){ featureLength |= 0x8000; } + + virtual int send(void) final; protected: // Implementation of the PUSBListNode @@ -78,8 +80,6 @@ protected: uint8_t* featureReport; int featureLength; - - virtual int send(void) override; }; extern BootKeyboard_ BootKeyboard; diff --git a/src/SingleReport/SingleNKROKeyboard.h b/src/SingleReport/SingleNKROKeyboard.h index 422a47b..d5f2ead 100644 --- a/src/SingleReport/SingleNKROKeyboard.h +++ b/src/SingleReport/SingleNKROKeyboard.h @@ -37,6 +37,8 @@ public: SingleNKROKeyboard_(void); uint8_t getLeds(void); uint8_t getProtocol(void); + + virtual int send(void) final; protected: // Implementation of the PUSBListNode @@ -49,8 +51,6 @@ protected: uint8_t idle; uint8_t leds; - - virtual inline int send(void) override; }; extern SingleNKROKeyboard_ SingleNKROKeyboard; From 5c245d7a8b94297a4f487ce8f20f3bb7bc7a0fe5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 18:05:56 +0100 Subject: [PATCH 16/19] Changed version number to 2.4.1 --- Readme.md | 10 +++++++--- library.properties | 2 +- src/HID-Project.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Readme.md b/Readme.md index da5c97d..ad1a29d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,5 @@ -Arduino HID Project 2.5 -======================= +Arduino HID Project 2.4.1 +========================= ![Header Picture](header.jpg) @@ -49,7 +49,11 @@ www.nicohood.de Version History =============== ``` -2.5 Release (xx.xx.2015) +2.4.1 Release (xx.xx.2015) +* RawHID Improvements +* Added Keyboard Feature Report +* NKRO and Keyboard API fixes +* Arduino library manager fix 2.4 Release (06.11.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID diff --git a/library.properties b/library.properties index 1bfd8b4..0dd202d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=HID-Project -version=2.5 +version=2.4.1 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino diff --git a/src/HID-Project.h b/src/HID-Project.h index 1858f0b..ff008b1 100644 --- a/src/HID-Project.h +++ b/src/HID-Project.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once // Software version -#define HID_PROJECT_VERSION 250 +#define HID_PROJECT_VERSION 241 #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. From 7754123b6eb4bbb60e8c1b354ceb46040a7ba7ca Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 5 Dec 2015 08:00:04 +0100 Subject: [PATCH 17/19] Added 1.6.7 as requirement --- src/HID-Project.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HID-Project.h b/src/HID-Project.h index ff008b1..5393c34 100644 --- a/src/HID-Project.h +++ b/src/HID-Project.h @@ -27,8 +27,8 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 241 -#if ARDUINO < 10606 -#error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. +#if ARDUINO < 10607 +#error HID Project requires Arduino IDE 1.6.7 or greater. Please update your IDE. #endif #if !defined(USBCON) From 4423cf6a472508cce6f158efe587952a6e30a4ba Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Dec 2015 01:43:28 +0100 Subject: [PATCH 18/19] Release 2.4.1 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index ad1a29d..34c0fc3 100644 --- a/Readme.md +++ b/Readme.md @@ -49,7 +49,7 @@ www.nicohood.de Version History =============== ``` -2.4.1 Release (xx.xx.2015) +2.4.1 Release (19.12.2015) * RawHID Improvements * Added Keyboard Feature Report * NKRO and Keyboard API fixes From 9a113eb8d20a63437672d7e774978a4e6d128a4c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Dec 2015 01:44:47 +0100 Subject: [PATCH 19/19] Added udev rule example --- extras/ArduinoRawHID.rules | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 extras/ArduinoRawHID.rules diff --git a/extras/ArduinoRawHID.rules b/extras/ArduinoRawHID.rules new file mode 100644 index 0000000..5b29231 --- /dev/null +++ b/extras/ArduinoRawHID.rules @@ -0,0 +1,44 @@ +# Original taken and modified from: +# https://github.com/ihowson/Teensy-Raw-HID-in-Python/blob/master/teensy_loader_cli/49-teensy.rules +# +# This file must be placed at: +# +# /etc/udev/rules.d/ArduinoRawHID.rules (preferred location) +# or +# /lib/udev/rules.d/ArduinoRawHID.rules (req'd on some broken systems) +# +# SUBSYSTEMS=="usb", ATTRS{idVendor}=="0x2341", ATTRS{idProduct}=="0x8036", MODE:="0666" +# +# Reload udev rules: +# udevadm control --reload && udevadm trigger +# +# +# Arduino devices (leonardo only, or all Arduino devices): +#SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="8036", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", MODE:="0666" +# +# +#SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", MODE:="0666" +#SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="8000", MODE:="0666" +#KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", SYMLINK+="ttyUSB00%n", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1" +# +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. +# +# +# If using USB Serial you get a new device each time (Ubuntu 9.10) +# eg: /dev/ttyACM0, ttyACM1, ttyACM2, ttyACM3, ttyACM4, etc +# apt-get remove --purge modemmanager (reboot may be necessary) +# +# +# Older modem proding (eg, Ubuntu 9.04) caused very slow serial device detection. +# To fix, add this near top of /lib/udev/rules.d/77-nm-probe-modem-capabilities.rules +# SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", GOTO="nm_modem_probe_end" +# +# +# (old udev rules) +#SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="047[78]", MODE:="0666" +#SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="048[02]", MODE:="0666" +#KERNEL=="ttyACM*", SYMLINK+="ttyUSB00%n", MODE:="0666"