⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

  Keyboard.c
    
Abstract:

  Helper functions for USB Keyboard Driver

Revision History

--*/
#include "keyboard.h"
#include "hid.h"

//
//USB Key Code to Efi key mapping table
//Format:<efi scan code>, <unicode without shift>, <unicode with shift>
//
static
UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
    SCAN_NULL,      'a',      'A',      // 0x04
    SCAN_NULL,      'b',      'B',      // 0x05
    SCAN_NULL,      'c',      'C',      // 0x06
    SCAN_NULL,      'd',      'D',      // 0x07
    SCAN_NULL,      'e',      'E',      // 0x08
    SCAN_NULL,      'f',      'F',      // 0x09
    SCAN_NULL,      'g',      'G',      // 0x0A
    SCAN_NULL,      'h',      'H',      // 0x0B
    SCAN_NULL,      'i',      'I',      // 0x0C
    SCAN_NULL,      'j',      'J',      // 0x0D
    SCAN_NULL,      'k',      'K',      // 0x0E
    SCAN_NULL,      'l',      'L',      // 0x0F
    SCAN_NULL,      'm',      'M',      // 0x10
    SCAN_NULL,      'n',      'N',      // 0x11
    SCAN_NULL,      'o',      'O',      // 0x12
    SCAN_NULL,      'p',      'P',      // 0x13
    SCAN_NULL,      'q',      'Q',      // 0x14
    SCAN_NULL,      'r',      'R',      // 0x15
    SCAN_NULL,      's',      'S',      // 0x16
    SCAN_NULL,      't',      'T',      // 0x17
    SCAN_NULL,      'u',      'U',      // 0x18
    SCAN_NULL,      'v',      'V',      // 0x19
    SCAN_NULL,      'w',      'W',      // 0x1A
    SCAN_NULL,      'x',      'X',      // 0x1B
    SCAN_NULL,      'y',      'Y',      // 0x1C
    SCAN_NULL,      'z',      'Z',      // 0x1D
    SCAN_NULL,      '1',      '!',      // 0x1E
    SCAN_NULL,      '2',      '@',      // 0x1F
    SCAN_NULL,      '3',      '#',      // 0x20
    SCAN_NULL,      '4',      '$',      // 0x21
    SCAN_NULL,      '5',      '%',      // 0x22
    SCAN_NULL,      '6',      '^',      // 0x23
    SCAN_NULL,      '7',      '&',      // 0x24
    SCAN_NULL,      '8',      '*',      // 0x25
    SCAN_NULL,      '9',      '(',      // 0x26
    SCAN_NULL,      '0',      ')',      // 0x27
    SCAN_NULL,      0x0d,     0x0d,     // 0x28   Enter
    SCAN_ESC,       0x00,     0x00,     // 0x29   Esc
    SCAN_NULL,      0x08,     0x08,     // 0x2A   Backspace
    SCAN_NULL,      0x09,     0x09,     // 0x2B   Tab
    SCAN_NULL,      ' ',      ' ',      // 0x2C   Spacebar
    SCAN_NULL,      '-',      '_',      // 0x2D
    SCAN_NULL,      '=',      '+',      // 0x2E
    SCAN_NULL,      '[',      '{',      // 0x2F
    SCAN_NULL,      ']',      '}',      // 0x30
    SCAN_NULL,      '\\',     '|',      // 0x31
    SCAN_NULL,      '\\',     '|',      // 0x32  Keyboard US \ and |
    SCAN_NULL,      ';',      ':',      // 0x33
    SCAN_NULL,      '\'',     '"',      // 0x34
    SCAN_NULL,      '`',      '~',      // 0x35  Keyboard Grave Accent and Tlide
    SCAN_NULL,      ',',      '<',      // 0x36
    SCAN_NULL,      '.',      '>',      // 0x37
    SCAN_NULL,      '/',      '?',      // 0x38
    SCAN_NULL,      0x00,     0x00,     // 0x39   CapsLock
    SCAN_F1,        0x00,     0x00,     // 0x3A
    SCAN_F2,        0x00,     0x00,     // 0x3B
    SCAN_F3,        0x00,     0x00,     // 0x3C  
    SCAN_F4,        0x00,     0x00,     // 0x3D  
    SCAN_F5,        0x00,     0x00,     // 0x3E
    SCAN_F6,        0x00,     0x00,     // 0x3F
    SCAN_F7,        0x00,     0x00,     // 0x40
    SCAN_F8,        0x00,     0x00,     // 0x41
    SCAN_F9,        0x00,     0x00,     // 0x42
    SCAN_F10,       0x00,     0x00,     // 0x43
    SCAN_NULL,      0x00,     0x00,     // 0x44   F11
    SCAN_NULL,      0x00,     0x00,     // 0x45   F12
    SCAN_NULL,      0x00,     0x00,     // 0x46   PrintScreen
    SCAN_NULL,      0x00,     0x00,     // 0x47   Scroll Lock
    SCAN_NULL,      0x00,     0x00,     // 0x48   Pause
    SCAN_INSERT,    0x00,     0x00,     // 0x49
    SCAN_HOME,      0x00,     0x00,     // 0x4A
    SCAN_PAGE_UP,   0x00,     0x00,     // 0x4B
    SCAN_DELETE,    0x00,     0x00,     // 0x4C
    SCAN_END,       0x00,     0x00,     // 0x4D
    SCAN_PAGE_DOWN, 0x00,     0x00,     // 0x4E
    SCAN_RIGHT,     0x00,     0x00,     // 0x4F
    SCAN_LEFT,      0x00,     0x00,     // 0x50
    SCAN_DOWN,      0x00,     0x00,     // 0x51
    SCAN_UP,        0x00,     0x00,     // 0x52
    SCAN_NULL,      0x00,     0x00,     // 0x53   NumLock
    SCAN_NULL,      '/',      '/',      // 0x54
    SCAN_NULL,      '*',      '*',      // 0x55
    SCAN_NULL,      '-',      '-',      // 0x56
    SCAN_NULL,      '+',      '+',      // 0x57
    SCAN_NULL,      0x0d,     0x0d,     // 0x58
    SCAN_END,       '1',      '1',      // 0x59
    SCAN_DOWN,      '2',      '2',      // 0x5A
    SCAN_PAGE_DOWN, '3',      '3',      // 0x5B
    SCAN_LEFT,      '4',      '4',      // 0x5C
    SCAN_NULL,      '5',      '5',      // 0x5D
    SCAN_RIGHT,     '6',      '6',      // 0x5E
    SCAN_HOME,      '7',      '7',      // 0x5F
    SCAN_UP,        '8',      '8',      // 0x60
    SCAN_PAGE_UP,   '9',      '9',      // 0x61
    SCAN_INSERT,    '0',      '0',      // 0x62
    SCAN_DELETE,    '.',      '.',      // 0x63
    SCAN_NULL,      '\\',     '|',      // 0x64 Keyboard Non-US \ and |
    SCAN_NULL,      0x00,     0x00,     // 0x65 Keyboard Application
    SCAN_NULL,      0x00,     0x00,     // 0x66 Keyboard Power
    SCAN_NULL,      '=' ,     '='      // 0x67 Keypad =
 }; 
    
