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.
I have previously written quite a bit about how to use thermal receipt printer protocols, but the previous printer I covered had only a network interface, not USB like this one:
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 /dev/usb:
ls /dev/usb
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:
stat /dev/usb/lp1
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
Troubleshooting: Check usblp
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.
- modprobe or insmod usblp
- blacklist a vendor driver which has claimed the interface.
- run lsusb -v and usb-devices (look for driver=)
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:
php foo2.php