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 CDC_ECM 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_cdc_ecm.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_cdc_ecm_interrupt_thread PORTABLE C */
37 /* 6.1.11 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is the thread of the cdc_ecm interrupt endpoint */
45 /* */
46 /* INPUT */
47 /* */
48 /* cdc_ecm_class Address of cdc_ecm 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_utility_short_put Put 16-bit value to buffer */
60 /* _ux_device_thread_suspend Suspend thread */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* ThreadX */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
71 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
72 /* used UX prefix to refer to */
73 /* TX symbols instead of using */
74 /* them directly, */
75 /* resulting in version 6.1 */
76 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
77 /* refined macros names, */
78 /* resulting in version 6.1.10 */
79 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
80 /* fixed standalone compile, */
81 /* resulting in version 6.1.11 */
82 /* */
83 /**************************************************************************/
_ux_device_class_cdc_ecm_interrupt_thread(ULONG cdc_ecm_class)84 VOID _ux_device_class_cdc_ecm_interrupt_thread(ULONG cdc_ecm_class)
85 {
86
87 UX_SLAVE_CLASS *class_ptr;
88 UX_SLAVE_CLASS_CDC_ECM *cdc_ecm;
89 UX_SLAVE_DEVICE *device;
90 UX_SLAVE_TRANSFER *transfer_request;
91 UINT status;
92 ULONG actual_flags;
93 UCHAR *notification_buffer;
94
95 /* Cast properly the cdc_ecm instance. */
96 UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class)
97
98 /* Get the cdc_ecm instance from this class container. */
99 cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
100
101 /* Get the pointer to the device. */
102 device = &_ux_system_slave -> ux_system_slave_device;
103
104 /* This thread runs forever but can be suspended or resumed. */
105 while(1)
106 {
107
108 /* All CDC_ECM events are on the interrupt endpoint IN, from the host. */
109 transfer_request = &cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint -> ux_slave_endpoint_transfer_request;
110
111 /* As long as the device is in the CONFIGURED state. */
112 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
113 {
114
115
116 /* Wait until we have a event sent by the application. We do not treat yet the case where a timeout based
117 on the interrupt pipe frequency or a change in the idle state forces us to send an empty report. */
118 _ux_utility_event_flags_get(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group,
119 UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT,
120 UX_OR_CLEAR, &actual_flags, UX_WAIT_FOREVER);
121
122 /* Build the Network Notification response. */
123 notification_buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
124
125 /* Set the request type. */
126 *(notification_buffer + UX_SETUP_REQUEST_TYPE) = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
127
128 /* Set the request itself. */
129 *(notification_buffer + UX_SETUP_REQUEST) = 0;
130
131 /* Set the value. It is the network link. */
132 _ux_utility_short_put(notification_buffer + UX_SETUP_VALUE, (USHORT)(cdc_ecm -> ux_slave_class_cdc_ecm_link_state));
133
134 /* Set the Index. It is interface. The interface used is the DATA interface. Here we simply take the interface number of the CONTROL and add 1 to it
135 as it is assumed the classes are contiguous in number. */
136 _ux_utility_short_put(notification_buffer + UX_SETUP_INDEX, (USHORT)(cdc_ecm -> ux_slave_class_cdc_ecm_interface -> ux_slave_interface_descriptor.bInterfaceNumber + 1));
137
138 /* And the length is zero. */
139 *(notification_buffer + UX_SETUP_LENGTH) = 0;
140
141 /* Send the request to the device controller. */
142 status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH,
143 UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH);
144
145 /* Check error code. */
146 if (status != UX_SUCCESS)
147 {
148
149 /* Since bus resets are expected, we do not treat it as an error. */
150 if (status != UX_TRANSFER_BUS_RESET)
151 {
152
153 /* Error trap. */
154 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status);
155 }
156 }
157 }
158
159 /* We need to suspend ourselves. We will be resumed by the device enumeration module. */
160 _ux_device_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread);
161 }
162 }
163 #endif
164