libexplain  1.4.D001
libexplain/buffer/v4l2_control.c
Go to the documentation of this file.
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