Compare commits

...

34 Commits

Author SHA1 Message Date
Neucrack
6aedfa43db fix init dev failed error 2025-07-30 13:34:59 +08:00
Neucrack
21ffdadc78 fix gitignore file error 2025-07-29 15:27:01 +08:00
Neucrack
64510bd44d optimize startup logo load and add PyQT5 package 2025-07-28 18:55:41 +08:00
Neucrack
4c9e842ee1 Merge pull request #90 from mcpanl/patch-1
Add USB audio support
2025-05-11 13:24:06 +08:00
洒脱
017c2724d2 Add USB audio support 2025-05-10 21:24:46 +08:00
lxowalle
639ae39291 * add isp config for os04a10 90fps 2025-04-21 15:31:01 +08:00
Neucrack
a3ccb527b2 add usb adbd support, enable with create /boot/usb.adbd file 2025-04-17 19:58:46 +08:00
lxowalle
e4e133f3df * fix audio bug 2025-03-11 18:02:41 +08:00
Neucrack
74169741e0 add compatibility with old mac addr config 2025-01-14 11:03:07 +08:00
Neucrack
48724b1a0d optimize uuid usage in init script 2025-01-11 15:35:19 +08:00
lxowalle
c4bd8d00cc * fix cvi_base deadlock2 2025-01-04 14:12:46 +08:00
lxowalle
d3b91ff1fd * fix cvi_base deadlock 2025-01-04 13:57:18 +08:00
lxowalle
80cd8fe0cf * optimize make_logo.sh 2024-12-25 13:46:24 +08:00
Neucrack
b8e61612e5 Merge pull request #71 from MK16kawai/main
[i2c@gpio5] Support for changing sda and scl at insmod time.
2024-12-20 19:04:06 +08:00
Mk16kawai
370d332f61 [i2c@gpio5] Support for changing sda and scl at insmod time. 2024-12-20 18:11:31 +08:00
taorye
1fcc2fd409 Merge branch 'feat_uvc_server_standalone_mode'
1. feat: UvcServer run in standalone mode without uvc-gadget-server.elf.
2. opt: provide 2560x1440.
2024-12-18 20:53:18 +08:00
taorye
b2af9afb7b fix: implement stop_server and restrict the server to run only in standalone mode. 2024-12-18 16:00:48 +08:00
taorye
6773bbd49c feat: up to 2560x1440 and all resulotions will be enabled default 2024-12-18 15:43:36 +08:00
taorye
3ce208ed4a Merge branch 'fix-uvc-gadget-cant-parse-config-file-with-first-empty-line'
1. provide source file of uvc-gadget-server
2. fix uvc_tool.sh to parse config file right
2024-12-16 19:22:39 +08:00
taorye
32fedadb95 fix: uvc_tool.sh cant provide empty line at first 2024-12-16 19:16:22 +08:00
taorye
71366bba6d chore: backup source code for the future 2024-12-16 18:58:08 +08:00
taorye
5394d82d36 Merge branch 'feat_uvc_gadget'
1. fix: ensure mjpg and yuyv formats both exist.
2. feat: add support for mjpeg streaming with mask 0x80.
3. feat: add support for auto config formats and set resolution limit.
2024-12-16 18:34:09 +08:00
taorye
3e15254fda feat: add support for auto config formats and set resolution limit 2024-12-16 18:33:50 +08:00
taorye
d687d7c89f feat: add support for streaming mjpg with 0x80 masked 2024-12-16 11:32:08 +08:00
taorye
e0857d878c fix: ensure mjpg and yuyv both exist 2024-12-16 11:31:08 +08:00
taorye
2506969b13 Merge branch 'feat_uvc_gadget'
1. feat: add uvc_tool.sh for uvc_gadget configfs mount and unmount.
2. feat: use uvc-gadget-server.elf to handle with uvc_gadget and provide shm to update framebuffer.
3. fix: expand img size to 1.5GB for additional files to be able to embedded in.
4. fix: high CPU usage for select unneeded dfds while !udev->is_streaming
2024-12-13 12:01:19 +08:00
taorye
71bcc30754 fix: high CPU usage for select unneeded dfds while !udev->is_streaming 2024-12-13 11:56:19 +08:00
taorye
c3b98df9aa fix: increase rootfs.sd's size from 1100M to 1536M 2024-12-12 18:16:53 +08:00
taorye
05cc1b41a9 feat: add support for uvc-gadget and provide a server default 2024-12-12 16:08:02 +08:00
Neucrack
c9179876b7 Merge pull request #68 from MK16kawai/main
[panel] support st7701_d310t9362v1
2024-12-10 16:53:22 +08:00
Mk16kawai
5613f01f4c [panel] support st7701_d310t9362v1 2024-12-10 16:36:33 +08:00
Neucrack
ae8d34b5c9 Merge pull request #67 from MK16kawai/main
[i2c5@gpio] supports dynamic rate modification
2024-12-10 15:07:06 +08:00
Mk16kawai
b9189b85b1 [i2c5@gpio] supports dynamic rate modification 2024-12-09 18:12:24 +08:00
Neucrack
fae0437895 fix customize build RNDIS and no /device_key file bug 2024-12-09 17:50:23 +08:00
32 changed files with 5577 additions and 432 deletions

3
.gitignore vendored
View File