STATIC KB_MODIFIER KB_Mod[8] = {
  { MOD_CONTROL_L,  0xe0 }, // 11100000 
  { MOD_CONTROL_R,  0xe4 }, // 11100100 
  { MOD_SHIFT_L,    0xe1 }, // 11100001 
  { MOD_SHIFT_R,    0xe5 }, // 11100101 
  { MOD_ALT_L,      0xe2 }, // 11100010 
  { MOD_ALT_R,      0xe6 }, // 11100110 
  { MOD_WIN_L,      0xe3 }, // 11100011 
  { MOD_WIN_R,      0xe7 }, // 11100111 
};


BOOLEAN
IsUSBKeyboard(
  IN  EFI_USB_IO_PROTOCOL       *UsbIo
  )
/*++
  
  Routine Description:
    Uses USB I/O to check whether the device is a USB Keyboard device.
  
  Arguments:
    UsbIo:    Points to a USB I/O protocol instance.
    
  Returns:
  
--*/  
{
  EFI_STATUS                      Status;
  EFI_USB_INTERFACE_DESCRIPTOR    InterfaceDescriptor;

  //
  // Get the Default interface descriptor, currently we 
  // assume it is interface 1
  //
  Status = UsbIo->UsbGetInterfaceDescriptor(
                        UsbIo,
                        &InterfaceDescriptor
                        );

  if(EFI_ERROR(Status)) {
    return FALSE;
  }    

  if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
    InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
    InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD) {
        
        return TRUE;
  }

  return FALSE; 
}


EFI_STATUS
InitUSBKeyboard(
  IN USB_KB_DEV   *UsbKeyboardDevice
  )
