diff options
Diffstat (limited to 'Core/EM/usb/rt/syskbc.c')
-rw-r--r-- | Core/EM/usb/rt/syskbc.c | 3225 |
1 files changed, 3225 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/syskbc.c b/Core/EM/usb/rt/syskbc.c new file mode 100644 index 0000000..157a9bd --- /dev/null +++ b/Core/EM/usb/rt/syskbc.c @@ -0,0 +1,3225 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2016, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/syskbc.c 41 10/16/16 10:12p Wilsonlee $ +// +// $Revision: 41 $ +// +// $Date: 10/16/16 10:12p $ +//**************************************************************************** +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/syskbc.c $ +// +// 41 10/16/16 10:12p Wilsonlee +// [TAG] EIP288158 +// [Category] Improvement +// [Description] Check if gUsbData is integrity. +// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl, +// AmiUsbSmmGlobalDataValidationLib.c, +// AmiUsbSmmGlobalDataValidationLib.cif, +// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h, +// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, +// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c, +// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c, +// AmiUsbController.h, AmiUsbLibInclude.cif, +// AmiUsbSmmGlobalDataValidationLib.h +// +// 40 2/24/15 5:50a Wilsonlee +// [TAG] EIP149716 +// [Category] Improvement +// [Description] Error Handling in USB mouse data. +// [Files] usbms.c, usbkbd.h, syskbc.c, xhci.c +// +// 39 7/23/14 10:23p Wilsonlee +// [TAG] EIP177642 +// [Category] Improvement +// [Description] SysKbcAutoRepeat handles the error case, the +// kbdInput_Send return error status. +// [Files] syskbc.c +// +// 38 6/26/14 1:15a Wilsonlee +// [TAG] EIP173387 +// [Category] Improvement +// [Description] Remove TODO comments. +// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c, +// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c, +// PeiEhci.c +// +// 37 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 +// +// 36 5/01/14 4:24a Ryanchou +// [TAG] EIP151894 +// [Category] Improvement +// [Description] Correct the break code of arrow keys. +// [Files] syskbc.c +// +// 35 4/29/14 7:53p 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 +// +// 34 12/30/13 3:42a Wilsonlee +// [TAG] EIP148411 +// [Category] Improvement +// [Description] Check if CCB_MOUSE_INTRPT is set before we sent mouse +// data. +// [Files] usbkbd.h, syskbc.c +// +// 33 8/22/13 6:32a Wilsonlee +// [TAG] EIP122944 +// [Category] Improvement +// [Description] Remove mouse_flag3 and check the mouse interface status +// in the CCB byte before we send the data to KBC. +// [Files] syskbc.c, usbms.c +// +// 32 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 +// +// 31 12/02/12 10:29p Roberthsu +// [TAG] EIP102150 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Push key and unplug KB , character repeat can not. +// stop +// [RootCause] Because repeat key does not clear when usb keyboard +// unplug. +// [Solution] When keyboard disconnrct, clear keyboard device id with +// device id buffer and scancode buffer. +// [Files] amiusb.c,syskbc.c,uhcd.c,usbkbd.c +// +// 30 8/27/12 5:08a Roberthsu +// [TAG] EIP98251 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] RF KB NumLock/ScrollLock/CapsLock indicator is not +// available during post or BIOS setup menu +// [RootCause] Set led command lost report id. +// [Solution] Check report id exist. +// [Files] syskbc.c,usbhid.c +// +// 29 5/22/12 10:55a Jittenkumarp +// [TAG] EIP87959 +// [Category] New Feature +// [Description] Proper Error path in the USB driver, incase KBC Input +// buffer is full +// [Files] usbkbd.h, syskbc.c +// +// 28 5/22/12 6:32a Ryanchou +// [TAG] EIP89608 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Barcode reader does not scan line-word +// [RootCause] The EIP72505 change breaks the loop of processing scan +// code buffer. +// [Solution] All the character should be processed. +// [Files] syskbc.c +// +// 27 1/04/12 6:54a Ryanchou +// [TAG] EIP72505 +// [Category] Improvement +// [Description] Clear the legacy USB keyboard buffer when switching +// between EFI and legacy. +// [Files] syskbc.c, uhcd.c, usbkbd.c +// +// 26 12/08/11 4:04a Ryanchou +// [TAG] EIP75266 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] There are garbage characters if press arrow key for a while +// [RootCause] The arrow generates 4 bytes of repeat key for scan code +// set 1, it should be 2 bytes. +// [Solution] Correct the repeat key generation. +// [Files] syskbc.c +// +// 25 9/27/11 12:07a Roberthsu +// [TAG] EIP65344 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Razer mouse will hang in post +// [RootCause] Razer has report keyboard interface.But not report led +// usage. +// [Solution] Check if not report led usage page.Do not send led +// command. +// [Files] syskbc.c,usbhid.c,usbdef.h +// +// 24 7/13/11 3:24a Ryanchou +// [TAG] EIP60380 +// [Bug fix] USB keyboard can't repeat character under DOS +// [Symptom] Insert the wireless USB keyboard. It can't repeat character +// under DOS +// [Root Cause] Because wRepeatCounter always clear by every time. +// [Solution] Do not clear wRepeatCounter everytime. +// +// 23 5/24/11 12:04p Olegi +// [TAG] EIP56557 +// [Category] Improvement +// [Description] Modified SendMouseData function. +// [Files] syskbc.c +// +// 22 5/24/11 12:00p Olegi +// [TAG] EIP60261 +// [Category] Improvement +// [Description] Ultrasound keyboard fails the LED related transfer. +// [Files] syskbc.c +// +// 21 5/03/11 6:56a Ryanchou +// [TAG] EIP57745 +// [Category] Improvement +// [Description] The token CHECK_MOUSE_FLAG is depend on CSM version, +// remove the token and check CSM verion to support this feature or not. +// [Files] syskbc.c, usbms.c, usbsrc.sdl +// +// 20 9/08/10 8:06a Ryanchou +// EIP43822: Add a toekn "CHECK_MOUSE_FLAG", the token controls whether +// apply EIP40121 solution. +// +// 19 8/18/10 4:27p Olegi +// - Klockwork related fixes; EIP37978 +// - Send mouse driver only when driver is active; EIP40121 +// +// 18 7/08/10 2:21a Rameshr +// Ohci Emulation support Added. +// EIP 39712 +// +// 17 11/24/09 11:33a Olegi +// BIOS adds an USB API (Block KBC Access) +// +// 16 11/18/09 11:49a Olegi +// +// 15 11/18/09 11:48a Olegi +// Modified the codes returned on Shift-NumLock-ExtKeys(Home, Ins,...) +// combination. For these combinations NumLock cancels Shift. EIP#27889 +// +// 14 9/15/09 12:21p Olegi +// Added KEY_REPEAT_LOGIC functionality. EIP#25841 +// +// 13 5/16/08 12:01p Olegi +// Compliance with AMI coding standard. +// +// 12 12/19/07 12:20p Rameshraju +// Emulation disabled before getting the CCB and Enabled back again if the +// Emulation is active. +// +// 11 12/17/07 4:04p Olegi +// KBC emulation support added. +// +// 10 9/27/07 4:12p Olegi +// +// 9 9/26/07 9:25a Olegi +// +// 8 8/14/07 11:03a Olegi +// USBSendMouseData is using USB_MOUSE_UPDATE_EBDA_DATA token. +// +// 7 3/29/07 6:42p Olegi +// Code improvement in USBMSSendMouseData to avoid sync problems between +// PS/2 and USB mice. +// +// 6 3/20/07 12:22p Olegi +// +// 4 4/14/06 6:39p Olegi +// Conversion to be able to use x64 compiler. +// +// 3 3/20/06 3:37p Olegi +// Version 8.5 - x64 compatible. +// +// 2 11/15/05 3:42p Andriyn +// Fix: 2-byte keys get lost. +// +// 1 8/25/05 7:15p Andriyn +// +// 5 8/11/05 9:53a Olegi +// 60/64 port emulation related fixes for EMU6064 driver. +// +// 4 8/04/05 5:58p Andriyn +// Legacy over LegacyFree +// +// 2 6/01/05 5:22p Olegi +// Debug message shortened. +// +// 1 3/28/05 6:20p Olegi +// +// 1 3/15/05 9:23a Olegi +// Initial VSS check-in. +// +//**************************************************************************** + +//<AMI_FHDR_START> +//----------------------------------------------------------------------------- +// +// Name: SysKbc.c +// +// Description: AMI USB keyboard driver data conversion and presentation +// routines, KBC is present +// +//----------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "amidef.h" +#include "usbdef.h" +#include "amiusb.h" +#include "usbkbd.h" + +extern USB_GLOBAL_DATA *gUsbData; + +extern UINT8 aTypematicRateDelayTable[]; +extern EFI_EMUL6064KBDINPUT_PROTOCOL* gKbdInput; +extern EFI_EMUL6064MSINPUT_PROTOCOL* gMsInput; +extern EFI_EMUL6064TRAP_PROTOCOL* gEmulationTrap; +extern void USBKB_LEDOn(); + +UINT8 IsKbcAccessBlocked=FALSE; //(EIP29733+) + +UINT8 aStaticSet2ToSet1ScanCode[133] = + { 0x000,0x0E5,0x0F5,0x006,0x016,0x026,0x01E,0x03D, //; 00h - 07h + 0x0DC,0x0DD,0x0ED,0x0FD,0x00E,0x087,0x0B6,0x035, //; 08h - 0Fh + 0x0D4,0x03E,0x0AE,0x07C,0x017,0x07F,0x0EF,0x02D, //; 10h - 17h + 0x0CC,0x074,0x09E,0x007,0x00F,0x077,0x0E7,0x025, //; 18h - 1Fh + 0x0C4,0x08E,0x096,0x0FE,0x06F,0x0D7,0x0DF,0x01D, //; 20h - 27h + 0x0BC,0x036,0x086,0x0F6,0x05F,0x067,0x0CF,0x015, //; 28h - 2Fh + 0x0B4,0x076,0x07E,0x0E6,0x0EE,0x057,0x0C7,0x00D, //; 30h - 37h + 0x0AC,0x06C,0x06E,0x0DE,0x04F,0x0BF,0x0B7,0x005, //; 38h - 3Fh + 0x0A4,0x066,0x0D6,0x047,0x03F,0x0A7,0x0AF,0x0FC, //; 40h - 47h + 0x09C,0x05E,0x056,0x0CE,0x0C6,0x037,0x09F,0x0F4, //; 48h - 4Fh + 0x094,0x064,0x0BE,0x05C,0x02F,0x097,0x0EC,0x08C, //; 50h - 57h + 0x02E,0x04E,0x01F,0x027,0x054,0x0A6,0x0E4,0x04C, //; 58h - 5Fh + 0x055,0x04D,0x044,0x03C,0x034,0x02C,0x08F,0x024, //; 60h - 67h + 0x01C,0x085,0x014,0x0A5,0x0C5,0x00C,0x004,0x084, //; 68h - 6Fh + 0x06D,0x065,0x07D,0x09D,0x095,0x0BD,0x0F7,0x0D5, //; 70h - 77h + 0x045,0x08D,0x075,0x0AD,0x046,0x0B5,0x0CD,0x05D, //; 78h - 7Fh + 0x0FB,0x0F3,0x0EB,0x0F5,0x05D //; 80h - 84h + }; + +//---------------------------------------------------------------------------- +//------ USA ENGLISH keyboard ------- +// USB Key Code to Scan Code Set 2 + +UINT8 aUSBKeyCodeToScanCodeSet2Table[256] = + { + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x32, 0x21, 0x23, //00 - 07h + 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, //08 - 0Fh + 0x3A, 0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, //10 - 17h + 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A, 0x16, 0x1E, //18 - 1Fh + 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46, 0x45, //20 - 27h + 0x5A, 0x76, 0x66, 0x0D, 0x29, 0x4E, 0x55, 0x54, //28 - 2Fh + 0x5B, 0x5D, 0x5D, 0x4C, 0x52, 0x0E, 0x41, 0x49, //30 - 37h + 0x4A, 0x58, 0x05, 0x06, 0x04, 0x0C, 0x03, 0x0B, //38 - 3Fh + 0x83, 0x0A, 0x01, 0x09, // 40 - 43h + 0x78, 0x07, PRINT_SCREEN,0x7E, // 44 - 47h + PAUSE_KEY, INSERT_KEY, HOME_KEY, // 48 - 4Ah + PAGE_UP_KEY, DEL_KEY, END_KEY, // 4B - 4Dh + PAGE_DOWN_KEY, RIGHT_KEY, // 4E - 4Fh + LEFT_KEY, DOWN_KEY, UP_KEY, 0x77, // 50 - 53h + SLASH_KEY, 0x7C, 0x7B, 0x79, // 54 - 57h + RIGHT_ENTER, 0x69, 0x72, 0x7A, // 58 - 5Ch + 0x6B, 0x73, 0x74, 0x6C, // 5D - 5Fh + 0x75, 0x7D, 0x70, 0x71, 0x61, APP_MS_KEY,00, 0x00, // 60 - 67h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 - 6Fh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 70 - 77h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //78 - 7Fh + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, // 80 - 87h + 0x13, 0x6A, 0x64, 0x67, 0x00, 0x00, 0x00, 0x00, // 88 - 8Fh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 90 - 97h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 98 - 9Fh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // A0 - A7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // A8 - AFh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B0 - B7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B8 - BFh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C0 - C7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C8 - CFh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // D0 - D7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // D8 - DFh + 0x14, 0x12, 0x11, LEFT_MS_KEY, // E0 - E3h + RIGHT_CTRL, 0x59, RIGHT_ALT, RIGHT_MS_KEY, // E4 - E7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // E8 - EFh + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // F0 - F7h + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // F8 - FFh + }; +// Keyboard Scan Code Set 3 Table +#define SCAN_CODE_SET_TABLE_SIZE_DW 8 // In double word +UINT8 aStaticScanCodeSet3Table[32] = + { + 0x00, 0x15, 0x00, 0x28, 0x94, 0x29, 0xA4, 0x2A, + 0xA8, 0x2A, 0xA8, 0x2A, 0xA8, 0x2A, 0xA0, 0x2A, + 0xA8, 0x2A, 0xA8, 0x2A, 0xA8, 0x0A, 0xA4, 0x0A, + 0x8A, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02 + }; + + +UINT8 aStaticExtendedKeyScan2Table[6] = + { RIGHT_ALT, RIGHT_CTRL, RIGHT_ENTER, LEFT_MS_KEY, + RIGHT_MS_KEY, APP_MS_KEY }; + +UINT8 aStaticKeyPadScan2Table[10] = + { END_KEY, LEFT_KEY, HOME_KEY, INSERT_KEY, + DEL_KEY, DOWN_KEY, RIGHT_KEY, UP_KEY, + PAGE_DOWN_KEY, PAGE_UP_KEY }; + + +UINT8 aStaticExtendedKeyScan3Table[6] = + { 0x39, 0x58, 0x79, 0x8B, 0x8C, 0x8D}; +UINT8 aStaticKeyPadScan3Table[10] = + { 0x65, 0x61, 0x6E, 0x67, 0x64, 0x60, 0x6A, 0x63, 0x6D, 0x6F }; + +//---------------------------------------------------------------------------- +// Table used to find length of scan code needed. Please refer to comments +// in the code below (somewhere) for the usage. +// +UINT8 aScanCodeLengthTable_1112[4] = {0x01, 0x01, 0x01, 0x02}; +UINT8 aScanCodeLengthTable_2223[4] = {0x02, 0x02, 0x02, 0x003}; +UINT8 aScanCodeLengthTable_4446[4] = {0x04, 0x04, 0x04, 0x06}; +UINT8 aScanCodeLengthTable_4500[4] = {0x04, 0x05, 0x00, 0x00}; +UINT8 aScanCodeLengthTable_4545[4] = {0x04, 0x05, 0x04, 0x05}; +UINT8 aScanCodeLengthTable_6800[4] = {0x06, 0x08, 0x00, 0x00}; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_WaitForInputBufferToBeFree +// +// Description: This routine checks the input buffer free bit and waits till +// it is set by the keyboard controller +// +// Input: Nothing +// +// Output: USB_SUCCESS - If Input buffer is Empty +// USB_ERROR - If Input buffer is Full +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_WaitForInputBufferToBeFree () +{ + UINT8 bCount = 16, + bStatus; + UINT16 wCount = 0xFFFF; + do { + bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT1); + while(bStatus) { + if(wCount == 0) + break; + bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT1); + --wCount; + } + --bCount; + } while (bCount && bStatus); + + if (!bStatus) { + return USB_SUCCESS; + } else { + return USB_ERROR; + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_WaitForOutputBufferToBeFilled +// +// Description: This routine checks the output buffer full bit and waits till +// it is set by the keyboard controller +// +// Input: Nothing +// +// Output: USB_SUCCESS - If OutPut buffer is Full +// USB_ERROR - If Output buffer Empty +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_WaitForOutputBufferToBeFilled () +{ + UINT8 bCount = 16, + bStatus; + UINT16 wCount = 0xffff; + do { + bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT0); + while (!bStatus) { + if(wCount == 0) break; + bStatus = (UINT8)(ByteReadIO(KBC_STATUS_REG) & BIT0); + wCount--; + } + bCount--; + } while (bCount && (!bStatus)); + + if (bStatus) { + return USB_SUCCESS; + } else { + return USB_ERROR; + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_ReadDataByte +// +// Description: This routine till the keyboard controller sends a data byte +// +// Input: Nothing +// +// Output: Status - USB_SUCCESS +// - USB_ERROR +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_ReadDataByte ( + IN UINT8 *Data ) +{ + UINT8 Status; + + Status = KBC_WaitForOutputBufferToBeFilled(); + + if (Status == USB_SUCCESS) { + *Data = ByteReadIO(KBC_DATA_REG); + } + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_WriteCommandByte +// +// Description: This routine sends the command byte to the keyboard +// controller +// +// Input: IN UNIT8 bCmd - Command byte +// +// Output: Status - USB_SUCCESS +// - USB_ERROR +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_WriteCommandByte ( + IN UINT8 bCmd ) +{ + UINT8 Status; + + Status = KBC_WaitForInputBufferToBeFree(); + + if (Status == USB_SUCCESS) { + ByteWriteIO(KBC_COMMAND_REG, bCmd); + } + + Status = KBC_WaitForInputBufferToBeFree(); + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_WriteSubCommandByte +// +// Description: This routine sends the sub-command byte to the keyboard +// controller +// +// Input: bCmd Sub-command byte +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +KBC_WriteSubCommandByte (UINT8 bCmd) +{ + ByteWriteIO(KBC_SUBCOMMAND_REG, bCmd); + KBC_WaitForInputBufferToBeFree(); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_ReadKeyboardControllerData +// +// Description: This routine sends a command and receives the response byte +// for that command +// +// Input: IN UINT8 bCmd - Command to be sent +// In UINT8 *Data - Data to be Read +// +// Output: Status - USB_SUCCESS +// - USB_ERROR +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_ReadKeyboardControllerData ( + IN UINT8 bCmd, + IN UINT8 *Data ) +{ + UINT8 Status; + + Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free + + if (Status == USB_SUCCESS) { + Status = KBC_WriteCommandByte(bCmd); // Send the command + if (Status == USB_SUCCESS) { + Status = KBC_ReadDataByte(Data); // Read the data + } + } + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: KBC_WriteKeyboardControllerData +// +// Description: This routine writes a data byte to the keyboard controller +// by first sending a command byte first +// +// Input: IN UINT8 bCmd - Command to be sent +// IN UINT8 bData - Data to be sent +// +// Output: Status - USB_SUCCESS +// USB_ERROR +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBC_WriteKeyboardControllerData ( + IN UINT8 bCmd, + IN UINT8 bData ) +{ + UINT8 Status; + + Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free + + if (Status == USB_SUCCESS) { + Status = KBC_WriteCommandByte(bCmd); // Send the command + if (Status == USB_SUCCESS) { + ByteWriteIO(KBC_DATA_REG, bData); // Write the data + } + } + + Status = KBC_WaitForInputBufferToBeFree(); // Wait for input buffer to be free + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SYSKBC_UpdateLEDState +// +// Description: This routine updates LEDs on Legacy keyboard +// +// Input: LED state data +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SYSKBC_UpdateLEDState ( + EFI_EMUL6064KBDINPUT_PROTOCOL* pThis, + UINT8 bData +) +{ +/* + UINT8 bCmd, + bKBData = 0, + bSave; + + // + // Wait for input buffer to be free + // + KBC_WaitForInputBufferToBeFree(); + KBC_WriteCommandByte(USB_SEND_COMMAND_TO_KBC); + bSave = ByteReadIO(KBC_STATUS_REG); + + // + // Data is pending. Read it in AL + // + if(bSave & BIT0) + { + bKBData = ByteReadIO(KBC_DATA_REG); + } + KBC_WriteCommandByte(0xAE); + KBC_WriteSubCommandByte(0xED); + KBC_ReadDataByte(); + KBC_WriteSubCommandByte(bData); + KBC_ReadDataByte(); + + if((bSave & BIT0) == 0) + { + return EFI_SUCCESS; + } + bCmd = 0xD2; + if(bSave & BIT5) + { + bCmd = 0xD3; + } + KBC_WriteKeyboardControllerData(bCmd, bKBData); +*/ + return EFI_SUCCESS; +} + +void +SYSKBC_GetAndStoreCCB() +{ + UINT8 bStatus, + bCmd, + bData = 0; + UINT8 Temp; + UINT8 Status; + + + // + //If Emulation Active disable the SMI Generation + // + if(gEmulationTrap) + gEmulationTrap->TrapDisable(gEmulationTrap); + + bStatus = ByteReadIO(KBC_STATUS_REG); + if(bStatus & BIT0) + { + bData = ByteReadIO(KBC_DATA_REG); + } + + Status = KBC_ReadKeyboardControllerData(0x20, &Temp); + if (Status == USB_SUCCESS) { + gUsbData->bCCB = Temp; + } + + if(bStatus & BIT0) + { + bCmd = 0xD2; + if(bStatus & BIT5) + { + bCmd = 0xD3; + } + KBC_WriteKeyboardControllerData(bCmd, bData); + } + // + //If Emulation Active Enable the SMI Generation + // + if(gEmulationTrap) + gEmulationTrap->TrapEnable(gEmulationTrap); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMSUpdateMouseInterface +// +// Description: This routine is called to enable or disable the mouse +// interface +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +/* +void USBMSUpdateMouseInterface() +{ + UINT8 bCmd = 0xA8; // Enable mouse interface + + if (!(gUsbData->bMouseStatusFlag & MOUSE_DATA_READY_BIT_MASK)) + { + if(gUsbData->fpMouseInputBufferHeadPtr != + gUsbData->fpMouseInputBufferTailPtr) + { + bCmd = 0xA7; // Disable mouse interface + } + } + KBC_WriteCommandByte(bCmd); // Send command to KBC + +} +*/ + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBMSSendMouseData +// +// Description: This routine is called to send the mouse data to the KB +// controller +// +// Input: Nothing +// +// Output: 0xFF data processed +// 0 data not processed +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 USBMSSendMouseData() +{ + UINT16 ebdaSeg = *(UINT16*)0x40E; + UINT8 bData; + UINT8 *ebda = (UINT8*)((UINTN)ebdaSeg<<4); + UINT8 packageSize = ebda[0x27] & 7; + UINT8 index=0; +/* + if (gUsbData->bMouseStatusFlag & MOUSE_DATA_READY_BIT_MASK) { + if (gUsbData->bCCB & 0x20) + { + gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0]; + gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0]; + return 0; + } else { + ebda[0x26] &= ~7; + KBC_WriteCommandByte(0xA7); // Disable mouse interface + } + } +*/ + if (gUsbData->fpMouseInputBufferHeadPtr == gUsbData->fpMouseInputBufferTailPtr) { + return 0; + } + + if ((gUsbData->bCCB & CCB_MOUSE_DISABLED) || + !(gUsbData->bCCB & CCB_MOUSE_INTRPT)) { + gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0]; + gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0]; + return 0; + } + + ebda[0x26] &= ~7; + +#if USB_MOUSE_UPDATE_EBDA_DATA + for (; index<packageSize; index++) { + ebda[0x28+index] = USBMouse_GetFromMouseBuffer(); + ebda[0x26]++; + } +#endif + bData = USBMouse_GetFromMouseBuffer(); + KBC_WriteKeyboardControllerData(0xD3, bData); // Send the last byte of data + + // + // Flag indicates data from USB mouse + // + //gUsbData->bMouseStatusFlag |= MOUSE_DATA_FROM_USB_BIT_MASK; + + // + // Indicate that first byte already sent + // + //gUsbData->bMouseStatusFlag &= ~(MOUSE_DATA_READY_BIT_MASK); + + //USBMSUpdateMouseInterface(); // Enable/disable mouse interface + + return 0xFF; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMouse_SendToMouseBuffer +// +// Description: This routine puts a byte into the mouse input buffer. +// Mouse input buffer pointers are also updated +// +// Input: bData - Byte to be put in the mouse input buffer +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +void +USBMouse_SendToMouseBuffer(UINT8 bData) +{ + *gUsbData->fpMouseInputBufferHeadPtr = bData; // Put the byte in the buffer + gUsbData->fpMouseInputBufferHeadPtr++; // Advance the buffer pointer + + // + // Check whether the buffer end is reached, if buffer end reached + // then position the buffer pointer to the start + // + if (gUsbData->fpMouseInputBufferHeadPtr == + (gUsbData->aMouseInputBuffer + sizeof(gUsbData->aMouseInputBuffer))) + { + gUsbData->fpMouseInputBufferHeadPtr = gUsbData->aMouseInputBuffer; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMouse_GetFromMouseBuffer +// +// Description: This routine retrieves a byte from the mouse input buffer. +// Mouse input buffer pointers are also updated +// +// Input: None +// +// Output: bData - Byte to be taken from the mouse input buffer +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 USBMouse_GetFromMouseBuffer () +{ + UINT8 bData = *gUsbData->fpMouseInputBufferTailPtr; + *gUsbData->fpMouseInputBufferTailPtr = 0; + gUsbData->fpMouseInputBufferTailPtr++; + + // + // Check whether the buffer end is reached, if buffer end reached + // then wrap around to the start + // + if (gUsbData->fpMouseInputBufferTailPtr == + (&gUsbData->aMouseInputBuffer[0] + sizeof(gUsbData->aMouseInputBuffer))) + { + gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0]; + } + return bData; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SYSKBC_SendKBCData +// +// Description: This routine is invoked periodically (every 8msec) to send +// USB keyboard and mouse data to the keyboard controller +// or to the keyboard controller emulation code +// +// Input: Nothing +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SYSKBC_SendKBCData() +{ + UINT8 bCmd = 0, + bTemp1 = 0, + bTemp = 0, + bFlag = 1; + UINT16 wTemp; +// UINT16 ebdaSeg = *(UINT16*)0x40E; +// UINT8 *ebda = (UINT8*)((UINTN)ebdaSeg<<4); +// UINT8 mouse_flag3; + UINT8 Status; + UINT8 Temp; + + //Is KBC access allowed? + if(IsKbcAccessBlocked) { + return EFI_NOT_READY; + } +// USBKBC_CheckAutoRepeat(); + + // + //If Emulation Active disable the SMI Generation + // + if(gEmulationTrap){ + if (!gEmulationTrap->TrapDisable(gEmulationTrap)) { + // Data is still pending. So don't push data. + goto enableRepeat_Exit; + } + } + + // + // Check whether BIOS is processing IRQ1 or IRQ12 + // + ByteWriteIO(0x20, 0xB); + if (ByteReadIO(0x20) & 2) { + goto enableRepeat_Exit; + } + + ByteWriteIO(0xA0, 0xB); + if (ByteReadIO(0xA0) & 0x10) { + goto enableRepeat_Exit; + } + + if (ByteReadIO(KBC_STATUS_REG) & BIT0){ + goto enableRepeat_Exit; + } + + for(;;) { + // + // Check the data transmit order + // + wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & + KBC_DATA_TX_ORDER_BIT_MASK); + if(wTemp == KBC_DATA_TX_ORDER_KB_FIRST) { + bFlag = 0; + bCmd = 0xD2; // Send keyboard data + // + // Check for keyboard data and then for mouse data + // + if(gUsbData->fpKBCCharacterBufferHead != + gUsbData->fpKBCCharacterBufferTail) + break; + // + // Check for mouse data + // + #if USB_DEV_MOUSE + bCmd = 0xD3; + if(gUsbData->fpMouseInputBufferHeadPtr != + gUsbData->fpMouseInputBufferTailPtr) + { + break; + } + #endif + bFlag = 1; + } else { + bFlag = 0; + #if USB_DEV_MOUSE + bCmd = 0xD3; + if(gUsbData->fpMouseInputBufferHeadPtr != + gUsbData->fpMouseInputBufferTailPtr) + { + // + // Check for keyboard data and then for mouse data + // + break; + } + #endif + // + // Check for keyboard data + // + bCmd = 0xD2; + if(gUsbData->fpKBCCharacterBufferHead != + gUsbData->fpKBCCharacterBufferTail) + break; + bFlag = 1; + } + break; + } + + if(bFlag) { + USB_DEBUG (DEBUG_LEVEL_8, "USBKBC_SendKBCData: Scan Code Buffer Empty \n"); + // + // Check whether the scan code buffer is empty + // + if(gUsbData->fpKBCScanCodeBufferPtr != gUsbData->aKBCScanCodeBufferStart) + { + goto enableRepeat_Exit; + } + // + // Get pointer to the HC driver + // Scan code buffer is empty. Stop the key repeat by stopping repeat TD + // + USB_DEBUG (DEBUG_LEVEL_8, "HCDDisableKeyRepeat \n"); + USBKeyRepeat(NULL, 1); // Disable Key repeat + + if(gEmulationTrap) { + gEmulationTrap->TrapEnable(gEmulationTrap); + } + return EFI_SUCCESS; + } + + for (;;) { + Status = KBC_WaitForInputBufferToBeFree(); + if (Status == USB_SUCCESS) { + ByteWriteIO(KBC_COMMAND_REG, USB_SEND_COMMAND_TO_KBC); + } else { + goto enableRepeat_Exit; + } + // + // Check the return status + // + do { + bTemp1 = ByteReadIO(KBC_STATUS_REG); + if(bTemp1 & BIT0) { + bFlag = 3 ; + break; + } + } while (bTemp1 & BIT1); + USB_DEBUG (DEBUG_LEVEL_8, "USBKBC_SendKBCData: bFlag %x\n",bFlag); + if (bFlag == 3) break; + // + // Update the data transmit order + // + gUsbData->wUSBKBC_StatusFlag = + (UINT16)((gUsbData->wUSBKBC_StatusFlag) + + (KBC_DATA_TX_ORDER_INC_VALUE)); + wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & + KBC_DATA_TX_ORDER_BIT_MASK); + if((wTemp & KBC_DATA_TX_ORDER_BIT_MASK) == 0) { + gUsbData->wUSBKBC_StatusFlag &= + ~((UINT16)KBC_DATA_TX_ORDER_BIT_MASK); + } + + // + // Get the CCB + // + Status = KBC_WriteCommandByte(0x20); // Send command to KBC + if (Status == USB_SUCCESS) { + Status = KBC_ReadDataByte(&Temp); // Get data from KBC + if (EFI_ERROR(Status)) { + goto enableRepeat_Exit; + } + gUsbData->bCCB = Temp; + } else { + goto enableRepeat_Exit ; + } + + // + // Check for mouse data + // + if((bCmd & 1) == 0) { + // + // Check whether keyboard is disabled + // + if((gUsbData->bCCB & CCB_KEYBOARD_DISABLED) == 0) { + // + // Check whether the current mode is IRQ + // Check whether password is enabled + // + if((gUsbData->wUSBKBC_StatusFlag & + KBC_PASSWORD_FLAG_BIT_MASK) == 0) + bTemp = USBKBC_GetFromCharacterBuffer(); + + if (bTemp == 0xff) { + goto enableRepeat_Exit; + } + KBC_WriteKeyboardControllerData(bCmd , bTemp); + USBKeyRepeat(NULL, 2); // Enable Key repeat + if (gEmulationTrap) { + gEmulationTrap->TrapEnable(gEmulationTrap); + } + return EFI_SUCCESS; + } + bTemp = 0xFF; + } else { + #if USB_DEV_MOUSE + if (USBMSSendMouseData()) { + USBKeyRepeat(NULL, 2); // Enable Key repeat + } + +/* + //(EIP57745+)> + // + // Check the version of CSM16, support is available for ver 7.64 or later + // + { + UINT8 MjCsmVer = *(UINT8*)0xF0018; + UINT8 MnCsmVer = *(UINT8*)0xF0019; + + if (MjCsmVer > 7 || MnCsmVer > 0x63) + { + mouse_flag3 = ebda[0x30] & 1; //check mouse driver + if(mouse_flag3) { + if(USBMSSendMouseData()) { + USBKeyRepeat(NULL, 2); // Enable Key repeat + } + } else { + gUsbData->fpMouseInputBufferHeadPtr = &gUsbData->aMouseInputBuffer[0]; + gUsbData->fpMouseInputBufferTailPtr = &gUsbData->aMouseInputBuffer[0]; + } + } + else + { + if(USBMSSendMouseData()) { + USBKeyRepeat(NULL, 2); // Enable Key repeat + } + } + } + //<(EIP57745+) +*/ + if(gEmulationTrap) + gEmulationTrap->TrapEnable(gEmulationTrap); + return EFI_SUCCESS; + #else + bTemp = 0xFF; + #endif + } + break; + } + + if(bFlag == 3) { + bTemp = 0xAE; + if(bTemp1 & 0x20) { // 0/1 = KB/Mouse data + #if USB_DEV_MOUSE + // + // Enable/disable mouse depending on the data + // + //USBMSUpdateMouseInterface(); + #endif + goto enableRepeat_Exit; + } + } + KBC_WriteCommandByte(bTemp); + +enableRepeat_Exit: + USBKeyRepeat(NULL, 2); // Enable Key repeat + if (gEmulationTrap) { + gEmulationTrap->TrapEnable(gEmulationTrap); + } + return EFI_NOT_READY; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SYSKBC_KbdInput_Send +// +// Description: This routine sends the Keyboard Data to Controller +// +// Input: +// IN EFI_EMUL6064KBDINPUT_PROTOCOL* This, +// IN UINT8* Data, +// IN UINT32 Count +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SYSKBC_KbdInput_Send( + IN EFI_EMUL6064KBDINPUT_PROTOCOL* This, + IN UINT8* Data, + IN UINT32 Count +) +{ + EFI_STATUS Status; + + if (Count == 0) { + return EFI_SUCCESS; + } + + do { + Status=SYSKBC_SendKBCData(); + Count--; + } while (Count != 0 && Status == EFI_SUCCESS); + + return Status; + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SYSKBC_MouseInput_Send +// +// Description: This routine sends the Mouse Data to Controller +// +// Input: +// IN EFI_EMUL6064MSINPUT_PROTOCOL* This, +// IN PS2MouseData* Data +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SYSKBC_MouseInput_Send( + IN EFI_EMUL6064MSINPUT_PROTOCOL* This, + IN PS2MouseData* Data +) +{ + return SYSKBC_SendKBCData(); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SendMouseData +// +// Description: This routine sends the Mouse Data to Local Mouse Buffer +// +// Input: +// IN PS2MouseData* Data +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SendMouseData( + IN PS2MouseData* Data +) +{ + USBMouse_SendToMouseBuffer(Data->flags); // Send status byte + USBMouse_SendToMouseBuffer(Data->x); // Send X-axis information + USBMouse_SendToMouseBuffer(Data->y); // Send Y-axis information + + // + // Check for 4-byte mouse data and send the 4th dummy data if needed + // + //if(gUsbData->bMouseStatusFlag & MOUSE_4BYTE_DATA_BIT_MASK) + //{ + // USBMouse_SendToMouseBuffer(0); + //} + // + // Set flag to indicate mouse data ready + // + //gUsbData->bMouseStatusFlag |= MOUSE_DATA_READY_BIT_MASK; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: SYSKBC_GetTranslation +// +// Description: This routine Get the KBC SCAN code transalation value +// +// Input: +// IN EFI_EMUL6064KBDINPUT_PROTOCOL* This, +// OUT KBC_KBDTRANSLATION* OutTrans +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SYSKBC_GetTranslation( + IN EFI_EMUL6064KBDINPUT_PROTOCOL* This, + OUT KBC_KBDTRANSLATION* OutTrans +) +{ + static BOOLEAN IsCcbLoaded = FALSE; + + if (!IsCcbLoaded) { + IsCcbLoaded = TRUE; + SYSKBC_GetAndStoreCCB(); + } + + *OutTrans = (gUsbData->bCCB & CCB_TRANSLATE_SCAN_CODE_BIT_MASK) != 0? + KBC_KBDTRANS_PCXT : KBC_KBDTRANS_AT; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_Scanner +// +// Description: This routine converts the USB keyboard input data into +// IBM PC format scan code +// +// Input: fpDevInfo Pointer to the device info. structure +// fpBuffer Pointer to the 8byte USB keyboard data +// +// Output: Nothing +// +// Notes: The format of the 8byte USB keyboard data is as follows: +//---------------------------------------------------------------------------- +// Byte Description +//---------------------------------------------------------------------------- +// Byte 0 Contains modifier key bits like SHIFT, CTRL, ALT etc +// Byte 1 Reserved +// Byte 2 - 7 Keycode (1-6) of the keys pressed +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_Scanner ( + DEV_INFO *fpDevInfo, + UINT8 *fpBuffer +) +{ + UINT8 bKeyCode; + UINT8 bValue; + UINT8 bTemp1; + + UINT16 wWorkOffset; + UINT16 wCount; + UINT16 wTemp; + + UINT8 *fptKBInputBuffer; + UINT8 *fptBuffer; + UINT8 *fPointer; + + fptKBInputBuffer = gUsbData->aKBInputBuffer ; + fptBuffer = (UINT8*)fpBuffer; + + // + // Convert the device address (1,2,3 .. 8) into + // device ID bit pattern (001h, 002h, 004h .. 080h) + // + gUsbData->bCurrentDeviceID = (UINT8)(1 << ((fpDevInfo->bDeviceAddress) -1)); + + bTemp1 = 0xE0; + wCount = 0x0; + bValue = (UINT8)(*fptBuffer); + + do { + if(bValue & 0x01) { + *fptKBInputBuffer = bTemp1; // Modifier key pressed. Send appropriate byte to the input buffer + ++fptKBInputBuffer; + } + bValue >>= 1; + ++bTemp1; + } while (bTemp1 <= 0xE7); + + // + // Discard the reserved byte from the USB KB input data stream + // + ++fptBuffer; + ++fptBuffer; + + // + // Process the remaining 6 input bytes + // + wCount = 6; + + do { + if(*fptBuffer) { + // + // Check whether the input is overrun. Overrun condition occurs if more than + // 6 keys are pressed at a same time. In that case, USB KB sends 01h in all + // its 6 key code bytes + // + if(*fptBuffer == 1) { // Keyboard error roll over (overrun) ? +// USB_DEBUG (DEBUG_LEVEL_5, "USBKB_Scanner: Overrun condition occur\n"); + // + // Check the space availability for the overrun code in the + // character buffer + // Overrun code needs 1 byte (0+1) + // + bTemp1 = USBKBC_CheckCharacterBufferFull(0); + if(bTemp1 == 0) { + return; + } + bTemp1 = 0xFF; // Scan code set 2 & 3 overrun code +#if USB_6064_TRAP +// +// The following routine returns overrun code depending upon the scan code +// set chosen. This facility is available only when 60/64h port trapping +// is enabled. Otherwise the scan code set is locked to set 2. +// + bTemp1 = USBTrap_GetOverrunCode(); +#endif + USBKBC_SendToCharacterBuffer(bTemp1); + // + // Invalidate the last key code processed data + // +// gUsbData->bLastUSBKeyCode = 0x00; //(EIP102150-) + return; + } + else { + *fptKBInputBuffer = *fptBuffer; + ++fptKBInputBuffer; + ++fptBuffer; + } + } + else { + ++fptBuffer; + } + --wCount; + } while (wCount); + + *fptKBInputBuffer = 0; // Null terminate the input buffer + ++fptKBInputBuffer; + + // + // Check for break code generation condition + // + wCount = (UINT16)(fptKBInputBuffer - gUsbData->aKBInputBuffer); + fptKBInputBuffer = gUsbData->aKBInputBuffer; + bValue = 0; + // + // wCount = Length of the buffer + // + while(wCount) { + if (*fptKBInputBuffer) + break; + ++fptKBInputBuffer; + --wCount; + } + + if(!wCount) { + // + // No key pressed. Set flags to generate break code + // + gUsbData->bBreakCodeDeviceID |= gUsbData->bCurrentDeviceID; + } + + fptKBInputBuffer = gUsbData->aKBInputBuffer; + //(EIP60380-)> +/* + // + // Check and load typematic rate setting + // + wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK); + wTemp >>= KBC_TYPE_DELAY_BIT_SHIFT; + gUsbData->wRepeatRate = aTypematicRateDelayTable[wTemp]; + gUsbData->wRepeatCounter = 0; +*/ + //<(EIP60380-) +// +// Save the keycode in the local variable +// +UKS_KeyCodeGenerateLoop: + + bKeyCode = *fptKBInputBuffer; + ++fptKBInputBuffer; + + if(bKeyCode) { // Check end of the list + // + // Get scan code buffer size + // + wCount = (UINT16)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); + bTemp1 = 0; + + while(wCount) { + if(bKeyCode == gUsbData->aKBCScanCodeBufferStart[bTemp1]) { + gUsbData->aKBCDeviceIDBufferStart[bTemp1] |= + gUsbData->bCurrentDeviceID; + goto UKS_KeyCodeGenerateLoop; + } + ++bTemp1; + --wCount; + }; + if(bTemp1 >= sizeof (gUsbData->aKBCScanCodeBufferStart)) + goto UKS_CheckBreakCodeGen; + // + // The key code is not in the buffer and also the buffer is not full. So + // generate the make code for the newly pressed key. + // + USBKB_GenerateScanCode(USB_GEN_MAKE_CODE, bKeyCode, 0); +// gUsbData->bLastUSBKeyCode = bKeyCode; //(EIP102150-) + gUsbData->aKBCScanCodeBufferStart[bTemp1] = bKeyCode; + // + // Store the device ID + // + gUsbData->aKBCDeviceIDBufferStart[bTemp1] = gUsbData->bCurrentDeviceID; + // + // Store the shift key status + // + gUsbData->aKBCShiftKeyStatusBufferStart[bTemp1] = gUsbData->bUSBKBShiftKeyStatus; + ++(gUsbData->fpKBCScanCodeBufferPtr); // Update pointer index + //(EIP60380+)> + // + // Check and load typematic rate setting + // + wTemp = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK); + wTemp >>= KBC_TYPE_DELAY_BIT_SHIFT; + gUsbData->wRepeatRate = aTypematicRateDelayTable[wTemp]; + gUsbData->wRepeatCounter = 0; + //<(EIP60380+) + goto UKS_KeyCodeGenerateLoop; + } +UKS_CheckBreakCodeGen: + --fptKBInputBuffer; + + fPointer = (UINT8*)(gUsbData->aKBCScanCodeBufferStart); + wTemp = (UINT16)(fptKBInputBuffer - gUsbData->aKBInputBuffer); + +UKS_ProcessNextCharacter: + if(fPointer >= gUsbData->fpKBCScanCodeBufferPtr) + goto UKS_BreakCodeGenCompleted; + + bKeyCode = *fPointer; + ++fPointer; + + fptKBInputBuffer = gUsbData->aKBInputBuffer; + wCount = wTemp; + while(wCount) { + if(bKeyCode == *fptKBInputBuffer) + goto UKS_ProcessNextCharacter; + + ++fptKBInputBuffer; + --wCount; + } + + --fPointer; + wWorkOffset = (UINT16)(fPointer - gUsbData->aKBCScanCodeBufferStart); + + gUsbData->aKBCDeviceIDBufferStart[wWorkOffset] &= ~((UINT8)(gUsbData->bCurrentDeviceID)); + if(gUsbData->aKBCDeviceIDBufferStart[wWorkOffset] ) { + ++fPointer; + goto UKS_ProcessNextCharacter; + } + bValue = gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset]; + gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] = + gUsbData->bUSBKBShiftKeyStatus; + gUsbData->bUSBKBShiftKeyStatus = bValue; + USBKB_GenerateScanCode(USB_GEN_BREAK_CODE,(UINT8)*fPointer, wWorkOffset); + // + // Restore shift key status + // + bValue = gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset]; + gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] = gUsbData->bUSBKBShiftKeyStatus; + gUsbData->bUSBKBShiftKeyStatus = bValue; + bValue = *fPointer; + USBKB_DiscardCharacter(&gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset]); + + --(gUsbData->fpKBCScanCodeBufferPtr); + // + // Stop auto repeat + // +// gUsbData->bLastUSBKeyCode = 0; //(EIP102150-) + goto UKS_ProcessNextCharacter; +UKS_BreakCodeGenCompleted: + gUsbData->bBreakCodeDeviceID &= ~((UINT8)(gUsbData->bCurrentDeviceID)); + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_Scanner: End\n"); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_GenerateScanCode +// +// Description: This routine generates the make/break code for th key +// pressed depending on the make/break flag +// +// Input: bCodeGenFlag Flag indicating whether it is a make or +// break code sequence +// bKeyCode USB key code for the key pressed +// wWorkOffset Offset into the buffers which has the +// code we are processing +// +// Output: 0xFFFF -on success , 0 on error +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_GenerateScanCode ( + UINT8 bCodeGenFlag, + UINT8 bKeyCode, + UINT16 wWorkOffset) +{ + UINT8 bMakeCode, + bTemp = 0, + bValue; + UINT16 wScanCode, + wTemp; + UINT8 *fPointer; + UINT8 ScanCodeCount; //(EIP102150+) + UINT16 i=0; //(EIP102150+) + +USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: bKeyCode %x:\n",bKeyCode); + + // + // Set the flag to indicate that make code is generated + // + gUsbData->wUSBKBC_StatusFlag &= ~((UINT16) KBC_MK_BRK_CODE_BIT_MASK); + + // + // Set the approprate flag indicating make or break code sequence + // + if (bCodeGenFlag != USB_GEN_MAKE_CODE) + { + // + // Set the flag to indicate that break code is generated + // + gUsbData->wUSBKBC_StatusFlag |= KBC_MK_BRK_CODE_BIT_MASK; + } + + // + // Save the current USB key code + // + gUsbData->bCurrentUSBKeyCode = bKeyCode; + + // + // Convert the USB key code into scan code (Set 2) + // + bMakeCode = USBKB_ConvertUSBKeyCodeToScanCodeSet2(bKeyCode); + USB_DEBUG (DEBUG_LEVEL_8, "USBKB_GenerateScanCode: bMakeCode %x:\n",bMakeCode); + + // + // Save the make code in the temporary variable + // + gUsbData->bSet2ScanCode = bMakeCode; + // + // Check whether any modifier keys (ALT, CTRL & SHIFT) are pressed + // + wScanCode = USBKB_CheckModifierKeyPress(bMakeCode); + wTemp = (UINT16)(wScanCode >> 8); + + if(wTemp) + { + // + // Check whether it is a make or break code generation + // + if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) + { + // + // Generating the break code, so clear the modifier status. + // Check for left/right shift key press + // + if(!(wTemp & (KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK))) + { + fPointer = gUsbData->fpKBCScanCodeBufferPtr ; + + while(fPointer != (gUsbData->aKBCScanCodeBufferStart)) + { + --fPointer; // Decrement scan code buffer pointer + bTemp = USBKB_ConvertUSBKeyCodeToScanCodeSet2(*fPointer); + if(bTemp == (wScanCode & 0xFF)) + { + break; + } + } + } + + if(bTemp != (wScanCode & 0xFF) || + (wTemp & (KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK))) + { + wTemp = (UINT16)(~wTemp); + gUsbData->bUSBKBShiftKeyStatus &= wTemp; + gUsbData->aKBCShiftKeyStatusBufferStart[wWorkOffset] &= wTemp; + } + } + else + { + gUsbData->bUSBKBShiftKeyStatus |= wTemp; // Set proper bits + } + } + +#if USB_KBC_EMULATION + bScanNum = USBTrap_GetCurrentScanCodeSetNumber(); + if(bScanNum == 3) + { + USBTrap_ProcessScanCodeSet3(); + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 1.\n"); + return; + } +#endif + // + // Check and process pause key + // + if(gUsbData->bSet2ScanCode == PAUSE_KEY ) + { +// +// It is scan code for pause key. No need to auto repeat pause key and +// also pause key doesn't have break key. Check the above two conditions +// and take care of them properly +// + // + // Check whether it is to generate make or break code + // + if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) + { + USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 2.\n"); + return; + } +// +// It is not a break code check whether it is for auto repeat +// Compare old key code and the current key code +// + //(EIP102150+)> + ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); + for (i = 0; i < ScanCodeCount; i++) { + if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) && + (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) { + return; + } + } + //<(EIP102150+) +// +// Pause key can have +// 4 bytes of make code for scan code set 1, if CTRL key is also pressed +// 5 bytes of make code for scan code set 2, if CTRL key is also pressed +// 6 bytes of make code for scan code set 1, if CTRL key is not pressed +// 8 bytes of make code for scan code set 2, if CTRL key is not pressed +// 0 bytes if it is a break code for pause key. +// The above conditions are handled generically using two tables +// pScanCodeLengthTable_4500 & pScanCodeLengthTable_6800. If CTRL key is +// pressed then _4500 table will be used or else _6800 table will be used. +// The logic in the later stage of the code can then choose one entry from +// this table depending on whether it is make or break code and whether +// it is for scan code set 1 or 2. +// + fPointer = aScanCodeLengthTable_4500; // CTRL + PAUSE + if((gUsbData->bUSBKBShiftKeyStatus & + KB_CTRL_KEY_BIT_MASK) == 0) + fPointer = aScanCodeLengthTable_6800; // PAUSE + } + else + if(gUsbData->bSet2ScanCode == PRINT_SCREEN ) + { +/*--- + Print screen key can have + 1 bytes of make code for scan code set 1, if pressed with ALT key + 1 bytes of make code for scan code set 2, if pressed with ALT key + 1 bytes of break code for scan code set 1, if pressed with ALT key + 2 bytes of break code for scan code set 2, if pressed with ALT key + 2 bytes of make code for scan code set 1, if pressed with CTRL+SFT key + 2 bytes of make code for scan code set 2, if pressed with CTRL+SFT key + 2 bytes of break code for scan code set 1, if pressed with CTRL+SFT key + 4 bytes of make code for scan code set 1, if no other key is pressed + 4 bytes of make code for scan code set 2, if no other key is pressed + 4 bytes of break code for scan code set 1, if no other key is pressed + 6 bytes of break code for scan code set 2, if no other key is pressed + The above conditions are handled generically using three tables + pScanCodeLengthTable_1112, pScanCodeLengthTable_2223 + & pScanCodeLengthTable_4446. If ALT key is pressed then _1112 table + will be used. If CTRL key is pressed then _2223 table will be used or + else _4446 table will be used. + The logic in the later stage of the code can then choose one entry from + this table depending on whether it is make or break code and whether + it is for scan code set 1 or 2. +---*/ + if(gUsbData->bUSBKBShiftKeyStatus & + KB_ALT_KEY_BIT_MASK) + fPointer = aScanCodeLengthTable_1112; + else if(gUsbData->bUSBKBShiftKeyStatus & + ( KB_CTRL_KEY_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) + fPointer = aScanCodeLengthTable_2223; + else + fPointer = aScanCodeLengthTable_4446; + + /* fPointer = aScanCodeLengthTable_1112; + if((gUsbData->bUSBKBShiftKeyStatus & KB_ALT_KEY_BIT_MASK) == 0) + { + fPointer = aScanCodeLengthTable_2223; + if((gUsbData->bUSBKBShiftKeyStatus & (KB_NUM_LOCK_BIT_MASK + KB_LSHIFT_KEY_BIT_MASK + KB_RSHIFT_KEY_BIT_MASK)) == 0) + { + fPointer = aScanCodeLengthTable_4446; + bTemp = (UINT8)USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode); + if(bTemp) + { +// goto UKGSC_NotANumericKeyPadKey; + } + fPointer = aScanCodeLengthTable_2223; + if(gUsbData->bUSBKBShiftKeyStatus & (KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) + { + fPointer = aScanCodeLengthTable_4446; + if((gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK) == 0) + { + if((gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK) == 0) + { + fPointer = aScanCodeLengthTable_4545; + } + } + } + } + } */ + } + else + { + wScanCode = USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode); + wTemp = (UINT16)(wScanCode & 0xFF); + if(!wTemp) + { + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Extended Key Pressed\n"); + +/*--- + It is a numeric key pad key. It can have + if no key is pressed or (NUMLOCK is ENABLED and SHIFT key is pressed) + 2 bytes of make code for scan code set 1 + 2 bytes of make code for scan code set 2 + 2 bytes of break code for scan code set 1 + 3 bytes of break code for scan code set 2 + if NUMLOCK is ENABLED + 4 bytes of make code for scan code set 1 + 4 bytes of make code for scan code set 2 + 4 bytes of break code for scan code set 1 + 6 bytes of break code for scan code set 2 + if pressed with SHIFT key + 4 bytes of make code for scan code set 1 + 5 bytes of make code for scan code set 2 + 4 bytes of break code for scan code set 1 + 5 bytes of break code for scan code set 2 + The above conditions are handled generically using three tables + pScanCodeLengthTable_2223, pScanCodeLengthTable_4446 + & pScanCodeLengthTable_4545. If no other key is pressed then _2223 table + will be used. If NUMLOCK is enabled then _4446 table will be used or + else _4545 table will be used. + The logic in the later stage of the code can then choose one entry from + this table depending on whether it is make or break code and whether + it is for scan code set 1 or 2. +---*/ + //(EIP27889)> + if( (!(gUsbData->bUSBKBShiftKeyStatus & + ( KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK))) || + ((gUsbData->bUSBKBShiftKeyStatus & + ( KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK)) == + ( KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK)) || + ((gUsbData->bUSBKBShiftKeyStatus & + ( KB_NUM_LOCK_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) == + ( KB_NUM_LOCK_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) ) + fPointer = aScanCodeLengthTable_2223; + //<(EIP27889) + else if(gUsbData->bUSBKBShiftKeyStatus & + KB_NUM_LOCK_BIT_MASK) + { + //(EIP102150+)> + fPointer = aScanCodeLengthTable_4446; + if (!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)) { + ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); + for (i = 0; i < ScanCodeCount; i++) { + if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) && + (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) { + fPointer = aScanCodeLengthTable_2223; + break; + } + } + } + //<(EIP102150+) + } + else + fPointer = aScanCodeLengthTable_4545; + } + else + { + // UKGSC_NotANumericKeyPadKey +/*--- + The extended keys will have + 2 bytes of make code for scan code set 1 + 2 bytes of make code for scan code set 2 + 2 bytes of break code for scan code set 1 + 3 bytes of break code for scan code set 2 +---*/ + wScanCode = USBKB_CheckForExtendedKey(gUsbData->bSet2ScanCode); + if(!(wScanCode & 0xff)) + fPointer = aScanCodeLengthTable_2223; + else if(gUsbData->bSet2ScanCode == SLASH_KEY) + { +/*--- + The slash key will normally have + 2 bytes of make code for scan code set 1 + 2 bytes of make code for scan code set 2 + 2 bytes of break code for scan code set 1 + 3 bytes of break code for scan code set 2 + But if pressed with slash key it has + 4 bytes of make code for scan code set 1 + 5 bytes of make code for scan code set 2 + 4 bytes of break code for scan code set 1 + 5 bytes of break code for scan code set 2 +---*/ + if(!(gUsbData->bUSBKBShiftKeyStatus & + (KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK))) + fPointer = aScanCodeLengthTable_2223; + else + fPointer = aScanCodeLengthTable_4545; + } + else // UKGSC_NotSlashKey: + /*--- + Regular keys will have + 1 bytes of make code for scan code set 1 + 1 bytes of make code for scan code set 2 + 1 bytes of break code for scan code set 1 + 2 bytes of break code for scan code set 2 + ---*/ + fPointer = aScanCodeLengthTable_1112; + } + } + // + // Find the appropriate scan code length from the table + // bOffset = Offset in the table + // + bValue = 0; // Assume make code for set 1 + + // + // Check whether to generate make or break code + // + if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) + { + bValue = 2; + } + // + // Check whether to generate set 1 scan code or set 2 + // + if((gUsbData->bCCB & CCB_TRANSLATE_SCAN_CODE_BIT_MASK) == 0 ) + { + ++bValue; // Update offset (for scan code set 2) + } + + bValue = fPointer[bValue]; + + bValue = USBKBC_CheckCharacterBufferFull(bValue); + + if (!bValue) return; + + // + // We had found out correct scan code length to generate and also we + // verified we have enough space. Now generate the scan code + // + bValue = gUsbData->bSet2ScanCode; + + if(bValue == PAUSE_KEY ) + { + // + // Check whether CTRL key is pressed + // + if(!(gUsbData->bUSBKBShiftKeyStatus & KB_CTRL_KEY_BIT_MASK)) + { + // + // Pause key scan code generation + // + USBKBC_SendToCharacterBuffer(0x0E1); + gUsbData->bSet2ScanCode = 0x14; + USBKB_GenerateType1MakeCode(); + gUsbData->bSet2ScanCode = 0x77; + USBKB_GenerateType1MakeCode(); + USBKBC_SendToCharacterBuffer(0xE1); + gUsbData->bSet2ScanCode = 0x14; + USBKB_GenerateType1BreakCode(); + gUsbData->bSet2ScanCode = 0x77; + USBKB_GenerateType1BreakCode(); + return; + } + else + { + gUsbData->bSet2ScanCode = 0x7E; + USBKB_GenerateType2MakeCode(); + USBKB_GenerateType2BreakCode(); + } + + } + else if(bValue == PRINT_SCREEN ) + { + gUsbData->bSet2ScanCode = 0x7C; // PRNSCRN for scan code set 2 + // + // Check for ALT+PRNSCRN key combination + // + if(!(gUsbData->bUSBKBShiftKeyStatus & KB_ALT_KEY_BIT_MASK )) + { + // + // Check for CTRL or SHIFT+PRNSCRN key combination + // + if(!(gUsbData->bUSBKBShiftKeyStatus & + (KB_CTRL_KEY_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK))) + { + UKGSC_KeyCombination2: +// +// Process PRNSCRN only key processing, NUMLOCK + any numeric key press +// processing at this point. Generate either (E0,12,E0,xx) or +// (E0,F0,xx,E0,F0,12). Where xx bSet2ScanCode +// + // + // Check whether to generate make or break code + // + if(!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)) + { + bTemp = gUsbData->bSet2ScanCode; + gUsbData->bSet2ScanCode = 0x12; + USBKB_GenerateType2MakeCode(); + gUsbData->bSet2ScanCode = bTemp; + USBKB_GenerateType2MakeCode(); + USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 5.\n"); + return; + + } + else + { + USBKB_GenerateType2BreakCode(); + gUsbData->bSet2ScanCode = 0x12; + USBKB_GenerateType2BreakCode(); + USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 6.\n"); + return; + } + } + else + goto UKGSC_KeyCombination1; + + } + else + { + gUsbData->bSet2ScanCode = 0x84; +UKGSC_ProcessRegularKey: +// +// Regular key press make & break code generation (xx or 0F0h, xx) +// Check whether to generate make or break code +// + if((gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK ) == 0) + { + USBKB_GenerateType1MakeCode(); + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 7.\n"); + return; + } + USBKB_GenerateType1BreakCode(); + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Return 8.\n"); + return; + } + + } + else + { + // + // Check for numeric key pad keys + // + wScanCode = USBKB_CheckForNumericKeyPadKey(gUsbData->bSet2ScanCode); + wTemp = (UINT16)(wScanCode & 0xFF); + if(wTemp == 0) + { + gUsbData->bSet2ScanCode &= 0x7F; + //(EIP27889)> + if( (!(gUsbData->bUSBKBShiftKeyStatus & + (KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK))) || + ((gUsbData->bUSBKBShiftKeyStatus & + ( KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK)) == + ( KB_NUM_LOCK_BIT_MASK + + KB_LSHIFT_KEY_BIT_MASK)) || + ((gUsbData->bUSBKBShiftKeyStatus & + ( KB_NUM_LOCK_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) == + ( KB_NUM_LOCK_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK)) ) + //<(EIP27889) + goto UKGSC_KeyCombination1; + + if(gUsbData->bUSBKBShiftKeyStatus & KB_NUM_LOCK_BIT_MASK) + //(EIP102150+)> + { + if (!(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK)) { + ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); + for (i = 0; i < ScanCodeCount; i++) { + if ((gUsbData->aKBCDeviceIDBufferStart[i] & gUsbData->bCurrentDeviceID) && + (gUsbData->bCurrentUSBKeyCode == gUsbData->aKBCScanCodeBufferStart[i])) { + goto UKGSC_KeyCombination1; + } + } + } + goto UKGSC_KeyCombination2; + } + //<(EIP102150+) +UKGSC_KeyCombination3: +// +// The following code will generate scan code for SHIFT+Numeric key pad +// key combination. It will generate one of the following sequence +// (0E0h, 0F0h, 012H or 059h, 0E0h, xx) or +// (0E0h, 0F0h, xx, 0E0h, 012H or 059h) +// + if((gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) == 0) + { + // + // Check whether to generate make or break code + // + bTemp = gUsbData->bSet2ScanCode; + if(gUsbData->bUSBKBShiftKeyStatus & KB_LSHIFT_KEY_BIT_MASK) + { + gUsbData->bSet2ScanCode = 0x12; // Save current scan code (xx) + USBKB_GenerateType2BreakCode(); // 0E0h, 0F0h, 012h + } + if(gUsbData->bUSBKBShiftKeyStatus & KB_RSHIFT_KEY_BIT_MASK) + { + gUsbData->bSet2ScanCode = 0x59; + USBKB_GenerateType2BreakCode(); // 0E0h, 0F0h, 059h + } + gUsbData->bSet2ScanCode = bTemp; // Restore current code (xx) + USBKB_GenerateType2MakeCode(); // 0E0h, xx + USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 9.\n"); + return; + } + else + { + USBKB_GenerateType2BreakCode(); + if(gUsbData->bUSBKBShiftKeyStatus & KB_RSHIFT_KEY_BIT_MASK) + { + gUsbData->bSet2ScanCode = 0x59; // Save current scan code (xx) + USBKB_GenerateType2MakeCode(); // 0E0h, 59h + } + if(gUsbData->bUSBKBShiftKeyStatus & KB_LSHIFT_KEY_BIT_MASK) + { + gUsbData->bSet2ScanCode = 0x12; // Save current scan code (xx) + USBKB_GenerateType2MakeCode(); // 0E0h, 12h + } + USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateScanCode: Return 10.\n"); + return; + } + } + else + { + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Notnumeric key\n"); + // + // Check and process extended key press + // + bValue = (UINT8)USBKB_CheckForExtendedKey(gUsbData->bSet2ScanCode); + if(bValue == 0) + { + gUsbData->bSet2ScanCode &= 0x7F; +UKGSC_KeyCombination1: +// +// Following code processes the following key combinations: +// Extended key make & break code generation +// CTRL or SHIFT + PRNSCRN key combination +// Numeric key pad key code generation +// One of the following sequence will be generated (0E0h, xx) or +// (0E0h, 0F0h, xx) +// + if(gUsbData->wUSBKBC_StatusFlag & KBC_MK_BRK_CODE_BIT_MASK) + { + USBKB_GenerateType2BreakCode(); + return; + } + USBKB_GenerateType2MakeCode(); + return; + } + else + { + // + // Check and process '/' key + // + if (gUsbData->bSet2ScanCode != SLASH_KEY) + { + USB_DEBUG (DEBUG_LEVEL_7, "USBKB_GenerateScanCode: Regular Key.\n"); + goto UKGSC_ProcessRegularKey; + } + // + // Generate make or break code for '/' key + // + gUsbData->bSet2ScanCode = 0x4A; + if(!(gUsbData->wUSBKBC_StatusFlag & + ( KB_LSHIFT_KEY_BIT_MASK + + KB_RSHIFT_KEY_BIT_MASK))) + goto UKGSC_KeyCombination1; + goto UKGSC_KeyCombination3; + return; + } + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_UpdateLEDState +// +// Description: This routine is used to update the LED state between the +// USB & PS/2 keyboard +// +// Input: bFlag Indicates how the LED local variables are adjusted +// +// Output: Nothing +// +// NOTE: This routine is not executed during EFI phase +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_UpdateLEDState (UINT8 bFlag) +{ + UINT8 bLStatus, + bHStatus; + + UINT8* fPtr; + + fPtr = (UINT8*)(UINTN)0x417; + // + // Make sure the password LED status is not changed. If KBC password is + // enabled then the LED state for NUMLOCK should be off, SCROLL-LOCK LED + // state should be on and CAPSLOCK LED state is in dont-care state. + // + bLStatus = gUsbData->bNonUSBKBShiftKeyStatus; + bLStatus &= 0x07 ; // Masking BIT0, BIT1 and BIT2 + if (bLStatus & 1) + { + // + // None of the LED is ON. Make Scroll LOCK LED to be ON + // + bLStatus = 0x04; + } + else + { + bLStatus >>= 1; + } + + gUsbData->bNonUSBKBShiftKeyStatus &= 0xF8; + gUsbData->bNonUSBKBShiftKeyStatus |= bLStatus; + + // + // Check whether password is disabled + // + if (gUsbData->wUSBKBC_StatusFlag & KBC_PASSWORD_FLAG_BIT_MASK) + { + bHStatus = (UINT8)(gUsbData->bUSBKBShiftKeyStatus & 0x70); + bLStatus = (UINT8)((gUsbData->bNonUSBKBShiftKeyStatus & 0x07) << 0x04); + + if(bHStatus == bLStatus) + { + return; + } + gUsbData->bUSBKBShiftKeyStatus &= + ~ (KB_CAPS_LOCK_BIT_MASK + + KB_NUM_LOCK_BIT_MASK + + KB_SCROLL_LOCK_BIT_MASK); + + gUsbData->bUSBKBShiftKeyStatus |= bLStatus; + // + // Check whether SCROLL-LOCK is ON + // + bLStatus = (UINT8)(bLStatus >> 3); + if(bLStatus & 0x08) + { + bLStatus ^= 0x09; + } + // + // ScrollOff + // + USBKB_LEDOn(); + return; + } + + // + // Get the current PS/2 keyboard LED state + // +// USB_DEBUG(DEBUG_LEVEL_5, "USBKB_UpdateLEDState : [0:417] = %x\n", *fPtr); + bLStatus = (UINT8)(((*fPtr) & 0x70) >> 1); + bHStatus = (UINT8)((gUsbData->bUSBKBShiftKeyStatus) & 0x70); + if(bLStatus & 0x08) + bLStatus ^= 0x48; + + if(bLStatus == bHStatus) + return; + + gUsbData->bUSBKBShiftKeyStatus &= + ~ (KB_CAPS_LOCK_BIT_MASK + + KB_NUM_LOCK_BIT_MASK + + KB_SCROLL_LOCK_BIT_MASK); + + gUsbData->bUSBKBShiftKeyStatus |= bLStatus; + USBKB_LEDOn(); + + return; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_LEDOn +// +// Description: This routine updates the keyboard LED status for all the +// USB keyboards present in the sytem +// +// Input: Nothing +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBKB_LEDOn( +) +{ + UINT8 LByte; + UINT8 Count; + DEV_INFO* DevInfo; + EFI_STATUS Status; + // + // Set the LED update progress status + // + gUsbData->bUSBKBC_ExtStatusFlag |= KBCEXT_LED_UPDATE_IN_PROGRESS_BIT; + + // + // Get the current USB LED status + // + USB_DEBUG(DEBUG_LEVEL_7, "USBKB_LEDOn: LedStatus %x\n", gUsbData->bUSBKBShiftKeyStatus); + // + // Form the byte to be transmitted to the USB keyboard + // + LByte = (UINT8)(((gUsbData->bUSBKBShiftKeyStatus) >> 4) & 0x07); + USB_DEBUG(DEBUG_LEVEL_4, "USBKB_LEDOn: LedStatus %x, bLByte %x\n", + gUsbData->bUSBKBShiftKeyStatus, LByte); + + // + // Update LED status in every USB keyboard on the system + // + for(Count = 0; Count < USB_DEV_HID_COUNT; Count++) { + DevInfo = gUsbData->aUSBKBDeviceTable[Count]; + if (DevInfo != NULL) { + Status = UsbDevInfoValidation(DevInfo); + if (EFI_ERROR(Status)) { + return; + } + UsbKbdSetLed(DevInfo, LByte); + } + } + // + // Reset the LED update progress status + // + gUsbData->bUSBKBC_ExtStatusFlag &= ~(KBCEXT_LED_UPDATE_IN_PROGRESS_BIT); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_ConvertSet2CodeToSet1Code +// +// Description: Converts the set 2 scan code to set 1 scan code +// +// Input: bScanCode Set 2 scan code +// +// Output: Set 1 scan code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBKB_ConvertSet2CodeToSet1Code(UINT8 bScanCode) +{ + return USBKB_ConvertScanCodeBetweenCodeSet( + bScanCode, + aStaticSet2ToSet1ScanCode); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_ConvertScanCodeBetweenCodeSet +// +// Description: Converts the set 2 scan code to set 3/1 scan code +// +// Input: bScanCode Set 2 scan code +// bConvTable Pointer to the code set conversion table +// +// Output: Set 1/3 scan code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBKB_ConvertScanCodeBetweenCodeSet( + UINT8 bScanCode, + UINT8 *fPointer +) +{ + UINT8 bValue; + // + // Load the parameter from the stack to register + // + bScanCode = fPointer[bScanCode]; + bScanCode = (UINT8)((bScanCode << 4) | (bScanCode >> 4)); + bValue = (UINT8)((bScanCode & 0x80) >> 7); + bScanCode = (UINT8)(~((bScanCode << 1) | bValue)); + return bScanCode; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_GenerateType1MakeCode +// +// Description: This routine generates the type 1 make code for the byte +// in the variable bSet2ScanCode +// +// Input: bSet2ScanCode - Byte containing the scan code +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_GenerateType1MakeCode() +{ + UINT8 bValue =0; + +// USB_DEBUG (DEBUG_LEVEL_5, "USBKB_GenerateType1MakeCode"); +#if USB_KBC_EMULATION + bValue = USBTrap_GetCurrentScanCodeSetNumber(); +#endif +// Check whether conversion (from set 2 to set 1) is opted + if(bValue != 1) + { + if(((UINT32)(gUsbData->bCCB) & (UINT32)CCB_TRANSLATE_SCAN_CODE_BIT_MASK ) == 0) + { + USBKBC_SendToCharacterBuffer(gUsbData->bSet2ScanCode); + return; + } + } + bValue = USBKB_ConvertSet2CodeToSet1Code(gUsbData->bSet2ScanCode); + + USBKBC_SendToCharacterBuffer(bValue); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_GenerateType1BreakCode +// +// Description: This routine generates the type 1 break code for the byte +// in the variable bSet2ScanCode +// +// Input: bSet2ScanCode - Byte containing the scan code +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_GenerateType1BreakCode() +{ + UINT8 bValue =0; + + USB_DEBUG (DEBUG_LEVEL_8, "USBKB_GenerateType1BreakCode \n"); + +#if USB_KBC_EMULATION + bValue = USBTrap_GetCurrentScanCodeSetNumber(); +#endif + // + // Check whether conversion (from set 2 to set 1) is opted + // + if(bValue != 1) + { + if(((UINT32)(gUsbData->bCCB) & (UINT32)CCB_TRANSLATE_SCAN_CODE_BIT_MASK ) == 0) + { + USBKBC_SendToCharacterBuffer(0xF0); + USBKBC_SendToCharacterBuffer(gUsbData->bSet2ScanCode); + return; + } + } + bValue = USBKB_ConvertSet2CodeToSet1Code(gUsbData->bSet2ScanCode); + bValue |= 0x80; + USBKBC_SendToCharacterBuffer(bValue); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_GenerateType2MakeCode +// +// Description: This routine generates the type 2 make code for the byte +// in the variable bSet2ScanCode +// +// Input: bSet2ScanCode - Byte containing the scan code +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_GenerateType2MakeCode() +{ + USBKBC_SendToCharacterBuffer(0xE0); + USBKB_GenerateType1MakeCode(); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_GenerateType2BreakCode +// +// Description: This routine generates the type 2 break code for the byte +// in the variable bSet2ScanCode +// +// Input: bSet2ScanCode - Byte containing the scan code +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_GenerateType2BreakCode() +{ + USBKBC_SendToCharacterBuffer(0xE0); + USBKB_GenerateType1BreakCode(); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBTrap_GetCurrentScanCodeSetNumber +// +// Description: Returns the current scan code set number +// +// Input: Nothing +// +// Output: Scan code set number (1, 2 or 3) +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBTrap_GetCurrentScanCodeSetNumber() +{ + UINT16 wStatus; + wStatus = (UINT16)(gUsbData->wUSBKBC_StatusFlag & KBC_SCAN_CODE_SET_BIT_MASK); + wStatus >>= KBC_SCAN_CODE_SET_BIT_SHIFT; + + return (UINT8)wStatus; + +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBTrap_GetOverrunCode +// +// Description: Returns the overrun code depending on the current +// scan code set +// +// Input: Nothing +// +// Output: Overrun code +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBTrap_GetOverrunCode() +{ + return 0xFF; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_DiscardCharacter +// +// Description: This routine discards the top character in the scan +// code buffer, keyboard status flag buffer and device ID +// buffer +// +// Input: fPointer Points to the keyboard status flag buffer +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKB_DiscardCharacter (UINT8* fPointer) +{ + UINT8 bCount; + UINT32 dCount = 0; + UINT8* fPtrEnd; + + fPtrEnd = gUsbData->aKBCShiftKeyStatusBufferStart + + sizeof (gUsbData->aKBCShiftKeyStatusBufferStart); + bCount = (UINT8)(fPtrEnd - (fPointer + 1)); + + do + { + fPointer[dCount] = fPointer[dCount+1]; + ++dCount; + --bCount; + } while(bCount); + + // + // Calculate offset + // + dCount = (UINT32)(fPointer - + (UINT8*)gUsbData->aKBCShiftKeyStatusBufferStart); + bCount = (UINT8)(fPtrEnd - (fPointer + 1)); + do + { + gUsbData->aKBCDeviceIDBufferStart[dCount] = + gUsbData->aKBCDeviceIDBufferStart[dCount+1]; + ++dCount; + --bCount; + } while(bCount); + + dCount = (UINT32)(fPointer - + (UINT8*)gUsbData->aKBCShiftKeyStatusBufferStart); + // + // Update device ID buf + // + bCount = (UINT8)(fPtrEnd - (fPointer + 1)); + do + { + gUsbData->aKBCScanCodeBufferStart[dCount] = + gUsbData->aKBCScanCodeBufferStart[dCount+1]; + ++dCount; + --bCount; + } while(bCount); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_CheckForExtendedKey +// +// Description: Checks whether the key pressed is a extended key +// +// Input: bScanCode Set 2 scan code for the key pressed +// +// Output: 0 Key pressed matches the numeric key pad key +// <> 0 It is not a numeric key pad key +// Set 3 scan code for the key pressed +// (if set 3 is chosen) +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +USBKB_CheckForExtendedKey (UINT8 bScanCode) +{ + UINT8 bCount, + bFound = FALSE; + UINT16 wRetValue = 0xff; + + bCount = 0; + while(bCount < sizeof (aStaticExtendedKeyScan2Table)) + { + if(aStaticExtendedKeyScan2Table[bCount] == bScanCode) + { + bFound = TRUE; + break; + } + ++bCount; + } + if(bFound == TRUE) + { +#if USB_KBC_EMULATION + wRetValue = (UINT16)aStaticExtendedKeyScan3Table[bCount]; + wRetValue = wRetValue << 8; +#endif + wRetValue &= 0xff00; + } + + return(wRetValue); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_CheckForNumericKeyPadKey +// +// Description: Checks whether the key pressed is from numeric key pad +// +// Input: bScanCode Set 2 scan code for the key pressed +// +// Output: 0 Key pressed matches the numeric key pad key +// <> 0 It is not a numeric key pad key +// Set 3 scan code for the key pressed +// (if set 3 is chosen) +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +USBKB_CheckForNumericKeyPadKey (UINT8 bScanCode) +{ + UINT8 bCount, + bFound = FALSE; + UINT16 wRetValue = 0xff; + + bCount = 0; + while(bCount < sizeof (aStaticKeyPadScan2Table)) + { + if(aStaticKeyPadScan2Table[bCount] == bScanCode) + { + bFound = TRUE; + break; + } + ++bCount; + } + if(bFound == TRUE) + { +#if USB_KBC_EMULATION + wRetValue = aStaticKeyPadScan3Table[bCount]; + wRetValue = wRetValue SHL 8; +#endif + wRetValue &= 0xff00; + } + return(wRetValue); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKBC_CheckCharacterBufferFull +// +// Description: This routine checks whether the character buffer can hold +// 'N'+1 character +// +// Input: bCount Space needed in the buffer (in characters) +// +// Output: 0 If buffer is full +// <> 0 If buffer is not full +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBKBC_CheckCharacterBufferFull (UINT8 bCount) +{ + UINT8 *dHead, *dTail, *dStart, *dEnd; + + dHead = gUsbData->fpKBCCharacterBufferHead; + dTail = gUsbData->fpKBCCharacterBufferTail; + dStart = gUsbData->aKBCCharacterBufferStart; + dEnd = dHead + sizeof (gUsbData->aKBCCharacterBufferStart); + ++bCount; + do { + ++dHead; + if(dHead == dEnd) dHead = dStart; + if(dHead == dTail) return 0; + --bCount; + } while(bCount); + + return 0xFF; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKBC_GetFromCharacterBuffer +// +// Description: This routine gets a character from the character buffer. +// Character buffer pointers are also updated +// +// Input: Nothing +// +// Output: Character taken from the character buffer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBKBC_GetFromCharacterBuffer() +{ + UINT8 bValue; + UINT8 *fPtr, *fPtrEnd; + + fPtrEnd = gUsbData->aKBCCharacterBufferStart + + sizeof (gUsbData->aKBCCharacterBufferStart); + fPtr = gUsbData->fpKBCCharacterBufferTail; + bValue = *fPtr; + ++fPtr; + // + // Check for buffer end condition + // + if(fPtr == fPtrEnd) + fPtr = gUsbData->aKBCCharacterBufferStart; + gUsbData->fpKBCCharacterBufferTail = fPtr; + + return bValue; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKBC_SendToCharacterBuffer +// +// Description: This routine puts a character into the character buffer. +// Character buffer pointers are also updated +// +// Input: Nothing +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKBC_SendToCharacterBuffer (UINT8 bChar) +{ + UINT8 *fPointer, *fPtrEnd; + + fPtrEnd = gUsbData->aKBCCharacterBufferStart + + sizeof (gUsbData->aKBCCharacterBufferStart); + + fPointer = gUsbData->fpKBCCharacterBufferHead; + *fPointer = bChar; + ++fPointer; + + if(fPointer == fPtrEnd) { + fPointer = gUsbData->aKBCCharacterBufferStart; + } + + gUsbData->fpKBCCharacterBufferHead = fPointer; + + USBKeyRepeat(NULL, 2); // Enable Key repeat +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_ConvertUSBKeyCodeToScanCodeSet2 +// +// Description: This routine converts the USB keycode into scan code set +// 2 scan code. Conversion is accomplished using a static table. +// +// Input: bKeyCode USB Key code +// +// Output: Set 2 scan code for the key +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +USBKB_ConvertUSBKeyCodeToScanCodeSet2 (UINT8 bKeyCode) +{ + return aUSBKeyCodeToScanCodeSet2Table[bKeyCode]; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKB_CheckModifierKeyPress +// +// Description: This routine checks whether any of the modifier keys, like +// shift, control or alternate keys, are pressed +// +// Input: bScanCode Scan code set 2 scan code +// +// Output: 0 None of the modifier keys are pressed +// Modifier key is pressed +// High Byte, Low Byte = Modifier key identifier +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +USBKB_CheckModifierKeyPress (UINT8 bScanCode) +{ + UINT8 bLByte = 0, + bHByte = 0; + UINT16 wValue; + // + // Check for left shift key status + // + if(bScanCode == LEFT_SHIFT) + bHByte = KB_LSHIFT_KEY_BIT_MASK; + // + // Check for right shift key status + // + if (bScanCode == RIGHT_SHIFT) + bHByte = KB_RSHIFT_KEY_BIT_MASK; + // + // Check for left control key status + // + if (bScanCode == LEFT_CTRL) + { + bHByte = KB_CTRL_KEY_BIT_MASK; + bLByte = RIGHT_CTRL; + } + // + // Check for left control key status + // + if (bScanCode == RIGHT_CTRL) + { + bHByte = KB_CTRL_KEY_BIT_MASK; + bLByte = LEFT_CTRL; + } + // + // Check for left alternate key status + // + if (bScanCode == LEFT_ALT) + { + bHByte = KB_ALT_KEY_BIT_MASK; + bLByte = RIGHT_ALT; + } + // + // Check for left alternate key status + // + if (bScanCode == RIGHT_ALT) + { + bHByte = KB_ALT_KEY_BIT_MASK; + bLByte = LEFT_ALT; + } + wValue = (UINT16)(bLByte + (bHByte << 8)); + return(wValue); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKBC_GetAndStoreCCB +// +// Description: This routine will read the CCB from the keyboard controller +// and store it in a local variable +// +// Input: Nothing +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKBC_GetAndStoreCCB() +{ + KBC_KBDTRANSLATION tr; + + ASSERT(gKbdInput); + // + // CCB is internal buisness of KBC relted code + // USB code only need to know about translation type + // + VERIFY_EFI_ERROR( + gKbdInput->GetTranslation(gKbdInput,&tr)); + gUsbData->bCCB = tr == KBC_KBDTRANS_PCXT? 0x40 : 0; + return ; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBKBC_CheckAutoRepeat +// +// Description: This routine will check the repeat counter and repeat rate +// and perform the auto repeat appropriately +// +// Input: Nothing +// +// Output: Nothing +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +void +USBKBC_CheckAutoRepeat() +{ + //(EIP102150+)> + UINT8 ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); + UINT8 i; + + if(ScanCodeCount){ + USB_DEBUG (DEBUG_LEVEL_7, "USBKBC_CheckAutoRepeat: \n"); + + // + // Update repeat counter + // + gUsbData->wRepeatCounter++; + + if (gUsbData->wRepeatCounter >= gUsbData->wRepeatRate) { + + // + // Repeat rate reached. Reload repeat delay counter + // + gUsbData->wRepeatRate = aTypematicRateDelayTable[ + (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_RATE_BIT_MASK) >> + KBC_TYPE_RATE_BIT_SHIFT]; + gUsbData->wRepeatCounter = 0; + + // + // Check for scan code in the buffer + // + if(gUsbData->fpKBCCharacterBufferHead == + gUsbData->fpKBCCharacterBufferTail) + { + // + // Buffer has character to process. + // + for(i = 0; i < ScanCodeCount; i++) + { + USBKB_GenerateScanCode(USB_GEN_MAKE_CODE, + gUsbData->aKBCScanCodeBufferStart[i], 0); + } + } + } + } + //<(EIP102150+) +} + + +VOID +SysKbcAutoRepeat( + HC_STRUC* HcStruc +) +{ + UINT8 BreakCodeDeviceId; + UINT8 DevAddr; + UINT8 *KbInputBuffer; + DEV_INFO *DevInfo; + PS2MouseData MouseData; + EFI_STATUS EfiStatus; + UINT8 DummyData; + static UINT8 Buffer[64]; + UINT32 Count = 1; + + USBKB_UpdateLEDState(0x0); + + BreakCodeDeviceId = gUsbData->bBreakCodeDeviceID; + + USB_DEBUG (DEBUG_LEVEL_8, "USBKBDpih: BreakCodeID %x \n", BreakCodeDeviceId); + + if (BreakCodeDeviceId) { + DevAddr = 1; + + while (!(BreakCodeDeviceId & 1)) { + BreakCodeDeviceId >>= 1; + ++DevAddr; + } + DevInfo = USB_GetDeviceInfoStruc( + USB_SRCH_DEV_ADDR, + (DEV_INFO*)0, + DevAddr, + HcStruc); + ASSERT(DevInfo != NULL); + if (DevInfo == NULL) { + return; + } + + KbInputBuffer = gUsbData->aKBInputBuffer; + *KbInputBuffer = 0; + ++KbInputBuffer; + *KbInputBuffer = 0; + --KbInputBuffer; + + USBKB_Scanner(DevInfo, KbInputBuffer); + } + + USBKBC_CheckAutoRepeat(); + if (gUsbData->fpKBCCharacterBufferTail != gUsbData->fpKBCCharacterBufferHead) { + // Get the Data from aKBInputBuffer Local Buffer + *Buffer = *gUsbData->fpKBCCharacterBufferTail; + //Optimization: Enable the code below; it must be more efficient + // UINT8 *p; + // for( p = Buffer; gUsbData->fpKBCCharacterBufferTail != gUsbData->fpKBCCharacterBufferHead; + // ++Count) + // *p++ = USBKBC_GetFromCharacterBuffer(); + + if (gKbdInput->Send == SYSKBC_KbdInput_Send) { + + // USB driver Emulation function already working on the aKBInputBuffer buffer + // So we don't need to remove the data from aKBInputBuffer incase if data send + // Successfully + EfiStatus = gKbdInput->Send(gKbdInput, Buffer, Count); + } else { + // Other Emulation drivers doesn't use the aKBInputBuffer. + // So remove the data from aKBInputBuffer if the data sent successfully. + EfiStatus = gKbdInput->Send(gKbdInput, Buffer, Count); + + if (!EFI_ERROR(EfiStatus)) { + *Buffer = USBKBC_GetFromCharacterBuffer(); + } + } + + USBKBC_GetAndStoreCCB(); + USBKeyRepeat(NULL, 2); + } else if (gUsbData->fpMouseInputBufferHeadPtr != + gUsbData->fpMouseInputBufferTailPtr) { + + // Get the Mouse data Packet from aMouseInputBuffer buffer + MouseData.flags = *gUsbData->fpMouseInputBufferTailPtr; + MouseData.x = *(gUsbData->fpMouseInputBufferTailPtr + 1); + MouseData.y = *(gUsbData->fpMouseInputBufferTailPtr + 2); + + if (gMsInput->Send == SYSKBC_MouseInput_Send) { + + // USB driver Emulation function already working on the aMouseInputBuffer buffer + // So we don't need to remove the data from aMouseInputBuffer incase if data send + // Successfully + EfiStatus = gMsInput->Send(gMsInput, &MouseData); + } else { + // Other Emulation drivers doesn't use the aMouseInputBuffer. + // So remove the data from aMouseInputBuffer if the data sent successfully. + EfiStatus = gMsInput->Send(gMsInput, &MouseData); + if (!EFI_ERROR(EfiStatus)) { + DummyData = USBMouse_GetFromMouseBuffer(); + DummyData = USBMouse_GetFromMouseBuffer(); + DummyData = USBMouse_GetFromMouseBuffer(); + } + } + + USBKeyRepeat(NULL, 2); // Enable Key repeat + + } else if(gUsbData->fpKBCScanCodeBufferPtr != gUsbData->aKBCScanCodeBufferStart ) { + USBKeyRepeat(NULL, 2); // Enable Key repeat + } else { + USBKeyRepeat(NULL, 1); // Disable Key repeat + } +} + +static EFI_EMUL6064KBDINPUT_PROTOCOL theKbdInput = +{ +SYSKBC_KbdInput_Send, +SYSKBC_GetTranslation, +SYSKBC_UpdateLEDState +}; + +EFI_EMUL6064MSINPUT_PROTOCOL theMsInput = +{ + SYSKBC_MouseInput_Send +}; + +void InitSysKbc( + EFI_EMUL6064KBDINPUT_PROTOCOL** ppKbd, + EFI_EMUL6064MSINPUT_PROTOCOL** ppMouse ) +{ + *ppKbd = &theKbdInput; + *ppMouse = &theMsInput; +} + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2016, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** |