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_interrupt_notification PORTABLE C */
38 /* 6.1.11 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function is called by the stack when an interrupt packet as */
46 /* been received. */
47 /* */
48 /* INPUT */
49 /* */
50 /* transfer_request Pointer to transfer request */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* None */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* USBX stack */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
69 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
72 /* refined macros names, */
73 /* resulting in version 6.1.10 */
74 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
75 /* fixed standalone compile, */
76 /* resulting in version 6.1.11 */
77 /* */
78 /**************************************************************************/
_ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER * transfer_request)79 VOID _ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER *transfer_request)
80 {
81
82 UX_HOST_CLASS_CDC_ECM *cdc_ecm;
83 ULONG notification_type;
84 ULONG notification_value;
85
86
87 /* Get the control class instance for this transfer request. */
88 cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance;
89
90 /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */
91 if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
92
93 /* We do not proceed. */
94 return;
95
96 /* Check if the class is in shutdown. */
97 if (cdc_ecm -> ux_host_class_cdc_ecm_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN)
98
99 /* We do not proceed. */
100 return;
101
102 /* Increment the notification count. */
103 cdc_ecm -> ux_host_class_cdc_ecm_notification_count++;
104
105 /* Get the notification. */
106 notification_type = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_NOTIFICATION_TYPE);
107
108 /* And the value. */
109 notification_value = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_VALUE);
110
111 /* Check if the notification is a Network notification. */
112 if (notification_type == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_CONNECTION)
113 {
114
115 /* Check the state of the link. */
116 if (notification_value == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_LINK_UP)
117 {
118
119 /* Link is up. See if we know about that. */
120 if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP &&
121 cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP)
122 {
123
124 /* Memorize the new link state. */
125 cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP;
126
127 /* We need to inform the cdc_ecm thread of this change. */
128 _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore);
129 }
130 }
131 else
132 {
133
134 /* Link is down. See if we know about that. */
135 if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN &&
136 cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN)
137 {
138
139 /* We need to abort any transfers on the bulk in endpoint. */
140
141 /* Make sure no one does any more transfers. */
142 cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN;
143
144 /* Now abort all transfers. It's possible we're executing right before the transfer
145 is armed. If this is the case, then the transfer will not be aborted if we do the abort right now; instead,
146 we should wait until after the transfer is armed. We must look at the CDC-ECM thread's state. */
147
148 /* Is it in the process of checking the link state and arming the transfer? */
149 if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process == UX_TRUE)
150 {
151
152 /* Yes. We must wait for it to finish arming the transfer. */
153
154 /* Let the CDC-ECM thread know we're waiting so it can wake us up. */
155 cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE;
156
157 /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up. */
158 _ux_host_semaphore_get_norc(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER);
159
160 /* We're no longer waiting. */
161 cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE;
162 }
163
164 /* Now we can abort the transfer. */
165 _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request);
166
167 /* We need to inform the CDC-ECM thread of this change. */
168 _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore);
169 }
170 }
171 }
172
173 /* Reactivate the CDC_ECM interrupt pipe. */
174 _ux_host_stack_transfer_request(transfer_request);
175
176 /* If trace is enabled, insert this event into the trace buffer. */
177 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_INTERRUPT_NOTIFICATION, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
178
179 /* Return to caller. */
180 return;
181 }
182
183