/*++
  
  Routine Description:
    Initialize USB Keyboard device and all private data structures.
    
  Arguments:
    UsbKeyboardDevice:    The USB_KB_DEV instance.
    
  Returns:
  
--*/
{
  UINT8           ConfigValue;
  UINT8           Protocol;
  UINT8           ReportId;
  UINT8           Duration;
  EFI_STATUS      Status;
  UINT32          TransferResult;

  
  InitUSBKeyBuffer(&(UsbKeyboardDevice->KeyboardBuffer));
  
  ConfigValue = 0x01;   // default configurations
  
  //
  // Uses default configuration to configure the USB Keyboard device.
  //
  Status = UsbSetDeviceConfiguration (
            UsbKeyboardDevice->UsbIo, 
            (UINT16)ConfigValue,
            &TransferResult
            );
  if(EFI_ERROR(Status)) {
    return EFI_DEVICE_ERROR;
  }
  
  UsbGetProtocolRequest(UsbKeyboardDevice->UsbIo,
                        UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
                        &Protocol
                        );
  //
  // Sets boot protocol for the USB Keyboard.
  // This driver only supports boot protocol.
  // !!BugBug: How about the device that does not support boot protocol?
  //
  if(Protocol != BOOT_PROTOCOL) {
    UsbSetProtocolRequest(
          UsbKeyboardDevice->UsbIo,
          UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
          BOOT_PROTOCOL
          );
  }   
  
  //
  // the duration is indefinite, so the endpoint will inhibit reporting forever,
  // and only reporting when a change is detected in the report data.
  //
  ReportId = 0;       // idle value for all report ID
  Duration = 0;   // idle forever until there is a key pressed and released.
  UsbSetIdleRequest(
                 UsbKeyboardDevice->UsbIo,
                 UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
                 ReportId,
                 Duration
                 );
  
  UsbKeyboardDevice->CtrlOn     = 0;
  UsbKeyboardDevice->AltOn      = 0;
  UsbKeyboardDevice->ShiftOn    = 0;
  UsbKeyboardDevice->NumLockOn  = 0 ;
  UsbKeyboardDevice->CapsOn     = 0 ;
  EfiZeroMem(UsbKeyboardDevice->LastKeyCodeArray, sizeof(UINT8)*8);
  
  //
  // Set a timer for repeat keys' generation.
  //
  if(UsbKeyboardDevice->RepeatTimer) {
    gBS->CloseEvent(UsbKeyboardDevice->RepeatTimer);
    UsbKeyboardDevice->RepeatTimer = 0;
  }  
  Status = gBS->CreateEvent (
            EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, 
            EFI_TPL_NOTIFY, 
            USBKeyboardRepeatHandler, 
            UsbKeyboardDevice, 
            &UsbKeyboardDevice->RepeatTimer
            ) ;
 
  return EFI_SUCCESS;
} 


EFI_STATUS
KeyboardHandler(
  IN  VOID          *Data,
  IN  UINTN         DataLength,
  IN  VOID          *Context,  
  IN  UINT32        Result
  )
