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 RNDIS 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_rndis.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_rndis_interrupt_thread PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is the thread of the rndis interrupt endpoint */
45 /* */
46 /* INPUT */
47 /* */
48 /* rndis_class Address of rndis class */
49 /* container */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* _ux_device_stack_transfer_request Request transfer */
58 /* _ux_utility_event_flags_get Get event flags */
59 /* _ux_device_thread_suspend Suspend thread */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* ThreadX */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
70 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
71 /* used UX prefix to refer to */
72 /* TX symbols instead of using */
73 /* them directly, */
74 /* resulting in version 6.1 */
75 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
76 /* refined macros names, */
77 /* resulting in version 6.1.10 */
78 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
79 /* fixed standalone compile, */
80 /* resulting in version 6.1.11 */
81 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
82 /* fixed parameter/variable */
83 /* names conflict C++ keyword, */
84 /* resulting in version 6.1.12 */
85 /* */
86 /**************************************************************************/
_ux_device_class_rndis_interrupt_thread(ULONG rndis_class)87 VOID _ux_device_class_rndis_interrupt_thread(ULONG rndis_class)
88 {
89
90 UX_SLAVE_CLASS *class_ptr;
91 UX_SLAVE_CLASS_RNDIS *rndis;
92 UX_SLAVE_DEVICE *device;
93 UX_SLAVE_TRANSFER *transfer_request;
94 UINT status;
95 ULONG actual_flags;
96
97 /* Cast properly the rndis instance. */
98 UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, rndis_class)
99
100 /* Get the rndis instance from this class container. */
101 rndis = (UX_SLAVE_CLASS_RNDIS *) class_ptr -> ux_slave_class_instance;
102
103 /* Get the pointer to the device. */
104 device = &_ux_system_slave -> ux_system_slave_device;
105
106 /* This thread runs forever but can be suspended or resumed. */
107 while(1)
108 {
109
110 /* All RNDIS events are on the interrupt endpoint IN, from the host. */
111 transfer_request = &rndis -> ux_slave_class_rndis_interrupt_endpoint -> ux_slave_endpoint_transfer_request;
112
113 /* As long as the device is in the CONFIGURED state. */
114 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
115 {
116
117
118 /* Wait until we have a event sent by the application. We do not treat yet the case where a timeout based
119 on the interrupt pipe frequency or a change in the idle state forces us to send an empty report. */
120 status = _ux_utility_event_flags_get(&rndis -> ux_slave_class_rndis_event_flags_group, (UX_DEVICE_CLASS_RNDIS_NEW_INTERRUPT_EVENT |
121 UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT),
122 UX_OR_CLEAR, &actual_flags, UX_WAIT_FOREVER);
123
124 /* If error log is enabled, insert this error message into the log buffer. */
125
126 /* Check the completion code. */
127 if (status == UX_SUCCESS && (actual_flags & UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT) == 0)
128 {
129
130 /* Send the request to the device controller. */
131 status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH,
132 UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH);
133
134 /* Check error code. */
135 if (status != UX_SUCCESS)
136
137 /* Error trap. */
138 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status);
139 }
140 }
141
142 /* We need to suspend ourselves. We will be resumed by the device enumeration module. */
143 _ux_device_thread_suspend(&rndis -> ux_slave_class_rndis_interrupt_thread);
144
145 }
146 }
147 #endif
148