From cdc113285ad75705d6084db755fe216e7f393ecd Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 17 Apr 2026 11:20:57 -0700 Subject: [PATCH] Remove USB/serial support: network-only protocol, drop tinyusb and PICOBOOT --- cmd/picomap/main.go | 55 +---------------------- firmware/CMakeLists.txt | 3 +- firmware/firmware.cpp | 1 - firmware/include/handlers.h | 1 - firmware/include/tusb_config.h | 7 --- firmware/include/usb_cdc.h | 32 ------------- firmware/include/wire.h | 12 ----- firmware/lib/dispatch.cpp | 44 ------------------ firmware/lib/handlers.cpp | 5 --- firmware/lib/tusb_config.cpp | 82 ---------------------------------- firmware/test.cpp | 1 - go.mod | 7 +-- go.sum | 12 ----- lib/client/client.go | 5 --- lib/client/serial.go | 75 ------------------------------- lib/client/types.go | 5 --- 16 files changed, 4 insertions(+), 343 deletions(-) delete mode 100644 firmware/include/tusb_config.h delete mode 100644 firmware/include/usb_cdc.h delete mode 100644 firmware/lib/tusb_config.cpp delete mode 100644 lib/client/serial.go diff --git a/cmd/picomap/main.go b/cmd/picomap/main.go index 615466b..3c4bde6 100644 --- a/cmd/picomap/main.go +++ b/cmd/picomap/main.go @@ -23,14 +23,12 @@ type target struct { } type targetFlags struct { - usb string udp string iface string } func addTargetFlags(fs *flag.FlagSet) *targetFlags { tf := &targetFlags{} - fs.StringVar(&tf.usb, "usb", "", "comma-separated USB serial devices") fs.StringVar(&tf.udp, "udp", "", "comma-separated UDP IP addresses") fs.StringVar(&tf.iface, "iface", "", "network interface for multicast discovery") return tf @@ -39,17 +37,6 @@ func addTargetFlags(fs *flag.FlagSet) *targetFlags { func (tf *targetFlags) connect(timeout time.Duration) ([]target, error) { var targets []target - if tf.usb != "" { - for _, dev := range strings.Split(tf.usb, ",") { - dev = strings.TrimSpace(dev) - c, err := client.NewSerial(dev, timeout) - if err != nil { - return nil, fmt.Errorf("usb %s: %w", dev, err) - } - targets = append(targets, target{dev, c}) - } - } - if tf.udp != "" { for _, addr := range strings.Split(tf.udp, ",") { addr = strings.TrimSpace(addr) @@ -84,21 +71,6 @@ func (tf *targetFlags) connect(timeout time.Duration) ([]target, error) { } } - if tf.usb == "" && tf.udp == "" && tf.iface == "" { - devs, err := client.ListSerial() - if err != nil { - return nil, err - } - for _, dev := range devs { - c, err := client.NewSerial(dev, timeout) - if err != nil { - slog.Warn("connect error", "dev", dev, "err", err) - continue - } - targets = append(targets, target{dev, c}) - } - } - if len(targets) == 0 { return nil, fmt.Errorf("no devices found") } @@ -113,7 +85,7 @@ func closeTargets(targets []target) { func main() { if len(os.Args) < 2 { - fmt.Fprintf(os.Stderr, "usage: picomap [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n picoboot\n test\n") + fmt.Fprintf(os.Stderr, "usage: picomap [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n test\n") os.Exit(1) } cmd := os.Args[1] @@ -131,12 +103,10 @@ func main() { err = cmdLog(args) case "reboot": err = cmdReboot(args) - case "picoboot": - err = cmdPICOBOOT(args) case "test": err = cmdTestGroup(args) default: - fmt.Fprintf(os.Stderr, "usage: picomap [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n picoboot\n test\n") + fmt.Fprintf(os.Stderr, "usage: picomap [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n test\n") os.Exit(1) } if err != nil { @@ -253,27 +223,6 @@ func cmdReboot(args []string) error { return nil } -func cmdPICOBOOT(args []string) error { - fs := flag.NewFlagSet("picoboot", flag.ExitOnError) - tf := addTargetFlags(fs) - fs.Parse(args) - - targets, err := tf.connect(500 * time.Millisecond) - if err != nil { - return err - } - defer closeTargets(targets) - - for _, t := range targets { - if err := t.client.PICOBOOT(); err != nil { - slog.Error("picoboot error", "via", t.name, "err", err) - continue - } - slog.Info("picoboot", "via", t.name) - } - return nil -} - func boardSerial(id [8]byte) string { return fmt.Sprintf("%02X%02X%02X%02X%02X%02X%02X%02X", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]) diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index ca00014..6ed2e0f 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -18,11 +18,10 @@ set(LIB_SOURCES lib/igmp.cpp lib/ipv4.cpp lib/net.cpp - lib/tusb_config.cpp w6300/w6300.cpp ) -set(LIB_DEPS pico_stdlib pico_sha256 tinyusb_device tinyusb_board hardware_pio hardware_spi hardware_dma hardware_clocks) +set(LIB_DEPS pico_stdlib pico_sha256 pico_unique_id hardware_pio hardware_spi hardware_dma hardware_clocks) add_executable(picomap firmware.cpp ${LIB_SOURCES}) target_include_directories(picomap PRIVATE include w6300) diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index 8626bce..f8441c1 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -4,7 +4,6 @@ std::string_view firmware_name = "picomap"; static constexpr handler_entry handlers[] = { - {RequestPICOBOOT::ext_id, typed_handler}, {RequestInfo::ext_id, typed_handler}, {RequestLog::ext_id, typed_handler}, {RequestFlashErase::ext_id, typed_handler}, diff --git a/firmware/include/handlers.h b/firmware/include/handlers.h index 949d11c..7e0082d 100644 --- a/firmware/include/handlers.h +++ b/firmware/include/handlers.h @@ -8,7 +8,6 @@ extern std::string_view firmware_name; void handlers_init(); void handlers_start(); -std::optional handle_picoboot(const responder& resp, const RequestPICOBOOT&); std::optional handle_info(const responder& resp, const RequestInfo&); std::optional handle_log(const responder& resp, const RequestLog&); std::optional handle_flash_erase(const responder& resp, const RequestFlashErase&); diff --git a/firmware/include/tusb_config.h b/firmware/include/tusb_config.h deleted file mode 100644 index f2d0b6d..0000000 --- a/firmware/include/tusb_config.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE -#define CFG_TUD_CDC 1 -#define CFG_TUD_CDC_RX_BUFSIZE 256 -#define CFG_TUD_CDC_TX_BUFSIZE 256 -#define CFG_TUD_CDC_EP_BUFSIZE 64 diff --git a/firmware/include/usb_cdc.h b/firmware/include/usb_cdc.h deleted file mode 100644 index bf75333..0000000 --- a/firmware/include/usb_cdc.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include -#include -#include -#include "tusb.h" -#include "ring_buffer.h" - -struct usb_cdc { - ring_buffer tx; - - bool send(std::span data) { - if (!tx.push(data)) return false; - drain(); - return true; - } - - void send(const std::vector& data) { - send(std::span{data}); - } - - void drain() { - while (!tx.empty()) { - uint32_t avail = tud_cdc_write_available(); - if (avail == 0) break; - auto chunk = tx.read_contiguous(); - if (chunk.size() > avail) chunk = chunk.first(avail); - tud_cdc_write(chunk.data(), chunk.size()); - tx.consume(chunk.size()); - } - tud_cdc_write_flush(); - } -}; diff --git a/firmware/include/wire.h b/firmware/include/wire.h index e8b5503..b0199b9 100644 --- a/firmware/include/wire.h +++ b/firmware/include/wire.h @@ -27,18 +27,6 @@ struct DeviceError { auto as_tuple() { return std::tie(code, message); } }; -struct RequestPICOBOOT { - static constexpr int8_t ext_id = 2; - auto as_tuple() const { return std::tie(); } - auto as_tuple() { return std::tie(); } -}; - -struct ResponsePICOBOOT { - static constexpr int8_t ext_id = 3; - auto as_tuple() const { return std::tie(); } - auto as_tuple() { return std::tie(); } -}; - struct RequestInfo { static constexpr int8_t ext_id = 4; auto as_tuple() const { return std::tie(); } diff --git a/firmware/lib/dispatch.cpp b/firmware/lib/dispatch.cpp index 26798bd..ae00e52 100644 --- a/firmware/lib/dispatch.cpp +++ b/firmware/lib/dispatch.cpp @@ -1,9 +1,7 @@ #include "dispatch.h" #include #include "pico/stdlib.h" -#include "tusb.h" #include "wire.h" -#include "usb_cdc.h" #include "timer_queue.h" #include "net.h" #include "igmp.h" @@ -19,7 +17,6 @@ static void igmp_reannounce() { } void dispatch_init() { - tusb_init(); net_init(); dispatch_schedule_ms(60000, igmp_reannounce); dlog("dispatch_init complete"); @@ -41,8 +38,6 @@ bool dispatch_cancel_timer(timer_handle h) { handler_map[entry.type_id] = entry.handle; } - static usb_cdc usb; - static static_vector usb_rx_buf; static std::array tx_buf; auto dispatch_msg = [&](const DecodedMessage& msg, send_fn send) { @@ -65,48 +60,9 @@ bool dispatch_cancel_timer(timer_handle h) { while (true) { uint32_t save = save_and_disable_interrupts(); - dlog_if_slow("tud_task", 1000, [&]{ tud_task(); }); - dlog_if_slow("drain", 1000, [&]{ usb.drain(); }); dlog_if_slow("timers", 1000, [&]{ timers.run(); }); dlog_if_slow("net_poll", 1000, [&]{ net_poll(std::span{tx_buf}); }); - while (tud_cdc_available()) { - uint8_t byte; - if (tud_cdc_read(&byte, 1) != 1) break; - - usb_rx_buf.push_back(byte); - - auto msg = try_decode(usb_rx_buf); - if (!msg) { - if (usb_rx_buf.full()) usb_rx_buf.clear(); - continue; - } - - dispatch_msg(*msg, [&](encode_fn encode) { - uint8_t buf[4096]; - span_writer out(buf, sizeof(buf)); - auto r = encode(out); - if (!r) return; - std::span data{buf, *r}; - if (data.size() <= usb.tx.free()) { - if (!usb.send(data)) - dlogf("usb send failed: %zu bytes, %u free", data.size(), usb.tx.free()); - } else { - dlogf("usb response too large: %zu bytes, %u free", data.size(), usb.tx.free()); - uint8_t err_buf[256]; - span_writer err_out(err_buf, sizeof(err_buf)); - auto err = encode_response_into(err_out, msg->message_id, - [&]{ - char m[48]; - snprintf(m, sizeof(m), "response too large: %zu", data.size()); - return DeviceError{2, m}; - }()); - if (err) usb.send(std::span{err_buf, *err}); - } - }); - usb_rx_buf.clear(); - } - __wfi(); restore_interrupts(save); } diff --git a/firmware/lib/handlers.cpp b/firmware/lib/handlers.cpp index 97e524e..c1b9b84 100644 --- a/firmware/lib/handlers.cpp +++ b/firmware/lib/handlers.cpp @@ -29,11 +29,6 @@ void handlers_start() { poke_watchdog(); } -std::optional handle_picoboot(const responder&, const RequestPICOBOOT&) { - dispatch_schedule_ms(100, []{ reset_usb_boot(0, 1); }); - return ResponsePICOBOOT{}; -} - std::optional handle_info(const responder&, const RequestInfo&) { ResponseInfo resp; pico_unique_board_id_t uid; diff --git a/firmware/lib/tusb_config.cpp b/firmware/lib/tusb_config.cpp deleted file mode 100644 index 6cf1c64..0000000 --- a/firmware/lib/tusb_config.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include "pico/unique_id.h" -#include "tusb.h" - -constexpr uint16_t USB_VID = 0x2E8A; -constexpr uint16_t USB_PID = 0x000A; - -static constexpr tusb_desc_device_t desc_device = { - sizeof(tusb_desc_device_t), - TUSB_DESC_DEVICE, - 0x0200, - TUSB_CLASS_MISC, - MISC_SUBCLASS_COMMON, - MISC_PROTOCOL_IAD, - CFG_TUD_ENDPOINT0_SIZE, - USB_VID, - USB_PID, - 0x0100, - 1, 2, 3, - 1, -}; - -enum { ITF_NUM_CDC, ITF_NUM_CDC_DATA, ITF_NUM_TOTAL }; - -constexpr uint8_t EPNUM_CDC_NOTIF = 0x81; -constexpr uint8_t EPNUM_CDC_OUT = 0x02; -constexpr uint8_t EPNUM_CDC_IN = 0x82; -constexpr uint16_t CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN; - -static uint8_t const desc_configuration[] = { - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 0, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), -}; - -static constexpr const char* string_desc[] = { - "\x09\x04", - "picomap", - "picomap", - nullptr, -}; - -static uint16_t desc_str_buf[33]; - -extern "C" { - -uint8_t const* tud_descriptor_device_cb(void) { - return reinterpret_cast(&desc_device); -} - -uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { - return desc_configuration; -} - -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - uint8_t chr_count; - - if (index == 0) { - memcpy(&desc_str_buf[1], string_desc[0], 2); - chr_count = 1; - } else if (index == 3) { - pico_unique_board_id_t uid; - pico_get_unique_board_id(&uid); - chr_count = 0; - for (int i = 0; i < 8; i++) { - desc_str_buf[1 + chr_count++] = "0123456789ABCDEF"[uid.id[i] >> 4]; - desc_str_buf[1 + chr_count++] = "0123456789ABCDEF"[uid.id[i] & 0xF]; - } - } else { - if (index >= sizeof(string_desc) / sizeof(string_desc[0])) return nullptr; - const char* str = string_desc[index]; - if (!str) return nullptr; - chr_count = strlen(str); - if (chr_count > 31) chr_count = 31; - for (uint8_t i = 0; i < chr_count; i++) - desc_str_buf[1 + i] = str[i]; - } - - desc_str_buf[0] = static_cast((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); - return desc_str_buf; -} - -} // extern "C" diff --git a/firmware/test.cpp b/firmware/test.cpp index 990d299..92025a7 100644 --- a/firmware/test.cpp +++ b/firmware/test.cpp @@ -14,7 +14,6 @@ static void led_toggle() { std::string_view firmware_name = "picomap_test"; static constexpr handler_entry handlers[] = { - {RequestPICOBOOT::ext_id, typed_handler}, {RequestInfo::ext_id, typed_handler}, {RequestLog::ext_id, typed_handler}, {RequestFlashErase::ext_id, typed_handler}, diff --git a/go.mod b/go.mod index a29da21..53fa35f 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,4 @@ module github.com/theater/picomap go 1.25.0 -require go.bug.st/serial v1.6.4 - -require ( - github.com/creack/goselect v0.1.2 // indirect - golang.org/x/sys v0.19.0 // indirect -) +require golang.org/x/sys v0.19.0 diff --git a/go.sum b/go.sum index df37244..e354f1e 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,2 @@ -github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= -github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A= -go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/client/client.go b/lib/client/client.go index efe8676..416eeba 100644 --- a/lib/client/client.go +++ b/lib/client/client.go @@ -100,11 +100,6 @@ func first[T any](results []Response[T], err error) (*T, error) { return results[0].Value, nil } -func (c *Client) PICOBOOT() error { - _, err := first(roundTrip[ResponsePICOBOOT](c, &RequestPICOBOOT{})) - return err -} - func (c *Client) Info() (*ResponseInfo, error) { return first(roundTrip[ResponseInfo](c, &RequestInfo{})) } diff --git a/lib/client/serial.go b/lib/client/serial.go deleted file mode 100644 index 3512cf3..0000000 --- a/lib/client/serial.go +++ /dev/null @@ -1,75 +0,0 @@ -package client - -import ( - "fmt" - "slices" - "strings" - "time" - - "github.com/theater/picomap/lib/msgpack" - "go.bug.st/serial" - "go.bug.st/serial/enumerator" -) - -func ListSerial() ([]string, error) { - ports, err := enumerator.GetDetailedPortsList() - if err != nil { - return nil, fmt.Errorf("enumerating ports: %w", err) - } - type entry struct { - name string - serial string - } - var entries []entry - for _, p := range ports { - if p.IsUSB && p.VID == "2E8A" && strings.HasPrefix(p.Name, "/dev/cu.") { - entries = append(entries, entry{p.Name, p.SerialNumber}) - } - } - slices.SortFunc(entries, func(a, b entry) int { - return strings.Compare(a.serial, b.serial) - }) - var result []string - for _, e := range entries { - result = append(result, e.name) - } - return result, nil -} - -type serialTransport struct { - port serial.Port - portName string - dec *msgpack.Decoder -} - -func NewSerial(portName string, timeout time.Duration) (*Client, error) { - port, err := serial.Open(portName, &serial.Mode{BaudRate: 115200}) - if err != nil { - return nil, fmt.Errorf("opening %s: %w", portName, err) - } - t := &serialTransport{port: port, portName: portName, dec: msgpack.NewDecoder(port)} - return &Client{transport: t, timeout: timeout}, nil -} - -func (t *serialTransport) Send(data []byte) error { - _, err := t.port.Write(data) - return err -} - -func (t *serialTransport) SetReadTimeout(timeout time.Duration) { - t.port.SetReadTimeout(timeout) -} - -func (t *serialTransport) Recv() ([]byte, string, error) { - var raw msgpack.RawMessage - if err := t.dec.Decode(&raw); err != nil { - return nil, "", err - } - return []byte(raw), t.portName, nil -} - -func (t *serialTransport) Broadcast() bool { return false } - -func (t *serialTransport) Close() error { - return t.port.Close() -} diff --git a/lib/client/types.go b/lib/client/types.go index 0bdc69c..e0f2811 100644 --- a/lib/client/types.go +++ b/lib/client/types.go @@ -2,9 +2,6 @@ package client import "github.com/theater/picomap/lib/msgpack" -type RequestPICOBOOT struct{} -type ResponsePICOBOOT struct{} - type RequestInfo struct{} type BootReason uint8 @@ -108,8 +105,6 @@ type Envelope struct { func init() { msgpack.RegisterExt(0, (*Envelope)(nil)) msgpack.RegisterExt(1, (*DeviceError)(nil)) - msgpack.RegisterExt(2, (*RequestPICOBOOT)(nil)) - msgpack.RegisterExt(3, (*ResponsePICOBOOT)(nil)) msgpack.RegisterExt(4, (*RequestInfo)(nil)) msgpack.RegisterExt(5, (*ResponseInfo)(nil)) msgpack.RegisterExt(6, (*RequestLog)(nil))