diff --git a/.gitignore b/.gitignore index 53ca7f842..a3a120cba 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ target/*/tools/mkheader cscope.* ncscope.* +# clangd +.cache +compile_commands.json diff --git a/Documentation/dt-bindings.md b/Documentation/dt-bindings.md index 485248149..725cf8c78 100644 --- a/Documentation/dt-bindings.md +++ b/Documentation/dt-bindings.md @@ -151,6 +151,16 @@ them in the device node and lk2nd will use them instead of autodetecting. qcom,board-id = <0xCE08FF01 1>; ``` +### Single-key navigation + +On some devices, such as smartwatches, there is only one key available for +navigation. In this case `lk2nd,single-key-navigation` property can be +used to switch the navigation scheme to short/long press of a single key. + +``` + lk2nd,single-key-navigation; +``` + ## Additional drivers lk2nd provides a set of optional nodes, following a simple driver diff --git a/lk2nd/device/device.c b/lk2nd/device/device.c index ff819e47c..7c99c9d43 100644 --- a/lk2nd/device/device.c +++ b/lk2nd/device/device.c @@ -122,6 +122,10 @@ static void parse_dtb(const void *dtb) if (len < 0) dprintf(CRITICAL, "Failed to read 'lk2nd,dtb-files': %d\n", len); + val = fdt_getprop(dtb, node, "lk2nd,single-key-navigation", &len); + if (len >= 0) + lk2nd_dev.single_key = true; + dprintf(INFO, "Detected device: %s (compatible: %s)\n", lk2nd_dev.model, lk2nd_dev.compatible); diff --git a/lk2nd/device/device.h b/lk2nd/device/device.h index 951efb15d..11e7ca6f9 100644 --- a/lk2nd/device/device.h +++ b/lk2nd/device/device.h @@ -2,6 +2,8 @@ #ifndef LK2ND_DEVICE_DEVICE_H #define LK2ND_DEVICE_DEVICE_H +#include + struct lk2nd_panel { const char *name; const char *old_compatible; @@ -23,6 +25,7 @@ struct lk2nd_device { const char *battery; const char *const *dtbfiles; + bool single_key; struct lk2nd_panel panel; diff --git a/lk2nd/device/dts/msm8226/apq8026-asus-sparrow.dts b/lk2nd/device/dts/msm8226/apq8026-asus-sparrow.dts index a841b6730..e07107a5d 100644 --- a/lk2nd/device/dts/msm8226/apq8026-asus-sparrow.dts +++ b/lk2nd/device/dts/msm8226/apq8026-asus-sparrow.dts @@ -12,5 +12,6 @@ model = "ASUS ZenWatch 2"; compatible = "asus,sparrow"; + lk2nd,single-key-navigation; lk2nd,dtb-files = "apq8026-asus-sparrow"; }; diff --git a/lk2nd/device/dts/msm8226/apq8026-huawei-sturgeon.dts b/lk2nd/device/dts/msm8226/apq8026-huawei-sturgeon.dts index f60bb9a52..7c94ff11d 100644 --- a/lk2nd/device/dts/msm8226/apq8026-huawei-sturgeon.dts +++ b/lk2nd/device/dts/msm8226/apq8026-huawei-sturgeon.dts @@ -12,6 +12,7 @@ model = "Huawei Watch"; compatible = "huawei,sturgeon"; + lk2nd,single-key-navigation; lk2nd,dtb-files = "apq8026-huawei-sturgeon"; gpio-keys { diff --git a/lk2nd/device/dts/msm8226/apq8026-lg-lenok.dts b/lk2nd/device/dts/msm8226/apq8026-lg-lenok.dts index 5e92d9982..3d67468e7 100644 --- a/lk2nd/device/dts/msm8226/apq8026-lg-lenok.dts +++ b/lk2nd/device/dts/msm8226/apq8026-lg-lenok.dts @@ -15,6 +15,7 @@ model = "LG G Watch R"; compatible = "lg,lenok"; + lk2nd,single-key-navigation; lk2nd,dtb-files = "apq8026-lg-lenok"; }; diff --git a/lk2nd/device/menu/menu.c b/lk2nd/device/menu/menu.c index a4a2c5426..ce6e8c90e 100644 --- a/lk2nd/device/menu/menu.c +++ b/lk2nd/device/menu/menu.c @@ -85,16 +85,30 @@ static uint16_t lk2nd_boot_pressed_key(void) return 0; } +#define LONG_PRESS_DURATION 1000 + static uint16_t wait_key(void) { uint16_t keycode = 0; + int press_start = 0; + int press_duration; while (!(keycode = lk2nd_boot_pressed_key())) thread_sleep(1); - while (lk2nd_keys_pressed(keycode)) + press_start = current_time(); + + while (lk2nd_keys_pressed(keycode)) { thread_sleep(1); + press_duration = current_time() - press_start; + if (lk2nd_dev.single_key && press_duration > LONG_PRESS_DURATION) + return KEY_POWER; + } + + if (lk2nd_dev.single_key) + keycode = KEY_VOLUMEDOWN; + /* A small debounce delay */ thread_sleep(5); @@ -180,8 +194,13 @@ void display_fastboot_menu(void) y_menu = y; y += incr * (ARRAY_SIZE(menu_options) + 1); - fbcon_puts_ln(SILVER, y, incr, true, "Volume keys to navigate."); - fbcon_puts_ln(SILVER, y, incr, true, "Power key to select."); + if (lk2nd_dev.single_key) { + fbcon_puts_ln(SILVER, y, incr, true, "Short press to navigate."); + fbcon_puts_ln(SILVER, y, incr, true, "Long press to select."); + } else { + fbcon_puts_ln(SILVER, y, incr, true, "Volume keys to navigate."); + fbcon_puts_ln(SILVER, y, incr, true, "Power key to select."); + } /* * Draw the device-specific information at the bottom of the screen