6d07d3e6082f3a55f378be1e0cb0bedafce8a360
[reactos.git] / drivers / usb / usbhub_new / pdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
5 * PURPOSE: Handle PDO
6 * PROGRAMMERS:
7 * Hervé Poussineau (hpoussin@reactos.org)
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbhub.h"
13
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
15
16 NTSTATUS
17 NTAPI
18 UrbCompletion(
19 PDEVICE_OBJECT DeviceObject,
20 PIRP Irp,
21 PVOID Context)
22 {
23 PIRP OriginalIrp;
24 DPRINT("Entered Urb Completion\n");
25
26 //
27 // Get the original Irp
28 //
29 OriginalIrp = (PIRP)Context;
30
31 //
32 // Update it to match what was returned for the IRP that was passed to RootHub
33 //
34 OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
35 OriginalIrp->IoStatus.Information = Irp->IoStatus.Information;
36 DPRINT("Status %x, Information %x\n", Irp->IoStatus.Status, Irp->IoStatus.Information);
37
38 //
39 // Complete the original Irp
40 //
41 IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
42
43 //
44 // Return this status so the IO Manager doesnt mess with the Irp
45 //
46 return STATUS_MORE_PROCESSING_REQUIRED;
47 }
48
49 NTSTATUS
50 FowardUrbToRootHub(
51 PDEVICE_OBJECT RootHubDeviceObject,
52 IN ULONG IoControlCode,
53 PIRP Irp,
54 OUT PVOID OutParameter1,
55 OUT PVOID OutParameter2)
56 {
57 NTSTATUS Status;
58 PIRP ForwardIrp;
59 IO_STATUS_BLOCK IoStatus;
60 PIO_STACK_LOCATION ForwardStack, CurrentStack;
61 PURB Urb;
62
63 //
64 // Get the current stack location for the Irp
65 //
66 CurrentStack = IoGetCurrentIrpStackLocation(Irp);
67 ASSERT(CurrentStack);
68
69 //
70 // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub
71 //
72 Urb = (PURB)CurrentStack->Parameters.Others.Argument1;
73 ASSERT(Urb);
74
75 //
76 // Create the Irp to forward to RootHub
77 //
78 ForwardIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN,
79 RootHubDeviceObject,
80 NULL,
81 0,
82 0,
83 &IoStatus);
84 if (!ForwardIrp)
85 {
86 DPRINT1("Failed to allocate IRP\n");
87 return STATUS_INSUFFICIENT_RESOURCES;
88 }
89
90 //
91 // Get the new Irps next stack
92 //
93 ForwardStack = IoGetNextIrpStackLocation(ForwardIrp);
94
95 //
96 // Copy the stack for the current irp into the next stack of new irp
97 //
98 RtlCopyMemory(ForwardStack, CurrentStack, sizeof(IO_STACK_LOCATION));
99
100 IoStatus.Status = STATUS_NOT_SUPPORTED;
101 IoStatus.Information = 0;
102
103 //
104 // Mark the Irp from upper driver as pending
105 //
106 IoMarkIrpPending(Irp);
107
108 //
109 // Now set the completion routine for the new Irp.
110 //
111 IoSetCompletionRoutine(ForwardIrp,
112 UrbCompletion,
113 Irp,
114 TRUE,
115 TRUE,
116 TRUE);
117
118 Status = IoCallDriver(RootHubDeviceObject, ForwardIrp);
119
120 //
121 // Always return pending as the completion routine will take care of it
122 //
123 return STATUS_PENDING;
124 }
125
126 NTSTATUS
127 USBHUB_PdoHandleInternalDeviceControl(
128 IN PDEVICE_OBJECT DeviceObject,
129 IN PIRP Irp)
130 {
131 NTSTATUS Status;
132 PIO_STACK_LOCATION Stack;
133 ULONG_PTR Information = 0;
134 PHUB_DEVICE_EXTENSION HubDeviceExtension;
135 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
136 PDEVICE_OBJECT RootHubDeviceObject;
137 PURB Urb;
138
139 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
140
141 //
142 // get current stack location
143 //
144 Stack = IoGetCurrentIrpStackLocation(Irp);
145 ASSERT(Stack);
146
147 //
148 // Set default status
149 //
150 Status = Irp->IoStatus.Status;
151
152 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
153 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
154 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
155 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
156
157 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
158 {
159 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
160 {
161 PHUB_DEVICE_EXTENSION DeviceExtension;
162
163 DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
164 if (Irp->AssociatedIrp.SystemBuffer == NULL
165 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
166 {
167 Status = STATUS_INVALID_PARAMETER;
168 }
169 else
170 {
171 PVOID* pHubPointer;
172 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
173
174 pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
175 // FIXME
176 *pHubPointer = NULL;
177 Information = sizeof(PVOID);
178 Status = STATUS_SUCCESS;
179 }
180 break;
181 }
182 case IOCTL_INTERNAL_USB_SUBMIT_URB:
183 {
184 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
185
186 //
187 // Get the Urb
188 //
189 Urb = (PURB)Stack->Parameters.Others.Argument1;
190 ASSERT(Urb);
191
192 //
193 // Set the real device handle
194 //
195 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
196
197 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
198
199 //
200 // Submit to RootHub
201 //
202 switch (Urb->UrbHeader.Function)
203 {
204 //
205 // Debugging only
206 //
207 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
208 DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
209 break;
210 case URB_FUNCTION_CLASS_DEVICE:
211 DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
212 break;
213 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
214 DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
215 break;
216 case URB_FUNCTION_SELECT_CONFIGURATION:
217 DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n");
218 break;
219 case URB_FUNCTION_SELECT_INTERFACE:
220 DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n");
221 break;
222 case URB_FUNCTION_CLASS_OTHER:
223 DPRINT1("URB_FUNCTION_CLASS_OTHER\n");
224 break;
225 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
226 {
227 /*
228 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
229 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
230 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
231 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
232 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
233 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
234 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
235 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
236 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
237 {
238 }
239 */
240 break;
241
242 }
243 case URB_FUNCTION_CLASS_INTERFACE:
244 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
245 break;
246 default:
247 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
248 break;
249 }
250 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
251 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
252 //
253 // Send the request to RootHub
254 //
255 Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
256 return Status;
257 break;
258 }
259 //
260 // FIXME: Can these be sent to RootHub?
261 //
262 case IOCTL_INTERNAL_USB_RESET_PORT:
263 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
264 break;
265 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
266 {
267 PORT_STATUS_CHANGE PortStatus;
268 LONG PortId;
269 PUCHAR PortStatusBits;
270
271 PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1;
272 //
273 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
274 //
275 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
276 DPRINT1("Arg1 %x\n", *PortStatusBits);
277 *PortStatusBits = 0;
278 if (Stack->Parameters.Others.Argument1)
279 {
280 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
281 {
282 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
283 if (NT_SUCCESS(Status))
284 {
285 DPRINT1("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2));
286 DPRINT1("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
287 *PortStatusBits +=
288 (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) +
289 (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
290
291 }
292 }
293 }
294
295 DPRINT1("Arg1 %x\n", *PortStatusBits);
296 Status = STATUS_SUCCESS;
297 break;
298 }
299 case IOCTL_INTERNAL_USB_ENABLE_PORT:
300 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
301 break;
302 case IOCTL_INTERNAL_USB_CYCLE_PORT:
303 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
304 break;
305 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
306 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
307 break;
308 default:
309 {
310 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
311 Information = Irp->IoStatus.Information;
312 Status = Irp->IoStatus.Status;
313 }
314 }
315
316 if (Status != STATUS_PENDING)
317 {
318 Irp->IoStatus.Information = Information;
319 Irp->IoStatus.Status = Status;
320 IoCompleteRequest(Irp, IO_NO_INCREMENT);
321 }
322 return Status;
323 }
324
325 NTSTATUS
326 USBHUB_PdoStartDevice(
327 IN PDEVICE_OBJECT DeviceObject,
328 IN PIRP Irp)
329 {
330 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
331 //NTSTATUS Status;
332 DPRINT1("USBHUB_PdoStartDevice %x\n", DeviceObject);
333 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
334
335 //
336 // This should be a PDO
337 //
338 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
339
340 //
341 // FIXME: Fow now assume success
342 //
343
344 UNIMPLEMENTED
345 return STATUS_SUCCESS;
346 }
347
348 NTSTATUS
349 USBHUB_PdoQueryId(
350 IN PDEVICE_OBJECT DeviceObject,
351 IN PIRP Irp,
352 OUT ULONG_PTR* Information)
353 {
354 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
355 ULONG IdType;
356 PUNICODE_STRING SourceString = NULL;
357 PWCHAR ReturnString = NULL;
358 NTSTATUS Status = STATUS_SUCCESS;
359
360 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
361 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
362
363 switch (IdType)
364 {
365 case BusQueryDeviceID:
366 {
367 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
368 SourceString = &ChildDeviceExtension->usDeviceId;
369 break;
370 }
371 case BusQueryHardwareIDs:
372 {
373 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
374 SourceString = &ChildDeviceExtension->usHardwareIds;
375 break;
376 }
377 case BusQueryCompatibleIDs:
378 {
379 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
380 SourceString = &ChildDeviceExtension->usCompatibleIds;
381 break;
382 }
383 case BusQueryInstanceID:
384 {
385 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
386 SourceString = &ChildDeviceExtension->usInstanceId;
387 break;
388 }
389 default:
390 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
391 return STATUS_NOT_SUPPORTED;
392 }
393
394 if (SourceString)
395 {
396 ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
397 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
398 DPRINT1("%S\n", ReturnString);
399 }
400
401 *Information = (ULONG_PTR)ReturnString;
402
403 return Status;
404 }
405
406 NTSTATUS
407 USBHUB_PdoQueryDeviceText(
408 IN PDEVICE_OBJECT DeviceObject,
409 IN PIRP Irp,
410 OUT ULONG_PTR* Information)
411 {
412 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
413 DEVICE_TEXT_TYPE DeviceTextType;
414 PUNICODE_STRING SourceString = NULL;
415 PWCHAR ReturnString = NULL;
416 NTSTATUS Status = STATUS_SUCCESS;
417 LCID LocaleId;
418
419 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
420 LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
421 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
422
423 //
424 // FIXME: LocaleId
425 //
426
427 switch (DeviceTextType)
428 {
429 case DeviceTextDescription:
430 case DeviceTextLocationInformation:
431 {
432 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
433
434 //
435 // does the device provide a text description
436 //
437 if (ChildDeviceExtension->usTextDescription.Buffer && ChildDeviceExtension->usTextDescription.Length)
438 {
439 //
440 // use device text
441 //
442 SourceString = &ChildDeviceExtension->usTextDescription;
443 }
444 break;
445 }
446 default:
447 {
448 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
449 Status = STATUS_NOT_SUPPORTED;
450 break;
451 }
452 }
453
454 if (SourceString)
455 {
456 ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
457 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
458 DPRINT1("%S\n", ReturnString);
459 *Information = (ULONG_PTR)ReturnString;
460 }
461
462 return Status;
463 }
464
465 NTSTATUS
466 USBHUB_PdoHandlePnp(
467 IN PDEVICE_OBJECT DeviceObject,
468 IN PIRP Irp)
469 {
470 NTSTATUS Status;
471 ULONG MinorFunction;
472 PIO_STACK_LOCATION Stack;
473 ULONG_PTR Information = 0;
474 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
475
476 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
477 Stack = IoGetCurrentIrpStackLocation(Irp);
478 MinorFunction = Stack->MinorFunction;
479
480 switch (MinorFunction)
481 {
482 case IRP_MN_START_DEVICE:
483 {
484 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
485 Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
486 break;
487 }
488 case IRP_MN_QUERY_CAPABILITIES:
489 {
490 PDEVICE_CAPABILITIES DeviceCapabilities;
491 ULONG i;
492 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
493
494 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
495 // FIXME: capabilities can change with connected device
496 DeviceCapabilities->LockSupported = FALSE;
497 DeviceCapabilities->EjectSupported = FALSE;
498 DeviceCapabilities->Removable = TRUE;
499 DeviceCapabilities->DockDevice = FALSE;
500 DeviceCapabilities->UniqueID = FALSE;
501 DeviceCapabilities->SilentInstall = FALSE;
502 DeviceCapabilities->RawDeviceOK = FALSE;
503 DeviceCapabilities->SurpriseRemovalOK = FALSE;
504 DeviceCapabilities->HardwareDisabled = FALSE;
505 //DeviceCapabilities->NoDisplayInUI = FALSE;
506 DeviceCapabilities->Address = UsbChildExtension->PortNumber;
507 DeviceCapabilities->UINumber = 0;
508 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
509 for (i = 1; i < PowerSystemMaximum; i++)
510 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
511 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
512 DeviceCapabilities->D1Latency = 0;
513 DeviceCapabilities->D2Latency = 0;
514 DeviceCapabilities->D3Latency = 0;
515 Status = STATUS_SUCCESS;
516 break;
517 }
518 case IRP_MN_QUERY_RESOURCES:
519 {
520 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
521
522 Information = Irp->IoStatus.Information;
523 Status = Irp->IoStatus.Status;
524 break;
525 }
526 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
527 {
528 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
529
530 Information = Irp->IoStatus.Information;
531 Status = Irp->IoStatus.Status;
532 break;
533 }
534 case IRP_MN_QUERY_DEVICE_TEXT:
535 {
536 Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
537 break;
538 }
539 case IRP_MN_QUERY_ID:
540 {
541 Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
542 break;
543 }
544 case IRP_MN_QUERY_BUS_INFORMATION:
545 {
546 PPNP_BUS_INFORMATION BusInfo;
547 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
548 RtlCopyMemory(&BusInfo->BusTypeGuid,
549 &GUID_BUS_TYPE_USB,
550 sizeof(BusInfo->BusTypeGuid));
551 BusInfo->LegacyBusType = PNPBus;
552 // FIXME
553 BusInfo->BusNumber = 0;
554 Information = (ULONG_PTR)BusInfo;
555 Status = STATUS_SUCCESS;
556 break;
557 }
558 case IRP_MN_REMOVE_DEVICE:
559 {
560 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
561 PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
562
563 DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
564
565 /* Remove the device */
566 HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
567
568 /* Complete the IRP */
569 Irp->IoStatus.Status = STATUS_SUCCESS;
570 IoCompleteRequest(Irp, IO_NO_INCREMENT);
571
572 /* Delete the device object */
573 IoDeleteDevice(DeviceObject);
574 return STATUS_SUCCESS;
575 }
576 default:
577 {
578 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
579 Information = Irp->IoStatus.Information;
580 Status = Irp->IoStatus.Status;
581 }
582 }
583
584 Irp->IoStatus.Information = Information;
585 Irp->IoStatus.Status = Status;
586 IoCompleteRequest(Irp, IO_NO_INCREMENT);
587 return Status;
588 }
589