diff options
Diffstat (limited to 'Core/EM/usb/rt/sysnokbc.c')
-rw-r--r-- | Core/EM/usb/rt/sysnokbc.c | 1146 |
1 files changed, 1146 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/sysnokbc.c b/Core/EM/usb/rt/sysnokbc.c new file mode 100644 index 0000000..d38812f --- /dev/null +++ b/Core/EM/usb/rt/sysnokbc.c @@ -0,0 +1,1146 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/sysnokbc.c 14 5/06/14 5:14a Ryanchou $ +// +// $Revision: 14 $ +// +// $Date: 5/06/14 5:14a $ +//**************************************************************************** +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/sysnokbc.c $ +// +// 14 5/06/14 5:14a Ryanchou +// [TAG] EIP166835 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Arrow keys cannot work with specific USB keyboard +// [RootCause] HID driver cannot parse a input report that includes both +// usage minimum/maximum and single usage. +// [Solution] Store the usage in the same array to determine the input +// data format. +// [Files] syskbc.c, sysnokbc.c, usbdef.h, usbhid.c, usbkbd.c, +// usbkbd.h, usbms.c, usbpoint, efiusbhid.c, efiusbpoint.c +// +// 13 4/29/14 7:54p Wilsonlee +// [TAG] EIP163828 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] The mouses stop more than 4 seconds during TP 0xB4 when +// power on several times. +// [RootCause] The device sometime doesn't respond the set report +// command. +// [Solution] Change the timeout of set report command to 100 ms. +// [Files] syskbc.c, sysnokbc.c, usbhid.c, amiusb.h +// +// 12 3/19/13 3:59a Ryanchou +// [TAG] EIP118177 +// [Category] Improvement +// [Description] Dynamically allocate HCStrucTable at runtime. +// [Files] usb.sdl, usbport.c, usbsb.c, amiusb.c, ehci.c, ohci.c, +// syskbc.c, sysnokbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, usbhid.c, +// usbhub.c, usbmass.c, usbrt.mak, usb.sd, amiusbhc.c, efiusbccid.c, +// efiusbhid.c, efiusbmass.c, efiusbms.c, uhcd.c, uhcd.h, uhcd.mak, +// usbmisc.c, usbsrc.sdl +// +// 11 2/21/12 4:53a Rameshr +// [TAG] EIP67630 +// [Category] Improvement +// [Description] With the SCAN code matching , attribute also needs to +// be matched in AMIUSB driver for the Keymon support. +// [Files] sysnokbc.c +// +// 10 9/23/11 12:19a Rajeshms +// [TAG] EIP69580 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] NumLock is not working fine when pressed, while booting to +// windows XP in a KBC absent platform. +// [RootCause] The USB INT9 updates the LED state in BDA by checking +// 0x497 location which is not updated correctly in case of OS (which +// doesn't not use INT16h) +// [Solution] The LED state is compared with 0x417 location and if +// changed, 0x497 location is also updated and LED is glown based on the +// state. +// [Files] sysnokbc.c +// +// 9 4/30/10 3:39p Fredericko +// Fixed EIP:38028:USB AutoKeyRepeat is not working properly +// +// 8 2/01/10 1:29p Olegi +// EIP32867: added checking for the validity of KeyMon pointer. +// +// 7 9/24/08 10:21a Rameshraju +// KeymonFilter support added +// +// 6 5/16/08 12:01p Olegi +// Compliance with AMI coding standard. +// +// 4 10/26/07 11:10a Olegi +// Added Europe1 and Europe2 keys. +// +// 3 9/27/07 5:04p Olegi +// +// 2 9/27/07 4:12p Olegi +// +// 1 3/20/07 12:22p Olegi +// +//**************************************************************************** + +//<AMI_FHDR_START> +//----------------------------------------------------------------------------- +// +// Name: SysNoKbc.c +// +// Description: AMI USB keyboard driver data conversion and presentation +// routines, KBC is not present +// +//----------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "amidef.h" +#include "usbdef.h" +#include "amiusb.h" +#include "usbkbd.h" + +#if KEYMONFILTER_SUPPORT +#include <protocol\KeyMonPlatform.h> +#define KEYMON_MAP 0x108 +#define KEYMON_DATA_ADDRESS 0x10C +#endif + +VOID UpdateKeyMon(UINT8 KeyCode); + +extern LEGACY_USB_KEYBOARD mLegacyKeyboard; +extern USB_GLOBAL_DATA *gUsbData; +extern UINT8 aTypematicRateDelayTable[]; + +VOID UpdateLEDs(); + +// +// USB scan codes and the corresponding data that will be used during key translation +// +/* +0, //0 00 Reserved (no event indicated) +0, //1 01 Keyboard ErrorRollOver +0, //2 02 Keyboard POSTFail +0, //3 03 Keyboard ErrorUndefined +*/ +UINT8 aLetters[] = { + 0x1e, //4 04 Keyboard a and A + 0x30, //5 05 Keyboard b and B + 0x2e, //6 06 Keyboard c and C + 0x20, //7 07 Keyboard d and D + 0x12, //8 08 Keyboard e and E + 0x21, //9 09 Keyboard f and F + 0x22, //10 0A Keyboard g and G + 0x23, //11 0B Keyboard h and H + 0x17, //12 0C Keyboard i and I + 0x24, //13 0D Keyboard j and J + 0x25, //14 0E Keyboard k and K + 0x26, //15 0F Keyboard l and L + 0x32, //16 10 Keyboard m and M + 0x31, //17 11 Keyboard n and N + 0x18, //18 12 Keyboard o and O + 0x19, //19 13 Keyboard p and P + 0x10, //20 14 Keyboard q and Q + 0x13, //21 15 Keyboard r and R + 0x1f, //22 16 Keyboard s and S + 0x14, //23 17 Keyboard t and T + 0x16, //24 18 Keyboard u and U + 0x2f, //25 19 Keyboard v and V + 0x11, //26 1A Keyboard w and W + 0x2d, //27 1B Keyboard x and X + 0x15, //28 1C Keyboard y and Y + 0x2c, //29 1D Keyboard z and Z +}; + +struct TNumbers { + UINT8 NormalNumber; + UINT8 ShiftedNumber; +} aNumbers[] = { + 0x31, 0x21, //30 1E Keyboard 1 and ! + 0x32, 0x40, //31 1F Keyboard 2 and @ + 0x33, 0x23, //32 20 Keyboard 3 and # + 0x34, 0x24, //33 21 Keyboard 4 and $ + 0x35, 0x25, //34 22 Keyboard 5 and % + 0x36, 0x5e, //35 23 Keyboard 6 and ^ + 0x37, 0x26, //36 24 Keyboard 7 and & + 0x38, 0x2a, //37 25 Keyboard 8 and * + 0x39, 0x28, //38 26 Keyboard 9 and ( + 0x30, 0x29, //39 27 Keyboard 0 and ) +}; + +struct TBasicKeys { + UINT8 BasicKeyScancode; + UINT8 BasicKeyAsciiNormal; + UINT8 BasicKeyAsciiShifted; + UINT16 BasicKeyCodeCtrl; + UINT8 BasicKeyAsciiAlt; +} aBasicKey[] = { + 0x1c, 0x0d, 0x0d, 0x1c0a, 0xa6, //40 28 Keyboard Return (ENTER) + 0x01, 0x1b, 0x1b, 0x011b, 0x01, //41 29 Keyboard ESCAPE + 0x0e, 0x08, 0x08, 0x0e7f, 0x0e, //42 2A Keyboard DELETE (Backspace) + 0x0f, 0x09, 0x00, 0x9400, 0xa5, //43 2B Keyboard Tab + 0x00, 0x00, 0x00, 0x0000, 0x00, //44 2C Keyboard Spacebar, processed separately + 0x0c, 0x2d, 0x5f, 0x0c1f, 0x82, //45 2D Keyboard - and (underscore + 0x0d, 0x3d, 0x2b, 0x0000, 0x83, //46 2E Keyboard = and + + 0x1a, 0x5b, 0x7b, 0x1a1b, 0x1a, //47 2F Keyboard [ and { + 0x1b, 0x5d, 0x7d, 0x1b1d, 0x1b, //48 30 Keyboard ] and } + 0x2b, 0x5c, 0x7c, 0x2b1c, 0x26, //49 31 Keyboard \ and | + 0x2b, 0x5c, 0x7c, 0x2b1c, 0x26, //50 32 Keyboard Non-US # and ~ + 0x27, 0x3b, 0x3a, 0x0000, 0x27, //51 33 Keyboard ; and : + 0x28, 0x27, 0x22, 0x0000, 0x00, //52 34 Keyboard ` and " + 0x29, 0x60, 0x7e, 0x0000, 0x00, //53 35 Keyboard Grave Accent and Tilde + 0x33, 0x2c, 0x3c, 0x0000, 0x00, //54 36 Keyboard, and < + 0x34, 0x2e, 0x3e, 0x0000, 0x00, //55 37 Keyboard . and > + 0x35, 0x2f, 0x3f, 0x0000, 0x00, //56 38 Keyboard / and ? +}; +/* +//0x0000, //57 39 Keyboard Caps Lock +*/ +UINT8 aF1_10Key[] = { + 0x3b, //58 3A Keyboard F1 + 0x3c, //59 3B Keyboard F2 + 0x3d, //60 3C Keyboard F3 + 0x3e, //61 3D Keyboard F4 + 0x3f, //62 3E Keyboard F5 + 0x40, //63 3F Keyboard F6 + 0x41, //64 40 Keyboard F7 + 0x42, //65 41 Keyboard F8 + 0x43, //66 42 Keyboard F9 + 0x44, //67 43 Keyboard F10 +}; +/* +0x85, //68 44 Keyboard F11 +0x86, //69 45 Keyboard F12 + + +0x00, //70 46 Keyboard PrintScreen +0x00, //71 47 Keyboard Scroll Lock +0x00, //72 48 Keyboard Pause +*/ +/* apparently the PS/2's int9 implementation returns the same +scan/ascii for extended keys, keeping the table below for +reference only. +struct TExtKeys { + UINT8 NormalShiftedScanCode; + UINT8 ShiftedAsciiCode; + UINT8 wCtrlScanCode; + UINT8 wAltScanCode; +} aExtKeys[] = { + 0x52, 0x30, 0x92, 0xA2, //73 49 Keyboard Insert + 0x47, 0x37, 0x77, 0x97, //74 4A Keyboard Home + 0x49, 0x39, 0x84, 0x99, //75 4B Keyboard PageUp + 0x53, 0x2e, 0x93, 0xA3, //76 4C Keyboard Delete Forward + 0x4f, 0x31, 0x75, 0x9F, //77 4D Keyboard End + 0x51, 0x33, 0x76, 0xA1, //78 4E Keyboard PageDown + 0x4d, 0x36, 0x74, 0x9D, //79 4F Keyboard RightArrow + 0x4b, 0x34, 0x73, 0x9B, //80 50 Keyboard LeftArrow + 0x50, 0x32, 0x91, 0xA0, //81 51 Keyboard DownArrow + 0x48, 0x38, 0x8D, 0x98, //82 52 Keyboard UpArrow +}; +*/ +UINT8 aExtKeys[] = {0x52,0x47,0x49,0x53,0x4f,0x51,0x4d,0x4b,0x50,0x48,}; +/* +0x, //83 53 Keypad Num Lock and Clear +*/ + +UINT16 aKeypad1[] = { + 0x352f, //84 54 Keypad / + 0x372a, //85 55 Keypad * + 0x4a2d, //86 56 Keypad - + 0x4e2b, //87 57 Keypad + + 0x1c0d, //88 58 Keypad ENTER +}; + +struct TKeypadNumbers { + UINT8 NormalScanCode; // ascii code is 0 + UINT8 ShiftedAsciiCode; // altered by both NumLock and Shift + UINT8 CtrlScanCode; // ascii code is 0 + UINT8 AltScanCode; // ascii code is 0 +} aKeypad2[] = { + 0x4f, 0x31, 0x75, 0x9f, //89 59 Keypad 1 and End + 0x50, 0x32, 0x91, 0xa0, //90 5A Keypad 2 and Down Arrow + 0x51, 0x33, 0x76, 0xa1, //91 5B Keypad 3 and PageDn + 0x4b, 0x34, 0x73, 0x9b, //92 5C Keypad 4 and Left Arrow + 0x4c, 0x35, 0x8f, 0x00, //93 5D Keypad 5 (special, no code if lowercase) + 0x4d, 0x36, 0x74, 0x9d, //94 5E Keypad 6 and Right Arrow + 0x47, 0x37, 0x77, 0x97, //95 5F Keypad 7 and Home + 0x48, 0x38, 0x8d, 0x98, //96 60 Keypad 8 and Up Arrow + 0x49, 0x39, 0x84, 0x99, //97 61 Keypad 9 and PageUp + 0x52, 0x30, 0x92, 0xa2, //98 62 Keypad 0 and Insert + 0x53, 0x2e, 0x93, 0xa3, //99 63 Keypad . and Delete +}; +/* +0x, //100 64 Keyboard Non-US \ and | +0x, //101 65 Keyboard Application +*/ + +typedef UINT16 (*GETCODE_FUNC) (UINT8 usbcode); + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_Letter +// +// Description: Returns the scan/ascii code for letter charachters, USB +// code from 4 to 1D. +// Keys from 'A' to 'Z' are interpreted using the following logic: +// 1) first_keycode is 04 +// 2) last_keycode is 1D +// 3) scan_code = letters[key-first_keycode].scancode +// 4) ascii_code (normal) = 0x61+(key-first_keycode) +// 5) ascii_code (shifted) = 0x41+(key-first_keycode) +// 6) ascii_code (w/Ctrl) = key-first_keycode+1 +// +// Input: Key index (key code - 4) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_Letter(UINT8 usbcode) +{ + UINT8 scan_code = aLetters[usbcode]; + UINT8 ascii_code = 0x61 + usbcode; + BOOLEAN changecase = mLegacyKeyboard.KeyModifierState.CapsLock + || mLegacyKeyboard.KeyModifierState.Shift; + + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(scan_code); + + if (mLegacyKeyboard.KeyModifierState.CapsLock + && mLegacyKeyboard.KeyModifierState.Shift) changecase = FALSE; + if (changecase) ascii_code -= 0x20; + if (mLegacyKeyboard.KeyModifierState.Ctrl) ascii_code = usbcode+1; + return (UINT16)(scan_code << 8) + ascii_code; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_Number +// +// Description: Returns the scan/ascii code for numbers, USB code from 1E to 27. +// Keys from '1' to '0' are interpreted using the following logic: +// 1) first_keycode is 1E +// 2) last_keycode is 27 +// 3) scan_code = key-first_keycode + 2 +// 4) ascii_code (normal) = aNumbers[key-first_keycode].NormalNumber +// 5) ascii_code (shifted) = aNumbers[key-first_keycode].ShiftedNumber +// 6) scan_code (w/Alt) = key-first_keycode + 0x78 +// +// Input: Key index (key code - 1E) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_Number(UINT8 usbcode) +{ + UINT8 scan_code = usbcode+2; + UINT8 ascii_code = aNumbers[usbcode].NormalNumber; + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(scan_code); + if (mLegacyKeyboard.KeyModifierState.Shift) { + ascii_code = aNumbers[usbcode].ShiftedNumber; + } + if (mLegacyKeyboard.KeyModifierState.Ctrl) { + ascii_code = 0; scan_code = 0; + if (usbcode == 1) { // "2" + scan_code = 3; + } + if (usbcode == 5) { // "6" + scan_code = 7; + ascii_code = 0x1E; + } + } + if (mLegacyKeyboard.KeyModifierState.Alt) { + scan_code = usbcode + 0x78; + } + + return (UINT16)(scan_code << 8) + ascii_code; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_BasicKey +// +// Description: Returns the scan/ascii code for "basic keys" - not letters, not +// numbers (Enter, Escape, '[', '/', etc.); USB code from 28 to 38. +// +// Input: Key index (key code - 28) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_BasicKey(UINT8 usbcode) +{ + UINT8 scan_code = aBasicKey[usbcode].BasicKeyScancode; + UINT8 ascii_code = (mLegacyKeyboard.KeyModifierState.Shift)? + aBasicKey[usbcode].BasicKeyAsciiShifted : aBasicKey[usbcode].BasicKeyAsciiNormal; + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(scan_code); + if (mLegacyKeyboard.KeyModifierState.Ctrl) return aBasicKey[usbcode].BasicKeyCodeCtrl; + if (mLegacyKeyboard.KeyModifierState.Alt) { + ascii_code = aBasicKey[usbcode].BasicKeyAsciiAlt; + if (ascii_code == 0) scan_code = 0; + } + + return (UINT16)(scan_code << 8) + ascii_code; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_F1_10Key +// +// Description: Returns the scan/ascii code for functional keys F1..F10; +// USB code from 3A to 43. +// +// Input: Key index (key code - 3A) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_F1_10Key(UINT8 usbcode) +{ + UINT8 code = aF1_10Key[usbcode]; + // + // ASCII codes are 0s + // Scan codes: + // shifted = normal+0x19 + // w/Ctrl = normal+0x23 + // w/Alt = normal+0x2d + // + + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(code); + + if (mLegacyKeyboard.KeyModifierState.Shift) return (UINT16)(code+0x19) << 8; + if (mLegacyKeyboard.KeyModifierState.Ctrl) return (UINT16)(code+0x23) << 8; + if (mLegacyKeyboard.KeyModifierState.Alt) return (UINT16)(code+0x2d) << 8; + + return (UINT16)code << 8; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_F11F12Key +// +// Description: Returns the scan/ascii code for functional keys F11 and F12; +// USB code 44 and 45. +// +// Input: Key index (key code - 44) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_F11F12Key(UINT8 usbcode) +{ + UINT16 aF11_F12[2] = {0x8500, 0x8600}; + // + // ASCII codes are 0s + // Scan codes: Normal Shifted w/Ctrl w/Alt + // F11 0x85 0x87 0x89 0x8B + // F12 0x86 0x88 0x8A 0x8C + // + + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon((UINT8)(aF11_F12[usbcode] >> 8)); + + if (mLegacyKeyboard.KeyModifierState.Shift) return aF11_F12[usbcode]+0x200; + if (mLegacyKeyboard.KeyModifierState.Ctrl) return aF11_F12[usbcode]+0x400; + if (mLegacyKeyboard.KeyModifierState.Alt) return aF11_F12[usbcode]+0x600; + + return aF11_F12[usbcode]; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_ExtKey +// +// Description: Returns the scan/ascii code for extended keys such as Home, +// End, arrows, PgUp/Dn; USB code from 49 to 52. +// +// Input: Key index (key code - 49) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_ExtKey(UINT8 usbcode) +{ +/* UINT8 scan_code = aExtKeys[usbcode].NormalShiftedScanCode; + UINT8 ascii_code = 0; + + if (mLegacyKeyboard.KeyModifierState.Shift) { + ascii_code = aExtKeys[usbcode].ShiftedAsciiCode; + } else { + if (mLegacyKeyboard.KeyModifierState.Ctrl) { + scan_code = aExtKeys[usbcode].wCtrlScanCode; + } else { + if (mLegacyKeyboard.KeyModifierState.Alt) { + scan_code = aExtKeys[usbcode].wAltScanCode; + } + } + } + return ((UINT16)scan_code << 8) + ascii_code;*/ + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(aExtKeys[usbcode]); + + return (UINT16)aExtKeys[usbcode]<<8; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_Keypad1 +// +// Description: Returns the scan/ascii code for non-numeric part of the keypad, +// such as '/', '*', etc.; USB code from 54 to 58. +// +// Input: Key index (key code - 54) +// +// Output: scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_Keypad1(UINT8 usbcode) +{ + if (mLegacyKeyboard.KeyModifierState.Ctrl || mLegacyKeyboard.KeyModifierState.Alt) { + return 0; + } + + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon((UINT8)(aKeypad1[usbcode] >> 8)); + + return aKeypad1[usbcode]; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_Keypad2 +// +// Description: Returns the scan/ascii code for numeric part of the keypad; +// USB code from 59 to 63. +// +// Input: Key index (key code - 59) +// +// Output: scan code in upper byte, ascii code in lower byte +// +// Notes: The ascii_code is altered depending on the combination of +// Shift and NumLock. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_Keypad2(UINT8 usbcode) +{ + UINT8 scan_code = aKeypad2[usbcode].NormalScanCode; + UINT8 ascii_code = 0; + BOOLEAN changecase = mLegacyKeyboard.KeyModifierState.NumLock + || mLegacyKeyboard.KeyModifierState.Shift; + + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(scan_code); + + if (mLegacyKeyboard.KeyModifierState.NumLock + && mLegacyKeyboard.KeyModifierState.Shift) changecase = FALSE; + + if (changecase) ascii_code = aKeypad2[usbcode].ShiftedAsciiCode; + if (mLegacyKeyboard.KeyModifierState.Ctrl) { + return (UINT16)aKeypad2[usbcode].CtrlScanCode << 8; + } + if (mLegacyKeyboard.KeyModifierState.Alt) { + return (UINT16)aKeypad2[usbcode].AltScanCode << 8; + } + return ((UINT16)scan_code<<8) + ascii_code; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetCode_64 +// +// Description: Returns the scan/ascii code for USB Key 0x64, a.k.a. Europe2 +// Europe2 is typically in AT-101 Key Position 45, between Left +// Shift and Z keys. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 GetCode_64(UINT8 usbcode) +{ + // + // Check for Hot Key from the KeyMon driver + // + UpdateKeyMon(0x56); + + if (mLegacyKeyboard.KeyModifierState.Shift) return 0x567C; + return 0x565C; +} + +//<AMI_SHDR_START> +//---------------------------------------------------------------------------- +// Name: TKEYGROUP +// +// Description: This structure describes the range of the USB keys and the +// function that is called if the USB key is found within this +// range. +// +// Fields: Name Type Description +//------------------------------------------------------------ +// first_keycode UINT8 first key code in the range +// last_keycode UINT8 last key code in the range +// GetCode GETCODE_FUNC function to call if the code is in the range +// +//---------------------------------------------------------------------------- +//<AMI_SHDR_END> + +typedef struct { + UINT8 first_keycode; + UINT8 last_keycode; + GETCODE_FUNC GetCode; +} TKEYGROUP; + +TKEYGROUP aGetKey[] = { + {0x04, 0x1d, GetCode_Letter}, + {0x1e, 0x27, GetCode_Number}, + {0x28, 0x38, GetCode_BasicKey}, + {0x3A, 0x43, GetCode_F1_10Key}, + {0x44, 0x45, GetCode_F11F12Key}, + {0x49, 0x52, GetCode_ExtKey}, + {0x54, 0x58, GetCode_Keypad1}, + {0x59, 0x63, GetCode_Keypad2}, + {0x64, 0x64, GetCode_64}, + {0, 0, 0} +}; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SysNoKbcAutoRepeat +// +// Description: This function performs the key autorepeat +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SysNoKbcAutoRepeat() +{ + UINT8 i; + UINT8 bdaKbdLedFlags = *(UINT8*)0x417; + UINT8 ledstate; + + gUsbData->wRepeatCounter++; + if (gUsbData->wRepeatCounter >= gUsbData->wRepeatRate) { + + // + // Repeat rate is reached. + // Reload repeat delay counter with keyrepeat delay value; original + // type delay value will be restored in ProcessKeyboardData + // + gUsbData->wRepeatRate = aTypematicRateDelayTable[ + (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_RATE_BIT_MASK) >> + KBC_TYPE_RATE_BIT_SHIFT]; + gUsbData->wRepeatCounter = 0; + + for (i=6; i>0; i--) if (mLegacyKeyboard.KeyCodeStorage[i-1] != 0) break; + + if (i != 0) { // Some keys to repeat + if (mLegacyKeyboard.KeyCodeStorage[i-1]==mLegacyKeyboard.KeyToRepeat) { + ProcessKeyCode(mLegacyKeyboard.KeyToRepeat); + } else { + mLegacyKeyboard.KeyToRepeat = mLegacyKeyboard.KeyCodeStorage[i-1]; + } + USBKeyRepeat(NULL, 2); // Enable Key repeat + } + } + + // + // See if current NumLock/ScrlLock/CapsLock matches the 40:17 values; update + // the local data and LEDs accordingly. + // + ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7; + if (((bdaKbdLedFlags>>4) & 7) != ledstate) { // 7 is a mask for Scrl/Num/Caps locks + *(UINT8*)&mLegacyKeyboard.KeyModifierState &= 0xF8; + *(UINT8*)&mLegacyKeyboard.KeyModifierState |= ((bdaKbdLedFlags>>4) & 7); + UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetAsciiScan +// +// Description: Calls the service routine for the given keycode. Returns the +// scan/ascii code. +// +// Input: Key code +// +// Output: scan code in upper byte, ascii code in lower byte +// +// Referrals: TKEYGROUP +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +GetAsciiScan(UINT8 keyCode) +{ + TKEYGROUP *KeyGroup; + UINT16 code; + + if (keyCode == 0x2C) return 0x3920; // Space Bar + for (KeyGroup = aGetKey; KeyGroup->GetCode != 0; KeyGroup++) { + if (keyCode >= KeyGroup->first_keycode && keyCode <= KeyGroup->last_keycode) { + code = KeyGroup->GetCode(keyCode-KeyGroup->first_keycode); + if (mLegacyKeyboard.KeyModifierState.Alt) code &= 0xFF00; + return code; + } + } + return 0; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UpdateKeyMon +// +// Description: This function takes the keyboard scan code and checks if it is present +// in the Key Monitor table. If found, it updates the corresponding bit in +// the Key Monitor map. +// Key monitor data structure pointer is at 9FC0:10C +// Key monitor map (32 bit) updated by this routine is at 9FC0:108 +// Map element is {BYTE, DWORD}; BYTE - scan code, DWORD - attribute +// +// Input: Key code +// +//Output Key monitor map is updated accordingly +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +UpdateKeyMon(UINT8 KeyCode) +{ + +#if KEYMONFILTER_SUPPORT + KEY_ELEMENT *KeyMonData; + UINT32 *KeyMonMap; + UINT16 EbdaSeg = *(UINT16*)0x40e; + UINTN i; + UINTN KeyMonSize; + + KeyMonMap=(UINT32 *)((EbdaSeg << 4)+ KEYMON_MAP); + // + //KeyMon data Seg is located in EBDA:10E and Offset is EBDA:0x10C + // + KeyMonData=(KEY_ELEMENT*)((*(UINT16 *)((EbdaSeg << 4) + KEYMON_DATA_ADDRESS + 2) << 4) + \ + *(UINT16 *)((EbdaSeg << 4) + KEYMON_DATA_ADDRESS)); + + if(KeyMonData == 0) { + // + //Nobody registerd the Hot key with KeyMon driver. + // + return; + } + + KeyMonSize=*(UINT32 *)KeyMonData; + (UINT8 *)KeyMonData+=4; + + for(i=0;i<=KeyMonSize;i++) { + if(KeyMonData[i].ScanCode == KeyCode && + KeyMonData[i].Keyattribute.ShiftKey == mLegacyKeyboard.KeyModifierState.Shift && + KeyMonData[i].Keyattribute.CtrlKey == mLegacyKeyboard.KeyModifierState.Ctrl && + KeyMonData[i].Keyattribute.AltKey == mLegacyKeyboard.KeyModifierState.Alt ) { + // + //Update the Keymon Map in the EBDA:0x108 area. + // + *KeyMonMap= (*KeyMonMap) | (1<< i); + } + + } + return; +#else + return; +#endif + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InsertChar +// +// Description: Insert the given scan/ascii code in the BDA keyboard queue. +// Updates the necessary BDA pointers, head and tail. +// +// Input: Key code, scan code in upper byte, ascii code in lower byte +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +InsertChar(UINT16 keyCode) +{ + UINT16 bufHead = *(UINT16*)0x41a; + UINT16 bufTail = *(UINT16*)0x41c; + UINT16 bufStart = *(UINT16*)0x480; + UINT16 bufEnd = *(UINT16*)0x482; + + *(UINT16*)(UINTN)(0x400+bufTail) = keyCode; + bufTail+=2; + if (bufTail >= bufEnd) { + bufTail = bufStart; + } + + if (bufTail == bufHead) { + // + // Buffer overflow should be indicated here + // + return; + } + *(UINT16*)0x41c = bufTail; + + return; +} + + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UpdateLEDs +// +// Description: Updates USB keyboard(s) LEDs according to the value of +// mLegacyKeyboard.KeyModifierState. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UpdateLEDs( +) +{ + UINT8 i; + DEV_INFO *KbdDev; + UINT8 Rb; + + // + // Update LED status in every USB keyboard on the system + // + // BIT0 ScrlLock, BIT1 NumLock, BIT2 CapsLock + Rb = (mLegacyKeyboard.KeyModifierState.NumLock)? 1 : 0; + Rb = (mLegacyKeyboard.KeyModifierState.CapsLock)? Rb |2 : Rb; + Rb = (mLegacyKeyboard.KeyModifierState.ScrlLock)? Rb |4 : Rb; + // + // Update the LED status in BDA. + // + *(UINT8*)0x497 = ((*(UINT8*)0x497) & 0xF8 ) | ((mLegacyKeyboard.KeyModifierState.NumLock)? 2 : 0) + | ((mLegacyKeyboard.KeyModifierState.CapsLock)? 4:0) | ((mLegacyKeyboard.KeyModifierState.ScrlLock)? 1 : 0) ; + + for (i = 0; i < USB_DEV_HID_COUNT; i++) { + KbdDev = gUsbData->aUSBKBDeviceTable[i]; + if (KbdDev != NULL) { + UsbKbdSetLed(KbdDev, Rb); + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ProcessCtrlAltShift +// +// Description: Updates mLegacyKeyboard.KeyModifierState according to the value +// of the 1st byte of the USB keyboard data. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessCtrlAltShift( + UINT8 *usbKeys +) +{ + UINT8 i; + + mLegacyKeyboard.KeyModifierState.Ctrl = (usbKeys[0] & 0x11)? 1 : 0; + mLegacyKeyboard.KeyModifierState.Shift = (usbKeys[0] & 0x22)? 1 : 0; + mLegacyKeyboard.KeyModifierState.Alt = (usbKeys[0] & 0x44)? 1 : 0; + + // + // Process Ctrl-Alt-Del combination + // + if (mLegacyKeyboard.KeyModifierState.Ctrl + && mLegacyKeyboard.KeyModifierState.Alt) { + for (i=2; i<6;i++) { + if (usbKeys[i]==0x4C || usbKeys[i]==0x63) { + if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) { + ASSERT(gRT); + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } else { + ByteWriteIO(0xcf9, 6); + } + } + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ProcessLockKeys +// +// Description: Process the keys that alter NumLock/ScrollLock/CapsLock; updates +// mLegacyKeyboard.KeyModifierState and 0:417 accordingly. +// +// Input: USB key buffer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessLockKeys( + UINT8 *usbKeys +) +{ + UINT8 i; + + for (i=2; i<8; i++) { + switch (usbKeys[i]) { + case 0x53: // NumLock + *(UINT8*)0x417 ^= 0x20; // Toggle BIT5 + // *(UINT8*)0x497 ^= 0x02; // Toggle BIT1 + mLegacyKeyboard.KeyModifierState.NumLock ^= 1; // Toggle numlock state + break; + case 0x39: // CapsLock + *(UINT8*)0x417 ^= 0x40; // Toggle BIT6 + // *(UINT8*)0x497 ^= 0x04; // Toggle BIT2 + mLegacyKeyboard.KeyModifierState.CapsLock ^= 1; // Toggle capslock state + break; + case 0x47: // ScrlLock + *(UINT8*)0x417 ^= 0x10; // Toggle BIT4 + // *(UINT8*)0x497 ^= 0x01; // Toggle BIT0 + mLegacyKeyboard.KeyModifierState.ScrlLock ^= 1; // Toggle scrollock state + break; + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: AdjustKeyBuffer +// +// Description: There is often the new key is pressed on a USB keyboard while +// the previous one is not quite released. In this case usbKeys +// buffer contains the old keys and the new ones. User, on the +// other hand, expects only the new ones to be processed. +// This requires the buffer data modification so that the "old" +// keys are removed. +// The only time we do not do this analysis is when the buffer +// is clear that indicates that all keys are released. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +AdjustKeyBuffer( + UINT8 *usbKeys +) +{ + UINT8 aData[6]; + UINT8 i, j; + + // Save the buffer + for (i=0; i<6; i++) aData[i]=usbKeys[i]; + + // Patch the buffer + for (j=0; j<6; j++) { + if (mLegacyKeyboard.KeyCodeStorage[j]==0) continue; + for (i=0; i<6; i++) { + if (usbKeys[i] == 0) continue; + if (usbKeys[i] == mLegacyKeyboard.KeyCodeStorage[j]) { + usbKeys[i] = 0; + } + } + } + // Store the original buffer + for (i=0; i<6; i++) mLegacyKeyboard.KeyCodeStorage[i] = aData[i]; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ProcessKeyCode +// +// Description: This routine converts USB code into UINT16 with ASCII code in the +// lower byte and PS/2 scan code in the upper byte and inserts this +// UINT16 in the legacy keyboard queue in BDA. +// +// Input: USB key +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessKeyCode(UINT8 code) +{ + UINT16 ascii_scan; + ascii_scan = GetAsciiScan(code); + if (ascii_scan != 0) { + InsertChar(ascii_scan); + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_Int9 +// +// Description: This routine is called from when the new data from USB keyboard +// is transmitted and available for processing. The functionality is +// similar to legacy INT9 handler - data is converted into PS/2 +// ASCII/Scan codes and placed in BDA. +// +// Input: Buffer with USB keys +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBKB_Int9( + UINT8 *usbKeys +) +{ + UINT8 *keyCode; + UINT8 i; + UINT8 ledstate; + UINT8 bdaKbdLedFlags = (*(UINT8*)0x417) >> 4; + + AdjustKeyBuffer(&usbKeys[2]); + + // + // See if current NumLock/ScrlLock/CapsLock matches the 40:17 values. + // ; update the local data and LEDs accordingly. + // + ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7; + if ((bdaKbdLedFlags & 7) != ledstate) { // 7 is a mask for Scrl/Num/Caps locks + *(UINT8*)&mLegacyKeyboard.KeyModifierState &= 0xF8; + *(UINT8*)&mLegacyKeyboard.KeyModifierState |= (bdaKbdLedFlags & 7); + UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs + // + // Update to current Ctrl, Alt, NumLock LEDs state. + // + ledstate = *(UINT8*)&mLegacyKeyboard.KeyModifierState & 7; + } + + ProcessLockKeys(usbKeys); + ProcessCtrlAltShift(usbKeys); + + for (keyCode=usbKeys+2, i=0; i<6; i++, keyCode++) { + if (*keyCode==0) continue; + ProcessKeyCode(*keyCode); + } + + if (ledstate != (*(UINT8*)&mLegacyKeyboard.KeyModifierState & 7)) { + UpdateLEDs(); // Turn on/off Ctrl, Alt, NumLock LEDs + } + + // + // Reload the typematic rate value + // + gUsbData->wRepeatRate = aTypematicRateDelayTable[ + (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK) >> + KBC_TYPE_DELAY_BIT_SHIFT]; + gUsbData->wRepeatCounter = 0; + + // + // Buffer might be modified, original buffer is stored + // in mLegacyKeyboard.KeyCodeStorage + // + if (mLegacyKeyboard.KeyCodeStorage[0] == 0) { + USBKeyRepeat(NULL, 1); // Disable Key repeat + } else { + USBKeyRepeat(NULL, 2); // Enable Key repeat + } +} + + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** |