1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/webcam_private/v4l2_webcam.h"
8 #include <linux/uvcvideo.h>
9 #include <linux/videodev2.h>
11 #include <sys/ioctl.h>
14 #include "base/posix/eintr_wrapper.h"
16 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
17 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
18 #define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE+34)
20 // GUID of the Extension Unit for Logitech CC3300e motor control:
21 // {212de5ff-3080-2c4e-82d9-f587d00540bd}
22 #define UVC_GUID_LOGITECH_CC3000E_MOTORS \
23 {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \
24 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd}
26 #define LOGITECH_MOTORCONTROL_PANTILT_CMD 2
29 const int kLogitechMenuIndexGoHome
= 2;
31 const uvc_menu_info kLogitechCmdMenu
[] = {
32 {1, "Set Preset"}, {2, "Get Preset"}, {3, "Go Home"}
35 const uvc_xu_control_mapping kLogitechCmdMapping
= {
38 UVC_GUID_LOGITECH_CC3000E_MOTORS
,
39 LOGITECH_MOTORCONTROL_PANTILT_CMD
,
43 UVC_CTRL_DATA_TYPE_ENUM
,
44 const_cast<uvc_menu_info
*>(&kLogitechCmdMenu
[0]),
45 arraysize(kLogitechCmdMenu
),
49 namespace extensions
{
51 V4L2Webcam::V4L2Webcam(const std::string
& device_id
) : device_id_(device_id
) {
54 V4L2Webcam::~V4L2Webcam() {
57 bool V4L2Webcam::Open() {
58 fd_
.reset(HANDLE_EINTR(open(device_id_
.c_str(), 0)));
59 return fd_
.is_valid();
62 bool V4L2Webcam::EnsureLogitechCommandsMapped() {
64 HANDLE_EINTR(ioctl(fd_
.get(), UVCIOC_CTRL_MAP
, &kLogitechCmdMapping
));
65 // If mapping is successful or it's already mapped, this is a Logitech
67 // NOTE: On success, occasionally EFAULT is returned. On a real error,
68 // ENOMEM, EPERM, EINVAL, or EOVERFLOW should be returned.
69 return res
>= 0 || errno
== EEXIST
|| errno
== EFAULT
;
72 bool V4L2Webcam::SetWebcamParameter(int fd
, uint32_t control_id
, int value
) {
73 struct v4l2_control v4l2_ctrl
= {control_id
, value
};
74 int res
= HANDLE_EINTR(ioctl(fd
, VIDIOC_S_CTRL
, &v4l2_ctrl
)) >= 0;
78 bool V4L2Webcam::GetWebcamParameter(int fd
, uint32_t control_id
, int* value
) {
79 struct v4l2_control v4l2_ctrl
= {control_id
};
81 if (HANDLE_EINTR(ioctl(fd
, VIDIOC_G_CTRL
, &v4l2_ctrl
)))
84 *value
= v4l2_ctrl
.value
;
88 void V4L2Webcam::Reset(bool pan
, bool tilt
, bool zoom
) {
90 if (EnsureLogitechCommandsMapped()) {
91 SetWebcamParameter(fd_
.get(), V4L2_CID_PANTILT_CMD
,
92 kLogitechMenuIndexGoHome
);
95 struct v4l2_control v4l2_ctrl
= {V4L2_CID_PAN_RESET
};
96 HANDLE_EINTR(ioctl(fd_
.get(), VIDIOC_S_CTRL
, &v4l2_ctrl
));
100 struct v4l2_control v4l2_ctrl
= {V4L2_CID_TILT_RESET
};
101 HANDLE_EINTR(ioctl(fd_
.get(), VIDIOC_S_CTRL
, &v4l2_ctrl
));
107 const int kDefaultZoom
= 100;
108 SetWebcamParameter(fd_
.get(), V4L2_CID_ZOOM_ABSOLUTE
, kDefaultZoom
);
112 bool V4L2Webcam::GetPan(int* value
) {
113 return GetWebcamParameter(fd_
.get(), V4L2_CID_PAN_ABSOLUTE
, value
);
116 bool V4L2Webcam::GetTilt(int* value
) {
117 return GetWebcamParameter(fd_
.get(), V4L2_CID_TILT_ABSOLUTE
, value
);
120 bool V4L2Webcam::GetZoom(int* value
) {
121 return GetWebcamParameter(fd_
.get(), V4L2_CID_ZOOM_ABSOLUTE
, value
);
124 bool V4L2Webcam::SetPan(int value
) {
125 return SetWebcamParameter(fd_
.get(), V4L2_CID_PAN_ABSOLUTE
, value
);
128 bool V4L2Webcam::SetTilt(int value
) {
129 return SetWebcamParameter(fd_
.get(), V4L2_CID_TILT_ABSOLUTE
, value
);
132 bool V4L2Webcam::SetZoom(int value
) {
133 return SetWebcamParameter(fd_
.get(), V4L2_CID_ZOOM_ABSOLUTE
, value
);
136 bool V4L2Webcam::SetPanDirection(PanDirection direction
) {
137 int direction_value
= 0;
148 direction_value
= -1;
151 return SetWebcamParameter(fd_
.get(), V4L2_CID_PAN_SPEED
, direction_value
);
154 bool V4L2Webcam::SetTiltDirection(TiltDirection direction
) {
155 int direction_value
= 0;
166 direction_value
= -1;
169 return SetWebcamParameter(fd_
.get(), V4L2_CID_TILT_SPEED
, direction_value
);
172 } // namespace extensions