2 * f_dfu.c -- Device Firmware Update USB function
4 * Copyright (C) 2012 Samsung Electronics
5 * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
6 * Lukasz Majewski <l.majewski@samsung.com>
8 * Based on OpenMoko u-boot: drivers/usb/usbdfu.c
9 * (C) 2007 by OpenMoko, Inc.
10 * Author: Harald Welte <laforge@openmoko.org>
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>
30 struct usb_function usb_function
;
32 struct usb_descriptor_header
**function
;
33 struct usb_string
*strings
;
35 /* when configured, we have one config */
38 enum dfu_state dfu_state
;
39 unsigned int dfu_status
;
41 /* Send/received block number is handy for data integrity check */
43 unsigned int poll_timeout
;
46 typedef int (*dfu_state_fn
) (struct f_dfu
*,
47 const struct usb_ctrlrequest
*,
49 struct usb_request
*);
51 static inline struct f_dfu
*func_to_dfu(struct usb_function
*f
)
53 return container_of(f
, struct f_dfu
, usb_function
);
56 static const struct dfu_function_descriptor dfu_func
= {
57 .bLength
= sizeof dfu_func
,
58 .bDescriptorType
= DFU_DT_FUNC
,
59 .bmAttributes
= DFU_BIT_WILL_DETACH
|
60 DFU_BIT_MANIFESTATION_TOLERANT
|
64 .wTransferSize
= DFU_USB_BUFSIZ
,
65 .bcdDFUVersion
= __constant_cpu_to_le16(0x0110),
68 static struct usb_interface_descriptor dfu_intf_runtime
= {
69 .bLength
= sizeof dfu_intf_runtime
,
70 .bDescriptorType
= USB_DT_INTERFACE
,
72 .bInterfaceClass
= USB_CLASS_APP_SPEC
,
73 .bInterfaceSubClass
= 1,
74 .bInterfaceProtocol
= 1,
75 /* .iInterface = DYNAMIC */
78 static struct usb_descriptor_header
*dfu_runtime_descs
[] = {
79 (struct usb_descriptor_header
*) &dfu_intf_runtime
,
83 static const struct usb_qualifier_descriptor dev_qualifier
= {
84 .bLength
= sizeof dev_qualifier
,
85 .bDescriptorType
= USB_DT_DEVICE_QUALIFIER
,
86 .bcdUSB
= __constant_cpu_to_le16(0x0200),
87 .bDeviceClass
= USB_CLASS_VENDOR_SPEC
,
88 .bNumConfigurations
= 1,
91 static const char dfu_name
[] = "Device Firmware Upgrade";
94 * static strings, in UTF-8
96 * dfu_generic configuration
98 static struct usb_string strings_dfu_generic
[] = {
100 { } /* end of list */
103 static struct usb_gadget_strings stringtab_dfu_generic
= {
104 .language
= 0x0409, /* en-us */
105 .strings
= strings_dfu_generic
,
108 static struct usb_gadget_strings
*dfu_generic_strings
[] = {
109 &stringtab_dfu_generic
,
114 * usb_function specific
116 static struct usb_gadget_strings stringtab_dfu
= {
117 .language
= 0x0409, /* en-us */
121 * assigned during initialization,
122 * depends on number of flash entities
127 static struct usb_gadget_strings
*dfu_strings
[] = {
132 static void dfu_set_poll_timeout(struct dfu_status
*dstat
, unsigned int ms
)
135 * The bwPollTimeout DFU_GETSTATUS request payload provides information
136 * about minimum time, in milliseconds, that the host should wait before
137 * sending a subsequent DFU_GETSTATUS request
139 * This permits the device to vary the delay depending on its need to
140 * erase or program the memory
144 unsigned char *p
= (unsigned char *)&ms
;
146 if (!ms
|| (ms
& ~DFU_POLL_TIMEOUT_MASK
)) {
147 dstat
->bwPollTimeout
[0] = 0;
148 dstat
->bwPollTimeout
[1] = 0;
149 dstat
->bwPollTimeout
[2] = 0;
154 dstat
->bwPollTimeout
[0] = *p
++;
155 dstat
->bwPollTimeout
[1] = *p
++;
156 dstat
->bwPollTimeout
[2] = *p
;
159 /*-------------------------------------------------------------------------*/
161 static void dnload_request_complete(struct usb_ep
*ep
, struct usb_request
*req
)
163 struct f_dfu
*f_dfu
= req
->context
;
165 dfu_write(dfu_get_entity(f_dfu
->altsetting
), req
->buf
,
166 req
->length
, f_dfu
->blk_seq_num
);
168 if (req
->length
== 0)
169 puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
172 static void handle_getstatus(struct usb_request
*req
)
174 struct dfu_status
*dstat
= (struct dfu_status
*)req
->buf
;
175 struct f_dfu
*f_dfu
= req
->context
;
177 switch (f_dfu
->dfu_state
) {
178 case DFU_STATE_dfuDNLOAD_SYNC
:
179 case DFU_STATE_dfuDNBUSY
:
180 f_dfu
->dfu_state
= DFU_STATE_dfuDNLOAD_IDLE
;
182 case DFU_STATE_dfuMANIFEST_SYNC
:
188 dfu_set_poll_timeout(dstat
, 0);
190 if (f_dfu
->poll_timeout
)
191 if (!(f_dfu
->blk_seq_num
%
192 (dfu_get_buf_size() / DFU_USB_BUFSIZ
)))
193 dfu_set_poll_timeout(dstat
, f_dfu
->poll_timeout
);
195 /* send status response */
196 dstat
->bStatus
= f_dfu
->dfu_status
;
197 dstat
->bState
= f_dfu
->dfu_state
;
201 static void handle_getstate(struct usb_request
*req
)
203 struct f_dfu
*f_dfu
= req
->context
;
205 ((u8
*)req
->buf
)[0] = f_dfu
->dfu_state
;
206 req
->actual
= sizeof(u8
);
209 static inline void to_dfu_mode(struct f_dfu
*f_dfu
)
211 f_dfu
->usb_function
.strings
= dfu_strings
;
212 f_dfu
->usb_function
.hs_descriptors
= f_dfu
->function
;
213 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
216 static inline void to_runtime_mode(struct f_dfu
*f_dfu
)
218 f_dfu
->usb_function
.strings
= NULL
;
219 f_dfu
->usb_function
.hs_descriptors
= dfu_runtime_descs
;
222 static int handle_upload(struct usb_request
*req
, u16 len
)
224 struct f_dfu
*f_dfu
= req
->context
;
226 return dfu_read(dfu_get_entity(f_dfu
->altsetting
), req
->buf
,
227 req
->length
, f_dfu
->blk_seq_num
);
230 static int handle_dnload(struct usb_gadget
*gadget
, u16 len
)
232 struct usb_composite_dev
*cdev
= get_gadget_data(gadget
);
233 struct usb_request
*req
= cdev
->req
;
234 struct f_dfu
*f_dfu
= req
->context
;
237 f_dfu
->dfu_state
= DFU_STATE_dfuMANIFEST_SYNC
;
239 req
->complete
= dnload_request_complete
;
244 /*-------------------------------------------------------------------------*/
245 /* DFU state machine */
246 static int state_app_idle(struct f_dfu
*f_dfu
,
247 const struct usb_ctrlrequest
*ctrl
,
248 struct usb_gadget
*gadget
,
249 struct usb_request
*req
)
253 switch (ctrl
->bRequest
) {
254 case USB_REQ_DFU_GETSTATUS
:
255 handle_getstatus(req
);
256 value
= RET_STAT_LEN
;
258 case USB_REQ_DFU_GETSTATE
:
259 handle_getstate(req
);
261 case USB_REQ_DFU_DETACH
:
262 f_dfu
->dfu_state
= DFU_STATE_appDETACH
;
274 static int state_app_detach(struct f_dfu
*f_dfu
,
275 const struct usb_ctrlrequest
*ctrl
,
276 struct usb_gadget
*gadget
,
277 struct usb_request
*req
)
281 switch (ctrl
->bRequest
) {
282 case USB_REQ_DFU_GETSTATUS
:
283 handle_getstatus(req
);
284 value
= RET_STAT_LEN
;
286 case USB_REQ_DFU_GETSTATE
:
287 handle_getstate(req
);
290 f_dfu
->dfu_state
= DFU_STATE_appIDLE
;
298 static int state_dfu_idle(struct f_dfu
*f_dfu
,
299 const struct usb_ctrlrequest
*ctrl
,
300 struct usb_gadget
*gadget
,
301 struct usb_request
*req
)
303 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
304 u16 len
= le16_to_cpu(ctrl
->wLength
);
307 switch (ctrl
->bRequest
) {
308 case USB_REQ_DFU_DNLOAD
:
310 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
314 f_dfu
->dfu_state
= DFU_STATE_dfuDNLOAD_SYNC
;
315 f_dfu
->blk_seq_num
= w_value
;
316 value
= handle_dnload(gadget
, len
);
318 case USB_REQ_DFU_UPLOAD
:
319 f_dfu
->dfu_state
= DFU_STATE_dfuUPLOAD_IDLE
;
320 f_dfu
->blk_seq_num
= 0;
321 value
= handle_upload(req
, len
);
323 case USB_REQ_DFU_ABORT
:
327 case USB_REQ_DFU_GETSTATUS
:
328 handle_getstatus(req
);
329 value
= RET_STAT_LEN
;
331 case USB_REQ_DFU_GETSTATE
:
332 handle_getstate(req
);
334 case USB_REQ_DFU_DETACH
:
336 * Proprietary extension: 'detach' from idle mode and
337 * get back to runtime mode in case of USB Reset. As
338 * much as I dislike this, we just can't use every USB
339 * bus reset to switch back to runtime mode, since at
340 * least the Linux USB stack likes to send a number of
344 DFU_STATE_dfuMANIFEST_WAIT_RST
;
345 to_runtime_mode(f_dfu
);
346 f_dfu
->dfu_state
= DFU_STATE_appIDLE
;
351 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
359 static int state_dfu_dnload_sync(struct f_dfu
*f_dfu
,
360 const struct usb_ctrlrequest
*ctrl
,
361 struct usb_gadget
*gadget
,
362 struct usb_request
*req
)
366 switch (ctrl
->bRequest
) {
367 case USB_REQ_DFU_GETSTATUS
:
368 handle_getstatus(req
);
369 value
= RET_STAT_LEN
;
371 case USB_REQ_DFU_GETSTATE
:
372 handle_getstate(req
);
375 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
383 static int state_dfu_dnbusy(struct f_dfu
*f_dfu
,
384 const struct usb_ctrlrequest
*ctrl
,
385 struct usb_gadget
*gadget
,
386 struct usb_request
*req
)
390 switch (ctrl
->bRequest
) {
391 case USB_REQ_DFU_GETSTATUS
:
392 handle_getstatus(req
);
393 value
= RET_STAT_LEN
;
396 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
404 static int state_dfu_dnload_idle(struct f_dfu
*f_dfu
,
405 const struct usb_ctrlrequest
*ctrl
,
406 struct usb_gadget
*gadget
,
407 struct usb_request
*req
)
409 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
410 u16 len
= le16_to_cpu(ctrl
->wLength
);
413 switch (ctrl
->bRequest
) {
414 case USB_REQ_DFU_DNLOAD
:
415 f_dfu
->dfu_state
= DFU_STATE_dfuDNLOAD_SYNC
;
416 f_dfu
->blk_seq_num
= w_value
;
417 value
= handle_dnload(gadget
, len
);
419 case USB_REQ_DFU_ABORT
:
420 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
423 case USB_REQ_DFU_GETSTATUS
:
424 handle_getstatus(req
);
425 value
= RET_STAT_LEN
;
427 case USB_REQ_DFU_GETSTATE
:
428 handle_getstate(req
);
431 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
439 static int state_dfu_manifest_sync(struct f_dfu
*f_dfu
,
440 const struct usb_ctrlrequest
*ctrl
,
441 struct usb_gadget
*gadget
,
442 struct usb_request
*req
)
446 switch (ctrl
->bRequest
) {
447 case USB_REQ_DFU_GETSTATUS
:
448 /* We're MainfestationTolerant */
449 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
450 handle_getstatus(req
);
451 f_dfu
->blk_seq_num
= 0;
452 value
= RET_STAT_LEN
;
454 case USB_REQ_DFU_GETSTATE
:
455 handle_getstate(req
);
458 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
466 static int state_dfu_upload_idle(struct f_dfu
*f_dfu
,
467 const struct usb_ctrlrequest
*ctrl
,
468 struct usb_gadget
*gadget
,
469 struct usb_request
*req
)
471 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
472 u16 len
= le16_to_cpu(ctrl
->wLength
);
475 switch (ctrl
->bRequest
) {
476 case USB_REQ_DFU_UPLOAD
:
477 /* state transition if less data then requested */
478 f_dfu
->blk_seq_num
= w_value
;
479 value
= handle_upload(req
, len
);
480 if (value
>= 0 && value
< len
)
481 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
483 case USB_REQ_DFU_ABORT
:
484 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
488 case USB_REQ_DFU_GETSTATUS
:
489 handle_getstatus(req
);
490 value
= RET_STAT_LEN
;
492 case USB_REQ_DFU_GETSTATE
:
493 handle_getstate(req
);
496 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
504 static int state_dfu_error(struct f_dfu
*f_dfu
,
505 const struct usb_ctrlrequest
*ctrl
,
506 struct usb_gadget
*gadget
,
507 struct usb_request
*req
)
511 switch (ctrl
->bRequest
) {
512 case USB_REQ_DFU_GETSTATUS
:
513 handle_getstatus(req
);
514 value
= RET_STAT_LEN
;
516 case USB_REQ_DFU_GETSTATE
:
517 handle_getstate(req
);
519 case USB_REQ_DFU_CLRSTATUS
:
520 f_dfu
->dfu_state
= DFU_STATE_dfuIDLE
;
521 f_dfu
->dfu_status
= DFU_STATUS_OK
;
526 f_dfu
->dfu_state
= DFU_STATE_dfuERROR
;
534 static dfu_state_fn dfu_state
[] = {
535 state_app_idle
, /* DFU_STATE_appIDLE */
536 state_app_detach
, /* DFU_STATE_appDETACH */
537 state_dfu_idle
, /* DFU_STATE_dfuIDLE */
538 state_dfu_dnload_sync
, /* DFU_STATE_dfuDNLOAD_SYNC */
539 state_dfu_dnbusy
, /* DFU_STATE_dfuDNBUSY */
540 state_dfu_dnload_idle
, /* DFU_STATE_dfuDNLOAD_IDLE */
541 state_dfu_manifest_sync
, /* DFU_STATE_dfuMANIFEST_SYNC */
542 NULL
, /* DFU_STATE_dfuMANIFEST */
543 NULL
, /* DFU_STATE_dfuMANIFEST_WAIT_RST */
544 state_dfu_upload_idle
, /* DFU_STATE_dfuUPLOAD_IDLE */
545 state_dfu_error
/* DFU_STATE_dfuERROR */
549 dfu_handle(struct usb_function
*f
, const struct usb_ctrlrequest
*ctrl
)
551 struct usb_gadget
*gadget
= f
->config
->cdev
->gadget
;
552 struct usb_request
*req
= f
->config
->cdev
->req
;
553 struct f_dfu
*f_dfu
= f
->config
->cdev
->req
->context
;
554 u16 len
= le16_to_cpu(ctrl
->wLength
);
555 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
557 u8 req_type
= ctrl
->bRequestType
& USB_TYPE_MASK
;
559 debug("w_value: 0x%x len: 0x%x\n", w_value
, len
);
560 debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
561 req_type
, ctrl
->bRequest
, f_dfu
->dfu_state
);
563 if (req_type
== USB_TYPE_STANDARD
) {
564 if (ctrl
->bRequest
== USB_REQ_GET_DESCRIPTOR
&&
565 (w_value
>> 8) == DFU_DT_FUNC
) {
566 value
= min(len
, (u16
) sizeof(dfu_func
));
567 memcpy(req
->buf
, &dfu_func
, value
);
569 } else /* DFU specific request */
570 value
= dfu_state
[f_dfu
->dfu_state
] (f_dfu
, ctrl
, gadget
, req
);
574 req
->zero
= value
< len
;
575 value
= usb_ep_queue(gadget
->ep0
, req
, 0);
577 debug("ep_queue --> %d\n", value
);
585 /*-------------------------------------------------------------------------*/
588 dfu_prepare_strings(struct f_dfu
*f_dfu
, int n
)
590 struct dfu_entity
*de
= NULL
;
593 f_dfu
->strings
= calloc(sizeof(struct usb_string
), n
+ 1);
597 for (i
= 0; i
< n
; ++i
) {
598 de
= dfu_get_entity(i
);
599 f_dfu
->strings
[i
].s
= de
->name
;
602 f_dfu
->strings
[i
].id
= 0;
603 f_dfu
->strings
[i
].s
= NULL
;
609 f_dfu
->strings
[--i
].s
= NULL
;
611 free(f_dfu
->strings
);
616 static int dfu_prepare_function(struct f_dfu
*f_dfu
, int n
)
618 struct usb_interface_descriptor
*d
;
621 f_dfu
->function
= calloc(sizeof(struct usb_descriptor_header
*), n
+ 1);
622 if (!f_dfu
->function
)
625 for (i
= 0; i
< n
; ++i
) {
626 d
= calloc(sizeof(*d
), 1);
630 d
->bLength
= sizeof(*d
);
631 d
->bDescriptorType
= USB_DT_INTERFACE
;
632 d
->bAlternateSetting
= i
;
633 d
->bNumEndpoints
= 0;
634 d
->bInterfaceClass
= USB_CLASS_APP_SPEC
;
635 d
->bInterfaceSubClass
= 1;
636 d
->bInterfaceProtocol
= 2;
638 f_dfu
->function
[i
] = (struct usb_descriptor_header
*)d
;
640 f_dfu
->function
[i
] = NULL
;
646 free(f_dfu
->function
[--i
]);
647 f_dfu
->function
[i
] = NULL
;
649 free(f_dfu
->function
);
654 static int dfu_bind(struct usb_configuration
*c
, struct usb_function
*f
)
656 struct usb_composite_dev
*cdev
= c
->cdev
;
657 struct f_dfu
*f_dfu
= func_to_dfu(f
);
658 int alt_num
= dfu_get_alt_number();
661 id
= usb_interface_id(c
, f
);
664 dfu_intf_runtime
.bInterfaceNumber
= id
;
666 f_dfu
->dfu_state
= DFU_STATE_appIDLE
;
667 f_dfu
->dfu_status
= DFU_STATUS_OK
;
669 rv
= dfu_prepare_function(f_dfu
, alt_num
);
673 rv
= dfu_prepare_strings(f_dfu
, alt_num
);
676 for (i
= 0; i
< alt_num
; i
++) {
677 id
= usb_string_id(cdev
);
680 f_dfu
->strings
[i
].id
= id
;
681 ((struct usb_interface_descriptor
*)f_dfu
->function
[i
])
687 stringtab_dfu
.strings
= f_dfu
->strings
;
689 cdev
->req
->context
= f_dfu
;
695 static void dfu_unbind(struct usb_configuration
*c
, struct usb_function
*f
)
697 struct f_dfu
*f_dfu
= func_to_dfu(f
);
698 int alt_num
= dfu_get_alt_number();
701 if (f_dfu
->strings
) {
704 f_dfu
->strings
[--i
].s
= NULL
;
706 free(f_dfu
->strings
);
709 if (f_dfu
->function
) {
712 free(f_dfu
->function
[--i
]);
713 f_dfu
->function
[i
] = NULL
;
715 free(f_dfu
->function
);
721 static int dfu_set_alt(struct usb_function
*f
, unsigned intf
, unsigned alt
)
723 struct f_dfu
*f_dfu
= func_to_dfu(f
);
725 debug("%s: intf:%d alt:%d\n", __func__
, intf
, alt
);
727 f_dfu
->altsetting
= alt
;
732 /* TODO: is this really what we need here? */
733 static void dfu_disable(struct usb_function
*f
)
735 struct f_dfu
*f_dfu
= func_to_dfu(f
);
736 if (f_dfu
->config
== 0)
739 debug("%s: reset config\n", __func__
);
744 static int dfu_bind_config(struct usb_configuration
*c
)
749 f_dfu
= calloc(sizeof(*f_dfu
), 1);
752 f_dfu
->usb_function
.name
= "dfu";
753 f_dfu
->usb_function
.hs_descriptors
= dfu_runtime_descs
;
754 f_dfu
->usb_function
.bind
= dfu_bind
;
755 f_dfu
->usb_function
.unbind
= dfu_unbind
;
756 f_dfu
->usb_function
.set_alt
= dfu_set_alt
;
757 f_dfu
->usb_function
.disable
= dfu_disable
;
758 f_dfu
->usb_function
.strings
= dfu_generic_strings
;
759 f_dfu
->usb_function
.setup
= dfu_handle
;
760 f_dfu
->poll_timeout
= DFU_DEFAULT_POLL_TIMEOUT
;
762 status
= usb_add_function(c
, &f_dfu
->usb_function
);
769 int dfu_add(struct usb_configuration
*c
)
773 id
= usb_string_id(c
->cdev
);
776 strings_dfu_generic
[0].id
= id
;
777 dfu_intf_runtime
.iInterface
= id
;
779 debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__
,
780 c
->cdev
, c
->cdev
->gadget
, c
->cdev
->gadget
->ep0
);
782 return dfu_bind_config(c
);