1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 2002 Max Vorobiev <pcwizard@telecoms.sins.ru>
3 This file is part of the SANE package.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18 As a special exception, the authors of SANE give permission for
19 additional uses of the libraries contained in this release of SANE.
20
21 The exception is that, if you link a SANE library with other files
22 to produce an executable, this does not by itself cause the
23 resulting executable to be covered by the GNU General Public
24 License. Your use of that executable is in no way restricted on
25 account of linking the SANE library code into it.
26
27 This exception does not, however, invalidate any other reasons why
28 the executable file might be covered by the GNU General Public
29 License.
30
31 If you submit changes to SANE to the maintainers to be included in
32 a subsequent release, you agree by submitting the changes that
33 those changes may be distributed with this exception intact.
34
35 If you write modifications of your own for SANE, it is your choice
36 whether to permit this exception to apply to your modifications.
37 If you do not wish that, delete this exception notice. */
38
39 #define BUILD 3
40
41 #define BACKEND_NAME hpsj5s
42 #define HPSJ5S_CONFIG_FILE "hpsj5s.conf"
43
44 #include "../include/sane/config.h"
45 #include "../include/sane/sane.h"
46 #include "../include/sane/sanei.h"
47 #include "../include/sane/saneopts.h"
48
49 #include "../include/sane/sanei_config.h"
50 #include "../include/sane/sanei_backend.h"
51
52 #include "hpsj5s.h"
53
54 #include <string.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <unistd.h>
58
59
60 #define LINES_TO_FEED 480 /*Default feed length */
61
62 static int scanner_d = -1; /*This is handler to the only-supported. Will be fixed. */
63 static char scanner_path[PATH_MAX] = ""; /*String for device-file */
64 static SANE_Byte bLastCalibration; /*Here we store calibration result */
65 static SANE_Byte bCalibration; /*Here we store new calibration value */
66 static SANE_Byte bHardwareState; /*Here we store copy of hardware flags register */
67
68 /*Here we store Parameters:*/
69 static SANE_Word wWidth = 2570; /*Scan area width */
70 static SANE_Word wResolution = 300; /*Resolution in DPI */
71 static SANE_Frame wCurrentFormat = SANE_FRAME_GRAY; /*Type of colors in image */
72 static SANE_Int wCurrentDepth = 8; /*Bits per pixel in image */
73
74 /*Here we count lines of every new image...*/
75 static SANE_Word wVerticalResolution;
76
77 /*Limits for resolution control*/
78 static const SANE_Range ImageWidthRange = {
79 0, /*minimal */
80 2570, /*maximum */
81 2 /*quant */
82 };
83
84 static const SANE_Word ImageResolutionsList[] = {
85 6, /*Number of resolutions */
86 75,
87 100,
88 150,
89 200,
90 250,
91 300
92 };
93
94 static SANE_Option_Descriptor sod[] = {
95 { /*Number of options */
96 SANE_NAME_NUM_OPTIONS,
97 SANE_TITLE_NUM_OPTIONS,
98 SANE_DESC_NUM_OPTIONS,
99 SANE_TYPE_INT,
100 SANE_UNIT_NONE,
101 sizeof (SANE_Word),
102 SANE_CAP_SOFT_DETECT,
103 SANE_CONSTRAINT_NONE,
104 {NULL} /*No constraints required */
105 }
106 ,
107 { /*Width of scanned area */
108 "width",
109 "Width",
110 "Width of area to scan",
111 SANE_TYPE_INT,
112 SANE_UNIT_PIXEL,
113 sizeof (SANE_Word),
114 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
115 SANE_CONSTRAINT_RANGE,
116 {NULL} /*Range constraint set in sane_init */
117 }
118 ,
119 { /*Resolution for scan */
120 "resolution",
121 "Resolution",
122 "Image resolution",
123 SANE_TYPE_INT,
124 SANE_UNIT_DPI,
125 sizeof (SANE_Word),
126 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
127 SANE_CONSTRAINT_WORD_LIST,
128 {NULL} /*Word list constraint set in sane_init */
129 }
130 };
131
132 static SANE_Parameters parms;
133
134 /*Recalculate Length in dependence of resolution*/
135 static SANE_Word
LengthForRes(SANE_Word Resolution,SANE_Word Length)136 LengthForRes (SANE_Word Resolution, SANE_Word Length)
137 {
138 switch (Resolution)
139 {
140 case 75:
141 return Length / 4;
142 case 100:
143 return Length / 3;
144 case 150:
145 return Length / 2;
146 case 200:
147 return Length * 2 / 3;
148 case 250:
149 return Length * 5 / 6;
150 case 300:
151 default:
152 return Length;
153 }
154 }
155
156 static struct parport_list pl; /*List of detected parallel ports. */
157
158 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)159 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
160 {
161 char line[PATH_MAX]; /*Line from config file */
162 FILE *config_file; /*Handle to config file of this backend */
163
164 DBG_INIT ();
165 DBG (1, ">>sane_init");
166 DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
167 version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
168 DBG (1, "sane_init: SANE hpsj5s backend version %d.%d.%d\n",
169 SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
170
171 /*Inform about supported version */
172 if (version_code)
173 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
174
175 /*Open configuration file for this backend */
176 config_file = sanei_config_open (HPSJ5S_CONFIG_FILE);
177
178 if (!config_file) /*Failed to open config file */
179 {
180 DBG (1, "sane_init: no config file found.");
181 return SANE_STATUS_GOOD;
182 }
183
184 /*Read line by line */
185 while (sanei_config_read (line, PATH_MAX, config_file))
186 {
187 if ((line[0] == '#') || (line[0] == '\0')) /*comment line or empty line */
188 continue;
189 strcpy (scanner_path, line); /*so, we choose last in file (uncommented) */
190 }
191
192 fclose (config_file); /*We don't need config file any more */
193
194 /*sanei_config_attach_matching_devices(devname, attach_one); To do latter */
195
196 scanner_d = -1; /*scanner device not opened yet. */
197 DBG (1, "<<sane_init");
198
199 /*Init params structure with defaults values: */
200 wCurrentFormat = SANE_FRAME_GRAY;
201 wCurrentDepth = 8;
202 wWidth = 2570;
203 wResolution = 300;
204
205 /*Setup some option descriptors */
206 sod[1].constraint.range = &ImageWidthRange; /*Width option */
207 sod[2].constraint.word_list = &ImageResolutionsList[0]; /*Resolution option */
208
209 /*Search for ports in system: */
210 ieee1284_find_ports (&pl, 0);
211
212 return SANE_STATUS_GOOD;
213 }
214
215 void
sane_exit(void)216 sane_exit (void)
217 {
218 if (scanner_d != -1)
219 {
220 CloseScanner (scanner_d);
221 scanner_d = -1;
222 }
223
224 /*Free allocated ports information: */
225 ieee1284_free_ports (&pl);
226
227 DBG (2, "sane_exit\n");
228 return;
229 }
230
231 /* Device select/open/close */
232 static const SANE_Device dev[] = {
233 {
234 "hpsj5s",
235 "Hewlett-Packard",
236 "ScanJet 5S",
237 "sheetfed scanner"}
238 };
239
240 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)241 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
242 {
243 /*One device is supported and currently present */
244 static const SANE_Device *devlist[] = {
245 dev + 0, 0
246 };
247
248 /*No scanners presents */
249 static const SANE_Device *void_devlist[] = { 0 };
250
251 DBG (2, "sane_get_devices: local_only = %d\n", local_only);
252
253 if (scanner_d != -1) /*Device is opened, so it's present. */
254 {
255 *device_list = devlist;
256 return SANE_STATUS_GOOD;
257 };
258
259 /*Device was not opened. */
260 scanner_d = OpenScanner (scanner_path);
261
262 if (scanner_d == -1) /*No devices present */
263 {
264 DBG (1, "failed to open scanner.\n");
265 *device_list = void_devlist;
266 return SANE_STATUS_GOOD;
267 }
268 DBG (1, "port opened.\n");
269
270 /*Check device. */
271 DBG (1, "sane_get_devices: check scanner started.");
272 if (DetectScanner () == 0)
273 { /*Device malfunction! */
274 DBG (1, "sane_get_devices: Device malfunction.");
275 *device_list = void_devlist;
276 return SANE_STATUS_GOOD;
277 }
278 else
279 {
280 DBG (1, "sane_get_devices: Device works OK.");
281 *device_list = devlist;
282 }
283
284 /*We do not need it any more */
285 CloseScanner (scanner_d);
286 scanner_d = -1;
287
288 return SANE_STATUS_GOOD;
289 }
290
291 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)292 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
293 {
294 int i;
295
296 if (!devicename)
297 {
298 DBG (1, "sane_open: devicename is NULL!");
299 return SANE_STATUS_INVAL;
300 }
301
302 DBG (2, "sane_open: devicename = \"%s\"\n", devicename);
303
304 if (!devicename[0])
305 i = 0;
306 else
307 for (i = 0; i < NELEMS (dev); ++i) /*Search for device in list */
308 if (strcmp (devicename, dev[i].name) == 0)
309 break;
310
311 if (i >= NELEMS (dev)) /*No such device */
312 return SANE_STATUS_INVAL;
313
314 if (scanner_d != -1) /*scanner opened already! */
315 return SANE_STATUS_DEVICE_BUSY;
316
317 DBG (1, "sane_open: scanner device path name is \'%s\'\n", scanner_path);
318
319 scanner_d = OpenScanner (scanner_path);
320 if (scanner_d == -1)
321 return SANE_STATUS_DEVICE_BUSY; /*This should be done more carefully */
322
323 /*Check device. */
324 DBG (1, "sane_open: check scanner started.");
325 if (DetectScanner () == 0)
326 { /*Device malfunction! */
327 DBG (1, "sane_open: Device malfunction.");
328 CloseScanner (scanner_d);
329 scanner_d = -1;
330 return SANE_STATUS_IO_ERROR;
331 }
332 DBG (1, "sane_open: Device found.All are green.");
333 *handle = (SANE_Handle) (unsigned long)scanner_d;
334
335 return SANE_STATUS_GOOD;
336 }
337
338 void
sane_close(SANE_Handle handle)339 sane_close (SANE_Handle handle)
340 {
341 DBG (2, "sane_close\n");
342 /*We support only single device - so ignore handle (FIX IT LATER) */
343 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
344 return; /* wrong device */
345 StandByScanner ();
346 CloseScanner (scanner_d);
347 scanner_d = -1;
348 }
349
350 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)351 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
352 {
353 DBG (2, "sane_get_option_descriptor: option = %d\n", option);
354 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
355 return NULL; /* wrong device */
356
357 if (option < 0 || option >= NELEMS (sod)) /*No real options supported */
358 return NULL;
359
360 return &sod[option]; /*Return demanded option */
361 }
362
363 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Int * info)364 sane_control_option (SANE_Handle handle, SANE_Int option,
365 SANE_Action action, void *value, SANE_Int * info)
366 {
367 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
368 return SANE_STATUS_INVAL; /* wrong device */
369
370 if ((option >= NELEMS (sod)) || (option < 0)) /*Supported only this option */
371 return SANE_STATUS_INVAL;
372
373 switch (option)
374 {
375 case 0: /*Number of options */
376 if (action != SANE_ACTION_GET_VALUE) /*It can be only read */
377 return SANE_STATUS_INVAL;
378
379 *((SANE_Int *) value) = NELEMS (sod);
380 return SANE_STATUS_GOOD;
381 case 1: /*Scan area width */
382 switch (action)
383 {
384 case SANE_ACTION_GET_VALUE:
385 *((SANE_Word *) value) = wWidth;
386 return SANE_STATUS_GOOD;
387 case SANE_ACTION_SET_VALUE: /*info should be set */
388 wWidth = *((SANE_Word *) value);
389 if (info != NULL)
390 *info = SANE_INFO_RELOAD_PARAMS;
391 return SANE_STATUS_GOOD;
392 default:
393 return SANE_STATUS_INVAL;
394 }
395 case 2: /*Resolution */
396 switch (action)
397 {
398 case SANE_ACTION_GET_VALUE:
399 *((SANE_Word *) value) = wResolution;
400 return SANE_STATUS_GOOD;
401 case SANE_ACTION_SET_VALUE: /*info should be set */
402 wResolution = *((SANE_Word *) value);
403 if (info != NULL)
404 *info = 0;
405 return SANE_STATUS_GOOD;
406 default:
407 return SANE_STATUS_INVAL;
408 }
409 default:
410 return SANE_STATUS_INVAL;
411 }
412 return SANE_STATUS_GOOD; /*For now we have no options to control */
413 }
414
415 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)416 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
417 {
418 DBG (2, "sane_get_parameters\n");
419
420 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
421 return SANE_STATUS_INVAL; /* wrong device */
422
423 /*Ignore handle parameter for now. FIX it latter. */
424 /*These parameters are OK for gray scale mode. */
425 parms.depth = /*wCurrentDepth */ 8;
426 parms.format = /*wCurrentFormat */ SANE_FRAME_GRAY;
427 parms.last_frame = SANE_TRUE; /*For grayscale... */
428 parms.lines = -1; /*Unknown a priory */
429 parms.pixels_per_line = LengthForRes (wResolution, wWidth); /*For grayscale... */
430 parms.bytes_per_line = parms.pixels_per_line; /*For grayscale... */
431 *params = parms;
432 return SANE_STATUS_GOOD;
433 }
434
435 SANE_Status
sane_start(SANE_Handle handle)436 sane_start (SANE_Handle handle)
437 {
438 int i;
439 DBG (2, "sane_start\n");
440
441 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
442 return SANE_STATUS_IO_ERROR;
443
444 CallFunctionWithParameter (0x93, 2);
445 bLastCalibration = CallFunctionWithRetVal (0xA9);
446 if (bLastCalibration == 0)
447 bLastCalibration = -1;
448
449 /*Turn on the lamp: */
450 CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, FLAGS_HW_LAMP_ON);
451 bHardwareState = FLAGS_HW_LAMP_ON;
452 /*Get average white point */
453 bCalibration = GetCalibration ();
454
455 if (bLastCalibration - bCalibration > 16)
456 { /*Lamp is not warm enough */
457 DBG (1, "sane_start: warming lamp for 30 sec.\n");
458 for (i = 0; i < 30; i++)
459 sleep (1);
460 }
461
462 /*Check paper presents */
463 if (CheckPaperPresent () == 0)
464 {
465 DBG (1, "sane_start: no paper detected.");
466 return SANE_STATUS_NO_DOCS;
467 }
468 CalibrateScanElements ();
469 TransferScanParameters (GrayScale, wResolution, wWidth);
470 /*Turn on indicator and prepare engine. */
471 SwitchHardwareState (FLAGS_HW_INDICATOR_OFF | FLAGS_HW_MOTOR_READY, 1);
472 /*Feed paper */
473 if (PaperFeed (LINES_TO_FEED) == 0) /*Feed only for fixel length. Change it */
474 {
475 DBG (1, "sane_start: paper feed failed.");
476 SwitchHardwareState (FLAGS_HW_INDICATOR_OFF | FLAGS_HW_MOTOR_READY, 0);
477 return SANE_STATUS_JAMMED;
478 }
479 /*Set paper moving speed */
480 TurnOnPaperPulling (GrayScale, wResolution);
481
482 wVerticalResolution = 0; /*Reset counter */
483
484 return SANE_STATUS_GOOD;
485 }
486
487 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)488 sane_read (SANE_Handle handle, SANE_Byte * data,
489 SANE_Int max_length, SANE_Int * length)
490 {
491 SANE_Byte bFuncResult, bTest;
492 int timeout;
493
494 if (!length)
495 {
496 DBG (1, "sane_read: length == NULL\n");
497 return SANE_STATUS_INVAL;
498 }
499 *length = 0;
500 if (!data)
501 {
502 DBG (1, "sane_read: data == NULL\n");
503 return SANE_STATUS_INVAL;
504 }
505
506 if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1))
507 {
508 DBG (1, "sane_read: unknown handle\n");
509 return SANE_STATUS_INVAL;
510 }
511
512 /*While end of paper sheet was not reached */
513 /*Wait for scanned line ready */
514 timeout = 0;
515 while (((bFuncResult = CallFunctionWithRetVal (0xB2)) & 0x20) == 0)
516 {
517 bTest = CallFunctionWithRetVal (0xB5);
518 usleep (1);
519 timeout++;
520 if ((timeout < 1000) &&
521 (((bTest & 0x80) && ((bTest & 0x3F) <= 2)) ||
522 (((bTest & 0x80) == 0) && ((bTest & 0x3F) >= 5))))
523 continue;
524
525 if (timeout >= 1000)
526 continue; /*do it again! */
527
528 /*Data ready state! */
529
530 if ((bFuncResult & 0x20) != 0) /*End of paper reached! */
531 {
532 *length = 0;
533 return SANE_STATUS_EOF;
534 }
535
536 /*Data ready */
537 *length = LengthForRes (wResolution, wWidth);
538 if (*length >= max_length)
539 *length = max_length;
540
541 CallFunctionWithParameter (0xCD, 0);
542 CallFunctionWithRetVal (0xC8);
543 WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC8);
544 WriteAddress (ADDRESS_RESULT);
545 /*Test if we need this line for current resolution
546 (scanner doesn't control vertical resolution in hardware) */
547 wVerticalResolution -= wResolution;
548 if (wVerticalResolution > 0)
549 {
550 timeout = 0;
551 continue;
552 }
553 else
554 wVerticalResolution = 300; /*Reset counter */
555
556 ReadDataBlock (data, *length);
557
558 /*switch indicator */
559 bHardwareState ^= FLAGS_HW_INDICATOR_OFF;
560 CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState);
561 return SANE_STATUS_GOOD;
562 }
563 return SANE_STATUS_EOF;
564 }
565
566 void
sane_cancel(SANE_Handle handle)567 sane_cancel (SANE_Handle handle)
568 {
569 DBG (2, "sane_cancel: handle = %p\n", handle);
570 /*Stop motor */
571 TurnOffPaperPulling ();
572
573 /*Indicator turn off */
574 bHardwareState |= FLAGS_HW_INDICATOR_OFF;
575 CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState);
576
577 /*Get out of paper */
578 ReleasePaper ();
579
580 /*Restore indicator */
581 bHardwareState &= ~FLAGS_HW_INDICATOR_OFF;
582 CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState);
583
584 bLastCalibration = CallFunctionWithRetVal (0xA9);
585 CallFunctionWithParameter (0xA9, bLastCalibration);
586 CallFunctionWithParameter (0x93, 4);
587
588 }
589
590 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)591 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
592 {
593 DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
594 non_blocking);
595 return SANE_STATUS_UNSUPPORTED;
596 }
597
598 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)599 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
600 {
601 DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
602 fd ? "!=" : "=");
603 return SANE_STATUS_UNSUPPORTED;
604 }
605
606 /*
607 Middle-level API:
608 */
609
610 /*
611 Detect if scanner present and works correctly.
612 Ret Val: 0 = detection failed, 1 = detection OK.
613 */
614 static int
DetectScanner(void)615 DetectScanner (void)
616 {
617 int Result1, Result2;
618 int Successful, Total;
619
620 Result1 = OutputCheck ();
621 Result2 = InputCheck ();
622
623 if (!(Result1 || Result2)) /*If all are 0 - it's error */
624 {
625 return 0;
626 }
627
628 WriteScannerRegister (0x7C, 0x80);
629 WriteScannerRegister (0x7F, 0x1);
630 WriteScannerRegister (0x72, 0x10);
631 WriteScannerRegister (0x72, 0x90);
632 WriteScannerRegister (0x7C, 0x24);
633 WriteScannerRegister (0x75, 0x0C);
634 WriteScannerRegister (0x78, 0x0);
635 WriteScannerRegister (0x79, 0x10);
636 WriteScannerRegister (0x71, 0x10);
637 WriteScannerRegister (0x71, 0x1);
638 WriteScannerRegister (0x72, 0x1);
639
640 for (Successful = 0, Total = 0; Total < 5; Total++)
641 {
642 if (CallCheck ())
643 Successful++;
644 if (Successful >= 3)
645 return 1; /*Correct and Stable */
646 }
647 return 0;
648 }
649
650 static void
StandByScanner()651 StandByScanner ()
652 {
653 WriteScannerRegister (0x74, 0x80);
654 WriteScannerRegister (0x75, 0x0C);
655 WriteScannerRegister (0x77, 0x0);
656 WriteScannerRegister (0x78, 0x0);
657 WriteScannerRegister (0x79, 0x0);
658 WriteScannerRegister (0x7A, 0x0);
659 WriteScannerRegister (0x7B, 0x0);
660 WriteScannerRegister (0x7C, 0x4);
661 WriteScannerRegister (0x70, 0x0);
662 WriteScannerRegister (0x72, 0x90);
663 WriteScannerRegister (0x70, 0x0);
664 }
665
666 static void
SwitchHardwareState(SANE_Byte mask,SANE_Byte invert_mask)667 SwitchHardwareState (SANE_Byte mask, SANE_Byte invert_mask)
668 {
669 if (!invert_mask)
670 {
671 bHardwareState &= ~mask;
672 }
673 else
674 bHardwareState |= mask;
675
676 CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState);
677 }
678
679 /*return value: 0 - no paper, 1 - paper loaded.*/
680 static int
CheckPaperPresent()681 CheckPaperPresent ()
682 {
683 if ((CallFunctionWithRetVal (0xB2) & 0x10) == 0)
684 return 1; /*Ok - paper present. */
685 return 0; /*No paper present */
686 }
687
688 static int
ReleasePaper()689 ReleasePaper ()
690 {
691 int i;
692
693 if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0)
694 { /*End of paper was not reached */
695 CallFunctionWithParameter (0xA7, 0xF);
696 CallFunctionWithParameter (0xA8, 0xFF);
697 CallFunctionWithParameter (0xC2, 0);
698
699 for (i = 0; i < 90000; i++)
700 {
701 if (CallFunctionWithRetVal (0xB2) & 0x80)
702 break;
703 usleep (1);
704 }
705 if (i >= 90000)
706 return 0; /*Fail. */
707
708 for (i = 0; i < 90000; i++)
709 {
710 if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0)
711 break;
712 else if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0)
713 {
714 i = 90000;
715 break;
716 }
717 usleep (1);
718 }
719
720 CallFunctionWithParameter (0xC5, 0);
721
722 if (i >= 90000)
723 return 0; /*Fail. */
724
725 while (CallFunctionWithRetVal (0xB2) & 0x80); /*Wait bit dismiss */
726
727 CallFunctionWithParameter (0xA7, 1);
728 CallFunctionWithParameter (0xA8, 0x25);
729 CallFunctionWithParameter (0xC2, 0);
730
731 for (i = 0; i < 90000; i++)
732 {
733 if (CallFunctionWithRetVal (0xB2) & 0x80)
734 break;
735 usleep (1);
736 }
737 if (i >= 90000)
738 return 0; /*Fail. */
739
740 for (i = 0; i < 90000; i++)
741 {
742 if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0)
743 break;
744 usleep (1);
745 }
746 if (i >= 90000)
747 return 0; /*Fail. */
748 }
749
750 if (CallFunctionWithRetVal (0xB2) & 0x10)
751 {
752 CallFunctionWithParameter (0xA7, 1);
753 CallFunctionWithParameter (0xA8, 0x40);
754 }
755 else
756 {
757 CallFunctionWithParameter (0xA7, 0);
758 CallFunctionWithParameter (0xA8, 0xFA);
759 }
760 CallFunctionWithParameter (0xC2, 0);
761
762 for (i = 0; i < 9000; i++)
763 {
764 if (CallFunctionWithRetVal (0xB2) & 0x80)
765 break;
766 usleep (1);
767 }
768 if (i >= 9000)
769 return 0; /*Fail. */
770
771 while (CallFunctionWithRetVal (0xB2) & 0x80)
772 usleep (1);
773
774 return 1;
775 }
776
777 static void
TransferScanParameters(enumColorDepth enColor,SANE_Word wResolution,SANE_Word wPixelsLength)778 TransferScanParameters (enumColorDepth enColor, SANE_Word wResolution,
779 SANE_Word wPixelsLength)
780 {
781 SANE_Word wRightBourder = (2570 + wPixelsLength) / 2 + 65;
782 SANE_Word wLeftBourder = (2570 - wPixelsLength) / 2 + 65;
783
784 switch (enColor)
785 {
786 case Drawing:
787 CallFunctionWithParameter (0x90, 2); /*Not supported correctle. FIX ME!!! */
788 break;
789 case Halftone:
790 CallFunctionWithParameter (0x90, 0xE3); /*Not supported correctly. FIX ME!!! */
791 CallFunctionWithParameter (0x92, 3);
792 break;
793 case GrayScale:
794 case TrueColor:
795 CallFunctionWithParameter (0x90, 0); /*Not supported correctly. FIX ME!!! */
796 break;
797 };
798 CallFunctionWithParameter (0xA1, 2);
799 CallFunctionWithParameter (0xA2, 1);
800 CallFunctionWithParameter (0xA3, 0x98);
801 /*Resolution: */
802 CallFunctionWithParameter (0x9A, (SANE_Byte) (wResolution >> 8)); /*High byte */
803 CallFunctionWithParameter (0x9B, (SANE_Byte) wResolution); /*Low byte */
804
805 LoadingPaletteToScanner ();
806
807 CallFunctionWithParameter (0xA4, 31); /*Some sort of constant parameter */
808 /*Left bourder */
809 CallFunctionWithParameter (0xA5, wLeftBourder / 256);
810 CallFunctionWithParameter (0xA6, wLeftBourder % 256);
811 /*Right bourder */
812 CallFunctionWithParameter (0xAA, wRightBourder / 256);
813 CallFunctionWithParameter (0xAB, wRightBourder % 256);
814
815 CallFunctionWithParameter (0xD0, 0);
816 CallFunctionWithParameter (0xD1, 0);
817 CallFunctionWithParameter (0xD2, 0);
818 CallFunctionWithParameter (0xD3, 0);
819 CallFunctionWithParameter (0xD4, 0);
820 CallFunctionWithParameter (0xD5, 0);
821
822 CallFunctionWithParameter (0x9D, 5);
823 }
824
825 static void
TurnOnPaperPulling(enumColorDepth enColor,SANE_Word wResolution)826 TurnOnPaperPulling (enumColorDepth enColor, SANE_Word wResolution)
827 {
828 switch (enColor)
829 {
830 case Drawing:
831 case Halftone:
832 CallFunctionWithParameter (0x91, 0xF7);
833 return;
834 case GrayScale:
835 switch (wResolution)
836 {
837 case 50:
838 case 75:
839 case 100:
840 CallFunctionWithParameter (0x91, 0xB7);
841 return;
842 case 150:
843 case 200:
844 CallFunctionWithParameter (0x91, 0x77);
845 return;
846 case 250:
847 case 300:
848 CallFunctionWithParameter (0x91, 0x37);
849 return;
850 default:
851 return;
852 }
853 case TrueColor:
854 switch (wResolution)
855 {
856 case 75:
857 case 100:
858 CallFunctionWithParameter (0x91, 0xA3);
859 return;
860 case 150:
861 case 200:
862 CallFunctionWithParameter (0x91, 0x53);
863 return;
864 case 250:
865 case 300:
866 CallFunctionWithParameter (0x91, 0x3);
867 return;
868 default:
869 return;
870 }
871 default:
872 return;
873 }
874 }
875
876 static void
TurnOffPaperPulling()877 TurnOffPaperPulling ()
878 {
879 CallFunctionWithParameter (0x91, 0);
880 }
881
882 /*
883 Returns average value of scanned row.
884 While paper not loaded this is base "white point".
885 */
886 static SANE_Byte
GetCalibration()887 GetCalibration ()
888 {
889 int i;
890 int Result;
891 SANE_Byte Buffer[2600];
892 SANE_Byte bTest;
893
894 CallFunctionWithParameter (0xA1, 2);
895 CallFunctionWithParameter (0xA2, 1);
896 CallFunctionWithParameter (0xA3, 0x98);
897
898 /*Resolution to 300 DPI */
899 CallFunctionWithParameter (0x9A, 1);
900 CallFunctionWithParameter (0x9B, 0x2C);
901
902 CallFunctionWithParameter (0x92, 0);
903 CallFunctionWithParameter (0xC6, 0);
904 CallFunctionWithParameter (0x92, 0x80);
905
906 for (i = 1; i < 256; i++)
907 CallFunctionWithParameter (0xC6, i);
908
909 for (i = 0; i < 256; i++)
910 CallFunctionWithParameter (0xC6, i);
911
912 for (i = 0; i < 256; i++)
913 CallFunctionWithParameter (0xC6, i);
914
915 CallFunctionWithParameter (0xA4, 31); /*Some sort of constant */
916
917 /*Left bourder */
918 CallFunctionWithParameter (0xA5, 0);
919 CallFunctionWithParameter (0xA6, 0x41);
920
921 /*Right bourder */
922 CallFunctionWithParameter (0xAA, 0xA);
923 CallFunctionWithParameter (0xAB, 0x39);
924
925 CallFunctionWithParameter (0xD0, 0);
926 CallFunctionWithParameter (0xD1, 0);
927 CallFunctionWithParameter (0xD2, 0);
928 CallFunctionWithParameter (0xD3, 0);
929 CallFunctionWithParameter (0xD4, 0);
930 CallFunctionWithParameter (0xD5, 0);
931
932 CallFunctionWithParameter (0x9C, 0x1B);
933 CallFunctionWithParameter (0x9D, 5);
934
935 CallFunctionWithParameter (0x92, 0x10);
936 CallFunctionWithParameter (0xC6, 0xFF);
937 CallFunctionWithParameter (0x92, 0x90);
938
939 for (i = 0; i < 2999; i++)
940 CallFunctionWithParameter (0xC6, 0xFF);
941
942 CallFunctionWithParameter (0x92, 0x50);
943 CallFunctionWithParameter (0xC6, 0);
944 CallFunctionWithParameter (0x92, 0xD0);
945
946 for (i = 0; i < 2999; i++)
947 CallFunctionWithParameter (0xC6, 0);
948
949 CallFunctionWithParameter (0x98, 0xFF); /*Up limit */
950 CallFunctionWithParameter (0x95, 0); /*Low limit */
951
952 CallFunctionWithParameter (0x90, 0); /*Gray scale... */
953
954 CallFunctionWithParameter (0x91, 0x3B); /*Turn motor on. */
955
956 for (i = 0; i < 5; i++)
957 {
958 do
959 { /*WARNING!!! Deadlock possible! */
960 bTest = CallFunctionWithRetVal (0xB5);
961 }
962 while ((bTest & 0x80) ? (bTest & 0x3F) <= 2 : (bTest & 0x3F) >= 5);
963
964 CallFunctionWithParameter (0xCD, 0);
965 /*Skip this line for ECP: */
966 CallFunctionWithRetVal (0xC8);
967
968 WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC8);
969 WriteAddress (0x20);
970 ReadDataBlock (Buffer, 2552);
971 };
972 CallFunctionWithParameter (0x91, 0); /*Turn off motor. */
973 usleep (10);
974 for (Result = 0, i = 0; i < 2552; i++)
975 Result += Buffer[i];
976 return Result / 2552;
977 }
978
979 static int
PaperFeed(SANE_Word wLinesToFeed)980 PaperFeed (SANE_Word wLinesToFeed)
981 {
982 int i;
983
984 CallFunctionWithParameter (0xA7, 0xF);
985 CallFunctionWithParameter (0xA8, 0xFF);
986 CallFunctionWithParameter (0xC2, 0);
987
988 for (i = 0; i < 9000; i++)
989 {
990 if (CallFunctionWithRetVal (0xB2) & 0x80)
991 break;
992 usleep (1);
993 }
994 if (i >= 9000)
995 return 0; /*Fail. */
996
997 for (i = 0; i < 9000; i += 5)
998 {
999 if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0)
1000 break;
1001 else if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0)
1002 {
1003 i = 9000;
1004 break;
1005 }
1006 usleep (5);
1007 }
1008
1009 CallFunctionWithParameter (0xC5, 0);
1010
1011 if (i >= 9000)
1012 return 0; /*Fail. */
1013
1014 /*Potential deadlock */
1015 while (CallFunctionWithRetVal (0xB2) & 0x80); /*Wait bit dismiss */
1016
1017 CallFunctionWithParameter (0xA7, wLinesToFeed / 256);
1018 CallFunctionWithParameter (0xA8, wLinesToFeed % 256);
1019 CallFunctionWithParameter (0xC2, 0);
1020
1021 for (i = 0; i < 9000; i++)
1022 {
1023 if (CallFunctionWithRetVal (0xB2) & 0x80)
1024 break;
1025 usleep (1);
1026 }
1027 if (i >= 9000)
1028 return 0; /*Fail. */
1029
1030 for (i = 0; i < 9000; i++)
1031 {
1032 if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0)
1033 break;
1034 usleep (1);
1035 }
1036 if (i >= 9000)
1037 return 0; /*Fail. */
1038
1039 return 1;
1040 }
1041
1042 /*For now we do no calibrate elements - just set maximum limits. FIX ME?*/
1043 static void
CalibrateScanElements()1044 CalibrateScanElements ()
1045 {
1046 /*Those arrays will be used in future for correct calibration. */
1047 /*Then we need to transfer UP brightness border, we use these registers */
1048 SANE_Byte arUpTransferBorders[] = { 0x10, 0x20, 0x30 };
1049 /*Then we need to transfer LOW brightness border, we use these registers */
1050 SANE_Byte arLowTransferBorders[] = { 0x50, 0x60, 0x70 };
1051 /*Then we need to save UP brightness border, we use these registers */
1052 SANE_Byte arUpSaveBorders[] = { 0x98, 0x97, 0x99 };
1053 /*Then we need to save LOW brightness border, we use these registers */
1054 SANE_Byte arLowSaveBorders[] = { 0x95, 0x94, 0x96 };
1055 /*Speeds, used for calibration */
1056 SANE_Byte arSpeeds[] = { 0x3B, 0x37, 0x3F };
1057 int j, Average, Temp, Index, /* Line, */ timeout,Calibration;
1058 SANE_Byte bTest /*, Min, Max, Result */ ;
1059 /*For current color component: (values from arrays). Next two lines - starting and terminating. */
1060
1061 SANE_Byte CurrentUpTransferBorder;
1062 SANE_Byte CurrentLowTransferBorder;
1063 SANE_Byte CurrentUpSaveBorder;
1064 SANE_Byte CurrentLowSaveBorder;
1065 SANE_Byte CurrentSpeed1, CurrentSpeed2;
1066 SANE_Byte CorrectionValue;
1067 SANE_Byte FilteredBuffer[2570];
1068
1069 CallFunctionWithParameter (0xA1, 2);
1070 CallFunctionWithParameter (0xA2, 0);
1071 CallFunctionWithParameter (0xA3, 0x98);
1072
1073 /*DPI = 300 */
1074 CallFunctionWithParameter (0x9A, 1); /*High byte */
1075 CallFunctionWithParameter (0x9B, 0x2C); /*Low byte */
1076
1077 /*Paletter settings. */
1078 CallFunctionWithParameter (0x92, 0);
1079 CallFunctionWithParameter (0xC6, 0);
1080 CallFunctionWithParameter (0x92, 0x80);
1081
1082 /*First color component */
1083 for (j = 1; j < 256; j++)
1084 CallFunctionWithParameter (0xC6, j);
1085
1086 /*Second color component */
1087 for (j = 0; j < 256; j++)
1088 CallFunctionWithParameter (0xC6, j);
1089
1090 /*Third color component */
1091 for (j = 0; j < 256; j++)
1092 CallFunctionWithParameter (0xC6, j);
1093
1094 CallFunctionWithParameter (0xA4, 31);
1095
1096 /*Left border */
1097 CallFunctionWithParameter (0xA5, 0); /*High byte */
1098 CallFunctionWithParameter (0xA6, 0x41); /*Low byte */
1099
1100 /*Right border */
1101 CallFunctionWithParameter (0xAA, 0xA); /*High byte */
1102 CallFunctionWithParameter (0xAB, 0x4B); /*Low byte */
1103
1104 /*Zero these registers... */
1105 CallFunctionWithParameter (0xD0, 0);
1106 CallFunctionWithParameter (0xD1, 0);
1107 CallFunctionWithParameter (0xD2, 0);
1108 CallFunctionWithParameter (0xD3, 0);
1109 CallFunctionWithParameter (0xD4, 0);
1110 CallFunctionWithParameter (0xD5, 0);
1111
1112 CallFunctionWithParameter (0x9C, 0x1B);
1113 CallFunctionWithParameter (0x9D, 0x5);
1114
1115 Average = 0;
1116 for (Index = 0; Index < 3; Index++) /*For theree color components */
1117 {
1118 /*Up border = 0xFF */
1119 CallFunctionWithParameter (0x92, arUpTransferBorders[Index]);
1120 CallFunctionWithParameter (0xC6, 0xFF);
1121 CallFunctionWithParameter (0x92, arUpTransferBorders[Index] | 0x80);
1122
1123 for (j = 2999; j > 0; j--)
1124 CallFunctionWithParameter (0xC6, 0xFF);
1125
1126 /*Low border = 0x0 */
1127 CallFunctionWithParameter (0x92, arLowTransferBorders[Index]);
1128 CallFunctionWithParameter (0xC6, 0x0);
1129 CallFunctionWithParameter (0x92, arLowTransferBorders[Index] | 0x80);
1130
1131 for (j = 2999; j > 0; j--)
1132 CallFunctionWithParameter (0xC6, 0x0);
1133
1134 /*Save borders */
1135 CallFunctionWithParameter (arUpSaveBorders[Index], 0xFF);
1136 CallFunctionWithParameter (arLowSaveBorders[Index], 0x0);
1137 CallFunctionWithParameter (0x90, 0); /*Gray Scale or True color sign :) */
1138
1139 CallFunctionWithParameter (0x91, arSpeeds[Index]);
1140
1141 /*waiting for scanned line... */
1142 timeout = 0;
1143 do
1144 {
1145 bTest = CallFunctionWithRetVal (0xB5);
1146 timeout++;
1147 usleep (1);
1148 }
1149 while ((timeout < 1000) &&
1150 ((bTest & 0x80) ? (bTest & 0x3F) <= 2 : (bTest & 0x3F) >= 5));
1151
1152 /*Let's read it... */
1153 if(timeout < 1000)
1154 {
1155 CallFunctionWithParameter (0xCD, 0);
1156 CallFunctionWithRetVal (0xC8);
1157 WriteScannerRegister (0x70, 0xC8);
1158 WriteAddress (0x20);
1159
1160 ReadDataBlock (FilteredBuffer, 2570);
1161 }
1162
1163 CallFunctionWithParameter (0x91, 0); /*Stop engine. */
1164
1165 /*Note: if first read failed, junk would be calculated, but if previous
1166 read was succeeded, but last one failed, previous data'ld be used.
1167 */
1168 for(Temp = 0, j = 0; j < 2570; j++)
1169 Temp += FilteredBuffer[j];
1170 Temp /= 2570;
1171
1172 if((Average == 0)||(Average > Temp))
1173 Average = Temp;
1174 }
1175
1176 for(Index = 0; Index < 3; Index++) /*Three color components*/
1177 {
1178 CurrentUpTransferBorder = arUpTransferBorders[Index];
1179 CallFunctionWithParameter (0xC6, 0xFF);
1180 CallFunctionWithParameter (0x92, CurrentUpTransferBorder|0x80);
1181 for(j=2999; j>0; j--)
1182 CallFunctionWithParameter (0xC6, 0xFF);
1183
1184 CurrentLowTransferBorder = arLowTransferBorders[Index];
1185 CallFunctionWithParameter (0xC6, 0x0);
1186 CallFunctionWithParameter (0x92, CurrentLowTransferBorder|0x80);
1187 for(j=2999; j>0; j--)
1188 CallFunctionWithParameter (0xC6, 0);
1189
1190 CurrentUpSaveBorder = arUpSaveBorders[Index];
1191 CallFunctionWithParameter (CurrentUpSaveBorder, 0xFF);
1192
1193 CurrentLowSaveBorder = arLowSaveBorders[Index];
1194 CallFunctionWithParameter (CurrentLowSaveBorder, 0x0);
1195 CallFunctionWithParameter (0x90,0);
1196 Calibration = 0x80;
1197 CallFunctionWithParameter (CurrentUpSaveBorder, 0x80);
1198
1199 CurrentSpeed1 = CurrentSpeed2 = arSpeeds[Index];
1200
1201 for(CorrectionValue = 0x40; CorrectionValue != 0;CorrectionValue >>= 2)
1202 {
1203 CallFunctionWithParameter (0x91, CurrentSpeed2);
1204 usleep(10);
1205
1206 /*waiting for scanned line... */
1207 for(j = 0; j < 5; j++)
1208 {
1209 timeout = 0;
1210 do
1211 {
1212 bTest = CallFunctionWithRetVal (0xB5);
1213 timeout++;
1214 usleep (1);
1215 }
1216 while ((timeout < 1000) &&
1217 ((bTest & 0x80) ? (bTest & 0x3F) <= 2 : (bTest & 0x3F) >= 5));
1218
1219 /*Let's read it... */
1220 if(timeout < 1000)
1221 {
1222 CallFunctionWithParameter (0xCD, 0);
1223 CallFunctionWithRetVal (0xC8);
1224 WriteScannerRegister (0x70, 0xC8);
1225 WriteAddress (0x20);
1226
1227 ReadDataBlock (FilteredBuffer, 2570);
1228 }
1229 }/*5 times we read. I don't understand what for, but so does HP's driver.
1230 Perhaps, we can optimize it in future.*/
1231 WriteScannerRegister (0x91, 0);
1232 usleep(10);
1233
1234 for(Temp = 0,j = 0; j < 16;j++)
1235 Temp += FilteredBuffer[509+j]; /*At this offset calcalates HP's driver.*/
1236 Temp /= 16;
1237
1238 if(Average > Temp)
1239 {
1240 Calibration += CorrectionValue;
1241 Calibration = 0xFF < Calibration ? 0xFF : Calibration; /*min*/
1242 }
1243 else
1244 Calibration -= CorrectionValue;
1245
1246 WriteScannerRegister (CurrentUpSaveBorder, Calibration);
1247 }/*By CorrectionValue we tune UpSaveBorder*/
1248
1249 WriteScannerRegister (0x90, 8);
1250 WriteScannerRegister (0x91, CurrentSpeed1);
1251 usleep(10);
1252 }/*By color components*/
1253
1254 return;
1255 }
1256
1257 /*
1258 Internal use functions:
1259 */
1260
1261 /*Returns 0 in case of fail and 1 in success.*/
1262 static int
OutputCheck()1263 OutputCheck ()
1264 {
1265 int i;
1266
1267 WriteScannerRegister (0x7F, 0x1);
1268 WriteAddress (0x7E);
1269 for (i = 0; i < 256; i++)
1270 WriteData ((SANE_Byte) i);
1271
1272 WriteAddress (0x3F);
1273 if (ReadDataByte () & 0x80)
1274 return 0;
1275
1276 return 1;
1277 }
1278
1279 static int
InputCheck()1280 InputCheck ()
1281 {
1282 int i;
1283 SANE_Byte Buffer[256];
1284
1285 WriteAddress (0x3E);
1286 for (i = 0; i < 256; i++)
1287 {
1288 Buffer[i] = ReadDataByte ();
1289 }
1290
1291 for (i = 0; i < 256; i++)
1292 {
1293 if (Buffer[i] != i)
1294 return 0;
1295 }
1296
1297 return 1;
1298 }
1299
1300 static int
CallCheck()1301 CallCheck ()
1302 {
1303 int i;
1304 SANE_Byte Buffer[256];
1305
1306 CallFunctionWithParameter (0x92, 0x10);
1307 CallFunctionWithParameter (0xC6, 0x0);
1308 CallFunctionWithParameter (0x92, 0x90);
1309 WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC6);
1310
1311 WriteAddress (0x60);
1312
1313 for (i = 1; i < 256; i++)
1314 WriteData ((SANE_Byte) i);
1315
1316 CallFunctionWithParameter (0x92, 0x10);
1317 CallFunctionWithRetVal (0xC6);
1318 CallFunctionWithParameter (0x92, 0x90);
1319 WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC6);
1320
1321 WriteAddress (ADDRESS_RESULT);
1322
1323 ReadDataBlock (Buffer, 256);
1324
1325 for (i = 0; i < 255; i++)
1326 {
1327 if (Buffer[i + 1] != (SANE_Byte) i)
1328 return 0;
1329 }
1330 return 1;
1331 }
1332
1333 static void
LoadingPaletteToScanner()1334 LoadingPaletteToScanner ()
1335 {
1336 /*For now we have statical gamma. */
1337 SANE_Byte Gamma[256];
1338 int i;
1339 for (i = 0; i < 256; i++)
1340 Gamma[i] = i;
1341
1342 CallFunctionWithParameter (0x92, 0);
1343 CallFunctionWithParameter (0xC6, Gamma[0]);
1344 CallFunctionWithParameter (0x92, 0x80);
1345 for (i = 1; i < 256; i++)
1346 CallFunctionWithParameter (0xC6, Gamma[i]);
1347
1348 for (i = 0; i < 256; i++)
1349 CallFunctionWithParameter (0xC6, Gamma[i]);
1350
1351 for (i = 0; i < 256; i++)
1352 CallFunctionWithParameter (0xC6, Gamma[i]);
1353 }
1354
1355 /*
1356 Low level warappers:
1357 */
1358 static void
WriteAddress(SANE_Byte Address)1359 WriteAddress (SANE_Byte Address)
1360 {
1361 ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */
1362 ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT);
1363 ieee1284_epp_write_addr (pl.portv[scanner_d], 0, (char *) &Address, 1);
1364 }
1365
1366 static void
WriteData(SANE_Byte Data)1367 WriteData (SANE_Byte Data)
1368 {
1369 ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */
1370 ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT);
1371 ieee1284_epp_write_data (pl.portv[scanner_d], 0, (char *) &Data, 1);
1372 }
1373
1374 static void
WriteScannerRegister(SANE_Byte Address,SANE_Byte Data)1375 WriteScannerRegister (SANE_Byte Address, SANE_Byte Data)
1376 {
1377 WriteAddress (Address);
1378 WriteData (Data);
1379 }
1380
1381 static void
CallFunctionWithParameter(SANE_Byte Function,SANE_Byte Parameter)1382 CallFunctionWithParameter (SANE_Byte Function, SANE_Byte Parameter)
1383 {
1384 WriteScannerRegister (REGISTER_FUNCTION_CODE, Function);
1385 WriteScannerRegister (REGISTER_FUNCTION_PARAMETER, Parameter);
1386 }
1387
1388 static SANE_Byte
CallFunctionWithRetVal(SANE_Byte Function)1389 CallFunctionWithRetVal (SANE_Byte Function)
1390 {
1391 WriteScannerRegister (REGISTER_FUNCTION_CODE, Function);
1392 WriteAddress (ADDRESS_RESULT);
1393 return ReadDataByte ();
1394 }
1395
1396 static SANE_Byte
ReadDataByte()1397 ReadDataByte ()
1398 {
1399 SANE_Byte Result;
1400
1401 ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */
1402 ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT);
1403 ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) &Result, 1);
1404 return Result;
1405 }
1406
1407 static void
ReadDataBlock(SANE_Byte * Buffer,int length)1408 ReadDataBlock (SANE_Byte * Buffer, int length)
1409 {
1410
1411 ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */
1412 ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT);
1413 ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) Buffer, length);
1414 }
1415
1416 /* Send a daisy-chain-style CPP command packet. */
1417 int
cpp_daisy(struct parport * port,int cmd)1418 cpp_daisy (struct parport *port, int cmd)
1419 {
1420 unsigned char s;
1421
1422 ieee1284_data_dir (port, 0); /*forward direction */
1423 ieee1284_write_control (port, C1284_NINIT);
1424 ieee1284_write_data (port, 0xaa);
1425 usleep (2);
1426 ieee1284_write_data (port, 0x55);
1427 usleep (2);
1428 ieee1284_write_data (port, 0x00);
1429 usleep (2);
1430 ieee1284_write_data (port, 0xff);
1431 usleep (2);
1432 s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Converted for PC-style */
1433
1434 s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT);
1435
1436 if (s != (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT))
1437 {
1438 DBG (1, "%s: cpp_daisy: aa5500ff(%02x)\n", port->name, s);
1439 return -1;
1440 }
1441
1442 ieee1284_write_data (port, 0x87);
1443 usleep (2);
1444 s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Convert to PC-style */
1445
1446 s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT);
1447
1448 if (s != (S1284_SELECT | S1284_NFAULT))
1449 {
1450 DBG (1, "%s: cpp_daisy: aa5500ff87(%02x)\n", port->name, s);
1451 return -1;
1452 }
1453
1454 ieee1284_write_data (port, 0x78);
1455 usleep (2);
1456 ieee1284_write_control (port, C1284_NINIT);
1457 ieee1284_write_data (port, cmd);
1458 usleep (2);
1459 ieee1284_frob_control (port, C1284_NSTROBE, C1284_NSTROBE);
1460 usleep (1);
1461 ieee1284_frob_control (port, C1284_NSTROBE, 0);
1462 usleep (1);
1463 s = ieee1284_read_status (port);
1464 ieee1284_write_data (port, 0xff);
1465 usleep (2);
1466
1467 return s;
1468 }
1469
1470 /*Daisy chain deselect operation.*/
1471 void
daisy_deselect_all(struct parport * port)1472 daisy_deselect_all (struct parport *port)
1473 {
1474 cpp_daisy (port, 0x30);
1475 }
1476
1477 /*Daisy chain select operation*/
1478 int
daisy_select(struct parport * port,int daisy,int mode)1479 daisy_select (struct parport *port, int daisy, int mode)
1480 {
1481 switch (mode)
1482 {
1483 /*For these modes we should switch to EPP mode: */
1484 case M1284_EPP:
1485 case M1284_EPPSL:
1486 case M1284_EPPSWE:
1487 return cpp_daisy (port, 0x20 + daisy) & S1284_NFAULT;
1488 /*For these modes we should switch to ECP mode: */
1489 case M1284_ECP:
1490 case M1284_ECPRLE:
1491 case M1284_ECPSWE:
1492 return cpp_daisy (port, 0xd0 + daisy) & S1284_NFAULT;
1493 /*Nothing was told for BECP in Daisy chain specification.
1494 May be it's wise to use ECP? */
1495 case M1284_BECP:
1496 /*Others use compat mode */
1497 case M1284_NIBBLE:
1498 case M1284_BYTE:
1499 case M1284_COMPAT:
1500 default:
1501 return cpp_daisy (port, 0xe0 + daisy) & S1284_NFAULT;
1502 }
1503 }
1504
1505 /*Daisy chain assign address operation.*/
1506 int
assign_addr(struct parport * port,int daisy)1507 assign_addr (struct parport *port, int daisy)
1508 {
1509 return cpp_daisy (port, daisy);
1510 }
1511
1512 static int
OpenScanner(const char * scanner_path)1513 OpenScanner (const char *scanner_path)
1514 {
1515 int handle;
1516 int caps;
1517
1518 /*Scaner name was specified in config file?*/
1519 if (strlen(scanner_path) == 0)
1520 return -1;
1521
1522 for (handle = 0; handle < pl.portc; handle++)
1523 {
1524 if (strcmp (scanner_path, pl.portv[handle]->name) == 0)
1525 break;
1526 }
1527 if (handle == pl.portc) /*No match found */
1528 return -1;
1529
1530 /*Open port */
1531 if (ieee1284_open (pl.portv[handle], 0, &caps) != E1284_OK)
1532 return -1;
1533
1534 /*Claim port */
1535 if (ieee1284_claim (pl.portv[handle]) != E1284_OK)
1536 return -1;
1537
1538 /*Total chain reset. */
1539 daisy_deselect_all (pl.portv[handle]);
1540
1541 /*Assign addresses. */
1542 assign_addr (pl.portv[handle], 0); /*Assume we have device first in chain. */
1543
1544 /*Select required device. For now - first in chain. */
1545 daisy_select (pl.portv[handle], 0, M1284_EPP);
1546
1547 return handle;
1548 }
1549
1550 static void
CloseScanner(int handle)1551 CloseScanner (int handle)
1552 {
1553 if (handle == -1)
1554 return;
1555
1556 daisy_deselect_all (pl.portv[handle]);
1557
1558 ieee1284_release (pl.portv[handle]);
1559
1560 ieee1284_close (pl.portv[handle]);
1561 }
1562