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