Last active
March 26, 2024 18:02
-
-
Save NickEngmann/c0af916fc6c6ad5258842503fffd4c0f to your computer and use it in GitHub Desktop.
radxa-uvcutils.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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