2 * (C) 2007 by OpenMoko, Inc.
3 * Author: Harald Welte <laforge@openmoko.org>
5 * based on existing SAM7DFU code from OpenPCD:
6 * (C) Copyright 2006 by Harald Welte <hwelte@hmw-consulting.de>
8 * See file CREDITS for list of people who contributed to this
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * - make NAND support reasonably self-contained and put in apropriate
29 * - add some means of synchronization, i.e. block commandline access
30 * while DFU transfer is in progress, and return to commandline once
32 * - add VERIFY support after writing to flash
33 * - sanely free() resources allocated during first uppload/download
34 * request when aborting
35 * - sanely free resources when another alternate interface is selected
38 * - add something like uImage or some other header that provides CRC
40 * - make 'dnstate' attached to 'struct usb_device_instance'
44 #if defined(CONFIG_USBD_DFU)
47 DECLARE_GLOBAL_DATA_PTR
;
50 #include <linux/types.h>
51 #include <linux/list.h>
52 #include <asm/errno.h>
55 #include <usb_dfu_descriptors.h>
56 #include <usb_dfu_trailer.h>
59 #include <jffs2/load_kernel.h>
60 int mtdparts_init(void);
61 extern struct list_head devices
;
63 #include "usbdcore_s3c2410.h"
64 #include "../serial/usbtty.h" /* for STR_* defs */
70 volatile enum dfu_state
*system_dfu_state
; /* for 3rd parties */
75 struct part_info
*part
;
76 unsigned int part_net_size
; /* net sizee (excl. bad blocks) of part */
78 nand_erase_options_t erase_opts
;
79 nand_write_options_t write_opts
;
80 nand_read_options_t read_opts
;
82 unsigned char *ptr
; /* pointer to next empty byte in buffer */
83 unsigned int off
; /* offset of current erase page in flash chip */
84 unsigned char *buf
; /* pointer to allocated erase page buffer */
86 /* unless doing an atomic transfer, we use the static buffer below.
87 * This saves us from having to clean up dynamic allications in the
88 * various error paths of the code. Also, it will always work, no
89 * matter what the memory situation is. */
90 unsigned char _buf
[0x20000]; /* FIXME: depends flash page size */
93 static struct dnload_state _dnstate
;
95 static int dfu_trailer_matching(const struct uboot_dfu_trailer
*trailer
)
97 if (trailer
->magic
!= UBOOT_DFU_TRAILER_MAGIC
||
98 trailer
->version
!= UBOOT_DFU_TRAILER_V1
||
99 trailer
->vendor
!= CONFIG_USBD_VENDORID
||
100 (trailer
->product
!= CONFIG_USBD_PRODUCTID_CDCACM
&&
101 trailer
->product
!= CONFIG_USBD_PRODUCTID_GSERIAL
))
103 #ifdef CONFIG_REVISION_TAG
104 if (trailer
->revision
!= get_board_rev())
111 static struct part_info
*get_partition_nand(int idx
)
113 struct mtd_device
*dev
;
114 struct part_info
*part
;
115 struct list_head
*pentry
;
120 if (list_empty(&devices
))
123 dev
= list_entry(devices
.next
, struct mtd_device
, link
);
125 list_for_each(pentry
, &dev
->parts
) {
127 part
= list_entry(pentry
, struct part_info
, link
);
136 #define LOAD_ADDR ((unsigned char *)0x32000000)
138 static int initialize_ds_nand(struct usb_device_instance
*dev
, struct dnload_state
*ds
)
140 ds
->part
= get_partition_nand(dev
->alternate
- 1);
142 printf("DFU: unable to find partition %u\b", dev
->alternate
-1);
143 dev
->dfu_state
= DFU_STATE_dfuERROR
;
144 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
147 ds
->nand
= &nand_info
[ds
->part
->dev
->id
->num
];
148 ds
->off
= ds
->part
->offset
;
149 ds
->part_net_size
= nand_net_part_size(ds
->part
);
151 if (ds
->nand
->erasesize
> sizeof(ds
->_buf
)) {
152 printf("*** Warning - NAND ERASESIZE bigger than static buffer\n");
153 ds
->buf
= malloc(ds
->nand
->erasesize
);
155 printf("DFU: can't allocate %u bytes\n", ds
->nand
->erasesize
);
156 dev
->dfu_state
= DFU_STATE_dfuERROR
;
157 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
165 memset(&ds
->read_opts
, 0, sizeof(ds
->read_opts
));
167 memset(&ds
->erase_opts
, 0, sizeof(ds
->erase_opts
));
168 ds
->erase_opts
.quiet
= 1;
169 /* FIXME: do this more dynamic */
170 if (!strcmp(ds
->part
->name
, "rootfs"))
171 ds
->erase_opts
.jffs2
= 1;
173 memset(&ds
->write_opts
, 0, sizeof(ds
->write_opts
));
174 ds
->write_opts
.pad
= 1;
175 ds
->write_opts
.blockalign
= 1;
176 ds
->write_opts
.quiet
= 1;
178 debug("initialize_ds_nand(dev=%p, ds=%p): ", dev
, ds
);
179 debug("nand=%p, ptr=%p, buf=%p, off=0x%x\n", ds
->nand
, ds
->ptr
, ds
->buf
, ds
->off
);
184 static int erase_flash_verify_nand(struct urb
*urb
, struct dnload_state
*ds
,
185 unsigned long erasesize
, unsigned long size
)
187 struct usb_device_instance
*dev
= urb
->device
;
190 debug("erase_flash_verify_nand(urb=%p, ds=%p, erase=0x%x size=0x%x)\n",
191 urb
, ds
, erasesize
, size
);
193 if (erasesize
== ds
->nand
->erasesize
) {
194 /* we're only writing a single block and need to
195 * do bad block skipping / offset adjustments our own */
196 while (ds
->nand
->block_isbad(ds
->nand
, ds
->off
)) {
197 debug("SKIP_ONE_BLOCK(0x%08x)!!\n", ds
->off
);
198 ds
->off
+= ds
->nand
->erasesize
;
202 /* we have finished one eraseblock, flash it */
203 ds
->erase_opts
.offset
= ds
->off
;
204 ds
->erase_opts
.length
= erasesize
;
205 debug("Erasing 0x%x bytes @ offset 0x%x (jffs=%u)\n",
206 ds
->erase_opts
.length
, ds
->erase_opts
.offset
,
207 ds
->erase_opts
.jffs2
);
208 rc
= nand_erase_opts(ds
->nand
, &ds
->erase_opts
);
210 debug("Error erasing\n");
211 dev
->dfu_state
= DFU_STATE_dfuERROR
;
212 dev
->dfu_status
= DFU_STATUS_errERASE
;
216 ds
->write_opts
.buffer
= ds
->buf
;
217 ds
->write_opts
.length
= size
;
218 ds
->write_opts
.offset
= ds
->off
;
219 debug("Writing 0x%x bytes @ offset 0x%x\n", size
, ds
->off
);
220 rc
= nand_write_opts(ds
->nand
, &ds
->write_opts
);
222 debug("Error writing\n");
223 dev
->dfu_state
= DFU_STATE_dfuERROR
;
224 dev
->dfu_status
= DFU_STATUS_errWRITE
;
231 /* FIXME: implement verify! */
235 static int erase_tail_clean_nand(struct urb
*urb
, struct dnload_state
*ds
)
237 struct usb_device_instance
*dev
= urb
->device
;
240 ds
->erase_opts
.offset
= ds
->off
;
241 ds
->erase_opts
.length
= ds
->part
->size
- (ds
->off
- ds
->part
->offset
);
242 debug("Erasing tail of 0x%x bytes @ offset 0x%x (jffs=%u)\n",
243 ds
->erase_opts
.length
, ds
->erase_opts
.offset
,
244 ds
->erase_opts
.jffs2
);
245 rc
= nand_erase_opts(ds
->nand
, &ds
->erase_opts
);
247 printf("Error erasing tail\n");
248 dev
->dfu_state
= DFU_STATE_dfuERROR
;
249 dev
->dfu_status
= DFU_STATUS_errERASE
;
253 ds
->off
+= ds
->erase_opts
.length
; /* for consistency */
258 /* Read the next erase blcok from NAND into buffer */
259 static int read_next_nand(struct urb
*urb
, struct dnload_state
*ds
)
261 struct usb_device_instance
*dev
= urb
->device
;
264 ds
->read_opts
.buffer
= ds
->buf
;
265 ds
->read_opts
.length
= ds
->nand
->erasesize
;
266 ds
->read_opts
.offset
= ds
->off
;
267 ds
->read_opts
.quiet
= 1;
269 debug("Reading 0x%x@0x%x to 0x%08p\n", ds
->nand
->erasesize
,
271 rc
= nand_read_opts(ds
->nand
, &ds
->read_opts
);
273 debug("Error reading\n");
274 dev
->dfu_state
= DFU_STATE_dfuERROR
;
275 dev
->dfu_status
= DFU_STATUS_errWRITE
;
278 ds
->off
+= ds
->nand
->erasesize
;
285 static int handle_dnload(struct urb
*urb
, u_int16_t val
, u_int16_t len
, int first
)
287 struct usb_device_instance
*dev
= urb
->device
;
288 struct dnload_state
*ds
= &_dnstate
;
289 unsigned int actual_len
= len
;
290 unsigned int remain_len
;
294 debug("download(len=%u, first=%u) ", len
, first
);
296 if (len
> CONFIG_USBD_DFU_XFER_SIZE
) {
297 /* Too big. Not that we'd really care, but it's a
298 * DFU protocol violation */
299 debug("length exceeds flash page size ");
300 dev
->dfu_state
= DFU_STATE_dfuERROR
;
301 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
306 /* Make sure that we have a valid mtd partition table */
307 char *mtdp
= getenv("mtdparts");
309 run_command("dynpart", 0);
313 debug("zero-size write -> MANIFEST_SYNC ");
314 dev
->dfu_state
= DFU_STATE_dfuMANIFEST_SYNC
;
317 switch (dev
->alternate
) {
320 sprintf(buf
, "%lx", ds
->ptr
- ds
->buf
);
321 setenv("filesize", buf
);
326 ds
->buf
+ sizeof(struct uboot_dfu_trailer
)) {
327 struct uboot_dfu_trailer trailer
;
328 dfu_trailer_mirror(&trailer
, ds
->ptr
);
329 if (!dfu_trailer_matching(&trailer
)) {
330 printf("DFU TRAILER NOT OK\n");
331 dev
->dfu_state
= DFU_STATE_dfuERROR
;
332 dev
->dfu_status
= DFU_STATUS_errTARGET
;
336 rc
= erase_flash_verify_nand(urb
, ds
,
339 /* re-write dynenv marker in OOB */
340 run_command("dynenv set u-boot_env", 0);
344 ds
->ptr
= ds
->buf
= ds
->_buf
;
348 if (ds
->ptr
> ds
->buf
)
349 rc
= erase_flash_verify_nand(urb
, ds
,
351 ds
->nand
->erasesize
);
352 /* rootfs partition */
353 if (!rc
&& !strcmp(ds
->part
->name
, "rootfs"))
354 rc
= erase_tail_clean_nand(urb
, ds
);
363 if (urb
->actual_length
!= len
) {
364 debug("urb->actual_length(%u) != len(%u) ?!? ",
365 urb
->actual_length
, len
);
366 dev
->dfu_state
= DFU_STATE_dfuERROR
;
367 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
371 if (first
&& ds
->buf
&& ds
->buf
!= ds
->_buf
&& ds
->buf
!= LOAD_ADDR
) {
376 switch (dev
->alternate
) {
379 printf("Starting DFU DOWNLOAD to RAM (0x%08p)\n",
385 memcpy(ds
->ptr
, urb
->buffer
, len
);
390 rc
= initialize_ds_nand(dev
, ds
);
393 ds
->buf
= malloc(ds
->part_net_size
);
395 printf("No memory for atomic buffer!!\n");
396 dev
->dfu_state
= DFU_STATE_dfuERROR
;
397 dev
->dfu_status
= DFU_STATUS_errUNKNOWN
;
401 printf("Starting Atomic DFU DOWNLOAD to partition '%s'\n",
405 remain_len
= (ds
->buf
+ ds
->part_net_size
) - ds
->ptr
;
406 if (remain_len
< len
) {
408 printf("End of write exceeds partition end\n");
409 dev
->dfu_state
= DFU_STATE_dfuERROR
;
410 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
413 memcpy(ds
->ptr
, urb
->buffer
, len
);
418 rc
= initialize_ds_nand(dev
, ds
);
421 printf("Starting DFU DOWNLOAD to partition '%s'\n",
425 size
= ds
->nand
->erasesize
;
426 remain_len
= ds
->buf
+ size
- ds
->ptr
;
427 if (remain_len
< len
)
428 actual_len
= remain_len
;
430 memcpy(ds
->ptr
, urb
->buffer
, actual_len
);
431 ds
->ptr
+= actual_len
;
433 /* check partition end */
434 if (ds
->off
+ (ds
->ptr
- ds
->buf
) > ds
->part
->offset
+ ds
->part
->size
) {
435 printf("End of write exceeds partition end\n");
436 dev
->dfu_state
= DFU_STATE_dfuERROR
;
437 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
441 if (ds
->ptr
>= ds
->buf
+ size
) {
442 rc
= erase_flash_verify_nand(urb
, ds
,
444 ds
->nand
->erasesize
);
447 /* copy remainder of data into buffer */
448 memcpy(ds
->ptr
, urb
->buffer
+ actual_len
, len
- actual_len
);
449 ds
->ptr
+= (len
- actual_len
);
457 static int handle_upload(struct urb
*urb
, u_int16_t val
, u_int16_t len
, int first
)
459 struct usb_device_instance
*dev
= urb
->device
;
460 struct dnload_state
*ds
= &_dnstate
;
464 debug("upload(val=0x%02x, len=%u, first=%u) ", val
, len
, first
);
466 if (len
> CONFIG_USBD_DFU_XFER_SIZE
) {
468 dev
->dfu_state
= DFU_STATE_dfuERROR
;
469 dev
->dfu_status
= DFU_STATUS_errADDRESS
;
470 //udc_ep0_send_stall();
471 debug("Error: Transfer size > CONFIG_USBD_DFU_XFER_SIZE ");
475 switch (dev
->alternate
) {
478 printf("Starting DFU Upload of RAM (0x%08p)\n",
483 /* FIXME: end at some more dynamic point */
484 if (ds
->ptr
+ len
> LOAD_ADDR
+ 0x200000)
485 len
= (LOAD_ADDR
+ 0x200000) - ds
->ptr
;
487 urb
->buffer
= ds
->ptr
;
488 urb
->actual_length
= len
;
493 rc
= initialize_ds_nand(dev
, ds
);
496 printf("Starting DFU Upload of partition '%s'\n",
498 rc
= read_next_nand(urb
, ds
);
503 if (len
> ds
->nand
->erasesize
) {
504 printf("We don't support transfers bigger than %u\n",
505 ds
->nand
->erasesize
);
506 len
= ds
->nand
->erasesize
;
509 remain
= ds
->nand
->erasesize
- (ds
->ptr
- ds
->buf
);
513 debug("copying %u bytes ", remain
);
514 urb
->buffer
= ds
->ptr
;
516 urb
->actual_length
= remain
;
518 if (ds
->ptr
>= ds
->buf
+ ds
->nand
->erasesize
&&
519 ds
->off
< ds
->part
->offset
+ ds
->part
->size
) {
520 rc
= read_next_nand(urb
, ds
);
524 debug("copying another %u bytes ", len
- remain
);
525 memcpy(urb
->buffer
+ remain
, ds
->ptr
, len
- remain
);
526 ds
->ptr
+= (len
- remain
);
527 urb
->actual_length
+= (len
- remain
);
533 debug("returning len=%u\n", len
);
537 static void handle_getstatus(struct urb
*urb
, int max
)
539 struct usb_device_instance
*dev
= urb
->device
;
540 struct dfu_status
*dstat
= (struct dfu_status
*) urb
->buffer
;
544 if (!urb
->buffer
|| urb
->buffer_length
< sizeof(*dstat
)) {
545 debug("invalid urb! ");
549 switch (dev
->dfu_state
) {
550 case DFU_STATE_dfuDNLOAD_SYNC
:
551 case DFU_STATE_dfuDNBUSY
:
553 if (fsr
& AT91C_MC_PROGE
) {
555 dev
->dfu_status
= DFU_STATUS_errPROG
;
556 dev
->dfu_state
= DFU_STATE_dfuERROR
;
557 } else if (fsr
& AT91C_MC_LOCKE
) {
559 dev
->dfu_status
= DFU_STATUS_errWRITE
;
560 dev
->dfu_state
= DFU_STATE_dfuERROR
;
561 } else if (fsr
& AT91C_MC_FRDY
) {
563 debug("DNLOAD_IDLE ");
564 dev
->dfu_state
= DFU_STATE_dfuDNLOAD_IDLE
;
568 dev
->dfu_state
= DFU_STATE_dfuDNBUSY
;
572 case DFU_STATE_dfuMANIFEST_SYNC
:
579 /* send status response */
580 dstat
->bStatus
= dev
->dfu_status
;
581 dstat
->bState
= dev
->dfu_state
;
583 /* FIXME: set dstat->bwPollTimeout */
584 urb
->actual_length
= MIN(sizeof(*dstat
), max
);
586 /* we don't need to explicitly send data here, will
587 * be done by the original caller! */
590 static void handle_getstate(struct urb
*urb
, int max
)
594 if (!urb
->buffer
|| urb
->buffer_length
< sizeof(u_int8_t
)) {
595 debug("invalid urb! ");
599 urb
->buffer
[0] = urb
->device
->dfu_state
& 0xff;
600 urb
->actual_length
= sizeof(u_int8_t
);
603 #ifndef CONFIG_USBD_PRODUCTID_DFU
604 #define CONFIG_USBD_PRODUCTID_DFU CONFIG_USBD_PRODUCTID_CDCACM
607 static const struct usb_device_descriptor dfu_dev_descriptor
= {
608 .bLength
= USB_DT_DEVICE_SIZE
,
609 .bDescriptorType
= USB_DT_DEVICE
,
611 .bDeviceClass
= 0x00,
612 .bDeviceSubClass
= 0x00,
613 .bDeviceProtocol
= 0x00,
614 .bMaxPacketSize0
= EP0_MAX_PACKET_SIZE
,
615 .idVendor
= CONFIG_USBD_VENDORID
,
616 .idProduct
= CONFIG_USBD_PRODUCTID_DFU
,
618 .iManufacturer
= DFU_STR_MANUFACTURER
,
619 .iProduct
= DFU_STR_PRODUCT
,
620 .iSerialNumber
= DFU_STR_SERIAL
,
621 .bNumConfigurations
= 0x01,
624 static struct _dfu_desc dfu_cfg_descriptor
= {
626 .bLength
= USB_DT_CONFIG_SIZE
,
627 .bDescriptorType
= USB_DT_CONFIG
,
628 .wTotalLength
= USB_DT_CONFIG_SIZE
+
629 DFU_NUM_ALTERNATES
* USB_DT_INTERFACE_SIZE
+
632 .bConfigurationValue
= 1,
633 .iConfiguration
= DFU_STR_CONFIG
,
634 .bmAttributes
= BMATTRIBUTE_RESERVED
,
637 .func_dfu
= DFU_FUNC_DESC
,
640 int dfu_ep0_handler(struct urb
*urb
)
642 int rc
, ret
= RET_NOTHING
;
643 u_int8_t req
= urb
->device_request
.bRequest
;
644 u_int16_t val
= urb
->device_request
.wValue
;
645 u_int16_t len
= urb
->device_request
.wLength
;
646 struct usb_device_instance
*dev
= urb
->device
;
648 debug("dfu_ep0(req=0x%x, val=0x%x, len=%u) old_state = %u ",
649 req
, val
, len
, dev
->dfu_state
);
651 switch (dev
->dfu_state
) {
652 case DFU_STATE_appIDLE
:
654 case USB_REQ_DFU_GETSTATUS
:
655 handle_getstatus(urb
, len
);
657 case USB_REQ_DFU_GETSTATE
:
658 handle_getstate(urb
, len
);
660 case USB_REQ_DFU_DETACH
:
661 dev
->dfu_state
= DFU_STATE_appDETACH
;
669 case DFU_STATE_appDETACH
:
671 case USB_REQ_DFU_GETSTATUS
:
672 handle_getstatus(urb
, len
);
674 case USB_REQ_DFU_GETSTATE
:
675 handle_getstate(urb
, len
);
678 dev
->dfu_state
= DFU_STATE_appIDLE
;
683 /* FIXME: implement timer to return to appIDLE */
685 case DFU_STATE_dfuIDLE
:
687 case USB_REQ_DFU_DNLOAD
:
689 dev
->dfu_state
= DFU_STATE_dfuERROR
;
693 dev
->dfu_state
= DFU_STATE_dfuDNLOAD_SYNC
;
694 ret
= handle_dnload(urb
, val
, len
, 1);
696 case USB_REQ_DFU_UPLOAD
:
697 dev
->dfu_state
= DFU_STATE_dfuUPLOAD_IDLE
;
698 handle_upload(urb
, val
, len
, 1);
700 case USB_REQ_DFU_ABORT
:
704 case USB_REQ_DFU_GETSTATUS
:
705 handle_getstatus(urb
, len
);
707 case USB_REQ_DFU_GETSTATE
:
708 handle_getstate(urb
, len
);
710 case USB_REQ_DFU_DETACH
:
711 /* Proprietary extension: 'detach' from idle mode and
712 * get back to runtime mode in case of USB Reset. As
713 * much as I dislike this, we just can't use every USB
714 * bus reset to switch back to runtime mode, since at
715 * least the Linux USB stack likes to send a number of resets
717 dev
->dfu_state
= DFU_STATE_dfuMANIFEST_WAIT_RST
;
720 dev
->dfu_state
= DFU_STATE_dfuERROR
;
726 case DFU_STATE_dfuDNLOAD_SYNC
:
728 case USB_REQ_DFU_GETSTATUS
:
729 handle_getstatus(urb
, len
);
730 /* FIXME: state transition depending on block completeness */
732 case USB_REQ_DFU_GETSTATE
:
733 handle_getstate(urb
, len
);
736 dev
->dfu_state
= DFU_STATE_dfuERROR
;
741 case DFU_STATE_dfuDNBUSY
:
743 case USB_REQ_DFU_GETSTATUS
:
744 /* FIXME: only accept getstatus if bwPollTimeout
746 handle_getstatus(urb
, len
);
749 dev
->dfu_state
= DFU_STATE_dfuERROR
;
754 case DFU_STATE_dfuDNLOAD_IDLE
:
756 case USB_REQ_DFU_DNLOAD
:
757 dev
->dfu_state
= DFU_STATE_dfuDNLOAD_SYNC
;
758 ret
= handle_dnload(urb
, val
, len
, 0);
760 case USB_REQ_DFU_ABORT
:
761 dev
->dfu_state
= DFU_STATE_dfuIDLE
;
764 case USB_REQ_DFU_GETSTATUS
:
765 handle_getstatus(urb
, len
);
767 case USB_REQ_DFU_GETSTATE
:
768 handle_getstate(urb
, len
);
771 dev
->dfu_state
= DFU_STATE_dfuERROR
;
776 case DFU_STATE_dfuMANIFEST_SYNC
:
778 case USB_REQ_DFU_GETSTATUS
:
779 /* We're MainfestationTolerant */
780 dev
->dfu_state
= DFU_STATE_dfuIDLE
;
781 handle_getstatus(urb
, len
);
783 case USB_REQ_DFU_GETSTATE
:
784 handle_getstate(urb
, len
);
787 dev
->dfu_state
= DFU_STATE_dfuERROR
;
792 case DFU_STATE_dfuMANIFEST
:
793 /* we should never go here */
794 dev
->dfu_state
= DFU_STATE_dfuERROR
;
797 case DFU_STATE_dfuMANIFEST_WAIT_RST
:
798 /* we should never go here */
800 case DFU_STATE_dfuUPLOAD_IDLE
:
802 case USB_REQ_DFU_UPLOAD
:
803 /* state transition if less data then requested */
804 rc
= handle_upload(urb
, val
, len
, 0);
805 if (rc
>= 0 && rc
< len
)
806 dev
->dfu_state
= DFU_STATE_dfuIDLE
;
808 case USB_REQ_DFU_ABORT
:
809 dev
->dfu_state
= DFU_STATE_dfuIDLE
;
813 case USB_REQ_DFU_GETSTATUS
:
814 handle_getstatus(urb
, len
);
816 case USB_REQ_DFU_GETSTATE
:
817 handle_getstate(urb
, len
);
820 dev
->dfu_state
= DFU_STATE_dfuERROR
;
825 case DFU_STATE_dfuERROR
:
827 case USB_REQ_DFU_GETSTATUS
:
828 handle_getstatus(urb
, len
);
830 case USB_REQ_DFU_GETSTATE
:
831 handle_getstate(urb
, len
);
833 case USB_REQ_DFU_CLRSTATUS
:
834 dev
->dfu_state
= DFU_STATE_dfuIDLE
;
835 dev
->dfu_status
= DFU_STATUS_OK
;
840 dev
->dfu_state
= DFU_STATE_dfuERROR
;
846 return DFU_EP0_UNHANDLED
;
851 debug("new_state = %u, ret = %u\n", dev
->dfu_state
, ret
);
855 //udc_ep0_send_zlp();
856 urb
->actual_length
= 0;
860 //udc_ep0_send_stall();
861 return DFU_EP0_STALL
;
870 void str2wide (char *str
, u16
* wide
);
871 static struct usb_string_descriptor
*create_usbstring(char *string
)
873 struct usb_string_descriptor
*strdesc
;
874 int size
= sizeof(*strdesc
) + strlen(string
)*2;
879 strdesc
= malloc(size
);
883 strdesc
->bLength
= size
;
884 strdesc
->bDescriptorType
= USB_DT_STRING
;
885 str2wide(string
, strdesc
->wData
);
891 static void dfu_init_strings(struct usb_device_instance
*dev
)
894 struct usb_string_descriptor
*strdesc
;
896 strdesc
= create_usbstring(CONFIG_DFU_CFG_STR
);
897 usb_strings
[DFU_STR_CONFIG
] = strdesc
;
899 for (i
= 0; i
< DFU_NUM_ALTERNATES
; i
++) {
901 strdesc
= create_usbstring(CONFIG_DFU_ALT0_STR
);
903 struct part_info
*part
= get_partition_nand(i
-1);
906 strdesc
= create_usbstring(part
->name
);
909 create_usbstring("undefined partition");
913 usb_strings
[STR_COUNT
+i
+1] = strdesc
;
918 #ifdef CONFIG_NAND_DYNPART
920 void dfu_update_strings(void)
924 if (!system_dfu_state
) {
925 printf("NASTY SURPRISE: system_dfu_state not set\n");
929 for (i
= 1; i
!= DFU_NUM_ALTERNATES
; i
++) {
930 struct part_info
*part
= get_partition_nand(i
-1);
931 struct usb_string_descriptor
*strdesc
, **slot
;
934 strdesc
= create_usbstring(part
->name
);
936 strdesc
= create_usbstring("undefined partition");
939 slot
= usb_strings
+STR_COUNT
+i
+1;
946 #endif /* CONFIG_NAND_DYNPART */
949 int dfu_init_instance(struct usb_device_instance
*dev
)
953 for (i
= 0; i
!= DFU_NUM_ALTERNATES
; i
++) {
954 struct usb_interface_descriptor
*uif
=
955 dfu_cfg_descriptor
.uif
+i
;
957 uif
->bLength
= USB_DT_INTERFACE_SIZE
;
958 uif
->bDescriptorType
= USB_DT_INTERFACE
;
959 uif
->bAlternateSetting
= i
;
960 uif
->bInterfaceClass
= 0xfe;
961 uif
->bInterfaceSubClass
= 1;
962 uif
->bInterfaceProtocol
= 2;
963 uif
->iInterface
= DFU_STR_ALT(i
);
966 dev
->dfu_dev_desc
= &dfu_dev_descriptor
;
967 dev
->dfu_cfg_desc
= &dfu_cfg_descriptor
;
968 dev
->dfu_state
= DFU_STATE_appIDLE
;
969 dev
->dfu_status
= DFU_STATUS_OK
;
971 if (system_dfu_state
)
972 printf("SURPRISE: system_dfu_state is already set\n");
973 system_dfu_state
= &dev
->dfu_state
;
975 dfu_init_strings(dev
);
980 static int stdout_switched
;
982 /* event handler for usb device state events */
983 void dfu_event(struct usb_device_instance
*device
,
984 usb_device_event_t event
, int data
)
990 switch (device
->dfu_state
) {
991 case DFU_STATE_appDETACH
:
992 device
->dfu_state
= DFU_STATE_dfuIDLE
;
993 out
= getenv("stdout");
994 if (out
&& !strcmp(out
, "usbtty")) {
995 setenv("stdout", "vga");
996 setenv("stderr", "vga");
999 printf("DFU: Switching to DFU Mode\n");
1001 case DFU_STATE_dfuMANIFEST_WAIT_RST
:
1002 device
->dfu_state
= DFU_STATE_appIDLE
;
1003 printf("DFU: Switching back to Runtime mode\n");
1004 if (stdout_switched
) {
1005 setenv("stdout", "usbtty");
1006 setenv("stderr", "usbtty");
1007 stdout_switched
= 0;
1014 case DEVICE_CONFIGURED
:
1015 case DEVICE_DE_CONFIGURED
:
1016 debug("SET_CONFIGURATION(%u) ", device
->configuration
);
1018 case DEVICE_SET_INTERFACE
:
1019 debug("SET_INTERFACE(%u,%u) old_state = %u ",
1020 device
->interface
, device
->alternate
,
1022 switch (device
->dfu_state
) {
1023 case DFU_STATE_appIDLE
:
1024 case DFU_STATE_appDETACH
:
1025 case DFU_STATE_dfuIDLE
:
1026 case DFU_STATE_dfuMANIFEST_WAIT_RST
:
1027 /* do nothing, we're fine */
1029 case DFU_STATE_dfuDNLOAD_SYNC
:
1030 case DFU_STATE_dfuDNBUSY
:
1031 case DFU_STATE_dfuDNLOAD_IDLE
:
1032 case DFU_STATE_dfuMANIFEST
:
1033 device
->dfu_state
= DFU_STATE_dfuERROR
;
1034 device
->dfu_status
= DFU_STATUS_errNOTDONE
;
1035 /* FIXME: free malloc()ed buffer! */
1037 case DFU_STATE_dfuMANIFEST_SYNC
:
1038 case DFU_STATE_dfuUPLOAD_IDLE
:
1039 case DFU_STATE_dfuERROR
:
1040 device
->dfu_state
= DFU_STATE_dfuERROR
;
1041 device
->dfu_status
= DFU_STATUS_errUNKNOWN
;
1044 debug("new_state = %u\n", device
->dfu_state
);
1050 #endif /* CONFIG_USBD_DFU */