Skip to content
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

feat(behavior) Add &sleep behavior #649

Closed
wants to merge 3 commits into from

Conversation

mcrosson
Copy link
Contributor

Add a new behavior that'll allow users to put their keyboard to sleep ahead of timeouts. This is meant to be used as a binding on a keymap.

@Nicell Nicell added behaviors enhancement New feature or request labels Feb 1, 2021
enum zmk_activity_state zmk_activity_get_state();
int activity_set_state(enum zmk_activity_state state);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int activity_set_state(enum zmk_activity_state state);
int zmk_activity_set_state(enum zmk_activity_state state);

To keep in line with the rest of our shared functions, I'm thinking this should be prefixed with zmk_.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

Comment on lines +58 to +60
// Second half of || statement is to ensure a user using &sleep doesn't lose sleep state when
// the idle or sleep timers expire
if (inactive_time > MAX_SLEEP_MS || activity_state == ZMK_ACTIVITY_SLEEP) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this handler is even called when ZMK is in deep sleep. I'd imagine it shouldn't, but if it does, why don't we just clear the timer? Seems unnecessary to run this while we're in sleep.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see a great spot to reset the timer and if the timer code does run at all in sleep mode... we're still going to need the 2nd half of the condition to ensure it's never going to wake up when asleep.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm thinking is this handler shouldn't even be called once you're in deep sleep. Have you tested it without this additional conditional? From my understanding when we go into deep sleep, timer-based handlers are no longer run since we don't set up any timer wakeups and therefore don't have any timers running.

Comment on lines 25 to 38
static const struct behavior_driver_api behavior_sleep_driver_api = {
.binding_released = on_keymap_binding_released,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.binding_pressed should be defined so you don't get an error in logs when pressing this key. You can have a function that just returns an opaque response like this: https://github.com/zmkfirmware/zmk/blob/main/app/src/behaviors/behavior_rgb_underglow.c#L54

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added


static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
return activity_set_state(ZMK_ACTIVITY_SLEEP);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return activity_set_state(ZMK_ACTIVITY_SLEEP);
#if IS_ENABLED(CONFIG_ZMK_SLEEP)
return activity_set_state(ZMK_ACTIVITY_SLEEP);
#endif
return ZMK_BEHAVIOR_OPAQUE;

This is so we don't sleep when sleep isn't turned on and we press this key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Copy link
Contributor

@petejohanson petejohanson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few additional tweaks needed.


/ {
behaviors {
sleep: behavior_sleep {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the /omit-if-no-ref/ here like other behaviors were updated to include.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added


LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

static int behavior_sleep_init(const struct device *dev) { return 0; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a wrapper #if HAS_DEVICE_STATUS_OKAY(DT_DRV_COMPAT) like other drivers do now, so this doesn't compile if the DT is omitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@petejohanson
Copy link
Contributor

@mcrosson did you see the review items on this?

@mcrosson
Copy link
Contributor Author

@mcrosson did you see the review items on this?

Yes, I thought it was agreed this was 'on hold' until after locality landed? I was planning on working on any necessary changes once locality landed.

@mcrosson mcrosson force-pushed the feat-behavior-sleep branch from 0550b30 to f9699eb Compare March 13, 2021 19:24
@mcrosson
Copy link
Contributor Author

Had some spare brain cycles and time ; updated according to the above feedback

@@ -34,7 +34,8 @@ int raise_event() {
(struct zmk_activity_state_changed){.state = activity_state}));
}

int set_state(enum zmk_activity_state state) {
int activity_set_state(enum zmk_activity_state state) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have to rename all of these activity_set_states to zmk_activity_set_state.

Comment on lines +58 to +60
// Second half of || statement is to ensure a user using &sleep doesn't lose sleep state when
// the idle or sleep timers expire
if (inactive_time > MAX_SLEEP_MS || activity_state == ZMK_ACTIVITY_SLEEP) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm thinking is this handler shouldn't even be called once you're in deep sleep. Have you tested it without this additional conditional? From my understanding when we go into deep sleep, timer-based handlers are no longer run since we don't set up any timer wakeups and therefore don't have any timers running.

Copy link
Contributor

@petejohanson petejohanson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few follow ups.


static const struct behavior_driver_api behavior_sleep_driver_api = {
.binding_released = on_keymap_binding_released,
.binding_pressed = on_keymap_binding_pressed,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a .locality set:

Suggested change
.binding_pressed = on_keymap_binding_pressed,
.binding_pressed = on_keymap_binding_pressed,
.locality = BEHAVIOR_LOCALITY_GLOBAL,


```
&sleep
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document this as being a global behavior, that will affect all components of a split. See other global behaviors, e.g. RGB, for an example docs.

@petejohanson
Copy link
Contributor

@mcrosson Any plans to wrap this up, fix current conflicts, etc?

@hyx0329
Copy link
Contributor

hyx0329 commented May 9, 2023

I was trying to implement soft power off/lockout in the application code, happened to almost reimplement this.

However, regardless of whether I called set_state, I can not wake up my keyboard through typing. This works great for my "power off" purpose, but not for the "sleep" here. When the keyboard is put to sleep by activity_work_handler in activity.c, I can wake the keyboard up by typing. So I wonder which part of code make it possible to wake up the keyboard by typing.

Edit: Oh I think I just found it, first introduced by pr 211 at app/drivers/kscan/kscan_gpio_matrix.c, documented. I think I have the idea to implement both.

In my code, the behavior is triggered upon pressing the key. My code is based on current latest main branch (94789a0).

@lesshonor
Copy link
Contributor

lesshonor commented Jul 7, 2024

Arguably obsoleted by #2085 and related PRs.

@Nick-Munnich
Copy link
Contributor

I recall someone requesting a &sleep behaviour in addition to &soft_off, to use &sleep for power conserving and &soft_off for transportation. For that reason I would say that it's not obsolete yet.

@mcrosson mcrosson closed this by deleting the head repository Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
behaviors enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants