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.)