diff options
author | fauxpark <fauxpark@gmail.com> | 2019-11-06 11:42:16 +1100 |
---|---|---|
committer | Joel Challis <git@zvecr.com> | 2019-11-06 00:42:16 +0000 |
commit | dfb78d2a086daa2ceb3fd043afce03785abfa23a (patch) | |
tree | 7cd724b1cd12a65025bbc9d3cb32d7dd39cb9928 | |
parent | ed0575fc8aacdfdd83a31fc98df2b1cad2e977f4 (diff) | |
download | qmk_firmware-dfb78d2a086daa2ceb3fd043afce03785abfa23a.tar.gz qmk_firmware-dfb78d2a086daa2ceb3fd043afce03785abfa23a.zip |
New and improved lock LED callbacks (#7215)
* New and improved lock LED callbacks
* Include stdbool
* Update documentation
* Use full function signatures and add keyboard-level example
-rw-r--r-- | docs/custom_quantum_functions.md | 96 | ||||
-rw-r--r-- | keyboards/maartenwut/wasdat/wasdat.c | 26 | ||||
-rw-r--r-- | quantum/quantum.c | 21 | ||||
-rw-r--r-- | quantum/quantum.h | 2 | ||||
-rw-r--r-- | quantum/template/base/keyboard.c | 4 | ||||
-rw-r--r-- | quantum/template/base/keymaps/default/keymap.c | 4 | ||||
-rw-r--r-- | tmk_core/common/host.c | 6 | ||||
-rw-r--r-- | tmk_core/common/host.h | 2 | ||||
-rw-r--r-- | tmk_core/common/led.h | 13 |
9 files changed, 123 insertions, 51 deletions
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index 839d49ca0..2d505b075 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md | |||
@@ -90,68 +90,110 @@ keyrecord_t record { | |||
90 | 90 | ||
91 | # LED Control | 91 | # LED Control |
92 | 92 | ||
93 | QMK provides methods to read the 5 LEDs defined as part of the HID spec: | 93 | QMK provides methods to read 5 of the LEDs defined in the HID spec: |
94 | 94 | ||
95 | * `USB_LED_NUM_LOCK` | 95 | * Num Lock |
96 | * `USB_LED_CAPS_LOCK` | 96 | * Caps Lock |
97 | * `USB_LED_SCROLL_LOCK` | 97 | * Scroll Lock |
98 | * `USB_LED_COMPOSE` | 98 | * Compose |
99 | * `USB_LED_KANA` | 99 | * Kana |
100 | 100 | ||
101 | These five constants correspond to the positional bits of the host LED state. | 101 | There are two ways to get the lock LED state: |
102 | There are two ways to get the host LED state: | ||
103 | 102 | ||
104 | * by implementing `led_set_user()` | 103 | * by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or |
105 | * by calling `host_keyboard_leds()` | 104 | * by calling `led_t host_keyboard_led_state()` |
106 | 105 | ||
107 | ## `led_set_user()` | 106 | !> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called. |
108 | 107 | ||
109 | This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a parameter. | 108 | Two more deprecated functions exist that provide the LED state as a `uint8_t`: |
110 | Use the `IS_LED_ON(usb_led, led_name)` and `IS_LED_OFF(usb_led, led_name)` macros to check the LED status. | ||
111 | 109 | ||
112 | !> `host_keyboard_leds()` may already reflect a new value before `led_set_user()` is called. | 110 | * `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)` |
111 | * `uint8_t host_keyboard_leds()` | ||
113 | 112 | ||
114 | ### Example `led_set_user()` Implementation | 113 | ## `led_update_user()` |
114 | |||
115 | This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter. | ||
116 | |||
117 | You must return either `true` or `false` from this function, depending on whether you want to override the keyboard-level implementation. | ||
118 | |||
119 | ?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead. | ||
120 | |||
121 | ### Example `led_update_kb()` Implementation | ||
122 | |||
123 | ```c | ||
124 | bool led_update_kb(led_t led_state) { | ||
125 | if(led_update_user(led_state)) { | ||
126 | if (led_state.num_lock) { | ||
127 | writePinLow(B0); | ||
128 | } else { | ||
129 | writePinHigh(B0); | ||
130 | } | ||
131 | if (led_state.caps_lock) { | ||
132 | writePinLow(B1); | ||
133 | } else { | ||
134 | writePinHigh(B1); | ||
135 | } | ||
136 | if (led_state.scroll_lock) { | ||
137 | writePinLow(B2); | ||
138 | } else { | ||
139 | writePinHigh(B2); | ||
140 | } | ||
141 | if (led_state.compose) { | ||
142 | writePinLow(B3); | ||
143 | } else { | ||
144 | writePinHigh(B3); | ||
145 | } | ||
146 | if (led_state.kana) { | ||
147 | writePinLow(B4); | ||
148 | } else { | ||
149 | writePinHigh(B4); | ||
150 | } | ||
151 | return true; | ||
152 | } | ||
153 | } | ||
154 | ``` | ||
155 | |||
156 | ### Example `led_update_user()` Implementation | ||
115 | 157 | ||
116 | ```c | 158 | ```c |
117 | void led_set_user(uint8_t usb_led) { | 159 | bool led_update_user(led_t led_state) { |
118 | if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) { | 160 | if (led_state.num_lock) { |
119 | writePinLow(B0); | 161 | writePinLow(B0); |
120 | } else { | 162 | } else { |
121 | writePinHigh(B0); | 163 | writePinHigh(B0); |
122 | } | 164 | } |
123 | if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) { | 165 | if (led_state.caps_lock) { |
124 | writePinLow(B1); | 166 | writePinLow(B1); |
125 | } else { | 167 | } else { |
126 | writePinHigh(B1); | 168 | writePinHigh(B1); |
127 | } | 169 | } |
128 | if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) { | 170 | if (led_state.scroll_lock) { |
129 | writePinLow(B2); | 171 | writePinLow(B2); |
130 | } else { | 172 | } else { |
131 | writePinHigh(B2); | 173 | writePinHigh(B2); |
132 | } | 174 | } |
133 | if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) { | 175 | if (led_state.compose) { |
134 | writePinLow(B3); | 176 | writePinLow(B3); |
135 | } else { | 177 | } else { |
136 | writePinHigh(B3); | 178 | writePinHigh(B3); |
137 | } | 179 | } |
138 | if (IS_LED_ON(usb_led, USB_LED_KANA)) { | 180 | if (led_state.kana) { |
139 | writePinLow(B4); | 181 | writePinLow(B4); |
140 | } else { | 182 | } else { |
141 | writePinHigh(B4); | 183 | writePinHigh(B4); |
142 | } | 184 | } |
185 | return true; | ||
143 | } | 186 | } |
144 | ``` | 187 | ``` |
145 | 188 | ||
146 | ### `led_set_*` Function Documentation | 189 | ### `led_update_*` Function Documentation |
147 | 190 | ||
148 | * Keyboard/Revision: `void led_set_kb(uint8_t usb_led)` | 191 | * Keyboard/Revision: `bool led_update_kb(led_t led_state)` |
149 | * Keymap: `void led_set_user(uint8_t usb_led)` | 192 | * Keymap: `bool led_update_user(led_t led_state)` |
150 | 193 | ||
151 | ## `host_keyboard_leds()` | 194 | ## `host_keyboard_led_state()` |
152 | 195 | ||
153 | Call this function to get the last received LED state. This is useful for reading the LED state outside `led_set_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code). | 196 | Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code). |
154 | For convenience, you can use the `IS_HOST_LED_ON(led_name)` and `IS_HOST_LED_OFF(led_name)` macros instead of calling and checking `host_keyboard_leds()` directly. | ||
155 | 197 | ||
156 | ## Setting Physical LED State | 198 | ## Setting Physical LED State |
157 | 199 | ||
diff --git a/keyboards/maartenwut/wasdat/wasdat.c b/keyboards/maartenwut/wasdat/wasdat.c index 11338634d..99dd97dcf 100644 --- a/keyboards/maartenwut/wasdat/wasdat.c +++ b/keyboards/maartenwut/wasdat/wasdat.c | |||
@@ -33,26 +33,12 @@ void led_init_ports(void) { | |||
33 | setPinOutput(B2); | 33 | setPinOutput(B2); |
34 | } | 34 | } |
35 | 35 | ||
36 | void led_set_kb(uint8_t usb_led) { | 36 | bool led_update_kb(led_t led_state) { |
37 | // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here | 37 | if(led_update_user(led_state)) { |
38 | 38 | writePin(B0, !led_state.caps_lock); | |
39 | if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) { | 39 | writePin(B1, !led_state.scroll_lock); |
40 | writePinLow(B0); | 40 | writePin(B2, !led_state.num_lock); |
41 | } else { | ||
42 | writePinHigh(B0); | ||
43 | } | ||
44 | |||
45 | if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) { | ||
46 | writePinLow(B1); | ||
47 | } else { | ||
48 | writePinHigh(B1); | ||
49 | } | ||
50 | |||
51 | if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) { | ||
52 | writePinLow(B2); | ||
53 | } else { | ||
54 | writePinHigh(B2); | ||
55 | } | 41 | } |
56 | 42 | ||
57 | led_set_user(usb_led); | 43 | return true; |
58 | } | 44 | } |
diff --git a/quantum/quantum.c b/quantum/quantum.c index 1f17c6ff7..c27c3aba6 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c | |||
@@ -1070,10 +1070,30 @@ void api_send_unicode(uint32_t unicode) { | |||
1070 | #endif | 1070 | #endif |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | /** \brief Lock LED set callback - keymap/user level | ||
1074 | * | ||
1075 | * \deprecated Use led_update_user() instead. | ||
1076 | */ | ||
1073 | __attribute__((weak)) void led_set_user(uint8_t usb_led) {} | 1077 | __attribute__((weak)) void led_set_user(uint8_t usb_led) {} |
1074 | 1078 | ||
1079 | /** \brief Lock LED set callback - keyboard level | ||
1080 | * | ||
1081 | * \deprecated Use led_update_kb() instead. | ||
1082 | */ | ||
1075 | __attribute__((weak)) void led_set_kb(uint8_t usb_led) { led_set_user(usb_led); } | 1083 | __attribute__((weak)) void led_set_kb(uint8_t usb_led) { led_set_user(usb_led); } |
1076 | 1084 | ||
1085 | /** \brief Lock LED update callback - keymap/user level | ||
1086 | * | ||
1087 | * \return True if led_update_kb() should run its own code, false otherwise. | ||
1088 | */ | ||
1089 | __attribute__((weak)) bool led_update_user(led_t led_state) { return true; } | ||
1090 | |||
1091 | /** \brief Lock LED update callback - keyboard level | ||
1092 | * | ||
1093 | * \return Ignored for now. | ||
1094 | */ | ||
1095 | __attribute__((weak)) bool led_update_kb(led_t led_state) { return led_update_user(led_state); } | ||
1096 | |||
1077 | __attribute__((weak)) void led_init_ports(void) {} | 1097 | __attribute__((weak)) void led_init_ports(void) {} |
1078 | 1098 | ||
1079 | __attribute__((weak)) void led_set(uint8_t usb_led) { | 1099 | __attribute__((weak)) void led_set(uint8_t usb_led) { |
@@ -1096,6 +1116,7 @@ __attribute__((weak)) void led_set(uint8_t usb_led) { | |||
1096 | #endif | 1116 | #endif |
1097 | 1117 | ||
1098 | led_set_kb(usb_led); | 1118 | led_set_kb(usb_led); |
1119 | led_update_kb((led_t) usb_led); | ||
1099 | } | 1120 | } |
1100 | 1121 | ||
1101 | //------------------------------------------------------------------------------ | 1122 | //------------------------------------------------------------------------------ |
diff --git a/quantum/quantum.h b/quantum/quantum.h index 87343a15d..7988c5878 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h | |||
@@ -289,5 +289,7 @@ uint16_t hex_to_keycode(uint8_t hex); | |||
289 | 289 | ||
290 | void led_set_user(uint8_t usb_led); | 290 | void led_set_user(uint8_t usb_led); |
291 | void led_set_kb(uint8_t usb_led); | 291 | void led_set_kb(uint8_t usb_led); |
292 | bool led_update_user(led_t led_state); | ||
293 | bool led_update_kb(led_t led_state); | ||
292 | 294 | ||
293 | void api_send_unicode(uint32_t unicode); | 295 | void api_send_unicode(uint32_t unicode); |
diff --git a/quantum/template/base/keyboard.c b/quantum/template/base/keyboard.c index 55e4fffd3..fc31c294a 100644 --- a/quantum/template/base/keyboard.c +++ b/quantum/template/base/keyboard.c | |||
@@ -42,9 +42,9 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { | |||
42 | return process_record_user(keycode, record); | 42 | return process_record_user(keycode, record); |
43 | } | 43 | } |
44 | 44 | ||
45 | void led_set_kb(uint8_t usb_led) { | 45 | bool led_update_kb(led_t led_state) { |
46 | // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here | 46 | // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here |
47 | 47 | ||
48 | led_set_user(usb_led); | 48 | return led_update_user(led_state); |
49 | } | 49 | } |
50 | */ | 50 | */ |
diff --git a/quantum/template/base/keymaps/default/keymap.c b/quantum/template/base/keymaps/default/keymap.c index 4d5bac7b2..3a68f5487 100644 --- a/quantum/template/base/keymaps/default/keymap.c +++ b/quantum/template/base/keymaps/default/keymap.c | |||
@@ -70,7 +70,7 @@ void matrix_scan_user(void) { | |||
70 | 70 | ||
71 | } | 71 | } |
72 | 72 | ||
73 | void led_set_user(uint8_t usb_led) { | 73 | bool led_update_user(led_t led_state) { |
74 | 74 | return true; | |
75 | } | 75 | } |
76 | */ | 76 | */ |
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index ce39760a5..713b0d945 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c | |||
@@ -39,6 +39,12 @@ uint8_t host_keyboard_leds(void) { | |||
39 | if (!driver) return 0; | 39 | if (!driver) return 0; |
40 | return (*driver->keyboard_leds)(); | 40 | return (*driver->keyboard_leds)(); |
41 | } | 41 | } |
42 | |||
43 | led_t host_keyboard_led_state(void) { | ||
44 | if (!driver) return (led_t) {0}; | ||
45 | return (led_t)((*driver->keyboard_leds)()); | ||
46 | } | ||
47 | |||
42 | /* send report */ | 48 | /* send report */ |
43 | void host_keyboard_send(report_keyboard_t *report) { | 49 | void host_keyboard_send(report_keyboard_t *report) { |
44 | if (!driver) return; | 50 | if (!driver) return; |
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h index b2a7f9842..2cffef6e1 100644 --- a/tmk_core/common/host.h +++ b/tmk_core/common/host.h | |||
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
21 | #include <stdbool.h> | 21 | #include <stdbool.h> |
22 | #include "report.h" | 22 | #include "report.h" |
23 | #include "host_driver.h" | 23 | #include "host_driver.h" |
24 | #include "led.h" | ||
24 | 25 | ||
25 | #define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) | 26 | #define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) |
26 | #define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) | 27 | #define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) |
@@ -41,6 +42,7 @@ host_driver_t *host_get_driver(void); | |||
41 | 42 | ||
42 | /* host driver interface */ | 43 | /* host driver interface */ |
43 | uint8_t host_keyboard_leds(void); | 44 | uint8_t host_keyboard_leds(void); |
45 | led_t host_keyboard_led_state(void); | ||
44 | void host_keyboard_send(report_keyboard_t *report); | 46 | void host_keyboard_send(report_keyboard_t *report); |
45 | void host_mouse_send(report_mouse_t *report); | 47 | void host_mouse_send(report_mouse_t *report); |
46 | void host_system_send(uint16_t data); | 48 | void host_system_send(uint16_t data); |
diff --git a/tmk_core/common/led.h b/tmk_core/common/led.h index 2c28fe540..daf974bed 100644 --- a/tmk_core/common/led.h +++ b/tmk_core/common/led.h | |||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
18 | #ifndef LED_H | 18 | #ifndef LED_H |
19 | #define LED_H | 19 | #define LED_H |
20 | #include "stdint.h" | 20 | #include "stdint.h" |
21 | #include "stdbool.h" | ||
21 | 22 | ||
22 | /* FIXME: Add doxygen comments here. */ | 23 | /* FIXME: Add doxygen comments here. */ |
23 | 24 | ||
@@ -32,6 +33,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
32 | extern "C" { | 33 | extern "C" { |
33 | #endif | 34 | #endif |
34 | 35 | ||
36 | typedef union { | ||
37 | uint8_t raw; | ||
38 | struct { | ||
39 | bool num_lock : 1; | ||
40 | bool caps_lock : 1; | ||
41 | bool scroll_lock : 1; | ||
42 | bool compose : 1; | ||
43 | bool kana : 1; | ||
44 | uint8_t reserved : 3; | ||
45 | }; | ||
46 | } led_t; | ||
47 | |||
35 | void led_set(uint8_t usb_led); | 48 | void led_set(uint8_t usb_led); |
36 | 49 | ||
37 | void led_init_ports(void); | 50 | void led_init_ports(void); |