@@ -3,7 +3,9 @@
*.o
*.ko
*.d
!init.d
host-tools/
host-tools
*.sqfs
build/tools/common/sd_tools/genimage.cfg.tmp
fsbl/build/*
@@ -419,3 +421,4 @@ osdrv/extdrv/wireless/.tmp_4261/
middleware/v2/lib
host-tools/
kvm/
.vscode*

View File

@@ -367,7 +367,9 @@ CONFIG_SND=y
# CONFIG_SND_DRIVERS is not set
CONFIG_SND_HDA_PREALLOC_SIZE=1
# CONFIG_SND_SPI is not set
# CONFIG_SND_USB is not set
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=y
CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_CV182XA_CV182XAADC=y
CONFIG_SND_SOC_CV182XA_CV182XADAC=y
@@ -1007,4 +1009,4 @@ CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_ACM=y
CONFIG_VETH=y
CONFIG_VETH=y

View File

@@ -1,4 +1,4 @@
<physical_partition type="sd">
<partition label="BOOT" size_in_kb="80960" readonly="false" file="boot.sd"/>
<partition label="ROOTFS" size_in_kb="1126400" readonly="false" file="rootfs.sd" />
<partition label="ROOTFS" size_in_kb="1638400" readonly="false" file="rootfs.sd" />
</physical_partition>

View File

@@ -17,18 +17,14 @@ then
insmod soph_vo.ko
# insmod soph_mipi_tx.ko
insmod soph_rgn.ko
insmod soph_wdt.ko
insmod soph_clock_cooling.ko
insmod soph_tpu.ko
insmod soph_vcodec.ko
insmod soph_jpeg.ko
insmod soph_vc_driver.ko MaxVencChnNum=9 MaxVdecChnNum=9
insmod soph_rtc.ko
insmod soph_ive.ko
insmod soph_mon.ko
insmod soph_pwm.ko
insmod soph_saradc.ko
insmod soph_wiegand.ko
# insmod soph_wiegand.ko # uncomment it if want use wiegand
echo "OK"
exit 0
fi

View File

@@ -1,31 +1,48 @@
#!/bin/sh
if ! command -v i2cget &> /dev/null
then
echo "i2cdetect not find, please install i2c-tools"
exit 1
fi
start() {
if ! command -v i2cget &> /dev/null
then
echo "i2cdetect not find, please install i2c-tools"
exit 1
fi
pmu_version=$(i2cget -y 4 0x34 0x03)
pmu_version=$((pmu_version & 0xCF))
pmu_version=$(i2cget -y 4 0x34 0x03)
pmu_version=$((pmu_version & 0xCF))
chip_id_1=$(printf "%d" 0x47)
chip_id_2=$(printf "%d" 0x4a)
chip_id_1=$(printf "%d" 0x47)
chip_id_2=$(printf "%d" 0x4a)
if [ "$pmu_version" -eq "$chip_id_1" ] || [ "$pmu_version" -eq "$chip_id_2" ]; then
case "$1" in
if [ "$pmu_version" -eq "$chip_id_1" ] || [ "$pmu_version" -eq "$chip_id_2" ]; then
exec /usr/bin/axp2101
echo "Starting PMU: OK\n"
fi
}
stop() {
runlevel=$(cat /run/runlevel | awk '{ print $1 }')
if [ "$runlevel" = "0" ]; then
printf "Stopping PMU\n"
value=$(i2cget -y 4 0x34 0x10)
value=$((value | 0x01))
i2cset -y 4 0x34 0x10 $value
fi
}
case "$1" in
start)
exec /usr/bin/axp2101
echo "Starting PMU: OK\n"
;;
stop)
runlevel=$(cat /run/runlevel | awk '{ print $1 }')
if [ "$runlevel" = "0" ]; then
printf "Stopping PMU\n"
value=$(i2cget -y 4 0x34 0x10)
value=$((value | 0x01))
i2cset -y 4 0x34 0x10 $value
if grep -q "pmu=axp2101" /boot/board 2>/dev/null; then
start
fi
;;
esac
fi
;;
stop)
if grep -q "pmu=axp2101" /boot/board 2>/dev/null; then
stop
fi
;;
*)
echo "Usage: /etc/init.d/S00pmu {start}"
exit 1
;;
esac

View File

@@ -6,7 +6,5 @@ then
printf "mounting filesystem : "
mkdir -p /boot
mount -t vfat /dev/mmcblk0p1 /boot
mount -t configfs configfs /sys/kernel/config
mount -t debugfs debugfs /sys/kernel/debug
echo "OK"
fi

View File

@@ -0,0 +1,13 @@
#!/bin/sh
if [ "$1" = "start" ]
then
str_value=$(cat /sys/class/cvi-base/base_uid | awk '{print $2}')
first_uint=$(echo $str_value | cut -d'_' -f1)
second_uint=$(echo $str_value | cut -d'_' -f2)
result="$first_uint$second_uint"
echo $result > /device_key
# for compatibility with previous network mac addr
cat /sys/class/cvi-base/base_uid > /device_key_legacy
fi

View File

@@ -2,7 +2,7 @@
if [ "$1" = "start" ]
then
. /etc/profile
# . /etc/profile
if [ ! -e /boot/alpha ]
then
devmem 0x030010AC 32 0x04 # PINMUX PWM10
@@ -21,11 +21,11 @@ then
then
panel_value=$(grep '^panel=' /boot/uEnv.txt | cut -d '=' -f 2)
fi
if [ "$panel_value" = "st7701_hd228001c31" ]
if [ "$panel_value" = "st7701_hd228001c31" ] || [ "$panel_value" = "st7701_lct024bsi20" ]
then
echo "2000" > ${blpwm}/duty_cycle # 20%
else
echo "9000" > ${blpwm}/duty_cycle
echo "5000" > ${blpwm}/duty_cycle
fi
echo 1 > $blpwm/enable
fi

View File

@@ -0,0 +1,10 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
printf "mounting filesystem : "
mount -t configfs configfs /sys/kernel/config
mount -t debugfs debugfs /sys/kernel/debug
echo "OK"
fi

View File

@@ -0,0 +1,14 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
printf "load kernel module: "
cd /mnt/system/ko/
insmod soph_wdt.ko
insmod soph_clock_cooling.ko
insmod soph_rtc.ko
insmod soph_mon.ko
echo "OK"
exit 0
fi

View File

@@ -76,6 +76,13 @@ then
echo 'licheervnano' > strings/0x409/product
fi
mkdir -p configs/c.1
# uvc
if [ -e /boot/usb.uvc ]
then
/etc/init.d/uvc_tool.sh mount /boot/usb.uvc
/etc/init.d/uvc_tool.sh server
fi
if [ -e /boot/usb.GS0 ]
then
mkdir -p functions/acm.GS0
@@ -161,13 +168,47 @@ then
ln -s functions/hid.GS2 configs/c.1
fi
ls /sys/class/udc/ | cat > UDC
# adbd
if [ -e /boot/usb.adbd ]
then
echo 0x18d1 > idVendor # google
mkdir -p configs/c.1/strings/0x409
echo "" > configs/c.1/strings/0x409/configuration
echo 0x80 > configs/c.1/bmAttributes
mkdir functions/ffs.adb
ln -s functions/ffs.adb configs/c.1/
mkdir -p /dev/usb-ffs/adb
mount -t functionfs adb /dev/usb-ffs/adb/
/usr/bin/adbd &
for i in $(seq 1 40); do
if [ -e /dev/usb-ffs/adb/ep2 ]; then
break
fi
sleep 0.1
done
fi
while true; do
ls /sys/class/udc/ | cat > UDC || true
res=$(cat UDC)
if [[ "x$res" != "x" ]]; then
break
fi
sleep 0.4
done
echo device > /proc/cviusb/otg_role
fi
fi
if [ "$1" = "stop" ]
then
echo '' > /sys/kernel/config/usb_gadget/g0/UDC
echo host > /proc/cviusb/otg_role
# uvc
if [ -e /sys/kernel/config/usb_gadget/g0/configs/c.1/uvc.usb0 ]
then
/etc/init.d/uvc_tool.sh unmount
fi
# rndis
if [ -e /sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0 ]
then
@@ -181,7 +222,5 @@ then
unlink /sys/kernel/config/usb_gadget/g0/configs/c.1/ncm.usb0
rmdir /sys/kernel/config/usb_gadget/g0/functions/ncm.usb0
fi
echo '' > /sys/kernel/config/usb_gadget/g0/UDC
echo host > /proc/cviusb/otg_role
fi

View File

@@ -19,7 +19,7 @@ then
prefix=$(cat /boot/hostname.prefix)
fi
old_hostname=$(cat /etc/hostname)
new_hostname=${prefix}-$(sha512sum /sys/class/cvi-base/base_uid | head -c 4)
new_hostname=${prefix}-$(sha512sum /device_key_legacy | head -c 4)
if [ -e /boot/hostname ]
then
@@ -38,7 +38,7 @@ then
then
new_ethmac=$(cat /boot/ethmac)
else
new_ethmac=$(hex2mac 48da356f$(sha512sum /sys/class/cvi-base/base_uid | head -c 4))
new_ethmac=$(hex2mac 48da356f$(sha512sum /device_key_legacy | head -c 4))
fi
ifconfig eth0 down

View File

@@ -0,0 +1,176 @@
#!/bin/sh
. /etc/profile
gen_udhcpd_conf() {
interface=${1}
ipv4_prefix=${2}
echo "start ${ipv4_prefix}.100"
echo "end ${ipv4_prefix}.200"
echo "interface ${interface}"
echo "pidfile /var/run/udhcpd.${interface}.pid"
echo "lease_file /var/lib/misc/udhcpd.${interface}.leases"
echo "option subnet 255.255.255.0"
echo "option lease 864000"
}
hex2mac() {
MAC=""
seq 2 2 12 | while read i
do
echo -n ${1} | head -c $i | tail -c 2
if [ $i != 12 ]
then
echo -n ':'
fi
done | tr '[:upper:]' '[:lower:]'
}
start() {
# S03usbdev start first
if [ -e /boot/usb.dev ]
then
rndis_ifname=usb0
# RNDIS
if [ -e /boot/usb.rndis ]
then
# mac
if [ -e /boot/usb.rndis.mac ]
then
new_rndismac=$(cat /boot/usb.rndis.mac)
else
new_rndismac=$(hex2mac 48da356f$(sha512sum /device_key_legacy | head -c 4))
fi
ip link set $rndis_ifname address ${new_rndismac}
ifconfig $rndis_ifname up
echo "rndis mac address: ${new_rndismac}"
# dhcp
if [ ! -e /boot/rndis.nodhcpd ]
then
if [ -e /boot/rndis.ipv4_prefix ]
then
ipv4_prefix=`cat /boot/rndis.ipv4_prefix`
else
id2=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 2))
id3=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 4 | tail -c 2))
id3=$((id3 + 1))
if [ "$id2" = "$id3" ]
then
id2=$((id2 + 2))
fi
if [ "$id2" -ge 255 ]
then
id2=252
fi
if [ "$id3" -ge 255 ]
then
id3=251
fi
ipv4_prefix=10.$id2.$id3
fi
gen_udhcpd_conf $rndis_ifname "${ipv4_prefix}" > /etc/udhcpd.${rndis_ifname}.conf
ip addr add $ipv4_prefix.1/24 dev $rndis_ifname
udhcpd -S /etc/udhcpd.${rndis_ifname}.conf
fi
echo "RNDIS DHCP OK"
rndis_ifname=usb1
fi
# CDC NCM
if [ -e /boot/usb.ncm ]
then
# mac
if [ -e /boot/usb.ncm.mac ]
then
new_mac=$(cat /boot/usb.ncm.mac)
else
new_mac=$(hex2mac 48da356e$(sha512sum /device_key_legacy | head -c 4))
fi
ip link set $rndis_ifname address ${new_mac}
ifconfig $rndis_ifname up
echo "ncm mac address: ${new_mac}"
# dhcp
if [ ! -e /boot/ncm.nodhcpd ]
then
if [ -e /boot/ncm.ipv4_prefix ]
then
ipv4_prefix=`cat /boot/ncm.ipv4_prefix`
else
id2=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 2))
id3=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 4 | tail -c 2))
if [ "$id2" = "$id3" ]
then
id2=$((id2 + 1))
fi
if [ "$id2" -ge 255 ]
then
id2=253
fi
if [ "$id3" -ge 255 ]
then
id3=254
fi
ipv4_prefix=10.$id2.$id3
fi
gen_udhcpd_conf $rndis_ifname "${ipv4_prefix}" > /etc/udhcpd.${rndis_ifname}.conf
ip addr add $ipv4_prefix.1/24 dev $rndis_ifname
udhcpd -S /etc/udhcpd.${rndis_ifname}.conf
fi
echo "CDC NCM DHCP OK"
fi
fi
}
stop() {
# first card
if [ -e /var/run/udhcpd.usb0.pid ]
then
kill $(cat "/var/run/udhcpd.usb0.pid")
rm /var/run/udhcpd.usb0.pid || true
fi
pnum=$(ps -ef|grep udhcpd|grep -v grep| grep udhcpd.usb0.conf | awk '{print $1}' | wc -l)
if [ x$pnum != x0 ]
then
ps -ef|grep udhcpd|grep -v grep| grep udhcpd.usb0.conf | awk '{print $1}'|xargs kill -2 || true
fi
usb0_info=$(ip link |grep usb0)
if [ -n "$usb0_info" ]
then
ifconfig usb0 down
fi
# second card
if [ -e /var/run/udhcpd.usb1.pid ]
then
kill $(cat /var/run/udhcpd.usb1.pid)
rm /var/run/udhcpd.usb1.pid || true
fi
pnum=$(ps -ef|grep udhcpd|grep -v grep| grep udhcpd.usb1.conf | awk '{print $1}' | wc -l)
if [ x$pnum != x0 ]
then
ps -ef|grep udhcpd|grep -v grep| grep udhcpd.usb1.conf | awk '{print $1}'|xargs kill -2 || true
fi
usb0_info=$(ip link |grep usb1)
if [ -n "$usb0_info" ]
then
ifconfig usb1 down
fi
}
restart() {
stop
start
}
if [ "${1}" = "start" ]
then
start
elif [ "${1}" = "stop" ]
then
stop
elif [ "${1}" = "restart" ]
then
restart
fi

View File

@@ -76,8 +76,8 @@ start() {
then
cp /boot/hostapd.conf /etc/hostapd.conf
else
id2=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 2))
id3=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 4 | tail -c 2))
id2=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 2))
id3=$(printf "%d" 0x$(sha512sum /device_key_legacy | head -c 4 | tail -c 2))
if [ "$id2" = "$id3" ]
then
id2=$((id2 + 1))

View File

@@ -27,8 +27,8 @@ case "$1" in
fi
echo "soc temp: $soc_temp" | fbbar 32 $colorfg $colorbg
colorfg=0xFFFFFFFF
echo "soc id: $(cat /sys/class/cvi-base/base_uid)" | fbbar 48 $colorfg $colorbg
sleep 1
echo "soc id: $(cat /device_key_legacy)" | fbbar 48 $colorfg $colorbg
sleep 1
done
) &
[ $? = 0 ] && echo "OK" || echo "FAIL"

View File

@@ -0,0 +1,274 @@
#! /bin/sh
# 支持的格式,可以通过修改这个变量自定义支持的格式
# Supported formats, you can customize the list by modifying this variable
supported_formats="yuyv mjpg"
# 支持的分辨率,可以通过修改这个变量自定义支持的分辨率
# Supported resolutions, you can customize the list by modifying this variable
supported_resolutions="480x320 640x360 640x480 1280x720 1920x1080 2560x1440"
parse_uvc_config() {
input_file="$1" # 传入的文件路径 / Path to the input file
parsed_data="" # 初始化 parsed_data 为空 / Initialize parsed_data as empty
# 检查文件是否存在并可读取 / Check if the file exists and is readable
if [ -z "$input_file" ]; then
# 没有提供文件路径 / No input file provided
echo "Warn: No input file provided for config." 1>&2 # 输出到标准错误 / Output to stderr
elif [ ! -f "$input_file" ]; then
# 文件不存在 / File does not exist
echo "Warn: File '$input_file' does not exist." 1>&2 # 输出到标准错误 / Output to stderr
elif [ ! -r "$input_file" ]; then
# 文件不可读取 / File is not readable
echo "Warn: File '$input_file' is not readable." 1>&2 # 输出到标准错误 / Output to stderr
else
# 使用 awk 处理文件内容 / Using awk to process the file content
parsed_data=$(awk -v resolutions="$supported_resolutions" -v formats="$supported_formats" '
BEGIN {
OFS = " ";
split(resolutions, supported_res, " "); # 将支持的分辨率放入数组 / Split the supported resolutions into an array
split(formats, supported_fmt, " "); # 将支持的格式放入数组 / Split the supported formats into an array
}
/^[^#]/ { # 只处理非 # 开头的行 / Process lines that do not start with #
fmt = $1;
res = $2;
# 检查格式是否在支持的格式列表中 / Check if the format is in the supported formats list
is_supported_fmt = 0;
for (i in supported_fmt) {
if (fmt == supported_fmt[i]) {
is_supported_fmt = 1;
break;
}
}
if (!is_supported_fmt) {
print "Unsupported format:", fmt > "/dev/stderr"; # 输出不支持的格式到标准错误 / Output unsupported format to stderr
next;
}
if (res ~ /^[0-9]+x[0-9]+$/) { # 匹配 640x360/1280x720 这种格式 / Match the format like 640x360 or 1280x720
is_supported_res = 0;
for (i in supported_res) {
if (res == supported_res[i]) {
is_supported_res = 1;
break;
}
}
if (!is_supported_res) {
print "Unsupported resolution:", res > "/dev/stderr"; # 输出不支持的分辨率到标准错误 / Output unsupported resolution to stderr
next;
}
split(res, dims, "x"); # 将 1280x720 按 "x" 分割成宽高 / Split 1280x720 into width and height
w = dims[1];
h = dims[2];
} else {
print "Invalid resolution format:", res > "/dev/stderr"; # 输出无效的分辨率格式到标准错误 / Output invalid resolution format to stderr
next;
}
print fmt, w, h; # 输出格式 fmt, w, h / Output fmt, w, h
}
' "$input_file")
fi
# 确保至少包含 'mjpg' 和 'yuyv' 格式 / Ensure at least one 'mjpg' and 'yuyv' format exists
has_mjpg=$(echo "$parsed_data" | grep -w "mjpg")
has_yuyv=$(echo "$parsed_data" | grep -w "yuyv")
if [ -z "$has_mjpg" ]; then
default_mjpg=$'\nmjpg 480x320\nmjpg 640x360\nmjpg 640x480\nmjpg 1280x720\nmjpg 1920x1080\nmjpg 2560x1440\n'
echo "Warn: No 'mjpg' config found, adding default: $default_mjpg" 1>&2
parsed_data="$parsed_data""$(echo "$default_mjpg" | sed 's/x/ /g')"
fi
if [ -z "$has_yuyv" ]; then
default_yuyv=$'\nyuyv 480x320\nyuyv 640x360\nyuyv 640x480\nyuyv 1280x720\nyuyv 1920x1080\nyuyv 2560x1440\n'
echo "Warn: No 'yuyv' config found, adding default: $default_yuyv" 1>&2
parsed_data="$parsed_data""$(echo "$default_yuyv" | sed 's/x/ /g')"
fi
parsed_data=$(echo "$parsed_data" | sed '/^$/d') # 删除空行
echo "$parsed_data" # 返回解析的数据 / Return the parsed data
}
##########################################################################
# UVC
CONFIGFS_PATH="/sys/kernel/config/usb_gadget/g0"
ORIGINAL_DIR=$(pwd) # 记录脚本启动时的目录 / Record the original working directory
create_frame() {
# Example usage:
# create_frame <width> <height> <format name>
WIDTH=$1
HEIGHT=$2
FORMAT=$3
if [ "$FORMAT" == "yuyv" ]; then
wdir=streaming/uncompressed/u/${HEIGHT}p
elif [ "$FORMAT" == "mjpg" ]; then
wdir=streaming/mjpeg/m/${HEIGHT}p
else
echo "only support format yuyv/mjpeg!"
exit 1
fi
mkdir -p $wdir
echo $WIDTH > $wdir/wWidth
echo $HEIGHT > $wdir/wHeight
echo $(( $WIDTH * $HEIGHT * 2 )) > $wdir/dwMaxVideoFrameBufferSize
echo $(( $WIDTH * $HEIGHT * 2 * 8 * 5 )) > $wdir/dwMinBitRate
echo $(( $WIDTH * $HEIGHT * 2 * 8 * 60 )) > $wdir/dwMaxBitRate
cat > $wdir/dwFrameInterval <<EOF
166666
333333
400000
500000
666666
1000000
2000000
EOF
echo "333333" > $wdir/dwDefaultFrameInterval
<< EOF
configure FrameRate
dwFrameInterfal is in 100-ns units (fps = 1/(dwFrameInterval * 10000000))
166666 -> 60 fps
333333 -> 30 fps
400000 -> 25 fps
500000 -> 20 fps
666666 -> 15 fps
1000000 -> 10 fps
2000000 -> 5 fps
5000000 -> 2 fps
10000000 -> 1 fps
EOF
}
# 挂载 UVC ConfigFS / Mount the UVC ConfigFS
mount_uvc_configfs() {
echo "Mounting UVC ConfigFS in $(pwd)"
# 创建 functions/uvc.usb0 目录 / Create the directory for uvc.usb0
mkdir -p functions/uvc.usb0
cd functions/uvc.usb0
# 在 functions/uvc.usb0 目录中创建控制头和符号链接 / Create control header and symlink it in uvc.usb0
mkdir -p control/header/h
ln -s control/header/h/ control/class/fs/
ln -s control/header/h/ control/class/ss/
# streaming_maxpacket sets wMaxPacketSize. Valid values are 1024/2048/3072
echo 1024 > streaming_maxpacket
# streaming_interval sets bInterval. Values range from 1..255
echo 1 > streaming_interval
# streaming_maxburst sets bMaxBurst. Valid values are 1..15
echo 1 > streaming_maxburst
# 在 functions/uvc.usb0 目录中创建流媒体路径 / Create streaming paths in uvc.usb0
mkdir -p streaming/uncompressed/u # YUV 目录 / YUV directory
mkdir -p streaming/mjpeg/m # MJPEG 目录 / MJPEG directory
# 执行解析并直接传递给 while 循环进行处理 / Execute parsing and directly pass to while loop for processing
parse_uvc_config "$1" | while read fmt w h; do
echo "Adding: Format: $fmt, Width: $w, Height: $h" # 输出格式、宽和高 / Output fmt, width, and height
create_frame $w $h $fmt
done
mkdir -p streaming/header/h
# 将 YUV 和 MJPEG 目录链接到流媒体头中 / Link YUV and MJPEG to streaming header
ln -s streaming/uncompressed/u/ streaming/header/h/
ln -s streaming/mjpeg/m/ streaming/header/h/
# 将 header 链接到 class 中 / Link header to classes
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 ../..
ln -s functions/uvc.usb0 configs/c.1
echo "UVC ConfigFS mounted successfully in $(pwd)"
}
# 卸载 UVC ConfigFS / Unmount the UVC ConfigFS
unmount_uvc_configfs() {
echo "Unmounting UVC ConfigFS in $(pwd)"
unlink configs/c.1/uvc.usb0
cd functions/uvc.usb0
# 删除流媒体目录 / Remove streaming directories
unlink streaming/class/fs/h
unlink streaming/class/hs/h
unlink streaming/class/ss/h
unlink streaming/header/h/u
unlink streaming/header/h/m
rmdir streaming/header/h
rmdir streaming/uncompressed/u/*p
rmdir streaming/mjpeg/m/*p
rmdir streaming/uncompressed/u
rmdir streaming/mjpeg/m
unlink control/class/fs/h
unlink control/class/ss/h
rmdir control/header/h
cd ../..
# 删除 functions/uvc.usb0 目录 / Remove the uvc.usb0 directory
rmdir functions/uvc.usb0
echo UVC ConfigFS unmounted successfully in $(pwd)
}
# 进入工作目录 / Enter the working directory
cd "$CONFIGFS_PATH" || return 1
# 处理传入的参数
# Process the input arguments
case "$1" in
"mount")
mount_uvc_configfs "$2"
;;
"unmount")
unmount_uvc_configfs
;;
"server")
if [ -z "$(fuser /etc/init.d/uvc-gadget-server.elf)" ]; then
(
echo "Waiting for UDC start..."
while [ -z "$(cat /sys/kernel/config/usb_gadget/g0/UDC)" ]; do
echo -n "."
sleep 1
done
sleep 3 # necessary delay time
if [ -z "$(fuser /etc/init.d/uvc-gadget-server.elf)" ]; then
echo -e "\nServer is starting..." # 输出选择了 server 模式 / Output that the server mode is selected
echo -e "===============================\n\n\n"
# 在这里添加你希望在 server 模式下执行的其他操作 / Add other operations you want to perform in server mode here
/etc/init.d/uvc-gadget-server.elf -u /dev/$(basename /sys/class/udc/*/device/gadget/video4linux/video*) -d -i /bin/cat_224.jpg
else
echo -e "\nServer has started..."
echo -e "===============================\n\n\n"
fi
) >/tmp/uvc-gadget.log 2>&1 &
fi
;;
"stop_server")
fuser -k /etc/init.d/uvc-gadget-server.elf
;;
*)
echo "Usage: $0 {mount <file>|unmount|server|stop_server}" # 提示正确的使用方式 / Prompt the correct usage
;;
esac
# 返回原始目录 / Return to the original directory
cd "$ORIGINAL_DIR" || return 1

