Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ jobs:
run: |
set -e
sudo apt-get update && sudo apt-get install -y --no-install-recommends cups-ipp-utils
python3 scripts/smoke-image.py ptouch-deploy:check
python3 scripts/smoke-image.py ptouch-deploy:check --model PT-2730
python3 scripts/smoke-image.py ptouch-deploy:check --model PT-P710BT
- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ if(NOT PTOUCH_CORE_ONLY)
target_link_directories(test_driver PRIVATE ${PAPPL_LIBRARY_DIRS} ${PNG_LIBRARY_DIRS})
target_compile_options(test_driver PRIVATE ${PAPPL_CFLAGS_OTHER})
add_test(NAME driver_finishings COMMAND test_driver)
set_tests_properties(driver_finishings PROPERTIES TIMEOUT 90)
add_test(NAME driver_finishings_p710bt COMMAND test_driver PT-P710BT)
set_tests_properties(driver_finishings driver_finishings_p710bt PROPERTIES TIMEOUT 90)
add_executable(test_pappl_raster tests/test_pappl_raster.c)
target_link_libraries(test_pappl_raster PRIVATE ${PAPPL_LIBRARIES} ${PNG_LIBRARIES})
target_include_directories(test_pappl_raster PRIVATE ${PAPPL_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS})
Expand Down
70 changes: 57 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ The Brother raster protocol and device table are reused from

## Capabilities

Only the **Brother PT-2730** is print-supported and hardware-certified;
other recognized models do not receive print output.
**Brother PT-2730** remains the default supported, hardware-certified model.
**PT-P710BT** is hardware-certified over USB on 9/12/18 mm tape, selected
explicitly below. Its 6/24 mm coverage is software-only. Other recognized models do not
receive print output.

- Prints 1:1 within the tape's imageable width, honoring submitted page geometry;
PNG length follows its image when a concrete media length is omitted.
Expand Down Expand Up @@ -51,13 +53,18 @@ Three layers:
## 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 remains recognition metadata and is **not print-supported**: discovery
reports it in diagnostics without offering a printable device. Per-model flag
dispatch (PackBits, P700 init) does not exist yet. All known models are 180 dpi /
128 px max. `PTOUCH_MODEL` defaults to `PT-2730`; unknown or unsupported values
fail before discovery. Multiple matching PT-2730 units block printing as ambiguous,
while a single unit can be unplugged and reattached without replacing its queue.
`ptdevs[]`, plus PT-P710BT). Only PT-2730 and PT-P710BT have implemented print
paths. All other entries remain recognition metadata: discovery reports them
without offering a printable device. Shared protocol flags do not grant support.
All known models are 180 dpi / 128 px max.

`PTOUCH_MODEL` defaults to `PT-2730` when absent or empty. Select the new printer
with `PTOUCH_MODEL=PT-P710BT`; unknown or unsupported values fail before discovery.
The server creates one stable queue for the selected model and never falls back
when it is absent. One of each supported model can coexist; two matching units
of the selected model block printing as ambiguous. USB renumbering after replug
does not replace the queue. Discovery names an attached but unselected printer
and its required `PTOUCH_MODEL` value.

| Model | USB id | flags | Print-supported |
|-------|--------|-------|-----------------|
Expand All @@ -67,6 +74,7 @@ while a single unit can be unplugged and reattached without replacing its queue.
| PT-1230PC (PLite) | 04f9:2030 | `PLITE` | recognized only |
| PT-2430PC (PLite) | 04f9:2031 | `PLITE` | recognized only |
| **PT-2730** | **04f9:2041** | `NONE` | **certified** |
| **PT-P710BT** | **04f9:20af** | `RASTER_PACKBITS \| P700_INIT` | **certified on 9/12/18 mm tape** |
| 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 |
Expand Down Expand Up @@ -104,7 +112,7 @@ ctest --test-dir build-app --output-on-failure

`Dockerfile` supplies the development dependencies; `Dockerfile.deploy` builds
all targets and runs CTest before installing the app into the runtime image.
These tests use no printer; physical behavior requires separate PT-2730 checks.
These tests use no printer; physical behavior requires acceptance on the affected model.

### Printing notes for clients

