youpko
Posts: 5
Joined: Wed Mar 22, 2023 7:02 pm

Compute Module 4 & USB Gadget composite device

Wed Mar 22, 2023 7:43 pm

Last week I ordered a Compute Module 4 and the IO Board for a small project which involves running the CM4 as a USB Device (CM4 is device, PC is host). I have a some programming knowledge of how this works on a PIC32 micro-controllers but this is my first time trying any thing like this on Linux.

My

After a lot of searching on google I am a bit confused as how to configure everything, also I feel like I am mixing up some of the terminology so just for my senity:
  • GadgetFS = old style of USB Gadgets, I should not use this.
  • Libcomposite = modern USB Gadget driver
  • ConfigFS = filesystem part used to configure LibComposite USB Gadgets
I want to configure a composite device containing the following parts:
  • HID functionality (This I managed to configure more info below)
  • Vendor bulk in/out pair (I think this is called FunctionFS?)
HID
I got this part working by doing the following:

Add the following to /boot/config.txt

Code: Select all

dtoverlay=dwc2,dr_mode=peripheral
Run the following command to configure the USB device with a HID function.

Code: Select all

#!/bin/bash

####
## adapted from http://isticktoit.net/?p=1383
####

SRCPATH=`pwd`
HIDDESCRIPTOR=$SRCPATH/Desc1.hid

modprobe libcomposite
cd /sys/kernel/config/usb_gadget/

mkdir -p test
cd test
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo `cat /proc/cpuinfo | grep Serial | cut -d ' ' -f 2` > strings/0x409/serialnumber
echo "Youpko" > strings/0x409/manufacturer
echo "USB Device" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Config 1: Test" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
# Add functions here
mkdir -p functions/hid.usb0
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length

cat $HIDDESCRIPTOR > functions/hid.usb0/report_desc

ln -s functions/hid.usb0 configs/c.1/
# End functions

ls /sys/class/udc > UDC
"Vendor"
This part has me stumped as I am used in the PIC32 micro-controller world this is often called a Vendor Interface, no pre-defined stuff from the USB foundation everything is up to the manufacturer, But this term is not used in Linux kernel documentation.
I think the term is FunctionFS and in the kernal documentation there is an configfs-usb-gadget-ffs page but there is no information explained on how to configure this.

I have 2 questions regarding this where can I find more information on the FunctionFS, and is FunctionFS combining with other functions supported things like HID/CDC/MSD.

User avatar
thagrol
Posts: 9297
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: Compute Module 4 & USB Gadget composite device

Wed Mar 22, 2023 11:29 pm

Old but as far as I know still valid. Talks about the zero but the CM4 has the same USB controller built in.

https://www.isticktoit.net/?p=1383
Knowledge, skills, & experience have value. If you expect to profit from someone's you should expect to pay for them.

All advice given is based on my experience. it worked for me, it may not work for you.
Need help? https://github.com/thagrol/Guides

youpko
Posts: 5
Joined: Wed Mar 22, 2023 7:02 pm

Re: Compute Module 4 & USB Gadget composite device

Thu Mar 23, 2023 8:50 am

thagrol wrote:
Wed Mar 22, 2023 11:29 pm
Old but as far as I know still valid. Talks about the zero but the CM4 has the same USB controller built in.

https://www.isticktoit.net/?p=1383
That is the resource I used and where I got the script from for HID. I got this working and successfully presented the CM4 as a HID Joystick to a Windows PC.

But it doesn't tell me anything about the FunctionFS(ffs). On the end of the page it points me to the kernel documentation but that doesn't give me any clue how to add/enable the ffs module.

incognitum
Posts: 1289
Joined: Tue Oct 30, 2018 3:34 pm

Re: Compute Module 4 & USB Gadget composite device

Thu Mar 23, 2023 12:46 pm

This is not the type of project you can expect to find ready-made tutorials for.
Using custom USB protocols means not only extra work on the gadget side, but also on the host side.
Make sure you know what you are getting yourself into...

youpko wrote:
Thu Mar 23, 2023 8:50 am
But it doesn't tell me anything about the FunctionFS(ffs). On the end of the page it points me to the kernel documentation but that doesn't give me any clue how to add/enable the ffs module.
The kernel documentation on the ffs configfs part is pretty simple: there are no attributes to set, only create the directory ffs.something. ;)
Then you use functionfs in the same way you would do without configfs.

So similar to what you have now:

Code: Select all

mkdir -p functions/hid.usb0
[...]
ln -s functions/hid.usb0 configs/c.1/
ls /sys/class/udc > UDC
You would also need to add something along the lines of:

Code: Select all

# configfs part
[.. your other configfs stuff.. ]
mkdir functions/ffs.mystuff
ln -s functions/ffs.mystuff configs/c.1

# normal functionfs stuff
mkdir /dev/mountpoint_for_ffs_mystuff
# assuming you are logged in as first user (userid 1000) during development, and your userspace program will run as that
mount -o uid=1000,gid=1000 -t functionfs mystuff /dev/mountpoint_for_ffs_mystuff

[...start your userspace program...]

ls /sys/class/udc > UDC
Your userspace application can then:
- open the device /dev/mountpoint_for_ffs_mystuff/ep0
- write descriptors to that, and keep polling it for events
- open additional epX devices to read/write endpoints.

See /usr/include/linux/usb/functionfs.h for some hints on how to interact with ep0

