1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** CDC-ECM Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_cdc_ecm.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_cdc_ecm_transmission_callback PORTABLE C */
38 /* 6.2.0 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function is the callback from the USBX transfer functions, */
46 /* it is called when a full or partial transfer has been done for a */
47 /* bulk out transfer. */
48 /* */
49 /* INPUT */
50 /* */
51 /* transfer_request Pointer to transfer request */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* None */
56 /* */
57 /* CALLS */
58 /* */
59 /* _ux_host_stack_transfer_request Process transfer request */
60 /* nx_packet_transmit_release Release NetX packet */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* Application */
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 /* resulting in version 6.1 */
73 /* 02-02-2021 Chaoqiong Xiao Modified comment(s), fixed */
74 /* ZLP issue for transmission, */
75 /* resulting in version 6.1.4 */
76 /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */
77 /* use pre-calculated value */
78 /* instead of wMaxPacketSize, */
79 /* resulting in version 6.1.9 */
80 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
81 /* fixed standalone compile, */
82 /* resulting in version 6.1.11 */
83 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
84 /* supported NX packet chain, */
85 /* resulting in version 6.2.0 */
86 /* */
87 /**************************************************************************/
_ux_host_class_cdc_ecm_transmission_callback(UX_TRANSFER * transfer_request)88 VOID _ux_host_class_cdc_ecm_transmission_callback(UX_TRANSFER *transfer_request)
89 {
90 #if defined(UX_HOST_STANDALONE)
91 UX_PARAMETER_NOT_USED(transfer_request);
92 #else
93
94 UX_HOST_CLASS_CDC_ECM *cdc_ecm;
95 NX_PACKET *current_packet;
96 NX_PACKET *next_packet;
97 UCHAR *packet_header;
98 #ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT
99 ULONG copied;
100 #endif
101
102 /* Get the data and control class instances for this transfer request. */
103 cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance;
104
105 /* Is the link not up, or the class is shutting down? */
106 if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP ||
107 cdc_ecm -> ux_host_class_cdc_ecm_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN)
108
109 /* The CDC-ECM thread or deactivation routine is in the process of freeing
110 the queue. Just return so we are not simultaneously accessing it. */
111 return;
112
113 /* Get the packet associated with this transfer. */
114 current_packet = cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head;
115
116 /* Do a sanity check on the packet. */
117 if (current_packet == UX_NULL)
118 {
119
120 /* Error trap. */
121 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FATAL_ERROR);
122
123 /* If trace is enabled, insert this event into the trace buffer. */
124 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, cdc_ecm, 0, 0, UX_FATAL_ERROR, 0, 0)
125
126 /* Something went terribly wrong. Do not proceed. */
127 return;
128 }
129
130 /* Check the state of the transfer. */
131 if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS)
132 {
133
134 /* Check if the transfer length is not zero and it is multiple of MPS (validated on device enum). */
135 if ((transfer_request -> ux_transfer_request_requested_length != 0) &&
136 (transfer_request -> ux_transfer_request_requested_length % transfer_request -> ux_transfer_request_packet_length) == 0)
137 {
138
139 /* Set transfer request length to zero. */
140 transfer_request -> ux_transfer_request_requested_length = 0;
141
142 /* Send the transfer. */
143 _ux_host_stack_transfer_request(transfer_request);
144
145 /* Finished processing. */
146 return;
147 }
148
149 /* Get the next packet associated with the first packet. */
150 next_packet = current_packet -> nx_packet_queue_next;
151
152 /* Set the next packet (or a NULL value) as the head of the xmit queue. */
153 cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head = next_packet;
154
155 /* If there is nothing else or if the link is down no need to rearm a packet. */
156 if (next_packet != UX_NULL)
157 {
158
159 #ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT
160
161 if (next_packet -> nx_packet_next != UX_NULL)
162 {
163
164 /* Put packet to continuous buffer to transfer. */
165 packet_header = cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer;
166 nx_packet_data_extract_offset(next_packet, 0, packet_header, next_packet -> nx_packet_length, &copied);
167 }
168 else
169 #endif
170 {
171
172 /* Load the address of the current packet header at the physical header. */
173 packet_header = next_packet -> nx_packet_prepend_ptr;
174 }
175
176 /* Prepare the values for this new transmission. */
177 transfer_request -> ux_transfer_request_data_pointer = packet_header;
178 transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length;
179
180 /* Store the packet that owns this transaction. */
181 transfer_request -> ux_transfer_request_user_specific = next_packet;
182
183 /* If error log is enabled, insert this message into the log buffer. */
184 UX_DEBUG_LOG("_ux_host_class_cdc_ecm_transmission_callback", "Sending packet", next_packet, next_packet, _ux_system -> ux_system_mutex.tx_mutex_suspended_count)
185
186 /* If there is an error, the system will hang up. Not much we can do to
187 fix this. */
188 _ux_host_stack_transfer_request(transfer_request);
189 }
190
191 /* If error log is enabled, insert this message into the log buffer. */
192 UX_DEBUG_LOG("_ux_host_class_cdc_ecm_transmission_callback", "Freeing transmitted packet", 0, transfer_request, current_packet)
193
194 /* Free the packet that was just sent. First do some housekeeping. */
195 current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE;
196 current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE;
197
198 /* And ask Netx to release it. */
199 nx_packet_transmit_release(current_packet);
200 }
201 else
202 {
203
204 /* The transfer failed. Retry it. Note that this can't be a transfer
205 abort, because otherwise the link is either down or the class is in
206 shutdown, both of which are checked for at the beginning. */
207 _ux_host_stack_transfer_request(transfer_request);
208 }
209
210 /* There is no status to be reported back to the stack. */
211 return;
212 #endif
213 }
214