public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
@ 2021-06-30 23:01 Ethin Probst
  2021-07-01 14:15 ` [edk2-devel] " Michael Brown
  2021-07-02  8:54 ` Laszlo Ersek
  0 siblings, 2 replies; 10+ messages in thread
From: Ethin Probst @ 2021-06-30 23:01 UTC (permalink / raw)
  To: devel

[-- Attachment #1: Type: text/plain, Size: 2267 bytes --]

Hi all,
So Leif and I have been working on USB Audio but we've run into a snag. We've encountered a problem -- neither of us knows enough about USB to figure out how to get the class-specific AC interface descriptors, and those contain vital information that I need to be able to control the audio device. The audio specification was quite useless. So I have two projects running in parallel: the USB audio one and the VirtIO audio (We managed to get the virtio-snd patchset in qemu and I've got a built version of it over here and, though its not a fully working implementation, as long as I get something -- no matter how bad it sounds -- I'll be happy). Whichever project we get working first is the one we move forward with.
The VirtIO sound device specification contains four virtqueues: the control queue for controlling the device; the event queue for receiving notifications from the device; the tx queue for transmitting audio data to the device; and the rx queue for receiving audio data from the device. Thus far I've been following the VirtioRngDxe code as a guide on how to get a VirtIO device initialized using the VirtioLib in OVMF, but I've reached an impasse regarding the queues and descriptors.

The VirtioRngDxe DXE uses a single descriptor and a single queue for operation. However, the RNG device works vastly differently to the audio device and is far simpler. The virtio-snd specification says that, to initialize the device, I must (copied from the spec):

* Configure the control, event, tx and rx queues.
* Read the jacks field and send a control request to query information about the available jacks.
* Read the streams field and send a control request to query information about the available PCM streams.
* Read the chmaps field and send a control request to query information about the available channel maps.
* Populate the event queue with empty buffers.

Steps 2, 3, 4, and 5 are a bit confusing and raise some questions:

1. Does the device automatically send notifications in the event queue about the jacks, streams, and channel maps, or do I have to explicitly ask for them?
2. How many buffers would we need to populate the event queue with, and what VirtioLib function (if any) specifically accomplishes that?

[-- Attachment #2: Type: text/html, Size: 2333 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-06-30 23:01 EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization Ethin Probst
@ 2021-07-01 14:15 ` Michael Brown
  2021-07-01 18:10   ` Ethin Probst
  2021-07-02  8:54 ` Laszlo Ersek
  1 sibling, 1 reply; 10+ messages in thread
From: Michael Brown @ 2021-07-01 14:15 UTC (permalink / raw)
  To: devel, harlydavidsen

On 01/07/2021 00:01, Ethin Probst wrote:
> So Leif and I have been working on USB Audio but we've run into a snag. 
> We've encountered a problem -- neither of us knows enough about USB to 
> figure out how to get the class-specific AC interface descriptors, and 
> those contain vital information that I need to be able to control the 
> audio device.

Do you mean that you can't figure out how to retrieve the descriptors 
via the UEFI APIs, or that you don't know how to interpret the 
descriptors after retrieval?

Thanks,

Michael

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-01 14:15 ` [edk2-devel] " Michael Brown
@ 2021-07-01 18:10   ` Ethin Probst
  2021-07-02  8:59     ` Laszlo Ersek
                       ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Ethin Probst @ 2021-07-01 18:10 UTC (permalink / raw)
  To: Michael Brown; +Cc: devel

The first: I don't know how to retrieve the descriptors on the UEFI
API. I've looked at the Chaos Key DXE, if memory serves, or the
display port one -- one of the two. One of them contained a
ReadDescriptor() function, and so I've borrowed that, but that doesn't
really help much.

On 7/1/21, Michael Brown <mcb30@ipxe.org> wrote:
> On 01/07/2021 00:01, Ethin Probst wrote:
>> So Leif and I have been working on USB Audio but we've run into a snag.
>> We've encountered a problem -- neither of us knows enough about USB to
>> figure out how to get the class-specific AC interface descriptors, and
>> those contain vital information that I need to be able to control the
>> audio device.
>
> Do you mean that you can't figure out how to retrieve the descriptors
> via the UEFI APIs, or that you don't know how to interpret the
> descriptors after retrieval?
>
> Thanks,
>
> Michael
>


-- 
Signed,
Ethin D. Probst

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-06-30 23:01 EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization Ethin Probst
  2021-07-01 14:15 ` [edk2-devel] " Michael Brown
@ 2021-07-02  8:54 ` Laszlo Ersek
  1 sibling, 0 replies; 10+ messages in thread
From: Laszlo Ersek @ 2021-07-02  8:54 UTC (permalink / raw)
  To: devel, harlydavidsen

On 07/01/21 01:01, Ethin Probst wrote:
> Hi all,
> So Leif and I have been working on USB Audio but we've run into a snag. We've encountered a problem -- neither of us knows enough about USB to figure out how to get the class-specific AC interface descriptors, and those contain vital information that I need to be able to control the audio device. The audio specification was quite useless. So I have two projects running in parallel: the USB audio one and the VirtIO audio (We managed to get the virtio-snd patchset in qemu and I've got a built version of it over here and, though its not a fully working implementation, as long as I get something -- no matter how bad it sounds -- I'll be happy). Whichever project we get working first is the one we move forward with.
> The VirtIO sound device specification contains four virtqueues: the control queue for controlling the device; the event queue for receiving notifications from the device; the tx queue for transmitting audio data to the device; and the rx queue for receiving audio data from the device. Thus far I've been following the VirtioRngDxe code as a guide on how to get a VirtIO device initialized using the VirtioLib in OVMF, but I've reached an impasse regarding the queues and descriptors.
> 
> The VirtioRngDxe DXE uses a single descriptor and a single queue for operation. However, the RNG device works vastly differently to the audio device and is far simpler. The virtio-snd specification says that, to initialize the device, I must (copied from the spec):
> 
> * Configure the control, event, tx and rx queues.
> * Read the jacks field and send a control request to query information about the available jacks.
> * Read the streams field and send a control request to query information about the available PCM streams.
> * Read the chmaps field and send a control request to query information about the available channel maps.
> * Populate the event queue with empty buffers.
> 
> Steps 2, 3, 4, and 5 are a bit confusing and raise some questions:
> 
> 1. Does the device automatically send notifications in the event queue about the jacks, streams, and channel maps, or do I have to explicitly ask for them?
> 2. How many buffers would we need to populate the event queue with, and what VirtioLib function (if any) specifically accomplishes that?

What you describe here makes the virtio-sound device the most complex
virtio device that OVMF has ever had any interest in. The only driver
you can use as an example is VirtioNetDxe. VirtioRngDxe is about the
simplest virtio device / driver, but for an example here, you need to be
looking at the opposite end of the spectrum.

For the duplex communication, please refer in particular to
"OvmfPkg/VirtioNetDxe/TechNotes.txt".

In virtio, requests are always created by the driver (= the guest), and
requests are always completed by the device (= the host). Therefore, for
asynchronous host-to-guest communication, the guest has to fully
pre-populate the affected queues with requests, and when host actions
arrive (technically presented as "request completions"), the guest has
to process those "completions" and re-populate the affected queue at
once to the brim.

VirtioLib provides a number of utility / convenience functions, for
various areas / actions. However, the VirtioPrepare(),
VirtioAppendDesc(), VirtioFlush() functions in particular are
inappropriate for your use case. Those helper functions implement a
simple, synchronous request-response pattern, building and submitting a
single descriptor chain, and blocking until the host reports that chain
processed. These functions exist because this simple pattern is suitable
for most of the virtio drivers (VirtioBlkDxe, VirtioFsDxe, VirtioGpuDxe,
VirtioRngDxe, VirtioScsiDxe). The reason being that the UEFI protocols
implemented all support the same, simple, synchronous pattern. These
functions are however not helpful for actual async communication, so
they are not used in VirtioNetDxe -- VirtioNetDxe does its own queue and
descriptor chain management. (It's documented in detail in "TechNotes.txt".)

To be honest, I would recommend abandoning the virtio-sound path for
now. The virtio programming will eat up a huge amount of your time, and
that's not what you want to be concentrating on.

I had had no previous experience with either audio programming or the
virtio-sound device itself; TBH I didn't expect this level of complexity
(in particular, based on your description, that *all four* queues would
have to be initialized, no questions asked). The virtio drivers in OVMF
are always kept as simple as possible, only the inevitably necessary
queues are initialized (and the devices are configured accordingly), and
only the simplest communication patterns are used. These drivers are not
OS drivers; what they need to do is "facilitate booting".

Example: the BlockIo protocol only supports synchronous requests,
whereas the BlockIo2 protocol supports asynchronous requests as well.
Technically speaking, virtio is fully capable of implementing the
asynchrony of BlockIo2, so (e.g.) a BlockIo2 protocol implementation on
top of virtio-blk would be possible. But why bother? It just complicates
the code a whole lot, and booting an OS with just BlockIo is
sufficiently fast already. VirtioNetDxe *must* be different however,
because the UEFI-level abstraction, SimpleNetworkProtocol (SNP), is
truly asynchronous itself.

If you can design a UEFI protocol for just sound *output* that lets you
get away with synchronous (blocking) UEFI protocol member function
calls, then you *might* be able to ignore most of the virtio-sound
complexity, and use the existent descriptor chain management functions
in VirtioLib. You could perhaps ignore the "event" and "rx" queues
altogether, and use the synchronous VirtioLib functions for both
"control" requests and actual audio output ("tx"). I can't tell.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-01 18:10   ` Ethin Probst
@ 2021-07-02  8:59     ` Laszlo Ersek
  2021-07-02  9:41     ` Michael Brown
       [not found]     ` <168DEFFB0E406B59.30759@groups.io>
  2 siblings, 0 replies; 10+ messages in thread
From: Laszlo Ersek @ 2021-07-02  8:59 UTC (permalink / raw)
  To: devel, harlydavidsen, Michael Brown, Ray Ni, Hao A Wu

On 07/01/21 20:10, Ethin Probst wrote:
> The first: I don't know how to retrieve the descriptors on the UEFI
> API. I've looked at the Chaos Key DXE, if memory serves, or the
> display port one -- one of the two. One of them contained a
> ReadDescriptor() function, and so I've borrowed that, but that doesn't
> really help much.

Does the stuff in "MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c" help?

(I don't know how that's exposed, if at all, through UEFI protocols, alas.)

I've added Hao and Ray to the address list (IIUC they maintain the USB
modules in edk2).

Thanks
Laszlo

> 
> On 7/1/21, Michael Brown <mcb30@ipxe.org> wrote:
>> On 01/07/2021 00:01, Ethin Probst wrote:
>>> So Leif and I have been working on USB Audio but we've run into a snag.
>>> We've encountered a problem -- neither of us knows enough about USB to
>>> figure out how to get the class-specific AC interface descriptors, and
>>> those contain vital information that I need to be able to control the
>>> audio device.
>>
>> Do you mean that you can't figure out how to retrieve the descriptors
>> via the UEFI APIs, or that you don't know how to interpret the
>> descriptors after retrieval?
>>
>> Thanks,
>>
>> Michael
>>
> 
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-01 18:10   ` Ethin Probst
  2021-07-02  8:59     ` Laszlo Ersek
@ 2021-07-02  9:41     ` Michael Brown
       [not found]     ` <168DEFFB0E406B59.30759@groups.io>
  2 siblings, 0 replies; 10+ messages in thread
From: Michael Brown @ 2021-07-02  9:41 UTC (permalink / raw)
  To: Ethin Probst; +Cc: devel

On 01/07/2021 19:10, Ethin Probst wrote:
> The first: I don't know how to retrieve the descriptors on the UEFI
> API. I've looked at the Chaos Key DXE, if memory serves, or the
> display port one -- one of the two. One of them contained a
> ReadDescriptor() function, and so I've borrowed that, but that doesn't
> really help much.

I have no idea what higher-level utility library functions exist within 
EDK2 that you might be able to use.  Based on skimming through the USB 
audio spec, at the raw protocol level you would need to use 
EFI_USB_IO_PROTOCOL.UsbControlTransfer() something like:

#define AUDIO_CS_INTERFACE 0x24

#pragma pack(1)
typedef struct {
   UINT8 Length;
   UINT8 DescriptorType;
   UINT8 DescriptorSubType;
   UINT16 BcdADC;
   UINT16 TotalLength;
   UINT8 InCollection;
} AUDIO_HEADER_DESCRIPTOR;
#pragma pack()

EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
EFI_USB_DEVICE_REQUEST Req;
AUDIO_CS_HEADER Header;
UINT32 Status;

UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDescriptor);

Req.RequestType = (USB_DEV_GET_DESCRIPTOR_REQ_TYPE |
                    USB_REQ_TYPE_CLASS);
Req.Request = USB_REQ_GET_DESCRIPTOR;
Req.Value = (AUDIO_CS_INTERFACE << 8);
Req.Index = InterfaceDescriptor.InterfaceNumber;
Req.Length = sizeof(Header);

UsbIo->UsbControlTransfer(UsbIo, &Req, EfiUsbDataIn,
                           PcdGet32 (PcdUsbTransferTimeoutValue),
                           &Header, sizeof(Header), &Status);

(Error handling etc omitted for brevity)

That would get you the first 8 bytes of the class-specific AC interface 
header descriptor.  You would then need to extract the TotalLength 
field, allocate that length of memory, and repeat the 
UsbControlTransfer() call to fetch the full-length descriptor into the 
newly allocated block.

Hope that helps,

Michael

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
       [not found]     ` <168DEFFB0E406B59.30759@groups.io>
@ 2021-07-02  9:46       ` Michael Brown
  2021-07-02 18:18         ` Ethin Probst
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Brown @ 2021-07-02  9:46 UTC (permalink / raw)
  To: Ethin Probst; +Cc: devel

On 02/07/2021 10:41, Michael Brown wrote:
> UsbIo->UsbControlTransfer(UsbIo, &Req, EfiUsbDataIn,
>                            PcdGet32 (PcdUsbTransferTimeoutValue),
>                            &Header, sizeof(Header), &Status);
> 
> (Error handling etc omitted for brevity)
> 
> That would get you the first 8 bytes of the class-specific AC interface 
> header descriptor.  You would then need to extract the TotalLength 
> field, allocate that length of memory, and repeat the 
> UsbControlTransfer() call to fetch the full-length descriptor into the 
> newly allocated block.
> 
> Hope that helps,

BTW, in case you aren't already aware of this: wireshark is pretty good 
at dissecting USB traffic.  You can capture it by doing a "modprobe 
usbmon", after which you'll see a number of usbmonN devices show up in 
the wireshark interface list.  Try them each in turn until you find 
which one corresponds to the host controller to which your device is 
attached.

My normal method for developing or debugging iPXE USB drivers will 
typically involve using wireshark to capture the USB traffic that 
happens when the device is being used by a known-working driver (e.g. 
the Linux driver for that device) and comparing it to the traffic that 
happens when I'm using my own driver (via USB pass-through in a VM). 
This is often a lot faster than trying to pull together all of the 
information from the multiple USB spec documents.

Good luck!

Michael

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-02  9:46       ` Michael Brown
@ 2021-07-02 18:18         ` Ethin Probst
  2021-07-02 18:22           ` Ethin Probst
  0 siblings, 1 reply; 10+ messages in thread
From: Ethin Probst @ 2021-07-02 18:18 UTC (permalink / raw)
  To: devel, mcb30

Thank you for all that information, both of you. I didn't realize that
VirtIO sound would be so complicated. The specification seemed simple
enough -- but, alas, all things seem simple until you actually go and
try to implement them.

I did manage to retrieve a packet dump, from both myself and from
somebody else that Leif contacted. The one from myself was from a USB
mixer that I have -- its how my audio headphones work, and that
generated far too many packets -- well over 5,000 at least. Utilizing
display filters wasn't much of a help either -- it doesn't seem like
my mixer makes available an audio device class descriptor anywhere,
which is odd because it should. But I also might not have been
filtering it properly. The other packet dump was sort-of helpful, but
did contain some confusing elements:

* There were four unknown URB transfer types (0x7F) that Wireshark
claimed were "malformed". I asked around on the OSDev.org forum and I
don't think anyone recognizes that either.
* The primary init sequence was understandable, along with the get
string requests, but after that there were a bunch of URB control
transfers from device-to-host and some requests from host-to-device
containing data that I didn't understand. I wasn't sure what those
were for. They looked something like this:

Frame 29: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on
interface wireshark_extcap1868, id 0
    Interface id: 0 (wireshark_extcap1868)
        Interface name: wireshark_extcap1868
    Encapsulation type: USB packets with USBPcap header (152)
    Arrival Time: Jul  1, 2021 02:21:45.291271000 CDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1625124105.291271000 seconds
    [Time delta from previous captured frame: 0.000008000 seconds]
    [Time delta from previous displayed frame: 0.000008000 seconds]
    [Time since reference or first frame: 0.035324000 seconds]
    Frame Number: 29
    Frame Length: 36 bytes (288 bits)
    Capture Length: 36 bytes (288 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: usb]
USB URB
    [Source: host]
    [Destination: 2.7.0]
    USBPcap pseudoheader length: 28
    IRP ID: 0xffffa90f548b8a20
    IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
    URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
    IRP information: 0x00, Direction: FDO -> PDO
        0000 000. = Reserved: 0x00
        .... ...0 = Direction: FDO -> PDO (0x0)
    URB bus id: 2
    Device address: 7
    Endpoint: 0x80, Direction: IN
        1... .... = Direction: IN (1)
        .... 0000 = Endpoint number: 0
    URB transfer type: URB_CONTROL (0x02)
    Packet Data Length: 8
    [Response in: 30]
    Control transfer stage: Setup (0)
    [bInterfaceClass: Audio (0x01)]
Setup Data
    bmRequestType: 0xa1
        1... .... = Direction: Device-to-host
        .01. .... = Type: Class (0x1)
        ...0 0001 = Recipient: Interface (0x01)
    bRequest: 130
    wValue: 0x0201
    wIndex: 1536 (0x0600)
    wLength: 2

Frame 30: 30 bytes on wire (240 bits), 30 bytes captured (240 bits) on
interface wireshark_extcap1868, id 0
    Interface id: 0 (wireshark_extcap1868)
        Interface name: wireshark_extcap1868
    Encapsulation type: USB packets with USBPcap header (152)
    Arrival Time: Jul  1, 2021 02:21:45.291389000 CDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1625124105.291389000 seconds
    [Time delta from previous captured frame: 0.000118000 seconds]
    [Time delta from previous displayed frame: 0.000118000 seconds]
    [Time since reference or first frame: 0.035442000 seconds]
    Frame Number: 30
    Frame Length: 30 bytes (240 bits)
    Capture Length: 30 bytes (240 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: usb]
USB URB
    [Source: 2.7.0]
    [Destination: host]
    USBPcap pseudoheader length: 28
    IRP ID: 0xffffa90f548b8a20
    IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
    URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008)
    IRP information: 0x01, Direction: PDO -> FDO
        0000 000. = Reserved: 0x00
        .... ...1 = Direction: PDO -> FDO (0x1)
    URB bus id: 2
    Device address: 7
    Endpoint: 0x80, Direction: IN
        1... .... = Direction: IN (1)
        .... 0000 = Endpoint number: 0
    URB transfer type: URB_CONTROL (0x02)
    Packet Data Length: 2
    [Request in: 29]
    [Time from request: 0.000118000 seconds]
    Control transfer stage: Complete (3)
    [bInterfaceClass: Audio (0x01)]
CONTROL response data: 00d3

According to the audio 1.0 specification, this is a "get_cur" request
(appendix 9: Audio Class-Specific Request Codes). However, I wasn't
really sure what it was trying to get. The spec (SEC. B.3.3.3)
indicates that this is an input terminal descriptor. I'll continue
following this chain of requests and responses and see if I can figure
out exactly what its doing -- I need to map the request IDs onto their
actual values since Wireshark isn't doing that for me automatically.

On 7/2/21, Michael Brown <mcb30@ipxe.org> wrote:
> On 02/07/2021 10:41, Michael Brown wrote:
>> UsbIo->UsbControlTransfer(UsbIo, &Req, EfiUsbDataIn,
>>                            PcdGet32 (PcdUsbTransferTimeoutValue),
>>                            &Header, sizeof(Header), &Status);
>>
>> (Error handling etc omitted for brevity)
>>
>> That would get you the first 8 bytes of the class-specific AC interface
>> header descriptor.  You would then need to extract the TotalLength
>> field, allocate that length of memory, and repeat the
>> UsbControlTransfer() call to fetch the full-length descriptor into the
>> newly allocated block.
>>
>> Hope that helps,
>
> BTW, in case you aren't already aware of this: wireshark is pretty good
> at dissecting USB traffic.  You can capture it by doing a "modprobe
> usbmon", after which you'll see a number of usbmonN devices show up in
> the wireshark interface list.  Try them each in turn until you find
> which one corresponds to the host controller to which your device is
> attached.
>
> My normal method for developing or debugging iPXE USB drivers will
> typically involve using wireshark to capture the USB traffic that
> happens when the device is being used by a known-working driver (e.g.
> the Linux driver for that device) and comparing it to the traffic that
> happens when I'm using my own driver (via USB pass-through in a VM).
> This is often a lot faster than trying to pull together all of the
> information from the multiple USB spec documents.
>
> Good luck!
>
> Michael
>


-- 
Signed,
Ethin D. Probst

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-02 18:18         ` Ethin Probst
@ 2021-07-02 18:22           ` Ethin Probst
  2021-07-06 12:53             ` Michael Brown
  0 siblings, 1 reply; 10+ messages in thread
From: Ethin Probst @ 2021-07-02 18:22 UTC (permalink / raw)
  To: devel, mcb30

Update: I just realized I'd made a typo -- the unknown request is
actually a get_min request.

On 7/2/21, Ethin Probst <harlydavidsen@gmail.com> wrote:
> Thank you for all that information, both of you. I didn't realize that
> VirtIO sound would be so complicated. The specification seemed simple
> enough -- but, alas, all things seem simple until you actually go and
> try to implement them.
>
> I did manage to retrieve a packet dump, from both myself and from
> somebody else that Leif contacted. The one from myself was from a USB
> mixer that I have -- its how my audio headphones work, and that
> generated far too many packets -- well over 5,000 at least. Utilizing
> display filters wasn't much of a help either -- it doesn't seem like
> my mixer makes available an audio device class descriptor anywhere,
> which is odd because it should. But I also might not have been
> filtering it properly. The other packet dump was sort-of helpful, but
> did contain some confusing elements:
>
> * There were four unknown URB transfer types (0x7F) that Wireshark
> claimed were "malformed". I asked around on the OSDev.org forum and I
> don't think anyone recognizes that either.
> * The primary init sequence was understandable, along with the get
> string requests, but after that there were a bunch of URB control
> transfers from device-to-host and some requests from host-to-device
> containing data that I didn't understand. I wasn't sure what those
> were for. They looked something like this:
>
> Frame 29: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on
> interface wireshark_extcap1868, id 0
>     Interface id: 0 (wireshark_extcap1868)
>         Interface name: wireshark_extcap1868
>     Encapsulation type: USB packets with USBPcap header (152)
>     Arrival Time: Jul  1, 2021 02:21:45.291271000 CDT
>     [Time shift for this packet: 0.000000000 seconds]
>     Epoch Time: 1625124105.291271000 seconds
>     [Time delta from previous captured frame: 0.000008000 seconds]
>     [Time delta from previous displayed frame: 0.000008000 seconds]
>     [Time since reference or first frame: 0.035324000 seconds]
>     Frame Number: 29
>     Frame Length: 36 bytes (288 bits)
>     Capture Length: 36 bytes (288 bits)
>     [Frame is marked: False]
>     [Frame is ignored: False]
>     [Protocols in frame: usb]
> USB URB
>     [Source: host]
>     [Destination: 2.7.0]
>     USBPcap pseudoheader length: 28
>     IRP ID: 0xffffa90f548b8a20
>     IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
>     URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
>     IRP information: 0x00, Direction: FDO -> PDO
>         0000 000. = Reserved: 0x00
>         .... ...0 = Direction: FDO -> PDO (0x0)
>     URB bus id: 2
>     Device address: 7
>     Endpoint: 0x80, Direction: IN
>         1... .... = Direction: IN (1)
>         .... 0000 = Endpoint number: 0
>     URB transfer type: URB_CONTROL (0x02)
>     Packet Data Length: 8
>     [Response in: 30]
>     Control transfer stage: Setup (0)
>     [bInterfaceClass: Audio (0x01)]
> Setup Data
>     bmRequestType: 0xa1
>         1... .... = Direction: Device-to-host
>         .01. .... = Type: Class (0x1)
>         ...0 0001 = Recipient: Interface (0x01)
>     bRequest: 130
>     wValue: 0x0201
>     wIndex: 1536 (0x0600)
>     wLength: 2
>
> Frame 30: 30 bytes on wire (240 bits), 30 bytes captured (240 bits) on
> interface wireshark_extcap1868, id 0
>     Interface id: 0 (wireshark_extcap1868)
>         Interface name: wireshark_extcap1868
>     Encapsulation type: USB packets with USBPcap header (152)
>     Arrival Time: Jul  1, 2021 02:21:45.291389000 CDT
>     [Time shift for this packet: 0.000000000 seconds]
>     Epoch Time: 1625124105.291389000 seconds
>     [Time delta from previous captured frame: 0.000118000 seconds]
>     [Time delta from previous displayed frame: 0.000118000 seconds]
>     [Time since reference or first frame: 0.035442000 seconds]
>     Frame Number: 30
>     Frame Length: 30 bytes (240 bits)
>     Capture Length: 30 bytes (240 bits)
>     [Frame is marked: False]
>     [Frame is ignored: False]
>     [Protocols in frame: usb]
> USB URB
>     [Source: 2.7.0]
>     [Destination: host]
>     USBPcap pseudoheader length: 28
>     IRP ID: 0xffffa90f548b8a20
>     IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
>     URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008)
>     IRP information: 0x01, Direction: PDO -> FDO
>         0000 000. = Reserved: 0x00
>         .... ...1 = Direction: PDO -> FDO (0x1)
>     URB bus id: 2
>     Device address: 7
>     Endpoint: 0x80, Direction: IN
>         1... .... = Direction: IN (1)
>         .... 0000 = Endpoint number: 0
>     URB transfer type: URB_CONTROL (0x02)
>     Packet Data Length: 2
>     [Request in: 29]
>     [Time from request: 0.000118000 seconds]
>     Control transfer stage: Complete (3)
>     [bInterfaceClass: Audio (0x01)]
> CONTROL response data: 00d3
>
> According to the audio 1.0 specification, this is a "get_cur" request
> (appendix 9: Audio Class-Specific Request Codes). However, I wasn't
> really sure what it was trying to get. The spec (SEC. B.3.3.3)
> indicates that this is an input terminal descriptor. I'll continue
> following this chain of requests and responses and see if I can figure
> out exactly what its doing -- I need to map the request IDs onto their
> actual values since Wireshark isn't doing that for me automatically.
>
> On 7/2/21, Michael Brown <mcb30@ipxe.org> wrote:
>> On 02/07/2021 10:41, Michael Brown wrote:
>>> UsbIo->UsbControlTransfer(UsbIo, &Req, EfiUsbDataIn,
>>>                            PcdGet32 (PcdUsbTransferTimeoutValue),
>>>                            &Header, sizeof(Header), &Status);
>>>
>>> (Error handling etc omitted for brevity)
>>>
>>> That would get you the first 8 bytes of the class-specific AC interface
>>> header descriptor.  You would then need to extract the TotalLength
>>> field, allocate that length of memory, and repeat the
>>> UsbControlTransfer() call to fetch the full-length descriptor into the
>>> newly allocated block.
>>>
>>> Hope that helps,
>>
>> BTW, in case you aren't already aware of this: wireshark is pretty good
>> at dissecting USB traffic.  You can capture it by doing a "modprobe
>> usbmon", after which you'll see a number of usbmonN devices show up in
>> the wireshark interface list.  Try them each in turn until you find
>> which one corresponds to the host controller to which your device is
>> attached.
>>
>> My normal method for developing or debugging iPXE USB drivers will
>> typically involve using wireshark to capture the USB traffic that
>> happens when the device is being used by a known-working driver (e.g.
>> the Linux driver for that device) and comparing it to the traffic that
>> happens when I'm using my own driver (via USB pass-through in a VM).
>> This is often a lot faster than trying to pull together all of the
>> information from the multiple USB spec documents.
>>
>> Good luck!
>>
>> Michael
>>
>
>
> --
> Signed,
> Ethin D. Probst
>


-- 
Signed,
Ethin D. Probst

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization
  2021-07-02 18:22           ` Ethin Probst
@ 2021-07-06 12:53             ` Michael Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Michael Brown @ 2021-07-06 12:53 UTC (permalink / raw)
  To: devel, harlydavidsen

On 02/07/2021 19:22, Ethin Probst wrote:
> Update: I just realized I'd made a typo -- the unknown request is
> actually a get_min request.
> 
> On 7/2/21, Ethin Probst <harlydavidsen@gmail.com> wrote:
>> Setup Data
>>      bmRequestType: 0xa1
>>          1... .... = Direction: Device-to-host
>>          .01. .... = Type: Class (0x1)
>>          ...0 0001 = Recipient: Interface (0x01)
>>      bRequest: 130
>>      wValue: 0x0201
>>      wIndex: 1536 (0x0600)
>>      wLength: 2

That doesn't immediately make sense to me in the context of reading 
sections 5.2.1.2 and 5.2.2.2.2 of the audio spec, but feel free to post 
the whole wireshark capture (off-list!) and I can take a look.

Michael

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-07-06 12:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-30 23:01 EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization Ethin Probst
2021-07-01 14:15 ` [edk2-devel] " Michael Brown
2021-07-01 18:10   ` Ethin Probst
2021-07-02  8:59     ` Laszlo Ersek
2021-07-02  9:41     ` Michael Brown
     [not found]     ` <168DEFFB0E406B59.30759@groups.io>
2021-07-02  9:46       ` Michael Brown
2021-07-02 18:18         ` Ethin Probst
2021-07-02 18:22           ` Ethin Probst
2021-07-06 12:53             ` Michael Brown
2021-07-02  8:54 ` Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox