unsigned int poll_timeout;
};
+struct dfu_entity *dfu_defer_flush;
+
typedef int (*dfu_state_fn) (struct f_dfu *,
const struct usb_ctrlrequest *,
struct usb_gadget *,
NULL,
};
-static const struct usb_qualifier_descriptor dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_VENDOR_SPEC,
- .bNumConfigurations = 1,
-};
-
static const char dfu_name[] = "Device Firmware Upgrade";
/*
static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_dfu *f_dfu = req->context;
+ int ret;
- dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
- req->length, f_dfu->blk_seq_num);
+ ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+ req->actual, f_dfu->blk_seq_num);
+ if (ret) {
+ f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
+ f_dfu->dfu_state = DFU_STATE_dfuERROR;
+ }
}
static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
{
struct f_dfu *f_dfu = req->context;
-
- dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
- req->length, f_dfu->blk_seq_num);
+ dfu_set_defer_flush(dfu_get_entity(f_dfu->altsetting));
}
static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu)
DFU_MANIFEST_POLL_TIMEOUT;
}
-static void handle_getstatus(struct usb_request *req)
+static int handle_getstatus(struct usb_request *req)
{
struct dfu_status *dstat = (struct dfu_status *)req->buf;
struct f_dfu *f_dfu = req->context;
dstat->bStatus = f_dfu->dfu_status;
dstat->bState = f_dfu->dfu_state;
dstat->iString = 0;
+
+ return sizeof(struct dfu_status);
}
-static void handle_getstate(struct usb_request *req)
+static int handle_getstate(struct usb_request *req)
{
struct f_dfu *f_dfu = req->context;
((u8 *)req->buf)[0] = f_dfu->dfu_state;
- req->actual = sizeof(u8);
+ return sizeof(u8);
}
static inline void to_dfu_mode(struct f_dfu *f_dfu)
{
f_dfu->usb_function.strings = dfu_strings;
f_dfu->usb_function.hs_descriptors = f_dfu->function;
+ f_dfu->usb_function.descriptors = f_dfu->function;
f_dfu->dfu_state = DFU_STATE_dfuIDLE;
}
{
f_dfu->usb_function.strings = NULL;
f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+ f_dfu->usb_function.descriptors = dfu_runtime_descs;
}
static int handle_upload(struct usb_request *req, u16 len)
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
case USB_REQ_DFU_DETACH:
f_dfu->dfu_state = DFU_STATE_appDETACH;
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_appIDLE;
value = RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
case USB_REQ_DFU_DETACH:
/*
to_runtime_mode(f_dfu);
f_dfu->dfu_state = DFU_STATE_appIDLE;
- dfu_trigger_reset();
+ g_dnl_trigger_detach();
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
value = RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
case USB_REQ_DFU_GETSTATUS:
/* We're MainfestationTolerant */
f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
- handle_getstatus(req);
+ value = handle_getstatus(req);
f_dfu->blk_seq_num = 0;
- value = RET_STAT_LEN;
req->complete = dnload_request_flush;
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
case USB_REQ_DFU_GETSTATUS:
/* We're MainfestationTolerant */
f_dfu->dfu_state = DFU_STATE_dfuIDLE;
- handle_getstatus(req);
+ value = handle_getstatus(req);
f_dfu->blk_seq_num = 0;
- value = RET_STAT_LEN;
puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
value = RET_ZLP;
break;
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
default:
f_dfu->dfu_state = DFU_STATE_dfuERROR;
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
- handle_getstatus(req);
- value = RET_STAT_LEN;
+ value = handle_getstatus(req);
break;
case USB_REQ_DFU_GETSTATE:
- handle_getstate(req);
+ value = handle_getstate(req);
break;
case USB_REQ_DFU_CLRSTATUS:
f_dfu->dfu_state = DFU_STATE_dfuIDLE;
f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
if (!f_dfu->strings)
- goto enomem;
+ return -ENOMEM;
for (i = 0; i < n; ++i) {
de = dfu_get_entity(i);
f_dfu->strings[i].s = NULL;
return 0;
-
-enomem:
- while (i)
- f_dfu->strings[--i].s = NULL;
-
- free(f_dfu->strings);
-
- return -ENOMEM;
}
static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
struct usb_interface_descriptor *d;
int i = 0;
- f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1);
+ f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 2);
if (!f_dfu->function)
goto enomem;
f_dfu->function[i] = (struct usb_descriptor_header *)d;
}
+
+ /* add DFU Functional Descriptor */
+ f_dfu->function[i] = calloc(sizeof(dfu_func), 1);
+ if (!f_dfu->function[i])
+ goto enomem;
+ memcpy(f_dfu->function[i], &dfu_func, sizeof(dfu_func));
+
+ i++;
f_dfu->function[i] = NULL;
return 0;
{
struct usb_composite_dev *cdev = c->cdev;
struct f_dfu *f_dfu = func_to_dfu(f);
+ const char *s;
int alt_num = dfu_get_alt_number();
int rv, id, i;
cdev->req->context = f_dfu;
+ s = env_get("serial#");
+ if (s)
+ g_dnl_set_serialnumber((char *)s);
+
error:
return rv;
}
debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
f_dfu->altsetting = alt;
+ f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+ f_dfu->dfu_status = DFU_STATUS_OK;
return 0;
}
+static int __dfu_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_dfu *f_dfu = func_to_dfu(f);
+
+ return f_dfu->altsetting;
+}
+
/* TODO: is this really what we need here? */
static void dfu_disable(struct usb_function *f)
{
return -ENOMEM;
f_dfu->usb_function.name = "dfu";
f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+ f_dfu->usb_function.descriptors = dfu_runtime_descs;
f_dfu->usb_function.bind = dfu_bind;
f_dfu->usb_function.unbind = dfu_unbind;
f_dfu->usb_function.set_alt = dfu_set_alt;
+ f_dfu->usb_function.get_alt = __dfu_get_alt;
f_dfu->usb_function.disable = dfu_disable;
f_dfu->usb_function.strings = dfu_generic_strings;
f_dfu->usb_function.setup = dfu_handle;