Sync with trunk (r48414)
[reactos.git] / drivers / input / sermouse / fdo.c
1 /*
2 * PROJECT: ReactOS Serial mouse driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/input/sermouse/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
6 * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 #include "sermouse.h"
10
11 NTSTATUS NTAPI
12 SermouseAddDevice(
13 IN PDRIVER_OBJECT DriverObject,
14 IN PDEVICE_OBJECT Pdo)
15 {
16 PSERMOUSE_DRIVER_EXTENSION DriverExtension;
17 PDEVICE_OBJECT Fdo;
18 PSERMOUSE_DEVICE_EXTENSION DeviceExtension = NULL;
19 NTSTATUS Status;
20
21 TRACE_(SERMOUSE, "SermouseAddDevice called. Pdo = 0x%p\n", Pdo);
22
23 if (Pdo == NULL)
24 return STATUS_SUCCESS;
25
26 /* Create new device object */
27 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
28 Status = IoCreateDevice(
29 DriverObject,
30 sizeof(SERMOUSE_DEVICE_EXTENSION),
31 NULL,
32 FILE_DEVICE_SERIAL_MOUSE_PORT,
33 FILE_DEVICE_SECURE_OPEN,
34 TRUE,
35 &Fdo);
36 if (!NT_SUCCESS(Status))
37 {
38 WARN_(SERMOUSE, "IoCreateDevice() failed with status 0x%08lx\n", Status);
39 goto cleanup;
40 }
41
42 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)Fdo->DeviceExtension;
43 RtlZeroMemory(DeviceExtension, sizeof(SERMOUSE_DEVICE_EXTENSION));
44 DeviceExtension->MouseType = mtNone;
45 DeviceExtension->PnpState = dsStopped;
46 DeviceExtension->DriverExtension = DriverExtension;
47 KeInitializeEvent(&DeviceExtension->StopWorkerThreadEvent, NotificationEvent, FALSE);
48 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
49 if (!NT_SUCCESS(Status))
50 {
51 WARN_(SERMOUSE, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
52 goto cleanup;
53 }
54 if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE)
55 Fdo->Flags |= DO_POWER_PAGABLE;
56 if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
57 Fdo->Flags |= DO_BUFFERED_IO;
58 if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
59 Fdo->Flags |= DO_DIRECT_IO;
60 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
61
62 return STATUS_SUCCESS;
63
64 cleanup:
65 if (DeviceExtension)
66 {
67 if (DeviceExtension->LowerDevice)
68 IoDetachDevice(DeviceExtension->LowerDevice);
69 }
70 if (Fdo)
71 {
72 IoDeleteDevice(Fdo);
73 }
74 return Status;
75 }
76
77 NTSTATUS NTAPI
78 SermouseStartDevice(
79 IN PDEVICE_OBJECT DeviceObject,
80 IN PIRP Irp)
81 {
82 PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
83 SERMOUSE_MOUSE_TYPE MouseType;
84 NTSTATUS Status;
85
86 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
87
88 ASSERT(DeviceExtension->PnpState == dsStopped);
89 ASSERT(DeviceExtension->LowerDevice);
90 MouseType = SermouseDetectLegacyDevice(DeviceExtension->LowerDevice);
91 if (MouseType == mtNone)
92 {
93 WARN_(SERMOUSE, "No mouse connected to Fdo %p\n",
94 DeviceExtension->LowerDevice);
95 return STATUS_DEVICE_NOT_CONNECTED;
96 }
97
98 switch (MouseType)
99 {
100 case mtMicrosoft:
101 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
102 DeviceExtension->AttributesInformation.NumberOfButtons = 2;
103 break;
104 case mtLogitech:
105 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
106 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
107 break;
108 case mtWheelZ:
109 DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE;
110 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
111 break;
112 default:
113 WARN_(SERMOUSE, "Unknown mouse type 0x%lx\n", MouseType);
114 ASSERT(FALSE);
115 return STATUS_UNSUCCESSFUL;
116 }
117
118 if (DeviceExtension->DriverExtension->NumberOfButtons != 0)
119 /* Override the number of buttons */
120 DeviceExtension->AttributesInformation.NumberOfButtons = DeviceExtension->DriverExtension->NumberOfButtons;
121
122 DeviceExtension->AttributesInformation.SampleRate = 1200 / 8;
123 DeviceExtension->AttributesInformation.InputDataQueueLength = 1;
124 DeviceExtension->MouseType = MouseType;
125 DeviceExtension->PnpState = dsStarted;
126
127 /* Start read loop */
128 Status = PsCreateSystemThread(
129 &DeviceExtension->WorkerThreadHandle,
130 (ACCESS_MASK)0L,
131 NULL,
132 NULL,
133 NULL,
134 SermouseDeviceWorker,
135 DeviceObject);
136
137 return Status;
138 }
139
140 NTSTATUS NTAPI
141 SermousePnp(
142 IN PDEVICE_OBJECT DeviceObject,
143 IN PIRP Irp)
144 {
145 ULONG MinorFunction;
146 PIO_STACK_LOCATION Stack;
147 ULONG_PTR Information = 0;
148 NTSTATUS Status;
149
150 Stack = IoGetCurrentIrpStackLocation(Irp);
151 MinorFunction = Stack->MinorFunction;
152 Information = Irp->IoStatus.Information;
153
154 switch (MinorFunction)
155 {
156 /* FIXME: do all these minor functions
157 IRP_MN_QUERY_REMOVE_DEVICE 0x1
158 IRP_MN_REMOVE_DEVICE 0x2
159 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
160 IRP_MN_STOP_DEVICE 0x4
161 IRP_MN_QUERY_STOP_DEVICE 0x5
162 IRP_MN_CANCEL_STOP_DEVICE 0x6
163 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
164 IRP_MN_QUERY_INTERFACE (optional) 0x8
165 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
166 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xd
167 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
168 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
169 IRP_MN_SURPRISE_REMOVAL 0x17
170 */
171 case IRP_MN_START_DEVICE: /* 0x0 */
172 {
173 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
174 /* Call lower driver */
175 Status = ForwardIrpAndWait(DeviceObject, Irp);
176 if (NT_SUCCESS(Status))
177 Status = SermouseStartDevice(DeviceObject, Irp);
178 break;
179 }
180 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
181 {
182 switch (Stack->Parameters.QueryDeviceRelations.Type)
183 {
184 case BusRelations:
185 {
186 PDEVICE_RELATIONS DeviceRelations = NULL;
187 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
188
189 DeviceRelations = ExAllocatePoolWithTag(PagedPool, FIELD_OFFSET(DEVICE_RELATIONS, Objects), SERMOUSE_TAG);
190 if (!DeviceRelations)
191 {
192 WARN_(SERMOUSE, "ExAllocatePoolWithTag() failed\n");
193 Status = STATUS_NO_MEMORY;
194 }
195 else
196 {
197 DeviceRelations->Count = 0;
198 Status = STATUS_SUCCESS;
199 Information = (ULONG_PTR)DeviceRelations;
200 }
201 break;
202 }
203 default:
204 {
205 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
206 Stack->Parameters.QueryDeviceRelations.Type);
207 return ForwardIrpAndForget(DeviceObject, Irp);
208 }
209 }
210 break;
211 }
212 default:
213 {
214 TRACE_(SERMOUSE, "IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
215 return ForwardIrpAndForget(DeviceObject, Irp);
216 }
217 }
218
219 Irp->IoStatus.Information = Information;
220 Irp->IoStatus.Status = Status;
221 IoCompleteRequest(Irp, IO_NO_INCREMENT);
222 return Status;
223 }