Allow more than one USB controller (was a XBOX hack no more needed)
[reactos.git] / reactos / drivers / usb / miniport / common / main.c
index 8d359cd..88785c7 100644 (file)
 #define INITGUID
 #include "usbcommon.h"
 
-static ULONG DeviceNumber = 0; /* FIXME: what is that? */
+// data for embedded drivers
+CONNECT_DATA KbdClassInformation;
+CONNECT_DATA MouseClassInformation;
+PDEVICE_OBJECT KeyboardFdo = NULL;
+PDEVICE_OBJECT MouseFdo = NULL;
 
 static NTSTATUS
 CreateRootHubPdo(
@@ -61,6 +65,125 @@ CreateRootHubPdo(
        return STATUS_SUCCESS;
 }
 
+static NTSTATUS
+AddRegistryEntry(
+       IN PCWSTR PortTypeName,
+       IN PUNICODE_STRING DeviceName,
+       IN PCWSTR RegistryPath)
+{
+       UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       HANDLE hDeviceMapKey = (HANDLE)-1;
+       HANDLE hPortKey = (HANDLE)-1;
+       UNICODE_STRING PortTypeNameU;
+       NTSTATUS Status;
+
+       InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
+       Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
+               goto cleanup;
+       }
+
+       RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
+       InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
+       Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
+               goto cleanup;
+       }
+
+       Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
+               goto cleanup;
+       }
+
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       if (hDeviceMapKey != (HANDLE)-1)
+               ZwClose(hDeviceMapKey);
+       if (hPortKey != (HANDLE)-1)
+               ZwClose(hPortKey);
+       return Status;
+}
+
+static NTSTATUS
+AddDevice_Keyboard(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PDEVICE_OBJECT Pdo)
+{
+       UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPortUSB");
+       PDEVICE_OBJECT Fdo;
+       NTSTATUS Status;
+
+       Status = AddRegistryEntry(L"KeyboardPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport");
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("USBMP: AddRegistryEntry() for usb keyboard driver failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       Status = IoCreateDevice(DriverObject,
+               8, // debug
+               &DeviceName,
+               FILE_DEVICE_KEYBOARD,
+               FILE_DEVICE_SECURE_OPEN,
+               TRUE,
+               &Fdo);
+
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("USBMP: IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+       KeyboardFdo = Fdo;
+       Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+       DPRINT("USBMP: Created keyboard Fdo: %p\n", Fdo);
+
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+AddDevice_Mouse(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PDEVICE_OBJECT Pdo)
+{
+       UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerPortUSB");
+       PDEVICE_OBJECT Fdo;
+       NTSTATUS Status;
+
+       Status = AddRegistryEntry(L"PointerPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport");
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("USBMP: AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       Status = IoCreateDevice(DriverObject,
+               8, // debug
+               &DeviceName,
+               FILE_DEVICE_MOUSE,
+               FILE_DEVICE_SECURE_OPEN,
+               TRUE,
+               &Fdo);
+
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("USBMP: IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+       MouseFdo = Fdo;
+       Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+       DPRINT("USBMP: Created mouse Fdo: %p\n", Fdo);
+
+       return STATUS_SUCCESS;
+}
+
 NTSTATUS STDCALL
 AddDevice(
        IN PDRIVER_OBJECT DriverObject,
@@ -74,8 +197,7 @@ AddDevice(
        UNICODE_STRING LinkDeviceName;
        PUSBMP_DRIVER_EXTENSION DriverExtension;
        PUSBMP_DEVICE_EXTENSION DeviceExtension;
-
-       DPRINT("USBMP: AddDevice called\n");
+       ULONG DeviceNumber;
 
        // Allocate driver extension now
        DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
@@ -95,7 +217,7 @@ AddDevice(
        }
 
        // Create a unicode device name
-//     DeviceNumber = 0; //TODO: Allocate new device number every time
+       DeviceNumber = 0; //TODO: Allocate new device number every time
        swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
        RtlInitUnicodeString(&DeviceName, DeviceBuffer);
 
@@ -142,8 +264,6 @@ AddDevice(
 
        DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
 
-       fdo->Flags &= ~DO_DEVICE_INITIALIZING;
-
        // Initialize device extension
        DeviceExtension->IsFDO = TRUE;
        DeviceExtension->DeviceNumber = DeviceNumber;
@@ -151,6 +271,8 @@ AddDevice(
        DeviceExtension->FunctionalDeviceObject = fdo;
        DeviceExtension->DriverExtension = DriverExtension;
 
+       fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+       
        /* FIXME: do a loop to find an available number */
        swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", 0);
 
@@ -158,13 +280,19 @@ AddDevice(
 
        Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName);
 
+       if (NT_SUCCESS(Status))
+               Status = AddDevice_Keyboard(DriverObject, pdo);
+       if (NT_SUCCESS(Status))
+               Status = AddDevice_Mouse(DriverObject, pdo);
+
        if (!NT_SUCCESS(Status))
        {
-               DPRINT("USBMP: IoCreateSymbolicLink call failed with status 0x%08x\n", Status);
+               DPRINT("USBMP: IoCreateSymbolicLink() call failed with status 0x%08x\n", Status);
                IoDeleteDevice(DeviceExtension->RootHubPdo);
                IoDeleteDevice(fdo);
                return Status;
        }
+       
 
        return STATUS_SUCCESS;
 }
@@ -238,6 +366,15 @@ DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
                return UsbMpDeviceControlPdo(DeviceObject, Irp);
 }
 
+static NTSTATUS STDCALL
+DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+       if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
+               return UsbMpInternalDeviceControlFdo(DeviceObject, Irp);
+       else
+               return IrpStub(DeviceObject, Irp);
+}
+
 static NTSTATUS STDCALL
 DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
@@ -263,6 +400,7 @@ DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
 NTSTATUS STDCALL
 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
 {
+       USBPORT_INTERFACE UsbPortInterface;
        ULONG i;
 
        DriverObject->DriverUnload = DriverUnload;
@@ -275,8 +413,20 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
        DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
+       DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl;
        DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
        DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
 
+       // Register in usbcore.sys
+       UsbPortInterface.KbdConnectData = &KbdClassInformation;
+       UsbPortInterface.MouseConnectData = &MouseClassInformation;
+       
+       KbdClassInformation.ClassService = NULL;
+       KbdClassInformation.ClassDeviceObject = NULL;
+       MouseClassInformation.ClassService = NULL;
+       MouseClassInformation.ClassDeviceObject = NULL;
+       
+       RegisterPortDriver(DriverObject, &UsbPortInterface);
+
        return STATUS_SUCCESS;
 }