From b45eec0ed447830ed54e1f271931ab25919eaaf7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 5 Jan 2012 23:35:54 +0100 Subject: various DFU fixes * make RET_* constants public as DFU_RET_* * support GET_DESCRIPTOR on the DFU interface descriptor * use static buffer for getstatus() --- usb/device/dfu/dfu.h | 18 +++++++++ usb/device/dfu/dfu_driver.c | 93 +++++++++++++++++++++++++++++++++------------ 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/usb/device/dfu/dfu.h b/usb/device/dfu/dfu.h index 4d5aa5b..34afa4a 100644 --- a/usb/device/dfu/dfu.h +++ b/usb/device/dfu/dfu.h @@ -25,6 +25,17 @@ struct USBStringDescriptor { #ifdef BOARD_USB_DFU +#include + +/* for board-specific config */ +#include + +struct dfu_desc { + USBConfigurationDescriptor ucfg; + USBInterfaceDescriptor uif[BOARD_DFU_NUM_IF]; + struct usb_dfu_func_descriptor func_dfu; +} __attribute__ ((packed)); + /* USB DFU functional descriptor */ #define DFU_FUNC_DESC { \ .bLength = USB_DT_DFU_SIZE, \ @@ -84,6 +95,9 @@ extern const struct USBStringDescriptor USBDFU_string3; (const unsigned char *) &USBDFU_string2, \ (const unsigned char *) &USBDFU_string3, +const struct dfu_desc dfu_cfg_descriptor; +const USBDDriverDescriptors dfu_descriptors; + #else /* BOARD_USB_DFU */ /* no DFU bootloader is being used */ @@ -115,4 +129,8 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request); void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors, unsigned char *pInterfaces); +#define DFU_RET_NOTHING 0 +#define DFU_RET_ZLP 1 +#define DFU_RET_STALL 2 + #endif diff --git a/usb/device/dfu/dfu_driver.c b/usb/device/dfu/dfu_driver.c index 1e9286e..f7705ac 100644 --- a/usb/device/dfu/dfu_driver.c +++ b/usb/device/dfu/dfu_driver.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -37,10 +38,6 @@ /// Standard device driver instance. static USBDDriver usbdDriver; -#define RET_NOTHING 0 -#define RET_ZLP 1 -#define RET_STALL 2 - __dfudata struct dfu dfu = { .state = DFU_STATE_appIDLE, .past_manifest = 0, @@ -48,7 +45,8 @@ __dfudata struct dfu dfu = { static __dfufunc void handle_getstatus(void) { - struct dfu_status dstat; + /* has to be static as USBD_Write is async ? */ + static struct dfu_status dstat; dfu_drv_updstatus(); @@ -58,6 +56,8 @@ static __dfufunc void handle_getstatus(void) dstat.iString = 0; /* FIXME: set dstat.bwPollTimeout */ + TRACE_DEBUG("handle_getstatus(%u, %u)\n\r", dstat.bStatus, dstat.bState); + USBD_Write(0, (char *)&dstat, sizeof(dstat), NULL, 0); } @@ -65,9 +65,23 @@ static void __dfufunc handle_getstate(void) { uint8_t u8 = dfu.state; + TRACE_DEBUG("handle_getstate(%u)\n\r", dfu.state); + USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); } +static void TerminateCtrlInWithNull(void *pArg, + unsigned char status, + unsigned int transferred, + unsigned int remaining) +{ + USBD_Write(0, // Endpoint #0 + 0, // No data buffer + 0, // No data buffer + (TransferCallback) 0, + (void *) 0); +} + /* this function gets daisy-chained into processing EP0 requests */ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) { @@ -76,7 +90,32 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) uint16_t val = USBGenericRequest_GetValue(request); int rc, ret; - /* only process actual DFU specific messages */ + TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n", + USBGenericRequest_GetType(request), + USBGenericRequest_GetRecipient(request), + val, len); + + /* check for GET_DESCRIPTOR on DFU */ + if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD && + USBGenericRequest_GetRecipient(request) == USBGenericRequest_DEVICE && + USBGenericRequest_GetRequest(request) == USBGenericRequest_GETDESCRIPTOR && + USBGetDescriptorRequest_GetDescriptorType(request) == USB_DT_DFU) { + uint16_t length = sizeof(struct usb_dfu_func_descriptor); + const USBDeviceDescriptor *pDevice; + int terminateWithNull; + + if (USBD_IsHighSpeed()) + pDevice = usbdDriver.pDescriptors->pHsDevice; + else + pDevice = usbdDriver.pDescriptors->pFsDevice; + + terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); + USBD_Write(0, &dfu_cfg_descriptor.func_dfu, length, + terminateWithNull ? TerminateCtrlInWithNull : 0, 0); + return; + } + + /* forward all non-DFU specific messages to core handler*/ if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS || USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) { TRACE_DEBUG("std_ho_usbd "); @@ -93,12 +132,13 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; case USB_REQ_DFU_DETACH: + TRACE_DEBUG("\r\n====dfu_detach\n\r"); dfu.state = DFU_STATE_appDETACH; - ret = RET_ZLP; + ret = DFU_RET_ZLP; goto out; break; default: - ret = RET_STALL; + ret = DFU_RET_STALL; } break; case DFU_STATE_appDETACH: @@ -111,7 +151,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_appIDLE; - ret = RET_STALL; + ret = DFU_RET_STALL; goto out; break; } @@ -122,7 +162,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) case USB_REQ_DFU_DNLOAD: if (len == 0) { dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; goto out; } dfu.state = DFU_STATE_dfuDNLOAD_SYNC; @@ -134,7 +174,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; case USB_REQ_DFU_ABORT: /* no zlp? */ - ret = RET_ZLP; + ret = DFU_RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: handle_getstatus(); @@ -144,7 +184,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; goto out; break; } @@ -160,7 +200,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; goto out; } break; @@ -173,7 +213,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; goto out; } break; @@ -185,7 +225,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; case USB_REQ_DFU_ABORT: dfu.state = DFU_STATE_dfuIDLE; - ret = RET_ZLP; + ret = DFU_RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: handle_getstatus(); @@ -195,7 +235,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; break; } break; @@ -209,7 +249,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; break; } break; @@ -233,7 +273,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; break; } break; @@ -251,7 +291,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) case USB_REQ_DFU_ABORT: dfu.state = DFU_STATE_dfuIDLE; /* no zlp? */ - ret = RET_ZLP; + ret = DFU_RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: handle_getstatus(); @@ -261,7 +301,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; break; } break; @@ -277,11 +317,11 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) dfu.state = DFU_STATE_dfuIDLE; dfu.status = DFU_STATUS_OK; /* no zlp? */ - ret = RET_ZLP; + ret = DFU_RET_ZLP; break; default: dfu.state = DFU_STATE_dfuERROR; - ret = RET_STALL; + ret = DFU_RET_STALL; break; } break; @@ -289,12 +329,12 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) out: switch (ret) { - case RET_NOTHING: + case DFU_RET_NOTHING: break; - case RET_ZLP: + case DFU_RET_ZLP: USBD_Write(0, 0, 0, 0, 0); break; - case RET_STALL: + case DFU_RET_STALL: USBD_Stall(0); break; } @@ -302,6 +342,9 @@ out: void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors, unsigned char *pInterfaces) { + /* We already start in DFU idle mode */ + dfu.state = DFU_STATE_dfuIDLE; + USBDDriver_Initialize(&usbdDriver, pDescriptors, pInterfaces); USBD_Init(); -- cgit v1.2.3