天天看點

linux gspca usb攝像頭驅動添加對新型号的詳細移植步驟

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所支援的,不妨都來一試,相信你的攝像頭也不會讓你失望。

繼續閱讀