mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 06:46:00 +00:00
efi_loader: implement key notify functions
Implement registering and unregistreing key notify functions in the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
4f17d8d391
commit
4fdcf06648
1 changed files with 98 additions and 3 deletions
|
@ -392,8 +392,23 @@ struct efi_simple_text_output_protocol efi_con_out = {
|
||||||
.mode = (void*)&efi_con_mode,
|
.mode = (void*)&efi_con_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct efi_cin_notify_function - registered console input notify function
|
||||||
|
*
|
||||||
|
* @link: link to list
|
||||||
|
* @data: key to notify
|
||||||
|
* @function: function to call
|
||||||
|
*/
|
||||||
|
struct efi_cin_notify_function {
|
||||||
|
struct list_head link;
|
||||||
|
struct efi_key_data key;
|
||||||
|
efi_status_t (EFIAPI *function)
|
||||||
|
(struct efi_key_data *key_data);
|
||||||
|
};
|
||||||
|
|
||||||
static bool key_available;
|
static bool key_available;
|
||||||
static struct efi_key_data next_key;
|
static struct efi_key_data next_key;
|
||||||
|
static LIST_HEAD(cin_notify_functions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set_shift_mask() - set shift mask
|
* set_shift_mask() - set shift mask
|
||||||
|
@ -597,6 +612,34 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key)
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_cin_notify() - notify registered functions
|
||||||
|
*/
|
||||||
|
static void efi_cin_notify(void)
|
||||||
|
{
|
||||||
|
struct efi_cin_notify_function *item;
|
||||||
|
|
||||||
|
list_for_each_entry(item, &cin_notify_functions, link) {
|
||||||
|
bool match = true;
|
||||||
|
|
||||||
|
/* We do not support toggle states */
|
||||||
|
if (item->key.key.unicode_char || item->key.key.scan_code) {
|
||||||
|
if (item->key.key.unicode_char !=
|
||||||
|
next_key.key.unicode_char ||
|
||||||
|
item->key.key.scan_code != next_key.key.scan_code)
|
||||||
|
match = false;
|
||||||
|
}
|
||||||
|
if (item->key.key_state.key_shift_state &&
|
||||||
|
item->key.key_state.key_shift_state !=
|
||||||
|
next_key.key_state.key_shift_state)
|
||||||
|
match = false;
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
/* We don't bother about the return code */
|
||||||
|
EFI_CALL(item->function(&next_key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_cin_check() - check if keyboard input is available
|
* efi_cin_check() - check if keyboard input is available
|
||||||
*/
|
*/
|
||||||
|
@ -614,7 +657,11 @@ static void efi_cin_check(void)
|
||||||
if (ret == EFI_SUCCESS) {
|
if (ret == EFI_SUCCESS) {
|
||||||
key_available = true;
|
key_available = true;
|
||||||
|
|
||||||
|
/* Notify registered functions */
|
||||||
|
efi_cin_notify();
|
||||||
|
|
||||||
/* Queue the wait for key event */
|
/* Queue the wait for key event */
|
||||||
|
if (key_available)
|
||||||
efi_signal_event(efi_con_in.wait_for_key, true);
|
efi_signal_event(efi_con_in.wait_for_key, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -757,9 +804,35 @@ static efi_status_t EFIAPI efi_cin_register_key_notify(
|
||||||
struct efi_key_data *key_data),
|
struct efi_key_data *key_data),
|
||||||
void **notify_handle)
|
void **notify_handle)
|
||||||
{
|
{
|
||||||
|
efi_status_t ret = EFI_SUCCESS;
|
||||||
|
struct efi_cin_notify_function *notify_function;
|
||||||
|
|
||||||
EFI_ENTRY("%p, %p, %p, %p",
|
EFI_ENTRY("%p, %p, %p, %p",
|
||||||
this, key_data, key_notify_function, notify_handle);
|
this, key_data, key_notify_function, notify_handle);
|
||||||
return EFI_EXIT(EFI_OUT_OF_RESOURCES);
|
|
||||||
|
/* Check parameters */
|
||||||
|
if (!this || !key_data || !key_notify_function || !notify_handle) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
|
||||||
|
key_data->key.unicode_char,
|
||||||
|
key_data->key.scan_code,
|
||||||
|
key_data->key_state.key_shift_state,
|
||||||
|
key_data->key_state.key_toggle_state);
|
||||||
|
|
||||||
|
notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
|
||||||
|
if (!notify_function) {
|
||||||
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
notify_function->key = *key_data;
|
||||||
|
notify_function->function = key_notify_function;
|
||||||
|
list_add_tail(¬ify_function->link, &cin_notify_functions);
|
||||||
|
*notify_handle = notify_function;
|
||||||
|
out:
|
||||||
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -779,8 +852,30 @@ static efi_status_t EFIAPI efi_cin_unregister_key_notify(
|
||||||
struct efi_simple_text_input_ex_protocol *this,
|
struct efi_simple_text_input_ex_protocol *this,
|
||||||
void *notification_handle)
|
void *notification_handle)
|
||||||
{
|
{
|
||||||
|
efi_status_t ret = EFI_INVALID_PARAMETER;
|
||||||
|
struct efi_cin_notify_function *item, *notify_function =
|
||||||
|
notification_handle;
|
||||||
|
|
||||||
EFI_ENTRY("%p, %p", this, notification_handle);
|
EFI_ENTRY("%p, %p", this, notification_handle);
|
||||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
|
||||||
|
/* Check parameters */
|
||||||
|
if (!this || !notification_handle)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
list_for_each_entry(item, &cin_notify_functions, link) {
|
||||||
|
if (item == notify_function) {
|
||||||
|
ret = EFI_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Remove the notify function */
|
||||||
|
list_del(¬ify_function->link);
|
||||||
|
free(notify_function);
|
||||||
|
out:
|
||||||
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue