Files
ESP32_Serial_Swiss_Army_Knife/src/usb_console.c

188 lines
5.7 KiB
C

#include "usb_console.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "esp_console.h"
#include "esp_err.h"
#include "session_broker.h"
#include "usb_cdc_transport.h"
static const char *yes_no(bool value)
{
return value ? "yes" : "no";
}
static const char *stop_bits_name(uint8_t stop_bits)
{
switch (stop_bits) {
case USB_CDC_TRANSPORT_STOP_BITS_1:
return "1";
case USB_CDC_TRANSPORT_STOP_BITS_1_5:
return "1.5";
case USB_CDC_TRANSPORT_STOP_BITS_2:
return "2";
default:
return "unknown";
}
}
static const char *parity_name(uint8_t parity)
{
switch (parity) {
case USB_CDC_TRANSPORT_PARITY_NONE:
return "none";
case USB_CDC_TRANSPORT_PARITY_ODD:
return "odd";
case USB_CDC_TRANSPORT_PARITY_EVEN:
return "even";
case USB_CDC_TRANSPORT_PARITY_MARK:
return "mark";
case USB_CDC_TRANSPORT_PARITY_SPACE:
return "space";
default:
return "unknown";
}
}
static int show_status(void)
{
usb_cdc_transport_snapshot_t snapshot;
esp_err_t err = usb_cdc_transport_get_snapshot(&snapshot);
if (err != ESP_OK) {
printf("Could not read USB CDC status: %s\n", esp_err_to_name(err));
return 1;
}
bool host_open = snapshot.attached && snapshot.dtr;
printf("USB CDC: initialized=%s attached=%s host-open=%s DTR=%s RTS=%s\n",
yes_no(snapshot.initialized),
yes_no(snapshot.attached),
yes_no(host_open),
yes_no(snapshot.dtr),
yes_no(snapshot.rts));
if (snapshot.broker_client_id == SESSION_BROKER_NO_CLIENT) {
printf("Broker: disconnected\n");
} else {
printf("Broker: client=%" PRIu32 " role=%s\n",
snapshot.broker_client_id,
snapshot.writer ? "writer" : "observer");
}
printf("Last host line coding: baud=%" PRIu32 " data=%u parity=%s stop=%s\n",
snapshot.line_coding.baud_rate,
(unsigned int)snapshot.line_coding.data_bits,
parity_name(snapshot.line_coding.parity),
stop_bits_name(snapshot.line_coding.stop_bits));
printf("Host line coding is reported only; UART1 uses the serial configuration.\n");
return 0;
}
static int show_counters(void)
{
usb_cdc_transport_snapshot_t snapshot;
esp_err_t err = usb_cdc_transport_get_snapshot(&snapshot);
if (err != ESP_OK) {
printf("Could not read USB CDC counters: %s\n", esp_err_to_name(err));
return 1;
}
const usb_cdc_transport_counters_t *counter = &snapshot.counters;
printf("Host RX: received=%" PRIu64 " stream-dropped=%" PRIu64
" broker-accepted=%" PRIu64 " discarded=%" PRIu64 "\n",
counter->host_rx_bytes,
counter->host_rx_stream_dropped_bytes,
counter->broker_accepted_bytes,
counter->broker_rejected_bytes);
printf("Host TX: broker-read=%" PRIu64 " USB-queued=%" PRIu64
" local-dropped=%" PRIu64 "\n",
counter->broker_to_usb_bytes,
counter->usb_tx_queued_bytes,
counter->usb_tx_dropped_bytes);
printf("Sessions: connect=%" PRIu64 " disconnect=%" PRIu64
" grants=%" PRIu64 " denials=%" PRIu64
" revocations=%" PRIu64 " writer-events=%" PRIu64 "\n",
counter->connections,
counter->disconnections,
counter->writer_grants,
counter->writer_denials,
counter->writer_revocations,
counter->writer_events);
printf("Service start failures=%" PRIu64 "\n",
counter->service_start_failures);
printf("Control/callback drops: control=%" PRIu64 " callback=%" PRIu64 "\n",
counter->control_drops,
counter->callback_drops);
return 0;
}
static int queue_writer_request(bool request)
{
esp_err_t err = request ? usb_cdc_transport_request_writer()
: usb_cdc_transport_release_writer();
if (err != ESP_OK) {
printf("Could not queue USB writer %s: %s\n",
request ? "request" : "release",
esp_err_to_name(err));
return 1;
}
printf("USB writer %s queued; use 'usb status' to observe the result.\n",
request ? "request" : "release");
return 0;
}
static void print_usage(void)
{
printf("Usage:\n");
printf(" usb status\n");
printf(" usb counters|clear-counters\n");
printf(" usb request-writer|release-writer\n");
}
static int command_usb(int argc, char **argv)
{
if (argc == 1 || (argc == 2 && strcmp(argv[1], "help") == 0)) {
print_usage();
return 0;
}
if (argc == 2 && strcmp(argv[1], "status") == 0) {
return show_status();
}
if (argc == 2 && strcmp(argv[1], "counters") == 0) {
return show_counters();
}
if (argc == 2 && strcmp(argv[1], "clear-counters") == 0) {
esp_err_t err = usb_cdc_transport_clear_counters();
if (err != ESP_OK) {
printf("Could not clear USB CDC counters: %s\n", esp_err_to_name(err));
return 1;
}
printf("USB CDC counters cleared.\n");
return 0;
}
if (argc == 2 && strcmp(argv[1], "request-writer") == 0) {
return queue_writer_request(true);
}
if (argc == 2 && strcmp(argv[1], "release-writer") == 0) {
return queue_writer_request(false);
}
print_usage();
return 1;
}
esp_err_t usb_console_register_commands(void)
{
const esp_console_cmd_t command = {
.command = "usb",
.help = "Inspect native USB CDC and manage writer ownership; run 'usb' for subcommands",
.hint = NULL,
.func = &command_usb,
.argtable = NULL,
};
return esp_console_cmd_register(&command);
}