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/random.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 gpio_callbacks[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, &gpio_callbacks[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, &gpio_callbacks[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, &gpio_callbacks[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, &gpio_callbacks[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 *ev2 = app_evt_alloc();
684 
685 					ev2->event_type = HID_KBD_STRING,
686 					app_evt_put(ev2);
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 *ev2 = app_evt_alloc();
817 
818 					ev2->event_type = HID_KBD_STRING,
819 					app_evt_put(ev2);
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