[U-Boot] [PATCH v2 11/13] efi_loader: implement key notify functions
Heinrich Schuchardt
xypron.glpk at gmx.de
Mon Sep 10 19:49:35 UTC 2018
Implement registering and unregistreing key notify functions in the
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
v2
rebase patch
---
lib/efi_loader/efi_console.c | 101 +++++++++++++++++++++++++++++++++--
1 file changed, 98 insertions(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 9a2eea8345..aec20b94e1 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -392,8 +392,23 @@ struct efi_simple_text_output_protocol efi_con_out = {
.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 struct efi_key_data next_key;
+static LIST_HEAD(cin_notify_functions);
/**
* analyze_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
@@ -586,6 +601,34 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key)
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
*/
@@ -603,8 +646,12 @@ static void efi_cin_check(void)
if (ret == EFI_SUCCESS) {
key_available = true;
+ /* Notify registered functions */
+ efi_cin_notify();
+
/* Queue the wait for key event */
- efi_signal_event(efi_con_in.wait_for_key, true);
+ if (key_available)
+ efi_signal_event(efi_con_in.wait_for_key, true);
}
}
}
@@ -746,9 +793,35 @@ static efi_status_t EFIAPI efi_cin_register_key_notify(
struct efi_key_data *key_data),
void **notify_handle)
{
+ efi_status_t ret = EFI_SUCCESS;
+ struct efi_cin_notify_function *notify_function;
+
EFI_ENTRY("%p, %p, %p, %p",
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);
}
/**
@@ -768,8 +841,30 @@ static efi_status_t EFIAPI efi_cin_unregister_key_notify(
struct efi_simple_text_input_ex_protocol *this,
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);
- 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);
}
--
2.18.0
More information about the U-Boot
mailing list