in HidPkg/HidKeyboardDxe/HidKeyboard.c [905:1116]
VOID ProcessKeyStroke (
IN UINT8 *HidInputReportBuffer,
IN UINTN HidInputReportBufferSize,
IN HID_KB_DEV *HidKeyboardDevice
)
{
HID_KEY HIDKey;
UINT8 ModifierIndex;
UINT8 Mask;
UINT8 KeyCode;
UINT8 LastKeyCode;
UINT8 NewRepeatKey = 0;
BOOLEAN KeyPress;
BOOLEAN KeyRelease;
EFI_KEY_DESCRIPTOR *KeyDescriptor;
KEYBOARD_HID_INPUT_BUFFER *LastReport;
UINTN LastReportKeyCount;
KEYBOARD_HID_INPUT_BUFFER *CurrentReport;
UINTN CurrentReportKeyCount;
if ((HidKeyboardDevice == NULL) || (HidInputReportBuffer == NULL)) {
DEBUG ((DEBUG_ERROR, "[%a] - Invalid input pointer.\n", __FUNCTION__));
ASSERT((HidKeyboardDevice != NULL) && (HidInputReportBuffer != NULL));
return;
}
if (HidInputReportBufferSize < INPUT_REPORT_HEADER_SIZE) {
DEBUG ((DEBUG_ERROR, "[%a] - HID input report buffer is too small to process.\n", __FUNCTION__));
return;
}
// if Last response doesn't exist, create it.
if (HidKeyboardDevice->LastReport == NULL) {
HidKeyboardDevice->LastReportSize = INPUT_REPORT_HEADER_SIZE;
HidKeyboardDevice->LastReport = AllocateZeroPool(INPUT_REPORT_HEADER_SIZE);
if (HidKeyboardDevice->LastReport == NULL) {
DEBUG ((DEBUG_ERROR, "[%a] - Could not allocate empty last report.\n", __FUNCTION__));
return;
}
}
LastReport = HidKeyboardDevice->LastReport;
LastReportKeyCount = HidKeyboardDevice->LastReportSize - INPUT_REPORT_HEADER_SIZE;
CurrentReport = (KEYBOARD_HID_INPUT_BUFFER *)HidInputReportBuffer;
CurrentReportKeyCount = HidInputReportBufferSize - INPUT_REPORT_HEADER_SIZE;
//
// Handle modifier key's pressing or releasing situation.
// According to USB HID Firmware spec, Byte 0 uses following map of Modifier keys:
// Bit0: Left Control, Keycode: 0xe0
// Bit1: Left Shift, Keycode: 0xe1
// Bit2: Left Alt, Keycode: 0xe2
// Bit3: Left GUI, Keycode: 0xe3
// Bit4: Right Control, Keycode: 0xe4
// Bit5: Right Shift, Keycode: 0xe5
// Bit6: Right Alt, Keycode: 0xe6
// Bit7: Right GUI, Keycode: 0xe7
//
for (ModifierIndex = 0; ModifierIndex < 8; ModifierIndex++) {
Mask = (UINT8) (1 << ModifierIndex);
if ((CurrentReport->ModifierKeys & Mask) != (LastReport->ModifierKeys & Mask)) {
//
// If current modifier key is up, then CurModifierMap & Mask = 0;
// otherwise it is a non-zero value.
// Insert the changed modifier key into key buffer.
//
HIDKey.KeyCode = (UINT8) (0xe0 + ModifierIndex);
HIDKey.Down = (BOOLEAN) ((CurrentReport->ModifierKeys & Mask) != 0);
Enqueue (&HidKeyboardDevice->HidKeyQueue, &HIDKey, sizeof (HID_KEY));
}
}
//
// Handle normal key's releasing situation
// Bytes 3 to n are for normal keycodes
//
KeyRelease = FALSE;
for (LastKeyCode = 0; LastKeyCode < LastReportKeyCount; LastKeyCode++) {
if (!HIDKBD_VALID_KEYCODE (LastReport->KeyCode[LastKeyCode])) {
continue;
}
//
// For any key in old keycode buffer, if it is not in current keycode buffer,
// then it is released. Otherwise, it is not released.
//
KeyRelease = TRUE;
for (KeyCode = 0; KeyCode < CurrentReportKeyCount; KeyCode++) {
if (!HIDKBD_VALID_KEYCODE (CurrentReport->KeyCode[KeyCode])) {
continue;
}
if (LastReport->KeyCode[LastKeyCode] == CurrentReport->KeyCode[KeyCode]) {
KeyRelease = FALSE;
break;
}
}
if (KeyRelease) {
HIDKey.KeyCode = LastReport->KeyCode[LastKeyCode];
HIDKey.Down = FALSE;
//
// The original repeat key is released.
//
if (LastReport->KeyCode[LastKeyCode] == HidKeyboardDevice->RepeatKey) {
DEBUG ((DEBUG_VERBOSE, "HIDKeyboard: Resetting key repeat\n"));
HidKeyboardDevice->RepeatKey = 0;
}
}
}
//
// If original repeat key is released, cancel the repeat timer
//
if (HidKeyboardDevice->RepeatKey == 0) {
DEBUG ((DEBUG_VERBOSE, "HIDKeyboard: Releasing Key Repeat Timer\n"));
gBS->SetTimer (
HidKeyboardDevice->RepeatTimer,
TimerCancel,
HIDKBD_REPEAT_RATE
);
}
//
// Handle normal key's pressing situation
//
KeyPress = FALSE;
for (KeyCode = 0; KeyCode < CurrentReportKeyCount; KeyCode++) {
if (!HIDKBD_VALID_KEYCODE (CurrentReport->KeyCode[KeyCode])) {
continue;
}
//
// For any key in current keycode buffer, if it is not in old keycode buffer,
// then it is pressed. Otherwise, it is not pressed.
//
KeyPress = TRUE;
for (LastKeyCode = 0; LastKeyCode < LastReportKeyCount; LastKeyCode++) {
if (!HIDKBD_VALID_KEYCODE (LastReport->KeyCode[LastKeyCode])) {
continue;
}
if (CurrentReport->KeyCode[KeyCode] == LastReport->KeyCode[LastKeyCode]) {
KeyPress = FALSE;
break;
}
}
if (KeyPress) {
HIDKey.KeyCode = CurrentReport->KeyCode[KeyCode];
HIDKey.Down = TRUE;
DEBUG ((DEBUG_VERBOSE, "HIDKeyboard: Enqueuing Key = %d, on KeyPress\n", HIDKey.KeyCode));
Enqueue (&HidKeyboardDevice->HidKeyQueue, &HIDKey, sizeof (HID_KEY));
//
// Handle repeat key
//
KeyDescriptor = GetKeyDescriptor (HidKeyboardDevice, CurrentReport->KeyCode[KeyCode]);
if (KeyDescriptor == NULL) {
return;
}
if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {
//
// For NumLock or CapsLock pressed, there is no need to handle repeat key for them.
//
HidKeyboardDevice->RepeatKey = 0;
} else {
//
// Prepare new repeat key, and clear the original one.
//
NewRepeatKey = CurrentReport->KeyCode[KeyCode];
HidKeyboardDevice->RepeatKey = 0;
}
}
}
//
// Copy the current report buffer as the last report buffer
//
FreePool(LastReport);
HidKeyboardDevice->LastReport = AllocateCopyPool(HidInputReportBufferSize, HidInputReportBuffer);
if (HidKeyboardDevice->LastReport == NULL) {
DEBUG ((DEBUG_ERROR, "[%a] - could not allocate last report buffer\n", __FUNCTION__));
HidKeyboardDevice->LastReportSize = 0;
} else {
HidKeyboardDevice->LastReportSize = HidInputReportBufferSize;
}
//
// If there is new key pressed, update the RepeatKey value, and set the
// timer to repeat the delay timer
//
if (NewRepeatKey != 0) {
//
// Sets trigger time to "Repeat Delay Time",
// to trigger the repeat timer when the key is hold long
// enough time.
//
gBS->SetTimer (
HidKeyboardDevice->RepeatTimer,
TimerRelative,
HIDKBD_REPEAT_DELAY
);
DEBUG ((DEBUG_VERBOSE, "HIDKeyboard: Setting Key repeat timer\n"));
DEBUG ((DEBUG_VERBOSE, "HIDKeyboard: New Repeat Key = %d, on KeyPress\n", NewRepeatKey));
HidKeyboardDevice->RepeatKey = NewRepeatKey;
}
}