1 /*
2  * magicolor.c - SANE library for Magicolor scanners.
3  *
4  * (C) 2010 Reinhold Kainhofer <reinhold@kainhofer.com>
5  *
6  * Based on the epson2 sane backend:
7  * Based on Kazuhiro Sasayama previous
8  * Work on epson.[ch] file from the SANE package.
9  * Please see those files for additional copyrights.
10  * Copyright (C) 2006-10 Tower Technologies
11  * Author: Alessandro Zummo <a.zummo@towertech.it>
12  *
13  * This file is part of the SANE package.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation, version 2.
18  */
19 
20 #define MAGICOLOR_VERSION	0
21 #define MAGICOLOR_REVISION	0
22 #define MAGICOLOR_BUILD	1
23 
24 /* debugging levels:
25  *
26  *     127	mc_recv buffer
27  *     125	mc_send buffer
28  *	35	fine-grained status and progress
29  *	30	sane_read
30  *	25	setvalue, getvalue, control_option
31  *	20	low-level (I/O) mc_* functions
32  *	15	mid-level mc_* functions
33  *	10	high-level cmd_* functions
34  *	 7	open/close/attach
35  *	 6	print_params
36  *	 5	basic functions
37  *	 3	status info and progress
38  *	 2	scanner info and capabilities
39  *	 1	errors & warnings
40  */
41 
42 #include "sane/config.h"
43 
44 #include <limits.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <ctype.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <sys/time.h>
53 #include <math.h>
54 #include <poll.h>
55 #include <sys/types.h>
56 #ifdef HAVE_SYS_SOCKET_H
57 #include <sys/socket.h>
58 #endif
59 
60 
61 #if HAVE_LIBSNMP
62 #include <net-snmp/net-snmp-config.h>
63 #include <net-snmp/net-snmp-includes.h>
64 #include <net-snmp/library/snmp_transport.h>
65 #include <arpa/inet.h>
66 #endif
67 
68 #include "../include/sane/saneopts.h"
69 #include "../include/sane/sanei_usb.h"
70 #include "../include/sane/sanei_tcp.h"
71 #include "../include/sane/sanei_udp.h"
72 #include "../include/sane/sanei_config.h"
73 #include "../include/sane/sanei_backend.h"
74 
75 #include "magicolor.h"
76 
77 
78 #define min(x,y) (((x)<(y))?(x):(y))
79 
80 
81 
82 /****************************************************************************
83  *   Devices supported by this backend
84  ****************************************************************************/
85 
86 
87 
88 /*          Scanner command type
89  *          |     Start scan
90  *          |     |     Poll for error
91  *          |     |     |     Stop scan?
92  *          |     |     |     |     Query image parameters
93  *          |     |     |     |     |     set scan parameters
94  *          |     |     |     |     |     |     Get status?
95  *          |     |     |     |     |     |     |     Read scanned data
96  *          |     |     |     |     |     |     |     |     Unknown
97  *          |     |     |     |     |     |     |     |     |     Unknown
98  *          |     |     |     |     |     |     |     |     |     |     Net wrapper command type
99  *          |     |     |     |     |     |     |     |     |     |     |     Net Welcome
100  *          |     |     |     |     |     |     |     |     |     |     |     |     Net Lock
101  *          |     |     |     |     |     |     |     |     |     |     |     |     |     Net Lock ACK
102  *          |     |     |     |     |     |     |     |     |     |     |     |     |     |     Net Unlock
103  *          |     |     |     |     |     |     |     |     |     |     |     |     |     |     |
104 */
105 static struct MagicolorCmd magicolor_cmd[] = {
106   {"mc1690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03},
107   {"mc4690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03},
108 };
109 
110 static SANE_Int magicolor_default_resolutions[] = {150, 300, 600};
111 static SANE_Int magicolor_default_depths[] = {1,8};
112 
113 static struct MagicolorCap magicolor_cap[] = {
114 
115   /* KONICA MINOLTA magicolor 1690MF, USB ID 0x123b:2089 */
116   {
117       0x2089, "mc1690mf", "KONICA MINOLTA magicolor 1690MF", ".1.3.6.1.4.1.18334.1.1.1.1.1.23.1.1",
118       -1, 0x85,
119       600, {150, 600, 0}, magicolor_default_resolutions, 3,  /* 600 dpi max, 3 resolutions */
120       8, magicolor_default_depths,                          /* color depth 8 default, 1 and 8 possible */
121       {1, 9, 0},                                             /* brightness ranges (TODO!) */
122       {0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, /* FBF x/y ranges (TODO!) */
123       SANE_TRUE, SANE_FALSE, /* non-duplex ADF, x/y ranges (TODO!) */
124       {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0},
125   },
126 
127   /* KONICA MINOLTA magicolor 4690MF, USB ID 0x132b:2079 */
128   {
129       0x2079, "mc4690mf", "KONICA MINOLTA magicolor 4690MF",
130       "FIXME",                                              /* FIXME: fill in the correct OID! */
131       0x03, 0x85,
132       600, {150, 600, 0}, magicolor_default_resolutions, 3,  /* 600 dpi max, 3 resolutions */
133       8, magicolor_default_depths,                          /* color depth 8 default, 1 and 8 possible */
134       {1, 9, 0},                                             /* brightness ranges (TODO!) */
135       {0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, /* FBF x/y ranges (TODO!) */
136       SANE_TRUE, SANE_TRUE, /* duplex ADF, x/y ranges (TODO!) */
137       {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0},
138   },
139 
140 };
141 
142 static int MC_SNMP_Timeout = 2500;
143 static int MC_Scan_Data_Timeout = 15000;
144 static int MC_Request_Timeout = 5000;
145 
146 
147 
148 /****************************************************************************
149  *   General configuration parameter definitions
150  ****************************************************************************/
151 
152 
153 /*
154  * Definition of the mode_param struct, that is used to
155  * specify the valid parameters for the different scan modes.
156  *
157  * The depth variable gets updated when the bit depth is modified.
158  */
159 
160 static struct mode_param mode_params[] = {
161 	{0x00, 1, 1},  /* Lineart, 1 color, 1 bit */
162 	{0x02, 1, 24}, /* Grayscale, 1 color, 24 bit */
163 	{0x03, 3, 24}  /* Color, 3 colors, 24 bit */
164 };
165 
166 static SANE_String_Const mode_list[] = {
167 	SANE_VALUE_SCAN_MODE_LINEART,
168 	SANE_VALUE_SCAN_MODE_GRAY,
169 	SANE_VALUE_SCAN_MODE_COLOR,
170 	NULL
171 };
172 
173 static const SANE_String_Const adf_mode_list[] = {
174 	SANE_I18N("Simplex"),
175 	SANE_I18N("Duplex"),
176 	NULL
177 };
178 
179 /* Define the different scan sources */
180 
181 #define FBF_STR	SANE_I18N("Flatbed")
182 #define ADF_STR	SANE_I18N("Automatic Document Feeder")
183 
184 /*
185  * source list need one dummy entry (save device settings is crashing).
186  * NOTE: no const - this list gets created while exploring the capabilities
187  * of the scanner.
188  */
189 
190 static SANE_String_Const source_list[] = {
191 	FBF_STR,
192 	NULL,
193 	NULL,
194 	NULL
195 };
196 
197 /* Some utility functions */
198 
199 static size_t
max_string_size(const SANE_String_Const strings[])200 max_string_size(const SANE_String_Const strings[])
201 {
202 	size_t size, max_size = 0;
203 	int i;
204 
205 	for (i = 0; strings[i]; i++) {
206 		size = strlen(strings[i]) + 1;
207 		if (size > max_size)
208 			max_size = size;
209 	}
210 	return max_size;
211 }
212 
213 static SANE_Status attach_one_usb(SANE_String_Const devname);
214 static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device);
215 
216 static void
print_params(const SANE_Parameters params)217 print_params(const SANE_Parameters params)
218 {
219 	DBG(6, "params.format          = %d\n", params.format);
220 	DBG(6, "params.last_frame      = %d\n", params.last_frame);
221 	DBG(6, "params.bytes_per_line  = %d\n", params.bytes_per_line);
222 	DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line);
223 	DBG(6, "params.lines           = %d\n", params.lines);
224 	DBG(6, "params.depth           = %d\n", params.depth);
225 }
226 
227 
228 
229 /****************************************************************************
230  *   Low-level Network communication functions
231  ****************************************************************************/
232 
233 
234 #define MAGICOLOR_SNMP_SYSDESCR_OID  ".1.3.6.1.2.1.1.1.0"
235 #define MAGICOLOR_SNMP_SYSOBJECT_OID ".1.3.6.1.2.1.1.2.0"
236 #define MAGICOLOR_SNMP_MAC_OID       ".1.3.6.1.2.1.2.2.1.6.1"
237 #define MAGICOLOR_SNMP_DEVICE_TREE   ".1.3.6.1.4.1.18334.1.1.1.1.1"
238 
239 
240 /* We don't have a packet wrapper, which holds packet size etc., so we
241    don't have to use a *read_raw and a *_read function... */
242 static int
sanei_magicolor_net_read(struct Magicolor_Scanner *s, unsigned char *buf, size_t wanted, SANE_Status * status)243 sanei_magicolor_net_read(struct Magicolor_Scanner *s, unsigned char *buf, size_t wanted,
244 		       SANE_Status * status)
245 {
246 	size_t size, read = 0;
247 	struct pollfd fds[1];
248 
249 	*status = SANE_STATUS_GOOD;
250 
251 	/* poll for data-to-be-read (using a 5 seconds timeout) */
252 	fds[0].fd = s->fd;
253 	fds[0].events = POLLIN;
254 	if (poll (fds, 1, MC_Request_Timeout) <= 0) {
255 		*status = SANE_STATUS_IO_ERROR;
256 		return read;
257 	}
258 
259 	while (read < wanted) {
260 		size = sanei_tcp_read(s->fd, buf + read, wanted - read);
261 
262 		if (size == 0)
263 			break;
264 
265 		read += size;
266 	}
267 
268 	if (read < wanted)
269 		*status = SANE_STATUS_IO_ERROR;
270 
271 	return read;
272 }
273 
274 /* We need to optionally pad the buffer with 0x00 to send 64-byte chunks.
275    On the other hand, the 0x04 commands don't need this, so we need two
276    functions, one *_write function that pads the buffer and then calls
277     *_write_raw */
278 static int
sanei_magicolor_net_write_raw(struct Magicolor_Scanner *s, const unsigned char *buf, size_t buf_size, SANE_Status *status)279 sanei_magicolor_net_write_raw(struct Magicolor_Scanner *s,
280 			      const unsigned char *buf, size_t buf_size,
281 			      SANE_Status *status)
282 {
283 	sanei_tcp_write(s->fd, buf, buf_size);
284 	/* TODO: Check whether sending failed... */
285 
286 	*status = SANE_STATUS_GOOD;
287 	return buf_size;
288 }
289 
290 static int
sanei_magicolor_net_write(struct Magicolor_Scanner *s, const unsigned char *buf, size_t buf_size, SANE_Status *status)291 sanei_magicolor_net_write(struct Magicolor_Scanner *s,
292 			  const unsigned char *buf, size_t buf_size,
293 			  SANE_Status *status)
294 {
295 	size_t len = 64;
296 	unsigned char *new_buf = malloc(len);
297 	if (!new_buf) {
298 		*status = SANE_STATUS_NO_MEM;
299 		return 0;
300 	}
301 	memset(new_buf, 0x00, len);
302 	if (buf_size > len)
303 		buf_size = len;
304 	if (buf_size)
305 		memcpy(new_buf, buf, buf_size);
306 	return sanei_magicolor_net_write_raw (s, new_buf, len, status);
307 }
308 
309 static SANE_Status
sanei_magicolor_net_open(struct Magicolor_Scanner *s)310 sanei_magicolor_net_open(struct Magicolor_Scanner *s)
311 {
312 	SANE_Status status;
313 	unsigned char buf[5];
314 
315 	ssize_t read;
316 	struct timeval tv;
317 	struct MagicolorCmd *cmd = s->hw->cmd;
318 
319 	tv.tv_sec = 5;
320 	tv.tv_usec = 0;
321 
322 	setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,  sizeof(tv));
323 
324 	DBG(1, "%s\n", __func__);
325 
326 	/* the scanner sends a kind of welcome msg */
327 	read = sanei_magicolor_net_read(s, buf, 3, &status);
328 	if (read != 3)
329 		return SANE_STATUS_IO_ERROR;
330 	if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_welcome) {
331 		DBG (32, "Invalid welcome message received, Expected 0x%02x %02x 00, but got 0x%02x %02x %02x\n",
332 			cmd->net_wrapper_cmd, cmd->net_welcome, buf[0], buf[1], buf[2]);
333 		return SANE_STATUS_IO_ERROR;
334 	} else if (buf[2] != 0x00) {
335 		/* TODO: Handle response "04 00 01", indicating an error! */
336 		DBG (32, "Welcome message received, busy status %02x\n", buf[2]);
337 		/* TODO: Return a human-readable error message (Unable to connect to scanner, scanner is not ready) */
338 		return SANE_STATUS_DEVICE_BUSY;
339 	}
340 
341 	buf[0] = cmd->net_wrapper_cmd;
342 	buf[1] = cmd->net_lock;
343 	buf[2] = 0x00;
344 	/* Copy the device's USB id to bytes 3-4: */
345 	buf[3] = s->hw->cap->id & 0xff;
346 	buf[4] = (s->hw->cap->id >> 8) & 0xff;
347 
348 	DBG(32, "Proper welcome message received, locking the scanner...\n");
349 	sanei_magicolor_net_write_raw(s, buf, 5, &status);
350 
351 	read = sanei_magicolor_net_read(s, buf, 3, &status);
352 	if (read != 3)
353 		return SANE_STATUS_IO_ERROR;
354 	if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_lock_ack || buf[2] != 0x00) {
355 		DBG (32, "Welcome message received, Expected 0x%x %x 00, but got 0x%x %x %x\n",
356 			cmd->net_wrapper_cmd, cmd->net_lock_ack, buf[0], buf[1], buf[2]);
357 		return SANE_STATUS_IO_ERROR;
358 	}
359 
360 	DBG(32, "scanner locked\n");
361 
362 	return status;
363 }
364 
365 static SANE_Status
sanei_magicolor_net_close(struct Magicolor_Scanner *s)366 sanei_magicolor_net_close(struct Magicolor_Scanner *s)
367 {
368 	SANE_Status status;
369 	struct MagicolorCmd *cmd = s->hw->cmd;
370 	unsigned char buf[3];
371 
372 	DBG(1, "%s\n", __func__);
373 	buf[0] = cmd->net_wrapper_cmd;
374 	buf[1] = cmd->net_unlock;
375 	buf[2] = 0x00;
376 	sanei_magicolor_net_write_raw(s, buf, 3, &status);
377 	return status;
378 }
379 
380 
381 
382 /****************************************************************************
383  *   Low-level USB communication functions
384  ****************************************************************************/
385 
386 #define SANE_MAGICOLOR_VENDOR_ID	(0x132b)
387 
388 SANE_Word sanei_magicolor_usb_product_ids[] = {
389   0x2089, /* magicolor 1690MF */
390   0x2079, /* magicolor 4690MF */
391   0				/* last entry - this is used for devices that are specified
392 				   in the config file as "usb <vendor> <product>" */
393 };
394 
395 static int
sanei_magicolor_getNumberOfUSBProductIds(void)396 sanei_magicolor_getNumberOfUSBProductIds (void)
397 {
398   return sizeof (sanei_magicolor_usb_product_ids) / sizeof (SANE_Word);
399 }
400 
401 
402 
403 
404 /****************************************************************************
405  *   Magicolor low-level communication commands
406  ****************************************************************************/
407 
dump_hex_buffer_dense(int level, const unsigned char *buf, size_t buf_size)408 static void dump_hex_buffer_dense (int level, const unsigned char *buf, size_t buf_size)
409 {
410 	size_t k;
411 	char msg[1024], fmt_buf[1024];
412 	memset (&msg[0], 0x00, 1024);
413 	memset (&fmt_buf[0], 0x00, 1024);
414 	for (k = 0; k < min(buf_size, 80); k++) {
415 		if (k % 16 == 0) {
416 			if (k>0) {
417 				DBG (level, "%s\n", msg);
418 				memset (&msg[0], 0x00, 1024);
419 			}
420 			sprintf (fmt_buf, "     0x%04lx  ", (unsigned long)k);
421 			strcat (msg, fmt_buf);
422 		}
423 		if (k % 8 == 0) {
424 			strcat (msg, " ");
425 		}
426 		sprintf (fmt_buf, " %02x" , buf[k]);
427 		strcat (msg, fmt_buf);
428 	}
429 	if (msg[0] != 0 ) {
430 		DBG (level, "%s\n", msg);
431 	}
432 }
433 
434 /* Create buffers containing the command and arguments. Length of reserved
435  * buffer is returned. It's the caller's job to free the buffer! */
mc_create_buffer(Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd, unsigned char **buf, unsigned char* arg1, size_t len1, SANE_Status *status)436 static int mc_create_buffer (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd,
437 		      unsigned char **buf, unsigned char* arg1, size_t len1,
438 		      SANE_Status *status)
439 {
440 	unsigned char* b = NULL;
441 	size_t buf_len = 2+4+len1+4;
442 	NOT_USED (s);
443 	if (len1 <= 0)
444 		buf_len = 6; /* no args, just cmd + final 0x00 00 00 00 */
445 	*buf = b = malloc (buf_len);
446 	memset (b, 0x00, buf_len);
447 	if (!b) {
448 		*status = SANE_STATUS_NO_MEM;
449 		return 0;
450 	}
451 	b[0] = cmd_type;
452 	b[1] = cmd;
453 	if (len1>0) {
454 		b[2] = len1 & 0xff;
455 		b[3] = (len1 >> 8) & 0xff;
456 		b[4] = (len1 >> 16) & 0xff;
457 		b[5] = (len1 >> 24) & 0xff;
458 		if (arg1)
459 			memcpy(b+6, arg1, len1);
460 	}
461 	/* Writing the final 0x00 00 00 00 is not necessary, they are 0x00 already */
462 	*status = SANE_STATUS_GOOD;
463 	return buf_len;
464 }
465 
mc_create_buffer2(Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd, unsigned char **buf, unsigned char* arg1, size_t len1, unsigned char* arg2, size_t len2, SANE_Status *status)466 static int mc_create_buffer2 (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd,
467 		       unsigned char **buf, unsigned char* arg1, size_t len1,
468 		       unsigned char* arg2, size_t len2, SANE_Status *status)
469 {
470 	unsigned char* b = NULL;
471 	size_t buf_len = 2+4+len1+4+len2+4;
472 	/* If any of the two args has size 0, use the simpler mc_create_buffer */
473 	if (len1<=0)
474 		return mc_create_buffer (s, cmd_type, cmd, buf, arg2, len2, status);
475 	else if (len2<=0)
476 		return mc_create_buffer (s, cmd_type, cmd, buf, arg1, len1, status);
477 	/* Allocate memory and copy over args and their lengths */
478 	*buf = b = malloc (buf_len);
479 	if (!b) {
480 		*status = SANE_STATUS_NO_MEM;
481 		return 0;
482 	}
483 	memset (b, 0x00, buf_len);
484 	b[0] = cmd_type;
485 	b[1] = cmd;
486 	/* copy over the argument length in lower endian */
487 	b[2] = len1 & 0xff;
488 	b[3] = (len1 >> 8) & 0xff;
489 	b[4] = (len1 >> 16) & 0xff;
490 	b[5] = (len1 >> 24) & 0xff;
491 	if (arg1) {
492 		/* Copy the arguments */
493 		memcpy(b+6, arg1, len1);
494 	}
495 	/* copy over the second argument length in little endian */
496 	b[6+len1] = len2 & 0xff;
497 	b[7+len1] = (len2 >> 8) & 0xff;
498 	b[8+len1] = (len2 >> 16) & 0xff;
499 	b[9+len1] = (len2 >> 24) & 0xff;
500 	if (arg2) {
501 		memcpy(b+10+len1, arg2, len2);
502 	}
503 	*status = SANE_STATUS_GOOD;
504 	return buf_len;
505 }
506 
507 static int
mc_send(Magicolor_Scanner * s, void *buf, size_t buf_size, SANE_Status * status)508 mc_send(Magicolor_Scanner * s, void *buf, size_t buf_size, SANE_Status * status)
509 {
510 	DBG(15, "%s: size = %lu\n", __func__, (u_long) buf_size);
511 
512 	if (DBG_LEVEL >= 125) {
513 		const unsigned char *s = buf;
514 		DBG(125, "Cmd: 0x%02x %02x, complete buffer:\n", s[0], s[1]);
515 		dump_hex_buffer_dense (125, s, buf_size);
516 	}
517 
518 	if (s->hw->connection == SANE_MAGICOLOR_NET) {
519 		return sanei_magicolor_net_write(s, buf, buf_size, status);
520 	} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
521 		size_t n;
522 		n = buf_size;
523 		*status = sanei_usb_write_bulk(s->fd, buf, &n);
524 		DBG(125, "USB: wrote %lu bytes, status: %s\n", (unsigned long)n, sane_strstatus(*status));
525 		return n;
526 	}
527 
528 	*status = SANE_STATUS_INVAL;
529 	return 0;
530 	/* never reached */
531 }
532 
533 static ssize_t
mc_recv(Magicolor_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status)534 mc_recv(Magicolor_Scanner * s, void *buf, ssize_t buf_size,
535 	    SANE_Status * status)
536 {
537 	ssize_t n = 0;
538 
539 	DBG(15, "%s: size = %ld, buf = %p\n", __func__, (long) buf_size, buf);
540 
541 	if (s->hw->connection == SANE_MAGICOLOR_NET) {
542 		n = sanei_magicolor_net_read(s, buf, buf_size, status);
543 	} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
544 		/* !!! only report an error if we don't read anything */
545 		n = buf_size;	/* buf_size gets overwritten */
546 		*status =
547 			sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf,
548 					    (size_t *) & n);
549 
550 		if (n > 0)
551 			*status = SANE_STATUS_GOOD;
552 	}
553 
554 	if (n < buf_size) {
555 		DBG(1, "%s: expected = %lu, got = %ld\n", __func__,
556 		    (u_long) buf_size, (long) n);
557 		*status = SANE_STATUS_IO_ERROR;
558 	}
559 
560 	/* dump buffer if appropriate */
561 	if (DBG_LEVEL >= 127 && n > 0) {
562 		const unsigned char* b=buf;
563 		dump_hex_buffer_dense (125, b, buf_size);
564 	}
565 
566 	return n;
567 }
568 
569 /* Simple function to exchange a fixed amount of
570  * data with the scanner
571  */
572 static SANE_Status
mc_txrx(Magicolor_Scanner * s, unsigned char *txbuf, size_t txlen, unsigned char *rxbuf, size_t rxlen)573 mc_txrx(Magicolor_Scanner * s, unsigned char *txbuf, size_t txlen,
574 	    unsigned char *rxbuf, size_t rxlen)
575 {
576 	SANE_Status status;
577 
578 	mc_send(s, txbuf, txlen, &status);
579 	if (status != SANE_STATUS_GOOD) {
580 		DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
581 		return status;
582 	}
583 
584 	mc_recv(s, rxbuf, rxlen, &status);
585 	if (status != SANE_STATUS_GOOD) {
586 		DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
587 	}
588 
589 	return status;
590 }
591 
592 
593 
594 
595 
596 /****************************************************************************
597  *   Magicolor high-level communication commands
598  ****************************************************************************/
599 
600 
601 /** 0x03 09 01 - Request last error
602  * <- Information block (0x00 for OK, 0x01 for ERROR)
603  */
604 static SANE_Status
cmd_request_error(SANE_Handle handle)605 cmd_request_error (SANE_Handle handle)
606 {
607 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
608 	SANE_Status status;
609 	unsigned char params[1];
610 	unsigned char *buf;
611 	size_t buflen;
612 
613 	DBG(8, "%s\n", __func__);
614 
615 	if (s->hw->cmd->request_status == 0)
616 		return SANE_STATUS_UNSUPPORTED;
617 
618 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_error,
619 				   &buf, NULL, 1, &status);
620 	if (buflen <= 0 ) {
621 		return SANE_STATUS_NO_MEM;
622 	} else if (status != SANE_STATUS_GOOD) {
623 		return status;
624 	}
625 
626 	status = mc_txrx (s, buf, buflen, params, 1);
627 	free(buf);
628 	if (status != SANE_STATUS_GOOD)
629 		return status;
630 
631 	DBG(1, "status: %02x\n", params[0]);
632 
633 	switch (params[0]) {
634 		case STATUS_READY:
635 			DBG(1, " ready\n");
636 			break;
637 		case STATUS_ADF_JAM:
638 			DBG(1, " paper jam in ADF\n");
639 			return SANE_STATUS_JAMMED;
640 			break;
641 		case STATUS_OPEN:
642 			DBG(1, " printer door open or waiting for button press\n");
643 			return SANE_STATUS_COVER_OPEN;
644 			break;
645 		case STATUS_NOT_READY:
646 			DBG(1, " scanner not ready (in use on another interface or warming up)\n");
647 			return SANE_STATUS_DEVICE_BUSY;
648 			break;
649 		default:
650 			DBG(1, " unknown status 0x%x\n", params[0]);
651 	}
652 	return status;
653 }
654 
655 /** 0x03 0d  - Request status command */
656 static SANE_Status
cmd_request_status(SANE_Handle handle, unsigned char *b)657 cmd_request_status(SANE_Handle handle, unsigned char *b)
658 {
659 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
660 	SANE_Status status;
661 	unsigned char *buf;
662 	size_t buflen;
663 
664 	DBG(8, "%s\n", __func__);
665 	if (!b) {
666 		DBG(1, "%s called with NULL buffer\n", __func__);
667 		return SANE_STATUS_INVAL;
668 	}
669 	memset (b, 0x00, 0x0b); /* initialize all 0x0b bytes with 0 */
670 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_status,
671 				   &buf, NULL, 0x0b, &status);
672 	if (buflen <= 0 ) {
673 		return SANE_STATUS_NO_MEM;
674 	} else if (status != SANE_STATUS_GOOD) {
675 		return status;
676 	}
677 
678 	status = mc_txrx (s, buf, buflen, b, 0x0b);
679 	free (buf);
680 	if (status != SANE_STATUS_GOOD)
681 		DBG(8, "%s: Status NOT successfully retrieved\n", __func__);
682 	else {
683 		DBG(8, "%s: Status successfully retrieved:\n", __func__);
684 		/* TODO: debug output of the returned parameters... */
685 		DBG (11, "  ADF status: 0x%02x", b[1]);
686 		if (b[1] & ADF_LOADED) {
687 			DBG (11, " loaded\n");
688 		} else {
689 			DBG (11, " not loaded\n");
690 		}
691 	}
692 	return status;
693 }
694 
695 
696 /** 0x03 08  - Start scan command */
697 static SANE_Status
cmd_start_scan(SANE_Handle handle, size_t value)698 cmd_start_scan (SANE_Handle handle, size_t value)
699 {
700 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
701 	SANE_Status status;
702 	unsigned char params1[4], params2[1];
703 	unsigned char *buf;
704 	size_t buflen;
705 
706 	DBG(8, "%s\n", __func__);
707 	/* Copy params to buffers */
708 	/* arg1 is expected returned bytes per line, 4-byte little endian */
709 	/* arg2 is unknown, seems to be always 0x00 */
710 	params1[0] = value & 0xff;
711 	params1[1] = (value >> 8) & 0xff;
712 	params1[2] = (value >> 16) & 0xff;
713 	params1[3] = (value >> 24) & 0xff;
714 
715 	params2[0] = 0x00;
716 	buflen = mc_create_buffer2 (s, s->hw->cmd->scanner_cmd, s->hw->cmd->start_scanning,
717 				    &buf, params1, 4, params2, 1, &status);
718 	if (buflen <= 0 ) {
719 		return SANE_STATUS_NO_MEM;
720 	} else if (status != SANE_STATUS_GOOD) {
721 		return status;
722 	}
723 
724 	mc_send(s, buf, buflen, &status);
725 	free (buf);
726 	if (status != SANE_STATUS_GOOD)
727 		DBG(8, "%s: Data NOT successfully sent\n", __func__);
728 	else
729 		DBG(8, "%s: Data successfully sent\n", __func__);
730 	return status;
731 }
732 
733 /** 0x03 0a  - Cancel(?) Scan command */
734 /* TODO: Does this command really mean CANCEL??? */
735 static SANE_Status
cmd_cancel_scan(SANE_Handle handle)736 cmd_cancel_scan (SANE_Handle handle)
737 {
738 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
739 	SANE_Status status;
740 	unsigned char *buf;
741 	size_t buflen;
742 
743 	DBG(8, "%s\n", __func__);
744 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->stop_scanning,
745 				    &buf, NULL, 0, &status);
746 	if (buflen <= 0 ) {
747 		return SANE_STATUS_NO_MEM;
748 	} else if (status != SANE_STATUS_GOOD) {
749 		return status;
750 	}
751 
752 	mc_send(s, buf, buflen, &status);
753 	free (buf);
754 	if (status != SANE_STATUS_GOOD)
755 		DBG(8, "%s: Data NOT successfully sent\n", __func__);
756 	else
757 		DBG(8, "%s: Data successfully sent\n", __func__);
758 	return status;
759 }
760 
761 /** 0x03 12  - Finish(?) scan command */
762 /* TODO: Does this command really mean FINISH??? */
763 static SANE_Status
cmd_finish_scan(SANE_Handle handle)764 cmd_finish_scan (SANE_Handle handle)
765 {
766 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
767 	SANE_Status status;
768 	unsigned char *buf, returned[0x0b];
769 	size_t buflen;
770 
771 	DBG(8, "%s\n", __func__);
772 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown2,
773 				    &buf, NULL, 0x0b, &status);
774 	if (buflen <= 0 ) {
775 		return SANE_STATUS_NO_MEM;
776 	} else if (status != SANE_STATUS_GOOD) {
777 		return status;
778 	}
779 	memset (&returned[0], 0x00, 0x0b);
780 
781 	status = mc_txrx (s, buf, buflen, returned, 0x0b);
782 	free (buf);
783 	if (status != SANE_STATUS_GOOD)
784 		DBG(8, "%s: Data NOT successfully sent\n", __func__);
785 	else
786 		DBG(8, "%s: Data successfully sent\n", __func__);
787 	return status;
788 }
789 
790 /** 0x03 0b  - Get scanning parameters command
791  *    input buffer seems to be 0x00 always */
792 static SANE_Status
cmd_get_scanning_parameters(SANE_Handle handle, SANE_Frame *format, SANE_Int *depth, SANE_Int *data_pixels, SANE_Int *pixels_per_line, SANE_Int *lines)793 cmd_get_scanning_parameters(SANE_Handle handle,
794 			    SANE_Frame *format, SANE_Int *depth,
795 			    SANE_Int *data_pixels, SANE_Int *pixels_per_line,
796 			    SANE_Int *lines)
797 {
798 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
799 	SANE_Status status;
800 	unsigned char *txbuf, rxbuf[8];
801 	size_t buflen;
802 	NOT_USED (format);
803 	NOT_USED (depth);
804 
805 	DBG(8, "%s\n", __func__);
806 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd,
807 				   s->hw->cmd->request_scan_parameters,
808 				   &txbuf, NULL, 8, &status);
809 	if (buflen <= 0 ) {
810 		return SANE_STATUS_NO_MEM;
811 	} else if (status != SANE_STATUS_GOOD) {
812 		return status;
813 	}
814 
815 	status = mc_txrx (s, txbuf, buflen, rxbuf, 8);
816 	free (txbuf);
817 	if (status != SANE_STATUS_GOOD)
818 		DBG(8, "%s: Parameters NOT successfully retrieved\n", __func__);
819 	else {
820 		DBG(8, "%s: Parameters successfully retrieved\n", __func__);
821 
822 		/* Assign px_per_line and lines. Bytes 7-8 must match 3-4 */
823 		if (rxbuf[2]!=rxbuf[6] || rxbuf[3]!=rxbuf[7]) {
824 			DBG (1, "%s: ERROR: Returned image parameters indicate an "
825 				"unsupported device: Bytes 3-4 do not match "
826 				"bytes 7-8! Trying to continue with bytes 3-4.\n",
827 				__func__);
828 			dump_hex_buffer_dense (1, rxbuf, 8);
829 		}
830 		/* Read returned values, encoded in 2-byte little endian */
831 		*data_pixels = rxbuf[1] * 0x100 + rxbuf[0];
832 		*lines = rxbuf[3] * 0x100 + rxbuf[2];
833 		*pixels_per_line = rxbuf[5] * 0x100 + rxbuf[4];
834 		DBG (8, "%s: data_pixels = 0x%x (%u), lines = 0x%x (%u), "
835 		        "pixels_per_line = 0x%x (%u)\n", __func__,
836 		        *data_pixels, *data_pixels,
837 		        *lines, *lines,
838 		        *pixels_per_line, *pixels_per_line);
839 
840 		/*
841 		 * SECURITY REMEDIATION
842 		 * See gitlab issue #279 - Issue10 SIGFPE in mc_setup_block_mode
843 		 *
844 		 * pixels_per_line cannot be zero, otherwise a division by zero error can occur later.
845 		 * Added checking the parameters to ensure that this issue cannot occur.
846 		 *
847 		 * Additionally to the reported issue, it makes no sense for any of the values of
848 		 * data_pixels, lines or pixels_per_line to be zero. I do not have any knowledge
849 		 * of valid maximums for these parameters.
850 		 *
851 		 */
852 		if ((*data_pixels == 0) || (*lines == 0) || (*pixels_per_line == 0)) {
853 			DBG (1, "%s: ERROR: Returned image parameters contain invalid "
854 				"bytes. Zero values for these parameters are not rational.\n",
855 				__func__);
856 			dump_hex_buffer_dense (1, rxbuf, 8);
857 			return SANE_STATUS_INVAL;
858 		}
859 	}
860 
861 	return status;
862 }
863 
864 /** 0x03 0c  - Set scanning parameters command */
865 static SANE_Status
cmd_set_scanning_parameters(SANE_Handle handle, unsigned char resolution, unsigned char color_mode, unsigned char brightness, unsigned char contrast, int tl_x, int tl_y, int width, int height, unsigned char source)866 cmd_set_scanning_parameters(SANE_Handle handle,
867 	unsigned char resolution, unsigned char color_mode,
868 	unsigned char brightness, unsigned char contrast,
869 	int tl_x, int tl_y, int width, int height, unsigned char source)
870 {
871 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
872 	SANE_Status status;
873 	unsigned char param[0x11];
874 	unsigned char *buf;
875 	size_t buflen;
876 
877 	DBG(8, "%s\n", __func__);
878 	/* Copy over the params to the param byte array */
879 	/* Byte structure:
880 	 *   byte 0:     resolution
881 	 *   byte 1:     color mode
882 	 *   byte 2:     brightness
883 	 *   byte 3:     0xff
884 	 *   byte 4-5:   x-start
885 	 *   byte 6-7:   y-start
886 	 *   byte 8-9:  x-extent
887 	 *   byte 10-11: y-extent
888 	 *   byte 12:    source (ADF/FBF)
889 	 **/
890 	memset (&param[0], 0x00, 0x11);
891 	param[0] = resolution;
892 	param[1] = color_mode;
893 	param[2] = brightness;
894 	param[3] = contrast | 0xff; /* TODO: Always 0xff? What about contrast? */
895 	/* Image coordinates are encoded 2-byte little endian: */
896 	param[4] = tl_x & 0xff;
897 	param[5] = (tl_x >> 8) & 0xff;
898 	param[6] = tl_y & 0xff;
899 	param[7] = (tl_y >> 8) & 0xff;
900 	param[8] = width & 0xff;
901 	param[9] = (width >> 8) & 0xff;
902 	param[10] = height & 0xff;
903 	param[11] = (height >> 8) & 0xff;
904 
905 	param[12] = source;
906 
907 	/* dump buffer if appropriate */
908 	DBG (127, "  Scanning parameter buffer:");
909 	dump_hex_buffer_dense (127, param, 0x11);
910 
911 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->set_scan_parameters,
912 				   &buf, param, 0x11, &status);
913 	if (buflen <= 0 ) {
914 		return SANE_STATUS_NO_MEM;
915 	} else if (status != SANE_STATUS_GOOD) {
916 		return status;
917 	}
918 
919 	mc_send(s, buf, buflen, &status);
920 	free (buf);
921 	if (status != SANE_STATUS_GOOD)
922 		DBG(8, "%s: Data NOT successfully sent\n", __func__);
923 	else
924 		DBG(8, "%s: Data successfully sent\n", __func__);
925 	return status;
926 }
927 
928 /** 0x03 ??  - Request push button status command */
929 #if 0
930 static SANE_Status
931 cmd_request_push_button_status(SANE_Handle handle, unsigned char *bstatus)
932 {
933 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
934 	SANE_Status status;
935 	unsigned char *buf;
936 	size_t buflen;
937 
938 	DBG(8, "%s\n", __func__);
939 
940 
941 	if (s->hw->cmd->unknown1 == 0)
942 		return SANE_STATUS_UNSUPPORTED;
943 
944 	DBG(8, "%s: Supported\n", __func__);
945 	memset (bstatus, 0x00, 1);
946 	buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown1,
947 				   &buf, bstatus, 1, &status);
948 	if (buflen <= 0 ) {
949 		return SANE_STATUS_NO_MEM;
950 	} else if (status != SANE_STATUS_GOOD) {
951 		return status;
952 	}
953 
954 	status = mc_txrx (s, buf, buflen, bstatus, 1);
955 	free(buf);
956 	if (status != SANE_STATUS_GOOD)
957 		return status;
958 
959 	DBG(1, "push button status: %02x ", bstatus[0]);
960 	switch (bstatus[0]) {
961 		/* TODO: What's the response code for button pressed??? */
962 		default:
963 			DBG(1, " unknown\n");
964 			status = SANE_STATUS_UNSUPPORTED;
965 	}
966 	return status;
967 }
968 #endif
969 
970 /** 0x03 0e  - Read data command */
971 static SANE_Status
cmd_read_data(SANE_Handle handle, unsigned char *buf, size_t len)972 cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t len)
973 {
974 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
975 	SANE_Status status;
976 	unsigned char *txbuf;
977 	unsigned char param[4];
978 	size_t txbuflen;
979 	int oldtimeout = MC_Request_Timeout;
980 
981 	DBG(8, "%s\n", __func__);
982 	param[0] = len & 0xff;
983 	param[1] = (len >> 8) & 0xff;
984 	param[2] = (len >> 16) & 0xff;
985 	param[3] = (len >> 24) & 0xff;
986 
987 	txbuflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_data,
988 				   &txbuf, param, 4, &status);
989 	if (txbuflen <= 0 ) {
990 		return SANE_STATUS_NO_MEM;
991 	} else if (status != SANE_STATUS_GOOD) {
992 		return status;
993 	}
994 
995 	/* Temporarily set the poll timeout to 10 seconds instead of 2,
996 	 * because a color scan needs >5 seconds to initialize. */
997 	MC_Request_Timeout = MC_Scan_Data_Timeout;
998 	status = mc_txrx (s, txbuf, txbuflen, buf, len);
999 	MC_Request_Timeout = oldtimeout;
1000 	free (txbuf);
1001 	if (status != SANE_STATUS_GOOD)
1002 		DBG(8, "%s: Image data NOT successfully retrieved\n", __func__);
1003 	else {
1004 		DBG(8, "%s: Image data successfully retrieved\n", __func__);
1005 	}
1006 
1007 	return status;
1008 }
1009 
1010 
1011 
1012 /* TODO: 0x03 0f command (unknown), 0x03 10 command (set button wait) */
1013 
1014 
1015 
1016 
1017 /****************************************************************************
1018  *   Magicolor backend high-level operations
1019  ****************************************************************************/
1020 
1021 
1022 static void
mc_dev_init(Magicolor_Device *dev, const char *devname, int conntype)1023 mc_dev_init(Magicolor_Device *dev, const char *devname, int conntype)
1024 {
1025 	DBG(5, "%s\n", __func__);
1026 
1027 	dev->name = NULL;
1028 	dev->model = NULL;
1029 	dev->connection = conntype;
1030 	dev->sane.name = devname;
1031 	dev->sane.model = NULL;
1032 	dev->sane.type = "flatbed scanner";
1033 	dev->sane.vendor = "Magicolor";
1034 	dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT];
1035 	dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT];
1036 	/* Change default level when using a network connection */
1037 	if (dev->connection == SANE_MAGICOLOR_NET)
1038 		dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_NET];
1039 }
1040 
1041 static SANE_Status
mc_dev_post_init(struct Magicolor_Device *dev)1042 mc_dev_post_init(struct Magicolor_Device *dev)
1043 {
1044 	DBG(5, "%s\n", __func__);
1045 	NOT_USED (dev);
1046 	/* Correct device parameters if needed */
1047 	return SANE_STATUS_GOOD;
1048 }
1049 
1050 static SANE_Status
mc_set_model(Magicolor_Scanner * s, const char *model, size_t len)1051 mc_set_model(Magicolor_Scanner * s, const char *model, size_t len)
1052 {
1053 	unsigned char *buf;
1054 	unsigned char *p;
1055 	struct Magicolor_Device *dev = s->hw;
1056 
1057 	buf = malloc(len + 1);
1058 	if (buf == NULL)
1059 		return SANE_STATUS_NO_MEM;
1060 
1061 	memcpy(buf, model, len);
1062 	buf[len] = '\0';
1063 
1064 	p = &buf[len - 1];
1065 
1066 	while (*p == ' ') {
1067 		*p = '\0';
1068 		p--;
1069 	}
1070 
1071 	if (dev->model)
1072 		free(dev->model);
1073 
1074 	dev->model = strndup((const char *) buf, len);
1075 	dev->sane.model = dev->model;
1076 	DBG(10, "%s: model is '%s'\n", __func__, dev->model);
1077 
1078 	free(buf);
1079 
1080 	return SANE_STATUS_GOOD;
1081 }
1082 
1083 static void
mc_set_device(SANE_Handle handle, unsigned int device)1084 mc_set_device (SANE_Handle handle, unsigned int device)
1085 {
1086 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
1087 	Magicolor_Device *dev = s->hw;
1088 	const char* cmd_level;
1089 	int n;
1090 
1091 	DBG(1, "%s: 0x%x\n", __func__, device);
1092 
1093 	for (n = 0; n < NELEMS (magicolor_cap); n++) {
1094 		if (magicolor_cap[n].id == device)
1095 			break;
1096 	}
1097 	if (n < NELEMS(magicolor_cap)) {
1098 		dev->cap = &magicolor_cap[n];
1099 	} else {
1100 		dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT];
1101 		DBG(1, " unknown device 0x%x, using default %s\n",
1102 		    device, dev->cap->model);
1103 	}
1104 	mc_set_model (s, dev->cap->model, strlen (dev->cap->model));
1105 
1106 	cmd_level = dev->cap->cmds;
1107 	/* set command type and level */
1108 	for (n = 0; n < NELEMS(magicolor_cmd); n++) {
1109 		if (!strcmp(cmd_level, magicolor_cmd[n].level))
1110 			break;
1111 	}
1112 
1113 	if (n < NELEMS(magicolor_cmd)) {
1114 		dev->cmd = &magicolor_cmd[n];
1115 	} else {
1116 		dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT];
1117 		DBG(1, " unknown command level %s, using %s\n",
1118 		    cmd_level, dev->cmd->level);
1119 	}
1120 }
1121 
1122 static SANE_Status
mc_discover_capabilities(Magicolor_Scanner *s)1123 mc_discover_capabilities(Magicolor_Scanner *s)
1124 {
1125 	SANE_Status status;
1126 	Magicolor_Device *dev = s->hw;
1127 
1128 	SANE_String_Const *source_list_add = source_list;
1129 
1130 	DBG(5, "%s\n", __func__);
1131 
1132 	/* always add flatbed */
1133 	*source_list_add++ = FBF_STR;
1134 	/* TODO: How can I check for existence of an ADF??? */
1135 	if (dev->cap->ADF)
1136 		*source_list_add++ = ADF_STR;
1137 
1138 	/* TODO: Is there any capability that we can extract from the
1139 	 *       device by some scanne command? So far, it looks like
1140 	 *       the device does not support any reporting. I don't even
1141 	 *       see a way to determine which device we are talking to!
1142 	 */
1143 
1144 
1145 	/* request error status */
1146 	status = cmd_request_error(s);
1147 	if (status != SANE_STATUS_GOOD)
1148 		return status;
1149 
1150 	dev->x_range = &dev->cap->fbf_x_range;
1151 	dev->y_range = &dev->cap->fbf_y_range;
1152 
1153 	DBG(5, "   x-range: %f %f\n", SANE_UNFIX(dev->x_range->min), SANE_UNFIX(dev->x_range->max));
1154 	DBG(5, "   y-range: %f %f\n", SANE_UNFIX(dev->y_range->min), SANE_UNFIX(dev->y_range->max));
1155 
1156 	DBG(5, "End of %s, status:%s\n", __func__, sane_strstatus(status));
1157 	*source_list_add = NULL; /* add end marker to source list */
1158 	return status;
1159 }
1160 
1161 static SANE_Status
mc_setup_block_mode(Magicolor_Scanner *s)1162 mc_setup_block_mode (Magicolor_Scanner *s)
1163 {
1164 	/* block_len should always be a multiple of bytes_per_line, so
1165 	 * we retrieve only whole lines at once */
1166 	s->block_len = (int)(0xff00/s->scan_bytes_per_line) * s->scan_bytes_per_line;
1167 	s->blocks = s->data_len / s->block_len;
1168 	s->last_len = s->data_len - (s->blocks * s->block_len);
1169 	if (s->last_len>0)
1170 		s->blocks++;
1171 	DBG(5, "%s: block_len=0x%x, last_len=0x%0x, blocks=%d\n", __func__, s->block_len, s->last_len, s->blocks);
1172 	s->counter = 0;
1173 	s->bytes_read_in_line = 0;
1174 	if (s->line_buffer)
1175 		free(s->line_buffer);
1176 	s->line_buffer = malloc(s->scan_bytes_per_line);
1177 	if (s->line_buffer == NULL) {
1178 		DBG(1, "out of memory (line %d)\n", __LINE__);
1179 		return SANE_STATUS_NO_MEM;
1180 	}
1181 
1182 
1183 	DBG (5, " %s: Setup block mode - scan_bytes_per_line=%d, pixels_per_line=%d, depth=%d, data_len=%x, block_len=%x, blocks=%d, last_len=%x\n",
1184 		__func__, s->scan_bytes_per_line, s->params.pixels_per_line, s->params.depth, s->data_len, s->block_len, s->blocks, s->last_len);
1185 	return SANE_STATUS_GOOD;
1186 }
1187 
1188 /* Call the 0x03 0c command to set scanning parameters from the s->opt list */
1189 static SANE_Status
mc_set_scanning_parameters(Magicolor_Scanner * s)1190 mc_set_scanning_parameters(Magicolor_Scanner * s)
1191 {
1192 	SANE_Status status;
1193 	unsigned char rs, source, brightness;
1194 	struct mode_param *mparam = &mode_params[s->val[OPT_MODE].w];
1195 	SANE_Int scan_pixels_per_line = 0;
1196 
1197 	DBG(1, "%s\n", __func__);
1198 
1199 	/* Find the resolution in the res list and assign the index to buf[1] */
1200 	for (rs=0; rs < s->hw->cap->res_list_size; rs++ ) {
1201 		if ( s->val[OPT_RESOLUTION].w == s->hw->cap->res_list[rs] )
1202 			break;
1203 	}
1204 
1205 	if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BRIGHTNESS].cap)) {
1206 		brightness = s->val[OPT_BRIGHTNESS].w;
1207 	} else {
1208 		brightness = 5;
1209 	}
1210 
1211 	/* ADF used? */
1212 	if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
1213 		/* Use ADF */
1214 		if (s->val[OPT_ADF_MODE].w == 0) {
1215 			source = 0x01;
1216 		} else {
1217 			/* Use duplex */
1218 			source = 0x02;
1219 		}
1220 	} else {
1221 		source = 0x00;
1222 	}
1223 
1224 	/* TODO: Any way to set PREVIEW??? */
1225 
1226 	/* Remaining bytes unused */
1227 	status = cmd_set_scanning_parameters(s,
1228 					     rs, mparam->flags,  /* res, color mode */
1229 					     brightness, 0xff, /* brightness, contrast? */
1230 					     s->left, s->top,  /* top/left start */
1231 					     s->width, s->height, /* extent */
1232 					     source); /* source */
1233 
1234 	if (status != SANE_STATUS_GOOD)
1235 		DBG (2, "%s: Command cmd_set_scanning_parameters failed, %s\n",
1236 		     __func__, sane_strstatus(status));
1237 
1238 	/* Now query the scanner for the current image parameters */
1239 	status = cmd_get_scanning_parameters (s,
1240 			&s->params.format, &s->params.depth,
1241 			&scan_pixels_per_line,
1242 			&s->params.pixels_per_line, &s->params.lines);
1243 	if (status != SANE_STATUS_GOOD) {
1244 		DBG (2, "%s: Command cmd_get_scanning_parameters failed, %s\n",
1245 		     __func__, sane_strstatus(status));
1246 		return status;
1247 	}
1248 
1249 	/* Calculate how many bytes are really used per line */
1250 	s->params.bytes_per_line = ceil (s->params.pixels_per_line * s->params.depth / 8.0);
1251 	if (s->val[OPT_MODE].w == MODE_COLOR)
1252 		s->params.bytes_per_line *= 3;
1253 
1254 	/* Calculate how many bytes per line will be returned by the scanner.
1255 	 * The values needed for this are returned by get_scannign_parameters */
1256 	s->scan_bytes_per_line = ceil (scan_pixels_per_line * s->params.depth / 8.0);
1257 	if (s->val[OPT_MODE].w == MODE_COLOR) {
1258 		s->scan_bytes_per_line *= 3;
1259 	}
1260 	s->data_len = s->params.lines * s->scan_bytes_per_line;
1261 
1262 	status = mc_setup_block_mode (s);
1263 	if (status != SANE_STATUS_GOOD)
1264 		DBG (2, "%s: Command mc_setup_block_mode failed, %s\n",
1265 		     __func__, sane_strstatus(status));
1266 
1267 	DBG (1, "%s: bytes_read  in line: %d\n", __func__, s->bytes_read_in_line);
1268 
1269 	return status;
1270 }
1271 
1272 static SANE_Status
mc_check_adf(Magicolor_Scanner * s)1273 mc_check_adf(Magicolor_Scanner * s)
1274 {
1275 	SANE_Status status;
1276 	unsigned char buf[0x0b];
1277 
1278 	DBG(5, "%s\n", __func__);
1279 
1280 	status = cmd_request_status(s, buf);
1281 	if (status != SANE_STATUS_GOOD)
1282 		return status;
1283 
1284 	if (!(buf[1] & ADF_LOADED))
1285 		return SANE_STATUS_NO_DOCS;
1286 
1287 	/* TODO: Check for jam in ADF */
1288 	return SANE_STATUS_GOOD;
1289 }
1290 
1291 static SANE_Status
mc_scan_finish(Magicolor_Scanner * s)1292 mc_scan_finish(Magicolor_Scanner * s)
1293 {
1294 	SANE_Status status;
1295 	DBG(5, "%s\n", __func__);
1296 
1297 	/* If we have not yet read all data, cancel the scan */
1298 	if (s->buf && !s->eof)
1299 		status = cmd_cancel_scan (s);
1300 
1301 	if (s->line_buffer)
1302 		free (s->line_buffer);
1303 	s->line_buffer = NULL;
1304 	free(s->buf);
1305 	s->buf = s->end = s->ptr = NULL;
1306 
1307 	/* TODO: Any magicolor command for "scan finished"? */
1308 	status = cmd_finish_scan (s);
1309 
1310 	status = cmd_request_error(s);
1311 	if (status != SANE_STATUS_GOOD) {
1312 		cmd_cancel_scan (s);
1313 		return status;
1314         }
1315 
1316 	/* XXX required? */
1317 	/* TODO:	cmd_reset(s);*/
1318 	return SANE_STATUS_GOOD;
1319 }
1320 
1321 static void
mc_copy_image_data(Magicolor_Scanner * s, SANE_Byte * data, SANE_Int max_length, SANE_Int * length)1322 mc_copy_image_data(Magicolor_Scanner * s, SANE_Byte * data, SANE_Int max_length,
1323 		   SANE_Int * length)
1324 {
1325 	DBG (1, "%s: bytes_read  in line: %d\n", __func__, s->bytes_read_in_line);
1326 	if (s->params.format == SANE_FRAME_RGB) {
1327 		SANE_Int bytes_available, scan_pixels_per_line = s->scan_bytes_per_line/3;
1328 		*length = 0;
1329 
1330 		while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) {
1331 			SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line;
1332 			/* First, fill the line buffer for the current line: */
1333 			bytes_available = (s->end - s->ptr);
1334 			/* Don't copy more than we have buffer and available */
1335 			if (bytes_to_copy > bytes_available)
1336 				bytes_to_copy = bytes_available;
1337 
1338 			if (bytes_to_copy > 0) {
1339 				memcpy (s->line_buffer + s->bytes_read_in_line, s->ptr, bytes_to_copy);
1340 				s->ptr += bytes_to_copy;
1341 				s->bytes_read_in_line += bytes_to_copy;
1342 			}
1343 
1344 			/* We have filled as much as possible of the current line
1345 			 * with data from the scanner. If we have a complete line,
1346 			 * copy it over. */
1347 			if ((s->bytes_read_in_line >= s->scan_bytes_per_line) &&
1348 			    (s->params.bytes_per_line <= max_length))
1349 			{
1350 				SANE_Int i;
1351 				SANE_Byte *line = s->line_buffer;
1352 				*length += s->params.bytes_per_line;
1353 				for (i=0; i< s->params.pixels_per_line; ++i) {
1354 					*data++ = line[0];
1355 					*data++ = line[scan_pixels_per_line];
1356 					*data++ = line[2 * scan_pixels_per_line];
1357 					line++;
1358 				}
1359 				max_length -= s->params.bytes_per_line;
1360 				s->bytes_read_in_line -= s->scan_bytes_per_line;
1361 			}
1362 		}
1363 
1364 	} else {
1365 		/* B/W and Grayscale use the same structure, so we use the same code */
1366 		SANE_Int bytes_available;
1367 		*length = 0;
1368 
1369 		while ((max_length != 0) && (s->ptr < s->end)) {
1370 			SANE_Int bytes_to_skip, bytes_to_copy;
1371 			bytes_available = (s->end - s->ptr);
1372 			bytes_to_copy = s->params.bytes_per_line - s->bytes_read_in_line;
1373 			bytes_to_skip = s->scan_bytes_per_line - s->bytes_read_in_line;
1374 
1375 			/* Don't copy more than we have buffer */
1376 			if (bytes_to_copy > max_length) {
1377 				bytes_to_copy = max_length;
1378 				bytes_to_skip = max_length;
1379 			}
1380 
1381 			/* Don't copy/skip more bytes than we have read in */
1382 			if (bytes_to_copy > bytes_available)
1383 				bytes_to_copy = bytes_available;
1384 			if (bytes_to_skip > bytes_available)
1385 				bytes_to_skip = bytes_available;
1386 
1387 			if (bytes_to_copy > 0) {
1388 				/* we have not yet copied all pixels of the line */
1389 				memcpy (data, s->ptr, bytes_to_copy);
1390 				max_length -= bytes_to_copy;
1391 				*length += bytes_to_copy;
1392 				data += bytes_to_copy;
1393 			}
1394 			if (bytes_to_skip > 0) {
1395 				s->ptr += bytes_to_skip;
1396 				s->bytes_read_in_line += bytes_to_skip;
1397 			}
1398 			if (s->bytes_read_in_line >= s->scan_bytes_per_line)
1399 				s->bytes_read_in_line -= s->scan_bytes_per_line;
1400 
1401 		}
1402 	}
1403 }
1404 
1405 static SANE_Status
mc_init_parameters(Magicolor_Scanner * s)1406 mc_init_parameters(Magicolor_Scanner * s)
1407 {
1408 	int dpi, optres;
1409 
1410 	DBG(5, "%s\n", __func__);
1411 
1412 	memset(&s->params, 0, sizeof(SANE_Parameters));
1413 
1414 	dpi = s->val[OPT_RESOLUTION].w;
1415 	optres = s->hw->cap->optical_res;
1416 
1417 	if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 ||
1418 		SANE_UNFIX(s->val[OPT_BR_X].w) == 0)
1419 		return SANE_STATUS_INVAL;
1420 
1421 	/* TODO: Use OPT_RESOLUTION or fixed 600dpi for left/top/width/height? */
1422 	s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5;
1423 
1424 	s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5;
1425 
1426 	s->width =
1427 		((SANE_UNFIX(s->val[OPT_BR_X].w -
1428 			   s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5;
1429 
1430 	s->height =
1431 		((SANE_UNFIX(s->val[OPT_BR_Y].w -
1432 			   s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5;
1433 
1434 	s->params.pixels_per_line = s->width * dpi / optres + 0.5;
1435 	s->params.lines = s->height * dpi / optres + 0.5;
1436 
1437 
1438 	DBG(1, "%s: resolution = %d, preview = %d\n",
1439 		__func__, dpi, s->val[OPT_PREVIEW].w);
1440 
1441 	DBG(1, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n",
1442 	    __func__, (void *) s, (void *) s->val,
1443 	    SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w),
1444 	    SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w));
1445 
1446 	/*
1447 	 * The default color depth is stored in mode_params.depth:
1448 	 */
1449 	DBG(1, " %s, vor depth\n", __func__);
1450 
1451 	if (mode_params[s->val[OPT_MODE].w].depth == 1)
1452 		s->params.depth = 1;
1453 	else
1454 		s->params.depth = s->val[OPT_BIT_DEPTH].w;
1455 
1456 	s->params.last_frame = SANE_TRUE;
1457 
1458 	s->params.bytes_per_line = ceil (s->params.depth * s->params.pixels_per_line / 8.0);
1459 
1460 	switch (s->val[OPT_MODE].w) {
1461 	case MODE_BINARY:
1462 	case MODE_GRAY:
1463 		s->params.format = SANE_FRAME_GRAY;
1464 		break;
1465 	case MODE_COLOR:
1466 		s->params.format = SANE_FRAME_RGB;
1467 		s->params.bytes_per_line *= 3;
1468 		break;
1469 	}
1470 
1471 
1472 	DBG(1, "%s: Parameters are format=%d, bytes_per_line=%d, lines=%d\n", __func__, s->params.format, s->params.bytes_per_line, s->params.lines);
1473 	return (s->params.lines > 0) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL;
1474 }
1475 
1476 static SANE_Status
mc_start_scan(Magicolor_Scanner * s)1477 mc_start_scan(Magicolor_Scanner * s)
1478 {
1479 	SANE_Status status = cmd_start_scan (s, s->data_len);
1480 	if (status != SANE_STATUS_GOOD ) {
1481 		DBG (1, "%s: starting the scan failed (%s)\n", __func__, sane_strstatus(status));
1482 	}
1483 	return status;
1484 }
1485 
1486 static SANE_Status
mc_read(struct Magicolor_Scanner *s)1487 mc_read(struct Magicolor_Scanner *s)
1488 {
1489 	SANE_Status status = SANE_STATUS_GOOD;
1490 	ssize_t buf_len = 0;
1491 
1492 	/* did we passed everything we read to sane? */
1493 	if (s->ptr == s->end) {
1494 
1495 		if (s->eof)
1496 			return SANE_STATUS_EOF;
1497 
1498 		s->counter++;
1499 		buf_len = s->block_len;
1500 
1501 		if (s->counter == s->blocks && s->last_len)
1502 			buf_len = s->last_len;
1503 
1504 		DBG(18, "%s: block %d/%d, size %lu\n", __func__,
1505 			s->counter, s->blocks,
1506 			(unsigned long) buf_len);
1507 
1508 		/* receive image data + error code */
1509 		status = cmd_read_data (s, s->buf, buf_len);
1510 		if (status != SANE_STATUS_GOOD) {
1511 			DBG (1, "%s: Receiving image data failed (%s)\n",
1512 					__func__, sane_strstatus(status));
1513 			cmd_cancel_scan(s);
1514 			return status;
1515 		}
1516 
1517 		DBG(18, "%s: successfully read %lu bytes\n", __func__, (unsigned long) buf_len);
1518 
1519 		if (s->counter < s->blocks) {
1520 			if (s->canceling) {
1521 				cmd_cancel_scan(s);
1522 				return SANE_STATUS_CANCELLED;
1523 			}
1524 		} else
1525 			s->eof = SANE_TRUE;
1526 
1527 		s->end = s->buf + buf_len;
1528 		s->ptr = s->buf;
1529 	}
1530 
1531 	return status;
1532 }
1533 
1534 
1535 
1536 
1537 /****************************************************************************
1538  *   SANE API implementation (high-level functions)
1539  ****************************************************************************/
1540 
1541 
1542 #if HAVE_LIBSNMP
1543 static struct MagicolorCap *
mc_get_device_from_identification(const char*ident)1544 mc_get_device_from_identification (const char*ident)
1545 {
1546 	int n;
1547 	for (n = 0; n < NELEMS (magicolor_cap); n++) {
1548 		if ((strcmp (magicolor_cap[n].model, ident) == 0) || (strcmp (magicolor_cap[n].OID, ident) == 0))
1549 		{
1550 			return &magicolor_cap[n];
1551 		}
1552 	}
1553 	return NULL;
1554 }
1555 #endif
1556 
1557 
1558 /*
1559  * close_scanner()
1560  *
1561  * Close the open scanner. Depending on the connection method, a different
1562  * close function is called.
1563  */
1564 static void
close_scanner(Magicolor_Scanner *s)1565 close_scanner(Magicolor_Scanner *s)
1566 {
1567 	DBG(7, "%s: fd = %d\n", __func__, s->fd);
1568 
1569 	if (s->fd == -1)
1570 		return;
1571 
1572 	mc_scan_finish(s);
1573 	if (s->hw->connection == SANE_MAGICOLOR_NET) {
1574 		sanei_magicolor_net_close(s);
1575 		sanei_tcp_close(s->fd);
1576 	} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
1577 		sanei_usb_close(s->fd);
1578 	}
1579 
1580 	s->fd = -1;
1581 }
1582 
1583 static SANE_Bool
split_scanner_name(const char *name, char * IP, unsigned int *model)1584 split_scanner_name (const char *name, char * IP, unsigned int *model)
1585 {
1586 	const char *device = name;
1587 	const char *qm;
1588 	*model = 0;
1589 	/* cut off leading net: */
1590 	if (strncmp(device, "net:", 4) == 0)
1591 		device = &device[4];
1592 
1593 	qm = strchr(device, '?');
1594 	if (qm != NULL) {
1595 		size_t len = qm-device;
1596 		strncpy (IP, device, len);
1597 		IP[len] = '\0';
1598 		qm++;
1599 		if (strncmp(qm, "model=", 6) == 0) {
1600 			qm += 6;
1601 			if (!sscanf(qm, "0x%x", model))
1602 				sscanf(qm, "%x", model);
1603 		}
1604 	} else {
1605 		strcpy (IP, device);
1606 	}
1607 	return SANE_TRUE;
1608 }
1609 
1610 /*
1611  * open_scanner()
1612  *
1613  * Open the scanner device. Depending on the connection method,
1614  * different open functions are called.
1615  */
1616 
1617 static SANE_Status
open_scanner(Magicolor_Scanner *s)1618 open_scanner(Magicolor_Scanner *s)
1619 {
1620 	SANE_Status status = 0;
1621 
1622 	DBG(7, "%s: %s\n", __func__, s->hw->sane.name);
1623 
1624 	if (s->fd != -1) {
1625 		DBG(7, "scanner is already open: fd = %d\n", s->fd);
1626 		return SANE_STATUS_GOOD;	/* no need to open the scanner */
1627 	}
1628 
1629 	if (s->hw->connection == SANE_MAGICOLOR_NET) {
1630 		/* device name has the form net:ipaddr?model=... */
1631 		char IP[1024];
1632 		unsigned int model = 0;
1633 		if (!split_scanner_name (s->hw->sane.name, IP, &model))
1634 			return SANE_STATUS_INVAL;
1635 		status = sanei_tcp_open(IP, 4567, &s->fd);
1636 		if (model>0)
1637 			mc_set_device (s, model);
1638 		if (status == SANE_STATUS_GOOD) {
1639 			DBG(7, "awaiting welcome message\n");
1640 			status = sanei_magicolor_net_open (s);
1641 		}
1642 
1643 	} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
1644 		status = sanei_usb_open(s->hw->sane.name, &s->fd);
1645 		if (s->hw->cap->out_ep>0)
1646 			sanei_usb_set_endpoint (s->fd,
1647 				USB_DIR_OUT | USB_ENDPOINT_TYPE_BULK, s->hw->cap->out_ep);
1648 		if (s->hw->cap->in_ep>0)
1649 			sanei_usb_set_endpoint (s->fd,
1650 				USB_DIR_IN | USB_ENDPOINT_TYPE_BULK, s->hw->cap->in_ep);
1651 	}
1652 
1653 	if (status == SANE_STATUS_ACCESS_DENIED) {
1654 		DBG(1, "please check that you have permissions on the device.\n");
1655 		DBG(1, "if this is a multi-function device with a printer,\n");
1656 		DBG(1, "disable any conflicting driver (like usblp).\n");
1657 	}
1658 
1659 	if (status != SANE_STATUS_GOOD)
1660 		DBG(1, "%s open failed: %s\n", s->hw->sane.name,
1661 			sane_strstatus(status));
1662 	else
1663 		DBG(3, "scanner opened\n");
1664 
1665 	return status;
1666 }
1667 
1668 static SANE_Status
detect_usb(struct Magicolor_Scanner *s)1669 detect_usb(struct Magicolor_Scanner *s)
1670 {
1671 	SANE_Status status;
1672 	int vendor, product;
1673 	int i, numIds;
1674 	SANE_Bool is_valid;
1675 
1676 	/* if the sanei_usb_get_vendor_product call is not supported,
1677 	 * then we just ignore this and rely on the user to config
1678 	 * the correct device.
1679 	 */
1680 
1681 	status = sanei_usb_get_vendor_product(s->fd, &vendor, &product);
1682 	if (status != SANE_STATUS_GOOD) {
1683 		DBG(1, "the device cannot be verified - will continue\n");
1684 		return SANE_STATUS_GOOD;
1685 	}
1686 
1687 	/* check the vendor ID to see if we are dealing with an MAGICOLOR device */
1688 	if (vendor != SANE_MAGICOLOR_VENDOR_ID) {
1689 		/* this is not a supported vendor ID */
1690 		DBG(1, "not an Magicolor device at %s (vendor id=0x%x)\n",
1691 		    s->hw->sane.name, vendor);
1692 		return SANE_STATUS_INVAL;
1693 	}
1694 
1695 	numIds = sanei_magicolor_getNumberOfUSBProductIds();
1696 	is_valid = SANE_FALSE;
1697 	i = 0;
1698 
1699 	/* check all known product IDs to verify that we know
1700 	 *	   about the device */
1701 	while (i != numIds && !is_valid) {
1702 		if (product == sanei_magicolor_usb_product_ids[i])
1703 			is_valid = SANE_TRUE;
1704 		i++;
1705 	}
1706 
1707 	if (is_valid == SANE_FALSE) {
1708 		DBG(1, "the device at %s is not a supported (product id=0x%x)\n",
1709 		    s->hw->sane.name, product);
1710 		return SANE_STATUS_INVAL;
1711 	}
1712 
1713 	DBG(2, "found valid Magicolor scanner: 0x%x/0x%x (vendorID/productID)\n",
1714 	    vendor, product);
1715 	mc_set_device(s, product);
1716 
1717 	return SANE_STATUS_GOOD;
1718 }
1719 
1720 /*
1721  * used by attach* and sane_get_devices
1722  * a ptr to a single-linked list of Magicolor_Device structs
1723  * a ptr to a null term array of ptrs to SANE_Device structs
1724  */
1725 static int num_devices;		/* number of scanners attached to backend */
1726 static Magicolor_Device *first_dev;	/* first MAGICOLOR scanner in list */
1727 static const SANE_Device **devlist = NULL;
1728 
1729 static struct Magicolor_Scanner *
scanner_create(struct Magicolor_Device *dev, SANE_Status *status)1730 scanner_create(struct Magicolor_Device *dev, SANE_Status *status)
1731 {
1732 	struct Magicolor_Scanner *s;
1733 
1734 	s = malloc(sizeof(struct Magicolor_Scanner));
1735 	if (s == NULL) {
1736 		*status = SANE_STATUS_NO_MEM;
1737 		return NULL;
1738 	}
1739 
1740 	memset(s, 0x00, sizeof(struct Magicolor_Scanner));
1741 
1742 	s->fd = -1;
1743 	s->hw = dev;
1744 
1745 	return s;
1746 }
1747 
1748 static struct Magicolor_Scanner *
device_detect(const char *name, int type, SANE_Status *status)1749 device_detect(const char *name, int type, SANE_Status *status)
1750 {
1751 	struct Magicolor_Scanner *s;
1752 	struct Magicolor_Device *dev;
1753 
1754 	/* try to find the device in our list */
1755 	for (dev = first_dev; dev; dev = dev->next) {
1756 		if (strcmp(dev->sane.name, name) == 0) {
1757 			dev->missing = 0;
1758 			DBG (10, "%s: Device %s already attached!\n", __func__,
1759 			     name);
1760 			return scanner_create(dev, status);
1761 		}
1762 	}
1763 
1764 	if (type == SANE_MAGICOLOR_NODEV) {
1765 		*status = SANE_STATUS_INVAL;
1766 		return NULL;
1767 	}
1768 
1769 	/* alloc and clear our device structure */
1770 	dev = malloc(sizeof(*dev));
1771 	if (!dev) {
1772 		*status = SANE_STATUS_NO_MEM;
1773 		return NULL;
1774 	}
1775 	memset(dev, 0x00, sizeof(struct Magicolor_Device));
1776 
1777 	s = scanner_create(dev, status);
1778 	if (s == NULL)
1779 		return NULL;
1780 
1781 	mc_dev_init(dev, name, type);
1782 
1783 	*status = open_scanner(s);
1784 	if (*status != SANE_STATUS_GOOD) {
1785 		free(s);
1786 		return NULL;
1787 	}
1788 
1789 	/* from now on, close_scanner() must be called */
1790 
1791 	/* USB requires special care */
1792 	if (dev->connection == SANE_MAGICOLOR_USB) {
1793 		*status = detect_usb(s);
1794 	}
1795 
1796 	if (*status != SANE_STATUS_GOOD)
1797 		goto close;
1798 
1799 	/* set name and model (if not already set) */
1800 	if (dev->model == NULL)
1801 		mc_set_model(s, "generic", 7);
1802 
1803 	dev->name = strdup(name);
1804 	dev->sane.name = dev->name;
1805 
1806 	*status = mc_discover_capabilities(s);
1807 	if (*status != SANE_STATUS_GOOD)
1808 		goto close;
1809 
1810 	if (source_list[0] == NULL || dev->cap->dpi_range.min == 0) {
1811 		DBG(1, "something is wrong in the discovery process, aborting.\n");
1812 		*status = SANE_STATUS_IO_ERROR;
1813 		goto close;
1814 	}
1815 
1816 	mc_dev_post_init(dev);
1817 
1818 	/* add this scanner to the device list */
1819 	num_devices++;
1820 	dev->missing = 0;
1821 	dev->next = first_dev;
1822 	first_dev = dev;
1823 
1824 	return s;
1825 
1826 	close:
1827 	close_scanner(s);
1828 	free(s);
1829 	return NULL;
1830 }
1831 
1832 #if HAVE_LIBSNMP
1833 
1834 /* Keep a linked list of already observed IP addresses */
1835 /* typedef struct snmp_ip SNMP_IP; */
1836 typedef struct snmp_ip {
1837   char ip_addr[1024];
1838   struct snmp_ip*next;
1839 } snmp_ip;
1840 
1841 typedef struct {
1842   int nr;
1843   snmp_ip*handled;
1844   snmp_ip*detected;
1845 } snmp_discovery_data;
1846 
1847 
1848 /** Handle one SNMP response (whether received sync or async) and if describes
1849  * a magicolor device, attach it. Returns the number of attached devices (0
1850  * or 1) */
1851 static int
mc_network_discovery_handle(struct snmp_pdu *pdu, snmp_discovery_data *magic)1852 mc_network_discovery_handle (struct snmp_pdu *pdu, snmp_discovery_data *magic)
1853 {
1854 	netsnmp_variable_list *varlist = pdu->variables, *vp;
1855 	oid anOID[MAX_OID_LEN];
1856 	size_t anOID_len = MAX_OID_LEN;
1857 	/* Device information variables */
1858 	char ip_addr[1024] = "";
1859 	char model[1024] = "";
1860 	char device[1024] = "";
1861 	/* remote IP detection variables */
1862 	netsnmp_indexed_addr_pair *responder = (netsnmp_indexed_addr_pair *) pdu->transport_data;
1863 	struct sockaddr_in *remote = NULL;
1864 	struct MagicolorCap *cap;
1865 	snmp_ip *ip = NULL;
1866 
1867 	DBG(5, "%s: Handling SNMP response \n", __func__);
1868 
1869 	if (responder == NULL || pdu->transport_data_length != sizeof(netsnmp_indexed_addr_pair )) {
1870 		DBG(1, "%s: Unable to extract IP address from SNMP response.\n",
1871 		    __func__);
1872 		return 0;
1873 	}
1874 	remote = (struct sockaddr_in *) &(responder->remote_addr);
1875 	if (remote == NULL) {
1876 		DBG(1, "%s: Unable to extract IP address from SNMP response.\n",
1877 			__func__);
1878 		return 0;
1879 	}
1880 	snprintf(ip_addr, sizeof(ip_addr), "%s", inet_ntoa(remote->sin_addr));
1881 	DBG(35, "%s: IP Address of responder is %s\n", __func__, ip_addr);
1882 	if (magic)
1883 		ip = magic->handled;
1884 	while (ip) {
1885 		if (strcmp (ip->ip_addr, ip_addr) == 0) {
1886 			DBG (5, "%s: Already handled device %s, skipping\n", __func__, ip_addr);
1887 			return 0;
1888 		}
1889 		ip = ip->next;
1890 	}
1891 	if (magic) {
1892 		snmp_ip *new_handled = malloc(sizeof(snmp_ip));
1893 		strcpy (&new_handled->ip_addr[0], ip_addr);
1894 		new_handled->next = magic->handled;
1895 		magic->handled = new_handled;
1896 	}
1897 
1898 	/* System Object ID (Unique OID identifying model)
1899 	 * This determines whether we really have a magicolor device */
1900 	anOID_len = MAX_OID_LEN;
1901 	read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len);
1902 	vp = find_varbind_in_list (varlist, anOID, anOID_len);
1903 	if (vp) {
1904 		size_t value_len = vp->val_len/sizeof(oid);
1905 		if (vp->type != ASN_OBJECT_ID) {
1906 			DBG (3, "%s: SystemObjectID does not return an OID, device is not a magicolor device\n", __func__);
1907 			return 0;
1908 		}
1909 
1910 		// Make sure that snprint_objid gives us just numbers, instead of a
1911 		// SNMPv2-SMI::enterprises prefix.
1912 		netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
1913 				   NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
1914 				   NETSNMP_OID_OUTPUT_NUMERIC);
1915 
1916 		snprint_objid (device, sizeof(device), vp->val.objid, value_len);
1917 		DBG (5, "%s: Device object ID is '%s'\n", __func__, device);
1918 
1919 		anOID_len = MAX_OID_LEN;
1920 		read_objid (MAGICOLOR_SNMP_DEVICE_TREE, anOID, &anOID_len);
1921 		if (netsnmp_oid_is_subtree (anOID, anOID_len,
1922 				vp->val.objid, value_len) == 0) {
1923 			DBG (5, "%s: Device appears to be a magicolor device (OID=%s)\n", __func__, device);
1924 		} else {
1925 			DBG (5, "%s: Device is not a Magicolor device\n", __func__);
1926 			return 0;
1927 		}
1928 	}
1929 
1930 	/* Retrieve sysDescr (i.e. model name) */
1931 	anOID_len = MAX_OID_LEN;
1932 	read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len);
1933 	vp = find_varbind_in_list (varlist, anOID, anOID_len);
1934 	if (vp) {
1935 		size_t model_len = min(vp->val_len, sizeof(model) - 1);
1936 		memcpy(model, vp->val.string, model_len);
1937 		model[model_len] = '\0';
1938 		DBG (5, "%s: Found model: %s\n", __func__, model);
1939 	}
1940 
1941 	DBG (1, "%s: Detected device '%s' on IP %s\n",
1942 	     __func__, model, ip_addr);
1943 
1944 	vp = pdu->variables;
1945 	/* TODO: attach the IP with attach_one_net(ip) */
1946 	cap = mc_get_device_from_identification (device);
1947 	if (cap) {
1948 		DBG(1, "%s: Found autodiscovered device: %s (type 0x%x)\n", __func__, cap->model, cap->id);
1949 		attach_one_net (ip_addr, cap->id);
1950 		if (magic) {
1951 			snmp_ip *new_detected = malloc(sizeof(snmp_ip));
1952 			strcpy (&new_detected->ip_addr[0], ip_addr);
1953 			new_detected->next = magic->detected;
1954 			magic->detected = new_detected;
1955 		}
1956 		return 1;
1957 	}
1958 	return 0;
1959 }
1960 
1961 static int
mc_network_discovery_cb(int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic)1962 mc_network_discovery_cb (int operation, struct snmp_session *sp, int reqid,
1963 			 struct snmp_pdu *pdu, void *magic)
1964 {
1965 	NOT_USED (reqid);
1966 	NOT_USED (sp);
1967 	DBG(5, "%s: Received broadcast response \n", __func__);
1968 
1969 	if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
1970 		snmp_discovery_data *m = (snmp_discovery_data*)magic;
1971 		int nr = mc_network_discovery_handle (pdu, m);
1972 		m->nr += nr;
1973 		DBG(5, "%s: Added %d discovered host(s) for SNMP response.\n", __func__, nr);
1974 	}
1975 
1976 	return 0;
1977 }
1978 #endif
1979 
1980 /* Use SNMP for automatic network discovery. If host is given, try to detect
1981  * that one host (using sync SNMP, otherwise send an SNMP broadcast (async).
1982  */
1983 static int
mc_network_discovery(const char*host)1984 mc_network_discovery(const char*host)
1985 {
1986 #if HAVE_LIBSNMP
1987 	netsnmp_session session, *ss;
1988 	netsnmp_pdu *pdu;
1989 	oid anOID[MAX_OID_LEN];
1990 	size_t anOID_len = MAX_OID_LEN;
1991 	snmp_discovery_data magic;
1992 	magic.nr = 0;
1993 	magic.handled = 0;
1994 	magic.detected = 0;
1995 
1996 	DBG(1, "%s: running network discovery \n", __func__);
1997 
1998 	/* Win32: init winsock */
1999 	SOCK_STARTUP;
2000 	init_snmp("sane-magicolor-backend");
2001 	snmp_sess_init (&session);
2002 	session.version = SNMP_VERSION_2c;
2003 	session.community = (u_char *) "public";
2004 	session.community_len = strlen ((char *)session.community);
2005 	if (host) {
2006 		session.peername = (char *) host;
2007 	} else {
2008 		/* Do a network discovery via a broadcast */
2009 		session.peername = "255.255.255.255";
2010 		session.flags   |= SNMP_FLAGS_UDP_BROADCAST;
2011 		session.callback = mc_network_discovery_cb;
2012 		session.callback_magic = &magic;
2013 	}
2014 
2015 	ss = snmp_open (&session); /* establish the session */
2016 	if (!ss) {
2017 		snmp_sess_perror ("ack", &session);
2018 		SOCK_CLEANUP;
2019 		return 0;
2020 	}
2021 
2022 	/* Create the PDU for the data for our request and add the three
2023 	 * desired OIDs to the PDU */
2024 	pdu = snmp_pdu_create (SNMP_MSG_GET);
2025 
2026 	/* SNMPv2-MIB::sysDescr.0 */
2027 	anOID_len = MAX_OID_LEN;
2028 	if (read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len)) {
2029 		snmp_add_null_var (pdu, anOID, anOID_len);
2030 	}
2031 	/* SNMPv2-MIB::sysObjectID.0 */
2032 	anOID_len = MAX_OID_LEN;
2033 	if (read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len)) {
2034 		snmp_add_null_var (pdu, anOID, anOID_len);
2035 	}
2036 	/* IF-MIB::ifPhysAddress.1 */
2037 	anOID_len = MAX_OID_LEN;
2038 	if (read_objid(MAGICOLOR_SNMP_MAC_OID, anOID, &anOID_len)) {
2039 		snmp_add_null_var (pdu, anOID, anOID_len);
2040 	}
2041 	/* TODO: Add more interesting OIDs, in particular vendor OIDs */
2042 
2043 	/* Now send out the request and wait for responses for some time.
2044 	 * If we get a response, connect to that device (in the callback),
2045 	 * otherwise we probably don't have a magicolor device in the
2046 	 * LAN (or SNMP is turned off, in which case we have no way to detect
2047 	 * it.
2048 	 */
2049 	DBG(100, "%s: Sending SNMP packet\n", __func__);
2050 	if (host) {
2051 		/* sync request to given hostname, immediately read the reply */
2052 		netsnmp_pdu *response = 0;
2053 		int status = snmp_synch_response(ss, pdu, &response);
2054  		if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
2055 			magic.nr = mc_network_discovery_handle (response, &magic);
2056 		}
2057 		if (response)
2058 			snmp_free_pdu(response);
2059 
2060 
2061 	} else {
2062 		/* No hostname, so do a broadcast */
2063 		struct timeval nowtime, endtime; /* end time for SNMP scan */
2064 		struct timeval timeout;
2065 		int i=0;
2066 
2067 		if (!snmp_send(ss, pdu)) {
2068 			snmp_free_pdu(pdu);
2069 			DBG(100, "%s: Sending SNMP packet NOT successful\n", __func__);
2070 			return 0;
2071 		}
2072 		/* listen for responses for MC_AutoDetectionTimeout milliseconds: */
2073 		/* First get the final timeout time */
2074 		gettimeofday (&nowtime, NULL);
2075 		timeout.tv_sec = MC_SNMP_Timeout / 1000;
2076 		timeout.tv_usec = (MC_SNMP_Timeout % 1000) * 1000;
2077 		timeradd (&nowtime, &timeout, &endtime);
2078 
2079 		while (timercmp(&nowtime, &endtime, <)) {
2080 			int fds = 0, block = 0;
2081 			fd_set fdset;
2082 			DBG(1, "    loop=%d\n", i++);
2083 			timeout.tv_sec = 0;
2084 			/* Use a 125ms timeout for select. If we get a response,
2085 			 * the loop will be entered earlier again, anyway */
2086 			timeout.tv_usec = 125000;
2087 			FD_ZERO (&fdset);
2088 			snmp_select_info (&fds, &fdset, &timeout, &block);
2089 			fds = select (fds, &fdset, NULL, NULL, /*block?NULL:*/&timeout);
2090 			if (fds) snmp_read(&fdset);
2091 			else snmp_timeout();
2092 			gettimeofday(&nowtime, NULL);
2093 		}
2094 		/* Clean up the data in magic */
2095 		while (magic.handled) {
2096 		  snmp_ip *tmp = magic.handled->next;
2097 		  free (magic.handled);
2098 		  magic.handled = tmp;
2099 		}
2100 		while (magic.detected) {
2101 		  snmp_ip *tmp = magic.detected->next;
2102 		  free (magic.detected);
2103 		  magic.detected = tmp;
2104 		}
2105 	}
2106 
2107 	/* Clean up */
2108 	snmp_close(ss);
2109 	SOCK_CLEANUP;
2110 	DBG (5, "%s: Discovered %d host(s)\n", __func__, magic.nr);
2111 	return magic.nr;
2112 
2113 #else
2114 	DBG (1, "%s: net-snmp library not enabled, auto-detecting network scanners not supported.\n", __func__);
2115 	NOT_USED (host);
2116 	return 0;
2117 #endif
2118 }
2119 
2120 static SANE_Status
attach(const char *name, int type)2121 attach(const char *name, int type)
2122 {
2123 	SANE_Status status;
2124 	Magicolor_Scanner *s;
2125 
2126 	DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type);
2127 
2128 	s = device_detect(name, type, &status);
2129 	if(s == NULL)
2130 		return status;
2131 
2132 	close_scanner(s);
2133 	free(s);
2134 	return status;
2135 }
2136 
2137 SANE_Status
attach_one_usb(const char *dev)2138 attach_one_usb(const char *dev)
2139 {
2140 	DBG(7, "%s: dev = %s\n", __func__, dev);
2141 	return attach(dev, SANE_MAGICOLOR_USB);
2142 }
2143 
2144 static SANE_Status
attach_one_net(const char *dev, unsigned int model)2145 attach_one_net(const char *dev, unsigned int model)
2146 {
2147 	char name[1024];
2148 
2149 	DBG(7, "%s: dev = %s\n", __func__, dev);
2150 	if (model > 0) {
2151 		snprintf(name, 1024, "net:%s?model=0x%x", dev, model);
2152 	} else {
2153 		snprintf(name, 1024, "net:%s", dev);
2154 	}
2155 
2156 	return attach(name, SANE_MAGICOLOR_NET);
2157 }
2158 
2159 static SANE_Status
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, void *data)2160 attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
2161 		  void *data)
2162 {
2163 	int vendor, product, timeout;
2164 	SANE_Bool local_only = *(SANE_Bool*) data;
2165 	int len = strlen(line);
2166 
2167 	DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
2168 
2169 	if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
2170 		/* add the vendor and product IDs to the list of
2171 		 *		   known devices before we call the attach function */
2172 
2173 		int numIds = sanei_magicolor_getNumberOfUSBProductIds();
2174 
2175 		if (vendor != SANE_MAGICOLOR_VENDOR_ID)
2176 			return SANE_STATUS_INVAL; /* this is not a KONICA MINOLTA device */
2177 
2178 		sanei_magicolor_usb_product_ids[numIds - 1] = product;
2179 		sanei_usb_attach_matching_devices(line, attach_one_usb);
2180 
2181 	} else if (strncmp(line, "usb", 3) == 0 && len == 3) {
2182 		int i, numIds;
2183 
2184 		numIds = sanei_magicolor_getNumberOfUSBProductIds();
2185 
2186 		for (i = 0; i < numIds; i++) {
2187 			sanei_usb_find_devices(SANE_MAGICOLOR_VENDOR_ID,
2188 					       sanei_magicolor_usb_product_ids[i], attach_one_usb);
2189 		}
2190 
2191 	} else if (strncmp(line, "net", 3) == 0) {
2192 
2193 		if (!local_only) {
2194 			/* remove the "net" sub string */
2195 			const char *name =
2196 				sanei_config_skip_whitespace(line + 3);
2197 			char IP[1024];
2198 			unsigned int model = 0;
2199 
2200 			if (strncmp(name, "autodiscovery", 13) == 0) {
2201 				DBG (50, "%s: Initiating network autodiscovervy via SNMP\n", __func__);
2202 				mc_network_discovery(NULL);
2203 			} else if (sscanf(name, "%s %x", IP, &model) == 2) {
2204 				DBG(50, "%s: Using network device on IP %s, forcing model 0x%x\n", __func__, IP, model);
2205 				attach_one_net(IP, model);
2206 			} else {
2207 				/* use SNMP to detect the type. If not successful,
2208 				 * add the host with model type 0 */
2209 				DBG(50, "%s: Using network device on IP %s, trying to autodetect model\n", __func__, IP);
2210 				if (mc_network_discovery(name)==0) {
2211 					DBG(1, "%s: Autodetecting device model failed, using default model\n", __func__);
2212 					attach_one_net(name, 0);
2213 				}
2214 			}
2215 		}
2216 
2217 	} else if (sscanf(line, "snmp-timeout %i\n", &timeout)) {
2218 		/* Timeout for SNMP network discovery */
2219 		DBG(50, "%s: SNMP timeout set to %d\n", __func__, timeout);
2220 		MC_SNMP_Timeout = timeout;
2221 
2222 	} else if (sscanf(line, "scan-data-timeout %i\n", &timeout)) {
2223 		/* Timeout for scan data requests */
2224 		DBG(50, "%s: Scan data timeout set to %d\n", __func__, timeout);
2225 		MC_Scan_Data_Timeout = timeout;
2226 
2227 	} else if (sscanf(line, "request-timeout %i\n", &timeout)) {
2228 		/* Timeout for all other read requests */
2229 		DBG(50, "%s: Request timeout set to %d\n", __func__, timeout);
2230 		MC_Request_Timeout = timeout;
2231 
2232 	} else {
2233 		/* TODO: Warning about unparsable line! */
2234 	}
2235 
2236 	return SANE_STATUS_GOOD;
2237 }
2238 
2239 static void
free_devices(void)2240 free_devices(void)
2241 {
2242 	Magicolor_Device *dev, *next;
2243 
2244 	DBG(5, "%s\n", __func__);
2245 
2246 	for (dev = first_dev; dev; dev = next) {
2247 		next = dev->next;
2248 		free(dev->name);
2249 		free(dev->model);
2250 		free(dev);
2251 	}
2252 
2253 	if (devlist)
2254 		free(devlist);
2255 	devlist = NULL;
2256 	first_dev = NULL;
2257 }
2258 
2259 SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)2260 sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
2261 {
2262 	DBG_INIT();
2263 	DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__);
2264 
2265 	DBG(1, "magicolor backend, version %i.%i.%i\n",
2266 	    MAGICOLOR_VERSION, MAGICOLOR_REVISION, MAGICOLOR_BUILD);
2267 
2268 	if (version_code != NULL)
2269 		*version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR,
2270 						  MAGICOLOR_BUILD);
2271 
2272 	sanei_usb_init();
2273 
2274 	return SANE_STATUS_GOOD;
2275 }
2276 
2277 /* Clean up the list of attached scanners. */
2278 void
sane_exit(void)2279 sane_exit(void)
2280 {
2281 	DBG(5, "%s\n", __func__);
2282 	free_devices();
2283 }
2284 
2285 SANE_Status
sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)2286 sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
2287 {
2288 	Magicolor_Device *dev, *s, *prev=0;
2289 	int i;
2290 
2291 	DBG(5, "%s\n", __func__);
2292 
2293 	sanei_usb_init();
2294 
2295 	/* mark all existing scanners as missing, attach_one will remove mark */
2296 	for (s = first_dev; s; s = s->next) {
2297 		s->missing = 1;
2298 	}
2299 
2300 	/* Read the config, mark each device as found, possibly add new devs */
2301 	sanei_configure_attach(MAGICOLOR_CONFIG_FILE, NULL,
2302 			       attach_one_config, &local_only);
2303 
2304 	/*delete missing scanners from list*/
2305 	for (s = first_dev; s;) {
2306 		if (s->missing) {
2307 			DBG (5, "%s: missing scanner %s\n", __func__, s->name);
2308 
2309 			/*splice s out of list by changing pointer in prev to next*/
2310 			if (prev) {
2311 				prev->next = s->next;
2312 				free (s);
2313 				s = prev->next;
2314 				num_devices--;
2315 			} else {
2316 				/*remove s from head of list */
2317 				first_dev = s->next;
2318 				free(s);
2319 				s = first_dev;
2320 				prev=NULL;
2321 				num_devices--;
2322 			}
2323 		} else {
2324 			prev = s;
2325 			s = prev->next;
2326 		}
2327 	}
2328 
2329 	DBG (15, "%s: found %d scanner(s)\n", __func__, num_devices);
2330 	for (s = first_dev; s; s=s->next) {
2331 		DBG (15, "%s: found scanner %s\n", __func__, s->name);
2332 	}
2333 
2334 	if (devlist)
2335 		free (devlist);
2336 
2337 	devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
2338 	if (!devlist) {
2339 		DBG(1, "out of memory (line %d)\n", __LINE__);
2340 		return SANE_STATUS_NO_MEM;
2341 	}
2342 
2343 	DBG(5, "%s - results:\n", __func__);
2344 
2345 	for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) {
2346 		DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model);
2347 		devlist[i] = &dev->sane;
2348 	}
2349 
2350 	devlist[i] = NULL;
2351 
2352 	if(device_list){
2353 		*device_list = devlist;
2354 	}
2355 
2356 	return SANE_STATUS_GOOD;
2357 }
2358 
2359 static SANE_Status
init_options(Magicolor_Scanner *s)2360 init_options(Magicolor_Scanner *s)
2361 {
2362 	int i;
2363 	SANE_Word *res_list;
2364 
2365 	for (i = 0; i < NUM_OPTIONS; i++) {
2366 		s->opt[i].size = sizeof(SANE_Word);
2367 		s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2368 	}
2369 
2370 	s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2371 	s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2372 	s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2373 	s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2374 	s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
2375 
2376 	/* "Scan Mode" group: */
2377 
2378 	s->opt[OPT_MODE_GROUP].name = SANE_NAME_STANDARD;
2379 	s->opt[OPT_MODE_GROUP].title = SANE_TITLE_STANDARD;
2380 	s->opt[OPT_MODE_GROUP].desc = SANE_DESC_STANDARD;
2381 	s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
2382 	s->opt[OPT_MODE_GROUP].cap = 0;
2383 
2384 	/* scan mode */
2385 	s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
2386 	s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
2387 	s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
2388 	s->opt[OPT_MODE].type = SANE_TYPE_STRING;
2389 	s->opt[OPT_MODE].size = max_string_size(mode_list);
2390 	s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2391 	s->opt[OPT_MODE].constraint.string_list = mode_list;
2392 	s->val[OPT_MODE].w = 0;	/* Binary */
2393 
2394 	/* bit depth */
2395 	s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
2396 	s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
2397 	s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
2398 	s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
2399 	s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE;
2400 	s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2401 	s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->cap->depth_list;
2402 	s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2403 	s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1];	/* the first "real" element is the default */
2404 
2405 	if (s->hw->cap->depth_list[0] == 1)	/* only one element in the list -> hide the option */
2406 		s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2407 
2408 
2409 	/* brightness */
2410 	s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
2411 	s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
2412 	s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2413 	s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
2414 	s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
2415 	s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2416 	s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cap->brightness;
2417 	s->val[OPT_BRIGHTNESS].w = 5;	/* Normal */
2418 
2419 	/* resolution */
2420 	s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2421 	s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2422 	s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2423 	s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
2424 	s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
2425 	s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2426 	res_list = malloc((s->hw->cap->res_list_size + 1) * sizeof(SANE_Word));
2427 	if (res_list == NULL) {
2428 		return SANE_STATUS_NO_MEM;
2429 	}
2430 	*(res_list) = s->hw->cap->res_list_size;
2431 	memcpy(&(res_list[1]), s->hw->cap->res_list, s->hw->cap->res_list_size * sizeof(SANE_Word));
2432 	s->opt[OPT_RESOLUTION].constraint.word_list = res_list;
2433 	s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min;
2434 
2435 
2436 	/* preview */
2437 	s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
2438 	s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2439 	s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
2440 	s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
2441 	s->val[OPT_PREVIEW].w = SANE_FALSE;
2442 
2443 	/* source */
2444 	s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
2445 	s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
2446 	s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
2447 	s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
2448 	s->opt[OPT_SOURCE].size = max_string_size(source_list);
2449 	s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2450 	s->opt[OPT_SOURCE].constraint.string_list = source_list;
2451 	s->val[OPT_SOURCE].w = 0;	/* always use Flatbed as default */
2452 
2453 	s->opt[OPT_ADF_MODE].name = "adf-mode";
2454 	s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode");
2455 	s->opt[OPT_ADF_MODE].desc =
2456 	SANE_I18N("Selects the ADF mode (simplex/duplex)");
2457 	s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING;
2458 	s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list);
2459 	s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2460 	s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list;
2461 	s->val[OPT_ADF_MODE].w = 0;	/* simplex */
2462 	if ((!s->hw->cap->ADF) || (s->hw->cap->adf_duplex == SANE_FALSE))
2463 		s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE;
2464 
2465 
2466 	/* "Geometry" group: */
2467 	s->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY;
2468 	s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY;
2469 	s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;
2470 	s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2471 	s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2472 
2473 	/* top-left x */
2474 	s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2475 	s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2476 	s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2477 	s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2478 	s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2479 	s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2480 	s->opt[OPT_TL_X].constraint.range = s->hw->x_range;
2481 	s->val[OPT_TL_X].w = 0;
2482 
2483 	/* top-left y */
2484 	s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2485 	s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2486 	s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2487 	s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2488 	s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2489 	s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2490 	s->opt[OPT_TL_Y].constraint.range = s->hw->y_range;
2491 	s->val[OPT_TL_Y].w = 0;
2492 
2493 	/* bottom-right x */
2494 	s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2495 	s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2496 	s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2497 	s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2498 	s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2499 	s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2500 	s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
2501 	s->val[OPT_BR_X].w = s->hw->x_range->max;
2502 
2503 	/* bottom-right y */
2504 	s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2505 	s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2506 	s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2507 	s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2508 	s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2509 	s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2510 	s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
2511 	s->val[OPT_BR_Y].w = s->hw->y_range->max;
2512 
2513 	return SANE_STATUS_GOOD;
2514 }
2515 
2516 SANE_Status
sane_open(SANE_String_Const name, SANE_Handle *handle)2517 sane_open(SANE_String_Const name, SANE_Handle *handle)
2518 {
2519 	SANE_Status status;
2520 	Magicolor_Scanner *s = NULL;
2521 
2522 	int l = strlen(name);
2523 
2524 	DBG(7, "%s: name = %s\n", __func__, name);
2525 
2526 	/* probe if empty device name provided */
2527 	if (l == 0) {
2528 
2529 		status = sane_get_devices(NULL,0);
2530 		if (status != SANE_STATUS_GOOD) {
2531 			return status;
2532 		}
2533 
2534 		if (first_dev == NULL) {
2535 			DBG(1, "no device detected\n");
2536 			return SANE_STATUS_INVAL;
2537 		}
2538 
2539 		s = device_detect(first_dev->sane.name, first_dev->connection,
2540 					&status);
2541 		if (s == NULL) {
2542 			DBG(1, "cannot open a perfectly valid device (%s),"
2543 				" please report to the authors\n", name);
2544 			return SANE_STATUS_INVAL;
2545 		}
2546 
2547 	} else {
2548 
2549 		if (strncmp(name, "net:", 4) == 0) {
2550 			s = device_detect(name, SANE_MAGICOLOR_NET, &status);
2551 			if (s == NULL)
2552 				return status;
2553 		} else if (strncmp(name, "libusb:", 7) == 0) {
2554 			s = device_detect(name, SANE_MAGICOLOR_USB, &status);
2555 			if (s == NULL)
2556 				return status;
2557 		} else {
2558 
2559 			/* as a last resort, check for a match
2560 			 * in the device list. This should handle platforms without libusb.
2561 			 */
2562 			if (first_dev == NULL) {
2563 				status = sane_get_devices(NULL,0);
2564 				if (status != SANE_STATUS_GOOD) {
2565 					return status;
2566 				}
2567 			}
2568 
2569 			s = device_detect(name, SANE_MAGICOLOR_NODEV, &status);
2570 			if (s == NULL) {
2571 				DBG(1, "invalid device name: %s\n", name);
2572 				return SANE_STATUS_INVAL;
2573 			}
2574 		}
2575 	}
2576 
2577 
2578 	/* s is always valid here */
2579 
2580 	DBG(1, "handle obtained\n");
2581 
2582 	init_options(s);
2583 
2584 	*handle = (SANE_Handle) s;
2585 
2586 	status = open_scanner(s);
2587 	if (status != SANE_STATUS_GOOD) {
2588 		free(s);
2589 		return status;
2590 	}
2591 
2592 	return status;
2593 }
2594 
2595 void
sane_close(SANE_Handle handle)2596 sane_close(SANE_Handle handle)
2597 {
2598 	Magicolor_Scanner *s;
2599 
2600 	/*
2601 	 * XXX Test if there is still data pending from
2602 	 * the scanner. If so, then do a cancel
2603 	 */
2604 
2605 	s = (Magicolor_Scanner *) handle;
2606 
2607 	if (s->fd != -1)
2608 		close_scanner(s);
2609 
2610 	free(s);
2611 }
2612 
2613 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)2614 sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
2615 {
2616 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2617 
2618 	if (option < 0 || option >= NUM_OPTIONS)
2619 		return NULL;
2620 
2621 	return s->opt + option;
2622 }
2623 
2624 static const SANE_String_Const *
search_string_list(const SANE_String_Const *list, SANE_String value)2625 search_string_list(const SANE_String_Const *list, SANE_String value)
2626 {
2627 	while (*list != NULL && strcmp(value, *list) != 0)
2628 		list++;
2629 
2630 	return ((*list == NULL) ? NULL : list);
2631 }
2632 
2633 /*
2634     Activate, deactivate an option. Subroutines so we can add
2635     debugging info if we want. The change flag is set to TRUE
2636     if we changed an option. If we did not change an option,
2637     then the value of the changed flag is not modified.
2638 */
2639 
2640 static void
activateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)2641 activateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)
2642 {
2643 	if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
2644 		s->opt[option].cap &= ~SANE_CAP_INACTIVE;
2645 		*change = SANE_TRUE;
2646 	}
2647 }
2648 
2649 static void
deactivateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)2650 deactivateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)
2651 {
2652 	if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
2653 		s->opt[option].cap |= SANE_CAP_INACTIVE;
2654 		*change = SANE_TRUE;
2655 	}
2656 }
2657 
2658 static SANE_Status
getvalue(SANE_Handle handle, SANE_Int option, void *value)2659 getvalue(SANE_Handle handle, SANE_Int option, void *value)
2660 {
2661 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2662 	SANE_Option_Descriptor *sopt = &(s->opt[option]);
2663 	Option_Value *sval = &(s->val[option]);
2664 
2665 	DBG(17, "%s: option = %d\n", __func__, option);
2666 
2667 	switch (option) {
2668 
2669 	case OPT_NUM_OPTS:
2670 	case OPT_BIT_DEPTH:
2671 	case OPT_BRIGHTNESS:
2672 	case OPT_RESOLUTION:
2673 	case OPT_PREVIEW:
2674 	case OPT_TL_X:
2675 	case OPT_TL_Y:
2676 	case OPT_BR_X:
2677 	case OPT_BR_Y:
2678 		*((SANE_Word *) value) = sval->w;
2679 		break;
2680 
2681 	case OPT_MODE:
2682 	case OPT_SOURCE:
2683 	case OPT_ADF_MODE:
2684 		strcpy((char *) value, sopt->constraint.string_list[sval->w]);
2685 		break;
2686 
2687 	default:
2688 		return SANE_STATUS_INVAL;
2689 	}
2690 
2691 	return SANE_STATUS_GOOD;
2692 }
2693 
2694 
2695 /*
2696  * Handles setting the source (flatbed, or auto document feeder (ADF)).
2697  *
2698  */
2699 
2700 static void
change_source(Magicolor_Scanner *s, SANE_Int optindex, char *value)2701 change_source(Magicolor_Scanner *s, SANE_Int optindex, char *value)
2702 {
2703 	int force_max = SANE_FALSE;
2704 	SANE_Bool dummy;
2705 
2706 	DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex,
2707 	    value);
2708 
2709 	if (s->val[OPT_SOURCE].w == optindex)
2710 		return;
2711 
2712 	s->val[OPT_SOURCE].w = optindex;
2713 
2714 	if (s->val[OPT_TL_X].w == s->hw->x_range->min
2715 	    && s->val[OPT_TL_Y].w == s->hw->y_range->min
2716 	    && s->val[OPT_BR_X].w == s->hw->x_range->max
2717 	    && s->val[OPT_BR_Y].w == s->hw->y_range->max) {
2718 		force_max = SANE_TRUE;
2719 	}
2720 
2721 	if (strcmp(ADF_STR, value) == 0) {
2722 		s->hw->x_range = &s->hw->cap->adf_x_range;
2723 		s->hw->y_range = &s->hw->cap->adf_y_range;
2724 		if (s->hw->cap->adf_duplex) {
2725 			activateOption(s, OPT_ADF_MODE, &dummy);
2726 		} else {
2727 			deactivateOption(s, OPT_ADF_MODE, &dummy);
2728 			s->val[OPT_ADF_MODE].w = 0;
2729 		}
2730 
2731 		DBG(1, "adf activated (%d)\n",s->hw->cap->adf_duplex);
2732 
2733 	} else {
2734 		/* ADF not active */
2735 		s->hw->x_range = &s->hw->cap->fbf_x_range;
2736 		s->hw->y_range = &s->hw->cap->fbf_y_range;
2737 
2738 		deactivateOption(s, OPT_ADF_MODE, &dummy);
2739 	}
2740 
2741 	s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
2742 	s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
2743 
2744 	if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max)
2745 		s->val[OPT_TL_X].w = s->hw->x_range->min;
2746 
2747 	if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max)
2748 		s->val[OPT_TL_Y].w = s->hw->y_range->min;
2749 
2750 	if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max)
2751 		s->val[OPT_BR_X].w = s->hw->x_range->max;
2752 
2753 	if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max)
2754 		s->val[OPT_BR_Y].w = s->hw->y_range->max;
2755 
2756 }
2757 
2758 static SANE_Status
setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)2759 setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
2760 {
2761 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2762 	SANE_Option_Descriptor *sopt = &(s->opt[option]);
2763 	Option_Value *sval = &(s->val[option]);
2764 
2765 	SANE_Status status;
2766 	const SANE_String_Const *optval = NULL;
2767 	int optindex = 0;
2768 	SANE_Bool reload = SANE_FALSE;
2769 
2770 	DBG(17, "%s: option = %d, value = %p, as word: %d\n", __func__, option, value, *(SANE_Word *) value);
2771 
2772 	status = sanei_constrain_value(sopt, value, info);
2773 	if (status != SANE_STATUS_GOOD)
2774 		return status;
2775 
2776 	if (info && value && (*info & SANE_INFO_INEXACT)
2777 	    && sopt->type == SANE_TYPE_INT)
2778 		DBG(17, "%s: constrained val = %d\n", __func__,
2779 		    *(SANE_Word *) value);
2780 
2781 	if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) {
2782 		optval = search_string_list(sopt->constraint.string_list,
2783 					    (char *) value);
2784 		if (optval == NULL)
2785 			return SANE_STATUS_INVAL;
2786 		optindex = optval - sopt->constraint.string_list;
2787 	}
2788 
2789 	switch (option) {
2790 
2791 	case OPT_MODE:
2792 	{
2793 		sval->w = optindex;
2794 		/* if binary, then disable the bit depth selection */
2795 		if (optindex == 0) {
2796 			s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2797 		} else {
2798 			if (s->hw->cap->depth_list[0] == 1)
2799 				s->opt[OPT_BIT_DEPTH].cap |=
2800 					SANE_CAP_INACTIVE;
2801 			else {
2802 				s->opt[OPT_BIT_DEPTH].cap &=
2803 					~SANE_CAP_INACTIVE;
2804 				s->val[OPT_BIT_DEPTH].w =
2805 					mode_params[optindex].depth;
2806 			}
2807 		}
2808 		reload = SANE_TRUE;
2809 		break;
2810 	}
2811 
2812 	case OPT_BIT_DEPTH:
2813 		sval->w = *((SANE_Word *) value);
2814 		mode_params[s->val[OPT_MODE].w].depth = sval->w;
2815 		reload = SANE_TRUE;
2816 		break;
2817 
2818 	case OPT_RESOLUTION:
2819 		sval->w = *((SANE_Word *) value);
2820 		DBG(17, "setting resolution to %d\n", sval->w);
2821 		reload = SANE_TRUE;
2822 		break;
2823 
2824 	case OPT_BR_X:
2825 	case OPT_BR_Y:
2826 		if (SANE_UNFIX(*((SANE_Word *) value)) == 0) {
2827 			DBG(17, "invalid br-x or br-y\n");
2828 			return SANE_STATUS_INVAL;
2829 		}
2830 		// fall through
2831 	case OPT_TL_X:
2832 	case OPT_TL_Y:
2833 		sval->w = *((SANE_Word *) value);
2834 		DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w));
2835 		if (NULL != info)
2836 			*info |= SANE_INFO_RELOAD_PARAMS;
2837 		break;
2838 
2839 	case OPT_SOURCE:
2840 		change_source(s, optindex, (char *) value);
2841 		reload = SANE_TRUE;
2842 		break;
2843 
2844 	case OPT_ADF_MODE:
2845 		sval->w = optindex;	/* Simple lists */
2846 		break;
2847 
2848 	case OPT_BRIGHTNESS:
2849 	case OPT_PREVIEW:	/* needed? */
2850 		sval->w = *((SANE_Word *) value);
2851 		break;
2852 
2853 	default:
2854 		return SANE_STATUS_INVAL;
2855 	}
2856 
2857 	if (reload && info != NULL)
2858 		*info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2859 
2860 	DBG(17, "%s: end\n", __func__);
2861 
2862 	return SANE_STATUS_GOOD;
2863 }
2864 
2865 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info)2866 sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
2867 		    void *value, SANE_Int *info)
2868 {
2869 	DBG(17, "%s: action = %x, option = %d\n", __func__, action, option);
2870 
2871 	if (option < 0 || option >= NUM_OPTIONS)
2872 		return SANE_STATUS_INVAL;
2873 
2874 	if (info != NULL)
2875 		*info = 0;
2876 
2877 	switch (action) {
2878 	case SANE_ACTION_GET_VALUE:
2879 		return getvalue(handle, option, value);
2880 
2881 	case SANE_ACTION_SET_VALUE:
2882 		return setvalue(handle, option, value, info);
2883 
2884 	default:
2885 		return SANE_STATUS_INVAL;
2886 	}
2887 
2888 	return SANE_STATUS_INVAL;
2889 }
2890 
2891 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)2892 sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
2893 {
2894 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2895 
2896 	DBG(5, "%s\n", __func__);
2897 
2898 	if (params == NULL)
2899 		DBG(1, "%s: params is NULL\n", __func__);
2900 
2901 	/*
2902 	 * If sane_start was already called, then just retrieve the parameters
2903 	 * from the scanner data structure
2904 	 */
2905 
2906 	if (!s->eof && s->ptr != NULL) {
2907 		DBG(5, "scan in progress, returning saved params structure\n");
2908 	} else {
2909 		/* otherwise initialize the params structure and gather the data */
2910 		mc_init_parameters(s);
2911 	}
2912 
2913 	if (params != NULL)
2914 		*params = s->params;
2915 
2916 	print_params(s->params);
2917 
2918 	return SANE_STATUS_GOOD;
2919 }
2920 
2921 /*
2922  * This function is part of the SANE API and gets called from the front end to
2923  * start the scan process.
2924  */
2925 
2926 SANE_Status
sane_start(SANE_Handle handle)2927 sane_start(SANE_Handle handle)
2928 {
2929 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2930 	SANE_Status status;
2931 
2932 	DBG(5, "%s\n", __func__);
2933 
2934 	/* calc scanning parameters */
2935 	status = mc_init_parameters(s);
2936 	if (status != SANE_STATUS_GOOD)
2937 		return status;
2938 
2939 	print_params(s->params);
2940 
2941 	/* set scanning parameters; also query the current image
2942 	 * parameters from the sanner and save
2943 	 * them to s->params */
2944 	status = mc_set_scanning_parameters(s);
2945 
2946 	if (status != SANE_STATUS_GOOD)
2947 		return status;
2948 
2949 	/* if we scan from ADF, check if it is loaded */
2950 	if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
2951 		status = mc_check_adf(s);
2952 		if (status != SANE_STATUS_GOOD)
2953 			return status;
2954 	}
2955 
2956 	/* prepare buffer here so that a memory allocation failure
2957 	 * will leave the scanner in a sane state.
2958 	 */
2959 	s->buf = realloc(s->buf, s->block_len);
2960 	if (s->buf == NULL)
2961 		return SANE_STATUS_NO_MEM;
2962 
2963 	s->eof = SANE_FALSE;
2964 	s->ptr = s->end = s->buf;
2965 	s->canceling = SANE_FALSE;
2966 
2967 	/* start scanning */
2968 	DBG(1, "%s: scanning...\n", __func__);
2969 
2970 	status = mc_start_scan(s);
2971 
2972 	if (status != SANE_STATUS_GOOD) {
2973 		DBG(1, "%s: start failed: %s\n", __func__,
2974 		    sane_strstatus(status));
2975 
2976 		return status;
2977 	}
2978 
2979 	return status;
2980 }
2981 
2982 /* this moves data from our buffers to SANE */
2983 
2984 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length)2985 sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
2986 	  SANE_Int *length)
2987 {
2988 	SANE_Status status;
2989 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2990 
2991 	if (s->buf == NULL || s->canceling)
2992 		return SANE_STATUS_CANCELLED;
2993 
2994 	*length = 0;
2995 
2996 	status = mc_read(s);
2997 
2998 	if (status == SANE_STATUS_CANCELLED) {
2999 		mc_scan_finish(s);
3000 		return status;
3001 	}
3002 
3003 	DBG(18, "moving data %p %p, %d (%d lines)\n",
3004 		(void *) s->ptr, (void *) s->end,
3005 		max_length, max_length / s->params.bytes_per_line);
3006 
3007 	mc_copy_image_data(s, data, max_length, length);
3008 
3009 	DBG(18, "%d lines read, status: %d\n",
3010 		*length / s->params.bytes_per_line, status);
3011 
3012 	/* continue reading if appropriate */
3013 	if (status == SANE_STATUS_GOOD)
3014 		return status;
3015 
3016 	mc_scan_finish(s);
3017 
3018 	return status;
3019 }
3020 
3021 /*
3022  * void sane_cancel(SANE_Handle handle)
3023  *
3024  * Set the cancel flag to true. The next time the backend requests data
3025  * from the scanner the CAN message will be sent.
3026  */
3027 
3028 void
sane_cancel(SANE_Handle handle)3029 sane_cancel(SANE_Handle handle)
3030 {
3031 	Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
3032 
3033 	s->canceling = SANE_TRUE;
3034 }
3035 
3036 /*
3037  * SANE_Status sane_set_io_mode()
3038  *
3039  * not supported - for asynchronous I/O
3040  */
3041 
3042 SANE_Status
sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking)3043 sane_set_io_mode(SANE_Handle __sane_unused__ handle,
3044 	SANE_Bool __sane_unused__ non_blocking)
3045 {
3046 	return SANE_STATUS_UNSUPPORTED;
3047 }
3048 
3049 /*
3050  * SANE_Status sane_get_select_fd()
3051  *
3052  * not supported - for asynchronous I/O
3053  */
3054 
3055 SANE_Status
sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd)3056 sane_get_select_fd(SANE_Handle __sane_unused__ handle,
3057 	SANE_Int __sane_unused__ *fd)
3058 {
3059 	return SANE_STATUS_UNSUPPORTED;
3060 }
3061