382 lines
8.4 KiB
Bash
Executable File
382 lines
8.4 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
|
|
|
|
#insmod libcomposite.ko
|
|
#insmod usb_f_uvc.ko
|
|
#insmod u_audio.ko
|
|
#insmod usb_f_uac1.ko
|
|
#insmod usb_f_uac2.ko
|
|
#insmod usb_f_fs.ko
|
|
#insmod usbmon.ko
|
|
|
|
UVC_ENABLE="true"
|
|
UVC1_ENABLE="false"
|
|
UAC_ENABLE="true"
|
|
|
|
UVC_ENABLE_YUYV="true"
|
|
UVC_ENABLE_NV21="true"
|
|
UVC_ENABLE_MJPEG="true"
|
|
UVC_ENABLE_H264="true"
|
|
UVC_ENABLE_H265="false"
|
|
|
|
# UVC data endpoint transmission mode: iso or bulk
|
|
UVC_TRANSFER_MODE="isoc"
|
|
|
|
# USB speed.
|
|
# ss: super-speed; hs: high-speed; fs: full-speed.
|
|
USB_SPEED="hs"
|
|
|
|
export VID="0x3337"
|
|
export PID="0x4321"
|
|
export MANUFACTURER="XMedia"
|
|
export PRODUCT="HD USB Camera"
|
|
export SERIALNUMBER="20251215"
|
|
|
|
export YUYV="640x360@30 1280x720@13"
|
|
export NV21="640x360@30 1280x720@13"
|
|
export MJPEG="640x360@30 1280x720@30 1920x1080@30"
|
|
export H264="640x360@30 1280x720@30 1920x1080@30"
|
|
export H265="640x360@30 1280x720@30 1920x1080@30"
|
|
|
|
export YUYV_GUID="YUY2\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71"
|
|
export YUYV_BITS="16"
|
|
export NV21_GUID="NV21\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71"
|
|
export NV21_BITS="12"
|
|
export H264_GUID="H264\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71"
|
|
export H265_GUID="H265\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71"
|
|
|
|
export FUNCTION_UVC="uvc.usb0"
|
|
export FUNCTION_UVC1="uvc1.usb0"
|
|
export FUNCTION_UAC1="uac1.usb0"
|
|
|
|
#-USB Device descriptor.
|
|
function gen_dev_desc() {
|
|
echo "0x01" > bDeviceProtocol
|
|
echo "0x02" > bDeviceSubClass
|
|
echo "0xEF" > bDeviceClass
|
|
echo "0x200" > bcdUSB
|
|
echo $VID > idVendor
|
|
echo $PID > idProduct
|
|
echo "0x100" > bcdDevice
|
|
mkdir -p strings/0x409
|
|
echo $MANUFACTURER > strings/0x409/manufacturer
|
|
echo $PRODUCT > strings/0x409/product
|
|
echo $SERIALNUMBER > strings/0x409/serialnumber
|
|
}
|
|
|
|
#-Payload Format Descriptors
|
|
function gen_payload_format_desc() {
|
|
local PAYLOAD=$1
|
|
local FORMAT=$2
|
|
local GUID=$3
|
|
local BITS=$4
|
|
local RESOLUTIONS=$5
|
|
local CR=1
|
|
|
|
mkdir -p streaming/$PAYLOAD/$FORMAT/
|
|
|
|
if [ $GUID != "null" ];then
|
|
echo -n -e $GUID > streaming/$PAYLOAD/$FORMAT/guidFormat
|
|
fi
|
|
|
|
if [ $BITS -ne 0 ];then
|
|
echo -n -e $BITS > streaming/$PAYLOAD/$FORMAT/bBitsPerPixel
|
|
fi
|
|
|
|
if [ $FORMAT = "mjpeg" ];then
|
|
# The compression ratio is calculated at 10:1.
|
|
CR=10
|
|
elif [ $FORMAT = "h264" ];then
|
|
# The compression ratio is calculated at 50:1.
|
|
CR=50
|
|
elif [ $FORMAT = "h265" ];then
|
|
# The compression ratio is calculated at 80:1.
|
|
CR=100
|
|
fi
|
|
|
|
for str in $RESOLUTIONS; do
|
|
# Width x Height
|
|
local RES=$(echo "$str" | awk -F '@' '{print $1}')
|
|
# Interval
|
|
local I=$(echo "$str" | awk -F '@' '{print $2}')
|
|
# Width
|
|
local W=$(echo "$RES" | awk -F 'x' '{print $1}')
|
|
# Height
|
|
local H=$(echo "$RES" | awk -F 'x' '{print $2}')
|
|
|
|
RES="${RES}p"
|
|
|
|
# microsecond
|
|
local TIME=10000000
|
|
# Interval
|
|
local INTERVAL=$((TIME / I))
|
|
# Video Frame Buffer Size
|
|
local FRAMESIZE=$((W * H))
|
|
if [ $BITS -eq 16 ]; then
|
|
FRAMESIZE=$((FRAMESIZE * 2))
|
|
else
|
|
# The data before encoding is YUV420
|
|
FRAMESIZE=$((FRAMESIZE * 3))
|
|
FRAMESIZE=$((FRAMESIZE / 2))
|
|
fi
|
|
|
|
FRAMESIZE=$((FRAMESIZE / CR))
|
|
|
|
# Max Bits Rate
|
|
local MAXBITRATE=$((FRAMESIZE * 8))
|
|
MAXBITRATE=$((MAXBITRATE * I))
|
|
# Min Bits Rate
|
|
local MINBITRATE=$MAXBITRATE
|
|
|
|
mkdir -p streaming/$PAYLOAD/$FORMAT/$RES/
|
|
echo "${W}" > streaming/$PAYLOAD/$FORMAT/$RES/wWidth
|
|
echo "${H}" > streaming/$PAYLOAD/$FORMAT/$RES/wHeight
|
|
echo "${INTERVAL}" > streaming/$PAYLOAD/$FORMAT/$RES/dwFrameInterval
|
|
echo "${INTERVAL}" > streaming/$PAYLOAD/$FORMAT/$RES/dwDefaultFrameInterval
|
|
echo "${MAXBITRATE}" > streaming/$PAYLOAD/$FORMAT/$RES/dwMaxBitRate
|
|
echo "${MINBITRATE}" > streaming/$PAYLOAD/$FORMAT/$RES/dwMinBitRate
|
|
|
|
if [ $PAYLOAD != "framebased" ];then
|
|
echo "${FRAMESIZE}" > streaming/$PAYLOAD/$FORMAT/$RES/dwMaxVideoFrameBufferSize
|
|
fi
|
|
|
|
#echo "$FORMAT $W x $H @ $INTERVAL $FRAMESIZE $MAXBITRATE"
|
|
done
|
|
}
|
|
|
|
#-For YUV Payload Format Descriptor
|
|
function gen_uncompressed_desc() {
|
|
local PAYLOAD="uncompressed"
|
|
local FORMAT=$1
|
|
local GUID=$2
|
|
local BITS=$3
|
|
local RESOLUTIONS=$4
|
|
|
|
gen_payload_format_desc ${PAYLOAD} ${FORMAT} ${GUID} ${BITS} "${RESOLUTIONS}"
|
|
|
|
ln -s streaming/$PAYLOAD/$FORMAT/ streaming/header/h/
|
|
}
|
|
|
|
#-For FRAMEBASE Payload Format Descriptor
|
|
function gen_framebase_desc() {
|
|
local PAYLOAD="framebased"
|
|
local FORMAT=$1
|
|
local GUID=$2
|
|
local BITS=0
|
|
local RESOLUTIONS=$3
|
|
|
|
gen_payload_format_desc ${PAYLOAD} ${FORMAT} ${GUID} ${BITS} "${RESOLUTIONS}"
|
|
|
|
ln -s streaming/$PAYLOAD/$FORMAT/ streaming/header/h/
|
|
}
|
|
|
|
#-For MJPEG Payload Format Descriptor
|
|
function __gen_mjpeg_desc() {
|
|
local PAYLOAD="mjpeg"
|
|
local FORMAT="mjpeg"
|
|
local GUID="null"
|
|
local BITS=0
|
|
local RESOLUTIONS=$1
|
|
|
|
gen_payload_format_desc ${PAYLOAD} ${FORMAT} ${GUID} ${BITS} "${RESOLUTIONS}"
|
|
|
|
ln -s streaming/$PAYLOAD/$FORMAT/ streaming/header/h/
|
|
}
|
|
|
|
#-YUYV Format
|
|
function gen_yuyv_desc() {
|
|
gen_uncompressed_desc "yuyv" "${YUYV_GUID}" "${YUYV_BITS}" "${YUYV}"
|
|
}
|
|
|
|
#-NV21 Format
|
|
function gen_nv21_desc() {
|
|
gen_uncompressed_desc "nv21" "${NV21_GUID}" "${NV21_BITS}" "${NV21}"
|
|
}
|
|
|
|
#-H264 Format
|
|
function gen_h264_desc() {
|
|
gen_framebase_desc "h264" "${H264_GUID}" "${H264}"
|
|
}
|
|
|
|
#-H265 Format
|
|
function gen_h265_desc() {
|
|
gen_framebase_desc "h265" "${H265_GUID}" "${H265}"
|
|
}
|
|
|
|
#-MJPEG Format
|
|
function gen_mjpeg_desc() {
|
|
__gen_mjpeg_desc "${MJPEG}"
|
|
}
|
|
|
|
#-UVC common
|
|
function __gen_uvc_desc() {
|
|
local FUNNAME=$1
|
|
|
|
mkdir -p functions/$FUNNAME
|
|
cd functions/$FUNNAME
|
|
|
|
# streaming_maxpacket: 1 ~ 3072
|
|
# high-speed and super-speed: (1 ~ 3072); full-speed: (1 ~ 1023)
|
|
if [ $UVC_TRANSFER_MODE = "isoc" ];then
|
|
# USB ISOC transfer mode
|
|
echo 0 > streaming_bulk
|
|
echo 1 > streaming_interval
|
|
|
|
if [ $USB_SPEED = "fs" ];then
|
|
# USB full-speed
|
|
echo 0 > streaming_maxburst
|
|
echo 512 > streaming_maxpacket
|
|
elif [ $USB_SPEED = "hs" ];then
|
|
# USB high-speed
|
|
echo 0 > streaming_maxburst
|
|
echo 3072 > streaming_maxpacket
|
|
elif [ $USB_SPEED = "ss" ];then
|
|
# USB super-speed
|
|
echo 9 > streaming_maxburst
|
|
echo 3072 > streaming_maxpacket
|
|
fi
|
|
else
|
|
# USB BULK transfer mode
|
|
echo 1 > streaming_bulk
|
|
echo 0 > streaming_interval
|
|
|
|
if [ $USB_SPEED = "fs" ];then
|
|
# USB full-speed
|
|
echo 0 > streaming_maxburst
|
|
echo 64 > streaming_maxpacket
|
|
elif [ $USB_SPEED = "hs" ];then
|
|
# USB high-speed
|
|
echo 0 > streaming_maxburst
|
|
echo 512 > streaming_maxpacket
|
|
elif [ $USB_SPEED = "ss" ];then
|
|
# USB super-speed
|
|
echo 9 > streaming_maxburst
|
|
echo 1024 > streaming_maxpacket
|
|
fi
|
|
fi
|
|
|
|
mkdir -p control/header/h/
|
|
mkdir -p streaming/header/h/
|
|
|
|
echo "0x0110" > control/header/h/bcdUVC
|
|
echo "96000000" > control/header/h/dwClockFrequency
|
|
|
|
ln -s control/header/h/ control/class/fs/
|
|
ln -s control/header/h/ control/class/ss/
|
|
|
|
#YUYV
|
|
if [ $UVC_ENABLE_YUYV = "true" ];then
|
|
gen_yuyv_desc
|
|
fi
|
|
|
|
#NV21
|
|
if [ $UVC_ENABLE_NV21 = "true" ];then
|
|
gen_nv21_desc
|
|
fi
|
|
|
|
#MJPEG
|
|
if [ $UVC_ENABLE_MJPEG = "true" ];then
|
|
gen_mjpeg_desc
|
|
fi
|
|
|
|
#H264
|
|
if [ $UVC_ENABLE_H264 = "true" ];then
|
|
gen_h264_desc
|
|
fi
|
|
|
|
#H265
|
|
if [ $UVC_ENABLE_H265 = "true" ];then
|
|
gen_h265_desc
|
|
fi
|
|
|
|
ln -s streaming/header/h/ streaming/class/fs/
|
|
ln -s streaming/header/h/ streaming/class/hs/
|
|
ln -s streaming/header/h/ streaming/class/ss/
|
|
|
|
cd ../../
|
|
}
|
|
|
|
#-UAC common
|
|
function __gen_uac_desc() {
|
|
local FUNNAME=$1
|
|
|
|
mkdir -p functions/$FUNNAME
|
|
echo "0x01" > functions/$FUNNAME/c_chmask
|
|
echo "16000" > functions/$FUNNAME/c_srate
|
|
|
|
echo "0x01" > functions/$FUNNAME/p_chmask
|
|
echo "16000" > functions/$FUNNAME/p_srate
|
|
}
|
|
|
|
#-UVC
|
|
function gen_uvc_desc() {
|
|
__gen_uvc_desc "${FUNCTION_UVC}"
|
|
}
|
|
|
|
#-UVC1
|
|
function gen_uvc1_desc() {
|
|
__gen_uvc_desc "${FUNCTION_UVC1}"
|
|
}
|
|
|
|
#-UAC1
|
|
function gen_uac1_desc() {
|
|
__gen_uac_desc "${FUNCTION_UAC1}"
|
|
}
|
|
|
|
################################################################################################
|
|
|
|
# Main
|
|
APP_PATH=$PWD
|
|
|
|
# Step 1
|
|
mount -t configfs none /sys/kernel/config/
|
|
cd /sys/kernel/config/usb_gadget/
|
|
mkdir -p camera
|
|
cd camera
|
|
|
|
# Step 2
|
|
gen_dev_desc
|
|
|
|
# Step 3
|
|
if [ $UVC_ENABLE = true ];then
|
|
gen_uvc_desc
|
|
fi
|
|
|
|
if [ $UVC1_ENABLE = true ];then
|
|
gen_uvc1_desc
|
|
fi
|
|
|
|
if [ $UAC_ENABLE = true ];then
|
|
gen_uac1_desc
|
|
fi
|
|
|
|
# Step 4
|
|
#-Create and setup configuration
|
|
mkdir -p configs/c.1/
|
|
echo "500" > configs/c.1/MaxPower
|
|
echo "0x80" > configs/c.1/bmAttributes
|
|
mkdir -p configs/c.1/strings/0x409/
|
|
echo "Config 1" > configs/c.1/strings/0x409/configuration
|
|
|
|
# Step 5
|
|
if [ $UVC_ENABLE = true ];then
|
|
ln -s functions/${FUNCTION_UVC}/ configs/c.1/
|
|
fi
|
|
|
|
if [ $UVC1_ENABLE = true ];then
|
|
ln -s functions/${FUNCTION_UVC1}/ configs/c.1/
|
|
fi
|
|
|
|
if [ $UAC_ENABLE = true ];then
|
|
ln -s functions/${FUNCTION_UAC1}/ configs/c.1/
|
|
fi
|
|
|
|
# Step 6
|
|
dwc=$(ls /sys/class/udc)
|
|
echo "${dwc}" > UDC
|
|
|
|
# Step 7
|
|
#cd $APP_PATH
|
|
#./uvc_app
|