Skip to content

Commit b462d39

Browse files
bjcobra
authored andcommitted
Fix IN stage SETUP requests and OUT stage class requests.
* Handle flags in ‘USBCore::sendControl' * When an OUT stage has been handled for an interface or class request, send a ZLP.
1 parent c166e01 commit b462d39

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

cores/arduino/USBCore.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,13 +442,17 @@ void USBCore_::disconnect()
442442
// sent, or -1 on error.
443443
int USBCore_::sendControl(uint8_t flags, const void* data, int len)
444444
{
445-
// TODO: parse out flags like we do for ‘send’.
446-
(void)flags;
447445
uint8_t* d = (uint8_t*)data;
448446
auto l = min(len, this->maxWrite);
449447
auto wrote = 0;
450448
while (wrote < l) {
451-
size_t w = EPBuffers().buf(0).push(d, l - wrote);
449+
auto w = 0;
450+
if (flags & TRANSFER_ZERO) {
451+
// TODO: handle writing zeros instead of ‘d’.
452+
return -1;
453+
} else {
454+
w = EPBuffers().buf(0).push(d, l - wrote);
455+
}
452456
d += w;
453457
wrote += w;
454458
this->maxWrite -= w;
@@ -457,6 +461,18 @@ int USBCore_::sendControl(uint8_t flags, const void* data, int len)
457461
}
458462
}
459463

464+
if (flags & TRANSFER_RELEASE) {
465+
this->flush(0);
466+
}
467+
468+
// Return ‘len’, rather than ‘wrote’, because PluggableUSB
469+
// calculates descriptor sizes by first having them write to an
470+
// empty buffer (setting ‘this->maxWrite’ to 0). To accomodate
471+
// that, we always just pretend we sent the entire buffer.
472+
//
473+
// TODO: this may cause issues when /actually/ sending buffers
474+
// larger than ‘this->maxWrite’, since we will have claimed to
475+
// send more data than we did.
460476
return len;
461477
}
462478

@@ -639,7 +655,11 @@ void USBCore_::transcSetup(usb_dev* usbd, uint8_t ep)
639655
this->sendDeviceStringDescriptor();
640656
return;
641657
} else if ((usbd->control.req.bmRequestType & USB_RECPTYPE_MASK) == USB_RECPTYPE_ITF) {
642-
ClassCore::reqProcess(usbd, &usbd->control.req);
658+
reqstat = (usb_reqsta)ClassCore::reqProcess(usbd, &usbd->control.req);
659+
if (reqstat == REQ_SUPP
660+
&& (usbd->control.req.bmRequestType & USB_TRX_IN) != USB_TRX_IN) {
661+
this->sendZLP(usbd, 0);
662+
}
643663
return;
644664
} else {
645665
reqstat = usbd_standard_request(usbd, &usbd->control.req);
@@ -650,7 +670,14 @@ void USBCore_::transcSetup(usb_dev* usbd, uint8_t ep)
650670
case USB_REQTYPE_CLASS:
651671
// Calls into class_core->req_process, does nothing else.
652672
reqstat = usbd_class_request(usbd, &usbd->control.req);
653-
break;
673+
674+
// Respond with a ZLP if the host has sent data,
675+
// because we’ve already handled in in the class request.
676+
if (reqstat == REQ_SUPP
677+
&& ((usbd->control.req.bmRequestType & USB_TRX_IN) != USB_TRX_IN)) {
678+
this->sendZLP(usbd, 0);
679+
}
680+
return;
654681

655682
/* vendor defined request */
656683
case USB_REQTYPE_VENDOR:

0 commit comments

Comments
 (0)