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 /** 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 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_device_class_rndis_activate                     PORTABLE C      */
36 /*                                                           6.1.12       */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function activates the USB RNDIS device.                       */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    command                             Pointer to rndis command        */
48 /*                                                                        */
49 /*  OUTPUT                                                                */
50 /*                                                                        */
51 /*    Completion Status                                                   */
52 /*                                                                        */
53 /*  CALLS                                                                 */
54 /*                                                                        */
55 /*    _ux_network_driver_activate         Activate NetX USB interface     */
56 /*    _ux_utility_memory_set              Set memory                      */
57 /*    _ux_device_thread_resume            Resume thread                   */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    USBX Source Code                                                    */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
68 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
69 /*                                            verified memset and memcpy  */
70 /*                                            cases,                      */
71 /*                                            resulting in version 6.1    */
72 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
73 /*                                            refined macros names,       */
74 /*                                            resulting in version 6.1.10 */
75 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            fixed standalone compile,   */
77 /*                                            resulting in version 6.1.11 */
78 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            fixed parameter/variable    */
80 /*                                            names conflict C++ keyword, */
81 /*                                            resulting in version 6.1.12 */
82 /*                                                                        */
83 /**************************************************************************/
_ux_device_class_rndis_activate(UX_SLAVE_CLASS_COMMAND * command)84 UINT  _ux_device_class_rndis_activate(UX_SLAVE_CLASS_COMMAND *command)
85 {
86 #if defined(UX_DEVICE_STANDALONE)
87     UX_PARAMETER_NOT_USED(command);
88     return(UX_FUNCTION_NOT_SUPPORTED);
89 #else
90 
91 UX_SLAVE_INTERFACE          *interface_ptr;
92 UX_SLAVE_CLASS              *class_ptr;
93 UX_SLAVE_CLASS_RNDIS        *rndis;
94 UX_SLAVE_ENDPOINT           *endpoint;
95 ULONG                       physical_address_msw;
96 ULONG                       physical_address_lsw;
97 
98     /* Get the class container.  */
99     class_ptr =  command -> ux_slave_class_command_class_ptr;
100 
101     /* Get the class instance in the container.  */
102     rndis = (UX_SLAVE_CLASS_RNDIS *) class_ptr -> ux_slave_class_instance;
103 
104     /* Get the interface that owns this instance.  */
105     interface_ptr =  (UX_SLAVE_INTERFACE  *) command -> ux_slave_class_command_interface;
106 
107     /* Check if this is the Control or Data interface.  */
108     if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_CONTROL)
109     {
110 
111         /* Store the class instance into the interface.  */
112         interface_ptr -> ux_slave_interface_class_instance =  (VOID *)rndis;
113 
114         /* Now the opposite, store the interface in the class instance.  */
115         rndis -> ux_slave_class_rndis_interface =  interface_ptr;
116 
117         /* If there is a activate function call it.  */
118         if (rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_activate != UX_NULL)
119 
120             /* Invoke the application.  */
121             rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_activate(rndis);
122     }
123     else
124 
125         /* This is the DATA Class, only store the rndis instance in the interface.  */
126         interface_ptr -> ux_slave_interface_class_instance =  (VOID *)rndis;
127 
128     /* Locate the endpoints.  Interrupt for Control and Bulk in/out for Data.  */
129     endpoint =  interface_ptr -> ux_slave_interface_first_endpoint;
130 
131     /* Parse all endpoints.  */
132     while (endpoint != UX_NULL)
133     {
134 
135         /* Check the endpoint direction, and type.  */
136         if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
137         {
138 
139             /* Look at type.  */
140             if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)
141 
142                 /* We have found the interrupt endpoint, save it.  */
143                 rndis -> ux_slave_class_rndis_interrupt_endpoint =  endpoint;
144 
145             else
146 
147                 /* We have found the bulk in endpoint, save it.  */
148                 rndis -> ux_slave_class_rndis_bulkin_endpoint =  endpoint;
149 
150         }
151         else
152         {
153             /* Look at type for out endpoint.  */
154             if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
155 
156                 /* We have found the bulk out endpoint, save it.  */
157                 rndis -> ux_slave_class_rndis_bulkout_endpoint =  endpoint;
158         }
159 
160         /* Next endpoint.  */
161         endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
162     }
163 
164     /* Check if this is the Control or Data interface.  */
165     if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_DATA)
166     {
167 
168         /* Now check if all endpoints have been found.  */
169         if (rndis -> ux_slave_class_rndis_bulkout_endpoint == UX_NULL || rndis -> ux_slave_class_rndis_bulkin_endpoint == UX_NULL ||
170             rndis -> ux_slave_class_rndis_interrupt_endpoint == UX_NULL)
171 
172             /* Not all endpoints have been found. Major error, do not proceed.  */
173             return(UX_ERROR);
174 
175         /* Declare the link to be up. That may need to change later to make it dependent on the
176            WAN/Wireless modem.  */
177         rndis -> ux_slave_class_rndis_link_state = UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP;
178 
179         /* Setup the physical address of this IP instance.  */
180         physical_address_msw =  (ULONG)((rndis -> ux_slave_class_rndis_local_node_id[0] << 8) | (rndis -> ux_slave_class_rndis_local_node_id[1]));
181         physical_address_lsw =  (ULONG)((rndis -> ux_slave_class_rndis_local_node_id[2] << 24) | (rndis -> ux_slave_class_rndis_local_node_id[3] << 16) |
182                                                        (rndis -> ux_slave_class_rndis_local_node_id[4] << 8) | (rndis -> ux_slave_class_rndis_local_node_id[5]));
183 
184         /* Register this interface to the NetX USB interface broker.  */
185         _ux_network_driver_activate((VOID *) rndis, _ux_device_class_rndis_write,
186                                         &rndis -> ux_slave_class_rndis_network_handle,
187                                         physical_address_msw,
188                                         physical_address_lsw);
189 
190         /* Reset the endpoint buffers.  */
191         _ux_utility_memory_set(rndis -> ux_slave_class_rndis_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
192                                         ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
193         _ux_utility_memory_set(rndis -> ux_slave_class_rndis_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
194                                         ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
195         _ux_utility_memory_set(rndis -> ux_slave_class_rndis_interrupt_endpoint -> ux_slave_endpoint_transfer_request.
196                                         ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
197 
198         /* Resume the endpoint threads.  */
199         _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_interrupt_thread);
200         _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_bulkout_thread);
201         _ux_device_thread_resume(&rndis -> ux_slave_class_rndis_bulkin_thread);
202 
203         /* If trace is enabled, insert this event into the trace buffer.  */
204         UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
205 
206         /* If trace is enabled, register this object.  */
207         UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, rndis, 0, 0, 0)
208 
209         /* Return completion status.  */
210         return(UX_SUCCESS);
211 
212     }
213     else
214     {
215 
216         /* If trace is enabled, insert this event into the trace buffer.  */
217         UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
218 
219         /* If trace is enabled, register this object.  */
220         UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, rndis, 0, 0, 0)
221 
222         /* Return completion status.  */
223         return(UX_SUCCESS);
224     }
225 #endif
226 }
227