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;
}
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 =
ret = pwc_button_ctrl(pdev,
RESTORE_FACTORY_DEFAULTS_FORMATTER);
break;
+ case V4L2_CID_PAN_RELATIVE:
+ ret = pwc_set_motor(pdev);
+ break;
default:
ret = -EINVAL;
}
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];
};
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);