Expand Down Expand Up @@ -208,16 +216,52 @@ Run state lives in memory. Restart during an unfinished run is unsupported;
finish it deliberately first. Interrupted output requires printer power-cycle
followed by server restart, as described below.

The finishing contract and canonical 32/52/76/120/128-dot tape windows are shared
by both implemented models. PT-2730 retains its legacy eight-byte print
information and uncompressed rows. PT-P710BT uses `ESC i a` raster mode,
automatic status notification, thirteen-byte `ESC i z` print information with
the actual destination row count, a 14-dot feed margin, and TIFF PackBits rows.
Its first page has indication 0 on a freshly initialized closed run; later
pages and healthy cross-batch continuation use 1. Only a fresh P710BT run sends
the 100-byte invalidation and initialization; continuation sends neither.
Finalization still uses deferred FF or late chain-off/EJECT for both models.
The P710BT integrated [hardware gate](tests/P710BT-ACCEPTANCE.md) passed all four
finishing policies, held-run continuation, wrong-media rejection, offline queue
recovery, and explicit uncertain-output recovery. It used 15 complete labels,
including four operator-requested repeat labels. Direct geometry probes remain
separate evidence; 6/24 mm have software coverage only.

## Configuration

Cutting uses the job's standard finishing choice. `PTOUCH_PRECUT`,
`PTOUCH_CUT_MODE`, and `PTOUCH_WIDTH_GUARD` are retired and ignored. Mandatory
batch precut and strict geometry rejection are intrinsic; no replacement server
knob is needed. `PTOUCH_MODEL` defaults to the supported PT-2730.
knob is needed. `PTOUCH_MODEL` defaults to PT-2730; configure
`PTOUCH_MODEL=PT-P710BT` for the P710BT USB path. This selects one queue, not
all attached printers, and never enables another model as a fallback.

`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.
`socket://127.0.0.1:9100`) for testing without USB hardware; queue identity and
protocol still follow `PTOUCH_MODEL`, and the printer connects on an actual print.
An explicit `ptouch://Brother/<model>` override must exactly match the configured
supported model; conflicting or unsupported custom USB URIs fail before commands.

### USB diagnostics

`ptouch-app probe` enumerates only the custom USB scheme and reports whether
exactly one selected VID/PID is present. It never opens the printer or sends
commands. Set `PTOUCH_MODEL` consistently for diagnostics and the server:

```sh
PTOUCH_MODEL=PT-P710BT ptouch-app probe
```

`PTOUCH_MODEL=PT-P710BT ptouch-app smoke` opens the selected printer and sends
initialization (`ESC @`), then checks that those bytes reached USB. Use it only
on a known closed tape run: initialization can destroy a held run. It is not a
read-only status preflight or the isolated IPP/socket image smoke used in CI.
Neither diagnostic chooses a different attached model when selection is absent
or ambiguous.

## Deploy

Expand Down
73 changes: 54 additions & 19 deletions docs/ADDING-A-MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

This guide explains how to add a Brother P-touch model to the device table. A new
entry makes the model **recognized in metadata**. Discovery and printing remain
restricted to the explicitly supported PT-2730. A table row does not grant
print support. See the support gate below.
restricted to the explicitly supported PT-2730 and PT-P710BT paths. PT-2730
remains the default; P710BT requires `PTOUCH_MODEL=PT-P710BT`. A table row does
not grant print support. P710BT integrated USB acceptance passed on 9/12/18 mm tape;
6/24 mm remain software-only coverage.
See the support gate below.

## The `pt_dev` fields

