aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfauxpark <fauxpark@gmail.com>2019-11-06 11:42:16 +1100
committerJoel Challis <git@zvecr.com>2019-11-06 00:42:16 +0000
commitdfb78d2a086daa2ceb3fd043afce03785abfa23a (patch)
tree7cd724b1cd12a65025bbc9d3cb32d7dd39cb9928
parented0575fc8aacdfdd83a31fc98df2b1cad2e977f4 (diff)
downloadqmk_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.md96
-rw-r--r--keyboards/maartenwut/wasdat/wasdat.c26
-rw-r--r--quantum/quantum.c21
-rw-r--r--quantum/quantum.h2
-rw-r--r--quantum/template/base/keyboard.c4
-rw-r--r--quantum/template/base/keymaps/default/keymap.c4
-rw-r--r--tmk_core/common/host.c6
-rw-r--r--tmk_core/common/host.h2
-rw-r--r--tmk_core/common/led.h13
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
93QMK provides methods to read the 5 LEDs defined as part of the HID spec: 93QMK 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
101These five constants correspond to the positional bits of the host LED state. 101There are two ways to get the lock LED state:
102There 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
109This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a parameter. 108Two more deprecated functions exist that provide the LED state as a `uint8_t`:
110Use 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
115This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
116
117You 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
124bool 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
117void led_set_user(uint8_t usb_led) { 159bool 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
153Call 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). 196Call 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).
154For 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
36void led_set_kb(uint8_t usb_led) { 36bool 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
290void led_set_user(uint8_t usb_led); 290void led_set_user(uint8_t usb_led);
291void led_set_kb(uint8_t usb_led); 291void led_set_kb(uint8_t usb_led);
292bool led_update_user(led_t led_state);
293bool led_update_kb(led_t led_state);
292 294
293void api_send_unicode(uint32_t unicode); 295void 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
45void led_set_kb(uint8_t usb_led) { 45bool 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
73void led_set_user(uint8_t usb_led) { 73bool 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
43led_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 */
43void host_keyboard_send(report_keyboard_t *report) { 49void 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 */
43uint8_t host_keyboard_leds(void); 44uint8_t host_keyboard_leds(void);
45led_t host_keyboard_led_state(void);
44void host_keyboard_send(report_keyboard_t *report); 46void host_keyboard_send(report_keyboard_t *report);
45void host_mouse_send(report_mouse_t *report); 47void host_mouse_send(report_mouse_t *report);
46void host_system_send(uint16_t data); 48void 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/>.
32extern "C" { 33extern "C" {
33#endif 34#endif
34 35
36typedef 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
35void led_set(uint8_t usb_led); 48void led_set(uint8_t usb_led);
36 49
37void led_init_ports(void); 50void led_init_ports(void);