Skip to content

Instantly share code, notes, and snippets.

@kbingham
Created May 15, 2018 08:18
Show Gist options
  • Save kbingham/c39c4cc7c20882a104c08df5206e2f9f to your computer and use it in GitHub Desktop.
Save kbingham/c39c4cc7c20882a104c08df5206e2f9f to your computer and use it in GitHub Desktop.
UVC ConfigFS Gadget configuration tool
#!/bin/sh
set -e
#set -x
CONFIGFS="/sys/kernel/config"
GADGET="$CONFIGFS/usb_gadget"
VID="0x0525"
PID="0xa4a2"
SERIAL="0123456789"
MANUF=$(hostname)
PRODUCT="UVC Gadget"
USBFILE=/root/usbstorage.img
BOARD=$(strings /proc/device-tree/model)
case $BOARD in
"Renesas Salvator-X board based on r8a7795 ES1.x")
UDC_USB2=e6590000.usb
UDC_USB3=ee020000.usb
UDC_ROLE2=/sys/devices/platform/soc/ee080200.usb-phy/role
UDC_ROLE2=/dev/null #Not needed - always peripheral
UDC_ROLE3=/sys/devices/platform/soc/ee020000.usb/role
UDC=$UDC_USB2
UDC_ROLE=$UDC_ROLE2
;;
"TI OMAP4 PandaBoard-ES")
UDC=`ls /sys/class/udc` # Should be musb-hdrc.0.auto
UDC_ROLE=/dev/null # Not needed - peripheral enabled
;;
*)
UDC=`ls /sys/class/udc` # will identify the 'first' UDC
UDC_ROLE=/dev/null # Not generic
;;
esac
echo "Detecting platform:"
echo " board : $BOARD"
echo " udc : $UDC"
create_msd() {
# Example usage:
# create_msd <target config> <function name> <image file>
# create_msd configs/c.1 mass_storage.0 /root/backing.img
CONFIG=$1
FUNCTION=$2
BACKING_STORE=$3
if [ ! -f $BACKING_STORE ]
then
echo "\tCreating backing file"
dd if=/dev/zero of=$BACKING_STORE bs=1M count=32 > /dev/null 2>&1
mkfs.ext4 $USBFILE > /dev/null 2>&1
echo "\tOK"
fi
echo "\tCreating MSD gadget functionality"
mkdir functions/$FUNCTION
echo 1 > functions/$FUNCTION/stall
echo $BACKING_STORE > functions/$FUNCTION/lun.0/file
echo 1 > functions/$FUNCTION/lun.0/removable
echo 0 > functions/$FUNCTION/lun.0/cdrom
ln -s functions/$FUNCTION configs/c.1
echo "\tOK"
}
delete_msd() {
# Example usage:
# delete_msd <target config> <function name>
# delete_msd config/c.1 uvc.0
CONFIG=$1
FUNCTION=$2
echo "Removing Mass Storage interface : $FUNCTION"
rm -f $CONFIG/$FUNCTION
rmdir functions/$FUNCTION
echo "OK"
}
create_uvc() {
# Example usage:
# create_uvc <target config> <function name>
# create_uvc config/c.1 uvc.0
CONFIG=$1
FUNCTION=$2
echo " Creating UVC gadget functionality : $FUNCTION"
mkdir functions/$FUNCTION
mkdir -p functions/$FUNCTION/streaming/uncompressed/u/360p
cat <<EOF > functions/$FUNCTION/streaming/uncompressed/u/360p/dwFrameInterval
666666
1000000
5000000
EOF
mkdir functions/$FUNCTION/streaming/header/h
cd functions/$FUNCTION/streaming/header/h
ln -s ../../uncompressed/u
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../../control
mkdir header/h
ln -s header/h class/fs
ln -s header/h class/ss
cd ../../../
echo 2048 > functions/$FUNCTION/streaming_maxpacket
ln -s functions/$FUNCTION configs/c.1
}
delete_uvc() {
# Example usage:
# delete_uvc <target config> <function name>
# delete_uvc config/c.1 uvc.0
CONFIG=$1
FUNCTION=$2
echo " Deleting UVC gadget functionality : $FUNCTION"
rm $CONFIG/$FUNCTION
rm functions/$FUNCTION/control/class/*/h
rm functions/$FUNCTION/streaming/class/*/h
rm functions/$FUNCTION/streaming/header/h/u
rmdir functions/$FUNCTION/streaming/uncompressed/u/360p
rmdir functions/$FUNCTION/streaming/uncompressed/u
rmdir functions/$FUNCTION/streaming/header/h
rmdir functions/$FUNCTION/control/header/h
rmdir functions/$FUNCTION
}
case "$1" in
start)
echo "Creating the USB gadget"
#echo "Loading composite module"
#modprobe libcomposite
echo "Creating gadget directory g1"
mkdir -p $GADGET/g1
cd $GADGET/g1
if [ $? -ne 0 ]; then
echo "Error creating usb gadget in configfs"
exit 1;
else
echo "OK"
fi
echo "Setting Vendor and Product ID's"
echo $VID > idVendor
echo $PID > idProduct
echo "OK"
echo "Setting English strings"
mkdir -p strings/0x409
echo $SERIAL > strings/0x409/serialnumber
echo $MANUF > strings/0x409/manufacturer
echo $PRODUCT > strings/0x409/product
echo "OK"
echo "Creating Config"
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "Creating functions..."
#create_msd configs/c.1 mass_storage.0 $USBFILE
create_uvc configs/c.1 uvc.0
echo "OK"
echo "Binding USB Device Controller"
echo $UDC > UDC
echo peripheral > $UDC_ROLE
cat $UDC_ROLE
echo "OK"
;;
stop)
echo "Stopping the USB gadget"
set +e # Ignore all errors here on a best effort
cd $GADGET/g1
if [ $? -ne 0 ]; then
echo "Error: no configfs gadget found"
exit 1;
fi
echo "Unbinding USB Device Controller"
grep $UDC UDC && echo "" > UDC
echo "OK"
delete_uvc configs/c.1 uvc.0
#delete_msd configs/c.1 mass_storage.0
echo "Clearing English strings"
rmdir strings/0x409
echo "OK"
echo "Cleaning up configuration"
rmdir configs/c.1/strings/0x409
rmdir configs/c.1
echo "OK"
echo "Removing gadget directory"
cd $GADGET
rmdir g1
cd /
echo "OK"
#echo "Disable composite USB gadgets"
#modprobe -r libcomposite
#echo "OK"
;;
*)
echo "Usage : $0 {start|stop}"
esac
@harsh04102002
Copy link

