2
* magicolor.c - SANE library for Magicolor scanners.
4
* (C) 2010 Reinhold Kainhofer <reinhold@kainhofer.com>
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>
13
* This file is part of the SANE package.
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.
20
#define MAGICOLOR_VERSION 0
21
#define MAGICOLOR_REVISION 0
22
#define MAGICOLOR_BUILD 1
28
* 35 fine-grained status and progress
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
37
* 3 status info and progress
38
* 2 scanner info and capabilities
42
#include "sane/config.h"
58
#include <net-snmp/net-snmp-config.h>
59
#include <net-snmp/net-snmp-includes.h>
60
#include <net-snmp/library/snmp_transport.h>
61
#include <arpa/inet.h>
64
#include "../include/sane/saneopts.h"
65
#include "../include/sane/sanei_usb.h"
66
#include "../include/sane/sanei_tcp.h"
67
#include "../include/sane/sanei_udp.h"
68
#include "../include/sane/sanei_config.h"
69
#include "../include/sane/sanei_backend.h"
71
#include "magicolor.h"
74
#define min(x,y) (((x)<(y))?(x):(y))
78
/****************************************************************************
79
* Devices supported by this backend
80
****************************************************************************/
84
/* Scanner command type
88
* | | | | Query image parameters
89
* | | | | | set scan parameters
90
* | | | | | | Get status?
91
* | | | | | | | Read scanned data
92
* | | | | | | | | Unknown
93
* | | | | | | | | | Unknown
94
* | | | | | | | | | | Net wrapper command type
95
* | | | | | | | | | | | Net Welcome
96
* | | | | | | | | | | | | Net Lock
97
* | | | | | | | | | | | | | Net Lock ACK
98
* | | | | | | | | | | | | | | Net Unlock
99
* | | | | | | | | | | | | | | |
101
static struct MagicolorCmd magicolor_cmd[] = {
102
{"mc1690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}
105
static SANE_Int magicolor_default_resolutions[] = {150, 300, 600};
106
static SANE_Int magicolor_default_depths[] = {1,8};
108
static struct MagicolorCap magicolor_cap[] = {
110
/* KONICA MINOLTA magicolor 1690MF, USB ID 0x123b:2089 */
112
0x2089, "mc1690mf", "KONICA MINOLTA magicolor 1690MF", "1.3.6.1.4.1.183341.1.1.2.1.32.3.2",
114
600, {150, 600, 0}, magicolor_default_resolutions, 3, /* 600 dpi max, 3 resolutions */
115
8, magicolor_default_depths, /* color depth 8 default, 1 and 8 possible */
116
{1, 9, 0}, /* brightness ranges (TODO!) */
117
{0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, /* FBF x/y ranges (TODO!) */
118
SANE_TRUE, SANE_FALSE, /* non-duplex ADF, x/y ranges (TODO!) */
119
{0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0},
124
static int MC_SNMP_Timeout = 2500;
125
static int MC_Scan_Data_Timeout = 15000;
126
static int MC_Request_Timeout = 5000;
130
/****************************************************************************
131
* General configuration parameter definitions
132
****************************************************************************/
136
* Definition of the mode_param struct, that is used to
137
* specify the valid parameters for the different scan modes.
139
* The depth variable gets updated when the bit depth is modified.
142
static struct mode_param mode_params[] = {
143
{0x00, 1, 1}, /* Lineart, 1 color, 1 bit */
144
{0x02, 1, 24}, /* Grayscale, 1 color, 24 bit */
145
{0x03, 3, 24} /* Color, 3 colors, 24 bit */
148
static SANE_String_Const mode_list[] = {
149
SANE_VALUE_SCAN_MODE_LINEART,
150
SANE_VALUE_SCAN_MODE_GRAY,
151
SANE_VALUE_SCAN_MODE_COLOR,
155
static const SANE_String_Const adf_mode_list[] = {
156
SANE_I18N("Simplex"),
161
/* Define the different scan sources */
163
#define FBF_STR SANE_I18N("Flatbed")
164
#define ADF_STR SANE_I18N("Automatic Document Feeder")
167
* source list need one dummy entry (save device settings is crashing).
168
* NOTE: no const - this list gets created while exploring the capabilities
172
static SANE_String_Const source_list[] = {
179
/* Some utility functions */
182
max_string_size(const SANE_String_Const strings[])
184
size_t size, max_size = 0;
187
for (i = 0; strings[i]; i++) {
188
size = strlen(strings[i]) + 1;
195
static SANE_Status attach_one_usb(SANE_String_Const devname);
196
static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device);
199
print_params(const SANE_Parameters params)
201
DBG(6, "params.format = %d\n", params.format);
202
DBG(6, "params.last_frame = %d\n", params.last_frame);
203
DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line);
204
DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line);
205
DBG(6, "params.lines = %d\n", params.lines);
206
DBG(6, "params.depth = %d\n", params.depth);
211
/****************************************************************************
212
* Low-level Network communication functions
213
****************************************************************************/
216
#define MAGICOLOR_SNMP_SYSDESCR_OID ".1.3.6.1.2.1.1.1.0"
217
#define MAGICOLOR_SNMP_SYSOBJECT_OID ".1.3.6.1.2.1.1.2.0"
218
#define MAGICOLOR_SNMP_MAC_OID ".1.3.6.1.2.1.2.2.1.6.1"
219
#define MAGICOLOR_SNMP_DEVICE_TREE ".1.3.6.1.4.1.18334.1.1.1.1.1"
222
/* We don't have a packet wrapper, which holds packet size etc., so we
223
don't have to use a *read_raw and a *_read function... */
225
sanei_magicolor_net_read(struct Magicolor_Scanner *s, unsigned char *buf, size_t wanted,
226
SANE_Status * status)
228
size_t size, read = 0;
229
struct pollfd fds[1];
231
*status = SANE_STATUS_GOOD;
233
/* poll for data-to-be-read (using a 5 seconds timeout) */
235
fds[0].events = POLLIN;
236
if (poll (fds, 1, MC_Request_Timeout) <= 0) {
237
*status = SANE_STATUS_IO_ERROR;
241
while (read < wanted) {
242
size = sanei_tcp_read(s->fd, buf + read, wanted - read);
251
*status = SANE_STATUS_IO_ERROR;
256
/* We need to optionally pad the buffer with 0x00 to send 64-byte chunks.
257
On the other hand, the 0x04 commands don't need this, so we need two
258
functions, one *_write function that pads the buffer and then calls
261
sanei_magicolor_net_write_raw(struct Magicolor_Scanner *s,
262
const unsigned char *buf, size_t buf_size,
265
sanei_tcp_write(s->fd, buf, buf_size);
266
/* TODO: Check whether sending failed... */
268
*status = SANE_STATUS_GOOD;
273
sanei_magicolor_net_write(struct Magicolor_Scanner *s,
274
const unsigned char *buf, size_t buf_size,
278
unsigned char *new_buf = malloc(len);
280
*status = SANE_STATUS_NO_MEM;
283
memset(new_buf, 0x00, len);
287
memcpy(new_buf, buf, buf_size);
288
return sanei_magicolor_net_write_raw (s, new_buf, len, status);
292
sanei_magicolor_net_open(struct Magicolor_Scanner *s)
295
unsigned char buf[5];
299
struct MagicolorCmd *cmd = s->hw->cmd;
304
setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
306
DBG(1, "%s\n", __func__);
308
/* the scanner sends a kind of welcome msg */
309
read = sanei_magicolor_net_read(s, buf, 3, &status);
311
return SANE_STATUS_IO_ERROR;
312
if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_welcome) {
313
DBG (32, "Invalid welcome message received, Expected 0x%02x %02x 00, but got 0x%02x %02x %02x\n",
314
cmd->net_wrapper_cmd, cmd->net_welcome, buf[0], buf[1], buf[2]);
315
return SANE_STATUS_IO_ERROR;
316
} else if (buf[2] != 0x00) {
317
/* TODO: Handle response "04 00 01", indicating an error! */
318
DBG (32, "Welcome message received, busy status %02x\n", buf[2]);
319
/* TODO: Return a human-readable error message (Unable to connect to scanner, scanner is not ready) */
320
return SANE_STATUS_DEVICE_BUSY;
323
buf[0] = cmd->net_wrapper_cmd;
324
buf[1] = cmd->net_lock;
326
/* Copy the device's USB id to bytes 3-4: */
327
buf[3] = s->hw->cap->id & 0xff;
328
buf[4] = (s->hw->cap->id >> 8) & 0xff;
330
DBG(32, "Proper welcome message received, locking the scanner...\n");
331
sanei_magicolor_net_write_raw(s, buf, 5, &status);
333
read = sanei_magicolor_net_read(s, buf, 3, &status);
335
return SANE_STATUS_IO_ERROR;
336
if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_lock_ack || buf[2] != 0x00) {
337
DBG (32, "Welcome message received, Expected 0x%x %x 00, but got 0x%x %x %x\n",
338
cmd->net_wrapper_cmd, cmd->net_lock_ack, buf[0], buf[1], buf[2]);
339
return SANE_STATUS_IO_ERROR;
342
DBG(32, "scanner locked\n");
348
sanei_magicolor_net_close(struct Magicolor_Scanner *s)
351
struct MagicolorCmd *cmd = s->hw->cmd;
352
unsigned char buf[3];
354
DBG(1, "%s\n", __func__);
355
buf[0] = cmd->net_wrapper_cmd;
356
buf[1] = cmd->net_unlock;
358
sanei_magicolor_net_write_raw(s, buf, 3, &status);
364
/****************************************************************************
365
* Low-level USB communication functions
366
****************************************************************************/
368
#define SANE_MAGICOLOR_VENDOR_ID (0x132b)
370
SANE_Word sanei_magicolor_usb_product_ids[] = {
371
0x2089, /* magicolor 1690MF */
372
0 /* last entry - this is used for devices that are specified
373
in the config file as "usb <vendor> <product>" */
377
sanei_magicolor_getNumberOfUSBProductIds (void)
379
return sizeof (sanei_magicolor_usb_product_ids) / sizeof (SANE_Word);
385
/****************************************************************************
386
* Magicolor low-level communication commands
387
****************************************************************************/
389
static void dump_hex_buffer_dense (int level, const unsigned char *buf, size_t buf_size)
392
char msg[1024], fmt_buf[1024];
393
memset (&msg[0], 0x00, 1024);
394
memset (&fmt_buf[0], 0x00, 1024);
395
for (k = 0; k < min(buf_size, 80); k++) {
398
DBG (level, "%s\n", msg);
399
memset (&msg[0], 0x00, 1024);
401
sprintf (fmt_buf, " 0x%04lx ", (unsigned long)k);
402
strcat (msg, fmt_buf);
407
sprintf (fmt_buf, " %02x" , buf[k]);
408
strcat (msg, fmt_buf);
411
DBG (level, "%s\n", msg);
415
/* Create buffers containing the command and arguments. Length of reserved
416
* buffer is returned. It's the caller's job to free the buffer! */
417
static int mc_create_buffer (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd,
418
unsigned char **buf, unsigned char* arg1, size_t len1,
421
unsigned char* b = NULL;
422
size_t buf_len = 2+4+len1+4;
425
buf_len = 6; /* no args, just cmd + final 0x00 00 00 00 */
426
*buf = b = malloc (buf_len);
427
memset (b, 0x00, buf_len);
429
*status = SANE_STATUS_NO_MEM;
436
b[3] = (len1 >> 8) & 0xff;
437
b[4] = (len1 >> 16) & 0xff;
438
b[5] = (len1 >> 24) & 0xff;
440
memcpy(b+6, arg1, len1);
442
/* Writing the final 0x00 00 00 00 is not necessary, they are 0x00 already */
443
*status = SANE_STATUS_GOOD;
447
static int mc_create_buffer2 (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd,
448
unsigned char **buf, unsigned char* arg1, size_t len1,
449
unsigned char* arg2, size_t len2, SANE_Status *status)
451
unsigned char* b = NULL;
452
size_t buf_len = 2+4+len1+4+len2+4;
453
/* If any of the two args has size 0, use the simpler mc_create_buffer */
455
return mc_create_buffer (s, cmd_type, cmd, buf, arg2, len2, status);
457
return mc_create_buffer (s, cmd_type, cmd, buf, arg1, len1, status);
458
/* Allocate memory and copy over args and their lengths */
459
*buf = b = malloc (buf_len);
461
*status = SANE_STATUS_NO_MEM;
464
memset (b, 0x00, buf_len);
467
/* copy over the argument length in lower endian */
469
b[3] = (len1 >> 8) & 0xff;
470
b[4] = (len1 >> 16) & 0xff;
471
b[5] = (len1 >> 24) & 0xff;
473
/* Copy the arguments */
474
memcpy(b+6, arg1, len1);
476
/* copy over the second argument length in little endian */
477
b[6+len1] = len2 & 0xff;
478
b[7+len1] = (len2 >> 8) & 0xff;
479
b[8+len1] = (len2 >> 16) & 0xff;
480
b[9+len1] = (len2 >> 24) & 0xff;
482
memcpy(b+10+len1, arg2, len2);
484
*status = SANE_STATUS_GOOD;
489
mc_send(Magicolor_Scanner * s, void *buf, size_t buf_size, SANE_Status * status)
491
DBG(15, "%s: size = %lu\n", __func__, (u_long) buf_size);
493
if (DBG_LEVEL >= 125) {
494
const unsigned char *s = buf;
495
DBG(125, "Cmd: 0x%02x %02x, complete buffer:\n", s[0], s[1]);
496
dump_hex_buffer_dense (125, s, buf_size);
499
if (s->hw->connection == SANE_MAGICOLOR_NET) {
500
return sanei_magicolor_net_write(s, buf, buf_size, status);
501
} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
504
*status = sanei_usb_write_bulk(s->fd, buf, &n);
505
DBG(125, "USB: wrote %lu bytes, status: %s\n", (unsigned long)n, sane_strstatus(*status));
509
*status = SANE_STATUS_INVAL;
515
mc_recv(Magicolor_Scanner * s, void *buf, ssize_t buf_size,
516
SANE_Status * status)
520
DBG(15, "%s: size = %ld, buf = %p\n", __func__, (long) buf_size, buf);
522
if (s->hw->connection == SANE_MAGICOLOR_NET) {
523
n = sanei_magicolor_net_read(s, buf, buf_size, status);
524
} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
525
/* !!! only report an error if we don't read anything */
526
n = buf_size; /* buf_size gets overwritten */
528
sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf,
532
*status = SANE_STATUS_GOOD;
536
DBG(1, "%s: expected = %lu, got = %ld\n", __func__,
537
(u_long) buf_size, (long) n);
538
*status = SANE_STATUS_IO_ERROR;
541
/* dump buffer if appropriate */
542
if (DBG_LEVEL >= 127 && n > 0) {
543
const unsigned char* b=buf;
544
dump_hex_buffer_dense (125, b, buf_size);
550
/* Simple function to exchange a fixed amount of
551
* data with the scanner
554
mc_txrx(Magicolor_Scanner * s, unsigned char *txbuf, size_t txlen,
555
unsigned char *rxbuf, size_t rxlen)
559
mc_send(s, txbuf, txlen, &status);
560
if (status != SANE_STATUS_GOOD) {
561
DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
565
mc_recv(s, rxbuf, rxlen, &status);
566
if (status != SANE_STATUS_GOOD) {
567
DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
577
/****************************************************************************
578
* Magicolor high-level communication commands
579
****************************************************************************/
582
/** 0x03 09 01 - Request last error
583
* <- Information block (0x00 for OK, 0x01 for ERROR)
586
cmd_request_error (SANE_Handle handle)
588
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
590
unsigned char params[1];
594
DBG(8, "%s\n", __func__);
596
if (s->hw->cmd->request_status == 0)
597
return SANE_STATUS_UNSUPPORTED;
599
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_error,
600
&buf, NULL, 1, &status);
602
return SANE_STATUS_NO_MEM;
603
} else if (status != SANE_STATUS_GOOD) {
607
status = mc_txrx (s, buf, buflen, params, 1);
609
if (status != SANE_STATUS_GOOD)
612
DBG(1, "status: %02x\n", params[0]);
619
DBG(1, " paper jam in ADF\n");
620
return SANE_STATUS_JAMMED;
623
DBG(1, " printer door open or waiting for button press\n");
624
return SANE_STATUS_COVER_OPEN;
626
case STATUS_NOT_READY:
627
DBG(1, " scanner not ready (in use on another interface or warming up)\n");
628
return SANE_STATUS_DEVICE_BUSY;
631
DBG(1, " unknown status 0x%x\n", params[0]);
636
/** 0x03 0d - Request status command */
638
cmd_request_status(SANE_Handle handle, unsigned char *b)
640
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
645
DBG(8, "%s\n", __func__);
647
DBG(1, "%s called with NULL buffer\n", __func__);
648
return SANE_STATUS_INVAL;
650
memset (b, 0x00, 0x0b); /* initialize all 0x0b bytes with 0 */
651
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_status,
652
&buf, NULL, 0x0b, &status);
654
return SANE_STATUS_NO_MEM;
655
} else if (status != SANE_STATUS_GOOD) {
659
status = mc_txrx (s, buf, buflen, b, 0x0b);
661
if (status != SANE_STATUS_GOOD)
662
DBG(8, "%s: Status NOT successfully retrieved\n", __func__);
664
DBG(8, "%s: Status successfully retrieved:\n", __func__);
665
/* TODO: debug output of the returned parameters... */
666
DBG (11, " ADF status: 0x%02x", b[1]);
667
if (b[1] & ADF_LOADED) {
668
DBG (11, " loaded\n");
670
DBG (11, " not loaded\n");
677
/** 0x03 08 - Start scan command */
679
cmd_start_scan (SANE_Handle handle, size_t value)
681
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
683
unsigned char params1[4], params2[1];
687
DBG(8, "%s\n", __func__);
688
/* Copy params to buffers */
689
/* arg1 is expected returned bytes per line, 4-byte little endian */
690
/* arg2 is unknown, seems to be always 0x00 */
691
params1[0] = value & 0xff;
692
params1[1] = (value >> 8) & 0xff;
693
params1[2] = (value >> 16) & 0xff;
694
params1[3] = (value >> 24) & 0xff;
697
buflen = mc_create_buffer2 (s, s->hw->cmd->scanner_cmd, s->hw->cmd->start_scanning,
698
&buf, params1, 4, params2, 1, &status);
700
return SANE_STATUS_NO_MEM;
701
} else if (status != SANE_STATUS_GOOD) {
705
mc_send(s, buf, buflen, &status);
707
if (status != SANE_STATUS_GOOD)
708
DBG(8, "%s: Data NOT successfully sent\n", __func__);
710
DBG(8, "%s: Data successfully sent\n", __func__);
714
/** 0x03 0a - Cancel(?) Scan command */
715
/* TODO: Does this command really mean CANCEL??? */
717
cmd_cancel_scan (SANE_Handle handle)
719
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
724
DBG(8, "%s\n", __func__);
725
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->stop_scanning,
726
&buf, NULL, 0, &status);
728
return SANE_STATUS_NO_MEM;
729
} else if (status != SANE_STATUS_GOOD) {
733
mc_send(s, buf, buflen, &status);
735
if (status != SANE_STATUS_GOOD)
736
DBG(8, "%s: Data NOT successfully sent\n", __func__);
738
DBG(8, "%s: Data successfully sent\n", __func__);
742
/** 0x03 12 - Finish(?) scan command */
743
/* TODO: Does this command really mean FINISH??? */
745
cmd_finish_scan (SANE_Handle handle)
747
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
749
unsigned char *buf, returned[0x0b];
752
DBG(8, "%s\n", __func__);
753
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown2,
754
&buf, NULL, 0x0b, &status);
756
return SANE_STATUS_NO_MEM;
757
} else if (status != SANE_STATUS_GOOD) {
760
memset (&returned[0], 0x00, 0x0b);
762
status = mc_txrx (s, buf, buflen, returned, 0x0b);
764
if (status != SANE_STATUS_GOOD)
765
DBG(8, "%s: Data NOT successfully sent\n", __func__);
767
DBG(8, "%s: Data successfully sent\n", __func__);
771
/** 0x03 0b - Get scanning parameters command
772
* input buffer seems to be 0x00 always */
774
cmd_get_scanning_parameters(SANE_Handle handle,
775
SANE_Frame *format, SANE_Int *depth,
776
SANE_Int *data_pixels, SANE_Int *pixels_per_line,
779
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
781
unsigned char *txbuf, rxbuf[8];
786
DBG(8, "%s\n", __func__);
787
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd,
788
s->hw->cmd->request_scan_parameters,
789
&txbuf, NULL, 8, &status);
791
return SANE_STATUS_NO_MEM;
792
} else if (status != SANE_STATUS_GOOD) {
796
status = mc_txrx (s, txbuf, buflen, rxbuf, 8);
798
if (status != SANE_STATUS_GOOD)
799
DBG(8, "%s: Parameters NOT successfully retrieved\n", __func__);
801
DBG(8, "%s: Parameters successfully retrieved\n", __func__);
803
/* Assign px_per_line and lines. Bytes 7-8 must match 3-4 */
804
if (rxbuf[2]!=rxbuf[6] || rxbuf[3]!=rxbuf[7]) {
805
DBG (1, "%s: ERROR: Returned image parameters indicate an "
806
"unsupported device: Bytes 3-4 do not match "
807
"bytes 7-8! Trying to continue with bytes 3-4.\n",
809
dump_hex_buffer_dense (1, rxbuf, 8);
811
/* Read returned values, encoded in 2-byte little endian */
812
*data_pixels = rxbuf[1] * 0x100 + rxbuf[0];
813
*lines = rxbuf[3] * 0x100 + rxbuf[2];
814
*pixels_per_line = rxbuf[5] * 0x100 + rxbuf[4];
815
DBG (8, "%s: data_pixels = 0x%x (%u), lines = 0x%x (%u), "
816
"pixels_per_line = 0x%x (%u)\n", __func__,
817
*data_pixels, *data_pixels,
819
*pixels_per_line, *pixels_per_line);
825
/** 0x03 0c - Set scanning parameters command */
827
cmd_set_scanning_parameters(SANE_Handle handle,
828
unsigned char resolution, unsigned char color_mode,
829
unsigned char brightness, unsigned char contrast,
830
int tl_x, int tl_y, int width, int height, unsigned char source)
832
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
834
unsigned char param[0x11];
838
DBG(8, "%s\n", __func__);
839
/* Copy over the params to the param byte array */
848
* byte 10-11: y-extent
849
* byte 12: source (ADF/FBF)
851
memset (¶m[0], 0x00, 0x11);
852
param[0] = resolution;
853
param[1] = color_mode;
854
param[2] = brightness;
855
param[3] = contrast | 0xff; /* TODO: Always 0xff? What about contrast? */
856
/* Image coordinates are encoded 2-byte little endian: */
857
param[4] = tl_x & 0xff;
858
param[5] = (tl_x >> 8) & 0xff;
859
param[6] = tl_y & 0xff;
860
param[7] = (tl_y >> 8) & 0xff;
861
param[8] = width & 0xff;
862
param[9] = (width >> 8) & 0xff;
863
param[10] = height & 0xff;
864
param[11] = (height >> 8) & 0xff;
868
/* dump buffer if appropriate */
869
DBG (127, " Scanning parameter buffer:");
870
dump_hex_buffer_dense (127, param, 0x11);
872
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->set_scan_parameters,
873
&buf, param, 0x11, &status);
875
return SANE_STATUS_NO_MEM;
876
} else if (status != SANE_STATUS_GOOD) {
880
mc_send(s, buf, buflen, &status);
882
if (status != SANE_STATUS_GOOD)
883
DBG(8, "%s: Data NOT successfully sent\n", __func__);
885
DBG(8, "%s: Data successfully sent\n", __func__);
889
/** 0x03 ?? - Request push button status command */
892
cmd_request_push_button_status(SANE_Handle handle, unsigned char *bstatus)
894
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
899
DBG(8, "%s\n", __func__);
902
if (s->hw->cmd->unknown1 == 0)
903
return SANE_STATUS_UNSUPPORTED;
905
DBG(8, "%s: Supported\n", __func__);
906
memset (bstatus, 0x00, 1);
907
buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown1,
908
&buf, bstatus, 1, &status);
910
return SANE_STATUS_NO_MEM;
911
} else if (status != SANE_STATUS_GOOD) {
915
status = mc_txrx (s, buf, buflen, bstatus, 1);
917
if (status != SANE_STATUS_GOOD)
920
DBG(1, "push button status: %02x ", bstatus[0]);
921
switch (bstatus[0]) {
922
/* TODO: What's the response code for button pressed??? */
924
DBG(1, " unknown\n");
925
status = SANE_STATUS_UNSUPPORTED;
931
/** 0x03 0e - Read data command */
933
cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t len)
935
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
937
unsigned char *txbuf;
938
unsigned char param[4];
940
int oldtimeout = MC_Request_Timeout;
942
DBG(8, "%s\n", __func__);
943
param[0] = len & 0xff;
944
param[1] = (len >> 8) & 0xff;
945
param[2] = (len >> 16) & 0xff;
946
param[3] = (len >> 24) & 0xff;
948
txbuflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_data,
949
&txbuf, param, 4, &status);
950
if (txbuflen <= 0 ) {
951
return SANE_STATUS_NO_MEM;
952
} else if (status != SANE_STATUS_GOOD) {
956
/* Temporarily set the poll timeout to 10 seconds instead of 2,
957
* because a color scan needs >5 seconds to initialize. */
958
MC_Request_Timeout = MC_Scan_Data_Timeout;
959
status = mc_txrx (s, txbuf, txbuflen, buf, len);
960
MC_Request_Timeout = oldtimeout;
962
if (status != SANE_STATUS_GOOD)
963
DBG(8, "%s: Image data NOT successfully retrieved\n", __func__);
965
DBG(8, "%s: Image data successfully retrieved\n", __func__);
973
/* TODO: 0x03 0f command (unknown), 0x03 10 command (set button wait) */
978
/****************************************************************************
979
* Magicolor backend high-level operations
980
****************************************************************************/
984
mc_dev_init(Magicolor_Device *dev, const char *devname, int conntype)
986
DBG(5, "%s\n", __func__);
990
dev->connection = conntype;
991
dev->sane.name = devname;
992
dev->sane.model = NULL;
993
dev->sane.type = "flatbed scanner";
994
dev->sane.vendor = "Magicolor";
995
dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT];
996
dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT];
997
/* Change default level when using a network connection */
998
if (dev->connection == SANE_MAGICOLOR_NET)
999
dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_NET];
1003
mc_dev_post_init(struct Magicolor_Device *dev)
1005
DBG(5, "%s\n", __func__);
1007
/* Correct device parameters if needed */
1008
return SANE_STATUS_GOOD;
1012
mc_set_model(Magicolor_Scanner * s, const char *model, size_t len)
1016
struct Magicolor_Device *dev = s->hw;
1018
buf = malloc(len + 1);
1020
return SANE_STATUS_NO_MEM;
1022
memcpy(buf, model, len);
1035
dev->model = strndup((const char *) buf, len);
1036
dev->sane.model = dev->model;
1037
DBG(10, "%s: model is '%s'\n", __func__, dev->model);
1041
return SANE_STATUS_GOOD;
1045
mc_set_device (SANE_Handle handle, unsigned int device)
1047
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
1048
Magicolor_Device *dev = s->hw;
1049
const char* cmd_level;
1052
DBG(1, "%s: 0x%x\n", __func__, device);
1054
for (n = 0; n < NELEMS (magicolor_cap); n++) {
1055
if (magicolor_cap[n].id == device)
1058
if (n < NELEMS(magicolor_cap)) {
1059
dev->cap = &magicolor_cap[n];
1061
dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT];
1062
DBG(1, " unknown device 0x%x, using default %s\n",
1063
device, dev->cap->model);
1065
mc_set_model (s, dev->cap->model, strlen (dev->cap->model));
1067
cmd_level = dev->cap->cmds;
1068
/* set command type and level */
1069
for (n = 0; n < NELEMS(magicolor_cmd); n++) {
1070
if (!strcmp(cmd_level, magicolor_cmd[n].level))
1074
if (n < NELEMS(magicolor_cmd)) {
1075
dev->cmd = &magicolor_cmd[n];
1077
dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT];
1078
DBG(1, " unknown command level %s, using %s\n",
1079
cmd_level, dev->cmd->level);
1084
mc_discover_capabilities(Magicolor_Scanner *s)
1087
Magicolor_Device *dev = s->hw;
1089
SANE_String_Const *source_list_add = source_list;
1091
DBG(5, "%s\n", __func__);
1093
/* always add flatbed */
1094
*source_list_add++ = FBF_STR;
1095
/* TODO: How can I check for existence of an ADF??? */
1097
*source_list_add++ = ADF_STR;
1099
/* TODO: Is there any capability that we can extract from the
1100
* device by some scanne command? So far, it looks like
1101
* the device does not support any reporting. I don't even
1102
* see a way to determine which device we are talking to!
1106
/* request error status */
1107
status = cmd_request_error(s);
1108
if (status != SANE_STATUS_GOOD)
1111
dev->x_range = &dev->cap->fbf_x_range;
1112
dev->y_range = &dev->cap->fbf_y_range;
1114
DBG(5, " x-range: %f %f\n", SANE_UNFIX(dev->x_range->min), SANE_UNFIX(dev->x_range->max));
1115
DBG(5, " y-range: %f %f\n", SANE_UNFIX(dev->y_range->min), SANE_UNFIX(dev->y_range->max));
1117
DBG(5, "End of %s, status:%s\n", __func__, sane_strstatus(status));
1118
*source_list_add = NULL; /* add end marker to source list */
1123
mc_setup_block_mode (Magicolor_Scanner *s)
1125
/* block_len should always be a multiple of bytes_per_line, so
1126
* we retrieve only whole lines at once */
1127
s->block_len = (int)(0xff00/s->scan_bytes_per_line) * s->scan_bytes_per_line;
1128
s->blocks = s->data_len / s->block_len;
1129
s->last_len = s->data_len - (s->blocks * s->block_len);
1132
DBG(5, "%s: block_len=0x%x, last_len=0x%0x, blocks=%d\n", __func__, s->block_len, s->last_len, s->blocks);
1134
s->bytes_read_in_line = 0;
1136
free(s->line_buffer);
1137
s->line_buffer = malloc(s->scan_bytes_per_line);
1138
if (s->line_buffer == NULL) {
1139
DBG(1, "out of memory (line %d)\n", __LINE__);
1140
return SANE_STATUS_NO_MEM;
1144
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",
1145
__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);
1146
return SANE_STATUS_GOOD;
1149
/* Call the 0x03 0c command to set scanning parameters from the s->opt list */
1151
mc_set_scanning_parameters(Magicolor_Scanner * s)
1154
unsigned char rs, source, brightness;
1155
struct mode_param *mparam = &mode_params[s->val[OPT_MODE].w];
1156
SANE_Int scan_pixels_per_line = 0;
1158
DBG(1, "%s\n", __func__);
1160
/* Find the resolution in the res list and assign the index to buf[1] */
1161
for (rs=0; rs < s->hw->cap->res_list_size; rs++ ) {
1162
if ( s->val[OPT_RESOLUTION].w == s->hw->cap->res_list[rs] )
1166
if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BRIGHTNESS].cap)) {
1167
brightness = s->val[OPT_BRIGHTNESS].w;
1173
if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
1180
/* TODO: Any way to set PREVIEW??? */
1182
/* Remaining bytes unused */
1183
status = cmd_set_scanning_parameters(s,
1184
rs, mparam->flags, /* res, color mode */
1185
brightness, 0xff, /* brightness, contrast? */
1186
s->left, s->top, /* top/left start */
1187
s->width, s->height, /* extent */
1188
source); /* source */
1190
if (status != SANE_STATUS_GOOD)
1191
DBG (2, "%s: Command cmd_set_scanning_parameters failed, %s\n",
1192
__func__, sane_strstatus(status));
1194
/* Now query the scanner for the current image parameters */
1195
status = cmd_get_scanning_parameters (s,
1196
&s->params.format, &s->params.depth,
1197
&scan_pixels_per_line,
1198
&s->params.pixels_per_line, &s->params.lines);
1199
if (status != SANE_STATUS_GOOD) {
1200
DBG (2, "%s: Command cmd_get_scanning_parameters failed, %s\n",
1201
__func__, sane_strstatus(status));
1205
/* Calculate how many bytes are really used per line */
1206
s->params.bytes_per_line = ceil (s->params.pixels_per_line * s->params.depth / 8.0);
1207
if (s->val[OPT_MODE].w == MODE_COLOR)
1208
s->params.bytes_per_line *= 3;
1210
/* Calculate how many bytes per line will be returned by the scanner.
1211
* The values needed for this are returned by get_scannign_parameters */
1212
s->scan_bytes_per_line = ceil (scan_pixels_per_line * s->params.depth / 8.0);
1213
if (s->val[OPT_MODE].w == MODE_COLOR) {
1214
s->scan_bytes_per_line *= 3;
1216
s->data_len = s->params.lines * s->scan_bytes_per_line;
1218
status = mc_setup_block_mode (s);
1219
if (status != SANE_STATUS_GOOD)
1220
DBG (2, "%s: Command mc_setup_block_mode failed, %s\n",
1221
__func__, sane_strstatus(status));
1223
DBG (1, "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line);
1229
mc_check_adf(Magicolor_Scanner * s)
1232
unsigned char buf[0x0b];
1234
DBG(5, "%s\n", __func__);
1236
status = cmd_request_status(s, buf);
1237
if (status != SANE_STATUS_GOOD)
1240
if (!(buf[1] & ADF_LOADED))
1241
return SANE_STATUS_NO_DOCS;
1243
/* TODO: Check for jam in ADF */
1244
return SANE_STATUS_GOOD;
1248
mc_scan_finish(Magicolor_Scanner * s)
1251
DBG(5, "%s\n", __func__);
1253
/* If we have not yet read all data, cancel the scan */
1254
if (s->buf && !s->eof)
1255
status = cmd_cancel_scan (s);
1258
free (s->line_buffer);
1259
s->line_buffer = NULL;
1261
s->buf = s->end = s->ptr = NULL;
1263
/* TODO: Any magicolor command for "scan finished"? */
1264
status = cmd_finish_scan (s);
1266
status = cmd_request_error(s);
1267
if (status != SANE_STATUS_GOOD)
1268
cmd_cancel_scan (s);
1272
/* TODO: cmd_reset(s);*/
1273
return SANE_STATUS_GOOD;
1277
mc_copy_image_data(Magicolor_Scanner * s, SANE_Byte * data, SANE_Int max_length,
1280
DBG (1, "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line);
1281
if (s->params.format == SANE_FRAME_RGB) {
1282
SANE_Int bytes_available, scan_pixels_per_line = s->scan_bytes_per_line/3;
1285
while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) {
1286
SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line;
1287
/* First, fill the line buffer for the current line: */
1288
bytes_available = (s->end - s->ptr);
1289
/* Don't copy more than we have buffer and available */
1290
if (bytes_to_copy > bytes_available)
1291
bytes_to_copy = bytes_available;
1293
if (bytes_to_copy > 0) {
1294
memcpy (s->line_buffer + s->bytes_read_in_line, s->ptr, bytes_to_copy);
1295
s->ptr += bytes_to_copy;
1296
s->bytes_read_in_line += bytes_to_copy;
1299
/* We have filled as much as possible of the current line
1300
* with data from the scanner. If we have a complete line,
1302
if ((s->bytes_read_in_line >= s->scan_bytes_per_line) &&
1303
(s->params.bytes_per_line <= max_length))
1306
SANE_Byte *line = s->line_buffer;
1307
*length += s->params.bytes_per_line;
1308
for (i=0; i< s->params.pixels_per_line; ++i) {
1310
*data++ = line[scan_pixels_per_line];
1311
*data++ = line[2 * scan_pixels_per_line];
1314
max_length -= s->params.bytes_per_line;
1315
s->bytes_read_in_line -= s->scan_bytes_per_line;
1320
/* B/W and Grayscale use the same structure, so we use the same code */
1321
SANE_Int bytes_available;
1324
while ((max_length != 0) && (s->ptr < s->end)) {
1325
SANE_Int bytes_to_skip, bytes_to_copy;
1326
bytes_available = (s->end - s->ptr);
1327
bytes_to_copy = s->params.bytes_per_line - s->bytes_read_in_line;
1328
bytes_to_skip = s->scan_bytes_per_line - s->bytes_read_in_line;
1330
/* Don't copy more than we have buffer */
1331
if (bytes_to_copy > max_length) {
1332
bytes_to_copy = max_length;
1333
bytes_to_skip = max_length;
1336
/* Don't copy/skip more bytes than we have read in */
1337
if (bytes_to_copy > bytes_available)
1338
bytes_to_copy = bytes_available;
1339
if (bytes_to_skip > bytes_available)
1340
bytes_to_skip = bytes_available;
1342
if (bytes_to_copy > 0) {
1343
/* we have not yet copied all pixels of the line */
1344
memcpy (data, s->ptr, bytes_to_copy);
1345
max_length -= bytes_to_copy;
1346
*length += bytes_to_copy;
1347
data += bytes_to_copy;
1349
if (bytes_to_skip > 0) {
1350
s->ptr += bytes_to_skip;
1351
s->bytes_read_in_line += bytes_to_skip;
1353
if (s->bytes_read_in_line >= s->scan_bytes_per_line)
1354
s->bytes_read_in_line -= s->scan_bytes_per_line;
1361
mc_init_parameters(Magicolor_Scanner * s)
1364
struct mode_param *mparam;
1366
DBG(5, "%s\n", __func__);
1368
memset(&s->params, 0, sizeof(SANE_Parameters));
1370
dpi = s->val[OPT_RESOLUTION].w;
1371
optres = s->hw->cap->optical_res;
1373
mparam = &mode_params[s->val[OPT_MODE].w];
1375
if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 ||
1376
SANE_UNFIX(s->val[OPT_BR_X].w) == 0)
1377
return SANE_STATUS_INVAL;
1379
/* TODO: Use OPT_RESOLUTION or fixed 600dpi for left/top/width/height? */
1380
s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5;
1382
s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5;
1385
((SANE_UNFIX(s->val[OPT_BR_X].w -
1386
s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5;
1389
((SANE_UNFIX(s->val[OPT_BR_Y].w -
1390
s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5;
1392
s->params.pixels_per_line = s->width * dpi / optres + 0.5;
1393
s->params.lines = s->height * dpi / optres + 0.5;
1396
DBG(1, "%s: resolution = %d, preview = %d\n",
1397
__func__, dpi, s->val[OPT_PREVIEW].w);
1399
DBG(1, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n",
1400
__func__, (void *) s, (void *) s->val,
1401
SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w),
1402
SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w));
1405
* The default color depth is stored in mode_params.depth:
1407
DBG(1, " %s, vor depth\n", __func__);
1409
if (mode_params[s->val[OPT_MODE].w].depth == 1)
1410
s->params.depth = 1;
1412
s->params.depth = s->val[OPT_BIT_DEPTH].w;
1414
s->params.last_frame = SANE_TRUE;
1416
s->params.bytes_per_line = ceil (s->params.depth * s->params.pixels_per_line / 8.0);
1418
switch (s->val[OPT_MODE].w) {
1421
s->params.format = SANE_FRAME_GRAY;
1424
s->params.format = SANE_FRAME_RGB;
1425
s->params.bytes_per_line *= 3;
1430
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);
1431
return (s->params.lines > 0) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL;
1435
mc_start_scan(Magicolor_Scanner * s)
1437
SANE_Status status = cmd_start_scan (s, s->data_len);
1438
if (status != SANE_STATUS_GOOD ) {
1439
DBG (1, "%s: starting the scan failed (%s)\n", __func__, sane_strstatus(status));
1445
mc_read(struct Magicolor_Scanner *s)
1447
SANE_Status status = SANE_STATUS_GOOD;
1448
ssize_t buf_len = 0;
1450
/* did we passed everything we read to sane? */
1451
if (s->ptr == s->end) {
1454
return SANE_STATUS_EOF;
1457
buf_len = s->block_len;
1459
if (s->counter == s->blocks && s->last_len)
1460
buf_len = s->last_len;
1462
DBG(18, "%s: block %d/%d, size %lu\n", __func__,
1463
s->counter, s->blocks,
1464
(unsigned long) buf_len);
1466
/* receive image data + error code */
1467
status = cmd_read_data (s, s->buf, buf_len);
1468
if (status != SANE_STATUS_GOOD) {
1469
DBG (1, "%s: Receiving image data failed (%s)\n",
1470
__func__, sane_strstatus(status));
1475
DBG(18, "%s: successfully read %lu bytes\n", __func__, (unsigned long) buf_len);
1477
if (s->counter < s->blocks) {
1480
return SANE_STATUS_CANCELLED;
1485
s->end = s->buf + buf_len;
1495
/****************************************************************************
1496
* SANE API implementation (high-level functions)
1497
****************************************************************************/
1500
static struct MagicolorCap *
1501
mc_get_device_from_identification (const char*ident)
1504
for (n = 0; n < NELEMS (magicolor_cap); n++) {
1505
if (strcmp (magicolor_cap[n].model, ident) || strcmp (magicolor_cap[n].OID, ident))
1506
return &magicolor_cap[n];
1515
* Close the open scanner. Depending on the connection method, a different
1516
* close function is called.
1519
close_scanner(Magicolor_Scanner *s)
1521
DBG(7, "%s: fd = %d\n", __func__, s->fd);
1527
if (s->hw->connection == SANE_MAGICOLOR_NET) {
1528
sanei_magicolor_net_close(s);
1529
sanei_tcp_close(s->fd);
1530
} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
1531
sanei_usb_close(s->fd);
1538
split_scanner_name (const char *name, char * IP, unsigned int *model)
1540
const char *device = name;
1543
/* cut off leading net: */
1544
if (strncmp(device, "net:", 4) == 0)
1545
device = &device[4];
1547
qm = strchr(device, '?');
1549
size_t len = qm-device;
1550
strncpy (IP, device, len);
1553
if (strncmp(qm, "model=", 6) == 0) {
1555
if (!sscanf(qm, "0x%x", model))
1556
sscanf(qm, "%x", model);
1559
strcpy (IP, device);
1567
* Open the scanner device. Depending on the connection method,
1568
* different open functions are called.
1572
open_scanner(Magicolor_Scanner *s)
1574
SANE_Status status = 0;
1576
DBG(7, "%s: %s\n", __func__, s->hw->sane.name);
1579
DBG(7, "scanner is already open: fd = %d\n", s->fd);
1580
return SANE_STATUS_GOOD; /* no need to open the scanner */
1583
if (s->hw->connection == SANE_MAGICOLOR_NET) {
1584
/* device name has the form net:ipaddr?model=... */
1586
unsigned int model = 0;
1587
if (!split_scanner_name (s->hw->sane.name, IP, &model))
1588
return SANE_STATUS_INVAL;
1589
status = sanei_tcp_open(IP, 4567, &s->fd);
1591
mc_set_device (s, model);
1592
if (status == SANE_STATUS_GOOD) {
1593
DBG(7, "awaiting welcome message\n");
1594
status = sanei_magicolor_net_open (s);
1597
} else if (s->hw->connection == SANE_MAGICOLOR_USB) {
1598
status = sanei_usb_open(s->hw->sane.name, &s->fd);
1599
if (s->hw->cap->out_ep>0)
1600
sanei_usb_set_endpoint (s->fd,
1601
USB_DIR_OUT | USB_ENDPOINT_TYPE_BULK, s->hw->cap->out_ep);
1602
if (s->hw->cap->in_ep>0)
1603
sanei_usb_set_endpoint (s->fd,
1604
USB_DIR_IN | USB_ENDPOINT_TYPE_BULK, s->hw->cap->in_ep);
1607
if (status == SANE_STATUS_ACCESS_DENIED) {
1608
DBG(1, "please check that you have permissions on the device.\n");
1609
DBG(1, "if this is a multi-function device with a printer,\n");
1610
DBG(1, "disable any conflicting driver (like usblp).\n");
1613
if (status != SANE_STATUS_GOOD)
1614
DBG(1, "%s open failed: %s\n", s->hw->sane.name,
1615
sane_strstatus(status));
1617
DBG(3, "scanner opened\n");
1623
detect_usb(struct Magicolor_Scanner *s)
1626
int vendor, product;
1630
/* if the sanei_usb_get_vendor_product call is not supported,
1631
* then we just ignore this and rely on the user to config
1632
* the correct device.
1635
status = sanei_usb_get_vendor_product(s->fd, &vendor, &product);
1636
if (status != SANE_STATUS_GOOD) {
1637
DBG(1, "the device cannot be verified - will continue\n");
1638
return SANE_STATUS_GOOD;
1641
/* check the vendor ID to see if we are dealing with an MAGICOLOR device */
1642
if (vendor != SANE_MAGICOLOR_VENDOR_ID) {
1643
/* this is not a supported vendor ID */
1644
DBG(1, "not an Magicolor device at %s (vendor id=0x%x)\n",
1645
s->hw->sane.name, vendor);
1646
return SANE_STATUS_INVAL;
1649
numIds = sanei_magicolor_getNumberOfUSBProductIds();
1650
is_valid = SANE_FALSE;
1653
/* check all known product IDs to verify that we know
1654
* about the device */
1655
while (i != numIds && !is_valid) {
1656
if (product == sanei_magicolor_usb_product_ids[i])
1657
is_valid = SANE_TRUE;
1661
if (is_valid == SANE_FALSE) {
1662
DBG(1, "the device at %s is not a supported (product id=0x%x)\n",
1663
s->hw->sane.name, product);
1664
return SANE_STATUS_INVAL;
1667
DBG(2, "found valid Magicolor scanner: 0x%x/0x%x (vendorID/productID)\n",
1670
return SANE_STATUS_GOOD;
1674
* used by attach* and sane_get_devices
1675
* a ptr to a single-linked list of Magicolor_Device structs
1676
* a ptr to a null term array of ptrs to SANE_Device structs
1678
static int num_devices; /* number of scanners attached to backend */
1679
static Magicolor_Device *first_dev; /* first MAGICOLOR scanner in list */
1680
static const SANE_Device **devlist = NULL;
1682
static struct Magicolor_Scanner *
1683
scanner_create(struct Magicolor_Device *dev, SANE_Status *status)
1685
struct Magicolor_Scanner *s;
1687
s = malloc(sizeof(struct Magicolor_Scanner));
1689
*status = SANE_STATUS_NO_MEM;
1693
memset(s, 0x00, sizeof(struct Magicolor_Scanner));
1701
static struct Magicolor_Scanner *
1702
device_detect(const char *name, int type, SANE_Status *status)
1704
struct Magicolor_Scanner *s;
1705
struct Magicolor_Device *dev;
1707
/* try to find the device in our list */
1708
for (dev = first_dev; dev; dev = dev->next) {
1709
if (strcmp(dev->sane.name, name) == 0) {
1711
DBG (10, "%s: Device %s already attached!\n", __func__,
1713
return scanner_create(dev, status);
1717
if (type == SANE_MAGICOLOR_NODEV) {
1718
*status = SANE_STATUS_INVAL;
1722
/* alloc and clear our device structure */
1723
dev = malloc(sizeof(*dev));
1725
*status = SANE_STATUS_NO_MEM;
1728
memset(dev, 0x00, sizeof(struct Magicolor_Device));
1730
s = scanner_create(dev, status);
1734
mc_dev_init(dev, name, type);
1736
*status = open_scanner(s);
1737
if (*status != SANE_STATUS_GOOD) {
1742
/* from now on, close_scanner() must be called */
1744
/* USB requires special care */
1745
if (dev->connection == SANE_MAGICOLOR_USB) {
1746
*status = detect_usb(s);
1749
if (*status != SANE_STATUS_GOOD)
1752
/* set name and model (if not already set) */
1753
if (dev->model == NULL)
1754
mc_set_model(s, "generic", 7);
1756
dev->name = strdup(name);
1757
dev->sane.name = dev->name;
1759
*status = mc_discover_capabilities(s);
1760
if (*status != SANE_STATUS_GOOD)
1763
if (source_list[0] == NULL || dev->cap->dpi_range.min == 0) {
1764
DBG(1, "something is wrong in the discovery process, aborting.\n");
1765
*status = SANE_STATUS_IO_ERROR;
1769
mc_dev_post_init(dev);
1771
/* add this scanner to the device list */
1774
dev->next = first_dev;
1786
/** Handle one SNMP response (whether received sync or async) and if describes
1787
* a magicolor device, attach it. Returns the number of attached devices (0
1790
mc_network_discovery_handle (struct snmp_pdu *pdu)
1792
netsnmp_variable_list *varlist = pdu->variables, *vp;
1793
oid anOID[MAX_OID_LEN];
1794
size_t anOID_len = MAX_OID_LEN;
1795
/* Device information variables */
1799
/* remote IP detection variables */
1800
netsnmp_indexed_addr_pair *responder = (netsnmp_indexed_addr_pair *) pdu->transport_data;
1801
struct sockaddr_in *remote = NULL;
1802
struct MagicolorCap *cap;
1804
DBG(5, "%s: Handling SNMP response \n", __func__);
1806
if (responder == NULL || pdu->transport_data_length != sizeof(netsnmp_indexed_addr_pair )) {
1807
DBG(1, "%s: Unable to extract IP address from SNMP response.\n",
1811
remote = (struct sockaddr_in *) &(responder->remote_addr);
1812
if (remote == NULL) {
1813
DBG(1, "%s: Unable to extract IP address from SNMP response.\n",
1817
snprintf(ip_addr, sizeof(ip_addr), "%s", inet_ntoa(remote->sin_addr));
1818
DBG(35, "%s: IP Address of responder is %s\n", __func__, ip_addr);
1820
/* System Object ID (Unique OID identifying model)
1821
* This determines whether we really have a magicolor device */
1822
anOID_len = MAX_OID_LEN;
1823
read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len);
1824
vp = find_varbind_in_list (varlist, anOID, anOID_len);
1826
size_t value_len = vp->val_len/sizeof(oid);
1827
if (vp->type != ASN_OBJECT_ID) {
1828
DBG (3, "%s: SystemObjectID does not return an OID, device is not a magicolor device\n", __func__);
1831
snprint_objid (device, sizeof(device), vp->val.objid, value_len);
1832
DBG (5, "%s: Device object ID is '%s'\n", __func__, device);
1834
anOID_len = MAX_OID_LEN;
1835
read_objid (MAGICOLOR_SNMP_DEVICE_TREE, anOID, &anOID_len);
1836
if (netsnmp_oid_is_subtree (anOID, anOID_len,
1837
vp->val.objid, value_len) == 0) {
1838
DBG (5, "%s: Device appears to be a magicolor device (OID=%s)\n", __func__, device);
1840
DBG (5, "%s: Device is not a Magicolor device\n", __func__);
1845
/* Retrieve sysDescr (i.e. model name) */
1846
anOID_len = MAX_OID_LEN;
1847
read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len);
1848
vp = find_varbind_in_list (varlist, anOID, anOID_len);
1850
memcpy(model,vp->val.string,vp->val_len);
1851
model[vp->val_len] = '\0';
1852
DBG (5, "%s: Found model: %s\n", __func__, model);
1855
DBG (1, "%s: Detected device '%s' on IP %s\n",
1856
__func__, model, ip_addr);
1858
vp = pdu->variables;
1859
/* TODO: attach the IP with attach_one_net(ip) */
1860
cap = mc_get_device_from_identification (device);
1862
DBG(1, "%s: Found autodiscovered device: %s (type 0x%x)\n", __func__, cap->model, cap->id);
1863
attach_one_net (ip_addr, cap->id);
1870
mc_network_discovery_cb (int operation, struct snmp_session *sp, int reqid,
1871
struct snmp_pdu *pdu, void *magic)
1875
DBG(5, "%s: Received broadcast response \n", __func__);
1877
if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
1878
int nr = mc_network_discovery_handle (pdu);
1879
int *m = (int*)magic;
1881
DBG(5, "%s: Added %d discovered host(s) for SNMP response.\n", __func__, nr);
1888
/* Use SNMP for automatic network discovery. If host is given, try to detect
1889
* that one host (using sync SNMP, otherwise send an SNMP broadcast (async).
1892
mc_network_discovery(const char*host)
1895
netsnmp_session session, *ss;
1897
oid anOID[MAX_OID_LEN];
1898
size_t anOID_len = MAX_OID_LEN;
1899
int nr = 0; /* Nr of added hosts */
1902
DBG(1, "%s: running network discovery \n", __func__);
1904
/* Win32: init winsock */
1906
init_snmp("sane-magicolor-backend");
1907
snmp_sess_init (&session);
1908
session.version = SNMP_VERSION_2c;
1909
session.community = "public";
1910
session.community_len = strlen (session.community);
1912
session.peername = host;
1914
/* Do a network discovery via a broadcast */
1915
session.peername = "255.255.255.255";
1916
session.flags |= SNMP_FLAGS_UDP_BROADCAST;
1917
session.callback = mc_network_discovery_cb;
1918
session.callback_magic = &nr;
1921
ss = snmp_open (&session); /* establish the session */
1923
snmp_sess_perror ("ack", &session);
1928
/* Create the PDU for the data for our request and add the three
1929
* desired OIDs to the PDU */
1930
pdu = snmp_pdu_create (SNMP_MSG_GET);
1932
/* SNMPv2-MIB::sysDescr.0 */
1933
anOID_len = MAX_OID_LEN;
1934
if (read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len)) {
1935
snmp_add_null_var (pdu, anOID, anOID_len);
1937
/* SNMPv2-MIB::sysObjectID.0 */
1938
anOID_len = MAX_OID_LEN;
1939
if (read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len)) {
1940
snmp_add_null_var (pdu, anOID, anOID_len);
1942
/* IF-MIB::ifPhysAddress.1 */
1943
anOID_len = MAX_OID_LEN;
1944
if (read_objid(MAGICOLOR_SNMP_MAC_OID, anOID, &anOID_len)) {
1945
snmp_add_null_var (pdu, anOID, anOID_len);
1947
/* TODO: Add more interesting OIDs, in particular vendor OIDs */
1949
/* Now send out the request and wait for responses for some time.
1950
* If we get a response, connect to that device (in the callback),
1951
* otherwise we probably don't have a magicolor device in the
1952
* LAN (or SNMP is turned off, in which case we have no way to detect
1955
DBG(100, "%s: Sending SNMP packet\n", __func__);
1957
/* sync request to given hostname, immediately read the reply */
1958
netsnmp_pdu *response = 0;
1959
int status = snmp_synch_response(ss, pdu, &response);
1960
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
1961
nr = mc_network_discovery_handle (response);
1964
snmp_free_pdu(response);
1968
/* No hostname, so do a broadcast */
1969
struct timeval nowtime, endtime; /* end time for SNMP scan */
1970
struct timeval timeout;
1973
if (!snmp_send(ss, pdu)) {
1975
DBG(100, "%s: Sending SNMP packet NOT successful\n", __func__);
1978
/* listen for responses for MC_AutoDetectionTimeout milliseconds: */
1979
/* First get the final timeout time */
1980
gettimeofday (&nowtime, NULL);
1981
timeout.tv_sec = MC_SNMP_Timeout / 1000;
1982
timeout.tv_usec = (MC_SNMP_Timeout % 1000) * 1000;
1983
timeradd (&nowtime, &timeout, &endtime);
1985
while (timercmp(&nowtime, &endtime, <)) {
1986
int fds = 0, block = 0;
1988
DBG(1, " loop=%d\n", i++);
1990
/* Use a 125ms timeout for select. If we get a response,
1991
* the loop will be entered earlier again, anyway */
1992
timeout.tv_usec = 125000;
1994
snmp_select_info (&fds, &fdset, &timeout, &block);
1995
fds = select (fds, &fdset, NULL, NULL, /*block?NULL:*/&timeout);
1996
if (fds) snmp_read(&fdset);
1997
else snmp_timeout();
1998
gettimeofday(&nowtime, NULL);
2005
DBG (5, "%s: Discovered %d host(s)\n", __func__, nr);
2009
DBG (1, "%s: net-snmp library not enabled, auto-detecting network scanners not supported.\n", __func__);
2016
attach(const char *name, int type)
2019
Magicolor_Scanner *s;
2021
DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type);
2023
s = device_detect(name, type, &status);
2033
attach_one_usb(const char *dev)
2035
DBG(7, "%s: dev = %s\n", __func__, dev);
2036
return attach(dev, SANE_MAGICOLOR_USB);
2040
attach_one_net(const char *dev, unsigned int model)
2044
DBG(7, "%s: dev = %s\n", __func__, dev);
2046
snprintf(name, 1024, "net:%s?model=0x%x", dev, model);
2048
snprintf(name, 1024, "net:%s", dev);
2051
return attach(name, SANE_MAGICOLOR_NET);
2055
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
2057
int vendor, product, timeout;
2059
int len = strlen(line);
2061
DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
2063
if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
2064
/* add the vendor and product IDs to the list of
2065
* known devices before we call the attach function */
2067
int numIds = sanei_magicolor_getNumberOfUSBProductIds();
2069
if (vendor != SANE_MAGICOLOR_VENDOR_ID)
2070
return SANE_STATUS_INVAL; /* this is not a KONICA MINOLTA device */
2072
sanei_magicolor_usb_product_ids[numIds - 1] = product;
2073
sanei_usb_attach_matching_devices(line, attach_one_usb);
2075
} else if (strncmp(line, "usb", 3) == 0 && len == 3) {
2078
numIds = sanei_magicolor_getNumberOfUSBProductIds();
2080
for (i = 0; i < numIds; i++) {
2081
sanei_usb_find_devices(SANE_MAGICOLOR_VENDOR_ID,
2082
sanei_magicolor_usb_product_ids[i], attach_one_usb);
2085
} else if (strncmp(line, "net", 3) == 0) {
2087
/* remove the "net" sub string */
2088
const char *name = sanei_config_skip_whitespace(line + 3);
2090
unsigned int model = 0;
2092
if (strncmp(name, "autodiscovery", 13) == 0) {
2093
DBG (50, "%s: Initiating network autodiscovervy via SNMP\n", __func__);
2094
mc_network_discovery(NULL);
2095
} else if (sscanf(name, "%s %x", IP, &model) == 2) {
2096
DBG(50, "%s: Using network device on IP %s, forcing model 0x%x\n", __func__, IP, model);
2097
attach_one_net(IP, model);
2099
/* use SNMP to detect the type. If not successful,
2100
* add the host with model type 0 */
2101
DBG(50, "%s: Using network device on IP %s, trying to autodetect model\n", __func__, IP);
2102
if (mc_network_discovery(name)==0) {
2103
DBG(1, "%s: Autodetecting device model failed, using default model\n", __func__);
2104
attach_one_net(name, 0);
2108
} else if (sscanf(line, "snmp-timeout %i\n", &timeout)) {
2109
/* Timeout for SNMP network discovery */
2110
DBG(50, "%s: SNMP timeout set to %d\n", __func__, timeout);
2111
MC_SNMP_Timeout = timeout;
2113
} else if (sscanf(line, "scan-data-timeout %i\n", &timeout)) {
2114
/* Timeout for scan data requests */
2115
DBG(50, "%s: Scan data timeout set to %d\n", __func__, timeout);
2116
MC_Scan_Data_Timeout = timeout;
2118
} else if (sscanf(line, "request-timeout %i\n", &timeout)) {
2119
/* Timeout for all other read requests */
2120
DBG(50, "%s: Request timeout set to %d\n", __func__, timeout);
2121
MC_Request_Timeout = timeout;
2124
/* TODO: Warning about unparsable line! */
2127
return SANE_STATUS_GOOD;
2133
Magicolor_Device *dev, *next;
2135
DBG(5, "%s\n", __func__);
2137
for (dev = first_dev; dev; dev = next) {
2151
sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
2154
DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__);
2156
DBG(1, "magicolor backend, version %i.%i.%i\n",
2157
MAGICOLOR_VERSION, MAGICOLOR_REVISION, MAGICOLOR_BUILD);
2159
if (version_code != NULL)
2160
*version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR,
2165
return SANE_STATUS_GOOD;
2168
/* Clean up the list of attached scanners. */
2172
DBG(5, "%s\n", __func__);
2177
sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only)
2179
Magicolor_Device *dev, *s, *prev=0;
2182
DBG(5, "%s\n", __func__);
2186
/* mark all existing scanners as missing, attach_one will remove mark */
2187
for (s = first_dev; s; s = s->next) {
2191
/* Read the config, mark each device as found, possibly add new devs */
2192
sanei_configure_attach(MAGICOLOR_CONFIG_FILE, NULL,
2195
/*delete missing scanners from list*/
2196
for (s = first_dev; s;) {
2198
DBG (5, "%s: missing scanner %s\n", __func__, s->name);
2200
/*splice s out of list by changing pointer in prev to next*/
2202
prev->next = s->next;
2207
/*remove s from head of list */
2208
first_dev = s->next;
2220
DBG (15, "%s: found %d scanner(s)\n", __func__, num_devices);
2221
for (s = first_dev; s; s=s->next) {
2222
DBG (15, "%s: found scanner %s\n", __func__, s->name);
2228
devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
2230
DBG(1, "out of memory (line %d)\n", __LINE__);
2231
return SANE_STATUS_NO_MEM;
2234
DBG(5, "%s - results:\n", __func__);
2236
for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) {
2237
DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model);
2238
devlist[i] = &dev->sane;
2244
*device_list = devlist;
2247
return SANE_STATUS_GOOD;
2251
init_options(Magicolor_Scanner *s)
2254
SANE_Word *res_list;
2256
for (i = 0; i < NUM_OPTIONS; i++) {
2257
s->opt[i].size = sizeof(SANE_Word);
2258
s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2261
s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2262
s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2263
s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2264
s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2265
s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
2267
/* "Scan Mode" group: */
2269
s->opt[OPT_MODE_GROUP].name = SANE_NAME_STANDARD;
2270
s->opt[OPT_MODE_GROUP].title = SANE_TITLE_STANDARD;
2271
s->opt[OPT_MODE_GROUP].desc = SANE_DESC_STANDARD;
2272
s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
2273
s->opt[OPT_MODE_GROUP].cap = 0;
2276
s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
2277
s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
2278
s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
2279
s->opt[OPT_MODE].type = SANE_TYPE_STRING;
2280
s->opt[OPT_MODE].size = max_string_size(mode_list);
2281
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2282
s->opt[OPT_MODE].constraint.string_list = mode_list;
2283
s->val[OPT_MODE].w = 0; /* Binary */
2286
s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
2287
s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
2288
s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
2289
s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
2290
s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE;
2291
s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2292
s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->cap->depth_list;
2293
s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2294
s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1]; /* the first "real" element is the default */
2296
if (s->hw->cap->depth_list[0] == 1) /* only one element in the list -> hide the option */
2297
s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2301
s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
2302
s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
2303
s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2304
s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
2305
s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
2306
s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2307
s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cap->brightness;
2308
s->val[OPT_BRIGHTNESS].w = 5; /* Normal */
2311
s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2312
s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2313
s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2314
s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
2315
s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
2316
s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2317
res_list = malloc((s->hw->cap->res_list_size + 1) * sizeof(SANE_Word));
2318
if (res_list == NULL) {
2319
return SANE_STATUS_NO_MEM;
2321
*(res_list) = s->hw->cap->res_list_size;
2322
memcpy(&(res_list[1]), s->hw->cap->res_list, s->hw->cap->res_list_size * sizeof(SANE_Word));
2323
s->opt[OPT_RESOLUTION].constraint.word_list = res_list;
2324
s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min;
2328
s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
2329
s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2330
s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
2331
s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
2332
s->val[OPT_PREVIEW].w = SANE_FALSE;
2335
s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
2336
s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
2337
s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
2338
s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
2339
s->opt[OPT_SOURCE].size = max_string_size(source_list);
2340
s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2341
s->opt[OPT_SOURCE].constraint.string_list = source_list;
2342
s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */
2344
s->opt[OPT_ADF_MODE].name = "adf-mode";
2345
s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode");
2346
s->opt[OPT_ADF_MODE].desc =
2347
SANE_I18N("Selects the ADF mode (simplex/duplex)");
2348
s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING;
2349
s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list);
2350
s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2351
s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list;
2352
s->val[OPT_ADF_MODE].w = 0; /* simplex */
2353
if ((!s->hw->cap->ADF) || (s->hw->cap->adf_duplex == SANE_FALSE))
2354
s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE;
2357
/* "Geometry" group: */
2358
s->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY;
2359
s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY;
2360
s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;
2361
s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2362
s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2365
s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2366
s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2367
s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2368
s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2369
s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2370
s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2371
s->opt[OPT_TL_X].constraint.range = s->hw->x_range;
2372
s->val[OPT_TL_X].w = 0;
2375
s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2376
s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2377
s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2378
s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2379
s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2380
s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2381
s->opt[OPT_TL_Y].constraint.range = s->hw->y_range;
2382
s->val[OPT_TL_Y].w = 0;
2384
/* bottom-right x */
2385
s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2386
s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2387
s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2388
s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2389
s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2390
s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2391
s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
2392
s->val[OPT_BR_X].w = s->hw->x_range->max;
2394
/* bottom-right y */
2395
s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2396
s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2397
s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2398
s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2399
s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2400
s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2401
s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
2402
s->val[OPT_BR_Y].w = s->hw->y_range->max;
2404
return SANE_STATUS_GOOD;
2408
sane_open(SANE_String_Const name, SANE_Handle *handle)
2411
Magicolor_Scanner *s = NULL;
2413
int l = strlen(name);
2415
DBG(7, "%s: name = %s\n", __func__, name);
2417
/* probe if empty device name provided */
2420
status = sane_get_devices(NULL,0);
2421
if (status != SANE_STATUS_GOOD) {
2425
if (first_dev == NULL) {
2426
DBG(1, "no device detected\n");
2427
return SANE_STATUS_INVAL;
2430
s = device_detect(first_dev->sane.name, first_dev->connection,
2433
DBG(1, "cannot open a perfectly valid device (%s),"
2434
" please report to the authors\n", name);
2435
return SANE_STATUS_INVAL;
2440
if (strncmp(name, "net:", 4) == 0) {
2441
s = device_detect(name, SANE_MAGICOLOR_NET, &status);
2444
} else if (strncmp(name, "libusb:", 7) == 0) {
2445
s = device_detect(name, SANE_MAGICOLOR_USB, &status);
2450
/* as a last resort, check for a match
2451
* in the device list. This should handle platforms without libusb.
2453
if (first_dev == NULL) {
2454
status = sane_get_devices(NULL,0);
2455
if (status != SANE_STATUS_GOOD) {
2460
s = device_detect(name, SANE_MAGICOLOR_NODEV, &status);
2462
DBG(1, "invalid device name: %s\n", name);
2463
return SANE_STATUS_INVAL;
2469
/* s is always valid here */
2471
DBG(1, "handle obtained\n");
2475
*handle = (SANE_Handle) s;
2477
status = open_scanner(s);
2478
if (status != SANE_STATUS_GOOD) {
2487
sane_close(SANE_Handle handle)
2489
Magicolor_Scanner *s;
2492
* XXX Test if there is still data pending from
2493
* the scanner. If so, then do a cancel
2496
s = (Magicolor_Scanner *) handle;
2504
const SANE_Option_Descriptor *
2505
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
2507
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2509
if (option < 0 || option >= NUM_OPTIONS)
2512
return s->opt + option;
2515
static const SANE_String_Const *
2516
search_string_list(const SANE_String_Const *list, SANE_String value)
2518
while (*list != NULL && strcmp(value, *list) != 0)
2521
return ((*list == NULL) ? NULL : list);
2525
Activate, deactivate an option. Subroutines so we can add
2526
debugging info if we want. The change flag is set to TRUE
2527
if we changed an option. If we did not change an option,
2528
then the value of the changed flag is not modified.
2532
activateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)
2534
if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
2535
s->opt[option].cap &= ~SANE_CAP_INACTIVE;
2536
*change = SANE_TRUE;
2541
deactivateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change)
2543
if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
2544
s->opt[option].cap |= SANE_CAP_INACTIVE;
2545
*change = SANE_TRUE;
2550
getvalue(SANE_Handle handle, SANE_Int option, void *value)
2552
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2553
SANE_Option_Descriptor *sopt = &(s->opt[option]);
2554
Option_Value *sval = &(s->val[option]);
2556
DBG(17, "%s: option = %d\n", __func__, option);
2562
case OPT_BRIGHTNESS:
2563
case OPT_RESOLUTION:
2569
*((SANE_Word *) value) = sval->w;
2575
strcpy((char *) value, sopt->constraint.string_list[sval->w]);
2579
return SANE_STATUS_INVAL;
2582
return SANE_STATUS_GOOD;
2587
* Handles setting the source (flatbed, or auto document feeder (ADF)).
2592
change_source(Magicolor_Scanner *s, SANE_Int optindex, char *value)
2594
int force_max = SANE_FALSE;
2597
DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex,
2600
if (s->val[OPT_SOURCE].w == optindex)
2603
s->val[OPT_SOURCE].w = optindex;
2605
if (s->val[OPT_TL_X].w == s->hw->x_range->min
2606
&& s->val[OPT_TL_Y].w == s->hw->y_range->min
2607
&& s->val[OPT_BR_X].w == s->hw->x_range->max
2608
&& s->val[OPT_BR_Y].w == s->hw->y_range->max) {
2609
force_max = SANE_TRUE;
2612
if (strcmp(ADF_STR, value) == 0) {
2613
s->hw->x_range = &s->hw->cap->adf_x_range;
2614
s->hw->y_range = &s->hw->cap->adf_y_range;
2615
if (s->hw->cap->adf_duplex) {
2616
activateOption(s, OPT_ADF_MODE, &dummy);
2618
deactivateOption(s, OPT_ADF_MODE, &dummy);
2619
s->val[OPT_ADF_MODE].w = 0;
2622
DBG(1, "adf activated (%d)\n",s->hw->cap->adf_duplex);
2625
/* ADF not active */
2626
s->hw->x_range = &s->hw->cap->fbf_x_range;
2627
s->hw->y_range = &s->hw->cap->fbf_y_range;
2629
deactivateOption(s, OPT_ADF_MODE, &dummy);
2632
s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
2633
s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
2635
if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max)
2636
s->val[OPT_TL_X].w = s->hw->x_range->min;
2638
if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max)
2639
s->val[OPT_TL_Y].w = s->hw->y_range->min;
2641
if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max)
2642
s->val[OPT_BR_X].w = s->hw->x_range->max;
2644
if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max)
2645
s->val[OPT_BR_Y].w = s->hw->y_range->max;
2650
setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
2652
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2653
SANE_Option_Descriptor *sopt = &(s->opt[option]);
2654
Option_Value *sval = &(s->val[option]);
2657
const SANE_String_Const *optval = NULL;
2659
SANE_Bool reload = SANE_FALSE;
2661
DBG(17, "%s: option = %d, value = %p, as word: %d\n", __func__, option, value, *(SANE_Word *) value);
2663
status = sanei_constrain_value(sopt, value, info);
2664
if (status != SANE_STATUS_GOOD)
2667
if (info && value && (*info & SANE_INFO_INEXACT)
2668
&& sopt->type == SANE_TYPE_INT)
2669
DBG(17, "%s: constrained val = %d\n", __func__,
2670
*(SANE_Word *) value);
2672
if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) {
2673
optval = search_string_list(sopt->constraint.string_list,
2676
return SANE_STATUS_INVAL;
2677
optindex = optval - sopt->constraint.string_list;
2685
/* if binary, then disable the bit depth selection */
2686
if (optindex == 0) {
2687
s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
2689
if (s->hw->cap->depth_list[0] == 1)
2690
s->opt[OPT_BIT_DEPTH].cap |=
2693
s->opt[OPT_BIT_DEPTH].cap &=
2695
s->val[OPT_BIT_DEPTH].w =
2696
mode_params[optindex].depth;
2704
sval->w = *((SANE_Word *) value);
2705
mode_params[s->val[OPT_MODE].w].depth = sval->w;
2709
case OPT_RESOLUTION:
2710
sval->w = *((SANE_Word *) value);
2711
DBG(17, "setting resolution to %d\n", sval->w);
2717
sval->w = *((SANE_Word *) value);
2718
if (SANE_UNFIX(sval->w) == 0) {
2719
DBG(17, "invalid br-x or br-y\n");
2720
return SANE_STATUS_INVAL;
2725
sval->w = *((SANE_Word *) value);
2726
DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w));
2728
*info |= SANE_INFO_RELOAD_PARAMS;
2732
change_source(s, optindex, (char *) value);
2737
sval->w = optindex; /* Simple lists */
2740
case OPT_BRIGHTNESS:
2741
case OPT_PREVIEW: /* needed? */
2742
sval->w = *((SANE_Word *) value);
2746
return SANE_STATUS_INVAL;
2749
if (reload && info != NULL)
2750
*info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2752
DBG(17, "%s: end\n", __func__);
2754
return SANE_STATUS_GOOD;
2758
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
2759
void *value, SANE_Int *info)
2761
DBG(17, "%s: action = %x, option = %d\n", __func__, action, option);
2763
if (option < 0 || option >= NUM_OPTIONS)
2764
return SANE_STATUS_INVAL;
2770
case SANE_ACTION_GET_VALUE:
2771
return getvalue(handle, option, value);
2773
case SANE_ACTION_SET_VALUE:
2774
return setvalue(handle, option, value, info);
2777
return SANE_STATUS_INVAL;
2780
return SANE_STATUS_INVAL;
2784
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
2786
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2788
DBG(5, "%s\n", __func__);
2791
DBG(1, "%s: params is NULL\n", __func__);
2794
* If sane_start was already called, then just retrieve the parameters
2795
* from the scanner data structure
2798
if (!s->eof && s->ptr != NULL) {
2799
DBG(5, "scan in progress, returning saved params structure\n");
2801
/* otherwise initialize the params structure and gather the data */
2802
mc_init_parameters(s);
2806
*params = s->params;
2808
print_params(s->params);
2810
return SANE_STATUS_GOOD;
2814
* This function is part of the SANE API and gets called from the front end to
2815
* start the scan process.
2819
sane_start(SANE_Handle handle)
2821
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2824
DBG(5, "%s\n", __func__);
2826
/* calc scanning parameters */
2827
status = mc_init_parameters(s);
2828
if (status != SANE_STATUS_GOOD)
2831
print_params(s->params);
2833
/* set scanning parameters; also query the current image
2834
* parameters from the sanner and save
2835
* them to s->params */
2836
status = mc_set_scanning_parameters(s);
2838
if (status != SANE_STATUS_GOOD)
2841
/* if we scan from ADF, check if it is loaded */
2842
if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
2843
status = mc_check_adf(s);
2844
if (status != SANE_STATUS_GOOD)
2848
/* prepare buffer here so that a memory allocation failure
2849
* will leave the scanner in a sane state.
2851
s->buf = realloc(s->buf, s->block_len);
2853
return SANE_STATUS_NO_MEM;
2855
s->eof = SANE_FALSE;
2856
s->ptr = s->end = s->buf;
2857
s->canceling = SANE_FALSE;
2859
/* start scanning */
2860
DBG(1, "%s: scanning...\n", __func__);
2862
status = mc_start_scan(s);
2864
if (status != SANE_STATUS_GOOD) {
2865
DBG(1, "%s: start failed: %s\n", __func__,
2866
sane_strstatus(status));
2874
/* this moves data from our buffers to SANE */
2877
sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
2881
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2883
if (s->buf == NULL || s->canceling)
2884
return SANE_STATUS_CANCELLED;
2888
status = mc_read(s);
2890
if (status == SANE_STATUS_CANCELLED) {
2895
DBG(18, "moving data %p %p, %d (%d lines)\n",
2897
max_length, max_length / s->params.bytes_per_line);
2899
mc_copy_image_data(s, data, max_length, length);
2901
DBG(18, "%d lines read, status: %d\n",
2902
*length / s->params.bytes_per_line, status);
2904
/* continue reading if appropriate */
2905
if (status == SANE_STATUS_GOOD)
2914
* void sane_cancel(SANE_Handle handle)
2916
* Set the cancel flag to true. The next time the backend requests data
2917
* from the scanner the CAN message will be sent.
2921
sane_cancel(SANE_Handle handle)
2923
Magicolor_Scanner *s = (Magicolor_Scanner *) handle;
2925
s->canceling = SANE_TRUE;
2929
* SANE_Status sane_set_io_mode()
2931
* not supported - for asynchronous I/O
2935
sane_set_io_mode(SANE_Handle __sane_unused__ handle,
2936
SANE_Bool __sane_unused__ non_blocking)
2938
return SANE_STATUS_UNSUPPORTED;
2942
* SANE_Status sane_get_select_fd()
2944
* not supported - for asynchronous I/O
2948
sane_get_select_fd(SANE_Handle __sane_unused__ handle,
2949
SANE_Int __sane_unused__ *fd)
2951
return SANE_STATUS_UNSUPPORTED;