1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** USBX Component                                                        */
15 /**                                                                       */
16 /**   DFU Class                                                           */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 /**************************************************************************/
22 /*                                                                        */
23 /*  COMPONENT DEFINITION                                   RELEASE        */
24 /*                                                                        */
25 /*    ux_device_class_dfu.h                               PORTABLE C      */
26 /*                                                           6.3.0        */
27 /*  AUTHOR                                                                */
28 /*                                                                        */
29 /*    Chaoqiong Xiao, Microsoft Corporation                               */
30 /*                                                                        */
31 /*  DESCRIPTION                                                           */
32 /*                                                                        */
33 /*    This file defines the equivalences for the USBX Device Class DFU    */
34 /*    ACM component.                                                      */
35 /*                                                                        */
36 /*  RELEASE HISTORY                                                       */
37 /*                                                                        */
38 /*    DATE              NAME                      DESCRIPTION             */
39 /*                                                                        */
40 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
41 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
42 /*                                            used UX prefix to refer to  */
43 /*                                            TX symbols instead of using */
44 /*                                            them directly,              */
45 /*                                            resulting in version 6.1    */
46 /*  04-02-2021     Chaoqiong Xiao           Modified comment(s),          */
47 /*                                            added DFU_UPLOAD support,   */
48 /*                                            refined dfu_read prototype, */
49 /*                                            removed block count (it's   */
50 /*                                            from host request wValue),  */
51 /*                                            resulting in version 6.1.6  */
52 /*  08-02-2021     Chaoqiong Xiao           Modified comment(s),          */
53 /*                                            added extern "C" keyword    */
54 /*                                            for compatibility with C++, */
55 /*                                            resulting in version 6.1.8  */
56 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
57 /*                                            added standalone support,   */
58 /*                                            resulting in version 6.1.10 */
59 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
60 /*                                            added macros for req types, */
61 /*                                            resulting in version 6.1.12 */
62 /*  10-31-2023     Yajun xia                Modified comment(s),          */
63 /*                                            added error checks support, */
64 /*                                            resulting in version 6.3.0  */
65 /*                                                                        */
66 /**************************************************************************/
67 
68 #ifndef UX_DEVICE_CLASS_DFU_H
69 #define UX_DEVICE_CLASS_DFU_H
70 
71 /* Determine if a C++ compiler is being used.  If so, ensure that standard
72    C is used to process the API information.  */
73 
74 #ifdef   __cplusplus
75 
76 /* Yes, C++ compiler is present.  Use standard C.  */
77 extern   "C" {
78 
79 #endif
80 
81 /* Internal option: enable the basic USBX error checking. This define is typically used
82    while debugging application.  */
83 #if defined(UX_ENABLE_ERROR_CHECKING) && !defined(UX_DEVICE_CLASS_DFU_ENABLE_ERROR_CHECKING)
84 #define UX_DEVICE_CLASS_DFU_ENABLE_ERROR_CHECKING
85 #endif
86 
87 /* Define DFU class descriptor capabilities.  */
88 #define UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH                   0x08
89 #define UX_SLAVE_CLASS_DFU_CAPABILITY_MANIFESTATION_TOLERANT        0x04
90 #define UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD                    0x02
91 #define UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD                  0x01
92 
93 /* Define DFU Class USB Class constants.  */
94 #define UX_SLAVE_CLASS_DFU_CLASS                                    0xFE
95 #define UX_SLAVE_CLASS_DFU_SUBCLASS                                 0x01
96 #define UX_SLAVE_CLASS_DFU_PROTOCOL_RUNTIME                         0x01
97 #define UX_SLAVE_CLASS_DFU_PROTOCOL_DFU_MODE                        0x02
98 
99 /* Define DFU MODES signals.  */
100 #define UX_DEVICE_CLASS_DFU_MODE_RUNTIME                            1
101 #define UX_DEVICE_CLASS_DFU_MODE_DFU                                2
102 
103 
104 /* Device DFU bmRequestType.  */
105 #define UX_DEVICE_CLASS_DFU_REQTYPE_INTERFACE_SET                   (UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE) /* 00100001b, 0x21   */
106 #define UX_DEVICE_CLASS_DFU_REQTYPE_INTERFACE_GET                   (UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE) /* 10100001b, 0xA1  */
107 
108 
109 /* Device DFU Requests */
110 #define UX_SLAVE_CLASS_DFU_COMMAND_DETACH                           0
111 #define UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD                         1
112 #define UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD                           2
113 #define UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS                       3
114 #define UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS                     4
115 #define UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE                        5
116 #define UX_SLAVE_CLASS_DFU_COMMAND_ABORT                            6
117 
118 /* Device DFU Status values */
119 #define UX_SLAVE_CLASS_DFU_STATUS_OK                                0x00
120 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_TARGET                      0x01
121 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_FILE                        0x02
122 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_WRITE                       0x03
123 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_ERASE                       0x04
124 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_CHECK_ERASED                0x05
125 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_PROG                        0x06
126 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_VERIFY                      0x07
127 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_ADDRESS                     0x08
128 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_NOTDONE                     0x09
129 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_FIRMWARE                    0x0A
130 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_VENDOR                      0x0B
131 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_USBR                        0x0C
132 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_POR                         0x0D
133 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_UNKNOWN                     0x0E
134 #define UX_SLAVE_CLASS_DFU_STATUS_ERROR_STALLEDPKT                  0x0F
135 
136 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_APP_IDLE                    0
137 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_APP_DETACH                  1
138 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_IDLE                    2
139 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_SYNC             3
140 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY                  4
141 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE             5
142 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC           6
143 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST                7
144 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET     8
145 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_UPLOAD_IDLE             9
146 #define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR                   10
147 
148 /* Define DFU class GET_STATUS command response.  */
149 #define UX_SLAVE_CLASS_DFU_GET_STATUS_STATUS                        0
150 #define UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT                  1
151 #define UX_SLAVE_CLASS_DFU_GET_STATUS_STATE                         4
152 #define UX_SLAVE_CLASS_DFU_GET_STATUS_STRING                        5
153 #define UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH                        6
154 
155 /* Status mode for DFU_GETSTATUS
156    0 - simple mode,
157        status is queried from application in dfuDNLOAD-SYNC and dfuMANIFEST-SYNC state,
158        no bwPollTimeout.
159    1 - status is queried from application once requested,
160        b0-3 : media status
161        b4-7 : bStatus
162        b8-31: bwPollTimeout
163        bwPollTimeout supported.
164 */
165 #ifndef UX_DEVICE_CLASS_DFU_STATUS_MODE
166 #define UX_DEVICE_CLASS_DFU_STATUS_MODE                             (0)
167 #endif
168 
169 /* Status mode 0 bwPollTimeout (width: 3 bytes, ~0xFFFFFF).  */
170 #ifndef UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT
171 #define UX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT                      (1)
172 #endif
173 
174 
175 /* Define DFU class GET_STATE command response.  */
176 #define UX_SLAVE_CLASS_DFU_GET_STATE_STATE                          0
177 #define UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH                         1
178 
179 /* Define DFU application notification signals.  */
180 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD              0x1u
181 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD                0x2u
182 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD              0x3u
183 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_UPLOAD                0x5u
184 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_UPLOAD                  0x6u
185 #define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_UPLOAD                0x7u
186 
187 /* Define DFU application notification signals.  */
188 #define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK                          0
189 #define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY                        1
190 #define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR                       2
191 
192 /* Define DFU thread event signals.  */
193 #define UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT                 0x1u
194 #define UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET                 0x2u
195 
196 /* Define Slave DFU Class Calling Parameter structure */
197 
198 typedef struct UX_SLAVE_CLASS_DFU_PARAMETER_STRUCT
199 {
200 
201     ULONG                   ux_slave_class_dfu_parameter_will_detach;
202     ULONG                   ux_slave_class_dfu_parameter_capabilities;
203     VOID                    (*ux_slave_class_dfu_parameter_instance_activate)(VOID *);
204     VOID                    (*ux_slave_class_dfu_parameter_instance_deactivate)(VOID *);
205     UINT                    (*ux_slave_class_dfu_parameter_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length);
206     UINT                    (*ux_slave_class_dfu_parameter_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status);
207     UINT                    (*ux_slave_class_dfu_parameter_get_status)(VOID *dfu, ULONG *media_status);
208     UINT                    (*ux_slave_class_dfu_parameter_notify)(VOID *dfu, ULONG notification);
209 #ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
210     UINT                    (*ux_device_class_dfu_parameter_custom_request)(VOID *dfu, UX_SLAVE_TRANSFER *transfer);
211 #endif
212     UCHAR                   *ux_slave_class_dfu_parameter_framework;
213     ULONG                   ux_slave_class_dfu_parameter_framework_length;
214 
215 } UX_SLAVE_CLASS_DFU_PARAMETER;
216 
217 /* Define DFU Class structure.  */
218 
219 typedef struct UX_SLAVE_CLASS_DFU_STRUCT
220 {
221     UX_SLAVE_INTERFACE      *ux_slave_class_dfu_interface;
222     ULONG                   ux_slave_class_dfu_status;
223     VOID                    (*ux_slave_class_dfu_instance_activate)(VOID *);
224     VOID                    (*ux_slave_class_dfu_instance_deactivate)(VOID *);
225     UINT                    (*ux_slave_class_dfu_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length);
226     UINT                    (*ux_slave_class_dfu_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status);
227     UINT                    (*ux_slave_class_dfu_get_status)(VOID *dfu, ULONG *media_status);
228     UINT                    (*ux_slave_class_dfu_notify)(VOID *dfu, ULONG notification);
229 #ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
230     UINT                    (*ux_device_class_dfu_custom_request)(VOID *dfu, UX_SLAVE_TRANSFER *transfer);
231 #endif
232 
233 #if !defined(UX_DEVICE_STANDALONE)
234     UX_THREAD               ux_slave_class_dfu_thread;
235     UCHAR                   *ux_slave_class_dfu_thread_stack;
236     UX_EVENT_FLAGS_GROUP    ux_slave_class_dfu_event_flags_group;
237 #else
238     ULONG                   ux_device_class_dfu_flags;
239 #endif
240 } UX_SLAVE_CLASS_DFU;
241 
242 #if !defined(UX_DEVICE_STANDALONE)
243 #define _ux_device_class_dfu_event_flags_set(dfu, flags)    do {                                    \
244         _ux_utility_event_flags_set(&(dfu) -> ux_slave_class_dfu_event_flags_group, flags, UX_OR);  \
245     } while(0)
246 #else
247 #define _ux_device_class_dfu_event_flags_set(dfu, flags)    do {                \
248         (dfu) -> ux_device_class_dfu_flags |= flags;                            \
249     } while(0)
250 #endif
251 
252 /* Define Device DFU Class prototypes.  */
253 
254 UINT  _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command);
255 UINT  _ux_device_class_dfu_control_request(UX_SLAVE_CLASS_COMMAND *command);
256 UINT  _ux_device_class_dfu_deactivate(UX_SLAVE_CLASS_COMMAND *command);
257 UINT  _ux_device_class_dfu_entry(UX_SLAVE_CLASS_COMMAND *command);
258 UINT  _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command);
259 VOID  _ux_device_class_dfu_thread(ULONG dfu_class);
260 
261 UCHAR _ux_device_class_dfu_state_get(UX_SLAVE_CLASS_DFU *dfu);
262 VOID  _ux_device_class_dfu_state_sync(UX_SLAVE_CLASS_DFU *dfu);
263 
264 UINT  _ux_device_class_dfu_tasks_run(VOID *class_instance);
265 
266 UINT  _uxe_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command);
267 
268 /* Define Device DFU Class API prototypes.  */
269 #define ux_device_class_dfu_entry        _ux_device_class_dfu_entry
270 #define ux_device_class_dfu_state_get    _ux_device_class_dfu_state_get
271 #define ux_device_class_dfu_state_sync   _ux_device_class_dfu_state_sync
272 
273 /* Determine if a C++ compiler is being used.  If so, complete the standard
274    C conditional started above.  */
275 #ifdef __cplusplus
276 }
277 #endif
278 
279 #endif /* UX_DEVICE_CLASS_DFU_H */
280