# Workabout MX barcode scanner — API notes (reverse-engineered) There is no official SDK documentation for the Workabout MX integral laser scanner. The Psion SIBO C SDK and I/O Devices Reference predate the MX and describe only the older *external* barcode modules (wands / wand-emulation), not the integral laser. These notes are reverse-engineered from device behaviour and from the Workabout MX ROM `w2mx_v7.20f_eng.bin` (strings), so treat unconfirmed items as such. ## Hardware - Integral **laser** scanner, Symbol engine. The demo (`DEMMAN.APP`) reports `Type: Laser 1223` (some units `1222`). - It is a **decoded** scanner: it decodes in hardware and lights a green good-read LED. It does **not** emit an undecoded (HHLC) signal. - Trigger: the keyboard **scan key**, which the Window Server reports as key code **368**. The key alone does not fire the laser from an arbitrary app; the scanner software arms/reads the engine. ## Device driver and ports `LLDEV` on the device lists a logical driver **`wl2`** (`units=1`). The scanner is reached through this driver. The demo's "Select Scanner" screen lets you pick both a **decoder type** and a **port** (device driver + unit letter): - Port device drivers offered: **`TTY`**, **`WLS`**, **`WL2`**. The MX integral laser uses **`WL2`**. - Units seen in the ROM: **`WL2:A`** and **`WL2:D`**. Decoder types (from the demo, "chosen from those used in standard Workabout products"): | Decoder | Meaning | | --- | --- | | `Generic` | External non-configurable reader | | `Symbol1` | Workabout standard scanner | | `Datalogic` | Workabout CCD | | `HP` | Workabout Wand | | **`Symbol2`** | **Workabout MX scanner (the integral laser)** | ## Opening the device ```c VOID *h; INT err = p_open(&h, "WL2:D", (UINT)-1); ``` Observed results: | Call | Result | Meaning | | --- | --- | --- | | `p_open("WL2:D", -1)` | `0` | **opens** — this is the integral-laser unit | | `p_open("WL2:A", -1)` | `-9` (`E_GEN_INUSE`) | in use — held by the resident scanner software | | `p_open("WL2:B" / ":C")` | (untested) | — | `WL2` has a single unit, so only one process may hold it. `WL2:A` is permanently `-9` even with the demo closed, indicating a resident holder; `WL2:D` is the unit an application opens. ## The 11-byte parameter block The scanner is configured by an **eleven-byte parameter block**. The application interprets these bytes and converts them into commands for the selected decoder (so the same block means different wire commands for `Symbol2` vs `HP`, etc.): | Byte | Parameter | | --- | --- | | Param0 | Decode security | | Param1 | Code type (symbology select) | | Param2 | Decode options A | | Param3 | Decode options B | | Param4 | General parameters | | Param5 | ITF length 1 | | Param6 | ITF length 2 | | Param7 | Preamble | | Param8 | Postamble byte 1 | | Param9 | Postamble byte 2 | | Param10 | General decode options | The preamble/postamble bytes mean decoded output may carry configurable leading / trailing characters — parsing code must account for them. ## Access model Applications do not drive `WL2` byte-by-byte themselves; they use the ROM library **`SCANNER.DYL`** (used by `SCANAPP.APP` and `DEMMAN.APP`). That library opens the port, converts the 11-byte block to decoder commands, configures and enables the engine, and returns decoded scans. ## Paths that do NOT work for the integral laser Recorded so they are not retried: - **`bar*.ldd` decoders (`BAREAN`, `BARC39`, …) + `BAR:` device.** These are software decoders for the *external* wand modules. Loading `BAREAN.LDD` and opening `BAR:A`/`BAR:B` returns `-41` (`E_FILE_DEVICE`, "no interface found in slot") — the integral laser is not a `BAR:` expansion interface. `BAR:D`/`BAR:E` return `-38` (`E_FILE_NAME`, invalid unit). - **`TTY:D` serial reads.** Opening `TTY:D` powers the laser (it fires briefly), but no decoded bytes ever arrive on the serial channel — not with default config, not after `P_FSET` to 9600/8/1, not with `P_OBEY_DSR` cleared, not with the intelligent-reader escape commands (`-y1J` / `-y1K`), not reading one byte at a time. The integral laser's decoded data is not on `TTY:D`. ## Open gap (not yet solved) Opening `WL2:D` succeeds, but the scanner does not start scanning on a bare open — it requires an **initialisation sequence** (set decoder type, write the 11-byte parameter block as decoder commands, enable the engine) before a read returns data. That sequence is the function-code / control protocol of the `WL2` driver and is implemented in the binary `SCANNER.DYL`; it is **not** present in any ROM strings or in the SDK. To close it, one of: 1. The **Workabout MX C SDK** scanner header / `SCANNER.DYL` category definition (what `SCANAPP` was built against) — the clean answer. 2. Disassembly of `SCANNER.DYL` / `SCANAPP` from the ROM to extract the `WL2` init sequence — large, uncertain effort. ## Error codes seen (from `epocdefs.h`) | Value | Name | Meaning | | --- | --- | --- | | `-9` | `E_GEN_INUSE` | device already open / in use | | `-32` | `E_FILE_EXIST` | (LDD) already loaded | | `-38` | `E_FILE_NAME` | invalid device name / unit | | `-41` | `E_FILE_DEVICE` | device / interface not present |