2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS USB miniport driver (Cromwell type)
4 * FILE: drivers/usb/miniport/common/main.c
5 * PURPOSE: Driver entry
7 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.com)
8 * Hervé Poussineau (hpoussin@reactos.org),
10 * Some parts of code are inspired (or even just copied) from
11 * ReactOS Videoport driver (drivers/video/videoprt)
18 #include "usbcommon.h"
20 // data for embedded drivers
21 CONNECT_DATA KbdClassInformation
;
22 CONNECT_DATA MouseClassInformation
;
23 PDEVICE_OBJECT KeyboardFdo
= NULL
;
24 PDEVICE_OBJECT MouseFdo
= NULL
;
28 IN PDRIVER_OBJECT DriverObject
,
29 IN PDEVICE_OBJECT Fdo
,
30 OUT PDEVICE_OBJECT
* pPdo
)
33 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
36 DPRINT("USBMP: CreateRootHubPdo()\n");
38 Status
= IoCreateDevice(
40 sizeof(USBMP_DEVICE_EXTENSION
),
41 NULL
, /* DeviceName */
42 FILE_DEVICE_BUS_EXTENDER
,
43 FILE_DEVICE_SECURE_OPEN
| FILE_AUTOGENERATED_DEVICE_NAME
,
46 if (!NT_SUCCESS(Status
))
48 DPRINT("USBMP: IoCreateDevice() call failed with status 0x%08x\n", Status
);
52 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
53 Pdo
->Flags
|= DO_POWER_PAGABLE
;
55 // zerofill device extension
56 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)Pdo
->DeviceExtension
;
57 RtlZeroMemory(DeviceExtension
, sizeof(USBMP_DEVICE_EXTENSION
));
59 DeviceExtension
->IsFDO
= FALSE
;
60 DeviceExtension
->FunctionalDeviceObject
= Fdo
;
62 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
65 return STATUS_SUCCESS
;
70 IN PCWSTR PortTypeName
,
71 IN PUNICODE_STRING DeviceName
,
72 IN PCWSTR RegistryPath
)
74 UNICODE_STRING PathU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
75 OBJECT_ATTRIBUTES ObjectAttributes
;
76 HANDLE hDeviceMapKey
= (HANDLE
)-1;
77 HANDLE hPortKey
= (HANDLE
)-1;
78 UNICODE_STRING PortTypeNameU
;
81 InitializeObjectAttributes(&ObjectAttributes
, &PathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
82 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
83 if (!NT_SUCCESS(Status
))
85 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
89 RtlInitUnicodeString(&PortTypeNameU
, PortTypeName
);
90 InitializeObjectAttributes(&ObjectAttributes
, &PortTypeNameU
, OBJ_KERNEL_HANDLE
, hDeviceMapKey
, NULL
);
91 Status
= ZwCreateKey(&hPortKey
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
92 if (!NT_SUCCESS(Status
))
94 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
98 Status
= ZwSetValueKey(hPortKey
, DeviceName
, 0, REG_SZ
, (PVOID
)RegistryPath
, wcslen(RegistryPath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
99 if (!NT_SUCCESS(Status
))
101 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
105 Status
= STATUS_SUCCESS
;
108 if (hDeviceMapKey
!= (HANDLE
)-1)
109 ZwClose(hDeviceMapKey
);
110 if (hPortKey
!= (HANDLE
)-1)
117 IN PDRIVER_OBJECT DriverObject
,
118 IN PDEVICE_OBJECT Pdo
)
120 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\KeyboardPortUSB");
124 Status
= AddRegistryEntry(L
"KeyboardPort", &DeviceName
, L
"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport");
125 if (!NT_SUCCESS(Status
))
127 DPRINT1("USBMP: AddRegistryEntry() for usb keyboard driver failed with status 0x%08lx\n", Status
);
131 Status
= IoCreateDevice(DriverObject
,
134 FILE_DEVICE_KEYBOARD
,
135 FILE_DEVICE_SECURE_OPEN
,
139 if (!NT_SUCCESS(Status
))
141 DPRINT1("USBMP: IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status
);
145 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
146 DPRINT("USBMP: Created keyboard Fdo: %p\n", Fdo
);
148 return STATUS_SUCCESS
;
153 IN PDRIVER_OBJECT DriverObject
,
154 IN PDEVICE_OBJECT Pdo
)
156 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\PointerPortUSB");
160 Status
= AddRegistryEntry(L
"PointerPort", &DeviceName
, L
"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport");
161 if (!NT_SUCCESS(Status
))
163 DPRINT1("USBMP: AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status
);
167 Status
= IoCreateDevice(DriverObject
,
171 FILE_DEVICE_SECURE_OPEN
,
175 if (!NT_SUCCESS(Status
))
177 DPRINT1("USBMP: IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status
);
181 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
182 DPRINT("USBMP: Created mouse Fdo: %p\n", Fdo
);
184 return STATUS_SUCCESS
;
189 IN PDRIVER_OBJECT DriverObject
,
190 IN PDEVICE_OBJECT pdo
)
194 WCHAR DeviceBuffer
[20];
195 WCHAR LinkDeviceBuffer
[20];
196 UNICODE_STRING DeviceName
;
197 UNICODE_STRING LinkDeviceName
;
198 PUSBMP_DRIVER_EXTENSION DriverExtension
;
199 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
202 /* FIXME: actually, we prevent multiple USB controllers on a computer */
203 static BOOLEAN xbox_workaround
= FALSE
;
205 DPRINT("USBMP: AddDevice called\n");
208 // Fail for any other host controller than the first
209 return STATUS_INSUFFICIENT_RESOURCES
;
210 xbox_workaround
= TRUE
;
212 // Allocate driver extension now
213 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
214 if (DriverExtension
== NULL
)
216 Status
= IoAllocateDriverObjectExtension(
219 sizeof(USBMP_DRIVER_EXTENSION
),
220 (PVOID
*)&DriverExtension
);
222 if (!NT_SUCCESS(Status
))
224 DPRINT("USBMP: Allocating DriverObjectExtension failed.\n");
229 // Create a unicode device name
230 DeviceNumber
= 0; //TODO: Allocate new device number every time
231 swprintf(DeviceBuffer
, L
"\\Device\\USBFDO-%lu", DeviceNumber
);
232 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
234 Status
= IoCreateDevice(DriverObject
,
235 sizeof(USBMP_DEVICE_EXTENSION
),
237 FILE_DEVICE_BUS_EXTENDER
,
242 if (!NT_SUCCESS(Status
))
244 DPRINT("USBMP: IoCreateDevice call failed with status 0x%08lx\n", Status
);
248 // zerofill device extension
249 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)fdo
->DeviceExtension
;
250 RtlZeroMemory(DeviceExtension
, sizeof(USBMP_DEVICE_EXTENSION
));
252 /* Create root hub Pdo */
253 Status
= CreateRootHubPdo(DriverObject
, fdo
, &DeviceExtension
->RootHubPdo
);
254 if (!NT_SUCCESS(Status
))
256 DPRINT("USBMP: CreateRootHubPdo() failed with status 0x%08lx\n", Status
);
261 /* Register device interface for controller */
262 Status
= IoRegisterDeviceInterface(
264 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER
,
266 &DeviceExtension
->HcdInterfaceName
);
267 if (!NT_SUCCESS(Status
))
269 DPRINT("USBMP: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
270 IoDeleteDevice(DeviceExtension
->RootHubPdo
);
275 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(fdo
, pdo
);
277 // Initialize device extension
278 DeviceExtension
->IsFDO
= TRUE
;
279 DeviceExtension
->DeviceNumber
= DeviceNumber
;
280 DeviceExtension
->PhysicalDeviceObject
= pdo
;
281 DeviceExtension
->FunctionalDeviceObject
= fdo
;
282 DeviceExtension
->DriverExtension
= DriverExtension
;
284 fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
286 /* FIXME: do a loop to find an available number */
287 swprintf(LinkDeviceBuffer
, L
"\\??\\HCD%lu", 0);
289 RtlInitUnicodeString(&LinkDeviceName
, LinkDeviceBuffer
);
291 Status
= IoCreateSymbolicLink(&LinkDeviceName
, &DeviceName
);
293 if (NT_SUCCESS(Status
))
294 Status
= AddDevice_Keyboard(DriverObject
, pdo
);
295 if (NT_SUCCESS(Status
))
296 Status
= AddDevice_Mouse(DriverObject
, pdo
);
298 if (!NT_SUCCESS(Status
))
300 DPRINT("USBMP: IoCreateSymbolicLink() call failed with status 0x%08x\n", Status
);
301 IoDeleteDevice(DeviceExtension
->RootHubPdo
);
307 return STATUS_SUCCESS
;
312 IN PDEVICE_OBJECT DeviceObject
,
315 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
317 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
319 DPRINT1("USBMP: FDO stub for major function 0x%lx\n",
320 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
324 return ForwardIrpAndForget(DeviceObject
, Irp
);
328 /* We can't forward request to the lower driver, because
329 * we are a Pdo, so we don't have lower driver...
331 DPRINT1("USBMP: PDO stub for major function 0x%lx\n",
332 IoGetCurrentIrpStackLocation(Irp
)->MajorFunction
);
338 Status
= Irp
->IoStatus
.Status
;
339 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
343 static NTSTATUS STDCALL
344 DispatchCreate(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
346 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
347 return UsbMpCreate(DeviceObject
, Irp
);
349 return IrpStub(DeviceObject
, Irp
);
352 static NTSTATUS STDCALL
353 DispatchClose(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
355 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
356 return UsbMpClose(DeviceObject
, Irp
);
358 return IrpStub(DeviceObject
, Irp
);
361 static NTSTATUS STDCALL
362 DispatchCleanup(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
364 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
365 return UsbMpCleanup(DeviceObject
, Irp
);
367 return IrpStub(DeviceObject
, Irp
);
370 static NTSTATUS STDCALL
371 DispatchDeviceControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
373 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
374 return UsbMpDeviceControlFdo(DeviceObject
, Irp
);
376 return UsbMpDeviceControlPdo(DeviceObject
, Irp
);
379 static NTSTATUS STDCALL
380 DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
382 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
383 return UsbMpInternalDeviceControlFdo(DeviceObject
, Irp
);
385 return IrpStub(DeviceObject
, Irp
);
388 static NTSTATUS STDCALL
389 DispatchPnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
391 if (((PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
)
392 return UsbMpPnpFdo(DeviceObject
, Irp
);
394 return UsbMpPnpPdo(DeviceObject
, Irp
);
397 static NTSTATUS STDCALL
398 DispatchPower(PDEVICE_OBJECT fido
, PIRP Irp
)
400 DPRINT1("USBMP: IRP_MJ_POWER unimplemented\n");
401 Irp
->IoStatus
.Information
= 0;
402 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
403 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
404 return STATUS_SUCCESS
;
408 * Standard DriverEntry method.
411 DriverEntry(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegPath
)
413 USBPORT_INTERFACE UsbPortInterface
;
416 DriverObject
->DriverUnload
= DriverUnload
;
417 DriverObject
->DriverExtension
->AddDevice
= AddDevice
;
419 for (i
= 0; i
< IRP_MJ_MAXIMUM_FUNCTION
; i
++)
420 DriverObject
->MajorFunction
[i
] = IrpStub
;
422 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = DispatchCreate
;
423 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = DispatchClose
;
424 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = DispatchCleanup
;
425 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = DispatchDeviceControl
;
426 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = DispatchInternalDeviceControl
;
427 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = DispatchPnp
;
428 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = DispatchPower
;
430 // Register in usbcore.sys
431 UsbPortInterface
.KbdConnectData
= &KbdClassInformation
;
432 UsbPortInterface
.MouseConnectData
= &MouseClassInformation
;
434 KbdClassInformation
.ClassService
= NULL
;
435 KbdClassInformation
.ClassDeviceObject
= NULL
;
436 MouseClassInformation
.ClassService
= NULL
;
437 MouseClassInformation
.ClassDeviceObject
= NULL
;
439 RegisterPortDriver(DriverObject
, &UsbPortInterface
);
441 return STATUS_SUCCESS
;