~ubuntu-branches/ubuntu/precise/v4l-utils/precise

« back to all changes in this revision

Viewing changes to utils/libv4l2util/v4l2_driver.c

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-02-28 19:44:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100228194415-067hdj8rvawj91zw
Tags: upstream-0.7.90
ImportĀ upstreamĀ versionĀ 0.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
 
3
 
 
4
   The GNU C Library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Lesser General Public
 
6
   License as published by the Free Software Foundation; either
 
7
   version 2.1 of the License, or (at your option) any later version.
 
8
 
 
9
   The GNU C Library is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   Lesser General Public License for more details.
 
13
  */
 
14
 
 
15
#include <assert.h>
 
16
#include <errno.h>
 
17
#include <fcntl.h>
 
18
#include <malloc.h>
 
19
#include <stdio.h>
 
20
#include <string.h>
 
21
#include <unistd.h>
 
22
#include <sys/ioctl.h>
 
23
#include <sys/mman.h>
 
24
#include <sys/stat.h>
 
25
#include <sys/types.h>
 
26
 
 
27
#include <stdlib.h>
 
28
 
 
29
#include "v4l2_driver.h"
 
30
 
 
31
/****************************************************************************
 
32
        Auxiliary routines
 
33
 ****************************************************************************/
 
34
static int xioctl (int fd, unsigned long int request, void *arg)
 
35
{
 
36
        int r;
 
37
 
 
38
        do r = ioctl (fd, request, arg);
 
39
        while (-1 == r && EINTR == errno);
 
40
 
 
41
        return r;
 
42
}
 
43
 
 
44
static void free_list(struct drv_list **list_ptr)
 
45
{
 
46
        struct drv_list *prev,*cur;
 
47
 
 
48
        if (list_ptr==NULL)
 
49
                return;
 
50
 
 
51
        prev=*list_ptr;
 
52
        if (prev==NULL)
 
53
                return;
 
54
 
 
55
        do {
 
56
                cur=prev->next;
 
57
                if (prev->curr)
 
58
                        free (prev->curr);      // Free data
 
59
                free (prev);                    // Free list
 
60
                prev=cur;
 
61
        } while (prev);
 
62
 
 
63
        *list_ptr=NULL;
 
64
}
 
65
 
 
66
/****************************************************************************
 
67
        Auxiliary Arrays to aid debug messages
 
68
 ****************************************************************************/
 
69
char *v4l2_field_names[] = {
 
70
        [V4L2_FIELD_ANY]        = "any",
 
71
        [V4L2_FIELD_NONE]       = "none",
 
72
        [V4L2_FIELD_TOP]        = "top",
 
73
        [V4L2_FIELD_BOTTOM]     = "bottom",
 
74
        [V4L2_FIELD_INTERLACED] = "interlaced",
 
75
        [V4L2_FIELD_SEQ_TB]     = "seq-tb",
 
76
        [V4L2_FIELD_SEQ_BT]     = "seq-bt",
 
77
        [V4L2_FIELD_ALTERNATE]  = "alternate",
 
78
};
 
