1. 先看APP以确定需要实现哪些接口
xawtv.c:
  grabber_scan
    ng_vid_open//根据链表的设置和读取可以在xawtv中找到是调用v4l2_driver.open
      v4l2_driver.open // v4l2_open
        get_device_capabilities(h);
          // 调用VIDIOC_QUERYCTRL ioctl确定是否支持某个属性
          /* controls */
          for (i = 0; i < MAX_CTRL; i++) {
            h->ctl[i].id = V4L2_CID_BASE+i;
            if (-1 == xioctl(h->fd, VIDIOC_QUERYCTRL, &h->ctl[i], EINVAL) ||
            (h->ctl[i].flags & V4L2_CTRL_FLAG_DISABLED))
            h->ctl[i].id = -1;//不支持会在这赋值-1,以后看到这个-1就表示不支持了
          }
怎么去获得/设置属性?
看drv0-v4l2.c
可见这2个函数:
v4l2_read_attr : VIDIOC_G_CTRL
v4l2_write_attr : VIDIOC_S_CTRL

所以: 视频驱动里要实现3个ioctl:
VIDIOC_QUERYCTRL
VIDIOC_G_CTRL
VIDIOC_S_CTRL

2. 硬件上怎么设置属性?
2.1 UVC规范里定义了哪些属性 : uvc_ctrl.c里数组: static struct uvc_control_info uvc_ctrls[]

{
.entity = UVC_GUID_UVC_PROCESSING, // 属于哪了个entity(比如PU)
.selector = PU_BRIGHTNESS_CONTROL, // 用于亮度
.index = 0, // 对应Processing Unit Descriptor的bmControls[0]
.size = 2, // 发给硬件的数据长度为2字节
.flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
| UVC_CONTROL_RESTORE,
},

里面的每一项都对应一个属性,entity表示那个单元,这里是表示PU,selector 用于区分PU里面的那个功能属性,index是这个功能属性的位置

2.2 我们的设备支持哪些属性
这需要去看描述符, 比如 Processing Unit Descriptor的bmControls的值为7f 14
可知BIT0为1,表示支持BRIGHTNESS

