1

We're switching to a system where our shippers need to put barcodes with our article IDs on the products they're sending henceforth. Our management is willing to lend them Brother TD-4100N label printers under the condition that they do not use it for other purposes other than printing our barcodes, and now I'm tasked with programming an interface that allows them to print our barcodes.

Their core competency however lies in shipping management, not IT administration, and so I have to keep things simple and platform-independent - or at least as platform-independent as possible. The idea here is to be able to plug in one of those printers via ethernet without any kind of setup - as simple as possible. No drivers, no nothing, keep it simple, stupid. An ethernet port and sockets is all I wanna use. And with this specific model having an ethernet port and accepting ESC/P codes that shouldn't be so hard, right?

After spending a week with one test machine I've learnt enough about the ESC/P codes and Brother's proprietary extensions (at least they claim them to be) to write a little framework in C. Printing barcodes in the required format (Code128) doesn't pose a problem in and of itself, but the bookkeeping around it does; I'm at my third manual at this point that claims that simply sending the command "\x1B\x69\x53" (ESC i S) should cause the printer to send me a 32-byte record of its current status, but for some reason the printer simply doesn't want to send me how it's doing:

char buffer_send[] = "x1B\x69\x53";
send(sock_jet,buffer_send,sizeof(buffer_send) - 1,0);

char buffer[32];
memset(buffer,0,sizeof(buffer));
recv(sock_jet,buffer,sizeof(buffer),0);

fprintf
(
    stderr,
    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
    buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]
);
fprintf
(
    stderr, 
    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
    buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]
);
fprintf
(
    stderr,
    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
    buffer[16],buffer[17],buffer[18],buffer[19],buffer[20],buffer[21],buffer[22],buffer[23]
);
fprintf
(
    stderr,
    "%02x%02x%02x%02x%02x%02x%02x%02x\n",
    buffer[24],buffer[25],buffer[26],buffer[27],buffer[28],buffer[29],buffer[30],buffer[31]
);

This code simply stalls for some time until timeout hits or whatever, and recv doesn't write any data into my buffer:

0000000000000000
0000000000000000
0000000000000000
0000000000000000

And I'm apparently not the only one with such a problem. This Ruby Python package (https://pypi.org/project/brotherprint/#files) claims to be specifically catered for Brother printers, but I never see them receive any data (in brotherprint/brotherprint.py at least). In fact I don't even see them spelling "receive" correctly.

On SO (operating printer with php socket programming) someone tried to do the same in PHP I'm trying to do in C - and they had the exact same problem as I'm having, with the printer refusing to give them status data. The solution seems to involve switching from port 9100 to port 515 and using a different protocol, and while I've seen port 515 to be open on the printer I've never seen any output from that printer, on paper or on the socket. At this point I'd contact the Brother support, but I'm already having another ticket open because another printer of their's does seem to have major problems sending status reports back to CUPS.

I've tried adding a NUL byte at the end of my payload, in case the printer is waiting for a page feed, but that didn't do the trick either. Again: printing barcodes to the damn thing works, so IP, port, and connection work at least to a degree - but receiving a status report doesn't.

The strace from my program:

connect(3, {sa_family=AF_INET, sin_port=htons(9100), sin_addr=inet_addr("192.168.XXX.XXX")}, 16) = 0
sendto(3, "\33iS", 3, 0, NULL, 0)       = 3
recvfrom(3, <blocks here for minutes> "", 32, 0, NULL, NULL)      = 0
write(2, "0000000000000000\n", 170000000000000000
)      = 17
write(2, "0000000000000000\n", 170000000000000000
)      = 17
write(2, "0000000000000000\n", 170000000000000000
)      = 17
write(2, "0000000000000000\n", 170000000000000000
)      = 17
close(3)

And the main manual that I'm using: https://download.brother.com/welcome/docp000579/cv_td4000_eng_escp_120.pdf (search for "ESC i S").

j_d
  • 21
  • 5
  • Well, despite better judgement I've been emailing the Brother support. They told me that they ain't really got any clue what to do about this, but have been relaying my mail to Japan, where it will probably be misunderstood because language barrier (I've been mailing in my native toungue, which isn't exactly easy to translate from into Japanese), ignored and then picked up after a long time. They are likely to siliently fixed the issue, then silently release a firmware update, which I'm going to ignore because it's been too long, and I'll keep telling people that it's a hardware issue. – j_d Jan 22 '19 at 13:08

1 Answers1

1

OK, so I actually got a response from the Japanese Brother support. And there is so much wrong with that response that I may come off as rambling a little right now.

Brother insists that

ESC/P is not supposed to be for bi-directional communications.

, which is a load of steaming BS seeing as Brother MADE their implementation bi-directional. That is what the documentation says! Read it for yourself in the ESC/P documentation they provide.

Requests the printer status. The printer status comprises 32 bytes.

So I've already caught them either lying or being incompetent.

The next lie/being incompetent is:

Namely what you have reported is within our specifications.

I'd have LOVED to actually see those specifications they've quoted here. The only thing I've found so far was section 5 "Additional Functions" in my manual, which has a paragraph called "ESC/P commands" in which they link to the aforementioned ESC/P manual. This manual specifically states:

This information is provided assuming that the user has full understanding of the operating system being used and basic mastery of RS-232C, USB or Ethernet in a developer's environment.

In section 8 "Using Interface Cables" they state that RS-232C (serial) and RJ-45 (ethernet) cables are not standard accessories, and that it's not possible to connect a RS-232C and a USB cable to the same printer at the same time. Then there are some installation instructions on MS Windows computers, and that's about it.

Their FAQ doesn't mention anything (https://www.brother.co.jp/eng/dev/command/faq/index.aspx) except for using SNMP (which doesn't work on this printer because Port 161/162 are not even open), and their network reference is just as mute (https://download.brother.com/welcome/docp000592/cv_td2130n_eng_net.c.pdf - not one mentioning of ESC/P). I'm seriously wondering if I'm too stupid to find this, or if they pulled that one out of their ar**s just to not have to deal with this.

And don't tell me they wouldn't do this. This printer also runs a webserver on port 80 that has a confirmed secvuln (https://threatpost.com/tag/debut-embedded-web-server/).

But then they actually get to the core of the issue here:

Besides, our specification never ruturns when using Netwrokd even if an error does not happen

This little part of Engrish here is probably supposed to mean:

Even if an error occurs our hardware does not send status reports over ethernet.

, which would explain why the printer remains silent. However I don't believe this is part of their specification, which I couldn't even find; I believe they got caught with their pants down yet again and refuse to acknowledge it. It shouldn't make any difference how you connect to the machine - ethernet, serial, or USB - as long as the transport layer works, which obviously is the case since I can send other commands to the printer. However this is supposed to be used on different machines on the same network. Why do they even have an ethernet port if the firmware is unable to send a status report? Who came up with this idea?

I can honestly only discourage people from getting Brother devices. This is the second printer I've seen from this company that simply doesn't work over ethernet, and what good is a printer if you cannot query its status to determine if you're to send a job to it? And they sell those unreliable machines for 600 € apiece.

j_d
  • 21
  • 5