-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: LED indicators #999
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (c) 2022 The ZMK Contributors | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <zmk/hid_indicators_types.h> | ||
#include <zmk/event_manager.h> | ||
|
||
struct zmk_hid_indicators_changed { | ||
zmk_hid_indicators indicators; | ||
}; | ||
|
||
ZMK_EVENT_DECLARE(zmk_hid_indicators_changed); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,15 @@ | |
|
||
#define COLLECTION_REPORT 0x03 | ||
|
||
#define HID_REPORT_ID_KEYBOARD 0x01 | ||
#define HID_REPORT_ID_LEDS 0x01 | ||
#define HID_REPORT_ID_CONSUMER 0x02 | ||
Comment on lines
+20
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed you had added these here. I had rolled a similar tweak into #1991 with different naming conventions. Let me pull that out into a small refactor PR (where it should be anyways, and we can then build on it for this and that PR as well. |
||
|
||
static const uint8_t zmk_hid_report_desc[] = { | ||
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), | ||
HID_USAGE(HID_USAGE_GD_KEYBOARD), | ||
HID_COLLECTION(HID_COLLECTION_APPLICATION), | ||
HID_REPORT_ID(0x01), | ||
HID_REPORT_ID(HID_REPORT_ID_KEYBOARD), | ||
HID_USAGE_PAGE(HID_USAGE_KEY), | ||
HID_USAGE_MIN8(HID_USAGE_KEY_KEYBOARD_LEFTCONTROL), | ||
HID_USAGE_MAX8(HID_USAGE_KEY_KEYBOARD_RIGHT_GUI), | ||
|
@@ -39,6 +43,20 @@ static const uint8_t zmk_hid_report_desc[] = { | |
/* INPUT (Cnst,Var,Abs) */ | ||
HID_INPUT(0x03), | ||
|
||
HID_USAGE_PAGE(HID_USAGE_LED), | ||
HID_USAGE_MIN8(HID_USAGE_LED_NUM_LOCK), | ||
HID_USAGE_MAX8(HID_USAGE_LED_KANA), | ||
HID_REPORT_SIZE(0x01), | ||
HID_REPORT_COUNT(0x05), | ||
/* OUTPUT (Data,Var,Abs) */ | ||
HID_OUTPUT(0x02), | ||
|
||
HID_USAGE_PAGE(HID_USAGE_LED), | ||
HID_REPORT_SIZE(0x03), | ||
HID_REPORT_COUNT(0x01), | ||
/* OUTPUT (Cnst,Var,Abs) */ | ||
HID_OUTPUT(0x03), | ||
|
||
HID_USAGE_PAGE(HID_USAGE_KEY), | ||
|
||
#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO) | ||
|
@@ -67,7 +85,7 @@ static const uint8_t zmk_hid_report_desc[] = { | |
HID_USAGE_PAGE(HID_USAGE_CONSUMER), | ||
HID_USAGE(HID_USAGE_CONSUMER_CONSUMER_CONTROL), | ||
HID_COLLECTION(HID_COLLECTION_APPLICATION), | ||
HID_REPORT_ID(0x02), | ||
HID_REPORT_ID(HID_REPORT_ID_CONSUMER), | ||
HID_USAGE_PAGE(HID_USAGE_CONSUMER), | ||
|
||
#if IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC) | ||
|
@@ -113,6 +131,15 @@ struct zmk_hid_keyboard_report { | |
struct zmk_hid_keyboard_report_body body; | ||
} __packed; | ||
|
||
struct zmk_hid_led_report_body { | ||
uint8_t leds; | ||
} __packed; | ||
|
||
struct zmk_hid_led_report { | ||
uint8_t report_id; | ||
struct zmk_hid_led_report_body body; | ||
} __packed; | ||
|
||
struct zmk_hid_consumer_report_body { | ||
#if IS_ENABLED(CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC) | ||
uint8_t keys[CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (c) 2022 The ZMK Contributors | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <zmk/endpoints_types.h> | ||
#include <zmk/hid.h> | ||
#include <zmk/hid_indicators_types.h> | ||
|
||
zmk_hid_indicators zmk_hid_indicators_get_current_profile(void); | ||
zmk_hid_indicators zmk_hid_indicators_get_profile(struct zmk_endpoint_instance endpoint); | ||
void zmk_hid_indicators_set_profile(zmk_hid_indicators indicators, | ||
struct zmk_endpoint_instance endpoint); | ||
|
||
void zmk_hid_indicators_process_report(struct zmk_hid_led_report_body *report, | ||
struct zmk_endpoint_instance endpoint); |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,9 @@ | ||||||
/* | ||||||
* Copyright (c) 2022 The ZMK Contributors | ||||||
* | ||||||
* SPDX-License-Identifier: MIT | ||||||
*/ | ||||||
|
||||||
#pragma once | ||||||
|
||||||
typedef uint8_t zmk_hid_indicators; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We usually follow the convention of using a
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (c) 2022 The ZMK Contributors | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#include <zephyr/kernel.h> | ||
#include <zmk/events/hid_indicators_changed.h> | ||
|
||
ZMK_EVENT_IMPL(zmk_hid_indicators_changed); |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,69 @@ | ||||||||||
/* | ||||||||||
* Copyright (c) 2022 The ZMK Contributors | ||||||||||
* | ||||||||||
* SPDX-License-Identifier: MIT | ||||||||||
*/ | ||||||||||
|
||||||||||
#include <zephyr/kernel.h> | ||||||||||
#include <zephyr/logging/log.h> | ||||||||||
|
||||||||||
#include <zmk/ble.h> | ||||||||||
#include <zmk/endpoints.h> | ||||||||||
#include <zmk/hid_indicators.h> | ||||||||||
#include <zmk/events/hid_indicators_changed.h> | ||||||||||
#include <zmk/events/endpoint_changed.h> | ||||||||||
#include <zmk/split/bluetooth/central.h> | ||||||||||
|
||||||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); | ||||||||||
|
||||||||||
static zmk_hid_indicators hid_indicators[ZMK_ENDPOINT_COUNT]; | ||||||||||
|
||||||||||
zmk_hid_indicators zmk_hid_indicators_get_current_profile(void) { | ||||||||||
return zmk_hid_indicators_get_profile(zmk_endpoints_selected()); | ||||||||||
} | ||||||||||
|
||||||||||
zmk_hid_indicators zmk_hid_indicators_get_profile(struct zmk_endpoint_instance endpoint) { | ||||||||||
int profile = zmk_endpoint_instance_to_index(endpoint); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
return hid_indicators[profile]; | ||||||||||
} | ||||||||||
|
||||||||||
static void raise_led_changed_event(struct k_work *_work) { | ||||||||||
zmk_hid_indicators indicators = zmk_hid_indicators_get_current_profile(); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
ZMK_EVENT_RAISE(new_zmk_hid_indicators_changed( | ||||||||||
(struct zmk_hid_indicators_changed){.indicators = indicators})); | ||||||||||
|
||||||||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT) && IS_ENABLED(CONFIG_ZMK_BLE) | ||||||||||
zmk_split_bt_update_hid_indicator(indicators); | ||||||||||
#endif | ||||||||||
} | ||||||||||
|
||||||||||
static K_WORK_DEFINE(led_changed_work, raise_led_changed_event); | ||||||||||
|
||||||||||
void zmk_hid_indicators_set_profile(zmk_hid_indicators indicators, | ||||||||||
struct zmk_endpoint_instance endpoint) { | ||||||||||
int profile = zmk_endpoint_instance_to_index(endpoint); | ||||||||||
|
||||||||||
// This write is not happening on the main thread. To prevent potential data races, every | ||||||||||
// operation involving hid_indicators must be atomic. Currently, each function either reads | ||||||||||
// or writes only one entry at a time, so it is safe to do these operations without a lock. | ||||||||||
hid_indicators[profile] = indicators; | ||||||||||
|
||||||||||
k_work_submit(&led_changed_work); | ||||||||||
} | ||||||||||
|
||||||||||
void zmk_hid_indicators_process_report(struct zmk_hid_led_report_body *report, | ||||||||||
struct zmk_endpoint_instance endpoint) { | ||||||||||
uint8_t indicators = report->leds; | ||||||||||
zmk_hid_indicators_set_profile(indicators, endpoint); | ||||||||||
Comment on lines
+57
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
LOG_DBG("Update HID indicators: endpoint=%d, indicators=%x", endpoint.transport, indicators); | ||||||||||
} | ||||||||||
|
||||||||||
static int profile_listener(const zmk_event_t *eh) { | ||||||||||
raise_led_changed_event(NULL); | ||||||||||
return 0; | ||||||||||
} | ||||||||||
|
||||||||||
static ZMK_LISTENER(profile_listener, profile_listener); | ||||||||||
static ZMK_SUBSCRIPTION(profile_listener, zmk_endpoint_changed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer needed after #2006 was merged since
CONFIG_ZMK_USB
now depends on theif
condition