Expand Down Expand Up @@ -43,17 +46,49 @@ Copied from `src/tables.h`:
#define FLAG_PLITE 0x04u /* P-Lite mode (not driven) */
```

- `FLAG_NONE`: plain uncompressed raster, PT-2730-style. This is the only path
the print code drives today.
- `FLAG_NONE`: plain uncompressed raster, used by PT-2730.
- `FLAG_RASTER_PACKBITS`: `sendraster` must wrap each line in a single
uncompressed PackBits run (`pt_cmd_sendraster_packbits` in `src/protocol.h`).
- `FLAG_P700_INIT`: `rasterstart` uses the P700 variant (`1b 69 61 01`) instead of
the default.
- `FLAG_PLITE`: the model is in P-Lite mode, which this project does not drive.

Set the flags to describe the model accurately even though the driver does not yet
dispatch on them. They document the protocol the model needs once per-model
dispatch lands.
Flags describe encoding and raster-mode commands, not print support. The driver
uses them only after resolving an explicitly supported model. P710BT has both
`FLAG_RASTER_PACKBITS` and `FLAG_P700_INIT`; it also needs the model-specific
extended page setup below. Sharing these flags does not enable another model.

## The implemented P710BT command path

P710BT metadata is `04f9:20af`, 128 dots, normal 180 dpi. Its page setup differs
from PT-2730's legacy eight-byte `ESC i c` command:

| Operation | Builder / command |
| --- | --- |
| Fresh-run preparation | `pt_cmd_invalidate`: 100 zero bytes, then `pt_cmd_init`: `1b 40`. Omit both when continuing a healthy held run. |
| Raster mode | `pt_cmd_rasterstart` with `FLAG_P700_INIT`: `1b 69 61 01`. |
| Automatic status | `pt_cmd_auto_status(o, true)`: `1b 69 21 00`. |
| Extended page information | `pt_cmd_printinfo_extended`: `1b 69 7a 84 00 mm 00 r0 r1 r2 r3 page 00`. `r0..r3` are the validated destination page's row count, little-endian. |
| Compression | `pt_cmd_compression(o, 2)`: `4d 02` selects TIFF PackBits. |
| Raster line | `pt_cmd_sendraster_packbits` wraps each complete 16-byte head line as `47 11 00 0f` followed by those bytes, a single literal run. |
| Feed margin | `pt_cmd_margin(o, 14)`: `1b 69 64 0e 00`. |

The extended page command uses width-valid/recovery flags `84`, unspecified
media kind, zero fixed-length and reserved fields. `page` is 0 for a freshly
initialized printer run and 1 for subsequent pages, including the first page of
an IPP batch continuing a healthy held run. Cross-batch indication and finishing
were verified by the integrated physical gate; separate-label probes did not
verify them. Normal resolution and finishing use the existing mode/advanced
builders and batch lifecycle, without half-cut or cut-every-N commands.

Direct USB geometry probes on 2026-10-12 used this setup with first-page
indication 0, normal resolution, autocut, chain-off, and terminal EJECT. The
operator confirmed complete 52-, 76-, and 120-dot rectangles on 9, 12, and 18 mm
tape. The existing 32/52/76/120/128-dot table is shared by both supported paths;
6 and 24 mm remain software/documentation coverage for P710BT. These observations
establish usable geometry, not integrated finishing, continuation, or recovery
certification. The change's validation summary records retained probe evidence
and any unavailable files separately.

## Adding the entry

Expand Down Expand Up @@ -97,18 +132,18 @@ do not enable it merely by adding metadata.

## Caveats: recognized is not supported

A new entry is **untested and not print-supported** until:

- The model is verified on real hardware. Only the PT-2730 (`04f9:2041`) is
hardware-certified. The status read, media detection, and print geometry are all
validated against it and nothing else.
- For PackBits or P700 models (`FLAG_RASTER_PACKBITS`, `FLAG_P700_INIT`), per-model
flag dispatch exists in the driver. The current supported-model gate rejects
these models before output; it does not send them PT-2730 bytes.

Until then a new row only adds lookup metadata. `pt_usb_supported_model` and the driver identity check must remain
restricted to the implemented, validated print path, and rejected models must
receive no output.
A new entry only adds lookup metadata. Enabling another model requires an
implemented protocol path, consistent queue/USB identity and status handling,
software regressions, and an explicit supported-model gate change. PT-2730
(`04f9:2041`) and P710BT (`04f9:20af`) are hardware-certified. P710BT's integrated
gate covers 9/12/18 mm USB printing, finishing, continuation, and recovery;
6/24 mm remain software-only. Recognition, pure command tests, and separate
geometry probes alone do not certify another model.

`pt_usb_supported_model` and the driver identity check must remain restricted
to these two implemented paths. Other catalog entries, including PackBits/P700
models, remain unsupported and must receive no output. Do not broaden the gate
based on flags or silently fall back to an attached model.

## Source of new PIDs

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-10-13
Loading
Loading