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