Re: Unable to Use Isochronous Behavior w/ Isoc Endpoint in FunctionFC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jun 21, 2020, at 9:09 AM, Alan Stern wrote:
> On Sat, Jun 20, 2020 at 10:38:33PM -0500, Sid Spry wrote:
> 
> > When I was using a repurposed audio device I had to set an alternate mode. Is
> > that related to the issue here? The alternate mode seems to be a relic of the
> > descriptor layout before I dropped the device class and substituted my own
> > driver. The current descriptors specify no alternate modes.
> 
> I don't know much about FunctionFS, so I can't help with your main 
> question about isochronous packets not being dropped.  But I can explain 
> this.
> 

Your responses have been quite helpful; I appreciate them.

For those reading along I have gotten a set of descriptors working (detailed
below) however write(2) still blocks meaning at least one stale data packet
will be received. However, I realize now that typically a writer thread will be
sending an asynchronously updated buffer and the single stale packet was
probably never noticed, especially for AV applications.

Unfortunately for my application the stale packet *does* matter, and I am still
seeking a way to mitigate it.

> In the USB-2.0 spec, at the end of section 5.6.3 the text says:
> 
> 	All device default interface settings must not include any 
> 	isochronous endpoints with non-zero data payload sizes (specified 
> 	via wMaxPacketSize in the endpoint descriptor). Alternate 
> 	interface settings may specify non-zero data payload sizes for 
> 	isochronous endpoints.
> 
> That's why you had to select an alternate setting before transferring 
> any isochronous data.  Any isochronous endpoint in altsetting 0 must have 
> its maxpacket size set to 0.
> 

This was the issue. I rely too heavily on the USB audio class spec, I should go
through all of the spec.

I now must ask the list: What is the relation of the isochronous endpoint setup
to the allocated bandwidth on the bus? I understand the limit of 3 1024 byte
transfers per frame, but this says nothing about how it will be allocated or
how a device is refused bandwidth. Do I need to look for link degradation on
the application layer? It seems like having a single non-spec device means
the OS can't arbitrate link bandwidth.


Also!

For the list's consideration I have included an accepted but nonworking
configuration that perplexes me. The application note for the original device
I used specified a set of descriptors which was like so (device and
configuration omitted):

(Vendor Microphone Class Descriptors)
```
    INTERFACE 0: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x0
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x1
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
    INTERFACE 1: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x0
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x2
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
    INTERFACE 1, 1: Vendor Specific ========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x1
     bNumEndpoints      :    0x1
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x2
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x81: Isochronous IN ========================
       bLength          :    0x9 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x5 Isochronous
       wMaxPacketSize   :   0xc8 (200 bytes)
       bInterval        :    0x1
```

If I (almost) match that:

(FunctionFS Device Descriptors)
```
    INTERFACE 0: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x0
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x5 Source/Sink
    INTERFACE 1: Vendor Specific ===========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x0
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x6 Isoc Source/Sink
    INTERFACE 1, 1: Vendor Specific ========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x1
     bNumEndpoints      :    0x2
     bInterfaceClass    :   0xff Vendor Specific
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x6 Isoc Source/Sink
      ENDPOINT 0x81: Isochronous IN ========================
       bLength          :    0x9 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x81 IN
       bmAttributes     :    0x5 Isochronous
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x1
      ENDPOINT 0x1: Isochronous OUT ========================
       bLength          :    0x9 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x1 OUT
       bmAttributes     :    0x5 Isochronous
       wMaxPacketSize   :  0x200 (512 bytes)
       bInterval        :    0x1
```

libusb seems to encounter an error:

(pyusb error output)
```
>>> import usb
>>> ds = [d for d in usb.core.find(find_all=True, idVendor=0x1d6b, idProduct=0x0104)]
>>> d = ds[0]
>>> d.set_interface_altsetting(interface=1, alternate_setting=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/usb/core.py", line 902, in set_interface_altsetting
    self._ctx.managed_set_interface(self, interface, alternate_setting)
  File "/usr/lib/python3.7/site-packages/usb/core.py", line 102, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3.7/site-packages/usb/core.py", line 204, in managed_set_interface
    self.backend.set_interface_altsetting(self.handle, i.bInterfaceNumber, alt)
  File "/usr/lib/python3.7/site-packages/usb/backend/libusb1.py", line 807, in set_interface_altsetting
    altsetting))
  File "/usr/lib/python3.7/site-packages/usb/backend/libusb1.py", line 595, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno None] Other error
```

(libusb error from C code)
```
libusb: error [op_set_interface] setintf failed error -1 errno 32
```

But, if interface 1 alternate setting 0 is dropped, and interface 1 alternate
setting 1 is kept, both invocations work and my C code spits out data very
fast, although I must inspect it further as I seem to be duplicating data in my
reads.



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux