自己写的uvc驱动支持IP2977/ip2970

Posted Jarry_le

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己写的uvc驱动支持IP2977/ip2970相关的知识,希望对你有一定的参考价值。

  1. /* 作者: 453411484@qq.com  
  2.  * 此驱动程序是基于linux2.6.31.14内核 
  3.  * 上一篇自己写的uvc驱动程序是针对环宇飞扬6190来写的,有一些缺点,这些缺点在本次的驱动 
  4.  * 中进行了修改此uvc驱动是针对IP2977进行了支持,根据IP2977芯片厂商提供的修改手册进行了修改。 
  5.  * 此驱动程序虽然支持IP2977摄像头,但是显示效果不太好,此驱动只是针对学习使用。 
  6.  */  
  7.   
  8. #include <linux kernel="" h="">  
  9. #include <linux list="" h="">  
  10. #include <linux module="" h="">  
  11. #include <linux usb="" h="">  
  12. #include <linux videodev2="" h="">  
  13. #include <linux vmalloc="" h="">  
  14. #include <linux wait="" h="">  
  15. #include <linux mm="" h="">  
  16. #include <asm atomic="" h="">  
  17. #include <asm unaligned="" h="">  
  18.   
  19. #include <media v4l2-common="" h="">  
  20. #include <media v4l2-ioctl="" h="">  
  21. #include <media videobuf-core="" h="">  
  22.   
  23. #include "uvcvideo.h"  
  24.   
  25. /* 参考 drivers/media/video/uvc */  
  26.   
  27. #define MYUVC_URBS 5  
  28.   
  29. /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */  
  30. #define UVC_STREAM_EOH  (1 << 7)  
  31. #define UVC_STREAM_ERR  (1 << 6)  
  32. #define UVC_STREAM_STI  (1 << 5)  
  33. #define UVC_STREAM_RES  (1 << 4)  
  34. #define UVC_STREAM_SCR  (1 << 3)  
  35. #define UVC_STREAM_PTS  (1 << 2)  
  36. #define UVC_STREAM_EOF  (1 << 1)  
  37. #define UVC_STREAM_FID  (1 << 0)  
  38.   
  39.   
  40. struct myuvc_streaming_control   
  41.     __u16 bmHint;  
  42.     __u8  bFormatIndex;  
  43.     __u8  bFrameIndex;  
  44.     __u32 dwFrameInterval;  
  45.     __u16 wKeyFrameRate;  
  46.     __u16 wPFrameRate;  
  47.     __u16 wCompQuality;  
  48.     __u16 wCompWindowSize;  
  49.     __u16 wDelay;  
  50.     __u32 dwMaxVideoFrameSize;  
  51.     __u32 dwMaxPayloadTransferSize;  
  52.     __u32 dwClockFrequency;  
  53.     __u8  bmFramingInfo;  
  54.     __u8  bPreferedVersion;  
  55.     __u8  bMinVersion;  
  56.     __u8  bMaxVersion;  
  57. ;  
  58.   
  59.   
  60.   
  61. struct frame_desc   
  62.     int width;  
  63.     int height;  
  64. ;  
  65.   
  66. /* 参考uvc_video_queue定义一些结构体 */  
  67. struct myuvc_buffer       
  68.     struct v4l2_buffer buf;  
  69.     int state;  
  70.     int vma_use_count; /* 表示是否已经被mmap */  
  71.     wait_queue_head_t wait;  /* APP要读某个缓冲区,如果无数据,在此休眠 */  
  72.     struct list_head stream;  
  73.     struct list_head irq;      
  74. ;  
  75.   
  76. struct myuvc_queue   
  77.     void *mem;  
  78.     int count;  
  79.     int buf_size;      
  80.     struct myuvc_buffer buffer[32];  
  81.   
  82.     struct urb *urb[32];  
  83.     char *urb_buffer[32];  
  84.     dma_addr_t urb_dma[32];  
  85.     unsigned int urb_size;  
  86.   
  87.     struct list_head mainqueue;   /* 供APP消费用 */  
  88.     struct list_head irqqueue;    /* 供底层驱动生产用 */  
  89. ;  
  90.   
  91. static struct myuvc_queue myuvc_queue;  
  92.   
  93. static struct video_device *myuvc_vdev;  
  94. static struct usb_device *myuvc_udev;  
  95.   
  96. static int myuvc_bEndpointAddress = 0x82;  
  97. static int myuvc_streaming_intf;  
  98. static int myuvc_control_intf;  
  99. static struct v4l2_format myuvc_format;  
  100.   
  101. static struct frame_desc frames[] = 640, 480, 320, 240, 160, 120;  
  102. static int frame_idx = 1;  
  103. static int bBitsPerPixel = 0; /* lsusb -v -d 0x1e4e:  "bBitsPerPixel" */  
  104. static int uvc_version = 0x0100; /* lsusb -v -d 0x1b3b: bcdUVC */  
  105.   
  106. static int ProcessingUnitID = 3;  /* lsusb -v -d 0x1b3b: PROCESSING_UNIT */  
  107.   
  108. /* 以后再设置 */  
  109. static int wMaxPacketSize = 800;  
  110. static int myuvc_streaming_bAlternateSetting = 5;  
  111. static int dwMaxVideoFrameSize = 77312;  
  112.   
  113. static struct myuvc_streaming_control myuvc_params;  
  114.   
  115. static int last_fid = -1;  
  116.   
  117. /* A2 参考 uvc_v4l2_do_ioctl */  
  118. static int myuvc_vidioc_querycap(struct file *file, void  *priv,  
  119.                     struct v4l2_capability *cap)  
  120.       
  121.     memset(cap, 0, sizeof *cap);  
  122.     strcpy(cap->driver, "myuvc");  
  123.     strcpy(cap->card, "myuvc");  
  124.     cap->version = 1;  
  125.       
  126.     cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;  
  127.    
  128.     return 0;  
  129.   
  130.   
  131. /* A3 列举支持哪种格式 
  132.  * 参考: uvc_fmts 数组 
  133.  */  
  134. static int myuvc_vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,  
  135.                     struct v4l2_fmtdesc *f)  
  136.   
  137.     /* 人工查看描述符可知我们用的摄像头只支持1种格式 */  
  138.     if (f->index >= 1)  
  139.         return -EINVAL;  
  140.   
  141.     strcpy(f->description, "MJPEG");  
  142.     f->pixelformat = V4L2_PIX_FMT_MJPEG;      
  143.     //f->flags       = ;  
  144.     f->type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  145.       
  146.     return 0;  
  147.   
  148.   
  149. /* A4 返回当前所使用的格式 */  
  150. static int myuvc_vidioc_g_fmt_vid_cap(struct file *file, void *priv,  
  151.                     struct v4l2_format *f)  
  152.   
  153.     memcpy(f, &myuvc_format, sizeof(myuvc_format));  
  154.     return (0);  
  155.   
  156.   
  157. /* A5 测试驱动程序是否支持某种格式, 强制设置该格式  
  158.  * 参考: uvc_v4l2_try_format 
  159.  *       myvivi_vidioc_try_fmt_vid_cap 
  160.  */  
  161. static int myuvc_vidioc_try_fmt_vid_cap(struct file *file, void *priv,  
  162.             struct v4l2_format *f)  
  163.   
  164.     if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)  
  165.       
  166.         return -EINVAL;  
  167.       
  168.   
  169.     if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)  
  170.         return -EINVAL;  
  171.       
  172.     /* 调整format的width, height,  
  173.      * 计算bytesperline, sizeimage 
  174.      */  
  175.   
  176.     /* 人工查看描述符, 确定支持哪几种分辨率 */  
  177.     f->fmt.pix.width  = frames[frame_idx].width;  
  178.     f->fmt.pix.height = frames[frame_idx].height;  
  179.   
  180.     /* 对于MJPEG数据类型来说,bBitsPerPixel是无法知道的。因此我们设为0 */  
  181.     f->fmt.pix.bytesperline =  
  182.         (f->fmt.pix.width * bBitsPerPixel) >> 3;  
  183.       
  184.     /* 一帧数据最大为dwMaxVideoFrameSize=77312,是由确定带宽时确定出来的。 */  
  185.     f->fmt.pix.sizeimage = dwMaxVideoFrameSize;  
  186.   
  187.     f->fmt.pix.field      = V4L2_FIELD_NONE;  
  188.     /* 由描述符bColorPrimaries  1 (BT.709,sRGB)可知 */  
  189.     f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;  
  190.     f->fmt.pix.priv       = 0;       /* private data, depends on pixelformat */  
  191.       
  192.     return 0;  
  193.   
  194.   
  195. /* A6 参考 myvivi_vidioc_s_fmt_vid_cap */  
  196. static int myuvc_vidioc_s_fmt_vid_cap(struct file *file, void *priv,  
  197.                     struct v4l2_format *f)  
  198.   
  199.     int ret = myuvc_vidioc_try_fmt_vid_cap(file, NULL, f);  
  200.     if (ret < 0)  
  201.         return ret;  
  202.   
  203.     memcpy(&myuvc_format, f, sizeof(myuvc_format));  
  204.       
  205.     return 0;  
  206.   
  207.   
  208. static int myuvc_free_buffers(void)  
  209.   
  210.     if (myuvc_queue.mem)  
  211.       
  212.         vfree(myuvc_queue.mem);  
  213.         memset(&myuvc_queue, 0, sizeof(myuvc_queue));  
  214.         myuvc_queue.mem = NULL;  
  215.       
  216.     return 0;  
  217.   
  218.   
  219. /* A7 APP调用该ioctl让驱动程序分配若干个缓存, APP将从这些缓存中读到视频数据  
  220.  * 参考: uvc_alloc_buffers 
  221.  */  
  222. static int myuvc_vidioc_reqbufs(struct file *file, void *priv,  
  223.               struct v4l2_requestbuffers *p)  
  224.   
  225.     int nbuffers = p->count;  
  226.     int bufsize  = PAGE_ALIGN(myuvc_format.fmt.pix.sizeimage);  
  227.     unsigned int i;  
  228.     void *mem = NULL;  
  229.     int ret;  
  230.   
  231.     if ((ret = myuvc_free_buffers()) < 0)  
  232.         goto done;  
  233.   
  234.     /* Bail out if no buffers should be allocated. */  
  235.     if (nbuffers == 0)  
  236.         goto done;  
  237.   
  238.     /* Decrement the number of buffers until allocation succeeds. */  
  239.     for (; nbuffers > 0; --nbuffers)   
  240.         mem = vmalloc_32(nbuffers * bufsize);  
  241.         if (mem != NULL)  
  242.             break;  
  243.       
  244.   
  245.     if (mem == NULL)   
  246.         ret = -ENOMEM;  
  247.         goto done;  
  248.       
  249.   
  250.     /* 这些缓存是一次性作为一个整体来分配的 */  
  251.     memset(&myuvc_queue, 0, sizeof(myuvc_queue));  
  252.   
  253.     INIT_LIST_HEAD(&myuvc_queue.mainqueue);  
  254.     INIT_LIST_HEAD(&myuvc_queue.irqqueue);  
  255.   
  256.     for (i = 0; i < nbuffers; ++i)   
  257.         myuvc_queue.buffer[i].buf.index = i;  
  258.         myuvc_queue.buffer[i].buf.m.offset = i * bufsize;  
  259.         myuvc_queue.buffer[i].buf.length = myuvc_format.fmt.pix.sizeimage;  
  260.         myuvc_queue.buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  261.         myuvc_queue.buffer[i].buf.sequence = 0;  
  262.         myuvc_queue.buffer[i].buf.field = V4L2_FIELD_NONE;  
  263.         myuvc_queue.buffer[i].buf.memory = V4L2_MEMORY_MMAP;  
  264.         myuvc_queue.buffer[i].buf.flags = 0;  
  265.         myuvc_queue.buffer[i].state     = VIDEOBUF_IDLE;  
  266.         init_waitqueue_head(&myuvc_queue.buffer[i].wait);  
  267.       
  268.   
  269.     myuvc_queue.mem = mem;  
  270.     myuvc_queue.count = nbuffers;  
  271.     myuvc_queue.buf_size = bufsize;  
  272.     ret = nbuffers;  
  273.   
  274. done:  
  275.     return ret;  
  276.   
  277.   
  278. /* A8 查询缓存状态, 比如地址信息(APP可以用mmap进行映射)  
  279.  * 参考 uvc_query_buffer 
  280.  */  
  281. static int myuvc_vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *v4l2_buf)  
  282.   
  283.     int ret = 0;  
  284.       
  285.     if (v4l2_buf->index >= myuvc_queue.count)   
  286.         ret = -EINVAL;  
  287.         goto done;  
  288.       
  289.   
  290.     memcpy(v4l2_buf, &myuvc_queue.buffer[v4l2_buf->index].buf, sizeof(*v4l2_buf));  
  291.   
  292.     /* 更新flags */  
  293.     if (myuvc_queue.buffer[v4l2_buf->index].vma_use_count)  
  294.         v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;  
  295.   
  296.   
  297.     switch (myuvc_queue.buffer[v4l2_buf->index].state)   
  298.         case VIDEOBUF_ERROR:  
  299.         case VIDEOBUF_DONE:  
  300.             v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;  
  301.             break;  
  302.         case VIDEOBUF_QUEUED:  
  303.         case VIDEOBUF_ACTIVE:  
  304.             v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;  
  305.             break;  
  306.         case VIDEOBUF_IDLE:  
  307.         default:  
  308.             break;  
  309.       
  310.   
  311. done:      
  312.     return ret;  
  313.   
  314.   
  315. /* A10 把缓冲区放入队列, 底层的硬件操作函数将会把数据放入这个队列的缓存  
  316.  * 参考: uvc_queue_buffer 
  317.  */  
  318. static int myuvc_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *v4l2_buf)  
  319.   
  320.     struct myuvc_buffer *buf;  
  321.   
  322.     /* 0. APP传入的v4l2_buf可能有问题, 要做判断 */  
  323.   
  324.     if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||  
  325.         v4l2_buf->memory != V4L2_MEMORY_MMAP)   
  326.         return -EINVAL;  
  327.       
  328.   
  329.     if (v4l2_buf->index >= myuvc_queue.count)   
  330.         return -EINVAL;  
  331.       
  332.   
  333.     buf = &myuvc_queue.buffer[v4l2_buf->index];  
  334.   
  335.     if (buf->state != VIDEOBUF_IDLE)   
  336.         return -EINVAL;  
  337.       
  338.   
  339.   
  340.     /* 1. 修改状态 */  
  341.     buf->state = VIDEOBUF_QUEUED;  
  342.     buf->buf.bytesused = 0;  
  343.   
  344.     /* 2. 放入2个队列 */  
  345.     /* 队列1: 供APP使用  
  346.      * 当缓冲区没有数据时,放入mainqueue队列 
  347.      * 当缓冲区有数据时, APP从mainqueue队列中取出 
  348.      */  
  349.     list_add_tail(&buf->stream, &myuvc_queue.mainqueue);  
  350.   
  351.     /* 队列2: 供产生数据的函数使用 
  352.      * 当采集到数据时,从irqqueue队列中取出第1个缓冲区,存入数据 
  353.      */  
  354.     list_add_tail(&buf->irq, &myuvc_queue.irqqueue);  
  355.       
  356.     return 0;  
  357.   
  358.   
  359. static void myuvc_print_streaming_params(struct myuvc_streaming_control *ctrl)  
  360.   
  361.     printk("video params:\\n");  
  362.     printk("bmHint                   = %d\\n", ctrl->bmHint);  
  363.     printk("bFormatIndex             = %d\\n", ctrl->bFormatIndex);  
  364.     printk("bFrameIndex              = %d\\n", ctrl->bFrameIndex);  
  365.     printk("dwFrameInterval          = %d\\n", ctrl->dwFrameInterval);  
  366.     printk("wKeyFrameRate            = %d\\n", ctrl->wKeyFrameRate);  
  367.     printk("wPFrameRate              = %d\\n", ctrl->wPFrameRate);  
  368.     printk("wCompQuality             = %d\\n", ctrl->wCompQuality);  
  369.     printk("wCompWindowSize          = %d\\n", ctrl->wCompWindowSize);  
  370.     printk("wDelay                   = %d\\n", ctrl->wDelay);  
  371.     printk("dwMaxVideoFrameSize      = %d\\n", ctrl->dwMaxVideoFrameSize);  
  372.     printk("dwMaxPayloadTransferSize = %d\\n", ctrl->dwMaxPayloadTransferSize);  
  373.     printk("dwClockFrequency         = %d\\n", ctrl->dwClockFrequency);  
  374.     printk("bmFramingInfo            = %d\\n", ctrl->bmFramingInfo);  
  375.     printk("bPreferedVersion         = %d\\n", ctrl->bPreferedVersion);  
  376.     printk("bMinVersion              = %d\\n", ctrl->bMinVersion);  
  377.     printk("bMinVersion              = %d\\n", ctrl->bMinVersion);  
  378.   
  379.   
  380.   
  381. /* 参考: uvc_get_video_ctrl  
  382.  (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR))  
  383.  static int uvc_get_video_ctrl(struct uvc_video_device *video, 
  384.      struct uvc_streaming_control *ctrl, int probe, __u8 query) 
  385.  */  
  386. static int myuvc_get_streaming_params(struct myuvc_streaming_control *ctrl)  
  387.   
  388.     __u8 *data;  
  389.     __u16 size;  
  390.     int ret;  
  391.     __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;  
  392.     unsigned int pipe;  
  393.   
  394.     size = uvc_version >= 0x0110 ? 34 : 26;  
  395.     data = kmalloc(size, GFP_KERNEL);  
  396.     if (data == NULL)  
  397.         return -ENOMEM;  
  398.      
  399.     pipe = (GET_CUR & 0x80) ? usb_rcvctrlpipe(myuvc_udev, 0)  
  400.                   : usb_sndctrlpipe(myuvc_udev, 0);  
  401.     type |= (GET_CUR & 0x80) ? USB_DIR_IN : USB_DIR_OUT;  
  402.   
  403.     ret = usb_control_msg(myuvc_udev, pipe, GET_CUR, type, VS_PROBE_CONTROL << 8,  
  404.             0 << 8 | myuvc_streaming_intf, data, size, 5000);  
  405.   
  406.     if (ret < 0)  
  407.         goto done;  
  408.   
  409.     ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);  
  410.     ctrl->bFormatIndex = data[2];  
  411.     ctrl->bFrameIndex = data[3];  
  412.     ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);  
  413.     ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);  
  414.     ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]);  
  415.     ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]);  
  416.     ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]);  
  417.     ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]);  
  418.     ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]);  
  419.     ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]);  
  420.   
  421.     if (size == 34)   
  422.         ctrl->dwClockFrequency = get_unaligned_le32(&data[26]);  
  423.         ctrl->bmFramingInfo = data[30];  
  424.         ctrl->bPreferedVersion = data[31];  
  425.         ctrl->bMinVersion = data[32];  
  426.         ctrl->bMaxVersion = data[33];  
  427.      else   
  428.         //ctrl->dwClockFrequency = video->dev->clock_frequency;  
  429.         ctrl->bmFramingInfo = 0;  
  430.         ctrl->bPreferedVersion = 0;  
  431.         ctrl->bMinVersion = 0;  
  432.         ctrl->bMaxVersion = 0;  
  433.       
  434.   
  435. done:  
  436.     kfree(data);  
  437.       
  438.     return (ret < 0) ? ret : 0;  
  439.   
  440.   
  441. /* 参考: uvc_v4l2_try_format ∕uvc_probe_video  
  442.  *       uvc_set_video_ctrl(video, probe, 1) 
  443.  */  
  444. static int myuvc_try_streaming_params(struct myuvc_streaming_control *ctrl)  
  445.   
  446.     __u8 *data;  
  447.     __u16 size;  
  448.     int ret;  
  449.     __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;  
  450.     unsigned int pipe;  
  451.       
  452.     memset(ctrl, 0, sizeof *ctrl);  
  453.       
  454.     ctrl->bmHint = 1;    /* dwFrameInterval */  
  455.     ctrl->bFormatIndex = 1;  
  456.     ctrl->bFrameIndex  = frame_idx + 1;  
  457.     ctrl->dwFrameInterval = 333333;  
  458.   
  459.   
  460.     size = uvc_version >= 0x0110 ? 34 : 26;  
  461.     data = kzalloc(size, GFP_KERNEL);  
  462.     if (data == NULL)  
  463.         return -ENOMEM;  
  464.   
  465.     *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);  
  466.     data[2] = ctrl->bFormatIndex;  
  467.     data[3] = ctrl->bFrameIndex;  
  468.     *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);  
  469.     *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);  
  470.     *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate);  
  471.     *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);  
  472.     *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);  
  473.     *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);  
  474.     put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);  
  475.     put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);  
  476.   
  477.     if (size == 34)   
  478.         put_unaligned_le32(ctrl->dwClockFrequency, &data[26]);  
  479.         data[30] = ctrl->bmFramingInfo;  
  480.         data[31] = ctrl->bPreferedVersion;  
  481.         data[32] = ctrl->bMinVersion;  
  482.         data[33] = ctrl->bMaxVersion;  
  483.       
  484.   
  485.     pipe = (SET_CUR & 0x80) ? usb_rcvctrlpipe(myuvc_udev, 0)  
  486.                   : usb_sndctrlpipe(myuvc_udev, 0);  
  487.     type |= (SET_CUR & 0x80) ? USB_DIR_IN : USB_DIR_OUT;  
  488.   
  489.     ret = usb_control_msg(myuvc_udev, pipe, SET_CUR, type, VS_PROBE_CONTROL << 8,  
  490.             0 << 8 | myuvc_streaming_intf, data, size, 5000);  
  491.   
  492.     kfree(data);  
  493.       
  494.     return (ret < 0) ? ret : 0;  
  495.       
  496.   
  497.   
  498.   
  499. /* 参考: uvc_v4l2_try_format ∕uvc_probe_video  
  500.  *       uvc_set_video_ctrl(video, probe, 1) 
  501.  */  
  502. static int myuvc_set_streaming_params(struct myuvc_streaming_control *ctrl)  
  503.   
  504.     __u8 *data;  
  505.     __u16 size;  
  506.     int ret;  
  507.     __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;  
  508.     unsigned int pipe;  
  509.       
  510.     size = uvc_version >= 0x0110 ? 34 : 26;  
  511.     data = kzalloc(size, GFP_KERNEL);  
  512.     if (data == NULL)  
  513.         return -ENOMEM;  
  514.   
  515.     *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);  
  516.     data[2] = ctrl->bFormatIndex;  
  517.     data[3] = ctrl->bFrameIndex;  
  518.     *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);  
  519.     *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);  
  520.     *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate);  
  521.     *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);  
  522.     *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);  
  523.     *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);  
  524.     put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);  
  525.     put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);  
  526.   
  527.     if (size == 34)   
  528.         put_unaligned_le32(ctrl->dwClockFrequency, &data[26]);  
  529.         data[30] = ctrl->bmFramingInfo;  
  530.         data[31] = ctrl->bPreferedVersion;  
  531.         data[32] = ctrl->bMinVersion;  
  532.         data[33] = ctrl->bMaxVersion;  
  533.       
  534.   
  535.     pipe = (SET_CUR & 0x80) ? usb_rcvctrlpipe(myuvc_udev, 0)  
  536.                   : usb_sndctrlpipe(myuvc_udev, 0);  
  537.     type |= (SET_CUR & 0x80) ? USB_DIR_IN : USB_DIR_OUT;  
  538.   
  539.     ret = usb_control_msg(myuvc_udev, pipe, SET_CUR, type, VS_COMMIT_CONTROL << 8,  
  540.             0 << 8 | myuvc_streaming_intf, data, size, 5000);  
  541.   
  542.     kfree(data);  
  543.       
  544.     return (ret < 0) ? ret : 0;  
  545.       
  546.   
  547.   
  548. static void myuvc_uninit_urbs(void)  
  549.   
  550.     int i;  
  551.     for (i = 0; i < MYUVC_URBS; ++i)   
  552.         if (myuvc_queue.urb_buffer[i])  
  553.           
  554.             usb_buffer_free(myuvc_udev, myuvc_queue.urb_size, myuvc_queue.urb_buffer[i], myuvc_queue.urb_dma[i]);  
  555.             myuvc_queue.urb_buffer[i] = NULL;  
  556.           
  557.   
  558.         if (myuvc_queue.urb[i])  
  559.           
  560.             usb_free_urb(myuvc_queue.urb[i]);  
  561.             myuvc_queue.urb[i] = NULL;  
  562.           
  563.       
  564.   
  565.   
  566. /* 参考: uvc_video_complete / uvc_video_decode_isoc */  
  567. static void myuvc_video_complete(struct urb *urb)  
  568.   
  569.     u8 *src;  
  570.     u8 *dest;  
  571.     int ret, i;  
  572.     int len;  
  573.     int maxlen;  
  574.     int nbytes;  
  575.     struct myuvc_buffer *buf;  
  576.     static int fid;  
  577.     static int wake_cnt = 0;  
  578.   
  579.     // 要修改影像資料,必須先宣告一個特別型態的指標變數,才能正確存取記憶體中的資料  
  580.     unsigned char *point_mem;  
  581.     static unsigned char *mem_temp = NULL;  
  582.   
  583.     // 初始化暫存用的記憶體位置  
  584.     static unsigned int nArrayTemp_Size = 1000;  
  585.   
  586.     u8* mem;  
  587.     int data_len;  
  588.       
  589.     switch (urb->status)   
  590.     case 0:  
  591.         break;  
  592.   
  593.     default:  
  594.         printk("Non-zero status (%d) in video "  
  595.             "completion handler.\\n", urb->status);  
  596.         return;  
  597.       
  598.   
  599.     /* 如果irqqueue队列不空的话,从irqqueue队列中取出第1个缓冲区,用于存放urb的数据 */  
  600.     if (!list_empty(&myuvc_queue.irqqueue))  
  601.       
  602.         buf = list_first_entry(&myuvc_queue.irqqueue, struct myuvc_buffer, irq);  
  603.       
  604.     else  
  605.       
  606.         /* 什么情况下会导致irqqueue队列为空呢? 
  607.          * usb设备填充数据太快,但是应用程序没能及时处理 
  608.          */  
  609.         buf = NULL;  
  610.       
  611.       
  612.     /* 开始处理urb中的每一个小包 */  
  613.     for (i = 0; i < urb->number_of_packets; ++i)   
  614.         if (urb->iso_frame_desc[i].status < 0)   
  615.             //printk("USB isochronous frame "  
  616.             //  "lost (%d).\\n", urb->iso_frame_desc[i].status);  
  617.             continue;  
  618.           
  619.   
  620.         src  = urb->transfer_buffer + urb->iso_frame_desc[i].offset;  
  621.   
  622.   
  623.         len = urb->iso_frame_desc[i].actual_length;  
  624.         /* 判断数据是否有效 */  
  625.         /* URB数据含义: 
  626.          * data[0] : 头部长度 
  627.          * data[1] : 错误状态 
  628.          */  
  629.         if (len < 2 || src[0] < 2 || src[0] > len)  
  630.             continue;  
  631.           
  632.         /* Skip payloads marked with the error bit ("error frames"). */  
  633.         if (src[1] & UVC_STREAM_ERR)   
  634.             //printk("Dropping payload (error bit set).\\n");  
  635.             continue;  
  636.           
  637.   
  638.         /* 根据ip2970/ip2977厂家提供的修改手册,如果想要支持ip2970/ip2977就必须 
  639.          * 添加如下代码  
  640.          */  
  641.         if (myuvc_udev->descriptor.idVendor == 0x1B3B)  
  642.           
  643.             if ( len >= 16 ) // have data in buffer  
  644.               
  645.                 // 資料必須從data[12]開始判斷,是因為前面的資料是封包專用  
  646.                 if ( (src[12]==0xFF && src[13]==0xD8 && src[14]==0xFF) ||  
  647.                     (src[12]==0xD8 && src[13]==0xFF && src[14]==0xC4))   
  648.                   
  649.                     if(last_fid)  
  650.                         fid &= ~UVC_STREAM_FID;  
  651.                     else  
  652.                         fid |= UVC_STREAM_FID;  
  653.                   
  654.               
  655.           
  656.         else  
  657.           
  658.             fid = src[1] & UVC_STREAM_FID;  
  659.           
  660.   
  661.         /* Store the payload FID bit and return immediately when the buffer is 
  662.          * NULL. 
  663.          */  
  664.         if (buf == NULL)   
  665.             last_fid = fid;  
  666.             continue;  
  667.           
  668.   
  669.         /* 根据FID判断当前帧的数据是否结束 */  
  670.         /* VIDEOBUF_ACTIVE表示正在接收数据,buf->state!= VIDEOBUF_ACTIVE, 表示"之前还未接收数据",  
  671.          * 因此就是说即将接收数据 
  672.         */    
  673.         if (buf->state != VIDEOBUF_ACTIVE)            
  674.             if (fid == last_fid)   
  675.                 /* 既然你刚开始接收数据, 那么FID应该是一个新的值,不应该等于原来的last_fid */  
  676.                 continue;  
  677.               
  678.   
  679.             /* 表示开始接收第1个数据 */  
  680.             buf->state = VIDEOBUF_ACTIVE;  
  681.           
  682.   
  683.         /* fid表示当前的fid。 
  684.          * fid != last_fid 表示开始新一帧了,当前的buffer已经被填充完了。 
  685.          * 这个地方是从fid来判断是否一帧数据已经结束,下面还有从数据是否填充不下了来 
  686.          * 强制认为一帧数据已经结束 
  687.          */  
  688.         if (fid != last_fid && buf->buf.bytesused != 0)   
  689.             buf->state = VIDEOBUF_DONE;  
  690.   
  691.             /* 从队列中删除, 唤醒进程 */  
  692.             list_del(&buf->irq);  
  693.             wake_up(&buf->wait);  
  694.   
  695.             mem = myuvc_queue.mem + buf->buf.m.offset;  
  696.             data_len = buf->buf.bytesused;  
  697.             //printk("wake_up %d : %s %d, start data: %02x %02x, end data: %02x %02x", wake_cnt++, __FUNCTION__, __LINE__, mem[0], mem[1], mem[data_len - 2], mem[data_len - 1]);  
  698.   
  699.             /* 取出下一个buf */  
  700.             if (!list_empty(&myuvc_queue.irqqueue))  
  701.               
  702.                 buf = list_first_entry(&myuvc_queue.irqqueue, struct myuvc_buffer, irq);  
  703.               
  704.             else  
  705.               
  706.                 buf = NULL;  
  707.               
  708.             continue;  
  709.           
  710.         last_fid = fid;  
  711.   
  712.         dest = myuvc_queue.mem + buf->buf.m.offset + buf->buf.bytesused;  
  713.   
  714.         /* 除去头部后的数据长度 */  
  715.         len -= src[0];  
  716.   
  717.         /* 缓冲区最多还能存多少数据 */  
  718.         maxlen = buf->buf.length - buf->buf.bytesused;  
  719.         nbytes = min(len, maxlen);  
  720.   
  721.         /* 复制数据 */  
  722.         memcpy(dest, src + src[0], nbytes);  
  723.         buf->buf.bytesused += nbytes;  
  724.   
  725.         /* ip2970/ip2977 */  
  726.         if (myuvc_udev->descriptor.idVendor == 0x1B3B)  
  727.           
  728.             if(mem_temp == NULL)   
  729.                 mem_temp = kmalloc(nArrayTemp_Size, GFP_KERNEL);  
  730.               
  731.             else if(nArrayTemp_Size <= nbytes) // 當收到的資料長度大於上一次的資料長度,則重新分配所需的空間+  
  732.                 kfree(mem_temp);  
  733.                 nArrayTemp_Size += 500;  
  734.                 mem_temp = kmalloc(nArrayTemp_Size, GFP_KERNEL);  
  735.               
  736.             memset(mem_temp, 0x00, nArrayTemp_Size);  
  737.               
  738.             // 指向資料儲存的記憶體位置  
  739.             point_mem = (unsigned char *)dest;  
  740.             if( *(point_mem) == 0xD8 && *(point_mem + 1) == 0xFF && *(point_mem + 2) == 0xC4)  
  741.                 memcpy( mem_temp + 1, point_mem, nbytes);  
  742.                 mem_temp[0] = 0xFF;  
  743.                 memcpy(point_mem, mem_temp, nbytes + 1);  
  744.               
  745.           
  746.   
  747.   
  748.   
  749.         /* 判断一帧数据是否已经全部接收到  
  750.          * 如果数据已经满了,就强制认为已经结束了 
  751.          */  
  752.         if (len > maxlen)   
  753.             buf->state = VIDEOBUF_DONE;  
  754.           
  755.           
  756.         /* Mark the buffer as done if the EOF marker is set. */  
  757.         if (src[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0)   
  758.            // printk("Frame complete (EOF found).\\n");  
  759.             //if (len == 0)  
  760.            //     printk("EOF in empty payload.\\n");  
  761.             buf->state = VIDEOBUF_DONE;  
  762.           
  763.   
  764.         /* 当接收完一帧数据,  
  765.          * 从irqqueue中删除这个缓冲区 
  766.          * 唤醒等待数据的进程  
  767.          */  
  768.         if (buf->state == VIDEOBUF_DONE ||  
  769.             buf->state == VIDEOBUF_ERROR)  
  770.           
  771.             list_del(&buf->irq);  
  772.             wake_up(&buf->wait);  
  773.   
  774.             mem = myuvc_queue.mem + buf->buf.m.offset;  
  775.             data_len = buf->buf.bytesused;  
  776.             //printk("wake_up %d : %s %d, start data: %02x %02x, end data: %02x %02x", wake_cnt++, __FUNCTION__, __LINE__, mem[0], mem[1], mem[data_len - 2], mem[data_len - 1]);  
  777.               
  778.             /* 取出下一个buf */  
  779.             if (!list_empty(&myuvc_queue.irqqueue))  
  780.               
  781.                 buf = list_first_entry(&myuvc_queue.irqqueue, struct myuvc_buffer, irq);  
  782.               
  783.             else  
  784.               
  785.                 buf = NULL;  
  786.               
  787.           
  788.   
  789.       
  790.   
  791.   
  792.     /* 再次提交URB */  
  793.     if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0)   
  794.         printk("Failed to resubmit video URB (%d).\\n", ret);  
  795.       
  796.   
  797.   
  798. /* 参考: uvc_init_video_isoc */  
  799. static int myuvc_alloc_init_urbs(void)  
  800.   
  801.     u16 psize;  
  802.     u32 size;  
  803.     int npackets;  
  804.     int i;  
  805.     int j;  
  806.   
  807.     struct urb *urb;  
  808.   
  809.     psize = wMaxPacketSize; /* 实时传输端点一次能传输的最大字节数 */  
  810.     size  = myuvc_params.dwMaxVideoFrameSize;  /* 一帧数据的最大长度 */  
  811.     npackets = DIV_ROUND_UP(size, psize);  
  812.     if (npackets > 32)  
  813.         npackets = 32;  
  814.   
  815.     size = myuvc_queue.urb_size = psize * npackets;  
  816.       
  817.     for (i = 0; i < MYUVC_URBS; ++i)   
  818.         /* 1. 分配usb_buffers */  
  819.           
  820.         myuvc_queue.urb_buffer[i] = usb_buffer_alloc(  
  821.             myuvc_udev, size,  
  822.             GFP_KERNEL | __GFP_NOWARN, &myuvc_queue.urb_dma[i]);  
  823.   
  824.         /* 2. 分配urb */  
  825.         myuvc_queue.urb[i] = usb_alloc_urb(npackets, GFP_KERNEL);  
  826.   
  827.         if (!myuvc_queue.urb_buffer[i] || !myuvc_queue.urb[i])  
  828.           
  829.             myuvc_uninit_urbs();  
  830.             return -ENOMEM;  
  831.           
  832.   
  833.       
  834.   
  835.   
  836.     /* 3. 设置urb */  
  837.     for (i = 0; i < MYUVC_URBS; ++i)   
  838.         urb = myuvc_queue.urb[i];  
  839.           
  840.         urb->dev = myuvc_udev;  
  841.         urb->context = NULL;  
  842.         urb->pipe = usb_rcvisocpipe(myuvc_udev,myuvc_bEndpointAddress);  
  843.         urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;  
  844.         urb->interval = 1;  
  845.         urb->transfer_buffer = myuvc_queue.urb_buffer[i];  
  846.         urb->transfer_dma = myuvc_queue.urb_dma[i];  
  847.         urb->complete = myuvc_video_complete;  
  848.         urb->number_of_packets = npackets;  
  849.         urb->transfer_buffer_length = size;  
  850.           
  851.         for (j = 0; j < npackets; ++j)   
  852.             urb->iso_frame_desc[j].offset = j * psize;  
  853.             urb->iso_frame_desc[j].length = psize;  
  854.           
  855.       
  856.       
  857.       
  858.     return 0;  
  859.   
  860.   
  861. /* A11 启动传输  
  862.  * 参考: uvc_video_enable(video, 1): 
  863.  *           uvc_commit_video 
  864.  *           uvc_init_video 
  865.  */  
  866. static int myuvc_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)  
  867.   
  868.     int ret;  
  869. 以上是关于自己写的uvc驱动支持IP2977/ip2970的主要内容,如果未能解决你的问题,请参考以下文章

    统信操作系统 摄像头驱动程序

    RT5350的uvc驱动支持yuv格式摄像头成功

    28从零写UVC驱动之实现设置属性

    有人用arm开发板用UVC驱动的USB camera采集到640*480的视频过吗?

    高手进 VB 支持 UVC摄像头吗?

    UVC 驱动调用过程与驱动框架的简单分析