浏览代码

V4L/DVB (4243): Exploit new V4L control features in pvrusb2

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Mike Isely 19 年之前
父节点
当前提交
1d9f8461f1
共有 2 个文件被更改,包括 76 次插入2 次删除
  1. 5 0
      drivers/media/video/pvrusb2/pvrusb2-ctrl.c
  2. 71 2
      drivers/media/video/pvrusb2/pvrusb2-v4l2.c

+ 5 - 0
drivers/media/video/pvrusb2/pvrusb2-ctrl.c

@@ -230,6 +230,11 @@ unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
 		flags = cptr->info->get_v4lflags(cptr);
 	}
 
+	if (cptr->info->set_value) {
+		flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+	} else {
+		flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	}
 
 	return flags;
 }

+ 71 - 2
drivers/media/video/pvrusb2/pvrusb2-v4l2.c

@@ -518,7 +518,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 		struct pvr2_ctrl *cptr;
 		struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
 		ret = 0;
-		cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
+		if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+			cptr = pvr2_hdw_get_ctrl_nextv4l(
+				hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
+			if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
+		} else {
+			cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
+		}
 		if (!cptr) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 				   "QUERYCTRL id=0x%x not implemented here",
@@ -542,7 +548,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 			vc->step = 1;
 			break;
 		case pvr2_ctl_bool:
-			vc->type = V4L2_CTRL_TYPE_INTEGER;
+			vc->type = V4L2_CTRL_TYPE_BOOLEAN;
 			vc->minimum = 0;
 			vc->maximum = 1;
 			vc->step = 1;
@@ -593,6 +599,69 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
+	case VIDIOC_G_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		unsigned int idx;
+		int val;
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			ret = pvr2_ctrl_get_value(
+				pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
+			if (ret) {
+				ctls->error_idx = idx;
+				break;
+			}
+			/* Ensure that if read as a 64 bit value, the user
+			   will still get a hopefully sane value */
+			ctrl->value64 = 0;
+			ctrl->value = val;
+		}
+		break;
+	}
+
+	case VIDIOC_S_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		unsigned int idx;
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			ret = pvr2_ctrl_set_value(
+				pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
+				ctrl->value);
+			if (ret) {
+				ctls->error_idx = idx;
+				break;
+			}
+		}
+		break;
+	}
+
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		struct pvr2_ctrl *pctl;
+		unsigned int idx;
+		/* For the moment just validate that the requested control
+		   actually exists. */
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
+			if (!pctl) {
+				ret = -EINVAL;
+				ctls->error_idx = idx;
+				break;
+			}
+		}
+		break;
+	}
+
 	case VIDIOC_LOG_STATUS:
 	{
 		pvr2_hdw_trigger_module_log(hdw);