Telpo C9D Cash Drawer
This page records the hardware details found on the Android POS terminal used for cash drawer integration.
Verified device
Checked over ADB on 2026-07-08.
| Field | Value |
|---|---|
| ADB serial | A65C009P00400034 |
| Manufacturer | Telpo |
| Android model | C9D |
| Android version | 14 |
| Build display id | C9D_A14_V1.1.3_202603250221 |
The device may be referred to operationally as CPOS TH C9PD, but Android
reports the hardware as Telpo C9D.
Installed helper packages
Relevant packages found on the terminal:
| Package | Notes |
|---|---|
com.cpos.helper | Installed helper app. APK strings identify it as Telpo Drawer Helper. |
com.telpo.omcservice | Telpo privileged system service. |
th.co.boonsiri.posterminal | POS terminal app. |
com.boonsiri.printerconfig | Printer configuration app/package with Android PrintService and PrinterContentProvider. |
com.cpos.helper was installed from Files (com.google.android.apps.nbu.files)
and reports version 1.1.1.
com.boonsiri.printerconfig reports version 1.0.0, declares
com.boonsiri.printerconfig.READ_PRINTERS, and exposes:
com.boonsiri.printerconfig/.print.BoonsiriPrintServicecom.boonsiri.printerconfig/.provider.PrinterContentProvider- provider authority
com.boonsiri.printerconfig.provider
Verified USB peripherals
adb -s A65C009P00400034 shell dumpsys usb found two USB peripherals.
Receipt printer
| Field | Value |
|---|---|
| USB path | /dev/bus/usb/001/005 |
| Manufacturer | ICOD |
| Product | ICOD_Thermal_Printer |
| Vendor ID | 1155 |
| Product ID | 30016 |
| USB class | 7 (Printer) |
| Interface class | 7 |
| Interface subclass | 1 |
| Interface protocol | 2 |
| Serial number | 000000000005920ca2 |
| OUT endpoint | address 3, max packet size 64 |
| IN endpoint | address 129, max packet size 64 |
The USB settings also register com.cpos.helper/.MainActivity for attached USB
devices with class 7, so the Telpo drawer helper is expected to handle USB
printer attach events.
Scanner / keyboard wedge
| Field | Value |
|---|---|
| USB path | /dev/bus/usb/001/003 |
| Manufacturer | HID . |
| Product | DECODER-KEYBOARD |
| Vendor ID | 7554 |
| Product ID | 23712 |
| USB class | HID class 3 |
This device appears as a keyboard-style scanner and should not be treated as the receipt printer.
Drawer capabilities found
The helper APK contains cash drawer specific code and text, including:
Telpo Drawer Helpercom.cpos.helper.Drawercom.cpos.helper.PrinterProxyServicecom.cpos.helper.TEST_DRAWERACTION_TEST_DRAWERDrawer ProxyDrawer ModeMODE_TELPOMODE_USBMODE_PRINTERTelpo only (GPIO/SDK)USB only (drawer on printer)Auto (printer + Telpo)Standard printer (drawer connected to printer)
The APK also includes Telpo SDK classes relevant to direct drawer control:
com.telpo.tps550.api.moneybox.MoneyBoxcom.common.apiutil.moneybox.MoneyBoxcom.common.apiutil.util.TelpoLib
Native libraries found in the helper APK:
libtelpo-lib.solibserial-util.solibusb-util.so
libtelpo-lib.so references /dev/telpo_gpio and exposes JNI symbol
Java_com_common_apiutil_util_TelpoLib_ioctlControlJNI, which suggests the
Telpo SDK can drive GPIO-level drawer control.
Printer drawer kick command
The helper APK also contains an ESC/POS drawer kick path for drawers connected through a receipt printer.
Command bytes found:
1B 70 00 19 FA
Equivalent byte array:
[0x1b, 0x70, 0x00, 0x19, 0xfa]
Send these bytes directly to a printer only when the cash drawer is connected to that printer's drawer port, usually RJ11/RJ12. Sending the same bytes to the CPOS Helper's localhost proxy is a separate path: Telpo mode interprets them as a MoneyBox command instead of forwarding them to a printer.
For the verified ICOD USB thermal printer, raw USB ESC/POS output should target the printer device, not the scanner:
- expected target product:
ICOD_Thermal_Printer - expected USB path at time of inspection:
/dev/bus/usb/001/005 - expected OUT endpoint: address
3
Verified helper interface and app integration
Rechecked on 2026-10-21 on the same C9D, with com.cpos.helper version
1.1.1 (version code 3). The helper APK and running service confirm:
PrinterProxyServiceis not exported. Other apps cannot invoke itscom.cpos.helper.TEST_DRAWERservice action directly.- The running service listens at 127.0.0.1:9100, not a LAN interface.
- It parses ESC/POS drawer commands. In Telpo only (GPIO/SDK) mode it
strips the printer command and calls
com.common.apiutil.moneybox.MoneyBox.open(1, pulseMs). - Automatic (printer + Telpo) also calls MoneyBox but forwards the printer bytes. Standard printer mode does not call MoneyBox. For a drawer wired directly to this POS, select Telpo only (GPIO/SDK) in CPOS Helper.
- The helper initializes the Telpo SDK in its Application and clamps MoneyBox
pulses to 120–800 ms. A direct
/dev/telpo_gpiopath was not present on this device; the library string alone is not a usable app integration contract.
An ADB-forwarded connection to this proxy was used to send a single
1B 70 00 19 FA command per test. The operator reported a drawer response and
requested another test after unlocking the drawer. A successful socket write
confirms delivery to the helper; its protocol has no physical-open acknowledgement.
Terminal uses CashDrawerModule in android/app/src/main/java/th/co/boonsiri/posterminal/cashdrawer
and the TypeScript wrapper src/native/cashDrawer.ts. It supports the verified
Telpo C9D when CPOS Helper is installed and enabled. The helper must already be
running; the module uses only its localhost TCP interface. No printer fallback,
SDK binary copying, root access, or exported helper service is needed.
StorefrontOrderPaymentStep sends a command after payOrder succeeds, before
the detail refresh, and when the current waiting order becomes CONFIRMED
through a server/QR update. Entering an already-confirmed order does not send a
command. Each order is requested once per mounted payment flow, and native code
rejects overlapping requests and suppresses pulses less than 1.5 seconds apart.
Unsupported devices skip this action. A connection failure reports the drawer
problem separately without resubmitting payment or automatically retrying a pulse.
Verification uses mocked payment APIs; no real financial transaction is needed to test the native drawer module on the connected terminal.
After installing the updated debug build on this C9D, calling the app's
openCashDrawer() wrapper twice concurrently returned [true, false]: one
command was sent through the native socket, and the immediate duplicate was
suppressed. Terminal typecheck, 56 payment/native-wrapper tests, Kotlin compile,
and Android build/install passed. This test did not create a payment transaction.
Safety notes
- Testing the command can physically open the drawer.
- Ask the operator before running drawer tests on a live terminal.
- Avoid repeated rapid pulses. Add debounce/rate limiting in app code.
- Do not assume every POS terminal has the same helper app or GPIO path. Check the Android model and installed packages before enabling direct Telpo mode.
Useful ADB commands
Identify the connected POS device:
adb devices
adb -s A65C009P00400034 shell getprop ro.product.manufacturer
adb -s A65C009P00400034 shell getprop ro.product.model
adb -s A65C009P00400034 shell getprop ro.build.display.id
adb -s A65C009P00400034 shell getprop ro.build.version.release
Inspect helper packages:
adb -s A65C009P00400034 shell pm list packages
adb -s A65C009P00400034 shell dumpsys package com.cpos.helper
adb -s A65C009P00400034 shell pm path com.cpos.helper
Inspect printer and scanner USB devices:
adb -s A65C009P00400034 shell dumpsys usb
adb -s A65C009P00400034 shell dumpsys package com.boonsiri.printerconfig