79
 
 
80
char *v4l2_type_names[] = {
 
81
        [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "video-cap",
 
82
        [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "video-over",
 
83
        [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "video-out",
 
84
        [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
 
85
        [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
 
86
        [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
 
87
        [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "slicec-vbi-out",
 
88
};
 
89
 
 
90
static char *v4l2_memory_names[] = {
 
91
        [V4L2_MEMORY_MMAP]    = "mmap",
 
92
        [V4L2_MEMORY_USERPTR] = "userptr",
 
93
        [V4L2_MEMORY_OVERLAY] = "overlay",
 
94
};
 
95
 
 
96
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr))
 
97
#define prt_names(a,arr) (((a)<ARRAY_SIZE(arr))?arr[a]:"unknown")
 
98
 
 
99
static char *prt_caps(uint32_t caps)
 
100
{
 
101
        static char s[4096]="";
 
102
 
 
103
        if (V4L2_CAP_VIDEO_CAPTURE & caps)
 
104
                strcat (s,"CAPTURE ");
 
105
        if (V4L2_CAP_VIDEO_OUTPUT & caps)
 
106
                strcat (s,"OUTPUT ");
 
107
        if (V4L2_CAP_VIDEO_OVERLAY & caps)
 
108
                strcat (s,"OVERLAY ");
 
109
        if (V4L2_CAP_VBI_CAPTURE & caps)
 
110
                strcat (s,"VBI_CAPTURE ");
 
111
        if (V4L2_CAP_VBI_OUTPUT & caps)
 
112
                strcat (s,"VBI_OUTPUT ");
 
113
        if (V4L2_CAP_SLICED_VBI_CAPTURE & caps)
 
114
                strcat (s,"SLICED_VBI_CAPTURE ");
 
115
        if (V4L2_CAP_SLICED_VBI_OUTPUT & caps)
 
116
                strcat (s,"SLICED_VBI_OUTPUT ");
 
117
        if (V4L2_CAP_RDS_CAPTURE & caps)
 
118
                strcat (s,"RDS_CAPTURE ");
 
119
        if (V4L2_CAP_TUNER & caps)
 
120
                strcat (s,"TUNER ");
 
121
        if (V4L2_CAP_AUDIO & caps)
 
122
                strcat (s,"AUDIO ");
 
123
        if (V4L2_CAP_RADIO & caps)
 
124
                strcat (s,"RADIO ");
 
125
        if (V4L2_CAP_READWRITE & caps)
 
126
                strcat (s,"READWRITE ");
 
127
        if (V4L2_CAP_ASYNCIO & caps)
 
128
                strcat (s,"ASYNCIO ");
 
129
        if (V4L2_CAP_STREAMING & caps)
 
130
                strcat (s,"STREAMING ");
 
131
 
 
132
        return s;
 
133
}
 
134
 
 
135
static void prt_buf_info(char *name,struct v4l2_buffer *p)
 
136
{
 
137
        struct v4l2_timecode *tc=&p->timecode;
 
138
 
 
139
        printf ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
 
140
                "bytesused=%d, flags=0x%08x, "
 
141
                "field=%s, sequence=%d, memory=%s, offset=0x%08x, length=%d\n",
 
142
                name, (p->timestamp.tv_sec/3600),
 
143
                (int)(p->timestamp.tv_sec/60)%60,
 
144
                (int)(p->timestamp.tv_sec%60),
 
145
                p->timestamp.tv_usec,
 
146
                p->index,
 
147
                prt_names(p->type,v4l2_type_names),
 
148
                p->bytesused,p->flags,
 
149
                prt_names(p->field,v4l2_field_names),
 
150
                p->sequence,
 
151
                prt_names(p->memory,v4l2_memory_names),
 
152
                p->m.offset,
 
153
                p->length);
 
154
        tc=&p->timecode;
 
155
        printf ("\tTIMECODE: %02d:%02d:%02d type=%d, "
 
156
                "flags=0x%08x, frames=%d, userbits=0x%08x\n",
 
157
                tc->hours,tc->minutes,tc->seconds,
 
158
                tc->type, tc->flags, tc->frames, *(uint32_t *) tc->userbits);
 
159
}
 
160
 
 
161
/****************************************************************************
 
162
        Open V4L2 devices
 
163
 ****************************************************************************/
 
164
int v4l2_open (char *device, int debug, struct v4l2_driver *drv)
 
165
{
 
166
        int ret;
 
167
 
 
168
        memset(drv,0,sizeof(*drv));
 
169
 
 
170
        drv->debug=debug;
 
171
 
 
172
        if ((drv->fd = open(device, O_RDWR )) < 0) {
 
173
                return(-errno);
 
174
        }
 
175
 
 
176
        ret=xioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap);
 
177
        if (!ret && drv->debug) {
 
178
                printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, "
 
179
                        "capabilities=%s\n",
 
180
                        drv->cap.driver,drv->cap.card,drv->cap.bus_info,
 
181
                        (drv->cap.version >> 16) & 0xff,
 
182
                        (drv->cap.version >>  8) & 0xff,
 
183
                        drv->cap.version         & 0xff,
 
184
                        prt_caps(drv->cap.capabilities));
 
185
 
 
186
 
 
187
        }
 
188
        return ret;
 
189
}
 
190
 
 
191
 
 
192
/****************************************************************************
 
193
        V4L2 Eumberations
 
194
 ****************************************************************************/
 
195
int v4l2_enum_stds (struct v4l2_driver *drv)
 
196
{
 
197
        struct v4l2_standard    *p=NULL;
 
198
        struct drv_list         *list;
 
199
        int                     ok=0,ret,i;
 
200
        v4l2_std_id             id;
 
201
 
 
202
        free_list(&drv->stds);
 
203
 
 
204
        list=drv->stds=calloc(1,sizeof(*drv->stds));
 
205
        assert (list!=NULL);
 
206
 
 
207
        for (i=0; ok==0; i++) {
 
208
                p=calloc(1,sizeof(*p));
 
209
                assert (p);
 
210
 
 
211
                p->index=i;
 
212
                ok=xioctl(drv->fd,VIDIOC_ENUMSTD,p);
 
213
                if (ok<0) {
 
214
                        ok=-errno;
 
215
                        free(p);
 
216
                        break;
 
217
                }
 
218
                if (drv->debug) {
 
219
                        printf ("STANDARD: index=%d, id=0x%08x, name=%s, fps=%.3f, "
 
220
                                "framelines=%d\n", p->index,
 
221
                                (unsigned int)p->id, p->name,
 
222
                                1.*p->frameperiod.denominator/p->frameperiod.numerator,
 
223
                                p->framelines);
 
224
                }
 
225
                if (list->curr) {
 
226
                        list->next=calloc(1,sizeof(*list->next));
 
227
                        list=list->next;
 
228
                        assert (list!=NULL);
 
229
                }
 
230
                list->curr=p;
 
231
        }
 
232
        if (i>0 && ok==-EINVAL)
 
233
                return 0;
 
234
 
 
235
        return ok;
 
236
}
 
237
 
 
238
int v4l2_enum_input (struct v4l2_driver *drv)
 
239
{
 
240
        struct v4l2_input       *p=NULL;
 
241
        struct drv_list         *list;
 
242
        int                     ok=0,ret,i;
 
243
        v4l2_std_id             id;
 
244
 
 
245
        free_list(&drv->inputs);
 
246
 
 
247
        list=drv->inputs=calloc(1,sizeof(*drv->inputs));
 
248
        assert (list!=NULL);
 
249
 
 
250
        for (i=0; ok==0; i++) {
 
251
                p=calloc(1,sizeof(*p));
 
252
                assert (p);
 
253
                p->index=i;
 
254
                ok=xioctl(drv->fd,VIDIOC_ENUMINPUT,p);
 
255
                if (ok<0) {
 
256
                        ok=errno;
 
257
                        free(p);
 
258
                        break;
 
259
                }
 
260
                if (drv->debug) {
 
261
                        printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, "
 
262
                                "tuner=%d, std=%08x, status=%d\n",
 
263
                                p->index,p->name,p->type,p->audioset, p->tuner,
 
264
                                (unsigned int)p->std, p->status);
 
265
                }
 
266
                if (list->curr) {
 
267
                        list->next=calloc(1,sizeof(*list->next));
 
268
                        list=list->next;
 
269
                        assert (list!=NULL);
 
270
                }
 
271
                list->curr=p;
 
272
        }
 
273
        if (i>0 && ok==-EINVAL)
 
274
                return 0;
 
275
        return ok;
 
276
}
 
277
 
 
278
int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type)
 
