1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 2001-2012 Stéphane Voltz <stef.dev@free.fr>
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    This file implements a SANE backend for Umax PP flatbed scanners.  */
40 
41 #define DEBUG_DECLARE_ONLY
42 #undef BACKEND_NAME
43 #define BACKEND_NAME umax_pp
44 
45 #include "../include/sane/config.h"
46 #include <stdlib.h>
47 #include <string.h>
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51 #include <stdio.h>
52 #include "../include/sane/sanei_debug.h"
53 
54 #define __MAIN__
55 
56 
57 #include "umax_pp_mid.h"
58 
59 /* this function locks the parallel port so that other devices */
60 /* won't interfere. Returns UMAX1220P_BUSY is port cannot be   */
61 /* lock or UMAX1220P_OK if it is locked                        */
62 static int locked = 0;
63 #ifdef HAVE_LINUX_PPDEV_H
64 static int exmode = IEEE1284_MODE_COMPAT;
65 static int exflags = 0;
66 #endif
67 
68 static int
lock_parport(void)69 lock_parport (void)
70 {
71 #ifdef HAVE_LINUX_PPDEV_H
72   int mode, fd;
73 #endif
74 
75   DBG_INIT ();
76   DBG (3, "lock_parport\n");
77 
78 #ifdef HAVE_LINUX_PPDEV_H
79   fd = sanei_umax_pp_getparport ();
80   if ((fd > 0) && (!locked))
81     {
82       if (ioctl (sanei_umax_pp_getparport (), PPCLAIM))
83         {
84           return UMAX1220P_BUSY;
85         }
86 #ifdef PPGETMODE
87       if (ioctl (fd, PPGETMODE, &exmode))
88         exmode = IEEE1284_MODE_COMPAT;
89       if (ioctl (fd, PPGETFLAGS, &exflags))
90         exflags = 0;
91 #endif
92       mode = IEEE1284_MODE_EPP;
93       ioctl (fd, PPNEGOT, &mode);
94       ioctl (fd, PPSETMODE, &mode);
95       locked = 1;
96     }
97 #else
98   locked = 1;
99 #endif
100   return UMAX1220P_OK;
101 }
102 
103 
104 /* this function release parport */
105 static int
unlock_parport(void)106 unlock_parport (void)
107 {
108 #ifdef HAVE_LINUX_PPDEV_H
109   int fd, mode;
110 
111   fd = sanei_umax_pp_getparport ();
112   if ((fd > 0) && (locked))
113     {
114       mode = IEEE1284_MODE_COMPAT;
115       ioctl (fd, PPNEGOT, &mode);
116       ioctl (fd, PPSETMODE, &exmode);
117 #ifdef PPSETFLAGS
118       ioctl (fd, PPSETFLAGS, &exflags);
119 #endif
120       ioctl (fd, PPRELEASE);
121       locked = 1;
122     }
123 #endif
124   DBG (3, "unlock_parport\n");
125   locked = 0;
126   return UMAX1220P_OK;
127 }
128 
129 
130 
131 
132 /*
133  *
134  *  This function recognize the scanner model by sending an image
135  * filter command. 1220P will use it as is, but 2000P will return
136  * it back modified.
137  *
138  */
139 int
sanei_umax_pp_model(int port, int *model)140 sanei_umax_pp_model (int port, int *model)
141 {
142   int recover = 0, rc;
143 
144   /* set up port */
145   DBG (3, "sanei_umax_pp_model\n");
146   sanei_umax_pp_setport (port);
147   if (lock_parport () == UMAX1220P_BUSY)
148     return UMAX1220P_BUSY;
149 
150   /* init transport layer */
151   /* 0: failed
152      1: success
153      2: retry
154      3: busy
155    */
156   do
157     {
158       rc = sanei_umax_pp_initTransport (recover);
159     }
160   while (rc == 2);
161 
162   if (rc == 3)
163     {
164       unlock_parport ();
165       return UMAX1220P_BUSY;
166     }
167   if (rc != 1)
168     {
169       DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__,
170            __LINE__);
171       unlock_parport ();
172       return UMAX1220P_TRANSPORT_FAILED;
173     }
174 
175   /* check model only, and if only none given in conf file */
176   if (!sanei_umax_pp_getastra ())
177     {
178       rc = sanei_umax_pp_checkModel ();
179     }
180   else
181     {
182       rc = sanei_umax_pp_getastra ();
183     }
184   sanei_umax_pp_endSession ();
185   unlock_parport ();
186   if (rc < 600)
187     {
188       DBG (0, "sanei_umax_pp_CheckModel() failed (%s:%d)\n", __FILE__,
189            __LINE__);
190       return UMAX1220P_PROBE_FAILED;
191     }
192   *model = rc;
193 
194 
195   /* OK */
196   return UMAX1220P_OK;
197 }
198 
199 int
sanei_umax_pp_attach(int port, const char *name)200 sanei_umax_pp_attach (int port, const char *name)
201 {
202   int recover = 0;
203 
204   /* set up port */
205   if (name == NULL)
206     {
207       DBG (3, "sanei_umax_pp_attach(%d,NULL)\n", port);
208     }
209   else
210     {
211       DBG (3, "sanei_umax_pp_attach(%d,%s)\n", port, name);
212     }
213 
214   sanei_umax_pp_setport (port);
215   if (sanei_umax_pp_initPort (port, name) != 1)
216     return UMAX1220P_PROBE_FAILED;
217 
218   /* init port locks the port, so we flag that */
219   locked = 1;
220 
221   if (sanei_umax_pp_probeScanner (recover) != 1)
222     {
223       if (recover)
224         {
225           sanei_umax_pp_initTransport (recover);
226           sanei_umax_pp_endSession ();
227           if (sanei_umax_pp_probeScanner (recover) != 1)
228             {
229               DBG (0, "Recover failed ....\n");
230               unlock_parport ();
231               return UMAX1220P_PROBE_FAILED;
232             }
233         }
234       else
235         {
236           unlock_parport ();
237           return UMAX1220P_PROBE_FAILED;
238         }
239     }
240   sanei_umax_pp_endSession ();
241   unlock_parport ();
242 
243 
244   /* OK */
245   return UMAX1220P_OK;
246 }
247 
248 
249 int
sanei_umax_pp_open(int port, char *name)250 sanei_umax_pp_open (int port, char *name)
251 {
252   int rc;
253   int recover = 0;
254 
255   /* set up port */
256   DBG (3, "sanei_umax_pp_open\n");
257 
258   if (name == NULL)
259     sanei_umax_pp_setport (port);
260 
261   if (lock_parport () == UMAX1220P_BUSY)
262     return UMAX1220P_BUSY;
263 
264   /* init transport layer */
265   /* 0: failed
266      1: success
267      2: retry
268      3: scanner busy
269    */
270   do
271     {
272       rc = sanei_umax_pp_initTransport (recover);
273     }
274   while (rc == 2);
275 
276   if (rc == 3)
277     {
278       unlock_parport ();
279       return UMAX1220P_BUSY;
280     }
281 
282   if (rc != 1)
283     {
284 
285       DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__,
286            __LINE__);
287       unlock_parport ();
288       return UMAX1220P_TRANSPORT_FAILED;
289     }
290   /* init scanner */
291   if (sanei_umax_pp_initScanner (recover) == 0)
292     {
293       DBG (0, "sanei_umax_pp_initScanner() failed (%s:%d)\n", __FILE__,
294            __LINE__);
295       sanei_umax_pp_endSession ();
296       unlock_parport ();
297       return UMAX1220P_SCANNER_FAILED;
298     }
299 
300   /* OK */
301   unlock_parport ();
302   return UMAX1220P_OK;
303 }
304 
305 
306 int
sanei_umax_pp_cancel(void)307 sanei_umax_pp_cancel (void)
308 {
309   DBG (3, "sanei_umax_pp_cancel\n");
310   if (lock_parport () == UMAX1220P_BUSY)
311     return UMAX1220P_BUSY;
312 
313   /* maybe EPAT reset here if exists */
314   sanei_umax_pp_cmdSync (0xC2);
315   sanei_umax_pp_cmdSync (0x00);
316   sanei_umax_pp_cmdSync (0x00);
317   if (sanei_umax_pp_park () == 0)
318     {
319       DBG (0, "sanei_umax_pp_park failed !!! (%s:%d)\n", __FILE__, __LINE__);
320       unlock_parport ();
321       return UMAX1220P_PARK_FAILED;
322     }
323   /* endSession() cancels any pending command  */
324   /* such as parking ...., so we only return   */
325   unlock_parport ();
326   return UMAX1220P_OK;
327 }
328 
329 
330 
331 int
sanei_umax_pp_start(int x, int y, int width, int height, int dpi, int color, int autoset, int gain, int offset, int *rbpp, int *rtw, int *rth)332 sanei_umax_pp_start (int x, int y, int width, int height, int dpi, int color,
333                      int autoset,
334                      int gain, int offset, int *rbpp, int *rtw,
335                      int *rth)
336 {
337   int col = BW_MODE;
338 
339   DBG (3, "sanei_umax_pp_start\n");
340   if (lock_parport () == UMAX1220P_BUSY)
341     return UMAX1220P_BUSY;
342   /* end session isn't done by cancel any more */
343   sanei_umax_pp_endSession ();
344 
345   if (autoset)
346     sanei_umax_pp_setauto (1);
347   else
348     sanei_umax_pp_setauto (0);
349 
350   switch (color)
351     {
352     case 0:
353       col = BW2_MODE;
354       break;
355     case 1:
356       col = BW_MODE;
357       break;
358     case 2:
359       col = RGB_MODE;
360       break;
361     }
362 
363   if (sanei_umax_pp_startScan
364       (x + sanei_umax_pp_getLeft (), y, width, height, dpi, col, gain,
365        offset, rbpp, rtw, rth) != 1)
366     {
367       sanei_umax_pp_endSession ();
368       unlock_parport ();
369       return UMAX1220P_START_FAILED;
370     }
371   unlock_parport ();
372   return UMAX1220P_OK;
373 }
374 
375 int
sanei_umax_pp_read(long len, int window, int dpi, int last, unsigned char *buffer)376 sanei_umax_pp_read (long len, int window, int dpi, int last,
377                     unsigned char *buffer)
378 {
379   int read = 0;
380   int bytes;
381 
382   DBG (3, "sanei_umax_pp_read\n");
383   if (lock_parport () == UMAX1220P_BUSY)
384     return UMAX1220P_BUSY;
385 
386   /* since 610P may override len and last to meet its */
387   /* hardware requirements, we have to loop until we  */
388   /* have all the data                                */
389   while (read < len)
390     {
391       bytes =
392         sanei_umax_pp_readBlock (len - read, window, dpi, last,
393                                  buffer + read);
394       if (bytes == 0)
395         {
396           sanei_umax_pp_endSession ();
397           return UMAX1220P_READ_FAILED;
398         }
399       read += bytes;
400     }
401   unlock_parport ();
402   return UMAX1220P_OK;
403 }
404 
405 
406 
407 int
sanei_umax_pp_lamp(int on)408 sanei_umax_pp_lamp (int on)
409 {
410   /* init transport layer */
411   DBG (3, "sanei_umax_pp_lamp\n");
412 
413   /* no lamp support for 610P ... */
414   if (sanei_umax_pp_getastra () < 1210)
415     return UMAX1220P_OK;
416 
417   if (lock_parport () == UMAX1220P_BUSY)
418     return UMAX1220P_BUSY;
419 
420   if (sanei_umax_pp_setLamp (on) == 0)
421     {
422       DBG (0, "Setting lamp state failed!\n");
423     }
424 
425   unlock_parport ();
426   return UMAX1220P_OK;
427 }
428 
429 
430 
431 
432 int
sanei_umax_pp_status(void)433 sanei_umax_pp_status (void)
434 {
435   int status;
436 
437   DBG (3, "sanei_umax_pp_status\n");
438   if (lock_parport () == UMAX1220P_BUSY)
439     return UMAX1220P_BUSY;
440   /* check if head is at home */
441   sanei_umax_pp_cmdSync (0x40);
442   status = sanei_umax_pp_scannerStatus ();
443   unlock_parport ();
444   DBG (8, "sanei_umax_pp_status=0x%02X\n", status);
445   if (((status & ASIC_BIT) != 0x00)||((status & MOTOR_BIT) == 0x00))
446     return UMAX1220P_BUSY;
447 
448   return UMAX1220P_OK;
449 }
450 
451 int
sanei_umax_pp_closenull452 sanei_umax_pp_close ()
453 {
454 #ifdef HAVE_LINUX_PPDEV_H
455   int fd;
456 #endif
457 
458   DBG (3, "sanei_umax_pp_close\n");
459 
460   lock_parport ();
461   sanei_umax_pp_endSession ();
462   unlock_parport ();
463 
464 #ifdef HAVE_LINUX_PPDEV_H
465   fd = sanei_umax_pp_getparport ();
466   if (fd > 0)
467     {
468       close (fd);
469       sanei_umax_pp_setparport (0);
470     }
471 #endif
472   return UMAX1220P_OK;
473 }
474