PIXNET Logo登入

馴龍窩

跳到主文

贊助馴龍窩->
歡迎來到馴龍窩
這邊記錄馴龍窩生活上的點點滴滴,方便日後回憶
也希望能一同紀錄在生命中重要的人事物

部落格全站分類:生活綜合

  • 相簿
  • 部落格
  • 留言
  • 名片
  • 10月 22 週四 201515:59
  • V4L2 driver Step by Step(part2)


.步驟二:  註冊一個 /dev/video0,並用應用程式去讀取測試
  我們延續上一篇文章中的 v4l2step1.c將之更改為 v4l2step2.c,並對 Makefile作相對應的修改
  將MODULE_NAME  = v4l2step1 改為 MODULE_NAME  = v4l2step2,讓他可以順利 compile成功。
 
  在這邊因為會呼叫到V4L2的 api v4l2_device_register,video_register_device,所以必須要加上必要的 header檔案
  ---
    #include <linux/videodev2.h>
    #include <media/videobuf2-vmalloc.h>
    #include <media/v4l2-device.h>
    #include <media/v4l2-ioctl.h>
    #include <media/v4l2-ctrls.h>
    #include <media/v4l2-fh.h>
    #include <media/v4l2-event.h>
    #include <media/v4l2-common.h>
  ---
  註冊一個 /dev/video0我們需要呼叫 v4l2_device_register 與 video_set_drvdata。
 
  在v4l2_device_register部分,根據函式定義-int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
  需要兩個結構,分別為 struct device 與  struct v4l2_device。
  我宣告一個  ar struct來包含這兩個結構如下,
  ---
  struct ar {
      struct v4l2_device v4l2_dev;
      struct video_device vdev;
  };  
  ---
  並宣告一個靜態結構變數 static struct ar ardev;給 v4l2_device_register  使用。
  在 vivi_init函式中宣告兩個 結構指標變數分別指到  video_device 與 v4l2_device 結構
  並給予 v4l2_device結構中 name ,並呼叫函式 v4l2_device_register(NULL, v4l2_dev); 就可以註冊 V4L2 driver了。
 
  接下來要註冊 /dev/video0 device,設定 ar 中 video_device 結構裡的 name ,並將 video_device 結構中v4l2_dev 指到 v4l2_dev 位址
  設定 video_device 結構裡的 fops , ioctl_ops , flags 與 release
 
  其中的 fops必須指到一個 v4l2_file_operations 結構,當應用程式將 /dev/video open , release, ioctl 時會呼叫相對應的函式
  ---
 
  static const struct v4l2_file_operations ar_fops = {
    .owner        = THIS_MODULE,
    .open        = v4l2_fh_open,   // open /dev/video0 will enter here
     .release    = v4l2_fh_release,   // close fd will enter here    
     .unlocked_ioctl    = video_ioctl2,  // need for ioctl
  };
  ---
 
  而其中的 ioctl_ops 則會指到一個 v4l2_ioctl_ops 結構,必須將支援的 ioctl command 函式implement出來。
  舉例當 /dev/video0 被應用程式open後,並下達 VIDIOC_QUERYCAP ioctl指令時,就會呼叫 ar_querycap 函式。
  目前在 ar_querycap 函式我填一些 struct v4l2_capability  需要的東西回去給應用程式。
  ----
    static const struct v4l2_ioctl_ops ar_ioctl_ops = {
        .vidioc_querycap                = ar_querycap,  // ioctl VIDIOC_QUERYCAP will enter here
    };  
  ----
 
  填完 video_device 結構裡的 fops , ioctl_ops , flags 與 release後
  就可以呼叫  video_register_device(&ar->vdev, VFL_TYPE_GRABBER, -1) 跟作業系統註冊一個 /dev/video0了
 
  這邊為了驗證 應用程式與 driver 之間的互動,我寫個一個簡單的 應用程式來驗證,應用程式名稱為 vidtest.c
  完整 source code如下:
  --vidtest.c--
          #include <errno.h>
          #include <fcntl.h>
          #include <linux/videodev2.h>
          #include <stdint.h>
          #include <stdio.h>
          #include <string.h>
          #include <sys/ioctl.h>
          #include <sys/mman.h>
          #include <unistd.h>
          
          static int xioctl(int fd,int request, void *arg)
          {
            int r;
            do r=ioctl(fd,request,arg);
            while(-1 ==r && EINTR == errno);
                
              return r;
          }
          
          
          int print_caps(int fd)
          {
              struct v4l2_capability caps={};
              
              perror("print_caps enter");
              
              if(-1 == xioctl(fd,VIDIOC_QUERYCAP,&caps))
              {
                perror("Querying cap fail");
                return 1;        
              }
              
          printf( "Driver Caps:\n"
                          "  Driver: \"%s\"\n"
                          "  Card: \"%s\"\n"
                          "  Bus: \"%s\"\n"
                          "  Version: %d.%d\n"
                          "  Capabilities: %08x\n",
                          caps.driver,
                          caps.card,
                          caps.bus_info,
                          (caps.version>>16)&&0xff,
                          (caps.version>>24)&&0xff,
                          caps.capabilities);
                          
                          
              perror("print_caps enter");
          
            return 0;    
          }
          
          int main()
          {
              int fd;
              fd=open("/dev/video0",O_RDWR);
              if(fd ==-1)
              {
                    perror("opening video device fail");
                    return 1;
                      
              }
              perror("opening video device success");
              
              if(print_caps(fd))
              {
                  return 1;
              }else{
                  
              }
              perror("close fd");
              close(fd);
              
              return 0;
              
          }  
  -------
  可以用 gcc vidtest.c -o vidtest 去編譯出 vidtest 執行檔。
 
  驗證方式:
  .將 v4l2step2.ko driver 載起來
   Note: 注意,要載入一個/dev/video0 裝置確定 videodev.ko 有載入,因這兩個driver有相依性。
   你可以用 lsmod 確定一下有無  videodev module,如果沒有就是表示你的 ubuntu kernel 在編譯時是將 videodev 設定為 module的
   ===
       mark@R3600:~/v4l2$ lsmod
    Module                  Size  Used by
    videodev               98259  0
    v4l2_compat_ioctl32    17128  1 videodev
    snd_hda_codec_hdmi     32530  1
    ....   
   ===
   這時候有兩個方法讓他載入,第一個方法是重新編譯 kernel( make menuconfig) 將 videodev 設定為 [一定載入]
   第二個方法,則是切換目錄到 cd lib/modules/3.2.0-31-generic/kernel/drivers/media/video/ ,確定有 videodev.ko
   使用指令  sudo modprobe videodev 手動載入他,再用 lsmod 確定一下有無載入 videodev.
 
   
  .檢查 /dev/video0 是否存在,確定是否正確載入 driver.
  .執行 vidtest 會秀出 ioctl VIDIOC_QUERYCAP 結果,如下:
 
  ---result--
       mark@R3600:~/v4l2$ ./vidtest
       opening video device success: Success
       print_caps enter: Success
       Driver Caps:
         Driver: "Mark vivi Drive"
         Card: "Mark test Card"
         Bus: "Mark's Platform"
         Version: 1.0
         Capabilities: 01000001
       print_caps enter: Success
       close fd: Success      
  ------------
 
  完整 v4l2step2.c source code如下
  ---v4l2step2.c---
               
               
             #include <linux/module.h>
             #include <linux/videodev2.h>
             #include <media/videobuf2-vmalloc.h>
             #include <media/v4l2-device.h>
             #include <media/v4l2-ioctl.h>
             #include <media/v4l2-ctrls.h>
             #include <media/v4l2-fh.h>
             #include <media/v4l2-event.h>
             #include <media/v4l2-common.h>
             
             //ar structure include v4l2_device
             struct ar {
                 struct v4l2_device v4l2_dev;
                 struct video_device vdev;
             };
             
             //static ardev var
             static struct ar ardev;
             
             
             
             static int ar_querycap(struct file *file, void  *priv,
                                 struct v4l2_capability *vcap)
             {
                 struct ar *ar = video_drvdata(file);
               /*
               fill
               struct v4l2_capability {
                 __u8    driver[16];
                 __u8    card[32];
                 __u8    bus_info[32];
                 __u32   version;
                 __u32    capabilities;
                 __u32    device_caps;
                 __u32    reserved[3];
               };
               
               */
                 strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver));
                 strlcpy(vcap->card, "Mark test Card", sizeof(vcap->card));
                 strlcpy(vcap->bus_info, "Mark test BUS", sizeof(vcap->bus_info));
                 vcap->capabilities =V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; // report capabilities
                 
                 printk(KERN_INFO "[mark]%s, %d, \n", __func__,__LINE__);
                 
                 return 0;
             }
             
             
             
             /****************************************************************************
              *
              * Video4Linux Module functions
              *
              ****************************************************************************/
             
             static const struct v4l2_file_operations ar_fops = {
                 .owner        = THIS_MODULE,
                 .open        = v4l2_fh_open,   // open /dev/video0 will enter here
                  .release    = v4l2_fh_release,   // close fd will enter here    
                  .unlocked_ioctl    = video_ioctl2,  // need for ioctl
             
             };
             
             static const struct v4l2_ioctl_ops ar_ioctl_ops = {
                 .vidioc_querycap                = ar_querycap,  // ioctl VIDIOC_QUERYCAP will enter here
             };
             
             
             static int __init vivi_init(void)
             {    
                 struct ar *ar;
                 struct v4l2_device *v4l2_dev;
                 int ret;
                 
             
             
               ar = &ardev;
                 v4l2_dev = &ar->v4l2_dev;
               //init v4l2 name , version
                 strlcpy(v4l2_dev->name, "arv", sizeof(v4l2_dev->name));
                 v4l2_info(v4l2_dev, "Colour AR VGA driver %s\n", "0.0.1"); // output V4l2 info
                 ret = v4l2_device_register(NULL, v4l2_dev);
                 if (ret < 0) {
                     printk(KERN_INFO "Could not register v4l2_device\n");
                     return ret;
                 }
                 
                 //setup video
                 strlcpy(ar->vdev.name, "Mark vivi Driver", sizeof(ar->vdev.name));
                 ar->vdev.v4l2_dev = v4l2_dev;   // set V4l2_device address to video_device
                 ar->vdev.fops = &ar_fops;   //v4l2_file_operations
                 ar->vdev.ioctl_ops = &ar_ioctl_ops;   //v4l2_ioctl_ops
                 ar->vdev.release = video_device_release_empty;
                 set_bit(V4L2_FL_USE_FH_PRIO, &ar->vdev.flags);
                 video_set_drvdata(&ar->vdev, ar);
             
                 if (video_register_device(&ar->vdev, VFL_TYPE_GRABBER, -1) != 0) {
                     /* return -1, -ENFILE(full) or others */
                     printk(KERN_INFO "[mark]%s, %d, video_register_device FAIL \n", __func__,__LINE__);
                     ret = -ENODEV;
                     goto out_dev;
                 }    
               printk(KERN_INFO "[mark]%s, %d, module inserted\n", __func__,__LINE__);
               return 0;
             
             out_dev:
                 v4l2_device_unregister(&ar->v4l2_dev);
                 video_unregister_device(&ar->vdev);
                 
                 return ret;
                 
               
             }
             
             static void __exit vivi_exit(void)
             {
                 struct ar *ar;
                 ar = &ardev;
                 
                 printk(KERN_INFO "[mark]%s, %d, module remove\n", __func__,__LINE__);
                 video_unregister_device(&ar->vdev);
                 v4l2_device_unregister(&ar->v4l2_dev);
                 
             }
             
             module_init(vivi_init);
             module_exit(vivi_exit);
             
             MODULE_DESCRIPTION("Mark test module");
             MODULE_AUTHOR("Mark Yang");
             MODULE_LICENSE("GPL");
             
  -----------------
 
 
