fixed difference in signedness warning
[reactos.git] / reactos / drivers / input / sermouse / fdo.c
1 /*
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
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #include "sermouse.h"
14
15 NTSTATUS NTAPI
16 SermouseAddDevice(
17 IN PDRIVER_OBJECT DriverObject,
18 IN PDEVICE_OBJECT Pdo)
19 {
20 PSERMOUSE_DRIVER_EXTENSION DriverExtension;
21 ULONG DeviceId = 0;
22 ULONG PrefixLength;
23 UNICODE_STRING DeviceNameU;
24 PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
25 PDEVICE_OBJECT Fdo;
26 PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
27 NTSTATUS Status;
28
29 DPRINT("SermouseAddDevice called. Pdo = 0x%p\n", Pdo);
30
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)
41 {
42 DPRINT("ExAllocatePool() failed\n");
43 return STATUS_INSUFFICIENT_RESOURCES;
44 }
45 Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
46 if (!NT_SUCCESS(Status))
47 {
48 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
49 goto cleanup;
50 }
51 Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->PointerDeviceBaseName);
52 if (!NT_SUCCESS(Status))
53 {
54 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
55 goto cleanup;
56 }
57 PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
58 DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
59 while (DeviceId < 9999)
60 {
61 DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR);
62 Status = IoCreateDevice(
63 DriverObject,
64 sizeof(SERMOUSE_DEVICE_EXTENSION),
65 &DeviceNameU,
66 FILE_DEVICE_SERIAL_MOUSE_PORT,
67 FILE_DEVICE_SECURE_OPEN,
68 TRUE,
69 &Fdo);
70 if (NT_SUCCESS(Status))
71 goto cleanup;
72 else if (Status != STATUS_OBJECT_NAME_COLLISION)
73 {
74 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
75 goto cleanup;
76 }
77 DeviceId++;
78 }
79 DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->PointerDeviceBaseName);
80 Status = STATUS_UNSUCCESSFUL;
81 cleanup:
82 if (!NT_SUCCESS(Status))
83 {
84 ExFreePool(DeviceNameU.Buffer);
85 return Status;
86 }
87
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])
96 {
97 DPRINT("ExAllocatePool() failed\n");
98 Status = STATUS_INSUFFICIENT_RESOURCES;
99 goto cleanupFDO;
100 }
101 DeviceExtension->MouseInputData[1] = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
102 if (!DeviceExtension->MouseInputData[1])
103 {
104 DPRINT("ExAllocatePool() failed\n");
105 Status = STATUS_INSUFFICIENT_RESOURCES;
106 goto cleanupFDO;
107 }
108 Fdo->Flags |= DO_POWER_PAGABLE;
109 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
110 if (!NT_SUCCESS(Status))
111 {
112 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
113 goto cleanupFDO;
114 }
115 Fdo->Flags |= DO_BUFFERED_IO;
116 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
117
118 /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
119
120 ExFreePool(DeviceNameU.Buffer);
121
122 return STATUS_SUCCESS;
123
124 cleanupFDO:
125 if (DeviceExtension)
126 {
127 ExFreePool(DeviceExtension->MouseInputData[0]);
128 ExFreePool(DeviceExtension->MouseInputData[1]);
129 }
130 if (Fdo)
131 {
132 IoDeleteDevice(Fdo);
133 }
134 return Status;
135 }
136
137 NTSTATUS NTAPI
138 SermouseStartDevice(
139 IN PDEVICE_OBJECT DeviceObject,
140 IN PIRP Irp)
141 {
142 PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
143 SERMOUSE_MOUSE_TYPE MouseType;
144
145 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
146
147 ASSERT(DeviceExtension->PnpState == dsStopped);
148 ASSERT(DeviceExtension->LowerDevice);
149 MouseType = SermouseDetectLegacyDevice(DeviceExtension->LowerDevice);
150 if (MouseType == mtNone)
151 {
152 DPRINT("No mouse connected to Fdo %p\n",
153 DeviceExtension->LowerDevice);
154 return STATUS_DEVICE_NOT_CONNECTED;
155 }
156
157 switch (MouseType)
158 {
159 case mtMicrosoft:
160 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
161 DeviceExtension->AttributesInformation.NumberOfButtons = 2;
162 break;
163 case mtLogitech:
164 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
165 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
166 break;
167 case mtWheelZ:
168 DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE;
169 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
170 break;
171 default:
172 CHECKPOINT;
173 return STATUS_UNSUCCESSFUL;
174 }
175
176 if (DeviceExtension->DriverExtension->NumberOfButtons != 0)
177 /* Override the number of buttons */
178 DeviceExtension->AttributesInformation.NumberOfButtons = DeviceExtension->DriverExtension->NumberOfButtons;
179
180 DeviceExtension->AttributesInformation.SampleRate = 1200 / 8;
181 DeviceExtension->AttributesInformation.InputDataQueueLength = DeviceExtension->DriverExtension->MouseDataQueueSize;
182 DeviceExtension->MouseType = MouseType;
183 DeviceExtension->PnpState = dsStarted;
184
185 return STATUS_SUCCESS;
186 }
187
188 NTSTATUS NTAPI
189 SermousePnp(
190 IN PDEVICE_OBJECT DeviceObject,
191 IN PIRP Irp)
192 {
193 ULONG MinorFunction;
194 PIO_STACK_LOCATION Stack;
195 ULONG Information = 0;
196 NTSTATUS Status;
197
198 Stack = IoGetCurrentIrpStackLocation(Irp);
199 MinorFunction = Stack->MinorFunction;
200
201 switch (MinorFunction)
202 {
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
218 */
219 case IRP_MN_START_DEVICE: /* 0x0 */
220 {
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);
226 break;
227 }
228 default:
229 {
230 DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
231 return ForwardIrpAndForget(DeviceObject, Irp);
232 }
233 }
234
235 Irp->IoStatus.Information = Information;
236 Irp->IoStatus.Status = Status;
237 IoCompleteRequest(Irp, IO_NO_INCREMENT);
238 return Status;
239 }