Skip to content

CompactAIOfficial/SlothFi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SlothFi

what? judgy? Im not the best at naming ok?

A $6 WiFi dongle, mass-produced by a mass of poor decisions.

Turn a Raspberry Pi Pico 2 W into a USB WiFi dongle using MicroPython. Plug it into any computer and get internet access over USB. Yes, you could just buy a WiFi dongle for less than the cost of the Pico. No, that didn't stop us.

What It Does

The Pico pretends to be a USB Ethernet adapter (CDC-ECM), connects to WiFi, and bridges traffic between the two using a hand-rolled network stack written in MicroPython -- a language famous for its speed in the same way that sloths are famous for their agility.

  1. Host computer sees a USB Ethernet adapter and gets an IP via our homebrew DHCP server.
  2. The Pico connects to WiFi using credentials you hardcode into a Python file like an animal.
  3. TCP and UDP traffic gets NAT'd through an application-level network stack that was definitely not written while reading RFC 793 with increasing despair.
  4. DNS requests are proxied so you can actually resolve domain names, which feels like a miracle every time it works.

Performance

101.9 KB/s. That is not a typo. We reimplemented networking in an interpreted language running on a microcontroller clocked at 150 MHz. You will feel the mass of every electron.

And well? I can load my own website. So I'd say it's actually usable for things. Unlike most of my things.

Prerequisites

  • Raspberry Pi Pico 2 W -- the $6 board doing $6 worth of work
  • MicroPython firmware (v1.23+ recommended)
  • usb-device package installed via mip
  • A willingness to accept that this exists

Installation

1. Flash MicroPython

Download the latest MicroPython .uf2 for the Pico 2 W from micropython.org. Hold BOOTSEL while plugging in the Pico, then drag the .uf2 file to the mounted drive.

2. Install the usb-device package

Connect to the Pico's REPL (e.g., via Thonny or mpremote) and run:

import mip
mip.install("usb-device")

3. Copy project files to the Pico

mpremote cp config.py :config.py
mpremote cp ecm_interface.py :ecm_interface.py
mpremote cp netstack.py :netstack.py
mpremote cp boot.py :boot.py
mpremote cp main.py :main.py

Or use the included flash.sh script, which will auto-detect your Pico, fight ModemManager for control of the serial port, and upload everything in one go. It works surprisingly often.

4. Edit WiFi credentials

Open config.py and set your WiFi network name and password:

WIFI_SSID = "YourNetworkName"
WIFI_PASS = "YourPassword"

Yes, plaintext credentials on an unencrypted filesystem. The security model here is "don't lose the Pico."

5. Reset the Pico

Unplug and re-plug the Pico. It will boot, connect to WiFi, and appear as a USB Ethernet adapter. If all goes well, which historically is a big "if."

Architecture

[Host Computer] --USB--> [Pico 2 W: CDC-ECM] --WiFi--> [The Internet]
                          ^                ^
                          |                |
                    Fake Ethernet     Application-level NAT
                    adapter that      written in a language
                    actually works    that shouldn't be doing
                    (somehow)         this (but is)

File Descriptions

File What It's Doing Down There
config.py WiFi credentials in plaintext, network settings, and connection limits that exist because we ran out of RAM, not because we planned ahead
ecm_interface.py Convinces your OS that this Pico is a real Ethernet adapter. USB descriptor wizardry. Contains dead code that survived review because the reviewer was also the author
netstack.py 571 lines of hand-rolled Ethernet/IP/TCP/UDP parsing, DHCP server, DNS proxy, and NAT. Every networking course project's final boss
boot.py Runs before anything else to hijack the USB bus. 12 lines that can brick your REPL access if you look at them wrong
main.py Connects to WiFi, starts the bridge loop, and garbage-collects every 100 iterations because MicroPython will eat your RAM like it's at a buffet
flash.sh Deployment script that kills ModemManager, probes serial ports, and uploads files. Enterprise-grade DevOps for a $6 board

Limitations

  • Throughput: 50-100 KB/s. You can load web pages. You probably can't stream video. You definitely can't stream video.
  • Connections: 128 TCP, 256 UDP at a time. Configurable, but the Pico has 520 KB of RAM, so go ahead and raise those limits -- see what happens.
  • No ICMP forwarding: You can ping the Pico itself (it responds to prove it's alive), but pings to the internet go nowhere. traceroute is right out.
  • Single client: One host computer at a time. If you need to share WiFi with multiple devices, you want an actual router.
  • TCP state machine: Written by someone who learned TCP by writing this TCP implementation. Connection edge cases may produce outcomes that are, charitably, creative.

OS Compatibility

OS Status
Linux Works out of the box. CDC-ECM is natively supported. The one time Linux's driver model paid off.
macOS Works out of the box. Apple supporting open standards -- mark the calendar.
Windows 10+ Requires registry tweaks, sacrificial offerings, and driver configuration. So, par for the course.

Getting the REPL Back

boot.py takes over the USB interface at startup. If you need to get back in:

  • Hold BOOTSEL during reset to enter USB mass-storage mode, then re-flash MicroPython.
  • Or use mpremote from another machine:
    mpremote rm :boot.py
    mpremote reset

Why

Because "I could just buy a WiFi dongle" is the coward's path, and we wanted to understand networking at a level that makes us mass uncomfortable at parties.

License

Do whatever you want with this. If you find a way to make money from a MicroPython WiFi dongle that maxes out at dial-up speeds, you deserve it.

About

Turn your 6$ Raspberry pi Pico 2 W into a network card. Because why the hell not.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages