| /* |
| * Copyright (c) 2019 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #include <zephyr/zephyr.h> |
| #include <zephyr/device.h> |
| #include <zephyr/drivers/gpio.h> |
| #include <zephyr/drivers/uart.h> |
| #include <string.h> |
| #include <zephyr/random/rand32.h> |
| |
| #include <zephyr/usb/usb_device.h> |
| #include <zephyr/usb/class/usb_hid.h> |
| #include <zephyr/usb/class/usb_cdc.h> |
| |
| #define LOG_LEVEL LOG_LEVEL_DBG |
| LOG_MODULE_REGISTER(main); |
| |
| #define SW0_NODE DT_ALIAS(sw0) |
| |
| #if DT_NODE_HAS_STATUS(SW0_NODE, okay) |
| #define PORT0 DT_GPIO_LABEL(SW0_NODE, gpios) |
| #define PIN0 DT_GPIO_PIN(SW0_NODE, gpios) |
| #define PIN0_FLAGS DT_GPIO_FLAGS(SW0_NODE, gpios) |
| #else |
| #error "Unsupported board: sw0 devicetree alias is not defined" |
| #define PORT0 "" |
| #define PIN0 0 |
| #define PIN0_FLAGS 0 |
| #endif |
| |
| #define SW1_NODE DT_ALIAS(sw1) |
| |
| #if DT_NODE_HAS_STATUS(SW1_NODE, okay) |
| #define PORT1 DT_GPIO_LABEL(SW1_NODE, gpios) |
| #define PIN1 DT_GPIO_PIN(SW1_NODE, gpios) |
| #define PIN1_FLAGS DT_GPIO_FLAGS(SW1_NODE, gpios) |
| #endif |
| |
| #define SW2_NODE DT_ALIAS(sw2) |
| |
| #if DT_NODE_HAS_STATUS(SW2_NODE, okay) |
| #define PORT2 DT_GPIO_LABEL(SW2_NODE, gpios) |
| #define PIN2 DT_GPIO_PIN(SW2_NODE, gpios) |
| #define PIN2_FLAGS DT_GPIO_FLAGS(SW2_NODE, gpios) |
| #endif |
| |
| #define SW3_NODE DT_ALIAS(sw3) |
| |
| #if DT_NODE_HAS_STATUS(SW3_NODE, okay) |
| #define PORT3 DT_GPIO_LABEL(SW3_NODE, gpios) |
| #define PIN3 DT_GPIO_PIN(SW3_NODE, gpios) |
| #define PIN3_FLAGS DT_GPIO_FLAGS(SW3_NODE, gpios) |
| #endif |
| |
| /* Event FIFO */ |
| |
| K_FIFO_DEFINE(evt_fifo); |
| |
| enum evt_t { |
| GPIO_BUTTON_0 = 0x00, |
| GPIO_BUTTON_1 = 0x01, |
| GPIO_BUTTON_2 = 0x02, |
| GPIO_BUTTON_3 = 0x03, |
| CDC_UP = 0x04, |
| CDC_DOWN = 0x05, |
| CDC_LEFT = 0x06, |
| CDC_RIGHT = 0x07, |
| CDC_UNKNOWN = 0x08, |
| CDC_STRING = 0x09, |
| HID_MOUSE_CLEAR = 0x0A, |
| HID_KBD_CLEAR = 0x0B, |
| HID_KBD_STRING = 0x0C, |
| }; |
| |
| struct app_evt_t { |
| sys_snode_t node; |
| enum evt_t event_type; |
| }; |
| |
| #define FIFO_ELEM_MIN_SZ sizeof(struct app_evt_t) |
| #define FIFO_ELEM_MAX_SZ sizeof(struct app_evt_t) |
| #define FIFO_ELEM_COUNT 255 |
| #define FIFO_ELEM_ALIGN sizeof(unsigned int) |
| |
| K_HEAP_DEFINE(event_elem_pool, FIFO_ELEM_MAX_SZ * FIFO_ELEM_COUNT + 256); |
| |
| static inline void app_evt_free(struct app_evt_t *ev) |
| { |
| k_heap_free(&event_elem_pool, ev); |
| } |
| |
| static inline void app_evt_put(struct app_evt_t *ev) |
| { |
| k_fifo_put(&evt_fifo, ev); |
| } |
| |
| static inline struct app_evt_t *app_evt_get(void) |
| { |
| return k_fifo_get(&evt_fifo, K_NO_WAIT); |
| } |
| |
| static inline void app_evt_flush(void) |
| { |
| struct app_evt_t *ev; |
| |
| do { |
| ev = app_evt_get(); |
| if (ev) { |
| app_evt_free(ev); |
| } |
| } while (ev != NULL); |
| } |
| |
| static inline struct app_evt_t *app_evt_alloc(void) |
| { |
| struct app_evt_t *ev; |
| |
| ev = k_heap_alloc(&event_elem_pool, |
| sizeof(struct app_evt_t), |
| K_NO_WAIT); |
| if (ev == NULL) { |
| LOG_ERR("APP event allocation failed!"); |
| app_evt_flush(); |
| |
| ev = k_heap_alloc(&event_elem_pool, |
| sizeof(struct app_evt_t), |
| K_NO_WAIT); |
| if (ev == NULL) { |
| LOG_ERR("APP event memory corrupted."); |
| __ASSERT_NO_MSG(0); |
| return NULL; |
| } |
| return NULL; |
| } |
| |
| return ev; |
| } |
| |
| /* HID */ |
| |
| static const uint8_t hid_mouse_report_desc[] = HID_MOUSE_REPORT_DESC(2); |
| static const uint8_t hid_kbd_report_desc[] = HID_KEYBOARD_REPORT_DESC(); |
| |
| static K_SEM_DEFINE(evt_sem, 0, 1); /* starts off "not available" */ |
| static K_SEM_DEFINE(usb_sem, 1, 1); /* starts off "available" */ |
| static struct gpio_callback callback[4]; |
| |
| static char data_buf_mouse[64], data_buf_kbd[64]; |
| static char string[64]; |
| static uint8_t chr_ptr_mouse, chr_ptr_kbd, str_pointer; |
| |
| #define MOUSE_BTN_REPORT_POS 0 |
| #define MOUSE_X_REPORT_POS 1 |
| #define MOUSE_Y_REPORT_POS 2 |
| |
| #define MOUSE_BTN_LEFT BIT(0) |
| #define MOUSE_BTN_RIGHT BIT(1) |
| #define MOUSE_BTN_MIDDLE BIT(2) |
| |
| static const char *welcome = "Welcome to "; |
| static const char *banner0 = "\r\n" |
| "Supported commands:\r\n" |
| "up - moves the mouse up\r\n" |
| "down - moves the mouse down\r\n" |
| "right - moves the mouse to right\r\n" |
| "left - moves the mouse to left\r\n"; |
| static const char *banner1 = "\r\n" |
| "Enter a string and terminate " |
| "it with ENTER.\r\n" |
| "It will be sent via HID " |
| "when BUTTON 2 is pressed.\r\n" |
| "You can modify it by sending " |
| "a new one here.\r\n"; |
| static const char *gpio0 = "Button 0 pressed\r\n"; |
| static const char *gpio1 = "Button 1 pressed\r\n"; |
| static const char *gpio2 = "Button 2 pressed\r\n"; |
| static const char *gpio3 = "Button 3 pressed\r\n"; |
| static const char *unknown = "Command not recognized.\r\n"; |
| static const char *up = "Mouse up\r\n"; |
| static const char *down = "Mouse down\r\n"; |
| static const char *left = "Mouse left\r\n"; |
| static const char *right = "Mouse right\r\n"; |
| static const char *evt_fail = "Unknown event detected!\r\n"; |
| static const char *set_str = "String set to: "; |
| static const char *endl = "\r\n"; |
| |
| static void in_ready_cb(const struct device *dev) |
| { |
| ARG_UNUSED(dev); |
| |
| k_sem_give(&usb_sem); |
| } |
| |
| static const struct hid_ops ops = { |
| .int_in_ready = in_ready_cb, |
| }; |
| |
| static void clear_mouse_report(void) |
| { |
| struct app_evt_t *new_evt = app_evt_alloc(); |
| |
| new_evt->event_type = HID_MOUSE_CLEAR; |
| app_evt_put(new_evt); |
| k_sem_give(&evt_sem); |
| } |
| |
| static void clear_kbd_report(void) |
| { |
| struct app_evt_t *new_evt = app_evt_alloc(); |
| |
| new_evt->event_type = HID_KBD_CLEAR; |
| app_evt_put(new_evt); |
| k_sem_give(&evt_sem); |
| } |
| |
| static int ascii_to_hid(uint8_t ascii) |
| { |
| if (ascii < 32) { |
| /* Character not supported */ |
| return -1; |
| } else if (ascii < 48) { |
| /* Special characters */ |
| switch (ascii) { |
| case 32: |
| return HID_KEY_SPACE; |
| case 33: |
| return HID_KEY_1; |
| case 34: |
| return HID_KEY_APOSTROPHE; |
| case 35: |
| return HID_KEY_3; |
| case 36: |
| return HID_KEY_4; |
| case 37: |
| return HID_KEY_5; |
| case 38: |
| return HID_KEY_7; |
| case 39: |
| return HID_KEY_APOSTROPHE; |
| case 40: |
| return HID_KEY_9; |
| case 41: |
| return HID_KEY_0; |
| case 42: |
| return HID_KEY_8; |
| case 43: |
| return HID_KEY_EQUAL; |
| case 44: |
| return HID_KEY_COMMA; |
| case 45: |
| return HID_KEY_MINUS; |
| case 46: |
| return HID_KEY_DOT; |
| case 47: |
| return HID_KEY_SLASH; |
| default: |
| return -1; |
| } |
| } else if (ascii < 58) { |
| /* Numbers */ |
| if (ascii == 48U) { |
| return HID_KEY_0; |
| } else { |
| return ascii - 19; |
| } |
| } else if (ascii < 65) { |
| /* Special characters #2 */ |
| switch (ascii) { |
| case 58: |
| return HID_KEY_SEMICOLON; |
| case 59: |
| return HID_KEY_SEMICOLON; |
| case 60: |
| return HID_KEY_COMMA; |
| case 61: |
| return HID_KEY_EQUAL; |
| case 62: |
| return HID_KEY_DOT; |
| case 63: |
| return HID_KEY_SLASH; |
| case 64: |
| return HID_KEY_2; |
| default: |
| return -1; |
| } |
| } else if (ascii < 91) { |
| /* Uppercase characters */ |
| return ascii - 61U; |
| } else if (ascii < 97) { |
| /* Special characters #3 */ |
| switch (ascii) { |
| case 91: |
| return HID_KEY_LEFTBRACE; |
| case 92: |
| return HID_KEY_BACKSLASH; |
| case 93: |
| return HID_KEY_RIGHTBRACE; |
| case 94: |
| return HID_KEY_6; |
| case 95: |
| return HID_KEY_MINUS; |
| case 96: |
| return HID_KEY_GRAVE; |
| default: |
| return -1; |
| } |
| } else if (ascii < 123) { |
| /* Lowercase letters */ |
| return ascii - 93; |
| } else if (ascii < 128) { |
| /* Special characters #4 */ |
| switch (ascii) { |
| case 123: |
| return HID_KEY_LEFTBRACE; |
| case 124: |
| return HID_KEY_BACKSLASH; |
| case 125: |
| return HID_KEY_RIGHTBRACE; |
| case 126: |
| return HID_KEY_GRAVE; |
| case 127: |
| return HID_KEY_DELETE; |
| default: |
| return -1; |
| } |
| } |
| |
| return -1; |
| } |
| |
| static bool needs_shift(uint8_t ascii) |
| { |
| if ((ascii < 33) || (ascii == 39U)) { |
| return false; |
| } else if ((ascii >= 33U) && (ascii < 44)) { |
| return true; |
| } else if ((ascii >= 44U) && (ascii < 58)) { |
| return false; |
| } else if ((ascii == 59U) || (ascii == 61U)) { |
| return false; |
| } else if ((ascii >= 58U) && (ascii < 91)) { |
| return true; |
| } else if ((ascii >= 91U) && (ascii < 94)) { |
| return false; |
| } else if ((ascii == 94U) || (ascii == 95U)) { |
| return true; |
| } else if ((ascii > 95) && (ascii < 123)) { |
| return false; |
| } else if ((ascii > 122) && (ascii < 127)) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /* CDC ACM */ |
| |
| static volatile bool data_transmitted; |
| static volatile bool data_arrived; |
| |
| static void flush_buffer_mouse(void) |
| { |
| chr_ptr_mouse = 0U; |
| memset(data_buf_mouse, 0, sizeof(data_buf_mouse)); |
| } |
| |
| static void flush_buffer_kbd(void) |
| { |
| chr_ptr_kbd = 0U; |
| memset(data_buf_kbd, 0, sizeof(data_buf_kbd)); |
| } |
| |
| static void write_data(const struct device *dev, const char *buf, int len) |
| { |
| uart_irq_tx_enable(dev); |
| |
| while (len) { |
| int written; |
| |
| data_transmitted = false; |
| written = uart_fifo_fill(dev, (const uint8_t *)buf, len); |
| while (data_transmitted == false) { |
| k_yield(); |
| } |
| |
| len -= written; |
| buf += written; |
| } |
| |
| uart_irq_tx_disable(dev); |
| } |
| |
| static void cdc_mouse_int_handler(const struct device *dev, void *user_data) |
| { |
| ARG_UNUSED(user_data); |
| |
| uart_irq_update(dev); |
| |
| if (uart_irq_tx_ready(dev)) { |
| data_transmitted = true; |
| } |
| |
| if (!uart_irq_rx_ready(dev)) { |
| return; |
| } |
| uint32_t bytes_read; |
| |
| while ((bytes_read = uart_fifo_read(dev, |
| (uint8_t *)data_buf_mouse+chr_ptr_mouse, |
| sizeof(data_buf_mouse)-chr_ptr_mouse))) { |
| chr_ptr_mouse += bytes_read; |
| if (data_buf_mouse[chr_ptr_mouse - 1] == '\r') { |
| /* ENTER */ |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| data_buf_mouse[chr_ptr_mouse - 1] = '\0'; |
| |
| if (!strcmp(data_buf_mouse, "up")) { |
| ev->event_type = CDC_UP; |
| } else if (!strcmp(data_buf_mouse, "down")) { |
| ev->event_type = CDC_DOWN; |
| } else if (!strcmp(data_buf_mouse, "right")) { |
| ev->event_type = CDC_RIGHT; |
| } else if (!strcmp(data_buf_mouse, "left")) { |
| ev->event_type = CDC_LEFT; |
| } else { |
| ev->event_type = CDC_UNKNOWN; |
| } |
| flush_buffer_mouse(); |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| |
| if (chr_ptr_mouse >= sizeof(data_buf_mouse)) { |
| LOG_WRN("Buffer overflow"); |
| flush_buffer_mouse(); |
| } |
| } |
| } |
| |
| static void cdc_kbd_int_handler(const struct device *dev, void *user_data) |
| { |
| ARG_UNUSED(user_data); |
| |
| uart_irq_update(dev); |
| |
| if (uart_irq_tx_ready(dev)) { |
| data_transmitted = true; |
| } |
| |
| if (!uart_irq_rx_ready(dev)) { |
| return; |
| } |
| uint32_t bytes_read; |
| |
| while ((bytes_read = uart_fifo_read(dev, |
| (uint8_t *)data_buf_kbd+chr_ptr_kbd, |
| sizeof(data_buf_kbd)-chr_ptr_kbd))) { |
| chr_ptr_kbd += bytes_read; |
| if (data_buf_kbd[chr_ptr_kbd - 1] == '\r') { |
| /* ENTER */ |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| data_buf_kbd[chr_ptr_kbd - 1] = '\0'; |
| strcpy(string, data_buf_kbd); |
| ev->event_type = CDC_STRING; |
| flush_buffer_kbd(); |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| } |
| } |
| |
| /* Devices */ |
| |
| static void btn0(const struct device *gpio, struct gpio_callback *cb, |
| uint32_t pins) |
| { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = GPIO_BUTTON_0, |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| |
| #if DT_NODE_HAS_STATUS(SW1_NODE, okay) |
| static void btn1(const struct device *gpio, struct gpio_callback *cb, |
| uint32_t pins) |
| { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = GPIO_BUTTON_1, |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| #endif |
| |
| #if DT_NODE_HAS_STATUS(SW2_NODE, okay) |
| static void btn2(const struct device *gpio, struct gpio_callback *cb, |
| uint32_t pins) |
| { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = GPIO_BUTTON_2, |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| #endif |
| |
| #if DT_NODE_HAS_STATUS(SW3_NODE, okay) |
| static void btn3(const struct device *gpio, struct gpio_callback *cb, |
| uint32_t pins) |
| { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = GPIO_BUTTON_3, |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } |
| #endif |
| |
| int callbacks_configure(const struct device *gpio, uint32_t pin, int flags, |
| void (*handler)(const struct device *, struct gpio_callback*, |
| uint32_t), |
| struct gpio_callback *callback) |
| { |
| if (!gpio) { |
| LOG_ERR("Could not find PORT"); |
| return -ENXIO; |
| } |
| |
| gpio_pin_configure(gpio, pin, GPIO_INPUT | flags); |
| |
| gpio_init_callback(callback, handler, BIT(pin)); |
| gpio_add_callback(gpio, callback); |
| gpio_pin_interrupt_configure(gpio, pin, GPIO_INT_EDGE_TO_ACTIVE); |
| |
| return 0; |
| } |
| |
| static void status_cb(enum usb_dc_status_code status, const uint8_t *param) |
| { |
| LOG_INF("Status %d", status); |
| } |
| |
| #define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), |
| |
| void main(void) |
| { |
| const struct device *cdc_dev[] = { |
| DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA) |
| }; |
| BUILD_ASSERT(ARRAY_SIZE(cdc_dev) >= 2, "Not enough CDC ACM instances"); |
| const struct device *hid0_dev, *hid1_dev; |
| struct app_evt_t *ev; |
| uint32_t dtr = 0U; |
| int ret; |
| |
| /* Configure devices */ |
| |
| hid0_dev = device_get_binding("HID_0"); |
| if (hid0_dev == NULL) { |
| LOG_ERR("Cannot get USB HID 0 Device"); |
| return; |
| } |
| |
| hid1_dev = device_get_binding("HID_1"); |
| if (hid1_dev == NULL) { |
| LOG_ERR("Cannot get USB HID 1 Device"); |
| return; |
| } |
| |
| for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { |
| if (!device_is_ready(cdc_dev[idx])) { |
| LOG_ERR("CDC ACM device %s is not ready", |
| cdc_dev[idx]->name); |
| return; |
| } |
| } |
| |
| if (callbacks_configure(device_get_binding(PORT0), PIN0, PIN0_FLAGS, |
| &btn0, &callback[0])) { |
| LOG_ERR("Failed configuring button 0 callback."); |
| return; |
| } |
| |
| #if DT_NODE_HAS_STATUS(SW1_NODE, okay) |
| if (callbacks_configure(device_get_binding(PORT1), PIN1, PIN1_FLAGS, |
| &btn1, &callback[1])) { |
| LOG_ERR("Failed configuring button 1 callback."); |
| return; |
| } |
| #endif |
| |
| #if DT_NODE_HAS_STATUS(SW2_NODE, okay) |
| if (callbacks_configure(device_get_binding(PORT2), PIN2, PIN2_FLAGS, |
| &btn2, &callback[2])) { |
| LOG_ERR("Failed configuring button 2 callback."); |
| return; |
| } |
| #endif |
| |
| #if DT_NODE_HAS_STATUS(SW3_NODE, okay) |
| if (callbacks_configure(device_get_binding(PORT3), PIN3, PIN3_FLAGS, |
| &btn3, &callback[3])) { |
| LOG_ERR("Failed configuring button 3 callback."); |
| return; |
| } |
| #endif |
| |
| /* Initialize HID */ |
| |
| usb_hid_register_device(hid0_dev, hid_mouse_report_desc, |
| sizeof(hid_mouse_report_desc), &ops); |
| |
| usb_hid_register_device(hid1_dev, hid_kbd_report_desc, |
| sizeof(hid_kbd_report_desc), &ops); |
| |
| usb_hid_init(hid0_dev); |
| usb_hid_init(hid1_dev); |
| |
| ret = usb_enable(status_cb); |
| if (ret != 0) { |
| LOG_ERR("Failed to enable USB"); |
| return; |
| } |
| |
| /* Initialize CDC ACM */ |
| for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { |
| LOG_INF("Wait for DTR on %s", cdc_dev[idx]->name); |
| while (1) { |
| uart_line_ctrl_get(cdc_dev[idx], |
| UART_LINE_CTRL_DTR, |
| &dtr); |
| if (dtr) { |
| break; |
| } else { |
| /* Give CPU resources to low priority threads. */ |
| k_sleep(K_MSEC(100)); |
| } |
| } |
| |
| LOG_INF("DTR on device %s", cdc_dev[idx]->name); |
| } |
| |
| /* Wait 1 sec for the host to do all settings */ |
| k_busy_wait(USEC_PER_SEC); |
| |
| uart_irq_callback_set(cdc_dev[0], cdc_mouse_int_handler); |
| uart_irq_callback_set(cdc_dev[1], cdc_kbd_int_handler); |
| |
| write_data(cdc_dev[0], welcome, strlen(welcome)); |
| write_data(cdc_dev[0], cdc_dev[0]->name, strlen(cdc_dev[0]->name)); |
| write_data(cdc_dev[0], banner0, strlen(banner0)); |
| write_data(cdc_dev[1], welcome, strlen(welcome)); |
| write_data(cdc_dev[1], cdc_dev[1]->name, strlen(cdc_dev[1]->name)); |
| write_data(cdc_dev[1], banner1, strlen(banner1)); |
| |
| uart_irq_rx_enable(cdc_dev[0]); |
| uart_irq_rx_enable(cdc_dev[1]); |
| |
| while (true) { |
| k_sem_take(&evt_sem, K_FOREVER); |
| |
| while ((ev = app_evt_get()) != NULL) { |
| switch (ev->event_type) { |
| case GPIO_BUTTON_0: |
| { |
| /* Move the mouse in random direction */ |
| uint8_t rep[] = {0x00, sys_rand32_get(), |
| sys_rand32_get(), 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], gpio0, strlen(gpio0)); |
| clear_mouse_report(); |
| break; |
| } |
| case GPIO_BUTTON_1: |
| { |
| /* Press left mouse button */ |
| uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; |
| |
| rep[MOUSE_BTN_REPORT_POS] |= MOUSE_BTN_LEFT; |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], gpio1, strlen(gpio1)); |
| clear_mouse_report(); |
| break; |
| } |
| case GPIO_BUTTON_2: |
| { |
| /* Send string on HID keyboard */ |
| write_data(cdc_dev[1], gpio2, strlen(gpio2)); |
| if (strlen(string) > 0) { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = HID_KBD_STRING, |
| app_evt_put(ev); |
| str_pointer = 0U; |
| k_sem_give(&evt_sem); |
| } |
| break; |
| } |
| case GPIO_BUTTON_3: |
| { |
| /* Toggle CAPS LOCK */ |
| uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, |
| HID_KEY_CAPSLOCK}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid1_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[1], gpio3, strlen(gpio3)); |
| clear_kbd_report(); |
| break; |
| } |
| case CDC_UP: |
| { |
| /* Mouse up */ |
| uint8_t rep[] = {0x00, 0x00, 0xE0, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], up, strlen(up)); |
| clear_mouse_report(); |
| break; |
| } |
| case CDC_DOWN: |
| { |
| /* Mouse down */ |
| uint8_t rep[] = {0x00, 0x00, 0x20, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], down, strlen(down)); |
| clear_mouse_report(); |
| break; |
| } |
| case CDC_RIGHT: |
| { |
| /* Mouse right */ |
| uint8_t rep[] = {0x00, 0x20, 0x00, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], right, strlen(right)); |
| clear_mouse_report(); |
| break; |
| } |
| case CDC_LEFT: |
| { |
| /* Mouse left */ |
| uint8_t rep[] = {0x00, 0xE0, 0x00, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| write_data(cdc_dev[0], left, strlen(left)); |
| clear_mouse_report(); |
| break; |
| } |
| case CDC_UNKNOWN: |
| { |
| write_data(cdc_dev[0], unknown, strlen(unknown)); |
| write_data(cdc_dev[1], unknown, strlen(unknown)); |
| break; |
| } |
| case CDC_STRING: |
| { |
| write_data(cdc_dev[0], set_str, strlen(set_str)); |
| write_data(cdc_dev[0], string, strlen(string)); |
| write_data(cdc_dev[0], endl, strlen(endl)); |
| |
| write_data(cdc_dev[1], set_str, strlen(set_str)); |
| write_data(cdc_dev[1], string, strlen(string)); |
| write_data(cdc_dev[1], endl, strlen(endl)); |
| break; |
| } |
| case HID_MOUSE_CLEAR: |
| { |
| /* Clear mouse report */ |
| uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid0_dev, rep, |
| sizeof(rep), NULL); |
| break; |
| } |
| case HID_KBD_CLEAR: |
| { |
| /* Clear kbd report */ |
| uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid1_dev, rep, |
| sizeof(rep), NULL); |
| break; |
| } |
| case HID_KBD_STRING: |
| { |
| int ch = ascii_to_hid(string[str_pointer]); |
| |
| if (ch == -1) { |
| LOG_WRN("Unsupported character: %d", |
| string[str_pointer]); |
| } else { |
| uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| if (needs_shift(string[str_pointer])) { |
| rep[0] |= |
| HID_KBD_MODIFIER_RIGHT_SHIFT; |
| } |
| rep[7] = ch; |
| |
| k_sem_take(&usb_sem, K_FOREVER); |
| hid_int_ep_write(hid1_dev, rep, |
| sizeof(rep), NULL); |
| } |
| |
| str_pointer++; |
| |
| if (strlen(string) > str_pointer) { |
| struct app_evt_t *ev = app_evt_alloc(); |
| |
| ev->event_type = HID_KBD_STRING, |
| app_evt_put(ev); |
| k_sem_give(&evt_sem); |
| } else if (strlen(string) == str_pointer) { |
| clear_kbd_report(); |
| } |
| |
| break; |
| } |
| default: |
| { |
| LOG_ERR("Unknown event to execute"); |
| write_data(cdc_dev[0], evt_fail, |
| strlen(evt_fail)); |
| write_data(cdc_dev[1], evt_fail, |
| strlen(evt_fail)); |
| break; |
| } |
| break; |
| } |
| app_evt_free(ev); |
| } |
| } |
| } |