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 (¶m[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