1 /*
2 # (C) 2008 Elmar Kleijn <elmar_kleijn@hotmail.com>
3 # (C) 2008 Sjoerd Piepenbrink <need4weed@gmail.com>
4 # (C) 2008 Hans de Goede <hdegoede@redhat.com>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU Lesser General Public License as published by
8 # the Free Software Foundation; either version 2.1 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include "../libv4lconvert/libv4lsyscall-priv.h"
26 #if defined(__OpenBSD__)
27 #include <sys/videoio.h>
28 #else
29 #include <linux/videodev2.h>
30 #endif
31 #include "libv4l2.h"
32 #include "libv4l2-priv.h"
33
34 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
35
36 FILE *v4l2_log_file = NULL;
37
38 const char *v4l2_ioctls[] = {
39 /* start v4l2 ioctls */
40 [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
41 [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
42 [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
43 [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
44 [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
45 [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
46 [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
47 [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
48 [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
49 [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
50 [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
51 [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
52 [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
53 [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
54 [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
55 [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
56 [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
57 [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
58 [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
59 [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
60 [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
61 [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
62 [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
63 [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
64 [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
65 [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
66 [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
67 [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
68 [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
69 [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
70 [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
71 [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
72 [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
73 [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
74 [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
75 [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
76 [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
77 [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
78 [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
79 [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
80 [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
81 [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
82 [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
83 [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
84 [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
85 [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
86 [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
87 [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
88 [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
89 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
90 [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
91 [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
92 [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
93 [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
94 [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
95 [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
96 [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
97 [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
98 [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
99 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
100 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
101 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
102 [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
103 [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
104 [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
105 [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
106 [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
107 [_IOC_NR(VIDIOC_CREATE_BUFS)] = "VIDIOC_CREATE_BUFS",
108 [_IOC_NR(VIDIOC_PREPARE_BUF)] = "VIDIOC_PREPARE_BUF",
109 [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION",
110 [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION",
111 [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD",
112 [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD",
113 [_IOC_NR(VIDIOC_ENUM_DV_TIMINGS)] = "VIDIOC_ENUM_DV_TIMINGS",
114 [_IOC_NR(VIDIOC_QUERY_DV_TIMINGS)] = "VIDIOC_QUERY_DV_TIMINGS",
115 [_IOC_NR(VIDIOC_DV_TIMINGS_CAP)] = "VIDIOC_DV_TIMINGS_CAP",
116 [_IOC_NR(VIDIOC_ENUM_FREQ_BANDS)] = "VIDIOC_ENUM_FREQ_BANDS",
117 [_IOC_NR(VIDIOC_DBG_G_CHIP_INFO)] = "VIDIOC_DBG_G_CHIP_INFO",
118 };
119
v4l2_log_ioctl(unsigned long int request,void * arg,int result)120 void v4l2_log_ioctl(unsigned long int request, void *arg, int result)
121 {
122 const char *ioctl_str;
123 char buf[40];
124 int saved_errno = errno;
125
126 if (!v4l2_log_file)
127 return;
128
129 if (_IOC_TYPE(request) == 'V' && _IOC_NR(request) < ARRAY_SIZE(v4l2_ioctls))
130 ioctl_str = v4l2_ioctls[_IOC_NR(request)];
131 else {
132 snprintf(buf, sizeof(buf), "unknown request: %c %d",
133 (int)_IOC_TYPE(request), (int)_IOC_NR(request));
134 ioctl_str = buf;
135 }
136
137 fprintf(v4l2_log_file, "request == %s\n", ioctl_str);
138
139 switch (request) {
140 case VIDIOC_ENUM_FMT: {
141 struct v4l2_fmtdesc *fmt = arg;
142
143 fprintf(v4l2_log_file, " index: %u, description: %s\n",
144 fmt->index, (result < 0) ? "" : (const char *)fmt->description);
145 break;
146 }
147 case VIDIOC_G_FMT:
148 case VIDIOC_S_FMT:
149 case VIDIOC_TRY_FMT: {
150 struct v4l2_format *fmt = arg;
151 int pixfmt = fmt->fmt.pix.pixelformat;
152
153 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
154 fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %ux%u\n",
155 pixfmt & 0xff,
156 (pixfmt >> 8) & 0xff,
157 (pixfmt >> 16) & 0xff,
158 pixfmt >> 24,
159 fmt->fmt.pix.width,
160 fmt->fmt.pix.height);
161 fprintf(v4l2_log_file, " field: %d bytesperline: %d imagesize: %d\n",
162 (int)fmt->fmt.pix.field, (int)fmt->fmt.pix.bytesperline,
163 (int)fmt->fmt.pix.sizeimage);
164 fprintf(v4l2_log_file, " colorspace: %d, priv: %x\n",
165 (int)fmt->fmt.pix.colorspace, (int)fmt->fmt.pix.priv);
166 } else {
167 fprintf(v4l2_log_file, " type: %d\n", (int)fmt->type);
168 }
169 break;
170 }
171 case VIDIOC_REQBUFS: {
172 struct v4l2_requestbuffers *req = arg;
173
174 fprintf(v4l2_log_file, " count: %u type: %d memory: %d\n",
175 req->count, (int)req->type, (int)req->memory);
176 break;
177 }
178 case VIDIOC_DQBUF: {
179 struct v4l2_buffer *buf = arg;
180 fprintf(v4l2_log_file, " timestamp %ld.%06ld\n",
181 (long)buf->timestamp.tv_sec,
182 (long)buf->timestamp.tv_usec);
183 break;
184 }
185 case VIDIOC_ENUM_FRAMESIZES: {
186 struct v4l2_frmsizeenum *frmsize = arg;
187 int pixfmt = frmsize->pixel_format;
188
189 fprintf(v4l2_log_file, " index: %u pixelformat: %c%c%c%c\n",
190 frmsize->index,
191 pixfmt & 0xff,
192 (pixfmt >> 8) & 0xff,
193 (pixfmt >> 16) & 0xff,
194 pixfmt >> 24);
195 switch (frmsize->type) {
196 case V4L2_FRMSIZE_TYPE_DISCRETE:
197 fprintf(v4l2_log_file, " %ux%u\n", frmsize->discrete.width,
198 frmsize->discrete.height);
199 break;
200 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
201 case V4L2_FRMSIZE_TYPE_STEPWISE:
202 fprintf(v4l2_log_file, " %ux%u -> %ux%u\n",
203 frmsize->stepwise.min_width, frmsize->stepwise.min_height,
204 frmsize->stepwise.max_width, frmsize->stepwise.max_height);
205 break;
206 }
207 break;
208 }
209 case VIDIOC_ENUM_FRAMEINTERVALS: {
210 struct v4l2_frmivalenum *frmival = arg;
211 int pixfmt = frmival->pixel_format;
212
213 fprintf(v4l2_log_file, " index: %u pixelformat: %c%c%c%c %ux%u:\n",
214 frmival->index,
215 pixfmt & 0xff,
216 (pixfmt >> 8) & 0xff,
217 (pixfmt >> 16) & 0xff,
218 pixfmt >> 24,
219 frmival->width,
220 frmival->height);
221 switch (frmival->type) {
222 case V4L2_FRMIVAL_TYPE_DISCRETE:
223 fprintf(v4l2_log_file, " %u/%u\n", frmival->discrete.numerator,
224 frmival->discrete.denominator);
225 break;
226 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
227 case V4L2_FRMIVAL_TYPE_STEPWISE:
228 fprintf(v4l2_log_file, " %u/%u -> %u/%u\n",
229 frmival->stepwise.min.numerator,
230 frmival->stepwise.min.denominator,
231 frmival->stepwise.max.numerator,
232 frmival->stepwise.max.denominator);
233 break;
234 }
235 break;
236 }
237 case VIDIOC_G_PARM:
238 case VIDIOC_S_PARM: {
239 struct v4l2_streamparm *parm = arg;
240
241 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
242 break;
243
244 if (parm->parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
245 fprintf(v4l2_log_file, "timeperframe: %u/%u\n",
246 parm->parm.capture.timeperframe.numerator,
247 parm->parm.capture.timeperframe.denominator);
248 break;
249 }
250 }
251
252 if (result < 0)
253 fprintf(v4l2_log_file, "result == %d (%s)\n", result, strerror(saved_errno));
254 else
255 fprintf(v4l2_log_file, "result == %d\n", result);
256
257 fflush(v4l2_log_file);
258 }
259