]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c
Add some definitions for efi event in Uefi/UefiSpec.h to follow spec.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbKb / Dxe / efikey.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EfiKey.c
15
16 Abstract:
17
18 USB Keyboard Driver
19
20 Revision History
21
22 --*/
23
24 #include "efikey.h"
25 #include "keyboard.h"
26
27 //
28 // Simple Text In Protocol Interface
29 //
30 STATIC
31 EFI_STATUS
32 EFIAPI
33 USBKeyboardReset (
34 IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
35 IN BOOLEAN ExtendedVerification
36 );
37
38 STATIC
39 EFI_STATUS
40 EFIAPI
41 USBKeyboardReadKeyStroke (
42 IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
43 OUT EFI_INPUT_KEY *Key
44 );
45
46 STATIC
47 VOID
48 EFIAPI
49 USBKeyboardWaitForKey (
50 IN EFI_EVENT Event,
51 IN VOID *Context
52 );
53
54 //
55 // Helper functions
56 //
57 STATIC
58 EFI_STATUS
59 USBKeyboardCheckForKey (
60 IN USB_KB_DEV *UsbKeyboardDevice
61 );
62
63 //
64 // USB Keyboard Driver Global Variables
65 //
66 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
67 USBKeyboardDriverBindingSupported,
68 USBKeyboardDriverBindingStart,
69 USBKeyboardDriverBindingStop,
70 0xa,
71 NULL,
72 NULL
73 };
74
75 EFI_STATUS
76 EFIAPI
77 USBKeyboardDriverBindingSupported (
78 IN EFI_DRIVER_BINDING_PROTOCOL *This,
79 IN EFI_HANDLE Controller,
80 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
81 )
82 /*++
83
84 Routine Description:
85 Supported.
86
87 Arguments:
88 This - EFI_DRIVER_BINDING_PROTOCOL
89 Controller - Controller handle
90 RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL
91 Returns:
92 EFI_STATUS
93
94 --*/
95 {
96 EFI_STATUS OpenStatus;
97 EFI_USB_IO_PROTOCOL *UsbIo;
98 EFI_STATUS Status;
99
100 //
101 // Check if USB_IO protocol is attached on the controller handle.
102 //
103 OpenStatus = gBS->OpenProtocol (
104 Controller,
105 &gEfiUsbIoProtocolGuid,
106 (VOID **) &UsbIo,
107 This->DriverBindingHandle,
108 Controller,
109 EFI_OPEN_PROTOCOL_BY_DRIVER
110 );
111 if (EFI_ERROR (OpenStatus)) {
112 return OpenStatus;
113 }
114
115 //
116 // Use the USB I/O protocol interface to check whether the Controller is
117 // the Keyboard controller that can be managed by this driver.
118 //
119 Status = EFI_SUCCESS;
120
121 if (!IsUSBKeyboard (UsbIo)) {
122 Status = EFI_UNSUPPORTED;
123 }
124
125 gBS->CloseProtocol (
126 Controller,
127 &gEfiUsbIoProtocolGuid,
128 This->DriverBindingHandle,
129 Controller
130 );
131
132 return Status;
133 }
134
135 EFI_STATUS
136 EFIAPI
137 USBKeyboardDriverBindingStart (
138 IN EFI_DRIVER_BINDING_PROTOCOL *This,
139 IN EFI_HANDLE Controller,
140 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
141 )
142 /*++
143
144 Routine Description:
145 Start.
146
147 Arguments:
148 This - EFI_DRIVER_BINDING_PROTOCOL
149 Controller - Controller handle
150 RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL
151 Returns:
152 EFI_SUCCESS - Success
153 EFI_OUT_OF_RESOURCES - Can't allocate memory
154 EFI_UNSUPPORTED - The Start routine fail
155 --*/
156 {
157 EFI_STATUS Status;
158 EFI_USB_IO_PROTOCOL *UsbIo;
159 USB_KB_DEV *UsbKeyboardDevice;
160 UINT8 EndpointNumber;
161 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
162 UINT8 Index;
163 UINT8 EndpointAddr;
164 UINT8 PollingInterval;
165 UINT8 PacketSize;
166 BOOLEAN Found;
167
168 UsbKeyboardDevice = NULL;
169 Found = FALSE;
170
171 //
172 // Open USB_IO Protocol
173 //
174 Status = gBS->OpenProtocol (
175 Controller,
176 &gEfiUsbIoProtocolGuid,
177 (VOID **) &UsbIo,
178 This->DriverBindingHandle,
179 Controller,
180 EFI_OPEN_PROTOCOL_BY_DRIVER
181 );
182 if (EFI_ERROR (Status)) {
183 return Status;
184 }
185
186 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));
187 if (UsbKeyboardDevice == NULL) {
188 gBS->CloseProtocol (
189 Controller,
190 &gEfiUsbIoProtocolGuid,
191 This->DriverBindingHandle,
192 Controller
193 );
194 return EFI_OUT_OF_RESOURCES;
195 }
196 //
197 // Get the Device Path Protocol on Controller's handle
198 //
199 Status = gBS->OpenProtocol (
200 Controller,
201 &gEfiDevicePathProtocolGuid,
202 (VOID **) &UsbKeyboardDevice->DevicePath,
203 This->DriverBindingHandle,
204 Controller,
205 EFI_OPEN_PROTOCOL_GET_PROTOCOL
206 );
207
208 if (EFI_ERROR (Status)) {
209 gBS->FreePool (UsbKeyboardDevice);
210 gBS->CloseProtocol (
211 Controller,
212 &gEfiUsbIoProtocolGuid,
213 This->DriverBindingHandle,
214 Controller
215 );
216 return Status;
217 }
218 //
219 // Report that the usb keyboard is being enabled
220 //
221 KbdReportStatusCode (
222 UsbKeyboardDevice->DevicePath,
223 EFI_PROGRESS_CODE,
224 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE)
225 );
226
227 //
228 // This is pretty close to keyboard detection, so log progress
229 //
230 KbdReportStatusCode (
231 UsbKeyboardDevice->DevicePath,
232 EFI_PROGRESS_CODE,
233 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT)
234 );
235
236 //
237 // Initialize UsbKeyboardDevice
238 //
239 UsbKeyboardDevice->UsbIo = UsbIo;
240
241 //
242 // Get interface & endpoint descriptor
243 //
244 UsbIo->UsbGetInterfaceDescriptor (
245 UsbIo,
246 &UsbKeyboardDevice->InterfaceDescriptor
247 );
248
249 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
250
251 for (Index = 0; Index < EndpointNumber; Index++) {
252
253 UsbIo->UsbGetEndpointDescriptor (
254 UsbIo,
255 Index,
256 &EndpointDescriptor
257 );
258
259 if ((EndpointDescriptor.Attributes & 0x03) == 0x03) {
260 //
261 // We only care interrupt endpoint here
262 //
263 CopyMem (&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
264 Found = TRUE;
265 }
266 }
267
268 if (!Found) {
269 //
270 // No interrupt endpoint found, then return unsupported.
271 //
272 gBS->FreePool (UsbKeyboardDevice);
273 gBS->CloseProtocol (
274 Controller,
275 &gEfiUsbIoProtocolGuid,
276 This->DriverBindingHandle,
277 Controller
278 );
279 return EFI_UNSUPPORTED;
280 }
281
282 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
283 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
284 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
285 Status = gBS->CreateEvent (
286 EVT_NOTIFY_WAIT,
287 TPL_NOTIFY,
288 USBKeyboardWaitForKey,
289 UsbKeyboardDevice,
290 &(UsbKeyboardDevice->SimpleInput.WaitForKey)
291 );
292
293 if (EFI_ERROR (Status)) {
294 gBS->FreePool (UsbKeyboardDevice);
295 gBS->CloseProtocol (
296 Controller,
297 &gEfiUsbIoProtocolGuid,
298 This->DriverBindingHandle,
299 Controller
300 );
301 return Status;
302 }
303
304 //
305 // Install simple txt in protocol interface
306 // for the usb keyboard device.
307 // Usb keyboard is a hot plug device, and expected to work immediately
308 // when plugging into system, so a HotPlugDeviceGuid is installed onto
309 // the usb keyboard device handle, to distinguish it from other conventional
310 // console devices.
311 //
312 Status = gBS->InstallMultipleProtocolInterfaces (
313 &Controller,
314 &gEfiSimpleTextInProtocolGuid,
315 &UsbKeyboardDevice->SimpleInput,
316 &gEfiHotPlugDeviceGuid,
317 NULL,
318 NULL
319 );
320 if (EFI_ERROR (Status)) {
321 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
322 gBS->FreePool (UsbKeyboardDevice);
323 gBS->CloseProtocol (
324 Controller,
325 &gEfiUsbIoProtocolGuid,
326 This->DriverBindingHandle,
327 Controller
328 );
329 return Status;
330 }
331
332 //
333 // Reset USB Keyboard Device
334 //
335 Status = UsbKeyboardDevice->SimpleInput.Reset (
336 &UsbKeyboardDevice->SimpleInput,
337 TRUE
338 );
339 if (EFI_ERROR (Status)) {
340 gBS->UninstallMultipleProtocolInterfaces (
341 Controller,
342 &gEfiSimpleTextInProtocolGuid,
343 &UsbKeyboardDevice->SimpleInput,
344 &gEfiHotPlugDeviceGuid,
345 NULL,
346 NULL
347 );
348 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
349 gBS->FreePool (UsbKeyboardDevice);
350 gBS->CloseProtocol (
351 Controller,
352 &gEfiUsbIoProtocolGuid,
353 This->DriverBindingHandle,
354 Controller
355 );
356 return Status;
357 }
358 //
359 // submit async interrupt transfer
360 //
361 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;
362 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;
363 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
364
365 Status = UsbIo->UsbAsyncInterruptTransfer (
366 UsbIo,
367 EndpointAddr,
368 TRUE,
369 PollingInterval,
370 PacketSize,
371 KeyboardHandler,
372 UsbKeyboardDevice
373 );
374
375 if (EFI_ERROR (Status)) {
376
377 gBS->UninstallMultipleProtocolInterfaces (
378 Controller,
379 &gEfiSimpleTextInProtocolGuid,
380 &UsbKeyboardDevice->SimpleInput,
381 &gEfiHotPlugDeviceGuid,
382 NULL,
383 NULL
384 );
385 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
386 gBS->FreePool (UsbKeyboardDevice);
387 gBS->CloseProtocol (
388 Controller,
389 &gEfiUsbIoProtocolGuid,
390 This->DriverBindingHandle,
391 Controller
392 );
393 return Status;
394 }
395
396 UsbKeyboardDevice->ControllerNameTable = NULL;
397 AddUnicodeString (
398 "eng",
399 gUsbKeyboardComponentName.SupportedLanguages,
400 &UsbKeyboardDevice->ControllerNameTable,
401 (CHAR16 *) L"Generic Usb Keyboard"
402 );
403
404 return EFI_SUCCESS;
405 }
406
407
408 EFI_STATUS
409 EFIAPI
410 USBKeyboardDriverBindingStop (
411 IN EFI_DRIVER_BINDING_PROTOCOL *This,
412 IN EFI_HANDLE Controller,
413 IN UINTN NumberOfChildren,
414 IN EFI_HANDLE *ChildHandleBuffer
415 )
416 /*++
417
418 Routine Description:
419 Stop.
420
421 Arguments:
422 This - EFI_DRIVER_BINDING_PROTOCOL
423 Controller - Controller handle
424 NumberOfChildren - Child handle number
425 ChildHandleBuffer - Child handle buffer
426 Returns:
427 EFI_SUCCESS - Success
428 EFI_UNSUPPORTED - Can't support
429 --*/
430 {
431 EFI_STATUS Status;
432 EFI_SIMPLE_TEXT_IN_PROTOCOL *SimpleInput;
433 USB_KB_DEV *UsbKeyboardDevice;
434
435 Status = gBS->OpenProtocol (
436 Controller,
437 &gEfiSimpleTextInProtocolGuid,
438 (VOID **) &SimpleInput,
439 This->DriverBindingHandle,
440 Controller,
441 EFI_OPEN_PROTOCOL_BY_DRIVER
442 );
443 if (EFI_ERROR (Status)) {
444 return EFI_UNSUPPORTED;
445 }
446
447 //
448 // Get USB_KB_DEV instance.
449 //
450 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);
451
452 gBS->CloseProtocol (
453 Controller,
454 &gEfiSimpleTextInProtocolGuid,
455 This->DriverBindingHandle,
456 Controller
457 );
458
459 //
460 // Uninstall the Asyn Interrupt Transfer from this device
461 // will disable the key data input from this device
462 //
463 KbdReportStatusCode (
464 UsbKeyboardDevice->DevicePath,
465 EFI_PROGRESS_CODE,
466 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE)
467 );
468
469 //
470 // Destroy asynchronous interrupt transfer
471 //
472 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (
473 UsbKeyboardDevice->UsbIo,
474 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
475 FALSE,
476 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
477 0,
478 NULL,
479 NULL
480 );
481
482 gBS->CloseProtocol (
483 Controller,
484 &gEfiUsbIoProtocolGuid,
485 This->DriverBindingHandle,
486 Controller
487 );
488
489 Status = gBS->UninstallMultipleProtocolInterfaces (
490 Controller,
491 &gEfiSimpleTextInProtocolGuid,
492 &UsbKeyboardDevice->SimpleInput,
493 &gEfiHotPlugDeviceGuid,
494 NULL,
495 NULL
496 );
497 //
498 // free all the resources.
499 //
500 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
501 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
502 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
503
504 if (UsbKeyboardDevice->ControllerNameTable != NULL) {
505 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
506 }
507
508 gBS->FreePool (UsbKeyboardDevice);
509
510 return Status;
511
512 }
513
514
515 EFI_STATUS
516 EFIAPI
517 USBKeyboardReset (
518 IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
519 IN BOOLEAN ExtendedVerification
520 )
521 /*++
522
523 Routine Description:
524 Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.Reset() function.
525
526 Arguments:
527 This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance.
528 ExtendedVerification
529 Indicates that the driver may perform a more exhaustive
530 verification operation of the device during reset.
531
532 Returns:
533 EFI_SUCCESS - Success
534 EFI_DEVICE_ERROR - Hardware Error
535 --*/
536 {
537 EFI_STATUS Status;
538 USB_KB_DEV *UsbKeyboardDevice;
539
540 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
541
542 KbdReportStatusCode (
543 UsbKeyboardDevice->DevicePath,
544 EFI_PROGRESS_CODE,
545 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET)
546 );
547
548 //
549 // Non Exhaustive reset:
550 // only reset private data structures.
551 //
552 if (!ExtendedVerification) {
553 //
554 // Clear the key buffer of this Usb keyboard
555 //
556 KbdReportStatusCode (
557 UsbKeyboardDevice->DevicePath,
558 EFI_PROGRESS_CODE,
559 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER)
560 );
561
562 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
563 UsbKeyboardDevice->CurKeyChar = 0;
564 return EFI_SUCCESS;
565 }
566
567 //
568 // Exhaustive reset
569 //
570 Status = InitUSBKeyboard (UsbKeyboardDevice);
571 UsbKeyboardDevice->CurKeyChar = 0;
572 if (EFI_ERROR (Status)) {
573 return EFI_DEVICE_ERROR;
574 }
575
576 return EFI_SUCCESS;
577 }
578
579 STATIC
580 EFI_STATUS
581 EFIAPI
582 USBKeyboardReadKeyStroke (
583 IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
584 OUT EFI_INPUT_KEY *Key
585 )
586 /*++
587
588 Routine Description:
589 Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.ReadKeyStroke() function.
590
591 Arguments:
592 This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance.
593 Key A pointer to a buffer that is filled in with the keystroke
594 information for the key that was pressed.
595
596 Returns:
597 EFI_SUCCESS - Success
598 --*/
599 {
600 USB_KB_DEV *UsbKeyboardDevice;
601 EFI_STATUS Status;
602 UINT8 KeyChar;
603
604 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
605
606 //
607 // if there is no saved ASCII byte, fetch it
608 // by calling USBKeyboardCheckForKey().
609 //
610 if (UsbKeyboardDevice->CurKeyChar == 0) {
611 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
612 if (EFI_ERROR (Status)) {
613 return Status;
614 }
615 }
616
617 Key->UnicodeChar = 0;
618 Key->ScanCode = SCAN_NULL;
619
620 KeyChar = UsbKeyboardDevice->CurKeyChar;
621
622 UsbKeyboardDevice->CurKeyChar = 0;
623
624 //
625 // Translate saved ASCII byte into EFI_INPUT_KEY
626 //
627 Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);
628
629 return Status;
630
631 }
632
633 STATIC
634 VOID
635 EFIAPI
636 USBKeyboardWaitForKey (
637 IN EFI_EVENT Event,
638 IN VOID *Context
639 )
640 /*++
641
642 Routine Description:
643 Handler function for WaitForKey event.
644
645 Arguments:
646 Event Event to be signaled when a key is pressed.
647 Context Points to USB_KB_DEV instance.
648
649 Returns:
650 VOID
651 --*/
652 {
653 USB_KB_DEV *UsbKeyboardDevice;
654
655 UsbKeyboardDevice = (USB_KB_DEV *) Context;
656
657 if (UsbKeyboardDevice->CurKeyChar == 0) {
658
659 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {
660 return ;
661 }
662 }
663 //
664 // If has key pending, signal the event.
665 //
666 gBS->SignalEvent (Event);
667 }
668
669
670 STATIC
671 EFI_STATUS
672 USBKeyboardCheckForKey (
673 IN USB_KB_DEV *UsbKeyboardDevice
674 )
675 /*++
676
677 Routine Description:
678 Check whether there is key pending.
679
680 Arguments:
681 UsbKeyboardDevice The USB_KB_DEV instance.
682
683 Returns:
684 EFI_SUCCESS - Success
685 --*/
686 {
687 EFI_STATUS Status;
688 UINT8 KeyChar;
689
690 //
691 // Fetch raw data from the USB keyboard input,
692 // and translate it into ASCII data.
693 //
694 Status = USBParseKey (UsbKeyboardDevice, &KeyChar);
695 if (EFI_ERROR (Status)) {
696 return Status;
697 }
698
699 UsbKeyboardDevice->CurKeyChar = KeyChar;
700 return EFI_SUCCESS;
701 }
702
703 VOID
704 KbdReportStatusCode (
705 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
706 IN EFI_STATUS_CODE_TYPE CodeType,
707 IN EFI_STATUS_CODE_VALUE Value
708 )
709 /*++
710
711 Routine Description:
712 Report Status Code in Usb Bot Driver
713
714 Arguments:
715 DevicePath - Use this to get Device Path
716 CodeType - Status Code Type
717 CodeValue - Status Code Value
718
719 Returns:
720 None
721
722 --*/
723 {
724
725 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
726 CodeType,
727 Value,
728 DevicePath
729 );
730 }