From: Kumar, S. <san...@hp...> - 2013-06-28 08:35:12
|
Hello Hans, After all the analysis from our side we believe that, it will be good if fix is provided in kernel (always allow the get_device_id printer request). Below are the calls for which we need this fix in the kernel. 1. Used for getting device ID rlen = libusb_control_transfer(hd, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bmRequestType */ LIBUSB_REQUEST_GET_STATUS, /* bRequest */ config, /* wValue */ interface, /* wIndex */ buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT); 2. Used for getting device status for some printers. len = libusb_control_transfer(hd, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bmRequestType */ LIBUSB_REQUEST_CLEAR_FEATURE, /* bRequest */ 0, /* wValue */ interface, /* wIndex */ &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT); And regarding the older kernels HPLIP users will see issues only when libusb version is > 1.0.9. I think that is fine for us as we can provide a hot fix to users falling in this category. But this fix will ensure that all future Distros have this fix present in the kernel . Please let us know your thoughts on this. Also please provide the kernel patch whenever available, so that we can test it here. Thanks again for all the help. Thanks, Sanjay -----Original Message----- From: Kumar, Sanjay Sent: Thursday, June 27, 2013 2:12 PM To: 'Hans de Goede' Cc: lib...@li... Subject: RE: [libusb] Can't write to a control endpoint in libusb-1.0.16_RC10, when bulk transfer (printing) is going on in interface 0 Thanks Hans for the detailed explanation. It answered most of my doubts. I will do some more analysis on your suggestion and get back to you. Thanks again. -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Thursday, June 27, 2013 1:43 PM To: Kumar, Sanjay Cc: lib...@li... Subject: Re: [libusb] Can't write to a control endpoint in libusb-1.0.16_RC10, when bulk transfer (printing) is going on in interface 0 Hi, On 06/27/2013 07:35 AM, Kumar, Sanjay wrote: <snip> > 6) As said this also explains what is going on, when printing another userspace app has the interface in question in use. I assume this is either something from cups, or some other part of hplip, so you will need to either wait and retry, or implement some proper locking; or ... > > [SANJAY]:During printing, hp backend claims the interface 0 (print > interface). But it uses this interface 0 only for bulk transfer > (EndPoint 8 in my printers case), This does not matter, the Linux kernel groups endpoints by interface, and a driver attaches to a single interface, this is also how things are written in the USB spec. > however I got to know from HP firmware folks that during printing, printer status can also be queried by using control endpoint (which in fact happens correctly in libusb-1.0.9 or below versions.). So my doubt is that do we now really need to wait for hp backend to terminate before we can query the status from the device? Isn't is possible to write on OUT endpoint and control endpoint parallelly? What if there is a large print job ? Will driver have to wait for such a long time? At the usb level you can access the control endpoint while bulk transfers are active, this is correct. But the Linux kernel allows only 1 driver per interface, for userspace drivers (such as a libusb using app), the usbfs driver is attached to the interface when you claim it. The control endpoint does not belong to a specific interface, but certain control requests do operate on a specific interface. To avoid userspace applications messing with the interface settings of interfaces the usbfs driver is not attached to the usbfs driver checks control-requests from userspace and if they operate on an interface which is not claimed, the control-request will be denied. So before you can do the status request you want to do you must first claim the interface, and you can only claim the interface if you first detach any existing the driver from the interface. I know your code already does the detach and the claim, I'm just trying to explain why they are needed. ### So one thing has changed in 1.0.16 compared to 1.0.9 wrt driver detaching, and that is that we will no longer detach the driver if it is usbfs, since that means an other userspace application is using the interface, and we don't want to interfere with another libusb using application. So with 1.0.16 if the interface is already claimed from another process using libusb (*), then the detach_kernel_driver and the subsequent claim_interface call will both fail with LIBUSB_ERROR_BUSY. This is what you are seeing and this is a good thing. Lets call the 2 process I believe are in play: 1) hp printing backend, which does the actual printing 2) hp status process, which makes the status control requests What I believe is happening with 1.0.9 is something along the lines of: 1) hp printing backend detaches the usblp driver 2) hp printing backend claims the interface (and the kernel now internally attaches the usbfs driver) 3) hp printing backend submits a bunch of bulk transfers 4) hp status process detaches the usbfs driver the hp printing backend is using 5) Note this denies further access to the bulk endpoint by the hp printing backend unless the hp printing backend detaches and reclaims again! 6) hp status process claims the interface (re-attaching the usbfs driver, but now on behalf of a different process) 7) hp status process makes its control request With 1.0.16 what happens instead if the status process runs while printing is: 4) hp status process tries to detach the usbfs driver libusb returns LIBUSB_ERROR_BUSY 5) The hp printing backend happily keeps access to the interface 6) hp status process claims the interface libusb returns LIBUSB_ERROR_BUSY 7) hp status process makes its control request libusb returns LIBUSB_ERROR_BUSY This is what breaks your printer status querying, but this is a good thing, as detaching the usbfs driver while the hp printing backend is printing is bad. One possible fix is accessing both the bulk endpoint and the control endpoint from one process, or if you're already using one process, by also using only 1 device handle for both. Alternatively we could change the kernel to simply always allow the get_device_id printer request. We already have special handling in the kernel for this request. Changing that code to allow this request without having to claim the interface first is trivial, and given that it is a read-only request also kind of sensible. Then you can simply make the control request without first needing to do any detach- or claiming. The downside of fixing this kernel side, is that it won't help with hplip running on older kernels. Let me know if you want me to write a kernel patch for this (and after you've tested it want me to push it into the upstream kernel, assuming no-one nacks it). > Detach kernel drivers is something which you should not do without very good reasons in general. In this case there is a better solution, there is a ieee1284_id file in sysfs which contains the exact string you're looking for, and you can get that without needing any special rights in usbfs, or without needing to detach the driver, ie when I turn on my printer, dmesg contains: > > [ 9643.182911] usblp 2-1.7:1.1: usblp0: USB Bidirectional printer dev > 7 if 1 alt 0 proto 2 vid 0x03F0 pid 0x3B11 > > So 2-1.7:1.1 is the printer class interface of my printer, and now I can get the device-id by a simple: > > cat /sys/bus/usb/devices/2-1.7:1.1/ieee1284_id > > You should seriously consider using this sysfs file, that seems a much better solution to your problem, without the need to coordinate (detach / claim / lock) with any other users of the printer. > > [SANJAY]: I could not get all the information which I get in device ID from ieee1284_id (especially for some devices, below string will contain device status cod) > device ID:MFG:HP;MDL:Deskjet 2000 J210 series;CMD:PCL,DW-PCL,DESKJET,DYN;CLS:PRINTER;DES:CH390A;CID:HPIJVIPAV1;LEDMDIS:USB#07#01#02,USB#FF#04#01;SN:CN03N1C06M05HY;S:038000C484001021002c1f0001ec2880032;J: ;Z:0102,05037460009600,0600,0c0,0e00000000,0f00000000,10000008000008,12000,143,150,16361a3746000316da15ae0003,17000000000000;: Ah, ok. Regards, Hans *) Or through another libusb_device_handle if you open the same device twice from the same process |