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 */ 62static int locked = 0; 63#ifdef HAVE_LINUX_PPDEV_H 64static int exmode = IEEE1284_MODE_COMPAT; 65static int exflags = 0; 66#endif 67 68static int 69lock_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 */ 105static int 106unlock_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 */ 139int 140sanei_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 199int 200sanei_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 249int 250sanei_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 306int 307sanei_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 331int 332sanei_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 375int 376sanei_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 407int 408sanei_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 432int 433sanei_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 451int 452sanei_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