Emulated_USB_Printer icon indicating copy to clipboard operation
Emulated_USB_Printer copied to clipboard

Troubles printing data

Open alassaneg opened this issue 4 years ago • 33 comments

Hello,

First of all, thank you for your projects, it helps me a lot moving forward on my project. Now, i'm having some issus printing data from my computer to the raspberry. So, i've well followed the tutorial and my computer recognize the rasperry as a printer (in my case, i'm emulating a HP laserjet P1005). When i launch the printing, the file goes to the printing queue and then nothing happens....I just receive the following characters : 12345x @PJL ENTER LANGUAGE=ACL (seems to be an hp command). While testing this, did you have to send some kind of acknowledgment to the computer to start the printing?

Thank you in advance for your help.

alassaneg avatar Feb 04 '21 18:02 alassaneg

Hi,

If I remember correctly, I had similar issues with a different printer (Xerox maybe), when it was recognized correctly but wouldn't sent the print job. I never tried solving it. Also, I needed to send back data to PC. The original example of the gadget api contains a method for sending back data to the host (here).

If you really need to stick to the HP P1005 and keep the current driver you might want to use the USB traffic analyzer again: Start capturing traffic, connect a real HP P1005, send a very simple print job (empty page or one char) and check if your printer sends data on the BULK IN endpoint. If so, you can try copying that communication by sending the same data as the printer did. BUT this potentially requires an exact emulation of the original interface. The Raspberry Pi emulates an Endpoint 1 Bulk IN and Endpoint 1 Bulk OUT interface. If the original interface uses 1 Bulk OUT and 2 Bulk IN you might need to build your own version of the g_printer module (wouldn't want to that!).

If you have access to the computer the pi is connected to, you can also try changing the drivers manually. That gives you the ability to for example select the Generic Text-Only driver on Windows which makes it much easier to work with the received data.

If you don't need to emulate that exact printer, try different ones! The foomatic DB contains almost 4000 printers. The most models I got working were Ricoh Postscript printers. Check the Makefile for good examples.

It would be really cool if you can share the parameters for your HP LaserJet P1005 and any other printer you get working :)

Attached is a file which I got from a HP1220 emulation. maybe this helps. hp1220_example.txt

Raspberryy avatar Feb 04 '21 19:02 Raspberryy

Actually i don't have to stick with the HP 1005, i just took it randomly, but at the end i will have to stick with a HP or Epson printer. I just haven't found the parameters for the printers i want to emulate.

For now, i've tried to emulate 3 different model and i can't get them working so i'll try to emulate a ricoh one as you suggest. And i need to get myself a HP printer so i can try to analyze the USB traffic, if i can't find the information online. And hopefully, i won't have to develop my own driver! But i actually don't think that the printer needs to send data to the computer. For example, HP uses the PJL (printer job language) to allow ones developping it's own application to communicate with the printer and return datas are not mentionned in the manual so the problem seems to be somewhere else, but i'll confirm that once i have a printer.

And actually, the HP LaserJet P1005 parameters are already in the PNP file you provided, i took it from there.

Thank you for your answer, it really helps!

alassaneg avatar Feb 04 '21 22:02 alassaneg

How are you going to process the received print jobs? I found, that GhostPDL isn't an optimal solution for converting PCL, which HP printers are most likely to have. That is another reason why used Ricoh printers. The best HP printer I found was the HP 1220. GhostPDL was able to convert it to readable PDF, but not able to extract the text.

Also be sure you have the correct VendorID and ProductID. I am not 100% sure but I think you need to set the HEX parameters with uppercase letters. so for HP use idVendor=0x03F0 and not idVendor=0x03f0.

Again, if you have access to the Host, e.g. the computer the pi is connected to, you can simply change the drivers manually. That way you don't need to stick with PCL, ACL, EPS or ESC. I would suggest you use a PostScript printer if you want to extract data from the print jobs!

Raspberryy avatar Feb 05 '21 06:02 Raspberryy

Actually, right now, i just want to check if i'm able to receive a print job whether it is PCL, ACL or anything else...So i'm not going to process anything right now. But at the end, i'll most likely have to stick with ESC/P printers and i'm planning on processing the received print jobs with the following tool : https://github.com/receipt-print-hq/escpos-tools . I might adapt it to your code.

Got it regarding the uppercase letters, i'm already using them.

I didn't know that changing the driver was an option so thank you for the info. I thought that one printer could work with a unique driver : the vendor driver.

alassaneg avatar Feb 05 '21 12:02 alassaneg

If you connect the real printer you will of course need the actual driver. So, if you are planning to forward the print job to the real printer someday you might want to stick to the real driver.

Are you now able to emulate a printer and receive some data? I didn't quite catch that.

Raspberryy avatar Feb 05 '21 13:02 Raspberryy

Right now, i'm just checking if the g_printer is working. I've tried to emulate the Ricoh Aficio SP35010SF but still not able to receive the print job... Could you tell me which printer you've used that work?

alassaneg avatar Feb 05 '21 13:02 alassaneg

All listed in the Makefile (except the Kyocera FS1020D) were detected by my Windows 10 PC. The Ricoh printers worked best. Do you get any error message? Do you still only receive a few lines?

I mentioned this in a different Issue but maybe this is your problem as well: The printer.c contains functions for setting three parameters: Paper Loaded/Paper Out, Error/ No Error, and Selected / Not selected. The correct status is Selected, Paper Loaded, No Error. Confirm that this is the case for you by running emulatedprinter -get_status. Change values if needed (See emulatedprinter -h).

Whats your host? What are you using to print? What drivers are currently loaded? What do you receive?

Raspberryy avatar Feb 05 '21 14:02 Raspberryy

I don't get any error messages. Actually, i tried again and it seems to work well. I first tried to print this page but its a complicated one so i opened word and tried to print a single white page and it worked well, finally!

Now that the driver and the code are working, i need to get my self an ESC/P printer and it's pnpString (hard to find online so I might buy one).

I still need to figure out what is going on with these other printers. HP and epson don't mention any return values from the printer to the host in their commands reference manual... I really appreciate your help.

alassaneg avatar Feb 05 '21 16:02 alassaneg

If you share I little mor of your setup, maybe we can help :) If you ever publish your project, keep me updated, I am really interested in seeing how people use this repo!

