michaelrsweet / pappl

PAPPL - Printer Application Framework
https://www.msweet.org/pappl
Apache License 2.0
309 stars 49 forks source link

USB connection only uni-directional #153

Closed tillkamppeter closed 3 years ago

tillkamppeter commented 3 years ago

In my PostScript Printer Application I use printer functionality which requires bi-directional communication. This functionality is querying the printer for default settings (what in CUPS is done by the commandtops filter). This works perfectly for me when I connect to the printer via network (both the DNS-SD- and SNMP-based device URIs work) but not when I connect via USB. If I set up the printer with the USB device URI I can only use the uni-directional functionality (printing and identifying the printer) but not the bi-directional functionality (querying the presence of installable accessories and defaults of options). The printer receives the query jobs but there is simply no answer comming back. The Printer Application waits 10 seconds, then times out, tries the next query, ... For none of the queried options an answer arrives.

I could not test with ink level queries as these are not yet supported (issue #83), but they will probably also not work via USB.

Perhaps PAPPL connects to the 7/1/1 interface and not to the 7/1/2 interface.

ipp-usb is not running, I have stopped it and checked that there is no process of it. After that I have restarted the (non-snapped) Printer Application.

The problem occurs for both the snapped and the non-snapped PostScript Printer Application.

Here is a log file (logging of PPD repository indexing removed): ps-printer-app-log-usb-unidirectional-20210221.txt

Printer is the HP OfficeJet Pro 8730 (It has bi-directional USB, as a 7/1/2 interface is available).

michaelrsweet commented 3 years ago

@tillkamppeter Can you attach the output from "lsusb -v" when the printer is connected?

tillkamppeter commented 3 years ago

Here we go. ipp-usb is not running, output is of sudo lsusb -v: sudo-lsusb-v-20210222.txt

tillkamppeter commented 3 years ago

Note that the fix of issue #156 did not fix this issue. The USB printers still get set up with only uni-directional access.

michaelrsweet commented 3 years ago

@tillkamppeter It looks like it should detect the bidirectional interface and use it. The printer doesn't have any 7/1/1 interfaces so I'm puzzled as to the cause here... Can you try changing the read timeout in device-usb.c to 10 seconds, e.g.:

diff --git a/pappl/device-usb.c b/pappl/device-usb.c
index d19a684..c530e33 100644
--- a/pappl/device-usb.c
+++ b/pappl/device-usb.c
@@ -607,7 +607,7 @@ pappl_usb_read(pappl_device_t *device,      // I - Device
   int                  error;          // USB transfer error

-  if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->read_endp, buffer, (int)bytes, &icount, 100)) < 0)
+  if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->read_endp, buffer, (int)bytes, &icount, 10000)) < 0)
   {
     papplDeviceError(device, "Unable to read from USB port: %s",  libusb_strerror((enum libusb_error)error));
     return (-1);

It's possible the printer just can't respond within 100ms...

tillkamppeter commented 3 years ago

I have tried it out (with unsnapped ps-printer-app) and it still does not work. Log output: usb-bi-directional-bug-20210414.txt

michaelrsweet commented 3 years ago

OK, try this patch:

diff --git a/pappl/device-usb.c b/pappl/device-usb.c
index d19a684..5adeb1e 100644
--- a/pappl/device-usb.c
+++ b/pappl/device-usb.c
@@ -261,9 +261,9 @@ pappl_usb_find(
        device->protocol   = altptr->bInterfaceProtocol;
        device->altset     = altptr->bAlternateSetting;
        device->ifacenum   = altptr->bInterfaceNumber;
-       device->write_endp = write_endp;
+       device->write_endp = altptr->endpoint[write_endp].bEndpointAddress;
        if (device->protocol > 1)
-         device->read_endp = read_endp;
+         device->read_endp = altptr->endpoint[read_endp].bEndpointAddress;
      }
    }

