• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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