diff options
Diffstat (limited to 'v4l2-apps')
-rw-r--r-- | v4l2-apps/lib/Makefile | 2 | ||||
-rw-r--r-- | v4l2-apps/lib/v4l2_driver.c | 307 | ||||
-rw-r--r-- | v4l2-apps/lib/v4l2_driver.h | 49 | ||||
-rw-r--r-- | v4l2-apps/test/Makefile | 8 | ||||
-rw-r--r-- | v4l2-apps/test/driver-test.c | 65 | ||||
-rw-r--r-- | v4l2-apps/test/ioctl-test.c | 193 |
6 files changed, 429 insertions, 195 deletions
diff --git a/v4l2-apps/lib/Makefile b/v4l2-apps/lib/Makefile index a69615bdc..f123f3380 100644 --- a/v4l2-apps/lib/Makefile +++ b/v4l2-apps/lib/Makefile @@ -4,7 +4,7 @@ CPPFLAGS += -I../../linux/include -I.. includes = v4l2.h -objects = frequencies.o +objects = frequencies.o v4l2_driver.o sharedlib = libv4l2.so staticlib = libv4l2.a diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c new file mode 100644 index 000000000..7714d8112 --- /dev/null +++ b/v4l2-apps/lib/v4l2_driver.c @@ -0,0 +1,307 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + */ + +#include <errno.h> +#include <fcntl.h> +#include <malloc.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "v4l2_driver.h" + +/**************************************************************************** + Auxiliary routines + ****************************************************************************/ +static void free_list(struct drv_list **list_ptr) +{ + struct drv_list *prev,*cur; + + if (list_ptr==NULL) + return; + + prev=*list_ptr; + if (prev==NULL) + return; + + do { + cur=prev->next; + if (prev->curr) + free (prev->curr); // Free data + free (prev); // Free list + prev=cur; + } while (prev); + + *list_ptr=NULL; +} + +/**************************************************************************** + Open/Close V4L2 devices + ****************************************************************************/ +int v4l2_open (char *device, int debug, struct v4l2_driver *drv) +{ + int ret; + + memset(drv,0,sizeof(*drv)); + + drv->debug=debug; + + if ((drv->fd = open(device, O_RDONLY)) < 0) { + perror("Couldn't open video0"); + return(errno); + } + + ret=ioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap); + if (ret>=0 && drv->debug) { + printf ("driver=%s, card=%s, bus=%s, version=0x%08x, " + "capabilities=0x%08x\n", + drv->cap.driver,drv->cap.card,drv->cap.bus_info, + drv->cap.version,drv->cap.capabilities); + } + return ret; +} + +int v4l2_close (struct v4l2_driver *drv) +{ + free_list(&drv->stds); + free_list(&drv->inputs); + free_list(&drv->fmt_caps); + + return (close(drv->fd)); +} + +/**************************************************************************** + V4L2 Eumberations + ****************************************************************************/ +int v4l2_enum_stds (struct v4l2_driver *drv) +{ + struct v4l2_standard *p=NULL; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->stds); + + list=drv->stds=calloc(1,sizeof(drv->stds)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + p->index=i; + ok=ioctl(drv->fd,VIDIOC_ENUMSTD,p); + if (ok<0) { + ok=errno; + free(p); + break; + } + if (drv->debug) { + printf ("STANDARD: index=%d, id=0x%08x, name=%s, fps=%.3f, " + "framelines=%d\n", p->index, + (unsigned int)p->id, p->name, + 1.*p->frameperiod.denominator/p->frameperiod.numerator, + p->framelines); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + + return ok; +} + +int v4l2_enum_input (struct v4l2_driver *drv) +{ + struct v4l2_input *p=NULL; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->inputs); + + list=drv->inputs=calloc(1,sizeof(drv->inputs)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + p->index=i; + ok=ioctl(drv->fd,VIDIOC_ENUMINPUT,p); + if (ok<0) { + ok=errno; + free(p); + break; + } + if (drv->debug) { + printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, " + "tuner=%d, std=%08x, status=%d\n", + p->index,p->name,p->type,p->audioset, p->tuner, + (unsigned int)p->std, p->status); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + return ok; +} + +int v4l2_enum_fmt_cap (struct v4l2_driver *drv) +{ + struct v4l2_fmtdesc *p=NULL; + struct v4l2_format fmt; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->fmt_caps); + + list=drv->fmt_caps=calloc(1,sizeof(drv->fmt_caps)); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + p->index=i; + p->type =V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ok=ioctl(drv->fd,VIDIOC_ENUM_FMT,p); + if (ok<0) { + ok=errno; + free(p); + break; + } + if (drv->debug) { + printf ("FORMAT: index=%d, type=%d, flags=%d, description=%s\n\t" + "pixelformat=0x%08x\n", + p->index, p->type, p->flags,p->description, + p->pixelformat); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + return ok; +} + +/**************************************************************************** + Set routines - currently, it also checks results with Get + ****************************************************************************/ +int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id) +{ + v4l2_std_id s_id=*id; + int ret=0; + char s[256]; + + if (dir & V4L2_SET) { + ret=ioctl(drv->fd,VIDIOC_S_STD,&s_id); + if (ret<0) { + ret=errno; + + sprintf (s,"while trying to set STD to %08x", + (unsigned int) id); + perror(s); + } + } + + if (dir & V4L2_GET) { + ret=ioctl(drv->fd,VIDIOC_G_STD,&s_id); + if (ret<0) { + ret=errno; + perror ("while trying to get STD id"); + } + } + + if (dir == V4L2_SET_GET) { + if (*id & s_id) { + if (*id != s_id) { + printf ("Warning: Received a std subset (%08x" + " std) while trying to adjust to %08x\n", + (unsigned int) s_id,(unsigned int) *id); + } + } else { + fprintf (stderr,"Error: Received %08x std while trying" + " to adjust to %08x\n", + (unsigned int) s_id,(unsigned int) *id); + } + } + return ret; +} + +int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input) +{ + int ok=0,ret,i; + unsigned int inp=input->index; + char s[256]; + + if (dir & V4L2_SET) { + ret=ioctl(drv->fd,VIDIOC_S_INPUT,input); + if (ret<0) { + ret=errno; + sprintf (s,"while trying to set INPUT to %d\n", inp); + perror(s); + } + } + + if (dir & V4L2_GET) { + ret=ioctl(drv->fd,VIDIOC_G_INPUT,input); + if (ret<0) { + perror ("while trying to get INPUT id\n"); + } + } + + if (dir & V4L2_SET_GET) { + if (input->index != inp) { + printf ("Input is different than expected (received %i, set %i)\n", + inp, input->index); + } + } + + return ok; +} + +/**************************************************************************** + Get routines + ****************************************************************************/ +int v4l2_get_parm (struct v4l2_driver *drv) +{ + int ret; + struct v4l2_captureparm *c; + + drv->parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if ((ret=ioctl(drv->fd,VIDIOC_G_PARM,&drv->parm))>=0) { + c=&drv->parm.parm.capture; + printf ("PARM: capability=%d, capturemode=%d, frame time =%.3f ns " + "ext=%x, readbuf=%d\n", + c->capability, + c->capturemode, + 100.*c->timeperframe.numerator/c->timeperframe.denominator, + c->extendedmode, c->readbuffers); + } else { + ret=errno; + + perror ("VIDIOC_G_PARM"); + } + + return ret; +} diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h new file mode 100644 index 000000000..a6f46dea3 --- /dev/null +++ b/v4l2-apps/lib/v4l2_driver.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + */ + +#include <sys/time.h> +#include <linux/videodev2.h> + +struct drv_list { + void *curr; + struct drv_list *next; +}; + +struct v4l2_driver { + int fd; /* Driver descriptor */ + + int debug; + + struct v4l2_capability cap; + + struct v4l2_streamparm parm; + + struct drv_list *stds,*inputs,*fmt_caps; +}; + +enum v4l2_direction { + V4L2_GET = 1, // Bit 1 + V4L2_SET = 2, // Bit 2 + V4L2_SET_GET = 3, // Bits 1 and 2 - sets then gets and compare +}; + +int v4l2_open (char *device, int debug, struct v4l2_driver *drv); +int v4l2_close (struct v4l2_driver *drv); +int v4l2_enum_stds (struct v4l2_driver *drv); +int v4l2_enum_input (struct v4l2_driver *drv); +int v4l2_enum_fmt_cap (struct v4l2_driver *drv); +int v4l2_get_parm (struct v4l2_driver *drv); +int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id); +int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input); diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile index b6a83b2b3..6c1edf6a5 100644 --- a/v4l2-apps/test/Makefile +++ b/v4l2-apps/test/Makefile @@ -6,7 +6,8 @@ binaries = ioctl-test \ sliced-vbi-test \ sliced-vbi-detect \ vbi-test \ - v4lgrab + v4lgrab \ + driver-test .PHONY: all clean install @@ -17,4 +18,9 @@ clean:: install: +../lib/libv4l2.a: ../lib/v4l2_driver.c ../lib/frequencies.c + make -C ../lib libv4l2.a + +driver-test: driver-test.o ../lib/libv4l2.a + include ../Make.rules diff --git a/v4l2-apps/test/driver-test.c b/v4l2-apps/test/driver-test.c new file mode 100644 index 000000000..cf3511fc4 --- /dev/null +++ b/v4l2-apps/test/driver-test.c @@ -0,0 +1,65 @@ +/* + driver-test.c - This program tests V4L2 kernel drivers + + Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + */ + +#include "../lib/v4l2_driver.h" +#include <stdio.h> + +int main(void) +{ + struct v4l2_driver drv; + struct drv_list *cur; + + if (v4l2_open ("/dev/video0", 1,&drv)<0) { + perror("open"); + return -1; + } + if (v4l2_enum_stds (&drv)<0) { + perror("enum_stds"); + } + + /* Tries all video standards */ + for (cur=drv.stds;cur!=NULL;cur=cur->next) { + v4l2_std_id id=((struct v4l2_standard *)cur->curr)->id; + if (cur->curr) + if (v4l2_setget_std (&drv, V4L2_SET_GET, &id)) + perror("set_std"); + } + + if (v4l2_enum_input (&drv)<0) { + perror("enum_input"); + } + + /* Tries all video inputs */ + for (cur=drv.inputs;cur!=NULL;cur=cur->next) { + struct v4l2_input input; + input.index=((struct v4l2_input* )cur->curr)->index; + if (cur->curr) + if (v4l2_setget_input (&drv, V4L2_SET_GET, &input)) + perror("set_input"); + } + + if (v4l2_enum_fmt_cap (&drv)<0) { + perror("enum_fmt_cap"); + } + if (v4l2_get_parm (&drv)<0) { + perror("get_parm"); + } + if (v4l2_close (&drv)<0) { + perror("close"); + return -1; + } + return 0; +} diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c index 335ccf102..f483338fb 100644 --- a/v4l2-apps/test/ioctl-test.c +++ b/v4l2-apps/test/ioctl-test.c @@ -210,192 +210,6 @@ int ioctls[] = { /********************************************************************/ -int get_capabilities (int fd, union v4l_parms *p) -{ - int ret; - - ret=ioctl(fd,VIDIOC_QUERYCAP,(void *) &p); - if (ret>=0) { - struct v4l2_capability *pq= (struct v4l2_capability *)&p; - printf ("driver=%s, card=%s, bus=%s, version=0x%08x, " - "capabilities=0x%08x\n", - pq->driver,pq->card,pq->bus_info, - pq->version, - pq->capabilities); - } - return ret; -} - -#define ERR "*** ERROR " -#define WARN "* Warning " - -int get_set_stds (int fd, union v4l_parms *p) -{ - struct v4l2_standard *pq=(void *)p; - int ok=0,ret,i; - v4l2_std_id id; - - for (i=0; ok==0; i++) { - pq->index=i; - ok=ioctl(fd,VIDIOC_ENUMSTD,pq); - if (ok>=0) { - printf ("STANDARD: index=%d, id=%Ld, name=%s, fps=%.3f, " - "framelines=%d\n", pq->index, - (unsigned long long)pq->id, pq->name, - 1.*pq->frameperiod.denominator/pq->frameperiod.numerator, - pq->framelines); - } else - break; - id=pq->id; - p->id=id; - ret=ioctl(fd,VIDIOC_S_STD,p); - if (ret) { - printf (ERR "%i while trying to set STD to %08x\n",ret, - (unsigned int) id); - } - ret=ioctl(fd,VIDIOC_G_STD,p); - if (ret) { - printf (ERR "%i while trying to get STD id\n",ret); - } - if (id & p->id) { - if (id != p->id) { - printf (WARN "Received a std subset (%08x std) while trying to adjust to %08x\n", - (unsigned int) p->id,(unsigned int) id); - } - } else - printf (ERR "Received %08x std while trying to adjust to %08x\n", - (unsigned int) p->id,(unsigned int) id); - - } - return ok; -} - -int get_set_inputs (int fd, union v4l_parms *arg) -{ - struct v4l2_input *p=(void *)arg; - int ok=0,ret,i; - int input; - - for (i=0; ok==0; i++) { - p->index=i; - ok=ioctl(fd,VIDIOC_ENUMINPUT,p); - if (ok>=0) { - - printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, " - "tuner=%d, std=%08x, status=%d\n", - p->index,p->name,p->type,p->audioset, - p->tuner, - (unsigned int)p->std, - p->status); - - } else - break; - input=p->index; - arg->i=input; - ret=ioctl(fd,VIDIOC_S_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to set INPUT to %d\n",ret, - input); - } - ret=ioctl(fd,VIDIOC_G_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to get INPUT id\n",ret); - } - if (input != arg->i) { - printf ("Input is different than expected (received %i, set %i)\n", - input, p->index); - } - } - return ok; -} - -int get_set_formats (int fd, union v4l_parms *arg) -{ - struct v4l2_fmtdesc *p=(void *)arg; - int ok=0,ret,i; - struct v4l2_format fmt; - struct v4l2_streamparm parm; - struct v4l2_captureparm *c; - - - for (i=0; ok==0; i++) { - p->index=i; - p->type=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ok=ioctl(fd,VIDIOC_ENUM_FMT,p); - if (ok>=0) { - printf ("FORMAT: index=%d, type=%d, flags=%d, description=%s\n\t" - "pixelformat=0x%08x\n", - p->index, p->type, p->flags,p->description, - p->pixelformat); - } else - break; - - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(fd,VIDIOC_G_PARM,&parm)>=0) { - c=&parm.parm.capture; - printf ("PARM: capability=%d, capturemode=%d, frame time =%.3f ns " - "ext=%x, readbuf=%d\n", - c->capability, - c->capturemode, - 100.*c->timeperframe.numerator/c->timeperframe.denominator, - c->extendedmode, c->readbuffers); - } else - perror ("VIDIOC_G_PARM"); - -#if 0 - fmt.type=p->type; - fmt.pixelformat=p->pixelformat; - - ret=ioctl(fd,VIDIOC_G_FMT,arg); - if (ret < 0) { - printf("VIDIOC_G_FMT failed\n"); - continue; - } - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - - err = cx8800_try_fmt(dev,fh,f); - if (0 != err) - return err; - - fmt.pixelformat=p->pixelformat; - fmt. - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - return 0; - case V4L2_BUF_TYPE_VBI_CAPTURE: - cx8800_vbi_fmt(dev, f); - return 0; - default: - printf(WARN "format type not implemented\n"); - continue; - } - - - input=p->index; - arg->i=input; - ret=ioctl(fd,VIDIOC_S_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to set INPUT to %d\n",ret, - input); - } - ret=ioctl(fd,VIDIOC_G_INPUT,arg); - if (ret) { - printf (ERR "%i while trying to get INPUT id\n",ret); - } - if (input != arg->i) { - printf ("Input is different than expected (received %i, set %i)\n", - input, p->index); - } -#endif - } - return ok; -} - int main (void) { int fd=0, ret=0; @@ -408,18 +222,11 @@ int main (void) return(-1); } - get_capabilities (fd, &p); - get_set_stds (fd, &p); - get_set_inputs (fd, &p); - get_set_formats (fd, &p); - -#if 0 for (i=0;i<S_IOCTLS;i++) { memset(&p,0,sizeof(p)); ret=ioctl(fd,ioctls[i], (void *) &p); printf("%i: ioctl=0x%08x, return=%d\n",i, ioctls[i], ret); } -#endif close (fd); |