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 /** Device dfu Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_dfu.h"
28 #include "ux_device_stack.h"
29
30
31 #if !defined(UX_DEVICE_STANDALONE)
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_device_class_dfu_thread PORTABLE C */
37 /* 6.1.10 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is the thread of the dfu class. It waits for the */
45 /* dfu command to signal a DFU_DETACH stage and either force a */
46 /* disconnect from the device or wait for the host to detach. */
47 /* */
48 /* It's for RTOS mode. */
49 /* */
50 /* INPUT */
51 /* */
52 /* dfu_class Address of dfu class */
53 /* container */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* _ux_utility_event_flags_get Get event flags */
62 /* _ux_utility_delay_ms Delay in milliseconds */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* ThreadX */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
73 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
74 /* used UX prefix to refer to */
75 /* TX symbols instead of using */
76 /* them directly, */
77 /* resulting in version 6.1 */
78 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
79 /* resulting in version 6.1.10 */
80 /* */
81 /**************************************************************************/
_ux_device_class_dfu_thread(ULONG dfu_class)82 VOID _ux_device_class_dfu_thread(ULONG dfu_class)
83 {
84
85 UX_SLAVE_CLASS *class_ptr;
86 UX_SLAVE_CLASS_DFU *dfu;
87 UX_SLAVE_DCD *dcd;
88 UINT status;
89 ULONG actual_flags;
90
91 /* Cast properly the dfu instance. */
92 UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, dfu_class)
93
94 /* Get the dfu instance from this class container. */
95 dfu = (UX_SLAVE_CLASS_DFU *) class_ptr -> ux_slave_class_instance;
96
97 /* This thread runs forever. */
98 while(1)
99 {
100
101
102 /* Wait until we have a event sent by the application. */
103 status = _ux_utility_event_flags_get(&dfu -> ux_slave_class_dfu_event_flags_group, (UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT |
104 UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET),
105 UX_OR_CLEAR, &actual_flags, UX_WAIT_FOREVER);
106
107 /* Check the completion code and the actual flags returned. */
108 if (status == UX_SUCCESS)
109 {
110
111 /* Check the source of event. */
112 if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT)
113 {
114
115 /* We need to disconnect. The control command for DETACH is still being processed, wait 2-3 ms. */
116 _ux_utility_delay_ms(2);
117
118 /* Get the pointer to the DCD. */
119 dcd = &_ux_system_slave -> ux_system_slave_dcd;
120
121 /* Issue a Soft Disconnect. */
122 dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_FORCE_DISCONNECT);
123
124 }
125
126 /* Check the source of event. */
127 if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET)
128 {
129
130 /* We need to wait for reset. Arm a timer. The timeout value is indicated in ms from
131 the device framework. */
132 _ux_utility_delay_ms(_ux_system_slave -> ux_system_slave_device_dfu_detach_timeout);
133
134 /* Check the mode. */
135 if (_ux_system_slave -> ux_system_slave_device_dfu_mode == UX_DEVICE_CLASS_DFU_MODE_RUNTIME)
136
137 /* We are still in RunTime mode. The host never reset. Revert to AppIdle state. */
138 _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE;
139
140 }
141 }
142 }
143 }
144 #endif
145