2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial mouse driver
4 * FILE: drivers/input/sermouse/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
17 IN PDRIVER_OBJECT DriverObject
,
18 IN PDEVICE_OBJECT Pdo
)
20 PSERMOUSE_DRIVER_EXTENSION DriverExtension
;
23 UNICODE_STRING DeviceNameU
;
24 PWSTR DeviceIdW
= NULL
; /* Pointer into DeviceNameU.Buffer */
26 PSERMOUSE_DEVICE_EXTENSION DeviceExtension
;
29 DPRINT("SermouseAddDevice called. Pdo = 0x%p\n", Pdo
);
31 /* Create new device object */
32 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
33 DeviceNameU
.Length
= 0;
34 DeviceNameU
.MaximumLength
=
35 wcslen(L
"\\Device\\") * sizeof(WCHAR
) /* "\Device\" */
36 + DriverExtension
->PointerDeviceBaseName
.Length
/* "PointerPort" */
37 + 4 * sizeof(WCHAR
) /* Id between 0 and 9999 */
38 + sizeof(UNICODE_NULL
); /* Final NULL char */
39 DeviceNameU
.Buffer
= ExAllocatePool(PagedPool
, DeviceNameU
.MaximumLength
);
40 if (!DeviceNameU
.Buffer
)
42 DPRINT("ExAllocatePool() failed\n");
43 return STATUS_INSUFFICIENT_RESOURCES
;
45 Status
= RtlAppendUnicodeToString(&DeviceNameU
, L
"\\Device\\");
46 if (!NT_SUCCESS(Status
))
48 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status
);
51 Status
= RtlAppendUnicodeStringToString(&DeviceNameU
, &DriverExtension
->PointerDeviceBaseName
);
52 if (!NT_SUCCESS(Status
))
54 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status
);
57 PrefixLength
= DeviceNameU
.MaximumLength
- 4 * sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
58 DeviceIdW
= &DeviceNameU
.Buffer
[PrefixLength
/ sizeof(WCHAR
)];
59 while (DeviceId
< 9999)
61 DeviceNameU
.Length
= PrefixLength
+ swprintf(DeviceIdW
, L
"%lu", DeviceId
) * sizeof(WCHAR
);
62 Status
= IoCreateDevice(
64 sizeof(SERMOUSE_DEVICE_EXTENSION
),
66 FILE_DEVICE_SERIAL_MOUSE_PORT
,
67 FILE_DEVICE_SECURE_OPEN
,
70 if (NT_SUCCESS(Status
))
72 else if (Status
!= STATUS_OBJECT_NAME_COLLISION
)
74 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
79 DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension
->PointerDeviceBaseName
);
80 Status
= STATUS_UNSUCCESSFUL
;
82 if (!NT_SUCCESS(Status
))
84 ExFreePool(DeviceNameU
.Buffer
);
88 DeviceExtension
= (PSERMOUSE_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
89 RtlZeroMemory(DeviceExtension
, sizeof(SERMOUSE_DEVICE_EXTENSION
));
90 DeviceExtension
->MouseType
= mtNone
;
91 DeviceExtension
->PnpState
= dsStopped
;
92 DeviceExtension
->DriverExtension
= DriverExtension
;
93 KeInitializeEvent(&DeviceExtension
->StopWorkerThreadEvent
, NotificationEvent
, FALSE
);
94 DeviceExtension
->MouseInputData
[0] = ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->MouseDataQueueSize
* sizeof(MOUSE_INPUT_DATA
));
95 if (!DeviceExtension
->MouseInputData
[0])
97 DPRINT("ExAllocatePool() failed\n");
98 Status
= STATUS_INSUFFICIENT_RESOURCES
;
101 DeviceExtension
->MouseInputData
[1] = ExAllocatePool(NonPagedPool
, DeviceExtension
->DriverExtension
->MouseDataQueueSize
* sizeof(MOUSE_INPUT_DATA
));
102 if (!DeviceExtension
->MouseInputData
[1])
104 DPRINT("ExAllocatePool() failed\n");
105 Status
= STATUS_INSUFFICIENT_RESOURCES
;
108 Fdo
->Flags
|= DO_POWER_PAGABLE
;
109 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
110 if (!NT_SUCCESS(Status
))
112 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
115 Fdo
->Flags
|= DO_BUFFERED_IO
;
116 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
118 /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
120 ExFreePool(DeviceNameU
.Buffer
);
122 return STATUS_SUCCESS
;
127 ExFreePool(DeviceExtension
->MouseInputData
[0]);
128 ExFreePool(DeviceExtension
->MouseInputData
[1]);
139 IN PDEVICE_OBJECT DeviceObject
,
142 PSERMOUSE_DEVICE_EXTENSION DeviceExtension
;
143 SERMOUSE_MOUSE_TYPE MouseType
;
145 DeviceExtension
= (PSERMOUSE_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
147 ASSERT(DeviceExtension
->PnpState
== dsStopped
);
148 ASSERT(DeviceExtension
->LowerDevice
);
149 MouseType
= SermouseDetectLegacyDevice(DeviceExtension
->LowerDevice
);
150 if (MouseType
== mtNone
)
152 DPRINT("No mouse connected to Fdo %p\n",
153 DeviceExtension
->LowerDevice
);
154 return STATUS_DEVICE_NOT_CONNECTED
;
160 DeviceExtension
->AttributesInformation
.MouseIdentifier
= MOUSE_SERIAL_HARDWARE
;
161 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 2;
164 DeviceExtension
->AttributesInformation
.MouseIdentifier
= MOUSE_SERIAL_HARDWARE
;
165 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 3;
168 DeviceExtension
->AttributesInformation
.MouseIdentifier
= WHEELMOUSE_SERIAL_HARDWARE
;
169 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 3;
173 return STATUS_UNSUCCESSFUL
;
176 if (DeviceExtension
->DriverExtension
->NumberOfButtons
!= 0)
177 /* Override the number of buttons */
178 DeviceExtension
->AttributesInformation
.NumberOfButtons
= DeviceExtension
->DriverExtension
->NumberOfButtons
;
180 DeviceExtension
->AttributesInformation
.SampleRate
= 1200 / 8;
181 DeviceExtension
->AttributesInformation
.InputDataQueueLength
= DeviceExtension
->DriverExtension
->MouseDataQueueSize
;
182 DeviceExtension
->MouseType
= MouseType
;
183 DeviceExtension
->PnpState
= dsStarted
;
185 return STATUS_SUCCESS
;
190 IN PDEVICE_OBJECT DeviceObject
,
194 PIO_STACK_LOCATION Stack
;
195 ULONG Information
= 0;
198 Stack
= IoGetCurrentIrpStackLocation(Irp
);
199 MinorFunction
= Stack
->MinorFunction
;
201 switch (MinorFunction
)
203 /* FIXME: do all these minor functions
204 IRP_MN_QUERY_REMOVE_DEVICE 0x1
205 IRP_MN_REMOVE_DEVICE 0x2
206 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
207 IRP_MN_STOP_DEVICE 0x4
208 IRP_MN_QUERY_STOP_DEVICE 0x5
209 IRP_MN_CANCEL_STOP_DEVICE 0x6
210 IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) 0x7
211 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
212 IRP_MN_QUERY_INTERFACE (optional) 0x8
213 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
214 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xd
215 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
216 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
217 IRP_MN_SURPRISE_REMOVAL 0x17
219 case IRP_MN_START_DEVICE
: /* 0x0 */
221 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
222 /* Call lower driver */
223 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
224 if (NT_SUCCESS(Status
))
225 Status
= SermouseStartDevice(DeviceObject
, Irp
);
230 DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
231 return ForwardIrpAndForget(DeviceObject
, Irp
);
235 Irp
->IoStatus
.Information
= Information
;
236 Irp
->IoStatus
.Status
= Status
;
237 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);