/* * Copyright (c) 2018 qianfan Zhao * Copyright (c) 2018, 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #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 enum usb_dc_status_code usb_status; #define MOUSE_BTN_LEFT 0 #define MOUSE_BTN_RIGHT 1 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 uint8_t report[MOUSE_REPORT_COUNT]; static K_SEM_DEFINE(report_sem, 0, 1); static void status_cb(enum usb_dc_status_code status, const uint8_t *param) { usb_status = status; } static ALWAYS_INLINE void rwup_if_suspended(void) { if (IS_ENABLED(CONFIG_USB_DEVICE_REMOTE_WAKEUP)) { if (usb_status == USB_DC_SUSPEND) { usb_wakeup_request(); return; } } } static void input_cb(struct input_event *evt) { uint8_t tmp[MOUSE_REPORT_COUNT]; (void)memcpy(tmp, report, sizeof(tmp)); 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; } break; case INPUT_KEY_3: if (evt->value) { tmp[MOUSE_Y_REPORT_IDX] += 10U; } break; default: LOG_INF("Unrecognized input code %u value %d", evt->code, evt->value); return; } if (memcmp(tmp, report, sizeof(tmp))) { memcpy(report, tmp, sizeof(report)); k_sem_give(&report_sem); } } INPUT_CALLBACK_DEFINE(NULL, input_cb); int main(void) { const struct device *hid_dev; int ret; if (!gpio_is_ready_dt(&led0)) { LOG_ERR("LED device %s is not ready", led0.port->name); return 0; } hid_dev = device_get_binding("HID_0"); if (hid_dev == NULL) { LOG_ERR("Cannot get USB HID Device"); return 0; } ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT); if (ret < 0) { LOG_ERR("Failed to configure the LED pin, error: %d", ret); return 0; } usb_hid_register_device(hid_dev, hid_report_desc, sizeof(hid_report_desc), NULL); usb_hid_init(hid_dev); ret = usb_enable(status_cb); if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; } while (true) { k_sem_take(&report_sem, K_FOREVER); ret = hid_int_ep_write(hid_dev, report, sizeof(report), NULL); report[MOUSE_X_REPORT_IDX] = 0U; report[MOUSE_Y_REPORT_IDX] = 0U; 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); } } return 0; }