ReactOS 0.4.15-dev-6056-gb29b268
hardware.c
Go to the documentation of this file.
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: Hardware support code
5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
6 */
7
8/* Note: Some code was taken from Linux */
9
10/* INCLUDES *******************************************************************/
11
12#include "inport.h"
13
14#define NDEBUG
15#include <debug.h>
16
17/* GLOBALS ********************************************************************/
18
19#define READ_MOUSE(DeviceExtension, Port) \
20 READ_PORT_UCHAR((DeviceExtension)->IoBase + (Port))
21
22#define WRITE_MOUSE(DeviceExtension, Port, Data) \
23 WRITE_PORT_UCHAR((DeviceExtension)->IoBase + (Port), (Data))
24
25/*
26 * NEC
27 */
28#define NEC_BM_DATA 0x00
29
30#define NEC_BM_CONTROL 0x04
31 #define NEC_INT_ENABLE 0x00
32 #define NEC_INT_DISABLE 0x10
33
34 #define NEC_READ_X_LOW 0x00
35 #define NEC_READ_X_HIGH 0x20
36 #define NEC_READ_Y_LOW 0x40
37 #define NEC_READ_Y_HIGH 0x60
38
39 #define NEC_INPUT_CAPTURE 0x00
40 #define NEC_INPUT_HOLD 0x80
41
42#define NEC_BM_CONFIG 0x06
43 #define NEC_PPI_INT_ENABLE 0x08
44 #define NEC_PPI_INT_DISABLE 0x09
45 #define NEC_PPI_HC_NO_CLEAR 0x0E
46 #define NEC_PPI_HC_CLEAR 0x0F
47 #define NEC_PPI_DEFAULT_MODE 0x93
48
49#define NEC_BM_INT_RATE 0x4002
50 #define NEC_RATE_120_HZ 0x00
51 #define NEC_RATE_60_HZ 0x01
52 #define NEC_RATE_30_HZ 0x02
53 #define NEC_RATE_15_HZ 0x03
54
55#define NEC_BM_HIRESO_BASE (PUCHAR)0x61
56
57#define NEC_BUTTON_RIGHT 0x20
58#define NEC_BUTTON_LEFT 0x80
59
60/*
61 * Microsoft InPort
62 */
63#define MS_INPORT_CONTROL 0x00
64 #define INPORT_REG_BTNS 0x00
65 #define INPORT_REG_X 0x01
66 #define INPORT_REG_Y 0x02
67 #define INPORT_REG_MODE 0x07
68 #define INPORT_RESET 0x80
69
70#define MS_INPORT_DATA 0x01
71 #define INPORT_MODE_IRQ 0x01
72 #define INPORT_MODE_BASE 0x10
73 #define INPORT_MODE_HOLD 0x20
74
75#define MS_INPORT_SIGNATURE 0x02
76
77#define MS_BUTTON_MIDDLE 0x01
78#define MS_BUTTON_LEFT 0x02
79#define MS_BUTTON_RIGHT 0x04
80
81/*
82 * Logitech
83 */
84#define LOG_BM_DATA 0x00
85
86#define LOG_BM_SIGNATURE 0x01
87 #define LOG_SIGNATURE_BYTE 0xA5
88
89#define LOG_BM_CONTROL 0x02
90 #define LOG_ENABLE_IRQ 0x00
91 #define LOG_DISABLE_IRQ 0x10
92
93 #define LOG_READ_X_LOW 0x80
94 #define LOG_READ_X_HIGH 0xA0
95 #define LOG_READ_Y_LOW 0xC0
96 #define LOG_READ_Y_HIGH 0xE0
97
98#define LOG_BM_CONFIG 0x03
99 #define LOG_DEFAULT_MODE 0x90
100 #define LOG_CONFIG_BYTE 0x91
101
102#define LOG_BUTTON_RIGHT 0x20
103#define LOG_BUTTON_MIDDLE 0x40
104#define LOG_BUTTON_LEFT 0x80
105
106/* FUNCTIONS ******************************************************************/
107
108VOID
109NTAPI
111 _In_ PKDPC Dpc,
115{
116 PINPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
118 ULONG DummyInputDataConsumed;
119 INPORT_RAW_DATA RawData;
120
124
125 /* Copy raw data */
127 RawData = DeviceExtension->RawData;
129
130 /* Fill out fields */
131 DeviceExtension->MouseInputData.LastX = RawData.DeltaX;
132 DeviceExtension->MouseInputData.LastY = RawData.DeltaY;
133 DeviceExtension->MouseInputData.ButtonFlags = 0;
134 if (RawData.ButtonDiff != 0)
135 {
136 switch (DeviceExtension->MouseType)
137 {
138 case NecBusMouse:
139 {
140 if (RawData.ButtonDiff & NEC_BUTTON_LEFT)
141 {
142 if (RawData.Buttons & NEC_BUTTON_LEFT)
144 else
146 }
147 if (RawData.ButtonDiff & NEC_BUTTON_RIGHT)
148 {
149 if (RawData.Buttons & NEC_BUTTON_RIGHT)
151 else
153 }
154
155 break;
156 }
157
158 case MsInPortMouse:
159 {
160 /* Button flags have to be inverted */
161 if (RawData.ButtonDiff & MS_BUTTON_LEFT)
162 {
163 if (RawData.Buttons & MS_BUTTON_LEFT)
165 else
167 }
168 if (RawData.ButtonDiff & MS_BUTTON_RIGHT)
169 {
170 if (RawData.Buttons & MS_BUTTON_RIGHT)
172 else
174 }
175 if (RawData.ButtonDiff & MS_BUTTON_MIDDLE)
176 {
177 if (RawData.Buttons & MS_BUTTON_MIDDLE)
179 else
181 }
182
183 break;
184 }
185
186 case LogitechBusMouse:
187 {
188 if (RawData.ButtonDiff & LOG_BUTTON_LEFT)
189 {
190 if (RawData.Buttons & LOG_BUTTON_LEFT)
192 else
194 }
195 if (RawData.ButtonDiff & LOG_BUTTON_RIGHT)
196 {
197 if (RawData.Buttons & LOG_BUTTON_RIGHT)
199 else
201 }
202 if (RawData.ButtonDiff & LOG_BUTTON_MIDDLE)
203 {
204 if (RawData.Buttons & LOG_BUTTON_MIDDLE)
206 else
208 }
209
210 break;
211 }
212 }
213 }
214
215 /* Send mouse packet */
216 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(
217 DeviceExtension->ClassDeviceObject,
218 &DeviceExtension->MouseInputData,
219 &DeviceExtension->MouseInputData + 1,
220 &DummyInputDataConsumed);
221}
222
224NTAPI
228{
230 ULONG ButtonDiff;
231 CHAR DeltaX, DeltaY;
232 PINPORT_DEVICE_EXTENSION DeviceExtension = Context;
233
235
236 switch (DeviceExtension->MouseType)
237 {
238 case NecBusMouse:
239 {
240 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
242
243 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
245 DeltaX = READ_MOUSE(DeviceExtension, NEC_BM_DATA) & 0x0F;
246
247 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
249 DeltaX |= READ_MOUSE(DeviceExtension, NEC_BM_DATA) << 4;
250
251 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
253 DeltaY = READ_MOUSE(DeviceExtension, NEC_BM_DATA) & 0x0F;
254
255 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
257 Buttons = READ_MOUSE(DeviceExtension, NEC_BM_DATA);
258 DeltaY |= Buttons << 4;
260
261 WRITE_MOUSE(DeviceExtension, NEC_BM_CONTROL,
263
264 break;
265 }
266
267 case MsInPortMouse:
268 {
270 WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
272
273 WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_X);
274 DeltaX = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
275
276 WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_REG_Y);
277 DeltaY = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
278
280 Buttons = READ_MOUSE(DeviceExtension, MS_INPORT_DATA);
282
284 WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
286
287 break;
288 }
289
290 case LogitechBusMouse:
291 {
292 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_X_LOW);
293 DeltaX = READ_MOUSE(DeviceExtension, LOG_BM_DATA) & 0x0F;
294
295 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_X_HIGH);
296 DeltaX |= READ_MOUSE(DeviceExtension, LOG_BM_DATA) << 4;
297
298 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_Y_LOW);
299 DeltaY = READ_MOUSE(DeviceExtension, LOG_BM_DATA) & 0x0F;
300
301 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_READ_Y_HIGH);
302 Buttons = READ_MOUSE(DeviceExtension, LOG_BM_DATA);
303 DeltaY |= Buttons << 4;
305
306 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_ENABLE_IRQ);
307
308 break;
309 }
310 }
311
312 ButtonDiff = DeviceExtension->MouseButtonState ^ Buttons;
313 DeviceExtension->MouseButtonState = Buttons;
314
315 /*
316 * Bus mouse devices don't have a status register to check
317 * whether this interrupt is indeed for us.
318 */
319 if ((DeltaX == 0) && (DeltaY == 0) && (ButtonDiff == 0))
320 {
321 /* We just pretend that the interrupt is not ours */
322 return FALSE;
323 }
324 else
325 {
326 DeviceExtension->RawData.DeltaX = DeltaX;
327 DeviceExtension->RawData.DeltaY = DeltaY;
328 DeviceExtension->RawData.Buttons = Buttons;
329 DeviceExtension->RawData.ButtonDiff = ButtonDiff;
330
331 IoRequestDpc(DeviceExtension->Self, NULL, NULL);
332
333 return TRUE;
334 }
335}
336
337CODE_SEG("PAGE")
338VOID
339NTAPI
341 _In_ PINPORT_DEVICE_EXTENSION DeviceExtension)
342{
343 PAGED_CODE();
344
345 /* Initialize mouse and disable interrupts */
346 switch (DeviceExtension->MouseType)
347 {
348 case NecBusMouse:
350
351 /* Setup interrupt rate (unavailable on hireso machines) */
352 if (DeviceExtension->IoBase != NEC_BM_HIRESO_BASE)
353 WRITE_MOUSE(DeviceExtension, NEC_BM_INT_RATE, NEC_RATE_60_HZ);
354
357 WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
358 break;
359
360 case MsInPortMouse:
361 WRITE_MOUSE(DeviceExtension, MS_INPORT_CONTROL, INPORT_RESET);
364 break;
365
366 case LogitechBusMouse:
367 WRITE_MOUSE(DeviceExtension, LOG_BM_CONFIG, LOG_DEFAULT_MODE);
368 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_DISABLE_IRQ);
369 break;
370 }
371}
372
374NTAPI
377{
379
380 /* Enable interrupts */
381 switch (DeviceExtension->MouseType)
382 {
383 case NecBusMouse:
386 WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
387 break;
388
389 case MsInPortMouse:
391 WRITE_MOUSE(DeviceExtension, MS_INPORT_DATA,
393 break;
394
395 case LogitechBusMouse:
396 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_ENABLE_IRQ);
397 break;
398 }
399
400 return TRUE;
401}
402
404NTAPI
407{
409
410 /* Disable interrupts */
411 switch (DeviceExtension->MouseType)
412 {
413 case NecBusMouse:
416 WRITE_MOUSE(DeviceExtension, NEC_BM_CONFIG, NEC_PPI_HC_CLEAR);
417 break;
418
419 case MsInPortMouse:
422 break;
423
424 case LogitechBusMouse:
425 WRITE_MOUSE(DeviceExtension, LOG_BM_CONTROL, LOG_DISABLE_IRQ);
426 break;
427 }
428
429 return TRUE;
430}
#define PAGED_CODE()
unsigned char BOOLEAN
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define LOG_READ_Y_HIGH
Definition: hardware.c:96
#define LOG_BUTTON_LEFT
Definition: hardware.c:104
#define MS_INPORT_CONTROL
Definition: hardware.c:63
#define NEC_INT_ENABLE
Definition: hardware.c:31
#define NEC_BUTTON_RIGHT
Definition: hardware.c:57
#define WRITE_MOUSE(DeviceExtension, Port, Data)
Definition: hardware.c:22
#define LOG_READ_X_HIGH
Definition: hardware.c:94
#define LOG_ENABLE_IRQ
Definition: hardware.c:90
#define LOG_BM_CONFIG
Definition: hardware.c:98
#define INPORT_MODE_BASE
Definition: hardware.c:72
#define NEC_PPI_INT_ENABLE
Definition: hardware.c:43
#define LOG_DEFAULT_MODE
Definition: hardware.c:99
#define NEC_READ_Y_LOW
Definition: hardware.c:36
#define NEC_RATE_60_HZ
Definition: hardware.c:51
#define INPORT_REG_Y
Definition: hardware.c:66
#define NEC_BUTTON_LEFT
Definition: hardware.c:58
#define LOG_BUTTON_RIGHT
Definition: hardware.c:102
#define INPORT_REG_X
Definition: hardware.c:65
#define NEC_PPI_INT_DISABLE
Definition: hardware.c:44
#define LOG_BUTTON_MIDDLE
Definition: hardware.c:103
#define LOG_BM_CONTROL
Definition: hardware.c:89
VOID NTAPI InPortInitializeMouse(_In_ PINPORT_DEVICE_EXTENSION DeviceExtension)
Definition: hardware.c:340
#define INPORT_MODE_IRQ
Definition: hardware.c:71
#define READ_MOUSE(DeviceExtension, Port)
Definition: hardware.c:19
#define NEC_BM_CONTROL
Definition: hardware.c:30
#define NEC_READ_X_HIGH
Definition: hardware.c:35
#define LOG_BM_DATA
Definition: hardware.c:84
#define NEC_BM_HIRESO_BASE
Definition: hardware.c:55
#define NEC_PPI_HC_NO_CLEAR
Definition: hardware.c:45
#define NEC_INPUT_CAPTURE
Definition: hardware.c:39
#define MS_BUTTON_MIDDLE
Definition: hardware.c:77
#define NEC_READ_Y_HIGH
Definition: hardware.c:37
#define MS_INPORT_DATA
Definition: hardware.c:70
#define LOG_READ_Y_LOW
Definition: hardware.c:95
#define NEC_READ_X_LOW
Definition: hardware.c:34
#define MS_BUTTON_RIGHT
Definition: hardware.c:79
#define NEC_BM_CONFIG
Definition: hardware.c:42
#define INPORT_REG_MODE
Definition: hardware.c:67
#define LOG_READ_X_LOW
Definition: hardware.c:93
#define NEC_BM_DATA
Definition: hardware.c:28
#define INPORT_REG_BTNS
Definition: hardware.c:64
#define NEC_INPUT_HOLD
Definition: hardware.c:40
#define NEC_PPI_DEFAULT_MODE
Definition: hardware.c:47
#define NEC_INT_DISABLE
Definition: hardware.c:32
#define MS_BUTTON_LEFT
Definition: hardware.c:78
#define NEC_BM_INT_RATE
Definition: hardware.c:49
#define INPORT_RESET
Definition: hardware.c:68
#define NEC_PPI_HC_CLEAR
Definition: hardware.c:46
#define LOG_DISABLE_IRQ
Definition: hardware.c:91
#define INPORT_MODE_HOLD
Definition: hardware.c:73
UCHAR KIRQL
Definition: env_spec_w32.h:591
KSERVICE_ROUTINE InPortIsr
Definition: inport.h:107
KSYNCHRONIZE_ROUTINE InPortStopMouse
Definition: inport.h:113
KSYNCHRONIZE_ROUTINE InPortStartMouse
Definition: inport.h:111
IO_DPC_ROUTINE InPortDpcForIsr
Definition: inport.h:109
@ NecBusMouse
Definition: inport.h:29
@ MsInPortMouse
Definition: inport.h:30
@ LogitechBusMouse
Definition: inport.h:31
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
VOID(STDAPICALLTYPE * PSERVICE_CALLBACK_ROUTINE)(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN OUT PVOID SystemArgument3)
Definition: kbdmou.h:86
static const TBBUTTON Buttons[]
Definition: mplay32.c:41
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define MOUSE_LEFT_BUTTON_DOWN
Definition: ntddmou.h:46
#define MOUSE_LEFT_BUTTON_UP
Definition: ntddmou.h:47
#define MOUSE_MIDDLE_BUTTON_DOWN
Definition: ntddmou.h:50
#define MOUSE_RIGHT_BUTTON_UP
Definition: ntddmou.h:49
#define MOUSE_MIDDLE_BUTTON_UP
Definition: ntddmou.h:51
#define MOUSE_RIGHT_BUTTON_DOWN
Definition: ntddmou.h:48
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171
INPORT_MOUSE_TYPE MouseType
Definition: inport.h:51
PDEVICE_OBJECT Self
Definition: inport.h:44
MOUSE_INPUT_DATA MouseInputData
Definition: inport.h:70
INPORT_RAW_DATA RawData
Definition: inport.h:62
PDEVICE_OBJECT ClassDeviceObject
Definition: inport.h:66
PKINTERRUPT InterruptObject
Definition: inport.h:54
UCHAR Buttons
Definition: inport.h:38
ULONG ButtonDiff
Definition: inport.h:39
Definition: ketypes.h:687
USHORT ButtonFlags
Definition: ntddmou.h:82
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
FORCEINLINE VOID IoRequestDpc(_Inout_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Irp, _In_opt_ __drv_aliasesMem PVOID Context)
Definition: iofuncs.h:2750
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
_In_ PKSYNCHRONIZE_ROUTINE _In_opt_ __drv_aliasesMem PVOID SynchronizeContext
Definition: kefuncs.h:539
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175