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