summaryrefslogtreecommitdiff
path: root/usb/device/dfu
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-01-05 23:35:54 +0100
committerHarald Welte <laforge@gnumonks.org>2012-01-05 23:35:54 +0100
commitb45eec0ed447830ed54e1f271931ab25919eaaf7 (patch)
tree177c358f1aee88e50c28e35ee6a21296d7075101 /usb/device/dfu
parentf04ca88a272a4edd89228119e502af262b59558d (diff)
various DFU fixes
* make RET_* constants public as DFU_RET_* * support GET_DESCRIPTOR on the DFU interface descriptor * use static buffer for getstatus()
Diffstat (limited to 'usb/device/dfu')
-rw-r--r--usb/device/dfu/dfu.h18
-rw-r--r--usb/device/dfu/dfu_driver.c93
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 <usb/common/dfu/usb_dfu.h>
+
+/* for board-specific config */
+#include <board.h>
+
+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 <usb/common/core/USBInterfaceDescriptor.h>
#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
#include <usb/device/core/USBD.h>
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
@@ -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();
personal git repositories of Harald Welte. Your mileage may vary