@@ -37,12 +37,47 @@ int HID_::getInterface(uint8_t* interfaceCount)
3737 };
3838 return USB_SendControl (0 , &hidInterface, sizeof (hidInterface));
3939}
40+ // Send a USB descriptor string. The string is stored in PROGMEM as a
41+ // plain ASCII string but is sent out as UTF-16 with the correct 2-byte
42+ // prefix
43+ static bool USB_SendStringDescriptor (const char * string_P, u8 string_len, uint8_t flags) {
44+
45+ u8 c[2 ] = {(u8 )(2 + string_len * 2 ), 3 };
46+
47+ USB_SendControl (0 ,&c,2 );
48+
49+ bool pgm = flags & TRANSFER_PGM;
50+ for (u8 i = 0 ; i < string_len; i++) {
51+ c[0 ] = pgm ? pgm_read_byte (&string_P[i]) : string_P[i];
52+ c[1 ] = 0 ;
53+ int r = USB_SendControl (0 ,&c,2 );
54+ if (!r) {
55+ return false ;
56+ }
57+ }
58+ return true ;
59+ }
4060
4161int HID_::getDescriptor (USBSetup& setup)
4262{
63+
64+ u8 t = setup.wValueH ;
65+
66+ if (USB_STRING_DESCRIPTOR_TYPE == t) {
67+
68+ // we place all strings in the 0xFF00-0xFFFE range
69+ HIDReport* rep = GetFeature (0xFF00 | setup.wValueL );
70+ if (rep) {
71+ return USB_SendStringDescriptor ((char *)rep->data , strlen_P ((char *)rep->data ), TRANSFER_PGM);
72+ }
73+ else {
74+ return 0 ;
75+ }
76+ }
77+
4378 // Check if this is a HID Class Descriptor request
4479 if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0 ; }
45- if (setup. wValueH != HID_REPORT_DESCRIPTOR_TYPE ) { return 0 ; }
80+ if (HID_REPORT_DESCRIPTOR_TYPE != t ) { return 0 ; }
4681
4782 // In a HID Class Descriptor wIndex cointains the interface number
4883 if (setup.wIndex != pluggedInterface) { return 0 ; }
@@ -65,12 +100,23 @@ int HID_::getDescriptor(USBSetup& setup)
65100
66101uint8_t HID_::getShortName (char *name)
67102{
103+ if (serial) {
104+ for (byte i=0 ; i<strlen_P (serial); i++) {
105+ name[i] = pgm_read_byte_near (serial + i);
106+ }
107+ return strlen_P (serial);
108+ }
109+ else {
110+
111+ // default serial number
112+
68113 name[0 ] = ' H' ;
69114 name[1 ] = ' I' ;
70115 name[2 ] = ' D' ;
71116 name[3 ] = ' A' + (descriptorSize & 0x0F );
72117 name[4 ] = ' A' + ((descriptorSize >> 4 ) & 0x0F );
73118 return 5 ;
119+ }
74120}
75121
76122void HID_::AppendDescriptor (HIDSubDescriptor *node)
@@ -87,7 +133,7 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node)
87133 descriptorSize += node->length ;
88134}
89135
90- int HID_::SetFeature (uint8_t id, const void * data, int len)
136+ int HID_::SetFeature (uint16_t id, const void * data, int len)
91137{
92138 if (!rootReport) {
93139 rootReport = new HIDReport (id, data, len);
@@ -111,7 +157,7 @@ int HID_::SetFeature(uint8_t id, const void* data, int len)
111157 return reportCount;
112158}
113159
114- bool HID_::LockFeature (uint8_t id, bool lock) {
160+ bool HID_::LockFeature (uint16_t id, bool lock) {
115161 if (rootReport) {
116162 HIDReport* current;
117163 for (current = rootReport;current; current=current->next ) {
@@ -125,7 +171,7 @@ bool HID_::LockFeature(uint8_t id, bool lock) {
125171}
126172
127173
128- int HID_::SendReport (uint8_t id, const void * data, int len)
174+ int HID_::SendReport (uint16_t id, const void * data, int len)
129175{
130176 auto ret = USB_Send (HID_TX, &id, 1 );
131177 if (ret < 0 ) return ret;
@@ -134,6 +180,18 @@ int HID_::SendReport(uint8_t id, const void* data, int len)
134180 return ret + ret2;
135181}
136182
183+ HIDReport* HID_::GetFeature (uint16_t id)
184+ {
185+ HIDReport* current;
186+ int i=0 ;
187+ for (current=rootReport; current && i<reportCount; current=current->next , i++) {
188+ if (id == current->id ) {
189+ return current;
190+ }
191+ }
192+ return (HIDReport*) NULL ;
193+ }
194+
137195bool HID_::setup (USBSetup& setup)
138196{
139197 if (pluggedInterface != setup.wIndex ) {
@@ -149,25 +207,16 @@ bool HID_::setup(USBSetup& setup)
149207
150208 if (setup.wValueH == HID_REPORT_TYPE_FEATURE)
151209 {
152- // dbg->print(setup.wValueL);
153- HIDReport* current;
154- int i=0 ;
155- for (current=rootReport; current && i<reportCount; current=current->next , i++) {
156- // dbg->print(":");
157- // dbg->print(current->id);
158- // dbg->print(" ");
159- // dbg->print(current->length);
160- // dbg->print(" ");
161- if (setup.wValueL == current->id ) {
162- if (USB_SendControl (0 , &(current->id ), 1 )<0 ||
163- USB_SendControl (0 , current->data , current->length )<0 )
164- return false ;
165-
166- break ;
167- }
168- // dbg->println("");
210+
211+ HIDReport* current = GetFeature (setup.wValueL );
212+ if (current){
213+ if (USB_SendControl (0 , &(current->id ), 1 )>0 &&
214+ USB_SendControl (0 , current->data , current->length )>0 )
215+ return true ;
169216 }
170217
218+ return false ;
219+
171220 }
172221 return true ;
173222 }
@@ -193,14 +242,22 @@ bool HID_::setup(USBSetup& setup)
193242 return true ;
194243 }
195244 if (request == HID_SET_REPORT)
196- {
197- // uint8_t reportID = setup.wValueL;
198- // uint16_t length = setup.wLength;
199- // uint8_t data[length];
200- // Make sure to not read more data than USB_EP_SIZE.
201- // You can read multiple times through a loop.
202- // The first byte (may!) contain the reportID on a multreport.
203- // USB_RecvControl(data, length);
245+ {
246+ if (setup.wValueH == HID_REPORT_TYPE_FEATURE)
247+ {
248+
249+ HIDReport* current = GetFeature (setup.wValueL );
250+ if (!current) return false ;
251+ if (setup.wLength != current->length + 1 ) return false ;
252+ uint8_t * data = new uint8_t [setup.wLength ];
253+ USB_RecvControl (data, setup.wLength );
254+ if (*data != current->id ) return false ;
255+ memcpy ((uint8_t *)current->data , data+1 , current->length );
256+ delete[] data;
257+ return true ;
258+
259+ }
260+
204261 }
205262 }
206263
0 commit comments