diff options
Diffstat (limited to 'backend/umax_pp_mid.c')
-rw-r--r-- | backend/umax_pp_mid.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/backend/umax_pp_mid.c b/backend/umax_pp_mid.c new file mode 100644 index 0000000..ee8d98d --- /dev/null +++ b/backend/umax_pp_mid.c @@ -0,0 +1,475 @@ +/* sane - Scanner Access Now Easy. + Copyright (C) 2001-2012 Stéphane Voltz <stef.dev@free.fr> + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. + + This file implements a SANE backend for Umax PP flatbed scanners. */ + +#define DEBUG_DECLARE_ONLY +#undef BACKEND_NAME +#define BACKEND_NAME umax_pp + +#include "../include/sane/config.h" +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdio.h> +#include "../include/sane/sanei_debug.h" + +#define __MAIN__ + + +#include "umax_pp_mid.h" + +/* this function locks the parallel port so that other devices */ +/* won't interfere. Returns UMAX1220P_BUSY is port cannot be */ +/* lock or UMAX1220P_OK if it is locked */ +static int locked = 0; +#ifdef HAVE_LINUX_PPDEV_H +static int exmode = IEEE1284_MODE_COMPAT; +static int exflags = 0; +#endif + +static int +lock_parport (void) +{ +#ifdef HAVE_LINUX_PPDEV_H + int mode, fd; +#endif + + DBG_INIT (); + DBG (3, "lock_parport\n"); + +#ifdef HAVE_LINUX_PPDEV_H + fd = sanei_umax_pp_getparport (); + if ((fd > 0) && (!locked)) + { + if (ioctl (sanei_umax_pp_getparport (), PPCLAIM)) + { + return UMAX1220P_BUSY; + } +#ifdef PPGETMODE + if (ioctl (fd, PPGETMODE, &exmode)) + exmode = IEEE1284_MODE_COMPAT; + if (ioctl (fd, PPGETFLAGS, &exflags)) + exflags = 0; +#endif + mode = IEEE1284_MODE_EPP; + ioctl (fd, PPNEGOT, &mode); + ioctl (fd, PPSETMODE, &mode); + locked = 1; + } +#else + locked = 1; +#endif + return UMAX1220P_OK; +} + + +/* this function release parport */ +static int +unlock_parport (void) +{ +#ifdef HAVE_LINUX_PPDEV_H + int fd, mode; + + fd = sanei_umax_pp_getparport (); + if ((fd > 0) && (locked)) + { + mode = IEEE1284_MODE_COMPAT; + ioctl (fd, PPNEGOT, &mode); + ioctl (fd, PPSETMODE, &exmode); +#ifdef PPSETFLAGS + ioctl (fd, PPSETFLAGS, &exflags); +#endif + ioctl (fd, PPRELEASE); + locked = 1; + } +#endif + DBG (3, "unlock_parport\n"); + locked = 0; + return UMAX1220P_OK; +} + + + + +/* + * + * This function recognize the scanner model by sending an image + * filter command. 1220P will use it as is, but 2000P will return + * it back modified. + * + */ +int +sanei_umax_pp_model (int port, int *model) +{ + int recover = 0, rc; + + /* set up port */ + DBG (3, "sanei_umax_pp_model\n"); + sanei_umax_pp_setport (port); + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + + /* init transport layer */ + /* 0: failed + 1: success + 2: retry + 3: busy + */ + do + { + rc = sanei_umax_pp_initTransport (recover); + } + while (rc == 2); + + if (rc == 3) + { + unlock_parport (); + return UMAX1220P_BUSY; + } + if (rc != 1) + { + DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__, + __LINE__); + unlock_parport (); + return UMAX1220P_TRANSPORT_FAILED; + } + + /* check model only, and if only none given in conf file */ + if (!sanei_umax_pp_getastra ()) + { + rc = sanei_umax_pp_checkModel (); + } + else + { + rc = sanei_umax_pp_getastra (); + } + sanei_umax_pp_endSession (); + unlock_parport (); + if (rc < 600) + { + DBG (0, "sanei_umax_pp_CheckModel() failed (%s:%d)\n", __FILE__, + __LINE__); + return UMAX1220P_PROBE_FAILED; + } + *model = rc; + + + /* OK */ + return UMAX1220P_OK; +} + +int +sanei_umax_pp_attach (int port, char *name) +{ + int recover = 0; + + /* set up port */ + if (name == NULL) + { + DBG (3, "sanei_umax_pp_attach(%d,NULL)\n", port); + } + else + { + DBG (3, "sanei_umax_pp_attach(%d,%s)\n", port, name); + } + + sanei_umax_pp_setport (port); + if (sanei_umax_pp_initPort (port, name) != 1) + return UMAX1220P_PROBE_FAILED; + + /* init port locks the port, so we flag that */ + locked = 1; + + if (sanei_umax_pp_probeScanner (recover) != 1) + { + if (recover) + { + sanei_umax_pp_initTransport (recover); + sanei_umax_pp_endSession (); + if (sanei_umax_pp_probeScanner (recover) != 1) + { + DBG (0, "Recover failed ....\n"); + unlock_parport (); + return UMAX1220P_PROBE_FAILED; + } + } + else + { + unlock_parport (); + return UMAX1220P_PROBE_FAILED; + } + } + sanei_umax_pp_endSession (); + unlock_parport (); + + + /* OK */ + return UMAX1220P_OK; +} + + +int +sanei_umax_pp_open (int port, char *name) +{ + int rc; + int recover = 0; + + /* set up port */ + DBG (3, "sanei_umax_pp_open\n"); + + if (name == NULL) + sanei_umax_pp_setport (port); + + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + + /* init transport layer */ + /* 0: failed + 1: success + 2: retry + 3: scanner busy + */ + do + { + rc = sanei_umax_pp_initTransport (recover); + } + while (rc == 2); + + if (rc == 3) + { + unlock_parport (); + return UMAX1220P_BUSY; + } + + if (rc != 1) + { + + DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__, + __LINE__); + unlock_parport (); + return UMAX1220P_TRANSPORT_FAILED; + } + /* init scanner */ + if (sanei_umax_pp_initScanner (recover) == 0) + { + DBG (0, "sanei_umax_pp_initScanner() failed (%s:%d)\n", __FILE__, + __LINE__); + sanei_umax_pp_endSession (); + unlock_parport (); + return UMAX1220P_SCANNER_FAILED; + } + + /* OK */ + unlock_parport (); + return UMAX1220P_OK; +} + + +int +sanei_umax_pp_cancel (void) +{ + DBG (3, "sanei_umax_pp_cancel\n"); + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + + /* maybe EPAT reset here if exists */ + sanei_umax_pp_cmdSync (0xC2); + sanei_umax_pp_cmdSync (0x00); + sanei_umax_pp_cmdSync (0x00); + if (sanei_umax_pp_park () == 0) + { + DBG (0, "sanei_umax_pp_park failed !!! (%s:%d)\n", __FILE__, __LINE__); + unlock_parport (); + return UMAX1220P_PARK_FAILED; + } + /* endSession() cancels any pending command */ + /* such as parking ...., so we only return */ + unlock_parport (); + return UMAX1220P_OK; +} + + + +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) +{ + int col = BW_MODE; + + DBG (3, "sanei_umax_pp_start\n"); + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + /* end session isn't done by cancel any more */ + sanei_umax_pp_endSession (); + + if (autoset) + sanei_umax_pp_setauto (1); + else + sanei_umax_pp_setauto (0); + + switch (color) + { + case 0: + col = BW2_MODE; + break; + case 1: + col = BW_MODE; + break; + case 2: + col = RGB_MODE; + break; + } + + if (sanei_umax_pp_startScan + (x + sanei_umax_pp_getLeft (), y, width, height, dpi, col, gain, + offset, rbpp, rtw, rth) != 1) + { + sanei_umax_pp_endSession (); + unlock_parport (); + return UMAX1220P_START_FAILED; + } + unlock_parport (); + return UMAX1220P_OK; +} + +int +sanei_umax_pp_read (long len, int window, int dpi, int last, + unsigned char *buffer) +{ + int read = 0; + int bytes; + + DBG (3, "sanei_umax_pp_read\n"); + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + + /* since 610P may override len and last to meet its */ + /* hardware requirements, we have to loop until we */ + /* have all the data */ + while (read < len) + { + bytes = + sanei_umax_pp_readBlock (len - read, window, dpi, last, + buffer + read); + if (bytes == 0) + { + sanei_umax_pp_endSession (); + return UMAX1220P_READ_FAILED; + } + read += bytes; + } + unlock_parport (); + return UMAX1220P_OK; +} + + + +int +sanei_umax_pp_lamp (int on) +{ + /* init transport layer */ + DBG (3, "sanei_umax_pp_lamp\n"); + + /* no lamp support for 610P ... */ + if (sanei_umax_pp_getastra () < 1210) + return UMAX1220P_OK; + + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + + if (sanei_umax_pp_setLamp (on) == 0) + { + DBG (0, "Setting lamp state failed!\n"); + } + + unlock_parport (); + return UMAX1220P_OK; +} + + + + +int +sanei_umax_pp_status (void) +{ + int status; + + DBG (3, "sanei_umax_pp_status\n"); + if (lock_parport () == UMAX1220P_BUSY) + return UMAX1220P_BUSY; + /* check if head is at home */ + sanei_umax_pp_cmdSync (0x40); + status = sanei_umax_pp_scannerStatus (); + unlock_parport (); + DBG (8, "sanei_umax_pp_status=0x%02X\n", status); + if (((status & ASIC_BIT) != 0x00)||((status & MOTOR_BIT) == 0x00)) + return UMAX1220P_BUSY; + + return UMAX1220P_OK; +} + +int +sanei_umax_pp_close () +{ +#ifdef HAVE_LINUX_PPDEV_H + int fd; +#endif + + DBG (3, "sanei_umax_pp_close\n"); + + lock_parport (); + sanei_umax_pp_endSession (); + unlock_parport (); + +#ifdef HAVE_LINUX_PPDEV_H + fd = sanei_umax_pp_getparport (); + if (fd > 0) + { + close (fd); + sanei_umax_pp_setparport (0); + } +#endif + return UMAX1220P_OK; +} |