[media] pwc: Add v4l2 controls for pan/tilt on Logitech QuickCam Orbit/Sphere
authorHans de Goede <hdegoede@redhat.com>
Sun, 3 Jul 2011 15:23:24 +0000 (12:23 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 27 Jul 2011 20:53:45 +0000 (17:53 -0300)
This makes the API for this:
1) v4l2 spec compliant
2) match that of the UVC Logitech QuickCam Sphere models

For now this operates in parellel to the sysfs interface for this, but the
intend is to deprecate the sysfs interface and remove it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h

index 8e0cc537e1e463605caaec42a2e277869446a5c8..d09413c44c86e543b48f4efc4fd7a143ae75c3cb 100644 (file)
@@ -165,7 +165,7 @@ static inline int send_video_command(struct pwc_device *pdev,
                buf, buflen);
 }
 
-static inline int send_control_msg(struct pwc_device *pdev,
+int send_control_msg(struct pwc_device *pdev,
        u8 request, u16 value, void *buf, int buflen)
 {
        return _send_control_msg(pdev,
index 537657283e794dd389976ce9817e93a1ac589a56..e9a0e94b9995003e26191583f4e91b8ba7690f56 100644 (file)
@@ -338,6 +338,22 @@ int pwc_init_controls(struct pwc_device *pdev)
        if (pdev->restore_factory)
                pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE;
 
+       if (!pdev->features & FEATURE_MOTOR_PANTILT)
+               return hdl->error;
+
+       /* Motor pan / tilt / reset */
+       pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
+       if (!pdev->motor_pan)
+               return hdl->error;
+       pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
+       pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RESET, 0, 0, 0, 0);
+       pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RESET, 0, 0, 0, 0);
+       v4l2_ctrl_cluster(4, &pdev->motor_pan);
+
        return hdl->error;
 }
 
@@ -764,6 +780,43 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
        return ret;
 }
 
+static int pwc_set_motor(struct pwc_device *pdev)
+{
+       int ret;
+       u8 buf[4];
+
+       buf[0] = 0;
+       if (pdev->motor_pan_reset->is_new)
+               buf[0] |= 0x01;
+       if (pdev->motor_tilt_reset->is_new)
+               buf[0] |= 0x02;
+       if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RESET_CONTROL_FORMATTER, buf, 1);
+               if (ret < 0)
+                       return ret;
+       }
+
+       memset(buf, 0, sizeof(buf));
+       if (pdev->motor_pan->is_new) {
+               buf[0] = pdev->motor_pan->val & 0xFF;
+               buf[1] = (pdev->motor_pan->val >> 8);
+       }
+       if (pdev->motor_tilt->is_new) {
+               buf[2] = pdev->motor_tilt->val & 0xFF;
+               buf[3] = (pdev->motor_tilt->val >> 8);
+       }
+       if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RELATIVE_CONTROL_FORMATTER,
+                                      buf, sizeof(buf));
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct pwc_device *pdev =
@@ -859,6 +912,9 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
                ret = pwc_button_ctrl(pdev,
                                      RESTORE_FACTORY_DEFAULTS_FORMATTER);
                break;
+       case V4L2_CID_PAN_RELATIVE:
+               ret = pwc_set_motor(pdev);
+               break;
        default:
                ret = -EINVAL;
        }
index e02dbf74515510c0046e56b7f6fb9bbe4fcf87f6..8f3607be5a71f99d9dabf0a235c8d6db705ad79a 100644 (file)
@@ -326,6 +326,13 @@ struct pwc_device
        struct v4l2_ctrl                *save_user;
        struct v4l2_ctrl                *restore_user;
        struct v4l2_ctrl                *restore_factory;
+       struct {
+               /* motor control cluster */
+               struct v4l2_ctrl        *motor_pan;
+               struct v4l2_ctrl        *motor_tilt;
+               struct v4l2_ctrl        *motor_pan_reset;
+               struct v4l2_ctrl        *motor_tilt_reset;
+       };
        /* CODEC3 models have both gain and exposure controlled by autogain */
        struct v4l2_ctrl                *autogain_expo_cluster[3];
 };
@@ -350,6 +357,8 @@ extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
 extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int send_control_msg(struct pwc_device *pdev,
+                           u8 request, u16 value, void *buf, int buflen);
 
 /* Control get / set helpers */
 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);