Skip to content

Commit c5353e4

Browse files
NicoHoodobra
authored andcommitted
Added RawHID
1 parent 9dc0068 commit c5353e4

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
Copyright (c) 2014-2015 NicoHood
3+
See the readme for credit to other people.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.
22+
*/
23+
24+
#include "RawHID.h"
25+
26+
static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = {
27+
/* RAW HID */
28+
0x06, lowByte(RAWHID_USAGE_PAGE), highByte(RAWHID_USAGE_PAGE), /* 30 */
29+
0x0A, lowByte(RAWHID_USAGE), highByte(RAWHID_USAGE),
30+
31+
0xA1, 0x01, /* Collection 0x01 */
32+
// RawHID is not multireport compatible.
33+
// On Linux it might work with some modifications,
34+
// however you are not happy to use it like that.
35+
//0x85, HID_REPORTID_RAWHID, /* REPORT_ID */
36+
0x75, 0x08, /* report size = 8 bits */
37+
0x15, 0x00, /* logical minimum = 0 */
38+
0x26, 0xFF, 0x00, /* logical maximum = 255 */
39+
40+
0x95, RAWHID_TX_SIZE, /* report count TX */
41+
0x09, 0x01, /* usage */
42+
0x81, 0x02, /* Input (array) */
43+
44+
0x95, RAWHID_RX_SIZE, /* report count RX */
45+
0x09, 0x02, /* usage */
46+
0x91, 0x02, /* Output (array) */
47+
0xC0 /* end collection */
48+
};
49+
50+
RawHID_::RawHID_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), dataLength(0)
51+
{
52+
epType[0] = EP_TYPE_INTERRUPT_IN;
53+
PluggableUSB().plug(this);
54+
}
55+
56+
int RawHID_::getInterface(uint8_t* interfaceCount)
57+
{
58+
// TODO add a 2nd OUT endpoint to get more speed???
59+
// Maybe as optional device
60+
*interfaceCount += 1; // uses 1
61+
HIDDescriptor hidInterface = {
62+
D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
63+
D_HIDREPORT(sizeof(_hidReportDescriptorRawHID)),
64+
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
65+
};
66+
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
67+
}
68+
69+
int RawHID_::getDescriptor(USBSetup& setup)
70+
{
71+
// Check if this is a HID Class Descriptor request
72+
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
73+
if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
74+
75+
// In a HID Class Descriptor wIndex cointains the interface number
76+
if (setup.wIndex != pluggedInterface) { return 0; }
77+
78+
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorRawHID, sizeof(_hidReportDescriptorRawHID));
79+
}
80+
81+
bool RawHID_::setup(USBSetup& setup)
82+
{
83+
if (pluggedInterface != setup.wIndex) {
84+
return false;
85+
}
86+
87+
uint8_t request = setup.bRequest;
88+
uint8_t requestType = setup.bmRequestType;
89+
90+
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
91+
{
92+
if (request == HID_GET_REPORT) {
93+
// TODO: HID_GetReport();
94+
return true;
95+
}
96+
if (request == HID_GET_PROTOCOL) {
97+
// TODO: Send8(protocol);
98+
return true;
99+
}
100+
}
101+
102+
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
103+
{
104+
if (request == HID_SET_PROTOCOL) {
105+
protocol = setup.wValueL;
106+
return true;
107+
}
108+
if (request == HID_SET_IDLE) {
109+
idle = setup.wValueL;
110+
return true;
111+
}
112+
if (request == HID_SET_REPORT)
113+
{
114+
// TODO
115+
}
116+
}
117+
118+
return false;
119+
}
120+
121+
void RawHID_::SendReport(void* data, int length){
122+
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length);
123+
}
124+
125+
RawHID_ RawHID;
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
Copyright (c) 2014-2015 NicoHood
3+
See the readme for credit to other people.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.
22+
*/
23+
24+
// Include guard
25+
#pragma once
26+
27+
#include <Arduino.h>
28+
#include "PluggableUSB.h"
29+
#include "HID.h"
30+
#include "HID-Settings.h"
31+
32+
// RawHID might never work with multireports, because of OS problems
33+
// therefore we have to make it a single report with no idea. No other HID device will be supported then.
34+
#undef RAWHID_USAGE_PAGE
35+
#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
36+
37+
#undef RAWHID_USAGE
38+
#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
39+
40+
// Keep one byte offset for the reportID if used
41+
#if (HID_REPORTID_RAWHID)
42+
#define RAWHID_SIZE (USB_EP_SIZE-1)
43+
#else
44+
#define RAWHID_SIZE (USB_EP_SIZE)
45+
#endif
46+
47+
#undef RAWHID_TX_SIZE
48+
#define RAWHID_TX_SIZE RAWHID_SIZE
49+
50+
#undef RAWHID_RX_SIZE
51+
#define RAWHID_RX_SIZE RAWHID_SIZE
52+
53+
typedef union{
54+
// a RAWHID_TX_SIZE byte buffer for tx
55+
uint8_t whole8[];
56+
uint16_t whole16[];
57+
uint32_t whole32[];
58+
uint8_t buff[RAWHID_TX_SIZE];
59+
} HID_RawKeyboardTXReport_Data_t;
60+
61+
typedef union{
62+
// a RAWHID_TX_SIZE byte buffer for rx
63+
uint8_t whole8[];
64+
uint16_t whole16[];
65+
uint32_t whole32[];
66+
uint8_t buff[RAWHID_RX_SIZE];
67+
} HID_RawKeyboardRXReport_Data_t;
68+
69+
class RawHID_ : public PUSBListNode, public Stream
70+
{
71+
public:
72+
RawHID_(void);
73+
74+
void begin(void){
75+
// empty
76+
}
77+
78+
void end(void){
79+
// empty
80+
}
81+
82+
virtual int available(void){
83+
return dataLength;
84+
}
85+
86+
virtual int read(){
87+
if(dataLength){
88+
// Get next data byte
89+
uint8_t data = *(dataTail - dataLength);
90+
dataLength--;
91+
92+
// Release buffer if its read fully
93+
if(!dataLength){
94+
free(dataHead);
95+
}
96+
97+
return data;
98+
}
99+
return -1;
100+
}
101+
102+
virtual int peek(){
103+
if(dataLength){
104+
return *(dataTail - dataLength);
105+
}
106+
return -1;
107+
}
108+
109+
virtual void flush(void){
110+
// Delete all incoming bytes
111+
if(dataLength){
112+
free(dataHead);
113+
dataLength = 0;
114+
}
115+
}
116+
117+
using Print::write;
118+
virtual size_t write(uint8_t b){
119+
return write(&b, 1);
120+
}
121+
122+
virtual size_t write(uint8_t *buffer, size_t size){
123+
// TODO this only sends the report ID in the first packat
124+
// TODO this will split the data into USB_EP_SIZE packets
125+
SendReport(buffer, size);
126+
return size;
127+
128+
size_t bytesleft = size;
129+
// First work through the buffer thats already there
130+
while (bytesleft >= RAWHID_TX_SIZE){
131+
SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE);
132+
bytesleft -= RAWHID_TX_SIZE;
133+
}
134+
135+
// Write down the leftover bytes and fill with zeros
136+
if (bytesleft){
137+
SendReport(&buffer[size - bytesleft], bytesleft);
138+
}
139+
140+
return size;
141+
}
142+
143+
void SendReport(void* data, int length);
144+
145+
protected:
146+
// Implementation of the PUSBListNode
147+
int getInterface(uint8_t* interfaceCount);
148+
int getDescriptor(USBSetup& setup);
149+
bool setup(USBSetup& setup);
150+
151+
uint8_t epType[1];
152+
uint8_t protocol;
153+
uint8_t idle;
154+
155+
156+
virtual void setReportData(void* &data, int len){
157+
// Only overwrite the buffer if its empty.
158+
// This avoids corrupted data while reading.
159+
if(!dataLength){
160+
// Save new data
161+
dataLength = len;
162+
dataHead = (uint8_t*) data;
163+
dataTail = (uint8_t*)(data) + len;
164+
165+
// Clear the passed in pointer to not free the data
166+
data = NULL;
167+
}
168+
}
169+
170+
// Buffer pointers to hold the received data
171+
int dataLength;
172+
uint8_t* dataHead;
173+
uint8_t* dataTail;
174+
};
175+
extern RawHID_ RawHID;
176+

0 commit comments

Comments
 (0)