From: Kumar, S. <san...@hp...> - 2013-06-20 06:26:25
|
#include <unistd.h> #include <errno.h> #include <stdio.h> #include<stdlib.h> #include <string.h> #include <libusb-1.0/libusb.h> #include <error.h> #include <syslog.h> #define LIBUSB_TIMEOUT 30000 /* milliseconds */ #define LIBUSB_CONTROL_REQ_TIMEOUT 5000 #define DBG(args...) printf(args) #define INFO(args...) printf(args) #define BUG(args...) printf(args) static int get_ep(libusb_device *dev, int config, int interface, int altset, enum libusb_transfer_type type, enum libusb_endpoint_direction epdir) { struct libusb_config_descriptor *confptr = NULL; const struct libusb_interface_descriptor *pi; int i, endpoint = -1; if (libusb_get_config_descriptor(dev, config, &confptr) != 0) goto bugout; if (confptr == NULL || confptr->interface == NULL || confptr->interface[interface].altsetting == NULL) goto bugout; pi = &(confptr->interface[interface].altsetting[altset]); for (i=0; i<pi->bNumEndpoints; i++) { if (pi->endpoint == NULL) goto bugout; if (pi->endpoint[i].bmAttributes == type) { if (epdir == LIBUSB_ENDPOINT_IN) { if (pi->endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_IN) { endpoint = pi->endpoint[i].bEndpointAddress; break; } } else if (epdir == LIBUSB_ENDPOINT_OUT) { if (!(pi->endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_IN)) { endpoint = pi->endpoint[i].bEndpointAddress; break; } } } } bugout: libusb_free_config_descriptor(confptr); if (endpoint == -1) DBG("get_ep: ERROR! returning -1\n"); return endpoint; /* no endpoint found */ } static int get_out_ep(libusb_device *dev, int config, int interface, int altset, enum libusb_transfer_type type) { return get_ep(dev, config, interface, altset, type, LIBUSB_ENDPOINT_OUT); } /* Detach any kernel module that may have claimed specified inteface. */ static int detach(libusb_device_handle *hd, int interface) { int ret ; /* If any kernel module has claimed this interface, detach it. */ ret = libusb_kernel_driver_active (hd, interface); DBG("Active kernel driver on interface=%d ret=%d (%m)\n", interface, ret); if (ret == 1) { ret = libusb_detach_kernel_driver(hd, interface); DBG("Detaching kernel driver on interface=%d ret=%d (%m)\n", interface, ret); if (ret < 0) BUG("could not remove kernel driver interface=%d, retvalue = %d: %m\n", interface,ret); } ret = libusb_kernel_driver_active (hd, interface); DBG("Varify Active kernel driver on interface=%d ret=%d (%m)...............\n", interface, ret); return 0; } int main(int argc, char **argv) { libusb_context *ctx = NULL; libusb_device **list; /*List of connected USB devices */ libusb_device *dev = NULL; /* Current device */ struct libusb_device_descriptor devdesc; /* Current device descriptor */ struct libusb_config_descriptor *confptr = NULL; /* Pointer to current configuration */ libusb_device_handle *hd = NULL; int i, j = 0,r, conf, numdevs = 0,status; /* number of connected devices */ char imanufact[128] = {0,} , iproduct[128] = {0,}, iserial[128] = {0,}; int num = 0; char string[128] = {0,}; char buffer[1024]={0}; int maxSize = 1024,size = 1024, rlen=-4, interfacenum=0; libusb_init(&ctx); libusb_set_debug(ctx,2); numdevs = libusb_get_device_list(ctx, &list); if (numdevs <= 0) goto bugout; for (i = 0; i < numdevs; i++) { dev = list[i]; libusb_get_device_descriptor (dev, &devdesc); if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct) continue; if(devdesc.idVendor != 0x3f0) /*Not a HP device */ continue; for (conf = 0; conf < devdesc.bNumConfigurations; conf++) { if (libusb_get_config_descriptor (dev, conf, &confptr) < 0) continue; if (confptr->interface[0].altsetting[0].bInterfaceClass != LIBUSB_CLASS_MASS_STORAGE) { libusb_open(dev, &hd); if (hd == NULL) { BUG("Invalid usb_open: %m\n"); continue; } detach(hd, 0); DBG("\n"); rlen = libusb_claim_interface(hd, 0); if (rlen) DBG("invalid claim_interface %d: (%m)\n",0); else DBG("claimed interface : %d (%m)\n",interfacenum); rlen = libusb_control_transfer(hd, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE , /* bmRequestType */ LIBUSB_REQUEST_GET_STATUS, /* bRequest */ 0, /* wValue */ 0, /* wIndex interface */ /* note firmware does not follow the USB Printer Class specification for wIndex */ buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT); if (rlen < 0) BUG("invalid deviceid ret=%d: (%m)\n\n", rlen); else BUG("Valid deviceid ret=%d: (%m)\n\n", rlen); rlen = ntohs(*(short *)buffer); if (rlen > (size-1)) rlen = size-1; /* leave byte for zero termination */ if (rlen > 2) rlen -= 2; memcpy(buffer, buffer+2, rlen); /* remove length */ buffer[rlen]=0; DBG("read actual device_id successfully fd=%d len=%d (%m)\n\n", 1, rlen); BUG("device ID:%s: \n\n", buffer); libusb_free_config_descriptor(confptr); confptr = NULL; } } } bugout: if (hd) libusb_close(hd); if (confptr) libusb_free_config_descriptor(confptr); libusb_free_device_list(list, 1); libusb_exit(ctx); return 0; } |
From: Hans de G. <hde...@re...> - 2013-06-20 09:54:06
Attachments:
getdeviceID.c
|
Hello Sanjay, On 06/20/2013 08:24 AM, Kumar, Sanjay wrote: > Hello All, > > I am working for HP Linux printer driver (HPLIP team ). Recently I found one issue in libusb-1.0.16RC release. I Can't write on a control endpoint in libusb-1.0.16_RC10, when bulk transfer (printing) is going on in interface 0. I have created a ticket also regarding the same but I can’t see it in the active tickets. I've a HP printer (PSC 1350) myself, so I've tried to reproduce this, but I could not reproduce. Still I've a hunch of what is going on: 1) First of all, next time, and in your next mail, please include: -Actual output of your test program, esp. the error code given by the libusb_control_transfer would be useful, I bet it is LIBUSB_ERROR_BUSY -lsusb -v output for the device in question -relevant messages in dmesg if any 2) Your getdeviceID.c is buggy, my printer has a device-id length > 127 bytes and bad things happen because of sign extension, and you use memcpy where you should memmove, fixed version attached. Also if it fails to claim the interface (which I think it does), the program should stop, continuing after that point is useless. 3) Are you sure that interface 0 is the right interface? On my printer interface 0 is a vendor interface, where as interface 1 is the actual printerclass interface, and the getvendorid call should be made on the printerclass interface. Note that it seems to work fine on both interface with my printer, ie both a wIndex of 0 and of (1 << 8) work. Note that the requested lsusb -v info will tell for sure. 4) In case of using 1 << 8 the usblp driver must first be detached from interface 1, since the linux kernel knows about the special wIndex usage for printerclasses, and looks at the upper 8 bits to determine which interface the ctrl req will apply too, and that must be claimed for the ctrl-req to be allowed (and thus the driver must be detached). 5) > 3) When printing is happening > > *libusb_kernel_driver_active()* returns 1 even after*libusb_detach_kernel_driver(hd, 0)* call is made. Please see the attached code also. Ah yes, this is a bug, which also explains what is going on, recent libusb code does not detach the kernel driver if it is usbfs, since then no other kernel driver is attached, but another userspace app is using it, and we don't want to interfere with that (detaching the kernel driver sometimes is a must, killing another userspace apps access is not). I've just pushed a bug-fix to libusbx git master fixing libusb_kernel_driver_active() to properly return 0 when the device is in use from userspace by another app. 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 ... 7) As said you seem to be operating on the wrong interface, which actually is a good thing, because detaching the usblp kernel driver while printing will likely kill the print job halfway through, not good. 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. 8) Note that the libusbx and libusb projects are merging back together, and all development is happening in libusbx git atm, you can find the latest code here: https://github.com/libusbx/libusbx I don't expect this to fix your problem, other then the libusb_kernel_driver_active() returning 1 when the device is in use from userspace by another app bug. Also as said, if I were you I would just abandon the whole libusb approach and use sysfs instead. Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-06-20 12:16:56
|
Hello Hans, Many thanks for looking into this. While I continue to look into the issue I thought of sharing the information you asked for. Please find the logs you requested in the attachment and my comments inline below. Please let me know if I am doing something wrong or you need some more information. -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Thursday, June 20, 2013 3:24 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 Hello Sanjay, On 06/20/2013 08:24 AM, Kumar, Sanjay wrote: > Hello All, > > I am working for HP Linux printer driver (HPLIP team ). Recently I found one issue in libusb-1.0.16RC release. I Can't write on a control endpoint in libusb-1.0.16_RC10, when bulk transfer (printing) is going on in interface 0. I have created a ticket also regarding the same but I can't see it in the active tickets. I've a HP printer (PSC 1350) myself, so I've tried to reproduce this, but I could not reproduce. Still I've a hunch of what is going on: [SANJAY]: I can still reproduce this issue after taking your changes (except interface number because for my printer interface 0 is used for printing) in Fedora 16 after upgrading the libusb version to 1.0.16RC. However 1.0.9 version works fine. 1) First of all, next time, and in your next mail, please include: -Actual output of your test program, esp. the error code given by the libusb_control_transfer would be useful, I bet it is LIBUSB_ERROR_BUSY -lsusb -v output for the device in question -relevant messages in dmesg if any [SANJAY]: In failure case claim interface itself is failing (LIBUSB_ERROR_BUSY). However claim interface does not fail with libusb-1.0.9 or below. 2) Your getdeviceID.c is buggy, my printer has a device-id length > 127 bytes and bad things happen because of sign extension, and you use memcpy where you should memmove, fixed version attached. Also if it fails to claim the interface (which I think it does), the program should stop, continuing after that point is useless. [SANJAY]: Corrected the code but same result. Please see the attached source file. 3) Are you sure that interface 0 is the right interface? On my printer interface 0 is a vendor interface, where as interface 1 is the actual printerclass interface, and the getvendorid call should be made on the printerclass interface. Note that it seems to work fine on both interface with my printer, ie both a wIndex of 0 and of (1 << 8) work. Note that the requested lsusb -v info will tell for sure. [SANJAY]: Attached lsusb.log for the same 4) In case of using 1 << 8 the usblp driver must first be detached from interface 1, since the linux kernel knows about the special wIndex usage for printerclasses, and looks at the upper 8 bits to determine which interface the ctrl req will apply too, and that must be claimed for the ctrl-req to be allowed (and thus the driver must be detached). [SANJAY]: ok 5) > 3) When printing is happening > > *libusb_kernel_driver_active()* returns 1 even after*libusb_detach_kernel_driver(hd, 0)* call is made. Please see the attached code also. Ah yes, this is a bug, which also explains what is going on, recent libusb code does not detach the kernel driver if it is usbfs, since then no other kernel driver is attached, but another userspace app is using it, and we don't want to interfere with that (detaching the kernel driver sometimes is a must, killing another userspace apps access is not). I've just pushed a bug-fix to libusbx git master fixing libusb_kernel_driver_active() to properly return 0 when the device is in use from userspace by another app. [SANJAY]: OK 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), 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? 7) As said you seem to be operating on the wrong interface, which actually is a good thing, because detaching the usblp kernel driver while printing will likely kill the print job halfway through, not good. [SANJAY]: usblp is detached even before printing is started as we make use of libusb_bulk_transfer APIs (usbfs) for printing. 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;: 8) Note that the libusbx and libusb projects are merging back together, and all development is happening in libusbx git atm, you can find the latest code here: https://github.com/libusbx/libusbx I don't expect this to fix your problem, other then the libusb_kernel_driver_active() returning 1 when the device is in use from userspace by another app bug. Also as said, if I were you I would just abandon the whole libusb approach and use sysfs instead. Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-06-27 05:37:38
Attachments:
lsusb.log
|
Hello Hans, Missed to attach output of lsusb command. It will be really helpful for me if you can provide answers to my doubts mentioned below. Thanks, Sanjay -----Original Message----- From: Kumar, Sanjay Sent: Thursday, June 20, 2013 5:46 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 Hello Hans, Many thanks for looking into this. While I continue to look into the issue I thought of sharing the information you asked for. Please find the logs you requested in the attachment and my comments inline below. Please let me know if I am doing something wrong or you need some more information. -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Thursday, June 20, 2013 3:24 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 Hello Sanjay, On 06/20/2013 08:24 AM, Kumar, Sanjay wrote: > Hello All, > > I am working for HP Linux printer driver (HPLIP team ). Recently I found one issue in libusb-1.0.16RC release. I Can't write on a control endpoint in libusb-1.0.16_RC10, when bulk transfer (printing) is going on in interface 0. I have created a ticket also regarding the same but I can't see it in the active tickets. I've a HP printer (PSC 1350) myself, so I've tried to reproduce this, but I could not reproduce. Still I've a hunch of what is going on: [SANJAY]: I can still reproduce this issue after taking your changes (except interface number because for my printer interface 0 is used for printing) in Fedora 16 after upgrading the libusb version to 1.0.16RC. However 1.0.9 version works fine. 1) First of all, next time, and in your next mail, please include: -Actual output of your test program, esp. the error code given by the libusb_control_transfer would be useful, I bet it is LIBUSB_ERROR_BUSY -lsusb -v output for the device in question -relevant messages in dmesg if any [SANJAY]: In failure case claim interface itself is failing (LIBUSB_ERROR_BUSY). However claim interface does not fail with libusb-1.0.9 or below. 2) Your getdeviceID.c is buggy, my printer has a device-id length > 127 bytes and bad things happen because of sign extension, and you use memcpy where you should memmove, fixed version attached. Also if it fails to claim the interface (which I think it does), the program should stop, continuing after that point is useless. [SANJAY]: Corrected the code but same result. Please see the attached source file. 3) Are you sure that interface 0 is the right interface? On my printer interface 0 is a vendor interface, where as interface 1 is the actual printerclass interface, and the getvendorid call should be made on the printerclass interface. Note that it seems to work fine on both interface with my printer, ie both a wIndex of 0 and of (1 << 8) work. Note that the requested lsusb -v info will tell for sure. [SANJAY]: Attached lsusb.log for the same 4) In case of using 1 << 8 the usblp driver must first be detached from interface 1, since the linux kernel knows about the special wIndex usage for printerclasses, and looks at the upper 8 bits to determine which interface the ctrl req will apply too, and that must be claimed for the ctrl-req to be allowed (and thus the driver must be detached). [SANJAY]: ok 5) > 3) When printing is happening > > *libusb_kernel_driver_active()* returns 1 even after*libusb_detach_kernel_driver(hd, 0)* call is made. Please see the attached code also. Ah yes, this is a bug, which also explains what is going on, recent libusb code does not detach the kernel driver if it is usbfs, since then no other kernel driver is attached, but another userspace app is using it, and we don't want to interfere with that (detaching the kernel driver sometimes is a must, killing another userspace apps access is not). I've just pushed a bug-fix to libusbx git master fixing libusb_kernel_driver_active() to properly return 0 when the device is in use from userspace by another app. [SANJAY]: OK 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), 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? 7) As said you seem to be operating on the wrong interface, which actually is a good thing, because detaching the usblp kernel driver while printing will likely kill the print job halfway through, not good. [SANJAY]: usblp is detached even before printing is started as we make use of libusb_bulk_transfer APIs (usbfs) for printing. 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;: 8) Note that the libusbx and libusb projects are merging back together, and all development is happening in libusbx git atm, you can find the latest code here: https://github.com/libusbx/libusbx I don't expect this to fix your problem, other then the libusb_kernel_driver_active() returning 1 when the device is in use from userspace by another app bug. Also as said, if I were you I would just abandon the whole libusb approach and use sysfs instead. Regards, Hans |
From: Hans de G. <hde...@re...> - 2013-06-27 08:13:30
|
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 |
From: Kumar, S. <san...@hp...> - 2013-06-27 08:43:38
|
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 |
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 |
From: Alan S. <st...@ro...> - 2013-06-28 15:15:51
|
On Fri, 28 Jun 2013, Kumar, Sanjay wrote: > 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. The kernel does not allow more than one program or driver to use an interface at any time. This means that while the HPLIP program uses the printer interface, other programs cannot use it. To do what you want, the HPLIP program needs to be changed. There should be a way to ask the program to get the device ID and status while printing is going on. For example, the program could create a Unix-domain socket, and other programs could read that socket to obtain the device ID and status. Alan Stern |
From: Hans de G. <hde...@re...> - 2013-06-30 19:36:16
|
Hi Alan et al, On 06/28/2013 05:15 PM, Alan Stern wrote: > On Fri, 28 Jun 2013, Kumar, Sanjay wrote: > >> 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. > > The kernel does not allow more than one program or driver to use an > interface at any time. This means that while the HPLIP program uses > the printer interface, other programs cannot use it. I was hoping that we could make life easier for the hplip people (and possible other printer related userspac), by simply always allowing REQUEST_GET_STATUS on printer-class interfaces. We already have special handling for this request in check_ctrlrecip, changing this to always allow is trivial, and it is a read-only request. I was not aware they were going to need LIBUSB_REQUEST_CLEAR_FEATURE too. Sanjay, if you need REQUEST_CLEAR_FEATURE to work too, you will need to do what Alan says and have some sort of daemon talking to / owning the interface, and have all apps which need access to the interface talk to the daemon. Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-07-01 04:41:33
|
Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. LIBUSB_REQUEST_CLEAR_FEATURE is used from the same process (hp backend), in which bulk transfer also happens therefore that should not fail for us. -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Monday, July 01, 2013 1:06 AM To: Alan Stern Cc: Kumar, Sanjay; 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 Alan et al, On 06/28/2013 05:15 PM, Alan Stern wrote: > On Fri, 28 Jun 2013, Kumar, Sanjay wrote: > >> 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. > > The kernel does not allow more than one program or driver to use an > interface at any time. This means that while the HPLIP program uses > the printer interface, other programs cannot use it. I was hoping that we could make life easier for the hplip people (and possible other printer related userspac), by simply always allowing REQUEST_GET_STATUS on printer-class interfaces. We already have special handling for this request in check_ctrlrecip, changing this to always allow is trivial, and it is a read-only request. I was not aware they were going to need LIBUSB_REQUEST_CLEAR_FEATURE too. Sanjay, if you need REQUEST_CLEAR_FEATURE to work too, you will need to do what Alan says and have some sort of daemon talking to / owning the interface, and have all apps which need access to the interface talk to the daemon. Regards, Hans |
From: Hans de G. <hde...@re...> - 2013-07-01 10:10:47
|
Hi, On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: > Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. That is Alan Stern's call. I can whip up a patch to allow this easily, but if Alan is going to nack that patch, me doing so is of little use. Alan, can we have your input on this please. My reasoning for allowing it, is: 1) It is useful to allow it from another process 2) It is a "read-only" call from the device's pov 3) We already have special handling for it, this just changes the special handling to always allow this request. > LIBUSB_REQUEST_CLEAR_FEATURE is used from the same process (hp backend), in which bulk transfer also happens therefore that should not fail for us. Regards, Hans |
From: Alan S. <st...@ro...> - 2013-07-01 14:08:31
|
On Mon, 1 Jul 2013, Hans de Goede wrote: > Hi, > > On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: > > Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. > > That is Alan Stern's call. I can whip up a patch to allow this easily, but if > Alan is going to nack that patch, me doing so is of little use. > > Alan, can we have your input on this please. My reasoning for allowing it, is: > 1) It is useful to allow it from another process > 2) It is a "read-only" call from the device's pov > 3) We already have special handling for it, this just changes the special > handling to always allow this request. Yes, we can expand the existing special case. (BTW, that code would be easier to read if the 0xa1 were replaced by a symbolic expression.) Is it known that all printers will accept these requests at random times, without affecting on ongoing print job? We have seen examples of hardware where a simple "read-only" request on ep0 would mess up a bulk transfer in progress. Alan Stern |
From: Hans de G. <hde...@re...> - 2013-07-02 09:54:04
|
Hi, On 07/01/2013 04:08 PM, Alan Stern wrote: > On Mon, 1 Jul 2013, Hans de Goede wrote: > >> Hi, >> >> On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: >>> Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. >> >> That is Alan Stern's call. I can whip up a patch to allow this easily, but if >> Alan is going to nack that patch, me doing so is of little use. >> >> Alan, can we have your input on this please. My reasoning for allowing it, is: >> 1) It is useful to allow it from another process >> 2) It is a "read-only" call from the device's pov >> 3) We already have special handling for it, this just changes the special >> handling to always allow this request. > > Yes, we can expand the existing special case. (BTW, that code would be > easier to read if the 0xa1 were replaced by a symbolic expression.) > > Is it known that all printers will accept these requests at random > times, without affecting on ongoing print job? We have seen examples > of hardware where a simple "read-only" request on ep0 would mess up a > bulk transfer in progress. Sanjay can probably give a better answer to this then I, Sanjay ? Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-07-02 12:40:36
|
Hello Hans/Alan, Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time. However it will be really great if you can send me the patch which you will apply in the kernel so that I can test some HP printers to make sure that there is no problem in printing and status. Thanks, Sanjay -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Tuesday, July 02, 2013 3:24 PM To: Alan Stern Cc: Kumar, Sanjay; 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 07/01/2013 04:08 PM, Alan Stern wrote: > On Mon, 1 Jul 2013, Hans de Goede wrote: > >> Hi, >> >> On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: >>> Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. >> >> That is Alan Stern's call. I can whip up a patch to allow this >> easily, but if Alan is going to nack that patch, me doing so is of little use. >> >> Alan, can we have your input on this please. My reasoning for allowing it, is: >> 1) It is useful to allow it from another process >> 2) It is a "read-only" call from the device's pov >> 3) We already have special handling for it, this just changes the >> special handling to always allow this request. > > Yes, we can expand the existing special case. (BTW, that code would > be easier to read if the 0xa1 were replaced by a symbolic expression.) > > Is it known that all printers will accept these requests at random > times, without affecting on ongoing print job? We have seen examples > of hardware where a simple "read-only" request on ep0 would mess up a > bulk transfer in progress. Sanjay can probably give a better answer to this then I, Sanjay ? Regards, Hans |
From: Tim R. <ti...@pr...> - 2013-07-02 17:01:11
|
Kumar, Sanjay wrote: > Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time.... Wait a minute. Are we all talking about the same issue? Because nothing has changed here. The issue is not part of libusb -- it is more fundamental. The Linux kernel USB stack has never allowed you to send a control transfer aimed at an interface or an endpoint unless you first claimed that interface, and it is not possible to claim the interface if another process has already claimed it. I scoffed when I first learned of this, because I come from Windows, and Windows does not have this requirement. However, Alan finally convinced me it was a good idea, so I stopped complaining. I don't understand how the libusb version could possibly be relevant. Is it possible the HP code has been reorganized, so that the two accessors used to be part of the same process, but they aren't any more? -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. |
From: Kumar, S. <san...@hp...> - 2013-07-03 05:18:57
|
Hello Tim, Hans already explained the issue and root cause in details in one of the mails. I am attaching the same mail here. Thanks, Sanjay Message: 3 Date: Tue, 2 Jul 2013 10:01:03 -0700 From: Tim Roberts <ti...@pr...> 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 To: Libusb Mailing List <lib...@li...> Message-ID: <51D...@pr...> Content-Type: text/plain; charset="ISO-8859-1" Kumar, Sanjay wrote: > Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time.... Wait a minute. Are we all talking about the same issue? Because nothing has changed here. The issue is not part of libusb -- it is more fundamental. The Linux kernel USB stack has never allowed you to send a control transfer aimed at an interface or an endpoint unless you first claimed that interface, and it is not possible to claim the interface if another process has already claimed it. I scoffed when I first learned of this, because I come from Windows, and Windows does not have this requirement. However, Alan finally convinced me it was a good idea, so I stopped complaining. I don't understand how the libusb version could possibly be relevant. Is it possible the HP code has been reorganized, so that the two accessors used to be part of the same process, but they aren't any more? -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. -----Original Message----- From: Kumar, Sanjay Sent: Tuesday, July 02, 2013 6:10 PM To: 'Hans de Goede'; Alan Stern 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 Hello Hans/Alan, Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time. However it will be really great if you can send me the patch which you will apply in the kernel so that I can test some HP printers to make sure that there is no problem in printing and status. Thanks, Sanjay -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Tuesday, July 02, 2013 3:24 PM To: Alan Stern Cc: Kumar, Sanjay; 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 07/01/2013 04:08 PM, Alan Stern wrote: > On Mon, 1 Jul 2013, Hans de Goede wrote: > >> Hi, >> >> On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: >>> Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. >> >> That is Alan Stern's call. I can whip up a patch to allow this >> easily, but if Alan is going to nack that patch, me doing so is of little use. >> >> Alan, can we have your input on this please. My reasoning for allowing it, is: >> 1) It is useful to allow it from another process >> 2) It is a "read-only" call from the device's pov >> 3) We already have special handling for it, this just changes the >> special handling to always allow this request. > > Yes, we can expand the existing special case. (BTW, that code would > be easier to read if the 0xa1 were replaced by a symbolic expression.) > > Is it known that all printers will accept these requests at random > times, without affecting on ongoing print job? We have seen examples > of hardware where a simple "read-only" request on ep0 would mess up a > bulk transfer in progress. Sanjay can probably give a better answer to this then I, Sanjay ? Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-07-04 12:38:45
Attachments:
PrintingIssue.pdf
|
Hello Hans/Alan, I did testing on some more HP printers using libusb1.0.9 version (as it allows both CONTROL and BULK transfers at the same time) and executed following test case. 1) Start print job. (hp backend process starts BULK write) 2) During printing, start querying device ID *quickly 5-6 times, after every 2 seconds or so* (status process starts CONTROL request) I could see BULK transfer(printing) getting messed up. **Some portion of the data was printed overlapped and repeated** (See attached PrintingIssue.pdf). I debugged this issue with HP firmware developers and found that if control request (which is a blocking call) is sent 4-5 times during printing then printer is receiving the duplicate BULK packet some times, which causes this issue in the printout. So looks like something wrong happens in USB host controller side, which makes it to send the duplicate packet to the printer even when printer sends back the ACK for the previous packet. So by seeing all this I think we have no other option but to avoid device ID query during printing in our driver. That means there is no need of doing any change in libusb/kernel code. Please let us know if you have any suggestions or if you want USB traces for the failure case (When device receives duplicate BULK packet from the host) Thanks, Sanjay -----Original Message----- From: Kumar, Sanjay Sent: Wednesday, July 03, 2013 10:47 AM To: 'ti...@pr...' Cc: 'lib...@li...'; 'Hans de Goede'; 'Alan Stern' 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 Hello Tim, Hans already explained the issue and root cause in details in one of the mails. I am attaching the same mail here. Thanks, Sanjay Message: 3 Date: Tue, 2 Jul 2013 10:01:03 -0700 From: Tim Roberts <ti...@pr...> 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 To: Libusb Mailing List <lib...@li...> Message-ID: <51D...@pr...> Content-Type: text/plain; charset="ISO-8859-1" Kumar, Sanjay wrote: > Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time.... Wait a minute. Are we all talking about the same issue? Because nothing has changed here. The issue is not part of libusb -- it is more fundamental. The Linux kernel USB stack has never allowed you to send a control transfer aimed at an interface or an endpoint unless you first claimed that interface, and it is not possible to claim the interface if another process has already claimed it. I scoffed when I first learned of this, because I come from Windows, and Windows does not have this requirement. However, Alan finally convinced me it was a good idea, so I stopped complaining. I don't understand how the libusb version could possibly be relevant. Is it possible the HP code has been reorganized, so that the two accessors used to be part of the same process, but they aren't any more? -- Tim Roberts, ti...@pr... Providenza & Boekelheide, Inc. -----Original Message----- From: Kumar, Sanjay Sent: Tuesday, July 02, 2013 6:10 PM To: 'Hans de Goede'; Alan Stern 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 Hello Hans/Alan, Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time. However it will be really great if you can send me the patch which you will apply in the kernel so that I can test some HP printers to make sure that there is no problem in printing and status. Thanks, Sanjay -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Tuesday, July 02, 2013 3:24 PM To: Alan Stern Cc: Kumar, Sanjay; 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 07/01/2013 04:08 PM, Alan Stern wrote: > On Mon, 1 Jul 2013, Hans de Goede wrote: > >> Hi, >> >> On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: >>> Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. >> >> That is Alan Stern's call. I can whip up a patch to allow this >> easily, but if Alan is going to nack that patch, me doing so is of little use. >> >> Alan, can we have your input on this please. My reasoning for allowing it, is: >> 1) It is useful to allow it from another process >> 2) It is a "read-only" call from the device's pov >> 3) We already have special handling for it, this just changes the >> special handling to always allow this request. > > Yes, we can expand the existing special case. (BTW, that code would > be easier to read if the 0xa1 were replaced by a symbolic expression.) > > Is it known that all printers will accept these requests at random > times, without affecting on ongoing print job? We have seen examples > of hardware where a simple "read-only" request on ep0 would mess up a > bulk transfer in progress. Sanjay can probably give a better answer to this then I, Sanjay ? Regards, Hans |
From: Hans de G. <hde...@re...> - 2013-07-04 14:09:47
|
Hi, On 07/04/2013 02:37 PM, Kumar, Sanjay wrote: > Hello Hans/Alan, > > I did testing on some more HP printers using libusb1.0.9 version (as it allows both CONTROL and BULK transfers at the same time) and executed following test case. > 1) Start print job. (hp backend process starts BULK write) > 2) During printing, start querying device ID *quickly 5-6 times, after every 2 seconds or so* (status process starts CONTROL request) > > I could see BULK transfer(printing) getting messed up. **Some portion of the data was printed overlapped and repeated** (See attached PrintingIssue.pdf). I debugged this issue with HP firmware developers and found that if control request (which is a blocking call) is sent 4-5 times during printing then printer is receiving the duplicate BULK packet some times, which causes this issue in the printout. So looks like something wrong happens in USB host controller side, which makes it to send the duplicate packet to the printer even when printer sends back the ACK for the previous packet. As I tried to explain earlier on in this thread, with libusb-1.0.9 things work because you're lucking out on the timing. By changing the code to do the get_status quickly 5 times you're changing the timing, and this seeing the predicted messing up of the bulk transfers. IOW you've just proven that libusbx-1.0.16's behavior of just returning LIBUSB_ERROR_BUSY is there for a good reason. If you want to try this without detaching the usbfs driver from the printing backend userspace code (and thus causing these issues), you need to either do the control requests from the printing backend userspace code (which should work with any libusb and kernel version); Or modify the code to query to status to no longer do the detach and claim, with a modified kernel. Modifying the kernel to allow this is easy, edit: drivers/usb/core/devio.c Go to the check_ctrlrecip code, and in the special case for the get status req: if (requesttype == 0xa1 && request == 0) { alt_setting = usb_find_alt_setting(ps->dev->actconfig, index >> 8, index & 0xff); if (alt_setting && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER) index >>= 8; } And replace the "index >>= 8;" with "return 0;" Then build a new kernel, and you should be able to make the status-req without detaching the printing backend userspace code from the interface. Regards, Hans > > So by seeing all this I think we have no other option but to avoid device ID query during printing in our driver. That means there is no need of doing any change in libusb/kernel code. Please let us know if you have any suggestions or if you want USB traces for the failure case (When device receives duplicate BULK packet from the host) > > > Thanks, > Sanjay > > -----Original Message----- > From: Kumar, Sanjay > Sent: Wednesday, July 03, 2013 10:47 AM > To: 'ti...@pr...' > Cc: 'lib...@li...'; 'Hans de Goede'; 'Alan Stern' > 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 > > Hello Tim, > > Hans already explained the issue and root cause in details in one of the mails. I am attaching the same mail here. > > Thanks, > Sanjay > > > Message: 3 > Date: Tue, 2 Jul 2013 10:01:03 -0700 > From: Tim Roberts <ti...@pr...> > 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 > To: Libusb Mailing List <lib...@li...> > Message-ID: <51D...@pr...> > Content-Type: text/plain; charset="ISO-8859-1" > > Kumar, Sanjay wrote: >> Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time.... > > Wait a minute. Are we all talking about the same issue? Because nothing has changed here. The issue is not part of libusb -- it is more fundamental. The Linux kernel USB stack has never allowed you to send a control transfer aimed at an interface or an endpoint unless you first claimed that interface, and it is not possible to claim the interface if another process has already claimed it. > > I scoffed when I first learned of this, because I come from Windows, and Windows does not have this requirement. However, Alan finally convinced me it was a good idea, so I stopped complaining. > > I don't understand how the libusb version could possibly be relevant. > Is it possible the HP code has been reorganized, so that the two accessors used to be part of the same process, but they aren't any more? > > -- > Tim Roberts, ti...@pr... > Providenza & Boekelheide, Inc. > > -----Original Message----- > From: Kumar, Sanjay > Sent: Tuesday, July 02, 2013 6:10 PM > To: 'Hans de Goede'; Alan Stern > 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 > > Hello Hans/Alan, > > Although we did not see any issue in any of the HP printers in the past when libusb1.0.9 and below versions used to allow bulk transfer and control transfer at the same time. However it will be really great if you can send me the patch which you will apply in the kernel so that I can test some HP printers to make sure that there is no problem in printing and status. > > Thanks, > Sanjay > > -----Original Message----- > From: Hans de Goede [mailto:hde...@re...] > Sent: Tuesday, July 02, 2013 3:24 PM > To: Alan Stern > Cc: Kumar, Sanjay; 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 07/01/2013 04:08 PM, Alan Stern wrote: >> On Mon, 1 Jul 2013, Hans de Goede wrote: >> >>> Hi, >>> >>> On 07/01/2013 06:40 AM, Kumar, Sanjay wrote: >>>> Thanks for the reply Hans. Is it possible to allow only LIBUSB_REQUEST_GET_STATUS. >>> >>> That is Alan Stern's call. I can whip up a patch to allow this >>> easily, but if Alan is going to nack that patch, me doing so is of little use. >>> >>> Alan, can we have your input on this please. My reasoning for allowing it, is: >>> 1) It is useful to allow it from another process >>> 2) It is a "read-only" call from the device's pov >>> 3) We already have special handling for it, this just changes the >>> special handling to always allow this request. >> >> Yes, we can expand the existing special case. (BTW, that code would >> be easier to read if the 0xa1 were replaced by a symbolic expression.) >> >> Is it known that all printers will accept these requests at random >> times, without affecting on ongoing print job? We have seen examples >> of hardware where a simple "read-only" request on ep0 would mess up a >> bulk transfer in progress. > > Sanjay can probably give a better answer to this then I, Sanjay ? > > Regards, > > Hans > |
From: Alan S. <st...@ro...> - 2013-07-04 14:35:11
|
On Thu, 4 Jul 2013, Kumar, Sanjay wrote: > Hello Hans/Alan, > > I did testing on some more HP printers using libusb1.0.9 version (as it allows both CONTROL and BULK transfers at the same time) and executed following test case. > 1) Start print job. (hp backend process starts BULK write) > 2) During printing, start querying device ID *quickly 5-6 times, after every 2 seconds or so* (status process starts CONTROL request) > > I could see BULK transfer(printing) getting messed up. **Some portion of the data was printed overlapped and repeated** (See attached PrintingIssue.pdf). I debugged this issue with HP firmware developers and found that if control request (which is a blocking call) is sent 4-5 times during printing then printer is receiving the duplicate BULK packet some times, which causes this issue in the printout. So looks like something wrong happens in USB host controller side, which makes it to send the duplicate packet to the printer even when printer sends back the ACK for the previous packet. > > So by seeing all this I think we have no other option but to avoid device ID query during printing in our driver. That means there is no need of doing any change in libusb/kernel code. Please let us know if you have any suggestions or if you want USB traces for the failure case (When device receives duplicate BULK packet from the host) Yes, if you can provide a trace of the failure case, I would like to see it. Alan Stern |
From: Hans de G. <hde...@re...> - 2013-07-04 15:02:13
|
Hi, On 07/04/2013 04:35 PM, Alan Stern wrote: > On Thu, 4 Jul 2013, Kumar, Sanjay wrote: > >> Hello Hans/Alan, >> >> I did testing on some more HP printers using libusb1.0.9 version (as it allows both CONTROL and BULK transfers at the same time) and executed following test case. >> 1) Start print job. (hp backend process starts BULK write) >> 2) During printing, start querying device ID *quickly 5-6 times, after every 2 seconds or so* (status process starts CONTROL request) >> >> I could see BULK transfer(printing) getting messed up. **Some portion of the data was printed overlapped and repeated** (See attached PrintingIssue.pdf). I debugged this issue with HP firmware developers and found that if control request (which is a blocking call) is sent 4-5 times during printing then printer is receiving the duplicate BULK packet some times, which causes this issue in the printout. So looks like something wrong happens in USB host controller side, which makes it to send the duplicate packet to the printer even when printer sends back the ACK for the previous packet. >> >> So by seeing all this I think we have no other option but to avoid device ID query during printing in our driver. That means there is no need of doing any change in libusb/kernel code. Please let us know if you have any suggestions or if you want USB traces for the failure case (When device receives duplicate BULK packet from the host) > > Yes, if you can provide a trace of the failure case, I would like to > see it. Alan, I believe the following is happening, there are 2 separate userspace processes, lets call these bulk-backend and ctrl-status 1) bulk-backend does a detach of usblp + claim + submits a bulk transfer 2) ctrl-backend does a detach + claim, sends ctrl-req, this detaches the usbfs instance which is attached on behalf of bulk-backend 3) bulk-backend sees an error (cancel) because of the detach, retries including re-doing the detach + claim And these retries are causing the data duplication. If I understand Sanjay correctly HPLIP has always had this race, and libusb-1.0.16 "breaks" hplip, because it no longer allows the detach in step 2. to proceed (it checks which driver is attached and returns LIBUSB_ERROR_BUSY if it is usbfs). I believe sofar HPLIP has been getting away with this through sheer luck. Sanjay's new test involved doing 2 repeatedly at a high frequency, causing the race to turn into an error scenario. Regards, Hans |
From: Alan S. <st...@ro...> - 2013-07-04 15:25:36
|
On Thu, 4 Jul 2013, Hans de Goede wrote: > Alan, I believe the following is happening, there are 2 separate userspace > processes, lets call these bulk-backend and ctrl-status > > 1) bulk-backend does a detach of usblp + claim + submits a bulk transfer > 2) ctrl-backend does a detach + claim, sends ctrl-req, this detaches > the usbfs instance which is attached on behalf of bulk-backend > 3) bulk-backend sees an error (cancel) because of the detach, retries > including re-doing the detach + claim I wouldn't expect a retry of a bulk transfer also to retry the detach + claim. But maybe it does... > And these retries are causing the data duplication. > > If I understand Sanjay correctly HPLIP has always had this race, and > libusb-1.0.16 "breaks" hplip, because it no longer allows the detach > in step 2. to proceed (it checks which driver is attached and returns > LIBUSB_ERROR_BUSY if it is usbfs). > > I believe sofar HPLIP has been getting away with this through sheer > luck. Sanjay's new test involved doing 2 repeatedly at a high > frequency, causing the race to turn into an error scenario. Yes, that would explain the results. Alan Stern |
From: Kumar, S. <san...@hp...> - 2013-07-04 16:44:23
|
Hi Hans, If I create two threads inside hp backend process (say bulk_writer() thread and control_requester() thread and control_requester() requests device ID every 3 seconds or so for testing purpose) and share the device handle in both threads, will that solve duplicate BULK data packet issue? Will there be a race condition even then? Basically I just want to understand that which of the following could be the real reason. 1) As you mentioned, bulk-backend sees an error (cancel) because of the detach, retries including re-doing the detach + claim 2) Because of too much of bandwidth consumed by BLOCKING control request, something like below happens. (This is what firmware developers suspect ) a) Host controller does not receive (or miss) the ACK Packet from the device or b) Sees some error in the previously sent packet or c) Timeout happens for BULK write. I will send USB capture once I reach office. Thanks, Sanjay -----Original Message----- From: Alan Stern [mailto:st...@ro...] Sent: Thursday, July 04, 2013 8:55 PM To: Hans de Goede Cc: Kumar, Sanjay; 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 On Thu, 4 Jul 2013, Hans de Goede wrote: > Alan, I believe the following is happening, there are 2 separate > userspace processes, lets call these bulk-backend and ctrl-status > > 1) bulk-backend does a detach of usblp + claim + submits a bulk > transfer > 2) ctrl-backend does a detach + claim, sends ctrl-req, this detaches > the usbfs instance which is attached on behalf of bulk-backend > 3) bulk-backend sees an error (cancel) because of the detach, retries > including re-doing the detach + claim I wouldn't expect a retry of a bulk transfer also to retry the detach + claim. But maybe it does... > And these retries are causing the data duplication. > > If I understand Sanjay correctly HPLIP has always had this race, and > libusb-1.0.16 "breaks" hplip, because it no longer allows the detach > in step 2. to proceed (it checks which driver is attached and returns > LIBUSB_ERROR_BUSY if it is usbfs). > > I believe sofar HPLIP has been getting away with this through sheer > luck. Sanjay's new test involved doing 2 repeatedly at a high > frequency, causing the race to turn into an error scenario. Yes, that would explain the results. Alan Stern |
From: Alan S. <st...@ro...> - 2013-07-04 17:29:37
|
On Thu, 4 Jul 2013, Kumar, Sanjay wrote: > Hi Hans, > > If I create two threads inside hp backend process (say bulk_writer() thread and control_requester() thread and control_requester() requests device ID every 3 seconds or so for testing purpose) and share the device handle in both threads, will that solve duplicate BULK data packet issue? Will there be a race condition even then? I think that will work correctly, with no races and no duplicate packets. > Basically I just want to understand that which of the following could be the real reason. > 1) As you mentioned, bulk-backend sees an error (cancel) because of the detach, retries including re-doing the detach + claim > 2) Because of too much of bandwidth consumed by BLOCKING control request, something like below happens. (This is what firmware developers suspect ) > a) Host controller does not receive (or miss) the ACK Packet from the device or > b) Sees some error in the previously sent packet or > c) Timeout happens for BULK write. Hans and I both suspect the reason is 1). > I will send USB capture once I reach office. Thank you. Alan Stern |
From: Hans de G. <hde...@re...> - 2013-07-05 07:01:55
|
Hi, On 07/04/2013 07:29 PM, Alan Stern wrote: > On Thu, 4 Jul 2013, Kumar, Sanjay wrote: > >> Hi Hans, >> >> If I create two threads inside hp backend process (say bulk_writer() thread and control_requester() thread and control_requester() requests device ID every 3 seconds or so for testing purpose) and share the device handle in both threads, will that solve duplicate BULK data packet issue? Will there be a race condition even then? > > I think that will work correctly, with no races and no duplicate > packets. I too believe that should work correctly. > >> Basically I just want to understand that which of the following could be the real reason. >> 1) As you mentioned, bulk-backend sees an error (cancel) because of the detach, retries including re-doing the detach + claim >> 2) Because of too much of bandwidth consumed by BLOCKING control request, something like below happens. (This is what firmware developers suspect ) >> a) Host controller does not receive (or miss) the ACK Packet from the device or >> b) Sees some error in the previously sent packet or >> c) Timeout happens for BULK write. > > Hans and I both suspect the reason is 1). As Alan already said, I too suspect the reason is 1). Regards, Hans |
From: Kumar, S. <san...@hp...> - 2013-07-05 12:15:47
|
Hello Hans/Alan, Yes, it works. Here is what I did. Created one thread control_requester() just before BULK transfer inside hp backend. This thread keeps on querying device id every second. I won't be able to send USB traces as it is huge in size (around 250 MB), But anyway above test case proves that your reasoning regarding duplicate packet is correct and checking USB traces will be of not much use. Thanks for all the help. Thanks, Sanjay -----Original Message----- From: Hans de Goede [mailto:hde...@re...] Sent: Friday, July 05, 2013 12:32 PM To: Alan Stern Cc: Kumar, Sanjay; 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 07/04/2013 07:29 PM, Alan Stern wrote: > On Thu, 4 Jul 2013, Kumar, Sanjay wrote: > >> Hi Hans, >> >> If I create two threads inside hp backend process (say bulk_writer() thread and control_requester() thread and control_requester() requests device ID every 3 seconds or so for testing purpose) and share the device handle in both threads, will that solve duplicate BULK data packet issue? Will there be a race condition even then? > > I think that will work correctly, with no races and no duplicate > packets. I too believe that should work correctly. > >> Basically I just want to understand that which of the following could be the real reason. >> 1) As you mentioned, bulk-backend sees an error (cancel) because of >> the detach, retries including re-doing the detach + claim >> 2) Because of too much of bandwidth consumed by BLOCKING control request, something like below happens. (This is what firmware developers suspect ) >> a) Host controller does not receive (or miss) the ACK Packet from the device or >> b) Sees some error in the previously sent packet or >> c) Timeout happens for BULK write. > > Hans and I both suspect the reason is 1). As Alan already said, I too suspect the reason is 1). Regards, Hans |