aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/common/dfu.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/common/dfu.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/common/dfu.c')
-rw-r--r--roms/u-boot/common/dfu.c117
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;
+}