xref: /third_party/backends/backend/v4l.c (revision 141cc406)
1/* sane - Scanner Access Now Easy.
2   Copyright (C) 1999 Juergen G. Schimmer
3   Updates and bugfixes (C) 2002 - 2004 Henning Meier-Geinitz
4
5   This file is part of the SANE package.
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20   As a special exception, the authors of SANE give permission for
21   additional uses of the libraries contained in this release of SANE.
22
23   The exception is that, if you link a SANE library with other files
24   to produce an executable, this does not by itself cause the
25   resulting executable to be covered by the GNU General Public
26   License.  Your use of that executable is in no way restricted on
27   account of linking the SANE library code into it.
28
29   This exception does not, however, invalidate any other reasons why
30   the executable file might be covered by the GNU General Public
31   License.
32
33   If you submit changes to SANE to the maintainers to be included in
34   a subsequent release, you agree by submitting the changes that
35   those changes may be distributed with this exception intact.
36
37   If you write modifications of your own for SANE, it is your choice
38   whether to permit this exception to apply to your modifications.
39   If you do not wish that, delete this exception notice.
40
41   This file implements a SANE backend for v4l-Devices.
42*/
43
44#define BUILD 5
45
46#include "../include/sane/config.h"
47
48#include <assert.h>
49#include <ctype.h>
50#include <errno.h>
51#include <fcntl.h>
52#include <limits.h>
53#include <math.h>
54#include <setjmp.h>
55#include <signal.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#include <sys/types.h>
60#include <sys/wait.h>
61#include <unistd.h>
62#include <sys/mman.h>
63
64#include <unistd.h>
65#include <sys/time.h>
66#include <sys/stat.h>
67
68#include "../include/sane/sane.h"
69#include "../include/sane/sanei.h"
70#include "../include/sane/saneopts.h"
71
72#include <sys/ioctl.h>
73
74#define BACKEND_NAME v4l
75#include "../include/sane/sanei_backend.h"
76
77#ifndef PATH_MAX
78# define PATH_MAX       1024
79#endif
80
81#include "../include/sane/sanei_config.h"
82#define V4L_CONFIG_FILE "v4l.conf"
83
84#include <libv4l1.h>
85#include "v4l.h"
86
87static const SANE_Device **devlist = NULL;
88static int num_devices;
89static V4L_Device *first_dev;
90static V4L_Scanner *first_handle;
91static char *buffer;
92
93static const SANE_String_Const mode_list[] = {
94  SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR,
95  0
96};
97
98static const SANE_Range u8_range = {
99  /* min, max, quantization */
100  0, 255, 0
101};
102
103static SANE_Range x_range = { 0, 338, 2 };
104
105static SANE_Range odd_x_range = { 1, 339, 2 };
106
107static SANE_Range y_range = { 0, 249, 1 };
108
109static SANE_Range odd_y_range = { 1, 250, 1 };
110
111
112static SANE_Parameters parms = {
113  SANE_FRAME_RGB,
114  1,				/* 1 = Last Frame , 0 = More Frames to come */
115  0,				/* Number of bytes returned per scan line: */
116  0,				/* Number of pixels per scan line.  */
117  0,				/* Number of lines for the current scan.  */
118  8,				/* Number of bits per sample. */
119};
120
121static SANE_Status
122attach (const char *devname, V4L_Device ** devp)
123{
124  V4L_Device *dev;
125  static int v4lfd;
126  static struct video_capability capability;
127
128  errno = 0;
129
130  for (dev = first_dev; dev; dev = dev->next)
131    if (strcmp (dev->sane.name, devname) == 0)
132      {
133	if (devp)
134	  *devp = dev;
135	DBG (5, "attach: device %s is already known\n", devname);
136	return SANE_STATUS_GOOD;
137      }
138
139  DBG (3, "attach: trying to open %s\n", devname);
140  v4lfd = v4l1_open (devname, O_RDWR);
141  if (v4lfd != -1)
142    {
143      if (v4l1_ioctl (v4lfd, VIDIOCGCAP, &capability) == -1)
144	{
145	  DBG (1,
146	       "attach: ioctl (%d, VIDIOCGCAP,..) failed on `%s': %s\n",
147	       v4lfd, devname, strerror (errno));
148	  v4l1_close (v4lfd);
149	  return SANE_STATUS_INVAL;
150	}
151      if (!(VID_TYPE_CAPTURE & capability.type))
152	{
153	  DBG (1, "attach: device %s can't capture to memory -- exiting\n",
154	       devname);
155	  v4l1_close (v4lfd);
156	  return SANE_STATUS_UNSUPPORTED;
157	}
158      DBG (2, "attach: found videodev `%s' on `%s'\n", capability.name,
159	   devname);
160      v4l1_close (v4lfd);
161    }
162  else
163    {
164      DBG (1, "attach: failed to open device `%s': %s\n", devname,
165	   strerror (errno));
166      return SANE_STATUS_INVAL;
167    }
168
169  dev = malloc (sizeof (*dev));
170  if (!dev)
171    return SANE_STATUS_NO_MEM;
172
173  memset (dev, 0, sizeof (*dev));
174
175  dev->sane.name = strdup (devname);
176  if (!dev->sane.name)
177    return SANE_STATUS_NO_MEM;
178  dev->sane.vendor = "Noname";
179  dev->sane.model = strdup (capability.name);
180  if (!dev->sane.model)
181    return SANE_STATUS_NO_MEM;
182  dev->sane.type = "virtual device";
183
184  ++num_devices;
185  dev->next = first_dev;
186  first_dev = dev;
187
188  if (devp)
189    *devp = dev;
190  return SANE_STATUS_GOOD;
191}
192
193static void
194update_parameters (V4L_Scanner * s)
195{
196  /* ??? should be per-device */
197  x_range.min = 0;
198  x_range.max = s->capability.maxwidth - s->capability.minwidth;
199  x_range.quant = 1;
200
201  y_range.min = 0;
202  y_range.max = s->capability.maxheight - s->capability.minheight;
203  y_range.quant = 1;
204
205  odd_x_range.min = s->capability.minwidth;
206  odd_x_range.max = s->capability.maxwidth;
207  if (odd_x_range.max > 767)
208    {
209      odd_x_range.max = 767;
210      x_range.max = 767 - s->capability.minwidth;
211    };
212  odd_x_range.quant = 1;
213
214  odd_y_range.min = s->capability.minheight;
215  odd_y_range.max = s->capability.maxheight;
216  if (odd_y_range.max > 511)
217    {
218      odd_y_range.max = 511;
219      y_range.max = 511 - s->capability.minheight;
220    };
221  odd_y_range.quant = 1;
222
223  parms.lines = s->window.height;
224  parms.pixels_per_line = s->window.width;
225
226  switch (s->pict.palette)
227    {
228    case VIDEO_PALETTE_GREY:	/* Linear greyscale */
229      {
230	parms.format = SANE_FRAME_GRAY;
231	parms.depth = 8;
232	parms.bytes_per_line = s->window.width;
233	break;
234      }
235    case VIDEO_PALETTE_RGB24:	/* 24bit RGB */
236      {
237	parms.format = SANE_FRAME_RGB;
238	parms.depth = 8;
239	parms.bytes_per_line = s->window.width * 3;
240	break;
241      }
242    default:
243      {
244	parms.format = SANE_FRAME_GRAY;
245	parms.bytes_per_line = s->window.width;
246	break;
247      }
248    }
249}
250
251static SANE_Status
252init_options (V4L_Scanner * s)
253{
254  int i;
255
256  memset (s->opt, 0, sizeof (s->opt));
257  memset (s->val, 0, sizeof (s->val));
258
259  for (i = 0; i < NUM_OPTIONS; ++i)
260    {
261      s->opt[i].size = sizeof (SANE_Word);
262      s->opt[i].cap = (SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT);
263    }
264
265  /* Number of options */
266  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
267  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
268  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
269  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
270  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
271
272  /* "Mode" group: */
273  s->opt[OPT_MODE_GROUP].title = "Scan Mode";
274  s->opt[OPT_MODE_GROUP].desc = "";
275  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
276  s->opt[OPT_MODE_GROUP].cap = 0;
277  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
278
279  /* mode */
280  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
281  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
282  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
283  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
284  s->opt[OPT_MODE].unit = SANE_UNIT_NONE;
285  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
286  s->opt[OPT_MODE].constraint.string_list = mode_list;
287  s->val[OPT_MODE].s = strdup (mode_list[0]);
288  if (!s->val[OPT_MODE].s)
289    return SANE_STATUS_NO_MEM;
290  s->opt[OPT_MODE].size = 1; /* '\0' */
291  for (i = 0; mode_list[i] != 0; ++i)
292    {
293      int len = strlen(mode_list[i]) + 1;
294      if (s->opt[OPT_MODE].size < len)
295        s->opt[OPT_MODE].size = len;
296    }
297
298  /* channel */
299  s->opt[OPT_CHANNEL].name = "channel";
300  s->opt[OPT_CHANNEL].title = "Channel";
301  s->opt[OPT_CHANNEL].desc =
302    "Selects the channel of the v4l device (e.g. television " "or video-in.";
303  s->opt[OPT_CHANNEL].type = SANE_TYPE_STRING;
304  s->opt[OPT_CHANNEL].unit = SANE_UNIT_NONE;
305  s->opt[OPT_CHANNEL].constraint_type = SANE_CONSTRAINT_STRING_LIST;
306  s->opt[OPT_CHANNEL].constraint.string_list = s->channel;
307  s->val[OPT_CHANNEL].s = strdup (s->channel[0]);
308  if (!s->val[OPT_CHANNEL].s)
309    return SANE_STATUS_NO_MEM;
310  if (s->channel[0] == 0 || s->channel[1] == 0)
311    s->opt[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE;
312  s->opt[OPT_CHANNEL].size = 1; /* '\0' */
313  for (i = 0; s->channel[i] != 0; ++i)
314    {
315      int len = strlen(s->channel[i]) + 1;
316      if (s->opt[OPT_CHANNEL].size < len)
317        s->opt[OPT_CHANNEL].size = len;
318    }
319
320  /* "Geometry" group: */
321  s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
322  s->opt[OPT_GEOMETRY_GROUP].desc = "";
323  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
324  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
325  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
326
327/* top-left x *//* ??? first check if window is settable at all */
328  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
329  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
330  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
331  s->opt[OPT_TL_X].type = SANE_TYPE_INT;
332  s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
333  s->opt[OPT_TL_X].cap |= SANE_CAP_INACTIVE;
334  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
335  s->opt[OPT_TL_X].constraint.range = &x_range;
336  s->val[OPT_TL_X].w = 0;
337
338  /* top-left y */
339  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
340  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
341  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
342  s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
343  s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
344  s->opt[OPT_TL_Y].cap |= SANE_CAP_INACTIVE;
345  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
346  s->opt[OPT_TL_Y].constraint.range = &y_range;
347  s->val[OPT_TL_Y].w = 0;
348
349  /* bottom-right x */
350  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
351  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
352  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
353  s->opt[OPT_BR_X].type = SANE_TYPE_INT;
354  s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
355  s->opt[OPT_BR_X].cap |= SANE_CAP_INACTIVE;
356  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
357  s->opt[OPT_BR_X].constraint.range = &odd_x_range;
358  s->val[OPT_BR_X].w = s->capability.maxwidth;
359  if (s->val[OPT_BR_X].w > 767)
360    s->val[OPT_BR_X].w = 767;
361
362  /* bottom-right y */
363  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
364  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
365  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
366  s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
367  s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
368  s->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE;
369  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
370  s->opt[OPT_BR_Y].constraint.range = &odd_y_range;
371  s->val[OPT_BR_Y].w = s->capability.maxheight;
372  if (s->val[OPT_BR_Y].w > 511)
373    s->val[OPT_BR_Y].w = 511;
374
375  /* "Enhancement" group: */
376  s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
377  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
378  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
379  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
380  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
381
382  /* brightness */
383  s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
384  s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
385  s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
386  s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
387  s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
388  s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
389  s->val[OPT_BRIGHTNESS].w = s->pict.brightness / 256;
390
391  /* hue */
392  s->opt[OPT_HUE].name = SANE_NAME_HUE;
393  s->opt[OPT_HUE].title = SANE_TITLE_HUE;
394  s->opt[OPT_HUE].desc = SANE_DESC_HUE;
395  s->opt[OPT_HUE].type = SANE_TYPE_INT;
396  s->opt[OPT_HUE].constraint_type = SANE_CONSTRAINT_RANGE;
397  s->opt[OPT_HUE].constraint.range = &u8_range;
398  s->val[OPT_HUE].w = s->pict.hue / 256;
399
400  /* colour */
401  s->opt[OPT_COLOR].name = "color";
402  s->opt[OPT_COLOR].title = "Picture color";
403  s->opt[OPT_COLOR].desc = "Sets the picture's color.";
404  s->opt[OPT_COLOR].type = SANE_TYPE_INT;
405  s->opt[OPT_COLOR].constraint_type = SANE_CONSTRAINT_RANGE;
406  s->opt[OPT_COLOR].constraint.range = &u8_range;
407  s->val[OPT_COLOR].w = s->pict.colour / 256;
408
409  /* contrast */
410  s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
411  s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
412  s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
413  s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
414  s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
415  s->opt[OPT_CONTRAST].constraint.range = &u8_range;
416  s->val[OPT_CONTRAST].w = s->pict.contrast / 256;
417
418  /* whiteness */
419  s->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL;
420  s->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL;
421  s->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL;
422  s->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_INT;
423  s->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_RANGE;
424  s->opt[OPT_WHITE_LEVEL].constraint.range = &u8_range;
425  s->val[OPT_WHITE_LEVEL].w = s->pict.whiteness / 256;
426
427  return SANE_STATUS_GOOD;
428}
429
430SANE_Status
431sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
432{
433  char dev_name[PATH_MAX], *str;
434  size_t len;
435  FILE *fp;
436
437  (void) authorize;		/* stop gcc from complaining */
438  DBG_INIT ();
439
440  DBG (2, "SANE v4l backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR,
441       SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
442
443  if (version_code)
444    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
445
446  fp = sanei_config_open (V4L_CONFIG_FILE);
447  if (!fp)
448    {
449      DBG (2,
450	   "sane_init: file `%s' not accessible (%s), trying /dev/video0\n",
451	   V4L_CONFIG_FILE, strerror (errno));
452
453      return attach ("/dev/video0", 0);
454    }
455
456  while (sanei_config_read (dev_name, sizeof (dev_name), fp))
457    {
458      if (dev_name[0] == '#')	/* ignore line comments */
459	continue;
460      len = strlen (dev_name);
461
462      if (!len)
463	continue;		/* ignore empty lines */
464
465      /* Remove trailing space and trailing comments */
466      for (str = dev_name; *str && !isspace (*str) && *str != '#'; ++str);
467      attach (dev_name, 0);
468    }
469  fclose (fp);
470  return SANE_STATUS_GOOD;
471}
472
473void
474sane_exit (void)
475{
476  V4L_Device *dev, *next;
477
478  for (dev = first_dev; dev; dev = next)
479    {
480      next = dev->next;
481      free ((void *) dev->sane.name);
482      free ((void *) dev->sane.model);
483      free (dev);
484    }
485
486  if (NULL != devlist)
487    {
488      free (devlist);
489      devlist = NULL;
490    }
491  DBG (5, "sane_exit: all devices freed\n");
492}
493
494SANE_Status
495sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only)
496{
497  V4L_Device *dev;
498  int i;
499
500  DBG (5, "sane_get_devices\n");
501
502  if (devlist)
503    free (devlist);
504
505  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
506  if (!devlist)
507    return SANE_STATUS_NO_MEM;
508
509  i = 0;
510  for (dev = first_dev; i < num_devices; dev = dev->next)
511    devlist[i++] = &dev->sane;
512  devlist[i++] = 0;
513
514  *device_list = devlist;
515  return SANE_STATUS_GOOD;
516}
517
518SANE_Status
519sane_open (SANE_String_Const devname, SANE_Handle * handle)
520{
521  V4L_Device *dev;
522  V4L_Scanner *s;
523  static int v4lfd;
524  int i;
525  struct video_channel channel;
526  SANE_Status status;
527  int max_channels = MAX_CHANNELS;
528
529  if (!devname)
530    {
531      DBG (1, "sane_open: devname == 0\n");
532      return SANE_STATUS_INVAL;
533    }
534
535  for (dev = first_dev; dev; dev = dev->next)
536    if (strcmp (dev->sane.name, devname) == 0)
537      {
538	DBG (5, "sane_open: device %s found in devlist\n", devname);
539	break;
540      }
541  if (!devname[0])
542    dev = first_dev;
543  if (!dev)
544    {
545      DBG (1, "sane_open: device %s doesn't seem to be a v4l "
546	   "device\n", devname);
547      return SANE_STATUS_INVAL;
548    }
549
550  v4lfd = v4l1_open (devname, O_RDWR);
551  if (v4lfd == -1)
552    {
553      DBG (1, "sane_open: can't open %s (%s)\n", devname, strerror (errno));
554      return SANE_STATUS_INVAL;
555    }
556  s = malloc (sizeof (*s));
557  if (!s)
558    return SANE_STATUS_NO_MEM;
559  memset (s, 0, sizeof (*s));
560  s->user_corner = 0;		/* ??? */
561  s->devicename = devname;
562  s->fd = v4lfd;
563
564  if (v4l1_ioctl (s->fd, VIDIOCGCAP, &s->capability) == -1)
565    {
566      DBG (1, "sane_open: ioctl (%d, VIDIOCGCAP,..) failed on `%s': %s\n",
567	   s->fd, devname, strerror (errno));
568      v4l1_close (s->fd);
569      return SANE_STATUS_INVAL;
570    }
571
572  DBG (5, "sane_open: %d channels, %d audio devices\n",
573       s->capability.channels, s->capability.audios);
574  DBG (5, "sane_open: minwidth=%d, minheight=%d, maxwidth=%d, "
575       "maxheight=%d\n", s->capability.minwidth, s->capability.minheight,
576       s->capability.maxwidth, s->capability.maxheight);
577  if (VID_TYPE_CAPTURE & s->capability.type)
578    DBG (5, "sane_open: V4L device can capture to memory\n");
579  if (VID_TYPE_TUNER & s->capability.type)
580    DBG (5, "sane_open: V4L device has a tuner of some form\n");
581  if (VID_TYPE_TELETEXT & s->capability.type)
582    DBG (5, "sane_open: V4L device supports teletext\n");
583  if (VID_TYPE_OVERLAY & s->capability.type)
584    DBG (5, "sane_open: V4L device can overlay its image onto the frame "
585	 "buffer\n");
586  if (VID_TYPE_CHROMAKEY & s->capability.type)
587    DBG (5, "sane_open: V4L device uses chromakey on overlay\n");
588  if (VID_TYPE_CLIPPING & s->capability.type)
589    DBG (5, "sane_open: V4L device supports overlay clipping\n");
590  if (VID_TYPE_FRAMERAM & s->capability.type)
591    DBG (5, "sane_open: V4L device overwrites frame buffer memory\n");
592  if (VID_TYPE_SCALES & s->capability.type)
593    DBG (5, "sane_open: V4L device supports hardware scaling\n");
594  if (VID_TYPE_MONOCHROME & s->capability.type)
595    DBG (5, "sane_open: V4L device is grey scale only\n");
596  if (VID_TYPE_SUBCAPTURE & s->capability.type)
597    DBG (5, "sane_open: V4L device can capture parts of the image\n");
598
599  if (s->capability.channels < max_channels)
600    max_channels = s->capability.channels;
601  for (i = 0; i < max_channels; i++)
602    {
603      channel.channel = i;
604      if (-1 == v4l1_ioctl (v4lfd, VIDIOCGCHAN, &channel))
605	{
606	  DBG (1, "sane_open: can't ioctl VIDIOCGCHAN %s: %s\n", devname,
607	       strerror (errno));
608	  return SANE_STATUS_INVAL;
609	}
610      DBG (5, "sane_open: channel %d (%s), tuners=%d, flags=0x%x, "
611	   "type=%d, norm=%d\n", channel.channel, channel.name,
612	   channel.tuners, channel.flags, channel.type, channel.norm);
613      if (VIDEO_VC_TUNER & channel.flags)
614	DBG (5, "sane_open: channel has tuner(s)\n");
615      if (VIDEO_VC_AUDIO & channel.flags)
616	DBG (5, "sane_open: channel has audio\n");
617      if (VIDEO_TYPE_TV == channel.type)
618	DBG (5, "sane_open: input is TV input\n");
619      if (VIDEO_TYPE_CAMERA == channel.type)
620	DBG (5, "sane_open: input is camera input\n");
621      s->channel[i] = strdup (channel.name);
622      if (!s->channel[i])
623	return SANE_STATUS_NO_MEM;
624    }
625  s->channel[i] = 0;
626  if (-1 == v4l1_ioctl (v4lfd, VIDIOCGPICT, &s->pict))
627    {
628      DBG (1, "sane_open: can't ioctl VIDIOCGPICT %s: %s\n", devname,
629	   strerror (errno));
630      return SANE_STATUS_INVAL;
631    }
632  DBG (5, "sane_open: brightness=%d, hue=%d, colour=%d, contrast=%d\n",
633       s->pict.brightness, s->pict.hue, s->pict.colour, s->pict.contrast);
634  DBG (5, "sane_open: whiteness=%d, depth=%d, palette=%d\n",
635       s->pict.whiteness, s->pict.depth, s->pict.palette);
636
637  /* ??? */
638  s->pict.palette = VIDEO_PALETTE_GREY;
639  if (-1 == v4l1_ioctl (s->fd, VIDIOCSPICT, &s->pict))
640    {
641      DBG (1, "sane_open: ioctl VIDIOCSPICT failed (%s)\n", strerror (errno));
642    }
643
644  if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window))
645    {
646      DBG (1, "sane_open: can't ioctl VIDIOCGWIN %s: %s\n", devname,
647	   strerror (errno));
648      return SANE_STATUS_INVAL;
649    }
650  DBG (5, "sane_open: x=%d, y=%d, width=%d, height=%d\n",
651       s->window.x, s->window.y, s->window.width, s->window.height);
652
653  /* already done in sane_start
654     if (-1 == v4l1_ioctl (v4lfd, VIDIOCGMBUF, &mbuf))
655     DBG (1, "sane_open: can't ioctl VIDIOCGMBUF (no Fbuffer?)\n");
656   */
657
658  status = init_options (s);
659  if (status != SANE_STATUS_GOOD)
660    return status;
661  update_parameters (s);
662
663  /* insert newly opened handle into list of open handles: */
664  s->next = first_handle;
665  first_handle = s;
666
667  *handle = s;
668
669  return SANE_STATUS_GOOD;
670}
671
672void
673sane_close (SANE_Handle handle)
674{
675  V4L_Scanner *prev, *s;
676
677  DBG (2, "sane_close: trying to close handle %p\n", (void *) handle);
678  /* remove handle from list of open handles: */
679  prev = 0;
680  for (s = first_handle; s; s = s->next)
681    {
682      if (s == handle)
683	break;
684      prev = s;
685    }
686  if (!s)
687    {
688      DBG (1, "sane_close: bad handle %p\n", handle);
689      return;			/* oops, not a handle we know about */
690    }
691  if (prev)
692    prev->next = s->next;
693  else
694    first_handle = s->next;
695
696  if (s->scanning)
697    sane_cancel (handle);
698  v4l1_close (s->fd);
699  free (s);
700}
701
702const SANE_Option_Descriptor *
703sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
704{
705  V4L_Scanner *s = handle;
706
707  if ((unsigned) option >= NUM_OPTIONS || option < 0)
708    return 0;
709  DBG (4, "sane_get_option_descriptor: option %d (%s)\n", option,
710       s->opt[option].name ? s->opt[option].name : s->opt[option].title);
711  return s->opt + option;
712}
713
714SANE_Status
715sane_control_option (SANE_Handle handle, SANE_Int option,
716		     SANE_Action action, void *val, SANE_Int * info)
717{
718  V4L_Scanner *s = handle;
719  SANE_Status status;
720  SANE_Word cap;
721
722  if (info)
723    *info = 0;
724
725  if (option >= NUM_OPTIONS || option < 0)
726    return SANE_STATUS_INVAL;
727
728  DBG (4, "sane_control_option: %s option %d (%s)\n",
729       action == SANE_ACTION_GET_VALUE ? "get" :
730       action == SANE_ACTION_SET_VALUE ? "set" :
731       action == SANE_ACTION_SET_AUTO ? "auto set" :
732       "(unknown action with)", option,
733       s->opt[option].name ? s->opt[option].name : s->opt[option].title);
734
735  cap = s->opt[option].cap;
736
737  if (!SANE_OPTION_IS_ACTIVE (cap))
738    {
739      DBG (1, "sane_control option: option is inactive\n");
740      return SANE_STATUS_INVAL;
741    }
742
743  if (action == SANE_ACTION_GET_VALUE)
744    {
745      switch (option)
746	{
747	  /* word options: */
748	case OPT_NUM_OPTS:
749	case OPT_TL_X:
750	case OPT_TL_Y:
751	case OPT_BR_X:
752	case OPT_BR_Y:
753	case OPT_BRIGHTNESS:
754	case OPT_HUE:
755	case OPT_COLOR:
756	case OPT_CONTRAST:
757	case OPT_WHITE_LEVEL:
758	  *(SANE_Word *) val = s->val[option].w;
759	  return SANE_STATUS_GOOD;
760	case OPT_CHANNEL:	/* string list options */
761	case OPT_MODE:
762	  strcpy (val, s->val[option].s);
763	  return SANE_STATUS_GOOD;
764	default:
765	  DBG (1, "sane_control_option: option %d unknown\n", option);
766	}
767    }
768  else if (action == SANE_ACTION_SET_VALUE)
769    {
770      if (!SANE_OPTION_IS_SETTABLE (cap))
771	{
772	  DBG (1, "sane_control_option: option is not settable\n");
773	  return SANE_STATUS_INVAL;
774	}
775      status = sanei_constrain_value (s->opt + option, val, info);
776      if (status != SANE_STATUS_GOOD)
777	{
778	  DBG (1, "sane_control_option: sanei_constarin_value failed: %s\n",
779	       sane_strstatus (status));
780	  return status;
781	}
782      if (option >= OPT_TL_X && option <= OPT_BR_Y)
783	{
784	  s->user_corner |= 1 << (option - OPT_TL_X);
785	  if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window))
786	    {
787	      DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed "
788		   "(can not get window geometry)\n");
789	      return SANE_STATUS_INVAL;
790	    }
791	  s->window.clipcount = 0;
792	  s->window.clips = 0;
793	  s->window.height = parms.lines;
794	  s->window.width = parms.pixels_per_line;
795	}
796
797
798      switch (option)
799	{
800	  /* (mostly) side-effect-free word options: */
801	case OPT_TL_X:
802	  break;
803	case OPT_TL_Y:
804	  break;
805	case OPT_BR_X:
806	  s->window.width = *(SANE_Word *) val;
807	  parms.pixels_per_line = *(SANE_Word *) val;
808	  if (info)
809	    *info |= SANE_INFO_RELOAD_PARAMS;
810	  break;
811	case OPT_BR_Y:
812	  s->window.height = *(SANE_Word *) val;
813	  parms.lines = *(SANE_Word *) val;
814	  if (info)
815	    *info |= SANE_INFO_RELOAD_PARAMS;
816	  break;
817	case OPT_MODE:
818	  if (info)
819	    *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
820	  s->val[option].s = strdup (val);
821	  if (!s->val[option].s)
822	    return SANE_STATUS_NO_MEM;
823	  if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
824	    s->pict.palette = VIDEO_PALETTE_GREY;
825	  else
826	    s->pict.palette = VIDEO_PALETTE_RGB24;
827	  update_parameters (s);
828	  break;
829	case OPT_BRIGHTNESS:
830	  s->pict.brightness = *(SANE_Word *) val *256;
831	  s->val[option].w = *(SANE_Word *) val;
832	  break;
833	case OPT_HUE:
834	  s->pict.hue = *(SANE_Word *) val *256;
835	  s->val[option].w = *(SANE_Word *) val;
836	  break;
837	case OPT_COLOR:
838	  s->pict.colour = *(SANE_Word *) val *256;
839	  s->val[option].w = *(SANE_Word *) val;
840	  break;
841	case OPT_CONTRAST:
842	  s->pict.contrast = *(SANE_Word *) val *256;
843	  s->val[option].w = *(SANE_Word *) val;
844	  break;
845	case OPT_WHITE_LEVEL:
846	  s->pict.whiteness = *(SANE_Word *) val *256;
847	  s->val[option].w = *(SANE_Word *) val;
848	  break;
849	case OPT_CHANNEL:
850	  {
851	    int i;
852	    struct video_channel channel;
853
854	    s->val[option].s = strdup (val);
855	    if (!s->val[option].s)
856	      return SANE_STATUS_NO_MEM;
857	    for (i = 0; i < MAX_CHANNELS; i++)
858	      {
859		if (strcmp (s->channel[i], val) == 0)
860		  {
861		    channel.channel = i;
862		    if (-1 == v4l1_ioctl (s->fd, VIDIOCGCHAN, &channel))
863		      {
864			DBG (1, "sane_open: can't ioctl VIDIOCGCHAN %s: %s\n",
865			     s->devicename, strerror (errno));
866			return SANE_STATUS_INVAL;
867		      }
868		    if (-1 == v4l1_ioctl (s->fd, VIDIOCSCHAN, &channel))
869		      {
870			DBG (1, "sane_open: can't ioctl VIDIOCSCHAN %s: %s\n",
871			     s->devicename, strerror (errno));
872			return SANE_STATUS_INVAL;
873		      }
874		    break;
875		  }
876	      }
877	    return SANE_STATUS_GOOD;
878	    break;
879	  }
880	default:
881	  DBG (1, "sane_control_option: option %d unknown\n", option);
882	  return SANE_STATUS_INVAL;
883	}
884      if (option >= OPT_TL_X && option <= OPT_BR_Y)
885	{
886	  if (-1 == v4l1_ioctl (s->fd, VIDIOCSWIN, &s->window))
887	    {
888	      DBG (1, "sane_control_option: ioctl VIDIOCSWIN failed (%s)\n",
889		   strerror (errno));
890	      /* return SANE_STATUS_INVAL; */
891	    }
892	  if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window))
893	    {
894	      DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed (%s)\n",
895		   strerror (errno));
896	      return SANE_STATUS_INVAL;
897	    }
898	}
899      if (option >= OPT_BRIGHTNESS && option <= OPT_WHITE_LEVEL)
900	{
901	  if (-1 == v4l1_ioctl (s->fd, VIDIOCSPICT, &s->pict))
902	    {
903	      DBG (1, "sane_control_option: ioctl VIDIOCSPICT failed (%s)\n",
904		   strerror (errno));
905	      /* return SANE_STATUS_INVAL; */
906	    }
907	}
908      return SANE_STATUS_GOOD;
909    }
910  else if (action == SANE_ACTION_SET_AUTO)
911    {
912      if (!(cap & SANE_CAP_AUTOMATIC))
913	{
914	  DBG (1, "sane_control_option: option can't be set automatically\n");
915	  return SANE_STATUS_INVAL;
916	}
917      switch (option)
918	{
919	case OPT_BRIGHTNESS:
920	  /* not implemented yet */
921	  return SANE_STATUS_GOOD;
922
923	default:
924	  break;
925	}
926    }
927  return SANE_STATUS_INVAL;
928}
929
930SANE_Status
931sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
932{
933  V4L_Scanner *s = handle;
934
935  DBG (4, "sane_get_parameters\n");
936  update_parameters (s);
937  if (params == 0)
938    {
939      DBG (1, "sane_get_parameters: params == 0\n");
940      return SANE_STATUS_INVAL;
941    }
942  if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window))
943    {
944      DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed "
945	   "(can not get window geometry)\n");
946      return SANE_STATUS_INVAL;
947    }
948  parms.pixels_per_line = s->window.width;
949  parms.bytes_per_line = s->window.width;
950  if (parms.format == SANE_FRAME_RGB)
951    parms.bytes_per_line = s->window.width * 3;
952  parms.lines = s->window.height;
953  *params = parms;
954  return SANE_STATUS_GOOD;
955
956}
957
958SANE_Status
959sane_start (SANE_Handle handle)
960{
961  int len;
962  V4L_Scanner *s;
963  char data;
964
965  DBG (2, "sane_start\n");
966  for (s = first_handle; s; s = s->next)
967    {
968      if (s == handle)
969	break;
970    }
971  if (!s)
972    {
973      DBG (1, "sane_start: bad handle %p\n", handle);
974      return SANE_STATUS_INVAL;	/* oops, not a handle we know about */
975    }
976  len = v4l1_ioctl (s->fd, VIDIOCGCAP, &s->capability);
977  if (-1 == len)
978    {
979      DBG (1, "sane_start: can not get capabilities\n");
980      return SANE_STATUS_INVAL;
981    }
982  s->buffercount = 0;
983  if (-1 == v4l1_ioctl (s->fd, VIDIOCGMBUF, &s->mbuf))
984    {
985      s->is_mmap = SANE_FALSE;
986      buffer =
987	malloc (s->capability.maxwidth * s->capability.maxheight *
988		s->pict.depth);
989      if (0 == buffer)
990	return SANE_STATUS_NO_MEM;
991      DBG (3, "sane_start: V4L trying to read frame\n");
992      len = v4l1_read (s->fd, buffer, parms.bytes_per_line * parms.lines);
993      DBG (3, "sane_start: %d bytes read\n", len);
994    }
995  else
996    {
997      int loop;
998      s->is_mmap = SANE_TRUE;
999      DBG (3,
1000	   "sane_start: mmap frame, buffersize: %d bytes, buffers: %d, offset 0 %d\n",
1001	   s->mbuf.size, s->mbuf.frames, s->mbuf.offsets[0]);
1002      buffer =
1003	v4l1_mmap (0, s->mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0);
1004      if (buffer == (void *)-1)
1005	{
1006	  DBG (1, "sane_start: mmap failed: %s\n", strerror (errno));
1007	  buffer = NULL;
1008	  return SANE_STATUS_IO_ERROR;
1009	}
1010      DBG (3, "sane_start: mmapped frame, capture 1 pict into %p\n", (void *) buffer);
1011      s->mmap.frame = 0;
1012      s->mmap.width = s->window.width;
1013      /*   s->mmap.width = parms.pixels_per_line;  ??? huh? */
1014      s->mmap.height = s->window.height;
1015      /*      s->mmap.height = parms.lines;  ??? huh? */
1016      s->mmap.format = s->pict.palette;
1017      DBG (2, "sane_start: mmapped frame %d x %d with palette %d\n",
1018	   s->mmap.width, s->mmap.height, s->mmap.format);
1019
1020      /* We need to loop here to empty the read buffers, so we don't
1021         get a stale image */
1022      for (loop = 0; loop <= s->mbuf.frames; loop++)
1023        {
1024          len = v4l1_ioctl (s->fd, VIDIOCMCAPTURE, &s->mmap);
1025          if (len == -1)
1026	    {
1027	      DBG (1, "sane_start: ioctl VIDIOCMCAPTURE failed: %s\n",
1028	           strerror (errno));
1029	      return SANE_STATUS_INVAL;
1030	    }
1031          DBG (3, "sane_start: waiting for frame %x, loop %d\n", s->mmap.frame, loop);
1032          len = v4l1_ioctl (s->fd, VIDIOCSYNC, &(s->mmap.frame));
1033          if (-1 == len)
1034	    {
1035	      DBG (1, "sane_start: call to ioctl(%d, VIDIOCSYNC, ..) failed\n",
1036	           s->fd);
1037	      return SANE_STATUS_INVAL;
1038	    }
1039        }
1040      DBG (3, "sane_start: frame %x done\n", s->mmap.frame);
1041    }
1042
1043  /* v4l1 actually returns BGR when we ask for RGB, so convert it */
1044  if (s->pict.palette == VIDEO_PALETTE_RGB24)
1045    {
1046      uint32_t loop;
1047      DBG (3, "sane_start: converting from BGR to RGB\n");
1048      for (loop = 0; loop < (s->window.width * s->window.height * 3); loop += 3)
1049        {
1050          data = *(buffer + loop);
1051          *(buffer + loop) = *(buffer + loop + 2);
1052          *(buffer + loop + 2) = data;
1053        }
1054    }
1055
1056  DBG (3, "sane_start: done\n");
1057  return SANE_STATUS_GOOD;
1058}
1059
1060SANE_Status
1061sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1062	   SANE_Int * lenp)
1063{
1064  int i, min;
1065  V4L_Scanner *s = handle;
1066
1067  DBG (4, "sane_read: max_len = %d\n", max_len);
1068  if (!lenp)
1069    {
1070      DBG (1, "sane_read: lenp == 0\n");
1071      return SANE_STATUS_INVAL;
1072    }
1073  if ((s->buffercount + 1) > (parms.lines * parms.bytes_per_line))
1074    {
1075      *lenp = 0;
1076      return SANE_STATUS_EOF;
1077    };
1078  min = parms.lines * parms.bytes_per_line;
1079  if (min > (max_len + s->buffercount))
1080    min = (max_len + s->buffercount);
1081  if (s->is_mmap == SANE_FALSE)
1082    {
1083      for (i = s->buffercount; i < (min + 0); i++)
1084	{
1085	  *(buf + i - s->buffercount) = *(buffer + i);
1086	};
1087      *lenp = (parms.lines * parms.bytes_per_line - s->buffercount);
1088      if (max_len < *lenp)
1089	*lenp = max_len;
1090      DBG (3, "sane_read: transferred %d bytes (from %d to %d)\n", *lenp,
1091	   s->buffercount, i);
1092      s->buffercount = i;
1093    }
1094  else
1095    {
1096      for (i = s->buffercount; i < (min + 0); i++)
1097	{
1098	  *(buf + i - s->buffercount) = *(buffer + i);
1099	};
1100      *lenp = (parms.lines * parms.bytes_per_line - s->buffercount);
1101      if ((i - s->buffercount) < *lenp)
1102	*lenp = (i - s->buffercount);
1103      DBG (3, "sane_read: transferred %d bytes (from %d to %d)\n", *lenp,
1104	   s->buffercount, i);
1105      s->buffercount = i;
1106    }
1107  return SANE_STATUS_GOOD;
1108}
1109
1110void
1111sane_cancel (SANE_Handle handle)
1112{
1113  V4L_Scanner *s = handle;
1114
1115  DBG (2, "sane_cancel\n");
1116
1117  /* ??? buffer isn't checked in sane_read? */
1118  if (buffer)
1119    {
1120      if (s->is_mmap)
1121	v4l1_munmap(buffer, s->mbuf.size);
1122      else
1123	free (buffer);
1124
1125      buffer = NULL;
1126    }
1127}
1128
1129
1130SANE_Status
1131sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool non_blocking)
1132{
1133  if (non_blocking == SANE_FALSE)
1134    return SANE_STATUS_GOOD;
1135  return SANE_STATUS_UNSUPPORTED;
1136}
1137
1138SANE_Status
1139sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)
1140{
1141  return SANE_STATUS_UNSUPPORTED;
1142}
1143