ether2ser 0.1.0
Ethernet <-> synchronous V.24 bridge firmware for RP2040 + W5500
Loading...
Searching...
No Matches
cli_usb_cdc.c
Go to the documentation of this file.
1/*
2 * ether2ser — Ethernet <-> synchronous V.24 (RS-232/V.28) bridge
3 *
4 * File: src/system/cli_usb_cdc.c
5 * Purpose: USB CDC CLI input handling and event dispatch.
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Copyright (c) 2026 Florian <f.leuze@outlook.de>
10 */
11
12// Related headers
13#include "cli_usb_cdc.h"
14
15// Standard library headers
16#include <stddef.h>
17#include <stdint.h>
18#include <stdio.h>
19#include <string.h>
20
21// Library Headers
22#include "pico/error.h"
23#include "pico/stdio.h"
24
25// Project Headers
26#include "system/common.h"
27#include "system/event_queue.h"
28
29// Generated headers
30
31// Heartbeat message interval in milliseconds
32#define CLI_BUFFER_SIZE 128
33#define CLI_EVENT_POOL_SIZE EVENT_QUEUE_CAPACITY
34#define ASCII_BACKSPACE 0x08
35#define ASCII_DELETE 0x7F
36#define ASCII_FIRST_PRINTABLE 32
37#define ASCII_LAST_PRINTABLE 126
38#define CLI_MAX_CHARS_PER_POLL 16U
39
40void cli_poll(void)
41{
42 static char line_buffer[CLI_BUFFER_SIZE];
43 static uint8_t buffer_len = 0;
44 static char cli_line_pool[CLI_EVENT_POOL_SIZE][CLI_BUFFER_SIZE];
45 static uint8_t cli_line_pool_write = 0;
46
47 int input_char;
48 uint32_t processed_chars = 0U;
49 while (processed_chars < CLI_MAX_CHARS_PER_POLL &&
50 (input_char = getchar_timeout_us(0)) != PICO_ERROR_TIMEOUT)
51 {
52 processed_chars++;
53
54 if (input_char == '\n' || input_char == '\r')
55 {
56 // add new line before processing command
57 LOG_PLAIN("\r\n");
58 line_buffer[buffer_len] = '\0';
59
60 char* line_slot = cli_line_pool[cli_line_pool_write];
61 int written = snprintf(line_slot, CLI_BUFFER_SIZE, "%s", line_buffer);
62 if (written < 0)
63 {
64 LOG_ERROR("Failed to format CLI line\r\n");
65 buffer_len = 0;
66 continue;
67 }
68 if (written >= CLI_BUFFER_SIZE)
69 {
70 LOG_ERROR("CLI line truncated (len=%d)\r\n", written);
71 buffer_len = 0;
72 continue;
73 }
74
75 event_t new_event = {
77 .data = {line_slot},
78 .data_len = strnlen(line_slot, CLI_BUFFER_SIZE) + 1,
79 };
80
81 if (event_queue_push(&new_event))
82 {
83 cli_line_pool_write = (uint8_t)((cli_line_pool_write + 1) % CLI_EVENT_POOL_SIZE);
84 }
85 else
86 {
87 LOG_ERROR("Event queue full, dropping line\r\n");
88 }
89
90 buffer_len = 0;
91 }
92 else if (input_char == ASCII_BACKSPACE || input_char == ASCII_DELETE)
93 { // backspace
94 LOG_PLAIN("\b \b");
95 if (buffer_len)
96 {
97 buffer_len--;
98 }
99 }
100 else if (input_char >= ASCII_FIRST_PRINTABLE && input_char <= ASCII_LAST_PRINTABLE)
101 {
102 if (buffer_len < sizeof(line_buffer) - 1)
103 {
104 // Echo character back and sore it in buffer
105 LOG_PLAIN("%c", (char)input_char);
106 line_buffer[buffer_len++] = (char)input_char;
107 }
108 }
109 else
110 {
111 LOG_DEBUG("[DEBUG] Ignoring char: 0x%02X\r\n", input_char);
112 }
113 }
114}
#define CLI_BUFFER_SIZE
Definition cli_usb_cdc.c:32
#define ASCII_LAST_PRINTABLE
Definition cli_usb_cdc.c:37
#define ASCII_DELETE
Definition cli_usb_cdc.c:35
#define ASCII_FIRST_PRINTABLE
Definition cli_usb_cdc.c:36
#define CLI_EVENT_POOL_SIZE
Definition cli_usb_cdc.c:33
void cli_poll(void)
Poll USB CDC for CLI input, echo, and emit line events.
Definition cli_usb_cdc.c:40
#define CLI_MAX_CHARS_PER_POLL
Definition cli_usb_cdc.c:38
#define ASCII_BACKSPACE
Definition cli_usb_cdc.c:34
#define LOG_DEBUG(...)
Definition common.h:165
#define LOG_PLAIN(...)
Definition common.h:162
#define LOG_ERROR(...)
Definition common.h:163
bool event_queue_push(const event_t *event_entry)
Enqueue an event.
Definition event_queue.c:49
@ EV_CLI_LINE
Definition event_queue.h:37
Event queue entry.
Definition event_queue.h:91
event_type_t type
Definition event_queue.h:93