1 /*
2 * Copyright (c) 2019 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/kernel.h>
7 #include <zephyr/device.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/drivers/uart.h>
10 #include <string.h>
11 #include <zephyr/random/rand32.h>
12
13 #include <zephyr/usb/usb_device.h>
14 #include <zephyr/usb/class/usb_hid.h>
15 #include <zephyr/usb/class/usb_cdc.h>
16
17 #define LOG_LEVEL LOG_LEVEL_DBG
18 LOG_MODULE_REGISTER(main);
19
20 #define SW0_NODE DT_ALIAS(sw0)
21
22 #if DT_NODE_HAS_STATUS(SW0_NODE, okay)
23 static const struct gpio_dt_spec sw0_gpio = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
24 #endif
25
26 #define SW1_NODE DT_ALIAS(sw1)
27
28 #if DT_NODE_HAS_STATUS(SW1_NODE, okay)
29 static const struct gpio_dt_spec sw1_gpio = GPIO_DT_SPEC_GET(SW1_NODE, gpios);
30 #endif
31
32 #define SW2_NODE DT_ALIAS(sw2)
33
34 #if DT_NODE_HAS_STATUS(SW2_NODE, okay)
35 static const struct gpio_dt_spec sw2_gpio = GPIO_DT_SPEC_GET(SW2_NODE, gpios);
36 #endif
37
38 #define SW3_NODE DT_ALIAS(sw3)
39
40 #if DT_NODE_HAS_STATUS(SW3_NODE, okay)
41 static const struct gpio_dt_spec sw3_gpio = GPIO_DT_SPEC_GET(SW3_NODE, gpios);
42 #endif
43
44 /* Event FIFO */
45
46 K_FIFO_DEFINE(evt_fifo);
47
48 enum evt_t {
49 GPIO_BUTTON_0 = 0x00,
50 GPIO_BUTTON_1 = 0x01,
51 GPIO_BUTTON_2 = 0x02,
52 GPIO_BUTTON_3 = 0x03,
53 CDC_UP = 0x04,
54 CDC_DOWN = 0x05,
55 CDC_LEFT = 0x06,
56 CDC_RIGHT = 0x07,
57 CDC_UNKNOWN = 0x08,
58 CDC_STRING = 0x09,
59 HID_MOUSE_CLEAR = 0x0A,
60 HID_KBD_CLEAR = 0x0B,
61 HID_KBD_STRING = 0x0C,
62 };
63
64 struct app_evt_t {
65 sys_snode_t node;
66 enum evt_t event_type;
67 };
68
69 #define FIFO_ELEM_MIN_SZ sizeof(struct app_evt_t)
70 #define FIFO_ELEM_MAX_SZ sizeof(struct app_evt_t)
71 #define FIFO_ELEM_COUNT 255
72 #define FIFO_ELEM_ALIGN sizeof(unsigned int)
73
74 K_HEAP_DEFINE(event_elem_pool, FIFO_ELEM_MAX_SZ * FIFO_ELEM_COUNT + 256);
75
app_evt_free(struct app_evt_t * ev)76 static inline void app_evt_free(struct app_evt_t *ev)
77 {
78 k_heap_free(&event_elem_pool, ev);
79 }
80
app_evt_put(struct app_evt_t * ev)81 static inline void app_evt_put(struct app_evt_t *ev)
82 {
83 k_fifo_put(&evt_fifo, ev);
84 }
85
app_evt_get(void)86 static inline struct app_evt_t *app_evt_get(void)
87 {
88 return k_fifo_get(&evt_fifo, K_NO_WAIT);
89 }
90
app_evt_flush(void)91 static inline void app_evt_flush(void)
92 {
93 struct app_evt_t *ev;
94
95 do {
96 ev = app_evt_get();
97 if (ev) {
98 app_evt_free(ev);
99 }
100 } while (ev != NULL);
101 }
102
app_evt_alloc(void)103 static inline struct app_evt_t *app_evt_alloc(void)
104 {
105 struct app_evt_t *ev;
106
107 ev = k_heap_alloc(&event_elem_pool,
108 sizeof(struct app_evt_t),
109 K_NO_WAIT);
110 if (ev == NULL) {
111 LOG_ERR("APP event allocation failed!");
112 app_evt_flush();
113
114 ev = k_heap_alloc(&event_elem_pool,
115 sizeof(struct app_evt_t),
116 K_NO_WAIT);
117 if (ev == NULL) {
118 LOG_ERR("APP event memory corrupted.");
119 __ASSERT_NO_MSG(0);
120 return NULL;
121 }
122 return NULL;
123 }
124
125 return ev;
126 }
127
128 /* HID */
129
130 static const uint8_t hid_mouse_report_desc[] = HID_MOUSE_REPORT_DESC(2);
131 static const uint8_t hid_kbd_report_desc[] = HID_KEYBOARD_REPORT_DESC();
132
133 static K_SEM_DEFINE(evt_sem, 0, 1); /* starts off "not available" */
134 static K_SEM_DEFINE(usb_sem, 1, 1); /* starts off "available" */
135 static struct gpio_callback callback[4];
136
137 static char data_buf_mouse[64], data_buf_kbd[64];
138 static char string[64];
139 static uint8_t chr_ptr_mouse, chr_ptr_kbd, str_pointer;
140
141 #define MOUSE_BTN_REPORT_POS 0
142 #define MOUSE_X_REPORT_POS 1
143 #define MOUSE_Y_REPORT_POS 2
144
145 #define MOUSE_BTN_LEFT BIT(0)
146 #define MOUSE_BTN_RIGHT BIT(1)
147 #define MOUSE_BTN_MIDDLE BIT(2)
148
149 static const char *welcome = "Welcome to ";
150 static const char *banner0 = "\r\n"
151 "Supported commands:\r\n"
152 "up - moves the mouse up\r\n"
153 "down - moves the mouse down\r\n"
154 "right - moves the mouse to right\r\n"
155 "left - moves the mouse to left\r\n";
156 static const char *banner1 = "\r\n"
157 "Enter a string and terminate "
158 "it with ENTER.\r\n"
159 "It will be sent via HID "
160 "when BUTTON 2 is pressed.\r\n"
161 "You can modify it by sending "
162 "a new one here.\r\n";
163 static const char *gpio0 = "Button 0 pressed\r\n";
164 static const char *gpio1 = "Button 1 pressed\r\n";
165 static const char *gpio2 = "Button 2 pressed\r\n";
166 static const char *gpio3 = "Button 3 pressed\r\n";
167 static const char *unknown = "Command not recognized.\r\n";
168 static const char *up = "Mouse up\r\n";
169 static const char *down = "Mouse down\r\n";
170 static const char *left = "Mouse left\r\n";
171 static const char *right = "Mouse right\r\n";
172 static const char *evt_fail = "Unknown event detected!\r\n";
173 static const char *set_str = "String set to: ";
174 static const char *endl = "\r\n";
175
in_ready_cb(const struct device * dev)176 static void in_ready_cb(const struct device *dev)
177 {
178 ARG_UNUSED(dev);
179
180 k_sem_give(&usb_sem);
181 }
182
183 static const struct hid_ops ops = {
184 .int_in_ready = in_ready_cb,
185 };
186
clear_mouse_report(void)187 static void clear_mouse_report(void)
188 {
189 struct app_evt_t *new_evt = app_evt_alloc();
190
191 new_evt->event_type = HID_MOUSE_CLEAR;
192 app_evt_put(new_evt);
193 k_sem_give(&evt_sem);
194 }
195
clear_kbd_report(void)196 static void clear_kbd_report(void)
197 {
198 struct app_evt_t *new_evt = app_evt_alloc();
199
200 new_evt->event_type = HID_KBD_CLEAR;
201 app_evt_put(new_evt);
202 k_sem_give(&evt_sem);
203 }
204
ascii_to_hid(uint8_t ascii)205 static int ascii_to_hid(uint8_t ascii)
206 {
207 if (ascii < 32) {
208 /* Character not supported */
209 return -1;
210 } else if (ascii < 48) {
211 /* Special characters */
212 switch (ascii) {
213 case 32:
214 return HID_KEY_SPACE;
215 case 33:
216 return HID_KEY_1;
217 case 34:
218 return HID_KEY_APOSTROPHE;
219 case 35:
220 return HID_KEY_3;
221 case 36:
222 return HID_KEY_4;
223 case 37:
224 return HID_KEY_5;
225 case 38:
226 return HID_KEY_7;
227 case 39:
228 return HID_KEY_APOSTROPHE;
229 case 40:
230 return HID_KEY_9;
231 case 41:
232 return HID_KEY_0;
233 case 42:
234 return HID_KEY_8;
235 case 43:
236 return HID_KEY_EQUAL;
237 case 44:
238 return HID_KEY_COMMA;
239 case 45:
240 return HID_KEY_MINUS;
241 case 46:
242 return HID_KEY_DOT;
243 case 47:
244 return HID_KEY_SLASH;
245 default:
246 return -1;
247 }
248 } else if (ascii < 58) {
249 /* Numbers */
250 if (ascii == 48U) {
251 return HID_KEY_0;
252 } else {
253 return ascii - 19;
254 }
255 } else if (ascii < 65) {
256 /* Special characters #2 */
257 switch (ascii) {
258 case 58:
259 return HID_KEY_SEMICOLON;
260 case 59:
261 return HID_KEY_SEMICOLON;
262 case 60:
263 return HID_KEY_COMMA;
264 case 61:
265 return HID_KEY_EQUAL;
266 case 62:
267 return HID_KEY_DOT;
268 case 63:
269 return HID_KEY_SLASH;
270 case 64:
271 return HID_KEY_2;
272 default:
273 return -1;
274 }
275 } else if (ascii < 91) {
276 /* Uppercase characters */
277 return ascii - 61U;
278 } else if (ascii < 97) {
279 /* Special characters #3 */
280 switch (ascii) {
281 case 91:
282 return HID_KEY_LEFTBRACE;
283 case 92:
284 return HID_KEY_BACKSLASH;
285 case 93:
286 return HID_KEY_RIGHTBRACE;
287 case 94:
288 return HID_KEY_6;
289 case 95:
290 return HID_KEY_MINUS;
291 case 96:
292 return HID_KEY_GRAVE;
293 default:
294 return -1;
295 }
296 } else if (ascii < 123) {
297 /* Lowercase letters */
298 return ascii - 93;
299 } else if (ascii < 128) {
300 /* Special characters #4 */
301 switch (ascii) {
302 case 123:
303 return HID_KEY_LEFTBRACE;
304 case 124:
305 return HID_KEY_BACKSLASH;
306 case 125:
307 return HID_KEY_RIGHTBRACE;
308 case 126:
309 return HID_KEY_GRAVE;
310 case 127:
311 return HID_KEY_DELETE;
312 default:
313 return -1;
314 }
315 }
316
317 return -1;
318 }
319
needs_shift(uint8_t ascii)320 static bool needs_shift(uint8_t ascii)
321 {
322 if ((ascii < 33) || (ascii == 39U)) {
323 return false;
324 } else if ((ascii >= 33U) && (ascii < 44)) {
325 return true;
326 } else if ((ascii >= 44U) && (ascii < 58)) {
327 return false;
328 } else if ((ascii == 59U) || (ascii == 61U)) {
329 return false;
330 } else if ((ascii >= 58U) && (ascii < 91)) {
331 return true;
332 } else if ((ascii >= 91U) && (ascii < 94)) {
333 return false;
334 } else if ((ascii == 94U) || (ascii == 95U)) {
335 return true;
336 } else if ((ascii > 95) && (ascii < 123)) {
337 return false;
338 } else if ((ascii > 122) && (ascii < 127)) {
339 return true;
340 } else {
341 return false;
342 }
343 }
344
345 /* CDC ACM */
346
347 static volatile bool data_transmitted;
348 static volatile bool data_arrived;
349
flush_buffer_mouse(void)350 static void flush_buffer_mouse(void)
351 {
352 chr_ptr_mouse = 0U;
353 memset(data_buf_mouse, 0, sizeof(data_buf_mouse));
354 }
355
flush_buffer_kbd(void)356 static void flush_buffer_kbd(void)
357 {
358 chr_ptr_kbd = 0U;
359 memset(data_buf_kbd, 0, sizeof(data_buf_kbd));
360 }
361
write_data(const struct device * dev,const char * buf,int len)362 static void write_data(const struct device *dev, const char *buf, int len)
363 {
364 uart_irq_tx_enable(dev);
365
366 while (len) {
367 int written;
368
369 data_transmitted = false;
370 written = uart_fifo_fill(dev, (const uint8_t *)buf, len);
371 while (data_transmitted == false) {
372 k_yield();
373 }
374
375 len -= written;
376 buf += written;
377 }
378
379 uart_irq_tx_disable(dev);
380 }
381
cdc_mouse_int_handler(const struct device * dev,void * user_data)382 static void cdc_mouse_int_handler(const struct device *dev, void *user_data)
383 {
384 ARG_UNUSED(user_data);
385
386 uart_irq_update(dev);
387
388 if (uart_irq_tx_ready(dev)) {
389 data_transmitted = true;
390 }
391
392 if (!uart_irq_rx_ready(dev)) {
393 return;
394 }
395 uint32_t bytes_read;
396
397 while ((bytes_read = uart_fifo_read(dev,
398 (uint8_t *)data_buf_mouse+chr_ptr_mouse,
399 sizeof(data_buf_mouse)-chr_ptr_mouse))) {
400 chr_ptr_mouse += bytes_read;
401 if (data_buf_mouse[chr_ptr_mouse - 1] == '\r') {
402 /* ENTER */
403 struct app_evt_t *ev = app_evt_alloc();
404
405 data_buf_mouse[chr_ptr_mouse - 1] = '\0';
406
407 if (!strcmp(data_buf_mouse, "up")) {
408 ev->event_type = CDC_UP;
409 } else if (!strcmp(data_buf_mouse, "down")) {
410 ev->event_type = CDC_DOWN;
411 } else if (!strcmp(data_buf_mouse, "right")) {
412 ev->event_type = CDC_RIGHT;
413 } else if (!strcmp(data_buf_mouse, "left")) {
414 ev->event_type = CDC_LEFT;
415 } else {
416 ev->event_type = CDC_UNKNOWN;
417 }
418 flush_buffer_mouse();
419 app_evt_put(ev);
420 k_sem_give(&evt_sem);
421 }
422
423 if (chr_ptr_mouse >= sizeof(data_buf_mouse)) {
424 LOG_WRN("Buffer overflow");
425 flush_buffer_mouse();
426 }
427 }
428 }
429
cdc_kbd_int_handler(const struct device * dev,void * user_data)430 static void cdc_kbd_int_handler(const struct device *dev, void *user_data)
431 {
432 ARG_UNUSED(user_data);
433
434 uart_irq_update(dev);
435
436 if (uart_irq_tx_ready(dev)) {
437 data_transmitted = true;
438 }
439
440 if (!uart_irq_rx_ready(dev)) {
441 return;
442 }
443 uint32_t bytes_read;
444
445 while ((bytes_read = uart_fifo_read(dev,
446 (uint8_t *)data_buf_kbd+chr_ptr_kbd,
447 sizeof(data_buf_kbd)-chr_ptr_kbd))) {
448 chr_ptr_kbd += bytes_read;
449 if (data_buf_kbd[chr_ptr_kbd - 1] == '\r') {
450 /* ENTER */
451 struct app_evt_t *ev = app_evt_alloc();
452
453 data_buf_kbd[chr_ptr_kbd - 1] = '\0';
454 strcpy(string, data_buf_kbd);
455 ev->event_type = CDC_STRING;
456 flush_buffer_kbd();
457 app_evt_put(ev);
458 k_sem_give(&evt_sem);
459 }
460 }
461 }
462
463 /* Devices */
464
btn0(const struct device * gpio,struct gpio_callback * cb,uint32_t pins)465 static void btn0(const struct device *gpio, struct gpio_callback *cb,
466 uint32_t pins)
467 {
468 struct app_evt_t *ev = app_evt_alloc();
469
470 ev->event_type = GPIO_BUTTON_0,
471 app_evt_put(ev);
472 k_sem_give(&evt_sem);
473 }
474
475 #if DT_NODE_HAS_STATUS(SW1_NODE, okay)
btn1(const struct device * gpio,struct gpio_callback * cb,uint32_t pins)476 static void btn1(const struct device *gpio, struct gpio_callback *cb,
477 uint32_t pins)
478 {
479 struct app_evt_t *ev = app_evt_alloc();
480
481 ev->event_type = GPIO_BUTTON_1,
482 app_evt_put(ev);
483 k_sem_give(&evt_sem);
484 }
485 #endif
486
487 #if DT_NODE_HAS_STATUS(SW2_NODE, okay)
btn2(const struct device * gpio,struct gpio_callback * cb,uint32_t pins)488 static void btn2(const struct device *gpio, struct gpio_callback *cb,
489 uint32_t pins)
490 {
491 struct app_evt_t *ev = app_evt_alloc();
492
493 ev->event_type = GPIO_BUTTON_2,
494 app_evt_put(ev);
495 k_sem_give(&evt_sem);
496 }
497 #endif
498
499 #if DT_NODE_HAS_STATUS(SW3_NODE, okay)
btn3(const struct device * gpio,struct gpio_callback * cb,uint32_t pins)500 static void btn3(const struct device *gpio, struct gpio_callback *cb,
501 uint32_t pins)
502 {
503 struct app_evt_t *ev = app_evt_alloc();
504
505 ev->event_type = GPIO_BUTTON_3,
506 app_evt_put(ev);
507 k_sem_give(&evt_sem);
508 }
509 #endif
510
callbacks_configure(const struct gpio_dt_spec * gpio,void (* handler)(const struct device *,struct gpio_callback *,uint32_t),struct gpio_callback * callback)511 int callbacks_configure(const struct gpio_dt_spec *gpio,
512 void (*handler)(const struct device *, struct gpio_callback*,
513 uint32_t),
514 struct gpio_callback *callback)
515 {
516 if (!device_is_ready(gpio->port)) {
517 LOG_ERR("%s: device not ready.", gpio->port->name);
518 return -ENODEV;
519 }
520
521 gpio_pin_configure_dt(gpio, GPIO_INPUT);
522
523 gpio_init_callback(callback, handler, BIT(gpio->pin));
524 gpio_add_callback(gpio->port, callback);
525 gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_TO_ACTIVE);
526
527 return 0;
528 }
529
status_cb(enum usb_dc_status_code status,const uint8_t * param)530 static void status_cb(enum usb_dc_status_code status, const uint8_t *param)
531 {
532 LOG_INF("Status %d", status);
533 }
534
535 #define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
536
main(void)537 int main(void)
538 {
539 const struct device *cdc_dev[] = {
540 DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)
541 };
542 BUILD_ASSERT(ARRAY_SIZE(cdc_dev) >= 2, "Not enough CDC ACM instances");
543 const struct device *hid0_dev, *hid1_dev;
544 struct app_evt_t *ev;
545 uint32_t dtr = 0U;
546 int ret;
547
548 /* Configure devices */
549
550 hid0_dev = device_get_binding("HID_0");
551 if (hid0_dev == NULL) {
552 LOG_ERR("Cannot get USB HID 0 Device");
553 return 0;
554 }
555
556 hid1_dev = device_get_binding("HID_1");
557 if (hid1_dev == NULL) {
558 LOG_ERR("Cannot get USB HID 1 Device");
559 return 0;
560 }
561
562 for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) {
563 if (!device_is_ready(cdc_dev[idx])) {
564 LOG_ERR("CDC ACM device %s is not ready",
565 cdc_dev[idx]->name);
566 return 0;
567 }
568 }
569
570 if (callbacks_configure(&sw0_gpio, &btn0, &callback[0])) {
571 LOG_ERR("Failed configuring button 0 callback.");
572 return 0;
573 }
574
575 #if DT_NODE_HAS_STATUS(SW1_NODE, okay)
576 if (callbacks_configure(&sw1_gpio, &btn1, &callback[1])) {
577 LOG_ERR("Failed configuring button 1 callback.");
578 return 0;
579 }
580 #endif
581
582 #if DT_NODE_HAS_STATUS(SW2_NODE, okay)
583 if (callbacks_configure(&sw2_gpio, &btn2, &callback[2])) {
584 LOG_ERR("Failed configuring button 2 callback.");
585 return 0;
586 }
587 #endif
588
589 #if DT_NODE_HAS_STATUS(SW3_NODE, okay)
590 if (callbacks_configure(&sw3_gpio, &btn3, &callback[3])) {
591 LOG_ERR("Failed configuring button 3 callback.");
592 return 0;
593 }
594 #endif
595
596 /* Initialize HID */
597
598 usb_hid_register_device(hid0_dev, hid_mouse_report_desc,
599 sizeof(hid_mouse_report_desc), &ops);
600
601 usb_hid_register_device(hid1_dev, hid_kbd_report_desc,
602 sizeof(hid_kbd_report_desc), &ops);
603
604 usb_hid_init(hid0_dev);
605 usb_hid_init(hid1_dev);
606
607 ret = usb_enable(status_cb);
608 if (ret != 0) {
609 LOG_ERR("Failed to enable USB");
610 return 0;
611 }
612
613 /* Initialize CDC ACM */
614 for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) {
615 LOG_INF("Wait for DTR on %s", cdc_dev[idx]->name);
616 while (1) {
617 uart_line_ctrl_get(cdc_dev[idx],
618 UART_LINE_CTRL_DTR,
619 &dtr);
620 if (dtr) {
621 break;
622 } else {
623 /* Give CPU resources to low priority threads. */
624 k_sleep(K_MSEC(100));
625 }
626 }
627
628 LOG_INF("DTR on device %s", cdc_dev[idx]->name);
629 }
630
631 /* Wait 1 sec for the host to do all settings */
632 k_busy_wait(USEC_PER_SEC);
633
634 uart_irq_callback_set(cdc_dev[0], cdc_mouse_int_handler);
635 uart_irq_callback_set(cdc_dev[1], cdc_kbd_int_handler);
636
637 write_data(cdc_dev[0], welcome, strlen(welcome));
638 write_data(cdc_dev[0], cdc_dev[0]->name, strlen(cdc_dev[0]->name));
639 write_data(cdc_dev[0], banner0, strlen(banner0));
640 write_data(cdc_dev[1], welcome, strlen(welcome));
641 write_data(cdc_dev[1], cdc_dev[1]->name, strlen(cdc_dev[1]->name));
642 write_data(cdc_dev[1], banner1, strlen(banner1));
643
644 uart_irq_rx_enable(cdc_dev[0]);
645 uart_irq_rx_enable(cdc_dev[1]);
646
647 while (true) {
648 k_sem_take(&evt_sem, K_FOREVER);
649
650 while ((ev = app_evt_get()) != NULL) {
651 switch (ev->event_type) {
652 case GPIO_BUTTON_0:
653 {
654 /* Move the mouse in random direction */
655 uint8_t rep[] = {0x00, sys_rand32_get(),
656 sys_rand32_get(), 0x00};
657
658 k_sem_take(&usb_sem, K_FOREVER);
659 hid_int_ep_write(hid0_dev, rep,
660 sizeof(rep), NULL);
661 write_data(cdc_dev[0], gpio0, strlen(gpio0));
662 clear_mouse_report();
663 break;
664 }
665 case GPIO_BUTTON_1:
666 {
667 /* Press left mouse button */
668 uint8_t rep[] = {0x00, 0x00, 0x00, 0x00};
669
670 rep[MOUSE_BTN_REPORT_POS] |= MOUSE_BTN_LEFT;
671 k_sem_take(&usb_sem, K_FOREVER);
672 hid_int_ep_write(hid0_dev, rep,
673 sizeof(rep), NULL);
674 write_data(cdc_dev[0], gpio1, strlen(gpio1));
675 clear_mouse_report();
676 break;
677 }
678 case GPIO_BUTTON_2:
679 {
680 /* Send string on HID keyboard */
681 write_data(cdc_dev[1], gpio2, strlen(gpio2));
682 if (strlen(string) > 0) {
683 struct app_evt_t *ev = app_evt_alloc();
684
685 ev->event_type = HID_KBD_STRING,
686 app_evt_put(ev);
687 str_pointer = 0U;
688 k_sem_give(&evt_sem);
689 }
690 break;
691 }
692 case GPIO_BUTTON_3:
693 {
694 /* Toggle CAPS LOCK */
695 uint8_t rep[] = {0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00,
697 HID_KEY_CAPSLOCK};
698
699 k_sem_take(&usb_sem, K_FOREVER);
700 hid_int_ep_write(hid1_dev, rep,
701 sizeof(rep), NULL);
702 write_data(cdc_dev[1], gpio3, strlen(gpio3));
703 clear_kbd_report();
704 break;
705 }
706 case CDC_UP:
707 {
708 /* Mouse up */
709 uint8_t rep[] = {0x00, 0x00, 0xE0, 0x00};
710
711 k_sem_take(&usb_sem, K_FOREVER);
712 hid_int_ep_write(hid0_dev, rep,
713 sizeof(rep), NULL);
714 write_data(cdc_dev[0], up, strlen(up));
715 clear_mouse_report();
716 break;
717 }
718 case CDC_DOWN:
719 {
720 /* Mouse down */
721 uint8_t rep[] = {0x00, 0x00, 0x20, 0x00};
722
723 k_sem_take(&usb_sem, K_FOREVER);
724 hid_int_ep_write(hid0_dev, rep,
725 sizeof(rep), NULL);
726 write_data(cdc_dev[0], down, strlen(down));
727 clear_mouse_report();
728 break;
729 }
730 case CDC_RIGHT:
731 {
732 /* Mouse right */
733 uint8_t rep[] = {0x00, 0x20, 0x00, 0x00};
734
735 k_sem_take(&usb_sem, K_FOREVER);
736 hid_int_ep_write(hid0_dev, rep,
737 sizeof(rep), NULL);
738 write_data(cdc_dev[0], right, strlen(right));
739 clear_mouse_report();
740 break;
741 }
742 case CDC_LEFT:
743 {
744 /* Mouse left */
745 uint8_t rep[] = {0x00, 0xE0, 0x00, 0x00};
746
747 k_sem_take(&usb_sem, K_FOREVER);
748 hid_int_ep_write(hid0_dev, rep,
749 sizeof(rep), NULL);
750 write_data(cdc_dev[0], left, strlen(left));
751 clear_mouse_report();
752 break;
753 }
754 case CDC_UNKNOWN:
755 {
756 write_data(cdc_dev[0], unknown, strlen(unknown));
757 write_data(cdc_dev[1], unknown, strlen(unknown));
758 break;
759 }
760 case CDC_STRING:
761 {
762 write_data(cdc_dev[0], set_str, strlen(set_str));
763 write_data(cdc_dev[0], string, strlen(string));
764 write_data(cdc_dev[0], endl, strlen(endl));
765
766 write_data(cdc_dev[1], set_str, strlen(set_str));
767 write_data(cdc_dev[1], string, strlen(string));
768 write_data(cdc_dev[1], endl, strlen(endl));
769 break;
770 }
771 case HID_MOUSE_CLEAR:
772 {
773 /* Clear mouse report */
774 uint8_t rep[] = {0x00, 0x00, 0x00, 0x00};
775
776 k_sem_take(&usb_sem, K_FOREVER);
777 hid_int_ep_write(hid0_dev, rep,
778 sizeof(rep), NULL);
779 break;
780 }
781 case HID_KBD_CLEAR:
782 {
783 /* Clear kbd report */
784 uint8_t rep[] = {0x00, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00};
786
787 k_sem_take(&usb_sem, K_FOREVER);
788 hid_int_ep_write(hid1_dev, rep,
789 sizeof(rep), NULL);
790 break;
791 }
792 case HID_KBD_STRING:
793 {
794 int ch = ascii_to_hid(string[str_pointer]);
795
796 if (ch == -1) {
797 LOG_WRN("Unsupported character: %d",
798 string[str_pointer]);
799 } else {
800 uint8_t rep[] = {0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00};
802 if (needs_shift(string[str_pointer])) {
803 rep[0] |=
804 HID_KBD_MODIFIER_RIGHT_SHIFT;
805 }
806 rep[7] = ch;
807
808 k_sem_take(&usb_sem, K_FOREVER);
809 hid_int_ep_write(hid1_dev, rep,
810 sizeof(rep), NULL);
811 }
812
813 str_pointer++;
814
815 if (strlen(string) > str_pointer) {
816 struct app_evt_t *ev = app_evt_alloc();
817
818 ev->event_type = HID_KBD_STRING,
819 app_evt_put(ev);
820 k_sem_give(&evt_sem);
821 } else if (strlen(string) == str_pointer) {
822 clear_kbd_report();
823 }
824
825 break;
826 }
827 default:
828 {
829 LOG_ERR("Unknown event to execute");
830 write_data(cdc_dev[0], evt_fail,
831 strlen(evt_fail));
832 write_data(cdc_dev[1], evt_fail,
833 strlen(evt_fail));
834 break;
835 }
836 break;
837 }
838 app_evt_free(ev);
839 }
840 }
841 }
842