win-pvdrivers

view xenusb/xenusb_hub.c @ 1031:329b9b9d47ec

re-enable xenusb. compiles but untested.
author James Harper <james.harper@bendigoit.com.au>
date Thu Feb 21 20:37:38 2013 +1100 (2013-02-21)
parents ea3c61839ff5
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenusb.h"
21 #include <stdlib.h>
22 #include <usbioctl.h>
24 typedef struct _USB_START_FAILDATA {
25 ULONG LengthInBytes;
26 NTSTATUS NtStatus;
27 USBD_STATUS UsbdStatus;
28 ULONG ConnectStatus;
29 UCHAR DriverData[4];
30 } USB_START_FAILDATA, *PUSB_START_FAILDATA;
32 #pragma warning(disable: 4127) // conditional expression is constant
34 static EVT_WDF_DEVICE_D0_ENTRY XenUsbHub_EvtDeviceD0Entry;
35 static EVT_WDF_DEVICE_D0_EXIT XenUsbHub_EvtDeviceD0Exit;
36 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenUsbHub_EvtDevicePrepareHardware;
37 static EVT_WDF_DEVICE_RELEASE_HARDWARE XenUsbHub_EvtDeviceReleaseHardware;
38 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenUsbHub_EvtDeviceUsageNotification;
39 static EVT_WDF_TIMER XenUsbHub_HubInterruptTimer;
40 static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsbHub_EvtIoInternalDeviceControl;
41 static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL XenUsbHub_EvtIoDeviceControl;
42 static EVT_WDF_IO_QUEUE_IO_DEFAULT XenUsbHub_EvtIoDefault;
43 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenUsbHub_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE;
45 static USB_BUSIFFN_CREATE_USB_DEVICE XenUsbHub_UBIH_CreateUsbDevice;
46 static USB_BUSIFFN_CREATE_USB_DEVICE_EX XenUsbHub_UBIH_CreateUsbDeviceEx;
47 static USB_BUSIFFN_CREATE_USB_DEVICE_V7 XenUsbHub_UBIH_CreateUsbDeviceV7;
48 static USB_BUSIFFN_INITIALIZE_USB_DEVICE XenUsbHub_UBIH_InitializeUsbDevice;
49 static USB_BUSIFFN_GET_USB_DESCRIPTORS XenUsbHub_UBIH_GetUsbDescriptors;
50 static USB_BUSIFFN_REMOVE_USB_DEVICE XenUsbHub_UBIH_RemoveUsbDevice;
51 static USB_BUSIFFN_RESTORE_DEVICE XenUsbHub_UBIH_RestoreUsbDevice;
52 static USB_BUSIFFN_GET_POTRTHACK_FLAGS XenUsbHub_UBIH_GetPortHackFlags;
53 static USB_BUSIFFN_GET_DEVICE_INFORMATION XenUsbHub_UBIH_QueryDeviceInformation;
54 static USB_BUSIFFN_GET_CONTROLLER_INFORMATION XenUsbHub_UBIH_GetControllerInformation;
55 static USB_BUSIFFN_CONTROLLER_SELECTIVE_SUSPEND XenUsbHub_UBIH_ControllerSelectiveSuspend;
56 static USB_BUSIFFN_GET_EXTENDED_HUB_INFO XenUsbHub_UBIH_GetExtendedHubInformation;
57 static USB_BUSIFFN_GET_ROOTHUB_SYM_NAME XenUsbHub_UBIH_GetRootHubSymbolicName;
58 static USB_BUSIFFN_GET_DEVICE_BUSCONTEXT XenUsbHub_UBIH_GetDeviceBusContext;
59 static USB_BUSIFFN_INITIALIZE_20HUB XenUsbHub_UBIH_Initialize20Hub;
60 static USB_BUSIFFN_ROOTHUB_INIT_NOTIFY XenUsbHub_UBIH_RootHubInitNotification;
61 static USB_BUSIFFN_FLUSH_TRANSFERS XenUsbHub_UBIH_FlushTransfers;
62 static USB_BUSIFFN_SET_DEVHANDLE_DATA XenUsbHub_UBIH_SetDeviceHandleData;
63 static USB_BUSIFFN_INITIALIZE_USB_DEVICE_EX XenUsbHub_UBIH_InitializeUsbDeviceEx;
64 static USB_BUSIFFN_IS_ROOT XenUsbHub_UBIH_HubIsRoot;
65 static USB_BUSIFFN_TEST_POINT XenUsbHub_UBIH_HubTestPoint;
66 static USB_BUSIFFN_GET_DEVICE_PERFORMANCE_INFO XenUsbHub_UBIH_GetDevicePerformanceInfo;
67 static USB_BUSIFFN_WAIT_ASYNC_POWERUP XenUsbHub_UBIH_WaitAsyncPowerUp;
68 static USB_BUSIFFN_GET_DEVICE_ADDRESS XenUsbHub_UBIH_GetDeviceAddress;
69 static USB_BUSIFFN_REF_DEVICE_HANDLE XenUsbHub_UBIH_RefDeviceHandle;
70 static USB_BUSIFFN_DEREF_DEVICE_HANDLE XenUsbHub_UBIH_DerefDeviceHandle;
71 static USB_BUSIFFN_SET_DEVICE_HANDLE_IDLE_READY_STATE XenUsbHub_UBIH_SetDeviceHandleIdleReadyState;
72 static USB_BUSIFFN_GET_CONTAINER_ID_FOR_PORT XenUsbHub_UBIH_GetContainerIdForPort;
73 static USB_BUSIFFN_SET_CONTAINER_ID_FOR_PORT XenUsbHub_UBIH_SetContainerIdForPort;
74 static USB_BUSIFFN_ABORT_ALL_DEVICE_PIPES XenUsbHub_UBIH_AbortAllDevicePipes;
75 static USB_BUSIFFN_SET_DEVICE_ERRATA_FLAG XenUsbHub_UBIH_SetDeviceErrataFlag;
76 static USB_BUSIFFN_ACQUIRE_SEMAPHORE XenUsbHub_UBIH_AcquireBusSemaphore;
77 static USB_BUSIFFN_RELEASE_SEMAPHORE XenUsbHub_UBIH_ReleaseBusSemaphore;
78 static USB_BUSIFFN_CALC_PIPE_BANDWIDTH XenUsbHub_UBIH_CaculatePipeBandwidth;
79 static USB_BUSIFFN_SET_BUS_WAKE_MODE XenUsbHub_UBIH_SetBusSystemWakeMode;
80 static USB_BUSIFFN_SET_DEVICE_FLAG XenUsbHub_UBIH_SetDeviceFlag;
86 static VOID
87 XenUsbHub_EvtIoDefault(
88 WDFQUEUE queue,
89 WDFREQUEST request)
90 {
91 NTSTATUS status;
92 WDF_REQUEST_PARAMETERS parameters;
94 FUNCTION_ENTER();
96 UNREFERENCED_PARAMETER(queue);
98 status = STATUS_UNSUCCESSFUL;
100 WDF_REQUEST_PARAMETERS_INIT(&parameters);
101 WdfRequestGetParameters(request, &parameters);
103 switch (parameters.Type)
104 {
105 case WdfRequestTypeCreate:
106 FUNCTION_MSG("WdfRequestTypeCreate\n");
107 break;
108 case WdfRequestTypeClose:
109 FUNCTION_MSG("WdfRequestTypeClose\n");
110 break;
111 case WdfRequestTypeRead:
112 FUNCTION_MSG("WdfRequestTypeRead\n");
113 break;
114 case WdfRequestTypeWrite:
115 FUNCTION_MSG("WdfRequestTypeWrite\n");
116 break;
117 case WdfRequestTypeDeviceControl:
118 FUNCTION_MSG("WdfRequestTypeDeviceControl\n");
120 break;
121 case WdfRequestTypeDeviceControlInternal:
122 FUNCTION_MSG("WdfRequestTypeDeviceControlInternal\n");
123 break;
124 default:
125 FUNCTION_MSG("Unknown type %x\n", parameters.Type);
126 break;
127 }
128 FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n");
129 WdfRequestComplete(request, status);
131 FUNCTION_EXIT();
132 }
134 static NTSTATUS
135 XenUsbHub_BusIrpCompletionRoutine(
136 PDEVICE_OBJECT device_object,
137 PIRP irp,
138 PVOID context)
139 {
140 WDFREQUEST request = context;
142 UNREFERENCED_PARAMETER(device_object);
144 FUNCTION_ENTER();
146 FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n");
147 WdfRequestCompleteWithInformation(request, irp->IoStatus.Status, irp->IoStatus.Information);
148 IoFreeIrp(irp);
150 FUNCTION_EXIT();
152 return STATUS_MORE_PROCESSING_REQUIRED;
153 }
155 static VOID
156 XenUsbHub_EvtIoDeviceControl(
157 WDFQUEUE queue,
158 WDFREQUEST request,
159 size_t output_buffer_length,
160 size_t input_buffer_length,
161 ULONG io_control_code)
162 {
163 NTSTATUS status;
164 //WDFDEVICE device = WdfIoQueueGetDevice(queue);
165 //PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
166 //WDF_REQUEST_PARAMETERS wrp;
167 //PURB urb;
168 //xenusb_device_t *usb_device;
170 UNREFERENCED_PARAMETER(queue);
171 UNREFERENCED_PARAMETER(input_buffer_length);
172 UNREFERENCED_PARAMETER(output_buffer_length);
174 FUNCTION_ENTER();
176 status = STATUS_UNSUCCESSFUL;
178 //WDF_REQUEST_PARAMETERS_INIT(&wrp);
179 //WdfRequestGetParameters(request, &wrp);
181 // these are in api\usbioctl.h
182 switch(io_control_code)
183 {
184 case IOCTL_USB_GET_NODE_INFORMATION:
185 FUNCTION_MSG("IOCTL_USB_GET_NODE_INFORMATION\n");
186 break;
187 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
188 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
189 break;
190 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
191 FUNCTION_MSG("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
192 break;
193 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
194 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
195 break;
196 case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
197 FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_ON\n");
198 break;
199 case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
200 FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n");
201 break;
202 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
203 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
204 break;
205 case IOCTL_USB_GET_HUB_CAPABILITIES:
206 FUNCTION_MSG("IOCTL_USB_GET_HUB_CAPABILITIES\n");
207 break;
208 case IOCTL_USB_HUB_CYCLE_PORT:
209 FUNCTION_MSG("IOCTL_USB_HUB_CYCLE_PORT\n");
210 break;
211 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
212 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n");
213 break;
214 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
215 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n");
216 break;
217 case IOCTL_GET_HCD_DRIVERKEY_NAME:
218 FUNCTION_MSG("IOCTL_GET_HCD_DRIVERKEY_NAME (***)\n");
219 break;
220 default:
221 FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
222 break;
223 }
224 FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n");
225 WdfRequestComplete(request, status);
227 FUNCTION_EXIT();
228 }
230 static VOID
231 XenUsbHub_EvtIoInternalDeviceControl(
232 WDFQUEUE queue,
233 WDFREQUEST request,
234 size_t output_buffer_length,
235 size_t input_buffer_length,
236 ULONG io_control_code)
237 {
238 NTSTATUS status;
239 WDFDEVICE device = WdfIoQueueGetDevice(queue);
240 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
241 WDF_REQUEST_PARAMETERS wrp;
242 PURB urb;
243 #if (NTDDI_VERSION >= NTDDI_VISTA)
244 PUSB_START_FAILDATA usfd;
245 PHUB_DEVICE_CONFIG_INFO hdci;
246 PUSB_TOPOLOGY_ADDRESS uta;
247 PUSB_HUB_NAME uhn;
248 size_t length;
249 #endif
250 xenusb_device_t *usb_device;
252 UNREFERENCED_PARAMETER(input_buffer_length);
253 UNREFERENCED_PARAMETER(output_buffer_length);
255 //FUNCTION_ENTER();
257 status = STATUS_UNSUCCESSFUL;
259 WDF_REQUEST_PARAMETERS_INIT(&wrp);
260 WdfRequestGetParameters(request, &wrp);
262 // these are in api\usbioctl.h
263 switch(io_control_code)
264 {
265 case IOCTL_INTERNAL_USB_CYCLE_PORT:
266 FUNCTION_MSG("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
267 break;
268 case IOCTL_INTERNAL_USB_ENABLE_PORT:
269 FUNCTION_MSG("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
270 break;
271 case IOCTL_INTERNAL_USB_GET_BUS_INFO:
272 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
273 break;
274 case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME:
275 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n");
276 break;
277 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
278 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
279 FUNCTION_MSG("Count before increment = %p\n", *(PULONG)wrp.Parameters.Others.Arg1);
280 (*(PULONG)wrp.Parameters.Others.Arg1)++;
281 status = STATUS_SUCCESS;
282 break;
283 #if (NTDDI_VERSION >= NTDDI_VISTA)
284 case IOCTL_INTERNAL_USB_GET_HUB_NAME:
285 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_HUB_NAME (hub)\n");
286 status = WdfRequestRetrieveOutputBuffer(request, FIELD_OFFSET(USB_HUB_NAME, HubName) + 18, (PVOID *)&uhn, &length);
287 if (NT_SUCCESS(status))
288 {
289 /* not sure this is correct... it's not the full symbolic name */
290 uhn->ActualLength = sizeof(USB_HUB_NAME);
291 RtlStringCbCopyW(uhn->HubName, length - FIELD_OFFSET(USB_HUB_NAME, HubName), L"ROOT_HUB");
292 status = STATUS_SUCCESS;
293 }
294 break;
295 #endif
296 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
297 //FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
298 *(PULONG)wrp.Parameters.Others.Arg1 = USBD_PORT_ENABLED | USBD_PORT_CONNECTED; /* enabled and connected */
299 status = STATUS_SUCCESS;
300 break;
301 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
302 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
303 FUNCTION_MSG("WdfDeviceWdmGetPhysicalDevice(device) = %p\n", WdfDeviceWdmGetPhysicalDevice(device));
304 //FUNCTION_MSG("IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device)) = %p\n", IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
305 *(PVOID *)wrp.Parameters.Others.Arg1 = WdfDeviceWdmGetPhysicalDevice(device);
306 //*(PVOID *)wrp.Parameters.Others.Arg2 = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(device));
307 *(PVOID *)wrp.Parameters.Others.Arg2 = IoGetAttachedDevice(WdfDeviceWdmGetDeviceObject(xupdd->wdf_device_bus_fdo));
308 status = STATUS_SUCCESS;
309 break;
310 case IOCTL_INTERNAL_USB_RESET_PORT:
311 FUNCTION_MSG("IOCTL_INTERNAL_USB_RESET_PORT\n");
312 break;
313 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
314 FUNCTION_MSG("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
315 break;
316 case IOCTL_INTERNAL_USB_SUBMIT_URB:
317 //FUNCTION_MSG("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
318 urb = (PURB)wrp.Parameters.Others.Arg1;
319 ASSERT(urb);
320 usb_device = urb->UrbHeader.UsbdDeviceHandle;
321 if (!usb_device)
322 usb_device = xupdd->usb_device;
323 WdfRequestForwardToIoQueue(request, usb_device->urb_queue);
324 return;
325 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
326 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE (returning %p)\n", xupdd->usb_device);
327 *(PVOID *)wrp.Parameters.Others.Arg1 = xupdd->usb_device;
328 status = STATUS_SUCCESS;
329 break;
330 #if (NTDDI_VERSION >= NTDDI_VISTA)
331 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE_EX: /* incomplete probably */
332 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE_EX (returning %p)\n", xupdd->usb_device);
333 *(PVOID *)wrp.Parameters.Others.Arg1 = xupdd->usb_device;
334 *(ULONG_PTR *)wrp.Parameters.Others.Arg2 = (ULONG_PTR)0x12345678;
335 status = STATUS_SUCCESS;
336 break;
337 case IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS:
338 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS\n");
339 uta = (PUSB_TOPOLOGY_ADDRESS)wrp.Parameters.Others.Arg1;
340 uta->PciBusNumber = 0;
341 uta->PciDeviceNumber = 0;
342 uta->PciFunctionNumber = 0;
343 uta->RootHubPortNumber = 0;
344 uta->HubPortNumber[1] = 0;
345 uta->HubPortNumber[2] = 0;
346 uta->HubPortNumber[3] = 0;
347 uta->HubPortNumber[4] = 0;
348 status = STATUS_SUCCESS;
349 break;
350 case IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO:
351 FUNCTION_MSG("IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO\n");
352 hdci = (PHUB_DEVICE_CONFIG_INFO)wrp.Parameters.Others.Arg1;
353 hdci->Version = 1;
354 hdci->Length = 192;
355 hdci->HubFlags.ul = 0;
356 hdci->HubFlags.HubIsHighSpeedCapable = 1;
357 hdci->HubFlags.HubIsHighSpeed = 1;
358 hdci->HubFlags.HubIsMultiTtCapable = 0;
359 hdci->HubFlags.HubIsMultiTt = 0;
360 hdci->HubFlags.HubIsRoot = 1;
361 hdci->HubFlags.HubIsArmedWakeOnConnect = 1;
362 hdci->HubFlags.HubIsBusPowered = 1;
363 //hdci->HardwareIds = ?;
364 //hdci->CompatibleIds = ?;
365 //hdci->DeviceDescription = ?;
366 status = STATUS_SUCCESS;
367 break;
368 case IOCTL_INTERNAL_USB_RECORD_FAILURE:
369 FUNCTION_MSG("IOCTL_INTERNAL_USB_RECORD_FAILURE\n");
370 usfd = (PUSB_START_FAILDATA)wrp.Parameters.Others.Arg1;
371 FUNCTION_MSG(" LengthInBytes = %d\n", usfd->LengthInBytes);
372 FUNCTION_MSG(" NtStatus = %08x\n", usfd->NtStatus);
373 FUNCTION_MSG(" UsbdStatus = %08x\n", usfd->UsbdStatus);
374 FUNCTION_MSG(" ConnectStatus = %08x\n", usfd->ConnectStatus);
375 status = STATUS_SUCCESS;
376 break;
377 #endif
378 default:
379 FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
380 break;
381 }
383 if (status != STATUS_SUCCESS)
384 FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n", status);
385 WdfRequestComplete(request, status);
387 //FUNCTION_EXIT();
388 }
390 static NTSTATUS
391 XenUsbHub_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
392 {
393 NTSTATUS status = STATUS_SUCCESS;
394 DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
395 WDFSTRING symbolicname_value_wdfstring;
396 WDFKEY device_key;
397 UNICODE_STRING symbolicname_value;
399 UNREFERENCED_PARAMETER(device);
401 FUNCTION_ENTER();
403 switch (previous_state)
404 {
405 case WdfPowerDeviceD0:
406 FUNCTION_MSG("WdfPowerDeviceD1\n");
407 break;
408 case WdfPowerDeviceD1:
409 FUNCTION_MSG("WdfPowerDeviceD1\n");
410 break;
411 case WdfPowerDeviceD2:
412 FUNCTION_MSG("WdfPowerDeviceD2\n");
413 break;
414 case WdfPowerDeviceD3:
415 FUNCTION_MSG("WdfPowerDeviceD3\n");
416 break;
417 case WdfPowerDeviceD3Final:
418 FUNCTION_MSG("WdfPowerDeviceD3Final\n");
419 break;
420 case WdfPowerDevicePrepareForHibernation:
421 FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
422 break;
423 default:
424 FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", previous_state);
425 break;
426 }
428 /* USB likes to have a registry key with the symbolic link name in it. Have to wait until D0Entry as this is the PDO */
429 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
430 if (!NT_SUCCESS(status)) {
431 FUNCTION_MSG("WdfStringCreate = %08x\n", status);
432 return status;
433 }
434 status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolicname_value_wdfstring);
435 if (!NT_SUCCESS(status)) {
436 FUNCTION_MSG("WdfDeviceREtrieveDeviceInterfaceString = %08x\n", status);
437 return status;
438 }
439 WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
440 FUNCTION_MSG("ROOT_HUB SymbolicName = %S\n", symbolicname_value.Buffer);
441 status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
442 if (!NT_SUCCESS(status)) {
443 FUNCTION_MSG("WdfDeviceOpenRegistryKey = %08x\n", status);
444 return status;
445 }
446 status = WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);
447 if (!NT_SUCCESS(status)) {
448 FUNCTION_MSG("WdfDeviceOpenRegistryKey = %08x\n", status);
449 return status;
450 }
451 WdfRegistryClose(device_key);
452 FUNCTION_EXIT();
454 return status;
455 }
457 static NTSTATUS
458 XenUsbHub_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
459 {
460 NTSTATUS status = STATUS_SUCCESS;
461 //PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
462 //PXENUSB_DEVICE_DATA xudd = GetXudd(xupdd->wdf_device_bus_fdo);
464 UNREFERENCED_PARAMETER(device);
466 FUNCTION_ENTER();
468 switch (target_state)
469 {
470 case WdfPowerDeviceD0:
471 FUNCTION_MSG("WdfPowerDeviceD1\n");
472 break;
473 case WdfPowerDeviceD1:
474 FUNCTION_MSG("WdfPowerDeviceD1\n");
475 break;
476 case WdfPowerDeviceD2:
477 FUNCTION_MSG("WdfPowerDeviceD2\n");
478 break;
479 case WdfPowerDeviceD3:
480 FUNCTION_MSG("WdfPowerDeviceD3\n");
481 break;
482 case WdfPowerDeviceD3Final:
483 FUNCTION_MSG("WdfPowerDeviceD3Final\n");
484 break;
485 case WdfPowerDevicePrepareForHibernation:
486 FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
487 break;
488 default:
489 FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", target_state);
490 break;
491 }
493 FUNCTION_EXIT();
495 return status;
496 }
498 static NTSTATUS
499 XenUsbHub_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
500 {
501 NTSTATUS status = STATUS_SUCCESS;
503 UNREFERENCED_PARAMETER(device);
504 UNREFERENCED_PARAMETER(resources_raw);
505 UNREFERENCED_PARAMETER(resources_translated);
507 FUNCTION_ENTER();
508 FUNCTION_EXIT();
510 return status;
511 }
513 static NTSTATUS
514 XenUsbHub_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
515 {
516 NTSTATUS status = STATUS_SUCCESS;
518 UNREFERENCED_PARAMETER(device);
519 UNREFERENCED_PARAMETER(resources_translated);
521 FUNCTION_ENTER();
522 FUNCTION_EXIT();
524 return status;
525 }
527 static VOID
528 XenUsbHub_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
529 {
530 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
532 UNREFERENCED_PARAMETER(xupdd);
533 UNREFERENCED_PARAMETER(is_in_notification_path);
535 FUNCTION_ENTER();
537 switch (notification_type)
538 {
539 case WdfSpecialFilePaging:
540 FUNCTION_MSG("notification_type = Paging, flag = %d\n", is_in_notification_path);
541 break;
542 case WdfSpecialFileHibernation:
543 FUNCTION_MSG("notification_type = Hibernation, flag = %d\n", is_in_notification_path);
544 break;
545 case WdfSpecialFileDump:
546 FUNCTION_MSG("notification_type = Dump, flag = %d\n", is_in_notification_path);
547 break;
548 default:
549 FUNCTION_MSG("notification_type = %d, flag = %d\n", notification_type, is_in_notification_path);
550 break;
551 }
553 FUNCTION_EXIT();
554 }
556 static NTSTATUS
557 XenUsb_SubmitCompletionRoutine(
558 PDEVICE_OBJECT device_object,
559 PIRP irp,
560 PVOID context)
561 {
562 UNREFERENCED_PARAMETER(device_object);
564 FUNCTION_ENTER();
566 if (irp->PendingReturned)
567 {
568 KeSetEvent ((PKEVENT)context, IO_NO_INCREMENT, FALSE);
569 }
571 FUNCTION_EXIT();
573 return STATUS_MORE_PROCESSING_REQUIRED;
574 }
576 static NTSTATUS
577 XenUsbHub_UBIH_CreateUsbDevice(
578 PVOID BusContext,
579 PUSB_DEVICE_HANDLE *DeviceHandle,
580 PUSB_DEVICE_HANDLE HubDeviceHandle,
581 USHORT PortStatus,
582 USHORT PortNumber)
583 {
584 NTSTATUS status = STATUS_SUCCESS;
585 xenusb_device_t *usb_device;
587 UNREFERENCED_PARAMETER(BusContext);
588 UNREFERENCED_PARAMETER(HubDeviceHandle);
589 UNREFERENCED_PARAMETER(PortStatus);
591 FUNCTION_ENTER();
593 FUNCTION_MSG("BusContext = %p\n", BusContext);
594 FUNCTION_MSG("DeviceHandle = %p\n", DeviceHandle);
595 FUNCTION_MSG("*DeviceHandle = %p\n", *DeviceHandle);
596 FUNCTION_MSG("HubDeviceHandle = %p\n", HubDeviceHandle);
597 FUNCTION_MSG("PortStatus = %04X\n", PortStatus);
598 FUNCTION_MSG("PortNumber = %d\n", PortNumber);
599 usb_device = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_device_t), XENUSB_POOL_TAG);
600 if (!usb_device) {
601 FUNCTION_EXIT();
602 return STATUS_INSUFFICIENT_RESOURCES;
603 }
604 usb_device->port_number = PortNumber;
605 *DeviceHandle = usb_device;
607 FUNCTION_EXIT();
608 return status;
609 }
611 static NTSTATUS
612 XenUsbHub_UBIH_InitializeUsbDevice(
613 PVOID BusContext,
614 PUSB_DEVICE_HANDLE DeviceHandle)
615 {
616 NTSTATUS status = STATUS_SUCCESS;
617 WDFDEVICE device = BusContext;
618 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
619 //PXENUSB_DEVICE_DATA xudd = GetXudd(xupdd->wdf_device_bus_fdo);
620 WDF_IO_QUEUE_CONFIG queue_config;
621 xenusb_device_t *usb_device = DeviceHandle;
622 PUCHAR ptr;
623 PVOID buf;
624 PMDL mdl;
625 pvurb_t pvurb; /* this can be local because it never leaves this routine */
626 PUSB_DEVICE_DESCRIPTOR device_descriptor;
627 PUSB_CONFIGURATION_DESCRIPTOR config_descriptor;
628 PUSB_INTERFACE_DESCRIPTOR interface_descriptor;
629 PUSB_ENDPOINT_DESCRIPTOR endpoint_descriptor;
630 int i, j, k;
631 PUSB_DEFAULT_PIPE_SETUP_PACKET setup_packet;
632 WDF_MEMORY_DESCRIPTOR pvurb_descriptor;
633 WDF_REQUEST_SEND_OPTIONS send_options;
635 FUNCTION_ENTER();
637 FUNCTION_MSG("device = %p\n", device);
638 FUNCTION_MSG("usb_device = %p\n", usb_device);
639 usb_device->pdo_device = BusContext;
641 // TODO: get address from freelist and assign it to the device...
642 usb_device->address = (UCHAR)get_id_from_freelist(xupdd->dev_id_ss);
643 // TODO: get this stuff properly ...
644 xupdd->usb_device->device_speed = UsbHighSpeed;
645 xupdd->usb_device->device_type = Usb20Device;
647 buf = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENUSB_POOL_TAG);
648 if (!buf) {
649 FUNCTION_MSG("ExAllocatePoolWithTag(buf) failed\n");
650 return STATUS_INSUFFICIENT_RESOURCES;
651 }
652 mdl = IoAllocateMdl(buf, PAGE_SIZE, FALSE, FALSE, NULL);
653 if (!mdl) {
654 FUNCTION_MSG("IoAllocateMdl(buf) failed\n", status);
655 return STATUS_INSUFFICIENT_RESOURCES;
656 }
657 MmBuildMdlForNonPagedPool(mdl);
659 WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&pvurb_descriptor, &pvurb, sizeof(pvurb));
660 WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_TIMEOUT);
661 WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&send_options, WDF_REL_TIMEOUT_IN_SEC(10));
663 /* set the address */
664 pvurb.req.pipe = LINUX_PIPE_TYPE_CTRL | usb_device->port_number;
665 pvurb.req.transfer_flags = 0;
666 pvurb.req.buffer_length = 0;
667 setup_packet = (PUSB_DEFAULT_PIPE_SETUP_PACKET)pvurb.req.u.ctrl;
668 setup_packet->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
669 setup_packet->bmRequestType.Type = BMREQUEST_STANDARD;
670 setup_packet->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
671 setup_packet->bRequest = USB_REQUEST_SET_ADDRESS;
672 setup_packet->wValue.W = usb_device->address;
673 setup_packet->wIndex.W = 0;
674 setup_packet->wLength = pvurb.req.buffer_length;
675 pvurb.mdl = NULL;
676 status = WdfIoTargetSendInternalIoctlOthersSynchronously(xupdd->bus_fdo_target, NULL, IOCTL_INTERNAL_PVUSB_SUBMIT_URB, &pvurb_descriptor, NULL, NULL, &send_options, NULL);
677 if (!NT_SUCCESS(status)) {
678 FUNCTION_MSG("WdfIoTargetSendInternalIoctlOthersSynchronously(USB_REQUEST_SET_ADDRESS) = %08x\n", status);
679 return status;
680 }
681 FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB status = %08x\n", status);
682 FUNCTION_MSG("rsp start_frame = %d\n", pvurb.rsp.start_frame);
683 FUNCTION_MSG("rsp status = %d\n", pvurb.rsp.status);
684 FUNCTION_MSG("rsp actual_length = %d\n", pvurb.rsp.actual_length);
685 FUNCTION_MSG("rsp error_count = %d\n", pvurb.rsp.error_count);
687 /* get the device descriptor */
688 pvurb.req.pipe = LINUX_PIPE_DIRECTION_IN | LINUX_PIPE_TYPE_CTRL | (usb_device->address << 8) | usb_device->port_number;
689 pvurb.req.transfer_flags = 0;
690 pvurb.req.buffer_length = PAGE_SIZE;
691 setup_packet = (PUSB_DEFAULT_PIPE_SETUP_PACKET)pvurb.req.u.ctrl;
692 setup_packet->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
693 setup_packet->bmRequestType.Type = BMREQUEST_STANDARD;
694 setup_packet->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
695 setup_packet->bRequest = USB_REQUEST_GET_DESCRIPTOR;
696 setup_packet->wValue.LowByte = 0;
697 setup_packet->wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; //device descriptor
698 setup_packet->wIndex.W = 0;
699 setup_packet->wLength = pvurb.req.buffer_length;
700 pvurb.mdl = mdl;
701 status = WdfIoTargetSendInternalIoctlOthersSynchronously(xupdd->bus_fdo_target, NULL, IOCTL_INTERNAL_PVUSB_SUBMIT_URB, &pvurb_descriptor, NULL, NULL, &send_options, NULL);
702 if (!NT_SUCCESS(status)) {
703 FUNCTION_MSG("WdfIoTargetSendInternalIoctlOthersSynchronously(USB_REQUEST_GET_DESCRIPTOR, USB_DEVICE_DESCRIPTOR_TYPE) = %08x\n", status);
704 return status;
705 }
706 FUNCTION_MSG("rsp start_frame = %d\n", pvurb.rsp.start_frame);
707 FUNCTION_MSG("rsp status = %d\n", pvurb.rsp.status);
708 FUNCTION_MSG("rsp actual_length = %d\n", pvurb.rsp.actual_length);
709 FUNCTION_MSG("rsp error_count = %d\n", pvurb.rsp.error_count);
710 ptr = buf;
711 device_descriptor = (PUSB_DEVICE_DESCRIPTOR)ptr;
712 FUNCTION_MSG("bLength = %d\n", device_descriptor->bLength);
713 FUNCTION_MSG("bNumConfigurations = %d\n", device_descriptor->bNumConfigurations);
714 memcpy(&usb_device->device_descriptor, device_descriptor, device_descriptor->bLength);
715 usb_device->configs = ExAllocatePoolWithTag(NonPagedPool, sizeof(PVOID) * device_descriptor->bNumConfigurations, XENUSB_POOL_TAG);
716 if (!usb_device->configs) {
717 FUNCTION_MSG("ExAllocatePoolWithTag(usb_device->configs) failed\n");
718 return STATUS_INSUFFICIENT_RESOURCES;
719 }
720 FUNCTION_MSG("bLength = %d\n", device_descriptor->bLength);
721 FUNCTION_MSG("bDescriptorType = %d\n", device_descriptor->bDescriptorType);
722 FUNCTION_MSG("bcdUSB = %04x\n", device_descriptor->bcdUSB);
723 FUNCTION_MSG("bDeviceClass = %02x\n", device_descriptor->bDeviceClass);
724 FUNCTION_MSG("bDeviceSubClass = %02x\n", device_descriptor->bDeviceSubClass);
725 FUNCTION_MSG("bDeviceProtocol = %02x\n", device_descriptor->bDeviceProtocol);
726 FUNCTION_MSG("idVendor = %04x\n", device_descriptor->idVendor);
727 FUNCTION_MSG("idProduct = %04x\n", device_descriptor->idProduct);
728 FUNCTION_MSG("bcdDevice = %04x\n", device_descriptor->bcdDevice);
729 FUNCTION_MSG("bNumConfigurations = %04x\n", device_descriptor->bNumConfigurations);
731 /* get the config descriptor */
732 for (i = 0; i < device_descriptor->bNumConfigurations; i++)
733 {
734 pvurb.req.pipe = LINUX_PIPE_DIRECTION_IN | LINUX_PIPE_TYPE_CTRL | (usb_device->address << 8) | usb_device->port_number;
735 pvurb.req.transfer_flags = 0;
736 pvurb.req.buffer_length = PAGE_SIZE;
737 setup_packet = (PUSB_DEFAULT_PIPE_SETUP_PACKET)pvurb.req.u.ctrl;
738 setup_packet->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
739 setup_packet->bmRequestType.Type = BMREQUEST_STANDARD;
740 setup_packet->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
741 setup_packet->bRequest = USB_REQUEST_GET_DESCRIPTOR;
742 setup_packet->wValue.LowByte = (UCHAR)(i + 1);
743 setup_packet->wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; //device descriptor
744 setup_packet->wIndex.W = 0;
745 setup_packet->wLength = pvurb.req.buffer_length;
746 pvurb.mdl = mdl;
747 status = WdfIoTargetSendInternalIoctlOthersSynchronously(xupdd->bus_fdo_target, NULL, IOCTL_INTERNAL_PVUSB_SUBMIT_URB, &pvurb_descriptor, NULL, NULL, &send_options, NULL);
748 if (!NT_SUCCESS(status)) {
749 FUNCTION_MSG("WdfIoTargetSendInternalIoctlOthersSynchronously(USB_REQUEST_GET_DESCRIPTOR, USB_CONFIGURATION_DESCRIPTOR_TYPE) = %08x\n", status);
750 return status;
751 }
752 FUNCTION_MSG("rsp start_frame = %d\n", pvurb.rsp.start_frame);
753 FUNCTION_MSG("rsp status = %d\n", pvurb.rsp.status);
754 FUNCTION_MSG("rsp actual_length = %d\n", pvurb.rsp.actual_length);
755 FUNCTION_MSG("rsp error_count = %d\n", pvurb.rsp.error_count);
756 ptr = buf;
757 config_descriptor = (PUSB_CONFIGURATION_DESCRIPTOR)ptr;
758 FUNCTION_MSG("Config %d\n", i);
759 FUNCTION_MSG(" bLength = %d\n", config_descriptor->bLength);
760 FUNCTION_MSG(" bDescriptorType = %d\n", config_descriptor->bDescriptorType);
761 FUNCTION_MSG(" wTotalLength = %d\n", config_descriptor->wTotalLength);
762 FUNCTION_MSG(" bNumInterfaces = %d\n", config_descriptor->bNumInterfaces);
763 FUNCTION_MSG(" iConfiguration = %d\n", config_descriptor->iConfiguration);
764 FUNCTION_MSG(" bConfigurationValue = %d\n", config_descriptor->bConfigurationValue);
765 FUNCTION_MSG(" bmAttributes = %02x\n", config_descriptor->bmAttributes);
766 FUNCTION_MSG(" MaxPower = %d\n", config_descriptor->MaxPower);
767 usb_device->configs[i] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_config_t) + sizeof(PVOID) * config_descriptor->bNumInterfaces, XENUSB_POOL_TAG);
768 if (!usb_device->configs) {
769 FUNCTION_MSG("ExAllocatePoolWithTag(usb_device->configs[i]) failed\n");
770 return STATUS_INSUFFICIENT_RESOURCES;
771 }
772 usb_device->configs[i]->device = usb_device;
773 memcpy(&usb_device->configs[i]->config_descriptor, config_descriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
774 usb_device->configs[i]->config_descriptor_all = ExAllocatePoolWithTag(NonPagedPool, config_descriptor->wTotalLength, XENUSB_POOL_TAG);
775 memcpy(usb_device->configs[i]->config_descriptor_all, config_descriptor, config_descriptor->wTotalLength);
776 ptr += config_descriptor->bLength;
777 j = 0;
778 while (j < config_descriptor->bNumInterfaces)
779 {
780 interface_descriptor = (PUSB_INTERFACE_DESCRIPTOR)ptr;
781 FUNCTION_MSG(" Interface %d\n", j);
782 FUNCTION_MSG(" bLength = %d\n", interface_descriptor->bLength);
783 FUNCTION_MSG(" bDescriptorType = %d\n", interface_descriptor->bDescriptorType);
784 FUNCTION_MSG(" bInterfaceNumber = %d\n", interface_descriptor->bInterfaceNumber);
785 FUNCTION_MSG(" bAlternateSetting = %d\n", interface_descriptor->bAlternateSetting);
786 FUNCTION_MSG(" bNumEndpoints = %d\n", interface_descriptor->bNumEndpoints);
787 FUNCTION_MSG(" bInterfaceClass = %d\n", interface_descriptor->bInterfaceClass);
788 FUNCTION_MSG(" bInterfaceSubClass = %d\n", interface_descriptor->bInterfaceSubClass);
789 FUNCTION_MSG(" bInterfaceProtocol = %d\n", interface_descriptor->bInterfaceProtocol);
790 FUNCTION_MSG(" iInterface = %d\n", interface_descriptor->iInterface);
791 ptr += interface_descriptor->bLength;
792 usb_device->configs[i]->interfaces[j] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_interface_t) + sizeof(PVOID) * interface_descriptor->bNumEndpoints, XENUSB_POOL_TAG);
793 usb_device->configs[i]->interfaces[j]->config = usb_device->configs[i];
794 memcpy(&usb_device->configs[i]->interfaces[j]->interface_descriptor, interface_descriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
795 k = 0;
796 while (k < interface_descriptor->bNumEndpoints)
797 {
798 endpoint_descriptor = (PUSB_ENDPOINT_DESCRIPTOR)ptr;
799 if (endpoint_descriptor->bDescriptorType != 5)
800 {
801 FUNCTION_MSG(" Unknown bDescriptorType %d found length = %d\n", endpoint_descriptor->bDescriptorType, endpoint_descriptor->bLength);
802 ptr += endpoint_descriptor->bLength;
803 continue;
804 }
806 FUNCTION_MSG(" Endpoint %d\n", k);
807 FUNCTION_MSG(" bLength = %d\n", endpoint_descriptor->bLength);
808 FUNCTION_MSG(" bDescriptorType = %d\n", endpoint_descriptor->bDescriptorType);
809 FUNCTION_MSG(" bEndpointAddress = %02x\n", endpoint_descriptor->bEndpointAddress);
810 FUNCTION_MSG(" bmAttributes = %02x\n", endpoint_descriptor->bmAttributes);
811 FUNCTION_MSG(" wMaxPacketSize = %d\n", endpoint_descriptor->wMaxPacketSize);
812 FUNCTION_MSG(" bInterval = %d\n", endpoint_descriptor->bInterval);
813 ptr += endpoint_descriptor->bLength;
814 usb_device->configs[i]->interfaces[j]->endpoints[k] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_endpoint_t), XENUSB_POOL_TAG);
815 usb_device->configs[i]->interfaces[j]->endpoints[k]->interface = usb_device->configs[i]->interfaces[j];
816 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value = (usb_device->address << 8) | usb_device->port_number;
817 /* linux uses nonstandard endpoint type identifiers... */
818 switch(endpoint_descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
819 {
820 case USB_ENDPOINT_TYPE_CONTROL:
821 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= LINUX_PIPE_TYPE_CTRL;
822 break;
823 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
824 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= LINUX_PIPE_TYPE_ISOC;
825 break;
826 case USB_ENDPOINT_TYPE_BULK:
827 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= LINUX_PIPE_TYPE_BULK;
828 break;
829 case USB_ENDPOINT_TYPE_INTERRUPT:
830 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= LINUX_PIPE_TYPE_INTR;
831 break;
832 }
833 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= (endpoint_descriptor->bEndpointAddress & 0x80);
834 usb_device->configs[i]->interfaces[j]->endpoints[k]->pipe_value |= (endpoint_descriptor->bEndpointAddress & 0x0F) << 15;
835 memcpy(&usb_device->configs[i]->interfaces[j]->endpoints[k]->endpoint_descriptor, endpoint_descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
836 k++;
837 }
838 j++;
839 }
840 }
841 ExFreePoolWithTag(buf, XENUSB_POOL_TAG);
843 usb_device->active_config = usb_device->configs[0];
844 usb_device->active_interface = usb_device->configs[0]->interfaces[0];
846 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel); // should this be serial?
847 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_DEVICE_SUBMIT_URB;
848 queue_config.PowerManaged = TRUE; /* power managed queue for SUBMIT_URB */
849 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &usb_device->urb_queue);
850 if (!NT_SUCCESS(status)) {
851 FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
852 return status;
853 }
854 FUNCTION_EXIT();
855 return status;
856 }
858 static NTSTATUS
859 XenUsbHub_UBIH_GetUsbDescriptors(
860 PVOID BusContext,
861 PUSB_DEVICE_HANDLE DeviceHandle,
862 PUCHAR DeviceDescriptorBuffer,
863 PULONG DeviceDescriptorBufferLength,
864 PUCHAR ConfigDescriptorBuffer,
865 PULONG ConfigDescriptorBufferLength
866 )
867 {
868 NTSTATUS status = STATUS_SUCCESS;
869 xenusb_device_t *usb_device = DeviceHandle;
870 xenusb_config_t *usb_config;
871 PUCHAR ptr;
873 UNREFERENCED_PARAMETER(BusContext);
875 FUNCTION_ENTER();
877 FUNCTION_MSG("BusContext = %p\n", BusContext);
878 FUNCTION_MSG("DeviceHandle = %p\n", DeviceHandle);
879 FUNCTION_MSG("DeviceDescriptorBuffer = %p\n", DeviceDescriptorBuffer);
880 FUNCTION_MSG("DeviceDescriptorBufferLength = %d\n", *DeviceDescriptorBufferLength);
881 FUNCTION_MSG("ConfigDescriptorBuffer = %p\n", ConfigDescriptorBuffer);
882 FUNCTION_MSG("ConfigDescriptorBufferLength = %d\n", *ConfigDescriptorBufferLength);
884 memcpy(DeviceDescriptorBuffer, &usb_device->device_descriptor, usb_device->device_descriptor.bLength);
885 *DeviceDescriptorBufferLength = usb_device->device_descriptor.bLength;
887 usb_config = usb_device->active_config;
888 ptr = ConfigDescriptorBuffer;
889 memcpy(ptr, usb_config->config_descriptor_all, min(usb_config->config_descriptor.wTotalLength, *ConfigDescriptorBufferLength));
890 *ConfigDescriptorBufferLength = ((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer)->wTotalLength;
892 #if 0
893 ptr += sizeof(USB_CONFIGURATION_DESCRIPTOR);
894 // why was this here? ((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer)->wTotalLength += 1;
896 for (i = 0; i < usb_config->config_descriptor.bNumInterfaces; i++)
897 {
898 memcpy(ptr, &usb_config->interfaces[i]->interface_descriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
899 ptr += sizeof(USB_INTERFACE_DESCRIPTOR);
900 ((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer)->wTotalLength += sizeof(USB_INTERFACE_DESCRIPTOR);
901 for (j = 0; j < usb_config->interfaces[i]->interface_descriptor.bNumEndpoints; j++)
902 {
903 memcpy(ptr, &usb_config->interfaces[i]->endpoints[j]->endpoint_descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
904 ptr += sizeof(USB_ENDPOINT_DESCRIPTOR);
905 ((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer)->wTotalLength += sizeof(USB_ENDPOINT_DESCRIPTOR);
906 }
907 }
908 *ConfigDescriptorBufferLength = ((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer)->wTotalLength;
909 #endif
911 FUNCTION_EXIT();
912 return status;
913 }
915 static NTSTATUS
916 XenUsbHub_UBIH_RemoveUsbDevice (
917 PVOID BusContext,
918 PUSB_DEVICE_HANDLE DeviceHandle,
919 ULONG Flags)
920 {
921 NTSTATUS status = STATUS_SUCCESS;
922 WDFDEVICE device = BusContext;
923 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
924 xenusb_device_t *usb_device = DeviceHandle;
925 int i, j, k;
927 FUNCTION_ENTER();
929 if (Flags & USBD_KEEP_DEVICE_DATA)
930 FUNCTION_MSG("USBD_KEEP_DEVICE_DATA\n");
932 if (Flags & USBD_MARK_DEVICE_BUSY)
933 FUNCTION_MSG("USBD_MARK_DEVICE_BUSY\n");
935 put_id_on_freelist(xupdd->dev_id_ss, (uint16_t)usb_device->address);
936 // check if there are no pending requests
937 for (i = 0; i < usb_device->device_descriptor.bNumConfigurations; i++) {
938 for (j = 0; j < usb_device->configs[i]->config_descriptor.bNumInterfaces; j++) {
939 for (k = 0; k < usb_device->configs[i]->interfaces[j]->interface_descriptor.bNumEndpoints; k++) {
940 ExFreePoolWithTag(usb_device->configs[i]->interfaces[j]->endpoints[k], XENUSB_POOL_TAG);
941 }
942 ExFreePoolWithTag(usb_device->configs[i]->interfaces[j], XENUSB_POOL_TAG);
943 }
944 ExFreePoolWithTag(usb_device->configs[i]->config_descriptor_all, XENUSB_POOL_TAG);
945 ExFreePoolWithTag(usb_device->configs[i], XENUSB_POOL_TAG);
946 }
947 ExFreePoolWithTag(usb_device->configs, XENUSB_POOL_TAG);
948 ExFreePoolWithTag(usb_device, XENUSB_POOL_TAG);
949 FUNCTION_EXIT();
950 return status;
951 }
953 static NTSTATUS
954 XenUsbHub_UBIH_RestoreUsbDevice(
955 PVOID BusContext,
956 PUSB_DEVICE_HANDLE OldDeviceHandle,
957 PUSB_DEVICE_HANDLE NewDeviceHandle)
958 {
959 NTSTATUS status = STATUS_UNSUCCESSFUL;
961 UNREFERENCED_PARAMETER(BusContext);
962 UNREFERENCED_PARAMETER(OldDeviceHandle);
963 UNREFERENCED_PARAMETER(NewDeviceHandle);
965 FUNCTION_ENTER();
967 FUNCTION_EXIT();
968 return status;
969 }
971 static NTSTATUS
972 XenUsbHub_UBIH_GetPortHackFlags(
973 PVOID BusContext,
974 PULONG HackFlags)
975 {
976 NTSTATUS status = STATUS_UNSUCCESSFUL;
978 UNREFERENCED_PARAMETER(BusContext);
979 UNREFERENCED_PARAMETER(HackFlags);
981 FUNCTION_ENTER();
983 FUNCTION_EXIT();
984 return status;
985 }
987 static NTSTATUS
988 XenUsbHub_UBIH_QueryDeviceInformation(
989 PVOID BusContext,
990 PUSB_DEVICE_HANDLE DeviceHandle,
991 PVOID DeviceInformationBuffer,
992 ULONG DeviceInformationBufferLength,
993 PULONG LengthOfDataReturned)
994 {
995 PUSB_DEVICE_INFORMATION_0 udi = DeviceInformationBuffer;
996 xenusb_device_t *usb_device = DeviceHandle;
997 ULONG i;
998 ULONG required_size;
1000 UNREFERENCED_PARAMETER(BusContext);
1002 FUNCTION_ENTER();
1004 FUNCTION_MSG("BusContext = %p\n", BusContext);
1005 FUNCTION_MSG("DeviceHandle = %p\n", DeviceHandle);
1006 FUNCTION_MSG("DeviceInformationBuffer = %p\n", DeviceInformationBuffer);
1007 FUNCTION_MSG("DeviceInformationBufferLength = %d\n", DeviceInformationBufferLength);
1008 FUNCTION_MSG("->InformationLevel = %d\n", udi->InformationLevel);
1009 required_size = (ULONG)FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[usb_device->active_interface->interface_descriptor.bNumEndpoints]);
1010 FUNCTION_MSG("required_size = %d\n", required_size);
1011 *LengthOfDataReturned = required_size;
1012 udi->ActualLength = required_size;
1013 if (DeviceInformationBufferLength < required_size)
1015 FUNCTION_MSG("STATUS_BUFFER_TOO_SMALL\n");
1016 FUNCTION_EXIT();
1017 return STATUS_BUFFER_TOO_SMALL;
1019 if (udi->InformationLevel != 0)
1021 FUNCTION_MSG("STATUS_NOT_SUPPORTED\n");
1022 FUNCTION_EXIT();
1023 return STATUS_NOT_SUPPORTED;
1025 udi->PortNumber = 1;
1026 memcpy(&udi->DeviceDescriptor, &usb_device->device_descriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1027 udi->CurrentConfigurationValue = usb_device->active_config->config_descriptor.bConfigurationValue;
1028 udi->DeviceAddress = usb_device->address;
1029 udi->HubAddress = 1; // ?
1030 udi->DeviceSpeed = usb_device->device_speed;
1031 udi->DeviceType = usb_device->device_type;
1032 udi->NumberOfOpenPipes = usb_device->active_interface->interface_descriptor.bNumEndpoints;
1033 for (i = 0; i < usb_device->active_interface->interface_descriptor.bNumEndpoints; i++)
1035 memcpy(&udi->PipeList[i].EndpointDescriptor, &usb_device->active_interface->endpoints[i]->endpoint_descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
1036 udi->PipeList[0].ScheduleOffset = 0; // not necessarily right
1038 FUNCTION_EXIT();
1039 return STATUS_SUCCESS;
1042 static NTSTATUS
1043 XenUsbHub_UBIH_GetControllerInformation (
1044 PVOID BusContext,
1045 PVOID ControllerInformationBuffer,
1046 ULONG ControllerInformationBufferLength,
1047 PULONG LengthOfDataReturned)
1049 NTSTATUS status = STATUS_UNSUCCESSFUL;
1050 PUSB_CONTROLLER_INFORMATION_0 uci = ControllerInformationBuffer;
1051 //WDFDEVICE device = BusContext;
1052 //xenusb_device_t *usb_device = DeviceHandle;
1054 UNREFERENCED_PARAMETER(BusContext);
1056 FUNCTION_ENTER();
1058 FUNCTION_MSG("BusContext = %p\n", BusContext);
1059 FUNCTION_MSG("ControllerInformationBuffer = %p\n", ControllerInformationBuffer);
1060 FUNCTION_MSG("ControllerInformationBufferLength = %d\n", ControllerInformationBufferLength);
1061 FUNCTION_MSG("->InformationLevel = %d\n", uci->InformationLevel);
1062 if (ControllerInformationBufferLength < sizeof(USB_CONTROLLER_INFORMATION_0)) {
1063 FUNCTION_MSG("STATUS_BUFFER_TOO_SMALL\n");
1064 FUNCTION_EXIT();
1065 return STATUS_BUFFER_TOO_SMALL;
1067 if (uci->InformationLevel != 0) {
1068 FUNCTION_MSG("STATUS_NOT_SUPPORTED\n");
1069 FUNCTION_EXIT();
1070 return STATUS_NOT_SUPPORTED;
1073 uci->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
1074 uci->SelectiveSuspendEnabled = FALSE;
1075 uci->IsHighSpeedController = TRUE;
1076 *LengthOfDataReturned = uci->ActualLength;
1078 FUNCTION_EXIT();
1079 return status;
1082 static NTSTATUS
1083 XenUsbHub_UBIH_ControllerSelectiveSuspend (
1084 PVOID BusContext,
1085 BOOLEAN Enable)
1087 NTSTATUS status = STATUS_UNSUCCESSFUL;
1089 UNREFERENCED_PARAMETER(BusContext);
1090 UNREFERENCED_PARAMETER(Enable);
1092 FUNCTION_ENTER();
1094 FUNCTION_EXIT();
1095 return status;
1098 static NTSTATUS
1099 XenUsbHub_UBIH_GetExtendedHubInformation (
1100 PVOID BusContext,
1101 PDEVICE_OBJECT HubPhysicalDeviceObject,
1102 PVOID HubInformationBuffer,
1103 ULONG HubInformationBufferLength,
1104 PULONG LengthOfDataReturned)
1106 PUSB_EXTHUB_INFORMATION_0 hib = HubInformationBuffer;
1107 ULONG i;
1109 UNREFERENCED_PARAMETER(BusContext);
1110 UNREFERENCED_PARAMETER(HubPhysicalDeviceObject);
1112 FUNCTION_ENTER();
1114 FUNCTION_MSG("BusContext = %p\n", BusContext);
1115 FUNCTION_MSG("HubPhysicalDeviceObject = %p\n", HubPhysicalDeviceObject);
1116 FUNCTION_MSG("HubInformationBuffer = %p\n", HubInformationBuffer);
1117 FUNCTION_MSG("HubInformationBufferLength = %d\n", HubInformationBufferLength);
1118 FUNCTION_MSG("->InformationLevel = %d\n", hib->InformationLevel);
1119 if (HubInformationBufferLength < (ULONG)FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[8]))
1121 FUNCTION_MSG("STATUS_BUFFER_TOO_SMALL\n");
1122 FUNCTION_EXIT();
1123 return STATUS_BUFFER_TOO_SMALL;
1125 #if 0
1126 if (hib->InformationLevel != 0)
1128 FUNCTION_MSG("STATUS_NOT_SUPPORTED\n");
1129 FUNCTION_EXIT();
1130 return STATUS_NOT_SUPPORTED;
1132 #endif
1133 hib->InformationLevel = 0;
1134 hib->NumberOfPorts = 8;
1135 for (i = 0; i < hib->NumberOfPorts; i++)
1137 hib->Port[i].PhysicalPortNumber = i + 1;
1138 hib->Port[i].PortLabelNumber = i + 1;
1139 hib->Port[i].VidOverride = 0;
1140 hib->Port[i].PidOverride = 0;
1141 hib->Port[i].PortAttributes = USB_PORTATTR_SHARED_USB2; // | USB_PORTATTR_NO_OVERCURRENT_UI;
1143 *LengthOfDataReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[8]);
1144 FUNCTION_EXIT();
1145 return STATUS_SUCCESS;
1148 static NTSTATUS
1149 XenUsbHub_UBIH_GetRootHubSymbolicName(
1150 PVOID BusContext,
1151 PVOID HubInformationBuffer,
1152 ULONG HubInformationBufferLength,
1153 PULONG HubNameActualLength)
1155 NTSTATUS status = STATUS_SUCCESS;
1156 FUNCTION_ENTER();
1158 UNREFERENCED_PARAMETER(BusContext);
1160 FUNCTION_MSG("BusContext = %p\n", BusContext);
1161 FUNCTION_MSG("HubInformationBuffer = %p\n", HubInformationBuffer);
1162 FUNCTION_MSG("HubInformationBufferLength = %d\n", HubInformationBufferLength);
1163 RtlStringCbCopyW(HubInformationBuffer, HubInformationBufferLength, L"ROOT_HUB");
1164 *HubNameActualLength = 16;
1166 FUNCTION_EXIT();
1167 return status;
1170 static PVOID
1171 XenUsbHub_UBIH_GetDeviceBusContext(
1172 PVOID BusContext,
1173 PVOID DeviceHandle)
1175 UNREFERENCED_PARAMETER(BusContext);
1176 UNREFERENCED_PARAMETER(DeviceHandle);
1178 FUNCTION_ENTER();
1180 FUNCTION_EXIT();
1181 return NULL;
1184 static NTSTATUS
1185 XenUsbHub_UBIH_Initialize20Hub (
1186 PVOID BusContext,
1187 PUSB_DEVICE_HANDLE HubDeviceHandle,
1188 ULONG TtCount)
1190 NTSTATUS status = STATUS_SUCCESS;
1192 UNREFERENCED_PARAMETER(BusContext);
1193 UNREFERENCED_PARAMETER(HubDeviceHandle);
1194 UNREFERENCED_PARAMETER(TtCount);
1196 FUNCTION_ENTER();
1197 FUNCTION_MSG("BusContext = %p\n", BusContext);
1198 FUNCTION_MSG("HubDeviceHandle = %p\n", HubDeviceHandle);
1199 FUNCTION_MSG("TtCount = %d\n", TtCount);
1200 FUNCTION_EXIT();
1201 return status;
1204 static NTSTATUS
1205 XenUsbHub_UBIH_RootHubInitNotification(
1206 PVOID BusContext,
1207 PVOID CallbackContext,
1208 PRH_INIT_CALLBACK CallbackFunction)
1210 NTSTATUS status = STATUS_SUCCESS;
1211 WDFDEVICE device = BusContext;
1212 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device);
1214 FUNCTION_ENTER();
1216 xupdd->BusCallbackFunction = CallbackFunction;
1217 xupdd->BusCallbackContext = CallbackContext;
1219 xupdd->BusCallbackFunction(xupdd->BusCallbackContext);
1221 FUNCTION_EXIT();
1222 return status;
1225 /* This definition is incorrect in the docs */
1226 static VOID
1227 XenUsbHub_UBIH_FlushTransfers(
1228 PVOID BusContext,
1229 PVOID DeviceHandle)
1231 UNREFERENCED_PARAMETER(BusContext);
1232 UNREFERENCED_PARAMETER(DeviceHandle);
1234 FUNCTION_ENTER();
1236 FUNCTION_EXIT();
1239 static VOID
1240 XenUsbHub_UBIH_SetDeviceHandleData(
1241 PVOID BusContext,
1242 PUSB_DEVICE_HANDLE DeviceHandle,
1243 PDEVICE_OBJECT UsbDevicePdo)
1245 UNREFERENCED_PARAMETER(BusContext);
1246 UNREFERENCED_PARAMETER(DeviceHandle);
1247 UNREFERENCED_PARAMETER(UsbDevicePdo);
1249 FUNCTION_ENTER();
1250 FUNCTION_EXIT();
1253 static NTSTATUS
1254 XenUsbHub_UBIH_CreateUsbDeviceEx(
1255 PVOID BusContext,
1256 PUSB_DEVICE_HANDLE *DeviceHandle,
1257 PUSB_DEVICE_HANDLE HubDeviceHandle,
1258 USHORT PortStatus,
1259 USHORT PortNumber,
1260 PUSB_CD_ERROR_INFORMATION CdErrorInfo,
1261 USHORT TtPortNumber)
1263 NTSTATUS status = STATUS_SUCCESS;
1265 UNREFERENCED_PARAMETER(CdErrorInfo);
1266 UNREFERENCED_PARAMETER(TtPortNumber);
1268 FUNCTION_ENTER();
1270 status = XenUsbHub_UBIH_CreateUsbDevice(BusContext, DeviceHandle, HubDeviceHandle, PortStatus, PortNumber);
1272 FUNCTION_MSG("CdErrorInfo = %p\n", CdErrorInfo);
1273 FUNCTION_MSG("TtPortNumber = %d\n", TtPortNumber);
1275 FUNCTION_EXIT();
1276 return status;
1279 #if (NTDDI_VERSION >= NTDDI_VISTA)
1280 static NTSTATUS
1281 XenUsbHub_UBIH_CreateUsbDeviceV7(
1282 PVOID BusContext,
1283 PUSB_DEVICE_HANDLE *NewDeviceHandle,
1284 PUSB_DEVICE_HANDLE HsHubDeviceHandle,
1285 USHORT PortStatus,
1286 PUSB_PORT_PATH PortPath,
1287 PUSB_CD_ERROR_INFORMATION CdErrorInfo,
1288 USHORT TtPortNumber,
1289 PDEVICE_OBJECT PdoDeviceObject,
1290 PUNICODE_STRING PhysicalDeviceObjectName)
1292 NTSTATUS status;
1294 UNREFERENCED_PARAMETER(PdoDeviceObject);
1295 UNREFERENCED_PARAMETER(PhysicalDeviceObjectName);
1297 FUNCTION_ENTER();
1298 FUNCTION_MSG("PortPath->PortPathDepth = %d\n", PortPath->PortPathDepth);
1299 FUNCTION_MSG("PortPath->PortPath[%d] = %d\n", PortPath->PortPathDepth - 1);
1300 status = XenUsbHub_UBIH_CreateUsbDeviceEx(BusContext, NewDeviceHandle, &HsHubDeviceHandle, PortStatus, (USHORT)PortPath->PortPath[PortPath->PortPathDepth-1], CdErrorInfo, TtPortNumber);
1301 FUNCTION_MSG("PdoDeviceObject = %p\n", PdoDeviceObject);
1302 FUNCTION_MSG("PhysicalDeviceObjectName = %S\n", PhysicalDeviceObjectName->Buffer);
1303 FUNCTION_EXIT();
1304 return status;
1306 #endif
1308 static NTSTATUS
1309 XenUsbHub_UBIH_InitializeUsbDeviceEx(
1310 PVOID BusContext,
1311 PUSB_DEVICE_HANDLE DeviceHandle,
1312 PUSB_ID_ERROR_INFORMATION IdErrInfo)
1314 NTSTATUS status;
1316 UNREFERENCED_PARAMETER(BusContext);
1317 UNREFERENCED_PARAMETER(DeviceHandle);
1318 UNREFERENCED_PARAMETER(IdErrInfo);
1319 FUNCTION_ENTER();
1320 FUNCTION_MSG("IdErrInfo->Version = %d\n", IdErrInfo->Version);
1321 FUNCTION_MSG("IdErrInfo->PathError = %d\n", IdErrInfo->PathError);
1322 FUNCTION_MSG("IdErrInfo->Arg1 = %08x\n", IdErrInfo->Arg1);
1323 FUNCTION_MSG("IdErrInfo->UsbAddress = %d\n", IdErrInfo->UsbAddress);
1324 FUNCTION_MSG("IdErrInfo->NtStatus = %08x\n", IdErrInfo->NtStatus);
1325 FUNCTION_MSG("IdErrInfo->UsbdStatus = %08x\n", IdErrInfo->UsbdStatus);
1326 FUNCTION_MSG("IdErrInfo->XtraInfo = %s\n", IdErrInfo->XtraInfo);
1327 status = XenUsbHub_UBIH_InitializeUsbDevice(BusContext, DeviceHandle);
1328 FUNCTION_EXIT();
1329 return status;
1332 static BOOLEAN
1333 XenUsbHub_UBIH_HubIsRoot(
1334 PVOID BusContext,
1335 PVOID DeviceObject)
1337 UNREFERENCED_PARAMETER(BusContext);
1338 UNREFERENCED_PARAMETER(DeviceObject);
1340 FUNCTION_ENTER();
1341 FUNCTION_EXIT();
1342 return TRUE;
1345 static VOID
1346 XenUsbHub_UBIH_AcquireBusSemaphore(
1347 PVOID BusContext)
1349 UNREFERENCED_PARAMETER(BusContext);
1350 FUNCTION_ENTER();
1351 FUNCTION_EXIT();
1352 return;
1355 static VOID
1356 XenUsbHub_UBIH_ReleaseBusSemaphore(
1357 PVOID BusContext)
1359 UNREFERENCED_PARAMETER(BusContext);
1360 FUNCTION_ENTER();
1361 FUNCTION_EXIT();
1362 return;
1365 static ULONG
1366 XenUsbHub_UBIH_CaculatePipeBandwidth(
1367 PVOID BusContext,
1368 PUSBD_PIPE_INFORMATION PipeInfo,
1369 USB_DEVICE_SPEED DeviceSpeed)
1371 UNREFERENCED_PARAMETER(BusContext);
1372 UNREFERENCED_PARAMETER(PipeInfo);
1373 UNREFERENCED_PARAMETER(DeviceSpeed);
1374 FUNCTION_ENTER();
1375 FUNCTION_EXIT();
1376 return (ULONG)-1;
1379 static VOID
1380 XenUsbHub_UBIH_SetBusSystemWakeMode(
1381 PVOID BusContext,
1382 ULONG Mode)
1384 UNREFERENCED_PARAMETER(BusContext);
1385 UNREFERENCED_PARAMETER(Mode);
1386 FUNCTION_ENTER();
1387 FUNCTION_EXIT();
1388 return;
1391 static VOID
1392 XenUsbHub_UBIH_SetDeviceFlag(
1393 PVOID BusContext,
1394 GUID *DeviceFlagGuid,
1395 PVOID ValueData,
1396 ULONG ValueLength)
1398 UNREFERENCED_PARAMETER(BusContext);
1399 UNREFERENCED_PARAMETER(DeviceFlagGuid);
1400 UNREFERENCED_PARAMETER(ValueData);
1401 UNREFERENCED_PARAMETER(ValueLength);
1402 FUNCTION_ENTER();
1403 FUNCTION_EXIT();
1404 return;
1407 static NTSTATUS
1408 XenUsbHub_UBIH_HubTestPoint(
1409 PVOID bus_context,
1410 PVOID device_handle,
1411 ULONG op_code,
1412 PVOID test_data)
1414 UNREFERENCED_PARAMETER(bus_context);
1415 UNREFERENCED_PARAMETER(device_handle);
1416 UNREFERENCED_PARAMETER(op_code);
1417 UNREFERENCED_PARAMETER(test_data);
1418 FUNCTION_ENTER();
1419 FUNCTION_MSG("device_handle = %p\n", device_handle);
1420 FUNCTION_MSG("op_code = %p\n", op_code);
1421 FUNCTION_MSG("test_data = %p\n", test_data);
1422 FUNCTION_EXIT();
1423 return STATUS_SUCCESS;
1426 static NTSTATUS
1427 XenUsbHub_UBIH_GetDevicePerformanceInfo(
1428 PVOID BusContext,
1429 PUSB_DEVICE_HANDLE DeviceHandle,
1430 PVOID DeviceInformationBuffer,
1431 ULONG DeviceInformationBufferLength,
1432 PULONG LengthOfDataCopied)
1434 UNREFERENCED_PARAMETER(BusContext);
1435 UNREFERENCED_PARAMETER(DeviceHandle);
1436 UNREFERENCED_PARAMETER(DeviceInformationBuffer);
1437 UNREFERENCED_PARAMETER(DeviceInformationBufferLength);
1438 UNREFERENCED_PARAMETER(LengthOfDataCopied);
1439 FUNCTION_ENTER();
1440 FUNCTION_EXIT();
1441 return STATUS_UNSUCCESSFUL;
1444 static NTSTATUS
1445 XenUsbHub_UBIH_WaitAsyncPowerUp(
1446 PVOID BusContext)
1448 UNREFERENCED_PARAMETER(BusContext);
1449 FUNCTION_ENTER();
1450 FUNCTION_EXIT();
1451 return STATUS_UNSUCCESSFUL;
1454 static NTSTATUS
1455 XenUsbHub_UBIH_GetDeviceAddress(
1456 PVOID BusContext,
1457 PUSB_DEVICE_HANDLE DeviceHandle,
1458 PUSHORT DeviceAddress)
1460 UNREFERENCED_PARAMETER(BusContext);
1461 UNREFERENCED_PARAMETER(DeviceHandle);
1462 UNREFERENCED_PARAMETER(DeviceAddress);
1463 FUNCTION_ENTER();
1464 FUNCTION_EXIT();
1465 return STATUS_UNSUCCESSFUL;
1468 static NTSTATUS
1469 XenUsbHub_UBIH_RefDeviceHandle(
1470 PVOID BusContext,
1471 PUSB_DEVICE_HANDLE DeviceHandle,
1472 PVOID Object,
1473 ULONG Tag)
1475 UNREFERENCED_PARAMETER(BusContext);
1476 UNREFERENCED_PARAMETER(DeviceHandle);
1477 UNREFERENCED_PARAMETER(Object);
1478 UNREFERENCED_PARAMETER(Tag);
1479 FUNCTION_ENTER();
1480 FUNCTION_MSG("This should do something\n");
1481 FUNCTION_EXIT();
1482 return STATUS_SUCCESS;
1485 static VOID
1486 XenUsbHub_UBIH_DerefDeviceHandle(
1487 PVOID BusContext,
1488 PUSB_DEVICE_HANDLE DeviceHandle,
1489 PVOID Object,
1490 ULONG Tag)
1492 UNREFERENCED_PARAMETER(BusContext);
1493 UNREFERENCED_PARAMETER(DeviceHandle);
1494 UNREFERENCED_PARAMETER(Object);
1495 UNREFERENCED_PARAMETER(Tag);
1496 FUNCTION_ENTER();
1497 FUNCTION_MSG("This should do something\n");
1498 FUNCTION_EXIT();
1501 static ULONG
1502 XenUsbHub_UBIH_SetDeviceHandleIdleReadyState(
1503 PVOID BusContext,
1504 PUSB_DEVICE_HANDLE DeviceHandle,
1505 ULONG NewIdleReadyState)
1507 UNREFERENCED_PARAMETER(BusContext);
1508 UNREFERENCED_PARAMETER(DeviceHandle);
1509 UNREFERENCED_PARAMETER(NewIdleReadyState);
1510 FUNCTION_ENTER();
1511 FUNCTION_EXIT();
1512 return (ULONG)-1;
1515 static NTSTATUS
1516 XenUsbHub_UBIH_GetContainerIdForPort(
1517 PVOID BusContext,
1518 USHORT PortNumber,
1519 LPGUID ContainerId)
1521 UNREFERENCED_PARAMETER(BusContext);
1522 UNREFERENCED_PARAMETER(PortNumber);
1523 UNREFERENCED_PARAMETER(ContainerId);
1524 FUNCTION_ENTER();
1525 FUNCTION_EXIT();
1526 return STATUS_UNSUCCESSFUL;
1529 static VOID
1530 XenUsbHub_UBIH_SetContainerIdForPort(
1531 PVOID BusContext,
1532 USHORT PortNumber,
1533 LPGUID ContainerId)
1535 UNREFERENCED_PARAMETER(BusContext);
1536 UNREFERENCED_PARAMETER(PortNumber);
1537 UNREFERENCED_PARAMETER(ContainerId);
1538 FUNCTION_ENTER();
1539 FUNCTION_EXIT();
1542 static NTSTATUS
1543 XenUsbHub_UBIH_AbortAllDevicePipes(
1544 PVOID BusContext,
1545 PUSB_DEVICE_HANDLE DeviceHandle)
1547 UNREFERENCED_PARAMETER(BusContext);
1548 UNREFERENCED_PARAMETER(DeviceHandle);
1549 FUNCTION_ENTER();
1550 FUNCTION_EXIT();
1551 return STATUS_SUCCESS;
1554 static VOID
1555 XenUsbHub_UBIH_SetDeviceErrataFlag(
1556 PVOID BusContext,
1557 PUSB_DEVICE_HANDLE DeviceHandle,
1558 ULONG DeviceErrataFlag)
1560 UNREFERENCED_PARAMETER(BusContext);
1561 UNREFERENCED_PARAMETER(DeviceHandle);
1562 UNREFERENCED_PARAMETER(DeviceErrataFlag);
1563 FUNCTION_ENTER();
1564 FUNCTION_EXIT();
1565 return;
1568 static NTSTATUS
1569 XenUsbHub_UBIU_GetUSBDIVersion(
1570 PVOID BusContext,
1571 PUSBD_VERSION_INFORMATION VersionInformation,
1572 PULONG HcdCapabilities
1575 NTSTATUS status = STATUS_UNSUCCESSFUL;
1577 UNREFERENCED_PARAMETER(BusContext);
1578 UNREFERENCED_PARAMETER(VersionInformation);
1579 UNREFERENCED_PARAMETER(HcdCapabilities);
1581 FUNCTION_ENTER();
1583 FUNCTION_EXIT();
1584 return status;
1587 static NTSTATUS
1588 XenUsbHub_UBIU_QueryBusTime(
1589 PVOID BusContext,
1590 PULONG CurrentFrame
1593 NTSTATUS status = STATUS_SUCCESS;
1594 static ULONG frame_no = 0;
1596 UNREFERENCED_PARAMETER(BusContext);
1597 UNREFERENCED_PARAMETER(CurrentFrame);
1599 //FUNCTION_ENTER();
1600 *CurrentFrame = frame_no++;
1601 //FUNCTION_EXIT();
1602 return status;
1605 static NTSTATUS
1606 XenUsbHub_UBIU_SubmitIsoOutUrb(
1607 PVOID BusContext,
1608 PURB Urb
1611 NTSTATUS status = STATUS_UNSUCCESSFUL;
1613 UNREFERENCED_PARAMETER(BusContext);
1614 UNREFERENCED_PARAMETER(Urb);
1616 FUNCTION_ENTER();
1618 FUNCTION_EXIT();
1619 return status;
1622 static NTSTATUS
1623 XenUsbHub_UBIU_QueryBusInformation(
1624 PVOID BusContext,
1625 ULONG Level,
1626 PVOID BusInformationBuffer,
1627 PULONG BusInformationBufferLength,
1628 PULONG BusInformationActualLength)
1630 NTSTATUS status = STATUS_UNSUCCESSFUL;
1632 UNREFERENCED_PARAMETER(BusContext);
1633 UNREFERENCED_PARAMETER(Level);
1634 UNREFERENCED_PARAMETER(BusInformationBuffer);
1635 UNREFERENCED_PARAMETER(BusInformationBufferLength);
1636 UNREFERENCED_PARAMETER(BusInformationActualLength);
1638 FUNCTION_ENTER();
1640 FUNCTION_EXIT();
1641 return status;
1644 static BOOLEAN
1645 XenUsbHub_UBIU_IsDeviceHighSpeed(PVOID BusContext)
1647 UNREFERENCED_PARAMETER(BusContext);
1649 FUNCTION_ENTER();
1651 FUNCTION_EXIT();
1652 return TRUE; //TODO: get port value
1655 static NTSTATUS
1656 XenUsbHub_UBIU_EnumLogEntry(
1657 PVOID BusContext,
1658 ULONG DriverTag,
1659 ULONG EnumTag,
1660 ULONG P1,
1661 ULONG P2
1664 NTSTATUS status = STATUS_SUCCESS;
1665 FUNCTION_ENTER();
1667 UNREFERENCED_PARAMETER(BusContext);
1668 UNREFERENCED_PARAMETER(DriverTag);
1669 UNREFERENCED_PARAMETER(EnumTag);
1670 UNREFERENCED_PARAMETER(P1);
1671 UNREFERENCED_PARAMETER(P2);
1673 FUNCTION_MSG("DriverTag = %08x\n", DriverTag);
1674 FUNCTION_MSG("EnumTag = %08x\n", EnumTag);
1675 FUNCTION_MSG("P1 = %08x\n", P1);
1676 FUNCTION_MSG("P2 = %08x\n", P2);
1678 FUNCTION_EXIT();
1679 return status;
1682 static NTSTATUS
1683 XenUsbHub_UBIU_QueryBusTimeEx(
1684 PVOID BusContext,
1685 PULONG HighSpeedFrameCounter)
1687 UNREFERENCED_PARAMETER(BusContext);
1688 UNREFERENCED_PARAMETER(HighSpeedFrameCounter);
1689 FUNCTION_ENTER();
1690 FUNCTION_EXIT();
1691 return STATUS_UNSUCCESSFUL;
1694 static NTSTATUS
1695 XenUsbHub_UBIU_QueryControllerType(
1696 PVOID BusContext,
1697 PULONG HcdiOptionFlags,
1698 PUSHORT PciVendorId,
1699 PUSHORT PciDeviceId,
1700 PUCHAR PciClass,
1701 PUCHAR PciSubClass,
1702 PUCHAR PciRevisionId,
1703 PUCHAR PciProgIf)
1705 UNREFERENCED_PARAMETER(BusContext);
1706 UNREFERENCED_PARAMETER(HcdiOptionFlags);
1707 UNREFERENCED_PARAMETER(PciVendorId);
1708 UNREFERENCED_PARAMETER(PciDeviceId);
1709 UNREFERENCED_PARAMETER(PciClass);
1710 UNREFERENCED_PARAMETER(PciSubClass);
1711 UNREFERENCED_PARAMETER(PciRevisionId);
1712 UNREFERENCED_PARAMETER(PciProgIf);
1713 FUNCTION_ENTER();
1714 FUNCTION_EXIT();
1715 return STATUS_UNSUCCESSFUL;
1718 static NTSTATUS
1719 XenUsbHub_UBIHSS_SuspendHub(
1720 PVOID BusContext)
1722 UNREFERENCED_PARAMETER(BusContext);
1723 FUNCTION_ENTER();
1724 FUNCTION_EXIT();
1725 return STATUS_SUCCESS;
1728 static NTSTATUS
1729 XenUsbHub_UBIHSS_ResumeHub(
1730 PVOID BusContext)
1732 UNREFERENCED_PARAMETER(BusContext);
1733 FUNCTION_ENTER();
1734 FUNCTION_EXIT();
1735 return STATUS_SUCCESS;
1738 VOID
1739 XenUsbHub_ProcessHubInterruptEvent(xenusb_endpoint_t *endpoint)
1741 NTSTATUS status;
1742 WDFDEVICE pdo_device = endpoint->interface->config->device->pdo_device;
1743 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(pdo_device);
1744 PXENUSB_DEVICE_DATA xudd = GetXudd(xupdd->wdf_device_bus_fdo);
1745 WDF_REQUEST_PARAMETERS wrp;
1746 WDFREQUEST request;
1747 PURB urb;
1748 ULONG i;
1749 BOOLEAN port_change_flag = FALSE;
1751 FUNCTION_ENTER();
1752 WdfSpinLockAcquire(endpoint->lock);
1753 status = WdfIoQueueRetrieveNextRequest(endpoint->queue, &request);
1754 if (status == STATUS_NO_MORE_ENTRIES)
1756 WdfSpinLockRelease(endpoint->lock);
1757 FUNCTION_MSG(" No More Entries\n", status);
1758 FUNCTION_EXIT();
1759 return;
1761 if (!NT_SUCCESS(status))
1763 WdfSpinLockRelease(endpoint->lock);
1764 FUNCTION_MSG(" Failed to get request from queue %08x\n", status);
1765 FUNCTION_EXIT();
1766 return;
1769 WDF_REQUEST_PARAMETERS_INIT(&wrp);
1770 WdfRequestGetParameters(request, &wrp);
1772 urb = (PURB)wrp.Parameters.Others.Arg1;
1773 ASSERT(urb);
1774 ASSERT(urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER);
1775 RtlZeroMemory(urb->UrbBulkOrInterruptTransfer.TransferBuffer, urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
1777 for (i = 0; i < xudd->num_ports; i++)
1779 FUNCTION_MSG("port %d - status = %04x, change = %04x\n", xudd->ports[i].port_number, xudd->ports[i].port_status, xudd->ports[i].port_change);
1780 if (xudd->ports[i].port_change) {
1781 FUNCTION_MSG("Port change on port %d - status = %04x, change = %04x\n",
1782 xudd->ports[i].port_number, xudd->ports[i].port_status, xudd->ports[i].port_change);
1783 ((PUCHAR)urb->UrbBulkOrInterruptTransfer.TransferBuffer)[xudd->ports[i].port_number >> 3] |= 1 << (xudd->ports[i].port_number & 7);
1784 port_change_flag = TRUE;
1786 FUNCTION_MSG("port %d - status = %04x, change = %04x\n", xudd->ports[i].port_number, xudd->ports[i].port_status, xudd->ports[i].port_change);
1788 WdfSpinLockRelease(endpoint->lock);
1789 if (port_change_flag)
1791 FUNCTION_MSG("Completing request %p\n", request);
1792 urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
1793 WdfRequestComplete(request, STATUS_SUCCESS);
1795 else
1797 FUNCTION_MSG("Requeuing request %p\n", request);
1798 WdfRequestRequeue(request);
1800 FUNCTION_EXIT();
1801 return;
1804 static NTSTATUS
1805 XenUsbHub_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE(WDFDEVICE device, PIRP irp)
1807 PIO_STACK_LOCATION stack;
1808 union {
1809 USB_BUS_INTERFACE_HUB_V5 ubih5;
1810 #if (NTDDI_VERSION >= NTDDI_VISTA)
1811 USB_BUS_INTERFACE_HUB_V7 ubih6;
1812 USB_BUS_INTERFACE_HUB_V7 ubih7;
1813 #endif
1814 } *ubih;
1815 union {
1816 USB_BUS_INTERFACE_USBDI_V1 ubiu0;
1817 USB_BUS_INTERFACE_USBDI_V1 ubiu1;
1818 USB_BUS_INTERFACE_USBDI_V2 ubiu2;
1819 #if (NTDDI_VERSION >= NTDDI_VISTA)
1820 USB_BUS_INTERFACE_USBDI_V3 ubiu3;
1821 #endif
1822 } *ubiu;
1824 FUNCTION_ENTER();
1826 stack = IoGetCurrentIrpStackLocation(irp);
1828 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID, sizeof(GUID)) == 0)
1830 FUNCTION_MSG("USB_BUS_INTERFACE_HUB_GUID\n");
1831 if ((stack->Parameters.QueryInterface.Version == USB_BUSIF_HUB_VERSION_5 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_HUB_V5))
1832 #if (NTDDI_VERSION >= NTDDI_VISTA)
1833 || (stack->Parameters.QueryInterface.Version == USB_BUSIF_HUB_VERSION_6 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_HUB_V6))
1834 || (stack->Parameters.QueryInterface.Version == USB_BUSIF_HUB_VERSION_7 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_HUB_V7))
1835 #endif
1838 ubih = (PVOID)stack->Parameters.QueryInterface.Interface;
1839 ubih->ubih5.Size = stack->Parameters.QueryInterface.Size;
1840 ubih->ubih5.Version = stack->Parameters.QueryInterface.Version;
1841 ubih->ubih5.BusContext = device;
1842 ubih->ubih5.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
1843 ubih->ubih5.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
1844 /* these two were changed to the Ex functions in v6 so we set them here so they don't get overwritten */
1845 ubih->ubih5.CreateUsbDevice = XenUsbHub_UBIH_CreateUsbDevice;
1846 ubih->ubih5.InitializeUsbDevice = XenUsbHub_UBIH_InitializeUsbDevice;
1847 switch (stack->Parameters.QueryInterface.Version)
1849 #if (NTDDI_VERSION >= NTDDI_VISTA)
1850 case USB_BUSIF_HUB_VERSION_7:
1851 ubih->ubih7.HubTestPoint = XenUsbHub_UBIH_HubTestPoint;
1852 ubih->ubih7.GetDevicePerformanceInfo = XenUsbHub_UBIH_GetDevicePerformanceInfo;
1853 ubih->ubih7.WaitAsyncPowerUp = XenUsbHub_UBIH_WaitAsyncPowerUp;
1854 ubih->ubih7.GetDeviceAddress = XenUsbHub_UBIH_GetDeviceAddress;
1855 ubih->ubih7.RefDeviceHandle = XenUsbHub_UBIH_RefDeviceHandle;
1856 ubih->ubih7.DerefDeviceHandle = XenUsbHub_UBIH_DerefDeviceHandle;
1857 ubih->ubih7.SetDeviceHandleIdleReadyState = XenUsbHub_UBIH_SetDeviceHandleIdleReadyState;
1858 ubih->ubih7.CreateUsbDeviceV7 = XenUsbHub_UBIH_CreateUsbDeviceV7;
1859 ubih->ubih7.GetContainerIdForPort = XenUsbHub_UBIH_GetContainerIdForPort;
1860 ubih->ubih7.SetContainerIdForPort = XenUsbHub_UBIH_SetContainerIdForPort;
1861 ubih->ubih7.AbortAllDevicePipes = XenUsbHub_UBIH_AbortAllDevicePipes;
1862 ubih->ubih7.SetDeviceErrataFlag = XenUsbHub_UBIH_SetDeviceErrataFlag;
1863 /* fall through */
1864 case USB_BUSIF_HUB_VERSION_6:
1865 ubih->ubih6.CreateUsbDevice = XenUsbHub_UBIH_CreateUsbDeviceEx;
1866 ubih->ubih6.InitializeUsbDevice = XenUsbHub_UBIH_InitializeUsbDeviceEx;
1867 ubih->ubih6.HubIsRoot = XenUsbHub_UBIH_HubIsRoot;
1868 ubih->ubih6.AcquireBusSemaphore = XenUsbHub_UBIH_AcquireBusSemaphore;
1869 ubih->ubih6.ReleaseBusSemaphore = XenUsbHub_UBIH_ReleaseBusSemaphore;
1870 ubih->ubih6.CaculatePipeBandwidth = XenUsbHub_UBIH_CaculatePipeBandwidth;
1871 ubih->ubih6.SetBusSystemWakeMode = XenUsbHub_UBIH_SetBusSystemWakeMode;
1872 ubih->ubih6.SetDeviceFlag = XenUsbHub_UBIH_SetDeviceFlag;
1873 /* fall through */
1874 #endif
1875 case USB_BUSIF_HUB_VERSION_5:
1876 ubih->ubih5.GetUsbDescriptors = XenUsbHub_UBIH_GetUsbDescriptors;
1877 ubih->ubih5.RemoveUsbDevice = XenUsbHub_UBIH_RemoveUsbDevice;
1878 ubih->ubih5.RestoreUsbDevice = XenUsbHub_UBIH_RestoreUsbDevice;
1879 ubih->ubih5.GetPortHackFlags = XenUsbHub_UBIH_GetPortHackFlags;
1880 ubih->ubih5.QueryDeviceInformation = XenUsbHub_UBIH_QueryDeviceInformation;
1881 ubih->ubih5.GetControllerInformation = XenUsbHub_UBIH_GetControllerInformation;
1882 ubih->ubih5.ControllerSelectiveSuspend = XenUsbHub_UBIH_ControllerSelectiveSuspend;
1883 ubih->ubih5.GetExtendedHubInformation = XenUsbHub_UBIH_GetExtendedHubInformation;
1884 ubih->ubih5.GetRootHubSymbolicName = XenUsbHub_UBIH_GetRootHubSymbolicName;
1885 ubih->ubih5.GetDeviceBusContext = XenUsbHub_UBIH_GetDeviceBusContext;
1886 ubih->ubih5.Initialize20Hub = XenUsbHub_UBIH_Initialize20Hub;
1887 ubih->ubih5.RootHubInitNotification = XenUsbHub_UBIH_RootHubInitNotification;
1888 ubih->ubih5.FlushTransfers = XenUsbHub_UBIH_FlushTransfers;
1889 ubih->ubih5.SetDeviceHandleData = XenUsbHub_UBIH_SetDeviceHandleData;
1891 irp->IoStatus.Information = 0;
1892 irp->IoStatus.Status = STATUS_SUCCESS;
1894 else
1896 FUNCTION_MSG("size/version mismatch\n");
1899 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID, sizeof(GUID)) == 0)
1901 FUNCTION_MSG("USB_BUS_INTERFACE_USBDI_GUID\n");
1902 if ((stack->Parameters.QueryInterface.Version == USB_BUSIF_USBDI_VERSION_0 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_USBDI_V0))
1903 || (stack->Parameters.QueryInterface.Version == USB_BUSIF_USBDI_VERSION_1 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_USBDI_V1))
1904 || (stack->Parameters.QueryInterface.Version == USB_BUSIF_USBDI_VERSION_2 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_USBDI_V2))
1905 #if (NTDDI_VERSION >= NTDDI_VISTA)
1906 || (stack->Parameters.QueryInterface.Version == USB_BUSIF_USBDI_VERSION_3 && stack->Parameters.QueryInterface.Size == sizeof(USB_BUS_INTERFACE_USBDI_V3))
1907 #endif
1910 ubiu = (PVOID)stack->Parameters.QueryInterface.Interface;
1911 ubiu->ubiu0.Size = stack->Parameters.QueryInterface.Size;
1912 ubiu->ubiu0.Version = stack->Parameters.QueryInterface.Version;
1913 ubiu->ubiu0.BusContext = device;
1914 ubiu->ubiu0.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
1915 ubiu->ubiu0.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
1916 switch (stack->Parameters.QueryInterface.Version)
1918 #if (NTDDI_VERSION >= NTDDI_VISTA)
1919 case USB_BUSIF_USBDI_VERSION_3:
1920 ubiu->ubiu3.QueryBusTimeEx = XenUsbHub_UBIU_QueryBusTimeEx;
1921 ubiu->ubiu3.QueryControllerType = XenUsbHub_UBIU_QueryControllerType;
1922 /* fall through */
1923 #endif
1924 case USB_BUSIF_USBDI_VERSION_2:
1925 ubiu->ubiu2.EnumLogEntry = XenUsbHub_UBIU_EnumLogEntry;
1926 /* fall through */
1927 case USB_BUSIF_USBDI_VERSION_1:
1928 ubiu->ubiu1.IsDeviceHighSpeed = XenUsbHub_UBIU_IsDeviceHighSpeed;
1929 /* fall through */
1930 case USB_BUSIF_USBDI_VERSION_0:
1931 ubiu->ubiu0.GetUSBDIVersion = XenUsbHub_UBIU_GetUSBDIVersion;
1932 ubiu->ubiu0.QueryBusTime = XenUsbHub_UBIU_QueryBusTime;
1933 ubiu->ubiu0.SubmitIsoOutUrb = XenUsbHub_UBIU_SubmitIsoOutUrb;
1934 ubiu->ubiu0.QueryBusInformation = XenUsbHub_UBIU_QueryBusInformation;
1936 irp->IoStatus.Information = 0;
1937 irp->IoStatus.Status = STATUS_SUCCESS;
1939 else
1941 FUNCTION_MSG("size/version mismatch\n");
1944 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_TRANSLATOR_INTERFACE_STANDARD, sizeof(GUID)) == 0)
1945 FUNCTION_MSG("GUID_TRANSLATOR_INTERFACE_STANDARD\n");
1946 #if (NTDDI_VERSION >= NTDDI_VISTA)
1947 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_PNP_LOCATION_INTERFACE, sizeof(GUID)) == 0)
1948 FUNCTION_MSG("GUID_PNP_LOCATION_INTERFACE\n");
1949 #endif
1950 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_MINIDUMP_GUID, sizeof(GUID)) == 0)
1951 FUNCTION_MSG("USB_BUS_INTERFACE_HUB_MINIDUMP_GUID\n");
1952 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_SS_GUID, sizeof(GUID)) == 0)
1953 FUNCTION_MSG("USB_BUS_INTERFACE_HUB_SS_GUID\n");
1954 else
1955 FUNCTION_MSG("GUID = %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
1956 stack->Parameters.QueryInterface.InterfaceType->Data1,
1957 stack->Parameters.QueryInterface.InterfaceType->Data2,
1958 stack->Parameters.QueryInterface.InterfaceType->Data3,
1959 (stack->Parameters.QueryInterface.InterfaceType->Data4[0] << 8) |
1960 stack->Parameters.QueryInterface.InterfaceType->Data4[1],
1961 stack->Parameters.QueryInterface.InterfaceType->Data4[2],
1962 stack->Parameters.QueryInterface.InterfaceType->Data4[3],
1963 stack->Parameters.QueryInterface.InterfaceType->Data4[4],
1964 stack->Parameters.QueryInterface.InterfaceType->Data4[5],
1965 stack->Parameters.QueryInterface.InterfaceType->Data4[6],
1966 stack->Parameters.QueryInterface.InterfaceType->Data4[7]);
1968 FUNCTION_MSG("Size = %d\n", stack->Parameters.QueryInterface.Size);
1969 FUNCTION_MSG("Version = %d\n", stack->Parameters.QueryInterface.Version);
1970 FUNCTION_MSG("Interface = %p\n", stack->Parameters.QueryInterface.Interface);
1972 IoSkipCurrentIrpStackLocation(irp);
1974 FUNCTION_EXIT();
1976 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
1979 NTSTATUS
1980 XenUsbHub_PLI_GetLocationString(PVOID context, PWCHAR *location_strings) {
1981 UNREFERENCED_PARAMETER(context);
1983 FUNCTION_ENTER();
1984 *location_strings = L"james\0";
1985 FUNCTION_EXIT();
1986 return STATUS_SUCCESS;
1989 NTSTATUS
1990 XenUsb_EvtChildListCreateDevice(WDFCHILDLIST child_list,
1991 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
1992 PWDFDEVICE_INIT child_init)
1994 NTSTATUS status = STATUS_SUCCESS;
1995 WDFDEVICE bus_device = WdfChildListGetDevice(child_list);
1996 WDF_OBJECT_ATTRIBUTES child_attributes;
1997 WDFDEVICE child_device;
1998 PXENUSB_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENUSB_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
1999 WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
2000 DECLARE_UNICODE_STRING_SIZE(buffer, 512);
2001 DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
2002 PXENUSB_PDO_DEVICE_DATA xupdd;
2003 PXENUSB_DEVICE_DATA xudd = GetXudd(bus_device);
2004 WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
2005 WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
2006 WDF_IO_QUEUE_CONFIG queue_config;
2007 WDF_IO_TARGET_OPEN_PARAMS target_params;
2008 #if (NTDDI_VERSION >= NTDDI_VISTA)
2009 WDF_QUERY_INTERFACE_CONFIG interface_config;
2010 #if 0
2011 USB_BUS_INTERFACE_HUB_SELECTIVE_SUSPEND ubihss;
2012 #endif
2013 PNP_LOCATION_INTERFACE pli;
2014 #endif
2015 UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
2016 int i;
2018 FUNCTION_ENTER();
2020 //FUNCTION_MSG("device = %d, port = %d, vendor_id = %04x, product_id = %04x\n",
2022 WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
2024 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenUsbHub_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
2025 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
2026 if (!NT_SUCCESS(status))
2028 return status;
2031 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
2032 child_pnp_power_callbacks.EvtDeviceD0Entry = XenUsbHub_EvtDeviceD0Entry;
2033 child_pnp_power_callbacks.EvtDeviceD0Exit = XenUsbHub_EvtDeviceD0Exit;
2034 child_pnp_power_callbacks.EvtDevicePrepareHardware = XenUsbHub_EvtDevicePrepareHardware;
2035 child_pnp_power_callbacks.EvtDeviceReleaseHardware = XenUsbHub_EvtDeviceReleaseHardware;
2036 child_pnp_power_callbacks.EvtDeviceUsageNotification = XenUsbHub_EvtDeviceUsageNotification;
2037 WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);
2039 RtlUnicodeStringPrintf(&buffer, L"USB\\ROOT_HUB");
2040 status = WdfPdoInitAssignDeviceID(child_init, &buffer);
2041 status = WdfPdoInitAddHardwareID(child_init, &buffer);
2043 RtlUnicodeStringPrintf(&buffer, L"VUSB_%d", identification->device_number);
2044 status = WdfPdoInitAssignInstanceID(child_init, &buffer);
2045 if (!NT_SUCCESS(status))
2047 return status;
2050 RtlUnicodeStringPrintf(&buffer, L"PVUSB device #%d", identification->device_number, identification);
2051 status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
2052 if (!NT_SUCCESS(status))
2054 return status;
2056 WdfPdoInitSetDefaultLocale(child_init, 0x0409);
2058 WdfDeviceInitSetPowerNotPageable(child_init);
2060 WdfDeviceInitSetIoType(child_init, WdfDeviceIoDirect);
2062 WdfPdoInitAllowForwardingRequestToParent(child_init);
2064 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENUSB_PDO_DEVICE_DATA);
2065 status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
2066 if (!NT_SUCCESS(status))
2068 return status;
2071 xupdd = GetXupdd(child_device);
2073 xudd->root_hub_device = child_device;
2075 stack_new(&xupdd->dev_id_ss, DEV_ID_COUNT);
2076 /* 0 is invalid and 1 is the root hub */
2077 for (i = 2; i < DEV_ID_COUNT; i++) {
2078 put_id_on_freelist(xupdd->dev_id_ss, (uint16_t)i);
2081 xupdd->wdf_device = child_device;
2082 xupdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
2084 status = WdfIoTargetCreate(bus_device, WDF_NO_OBJECT_ATTRIBUTES, &xupdd->bus_fdo_target);
2085 ASSERT(NT_SUCCESS(status));
2086 WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&target_params, WdfDeviceWdmGetDeviceObject(bus_device));
2087 status = WdfIoTargetOpen(xupdd->bus_fdo_target, &target_params);
2088 ASSERT(NT_SUCCESS(status));
2090 xupdd->usb_device = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_device_t), XENUSB_POOL_TAG);
2091 // get address from freelist...
2092 xupdd->usb_device->pdo_device = child_device;
2093 xupdd->usb_device->address = 1;
2094 xupdd->usb_device->device_speed = UsbHighSpeed;
2095 xupdd->usb_device->device_type = Usb20Device;
2096 xupdd->usb_device->device_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
2097 xupdd->usb_device->device_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
2098 xupdd->usb_device->device_descriptor.bcdUSB = 0x0200;
2099 xupdd->usb_device->device_descriptor.bDeviceClass = 9;
2100 xupdd->usb_device->device_descriptor.bDeviceSubClass = 0;
2101 xupdd->usb_device->device_descriptor.bDeviceProtocol = 1;
2102 xupdd->usb_device->device_descriptor.bMaxPacketSize0 = 64;
2103 xupdd->usb_device->device_descriptor.idVendor = 0x0000;
2104 xupdd->usb_device->device_descriptor.idProduct = 0x0000;
2105 xupdd->usb_device->device_descriptor.bcdDevice = 0x0206;
2106 xupdd->usb_device->device_descriptor.iManufacturer = 3;
2107 xupdd->usb_device->device_descriptor.iProduct = 2;
2108 xupdd->usb_device->device_descriptor.iSerialNumber = 1;
2109 xupdd->usb_device->device_descriptor.bNumConfigurations = 1;
2110 xupdd->usb_device->configs = ExAllocatePoolWithTag(NonPagedPool, sizeof(PVOID) * 1, XENUSB_POOL_TAG);
2111 xupdd->usb_device->configs[0] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_config_t) + sizeof(PVOID) * 1, XENUSB_POOL_TAG);
2112 xupdd->usb_device->active_config = xupdd->usb_device->configs[0];
2113 xupdd->usb_device->configs[0]->device = xupdd->usb_device;
2114 xupdd->usb_device->configs[0]->config_descriptor.bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
2115 xupdd->usb_device->configs[0]->config_descriptor.bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
2116 xupdd->usb_device->configs[0]->config_descriptor.wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
2117 xupdd->usb_device->configs[0]->config_descriptor.bNumInterfaces = 1;
2118 xupdd->usb_device->configs[0]->config_descriptor.bConfigurationValue = 1;
2119 xupdd->usb_device->configs[0]->config_descriptor.iConfiguration = 0;
2120 xupdd->usb_device->configs[0]->config_descriptor.bmAttributes = 0xe0;
2121 xupdd->usb_device->configs[0]->config_descriptor.MaxPower = 0;
2122 xupdd->usb_device->configs[0]->interfaces[0] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_interface_t) + sizeof(PVOID) * 1, XENUSB_POOL_TAG);
2123 xupdd->usb_device->active_interface = xupdd->usb_device->configs[0]->interfaces[0];
2124 xupdd->usb_device->configs[0]->interfaces[0]->config = xupdd->usb_device->configs[0];
2125 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bLength = 9;
2126 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE;
2127 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bInterfaceNumber = 0;
2128 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bAlternateSetting = 0;
2129 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bNumEndpoints = 1;
2130 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bInterfaceClass = 9;
2131 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bInterfaceSubClass = 0;
2132 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.bInterfaceProtocol = 0;
2133 xupdd->usb_device->configs[0]->interfaces[0]->interface_descriptor.iInterface = 0;
2134 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0] = ExAllocatePoolWithTag(NonPagedPool, sizeof(xenusb_endpoint_t), XENUSB_POOL_TAG);
2135 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->interface = xupdd->usb_device->configs[0]->interfaces[0];
2136 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->pipe_value = 0;
2137 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.bLength = 7;
2138 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
2139 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.bEndpointAddress = 0x81; // EP 1 IN
2140 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT;
2141 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.wMaxPacketSize = 2;
2142 xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->endpoint_descriptor.bInterval = 12;
2143 WdfSpinLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->lock);
2145 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
2146 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_ROOTHUB_SUBMIT_URB;
2147 queue_config.PowerManaged = TRUE; /* power managed queue for SUBMIT_URB */
2148 status = WdfIoQueueCreate(child_device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xupdd->usb_device->urb_queue);
2149 if (!NT_SUCCESS(status)) {
2150 FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
2151 return status;
2154 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchManual);
2155 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queue_attributes, pxenusb_endpoint_t);
2156 queue_config.PowerManaged = TRUE;
2157 //queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_Interrupt_SUBMIT_URB;
2158 status = WdfIoQueueCreate(child_device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES,
2159 &xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->queue);
2160 if (!NT_SUCCESS(status)) {
2161 FUNCTION_MSG("Error creating timer io_queue 0x%x\n", status);
2162 return status;
2164 //*GetEndpoint(xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]->queue) = xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0];
2166 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
2167 queue_config.EvtIoInternalDeviceControl = XenUsbHub_EvtIoInternalDeviceControl;
2168 queue_config.EvtIoDeviceControl = XenUsbHub_EvtIoDeviceControl;
2169 queue_config.EvtIoDefault = XenUsbHub_EvtIoDefault;
2170 /* can't be power managed or deadlocks occur */
2171 queue_config.PowerManaged = FALSE;
2172 status = WdfIoQueueCreate(child_device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xupdd->io_queue);
2173 if (!NT_SUCCESS(status)) {
2174 FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
2175 return status;
2178 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
2179 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
2180 WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);
2182 WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
2183 child_pnp_capabilities.LockSupported = WdfFalse;
2184 child_pnp_capabilities.EjectSupported = WdfTrue;
2185 child_pnp_capabilities.Removable = WdfTrue;
2186 child_pnp_capabilities.DockDevice = WdfFalse;
2187 child_pnp_capabilities.UniqueID = WdfTrue;
2188 child_pnp_capabilities.SilentInstall = WdfTrue;
2189 child_pnp_capabilities.SurpriseRemovalOK = WdfTrue;
2190 child_pnp_capabilities.HardwareDisabled = WdfFalse;
2191 WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);
2193 WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
2194 child_power_capabilities.DeviceD1 = WdfTrue;
2195 child_power_capabilities.WakeFromD1 = WdfTrue;
2196 child_power_capabilities.DeviceWake = PowerDeviceD1;
2197 child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
2198 child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
2199 child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
2200 child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
2201 child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
2202 child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
2203 WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);
2205 #if (NTDDI_VERSION >= NTDDI_VISTA)
2206 #if 0
2207 ubihss.BusContext = child_device;
2208 ubihss.Size = sizeof(USB_BUS_INTERFACE_HUB_SELECTIVE_SUSPEND);
2209 ubihss.Version = USB_BUSIF_HUB_SS_VERSION_0;
2210 ubihss.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2211 ubihss.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2212 ubihss.SuspendHub = XenUsbHub_UBIHSS_SuspendHub;
2213 ubihss.ResumeHub = XenUsbHub_UBIHSS_ResumeHub;
2214 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&ubihss, &USB_BUS_INTERFACE_HUB_SS_GUID, NULL);
2215 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2216 if (!NT_SUCCESS(status))
2217 return status;
2218 #endif
2219 pli.Size = sizeof(USB_BUS_INTERFACE_HUB_SELECTIVE_SUSPEND);
2220 pli.Version = 1;
2221 pli.Context = child_device;
2222 pli.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
2223 pli.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
2224 pli.GetLocationString = XenUsbHub_PLI_GetLocationString;
2225 WDF_QUERY_INTERFACE_CONFIG_INIT(&interface_config, (PINTERFACE)&pli, &GUID_PNP_LOCATION_INTERFACE, NULL);
2226 status = WdfDeviceAddQueryInterface(child_device, &interface_config);
2227 if (!NT_SUCCESS(status))
2228 return status;
2229 #endif
2231 status = WdfDeviceCreateDeviceInterface(child_device, &GUID_DEVINTERFACE_USB_HUB, NULL);
2232 if (!NT_SUCCESS(status))
2233 return status;
2235 FUNCTION_EXIT();
2237 return status;