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 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_device_class_rndis_msg_query                    PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function analyzes and replies to the MSG QUERY                 */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    rndis                           Pointer to rndis class              */
49 /*    transfer_request                Pointer to the transfer request     */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    None                                                                */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _ux_utility_long_get            Get 32-bit value                    */
58 /*    _ux_utility_long_put            Put 32-bit value                    */
59 /*    _ux_utility_string_length_check Check and return C string length    */
60 /*    _ux_utility_memory_copy         Copy memory                         */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    RNDIS Class                                                         */
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 /*                                            verified memset and memcpy  */
73 /*                                            cases,                      */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
_ux_device_class_rndis_msg_query(UX_SLAVE_CLASS_RNDIS * rndis,UX_SLAVE_TRANSFER * transfer_request)77 UINT _ux_device_class_rndis_msg_query(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request)
78 {
79 
80 UCHAR            *rndis_msg;
81 UCHAR            *rndis_response;
82 ULONG            rndis_oid;
83 ULONG            rndis_response_length;
84 UINT             rndis_response_string_length =  0;
85 ULONG            oid_index;
86 ULONG            status;
87 
88     /* Get the pointer to the RNDIS message.  */
89     rndis_msg = transfer_request -> ux_slave_transfer_request_data_pointer;
90 
91     /* Get the request ID and keep it for the response.  */
92     rndis -> ux_slave_class_rndis_request_id =  _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_QUERY_REQUEST_ID);
93 
94     /* Get the OID.  */
95     rndis_oid = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_QUERY_OID);
96 
97     /* If trace is enabled, insert this event into the trace buffer.  */
98     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_MSG_QUERY, rndis, rndis_oid, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
99 
100     /* Now prepare the response.  */
101     rndis_response = rndis -> ux_slave_class_rndis_response;
102 
103     /* First store the command. */
104     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY);
105 
106     /* Store the request ID.  */
107     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_REQUEST_ID, rndis -> ux_slave_class_rndis_request_id);
108 
109     /* By default the function will succeed. */
110     status = UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS;
111 
112     /* What OID are we dealing here ? */
113     switch (rndis_oid)
114     {
115 
116          case UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_LIST        :
117 
118              /* Supported List of OIDs.  Parse each OID until the end and store it in the response buffer. */
119               oid_index = 0;
120             while (ux_device_class_rndis_oid_supported_list[oid_index] != 0)
121             {
122 
123                 /* We have found a valid OID to return.  */
124                 _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + (oid_index * sizeof(ULONG)),
125                                         ux_device_class_rndis_oid_supported_list[oid_index]);
126 
127                 /* Next OID index.  */
128                 oid_index++;
129 
130             }
131 
132             /* Set the total response length.  */
133             rndis_response_length = oid_index * (ULONG)sizeof(ULONG);
134 
135             break;
136 
137         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE    :
138 
139             /* Set the maximum frame size.  */
140             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAX_FRAME_SIZE);
141 
142             /* Set the total response length.  */
143             rndis_response_length = sizeof(ULONG);
144 
145             break;
146 
147         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SUPPORTED         :
148 
149             /* Set the media supported.  */
150             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_802_3);
151 
152             /* Set the total response length.  */
153             rndis_response_length = sizeof(ULONG);
154 
155             break;
156 
157         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_IN_USE            :
158 
159             /* Set the media in use.  */
160             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_802_3);
161 
162             /* Set the total response length.  */
163             rndis_response_length = sizeof(ULONG);
164 
165             break;
166 
167         case UX_DEVICE_CLASS_RNDIS_OID_GEN_HARDWARE_STATUS            :
168 
169             /* Set the hardware status.  */
170             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_READY);
171 
172             /* Set the total response length.  */
173             rndis_response_length = sizeof(ULONG);
174 
175             break;
176 
177         case UX_DEVICE_CLASS_RNDIS_OID_GEN_PHYSICAL_MEDIUM            :
178 
179             /* Set the physical medium.  */
180             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, 0);
181 
182             /* Set the total response length.  */
183             rndis_response_length = sizeof(ULONG);
184 
185             break;
186 
187         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE            :
188 
189             /* Set the physical medium.  */
190             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH);
191 
192             /* Set the total response length.  */
193             rndis_response_length = sizeof(ULONG);
194 
195             break;
196 
197 
198         case UX_DEVICE_CLASS_RNDIS_OID_GEN_LINK_SPEED            :
199 
200             /* Set the link speed.  For now we assume a full speed device.  */
201             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_LINK_SPEED_FS);
202 
203             /* Set the total response length.  */
204             rndis_response_length = sizeof(ULONG);
205 
206             break;
207 
208         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CONNECT_STATUS            :
209 
210             /* Set the media connection status.  */
211             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_CONNECTED);
212 
213             /* Set the total response length.  */
214             rndis_response_length = sizeof(ULONG);
215 
216             break;
217 
218 
219         case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAC_OPTIONS                    :
220 
221             /* Set the MAC options.  */
222             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAC_OPTIONS);
223 
224             /* Set the total response length.  */
225             rndis_response_length = sizeof(ULONG);
226 
227             break;
228 
229         case UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_ID                     :
230 
231             /* Set the vendor ID.  */
232             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_id);
233 
234             /* Set the total response length.  */
235             rndis_response_length = sizeof(ULONG);
236 
237             break;
238 
239         case UX_DEVICE_CLASS_RNDIS_OID_GEN_DRIVER_VERSION                  :
240 
241             /* Set the driver version.  */
242             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_driver_version);
243 
244             /* Set the total response length.  */
245             rndis_response_length = sizeof(ULONG);
246 
247             break;
248 
249 
250         case UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DESCRIPTION            :
251 
252             /* Get the string length for the vendor description.  */
253             status = _ux_utility_string_length_check(rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_description, &rndis_response_string_length, UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH);
254             if (status)
255                 return(status);
256 
257             /* Set the total response length.  */
258             rndis_response_length =  (ULONG) rndis_response_string_length;
259 
260             /* Copy the vendor description.  */
261             _ux_utility_memory_copy(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_description, rndis_response_length); /* Use case of memcpy is verified. */
262 
263             break;
264 
265         case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_OK                        :
266 
267             /* Set the appropriate statistic value. */
268             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_xmit_ok);
269 
270             /* Set the total response length.  */
271             rndis_response_length = sizeof(ULONG);
272 
273             break;
274 
275         case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_OK                        :
276 
277             /* Set the appropriate statistic value. */
278             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_ok);
279 
280             /* Set the total response length.  */
281             rndis_response_length = sizeof(ULONG);
282 
283             break;
284 
285         case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_ERROR                    :
286 
287             /* Set the appropriate statistic value. */
288             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_xmit_error);
289 
290             /* Set the total response length.  */
291             rndis_response_length = sizeof(ULONG);
292 
293             break;
294 
295         case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_ERROR                    :
296 
297             /* Set the appropriate statistic value. */
298             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_error);
299 
300             /* Set the total response length.  */
301             rndis_response_length = sizeof(ULONG);
302 
303             break;
304 
305         case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_NO_BUFFER                :
306 
307             /* Set the appropriate statistic value. */
308             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_no_buffer);
309 
310             /* Set the total response length.  */
311             rndis_response_length = sizeof(ULONG);
312 
313             break;
314 
315          case UX_DEVICE_CLASS_RNDIS_OID_802_3_CURRENT_ADDRESS            :
316 
317 
318             /* Save the Hardware address in the return message.   */
319             _ux_utility_memory_copy(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER,
320                                     rndis -> ux_slave_class_rndis_remote_node_id, UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
321 
322             /* Set the total response length.  */
323             rndis_response_length = UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH;
324 
325             break;
326 
327 
328         default                                                            :
329 
330             /* Just return zero ULONG field. */
331             _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, 0);
332 
333             /* Set the total response length.  */
334             rndis_response_length = sizeof(ULONG);
335 
336             break;
337 
338     }
339 
340     /* Set the status field.  */
341     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_STATUS, status);
342 
343     /* Set the buffer offset value.  */
344     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_OFFSET,
345                             (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER - UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_REQUEST_ID));
346 
347     /* Store the length of the buffer.  */
348     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_LENGTH, rndis_response_length);
349 
350     /* Update the response length to add the header.  */
351     rndis_response_length += UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER;
352 
353     /* Set the response length.  */
354     rndis -> ux_slave_class_rndis_response_length =   rndis_response_length;
355     _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_LENGTH, rndis_response_length);
356 
357     /* We are done. Return UX_SUCCESS.  */
358     return(status);
359 }
360 
361