How to extend the BOS descriptor in FunctionFS?

569 views Asked by At

I'm trying to implement a simple WebUSB device on a Raspberry Pi 4. I've created a Linux USB Gadget for this purpose with a FunctionFS function. Currently I've taken the usb/ffs-test.c example from the Linux kernel as a basis.

According to this excellent Google blog by Reilly Grant on "Building a Device for WebUSB", I have to extend the Binary device Object Store (BOS) with the Microsoft OS compatibility descriptors to get this to work on Windows. I could also add the WebUSB descriptors to it but this is not a functional requirement.

However I'm stuck on this step, how do I extend the BOS with FunctionFS? This is my first experience with FunctionFS or USB for that matter, so I could be missing something obvious. I've found some usb_os_desc_header struct defined here in usb/functionfs.h, but I don't know if this is what I need or how I should use it.

1

There are 1 answers

0
msohn On

I finally figured this out as well, so here's what I had to do (based on tools/usb/ffs-test.c).

A user space function must write all descriptors to ep0, so the trick is to extend your descriptors struct:

  • add __le32 os_count after ss_count
  • add struct usb_os_desc_header os_header and struct usb_ext_compat_desc os_desc after ss_descs
  • FUNCTIONFS_HAS_MS_OS_DESC needs to be added to header.flags

Here's how I initialise the new fields for WinUSB compatibility, I presume WebUSB in general works similar:

    .os_count = cpu_to_le32(1),
    .os_header = {
        .interface = cpu_to_le32(1),
        .dwLength = cpu_to_le32(sizeof(descriptors.os_header) + sizeof(descriptors.os_desc)),
        .bcdVersion = cpu_to_le32(1),
        .wIndex = cpu_to_le32(4),
        .bCount = cpu_to_le32(1),
        .Reserved = cpu_to_le32(0),
    },
    .os_desc = {
        .bFirstInterfaceNumber = 0,
        .Reserved1 = cpu_to_le32(1),
        .CompatibleID = {'W', 'I', 'N', 'U', 'S', 'B', 0, 0},
        .SubCompatibleID = {0},
        .Reserved2 = {0},
    }