1 / 19

SNONIX 120 摄像头驱动程序设计

SNONIX 120 摄像头驱动程序设计. By :刘京 李康年 刘权 陈靖. 主要内容:. USB 摄像头驱动简介 V4L2 简介 v4l2 视频处理的步骤 urb 结构体简介 驱动原理. USB 摄像头驱动. USB 摄像头以其良好的性能和低廉的价格得到广泛应用 但由于摄像头所用芯片的不同,以及传感器的多样性,需对其进行驱动程序的编写. 摄像头驱动的特殊性.

havyn
Download Presentation

SNONIX 120 摄像头驱动程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. SNONIX 120摄像头驱动程序设计 By:刘京 李康年 刘权 陈靖

  2. 主要内容: • USB摄像头驱动简介 • V4L2简介 • v4l2视频处理的步骤 • urb结构体简介 • 驱动原理

  3. USB摄像头驱动 • USB摄像头以其良好的性能和低廉的价格得到广泛应用 • 但由于摄像头所用芯片的不同,以及传感器的多样性,需对其进行驱动程序的编写

  4. 摄像头驱动的特殊性 • 摄像头属于视频类设备。在目前的Linux核心中,视频部分的标准是Video for Linux(简称V4L)。这个标准其实定义了一套接口,内核、驱动、应用程序以这个接口为标准进行交流

  5. V4L2简介 • 一个Linux系统用来处理视频图形的接口。它由一个视频接口 • 标准以及一系列的API组成。

  6. v4l2视频处理的步骤: • 1:打开设备。 • 2:设置设备属性,图形分辨率,亮度。 • 3:协定数据格式。 • 4:协定输入输出方法。 • 5:输入,输出循环。 • 6:关闭设备。

  7. urb结构体简介 • Linux 内核中的USB代码通过一个称为urb(USB 请求块)的东西和所有的USB设备通信。 • urb 被用来以一种异步的方式往/ 从特定的USB 设备上的特定USB端点发送/ 接收数据。重用单个的urb,这取决于驱动程序的需要。设备中的每个端点都可以处理一个urb 队列,所以多个urb可以在队列为空之前发送到同一个端点

  8. urb的生命周期(一) • 由USB 设备驱动程序创建。 • 分配给一个特定USB 设备的特定端点。 • 由USB 设备驱动程序递交到USB 核心。

  9. urb的生命周期(二) • 由USB 核心递交到特定设备的特定USB 主控制器驱动程序。 • 由USB 主控制器驱动程序处理,它从设备进行USB 传送。 • 当urb 结束之后,USB 主控制器驱动程序通知USB设备驱动程序。

  10. 驱动原理图:

  11. static void sn9c120_urb_complete(struct urb *urb) //ok • { • struct sn9c120_device* cam = urb->context; • struct sn9c120_frame_t** f; • size_t imagesize, soflen; • u8 i; • int err = 0; • if (urb->status == -ENOENT) • return;

  12. f = &cam->frame_current; • if (cam->stream == STREAM_INTERRUPT) { • cam->stream = STREAM_OFF; • if ((*f)) • (*f)->state = F_QUEUED; • cam->sof.bytesread = 0; • printk( "Stream interrupted by application\n"); • wake_up(&cam->wait_stream); • } • if (cam->state & DEV_DISCONNECTED) • return; • if (cam->state & DEV_MISCONFIGURED) { • wake_up_interruptible(&cam->wait_frame); • return; • } • if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) • goto resubmit_urb;

  13. if (!(*f)) • (*f) = list_entry(cam->inqueue.next, struct sn9c120_frame_t, • frame); • imagesize = (cam->sensor.pix_format.width * • cam->sensor.pix_format.height * • cam->sensor.pix_format.priv) / 8; • if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) • imagesize += 589; /* length of jpeg header */ • soflen = sn9c120_sof_length(cam); • for (i = 0; i < urb->number_of_packets; i++) { • unsigned int img, len, status; • void *pos, *sof, *eof; • len = urb->iso_frame_desc[i].actual_length; • status = urb->iso_frame_desc[i].status; • pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; • if (status) { • printk( "Error in isochronous frame\n"); • (*f)->state = F_ERROR; • cam->sof.bytesread = 0; • continue; • }

  14. redo: • sof = sn9c120_find_sof_header(cam, pos, len); • if (likely(!sof)) { • eof = sn9c120_find_eof_header(cam, pos, len); • if ((*f)->state == F_GRABBING) { • end_of_frame: • img = len; • if (eof) • img = (eof > pos) ? eof - pos - 1 : 0; • if ((*f)->buf.bytesused + img > imagesize) { • u32 b; • b = (*f)->buf.bytesused + img - • imagesize; • img = imagesize - (*f)->buf.bytesused; • printk("Expected EOF not found: video " • "frame cut\n"); • if (eof) • printk( "Exceeded limit: +%u " • "bytes\n", (unsigned)(b)); • }

  15. memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, • img); • if ((*f)->buf.bytesused == 0) • do_gettimeofday(&(*f)->buf.timestamp); • (*f)->buf.bytesused += img; • if ((*f)->buf.bytesused == imagesize || • ((cam->sensor.pix_format.pixelformat == • V4L2_PIX_FMT_SN9C10X || • cam->sensor.pix_format.pixelformat == • V4L2_PIX_FMT_JPEG) && eof)) { • u32 b; • b = (*f)->buf.bytesused; • (*f)->state = F_DONE; • (*f)->buf.sequence= ++cam->frame_count; • spin_lock(&cam->queue_lock); • list_move_tail(&(*f)->frame, • &cam->outqueue); • if (!list_empty(&cam->inqueue)) • (*f) = list_entry( • cam->inqueue.next, • struct sn9c120_frame_t, • frame ); • else • (*f) = NULL; • spin_unlock(&cam->queue_lock);

  16. memcpy(cam->sysfs.frame_header, • cam->sof.header, soflen); • printk( "Video frame captured: %lu " • "bytes\n", (unsigned long)(b)); • if (!(*f)) • goto resubmit_urb; • } else if (eof) { • (*f)->state = F_ERROR; • } • if (sof) /* (1) */ • goto start_of_frame; • } else if (eof) { • printk( "EOF without SOF\n"); • continue; • } else { • printk("Ignoring pointless isochronous frame\n"); • continue; • } • } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {

  17. start_of_frame: • (*f)->state = F_GRABBING; • (*f)->buf.bytesused = 0; • len -= (sof - pos); • pos = sof; • if (cam->sensor.pix_format.pixelformat == • V4L2_PIX_FMT_JPEG) • sn9c120_write_jpegheader(cam, (*f)); • printk( "SOF detected: new video frame\n"); • if (len) • goto redo; • } else if ((*f)->state == F_GRABBING) { • eof = sn9c120_find_eof_header(cam, pos, len); • if (eof && eof < sof) • goto end_of_frame; /* (1) */

  18. else { • if (cam->sensor.pix_format.pixelformat == • V4L2_PIX_FMT_SN9C10X || • cam->sensor.pix_format.pixelformat == • V4L2_PIX_FMT_JPEG) { • if (sof - pos >= soflen) { • eof = sof - soflen; • } else { /* remove header */ • eof = pos; • (*f)->buf.bytesused -= • (soflen - (sof - pos)); • } • goto end_of_frame; • } else { • printk( "SOF before expected EOF after " • "%lu bytes of image data\n", • (unsigned long) • ((*f)->buf.bytesused)); • goto start_of_frame; • } • } • } • }

  19. resubmit_urb: • urb->dev = cam->usbdev; • err = usb_submit_urb(urb, GFP_ATOMIC); • if (err < 0 && err != -EPERM) { • cam->state |= DEV_MISCONFIGURED; • printk( "usb_submit_urb() failed\n"); • } • wake_up_interruptible(&cam->wait_frame); • }

More Related