Added RawHID
Works under linux with a patched Teensy RawHID testprogram Only works without any other HID device (like keyboard) used together
This commit is contained in:
parent
85922c2860
commit
6c9e2fd99c
5 changed files with 375 additions and 10 deletions
133
examples/RawHID/RawHID.ino
Normal file
133
examples/RawHID/RawHID.ino
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
Advanced RawHID example
|
||||
|
||||
Shows how to send bytes via RawHID.
|
||||
Press a button to send some example values.
|
||||
Keep in mind that you can only send full data packets,
|
||||
the rest is filled with zero!
|
||||
|
||||
Definitions from HID_Reports.h:
|
||||
RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
|
||||
RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
|
||||
RAWHID_TX_SIZE 15 // 1 byte for report ID
|
||||
RAWHID_RX_SIZE 15 // 1 byte for report ID
|
||||
|
||||
See HID Project documentation for more information.
|
||||
https://github.com/NicoHood/HID/wiki/RawHID-API
|
||||
*/
|
||||
|
||||
#include "HID-Project.h"
|
||||
|
||||
const int pinLed = LED_BUILTIN;
|
||||
const int pinButton = 2;
|
||||
|
||||
void setup() {
|
||||
pinMode(pinLed, OUTPUT);
|
||||
pinMode(pinButton, INPUT_PULLUP);
|
||||
Serial.begin(0);//TODO
|
||||
//Keyboard.begin();
|
||||
// No begin function needed for RawHID
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!digitalRead(pinButton)) {
|
||||
digitalWrite(pinLed, HIGH);
|
||||
|
||||
// Direct without library. Always send RAWHID_RX_SIZE bytes!
|
||||
uint8_t buff[RAWHID_TX_SIZE] = {0};
|
||||
|
||||
// With library
|
||||
memset(&buff, 42, sizeof(buff));
|
||||
RawHID.write(buff, sizeof(buff));
|
||||
|
||||
// Write a single byte, will fill the rest with zeros
|
||||
RawHID.write(0xCD);
|
||||
|
||||
// Huge buffer with library, will fill the rest with zeros
|
||||
uint8_t megabuff[100];
|
||||
for (int i = 0; i < sizeof(megabuff); i++)
|
||||
megabuff[i] = i;
|
||||
RawHID.write(megabuff, sizeof(megabuff));
|
||||
|
||||
// You can use print too, but better do not use a linefeed.
|
||||
// A linefeed will send the \r and \n in a separate report.
|
||||
RawHID.println("Hello World");
|
||||
|
||||
// Compare print to write:
|
||||
RawHID.write("Hello World\r\n");
|
||||
|
||||
// Simple debounce
|
||||
delay(300);
|
||||
digitalWrite(pinLed, LOW);
|
||||
}
|
||||
|
||||
uint8_t len = RawHID.available();
|
||||
if (len) {
|
||||
digitalWrite(pinLed, HIGH);
|
||||
|
||||
// Mirror the incoming data from the host back
|
||||
uint8_t buff[len + 1];
|
||||
buff[0] = len;
|
||||
for (int i = 1; i < sizeof(buff); i++) {
|
||||
buff[i] = RawHID.read();
|
||||
}
|
||||
RawHID.write(buff, len);
|
||||
|
||||
// Simple debounce
|
||||
delay(300);
|
||||
digitalWrite(pinLed, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Expected output:
|
||||
|
||||
// manual with unintialized buff
|
||||
recv 15 bytes:
|
||||
01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20
|
||||
|
||||
// filled buff
|
||||
recv 15 bytes:
|
||||
2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A
|
||||
|
||||
// single byte filled with zero
|
||||
recv 15 bytes:
|
||||
CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
// huge buffer filled with zero at the end
|
||||
recv 15 bytes:
|
||||
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
|
||||
|
||||
recv 15 bytes:
|
||||
0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D
|
||||
|
||||
recv 15 bytes:
|
||||
1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C
|
||||
|
||||
recv 15 bytes:
|
||||
2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B
|
||||
|
||||
recv 15 bytes:
|
||||
3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
// print
|
||||
recv 15 bytes:
|
||||
48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00
|
||||
|
||||
//\r
|
||||
recv 15 bytes:
|
||||
0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
//\n
|
||||
recv 15 bytes:
|
||||
0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
//write
|
||||
recv 15 bytes:
|
||||
48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00
|
||||
|
||||
*/
|
||||
|
||||
|
|
@ -92,6 +92,12 @@ THE SOFTWARE.
|
|||
#define HID_REPORTID_KEYBOARD 2
|
||||
#endif
|
||||
|
||||
#ifndef HID_REPORTID_RAWHID
|
||||
// On Windows you might want to use 0 here and no other HID device combined.
|
||||
// Make sure to also disable the boot protocol for keyboard or mouse.
|
||||
#define HID_REPORTID_RAWHID 3
|
||||
#endif
|
||||
|
||||
#ifndef HID_REPORTID_CONSUMERCONTROL
|
||||
#define HID_REPORTID_CONSUMERCONTROL 4
|
||||
#endif
|
||||
|
|
@ -131,6 +137,7 @@ THE SOFTWARE.
|
|||
#include "Consumer.h"
|
||||
#include "Gamepad.h"
|
||||
#include "System.h"
|
||||
#include "RawHID.h"
|
||||
|
||||
// Include Teensy HID afterwards to overwrite key definitions if used
|
||||
#ifdef USE_TEENSY_KEYBOARD
|
||||
|
|
|
|||
|
|
@ -27,16 +27,7 @@ HID_ HID;
|
|||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
|
||||
// HID report descriptor
|
||||
|
||||
#define LSB(_x) ((_x) & 0xFF)
|
||||
#define MSB(_x) ((_x) >> 8)
|
||||
|
||||
#define RAWHID_USAGE_PAGE 0xFFC0
|
||||
#define RAWHID_USAGE 0x0C00
|
||||
#define RAWHID_TX_SIZE 64
|
||||
#define RAWHID_RX_SIZE 64
|
||||
// HID Interface
|
||||
|
||||
// Static variables
|
||||
uint8_t HID_::HID_ENDPOINT_INT;
|
||||
|
|
|
|||
30
src/RawHID.cpp
Normal file
30
src/RawHID.cpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "RawHID.h"
|
||||
|
||||
//================================================================================
|
||||
// RawHID
|
||||
//================================================================================
|
||||
|
||||
RawHID_ RawHID;
|
||||
204
src/RawHID.h
Normal file
204
src/RawHID.h
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HID.h"
|
||||
|
||||
#if !defined(_USING_HID)
|
||||
|
||||
#warning "Using legacy HID core (non pluggable)"
|
||||
|
||||
#else
|
||||
|
||||
#include "HID-Project.h"
|
||||
|
||||
//================================================================================
|
||||
// RawHID
|
||||
//================================================================================
|
||||
|
||||
// RawHID might never work with multireports, because of OS problems
|
||||
// therefore we have to make it a single report with no idea. No other HID device will be supported then.
|
||||
#undef RAWHID_USAGE_PAGE
|
||||
#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
|
||||
|
||||
#undef RAWHID_USAGE
|
||||
#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
|
||||
|
||||
// Keep one byte offset for the reportID if used
|
||||
#if (HID_REPORTID_RAWHID)
|
||||
#define RAWHID_SIZE (USB_EP_SIZE-1)
|
||||
#else
|
||||
#define RAWHID_SIZE (USB_EP_SIZE)
|
||||
#endif
|
||||
|
||||
#undef RAWHID_TX_SIZE
|
||||
#define RAWHID_TX_SIZE RAWHID_SIZE
|
||||
|
||||
#undef RAWHID_RX_SIZE
|
||||
#define RAWHID_RX_SIZE RAWHID_SIZE
|
||||
|
||||
#define LSB(_x) ((_x) & 0xFF)
|
||||
#define MSB(_x) ((_x) >> 8)
|
||||
|
||||
static const uint8_t _rawhidReportDescriptor[] PROGMEM = {
|
||||
/* RAW HID */
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
|
||||
0xA1, 0x01, /* Collection 0x01 */
|
||||
#if (HID_REPORTID_RAWHID)
|
||||
0x85, HID_REPORTID_RAWHID, /* REPORT_ID */
|
||||
#endif
|
||||
0x75, 0x08, /* report size = 8 bits */
|
||||
0x15, 0x00, /* logical minimum = 0 */
|
||||
0x26, 0xFF, 0x00, /* logical maximum = 255 */
|
||||
|
||||
0x95, RAWHID_TX_SIZE, /* report count TX */
|
||||
0x09, 0x01, /* usage */
|
||||
0x81, 0x02, /* Input (array) */
|
||||
|
||||
0x95, RAWHID_RX_SIZE, /* report count RX */
|
||||
0x09, 0x02, /* usage */
|
||||
0x91, 0x02, /* Output (array) */
|
||||
0xC0 /* end collection */
|
||||
};
|
||||
|
||||
typedef union{
|
||||
// a RAWHID_TX_SIZE byte buffer for tx
|
||||
uint8_t whole8[];
|
||||
uint16_t whole16[];
|
||||
uint32_t whole32[];
|
||||
uint8_t buff[RAWHID_TX_SIZE];
|
||||
} HID_RawKeyboardTXReport_Data_t;
|
||||
|
||||
typedef union{
|
||||
// a RAWHID_TX_SIZE byte buffer for rx
|
||||
uint8_t whole8[];
|
||||
uint16_t whole16[];
|
||||
uint32_t whole32[];
|
||||
uint8_t buff[RAWHID_RX_SIZE];
|
||||
} HID_RawKeyboardRXReport_Data_t;
|
||||
|
||||
class RawHID_ : public Stream, private HIDDevice
|
||||
{
|
||||
public:
|
||||
RawHID_(void) :
|
||||
HIDDevice((uint8_t*)_rawhidReportDescriptor, sizeof(_rawhidReportDescriptor), HID_REPORTID_RAWHID),
|
||||
dataLength(0)
|
||||
{
|
||||
// HID Descriptor is appended via the inherited HIDDevice class
|
||||
}
|
||||
|
||||
void begin(void){
|
||||
// empty
|
||||
}
|
||||
|
||||
void end(void){
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual int available(void){
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
virtual int read(){
|
||||
if(dataLength){
|
||||
// Get next data byte
|
||||
uint8_t data = *(dataTail - dataLength);
|
||||
dataLength--;
|
||||
|
||||
// Release buffer if its read fully
|
||||
if(!dataLength){
|
||||
free(dataHead);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek(){
|
||||
if(dataLength){
|
||||
return *(dataTail - dataLength);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void flush(void){
|
||||
// Delete all incoming bytes
|
||||
if(dataLength){
|
||||
free(dataHead);
|
||||
dataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
using Print::write;
|
||||
virtual size_t write(uint8_t b){
|
||||
write(&b, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buffer, size_t size){
|
||||
// TODO this only sends the report ID in the first packat
|
||||
// TODO this will split the data into USB_EP_SIZE packets
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void setReportData(void* &data, int len){
|
||||
// Only overwrite the buffer if its empty.
|
||||
// This avoids corrupted data while reading.
|
||||
if(!dataLength){
|
||||
// Save new data
|
||||
dataLength = len;
|
||||
dataHead = (uint8_t*) data;
|
||||
dataTail = (uint8_t*)(data + len);
|
||||
|
||||
// Clear the passed in pointer to not free the data
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer pointers to hold the received data
|
||||
int dataLength;
|
||||
uint8_t* dataHead;
|
||||
uint8_t* dataTail;
|
||||
};
|
||||
extern RawHID_ RawHID;
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue