Open speachy opened 3 years ago
Hi Solomon,
actually, ipp-usb uses all available interfaces, but first request always sent to the first interface. At this case, first request fails, so ipp-usb runts reset/retry loop.
Are you able to build ipp-usb by youself? If so, could you please try the latest github version?
Hmm, building and running directly out of the git repo yields an endless loop of:
! PNP Bus 003 Device 017: libusb_get_device_descriptor: Pipe error
+ PNP Bus 003 Device 017: retry
Please update and try again
Post-update:
! PNP Bus 003 Device 017: libusb_get_descriptor(0x21): Pipe error
+ PNP Bus 003 Device 017: retry
It seems that the commit (10450463) only changes a string, rather than making any logic changes?
EDIT: I'm compiing and running ' ./ipp-usb debug' -- that's the totality of the console logging message.
bisecting between the 0.9.19 and master shows "nothing but pipe errors" started with commit 971f06606b7fa8ee4725a41d7d
EDIT: pasted the wrong commit.
Ok, the current problem is that you're looking at the top-level interface descriptor type (which is 0x04, ie "DT_INTERFACE"), not the class-specific descriptor. This information is not directly exposed via libusb -- you'll have to manually decode it using the 'extra' and 'extra_length' fields in the interface descriptor.
Here's an example of how to do this -- see https://github.com/gregkh/usbutils/commit/657da96106d17ef64d9a17420e1b98bd828b7d35
Yes, the previous patch only changed string in the log, to localize the problem (I onerously used the same string in two different places).
I'm actually trying to request class-specific descriptor from device, using libusb_get_descriptor
and device refuses the requests. This is in usbio_libusb.go
, line 528
Does usbutils
correctly decode class-specific descriptor for your device?
Yes, ubutils works fine -- I originally wrote that patch for this very CP1200. :)
The problem is that you're asking for a device descriptor; whereas the class-specific stuff is tacked onto the end of interface descriptors -- ie 'alt' on line 243. with devhandle you can find out the current interface/altsetting, and walk the full config descriptor chain again to find the interface descriptor you need... or instead, run UsbIppBasicCaps() at the time you're probing things in libusbBuildUsbDeviceDesc() and stash the results?
Full lsusb -v output for the device:
Bus 003 Device 017: ID 04a9:32b1 Canon, Inc. SELPHY CP1200
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x04a9 Canon, Inc.
idProduct 0x32b1 SELPHY CP1200
bcdDevice 0.01
iManufacturer 1 Canon
iProduct 2 SELPHY CP1200
iSerial 3 ZT15120100000091
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x006b
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 2mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 7 Printer
bInterfaceSubClass 1 Printer
bInterfaceProtocol 2 Bidirectional
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 1
bNumEndpoints 2
bInterfaceClass 7 Printer
bInterfaceSubClass 1 Printer
bInterfaceProtocol 4
iInterface 0
IPP Printer Descriptor:
bLength 10
bDescriptorType 33
bcdReleaseNumber 1
bcdNumDescriptors 1
iIPPVersionsSupported 0
iIPPPrinterUUID 0
wBasicCapabilities 0x0011 Print HTTP-over-USB No-Auth
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 2
bInterfaceClass 7 Printer
bInterfaceSubClass 1 Printer
bInterfaceProtocol 4
iInterface 0
IPP Printer Descriptor:
bLength 10
bDescriptorType 33
bcdReleaseNumber 1
bcdNumDescriptors 1
iIPPVersionsSupported 0
iIPPPrinterUUID 0
wBasicCapabilities 0x0011 Print HTTP-over-USB No-Auth
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x05 EP 5 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x86 EP 6 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
bNumConfigurations 1
Device Status: 0x0001
Self Powered
I understand the idea and basically agree. The problem is that the next few days I will not have access to my printer, to test the changes.
For now, you can temporary hack the usbIppBasicCaps
to always return UsbIppBasicCapsPrint | UsbIppBasicCapsScan | UsbIppBasicCapsFax | UsbIppBasicCapsAnyHTTP
in caps and nil in error.
I want to understand, what is the reason of the timeout (the initial problem you came with). Latest official release requests all printer attributes, and it causes some HP devices to timeout; latest github version requests only attributes it really needs, which fixes initialization of these HP printers and may be will help with your printer too.
You may also try to play a little bit with the timeout duration, this is DevInitTimeout
constant defined in the const.go
file.
ping
ok, short-circuiting usbIppBasicCaps to return that fixed value allows the device probe to succeed, however it's still timing out, even after I doubled DevInitTimeout to 10 seconds.
Interestingly, if I force it to use USB[1] instead of [0] it still times out.
sniff of USB handshake The interesting stuff is packets 289-310 (the IN URB is returned with -ENOENT)
It's worth stating that I have no idea if this printer actually works using IPP; under Windows (connecting via wifi) it uses Microsoft's WS-Print ("Web Services for Devices for Printing"), and via USB it uses a non-ipp proprietary protocol that I reverse-engineered several years ago. I'm still trying to get its builtin wifi working so I can see it it'll work via airprint and/or android print.
EDIT: I successfully printed directly via Android Print over wifi. But I don't have any way to determine if IPP-over-USB is expected to work on this thing.
If it doesn't work with IPP-USB, it at least makes sense to blacklist it in the ipp-usb, so ipp-usb will not steal USB interfaces from legacy drivers. I've already seen a HP device which was announcing IPP-USB support, but responded 404 Not found
to all HTTP requests sent to device,
But before doing so, it makes sense to play a little bit with the Connection:
header in the HTTP requests. Please look to the /usr/share/ipp-usb/quirks/default.conf
file:
http-connection = ""
Try to replace empty string with keep-alive
or close
Okay... now it's suddently probing properly, with the hard-coded change to usbIppBasicCaps, the printer's now making it through the probe and advertising on the network. So once that descriptor parsing is fixed, this bug can probably be closed.
It seems that in order for the IPP-USB stuff to work, this printer has to be connected to WiFi. (wtf..)
I'm still not able to print (due to other issues) but I'll open other tickets.
So http-connection
setting is not required for your device, correct?
You probably can now return to the latest "official" release of the ipp-usb. The only advantage of the latest github release is that it requests less data from device during initialization, but seems it doesn't improve anything for your device. I'll notify you (and will ask to test), when I'll update the descriptor parsing.
Honestly, I've suspected that IPP-USB needs some configuration tweaks on your device, but the fact that it is bound to WiFi settings is really surprising. Looks that enabling WiFi actually enables all the HTTP stuff, including IPP-USB.
And it's back to not working again. Sigh. In the end it may make more sense to blacklist this thing, but in the mean time it's still useful as a particularly pathological test case.
Have you tried to play with http-connection
a little bit? For many devices it helps a lot.
Hi!
Situation becomes more interesting. For my printer (Kyocera ECOSYS M2040dn), extra_length
in the libusb_interface_descriptor
is equal to 0, so lsusb
with your patch doesn't print IPP capabilities, and ipp-usb
also can't obtain it this way.
From another hand, obtaining class-specific Device Info Descriptor via libusb_get_descriptor
, as it currently implemented in the ipp-usb
, works well.
Hi Solomon,
after some thinking/reading, I came to the following conclusion:
So my solution is to query descriptor 0x21, but in a case of any error fall back to the reasonable default.
The only remaining question, should we try to fix IPP-USB instability of this device or simple blacklist it. Here I'm waiting for your feedback.
To be honest, I think the "correct" way to deal with this is to first look at the interface descriptor for the class-specific data, and if it is not detected (or invalid), fall back to a top-level descriptor query. It's all fine to quote the spec, but at the end of the day, we need to handle the printers encountered in the real world. If Canon did this for one model, they (and other manufacturers) likely did it for others.
Now it may come to pass that blacklisting the CP1200 is the a good idea, but I think there's still a lot of utility in using it as a (perhaps highly pathological) test case. I really want to see this thing print via IPP-USB.
(Oh, with respect to IPP-USB only working if a wifi connection is active; I suspect this is because the IPP functionality is implemented within the wifi module firmware...)
Actually, query for class-specific descriptor was added as a workaroung for HP Color LaserJet Enterprise MFP M578, which returns unparseable HTTP response, when probing for /ipp/faxout, if fax unit is not installed. It's the first device to have this problem, in most cases legacy approach, which simply probes for printer/fax/scan, works well. So if ipp-usb ignores failed attempt to obtain class-specific descriptor, it will anyway work in most real world cases.
I still want you to play a little bit with the http-connection
quirk, it may improve stability with the CP1200. If it helps, I will add the resulting quirk to the set of quirks that comes with the standard distribution.
Can confirm I'm seeing a similar problem trying to connect to the Canon SELPHY CP1300.
Error output below:
This is ipp-usb
compiled from the 0.9.19
branch (the same also happens on master
as of the time of this comment). I've tried setting the http-connection
quirk to keep-alive
and close
and neither makes any difference for me.
I must admit, I know next to nothing about ipp
but just sharing this in case it helps.
It'd be really nice to get this working, so I'm happy to run more tests if it can help get to the bottom of this.
An example of the failure. This repeats endlessly:
I'm using ipp-usb 0.9.19, on a Fedora 34 box.
It appears the printer exports two interface/configurations that claim to support ipp-over-usb, but ipp-usb only ever attempts to bind to the first...
EDIT: I mean to say we never attempt to use USB[1], even when USB[0] is failing. That seems like an oversight!