1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 1997, 1998, 2001, 2002, 2013 Franck Schnefra, Michel Roelofs, 4141cc406Sopenharmony_ci Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, 5141cc406Sopenharmony_ci Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson, 6141cc406Sopenharmony_ci Max Ushakov, Andrew Goodbody, Oliver Schwartz and Kevin Charter 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This file is part of the SANE package. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 11141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 12141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 13141cc406Sopenharmony_ci License, or (at your option) any later version. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 16141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 17141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18141cc406Sopenharmony_ci General Public License for more details. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 21141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 24141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 27141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 28141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 29141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 30141cc406Sopenharmony_ci account of linking the SANE library code into it. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 33141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 34141cc406Sopenharmony_ci License. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 37141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 38141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 41141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 42141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci This file is a component of the implementation of a backend for many 45141cc406Sopenharmony_ci of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. 46141cc406Sopenharmony_ci*/ 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci/* 49141cc406Sopenharmony_ci SnapScan backend scsi command functions 50141cc406Sopenharmony_ci*/ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci/* scanner scsi commands */ 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_cistatic SANE_Status download_firmware(SnapScan_Scanner * pss); 55141cc406Sopenharmony_cistatic SANE_Status wait_scanner_ready (SnapScan_Scanner * pss); 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci#include "snapscan-usb.h" 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci/* find model by SCSI ID string or USB vendor/product ID */ 60141cc406Sopenharmony_cistatic SnapScan_Model snapscani_get_model_id(char* model_str, int fd, SnapScan_Bus bus_type) 61141cc406Sopenharmony_ci{ 62141cc406Sopenharmony_ci static char me[] = "snapscani_get_model_id"; 63141cc406Sopenharmony_ci SnapScan_Model model_id = UNKNOWN; 64141cc406Sopenharmony_ci SANE_Word vendor_id, product_id; 65141cc406Sopenharmony_ci int i; 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci DBG(DL_CALL_TRACE, "%s(%s, %d, %d)\n",me, model_str, fd, bus_type); 68141cc406Sopenharmony_ci for (i = 0; i < known_scanners; i++) 69141cc406Sopenharmony_ci { 70141cc406Sopenharmony_ci if (0 == strcasecmp (model_str, scanners[i].scsi_name)) 71141cc406Sopenharmony_ci { 72141cc406Sopenharmony_ci model_id = scanners[i].id; 73141cc406Sopenharmony_ci break; 74141cc406Sopenharmony_ci } 75141cc406Sopenharmony_ci } 76141cc406Sopenharmony_ci /* Also test USB vendor and product ID numbers, since some USB models use 77141cc406Sopenharmony_ci identical model names. 78141cc406Sopenharmony_ci */ 79141cc406Sopenharmony_ci if ((bus_type == USB) && 80141cc406Sopenharmony_ci (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) == SANE_STATUS_GOOD)) 81141cc406Sopenharmony_ci { 82141cc406Sopenharmony_ci DBG(DL_MINOR_INFO, 83141cc406Sopenharmony_ci "%s: looking up scanner for ID 0x%04x,0x%04x.\n", 84141cc406Sopenharmony_ci me, vendor_id, product_id); 85141cc406Sopenharmony_ci for (i = 0; i < known_usb_scanners; i++) 86141cc406Sopenharmony_ci { 87141cc406Sopenharmony_ci if ((usb_scanners[i].vendor_id == vendor_id) && 88141cc406Sopenharmony_ci (usb_scanners[i].product_id == product_id)) 89141cc406Sopenharmony_ci { 90141cc406Sopenharmony_ci model_id = usb_scanners[i].id; 91141cc406Sopenharmony_ci DBG(DL_MINOR_INFO, "%s: scanner identified\n", me); 92141cc406Sopenharmony_ci break; 93141cc406Sopenharmony_ci } 94141cc406Sopenharmony_ci } 95141cc406Sopenharmony_ci } 96141cc406Sopenharmony_ci return model_id; 97141cc406Sopenharmony_ci} 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/* a sensible sense handler, courtesy of Franck; 100141cc406Sopenharmony_ci the last argument is expected to be a pointer to the associated 101141cc406Sopenharmony_ci SnapScan_Scanner structure */ 102141cc406Sopenharmony_cistatic SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg) 103141cc406Sopenharmony_ci{ 104141cc406Sopenharmony_ci static char me[] = "sense_handler"; 105141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) arg; 106141cc406Sopenharmony_ci u_char sense, asc, ascq; 107141cc406Sopenharmony_ci char *sense_str = NULL, *as_str = NULL; 108141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s(%ld, %p, %p)\n", me, (long) scsi_fd, 111141cc406Sopenharmony_ci (void *) result, (void *) arg); 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci sense = result[2] & 0x0f; 114141cc406Sopenharmony_ci asc = result[12]; 115141cc406Sopenharmony_ci ascq = result[13]; 116141cc406Sopenharmony_ci if (pss) 117141cc406Sopenharmony_ci { 118141cc406Sopenharmony_ci pss->asi1 = result[18]; 119141cc406Sopenharmony_ci pss->asi2 = result[19]; 120141cc406Sopenharmony_ci } 121141cc406Sopenharmony_ci if ((result[0] & 0x80) == 0) 122141cc406Sopenharmony_ci { 123141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: sense key is invalid.\n", me); 124141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* sense key invalid */ 125141cc406Sopenharmony_ci } else { 126141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: sense key: 0x%02x, asc: 0x%02x, ascq: 0x%02x, i1: 0x%02x, i2: 0x%02x\n", 127141cc406Sopenharmony_ci me, sense, asc, ascq, result[18], result[19]); 128141cc406Sopenharmony_ci } 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci switch (sense) 131141cc406Sopenharmony_ci { 132141cc406Sopenharmony_ci case 0x00: 133141cc406Sopenharmony_ci /* no sense */ 134141cc406Sopenharmony_ci sense_str = "No sense."; 135141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, sense_str); 136141cc406Sopenharmony_ci break; 137141cc406Sopenharmony_ci case 0x02: 138141cc406Sopenharmony_ci /* not ready */ 139141cc406Sopenharmony_ci sense_str = "Not ready."; 140141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, sense_str); 141141cc406Sopenharmony_ci if (asc == 0x04 && ascq == 0x01) 142141cc406Sopenharmony_ci { 143141cc406Sopenharmony_ci /* warming up; byte 18 contains remaining seconds */ 144141cc406Sopenharmony_ci as_str = "Logical unit is in process of becoming ready."; 145141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s (%d seconds)\n", me, as_str, result[18]); 146141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 147141cc406Sopenharmony_ci } 148141cc406Sopenharmony_ci break; 149141cc406Sopenharmony_ci case 0x04: 150141cc406Sopenharmony_ci /* hardware error */ 151141cc406Sopenharmony_ci sense_str = "Hardware error."; 152141cc406Sopenharmony_ci /* byte 18 and 19 detail the hardware problems */ 153141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s (0x%02x, 0x%02x)\n", me, sense_str, result[18], 154141cc406Sopenharmony_ci result[19]); 155141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 156141cc406Sopenharmony_ci break; 157141cc406Sopenharmony_ci case 0x05: 158141cc406Sopenharmony_ci /* illegal request */ 159141cc406Sopenharmony_ci sense_str = "Illegal request."; 160141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, sense_str); 161141cc406Sopenharmony_ci if (asc == 0x25 && ascq == 0x00) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci as_str = "Logical unit not supported."; 164141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, as_str); 165141cc406Sopenharmony_ci } 166141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 167141cc406Sopenharmony_ci break; 168141cc406Sopenharmony_ci case 0x09: 169141cc406Sopenharmony_ci /* process error */ 170141cc406Sopenharmony_ci sense_str = "Process error."; 171141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, sense_str); 172141cc406Sopenharmony_ci if (asc == 0x00 && ascq == 0x05) 173141cc406Sopenharmony_ci { 174141cc406Sopenharmony_ci /* no documents in ADF */ 175141cc406Sopenharmony_ci as_str = "End of data detected."; 176141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, as_str); 177141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 178141cc406Sopenharmony_ci } 179141cc406Sopenharmony_ci else if (asc == 0x3b && ascq == 0x05) 180141cc406Sopenharmony_ci { 181141cc406Sopenharmony_ci /* paper jam in ADF */ 182141cc406Sopenharmony_ci as_str = "Paper jam."; 183141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, as_str); 184141cc406Sopenharmony_ci status = SANE_STATUS_JAMMED; 185141cc406Sopenharmony_ci } 186141cc406Sopenharmony_ci else if (asc == 0x3b && ascq == 0x09) 187141cc406Sopenharmony_ci { 188141cc406Sopenharmony_ci /* scanning area exceeds end of paper in ADF */ 189141cc406Sopenharmony_ci as_str = "Read past end of medium."; 190141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, as_str); 191141cc406Sopenharmony_ci status = SANE_STATUS_EOF; 192141cc406Sopenharmony_ci } 193141cc406Sopenharmony_ci break; 194141cc406Sopenharmony_ci case 0x0b: 195141cc406Sopenharmony_ci /* Aborted command */ 196141cc406Sopenharmony_ci sense_str = "Aborted Command."; 197141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: %s\n", me, sense_str); 198141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 199141cc406Sopenharmony_ci break; 200141cc406Sopenharmony_ci default: 201141cc406Sopenharmony_ci DBG (DL_MINOR_ERROR, "%s: no handling for sense %x.\n", me, sense); 202141cc406Sopenharmony_ci break; 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci if (pss) 206141cc406Sopenharmony_ci { 207141cc406Sopenharmony_ci pss->sense_str = sense_str; 208141cc406Sopenharmony_ci pss->as_str = as_str; 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci return status; 211141cc406Sopenharmony_ci} 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_cistatic SANE_Status open_scanner (SnapScan_Scanner *pss) 215141cc406Sopenharmony_ci{ 216141cc406Sopenharmony_ci SANE_Status status; 217141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "open_scanner\n"); 218141cc406Sopenharmony_ci if (!pss->opens) 219141cc406Sopenharmony_ci { 220141cc406Sopenharmony_ci if(pss->pdev->bus == SCSI) 221141cc406Sopenharmony_ci { 222141cc406Sopenharmony_ci status = sanei_scsi_open (pss->devname, &(pss->fd), 223141cc406Sopenharmony_ci sense_handler, (void *) pss); 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci else 226141cc406Sopenharmony_ci { 227141cc406Sopenharmony_ci status = snapscani_usb_open (pss->devname, &(pss->fd), 228141cc406Sopenharmony_ci sense_handler, (void *) pss); 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci } 231141cc406Sopenharmony_ci else 232141cc406Sopenharmony_ci { 233141cc406Sopenharmony_ci /* already open */ 234141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 235141cc406Sopenharmony_ci } 236141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 237141cc406Sopenharmony_ci pss->opens++; 238141cc406Sopenharmony_ci return status; 239141cc406Sopenharmony_ci} 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_cistatic void close_scanner (SnapScan_Scanner *pss) 242141cc406Sopenharmony_ci{ 243141cc406Sopenharmony_ci static char me[] = "close_scanner"; 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 246141cc406Sopenharmony_ci if (pss->opens) 247141cc406Sopenharmony_ci { 248141cc406Sopenharmony_ci pss->opens--; 249141cc406Sopenharmony_ci if (!pss->opens) 250141cc406Sopenharmony_ci { 251141cc406Sopenharmony_ci if(pss->pdev->bus == SCSI) 252141cc406Sopenharmony_ci { 253141cc406Sopenharmony_ci sanei_scsi_close (pss->fd); 254141cc406Sopenharmony_ci } 255141cc406Sopenharmony_ci else if(pss->pdev->bus == USB) 256141cc406Sopenharmony_ci { 257141cc406Sopenharmony_ci snapscani_usb_close (pss->fd); 258141cc406Sopenharmony_ci } 259141cc406Sopenharmony_ci } else { 260141cc406Sopenharmony_ci DBG(DL_INFO, "%s: handles left: %d\n,",me, pss->opens); 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci } 263141cc406Sopenharmony_ci} 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_cistatic SANE_Status snapscan_cmd(SnapScan_Bus bus, int fd, const void *src, 266141cc406Sopenharmony_ci size_t src_size, void *dst, size_t * dst_size) 267141cc406Sopenharmony_ci{ 268141cc406Sopenharmony_ci SANE_Status status; 269141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "snapscan_cmd\n"); 270141cc406Sopenharmony_ci if(bus == USB) 271141cc406Sopenharmony_ci { 272141cc406Sopenharmony_ci status = snapscani_usb_cmd(fd, src, src_size, dst, dst_size); 273141cc406Sopenharmony_ci } 274141cc406Sopenharmony_ci else 275141cc406Sopenharmony_ci { 276141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, src, src_size, dst, dst_size); 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci return status; 279141cc406Sopenharmony_ci} 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci/* SCSI commands */ 282141cc406Sopenharmony_ci#define TEST_UNIT_READY 0x00 283141cc406Sopenharmony_ci#define INQUIRY 0x12 284141cc406Sopenharmony_ci#define SEND 0x2A 285141cc406Sopenharmony_ci#define SET_WINDOW 0x24 286141cc406Sopenharmony_ci#define SCAN 0x1B 287141cc406Sopenharmony_ci#define READ 0x28 288141cc406Sopenharmony_ci#define REQUEST_SENSE 0x03 289141cc406Sopenharmony_ci#define RESERVE_UNIT 0x16 290141cc406Sopenharmony_ci#define RELEASE_UNIT 0x17 291141cc406Sopenharmony_ci#define SEND_DIAGNOSTIC 0x1D 292141cc406Sopenharmony_ci#define OBJECT_POSITION 0x31 293141cc406Sopenharmony_ci#define GET_DATA_BUFFER_STATUS 0x34 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_ci#define SCAN_LEN 6 296141cc406Sopenharmony_ci#define READ_LEN 10 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci/* buffer tools */ 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_cistatic void zero_buf (u_char * buf, size_t len) 301141cc406Sopenharmony_ci{ 302141cc406Sopenharmony_ci size_t i; 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci for (i = 0; i < len; i++) 305141cc406Sopenharmony_ci buf[i] = 0x00; 306141cc406Sopenharmony_ci} 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci#define BYTE_SIZE 8 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_cistatic u_short u_char_to_u_short (u_char * pc) 312141cc406Sopenharmony_ci{ 313141cc406Sopenharmony_ci u_short r = 0; 314141cc406Sopenharmony_ci r |= pc[0]; 315141cc406Sopenharmony_ci r = r << BYTE_SIZE; 316141cc406Sopenharmony_ci r |= pc[1]; 317141cc406Sopenharmony_ci return r; 318141cc406Sopenharmony_ci} 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_cistatic void u_short_to_u_charp (u_short x, u_char * pc) 321141cc406Sopenharmony_ci{ 322141cc406Sopenharmony_ci pc[0] = (0xFF00 & x) >> BYTE_SIZE; 323141cc406Sopenharmony_ci pc[1] = (0x00FF & x); 324141cc406Sopenharmony_ci} 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_cistatic void u_int_to_u_char3p (u_int x, u_char * pc) 327141cc406Sopenharmony_ci{ 328141cc406Sopenharmony_ci pc[0] = (0xFF0000 & x) >> 2 * BYTE_SIZE; 329141cc406Sopenharmony_ci pc[1] = (0x00FF00 & x) >> BYTE_SIZE; 330141cc406Sopenharmony_ci pc[2] = (0x0000FF & x); 331141cc406Sopenharmony_ci} 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_cistatic void u_int_to_u_char4p (u_int x, u_char * pc) 334141cc406Sopenharmony_ci{ 335141cc406Sopenharmony_ci pc[0] = (0xFF000000 & x) >> 3 * BYTE_SIZE; 336141cc406Sopenharmony_ci pc[1] = (0x00FF0000 & x) >> 2 * BYTE_SIZE; 337141cc406Sopenharmony_ci pc[2] = (0x0000FF00 & x) >> BYTE_SIZE; 338141cc406Sopenharmony_ci pc[3] = (0x000000FF & x); 339141cc406Sopenharmony_ci} 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ci/* Convert 'STRING ' to 'STRING' by adding 0 after last non-space */ 342141cc406Sopenharmony_cistatic void remove_trailing_space (char *s) 343141cc406Sopenharmony_ci{ 344141cc406Sopenharmony_ci int position; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci if (NULL == s) 347141cc406Sopenharmony_ci return; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci for (position = strlen (s); 350141cc406Sopenharmony_ci position > 0 && ' ' == s[position - 1]; 351141cc406Sopenharmony_ci position--) 352141cc406Sopenharmony_ci { 353141cc406Sopenharmony_ci /* dummy */; 354141cc406Sopenharmony_ci } 355141cc406Sopenharmony_ci s[position] = 0; 356141cc406Sopenharmony_ci} 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_cistatic void check_range (int *v, SANE_Range r) 359141cc406Sopenharmony_ci{ 360141cc406Sopenharmony_ci if (*v < r.min) 361141cc406Sopenharmony_ci *v = r.min; 362141cc406Sopenharmony_ci if (*v > r.max) 363141cc406Sopenharmony_ci *v = r.max; 364141cc406Sopenharmony_ci} 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci#define INQUIRY_LEN 6 367141cc406Sopenharmony_ci#define INQUIRY_RET_LEN 120 368141cc406Sopenharmony_ci#define INQUIRY_RET_LEN_EPSON 139 369141cc406Sopenharmony_ci#define INQUIRY_RET_LEN_5000 138 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci#define INQUIRY_VENDOR 8 /* Offset in reply data to vendor name */ 372141cc406Sopenharmony_ci#define INQUIRY_PRODUCT 16 /* Offset in reply data to product id */ 373141cc406Sopenharmony_ci#define INQUIRY_REV 32 /* Offset in reply data to revision level */ 374141cc406Sopenharmony_ci#define INQUIRY_PRL2 36 /* Product Revision Level 2 (AGFA) */ 375141cc406Sopenharmony_ci#define INQUIRY_HCFG 37 /* Hardware Configuration (AGFA) */ 376141cc406Sopenharmony_ci#define INQUIRY_HWST 40 /* Hardware status */ 377141cc406Sopenharmony_ci#define INQUIRY_HWMI 41 /* HARDWARE Model ID */ 378141cc406Sopenharmony_ci#define INQUIRY_PIX_PER_LINE 42 /* Pixels per scan line (AGFA) */ 379141cc406Sopenharmony_ci#define INQUIRY_BYTE_PER_LINE 44 /* Bytes per scan line (AGFA) */ 380141cc406Sopenharmony_ci#define INQUIRY_NUM_LINES 46 /* number of scan lines (AGFA) */ 381141cc406Sopenharmony_ci#define INQUIRY_OPT_RES 48 /* optical resolution (AGFA) */ 382141cc406Sopenharmony_ci#define INQUIRY_SCAN_SPEED 51 /* scan speed (AGFA) */ 383141cc406Sopenharmony_ci#define INQUIRY_EXPTIME1 52 /* exposure time, first digit (AGFA) */ 384141cc406Sopenharmony_ci#define INQUIRY_EXPTIME2 53 /* exposure time, second digit (AGFA) */ 385141cc406Sopenharmony_ci#define INQUIRY_G2R_DIFF 54 /* green to red difference (AGFA) */ 386141cc406Sopenharmony_ci#define INQUIRY_B2R_DIFF 55 /* green to red difference (AGFA) */ 387141cc406Sopenharmony_ci#define INQUIRY_FIRMWARE 96 /* firmware date and time (AGFA) */ 388141cc406Sopenharmony_ci#define INQUIRY_BYTE_PER_LINE_MSB 132 /* ?? top byte of bytes per scan line - epson 2480 */ 389141cc406Sopenharmony_ci#define INQUIRY_EPSON_HCFG 138 /* ?? Hardware configuration (Epson) */ 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_ci/* a mini-inquiry reads only the first 36 bytes of inquiry data, and 393141cc406Sopenharmony_ci returns the vendor(7 chars) and model(16 chars); vendor and model 394141cc406Sopenharmony_ci must point to character buffers of size at least 8 and 17 395141cc406Sopenharmony_ci respectively */ 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_cistatic SANE_Status mini_inquiry (SnapScan_Bus bus, int fd, char *vendor, char *model) 398141cc406Sopenharmony_ci{ 399141cc406Sopenharmony_ci static const char *me = "mini_inquiry"; 400141cc406Sopenharmony_ci size_t read_bytes; 401141cc406Sopenharmony_ci char cmd[] = {INQUIRY, 0, 0, 0, 36, 0}; 402141cc406Sopenharmony_ci char data[36]; 403141cc406Sopenharmony_ci SANE_Status status; 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci read_bytes = 36; 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 408141cc406Sopenharmony_ci status = snapscan_cmd (bus, fd, cmd, sizeof (cmd), data, &read_bytes); 409141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 410141cc406Sopenharmony_ci 411141cc406Sopenharmony_ci memcpy (vendor, data + 8, 7); 412141cc406Sopenharmony_ci vendor[7] = 0; 413141cc406Sopenharmony_ci memcpy (model, data + 16, 16); 414141cc406Sopenharmony_ci model[16] = 0; 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci remove_trailing_space (vendor); 417141cc406Sopenharmony_ci remove_trailing_space (model); 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 420141cc406Sopenharmony_ci} 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci/* TODO: Remove */ 423141cc406Sopenharmony_cistatic char *snapscani_debug_data(char *str,const SANE_Byte *data, int len) { 424141cc406Sopenharmony_ci char tmpstr[10]; 425141cc406Sopenharmony_ci int i; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci str[0]=0; 428141cc406Sopenharmony_ci for(i=0; i < (len < 20 ? len : 20); i++) { 429141cc406Sopenharmony_ci sprintf(tmpstr," 0x%02x",((int)data[i]) & 0xff); 430141cc406Sopenharmony_ci if(i%16 == 0 && i != 0) 431141cc406Sopenharmony_ci strcat(str,"\n"); 432141cc406Sopenharmony_ci strcat(str,tmpstr); 433141cc406Sopenharmony_ci } 434141cc406Sopenharmony_ci if(i < len) 435141cc406Sopenharmony_ci strcat(str," ..."); 436141cc406Sopenharmony_ci return str; 437141cc406Sopenharmony_ci} 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_cistatic SANE_Status inquiry (SnapScan_Scanner *pss) 440141cc406Sopenharmony_ci{ 441141cc406Sopenharmony_ci static const char *me = "inquiry"; 442141cc406Sopenharmony_ci char tmpstr[150]; /* TODO: Remove */ 443141cc406Sopenharmony_ci SANE_Status status; 444141cc406Sopenharmony_ci switch (pss->pdev->model) 445141cc406Sopenharmony_ci { 446141cc406Sopenharmony_ci case PERFECTION2480: 447141cc406Sopenharmony_ci case PERFECTION3490: 448141cc406Sopenharmony_ci if (pss->firmware_loaded) 449141cc406Sopenharmony_ci pss->read_bytes = INQUIRY_RET_LEN_EPSON; 450141cc406Sopenharmony_ci else 451141cc406Sopenharmony_ci pss->read_bytes = INQUIRY_RET_LEN; 452141cc406Sopenharmony_ci break; 453141cc406Sopenharmony_ci case PRISA5000: 454141cc406Sopenharmony_ci case PRISA5150: 455141cc406Sopenharmony_ci pss->read_bytes = INQUIRY_RET_LEN_5000; 456141cc406Sopenharmony_ci break; 457141cc406Sopenharmony_ci default: 458141cc406Sopenharmony_ci pss->read_bytes = INQUIRY_RET_LEN; 459141cc406Sopenharmony_ci break; 460141cc406Sopenharmony_ci } 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 463141cc406Sopenharmony_ci pss->cmd[0] = INQUIRY; 464141cc406Sopenharmony_ci pss->cmd[4] = pss->read_bytes; 465141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 466141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, 467141cc406Sopenharmony_ci pss->fd, 468141cc406Sopenharmony_ci pss->cmd, 469141cc406Sopenharmony_ci INQUIRY_LEN, 470141cc406Sopenharmony_ci pss->buf, 471141cc406Sopenharmony_ci &pss->read_bytes); 472141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci /* record current parameters */ 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci char exptime[4] = {' ', '.', ' ', 0}; 477141cc406Sopenharmony_ci exptime[0] = (char) (pss->buf[INQUIRY_EXPTIME1] + '0'); 478141cc406Sopenharmony_ci exptime[2] = (char) (pss->buf[INQUIRY_EXPTIME2] + '0'); 479141cc406Sopenharmony_ci pss->ms_per_line = atof (exptime)*(float) pss->buf[INQUIRY_SCAN_SPEED]; 480141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: exposure time: %s ms\n", me, exptime); 481141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: ms per line: %f\n", me, pss->ms_per_line); 482141cc406Sopenharmony_ci } 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci switch (pss->pdev->model) 485141cc406Sopenharmony_ci { 486141cc406Sopenharmony_ci case SNAPSCAN: 487141cc406Sopenharmony_ci case ACER300F: 488141cc406Sopenharmony_ci pss->chroma_offset[R_CHAN] = 489141cc406Sopenharmony_ci pss->chroma_offset[G_CHAN] = 490141cc406Sopenharmony_ci pss->chroma_offset[B_CHAN] = 0; 491141cc406Sopenharmony_ci pss->chroma = 0; 492141cc406Sopenharmony_ci break; 493141cc406Sopenharmony_ci case PERFECTION2480: 494141cc406Sopenharmony_ci case PERFECTION3490: 495141cc406Sopenharmony_ci if (pss->firmware_loaded) 496141cc406Sopenharmony_ci { 497141cc406Sopenharmony_ci snapscani_debug_data(tmpstr, pss->buf+120, 19); 498141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Epson additional inquiry data:\n%s\n", me, tmpstr); 499141cc406Sopenharmony_ci pss->hconfig_epson = pss->buf[INQUIRY_EPSON_HCFG]; 500141cc406Sopenharmony_ci } 501141cc406Sopenharmony_ci /* fall through */ 502141cc406Sopenharmony_ci default: 503141cc406Sopenharmony_ci { 504141cc406Sopenharmony_ci signed char min_diff; 505141cc406Sopenharmony_ci u_char r_off, g_off, b_off; 506141cc406Sopenharmony_ci signed char g = (pss->buf[INQUIRY_G2R_DIFF] & 0x80) ? -(pss->buf[INQUIRY_G2R_DIFF] & 0x7F) : pss->buf[INQUIRY_G2R_DIFF]; 507141cc406Sopenharmony_ci signed char b = (pss->buf[INQUIRY_B2R_DIFF] & 0x80) ? -(pss->buf[INQUIRY_B2R_DIFF] & 0x7F) : pss->buf[INQUIRY_B2R_DIFF]; 508141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: G2R_DIFF: %d\n", me, pss->buf[INQUIRY_G2R_DIFF]); 509141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: B2R_DIFF: %d\n", me, pss->buf[INQUIRY_B2R_DIFF]); 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci min_diff = MIN (MIN (b, g), 0); 512141cc406Sopenharmony_ci r_off = (u_char) (0 - min_diff); 513141cc406Sopenharmony_ci g_off = (u_char) (g - min_diff); 514141cc406Sopenharmony_ci b_off = (u_char) (b - min_diff); 515141cc406Sopenharmony_ci pss->chroma_offset[R_CHAN] = r_off; 516141cc406Sopenharmony_ci pss->chroma_offset[G_CHAN] = g_off; 517141cc406Sopenharmony_ci pss->chroma_offset[B_CHAN] = b_off; 518141cc406Sopenharmony_ci pss->chroma = MAX(MAX(r_off, g_off), b_off); 519141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 520141cc406Sopenharmony_ci "%s: Chroma offsets=%d; Red=%u, Green:=%u, Blue=%u\n", 521141cc406Sopenharmony_ci me, pss->chroma, 522141cc406Sopenharmony_ci pss->chroma_offset[R_CHAN], 523141cc406Sopenharmony_ci pss->chroma_offset[G_CHAN], 524141cc406Sopenharmony_ci pss->chroma_offset[B_CHAN]); 525141cc406Sopenharmony_ci } 526141cc406Sopenharmony_ci break; 527141cc406Sopenharmony_ci } 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci pss->actual_res = 530141cc406Sopenharmony_ci u_char_to_u_short (pss->buf + INQUIRY_OPT_RES); 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci pss->pixels_per_line = 533141cc406Sopenharmony_ci u_char_to_u_short (pss->buf + INQUIRY_PIX_PER_LINE); 534141cc406Sopenharmony_ci pss->bytes_per_line = 535141cc406Sopenharmony_ci u_char_to_u_short (pss->buf + INQUIRY_BYTE_PER_LINE); 536141cc406Sopenharmony_ci if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) 537141cc406Sopenharmony_ci pss->bytes_per_line += pss->buf[INQUIRY_BYTE_PER_LINE_MSB] << 16; 538141cc406Sopenharmony_ci pss->lines = 539141cc406Sopenharmony_ci u_char_to_u_short (pss->buf + INQUIRY_NUM_LINES) - pss->chroma; 540141cc406Sopenharmony_ci /* effective buffer size must be a whole number of scan lines */ 541141cc406Sopenharmony_ci if (pss->lines) 542141cc406Sopenharmony_ci pss->buf_sz = (pss->phys_buf_sz/pss->bytes_per_line)*pss->bytes_per_line; 543141cc406Sopenharmony_ci else 544141cc406Sopenharmony_ci pss->buf_sz = 0; 545141cc406Sopenharmony_ci pss->bytes_remaining = pss->bytes_per_line * (pss->lines + pss->chroma); 546141cc406Sopenharmony_ci pss->expected_read_bytes = 0; 547141cc406Sopenharmony_ci pss->read_bytes = 0; 548141cc406Sopenharmony_ci pss->hwst = pss->buf[INQUIRY_HWST]; 549141cc406Sopenharmony_ci if ((pss->pdev->bus == USB) && !(pss->hwst & 0x02)) 550141cc406Sopenharmony_ci { 551141cc406Sopenharmony_ci pss->firmware_loaded = SANE_TRUE; 552141cc406Sopenharmony_ci } 553141cc406Sopenharmony_ci pss->hconfig = pss->buf[INQUIRY_HCFG]; 554141cc406Sopenharmony_ci switch (pss->pdev->model) 555141cc406Sopenharmony_ci { 556141cc406Sopenharmony_ci case PERFECTION1270: 557141cc406Sopenharmony_ci case PERFECTION1670: 558141cc406Sopenharmony_ci case PERFECTION2480: 559141cc406Sopenharmony_ci case PERFECTION3490: 560141cc406Sopenharmony_ci case PRISA5150: 561141cc406Sopenharmony_ci case PRISA5000: 562141cc406Sopenharmony_ci pss->bpp = 14; 563141cc406Sopenharmony_ci break; 564141cc406Sopenharmony_ci case STYLUS_CX1500: 565141cc406Sopenharmony_ci case SCANWIT2720S: 566141cc406Sopenharmony_ci pss->bpp = 12; 567141cc406Sopenharmony_ci break; 568141cc406Sopenharmony_ci default: 569141cc406Sopenharmony_ci pss->bpp = 8; 570141cc406Sopenharmony_ci if (pss->hconfig & HCFG_ADC) 571141cc406Sopenharmony_ci pss->bpp = 10; 572141cc406Sopenharmony_ci break; 573141cc406Sopenharmony_ci } 574141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 575141cc406Sopenharmony_ci "%s: hardware config = 0x%02x\n", 576141cc406Sopenharmony_ci me, 577141cc406Sopenharmony_ci pss->hconfig); 578141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 579141cc406Sopenharmony_ci "%s: bits per pixel = %lu\n", 580141cc406Sopenharmony_ci me, 581141cc406Sopenharmony_ci (u_long) pss->bpp); 582141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 583141cc406Sopenharmony_ci "%s: pixels per scan line = %lu\n", 584141cc406Sopenharmony_ci me, 585141cc406Sopenharmony_ci (u_long) pss->pixels_per_line); 586141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 587141cc406Sopenharmony_ci "%s: bytes per scan line = %lu\n", 588141cc406Sopenharmony_ci me, 589141cc406Sopenharmony_ci (u_long) pss->bytes_per_line); 590141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 591141cc406Sopenharmony_ci "%s: number of scan lines = %lu\n", 592141cc406Sopenharmony_ci me, 593141cc406Sopenharmony_ci (u_long) pss->lines); 594141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 595141cc406Sopenharmony_ci "%s: effective buffer size = %lu bytes, %lu lines\n", 596141cc406Sopenharmony_ci me, 597141cc406Sopenharmony_ci (u_long) pss->buf_sz, 598141cc406Sopenharmony_ci (u_long) (pss->lines ? pss->buf_sz / pss->lines : 0)); 599141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 600141cc406Sopenharmony_ci "%s: expected total scan data: %lu bytes\n", 601141cc406Sopenharmony_ci me, 602141cc406Sopenharmony_ci (u_long) pss->bytes_remaining); 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci return status; 605141cc406Sopenharmony_ci} 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_cistatic SANE_Status test_unit_ready (SnapScan_Scanner *pss) 608141cc406Sopenharmony_ci{ 609141cc406Sopenharmony_ci static const char *me = "test_unit_ready"; 610141cc406Sopenharmony_ci char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; 611141cc406Sopenharmony_ci SANE_Status status; 612141cc406Sopenharmony_ci 613141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 614141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, cmd, sizeof (cmd), NULL, NULL); 615141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 616141cc406Sopenharmony_ci return status; 617141cc406Sopenharmony_ci} 618141cc406Sopenharmony_ci 619141cc406Sopenharmony_cistatic void reserve_unit (SnapScan_Scanner *pss) 620141cc406Sopenharmony_ci{ 621141cc406Sopenharmony_ci static const char *me = "reserve_unit"; 622141cc406Sopenharmony_ci char cmd[] = {RESERVE_UNIT, 0, 0, 0, 0, 0}; 623141cc406Sopenharmony_ci SANE_Status status; 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 626141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, cmd, sizeof (cmd), NULL, NULL); 627141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 628141cc406Sopenharmony_ci { 629141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 630141cc406Sopenharmony_ci "%s: scsi command error: %s\n", 631141cc406Sopenharmony_ci me, 632141cc406Sopenharmony_ci sane_strstatus (status)); 633141cc406Sopenharmony_ci } 634141cc406Sopenharmony_ci} 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_cistatic void release_unit (SnapScan_Scanner *pss) 637141cc406Sopenharmony_ci{ 638141cc406Sopenharmony_ci static const char *me = "release_unit"; 639141cc406Sopenharmony_ci char cmd[] = {RELEASE_UNIT, 0, 0, 0, 0, 0}; 640141cc406Sopenharmony_ci SANE_Status status; 641141cc406Sopenharmony_ci 642141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 643141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, cmd, sizeof (cmd), NULL, NULL); 644141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 645141cc406Sopenharmony_ci { 646141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 647141cc406Sopenharmony_ci "%s: scsi command error: %s\n", 648141cc406Sopenharmony_ci me, sane_strstatus (status)); 649141cc406Sopenharmony_ci } 650141cc406Sopenharmony_ci} 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci#define SEND_LENGTH 10 653141cc406Sopenharmony_ci#define DTC_HALFTONE 0x02 654141cc406Sopenharmony_ci#define DTC_GAMMA 0x03 655141cc406Sopenharmony_ci#define DTC_GAMMA2 0x04 656141cc406Sopenharmony_ci#define DTC_SPEED 0x81 657141cc406Sopenharmony_ci#define DTC_CALIBRATION 0x82 658141cc406Sopenharmony_ci#define DTC_CALIBRATION_BLACK 0x89 659141cc406Sopenharmony_ci#define DTCQ_HALFTONE_BW8 0x00 660141cc406Sopenharmony_ci#define DTCQ_HALFTONE_COLOR8 0x01 661141cc406Sopenharmony_ci#define DTCQ_HALFTONE_BW16 0x80 662141cc406Sopenharmony_ci#define DTCQ_HALFTONE_COLOR16 0x81 663141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY8 0x00 664141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED8 0x01 665141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN8 0x02 666141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE8 0x03 667141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY10 0x80 668141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED10 0x81 669141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN10 0x82 670141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE10 0x83 671141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY12 0x90 672141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED12 0x91 673141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN12 0x92 674141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE12 0x93 675141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY14 0x95 /* ? */ 676141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED14 0x96 677141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN14 0x97 678141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE14 0x98 679141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY12_16BIT 0xa0 680141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED12_16BIT 0xa1 681141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN12_16BIT 0xa2 682141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE12_16BIT 0xa3 683141cc406Sopenharmony_ci#define DTCQ_GAMMA_GRAY14_16BIT 0xa5 /* ? */ 684141cc406Sopenharmony_ci#define DTCQ_GAMMA_RED14_16BIT 0xa6 685141cc406Sopenharmony_ci#define DTCQ_GAMMA_GREEN14_16BIT 0xa7 686141cc406Sopenharmony_ci#define DTCQ_GAMMA_BLUE14_16BIT 0xa8 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_cistatic SANE_Status send (SnapScan_Scanner *pss, u_char dtc, u_char dtcq) 689141cc406Sopenharmony_ci{ 690141cc406Sopenharmony_ci static char me[] = "send"; 691141cc406Sopenharmony_ci SANE_Status status; 692141cc406Sopenharmony_ci u_short tl; /* transfer length */ 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci zero_buf (pss->buf, SEND_LENGTH); 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci switch (dtc) 699141cc406Sopenharmony_ci { 700141cc406Sopenharmony_ci case DTC_HALFTONE: /* halftone mask */ 701141cc406Sopenharmony_ci switch (dtcq) 702141cc406Sopenharmony_ci { 703141cc406Sopenharmony_ci case DTCQ_HALFTONE_BW8: 704141cc406Sopenharmony_ci tl = 64; /* bw 8x8 table */ 705141cc406Sopenharmony_ci break; 706141cc406Sopenharmony_ci case DTCQ_HALFTONE_COLOR8: 707141cc406Sopenharmony_ci tl = 3 * 64; /* rgb 8x8 tables */ 708141cc406Sopenharmony_ci break; 709141cc406Sopenharmony_ci case DTCQ_HALFTONE_BW16: 710141cc406Sopenharmony_ci tl = 256; /* bw 16x16 table */ 711141cc406Sopenharmony_ci break; 712141cc406Sopenharmony_ci case DTCQ_HALFTONE_COLOR16: 713141cc406Sopenharmony_ci tl = 3 * 256; /* rgb 16x16 tables */ 714141cc406Sopenharmony_ci break; 715141cc406Sopenharmony_ci default: 716141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: bad halftone data type qualifier 0x%x\n", 717141cc406Sopenharmony_ci me, dtcq); 718141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 719141cc406Sopenharmony_ci } 720141cc406Sopenharmony_ci break; 721141cc406Sopenharmony_ci case DTC_GAMMA: /* gamma function */ 722141cc406Sopenharmony_ci case DTC_GAMMA2: 723141cc406Sopenharmony_ci switch (dtcq) 724141cc406Sopenharmony_ci { 725141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY8: /* 8-bit tables */ 726141cc406Sopenharmony_ci case DTCQ_GAMMA_RED8: 727141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN8: 728141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE8: 729141cc406Sopenharmony_ci tl = 256; 730141cc406Sopenharmony_ci break; 731141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY10: /* 10-bit tables */ 732141cc406Sopenharmony_ci case DTCQ_GAMMA_RED10: 733141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN10: 734141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE10: 735141cc406Sopenharmony_ci tl = 1024; 736141cc406Sopenharmony_ci break; 737141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY12: /* 12-bit tables */ 738141cc406Sopenharmony_ci case DTCQ_GAMMA_RED12: 739141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN12: 740141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE12: 741141cc406Sopenharmony_ci tl = 4096; 742141cc406Sopenharmony_ci break; 743141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY12_16BIT: /* 12-bit tables with 16 bit data */ 744141cc406Sopenharmony_ci case DTCQ_GAMMA_RED12_16BIT: 745141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN12_16BIT: 746141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE12_16BIT: 747141cc406Sopenharmony_ci tl = 8192; 748141cc406Sopenharmony_ci break; 749141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY14: /* 14-bit tables */ 750141cc406Sopenharmony_ci case DTCQ_GAMMA_RED14: 751141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN14: 752141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE14: 753141cc406Sopenharmony_ci tl = 16384; 754141cc406Sopenharmony_ci break; 755141cc406Sopenharmony_ci case DTCQ_GAMMA_GRAY14_16BIT: /* 14-bit tables with 16 bit data */ 756141cc406Sopenharmony_ci case DTCQ_GAMMA_RED14_16BIT: 757141cc406Sopenharmony_ci case DTCQ_GAMMA_GREEN14_16BIT: 758141cc406Sopenharmony_ci case DTCQ_GAMMA_BLUE14_16BIT: 759141cc406Sopenharmony_ci tl = 32768; 760141cc406Sopenharmony_ci break; 761141cc406Sopenharmony_ci default: 762141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: bad gamma data type qualifier 0x%x\n", 763141cc406Sopenharmony_ci me, dtcq); 764141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci break; 767141cc406Sopenharmony_ci case DTC_SPEED: /* static transfer speed */ 768141cc406Sopenharmony_ci tl = 2; 769141cc406Sopenharmony_ci break; 770141cc406Sopenharmony_ci case DTC_CALIBRATION: 771141cc406Sopenharmony_ci tl = calibration_line_length(pss); 772141cc406Sopenharmony_ci break; 773141cc406Sopenharmony_ci default: 774141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: unsupported data type code 0x%x\n", 775141cc406Sopenharmony_ci me, (unsigned) dtc); 776141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 777141cc406Sopenharmony_ci } 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci pss->buf[0] = SEND; 780141cc406Sopenharmony_ci pss->buf[2] = dtc; 781141cc406Sopenharmony_ci pss->buf[5] = dtcq; 782141cc406Sopenharmony_ci pss->buf[7] = (tl >> 8) & 0xff; 783141cc406Sopenharmony_ci pss->buf[8] = tl & 0xff; 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->buf, SEND_LENGTH + tl, 786141cc406Sopenharmony_ci NULL, NULL); 787141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 788141cc406Sopenharmony_ci return status; 789141cc406Sopenharmony_ci} 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci#include "snapscan-data.c" 792141cc406Sopenharmony_cistatic SANE_Status send_calibration_5150(SnapScan_Scanner *pss) 793141cc406Sopenharmony_ci{ 794141cc406Sopenharmony_ci static const int length = sizeof(calibration_data_5150); 795141cc406Sopenharmony_ci SANE_Byte* buf = malloc (length + SEND_LENGTH); 796141cc406Sopenharmony_ci SANE_Status status; 797141cc406Sopenharmony_ci zero_buf (buf, SEND_LENGTH); 798141cc406Sopenharmony_ci *buf = SEND; 799141cc406Sopenharmony_ci *(buf + 2) = DTC_CALIBRATION; 800141cc406Sopenharmony_ci *(buf + 6) = (length >> 16) & 0xff; 801141cc406Sopenharmony_ci *(buf + 7) = (length >> 8) & 0xff; 802141cc406Sopenharmony_ci *(buf + 8) = length & 0xff; 803141cc406Sopenharmony_ci memcpy(buf + SEND_LENGTH, calibration_data_5150, length); 804141cc406Sopenharmony_ci status = snapscan_cmd ( 805141cc406Sopenharmony_ci pss->pdev->bus, pss->fd, buf, SEND_LENGTH + length, NULL, NULL); 806141cc406Sopenharmony_ci free (buf); 807141cc406Sopenharmony_ci return status; 808141cc406Sopenharmony_ci} 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci#define SET_WINDOW_LEN 10 811141cc406Sopenharmony_ci#define SET_WINDOW_HEADER 10 /* header starts */ 812141cc406Sopenharmony_ci#define SET_WINDOW_HEADER_LEN 8 813141cc406Sopenharmony_ci#define SET_WINDOW_DESC 18 /* window descriptor starts */ 814141cc406Sopenharmony_ci#define SET_WINDOW_DESC_LEN 48 815141cc406Sopenharmony_ci#define SET_WINDOW_TRANSFER_LEN 56 816141cc406Sopenharmony_ci#define SET_WINDOW_TOTAL_LEN 66 817141cc406Sopenharmony_ci#define SET_WINDOW_RET_LEN 0 /* no returned data */ 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci#define SET_WINDOW_P_TRANSFER_LEN 6 820141cc406Sopenharmony_ci#define SET_WINDOW_P_DESC_LEN 6 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci#define SET_WINDOW_P_WIN_ID 0 823141cc406Sopenharmony_ci#define SET_WINDOW_P_XRES 2 824141cc406Sopenharmony_ci#define SET_WINDOW_P_YRES 4 825141cc406Sopenharmony_ci#define SET_WINDOW_P_TLX 6 826141cc406Sopenharmony_ci#define SET_WINDOW_P_TLY 10 827141cc406Sopenharmony_ci#define SET_WINDOW_P_WIDTH 14 828141cc406Sopenharmony_ci#define SET_WINDOW_P_LENGTH 18 829141cc406Sopenharmony_ci#define SET_WINDOW_P_BRIGHTNESS 22 830141cc406Sopenharmony_ci#define SET_WINDOW_P_THRESHOLD 23 831141cc406Sopenharmony_ci#define SET_WINDOW_P_CONTRAST 24 832141cc406Sopenharmony_ci#define SET_WINDOW_P_COMPOSITION 25 833141cc406Sopenharmony_ci#define SET_WINDOW_P_BITS_PER_PIX 26 834141cc406Sopenharmony_ci#define SET_WINDOW_P_HALFTONE_PATTERN 27 835141cc406Sopenharmony_ci#define SET_WINDOW_P_PADDING_TYPE 29 836141cc406Sopenharmony_ci#define SET_WINDOW_P_BIT_ORDERING 30 837141cc406Sopenharmony_ci#define SET_WINDOW_P_COMPRESSION_TYPE 32 838141cc406Sopenharmony_ci#define SET_WINDOW_P_COMPRESSION_ARG 33 839141cc406Sopenharmony_ci#define SET_WINDOW_P_HALFTONE_FLAG 35 840141cc406Sopenharmony_ci#define SET_WINDOW_P_DEBUG_MODE 40 841141cc406Sopenharmony_ci#define SET_WINDOW_P_GAMMA_NO 41 842141cc406Sopenharmony_ci#define SET_WINDOW_P_OPERATION_MODE 42 843141cc406Sopenharmony_ci#define SET_WINDOW_P_RED_UNDER_COLOR 43 844141cc406Sopenharmony_ci#define SET_WINDOW_P_BLUE_UNDER_COLOR 45 845141cc406Sopenharmony_ci#define SET_WINDOW_P_GREEN_UNDER_COLOR 44 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_cistatic SANE_Status prepare_set_window (SnapScan_Scanner *pss) 848141cc406Sopenharmony_ci{ 849141cc406Sopenharmony_ci static const char *me = "prepare_set_window"; 850141cc406Sopenharmony_ci u_char *pc; 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 853141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 854141cc406Sopenharmony_ci 855141cc406Sopenharmony_ci /* basic command */ 856141cc406Sopenharmony_ci pc = pss->cmd; 857141cc406Sopenharmony_ci pc[0] = SET_WINDOW; 858141cc406Sopenharmony_ci u_int_to_u_char3p ((u_int) SET_WINDOW_TRANSFER_LEN, 859141cc406Sopenharmony_ci pc + SET_WINDOW_P_TRANSFER_LEN); 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci /* header; we support only one window */ 862141cc406Sopenharmony_ci pc += SET_WINDOW_LEN; 863141cc406Sopenharmony_ci u_short_to_u_charp (SET_WINDOW_DESC_LEN, pc + SET_WINDOW_P_DESC_LEN); 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci /* the sole window descriptor */ 866141cc406Sopenharmony_ci pc += SET_WINDOW_HEADER_LEN; 867141cc406Sopenharmony_ci pc[SET_WINDOW_P_WIN_ID] = 0; 868141cc406Sopenharmony_ci u_short_to_u_charp (pss->res, pc + SET_WINDOW_P_XRES); 869141cc406Sopenharmony_ci u_short_to_u_charp (pss->res, pc + SET_WINDOW_P_YRES); 870141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s Resolution: %d\n", me, pss->res); 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ci pc[SET_WINDOW_P_BRIGHTNESS] = 128; 873141cc406Sopenharmony_ci pc[SET_WINDOW_P_THRESHOLD] = 874141cc406Sopenharmony_ci (u_char) (255.0*(pss->threshold / 100.0)); 875141cc406Sopenharmony_ci pc[SET_WINDOW_P_CONTRAST] = 128; 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci { 878141cc406Sopenharmony_ci SnapScan_Mode mode = pss->mode; 879141cc406Sopenharmony_ci pss->bpp_scan = pss->val[OPT_BIT_DEPTH].w; 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci if (pss->preview) 882141cc406Sopenharmony_ci { 883141cc406Sopenharmony_ci mode = pss->preview_mode; 884141cc406Sopenharmony_ci if (pss->pdev->model != SCANWIT2720S) 885141cc406Sopenharmony_ci pss->bpp_scan = 8; 886141cc406Sopenharmony_ci } 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s Mode: %d\n", me, mode); 889141cc406Sopenharmony_ci switch (mode) 890141cc406Sopenharmony_ci { 891141cc406Sopenharmony_ci case MD_COLOUR: 892141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x05; /* multi-level RGB */ 893141cc406Sopenharmony_ci break; 894141cc406Sopenharmony_ci case MD_BILEVELCOLOUR: 895141cc406Sopenharmony_ci if (pss->halftone) 896141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x04; /* halftone RGB */ 897141cc406Sopenharmony_ci else 898141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x03; /* bi-level RGB */ 899141cc406Sopenharmony_ci pss->bpp_scan = 1; 900141cc406Sopenharmony_ci break; 901141cc406Sopenharmony_ci case MD_GREYSCALE: 902141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x02; /* grayscale */ 903141cc406Sopenharmony_ci break; 904141cc406Sopenharmony_ci case MD_LINEART: 905141cc406Sopenharmony_ci if (pss->halftone) 906141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x01; /* b&w halftone */ 907141cc406Sopenharmony_ci else 908141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPOSITION] = 0x00; /* b&w (lineart) */ 909141cc406Sopenharmony_ci pss->bpp_scan = 1; 910141cc406Sopenharmony_ci break; 911141cc406Sopenharmony_ci default: 912141cc406Sopenharmony_ci break; 913141cc406Sopenharmony_ci } 914141cc406Sopenharmony_ci 915141cc406Sopenharmony_ci pc[SET_WINDOW_P_BITS_PER_PIX] = pss->bpp_scan; 916141cc406Sopenharmony_ci DBG (DL_INFO, "%s: bits-per-pixel set to %d\n", me, (int) pss->bpp_scan); 917141cc406Sopenharmony_ci } 918141cc406Sopenharmony_ci /* the RIF bit is the high bit of the padding type */ 919141cc406Sopenharmony_ci pc[SET_WINDOW_P_PADDING_TYPE] = 0x00 /*| (pss->negative ? 0x00 : 0x80) */ ; 920141cc406Sopenharmony_ci pc[SET_WINDOW_P_HALFTONE_PATTERN] = 0; 921141cc406Sopenharmony_ci pc[SET_WINDOW_P_HALFTONE_FLAG] = 0x80; /* always set; image 922141cc406Sopenharmony_ci composition 923141cc406Sopenharmony_ci determines whether 924141cc406Sopenharmony_ci halftone is 925141cc406Sopenharmony_ci actually used */ 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci u_short_to_u_charp (0x0000, pc + SET_WINDOW_P_BIT_ORDERING); /* used? */ 928141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPRESSION_TYPE] = 0; /* none */ 929141cc406Sopenharmony_ci pc[SET_WINDOW_P_COMPRESSION_ARG] = 0; /* none applicable */ 930141cc406Sopenharmony_ci if(pss->pdev->model != ACER300F 931141cc406Sopenharmony_ci && 932141cc406Sopenharmony_ci pss->pdev->model != SNAPSCAN310 933141cc406Sopenharmony_ci && 934141cc406Sopenharmony_ci pss->pdev->model != PRISA310 935141cc406Sopenharmony_ci && 936141cc406Sopenharmony_ci pss->pdev->model != PRISA610 937141cc406Sopenharmony_ci ) { 938141cc406Sopenharmony_ci pc[SET_WINDOW_P_DEBUG_MODE] = 2; /* use full 128k buffer */ 939141cc406Sopenharmony_ci if (pss->mode != MD_LINEART) 940141cc406Sopenharmony_ci { 941141cc406Sopenharmony_ci pc[SET_WINDOW_P_GAMMA_NO] = 0x01; /* downloaded gamma table */ 942141cc406Sopenharmony_ci } 943141cc406Sopenharmony_ci } 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci pc[SET_WINDOW_P_RED_UNDER_COLOR] = 0xff; /* defaults */ 946141cc406Sopenharmony_ci pc[SET_WINDOW_P_BLUE_UNDER_COLOR] = 0xff; 947141cc406Sopenharmony_ci pc[SET_WINDOW_P_GREEN_UNDER_COLOR] = 0xff; 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 950141cc406Sopenharmony_ci} 951141cc406Sopenharmony_ci 952141cc406Sopenharmony_cistatic SANE_Status set_window (SnapScan_Scanner *pss) 953141cc406Sopenharmony_ci{ 954141cc406Sopenharmony_ci static const char *me = "set_window"; 955141cc406Sopenharmony_ci SANE_Status status; 956141cc406Sopenharmony_ci unsigned char source; 957141cc406Sopenharmony_ci u_char *pc; 958141cc406Sopenharmony_ci int pos_factor; 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 961141cc406Sopenharmony_ci status = prepare_set_window(pss); 962141cc406Sopenharmony_ci CHECK_STATUS (status, me, "prepare_set_window"); 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci pc = pss->cmd; 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci /* header; we support only one window */ 967141cc406Sopenharmony_ci pc += SET_WINDOW_LEN; 968141cc406Sopenharmony_ci 969141cc406Sopenharmony_ci /* the sole window descriptor */ 970141cc406Sopenharmony_ci pc += SET_WINDOW_HEADER_LEN; 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci switch (pss->pdev->model) 973141cc406Sopenharmony_ci { 974141cc406Sopenharmony_ci case PRISA5000: 975141cc406Sopenharmony_ci case PRISA5000E: 976141cc406Sopenharmony_ci case PRISA5150: 977141cc406Sopenharmony_ci pos_factor = (pss->res > 600) ? 1200 : 600; 978141cc406Sopenharmony_ci break; 979141cc406Sopenharmony_ci case PERFECTION1270: 980141cc406Sopenharmony_ci case PERFECTION1670: 981141cc406Sopenharmony_ci pos_factor = (pss->res > 800) ? 1600 : 800; 982141cc406Sopenharmony_ci break; 983141cc406Sopenharmony_ci case PERFECTION2480: 984141cc406Sopenharmony_ci pos_factor = (pss->res > 1200) ? 2400 : 1200; 985141cc406Sopenharmony_ci break; 986141cc406Sopenharmony_ci case PERFECTION3490: 987141cc406Sopenharmony_ci pos_factor = (pss->res > 1600) ? 3200 : 1600; 988141cc406Sopenharmony_ci break; 989141cc406Sopenharmony_ci default: 990141cc406Sopenharmony_ci pos_factor = pss->actual_res; 991141cc406Sopenharmony_ci break; 992141cc406Sopenharmony_ci } 993141cc406Sopenharmony_ci /* it's an ugly sound if the scanner drives against the rear 994141cc406Sopenharmony_ci wall, and with changing max values we better be sure */ 995141cc406Sopenharmony_ci check_range(&(pss->brx), pss->pdev->x_range); 996141cc406Sopenharmony_ci check_range(&(pss->bry), pss->pdev->y_range); 997141cc406Sopenharmony_ci { 998141cc406Sopenharmony_ci int tlxp = 999141cc406Sopenharmony_ci (int) (pos_factor*IN_PER_MM*SANE_UNFIX(pss->tlx)); 1000141cc406Sopenharmony_ci int tlyp = 1001141cc406Sopenharmony_ci (int) (pos_factor*IN_PER_MM*SANE_UNFIX(pss->tly)); 1002141cc406Sopenharmony_ci int brxp = 1003141cc406Sopenharmony_ci (int) (pos_factor*IN_PER_MM*SANE_UNFIX(pss->brx)); 1004141cc406Sopenharmony_ci int bryp = 1005141cc406Sopenharmony_ci (int) (pos_factor*IN_PER_MM*SANE_UNFIX(pss->bry)); 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci /* Check for brx > tlx and bry > tly */ 1008141cc406Sopenharmony_ci if (brxp <= tlxp) { 1009141cc406Sopenharmony_ci tlxp = MAX (0, brxp - 75); 1010141cc406Sopenharmony_ci } 1011141cc406Sopenharmony_ci if (bryp <= tlyp) { 1012141cc406Sopenharmony_ci tlyp = MAX (0, bryp - 75); 1013141cc406Sopenharmony_ci } 1014141cc406Sopenharmony_ci 1015141cc406Sopenharmony_ci u_int_to_u_char4p (tlxp, pc + SET_WINDOW_P_TLX); 1016141cc406Sopenharmony_ci u_int_to_u_char4p (tlyp, pc + SET_WINDOW_P_TLY); 1017141cc406Sopenharmony_ci u_int_to_u_char4p (MAX (((unsigned) (brxp - tlxp)), 75), 1018141cc406Sopenharmony_ci pc + SET_WINDOW_P_WIDTH); 1019141cc406Sopenharmony_ci u_int_to_u_char4p (MAX (((unsigned) (bryp - tlyp)), 75), 1020141cc406Sopenharmony_ci pc + SET_WINDOW_P_LENGTH); 1021141cc406Sopenharmony_ci DBG (DL_INFO, "%s Width: %d\n", me, brxp-tlxp); 1022141cc406Sopenharmony_ci DBG (DL_INFO, "%s Length: %d\n", me, bryp-tlyp); 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci 1025141cc406Sopenharmony_ci source = 0x0; 1026141cc406Sopenharmony_ci if (pss->preview) { 1027141cc406Sopenharmony_ci source |= 0x80; /* no high quality in preview */ 1028141cc406Sopenharmony_ci } 1029141cc406Sopenharmony_ci else { 1030141cc406Sopenharmony_ci source |= 0x40; /* no preview */ 1031141cc406Sopenharmony_ci } 1032141cc406Sopenharmony_ci if (!pss->highquality) { 1033141cc406Sopenharmony_ci source |= 0x80; /* no high quality */ 1034141cc406Sopenharmony_ci } 1035141cc406Sopenharmony_ci if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) { 1036141cc406Sopenharmony_ci source |= 0x40; /* 2480/3490 always need no_preview bit */ 1037141cc406Sopenharmony_ci } 1038141cc406Sopenharmony_ci if (pss->source == SRC_TPO) { 1039141cc406Sopenharmony_ci source |= 0x08; 1040141cc406Sopenharmony_ci } 1041141cc406Sopenharmony_ci if (pss->source == SRC_ADF) { 1042141cc406Sopenharmony_ci source |= 0x10; 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci pc[SET_WINDOW_P_OPERATION_MODE] = source; 1045141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: operation mode set to 0x%02x\n", me, (int) source); 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci do { 1048141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, 1049141cc406Sopenharmony_ci SET_WINDOW_TOTAL_LEN, NULL, NULL); 1050141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY) { 1051141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: waiting for scanner to warm up\n", me); 1052141cc406Sopenharmony_ci wait_scanner_ready (pss); 1053141cc406Sopenharmony_ci } 1054141cc406Sopenharmony_ci } while (status == SANE_STATUS_DEVICE_BUSY); 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1057141cc406Sopenharmony_ci return status; 1058141cc406Sopenharmony_ci} 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_cistatic SANE_Status set_window_autofocus (SnapScan_Scanner *copy) 1061141cc406Sopenharmony_ci{ 1062141cc406Sopenharmony_ci static char me[] = "set_window_autofocus"; 1063141cc406Sopenharmony_ci SANE_Status status; 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s(%p)\n", me, (void*)copy); 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci copy->res = copy->actual_res; 1068141cc406Sopenharmony_ci status = prepare_set_window (copy); 1069141cc406Sopenharmony_ci CHECK_STATUS (status, me, "prepare_set_window"); 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci u_int_to_u_char4p (1700, copy->cmd + SET_WINDOW_DESC + SET_WINDOW_P_TLY); 1072141cc406Sopenharmony_ci /* fill in width & height */ 1073141cc406Sopenharmony_ci u_int_to_u_char4p (2550, copy->cmd + SET_WINDOW_DESC + SET_WINDOW_P_WIDTH); 1074141cc406Sopenharmony_ci u_int_to_u_char4p (128, copy->cmd + SET_WINDOW_DESC + SET_WINDOW_P_LENGTH); 1075141cc406Sopenharmony_ci 1076141cc406Sopenharmony_ci copy->cmd[SET_WINDOW_DESC + SET_WINDOW_P_BITS_PER_PIX] = 12; 1077141cc406Sopenharmony_ci copy->cmd[SET_WINDOW_DESC + SET_WINDOW_P_OPERATION_MODE] = 0x49; /* focusing mode */ 1078141cc406Sopenharmony_ci return snapscan_cmd (copy->pdev->bus, copy->fd, copy->cmd, 1079141cc406Sopenharmony_ci SET_WINDOW_TOTAL_LEN, NULL, NULL); 1080141cc406Sopenharmony_ci} 1081141cc406Sopenharmony_ci 1082141cc406Sopenharmony_ci#define SET_FRAME_LEN 10 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_cistatic SANE_Status set_frame (SnapScan_Scanner *pss, SANE_Byte frame_no) 1085141cc406Sopenharmony_ci{ 1086141cc406Sopenharmony_ci static const char *me = "set_frame"; 1087141cc406Sopenharmony_ci SANE_Status status; 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1090141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s setting frame to %d\n", me, frame_no); 1091141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1092141cc406Sopenharmony_ci pss->cmd[0] = OBJECT_POSITION; 1093141cc406Sopenharmony_ci pss->cmd[1] = 2; /* Absolute position used here to select the frame */ 1094141cc406Sopenharmony_ci pss->cmd[4] = frame_no; 1095141cc406Sopenharmony_ci 1096141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, SET_FRAME_LEN, NULL, NULL); 1097141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci return status; 1100141cc406Sopenharmony_ci} 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_cistatic SANE_Status set_focus (SnapScan_Scanner *pss, SANE_Int focus) 1103141cc406Sopenharmony_ci{ 1104141cc406Sopenharmony_ci static const char *me = "set_focus"; 1105141cc406Sopenharmony_ci SANE_Status status; 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s(%d)\n", me, focus); 1108141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1109141cc406Sopenharmony_ci pss->cmd[0] = OBJECT_POSITION; 1110141cc406Sopenharmony_ci pss->cmd[1] = 4; /* Rotate object but here it sets the focus point */ 1111141cc406Sopenharmony_ci pss->cmd[3] = (focus >> 8) & 0xFF; 1112141cc406Sopenharmony_ci pss->cmd[4] = focus & 0xFF; 1113141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, SET_FRAME_LEN, NULL, NULL); 1114141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1115141cc406Sopenharmony_ci return status; 1116141cc406Sopenharmony_ci} 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_cistatic SANE_Int get_8 (u_char *p) 1119141cc406Sopenharmony_ci{ 1120141cc406Sopenharmony_ci SANE_Int b; 1121141cc406Sopenharmony_ci b = p[0] | (p[1] << 8); 1122141cc406Sopenharmony_ci return b; 1123141cc406Sopenharmony_ci} 1124141cc406Sopenharmony_ci 1125141cc406Sopenharmony_cistatic double get_val (u_char *p, SANE_Int len, SANE_Int x) 1126141cc406Sopenharmony_ci{ 1127141cc406Sopenharmony_ci return get_8 (p + ((x + len) << 1)) / 255.0; 1128141cc406Sopenharmony_ci} 1129141cc406Sopenharmony_ci 1130141cc406Sopenharmony_cistatic double sum_pixel_differences (u_char *p, int len) 1131141cc406Sopenharmony_ci{ 1132141cc406Sopenharmony_ci double v, m, s; 1133141cc406Sopenharmony_ci SANE_Int i; 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci s = 0; 1136141cc406Sopenharmony_ci for (i = 0; i < len-1; i++) { 1137141cc406Sopenharmony_ci v = get_val (p, len, i); 1138141cc406Sopenharmony_ci m = get_val (p, len, i+1); 1139141cc406Sopenharmony_ci s += fabs (v - m); 1140141cc406Sopenharmony_ci } 1141141cc406Sopenharmony_ci return s; 1142141cc406Sopenharmony_ci} 1143141cc406Sopenharmony_ci 1144141cc406Sopenharmony_cistatic SANE_Status scan (SnapScan_Scanner *pss) 1145141cc406Sopenharmony_ci{ 1146141cc406Sopenharmony_ci static const char *me = "scan"; 1147141cc406Sopenharmony_ci SANE_Status status; 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1150141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1151141cc406Sopenharmony_ci pss->cmd[0] = SCAN; 1152141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, SCAN_LEN, NULL, NULL); 1153141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1154141cc406Sopenharmony_ci return status; 1155141cc406Sopenharmony_ci} 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci/* supported read operations */ 1158141cc406Sopenharmony_ci 1159141cc406Sopenharmony_ci#define READ_IMAGE 0x00 1160141cc406Sopenharmony_ci#define READ_TRANSTIME 0x80 1161141cc406Sopenharmony_ci 1162141cc406Sopenharmony_ci/* number of bytes expected must be in pss->expected_read_bytes */ 1163141cc406Sopenharmony_cistatic SANE_Status scsi_read (SnapScan_Scanner *pss, u_char read_type) 1164141cc406Sopenharmony_ci{ 1165141cc406Sopenharmony_ci static const char *me = "scsi_read"; 1166141cc406Sopenharmony_ci SANE_Status status; 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1169141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1170141cc406Sopenharmony_ci pss->cmd[0] = READ; 1171141cc406Sopenharmony_ci pss->cmd[2] = read_type; 1172141cc406Sopenharmony_ci if (read_type == READ_TRANSTIME && pss->pdev->model == PERFECTION2480) 1173141cc406Sopenharmony_ci pss->cmd[5] = 1; 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ci u_int_to_u_char3p (pss->expected_read_bytes, pss->cmd + 6); 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci pss->read_bytes = pss->expected_read_bytes; 1178141cc406Sopenharmony_ci 1179141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, 1180141cc406Sopenharmony_ci READ_LEN, pss->buf, &pss->read_bytes); 1181141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1182141cc406Sopenharmony_ci return status; 1183141cc406Sopenharmony_ci} 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_cistatic SANE_Status get_focus (SnapScan_Scanner *pss) 1186141cc406Sopenharmony_ci{ 1187141cc406Sopenharmony_ci static const char *me = "get_focus"; 1188141cc406Sopenharmony_ci SANE_Int focus_point, max_focus_point; 1189141cc406Sopenharmony_ci double sum, max; 1190141cc406Sopenharmony_ci SANE_Status status; 1191141cc406Sopenharmony_ci SnapScan_Scanner copy; 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci copy = *pss; 1194141cc406Sopenharmony_ci 1195141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1196141cc406Sopenharmony_ci reserve_unit(©); 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci status = set_window_autofocus (©); 1199141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_window_autofocus"); 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci status = inquiry (©); 1202141cc406Sopenharmony_ci CHECK_STATUS (status, me, "inquiry"); 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci status = scan (©); 1205141cc406Sopenharmony_ci CHECK_STATUS (status, me, "scan"); 1206141cc406Sopenharmony_ci 1207141cc406Sopenharmony_ci status = set_frame (©, copy.frame_no); 1208141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_frame"); 1209141cc406Sopenharmony_ci 1210141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Expected number of bytes for each read %d\n", me, (int)copy.bytes_per_line); 1211141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Expected number of pixels per line %d\n", me, (int)copy.pixels_per_line); 1212141cc406Sopenharmony_ci max_focus_point = -1; 1213141cc406Sopenharmony_ci max = -1; 1214141cc406Sopenharmony_ci for (focus_point = 0; focus_point <= 0x300; focus_point += 6) { 1215141cc406Sopenharmony_ci status = set_focus (©, focus_point); 1216141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_focus"); 1217141cc406Sopenharmony_ci 1218141cc406Sopenharmony_ci copy.expected_read_bytes = copy.bytes_per_line; 1219141cc406Sopenharmony_ci status = scsi_read (©, READ_IMAGE); 1220141cc406Sopenharmony_ci CHECK_STATUS (status, me, "scsi_read"); 1221141cc406Sopenharmony_ci 1222141cc406Sopenharmony_ci sum = sum_pixel_differences (copy.buf, copy.pixels_per_line); 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci if (sum > max) { 1225141cc406Sopenharmony_ci max = sum; 1226141cc406Sopenharmony_ci max_focus_point = focus_point; 1227141cc406Sopenharmony_ci } 1228141cc406Sopenharmony_ci } 1229141cc406Sopenharmony_ci pss->focus = max_focus_point; 1230141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Focus point found to be at 0x%x\n", me, max_focus_point); 1231141cc406Sopenharmony_ci release_unit (©); 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci wait_scanner_ready (©); 1234141cc406Sopenharmony_ci CHECK_STATUS (status, me, "wait_scanner_ready"); 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci return status; 1237141cc406Sopenharmony_ci} 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci/* 1240141cc406Sopenharmony_cistatic SANE_Status request_sense (SnapScan_Scanner *pss) 1241141cc406Sopenharmony_ci{ 1242141cc406Sopenharmony_ci static const char *me = "request_sense"; 1243141cc406Sopenharmony_ci size_t read_bytes = 0; 1244141cc406Sopenharmony_ci u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, 20, 0}; 1245141cc406Sopenharmony_ci u_char data[20]; 1246141cc406Sopenharmony_ci SANE_Status status; 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci read_bytes = 20; 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1251141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, cmd, sizeof (cmd), 1252141cc406Sopenharmony_ci data, &read_bytes); 1253141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1254141cc406Sopenharmony_ci { 1255141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: scsi command error: %s\n", 1256141cc406Sopenharmony_ci me, sane_strstatus (status)); 1257141cc406Sopenharmony_ci } 1258141cc406Sopenharmony_ci else 1259141cc406Sopenharmony_ci { 1260141cc406Sopenharmony_ci status = sense_handler (pss->fd, data, (void *) pss); 1261141cc406Sopenharmony_ci } 1262141cc406Sopenharmony_ci return status; 1263141cc406Sopenharmony_ci} 1264141cc406Sopenharmony_ci*/ 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_cistatic SANE_Status send_diagnostic (SnapScan_Scanner *pss) 1267141cc406Sopenharmony_ci{ 1268141cc406Sopenharmony_ci static const char *me = "send_diagnostic"; 1269141cc406Sopenharmony_ci u_char cmd[] = {SEND_DIAGNOSTIC, 0x04, 0, 0, 0, 0}; /* self-test */ 1270141cc406Sopenharmony_ci SANE_Status status; 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_ci if (pss->pdev->model == PRISA620 1273141cc406Sopenharmony_ci || 1274141cc406Sopenharmony_ci pss->pdev->model == PRISA610 1275141cc406Sopenharmony_ci || 1276141cc406Sopenharmony_ci pss->pdev->model == SNAPSCAN1236 1277141cc406Sopenharmony_ci || 1278141cc406Sopenharmony_ci pss->pdev->model == SCANWIT2720S 1279141cc406Sopenharmony_ci || 1280141cc406Sopenharmony_ci pss->pdev->model == ARCUS1200) 1281141cc406Sopenharmony_ci { 1282141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1283141cc406Sopenharmony_ci } 1284141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, cmd, sizeof (cmd), NULL, NULL); 1287141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1288141cc406Sopenharmony_ci return status; 1289141cc406Sopenharmony_ci} 1290141cc406Sopenharmony_ci 1291141cc406Sopenharmony_cistatic SANE_Status wait_scanner_ready (SnapScan_Scanner *pss) 1292141cc406Sopenharmony_ci{ 1293141cc406Sopenharmony_ci static char me[] = "wait_scanner_ready"; 1294141cc406Sopenharmony_ci SANE_Status status; 1295141cc406Sopenharmony_ci int retries; 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci /* if the tray is returning to the start position 1300141cc406Sopenharmony_ci no time to wait is returned by the scanner. We'll 1301141cc406Sopenharmony_ci try several times and sleep 1 second between each try. */ 1302141cc406Sopenharmony_ci for (retries = 20; retries; retries--) 1303141cc406Sopenharmony_ci { 1304141cc406Sopenharmony_ci status = test_unit_ready (pss); 1305141cc406Sopenharmony_ci switch (status) 1306141cc406Sopenharmony_ci { 1307141cc406Sopenharmony_ci case SANE_STATUS_GOOD: 1308141cc406Sopenharmony_ci return status; 1309141cc406Sopenharmony_ci case SANE_STATUS_DEVICE_BUSY: 1310141cc406Sopenharmony_ci /* first additional sense byte contains time to wait */ 1311141cc406Sopenharmony_ci { 1312141cc406Sopenharmony_ci int delay = pss->asi1; 1313141cc406Sopenharmony_ci if (delay > 0) 1314141cc406Sopenharmony_ci { 1315141cc406Sopenharmony_ci DBG (0, 1316141cc406Sopenharmony_ci "Scanner warming up - waiting %d seconds.\n", 1317141cc406Sopenharmony_ci delay); 1318141cc406Sopenharmony_ci sleep (delay); 1319141cc406Sopenharmony_ci } 1320141cc406Sopenharmony_ci else 1321141cc406Sopenharmony_ci { 1322141cc406Sopenharmony_ci /* This seems to happen for Epson scanners. Return 1323141cc406Sopenharmony_ci SANE_STATUS_GOOD and hope the scanner accepts the 1324141cc406Sopenharmony_ci next command... */ 1325141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s: No timeout specified, returning immediately\n", me); 1326141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1327141cc406Sopenharmony_ci } 1328141cc406Sopenharmony_ci } 1329141cc406Sopenharmony_ci break; 1330141cc406Sopenharmony_ci case SANE_STATUS_IO_ERROR: 1331141cc406Sopenharmony_ci /* hardware error; bail */ 1332141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: hardware error detected.\n", me); 1333141cc406Sopenharmony_ci return status; 1334141cc406Sopenharmony_ci case SANE_STATUS_JAMMED: 1335141cc406Sopenharmony_ci case SANE_STATUS_NO_DOCS: 1336141cc406Sopenharmony_ci return status; 1337141cc406Sopenharmony_ci default: 1338141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1339141cc406Sopenharmony_ci "%s: unhandled request_sense result; trying again.\n", 1340141cc406Sopenharmony_ci me); 1341141cc406Sopenharmony_ci break; 1342141cc406Sopenharmony_ci } 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci return status; 1346141cc406Sopenharmony_ci} 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_ci#define READ_CALIBRATION 0x82 1349141cc406Sopenharmony_ci#define READ_CALIBRATION_BLACK 0x89 1350141cc406Sopenharmony_ci#define NUM_CALIBRATION_LINES 16 1351141cc406Sopenharmony_ci#define NUM_CALIBRATION_LINES_EPSON 48 1352141cc406Sopenharmony_ci#define NUM_CALIBRATION_LINES_EPSON_BLACK 128 1353141cc406Sopenharmony_ci 1354141cc406Sopenharmony_cistatic SANE_Status calibrate_epson (SnapScan_Scanner *pss) 1355141cc406Sopenharmony_ci{ 1356141cc406Sopenharmony_ci u_char *buf, *pbuf; 1357141cc406Sopenharmony_ci int *bins; 1358141cc406Sopenharmony_ci static const char *me = "calibrate_epson"; 1359141cc406Sopenharmony_ci /* pixels_per_line = 8.5 inch * resolution of one sensor */ 1360141cc406Sopenharmony_ci int pixels_per_line = pss->actual_res * 17/4; 1361141cc406Sopenharmony_ci int num_bins = pixels_per_line; 1362141cc406Sopenharmony_ci int i, j, k, loop_inc, tl; 1363141cc406Sopenharmony_ci int r, g, b; 1364141cc406Sopenharmony_ci size_t expected_read_bytes; 1365141cc406Sopenharmony_ci size_t read_bytes; 1366141cc406Sopenharmony_ci SANE_Status status; 1367141cc406Sopenharmony_ci int pass; 1368141cc406Sopenharmony_ci int cal_lines = NUM_CALIBRATION_LINES_EPSON; 1369141cc406Sopenharmony_ci int dtc = READ_CALIBRATION; 1370141cc406Sopenharmony_ci int bytes_per_bin = 1; 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci /* in 16 bit mode we get two bytes of cal data per bin */ 1373141cc406Sopenharmony_ci if (pss->bpp_scan == 16) 1374141cc406Sopenharmony_ci bytes_per_bin = 2; 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_ci /* calculate number of bins depending on mode and resolution 1377141cc406Sopenharmony_ci * colour mode requires bins for each of rgb 1378141cc406Sopenharmony_ci * full resolution doubles it because of second sensor line */ 1379141cc406Sopenharmony_ci if (is_colour_mode(actual_mode(pss))) { 1380141cc406Sopenharmony_ci num_bins *= 3; 1381141cc406Sopenharmony_ci } 1382141cc406Sopenharmony_ci if (pss->res >= (SANE_Int)pss->actual_res) { 1383141cc406Sopenharmony_ci num_bins *= 2; 1384141cc406Sopenharmony_ci } 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci /* allocate memory for bins, all the red, then green, then blue */ 1387141cc406Sopenharmony_ci bins = (int *) malloc (num_bins * sizeof (int)); 1388141cc406Sopenharmony_ci if (!bins) { 1389141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: out of memory allocating bins, %ld bytes.", me, (u_long)num_bins * sizeof (int)); 1390141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1391141cc406Sopenharmony_ci } 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci /* allocate buffer for receive data */ 1394141cc406Sopenharmony_ci expected_read_bytes = pixels_per_line * 3 * 4; 1395141cc406Sopenharmony_ci buf = (u_char *) malloc (expected_read_bytes); 1396141cc406Sopenharmony_ci if (!buf) { 1397141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: out of memory allocating calibration, %ld bytes.", me, (u_long)expected_read_bytes); 1398141cc406Sopenharmony_ci free (bins); 1399141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1400141cc406Sopenharmony_ci } 1401141cc406Sopenharmony_ci 1402141cc406Sopenharmony_ci loop_inc = expected_read_bytes / (num_bins * bytes_per_bin); 1403141cc406Sopenharmony_ci 1404141cc406Sopenharmony_ci /* do two passes, first pass does basic calibration, second does transparency adaptor if in use */ 1405141cc406Sopenharmony_ci for (pass = 0; pass < 2; pass++) { 1406141cc406Sopenharmony_ci if (pass == 1) { 1407141cc406Sopenharmony_ci if (pss->source == SRC_TPO) { 1408141cc406Sopenharmony_ci /* pass 1 is for black level calibration of transparency adaptor */ 1409141cc406Sopenharmony_ci cal_lines = NUM_CALIBRATION_LINES_EPSON_BLACK; 1410141cc406Sopenharmony_ci dtc = READ_CALIBRATION_BLACK; 1411141cc406Sopenharmony_ci } else 1412141cc406Sopenharmony_ci continue; 1413141cc406Sopenharmony_ci } 1414141cc406Sopenharmony_ci 1415141cc406Sopenharmony_ci /* empty the bins */ 1416141cc406Sopenharmony_ci for (i = 0; i < num_bins; i++) 1417141cc406Sopenharmony_ci bins[i] = 0; 1418141cc406Sopenharmony_ci 1419141cc406Sopenharmony_ci for (i = 0; i < cal_lines; i += loop_inc) { 1420141cc406Sopenharmony_ci /* get the calibration data */ 1421141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1422141cc406Sopenharmony_ci pss->cmd[0] = READ; 1423141cc406Sopenharmony_ci pss->cmd[2] = dtc; 1424141cc406Sopenharmony_ci pss->cmd[5] = cal_lines; 1425141cc406Sopenharmony_ci if (cal_lines - i > loop_inc) 1426141cc406Sopenharmony_ci expected_read_bytes = loop_inc * (num_bins * bytes_per_bin); 1427141cc406Sopenharmony_ci else 1428141cc406Sopenharmony_ci expected_read_bytes = (cal_lines - i) * (num_bins * bytes_per_bin); 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci u_int_to_u_char3p (expected_read_bytes, pss->cmd + 6); 1431141cc406Sopenharmony_ci read_bytes = expected_read_bytes; 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, 1434141cc406Sopenharmony_ci READ_LEN, buf, &read_bytes); 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1437141cc406Sopenharmony_ci DBG(DL_MAJOR_ERROR, "%s: %s command failed: %s\n", me, "read_cal_2480", sane_strstatus(status)); 1438141cc406Sopenharmony_ci free (bins); 1439141cc406Sopenharmony_ci free (buf); 1440141cc406Sopenharmony_ci return status; 1441141cc406Sopenharmony_ci } 1442141cc406Sopenharmony_ci 1443141cc406Sopenharmony_ci if (read_bytes != expected_read_bytes) { 1444141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: read %lu of %lu calibration data\n", me, (u_long) read_bytes, (u_long) expected_read_bytes); 1445141cc406Sopenharmony_ci free (bins); 1446141cc406Sopenharmony_ci free (buf); 1447141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1448141cc406Sopenharmony_ci } 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci /* add calibration results into bins */ 1451141cc406Sopenharmony_ci pbuf = buf; 1452141cc406Sopenharmony_ci for (j = 0; j < (int)expected_read_bytes / (num_bins * bytes_per_bin); j++) { 1453141cc406Sopenharmony_ci for (k = 0; k < num_bins; k++) { 1454141cc406Sopenharmony_ci bins[k] += *pbuf++; 1455141cc406Sopenharmony_ci /* add in second byte for 16bit mode */ 1456141cc406Sopenharmony_ci if (bytes_per_bin == 2) { 1457141cc406Sopenharmony_ci bins[k] += *pbuf++ * 256; 1458141cc406Sopenharmony_ci } 1459141cc406Sopenharmony_ci } 1460141cc406Sopenharmony_ci } 1461141cc406Sopenharmony_ci } 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci /* now make averages */ 1464141cc406Sopenharmony_ci for (k = 0; k < num_bins; k++) { 1465141cc406Sopenharmony_ci bins[k] /= cal_lines; 1466141cc406Sopenharmony_ci /* also divide by 64 for 16bit mode */ 1467141cc406Sopenharmony_ci if (bytes_per_bin == 2) 1468141cc406Sopenharmony_ci bins[k] /= 64; 1469141cc406Sopenharmony_ci } 1470141cc406Sopenharmony_ci /* now fill up result buffer */ 1471141cc406Sopenharmony_ci r = g = b = 0; 1472141cc406Sopenharmony_ci 1473141cc406Sopenharmony_ci /* create data to send back: start with r g b values, and follow with differences 1474141cc406Sopenharmony_ci * to previous value */ 1475141cc406Sopenharmony_ci pbuf = pss->buf + SEND_LENGTH; 1476141cc406Sopenharmony_ci if (is_colour_mode(actual_mode(pss))) { 1477141cc406Sopenharmony_ci for (k = 0; k < num_bins / 3; k++) { 1478141cc406Sopenharmony_ci *pbuf++ = bins[k] - r; 1479141cc406Sopenharmony_ci r = bins[k]; 1480141cc406Sopenharmony_ci *pbuf++ = bins[k + num_bins/3] - g; 1481141cc406Sopenharmony_ci g = bins[k + num_bins/3]; 1482141cc406Sopenharmony_ci *pbuf++ = bins[k + 2*num_bins/3] - b; 1483141cc406Sopenharmony_ci b = bins[k + 2*num_bins/3]; 1484141cc406Sopenharmony_ci } 1485141cc406Sopenharmony_ci } else { 1486141cc406Sopenharmony_ci for (k = 0; k < num_bins; k++) { 1487141cc406Sopenharmony_ci *pbuf++ = bins[k] - g; 1488141cc406Sopenharmony_ci g = bins[k]; 1489141cc406Sopenharmony_ci } 1490141cc406Sopenharmony_ci } 1491141cc406Sopenharmony_ci 1492141cc406Sopenharmony_ci /* send back the calibration data; round up transfer length (to match windows driver) */ 1493141cc406Sopenharmony_ci zero_buf (pss->buf, SEND_LENGTH); 1494141cc406Sopenharmony_ci pss->buf[0] = SEND; 1495141cc406Sopenharmony_ci pss->buf[2] = dtc; 1496141cc406Sopenharmony_ci tl = (num_bins + 0xff) & ~0xff; 1497141cc406Sopenharmony_ci u_int_to_u_char3p (tl, pss->buf + 6); 1498141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->buf, SEND_LENGTH + tl, 1499141cc406Sopenharmony_ci NULL, NULL); 1500141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1501141cc406Sopenharmony_ci DBG(DL_MAJOR_ERROR, "%s: %s command failed: %s\n", me, "send_cal_2480", sane_strstatus(status)); 1502141cc406Sopenharmony_ci free (bins); 1503141cc406Sopenharmony_ci free (buf); 1504141cc406Sopenharmony_ci return status; 1505141cc406Sopenharmony_ci } 1506141cc406Sopenharmony_ci } 1507141cc406Sopenharmony_ci 1508141cc406Sopenharmony_ci free (bins); 1509141cc406Sopenharmony_ci free (buf); 1510141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1511141cc406Sopenharmony_ci} 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_cistatic SANE_Status read_calibration_data (SnapScan_Scanner *pss, void *buf, u_char num_lines) 1514141cc406Sopenharmony_ci{ 1515141cc406Sopenharmony_ci static const char *me = "read_calibration_data"; 1516141cc406Sopenharmony_ci SANE_Status status; 1517141cc406Sopenharmony_ci size_t expected_read_bytes = num_lines * calibration_line_length(pss); 1518141cc406Sopenharmony_ci size_t read_bytes; 1519141cc406Sopenharmony_ci 1520141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1521141cc406Sopenharmony_ci zero_buf (pss->cmd, MAX_SCSI_CMD_LEN); 1522141cc406Sopenharmony_ci pss->cmd[0] = READ; 1523141cc406Sopenharmony_ci pss->cmd[2] = READ_CALIBRATION; 1524141cc406Sopenharmony_ci pss->cmd[5] = num_lines; 1525141cc406Sopenharmony_ci u_int_to_u_char3p (expected_read_bytes, pss->cmd + 6); 1526141cc406Sopenharmony_ci read_bytes = expected_read_bytes; 1527141cc406Sopenharmony_ci 1528141cc406Sopenharmony_ci status = snapscan_cmd (pss->pdev->bus, pss->fd, pss->cmd, 1529141cc406Sopenharmony_ci READ_LEN, buf, &read_bytes); 1530141cc406Sopenharmony_ci CHECK_STATUS (status, me, "snapscan_cmd"); 1531141cc406Sopenharmony_ci 1532141cc406Sopenharmony_ci if(read_bytes != expected_read_bytes) { 1533141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: read %lu of %lu calibration data\n", me, (u_long) read_bytes, (u_long) expected_read_bytes); 1534141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1535141cc406Sopenharmony_ci } 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1538141cc406Sopenharmony_ci} 1539141cc406Sopenharmony_ci 1540141cc406Sopenharmony_cistatic SANE_Status calibrate (SnapScan_Scanner *pss) 1541141cc406Sopenharmony_ci{ 1542141cc406Sopenharmony_ci int r; 1543141cc406Sopenharmony_ci int c; 1544141cc406Sopenharmony_ci u_char *buf; 1545141cc406Sopenharmony_ci static const char *me = "calibrate"; 1546141cc406Sopenharmony_ci SANE_Status status; 1547141cc406Sopenharmony_ci int line_length = calibration_line_length(pss); 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci if ((pss->pdev->model == PERFECTION2480) || 1550141cc406Sopenharmony_ci (pss->pdev->model == PERFECTION3490)) { 1551141cc406Sopenharmony_ci return calibrate_epson (pss); 1552141cc406Sopenharmony_ci } 1553141cc406Sopenharmony_ci 1554141cc406Sopenharmony_ci if (pss->pdev->model == PRISA5150) 1555141cc406Sopenharmony_ci { 1556141cc406Sopenharmony_ci return send_calibration_5150(pss); 1557141cc406Sopenharmony_ci } 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci if (line_length) { 1562141cc406Sopenharmony_ci int num_lines = pss->phys_buf_sz / line_length; 1563141cc406Sopenharmony_ci if (num_lines > NUM_CALIBRATION_LINES) 1564141cc406Sopenharmony_ci { 1565141cc406Sopenharmony_ci num_lines = NUM_CALIBRATION_LINES; 1566141cc406Sopenharmony_ci } else if (num_lines == 0) 1567141cc406Sopenharmony_ci { 1568141cc406Sopenharmony_ci DBG(DL_MAJOR_ERROR, "%s: scsi request size underflow (< %d bytes)", me, line_length); 1569141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci buf = (u_char *) malloc(num_lines * line_length); 1572141cc406Sopenharmony_ci if (!buf) 1573141cc406Sopenharmony_ci { 1574141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: out of memory allocating calibration, %d bytes.", me, num_lines * line_length); 1575141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1576141cc406Sopenharmony_ci } 1577141cc406Sopenharmony_ci 1578141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: reading calibration data (%d lines)\n", me, num_lines); 1579141cc406Sopenharmony_ci status = read_calibration_data(pss, buf, num_lines); 1580141cc406Sopenharmony_ci CHECK_STATUS(status, me, "read_calibration_data"); 1581141cc406Sopenharmony_ci 1582141cc406Sopenharmony_ci for(c=0; c < line_length; c++) { 1583141cc406Sopenharmony_ci u_int sum = 0; 1584141cc406Sopenharmony_ci for(r=0; r < num_lines; r++) { 1585141cc406Sopenharmony_ci sum += buf[c + r * line_length]; 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci pss->buf[c + SEND_LENGTH] = sum / num_lines; 1588141cc406Sopenharmony_ci } 1589141cc406Sopenharmony_ci 1590141cc406Sopenharmony_ci status = send (pss, DTC_CALIBRATION, 1); 1591141cc406Sopenharmony_ci CHECK_STATUS(status, me, "send calibration"); 1592141cc406Sopenharmony_ci free(buf); 1593141cc406Sopenharmony_ci } 1594141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1595141cc406Sopenharmony_ci} 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_cistatic SANE_Status download_firmware(SnapScan_Scanner * pss) 1598141cc406Sopenharmony_ci{ 1599141cc406Sopenharmony_ci static const char *me = "download_firmware"; 1600141cc406Sopenharmony_ci unsigned char *pFwBuf, *pCDB; 1601141cc406Sopenharmony_ci char* firmware = NULL; 1602141cc406Sopenharmony_ci FILE *fd; 1603141cc406Sopenharmony_ci size_t bufLength,cdbLength; 1604141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1605141cc406Sopenharmony_ci char cModelName[8], cModel[255]; 1606141cc406Sopenharmony_ci unsigned char bModelNo; 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci bModelNo =*(pss->buf + INQUIRY_HWMI); 1609141cc406Sopenharmony_ci zero_buf((unsigned char *)cModel, 255); 1610141cc406Sopenharmony_ci sprintf(cModelName, "%d", bModelNo); 1611141cc406Sopenharmony_ci DBG(DL_INFO, "Looking up %s\n", cModelName); 1612141cc406Sopenharmony_ci if (pss->pdev->firmware_filename) { 1613141cc406Sopenharmony_ci firmware = pss->pdev->firmware_filename; 1614141cc406Sopenharmony_ci } else if (default_firmware_filename) { 1615141cc406Sopenharmony_ci firmware = default_firmware_filename; 1616141cc406Sopenharmony_ci } else { 1617141cc406Sopenharmony_ci DBG (0, 1618141cc406Sopenharmony_ci "%s: No firmware entry found in config file %s.\n", 1619141cc406Sopenharmony_ci me, 1620141cc406Sopenharmony_ci SNAPSCAN_CONFIG_FILE 1621141cc406Sopenharmony_ci ); 1622141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1623141cc406Sopenharmony_ci } 1624141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1625141cc406Sopenharmony_ci { 1626141cc406Sopenharmony_ci cdbLength = 10; 1627141cc406Sopenharmony_ci DBG(DL_INFO, "Downloading %s\n", firmware); 1628141cc406Sopenharmony_ci fd = fopen(firmware,"rb"); 1629141cc406Sopenharmony_ci if(fd == NULL) 1630141cc406Sopenharmony_ci { 1631141cc406Sopenharmony_ci DBG (0, "Cannot open firmware file %s.\n", firmware); 1632141cc406Sopenharmony_ci DBG (0, "Edit the firmware file entry in %s.\n", SNAPSCAN_CONFIG_FILE); 1633141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1634141cc406Sopenharmony_ci } 1635141cc406Sopenharmony_ci else 1636141cc406Sopenharmony_ci { 1637141cc406Sopenharmony_ci switch (pss->pdev->model) 1638141cc406Sopenharmony_ci { 1639141cc406Sopenharmony_ci case PRISA610: 1640141cc406Sopenharmony_ci case PRISA310: 1641141cc406Sopenharmony_ci case PRISA620: 1642141cc406Sopenharmony_ci case PRISA1240: 1643141cc406Sopenharmony_ci case PRISA640: 1644141cc406Sopenharmony_ci case PRISA4300: 1645141cc406Sopenharmony_ci case PRISA4300_2: 1646141cc406Sopenharmony_ci case PRISA5000: 1647141cc406Sopenharmony_ci case PRISA5000E: 1648141cc406Sopenharmony_ci case PRISA5150: 1649141cc406Sopenharmony_ci case PRISA5300: 1650141cc406Sopenharmony_ci case STYLUS_CX1500: 1651141cc406Sopenharmony_ci /* ACER firmware files do not contain an info block */ 1652141cc406Sopenharmony_ci fseek(fd, 0, SEEK_END); 1653141cc406Sopenharmony_ci bufLength = ftell(fd); 1654141cc406Sopenharmony_ci fseek(fd, 0, SEEK_SET); 1655141cc406Sopenharmony_ci break; 1656141cc406Sopenharmony_ci case PERFECTION1270: 1657141cc406Sopenharmony_ci case PERFECTION1670: 1658141cc406Sopenharmony_ci case PERFECTION2480: 1659141cc406Sopenharmony_ci case PERFECTION3490: 1660141cc406Sopenharmony_ci /* Epson firmware files contain an info block which 1661141cc406Sopenharmony_ci specifies the length of the firmware data. The 1662141cc406Sopenharmony_ci length information is stored at offset 0x64 from 1663141cc406Sopenharmony_ci end of file */ 1664141cc406Sopenharmony_ci { 1665141cc406Sopenharmony_ci unsigned char size_l, size_h; 1666141cc406Sopenharmony_ci fseek(fd, -0x64, SEEK_END); 1667141cc406Sopenharmony_ci fread(&size_l, 1, 1, fd); 1668141cc406Sopenharmony_ci fread(&size_h, 1, 1, fd); 1669141cc406Sopenharmony_ci fseek(fd, 0, SEEK_SET); 1670141cc406Sopenharmony_ci bufLength = (size_h << 8) + size_l; 1671141cc406Sopenharmony_ci } 1672141cc406Sopenharmony_ci break; 1673141cc406Sopenharmony_ci default: 1674141cc406Sopenharmony_ci /* AGFA firmware files contain an info block which 1675141cc406Sopenharmony_ci specifies the length of the firmware data. The 1676141cc406Sopenharmony_ci length information is stored at offset 0x5e from 1677141cc406Sopenharmony_ci end of file */ 1678141cc406Sopenharmony_ci { 1679141cc406Sopenharmony_ci unsigned char size_l, size_h; 1680141cc406Sopenharmony_ci fseek(fd, -0x5e, SEEK_END); 1681141cc406Sopenharmony_ci fread(&size_l, 1, 1, fd); 1682141cc406Sopenharmony_ci fread(&size_h, 1, 1, fd); 1683141cc406Sopenharmony_ci fseek(fd, 0, SEEK_SET); 1684141cc406Sopenharmony_ci bufLength = (size_h << 8) + size_l; 1685141cc406Sopenharmony_ci } 1686141cc406Sopenharmony_ci break; 1687141cc406Sopenharmony_ci } 1688141cc406Sopenharmony_ci 1689141cc406Sopenharmony_ci DBG(DL_INFO, "Size of firmware: %lu\n", (u_long) bufLength); 1690141cc406Sopenharmony_ci pCDB = (unsigned char *)malloc(bufLength + cdbLength); 1691141cc406Sopenharmony_ci pFwBuf = pCDB + cdbLength; 1692141cc406Sopenharmony_ci zero_buf (pCDB, cdbLength); 1693141cc406Sopenharmony_ci (void)fread(pFwBuf,1,bufLength,fd); 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci *pCDB = SEND; 1696141cc406Sopenharmony_ci *(pCDB + 2) = 0x87; 1697141cc406Sopenharmony_ci *(pCDB + 6) = (bufLength >> 16) & 0xff; 1698141cc406Sopenharmony_ci *(pCDB + 7) = (bufLength >> 8) & 0xff; 1699141cc406Sopenharmony_ci *(pCDB + 8) = bufLength & 0xff; 1700141cc406Sopenharmony_ci 1701141cc406Sopenharmony_ci status = snapscan_cmd ( 1702141cc406Sopenharmony_ci pss->pdev->bus, pss->fd, pCDB, bufLength+cdbLength, NULL, NULL); 1703141cc406Sopenharmony_ci pss->firmware_loaded = SANE_TRUE; 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci free(pCDB); 1706141cc406Sopenharmony_ci fclose(fd); 1707141cc406Sopenharmony_ci } 1708141cc406Sopenharmony_ci } 1709141cc406Sopenharmony_ci return status; 1710141cc406Sopenharmony_ci} 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci/* 1713141cc406Sopenharmony_ci * Revision 1.58 2006/09/03 10:00:11 oliver-guest 1714141cc406Sopenharmony_ci * Bugfix for firmware download by Paul Smedley 1715141cc406Sopenharmony_ci * 1716141cc406Sopenharmony_ci * Revision 1.57 2006/03/20 18:20:10 oliver-guest 1717141cc406Sopenharmony_ci * Limit inquiry length to 120 bytes if firmware is not yet loaded 1718141cc406Sopenharmony_ci * 1719141cc406Sopenharmony_ci * Revision 1.56 2006/01/10 19:32:16 oliver-guest 1720141cc406Sopenharmony_ci * Added 12 bit gamma tables for Epson Stylus CX-1500 1721141cc406Sopenharmony_ci * 1722141cc406Sopenharmony_ci * Revision 1.55 2006/01/06 20:59:17 oliver-guest 1723141cc406Sopenharmony_ci * Some fixes for the Epson Stylus CX 1500 1724141cc406Sopenharmony_ci * 1725141cc406Sopenharmony_ci * Revision 1.54 2006/01/01 22:57:01 oliver-guest 1726141cc406Sopenharmony_ci * Added calibration data for Benq 5150 / 5250, preliminary support for Epson Stylus CX 1500 1727141cc406Sopenharmony_ci * 1728141cc406Sopenharmony_ci * Revision 1.53 2005/12/05 20:38:22 oliver-guest 1729141cc406Sopenharmony_ci * Small bugfix for Benq 5150 1730141cc406Sopenharmony_ci * 1731141cc406Sopenharmony_ci * Revision 1.52 2005/12/04 15:03:00 oliver-guest 1732141cc406Sopenharmony_ci * Some fixes for Benq 5150 1733141cc406Sopenharmony_ci * 1734141cc406Sopenharmony_ci * Revision 1.51 2005/11/26 18:53:03 oliver-guest 1735141cc406Sopenharmony_ci * Fix inquiry bug for Benq 5000 1736141cc406Sopenharmony_ci * 1737141cc406Sopenharmony_ci * Revision 1.50 2005/11/17 23:47:10 oliver-guest 1738141cc406Sopenharmony_ci * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead 1739141cc406Sopenharmony_ci * 1740141cc406Sopenharmony_ci * Revision 1.49 2005/11/17 23:32:22 oliver-guest 1741141cc406Sopenharmony_ci * Fixes for Epson 3490 @ 2400 DPI 1742141cc406Sopenharmony_ci * 1743141cc406Sopenharmony_ci * Revision 1.48 2005/11/15 20:11:19 oliver-guest 1744141cc406Sopenharmony_ci * Enabled quality calibration for the Epson 3490 1745141cc406Sopenharmony_ci * 1746141cc406Sopenharmony_ci * Revision 1.47 2005/11/02 19:22:06 oliver-guest 1747141cc406Sopenharmony_ci * Fixes for Benq 5000 1748141cc406Sopenharmony_ci * 1749141cc406Sopenharmony_ci * Revision 1.46 2005/10/31 21:08:47 oliver-guest 1750141cc406Sopenharmony_ci * Distinguish between Benq 5000/5000E/5000U 1751141cc406Sopenharmony_ci * 1752141cc406Sopenharmony_ci * Revision 1.45 2005/10/24 19:46:40 oliver-guest 1753141cc406Sopenharmony_ci * Preview and range fix for Epson 2480/2580 1754141cc406Sopenharmony_ci * 1755141cc406Sopenharmony_ci * Revision 1.44 2005/10/23 21:28:58 oliver-guest 1756141cc406Sopenharmony_ci * Fix for buffer size in high res modes, fixes for delay code 1757141cc406Sopenharmony_ci * 1758141cc406Sopenharmony_ci * Revision 1.43 2005/10/20 21:23:53 oliver-guest 1759141cc406Sopenharmony_ci * Fixes for 16 bit quality calibration by Simon Munton 1760141cc406Sopenharmony_ci * 1761141cc406Sopenharmony_ci * Revision 1.42 2005/10/13 22:43:30 oliver-guest 1762141cc406Sopenharmony_ci * Fixes for 16 bit scan mode from Simon Munton 1763141cc406Sopenharmony_ci * 1764141cc406Sopenharmony_ci * Revision 1.41 2005/10/11 18:47:07 oliver-guest 1765141cc406Sopenharmony_ci * Fixes for Epson 3490 and 16 bit scan mode 1766141cc406Sopenharmony_ci * 1767141cc406Sopenharmony_ci * Revision 1.40 2005/09/28 22:09:26 oliver-guest 1768141cc406Sopenharmony_ci * Re-enabled enhanced inquiry command for Epson scanners (duh\!) 1769141cc406Sopenharmony_ci * 1770141cc406Sopenharmony_ci * Revision 1.39 2005/09/28 21:33:10 oliver-guest 1771141cc406Sopenharmony_ci * Added 16 bit option for Epson scanners (untested) 1772141cc406Sopenharmony_ci * 1773141cc406Sopenharmony_ci * Revision 1.38 2005/09/25 08:19:12 oliver-guest 1774141cc406Sopenharmony_ci * Removed debugging code for Epson scanners 1775141cc406Sopenharmony_ci * 1776141cc406Sopenharmony_ci * Revision 1.37 2005/09/03 11:31:31 oliver-guest 1777141cc406Sopenharmony_ci * Another small bugfix 1778141cc406Sopenharmony_ci * 1779141cc406Sopenharmony_ci * Revision 1.36 2005/09/03 10:52:11 oliver-guest 1780141cc406Sopenharmony_ci * Fixed debugging code for epson scanners 1781141cc406Sopenharmony_ci * 1782141cc406Sopenharmony_ci * Revision 1.35 2005/08/16 17:19:20 oliver-guest 1783141cc406Sopenharmony_ci * Make compileable again 1784141cc406Sopenharmony_ci * 1785141cc406Sopenharmony_ci * Revision 1.34 2005/08/15 18:56:55 oliver-guest 1786141cc406Sopenharmony_ci * Added temporary debug code for 2480/2580 distinction 1787141cc406Sopenharmony_ci * 1788141cc406Sopenharmony_ci * Revision 1.33 2005/08/15 18:06:37 oliver-guest 1789141cc406Sopenharmony_ci * Added support for Epson 3490/3590 (thanks to Matt Judge) 1790141cc406Sopenharmony_ci * 1791141cc406Sopenharmony_ci * Revision 1.32 2005/07/18 17:37:37 oliver-guest 1792141cc406Sopenharmony_ci * ZETA changes for SnapScan backend 1793141cc406Sopenharmony_ci * 1794141cc406Sopenharmony_ci * Revision 1.31 2004/12/09 23:21:48 oliver-guest 1795141cc406Sopenharmony_ci * Added quality calibration for Epson 2480 (by Simon Munton) 1796141cc406Sopenharmony_ci * 1797141cc406Sopenharmony_ci * Revision 1.30 2004/12/01 22:12:03 oliver-guest 1798141cc406Sopenharmony_ci * Added support for Epson 1270 1799141cc406Sopenharmony_ci * 1800141cc406Sopenharmony_ci * Revision 1.29 2004/10/03 17:34:36 hmg-guest 1801141cc406Sopenharmony_ci * 64 bit platform fixes (bug #300799). 1802141cc406Sopenharmony_ci * 1803141cc406Sopenharmony_ci * Revision 1.28 2004/09/02 20:59:11 oliver-guest 1804141cc406Sopenharmony_ci * Added support for Epson 2480 1805141cc406Sopenharmony_ci * 1806141cc406Sopenharmony_ci * Revision 1.27 2004/04/02 20:19:24 oliver-guest 1807141cc406Sopenharmony_ci * Various bugfixes for gamma correction (thanks to Robert Tsien) 1808141cc406Sopenharmony_ci * 1809141cc406Sopenharmony_ci * Revision 1.26 2003/11/07 23:26:49 oliver-guest 1810141cc406Sopenharmony_ci * Final bugfixes for bascic support of Epson 1670 1811141cc406Sopenharmony_ci * 1812141cc406Sopenharmony_ci * Revision 1.25 2003/10/21 20:43:25 oliver-guest 1813141cc406Sopenharmony_ci * Bugfixes for SnapScan backend 1814141cc406Sopenharmony_ci * 1815141cc406Sopenharmony_ci * Revision 1.24 2003/10/07 19:41:34 oliver-guest 1816141cc406Sopenharmony_ci * Updates for Epson Perfection 1670 1817141cc406Sopenharmony_ci * 1818141cc406Sopenharmony_ci * Revision 1.23 2003/08/19 21:05:08 oliverschwartz 1819141cc406Sopenharmony_ci * Scanner ID cleanup 1820141cc406Sopenharmony_ci * 1821141cc406Sopenharmony_ci * Revision 1.22 2003/04/30 20:49:39 oliverschwartz 1822141cc406Sopenharmony_ci * SnapScan backend 1.4.26 1823141cc406Sopenharmony_ci * 1824141cc406Sopenharmony_ci * Revision 1.37 2003/04/30 20:42:19 oliverschwartz 1825141cc406Sopenharmony_ci * Added support for Agfa Arcus 1200 (supplied by Valtteri Vuorikoski) 1826141cc406Sopenharmony_ci * 1827141cc406Sopenharmony_ci * Revision 1.36 2003/04/02 21:17:13 oliverschwartz 1828141cc406Sopenharmony_ci * Fix for 1200 DPI with Acer 5000 1829141cc406Sopenharmony_ci * 1830141cc406Sopenharmony_ci * Revision 1.35 2003/02/08 10:45:09 oliverschwartz 1831141cc406Sopenharmony_ci * Use 600 DPI as optical resolution for Benq 5000 1832141cc406Sopenharmony_ci * 1833141cc406Sopenharmony_ci * Revision 1.34 2002/12/10 20:14:12 oliverschwartz 1834141cc406Sopenharmony_ci * Enable color offset correction for SnapScan300 1835141cc406Sopenharmony_ci * 1836141cc406Sopenharmony_ci * Revision 1.33 2002/09/24 16:07:48 oliverschwartz 1837141cc406Sopenharmony_ci * Added support for Benq 5000 1838141cc406Sopenharmony_ci * 1839141cc406Sopenharmony_ci * Revision 1.32 2002/06/06 20:40:01 oliverschwartz 1840141cc406Sopenharmony_ci * Changed default scan area for transparency unit of SnapScan e50 1841141cc406Sopenharmony_ci * 1842141cc406Sopenharmony_ci * Revision 1.31 2002/05/02 18:28:44 oliverschwartz 1843141cc406Sopenharmony_ci * Added ADF support 1844141cc406Sopenharmony_ci * 1845141cc406Sopenharmony_ci * Revision 1.30 2002/04/27 14:41:22 oliverschwartz 1846141cc406Sopenharmony_ci * Print number of open handles in close_scanner() 1847141cc406Sopenharmony_ci * 1848141cc406Sopenharmony_ci * Revision 1.29 2002/04/10 21:46:48 oliverschwartz 1849141cc406Sopenharmony_ci * Removed illegal character 1850141cc406Sopenharmony_ci * 1851141cc406Sopenharmony_ci * Revision 1.28 2002/04/10 21:01:02 oliverschwartz 1852141cc406Sopenharmony_ci * Disable send_diagnostic() for 1236s 1853141cc406Sopenharmony_ci * 1854141cc406Sopenharmony_ci * Revision 1.27 2002/03/24 12:11:20 oliverschwartz 1855141cc406Sopenharmony_ci * Get name of firmware file in sane_init 1856141cc406Sopenharmony_ci * 1857141cc406Sopenharmony_ci * Revision 1.26 2002/01/23 20:42:41 oliverschwartz 1858141cc406Sopenharmony_ci * Improve recognition of Acer 320U 1859141cc406Sopenharmony_ci * Add sense_handler code for sense code 0x0b 1860141cc406Sopenharmony_ci * Fix for spaces in model strings 1861141cc406Sopenharmony_ci * 1862141cc406Sopenharmony_ci * Revision 1.25 2001/12/12 19:44:59 oliverschwartz 1863141cc406Sopenharmony_ci * Clean up CVS log 1864141cc406Sopenharmony_ci * 1865141cc406Sopenharmony_ci * Revision 1.24 2001/12/09 23:01:00 oliverschwartz 1866141cc406Sopenharmony_ci * - use sense handler for USB 1867141cc406Sopenharmony_ci * - fix scan mode 1868141cc406Sopenharmony_ci * 1869141cc406Sopenharmony_ci * Revision 1.23 2001/12/08 11:53:31 oliverschwartz 1870141cc406Sopenharmony_ci * - Additional logging in sense handler 1871141cc406Sopenharmony_ci * - Fix wait_scanner_ready() if device reports busy 1872141cc406Sopenharmony_ci * - Fix scanning mode (preview/normal) 1873141cc406Sopenharmony_ci * 1874141cc406Sopenharmony_ci * Revision 1.22 2001/11/27 23:16:17 oliverschwartz 1875141cc406Sopenharmony_ci * - Fix color alignment for SnapScan 600 1876141cc406Sopenharmony_ci * - Added documentation in snapscan-sources.c 1877141cc406Sopenharmony_ci * - Guard against TL_X < BR_X and TL_Y < BR_Y 1878141cc406Sopenharmony_ci * 1879141cc406Sopenharmony_ci * Revision 1.21 2001/10/21 08:49:37 oliverschwartz 1880141cc406Sopenharmony_ci * correct number of scan lines for calibration thanks to Mikko Ty���vi 1881141cc406Sopenharmony_ci * 1882141cc406Sopenharmony_ci * Revision 1.20 2001/10/12 20:54:04 oliverschwartz 1883141cc406Sopenharmony_ci * enable gamma correction for Snapscan 1236, e20 and e50 scanners 1884141cc406Sopenharmony_ci * 1885141cc406Sopenharmony_ci * Revision 1.19 2001/10/11 14:02:10 oliverschwartz 1886141cc406Sopenharmony_ci * Distinguish between e20/e25 and e40/e50 1887141cc406Sopenharmony_ci * 1888141cc406Sopenharmony_ci * Revision 1.18 2001/10/09 22:34:23 oliverschwartz 1889141cc406Sopenharmony_ci * fix compiler warnings 1890141cc406Sopenharmony_ci * 1891141cc406Sopenharmony_ci * Revision 1.17 2001/10/08 19:26:01 oliverschwartz 1892141cc406Sopenharmony_ci * - Disable quality calibration for scanners that do not support it 1893141cc406Sopenharmony_ci * 1894141cc406Sopenharmony_ci * Revision 1.16 2001/10/08 18:22:01 oliverschwartz 1895141cc406Sopenharmony_ci * - Disable quality calibration for Acer Vuego 310F 1896141cc406Sopenharmony_ci * - Use sanei_scsi_max_request_size as scanner buffer size 1897141cc406Sopenharmony_ci * for SCSI devices 1898141cc406Sopenharmony_ci * - Added new devices to snapscan.desc 1899141cc406Sopenharmony_ci * 1900141cc406Sopenharmony_ci * Revision 1.15 2001/09/18 15:01:07 oliverschwartz 1901141cc406Sopenharmony_ci * - Read scanner id string again after firmware upload 1902141cc406Sopenharmony_ci * to identify correct model 1903141cc406Sopenharmony_ci * - Make firmware upload work for AGFA scanners 1904141cc406Sopenharmony_ci * - Change copyright notice 1905141cc406Sopenharmony_ci * 1906141cc406Sopenharmony_ci * Revision 1.14 2001/09/17 10:01:08 sable 1907141cc406Sopenharmony_ci * Added model AGFA 1236U 1908141cc406Sopenharmony_ci * 1909141cc406Sopenharmony_ci * Revision 1.13 2001/09/09 18:06:32 oliverschwartz 1910141cc406Sopenharmony_ci * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup 1911141cc406Sopenharmony_ci * 1912141cc406Sopenharmony_ci * Revision 1.12 2001/04/10 13:00:31 sable 1913141cc406Sopenharmony_ci * Moving sanei_usb_* to snapscani_usb* 1914141cc406Sopenharmony_ci * 1915141cc406Sopenharmony_ci * Revision 1.11 2001/04/10 11:04:31 sable 1916141cc406Sopenharmony_ci * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli 1917141cc406Sopenharmony_ci * 1918141cc406Sopenharmony_ci * Revision 1.10 2001/03/17 22:53:21 sable 1919141cc406Sopenharmony_ci * Applying Mikael Magnusson patch concerning Gamma correction 1920141cc406Sopenharmony_ci * Support for 1212U_2 1921141cc406Sopenharmony_ci * 1922141cc406Sopenharmony_ci * Revision 1.9 2000/11/10 01:01:59 sable 1923141cc406Sopenharmony_ci * USB (kind of) autodetection 1924141cc406Sopenharmony_ci * 1925141cc406Sopenharmony_ci * Revision 1.8 2000/11/01 01:26:43 sable 1926141cc406Sopenharmony_ci * Support for 1212U 1927141cc406Sopenharmony_ci * 1928141cc406Sopenharmony_ci * Revision 1.7 2000/10/30 22:32:20 sable 1929141cc406Sopenharmony_ci * Support for vuego310s vuego610s and 1236s 1930141cc406Sopenharmony_ci * 1931141cc406Sopenharmony_ci * Revision 1.6 2000/10/29 22:44:55 sable 1932141cc406Sopenharmony_ci * Bug correction for 1236s 1933141cc406Sopenharmony_ci * 1934141cc406Sopenharmony_ci * Revision 1.5 2000/10/28 14:16:10 sable 1935141cc406Sopenharmony_ci * Bug correction for SnapScan310 1936141cc406Sopenharmony_ci * 1937141cc406Sopenharmony_ci * Revision 1.4 2000/10/28 14:06:35 sable 1938141cc406Sopenharmony_ci * Add support for Acer300f 1939141cc406Sopenharmony_ci * 1940141cc406Sopenharmony_ci * Revision 1.3 2000/10/15 19:52:06 cbagwell 1941141cc406Sopenharmony_ci * Changed USB support to a 1 line modification instead of multi-file 1942141cc406Sopenharmony_ci * changes. 1943141cc406Sopenharmony_ci * 1944141cc406Sopenharmony_ci * Revision 1.2 2000/10/13 03:50:27 cbagwell 1945141cc406Sopenharmony_ci * Updating to source from SANE 1.0.3. Calling this version 1.1 1946141cc406Sopenharmony_ci * 1947141cc406Sopenharmony_ci * */ 1948