1 /*
2 * epsonds-cmd.c - Epson ESC/I-2 routines.
3 *
4 * Copyright (C) 2015 Tower Technologies
5 * Author: Alessandro Zummo <a.zummo@towertech.it>
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, version 2.
12 */
13
14 #define DEBUG_DECLARE_ONLY
15
16 #include "sane/config.h"
17 #include <ctype.h>
18 #include <unistd.h> /* sleep */
19
20 #include "epsonds.h"
21 #include "epsonds-io.h"
22 #include "epsonds-cmd.h"
23 #include "epsonds-ops.h"
24 #include "epsonds-net.h"
25
26 static SANE_Status
esci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))27 esci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))
28 {
29 SANE_Status status = SANE_STATUS_GOOD;
30 SANE_Status delayed_status = SANE_STATUS_GOOD;
31
32
33 char *start = buf;
34 char *end = (buf + len) - 1;
35
36 /* 0 : #
37 * 1-3: param
38 * 4- : data
39 */
40
41 while (1) {
42
43 char param[4];
44
45 while (*start != '#' && start < end)
46 start++;
47
48 if (*start != '#')
49 break;
50
51 param[0] = *++start;
52 param[1] = *++start;
53 param[2] = *++start;
54 param[3] = '\0';
55
56 if (strncmp("---", param, 3) == 0)
57 break;
58
59 /* ugly hack to skip over GMT in RESA */
60 if (strncmp("GMT", param, 3) == 0 && *(start + 5) == 'h') {
61 start = start + 4 + 0x100;
62 continue;
63 }
64
65 /* find the end of the token */
66 {
67 int tlen;
68 char *next = start;
69
70 while (*next != '#' && *next != 0x00 && next < end)
71 next++;
72
73 tlen = next - start - 1;
74
75 if (cb) {
76 status = cb(userdata, start - 2, tlen);
77 if (status != SANE_STATUS_GOOD) {
78 delayed_status = status;
79 }
80 }
81
82 start = next;
83 }
84 }
85
86 if (delayed_status != SANE_STATUS_GOOD)
87 return delayed_status;
88
89 return status;
90 }
91
92 static SANE_Bool
esci2_check_header(const char *cmd, const char *buf, unsigned int *more)93 esci2_check_header(const char *cmd, const char *buf, unsigned int *more)
94 {
95 int err;
96
97 *more = 0;
98
99 if (strncmp(cmd, buf, 4) != 0) {
100
101 if (strncmp("UNKN", buf, 4) == 0) {
102 DBG(1, "UNKN reply code received\n");
103 } else if (strncmp("INVD", buf, 4) == 0) {
104 DBG(1, "INVD reply code received\n");
105 } else {
106 DBG(1, "%c%c%c%c, unexpected reply code\n", buf[0], buf[1], buf[2], buf[3]);
107 }
108
109 return 0;
110 }
111
112 /* INFOx0000100#.... */
113
114 /* read the answer len */
115 if (buf[4] != 'x') {
116 DBG(1, "unknown type in header: %c\n", buf[4]);
117 return 0;
118 }
119
120 err = sscanf(&buf[5], "%7x#", more);
121 if (err != 1) {
122 DBG(1, "cannot decode length from header\n");
123 return 0;
124 }
125
126 return 1;
127 }
128
esci2_cmd(epsonds_scanner* s, char *cmd, size_t len, char *payload, size_t plen, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))129 static SANE_Status esci2_cmd(epsonds_scanner* s,
130 char *cmd, size_t len,
131 char *payload, size_t plen,
132 void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))
133 {
134 SANE_Status status;
135 unsigned int more;
136 char header[13], rbuf[64]; /* add one more byte for header buffer to correct buffer overflow issue,*/
137 char *buf;
138
139 DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen);
140
141 memset(header, 0x00, sizeof(header));
142 memset(rbuf, 0x00, sizeof(rbuf));
143
144 // extra safety check, will not happen
145 if (len != 12) {
146 DBG(1, "%s: command has wrong size (%lu != 12)\n", __func__, len);
147 return SANE_STATUS_INVAL;
148 }
149
150 // merge ParameterBlock size
151 sprintf(header, "%4.4sx%07x", cmd, (unsigned int)plen);
152
153 // send RequestBlock, request immediate response if there's no payload
154 status = eds_txrx(s, header, len, rbuf, (plen > 0) ? 0 : 64);
155
156 /* pointer to the token's value */
157 buf = rbuf + 12;
158 /* nrd / nrdBUSY */
159 DBG(8, "buf = %s\n",buf);
160 if (strncmp("#nrd", buf, 4) == 0) {
161 buf += 4;
162 DBG(8, "buf = %s\n",buf);
163 if (strncmp("BUSY", buf, 4) == 0) {
164 DBG(8, "device busy\n");
165 DBG(8, "SANE_STATUS:%d\n", SANE_STATUS_DEVICE_BUSY);
166 return SANE_STATUS_DEVICE_BUSY;
167 }
168 }
169
170 if (status != SANE_STATUS_GOOD) {
171 return status;
172 }
173
174 /* send ParameterBlock, request response */
175 if (plen) {
176
177 DBG(8, " %12.12s (%lu)\n", header, plen);
178
179 status = eds_txrx(s, payload, plen, rbuf, 64);
180 if (status != SANE_STATUS_GOOD) {
181 return status;
182 }
183 }
184
185 /* rxbuf holds the DataHeaderBlock, which should be
186 * parsed to know if we need to read more data
187 */
188 if (!esci2_check_header(cmd, rbuf, &more)) {
189 return SANE_STATUS_IO_ERROR;
190 }
191
192 /* parse the received header block */
193 if (cb) {
194 status = esci2_parse_block(rbuf + 12, 64 - 12, userdata, cb);
195 if (status != SANE_STATUS_GOOD && status != SANE_STATUS_DEVICE_BUSY) {
196 DBG(1, "%s: %4s error while parsing received header\n", __func__, cmd);
197 }
198 }
199
200 /* header valid, get the data block if present */
201 if (more) {
202
203 char *pbuf = malloc(more);
204 if (pbuf) {
205
206 if (s->hw->connection == SANE_EPSONDS_NET) {
207 epsonds_net_request_read(s, more);
208 }
209
210 ssize_t read = eds_recv(s, pbuf, more, &status);
211 if (read != more) {
212 free(pbuf);
213 return SANE_STATUS_IO_ERROR;
214 }
215
216 /* parse the received data block */
217 if (cb) {
218 status = esci2_parse_block(pbuf, more, userdata, cb);
219 if (status != SANE_STATUS_GOOD) {
220 DBG(1, "%s: %4s error while parsing received data block\n", __func__, cmd);
221 }
222 }
223
224 free(pbuf);
225
226 } else {
227 return SANE_STATUS_NO_MEM;
228 }
229 }
230
231 return status;
232 }
233
esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status (*cb)(void *userdata, char *token, int len))234 static SANE_Status esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status (*cb)(void *userdata, char *token, int len))
235 {
236 return esci2_cmd(s, cmd, 12, NULL, 0, s, cb);
237 }
238
esci2_fin(epsonds_scanner *s)239 SANE_Status esci2_fin(epsonds_scanner *s)
240 {
241 SANE_Status status;
242
243 DBG(5, "%s\n", __func__);
244
245 status = esci2_cmd_simple(s, "FIN x0000000", NULL);
246
247 for(int i = 0; i < 10; i++) {
248
249 if(status == SANE_STATUS_DEVICE_BUSY || status == SANE_STATUS_IO_ERROR) {
250 status = esci2_cmd_simple(s, "FIN x0000000", NULL);
251 }
252 else {
253 DBG(1, "break\n");
254 break;
255 }
256 DBG(1, "sleep(5)\n");
257 sleep(5);
258
259 }
260
261 s->locked = 0;
262 return status;
263 }
264
esci2_can(epsonds_scanner *s)265 SANE_Status esci2_can(epsonds_scanner *s)
266 {
267 return esci2_cmd_simple(s, "CAN x0000000", NULL);
268 }
269
decode_value(char *buf, int len)270 static int decode_value(char *buf, int len)
271 {
272 char tmp[10];
273
274 memcpy(tmp, buf, len);
275 tmp[len] = '\0';
276
277 if (buf[0] == 'd' && len == 4) {
278 return strtol(buf + 1, NULL, 10);
279 } else if (buf[0] == 'i' && len == 8) {
280 return strtol(buf + 1, NULL, 10);
281 } else if (buf[0] == 'x' && len == 8) {
282 return strtol(buf + 1, NULL, 16);
283 } else if (buf[0] == 'h' && len == 4) {
284 return strtol(buf + 1, NULL, 16);
285 }
286
287 return -1;
288 }
289
290 /* h000 */
decode_binary(char *buf, int len)291 static char *decode_binary(char *buf, int len)
292 {
293 char tmp[6];
294 int hl;
295
296 memcpy(tmp, buf, 4);
297 tmp[4] = '\0';
298
299 if (buf[0] != 'h')
300 return NULL;
301
302 hl = strtol(tmp + 1, NULL, 16);
303 if (hl > len)
304 hl = len;
305 if (hl) {
306
307 char *v = malloc(hl + 1);
308 memcpy(v, buf + 4, hl);
309 v[hl] = '\0';
310
311 return v;
312 }
313
314 return NULL;
315 }
316
decode_string(char *buf, int len)317 static char *decode_string(char *buf, int len)
318 {
319 char *p, *s = decode_binary(buf, len);
320 if (s == NULL)
321 return NULL;
322
323 /* trim white space at the end */
324 p = s + strlen(s);
325 while (*--p == ' ')
326 *p = '\0';
327
328 return s;
329 }
330
debug_token(int level, const char *func, char *token, int len)331 static void debug_token(int level, const char *func, char *token, int len)
332 {
333 char *tdata = malloc(len + 1);
334 memcpy(tdata, token + 3, len);
335 tdata[len] = '\0';
336
337 DBG(level, "%s: %3.3s / %s / %d\n", func, token, tdata, len);
338
339 free(tdata);
340 }
341
info_cb(void *userdata, char *token, int len)342 static SANE_Status info_cb(void *userdata, char *token, int len)
343 {
344 epsonds_scanner *s = (epsonds_scanner *)userdata;
345 char *value;
346
347
348 /* pointer to the token's value */
349 value = token + 3;
350
351 /* nrd / nrdBUSY */
352
353 if (strncmp("nrd", token, 3) == 0) {
354 if (strncmp("BUSY", value, 4) == 0) {
355 return SANE_STATUS_DEVICE_BUSY;
356 }
357 }
358
359 if (strncmp("PRD", token, 3) == 0) {
360 free(s->hw->model);
361 s->hw->model = decode_string(value, len);
362 s->hw->sane.model = s->hw->model;
363 DBG(1, " product: %s\n", s->hw->model);
364 }
365
366 if (strncmp("VER", token, 3) == 0) {
367 char *v = decode_string(value, len);
368 DBG(1, " version: %s\n", v);
369 free(v);
370 }
371
372 if (strncmp("S/N", token, 3) == 0) {
373 char *v = decode_string(value, len);
374 DBG(1, " serial: %s\n", v);
375 free(v);
376 }
377
378 if (strncmp("ADF", token, 3) == 0) {
379
380 s->hw->has_adf = 1;
381
382 if (len == 8) {
383
384 if (strncmp("TYPEPAGE", value, len) == 0) {
385 DBG(1, " ADF: page type\n");
386 }
387
388 if (strncmp("TYPEFEED", value, len) == 0) {
389 DBG(1, " ADF: sheet feed type\n");
390 }
391
392 if (strncmp("DPLX1SCN", value, len) == 0) {
393 DBG(1, " ADF: duplex single pass\n");
394 s->hw->adf_singlepass = 1;
395 }
396
397 if (strncmp("DPLX2SCN", value, len) == 0) {
398 DBG(1, " ADF: duplex double pass\n");
399 s->hw->adf_singlepass = 0;
400 }
401
402 if (strncmp("FORDPF1N", value, len) == 0) {
403 DBG(1, " ADF: order is 1 to N\n");
404 }
405
406 if (strncmp("FORDPFN1", value, len) == 0) {
407 DBG(1, " ADF: order is N to 1\n");
408 }
409
410 if (strncmp("ALGNLEFT", value, len) == 0) {
411 DBG(1, " ADF: left aligned\n");
412 s->hw->adf_alignment = 0;
413 }
414
415 if (strncmp("ALGNCNTR", value, len) == 0) {
416 DBG(1, " ADF: center aligned\n");
417 s->hw->adf_alignment = 1;
418 }
419
420 if (strncmp("ALGNRIGT", value, len) == 0) {
421 DBG(1, " ADF: right aligned (not supported!)\n");
422 s->hw->adf_alignment = 2;
423 }
424 }
425
426 if (len == 4) {
427
428 if (strncmp("PREF", value, len) == 0) {
429 DBG(1, " ADF: auto pre-feed\n");
430 }
431
432 if (strncmp("ASCN", value, len) == 0) {
433 DBG(1, " ADF: auto scan\n");
434 }
435
436 if (strncmp("RCVR", value, len) == 0) {
437 DBG(1, " ADF: auto recovery\n");
438 }
439 }
440
441 if (len == 20) {
442
443 /* ADFAREAi0000850i0001400 */
444
445 if (strncmp("AREA", value, 4) == 0) {
446
447 int min = decode_value(value + 4, 8);
448 int max = decode_value(value + 4 + 8, 8);
449
450 DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max);
451 eds_set_adf_area(s->hw, min, max, 100);
452 }
453
454 if (strncmp("AMIN", value, 4) == 0) {
455
456 int min = decode_value(value + 4, 8);
457 int max = decode_value(value + 4 + 8, 8);
458
459 DBG(1, " ADF: min %dx%d @ 100dpi\n", min, max);
460 }
461
462 if (strncmp("AMAX", value, 4) == 0) {
463
464 int min = decode_value(value + 4, 8);
465 int max = decode_value(value + 4 + 8, 8);
466
467 DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max);
468 }
469 }
470
471
472
473
474
475
476 if (len == 16) {
477
478 if (strncmp("AREA", value, 4) == 0) {
479
480 int min = decode_value(value + 4, 4);
481 int max = decode_value(value + 4 + 4, 8);
482
483 DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max);
484
485 eds_set_adf_area(s->hw, min, max, 100);
486 }
487
488 if (strncmp("AMAX", value, 4) == 0) {
489
490 // d
491 int min = decode_value(value + 4, 4);
492 // i
493 int max = decode_value(value + 4 + 4, 8);
494
495 DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max);
496 }
497 }
498
499
500
501
502 if (len == 12) {
503
504 /* RESOi0000600 */
505
506 if (strncmp("RESO", value, 4) == 0) {
507
508 int res = decode_value(value + 4, 8);
509
510 DBG(1, " ADF: basic resolution is %d dpi\n", res);
511 }
512
513 /* OVSNd025d035 */
514
515 if (strncmp("OVSN", value, 4) == 0) {
516
517 int x = decode_value(value + 4, 4);
518 int y = decode_value(value + 4 + 4, 4);
519
520 DBG(1, " ADF: overscan %dx%d @ 100dpi\n", x, y);
521 }
522 }
523 }
524
525 if (strncmp("FB ", token, 3) == 0) {
526
527 s->hw->has_fb = 1;
528
529 if (len == 20) {
530
531 /* AREAi0000850i0001400 */
532 if (strncmp("AREA", value, 4) == 0) {
533
534 int min = decode_value(value + 4, 8);
535 int max = decode_value(value + 4 + 8, 8);
536
537 DBG(1, " FB: area %dx%d @ 100dpi\n", min, max);
538
539 eds_set_fbf_area(s->hw, min, max, 100);
540 }
541 }
542
543
544 if (len == 16) {
545
546 /* AREAi0000850i0001400 */
547 if (strncmp("AREA", value, 4) == 0) {
548 //d
549 int min = decode_value(value + 4, 4);
550 //i
551 int max = decode_value(value + 4 + 4, 8);
552
553 DBG(1, " FB: area %dx%d @ 100dpi\n", min, max);
554
555 eds_set_fbf_area(s->hw, min, max, 100);
556 }
557 }
558
559 if (len == 8) {
560
561 if (strncmp("ALGNLEFT", value, len) == 0) {
562 DBG(1, " FB: left aligned\n");
563 s->hw->fbf_alignment = 0;
564 }
565
566 if (strncmp("ALGNCNTR", value, len) == 0) {
567 DBG(1, " FB: center aligned\n");
568 s->hw->fbf_alignment = 1;
569 }
570
571 if (strncmp("ALGNRIGT", value, len) == 0) {
572 DBG(1, " FB: right aligned (not supported!)\n");
573 s->hw->fbf_alignment = 2;
574 }
575 }
576
577 if (len == 12) {
578
579 /* RESOi0000600 */
580
581 if (strncmp("RESO", value, 4) == 0) {
582
583 int res = decode_value(value + 4, 8);
584
585 DBG(1, " FB: basic resolution is %d dpi\n", res);
586 }
587
588 /* OVSNd025d035 */
589
590 if (strncmp("OVSN", value, 4) == 0) {
591
592 int x = decode_value(value + 4, 4);
593 int y = decode_value(value + 4 + 4, 4);
594
595 DBG(1, " FB: overscan %dx%d @ 100dpi\n", x, y);
596 }
597 }
598
599 if (len == 4) {
600
601 if (strncmp("DETX", value, len) == 0) {
602 DBG(1, " FB: paper width detection\n");
603 }
604
605 if (strncmp("DETY", value, len) == 0) {
606 DBG(1, " FB: paper height detection\n");
607 }
608 }
609 }
610
611 return SANE_STATUS_GOOD;
612 }
613
esci2_info(epsonds_scanner *s)614 SANE_Status esci2_info(epsonds_scanner *s)
615 {
616 SANE_Status status;
617 int i = 4;
618
619 DBG(1, "= gathering device information\n");
620
621 do {
622 status = esci2_cmd_simple(s, "INFOx0000000", &info_cb);
623 if (status == SANE_STATUS_DEVICE_BUSY) {
624 sleep(2);
625 }
626
627 i--;
628
629 } while (status == SANE_STATUS_DEVICE_BUSY && i);
630
631 return status;
632 }
633
634 /* CAPA */
635
capa_cb(void *userdata, char *token, int len)636 static SANE_Status capa_cb(void *userdata, char *token, int len)
637 {
638 epsonds_scanner *s = (epsonds_scanner *)userdata;
639
640 char *value = token + 3;
641
642 if (DBG_LEVEL >= 11) {
643 debug_token(DBG_LEVEL, __func__, token, len);
644 }
645
646 if (len == 4) {
647
648 if (strncmp("ADFDPLX", token, 3 + 4) == 0) {
649 DBG(1, " ADF: duplex\n");
650 s->hw->adf_is_duplex = 1;
651 }
652
653 if (strncmp("ADFSKEW", token, 3 + 4) == 0) {
654 DBG(1, " ADF: skew correction\n");
655 s->hw->adf_has_skew = 1;
656 }
657
658 if (strncmp("ADFOVSN", token, 3 + 4) == 0) {
659 DBG(1, " ADF: overscan\n");
660 }
661
662 if (strncmp("ADFPEDT", token, 3 + 4) == 0) {
663 DBG(1, " ADF: paper end detection\n");
664 }
665
666 if (strncmp("ADFLOAD", token, 3 + 4) == 0) {
667 DBG(1, " ADF: paper load\n");
668 s->hw->adf_has_load = 1;
669 }
670
671 if (strncmp("ADFEJCT", token, 3 + 4) == 0) {
672 DBG(1, " ADF: paper eject\n");
673 s->hw->adf_has_eject = 1;
674 }
675
676 if (strncmp("ADFCRP ", token, 3 + 4) == 0) {
677 DBG(1, " ADF: image cropping\n");
678 s->hw->adf_has_crp = 1;
679 }
680
681 if (strncmp("ADFFAST", token, 3 + 4) == 0) {
682 DBG(1, " ADF: fast mode available\n");
683 }
684
685 if (strncmp("ADFDFL1", token, 3 + 4) == 0) {
686 DBG(1, " ADF: double feed detection\n");
687 s->hw->adf_has_dfd = 1;
688 }
689 }
690
691 if (len == 8 && strncmp("ADFDFL1DFL2", token, 3 + 4) == 0) {
692 DBG(1, " ADF: double feed detection (high sensitivity)\n");
693 s->hw->adf_has_dfd = 2;
694 }
695
696 if (strncmp("FMT", token, 3) == 0) {
697
698 /* a bit ugly... */
699
700 if (len >= 8) {
701 if (strncmp("RAW ", value + 4, 4) == 0) {
702 s->hw->has_raw = 1;
703 }
704 }
705
706 if (len >= 12) {
707 if (strncmp("RAW ", value + 8, 4) == 0) {
708 s->hw->has_raw = 1;
709 }
710 }
711 }
712
713
714 if (strncmp("COLLIST", token, 3 + 4) == 0)
715 {
716 char *p = token + 3 + 4;
717 int count = (len - 4);
718 int readBytes = 0;
719 s->hw->has_mono = 0;
720 while (readBytes < count) {
721 if (strncmp(p, "M001", 4) == 0)
722 {
723 s->hw->has_mono = 1;
724 }
725 readBytes+=4;
726 p+=4;
727 }
728 }
729
730 /* RSMRANGi0000050i0000600 */
731
732 if (strncmp("RSMRANG", token, 3 + 4) == 0) {
733
734 char *p = token + 3 + 4;
735
736 if (p[0] == 'i') {
737
738 int min = decode_value(p, 8);
739 int max = decode_value(p + 8, 8);
740
741 eds_set_resolution_range(s->hw, min, max);
742
743 DBG(1, "resolution min/max %d/%d\n", min, max);
744 }
745 }
746
747 /* RSMLISTi0000300i0000600 */
748
749 if (strncmp("RSMLIST", token, 3 + 4) == 0) {
750
751 char *p = token + 3 + 4;
752
753
754 int count = (len - 4);
755 int readBytes = 0;
756
757 while (readBytes < count) {
758 if(*p == 'i')
759 {
760 eds_add_resolution(s->hw, decode_value(p, 8));
761 p += 8;
762 readBytes += 8;
763 }else if(*p == 'd')
764 {
765 eds_add_resolution(s->hw, decode_value(p, 4));
766 p += 4;
767 readBytes +=4;
768 }
769 }
770
771 }
772
773 return SANE_STATUS_GOOD;
774 }
775
esci2_capa(epsonds_scanner *s)776 SANE_Status esci2_capa(epsonds_scanner *s)
777 {
778 return esci2_cmd_simple(s, "CAPAx0000000", &capa_cb);
779 }
780
781 /* STAT */
782
stat_cb(void *userdata, char *token, int len)783 static SANE_Status stat_cb(void *userdata, char *token, int len)
784 {
785 char *value = token + 3;
786
787 (void) userdata;
788
789 if (DBG_LEVEL >= 11) {
790 debug_token(DBG_LEVEL, __func__, token, len);
791 }
792
793 if (strncmp("ERR", token, 3) == 0) {
794 if (strncmp("ADF PE ", value, len) == 0) {
795 DBG(1, " PE : paper empty\n");
796 return SANE_STATUS_NO_DOCS;
797 }
798
799 if (strncmp("ADF OPN", value, len) == 0) {
800 DBG(1, " conver open\n");
801 return SANE_STATUS_COVER_OPEN;
802 }
803 }
804
805 return SANE_STATUS_GOOD;
806 }
807
esci2_stat(epsonds_scanner *s)808 SANE_Status esci2_stat(epsonds_scanner *s)
809 {
810 return esci2_cmd_simple(s, "STATx0000000", &stat_cb);
811 }
812
813 /* RESA */
814
resa_cb(void *userdata, char *token, int len)815 static SANE_Status resa_cb(void *userdata, char *token, int len)
816 {
817 /* epsonds_scanner *s = (epsonds_scanner *)userdata; */
818
819 (void) userdata;
820
821 if (DBG_LEVEL >= 11) {
822 debug_token(DBG_LEVEL, __func__, token, len);
823 }
824
825 return SANE_STATUS_GOOD;
826 }
827
esci2_resa(epsonds_scanner *s)828 SANE_Status esci2_resa(epsonds_scanner *s)
829 {
830 return esci2_cmd_simple(s, "RESAx0000000", &resa_cb);
831 }
832
833 /* PARA */
834
para_cb(void *userdata, char *token, int len)835 static SANE_Status para_cb(void *userdata, char *token, int len)
836 {
837 if (DBG_LEVEL >= 11) {
838 debug_token(DBG_LEVEL, __func__, token, len);
839 }
840
841 (void) userdata;
842
843 if (strncmp("par", token, 3) == 0) {
844 if (strncmp("FAIL", token + 3, 4) == 0) {
845 DBG(1, "%s: parameter setting failed\n", __func__);
846 return SANE_STATUS_INVAL;
847 }
848 }
849
850 return SANE_STATUS_GOOD;
851 }
852
esci2_para(epsonds_scanner *s, char *parameters, int len)853 SANE_Status esci2_para(epsonds_scanner *s, char *parameters, int len)
854 {
855 DBG(8, "%s: %s\n", __func__, parameters);
856 return esci2_cmd(s, "PARAx0000000", 12, parameters, len, NULL, ¶_cb);
857 }
858
esci2_mech(epsonds_scanner *s, char *parameters)859 SANE_Status esci2_mech(epsonds_scanner *s, char *parameters)
860 {
861 DBG(8, "%s: %s\n", __func__, parameters);
862 return esci2_cmd(s, "MECHx0000000", 12, parameters, strlen(parameters), NULL, ¶_cb);
863 }
864
esci2_trdt(epsonds_scanner *s)865 SANE_Status esci2_trdt(epsonds_scanner *s)
866 {
867 return esci2_cmd_simple(s, "TRDTx0000000", NULL);
868 }
869
870
img_cb(void *userdata, char *token, int len)871 static SANE_Status img_cb(void *userdata, char *token, int len)
872 {
873 struct epsonds_scanner *s = userdata;
874
875 if (DBG_LEVEL >= 11) {
876 debug_token(DBG_LEVEL, __func__, token, len);
877 }
878
879 /* psti0000256i0000000i0000945 / 24 */
880
881 /* integer comparison first so it's faster */
882 if (len == 24 && strncmp("pst", token, 3) == 0) {
883
884 s->dummy = decode_value(token + 3 + 8, 8);
885
886 DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
887 __func__,
888 decode_value(token + 3, 8),
889 decode_value(token + 3 + 8 + 8, 8),
890 s->dummy);
891
892 return SANE_STATUS_GOOD;
893 }
894
895 if (len == 12 && strncmp("pst", token, 3) == 0) {
896
897 s->dummy = decode_value(token + 3 + 4, 4);
898
899 DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
900 __func__,
901 decode_value(token + 3, 4),
902 decode_value(token + 3 + 4 + 4, 4),
903 s->dummy);
904
905 return SANE_STATUS_GOOD;
906 }
907
908 if (len == 16 && strncmp("pst", token, 3) == 0) {
909
910 s->dummy = decode_value(token + 3 + 4, 4);
911
912 DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
913 __func__,
914 decode_value(token + 3, 4),
915 decode_value(token + 3 + 4 + 4, 8),
916 s->dummy);
917
918 return SANE_STATUS_GOOD;
919 }
920
921 if (len == 20 && strncmp("pst", token, 3) == 0) {
922
923 s->dummy = decode_value(token + 3 + 8, 4);
924
925 DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
926 __func__,
927 decode_value(token + 3, 8),
928 decode_value(token + 3 + 8 + 4, 8),
929 s->dummy);
930
931 return SANE_STATUS_GOOD;
932 }
933
934
935 // i0001696i0002347
936 if (len == 16 && strncmp("pen", token, 3) == 0) {
937 DBG(10, "%s: page end\n", __func__);
938 s->eof = 1;
939 if (s->isflatbedScan)
940 {
941 s->scanning = 0;
942 }
943 DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
944 __func__,
945 decode_value(token + 3, 8),
946 decode_value(token + 3 + 8, 8),
947 s->dummy);
948 s->width_temp = decode_value(token + 3, 8);
949 s->height_temp = decode_value(token + 3 + 8, 8);
950 return SANE_STATUS_EOF;
951 }
952
953 // d696i0002347
954 if (len == 12 && strncmp("pen", token, 3) == 0) {
955 DBG(10, "%s: page end\n", __func__);
956 s->eof = 1;
957 if (s->isflatbedScan)
958 {
959 s->scanning = 0;
960 }
961
962 DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
963 __func__,
964 decode_value(token + 3, 4),
965 decode_value(token + 3 + 4, 8),
966 s->dummy);
967
968 s->width_temp = decode_value(token + 3, 4);
969 s->height_temp = decode_value(token + 3 + 4, 8);
970 return SANE_STATUS_EOF;
971 }
972
973 // d696d2347
974 if (len == 8 && strncmp("pen", token, 3) == 0) {
975 DBG(10, "%s: page end\n", __func__);
976 s->eof = 1;
977 if (s->isflatbedScan)
978 {
979 s->scanning = 0;
980 }
981 DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
982 __func__,
983 decode_value(token + 3, 4),
984 decode_value(token + 3 + 4, 4),
985 s->dummy);
986
987 s->width_temp = decode_value(token + 3, 4);
988 s->height_temp = decode_value(token + 3 + 4, 4);
989
990 return SANE_STATUS_EOF;
991 }
992
993
994 /* typIMGA or typIMGB */
995 if (len == 4 && strncmp("typ", token, 3) == 0) {
996
997 if (token[6] == 'B')
998 s->backside = 1;
999 else
1000 s->backside = 0;
1001
1002 return SANE_STATUS_GOOD;
1003 }
1004
1005 if (strncmp("err", token, 3) == 0) {
1006
1007 char *option = token + 3; /* ADF, TPU, FB */
1008 char *cause = token + 3 + 4; /* OPN, PJ, PE, ERR, LTF, LOCK, DFED, DTCL, AUT, PERM */
1009
1010 s->scanning = 0;
1011 s->scanEnd = 1;
1012
1013 DBG(1, "%s: error on option %3.3s, cause %4.4s\n",
1014 __func__, option, cause);
1015
1016 if (cause[0] == 'P' && cause[1] == 'J')
1017 return SANE_STATUS_JAMMED;
1018
1019 if (cause[0] == 'P' && cause[1] == 'E')
1020 return SANE_STATUS_NO_DOCS;
1021
1022 if (cause[0] == 'O' && cause[1] == 'P' && cause[2] == 'N')
1023 return SANE_STATUS_COVER_OPEN;
1024
1025 return SANE_STATUS_IO_ERROR;
1026 }
1027
1028 if (len == 4 && strncmp("atnCAN ", token, 3 + 4) == 0) {
1029 DBG(1, "%s: cancel request\n", __func__);
1030 s->canceling = 1;
1031 s->scanning = 0;
1032 return SANE_STATUS_CANCELLED;
1033 }
1034
1035 if (len == 4 && strncmp("lftd000", token, 3 + 4) == 0) {
1036 DBG(1, "%s:lft ok\n", __func__);
1037 s->scanEnd = 1;
1038 s->scanning = 0;
1039 }
1040
1041 return SANE_STATUS_GOOD;
1042 }
1043
1044
1045 SANE_Status
esci2_img(struct epsonds_scanner *s, SANE_Int *length)1046 esci2_img(struct epsonds_scanner *s, SANE_Int *length)
1047 {
1048 SANE_Status status = SANE_STATUS_GOOD;
1049 SANE_Status parse_status;
1050 unsigned int more;
1051 ssize_t read;
1052
1053 DBG(15, "esci2_img start\n");
1054
1055 *length = 0;
1056
1057 if (s->canceling)
1058 return SANE_STATUS_CANCELLED;
1059
1060 /* request image data */
1061 eds_send(s, "IMG x0000000", 12, &status, 64);
1062 if (status != SANE_STATUS_GOOD) {
1063 return status;
1064 }
1065 DBG(15, "request img OK\n");
1066
1067 /* receive DataHeaderBlock */
1068 memset(s->buf, 0x00, 64);
1069 eds_recv(s, s->buf, 64, &status);
1070 if (status != SANE_STATUS_GOOD) {
1071 return status;
1072 }
1073 DBG(15, "receive img OK\n");
1074
1075 /* check if we need to read any image data */
1076 more = 0;
1077 if (!esci2_check_header("IMG ", (char *)s->buf, &more)) {
1078 return SANE_STATUS_IO_ERROR;
1079 }
1080
1081 /* this handles eof and errors */
1082 parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb);
1083
1084 if (s->backside)
1085 {
1086 s->width_back = s->width_temp;
1087 s->height_back = s->height_temp;
1088 }else{
1089 s->width_front = s->width_temp;
1090 s->height_front = s->height_temp;
1091
1092 }
1093
1094
1095 /* no more data? return using the status of the esci2_parse_block
1096 * call, which might hold other error conditions.
1097 */
1098 if (!more) {
1099 return parse_status;
1100 }
1101
1102 /* more data than was accounted for in s->buf */
1103 if (more > s->bsz) {
1104 return SANE_STATUS_IO_ERROR;
1105 }
1106 /* ALWAYS read image data */
1107 if (s->hw->connection == SANE_EPSONDS_NET) {
1108 epsonds_net_request_read(s, more);
1109 }
1110
1111 read = eds_recv(s, s->buf, more, &status);
1112 if (status != SANE_STATUS_GOOD) {
1113 return status;
1114 }
1115
1116 if (read != more) {
1117 return SANE_STATUS_IO_ERROR;
1118 }
1119
1120 /* handle esci2_parse_block errors */
1121 if (parse_status != SANE_STATUS_GOOD) {
1122 return parse_status;
1123 }
1124
1125 DBG(15, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status);
1126
1127 *length = read;
1128
1129 if (s->canceling) {
1130 return SANE_STATUS_CANCELLED;
1131 }
1132
1133 return SANE_STATUS_GOOD;
1134 }
1135