1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 1997 Geoffrey T. Dairiki 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci This file is part of a SANE backend for HP Scanners supporting 40141cc406Sopenharmony_ci HP Scanner Control Language (SCL). 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* 44141cc406Sopenharmony_ci Revision 1.15 2008/03/28 14:37:36 kitno-guest 45141cc406Sopenharmony_ci add usleep to improve usb performance, from jim a t meyering d o t net 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci Revision 1.14 2004-10-04 18:09:05 kig-guest 48141cc406Sopenharmony_ci Rename global function hp_init_openfd to sanei_hp_init_openfd 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci Revision 1.13 2004/03/27 13:52:39 kig-guest 51141cc406Sopenharmony_ci Keep USB-connection open (was problem with Linux 2.6.x) 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci Revision 1.12 2003/10/09 19:34:57 kig-guest 54141cc406Sopenharmony_ci Redo when TEST UNIT READY failed 55141cc406Sopenharmony_ci Redo when read returns with 0 bytes (non-SCSI only) 56141cc406Sopenharmony_ci*/ 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci/* 59141cc406Sopenharmony_ci#define STUBS 60141cc406Sopenharmony_ciextern int sanei_debug_hp;*/ 61141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 62141cc406Sopenharmony_ci#include "../include/sane/config.h" 63141cc406Sopenharmony_ci#include "../include/lalloca.h" /* Must be first */ 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci#ifdef HAVE_UNISTD_H 66141cc406Sopenharmony_ci# include <unistd.h> 67141cc406Sopenharmony_ci#endif 68141cc406Sopenharmony_ci#include <stdlib.h> 69141cc406Sopenharmony_ci#include <ctype.h> 70141cc406Sopenharmony_ci#include <stdio.h> 71141cc406Sopenharmony_ci#include <string.h> 72141cc406Sopenharmony_ci#include <errno.h> 73141cc406Sopenharmony_ci#include "../include/lassert.h" 74141cc406Sopenharmony_ci#include <signal.h> 75141cc406Sopenharmony_ci#include <sys/types.h> 76141cc406Sopenharmony_ci#include <sys/stat.h> 77141cc406Sopenharmony_ci#include <fcntl.h> 78141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 79141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 80141cc406Sopenharmony_ci#include "../include/sane/sanei_pio.h" 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci#include "hp.h" 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#include "hp-option.h" 87141cc406Sopenharmony_ci#include "hp-scsi.h" 88141cc406Sopenharmony_ci#include "hp-scl.h" 89141cc406Sopenharmony_ci#include "hp-device.h" 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci#define HP_SCSI_INQ_LEN (36) 92141cc406Sopenharmony_ci#define HP_SCSI_CMD_LEN (6) 93141cc406Sopenharmony_ci#define HP_SCSI_BUFSIZ (HP_SCSI_MAX_WRITE + HP_SCSI_CMD_LEN) 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci#define HP_MAX_OPEN_FD 16 96141cc406Sopenharmony_cistatic struct hp_open_fd_s /* structure to save info about open file descriptor */ 97141cc406Sopenharmony_ci{ 98141cc406Sopenharmony_ci char *devname; 99141cc406Sopenharmony_ci HpConnect connect; 100141cc406Sopenharmony_ci int fd; 101141cc406Sopenharmony_ci} asHpOpenFd[HP_MAX_OPEN_FD]; 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci/* 105141cc406Sopenharmony_ci * 106141cc406Sopenharmony_ci */ 107141cc406Sopenharmony_cistruct hp_scsi_s 108141cc406Sopenharmony_ci{ 109141cc406Sopenharmony_ci int fd; 110141cc406Sopenharmony_ci char * devname; 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci /* Output buffering */ 113141cc406Sopenharmony_ci hp_byte_t buf[HP_SCSI_BUFSIZ]; 114141cc406Sopenharmony_ci hp_byte_t * bufp; 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci hp_byte_t inq_data[HP_SCSI_INQ_LEN]; 117141cc406Sopenharmony_ci}; 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_ci#define HP_TMP_BUF_SIZE (1024*4) 120141cc406Sopenharmony_ci#define HP_WR_BUF_SIZE (1024*4) 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_citypedef struct 123141cc406Sopenharmony_ci{ 124141cc406Sopenharmony_ci HpProcessData procdata; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci int outfd; 127141cc406Sopenharmony_ci const unsigned char *map; 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_ci unsigned char *image_buf; /* Buffer to store complete image (if req.) */ 130141cc406Sopenharmony_ci unsigned char *image_ptr; 131141cc406Sopenharmony_ci int image_buf_size; 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci unsigned char *tmp_buf; /* Buffer for scan data to get even number of bytes */ 134141cc406Sopenharmony_ci int tmp_buf_size; 135141cc406Sopenharmony_ci int tmp_buf_len; 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci unsigned char wr_buf[HP_WR_BUF_SIZE]; 138141cc406Sopenharmony_ci unsigned char *wr_ptr; 139141cc406Sopenharmony_ci int wr_buf_size; 140141cc406Sopenharmony_ci int wr_left; 141141cc406Sopenharmony_ci} PROCDATA_HANDLE; 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci/* Initialize structure where we remember out open file descriptors */ 145141cc406Sopenharmony_civoid 146141cc406Sopenharmony_cisanei_hp_init_openfd () 147141cc406Sopenharmony_ci{int iCount; 148141cc406Sopenharmony_ci memset (asHpOpenFd, 0, sizeof (asHpOpenFd)); 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) 151141cc406Sopenharmony_ci asHpOpenFd[iCount].fd = -1; 152141cc406Sopenharmony_ci} 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_ci/* Look if the device is still open */ 156141cc406Sopenharmony_cistatic SANE_Status 157141cc406Sopenharmony_cihp_GetOpenDevice (const char *devname, HpConnect connect, int *pfd) 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci{int iCount; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci if (!asHpOpenFd[iCount].devname) continue; 164141cc406Sopenharmony_ci if ( (strcmp (asHpOpenFd[iCount].devname, devname) == 0) 165141cc406Sopenharmony_ci && (asHpOpenFd[iCount].connect == connect) ) 166141cc406Sopenharmony_ci { 167141cc406Sopenharmony_ci if (pfd) *pfd = asHpOpenFd[iCount].fd; 168141cc406Sopenharmony_ci DBG(3, "hp_GetOpenDevice: device %s is open with fd=%d\n", devname, 169141cc406Sopenharmony_ci asHpOpenFd[iCount].fd); 170141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 171141cc406Sopenharmony_ci } 172141cc406Sopenharmony_ci } 173141cc406Sopenharmony_ci DBG(3, "hp_GetOpenDevice: device %s not open\n", devname); 174141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 175141cc406Sopenharmony_ci} 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci/* Add an open file descriptor. This also decides */ 178141cc406Sopenharmony_ci/* if we keep a connection open or not. */ 179141cc406Sopenharmony_cistatic SANE_Status 180141cc406Sopenharmony_cihp_AddOpenDevice (const char *devname, HpConnect connect, int fd) 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci{int iCount, iKeepOpen; 183141cc406Sopenharmony_ci static int iInitKeepFlags = 1; 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci /* The default values which connections to keep open or not */ 186141cc406Sopenharmony_ci static int iKeepOpenSCSI = 0; 187141cc406Sopenharmony_ci static int iKeepOpenUSB = 1; 188141cc406Sopenharmony_ci static int iKeepOpenDevice = 0; 189141cc406Sopenharmony_ci static int iKeepOpenPIO = 0; 190141cc406Sopenharmony_ci 191141cc406Sopenharmony_ci if (iInitKeepFlags) /* Change the defaults by environment */ 192141cc406Sopenharmony_ci {char *eptr; 193141cc406Sopenharmony_ci 194141cc406Sopenharmony_ci iInitKeepFlags = 0; 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci eptr = getenv ("SANE_HP_KEEPOPEN_SCSI"); 197141cc406Sopenharmony_ci if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) 198141cc406Sopenharmony_ci iKeepOpenSCSI = (*eptr == '1'); 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci eptr = getenv ("SANE_HP_KEEPOPEN_USB"); 201141cc406Sopenharmony_ci if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) 202141cc406Sopenharmony_ci iKeepOpenUSB = (*eptr == '1'); 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci eptr = getenv ("SANE_HP_KEEPOPEN_DEVICE"); 205141cc406Sopenharmony_ci if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) 206141cc406Sopenharmony_ci iKeepOpenDevice = (*eptr == '1'); 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci eptr = getenv ("SANE_HP_KEEPOPEN_PIO"); 209141cc406Sopenharmony_ci if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) 210141cc406Sopenharmony_ci iKeepOpenPIO = (*eptr == '1'); 211141cc406Sopenharmony_ci } 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci /* Look if we should keep it open or not */ 214141cc406Sopenharmony_ci iKeepOpen = 0; 215141cc406Sopenharmony_ci switch (connect) 216141cc406Sopenharmony_ci { 217141cc406Sopenharmony_ci case HP_CONNECT_SCSI: iKeepOpen = iKeepOpenSCSI; 218141cc406Sopenharmony_ci break; 219141cc406Sopenharmony_ci case HP_CONNECT_PIO : iKeepOpen = iKeepOpenPIO; 220141cc406Sopenharmony_ci break; 221141cc406Sopenharmony_ci case HP_CONNECT_USB : iKeepOpen = iKeepOpenUSB; 222141cc406Sopenharmony_ci break; 223141cc406Sopenharmony_ci case HP_CONNECT_DEVICE : iKeepOpen = iKeepOpenDevice; 224141cc406Sopenharmony_ci break; 225141cc406Sopenharmony_ci case HP_CONNECT_RESERVE: 226141cc406Sopenharmony_ci break; 227141cc406Sopenharmony_ci } 228141cc406Sopenharmony_ci if (!iKeepOpen) 229141cc406Sopenharmony_ci { 230141cc406Sopenharmony_ci DBG(3, "hp_AddOpenDevice: %s should not be kept open\n", devname); 231141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 232141cc406Sopenharmony_ci } 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) 235141cc406Sopenharmony_ci { 236141cc406Sopenharmony_ci if (!asHpOpenFd[iCount].devname) /* Is this entry free ? */ 237141cc406Sopenharmony_ci { 238141cc406Sopenharmony_ci asHpOpenFd[iCount].devname = sanei_hp_strdup (devname); 239141cc406Sopenharmony_ci if (!asHpOpenFd[iCount].devname) return SANE_STATUS_NO_MEM; 240141cc406Sopenharmony_ci DBG(3, "hp_AddOpenDevice: added device %s with fd=%d\n", devname, fd); 241141cc406Sopenharmony_ci asHpOpenFd[iCount].connect = connect; 242141cc406Sopenharmony_ci asHpOpenFd[iCount].fd = fd; 243141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 244141cc406Sopenharmony_ci } 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci DBG(3, "hp_AddOpenDevice: %s not added\n", devname); 247141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 248141cc406Sopenharmony_ci} 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci/* Check if we have remembered an open file descriptor */ 252141cc406Sopenharmony_cistatic SANE_Status 253141cc406Sopenharmony_cihp_IsOpenFd (int fd, HpConnect connect) 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci{int iCount; 256141cc406Sopenharmony_ci 257141cc406Sopenharmony_ci for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) 258141cc406Sopenharmony_ci { 259141cc406Sopenharmony_ci if ( (asHpOpenFd[iCount].devname != NULL) 260141cc406Sopenharmony_ci && (asHpOpenFd[iCount].fd == fd) 261141cc406Sopenharmony_ci && (asHpOpenFd[iCount].connect == connect) ) 262141cc406Sopenharmony_ci { 263141cc406Sopenharmony_ci DBG(3, "hp_IsOpenFd: %d is open\n", fd); 264141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 265141cc406Sopenharmony_ci } 266141cc406Sopenharmony_ci } 267141cc406Sopenharmony_ci DBG(3, "hp_IsOpenFd: %d not open\n", fd); 268141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 269141cc406Sopenharmony_ci} 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_cistatic SANE_Status 273141cc406Sopenharmony_cihp_RemoveOpenFd (int fd, HpConnect connect) 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci{int iCount; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) 278141cc406Sopenharmony_ci { 279141cc406Sopenharmony_ci if ( (asHpOpenFd[iCount].devname != NULL) 280141cc406Sopenharmony_ci && (asHpOpenFd[iCount].fd == fd) 281141cc406Sopenharmony_ci && (asHpOpenFd[iCount].connect == connect) ) 282141cc406Sopenharmony_ci { 283141cc406Sopenharmony_ci sanei_hp_free (asHpOpenFd[iCount].devname); 284141cc406Sopenharmony_ci asHpOpenFd[iCount].devname = NULL; 285141cc406Sopenharmony_ci DBG(3, "hp_RemoveOpenFd: removed %d\n", asHpOpenFd[iCount].fd); 286141cc406Sopenharmony_ci asHpOpenFd[iCount].fd = -1; 287141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 288141cc406Sopenharmony_ci } 289141cc406Sopenharmony_ci } 290141cc406Sopenharmony_ci DBG(3, "hp_RemoveOpenFd: %d not removed\n", fd); 291141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 292141cc406Sopenharmony_ci} 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_cistatic SANE_Status 296141cc406Sopenharmony_cihp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect) 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci{int n = -1; 299141cc406Sopenharmony_ci size_t loc_len; 300141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci if (len <= 0) return SANE_STATUS_GOOD; 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci switch (connect) 305141cc406Sopenharmony_ci { 306141cc406Sopenharmony_ci case HP_CONNECT_DEVICE: /* direct device-io */ 307141cc406Sopenharmony_ci n = write (this->fd, data, len); 308141cc406Sopenharmony_ci break; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci case HP_CONNECT_PIO: /* Use sanepio interface */ 311141cc406Sopenharmony_ci n = sanei_pio_write (this->fd, data, len); 312141cc406Sopenharmony_ci break; 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ci case HP_CONNECT_USB: /* Not supported */ 315141cc406Sopenharmony_ci loc_len = len; 316141cc406Sopenharmony_ci status = sanei_usb_write_bulk ((SANE_Int)this->fd, data, &loc_len); 317141cc406Sopenharmony_ci n = loc_len; 318141cc406Sopenharmony_ci break; 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci case HP_CONNECT_RESERVE: 321141cc406Sopenharmony_ci n = -1; 322141cc406Sopenharmony_ci break; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci default: 325141cc406Sopenharmony_ci n = -1; 326141cc406Sopenharmony_ci break; 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci if (n == 0) return SANE_STATUS_EOF; 330141cc406Sopenharmony_ci else if (n < 0) return SANE_STATUS_IO_ERROR; 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci return status; 333141cc406Sopenharmony_ci} 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_cistatic SANE_Status 336141cc406Sopenharmony_cihp_nonscsi_read (HpScsi this, hp_byte_t *data, size_t *len, HpConnect connect, 337141cc406Sopenharmony_ci int __sane_unused__ isResponse) 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci{int n = -1; 340141cc406Sopenharmony_ci static int retries = -1; 341141cc406Sopenharmony_ci size_t save_len = *len; 342141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci if (*len <= 0) return SANE_STATUS_GOOD; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci if (retries < 0) /* Read environment */ 347141cc406Sopenharmony_ci {char *eptr = getenv ("SANE_HP_RDREDO"); 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci retries = 1; /* Set default value */ 350141cc406Sopenharmony_ci if (eptr != NULL) 351141cc406Sopenharmony_ci { 352141cc406Sopenharmony_ci if (sscanf (eptr, "%d", &retries) != 1) retries = 1; /* Restore default */ 353141cc406Sopenharmony_ci else if (retries < 0) retries = 0; /* Allow no retries here */ 354141cc406Sopenharmony_ci } 355141cc406Sopenharmony_ci } 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci for (;;) /* Retry on EOF */ 358141cc406Sopenharmony_ci { 359141cc406Sopenharmony_ci switch (connect) 360141cc406Sopenharmony_ci { 361141cc406Sopenharmony_ci case HP_CONNECT_DEVICE: 362141cc406Sopenharmony_ci n = read (this->fd, data, *len); 363141cc406Sopenharmony_ci break; 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci case HP_CONNECT_PIO: 366141cc406Sopenharmony_ci n = sanei_pio_read (this->fd, data, *len); 367141cc406Sopenharmony_ci break; 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci case HP_CONNECT_USB: 370141cc406Sopenharmony_ci status = sanei_usb_read_bulk((SANE_Int)this->fd, (SANE_Byte *)data, len); 371141cc406Sopenharmony_ci n = *len; 372141cc406Sopenharmony_ci break; 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci case HP_CONNECT_RESERVE: 375141cc406Sopenharmony_ci n = -1; 376141cc406Sopenharmony_ci break; 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci default: 379141cc406Sopenharmony_ci n = -1; 380141cc406Sopenharmony_ci break; 381141cc406Sopenharmony_ci } 382141cc406Sopenharmony_ci if ((n != 0) || (retries <= 0)) break; 383141cc406Sopenharmony_ci retries--; 384141cc406Sopenharmony_ci usleep (100*1000); /* sleep 0.1 seconds */ 385141cc406Sopenharmony_ci *len = save_len; /* Restore value */ 386141cc406Sopenharmony_ci } 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci if (n == 0) return SANE_STATUS_EOF; 389141cc406Sopenharmony_ci else if (n < 0) return SANE_STATUS_IO_ERROR; 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci *len = n; 392141cc406Sopenharmony_ci return status; 393141cc406Sopenharmony_ci} 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_cistatic SANE_Status 396141cc406Sopenharmony_cihp_nonscsi_open (const char *devname, int *fd, HpConnect connect) 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci{int lfd, flags; 399141cc406Sopenharmony_ci SANE_Int dn; 400141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_INVAL; 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci#ifdef _O_RDWR 403141cc406Sopenharmony_ci flags = _O_RDWR; 404141cc406Sopenharmony_ci#else 405141cc406Sopenharmony_ci flags = O_RDWR; 406141cc406Sopenharmony_ci#endif 407141cc406Sopenharmony_ci#ifdef _O_EXCL 408141cc406Sopenharmony_ci flags |= _O_EXCL; 409141cc406Sopenharmony_ci#else 410141cc406Sopenharmony_ci flags |= O_EXCL; 411141cc406Sopenharmony_ci#endif 412141cc406Sopenharmony_ci#ifdef _O_BINARY 413141cc406Sopenharmony_ci flags |= _O_BINARY; 414141cc406Sopenharmony_ci#endif 415141cc406Sopenharmony_ci#ifdef O_BINARY 416141cc406Sopenharmony_ci flags |= O_BINARY; 417141cc406Sopenharmony_ci#endif 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci switch (connect) 420141cc406Sopenharmony_ci { 421141cc406Sopenharmony_ci case HP_CONNECT_DEVICE: 422141cc406Sopenharmony_ci lfd = open (devname, flags); 423141cc406Sopenharmony_ci if (lfd < 0) 424141cc406Sopenharmony_ci { 425141cc406Sopenharmony_ci DBG(1, "hp_nonscsi_open: open device %s failed (%s)\n", devname, 426141cc406Sopenharmony_ci strerror (errno) ); 427141cc406Sopenharmony_ci status = (errno == EACCES) ? SANE_STATUS_ACCESS_DENIED : SANE_STATUS_INVAL; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci else 430141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 431141cc406Sopenharmony_ci break; 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci case HP_CONNECT_PIO: 434141cc406Sopenharmony_ci status = sanei_pio_open (devname, &lfd); 435141cc406Sopenharmony_ci break; 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci case HP_CONNECT_USB: 438141cc406Sopenharmony_ci DBG(17, "hp_nonscsi_open: open usb with \"%s\"\n", devname); 439141cc406Sopenharmony_ci status = sanei_usb_open (devname, &dn); 440141cc406Sopenharmony_ci lfd = (int)dn; 441141cc406Sopenharmony_ci break; 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci case HP_CONNECT_RESERVE: 444141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 445141cc406Sopenharmony_ci break; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci default: 448141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 449141cc406Sopenharmony_ci break; 450141cc406Sopenharmony_ci } 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 453141cc406Sopenharmony_ci { 454141cc406Sopenharmony_ci DBG(1, "hp_nonscsi_open: open device %s failed\n", devname); 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci else 457141cc406Sopenharmony_ci { 458141cc406Sopenharmony_ci DBG(17,"hp_nonscsi_open: device %s opened, fd=%d\n", devname, lfd); 459141cc406Sopenharmony_ci } 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci if (fd) *fd = lfd; 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci return status; 464141cc406Sopenharmony_ci} 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_cistatic void 467141cc406Sopenharmony_cihp_nonscsi_close (int fd, HpConnect connect) 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_ci{ 470141cc406Sopenharmony_ci switch (connect) 471141cc406Sopenharmony_ci { 472141cc406Sopenharmony_ci case HP_CONNECT_DEVICE: 473141cc406Sopenharmony_ci close (fd); 474141cc406Sopenharmony_ci break; 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci case HP_CONNECT_PIO: 477141cc406Sopenharmony_ci sanei_pio_close (fd); 478141cc406Sopenharmony_ci break; 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci case HP_CONNECT_USB: 481141cc406Sopenharmony_ci sanei_usb_close (fd); 482141cc406Sopenharmony_ci break; 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci case HP_CONNECT_RESERVE: 485141cc406Sopenharmony_ci break; 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci default: 488141cc406Sopenharmony_ci break; 489141cc406Sopenharmony_ci } 490141cc406Sopenharmony_ci DBG(17,"hp_nonscsi_close: closed fd=%d\n", fd); 491141cc406Sopenharmony_ci} 492141cc406Sopenharmony_ci 493141cc406Sopenharmony_ciSANE_Status 494141cc406Sopenharmony_cisanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect) 495141cc406Sopenharmony_ci{ 496141cc406Sopenharmony_ci HpScsi new; 497141cc406Sopenharmony_ci SANE_Status status; 498141cc406Sopenharmony_ci int iAlreadyOpen = 0; 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci new = sanei_hp_allocz(sizeof(*new)); 501141cc406Sopenharmony_ci if (!new) 502141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci /* Is the device already open ? */ 505141cc406Sopenharmony_ci if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) 506141cc406Sopenharmony_ci { 507141cc406Sopenharmony_ci iAlreadyOpen = 1; 508141cc406Sopenharmony_ci } 509141cc406Sopenharmony_ci else 510141cc406Sopenharmony_ci { 511141cc406Sopenharmony_ci status = hp_nonscsi_open(devname, &new->fd, connect); 512141cc406Sopenharmony_ci if (FAILED(status)) 513141cc406Sopenharmony_ci { 514141cc406Sopenharmony_ci DBG(1, "nonscsi_new: open failed (%s)\n", sane_strstatus(status)); 515141cc406Sopenharmony_ci sanei_hp_free(new); 516141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 517141cc406Sopenharmony_ci } 518141cc406Sopenharmony_ci } 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ci /* For SCSI-devices we would have the inquire command here */ 521141cc406Sopenharmony_ci memcpy (new->inq_data, "\003zzzzzzzHP ------ R000", 522141cc406Sopenharmony_ci sizeof (new->inq_data)); 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci new->bufp = new->buf + HP_SCSI_CMD_LEN; 525141cc406Sopenharmony_ci new->devname = sanei_hp_alloc ( strlen ( devname ) + 1 ); 526141cc406Sopenharmony_ci if ( new->devname ) strcpy (new->devname, devname); 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci *newp = new; 529141cc406Sopenharmony_ci 530141cc406Sopenharmony_ci /* Remember the open device */ 531141cc406Sopenharmony_ci if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 534141cc406Sopenharmony_ci} 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_cistatic void 537141cc406Sopenharmony_cihp_scsi_close (HpScsi this, int completely) 538141cc406Sopenharmony_ci{HpConnect connect; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci DBG(3, "scsi_close: closing fd %ld\n", (long)this->fd); 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci connect = sanei_hp_scsi_get_connect (this); 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci if (!completely) /* May we keep the device open ? */ 545141cc406Sopenharmony_ci { 546141cc406Sopenharmony_ci if ( hp_IsOpenFd (this->fd, connect) == SANE_STATUS_GOOD ) 547141cc406Sopenharmony_ci { 548141cc406Sopenharmony_ci DBG(3, "scsi_close: not closing. Keep open\n"); 549141cc406Sopenharmony_ci return; 550141cc406Sopenharmony_ci } 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci } 553141cc406Sopenharmony_ci assert(this->fd >= 0); 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci if (connect != HP_CONNECT_SCSI) 556141cc406Sopenharmony_ci hp_nonscsi_close (this->fd, connect); 557141cc406Sopenharmony_ci else 558141cc406Sopenharmony_ci sanei_scsi_close (this->fd); 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_ci DBG(3,"scsi_close: really closed\n"); 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci /* Remove a remembered open device */ 563141cc406Sopenharmony_ci hp_RemoveOpenFd (this->fd, connect); 564141cc406Sopenharmony_ci} 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ciSANE_Status 568141cc406Sopenharmony_cisanei_hp_scsi_new (HpScsi * newp, const char * devname) 569141cc406Sopenharmony_ci{ 570141cc406Sopenharmony_ci static hp_byte_t inq_cmd[] = { 0x12, 0, 0, 0, HP_SCSI_INQ_LEN, 0}; 571141cc406Sopenharmony_ci static hp_byte_t tur_cmd[] = { 0x00, 0, 0, 0, 0, 0}; 572141cc406Sopenharmony_ci size_t inq_len = HP_SCSI_INQ_LEN; 573141cc406Sopenharmony_ci HpScsi new; 574141cc406Sopenharmony_ci HpConnect connect; 575141cc406Sopenharmony_ci SANE_Status status; 576141cc406Sopenharmony_ci int iAlreadyOpen = 0; 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci connect = sanei_hp_get_connect (devname); 579141cc406Sopenharmony_ci 580141cc406Sopenharmony_ci if (connect != HP_CONNECT_SCSI) 581141cc406Sopenharmony_ci return sanei_hp_nonscsi_new (newp, devname, connect); 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci new = sanei_hp_allocz(sizeof(*new)); 584141cc406Sopenharmony_ci if (!new) 585141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci /* Is the device still open ? */ 588141cc406Sopenharmony_ci if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) 589141cc406Sopenharmony_ci { 590141cc406Sopenharmony_ci iAlreadyOpen = 1; 591141cc406Sopenharmony_ci } 592141cc406Sopenharmony_ci else 593141cc406Sopenharmony_ci { 594141cc406Sopenharmony_ci status = sanei_scsi_open(devname, &new->fd, 0, 0); 595141cc406Sopenharmony_ci if (FAILED(status)) 596141cc406Sopenharmony_ci { 597141cc406Sopenharmony_ci DBG(1, "scsi_new: open failed (%s)\n", sane_strstatus(status)); 598141cc406Sopenharmony_ci sanei_hp_free(new); 599141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 600141cc406Sopenharmony_ci } 601141cc406Sopenharmony_ci } 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci DBG(3, "scsi_inquire: sending INQUIRE\n"); 604141cc406Sopenharmony_ci status = sanei_scsi_cmd(new->fd, inq_cmd, 6, new->inq_data, &inq_len); 605141cc406Sopenharmony_ci if (FAILED(status)) 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci DBG(1, "scsi_inquire: inquiry failed: %s\n", sane_strstatus(status)); 608141cc406Sopenharmony_ci sanei_scsi_close(new->fd); 609141cc406Sopenharmony_ci sanei_hp_free(new); 610141cc406Sopenharmony_ci return status; 611141cc406Sopenharmony_ci } 612141cc406Sopenharmony_ci 613141cc406Sopenharmony_ci {char vendor[9], model[17], rev[5]; 614141cc406Sopenharmony_ci memset (vendor, 0, sizeof (vendor)); 615141cc406Sopenharmony_ci memset (model, 0, sizeof (model)); 616141cc406Sopenharmony_ci memset (rev, 0, sizeof (rev)); 617141cc406Sopenharmony_ci memcpy (vendor, new->inq_data + 8, 8); 618141cc406Sopenharmony_ci memcpy (model, new->inq_data + 16, 16); 619141cc406Sopenharmony_ci memcpy (rev, new->inq_data + 32, 4); 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci DBG(3, "vendor=%s, model=%s, rev=%s\n", vendor, model, rev); 622141cc406Sopenharmony_ci } 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci DBG(3, "scsi_new: sending TEST_UNIT_READY\n"); 625141cc406Sopenharmony_ci status = sanei_scsi_cmd(new->fd, tur_cmd, 6, 0, 0); 626141cc406Sopenharmony_ci if (FAILED(status)) 627141cc406Sopenharmony_ci { 628141cc406Sopenharmony_ci DBG(1, "hp_scsi_open: test unit ready failed (%s)\n", 629141cc406Sopenharmony_ci sane_strstatus(status)); 630141cc406Sopenharmony_ci usleep (500*1000); /* Wait 0.5 seconds */ 631141cc406Sopenharmony_ci DBG(3, "scsi_new: sending TEST_UNIT_READY second time\n"); 632141cc406Sopenharmony_ci status = sanei_scsi_cmd(new->fd, tur_cmd, 6, 0, 0); 633141cc406Sopenharmony_ci } 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci if (FAILED(status)) 636141cc406Sopenharmony_ci { 637141cc406Sopenharmony_ci DBG(1, "hp_scsi_open: test unit ready failed (%s)\n", 638141cc406Sopenharmony_ci sane_strstatus(status)); 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci sanei_scsi_close(new->fd); 641141cc406Sopenharmony_ci sanei_hp_free(new); 642141cc406Sopenharmony_ci return status; /* Fix problem with non-scanner devices */ 643141cc406Sopenharmony_ci } 644141cc406Sopenharmony_ci 645141cc406Sopenharmony_ci new->bufp = new->buf + HP_SCSI_CMD_LEN; 646141cc406Sopenharmony_ci new->devname = sanei_hp_alloc ( strlen ( devname ) + 1 ); 647141cc406Sopenharmony_ci if ( new->devname ) strcpy (new->devname, devname); 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci *newp = new; 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci /* Remember the open device */ 652141cc406Sopenharmony_ci if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 655141cc406Sopenharmony_ci} 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci/* The "completely" parameter was added for OfficeJet support. 660141cc406Sopenharmony_ci * For JetDirect connections, closing and re-opening the scan 661141cc406Sopenharmony_ci * channel is very time consuming. Also, the OfficeJet G85 662141cc406Sopenharmony_ci * unloads a loaded document in the ADF when the scan channel 663141cc406Sopenharmony_ci * gets closed. The solution is to "completely" destroy the 664141cc406Sopenharmony_ci * connection, including closing and deallocating the PTAL 665141cc406Sopenharmony_ci * channel, when initially probing the device in hp-device.c, 666141cc406Sopenharmony_ci * but leave it open while the frontend is actually using the 667141cc406Sopenharmony_ci * device (from hp-handle.c), and "completely" destroy it when 668141cc406Sopenharmony_ci * the frontend closes its handle. */ 669141cc406Sopenharmony_civoid 670141cc406Sopenharmony_cisanei_hp_scsi_destroy (HpScsi this,int completely) 671141cc406Sopenharmony_ci{ 672141cc406Sopenharmony_ci /* Moved to hp_scsi_close(): 673141cc406Sopenharmony_ci * assert(this->fd >= 0); 674141cc406Sopenharmony_ci * DBG(3, "scsi_close: closing fd %d\n", this->fd); 675141cc406Sopenharmony_ci */ 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci hp_scsi_close (this, completely); 678141cc406Sopenharmony_ci if ( this->devname ) sanei_hp_free (this->devname); 679141cc406Sopenharmony_ci sanei_hp_free(this); 680141cc406Sopenharmony_ci} 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_cihp_byte_t * 683141cc406Sopenharmony_cisanei_hp_scsi_inq (HpScsi this) 684141cc406Sopenharmony_ci{ 685141cc406Sopenharmony_ci return this->inq_data; 686141cc406Sopenharmony_ci} 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ciconst char * 689141cc406Sopenharmony_cisanei_hp_scsi_vendor (HpScsi this) 690141cc406Sopenharmony_ci{ 691141cc406Sopenharmony_ci static char buf[9]; 692141cc406Sopenharmony_ci memcpy(buf, sanei_hp_scsi_inq(this) + 8, 8); 693141cc406Sopenharmony_ci buf[8] = '\0'; 694141cc406Sopenharmony_ci return buf; 695141cc406Sopenharmony_ci} 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ciconst char * 698141cc406Sopenharmony_cisanei_hp_scsi_model (HpScsi this) 699141cc406Sopenharmony_ci{ 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci static char buf[17]; 702141cc406Sopenharmony_ci memcpy(buf, sanei_hp_scsi_inq(this) + 16, 16); 703141cc406Sopenharmony_ci buf[16] = '\0'; 704141cc406Sopenharmony_ci return buf; 705141cc406Sopenharmony_ci} 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ciconst char * 708141cc406Sopenharmony_cisanei_hp_scsi_devicename (HpScsi this) 709141cc406Sopenharmony_ci{ 710141cc406Sopenharmony_ci return this->devname; 711141cc406Sopenharmony_ci} 712141cc406Sopenharmony_ci 713141cc406Sopenharmony_cihp_bool_t 714141cc406Sopenharmony_cisanei_hp_is_active_xpa (HpScsi scsi) 715141cc406Sopenharmony_ci{HpDeviceInfo *info; 716141cc406Sopenharmony_ci int model_num; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); 719141cc406Sopenharmony_ci if (info->active_xpa < 0) 720141cc406Sopenharmony_ci { 721141cc406Sopenharmony_ci model_num = sanei_hp_get_max_model (scsi); 722141cc406Sopenharmony_ci info->active_xpa = (model_num >= 17); 723141cc406Sopenharmony_ci DBG(5,"sanei_hp_is_active_xpa: model=%d, active_xpa=%d\n", 724141cc406Sopenharmony_ci model_num, info->active_xpa); 725141cc406Sopenharmony_ci } 726141cc406Sopenharmony_ci return info->active_xpa; 727141cc406Sopenharmony_ci} 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ciint 730141cc406Sopenharmony_cisanei_hp_get_max_model (HpScsi scsi) 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci{HpDeviceInfo *info; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); 735141cc406Sopenharmony_ci if (info->max_model < 0) 736141cc406Sopenharmony_ci {enum hp_device_compat_e compat; 737141cc406Sopenharmony_ci int model_num; 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci if ( sanei_hp_device_probe_model ( &compat, scsi, &model_num, 0) 740141cc406Sopenharmony_ci == SANE_STATUS_GOOD ) 741141cc406Sopenharmony_ci info->max_model = model_num; 742141cc406Sopenharmony_ci } 743141cc406Sopenharmony_ci return info->max_model; 744141cc406Sopenharmony_ci} 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ciint 748141cc406Sopenharmony_cisanei_hp_is_flatbed_adf (HpScsi scsi) 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci{int model = sanei_hp_get_max_model (scsi); 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci return ((model == 2) || (model == 4) || (model == 5) || (model == 8)); 753141cc406Sopenharmony_ci} 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ciHpConnect 757141cc406Sopenharmony_cisanei_hp_get_connect (const char *devname) 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci{const HpDeviceInfo *info; 760141cc406Sopenharmony_ci HpConnect connect = HP_CONNECT_SCSI; 761141cc406Sopenharmony_ci int got_connect_type = 0; 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci info = sanei_hp_device_info_get (devname); 764141cc406Sopenharmony_ci if (!info) 765141cc406Sopenharmony_ci { 766141cc406Sopenharmony_ci DBG(1, "sanei_hp_get_connect: Could not get info for %s. Assume SCSI\n", 767141cc406Sopenharmony_ci devname); 768141cc406Sopenharmony_ci connect = HP_CONNECT_SCSI; 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci else 771141cc406Sopenharmony_ci if ( !(info->config_is_up) ) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci DBG(1, "sanei_hp_get_connect: Config not initialized for %s. Assume SCSI\n", 774141cc406Sopenharmony_ci devname); 775141cc406Sopenharmony_ci connect = HP_CONNECT_SCSI; 776141cc406Sopenharmony_ci } 777141cc406Sopenharmony_ci else 778141cc406Sopenharmony_ci { 779141cc406Sopenharmony_ci connect = info->config.connect; 780141cc406Sopenharmony_ci got_connect_type = info->config.got_connect_type; 781141cc406Sopenharmony_ci } 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ci /* Beware of using a USB-device as a SCSI-device (not 100% perfect) */ 784141cc406Sopenharmony_ci if ((connect == HP_CONNECT_SCSI) && !got_connect_type) 785141cc406Sopenharmony_ci {int maybe_usb; 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci maybe_usb = ( strstr (devname, "usb") 788141cc406Sopenharmony_ci || strstr (devname, "uscanner") 789141cc406Sopenharmony_ci || strstr (devname, "ugen")); 790141cc406Sopenharmony_ci if (maybe_usb) 791141cc406Sopenharmony_ci {static int print_warning = 1; 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci if (print_warning) 794141cc406Sopenharmony_ci { 795141cc406Sopenharmony_ci print_warning = 0; 796141cc406Sopenharmony_ci DBG(1,"sanei_hp_get_connect: WARNING\n"); 797141cc406Sopenharmony_ci DBG(1," Device %s assumed to be SCSI, but device name\n",devname); 798141cc406Sopenharmony_ci DBG(1," looks like USB. Will continue with USB.\n"); 799141cc406Sopenharmony_ci DBG(1," If you really want it as SCSI, add the following\n"); 800141cc406Sopenharmony_ci DBG(1," to your file .../etc/sane.d/hp.conf:\n"); 801141cc406Sopenharmony_ci DBG(1," %s\n", devname); 802141cc406Sopenharmony_ci DBG(1," option connect-scsi\n"); 803141cc406Sopenharmony_ci DBG(1," The same warning applies to other device names containing\n"); 804141cc406Sopenharmony_ci DBG(1," \"usb\", \"uscanner\" or \"ugen\".\n"); 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci connect = HP_CONNECT_DEVICE; 807141cc406Sopenharmony_ci } 808141cc406Sopenharmony_ci } 809141cc406Sopenharmony_ci return connect; 810141cc406Sopenharmony_ci} 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_ciHpConnect 813141cc406Sopenharmony_cisanei_hp_scsi_get_connect (HpScsi this) 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci{ 816141cc406Sopenharmony_ci return sanei_hp_get_connect (sanei_hp_scsi_devicename (this)); 817141cc406Sopenharmony_ci} 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_cistatic SANE_Status 821141cc406Sopenharmony_cihp_scsi_flush (HpScsi this) 822141cc406Sopenharmony_ci{ 823141cc406Sopenharmony_ci hp_byte_t * data = this->buf + HP_SCSI_CMD_LEN; 824141cc406Sopenharmony_ci size_t len = this->bufp - data; 825141cc406Sopenharmony_ci HpConnect connect; 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci assert(len < HP_SCSI_MAX_WRITE); 828141cc406Sopenharmony_ci if (len == 0) 829141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci this->bufp = this->buf; 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci DBG(16, "scsi_flush: writing %lu bytes:\n", (unsigned long) len); 834141cc406Sopenharmony_ci DBGDUMP(16, data, len); 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci *this->bufp++ = 0x0A; 837141cc406Sopenharmony_ci *this->bufp++ = 0; 838141cc406Sopenharmony_ci *this->bufp++ = len >> 16; 839141cc406Sopenharmony_ci *this->bufp++ = len >> 8; 840141cc406Sopenharmony_ci *this->bufp++ = len; 841141cc406Sopenharmony_ci *this->bufp++ = 0; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci connect = sanei_hp_scsi_get_connect (this); 844141cc406Sopenharmony_ci if (connect == HP_CONNECT_SCSI) 845141cc406Sopenharmony_ci return sanei_scsi_cmd (this->fd, this->buf, HP_SCSI_CMD_LEN + len, 0, 0); 846141cc406Sopenharmony_ci else 847141cc406Sopenharmony_ci return hp_nonscsi_write (this, this->buf+HP_SCSI_CMD_LEN, len, connect); 848141cc406Sopenharmony_ci} 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_cistatic size_t 851141cc406Sopenharmony_cihp_scsi_room (HpScsi this) 852141cc406Sopenharmony_ci{ 853141cc406Sopenharmony_ci return this->buf + HP_SCSI_BUFSIZ - this->bufp; 854141cc406Sopenharmony_ci} 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_cistatic SANE_Status 857141cc406Sopenharmony_cihp_scsi_need (HpScsi this, size_t need) 858141cc406Sopenharmony_ci{ 859141cc406Sopenharmony_ci assert(need < HP_SCSI_MAX_WRITE); 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci if (need > hp_scsi_room(this)) 862141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush(this) ); 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 865141cc406Sopenharmony_ci} 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_cistatic SANE_Status 868141cc406Sopenharmony_cihp_scsi_write (HpScsi this, const void *data, size_t len) 869141cc406Sopenharmony_ci{ 870141cc406Sopenharmony_ci if ( len < HP_SCSI_MAX_WRITE ) 871141cc406Sopenharmony_ci { 872141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_need(this, len) ); 873141cc406Sopenharmony_ci memcpy(this->bufp, data, len); 874141cc406Sopenharmony_ci this->bufp += len; 875141cc406Sopenharmony_ci } 876141cc406Sopenharmony_ci else 877141cc406Sopenharmony_ci {size_t maxwrite = HP_SCSI_MAX_WRITE - 16; 878141cc406Sopenharmony_ci const char *c_data = (const char *)data; 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci while ( len > 0 ) 881141cc406Sopenharmony_ci { 882141cc406Sopenharmony_ci if ( maxwrite > len ) maxwrite = len; 883141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_write(this, c_data, maxwrite) ); 884141cc406Sopenharmony_ci c_data += maxwrite; 885141cc406Sopenharmony_ci len -= maxwrite; 886141cc406Sopenharmony_ci } 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 889141cc406Sopenharmony_ci} 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_cistatic SANE_Status 892141cc406Sopenharmony_cihp_scsi_scl(HpScsi this, HpScl scl, int val) 893141cc406Sopenharmony_ci{ 894141cc406Sopenharmony_ci char group = tolower(SCL_GROUP_CHAR(scl)); 895141cc406Sopenharmony_ci char param = toupper(SCL_PARAM_CHAR(scl)); 896141cc406Sopenharmony_ci int count; 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci assert(IS_SCL_CONTROL(scl) || IS_SCL_COMMAND(scl)); 899141cc406Sopenharmony_ci assert(isprint(group) && isprint(param)); 900141cc406Sopenharmony_ci 901141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_need(this, 10) ); 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci /* Don't try to optimize SCL-commands like using <ESC>*a1b0c5T */ 904141cc406Sopenharmony_ci /* Some scanners have problems with it (e.g. HP Photosmart Photoscanner */ 905141cc406Sopenharmony_ci /* with window position/extent, resolution) */ 906141cc406Sopenharmony_ci count = sprintf((char *)this->bufp, "\033*%c%d%c", group, val, param); 907141cc406Sopenharmony_ci this->bufp += count; 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci assert(count > 0 && this->bufp < this->buf + HP_SCSI_BUFSIZ); 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci return hp_scsi_flush(this); 912141cc406Sopenharmony_ci} 913141cc406Sopenharmony_ci 914141cc406Sopenharmony_ci/* Read it bytewise */ 915141cc406Sopenharmony_cistatic SANE_Status 916141cc406Sopenharmony_cihp_scsi_read_slow (HpScsi this, void * dest, size_t *len) 917141cc406Sopenharmony_ci{static hp_byte_t read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 }; 918141cc406Sopenharmony_ci size_t leftover = *len; 919141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 920141cc406Sopenharmony_ci unsigned char *start_dest = (unsigned char *)dest; 921141cc406Sopenharmony_ci unsigned char *next_dest = start_dest; 922141cc406Sopenharmony_ci 923141cc406Sopenharmony_ci DBG(16, "hp_scsi_read_slow: Start reading %d bytes bytewise\n", (int)*len); 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci while (leftover > 0) /* Until we got all the bytes */ 926141cc406Sopenharmony_ci {size_t one = 1; 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci read_cmd[2] = 0; 929141cc406Sopenharmony_ci read_cmd[3] = 0; 930141cc406Sopenharmony_ci read_cmd[4] = 1; /* Read one byte */ 931141cc406Sopenharmony_ci 932141cc406Sopenharmony_ci status = sanei_scsi_cmd (this->fd, read_cmd, sizeof(read_cmd), 933141cc406Sopenharmony_ci next_dest, &one); 934141cc406Sopenharmony_ci if ((status != SANE_STATUS_GOOD) || (one != 1)) 935141cc406Sopenharmony_ci { 936141cc406Sopenharmony_ci DBG(250,"hp_scsi_read_slow: Reading byte %d: status=%s, len=%d\n", 937141cc406Sopenharmony_ci (int)(next_dest-start_dest), sane_strstatus(status), (int)one); 938141cc406Sopenharmony_ci } 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) break; /* Finish on error */ 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci next_dest++; 943141cc406Sopenharmony_ci leftover--; 944141cc406Sopenharmony_ci } 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci *len = next_dest-start_dest; /* This is the number of bytes we got */ 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci DBG(16, "hp_scsi_read_slow: Got %d bytes\n", (int)*len); 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci if ((status != SANE_STATUS_GOOD) && (*len > 0)) 951141cc406Sopenharmony_ci { 952141cc406Sopenharmony_ci DBG(16, "We got some data. Ignore the error \"%s\"\n", 953141cc406Sopenharmony_ci sane_strstatus(status)); 954141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 955141cc406Sopenharmony_ci } 956141cc406Sopenharmony_ci return status; 957141cc406Sopenharmony_ci} 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci/* The OfficeJets tend to return inquiry responses containing array 960141cc406Sopenharmony_ci * data in two packets. The added "isResponse" parameter tells 961141cc406Sopenharmony_ci * whether we should keep reading until we get 962141cc406Sopenharmony_ci * a well-formed response. Naturally, this parameter would be zero 963141cc406Sopenharmony_ci * when reading scan data. */ 964141cc406Sopenharmony_cistatic SANE_Status 965141cc406Sopenharmony_cihp_scsi_read (HpScsi this, void * dest, size_t *len, int isResponse) 966141cc406Sopenharmony_ci{ 967141cc406Sopenharmony_ci HpConnect connect; 968141cc406Sopenharmony_ci 969141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush(this) ); 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci connect = sanei_hp_scsi_get_connect (this); 972141cc406Sopenharmony_ci if (connect == HP_CONNECT_SCSI) 973141cc406Sopenharmony_ci {int read_bytewise = 0; 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci if (*len <= 32) /* Is it a candidate for reading bytewise ? */ 976141cc406Sopenharmony_ci {const HpDeviceInfo *info; 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci info = sanei_hp_device_info_get (sanei_hp_scsi_devicename (this)); 979141cc406Sopenharmony_ci if ((info != NULL) && (info->config_is_up) && info->config.dumb_read) 980141cc406Sopenharmony_ci read_bytewise = 1; 981141cc406Sopenharmony_ci } 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci if ( ! read_bytewise ) 984141cc406Sopenharmony_ci {static hp_byte_t read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 }; 985141cc406Sopenharmony_ci read_cmd[2] = *len >> 16; 986141cc406Sopenharmony_ci read_cmd[3] = *len >> 8; 987141cc406Sopenharmony_ci read_cmd[4] = *len; 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci RETURN_IF_FAIL( sanei_scsi_cmd (this->fd, read_cmd, 990141cc406Sopenharmony_ci sizeof(read_cmd), dest, len) ); 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci else 993141cc406Sopenharmony_ci { 994141cc406Sopenharmony_ci RETURN_IF_FAIL (hp_scsi_read_slow (this, dest, len)); 995141cc406Sopenharmony_ci } 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci else 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_nonscsi_read (this, dest, len, connect, isResponse) ); 1000141cc406Sopenharmony_ci } 1001141cc406Sopenharmony_ci DBG(16, "scsi_read: %lu bytes:\n", (unsigned long) *len); 1002141cc406Sopenharmony_ci DBGDUMP(16, dest, *len); 1003141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1004141cc406Sopenharmony_ci} 1005141cc406Sopenharmony_ci 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_cistatic int signal_caught = 0; 1008141cc406Sopenharmony_ci 1009141cc406Sopenharmony_cistatic void 1010141cc406Sopenharmony_cisignal_catcher (int sig) 1011141cc406Sopenharmony_ci{ 1012141cc406Sopenharmony_ci DBG(1,"signal_catcher(sig=%d): old signal_caught=%d\n",sig,signal_caught); 1013141cc406Sopenharmony_ci if (!signal_caught) 1014141cc406Sopenharmony_ci signal_caught = sig; 1015141cc406Sopenharmony_ci} 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_cistatic void 1018141cc406Sopenharmony_cihp_data_map (register const unsigned char *map, register int count, 1019141cc406Sopenharmony_ci register unsigned char *data) 1020141cc406Sopenharmony_ci{ 1021141cc406Sopenharmony_ci if (count <= 0) return; 1022141cc406Sopenharmony_ci while (count--) 1023141cc406Sopenharmony_ci { 1024141cc406Sopenharmony_ci *data = map[*data]; 1025141cc406Sopenharmony_ci data++; 1026141cc406Sopenharmony_ci } 1027141cc406Sopenharmony_ci} 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_cistatic const unsigned char * 1030141cc406Sopenharmony_cihp_get_simulation_map (const char *devname, const HpDeviceInfo *info) 1031141cc406Sopenharmony_ci{ 1032141cc406Sopenharmony_ci hp_bool_t sim_gamma, sim_brightness, sim_contrast; 1033141cc406Sopenharmony_ci int k, ind; 1034141cc406Sopenharmony_ci const unsigned char *map = NULL; 1035141cc406Sopenharmony_ci static unsigned char map8x8[256]; 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci sim_gamma = info->simulate.gamma_simulate; 1038141cc406Sopenharmony_ci sim_brightness = sanei_hp_device_simulate_get (devname, SCL_BRIGHTNESS); 1039141cc406Sopenharmony_ci sim_contrast = sanei_hp_device_simulate_get (devname, SCL_CONTRAST); 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci if ( sim_gamma ) 1042141cc406Sopenharmony_ci { 1043141cc406Sopenharmony_ci map = &(info->simulate.gamma_map[0]); 1044141cc406Sopenharmony_ci } 1045141cc406Sopenharmony_ci else if ( sim_brightness && sim_contrast ) 1046141cc406Sopenharmony_ci { 1047141cc406Sopenharmony_ci for (k = 0; k < 256; k++) 1048141cc406Sopenharmony_ci { 1049141cc406Sopenharmony_ci ind = info->simulate.contrast_map[k]; 1050141cc406Sopenharmony_ci map8x8[k] = info->simulate.brightness_map[ind]; 1051141cc406Sopenharmony_ci } 1052141cc406Sopenharmony_ci map = &(map8x8[0]); 1053141cc406Sopenharmony_ci } 1054141cc406Sopenharmony_ci else if ( sim_brightness ) 1055141cc406Sopenharmony_ci map = &(info->simulate.brightness_map[0]); 1056141cc406Sopenharmony_ci else if ( sim_contrast ) 1057141cc406Sopenharmony_ci map = &(info->simulate.contrast_map[0]); 1058141cc406Sopenharmony_ci 1059141cc406Sopenharmony_ci return map; 1060141cc406Sopenharmony_ci} 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci/* Check the native byte order on the local machine */ 1064141cc406Sopenharmony_cistatic hp_bool_t 1065141cc406Sopenharmony_ciis_lowbyte_first_byteorder (void) 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci{unsigned short testvar = 1; 1068141cc406Sopenharmony_ci unsigned char *testptr = (unsigned char *)&testvar; 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ci if (sizeof (unsigned short) == 2) 1071141cc406Sopenharmony_ci return (testptr[0] == 1); 1072141cc406Sopenharmony_ci else if (sizeof (unsigned short) == 4) 1073141cc406Sopenharmony_ci return ((testptr[0] == 1) || (testptr[2] == 1)); 1074141cc406Sopenharmony_ci else 1075141cc406Sopenharmony_ci return ( (testptr[0] == 1) || (testptr[2] == 1) 1076141cc406Sopenharmony_ci || (testptr[4] == 1) || (testptr[6] == 1)); 1077141cc406Sopenharmony_ci} 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci/* The SANE standard defines that 2-byte data must use the full 16 bit range. 1080141cc406Sopenharmony_ci * Byte order returned by the backend must be native byte order. 1081141cc406Sopenharmony_ci * Scaling to 16 bit and byte order is achieved by hp_scale_to_16bit. 1082141cc406Sopenharmony_ci * for >8 bits data, take the two data bytes and scale their content 1083141cc406Sopenharmony_ci * to the full 16 bit range, using 1084141cc406Sopenharmony_ci * scaled = unscaled << (newlen - oldlen) + 1085141cc406Sopenharmony_ci * unscaled >> (oldlen - (newlen - oldlen)), 1086141cc406Sopenharmony_ci * with newlen=16 and oldlen the original bit depth. 1087141cc406Sopenharmony_ci */ 1088141cc406Sopenharmony_cistatic void 1089141cc406Sopenharmony_cihp_scale_to_16bit(int count, register unsigned char *data, int depth, 1090141cc406Sopenharmony_ci hp_bool_t invert) 1091141cc406Sopenharmony_ci{ 1092141cc406Sopenharmony_ci register unsigned int tmp; 1093141cc406Sopenharmony_ci register unsigned int mask; 1094141cc406Sopenharmony_ci register hp_bool_t lowbyte_first = is_lowbyte_first_byteorder (); 1095141cc406Sopenharmony_ci unsigned int shift1 = 16 - depth; 1096141cc406Sopenharmony_ci unsigned int shift2 = 2*depth - 16; 1097141cc406Sopenharmony_ci int k; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci if (count <= 0) return; 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci mask = 1; 1102141cc406Sopenharmony_ci for (k = 1; k < depth; k++) mask |= (1 << k); 1103141cc406Sopenharmony_ci 1104141cc406Sopenharmony_ci if (lowbyte_first) 1105141cc406Sopenharmony_ci { 1106141cc406Sopenharmony_ci while (count--) { 1107141cc406Sopenharmony_ci tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; 1108141cc406Sopenharmony_ci tmp = (tmp << shift1) + (tmp >> shift2); 1109141cc406Sopenharmony_ci if (invert) tmp = ~tmp; 1110141cc406Sopenharmony_ci *data++ = tmp & 255U; 1111141cc406Sopenharmony_ci *data++ = (tmp >> 8) & 255U; 1112141cc406Sopenharmony_ci } 1113141cc406Sopenharmony_ci } 1114141cc406Sopenharmony_ci else /* Highbyte first */ 1115141cc406Sopenharmony_ci { 1116141cc406Sopenharmony_ci while (count--) { 1117141cc406Sopenharmony_ci tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; 1118141cc406Sopenharmony_ci tmp = (tmp << shift1) + (tmp >> shift2); 1119141cc406Sopenharmony_ci if (invert) tmp = ~tmp; 1120141cc406Sopenharmony_ci *data++ = (tmp >> 8) & 255U; 1121141cc406Sopenharmony_ci *data++ = tmp & 255U; 1122141cc406Sopenharmony_ci } 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci} 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_cistatic void 1128141cc406Sopenharmony_cihp_scale_to_8bit(int count, register unsigned char *data, int depth, 1129141cc406Sopenharmony_ci hp_bool_t invert) 1130141cc406Sopenharmony_ci{ 1131141cc406Sopenharmony_ci register unsigned int tmp, mask; 1132141cc406Sopenharmony_ci register hp_bool_t lowbyte_first = is_lowbyte_first_byteorder (); 1133141cc406Sopenharmony_ci unsigned int shift1 = depth-8; 1134141cc406Sopenharmony_ci int k; 1135141cc406Sopenharmony_ci unsigned char *dataout = data; 1136141cc406Sopenharmony_ci 1137141cc406Sopenharmony_ci if ((count <= 0) || (shift1 <= 0)) return; 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci mask = 1; 1140141cc406Sopenharmony_ci for (k = 1; k < depth; k++) mask |= (1 << k); 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci if (lowbyte_first) 1143141cc406Sopenharmony_ci { 1144141cc406Sopenharmony_ci while (count--) { 1145141cc406Sopenharmony_ci tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; 1146141cc406Sopenharmony_ci tmp >>= shift1; 1147141cc406Sopenharmony_ci if (invert) tmp = ~tmp; 1148141cc406Sopenharmony_ci *(dataout++) = tmp & 255U; 1149141cc406Sopenharmony_ci data += 2; 1150141cc406Sopenharmony_ci } 1151141cc406Sopenharmony_ci } 1152141cc406Sopenharmony_ci else /* Highbyte first */ 1153141cc406Sopenharmony_ci { 1154141cc406Sopenharmony_ci while (count--) { 1155141cc406Sopenharmony_ci tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; 1156141cc406Sopenharmony_ci tmp >>= shift1; 1157141cc406Sopenharmony_ci if (invert) tmp = ~tmp; 1158141cc406Sopenharmony_ci *(dataout++) = tmp & 255U; 1159141cc406Sopenharmony_ci data += 2; 1160141cc406Sopenharmony_ci } 1161141cc406Sopenharmony_ci } 1162141cc406Sopenharmony_ci} 1163141cc406Sopenharmony_ci 1164141cc406Sopenharmony_cistatic void 1165141cc406Sopenharmony_cihp_soft_invert(int count, register unsigned char *data) { 1166141cc406Sopenharmony_ci while (count>0) { 1167141cc406Sopenharmony_ci *data = ~(*data); 1168141cc406Sopenharmony_ci data++; 1169141cc406Sopenharmony_ci count--; 1170141cc406Sopenharmony_ci } 1171141cc406Sopenharmony_ci} 1172141cc406Sopenharmony_ci 1173141cc406Sopenharmony_cistatic PROCDATA_HANDLE * 1174141cc406Sopenharmony_ciprocess_data_init (HpProcessData *procdata, const unsigned char *map, 1175141cc406Sopenharmony_ci int outfd, hp_bool_t use_imgbuf) 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci{PROCDATA_HANDLE *ph = sanei_hp_alloc (sizeof (PROCDATA_HANDLE)); 1178141cc406Sopenharmony_ci int tsz; 1179141cc406Sopenharmony_ci 1180141cc406Sopenharmony_ci if (ph == NULL) return NULL; 1181141cc406Sopenharmony_ci 1182141cc406Sopenharmony_ci memset (ph, 0, sizeof (*ph)); 1183141cc406Sopenharmony_ci memcpy (&(ph->procdata), procdata, sizeof (*procdata)); 1184141cc406Sopenharmony_ci procdata = &(ph->procdata); 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci tsz = (HP_TMP_BUF_SIZE <= 0) ? procdata->bytes_per_line : HP_TMP_BUF_SIZE; 1187141cc406Sopenharmony_ci ph->tmp_buf = sanei_hp_alloc (tsz); 1188141cc406Sopenharmony_ci if (ph->tmp_buf == NULL) 1189141cc406Sopenharmony_ci { 1190141cc406Sopenharmony_ci sanei_hp_free (ph); 1191141cc406Sopenharmony_ci return NULL; 1192141cc406Sopenharmony_ci } 1193141cc406Sopenharmony_ci ph->tmp_buf_size = tsz; 1194141cc406Sopenharmony_ci ph->tmp_buf_len = 0; 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci ph->map = map; 1197141cc406Sopenharmony_ci ph->outfd = outfd; 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci if ( procdata->mirror_vertical || use_imgbuf) 1200141cc406Sopenharmony_ci { 1201141cc406Sopenharmony_ci tsz = procdata->lines*procdata->bytes_per_line; 1202141cc406Sopenharmony_ci if (procdata->out8) tsz /= 2; 1203141cc406Sopenharmony_ci ph->image_ptr = ph->image_buf = sanei_hp_alloc (tsz); 1204141cc406Sopenharmony_ci if ( !ph->image_buf ) 1205141cc406Sopenharmony_ci { 1206141cc406Sopenharmony_ci procdata->mirror_vertical = 0; 1207141cc406Sopenharmony_ci ph->image_buf_size = 0; 1208141cc406Sopenharmony_ci DBG(1, "process_scanline_init: Not enough memory to mirror image\n"); 1209141cc406Sopenharmony_ci } 1210141cc406Sopenharmony_ci else 1211141cc406Sopenharmony_ci ph->image_buf_size = tsz; 1212141cc406Sopenharmony_ci } 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci ph->wr_ptr = ph->wr_buf; 1215141cc406Sopenharmony_ci ph->wr_buf_size = ph->wr_left = sizeof (ph->wr_buf); 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci return ph; 1218141cc406Sopenharmony_ci} 1219141cc406Sopenharmony_ci 1220141cc406Sopenharmony_ci 1221141cc406Sopenharmony_cistatic SANE_Status 1222141cc406Sopenharmony_ciprocess_data_write (PROCDATA_HANDLE *ph, unsigned char *data, int nbytes) 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci{int ncopy; 1225141cc406Sopenharmony_ci 1226141cc406Sopenharmony_ci if (ph == NULL) return SANE_STATUS_INVAL; 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci /* Fill up write buffer */ 1229141cc406Sopenharmony_ci ncopy = ph->wr_left; 1230141cc406Sopenharmony_ci if (ncopy > nbytes) ncopy = nbytes; 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci memcpy (ph->wr_ptr, data, ncopy); 1233141cc406Sopenharmony_ci ph->wr_ptr += ncopy; 1234141cc406Sopenharmony_ci ph->wr_left -= ncopy; 1235141cc406Sopenharmony_ci data += ncopy; 1236141cc406Sopenharmony_ci nbytes -= ncopy; 1237141cc406Sopenharmony_ci 1238141cc406Sopenharmony_ci if ( ph->wr_left > 0 ) /* Did not fill up the write buffer ? Finished */ 1239141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_ci DBG(12, "process_data_write: write %d bytes\n", ph->wr_buf_size); 1242141cc406Sopenharmony_ci /* Don't write data if we got a signal in the meantime */ 1243141cc406Sopenharmony_ci if ( signal_caught 1244141cc406Sopenharmony_ci || (write (ph->outfd, ph->wr_buf, ph->wr_buf_size) != ph->wr_buf_size)) 1245141cc406Sopenharmony_ci { 1246141cc406Sopenharmony_ci DBG(1, "process_data_write: write failed: %s\n", 1247141cc406Sopenharmony_ci signal_caught ? "signal caught" : strerror(errno)); 1248141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1249141cc406Sopenharmony_ci } 1250141cc406Sopenharmony_ci ph->wr_ptr = ph->wr_buf; 1251141cc406Sopenharmony_ci ph->wr_left = ph->wr_buf_size; 1252141cc406Sopenharmony_ci 1253141cc406Sopenharmony_ci /* For large amount of data write it from data-buffer */ 1254141cc406Sopenharmony_ci while ( nbytes > ph->wr_buf_size ) 1255141cc406Sopenharmony_ci { 1256141cc406Sopenharmony_ci if ( signal_caught 1257141cc406Sopenharmony_ci || (write (ph->outfd, data, ph->wr_buf_size) != ph->wr_buf_size)) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci DBG(1, "process_data_write: write failed: %s\n", 1260141cc406Sopenharmony_ci signal_caught ? "signal caught" : strerror(errno)); 1261141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1262141cc406Sopenharmony_ci } 1263141cc406Sopenharmony_ci nbytes -= ph->wr_buf_size; 1264141cc406Sopenharmony_ci data += ph->wr_buf_size; 1265141cc406Sopenharmony_ci } 1266141cc406Sopenharmony_ci 1267141cc406Sopenharmony_ci if ( nbytes > 0 ) /* Something left ? Save it to (empty) write buffer */ 1268141cc406Sopenharmony_ci { 1269141cc406Sopenharmony_ci memcpy (ph->wr_ptr, data, nbytes); 1270141cc406Sopenharmony_ci ph->wr_ptr += nbytes; 1271141cc406Sopenharmony_ci ph->wr_left -= nbytes; 1272141cc406Sopenharmony_ci } 1273141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1274141cc406Sopenharmony_ci} 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_cistatic SANE_Status 1277141cc406Sopenharmony_ciprocess_scanline (PROCDATA_HANDLE *ph, unsigned char *linebuf, 1278141cc406Sopenharmony_ci int bytes_per_line) 1279141cc406Sopenharmony_ci 1280141cc406Sopenharmony_ci{int out_bytes_per_line = bytes_per_line; 1281141cc406Sopenharmony_ci HpProcessData *procdata; 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci if (ph == NULL) return SANE_STATUS_INVAL; 1284141cc406Sopenharmony_ci procdata = &(ph->procdata); 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci if ( ph->map ) 1287141cc406Sopenharmony_ci hp_data_map (ph->map, bytes_per_line, linebuf); 1288141cc406Sopenharmony_ci 1289141cc406Sopenharmony_ci if (procdata->bits_per_channel > 8) 1290141cc406Sopenharmony_ci { 1291141cc406Sopenharmony_ci if (procdata->out8) 1292141cc406Sopenharmony_ci { 1293141cc406Sopenharmony_ci hp_scale_to_8bit( bytes_per_line/2, linebuf, 1294141cc406Sopenharmony_ci procdata->bits_per_channel, 1295141cc406Sopenharmony_ci procdata->invert); 1296141cc406Sopenharmony_ci out_bytes_per_line /= 2; 1297141cc406Sopenharmony_ci } 1298141cc406Sopenharmony_ci else 1299141cc406Sopenharmony_ci { 1300141cc406Sopenharmony_ci hp_scale_to_16bit( bytes_per_line/2, linebuf, 1301141cc406Sopenharmony_ci procdata->bits_per_channel, 1302141cc406Sopenharmony_ci procdata->invert); 1303141cc406Sopenharmony_ci } 1304141cc406Sopenharmony_ci } else if (procdata->invert) { 1305141cc406Sopenharmony_ci hp_soft_invert(bytes_per_line,linebuf); 1306141cc406Sopenharmony_ci } 1307141cc406Sopenharmony_ci 1308141cc406Sopenharmony_ci if ( ph->image_buf ) 1309141cc406Sopenharmony_ci { 1310141cc406Sopenharmony_ci DBG(5, "process_scanline: save in memory\n"); 1311141cc406Sopenharmony_ci 1312141cc406Sopenharmony_ci if ( ph->image_ptr+out_bytes_per_line-1 1313141cc406Sopenharmony_ci <= ph->image_buf+ph->image_buf_size-1 ) 1314141cc406Sopenharmony_ci { 1315141cc406Sopenharmony_ci memcpy(ph->image_ptr, linebuf, out_bytes_per_line); 1316141cc406Sopenharmony_ci ph->image_ptr += out_bytes_per_line; 1317141cc406Sopenharmony_ci } 1318141cc406Sopenharmony_ci else 1319141cc406Sopenharmony_ci { 1320141cc406Sopenharmony_ci DBG(1, "process_scanline: would exceed image buffer\n"); 1321141cc406Sopenharmony_ci } 1322141cc406Sopenharmony_ci } 1323141cc406Sopenharmony_ci else /* Save scanlines in a bigger buffer. */ 1324141cc406Sopenharmony_ci { /* Otherwise we will get performance problems */ 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci RETURN_IF_FAIL ( process_data_write (ph, linebuf, out_bytes_per_line) ); 1327141cc406Sopenharmony_ci } 1328141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1329141cc406Sopenharmony_ci} 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci 1332141cc406Sopenharmony_cistatic SANE_Status 1333141cc406Sopenharmony_ciprocess_data (PROCDATA_HANDLE *ph, unsigned char *read_ptr, int nread) 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci{int bytes_left; 1336141cc406Sopenharmony_ci 1337141cc406Sopenharmony_ci if (nread <= 0) return SANE_STATUS_GOOD; 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci if (ph == NULL) return SANE_STATUS_INVAL; 1340141cc406Sopenharmony_ci 1341141cc406Sopenharmony_ci if ( ph->tmp_buf_len > 0 ) /* Something left ? */ 1342141cc406Sopenharmony_ci { 1343141cc406Sopenharmony_ci bytes_left = ph->tmp_buf_size - ph->tmp_buf_len; 1344141cc406Sopenharmony_ci if (nread < bytes_left) /* All to buffer ? */ 1345141cc406Sopenharmony_ci { 1346141cc406Sopenharmony_ci memcpy (ph->tmp_buf+ph->tmp_buf_len, read_ptr, nread); 1347141cc406Sopenharmony_ci ph->tmp_buf_len += nread; 1348141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1349141cc406Sopenharmony_ci } 1350141cc406Sopenharmony_ci memcpy (ph->tmp_buf+ph->tmp_buf_len, read_ptr, bytes_left); 1351141cc406Sopenharmony_ci read_ptr += bytes_left; 1352141cc406Sopenharmony_ci nread -= bytes_left; 1353141cc406Sopenharmony_ci RETURN_IF_FAIL ( process_scanline (ph, ph->tmp_buf, ph->tmp_buf_size) ); 1354141cc406Sopenharmony_ci ph->tmp_buf_len = 0; 1355141cc406Sopenharmony_ci } 1356141cc406Sopenharmony_ci while (nread > 0) 1357141cc406Sopenharmony_ci { 1358141cc406Sopenharmony_ci if (nread >= ph->tmp_buf_size) 1359141cc406Sopenharmony_ci { 1360141cc406Sopenharmony_ci RETURN_IF_FAIL ( process_scanline (ph, read_ptr, ph->tmp_buf_size) ); 1361141cc406Sopenharmony_ci read_ptr += ph->tmp_buf_size; 1362141cc406Sopenharmony_ci nread -= ph->tmp_buf_size; 1363141cc406Sopenharmony_ci } 1364141cc406Sopenharmony_ci else 1365141cc406Sopenharmony_ci { 1366141cc406Sopenharmony_ci memcpy (ph->tmp_buf, read_ptr, nread); 1367141cc406Sopenharmony_ci ph->tmp_buf_len = nread; 1368141cc406Sopenharmony_ci nread = 0; 1369141cc406Sopenharmony_ci } 1370141cc406Sopenharmony_ci } 1371141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1372141cc406Sopenharmony_ci} 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_cistatic SANE_Status 1376141cc406Sopenharmony_ciprocess_data_flush (PROCDATA_HANDLE *ph) 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ci{SANE_Status status = SANE_STATUS_GOOD; 1379141cc406Sopenharmony_ci HpProcessData *procdata; 1380141cc406Sopenharmony_ci unsigned char *image_data; 1381141cc406Sopenharmony_ci size_t image_len; 1382141cc406Sopenharmony_ci int num_lines, bytes_per_line; 1383141cc406Sopenharmony_ci int nbytes; 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci if (ph == NULL) return SANE_STATUS_INVAL; 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci if ( ph->tmp_buf_len > 0 ) 1388141cc406Sopenharmony_ci process_scanline (ph, ph->tmp_buf, ph->tmp_buf_len); 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci if ( ph->wr_left != ph->wr_buf_size ) /* Something in write buffer ? */ 1391141cc406Sopenharmony_ci { 1392141cc406Sopenharmony_ci nbytes = ph->wr_buf_size - ph->wr_left; 1393141cc406Sopenharmony_ci if ( signal_caught || (write (ph->outfd, ph->wr_buf, nbytes) != nbytes)) 1394141cc406Sopenharmony_ci { 1395141cc406Sopenharmony_ci DBG(1, "process_data_flush: write failed: %s\n", 1396141cc406Sopenharmony_ci signal_caught ? "signal caught" : strerror(errno)); 1397141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1398141cc406Sopenharmony_ci } 1399141cc406Sopenharmony_ci ph->wr_ptr = ph->wr_buf; 1400141cc406Sopenharmony_ci ph->wr_left = ph->wr_buf_size; 1401141cc406Sopenharmony_ci } 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci procdata = &(ph->procdata); 1404141cc406Sopenharmony_ci if ( ph->image_buf ) 1405141cc406Sopenharmony_ci { 1406141cc406Sopenharmony_ci bytes_per_line = procdata->bytes_per_line; 1407141cc406Sopenharmony_ci if (procdata->out8) bytes_per_line /= 2; 1408141cc406Sopenharmony_ci image_len = (size_t) (ph->image_ptr - ph->image_buf); 1409141cc406Sopenharmony_ci num_lines = ((int)(image_len + bytes_per_line-1)) / bytes_per_line; 1410141cc406Sopenharmony_ci 1411141cc406Sopenharmony_ci DBG(3, "process_data_finish: write %d bytes from memory...\n", 1412141cc406Sopenharmony_ci (int)image_len); 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci if ( procdata->mirror_vertical ) 1415141cc406Sopenharmony_ci { 1416141cc406Sopenharmony_ci image_data = ph->image_buf + (num_lines-1) * bytes_per_line; 1417141cc406Sopenharmony_ci while (num_lines > 0 ) 1418141cc406Sopenharmony_ci { 1419141cc406Sopenharmony_ci if ( signal_caught 1420141cc406Sopenharmony_ci || (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)) 1421141cc406Sopenharmony_ci { 1422141cc406Sopenharmony_ci DBG(1,"process_data_finish: write from memory failed: %s\n", 1423141cc406Sopenharmony_ci signal_caught ? "signal caught" : strerror(errno)); 1424141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 1425141cc406Sopenharmony_ci break; 1426141cc406Sopenharmony_ci } 1427141cc406Sopenharmony_ci num_lines--; 1428141cc406Sopenharmony_ci image_data -= bytes_per_line; 1429141cc406Sopenharmony_ci } 1430141cc406Sopenharmony_ci } 1431141cc406Sopenharmony_ci else 1432141cc406Sopenharmony_ci { 1433141cc406Sopenharmony_ci image_data = ph->image_buf; 1434141cc406Sopenharmony_ci while (num_lines > 0 ) 1435141cc406Sopenharmony_ci { 1436141cc406Sopenharmony_ci if ( signal_caught 1437141cc406Sopenharmony_ci || (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)) 1438141cc406Sopenharmony_ci { 1439141cc406Sopenharmony_ci DBG(1,"process_data_finish: write from memory failed: %s\n", 1440141cc406Sopenharmony_ci signal_caught ? "signal caught" : strerror(errno)); 1441141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 1442141cc406Sopenharmony_ci break; 1443141cc406Sopenharmony_ci } 1444141cc406Sopenharmony_ci num_lines--; 1445141cc406Sopenharmony_ci image_data += bytes_per_line; 1446141cc406Sopenharmony_ci } 1447141cc406Sopenharmony_ci } 1448141cc406Sopenharmony_ci } 1449141cc406Sopenharmony_ci return status; 1450141cc406Sopenharmony_ci} 1451141cc406Sopenharmony_ci 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_cistatic void 1454141cc406Sopenharmony_ciprocess_data_finish (PROCDATA_HANDLE *ph) 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci{ 1457141cc406Sopenharmony_ci DBG(12, "process_data_finish called\n"); 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci if (ph == NULL) return; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci if (ph->image_buf != NULL) sanei_hp_free (ph->image_buf); 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci sanei_hp_free (ph->tmp_buf); 1464141cc406Sopenharmony_ci sanei_hp_free (ph); 1465141cc406Sopenharmony_ci} 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ci 1468141cc406Sopenharmony_ciSANE_Status 1469141cc406Sopenharmony_cisanei_hp_scsi_pipeout (HpScsi this, int outfd, HpProcessData *procdata) 1470141cc406Sopenharmony_ci{ 1471141cc406Sopenharmony_ci /* We will catch these signals, and rethrow them after cleaning up, 1472141cc406Sopenharmony_ci * anything not in this list, we will ignore. */ 1473141cc406Sopenharmony_ci static int kill_sig[] = { 1474141cc406Sopenharmony_ci SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGPIPE, SIGALRM, SIGTERM, 1475141cc406Sopenharmony_ci SIGUSR1, SIGUSR2, SIGBUS, 1476141cc406Sopenharmony_ci#ifdef SIGSTKFLT 1477141cc406Sopenharmony_ci SIGSTKFLT, 1478141cc406Sopenharmony_ci#endif 1479141cc406Sopenharmony_ci#ifdef SIGIO 1480141cc406Sopenharmony_ci SIGIO, 1481141cc406Sopenharmony_ci#else 1482141cc406Sopenharmony_ci# ifdef SIGPOLL 1483141cc406Sopenharmony_ci SIGPOLL, 1484141cc406Sopenharmony_ci# endif 1485141cc406Sopenharmony_ci#endif 1486141cc406Sopenharmony_ci#ifdef SIGXCPU 1487141cc406Sopenharmony_ci SIGXCPU, 1488141cc406Sopenharmony_ci#endif 1489141cc406Sopenharmony_ci#ifdef SIGXFSZ 1490141cc406Sopenharmony_ci SIGXFSZ, 1491141cc406Sopenharmony_ci#endif 1492141cc406Sopenharmony_ci#ifdef SIGVTALRM 1493141cc406Sopenharmony_ci SIGVTALRM, 1494141cc406Sopenharmony_ci#endif 1495141cc406Sopenharmony_ci#ifdef SIGPWR 1496141cc406Sopenharmony_ci SIGPWR, 1497141cc406Sopenharmony_ci#endif 1498141cc406Sopenharmony_ci }; 1499141cc406Sopenharmony_ci#define HP_NSIGS (sizeof(kill_sig)/sizeof(kill_sig[0])) 1500141cc406Sopenharmony_ci struct SIGACTION old_handler[HP_NSIGS]; 1501141cc406Sopenharmony_ci struct SIGACTION sa; 1502141cc406Sopenharmony_ci sigset_t old_set, sig_set; 1503141cc406Sopenharmony_ci int i; 1504141cc406Sopenharmony_ci int bits_per_channel = procdata->bits_per_channel; 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_ci#define HP_PIPEBUF 32768 1507141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1508141cc406Sopenharmony_ci struct { 1509141cc406Sopenharmony_ci size_t len; 1510141cc406Sopenharmony_ci void * id; 1511141cc406Sopenharmony_ci hp_byte_t cmd[6]; 1512141cc406Sopenharmony_ci hp_byte_t data[HP_PIPEBUF]; 1513141cc406Sopenharmony_ci } buf[2], *req = NULL; 1514141cc406Sopenharmony_ci 1515141cc406Sopenharmony_ci int reqs_completed = 0; 1516141cc406Sopenharmony_ci int reqs_issued = 0; 1517141cc406Sopenharmony_ci char *image_buf = 0; 1518141cc406Sopenharmony_ci char *read_buf = 0; 1519141cc406Sopenharmony_ci const HpDeviceInfo *info; 1520141cc406Sopenharmony_ci const char *devname = sanei_hp_scsi_devicename (this); 1521141cc406Sopenharmony_ci int enable_requests = 1; 1522141cc406Sopenharmony_ci int enable_image_buffering = 0; 1523141cc406Sopenharmony_ci const unsigned char *map = NULL; 1524141cc406Sopenharmony_ci HpConnect connect; 1525141cc406Sopenharmony_ci PROCDATA_HANDLE *ph = NULL; 1526141cc406Sopenharmony_ci size_t count = procdata->lines * procdata->bytes_per_line; 1527141cc406Sopenharmony_ci 1528141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush(this) ); 1529141cc406Sopenharmony_ci 1530141cc406Sopenharmony_ci connect = sanei_hp_get_connect (devname); 1531141cc406Sopenharmony_ci info = sanei_hp_device_info_get (devname); 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci assert (info); 1534141cc406Sopenharmony_ci 1535141cc406Sopenharmony_ci if ( info->config_is_up ) 1536141cc406Sopenharmony_ci { 1537141cc406Sopenharmony_ci enable_requests = info->config.use_scsi_request; 1538141cc406Sopenharmony_ci enable_image_buffering = info->config.use_image_buffering; 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci else 1541141cc406Sopenharmony_ci { 1542141cc406Sopenharmony_ci enable_requests = 0; 1543141cc406Sopenharmony_ci } 1544141cc406Sopenharmony_ci 1545141cc406Sopenharmony_ci if (connect != HP_CONNECT_SCSI) 1546141cc406Sopenharmony_ci enable_requests = 0; 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci /* Currently we can only simulate 8 bits mapping */ 1549141cc406Sopenharmony_ci if (bits_per_channel == 8) 1550141cc406Sopenharmony_ci map = hp_get_simulation_map (devname, info); 1551141cc406Sopenharmony_ci 1552141cc406Sopenharmony_ci sigfillset(&sig_set); 1553141cc406Sopenharmony_ci sigprocmask(SIG_BLOCK, &sig_set, &old_set); 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci memset(&sa, 0, sizeof(sa)); 1556141cc406Sopenharmony_ci sa.sa_handler = signal_catcher; 1557141cc406Sopenharmony_ci sigfillset(&sa.sa_mask); 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci sigemptyset(&sig_set); 1560141cc406Sopenharmony_ci for (i = 0; i < (int)(HP_NSIGS); i++) 1561141cc406Sopenharmony_ci { 1562141cc406Sopenharmony_ci sigaction(kill_sig[i], &sa, &old_handler[i]); 1563141cc406Sopenharmony_ci sigaddset(&sig_set, kill_sig[i]); 1564141cc406Sopenharmony_ci } 1565141cc406Sopenharmony_ci signal_caught = 0; 1566141cc406Sopenharmony_ci sigprocmask(SIG_UNBLOCK, &sig_set, 0); 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci /* Wait for front button push ? */ 1569141cc406Sopenharmony_ci if ( procdata->startscan ) 1570141cc406Sopenharmony_ci { 1571141cc406Sopenharmony_ci for (;;) 1572141cc406Sopenharmony_ci {int val = 0; 1573141cc406Sopenharmony_ci 1574141cc406Sopenharmony_ci if (signal_caught) goto quit; 1575141cc406Sopenharmony_ci sanei_hp_scl_inquire (this, SCL_FRONT_BUTTON, &val, 0, 0); 1576141cc406Sopenharmony_ci if (val) break; 1577141cc406Sopenharmony_ci usleep ((unsigned long)333*1000); /* Wait 1/3 second */ 1578141cc406Sopenharmony_ci } 1579141cc406Sopenharmony_ci status = sanei_hp_scl_startScan (this, procdata->startscan); 1580141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD ) 1581141cc406Sopenharmony_ci { 1582141cc406Sopenharmony_ci DBG(1, "do_read: Error starting scan in reader process\n"); 1583141cc406Sopenharmony_ci goto quit; 1584141cc406Sopenharmony_ci } 1585141cc406Sopenharmony_ci } 1586141cc406Sopenharmony_ci ph = process_data_init (procdata, map, outfd, enable_image_buffering); 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci if ( ph == NULL ) 1589141cc406Sopenharmony_ci { 1590141cc406Sopenharmony_ci DBG(1, "do_read: Error with process_data_init()\n"); 1591141cc406Sopenharmony_ci goto quit; 1592141cc406Sopenharmony_ci } 1593141cc406Sopenharmony_ci 1594141cc406Sopenharmony_ci DBG(1, "do_read: Start reading data from scanner\n"); 1595141cc406Sopenharmony_ci 1596141cc406Sopenharmony_ci if (enable_requests) /* Issue SCSI-requests ? */ 1597141cc406Sopenharmony_ci { 1598141cc406Sopenharmony_ci while (count > 0 || reqs_completed < reqs_issued) 1599141cc406Sopenharmony_ci { 1600141cc406Sopenharmony_ci while (count > 0 && reqs_issued < reqs_completed + 2) 1601141cc406Sopenharmony_ci { 1602141cc406Sopenharmony_ci req = buf + (reqs_issued++ % 2); 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci req->len = HP_PIPEBUF; 1605141cc406Sopenharmony_ci if (count < req->len) 1606141cc406Sopenharmony_ci req->len = count; 1607141cc406Sopenharmony_ci count -= req->len; 1608141cc406Sopenharmony_ci 1609141cc406Sopenharmony_ci req->cmd[0] = 0x08; 1610141cc406Sopenharmony_ci req->cmd[1] = 0; 1611141cc406Sopenharmony_ci req->cmd[2] = req->len >> 16; 1612141cc406Sopenharmony_ci req->cmd[3] = req->len >> 8; 1613141cc406Sopenharmony_ci req->cmd[4] = req->len; 1614141cc406Sopenharmony_ci req->cmd[5] = 0; 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci DBG(3, "do_read: entering request to read %lu bytes\n", 1617141cc406Sopenharmony_ci (unsigned long) req->len); 1618141cc406Sopenharmony_ci 1619141cc406Sopenharmony_ci status = sanei_scsi_req_enter(this->fd, req->cmd, 6, 1620141cc406Sopenharmony_ci req->data, &req->len, &req->id); 1621141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1622141cc406Sopenharmony_ci { 1623141cc406Sopenharmony_ci DBG(1, "do_read: Error from scsi_req_enter: %s\n", 1624141cc406Sopenharmony_ci sane_strstatus(status)); 1625141cc406Sopenharmony_ci goto quit; 1626141cc406Sopenharmony_ci } 1627141cc406Sopenharmony_ci if (signal_caught) 1628141cc406Sopenharmony_ci goto quit; 1629141cc406Sopenharmony_ci } 1630141cc406Sopenharmony_ci 1631141cc406Sopenharmony_ci if (signal_caught) 1632141cc406Sopenharmony_ci goto quit; 1633141cc406Sopenharmony_ci 1634141cc406Sopenharmony_ci assert(reqs_completed < reqs_issued); 1635141cc406Sopenharmony_ci req = buf + (reqs_completed++ % 2); 1636141cc406Sopenharmony_ci 1637141cc406Sopenharmony_ci DBG(3, "do_read: waiting for data\n"); 1638141cc406Sopenharmony_ci status = sanei_scsi_req_wait(req->id); 1639141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1640141cc406Sopenharmony_ci { 1641141cc406Sopenharmony_ci DBG(1, "do_read: Error from scsi_req_wait: %s\n", 1642141cc406Sopenharmony_ci sane_strstatus(status)); 1643141cc406Sopenharmony_ci goto quit; 1644141cc406Sopenharmony_ci } 1645141cc406Sopenharmony_ci if (signal_caught) 1646141cc406Sopenharmony_ci goto quit; 1647141cc406Sopenharmony_ci 1648141cc406Sopenharmony_ci status = process_data (ph, (unsigned char *)req->data, (int)req->len); 1649141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 1650141cc406Sopenharmony_ci { 1651141cc406Sopenharmony_ci DBG(1,"do_read: Error in process_data\n"); 1652141cc406Sopenharmony_ci goto quit; 1653141cc406Sopenharmony_ci } 1654141cc406Sopenharmony_ci } 1655141cc406Sopenharmony_ci } 1656141cc406Sopenharmony_ci else /* Read directly */ 1657141cc406Sopenharmony_ci { 1658141cc406Sopenharmony_ci read_buf = sanei_hp_alloc ( HP_PIPEBUF ); 1659141cc406Sopenharmony_ci if (!read_buf) 1660141cc406Sopenharmony_ci { 1661141cc406Sopenharmony_ci DBG(1, "do_read: not enough memory for read buffer\n"); 1662141cc406Sopenharmony_ci goto quit; 1663141cc406Sopenharmony_ci } 1664141cc406Sopenharmony_ci 1665141cc406Sopenharmony_ci while (count > 0) 1666141cc406Sopenharmony_ci {size_t nread; 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci if (signal_caught) 1669141cc406Sopenharmony_ci goto quit; 1670141cc406Sopenharmony_ci 1671141cc406Sopenharmony_ci DBG(5, "do_read: %lu bytes left to read\n", (unsigned long)count); 1672141cc406Sopenharmony_ci 1673141cc406Sopenharmony_ci nread = HP_PIPEBUF; 1674141cc406Sopenharmony_ci if (nread > count) nread = count; 1675141cc406Sopenharmony_ci 1676141cc406Sopenharmony_ci DBG(3, "do_read: try to read data (%lu bytes)\n", (unsigned long)nread); 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci status = hp_scsi_read (this, read_buf, &nread, 0); 1679141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1680141cc406Sopenharmony_ci { 1681141cc406Sopenharmony_ci DBG(1, "do_read: Error from scsi_read: %s\n",sane_strstatus(status)); 1682141cc406Sopenharmony_ci goto quit; 1683141cc406Sopenharmony_ci } 1684141cc406Sopenharmony_ci 1685141cc406Sopenharmony_ci DBG(3, "do_read: got %lu bytes\n", (unsigned long)nread); 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci if (nread <= 0) 1688141cc406Sopenharmony_ci { 1689141cc406Sopenharmony_ci DBG(1, "do_read: Nothing read\n"); 1690141cc406Sopenharmony_ci continue; 1691141cc406Sopenharmony_ci } 1692141cc406Sopenharmony_ci 1693141cc406Sopenharmony_ci status = process_data (ph, (unsigned char *)read_buf, (int)nread); 1694141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 1695141cc406Sopenharmony_ci { 1696141cc406Sopenharmony_ci DBG(1,"do_read: Error in process_data\n"); 1697141cc406Sopenharmony_ci goto quit; 1698141cc406Sopenharmony_ci } 1699141cc406Sopenharmony_ci count -= nread; 1700141cc406Sopenharmony_ci } 1701141cc406Sopenharmony_ci } 1702141cc406Sopenharmony_ci 1703141cc406Sopenharmony_ci process_data_flush (ph); 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ciquit: 1706141cc406Sopenharmony_ci 1707141cc406Sopenharmony_ci process_data_finish (ph); 1708141cc406Sopenharmony_ci 1709141cc406Sopenharmony_ci if ( image_buf ) sanei_hp_free ( image_buf ); 1710141cc406Sopenharmony_ci if ( read_buf ) sanei_hp_free ( read_buf ); 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci if (enable_requests && (reqs_completed < reqs_issued)) 1713141cc406Sopenharmony_ci { 1714141cc406Sopenharmony_ci DBG(1, "do_read: cleaning up leftover requests\n"); 1715141cc406Sopenharmony_ci while (reqs_completed < reqs_issued) 1716141cc406Sopenharmony_ci { 1717141cc406Sopenharmony_ci req = buf + (reqs_completed++ % 2); 1718141cc406Sopenharmony_ci sanei_scsi_req_wait(req->id); 1719141cc406Sopenharmony_ci } 1720141cc406Sopenharmony_ci } 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci sigfillset(&sig_set); 1723141cc406Sopenharmony_ci sigprocmask(SIG_BLOCK, &sig_set, 0); 1724141cc406Sopenharmony_ci for (i = 0; i < (int)(HP_NSIGS); i++) 1725141cc406Sopenharmony_ci sigaction(kill_sig[i], &old_handler[i], 0); 1726141cc406Sopenharmony_ci sigprocmask(SIG_SETMASK, &old_set, 0); 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_ci if (signal_caught) 1729141cc406Sopenharmony_ci { 1730141cc406Sopenharmony_ci DBG(1, "do_read: caught signal %d\n", signal_caught); 1731141cc406Sopenharmony_ci raise(signal_caught); 1732141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1733141cc406Sopenharmony_ci } 1734141cc406Sopenharmony_ci 1735141cc406Sopenharmony_ci return status; 1736141cc406Sopenharmony_ci} 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci/* 1741141cc406Sopenharmony_ci * 1742141cc406Sopenharmony_ci */ 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_cistatic SANE_Status 1745141cc406Sopenharmony_ci_hp_scl_inq (HpScsi scsi, HpScl scl, HpScl inq_cmnd, 1746141cc406Sopenharmony_ci void *valp, size_t *lengthp) 1747141cc406Sopenharmony_ci{ 1748141cc406Sopenharmony_ci size_t bufsize = 16 + (lengthp ? *lengthp: 0); 1749141cc406Sopenharmony_ci char * buf = alloca(bufsize); 1750141cc406Sopenharmony_ci char expect[16], expect_char; 1751141cc406Sopenharmony_ci int val, count; 1752141cc406Sopenharmony_ci SANE_Status status; 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci if (!buf) 1755141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1756141cc406Sopenharmony_ci 1757141cc406Sopenharmony_ci /* Flush data before sending inquiry. */ 1758141cc406Sopenharmony_ci /* Otherwise scanner might not generate a response. */ 1759141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush (scsi)) ; 1760141cc406Sopenharmony_ci 1761141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, inq_cmnd, SCL_INQ_ID(scl)) ); 1762141cc406Sopenharmony_ci usleep (1000); /* 500 works, too, but not 100 */ 1763141cc406Sopenharmony_ci 1764141cc406Sopenharmony_ci status = hp_scsi_read(scsi, buf, &bufsize, 1); 1765141cc406Sopenharmony_ci if (FAILED(status)) 1766141cc406Sopenharmony_ci { 1767141cc406Sopenharmony_ci DBG(1, "scl_inq: read failed (%s)\n", sane_strstatus(status)); 1768141cc406Sopenharmony_ci return status; 1769141cc406Sopenharmony_ci } 1770141cc406Sopenharmony_ci 1771141cc406Sopenharmony_ci if (SCL_PARAM_CHAR(inq_cmnd) == 'R') 1772141cc406Sopenharmony_ci expect_char = 'p'; 1773141cc406Sopenharmony_ci else 1774141cc406Sopenharmony_ci expect_char = tolower(SCL_PARAM_CHAR(inq_cmnd) - 1); 1775141cc406Sopenharmony_ci 1776141cc406Sopenharmony_ci count = sprintf(expect, "\033*s%d%c", SCL_INQ_ID(scl), expect_char); 1777141cc406Sopenharmony_ci if (memcmp(buf, expect, count) != 0) 1778141cc406Sopenharmony_ci { 1779141cc406Sopenharmony_ci DBG(1, "scl_inq: malformed response: expected '%s', got '%.*s'\n", 1780141cc406Sopenharmony_ci expect, count, buf); 1781141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1782141cc406Sopenharmony_ci } 1783141cc406Sopenharmony_ci buf += count; 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci if (buf[0] == 'N') 1786141cc406Sopenharmony_ci { /* null response */ 1787141cc406Sopenharmony_ci DBG(3, "scl_inq: parameter %d unsupported\n", SCL_INQ_ID(scl)); 1788141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1789141cc406Sopenharmony_ci } 1790141cc406Sopenharmony_ci 1791141cc406Sopenharmony_ci if (sscanf(buf, "%d%n", &val, &count) != 1) 1792141cc406Sopenharmony_ci { 1793141cc406Sopenharmony_ci DBG(1, "scl_inq: malformed response: expected int, got '%.8s'\n", buf); 1794141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1795141cc406Sopenharmony_ci } 1796141cc406Sopenharmony_ci buf += count; 1797141cc406Sopenharmony_ci 1798141cc406Sopenharmony_ci expect_char = lengthp ? 'W' : 'V'; 1799141cc406Sopenharmony_ci if (*buf++ != expect_char) 1800141cc406Sopenharmony_ci { 1801141cc406Sopenharmony_ci DBG(1, "scl_inq: malformed response: expected '%c', got '%.4s'\n", 1802141cc406Sopenharmony_ci expect_char, buf - 1); 1803141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1804141cc406Sopenharmony_ci } 1805141cc406Sopenharmony_ci 1806141cc406Sopenharmony_ci if (!lengthp) 1807141cc406Sopenharmony_ci *(int *)valp = val; /* Get integer value */ 1808141cc406Sopenharmony_ci else 1809141cc406Sopenharmony_ci { 1810141cc406Sopenharmony_ci if (val > (int)*lengthp) 1811141cc406Sopenharmony_ci { 1812141cc406Sopenharmony_ci DBG(1, "scl_inq: inquiry returned %d bytes, expected <= %lu\n", 1813141cc406Sopenharmony_ci val, (unsigned long) *lengthp); 1814141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1815141cc406Sopenharmony_ci } 1816141cc406Sopenharmony_ci *lengthp = val; 1817141cc406Sopenharmony_ci memcpy(valp, buf , *lengthp); /* Get binary data */ 1818141cc406Sopenharmony_ci } 1819141cc406Sopenharmony_ci 1820141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1821141cc406Sopenharmony_ci} 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci 1824141cc406Sopenharmony_ciSANE_Status 1825141cc406Sopenharmony_cisanei_hp_scl_upload_binary (HpScsi scsi, HpScl scl, size_t *lengthhp, 1826141cc406Sopenharmony_ci char **bufhp) 1827141cc406Sopenharmony_ci{ 1828141cc406Sopenharmony_ci size_t bufsize = 16, sv; 1829141cc406Sopenharmony_ci char * buf = alloca(bufsize); 1830141cc406Sopenharmony_ci char * bufstart = buf; 1831141cc406Sopenharmony_ci char * hpdata; 1832141cc406Sopenharmony_ci char expect[16], expect_char; 1833141cc406Sopenharmony_ci int n, val, count; 1834141cc406Sopenharmony_ci SANE_Status status; 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci if (!buf) 1837141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1838141cc406Sopenharmony_ci 1839141cc406Sopenharmony_ci assert ( IS_SCL_DATA_TYPE (scl) ); 1840141cc406Sopenharmony_ci 1841141cc406Sopenharmony_ci /* Flush data before sending inquiry. */ 1842141cc406Sopenharmony_ci /* Otherwise scanner might not generate a response. */ 1843141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush (scsi)) ; 1844141cc406Sopenharmony_ci 1845141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_UPLOAD_BINARY_DATA, SCL_INQ_ID(scl)) ); 1846141cc406Sopenharmony_ci 1847141cc406Sopenharmony_ci status = hp_scsi_read(scsi, buf, &bufsize, 0); 1848141cc406Sopenharmony_ci if (FAILED(status)) 1849141cc406Sopenharmony_ci { 1850141cc406Sopenharmony_ci DBG(1, "scl_upload_binary: read failed (%s)\n", sane_strstatus(status)); 1851141cc406Sopenharmony_ci return status; 1852141cc406Sopenharmony_ci } 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci expect_char = 't'; 1855141cc406Sopenharmony_ci count = sprintf(expect, "\033*s%d%c", SCL_INQ_ID(scl), expect_char); 1856141cc406Sopenharmony_ci if (memcmp(buf, expect, count) != 0) 1857141cc406Sopenharmony_ci { 1858141cc406Sopenharmony_ci DBG(1, "scl_upload_binary: malformed response: expected '%s', got '%.*s'\n", 1859141cc406Sopenharmony_ci expect, count, buf); 1860141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1861141cc406Sopenharmony_ci } 1862141cc406Sopenharmony_ci buf += count; 1863141cc406Sopenharmony_ci 1864141cc406Sopenharmony_ci if (buf[0] == 'N') 1865141cc406Sopenharmony_ci { /* null response */ 1866141cc406Sopenharmony_ci DBG(1, "scl_upload_binary: parameter %d unsupported\n", SCL_INQ_ID(scl)); 1867141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1868141cc406Sopenharmony_ci } 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci if (sscanf(buf, "%d%n", &val, &count) != 1) 1871141cc406Sopenharmony_ci { 1872141cc406Sopenharmony_ci DBG(1, "scl_inq: malformed response: expected int, got '%.8s'\n", buf); 1873141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1874141cc406Sopenharmony_ci } 1875141cc406Sopenharmony_ci buf += count; 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci expect_char = 'W'; 1878141cc406Sopenharmony_ci if (*buf++ != expect_char) 1879141cc406Sopenharmony_ci { 1880141cc406Sopenharmony_ci DBG(1, "scl_inq: malformed response: expected '%c', got '%.4s'\n", 1881141cc406Sopenharmony_ci expect_char, buf - 1); 1882141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1883141cc406Sopenharmony_ci } 1884141cc406Sopenharmony_ci 1885141cc406Sopenharmony_ci *lengthhp = val; 1886141cc406Sopenharmony_ci *bufhp = hpdata = sanei_hp_alloc ( val ); 1887141cc406Sopenharmony_ci if (!hpdata) 1888141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1889141cc406Sopenharmony_ci 1890141cc406Sopenharmony_ci if (buf < bufstart + bufsize) 1891141cc406Sopenharmony_ci { 1892141cc406Sopenharmony_ci n = bufsize - (buf - bufstart); 1893141cc406Sopenharmony_ci if (n > val) n = val; 1894141cc406Sopenharmony_ci memcpy (hpdata, buf, n); 1895141cc406Sopenharmony_ci hpdata += n; 1896141cc406Sopenharmony_ci val -= n; 1897141cc406Sopenharmony_ci } 1898141cc406Sopenharmony_ci 1899141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 1900141cc406Sopenharmony_ci if ( val > 0 ) 1901141cc406Sopenharmony_ci { 1902141cc406Sopenharmony_ci sv = val; 1903141cc406Sopenharmony_ci status = hp_scsi_read(scsi, hpdata, &sv, 0); 1904141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1905141cc406Sopenharmony_ci sanei_hp_free ( *bufhp ); 1906141cc406Sopenharmony_ci } 1907141cc406Sopenharmony_ci 1908141cc406Sopenharmony_ci return status; 1909141cc406Sopenharmony_ci} 1910141cc406Sopenharmony_ci 1911141cc406Sopenharmony_ci 1912141cc406Sopenharmony_ciSANE_Status 1913141cc406Sopenharmony_cisanei_hp_scl_set(HpScsi scsi, HpScl scl, int val) 1914141cc406Sopenharmony_ci{ 1915141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, scl, val) ); 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci 1918141cc406Sopenharmony_ci#ifdef PARANOID 1919141cc406Sopenharmony_ci RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); 1920141cc406Sopenharmony_ci#endif 1921141cc406Sopenharmony_ci 1922141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1923141cc406Sopenharmony_ci} 1924141cc406Sopenharmony_ci 1925141cc406Sopenharmony_ciSANE_Status 1926141cc406Sopenharmony_cisanei_hp_scl_inquire(HpScsi scsi, HpScl scl, int * valp, int * minp, int * maxp) 1927141cc406Sopenharmony_ci{ 1928141cc406Sopenharmony_ci HpScl inquiry = ( IS_SCL_CONTROL(scl) 1929141cc406Sopenharmony_ci ? SCL_INQUIRE_PRESENT_VALUE 1930141cc406Sopenharmony_ci : SCL_INQUIRE_DEVICE_PARAMETER ); 1931141cc406Sopenharmony_ci 1932141cc406Sopenharmony_ci assert(IS_SCL_CONTROL(scl) || IS_SCL_PARAMETER(scl)); 1933141cc406Sopenharmony_ci assert(IS_SCL_CONTROL(scl) || (!minp && !maxp)); 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci if (valp) 1936141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, inquiry, valp, 0) ); 1937141cc406Sopenharmony_ci if (minp) 1938141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, 1939141cc406Sopenharmony_ci SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); 1940141cc406Sopenharmony_ci if (maxp) 1941141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, 1942141cc406Sopenharmony_ci SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0) ); 1943141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1944141cc406Sopenharmony_ci} 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci#ifdef _HP_NOT_USED 1947141cc406Sopenharmony_cistatic SANE_Status 1948141cc406Sopenharmony_cihp_scl_get_bounds(HpScsi scsi, HpScl scl, int * minp, int * maxp) 1949141cc406Sopenharmony_ci{ 1950141cc406Sopenharmony_ci assert(IS_SCL_CONTROL(scl)); 1951141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); 1952141cc406Sopenharmony_ci return _hp_scl_inq(scsi, scl, SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0); 1953141cc406Sopenharmony_ci} 1954141cc406Sopenharmony_ci#endif 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci#ifdef _HP_NOT_USED 1957141cc406Sopenharmony_cistatic SANE_Status 1958141cc406Sopenharmony_cihp_scl_get_bounds_and_val(HpScsi scsi, HpScl scl, 1959141cc406Sopenharmony_ci int * minp, int * maxp, int * valp) 1960141cc406Sopenharmony_ci{ 1961141cc406Sopenharmony_ci assert(IS_SCL_CONTROL(scl)); 1962141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); 1963141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0) ); 1964141cc406Sopenharmony_ci return _hp_scl_inq(scsi, scl, SCL_INQUIRE_PRESENT_VALUE, valp, 0); 1965141cc406Sopenharmony_ci} 1966141cc406Sopenharmony_ci#endif 1967141cc406Sopenharmony_ci 1968141cc406Sopenharmony_ciSANE_Status 1969141cc406Sopenharmony_cisanei_hp_scl_download(HpScsi scsi, HpScl scl, const void * valp, size_t len) 1970141cc406Sopenharmony_ci{ 1971141cc406Sopenharmony_ci assert(IS_SCL_DATA_TYPE(scl)); 1972141cc406Sopenharmony_ci 1973141cc406Sopenharmony_ci sanei_hp_scl_clearErrors ( scsi ); 1974141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_need(scsi, 16) ); 1975141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_DOWNLOAD_TYPE, SCL_INQ_ID(scl)) ); 1976141cc406Sopenharmony_ci /* Download type not supported ? */ 1977141cc406Sopenharmony_ci RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); 1978141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_DOWNLOAD_LENGTH, len) ); 1979141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_write(scsi, valp, len) ); 1980141cc406Sopenharmony_ci 1981141cc406Sopenharmony_ci#ifdef PARANOID 1982141cc406Sopenharmony_ci RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); 1983141cc406Sopenharmony_ci#endif 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1986141cc406Sopenharmony_ci} 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ciSANE_Status 1989141cc406Sopenharmony_cisanei_hp_scl_upload(HpScsi scsi, HpScl scl, void * valp, size_t len) 1990141cc406Sopenharmony_ci{ 1991141cc406Sopenharmony_ci size_t nread = len; 1992141cc406Sopenharmony_ci HpScl inquiry = ( IS_SCL_DATA_TYPE(scl) 1993141cc406Sopenharmony_ci ? SCL_UPLOAD_BINARY_DATA 1994141cc406Sopenharmony_ci : SCL_INQUIRE_DEVICE_PARAMETER ); 1995141cc406Sopenharmony_ci 1996141cc406Sopenharmony_ci assert(IS_SCL_DATA_TYPE(scl) || IS_SCL_PARAMETER(scl)); 1997141cc406Sopenharmony_ci 1998141cc406Sopenharmony_ci RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, inquiry, valp, &nread) ); 1999141cc406Sopenharmony_ci if (IS_SCL_PARAMETER(scl) && nread < len) 2000141cc406Sopenharmony_ci ((char *)valp)[nread] = '\0'; 2001141cc406Sopenharmony_ci else if (len != nread) 2002141cc406Sopenharmony_ci { 2003141cc406Sopenharmony_ci DBG(1, "scl_upload: requested %lu bytes, got %lu\n", 2004141cc406Sopenharmony_ci (unsigned long) len, (unsigned long) nread); 2005141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2006141cc406Sopenharmony_ci } 2007141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2008141cc406Sopenharmony_ci} 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ciSANE_Status 2011141cc406Sopenharmony_cisanei_hp_scl_calibrate(HpScsi scsi) 2012141cc406Sopenharmony_ci{ 2013141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_CALIBRATE, 0) ); 2014141cc406Sopenharmony_ci return hp_scsi_flush(scsi); 2015141cc406Sopenharmony_ci} 2016141cc406Sopenharmony_ci 2017141cc406Sopenharmony_ciSANE_Status 2018141cc406Sopenharmony_cisanei_hp_scl_startScan(HpScsi scsi, HpScl scl) 2019141cc406Sopenharmony_ci{ 2020141cc406Sopenharmony_ci char *msg = ""; 2021141cc406Sopenharmony_ci 2022141cc406Sopenharmony_ci if (scl == SCL_ADF_SCAN) msg = " (ADF)"; 2023141cc406Sopenharmony_ci else if (scl == SCL_XPA_SCAN) msg = " (XPA)"; 2024141cc406Sopenharmony_ci else scl = SCL_START_SCAN; 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci DBG(1, "sanei_hp_scl_startScan: Start scan%s\n", msg); 2027141cc406Sopenharmony_ci 2028141cc406Sopenharmony_ci /* For active XPA we must not use XPA scan */ 2029141cc406Sopenharmony_ci if ((scl == SCL_XPA_SCAN) && sanei_hp_is_active_xpa (scsi)) 2030141cc406Sopenharmony_ci { 2031141cc406Sopenharmony_ci DBG(3,"Map XPA scan to scan because of active XPA\n"); 2032141cc406Sopenharmony_ci scl = SCL_START_SCAN; 2033141cc406Sopenharmony_ci } 2034141cc406Sopenharmony_ci 2035141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_scl(scsi, scl, 0) ); 2036141cc406Sopenharmony_ci return hp_scsi_flush(scsi); 2037141cc406Sopenharmony_ci} 2038141cc406Sopenharmony_ci 2039141cc406Sopenharmony_ciSANE_Status 2040141cc406Sopenharmony_cisanei_hp_scl_reset(HpScsi scsi) 2041141cc406Sopenharmony_ci{ 2042141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_write(scsi, "\033E", 2) ); 2043141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush(scsi) ); 2044141cc406Sopenharmony_ci return sanei_hp_scl_errcheck(scsi); 2045141cc406Sopenharmony_ci} 2046141cc406Sopenharmony_ci 2047141cc406Sopenharmony_ciSANE_Status 2048141cc406Sopenharmony_cisanei_hp_scl_clearErrors(HpScsi scsi) 2049141cc406Sopenharmony_ci{ 2050141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_flush(scsi) ); 2051141cc406Sopenharmony_ci RETURN_IF_FAIL( hp_scsi_write(scsi, "\033*oE", 4) ); 2052141cc406Sopenharmony_ci return hp_scsi_flush(scsi); 2053141cc406Sopenharmony_ci} 2054141cc406Sopenharmony_ci 2055141cc406Sopenharmony_cistatic const char * 2056141cc406Sopenharmony_cihp_scl_strerror (int errnum) 2057141cc406Sopenharmony_ci{ 2058141cc406Sopenharmony_ci static const char * errlist[] = { 2059141cc406Sopenharmony_ci "Command Format Error", 2060141cc406Sopenharmony_ci "Unrecognized Command", 2061141cc406Sopenharmony_ci "Parameter Error", 2062141cc406Sopenharmony_ci "Illegal Window", 2063141cc406Sopenharmony_ci "Scaling Error", 2064141cc406Sopenharmony_ci "Dither ID Error", 2065141cc406Sopenharmony_ci "Tone Map ID Error", 2066141cc406Sopenharmony_ci "Lamp Error", 2067141cc406Sopenharmony_ci "Matrix ID Error", 2068141cc406Sopenharmony_ci "Cal Strip Param Error", 2069141cc406Sopenharmony_ci "Gross Calibration Error" 2070141cc406Sopenharmony_ci }; 2071141cc406Sopenharmony_ci 2072141cc406Sopenharmony_ci if (errnum >= 0 && errnum < (int)(sizeof(errlist)/sizeof(errlist[0]))) 2073141cc406Sopenharmony_ci return errlist[errnum]; 2074141cc406Sopenharmony_ci else 2075141cc406Sopenharmony_ci switch(errnum) { 2076141cc406Sopenharmony_ci case 1024: return "ADF Paper Jam"; 2077141cc406Sopenharmony_ci case 1025: return "Home Position Missing"; 2078141cc406Sopenharmony_ci case 1026: return "Paper Not Loaded"; 2079141cc406Sopenharmony_ci default: return "??Unknown Error??"; 2080141cc406Sopenharmony_ci } 2081141cc406Sopenharmony_ci} 2082141cc406Sopenharmony_ci 2083141cc406Sopenharmony_ci/* Check for SCL errors */ 2084141cc406Sopenharmony_ciSANE_Status 2085141cc406Sopenharmony_cisanei_hp_scl_errcheck (HpScsi scsi) 2086141cc406Sopenharmony_ci{ 2087141cc406Sopenharmony_ci int errnum; 2088141cc406Sopenharmony_ci int nerrors; 2089141cc406Sopenharmony_ci SANE_Status status; 2090141cc406Sopenharmony_ci 2091141cc406Sopenharmony_ci status = sanei_hp_scl_inquire(scsi, SCL_CURRENT_ERROR_STACK, &nerrors,0,0); 2092141cc406Sopenharmony_ci if (!FAILED(status) && nerrors) 2093141cc406Sopenharmony_ci status = sanei_hp_scl_inquire(scsi, SCL_OLDEST_ERROR, &errnum,0,0); 2094141cc406Sopenharmony_ci if (FAILED(status)) 2095141cc406Sopenharmony_ci { 2096141cc406Sopenharmony_ci DBG(1, "scl_errcheck: Can't read SCL error stack: %s\n", 2097141cc406Sopenharmony_ci sane_strstatus(status)); 2098141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2099141cc406Sopenharmony_ci } 2100141cc406Sopenharmony_ci 2101141cc406Sopenharmony_ci if (nerrors) 2102141cc406Sopenharmony_ci { 2103141cc406Sopenharmony_ci DBG(1, "Scanner issued SCL error: (%d) %s\n", 2104141cc406Sopenharmony_ci errnum, hp_scl_strerror(errnum)); 2105141cc406Sopenharmony_ci 2106141cc406Sopenharmony_ci sanei_hp_scl_clearErrors (scsi); 2107141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2108141cc406Sopenharmony_ci } 2109141cc406Sopenharmony_ci 2110141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2111141cc406Sopenharmony_ci} 2112