fix(devices): USB printing dropped the job tail — chunked write loop
Field bug (ICS XP-K200L over USB): text printed, barcode + cut missing; same bytes over TCP fine. sendRawUsb did ONE write() on an O_NONBLOCK usblp fd and never checked bytesWritten — the kernel accepts only what fits the printer's ~8 KB USB buffer and returns a short write, so the tail of any job bigger than one buffer (the barcode mid-payload, the cut at the end) was silently discarded. The regular-file test stand-in can't short-write, which is why tests never caught it. writeAllUsb now pushes 4 KB chunks until every byte is accepted, continues after partial writes, retries EAGAIN/zero-byte with a short pause, and fails at the deadline with an (N/M bytes) diagnostic. Driven by fake-handle tests (short writes, EAGAIN interleave, wedged-printer timeout, non-EAGAIN passthrough). Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
type: concept
|
||||
tags: [parking, device, printer, transport, usb, escpos, provisioning]
|
||||
sources: []
|
||||
updated: 2026-06-24
|
||||
updated: 2026-07-06
|
||||
status: settled
|
||||
---
|
||||
|
||||
@@ -87,5 +87,28 @@ The setup UI offers a **Connection** select (Network / USB) + a **USB device** p
|
||||
to the node and reports ready/offline). The on-hardware confirmation + the udev/usblp provisioning
|
||||
are pending (open-questions #14).
|
||||
|
||||
## Field bug — the NONBLOCK partial-write truncation (found + fixed 2026-07-06)
|
||||
|
||||
First on-hardware USB test (ICS XP-K200L, an ESC/POS clone): over TCP it printed + cut fine; over
|
||||
USB it printed the ticket's TEXT but **no barcode and no cut**. Root cause was in OUR transport,
|
||||
not the printer: `sendRawUsb` opened the node with `O_NONBLOCK` and issued ONE `write()` for the
|
||||
whole job. On a non-blocking usblp fd the kernel accepts only what fits the printer's USB buffer
|
||||
(~8 KB) and returns a **short write**; the old code never checked `bytesWritten`, closed the
|
||||
handle, and silently dropped the tail — which is exactly where the barcode (mid-payload) and the
|
||||
CUT (last bytes) live. Small jobs fit one buffer, hence "text prints fine". The regular-file test
|
||||
stand-in can't short-write, so tests never caught it.
|
||||
|
||||
Fix: `writeAllUsb` — chunked loop (4 KB, safely under the usblp buffer) that continues after
|
||||
partial writes, retries `EAGAIN`/zero-byte writes with a short pause, and fails at the caller's
|
||||
deadline with a `(N/M bytes accepted)` diagnostic. Driven by fake-handle tests (short writes,
|
||||
EAGAIN interleave, wedged-printer timeout, non-EAGAIN passthrough) since a real file can't
|
||||
reproduce the char device's behaviour.
|
||||
|
||||
> Driver-choice note for this clone: the ICS XP-K200L does NOT serve the Rongta `/prn_stat.htm`
|
||||
> status page (checked on hardware at 10.0.10.11 — print socket 9100 open, status page absent),
|
||||
> so on NETWORK the honest driver is **cashino** (reachability-only monitoring); under `rongta`
|
||||
> the monitor would mark a perfectly working printer offline/degraded. Over USB the two drivers
|
||||
> behave identically (reachability floor), so either works post-fix. See [[rongta-printer]].
|
||||
|
||||
Related: [[rongta-printer]], [[printer-status-monitoring]], [[printer-roles-failover]],
|
||||
[[appliance-provisioning]], [[network-isolation]], [[technology-stack]].
|
||||
|
||||
Reference in New Issue
Block a user