Skip to content

pfa230/ptouch-print-server

Repository files navigation

ptouch-print-server

A generic Brother P-touch IPP Everywhere print server, built on PAPPL. It exposes a P-touch label printer as a driverless IPP Everywhere / AirPrint device so any client can discover it and print without a vendor driver.

The Brother raster protocol and device table are reused from hannesweisbach/ptouch-print (GPL). See LICENSE.

Status

The project is built in milestones. Only the Brother PT-2730 is hardware-certified; the print path currently emits PT-2730 protocol for every device.

Milestone Scope State
M0 Hardware spike: confirm the raster bytes and the usb:// hang on real hardware Done
M1 Pure C core: device table, protocol command builders, raster packing, status parse Done
M2 PAPPL adapter and read path: custom ptouch:// libusb scheme, media/status callback Done
M3 Print path: raster callbacks that print and cut on the PT-2730 In progress
M4 Cutter modes and width guard (PTOUCH_* configuration) Pending
M5 Packaging Pending

M3 raster callbacks print and cut a label on the PT-2730 today (init / rasterstart / sendraster per line / eject). The exact print geometry is still being finished: no-scaling fit, variable label length, and head-limiting behaviour are not yet final.

Architecture

Three layers:

  1. Pure C core (src/tables.c, src/protocol.c, src/raster.c, src/status.c, src/cutter.c). Libc only, no hardware, no PAPPL. All Brother byte sequences live in protocol.c; raster packing centers a scanline into the 16-byte (128-dot) raster line in raster.c; the device table and per-model flags live in tables.c. This layer builds and unit-tests on any machine.

  2. PAPPL driver (src/driver.c). Registers the IPP printer, fills the driver data (media, resolution, finishings), reads loaded-tape status, and drives the raster print callbacks (rstartjob / rwriteline / rendjob).

  3. Custom ptouch:// libusb scheme (src/device_usb.c). PAPPL's built-in usb:// scheme issues an IEEE-1284 device-ID probe that hangs on the PT-2730 (confirmed in M0). This project registers its own ptouch:// PAPPL_DEVTYPE_CUSTOM_LOCAL scheme over raw libusb with bounded timeouts, and never auto-adds the built-in usb:// device.

Supported devices

src/tables.c recognizes the P-touch USB ids below (transcribed from upstream ptdevs[]). Only the PT-2730 is print-supported and hardware-certified. Every other entry is recognized and discoverable, but is not print-supported: the raster path emits PT-2730 protocol (uncompressed, 128-dot head) regardless of the matched model, and per-model flag dispatch (PackBits, P700 init) does not exist yet. All known models are 180 dpi / 128 px max.

Model USB id flags Print-supported
PT-2420PC 04f9:2007 RASTER_PACKBITS recognized only
PT-1230PC 04f9:202c NONE recognized only
PT-2430PC 04f9:202d NONE recognized only
PT-1230PC (PLite) 04f9:2030 PLITE recognized only
PT-2430PC (PLite) 04f9:2031 PLITE recognized only
PT-2730 04f9:2041 NONE certified
PT-E500 04f9:205f RASTER_PACKBITS recognized only
PT-H500 04f9:205e RASTER_PACKBITS | P700_INIT recognized only
PT-P700 04f9:2061 RASTER_PACKBITS | P700_INIT recognized only
PT-P700 (PLite) 04f9:2064 PLITE recognized only
PT-P750W 04f9:2062 RASTER_PACKBITS | P700_INIT recognized only
PT-P750W (PLite) 04f9:2065 PLITE recognized only
PT-D450 04f9:2073 RASTER_PACKBITS recognized only
PT-D600 04f9:2074 RASTER_PACKBITS recognized only

To add a model, see docs/ADDING-A-MODEL.md.

Build and run

The pure C core builds and unit-tests anywhere with CMake and a C11 compiler. No hardware or PAPPL needed:

cmake -S . -B build && cmake --build build && ctest --test-dir build

This builds ptcore and runs the five core test suites (tables, protocol, raster, status, cutter).

The full ptouch-app executable builds only where PAPPL and libusb-1.0 are present (pkg-config finds pappl and libusb-1.0). On a machine without them, CMake skips the app target and still builds the core and tests. The app is built and exercised against PT-2730 hardware in a container; see Dockerfile.

Printing notes for clients

The printer advertises continuous-roll media (tape-width-fixed, length-variable roll_min/roll_max range) and uses print-scaling=none, so a label prints 1:1. For a label to come out at its true size, a client must:

  • send the image at the printer resolution, 180 dpi (a PNG with no DPI metadata is placed at a default ppi and will not fill the requested media), and
  • request a media-col size matching the image (tape imageable width x label length). The printer reports the loaded tape's printable width via media-ready; note media is advertised at printable, not physical, width (a 24 mm tape images ~18 mm, the 128-dot head).

Configuration

The print path is configured entirely through environment variables (no config file or volume). The driver reads them per job.

Variable Values Meaning
PTOUCH_CUT_MODE each (default) / end / none Cut policy for a batch: cut after every label, only after the last, or never
PTOUCH_PRECUT 1 (default) / 0 Feed and cut a leader before the first label of a batch
PTOUCH_WIDTH_GUARD strict (default) Refuse to print when the rendered width does not match the loaded tape. Only strict is implemented; any other value falls back to strict

PTOUCH_DEVICE_URI overrides device discovery with an explicit URI (e.g. socket://127.0.0.1:9100) for testing without a PT-2730; the printer registers but only connects on an actual print.

Deploy

The deploy image is published to GHCR as ghcr.io/pfa230/ptouch-print-server:edge (the moving tag) and a per-commit sha-<commit> tag for rollback. It is built and pushed by .github/workflows/deploy.yml on every push to main; pull requests build and run an IPP smoke test but do not push.

The image is a multi-stage build (Dockerfile.deploy): PAPPL 1.4.11 and the app compile in a Debian build stage, and only the runtime libraries, avahi-daemon, and dbus ship in the debian-bookworm-slim runtime stage. The entrypoint starts a system dbus and Avahi (DNS-SD on the container's own LAN IP), then runs ptouch-app server on port 8000. The container has no persistent state, so no volume is needed.

Run it on the LAN with its own IP and the PT-2730 passed through:

services:
  ptouch:
    image: ghcr.io/pfa230/ptouch-print-server:edge
    container_name: ptouch
    restart: unless-stopped
    hostname: ptouch
    environment:
      PTOUCH_CUT_MODE: each
      PTOUCH_PRECUT: "1"
      PTOUCH_WIDTH_GUARD: strict
    devices:
      - /dev/bus/usb:/dev/bus/usb        # PT-2730 USB passthrough
    device_cgroup_rules:
      - 'c 189:* rwm'                    # allow libusb to re-claim across replug
    networks:
      br0:
        ipv4_address: 10.10.1.40         # its own LAN IP (adjust to your network)
networks:
  br0:
    external: true

The PT-2730 USB interface can be held by only one process. A dev/spike container holding the device must be stopped before this container starts; both cannot own the device at once.

Licensing

This project is licensed under the GNU General Public License v3.0 only (GPL-3.0-only). The full text is in LICENSE.

It is GPL because it reuses Brother P-touch raster protocol and device-table code from hannesweisbach/ptouch-print (GPLv3, by Dominic Radermacher). Credit and thanks to that upstream project.

About

Generic Brother P-touch label printer as a driverless IPP Everywhere / AirPrint print server (PAPPL)

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors