summaryrefslogtreecommitdiff
path: root/Core/EM/usb/rt/usbkbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/usb/rt/usbkbd.c')
-rw-r--r--Core/EM/usb/rt/usbkbd.c1315
1 files changed, 1315 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/usbkbd.c b/Core/EM/usb/rt/usbkbd.c
new file mode 100644
index 0000000..e7240ad
--- /dev/null
+++ b/Core/EM/usb/rt/usbkbd.c
@@ -0,0 +1,1315 @@
+#pragma warning(disable: 4001)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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/usbkbd.c 70 10/16/16 10:11p Wilsonlee $
+//
+// $Revision: 70 $
+//
+// $Date: 10/16/16 10:11p $
+//****************************************************************************
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbkbd.c $
+//
+// 70 10/16/16 10:11p 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
+//
+// 69 7/21/16 11:00p Wilsonlee
+// Build error if USB_HID_KEYREPEAT_USE_SETIDLE is 1.
+//
+// 68 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 67 12/24/14 9:33p Wilsonlee
+// [TAG] EIP194683
+// [Category] Improvement
+// [Description] Add the flag "USB_INCMPT_HID_BOOT_PROTOCOL_ONLY" of usb
+// bad device table to keep devices use boot protocol.
+// [Files] usbkbd.c, usbms.c, usbhid.c, usbdef.h
+//
+// 66 11/23/14 9:24p Wilsonlee
+// [TAG] EIP190127
+// [Category] Improvement
+// [Description] Remove scan code algorithm update.
+// [Files] usbkbd.c
+//
+// 65 11/23/14 9:10p Wilsonlee
+// [TAG] EIP188119
+// [Category] Improvement
+// [Description] Disconnect devices and uninstall usb device related
+// protocols if we call stop api for the host controllers.
+// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c
+//
+// 64 8/07/14 2:20a Wilsonlee
+// [TAG] EIP176549
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Microstep USB Keyboard issue.
+// [RootCause] The report descriptor of Microstep USB Keyboard (Sonix
+// Technology Co chip) has an error, Modifier keys is bitmap data, but it
+// reports as array data.
+// [Solution] We need to force variable flag for Modifier keys input
+// item.
+// [Files] usbhid.c, usbkbd.c, usbdef.h
+//
+// 63 7/04/14 7:31a Wilsonlee
+// [TAG] EIP176044
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] NEC USB keyboard doesn't work
+// [RootCause] When we extract input report data, the report offset is
+// incorrect if ReportId isn't 0.
+// [Solution] Adjust report offset.
+// [Files] usbkbd.c
+//
+// 62 5/15/14 5:41a Wilsonlee
+// Fix the code check error result.
+//
+// 61 5/06/14 5:15a 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
+//
+// 60 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 59 11/05/13 4:47a Ryanchou
+// [TAG] EIP135636
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] NumLock LED cannot be on/off properly.
+// [RootCause] It is the side effect of EIP #107429 changes, the
+// keyboard does not generate break code when pressing NumLock.
+// [Solution] Remove the EIP #107429 changes.
+// [Files] amiusb.c, usbkbd.c, efiusbkb.c
+//
+// 58 3/07/13 8:53a Ryanchou
+// [TAG] EIP113218
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work after ownership change back to
+// BIOS
+// [RootCause] The key repeat SMI does not generated because the HC is
+// stopped.
+// [Solution] Use the other HC to generate key repeat SMI
+// [Files] usb.c, usbhid.c, usbkbd.c
+//
+// 57 1/23/13 4:35a Wilsonlee
+// [TAG] EIP109538
+// [Category] Improvement
+// [Description] Fix the code check error result.
+// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c
+//
+// 56 1/11/13 4:15a Ryanchou
+// [TAG] EIP102491
+// [Category] Improvement
+// [Description] Synchronized with Aptio V USB module
+// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h,
+// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c.
+// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c,
+// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c
+//
+// 55 1/07/13 12:56a Wilsonlee
+// [TAG] EIP111305
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] It is failed at reloading the usb keyboard driver.
+// [RootCause] The DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag
+// were cleared when the usb driver is disconnecting.
+// [Solution] We should not clear the DEV_INFO_VALID_STRUC and
+// DEV_INFO_DEV_PRESENT flag at USBKBDDisconnectDevice.
+// [Files] usbkbd.c, usbbus.c
+//
+// 54 12/19/12 3:38a Roberthsu
+// [TAG] EIP107262
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] CHOC keyboard can not work.
+// [RootCause] Usage offset error.
+// [Solution] Count correct usage offset.Ceck correct usage offset.
+// [Files] usbkbd.c
+//
+// 53 12/02/12 10:34p 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
+//
+// 52 11/20/12 9:08p Wilsonlee
+// [TAG] EIP90887
+// [Category] New Feature
+// [Description] Add a hook to check keyboard buffer for speicial chars.
+// [Files] usb.sdl, usbrt.mak, usbkbd.c
+//
+// 51 11/14/12 4:26a Roberthsu
+// [TAG] EIP105587
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Rapoo keyboard press key have some garbage key.
+// [RootCause] Get report descriptor need skip constant data.
+// [Solution] Skip constant data.
+// [Files] usbkbd.c
+//
+// 50 11/10/12 6:39a Ryanchou
+// [TAG] EIP99431
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for
+// keyboard input
+// [RootCause] Stopping EFI USB keyboard driver does not stop the
+// endpoint polling, then application calls UsbAsyncInterruptTransfer,
+// error will be returned.
+// [Solution] Stops endpoint polling and release resource when
+// disconnecting the device driver. And improve the
+// UsbSyncInterruptTransfer.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c,
+// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c,
+// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h
+//
+// 49 8/07/12 4:47a Roberthsu
+// [TAG] EIP93637
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Keyboard operate incorrectly in BIOS
+// [RootCause] When keyboard disconnect.Usb keyboard buffer does not
+// clear.
+// [Solution] Clear usb keyboard buffer and repeat key.
+// [Files] usbkbd.c
+//
+// 48 8/06/12 11:53p Roberthsu
+// [TAG] EIP95349
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Roccat ISKU Keyboard can not work
+// [RootCause] Variable value overflow.
+// [Solution] Change variable type.
+// [Files] usbkbd.c
+//
+// 47 5/23/12 7:56a Roberthsu
+// [TAG] EIP90797
+// [Category] Improvement
+// [Description] Fix keyboard buffer transfer error
+// [Files] usbkbd.c
+//
+// 46 5/03/12 6:27a Roberthsu
+// [TAG] EIP84455
+// [Category] Improvement
+// [Description] Implement usb hid device gencric.
+// [Files] amiusb.c,amiusbhc.c,efiusbhid.c,efiusbkb.c,ehci.c,ohci.c,uhc
+// d.c,uhci.c,usbdef.h,usbhid.c,usbhub.c,usbkbd.c,usbkbd.h,usbms.c,usbsb.c
+// ,usbsrc.sdl
+//
+// 45 4/24/12 3:40a Roberthsu
+// [TAG] EIP83888
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Can not catch F8 key event on Keyboard
+// [RootCause] OS only call readkeystroke once.If OS get break key
+// readkeystroke will return EFI_NOT_READY.
+// [Solution] UsbKbdReadKeyStroke will serach available key in usb
+// data buffer.Fixed key repeat can not work when efi to legacy or legacy
+// to efi.
+// [Files] efiusbkb.c,usbkbd.c
+//
+// 44 3/05/12 1:26a Rameshr
+// [TAG] EIP81057
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Stall after RAID BIOS
+// [RootCause] Make code and break code handled by different environment
+// ( EFI, Legacy)
+// [Solution] If the Makecode processed by Legacy, the breakcode also
+// send to Legacy. The same applies for EFI also.
+// [Files] UsbKbd.c
+//
+// 43 1/04/12 6:56a 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
+//
+// 42 12/22/11 6:36a Roberthsu
+// [TAG] EIP77936
+// [Category] Improvement
+// [Description] Chang set_idle command timeout to 1sec
+// [Files] usbkbd.c
+//
+// 41 11/03/11 11:51p Roberthsu
+// [TAG] EIP73685
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Ducky keyboard can not work.
+// [RootCause] Ducky keyboard report key usage is by usage keyboard
+// arrow.
+// [Solution] Get start offset by keyboard usage page .
+// [Files] usbkbd.c
+//
+// 40 9/27/11 1:37a Roberthsu
+// [TAG] EIP67400
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Microsoft wireless Media Desktop 1000 can¡¦t work normal.
+// [RootCause] Wireless ms report data contains usage page keyboard.And
+// output data not contains vaild report id.
+// [Solution] Check usage page led to decide kb or ms.Check correct
+// report id with report data.
+// [Files] usbkbd.c,usbhid.c,usbms.c
+//
+// 39 7/15/11 6:11a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c, usb.c, usbdef.h,
+// usbkbd.c, usbkbd.h, usbms.c, usbrt.cif, usbsb.c, usbsetup.c,
+// usbsrc.sdl, xhci.c
+//
+// 38 7/13/11 3:32a Ryanchou
+// [TAG] EIP63973
+// [Category] Improvement
+// [Description] Change the order of Set Protocol command and Set Idle
+// command.
+// [Files] usbkbd.c
+//
+// 37 6/21/11 11:02a Ryanchou
+// [TAG] EIP59579
+// [Category] Improvement
+// [Description] USB device information structure should be reserved for
+// the UsbIO to use even install driver fail.
+// [Files] usbmass.c, usbkbd.c, usbms.c
+//
+// 36 3/30/11 8:17a Ryanchou
+// [TAG] EIP54126
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometimes system hangs at checkpoint 0xB4.
+// [RootCause] The bLength field of configuration descriptor is zero.
+// [Solution] Check wether bLength field is zero before paring next
+// descriptor.
+// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c
+//
+// 35 2/10/11 7:40a Ryanchou
+// [TAG] EIP52206
+// [Category] Improvement
+// [Description] Remote wakeup command should be sent before sleep,
+// comment out the command.
+// [Files] usbkbd.c, usbms.c
+//
+// 34 1/17/11 4:34a Ryanchou
+// [TAG] EIP51108
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Some HID devices that has two interfaces can't work.
+// [RootCause] BIOS using the wrong endpoint to poll KBD/MS data.
+// [Solution] Get the first interrupt in endpoint when parsing
+// descriptors.
+// [Files] usbkbd.c, usbms.c
+//
+// 33 9/24/10 5:38p Olegi
+// EIP38221: Added the code that properly initializes
+// DEV_INFO.bIntEndpoint field; interrupt endpoint polling is using this
+// endpoint number.
+//
+// 32 3/11/10 9:41a Olegi
+//
+// 31 11/24/09 11:38a Olegi
+// EIP#29733 - BIOS adds an USB API (Block KBC Access)
+//
+// 30 11/13/09 9:13a Olegi
+// EIP31023: key repeat rates are defined by SDL tokens.
+//
+// 29 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 28 5/05/09 10:21a Olegi
+// Modification in USBKBDConnectKeyboard. Resolves the problem of device
+// being reconnected using the SW (DisconnectController->ConnectController
+// sequence). EIP#21456.
+//
+// 27 4/20/09 9:26a Olegi
+// Completion of the fix for EIP#19563.
+//
+// 26 3/27/09 10:15a Olegi
+// Modifications in USBKBDProcessKeyboardData: keypress and key release
+// are synchronized between the modes (EFI/Legacy). If key is pressed in
+// one mode and released in the other, then keypress is discarded. This
+// fixes the problem of accidental key repeat sequence due to the mode
+// change. EIP #19563.
+//
+// 25 9/19/08 4:44p Olegi
+// Bugfix in USBKBDPeriodicInterruptHandler (EIP#16452) that takes care of
+// the key release situation.
+//
+// 24 9/05/08 4:19p Olegi
+// Removed calls to fpCallbackNotify functions, they are implemented in
+// SMI.
+//
+// 23 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 21 12/17/07 4:04p Olegi
+// KBC emulation support added.
+//
+// 20 30/10/07 2:02p Anandakrishnanl
+// Updated USBKBDPeriodicInterruptHandler to see if CallbackNotify2 is not
+// NULL beforfe calling it.
+//
+// 19 30/10/07 12:20p Anandakrishnanl
+// Updated USBKBDPeriodicInterruptHandler to see if CallbackNotify3 is not
+// NULL beforfe calling it.
+//
+// 18 9/27/07 4:12p Olegi
+//
+// 17 3/20/07 12:17p Olegi
+// Legacy free related changes.
+//
+// 15 10/18/06 9:40a Andriyn
+// Fix: race condition on hot-plug in / plug-off
+//
+// 14 5/17/06 3:52p Fredericko
+// Fix: Mouse Button events get lost: no auto-repeat
+//
+// 13 4/26/06 12:26p Olegi
+//
+// 12 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 11 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 10 3/06/06 6:23p Olegi
+//
+// 9 3/01/06 3:50p Olegi
+// ProcessKeyboardData is change to use USB_FLAG_RUNNING_UNDER_OS flag.
+//
+// 8 2/06/06 9:34a Andriyn
+//
+// 7 8/26/05 12:25p Andriyn
+// Simulate Mouse Sampling rate by disabling Mouse Polling (reduce USB
+// SMI# generation)
+//
+// 6 8/25/05 7:19p Andriyn
+// USB Keyboard and mouse to use EMUL 60/64 for passing data to KBC.
+// Fall-back when EMUL 60/64 is not present
+//
+// 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: UsbKbd.c
+//
+// Description: USB keyboard driver SMI routines
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "USBKBD.H"
+#include <UsbDevDriverElinks.h> //(EIP90887+)
+
+extern USB_GLOBAL_DATA *gUsbData;
+extern BOOLEAN gKeyRepeatStatus;
+extern UINT16 gKbcSetTypeRate11CharsSec;
+extern UINT16 gKbcSetTypeDelay500MSec;
+UINT8 gLastKeyCodeArray[8]={0,0,0,0,0,0,0,0};
+
+//----------------------------------------------------------------------------
+// Typematic rate delay table will have counts to generate key repeat delays.
+// Since the periodic interrupt is set to 8msec the following repeat times
+// will generate necessary delay.
+// First three numbers are meant to define the frequency of the repeated keys;
+// four other numbers are used to define the amount of delay between the first
+// keypress-and-hold til the key actually starts repeating; the appropriate values
+// of this table are selected using the equates defined in UsbKbd.h
+//
+UINT8 aTypematicRateDelayTable[] = {2, 4, 8, 16, 32, 48, 64, 96};
+
+//
+// The global data variables are stored in USB_GLOBAL_DATA structure and can be accessed through
+// gUsbData->xxx
+//
+
+LEGACY_USB_KEYBOARD mLegacyKeyboard;
+
+extern UINT8 IsKbcAccessBlocked; //(EIP29733+)
+extern VOID USBKB_LEDOn();
+
+BOOLEAN gEfiMakeCodeGenerated=FALSE;
+BOOLEAN gLegacyMakeCodeGenerated=FALSE;
+
+extern EFI_EMUL6064KBDINPUT_PROTOCOL* gKbdInput ;
+
+UINT8 UsbControlTransfer(HC_STRUC*, DEV_INFO*, DEV_REQ, UINT16, VOID*);
+
+UINT32 ExtractInputReportData (UINT8 *Report, UINT16 Offset, UINT16 Size);
+ //(EIP90887+)>
+typedef BOOLEAN (KBD_BUFFER_CHECK_FUNCTIONS)(
+ DEV_INFO* DevInfo,
+ UINT8 *Buffer
+ );
+extern KBD_BUFFER_CHECK_FUNCTIONS KBD_BUFFER_CHECK_ELINK_LIST EndOfInitList;
+KBD_BUFFER_CHECK_FUNCTIONS* KbdBufferCheckFunctionsList[] = {KBD_BUFFER_CHECK_ELINK_LIST NULL};
+ //<(EIP90887+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDInitialize (VOID)
+//
+// Description: This function returns fills the host controller driver
+// routine pointers in the structure provided
+//
+// Input: Nothing
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBDInitialize (VOID)
+{
+ UINT8 bTemp;
+
+ //
+ // Initialize the typematic rate to 500 ms, 10.9 Char/Sec and auto repeat flag
+ // to disabled
+ //
+ gUsbData->wUSBKBC_StatusFlag |= ((gKbcSetTypeRate11CharsSec << KBC_TYPE_RATE_BIT_SHIFT) +
+ (gKbcSetTypeDelay500MSec << KBC_TYPE_DELAY_BIT_SHIFT));
+
+ USB_DEBUG (DEBUG_LEVEL_5, "USBKBDInitialize: CodeBufferStart : %lx\n", gUsbData->aKBCScanCodeBufferStart);
+
+ //
+ // Initialize the scanner buffer
+ //
+ gUsbData->fpKBCScanCodeBufferPtr = gUsbData->aKBCScanCodeBufferStart;
+ gUsbData->bLastUSBKeyCode = 0;
+
+ //
+ // Initialize the character buffer
+ //
+ gUsbData->fpKBCCharacterBufferHead = gUsbData->aKBCCharacterBufferStart;
+ gUsbData->fpKBCCharacterBufferTail = gUsbData->aKBCCharacterBufferStart;
+
+ //
+ // Initialize the USB Data buffer
+ //
+ gUsbData->aKBCUsbDataBufferHead = gUsbData->aKBCUsbDataBufferStart;
+ gUsbData->aKBCUsbDataBufferTail = gUsbData->aKBCUsbDataBufferStart;
+
+ gUsbData->fpKeyRepeatDevInfo=NULL;
+
+ //
+ // Set scan code set to 2 in the scanner flag
+ //
+ gUsbData->wUSBKBC_StatusFlag |= KBC_SET_SCAN_CODE_SET2;
+
+ gUsbData->bUSBKBShiftKeyStatus = 0;
+
+ //
+ // Get the keyboard controller command byte (CCB) and store it locally
+ //
+ //USBKBC_GetAndStoreCCB();
+ gUsbData->bCCB = 0x40;
+
+ for (bTemp=0; bTemp<6; bTemp++) mLegacyKeyboard.KeyCodeStorage[bTemp] = 0;
+ mLegacyKeyboard.KeyToRepeat = 0;
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBKBDConfigureKeyboard
+//
+// Description: This routine checks an interface descriptor of the USB device
+// detected to see if it describes a HID/Boot/Keyboard device.
+// If the device matches the above criteria, then the device is
+// configured and initialized
+//
+// Input: fpHCStruc HCStruc pointer
+// fpDevInfo Device information structure pointer
+// fpDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: FPDEV_INFO New device info structure, 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(EIP84455+)>
+DEV_INFO*
+USBKBDConfigureDevice (
+ DEV_INFO* DevInfo
+)
+{
+ UINT16 Index;
+
+ DevInfo->fpPollTDPtr = 0;
+ Index = USBKBDFindUSBKBDeviceTableEntry(DevInfo);
+ if (Index == 0xFFFF) {
+ Index = USBKBDFindUSBKBDeviceTableEntry(NULL);
+ }
+ if (Index != 0xFFFF) {
+ gUsbData->aUSBKBDeviceTable[Index] = DevInfo;
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) {
+ if (BOOT_PROTOCOL_SUPPORT || (DevInfo->HidReport.Flag & HID_REPORT_FLAG_LED_FLAG) ||
+ (DevInfo->wIncompatFlags & USB_INCMPT_HID_BOOT_PROTOCOL_ONLY)) {
+ USBKB_LEDOn();
+ }
+ }
+ } else {
+ return 0;
+ }
+
+ return DevInfo;
+}
+ //<(EIP84455+)
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDFindUSBKBDeviceTableEntry
+//
+// Description: This routine searches for the HID table entry which matches
+// the provided device info structure
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: offset of the HID table for the requested fpDevinfo
+// 0xFFFF -on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+USBKBDFindUSBKBDeviceTableEntry(DEV_INFO* fpDevinfo)
+{
+ UINT16 wCount ;
+
+ for (wCount = 0; wCount < USB_DEV_HID_COUNT; wCount++)
+ {
+ if(gUsbData->aUSBKBDeviceTable[wCount] == fpDevinfo )
+ return wCount;
+ }
+ USB_DEBUG (DEBUG_LEVEL_3, "No Free KBD DevInfo Entry\n");
+ return 0xFFFF;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDDisconnectDevice
+//
+// Description: This routine disconnects the keyboard by freeing
+// the USB keyboard device table entry
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: USB_SUCCESS/USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBDDisconnectDevice (
+ DEV_INFO* DevInfo
+)
+{
+ UINT16 Index;
+ //(EIP93637+)>
+ UINT8 ScanCodeCount = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr -
+ (UINT8*)gUsbData->aKBCScanCodeBufferStart); //(EIP102150+)
+ UINT8 i = 0;
+ UINT8 CurrentDeviceId;
+ UINT8 Key;
+
+ USB_KB_BUFFER *KeyboardBuffer;
+ KeyboardBuffer = gUsbData->EfiKeyboardBuffer;
+
+ Index = USBKBDFindUSBKBDeviceTableEntry(DevInfo);
+ if (Index == 0xFFFF) {
+ USBLogError(USB_ERR_KBCONNECT_FAILED);
+ return USB_ERROR;
+ } else {
+ CurrentDeviceId = (UINT8)(1 << ((DevInfo->bDeviceAddress) -1));
+ while ((i < ScanCodeCount) && (ScanCodeCount != 0)) {
+ if (gUsbData->aKBCDeviceIDBufferStart[i] & CurrentDeviceId) {
+ gUsbData->aKBCDeviceIDBufferStart[i] &= ~CurrentDeviceId;
+ if (gUsbData->aKBCDeviceIDBufferStart[i] == 0) {
+ Key = gUsbData->aKBCScanCodeBufferStart[i];
+ if ((Key == HID_UP_KEYBOARD_RIGHT_SHIFT) ||
+ (Key == HID_UP_KEYBOARD_LEFT_SHIFT)) {
+ gUsbData->bUSBKBShiftKeyStatus &= ~(KB_RSHIFT_KEY_BIT_MASK+KB_LSHIFT_KEY_BIT_MASK);
+ }
+ USBKB_DiscardCharacter(&gUsbData->aKBCShiftKeyStatusBufferStart[i]);
+ gUsbData->fpKBCScanCodeBufferPtr--;
+ ScanCodeCount--;
+ continue;
+ }
+ }
+ i++;
+ }
+ if (gUsbData->fpKeyRepeatDevInfo == DevInfo) {
+ for (i = 0; i < 8; i++) {
+ *(gLastKeyCodeArray + i) = 0;
+ }
+ if(KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode == gUsbData->RepeatKey)
+ {
+ gUsbData->RepeatKey = 0;
+ KeyboardBuffer->bHead = KeyboardBuffer->bTail;
+ }
+ }
+ gUsbData->aUSBKBDeviceTable[Index] = 0;
+ return USB_SUCCESS;
+ }
+ //<(EIP93637+)
+}
+
+//<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_CheckUsbDataBufferFull (UINT8 bCount)
+{
+ UINT8 *dHead, *dTail, *dStart, *dEnd;
+
+ dHead = gUsbData->aKBCUsbDataBufferHead;
+ dTail = gUsbData->aKBCUsbDataBufferTail;
+ dStart = gUsbData->aKBCUsbDataBufferStart;
+ dEnd = dStart + sizeof (gUsbData->aKBCUsbDataBufferStart);
+ ++bCount;
+ do {
+ ++dHead;
+ if(dHead == dEnd) dHead = dStart;
+ if(dHead == dTail) return 0;
+ --bCount;
+ } while(bCount);
+
+ return 0xFF;
+}
+
+
+
+//<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_SendToUsbDataBuffer (UINT8 *fpSrc)
+{
+ UINT8 *fPointer;
+ UINT8 *fPtrEnd;
+ UINT8 i;
+
+ fPtrEnd = ( gUsbData->aKBCUsbDataBufferStart +
+ sizeof (gUsbData->aKBCUsbDataBufferStart));
+
+ fPointer = gUsbData->aKBCUsbDataBufferHead;
+
+ for (i = 0; i < 8; i++) {
+ *fPointer++ = *fpSrc++;
+ }
+
+ if(fPointer == fPtrEnd) {
+ fPointer = gUsbData->aKBCUsbDataBufferStart;
+ }
+
+ gUsbData->aKBCUsbDataBufferHead = fPointer;
+
+ return;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDProcessKeyboardData
+//
+// Description: This routine is called with USB keyboard report data. This
+// routine handles the translation of USB keyboard data
+// into PS/2 keyboard data, and makes the PS/2 data available
+// to software using ports 60/64h by communicating with
+// PS/2 keyboard controller.
+//
+// Input: fpHCStruc Pointer to HCStruc
+// fpDevInfo Pointer to device information structure
+// fpTD Pointer to the polling TD
+// fpBuffer Pointer to the data buffer
+//
+// Output: Nothing
+//
+// Notes: TD's control status field has the packet length (0 based).
+// It could be one of three values 0,1 or 7 indicating packet
+// lengths of 1, 2 & 8 repectively.
+// The format of 8 byte data packet is as follow:
+// Byte Description
+// -----------------------------------------------------------
+// 0 Modifier key (like shift, cntr & LED status)
+// 1 Reserved
+// 2 Keycode of 1st key pressed
+// 3 Keycode of 2nd key pressed
+// 4 Keycode of 3rd key pressed
+// 5 Keycode of 4th key pressed
+// 6 Keycode of 5th key pressed
+// 7 Keycode of 6th key pressed
+// -----------------------------------------------------------
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBKBDProcessKeyboardData (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ UINT8 Count = 8;
+ HID_REPORT_FIELD *Field = NULL;
+ UINT8 FieldIndex = 0;
+ UINT32 BitOffset = 0;
+ BOOLEAN ValidData = FALSE;
+ UINT8 Data = 0;
+ UINT16 Index = 0;
+ UINT8 UsageBuffer[32] = {0};
+ UINT16 UsageIndex = 0;
+ UINT8 i;
+ UINTN OemHookIndex;
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ for (FieldIndex = 0; FieldIndex < DevInfo->HidReport.FieldCount; FieldIndex++) {
+ Field = DevInfo->HidReport.Fields[FieldIndex];
+
+ // Check if the field is input report.
+ if (!(Field->Flag & HID_REPORT_FIELD_FLAG_INPUT)) {
+ continue;
+ }
+
+ //if report id exist, check first byte
+ if ((Field->ReportId != 0) && (Field->ReportId != Buffer[0])) {
+ continue;
+ }
+
+ // Check if the field is contant.
+ if (Field->Flag & HID_REPORT_FIELD_FLAG_CONSTANT) {
+ BitOffset += Field->ReportCount * Field->ReportSize;
+ continue;
+ }
+
+ //find start offset
+ if (Field->UsagePage == HID_UP_KEYBOARD) {
+ ValidData = TRUE;
+
+ // If Report ID tags are used in the report descriptor, the first byte is
+ // report id, we offset 8 bits to get data.
+ if (Field->ReportId != 0) {
+ BitOffset += 8;
+ }
+
+ for (Index = 0; Index < Field->ReportCount; Index++) {
+ Data = ExtractInputReportData(Buffer,
+ BitOffset + (Index * Field->ReportSize), Field->ReportSize);
+
+ if ((Data < Field->LogicalMin) || (Data > Field->LogicalMax)) {
+ continue;
+ }
+
+ Data = Field->Flag & HID_REPORT_FIELD_FLAG_VARIABLE ?
+ (Data != 0 ? Field->Usages[Index] : Data) :
+ Field->Usages[Data - Field->LogicalMin];
+
+ if ((Data != 0) && (UsageIndex < COUNTOF(UsageBuffer))) {
+ UsageBuffer[UsageIndex++] = Data;
+ }
+ }
+ if (Field->ReportId != 0) {
+ BitOffset -= 8;
+ }
+ }
+ BitOffset += Field->ReportCount * Field->ReportSize;
+ }
+
+ if (ValidData == FALSE) {
+ return USB_SUCCESS;
+ }
+
+ MemSet(Buffer, 8, 0);
+
+ // Translate the report data to boot protocol data.
+
+ // 0 Modifier key (like shift, cntr & LED status)
+ // 1 Reserved
+ // 2 Keycode of 1st key pressed
+ // 3 Keycode of 2nd key pressed
+ // 4 Keycode of 3rd key pressed
+ // 5 Keycode of 4th key pressed
+ // 6 Keycode of 5th key pressed
+ // 7 Keycode of 6th key pressed
+
+ for (Index = 0, i = 0; Index < UsageIndex; Index++) {
+ if (UsageBuffer[Index] >= HID_UP_KEYBOARD_LEFT_CTRL &&
+ UsageBuffer[Index] <= HID_UP_KEYBOARD_RIGHT_GUI) {
+ Buffer[0] |= 1 << (UsageBuffer[Index] - HID_UP_KEYBOARD_LEFT_CTRL);
+ } else {
+ if (i < 6) {
+ Buffer[i + 2] = UsageBuffer[Index];
+ i++;
+ }
+ }
+ }
+ }
+ //(EIP90887+)>
+ // Call all the OEM hooks that wants to check KBD buffer
+ for (OemHookIndex = 0; KbdBufferCheckFunctionsList[OemHookIndex]; OemHookIndex++) {
+ if (KbdBufferCheckFunctionsList[OemHookIndex](DevInfo, Buffer)) {
+ return USB_SUCCESS;
+ }
+ }
+ //<(EIP90887+)
+ //Is KBC access allowed?
+ if (IsKbcAccessBlocked) {
+ if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) || !gEfiMakeCodeGenerated) {
+ return USB_SUCCESS;
+ }
+ MemSet(Buffer, 8, 0);
+ }
+
+ //
+ // Save the device info pointer for later use
+ //
+ gUsbData->fpKeyRepeatDevInfo = DevInfo;
+
+ for (i = 0, Count = 8; i < 8; i++, Count--) {
+ if (Buffer[i]) {
+ break;
+ }
+ }
+
+ if ((gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) {
+ if (Count==0) {
+ gEfiMakeCodeGenerated=FALSE;
+ } else {
+ gEfiMakeCodeGenerated=TRUE;
+ gLegacyMakeCodeGenerated=FALSE;
+ }
+ } else {
+ if (Count==0) {
+ gLegacyMakeCodeGenerated=FALSE;
+ } else {
+ gLegacyMakeCodeGenerated=TRUE;
+ gEfiMakeCodeGenerated=FALSE;
+ }
+ }
+
+ //
+ // checks for new key stroke.
+ // if no new key got, return immediately.
+ //
+ for (i = 0; i < 8; i ++) {
+ if (Buffer[i] != gLastKeyCodeArray[i]) {
+ break;
+ }
+ }
+
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if ((i == 8) && gKeyRepeatStatus) {
+ USBKBDPeriodicInterruptHandler(HcStruc);
+ return USB_SUCCESS;
+ }
+#endif
+
+ //
+ // Update LastKeycodeArray[] buffer in the
+ // Usb Keyboard Device data structure.
+ //
+ for (i = 0; i < 8; i ++) {
+ gLastKeyCodeArray[i] = Buffer[i];
+ }
+
+ if ((!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) || gLegacyMakeCodeGenerated) &&(!gEfiMakeCodeGenerated))
+ {
+ if (Count==0) {
+ gLegacyMakeCodeGenerated=FALSE;
+ }
+ UsbScanner(DevInfo, Buffer);
+ } else {
+ if(Count==0) {
+ gEfiMakeCodeGenerated=FALSE;
+ }
+
+ if(USBKBC_CheckUsbDataBufferFull(8) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ USBKBC_SendToUsbDataBuffer(Buffer);
+
+ //
+ // Reload the typematic rate value
+ //
+ gUsbData->wRepeatRate = aTypematicRateDelayTable[
+ (gUsbData->wUSBKBC_StatusFlag & KBC_TYPE_DELAY_BIT_MASK) >>
+ KBC_TYPE_DELAY_BIT_SHIFT];
+ gUsbData->wRepeatCounter = 0;
+
+ //
+ // Enable periodic interrupt to catch the repeat key
+ //
+ if (Count==0) {
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ } else {
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBDPeriodicInterruptHandler
+//
+// Description: This routine is called every 16ms and is used to send
+// the characters read from USB keyboard to the keyboard
+// controller for legacy operation. Also this function updates
+// the keyboard LED status
+//
+// Input: fpHCStruc Pointer to the HCStruc structure
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBDPeriodicInterruptHandler (HC_STRUC* fpHcStruc)
+{
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ //(EIP83888+)>
+ if (!(*(UINT32*)gLastKeyCodeArray ||
+ *(UINT32*)(gLastKeyCodeArray + 4))) { //(EIP93637)
+ //<(EIP83888+)
+ //
+ // Keyboard data is zero, the key is released - stop repeating the key
+ //
+ USBKeyRepeat(NULL, 1); // Disable Key repeat
+ return;
+ } else {
+ //
+ // Check whether keyboard buffer is not empty;
+ // Execute Efi callback function if repeat counter is expired
+ //
+ 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;
+
+ USBKBKeyrepeatCallback();
+ }
+ //
+ // Reenable periodic interrupt handler
+ //
+ USBKeyRepeat(NULL, 2); // Enable Key repeat
+ }
+ } else { // Not under EFI
+ LegacyAutoRepeat(fpHcStruc);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbScanner
+//
+// Description: This routine is executed to convert USB scan codes into PS/2
+// make/bread codes.
+//
+// Input: fpDevInfo - USB keyboard device
+// fpBuffer - USB scan codes data buffer
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbScanner(
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpBuffer
+)
+{
+ if(gUsbData->kbc_support || ((gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON)
+ && (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_IRQ_SUPPORT))) {
+ USBKBC_GetAndStoreCCB();
+ USBKB_Scanner (fpDevInfo, fpBuffer);
+ USBKB_UpdateLEDState (0xFF);
+ }else {
+ USBKB_Int9(fpBuffer);
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: LegacyAutoRepeat
+//
+// Description: This routine is called periodically based on 8ms TD and used
+// to implement the key repeat.
+//
+// Input: Hc Pointer to the HCStruc structure
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+LegacyAutoRepeat(
+ HC_STRUC *Hc
+)
+{
+ if(gUsbData->kbc_support || ((gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON)
+ && (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_IRQ_SUPPORT))) {
+ SysKbcAutoRepeat(Hc);
+ } else {
+ SysNoKbcAutoRepeat();
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: USBKBKeyrepeatCallback
+//
+// Description: This routine is called every time the key repeat is requested
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKBKeyrepeatCallback()
+{
+ USB_KEY UsbKey;
+ USB_KB_BUFFER *KeyboardBuffer;
+
+ if(!gUsbData->RepeatKey) return; // Do nothing when there is no repeat key.
+
+ KeyboardBuffer = gUsbData->EfiKeyboardBuffer;
+
+ //
+ // If keyboard buffer is full, throw the first key out of the keyboard buffer.
+ //
+ if (((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == KeyboardBuffer->bHead) {
+
+ UsbKey.KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;
+ UsbKey.Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;
+
+ //
+ // adjust the head pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bHead = (UINT8)((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));
+ }
+
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = gUsbData->RepeatKey;
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = 1;
+
+ //
+ // adjust the tail pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bTail = (UINT8)((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: UsbKbdSetLed
+//
+// Description: This routine set the USB keyboard LED status.
+//
+// Input: DevInfo Pointer to device information structure
+// LedStatus LED status
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbKbdSetLed (
+ DEV_INFO *DevInfo,
+ UINT8 LedStatus
+)
+{
+ HC_STRUC *HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+ DEV_REQ DevReq = {0};
+ UINT8 Status;
+ UINT8 ReportId = 0;
+ UINT16 ReportLen;
+ UINT8 *ReportData = NULL;
+ UINT8 Index;
+
+ if ((DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) &&
+ !(DevInfo->HidReport.Flag & HID_REPORT_FLAG_LED_FLAG)) {
+ return USB_ERROR;
+ }
+
+ ReportData = USB_MemAlloc(GET_MEM_BLK_COUNT(4));
+ if (ReportData == NULL) return USB_ERROR;
+
+ ReportLen = 1;
+ ReportData[0] = LedStatus & 0x7;
+
+ if (DevInfo->HidReport.Flag & HID_REPORT_FLAG_REPORT_PROTOCOL) {
+ if (DevInfo->HidReport.Fields == NULL) {
+ USB_MemFree(ReportData, GET_MEM_BLK_COUNT(4));
+ return USB_ERROR;
+ }
+ for (Index = 0; Index < DevInfo->HidReport.FieldCount; Index++) {
+ //find start offset
+ if ((DevInfo->HidReport.Fields[Index]->UsagePage == 0x8) &&
+ (DevInfo->HidReport.Fields[Index]->ReportId != 0) &&
+ (DevInfo->HidReport.Fields[Index]->Usages[0] == 1)) {
+ ReportId = DevInfo->HidReport.Fields[Index]->ReportId;
+ ReportData[1] = ReportData[0];
+ ReportData[0] = ReportId;
+ ReportLen++;
+ }
+ }
+ }
+ if (DevInfo->IntOutEndpoint == 0) {
+ DevReq.wRequestType = HID_RQ_SET_REPORT;
+ DevReq.wValue = (0x02 << 8) | ReportId; // Output
+ DevReq.wIndex = DevInfo->bInterfaceNum;
+ DevReq.wDataLength = ReportLen;
+
+ Status = UsbControlTransfer(HcStruc, DevInfo, DevReq, USB_KBD_SET_LED_TIMEOUT_MS, ReportData);
+ } else {
+ Status = UsbInterruptTransfer(HcStruc, DevInfo, DevInfo->IntOutEndpoint,
+ DevInfo->IntOutMaxPkt, ReportData, ReportLen, USB_KBD_SET_LED_TIMEOUT_MS);
+ }
+
+ USB_MemFree(ReportData, GET_MEM_BLK_COUNT(4));
+ return Status;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************