xref: /reactos/drivers/input/inport/inport.c (revision 3adf4508)
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