3 Copyright (c) 2004 - 2007, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
26 #include "keyboard.h"
\r
30 // Driver model protocol interface
\r
34 USBKeyboardDriverBindingEntryPoint (
\r
35 IN EFI_HANDLE ImageHandle,
\r
36 IN EFI_SYSTEM_TABLE *SystemTable
\r
41 USBKeyboardDriverBindingSupported (
\r
42 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
43 IN EFI_HANDLE Controller,
\r
44 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
49 USBKeyboardDriverBindingStart (
\r
50 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
51 IN EFI_HANDLE Controller,
\r
52 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
57 USBKeyboardDriverBindingStop (
\r
58 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
59 IN EFI_HANDLE Controller,
\r
60 IN UINTN NumberOfChildren,
\r
61 IN EFI_HANDLE *ChildHandleBuffer
\r
65 // Simple Text In Protocol Interface
\r
71 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
72 IN BOOLEAN ExtendedVerification
\r
78 USBKeyboardReadKeyStroke (
\r
79 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
80 OUT EFI_INPUT_KEY *Key
\r
86 USBKeyboardWaitForKey (
\r
96 USBKeyboardCheckForKey (
\r
97 IN USB_KB_DEV *UsbKeyboardDevice
\r
100 EFI_GUID gEfiUsbKeyboardDriverGuid = {
\r
101 0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}
\r
105 // USB Keyboard Driver Global Variables
\r
107 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
\r
108 USBKeyboardDriverBindingSupported,
\r
109 USBKeyboardDriverBindingStart,
\r
110 USBKeyboardDriverBindingStop,
\r
118 USBKeyboardDriverBindingEntryPoint (
\r
119 IN EFI_HANDLE ImageHandle,
\r
120 IN EFI_SYSTEM_TABLE *SystemTable
\r
124 Routine Description:
\r
125 Driver Entry Point.
\r
128 ImageHandle - EFI_HANDLE
\r
129 SystemTable - EFI_SYSTEM_TABLE
\r
135 return EfiLibInstallAllDriverProtocols (
\r
138 &gUsbKeyboardDriverBinding,
\r
140 &gUsbKeyboardComponentName,
\r
151 @param This EFI_DRIVER_BINDING_PROTOCOL
\r
152 @param Controller Controller handle
\r
153 @param RemainingDevicePath EFI_DEVICE_PATH_PROTOCOL
\r
159 USBKeyboardDriverBindingSupported (
\r
160 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
161 IN EFI_HANDLE Controller,
\r
162 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
165 EFI_STATUS OpenStatus;
\r
166 EFI_USB_IO_PROTOCOL *UsbIo;
\r
170 // Check if USB_IO protocol is attached on the controller handle.
\r
172 OpenStatus = gBS->OpenProtocol (
\r
174 &gEfiUsbIoProtocolGuid,
\r
176 This->DriverBindingHandle,
\r
178 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
180 if (EFI_ERROR (OpenStatus)) {
\r
185 // Use the USB I/O protocol interface to check whether the Controller is
\r
186 // the Keyboard controller that can be managed by this driver.
\r
188 Status = EFI_SUCCESS;
\r
190 if (!IsUSBKeyboard (UsbIo)) {
\r
191 Status = EFI_UNSUPPORTED;
\r
194 gBS->CloseProtocol (
\r
196 &gEfiUsbIoProtocolGuid,
\r
197 This->DriverBindingHandle,
\r
208 @param This EFI_DRIVER_BINDING_PROTOCOL
\r
209 @param Controller Controller handle
\r
210 @param RemainingDevicePath EFI_DEVICE_PATH_PROTOCOL
\r
212 @retval EFI_SUCCESS Success
\r
213 @retval EFI_OUT_OF_RESOURCES Can't allocate memory
\r
214 @retval EFI_UNSUPPORTED The Start routine fail
\r
219 USBKeyboardDriverBindingStart (
\r
220 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
221 IN EFI_HANDLE Controller,
\r
222 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
\r
226 EFI_USB_IO_PROTOCOL *UsbIo;
\r
227 USB_KB_DEV *UsbKeyboardDevice;
\r
228 UINT8 EndpointNumber;
\r
229 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
\r
231 UINT8 EndpointAddr;
\r
232 UINT8 PollingInterval;
\r
236 UsbKeyboardDevice = NULL;
\r
240 // Open USB_IO Protocol
\r
242 Status = gBS->OpenProtocol (
\r
244 &gEfiUsbIoProtocolGuid,
\r
246 This->DriverBindingHandle,
\r
248 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
250 if (EFI_ERROR (Status)) {
\r
254 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));
\r
255 if (UsbKeyboardDevice == NULL) {
\r
256 gBS->CloseProtocol (
\r
258 &gEfiUsbIoProtocolGuid,
\r
259 This->DriverBindingHandle,
\r
262 return EFI_OUT_OF_RESOURCES;
\r
265 // Get the Device Path Protocol on Controller's handle
\r
267 Status = gBS->OpenProtocol (
\r
269 &gEfiDevicePathProtocolGuid,
\r
270 (VOID **) &UsbKeyboardDevice->DevicePath,
\r
271 This->DriverBindingHandle,
\r
273 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
276 if (EFI_ERROR (Status)) {
\r
277 gBS->FreePool (UsbKeyboardDevice);
\r
278 gBS->CloseProtocol (
\r
280 &gEfiUsbIoProtocolGuid,
\r
281 This->DriverBindingHandle,
\r
287 // Report that the usb keyboard is being enabled
\r
289 KbdReportStatusCode (
\r
290 UsbKeyboardDevice->DevicePath,
\r
292 PcdGet32 (PcdStatusCodeValueKeyboardEnable)
\r
296 // This is pretty close to keyboard detection, so log progress
\r
298 KbdReportStatusCode (
\r
299 UsbKeyboardDevice->DevicePath,
\r
301 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect)
\r
305 // Initialize UsbKeyboardDevice
\r
307 UsbKeyboardDevice->UsbIo = UsbIo;
\r
310 // Get interface & endpoint descriptor
\r
312 UsbIo->UsbGetInterfaceDescriptor (
\r
314 &UsbKeyboardDevice->InterfaceDescriptor
\r
317 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
\r
319 for (Index = 0; Index < EndpointNumber; Index++) {
\r
321 UsbIo->UsbGetEndpointDescriptor (
\r
324 &EndpointDescriptor
\r
327 if ((EndpointDescriptor.Attributes & 0x03) == 0x03) {
\r
329 // We only care interrupt endpoint here
\r
331 CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
\r
338 // No interrupt endpoint found, then return unsupported.
\r
340 gBS->FreePool (UsbKeyboardDevice);
\r
341 gBS->CloseProtocol (
\r
343 &gEfiUsbIoProtocolGuid,
\r
344 This->DriverBindingHandle,
\r
347 return EFI_UNSUPPORTED;
\r
350 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
\r
351 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
\r
352 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
\r
353 Status = gBS->CreateEvent (
\r
356 USBKeyboardWaitForKey,
\r
358 &(UsbKeyboardDevice->SimpleInput.WaitForKey)
\r
361 if (EFI_ERROR (Status)) {
\r
362 gBS->FreePool (UsbKeyboardDevice);
\r
363 gBS->CloseProtocol (
\r
365 &gEfiUsbIoProtocolGuid,
\r
366 This->DriverBindingHandle,
\r
373 // Install simple txt in protocol interface
\r
374 // for the usb keyboard device.
\r
375 // Usb keyboard is a hot plug device, and expected to work immediately
\r
376 // when plugging into system, so a HotPlugDeviceGuid is installed onto
\r
377 // the usb keyboard device handle, to distinguish it from other conventional
\r
378 // console devices.
\r
380 Status = gBS->InstallMultipleProtocolInterfaces (
\r
382 &gEfiSimpleTextInProtocolGuid,
\r
383 &UsbKeyboardDevice->SimpleInput,
\r
384 &gEfiHotPlugDeviceGuid,
\r
388 if (EFI_ERROR (Status)) {
\r
389 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
\r
390 gBS->FreePool (UsbKeyboardDevice);
\r
391 gBS->CloseProtocol (
\r
393 &gEfiUsbIoProtocolGuid,
\r
394 This->DriverBindingHandle,
\r
401 // Reset USB Keyboard Device
\r
403 Status = UsbKeyboardDevice->SimpleInput.Reset (
\r
404 &UsbKeyboardDevice->SimpleInput,
\r
407 if (EFI_ERROR (Status)) {
\r
408 gBS->UninstallMultipleProtocolInterfaces (
\r
410 &gEfiSimpleTextInProtocolGuid,
\r
411 &UsbKeyboardDevice->SimpleInput,
\r
412 &gEfiHotPlugDeviceGuid,
\r
416 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
\r
417 gBS->FreePool (UsbKeyboardDevice);
\r
418 gBS->CloseProtocol (
\r
420 &gEfiUsbIoProtocolGuid,
\r
421 This->DriverBindingHandle,
\r
427 // submit async interrupt transfer
\r
429 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;
\r
430 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;
\r
431 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
\r
433 Status = UsbIo->UsbAsyncInterruptTransfer (
\r
443 if (EFI_ERROR (Status)) {
\r
445 gBS->UninstallMultipleProtocolInterfaces (
\r
447 &gEfiSimpleTextInProtocolGuid,
\r
448 &UsbKeyboardDevice->SimpleInput,
\r
449 &gEfiHotPlugDeviceGuid,
\r
453 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
\r
454 gBS->FreePool (UsbKeyboardDevice);
\r
455 gBS->CloseProtocol (
\r
457 &gEfiUsbIoProtocolGuid,
\r
458 This->DriverBindingHandle,
\r
464 UsbKeyboardDevice->ControllerNameTable = NULL;
\r
467 gUsbKeyboardComponentName.SupportedLanguages,
\r
468 &UsbKeyboardDevice->ControllerNameTable,
\r
469 L"Generic Usb Keyboard"
\r
472 return EFI_SUCCESS;
\r
480 @param This EFI_DRIVER_BINDING_PROTOCOL
\r
481 @param Controller Controller handle
\r
482 @param NumberOfChildren Child handle number
\r
483 @param ChildHandleBuffer Child handle buffer
\r
485 @retval EFI_SUCCESS Success
\r
486 @retval EFI_UNSUPPORTED Can't support
\r
491 USBKeyboardDriverBindingStop (
\r
492 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
493 IN EFI_HANDLE Controller,
\r
494 IN UINTN NumberOfChildren,
\r
495 IN EFI_HANDLE *ChildHandleBuffer
\r
499 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;
\r
500 USB_KB_DEV *UsbKeyboardDevice;
\r
502 Status = gBS->OpenProtocol (
\r
504 &gEfiSimpleTextInProtocolGuid,
\r
505 (VOID **) &SimpleInput,
\r
506 This->DriverBindingHandle,
\r
508 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
510 if (EFI_ERROR (Status)) {
\r
511 return EFI_UNSUPPORTED;
\r
515 // Get USB_KB_DEV instance.
\r
517 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);
\r
519 gBS->CloseProtocol (
\r
521 &gEfiSimpleTextInProtocolGuid,
\r
522 This->DriverBindingHandle,
\r
527 // Uninstall the Asyn Interrupt Transfer from this device
\r
528 // will disable the key data input from this device
\r
530 KbdReportStatusCode (
\r
531 UsbKeyboardDevice->DevicePath,
\r
533 PcdGet32 (PcdStatusCodeValueKeyboardDisable)
\r
537 // Destroy asynchronous interrupt transfer
\r
539 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (
\r
540 UsbKeyboardDevice->UsbIo,
\r
541 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
\r
543 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
\r
549 gBS->CloseProtocol (
\r
551 &gEfiUsbIoProtocolGuid,
\r
552 This->DriverBindingHandle,
\r
556 Status = gBS->UninstallMultipleProtocolInterfaces (
\r
558 &gEfiSimpleTextInProtocolGuid,
\r
559 &UsbKeyboardDevice->SimpleInput,
\r
560 &gEfiHotPlugDeviceGuid,
\r
565 // free all the resources.
\r
567 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
\r
568 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
\r
569 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
\r
571 if (UsbKeyboardDevice->ControllerNameTable != NULL) {
\r
572 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
\r
575 gBS->FreePool (UsbKeyboardDevice);
\r
584 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset() function.
\r
586 This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
\r
587 ExtendedVerification
\r
588 Indicates that the driver may perform a more exhaustive
\r
589 verification operation of the device during reset.
\r
591 @retval EFI_SUCCESS Success
\r
592 @retval EFI_DEVICE_ERROR Hardware Error
\r
598 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
599 IN BOOLEAN ExtendedVerification
\r
603 USB_KB_DEV *UsbKeyboardDevice;
\r
605 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
\r
607 KbdReportStatusCode (
\r
608 UsbKeyboardDevice->DevicePath,
\r
610 PcdGet32 (PcdStatusCodeValueKeyboardReset)
\r
614 // Non Exhaustive reset:
\r
615 // only reset private data structures.
\r
617 if (!ExtendedVerification) {
\r
619 // Clear the key buffer of this Usb keyboard
\r
621 KbdReportStatusCode (
\r
622 UsbKeyboardDevice->DevicePath,
\r
624 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer)
\r
627 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
\r
628 UsbKeyboardDevice->CurKeyChar = 0;
\r
629 return EFI_SUCCESS;
\r
633 // Exhaustive reset
\r
635 Status = InitUSBKeyboard (UsbKeyboardDevice);
\r
636 UsbKeyboardDevice->CurKeyChar = 0;
\r
637 if (EFI_ERROR (Status)) {
\r
638 return EFI_DEVICE_ERROR;
\r
641 return EFI_SUCCESS;
\r
646 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.
\r
648 This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
\r
649 Key A pointer to a buffer that is filled in with the keystroke
\r
650 information for the key that was pressed.
\r
652 @retval EFI_SUCCESS Success
\r
658 USBKeyboardReadKeyStroke (
\r
659 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
660 OUT EFI_INPUT_KEY *Key
\r
663 USB_KB_DEV *UsbKeyboardDevice;
\r
667 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
\r
670 // if there is no saved ASCII byte, fetch it
\r
671 // by calling USBKeyboardCheckForKey().
\r
673 if (UsbKeyboardDevice->CurKeyChar == 0) {
\r
674 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
\r
675 if (EFI_ERROR (Status)) {
\r
680 Key->UnicodeChar = 0;
\r
681 Key->ScanCode = SCAN_NULL;
\r
683 KeyChar = UsbKeyboardDevice->CurKeyChar;
\r
685 UsbKeyboardDevice->CurKeyChar = 0;
\r
688 // Translate saved ASCII byte into EFI_INPUT_KEY
\r
690 Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);
\r
698 Handler function for WaitForKey event.
\r
700 Event Event to be signaled when a key is pressed.
\r
701 Context Points to USB_KB_DEV instance.
\r
709 USBKeyboardWaitForKey (
\r
710 IN EFI_EVENT Event,
\r
714 USB_KB_DEV *UsbKeyboardDevice;
\r
716 UsbKeyboardDevice = (USB_KB_DEV *) Context;
\r
718 if (UsbKeyboardDevice->CurKeyChar == 0) {
\r
720 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {
\r
725 // If has key pending, signal the event.
\r
727 gBS->SignalEvent (Event);
\r
733 Check whether there is key pending.
\r
735 UsbKeyboardDevice The USB_KB_DEV instance.
\r
737 @retval EFI_SUCCESS Success
\r
742 USBKeyboardCheckForKey (
\r
743 IN USB_KB_DEV *UsbKeyboardDevice
\r
750 // Fetch raw data from the USB keyboard input,
\r
751 // and translate it into ASCII data.
\r
753 Status = USBParseKey (UsbKeyboardDevice, &KeyChar);
\r
754 if (EFI_ERROR (Status)) {
\r
758 UsbKeyboardDevice->CurKeyChar = KeyChar;
\r
759 return EFI_SUCCESS;
\r
764 Report Status Code in Usb Bot Driver
\r
766 @param DevicePath Use this to get Device Path
\r
767 @param CodeType Status Code Type
\r
768 @param CodeValue Status Code Value
\r
774 KbdReportStatusCode (
\r
775 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
\r
776 IN EFI_STATUS_CODE_TYPE CodeType,
\r
777 IN EFI_STATUS_CODE_VALUE Value
\r
781 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
\r