http://blog.chinaunix.net/u/26710/showart_387765.html
0 前言
在Linux下驅動USB攝像頭一直不是容易的事情,盡管其核心中就內建了對0V511系列攝像頭的支援,開源驅動spca5xx/gspca也提供了對大部分主流攝像頭的支援,但還是無法涵蓋所有品牌的各種型号的攝像頭,尤其是對于國内的中低端使用者,很難找到直接可用的Linux下的驅動。
本文簡單介紹了gspca驅動程式、spcagui和spcaview等測試程式的安裝過程,并以在gspca中添加對Logitech QuickCam Easy/Cool(快看靈訊版)攝像頭的支援為例,給出了在gspca驅動程式中添加新的攝像頭支援的一般方法。
1 安裝gspca驅動程式
gspca用于2.6.17以上的核心版本,以前的版本使用spca5xx驅動程式。gspca可直接支援的攝像頭清單可見http://mxhaard.free.fr/spca5xx.html。
(1)安裝核心頭檔案
#uname -r
2.6.20-1.2962.fc6
#arch
i686
#wget http://fedora.fastbull.org/updates/testing/6/i386/kernel-
devel-2.6.20-1.2962.fc6.i686.rpm
#rpm -ivh kernel-devel-2.6.20-1.2962.fc6.i686.rpm
這樣,核心頭檔案被安裝到/usr/src/kernels/2.6.20-1.2962.fc6-i686目錄下。
(2)安裝gspca驅動:
#wget http://mxhaard.free.fr/spca50x/Download/gspcav1-
20070508.tar.gz
#tar xfv gspcav1-20070508.tar.gz
#cd gspcav1-20070508
#./gspca_build
gspca_build是一個自動編譯、安裝、加載驅動子產品的腳本。可以使用指令“depmod -ae”來檢查核心子產品的依賴關系是否沖突。
注意,安裝好驅動并加載gspca.ko子產品後,一般會有/dev/video和/dev/video0等裝置檔案的存在,否則可能是驅動程式對本機的攝像頭的支援有問題。另外,要正常使用攝像頭,核心中應有video for linux的支援(Fedora核心一般是預設支援)。
(3)安裝spcagui、spcaview等攝像頭測試程式
實際上,隻要正确安裝好驅動之後,就可以使用"應用程式->Internet->Kopete"或gnome-netmeeting等程式來測試攝像頭是否能正常工作了。當然也可以使用spcagui、spcaview等專門的攝像頭工具軟體。
要安裝spcagui或spcaview,必須先安裝SDL、SDL-devel、SDL_image和SDL_image-devel軟體包。然後直接make并make install即可。
2 gspca不能直接支援Logitech QuickCam Easy/Cool(快看靈訊版,046d:08af)
Logitech的攝像頭有個“特點”,一個英文名有好幾個中文名,例如快看靈訊版和快看酷訊版,包裝盒上都寫的是Logitech QuickCam Cool,由于在gspca的攝像頭支援清單中看到了Logitech QuickCam Cool,于是買了個靈訊版。
首先在Windows上試驗攝像頭效果,插入USB口,顯示裝置為Logitech QuickCam Easy/Cool,就感覺情況不妙,一看Vendor ID:Product ID是046d:08af,果然不在gspca的攝像頭支援清單内。不管怎麼樣,先到Fedora下試試再說。
#lsusb
Bus 002 Device 001: ID 0000:0000
Bus 002 Device 003: ID 046d:08af Logitech, Inc.
Bus 001 Device 001: ID 0000:0000
Bus 004 Device 001: ID 0000:0000
Bus 003 Device 001: ID 0000:0000
可見裝置ID的确是046d:08af。加載gspca驅動子產品後,運作spcagui或者spcaview,提示“No such file or directory.”
“ls /dev/video*”發現沒有任何相應的裝置檔案,于是手動建立:
#mknod /dev/video0 c 81 0
#ln -s /dev/video0 /dev/video
之後再運作spcagui或者spcaview,提示“Device not found.”
在Google上搜了兩個晚上,還是沒能找到解決問題的辦法。看來唯一能找到問題所在并加以解決的辦法就是從gspca驅動程式的源代碼入手了。
3 使gspca驅動程式支援Logitech QuickCam Easy/Cool
(1)gspca驅動程式結構簡析
gspca驅動程式的核心代碼是gspca_core.c,包括了裝置注冊、登出、各種操作方法集(定義了所支援的攝像頭裝置清單,裝置檢測和初始化,裝置打開、參數設定、關閉等各種操作函數)。
gspca.h是一個核心頭檔案,它的主要内容有:
a)定義所支援的Vendor ID号,例如:
#define VENDOR_LOGITECH 0x046d
b)為所支援的DSP橋接控制晶片型号進行編号,例如:
#define BRIDGE_ZC3XX 12
c)為所支援的CMOS/CCD圖像傳感器型号進行編号,例如:
#define SENSOR_HV7131B 2
#define SENSOR_HDCS2020 9
#define SENSOR_HV7131C 12
#define SENSOR_HV7131R 15
#define SENSOR_PAS202 19
#define SENSOR_TAS5130C_VF0250 22
另外,它還定義了圖像格式相關的常量和資料結構(如圖像分辨率,色彩空間,調色闆等),幀資料結構,攝像頭操作方法集等。
Vimicro,Sonix,PixArt,Sunplus等檔案夾中定義了各傳感器相關的頭檔案。
decoder檔案夾中包含了對各種圖像格式進行編解碼的源代碼。
結論:要驅動一個攝像頭,首先要知道它的DSP晶片和CMOS晶片型号。如果攝像頭的Vendor ID,DSP晶片,image sensor不在其中,則要定義DSP和sensor晶片的相應頭檔案,并在gspca.h中添加相應的裝置資訊,還要把攝像頭加入到gspca_core.c的攝像頭裝置清單中。
(2)與Logitech QuickCam Easy/Cool相近的攝像頭資訊清單
Camera Type
Product ID
Bridge DSP
Sensor
Comments(sensor in driver code)
QC IM
08a0
zc030x
HDCS2020
TAS5130C(08a0/a1/a3,08d9/da)
QC IM
08a6
zc030x
HV7131R
HV7131C (08a6/ad, 08d7)
NoteBook Deluxe
08a9
zc0302
HV7131B
HDCS2020 (08a2/a9/ae, 08d8)
QC Image
08a7
zc030x
PAS202
QC for Notebook
08ae
zc030x
PAS202
HDCS2020
QC Cool
08ac
zc030x
PAS202
HV7131B
Communicate STX
08ad
zc0302
TAS5130C
HV7131C
Communicate STX
08d7
vc0302/zc0302
TAS5130C
HV7131C
QC IM/Connect
08d9
zc030x
TAS5130C
QC Messenger
08da
zc030x
TAS5130C
NoteBook Deluxe
08d8
vc0302/zc0302
TAS5130C
QC Easy/Cool
08af
?(zc030x)
?
(HV7131C/HV7131B/TAS5130C/HDCS2020)
上面是Logitech攝像頭産品中與Logitech QuickCam Easy/Cool相近的産品(從Product ID,攝像頭英文名,産品價格等判斷),摘自http://mxhaard.free.fr/spca5xx.html,其中最後一列的注釋是gspca_core.c源檔案中給相應型号攝像頭定義的CMOS晶片型号,與網頁上的清單并不完全一緻,我們以驅動程式中定義的為準。
列出上面的表,主要是為了要推斷出Logitech QuickCam Easy/Cool的DSP晶片型号和CMOS傳感器型号。從上表可以發現,所有的攝像頭都使用了zc030x(包括zc0302)作為DSP控制晶片,是以可以斷定,Easy/Cool也使用了這一系列的DSP晶片,在驅動程式中用BRIDGE_ZC3XX表示。而CMOS晶片也無非是HV7131C/HV7131B/TAS5130C/HDCS2020中的一種,我們可以逐一試驗。
(3)在gspca_core.c中添加Logitech QuickCam Easy/Cool相關資訊
由于Logitech QuickCam Easy/Cool的Vendor、DSP型号、CMOS傳感器型号在gspca.h中均有定義,也有相關的晶片頭檔案,是以,隻需改動gspca_core.c,把Easy/Cool攝像頭的資訊加入到其中即可。
以下藍色部分是添加的相關内容。
在gspca_core.c中有一個Camera型号清單,如下: enum {
UnknownCamera = 0, // 0
IntelPCCameraPro,
IntelCreateAndShare,
......
PhilipsDMVC1300K,
LogitechQC_EasyCool, // added by aaron
LastCamera
};
static struct cam_list clist[] = {
{UnknownCamera, "Unknown"},
{IntelPCCameraPro, "Intel PC Camera Pro"},
{IntelCreateAndShare, "Intel Create and Share"},
......
{PhilipsDMVC1300K,"Philips DMVC 1300K"},
{LogitechQC_EasyCool,"Logitech QuickCam Easy_Cool"}, //added by aaron
{-1, NULL}
};
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0733, 0x0430)},
{USB_DEVICE(0x0733, 0x0401)},
......
{USB_DEVICE(0x0471, 0x0322)},
{USB_DEVICE(0x046d, 0x08af)},
{USB_DEVICE(0x0000, 0x0000)},
{}
};
static int
gspca_attach_bridge(struct usb_spca50x *spca50x)
{
spca50x->epadr =1;
switch (spca50x->bridge) {
......
case BRIDGE_ZC3XX:
spca50x->cameratype = JPGH;
info("USB GSPCA camera found.(ZC3XX) ");
memcpy(&spca50x->funct, &fzc3xx, sizeof (struct cam_operation));
break;
...... //other DSP bridges
default:
return -ENODEV;
}
return 0;
}
檢測攝像頭型号: static int
spcaDetectCamera(struct usb_spca50x *spca50x)
{
struct usb_device *dev = spca50x->dev;
__u8 fw = 0;
__u16 vendor;
__u16 product;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
vendor = le16_to_cpu(dev->descriptor.idVendor);
product = le16_to_cpu(dev->descriptor.idProduct);
#else
vendor = dev->descriptor.idVendor;
product = dev->descriptor.idProduct;
#endif
switch (vendor) {
case 0x046d:
switch (product) {
case 0x08af: //added by aaron
spca50x->desc = LogitechQC_EasyCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131B;
break;
......
case 0x08a0:
spca50x->desc = QCim;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a1:
spca50x->desc = QCimA1;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a2: // zc302 chips
spca50x->desc = LabtecPro;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08a3:
spca50x->desc = QCchat;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a6:
spca50x->desc = LogitechQCim;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131C;
break;
case 0x08a7:
spca50x->desc = LogitechQCImage;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_PAS202;
break;
case 0x08d8:
case 0x08a9:
spca50x->desc = LogitechNotebookDeluxe;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08ae:
spca50x->desc = QuickCamNB;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08ac:
spca50x->desc = LogitechQCCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131B;
break;
......
default:
goto error;
};
break;
...... //other vendors
return gspca_attach_bridge(spca50x);
error:
return -ENODEV; //no camera match
}
static int
spca5xx_probe(struct usb_interface *intf, const struct usb_device_id *id){
......
if ((err_probe = spcaDetectCamera(spca50x)) < 0) {
err(" Devices not found !! ");
goto error;
}
......
}
到此,我們對gspca驅動程式的擴充就算完成了。在函數spcaDetectCamera()中的switch結構中,将我們的攝像頭放到第一個case,是為了在探測攝像頭時第一個就找到我們的攝像頭,提高檢測速度。
需要指出兩點,一是在函數spcaDetectCamera()中,我們假定Logitech QC Easy/Cool的CMOS傳感器型号為SENSOR_HV7131B,這需要在後續的實驗中進行驗證;二是spca5xx_probe()函數中,紅色代碼部分,實際上調用了spcaDetectCamera()函數來探測攝像頭,如果出錯則報錯" Devices not found !! "并退出,由于之前gspca中沒有Easy/Cool攝像頭的資訊,是以,之前即使自己建立了/dev/video0等裝置檔案,還是會報錯“找不到裝置”。
(4)解除安裝舊的gspca驅動子產品,安裝新的gspca驅動子產品 #rm -f /dev/video* //删除舊的自己建立的裝置節點
#modprobe -rv gspca
#make uninstall
#make clean
#./gspca_build
#ls /dev/video*
lrwxrwxrwx 1 root root 6 09-22 21:44 /dev/video->video0
crw------- 1 aaronwong root 81, 0 09-22 21:42 /dev/video0
可見,這次在加載gspca驅動子產品後,自動生成了裝置檔案/dev/video0和/dev/video。
(5)攝像頭試用效果 $spcagui
SpcaGui version: 0.3.5 date: 18 September 2005
video device /dev/video0
Camera found: Logitech QuickCam Easy_Cool
VIDIOCGPICT brightnes=32768 hue=0 color=0 contrast=32768 whiteness=0depth=24 palette=4
Bridge found: ZC301-2
Unable to find a StreamId !!
StreamId: 6 Unknow Camera
try palette 15 depth 12
Available palette 15
try palette 3 depth 16
Available palette 3
try palette 4 depth 24
Available palette 4
try palette 5 depth 32
Available palette 5
probe size in
Available Resolutions width 640 heigth 480
Available Resolutions width 384 heigth 288
Available Resolutions width 352 heigth 288
Available Resolutions width 320 heigth 240
Available Resolutions width 192 heigth 144
Available Resolutions width 176 heigth 144
grabbing method default MMAP asked
VIDIOCGMBUF size 2457616 frames 2 offets[0]=0 offsets[1]=1228808
......
截圖如下:
(6)修正CMOS晶片型号資訊 #modprobe -v gspca
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/v4l1-compat.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/v4l2-common.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/videodev.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/usb/media/gspca.ko
#dmesg | grep gspca
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: USB GSPCA camera found.(ZC3XX)
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: [spca5xx_probe:4109] Camera type JPEG
/home/aaronwong/webcam/driver/gspcav1-20070508/Vimicro/zc3xx.h: [zc3xx_config:515] Sensor ID:2
/home/aaronwong/webcam/driver/gspcav1-20070508/Vimicro/zc3xx.h: [zc3xx_config:597] Find Sensor HV7131R(c)
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: [spca5xx_getcapability:1218] maxw 640 maxh 480 minw 176 minh 144
usbcore: registered new interface driver gspca
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: gspca driver 01.00.18 registered
注意紅色标出的部分,即使在驅動程式中指定QuickCam Easy/Cool攝像頭的CMOS SENSOR類型為SENSOR_HV7131B(或者是SENSOR_HDCS2020等其他類型),在加載gspca.ko子產品時,找到的還是HV7131R(c),是以,QuickCam Easy/Cool攝像頭的CMOS SENSOR類型應該就是SENSOR_HV7131R或SENSOR_HV7131C。
在源程式gspca_core.c的spcaDetectCamera()函數的相應部分修改如下: case 0x08af: //added by aaron
spca50x->desc = LogitechQC_EasyCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131R;
//SENSOR_HV7131C;
break;
解除安裝gspca驅動子產品,再重新編譯安裝gspca驅動即可。
由此也可知,在gspca攝像頭驅動中最重要的是要正确識别DSP控制晶片的型号,而CMOS傳感器的型号并不是必須的。是以,隻要攝像頭使用了gspca所支援的DSP控制晶片,就可以很容易地按照上面的方法,添加gspca對新的攝像頭的支援。即使使用了别的DSP控制晶片,也可以利用gspca的程式架構,為新的DSP晶片添加頭檔案等資訊,來擴充gspca對更多系列的USB攝像頭的支援。
不管你的攝像頭是ANC奧尼,還是環宇飛揚,或是戀影雙雙,如果你發現它的DSP晶片是gspca所支援的,不妨都來一試,相信你的攝像頭也不會讓你失望。