本教程适合有一定Linux基础的小白学习,如果遇到不懂的问题请优先自己百度,学习本身就是一个递归过程,学到至深处你就已经是个大佬了,本人纯小白菜鸡一枚,如果文章出现错误还请指出,事前先交代一些信息:
博主我使用的是:
- 台电网络摄像头TL-L220-NDD2K(中星微)
- newifi D1 无线路由器
- 老毛子固件padavan hiboy汉化版3.4.3.9-099_20-02-3
主人公们一览:
1.台电网络摄像头TL-L220-NDD2K(本次主角)
2.newifi D1 无线路由器
3.老毛子固件padavan hiboy汉化版3.4.3.9-099_20-02-3
padavan固件:为啥我只是个文件?!
PS:不建议入手newifi D1,要买就买newifi D2。
任何事情开始之前都得做好准备,首先要测试一下你的USB摄像头到底还能不能正常工作,防止折腾半天发现原来设备是坏的,将USB摄像头和计算机联机(Windows),学习下面这篇文章:
https://blog.csdn.net/wuye110/article/details/8443913
通过学习以上文章,你至少已经懂得了什么是硬件ID
现在已经知道了硬件ID是多少,把它抄下来:
VID:0AC8
PID:3340
如果你的USB摄像头在Windows下找不到驱动,可以根据以上信息上网找驱动安装好。检查一下能否正常工作:
可以正常工作,就是东西太老,像素感人,拍人都自带美颜,通过上面发的链接,基本可以确认它的一些消息:
这篇文章主要是方便网友寻找当年Windows下USB摄像头驱动支持(现在这些链接都失效了),但是我们需要的是Linux的驱动,无奈且去查一下看看Linux下,这个硬件有没有驱动支持,奉上另一个博主的链接:
https://blog.csdn.net/huofeng_2008/article/details/49762323
顺便整理一下支持列表链接:
http://www.linux-usb.org/usb.ids
http://www.ideasonboard.org/uvc/
http://linuxtv.org/wiki/index.php/Gspca_devices
咦?说好免驱的呢?怎么不在官方支持的列表里呢?看了一些网站的资料,都没有发现明确支持这个型号的USB摄像头,是不是我的USB摄像头被时代抛弃了?折腾就此收手了?不!实际上,只要你的USB摄像头确实是免驱类型的,一般就能驱动得了!不要气馁善罢甘休,要折腾到底!(如果你没有折腾精神,无法继续坚持到底,不能屡败屡战的话,建议你现在就放弃)
接下来,来到路由器折腾环节:
首先确保你的opt空间足够大(至少512MiB)
然后,优先解决hiboy魔改padavan固件的一些遗留的坑爹BUG!(带你一起魔改padavan!)
刷完hiboy的padavan,换个主题,你的opt设置页面应该是这样的:
你会发现,右边有一个内容是 “备份 /opt/lib|bin” 的绿色按钮, 请留意这个家伙,它非常可能让你的一切努力功亏一篑!!! 因为当固件自带脚本跑完安装opt的任务之后,/opt目录下会有一个叫“opt_backup”的文件夹,里面有/opt/bin和/opt/lib下所有文件的备份和md5校验值,如果你修改了/opt/bin下的任意程序(修改、升级或删除,/opt/lib同理),在下次路由器重启之后,挂载opt之前,系统自带脚本会优先检查opt_backup下的文件和/opt下的文件是否一致,如果不一致,会优先恢复opt_backup里的文件到opt目录里面,如果opt有opt_backup里没有的东西,则会从opt备份文件到opt_backup。这种备份还原机制看起来貌似是防止路由器掉电后造成的文件损坏,但我感觉是为了防止你修改opt文件夹产生其他兼容问题,应该是怕小白折腾坏了。 如果没有按本教程操作,你通过opkg升级了软件,也就是修改了opt内容,下次重启后会直接覆盖还原你修改的文件,但软件版本信息并没有还原回来,新增的lib文件也没有删掉,导致各种莫名其妙的版本不匹配的严重后果,如果这个事情发生了,你唯一能做的就是删除这个opt目录下的所有文件,然后到opt设置页面里重置opt!
所以,我们要想保留修改, 得先把opt_backup文件夹删除掉 ,同时 也把opt目录下名字里含有opt并且以tgz结尾的文件删除掉 ,以绝后患,在做完本教程里的所有任务后,去到这个opt设置页面点击这个 “备份 /opt/lib|bin” 绿色按钮,它会在系统日志里输出当前动作,待到备份完成,才可以重启,以后只要是修改了/opt/bin或/opt/lib目录下的文件,都要记得重新来一遍备份操作!切记!!!
优先解决一个挂载了opt环境却不能正常工作的BUG:
问题分析:LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径,在没有魔改之前,你执行命令export
得到的结果里,LD_LIBRARY_PATH那行应该是这样:
export LD_LIBRARY_PATH='/lib:/opt/lib'
而我们的PATH路径却是这样的:
export PATH='/etc/storage/bin:/tmp/script:/etc/storage/script:/opt/usr/sbin:/opt/usr/bin:/opt/sbin:/opt/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin'
这样,问题就很严重了,假如我们要用到的程序不是固件自带的,而是通过opt安装的,系统执行程序的时候,会优先在/lib里面找它依赖的库文件,如果没找到才会去/opt/lib里找,但是固件里自带的库文件很可能是过时的,一旦/lib里恰好有同名的库文件但却过时,导致不兼容,使得opt安装的新软件无法正常工作,甚至导致系统不稳定,产生难以预料的恐怖后果。所以我们要把这个BUG修复过来。学习一下文章:
https://www.right.com.cn/forum/thread-184418-1-1.html
我们可以知道,只有/etc/storage下的文件可以烧入到flash里和固件长存,而/etc/storage是可读可写的!虽然padavan启动起来是个Read-only系统,只读,不可写,但是没关系,有这个突破口跟着固件一起保存,我们就可以魔改:
通过执行命令ls -l -h /etc/profile
我们可以知道它是个软连接文件,它的真身是/etc_ro/profile,大胆放心删除它:
rm /etc/profile
我们把它的真身拷贝过来,与固件长存:
cp /etc_ro/profile /etc/storage/profile
简单修改一下这个profile文件,完成profile自定义:
busybox vi /etc/storage/profile
修改之后如下:
# /etc/profile
# If running interactively, then
if [ "$PS1" ] ; then
export PATH='/etc/storage/bin:/tmp/script:/etc/storage/script:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin'
export HOSTNAME=`/bin/hostname`
export TERMINFO=/usr/share/terminfo
export TERM=xterm
export LD_LIBRARY_PATH=/lib
export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'
export PS1='\[\e]0;\h: \w\a\][\[\e[36;1m\]\h \[\e[35;1m\]\w\[\e[m\]]\$ '
echo -e "[\033[36m$(grep Web_Title= /www/EN.dict | sed 's/Web_Title=//g'| sed 's/ 无线路由器\| Wireless Router//g')\033[0m \033[35m$(nvram get firmver_sub)\033[0m]# \033[33m$(date "+%Y-%m-%d %H:%M:%S")\033[0m"
fi;
alias treboot="sh +x /opt/home/reboot-diy.sh"
alias c='clear'
alias f='find / -name '
alias ll='ls -alF'
alias mc='mc -c'
alias md5='md5sum'
alias sl='less /tmp/syslog.log'
ulimit -HSn 65536
if [ -r /opt/etc/profile ] ;then
. /opt/etc/profile
export PATH="/etc/storage/bin:/tmp/script:/etc/storage/script:\
/opt/usr/sbin:/opt/usr/bin:/opt/sbin:/opt/bin:\
/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin"
export LD_LIBRARY_PATH="/opt/lib:/lib"
fi
把diy之后的profile软链接到etc之下,并使之生效:
ln -s /etc/storage/profile /etc/profile
source /etc/profile
WebUI转跳到 “系统管理——恢复/导出/上传设置——保存 /etc/storage/ 内容到闪存” 盯住这个按钮,点击提交,待到按钮变成浅绿色一小会儿后变回原来的颜色即表示刷写flash成功(此时/etc/storage下的所有文件与固件长存):
因为原生固件对reboot程序有做专门处理,是个不同于原生busybox里的reboot的程序,所以千万不要通过opkg安装或更新busybox,固件自带程序需要固件自带lib库(如果重启任务未能正常执行,将可能导致机器假死,无法重启,只能掉电强制重启),因此为了确保重启任务是完整且正确执行(真正的重启)的,我们把LD_LIBRARY_PATH修改回来,我特意写了一个脚本以方便一条命令做完,因为当且仅当opt挂载成功了才会修改LD_LIBRARY_PATH,所以我把脚本文件放到了opt目录下
touch /opt/home/reboot-diy.sh
chmod 755 /opt/home/reboot-diy.sh
/opt/home/reboot-diy.sh的内容如下:
#!/bin/sh
export PATH="/etc/storage/bin:/tmp/script:/etc/storage/script:\
/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin"
export LD_LIBRARY_PATH="/lib"
reboot
之前在自定义的profile里已经加了alias treboot="sh +x /opt/home/reboot-diy.sh"
,日后如果opt正常挂载的话,想重启路由器直接执行命令treboot
即可正常正确地重启你的路由器,一步到位。
看到这里,可能部分网友会问,如果/opt/lib下的库文件不兼容固件自带的老版本程序怎么办?我可以放心告诉你,折腾到现在就没翻车过,估计新版lib做了向后兼容处理,大胆放心用,但是reboot程序必须特殊照顾。
这个LD_LIBRARY_PATH之BUG修复还没完,我们要做到开机自动替换原来的profile并使之生效,首先要确保opt确定是我们要的那个存储空间(因为如果opt从U盘或TF卡里挂载失败之后,系统脚本会自动把opt重新安装到内存里面!),我们在opt下创建一个smb_share文件夹,同时往里面添加一个文件:
mkdir -p /opt/smb_share
chmod 755 -R /opt/smb_share
touch /opt/smb_share/for-test-loaded.txt
然后WebUI里面添加开机脚本,到 “自定义设置——在路由器启动后执执行” 的最低部添加内容:
#脚本位置:/etc/storage/started_script.sh
#swapon /media/XFL/swapfile
if [ -r /opt/smb_share/for-test-loaded.txt ] ;then
logger -t "【运行路由器启动后】" "DIY:opt已挂载"
else
logger -t "【运行路由器启动后】" "DIY:opt未挂载,开始挂载"
sh +x /etc/storage/script/Sh01_mountopt.sh start
sleep 10
fi
if [ -r /opt/smb_share/for-test-loaded.txt ] ;then
rm /etc/profile
ln -s /etc/storage/profile /etc/profile
source /etc/profile
export PATH="/etc/storage/bin:/tmp/script:/etc/storage/script:\
/opt/usr/sbin:/opt/usr/bin:/opt/sbin:/opt/bin:\
/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin"
export LD_LIBRARY_PATH="/opt/lib:/lib"
#chown nobody:nogroup -R /opt/wwwroot/default
#chmod 755 -R /opt/wwwroot/default
#mount --bind /opt /media/XFL/remote-opt-img
#Do anything you want!
else
logger -t "【运行路由器启动后】" "DIY:opt挂载失败!"
fi
UI界面看起来是这样的:
不要忘记页面滑动到最低部保存设置——应用本页面设置!!!
这样,opt软件的运行环境的BUG算是彻底修复了,再次检查一下系统环境export
以防万一,当然再执行一遍export LD_LIBRARY_PATH="/opt/lib:/lib"
也是非常可以的。
我们先更新一下opkg(请确保你的opt环境软件来源是Entware!),因为Entware使用的是Cloudflare的CDN加速,实际上,一般国内DNS解析到的CDN节点速度都非常慢,如果你勇于尝试,你可以自己去修改一下路由器的hosts文件!强行解析到速度比较快的节点!比如,直接往hosts文件添加这个解析(重启后会被自动还原失效),懒人一键命令:echo "104.16.192.22 bin.entware.net" >> /etc/hosts
,优先更新wget,先更新下载工具以提升下载体验,然后升级软件:
opkg update && opkg install wget
opkg upgrade
然后安装一堆的软件:
opkg install curl sudo lrzsz whereis #不要busybox
opkg install usbutils e2fsprogs tune2fs
opkg install libfdisk libext2fs
opkg install gcc gdb make cmake python3 python3-pip
opkg install htop iftop mtr
opkg install libstdcpp libpthread libjson-c
opkg install binutils coreutils dbus-utils diffutils swap-utils sysfsutils
opkg install kmod libkmod libmodbus
opkg install libusb-compat usbreset usbutils
opkg install v4l-utils uvcdynctrl libwebcam oscam
opkg install openssl-util script-utils
#覆盖 coreutils-ch* 基本工具为GNU版本
opkg install `opkg list 'coreutils-ch**' | awk '{print $1}'`
#mjpg-streamer 全家桶
opkg install `opkg list '*mjpg-streamer*' | awk '{print $1}'`
至此,你已经安装完了所有必须的软件,WebUI请到 配置扩展环境——配置扩展环境 点击之前说的那个 内容是“备份 /opt/lib|bin” 的绿色按钮 ,然后把USB摄像头插到路由器上吧!
检查一下padavan是否识别到USB硬件:
dmesg | grep usb
以下是我路由器的输出:
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
usbcore: registered new interface driver libusual
usbcore: registered new interface driver usblp
usbcore: registered new interface driver usb-storage
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: Product: xHCI Host Controller
usb usb1: Manufacturer: Linux 3.4.113 xhci-hcd
usb usb1: SerialNumber: xhci-hcd
usb usb2: New USB device found, idVendor=1d6b, idProduct=0003
usb usb2: Product: xHCI Host Controller
usb usb2: Manufacturer: Linux 3.4.113 xhci-hcd
usb usb2: SerialNumber: xhci-hcd
usb 1-2: new high-speed USB device number 2 using xhci-hcd
usb 1-2: New USB device found, idVendor=0ac8, idProduct=3340
usb 1-2: Product: Sirius USB2.0 Camera
usb 1-2: Manufacturer: Vimicro Corp.
可以看到,最后4行,idVendor(VID)=0ac8,idProduct(PID)=3340,和我之前抄下来的硬件ID完全匹配没毛病,就是它了——USB摄像头台电网络摄像头TL-L220-NDD2K。
如果不好查看,可以使用另外一条命令:
lsusb
以下是我路由器的输出:
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 0ac8:3340 Z-Star Microelectronics Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
可以看到,第二行就是本次主角USB摄像头,硬件ID也完全对得上。
我之前看到一篇文章:https://blog.csdn.net/aileheart/article/details/79809781
我还以为离成功近了一大步,可怕的是,这是一个坑的开始,太坑人了。
按照他的做法,执行完命令modprobe uvcvideo
后,USB摄像头就应该驱动起来了,兴致冲冲地执行命令ls /dev/video*
结果却是这样的:
ls: /dev/video*: No such file or directory
明摆着还没成功挂载USB摄像头嘛!!
问题原因很简单,就是uvcvideo这个内核模块没有成功加载,导致驱动失败。
解决这个坑,首先 重点学习 一下这个文章:
https://www.cnblogs.com/jacklikedogs/p/4659249.html
前面有文章分析过,padavan启动起来是个Read-only系统,那么便不能通过执行命令depmod -a
来一键分析所有可加载模块的依赖性,生成modules.dep文件和映射文件。以我当前固件来说,padavan执行命令modprobe uvcvideo
并不能加载成功uvcvideo这个内核模块,而且通过modprobe加载内核模块的话,什么反馈都没有,到底是加载成功了还是失败了,不知道!(因为这个坑,我还曾一度以为我的USB摄像头真的不行了,挂不上去)
不过我们可以通过别的命令来检查模块是否加载:
lsmod | grep uvcvideo
如果通过命令modprobe uvcvideo
加载成功了,那便是成功了,如果没有,可以手动加载内核模块(有先后加载顺序要求,因为内核模块具有依赖性),加载之前,先看看都有哪些文件,全部都加载起来肯定覆盖设备型号范围Max,执行命令:
ls -l -h /lib/modules/3.4.113/kernel/drivers/media/video/
这条命令中的数字那部分看具体情况,可能会不一样,我的固件输出结果如下:
drwxr-xr-x 2 root root 34 Feb 10 02:20 uvc
-rw-r--r-- 1 root root 5.8K Feb 10 02:20 v4l2-common.ko
-rw-r--r-- 1 root root 4.0K Feb 10 02:20 v4l2-int-device.ko
-rw-r--r-- 1 root root 28.8K Feb 10 02:20 videobuf2-core.ko
-rw-r--r-- 1 root root 3.8K Feb 10 02:20 videobuf2-memops.ko
-rw-r--r-- 1 root root 4.8K Feb 10 02:20 videobuf2-vmalloc.ko
-rw-r--r-- 1 root root 116.3K Feb 10 02:20 videodev.ko
uvc是个文件夹,继续查看它里面有什么,执行命令:
ls -l -h /lib/modules/3.4.113/kernel/drivers/media/video/uvc/
输出:
-rw-r--r-- 1 root root 89.5K Feb 10 02:20 uvcvideo.ko
啊哈!这不就是我们要加载的目标模块吗?
废话不多说,上代码:
insmod /lib/modules/3.4.113/kernel/drivers/media/video/videobuf2-core.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/videobuf2-memops.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/videobuf2-vmalloc.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/videodev.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/v4l2-int-device.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/v4l2-common.ko
insmod /lib/modules/3.4.113/kernel/drivers/media/video/uvc/uvcvideo.ko
通过执行完以上命令,USB摄像头应该就已经驱动起来了,但是我们还是优先检查一下uvcvideo模块是否加载成功,执行命令
lsmod | grep uvcvideo
我的路由器输出:
uvcvideo 60192 0
videodev 77616 2 uvcvideo,v4l2_common
videobuf2_vmalloc 1840 1 uvcvideo
videobuf2_core 17824 1 uvcvideo
有信息,确实加载成功了,查看USB摄像头是否挂载:
ls /dev/video*
我的路由器输出:
/dev/video0
不再是not found了!至此,USB摄像头算是真的挂载成功了!
但是能否正常驱动呢?
在此,要感谢这位博主的文章:
https://blog.csdn.net/aiwangtingyun/article/details/79834959
他直接提供了C程序源码,当然,我们可以做个简单测试,编译运行这个程序:
使用Notepad++,复制源代码,修改文件编码格式为UTF-8编码,修改行尾为Unix格式(LF),给文件取名为testCam.c,提供命令rz
直接通过Xshell把文件传输到当前命令行所在文件夹里,执行命令:
gcc testCam.c -o testCam
chmod 755 testCam
./testCam
它会在当前目录生成一个名叫“my.yuyv”的文件,这种格式当然不能直接打开,通过命令sz my.yuyv
通过Xshell直接把文件从Linux发送到Windows里,通过格式工厂转化图片格式为png,以下是我这般操作获得的第一张照片:
些许是因为曝光时间不够长才会这样的,我也没有去深入研究这个源代码,不过至少可以证明它确实可以驱动!
接下来折腾mjpg-streamer!mjpg-streamer项目官网是:
https://sourceforge.net/p/mjpg-streamer/code/HEAD/tree/
下载并拷贝好网页文件
mkdir -p /opt/wwwroot
mkdir -p /opt/wwwroot/webcam
wget https://sourceforge.net/code-snapshots/svn/m/mj/mjpg-streamer/code/mjpg-streamer-code-r182.zip
unzip mjpg-streamer-code-r182.zip
cd mjpg-streamer-code-r182
cp -R mjpg-streamer/www/* /opt/wwwroot/webcam/
启动mjpg_streamer:
export LD_LIBRARY_PATH=/opt/lib/mjpg-streamer:/opt/lib:/lib
mjpg_streamer -i "input_uvc.so -f 30 -yuv -r 640x480 -d /dev/video0" -o "output_http.so -p 8998 -w /opt/wwwroot/webcam"
注意,我这个摄像头比较垃圾,不支持jpeg格式,如果你的摄像头支持jpeg格式,大可把参数“-yuv”删掉以提升图像质量。“-d”参数要根据你的实际情况来修改,参数内容是摄像头路径,我这里是“/dev/video0”,你的可能是“/dev/video1”等等。。
最后在路由器内网里访问网址看看效果吧(地址为你路由器地址,加上端口号8998):
http://192.168.3.1:8998/
测试直播效果:
可能会有人问我为什么不顺便搞个openwrt的教程?
博主我本来还想再搞个openwrt教程的,但是openwrt太老了,gcc都还是5.4.0版本,人家Entware是激进派,gcc直接干上了7.4.0版本,所以就算要出个openwrt版的教程,那也是先安装完一大堆kmod,然后教大家装好Entware环境,后面的路子就差不多一样了!所以懒癌犯了就没再想去折腾openwrt了,如果评论区留言超过5个要求搞openwrt教程的话,我会考虑考虑。
再奉上几个对我帮助十分巨大的文章链接,如果你还有什么疑问,建议先浏览他们的文章,思考之后还不能解决的话再留言问我,能百度的也最好不要问我,衷心感谢他们:
https://blog.csdn.net/huofeng_2008/article/details/49762323
http://blog.chinaunix.net/uid-27194309-id-3869697.html
https://blog.csdn.net/u014683513/article/details/39119345