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