@@ -607,9 +607,12 @@ pappl_usb_read(pappl_device_t *device, // I - Device
   int          error;      // USB transfer error

-  if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->read_endp, buffer, (int)bytes, &icount, 100)) < 0)
+  if (usb->read_endp < 0)
+    return (-1);
+
+  if ((error = libusb_bulk_transfer(usb->handle, (unsigned char)usb->read_endp, buffer, (int)bytes, &icount, 10000)) < 0)
   {
-    papplDeviceError(device, "Unable to read from USB port: %s",  libusb_strerror((enum libusb_error)error));
+    papplDeviceError(device, "Unable to read from USB port: %s", libusb_strerror((enum libusb_error)error));
     return (-1);
   }
   else
tillkamppeter commented 3 years ago

Tried also this and it is even worse. Printer detected and set up, but when polling installable options the printer does not even make the noise to say that it has received the commands. Log file (of printer creation and of poll): usb-bi-directional-bug-20210414-2.txt

tillkamppeter commented 3 years ago

Update: Running the Printer Application as root the printer makes the noise of having received the commands, so writing to the printer works, but reading from the printer does not work, no data is coming back within 10 seconds (reading every 100 msec), no error message from pappl_usb_read(). Log file (only poll but with DEBUG=1): usb-bi-directional-bug-20210414-3.txt

tillkamppeter commented 3 years ago

Another update: Thee bug seems to be in the printer, not in PAPPL.

I did the following:

For development of the PostScript Printer Application I hacked the original PPD file for my HP OfficeJet Pro 8730 (from HPLIP) with query code of the PPDs of some older LaserJet printers. With this PPD and the PostScript Printer Application I can actually query my printer, but only if it is connected via Socket/JetDirect (port 9100), not via USB. Therefore I opened this issue.

The PPD is here: hp8730ps-query-en.ppd.txt

Now I tested with CUPS:

lpadmin -p commandtops-test -E -v 'usb://HP/OfficeJet%20Pro%208730?serial=CN783F60W1&interface=1' -P hp8730ps-query-en.ppd.txt
echo -en '#CUPS-COMMAND\nAutoConfigure\n' | lp -d commandtops-test

According to error_log the commands got sent (printer also made the noise of receiving a job, but did not print anything, and after some time the job-proccessing information on the front panel disappeared) but none of the commands produced an answer from the printer. No USB I/O errors, too.

In the PostScript Printer Application I also only get timeouts, no USB I/O errors.

So I recommend that you test this feature with another USB printer, preferably not HP.

tillkamppeter commented 3 years ago

Note that this part of your second suggested patch is wrong:

diff --git a/pappl/device-usb.c b/pappl/device-usb.c
index d19a684..5adeb1e 100644
--- a/pappl/device-usb.c
+++ b/pappl/device-usb.c
@@ -261,9 +261,9 @@ pappl_usb_find(
        device->protocol   = altptr->bInterfaceProtocol;
        device->altset     = altptr->bAlternateSetting;
        device->ifacenum   = altptr->bInterfaceNumber;
-       device->write_endp = write_endp;
+       device->write_endp = altptr->endpoint[write_endp].bEndpointAddress;
        if (device->protocol > 1)
-         device->read_endp = read_endp;
+         device->read_endp = altptr->endpoint[read_endp].bEndpointAddress;
      }
    }

You already replace the endpoint indices in device->write_endp and device->read_endp by the actual endpoint addresses later in the code, near line 436:

if (device->read_endp != -1)
                device->read_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device>read_endp].bEndpointAddress;

if (device->write_endp != -1)
                device->write_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device>write_endp].bEndpointAddress;

Replacing the endpoint indices twice makes things completely break, with the commands even not making it into the printer (and also no printing).

The extension of the timeout and exiting from the read function when there is no read endpoint is OK, and I think we should do it even if we cannot prove with my printer whether it makes things better or not.

michaelrsweet commented 3 years ago

@tillkamppeter OK, I've pushed some minor changes for the timeout and a new "--ps-query DEVICE-URI" option for the testpappl program that lets me test a simple PostScript query (to get the product string). Seems to work OK with my Lexmark and HP printers with PostScript support.

michaelrsweet commented 3 years ago

Closing this now; works for me with the printers I have available...