1 /*
2 * PROJECT: ReactOS InPort (Bus) Mouse Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Driver entrypoint
5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "inport.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 UNICODE_STRING DriverRegistryPath;
18
19 /* FUNCTIONS ******************************************************************/
20
21 CODE_SEG("PAGE")
22 NTSTATUS
23 NTAPI
InPortCreateClose(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)24 InPortCreateClose(
25 _In_ PDEVICE_OBJECT DeviceObject,
26 _Inout_ PIRP Irp)
27 {
28 PAGED_CODE();
29
30 DPRINT("%s(%p, %p) %X\n", __FUNCTION__, DeviceObject,
31 Irp, IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
32
33 Irp->IoStatus.Information = 0;
34 Irp->IoStatus.Status = STATUS_SUCCESS;
35 IoCompleteRequest(Irp, IO_NO_INCREMENT);
36
37 return STATUS_SUCCESS;
38 }
39
40 CODE_SEG("PAGE")
41 NTSTATUS
42 NTAPI
InPortAddDevice(_In_ PDRIVER_OBJECT DriverObject,_In_ PDEVICE_OBJECT PhysicalDeviceObject)43 InPortAddDevice(
44 _In_ PDRIVER_OBJECT DriverObject,
45 _In_ PDEVICE_OBJECT PhysicalDeviceObject)
46 {
47 NTSTATUS Status;
48 PDEVICE_OBJECT Fdo;
49 PINPORT_DEVICE_EXTENSION FdoExtension = NULL;
50 WCHAR HardwareIdBuffer[32];
51 UNICODE_STRING HardwareId;
52 ULONG DummyResultLength;
53 UNICODE_STRING HardwareId1 = RTL_CONSTANT_STRING(L"*nEC1F00");
54 UNICODE_STRING HardwareId2 = RTL_CONSTANT_STRING(L"*PNP0F00");
55 UNICODE_STRING HardwareId3 = RTL_CONSTANT_STRING(L"*PNP0F02");
56 UNICODE_STRING HardwareId4 = RTL_CONSTANT_STRING(L"*PNP0F0D");
57 UNICODE_STRING HardwareId5 = RTL_CONSTANT_STRING(L"*PNP0F11");
58 UNICODE_STRING HardwareId6 = RTL_CONSTANT_STRING(L"*PNP0F15");
59
60 PAGED_CODE();
61
62 DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject);
63
64 Status = IoCreateDevice(DriverObject,
65 sizeof(INPORT_DEVICE_EXTENSION),
66 NULL,
67 FILE_DEVICE_INPORT_PORT,
68 FILE_DEVICE_SECURE_OPEN,
69 FALSE,
70 &Fdo);
71 if (!NT_SUCCESS(Status))
72 {
73 DPRINT1("Failed to create FDO 0x%X\n", Status);
74 goto Failure;
75 }
76
77 FdoExtension = Fdo->DeviceExtension;
78
79 RtlZeroMemory(FdoExtension, sizeof(INPORT_DEVICE_EXTENSION));
80 FdoExtension->State = dsStopped;
81 FdoExtension->Self = Fdo;
82 FdoExtension->Pdo = PhysicalDeviceObject;
83 FdoExtension->Ldo = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
84 if (!FdoExtension->Ldo)
85 {
86 DPRINT1("Failed to attach FDO\n");
87 Status = STATUS_NO_SUCH_DEVICE;
88 goto Failure;
89 }
90
91 IoInitializeRemoveLock(&FdoExtension->RemoveLock, INPORT_TAG, 0, 0);
92 IoInitializeDpcRequest(Fdo, InPortDpcForIsr);
93
94 Status = IoGetDeviceProperty(PhysicalDeviceObject,
95 DevicePropertyHardwareID,
96 sizeof(HardwareIdBuffer),
97 HardwareIdBuffer,
98 &DummyResultLength);
99 if (!NT_SUCCESS(Status))
100 {
101 DPRINT1("Failed to query the hardware ID string 0x%X\n", Status);
102 goto Failure;
103 }
104 RtlInitUnicodeString(&HardwareId, HardwareIdBuffer);
105
106 if (RtlEqualUnicodeString(&HardwareId, &HardwareId1, FALSE))
107 {
108 FdoExtension->MouseType = NecBusMouse;
109 FdoExtension->MouseAttributes.SampleRate = 60;
110 FdoExtension->MouseAttributes.NumberOfButtons = 2;
111 }
112 else if (RtlEqualUnicodeString(&HardwareId, &HardwareId3, FALSE) ||
113 RtlEqualUnicodeString(&HardwareId, &HardwareId4, FALSE))
114 {
115 FdoExtension->MouseType = MsInPortMouse;
116 FdoExtension->MouseAttributes.SampleRate = 100;
117 FdoExtension->MouseAttributes.NumberOfButtons = 3;
118 }
119 else if (RtlEqualUnicodeString(&HardwareId, &HardwareId2, FALSE) ||
120 RtlEqualUnicodeString(&HardwareId, &HardwareId5, FALSE) ||
121 RtlEqualUnicodeString(&HardwareId, &HardwareId6, FALSE))
122 {
123 FdoExtension->MouseType = LogitechBusMouse;
124 FdoExtension->MouseAttributes.SampleRate = 100;
125 FdoExtension->MouseAttributes.NumberOfButtons = 3;
126 }
127 else
128 {
129 DPRINT1("Unrecognized hardware '%wZ'\n", &HardwareId);
130 Status = STATUS_DEVICE_REMOVED;
131 goto Failure;
132 }
133 FdoExtension->MouseAttributes.MouseIdentifier = MOUSE_INPORT_HARDWARE;
134 /* 1 packet */
135 FdoExtension->MouseAttributes.InputDataQueueLength = sizeof(MOUSE_INPUT_DATA);
136
137 Fdo->Flags |= DO_BUFFERED_IO;
138 if (FdoExtension->Ldo->Flags & DO_POWER_PAGABLE)
139 Fdo->Flags |= DO_POWER_PAGABLE;
140 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
141
142 return STATUS_SUCCESS;
143
144 Failure:
145 if (FdoExtension)
146 {
147 if (FdoExtension->Ldo)
148 IoDetachDevice(FdoExtension->Ldo);
149 }
150
151 if (Fdo)
152 {
153 IoDeleteDevice(Fdo);
154 }
155
156 return Status;
157 }
158
159 CODE_SEG("PAGE")
160 VOID
161 NTAPI
InPortUnload(_In_ PDRIVER_OBJECT DriverObject)162 InPortUnload(
163 _In_ PDRIVER_OBJECT DriverObject)
164 {
165 PAGED_CODE();
166
167 DPRINT("%s(%p)\n", __FUNCTION__, DriverObject);
168
169 RtlFreeUnicodeString(&DriverRegistryPath);
170 }
171
172 NTSTATUS
173 NTAPI
InPortPower(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)174 InPortPower(
175 _In_ PDEVICE_OBJECT DeviceObject,
176 _Inout_ PIRP Irp)
177 {
178 NTSTATUS Status;
179 PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
180
181 DPRINT("%s(%p, %p) %X\n", __FUNCTION__, DeviceObject, Irp,
182 IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
183
184 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
185 if (!NT_SUCCESS(Status))
186 {
187 Irp->IoStatus.Status = Status;
188 PoStartNextPowerIrp(Irp);
189 IoCompleteRequest(Irp, IO_NO_INCREMENT);
190
191 return Status;
192 }
193
194 PoStartNextPowerIrp(Irp);
195 IoSkipCurrentIrpStackLocation(Irp);
196 Status = PoCallDriver(DeviceExtension->Ldo, Irp);
197
198 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
199
200 return Status;
201 }
202
203 CODE_SEG("INIT")
204 NTSTATUS
205 NTAPI
DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath)206 DriverEntry(
207 _In_ PDRIVER_OBJECT DriverObject,
208 _In_ PUNICODE_STRING RegistryPath)
209 {
210 DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath);
211
212 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
213 RegistryPath->Length +
214 sizeof(UNICODE_NULL),
215 INPORT_TAG);
216 if (!DriverRegistryPath.Buffer)
217 {
218 DPRINT1("Failed to allocate the registry string buffer\n");
219 return STATUS_INSUFFICIENT_RESOURCES;
220 }
221 DriverRegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
222 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
223 DriverRegistryPath.Buffer[RegistryPath->Length / sizeof(WCHAR)] = UNICODE_NULL;
224
225 DriverObject->MajorFunction[IRP_MJ_CREATE] =
226 DriverObject->MajorFunction[IRP_MJ_CLOSE] = InPortCreateClose;
227 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = InPortInternalDeviceControl;
228 DriverObject->MajorFunction[IRP_MJ_POWER] = InPortPower;
229 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = InPortWmi;
230 DriverObject->MajorFunction[IRP_MJ_PNP] = InPortPnp;
231 DriverObject->DriverExtension->AddDevice = InPortAddDevice;
232 DriverObject->DriverUnload = InPortUnload;
233
234 return STATUS_SUCCESS;
235 }
236