DFU: Resolve DFU runtime descriptor dynamically from descriptors

We cannoy simply use the DFU runtime descriptor of the DFU mode, but we
have to use the descriptor of the specific currently-selected runtime
configuration.  Let's iterate over the descriptors of a configuration
and find the DFU runtime descriptor in it.
This commit is contained in:
Harald Welte
2017-03-06 22:42:11 +01:00
parent 5b108d8cf0
commit e8869fb8ff

View File

@@ -22,6 +22,7 @@
*/ */
#include <board.h> #include <board.h>
#include <assert.h>
#include <core_cm3.h> #include <core_cm3.h>
#include <usb/include/USBD.h> #include <usb/include/USBD.h>
@@ -67,6 +68,26 @@ static void __dfufunc handle_getstate(void)
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
} }
static const uint8_t *get_dfu_func_desc(void)
{
USBDDriver *usbdDriver = USBD_GetDriver();
const USBConfigurationDescriptor *cfg_desc;
const USBGenericDescriptor *gen_desc;
if (USBD_IsHighSpeed())
cfg_desc = &usbdDriver->pDescriptors->pHsConfiguration[usbdDriver->cfgnum];
else
cfg_desc = usbdDriver->pDescriptors->pFsConfiguration[usbdDriver->cfgnum];
for (gen_desc = (const USBGenericDescriptor *) cfg_desc;
(const uint8_t *) gen_desc < (const uint8_t *) cfg_desc + cfg_desc->wTotalLength;
gen_desc = (const USBGenericDescriptor *) ((const uint8_t *)gen_desc + gen_desc->bLength)) {
if (gen_desc->bDescriptorType == USB_DT_DFU)
return (const uint8_t *) gen_desc;
}
return NULL;
}
static void TerminateCtrlInWithNull(void *pArg, static void TerminateCtrlInWithNull(void *pArg,
unsigned char status, unsigned char status,
unsigned long int transferred, unsigned long int transferred,
@@ -100,15 +121,18 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) { USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) {
uint16_t length = sizeof(struct usb_dfu_func_descriptor); uint16_t length = sizeof(struct usb_dfu_func_descriptor);
const USBDeviceDescriptor *pDevice; const USBDeviceDescriptor *pDevice;
const uint8_t *dfu_func_desc = get_dfu_func_desc();
int terminateWithNull; int terminateWithNull;
ASSERT(dfu_func_desc);
if (USBD_IsHighSpeed()) if (USBD_IsHighSpeed())
pDevice = usbdDriver->pDescriptors->pHsDevice; pDevice = usbdDriver->pDescriptors->pHsDevice;
else else
pDevice = usbdDriver->pDescriptors->pFsDevice; pDevice = usbdDriver->pDescriptors->pFsDevice;
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length, USBD_Write(0, dfu_func_desc, length,
terminateWithNull ? TerminateCtrlInWithNull : 0, 0); terminateWithNull ? TerminateCtrlInWithNull : 0, 0);
return; return;
} }