[CMAKE]
[reactos.git] / reactos / drivers / usb / usbhub / fdo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: USB hub driver
4 * FILE: drivers/usb/cromwell/hub/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
6 *
7 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.com)
8 * Michael Martin (michael.martin@reactos.org)
9 */
10
11 #define INITGUID
12 #include <stdio.h>
13 #define NDEBUG
14 #include "usbhub.h"
15 #include "usbdlib.h"
16
17 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
18
19 typedef struct _PORTSTATUSANDCHANGE
20 {
21 USHORT Status;
22 USHORT Change;
23 } PORTSTATUSANDCHANGE, *PPORTSTATUSANDCHANGE;
24
25 NTSTATUS
26 QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2);
27 NTSTATUS
28 WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject);
29 NTSTATUS
30 SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb);
31
32 VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
33 {
34 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
35 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
36 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
37 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
38 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
39 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
40 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
41 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
42 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
43 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
44 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
45 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
46 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
47 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
48 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
49 }
50
51 VOID DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
52 {
53 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
54 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
55 LONG i, j;
56
57 DPRINT1("Duming ConfigurationDescriptor %x\n", ConfigurationDescriptor);
58 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
59 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
60 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
61 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
62 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
63 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
64 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
65 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
66
67 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
68
69 for (i=0; i < ConfigurationDescriptor->bNumInterfaces; i++)
70 {
71 DPRINT1("- Dumping InterfaceDescriptor %x\n", InterfaceDescriptor);
72 DPRINT1(" bLength %x\n", InterfaceDescriptor->bLength);
73 DPRINT1(" bDescriptorType %x\n", InterfaceDescriptor->bDescriptorType);
74 DPRINT1(" bInterfaceNumber %x\n", InterfaceDescriptor->bInterfaceNumber);
75 DPRINT1(" bAlternateSetting %x\n", InterfaceDescriptor->bAlternateSetting);
76 DPRINT1(" bNumEndpoints %x\n", InterfaceDescriptor->bNumEndpoints);
77 DPRINT1(" bInterfaceClass %x\n", InterfaceDescriptor->bInterfaceClass);
78 DPRINT1(" bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceSubClass);
79 DPRINT1(" bInterfaceProtocol %x\n", InterfaceDescriptor->bInterfaceProtocol);
80 DPRINT1(" iInterface %x\n", InterfaceDescriptor->iInterface);
81
82 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR));
83
84 for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++)
85 {
86 DPRINT1(" bLength %x\n", EndpointDescriptor->bLength);
87 DPRINT1(" bDescriptorType %x\n", EndpointDescriptor->bDescriptorType);
88 DPRINT1(" bEndpointAddress %x\n", EndpointDescriptor->bEndpointAddress);
89 DPRINT1(" bmAttributes %x\n", EndpointDescriptor->bmAttributes);
90 DPRINT1(" wMaxPacketSize %x\n", EndpointDescriptor->wMaxPacketSize);
91 DPRINT1(" bInterval %x\n", EndpointDescriptor->bInterval);
92 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDescriptor + sizeof(USB_ENDPOINT_DESCRIPTOR));
93 }
94 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor;
95 }
96
97 }
98
99 VOID DumpInterfaceInfo(PUSBD_INTERFACE_INFORMATION InterfaceInformation)
100 {
101 PUSBD_PIPE_INFORMATION PipeInformation;
102 ULONG i;
103
104 DPRINT1("IntefaceLenth %x\n",InterfaceInformation->Length);
105 DPRINT1("InterfaceNumber %x\n",InterfaceInformation->InterfaceNumber);
106 DPRINT1("AlternateSetting %x\n",InterfaceInformation->AlternateSetting);
107 DPRINT1("Class %x\n",InterfaceInformation->Class);
108 DPRINT1("SubClass %x\n",InterfaceInformation->SubClass);
109 DPRINT1("Protocol %x\n",InterfaceInformation->Protocol);
110 DPRINT1("Reserved %x\n",InterfaceInformation->Reserved);
111 DPRINT1("InterfaceHandle %x\n",InterfaceInformation->InterfaceHandle);
112 DPRINT1("NumberOfPipes %x\n", InterfaceInformation->NumberOfPipes);
113
114 PipeInformation = &InterfaceInformation->Pipes[0];
115
116 for (i = 0; i < InterfaceInformation->NumberOfPipes; i++)
117 {
118
119 DPRINT1("MaximumPacketSize %x\n", PipeInformation->MaximumPacketSize);
120 DPRINT1("EndpointAddress %x\n", PipeInformation->EndpointAddress);
121 DPRINT1("Interval %x\n", PipeInformation->Interval);
122 DPRINT1("PipeType %x\n", PipeInformation->PipeType);
123 DPRINT1("PipeHandle %x\n", PipeInformation->PipeHandle);
124 DPRINT1("PipeFlags %x\n", PipeInformation->PipeFlags);
125 DPRINT1("MaximumTransferSize %x\n", PipeInformation->MaximumTransferSize);
126 PipeInformation = (PUSBD_PIPE_INFORMATION)((ULONG_PTR)PipeInformation + sizeof(USBD_PIPE_INFORMATION));
127 }
128 }
129
130
131 VOID NTAPI
132 WorkerThread(IN PVOID Context)
133 {
134 PHUB_DEVICE_EXTENSION DeviceExtension;
135 PDEVICE_OBJECT DeviceObject, Pdo;
136 PHUB_CHILDDEVICE_EXTENSION PdoExtension;
137 PURB Urb = NULL;
138 PORTSTATUSANDCHANGE PortStatusAndChange;
139 int PortLoop, DeviceCount;
140 NTSTATUS Status;
141 USB_DEVICE_DESCRIPTOR DevDesc;
142 USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
143 ULONG DevDescSize, ConfigDescSize;
144 PUSB_STRING_DESCRIPTOR StringDesc;
145 USB_STRING_DESCRIPTOR LanguageIdDescriptor;
146 PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context;
147
148 DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
149
150 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
151
152 /* Determine where in the children array to store this device info */
153 for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++)
154 {
155 if (DeviceExtension->UsbChildren[DeviceCount] == NULL)
156 {
157 break;
158 }
159 }
160
161 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
162 if (!Urb)
163 {
164 DPRINT1("Failed to allocate memory for URB!\n");
165 ASSERT(FALSE);
166 }
167
168 RtlZeroMemory(Urb, sizeof(URB));
169
170 for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++)
171 {
172 /* Get the port status */
173 UsbBuildVendorRequest(Urb,
174 URB_FUNCTION_CLASS_OTHER,
175 sizeof(Urb->UrbControlVendorClassRequest),
176 USBD_TRANSFER_DIRECTION_OUT,
177 0,
178 USB_REQUEST_GET_STATUS,
179 0,
180 PortLoop + 1,
181 &PortStatusAndChange,
182 0,
183 sizeof(PORTSTATUSANDCHANGE),
184 0);
185
186 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
187 if (!NT_SUCCESS(Status))
188 {
189 DPRINT1("Failed to get PortStatus!\n");
190 goto CleanUp;
191 }
192
193 DPRINT("Notification Port %x:\n", PortLoop + 1);
194 DPRINT("Status %x\n", PortStatusAndChange.Status);
195 DPRINT("Change %x\n", PortStatusAndChange.Change);
196
197 if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET)
198 {
199 /* Clear the Reset */
200 UsbBuildVendorRequest(Urb,
201 URB_FUNCTION_CLASS_OTHER,
202 sizeof(Urb->UrbControlVendorClassRequest),
203 USBD_TRANSFER_DIRECTION_IN,
204 0,
205 USB_REQUEST_CLEAR_FEATURE,
206 C_PORT_RESET,
207 PortLoop + 1,
208 &PortStatusAndChange,
209 0,
210 sizeof(PORTSTATUSANDCHANGE),
211 0);
212
213 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
214 if (!NT_SUCCESS(Status))
215 {
216 DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status);
217 goto CleanUp;
218 }
219
220 UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER,
221 sizeof(Urb->UrbControlVendorClassRequest),
222 USBD_TRANSFER_DIRECTION_OUT,
223 0,
224 USB_REQUEST_GET_STATUS,
225 0,
226 PortLoop + 1,
227 &PortStatusAndChange,
228 0,
229 sizeof(PORTSTATUSANDCHANGE),
230 0);
231
232 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
233
234 DPRINT("Status %x\n", PortStatusAndChange.Status);
235 DPRINT("Change %x\n", PortStatusAndChange.Change);
236
237 /* Create the UsbDevice */
238 Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo,
239 (PVOID)&DeviceExtension->UsbChildren[DeviceCount],
240 DeviceExtension->RootHubUsbDevice,
241 PortStatusAndChange.Status,
242 PortLoop + 1);
243 DPRINT1("CreateUsbDevice Status %x\n", Status);
244
245 Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]);
246 DPRINT1("InitializeUsbDevice Status %x\n", Status);
247
248 DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
249 ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
250 Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo,
251 DeviceExtension->UsbChildren[DeviceCount],
252 (PUCHAR)&DevDesc,
253 &DevDescSize,
254 (PUCHAR)&ConfigDesc,
255 &ConfigDescSize);
256 if (!NT_SUCCESS(Status))
257 {
258 DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status);
259 }
260
261 DumpDeviceDescriptor(&DevDesc);
262
263 Status = IoCreateDevice(DeviceObject->DriverObject,
264 sizeof(HUB_CHILDDEVICE_EXTENSION),
265 NULL,
266 FILE_DEVICE_CONTROLLER,
267 FILE_AUTOGENERATED_DEVICE_NAME,
268 FALSE,
269 &DeviceExtension->Children[DeviceCount]);
270
271 if (!NT_SUCCESS(Status))
272 {
273 DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status);
274 goto CleanUp;
275 }
276
277 Pdo = DeviceExtension->Children[DeviceCount];
278 DPRINT1("Created New Device with %x\n", Pdo);
279 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
280
281 PdoExtension = Pdo->DeviceExtension;
282
283 RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
284
285 PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG);
286 RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR));
287 swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct);
288
289
290 /* Get the LANGids */
291 RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR));
292 UsbBuildGetDescriptorRequest(Urb,
293 sizeof(Urb->UrbControlDescriptorRequest),
294 USB_STRING_DESCRIPTOR_TYPE,
295 0,
296 0,
297 &LanguageIdDescriptor,
298 NULL,
299 sizeof(USB_STRING_DESCRIPTOR),
300 NULL);
301
302 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
303 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
304
305 /* Get the length of the SerialNumber */
306 StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG);
307 RtlZeroMemory(StringDesc, 64);
308 StringDesc->bLength = 0;
309 StringDesc->bDescriptorType = 0;
310
311 UsbBuildGetDescriptorRequest(Urb,
312 sizeof(Urb->UrbControlDescriptorRequest),
313 USB_STRING_DESCRIPTOR_TYPE,
314 DevDesc.iSerialNumber,
315 LanguageIdDescriptor.bString[0],
316 StringDesc,
317 NULL,
318 64,
319 NULL);
320
321 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
322
323 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
324
325 PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG);
326 DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId);
327
328 RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR));
329 RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength);
330 DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId);
331
332
333
334 RtlZeroMemory(StringDesc, 64);
335 StringDesc->bLength = 0;
336 StringDesc->bDescriptorType = 0;
337
338 UsbBuildGetDescriptorRequest(Urb,
339 sizeof(Urb->UrbControlDescriptorRequest),
340 USB_STRING_DESCRIPTOR_TYPE,
341 DevDesc.iProduct,
342 LanguageIdDescriptor.bString[0],
343 StringDesc,
344 NULL,
345 64,
346 NULL);
347
348 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
349
350 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
351
352 PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG);
353
354 RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR));
355 RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength);
356 ExFreePool(StringDesc);
357 DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription);
358
359 PdoExtension->IsFDO = FALSE;
360 PdoExtension->Parent = DeviceObject;
361 Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
362
363 ExFreePool(WorkItemData);
364 ExFreePool(Urb);
365
366 IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations);
367 return;
368 }
369
370 /* Is a device connected to this port */
371 if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT)
372 {
373 /* Clear the Connect from ProtChange */
374 UsbBuildVendorRequest(Urb,
375 URB_FUNCTION_CLASS_OTHER,
376 sizeof(Urb->UrbControlVendorClassRequest),
377 USBD_TRANSFER_DIRECTION_IN,
378 0,
379 USB_REQUEST_CLEAR_FEATURE,
380 C_PORT_CONNECTION,
381 PortLoop + 1,
382 &PortStatusAndChange,
383 0,
384 sizeof(PORTSTATUSANDCHANGE),
385 0);
386
387 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
388 if (!NT_SUCCESS(Status))
389 {
390 DPRINT1("Failed to Clear the Port Connect!\n");
391 goto CleanUp;
392 }
393
394 /* Send the miniport controller a SCE request so when the port resets we can be informed */
395 WaitForUsbDeviceArrivalNotification(DeviceObject);
396
397 UsbBuildVendorRequest(Urb,
398 URB_FUNCTION_CLASS_OTHER,
399 sizeof(Urb->UrbControlVendorClassRequest),
400 USBD_TRANSFER_DIRECTION_IN,
401 0,
402 USB_REQUEST_SET_FEATURE,
403 PORT_RESET,
404 PortLoop + 1,
405 &PortStatusAndChange,
406 0,
407 sizeof(PORTSTATUSANDCHANGE),
408 0);
409
410 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
411
412 if (!NT_SUCCESS(Status))
413 {
414 DPRINT1("Failed to Reset the port!\n");
415 goto CleanUp;
416 }
417 /* At this point the miniport will complete another SCE to inform of Reset completed */
418 }
419 }
420
421 CleanUp:
422 ExFreePool(WorkItemData);
423 ExFreePool(Urb);
424 }
425
426 NTSTATUS
427 DeviceArrivalCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
428 {
429 PHUB_DEVICE_EXTENSION DeviceExtension;
430 LONG i;
431 PWORKITEMDATA WorkItemData;
432
433 DeviceExtension = (PHUB_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
434
435 for (i=0; i < DeviceExtension->UsbExtHubInfo.NumberOfPorts; i++)
436 DPRINT1("Port %x DeviceExtension->PortStatus %x\n",i+1, DeviceExtension->PortStatus[i]);
437
438 IoFreeIrp(Irp);
439
440 WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEMDATA));
441 if (!WorkItemData)
442 {
443 DPRINT1("Failed to allocate memory\n");
444 return STATUS_NO_MEMORY;
445 }
446
447
448 RtlZeroMemory(WorkItemData, sizeof(WORKITEMDATA));
449 WorkItemData->Context = Context;
450
451 ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)WorkerThread, (PVOID)WorkItemData);
452 ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
453 return STATUS_MORE_PROCESSING_REQUIRED;
454 }
455
456
457 NTSTATUS
458 WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject)
459 {
460 PURB Urb;
461 PIRP Irp;
462 NTSTATUS Status;
463 PIO_STACK_LOCATION Stack = NULL;
464 PHUB_DEVICE_EXTENSION DeviceExtension;
465
466 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
467
468 Urb = &DeviceExtension->Urb;
469
470 RtlZeroMemory(Urb, sizeof(URB));
471
472 /* Send URB to the miniports Status Change Endpoint SCE */
473 UsbBuildInterruptOrBulkTransferRequest(Urb,
474 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
475 DeviceExtension->PipeHandle,
476 &DeviceExtension->PortStatus,
477 NULL,
478 sizeof(ULONG) * 2,
479 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
480 NULL);
481
482 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
483
484 Irp = IoAllocateIrp(DeviceExtension->RootHubPdo->StackSize, FALSE);
485
486 if (Irp == NULL)
487 {
488 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
489 return STATUS_INSUFFICIENT_RESOURCES;
490 }
491
492
493 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
494 Irp->IoStatus.Information = 0;
495 Irp->Flags = 0;
496 Irp->UserBuffer = NULL;
497
498 Stack = IoGetCurrentIrpStackLocation(Irp);
499 Stack->DeviceObject = DeviceExtension->RootHubPdo;
500
501 Stack = IoGetNextIrpStackLocation(Irp);
502 Stack->DeviceObject = DeviceExtension->RootHubPdo;
503 Stack->Parameters.Others.Argument1 = Urb;
504 Stack->Parameters.Others.Argument2 = NULL;
505 Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
506 Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
507
508 //IoSetCompletionRoutineEx(DeviceExtension->RootHubPdo, Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE);
509 IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE);
510
511 Status = IoCallDriver(DeviceExtension->RootHubPdo, Irp);
512 DPRINT1("SCE request status %x\n", Status);
513
514 return STATUS_PENDING;
515 }
516
517 NTSTATUS
518 SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb)
519 {
520 PIRP Irp;
521 IO_STATUS_BLOCK IoStatus;
522 NTSTATUS Status;
523 PIO_STACK_LOCATION Stack = NULL;
524
525 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
526 Pdo,
527 NULL, 0,
528 NULL, 0,
529 TRUE,
530 NULL,
531 &IoStatus);
532
533 if (Irp == NULL)
534 {
535 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
536 return STATUS_INSUFFICIENT_RESOURCES;
537 }
538
539 /* Initialize the status block before sending the IRP */
540 IoStatus.Status = STATUS_NOT_SUPPORTED;
541 IoStatus.Information = 0;
542
543 Stack = IoGetNextIrpStackLocation(Irp);
544
545 Stack->Parameters.Others.Argument1 = Urb;
546 Stack->Parameters.Others.Argument2 = NULL;
547
548 Status = IoCallDriver(Pdo, Irp);
549
550 return Status;
551 }
552
553 NTSTATUS
554 QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2)
555 {
556 KEVENT Event;
557 PIRP Irp;
558 IO_STATUS_BLOCK IoStatus;
559 NTSTATUS Status;
560 PIO_STACK_LOCATION Stack = NULL;
561
562 KeInitializeEvent(&Event, NotificationEvent, FALSE);
563
564 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
565 Pdo,
566 NULL, 0,
567 NULL, 0,
568 TRUE,
569 &Event,
570 &IoStatus);
571
572 if (Irp == NULL)
573 {
574 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
575 return STATUS_INSUFFICIENT_RESOURCES;
576 }
577
578 /* Initialize the status block before sending the IRP */
579 IoStatus.Status = STATUS_NOT_SUPPORTED;
580 IoStatus.Information = 0;
581
582 Stack = IoGetNextIrpStackLocation(Irp);
583
584 Stack->Parameters.Others.Argument1 = OutParameter1;
585 Stack->Parameters.Others.Argument2 = OutParameter2;
586
587 Status = IoCallDriver(Pdo, Irp);
588
589 if (Status == STATUS_PENDING)
590 {
591 DPRINT1("Usbhub: Operation pending\n");
592 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
593 Status = IoStatus.Status;
594 }
595
596 return Status;
597 }
598
599 NTSTATUS QueryInterface(IN PDEVICE_OBJECT Pdo, IN CONST GUID InterfaceType, IN LONG Size, IN LONG Version, OUT PVOID Interface)
600 {
601 KEVENT Event;
602 PIRP Irp;
603 IO_STATUS_BLOCK IoStatus;
604 NTSTATUS Status;
605 PIO_STACK_LOCATION Stack = NULL;
606
607 KeInitializeEvent(&Event, NotificationEvent, FALSE);
608
609 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
610 Pdo,
611 NULL,
612 0,
613 NULL,
614 &Event,
615 &IoStatus);
616
617 Stack = IoGetNextIrpStackLocation(Irp);
618 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
619 Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
620 Stack->Parameters.QueryInterface.Size = Size;
621 Stack->Parameters.QueryInterface.Version = Version;
622 Stack->Parameters.QueryInterface.Interface = Interface;
623 Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
624
625 Status = IoCallDriver(Pdo, Irp);
626
627 if (Status == STATUS_PENDING)
628 {
629 DPRINT("Usbhub: Operation pending\n");
630 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
631 Status = IoStatus.Status;
632 }
633
634 return Status;
635 }
636
637 static VOID
638 UsbhubGetUserBuffers(IN PIRP Irp, IN ULONG IoControlCode, OUT PVOID* BufferIn, OUT PVOID* BufferOut)
639 {
640 ASSERT(Irp);
641 ASSERT(BufferIn);
642 ASSERT(BufferOut);
643
644 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
645 {
646 case METHOD_BUFFERED:
647 *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer;
648 break;
649 case METHOD_IN_DIRECT:
650 case METHOD_OUT_DIRECT:
651 *BufferIn = Irp->AssociatedIrp.SystemBuffer;
652 *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress);
653 break;
654 case METHOD_NEITHER:
655 *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
656 *BufferOut = Irp->UserBuffer;
657 break;
658 default:
659 /* Should never happen */
660 *BufferIn = NULL;
661 *BufferOut = NULL;
662 break;
663 }
664 }
665
666 NTSTATUS
667 UsbhubFdoQueryBusRelations(IN PDEVICE_OBJECT DeviceObject, OUT PDEVICE_RELATIONS* pDeviceRelations)
668 {
669 PHUB_DEVICE_EXTENSION DeviceExtension;
670 PDEVICE_RELATIONS DeviceRelations;
671 ULONG i;
672 ULONG Children = 0;
673 ULONG NeededSize;
674
675 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
676 DPRINT1("USBHUB: Query Bus Relations\n");
677
678 /* Create PDOs that are missing */
679 for (i = 0; i < USB_MAXCHILDREN; i++)
680 {
681
682 if (DeviceExtension->UsbChildren[i] == NULL)
683 {
684 continue;
685 }
686 Children++;
687 }
688
689 /* Fill returned structure */
690 NeededSize = sizeof(DEVICE_RELATIONS);
691 if (Children > 1)
692 NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
693
694 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
695 NeededSize);
696
697 if (!DeviceRelations)
698 return STATUS_INSUFFICIENT_RESOURCES;
699 DeviceRelations->Count = Children;
700 Children = 0;
701
702 for (i = 0; i < USB_MAXCHILDREN; i++)
703 {
704 if (DeviceExtension->Children[i])
705 {
706 ObReferenceObject(DeviceExtension->Children[i]);
707 DeviceRelations->Objects[Children++] = DeviceExtension->Children[i];
708 }
709 }
710
711 ASSERT(Children == DeviceRelations->Count);
712 *pDeviceRelations = DeviceRelations;
713
714 WaitForUsbDeviceArrivalNotification(DeviceObject);
715
716 return STATUS_SUCCESS;
717 }
718
719 VOID CallBackRoutine(IN PVOID Argument1)
720 {
721 DPRINT1("RH_INIT_CALLBACK %x\n", Argument1);
722 ASSERT(FALSE);
723 }
724
725 NTSTATUS NTAPI
726 UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
727 {
728 PIO_STACK_LOCATION IrpSp;
729 NTSTATUS Status = STATUS_SUCCESS;
730 ULONG MinorFunction;
731 ULONG_PTR Information = 0;
732 PHUB_DEVICE_EXTENSION DeviceExtension;
733
734 IrpSp = IoGetCurrentIrpStackLocation(Irp);
735 MinorFunction = IrpSp->MinorFunction;
736
737 DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
738
739 switch (MinorFunction)
740 {
741 case IRP_MN_START_DEVICE: /* 0x0 */
742 {
743 PURB Urb;
744 ULONG Result = 0;
745 PUSB_INTERFACE_DESCRIPTOR Pid;
746 /* Theres only one descriptor on hub */
747 USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
748 PURB ConfigUrb = NULL;
749
750 /* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */
751 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
752
753 /* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */
754 Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
755 RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
756
757 /* Get the hubs PDO */
758 QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo);
759 ASSERT(DeviceExtension->RootHubPdo);
760 ASSERT(DeviceExtension->RootHubFdo);
761 DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo);
762
763 /* Send the START_DEVICE irp down to the PDO of RootHub */
764 Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp);
765
766 if (!NT_SUCCESS(Status))
767 {
768 DPRINT1("Failed to start the RootHub PDO\n");
769 ASSERT(FALSE);
770 }
771
772 /* Get the current number of hubs */
773 QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL);
774
775 /* Get the Direct Call Interfaces */
776 Status = QueryInterface(DeviceExtension->RootHubPdo,
777 USB_BUS_INTERFACE_HUB_GUID,
778 sizeof(USB_BUS_INTERFACE_HUB_V5),
779 5,
780 (PVOID)&DeviceExtension->HubInterface);
781 if (!NT_SUCCESS(Status))
782 {
783 DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
784 return STATUS_UNSUCCESSFUL;
785 }
786
787 Status = QueryInterface(DeviceExtension->RootHubPdo,
788 USB_BUS_INTERFACE_USBDI_GUID,
789 sizeof(USB_BUS_INTERFACE_USBDI_V2),
790 2,
791 (PVOID)&DeviceExtension->UsbDInterface);
792 if (!NT_SUCCESS(Status))
793 {
794 DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
795 return STATUS_UNSUCCESSFUL;
796 }
797
798 /* Get roothub device handle */
799 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL);
800 if (!NT_SUCCESS(Status))
801 {
802 DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status);
803 return Status;
804 }
805
806 Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo,
807 DeviceExtension->RootHubUsbDevice,
808 &DeviceExtension->DeviceInformation,
809 sizeof(USB_DEVICE_INFORMATION_0),
810 &Result);
811
812
813 DPRINT("Status %x, Result %x\n", Status, Result);
814 DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel);
815 DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength);
816 DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber);
817 DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor);
818 DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress);
819 DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes);
820
821 /* Get roothubs device descriptor */
822 UsbBuildGetDescriptorRequest(Urb,
823 sizeof(Urb->UrbControlDescriptorRequest),
824 USB_DEVICE_DESCRIPTOR_TYPE,
825 0,
826 0,
827 &DeviceExtension->HubDeviceDescriptor,
828 NULL,
829 sizeof(USB_DEVICE_DESCRIPTOR),
830 NULL);
831
832 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
833
834 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
835 if (!NT_SUCCESS(Status))
836 {
837 DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n");
838 }
839
840 DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor);
841
842 /* Get roothubs configuration descriptor */
843 UsbBuildGetDescriptorRequest(Urb,
844 sizeof(Urb->UrbControlDescriptorRequest),
845 USB_CONFIGURATION_DESCRIPTOR_TYPE,
846 0,
847 0,
848 &DeviceExtension->HubConfigDescriptor,
849 NULL,
850 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
851 NULL);
852 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
853
854 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
855
856 if (!NT_SUCCESS(Status))
857 {
858 DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status);
859 ASSERT(FALSE);
860 }
861 ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength);
862
863 DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor);
864 //DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength);
865
866 Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo,
867 DeviceExtension->RootHubPdo,
868 &DeviceExtension->UsbExtHubInfo,
869 sizeof(USB_EXTHUB_INFORMATION_0),
870 &Result);
871 if (!NT_SUCCESS(Status))
872 {
873 DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n");
874 ASSERT(FALSE);
875 }
876
877 DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts);
878
879 UsbBuildVendorRequest(Urb,
880 URB_FUNCTION_CLASS_DEVICE,
881 sizeof(Urb->UrbControlVendorClassRequest),
882 USBD_TRANSFER_DIRECTION_IN,
883 0,
884 USB_DEVICE_CLASS_RESERVED,
885 0,
886 0,
887 &DeviceExtension->HubDescriptor,
888 NULL,
889 sizeof(USB_HUB_DESCRIPTOR),
890 NULL);
891
892 Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
893
894 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
895
896 DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType);
897
898 /* Select the configuration */
899
900 /* Get the first one */
901 Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor,
902 &DeviceExtension->HubConfigDescriptor,
903 -1, -1, -1, -1, -1);
904 ASSERT(Pid != NULL);
905 InterfaceList[0].InterfaceDescriptor = Pid;
906 ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
907 ASSERT(ConfigUrb != NULL);
908 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL);
909
910 DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
911 DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
912 DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle);
913
914 ExFreePool(ConfigUrb);
915
916 Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1);
917 DPRINT1("Status %x\n", Status);
918
919 {
920 int PortLoop;
921 USHORT PortStatusAndChange[2];
922
923 for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++)
924 {
925 DPRINT1("Port %x\n", PortLoop);
926 UsbBuildVendorRequest(Urb,
927 URB_FUNCTION_CLASS_OTHER,
928 sizeof(Urb->UrbControlVendorClassRequest),
929 USBD_TRANSFER_DIRECTION_IN,
930 0,
931 USB_REQUEST_SET_FEATURE,
932 PORT_POWER,
933 1,
934 0,
935 0,
936 0,
937 0);
938
939 Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1;
940 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
941
942 DPRINT1("Status %x\n", Status);
943
944 UsbBuildVendorRequest(Urb,
945 URB_FUNCTION_CLASS_OTHER,
946 sizeof(Urb->UrbControlVendorClassRequest),
947 USBD_TRANSFER_DIRECTION_OUT,
948 0,
949 USB_REQUEST_GET_STATUS,
950 0,
951 PortLoop + 1,
952 &PortStatusAndChange,
953 0,
954 sizeof(PortStatusAndChange),
955 0);
956 Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
957
958 DPRINT1("Status %x\n", Status);
959 DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]);
960 DPRINT1("PortChange = %x\n", PortStatusAndChange[1]);
961 }
962 }
963
964 ExFreePool(Urb);
965 break;
966 }
967
968 case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
969 {
970 switch (IrpSp->Parameters.QueryDeviceRelations.Type)
971 {
972 case BusRelations:
973 {
974 PDEVICE_RELATIONS DeviceRelations = NULL;
975 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
976
977 Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations);
978
979 Information = (ULONG_PTR)DeviceRelations;
980 break;
981 }
982 case RemovalRelations:
983 {
984 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
985 return ForwardIrpAndForget(DeviceObject, Irp);
986 }
987 default:
988 DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
989 IrpSp->Parameters.QueryDeviceRelations.Type);
990 return ForwardIrpAndForget(DeviceObject, Irp);
991 }
992 break;
993 }
994 case IRP_MN_QUERY_BUS_INFORMATION:
995 {
996 DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
997 break;
998 }
999 case IRP_MN_QUERY_ID:
1000 {
1001 DPRINT1("IRP_MN_QUERY_ID\n");
1002 break;
1003 }
1004 case IRP_MN_QUERY_CAPABILITIES:
1005 {
1006 DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
1007 break;
1008 }
1009 default:
1010 {
1011 DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
1012 return ForwardIrpAndForget(DeviceObject, Irp);
1013 }
1014 }
1015 Irp->IoStatus.Information = Information;
1016 Irp->IoStatus.Status = Status;
1017 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1018 return Status;
1019 }
1020
1021 NTSTATUS
1022 UsbhubDeviceControlFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1023 {
1024 PIO_STACK_LOCATION Stack;
1025 ULONG IoControlCode;
1026 PHUB_DEVICE_EXTENSION DeviceExtension;
1027 ULONG LengthIn, LengthOut;
1028 ULONG_PTR Information = 0;
1029 PVOID BufferIn, BufferOut;
1030 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1031
1032 Stack = IoGetCurrentIrpStackLocation(Irp);
1033 LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
1034 LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
1035 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1036 IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
1037 UsbhubGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);
1038
1039 switch (IoControlCode)
1040 {
1041 case IOCTL_USB_GET_NODE_INFORMATION:
1042 {
1043 //PUSB_NODE_INFORMATION NodeInformation;
1044
1045 DPRINT1("Usbhub: IOCTL_USB_GET_NODE_INFORMATION\n");
1046 if (LengthOut < sizeof(USB_NODE_INFORMATION))
1047 Status = STATUS_BUFFER_TOO_SMALL;
1048 else if (BufferOut == NULL)
1049 Status = STATUS_INVALID_PARAMETER;
1050 else
1051 {
1052 /*NodeInformation = (PUSB_NODE_INFORMATION)BufferOut;
1053 dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev;
1054 NodeInformation->NodeType = UsbHub;
1055 RtlCopyMemory(
1056 &NodeInformation->u.HubInformation.HubDescriptor,
1057 ((struct usb_hub *)usb_get_intfdata(to_usb_interface(&dev->actconfig->interface[0].dev)))->descriptor,
1058 sizeof(USB_HUB_DESCRIPTOR));
1059 NodeInformation->u.HubInformation.HubIsBusPowered = dev->actconfig->desc.bmAttributes & 0x80;
1060 Information = sizeof(USB_NODE_INFORMATION);*/
1061 Status = STATUS_SUCCESS;
1062 }
1063 break;
1064 }
1065 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
1066 {
1067 PHUB_DEVICE_EXTENSION DeviceExtension;
1068 PUSB_NODE_CONNECTION_NAME ConnectionName;
1069 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1070 ConnectionName = (PUSB_NODE_CONNECTION_NAME)BufferOut;
1071
1072 DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
1073 if (LengthOut < sizeof(USB_NODE_CONNECTION_NAME))
1074 Status = STATUS_BUFFER_TOO_SMALL;
1075 else if (BufferOut == NULL)
1076 Status = STATUS_INVALID_PARAMETER;
1077 else if (ConnectionName->ConnectionIndex < 1
1078 || ConnectionName->ConnectionIndex > USB_MAXCHILDREN)
1079 Status = STATUS_INVALID_PARAMETER;
1080 else if (DeviceExtension->Children[ConnectionName->ConnectionIndex - 1] == NULL)
1081 Status = STATUS_INVALID_PARAMETER;
1082 else
1083 {
1084 ULONG NeededStructureSize;
1085 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceExtension->Children[ConnectionName->ConnectionIndex - 1]->DeviceExtension;
1086 NeededStructureSize = DeviceExtension->SymbolicLinkName.Length + sizeof(UNICODE_NULL) + FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName);
1087 if (ConnectionName->ActualLength < NeededStructureSize / sizeof(WCHAR)
1088 || LengthOut < NeededStructureSize)
1089 {
1090 /* Buffer too small */
1091 ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR);
1092 Information = sizeof(USB_NODE_CONNECTION_NAME);
1093 Status = STATUS_BUFFER_TOO_SMALL;
1094 }
1095 else
1096 {
1097 RtlCopyMemory(
1098 ConnectionName->NodeName,
1099 DeviceExtension->SymbolicLinkName.Buffer,
1100 DeviceExtension->SymbolicLinkName.Length);
1101 ConnectionName->NodeName[DeviceExtension->SymbolicLinkName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1102 DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME returns '%S'\n", ConnectionName->NodeName);
1103 ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR);
1104 Information = NeededStructureSize;
1105 Status = STATUS_SUCCESS;
1106 }
1107 Information = LengthOut;
1108 }
1109 break;
1110 }
1111 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
1112 {
1113 PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation;
1114 /*
1115 ULONG i, j, k;
1116 struct usb_device* dev;
1117 ULONG NumberOfOpenPipes = 0;
1118 ULONG SizeOfOpenPipesArray;
1119 */
1120 ConnectionInformation = (PUSB_NODE_CONNECTION_INFORMATION)BufferOut;
1121
1122 DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
1123 if (LengthOut < sizeof(USB_NODE_CONNECTION_INFORMATION))
1124 Status = STATUS_BUFFER_TOO_SMALL;
1125 else if (BufferOut == NULL)
1126 Status = STATUS_INVALID_PARAMETER;
1127 else if (ConnectionInformation->ConnectionIndex < 1
1128 || ConnectionInformation->ConnectionIndex > USB_MAXCHILDREN)
1129 Status = STATUS_INVALID_PARAMETER;
1130 else
1131 {
1132 DPRINT1("Usbhub: We should succeed\n");
1133 }
1134 break;
1135 }
1136 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
1137 {
1138 //PUSB_DESCRIPTOR_REQUEST Descriptor;
1139 DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
1140 Information = 0;
1141 Status = STATUS_NOT_IMPLEMENTED;
1142 break;
1143 }
1144 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
1145 {
1146 PHUB_DEVICE_EXTENSION DeviceExtension;
1147 PUSB_NODE_CONNECTION_DRIVERKEY_NAME StringDescriptor;
1148 DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
1149 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1150 StringDescriptor = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)BufferOut;
1151 if (LengthOut < sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME))
1152 Status = STATUS_BUFFER_TOO_SMALL;
1153 else if (StringDescriptor == NULL)
1154 Status = STATUS_INVALID_PARAMETER;
1155 else if (StringDescriptor->ConnectionIndex < 1
1156 || StringDescriptor->ConnectionIndex > USB_MAXCHILDREN)
1157 Status = STATUS_INVALID_PARAMETER;
1158 else if (DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1] == NULL)
1159 Status = STATUS_INVALID_PARAMETER;
1160 else
1161 {
1162 ULONG StringSize;
1163 Status = IoGetDeviceProperty(
1164 DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1],
1165 DevicePropertyDriverKeyName,
1166 LengthOut - FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName),
1167 StringDescriptor->DriverKeyName,
1168 &StringSize);
1169 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
1170 {
1171 StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName);
1172 Information = LengthOut;
1173 Status = STATUS_SUCCESS;
1174 }
1175 }
1176 break;
1177 }
1178 default:
1179 {
1180 /* Pass Irp to lower driver */
1181 DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
1182 return ForwardIrpAndForget(DeviceObject, Irp);
1183 }
1184 }
1185
1186 Irp->IoStatus.Information = Information;
1187 Irp->IoStatus.Status = Status;
1188 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1189 return Status;
1190 }