279
{
 
280
        struct v4l2_fmtdesc     *p=NULL;
 
281
        struct v4l2_format      fmt;
 
282
        struct drv_list         *list;
 
283
        int                     ok=0,ret,i;
 
284
        v4l2_std_id             id;
 
285
 
 
286
        free_list(&drv->fmt_caps);
 
287
 
 
288
        list=drv->fmt_caps=calloc(1,sizeof(*drv->fmt_caps));
 
289
        assert (list!=NULL);
 
290
 
 
291
        for (i=0; ok==0; i++) {
 
292
                p=calloc(1,sizeof(*p));
 
293
                assert (p!=NULL);
 
294
 
 
295
                p->index=i;
 
296
                p->type =type;
 
297
 
 
298
                ok=xioctl(drv->fd,VIDIOC_ENUM_FMT,p);
 
299
                if (ok<0) {
 
300
                        ok=errno;
 
301
                        free(p);
 
302
                        break;
 
303
                }
 
304
                if (drv->debug) {
 
305
                        printf ("FORMAT: index=%d, type=%d, flags=%d, description='%s'\n\t"
 
306
                                "fourcc=%c%c%c%c\n",
 
307
                                p->index, p->type, p->flags,p->description,
 
308
                                p->pixelformat & 0xff,
 
309
                                (p->pixelformat >>  8) & 0xff,
 
310
                                (p->pixelformat >> 16) & 0xff,
 
311
                                (p->pixelformat >> 24) & 0xff
 
312
                                );
 
313
                }
 
314
                if (list->curr) {
 
315
                        list->next=calloc(1,sizeof(*list->next));
 
316
                        list=list->next;
 
317
                        assert (list!=NULL);
 
318
                }
 
319
                list->curr=p;
 
320
        }
 
321
        if (i>0 && ok==-EINVAL)
 
322
                return 0;
 
323
        return ok;
 
324
}
 
325
 
 
326
/****************************************************************************
 
327
        Set routines - currently, it also checks results with Get
 
328
 ****************************************************************************/
 
329
int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id)
 
330
{
 
331
        v4l2_std_id             s_id=*id;
 
332
        int                     ret=0;
 
333
        char                    s[256];
 
334
 
 
335
        if (dir & V4L2_SET) {
 
336
                ret=xioctl(drv->fd,VIDIOC_S_STD,&s_id);
 
337
                if (ret<0) {
 
338
                        ret=errno;
 
339
 
 
340
                        sprintf (s,"while trying to set STD to %08x",
 
341
                                                                (unsigned int) *id);
 
342
                        perror(s);
 
343
                }
 
344
        }
 
345
 
 
346
        if (dir & V4L2_GET) {
 
347
                ret=xioctl(drv->fd,VIDIOC_G_STD,&s_id);
 
348
                if (ret<0) {
 
349
                        ret=errno;
 
350
                        perror ("while trying to get STD id");
 
351
                }
 
352
        }
 
353
 
 
354
        if (dir == V4L2_SET_GET) {
 
355
                if (*id & s_id) {
 
356
                        if (*id != s_id) {
 
357
                                printf ("Warning: Received a std subset (%08x"
 
358
                                        " std) while trying to adjust to %08x\n",
 
359
                                        (unsigned int) s_id,(unsigned int) *id);
 
360
                        }
 
361
                } else {
 
362
                        fprintf (stderr,"Error: Received %08x std while trying"
 
363
                                " to adjust to %08x\n",
 
364
                                (unsigned int) s_id,(unsigned int) *id);
 
365
                }
 
366
        }
 
367
        return ret;
 
368
}
 
369
 
 
370
int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input)
 
371
{
 
372
        int                     ok=0,ret,i;
 
373
        unsigned int            inp=input->index;
 
374
        char                    s[256];
 
375
 
 
376
        if (dir & V4L2_SET) {
 
377
                ret=xioctl(drv->fd,VIDIOC_S_INPUT,input);
 
378
                if (ret<0) {
 
379
                        ret=errno;
 
380
                        sprintf (s,"while trying to set INPUT to %d\n", inp);
 
381
                        perror(s);
 
382
                }
 
383
        }
 
384
 
 
385
        if (dir & V4L2_GET) {
 
386
                ret=xioctl(drv->fd,VIDIOC_G_INPUT,input);
 
387
                if (ret<0) {
 
388
                        perror ("while trying to get INPUT id\n");
 
389
                }
 
390
        }
 
391
 
 
392
        if (dir & V4L2_SET_GET) {
 
393
                if (input->index != inp) {
 
394
                        printf ("Input is different than expected (received %i, set %i)\n",
 
395
                                                inp, input->index);
 
396
                }
 
397
        }
 
398
 
 
399
        return ok;
 
400
}
 
401
 
 
402
int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir,
 
