In this post, I’ll step through how to get a thermal receipt printer with USB interface appearing on Linux. The aim of this is to be able to point a driver such as escpos-php at the device. The printer used here is an Epson TM-T20, which is very common in point-of-sale environments.
The directions below are for Debian, but could be adapted for any other Linux.
Find the device file
Plug in your printer, and check that
usblp sees it:
dmesg [12724.994550] usb 8-4: new full-speed USB device number 5 using ohci-pci [12725.168956] usb 8-4: New USB device found, idVendor=04b8, idProduct=0e03 [12725.168963] usb 8-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [12725.168968] usb 8-4: Product: TM-T20 [12725.168971] usb 8-4: Manufacturer: EPSON [12725.168975] usb 8-4: SerialNumber: .... [12725.175114] usblp 8-4:1.0: usblp1: USB Bidirectional printer dev 5 if 0 alt 0 proto 2 vid 0x04B8 pid 0x0E03
This kernel module makes your printer visible as a device file, so that it can be accessed in the old-fashioned way. Find the new device file under
In my case, this was
/dev/usb/lp1. The next step is to see if you can write to it:
echo "Hello" >> /dev/usb/lp1
Chances are, you will get a permission denied error at this point, so find out what group the printer is in:
Which will show output something like:
File: ‘/dev/usb/lp1’ Size: 0 Blocks: 0 IO Block: 4096 character special file Device: 5h/5d Inode: 220997 Links: 1 Device type: b4,1 Access: (0660/crw-rw----) Uid: ( 0/ root) Gid: ( 7/ lp)
This file is owned by group
lp (“line printer”). If your username was
bob, you would add yourself to this group using:
sudo usermod -a -G lp bob
If you plan to build a web-based point-of-sale system with this, then also add the
www-data user to that group.
Now log out and back in, and the previous test should now be working:
echo "Hello" >> /dev/usb/lp1
If these steps don’t work, then your computer ether doesn’t have, or isn’t using
usblp. You’ll need to check a few things:
- Install a different linux-image if the driver is not on your computer at all.
- blacklist a vendor driver which has claimed the interface.
Printing something useful
As a duplicated section from my earlier post, the printer uses ESC/POS, which means it accepts plaintext with some special commands for formatting.
A simple receipt-generator,
foo.php, might look like this:
<?php /* ASCII constants */ const ESC = "\x1b"; const GS="\x1d"; const NUL="\x00"; /* Output an example receipt */ echo ESC."@"; // Reset to defaults echo ESC."E".chr(1); // Bold echo "FOO CORP Ltd.\n"; // Company echo ESC."E".chr(0); // Not Bold echo ESC."d".chr(1); // Blank line echo "Receipt for whatever\n"; // Print text echo ESC."d".chr(4); // 4 Blank lines /* Bar-code at the end */ echo ESC."a".chr(1); // Centered printing echo GS."k".chr(4)."987654321".NUL; // Print barcode echo ESC."d".chr(1); // Blank line echo "987654321\n"; // Print number echo GS."V\x41".chr(3); // Cut exit(0);
And you would send it to the printer like this:
php foo.php > /dev/usb/lp1
Scaling this up
The codes are quite tricky to work with manually, which is why I put together the escpos-php driver. You can find it at:
The above example would be written using escpos-php as:
<?php require __DIR__ . '/autoload.php'; use Mike42\Escpos\Printer; use Mike42\Escpos\PrintConnectors\FilePrintConnector; $connector = new FilePrintConnector("/dev/usb/lp1"); $printer = new Printer($connector); /* Print some bold text */ $printer -> setEmphasis(true); $printer -> text("FOO CORP Ltd.\n"); $printer -> setEmphasis(false); $printer -> feed(); $printer -> text("Receipt for whatever\n"); $printer -> feed(4); /* Bar-code at the end */ $printer -> setJustification(Printer::JUSTIFY_CENTER); $printer -> barcode("987654321"); $printer -> cut(); ?>
This would be sent to the printer by loading it from the web, or running the script on the command-line: