ngxson/esp32-usb-to-airprint

★ 178⑂ 11

Add AirPrint / AirScan support to your old printer, using just a cheap ESP32-S3

About ngxson/esp32-usb-to-airprint

ngxson/esp32-usb-to-airprint is an open-source project on GitHub, mainly written in C. Add AirPrint / AirScan support to your old printer, using just a cheap ESP32-S3 It currently holds 178 stars and 11 forks with 5 open issues, and was last pushed on 2026-10-26 (repository created 2026-10-26).

Project Overview

Git Homed tracks it on the Today's Trending board, currently at rank #38 with 0 new stars today.

GitHub Repository Details

Repository ngxson/esp32-usb-to-airprint · default branch master · size 10687 KB · watchers 0 · source: GitHub REST API and repository README

README

Add AirPrint / AirScan support to your old printer, using just a cheap ESP32-S3

[!IMPORTANT]
This project is actively looking for contributors to add support for more printers. Most importantly, you need to really own the printer you add: every driver must be tested on the real hardware, not only in emulation. See Adding a printer to get started.

Turns any USB-only printers into a wireless printer and scanner. An ESP32-S3 board plugs into the printer's USB port and joins your WiFi:

| | | |---|---| | | | | | |

Supported printers

| Series | Models | Scan | |---|---|---| | 🟢 MG2500 | MG2550S | yes | | 🟡 MG2400 | MG2410 to MG2490 | yes | | 🟡 MG2500 | MG2510 to MG2590 (other than the MG2500S) | yes | | 🟡 P200 | P200 | no scanner | | 🟡 MG2900 | MG2910 to MG2990 | yes | | 🟡 MG3000 | MG3010 to MG3090 | yes | | 🟡 E470 | E470 to E478 | yes | | 🟡 E460 | E460 to E468 | yes | | 🟡 iP2800 | iP2810 to iP2899 | no scanner | | 🟡 E3100 | E3170 to E3195 | yes | | 🟡 TS3100 | TS3110 to TS3195 | yes | | 🟡 MP230 | MP230 to MP237 | yes | | 🟡 iP2700 | iP2700 to iP2788 | no scanner | | 🟡 MP250, MP270, MP280 | MP250 to MP288 | yes | | 🟡 MP490, MP493, MP495 | MP490 to MP499 | yes | | 🟡 MX340, MX350 | MX340 to MX358 | yes (glass only) | | 🟡 MX360, MX410, MX420 | MX360 to MX428 | yes (glass only) |

The firmware recognises the printer when it is plugged in. Other printers? Please open an issue or a PR.

What you need

Just one thing: An ESP32-S3 dev board with two USB-C ports:

Optionally: a SSD1315 OLED screen and a 3D-printed case, see later in this tutorial

Setup

Step 1: Hardware. Plug the ESP32-S3 into your computer via the COM port on the ESP32 board (NOT the port labelled "USB")

Step 2: Settings. Build once (pio run): this creates .env. Edit it:

   WIFI_SSID=your-network
   WIFI_PASSWORD=your-password
   PRINTER_NAME=Canon MG2500 (ESP32)
   HOSTNAME=canon-mg2500
   MODE=debug
   
MODE=debug lets you update the board over WiFi later (see below); MODE=normal does without. .env is git-ignored, so your WiFi password stays local.

Step 3: Flash. Connect the board's COM port to your computer and run pio run -t upload. PlatformIO finds the board's serial port; if several are connected, add --upload-port /dev/cu.usbmodem….

Using it

Plug the printer to the port labelled "USB"

NOTE: You may also need to bridge the "USB-OTG" solder join on the board, so that it supplies 5V to the printer. While the printer doesn't actively use 5V, it sense the USB plug using this signal.

Adding OLED screen and buttons

This step is optional, you can connect a SSD1315 OLED screen with the pinout below:

| OLED | ESP32-S3 | |---|---| | VCC | 3V3 | | GND | GND | | SCL | GPIO41 | | SDA | GPIO42 |

Connect it before powering on: the board only looks for it at startup.

For buttons, wire each one between a pin and GND:

| Button | ESP32-S3 | Action | |---|---|---| | 1 | GPIO4 | Same as BOOT (scan, test page, cancel) | | 2 | GPIO5 | Not assigned: add your own in on_user_button() (src/main.c) |

While the screen is off, a press only wakes it up.

Development

Set MODE=dev and flash: print jobs are processed but not printed, and scans show a built-in test page.

On the computer, without the board: make -C host && cd host && ./airprint_host, then open http://localhost:8631/ (an emulated printer and scanner). To work on the web app with live reloading: cd web && npm run dev (it talks to that server; DEVICE=http:// npm run dev talks to the board).

Technical details are in AGENTS.md.

Adding a printer

Each printer model is a driver in components/printers/, listed in printers.c; the firmware picks the one of the printer that is plugged in. A Canon PIXMA whose stream is close to the MG2500's is one line in canon_pixma.c; another printer is a new file in the same folder. See AGENTS.md for details.

License

MIT, see LICENSE.

The printer and scanner protocols follow Gutenprint and SANE's pixma backend. The JPEG encoder's DCT is a translation of libjpeg's jfdctint.c: this software is based in part on the work of the Independent JPEG Group. The web UI bundles Svelte (MIT) and pdf.js (Apache-2.0).

GitHub Stars & Activity

178Stars
11Forks
5Open issues
CLanguage

GitHub Popularity

GitHub stars178
Forks11
Open issues5
Primary languageC
LicenseMIT
Stars gained today0
Created2026-10-26
Last pushed2026-10-26

Trending History

Daily boardrank #38 · ▲ 0 stars

Related GitHub Projects

1
→
2

anhao / ai-pose-gallery-zh

HTML★ 2,551⑂ 668
→
3

andyhuo520 / digital-human-koubo

TypeScript★ 1,400⑂ 323
→
4

Motionsites-AI / claude-skill

Python★ 1,021⑂ 106
→
5

kargulstudio / calender-app-design

TypeScript★ 795⑂ 96
→
6

smithjohn78390 / tongjiang-lab

HTML★ 760⑂ 206
→
7

yaojingang / GEOInflow

TypeScript★ 707⑂ 227
→
8

blakeandersonw / ai-app-playbook

TypeScript★ 571⑂ 77
→

More Trending Repositories