2 * PROJECT: ReactOS USB miniport driver (Cromwell type)
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/miniport/common/pdo.c
5 * PURPOSE: Operations on PDOs
6 * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * Copyright James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
13 #include "usbcommon.h"
16 extern struct usb_driver hub_driver
;
18 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
22 IN PDEVICE_OBJECT DeviceObject
,
25 DPRINT("IRP_MJ_CREATE\n");
28 Irp
->IoStatus
.Information
= 0;
29 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
30 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
31 return STATUS_SUCCESS
;
36 IN PDEVICE_OBJECT DeviceObject
,
39 DPRINT("IRP_MJ_CLOSE\n");
42 Irp
->IoStatus
.Information
= 0;
43 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
44 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
45 return STATUS_SUCCESS
;
50 IN PDEVICE_OBJECT DeviceObject
,
53 DPRINT("IRP_MJ_CLEANUP\n");
56 Irp
->IoStatus
.Information
= 0;
57 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
58 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
59 return STATUS_SUCCESS
;
63 UsbMpPdoDeviceControl(
64 IN PDEVICE_OBJECT DeviceObject
,
67 PIO_STACK_LOCATION Stack
;
68 ULONG_PTR Information
= 0;
71 DPRINT("UsbMpDeviceControlPdo() called\n");
73 Stack
= IoGetCurrentIrpStackLocation(Irp
);
74 Status
= Irp
->IoStatus
.Status
;
76 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
78 case IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE
:
80 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
82 DPRINT("IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE\n");
83 if (Irp
->AssociatedIrp
.SystemBuffer
== NULL
84 || Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(PVOID
))
86 Status
= STATUS_INVALID_PARAMETER
;
90 PVOID
* pRootHubPointer
;
91 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
92 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceExtension
->FunctionalDeviceObject
->DeviceExtension
;
94 pRootHubPointer
= (PVOID
*)Irp
->AssociatedIrp
.SystemBuffer
;
95 *pRootHubPointer
= ((struct usb_hcd
*)DeviceExtension
->pdev
->data
)->self
.root_hub
;
96 Information
= sizeof(PVOID
);
97 Status
= STATUS_SUCCESS
;
103 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
104 Information
= Irp
->IoStatus
.Information
;
105 Status
= Irp
->IoStatus
.Status
;
109 Irp
->IoStatus
.Information
= Information
;
110 Irp
->IoStatus
.Status
= Status
;
111 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
117 IN PDEVICE_OBJECT DeviceObject
,
119 OUT ULONG_PTR
* Information
)
121 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
123 UNICODE_STRING SourceString
;
124 UNICODE_STRING String
;
125 struct usb_device
*roothub
;
126 NTSTATUS Status
= STATUS_SUCCESS
;
128 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
129 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
130 RtlInitUnicodeString(&String
, NULL
);
131 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceExtension
->FunctionalDeviceObject
->DeviceExtension
;
132 roothub
= ((struct usb_hcd
*)DeviceExtension
->pdev
->data
)->self
.root_hub
;
136 case BusQueryDeviceID
:
138 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
139 if (roothub
->speed
== USB_SPEED_LOW
|| roothub
->speed
== USB_SPEED_FULL
)
140 RtlInitUnicodeString(&SourceString
, L
"USB\\ROOT_HUB"); /* USB 1.1 */
142 RtlInitUnicodeString(&SourceString
, L
"USB\\ROOT_HUB20"); /* USB 2.0 */
145 case BusQueryHardwareIDs
:
149 PCI_COMMON_CONFIG PciData
;
150 ULONG BusNumber
, SlotNumber
;
154 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
156 Pdo
= DeviceExtension
->PhysicalDeviceObject
;
157 Status
= IoGetDeviceProperty(
159 DevicePropertyBusNumber
,
163 if (!NT_SUCCESS(Status
))
165 DPRINT("IoGetDeviceProperty() failed with status 0x%08lx\n", Status
);
169 Status
= IoGetDeviceProperty(
171 DevicePropertyAddress
,
175 if (!NT_SUCCESS(Status
))
177 DPRINT("IoGetDeviceProperty() failed with status 0x%08lx\n", Status
);
181 ret
= HalGetBusDataByOffset(PCIConfiguration
,
186 PCI_COMMON_HDR_LENGTH
);
187 if (ret
!= PCI_COMMON_HDR_LENGTH
)
189 DPRINT("HalGetBusDataByOffset() failed (ret = %ld)\n", ret
);
190 Status
= STATUS_IO_DEVICE_ERROR
;
194 sprintf(Buffer
[0], "USB\\VID%04X&PID%04X&REV%04X",
195 PciData
.VendorID
, PciData
.DeviceID
, PciData
.RevisionID
);
196 sprintf(Buffer
[1], "USB\\VID%04X&PID%04X",
197 PciData
.VendorID
, PciData
.DeviceID
);
198 if (roothub
->speed
== USB_SPEED_LOW
|| roothub
->speed
== USB_SPEED_FULL
)
199 RootHubName
= "USB\\ROOT_HUB"; /* USB 1.1 */
201 RootHubName
= "USB\\ROOT_HUB20"; /* USB 2.0 */
202 Status
= UsbMpInitMultiSzString(
204 Buffer
[0], Buffer
[1], RootHubName
, NULL
);
207 case BusQueryCompatibleIDs
:
208 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
209 /* No compatible ID */
211 return STATUS_NOT_SUPPORTED
;
212 case BusQueryInstanceID
:
214 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
219 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
220 return STATUS_NOT_SUPPORTED
;
223 if (NT_SUCCESS(Status
))
225 Status
= UsbMpDuplicateUnicodeString(
229 *Information
= (ULONG_PTR
)String
.Buffer
;
236 IN PDEVICE_OBJECT DeviceObject
,
238 OUT ULONG_PTR
* Information
)
240 PPNP_BUS_INFORMATION BusInformation
;
242 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
244 BusInformation
= ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
246 return STATUS_INSUFFICIENT_RESOURCES
;
247 BusInformation
->BusTypeGuid
= GUID_BUS_TYPE_USB
;
248 BusInformation
->LegacyBusType
= PNPBus
;
249 BusInformation
->BusNumber
= 0; /* FIXME */
250 return STATUS_SUCCESS
;
255 IN PDEVICE_OBJECT DeviceObject
)
257 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
260 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
262 /* Register device interface for root hub */
263 Status
= IoRegisterDeviceInterface(
265 &GUID_DEVINTERFACE_USB_HUB
,
267 &DeviceExtension
->HcdInterfaceName
);
268 if (!NT_SUCCESS(Status
))
270 DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
279 IN PDEVICE_OBJECT DeviceObject
,
283 PIO_STACK_LOCATION Stack
;
284 ULONG_PTR Information
= 0;
287 Stack
= IoGetCurrentIrpStackLocation(Irp
);
288 MinorFunction
= Stack
->MinorFunction
;
290 switch (MinorFunction
)
292 case IRP_MN_START_DEVICE
: /* 0x00 */
294 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
295 Status
= StartDevice(DeviceObject
);
298 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
300 PDEVICE_CAPABILITIES DeviceCapabilities
;
302 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
304 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
305 /* FIXME: capabilities can change with connected device */
306 DeviceCapabilities
->LockSupported
= FALSE
;
307 DeviceCapabilities
->EjectSupported
= FALSE
;
308 DeviceCapabilities
->Removable
= FALSE
;
309 DeviceCapabilities
->DockDevice
= FALSE
;
310 DeviceCapabilities
->UniqueID
= FALSE
;
311 DeviceCapabilities
->SilentInstall
= TRUE
;
312 DeviceCapabilities
->RawDeviceOK
= FALSE
;
313 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
314 DeviceCapabilities
->HardwareDisabled
= FALSE
; /* FIXME */
315 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
316 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
; /* FIXME */
317 for (i
= 0; i
< PowerSystemMaximum
; i
++)
318 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
; /* FIXME */
319 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
320 DeviceCapabilities
->D1Latency
= 0; /* FIXME */
321 DeviceCapabilities
->D2Latency
= 0; /* FIXME */
322 DeviceCapabilities
->D3Latency
= 0; /* FIXME */
323 Status
= STATUS_SUCCESS
;
326 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
328 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
329 /* Root buses don't need resources, except the ones of
330 * the usb controller. This PDO is the root bus PDO, so
331 * report no resource by not changing Information and
334 Information
= Irp
->IoStatus
.Information
;
335 Status
= Irp
->IoStatus
.Status
;
338 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
340 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
341 /* Root buses don't need resources, except the ones of
342 * the usb controller. This PDO is the root bus PDO, so
343 * report no resource by not changing Information and
346 Information
= Irp
->IoStatus
.Information
;
347 Status
= Irp
->IoStatus
.Status
;
350 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
352 switch (Stack
->Parameters
.QueryDeviceText
.DeviceTextType
)
354 case DeviceTextDescription
:
356 UNICODE_STRING SourceString
= RTL_CONSTANT_STRING(L
"Root USB hub");
357 UNICODE_STRING Description
;
359 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
361 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &SourceString
, &Description
);
362 if (NT_SUCCESS(Status
))
363 Information
= (ULONG_PTR
)Description
.Buffer
;
366 case DeviceTextLocationInformation
:
368 /* We don't have any text location to report,
369 * and this query is optional, so ignore it.
371 Information
= Irp
->IoStatus
.Information
;
372 Status
= Irp
->IoStatus
.Status
;
377 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
378 Stack
->Parameters
.QueryDeviceText
.DeviceTextType
);
380 Status
= STATUS_NOT_SUPPORTED
;
385 case IRP_MN_QUERY_ID
: /* 0x13 */
387 Status
= QueryId(DeviceObject
, Irp
, &Information
);
390 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
392 Status
= QueryBusInformation(DeviceObject
, Irp
, &Information
);
397 /* We can't forward request to the lower driver, because
398 * we are a Pdo, so we don't have lower driver...
400 DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
401 Information
= Irp
->IoStatus
.Information
;
402 Status
= Irp
->IoStatus
.Status
;
407 Irp
->IoStatus
.Information
= Information
;
408 Irp
->IoStatus
.Status
= Status
;
409 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
414 UsbMpPdoInternalDeviceControl(
415 IN PDEVICE_OBJECT DeviceObject
,
418 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
420 DPRINT("UsbMpDeviceInternalControlPdo(DO %p, code 0x%lx) called\n",
422 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
);
424 if (DeviceObject
== KeyboardFdo
)
426 // it's keyboard's IOCTL
427 PIO_STACK_LOCATION Stk
;
429 Irp
->IoStatus
.Information
= 0;
430 Stk
= IoGetCurrentIrpStackLocation(Irp
);
432 switch (Stk
->Parameters
.DeviceIoControl
.IoControlCode
)
434 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
435 DPRINT("IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
436 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
)) {
437 DPRINT1("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT "
438 "invalid buffer size\n");
439 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
443 RtlCopyMemory(&KbdClassInformation
,
444 Stk
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
445 sizeof(CONNECT_DATA
));
447 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
450 case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER
:
451 DPRINT("IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER\n");
452 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
< 1) {
453 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
456 /* if (!DevExt->KeyboardInterruptObject) {
457 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
461 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
463 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
464 DPRINT("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n");
465 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
466 sizeof(KEYBOARD_ATTRIBUTES
)) {
467 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES: "
468 "invalid buffer size\n");
469 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
472 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
473 &DevExt->KeyboardAttributes,
474 sizeof(KEYBOARD_ATTRIBUTES));*/
476 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
478 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
479 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATORS\n");
480 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
481 sizeof(KEYBOARD_INDICATOR_PARAMETERS
)) {
482 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_INDICATORS: "
483 "invalid buffer size\n");
484 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
487 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
488 &DevExt->KeyboardIndicators,
489 sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/
491 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
493 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
494 DPRINT("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n");
495 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
496 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
)) {
497 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC: "
498 "invalid buffer size\n");
499 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
502 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
503 &DevExt->KeyboardTypematic,
504 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
506 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
508 case IOCTL_KEYBOARD_SET_INDICATORS
:
509 DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n");
510 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
<
511 sizeof(KEYBOARD_INDICATOR_PARAMETERS
)) {
512 DPRINT("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS: "
513 "invalid buffer size\n");
514 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
518 /*RtlCopyMemory(&DevExt->KeyboardIndicators,
519 Irp->AssociatedIrp.SystemBuffer,
520 sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/
522 //DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags);
524 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
526 case IOCTL_KEYBOARD_SET_TYPEMATIC
:
527 DPRINT("IOCTL_KEYBOARD_SET_TYPEMATIC\n");
528 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
<
529 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
)) {
530 DPRINT("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC "
531 "invalid buffer size\n");
532 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
536 /*RtlCopyMemory(&DevExt->KeyboardTypematic,
537 Irp->AssociatedIrp.SystemBuffer,
538 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
540 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
542 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
543 /* We should check the UnitID, but it's kind of pointless as
544 * all keyboards are supposed to have the same one
547 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION\n");
548 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
549 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
)) {
550 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: "
551 "invalid buffer size (expected)\n");
552 /* It's to query the buffer size */
553 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
556 Irp
->IoStatus
.Information
=
557 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
);
559 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
560 &IndicatorTranslation,
561 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION));*/
563 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
565 case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
:
566 /* Nothing to do here */
567 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
570 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
575 Status
= Irp
->IoStatus
.Status
;
577 else if (DeviceObject
== MouseFdo
)
579 // it's mouse's IOCTL
580 PIO_STACK_LOCATION Stk
;
582 Irp
->IoStatus
.Information
= 0;
583 Stk
= IoGetCurrentIrpStackLocation(Irp
);
585 switch (Stk
->Parameters
.DeviceIoControl
.IoControlCode
)
587 case IOCTL_INTERNAL_MOUSE_CONNECT
:
588 DPRINT("IOCTL_INTERNAL_MOUSE_CONNECT\n");
589 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
)) {
590 DPRINT1("IOCTL_INTERNAL_MOUSE_CONNECT: "
591 "invalid buffer size\n");
592 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
593 goto intcontfailure2
;
596 RtlCopyMemory(&MouseClassInformation
,
597 Stk
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
598 sizeof(CONNECT_DATA
));
600 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
604 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;//STATUS_INVALID_DEVICE_REQUEST;
608 Status
= Irp
->IoStatus
.Status
;
612 DPRINT("We got IOCTL for UsbCore\n");
613 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
614 return STATUS_SUCCESS
;
618 if (Status
== STATUS_INVALID_DEVICE_REQUEST
) {
619 DPRINT1("Invalid internal device request!\n");
622 if (Status
!= STATUS_PENDING
)
623 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);