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