1
1
/*
2
2
Copyright (c) 2015, Arduino LLC
3
3
Original code (pre-library): Copyright (c) 2011, Peter Barrett
4
+ Modified code: Copyright (c) 2020, Aleksandr Bratchik
4
5
5
6
Permission to use, copy, modify, and/or distribute this software for
6
7
any purpose with or without fee is hereby granted, provided that the
@@ -30,18 +31,35 @@ int HID_::getInterface(uint8_t* interfaceCount)
30
31
{
31
32
*interfaceCount += 1 ; // uses 1
32
33
HIDDescriptor hidInterface = {
33
- D_INTERFACE (pluggedInterface, 1 , USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
34
+ D_INTERFACE (pluggedInterface, 2 , USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
34
35
D_HIDREPORT (descriptorSize),
35
- D_ENDPOINT (USB_ENDPOINT_IN (pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01 )
36
+ D_ENDPOINT (USB_ENDPOINT_IN (HID_TX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x14 ),
37
+ D_ENDPOINT (USB_ENDPOINT_OUT (HID_RX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x0A )
36
38
};
37
39
return USB_SendControl (0 , &hidInterface, sizeof (hidInterface));
38
40
}
39
41
40
42
int HID_::getDescriptor (USBSetup& setup)
41
43
{
44
+
45
+ u8 t = setup.wValueH ;
46
+
47
+ // HID-specific strings
48
+ if (USB_STRING_DESCRIPTOR_TYPE == t) {
49
+
50
+ // we place all strings in the 0xFF00-0xFFFE range
51
+ HIDReport* rep = GetFeature (0xFF00 | setup.wValueL );
52
+ if (rep) {
53
+ return USB_SendStringDescriptor ((u8*)rep->data , strlen_P ((char *)rep->data ), TRANSFER_PGM);
54
+ }
55
+ else {
56
+ return 0 ;
57
+ }
58
+ }
59
+
42
60
// Check if this is a HID Class Descriptor request
43
61
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0 ; }
44
- if (setup. wValueH != HID_REPORT_DESCRIPTOR_TYPE ) { return 0 ; }
62
+ if (HID_REPORT_DESCRIPTOR_TYPE != t ) { return 0 ; }
45
63
46
64
// In a HID Class Descriptor wIndex cointains the interface number
47
65
if (setup.wIndex != pluggedInterface) { return 0 ; }
@@ -64,12 +82,23 @@ int HID_::getDescriptor(USBSetup& setup)
64
82
65
83
uint8_t HID_::getShortName (char *name)
66
84
{
85
+ if (serial) {
86
+ for (byte i=0 ; i<strlen_P (serial); i++) {
87
+ name[i] = pgm_read_byte_near (serial + i);
88
+ }
89
+ return strlen_P (serial);
90
+ }
91
+ else {
92
+
93
+ // default serial number
94
+
67
95
name[0 ] = ' H' ;
68
96
name[1 ] = ' I' ;
69
97
name[2 ] = ' D' ;
70
98
name[3 ] = ' A' + (descriptorSize & 0x0F );
71
99
name[4 ] = ' A' + ((descriptorSize >> 4 ) & 0x0F );
72
100
return 5 ;
101
+ }
73
102
}
74
103
75
104
void HID_::AppendDescriptor (HIDSubDescriptor *node)
@@ -86,28 +115,91 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node)
86
115
descriptorSize += node->length ;
87
116
}
88
117
89
- int HID_::SendReport ( uint8_t id, const void * data, int len)
118
+ int HID_::SetFeature ( uint16_t id, const void * data, int len)
90
119
{
91
- auto ret = USB_Send (pluggedEndpoint, &id, 1 );
120
+ if (!rootReport) {
121
+ rootReport = new HIDReport (id, data, len);
122
+ } else {
123
+ HIDReport* current;
124
+ int i=0 ;
125
+ for ( current = rootReport; current; current = current->next , i++) {
126
+ if (current->id == id) {
127
+ return i;
128
+ }
129
+ // check if we are on the last report
130
+ if (!current->next ) {
131
+ current->next = new HIDReport (id, data, len);
132
+ break ;
133
+ }
134
+ }
135
+
136
+ }
137
+
138
+ reportCount++;
139
+ return reportCount;
140
+ }
141
+
142
+ bool HID_::LockFeature (uint16_t id, bool lock) {
143
+ if (rootReport) {
144
+ HIDReport* current;
145
+ for (current = rootReport;current; current=current->next ) {
146
+ if (current->id == id) {
147
+ current->lock = lock;
148
+ return true ;
149
+ }
150
+ }
151
+ }
152
+ return false ;
153
+ }
154
+
155
+
156
+ int HID_::SendReport (uint16_t id, const void * data, int len)
157
+ {
158
+ auto ret = USB_Send (HID_TX, &id, 1 );
92
159
if (ret < 0 ) return ret;
93
- auto ret2 = USB_Send (pluggedEndpoint | TRANSFER_RELEASE, data, len);
160
+ auto ret2 = USB_Send (HID_TX | TRANSFER_RELEASE, data, len);
94
161
if (ret2 < 0 ) return ret2;
95
162
return ret + ret2;
96
163
}
97
164
98
- bool HID_::setup (USBSetup& setup )
165
+ HIDReport* HID_::GetFeature ( uint16_t id )
99
166
{
167
+ HIDReport* current;
168
+ int i=0 ;
169
+ for (current=rootReport; current && i<reportCount; current=current->next , i++) {
170
+ if (id == current->id ) {
171
+ return current;
172
+ }
173
+ }
174
+ return (HIDReport*) NULL ;
175
+ }
176
+
177
+ bool HID_::setup (USBSetup& setup)
178
+ {
100
179
if (pluggedInterface != setup.wIndex ) {
101
180
return false ;
102
181
}
103
182
104
183
uint8_t request = setup.bRequest ;
105
184
uint8_t requestType = setup.bmRequestType ;
106
-
185
+
107
186
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
108
- {
187
+ {
109
188
if (request == HID_GET_REPORT) {
110
- // TODO: HID_GetReport();
189
+
190
+ if (setup.wValueH == HID_REPORT_TYPE_FEATURE)
191
+ {
192
+
193
+ HIDReport* current = GetFeature (setup.wValueL );
194
+ if (current){
195
+ if (USB_SendControl (0 , &(current->id ), 1 )>0 &&
196
+ USB_SendControl (0 , current->data , current->length )>0 )
197
+ return true ;
198
+ }
199
+
200
+ return false ;
201
+
202
+ }
111
203
return true ;
112
204
}
113
205
if (request == HID_GET_PROTOCOL) {
@@ -120,7 +212,7 @@ bool HID_::setup(USBSetup& setup)
120
212
}
121
213
122
214
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
123
- {
215
+ {
124
216
if (request == HID_SET_PROTOCOL) {
125
217
// The USB Host tells us if we are in boot or report mode.
126
218
// This only works with a real boot compatible device.
@@ -133,24 +225,33 @@ bool HID_::setup(USBSetup& setup)
133
225
}
134
226
if (request == HID_SET_REPORT)
135
227
{
136
- // uint8_t reportID = setup.wValueL;
137
- // uint16_t length = setup.wLength;
138
- // uint8_t data[length];
139
- // Make sure to not read more data than USB_EP_SIZE.
140
- // You can read multiple times through a loop.
141
- // The first byte (may!) contain the reportID on a multreport.
142
- // USB_RecvControl(data, length);
228
+ if (setup.wValueH == HID_REPORT_TYPE_FEATURE)
229
+ {
230
+
231
+ HIDReport* current = GetFeature (setup.wValueL );
232
+ if (!current) return false ;
233
+ if (setup.wLength != current->length + 1 ) return false ;
234
+ uint8_t * data = new uint8_t [setup.wLength ];
235
+ USB_RecvControl (data, setup.wLength );
236
+ if (*data != current->id ) return false ;
237
+ memcpy ((uint8_t *)current->data , data+1 , current->length );
238
+ delete[] data;
239
+ return true ;
240
+
241
+ }
242
+
143
243
}
144
244
}
145
245
146
246
return false ;
147
247
}
148
248
149
- HID_::HID_ (void ) : PluggableUSBModule(1 , 1 , epType),
249
+ HID_::HID_ (void ) : PluggableUSBModule(2 , 1 , epType),
150
250
rootNode(NULL ), descriptorSize(0 ),
151
251
protocol(HID_REPORT_PROTOCOL), idle(1 )
152
252
{
153
253
epType[0 ] = EP_TYPE_INTERRUPT_IN;
254
+ epType[1 ] = EP_TYPE_INTERRUPT_OUT;
154
255
PluggableUSB ().plug (this );
155
256
}
156
257
0 commit comments