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