/*++
  
  Routine Description:
    Handler function for USB Keyboard's asynchronous interrupt transfer.
    
  Arguments:
    Data:       A pointer to a buffer that is filled with key data which is
                retrieved via asynchronous interrupt transfer.
    DataLength: Indicates the size of the data buffer.
    Context:    Pointing to USB_KB_DEV instance.
    Result:     Indicates the result of the asynchronous interrupt transfer.
    
  Returns:
  
--*/  
{
  USB_KB_DEV              *UsbKeyboardDevice;
  EFI_USB_IO_PROTOCOL     *UsbIo;
  UINT8                   *CurKeyCodeBuffer;
  UINT8                   *OldKeyCodeBuffer;
  UINT8                   CurModifierMap;
  UINT8                   OldModifierMap;
  UINT8                   i;
  UINT8                   j;
  BOOLEAN                 Down;
  EFI_STATUS              Status;
  BOOLEAN                 KeyRelease,KeyPress;
  UINT8                   SavedTail;
  USB_KEY                 UsbKey;  
  UINT8                   NewRepeatKey = 0;
  UINT32                  UsbStatus;
  UINT8                   PacketSize;
  
  UsbKeyboardDevice = (USB_KB_DEV*)Context;
  ASSERT(UsbKeyboardDevice);
  
  UsbIo = UsbKeyboardDevice->UsbIo;
  
  //
  // Analyzes the Result and performs corresponding action.
  //
  if (Result != EFI_USB_NOERROR) {
    //
    // stop the repeat key generation if any
    //
    UsbKeyboardDevice->RepeatKey = 0;
    
    gBS->SetTimer(UsbKeyboardDevice->RepeatTimer, 
                  TimerCancel, 
                  USBKBD_REPEAT_RATE
                  );
    
    if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
      UsbClearEndpointHalt (
                UsbIo,
                UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
                &UsbStatus
                );
    }
    
    //
    // Delete & Submit this interrupt again
    //
    
    Status = UsbIo->UsbAsyncInterruptTransfer(
             UsbIo,
             UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
             FALSE,
             0,
             0,
             NULL,
             NULL
           );
    
    PacketSize =  (UINT8)(UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
      
    Status = UsbIo->UsbAsyncInterruptTransfer(
                      UsbIo,
                      UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
                      TRUE,
                      UsbKeyboardDevice->IntEndpointDescriptor.Interval,
                      PacketSize,
                      KeyboardHandler,
                      UsbKeyboardDevice
                );
    return EFI_DEVICE_ERROR;
  }
  
  if(DataLength == 0 || Data == NULL) {
    return EFI_SUCCESS;
  }
  
  CurKeyCodeBuffer = (UINT8*)Data;    
  OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray ;
  
  //
  // checks for new key stroke.
  // if no new key got, return immediately.
  //
  for (i = 0; i < 8; i ++) {
    if(OldKeyCodeBuffer[i] != CurKeyCodeBuffer[i]) {
      break;
    }
  }
  if(i == 8) {
    return EFI_SUCCESS;
  }
  
  //
  // Parse the modifier key
  //
  
  CurModifierMap = CurKeyCodeBuffer[0];
  OldModifierMap = OldKeyCodeBuffer[0];

  //
  // handle modifier key's pressing or releasing situation.
  //
  for (i = 0; i < 8; i ++) {

    if ((CurModifierMap & KB_Mod[i].Mask) != 
                      (OldModifierMap & KB_Mod[i].Mask)) {
      //
      // if current modifier key is up, then 
      // CurModifierMap & KB_Mod[i].Mask = 0;
      // otherwize it is a non-zero value.
      // Inserts the pressed modifier key into key buffer.
      //
      Down = (UINT8)(CurModifierMap & KB_Mod[i].Mask);
      InsertKeyCode(&(UsbKeyboardDevice->KeyboardBuffer),KB_Mod[i].Key,Down);
    } 
  }
  
  //
  // handle normal key's releasing situation
  //  
  KeyRelease = FALSE;
  for (i = 2; i < 8; i ++) {
    
    if(!USBKBD_VALID_KEYCODE(OldKeyCodeBuffer[i])) {
      continue;
    }
    
    KeyRelease = TRUE;
    for (j = 2; j < 8; j ++) {
      
      if(!USBKBD_VALID_KEYCODE(CurKeyCodeBuffer[j])) {
        continue;
      }
        
      if (OldKeyCodeBuffer[i] == CurKeyCodeBuffer[j]) {
        KeyRelease = FALSE;
        break;
      }
    }
    if (KeyRelease) {
      InsertKeyCode(&(UsbKeyboardDevice->KeyboardBuffer),OldKeyCodeBuffer[i],0);
      //
      // the original reapeat key is released.
      //
      if (OldKeyCodeBuffer[i] == UsbKeyboardDevice->RepeatKey) {
        UsbKeyboardDevice->RepeatKey = 0;
      }
    }
  }
  
  
  //
  // original repeat key is released, cancel the repeat timer
  //
  if (UsbKeyboardDevice->RepeatKey == 0) {
    gBS->SetTimer(UsbKeyboardDevice->RepeatTimer, 
                  TimerCancel, 
                  USBKBD_REPEAT_RATE
                  );
  }
  
  //
  // handle normal key's pressing situation
  //
  KeyPress = FALSE;
  for (i = 2; i < 8; i ++) {
    
    if(!USBKBD_VALID_KEYCODE(CurKeyCodeBuffer[i])) {
      continue;
    }
    
    KeyPress = TRUE;
    for (j = 2; j < 8; j ++) {
      
      if(!USBKBD_VALID_KEYCODE(OldKeyCodeBuffer[j])) {
        continue;
      }
        
      if (CurKeyCodeBuffer[i] == OldKeyCodeBuffer[j]) {
        KeyPress = FALSE;
        break;
      }
    }
    if(KeyPress) {    
      InsertKeyCode(&(UsbKeyboardDevice->KeyboardBuffer),CurKeyCodeBuffer[i],1);
      //
      // NumLock pressed or CapsLock pressed
      //
      if(CurKeyCodeBuffer[i] == 0x53 || CurKeyCodeBuffer[i] == 0x39) {
        UsbKeyboardDevice->RepeatKey = 0;
      } else {
        NewRepeatKey = CurKeyCodeBuffer[i];
        //
        // do not repeat the original repeated key
        //
        UsbKeyboardDevice->RepeatKey = 0;
      }
    }   
  } 
  
  //
  // Update LastKeycodeArray[] buffer in the 
  // Usb Keyboard Device data structure.
  //
  for (i = 0; i < 8; i ++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -