{"id":49921155,"url":"https://github.com/ulso/pico-can-bridge","last_synced_at":"2026-05-16T20:03:15.406Z","repository":{"id":357645076,"uuid":"1237822974","full_name":"ulso/pico-can-bridge","owner":"ulso","description":"USB-C CAN bridge with a built-in web UI for desktop and mobile hosts","archived":false,"fork":false,"pushed_at":"2026-05-13T16:27:40.000Z","size":1712,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T18:24:49.152Z","etag":null,"topics":["can-bus","cdc-ncm","embedded","ipad","iphone","mcp2515","rp2040","usb","usb-c","websocket","zephyr"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ulso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-13T14:41:35.000Z","updated_at":"2026-05-13T16:27:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ulso/pico-can-bridge","commit_stats":null,"previous_names":["ulso/pico-can-bridge"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ulso/pico-can-bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulso%2Fpico-can-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulso%2Fpico-can-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulso%2Fpico-can-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulso%2Fpico-can-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ulso","download_url":"https://codeload.github.com/ulso/pico-can-bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulso%2Fpico-can-bridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33117350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T18:38:32.183Z","status":"ssl_error","status_checked_at":"2026-05-16T18:38:29.903Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["can-bus","cdc-ncm","embedded","ipad","iphone","mcp2515","rp2040","usb","usb-c","websocket","zephyr"],"created_at":"2026-05-16T20:03:12.157Z","updated_at":"2026-05-16T20:03:15.395Z","avatar_url":"https://github.com/ulso.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pico CAN Bridge\n\nFirmware for the [Adafruit Feather RP2040 CAN Bus board](https://www.adafruit.com/product/5724).\nThe board appears as a USB CDC-NCM network interface and exposes a small web UI\nplus a JSON WebSocket API for CAN traffic.\n\nCurrent features:\n\n- USB CDC-NCM using Zephyr's USB device stack next\n- IPv4 link-local addressing\n- mDNS hostname and DNS-SD HTTP service announcement\n- HTTP web UI served from the firmware\n- Optional user HTML page served from LittleFS at `/user`\n- WebSocket CAN bridge at `/can`\n- JSON CAN TX/RX/status/config protocol\n- MCP25625 CAN controller/transceiver in normal, loopback, or listen-only mode\n- Startup recovery for a macOS/RP2040 CDC-NCM alternate-setting race\n\n## Current status\n\nThis project is in early development. It is functional on the tested Apple\nUSB-C hosts, with known RP2040/Zephyr CDC-NCM startup quirks documented in\n[docs/known-issues.md](docs/known-issues.md). Additional host platforms will\nbe listed as they are tested.\n\nPrebuilt UF2 test builds are available from the\n[GitHub Releases page](https://github.com/ulso/pico-can-bridge/releases).\n\n## Hardware\n\nThe firmware targets the\n[Adafruit Feather RP2040 CAN Bus board](https://www.adafruit.com/product/5724).\nThe photo below shows a test setup with the Pico CAN Bridge board connected to\nanother CAN node, a battery, USB-C, and a serial debug adapter on the board's\nTX/RX pins.\n\n![Pico CAN Bridge test setup](docs/images/test-setup.png)\n\n## Screenshots\n\n### Desktop web UI\n\n![Pico CAN Bridge desktop web UI](docs/images/web-ui-desktop.png)\n\n### Uploaded user page\n\n![Pico CAN Bridge uploaded user LED control page](docs/images/user-led.png)\n\n### iPad\n\n![Pico CAN Bridge running on iPad](docs/images/web-ui-ipad.png)\n\n### iPhone\n\n![Pico CAN Bridge running on iPhone, status and transmit view](docs/images/web-ui-iphone1.png)\n\n![Pico CAN Bridge running on iPhone, filters and log view](docs/images/web-ui-iphone2.png)\n\n## Build\n\nRun the build from the Zephyr workspace so `west build` finds Zephyr's command extensions.\nReplace `\u003czephyr-workspace\u003e` and `\u003crepo\u003e` with your local paths:\n\n```sh\ncd \u003czephyr-workspace\u003e\n./venv/bin/west build --pristine \\\n  -b adafruit_feather_canbus_rp2040 \\\n  -d \u003crepo\u003e/build \\\n  \u003crepo\u003e\n```\n\nThe UF2 ends up at:\n\n```text\n\u003crepo\u003e/build/zephyr/zephyr.uf2\n```\n\n## USB CDC-NCM\n\nThe firmware uses IPv4 link-local autoconfiguration on the CDC-NCM interface.\nThe host should also use link-local addressing on the new USB network\ninterface.\n\nThe firmware uses Zephyr's sample USB VID/PID (`0x2FE3:0x0100`) and its own\nUSB product/manufacturer strings. This intentionally differs from the original\nAdafruit CircuitPython USB identity for the board (`0x239A:0x8130`).\n\nThis project currently carries a local Zephyr CDC-NCM patch for macOS\nalternate-setting handling:\n\n```text\npatches/zephyr-cdc-ncm-macos-altsetting.patch\n```\n\nApply it in the Zephyr workspace before building if the workspace has been\nupdated or reset. In particular, run this check after every `west update`,\nbecause updating Zephyr can replace the locally patched CDC-NCM source file.\n\n```sh\ncd \u003czephyr-workspace\u003e/zephyr-main\ngit apply --check \u003crepo\u003e/patches/zephyr-cdc-ncm-macos-altsetting.patch\ngit apply \u003crepo\u003e/patches/zephyr-cdc-ncm-macos-altsetting.patch\n```\n\nIf `git apply --check` reports that the patch is already applied, confirm that\n`subsys/usb/device_next/class/usbd_cdc_ncm.c` is locally modified before\nbuilding.\n\nThe board advertises:\n\n```text\nHostname: pico-can-bridge.local\nService:  _http._tcp.local\nPort:     80\n```\n\nAfter flashing, unplug and reconnect USB, then test:\n\n```sh\nping pico-can-bridge.local\ncurl http://pico-can-bridge.local/\ndns-sd -B _http._tcp local\ndns-sd -L pico-can-bridge _http._tcp local\n```\n\nGive macOS a few seconds after reconnecting the board before starting the\nDNS-SD browse.\n\nThe onboard LED blinks while CDC-NCM/link-local setup is pending and stays on\nonce the firmware has a link-local IPv4 address.\n\nThe root HTTP endpoint serves a small browser UI for the WebSocket endpoint.\n\n## Web UI\n\nOpen:\n\n```text\nhttp://pico-can-bridge.local/\n```\n\nThe UI can connect to the CAN WebSocket, transmit frames, display received\nframes, show CAN status, change bitrate/mode, and copy the current transmit\nframe as JSON for scripts.\n\nThe root page is always the built-in firmware UI. This keeps a known-good\ncontrol surface available even if an uploaded user page is missing or broken.\n\n### User Page Storage\n\nThe firmware also exposes a LittleFS-backed user page at:\n\n```text\nhttp://pico-can-bridge.local/user\n```\n\nThe built-in web UI can upload an HTML file to this page from the User Page\npanel. The same operation can also be done with curl:\n\n```sh\ncurl -i -X PUT \\\n  -H \"Content-Type: text/html; charset=utf-8\" \\\n  --data-binary @my-page.html \\\n  http://pico-can-bridge.local/user/index.html\n```\n\nUploaded pages are stored as `/lfs/user/index.html` and are served back from\nLittleFS. The current upload limit is 512 KiB. If no user page has been\nuploaded, `/user` returns `404 Not Found`.\n\nFilesystem status is available at:\n\n```text\nhttp://pico-can-bridge.local/fs/status\n```\n\n## WebSocket\n\nThe firmware exposes the CAN WebSocket endpoint at:\n\n```text\nws://pico-can-bridge.local/can\n```\n\nThe legacy `/ws` endpoint is kept as an alias for older tests. The endpoint\naccepts JSON-formatted CAN frames and replies with a JSON result.\nFor a quick browser-console test:\n\n```js\nconst ws = new WebSocket(\"ws://pico-can-bridge.local/can\");\nws.onmessage = (event) =\u003e console.log(event.data);\nws.onopen = () =\u003e ws.send(JSON.stringify({\n  type: \"can.tx\",\n  bus: 0,\n  id: 1234,\n  ext: false,\n  rtr: false,\n  dlc: 2,\n  data: [1, 2]\n}));\n```\n\nSee [docs/protocol.md](docs/protocol.md) for the JSON protocol.\n\nPython client examples are available in [examples/](examples/).\n\n## Documentation\n\n- [docs/sdd.md](docs/sdd.md): software design description\n- [docs/protocol.md](docs/protocol.md): WebSocket JSON protocol\n- [docs/known-issues.md](docs/known-issues.md): known USB/macOS notes and local Zephyr patch\n- [docs/release.md](docs/release.md): manual release checklist\n\n## License\n\nLicensed under either of:\n\n- [Apache License, Version 2.0](LICENSE-APACHE)\n- [MIT license](LICENSE-MIT)\n\nat your option.\n\n## Development\n\nThis project was developed in close collaboration with OpenAI Codex, used for\nfirmware implementation, debugging support, documentation, and iteration on the\nbuilt-in web UI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulso%2Fpico-can-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fulso%2Fpico-can-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulso%2Fpico-can-bridge/lists"}