Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB connection only uni-directional #153

Closed
tillkamppeter opened this issue Feb 21, 2021 · 12 comments
Closed

USB connection only uni-directional #153

tillkamppeter opened this issue Feb 21, 2021 · 12 comments
Assignees
Labels
unable-to-reproduce Unable to reproduce

Comments

@tillkamppeter
Copy link
Contributor

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
Copy link
Owner

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

@michaelrsweet michaelrsweet self-assigned this Feb 22, 2021
@michaelrsweet michaelrsweet added the investigating Investigating the issue label Feb 22, 2021
@tillkamppeter
Copy link
Contributor Author

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

@tillkamppeter
Copy link
Contributor Author

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
Copy link
Owner

@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
Copy link
Contributor Author

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
Copy link
Owner

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Copy link
Contributor Author

tillkamppeter commented Apr 14, 2021

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
Copy link
Contributor Author

tillkamppeter commented Apr 14, 2021

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
Copy link
Owner

@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
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unable-to-reproduce Unable to reproduce
Projects
None yet
Development

No branches or pull requests

2 participants