I am using a Raspi4 and want the it to be converted to a USB-UVC device mimicking a USB camera. Can anyone suggest how to do it and what changes need to be done because i tried using U4VL and that didn,t worked?

@kbingham
Copy link
Author

@harsh04102002 Have you followed : https://www.raspberrypi.com/tutorials/plug-and-play-raspberry-pi-usb-webcam/ ? If so and you still have issues please file an issue at https://gitlab.freedesktop.org/camera/uvc-gadget/

(Note for any future commentors here - it's likely better to raise an issue at https://gitlab.freedesktop.org/camera/uvc-gadget/ )

@harsh04102002
Copy link

HI @kbingham , yes i followed that blog already but actually i don,t have any physical camera attached to the Pi and want a prestored video to stream over the USB connection (that,s why i used 'mimicking' above). Without connecting any camera to the RPi my PC (Windows and Linux both) is not even recognizing the RPi as any device just an standard popup of 'USB device not Recognized' comes on Windows .I have connected to the Power type-C to the PC USB .Connections are fine .I didn,t tried with the camera coz i don,t have it now.Will highly appreciate if you can help.Thanks for reviewing .

@kbingham
Copy link
Author

Then you'll need to configure the uvc-gadget to be fed by a pipeline from gstreamer or such.

@harsh04102002
Copy link

harsh04102002 commented Jun 13, 2023

@kbingham Thanks for Quick reply , You are right and i even thought something of pipelining but was not confident in implementing though but before that Can the PC even recognize the solo Raspberry(no CSI camera attached) as a camera device after doing the above mentioned configurations in this documentaion shared by you.Because for me it,s not happenning.My primary objective is to first let the Raspi be recognized as a Camera device whether camera is attached to it or not .

@kbingham
Copy link
Author

Are you running the uvc-gadget application? There has to be something sending frames or otherwise the host will not be happy. Our implementation of uvc-gadget at https://gitlab.freedesktop.org/camera/uvc-gadget/ can send images from files or from a test pattern generator if you don't have a camera attached, or you can use a virtual camera device like vivid ...

@kbingham
Copy link
Author

To be clear - this script in this gist is only about configuration. The system must run an application which will manage the interactions with the host, respond to messages and events, and deliver frames.

@harsh04102002
Copy link

harsh04102002 commented Jun 16, 2023

Hi @kbingham , i have tried above shared repo as well your repository but i think the options like mentioned in the repository by 'wlhe' (which somehow is working for me) for standalone operation of 'Pi' i.e, without any capture device attached to it , are not present there in your and the above shared freedesktop library .Please correct me if i am wrong as i just typed uvc-gadget -h and couldn,t find the standalone option in them .
.So,this is all about your repository and I might be doing some silly mistake i guess if you can please helping pointing it out .

Now, i see that all of these repo are linked some or other way on ideasonboard which i figured out after getting same readme file in multiple repos :) .Thanks to all of you guys for such outstanding work !. Thinking that you are aware of 'wlhe' repo ...could you please help me figuring out error as it,s working is very crucial step in my main project .

I ran the command ./uvc-gadget -d -i /home/pi/Downloads/test.mjpeg -u /dev/video0 -v uvc.0 with the 'wlhe' repo and with the scrpit mentioned in this documentation but i get 'ioctl' error even though i am passing mjpeg format only .
Snap of error :
image

My issue is similar to this raised in your repo only because for me also ioctl: VIDIOC_ENUM_FMT , Type: Video Capture . Can you please share if there is an updated repo which has resolved this issue or any similar kind of issue.
Also i am using VLC and selecting capture device as this newly made UVC camera in the host side.Please correct me if i am wrong .

Thanks for your time and effort ! Really appreciate that.

EDIT :My bad , missed ' -d ' in command for standalone mode .Updated .

@kbingham
Copy link
Author

This is not a support forum. Please use https://gitlab.freedesktop.org/camera/uvc-gadget/

@Bhavesh1125
Copy link

Hey i hope you doing well,
I have stuck in one problem which you can see on image
usb

When I run this script, it shows a "resource busy" error, and I already have the /config/usb_gadget/g1/configs/b.1 directory, so it does not create a new c.1 directory. Can you help me solve this problem?

@kbingham
Copy link
Author

This is not a support forum. Please use https://gitlab.freedesktop.org/camera/uvc-gadget/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment