reactos/drivers/usb/usbhub/usbhub.c
Timo Kreuzer 9ea495ba33 Create a branch for header work.
svn path=/branches/header-work/; revision=45691
2010-02-26 22:57:55 +00:00

209 lines
5.6 KiB
C

/*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_PARENT_HUB_INFO,
Pdo,
NULL, sizeof(NULL),
RootHubPointer, sizeof(*RootHubPointer),
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize the status block before sending the IRP */
IoGetNextIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStatus.Status = STATUS_NOT_SUPPORTED;
IoStatus.Information = 0;
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 NTAPI
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_PARENT_HUB_INFO 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 NTAPI
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 NTAPI
DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return UsbhubDeviceControlFdo(DeviceObject, Irp);
else
return IrpStub(DeviceObject, Irp);
}
static NTSTATUS NTAPI
DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return IrpStub(DeviceObject, Irp);
else
return UsbhubInternalDeviceControlPdo(DeviceObject, Irp);
}
static NTSTATUS NTAPI
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 NTAPI
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_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
return STATUS_SUCCESS;
}