Add firmware for the ATUSB IEEE 802.15.4 USB Adapter
[linux-libre-firmware.git] / atusb / usb / dfu_common.c
1 /*
2  * boot/dfu_common.c - DFU protocol engine parts common to App/DFU
3  *
4  * Written 2008-2011, 2013-2014 by Werner Almesberger
5  * Copyright 2008-2011, 2013-2014 Werner Almesberger
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  */
12
13 /*
14  * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
15  */
16
17 /*
18  * A few, erm, shortcuts:
19  *
20  * - we don't bother with the app* states since DFU is all this firmware does
21  * - after DFU_DNLOAD, we just block until things are written, so we never
22  *   enter dfuDNLOAD_SYNC or dfuDNBUSY
23  * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET
24  * - to keep our buffers small, we only accept EP0-sized blocks
25  */
26
27
28 #include <stdbool.h>
29 #include <stdint.h>
30
31 #include "usb.h"
32 #include "dfu.h"
33
34 #include "board.h"
35 #include "../sernum.h"
36
37
38 #ifndef NULL
39 #define NULL 0
40 #endif
41
42 #define debug(...)
43 #define error(...)
44
45
46 static const uint8_t functional_descriptor[] = {
47         9,                      /* bLength */
48         DFU_DT_FUNCTIONAL,      /* bDescriptorType */
49         0xf,                    /* bmAttributes (claim omnipotence :-) */
50         LE(0xffff),             /* wDetachTimeOut (we're very patient) */
51         LE(EP0_SIZE),           /* wTransferSize */
52         LE(0x101),              /* bcdDFUVersion */
53 };
54
55
56 /*
57  * The worst-case activity would be flashing a one page and erasing another
58  * one, would should take less than 10 ms. A 100 ms timeout ought to be plenty.
59  */
60
61 struct dfu dfu = {
62         OK,                     /* bStatus */
63         LE(100), 0,             /* bwPollTimeout, 100 ms */
64         dfuIDLE,                /* bState */
65         0,                      /* iString */
66 };
67
68
69 bool dfu_setup_common(const struct setup_request *setup)
70 {
71         switch (setup->bmRequestType | setup->bRequest << 8) {
72         case DFU_FROM_DEV(DFU_GETSTATUS):
73                 debug("DFU_GETSTATUS\n");
74                 usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
75                 return 1;
76         case DFU_TO_DEV(DFU_CLRSTATUS):
77                 debug("DFU_CLRSTATUS\n");
78                 dfu.state = dfuIDLE;
79                 dfu.status = OK;
80                 return 1;
81         case DFU_FROM_DEV(DFU_GETSTATE):
82                 debug("DFU_GETSTATE\n");
83                 usb_send(&eps[0], &dfu.state, 1, NULL, NULL);
84                 return 1;
85         default:
86                 error("DFU rt %x, rq%x ?\n",
87                     setup->bmRequestType, setup->bRequest);
88                 return 0;
89         }
90 }
91
92
93 bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
94     uint8_t *size)
95 {
96         if (type != DFU_DT_FUNCTIONAL)
97                 return sernum_get_descr(type, index, reply, size);
98         *reply = functional_descriptor;
99         *size = sizeof(functional_descriptor);
100         return 1;
101 }