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
87 static const SANE_Device **devlist = NULL;
88 static int num_devices;
89 static V4L_Device *first_dev;
90 static V4L_Scanner *first_handle;
91 static char *buffer;
92
93 static const SANE_String_Const mode_list[] = {
94 SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR,
95 0
96 };
97
98 static const SANE_Range u8_range = {
99 /* min, max, quantization */
100 0, 255, 0
101 };
102
103 static SANE_Range x_range = { 0, 338, 2 };
104
105 static SANE_Range odd_x_range = { 1, 339, 2 };
106
107 static SANE_Range y_range = { 0, 249, 1 };
108
109 static SANE_Range odd_y_range = { 1, 250, 1 };
110
111
112 static 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
121 static SANE_Status
attach(const char *devname, V4L_Device ** devp)122 attach (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
193 static void
update_parameters(V4L_Scanner * s)194 update_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
251 static SANE_Status
init_options(V4L_Scanner * s)252 init_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
430 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)431 sane_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
473 void
sane_exit(void)474 sane_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
494 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only)495 sane_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
518 SANE_Status
sane_open(SANE_String_Const devname, SANE_Handle * handle)519 sane_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
672 void
sane_close(SANE_Handle handle)673 sane_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
702 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)703 sane_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
714 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)715 sane_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
930 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)931 sane_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
958 SANE_Status
sane_start(SANE_Handle handle)959 sane_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
1060 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * lenp)1061 sane_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
1110 void
sane_cancel(SANE_Handle handle)1111 sane_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
1130 SANE_Status
sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool non_blocking)1131 sane_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
1138 SANE_Status
sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)1139 sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)
1140 {
1141 return SANE_STATUS_UNSUPPORTED;
1142 }
1143