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

📄 mmvideo.c

📁 LINUX内核编程的一些程序例子
💻 C
📖 第 1 页 / 共 2 页
字号:
  mmvideo_hw_stop( mvdev );  mvdev->user = 0;  MOD_DEC_USE_COUNT;}static long mmvideo_v4l_write( struct video_device * vdev, const char * buf,  unsigned long cnt, int noblock ){  struct mmvideo_device * mvdev = (struct mmvideo_device *)(vdev->priv);  if ( cnt != MMVIDEO_FRAMESIZE )    return -EINVAL;   down( & mvdev->lock );   if ( copy_from_user(			 mvdev->hw_frame[mvdev->hw_frame_nr].data, buf, cnt ) != 0 ) {    up( & mvdev->lock );     return -EFAULT;  }  // mvdev->frame_index = 0;  up( & mvdev->lock );   return MMVIDEO_FRAMESIZE;}static long mmvideo_v4l_read( struct video_device * vdev, char * buf,  unsigned long cnt, int noblock ){  struct mmvideo_device * mvdev = (struct mmvideo_device *)(vdev->priv);  DECLARE_WAITQUEUE( wait, current );  // struct file * file = vdev->file;  // clipping not supported  if ( cnt < MMVIDEO_FRAMESIZE )     return -EINVAL;  /* pre-sleep */  add_wait_queue( & mvdev->wq, & wait );  current->state = TASK_INTERRUPTIBLE;  down( & mvdev->lock );  while ( mvdev->frame_to_read < 0 ) {	// printk("mmvideo_v4l_read frame_to_read %d wait\n",	// 	       	mvdev->frame_to_read );	up( & mvdev->lock );    // if ( file->flags & O_NDELAY ) {    //   remove_wait_queue( & mmvideo_v4l_wait, & wait );    //   current->state = TASK_RUNNING;    //   return -EWOULDBLOCK;    // }    if ( signal_pending( current ) ) {      remove_wait_queue( & mvdev->wq, & wait );      current->state = TASK_RUNNING;      return -ERESTARTSYS;    }          /* sleep */    schedule();    current->state = TASK_INTERRUPTIBLE;    down( & mvdev->lock );  }   /* post-sleep */  remove_wait_queue( & mvdev->wq, & wait );  current->state = TASK_RUNNING;  // printk("mmvideo_v4l_read frame_to_read %d\n", mvdev->frame_to_read );  if ( copy_to_user(buf,                    mvdev->hw_frame[mvdev->frame_to_read].data,                    MMVIDEO_FRAMESIZE ) != 0 ) {	mvdev->frame_to_read = -1;    up( & mvdev->lock );	mvdev->error_cnt ++;    return -EFAULT;  }  mvdev->frame_to_read = -1;  up( & mvdev->lock );  mvdev->frame_cnt ++;    return MMVIDEO_FRAMESIZE;}static int mmvideo_v4l_mmap( struct video_device * vdev, const char * addr,  unsigned long size ){  struct mmvideo_device * mvdev = (struct mmvideo_device *)(vdev->priv);  unsigned long start = (unsigned long)addr;  unsigned long page, pos;  // printk("mmvideo mmap() size %ld %ld \n",  //   size, MMVIDEO_NUMFRAMES * MMVIDEO_FRAMESIZE );  if ( size > MMVIDEO_NUMFRAMES * MMVIDEO_FRAMESIZE )    return -EINVAL;    down( &mvdev->lock );  pos = (unsigned long) mvdev->fbuf;  while ( size > 0 ) {    page = kvirt_to_pa( pos );    if ( remap_page_range( start, page, PAGE_SIZE, PAGE_SHARED ) ) {      up( &mvdev->lock );      return -EAGAIN;    }    start += PAGE_SIZE;    pos   += PAGE_SIZE;    if ( size > PAGE_SIZE) {       size -= PAGE_SIZE;    } else {      size = 0;    }  }  up( &mvdev->lock );  return 0;}// this is called by V4L at the end of the initialization//static int mmvideo_v4l_init_done( struct video_device * vdev ){  struct mmvideo_device * mvdev = (struct mmvideo_device *)(vdev->priv);  #if defined( CONFIG_PROC_FS ) && defined( CONFIG_VIDEO_PROC_FS )    if (mmvideo_proc_create_entry( mvdev ) < 0 )      return -1;  #endif  mvdev->hw_frame_nr = 0;  // not really necessary  return 0;}static int mmvideo_v4l_ioctl( struct video_device * vdev, unsigned int cmd,  void * arg ){  struct mmvideo_device * mvdev = (struct mmvideo_device *)(vdev->priv);  switch ( cmd ) {    case VIDIOCGCAP: {      struct video_capability b;      strcpy( b.name, "mmvideo" );      b.type = VID_TYPE_CAPTURE;      b.channels = 1;      b.audios   = 0;      b.maxwidth  = mvdev->cwidth;      b.maxheight = mvdev->cheight;      b.minwidth  = mvdev->cwidth;      b.minheight = mvdev->cheight;      if ( copy_to_user( arg, &b, sizeof(b) ) ) return -EFAULT;      return 0;    }    case VIDIOCGCHAN: {   // only channel 0 allowed      struct video_channel c;      if ( copy_from_user( &c, arg, sizeof(c) ) ) return -EFAULT;      if ( c.channel != 0 ) return -EINVAL;      c.flags  = 0;      c.tuners = 0;      c.type   = VIDEO_TYPE_CAMERA;      strcpy( c.name, "mmvideo" );      if ( copy_to_user( arg, &c, sizeof(c) ) ) return -EFAULT;      return 0;    }    case VIDIOCSCHAN:      return -EINVAL;    case VIDIOCGPICT:      if ( copy_to_user( arg, &(mvdev->vpict), sizeof(struct video_picture) ) )        return -EFAULT;      return 0;    case VIDIOCSPICT:      return -EINVAL;    case VIDIOCGWIN: {	  // instantiate and fill a video_window struct	  //      // struct video_window w;      // w.x = 0;          // position on the framebuffer      // w.y = 0;      // w.chromakey = 0;      // w.flags = 0;      // w.clipcount = 0;  // number of clip rectangles      // w.width  = mvdev->vwidth;      // w.height = mvdev->vheight;	  //	  // and copy to userspace      // if ( copy_to_user( arg, &w, sizeof(w) ) ) return -EFAULT;      // return 0;	  return -EINVAL;    }    case VIDIOCSWIN:      return -EINVAL;    case VIDIOCGMBUF: {      struct video_mbuf m;      int i;      memset(&m, 0, sizeof(m));      m.size = MMVIDEO_FRAMESIZE * MMVIDEO_NUMFRAMES;      m.frames = MMVIDEO_NUMFRAMES;        for (i=0; i<MMVIDEO_NUMFRAMES; i++)            m.offsets[i] = i * MMVIDEO_FRAMESIZE;      if ( copy_to_user( arg, &m, sizeof(m) ) ) return -EFAULT;      return 0;    }    // VIDIOCMCAPTURE is used to tell the driver the size of the image    // and to start acquiring a frame    // VIDIOCSYNC is used to free the frame that has been acquired    case VIDIOCMCAPTURE: {      struct video_mmap m;        if ( copy_from_user( &m, arg, sizeof(m) ) ) return -EFAULT;      if ( m.format != MMVIDEO_PALETTE ) return -EINVAL;      if ( m.width != mvdev->vwidth ) return -EINVAL;      if ( m.height != mvdev->vheight ) return -EINVAL;      if ( m.frame < 0 || m.frame >= MMVIDEO_NUMFRAMES ) return -EINVAL;      // start mmap streaming       return mmvideo_hw_mcapture( mvdev, m.frame );      return 0;    }    case VIDIOCSYNC: {      int frame;      if ( copy_from_user( (void *)&frame, arg, sizeof(int) ) ) return -EFAULT;      if ( frame < 0 || frame >= MMVIDEO_NUMFRAMES ) return -EINVAL;      return mmvideo_hw_mrelease( mvdev, frame );    }    case VIDIOCGFBUF: {      struct video_buffer b;      memset( &b, 0, sizeof(b) );      b.base   = mvdev->fbuf;      b.width  = mvdev->cwidth;      b.height = mvdev->cheight;      b.depth  = MMVIDEO_DEPTH;      b.bytesperline = mvdev->cwidth * MMVIDEO_DEPTH;       if ( copy_to_user( arg, &b, sizeof(b) ) ) return -EFAULT;      return 0;    }    case VIDIOCKEY:      return 0;    case VIDIOCCAPTURE: // overlay capture not supported      return -EINVAL;    case VIDIOCGTUNER:    case VIDIOCSTUNER:    case VIDIOCGFREQ:    case VIDIOCSFREQ:    case VIDIOCGAUDIO:    case VIDIOCSAUDIO:      return -EINVAL;    default:      return -ENOIOCTLCMD;  }  return 0;}static struct video_device vdev_template = {  #ifdef VIDEO_DEVICE_HAVE_OWNER    owner:      THIS_MODULE,  #endif  name:       "mmvideo",  type:       VID_TYPE_CAPTURE,     // VID_TYPE_OVERLAY not supported			                        // thus no VID_TYPE_CLIPPING / CHROMAKEY			                        // VID_TYPE_FRAMERAM not supported  hardware:   VID_HARDWARE_PSEUDO,  // see videodev.h  open:       mmvideo_v4l_open,  close:      mmvideo_v4l_close,  read:       mmvideo_v4l_read,  write:      mmvideo_v4l_write,  ioctl:      mmvideo_v4l_ioctl,  mmap:       mmvideo_v4l_mmap,  initialize: mmvideo_v4l_init_done,  // minor:      1,};/* ------------------------------------------------------------ */static struct mmvideo_device * mmvideo = NULL;static int __init mmvideo_init( void ){  int i,j;  unsigned char * chp;  int nr;  if ((mmvideo =       kmalloc( sizeof(struct mmvideo_device), GFP_KERNEL)) == NULL) {    return -1;  }  memset( mmvideo, 0, sizeof(struct mmvideo_device) );  // video buffer memory allocation  mmvideo->fbuf = rvmalloc( MMVIDEO_FRAMESIZE * MMVIDEO_NUMFRAMES );  if ( ! mmvideo->fbuf ) {    kfree( mmvideo );    return -1;  }  mmvideo->hw_fbuf = rvmalloc( MMVIDEO_FRAMESIZE * 2);  if ( ! mmvideo->hw_fbuf ) {	rvfree( mmvideo->fbuf, MMVIDEO_FRAMESIZE * MMVIDEO_NUMFRAMES );	kfree( mmvideo );	return -1;  }  // mmvideo->frame_index = 0;  // first frame   for (i=0; i<2; i++)     mmvideo->hw_frame[i].data = mmvideo->hw_fbuf + i * MMVIDEO_FRAMESIZE;    for (i=0; i<MMVIDEO_NUMFRAMES; i++)    mmvideo->frame[i].data = mmvideo->fbuf + i * MMVIDEO_FRAMESIZE;    // now fake an initial picture  chp = mmvideo->hw_frame[0].data;  for (j=0; j<MMVIDEO_HEIGHT; j++) {    for (i=0; i<MMVIDEO_WIDTH; i++) {      if ( (i+j)>100 && (i+j)<150 && (i-j)>0 && (i-j)<50)         *(chp) = 128;      else if (i>150 && i<200 && j>100 && j<150)         *(chp+1) = 128;      else if (i>50 && i<100 && j>150 && j<200 && (i-j)<-100)         *(chp+2) = 128;      chp += 3;  } }  mmvideo->hw_frame_nr = 0;      memcpy( &mmvideo->vdev, &vdev_template, sizeof(struct video_device) );  mmvideo->vdev.priv = mmvideo;  // use private data  init_waitqueue_head( &mmvideo->wq );  init_MUTEX( &mmvideo->lock );  wmb();  // the proc dir must be created before registering with V4L  #if defined( CONFIG_PROC_FS ) && defined( CONFIG_VIDEO_PROC_FS )    if ( mmvideo_proc_create_dir() < 0 ) {      video_unregister_device( &mmvideo->vdev );      rvfree( mmvideo->hw_fbuf, MMVIDEO_NUMFRAMES*2 );      rvfree( mmvideo->fbuf, MMVIDEO_NUMFRAMES*MMVIDEO_FRAMESIZE );      kfree( mmvideo );      return -1;    }  #endif  PDEBUG( "mmvideo_init() registering with video\n");   // nr >= 0 specifies the device   // nr = -1 means the first free device  if (	// (nr = video_register_device( &mmvideo->vdev, VFL_TYPE_GRABBER, -1)) 	(nr = video_register_device( &mmvideo->vdev, VFL_TYPE_GRABBER)) 	== -1) {    rvfree( mmvideo->hw_fbuf, MMVIDEO_NUMFRAMES*2 );    rvfree( mmvideo->fbuf, MMVIDEO_NUMFRAMES*MMVIDEO_FRAMESIZE );    kfree( mmvideo );    return -1;  }  // printk( "mmvideo_init() registered with video, nr. %d\n", nr);  return 0;}static void __exit mmvideo_exit( void ){  if ( ! mmvideo ) return;  wake_up_interruptible( & mmvideo->wq );  #if defined( CONFIG_PROC_FS ) && defined( CONFIG_VIDEO_PROC_FS )    mmvideo_proc_destroy_dir();  #endif  lock_kernel();  if ( mmvideo->user == 0 ) {    PDEBUG( "mmvideo_init() unregistering with video\n");  } else {    PDEBUG( "mmvideo_init() unregistering when user 1\n");  }  video_unregister_device( &mmvideo->vdev );  rvfree( mmvideo->hw_fbuf, MMVIDEO_NUMFRAMES*2 );  rvfree( mmvideo->fbuf, MMVIDEO_NUMFRAMES * MMVIDEO_FRAMESIZE );  kfree( mmvideo );  unlock_kernel();}module_init( mmvideo_init );module_exit( mmvideo_exit );

⌨️ 快捷键说明

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