File diff suppressed because it is too large Load Diff

View File

@@ -1252,6 +1252,7 @@ menu "External python modules"
source "package/python-pyphen/Config.in"
source "package/python-pyqrcode/Config.in"
source "package/python-pyqt5/Config.in"
source "package/python-pyqt5-sip/Config.in"
source "package/python-pyratemp/Config.in"
source "package/python-pyroute2/Config.in"
source "package/python-pyrsistent/Config.in"

View File

@@ -0,0 +1,7 @@
config BR2_PACKAGE_PYTHON_PYQT5_SIP
bool "python-pyqt5-sip"
help
This is the PyQt5.sip module which is needed at runtime for
the PyQt5 module from package python-pyqt5.
https://pypi.org/project/PyQt5-sip/

View File

@@ -0,0 +1,6 @@
# From https://pypi.org/pypi/PyQt5-sip/json
md5 9e0909e79f40619b0f2d3d3c33b4d4f7 PyQt5_sip-12.15.0.tar.gz
sha256 d23fdfcf363b5cedd9d39f8a9c5710e7d52804f5b08a58e91c638b36eafcb702 PyQt5_sip-12.15.0.tar.gz
# Locally calculated
sha256 3859cfca971e429d6b79bdfeb1dc9e43aa9592f7295bf28fdd62824097909383 LICENSE

