From 17152f50886810b775a1da5394c96ee4c110a91e Mon Sep 17 00:00:00 2001 From: valeros Date: Tue, 13 Aug 2024 15:03:47 +0300 Subject: [PATCH 1/2] Update Zephyr package to v3.7.0 Update Zephyr examples Resolves #792 --- examples/zephyr-drivers-can/src/main.c | 342 +++++------------- examples/zephyr-drivers-can/zephyr/Kconfig | 42 ++- examples/zephyr-drivers-can/zephyr/prj.conf | 12 - .../zephyr-subsys-usb-hid-mouse/src/main.c | 316 +++++----------- .../src/sample_usbd_init.c | 181 +++++++++ .../zephyr/CMakeLists.txt | 7 +- .../zephyr/Kconfig | 9 + .../zephyr/app.overlay | 15 + .../zephyr/prj.conf | 15 +- platform.json | 2 +- 10 files changed, 433 insertions(+), 508 deletions(-) create mode 100644 examples/zephyr-subsys-usb-hid-mouse/src/sample_usbd_init.c create mode 100644 examples/zephyr-subsys-usb-hid-mouse/zephyr/Kconfig create mode 100644 examples/zephyr-subsys-usb-hid-mouse/zephyr/app.overlay diff --git a/examples/zephyr-drivers-can/src/main.c b/examples/zephyr-drivers-can/src/main.c index 2119069e..ada6852a 100644 --- a/examples/zephyr-drivers-can/src/main.c +++ b/examples/zephyr-drivers-can/src/main.c @@ -1,309 +1,139 @@ /* - * Copyright (c) 2018 Alexander Wachter + * Copyright (c) 2021-2022 Henrik Brix Andersen * * SPDX-License-Identifier: Apache-2.0 */ -#include - -#include -#include #include +#include #include #include -#include - -#define RX_THREAD_STACK_SIZE 512 -#define RX_THREAD_PRIORITY 2 -#define STATE_POLL_THREAD_STACK_SIZE 512 -#define STATE_POLL_THREAD_PRIORITY 2 -#define LED_MSG_ID 0x10 -#define COUNTER_MSG_ID 0x12345 -#define SET_LED 1 -#define RESET_LED 0 -#define SLEEP_TIME K_MSEC(250) - -K_THREAD_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE); -K_THREAD_STACK_DEFINE(poll_state_stack, STATE_POLL_THREAD_STACK_SIZE); - -const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); -struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0}); - -struct k_thread rx_thread_data; -struct k_thread poll_state_thread_data; -struct k_work_poll change_led_work; -struct k_work state_change_work; -enum can_state current_state; -struct can_bus_err_cnt current_err_cnt; +#include -CAN_MSGQ_DEFINE(change_led_msgq, 2); -CAN_MSGQ_DEFINE(counter_msgq, 2); +/* Devicetree */ +#define CANBUS_NODE DT_CHOSEN(zephyr_canbus) +#define BUTTON_NODE DT_ALIAS(sw0) +#define BUTTON_NAME DT_PROP_OR(BUTTON_NODE, label, "sw0") -static struct k_poll_event change_led_events[1] = { - K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE, - K_POLL_MODE_NOTIFY_ONLY, - &change_led_msgq, 0) +#if DT_NODE_EXISTS(BUTTON_NODE) +struct button_callback_context { + struct gpio_callback callback; + struct k_sem sem; }; -void tx_irq_callback(const struct device *dev, int error, void *arg) +static void button_callback(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) { - char *sender = (char *)arg; - - ARG_UNUSED(dev); + struct button_callback_context *ctx = + CONTAINER_OF(cb, struct button_callback_context, callback); - if (error != 0) { - printf("Callback! error-code: %d\nSender: %s\n", - error, sender); - } + k_sem_give(&ctx->sem); } +#endif /* DT_NODE_EXISTS(BUTTON_NODE) */ -void rx_thread(void *arg1, void *arg2, void *arg3) +static void can_tx_callback(const struct device *dev, int error, void *user_data) { - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - const struct can_filter filter = { - .flags = CAN_FILTER_IDE, - .id = COUNTER_MSG_ID, - .mask = CAN_EXT_ID_MASK - }; - struct can_frame frame; - int filter_id; - - filter_id = can_add_rx_filter_msgq(can_dev, &counter_msgq, &filter); - printf("Counter filter id: %d\n", filter_id); - - while (1) { - k_msgq_get(&counter_msgq, &frame, K_FOREVER); - - if (IS_ENABLED(CONFIG_CAN_ACCEPT_RTR) && (frame.flags & CAN_FRAME_RTR) != 0U) { - continue; - } - - if (frame.dlc != 2U) { - printf("Wrong data length: %u\n", frame.dlc); - continue; - } + struct k_sem *tx_queue_sem = user_data; - printf("Counter received: %u\n", - sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&frame.data))); - } + k_sem_give(tx_queue_sem); } -void change_led_work_handler(struct k_work *work) +int main(void) { - struct can_frame frame; - int ret; - - while (k_msgq_get(&change_led_msgq, &frame, K_NO_WAIT) == 0) { - if (IS_ENABLED(CONFIG_CAN_ACCEPT_RTR) && (frame.flags & CAN_FRAME_RTR) != 0U) { - continue; - } +#if DT_NODE_EXISTS(BUTTON_NODE) + const struct gpio_dt_spec btn = GPIO_DT_SPEC_GET(BUTTON_NODE, gpios); + struct button_callback_context btn_cb_ctx; +#endif /* DT_NODE_EXISTS(BUTTON_NODE) */ + const struct device *dev = DEVICE_DT_GET(CANBUS_NODE); + struct k_sem tx_queue_sem; + struct can_frame frame = {0}; + int err; - if (led.port == NULL) { - printf("LED %s\n", frame.data[0] == SET_LED ? "ON" : "OFF"); - } else { - gpio_pin_set(led.port, led.pin, frame.data[0] == SET_LED ? 1 : 0); - } - } + k_sem_init(&tx_queue_sem, CONFIG_SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE, + CONFIG_SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE); - ret = k_work_poll_submit(&change_led_work, change_led_events, - ARRAY_SIZE(change_led_events), K_FOREVER); - if (ret != 0) { - printf("Failed to resubmit msgq polling: %d", ret); - } -} - -char *state_to_str(enum can_state state) -{ - switch (state) { - case CAN_STATE_ERROR_ACTIVE: - return "error-active"; - case CAN_STATE_ERROR_WARNING: - return "error-warning"; - case CAN_STATE_ERROR_PASSIVE: - return "error-passive"; - case CAN_STATE_BUS_OFF: - return "bus-off"; - case CAN_STATE_STOPPED: - return "stopped"; - default: - return "unknown"; + if (!device_is_ready(dev)) { + printk("CAN device not ready"); + return 0; } -} - -void poll_state_thread(void *unused1, void *unused2, void *unused3) -{ - struct can_bus_err_cnt err_cnt = {0, 0}; - struct can_bus_err_cnt err_cnt_prev = {0, 0}; - enum can_state state_prev = CAN_STATE_ERROR_ACTIVE; - enum can_state state; - int err; - while (1) { - err = can_get_state(can_dev, &state, &err_cnt); + if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_FD_MODE)) { + err = can_set_mode(dev, CAN_MODE_FD); if (err != 0) { - printf("Failed to get CAN controller state: %d", err); - k_sleep(K_MSEC(100)); - continue; - } - - if (err_cnt.tx_err_cnt != err_cnt_prev.tx_err_cnt || - err_cnt.rx_err_cnt != err_cnt_prev.rx_err_cnt || - state_prev != state) { - - err_cnt_prev.tx_err_cnt = err_cnt.tx_err_cnt; - err_cnt_prev.rx_err_cnt = err_cnt.rx_err_cnt; - state_prev = state; - printf("state: %s\n" - "rx error count: %d\n" - "tx error count: %d\n", - state_to_str(state), - err_cnt.rx_err_cnt, err_cnt.tx_err_cnt); - } else { - k_sleep(K_MSEC(100)); + printk("Error setting CAN FD mode (err %d)", err); + return 0; } } -} - -void state_change_work_handler(struct k_work *work) -{ - printf("State Change ISR\nstate: %s\n" - "rx error count: %d\n" - "tx error count: %d\n", - state_to_str(current_state), - current_err_cnt.rx_err_cnt, current_err_cnt.tx_err_cnt); - -#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY - if (current_state == CAN_STATE_BUS_OFF) { - printf("Recover from bus-off\n"); - if (can_recover(can_dev, K_MSEC(100)) != 0) { - printf("Recovery timed out\n"); - } + err = can_start(dev); + if (err != 0) { + printk("Error starting CAN controller (err %d)", err); + return 0; } -#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ -} - -void state_change_callback(const struct device *dev, enum can_state state, - struct can_bus_err_cnt err_cnt, void *user_data) -{ - struct k_work *work = (struct k_work *)user_data; - - ARG_UNUSED(dev); - current_state = state; - current_err_cnt = err_cnt; - k_work_submit(work); -} +#if DT_NODE_EXISTS(BUTTON_NODE) + k_sem_init(&btn_cb_ctx.sem, 0, 1); -int main(void) -{ - const struct can_filter change_led_filter = { - .flags = 0U, - .id = LED_MSG_ID, - .mask = CAN_STD_ID_MASK - }; - struct can_frame change_led_frame = { - .flags = 0, - .id = LED_MSG_ID, - .dlc = 1 - }; - struct can_frame counter_frame = { - .flags = CAN_FRAME_IDE, - .id = COUNTER_MSG_ID, - .dlc = 2 - }; - uint8_t toggle = 1; - uint16_t counter = 0; - k_tid_t rx_tid, get_state_tid; - int ret; - - if (!device_is_ready(can_dev)) { - printf("CAN: Device %s not ready.\n", can_dev->name); + if (!gpio_is_ready_dt(&btn)) { + printk("button device not ready\n"); return 0; } -#ifdef CONFIG_LOOPBACK_MODE - ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK); - if (ret != 0) { - printf("Error setting CAN mode [%d]", ret); - return 0; - } -#endif - ret = can_start(can_dev); - if (ret != 0) { - printf("Error starting CAN controller [%d]", ret); + err = gpio_pin_configure_dt(&btn, GPIO_INPUT); + if (err != 0) { + printk("failed to configure button GPIO (err %d)\n", err); return 0; } - if (led.port != NULL) { - if (!gpio_is_ready_dt(&led)) { - printf("LED: Device %s not ready.\n", - led.port->name); - return 0; - } - ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_HIGH); - if (ret < 0) { - printf("Error setting LED pin to output mode [%d]", - ret); - led.port = NULL; - } - } - - k_work_init(&state_change_work, state_change_work_handler); - k_work_poll_init(&change_led_work, change_led_work_handler); - - ret = can_add_rx_filter_msgq(can_dev, &change_led_msgq, &change_led_filter); - if (ret == -ENOSPC) { - printf("Error, no filter available!\n"); + err = gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_TO_ACTIVE); + if (err != 0) { + printk("failed to configure button interrupt (err %d)\n", err); return 0; } - printf("Change LED filter ID: %d\n", ret); + gpio_init_callback(&btn_cb_ctx.callback, button_callback, BIT(btn.pin)); + gpio_add_callback(btn.port, &btn_cb_ctx.callback); +#endif /* DT_NODE_EXISTS(BUTTON_NODE) */ - ret = k_work_poll_submit(&change_led_work, change_led_events, - ARRAY_SIZE(change_led_events), K_FOREVER); - if (ret != 0) { - printf("Failed to submit msgq polling: %d", ret); - return 0; + if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_EXT_ID)) { + frame.flags |= CAN_FRAME_IDE; } - rx_tid = k_thread_create(&rx_thread_data, rx_thread_stack, - K_THREAD_STACK_SIZEOF(rx_thread_stack), - rx_thread, NULL, NULL, NULL, - RX_THREAD_PRIORITY, 0, K_NO_WAIT); - if (!rx_tid) { - printf("ERROR spawning rx thread\n"); + if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_RTR)) { + frame.flags |= CAN_FRAME_RTR; } - get_state_tid = k_thread_create(&poll_state_thread_data, - poll_state_stack, - K_THREAD_STACK_SIZEOF(poll_state_stack), - poll_state_thread, NULL, NULL, NULL, - STATE_POLL_THREAD_PRIORITY, 0, - K_NO_WAIT); - if (!get_state_tid) { - printf("ERROR spawning poll_state_thread\n"); + if (IS_ENABLED(CONFIG_SAMPLE_CAN_BABBLING_FD_MODE)) { + frame.flags |= CAN_FRAME_FDF; } - can_set_state_change_callback(can_dev, state_change_callback, &state_change_work); + frame.id = CONFIG_SAMPLE_CAN_BABBLING_CAN_ID; - printf("Finished init.\n"); + printk("babbling on %s with %s (%d-bit) CAN ID 0x%0*x, RTR %d, CAN FD %d\n", + dev->name, + (frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard", + (frame.flags & CAN_FRAME_IDE) != 0 ? 29 : 11, + (frame.flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame.id, + (frame.flags & CAN_FRAME_RTR) != 0 ? 1 : 0, + (frame.flags & CAN_FRAME_FDF) != 0 ? 1 : 0); - while (1) { - change_led_frame.data[0] = toggle++ & 0x01 ? SET_LED : RESET_LED; - /* This sending call is none blocking. */ - can_send(can_dev, &change_led_frame, K_FOREVER, - tx_irq_callback, - "LED change"); - k_sleep(SLEEP_TIME); +#if DT_NODE_EXISTS(BUTTON_NODE) + printk("abort by pressing %s button\n", BUTTON_NAME); +#endif /* DT_NODE_EXISTS(BUTTON_NODE) */ - UNALIGNED_PUT(sys_cpu_to_be16(counter), - (uint16_t *)&counter_frame.data[0]); - counter++; - /* This sending call is blocking until the message is sent. */ - can_send(can_dev, &counter_frame, K_MSEC(100), NULL, NULL); - k_sleep(SLEEP_TIME); + while (true) { + if (k_sem_take(&tx_queue_sem, K_MSEC(100)) == 0) { + err = can_send(dev, &frame, K_NO_WAIT, can_tx_callback, &tx_queue_sem); + if (err != 0) { + printk("failed to enqueue CAN frame (err %d)\n", err); + } + } + +#if DT_NODE_EXISTS(BUTTON_NODE) + if (k_sem_take(&btn_cb_ctx.sem, K_NO_WAIT) == 0) { + printk("button press detected, babbling stopped\n"); + return 0; + } +#endif /* DT_NODE_EXISTS(BUTTON_NODE) */ } } diff --git a/examples/zephyr-drivers-can/zephyr/Kconfig b/examples/zephyr-drivers-can/zephyr/Kconfig index 12809994..0d283081 100644 --- a/examples/zephyr-drivers-can/zephyr/Kconfig +++ b/examples/zephyr-drivers-can/zephyr/Kconfig @@ -1,15 +1,39 @@ -# Private config options for can sample app - -# Copyright (c) 2018 Alexander Wachter +# Copyright (c) 2022 Henrik Brix Andersen # SPDX-License-Identifier: Apache-2.0 -mainmenu "Controller Area Network sample application" +menu "Controller Area Network babbling node sample" + +config SAMPLE_CAN_BABBLING_CAN_ID + hex "CAN ID" + default 0x010 + range 0x000 0x7ff if !SAMPLE_CAN_BABBLING_EXT_ID + range 0x00000000 0x1fffffff if SAMPLE_CAN_BABBLING_EXT_ID + help + Babbling node CAN ID. + +config SAMPLE_CAN_BABBLING_EXT_ID + bool "Use Extended (29-bit) CAN ID" + help + Babling node sends extended (29-bit) CAN ID frames. + +config SAMPLE_CAN_BABBLING_RTR + bool "Send Remote Transmit Request (RTR) frames" + help + Babbling node sends Remote Transmission Request (RTR) frames. -config LOOPBACK_MODE - bool "Loopback LOOPBACK_MODE" - default y +config SAMPLE_CAN_BABBLING_FD_MODE + bool "Send CAN FD format frames" + select CAN_FD_MODE help - Set the controller to loopback mode. - This allows testing without a second board. + Babbling node sends CAN FD format frames. + +config SAMPLE_CAN_BABBLING_TX_QUEUE_SIZE + int "Maximum number of CAN frames to enqueue" + default 3 + range 1 3 + help + Maximum number of CAN frames to enqueue for transmission. + +endmenu source "Kconfig.zephyr" diff --git a/examples/zephyr-drivers-can/zephyr/prj.conf b/examples/zephyr-drivers-can/zephyr/prj.conf index 7345dfab..8fddc6a9 100644 --- a/examples/zephyr-drivers-can/zephyr/prj.conf +++ b/examples/zephyr-drivers-can/zephyr/prj.conf @@ -1,14 +1,2 @@ -CONFIG_POLL=y CONFIG_CAN=y -CONFIG_CAN_INIT_PRIORITY=80 -CONFIG_CAN_MAX_FILTER=5 - -CONFIG_SHELL=y -CONFIG_CAN_SHELL=y -CONFIG_DEVICE_SHELL=y - CONFIG_GPIO=y -CONFIG_STATS=y -CONFIG_STATS_NAMES=y -CONFIG_STATS_SHELL=y -CONFIG_CAN_STATS=y diff --git a/examples/zephyr-subsys-usb-hid-mouse/src/main.c b/examples/zephyr-subsys-usb-hid-mouse/src/main.c index 36da0536..84913f79 100644 --- a/examples/zephyr-subsys-usb-hid-mouse/src/main.c +++ b/examples/zephyr-subsys-usb-hid-mouse/src/main.c @@ -1,252 +1,151 @@ /* * Copyright (c) 2018 qianfan Zhao - * Copyright (c) 2018 Nordic Semiconductor ASA + * Copyright (c) 2018, 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ + +#include + +#include + #include #include #include +#include +#include #include +#include #include -#define LOG_LEVEL LOG_LEVEL_DBG -LOG_MODULE_REGISTER(main); - -/* - * Devicetree node identifiers for the buttons and LED this sample - * supports. - */ -#define SW0_NODE DT_ALIAS(sw0) -#define SW1_NODE DT_ALIAS(sw1) -#define SW2_NODE DT_ALIAS(sw2) -#define SW3_NODE DT_ALIAS(sw3) -#define LED0_NODE DT_ALIAS(led0) - -/* - * Button sw0 and LED led0 are required. - */ -#if !DT_NODE_EXISTS(SW0_NODE) -#error "Unsupported board: sw0 devicetree alias is not defined" -#endif - -#if !DT_NODE_EXISTS(LED0_NODE) -#error "Unsupported board: led0 devicetree alias is not defined" -#endif - -/* - * Helper macro for initializing a gpio_dt_spec from the devicetree - * with fallback values when the nodes are missing. - */ -#define GPIO_SPEC(node_id) GPIO_DT_SPEC_GET_OR(node_id, gpios, {0}) - -/* - * Create gpio_dt_spec structures from the devicetree. - */ -static const struct gpio_dt_spec sw0 = GPIO_SPEC(SW0_NODE), - sw1 = GPIO_SPEC(SW1_NODE), - sw2 = GPIO_SPEC(SW2_NODE), - sw3 = GPIO_SPEC(SW3_NODE), - led0 = GPIO_SPEC(LED0_NODE); +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); +static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); static const uint8_t hid_report_desc[] = HID_MOUSE_REPORT_DESC(2); - -static uint8_t def_val[4]; -static volatile uint8_t status[4]; -static K_SEM_DEFINE(sem, 0, 1); /* starts off "not available" */ -static struct gpio_callback callback[4]; static enum usb_dc_status_code usb_status; -#define MOUSE_BTN_REPORT_POS 0 -#define MOUSE_X_REPORT_POS 1 -#define MOUSE_Y_REPORT_POS 2 +#define MOUSE_BTN_LEFT 0 +#define MOUSE_BTN_RIGHT 1 -#define MOUSE_BTN_LEFT BIT(0) -#define MOUSE_BTN_RIGHT BIT(1) -#define MOUSE_BTN_MIDDLE BIT(2) +enum mouse_report_idx { + MOUSE_BTN_REPORT_IDX = 0, + MOUSE_X_REPORT_IDX = 1, + MOUSE_Y_REPORT_IDX = 2, + MOUSE_WHEEL_REPORT_IDX = 3, + MOUSE_REPORT_COUNT = 4, +}; -static void status_cb(enum usb_dc_status_code status, const uint8_t *param) +K_MSGQ_DEFINE(mouse_msgq, MOUSE_REPORT_COUNT, 2, 1); +static K_SEM_DEFINE(ep_write_sem, 0, 1); + +static inline void status_cb(enum usb_dc_status_code status, const uint8_t *param) { usb_status = status; } -static void left_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) +static ALWAYS_INLINE void rwup_if_suspended(void) { - int ret; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; - if (IS_ENABLED(CONFIG_USB_DEVICE_REMOTE_WAKEUP)) { if (usb_status == USB_DC_SUSPEND) { usb_wakeup_request(); return; } } - - ret = gpio_pin_get(gpio, sw0.pin); - if (ret < 0) { - LOG_ERR("Failed to get the state of port %s pin %u, error: %d", - gpio->name, sw0.pin, ret); - return; - } - - if (def_val[0] != (uint8_t)ret) { - state |= MOUSE_BTN_LEFT; - } else { - state &= ~MOUSE_BTN_LEFT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } } -static void right_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) +static void input_cb(struct input_event *evt) { - int ret; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; + static uint8_t tmp[MOUSE_REPORT_COUNT]; + + switch (evt->code) { + case INPUT_KEY_0: + rwup_if_suspended(); + WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_LEFT, evt->value); + break; + case INPUT_KEY_1: + rwup_if_suspended(); + WRITE_BIT(tmp[MOUSE_BTN_REPORT_IDX], MOUSE_BTN_RIGHT, evt->value); + break; + case INPUT_KEY_2: + if (evt->value) { + tmp[MOUSE_X_REPORT_IDX] += 10U; + } - if (IS_ENABLED(CONFIG_USB_DEVICE_REMOTE_WAKEUP)) { - if (usb_status == USB_DC_SUSPEND) { - usb_wakeup_request(); - return; + break; + case INPUT_KEY_3: + if (evt->value) { + tmp[MOUSE_Y_REPORT_IDX] += 10U; } - } - ret = gpio_pin_get(gpio, sw1.pin); - if (ret < 0) { - LOG_ERR("Failed to get the state of port %s pin %u, error: %d", - gpio->name, sw1.pin, ret); + break; + default: + LOG_INF("Unrecognized input code %u value %d", + evt->code, evt->value); return; } - if (def_val[1] != (uint8_t)ret) { - state |= MOUSE_BTN_RIGHT; - } else { - state &= ~MOUSE_BTN_RIGHT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } -} - -static void x_move(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - int ret; - uint8_t state = status[MOUSE_X_REPORT_POS]; - - ret = gpio_pin_get(gpio, sw2.pin); - if (ret < 0) { - LOG_ERR("Failed to get the state of port %s pin %u, error: %d", - gpio->name, sw2.pin, ret); - return; + if (k_msgq_put(&mouse_msgq, tmp, K_NO_WAIT) != 0) { + LOG_ERR("Failed to put new input event"); } - if (def_val[2] != (uint8_t)ret) { - state += 10U; - } + tmp[MOUSE_X_REPORT_IDX] = 0U; + tmp[MOUSE_Y_REPORT_IDX] = 0U; - if (status[MOUSE_X_REPORT_POS] != state) { - status[MOUSE_X_REPORT_POS] = state; - k_sem_give(&sem); - } } -static void y_move(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - int ret; - uint8_t state = status[MOUSE_Y_REPORT_POS]; - - ret = gpio_pin_get(gpio, sw3.pin); - if (ret < 0) { - LOG_ERR("Failed to get the state of port %s pin %u, error: %d", - gpio->name, sw3.pin, ret); - return; - } +INPUT_CALLBACK_DEFINE(NULL, input_cb); - if (def_val[3] != (uint8_t)ret) { - state += 10U; - } - - if (status[MOUSE_Y_REPORT_POS] != state) { - status[MOUSE_Y_REPORT_POS] = state; - k_sem_give(&sem); - } -} - -int callbacks_configure(const struct gpio_dt_spec *spec, - gpio_callback_handler_t handler, - struct gpio_callback *callback, uint8_t *val) +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) +static int enable_usb_device_next(void) { - const struct device *gpio = spec->port; - gpio_pin_t pin = spec->pin; - int ret; + struct usbd_context *sample_usbd; + int err; - if (gpio == NULL) { - /* Optional GPIO is missing. */ - return 0; - } - - if (!device_is_ready(gpio)) { - LOG_ERR("GPIO port %s is not ready", gpio->name); + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); return -ENODEV; } - ret = gpio_pin_configure_dt(spec, GPIO_INPUT); - if (ret < 0) { - LOG_ERR("Failed to configure port %s pin %u, error: %d", - gpio->name, pin, ret); - return ret; - } - - ret = gpio_pin_get(gpio, pin); - if (ret < 0) { - LOG_ERR("Failed to get the state of port %s pin %u, error: %d", - gpio->name, pin, ret); - return ret; + err = usbd_enable(sample_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; } - *val = (uint8_t)ret; - - gpio_init_callback(callback, handler, BIT(pin)); - ret = gpio_add_callback(gpio, callback); - if (ret < 0) { - LOG_ERR("Failed to add the callback for port %s pin %u, " - "error: %d", - gpio->name, pin, ret); - return ret; - } - - ret = gpio_pin_interrupt_configure_dt(spec, GPIO_INT_EDGE_BOTH); - if (ret < 0) { - LOG_ERR("Failed to configure interrupt for port %s pin %u, " - "error: %d", - gpio->name, pin, ret); - return ret; - } + LOG_DBG("USB device support enabled"); return 0; } +#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ + +static void int_in_ready_cb(const struct device *dev) +{ + ARG_UNUSED(dev); + k_sem_give(&ep_write_sem); +} + +static const struct hid_ops ops = { + .int_in_ready = int_in_ready_cb, +}; int main(void) { - int ret; - uint8_t report[4] = { 0x00 }; const struct device *hid_dev; + int ret; - if (!device_is_ready(led0.port)) { + if (!gpio_is_ready_dt(&led0)) { LOG_ERR("LED device %s is not ready", led0.port->name); return 0; } +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); +#else hid_dev = device_get_binding("HID_0"); +#endif if (hid_dev == NULL) { LOG_ERR("Cannot get USB HID Device"); return 0; @@ -258,57 +157,34 @@ int main(void) return 0; } - if (callbacks_configure(&sw0, &left_button, &callback[0], - &def_val[0])) { - LOG_ERR("Failed configuring left button callback."); - return 0; - } - - if (callbacks_configure(&sw1, &right_button, &callback[1], - &def_val[1])) { - LOG_ERR("Failed configuring right button callback."); - return 0; - } - - if (callbacks_configure(&sw2, &x_move, &callback[2], &def_val[2])) { - LOG_ERR("Failed configuring X axis movement callback."); - return 0; - } - - if (callbacks_configure(&sw3, &y_move, &callback[3], &def_val[3])) { - LOG_ERR("Failed configuring Y axis movement callback."); - return 0; - } - usb_hid_register_device(hid_dev, hid_report_desc, sizeof(hid_report_desc), - NULL); + &ops); usb_hid_init(hid_dev); +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + ret = enable_usb_device_next(); +#else ret = usb_enable(status_cb); +#endif if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; } while (true) { - k_sem_take(&sem, K_FOREVER); + uint8_t __aligned(sizeof(void *)) report[MOUSE_REPORT_COUNT]; + + k_msgq_get(&mouse_msgq, &report, K_FOREVER); - report[MOUSE_BTN_REPORT_POS] = status[MOUSE_BTN_REPORT_POS]; - report[MOUSE_X_REPORT_POS] = status[MOUSE_X_REPORT_POS]; - status[MOUSE_X_REPORT_POS] = 0U; - report[MOUSE_Y_REPORT_POS] = status[MOUSE_Y_REPORT_POS]; - status[MOUSE_Y_REPORT_POS] = 0U; ret = hid_int_ep_write(hid_dev, report, sizeof(report), NULL); if (ret) { LOG_ERR("HID write error, %d", ret); - } - - /* Toggle LED on sent report */ - ret = gpio_pin_toggle(led0.port, led0.pin); - if (ret < 0) { - LOG_ERR("Failed to toggle the LED pin, error: %d", ret); + } else { + k_sem_take(&ep_write_sem, K_FOREVER); + /* Toggle LED on sent report */ + (void)gpio_pin_toggle(led0.port, led0.pin); } } return 0; diff --git a/examples/zephyr-subsys-usb-hid-mouse/src/sample_usbd_init.c b/examples/zephyr-subsys-usb-hid-mouse/src/sample_usbd_init.c new file mode 100644 index 00000000..1cca20d8 --- /dev/null +++ b/examples/zephyr-subsys-usb-hid-mouse/src/sample_usbd_init.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(usbd_sample_config); + +#define ZEPHYR_PROJECT_USB_VID 0x2fe3 + +/* doc device instantiation start */ +/* + * Instantiate a context named sample_usbd using the default USB device + * controller, the Zephyr project vendor ID, and the sample product ID. + * Zephyr project vendor ID must not be used outside of Zephyr samples. + */ +USBD_DEVICE_DEFINE(sample_usbd, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + ZEPHYR_PROJECT_USB_VID, CONFIG_SAMPLE_USBD_PID); +/* doc device instantiation end */ + +/* doc string instantiation start */ +USBD_DESC_LANG_DEFINE(sample_lang); +USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_SAMPLE_USBD_MANUFACTURER); +USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_SAMPLE_USBD_PRODUCT); +USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn); +/* doc string instantiation end */ + +/* doc configuration instantiation start */ +static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? + USB_SCD_SELF_POWERED : 0) | + (IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ? + USB_SCD_REMOTE_WAKEUP : 0); + +/* Full speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_fs_config, + attributes, + CONFIG_SAMPLE_USBD_MAX_POWER); + +/* High speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_hs_config, + attributes, + CONFIG_SAMPLE_USBD_MAX_POWER); +/* doc configuration instantiation end */ + +/* + * This does not yet provide valuable information, but rather serves as an + * example, and will be improved in the future. + */ +static const struct usb_bos_capability_lpm bos_cap_lpm = { + .bLength = sizeof(struct usb_bos_capability_lpm), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, + .bmAttributes = 0UL, +}; + +USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); + +static void sample_fix_code_triple(struct usbd_context *uds_ctx, + const enum usbd_speed speed) +{ + /* Always use class code information from Interface Descriptors */ + if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || + IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || + IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) { + /* + * Class with multiple interfaces have an Interface + * Association Descriptor available, use an appropriate triple + * to indicate it. + */ + usbd_device_set_code_triple(uds_ctx, speed, + USB_BCC_MISCELLANEOUS, 0x02, 0x01); + } else { + usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0); + } +} + +struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) +{ + int err; + + /* doc add string descriptor start */ + err = usbd_add_descriptor(&sample_usbd, &sample_lang); + if (err) { + LOG_ERR("Failed to initialize language descriptor (%d)", err); + return NULL; + } + + err = usbd_add_descriptor(&sample_usbd, &sample_mfr); + if (err) { + LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err); + return NULL; + } + + err = usbd_add_descriptor(&sample_usbd, &sample_product); + if (err) { + LOG_ERR("Failed to initialize product descriptor (%d)", err); + return NULL; + } + + err = usbd_add_descriptor(&sample_usbd, &sample_sn); + if (err) { + LOG_ERR("Failed to initialize SN descriptor (%d)", err); + return NULL; + } + /* doc add string descriptor end */ + + if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS, + &sample_hs_config); + if (err) { + LOG_ERR("Failed to add High-Speed configuration"); + return NULL; + } + + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_HS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_HS); + } + + /* doc configuration register start */ + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_FS, + &sample_fs_config); + if (err) { + LOG_ERR("Failed to add Full-Speed configuration"); + return NULL; + } + /* doc configuration register end */ + + /* doc functions register start */ + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + /* doc functions register end */ + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_FS); + + if (msg_cb != NULL) { + /* doc device init-and-msg start */ + err = usbd_msg_register_cb(&sample_usbd, msg_cb); + if (err) { + LOG_ERR("Failed to register message callback"); + return NULL; + } + /* doc device init-and-msg end */ + } + + if (IS_ENABLED(CONFIG_SAMPLE_USBD_20_EXTENSION_DESC)) { + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_FS, 0x0201); + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_HS, 0x0201); + + err = usbd_add_descriptor(&sample_usbd, &sample_usbext); + if (err) { + LOG_ERR("Failed to add USB 2.0 Extension Descriptor"); + return NULL; + } + } + + /* doc device init start */ + err = usbd_init(&sample_usbd); + if (err) { + LOG_ERR("Failed to initialize device support"); + return NULL; + } + /* doc device init end */ + + return &sample_usbd; +} diff --git a/examples/zephyr-subsys-usb-hid-mouse/zephyr/CMakeLists.txt b/examples/zephyr-subsys-usb-hid-mouse/zephyr/CMakeLists.txt index 3008afc4..b2f8c307 100644 --- a/examples/zephyr-subsys-usb-hid-mouse/zephyr/CMakeLists.txt +++ b/examples/zephyr-subsys-usb-hid-mouse/zephyr/CMakeLists.txt @@ -1,8 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 -cmake_minimum_required(VERSION 3.13.1) -include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) -project(hid-mouse) +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hid-keyboard) +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources ../src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/examples/zephyr-subsys-usb-hid-mouse/zephyr/Kconfig b/examples/zephyr-subsys-usb-hid-mouse/zephyr/Kconfig new file mode 100644 index 00000000..96c54558 --- /dev/null +++ b/examples/zephyr-subsys-usb-hid-mouse/zephyr/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. +source "samples/subsys/usb/common/Kconfig.sample_usbd" + +source "Kconfig.zephyr" diff --git a/examples/zephyr-subsys-usb-hid-mouse/zephyr/app.overlay b/examples/zephyr-subsys-usb-hid-mouse/zephyr/app.overlay new file mode 100644 index 00000000..0d3d2ee7 --- /dev/null +++ b/examples/zephyr-subsys-usb-hid-mouse/zephyr/app.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + protocol-code = "keyboard"; + in-report-size = <64>; + in-polling-period-us = <1000>; + }; +}; diff --git a/examples/zephyr-subsys-usb-hid-mouse/zephyr/prj.conf b/examples/zephyr-subsys-usb-hid-mouse/zephyr/prj.conf index 3aadd530..04ce14ad 100644 --- a/examples/zephyr-subsys-usb-hid-mouse/zephyr/prj.conf +++ b/examples/zephyr-subsys-usb-hid-mouse/zephyr/prj.conf @@ -1,11 +1,12 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID mouse sample" -CONFIG_USB_DEVICE_PID=0x0007 -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 CONFIG_GPIO=y +CONFIG_INPUT=y +CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/platform.json b/platform.json index cfbefd1f..fe4acb41 100644 --- a/platform.json +++ b/platform.json @@ -298,7 +298,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~2.30600.0" + "version": "~2.30700.0" }, "tool-stm32duino": { "type": "uploader", From e43765575fb8bb1f096f367f01e19f57da99212c Mon Sep 17 00:00:00 2001 From: valeros Date: Thu, 26 Sep 2024 14:43:42 +0300 Subject: [PATCH 2/2] Bump version to 17.6.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fe4acb41..5041f02d 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/platformio/platform-ststm32.git" }, - "version": "17.5.0", + "version": "17.6.0", "frameworks": { "mbed": { "package": "framework-mbed",