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