2 * f_dfu.c -- Device Firmware Update USB function
4 * Copyright (C) 2012 Samsung Electronics
8 * Based on OpenMoko u-boot: drivers/usb/usbdfu.c
9 * (C) 2007 by OpenMoko, Inc.
12 * based on existing SAM7DFU code from OpenPCD:
13 * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de>
15 * SPDX-License-Identifier: GPL-2.0+
22 #include <linux/usb/ch9.h>
23 #include <linux/usb/gadget.h>
24 #include <linux/usb/composite.h>
31 struct usb_function usb_function;
33 struct usb_descriptor_header **function;
34 struct usb_string *strings;
36 /* when configured, we have one config */
39 enum dfu_state dfu_state;
40 unsigned int dfu_status;
42 /* Send/received block number is handy for data integrity check */
44 unsigned int poll_timeout;
47 typedef int (*dfu_state_fn) (struct f_dfu *,
48 const struct usb_ctrlrequest *,
50 struct usb_request *);
52 static inline struct f_dfu *func_to_dfu(struct usb_function *f)
54 return container_of(f, struct f_dfu, usb_function);
57 static const struct dfu_function_descriptor dfu_func = {
58 .bLength = sizeof dfu_func,
59 .bDescriptorType = DFU_DT_FUNC,
60 .bmAttributes = DFU_BIT_WILL_DETACH |
61 DFU_BIT_MANIFESTATION_TOLERANT |
65 .wTransferSize = DFU_USB_BUFSIZ,
66 .bcdDFUVersion = __constant_cpu_to_le16(0x0110),
69 static struct usb_interface_descriptor dfu_intf_runtime = {
70 .bLength = sizeof dfu_intf_runtime,
71 .bDescriptorType = USB_DT_INTERFACE,
73 .bInterfaceClass = USB_CLASS_APP_SPEC,
74 .bInterfaceSubClass = 1,
75 .bInterfaceProtocol = 1,
76 /* .iInterface = DYNAMIC */
79 static struct usb_descriptor_header *dfu_runtime_descs[] = {
80 (struct usb_descriptor_header *) &dfu_intf_runtime,
84 static const char dfu_name[] = "Device Firmware Upgrade";
87 * static strings, in UTF-8
89 * dfu_generic configuration
91 static struct usb_string strings_dfu_generic[] = {
96 static struct usb_gadget_strings stringtab_dfu_generic = {
97 .language = 0x0409, /* en-us */
98 .strings = strings_dfu_generic,
101 static struct usb_gadget_strings *dfu_generic_strings[] = {
102 &stringtab_dfu_generic,
107 * usb_function specific
109 static struct usb_gadget_strings stringtab_dfu = {
110 .language = 0x0409, /* en-us */
114 * assigned during initialization,
115 * depends on number of flash entities
120 static struct usb_gadget_strings *dfu_strings[] = {
125 static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms)
128 * The bwPollTimeout DFU_GETSTATUS request payload provides information
129 * about minimum time, in milliseconds, that the host should wait before
130 * sending a subsequent DFU_GETSTATUS request
132 * This permits the device to vary the delay depending on its need to
133 * erase or program the memory
137 unsigned char *p = (unsigned char *)&ms;
139 if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) {
140 dstat->bwPollTimeout[0] = 0;
141 dstat->bwPollTimeout[1] = 0;
142 dstat->bwPollTimeout[2] = 0;
147 dstat->bwPollTimeout[0] = *p++;
148 dstat->bwPollTimeout[1] = *p++;
149 dstat->bwPollTimeout[2] = *p;
152 /*-------------------------------------------------------------------------*/
154 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
156 struct f_dfu *f_dfu = req->context;
159 ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
160 req->length, f_dfu->blk_seq_num);
162 f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
163 f_dfu->dfu_state = DFU_STATE_dfuERROR;
167 static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
169 struct f_dfu *f_dfu = req->context;
172 ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
173 req->length, f_dfu->blk_seq_num);
175 f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
176 f_dfu->dfu_state = DFU_STATE_dfuERROR;
180 static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu)
182 return dfu->poll_timeout ? dfu->poll_timeout(dfu) :
183 DFU_MANIFEST_POLL_TIMEOUT;
186 static void handle_getstatus(struct usb_request *req)
188 struct dfu_status *dstat = (struct dfu_status *)req->buf;
189 struct f_dfu *f_dfu = req->context;
190 struct dfu_entity *dfu = dfu_get_entity(f_dfu->altsetting);
192 dfu_set_poll_timeout(dstat, 0);
194 switch (f_dfu->dfu_state) {
195 case DFU_STATE_dfuDNLOAD_SYNC:
196 case DFU_STATE_dfuDNBUSY:
197 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
199 case DFU_STATE_dfuMANIFEST_SYNC:
200 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
202 case DFU_STATE_dfuMANIFEST:
203 dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu));
209 if (f_dfu->poll_timeout)
210 if (!(f_dfu->blk_seq_num %
211 (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
212 dfu_set_poll_timeout(dstat, f_dfu->poll_timeout);
214 /* send status response */
215 dstat->bStatus = f_dfu->dfu_status;
216 dstat->bState = f_dfu->dfu_state;
220 static void handle_getstate(struct usb_request *req)
222 struct f_dfu *f_dfu = req->context;
224 ((u8 *)req->buf)[0] = f_dfu->dfu_state;
225 req->actual = sizeof(u8);
228 static inline void to_dfu_mode(struct f_dfu *f_dfu)
230 f_dfu->usb_function.strings = dfu_strings;
231 f_dfu->usb_function.hs_descriptors = f_dfu->function;
232 f_dfu->usb_function.descriptors = f_dfu->function;
233 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
236 static inline void to_runtime_mode(struct f_dfu *f_dfu)
238 f_dfu->usb_function.strings = NULL;
239 f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
240 f_dfu->usb_function.descriptors = dfu_runtime_descs;
243 static int handle_upload(struct usb_request *req, u16 len)
245 struct f_dfu *f_dfu = req->context;
247 return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
248 req->length, f_dfu->blk_seq_num);
251 static int handle_dnload(struct usb_gadget *gadget, u16 len)
253 struct usb_composite_dev *cdev = get_gadget_data(gadget);
254 struct usb_request *req = cdev->req;
255 struct f_dfu *f_dfu = req->context;
258 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
260 req->complete = dnload_request_complete;
265 /*-------------------------------------------------------------------------*/
266 /* DFU state machine */
267 static int state_app_idle(struct f_dfu *f_dfu,
268 const struct usb_ctrlrequest *ctrl,
269 struct usb_gadget *gadget,
270 struct usb_request *req)
274 switch (ctrl->bRequest) {
275 case USB_REQ_DFU_GETSTATUS:
276 handle_getstatus(req);
277 value = RET_STAT_LEN;
279 case USB_REQ_DFU_GETSTATE:
280 handle_getstate(req);
282 case USB_REQ_DFU_DETACH:
283 f_dfu->dfu_state = DFU_STATE_appDETACH;
295 static int state_app_detach(struct f_dfu *f_dfu,
296 const struct usb_ctrlrequest *ctrl,
297 struct usb_gadget *gadget,
298 struct usb_request *req)
302 switch (ctrl->bRequest) {
303 case USB_REQ_DFU_GETSTATUS:
304 handle_getstatus(req);
305 value = RET_STAT_LEN;
307 case USB_REQ_DFU_GETSTATE:
308 handle_getstate(req);
311 f_dfu->dfu_state = DFU_STATE_appIDLE;
319 static int state_dfu_idle(struct f_dfu *f_dfu,
320 const struct usb_ctrlrequest *ctrl,
321 struct usb_gadget *gadget,
322 struct usb_request *req)
324 u16 w_value = le16_to_cpu(ctrl->wValue);
325 u16 len = le16_to_cpu(ctrl->wLength);
328 switch (ctrl->bRequest) {
329 case USB_REQ_DFU_DNLOAD:
331 f_dfu->dfu_state = DFU_STATE_dfuERROR;
335 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
336 f_dfu->blk_seq_num = w_value;
337 value = handle_dnload(gadget, len);
339 case USB_REQ_DFU_UPLOAD:
340 f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
341 f_dfu->blk_seq_num = 0;
342 value = handle_upload(req, len);
344 case USB_REQ_DFU_ABORT:
348 case USB_REQ_DFU_GETSTATUS:
349 handle_getstatus(req);
350 value = RET_STAT_LEN;
352 case USB_REQ_DFU_GETSTATE:
353 handle_getstate(req);
355 case USB_REQ_DFU_DETACH:
357 * Proprietary extension: 'detach' from idle mode and
358 * get back to runtime mode in case of USB Reset. As
359 * much as I dislike this, we just can't use every USB
360 * bus reset to switch back to runtime mode, since at
361 * least the Linux USB stack likes to send a number of
365 DFU_STATE_dfuMANIFEST_WAIT_RST;
366 to_runtime_mode(f_dfu);
367 f_dfu->dfu_state = DFU_STATE_appIDLE;
369 g_dnl_trigger_detach();
372 f_dfu->dfu_state = DFU_STATE_dfuERROR;
380 static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
381 const struct usb_ctrlrequest *ctrl,
382 struct usb_gadget *gadget,
383 struct usb_request *req)
387 switch (ctrl->bRequest) {
388 case USB_REQ_DFU_GETSTATUS:
389 handle_getstatus(req);
390 value = RET_STAT_LEN;
392 case USB_REQ_DFU_GETSTATE:
393 handle_getstate(req);
396 f_dfu->dfu_state = DFU_STATE_dfuERROR;
404 static int state_dfu_dnbusy(struct f_dfu *f_dfu,
405 const struct usb_ctrlrequest *ctrl,
406 struct usb_gadget *gadget,
407 struct usb_request *req)
411 switch (ctrl->bRequest) {
412 case USB_REQ_DFU_GETSTATUS:
413 handle_getstatus(req);
414 value = RET_STAT_LEN;
417 f_dfu->dfu_state = DFU_STATE_dfuERROR;
425 static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
426 const struct usb_ctrlrequest *ctrl,
427 struct usb_gadget *gadget,
428 struct usb_request *req)
430 u16 w_value = le16_to_cpu(ctrl->wValue);
431 u16 len = le16_to_cpu(ctrl->wLength);
434 switch (ctrl->bRequest) {
435 case USB_REQ_DFU_DNLOAD:
436 f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
437 f_dfu->blk_seq_num = w_value;
438 value = handle_dnload(gadget, len);
440 case USB_REQ_DFU_ABORT:
441 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
444 case USB_REQ_DFU_GETSTATUS:
445 handle_getstatus(req);
446 value = RET_STAT_LEN;
448 case USB_REQ_DFU_GETSTATE:
449 handle_getstate(req);
452 f_dfu->dfu_state = DFU_STATE_dfuERROR;
460 static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
461 const struct usb_ctrlrequest *ctrl,
462 struct usb_gadget *gadget,
463 struct usb_request *req)
467 switch (ctrl->bRequest) {
468 case USB_REQ_DFU_GETSTATUS:
469 /* We're MainfestationTolerant */
470 f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
471 handle_getstatus(req);
472 f_dfu->blk_seq_num = 0;
473 value = RET_STAT_LEN;
474 req->complete = dnload_request_flush;
476 case USB_REQ_DFU_GETSTATE:
477 handle_getstate(req);
480 f_dfu->dfu_state = DFU_STATE_dfuERROR;
488 static int state_dfu_manifest(struct f_dfu *f_dfu,
489 const struct usb_ctrlrequest *ctrl,
490 struct usb_gadget *gadget,
491 struct usb_request *req)
495 switch (ctrl->bRequest) {
496 case USB_REQ_DFU_GETSTATUS:
497 /* We're MainfestationTolerant */
498 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
499 handle_getstatus(req);
500 f_dfu->blk_seq_num = 0;
501 value = RET_STAT_LEN;
502 puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
504 case USB_REQ_DFU_GETSTATE:
505 handle_getstate(req);
508 f_dfu->dfu_state = DFU_STATE_dfuERROR;
515 static int state_dfu_upload_idle(struct f_dfu *f_dfu,
516 const struct usb_ctrlrequest *ctrl,
517 struct usb_gadget *gadget,
518 struct usb_request *req)
520 u16 w_value = le16_to_cpu(ctrl->wValue);
521 u16 len = le16_to_cpu(ctrl->wLength);
524 switch (ctrl->bRequest) {
525 case USB_REQ_DFU_UPLOAD:
526 /* state transition if less data then requested */
527 f_dfu->blk_seq_num = w_value;
528 value = handle_upload(req, len);
529 if (value >= 0 && value < len)
530 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
532 case USB_REQ_DFU_ABORT:
533 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
537 case USB_REQ_DFU_GETSTATUS:
538 handle_getstatus(req);
539 value = RET_STAT_LEN;
541 case USB_REQ_DFU_GETSTATE:
542 handle_getstate(req);
545 f_dfu->dfu_state = DFU_STATE_dfuERROR;
553 static int state_dfu_error(struct f_dfu *f_dfu,
554 const struct usb_ctrlrequest *ctrl,
555 struct usb_gadget *gadget,
556 struct usb_request *req)
560 switch (ctrl->bRequest) {
561 case USB_REQ_DFU_GETSTATUS:
562 handle_getstatus(req);
563 value = RET_STAT_LEN;
565 case USB_REQ_DFU_GETSTATE:
566 handle_getstate(req);
568 case USB_REQ_DFU_CLRSTATUS:
569 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
570 f_dfu->dfu_status = DFU_STATUS_OK;
575 f_dfu->dfu_state = DFU_STATE_dfuERROR;
583 static dfu_state_fn dfu_state[] = {
584 state_app_idle, /* DFU_STATE_appIDLE */
585 state_app_detach, /* DFU_STATE_appDETACH */
586 state_dfu_idle, /* DFU_STATE_dfuIDLE */
587 state_dfu_dnload_sync, /* DFU_STATE_dfuDNLOAD_SYNC */
588 state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */
589 state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */
590 state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
591 state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */
592 NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */
593 state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */
594 state_dfu_error /* DFU_STATE_dfuERROR */
598 dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
600 struct usb_gadget *gadget = f->config->cdev->gadget;
601 struct usb_request *req = f->config->cdev->req;
602 struct f_dfu *f_dfu = f->config->cdev->req->context;
603 u16 len = le16_to_cpu(ctrl->wLength);
604 u16 w_value = le16_to_cpu(ctrl->wValue);
606 u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
608 debug("w_value: 0x%x len: 0x%x\n", w_value, len);
609 debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
610 req_type, ctrl->bRequest, f_dfu->dfu_state);
612 if (req_type == USB_TYPE_STANDARD) {
613 if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
614 (w_value >> 8) == DFU_DT_FUNC) {
615 value = min(len, (u16) sizeof(dfu_func));
616 memcpy(req->buf, &dfu_func, value);
618 } else /* DFU specific request */
619 value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
623 req->zero = value < len;
624 value = usb_ep_queue(gadget->ep0, req, 0);
626 debug("ep_queue --> %d\n", value);
634 /*-------------------------------------------------------------------------*/
637 dfu_prepare_strings(struct f_dfu *f_dfu, int n)
639 struct dfu_entity *de = NULL;
642 f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
646 for (i = 0; i < n; ++i) {
647 de = dfu_get_entity(i);
648 f_dfu->strings[i].s = de->name;
651 f_dfu->strings[i].id = 0;
652 f_dfu->strings[i].s = NULL;
658 f_dfu->strings[--i].s = NULL;
660 free(f_dfu->strings);
665 static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
667 struct usb_interface_descriptor *d;
670 f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1);
671 if (!f_dfu->function)
674 for (i = 0; i < n; ++i) {
675 d = calloc(sizeof(*d), 1);
679 d->bLength = sizeof(*d);
680 d->bDescriptorType = USB_DT_INTERFACE;
681 d->bAlternateSetting = i;
682 d->bNumEndpoints = 0;
683 d->bInterfaceClass = USB_CLASS_APP_SPEC;
684 d->bInterfaceSubClass = 1;
685 d->bInterfaceProtocol = 2;
687 f_dfu->function[i] = (struct usb_descriptor_header *)d;
689 f_dfu->function[i] = NULL;
695 free(f_dfu->function[--i]);
696 f_dfu->function[i] = NULL;
698 free(f_dfu->function);
703 static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
705 struct usb_composite_dev *cdev = c->cdev;
706 struct f_dfu *f_dfu = func_to_dfu(f);
707 int alt_num = dfu_get_alt_number();
710 id = usb_interface_id(c, f);
713 dfu_intf_runtime.bInterfaceNumber = id;
715 f_dfu->dfu_state = DFU_STATE_appIDLE;
716 f_dfu->dfu_status = DFU_STATUS_OK;
718 rv = dfu_prepare_function(f_dfu, alt_num);
722 rv = dfu_prepare_strings(f_dfu, alt_num);
725 for (i = 0; i < alt_num; i++) {
726 id = usb_string_id(cdev);
729 f_dfu->strings[i].id = id;
730 ((struct usb_interface_descriptor *)f_dfu->function[i])
736 stringtab_dfu.strings = f_dfu->strings;
738 cdev->req->context = f_dfu;
744 static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
746 struct f_dfu *f_dfu = func_to_dfu(f);
747 int alt_num = dfu_get_alt_number();
750 if (f_dfu->strings) {
753 f_dfu->strings[--i].s = NULL;
755 free(f_dfu->strings);
758 if (f_dfu->function) {
761 free(f_dfu->function[--i]);
762 f_dfu->function[i] = NULL;
764 free(f_dfu->function);
770 static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
772 struct f_dfu *f_dfu = func_to_dfu(f);
774 debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
776 f_dfu->altsetting = alt;
777 f_dfu->dfu_state = DFU_STATE_dfuIDLE;
778 f_dfu->dfu_status = DFU_STATUS_OK;
783 static int __dfu_get_alt(struct usb_function *f, unsigned intf)
785 struct f_dfu *f_dfu = func_to_dfu(f);
787 return f_dfu->altsetting;
790 /* TODO: is this really what we need here? */
791 static void dfu_disable(struct usb_function *f)
793 struct f_dfu *f_dfu = func_to_dfu(f);
794 if (f_dfu->config == 0)
797 debug("%s: reset config\n", __func__);
802 static int dfu_bind_config(struct usb_configuration *c)
807 f_dfu = calloc(sizeof(*f_dfu), 1);
810 f_dfu->usb_function.name = "dfu";
811 f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
812 f_dfu->usb_function.descriptors = dfu_runtime_descs;
813 f_dfu->usb_function.bind = dfu_bind;
814 f_dfu->usb_function.unbind = dfu_unbind;
815 f_dfu->usb_function.set_alt = dfu_set_alt;
816 f_dfu->usb_function.get_alt = __dfu_get_alt;
817 f_dfu->usb_function.disable = dfu_disable;
818 f_dfu->usb_function.strings = dfu_generic_strings;
819 f_dfu->usb_function.setup = dfu_handle;
820 f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT;
822 status = usb_add_function(c, &f_dfu->usb_function);
829 int dfu_add(struct usb_configuration *c)
833 id = usb_string_id(c->cdev);
836 strings_dfu_generic[0].id = id;
837 dfu_intf_runtime.iInterface = id;
839 debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
840 c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
842 return dfu_bind_config(c);
845 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add);