⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videobook.tmpl

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 TMPL
📖 第 1 页 / 共 5 页
字号:
                        hardware_set_volume(current_volume);                        return 0;                }  </programlisting>  <para>        In our case there is very little that the user can set. The volume is        basically the limit. Note that we could pretend to have a mute feature        by rewriting this to   </para>  <programlisting>                case VIDIOCSAUDIO:                {                        struct video_audio v;                        if(copy_from_user(&amp;v, arg, sizeof(v)))                                return -EFAULT;                        if(v.audio)                                return -EINVAL;                        current_volume = v/16384;                        if(v.flags&amp;VIDEO_AUDIO_MUTE)                                hardware_set_volume(0);                        else                                hardware_set_volume(current_volume);                        current_muted = v.flags &amp;                                               VIDEO_AUDIO_MUTE;                        return 0;                }  </programlisting>  <para>        This with the corresponding changes to the VIDIOCGAUDIO code to report the        state of the mute flag we save and to report the card has a mute function,        will allow applications to use a mute facility with this card. It is        questionable whether this is a good idea however. User applications can already        fake this themselves and kernel space is precious.  </para>  <para>        We now have a working radio ioctl handler. So we just wrap up the function  </para>  <programlisting>        }        return -ENOIOCTLCMD;}  </programlisting>  <para>        and pass the Video4Linux layer back an error so that it knows we did not        understand the request we got passed.  </para>  </sect1>  <sect1 id="modradio">  <title>Module Wrapper</title>  <para>        Finally we add in the usual module wrapping and the driver is done.  </para>  <programlisting>#ifndef MODULEstatic int io = 0x300;#elsestatic int io = -1;MODULE_AUTHOR("Alan Cox");MODULE_DESCRIPTION("A driver for an imaginary radio card.");MODULE_PARM(io, "i");MODULE_PARM_DESC(io, "I/O address of the card.");EXPORT_NO_SYMBOLS;int init_module(void){        if(io==-1)        {                printk(KERN_ERR          "You must set an I/O address with io=0x???\n");                return -EINVAL;        }        return myradio_init(NULL);}void cleanup_module(void){        video_unregister_device(&amp;my_radio);        release_region(io, MY_IO_SIZE);}#endif  </programlisting>  <para>        In this example we set the IO base by default if the driver is compiled into        the kernel where you cannot pass a parameter. For the module we require the        user sets the parameter. We set io to a nonsense port (-1) so that we can        tell if the user supplied an io parameter or not.  </para>  <para>        We use MODULE_ defines to give an author for the card driver and a        description. We also use them to declare that io is an integer and it is the        address of the card.  </para>  <para>        The clean-up routine unregisters the video_device we registered, and frees        up the I/O space. Note that the unregister takes the actual video_device        structure as its argument. Unlike the file operations structure which can be        shared by all instances of a device a video_device structure as an actual        instance of the device. If you are registering multiple radio devices you        need to fill in one structure per device (most likely by setting up a        template and copying it to each of the actual device structures).  </para>  </sect1>  </chapter>  <chapter>        <title>Video Capture Devices</title>  <sect1 id="introvid">  <title>Video Capture Device Types</title>  <para>        The video capture devices share the same interfaces as radio devices. In        order to explain the video capture interface I will use the example of a        camera that has no tuners or audio input. This keeps the example relatively        clean. To get both combine the two driver examples.  </para>  <para>        Video capture devices divide into four categories. A little technology        backgrounder. Full motion video even at television resolution (which is        actually fairly low) is pretty resource-intensive. You are continually        passing megabytes of data every second from the capture card to the display.         several alternative approaches have emerged because copying this through the         processor and the user program is a particularly bad idea .  </para>  <para>        The first is to add the television image onto the video output directly.        This is also how some 3D cards work. These basic cards can generally drop the        video into any chosen rectangle of the display. Cards like this, which        include most mpeg1 cards that used the feature connector,  aren't very        friendly in a windowing environment. They don't understand windows or        clipping. The video window is always on the top of the display.  </para>  <para>        Chroma keying is a technique used by cards to get around this. It is an old        television mixing trick where you mark all the areas you wish to replace        with a single clear colour that isn't used in the image - TV people use an        incredibly bright blue while computing people often use a particularly        virulent purple. Bright blue occurs on the desktop. Anyone with virulent        purple windows has another problem besides their TV overlay.  </para>  <para>        The third approach is to copy the data from the capture card to the video        card, but to do it directly across the PCI bus. This relieves the processor        from doing the work but does require some smartness on the part of the video        capture chip, as well as a suitable video card. Programming this kind of        card and more so debugging it can be extremely tricky. There are some quite        complicated interactions with the display and you may also have to cope with        various chipset bugs that show up when PCI cards start talking to each        other.   </para>  <para>        To keep our example fairly simple we will assume a card that supports        overlaying a flat rectangular image onto the frame buffer output, and which        can also capture stuff into processor memory.  </para>  </sect1>  <sect1 id="regvid">  <title>Registering Video Capture Devices</title>  <para>        This time we need to add more functions for our camera device.  </para>  <programlisting>static struct video_device my_camera{        "My Camera",        VID_TYPE_OVERLAY|VID_TYPE_SCALES|\        VID_TYPE_CAPTURE|VID_TYPE_CHROMAKEY,        VID_HARDWARE_MYCAMERA,        camera_open.        camera_close,        camera_read,      /* no read */        NULL,             /* no write */        camera_poll,      /* no poll */        camera_ioctl,        NULL,             /* no special init function */        NULL              /* no private data */};  </programlisting>  <para>        We need a read() function which is used for capturing data from        the card, and we need a poll function so that a driver can wait for the next        frame to be captured.  </para>  <para>        We use the extra video capability flags that did not apply to the        radio interface. The video related flags are  </para>   <table frame=all><title>Capture Capabilities</title>   <tgroup cols=2 align=left>   <tbody>   <row><entry>VID_TYPE_CAPTURE</><entry>We support image capture</></row><row><entry>VID_TYPE_TELETEXT</><entry>A teletext capture device (vbi{n])</></row><row><entry>VID_TYPE_OVERLAY</><entry>The image can be directly overlaid onto the                                frame buffer</></row><row><entry>VID_TYPE_CHROMAKEY</><entry>Chromakey can be used to select which parts                                of the image to display</></row><row><entry>VID_TYPE_CLIPPING</><entry>It is possible to give the board a list of                                rectangles to draw around. </></row><row><entry>VID_TYPE_FRAMERAM</><entry>The video capture goes into the video memory                                and actually changes it. Applications need                                to know this so they can clean up after the                                card</></row><row><entry>VID_TYPE_SCALES</><entry>The image can be scaled to various sizes,                                rather than being a single fixed size.</></row><row><entry>VID_TYPE_MONOCHROME</><entry>The capture will be monochrome. This isn't a                                 complete answer to the question since a mono                                camera on a colour capture card will still                                produce mono output.</></row><row><entry>VID_TYPE_SUBCAPTURE</><entry>The card allows only part of its field of                                view to be captured. This enables                                applications to avoid copying all of a large                                image into memory when only some section is                                relevant.</>    </row>    </tbody>    </tgroup>    </table>  <para>        We set VID_TYPE_CAPTURE so that we are seen as a capture card,        VID_TYPE_CHROMAKEY so the application knows it is time to draw in virulent        purple, and VID_TYPE_SCALES because we can be resized.  </para>  <para>        Our setup is fairly similar. This time we also want an interrupt line        for the 'frame captured' signal. Not all cards have this so some of them        cannot handle poll().  </para>  <programlisting>static int io = 0x320;static int irq = 11;int __init mycamera_init(struct video_init *v){        if(check_region(io, MY_IO_SIZE))        {                printk(KERN_ERR                       "mycamera: port 0x%03X is in use.\n", io);                return -EBUSY;        }        if(video_device_register(&amp;my_camera,             VFL_TYPE_GRABBER)==-1)                return -EINVAL;        request_region(io, MY_IO_SIZE, "mycamera");        return 0;}  </programlisting>  <para>        This is little changed from the needs of the radio card. We specify        VFL_TYPE_GRABBER this time as we want to be allocated a /dev/video name.  </para>  </sect1>  <sect1 id="opvid">  <title>Opening And Closing The Capture Device</title>  <programlisting>static int users = 0;static int camera_open(stuct video_device *dev, int flags){        if(users)                return -EBUSY;        if(request_irq(irq, camera_irq, 0, "camera", dev)&lt;0)                return -EBUSY;        users++;        MOD_INC_USE_COUNT;        return 0;}static int camera_close(struct video_device *dev){        users--;        free_irq(irq, dev);        MOD_DEC_USE_COUNT;}  </programlisting>  <para>        The open and close routines are also quite similar. The only real change is        that we now request an interrupt for the camera device interrupt line. If we        cannot get the interrupt we report EBUSY to the application and give up.  </para>  </sect1>  <sect1 id="irqvid">  <title>Interrupt Handling</title>  <para>        Our example handler is for an ISA bus device. If it was PCI you would be        able to share the interrupt and would have set SA_SHIRQ to indicate a         shared IRQ. We pass the device pointer as the interrupt routine argument. We        don't need to since we only support one card but doing this will make it        easier to upgrade the driver for multiple devices in the future.  </para>  <para>        Our interrupt routine needs to do little if we assume the card can simply        queue one frame to be read after it captures it.   </para>  <programlisting>static struct wait_queue *capture_wait;static int capture_ready = 0;static void camera_irq(int irq, void *dev_id,                           struct pt_regs *regs){        capture_ready=1;        wake_up_interruptible(&amp;capture_wait);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -