@@ -442,13 +442,17 @@ void USBCore_::disconnect()
442
442
// sent, or -1 on error.
443
443
int USBCore_::sendControl (uint8_t flags, const void * data, int len)
444
444
{
445
- // TODO: parse out flags like we do for ‘send’.
446
- (void )flags;
447
445
uint8_t * d = (uint8_t *)data;
448
446
auto l = min (len, this ->maxWrite );
449
447
auto wrote = 0 ;
450
448
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
+ }
452
456
d += w;
453
457
wrote += w;
454
458
this ->maxWrite -= w;
@@ -457,6 +461,18 @@ int USBCore_::sendControl(uint8_t flags, const void* data, int len)
457
461
}
458
462
}
459
463
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.
460
476
return len;
461
477
}
462
478
@@ -639,7 +655,11 @@ void USBCore_::transcSetup(usb_dev* usbd, uint8_t ep)
639
655
this ->sendDeviceStringDescriptor ();
640
656
return ;
641
657
} 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
+ }
643
663
return ;
644
664
} else {
645
665
reqstat = usbd_standard_request (usbd, &usbd->control .req );
@@ -650,7 +670,14 @@ void USBCore_::transcSetup(usb_dev* usbd, uint8_t ep)
650
670
case USB_REQTYPE_CLASS:
651
671
// Calls into class_core->req_process, does nothing else.
652
672
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 ;
654
681
655
682
/* vendor defined request */
656
683
case USB_REQTYPE_VENDOR:
0 commit comments