linux usb摄像头 源码,Linux USB摄像头驱动实现源码分析
Spac5xx的實(shí)現(xiàn)是按照標(biāo)準(zhǔn)的USB VIDEO設(shè)備的驅(qū)動(dòng)框架編寫(其具體的驅(qū)動(dòng)框架可參照/usr/src/linux/drivers/usb/usbvideo.c文件),整個(gè)源程序由四個(gè)主體部分組成:
設(shè)備模塊的初始化模塊和卸載模塊,上層軟件接口模塊,數(shù)據(jù)傳輸模塊。
具體的模塊分析如下:
一、初始化設(shè)備模塊
該驅(qū)動(dòng)采用了顯式的模塊初始化和消除函數(shù),即調(diào)用module_init來(lái)初始化一個(gè)模塊,并在卸載時(shí)調(diào)用moduel-exit函數(shù)
其具體實(shí)現(xiàn)如下:
1、模塊初始化:
module_init (usb_spca5xx_init);
static int __init usb_spca5xx_init (void)
{
#ifdef CONFIG_PROC_FS
proc_spca50x_create ();//建立PROC設(shè)備文件
#endif /* CONFIG_PROC_FS */
if (usb_register (&spca5xx_driver) < 0) //注冊(cè)USB設(shè)備驅(qū)動(dòng)
return -1;
info ("spca5xx driver %s registered", version);
return 0;
}
2、模塊卸載:
module_exit (usb_spca5xx_exit);
static void __exit usb_spca5xx_exit (void)
{
usb_deregister (&spca5xx_driver); //注銷USB設(shè)備驅(qū)動(dòng)
info ("driver spca5xx deregistered");
#ifdef CONFIG_PROC_FS
proc_spca50x_destroy ();//撤消PROC設(shè)備文件
#endif /* CONFIG_PROC_FS */
}
關(guān)鍵數(shù)據(jù)結(jié)構(gòu)USB驅(qū)動(dòng)結(jié)構(gòu),即插即用功能的實(shí)現(xiàn)
static struct usb_driver spca5xx_driver = {
"spca5xx",
spca5xx_probe, //注冊(cè)設(shè)備自我偵測(cè)功能
spca5xx_disconnect,//注冊(cè)設(shè)備自我斷開(kāi)功能
{NULL,NULL}
};
用兩個(gè)函數(shù)調(diào)用spca5xx_probe 和spca5xx_disconnect來(lái)支持USB設(shè)備的即插即用功能:
a --?spca5xx_probe具體實(shí)現(xiàn)如下:
static void * spca5xx_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface; //USB設(shè)備接口描述符
struct usb_spca50x *spca50x; //物理設(shè)備數(shù)據(jù)結(jié)構(gòu)
int err_probe;
int i;
if (dev->descriptor.bNumConfigurations != 1) //探測(cè)設(shè)備是不是可配置
goto nodevice;
if (ifnum > 0)
goto nodevice;
interface = &dev->actconfig->interface[ifnum].altsetting[0];
MOD_INC_USE_COUNT;
interface = &intf->altsetting[0].desc;
if (interface->bInterfaceNumber > 0)
goto nodevice;
if ((spca50x = kmalloc (sizeof (struct usb_spca50x), GFP_KERNEL)) == NULL) //分配物理地址空間
{
err ("couldn't kmalloc spca50x struct");
goto error;
}
memset (spca50x, 0, sizeof (struct usb_spca50x));
spca50x->dev = dev;
spca50x->iface = interface->bInterfaceNumber;
if ((err_probe = spcaDetectCamera (spca50x)) < 0) //具體物理設(shè)備查找,匹配廠商號(hào),設(shè)備號(hào)(在子程序中)
{
err (" Devices not found !! ");
goto error;
}
PDEBUG (0, "Camera type %s ", Plist[spca50x->cameratype].name)
for (i = 0; i < SPCA50X_NUMFRAMES; i++)
init_waitqueue_head (&spca50x->frame[i].wq); //初始化幀等待隊(duì)列
init_waitqueue_head (&spca50x->wq); //初始化驅(qū)動(dòng)等待隊(duì)列
if (!spca50x_configure (spca50x)) //物理設(shè)備配置(主要完成傳感器偵測(cè)和圖形參數(shù)配置),主要思想是給控制寄存器寫值,讀回其返回值,以此判斷具體的傳感器型號(hào)
{
spca50x->user = 0;
init_MUTEX (&spca50x->lock); //信號(hào)量初始化
init_MUTEX (&spca50x->buf_lock);
spca50x->v4l_lock = SPIN_LOCK_UNLOCKED;
spca50x->buf_state = BUF_NOT_ALLOCATED;
}
else
{
err?("Failed?to?configure?camera");
goto?error;
}
/*?Init?video?stuff?*/
spca50x->vdev?=?video_device_alloc?();???????????//設(shè)備控制塊內(nèi)存分配
if?(!spca50x->vdev)
goto?error;
memcpy?(spca50x->vdev,?&spca50x_template,?sizeof?(spca50x_template));
//系統(tǒng)調(diào)用的掛接,在此將驅(qū)動(dòng)實(shí)現(xiàn)的系統(tǒng)調(diào)用,掛到內(nèi)核中
video_set_drvdata?(spca50x->vdev,?spca50x);
if?(video_register_device?(spca50x->vdev,?VFL_TYPE_GRABBER,?video_nr)?
{
//video設(shè)備注冊(cè)
err?("video_register_device?failed");
goto?error;
}
spca50x->present?=?1;
if?(spca50x->force_rgb)
info?("data?format?set?to?RGB");
spca50x->task.sync?=?0;
spca50x->task.routine?=?auto_bh;
spca50x->task.data?=?spca50x;
spca50x->bh_requested?=?0;
MOD_DEC_USE_COUNT;?//增加模塊使用數(shù)
return?spca50x;?//返回?cái)?shù)劇結(jié)構(gòu)
error://錯(cuò)誤處理
if?(spca50x->vdev)
{
if?(spca50x->vdev->minor?==?-1)
video_device_release?(spca50x->vdev);
else
video_unregister_device?(spca50x->vdev);
spca50x->vdev?=?NULL;
}
if?(spca50x)
{
kfree?(spca50x);
spca50x?=?NULL;
}
MOD_DEC_USE_COUNT;
return?NULL;
nodevice:
return?NULL;
}
b -- Spca5xx_disconnect 的具體實(shí)現(xiàn)如下:
static void spca5xx_disconnect (struct usb_device *dev, void *ptr)
{
struct usb_spca50x *spca50x = (struct usb_spca50x *) ptr;
int n;
MOD_INC_USE_COUNT; //增加模塊使用數(shù)
if (!spca50x)
return;
down (&spca50x->lock); //減少信號(hào)量
spca50x->present = 0; //驅(qū)動(dòng)卸載置0
for (n = 0; n < SPCA50X_NUMFRAMES; n++) //標(biāo)示所有幀ABORTING狀態(tài)
{
spca50x->frame[n].grabstate = FRAME_ABORTING;
spca50x->curframe = -1;
}
for (n = 0; n < SPCA50X_NUMFRAMES; n++) //喚醒所有等待進(jìn)程
{
if (waitqueue_active (&spca50x->frame[n].wq))
wake_up_interruptible (&spca50x->frame[n].wq);
if (waitqueue_active (&spca50x->wq))
wake_up_interruptible (&spca50x->wq);
}
spca5xx_kill_isoc(spca50x); //子函數(shù)終止URB包的傳輸
PDEBUG (3,"Disconnect Kill isoc done");
up (&spca50x->lock); //增加信號(hào)量
while(spca50x->user) /如果還有進(jìn)程在使用,進(jìn)程切換
schedule();
down (&spca50x->lock);
if (spca50x->vdev)
{
video_unregister_device (spca50x->vdev); //注銷video設(shè)備
usb_driver_release_interface (&spca5xx_driver,&spca50x->dev->actconfig->interface[spca50x->iface]); //端口釋放
spca50x->dev = NULL;
}
up (&spca50x->lock);
#ifdef CONFIG_PROC_FS
destroy_proc_spca50x_cam (spca50x); //注銷PROC文件
#endif /* CONFIG_PROC_FS */
if (spca50x && !spca50x->user) //釋放內(nèi)存空間
{
spca5xx_dealloc (spca50x);
kfree (spca50x);
spca50x = NULL;
}
MOD_DEC_USE_COUNT; //減少模塊記數(shù)
PDEBUG (3, "Disconnect complete");
}
二、上層軟件接口模塊:
該模塊通過(guò)file_operations數(shù)據(jù)結(jié)構(gòu),依據(jù)V4L協(xié)議規(guī)范,實(shí)現(xiàn)設(shè)備的關(guān)鍵系統(tǒng)調(diào)用,實(shí)現(xiàn)設(shè)備文件化的UNIX系統(tǒng)設(shè)計(jì)特點(diǎn)。作為攝相頭驅(qū)動(dòng),其功能在于數(shù)據(jù)采集,而沒(méi)有向攝相頭輸出的功能,因此在源碼中沒(méi)有實(shí)現(xiàn)write系統(tǒng)調(diào)用。
其關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)如下:
static?struct?video_device?spca50x_template?=?{
.owner?=?THIS_MODULE,
.name?=?"SPCA5XX?USB?Camera",
.type?=?VID_TYPE_CAPTURE,
.hardware?=?VID_HARDWARE_SPCA5XX,
.fops?=?&spca5xx_fops,
};
static?struct?file_operations?spca5xx_fops?=?{
.owner?=?THIS_MODULE,
.open?=?spca5xx_open,?//open功能
.release?=?spca5xx_close,//close功能
.read?=?spca5xx_read,?//read功能
.mmap?=?spca5xx_mmap,?//內(nèi)存映射功能
.ioctl?=?spca5xx_ioctl,?//文件信息獲取
.llseek?=?no_llseek,//文件定位功能未實(shí)現(xiàn)
};
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的linux usb摄像头 源码,Linux USB摄像头驱动实现源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: kali linux升级火狐,Kali安
- 下一篇: linux vi 是目录,linux基本