Add serial port enumerator driver:
- Enumerate legacy mice
- Should also detect PnP serial devices even if they are not yet
reported
It is implemented as an upper filter for serial port driver (serial.sys)
Add corresponding registry entries
Modified: trunk/reactos/Makefile
Modified: trunk/reactos/bootdata/hivesys.inf
Modified: trunk/reactos/bootdata/packages/reactos.dff
Modified: trunk/reactos/drivers/bus/Makefile
Added: trunk/reactos/drivers/bus/serenum/
Added: trunk/reactos/drivers/bus/serenum/detect.c
Added: trunk/reactos/drivers/bus/serenum/fdo.c
Added: trunk/reactos/drivers/bus/serenum/makefile
Added: trunk/reactos/drivers/bus/serenum/misc.c
Added: trunk/reactos/drivers/bus/serenum/pdo.c
Added: trunk/reactos/drivers/bus/serenum/serenum.c
Added: trunk/reactos/drivers/bus/serenum/serenum.h
Added: trunk/reactos/drivers/bus/serenum/serenum.rc
_____
Modified: trunk/reactos/Makefile
--- trunk/reactos/Makefile 2005-04-05 18:59:56 UTC (rev 14511)
+++ trunk/reactos/Makefile 2005-04-05 19:04:07 UTC (rev 14512)
@@ -34,8 +34,8 @@
HALS = halx86/up halx86/mp
# Bus drivers
-# acpi isapnp pci
-BUS = acpi isapnp pci
+# acpi isapnp pci serenum
+BUS = acpi isapnp pci serenum
# Filesystem libraries
# vfatlib
_____
Modified: trunk/reactos/bootdata/hivesys.inf
--- trunk/reactos/bootdata/hivesys.inf 2005-04-05 18:59:56 UTC (rev
14511)
+++ trunk/reactos/bootdata/hivesys.inf 2005-04-05 19:04:07 UTC (rev
14512)
@@ -469,6 +469,19 @@
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Start",0x00010001,0x0
0000001
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Type",0x00010001,0x00
000001
+; Serial port enumerator
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum","ErrorControl",0x00010
001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Group",0x00000000,"PN
P Filter"
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum","ImagePath",0x00020000
,"system32\drivers\serenum.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Start",0x00010001,0x0
0000003
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Type",0x00010001,0x00
000001
+;hard coded values
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","0",0x00000000,"A
CPI\PNP0501"
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","Count",0x0001000
1,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","NextInstance",0x
00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1","UpperFilters",0x00
010000,"serenum"
+HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\2","UpperFilters",0x00
010000,"serenum"
+
; SB16 driver
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Bas
e"
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ServiceType",0x0001000
1,0x00000001
_____
Modified: trunk/reactos/bootdata/packages/reactos.dff
--- trunk/reactos/bootdata/packages/reactos.dff 2005-04-05 18:59:56 UTC
(rev 14511)
+++ trunk/reactos/bootdata/packages/reactos.dff 2005-04-05 19:04:07 UTC
(rev 14512)
@@ -29,6 +29,7 @@
drivers\bus\acpi\acpi.sys 2
drivers\bus\isapnp\isapnp.sys 2
drivers\bus\pci\pci.sys 2
+drivers\bus\serenum\serenum.sys 2
drivers\dd\beep\beep.sys 2
drivers\dd\bootvid\bootvid.sys 2
drivers\dd\null\null.sys 2
_____
Modified: trunk/reactos/drivers/bus/Makefile
--- trunk/reactos/drivers/bus/Makefile 2005-04-05 18:59:56 UTC (rev
14511)
+++ trunk/reactos/drivers/bus/Makefile 2005-04-05 19:04:07 UTC (rev
14512)
@@ -6,7 +6,7 @@
include $(PATH_TO_TOP)/rules.mak
-DRIVERS = acpi isapnp pci
+DRIVERS = acpi isapnp pci serenum
all: $(DRIVERS)
_____
Added: trunk/reactos/drivers/bus/serenum/detect.c
--- trunk/reactos/drivers/bus/serenum/detect.c 2005-04-05 18:59:56 UTC
(rev 14511)
+++ trunk/reactos/drivers/bus/serenum/detect.c 2005-04-05 19:04:07 UTC
(rev 14512)
@@ -0,0 +1,541 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Serial enumerator driver
+ * FILE: drivers/bus/serenum/detect.c
+ * PURPOSE: Detection of serial devices
+ *
+ * PROGRAMMERS: Jason Filby (jasonfilby(a)yahoo.com)
+ * Filip Navara (xnavara(a)volny.cz)
+ * HervÚ Poussineau (hpoussin(a)reactos.com)
+ */
+
+#define NDEBUG
+#include "serenum.h"
+
+static NTSTATUS
+SerenumDeviceIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG CtlCode,
+ IN PVOID InputBuffer OPTIONAL,
+ IN ULONG InputBufferSize,
+ IN OUT PVOID OutputBuffer OPTIONAL,
+ IN OUT PULONG OutputBufferSize)
+{
+ KEVENT Event;
+ PIRP Irp;
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status;
+
+ KeInitializeEvent (&Event, NotificationEvent, FALSE);
+
+ Irp = IoBuildDeviceIoControlRequest(CtlCode,
+ DeviceObject,
+ InputBuffer,
+ InputBufferSize,
+ OutputBuffer,
+ (OutputBufferSize) ? *OutputBufferSize : 0,
+ FALSE,
+ &Event,
+ &IoStatus);
+ if (Irp == NULL)
+ {
+ DPRINT("Serenum: IoBuildDeviceIoControlRequest()
failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = IoCallDriver(DeviceObject, Irp);
+
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("Serenum: Operation pending\n");
+ KeWaitForSingleObject(&Event, Suspended, KernelMode,
FALSE, NULL);
+ Status = IoStatus.Status;
+ }
+
+ if (OutputBufferSize)
+ {
+ *OutputBufferSize = IoStatus.Information;
+ }
+
+ return Status;
+}
+
+static NTSTATUS
+ReadBytes(
+ IN PDEVICE_OBJECT LowerDevice,
+ OUT PUCHAR Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG FilledBytes)
+{
+ PIRP Irp;
+ IO_STATUS_BLOCK ioStatus;
+ KEVENT event;
+ NTSTATUS Status;
+
+ KeInitializeEvent(&event, NotificationEvent, FALSE);
+ Irp = IoBuildSynchronousFsdRequest(
+ IRP_MJ_READ,
+ LowerDevice,
+ Buffer, BufferSize,
+ 0,
+ &event,
+ &ioStatus);
+ if (!Irp)
+ return FALSE;
+
+ Status = IoCallDriver(LowerDevice, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&event, Suspended, KernelMode,
FALSE, NULL);
+ Status = ioStatus.Status;
+ }
+ DPRINT("Serenum: bytes received: %lu/%lu\n",
+ ioStatus.Information, BufferSize);
+ *FilledBytes = ioStatus.Information;
+ return Status;
+}
+
+static NTSTATUS
+ReportDetectedDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PUNICODE_STRING DeviceDescription,
+ IN PUNICODE_STRING DeviceId,
+ IN PUNICODE_STRING HardwareIds,
+ IN PUNICODE_STRING CompatibleIds)
+{
+ PDEVICE_OBJECT Pdo = NULL;
+ PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+ PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+ NTSTATUS Status;
+
+ DPRINT("Serenum: SerenumReportDetectedDevice() called with %wZ
(%wZ) detected\n", DeviceId, DeviceDescription);
+
+ Status = IoCreateDevice(
+ DeviceObject->DriverObject,
+ sizeof(PDO_DEVICE_EXTENSION),
+ NULL,
+ FILE_DEVICE_CONTROLLER,
+ FILE_AUTOGENERATED_DEVICE_NAME,
+ FALSE,
+ &Pdo);
+ if (!NT_SUCCESS(Status)) goto ByeBye;
+
+ Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+ Pdo->Flags |= DO_POWER_PAGABLE;
+ PdoDeviceExtension =
(PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
+ FdoDeviceExtension =
(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+ PdoDeviceExtension->Common.IsFDO = FALSE;
+ Status =
SerenumDuplicateUnicodeString(&PdoDeviceExtension->DeviceDescription,
DeviceDescription, PagedPool);
+ if (!NT_SUCCESS(Status)) goto ByeBye;
+ Status =
SerenumDuplicateUnicodeString(&PdoDeviceExtension->DeviceId, DeviceId,
PagedPool);
+ if (!NT_SUCCESS(Status)) goto ByeBye;
+ Status =
SerenumDuplicateUnicodeString(&PdoDeviceExtension->HardwareIds,
HardwareIds, PagedPool);
+ if (!NT_SUCCESS(Status)) goto ByeBye;
+ Status =
SerenumDuplicateUnicodeString(&PdoDeviceExtension->CompatibleIds,
CompatibleIds, PagedPool);
+ if (!NT_SUCCESS(Status)) goto ByeBye;
+
+ /* Device attached to serial port (Pdo) may delegate work to
+ * serial port stack (Fdo = DeviceObject variable) */
+ Pdo->StackSize = DeviceObject->StackSize + 1;
+
+ FdoDeviceExtension->AttachedPdo = Pdo;
+ PdoDeviceExtension->AttachedFdo = DeviceObject;
+
+ Pdo->Flags |= DO_BUFFERED_IO;
+ Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ return STATUS_SUCCESS;
+
+ByeBye:
+ if (Pdo)
+ {
+ if (PdoDeviceExtension->DeviceDescription.Buffer)
+
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceDescription);
+ if (PdoDeviceExtension->DeviceId.Buffer)
+
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceId);
+ if (PdoDeviceExtension->HardwareIds.Buffer)
+
RtlFreeUnicodeString(&PdoDeviceExtension->HardwareIds);
+ if (PdoDeviceExtension->CompatibleIds.Buffer)
+
RtlFreeUnicodeString(&PdoDeviceExtension->CompatibleIds);
+ IoDeleteDevice(Pdo);
+ }
+ return Status;
+}
+
+static BOOLEAN
+SerenumIsValidPnpIdString(
+ IN PUCHAR Buffer,
+ IN ULONG BufferLength)
+{
+ /* FIXME: SerenumIsValidPnpIdString not implemented */
+ DPRINT1("Serenum: SerenumIsValidPnpIdString() unimplemented\n");
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+ReportDetectedPnpDevice(
+ IN PUCHAR Buffer,
+ IN ULONG BufferLength)
+{
+ ULONG i;
+ /* FIXME: ReportDetectedPnpDevice not implemented */
+ DPRINT1("Serenum: ReportDetectedPnpDevice() unimplemented\n");
+ DPRINT1("");
+ for (i = 0; i < BufferLength; i++)
+ DbgPrint("%c", Buffer[i]);
+ DbgPrint("\n");
+ /* Call ReportDetectedDevice */
+ return STATUS_SUCCESS;
+}
+
+#define BEGIN_ID '('
+#define END_ID ')'
+
+static NTSTATUS
+SerenumWait(ULONG milliseconds)
+{
+ KTIMER Timer;
+ LARGE_INTEGER DueTime;
+
+ DueTime.QuadPart = -milliseconds * 10;
+ KeInitializeTimer(&Timer);
+ KeSetTimer(&Timer, DueTime, NULL);
+ return KeWaitForSingleObject(&Timer, Executive, KernelMode,
FALSE, NULL);
+}
+
+NTSTATUS
+SerenumDetectPnpDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PDEVICE_OBJECT LowerDevice)
+{
+ UCHAR Buffer[256];
+ ULONG BaudRate;
+ ULONG TotalBytesReceived = 0;
+ ULONG Size;
+ ULONG Msr, Purge;
+ ULONG i;
+ BOOLEAN BufferContainsBeginId, BufferContainsEndId;
+ SERIAL_LINE_CONTROL Lcr;
+ SERIAL_TIMEOUTS Timeouts;
+ SERIALPERF_STATS PerfStats;
+ NTSTATUS Status;
+
+ /* 1. COM port initialization, check for device enumerate */
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ SerenumWait(200);
+ Size = sizeof(Msr);
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_GET_MODEMSTATUS,
+ NULL, 0, &Msr, &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ if ((Msr & SR_MSR_DSR) == 0) goto SerenumDisconnectIdle;
+
+ /* 2. COM port setup, 1st phase */
+ CHECKPOINT;
+ BaudRate = SERIAL_BAUD_1200;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_BAUD_RATE,
+ &BaudRate, sizeof(BaudRate), NULL, 0);
+ if (!NT_SUCCESS(Status)) return Status;
+ Lcr.WordLength = 7;
+ Lcr.Parity = NO_PARITY;
+ Lcr.StopBits = STOP_BIT_1;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_LINE_CONTROL,
+ &Lcr, sizeof(Lcr), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ SerenumWait(200);
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ SerenumWait(200);
+
+ /* 3. Wait for response, 1st phase */
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Timeouts.ReadIntervalTimeout = 0;
+ Timeouts.ReadTotalTimeoutMultiplier = 0;
+ Timeouts.ReadTotalTimeoutConstant = 200;
+ Timeouts.WriteTotalTimeoutMultiplier =
Timeouts.WriteTotalTimeoutConstant = 0;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_TIMEOUTS,
+ &Timeouts, sizeof(Timeouts), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer), &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ if (Size != 0) goto SerenumCollectPnpComDeviceId;
+
+ /* 4. COM port setup, 2nd phase */
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Purge = SERIAL_PURGE_RXABORT | SERIAL_PURGE_RXCLEAR;
+ Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_PURGE,
+ &Purge, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ SerenumWait(200);
+
+ /* 5. Wait for response, 2nd phase */
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = ReadBytes(LowerDevice, Buffer, 1, &TotalBytesReceived);
+ if (!NT_SUCCESS(Status)) return Status;
+ if (TotalBytesReceived != 0) goto SerenumCollectPnpComDeviceId;
+ Size = sizeof(Msr);
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_GET_MODEMSTATUS,
+ NULL, 0, &Msr, &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ if ((Msr & SR_MSR_DSR) == 0) goto SerenumVerifyDisconnect; else
goto SerenumConnectIdle;
+
+ /* 6. Collect PnP COM device ID */
+SerenumCollectPnpComDeviceId:
+ CHECKPOINT;
+ Timeouts.ReadIntervalTimeout = 200;
+ Timeouts.ReadTotalTimeoutMultiplier = 0;
+ Timeouts.ReadTotalTimeoutConstant = 2200;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_TIMEOUTS,
+ &Timeouts, sizeof(Timeouts), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = ReadBytes(LowerDevice, &Buffer[TotalBytesReceived],
sizeof(Buffer) - TotalBytesReceived, &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ TotalBytesReceived += Size;
+ Size = sizeof(PerfStats);
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_GET_STATS,
+ NULL, 0, &PerfStats, &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ if (PerfStats.FrameErrorCount + PerfStats.ParityErrorCount != 0)
goto SerenumConnectIdle;
+ BufferContainsBeginId = BufferContainsEndId = FALSE;
+ for (i = 0; i < TotalBytesReceived; i++)
+ {
+ if (Buffer[i] == BEGIN_ID) BufferContainsBeginId = TRUE;
+ if (Buffer[i] == END_ID) BufferContainsEndId = TRUE;
+ }
+ if (TotalBytesReceived == 1 || BufferContainsEndId)
+ {
+ if (SerenumIsValidPnpIdString(Buffer,
TotalBytesReceived))
+ return ReportDetectedPnpDevice(Buffer,
TotalBytesReceived);
+ goto SerenumConnectIdle;
+ }
+ if (!BufferContainsBeginId) goto SerenumConnectIdle;
+ if (!BufferContainsEndId) goto SerenumConnectIdle;
+ Size = sizeof(Msr);
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_GET_MODEMSTATUS,
+ NULL, 0, &Msr, &Size);
+ if (!NT_SUCCESS(Status)) return Status;
+ if ((Msr & SR_MSR_DSR) == 0) goto SerenumVerifyDisconnect;
+
+ /* 7. Verify disconnect */
+SerenumVerifyDisconnect:
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ SerenumWait(5000);
+ goto SerenumDisconnectIdle;
+
+ /* 8. Connect idle */
+SerenumConnectIdle:
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ BaudRate = SERIAL_BAUD_300;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_BAUD_RATE,
+ &BaudRate, sizeof(BaudRate), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Lcr.WordLength = 7;
+ Lcr.Parity = NO_PARITY;
+ Lcr.StopBits = STOP_BIT_1;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_LINE_CONTROL,
+ &Lcr, sizeof(Lcr), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ if (TotalBytesReceived == 0)
+ return STATUS_DEVICE_NOT_CONNECTED;
+ else
+ return STATUS_SUCCESS;
+
+ /* 9. Disconnect idle */
+SerenumDisconnectIdle:
+ CHECKPOINT;
+ /* FIXME: report to OS device removal, if it was present */
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_CLR_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ BaudRate = SERIAL_BAUD_300;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_BAUD_RATE,
+ &BaudRate, sizeof(BaudRate), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Lcr.WordLength = 7;
+ Lcr.Parity = NO_PARITY;
+ Lcr.StopBits = STOP_BIT_1;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_LINE_CONTROL,
+ &Lcr, sizeof(Lcr), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ return STATUS_DEVICE_NOT_CONNECTED;
+}
+
+NTSTATUS
+SerenumDetectLegacyDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PDEVICE_OBJECT LowerDevice)
+{
+ ULONG Fcr, Mcr;
+ ULONG BaudRate;
+ ULONG Command;
+ SERIAL_TIMEOUTS Timeouts;
+ SERIAL_LINE_CONTROL LCR;
+ ULONG i, Count;
+ UCHAR Buffer[16];
+ UNICODE_STRING DeviceDescription;
+ UNICODE_STRING DeviceId;
+ UNICODE_STRING HardwareIds;
+ UNICODE_STRING CompatibleIds;
+ NTSTATUS Status;
+
+ RtlZeroMemory(Buffer, sizeof(Buffer));
+
+ /* Reset UART */
+ CHECKPOINT;
+ Mcr = 0; /* MCR: DTR/RTS/OUT2 off */
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_MODEM_CONTROL,
+ &Mcr, sizeof(Mcr), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Set communications parameters */
+ CHECKPOINT;
+ /* DLAB off */
+ Fcr = 0;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_FIFO_CONTROL,
+ &Fcr, sizeof(Fcr), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ /* Set serial port speed */
+ BaudRate = SERIAL_BAUD_1200;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_BAUD_RATE,
+ &BaudRate, sizeof(BaudRate), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ /* Set LCR */
+ LCR.WordLength = 7;
+ LCR.Parity = NO_PARITY;
+ LCR.StopBits = STOP_BITS_2;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_LINE_CONTROL,
+ &LCR, sizeof(LCR), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Flush receive buffer */
+ CHECKPOINT;
+ Command = SERIAL_PURGE_RXCLEAR;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_MODEM_CONTROL,
+ &Command, sizeof(Command), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ /* Wait 100 ms */
+ SerenumWait(100);
+
+ /* Enable DTR/RTS */
+ CHECKPOINT;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_DTR,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_RTS,
+ NULL, 0, NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Set timeout to 500 microseconds */
+ CHECKPOINT;
+ Timeouts.ReadIntervalTimeout = 100;
+ Timeouts.ReadTotalTimeoutMultiplier = 0;
+ Timeouts.ReadTotalTimeoutConstant = 500;
+ Timeouts.WriteTotalTimeoutMultiplier =
Timeouts.WriteTotalTimeoutConstant = 0;
+ Status = SerenumDeviceIoControl(LowerDevice,
IOCTL_SERIAL_SET_TIMEOUTS,
+ &Timeouts, sizeof(Timeouts), NULL, NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Fill the read buffer */
+ CHECKPOINT;
+ Status = ReadBytes(LowerDevice, Buffer,
sizeof(Buffer)/sizeof(Buffer[0]), &Count);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ for (i = 0; i < Count; i++)
+ {
+ if (Buffer[i] == 'B')
+ {
+ /* Sign for Microsoft Ballpoint */
+ /* Hardware id: *PNP0F09
+ * Compatible id: *PNP0F0F, SERIAL_MOUSE
+ */
+ RtlInitUnicodeString(&DeviceDescription,
L"Microsoft Ballpoint device");
+ RtlInitUnicodeString(&DeviceId, L"*PNP0F09");
+ SerenumInitMultiSzString(&HardwareIds,
"*PNP0F09", NULL);
+ SerenumInitMultiSzString(&CompatibleIds,
"*PNP0F0F", "SERIAL_MOUSE", NULL);
+ Status = ReportDetectedDevice(DeviceObject,
+ &DeviceDescription, &DeviceId,
&HardwareIds, &CompatibleIds);
+ RtlFreeUnicodeString(&HardwareIds);
+ RtlFreeUnicodeString(&CompatibleIds);
+ return Status;
+ }
+ else if (Buffer[i] == 'M')
+ {
+ /* Sign for Microsoft Mouse protocol followed by
button specifier */
+ if (i == sizeof(Buffer) - 1)
+ {
+ /* Overflow Error */
+ return STATUS_DEVICE_NOT_CONNECTED;
+ }
+ switch (Buffer[i + 1])
+ {
+ case '3':
+ /* Hardware id: *PNP0F08
+ * Compatible id: SERIAL_MOUSE
+ */
+
RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with
3-buttons");
+ RtlInitUnicodeString(&DeviceId,
L"*PNP0F08");
+
SerenumInitMultiSzString(&HardwareIds, "*PNP0F08", NULL);
+
SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL);
+ default:
+ /* Hardware id: *PNP0F01
+ * Compatible id: SERIAL_MOUSE
+ */
+
RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with
2-buttons or Microsoft Wheel Mouse");
+ RtlInitUnicodeString(&DeviceId,
L"*PNP0F01");
+
SerenumInitMultiSzString(&HardwareIds, "*PNP0F01", NULL);
+
SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL);
+ }
+ Status = ReportDetectedDevice(DeviceObject,
+ &DeviceDescription, &DeviceId,
&HardwareIds, &CompatibleIds);
+ RtlFreeUnicodeString(&HardwareIds);
+ RtlFreeUnicodeString(&CompatibleIds);
+ return Status;
+ }
+ }
+
+ return STATUS_DEVICE_NOT_CONNECTED;
+}
Property changes on: trunk/reactos/drivers/bus/serenum/detect.c
___________________________________________________________________
Name: svn:keywords
+ author date id revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/drivers/bus/serenum/fdo.c
--- trunk/reactos/drivers/bus/serenum/fdo.c 2005-04-05 18:59:56 UTC
(rev 14511)
+++ trunk/reactos/drivers/bus/serenum/fdo.c 2005-04-05 19:04:07 UTC
(rev 14512)
@@ -0,0 +1,213 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Serial enumerator driver
+ * FILE: drivers/bus/serenum/fdo.c
+ * PURPOSE: IRP_MJ_PNP operations for FDOs
+ *
+ * PROGRAMMERS: HervÚ Poussineau (hpoussin(a)reactos.com)
+ */
+
+#define NDEBUG
+#include "serenum.h"
+
+NTSTATUS STDCALL
+SerenumAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT Pdo)
+{
+ PDEVICE_OBJECT Fdo;
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+ //UNICODE_STRING SymbolicLinkName;
+ NTSTATUS Status;
+
+ DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo);
+
+ /* Create new device object */
+ Status = IoCreateDevice(DriverObject,
+ sizeof(FDO_DEVICE_EXTENSION),
+ NULL,
+ FILE_DEVICE_BUS_EXTENDER,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &Fdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Serenum: IoCreateDevice() failed with status
0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Register device interface */
+#if 0 /* FIXME: activate */
+ Status = IoRegisterDeviceInterface(Pdo,
&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, NULL, &SymbolicLinkName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Serenum: IoRegisterDeviceInterface() failed with
status 0x%08lx\n", Status);
+ goto ByeBye;
+ }
+ DPRINT1("Serenum: IoRegisterDeviceInterface() returned '%wZ'\n",
&SymbolicLinkName);
+ Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Serenum: IoSetDeviceInterfaceState() failed with
status 0x%08lx\n", Status);
+ goto ByeBye;
+ }
+ RtlFreeUnicodeString(&SymbolicLinkName);
+#endif
+
+ DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
+ DeviceExtension->Common.IsFDO = TRUE;
+ DeviceExtension->Common.PnpState = dsStopped;
+ DeviceExtension->Pdo = Pdo;
+ IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
SERENUM_TAG, 0, 0);
+ Fdo->Flags |= DO_POWER_PAGABLE;
+ Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo,
&DeviceExtension->LowerDevice);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Serenum: 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;
+}
+
+NTSTATUS STDCALL
+SerenumFdoStartDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PCOMMON_DEVICE_EXTENSION DeviceExtension;
+
+ DPRINT("Serenum: SerenumFdoStartDevice() called\n");
+ DeviceExtension =
(PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ ASSERT(DeviceExtension->PnpState == dsStopped);
+ DeviceExtension->PnpState = dsStarted;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+SerenumFdoQueryBusRelations(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PDEVICE_RELATIONS* pDeviceRelations)
+{
+ PFDO_DEVICE_EXTENSION DeviceExtension;
+ PDEVICE_RELATIONS DeviceRelations;
+ ULONG NumPDO;
+ ULONG i;
+ NTSTATUS Status;
+
+ DeviceExtension =
(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(DeviceExtension->Common.IsFDO);
+
+ /* Do enumeration if needed */
+ if (!(DeviceExtension->Flags & FLAG_ENUMERATION_DONE))
+ {
+ ASSERT(DeviceExtension->AttachedPdo == NULL);
+ /* Detect plug-and-play devices */
+ Status = SerenumDetectPnpDevice(DeviceObject,
DeviceExtension->LowerDevice);
+ if (Status == STATUS_DEVICE_NOT_CONNECTED)
+ {
+ /* Detect legacy devices */
+ Status = SerenumDetectLegacyDevice(DeviceObject,
DeviceExtension->LowerDevice);
+ if (Status == STATUS_DEVICE_NOT_CONNECTED)
+ Status = STATUS_SUCCESS;
+ }
+ DeviceExtension->Flags |= FLAG_ENUMERATION_DONE;
+ }
+ NumPDO = (DeviceExtension->AttachedPdo != NULL ? 1 : 0);
+
+ DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) *
(NumPDO - 1),
+ SERENUM_TAG);
+ if (!DeviceRelations)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Fill returned structure */
+ DeviceRelations->Count = NumPDO;
+ for (i = 0; i < NumPDO; i++)
+ {
+ ObReferenceObject(DeviceExtension->AttachedPdo);
+ DeviceRelations->Objects[i] =
DeviceExtension->AttachedPdo;
+ }
+
+ *pDeviceRelations = DeviceRelations;
+ return Status;
+}
+
+NTSTATUS
+SerenumFdoPnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ ULONG MinorFunction;
+ PIO_STACK_LOCATION Stack;
+ ULONG_PTR Information = 0;
+ NTSTATUS Status;
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ MinorFunction = Stack->MinorFunction;
+
+ switch (MinorFunction)
+ {
+ /* FIXME: do all these minor functions
+ IRP_MN_QUERY_REMOVE_DEVICE 0x1
+ IRP_MN_REMOVE_DEVICE 0x2
+ IRP_MN_CANCEL_REMOVE_DEVICE 0x3
+ IRP_MN_STOP_DEVICE 0x4
+ IRP_MN_QUERY_STOP_DEVICE 0x5
+ IRP_MN_CANCEL_STOP_DEVICE 0x6
+ IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations
(optional) 0x7
+ IRP_MN_QUERY_INTERFACE (optional) 0x8
+ IRP_MN_QUERY_CAPABILITIES (optional) 0x9
+ IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or
required) 0xb
+ IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
+ IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional)
0x16
+ IRP_MN_SURPRISE_REMOVAL 0x17
+ */
+ case IRP_MN_START_DEVICE: /* 0x0 */
+ {
+ DPRINT("Serenum: IRP_MJ_PNP /
IRP_MN_START_DEVICE\n");
+ /* Call lower driver */
+ Status = ForwardIrpAndWait(DeviceObject, Irp);
+ if (NT_SUCCESS(Status))
+ Status =
SerenumFdoStartDevice(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
+ {
+ switch
(Stack->Parameters.QueryDeviceRelations.Type)
+ {
+ case BusRelations:
+ {
+ PDEVICE_RELATIONS
DeviceRelations;
+ DPRINT("Serenum: IRP_MJ_PNP /
IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
+ Status =
SerenumFdoQueryBusRelations(DeviceObject, &DeviceRelations);
+ Information =
(ULONG_PTR)DeviceRelations;
+ break;
+ }
+ default:
+ DPRINT1("Serenum: IRP_MJ_PNP /
IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+
Stack->Parameters.QueryDeviceRelations.Type);
+ return
ForwardIrpAndForget(DeviceObject, Irp);
+ }
+ break;
+ }
+ default:
+ {
+ DPRINT1("Serenum: IRP_MJ_PNP / unknown minor
function 0x%lx\n", MinorFunction);
+ return ForwardIrpAndForget(DeviceObject, Irp);
+ }
+ }
+
+ Irp->IoStatus.Information = Information;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
Property changes on: trunk/reactos/drivers/bus/serenum/fdo.c
___________________________________________________________________
Name: svn:keywords
+ author date id revision
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/drivers/bus/serenum/makefile
--- trunk/reactos/drivers/bus/serenum/makefile 2005-04-05 18:59:56 UTC
(rev 14511)
+++ trunk/reactos/drivers/bus/serenum/makefile 2005-04-05 19:04:07 UTC
(rev 14512)
@@ -0,0 +1,20 @@
+# $Id: makefile 12852 2005-01-06 13:58:04Z mf $
+
+PATH_TO_TOP = ../../..
+
+TARGET_TYPE = driver
+
+TARGET_NAME = serenum
+
+TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
+
+TARGET_OBJECTS = \
+ detect.o \
+ fdo.o \
+ misc.o \
+ pdo.o \
+ serenum.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
Property changes on: trunk/reactos/drivers/bus/serenum/makefile
___________________________________________________________________
Name: svn:eol-style
+ native
_____
Added: trunk/reactos/drivers/bus/serenum/misc.c
--- trunk/reactos/drivers/bus/serenum/misc.c 2005-04-05 18:59:56 UTC
(rev 14511)
+++ trunk/reactos/drivers/bus/serenum/misc.c 2005-04-05 19:04:07 UTC
(rev 14512)
@@ -0,0 +1,201 @@
+/* $Id:
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Serial enumerator driver
+ * FILE: drivers/dd/serenum/misc.c
+ * PURPOSE: Misceallenous operations
+ *
+ * PROGRAMMERS: HervÚ Poussineau (hpoussin(a)reactos.com)
+ */
+
+#define NDEBUG
+#include "serenum.h"
+#include <stdarg.h>
+
+NTSTATUS
+SerenumDuplicateUnicodeString(
+ OUT PUNICODE_STRING Destination,
+ IN PUNICODE_STRING Source,
+ IN POOL_TYPE PoolType)
+{
+ if (Source == NULL)
+ {
+ RtlInitUnicodeString(Destination, NULL);
+ return STATUS_SUCCESS;
+ }
+
+ Destination->Buffer = ExAllocatePool(PoolType,
Source->MaximumLength);
+ if (Destination->Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Destination->MaximumLength = Source->MaximumLength;
+ Destination->Length = Source->Length;
+ RtlCopyMemory(Destination->Buffer, Source->Buffer,
Source->MaximumLength);
+
+ return STATUS_SUCCESS;
+}
+
+/* I really want ANSI strings as last arguments because
+ * PnP ids are ANSI-encoded in PnP device string
+ * identification */
+NTSTATUS
+SerenumInitMultiSzString(
+ OUT PUNICODE_STRING Destination,
+ ... /* list of PCSZ */)
+{
+ va_list args;
+ PCSZ Source;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING UnicodeString;
+ ULONG DestinationSize = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Calculate length needed for destination unicode string */
+ va_start(args, Destination);
+ Source = va_arg(args, PCSZ);
+ while (Source != NULL)
+ {
+ RtlInitAnsiString(&AnsiString, Source);
+ DestinationSize +=
RtlAnsiStringToUnicodeSize(&AnsiString)
+ + sizeof(WCHAR) /* final NULL */;
+ Source = va_arg(args, PCSZ);
+ }
+ va_end(args);
+ if (DestinationSize == 0)
+ {
+ RtlInitUnicodeString(Destination, NULL);
+ return STATUS_SUCCESS;
+ }
+
+ /* Initialize destination string */
+ DestinationSize += sizeof(WCHAR); // final NULL
+ Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool,
DestinationSize, SERENUM_TAG);
+ if (!Destination->Buffer)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ Destination->Length = 0;
+ Destination->MaximumLength = (USHORT)DestinationSize;
+
+ /* Copy arguments to destination string */
+ /* Use a temporary unicode string, which buffer is shared with
+ * destination string, to copy arguments */
+ UnicodeString.Length = Destination->Length;
+ UnicodeString.MaximumLength = Destination->MaximumLength;
+ UnicodeString.Buffer = Destination->Buffer;
+ va_start(args, Destination);
+ Source = va_arg(args, PCSZ);
+ while (Source != NULL)
+ {
+ RtlInitAnsiString(&AnsiString, Source);
+ Status = RtlAnsiStringToUnicodeString(&UnicodeString,
&AnsiString, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(Destination->Buffer,
SERENUM_TAG);
+ break;
+ }
+ Destination->Length += UnicodeString.Length +
sizeof(WCHAR);
+ UnicodeString.MaximumLength -= UnicodeString.Length +
sizeof(WCHAR);
+ UnicodeString.Buffer += UnicodeString.Length /
sizeof(WCHAR) + 1;
+ UnicodeString.Length = 0;
+ Source = va_arg(args, PCSZ);
+ }
+ va_end(args);
+ if (NT_SUCCESS(Status))
+ {
+ /* Finish multi-sz string */
+ Destination->Buffer[Destination->Length / sizeof(WCHAR)]
= L'\0';
+ Destination->Length += sizeof(WCHAR);
+ }
+ return Status;
+}
+
+NTSTATUS STDCALL
+ForwardIrpAndWaitCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ if (Irp->PendingReturned)
+ KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+ForwardIrpAndWait(
+ IN PDEVICE_OBJECT DeviceObject,
[truncated at 1000 lines; 711 more skipped]