12

I am currently trying to interface with a USB audio device from user land. I currently have the device fully enumerated and I've set the interface and set the alternative interface to the interface non-zero-bandwidth alternative interface.

Firstly I have to say I can't use anything like libusb. I ned to do this via Linux's USB device file system.

So as far as I can tell I'm ready to begin receiving isochronous data. However I can find very little information on how to do an isochronous transfer.

From what I can tell I need to populate a usbdevfs_urb structure but I'm completely unsure of how exactly to fill this structure.

Also, once I have filled this structure am I right in thinking I need to call the following:

int retSubmit   = ioctl( fd, USBDEVFS_SUBMITURB, &usbRequest );

and then once submitted I can wait for the request to complete using

USBDEVFS_REAPURBNDELAY

In the case of REAPURBNDELAY what exactly is the parameter I need to pass?

Am I even barking up the right tree?

Any information would be massively appreciated.

Thanks in advance!

Edit:

I attempt to do the isochronous transfer as follows:

usbdevfs_urb&   urbRequest      = *(usbdevfs_urb*)malloc( 384 );
urbRequest.type                 = USBDEVFS_URB_TYPE_ISO;
urbRequest.endpoint             = mpEndpoint->GetEndpointAddress();//mpEndpoint->GetEndpointIndex();
urbRequest.status               = 0;
urbRequest.flags                = USBDEVFS_URB_ISO_ASAP;
urbRequest.buffer               = pData;
urbRequest.buffer_length        = 0;
urbRequest.actual_length        = 0;
urbRequest.start_frame          = 0;
urbRequest.number_of_packets    = 1;
urbRequest.error_count          = 0;
urbRequest.signr                = 0;
urbRequest.usercontext          = pData;

usbdevfs_iso_packet_desc* pIsoPacketDesc    = &urbRequest.iso_frame_desc[0];
pIsoPacketDesc->length          = 384;
pIsoPacketDesc->actual_length   = 0;
pIsoPacketDesc->status          = 0;

Unfgortunately this gives me an error of -28 (ENOSPC).

<7>[ 3184.243163] usb 1-1: usbfs: usb_submit_urb returned -28

I can't understand why there wouldn't be enough usb bus bandwidth. There is only 1 usb port and my device is the only device plugged into it.

Any thoughts?

Goz
  • 61,365
  • 24
  • 124
  • 204
  • @Jim Clay Because the specific platform in question is android and I already have an open file descriptor and I can't, due to permissions, open a device using libusb ... – Goz Nov 01 '11 at 22:06
  • Hi Goz, I'm currently trying to solve the same problem - that of isochronous transfers on android, avoiding libusb. Is there any way you would post a working code sample? My sticking point currently is struct definitions and request values. Where are you sourcing these? Thanks in advance. – Gusdor Mar 01 '13 at 15:12
  • @Gusdor: Its quite complicated. Basically I worked everything out from the documentation available at http://usb.org ... At some point I might actually get round to doing an android style api for isochronous transfers that works together with the android usb api. Its a lot of work, though, and I would rather not spend the time unless I can get someone to pay for it ;) I have a version of libusb that was passed on to me that doesn't require root though ... – Goz Mar 01 '13 at 18:11
  • No worries, @Goz. I started plugging though the usb audio spec at the weekend. It reads harder than it is so I'm sure I'll get there. Removing the HID driver remains a 'pro tip', thanks! – Gusdor Mar 04 '13 at 10:39
  • @Goz I have a further question as I am still trying to crack iso transfers. ioctl is setting errno to '2'. This is apparently not a valid code for ioctl but it makes me suspect that either my endpoint address or file descriptor are incorrect. I have read interesting things about marshalling filesdescriptors to use in native code but querying on the issue is complicated by the FileDescriptor class and Parcel API. I am calling USBConnection.getFileDescriptor():int. Is this correct? – Gusdor Apr 18 '13 at 13:26

3 Answers3

5

Ok so it turns out that the problem is due to the fact that the android OS has placed an HID driver to handle the HID controls. This seems to block up the bandwidth. Detaching these drivers from the HID interfaces releases the bandwidth allowing the isochronous transfer to proceed.

You detach the kernel driver by doing the following:

usbdevfs_ioctl command;
command.ifno        = mpInterface->GetInterfaceNumber();
command.ioctl_code  = USBDEVFS_DISCONNECT;
command.data        = NULL;

int ret = ioctl( fd, USBDEVFS_IOCTL, &command );

Otherwise what I have done is correct.

Goz
  • 61,365
  • 24
  • 124
  • 204
3

I understand the only reason you're not using libusb is that you can't open the usb device by by yourself but you do have a file descriptor pointing to it.

If this is all correct, why are you trying to re-implement everything there is in libusb instead of just re-implementing the usb_open() function which would take a file descriptor as argument and your struct usb_device*. You could take most of the code from the libusb usb_open() source code, and use libusb for the rest.

Quentin Casasnovas
  • 1,079
  • 5
  • 10
  • 2
    I don't understand your issue with the LGPL, are you developing a proprietary software? If this is the case, you can still link it with a LGPL library, as opposed to a GPL library. The only obligation you would have, if I remember correctly, would be to provide a way for linking with another library. If you're distributing a dynamically linked binary, then you have no issue. If you are providing a statically linked binary, then you would have to provide the object file of your binary so that people can re-link with something else easily. – Quentin Casasnovas Nov 06 '11 at 21:02
  • Alas I don't get to make that choice. – Goz Nov 06 '11 at 22:31
  • As it happens I've been experimenting with libusb. I rooted my device and can get as far as submitting an ISOC request. Then ... guess what? errno=28 :( – Goz Nov 09 '11 at 21:15
  • Cracked it. See my answer if you are interested in finding out what the issue was! – Goz Nov 11 '11 at 08:47
1

I have written a Java class for user mode USB isochronous transfer: UsbIso

It uses JNA to access the USBFS API via IOCTL calls.

Christian d'Heureuse
  • 5,090
  • 1
  • 32
  • 28