403
                      struct v4l2_format *fmt,uint32_t width, uint32_t height,
 
404
                      uint32_t pixelformat, enum v4l2_field field)
 
405
{
 
406
        struct v4l2_pix_format  *pix=&(fmt->fmt.pix);
 
407
        int                     ret=0;
 
408
 
 
409
        fmt->type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
410
        if (dir == V4L2_GET) {
 
411
                ret=xioctl(drv->fd,VIDIOC_G_FMT,fmt);
 
412
                if (ret < 0) {
 
413
                        ret=errno;
 
414
                        perror("VIDIOC_G_FMT failed\n");
 
415
                }
 
416
                return ret;
 
417
        } else if (dir & (~(V4L2_TRY|V4L2_SET)) ) {
 
418
                perror ("Invalid direction\n");
 
419
                return EINVAL;
 
420
        }
 
421
 
 
422
        if (dir & (V4L2_TRY|V4L2_SET)) {
 
423
                pix->width       = width;
 
424
                pix->height      = height;
 
425
                pix->pixelformat = pixelformat;
 
426
                pix->field       = field;
 
427
        /*
 
428
                enum v4l2_colorspace    colorspace;
 
429
        */
 
430
 
 
431
                if (dir & V4L2_TRY) {
 
432
                        ret=xioctl(drv->fd,VIDIOC_TRY_FMT,fmt);
 
433
                        if (ret < 0) {
 
434
                                perror("VIDIOC_TRY_FMT failed\n");
 
435
                        }
 
436
                }
 
437
 
 
438
                if (dir & V4L2_SET) {
 
439
                        ret=xioctl(drv->fd,VIDIOC_S_FMT,fmt);
 
440
                        if (ret < 0) {
 
441
                                perror("VIDIOC_S_FMT failed\n");
 
442
                        }
 
443
                        drv->sizeimage=pix->sizeimage;
 
444
                }
 
445
 
 
446
                if (pix->pixelformat != pixelformat) {
 
447
                        fprintf(stderr,"Error: asked for format %d, received %d",pixelformat,
 
448
                                pix->pixelformat);
 
449
                }
 
450
 
 
451
                if (pix->width != width) {
 
452
                        fprintf(stderr,"Error: asked for format %d, received %d\n",width,
 
453
                                pix->width);
 
454
                }
 
455
 
 
456
                if (pix->height != height) {
 
457
                        fprintf(stderr,"Error: asked for format %d, received %d\n",height,
 
458
                                pix->height);
 
459
                }
 
460
 
 
461
                if (pix->bytesperline == 0 ) {
 
462
                        fprintf(stderr,"Error: bytesperline = 0\n");
 
463
                }
 
464
 
 
465
                if (pix->sizeimage == 0 ) {
 
466
                        fprintf(stderr,"Error: sizeimage = 0\n");
 
467
                }
 
468
        }
 
469
 
 
470
        if (drv->debug)
 
471
                printf( "FMT SET: %dx%d, fourcc=%c%c%c%c, %d bytes/line,"
 
472
                        " %d bytes/frame, colorspace=0x%08x\n",
 
473
                        pix->width,pix->height,
 
474
                        pix->pixelformat & 0xff,
 
475
                        (pix->pixelformat >>  8) & 0xff,
 
476
                        (pix->pixelformat >> 16) & 0xff,
 
477
                        (pix->pixelformat >> 24) & 0xff,
 
478
                        pix->bytesperline,
 
479
                        pix->sizeimage,
 
480
                        pix->colorspace);
 
481
 
 
482
        return 0;
 
483
}
 
484
 
 
485
/****************************************************************************
 
486
        Get routines
 
487
 ****************************************************************************/
 
488
int v4l2_get_parm (struct v4l2_driver *drv)
 