Raspberryy avatar Feb 08 '21 15:02 Raspberryy

I finally got myself an epson TM-T88V printer. For some reason, it doesn't have a pnp number. I didn't see it with usblyzer but i was able to get the vendor and product ID and after installing manually the driver, the printer work. Then, when trying to emulate it, it's not working. Windows can see the emulated printer but it's considered as unavailable. Actually the TM-T88V doesn't seem to act as a normal printer. When i plug it, the printer doesn't appear in the printer tree of the peripheral manager... So the conclusion is that i don't think the gadget_printer driver can handle that POS printer.

alassaneg avatar Feb 12 '21 12:02 alassaneg

Thats weird :/ You can share the USBlyzer capture file, maybe I can help you :)

Raspberryy avatar Feb 12 '21 12:02 Raspberryy

TM-88V_LOG.zip

The file is right here!

alassaneg avatar Feb 12 '21 14:02 alassaneg

Looks like the best solution is getting started on building your own version of the g_printer module. It looks quite similar to the emulated interface of the g_printer module (e.g. same Endpoints), but the interface descriptor is different. You might simply need to change bInterfaceClass and the bInterfaceSubClass for your version of the g_printer module. Sadly I never needed to build a custom version and currently I don't really have the time to get into this.

But hey, that might be a cool project!

Raspberryy avatar Feb 12 '21 15:02 Raspberryy

That was my concern but anyway, i'll still have to give a try then! I'll have to go deep in the g_printer and i'll try to modify it.

Thanks again for your help

alassaneg avatar Feb 15 '21 21:02 alassaneg

Hello,

I'm back for one more question for you! First of all, i was using the TM88 printer using the vendor device class and i was able to change it using the printer class by changing one option in the printer utility software. I then figured out that the driver was sending vendor specific request to the printer so i had to modify and rebuild the g_printer driver so he knows about these vendor request but unfortunately, i was still unable to catch the data using g_printer. So, i switched to the generic/text only driver and it works perfectly when using the TM88 printer but once again, doesn't work with g_printer... Have you ever tried to use g_printer using the generic text only driver?

alassaneg avatar Mar 08 '21 19:03 alassaneg

Yes, I did. Generic Text Only were my first attempts and worked perfectly fine. Do I understand correctly, that you compiled your own kernel module, aka "rebuild the g_printer"? Or did you adjusted the code talking to /etc/g_printer? Also, your last sentence is at least for me a little bit confusing. Do you refer to the emulated model?

Raspberryy avatar Mar 08 '21 20:03 Raspberryy

No, i've just added a few lines to the driver source code ( https://elixir.bootlin.com/linux/v5.4.41/source/drivers/usb/gadget/function/f_printer.c ) and recompiled it. Regarding the last sentence, indeed, i emulated the TM88V printer and tried to use it with the Generic Text Only and it was not working... What is the model of the printer you've emulated to make it work with the Generic Text Only ?

alassaneg avatar Mar 08 '21 21:03 alassaneg

I was able to use multiple printers with the Generic Text Only. All I did was

  1. Find parameters for g_printer module by looking at the enumeration of a real printer/looking in the FoomaticDB
  2. Connecting the Pi to a PC
  3. Starting g_printer with needed parameters
  4. Confirm PC detects Pi as the printer model that needs to be emulated
  5. Go to Printer Settings on PC
  6. Manually change driver to Generic Text Only
  7. Run printer.c from this repository
  8. Print on PC

That way the PC uses the Text Only driver. For printing I only used MS Word and notepad.exe. Maybe the programm you are using to print does not accept the drivers..?

Raspberryy avatar Mar 09 '21 09:03 Raspberryy

Ok now it's working. So what i did first was: 1- Pluging the TM88 printer 2- Add a new printer 3- use the generic/text printer 4- print That worked perfect.

