]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Bootloader/dfu.h
1a7340f1b4f439ae0ddfe7c2eed3f1fbe2680dac
[kiibohd-controller.git] / Bootloader / dfu.h
1 /* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
2  * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifndef _USB_DFU_H
19 #define _USB_DFU_H
20
21 // ----- Compiler Includes -----
22
23 #include <sys/types.h>
24
25
26
27 // ----- Defines -----
28
29 #define USB_FUNCTION_DFU_IFACE_COUNT 1
30
31
32 #ifndef USB_DFU_TRANSFER_SIZE
33 #define USB_DFU_TRANSFER_SIZE   FLASH_SECTOR_SIZE
34 #endif
35
36 #define USB_FUNCTION_DESC_DFU_DECL                         \
37         struct dfu_function_desc
38
39 #define USB_FUNCTION_DFU_IFACE_COUNT    1
40 #define USB_FUNCTION_DFU_RX_EP_COUNT    0
41 #define USB_FUNCTION_DFU_TX_EP_COUNT    0
42
43
44
45 // ----- Macros -----
46
47 #define USB_FUNCTION_DESC_DFU(state...)                                 \
48         {                                                               \
49                 .iface = {                                              \
50                         .bLength = sizeof(struct usb_desc_iface_t),     \
51                         .bDescriptorType = USB_DESC_IFACE,              \
52                         .bInterfaceNumber = USB_FUNCTION_IFACE(0, state), \
53                         .bAlternateSetting = 0,                         \
54                         .bNumEndpoints = 0,                             \
55                         .bInterfaceClass = USB_DEV_CLASS_APP,           \
56                         .bInterfaceSubClass = USB_DEV_SUBCLASS_APP_DFU, \
57                         .bInterfaceProtocol = USB_DEV_PROTO_DFU_DFU,    \
58                         .iInterface = 0,                                \
59                 },                                                      \
60                         .dfu = {                                        \
61                         .bLength = sizeof(struct dfu_desc_functional),  \
62                         .bDescriptorType = {                            \
63                                 .id = 0x1,                              \
64                                 .type_type = USB_DESC_TYPE_CLASS        \
65                         },                                              \
66                         .will_detach = 1,                               \
67                         .manifestation_tolerant = 0,                    \
68                         .can_upload = 0,                                \
69                         .can_download = 1,                              \
70                         .wDetachTimeOut = 0,                            \
71                         .wTransferSize = USB_DFU_TRANSFER_SIZE,         \
72                         .bcdDFUVersion = { .maj = 1, .min = 1 }         \
73                 }                                                       \
74         }
75
76
77
78 // ----- Enumerations -----
79
80 enum dfu_dev_subclass {
81         USB_DEV_SUBCLASS_APP_DFU = 0x01
82 };
83
84 enum dfu_dev_proto {
85         USB_DEV_PROTO_DFU_APP = 0x01,
86         USB_DEV_PROTO_DFU_DFU = 0x02
87 };
88
89 enum dfu_ctrl_req_code {
90         USB_CTRL_REQ_DFU_DETACH = 0,
91         USB_CTRL_REQ_DFU_DNLOAD = 1,
92         USB_CTRL_REQ_DFU_UPLOAD = 2,
93         USB_CTRL_REQ_DFU_GETSTATUS = 3,
94         USB_CTRL_REQ_DFU_CLRSTATUS = 4,
95         USB_CTRL_REQ_DFU_GETSTATE = 5,
96         USB_CTRL_REQ_DFU_ABORT = 6
97 };
98
99 enum dfu_status {
100         DFU_STATUS_async = 0xff,
101         DFU_STATUS_OK = 0x00,
102         DFU_STATUS_errTARGET = 0x01,
103         DFU_STATUS_errFILE = 0x02,
104         DFU_STATUS_errWRITE = 0x03,
105         DFU_STATUS_errERASE = 0x04,
106         DFU_STATUS_errCHECK_ERASED = 0x05,
107         DFU_STATUS_errPROG = 0x06,
108         DFU_STATUS_errVERIFY = 0x07,
109         DFU_STATUS_errADDRESS = 0x08,
110         DFU_STATUS_errNOTDONE = 0x09,
111         DFU_STATUS_errFIRMWARE = 0x0a,
112         DFU_STATUS_errVENDOR = 0x0b,
113         DFU_STATUS_errUSBR = 0x0c,
114         DFU_STATUS_errPOR = 0x0d,
115         DFU_STATUS_errUNKNOWN = 0x0e,
116         DFU_STATUS_errSTALLEDPKT = 0x0f
117 };
118
119 enum dfu_state {
120         DFU_STATE_appIDLE = 0,
121         DFU_STATE_appDETACH = 1,
122         DFU_STATE_dfuIDLE = 2,
123         DFU_STATE_dfuDNLOAD_SYNC = 3,
124         DFU_STATE_dfuDNBUSY = 4,
125         DFU_STATE_dfuDNLOAD_IDLE = 5,
126         DFU_STATE_dfuMANIFEST_SYNC = 6,
127         DFU_STATE_dfuMANIFEST = 7,
128         DFU_STATE_dfuMANIFEST_WAIT_RESET = 8,
129         DFU_STATE_dfuUPLOAD_IDLE = 9,
130         DFU_STATE_dfuERROR = 10
131 };
132
133
134
135 // ----- Structs -----
136
137 struct dfu_status_t {
138         enum dfu_status bStatus : 8;
139         uint32_t bwPollTimeout : 24;
140         enum dfu_state bState : 8;
141         uint8_t iString;
142 } __packed;
143 CTASSERT_SIZE_BYTE(struct dfu_status_t, 6);
144
145
146 typedef enum dfu_status (*dfu_setup_write_t)(size_t off, size_t len, void **buf);
147 typedef enum dfu_status (*dfu_finish_write_t)(void *, size_t off, size_t len);
148 typedef void (*dfu_detach_t)(void);
149
150 struct dfu_ctx {
151         struct usbd_function_ctx_header header;
152         enum dfu_state state;
153         enum dfu_status status;
154         dfu_setup_write_t setup_write;
155         dfu_finish_write_t finish_write;
156         size_t off;
157         size_t len;
158 };
159
160
161 struct dfu_desc_functional {
162         uint8_t bLength;
163         struct usb_desc_type_t bDescriptorType; /* = class DFU/0x1 FUNCTIONAL */
164         union {
165                 struct {
166                         uint8_t can_download : 1;
167                         uint8_t can_upload : 1;
168                         uint8_t manifestation_tolerant : 1;
169                         uint8_t will_detach : 1;
170                         uint8_t _rsvd0 : 4;
171                 };
172                 uint8_t bmAttributes;
173         };
174         uint16_t wDetachTimeOut;
175         uint16_t wTransferSize;
176         struct usb_bcd_t bcdDFUVersion;
177 } __packed;
178 CTASSERT_SIZE_BYTE(struct dfu_desc_functional, 9);
179
180 struct dfu_function_desc {
181         struct usb_desc_iface_t iface;
182         struct dfu_desc_functional dfu;
183 };
184
185
186 extern const struct usbd_function dfu_function;
187 extern const struct usbd_function dfu_app_function;
188
189
190
191 // ----- Functions -----
192
193 void dfu_write_done(enum dfu_status, struct dfu_ctx *ctx);
194 void dfu_init(dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx);
195 void dfu_app_init(dfu_detach_t detachcb);
196
197 #endif