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 */
217 KeStallExecutionProcessor(10);
221 Status
= IoCallDriver(LowerDevice
, Irp
);
222 if (Status
== STATUS_PENDING
)
224 KeWaitForSingleObject(&event
, Suspended
, KernelMode
, FALSE
, NULL
);
225 Status
= ioStatus
.Status
;
227 if (!NT_SUCCESS(Status
))
230 /* Read all available data and process */
232 while (i
< ioStatus
.Information
)
234 Queue
= DeviceExtension
->ActiveQueue
% 2;
236 Input
= &DeviceExtension
->KeyboardInputData
[Queue
][DeviceExtension
->InputDataCount
[Queue
]];
238 /* Translate current chars to scan codes */
239 SpaceInQueue
= KEYBOARD_BUFFER_SIZE
- DeviceExtension
->InputDataCount
[Queue
];
240 if (TranslateCharToScanCodes(
241 &Buffer
[i
], /* input buffer */
242 ioStatus
.Information
- i
, /* input buffer size */
243 Input
, /* output buffer */
244 &SpaceInQueue
, /* output buffer size */
245 &BytesConsumed
)) /* bytes consumed in input buffer */
247 DPRINT("Got char 0x%02x (%c)\n", Buffer
[i
], Buffer
[i
] >= 32 ? Buffer
[i
] : ' ');
248 DeviceExtension
->InputDataCount
[Queue
] += BytesConsumed
;
250 /* Send the data to the keyboard class driver */
251 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
252 KeInsertQueueDpc(&DeviceExtension
->KeyboardDpc
, NULL
, NULL
);
253 KeLowerIrql(OldIrql
);
258 /* TranslateCharToScanCodes failed. Possible reasons:
259 * - not enough bytes in input buffer (escape control code; wait next received bytes)
260 * - not enough room in output buffer (wait for the Dpc to empty it)
262 * The best way to resolve this is to try later.
269 PsTerminateSystemThread(STATUS_SUCCESS
);
273 KeyboardInternalDeviceControl(
274 IN PDEVICE_OBJECT DeviceObject
,
277 PIO_STACK_LOCATION Stack
;
278 PKEYBOARD_DEVICE_EXTENSION DeviceExtension
;
281 Stack
= IoGetCurrentIrpStackLocation(Irp
);
282 Irp
->IoStatus
.Information
= 0;
283 DeviceExtension
= (PKEYBOARD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
285 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
287 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
289 DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
290 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
292 Status
= STATUS_INVALID_PARAMETER
;
296 DeviceExtension
->ClassInformation
=
297 *((PCONNECT_DATA
)Stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
);
299 /* Start read loop */
300 Status
= PsCreateSystemThread(
301 &DeviceExtension
->WorkerThreadHandle
,
306 KeyboardDeviceWorker
,
312 DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
313 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
314 Status
= STATUS_INVALID_DEVICE_REQUEST
;
318 Irp
->IoStatus
.Status
= Status
;
319 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);