View File

@@ -0,0 +1,24 @@
################################################################################
#
# python-sip-qt5
#
################################################################################
# Note about the package version:
# This module version corresponds in fact to the "sip" ABI
# version (not the version of its generator). See:
# https://github.com/Python-SIP/sip/blob/6.8.6/sipbuild/module/source/12/sip.h.in#L43
# The source git repository of this module is located at:
# https://github.com/Python-SIP/sip/tree/main/sipbuild/module/source
# The Python-SIP version/tag which generated a given "sip" module is
# recorded in the PyPI source file "sip.h", in the SIP_VERSION_STR
# macro. For example, PyQt5-sip 12.15.0 was generated with Python-SIP
# 6.8.6.
PYTHON_PYQT5_SIP_VERSION = 12.15.0
PYTHON_PYQT5_SIP_SITE = https://files.pythonhosted.org/packages/1b/15/78318d50f10062c428e97e7ce387e772616a4673c356018b905f247a6a85
PYTHON_PYQT5_SIP_SOURCE = PyQt5_sip-$(PYTHON_PYQT5_SIP_VERSION).tar.gz
PYTHON_PYQT5_SIP_LICENSE = BSD-2-Clause
PYTHON_PYQT5_SIP_LICENSE_FILES = LICENSE
PYTHON_PYQT5_SIP_SETUP_TYPE = setuptools
$(eval $(python-package))

