在小公司或者在家庭里面,直接使用 AP 就行,直接在里面预先设置好密码,如果外部设备连接到 AP 上,密码对了就会连接上。
修改Makefile,因为需要交叉编译,所以需要修改里面的
CC= arm-linux-gcc
发现需要 openssl 库的支持,所以还需要找到这个依赖库进行编译,然后将编译出来的 头文件、库文件 全部拷贝到交叉编译工具链中。
拿到一个新的库,先ls看看有没有说明readme文件。
shared 是指定生成动态库
–prefix=DIR是指定之后 make install 的时候安装到哪个目录下面
// 编译之前的配置,就是为了自动生成一个 Makefile
// no-asm 是不使用里面的汇编代码进行优化,这里使用汇编代码就会出错提示给 X86 使用的
./config shared no-asm --prefix=$PWD/tmp
// 因为不能直接指定交叉编译器,所以上面的指令生成的 Makefile中,需要手动修改里面的编译指令
CC= arm-linux-gcc
AR= arm-linux-ar $(ARFLAGS) r
RANLIB= arm-linux-ranlib
NM= arm-linux-nm
MAKEDEPPROG= arm-linux-gcc
wpa的操作,好像都是修改配置文件,然后使用 supplicant 命令来操作
上面的文件 .conf 就是下面这个样子
然后查看状态
不同的加密方式,需要拷贝不同的配置文件出来,然后修改里面的 热点名称和密码。
如果不借助 iw,wpa 这些应用工具,我们连接配置好WIFI网卡之后,也只能查询或者设置一下 IP地址,但是却还不能上网,因为我们的 WIFI还没有连接到热点或者网络上面。所以借助 iw 和 wpa 这些工具可以很方便的连接到外部网络上。
DNS的配置
之前通过 iw,wpa 工具连接到热点之后,我们都是通过手工的方式来设置 IP,我们能不能设置自动获得 IP呢?
可以的,就是通过移植一个 dhcp 库来实现自动获得 IP。
一连接上 WIFI AP ,就自动指定 dhclient
一连接上 WIFI AP ,就自动指定 dhclient
我们手机一般工作于 STA 模式,能不能将开发板作为 AP模式,让手机连接开发板的热点呢?
需要移植 hostapd 到开发板上,建立无线热点
然后我们怎么编译它呢?官方文档中有说明
如果没有configure 文件,则可以直接修改 Makefile,修改里面的交叉编译器。
AP模式的自启动
也是采用 mdev.conf 中,修改为别的自启动脚本。
下面箭头指着的两个是配置好的文件系统,打包了,到时候直接放到一个 nfs中,替换原来的文件系统就可以挂载这些文件系统了。
功能如下:
输入 wpa_cli ,直接回车的话,进入的是一个交互模式
然后在里面可以运行各种命令
核心:wpa_cli 通过 wpa_request函数 向 wpa_supplicant 发出命令,并得到结果
函数(指令),可以看源码的 readme ,里面有提到
扫描出来的 wifi 热点的信息,在 while 循环里面定时打印出来,可以实现定时刷新 wifi热点信息的功能。
sprintf
配凑字符串
注意点:
如果我们成功连接了某个wifi之后,这个 wifi号和密码就会保存到一个配置文件中。
这就完成了 模拟手机wifi的功能
说明:
不知道这些含义是什么,可以全部 ppp 都选上。
之后我们得到的是 ttyUSB是吧,所以还需要把USB串口给配置了。
把下面的文章看完之后,对3G USB Modem就会了如指掌。
参考文章: 嵌入式Linux下3G USB Modem的使用 - 空之轨迹~约修亚 - 博客频道 - CSDN.NET.htm http://blog.csdn.net/ling1874/article/details/8148822 http://wenku.baidu.com/link?url=HLRk3U9Jbr2Zx35e5knamYeUKYs14bhV3F9-hzC6rWMwdxCu2gTtAR89VBAdpoAF4UC9LmxCPxGLbjAu_XoSXuy065ZbbvfwtWm9vLy5UWe
配置文件最全: HI3515海思开发板移植3G模块笔记 - 倔强的晓奇 - 博客频道 - CSDN.NET.htm http://blog.csdn.net/alangdangjia/article/details/9413009
好文章:ppp及usb_modeswitch等工具移植说明_百度文库.htm http://wenku.baidu.com/link?url=Y7gsW5izmXwzur3VS3hGYWV_k_glZwzmu7Prdh_F69LuFxcOGT1LwhtsmXA3TVhR6F0l8_ozspcQvO08nlHex2yss0EW7wWIzysw9cZn-wu
使用 lsusb 可以查看到 ID值为:12d11505
找到之后,就把里面对应的配置信息拷贝出来,
把配置文件另存为 eq10b.cfg
切换完成之后,其 ID就会发生变化
华为的这个,有4个 USB串口
对于移动这款比较奇怪的上网卡,就不能实现自动的模式切换。
参考ubuntu上对3G上网卡的自动识别过程来学习
在pc上编译usb_modeswitch 非常简单,直接 ./configure, 然后make就行
在pc上编译 ppp
PC使用的是 udev
它并不使用配置文件,而是使用 -f 配置信息
然后我们可以仿照lsusb的源码来写这个功能
前面实现了热插拔自动切换3G上网卡的模式到modem,然后出现了 ttyUSB*
下面还要确定是哪个 ttyUSB* 作为拨号端口
四种接线方法
第一种接线方式
C:\BaiduNetdiskDownload\01_无线监控文档源码\01_课堂笔记及代码\01_课堂笔记及代码\第2课第1.1_18节_讲解mjpg-streamer\doc\视频监控的实现.pdf
这个pdf文档中介绍的移植方法,是这种方式。
USB_Hub 的作用是可以将2440上的一个USB接口扩展为多个USB接口来使用。
这里开发板竟然是工作在 AP模式???这怎么实现远程传输呢?
mjpg-streamer分析源码可以知道其是通过 ioctl 的方式来获取摄像头数据的,而我们写的 CMOS摄像头的驱动中,只支持 read,write 两种方式的读取摄像头数据。
所以想实现这种方式,有两种方法:
还有很多 .so 文件
然后插入无线WIFI网卡
成功识别到无线网卡
然后插入USB摄像头
插入USB摄像头,也自动识别到 UVC摄像头,并且出现了设备节点
执行上面的指令,mjpg-streamer就运行起来了
手机连接开发板的AP热点
因为开发板的无线WIFI是工作在AP模式的,所以我们手机(STA模式)需要连接到这个AP热点才能实现连接。
mjpg-streamer是怎么实现采集数据和传输数据两个功能的,将在后面分析这个应用程序的源代码的时候深入了解。
dlopen是打开一个动态链接库
这些输入输出动态链接库是实现了什么功能呢?里面有 .init .run .stop,通过这些函数来实现不同的功能。
output_hppt.so就是使用 socket 编程,来模拟 http协议。
getopt_long_only
函数来解析参数分析 getopt_long_only
的用法(用于解析命令行选项)
mjpg-streamer.c函数的主流程
input_init(&global.in.param)函数,初始化输入源接口
output_init(&global.out[i].param)函数,对于所有的输出接口都调用,初始化多有的输出接口
下面依次分析上面这4个函数
我们输入的命令行是 "input_uvc.so -f 10 -r 320*240"
则这里我们也可以仿照 mian 函数的参数解析,自己构造好 argc 和 argv[],来实现调用 getopt_long_only
来解析出参数。
分辨率 -r 320*240
帧率 -f 10
input_init 函数实现的功能
初始化一堆局部变量,初始化互斥锁
将传入的参数字符串,分割存进数组中argv[],方便后面解析选项参数
getopt_long_only解析参数,主要得到 分辨率和帧率
分配一个 vdIn 结构体,并初始化为0
打印出相关的调试信息,也就是上面的 使用的是哪个设备节点 、分辨率、帧率 等等
调用 init_videoIn(videoIn, dev, width, height, fps, format, 1) 函数
format=V4L2_PIX_FMT_MJPEG
init_videoIn 函数里面会:
动态调整摄像头的焦距之类的,这个项目没有使用到
这里面涉及到摄像头的操作,都是采用 V4L2的ioctl来实现的
input_run 函数实现的功能
给仓库buf 分配一段内存空间,分配1帧视频数据那么大
创建一个线程,线程函数是 cam_thread
当线程执行完后,会调用 cam_cleanup 来做些清理工作
进入死循环while( !pglobal->stop ),直到按 <CTRL>+C
时触发信号,信号函数设置stop=1
uvcGrab 函数获得一帧数据
MJPEG格式的话:则将一帧视频数据存放到 videoIn->tempbuffer 中
YUV格式的话:则将一帧数据存放到 videoIn->framebuffer 中
打印调试信息,一帧数据有多大
如果这一帧数据太小,则认为他是无效数据
拷贝 JPG 图像到 仓库中 (这段区间的内容是不允许被别的线程打断的)
如果摄像头输出的视频数据为YUV格式,则执行该分支
最终的MJPEG数据存放到 pglobal->buf 中
如果摄像头输出的数据为MJPEG格式,则直接将它拷贝到 pglobal->buf 中
pthread_cond_broadcast(&pglobal->db_update);
// 发出一个数据更新的信号,通知发送通道来取数据,也就是输入通道进程已经把数据传输到仓库buf中了,需要通知一下 输出通道来仓库中获取一下数据.
如果我们的帧率小于5,则要做一个小的延时操作
等待线程执行完,然后回收它的资源
将YUV转换为JPEG YUV->RGB->JPEG (RGB->JPEG 利用libjpeg)(YUV->RGB 利用公式转换一下) 先将 YUV格式的颜色空间转换为RGB格式的颜色空间,然后再将RGB颜色空间转换为JPEG格式
output_http.c
output_init 函数实现的功能
output_http.so -w www
output_http.c
output_run 函数实现的功能
打印出一个调试信息
创建一个线程 server_thread
取出globals结构体变量
pthread_cleanup_push 当线程结束的时候,会调用 server_cleanup 来做些清理工作
socket(PF_INET, SOCK_STREAM, 0) 打开 socket,充当服务器的角色,相当于open函数
设置套接字 etsockopt(pcontext->sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
bind 绑定本地的端口和IP
listen 启动监测数据,最多可以同时连接10个客服端
给每一个连接客户端创建一个 child
分配一个cfd结构体
判断是否分配成功
accept 等待客服端的链接,如果有链接,则建立链接 这里会阻塞住
pthread_create 创建一个线程 client_thread
第一个参数:线程标识符的指针 第二个参数:设置线程的属性 第三个参数:线程函数的起始地址 第四个参数:传给线程函数的参数
client_thread
如果我们传人的参数不为空,则将参数的内容拷贝到 lcfd 中(参数为 pcfd ,不为空)
init_request(&req);// http协议,需要客服端给服务器发送一个请求,而request就是这个请求
/* _readline:从客服端中读取一行的数据,以换行符结束 */
/* buffer中存有"abcd\n" */
/*
如果需要我们自己来写 mjpg-streamer 的客户端程序,则:
客服此时必须发送一个请求字符串,以换行符作为结束!
问:可以发送哪些字符串?
答:有
"GET /?action=snapshot\n" 快照类型
"GET /?action=stream\n" 视频流类型 让服务器发送视频流
"GET /?action=command\n" 命令类型请求
*/
解析buf中的字符串,看是哪一种类型的请求
将请求后面的参数保存到 req.parameter
do while
如果支持密码功能,则要检查用户名和密码是否匹配
根据请求的类型,采取相应的行动
send_snapshot
pthread_cond_wait 等待输入通道发送数据更新请求,这里就会阻塞等待
这个有意思了,之前输入通道的线程中互斥锁,然后取到数据到Buf中了才通知数据更新
得到一帧数据的大小
根据一帧数据的大小,分配一个 frame 缓冲区
从仓库(pglobal->buf)中取出数据放到这个缓冲区中
让buffer = “字符串”
将buffer中的字符串发送给客服端, socket模仿http请求,所以客户端请求数据之后,服务器要回复一个应答,这里就是回复应答的功能
将一帧图片给发送出去,真正的发送数据出去
释放缓冲区
send_stream(lcfd.fd)
让buffer = “字符串”
将 buffer 中的字符串发送出去(报文), socket模仿http请求, 回复一个应答
while ( !pglobal->stop ) 因为是视频流,所以要一直发送,就有一个 while循环
contl+C的时候,才会跳出这个 while 循环
–> pthread_cond_wait 等待输入通道发出数据更新的信号
–> 得到一帧图片的大小
–> 检查我们之前分配的缓存是否够大,如果不够,则重新分配
–> 从仓库中取出一帧数据
–> 让 buffer = ““报文,告诉客服端即将发送的图片的大小
–> write 将一帧图片发送出去
–> 让 buffer = “boundarydonotcross”
–> write buffer 发送给客户端,让客户端知道一帧数据接收完了
command
等待线程结束,以便回收它的资源