2八、從零寫UVC驅動之實現設置屬性

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_CTRLapp


2. 硬件上怎麼設置屬性?
2.1 UVC規範裏定義了哪些屬性 : uvc_ctrl.c裏數組: static struct uvc_control_info uvc_ctrls[]ide

{
.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,// 數據類型,用於用戶下發控制屬性的數據類型
       },ip

    uvc_control_mapping結構體 用來更加細緻地描述屬性get

  uvc_query_ctrl
    usb_control_msgit


舉例說明: 要設置亮度,怎麼操做?
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,
  },io

知道了:這個設備支持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

相關文章
相關標籤/搜索