2 * PROJECT: ReactOS VT100 emulator
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/dd/green/keyboard.c
5 * PURPOSE: Keyboard part of green management
6 * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
15 TranslateCharToScanCodes(
16 IN PUCHAR InputBuffer
,
17 IN ULONG InputBufferSize
,
18 OUT KEYBOARD_INPUT_DATA
* OutputBuffer
,
19 OUT PULONG OutputBufferSize
,
20 OUT PULONG BytesConsumed
)
22 BOOLEAN NormalKey
= FALSE
;
25 if (InputBufferSize
== 0)
30 case 0x1b: MakeCode
= 0x01; NormalKey
= TRUE
; break; /* ESC */
32 case '1': MakeCode
= 0x02; NormalKey
= TRUE
; break;
33 case '2': MakeCode
= 0x03; NormalKey
= TRUE
; break;
34 case '3': MakeCode
= 0x04; NormalKey
= TRUE
; break;
35 case '4': MakeCode
= 0x05; NormalKey
= TRUE
; break;
36 case '5': MakeCode
= 0x06; NormalKey
= TRUE
; break;
37 case '6': MakeCode
= 0x07; NormalKey
= TRUE
; break;
38 case '7': MakeCode
= 0x08; NormalKey
= TRUE
; break;
39 case '8': MakeCode
= 0x09; NormalKey
= TRUE
; break;
40 case '9': MakeCode
= 0x0a; NormalKey
= TRUE
; break;
41 case '0': MakeCode
= 0x0b; NormalKey
= TRUE
; break;
42 case '-': MakeCode
= 0x0c; NormalKey
= TRUE
; break;
43 case '=': MakeCode
= 0x0d; NormalKey
= TRUE
; break;
44 case '\b': MakeCode
= 0x0e; NormalKey
= TRUE
; break;
46 case '\t': MakeCode
= 0x0f; NormalKey
= TRUE
; break;
47 case 'q': MakeCode
= 0x10; NormalKey
= TRUE
; break;
48 case 'w': MakeCode
= 0x11; NormalKey
= TRUE
; break;
49 case 'e': MakeCode
= 0x12; NormalKey
= TRUE
; break;
50 case 'r': MakeCode
= 0x13; NormalKey
= TRUE
; break;
51 case 't': MakeCode
= 0x14; NormalKey
= TRUE
; break;
52 case 'y': MakeCode
= 0x15; NormalKey
= TRUE
; break;
53 case 'u': MakeCode
= 0x16; NormalKey
= TRUE
; break;
54 case 'i': MakeCode
= 0x17; NormalKey
= TRUE
; break;
55 case 'o': MakeCode
= 0x18; NormalKey
= TRUE
; break;
56 case 'p': MakeCode
= 0x19; NormalKey
= TRUE
; break;
57 case '[': MakeCode
= 0x1a; NormalKey
= TRUE
; break;
58 case ']': MakeCode
= 0x1b; NormalKey
= TRUE
; break;
60 case '\r': MakeCode
= 0x1c; NormalKey
= TRUE
; break;
62 case 'a': MakeCode
= 0x1e; NormalKey
= TRUE
; break;
63 case 's': MakeCode
= 0x1f; NormalKey
= TRUE
; break;
64 case 'd': MakeCode
= 0x20; NormalKey
= TRUE
; break;
65 case 'f': MakeCode
= 0x21; NormalKey
= TRUE
; break;
66 case 'g': MakeCode
= 0x22; NormalKey
= TRUE
; break;
67 case 'h': MakeCode
= 0x23; NormalKey
= TRUE
; break;
68 case 'j': MakeCode
= 0x24; NormalKey
= TRUE
; break;
69 case 'k': MakeCode
= 0x25; NormalKey
= TRUE
; break;
70 case 'l': MakeCode
= 0x26; NormalKey
= TRUE
; break;
71 case ';': MakeCode
= 0x27; NormalKey
= TRUE
; break;
72 case '\'': MakeCode
= 0x28; NormalKey
= TRUE
; break;
74 case '`': MakeCode
= 0x29; NormalKey
= TRUE
; break;
76 case '\\': MakeCode
= 0x2b; NormalKey
= TRUE
; break;
78 case 'z': MakeCode
= 0x2c; NormalKey
= TRUE
; break;
79 case 'x': MakeCode
= 0x2d; NormalKey
= TRUE
; break;
80 case 'c': MakeCode
= 0x2e; NormalKey
= TRUE
; break;
81 case 'v': MakeCode
= 0x2f; NormalKey
= TRUE
; break;
82 case 'b': MakeCode
= 0x30; NormalKey
= TRUE
; break;
83 case 'n': MakeCode
= 0x31; NormalKey
= TRUE
; break;
84 case 'm': MakeCode
= 0x32; NormalKey
= TRUE
; break;
85 case ',': MakeCode
= 0x33; NormalKey
= TRUE
; break;
86 case '.': MakeCode
= 0x34; NormalKey
= TRUE
; break;
87 case '/': MakeCode
= 0x35; NormalKey
= TRUE
; break;
89 case ' ': MakeCode
= 0x39; NormalKey
= TRUE
; break;
91 if (NormalKey
&& *OutputBufferSize
>= 2)
93 OutputBuffer
[0].MakeCode
= MakeCode
;
94 OutputBuffer
[0].Flags
= KEY_MAKE
;
95 OutputBuffer
[1].MakeCode
= MakeCode
;
96 OutputBuffer
[1].Flags
= KEY_BREAK
;
101 /* Consume strange character by ignoring it */
102 DPRINT1("Strange byte received 0x%02x ('%c')\n",
103 *InputBuffer
, *InputBuffer
>= 32 ? *InputBuffer
: '.');
110 IN PDRIVER_OBJECT DriverObject
,
111 IN PDEVICE_OBJECT Pdo
)
114 PKEYBOARD_DEVICE_EXTENSION DeviceExtension
;
117 DPRINT("KeyboardInitialize() called\n");
119 Status
= IoCreateDevice(DriverObject
,
120 sizeof(KEYBOARD_DEVICE_EXTENSION
),
122 FILE_DEVICE_KEYBOARD
,
123 FILE_DEVICE_SECURE_OPEN
,
126 if (!NT_SUCCESS(Status
))
129 DeviceExtension
= (PKEYBOARD_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
130 RtlZeroMemory(DeviceExtension
, sizeof(KEYBOARD_DEVICE_EXTENSION
));
131 DeviceExtension
->Common
.Type
= KeyboardFDO
;
132 DeviceExtension
->Common
.LowerDevice
= IoAttachDeviceToDeviceStack(Fdo
, Pdo
);
133 DeviceExtension
->Green
= ((PGREEN_DRIVER_EXTENSION
)IoGetDriverObjectExtension(DriverObject
, DriverObject
))->GreenMainDO
;
134 ((PGREEN_DEVICE_EXTENSION
)DeviceExtension
->Green
->DeviceExtension
)->KeyboardFdo
= Fdo
;
135 Fdo
->Flags
|= DO_POWER_PAGABLE
| DO_BUFFERED_IO
;
136 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
138 return STATUS_SUCCESS
;
144 IN PVOID pDeviceExtension
, /* real type PKEYBOARD_DEVICE_EXTENSION */
148 PKEYBOARD_DEVICE_EXTENSION DeviceExtension
;
150 ULONG InputDataConsumed
;
152 DeviceExtension
= (PKEYBOARD_DEVICE_EXTENSION
)pDeviceExtension
;
154 Queue
= DeviceExtension
->ActiveQueue
% 2;
155 InterlockedIncrement((PLONG
)&DeviceExtension
->ActiveQueue
);
156 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ClassInformation
.ClassService
)(
157 DeviceExtension
->ClassInformation
.ClassDeviceObject
,
158 DeviceExtension
->KeyboardInputData
[Queue
],
159 DeviceExtension
->KeyboardInputData
[Queue
] + DeviceExtension
->InputDataCount
[Queue
],
162 DeviceExtension
->InputDataCount
[Queue
] = 0;
166 KeyboardDeviceWorker(
169 PDEVICE_OBJECT DeviceObject
;
170 PKEYBOARD_DEVICE_EXTENSION DeviceExtension
;
171 PGREEN_DEVICE_EXTENSION GreenDeviceExtension
;
172 PDEVICE_OBJECT LowerDevice
;
173 UCHAR Buffer
[16]; /* Arbitrary size */
177 IO_STATUS_BLOCK ioStatus
;
182 ULONG BytesConsumed
= 0;
183 PKEYBOARD_INPUT_DATA Input
;
186 DPRINT("KeyboardDeviceWorker() called\n");
188 DeviceObject
= (PDEVICE_OBJECT
)Context
;
189 DeviceExtension
= (PKEYBOARD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
190 GreenDeviceExtension
= (PGREEN_DEVICE_EXTENSION
)DeviceExtension
->Green
->DeviceExtension
;
191 LowerDevice
= GreenDeviceExtension
->Serial
;
192 BufferSize
= sizeof(Buffer
);
195 /* Initialize device extension */
196 DeviceExtension
->ActiveQueue
= 0;
197 DeviceExtension
->InputDataCount
[0] = 0;
198 DeviceExtension
->InputDataCount
[1] = 0;
199 KeInitializeDpc(&DeviceExtension
->KeyboardDpc
, KeyboardDpcSendData
, DeviceExtension
);
200 RtlZeroMemory(&DeviceExtension
->KeyboardInputData
, sizeof(DeviceExtension
->KeyboardInputData
));
205 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
206 Irp
= IoBuildSynchronousFsdRequest(
215 /* no memory actually, try later */
216 KeStallExecutionProcessor(10);
220 Status
= IoCallDriver(LowerDevice
, Irp
);
221 if (Status
== STATUS_PENDING
)
223 KeWaitForSingleObject(&event
, Suspended
, KernelMode
, FALSE
, NULL
);
224 Status
= ioStatus
.Status
;
226 if (!NT_SUCCESS(Status
))
229 /* Read all available data and process */
231 while (i
< ioStatus
.Information
)
233 Queue
= DeviceExtension
->ActiveQueue
% 2;
235 Input
= &DeviceExtension
->KeyboardInputData
[Queue
][DeviceExtension
->InputDataCount
[Queue
]];
237 /* Translate current chars to scan codes */
238 SpaceInQueue
= KEYBOARD_BUFFER_SIZE
- DeviceExtension
->InputDataCount
[Queue
];
239 if (TranslateCharToScanCodes(
240 &Buffer
[i
], /* input buffer */
241 ioStatus
.Information
- i
, /* input buffer size */
242 Input
, /* output buffer */
243 &SpaceInQueue
, /* output buffer size */
244 &BytesConsumed
)) /* bytes consumed in input buffer */
246 DPRINT("Got char 0x%02x (%c)\n", Buffer
[i
], Buffer
[i
] >= 32 ? Buffer
[i
] : ' ');
247 DeviceExtension
->InputDataCount
[Queue
] += BytesConsumed
;
249 /* Send the data to the keyboard class driver */
250 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
251 KeInsertQueueDpc(&DeviceExtension
->KeyboardDpc
, NULL
, NULL
);
252 KeLowerIrql(OldIrql
);
257 /* TranslateCharToScanCodes failed. Possible reasons:
258 * - not enough bytes in input buffer (escape control code; wait next received bytes)
259 * - not enough room in output buffer (wait for the Dpc to empty it)
261 * The best way to resolve this is to try later.
268 PsTerminateSystemThread(STATUS_SUCCESS
);
272 KeyboardInternalDeviceControl(
273 IN PDEVICE_OBJECT DeviceObject
,
276 PIO_STACK_LOCATION Stack
;
277 PKEYBOARD_DEVICE_EXTENSION DeviceExtension
;
280 Stack
= IoGetCurrentIrpStackLocation(Irp
);
281 Irp
->IoStatus
.Information
= 0;
282 DeviceExtension
= (PKEYBOARD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
284 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
286 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
288 DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
289 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
291 Status
= STATUS_INVALID_PARAMETER
;
295 DeviceExtension
->ClassInformation
=
296 *((PCONNECT_DATA
)Stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
);
298 /* Start read loop */
299 Status
= PsCreateSystemThread(
300 &DeviceExtension
->WorkerThreadHandle
,
305 KeyboardDeviceWorker
,
311 DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
312 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
313 Status
= STATUS_INVALID_DEVICE_REQUEST
;
317 Irp
->IoStatus
.Status
= Status
;
318 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);