Home | History | Annotate | Download | only in common
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * dfu.c -- dfu command
      4  *
      5  * Copyright (C) 2015
      6  * Lukasz Majewski <l.majewski (at) majess.pl>
      7  *
      8  * Copyright (C) 2012 Samsung Electronics
      9  * authors: Andrzej Pietrasiewicz <andrzej.p (at) samsung.com>
     10  *	    Lukasz Majewski <l.majewski (at) samsung.com>
     11  */
     12 
     13 #include <common.h>
     14 #include <watchdog.h>
     15 #include <dfu.h>
     16 #include <console.h>
     17 #include <g_dnl.h>
     18 #include <usb.h>
     19 #include <net.h>
     20 
     21 int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
     22 {
     23 	bool dfu_reset = false;
     24 	int ret, i = 0;
     25 
     26 	ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
     27 	if (ret) {
     28 		pr_err("board usb init failed\n");
     29 		return CMD_RET_FAILURE;
     30 	}
     31 	g_dnl_clear_detach();
     32 	ret = g_dnl_register(usb_dnl_gadget);
     33 	if (ret) {
     34 		pr_err("g_dnl_register failed");
     35 		return CMD_RET_FAILURE;
     36 	}
     37 
     38 	while (1) {
     39 		if (g_dnl_detach()) {
     40 			/*
     41 			 * Check if USB bus reset is performed after detach,
     42 			 * which indicates that -R switch has been passed to
     43 			 * dfu-util. In this case reboot the device
     44 			 */
     45 			if (dfu_usb_get_reset()) {
     46 				dfu_reset = true;
     47 				goto exit;
     48 			}
     49 
     50 			/*
     51 			 * This extra number of usb_gadget_handle_interrupts()
     52 			 * calls is necessary to assure correct transmission
     53 			 * completion with dfu-util
     54 			 */
     55 			if (++i == 10000)
     56 				goto exit;
     57 		}
     58 
     59 		if (ctrlc())
     60 			goto exit;
     61 
     62 		if (dfu_get_defer_flush()) {
     63 			/*
     64 			 * Call to usb_gadget_handle_interrupts() is necessary
     65 			 * to act on ZLP OUT transaction from HOST PC after
     66 			 * transmitting the whole file.
     67 			 *
     68 			 * If this ZLP OUT packet is NAK'ed, the HOST libusb
     69 			 * function fails after timeout (by default it is set to
     70 			 * 5 seconds). In such situation the dfu-util program
     71 			 * exits with error message.
     72 			 */
     73 			usb_gadget_handle_interrupts(usbctrl_index);
     74 			ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0);
     75 			dfu_set_defer_flush(NULL);
     76 			if (ret) {
     77 				pr_err("Deferred dfu_flush() failed!");
     78 				goto exit;
     79 			}
     80 		}
     81 
     82 		WATCHDOG_RESET();
     83 		usb_gadget_handle_interrupts(usbctrl_index);
     84 	}
     85 exit:
     86 	g_dnl_unregister();
     87 	board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
     88 
     89 	if (dfu_reset)
     90 		do_reset(NULL, 0, 0, NULL);
     91 
     92 	g_dnl_clear_detach();
     93 
     94 	return ret;
     95 }
     96