USB differences between 10.0 and 10.3

Hello,

I have a USB-interface program (Client Software according to the USB 2.0 doc) which works on SuSe 10.0, but not SuSe 10.3. The problem seems to be related to the usb_bulk_write() call. One computer runs 32-bit SuSe 10.0 with kernel version 2.6.13-15.16; the other runs 64-bit SuSe 10.3 with kernel version 2.6.22.17-0.1 Both machines are native 64-bit. Both machines use libusb-0.1.12 The USB device is a Tektronix TDS2014B oscilloscope, but I’ve tested the code with different cables, different ports, and different 'scopes. The problem seems to be in the OS / kernel. Can anyone give me pointers on where I might find & fix the trouble? This is my test code:

/* This program is intended to simply test the libusb library
 *  compile it with something like:
 *      gcc -o npt_stripped npt_stripped.c
 *  run it with something like:
 *      ./npt_stripped
 *
 *  Adapted from sending.py and pyusb.c
 *
 *  See SJM notes Vol #6 p. 132, 135, 138
 */
#include <usb.h>
#include "usbi.h"   /* get the usb_dev_handle type */
#include <stdio.h>
//#include <string.h>

int claimInterface(struct usb_dev_handle *hand){
    struct usb_device *devo;
    struct usb_device_descriptor    desc;
    struct usb_config_descriptor    *conf;
    struct usb_interface    *intf;
    struct usb_interface_descriptor *interred;
    struct usb_endpoint_descriptor eep;

    devo=hand->device;

    desc=devo->descriptor;

    printf("Chosen device has idVendor %d and idProduct %d.
",desc.idVendor, desc.idProduct);
    printf("It has %d available configurations.
",desc.bNumConfigurations);

    conf=devo->config;
    printf("config %d is available.
",conf[0].bConfigurationValue);
    intf=conf[0].interface;
    interred=intf[0].altsetting;
    printf("interface w/ inf. number %d and alt. setting number %d is available.
", interred[0].bInterfaceNumber, interred[0].bAlternateSetting);
    eep=(interred->endpoint)[1];

    printf("
Endpoint %d has Length %d,
",eep.bEndpointAddress, eep.bLength);
    printf("        DescriptorType %d, mAttributes %x, MaxPacketSize %d,
", eep.bDescriptorType, eep.bmAttributes, eep.wMaxPacketSize);
    printf("        SynchAddress %d, and extra descriptors:(
",eep.bSynchAddress);
    printf("         )
");

    printf("Attempting to claim interface %d.
",(int)interred->bInterfaceNumber);
    return usb_claim_interface(hand,(int)interred->bInterfaceNumber);
}

struct usb_device *getscope(void){
    struct usb_bus  *thisbus;
    struct usb_device *devo;
    struct usb_device_descriptor    desc;
    struct usb_config_descriptor    *conf;
    int done;

    usb_find_busses( ); //returns number of busses

    usb_find_devices();   //returns total number of devices on all busses
        //usb_find_devices() fills inthe ->devices fields for each bus.

    thisbus=usb_get_busses();   //pick the first bus in a doubly-linked list

        //scroll to where the scope is usually mounted
        //change the number of "->next" to get a different bus
    done=0;
    while (!done){
        devo=thisbus->devices;
        desc=devo->descriptor;
        printf("Found vendor %d w/ product %d:  ",desc.idVendor, desc.idProduct);
        if((desc.idVendor==1689) && (desc.idProduct==872)){
            printf("This is the right device.
");
            done=1;
        }
        else{
            if (thisbus->next){
                thisbus=thisbus->next;
                printf("Trying next bus.
");
            }
            else{
                printf("Out of busses; giving up.
");
                devo=0;
                done=1;
            }
        }
    }

    conf=devo->config;
    printf("Base configuration for this device is number %d.
", conf[0].bConfigurationValue);

    return devo;
}

int main(void){
    struct usb_device *devo;
    struct usb_dev_handle *hand;
    int count,altnum,
        writeret,ret;    //value returned by function calls.
    unsigned char btag, nbtag;
    char stop[28]="\x01\x01\xfe\0\x0e\0\0\0\x01\0\0\0acq:state stop
\0";
    //char stop[20]="\x01\x01\xfe\0\x0e\0\0\0\x01\0\0\0loc all
";

    count=1;

    usb_init();
    usb_set_debug(0);

    devo=getscope();

    hand=usb_open(devo);
    if(!hand){
        printf("
%s

\a",usb_strerror());
        return -1;
    }
    else{
        printf("usb_open returned a handle %d.
",hand);
    }

    usb_set_debug(1);

    printf("Handle has Config %d, Intf %d, and AltSetting %d.
",hand->config,hand->interface, hand->altsetting);

    ret=usb_set_configuration(hand,1);
    printf("setConfig returned %d.
",ret);
    if(ret){
        printf("
%s

\a",usb_strerror());
        return -1;
    }

    printf("Handle has Config %d, Intf %d, and AltSetting %d.
",hand->config,hand->interface, hand->altsetting);

    ret=claimInterface(hand);
    printf("claimInterface returned %d.
",ret);
    if(ret){
        printf("
%s

\a",usb_strerror());
        return -1;
    }

    printf("Handle has Config %d, Intf %d, and AltSetting %d.
",hand->config,hand->interface, hand->altsetting);

    altnum=0;
    printf("attempting to set altinterface to %d.
",altnum);
    ret=usb_set_altinterface(hand,altnum);
    printf("SetAltInterface returned %d.
",ret);
    if(ret){
        printf("
%s

\a",usb_strerror());
        return -1;
    }

    printf("Handle has Config %d, Intf %d, and AltSetting %d.
",hand->config,hand->interface, hand->altsetting);

    while(count>0){
        btag=(unsigned char) count;
        nbtag=~btag;
        printf("
initialize iteration %d = x%02x ~x%02x
",count,btag,nbtag);
        stop[1]=btag;
        stop[2]=nbtag;

        fflush(stdout);
        fflush(stderr);

        //writeret=usb_bulk_write(hand,6,stop,20,16000);
        writeret=usb_bulk_write(hand,6,stop,28,16000);
        printf("bulkWrite returned %d.
",writeret);
        if(writeret<0){
            printf("
                  %s

",usb_strerror());
        }
        else{
            printf("
                  Success

");
        }

        printf("iteration %d Handle has Config %d, Intf %d, and AltSetting %d.
",count,hand->config,hand->interface, hand->altsetting);

                //choose single pass versus infinite loop
        if (writeret<0)
            count++;
        else
            count=0;

        if (count>5)
            count=0;
    }
    ret=usb_release_interface(hand, hand->interface);
    printf("release iteration %d returned %d

",count,ret);

    return 0;
}

To recap (with extra-tasty detail):
Program Q (which is 4458 lines long, and so not reproduced here) works fine on Computer A (process control) but not computer B (mine, debugging & programming). Computer A uses SuSe 10.0 with linux-2.6.13-15.16; Computer B uses SuSe 10.3 with linux-2.6.22.17-0.1 This has been confirmed for multiple scopes, multiple cables, and multiple USB ports. Therefore the problem is in Computer B, below the level of libusb-0.1.12, which is installed on both A & B.
Computer B previously had an installation of SuSe 10.0 with linux-2.6.13-15.16. Call that earlier configuration B’. Program Q worked fine with B’, and showed no trouble until the upgrade to SuSe 10.3 Therefore the problem is not the hardware.
To make debugging of this issue manageable, I trimmed Q down to 182 lines by ripping out most of the functionality. Call this shorter version R, above. On computer B, Q & R both give the same Connection-timed-out error message. The test command (“acq:state stop”) is taken directly from the scope manual. I’ve also tried several other forms for the test command and several other test commands for R; these commands appear directly in Q. All give the same error message.
USB flash drives and printer work. This makes me think the error is relatively high up… maybe just below the libusb level.

     I'd like to identify which library or module is causing trouble, and either fix it or replace it.  How do I identify which ioctl.h (for example) gets included?  How do I extend debugging tools further down into the Host Controller Driver?  Where can I find docs describing how libusb interfaces with the software level below it?

     SuSe 10.0 is no longer available, and I'll need to upgrade the OS on Computer A to support additional hardware.  This makes me think that SuSe 10.3 is the way to go, esp. since that OS is used by most of the company.

  Thanks....  (and sorry if my frustration's coming through the email - I've been hammering on this problem longer than I like to admit.)

SMesser wrote:
> Hello,
>
> I have a USB-interface program (Client Software according to the USB
> 2.0 doc) which works on SuSe 10.0, but not SuSe 10.3. The problem seems
> to be related to the usb_bulk_write() call. One computer runs 32-bit
> SuSe 10.0 with kernel version 2.6.13-15.16; the other runs 64-bit SuSe
> 10.3 with kernel version 2.6.22.17-0.1 Both machines are native
> 64-bit. Both machines use libusb-0.1.12 The USB device is a Tektronix
> TDS2014B oscilloscope, but I’ve tested the code with different cables,
> different ports, and different 'scopes. The problem seems to be in the
> OS / kernel. Can anyone give me pointers on where I might find & fix
> the trouble? This is my test code:

No help… but I do know that hotplugging changed RADICALLY from 10.0
to 10.3. Might be related??

My problem seems to have separated itself into two discrete chunks:

  1. The scope doesn’t reliably acknowledge the PC’s bulkWrite attempts unless there is an external USB hub in the path. This happens on 2 different PCs, for Suse 10.0 and 10.3, and for multiple scopes (I think… there’ve been multiple rounds of debugging / error-hunting, and I’m getting a bit muddled with them.)

  2. udev and the rules in /etc/udev/rules.d/55-libsane.rules doesn’t seem to set up the permissions right. I can get udevcontrol log messages saying the device was added to group usb with r/w permissions, but members of group usb get a “operation not permitted” error when trying to access the scope. This is different between 10.0 and 10.3. Can you point me to docs on how hotplugging changed between 10.0 and 10.3? Or maybe some FAQs / help on hotplugging and permissions?

Thanks.

SMesser wrote:
> My problem seems to have separated itself into two discrete chunks:
>
> 1) The scope doesn’t reliably acknowledge the PC’s bulkWrite attempts
> unless there is an external USB hub in the path. This happens on 2
> different PCs, for Suse 10.0 and 10.3, and for multiple scopes (I
> think… there’ve been multiple rounds of debugging / error-hunting,
> and I’m getting a bit muddled with them.)
>
> 2) udev and the rules in /etc/udev/rules.d/55-libsane.rules doesn’t
> seem to set up the permissions right. I can get udevcontrol log
> messages saying the device was added to group usb with r/w permissions,
> but members of group usb get a “operation not permitted” error when
> trying to access the scope. This is different between 10.0 and 10.3.
> Can you point me to docs on how hotplugging changed between 10.0 and
> 10.3? Or maybe some FAQs / help on hotplugging and permissions?
>
> Thanks.
>
>

http://www.ntlug.org/Articles/Hotplug?action=login

Login as: GuestReader/guestguest

The article isn’t finished which is why it’s not
available without logging in. So… it may not have
enough info to help out, but it might be enough
to get you started on the path (I really need to finish
that article).

Thanks for the reference. Here is the output from udevmonitor --env when the scope is turned on / attached

ll claims the /dev file is set up as follows:
crw-rw-r-- 1 root usb 189, 3

… any idea why members of usb can’t access the scope? (running “groups sarah” confirms sarah is in usb)

Thanks.
-Sarah

env.boot:


udevmonitor will print the received events for:
UDEV the event which udev sends out after rule processing
UEVENT the kernel uevent

UEVENT[1213795404.362844] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5
SUBSYSTEM=usb
SEQNUM=1683
MAJOR=189
MINOR=132
DEVTYPE=usb_device
DEVICE=/proc/bus/usb/002/005
PRODUCT=699/368/42
TYPE=0/0/0
BUSNUM=002
DEVNUM=005

UEVENT[1213795404.362893] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/usb_endpoint/usbdev2.5_ep00 (usb_endpoint)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/usb_endpoint/usbdev2.5_ep00
SUBSYSTEM=usb_endpoint
SEQNUM=1684
MAJOR=254
MINOR=19

UEVENT[1213795404.368929] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0
SUBSYSTEM=usb
SEQNUM=1685
DEVTYPE=usb_interface
DEVICE=/proc/bus/usb/002/005
PRODUCT=699/368/42
TYPE=0/0/0
INTERFACE=254/3/1
MODALIAS=usb:v0699p0368d0042dc00dsc00dp00icFEisc03ip01

UEVENT[1213795404.368952] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep85 (usb_endpoint)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep85
SUBSYSTEM=usb_endpoint
SEQNUM=1686
MAJOR=254
MINOR=20

UEVENT[1213795404.368960] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep06 (usb_endpoint)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep06
SUBSYSTEM=usb_endpoint
SEQNUM=1687
MAJOR=254
MINOR=21

UEVENT[1213795404.368967] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep87 (usb_endpoint)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep87
SUBSYSTEM=usb_endpoint
SEQNUM=1688
MAJOR=254
MINOR=22

UDEV  [1213795404.391825] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5 (usb)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5
SUBSYSTEM=usb
SEQNUM=1683
MAJOR=189
MINOR=132
DEVTYPE=usb_device
DEVICE=/proc/bus/usb/002/005
PRODUCT=699/368/42
TYPE=0/0/0
BUSNUM=002
DEVNUM=005
UDEVD_EVENT=1
DEVNAME=/dev/bus/usb/002/005

UDEV  [1213795404.394237] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/usb_endpoint/usbdev2.5_ep00 (usb_endpoint)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/usb_endpoint/usbdev2.5_ep00
SUBSYSTEM=usb_endpoint
SEQNUM=1684
MAJOR=254
MINOR=19
UDEVD_EVENT=1
DEVNAME=/dev/usbdev2.5_ep00

UDEV  [1213795404.424971] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0 (usb)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0
SUBSYSTEM=usb
SEQNUM=1685
DEVTYPE=usb_interface
DEVICE=/proc/bus/usb/002/005
PRODUCT=699/368/42
TYPE=0/0/0
INTERFACE=254/3/1
MODALIAS=usb:v0699p0368d0042dc00dsc00dp00icFEisc03ip01
UDEVD_EVENT=1

UDEV  [1213795404.425021] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep85 (usb_endpoint)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep85
SUBSYSTEM=usb_endpoint
SEQNUM=1686
MAJOR=254
MINOR=20
UDEVD_EVENT=1
DEVNAME=/dev/usbdev2.5_ep85

UDEV  [1213795404.425634] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep06 (usb_endpoint)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep06
SUBSYSTEM=usb_endpoint
SEQNUM=1687
MAJOR=254
MINOR=21
UDEVD_EVENT=1
DEVNAME=/dev/usbdev2.5_ep06

UDEV  [1213795404.426169] add      /devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep87 (usb_endpoint)
UDEV_LOG=7
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb2/2-4/2-4.5/2-4.5:1.0/usb_endpoint/usbdev2.5_ep87
SUBSYSTEM=usb_endpoint
SEQNUM=1688
MAJOR=254
MINOR=22
UDEVD_EVENT=1
DEVNAME=/dev/usbdev2.5_ep87