1 /* SANE - Scanner Access Now Easy.
2
3 Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
4 Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
5 Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
6
7 This file is part of the SANE package.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22 As a special exception, the authors of SANE give permission for
23 additional uses of the libraries contained in this release of SANE.
24
25 The exception is that, if you link a SANE library with other files
26 to produce an executable, this does not by itself cause the
27 resulting executable to be covered by the GNU General Public
28 License. Your use of that executable is in no way restricted on
29 account of linking the SANE library code into it.
30
31 This exception does not, however, invalidate any other reasons why
32 the executable file might be covered by the GNU General Public
33 License.
34
35 If you submit changes to SANE to the maintainers to be included in
36 a subsequent release, you agree by submitting the changes that
37 those changes may be distributed with this exception intact.
38
39 If you write modifications of your own for SANE, it is your choice
40 whether to permit this exception to apply to your modifications.
41 If you do not wish that, delete this exception notice.
42 */
43 #include "../include/sane/config.h"
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <ctype.h>
50 #include <math.h> /* pow(C90) */
51
52 #include <sys/time.h> /* gettimeofday(4.3BSD) */
53 #include <unistd.h> /* usleep */
54
55 #if defined(HAVE_LIBXML2)
56 # include <libxml/parser.h>
57 #endif
58
59 #include "pixma_rename.h"
60 #include "pixma_common.h"
61 #include "pixma_io.h"
62
63 #include "../include/sane/sanei_usb.h"
64 #include "../include/sane/sane.h"
65
66 #ifdef __GNUC__
67 # define UNUSED(v) (void) v
68 #else
69 # define UNUSED(v)
70 #endif
71
72 extern const pixma_config_t pixma_mp150_devices[];
73 extern const pixma_config_t pixma_mp750_devices[];
74 extern const pixma_config_t pixma_mp730_devices[];
75 extern const pixma_config_t pixma_mp800_devices[];
76 extern const pixma_config_t pixma_iclass_devices[];
77
78 static const pixma_config_t *const pixma_devices[] = {
79 pixma_mp150_devices,
80 pixma_mp750_devices,
81 pixma_mp730_devices,
82 pixma_mp800_devices,
83 pixma_iclass_devices,
84 NULL
85 };
86
87 static pixma_t *first_pixma = NULL;
88 static time_t tstart_sec = 0;
89 static uint32_t tstart_usec = 0;
90 static int debug_level = 1;
91
92
93 #ifndef NDEBUG
94
95 static void
u8tohex(uint8_t x, char *str)96 u8tohex (uint8_t x, char *str)
97 {
98 static const char hdigit[16] =
99 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
100 'e', 'f'
101 };
102 str[0] = hdigit[(x >> 4) & 0xf];
103 str[1] = hdigit[x & 0xf];
104 str[2] = '\0';
105 }
106
107 static void
u32tohex(uint32_t x, char *str)108 u32tohex (uint32_t x, char *str)
109 {
110 u8tohex (x >> 24, str);
111 u8tohex (x >> 16, str + 2);
112 u8tohex (x >> 8, str + 4);
113 u8tohex (x, str + 6);
114 }
115
116 void
pixma_hexdump(int level, const void *d_, unsigned len)117 pixma_hexdump (int level, const void *d_, unsigned len)
118 {
119 const uint8_t *d = (const uint8_t *) (d_);
120 unsigned ofs, c, plen;
121 char line[100]; /* actually only 1+8+1+8*3+1+8*3+1 = 61 bytes needed */
122
123 if (level > debug_level)
124 return;
125 if (level == debug_level)
126 /* if debuglevel == exact match and buffer contains more than 3 lines, print 2 lines + .... */
127 plen = (len > 64) ? 32: len;
128 else
129 plen = len;
130 ofs = 0;
131 while (ofs < plen)
132 {
133 char *p;
134 line[0] = ' ';
135 u32tohex (ofs, line + 1);
136 line[9] = ':';
137 p = line + 10;
138 for (c = 0; c != 16 && (ofs + c) < plen; c++)
139 {
140 u8tohex (d[ofs + c], p);
141 p[2] = ' ';
142 p += 3;
143 if (c == 7)
144 {
145 p[0] = ' ';
146 p++;
147 }
148 }
149 for (c = 0; c < 4; c++)
150 {
151 p[0] = ' ';
152 p++;
153 }
154 for (c = 0; c != 16 && (ofs + c) < plen; c++)
155 {
156 if (isprint(d[ofs + c]))
157 p[0] = d[ofs + c];
158 else
159 p[0] = '.';
160 p++;
161 if (c == 7)
162 {
163 p[0] = ' ';
164 p++;
165 }
166 }
167 p[0] = '\0';
168 pixma_dbg (level, "%s\n", line);
169 ofs += c;
170 }
171 if (len > plen)
172 pixma_dbg(level, "......\n");
173 }
174
175 static void
time2str(char *buf, unsigned size)176 time2str (char *buf, unsigned size)
177 {
178 time_t sec;
179 uint32_t usec;
180
181 pixma_get_time (&sec, &usec);
182 sec -= tstart_sec;
183 if (usec >= tstart_usec)
184 {
185 usec -= tstart_usec;
186 }
187 else
188 {
189 usec = 1000000 + usec - tstart_usec;
190 sec--;
191 }
192 snprintf (buf, size, "%lu.%03u", (unsigned long) sec,
193 (unsigned) (usec / 1000));
194 }
195
196 void
pixma_dump(int level, const char *type, const void *data, int len, int size, int max)197 pixma_dump (int level, const char *type, const void *data, int len,
198 int size, int max)
199 {
200 int actual_len, print_len;
201 char buf[20];
202
203 if (level > debug_level)
204 return;
205 if (debug_level >= 20)
206 max = -1; /* dump every bytes */
207
208 time2str (buf, sizeof (buf));
209 pixma_dbg (level, "%s T=%s len=%d\n", type, buf, len);
210
211 actual_len = (size >= 0) ? size : len;
212 print_len = (max >= 0 && max < actual_len) ? max : actual_len;
213 if (print_len >= 0)
214 {
215 pixma_hexdump (level, data, print_len);
216 if (print_len < actual_len)
217 pixma_dbg (level, " ...\n");
218 }
219 if (len < 0)
220 pixma_dbg (level, " ERROR: %s\n", pixma_strerror (len));
221 pixma_dbg (level, "\n");
222 }
223
224
225 #endif /* NDEBUG */
226
227 /* NOTE: non-reentrant */
228 const char *
pixma_strerror(int error)229 pixma_strerror (int error)
230 {
231 static char buf[50];
232
233 /* TODO: more human friendly messages */
234 switch (error)
235 {
236 case PIXMA_EIO:
237 return "EIO";
238 case PIXMA_ENODEV:
239 return "ENODEV";
240 case PIXMA_EACCES:
241 return "EACCES";
242 case PIXMA_ENOMEM:
243 return "ENOMEM";
244 case PIXMA_EINVAL:
245 return "EINVAL";
246 case PIXMA_EBUSY:
247 return "EBUSY";
248 case PIXMA_ECANCELED:
249 return "ECANCELED";
250 case PIXMA_ENOTSUP:
251 return "ENOTSUP";
252 case PIXMA_ETIMEDOUT:
253 return "ETIMEDOUT";
254 case PIXMA_EPROTO:
255 return "EPROTO";
256 case PIXMA_EPAPER_JAMMED:
257 return "EPAPER_JAMMED";
258 case PIXMA_ECOVER_OPEN:
259 return "ECOVER_OPEN";
260 case PIXMA_ENO_PAPER:
261 return "ENO_PAPER";
262 case PIXMA_EOF:
263 return "EEOF";
264 }
265 snprintf (buf, sizeof (buf), "EUNKNOWN:%d", error);
266 return buf;
267 }
268
269 void
pixma_set_debug_level(int level)270 pixma_set_debug_level (int level)
271 {
272 debug_level = level;
273 }
274
275 void
pixma_set_be16(uint16_t x, uint8_t * buf)276 pixma_set_be16 (uint16_t x, uint8_t * buf)
277 {
278 buf[0] = x >> 8;
279 buf[1] = x;
280 }
281
282 void
pixma_set_be32(uint32_t x, uint8_t * buf)283 pixma_set_be32 (uint32_t x, uint8_t * buf)
284 {
285 buf[0] = x >> 24;
286 buf[1] = x >> 16;
287 buf[2] = x >> 8;
288 buf[3] = x;
289 }
290
291 uint16_t
pixma_get_be16(const uint8_t * buf)292 pixma_get_be16 (const uint8_t * buf)
293 {
294 return ((uint16_t) buf[0] << 8) | buf[1];
295 }
296
297 uint32_t
pixma_get_be32(const uint8_t * buf)298 pixma_get_be32 (const uint8_t * buf)
299 {
300 return ((uint32_t) buf[0] << 24) + ((uint32_t) buf[1] << 16) +
301 ((uint32_t) buf[2] << 8) + buf[3];
302 }
303
304 uint8_t
pixma_sum_bytes(const void *data, unsigned len)305 pixma_sum_bytes (const void *data, unsigned len)
306 {
307 const uint8_t *d = (const uint8_t *) data;
308 unsigned i, sum = 0;
309 for (i = 0; i != len; i++)
310 sum += d[i];
311 return sum;
312 }
313
314 void
pixma_sleep(unsigned long usec)315 pixma_sleep (unsigned long usec)
316 {
317 usleep (usec);
318 }
319
320 void
pixma_get_time(time_t * sec, uint32_t * usec)321 pixma_get_time (time_t * sec, uint32_t * usec)
322 {
323 struct timeval tv;
324 gettimeofday (&tv, NULL);
325 if (sec)
326 *sec = tv.tv_sec;
327 if (usec)
328 *usec = tv.tv_usec;
329 }
330
331 /* convert 24/48 bit RGB to 8/16 bit ir
332 *
333 * Formular: g = R
334 * drop G + B
335 *
336 * sptr: source color scale buffer
337 * gptr: destination gray scale buffer
338 * c == 3: 24 bit RGB -> 8 bit ir
339 * c == 6: 48 bit RGB -> 16 bit ir
340 */
341 uint8_t *
pixma_r_to_ir(uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)342 pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
343 {
344 unsigned i;
345
346 /* PDBG (pixma_dbg (4, "*pixma_rgb_to_ir*****\n")); */
347
348 for (i = 0; i < w; i++)
349 {
350 *gptr++ = *sptr++;
351 if (c == 6) *gptr++ = *sptr++; /* 48 bit RGB: high byte */
352 sptr += (c == 6) ? 4 : 2; /* drop G + B */
353 }
354 return gptr;
355 }
356
357 /* convert 24/48 bit RGB to 8/16 bit grayscale
358 *
359 * Formular: Y' = 0,2126 R' + 0,7152 G' + 0,0722 B'
360 *
361 * sptr: source color scale buffer
362 * gptr: destination gray scale buffer
363 * c == 3: 24 bit RGB -> 8 bit gray
364 * c == 6: 48 bit RGB -> 16 bit gray
365 */
366 uint8_t *
pixma_rgb_to_gray(uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)367 pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
368 {
369 unsigned i, g;
370
371 /* PDBG (pixma_dbg (4, "*pixma_rgb_to_gray*****\n")); */
372
373 for (i = 0; i < w; i++)
374 {
375 if (c == 6)
376 { /* 48 bit RGB */
377 unsigned r = sptr[0] + (sptr[1] << 8);
378 unsigned y = sptr[2] + (sptr[3] << 8);
379 unsigned b = sptr[4] + (sptr[5] << 8);
380
381 g = (r * 2126) + (y * 7152) + (b * 722);
382 sptr += 6;
383 }
384 else
385 { /* 24 bit RGB */
386 g = (sptr[0] * 2126) + (sptr[1] * 7152) + (sptr[2] * 722);
387 sptr += 3;
388 }
389 g /= 10000; /* 8 and 16 bit gray */
390
391 *gptr++ = g;
392 if (c == 6) *gptr++ = (g >> 8); /* 16 bit gray: high byte */
393 }
394 return gptr;
395 }
396
397 /**
398 * This code was taken from the genesys backend
399 * uses threshold and threshold_curve to control software binarization
400 * @param sp device set up for the scan
401 * @param dst pointer where to store result
402 * @param src pointer to raw data
403 * @param width width of the processed line
404 * @param c 1 for 1-channel single-byte data,
405 * 3 for 3-channel single-byte data,
406 * 6 for double-byte data
407 * */
408 uint8_t *
pixma_binarize_line(pixma_scan_param_t * sp, uint8_t * dst, uint8_t * src, unsigned width, unsigned c)409 pixma_binarize_line(pixma_scan_param_t * sp, uint8_t * dst, uint8_t * src, unsigned width, unsigned c)
410 {
411 unsigned j, x, windowX, sum = 0;
412 unsigned threshold;
413 unsigned offset, addCol;
414 int dropCol, offsetX;
415 unsigned char mask;
416 uint8_t min, max;
417
418 /* PDBG (pixma_dbg (4, "*pixma_binarize_line***** src = %u, dst = %u, width = %u, c = %u, threshold = %u, threshold_curve = %u *****\n",
419 src, dst, width, c, sp->threshold, sp->threshold_curve)); */
420
421 /* 16 bit grayscale not supported */
422 if (c == 6)
423 {
424 PDBG (pixma_dbg (1, "*pixma_binarize_line***** Error: 16 bit grayscale not supported\n"));
425 return dst;
426 }
427
428 /* first, color convert to grayscale */
429 if (c != 1)
430 pixma_rgb_to_gray(dst, src, width, c);
431
432 /* second, normalize line */
433 min = 255;
434 max = 0;
435 for (x = 0; x < width; x++)
436 {
437 if (src[x] > max)
438 {
439 max = src[x];
440 }
441 if (src[x] < min)
442 {
443 min = src[x];
444 }
445 }
446
447 /* safeguard against dark or white areas */
448 if(min>80)
449 min=0;
450 if(max<80)
451 max=255;
452 for (x = 0; x < width; x++)
453 {
454 src[x] = ((src[x] - min) * 255) / (max - min);
455 }
456
457 /* third, create sliding window, prefill the sliding sum */
458 /* ~1mm works best, but the window needs to have odd # of pixels */
459 windowX = (6 * sp->xdpi) / 150;
460 if (!(windowX % 2))
461 windowX++;
462
463 /* to avoid conflicts with *dst start with offset */
464 offsetX = 1 + (windowX / 2) / 8;
465 for (j = offsetX; j <= windowX; j++)
466 sum += src[j];
467 /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** windowX = %u, startX = %u, sum = %u\n",
468 windowX, startX, sum)); */
469
470 /* fourth, walk the input buffer, output bits */
471 for (j = 0; j < width; j++)
472 {
473 /* output image location */
474 offset = j % 8;
475 mask = 0x80 >> offset;
476 threshold = sp->threshold;
477
478 /* move sum/update threshold only if there is a curve */
479 if (sp->threshold_curve)
480 {
481 addCol = j + windowX / 2;
482 dropCol = addCol - windowX;
483
484 if (dropCol >= offsetX && addCol < width)
485 {
486 sum += src[addCol];
487 sum -= (sum < src[dropCol] ? sum : src[dropCol]); /* no negative sum */
488 }
489 threshold = sp->lineart_lut[sum / windowX];
490 /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** addCol = %u, dropCol = %d, sum = %u, windowX = %u, lut-element = %d, threshold = %u\n",
491 addCol, dropCol, sum, windowX, sum/windowX, threshold)); */
492 }
493
494 /* lookup threshold */
495 if (src[j] > threshold)
496 *dst &= ~mask; /* white */
497 else
498 *dst |= mask; /* black */
499
500 if (offset == 7)
501 dst++;
502 }
503
504 /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** ready: src = %u, dst = %u *****\n", src, dst)); */
505
506 return dst;
507 }
508
509 /**
510 This code was taken from the genesys backend
511 Function to build a lookup table (LUT), often
512 used by scanners to implement brightness/contrast/gamma
513 or by backends to speed binarization/thresholding
514
515 offset and slope inputs are -127 to +127
516
517 slope rotates line around central input/output val,
518 0 makes horizontal line
519
520 pos zero neg
521 . x . . x
522 . x . . x
523 out . x .xxxxxxxxxxx . x
524 . x . . x
525 ....x....... ............ .......x....
526 in in in
527
528 offset moves line vertically, and clamps to output range
529 0 keeps the line crossing the center of the table
530
531 high low
532 . xxxxxxxx .
533 . x .
534 out x . x
535 . . x
536 ............ xxxxxxxx....
537 in in
538
539 out_min/max provide bounds on output values,
540 useful when building thresholding lut.
541 0 and 255 are good defaults otherwise.
542 * */
543 static SANE_Status
load_lut(unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset)544 load_lut (unsigned char * lut,
545 int in_bits, int out_bits,
546 int out_min, int out_max,
547 int slope, int offset)
548 {
549 int i, j;
550 double shift, rise;
551 int max_in_val = (1 << in_bits) - 1;
552 int max_out_val = (1 << out_bits) - 1;
553 unsigned char * lut_p = lut;
554
555 /* PDBG (pixma_dbg (4, "*load_lut***** start %d %d *****\n", slope, offset)); */
556
557 /* slope is converted to rise per unit run:
558 * first [-127,127] to [-1,1]
559 * then multiply by PI/2 to convert to radians
560 * then take the tangent (T.O.A)
561 * then multiply by the normal linear slope
562 * because the table may not be square, i.e. 1024x256*/
563 rise = tan((double)slope/127 * M_PI/2) * max_out_val / max_in_val;
564
565 /* line must stay vertically centered, so figure
566 * out vertical offset at central input value */
567 shift = (double)max_out_val/2 - (rise*max_in_val/2);
568
569 /* convert the user offset setting to scale of output
570 * first [-127,127] to [-1,1]
571 * then to [-max_out_val/2,max_out_val/2]*/
572 shift += (double)offset / 127 * max_out_val / 2;
573
574 for(i=0;i<=max_in_val;i++){
575 j = rise*i + shift;
576
577 if(j<out_min){
578 j=out_min;
579 }
580 else if(j>out_max){
581 j=out_max;
582 }
583
584 *lut_p=j;
585 lut_p++;
586 }
587
588 /* PDBG (pixma_dbg (4, "*load_lut***** finish *****\n")); */
589 /* PDBG (pixma_hexdump (4, lut, max_in_val+1)); */
590
591 return SANE_STATUS_GOOD;
592 }
593
594 int
pixma_map_status_errno(unsigned status)595 pixma_map_status_errno (unsigned status)
596 {
597 switch (status)
598 {
599 case PIXMA_STATUS_OK:
600 return 0;
601 case PIXMA_STATUS_FAILED:
602 return PIXMA_ECANCELED;
603 case PIXMA_STATUS_BUSY:
604 return PIXMA_EBUSY;
605 default:
606 return PIXMA_EPROTO;
607 }
608 }
609
610 int
pixma_check_result(pixma_cmdbuf_t * cb)611 pixma_check_result (pixma_cmdbuf_t * cb)
612 {
613 const uint8_t *r = cb->buf;
614 unsigned header_len = cb->res_header_len;
615 unsigned expected_reslen = cb->expected_reslen;
616 int error;
617 unsigned len;
618
619 if (cb->reslen < 0)
620 return cb->reslen;
621
622 len = (unsigned) cb->reslen;
623 if (len >= header_len)
624 {
625 error = pixma_map_status_errno (pixma_get_be16 (r));
626 if (expected_reslen != 0)
627 {
628 if (len == expected_reslen)
629 {
630 if (pixma_sum_bytes (r + header_len, len - header_len) != 0)
631 error = PIXMA_EPROTO;
632 }
633 else
634 {
635 /* This case will happen when a command cannot be completely
636 executed, e.g. because you press the cancel button. The
637 device will return only a header with PIXMA_STATUS_FAILED. */
638 if (len != header_len)
639 error = PIXMA_EPROTO;
640 }
641 }
642 }
643 else
644 error = PIXMA_EPROTO;
645
646 #ifndef NDEBUG
647 if (error == PIXMA_EPROTO)
648 {
649 pixma_dbg (1, "WARNING: result len=%d expected %d\n",
650 len, cb->expected_reslen);
651 pixma_hexdump (1, r, MIN (len, 64));
652 }
653 #endif
654 return error;
655 }
656
657 int
pixma_cmd_transaction(pixma_t * s, const void *cmd, unsigned cmdlen, void *data, unsigned expected_len)658 pixma_cmd_transaction (pixma_t * s, const void *cmd, unsigned cmdlen,
659 void *data, unsigned expected_len)
660 {
661 int error, tmo;
662
663 error = pixma_write (s->io, cmd, cmdlen);
664 if (error != (int) cmdlen)
665 {
666 if (error >= 0)
667 {
668 /* Write timeout is too low? */
669 PDBG (pixma_dbg
670 (1, "ERROR: incomplete write, %u out of %u written\n",
671 (unsigned) error, cmdlen));
672 error = PIXMA_ETIMEDOUT;
673 }
674 return error;
675 }
676
677 /* When you send the start_session command while the scanner optic is
678 going back to the home position after the last scan session has been
679 cancelled, you won't get the response before it arrives home. This takes
680 about 5 seconds. If the last session was succeeded, the scanner will
681 immediately answer with PIXMA_STATUS_BUSY.
682
683 Is 8 seconds timeout enough? This affects ALL commands that use
684 pixma_cmd_transaction(). Default value set in pixma_open(). */
685 tmo = s->rec_tmo;
686 do
687 {
688 error = pixma_read (s->io, data, expected_len);
689 if (error == PIXMA_ETIMEDOUT)
690 {
691 PDBG (pixma_dbg (2, "No response yet. Timed out in %d sec.\n", tmo));
692
693 #ifndef HAVE_SANEI_USB_SET_TIMEOUT
694 /* 1s timeout
695 Only needed, if sanei_usb_set_timeout() isn't available.
696 pixma_read() has an internal timeout of 1 sec. */
697 pixma_sleep (1000000);
698 #endif
699 }
700 }
701 while (error == PIXMA_ETIMEDOUT && --tmo != 0);
702 if (error < 0)
703 {
704 PDBG (pixma_dbg (1, "WARNING: Error in response phase. cmd:%02x%02x\n",
705 ((const uint8_t *) cmd)[0],
706 ((const uint8_t *) cmd)[1]));
707 PDBG (pixma_dbg (1," If the scanner hangs, reset it and/or unplug the "
708 "USB cable.\n"));
709 }
710 return error; /* length of the result packet or error */
711 }
712
713 uint8_t *
pixma_newcmd(pixma_cmdbuf_t * cb, unsigned cmd, unsigned dataout, unsigned datain)714 pixma_newcmd (pixma_cmdbuf_t * cb, unsigned cmd,
715 unsigned dataout, unsigned datain)
716 {
717 unsigned cmdlen = cb->cmd_header_len + dataout;
718 unsigned reslen = cb->res_header_len + datain;
719
720 if (cmdlen > cb->size || reslen > cb->size)
721 return NULL;
722 memset (cb->buf, 0, cmdlen);
723 cb->cmdlen = cmdlen;
724 cb->expected_reslen = reslen;
725 pixma_set_be16 (cmd, cb->buf);
726 pixma_set_be16 (dataout + datain, cb->buf + cb->cmd_len_field_ofs);
727 if (dataout != 0)
728 return cb->buf + cb->cmd_header_len;
729 else
730 return cb->buf + cb->res_header_len;
731 }
732
733 int
pixma_exec(pixma_t * s, pixma_cmdbuf_t * cb)734 pixma_exec (pixma_t * s, pixma_cmdbuf_t * cb)
735 {
736 if (cb->cmdlen > cb->cmd_header_len)
737 pixma_fill_checksum (cb->buf + cb->cmd_header_len,
738 cb->buf + cb->cmdlen - 1);
739 cb->reslen =
740 pixma_cmd_transaction (s, cb->buf, cb->cmdlen, cb->buf,
741 cb->expected_reslen);
742 return pixma_check_result (cb);
743 }
744
745 int
pixma_exec_short_cmd(pixma_t * s, pixma_cmdbuf_t * cb, unsigned cmd)746 pixma_exec_short_cmd (pixma_t * s, pixma_cmdbuf_t * cb, unsigned cmd)
747 {
748 pixma_newcmd (cb, cmd, 0, 0);
749 return pixma_exec (s, cb);
750 }
751
752 int
pixma_check_dpi(unsigned dpi, unsigned max)753 pixma_check_dpi (unsigned dpi, unsigned max)
754 {
755 /* valid dpi = 75 * 2^n */
756 unsigned temp = dpi / 75;
757 if (dpi > max || dpi < 75 || 75 * temp != dpi || (temp & (temp - 1)) != 0)
758 return PIXMA_EINVAL;
759 return 0;
760 }
761
762
763 int
pixma_init(void)764 pixma_init (void)
765 {
766 PDBG (pixma_dbg (2, "pixma version %d.%d.%d\n", PIXMA_VERSION_MAJOR,
767 PIXMA_VERSION_MINOR, PIXMA_VERSION_BUILD));
768 PASSERT (first_pixma == NULL);
769 if (tstart_sec == 0)
770 pixma_get_time (&tstart_sec, &tstart_usec);
771 return pixma_io_init ();
772 }
773
774 void
pixma_cleanup(void)775 pixma_cleanup (void)
776 {
777 while (first_pixma)
778 pixma_close (first_pixma);
779 pixma_io_cleanup ();
780 }
781
782 int
pixma_open(unsigned devnr, pixma_t ** handle)783 pixma_open (unsigned devnr, pixma_t ** handle)
784 {
785 int error;
786 pixma_t *s;
787 const pixma_config_t *cfg;
788
789 *handle = NULL;
790 cfg = pixma_get_device_config (devnr);
791 if (!cfg)
792 return PIXMA_EINVAL; /* invalid devnr */
793 PDBG (pixma_dbg (2, "pixma_open(): %s\n", cfg->name));
794
795 s = (pixma_t *) calloc (1, sizeof (s[0]));
796 if (!s)
797 return PIXMA_ENOMEM;
798 s->next = first_pixma;
799 first_pixma = s;
800
801 s->cfg = cfg;
802 s->rec_tmo = 8; /* set receive timeout to 8 seconds */
803 error = pixma_connect (devnr, &s->io);
804 if (error < 0)
805 {
806 PDBG (pixma_dbg
807 (2, "pixma_connect() failed %s\n", pixma_strerror (error)));
808 goto rollback;
809 }
810 strncpy (s->id, pixma_get_device_id (devnr), sizeof (s->id) - 1);
811 s->ops = s->cfg->ops;
812 s->scanning = 0;
813 s->last_source = PIXMA_SOURCE_NONE;
814 error = s->ops->open (s);
815 if (error < 0)
816 goto rollback;
817 error = pixma_deactivate (s->io);
818 if (error < 0)
819 goto rollback;
820 *handle = s;
821 return 0;
822
823 rollback:
824 PDBG (pixma_dbg (2, "pixma_open() failed %s\n", pixma_strerror (error)));
825 pixma_close (s);
826 return error;
827 }
828
829 void
pixma_close(pixma_t * s)830 pixma_close (pixma_t * s)
831 {
832 pixma_t **p;
833
834 if (!s)
835 return;
836 for (p = &first_pixma; *p && *p != s; p = &((*p)->next))
837 {
838 }
839 PASSERT (*p);
840 if (!(*p))
841 return;
842 PDBG (pixma_dbg (2, "pixma_close(): %s\n", s->cfg->name));
843 if (s->io)
844 {
845 if (s->scanning)
846 {
847 PDBG (pixma_dbg (3, "pixma_close(): scanning in progress, call"
848 " finish_scan()\n"));
849 s->ops->finish_scan (s);
850 }
851 s->ops->close (s);
852 pixma_disconnect (s->io);
853 }
854 *p = s->next;
855 free (s);
856 }
857
858 int
pixma_scan(pixma_t * s, pixma_scan_param_t * sp)859 pixma_scan (pixma_t * s, pixma_scan_param_t * sp)
860 {
861 int error;
862
863 error = pixma_check_scan_param (s, sp);
864 if (error < 0)
865 return error;
866
867 if (sp->mode == PIXMA_SCAN_MODE_LINEART)
868 {
869 load_lut(sp->lineart_lut, 8, 8, 50, 205,
870 sp->threshold_curve, sp->threshold-127);
871 }
872
873 #ifndef NDEBUG
874 pixma_dbg (3, "\n");
875 pixma_dbg (3, "pixma_scan(): start\n");
876 pixma_dbg (3, " line_size=%"PRIu64" image_size=%"PRIu64" channels=%u depth=%u\n",
877 sp->line_size, sp->image_size, sp->channels, sp->depth);
878 pixma_dbg (3, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n",
879 sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h);
880 pixma_dbg (3, " gamma=%f gamma_table=%p source=%d\n", sp->gamma, (void *) sp->gamma_table, sp->source);
881 pixma_dbg (3, " threshold=%d threshold_curve=%d\n", sp->threshold, sp->threshold_curve);
882 pixma_dbg (3, " adf-wait=%d\n", sp->adf_wait);
883 pixma_dbg (3, " ADF page count: %d\n", sp->adf_pageid);
884 #endif
885
886 s->param = sp;
887 s->cancel = 0;
888 s->cur_image_size = 0;
889 s->imagebuf.wptr = NULL;
890 s->imagebuf.wend = NULL;
891 s->imagebuf.rptr = NULL;
892 s->imagebuf.rend = NULL;
893 s->underrun = 0;
894 error = s->ops->scan (s);
895 if (error >= 0)
896 {
897 s->scanning = 1;
898 }
899 else
900 {
901 PDBG (pixma_dbg
902 (3, "pixma_scan() failed %s\n", pixma_strerror (error)));
903 }
904
905 return error;
906 }
907
908 static uint8_t *
fill_pixels(pixma_t * s, uint8_t * ptr, uint8_t * end, uint8_t value)909 fill_pixels (pixma_t * s, uint8_t * ptr, uint8_t * end, uint8_t value)
910 {
911 if (s->cur_image_size < s->param->image_size)
912 {
913 long n = s->param->image_size - s->cur_image_size;
914 if (n > (end - ptr))
915 n = end - ptr;
916 memset (ptr, value, n);
917 s->cur_image_size += n;
918 ptr += n;
919 }
920 return ptr;
921 }
922
923 int
pixma_read_image(pixma_t * s, void *buf, unsigned len)924 pixma_read_image (pixma_t * s, void *buf, unsigned len)
925 {
926 int result;
927 pixma_imagebuf_t ib;
928
929 if (!s->scanning)
930 return 0;
931 if (s->cancel)
932 {
933 result = PIXMA_ECANCELED;
934 goto cancel;
935 }
936
937 ib = s->imagebuf; /* get rptr and rend */
938 ib.wptr = (uint8_t *) buf;
939 ib.wend = ib.wptr + len;
940
941 if (s->underrun)
942 {
943 if (s->cur_image_size < s->param->image_size)
944 {
945 ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
946 }
947 else
948 {
949 PDBG (pixma_dbg
950 (3, "pixma_read_image(): completed (underrun detected)\n"));
951 s->scanning = 0;
952 }
953 return ib.wptr - (uint8_t *) buf;
954 }
955
956 while (ib.wptr != ib.wend)
957 {
958 if (ib.rptr == ib.rend)
959 {
960 ib.rptr = ib.rend = NULL;
961 result = s->ops->fill_buffer (s, &ib);
962 if (result < 0)
963 goto cancel;
964 if (result == 0)
965 { /* end of image? */
966 s->ops->finish_scan (s);
967 /* set last source after successful scan */
968 s->last_source = s->param->source;
969 if ((s->cur_image_size != s->param->image_size) && !s->param->mode_jpeg)
970 {
971 PDBG (pixma_dbg (1, "WARNING:image size mismatches\n"));
972 PDBG (pixma_dbg (1,
973 " %"PRIu64" expected (%d lines) but %"PRIu64" received (%"PRIu64" lines)\n",
974 s->param->image_size, s->param->h,
975 s->cur_image_size,
976 s->cur_image_size / s->param->line_size));
977 if ((s->cur_image_size % s->param->line_size) != 0)
978 {
979 PDBG (pixma_dbg (1,
980 "BUG:received data not multiple of line_size\n"));
981 }
982 }
983 if ((s->cur_image_size < s->param->image_size) && !s->param->mode_jpeg)
984 {
985 s->underrun = 1;
986 ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
987 }
988 else
989 {
990 PDBG (pixma_dbg (3, "pixma_read_image():completed\n"));
991 s->scanning = 0;
992 }
993 break;
994 }
995 s->cur_image_size += result;
996
997 PASSERT (s->cur_image_size <= s->param->image_size);
998 }
999 if (ib.rptr)
1000 {
1001 unsigned count = MIN (ib.rend - ib.rptr, ib.wend - ib.wptr);
1002 memcpy (ib.wptr, ib.rptr, count);
1003 ib.rptr += count;
1004 ib.wptr += count;
1005 }
1006 }
1007 s->imagebuf = ib; /* store rptr and rend */
1008 return ib.wptr - (uint8_t *) buf;
1009
1010 cancel:
1011 s->ops->finish_scan (s);
1012 s->scanning = 0;
1013 if (result == PIXMA_ECANCELED)
1014 {
1015 PDBG (pixma_dbg (3, "pixma_read_image(): cancelled by %sware\n",
1016 (s->cancel) ? "soft" : "hard"));
1017 }
1018 else
1019 {
1020 PDBG (pixma_dbg (3, "pixma_read_image() failed %s\n",
1021 pixma_strerror (result)));
1022 }
1023 return result;
1024 }
1025
1026 void
pixma_cancel(pixma_t * s)1027 pixma_cancel (pixma_t * s)
1028 {
1029 s->cancel = 1;
1030 }
1031
1032 int
pixma_enable_background(pixma_t * s, int enabled)1033 pixma_enable_background (pixma_t * s, int enabled)
1034 {
1035 return pixma_set_interrupt_mode (s->io, enabled);
1036 }
1037
1038 int
pixma_activate_connection(pixma_t * s)1039 pixma_activate_connection(pixma_t * s)
1040 {
1041 return pixma_activate (s->io);
1042 }
1043
1044 int
pixma_deactivate_connection(pixma_t * s)1045 pixma_deactivate_connection(pixma_t * s)
1046 {
1047 return pixma_deactivate (s->io);
1048 }
1049
1050 uint32_t
pixma_wait_event(pixma_t * s, int timeout )1051 pixma_wait_event (pixma_t * s, int timeout /*ms */ )
1052 {
1053 unsigned events;
1054
1055 if (s->events == PIXMA_EV_NONE && s->ops->wait_event)
1056 s->ops->wait_event (s, timeout);
1057 events = s->events;
1058 s->events = PIXMA_EV_NONE;
1059 return events;
1060 }
1061
1062 #define CLAMP2(x,w,min,max,dpi) do { \
1063 unsigned m = (max) * (dpi) / 75; \
1064 x = MIN(x, m - min); \
1065 w = MIN(w, m - x); \
1066 if (w < min) w = min; \
1067 } while(0)
1068
1069 int
pixma_check_scan_param(pixma_t * s, pixma_scan_param_t * sp)1070 pixma_check_scan_param (pixma_t * s, pixma_scan_param_t * sp)
1071 {
1072 unsigned cfg_xdpi;
1073
1074 if (!(sp->channels == 3 ||
1075 (sp->channels == 1 && (s->cfg->cap & PIXMA_CAP_GRAY) != 0)))
1076 return PIXMA_EINVAL;
1077
1078 /* flatbed: use s->cfg->xdpi
1079 * TPU/ADF: use s->cfg->adftpu_max_dpi, if configured with dpi value */
1080 cfg_xdpi = ((sp->source == PIXMA_SOURCE_FLATBED
1081 || s->cfg->adftpu_max_dpi == 0) ? s->cfg->xdpi
1082 : s->cfg->adftpu_max_dpi);
1083
1084 if (pixma_check_dpi (sp->xdpi, cfg_xdpi) < 0 ||
1085 pixma_check_dpi (sp->ydpi, s->cfg->ydpi) < 0)
1086 return PIXMA_EINVAL;
1087
1088 /* xdpi must be equal to ydpi except that
1089 xdpi = max_xdpi and ydpi = max_ydpi. */
1090 if (!(sp->xdpi == sp->ydpi ||
1091 (sp->xdpi == cfg_xdpi && sp->ydpi == s->cfg->ydpi)))
1092 return PIXMA_EINVAL;
1093
1094 if (s->ops->check_param (s, sp) < 0)
1095 return PIXMA_EINVAL;
1096
1097 /* FIXME: I assume the same minimum width and height for every model.
1098 * new scanners need minimum 16 px height
1099 * minimum image size: 16 px x 16 px */
1100 CLAMP2 (sp->x, sp->w, 16, s->cfg->width, sp->xdpi);
1101 CLAMP2 (sp->y, sp->h, 16, s->cfg->height, sp->ydpi);
1102
1103 switch (sp->source)
1104 {
1105 case PIXMA_SOURCE_FLATBED:
1106 break;
1107
1108 case PIXMA_SOURCE_TPU:
1109 if ((s->cfg->cap & PIXMA_CAP_TPU) != PIXMA_CAP_TPU)
1110 {
1111 sp->source = PIXMA_SOURCE_FLATBED;
1112 PDBG (pixma_dbg
1113 (1, "WARNING: TPU unsupported, fallback to flatbed.\n"));
1114 }
1115 break;
1116
1117 case PIXMA_SOURCE_ADF:
1118 if ((s->cfg->cap & PIXMA_CAP_ADF) != PIXMA_CAP_ADF)
1119 {
1120 sp->source = PIXMA_SOURCE_FLATBED;
1121 PDBG (pixma_dbg
1122 (1, "WARNING: ADF unsupported, fallback to flatbed.\n"));
1123 }
1124 break;
1125
1126 case PIXMA_SOURCE_ADFDUP:
1127 if ((s->cfg->cap & PIXMA_CAP_ADFDUP) != PIXMA_CAP_ADFDUP)
1128 {
1129 if (s->cfg->cap & PIXMA_CAP_ADF)
1130 {
1131 sp->source = PIXMA_SOURCE_ADF;
1132 }
1133 else
1134 {
1135 sp->source = PIXMA_SOURCE_FLATBED;
1136 }
1137 PDBG (pixma_dbg
1138 (1, "WARNING: ADF duplex unsupported, fallback to %d.\n",
1139 sp->source));
1140 }
1141 break;
1142 case PIXMA_SOURCE_NONE:
1143 /* this source can not be selected */
1144 break;
1145 }
1146
1147 if (sp->depth == 0)
1148 sp->depth = 8;
1149 if ((sp->depth % 8) != 0 && sp->depth != 1)
1150 return PIXMA_EINVAL;
1151
1152 sp->line_size = 0;
1153
1154 if (s->ops->check_param (s, sp) < 0)
1155 return PIXMA_EINVAL;
1156
1157 if (sp->line_size == 0)
1158 sp->line_size = sp->depth / 8 * sp->channels * sp->w;
1159 sp->image_size = sp->line_size * sp->h;
1160
1161 /* image_size for software lineart is counted in bits */
1162 if (sp->software_lineart == 1)
1163 sp->image_size /= 8;
1164 return 0;
1165 }
1166
1167 const char *
pixma_get_string(pixma_t * s, pixma_string_index_t i)1168 pixma_get_string (pixma_t * s, pixma_string_index_t i)
1169 {
1170 switch (i)
1171 {
1172 case PIXMA_STRING_MODEL:
1173 return s->cfg->name;
1174 case PIXMA_STRING_ID:
1175 return s->id;
1176 case PIXMA_STRING_LAST:
1177 return NULL;
1178 }
1179 return NULL;
1180 }
1181
1182 const pixma_config_t *
pixma_get_config(pixma_t * s)1183 pixma_get_config (pixma_t * s)
1184 {
1185 return s->cfg;
1186 }
1187
1188 void
pixma_fill_gamma_table(double gamma, uint8_t * table, unsigned n)1189 pixma_fill_gamma_table (double gamma, uint8_t * table, unsigned n)
1190 {
1191 unsigned i;
1192 double r_gamma = 1.0 / gamma;
1193 double in_scale = 1.0 / (n - 1);
1194
1195 /* 8-bits gamma table
1196 * for generation 1 scanners
1197 */
1198 if (n == 4096)
1199 {
1200 double out_scale = 255.0;
1201
1202 for (i = 0; (unsigned) i != n; i++)
1203 {
1204 table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5);
1205 }
1206 }
1207
1208 /* 16-bits gamma table */
1209 else
1210 {
1211 double out_scale = 65535.0;
1212 uint16_t value;
1213
1214 for (i = 0; i < n; i++)
1215 {
1216 value = (uint16_t) (out_scale * pow (i * in_scale, r_gamma) + 0.5);
1217 table[2 * i] = (uint8_t) (value & 0xff);
1218 table[2 * i + 1] = (uint8_t) (value >> 8);
1219 }
1220 }
1221 }
1222
1223 int
pixma_find_scanners(const char **conf_devices, SANE_Bool local_only)1224 pixma_find_scanners (const char **conf_devices, SANE_Bool local_only)
1225 {
1226 return pixma_collect_devices (conf_devices, pixma_devices, local_only);
1227 }
1228
1229 const char *
pixma_get_device_model(unsigned devnr)1230 pixma_get_device_model (unsigned devnr)
1231 {
1232 const pixma_config_t *cfg = pixma_get_device_config (devnr);
1233 return (cfg) ? cfg->name : NULL;
1234 }
1235
1236
1237 int
pixma_get_device_status(pixma_t * s, pixma_device_status_t * status)1238 pixma_get_device_status (pixma_t * s, pixma_device_status_t * status)
1239 {
1240 if (!status)
1241 return PIXMA_EINVAL;
1242 memset (status, 0, sizeof (*status));
1243 return s->ops->get_status (s, status);
1244 }
1245
1246 unsigned
pixma_calc_calibrate(pixma_t * p)1247 pixma_calc_calibrate (pixma_t * p)
1248 {
1249 pixma_scan_param_t * sp = p->param;
1250 if (sp->calibrate == PIXMA_CALIBRATE_ALWAYS)
1251 return 0x01;
1252 if (sp->calibrate == PIXMA_CALIBRATE_NEVER)
1253 return 0x00;
1254 /* sp->calibrate == PIXMA_CALIBRATE_ONCE */
1255 if (sp->source == PIXMA_SOURCE_ADF || sp->source == PIXMA_SOURCE_ADFDUP)
1256 return sp->adf_pageid == 0 ? 0x01 : 0x00;
1257 /* sp->source == PIXMA_SOURCE_FLATBED | TPU */
1258 return sp->source == p->last_source ? 0x00 : 0x01;
1259 }
1260
1261 #if defined(HAVE_LIBXML2)
1262 static const char *
format_xml_response(const char *resp_details)1263 format_xml_response(const char *resp_details)
1264 {
1265 if (strcmp(resp_details, "DeviceBusy") == 0)
1266 /* https://cromwell-intl.com/open-source/canon-pixma-printer-scanner.html */
1267 return "DeviceBusy - Device not initialized (yet). " \
1268 "Please check the USB power, try a different port or install the Ink Cartridges if the device supports them.";
1269 else if (strcmp(resp_details, "ScannerCarriageLockError") == 0)
1270 return "ScannerCarriageLockError - Please consult the manual to unlock the Carriage Lock.";
1271 else if (strcmp(resp_details, "PCScanning") == 0)
1272 return "PCScanning - Previous scan attempt was not completed. Try disconnecting and reconnecting the scanner. " \
1273 "If the problem persists, consider reporting it as a bug at http://www.sane-project.org/bugs.html.";
1274 else if (strcmp(resp_details, "DeviceCheckError") == 0)
1275 return "DeviceCheckError - Device detected a fault. Contact the repair center.";
1276 else
1277 return resp_details;
1278 }
1279
1280 int
pixma_parse_xml_response(const char *xml_message)1281 pixma_parse_xml_response(const char *xml_message)
1282 {
1283 int status = PIXMA_EPROTO;
1284 xmlDoc *doc = NULL;
1285 xmlNode *node = NULL;
1286 xmlChar *content = NULL;
1287
1288 doc = xmlReadMemory(xml_message, strlen(xml_message), "mem:device-resp.xml", NULL, 0);
1289 if (doc == NULL) {
1290 PDBG(pixma_dbg(10, "unable to parse xml response\n"));
1291 status = PIXMA_EINVAL;
1292 goto clean;
1293 }
1294
1295 node = xmlDocGetRootElement(doc);
1296 if (node == NULL) {
1297 status = PIXMA_EPROTO;
1298 goto clean;
1299 }
1300
1301 /* /cmd */
1302 for (; node; node = node->next) {
1303 if (strcmp((const char*)node->name, "cmd") == 0)
1304 break;
1305 }
1306 if (!node) {
1307 status = PIXMA_EPROTO;
1308 goto clean;
1309 }
1310
1311 /* /cmd/contents */
1312 for (node = node->children; node; node = node->next) {
1313 if (strcmp((const char*)node->name, "contents") == 0)
1314 break;
1315 }
1316 if (!node) {
1317 status = PIXMA_EPROTO;
1318 goto clean;
1319 }
1320
1321 /* /cmd/contents/param_set */
1322 for (node = node->children; node; node = node->next) {
1323 if (strcmp((const char*)node->name, "param_set") == 0)
1324 break;
1325 }
1326 if (!node) {
1327 status = PIXMA_EPROTO;
1328 goto clean;
1329 }
1330
1331 /* /cmd/contents/param_set/response... */
1332 for (node = node->children; node; node = node->next)
1333 {
1334 if (strcmp((const char*)node->name, "response") == 0) {
1335 content = xmlNodeGetContent(node);
1336 if (strcmp((const char*)content, "OK") == 0)
1337 status = PIXMA_STATUS_OK;
1338 else
1339 status = PIXMA_EINVAL;
1340 xmlFree(content);
1341 } else if (strcmp((const char*)node->name, "response_detail") == 0) {
1342 content = xmlNodeGetContent(node);
1343 if (strlen((const char*)content) > 0) {
1344 PDBG(pixma_dbg(0, "device response: %s\n",
1345 format_xml_response((const char*)content)));
1346 }
1347 xmlFree(content);
1348 }
1349 }
1350
1351 clean:
1352 xmlFreeDoc(doc);
1353 return status;
1354 }
1355 #endif
1356