xref: /rk3399_rockchip-uboot/drivers/usb/gadget/f_dfu.c (revision b9c99d32466b90aa2269eca99545f045a23266ab)
1 /*
2  * f_dfu.c -- Device Firmware Update USB function
3  *
4  * Copyright (C) 2012 Samsung Electronics
5  * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
6  *          Lukasz Majewski <l.majewski@samsung.com>
7  *
8  * Based on OpenMoko u-boot: drivers/usb/usbdfu.c
9  * (C) 2007 by OpenMoko, Inc.
10  * Author: Harald Welte <laforge@openmoko.org>
11  *
12  * based on existing SAM7DFU code from OpenPCD:
13  * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de>
14  *
15  * SPDX-License-Identifier:	GPL-2.0+
16  */
17 
18 #include <errno.h>
19 #include <common.h>
20 #include <malloc.h>
21 
22 #include <linux/usb/ch9.h>
23 #include <linux/usb/gadget.h>
24 #include <linux/usb/composite.h>
25 
26 #include <dfu.h>
27 #include <g_dnl.h>
28 #include "f_dfu.h"
29 
30 struct f_dfu {
31 	struct usb_function		usb_function;
32 
33 	struct usb_descriptor_header	**function;
34 	struct usb_string		*strings;
35 
36 	/* when configured, we have one config */
37 	u8				config;
38 	u8				altsetting;
39 	enum dfu_state			dfu_state;
40 	unsigned int			dfu_status;
41 
42 	/* Send/received block number is handy for data integrity check */
43 	int                             blk_seq_num;
44 	unsigned int                    poll_timeout;
45 };
46 
47 typedef int (*dfu_state_fn) (struct f_dfu *,
48 			     const struct usb_ctrlrequest *,
49 			     struct usb_gadget *,
50 			     struct usb_request *);
51 
52 static inline struct f_dfu *func_to_dfu(struct usb_function *f)
53 {
54 	return container_of(f, struct f_dfu, usb_function);
55 }
56 
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 |
62 				DFU_BIT_CAN_UPLOAD |
63 				DFU_BIT_CAN_DNLOAD,
64 	.wDetachTimeOut =	0,
65 	.wTransferSize =	DFU_USB_BUFSIZ,
66 	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
67 };
68 
69 static struct usb_interface_descriptor dfu_intf_runtime = {
70 	.bLength =		sizeof dfu_intf_runtime,
71 	.bDescriptorType =	USB_DT_INTERFACE,
72 	.bNumEndpoints =	0,
73 	.bInterfaceClass =	USB_CLASS_APP_SPEC,
74 	.bInterfaceSubClass =	1,
75 	.bInterfaceProtocol =	1,
76 	/* .iInterface = DYNAMIC */
77 };
78 
79 static struct usb_descriptor_header *dfu_runtime_descs[] = {
80 	(struct usb_descriptor_header *) &dfu_intf_runtime,
81 	NULL,
82 };
83 
84 static const char dfu_name[] = "Device Firmware Upgrade";
85 
86 /*
87  * static strings, in UTF-8
88  *
89  * dfu_generic configuration
90  */
91 static struct usb_string strings_dfu_generic[] = {
92 	[0].s = dfu_name,
93 	{  }			/* end of list */
94 };
95 
96 static struct usb_gadget_strings stringtab_dfu_generic = {
97 	.language	= 0x0409,	/* en-us */
98 	.strings	= strings_dfu_generic,
99 };
100 
101 static struct usb_gadget_strings *dfu_generic_strings[] = {
102 	&stringtab_dfu_generic,
103 	NULL,
104 };
105 
106 /*
107  * usb_function specific
108  */
109 static struct usb_gadget_strings stringtab_dfu = {
110 	.language	= 0x0409,	/* en-us */
111 	/*
112 	 * .strings
113 	 *
114 	 * assigned during initialization,
115 	 * depends on number of flash entities
116 	 *
117 	 */
118 };
119 
120 static struct usb_gadget_strings *dfu_strings[] = {
121 	&stringtab_dfu,
122 	NULL,
123 };
124 
125 static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms)
126 {
127 	/*
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
131 	 *
132 	 * This permits the device to vary the delay depending on its need to
133 	 * erase or program the memory
134 	 *
135 	 */
136 
137 	unsigned char *p = (unsigned char *)&ms;
138 
139 	if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) {
140 		dstat->bwPollTimeout[0] = 0;
141 		dstat->bwPollTimeout[1] = 0;
142 		dstat->bwPollTimeout[2] = 0;
143 
144 		return;
145 	}
146 
147 	dstat->bwPollTimeout[0] = *p++;
148 	dstat->bwPollTimeout[1] = *p++;
149 	dstat->bwPollTimeout[2] = *p;
150 }
151 
152 /*-------------------------------------------------------------------------*/
153 
154 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
155 {
156 	struct f_dfu *f_dfu = req->context;
157 	int ret;
158 
159 	ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
160 			req->length, f_dfu->blk_seq_num);
161 	if (ret) {
162 		f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
163 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
164 	}
165 }
166 
167 static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
168 {
169 	struct f_dfu *f_dfu = req->context;
170 	int ret;
171 
172 	ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
173 			req->length, f_dfu->blk_seq_num);
174 	if (ret) {
175 		f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
176 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
177 	}
178 }
179 
180 static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu)
181 {
182 	return dfu->poll_timeout ? dfu->poll_timeout(dfu) :
183 		DFU_MANIFEST_POLL_TIMEOUT;
184 }
185 
186 static void handle_getstatus(struct usb_request *req)
187 {
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);
191 
192 	dfu_set_poll_timeout(dstat, 0);
193 
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;
198 		break;
199 	case DFU_STATE_dfuMANIFEST_SYNC:
200 		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
201 		break;
202 	case DFU_STATE_dfuMANIFEST:
203 		dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu));
204 		break;
205 	default:
206 		break;
207 	}
208 
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);
213 
214 	/* send status response */
215 	dstat->bStatus = f_dfu->dfu_status;
216 	dstat->bState = f_dfu->dfu_state;
217 	dstat->iString = 0;
218 }
219 
220 static void handle_getstate(struct usb_request *req)
221 {
222 	struct f_dfu *f_dfu = req->context;
223 
224 	((u8 *)req->buf)[0] = f_dfu->dfu_state;
225 	req->actual = sizeof(u8);
226 }
227 
228 static inline void to_dfu_mode(struct f_dfu *f_dfu)
229 {
230 	f_dfu->usb_function.strings = dfu_strings;
231 	f_dfu->usb_function.hs_descriptors = f_dfu->function;
232 	f_dfu->dfu_state = DFU_STATE_dfuIDLE;
233 }
234 
235 static inline void to_runtime_mode(struct f_dfu *f_dfu)
236 {
237 	f_dfu->usb_function.strings = NULL;
238 	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
239 }
240 
241 static int handle_upload(struct usb_request *req, u16 len)
242 {
243 	struct f_dfu *f_dfu = req->context;
244 
245 	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
246 			req->length, f_dfu->blk_seq_num);
247 }
248 
249 static int handle_dnload(struct usb_gadget *gadget, u16 len)
250 {
251 	struct usb_composite_dev *cdev = get_gadget_data(gadget);
252 	struct usb_request *req = cdev->req;
253 	struct f_dfu *f_dfu = req->context;
254 
255 	if (len == 0)
256 		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
257 
258 	req->complete = dnload_request_complete;
259 
260 	return len;
261 }
262 
263 /*-------------------------------------------------------------------------*/
264 /* DFU state machine  */
265 static int state_app_idle(struct f_dfu *f_dfu,
266 			  const struct usb_ctrlrequest *ctrl,
267 			  struct usb_gadget *gadget,
268 			  struct usb_request *req)
269 {
270 	int value = 0;
271 
272 	switch (ctrl->bRequest) {
273 	case USB_REQ_DFU_GETSTATUS:
274 		handle_getstatus(req);
275 		value = RET_STAT_LEN;
276 		break;
277 	case USB_REQ_DFU_GETSTATE:
278 		handle_getstate(req);
279 		break;
280 	case USB_REQ_DFU_DETACH:
281 		f_dfu->dfu_state = DFU_STATE_appDETACH;
282 		to_dfu_mode(f_dfu);
283 		value = RET_ZLP;
284 		break;
285 	default:
286 		value = RET_STALL;
287 		break;
288 	}
289 
290 	return value;
291 }
292 
293 static int state_app_detach(struct f_dfu *f_dfu,
294 			    const struct usb_ctrlrequest *ctrl,
295 			    struct usb_gadget *gadget,
296 			    struct usb_request *req)
297 {
298 	int value = 0;
299 
300 	switch (ctrl->bRequest) {
301 	case USB_REQ_DFU_GETSTATUS:
302 		handle_getstatus(req);
303 		value = RET_STAT_LEN;
304 		break;
305 	case USB_REQ_DFU_GETSTATE:
306 		handle_getstate(req);
307 		break;
308 	default:
309 		f_dfu->dfu_state = DFU_STATE_appIDLE;
310 		value = RET_STALL;
311 		break;
312 	}
313 
314 	return value;
315 }
316 
317 static int state_dfu_idle(struct f_dfu *f_dfu,
318 			  const struct usb_ctrlrequest *ctrl,
319 			  struct usb_gadget *gadget,
320 			  struct usb_request *req)
321 {
322 	u16 w_value = le16_to_cpu(ctrl->wValue);
323 	u16 len = le16_to_cpu(ctrl->wLength);
324 	int value = 0;
325 
326 	switch (ctrl->bRequest) {
327 	case USB_REQ_DFU_DNLOAD:
328 		if (len == 0) {
329 			f_dfu->dfu_state = DFU_STATE_dfuERROR;
330 			value = RET_STALL;
331 			break;
332 		}
333 		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
334 		f_dfu->blk_seq_num = w_value;
335 		value = handle_dnload(gadget, len);
336 		break;
337 	case USB_REQ_DFU_UPLOAD:
338 		f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
339 		f_dfu->blk_seq_num = 0;
340 		value = handle_upload(req, len);
341 		break;
342 	case USB_REQ_DFU_ABORT:
343 		/* no zlp? */
344 		value = RET_ZLP;
345 		break;
346 	case USB_REQ_DFU_GETSTATUS:
347 		handle_getstatus(req);
348 		value = RET_STAT_LEN;
349 		break;
350 	case USB_REQ_DFU_GETSTATE:
351 		handle_getstate(req);
352 		break;
353 	case USB_REQ_DFU_DETACH:
354 		/*
355 		 * Proprietary extension: 'detach' from idle mode and
356 		 * get back to runtime mode in case of USB Reset.  As
357 		 * much as I dislike this, we just can't use every USB
358 		 * bus reset to switch back to runtime mode, since at
359 		 * least the Linux USB stack likes to send a number of
360 		 * resets in a row :(
361 		 */
362 		f_dfu->dfu_state =
363 			DFU_STATE_dfuMANIFEST_WAIT_RST;
364 		to_runtime_mode(f_dfu);
365 		f_dfu->dfu_state = DFU_STATE_appIDLE;
366 
367 		dfu_trigger_detach();
368 		break;
369 	default:
370 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
371 		value = RET_STALL;
372 		break;
373 	}
374 
375 	return value;
376 }
377 
378 static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
379 				 const struct usb_ctrlrequest *ctrl,
380 				 struct usb_gadget *gadget,
381 				 struct usb_request *req)
382 {
383 	int value = 0;
384 
385 	switch (ctrl->bRequest) {
386 	case USB_REQ_DFU_GETSTATUS:
387 		handle_getstatus(req);
388 		value = RET_STAT_LEN;
389 		break;
390 	case USB_REQ_DFU_GETSTATE:
391 		handle_getstate(req);
392 		break;
393 	default:
394 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
395 		value = RET_STALL;
396 		break;
397 	}
398 
399 	return value;
400 }
401 
402 static int state_dfu_dnbusy(struct f_dfu *f_dfu,
403 			    const struct usb_ctrlrequest *ctrl,
404 			    struct usb_gadget *gadget,
405 			    struct usb_request *req)
406 {
407 	int value = 0;
408 
409 	switch (ctrl->bRequest) {
410 	case USB_REQ_DFU_GETSTATUS:
411 		handle_getstatus(req);
412 		value = RET_STAT_LEN;
413 		break;
414 	default:
415 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
416 		value = RET_STALL;
417 		break;
418 	}
419 
420 	return value;
421 }
422 
423 static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
424 				 const struct usb_ctrlrequest *ctrl,
425 				 struct usb_gadget *gadget,
426 				 struct usb_request *req)
427 {
428 	u16 w_value = le16_to_cpu(ctrl->wValue);
429 	u16 len = le16_to_cpu(ctrl->wLength);
430 	int value = 0;
431 
432 	switch (ctrl->bRequest) {
433 	case USB_REQ_DFU_DNLOAD:
434 		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
435 		f_dfu->blk_seq_num = w_value;
436 		value = handle_dnload(gadget, len);
437 		break;
438 	case USB_REQ_DFU_ABORT:
439 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
440 		value = RET_ZLP;
441 		break;
442 	case USB_REQ_DFU_GETSTATUS:
443 		handle_getstatus(req);
444 		value = RET_STAT_LEN;
445 		break;
446 	case USB_REQ_DFU_GETSTATE:
447 		handle_getstate(req);
448 		break;
449 	default:
450 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
451 		value = RET_STALL;
452 		break;
453 	}
454 
455 	return value;
456 }
457 
458 static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
459 				   const struct usb_ctrlrequest *ctrl,
460 				   struct usb_gadget *gadget,
461 				   struct usb_request *req)
462 {
463 	int value = 0;
464 
465 	switch (ctrl->bRequest) {
466 	case USB_REQ_DFU_GETSTATUS:
467 		/* We're MainfestationTolerant */
468 		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
469 		handle_getstatus(req);
470 		f_dfu->blk_seq_num = 0;
471 		value = RET_STAT_LEN;
472 		req->complete = dnload_request_flush;
473 		break;
474 	case USB_REQ_DFU_GETSTATE:
475 		handle_getstate(req);
476 		break;
477 	default:
478 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
479 		value = RET_STALL;
480 		break;
481 	}
482 
483 	return value;
484 }
485 
486 static int state_dfu_manifest(struct f_dfu *f_dfu,
487 			      const struct usb_ctrlrequest *ctrl,
488 			      struct usb_gadget *gadget,
489 			      struct usb_request *req)
490 {
491 	int value = 0;
492 
493 	switch (ctrl->bRequest) {
494 	case USB_REQ_DFU_GETSTATUS:
495 		/* We're MainfestationTolerant */
496 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
497 		handle_getstatus(req);
498 		f_dfu->blk_seq_num = 0;
499 		value = RET_STAT_LEN;
500 		puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
501 		break;
502 	case USB_REQ_DFU_GETSTATE:
503 		handle_getstate(req);
504 		break;
505 	default:
506 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
507 		value = RET_STALL;
508 		break;
509 	}
510 	return value;
511 }
512 
513 static int state_dfu_upload_idle(struct f_dfu *f_dfu,
514 				 const struct usb_ctrlrequest *ctrl,
515 				 struct usb_gadget *gadget,
516 				 struct usb_request *req)
517 {
518 	u16 w_value = le16_to_cpu(ctrl->wValue);
519 	u16 len = le16_to_cpu(ctrl->wLength);
520 	int value = 0;
521 
522 	switch (ctrl->bRequest) {
523 	case USB_REQ_DFU_UPLOAD:
524 		/* state transition if less data then requested */
525 		f_dfu->blk_seq_num = w_value;
526 		value = handle_upload(req, len);
527 		if (value >= 0 && value < len)
528 			f_dfu->dfu_state = DFU_STATE_dfuIDLE;
529 		break;
530 	case USB_REQ_DFU_ABORT:
531 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
532 		/* no zlp? */
533 		value = RET_ZLP;
534 		break;
535 	case USB_REQ_DFU_GETSTATUS:
536 		handle_getstatus(req);
537 		value = RET_STAT_LEN;
538 		break;
539 	case USB_REQ_DFU_GETSTATE:
540 		handle_getstate(req);
541 		break;
542 	default:
543 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
544 		value = RET_STALL;
545 		break;
546 	}
547 
548 	return value;
549 }
550 
551 static int state_dfu_error(struct f_dfu *f_dfu,
552 				 const struct usb_ctrlrequest *ctrl,
553 				 struct usb_gadget *gadget,
554 				 struct usb_request *req)
555 {
556 	int value = 0;
557 
558 	switch (ctrl->bRequest) {
559 	case USB_REQ_DFU_GETSTATUS:
560 		handle_getstatus(req);
561 		value = RET_STAT_LEN;
562 		break;
563 	case USB_REQ_DFU_GETSTATE:
564 		handle_getstate(req);
565 		break;
566 	case USB_REQ_DFU_CLRSTATUS:
567 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
568 		f_dfu->dfu_status = DFU_STATUS_OK;
569 		/* no zlp? */
570 		value = RET_ZLP;
571 		break;
572 	default:
573 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
574 		value = RET_STALL;
575 		break;
576 	}
577 
578 	return value;
579 }
580 
581 static dfu_state_fn dfu_state[] = {
582 	state_app_idle,          /* DFU_STATE_appIDLE */
583 	state_app_detach,        /* DFU_STATE_appDETACH */
584 	state_dfu_idle,          /* DFU_STATE_dfuIDLE */
585 	state_dfu_dnload_sync,   /* DFU_STATE_dfuDNLOAD_SYNC */
586 	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
587 	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
588 	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
589 	state_dfu_manifest,	 /* DFU_STATE_dfuMANIFEST */
590 	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
591 	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
592 	state_dfu_error          /* DFU_STATE_dfuERROR */
593 };
594 
595 static int
596 dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
597 {
598 	struct usb_gadget *gadget = f->config->cdev->gadget;
599 	struct usb_request *req = f->config->cdev->req;
600 	struct f_dfu *f_dfu = f->config->cdev->req->context;
601 	u16 len = le16_to_cpu(ctrl->wLength);
602 	u16 w_value = le16_to_cpu(ctrl->wValue);
603 	int value = 0;
604 	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
605 
606 	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
607 	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
608 	       req_type, ctrl->bRequest, f_dfu->dfu_state);
609 
610 	if (req_type == USB_TYPE_STANDARD) {
611 		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
612 		    (w_value >> 8) == DFU_DT_FUNC) {
613 			value = min(len, (u16) sizeof(dfu_func));
614 			memcpy(req->buf, &dfu_func, value);
615 		}
616 	} else /* DFU specific request */
617 		value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
618 
619 	if (value >= 0) {
620 		req->length = value;
621 		req->zero = value < len;
622 		value = usb_ep_queue(gadget->ep0, req, 0);
623 		if (value < 0) {
624 			debug("ep_queue --> %d\n", value);
625 			req->status = 0;
626 		}
627 	}
628 
629 	return value;
630 }
631 
632 /*-------------------------------------------------------------------------*/
633 
634 static int
635 dfu_prepare_strings(struct f_dfu *f_dfu, int n)
636 {
637 	struct dfu_entity *de = NULL;
638 	int i = 0;
639 
640 	f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
641 	if (!f_dfu->strings)
642 		goto enomem;
643 
644 	for (i = 0; i < n; ++i) {
645 		de = dfu_get_entity(i);
646 		f_dfu->strings[i].s = de->name;
647 	}
648 
649 	f_dfu->strings[i].id = 0;
650 	f_dfu->strings[i].s = NULL;
651 
652 	return 0;
653 
654 enomem:
655 	while (i)
656 		f_dfu->strings[--i].s = NULL;
657 
658 	free(f_dfu->strings);
659 
660 	return -ENOMEM;
661 }
662 
663 static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
664 {
665 	struct usb_interface_descriptor *d;
666 	int i = 0;
667 
668 	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1);
669 	if (!f_dfu->function)
670 		goto enomem;
671 
672 	for (i = 0; i < n; ++i) {
673 		d = calloc(sizeof(*d), 1);
674 		if (!d)
675 			goto enomem;
676 
677 		d->bLength =		sizeof(*d);
678 		d->bDescriptorType =	USB_DT_INTERFACE;
679 		d->bAlternateSetting =	i;
680 		d->bNumEndpoints =	0;
681 		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
682 		d->bInterfaceSubClass =	1;
683 		d->bInterfaceProtocol =	2;
684 
685 		f_dfu->function[i] = (struct usb_descriptor_header *)d;
686 	}
687 	f_dfu->function[i] = NULL;
688 
689 	return 0;
690 
691 enomem:
692 	while (i) {
693 		free(f_dfu->function[--i]);
694 		f_dfu->function[i] = NULL;
695 	}
696 	free(f_dfu->function);
697 
698 	return -ENOMEM;
699 }
700 
701 static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
702 {
703 	struct usb_composite_dev *cdev = c->cdev;
704 	struct f_dfu *f_dfu = func_to_dfu(f);
705 	int alt_num = dfu_get_alt_number();
706 	int rv, id, i;
707 
708 	id = usb_interface_id(c, f);
709 	if (id < 0)
710 		return id;
711 	dfu_intf_runtime.bInterfaceNumber = id;
712 
713 	f_dfu->dfu_state = DFU_STATE_appIDLE;
714 	f_dfu->dfu_status = DFU_STATUS_OK;
715 
716 	rv = dfu_prepare_function(f_dfu, alt_num);
717 	if (rv)
718 		goto error;
719 
720 	rv = dfu_prepare_strings(f_dfu, alt_num);
721 	if (rv)
722 		goto error;
723 	for (i = 0; i < alt_num; i++) {
724 		id = usb_string_id(cdev);
725 		if (id < 0)
726 			return id;
727 		f_dfu->strings[i].id = id;
728 		((struct usb_interface_descriptor *)f_dfu->function[i])
729 			->iInterface = id;
730 	}
731 
732 	to_dfu_mode(f_dfu);
733 
734 	stringtab_dfu.strings = f_dfu->strings;
735 
736 	cdev->req->context = f_dfu;
737 
738 error:
739 	return rv;
740 }
741 
742 static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
743 {
744 	struct f_dfu *f_dfu = func_to_dfu(f);
745 	int alt_num = dfu_get_alt_number();
746 	int i;
747 
748 	if (f_dfu->strings) {
749 		i = alt_num;
750 		while (i)
751 			f_dfu->strings[--i].s = NULL;
752 
753 		free(f_dfu->strings);
754 	}
755 
756 	if (f_dfu->function) {
757 		i = alt_num;
758 		while (i) {
759 			free(f_dfu->function[--i]);
760 			f_dfu->function[i] = NULL;
761 		}
762 		free(f_dfu->function);
763 	}
764 
765 	free(f_dfu);
766 }
767 
768 static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
769 {
770 	struct f_dfu *f_dfu = func_to_dfu(f);
771 
772 	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
773 
774 	f_dfu->altsetting = alt;
775 	f_dfu->dfu_state = DFU_STATE_dfuIDLE;
776 	f_dfu->dfu_status = DFU_STATUS_OK;
777 
778 	return 0;
779 }
780 
781 /* TODO: is this really what we need here? */
782 static void dfu_disable(struct usb_function *f)
783 {
784 	struct f_dfu *f_dfu = func_to_dfu(f);
785 	if (f_dfu->config == 0)
786 		return;
787 
788 	debug("%s: reset config\n", __func__);
789 
790 	f_dfu->config = 0;
791 }
792 
793 static int dfu_bind_config(struct usb_configuration *c)
794 {
795 	struct f_dfu *f_dfu;
796 	int status;
797 
798 	f_dfu = calloc(sizeof(*f_dfu), 1);
799 	if (!f_dfu)
800 		return -ENOMEM;
801 	f_dfu->usb_function.name = "dfu";
802 	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
803 	f_dfu->usb_function.bind = dfu_bind;
804 	f_dfu->usb_function.unbind = dfu_unbind;
805 	f_dfu->usb_function.set_alt = dfu_set_alt;
806 	f_dfu->usb_function.disable = dfu_disable;
807 	f_dfu->usb_function.strings = dfu_generic_strings;
808 	f_dfu->usb_function.setup = dfu_handle;
809 	f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT;
810 
811 	status = usb_add_function(c, &f_dfu->usb_function);
812 	if (status)
813 		free(f_dfu);
814 
815 	return status;
816 }
817 
818 int dfu_add(struct usb_configuration *c)
819 {
820 	int id;
821 
822 	id = usb_string_id(c->cdev);
823 	if (id < 0)
824 		return id;
825 	strings_dfu_generic[0].id = id;
826 	dfu_intf_runtime.iInterface = id;
827 
828 	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
829 	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
830 
831 	return dfu_bind_config(c);
832 }
833 
834 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add);
835