View File

@@ -1,18 +1,40 @@
#!/bin/bash
# Check if the correct number of arguments is provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <input file path> <output file path>"
if [ "$#" -eq 2 ]; then
# Get input and output file paths
input_file="$1"
output_file="$2"
# Use ffmpeg to convert the image to YUV420P format JPEG
ffmpeg -i "$input_file" -pix_fmt yuvj420p "$output_file"
elif [ "$#" -eq 4 ]; then
# Get input and output file paths
input_file="$1"
output_file="$2"
output_width="$3"
output_height="$4"
# Use ffmpeg to convert the image to YUV420P format JPEG
ffmpeg -i "$input_file" -vf "scale=$output_width:$output_height" -pix_fmt yuvj420p "$output_file"
elif [ "$#" -eq 5 ]; then
# Get input and output file paths
input_file="$1"
output_file="$2"
output_width="$3"
output_height="$4"
transpose="$5"
# Use ffmpeg to convert the image to YUV420P format JPEG
ffmpeg -i "$input_file" -vf "transpose=$transpose,scale=$output_width:$output_height" -pix_fmt yuvj420p "$output_file"
else
echo "Usage: $0 <input file path> <output file path> <output width> <output height> <transpose>"
echo "example: $0 input.jpg logo.jpeg"
echo "example: $0 input.jpg logo.jpeg 640 480"
echo "example: $0 input.jpg logo.jpeg 640 480 3"
exit 1
fi
# Get input and output file paths
input_file="$1"
output_file="$2"
# Use ffmpeg to convert the image to YUV420P format JPEG
ffmpeg -i "$input_file" -pix_fmt yuvj420p "$output_file"
# Check if the conversion was successful
if [ $? -eq 0 ]; then
echo "The file has been successfully converted to YUV420P JPEG and saved to $output_file"

View File

