diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/common/dfu.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/common/dfu.c')
-rw-r--r-- | roms/u-boot/common/dfu.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/roms/u-boot/common/dfu.c b/roms/u-boot/common/dfu.c new file mode 100644 index 000000000..16bd1ba58 --- /dev/null +++ b/roms/u-boot/common/dfu.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * dfu.c -- dfu command + * + * Copyright (C) 2015 + * Lukasz Majewski <l.majewski@majess.pl> + * + * Copyright (C) 2012 Samsung Electronics + * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> + * Lukasz Majewski <l.majewski@samsung.com> + */ + +#include <common.h> +#include <command.h> +#include <log.h> +#include <watchdog.h> +#include <dfu.h> +#include <console.h> +#include <g_dnl.h> +#include <usb.h> +#include <net.h> + +int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) +{ + bool dfu_reset = false; + int ret, i = 0; + + ret = usb_gadget_initialize(usbctrl_index); + if (ret) { + pr_err("usb_gadget_initialize failed\n"); + return CMD_RET_FAILURE; + } + g_dnl_clear_detach(); + ret = g_dnl_register(usb_dnl_gadget); + if (ret) { + pr_err("g_dnl_register failed"); + return CMD_RET_FAILURE; + } + +#ifdef CONFIG_DFU_TIMEOUT + unsigned long start_time = get_timer(0); +#endif + + while (1) { + if (g_dnl_detach()) { + /* + * Check if USB bus reset is performed after detach, + * which indicates that -R switch has been passed to + * dfu-util. In this case reboot the device + */ + if (dfu_usb_get_reset()) { + dfu_reset = true; + goto exit; + } + + /* + * This extra number of usb_gadget_handle_interrupts() + * calls is necessary to assure correct transmission + * completion with dfu-util + */ + if (++i == 10000) + goto exit; + } + + if (ctrlc()) + goto exit; + + if (dfu_get_defer_flush()) { + /* + * Call to usb_gadget_handle_interrupts() is necessary + * to act on ZLP OUT transaction from HOST PC after + * transmitting the whole file. + * + * If this ZLP OUT packet is NAK'ed, the HOST libusb + * function fails after timeout (by default it is set to + * 5 seconds). In such situation the dfu-util program + * exits with error message. + */ + usb_gadget_handle_interrupts(usbctrl_index); + ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0); + dfu_set_defer_flush(NULL); + if (ret) { + pr_err("Deferred dfu_flush() failed!"); + goto exit; + } + } + +#ifdef CONFIG_DFU_TIMEOUT + unsigned long wait_time = dfu_get_timeout(); + + if (wait_time) { + unsigned long current_time = get_timer(start_time); + + if (current_time > wait_time) { + debug("Inactivity timeout, abort DFU\n"); + goto exit; + } + } +#endif + + if (dfu_reinit_needed) + goto exit; + + WATCHDOG_RESET(); + usb_gadget_handle_interrupts(usbctrl_index); + } +exit: + g_dnl_unregister(); + usb_gadget_release(usbctrl_index); + + if (dfu_reset) + do_reset(NULL, 0, 0, NULL); + + g_dnl_clear_detach(); + + return ret; +} |