-/*\r
- * ReactOS USB hub driver\r
- * Copyright (C) 2004 Aleksey Bragin\r
- * (C) 2005 Mark Tempel\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- *\r
- */\r
-\r
-/* INCLUDES *******************************************************************/\r
-#include <stddef.h>\r
-#include <windef.h>\r
-#include <ddk/ntddk.h>\r
-#include "../usbport/usbport.h"\r
-\r
-/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/\r
-\r
-/*\r
- * Standard DriverEntry method.\r
- */\r
-NTSTATUS STDCALL\r
-DriverEntry(IN PVOID Context1, IN PVOID Context2)\r
-{\r
- return STATUS_SUCCESS;\r
-}\r
-\r
+/*
+ * ReactOS USB hub driver
+ * Copyright (C) 2004 Aleksey Bragin
+ * (C) 2005 Mark Tempel
+ * (C) 2005 Hervé Poussineau
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* INCLUDES *******************************************************************/
+//#define NDEBUG
+#include "usbhub.h"
+
+/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
+
+static NTSTATUS
+GetRootHubPointer(
+ IN PDEVICE_OBJECT Pdo,
+ OUT PVOID* RootHubPointer)
+{
+ KEVENT Event;
+ PIRP Irp;
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status;
+
+ KeInitializeEvent (&Event, NotificationEvent, FALSE);
+
+ Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE,
+ Pdo,
+ NULL, sizeof(NULL),
+ RootHubPointer, sizeof(*RootHubPointer),
+ FALSE,
+ &Event,
+ &IoStatus);
+ if (Irp == NULL)
+ {
+ DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = IoCallDriver(Pdo, Irp);
+
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("Usbhub: Operation pending\n");
+ KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+ Status = IoStatus.Status;
+ }
+
+ return Status;
+}
+
+NTSTATUS STDCALL
+UsbhubAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT Pdo)
+{
+ PDEVICE_OBJECT Fdo;
+ PHUB_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+
+ Status = IoCreateDevice(DriverObject,
+ sizeof(HUB_DEVICE_EXTENSION),
+ NULL, /* DeviceName */
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &Fdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Usbhub: IoCreateDevice() failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ // zerofill device extension
+ DeviceExtension = (PHUB_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, sizeof(HUB_DEVICE_EXTENSION));
+
+ /* Get a pointer to the linux structure created by the USB controller,
+ * by sending IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE to lower device.
+ */
+ Status = GetRootHubPointer(Pdo, (PVOID*)&DeviceExtension->dev);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Usbhub: GetRootHubPointer() failed with status 0x%08lx\n", Status);
+ IoDeleteDevice(Fdo);
+ return Status;
+ }
+ DeviceExtension->dev->dev.dev_ext = Pdo;
+
+ DeviceExtension->IsFDO = TRUE;
+ Fdo->Flags |= DO_POWER_PAGABLE;
+ Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Usbhub: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
+ IoDeleteDevice(Fdo);
+ return Status;
+ }
+ Fdo->Flags |= DO_BUFFERED_IO;
+ Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS STDCALL
+IrpStub(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+
+ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
+ {
+ DPRINT1("Usbhub: FDO stub for major function 0x%lx\n",
+ IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+#ifndef NDEBUG
+ DbgBreakPoint();
+#endif
+ return ForwardIrpAndForget(DeviceObject, Irp);
+ }
+ else
+ {
+ /* We can't forward request to the lower driver, because
+ * we are a Pdo, so we don't have lower driver...
+ */
+ DPRINT1("Usbhub: PDO stub for major function 0x%lx\n",
+ IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+#ifndef NDEBUG
+ DbgBreakPoint();
+#endif
+ }
+
+ Status = Irp->IoStatus.Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+static NTSTATUS STDCALL
+DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
+ return UsbhubDeviceControlFdo(DeviceObject, Irp);
+ else
+ return UsbhubDeviceControlPdo(DeviceObject, Irp);
+}
+
+static NTSTATUS STDCALL
+DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
+ return UsbhubPnpFdo(DeviceObject, Irp);
+ else
+ return UsbhubPnpPdo(DeviceObject, Irp);
+}
+
+/*
+ * Standard DriverEntry method.
+ */
+NTSTATUS STDCALL
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+{
+ ULONG i;
+
+ DriverObject->DriverExtension->AddDevice = UsbhubAddDevice;
+
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+ DriverObject->MajorFunction[i] = IrpStub;
+
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbhubCreate;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbhubClose;
+ DriverObject->MajorFunction[IRP_MJ_CLEANUP] = UsbhubCleanup;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
+ DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+ return STATUS_SUCCESS;
+}
+