(繼續閱讀...)
文章標籤

CuteParrot 發表在 痞客邦 留言(0) 人氣(2,299)

  • 個人分類:V4L2 Driver
▲top
  • 10月 22 週四 201510:56
  • V4L2 driver Step by Step(part1)

V4L2 driver Step by Step
.甚麼是V4L2 ?
  V4L2 全名為 Video For Linux Version 2,是 Linux 對於視訊擷取相關設備所建立的框架(Framework),此框架為驅動程式及應用程式提供了一套統一的接口規範。
  其支援的設備很多,不單只有視訊擷取設備,更可能包括: camera,video decoder, video encoder,tunner, ir remote, etc.
  列舉如下:
(繼續閱讀...)
文章標籤

CuteParrot 發表在 痞客邦 留言(0) 人氣(5,319)

  • 個人分類:V4L2 Driver
▲top
1

個人資訊

CuteParrot
暱稱:
CuteParrot
分類:
生活綜合
好友:
累積中
地區:

最新文章

  • [Gemini]線上多人賓果連線遊戲
  • [Gemini]gstreamer與 gst-launch-1.0相關知識
  • [Arduino UNO Q]將 arduino uno Q上面的usb camera經由UDP傳到 windows 11電腦上
  • [Gemini] 羽球分組對戰產生器
  • [Gemini]運動員公仔圖像生成
  • [Arduino UNO Q]Single-Board Computer (SBC) Mode
  • [Arduino UNO Q] 何處購買Arduino UNO Q
  • [車輛]森林人排放系統、車輛動態控制系統、上坡起步輔助系統-三燈獎(#8234946164)
  • [AI]Gemini影像處理成黑白(#8234928209)
  • [3C]Canon 850D夜間煙火拍攝記錄

熱門文章

  • (15,117)更換March K11 駕駛座門外把手
  • (106,739)格來得遙控器設定
  • (46,133)水塔液面控制器更換
  • (58,007)eDP 介面與資料整理
  • (6,400)vitantonio鬆餅機更換保險絲
  • (11,861)[DIY]更換延長線的帶燈開關
  • (36,665)[12代Corolla Altis] ACC設定三步驟,好記的方法
  • (38,812)[Altis]2019 12代altis (corolla) 中文車主手冊下載方法
  • (11,508)[12代ALTIS]拆解車門飾板,安裝前門警示燈
  • (10,504)[3C]QSPI通訊協定

文章分類

toggle AI應用 (1)
  • Gemini (5)
toggle 人生體悟 (3)
  • 提升工作效率 (7)
  • 雜項 (23)
  • 有感而發 (2)
toggle 大叔的滑板夢 (1)
  • 年輕時的滑板夢 (0)
toggle 手機相關 (4)
  • Zenfone3 ZE552KL (5)
  • POCO-F5 (3)
  • ZenFone6 ZS630KL (1)
  • Galaxy S4 (3)
toggle 太陽能相關 (2)
  • 太陽能躉售 (3)
  • 太陽能DIY套件 (5)
toggle AT32F415 (1)
  • AT32F415RCT7-7環境設定 (1)
toggle 電腦通訊協定 (5)
  • eDP (1)
  • CANBUS (3)
  • LVDS (1)
  • I2C (1)
  • SPI (2)
toggle PS4-PRO (2)
  • 單機多人遊戲 (1)
  • 單人遊戲 (1)
toggle XnBay (4)
  • 0-開箱 (1)
  • 連線網路磁碟機(Windows) (1)
  • 控制台、設定語言 (1)
  • DDNS設定 (1)
toggle 電腦相關 (5)
  • NXP i.MX 8M MINI EVK (10)
  • PhotoShop (3)
  • Arduino (9)
  • 3D印表機 (7)
  • 3C (78)
toggle Linux (7)
  • V4L2 Driver (2)
  • opencv (1)
  • ubuntu14.04 (3)
  • ubuntu 10.4 (7)
  • Android (23)
  • ubuntu 12.04 (22)
  • Android CTS (5)
toggle 汽機車相關 (7)
  • 行車紀錄器 (5)
  • 2021迪爵 (1)
  • 2022新迪爵EnMIS (2)
  • 2016 Forester 2.0i-e (16)
  • 12代Altis (15)
  • CAN BUS (3)
  • 汽機車修繕 (14)
toggle 露營 (31)
  • 第30露埔里樂活森林農場 (1)
  • 第29露南投國姓連興農場露營區 (1)
  • 第28露南投竹山大鞍幸福農場 (1)
  • 第27露南投中寮賞星月慕露營區 (1)
  • 第26露苗栗公館銃庫露營地 (1)
  • 第24露台中石岡九甲林秘境 (2)
  • 第25露苗栗泰安武嵐露營區 (1)
  • 第23露南投森林蜂味營地 (2)
  • 第22露花蓮壽豐慢活趣露營 (3)
  • 第21露國姓水岸松林農場 (1)
  • 第20露三義不遠露營山莊 (1)
  • 第19露FTC車露Payas之家 (1)
  • 第18露埔里廣成宋爸農場 (2)
  • 第17露高雄桂田莊園 (2)
  • 第16露泰安鄉司馬限山嵐 (3)
  • 第15露台南四草舟屋 (2)
  • 第14露新社趣露營 (3)
  • 第13露再訪魚雅筑渡假村 (2)
  • 第12露再訪龍泉營地 (2)
  • 第11露樹寄屋籬景觀民宿 (2)
  • 第10露逸香園休閒莊園 (3)
  • 第9露黃金森林露營區 (2)
  • 第8露魚雅筑渡假村(民宿露營) (1)
  • 第7露哈里露露營地 (3)
  • 第6露埔里龍泉營地 (3)
  • 第5露Payas之家露營區 (3)
  • 第4露土牧譯健康農莊 (3)
  • 第3露橫山仙境(南投) (2)
  • 第2露麒帆如 (4)
  • 第1露居大雁 (1)
  • 露營裝備與器材分享 (3)
toggle 寵物 (3)
  • 兔星人 (5)
  • 柴犬 (1)
  • 侏儒兔 (2)
toggle 玩木工 (2)
  • 2木工作品 (22)
  • 0木工電動工具 (6)
toggle 水族 (2)
  • 這是甚麼魚啊 (1)
  • 龍紋螯蝦 (2)
toggle 養鳥生活 (12)
  • 畫鸚鵡 (3)
  • 歷屆虎皮鸚鵡成員 (8)
  • 玄鳳生蛋 (2)
  • 虎皮鸚鵡相關網站與書籍 (3)
  • 員林的鳥店在哪裡? (4)
  • 玄鳳成員 (4)
  • 虎皮鸚鵡[活多久?] (1)
  • 虎皮鸚鵡[哪時候出巢?] (3)
  • 虎皮鸚鵡[會生病嗎?] (2)
  • 虎皮鸚鵡[吃甚麼] (2)
  • 虎皮鸚鵡[的鳥籠] (4)
  • 虎皮鸚鵡[成長過程] (30)
toggle 休閒運動 (3)
  • 羽球 (3)
  • 跑步 (3)
  • Game (5)
  • Arduino UNO Q (3)
  • Home Assistant相關 (2)
  • 虛擬貨幣交易 (2)
  • 居家DIY (24)
  • 台灣國內旅遊 (23)
  • 模型 (1)
  • 未分類文章 (1)

露營足跡

文章搜尋

參觀人氣

  • 本日人氣:
  • 累積人氣:

贊助馴龍窩