libexplain
1.4.D001
|
00001 /* 00002 * libexplain - a library of system-call-specific strerror replacements 00003 * Copyright (C) 2011-2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as 00007 * published by the Free Software Foundation; either version 3 of the 00008 * License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/errno.h> 00020 #include <libexplain/ac/linux/videodev2.h> 00021 #include <libexplain/ac/string.h> 00022 #include <libexplain/ac/sys/ioctl.h> 00023 00024 #include <libexplain/buffer/boolean.h> 00025 #include <libexplain/buffer/int32_t.h> 00026 #include <libexplain/buffer/int64_t.h> 00027 #include <libexplain/buffer/pointer.h> 00028 #include <libexplain/buffer/v4l2_control.h> 00029 #include <libexplain/buffer/v4l2_control_id.h> 00030 #include <libexplain/is_efault.h> 00031 00032 00033 #ifdef HAVE_LINUX_VIDEODEV2_H 00034 00035 void 00036 explain_buffer_v4l2_control(explain_string_buffer_t *sb, 00037 const struct v4l2_control *data, int extra, int fildes) 00038 { 00039 #ifdef HAVE_LINUX_VIDEODEV2_H 00040 struct v4l2_queryctrl info; 00041 00042 if (explain_is_efault_pointer(data, sizeof(*data))) 00043 { 00044 explain_buffer_pointer(sb, data); 00045 return; 00046 } 00047 00048 explain_string_buffer_puts(sb, "{ id = "); 00049 explain_buffer_v4l2_control_id(sb, data->id); 00050 00051 /* 00052 * If possible, supplement with the name of the control. 00053 */ 00054 memset(&info, 0, sizeof(info)); 00055 info.id = data->id; 00056 if (ioctl(fildes, VIDIOC_QUERYCTRL, &info) < 0) 00057 info.type = V4L2_CTRL_TYPE_INTEGER; 00058 if (info.name[0]) 00059 { 00060 explain_string_buffer_putc(sb, ' '); 00061 explain_string_buffer_putsu_quoted_n(sb, info.name, sizeof(info.name)); 00062 } 00063 00064 if (extra) 00065 { 00066 explain_string_buffer_puts(sb, ", value = "); 00067 00068 /* 00069 * If possible, supplement with the name of the value. 00070 */ 00071 switch (info.type) 00072 { 00073 case V4L2_CTRL_TYPE_INTEGER64: 00074 { 00075 struct v4l2_ext_control c; 00076 struct v4l2_ext_controls d; 00077 00078 memset(&c, 0, sizeof(c)); 00079 c.id = data->id; 00080 00081 memset(&d, 0, sizeof(d)); 00082 d.ctrl_class = V4L2_CTRL_ID2CLASS(data->id); 00083 d.count = 1; 00084 d.controls = &c; 00085 if (ioctl(fildes, VIDIOC_G_EXT_CTRLS, &d) >= 0) 00086 explain_buffer_uint64_t(sb, c.value64); 00087 } 00088 break; 00089 00090 case V4L2_CTRL_TYPE_CTRL_CLASS: 00091 /* Huh?!? */ 00092 explain_buffer_int32_t(sb, data->value); 00093 break; 00094 00095 #if defined(V4L2_CTRL_TYPE_STRING) || defined(HAVE_V4L2_CTRL_TYPE_STRING) 00096 case V4L2_CTRL_TYPE_STRING: 00097 { 00098 struct v4l2_ext_control c; 00099 struct v4l2_ext_controls d; 00100 char string[1000]; 00101 00102 memset(&c, 0, sizeof(c)); 00103 c.id = data->id; 00104 c.size = sizeof(string); 00105 c.string = string; 00106 00107 memset(&d, 0, sizeof(d)); 00108 d.ctrl_class = V4L2_CTRL_ID2CLASS(data->id); 00109 d.count = 1; 00110 d.controls = &c; 00111 if (ioctl(fildes, VIDIOC_G_EXT_CTRLS, &d) >= 0) 00112 { 00113 explain_string_buffer_puts_quoted_n 00114 ( 00115 sb, 00116 string, 00117 sizeof(string) 00118 ); 00119 } 00120 } 00121 break; 00122 #endif 00123 00124 default: 00125 case V4L2_CTRL_TYPE_INTEGER: 00126 case V4L2_CTRL_TYPE_BUTTON: 00127 #if defined(V4L2_CTRL_TYPE_BITMASK) || defined(HAVE_V4L2_CTRL_TYPE_BITMASK) 00128 case V4L2_CTRL_TYPE_BITMASK: 00129 #endif 00130 explain_buffer_int32_t(sb, data->value); 00131 break; 00132 00133 case V4L2_CTRL_TYPE_BOOLEAN: 00134 explain_buffer_boolean(sb, data->value); 00135 break; 00136 00137 case V4L2_CTRL_TYPE_MENU: 00138 { 00139 struct v4l2_querymenu value; 00140 00141 explain_buffer_int32_t(sb, data->value); 00142 00143 memset(&value, 0, sizeof(value)); 00144 value.id = data->id; 00145 value.index = data->value; 00146 if 00147 ( 00148 ioctl(fildes, VIDIOC_QUERYMENU, &value) >= 0 00149 && 00150 value.name[0] 00151 ) 00152 { 00153 explain_string_buffer_putc(sb, ' '); 00154 explain_string_buffer_putsu_quoted_n 00155 ( 00156 sb, 00157 value.name, 00158 sizeof(value.name) 00159 ); 00160 } 00161 } 00162 break; 00163 } 00164 } 00165 explain_string_buffer_puts(sb, " }"); 00166 #else 00167 explain_buffer_pointer(sb, data); 00168 #endif 00169 } 00170 00171 00172 enum explain_v4l2_control_check_id_t 00173 explain_v4l2_control_check_id(int fildes, const struct v4l2_control *data) 00174 { 00175 struct v4l2_queryctrl dummy; 00176 00177 if (explain_is_efault_pointer(data, sizeof(*data))) 00178 return explain_v4l2_control_check_id_no_idea; 00179 memset(&dummy, 0, sizeof(dummy)); 00180 dummy.id = data->id; 00181 if (ioctl(fildes, VIDIOC_QUERYCTRL, &dummy) >= 0) 00182 return explain_v4l2_control_check_id_ok; 00183 switch (errno) 00184 { 00185 case EIO: 00186 case EINVAL: 00187 switch (V4L2_CTRL_ID2CLASS(data->id)) 00188 { 00189 case V4L2_CTRL_CLASS_USER: 00190 case V4L2_CTRL_CLASS_MPEG: 00191 #ifdef V4L2_CTRL_CLASS_CAMERA 00192 case V4L2_CTRL_CLASS_CAMERA: 00193 #endif 00194 #ifdef V4L2_CTRL_CLASS_FM_TX 00195 case V4L2_CTRL_CLASS_FM_TX: 00196 #endif 00197 return explain_v4l2_control_check_id_notsup; 00198 00199 default: 00200 return explain_v4l2_control_check_id_nosuch; 00201 } 00202 00203 default: 00204 return explain_v4l2_control_check_id_no_idea; 00205 } 00206 } 00207 00208 /* vim: set ts=8 sw=4 et : */ 00209 #endif