ReactOS  0.4.14-dev-49-gfb4591c
keyboard.c
Go to the documentation of this file.
1 /*
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)
7  */
8 
9 #include "green.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 static BOOLEAN
17  IN ULONG InputBufferSize,
19  OUT PULONG OutputBufferSize,
20  OUT PULONG BytesConsumed)
21 {
22  BOOLEAN NormalKey = FALSE;
23  USHORT MakeCode;
24 
25  if (InputBufferSize == 0)
26  return FALSE;
27 
28  switch (*InputBuffer)
29  {
30  case 0x1b: MakeCode = 0x01; NormalKey = TRUE; break; /* ESC */
31 
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;
45 
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;
59 
60  case '\r': MakeCode = 0x1c; NormalKey = TRUE; break;
61 
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;
73 
74  case '`': MakeCode = 0x29; NormalKey = TRUE; break;
75 
76  case '\\': MakeCode = 0x2b; NormalKey = TRUE; break;
77 
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;
88 
89  case ' ': MakeCode = 0x39; NormalKey = TRUE; break;
90  }
91  if (NormalKey && *OutputBufferSize >= 2)
92  {
93  OutputBuffer[0].MakeCode = MakeCode;
95  OutputBuffer[1].MakeCode = MakeCode;
97  *BytesConsumed = 2;
98  return TRUE;
99  }
100 
101  /* Consume strange character by ignoring it */
102  DPRINT1("Strange byte received 0x%02x ('%c')\n",
103  *InputBuffer, *InputBuffer >= 32 ? *InputBuffer : '.');
104  *BytesConsumed = 1;
105  return TRUE;
106 }
107 
108 NTSTATUS
112 {
113  PDEVICE_OBJECT Fdo;
114  PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
116 
117  DPRINT("KeyboardInitialize() called\n");
118 
121  NULL,
124  TRUE,
125  &Fdo);
126  if (!NT_SUCCESS(Status))
127  return Status;
128 
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);
134  ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->KeyboardFdo = Fdo;
136  Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
137 
138  return STATUS_SUCCESS;
139 }
140 
141 static VOID NTAPI
143  IN PKDPC Dpc,
144  IN PVOID pDeviceExtension, /* real type PKEYBOARD_DEVICE_EXTENSION */
145  IN PVOID Unused1,
146  IN PVOID Unused2)
147 {
148  PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
149  ULONG Queue;
150  ULONG InputDataConsumed;
151 
152  DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)pDeviceExtension;
153 
154  Queue = DeviceExtension->ActiveQueue % 2;
155  InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
157  DeviceExtension->ClassInformation.ClassDeviceObject,
158  DeviceExtension->KeyboardInputData[Queue],
159  DeviceExtension->KeyboardInputData[Queue] + DeviceExtension->InputDataCount[Queue],
160  &InputDataConsumed);
161 
162  DeviceExtension->InputDataCount[Queue] = 0;
163 }
164 
165 static VOID NTAPI
167  PVOID Context)
168 {
170  PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
171  PGREEN_DEVICE_EXTENSION GreenDeviceExtension;
172  PDEVICE_OBJECT LowerDevice;
173  UCHAR Buffer[16]; /* Arbitrary size */
176  PIRP Irp;
177  IO_STATUS_BLOCK ioStatus;
178  KEVENT event;
179  KIRQL OldIrql;
180  ULONG i, Queue;
181  ULONG SpaceInQueue;
182  ULONG BytesConsumed = 0;
185 
186  DPRINT("KeyboardDeviceWorker() called\n");
187 
190  GreenDeviceExtension = (PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension;
191  LowerDevice = GreenDeviceExtension->Serial;
192  BufferSize = sizeof(Buffer);
193  Zero.QuadPart = 0;
194 
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));
201 
202  /* main read loop */
203  while (TRUE)
204  {
207  IRP_MJ_READ,
208  LowerDevice,
210  &Zero,
211  &event,
212  &ioStatus);
213  if (!Irp)
214  {
215  /* no memory actually, try later */
217  continue;
218  }
219 
220  Status = IoCallDriver(LowerDevice, Irp);
221  if (Status == STATUS_PENDING)
222  {
224  Status = ioStatus.Status;
225  }
226  if (!NT_SUCCESS(Status))
227  continue;
228 
229  /* Read all available data and process */
230  i = 0;
231  while (i < ioStatus.Information)
232  {
233  Queue = DeviceExtension->ActiveQueue % 2;
234 
235  Input = &DeviceExtension->KeyboardInputData[Queue][DeviceExtension->InputDataCount[Queue]];
236 
237  /* Translate current chars to scan codes */
238  SpaceInQueue = KEYBOARD_BUFFER_SIZE - DeviceExtension->InputDataCount[Queue];
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 */
245  {
246  DPRINT("Got char 0x%02x (%c)\n", Buffer[i], Buffer[i] >= 32 ? Buffer[i] : ' ');
247  DeviceExtension->InputDataCount[Queue] += BytesConsumed;
248 
249  /* Send the data to the keyboard class driver */
251  KeInsertQueueDpc(&DeviceExtension->KeyboardDpc, NULL, NULL);
253  i += BytesConsumed;
254  }
255  else
256  {
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)
260  *
261  * The best way to resolve this is to try later.
262  */
263  i++;
264  }
265  }
266  }
267 
269 }
270 
271 NTSTATUS
274  IN PIRP Irp)
275 {
276  PIO_STACK_LOCATION Stack;
277  PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
279 
281  Irp->IoStatus.Information = 0;
283 
284  switch (Stack->Parameters.DeviceIoControl.IoControlCode)
285  {
287  {
288  DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
289  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
290  {
292  break;
293  }
294 
295  DeviceExtension->ClassInformation =
296  *((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
297 
298  /* Start read loop */
300  &DeviceExtension->WorkerThreadHandle,
301  (ACCESS_MASK)0L,
302  NULL,
303  NULL,
304  NULL,
306  DeviceObject);
307  break;
308  }
309  default:
310  {
311  DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
312  Stack->Parameters.DeviceIoControl.IoControlCode);
314  }
315  }
316 
317  Irp->IoStatus.Status = Status;
319  return Status;
320 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define DO_POWER_PAGABLE
#define IN
Definition: typedefs.h:38
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
_In_ PDEVICE_OBJECT Pdo
Definition: classpnp.h:301
ULONG InputDataCount[2]
Definition: green.h:55
struct _GREEN_DRIVER_EXTENSION * PGREEN_DRIVER_EXTENSION
static VOID NTAPI KeyboardDpcSendData(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: keyboard.c:142
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _DEVICE_OBJECT * PDEVICE_OBJECT
unsigned char * PUCHAR
Definition: retypes.h:3
CONNECT_DATA ClassInformation
Definition: green.h:50
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
LONG NTSTATUS
Definition: precomp.h:26
Definition: arc.h:84
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
struct _KEYBOARD_DEVICE_EXTENSION * PKEYBOARD_DEVICE_EXTENSION
#define KEY_BREAK
Definition: ntddkbd.h:71
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
CHAR InputBuffer[80]
Definition: conmgr.c:33
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PDEVICE_OBJECT NTAPI IoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:966
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
GREEN_DEVICE_TYPE Type
Definition: green.h:40
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
switch(r->id)
Definition: btrfs.c:2932
NTSTATUS KeyboardInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: keyboard.c:272
struct _GREEN_DEVICE_EXTENSION * PGREEN_DEVICE_EXTENSION
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
PDEVICE_OBJECT Serial
Definition: green.h:84
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
static VOID NTAPI KeyboardDeviceWorker(PVOID Context)
Definition: keyboard.c:166
#define BufferSize
Definition: classpnp.h:419
PVOID ClassService
Definition: kbdmou.h:82
#define IOCTL_INTERNAL_KEYBOARD_CONNECT
Definition: kbdmou.h:56
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID(STDAPICALLTYPE * PSERVICE_CALLBACK_ROUTINE)(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN OUT PVOID SystemArgument3)
Definition: kbdmou.h:86
static const WCHAR L[]
Definition: oid.c:1250
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: ketypes.h:687
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1842
struct _cl_event * event
Definition: glext.h:7739
static BOOLEAN TranslateCharToScanCodes(IN PUCHAR InputBuffer, IN ULONG InputBufferSize, OUT KEYBOARD_INPUT_DATA *OutputBuffer, OUT PULONG OutputBufferSize, OUT PULONG BytesConsumed)
Definition: keyboard.c:15
#define KEYBOARD_BUFFER_SIZE
Definition: green.h:19
KEYBOARD_INPUT_DATA KeyboardInputData[2][KEYBOARD_BUFFER_SIZE]
Definition: green.h:56
PDEVICE_OBJECT Green
Definition: green.h:48
Status
Definition: gdiplustypes.h:24
COMMON_FDO_DEVICE_EXTENSION Common
Definition: green.h:47
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:402
#define DPRINT1
Definition: precomp.h:8
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
NTSTATUS KeyboardAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo)
Definition: keyboard.c:109
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
struct _CONNECT_DATA * PCONNECT_DATA
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
signed int * PLONG
Definition: retypes.h:5
PDEVICE_OBJECT LowerDevice
Definition: green.h:41
#define KEY_MAKE
Definition: ntddkbd.h:70
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define FILE_DEVICE_KEYBOARD
Definition: winioctl.h:116
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:99
PDEVICE_OBJECT ClassDeviceObject
Definition: kbdmou.h:81