various DFU fixes

* make RET_* constants public as DFU_RET_*
 * support GET_DESCRIPTOR on the DFU interface descriptor
 * use static buffer for getstatus()
This commit is contained in:
Harald Welte 2012-01-05 23:35:54 +01:00
parent f04ca88a27
commit b45eec0ed4
2 changed files with 86 additions and 25 deletions

View File

@ -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

View File

@ -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();