@@ -7,6 +7,7 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c.h>
@@ -18,6 +19,25 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <linux/err.h>
#define DEBUG_LOG_TAG "[i2c gpio]"
#define DEBUG_LOG(fmt, ...) printk(KERN_DEBUG DEBUG_LOG_TAG " " fmt, ##__VA_ARGS__)
static int delay_us = -1;
volatile int udelay_value = 0;
struct kobject *udelay_v;
struct i2c_algo_bit_data *udelay_data = NULL;
static int sda = -1;
static int scl = -1;
static bool insmod_gpio = false;
struct i2c_gpio_private_data {
struct gpio_desc *sda;
struct gpio_desc *scl;
@@ -32,6 +52,49 @@ struct i2c_gpio_private_data {
#endif
};
static void show_freq(void)
{
switch(udelay_data->udelay) {
case 0:
DEBUG_LOG("Freq max ~ 750KHz for MaixCAM");
break;
case 1:
DEBUG_LOG("Freq 500KHz ~ 308KHz for MaixCAM");
break;
case 2:
DEBUG_LOG("Freq 250KHz");
break;
case 5:
DEBUG_LOG("Freq 100KHz");
break;
default:
DEBUG_LOG("Freq - Unknown");
break;
}
}
static ssize_t __udelay_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
// DEBUG_LOG("Read udelay value: %d\n", udelay_value);
show_freq();
udelay_value = udelay_data->udelay;
return sprintf(buf, "%d", udelay_value);
}
static ssize_t __udelay_store(struct kobject *kobj,
struct kobj_attribute *attr,const char *buf, size_t count)
{
// int old_value = udelay_value;
sscanf(buf,"%d",&udelay_value);
udelay_data->udelay = udelay_value;
// DEBUG_LOG("Write udelay value: %d --> %d\n", old_value, udelay_value);
// show_freq();
return count;
}
struct kobj_attribute sysfs_test_attr = __ATTR(udelay_v, 0664, __udelay_show, __udelay_store);
/*
* Toggle SDA by changing the output value of the pin. This is only
* valid for pins configured as open drain (i.e. setting the value
@@ -362,8 +425,10 @@ static int i2c_gpio_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
enum gpiod_flags gflags;
enum gpiod_flags gflags_sda, gflags_scl;
unsigned long gf_sda, gf_scl;
int ret;
struct device *curr_dev;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -384,6 +449,9 @@ static int i2c_gpio_probe(struct platform_device *pdev)
memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));
}
/* 508 SCL
509 SDA */
/*
* First get the GPIO pins; if it fails, we'll defer the probe.
* If the SCL/SDA lines are marked "open drain" by platform data or
@@ -392,21 +460,67 @@ static int i2c_gpio_probe(struct platform_device *pdev)
* handle them as we handle any other output. Else we enforce open
* drain as this is required for an I2C bus.
*/
if (pdata->sda_is_open_drain)
gflags = GPIOD_OUT_HIGH;
else
gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags);
if (IS_ERR(priv->sda))
return PTR_ERR(priv->sda);
if (sda >= 0 && scl >= 0) {
DEBUG_LOG("used sda %d and scl %d without device tree\n", sda, scl);
if (pdata->scl_is_open_drain)
gflags = GPIOD_OUT_HIGH;
else
gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags);
if (IS_ERR(priv->scl))
return PTR_ERR(priv->scl);
if (pdata->sda_is_open_drain) {
gf_sda = GPIOF_OUT_INIT_HIGH;
} else
gf_sda = GPIOF_OUT_INIT_HIGH | GPIOF_OPEN_DRAIN;
if (pdata->scl_is_open_drain)
gf_scl = GPIOF_OUT_INIT_HIGH;
else
gf_scl = GPIOF_OUT_INIT_HIGH | GPIOF_OPEN_DRAIN;
/* request sda */
ret = gpio_request_one(sda, gf_sda, "sda");
if (ret < 0) {
DEBUG_LOG("request sda failed!\n");
return -1;
}
priv->sda = gpio_to_desc(sda);
if (IS_ERR(priv->sda))
return PTR_ERR(priv->sda);
DEBUG_LOG("request sda succ!\n");
/* request scl */
ret = gpio_request_one(scl, gf_scl, "scl");
if (ret < 0) {
DEBUG_LOG("request scl failed!\n");
DEBUG_LOG("release sda\n");
gpio_free(sda);
return -1;
}
priv->scl = gpio_to_desc(scl);
if (IS_ERR(priv->scl))
return PTR_ERR(priv->scl);
DEBUG_LOG("request scl succ!\n");
insmod_gpio = true;
} else {
if (pdata->sda_is_open_drain)
gflags_sda = GPIOD_OUT_HIGH;
else
gflags_sda = GPIOD_OUT_HIGH_OPEN_DRAIN;
if (pdata->scl_is_open_drain)
gflags_scl = GPIOD_OUT_HIGH;
else
gflags_scl = GPIOD_OUT_HIGH_OPEN_DRAIN;
DEBUG_LOG("used sda and scl with device tree\n");
priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags_sda);
if (IS_ERR(priv->sda))
return PTR_ERR(priv->sda);
priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags_scl);
if (IS_ERR(priv->scl))
return PTR_ERR(priv->scl);
insmod_gpio = false;
}
if (gpiod_cansleep(priv->sda) || gpiod_cansleep(priv->scl))
dev_warn(dev, "Slow GPIO pins might wreak havoc into I2C/SMBus bus timing");
@@ -420,6 +534,9 @@ static int i2c_gpio_probe(struct platform_device *pdev)
bit_data->getscl = i2c_gpio_getscl;
bit_data->getsda = i2c_gpio_getsda;
udelay_data = bit_data;
/* Get udelay from device tree */
if (pdata->udelay)
bit_data->udelay = pdata->udelay;
else if (pdata->scl_is_output_only)
@@ -432,6 +549,17 @@ static int i2c_gpio_probe(struct platform_device *pdev)
else
bit_data->timeout = HZ / 10; /* 100 ms */
/* If `insmod ko delay_us=x` (x>=0) */
if (delay_us >= 0) {
DEBUG_LOG("Get delay_us from insmod: %d\n", delay_us);
bit_data->udelay = delay_us;
} else {
DEBUG_LOG("Get delay_us from device tree: %d\n", bit_data->udelay);
}
DEBUG_LOG("delay us: %d\n", bit_data->udelay);
show_freq();
bit_data->data = priv;
adap->owner = THIS_MODULE;
@@ -464,6 +592,17 @@ static int i2c_gpio_probe(struct platform_device *pdev)
i2c_gpio_fault_injector_init(pdev);
/* Add udelay kobj */
curr_dev = &pdev->dev;
udelay_v = kobject_create_and_add("udelay_value", &curr_dev->kobj);
if(sysfs_create_file(udelay_v, &sysfs_test_attr.attr)){
DEBUG_LOG("Create sysfs file failed!\n");
kobject_put(udelay_v);
sysfs_remove_file(kernel_kobj, &sysfs_test_attr.attr);
}
udelay_value = udelay_data->udelay;
return 0;
}
@@ -472,6 +611,11 @@ static int i2c_gpio_remove(struct platform_device *pdev)
struct i2c_gpio_private_data *priv;
struct i2c_adapter *adap;
if (insmod_gpio) {
gpio_free(scl);
gpio_free(sda);
}
i2c_gpio_fault_injector_exit(pdev);
priv = platform_get_drvdata(pdev);
@@ -479,6 +623,10 @@ static int i2c_gpio_remove(struct platform_device *pdev)
i2c_del_adapter(adap);
/* Remove udelay kobj */
kobject_put(udelay_v);
sysfs_remove_file(kernel_kobj, &sysfs_test_attr.attr);
return 0;
}
@@ -500,6 +648,15 @@ static struct platform_driver i2c_gpio_driver = {
.remove = i2c_gpio_remove,
};
module_param(delay_us, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(delay_us, "An integer parameter for the i2c udelay");
module_param(sda, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(sda, "sda gpio");
module_param(scl, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(scl, "scl gpio");
static int __init i2c_gpio_init(void)
{
int ret;

View File

@@ -20,6 +20,10 @@ static unsigned long pool_size_dma32;
static struct gen_pool *atomic_pool_kernel __ro_after_init;
static unsigned long pool_size_kernel;
#ifndef DEFAULT_DMA_COHERENT_POOL_SIZE
#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_1M
#endif
/* Size can be defined by the coherent_pool command line */
static size_t atomic_pool_size;
@@ -198,7 +202,7 @@ static int __init dma_atomic_pool_init(void)
if (!atomic_pool_size) {
unsigned long pages = totalram_pages() / (SZ_1G / SZ_128K);
pages = min_t(unsigned long, pages, MAX_ORDER_NR_PAGES);
atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, SZ_128K);
atomic_pool_size = max_t(size_t, pages << PAGE_SHIFT, DEFAULT_DMA_COHERENT_POOL_SIZE);
}
INIT_WORK(&atomic_pool_work, atomic_pool_work_fn);

View File

@@ -3,9 +3,38 @@
export PATH=/
msc() {
umount /dev/mmcblk0p1
umount /dev/mmcblk0p2
echo mmc0 > /sys/devices/platform/leds/leds/led-user/trigger
# backlight
devmem 0x030010AC 32 0x04 # PINMUX PWM10
blpwm="/sys/class/pwm/pwmchip8/pwm2/"
if [ ! -e "${blpwm}" ]
then
echo 2 > /sys/class/pwm/pwmchip8/export
fi
echo 0 > $blpwm/enable
echo "10000" > ${blpwm}/period # 100KHZ
panel_value=""
if [ -e /boot/board ]
then
panel_value=$(grep '^panel=' /boot/board | cut -d '=' -f 2)
elif [ -e /boot/uEnv.txt ]
then
panel_value=$(grep '^panel=' /boot/uEnv.txt | cut -d '=' -f 2)
fi
if [ "$panel_value" = "st7701_hd228001c31" ] || [ "$panel_value" = "st7701_lct024bsi20" ]
then
echo "2000" > ${blpwm}/duty_cycle # 20%
else
echo "5000" > ${blpwm}/duty_cycle
fi
echo 1 > $blpwm/enable
umount /dev/mmcblk0p1
umount /dev/mmcblk0p2 || true
# usb
mount -t configfs configfs /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g0
cd g0
@@ -65,31 +94,48 @@ mkdir -p /proc
mount -t proc proc /proc
mkdir -p /sys
mount -t sysfs sysfs /sys
mount -t configfs configfs /sys/kernel/config
mount -t debugfs debugfs /sys/kernel/debug
# mount -t debugfs debugfs /sys/kernel/debug
mkdir -p /boot
mount -o ro /dev/mmcblk0p1 /boot
msc=0
if [ -e /boot/rec ]
# wait ready
i=0
while [ ! -e /dev/mmcblk0p1 ] && [ $i -lt 5 ]; do
echo "Waiting for /dev/mmcblk0p1..."
sleep 1
i=$((i+1))
done
mount -o ro /dev/mmcblk0p1 /boot
ret=$?
if [ $ret -ne 0 ] || [ -e /boot/rec ]; then
echo "Mount boot failed, Entering recovery mode..."
msc
fi
# flashkey0=$(cat /sys/kernel/debug/gpio | grep 'User Key' | grep lo | wc -l)
# if [ "${flashkey0}" -ne 0 ]
# then
# msc
# fi
boot_key=0
for arg in $(cat /proc/cmdline); do
case "$arg" in
boot_key=*)
boot_key="${arg#boot_key=}"
;;
esac
done
if [ "${boot_key}" -eq 1 ] # boot key pressed
then
msc
fi
umount /dev/mmcblk0p1
flashkey0=$(cat /sys/kernel/debug/gpio | grep 'User Key' | grep lo | wc -l)
sleep 0.5
flashkey1=$(cat /sys/kernel/debug/gpio | grep 'User Key' | grep lo | wc -l)
if [ "${flashkey0}" -ne 0 ]
then
if [ "${flashkey1}" -ne 0 ]
then
msc
fi
fi
mkdir /realroot
# parted -s /dev/mmcblk0 "resizepart 2 -0"
# echo "yes

View File

@@ -18,6 +18,8 @@
#include <cvi_panels/cvi_panels.h>
#include <asm/io.h>
#include "part.h"
#include "fs.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -278,6 +280,40 @@ static int get_value_from_header(const char *filepath, const char *key, char *bu
return -2; // 未找到 key 或 value 为空
}
static bool fat_file_exists(const char *filename)
{
struct blk_desc *dev_desc;
#if defined(CONFIG_NAND_SUPPORT) || defined(CONFIG_SPI_FLASH)
const char *dev_part = "0:1";
int dev = 0;
#elif defined(CONFIG_EMMC_SUPPORT)
const char *dev_part = "1:1";
int dev = 1;
#else
const char *dev_part = "0:1";
int dev = 0;
#endif
dev_desc = blk_get_dev("mmc", dev);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
printf("Cannot find mmc device %s\n", dev_part);
return -ENODEV;
}
if (fs_set_blk_dev("mmc", dev_part, FS_TYPE_FAT)) {
printf("Failed to set fs device mmc %s\n", dev_part);
return -EINVAL;
}
if (fs_exists(filename)) {
printf("File %s exists on mmc %s\n", filename, dev_part);
return true;
} else {
printf("File %s not found on mmc %s\n", filename, dev_part);
return false;
}
}
/***************************************************/
static int do_startvo(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
@@ -288,6 +324,31 @@ static int do_startvo(struct cmd_tbl *cmdtp, int flag, int argc, char * const ar
if (argc < 4)
return CMD_RET_USAGE;
// check boot key pressed
// writel(0x00000003, 0x03001078);
uint32_t val = readl((const volatile void *)0x03020050);
int boot_key = (val >> 30) & 0x01; // GPIOA30
if (boot_key == 0) // boot key pressed
{
char *_bootargs = NULL;
char new_bootargs[256] = {0};
printf("boot key pressed\n");
_bootargs = env_get("othbootargs");
memcpy(new_bootargs, _bootargs, strlen(_bootargs));
char *boot_key_arg = " boot_key=1";
memcpy(new_bootargs + strlen(new_bootargs), boot_key_arg, strlen(boot_key_arg));
printf("new_othbootargs[%ld]: %s\n", strlen(new_bootargs), new_bootargs);
env_set("othbootargs", new_bootargs);
if (fat_file_exists("logo_upgrade.jpeg"))
env_set("logo", "logo_upgrade.jpeg");
else
env_set("logo", "logo.jpeg");
}
else
{
env_set("logo", "logo.jpeg");
}
dev = simple_strtoul(argv[1], &endp, 10);
if (*argv[1] == 0 || *endp != 0)
return CMD_RET_USAGE;
@@ -347,6 +408,12 @@ static int do_startvo(struct cmd_tbl *cmdtp, int flag, int argc, char * const ar
panel_desc.hs_timing_cfg = &hs_timing_cfg_d240si31; // g
panel_desc.dsi_init_cmds = dsi_init_cmds_d240si31; // g
panel_desc.dsi_init_cmds_size = ARRAY_SIZE(dsi_init_cmds_d240si31); // g
} else if (strcmp(panel_name,"st7701_d310t9362v1") == 0) {
panel_desc.panel_name = "ST7701-480x800";
panel_desc.dev_cfg = &dev_cfg_st7701_d310t9362v1_480x800;
panel_desc.hs_timing_cfg = &hs_timing_cfg_st7701_d310t9362v1_480x800;
panel_desc.dsi_init_cmds = dsi_init_cmds_st7701_d310t9362v1_480x800;
panel_desc.dsi_init_cmds_size = ARRAY_SIZE(dsi_init_cmds_st7701_d310t9362v1_480x800); // g
} else {
printf("panel %s not found\n\r", panel_name);
}

View File

@@ -283,9 +283,9 @@
#elif defined(CONFIG_SPI_FLASH)
#define LOAD_LOGO "sf probe;sf read " LOGO_READ_ADDR " ${MISC_PART_OFFSET} ${MISC_PART_SIZE};"
#else
#define LOAD_LOGO "mmc dev 0;load mmc 0:1 " LOGO_READ_ADDR " logo.jpeg ;"
#define LOAD_LOGO "mmc dev 0;load mmc 0:1 " LOGO_READ_ADDR " ${logo} ;"
#endif
#define SHOWLOGOCOMMAND LOAD_LOGO CVI_JPEG START_VO START_VL SET_VO_BG
#define SHOWLOGOCOMMAND START_VO LOAD_LOGO CVI_JPEG START_VL SET_VO_BG
#else
#define SHOWLOGOCMD
#endif

View File

@@ -32,6 +32,7 @@ struct panel_desc_s {
#include "dsi_st7701_dxq5d0019_V0.h"
#include "dsi_st7701_hd228001c31.h"
#include "dsi_d240si31.h"
#include "dsi_st7701_d310t9362v1.h"
#ifdef MIPI_PANEL_HX8394
#include "dsi_hx8394_evb.h"
@@ -172,6 +173,15 @@ static struct panel_desc_s panel_desc = {
.dsi_init_cmds = dsi_init_cmds_st7701_368x552_alt0,
.dsi_init_cmds_size = ARRAY_SIZE(dsi_init_cmds_st7701_368x552_alt0)
};
#elif defined(MIPI_PANEL_ST7701_UNKNOWN)
#include "dsi_st7701_d310t9362v1.h"
static struct panel_desc_s panel_desc = {
.panel_name = "ST7701-480x800",
.dev_cfg = &dev_cfg_st7701_d310t9362v1_480x800,
.hs_timing_cfg = &hs_timing_cfg_st7701_d310t9362v1_480x800,
.dsi_init_cmds = dsi_init_cmds_st7701_d310t9362v1_480x800,
.dsi_init_cmds_size = ARRAY_SIZE(dsi_init_cmds_st7701_d310t9362v1_480x800)
};
#elif defined(MIPI_PANEL_ST7785M)
#include "dsi_st7785m.h"
static struct panel_desc_s panel_desc = {

View File

@@ -0,0 +1,185 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _MIPI_TX_PARAM_ST7701_D310T9362V1_H_
#define _MIPI_TX_PARAM_ST7701_D310T9362V1_H_
// st7701_d310t9362v1
// ST7701_D310T9362V1
#ifndef __UBOOT__
#include <linux/vo_mipi_tx.h>
#include <linux/cvi_comm_mipi_tx.h>
#else
#include <cvi_mipi.h>
#endif
#define PANEL_NAME "ST7701_D310T9362V1"
#define ST7701_D310T9362V1_VACT 800
#define ST7701_D310T9362V1_VSA 10
#define ST7701_D310T9362V1_VBP 28
#define ST7701_D310T9362V1_VFP 8
#define ST7701_D310T9362V1_HACT 480
#define ST7701_D310T9362V1_HSA 10
#define ST7701_D310T9362V1_HBP 43
#define ST7701_D310T9362V1_HFP 48
#define ST7701_D310T9362V1_PIXEL_CLK(x) ((x##_VACT + x##_VSA + x##_VBP + x##_VFP) \
* (x##_HACT + x##_HSA + x##_HBP + x##_HFP) * 60 / 1000)
const struct combo_dev_cfg_s dev_cfg_st7701_d310t9362v1_480x800 = {
.devno = 0,
.lane_id = {MIPI_TX_LANE_0, MIPI_TX_LANE_CLK, MIPI_TX_LANE_1, -1, -1},
.lane_pn_swap = {false, false, false, false, false},
.output_mode = OUTPUT_MODE_DSI_VIDEO,
.video_mode = BURST_MODE,
.output_format = OUT_FORMAT_RGB_24_BIT,
.sync_info = {
.vid_hsa_pixels = ST7701_D310T9362V1_HSA,
.vid_hbp_pixels = ST7701_D310T9362V1_HBP,
.vid_hfp_pixels = ST7701_D310T9362V1_HFP,
.vid_hline_pixels = ST7701_D310T9362V1_HACT,
.vid_vsa_lines = ST7701_D310T9362V1_VSA,
.vid_vbp_lines = ST7701_D310T9362V1_VBP,
.vid_vfp_lines = ST7701_D310T9362V1_VFP,
.vid_active_lines = ST7701_D310T9362V1_VACT,
.vid_vsa_pos_polarity = true,
.vid_hsa_pos_polarity = false,
},
.pixel_clk = ST7701_D310T9362V1_PIXEL_CLK(ST7701_D310T9362V1),
};
const struct hs_settle_s hs_timing_cfg_st7701_d310t9362v1_480x800 = { .prepare = 6, .zero = 32, .trail = 1 };
#ifndef CVI_U8
#define CVI_U8 unsigned char
#endif
static CVI_U8 data_st7701_d310t9362v1_1[] = {0x01}; // len: 1, delay 120ms
static CVI_U8 data_st7701_d310t9362v1_2[] = {0x11}; // len: 1, delay 120ms
static CVI_U8 data_st7701_d310t9362v1_3[] = {0xFF,0x77,0x01,0x00,0x00,0x11}; // len: 6,
static CVI_U8 data_st7701_d310t9362v1_4[] = {0xD1,0x11}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_5[] = {0x55,0xb0}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_6[] = {0xFF,0x77,0x01,0x00,0x00,0x10}; // len: 6,
static CVI_U8 data_st7701_d310t9362v1_7[] = {0xC0,0x63,0x00}; // len: 3,
static CVI_U8 data_st7701_d310t9362v1_8[] = {0xC1,0x09,0x02}; // len: 3,
static CVI_U8 data_st7701_d310t9362v1_9[] = {0xC2,0x37,0x08}; // len: 3,
static CVI_U8 data_st7701_d310t9362v1_10[] = {0xC7,0x04}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_11[] = {0xCC,0x38}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_12[] = {0xB0,0x00,0x11,0x19,0x0C,0x10,0x06,0x07,0x0A,0x09,0x22,0x04,0x10,0x0E,0x28,0x30,0x1C}; // len: 17,
static CVI_U8 data_st7701_d310t9362v1_13[] = {0xB1,0x00,0x12,0x19,0x0D,0x10,0x04,0x06,0x07,0x08,0x23,0x04,0x12,0x11,0x28,0x30,0x1C}; // len: 17,
static CVI_U8 data_st7701_d310t9362v1_14[] = {0xFF,0x77,0x01,0x00,0x00,0x11}; // len: 6,
static CVI_U8 data_st7701_d310t9362v1_15[] = {0xB0,0x4D}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_16[] = {0xB1,0x60}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_17[] = {0xB2,0x07}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_18[] = {0xB3,0x80}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_19[] = {0xB5,0x47}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_20[] = {0xB7,0x8A}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_21[] = {0xB8,0x21}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_22[] = {0xC1,0x78}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_23[] = {0xC2,0x78}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_24[] = {0xD0,0x88}; // len: 2, delay 100ms
static CVI_U8 data_st7701_d310t9362v1_25[] = {0xE0,0x00,0x00,0x02}; // len: 4,
static CVI_U8 data_st7701_d310t9362v1_26[] = {0xE1,0x01,0xA0,0x03,0xA0,0x02,0xA0,0x04,0xA0,0x00,0x44,0x44}; // len: 12,
static CVI_U8 data_st7701_d310t9362v1_27[] = {0xE2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // len: 13,
static CVI_U8 data_st7701_d310t9362v1_28[] = {0xE3,0x00,0x00,0x33,0x33}; // len: 5,
static CVI_U8 data_st7701_d310t9362v1_29[] = {0xE4,0x44,0x44}; // len: 3,
static CVI_U8 data_st7701_d310t9362v1_30[] = {0xE5,0x01,0x26,0xA0,0xA0,0x03,0x28,0xA0,0xA0,0x05,0x2A,0xA0,0xA0,0x07,0x2C,0xA0,0xA0}; // len: 17,
static CVI_U8 data_st7701_d310t9362v1_31[] = {0xE6,0x00,0x00,0x33,0x33}; // len: 5,
static CVI_U8 data_st7701_d310t9362v1_32[] = {0xE7,0x44,0x44}; // len: 3,
static CVI_U8 data_st7701_d310t9362v1_33[] = {0xE8,0x02,0x26,0xA0,0xA0,0x04,0x28,0xA0,0xA0,0x06,0x2A,0xA0,0xA0,0x08,0x2C,0xA0,0xA0}; // len: 17,
static CVI_U8 data_st7701_d310t9362v1_34[] = {0xEB,0x00,0x01,0xE4,0xE4,0x44,0x00,0x40}; // len: 8,
static CVI_U8 data_st7701_d310t9362v1_35[] = {0xED,0xFF,0xF7,0x65,0x4F,0x0B,0xA1,0xCF,0xFF,0xFF,0xFC,0x1A,0xB0,0xF4,0x56,0x7F,0xFF}; // len: 17,
static CVI_U8 data_st7701_d310t9362v1_36[] = {0xFF,0x77,0x01,0x00,0x00,0x00}; // len: 6,
static CVI_U8 data_st7701_d310t9362v1_37[] = {0x36,0x10}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_38[] = {0x3A,0x55}; // len: 2,
static CVI_U8 data_st7701_d310t9362v1_39[] = {0x29}; // len: 1,
// LCD_Rotate_180
// static CVI_U8 data_st7701_d310t9362v1_40[] = {0xFF,0x77,0x01,0x00,0x00,0x10}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_41[] = {0xC7,0x00}; // len: 2,
// static CVI_U8 data_st7701_d310t9362v1_42[] = {0xFF,0x77,0x01,0x00,0x00,0x00}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_43[] = {0x36,0x00}; // len: 2,
// static CVI_U8 data_st7701_d310t9362v1_44[] = {0xFF,0x77,0x01,0x00,0x00,0x11}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_45[] = {0xB1,0x5B}; // len: 2,
// LCD_Rotate_0
// static CVI_U8 data_st7701_d310t9362v1_46[] = {0xFF,0x77,0x01,0x00,0x00,0x10}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_47[] = {0xC7,0x04}; // len: 2,
// static CVI_U8 data_st7701_d310t9362v1_48[] = {0xFF,0x77,0x01,0x00,0x00,0x00}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_49[] = {0x36,0x10}; // len: 2,
// static CVI_U8 data_st7701_d310t9362v1_50[] = {0xFF,0x77,0x01,0x00,0x00,0x11}; // len: 6,
// static CVI_U8 data_st7701_d310t9362v1_51[] = {0xB1,0x60}; // len: 2,
// len == 1 , type 0x05
// len == 2 , type 0x15 or type 23
// len >= 3 , type 0x29 or type 0x39
#define TYPE1_DCS_SHORT_WRITE 0x05
#define TYPE2_DCS_SHORT_WRITE 0x15
#define TYPE3_DCS_LONG_WRITE 0x39
#define TYPE3_GENERIC_LONG_WRITE 0x29
const struct dsc_instr dsi_init_cmds_st7701_d310t9362v1_480x800[] = {
{.delay = 120, .data_type = TYPE1_DCS_SHORT_WRITE, .size = 1, .data = data_st7701_d310t9362v1_1 },
{.delay = 120, .data_type = TYPE1_DCS_SHORT_WRITE, .size = 1, .data = data_st7701_d310t9362v1_2 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_3 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_4 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_5 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_6 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 3, .data = data_st7701_d310t9362v1_7 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 3, .data = data_st7701_d310t9362v1_8 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 3, .data = data_st7701_d310t9362v1_9 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_10 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_11 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 17, .data = data_st7701_d310t9362v1_12 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 17, .data = data_st7701_d310t9362v1_13 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_14 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_15 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_16 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_17 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_18 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_19 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_20 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_21 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_22 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_23 },
{.delay = 100, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_24 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 4, .data = data_st7701_d310t9362v1_25 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 12, .data = data_st7701_d310t9362v1_26 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 13, .data = data_st7701_d310t9362v1_27 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 5, .data = data_st7701_d310t9362v1_28 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 3, .data = data_st7701_d310t9362v1_29 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 17, .data = data_st7701_d310t9362v1_30 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 5, .data = data_st7701_d310t9362v1_31 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 3, .data = data_st7701_d310t9362v1_32 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 17, .data = data_st7701_d310t9362v1_33 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 8, .data = data_st7701_d310t9362v1_34 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 17, .data = data_st7701_d310t9362v1_35 },
{.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_36 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_37 },
{.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_38 },
{.delay = 0, .data_type = TYPE1_DCS_SHORT_WRITE, .size = 1, .data = data_st7701_d310t9362v1_39 },
/* LCD_Rotate_180 */
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_40 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_41 },
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_42 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_43 },
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_44 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_45 },
/* LCD_Rotate_0 */
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_46 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_47 },
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_48 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_49 },
// {.delay = 0, .data_type = TYPE3_GENERIC_LONG_WRITE, .size = 6, .data = data_st7701_d310t9362v1_50 },
// {.delay = 0, .data_type = TYPE2_DCS_SHORT_WRITE, .size = 2, .data = data_st7701_d310t9362v1_51 },
};
#else
#error "_MIPI_TX_PARAM_ST_7701_H_ multi-delcaration!!"
#endif // _MIPI_TX_PARAM_ST7701_D310T9362V1_H_