+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Keyboard.c\r
-\r
-Abstract:\r
-\r
- Helper functions for USB Keyboard Driver\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include "keyboard.h"\r
-\r
-//\r
-// USB Key Code to Efi key mapping table\r
-// Format:<efi scan code>, <unicode without shift>, <unicode with shift>\r
-//\r
-STATIC\r
-UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {\r
- { SCAN_NULL, 'a', 'A' }, // 0x04\r
- { SCAN_NULL, 'b', 'B' }, // 0x05\r
- { SCAN_NULL, 'c', 'C' }, // 0x06\r
- { SCAN_NULL, 'd', 'D' }, // 0x07\r
- { SCAN_NULL, 'e', 'E' }, // 0x08\r
- { SCAN_NULL, 'f', 'F' }, // 0x09\r
- { SCAN_NULL, 'g', 'G' }, // 0x0A\r
- { SCAN_NULL, 'h', 'H' }, // 0x0B\r
- { SCAN_NULL, 'i', 'I' }, // 0x0C\r
- { SCAN_NULL, 'j', 'J' }, // 0x0D\r
- { SCAN_NULL, 'k', 'K' }, // 0x0E\r
- { SCAN_NULL, 'l', 'L' }, // 0x0F\r
- { SCAN_NULL, 'm', 'M' }, // 0x10\r
- { SCAN_NULL, 'n', 'N' }, // 0x11\r
- { SCAN_NULL, 'o', 'O' }, // 0x12\r
- { SCAN_NULL, 'p', 'P' }, // 0x13\r
- { SCAN_NULL, 'q', 'Q' }, // 0x14\r
- { SCAN_NULL, 'r', 'R' }, // 0x15\r
- { SCAN_NULL, 's', 'S' }, // 0x16\r
- { SCAN_NULL, 't', 'T' }, // 0x17\r
- { SCAN_NULL, 'u', 'U' }, // 0x18\r
- { SCAN_NULL, 'v', 'V' }, // 0x19\r
- { SCAN_NULL, 'w', 'W' }, // 0x1A\r
- { SCAN_NULL, 'x', 'X' }, // 0x1B\r
- { SCAN_NULL, 'y', 'Y' }, // 0x1C\r
- { SCAN_NULL, 'z', 'Z' }, // 0x1D\r
- { SCAN_NULL, '1', '!' }, // 0x1E\r
- { SCAN_NULL, '2', '@' }, // 0x1F\r
- { SCAN_NULL, '3', '#' }, // 0x20\r
- { SCAN_NULL, '4', '$' }, // 0x21\r
- { SCAN_NULL, '5', '%' }, // 0x22\r
- { SCAN_NULL, '6', '^' }, // 0x23\r
- { SCAN_NULL, '7', '&' }, // 0x24\r
- { SCAN_NULL, '8', '*' }, // 0x25\r
- { SCAN_NULL, '9', '(' }, // 0x26\r
- { SCAN_NULL, '0', ')' }, // 0x27\r
- { SCAN_NULL, 0x0d, 0x0d }, // 0x28 Enter\r
- { SCAN_ESC, 0x00, 0x00 }, // 0x29 Esc\r
- { SCAN_NULL, 0x08, 0x08 }, // 0x2A Backspace\r
- { SCAN_NULL, 0x09, 0x09 }, // 0x2B Tab\r
- { SCAN_NULL, ' ', ' ' }, // 0x2C Spacebar\r
- { SCAN_NULL, '-', '_' }, // 0x2D\r
- { SCAN_NULL, '=', '+' }, // 0x2E\r
- { SCAN_NULL, '[', '{' }, // 0x2F\r
- { SCAN_NULL, ']', '}' }, // 0x30\r
- { SCAN_NULL, '\\', '|' }, // 0x31\r
- { SCAN_NULL, '\\', '|' }, // 0x32 Keyboard US \ and |\r
- { SCAN_NULL, ';', ':' }, // 0x33\r
- { SCAN_NULL, '\'', '"' }, // 0x34\r
- { SCAN_NULL, '`', '~' }, // 0x35 Keyboard Grave Accent and Tlide\r
- { SCAN_NULL, ',', '<' }, // 0x36\r
- { SCAN_NULL, '.', '>' }, // 0x37\r
- { SCAN_NULL, '/', '?' }, // 0x38\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x39 CapsLock\r
- { SCAN_F1, 0x00, 0x00 }, // 0x3A\r
- { SCAN_F2, 0x00, 0x00 }, // 0x3B\r
- { SCAN_F3, 0x00, 0x00 }, // 0x3C\r
- { SCAN_F4, 0x00, 0x00 }, // 0x3D\r
- { SCAN_F5, 0x00, 0x00 }, // 0x3E\r
- { SCAN_F6, 0x00, 0x00 }, // 0x3F\r
- { SCAN_F7, 0x00, 0x00 }, // 0x40\r
- { SCAN_F8, 0x00, 0x00 }, // 0x41\r
- { SCAN_F9, 0x00, 0x00 }, // 0x42\r
- { SCAN_F10, 0x00, 0x00 }, // 0x43\r
- { SCAN_F11, 0x00, 0x00 }, // 0x44 F11\r
- { SCAN_F12, 0x00, 0x00 }, // 0x45 F12\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause\r
- { SCAN_INSERT, 0x00, 0x00 }, // 0x49\r
- { SCAN_HOME, 0x00, 0x00 }, // 0x4A\r
- { SCAN_PAGE_UP, 0x00, 0x00 }, // 0x4B\r
- { SCAN_DELETE, 0x00, 0x00 }, // 0x4C\r
- { SCAN_END, 0x00, 0x00 }, // 0x4D\r
- { SCAN_PAGE_DOWN, 0x00, 0x00 }, // 0x4E\r
- { SCAN_RIGHT, 0x00, 0x00 }, // 0x4F\r
- { SCAN_LEFT, 0x00, 0x00 }, // 0x50\r
- { SCAN_DOWN, 0x00, 0x00 }, // 0x51\r
- { SCAN_UP, 0x00, 0x00 }, // 0x52\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x53 NumLock\r
- { SCAN_NULL, '/', '/' }, // 0x54\r
- { SCAN_NULL, '*', '*' }, // 0x55\r
- { SCAN_NULL, '-', '-' }, // 0x56\r
- { SCAN_NULL, '+', '+' }, // 0x57\r
- { SCAN_NULL, 0x0d, 0x0d }, // 0x58\r
- { SCAN_END, '1', '1' }, // 0x59\r
- { SCAN_DOWN, '2', '2' }, // 0x5A\r
- { SCAN_PAGE_DOWN, '3', '3' }, // 0x5B\r
- { SCAN_LEFT, '4', '4' }, // 0x5C\r
- { SCAN_NULL, '5', '5' }, // 0x5D\r
- { SCAN_RIGHT, '6', '6' }, // 0x5E\r
- { SCAN_HOME, '7', '7' }, // 0x5F\r
- { SCAN_UP, '8', '8' }, // 0x60\r
- { SCAN_PAGE_UP, '9', '9' }, // 0x61\r
- { SCAN_INSERT, '0', '0' }, // 0x62\r
- { SCAN_DELETE, '.', '.' }, // 0x63\r
- { SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application\r
- { SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power\r
- { SCAN_NULL, '=' , '=' } // 0x67 Keypad =\r
-};\r
-\r
-STATIC KB_MODIFIER KB_Mod[8] = {\r
- { MOD_CONTROL_L, 0xe0 }, // 11100000\r
- { MOD_CONTROL_R, 0xe4 }, // 11100100\r
- { MOD_SHIFT_L, 0xe1 }, // 11100001\r
- { MOD_SHIFT_R, 0xe5 }, // 11100101\r
- { MOD_ALT_L, 0xe2 }, // 11100010\r
- { MOD_ALT_R, 0xe6 }, // 11100110\r
- { MOD_WIN_L, 0xe3 }, // 11100011\r
- { MOD_WIN_R, 0xe7 } // 11100111\r
-};\r
-\r
-\r
-BOOLEAN\r
-IsUSBKeyboard (\r
- IN EFI_USB_IO_PROTOCOL *UsbIo\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Uses USB I/O to check whether the device is a USB Keyboard device.\r
-\r
- Arguments:\r
- UsbIo: Points to a USB I/O protocol instance.\r
-\r
- Returns:\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
-\r
- //\r
- // Get the Default interface descriptor, currently we\r
- // assume it is interface 1\r
- //\r
- Status = UsbIo->UsbGetInterfaceDescriptor (\r
- UsbIo,\r
- &InterfaceDescriptor\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&\r
- InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&\r
- InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD\r
- ) {\r
-\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-InitUSBKeyboard (\r
- IN USB_KB_DEV *UsbKeyboardDevice\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Initialize USB Keyboard device and all private data structures.\r
-\r
- Arguments:\r
- UsbKeyboardDevice The USB_KB_DEV instance.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
- EFI_DEVICE_ERROR - Hardware Error\r
---*/\r
-{\r
- UINT8 ConfigValue;\r
- UINT8 Protocol;\r
- UINT8 ReportId;\r
- UINT8 Duration;\r
- EFI_STATUS Status;\r
- UINT32 TransferResult;\r
-\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
- EFI_PROGRESS_CODE,\r
- (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST)\r
- );\r
-\r
- InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
-\r
- //\r
- // default configurations\r
- //\r
- ConfigValue = 0x01;\r
-\r
- //\r
- // Uses default configuration to configure the USB Keyboard device.\r
- //\r
- Status = UsbSetDeviceConfiguration (\r
- UsbKeyboardDevice->UsbIo,\r
- (UINT16) ConfigValue,\r
- &TransferResult\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If configuration could not be set here, it means\r
- // the keyboard interface has some errors and could\r
- // not be initialized\r
- //\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR)\r
- );\r
-\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- UsbGetProtocolRequest (\r
- UsbKeyboardDevice->UsbIo,\r
- UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
- &Protocol\r
- );\r
- //\r
- // Sets boot protocol for the USB Keyboard.\r
- // This driver only supports boot protocol.\r
- // !!BugBug: How about the device that does not support boot protocol?\r
- //\r
- if (Protocol != BOOT_PROTOCOL) {\r
- UsbSetProtocolRequest (\r
- UsbKeyboardDevice->UsbIo,\r
- UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
- BOOT_PROTOCOL\r
- );\r
- }\r
- //\r
- // the duration is indefinite, so the endpoint will inhibit reporting forever,\r
- // and only reporting when a change is detected in the report data.\r
- //\r
-\r
- //\r
- // idle value for all report ID\r
- //\r
- ReportId = 0;\r
- //\r
- // idle forever until there is a key pressed and released.\r
- //\r
- Duration = 0;\r
- UsbSetIdleRequest (\r
- UsbKeyboardDevice->UsbIo,\r
- UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
- ReportId,\r
- Duration\r
- );\r
-\r
- UsbKeyboardDevice->CtrlOn = 0;\r
- UsbKeyboardDevice->AltOn = 0;\r
- UsbKeyboardDevice->ShiftOn = 0;\r
- UsbKeyboardDevice->NumLockOn = 0;\r
- UsbKeyboardDevice->CapsOn = 0;\r
- UsbKeyboardDevice->ScrollOn = 0;\r
- ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);\r
-\r
- //\r
- // Set a timer for repeat keys' generation.\r
- //\r
- if (UsbKeyboardDevice->RepeatTimer) {\r
- gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
- UsbKeyboardDevice->RepeatTimer = 0;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- USBKeyboardRepeatHandler,\r
- UsbKeyboardDevice,\r
- &UsbKeyboardDevice->RepeatTimer\r
- );\r
-\r
- if (UsbKeyboardDevice->DelayedRecoveryEvent) {\r
- gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
- UsbKeyboardDevice->DelayedRecoveryEvent = 0;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- USBKeyboardRecoveryHandler,\r
- UsbKeyboardDevice,\r
- &UsbKeyboardDevice->DelayedRecoveryEvent\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-KeyboardHandler (\r
- IN VOID *Data,\r
- IN UINTN DataLength,\r
- IN VOID *Context,\r
- IN UINT32 Result\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Handler function for USB Keyboard's asynchronous interrupt transfer.\r
-\r
- Arguments:\r
- Data A pointer to a buffer that is filled with key data which is\r
- retrieved via asynchronous interrupt transfer.\r
- DataLength Indicates the size of the data buffer.\r
- Context Pointing to USB_KB_DEV instance.\r
- Result Indicates the result of the asynchronous interrupt transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
- EFI_DEVICE_ERROR - Hardware Error\r
---*/\r
-{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- UINT8 *CurKeyCodeBuffer;\r
- UINT8 *OldKeyCodeBuffer;\r
- UINT8 CurModifierMap;\r
- UINT8 OldModifierMap;\r
- UINT8 Index;\r
- UINT8 Index2;\r
- BOOLEAN Down;\r
- BOOLEAN KeyRelease;\r
- BOOLEAN KeyPress;\r
- UINT8 SavedTail;\r
- USB_KEY UsbKey;\r
- UINT8 NewRepeatKey;\r
- UINT32 UsbStatus;\r
-\r
- ASSERT (Context);\r
-\r
- NewRepeatKey = 0;\r
- UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
- UsbIo = UsbKeyboardDevice->UsbIo;\r
-\r
- //\r
- // Analyzes the Result and performs corresponding action.\r
- //\r
- if (Result != EFI_USB_NOERROR) {\r
- //\r
- // Some errors happen during the process\r
- //\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR)\r
- );\r
-\r
- //\r
- // stop the repeat key generation if any\r
- //\r
- UsbKeyboardDevice->RepeatKey = 0;\r
-\r
- gBS->SetTimer (\r
- UsbKeyboardDevice->RepeatTimer,\r
- TimerCancel,\r
- USBKBD_REPEAT_RATE\r
- );\r
-\r
- if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
- UsbClearEndpointHalt (\r
- UsbIo,\r
- UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
- &UsbStatus\r
- );\r
- }\r
-\r
- //\r
- // Delete & Submit this interrupt again\r
- //\r
-\r
- UsbIo->UsbAsyncInterruptTransfer (\r
- UsbIo,\r
- UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
- FALSE,\r
- 0,\r
- 0,\r
- NULL,\r
- NULL\r
- );\r
-\r
- gBS->SetTimer (\r
- UsbKeyboardDevice->DelayedRecoveryEvent,\r
- TimerRelative,\r
- EFI_USB_INTERRUPT_DELAY\r
- );\r
-\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (DataLength == 0 || Data == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- CurKeyCodeBuffer = (UINT8 *) Data;\r
- OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;\r
-\r
- //\r
- // checks for new key stroke.\r
- // if no new key got, return immediately.\r
- //\r
- for (Index = 0; Index < 8; Index++) {\r
- if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index == 8) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Parse the modifier key\r
- //\r
- CurModifierMap = CurKeyCodeBuffer[0];\r
- OldModifierMap = OldKeyCodeBuffer[0];\r
-\r
- //\r
- // handle modifier key's pressing or releasing situation.\r
- //\r
- for (Index = 0; Index < 8; Index++) {\r
-\r
- if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) {\r
- //\r
- // if current modifier key is up, then\r
- // CurModifierMap & KB_Mod[Index].Mask = 0;\r
- // otherwize it is a non-zero value.\r
- // Inserts the pressed modifier key into key buffer.\r
- //\r
- Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask);\r
- InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), KB_Mod[Index].Key, Down);\r
- }\r
- }\r
-\r
- //\r
- // handle normal key's releasing situation\r
- //\r
- KeyRelease = FALSE;\r
- for (Index = 2; Index < 8; Index++) {\r
-\r
- if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {\r
- continue;\r
- }\r
-\r
- KeyRelease = TRUE;\r
- for (Index2 = 2; Index2 < 8; Index2++) {\r
-\r
- if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {\r
- continue;\r
- }\r
-\r
- if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {\r
- KeyRelease = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- if (KeyRelease) {\r
- InsertKeyCode (\r
- &(UsbKeyboardDevice->KeyboardBuffer),\r
- OldKeyCodeBuffer[Index],\r
- 0\r
- );\r
- //\r
- // the original reapeat key is released.\r
- //\r
- if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {\r
- UsbKeyboardDevice->RepeatKey = 0;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // original repeat key is released, cancel the repeat timer\r
- //\r
- if (UsbKeyboardDevice->RepeatKey == 0) {\r
- gBS->SetTimer (\r
- UsbKeyboardDevice->RepeatTimer,\r
- TimerCancel,\r
- USBKBD_REPEAT_RATE\r
- );\r
- }\r
-\r
- //\r
- // handle normal key's pressing situation\r
- //\r
- KeyPress = FALSE;\r
- for (Index = 2; Index < 8; Index++) {\r
-\r
- if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {\r
- continue;\r
- }\r
-\r
- KeyPress = TRUE;\r
- for (Index2 = 2; Index2 < 8; Index2++) {\r
-\r
- if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {\r
- continue;\r
- }\r
-\r
- if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {\r
- KeyPress = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- if (KeyPress) {\r
- InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], 1);\r
- //\r
- // NumLock pressed or CapsLock pressed\r
- //\r
- if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) {\r
- UsbKeyboardDevice->RepeatKey = 0;\r
- } else {\r
- NewRepeatKey = CurKeyCodeBuffer[Index];\r
- //\r
- // do not repeat the original repeated key\r
- //\r
- UsbKeyboardDevice->RepeatKey = 0;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Update LastKeycodeArray[] buffer in the\r
- // Usb Keyboard Device data structure.\r
- //\r
- for (Index = 0; Index < 8; Index++) {\r
- UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];\r
- }\r
-\r
- //\r
- // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence\r
- // and judge whether it will invoke reset event.\r
- //\r
- SavedTail = UsbKeyboardDevice->KeyboardBuffer.bTail;\r
- Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
- while (Index != SavedTail) {\r
- RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
-\r
- switch (UsbKey.KeyCode) {\r
-\r
- case 0xe0:\r
- case 0xe4:\r
- if (UsbKey.Down) {\r
- UsbKeyboardDevice->CtrlOn = 1;\r
- } else {\r
- UsbKeyboardDevice->CtrlOn = 0;\r
- }\r
- break;\r
-\r
- case 0xe2:\r
- case 0xe6:\r
- if (UsbKey.Down) {\r
- UsbKeyboardDevice->AltOn = 1;\r
- } else {\r
- UsbKeyboardDevice->AltOn = 0;\r
- }\r
- break;\r
-\r
- //\r
- // Del Key Code\r
- //\r
- case 0x4c:\r
- case 0x63:\r
- if (UsbKey.Down) {\r
- if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
- gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
- }\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- //\r
- // insert the key back to the buffer.\r
- // so the key sequence will not be destroyed.\r
- //\r
- InsertKeyCode (\r
- &(UsbKeyboardDevice->KeyboardBuffer),\r
- UsbKey.KeyCode,\r
- UsbKey.Down\r
- );\r
- Index = UsbKeyboardDevice->KeyboardBuffer.bHead;\r
-\r
- }\r
- //\r
- // If have new key pressed, update the RepeatKey value, and set the\r
- // timer to repeate delay timer\r
- //\r
- if (NewRepeatKey != 0) {\r
- //\r
- // sets trigger time to "Repeat Delay Time",\r
- // to trigger the repeat timer when the key is hold long\r
- // enough time.\r
- //\r
- gBS->SetTimer (\r
- UsbKeyboardDevice->RepeatTimer,\r
- TimerRelative,\r
- USBKBD_REPEAT_DELAY\r
- );\r
- UsbKeyboardDevice->RepeatKey = NewRepeatKey;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-USBParseKey (\r
- IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
- OUT UINT8 *KeyChar\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves a key character after parsing the raw data in keyboard buffer.\r
-\r
- Arguments:\r
- UsbKeyboardDevice The USB_KB_DEV instance.\r
- KeyChar Points to the Key character after key parsing.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
- EFI_NOT_READY - Device is not ready\r
---*/\r
-{\r
- USB_KEY UsbKey;\r
-\r
- *KeyChar = 0;\r
-\r
- while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {\r
- //\r
- // pops one raw data off.\r
- //\r
- RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
-\r
- if (!UsbKey.Down) {\r
- switch (UsbKey.KeyCode) {\r
-\r
- case 0xe0:\r
- case 0xe4:\r
- UsbKeyboardDevice->CtrlOn = 0;\r
- break;\r
-\r
- case 0xe1:\r
- case 0xe5:\r
- UsbKeyboardDevice->ShiftOn = 0;\r
- break;\r
-\r
- case 0xe2:\r
- case 0xe6:\r
- UsbKeyboardDevice->AltOn = 0;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- continue;\r
- }\r
-\r
- //\r
- // Analyzes key pressing situation\r
- //\r
- switch (UsbKey.KeyCode) {\r
-\r
- case 0xe0:\r
- case 0xe4:\r
- UsbKeyboardDevice->CtrlOn = 1;\r
- continue;\r
- break;\r
-\r
- case 0xe1:\r
- case 0xe5:\r
- UsbKeyboardDevice->ShiftOn = 1;\r
- continue;\r
- break;\r
-\r
- case 0xe2:\r
- case 0xe6:\r
- UsbKeyboardDevice->AltOn = 1;\r
- continue;\r
- break;\r
-\r
- case 0xe3:\r
- case 0xe7:\r
- continue;\r
- break;\r
-\r
- case 0x53:\r
- UsbKeyboardDevice->NumLockOn ^= 1;\r
- SetKeyLED (UsbKeyboardDevice);\r
- continue;\r
- break;\r
-\r
- case 0x39:\r
- UsbKeyboardDevice->CapsOn ^= 1;\r
- SetKeyLED (UsbKeyboardDevice);\r
- continue;\r
- break;\r
-\r
- //\r
- // F11,F12,PrintScreen,ScrollLock,Pause,Application,Power\r
- // keys are not valid EFI key\r
- //\r
- case 0x44:\r
- //\r
- // fall through\r
- //\r
- case 0x45:\r
- //\r
- // fall through\r
- //\r
- case 0x46:\r
- //\r
- // fall through\r
- //\r
- case 0x47:\r
- //\r
- // Turn on the ScrollLock light on KB\r
- //\r
- UsbKeyboardDevice->ScrollOn ^= 1;\r
- SetKeyLED (UsbKeyboardDevice);\r
- continue;\r
- break;\r
- case 0x48:\r
- //\r
- // fall through\r
- //\r
- case 0x65:\r
- case 0x66:\r
- continue;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- //\r
- // When encountered Del Key...\r
- //\r
- if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
- if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
- gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
- }\r
- }\r
-\r
- *KeyChar = UsbKey.KeyCode;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return EFI_NOT_READY;\r
-\r
-}\r
-\r
-\r
-EFI_STATUS\r
-USBKeyCodeToEFIScanCode (\r
- IN USB_KB_DEV *UsbKeyboardDevice,\r
- IN UINT8 KeyChar,\r
- OUT EFI_INPUT_KEY *Key\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Converts USB Keyboard code to EFI Scan Code.\r
-\r
- Arguments:\r
- UsbKeyboardDevice The USB_KB_DEV instance.\r
- KeyChar Indicates the key code that will be interpreted.\r
- Key A pointer to a buffer that is filled in with\r
- the keystroke information for the key that\r
- was pressed.\r
- Returns:\r
- EFI_NOT_READY - Device is not ready\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- UINT8 Index;\r
-\r
- if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- //\r
- // valid USB Key Code starts from 4\r
- //\r
- Index = (UINT8) (KeyChar - 4);\r
-\r
- if (Index >= USB_KEYCODE_MAX_MAKE) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- Key->ScanCode = KeyConvertionTable[Index][0];\r
-\r
- if (UsbKeyboardDevice->ShiftOn) {\r
-\r
- Key->UnicodeChar = KeyConvertionTable[Index][2];\r
-\r
- } else {\r
-\r
- Key->UnicodeChar = KeyConvertionTable[Index][1];\r
- }\r
-\r
- if (UsbKeyboardDevice->CapsOn) {\r
-\r
- if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
-\r
- Key->UnicodeChar = KeyConvertionTable[Index][2];\r
-\r
- } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
-\r
- Key->UnicodeChar = KeyConvertionTable[Index][1];\r
-\r
- }\r
- }\r
-\r
- if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
-\r
- if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
-\r
- Key->ScanCode = SCAN_NULL;\r
-\r
- } else {\r
-\r
- Key->UnicodeChar = 0x00;\r
- }\r
- }\r
-\r
- if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-EFI_STATUS\r
-InitUSBKeyBuffer (\r
- IN OUT USB_KB_BUFFER *KeyboardBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Resets USB Keyboard Buffer.\r
-\r
- Arguments:\r
- KeyboardBuffer - Points to the USB Keyboard Buffer.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));\r
-\r
- KeyboardBuffer->bHead = KeyboardBuffer->bTail;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-IsUSBKeyboardBufferEmpty (\r
- IN USB_KB_BUFFER *KeyboardBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Check whether USB Keyboard buffer is empty.\r
-\r
- Arguments:\r
- KeyboardBuffer - USB Keyboard Buffer.\r
-\r
- Returns:\r
-\r
---*/\r
-{\r
- //\r
- // meet FIFO empty condition\r
- //\r
- return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);\r
-}\r
-\r
-\r
-BOOLEAN\r
-IsUSBKeyboardBufferFull (\r
- IN USB_KB_BUFFER *KeyboardBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Check whether USB Keyboard buffer is full.\r
-\r
- Arguments:\r
- KeyboardBuffer - USB Keyboard Buffer.\r
-\r
- Returns:\r
-\r
---*/\r
-{\r
- return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) ==\r
- KeyboardBuffer->bHead);\r
-}\r
-\r
-\r
-EFI_STATUS\r
-InsertKeyCode (\r
- IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
- IN UINT8 Key,\r
- IN UINT8 Down\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Inserts a key code into keyboard buffer.\r
-\r
- Arguments:\r
- KeyboardBuffer - Points to the USB Keyboard Buffer.\r
- Key - Key code\r
- Down - Special key\r
- Returns:\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- USB_KEY UsbKey;\r
-\r
- //\r
- // if keyboard buffer is full, throw the\r
- // first key out of the keyboard buffer.\r
- //\r
- if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {\r
- RemoveKeyCode (KeyboardBuffer, &UsbKey);\r
- }\r
-\r
- KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;\r
- KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;\r
-\r
- //\r
- // adjust the tail pointer of the FIFO keyboard buffer.\r
- //\r
- KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-RemoveKeyCode (\r
- IN OUT USB_KB_BUFFER *KeyboardBuffer,\r
- OUT USB_KEY *UsbKey\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Pops a key code off from keyboard buffer.\r
-\r
- Arguments:\r
- KeyboardBuffer - Points to the USB Keyboard Buffer.\r
- UsbKey - Points to the buffer that contains a usb key code.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
- EFI_DEVICE_ERROR - Hardware Error\r
---*/\r
-{\r
- if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;\r
- UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;\r
-\r
- //\r
- // adjust the head pointer of the FIFO keyboard buffer.\r
- //\r
- KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SetKeyLED (\r
- IN USB_KB_DEV *UsbKeyboardDevice\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Sets USB Keyboard LED state.\r
-\r
- Arguments:\r
- UsbKeyboardDevice - The USB_KB_DEV instance.\r
-\r
- Returns:\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- LED_MAP Led;\r
- UINT8 ReportId;\r
-\r
- //\r
- // Set each field in Led map.\r
- //\r
- Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;\r
- Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;\r
- Led.ScrollLock = (UINT8) UsbKeyboardDevice->ScrollOn;\r
- Led.Resrvd = 0;\r
-\r
- ReportId = 0;\r
- //\r
- // call Set Report Request to lighten the LED.\r
- //\r
- UsbSetReportRequest (\r
- UsbKeyboardDevice->UsbIo,\r
- UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
- ReportId,\r
- HID_OUTPUT_REPORT,\r
- 1,\r
- (UINT8 *) &Led\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-EFIAPI\r
-USBKeyboardRepeatHandler (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Timer handler for Repeat Key timer.\r
-\r
- Arguments:\r
- Event - The Repeat Key event.\r
- Context - Points to the USB_KB_DEV instance.\r
-\r
- Returns:\r
-\r
---*/\r
-{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
-\r
- UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
-\r
- //\r
- // Do nothing when there is no repeat key.\r
- //\r
- if (UsbKeyboardDevice->RepeatKey != 0) {\r
- //\r
- // Inserts one Repeat key into keyboard buffer,\r
- //\r
- InsertKeyCode (\r
- &(UsbKeyboardDevice->KeyboardBuffer),\r
- UsbKeyboardDevice->RepeatKey,\r
- 1\r
- );\r
-\r
- //\r
- // set repeate rate for repeat key generation.\r
- //\r
- gBS->SetTimer (\r
- UsbKeyboardDevice->RepeatTimer,\r
- TimerRelative,\r
- USBKBD_REPEAT_RATE\r
- );\r
-\r
- }\r
-}\r
-\r
-VOID\r
-EFIAPI\r
-USBKeyboardRecoveryHandler (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Timer handler for Delayed Recovery timer.\r
-\r
- Arguments:\r
- Event - The Delayed Recovery event.\r
- Context - Points to the USB_KB_DEV instance.\r
-\r
- Returns:\r
-\r
---*/\r
-{\r
-\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- UINT8 PacketSize;\r
-\r
- UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
-\r
- UsbIo = UsbKeyboardDevice->UsbIo;\r
-\r
- PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
-\r
- UsbIo->UsbAsyncInterruptTransfer (\r
- UsbIo,\r
- UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
- TRUE,\r
- UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
- PacketSize,\r
- KeyboardHandler,\r
- UsbKeyboardDevice\r
- );\r
-}\r