00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sys/ioctl.h>
00024 #include <sys/time.h>
00025 #include <getopt.h>
00026 #include <errno.h>
00027 #include <pthread.h>
00028 #include <stdio.h>
00029
00030 #include <linux/videodev2.h>
00031
00032 #include "utils.h"
00033 #include "dynctrl.h"
00034
00035
00036 #define LENGTH_OF_XU_CTR (6)
00037 #define LENGTH_OF_XU_MAP (10)
00038
00039 static struct uvc_xu_control_info xu_ctrls[] = {
00040 {
00041 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00042 .selector = XU_MOTORCONTROL_PANTILT_RELATIVE,
00043 .index = 0,
00044 .size = 4,
00045 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00046 },
00047 {
00048 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00049 .selector = XU_MOTORCONTROL_PANTILT_RESET,
00050 .index = 1,
00051 .size = 1,
00052 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00053 },
00054 {
00055 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00056 .selector = XU_MOTORCONTROL_FOCUS,
00057 .index = 2,
00058 .size = 6,
00059 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00060 },
00061 {
00062 .entity = UVC_GUID_LOGITECH_VIDEO_PIPE,
00063 .selector = XU_COLOR_PROCESSING_DISABLE,
00064 .index = 4,
00065 .size = 1,
00066 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00067 },
00068 {
00069 .entity = UVC_GUID_LOGITECH_VIDEO_PIPE,
00070 .selector = XU_RAW_DATA_BITS_PER_PIXEL,
00071 .index = 7,
00072 .size = 1,
00073 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00074 },
00075 {
00076 .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL,
00077 .selector = XU_HW_CONTROL_LED1,
00078 .index = 0,
00079 .size = 3,
00080 .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE
00081 },
00082
00083 };
00084
00085
00086 static struct uvc_xu_control_mapping xu_mappings[] = {
00087 {
00088 .id = V4L2_CID_PAN_RELATIVE,
00089 .name = "Pan (relative)",
00090 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00091 .selector = XU_MOTORCONTROL_PANTILT_RELATIVE,
00092 .size = 16,
00093 .offset = 0,
00094 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00095 .data_type = UVC_CTRL_DATA_TYPE_SIGNED
00096 },
00097 {
00098 .id = V4L2_CID_TILT_RELATIVE,
00099 .name = "Tilt (relative)",
00100 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00101 .selector = XU_MOTORCONTROL_PANTILT_RELATIVE,
00102 .size = 16,
00103 .offset = 16,
00104 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00105 .data_type = UVC_CTRL_DATA_TYPE_SIGNED
00106 },
00107 {
00108 .id = V4L2_CID_PAN_RESET,
00109 .name = "Pan Reset",
00110 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00111 .selector = XU_MOTORCONTROL_PANTILT_RESET,
00112 .size = 1,
00113 .offset = 0,
00114 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00115 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00116 },
00117 {
00118 .id = V4L2_CID_TILT_RESET,
00119 .name = "Tilt Reset",
00120 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00121 .selector = XU_MOTORCONTROL_PANTILT_RESET,
00122 .size = 1,
00123 .offset = 1,
00124 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00125 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00126 },
00127 {
00128 .id = V4L2_CID_PANTILT_RESET_LOGITECH,
00129 .name = "Pan/tilt Reset",
00130 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00131 .selector = XU_MOTORCONTROL_PANTILT_RESET,
00132 .size = 8,
00133 .offset = 0,
00134 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00135 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00136 },
00137 {
00138 .id = V4L2_CID_FOCUS_LOGITECH,
00139 .name = "Focus (absolute)",
00140 .entity = UVC_GUID_LOGITECH_MOTOR_CONTROL,
00141 .selector = XU_MOTORCONTROL_FOCUS,
00142 .size = 8,
00143 .offset = 0,
00144 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00145 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00146 },
00147 {
00148 .id = V4L2_CID_LED1_MODE_LOGITECH,
00149 .name = "LED1 Mode",
00150 .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL,
00151 .selector = XU_HW_CONTROL_LED1,
00152 .size = 8,
00153 .offset = 0,
00154 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00155 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00156 },
00157 {
00158 .id = V4L2_CID_LED1_FREQUENCY_LOGITECH,
00159 .name = "LED1 Frequency",
00160 .entity = UVC_GUID_LOGITECH_USER_HW_CONTROL,
00161 .selector = XU_HW_CONTROL_LED1,
00162 .size = 8,
00163 .offset = 16,
00164 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00165 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00166 },
00167 {
00168 .id = V4L2_CID_DISABLE_PROCESSING_LOGITECH,
00169 .name = "Disable video processing",
00170 .entity = UVC_GUID_LOGITECH_VIDEO_PIPE,
00171 .selector = XU_COLOR_PROCESSING_DISABLE,
00172 .size = 8,
00173 .offset = 0,
00174 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
00175 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN
00176 },
00177 {
00178 .id = V4L2_CID_RAW_BITS_PER_PIXEL_LOGITECH,
00179 .name = "Raw bits per pixel",
00180 .entity = UVC_GUID_LOGITECH_VIDEO_PIPE,
00181 .selector = XU_RAW_DATA_BITS_PER_PIXEL,
00182 .size = 8,
00183 .offset = 0,
00184 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
00185 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED
00186 },
00187
00188 };
00189
00190 int initDynCtrls(int fd)
00191 {
00192 int i = 0;
00193 int err = 0;
00194
00195 for(i = 0; i < LENGTH_OF_XU_CTR; i++) {
00196 fprintf(stderr, "Adding control for %s\n", xu_mappings[i].name);
00197 if((err = xioctl(fd, UVCIOC_CTRL_ADD, &xu_ctrls[i])) < 0) {
00198 if(errno != EEXIST)
00199 perror("UVCIOC_CTRL_ADD - Error");
00200 else
00201 perror("Control exists");
00202 }
00203 }
00204
00205 for(i = 0; i < LENGTH_OF_XU_MAP; i++) {
00206 fprintf(stderr, "mapping control for %s\n", xu_mappings[i].name);
00207 if((err = xioctl(fd, UVCIOC_CTRL_MAP, &xu_mappings[i])) < 0) {
00208 if(errno != EEXIST)
00209 perror("UVCIOC_CTRL_MAP - Error");
00210 else
00211 perror("Mapping exists");
00212 }
00213 }
00214 return 0;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 int uvcPanTilt(int dev, int pan, int tilt, int reset) {
00226 struct v4l2_ext_control xctrls[2];
00227 struct v4l2_ext_controls ctrls;
00228
00229 if (reset) {
00230 xctrls[0].id = V4L2_CID_PANTILT_RESET_LOGITECH;
00231 xctrls[0].value = 3;
00232
00233 ctrls.count = 1;
00234 ctrls.controls = xctrls;
00235 } else {
00236 xctrls[0].id = V4L2_CID_PAN_RELATIVE;
00237 xctrls[0].value = pan;
00238 xctrls[1].id = V4L2_CID_TILT_RELATIVE;
00239 xctrls[1].value = -tilt;
00240
00241 ctrls.count = 2;
00242 ctrls.controls = xctrls;
00243 }
00244
00245 if ( ioctl(dev, VIDIOC_S_EXT_CTRLS, &ctrls) < 0 ) {
00246
00247 return -1;
00248 }
00249
00250 return 0;
00251 }