489
{
 
490
        int ret;
 
491
        struct v4l2_captureparm *c;
 
492
 
 
493
        drv->parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
494
        if ((ret=xioctl(drv->fd,VIDIOC_G_PARM,&drv->parm))>=0) {
 
495
                c=&drv->parm.parm.capture;
 
496
                printf ("PARM: capability=%d, capturemode=%d, %.3f fps "
 
497
                        "ext=%x, readbuf=%d\n",
 
498
                        c->capability,
 
499
                        c->capturemode,
 
500
                        c->timeperframe.denominator*1./c->timeperframe.numerator,
 
501
                        c->extendedmode, c->readbuffers);
 
502
        } else {
 
503
                ret=errno;
 
504
 
 
505
                perror ("VIDIOC_G_PARM");
 
506
        }
 
507
 
 
508
        return ret;
 
509
}
 
510
 
 
511
/****************************************************************************
 
512
        Queue and stream control
 
513
 ****************************************************************************/
 
514
 
 
515
int v4l2_free_bufs(struct v4l2_driver *drv)
 
516
{
 
517
        unsigned int i;
 
518
 
 
519
        if (!drv->n_bufs)
 
520
                return 0;
 
521
 
 
522
        /* Requests the driver to free all buffers */
 
523
        drv->reqbuf.count  = 0;
 
524
        drv->reqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
525
        drv->reqbuf.memory = V4L2_MEMORY_MMAP;
 
526
 
 
527
        /* stop capture */
 
528
        if (xioctl(drv->fd,VIDIOC_STREAMOFF,&drv->reqbuf.type)<0)
 
529
                return errno;
 
530
 
 
531
        sleep (1);      // FIXME: Should check if all buffers are stopped
 
532
 
 
533
/* V4L2 API says REQBUFS with count=0 should be used to release buffer.
 
534
   However, video-buf.c doesn't implement it.
 
535
 */
 
536
#if 0
 
537
        if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) {
 
538
                perror("reqbufs while freeing buffers");
 
539
                return errno;
 
540
        }
 
541
#endif
 
542
 
 
543
        if (drv->reqbuf.count != 0) {
 
544
                fprintf(stderr,"REQBUFS returned %d buffers while asking for freeing it!\n",
 
545
                        drv->reqbuf.count);
 
546
        }
 
547
 
 
548
        for (i = 0; i < drv->n_bufs; i++) {
 
549
                if (drv->bufs[i].length)
 
550
                        munmap(drv->bufs[i].start, drv->bufs[i].length);
 
551
                if (drv->v4l2_bufs[i])
 
552
                        free (drv->v4l2_bufs[i]);
 
553
        }
 
554
 
 
555
        free(drv->v4l2_bufs);
 
556
        free(drv->bufs);
 
557
 
 
558
        drv->v4l2_bufs=NULL;
 
559
        drv->bufs=NULL;
 
560
        drv->n_bufs=0;
 
561
 
 
562
        return 0;
 
563
}
 
564
 
 
565
int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers)
 
566
{
 
567
        /* Frees previous allocations, if required */
 
568
        v4l2_free_bufs(drv);
 
569
 
 
570
        if (drv->sizeimage==0) {
 
571
                fprintf(stderr,"Image size is zero! Can't proceed\n");
 
572
                return -1;
 
573
        }
 
574
        /* Requests the specified number of buffers */
 
575
        drv->reqbuf.count  = num_buffers;
 
576
        drv->reqbuf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
577
        drv->reqbuf.memory = V4L2_MEMORY_MMAP;
 
578
 
 
579
        if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) {
 
580
                perror("reqbufs");
 
581
                return errno;
 
582
        }
 
583
 
 
584
        if (drv->debug)
 
585
                printf ("REQBUFS: count=%d, type=%s, memory=%s\n",
 
586
                                drv->reqbuf.count,
 
587
                                prt_names(drv->reqbuf.type,v4l2_type_names),
 
588
                                prt_names(drv->reqbuf.memory,v4l2_memory_names));
 
589
 
 
590
        /* Allocates the required number of buffers */
 
591
        drv->v4l2_bufs=calloc(drv->reqbuf.count, sizeof(*drv->v4l2_bufs));
 
592
        assert(drv->v4l2_bufs!=NULL);
 
593
        drv->bufs=calloc(drv->reqbuf.count, sizeof(*drv->bufs));
 
594
        assert(drv->bufs!=NULL);
 