After that, i unplugged the printer and i : 5- loaded g_printer 6- Plugged the embedded linux (not raspberry in my case but an atsama5d27 sm1 ek) 7- Launche printer.c and tried to print to the embedded linux but it doesn't seem to be fully recognize as a tm88 printer so i repeated steps 2 to 4 and added once again a new printer and then it worked.

So, it's not really what i want because for my final product, i'm going to use a usb hub to redirect the printjob to the embedded linux or to the printer so i need windows to believe that my embedded linux board is a real tm88 printer so i need to figure out what is going on!

alassaneg avatar Mar 09 '21 14:03 alassaneg

Awesome. My guess would still be that something in the descriptors/Device ID is wrong. Did you see that the g_printer module trims the device ID? E.g. when ipnpstring="12345", the g_printer module will send "123", so you might need to call the module with "12345 " ("12345" + 2 spaces).

Raspberryy avatar Mar 11 '21 08:03 Raspberryy

I just took a look at the usblyzer logs and indeed, the two last characters of the pnp string are missing, i'd have never noticed that so thanks a lot for the info! How did you notice that? I'll make more test tomorrow when i'll have access to the printer. But when using the ricoh aficio pnp string without leaving a sapce at the end it was working, but i'll make sure that the issue is still coming from that pnp string.

alassaneg avatar Mar 11 '21 14:03 alassaneg

I can't remember when or how I noticed that. My first thought was, maybe USBlyzer is wrong, because all printer models worked just fine without the double spaces. Maybe Windows only parses MFG and MDL, so it doesn't matter if CMD is formatted correctly or not. But this is just a guess. I would be curious if this would solve one of your problems.

Raspberryy avatar Mar 12 '21 11:03 Raspberryy

It'ill probably solve one of my issue, i'll let you know as soon as i can test this. I also noticed something "interesting". The tm88 printer driver sends periodically an "in 66048 bytes bulk transfer" to the gadget driver. Everytime, it fails. The ricoh printer driver sends periodically an "in 512 bytes bulk transfer" to the gadget driver and it's a success everytime. So right now, i'm looking at the bulk capabilities of the gadget driver.

alassaneg avatar Mar 12 '21 13:03 alassaneg

New updates! I figured out that i needed to set the iManufacturer and iProduct so windows could then recognize the embedded linux as the real printer and load th driver as if it was the TM88V that was plugged in the computer. However, the bulk in request stilll fail and i'm still investigating on that.

alassaneg avatar Mar 20 '21 20:03 alassaneg

So you are increasing buffers to recreate the message?

Raspberryy avatar Mar 27 '21 18:03 Raspberryy

So, i did it, i increased the buffer size but it's still not working. I still need to resolve this, but for now, i installed the gadget printer manually on windows and in the printer parameters, i've selected the espon APD5 driver and i'm able to receive the printer datas on linux. It's not exaclty what i want, but it's gonna be ok for now. But i'm still not done with this bulk transfer issue, i really need to understant what is going on.

alassaneg avatar Mar 27 '21 19:03 alassaneg

So, i did it, i increased the buffer size but it's still not working. I still need to resolve this, but for now, i installed the gadget printer manually on windows and in the printer parameters, i've selected the espon APD5 driver and i'm able to receive the printer datas on linux. It's not exaclty what i want, but it's gonna be ok for now. But i'm still not done with this bulk transfer issue, i really need to understant what is going on.

Did you get any further with the TM88V being recognised?

I have actually written a little bit of code which waits until an ESC character is received (which indicates the start of an ESC/POS sequence). Anything received up until then is echoed to the USB printer, and the response is captured and sent back through the gadget printer to the host PC.

This should work in theory, but Windows still does not recognise the gadget printer as the TM88V.

RWAP avatar Aug 02 '21 11:08 RWAP

@RWAP any chance you could share the code? Would be super interested to see it!

bcheidemann avatar Aug 06 '21 12:08 bcheidemann

So, i did it, i increased the buffer size but it's still not working. I still need to resolve this, but for now, i installed the gadget printer manually on windows and in the printer parameters, i've selected the espon APD5 driver and i'm able to receive the printer datas on linux. It's not exaclty what i want, but it's gonna be ok for now. But i'm still not done with this bulk transfer issue, i really need to understant what is going on.

Did you get any further with the TM88V being recognised?

I have actually written a little bit of code which waits until an ESC character is received (which indicates the start of an ESC/POS sequence). Anything received up until then is echoed to the USB printer, and the response is captured and sent back through the gadget printer to the host PC.

This should work in theory, but Windows still does not recognise the gadget printer as the TM88V.

No, i'm still not able to get windows recognize the gadget printer as the TM88V. As i said, my workaround was to manually install the gadget printer and then to select the APD5 driver in the printer options.

alassaneg avatar Aug 06 '21 12:08 alassaneg

Hi, I am curious, why are all of you interested in the TM88V? Is there anything special about that printer?

Raspberryy avatar Aug 19 '21 17:08 Raspberryy