Add firmware for the ATUSB IEEE 802.15.4 USB Adapter
[linux-libre-firmware.git] / atusb / usb / dfu_common.c
diff --git a/atusb/usb/dfu_common.c b/atusb/usb/dfu_common.c
new file mode 100644 (file)
index 0000000..9b6feef
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * boot/dfu_common.c - DFU protocol engine parts common to App/DFU
+ *
+ * Written 2008-2011, 2013-2014 by Werner Almesberger
+ * Copyright 2008-2011, 2013-2014 Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
+ */
+
+/*
+ * A few, erm, shortcuts:
+ *
+ * - we don't bother with the app* states since DFU is all this firmware does
+ * - after DFU_DNLOAD, we just block until things are written, so we never
+ *   enter dfuDNLOAD_SYNC or dfuDNBUSY
+ * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET
+ * - to keep our buffers small, we only accept EP0-sized blocks
+ */
+
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "usb.h"
+#include "dfu.h"
+
+#include "board.h"
+#include "../sernum.h"
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define debug(...)
+#define error(...)
+
+
+static const uint8_t functional_descriptor[] = {
+       9,                      /* bLength */
+       DFU_DT_FUNCTIONAL,      /* bDescriptorType */
+       0xf,                    /* bmAttributes (claim omnipotence :-) */
+       LE(0xffff),             /* wDetachTimeOut (we're very patient) */
+       LE(EP0_SIZE),           /* wTransferSize */
+       LE(0x101),              /* bcdDFUVersion */
+};
+
+
+/*
+ * The worst-case activity would be flashing a one page and erasing another
+ * one, would should take less than 10 ms. A 100 ms timeout ought to be plenty.
+ */
+
+struct dfu dfu = {
+       OK,                     /* bStatus */
+       LE(100), 0,             /* bwPollTimeout, 100 ms */
+       dfuIDLE,                /* bState */
+       0,                      /* iString */
+};
+
+
+bool dfu_setup_common(const struct setup_request *setup)
+{
+       switch (setup->bmRequestType | setup->bRequest << 8) {
+       case DFU_FROM_DEV(DFU_GETSTATUS):
+               debug("DFU_GETSTATUS\n");
+               usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
+               return 1;
+       case DFU_TO_DEV(DFU_CLRSTATUS):
+               debug("DFU_CLRSTATUS\n");
+               dfu.state = dfuIDLE;
+               dfu.status = OK;
+               return 1;
+       case DFU_FROM_DEV(DFU_GETSTATE):
+               debug("DFU_GETSTATE\n");
+               usb_send(&eps[0], &dfu.state, 1, NULL, NULL);
+               return 1;
+       default:
+               error("DFU rt %x, rq%x ?\n",
+                   setup->bmRequestType, setup->bRequest);
+               return 0;
+       }
+}
+
+
+bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
+    uint8_t *size)
+{
+       if (type != DFU_DT_FUNCTIONAL)
+               return sernum_get_descr(type, index, reply, size);
+       *reply = functional_descriptor;
+       *size = sizeof(functional_descriptor);
+       return 1;
+}