If you find that too complicated, and your communication needs are modest, you may be able to get away with something simpler like using a standard class like acm and opening the tty that will be created for communication instead...
Last edited by incognitum on Thu Mar 23, 2023 9:47 pm, edited 1 time in total.

youpko
Posts: 5
Joined: Wed Mar 22, 2023 7:02 pm

Re: Compute Module 4 & USB Gadget composite device

Thu Mar 23, 2023 2:32 pm

Thanks Incognitum you provided me with the part that made sense of all the different bits of information I found.

I indeed have now the EP0, I have found some tutorials explaining this, and it also looks very similar to the C/C++ code I have experience with on the PIC32 micro-controllers.

I have a issue when adding your information to my test script.

Code: Select all

mkdir -p functions/ffs.mystuff

ln -s functions/hid.usb0 configs/c.1/
ln -s functions/ffs.mystuff configs/c.1/

ls /sys/class/udc > UDC

mkdir /dev/mystuff
mount -t functionfs mystuff /dev/mystuff
the line

Code: Select all

ls /sys/class/udc > UDC
fails with

Code: Select all

ls: write error: Device or resource busy
Is this because I should first write the descriptors to EP0? which are not done yet because I need to write the C program.
Your userspace application can then:
- open the device /dev/mountpoint_for_ffs_mystuff/ep0
- write descriptors to that, and keep polling it for events
- open additional epX devices to read/write endpoints.

See /usr/include/linux/usb/functionfs.h for some hints on how to interact with ep0

If you find that too complicated, and your communication needs are modest, you may be able to get away with something simpler like using a standard class like acm and opening the tty that will be created for communication instead...
This is indeed a bit complicated but that is more due to the fact that I am very familiar with Linux (most definitely not on this level). My application requires some data transfers that don't fit really well with the USB predefined classes, Hence I want to use FunctionFS to allow my custom data transfer next to the normal HID class (I don't want to re-invent the wheel if I don't have to ;) ).

My next step is to program a little FunctionFS and HID C/C++ test program. And I am need to read a bit more on how to implement the FunctionFS descriptors to also add the WinUSB functionality, but this should not be that difficult as this should be the same as on my microcontroller projects.

incognitum
Posts: 1289
Joined: Tue Oct 30, 2018 3:34 pm

Re: Compute Module 4 & USB Gadget composite device

Thu Mar 23, 2023 4:49 pm

youpko wrote:
Thu Mar 23, 2023 2:32 pm
the line

Code: Select all

ls /sys/class/udc > UDC
fails with

Code: Select all

ls: write error: Device or resource busy
Is this because I should first write the descriptors to EP0? which are not done yet because I need to write the C program.
Ah, yes. You are right.
That line should come last of everything.

youpko
Posts: 5
Joined: Wed Mar 22, 2023 7:02 pm

Re: Compute Module 4 & USB Gadget composite device

Fri Mar 24, 2023 1:25 pm

I got the USB Gadget working (No WinUSB descriptors yet). But I ran in to a small problem when wanting to disable the gadget but i get a permission denied with the following command

Code: Select all

echo "" > /sys/kernel/config/usb_gadget/UDC
-bash: /sys/kernel/config/usb_gadget/UDC: Permission denied
Even trying it as sudo i get the same error message.

For now I have just rebooted the CM4 every time I changed something but that becomes very annoying :D

Is there some here that can point me to the resource on how to set all the permission correct?

incognitum
Posts: 1289
Joined: Tue Oct 30, 2018 3:34 pm

Re: Compute Module 4 & USB Gadget composite device

Fri Mar 24, 2023 1:38 pm

youpko wrote:
Fri Mar 24, 2023 1:25 pm
I got the USB Gadget working (No WinUSB descriptors yet). But I ran in to a small problem when wanting to disable the gadget but i get a permission denied with the following command

Code: Select all

echo "" > /sys/kernel/config/usb_gadget/UDC
-bash: /sys/kernel/config/usb_gadget/UDC: Permission denied
Even trying it as sudo i get the same error message.
How are you trying to sudo exactly?

If you entered:

Code: Select all

sudo echo "" > /sys/kernel/config/usb_gadget/UDC
Your "sudo" will only apply to the echo, and not to the ">" output redirection being done by the current shell running as the current user...

Try instead:

Code: Select all

sudo bash
echo "" > /sys/kernel/config/usb_gadget/UDC
(press ctrl-d when you no longer want to run commands as root, to close bash running as root)
And also make sure your application does not have any devices open, and you umount'ed your functionfs mount. Or disabling by echo may also be failing because of that.

User avatar
thagrol
Posts: 9297
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: Compute Module 4 & USB Gadget composite device

Fri Mar 24, 2023 1:50 pm

Or try

Code: Select all

echo "" | sudo tee /sys/kernel/config/usb_gadget/UDC
Knowledge, skills, & experience have value. If you expect to profit from someone's you should expect to pay for them.

All advice given is based on my experience. it worked for me, it may not work for you.
Need help? https://github.com/thagrol/Guides

youpko
Posts: 5
Joined: Wed Mar 22, 2023 7:02 pm

Re: Compute Module 4 & USB Gadget composite device

Fri Mar 24, 2023 2:00 pm

I put the sudo in front of the echo command thanks for the explanation why that doesn't work. Feel like I should have known :oops:

Code: Select all

sudo bash
echo "" > /sys/kernel/config/usb_gadget/UDC
Does the trick nicely

Return to “Advanced users”