188 lines
5.7 KiB
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);
|
|
}
|