11/*
22 Copyright (c) 2015, Arduino LLC
33 Original code (pre-library): Copyright (c) 2011, Peter Barrett
4+ Modified code: Copyright (c) 2020, Aleksandr Bratchik
45
56 Permission to use, copy, modify, and/or distribute this software for
67 any purpose with or without fee is hereby granted, provided that the
@@ -30,18 +31,35 @@ int HID_::getInterface(uint8_t* interfaceCount)
3031{
3132 *interfaceCount += 1 ; // uses 1
3233 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),
3435 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 )
3638 };
3739 return USB_SendControl (0 , &hidInterface, sizeof (hidInterface));
3840}
3941
4042int HID_::getDescriptor (USBSetup& setup)
4143{
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+
4260 // Check if this is a HID Class Descriptor request
4361 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 ; }
4563
4664 // In a HID Class Descriptor wIndex cointains the interface number
4765 if (setup.wIndex != pluggedInterface) { return 0 ; }
@@ -64,12 +82,23 @@ int HID_::getDescriptor(USBSetup& setup)
6482
6583uint8_t HID_::getShortName (char *name)
6684{
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+
6795 name[0 ] = ' H' ;
6896 name[1 ] = ' I' ;
6997 name[2 ] = ' D' ;
7098 name[3 ] = ' A' + (descriptorSize & 0x0F );
7199 name[4 ] = ' A' + ((descriptorSize >> 4 ) & 0x0F );
72100 return 5 ;
101+ }
73102}
74103
75104void HID_::AppendDescriptor (HIDSubDescriptor *node)
@@ -86,28 +115,91 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node)
86115 descriptorSize += node->length ;
87116}
88117
89- int HID_::SendReport ( uint8_t id, const void * data, int len)
118+ int HID_::SetFeature ( uint16_t id, const void * data, int len)
90119{
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 );
92159 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);
94161 if (ret2 < 0 ) return ret2;
95162 return ret + ret2;
96163}
97164
98- bool HID_::setup (USBSetup& setup )
165+ HIDReport* HID_::GetFeature ( uint16_t id )
99166{
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+ {
100179 if (pluggedInterface != setup.wIndex ) {
101180 return false ;
102181 }
103182
104183 uint8_t request = setup.bRequest ;
105184 uint8_t requestType = setup.bmRequestType ;
106-
185+
107186 if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
108- {
187+ {
109188 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+ }
111203 return true ;
112204 }
113205 if (request == HID_GET_PROTOCOL) {
@@ -120,7 +212,7 @@ bool HID_::setup(USBSetup& setup)
120212 }
121213
122214 if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
123- {
215+ {
124216 if (request == HID_SET_PROTOCOL) {
125217 // The USB Host tells us if we are in boot or report mode.
126218 // This only works with a real boot compatible device.
@@ -133,24 +225,33 @@ bool HID_::setup(USBSetup& setup)
133225 }
134226 if (request == HID_SET_REPORT)
135227 {
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+
143243 }
144244 }
145245
146246 return false ;
147247}
148248
149- HID_::HID_ (void ) : PluggableUSBModule(1 , 1 , epType),
249+ HID_::HID_ (void ) : PluggableUSBModule(2 , 1 , epType),
150250 rootNode(NULL ), descriptorSize(0 ),
151251 protocol(HID_REPORT_PROTOCOL), idle(1 )
152252{
153253 epType[0 ] = EP_TYPE_INTERRUPT_IN;
254+ epType[1 ] = EP_TYPE_INTERRUPT_OUT;
154255 PluggableUSB ().plug (this );
155256}
156257
0 commit comments