在代码里:
uvc_drvier.c
uvc_ctrl_init_device
  // 对于每一个entity(IT,PU,SU,OT等)
    list_for_each_entry(entity, &dev->entities, list) {
      // 取出bmControls
      bmControls = ....

      // 计算bmControls里位值为1的个数,就是支持的属性个数
      ncontrols += hweight8(bmControls[i]);

      // 为每一个属性分配一个struct uvc_control,这些ctrl都在controls指向的buf中
      entity->controls = kzalloc(ncontrols *sizeof(*ctrl))

      // 设置这些struct uvc_control
      ctrl = entity->controls;
      for (...)
      {
        ctrl->entity = entity;
        ctrl->index = i;
      }

      // 把uvc_control和uvc_control_info挂构
      uvc_ctrl_add_ctrl(dev, info);
        ctrl->info = 某个uvc_control_info数组项(同属于一个entity, index相同)

2.3 怎么去操作这些属性
  参考 uvc_query_v4l2_ctrl(应用程序会传下来一个id值,程序根据这个id值找到mapping结构体)
  uvc_find_control
    找到一个uvc_control_mapping结构体: uvc_ctrl.c里有static struct uvc_control_mapping uvc_ctrl_mappings[]
      {
        .id = V4L2_CID_BRIGHTNESS, // APP根据ID来找到对应的属性
        .name = "Brightness",
        .entity = UVC_GUID_UVC_PROCESSING, // 属于哪了个entity(比如PU)
        .selector = PU_BRIGHTNESS_CONTROL, // 用于亮度
        .size = 16, // 数据占多少位
        .offset = 0, // 从哪位开始
        .v4l2_type = V4L2_CTRL_TYPE_INTEGER, // 属性类别,用于应用图形显示怎么控制属性,是下拉还是滑动图标等
        .data_type = UVC_CTRL_DATA_TYPE_SIGNED,// 数据类型,用于用户下发控制属性的数据类型
       },

    uvc_control_mapping结构体 用来更加细致地描述属性

  uvc_query_ctrl
    usb_control_msg

举例说明: 要设置亮度,怎么操作?
a. 根据PU的描述符的bmControls, 从它的bit0等于1知道它支持调节亮度
b. 在uvc_ctrls数组中根据entity和index找到这一项:
  {
    .entity = UVC_GUID_UVC_PROCESSING,
    .selector = PU_BRIGHTNESS_CONTROL,
    .index = 0,
    .size = 2,
    .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
        | UVC_CONTROL_RESTORE,
  },

知道了:这个设备支持SET_CUR, GET_CUR, GET_MIN等
要设置时,可以向PU的selector发数据, 发的数据是2字节

c. 在uvc_ctrl_mappings数组中根据ID找到对应的数组项
从而知道了更加细致的信息,
然后使用usb_control_msg读写数据

3. 怎么写代码?
实现3个ioctl: vidioc_queryctrl/vidioc_g_ctrl/vidioc_s_ctrl
vidioc_queryctrl : 发起USB控制传输获得亮度的最小值、最大值、默认值、步进值
vidioc_s_ctrl : 把APP传入的亮度值通过USB传输发给硬件
vidioc_g_ctrl : 发起USB传输获得当前亮度值

要点:数据发给谁?发给usb_device的
            VideoControl Interface
              里面的Processing Unit
                里面的PU_BRIGHTNESS_CONTROL

28、从零写UVC驱动之实现设置属性的更多相关文章

  1. 27、从零写UVC驱动之分析数据传输(设置ubuntu通过串口打印,指定打印到文件,ubuntu切换root用户)

    A. 设置ubuntu让它从串口0输出printk信息a. 设置vmware添加serial port, 使用文件作为串口(在vmware中设置,文件是保存在windows中)b. 启动ubuntu, ...

  2. 26、从零写UVC驱动之分析描述符

    指令:lsusb 可以查看usb设备的描述符信息,当然lsusb指令要带一些参数 一个usb设备有多个config配置+设备描述符,一个config有多个接口和association.config描述 ...

  3. Linux摄像头驱动学习之:(三)从零写虚拟驱动(仿照vivi.c)

    本篇仿照vivi.c 写虚拟视频驱动,代码(myvivi.c+fillbuf.c+Makefile)如下: //==========================myvivi.c========== ...

  4. 13、虚拟驱动vivi.c注册过程分析及怎么写V4L2驱动及启动过程

    UVC设备也是一个usb设备,在uvc_driver.c中的init函数会调用usb_register注册,根据id_table发送可支持的设备后调用probe函数,其会去uvc_register_c ...

  5. 【原理】从零编写ILI9341驱动全过程(基于Arduino)

    最近在淘宝入手了一块ILI9341彩色屏幕,支持320x240分辨率.之前一直很好奇这类单片机驱动的彩色屏幕的原理,就打算自己写一个驱动,从电流层面操控ILI9341屏幕.话不多说,我们开始吧( ̄▽ ̄ ...

  6. 手把手教你从零写一个简单的 VUE

    本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...

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

    内核:Linux-3.4.2 驱动:drivers\media\video\uvc\uvc_driver.c UVC 驱动整体调用流程: /* 打开设备描述符 */ 1. open: uvc_v4l2 ...

  8. 7、基于嵌入式Linux的视频采集系统---UVC驱动模型介绍

    UVC 即 usb video class.USB协议中,除了通用的软硬件电气接口规范等,还包含了各种各样的Class协议,用来为不同的功能定义各自的标准接口和具体的总线上的数据交互格式和内容.这些C ...

  9. 手把手教你从零写一个简单的 VUE--模板篇

    教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...

随机推荐

  1. 获取session中存储的所有值的方法

    记录一个获取系统中session存储的对象都有哪些的方法 HttpSession session = request.getSession(); for ( Enumeration e = sessi ...

  2. px、em、rem、vw、vh、vm、rpx这些单位的

    px是像素 em是参考父元素的font-size的倍数 rem是参考根元素的font-size 常用于响应式,一般会让html的font-size:625%,body的大小为.16rem.这样1rem ...

  3. linux中内存泄漏的检測(五)记录内存泄漏的代码

    到眼下为止,先后通过wrap malloc.new函数重载和计算指针内存大小的方法.基本上满足了对内存泄漏检測的须要. 假设发现了内存泄漏.那么就要找到内存泄漏的地方而且修正它了. 茫茫代码.如何去找 ...

  4. 写了个去重复文件的 PHP 脚本,

    写了个去重复文件的 PHP 脚本点击打开链接 把各个零散网盘.邮箱和服务器上的文件,三台电脑上的文件收集在新硬盘里,然后清空了网络和电脑上的文件.才发现这个文件不能这里放点,那里存点,到时候不知道在哪 ...

  5. 27.mutex跨进程通信

    创建互斥量mutex HANDLE mutex = CreateMutexA(NULL, TRUE, name); 根据id打开mutex HANDLE mutex = OpenMutexA(MUTE ...

  6. jQuery自定义插件规范

    <ul class="list"> <li>导航列表 <ul class="nav"> <li>导航列表1< ...

  7. android 仿ios 对话框已封装成工具类

    对话框 在android中是一种非经常见的交互提示用户的方式,可是非常多产品狗都叫我们这些做android的仿ios,搞的我们android程序猿非常苦逼,凭什么效果老是仿ios,有没有一点情怀,只是 ...

  8. C语言速度优化之指针赋值与if推断

    近期在写的一个项目须要优化处理速度,我写了一下程序来測试指针赋值与指针推断的速度比較.结果让我大吃一惊. #include <stdio.h> #include <stdlib.h& ...

  9. 51 nod 1189 阶乘分数

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1189 题目思路: 1/n! = 1/x +1/y ==> ...

  10. 看好腾讯,鄙视百度(腾讯的核心竞争力,不是超过10亿的QQ的注册用户,也不是某一项产品、技术方面优势,而是“耐心”:懂得在合适的时间推出合适的产品。”)

    百度,自始至终只是一个低劣的模仿者,且一切向前看,完全违背了一个搜索引擎所应该遵循的基本原则.谁给的钱多就能搜着谁,这跟贩毒有什么区别? 腾讯也在模仿别人,但是,它是模仿然后超越.在中国互联网发展历史 ...