595
 
 
596
        for (drv->n_bufs = 0; drv->n_bufs < drv->reqbuf.count; drv->n_bufs++) {
 
597
                struct v4l2_buffer *p;
 
598
                struct v4l2_timecode *tc;
 
599
 
 
600
                /* Requests kernel buffers to be mmapped */
 
601
                p=drv->v4l2_bufs[drv->n_bufs]=calloc(1,sizeof(*p));
 
602
                assert (p!=NULL);
 
603
                p->index  = drv->n_bufs;
 
604
                p->type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
605
                p->memory = V4L2_MEMORY_MMAP;
 
606
                if (xioctl(drv->fd,VIDIOC_QUERYBUF,p)<0) {
 
607
                        int ret=errno;
 
608
                        perror("querybuf");
 
609
 
 
610
                        free (drv->v4l2_bufs[drv->n_bufs]);
 
611
 
 
612
                        v4l2_free_bufs(drv);
 
613
                        return ret;
 
614
                }
 
615
 
 
616
                if (drv->debug)
 
617
                        prt_buf_info("QUERYBUF",p);
 
618
 
 
619
                if (drv->sizeimage != p->length) {
 
620
                        if (drv->sizeimage < p->length) {
 
621
                                fprintf (stderr, "QUERYBUF: ERROR: VIDIOC_S_FMT said buffer should have %d size, but received %d from QUERYBUF!\n",
 
622
                                        drv->sizeimage, p->length);
 
623
                        } else {
 
624
                                fprintf (stderr, "QUERYBUF: Expecting %d size, received %d buff length\n",
 
625
                                        drv->sizeimage, p->length);
 
626
                        }
 
627
                }
 
628
 
 
629
                drv->bufs[drv->n_bufs].length = p->length;
 
630
                drv->bufs[drv->n_bufs].start =  mmap (NULL,     /* start anywhere */
 
631
                              p->length,
 
632
                              PROT_READ | PROT_WRITE,           /* required */
 
633
                              MAP_SHARED,                       /* recommended */
 
634
                              drv->fd, p->m.offset);
 
635
 
 
636
 
 
637
                if (MAP_FAILED == drv->bufs[drv->n_bufs].start) {
 
638
                        perror("mmap");
 
639
 
 
640
                        free (drv->v4l2_bufs[drv->n_bufs]);
 
641
                        v4l2_free_bufs(drv);
 
642
                        return errno;
 
643
                }
 
644
        }
 
645
 
 
646
        return 0;
 
647
}
 
648
 
 
649
/* Returns <0, if error, 0 if nothing to read and <size>, if something
 
650
   read
 
651
 */
 
652
int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf)
 
653
{
 
654
        int ret;
 
655
 
 
656
        struct v4l2_buffer buf;
 
657
        memset (&buf, 0, sizeof(buf));
 
658
 
 
659
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
660
        buf.memory = V4L2_MEMORY_MMAP;
 
661
 
 
662
        if (-1 == xioctl (drv->fd, VIDIOC_DQBUF, &buf)) {
 
663
                switch (errno) {
 
664
                case EAGAIN:
 
665
                        return 0;
 
666
 
 
667
                case EIO:
 
668
                        /* Could ignore EIO, see spec. */
 
669
 
 
670
                        /* fall through */
 
671
 
 
672
                default:
 
673
                        perror ("dqbuf");
 
674
                        return -errno;
 
675
                }
 
676
        }
 
677
        prt_buf_info("DQBUF",&buf);
 
678
 
 
679
        assert (buf.index < drv->n_bufs);
 
680
 
 
681
        ret = rec_buf (&buf,&drv->bufs[buf.index]);
 
682
 
 
683
        if (ret<0) {
 
684
                v4l2_free_bufs(drv);
 
685
                return ret;
 
686
        }
 
687
 
 
688
        if (-1 == xioctl (drv->fd, VIDIOC_QBUF, &buf)) {
 
689
                perror ("qbuf");
 
690
                return -errno;
 
691
        }
 
692
        return ret;
 
693
}
 
694
 
 
695
int v4l2_start_streaming(struct v4l2_driver *drv)
 
696
{
 
697
        uint32_t        i;
 
698
        struct v4l2_buffer buf;
 
699
 
 
700
        if (drv->debug)
 
701
                printf("Activating %d queues\n", drv->n_bufs);
 
702
        for (i = 0; i < drv->n_bufs; i++) {
 
703
                int res;
 
704
 
 
705
                memset(&buf, 0, sizeof(buf));
 
706
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
707
                buf.memory = V4L2_MEMORY_MMAP;
 
708
                buf.index  = i;
 
709
 
 
710
                res = xioctl (drv->fd, VIDIOC_QBUF, &buf);
 
711
 
 
712
                if (!res)
 
713
                        prt_buf_info("QBUF",&buf);
 
714
                else {
 
715
                        perror("qbuf");
 
716
                        return errno;
 
717
                }
 
718
        }
 
719
 
 
720
        /* Activates stream */
 
721
        if (drv->debug)
 
722
                printf("Enabling streaming\n");
 
723
 
 
724
        if (xioctl(drv->fd,VIDIOC_STREAMON,&drv->reqbuf.type)<0)
 
725
                return errno;
 
726
 
 
727
        return 0;
 
728
}
 
729
 
 
730
int v4l2_stop_streaming(struct v4l2_driver *drv)
 
731
{
 
732
        v4l2_free_bufs(drv);
 
733
 
 
734
        return 0;
 
735
}
 
736
 
 
737
/****************************************************************************
 
738
        Close V4L2, disallocating all structs
 
739
 ****************************************************************************/
 
740
int v4l2_close (struct v4l2_driver *drv)
 
741
{
 
742
        v4l2_free_bufs(drv);
 
743
 
 
744
        free_list(&drv->stds);
 
745
        free_list(&drv->inputs);
 
746
        free_list(&drv->fmt_caps);
 
747
 
 
748
        return (close(drv->fd));
 
749
}
 
750
 
 
751
/****************************************************************************
 
752
        Get/Set frequency
 
753
 ****************************************************************************/
 
754
 
 
755
int v4l2_getset_freq (struct v4l2_driver *drv, enum v4l2_direction dir,
 
756
                      double *freq)
 
757
{
 
758
        struct v4l2_tuner     tun;
 
759
        struct v4l2_frequency frq;
 
760
        double d = 62500;
 
761
        unsigned int counter;
 
762
 
 
763
        memset(&tun, 0, sizeof(tun));
 
764
 
 
765
        if (-1 == xioctl (drv->fd, VIDIOC_G_TUNER, &tun)) {
 
766
                perror ("g_tuner");
 
767
                printf("Assuming 62.5 kHz step\n");
 
768
        } else {
 
769
                if (tun.capability & V4L2_TUNER_CAP_LOW)
 
770
                        d=62.5;
 
771
        }
 
772
 
 
773
        if (drv->debug) {
 
774
                if (tun.capability & V4L2_TUNER_CAP_LOW)
 
775
                        printf("62.5 Hz step\n");
 
776
                else
 
777
                        printf("62.5 kHz step\n");
 
778
        }
 
779
 
 
780
        memset(&frq, 0, sizeof(frq));
 
781
 
 
782
        frq.type = V4L2_TUNER_ANALOG_TV;
 
783
 
 
784
        if (dir & V4L2_GET) {
 
785
                if (-1 == xioctl (drv->fd, VIDIOC_G_FREQUENCY, &frq)) {
 
786
                        perror ("s_frequency");
 
787
                        return errno;
 
788
                }
 
789
                *freq = frq.frequency * d;
 
790
                if (drv->debug)
 
791
                        printf("board is at freq %4.3f MHz (%d)\n",
 
792
                                *freq/1000000, frq.frequency);
 
793
        } else {
 
794
                frq.frequency = (uint32_t)(((*freq)+d/2) / d);
 
795
 
 
796
                if (-1 == xioctl (drv->fd, VIDIOC_S_FREQUENCY, &frq)) {
 
797
                        perror ("s_frequency");
 
798
                        return errno;
 
799
                }
 
800
                if (drv->debug)
 
801
                        printf("board set to freq %4.3f MHz (%d)\n",
 
802
                                *freq/1000000, frq.frequency);
 
803
 
 
804
        }
 
805
        return 0;
 
806
}