歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux中與驅動相關的ioctl函數

一:    ioctl函數的作用

    ioctl用於向設備發控制和配置命令 ,有些命令也需要讀寫一些數據,但這些數據是不能用read/write讀寫的,稱為Out-of-band數據。也就是說,read/write讀寫的數據是in-band數據,是I/O操作的主體,而ioctl命令傳送的是控制信息 ,其中的數據是輔助的數據。

    ioctl是設備驅動程序中對設備的I/O通道進行管理的函數,所謂對I/O通道進行管理,就是對設備的一些特性進行控制 ,例如,在串口線上收發數據通過read/write操作,而串口的波特率、校驗位、停止位通過ioctl設置,A/D轉換的結果通過read讀取,而A/D轉換的精度和工作頻率通過ioctl設置。
    ioctl函數是文件結構中的一個屬性分量,就是說如果你的驅動程序提供了對ioctl的支持,用戶就可以在用戶程序中使用ioctl函數控制設備的I/O通道。
    如果不用ioctl的話,也可以實現對設備I/O通道的控制,但那就是蠻擰了。例如,我們可以在驅動程序中實現write的時候檢查一下是否有特殊約定的數據流通過,如果有的話,那麼後面就跟著控制命令(一般在socket編程中常常這樣做)。但是如果這樣做的話,會導致代碼分工不明,程序結構混亂,程序員自己也會頭昏眼花的。
  
  所以,我們就使用ioctl來實現控制的功能 。要記住,用戶程序所作的只是通過命令碼告訴驅動程序它想做什麼,至於怎麼解釋這些命令和怎麼實現這些命令,這都是驅動程序要做的事情。

二: ioctl()用法
    int ioctl(int fd, ind cmd, …);

其中fd就是用戶程序打開設備時使用open函數返回的文件標示符,cmd就是用戶程序對設備的控制命令,至於後面的省略號,那是一些補充參數,一般最多一個,有或沒有是和cmd的意義相關的。下面是一個關於V4L視頻采集中用到的用ioctl來配置視頻采集設備(USB攝像頭)的一些特性參數的例子:

1.   定義設備結構體

    struct vdIn {
    int fd ; //設備描述符
    char *videodevice ; //設備節點,在linux下,通用的視頻采集設備節點為/dev/video0
    struct video_mmap vmmap;
    struct video_capability videocap;
    int mmapsize;
    struct video_mbuf videombuf;
    struct video_picture videopict;
    struct video_window videowin;
    struct video_channel videochan;   
    int cameratype ;
    char *cameraname;
    char bridge[9];
    int sizenative; // available size in jpeg
    int sizeothers;    // others palette
    int palette; // available palette
    int norme ; // set spca506 usb video grabber
    int channel ; // set spca506 usb video grabber
    int grabMethod ;
    unsigned char *pFramebuffer;
    unsigned char *ptframe[4];
    int framelock[4];
    pthread_mutex_t grabmutex;
    int framesizeIn ;
    volatile int frame_cour;
    int bppIn;
    int  hdrwidth;
    int  hdrheight;
    int  formatIn;
    int signalquit;   
    };

2.   設備節點賦值, "/dev/video0"是真實的物理攝像頭設備在linux中的表示

    if (videodevice == NULL || *videodevice == 0)
    {
      videodevice = "/dev/video0";
    }

3.  調用 設備 初始化函數

   struct vdIn videoIn;  //在spcav4l.h中定義
   videodevice = "/dev/video0"; //節點
   int width = 352;  //寬
   int height = 288;   //高
   int format = VIDEO_PALETTE_JPEG; //格式
   int grabmethod = 1;

   memset (&videoIn, 0, sizeof (struct vdIn));
  if (init_videoIn(&videoIn, videodevice, width, height, format,grabmethod) != 0)
    
    if(debug) printf (" damned encore rate !!/n");

4.   設備初始化函數傳值

  int init_videoIn (struct vdIn *vd, char *device, int width, int height,
          int format, int grabmethod)
{
  int err = -1;
  int i;
  if (vd == NULL || device == NULL)
    return -1;
  if (width == 0 || height == 0)
    return -1;
  if(grabmethod < 0 || grabmethod > 1)
      grabmethod = 1; //read by default;
    // check format
  vd->videodevice = NULL;
  vd->cameraname = NULL;
  vd->videodevice = NULL;
  vd->videodevice = (char *) realloc (vd->videodevice, 16);
  vd->cameraname = (char *) realloc (vd->cameraname, 32);


  snprintf (vd->videodevice, 12, "%s", device);
  if(debug) printf("video %s /n",vd->videodevice);


  memset (vd->cameraname, 0, sizeof (vd->cameraname));
  memset(vd->bridge, 0, sizeof(vd->bridge));
  vd->signalquit = 1;//信號設置
  vd->hdrwidth = width;
  vd->hdrheight = height;
  /*          compute the max frame size   */
  vd->formatIn = format; //傳進來的 format = VIDEO_PALETTE_JPEG;
  vd->bppIn = GetDepth (vd->formatIn);
 

  vd->grabMethod = grabmethod;        //mmap or read
  vd->pFramebuffer = NULL;
  /* init and check all setting */


  err = init_v4l (vd); // V4L初始化函數
  ....................................................
}

Copyright © Linux教程網 All Rights Reserved