summaryrefslogtreecommitdiff
path: root/v4l2-apps
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps')
-rw-r--r--v4l2-apps/lib/Makefile2
-rw-r--r--v4l2-apps/lib/v4l2_driver.c307
-rw-r--r--v4l2-apps/lib/v4l2_driver.h49
-rw-r--r--v4l2-apps/test/Makefile8
-rw-r--r--v4l2-apps/test/driver-test.c65
-rw-r--r--v4l2-apps/test/ioctl-test.c193
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);