Skip to content

Instantly share code, notes, and snippets.

@NickEngmann
Last active March 26, 2024 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NickEngmann/c0af916fc6c6ad5258842503fffd4c0f to your computer and use it in GitHub Desktop.
Save NickEngmann/c0af916fc6c6ad5258842503fffd4c0f to your computer and use it in GitHub Desktop.
radxa-uvcutils.sh
#!/bin/bash -e
lock_udc()
{
configfs_make
exec 100<"/sys/kernel/config/usb_gadget/$UDC"
flock 100
}
unlock_udc()
{
exec 100<&-
}
enable_udc()
{
if [[ -n $(cat "/sys/kernel/config/usb_gadget/$UDC/UDC") ]];
then
echo "" > "/sys/kernel/config/usb_gadget/$UDC/UDC"
fi
echo "$UDC" > "/sys/kernel/config/usb_gadget/$UDC/UDC"
}
configfs_make()
{
if [ ! -e "/sys/kernel/config/usb_gadget/$UDC" ];
then
modprobe libcomposite
mkdir -p "/sys/kernel/config/usb_gadget/$UDC"
fi
}
configfs_init()
{
echo "0x1d6b" > "/sys/kernel/config/usb_gadget/$UDC/idVendor" # Linux Foundation
echo "0x0104" > "/sys/kernel/config/usb_gadget/$UDC/idProduct" # Multifunction Composite Gadget
echo "0x0100" > "/sys/kernel/config/usb_gadget/$UDC/bcdDevice" # v1.0.0
echo "0x0200" > "/sys/kernel/config/usb_gadget/$UDC/bcdUSB" # USB 2.0
echo "0xEF" > "/sys/kernel/config/usb_gadget/$UDC/bDeviceClass" # Miscellaneous Device Class
echo "0x02" > "/sys/kernel/config/usb_gadget/$UDC/bDeviceSubClass" # Common Class
echo "0x01" > "/sys/kernel/config/usb_gadget/$UDC/bDeviceProtocol" # Interface Association Descriptor
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/strings/0x409"
echo "0123456789ABCDEF" > "/sys/kernel/config/usb_gadget/$UDC/strings/0x409/serialnumber"
echo "Radxa" > "/sys/kernel/config/usb_gadget/$UDC/strings/0x409/manufacturer"
echo "UVC Gadget" > "/sys/kernel/config/usb_gadget/$UDC/strings/0x409/product" # Update the product name
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/strings/0x409"
echo "500" > "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/MaxPower"
echo "UVC Configuration" > "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/strings/0x409/configuration" # Update the configuration name
}
function_init()
{
local GADGET="uvc.0"
echo "Creating functions directory for $GADGET..."
if [ ! -e "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET" ];
then
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET"
echo "0" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming_maxpacket"
echo "1" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming_maxburst"
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/control/header/h"
ln -s "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/control/header/h" "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/$GADGET"
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p"
echo "1000000" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p/dwFrameInterval"
echo "1280" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p/wWidth"
echo "720" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p/wHeight"
echo "4" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p/dwMaxVideoFrameBufferSize"
mkdir -p "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p"
echo "1000000" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p/dwFrameInterval"
echo "1280" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p/wWidth"
echo "720" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p/wHeight"
echo "4" > "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p/dwMaxVideoFrameBufferSize"
fi
if [ ! -e "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/$GADGET" ];
then
echo "Creating symbolic link for $GADGET in configs directory..."
ln -s "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET" "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/$GADGET"
fi
}
function_stop()
{
local GADGET="uvc.0"
if [ -e "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/$GADGET" ];
then
echo "Removing symbolic link for $GADGET from configs directory..."
rm "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/$GADGET"
fi
if [ -e "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET" ];
then
echo "Removing $GADGET functions directory..."
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u/720p"
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/uncompressed/u"
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/streaming/mjpeg/m/720p"
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/control/header/h"
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET/control"
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/functions/$GADGET"
fi
if [ -n "$(find "/sys/kernel/config/usb_gadget/$UDC/functions" -maxdepth 0 -type d -empty)" ];
then
echo "Removing empty configs and strings directories..."
if [ -e "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/strings/0x409" ];
then
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/configs/c.1/strings/0x409"
fi
if [ -e "/sys/kernel/config/usb_gadget/$UDC/configs/c.1" ];
then
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/configs/c.1"
fi
if [ -e "/sys/kernel/config/usb_gadget/$UDC/strings/0x409" ];
then
rmdir --ignore-fail-on-non-empty "/sys/kernel/config/usb_gadget/$UDC/strings/0x409"
fi
else
echo "Enabling UDC..."
enable_udc
fi
}
start()
{
echo "Locking UDC..."
lock_udc
echo "Initializing configfs..."
configfs_init
echo "Initializing UVC function..."
function_init
if [ ! -e "/dev/video0" ];
then
echo "Loading v4l2loopback module..."
modprobe v4l2loopback
sleep 1
if [ ! -e "/dev/video0" ];
then
echo "Failed to create v4l2loopback device /dev/video0."
exit 1
fi
fi
echo "Enabling UDC..."
enable_udc
echo "Unlocking UDC..."
unlock_udc
echo "Starting FFmpeg..."
ffmpeg -hide_banner -loglevel verbose -f v4l2 -i /dev/video0 -f v4l2 -r 15 -s 1280x720 -pix_fmt yuv420p "/sys/kernel/config/usb_gadget/$UDC/functions/uvc.0/streaming/uncompressed/u/720p/data" &
FFmpeg_PID=$!
sleep 1
if ! ps -p $FFmpeg_PID > /dev/null; then
echo "Failed to start FFmpeg."
exit 1
fi
echo "UVC gadget started successfully."
}
stop()
{
echo "Locking UDC..."
lock_udc
echo "Stopping UVC function..."
function_stop
echo "Stopping FFmpeg..."
pkill ffmpeg
echo "Unlocking UDC..."
unlock_udc
}
UDC=""
if [ -e "/sys/class/udc/$1" ];
then
UDC="$1"
else
echo "This UDC does not exist, you can turn on the OTG port Peripheral mode device tree overlay at rsetup and look in the /sys/class/udc directory for."
echo "Usage: $0 <UDC> <start|stop|restart>"
exit 1
fi
case "$2" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
start
;;
*)
echo "Usage: $0 <UDC> <start|stop|restart>"
exit 1
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment