From 307a8d09db78b95c858c41bd5549c721da7eb1f8 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 17:18:01 -0400 Subject: feat(usb): Function to access latest USB status. * To be leveraged by upcoming power management work. --- app/src/usb_hid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/src') diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c index 530ffea..64addae 100644 --- a/app/src/usb_hid.c +++ b/app/src/usb_hid.c @@ -28,6 +28,8 @@ static const struct hid_ops ops = { .int_in_ready = in_ready_cb, }; +enum usb_dc_status_code zmk_usb_hid_get_status() { return usb_status; } + int zmk_usb_hid_send_report(const u8_t *report, size_t len) { switch (usb_status) { case USB_DC_SUSPEND: -- cgit v1.2.3 From fc5915b2001c80df5ab2db72b04d86a083e27556 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 4 Oct 2020 12:33:12 -0500 Subject: improvement(kscan): use ARRAY_SIZE macro --- app/src/kscan_composite.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'app/src') diff --git a/app/src/kscan_composite.c b/app/src/kscan_composite.c index 0249140..f8e8d60 100644 --- a/app/src/kscan_composite.c +++ b/app/src/kscan_composite.c @@ -38,8 +38,7 @@ struct kscan_composite_data { }; static int kscan_composite_enable_callback(struct device *dev) { - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_enable_callback(device_get_binding(cfg->label)); @@ -48,8 +47,7 @@ static int kscan_composite_enable_callback(struct device *dev) { } static int kscan_composite_disable_callback(struct device *dev) { - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_disable_callback(device_get_binding(cfg->label)); @@ -63,8 +61,7 @@ static void kscan_composite_child_callback(struct device *child_dev, u32_t row, struct device *dev = device_get_binding(DT_INST_LABEL(0)); struct kscan_composite_data *data = dev->driver_data; - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; if (device_get_binding(cfg->label) != child_dev) { @@ -82,8 +79,7 @@ static int kscan_composite_configure(struct device *dev, kscan_callback_t callba return -EINVAL; } - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback); -- cgit v1.2.3 From bbf5a5905a973d6d23457d2e7bf15bf6bac234c3 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Sun, 4 Oct 2020 18:18:44 -0400 Subject: refactor(usb): Report USB status w/o HID output. --- app/src/endpoints.c | 2 +- app/src/usb.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ app/src/usb_hid.c | 79 ------------------------------------------------ 3 files changed, 87 insertions(+), 80 deletions(-) create mode 100644 app/src/usb.c delete mode 100644 app/src/usb_hid.c (limited to 'app/src') diff --git a/app/src/endpoints.c b/app/src/endpoints.c index ae78587..79d294e 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/app/src/usb.c b/app/src/usb.c new file mode 100644 index 0000000..434b3d4 --- /dev/null +++ b/app/src/usb.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#include +#include +#include + +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; + +#ifdef CONFIG_ZMK_USB + +static struct device *hid_dev; + +static K_SEM_DEFINE(hid_sem, 1, 1); + +static void in_ready_cb(void) { k_sem_give(&hid_sem); } + +static const struct hid_ops ops = { + .int_in_ready = in_ready_cb, +}; + +int zmk_usb_hid_send_report(const u8_t *report, size_t len) { + switch (usb_status) { + case USB_DC_SUSPEND: + return usb_wakeup_request(); + case USB_DC_ERROR: + case USB_DC_RESET: + case USB_DC_DISCONNECTED: + case USB_DC_UNKNOWN: + return -ENODEV; + default: + k_sem_take(&hid_sem, K_MSEC(30)); + int err = hid_int_ep_write(hid_dev, report, len, NULL); + + if (err) { + k_sem_give(&hid_sem); + } + + return err; + } +} + +#endif /* CONFIG_ZMK_USB */ + +enum usb_dc_status_code zmk_usb_get_status() { return usb_status; } + +void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; }; + +static int zmk_usb_init(struct device *_arg) { + int usb_enable_ret; + +#ifdef CONFIG_ZMK_USB + hid_dev = device_get_binding("HID_0"); + if (hid_dev == NULL) { + LOG_ERR("Unable to locate HID device"); + return -EINVAL; + } + + usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops); + + usb_hid_init(hid_dev); + +#endif /* CONFIG_ZMK_USB */ + + usb_enable_ret = usb_enable(usb_status_cb); + + if (usb_enable_ret != 0) { + LOG_ERR("Unable to enable USB"); + return -EINVAL; + } + + return 0; +} + +SYS_INIT(zmk_usb_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c deleted file mode 100644 index 64addae..0000000 --- a/app/src/usb_hid.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2020 The ZMK Contributors - * - * SPDX-License-Identifier: MIT - */ - -#include -#include - -#include -#include -#include - -#include -#include - -LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); - -static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; - -static struct device *hid_dev; - -static K_SEM_DEFINE(hid_sem, 1, 1); - -static void in_ready_cb(void) { k_sem_give(&hid_sem); } - -static const struct hid_ops ops = { - .int_in_ready = in_ready_cb, -}; - -enum usb_dc_status_code zmk_usb_hid_get_status() { return usb_status; } - -int zmk_usb_hid_send_report(const u8_t *report, size_t len) { - switch (usb_status) { - case USB_DC_SUSPEND: - return usb_wakeup_request(); - case USB_DC_ERROR: - case USB_DC_RESET: - case USB_DC_DISCONNECTED: - case USB_DC_UNKNOWN: - return -ENODEV; - default: - k_sem_take(&hid_sem, K_MSEC(30)); - int err = hid_int_ep_write(hid_dev, report, len, NULL); - - if (err) { - k_sem_give(&hid_sem); - } - - return err; - } -} - -void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; }; - -static int zmk_usb_hid_init(struct device *_arg) { - int usb_enable_ret; - - hid_dev = device_get_binding("HID_0"); - if (hid_dev == NULL) { - LOG_ERR("Unable to locate HID device"); - return -EINVAL; - } - - usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops); - - usb_hid_init(hid_dev); - - usb_enable_ret = usb_enable(usb_hid_status_cb); - - if (usb_enable_ret != 0) { - LOG_ERR("Unable to enable USB"); - return -EINVAL; - } - - return 0; -} - -SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); -- cgit v1.2.3 From a7496ab06425cab7de5fc7164b4ce5a34dd7107b Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 2 Oct 2020 02:09:38 -0400 Subject: feat(power): Initial deep sleep work. * New ZMK_SLEEP Kconfig symbol to enable the functionality. * Switch to PORT events that allows wake from deep sleep. * Initial basic power management policy, with idle ms, and ignoring deep sleep if we detect a USB connection. --- app/src/power.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 app/src/power.c (limited to 'app/src') diff --git a/app/src/power.c b/app/src/power.c new file mode 100644 index 0000000..73b3f12 --- /dev/null +++ b/app/src/power.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include + +static u32_t power_last_uptime; + +#define MAX_IDLE_MS CONFIG_ZMK_IDLE_SLEEP_TIMEOUT + +bool is_usb_power_present() { +#ifdef CONFIG_USB + enum usb_dc_status_code usb_status = zmk_usb_get_status(); + switch (usb_status) { + case USB_DC_DISCONNECTED: + case USB_DC_UNKNOWN: + return false; + default: + return true; + } +#else + return false; +#endif /* CONFIG_USB */ +} + +enum power_states sys_pm_policy_next_state(s32_t ticks) { +#ifdef CONFIG_SYS_POWER_DEEP_SLEEP_STATES +#ifdef CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1 + s32_t current = k_uptime_get(); + if (power_last_uptime > 0 && !is_usb_power_present() && + current - power_last_uptime > MAX_IDLE_MS) { + return SYS_POWER_STATE_DEEP_SLEEP_1; + } +#endif /* CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1 */ +#endif /* CONFIG_SYS_POWER_DEEP_SLEEP_STATES */ + + return SYS_POWER_STATE_ACTIVE; +} + +int power_event_listener(const struct zmk_event_header *eh) { + power_last_uptime = k_uptime_get(); + + return 0; +} + +int power_init() { + power_last_uptime = k_uptime_get(); + + return 0; +} + +ZMK_LISTENER(power, power_event_listener); +ZMK_SUBSCRIPTION(power, position_state_changed); +ZMK_SUBSCRIPTION(power, sensor_event); + +SYS_INIT(power_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); \ No newline at end of file -- cgit v1.2.3 From 4d81b10ba7047a4dbd63cfe33ac879ecf437e108 Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Tue, 6 Oct 2020 15:52:21 +0800 Subject: Added driver to control the external power output This PR adds support to control the external power output from controllers like nice!nano, nRFMicro etc I have implemented based on my understanding of Pete suggestion on this feature. Testing done: Tested by enabling and disabling the ext_power from application and verified Verified the application does not crash with boards that does not have ext_power support Note: I did not test this in nice!nano since I don't have the boards. Will get help from others once the behavior PR is up Next Steps: Create a behavior PR to control enable/disable ext_power --- app/src/ext_power_generic.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ app/src/main.c | 9 +++++ 2 files changed, 100 insertions(+) create mode 100644 app/src/ext_power_generic.c (limited to 'app/src') diff --git a/app/src/ext_power_generic.c b/app/src/ext_power_generic.c new file mode 100644 index 0000000..4817030 --- /dev/null +++ b/app/src/ext_power_generic.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_ext_power_generic + +#include +#include +#include +#include + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +struct ext_power_generic_config { + const char *label; + const u8_t pin; + const u8_t flags; +}; + +struct ext_power_generic_data { + struct device *gpio; + bool status; +}; + +static int ext_power_generic_enable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 1)) { + LOG_WRN("Failed to set ext-power control pin"); + return -EIO; + } + data->status = true; + return 0; +} + +static int ext_power_generic_disable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 0)) { + LOG_WRN("Failed to clear ext-power control pin"); + return -EIO; + } + data->status = false; + return 0; +} + +static int ext_power_generic_get(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + return data->status; +} + +static int ext_power_generic_init(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + data->gpio = device_get_binding(config->label); + if (data->gpio == NULL) { + LOG_ERR("Failed to get ext-power control device"); + return -EINVAL; + } + + if (gpio_pin_configure(data->gpio, config->pin, config->flags | GPIO_OUTPUT)) { + LOG_ERR("Failed to configure ext-power control pin"); + return -EIO; + } + + return 0; +} + +static const struct ext_power_generic_config config = { + .label = DT_INST_GPIO_LABEL(0, control_gpios), + .pin = DT_INST_GPIO_PIN(0, control_gpios), + .flags = DT_INST_GPIO_FLAGS(0, control_gpios)}; + +static struct ext_power_generic_data data = {.status = false}; + +static const struct ext_power_api api = {.enable = ext_power_generic_enable, + .disable = ext_power_generic_disable, + .get = ext_power_generic_get}; + +DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config, + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &api); + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/main.c b/app/src/main.c index dca923e..0551356 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -15,16 +15,25 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID) void main(void) { + struct device *ext_power; LOG_INF("Welcome to ZMK!\n"); if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) { return; } + // Enable the external VCC output + ext_power = device_get_binding("EXT_POWER"); + if (ext_power != NULL) { + const struct ext_power_api *ext_power_api = ext_power->driver_api; + ext_power_api->enable(ext_power); + } + #ifdef CONFIG_ZMK_DISPLAY zmk_display_init(); -- cgit v1.2.3