1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Artec AS6E backend. 3141cc406Sopenharmony_ci Copyright (C) 2000 Eugene S. Weiss 4141cc406Sopenharmony_ci This file is part of the SANE package. 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 7141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 8141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 9141cc406Sopenharmony_ci License, or (at your option) any later version. 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 12141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 13141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14141cc406Sopenharmony_ci General Public License for more details. 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 17141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 18141cc406Sopenharmony_ci 19141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 20141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 23141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 24141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 25141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 26141cc406Sopenharmony_ci account of linking the SANE library code into it. 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 29141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 30141cc406Sopenharmony_ci License. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 33141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 34141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 37141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 38141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci This file implements a backend for the Artec AS6E by making a bridge 41141cc406Sopenharmony_ci to the as6edriver program. The as6edriver program can be found at 42141cc406Sopenharmony_ci http://as6edriver.sourceforge.net . */ 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#include "../include/sane/config.h" 48141cc406Sopenharmony_ci#include <string.h> 49141cc406Sopenharmony_ci#include <stdio.h> 50141cc406Sopenharmony_ci#include <stdlib.h> 51141cc406Sopenharmony_ci#include <unistd.h> 52141cc406Sopenharmony_ci#include <ctype.h> 53141cc406Sopenharmony_ci#include <limits.h> 54141cc406Sopenharmony_ci#include <stdarg.h> 55141cc406Sopenharmony_ci#include <string.h> 56141cc406Sopenharmony_ci#include <signal.h> 57141cc406Sopenharmony_ci#include <sys/stat.h> 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include "../include/sane/sane.h" 60141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci#define BACKENDNAME as6e 63141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 64141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#include "as6e.h" 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_cistatic int num_devices; 69141cc406Sopenharmony_cistatic AS6E_Device *first_dev; 70141cc406Sopenharmony_cistatic AS6E_Scan *first_handle; 71141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_cistatic SANE_Status attach (const char *devname, AS6E_Device ** devp); 74141cc406Sopenharmony_ci/* static SANE_Status attach_one (const char *dev); */ 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = { 77141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 78141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 79141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 80141cc406Sopenharmony_ci 0 81141cc406Sopenharmony_ci}; 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_cistatic const SANE_Word resolution_list[] = { 84141cc406Sopenharmony_ci 4, 300, 200, 100, 50 85141cc406Sopenharmony_ci}; 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_cistatic const SANE_Range x_range = { 88141cc406Sopenharmony_ci SANE_FIX (0), 89141cc406Sopenharmony_ci SANE_FIX (215.91), 90141cc406Sopenharmony_ci SANE_FIX (0) 91141cc406Sopenharmony_ci}; 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_cistatic const SANE_Range y_range = { 94141cc406Sopenharmony_ci SANE_FIX (0), 95141cc406Sopenharmony_ci SANE_FIX (297.19), 96141cc406Sopenharmony_ci SANE_FIX (0) 97141cc406Sopenharmony_ci}; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistatic const SANE_Range brightness_range = { 101141cc406Sopenharmony_ci -100, 102141cc406Sopenharmony_ci 100, 103141cc406Sopenharmony_ci 1 104141cc406Sopenharmony_ci}; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_cistatic const SANE_Range contrast_range = { 107141cc406Sopenharmony_ci -100, 108141cc406Sopenharmony_ci 100, 109141cc406Sopenharmony_ci 1 110141cc406Sopenharmony_ci}; 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 113141cc406Sopenharmony_cistatic SANE_Int 114141cc406Sopenharmony_cias6e_unit_convert (SANE_Fixed value) 115141cc406Sopenharmony_ci{ 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci double precise; 118141cc406Sopenharmony_ci SANE_Int return_value; 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci precise = SANE_UNFIX (value); 121141cc406Sopenharmony_ci precise = (precise * 300) / MM_PER_INCH; 122141cc406Sopenharmony_ci return_value = precise; 123141cc406Sopenharmony_ci return return_value; 124141cc406Sopenharmony_ci} 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ciSANE_Status 129141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 130141cc406Sopenharmony_ci SANE_Int * len) 131141cc406Sopenharmony_ci{ 132141cc406Sopenharmony_ci AS6E_Scan *s = handle; 133141cc406Sopenharmony_ci SANE_Word buffer_offset = 0; 134141cc406Sopenharmony_ci int written = 0, bytes_read = 0, maxbytes; 135141cc406Sopenharmony_ci SANE_Word bytecounter, linebufcounter, ctlbytes; 136141cc406Sopenharmony_ci SANE_Byte *linebuffer; 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci DBG (3, "reading %d bytes, %d bytes in carryover buffer\n", max_len, 139141cc406Sopenharmony_ci s->scan_buffer_count); 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci if ((unsigned int) s->image_counter >= s->bytes_to_read) 142141cc406Sopenharmony_ci { 143141cc406Sopenharmony_ci *len = 0; 144141cc406Sopenharmony_ci if (s->scanning) 145141cc406Sopenharmony_ci { 146141cc406Sopenharmony_ci read (s->as6e_params.ctlinpipe, &written, sizeof (written)); 147141cc406Sopenharmony_ci if (written != -1) 148141cc406Sopenharmony_ci DBG (3, "pipe error\n"); 149141cc406Sopenharmony_ci DBG (3, "trying to read -1 ...written = %d\n", written); 150141cc406Sopenharmony_ci } 151141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 152141cc406Sopenharmony_ci DBG (1, "image data complete, sending EOF...\n"); 153141cc406Sopenharmony_ci return SANE_STATUS_EOF; 154141cc406Sopenharmony_ci } /*image complete */ 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci linebuffer = s->line_buffer; 157141cc406Sopenharmony_ci if (s->scan_buffer_count > 0) 158141cc406Sopenharmony_ci { /*there are leftover bytes from the last call */ 159141cc406Sopenharmony_ci if (s->scan_buffer_count <= max_len) 160141cc406Sopenharmony_ci { 161141cc406Sopenharmony_ci for (*len = 0; *len < s->scan_buffer_count; (*len)++) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci buf[*len] = s->scan_buffer[*len]; 164141cc406Sopenharmony_ci buffer_offset++; 165141cc406Sopenharmony_ci } 166141cc406Sopenharmony_ci s->scan_buffer_count = 0; 167141cc406Sopenharmony_ci if (s->scan_buffer_count == max_len) 168141cc406Sopenharmony_ci { 169141cc406Sopenharmony_ci s->scan_buffer_count = 0; 170141cc406Sopenharmony_ci s->image_counter += max_len; 171141cc406Sopenharmony_ci DBG (3, "returning %d bytes from the carryover buffer\n", *len); 172141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 173141cc406Sopenharmony_ci } 174141cc406Sopenharmony_ci } 175141cc406Sopenharmony_ci else 176141cc406Sopenharmony_ci { 177141cc406Sopenharmony_ci for (*len = 0; *len < max_len; (*len)++) 178141cc406Sopenharmony_ci buf[*len] = s->scan_buffer[*len]; 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci for (bytecounter = max_len; 181141cc406Sopenharmony_ci bytecounter < s->scan_buffer_count; bytecounter++) 182141cc406Sopenharmony_ci s->scan_buffer[bytecounter - max_len] 183141cc406Sopenharmony_ci = s->scan_buffer[bytecounter]; 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci s->scan_buffer_count -= max_len; 186141cc406Sopenharmony_ci s->image_counter += max_len; 187141cc406Sopenharmony_ci DBG (3, "returning %d bytes from the carryover buffer\n", *len); 188141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 189141cc406Sopenharmony_ci } 190141cc406Sopenharmony_ci } 191141cc406Sopenharmony_ci else 192141cc406Sopenharmony_ci { 193141cc406Sopenharmony_ci *len = 0; /*no bytes in the buffer */ 194141cc406Sopenharmony_ci if (!s->scanning) 195141cc406Sopenharmony_ci { 196141cc406Sopenharmony_ci DBG (1, "scan over returning %d\n", *len); 197141cc406Sopenharmony_ci if (s->scan_buffer_count) 198141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 199141cc406Sopenharmony_ci else 200141cc406Sopenharmony_ci return SANE_STATUS_EOF; 201141cc406Sopenharmony_ci } 202141cc406Sopenharmony_ci } 203141cc406Sopenharmony_ci while (*len < max_len) 204141cc406Sopenharmony_ci { 205141cc406Sopenharmony_ci DBG (3, "trying to read number of bytes...\n"); 206141cc406Sopenharmony_ci ctlbytes = read (s->as6e_params.ctlinpipe, &written, sizeof (written)); 207141cc406Sopenharmony_ci DBG (3, "bytes written = %d, ctlbytes =%d\n", written, ctlbytes); 208141cc406Sopenharmony_ci fflush (stdout); 209141cc406Sopenharmony_ci if ((s->cancelled) && (written == 0)) 210141cc406Sopenharmony_ci { /*first clear -1 from pipe */ 211141cc406Sopenharmony_ci DBG (1, "sending SANE_STATUS_CANCELLED\n"); 212141cc406Sopenharmony_ci read (s->as6e_params.ctlinpipe, &written, sizeof (written)); 213141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 214141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci if (written == -1) 217141cc406Sopenharmony_ci { 218141cc406Sopenharmony_ci DBG (1, "-1READ Scanner through. returning %d bytes\n", *len); 219141cc406Sopenharmony_ci s->image_counter += *len; 220141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 221141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 222141cc406Sopenharmony_ci } 223141cc406Sopenharmony_ci linebufcounter = 0; 224141cc406Sopenharmony_ci DBG (3, 225141cc406Sopenharmony_ci "linebufctr reset, len =%d written =%d bytes_read =%d, max = %d\n", 226141cc406Sopenharmony_ci *len, written, bytes_read, max_len); 227141cc406Sopenharmony_ci maxbytes = written; 228141cc406Sopenharmony_ci while (linebufcounter < written) 229141cc406Sopenharmony_ci { 230141cc406Sopenharmony_ci DBG (4, "trying to read data pipe\n"); 231141cc406Sopenharmony_ci bytes_read = 232141cc406Sopenharmony_ci read (s->as6e_params.datapipe, linebuffer + linebufcounter, 233141cc406Sopenharmony_ci maxbytes); 234141cc406Sopenharmony_ci linebufcounter += bytes_read; 235141cc406Sopenharmony_ci maxbytes -= bytes_read; 236141cc406Sopenharmony_ci DBG (3, "bytes_read = %d linebufcounter = %d\n", bytes_read, 237141cc406Sopenharmony_ci linebufcounter); 238141cc406Sopenharmony_ci } 239141cc406Sopenharmony_ci DBG (3, "written =%d max_len =%d len =%d\n", written, max_len, *len); 240141cc406Sopenharmony_ci if (written <= (max_len - *len)) 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci for (bytecounter = 0; bytecounter < written; bytecounter++) 243141cc406Sopenharmony_ci { 244141cc406Sopenharmony_ci buf[bytecounter + buffer_offset] = linebuffer[bytecounter]; 245141cc406Sopenharmony_ci (*len)++; 246141cc406Sopenharmony_ci } 247141cc406Sopenharmony_ci buffer_offset += written; 248141cc406Sopenharmony_ci DBG (3, "buffer offset = %d\n", buffer_offset); 249141cc406Sopenharmony_ci } 250141cc406Sopenharmony_ci else if (max_len > *len) 251141cc406Sopenharmony_ci { /*there's still room to send data */ 252141cc406Sopenharmony_ci for (bytecounter = 0; bytecounter < (max_len - *len); bytecounter++) 253141cc406Sopenharmony_ci buf[bytecounter + buffer_offset] = linebuffer[bytecounter]; 254141cc406Sopenharmony_ci DBG (3, "topping off buffer\n"); 255141cc406Sopenharmony_ci for (bytecounter = (max_len - *len); bytecounter < written; 256141cc406Sopenharmony_ci bytecounter++) 257141cc406Sopenharmony_ci { 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci s->scan_buffer[s->scan_buffer_count + bytecounter - 260141cc406Sopenharmony_ci (max_len - *len)] = linebuffer[bytecounter]; 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci s->scan_buffer_count += (written - (max_len - *len)); 263141cc406Sopenharmony_ci *len = max_len; 264141cc406Sopenharmony_ci } 265141cc406Sopenharmony_ci else 266141cc406Sopenharmony_ci { /*everything goes into the carryover buffer */ 267141cc406Sopenharmony_ci for (bytecounter = 0; bytecounter < written; bytecounter++) 268141cc406Sopenharmony_ci s->scan_buffer[s->scan_buffer_count + bytecounter] 269141cc406Sopenharmony_ci = linebuffer[bytecounter]; 270141cc406Sopenharmony_ci s->scan_buffer_count += written; 271141cc406Sopenharmony_ci } 272141cc406Sopenharmony_ci } /*while there's space in the buffer */ 273141cc406Sopenharmony_ci s->image_counter += *len; 274141cc406Sopenharmony_ci DBG (3, "image ctr = %d bytes_to_read = %lu returning %d\n", 275141cc406Sopenharmony_ci s->image_counter, (u_long) s->bytes_to_read, *len); 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 278141cc406Sopenharmony_ci} 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 281141cc406Sopenharmony_civoid 282141cc406Sopenharmony_cisane_cancel (SANE_Handle h) 283141cc406Sopenharmony_ci{ 284141cc406Sopenharmony_ci AS6E_Scan *s = h; 285141cc406Sopenharmony_ci SANE_Word test; 286141cc406Sopenharmony_ci DBG (2, "trying to cancel...\n"); 287141cc406Sopenharmony_ci if (s->scanning) 288141cc406Sopenharmony_ci { 289141cc406Sopenharmony_ci test = kill (s->child_pid, SIGUSR1); 290141cc406Sopenharmony_ci if (test == 0) 291141cc406Sopenharmony_ci s->cancelled = SANE_TRUE; 292141cc406Sopenharmony_ci } 293141cc406Sopenharmony_ci} 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ciSANE_Status 298141cc406Sopenharmony_cisane_start (SANE_Handle handle) 299141cc406Sopenharmony_ci{ 300141cc406Sopenharmony_ci AS6E_Scan *s = handle; 301141cc406Sopenharmony_ci SANE_Status status; 302141cc406Sopenharmony_ci int repeat = 1; 303141cc406Sopenharmony_ci SANE_Word numbytes; 304141cc406Sopenharmony_ci int scan_params[8]; 305141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the 306141cc406Sopenharmony_ci * parameters will be overwritten below, but that's OK. */ 307141cc406Sopenharmony_ci DBG (2, "sane_start\n"); 308141cc406Sopenharmony_ci status = sane_get_parameters (s, 0); 309141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 310141cc406Sopenharmony_ci return status; 311141cc406Sopenharmony_ci DBG (1, "Got params again...\n"); 312141cc406Sopenharmony_ci numbytes = write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat)); 313141cc406Sopenharmony_ci if (numbytes != sizeof (repeat)) 314141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 315141cc406Sopenharmony_ci DBG (1, "sending start_scan signal\n"); 316141cc406Sopenharmony_ci scan_params[0] = s->as6e_params.resolution; 317141cc406Sopenharmony_ci if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 318141cc406Sopenharmony_ci scan_params[1] = 0; 319141cc406Sopenharmony_ci else if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) 320141cc406Sopenharmony_ci scan_params[1] = 1; 321141cc406Sopenharmony_ci else if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) 322141cc406Sopenharmony_ci scan_params[1] = 2; 323141cc406Sopenharmony_ci else 324141cc406Sopenharmony_ci return (SANE_STATUS_JAMMED); /*this should never happen */ 325141cc406Sopenharmony_ci scan_params[2] = s->as6e_params.startpos; 326141cc406Sopenharmony_ci scan_params[3] = s->as6e_params.stoppos; 327141cc406Sopenharmony_ci scan_params[4] = s->as6e_params.startline; 328141cc406Sopenharmony_ci scan_params[5] = s->as6e_params.stopline; 329141cc406Sopenharmony_ci scan_params[6] = s->value[OPT_BRIGHTNESS].w; 330141cc406Sopenharmony_ci scan_params[7] = s->value[OPT_CONTRAST].w; 331141cc406Sopenharmony_ci DBG (1, "scan params = %d %d %d %d %d %d %d %d\n", scan_params[0], 332141cc406Sopenharmony_ci scan_params[1], scan_params[2], scan_params[3], 333141cc406Sopenharmony_ci scan_params[4], scan_params[5], scan_params[6], scan_params[7]); 334141cc406Sopenharmony_ci numbytes = 335141cc406Sopenharmony_ci write (s->as6e_params.ctloutpipe, scan_params, sizeof (scan_params)); 336141cc406Sopenharmony_ci if (numbytes != sizeof (scan_params)) 337141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 338141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 339141cc406Sopenharmony_ci s->scan_buffer_count = 0; 340141cc406Sopenharmony_ci s->image_counter = 0; 341141cc406Sopenharmony_ci s->cancelled = 0; 342141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 343141cc406Sopenharmony_ci} 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ciSANE_Status 348141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 349141cc406Sopenharmony_ci{ 350141cc406Sopenharmony_ci AS6E_Scan *s = handle; 351141cc406Sopenharmony_ci SANE_String mode; 352141cc406Sopenharmony_ci SANE_Word divisor = 1; 353141cc406Sopenharmony_ci DBG (2, "sane_get_parameters\n"); 354141cc406Sopenharmony_ci if (!s->scanning) 355141cc406Sopenharmony_ci { 356141cc406Sopenharmony_ci memset (&s->sane_params, 0, sizeof (s->sane_params)); 357141cc406Sopenharmony_ci s->as6e_params.resolution = s->value[OPT_RESOLUTION].w; 358141cc406Sopenharmony_ci s->as6e_params.startpos = as6e_unit_convert (s->value[OPT_TL_X].w); 359141cc406Sopenharmony_ci s->as6e_params.stoppos = as6e_unit_convert (s->value[OPT_BR_X].w); 360141cc406Sopenharmony_ci s->as6e_params.startline = as6e_unit_convert (s->value[OPT_TL_Y].w); 361141cc406Sopenharmony_ci s->as6e_params.stopline = as6e_unit_convert (s->value[OPT_BR_Y].w); 362141cc406Sopenharmony_ci if ((s->as6e_params.resolution == 200) 363141cc406Sopenharmony_ci || (s->as6e_params.resolution == 100)) 364141cc406Sopenharmony_ci divisor = 3; 365141cc406Sopenharmony_ci else if (s->as6e_params.resolution == 50) 366141cc406Sopenharmony_ci divisor = 6; /*get legal values for 200 dpi */ 367141cc406Sopenharmony_ci s->as6e_params.startpos = (s->as6e_params.startpos / divisor) * divisor; 368141cc406Sopenharmony_ci s->as6e_params.stoppos = (s->as6e_params.stoppos / divisor) * divisor; 369141cc406Sopenharmony_ci s->as6e_params.startline = 370141cc406Sopenharmony_ci (s->as6e_params.startline / divisor) * divisor; 371141cc406Sopenharmony_ci s->as6e_params.stopline = (s->as6e_params.stopline / divisor) * divisor; 372141cc406Sopenharmony_ci s->sane_params.pixels_per_line = 373141cc406Sopenharmony_ci (s->as6e_params.stoppos - 374141cc406Sopenharmony_ci s->as6e_params.startpos) * s->as6e_params.resolution / 300; 375141cc406Sopenharmony_ci s->sane_params.lines = 376141cc406Sopenharmony_ci (s->as6e_params.stopline - 377141cc406Sopenharmony_ci s->as6e_params.startline) * s->as6e_params.resolution / 300; 378141cc406Sopenharmony_ci mode = s->value[OPT_MODE].s; 379141cc406Sopenharmony_ci/* if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || 380141cc406Sopenharmony_ci (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)) 381141cc406Sopenharmony_ci { 382141cc406Sopenharmony_ci s->sane_params.format = SANE_FRAME_GRAY; 383141cc406Sopenharmony_ci s->sane_params.bytes_per_line = (s->sane_params.pixels_per_line + 7) / 8; 384141cc406Sopenharmony_ci s->sane_params.depth = 1; 385141cc406Sopenharmony_ci } */ 386141cc406Sopenharmony_ci/*else*/ if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 387141cc406Sopenharmony_ci || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 388141cc406Sopenharmony_ci { 389141cc406Sopenharmony_ci s->sane_params.format = SANE_FRAME_GRAY; 390141cc406Sopenharmony_ci s->sane_params.bytes_per_line = s->sane_params.pixels_per_line; 391141cc406Sopenharmony_ci s->sane_params.depth = 8; 392141cc406Sopenharmony_ci } /*grey frame */ 393141cc406Sopenharmony_ci else 394141cc406Sopenharmony_ci { 395141cc406Sopenharmony_ci s->sane_params.format = SANE_FRAME_RGB; 396141cc406Sopenharmony_ci s->sane_params.bytes_per_line = 3 * s->sane_params.pixels_per_line; 397141cc406Sopenharmony_ci s->sane_params.depth = 8; 398141cc406Sopenharmony_ci } /*color frame */ 399141cc406Sopenharmony_ci s->bytes_to_read = s->sane_params.lines * s->sane_params.bytes_per_line; 400141cc406Sopenharmony_ci s->sane_params.last_frame = SANE_TRUE; 401141cc406Sopenharmony_ci } /*!scanning */ 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci if (params) 404141cc406Sopenharmony_ci *params = s->sane_params; 405141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 406141cc406Sopenharmony_ci} 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 409141cc406Sopenharmony_ciSANE_Status 410141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 411141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 412141cc406Sopenharmony_ci{ 413141cc406Sopenharmony_ci AS6E_Scan *s = handle; 414141cc406Sopenharmony_ci SANE_Status status = 0; 415141cc406Sopenharmony_ci SANE_Word cap; 416141cc406Sopenharmony_ci DBG (2, "sane_control_option\n"); 417141cc406Sopenharmony_ci if (info) 418141cc406Sopenharmony_ci *info = 0; 419141cc406Sopenharmony_ci if (s->scanning) 420141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 421141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 422141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 423141cc406Sopenharmony_ci cap = s->options_list[option].cap; 424141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 425141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 426141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 427141cc406Sopenharmony_ci { 428141cc406Sopenharmony_ci DBG (1, "sane_control_option %d, get value\n", option); 429141cc406Sopenharmony_ci switch (option) 430141cc406Sopenharmony_ci { 431141cc406Sopenharmony_ci /* word options: */ 432141cc406Sopenharmony_ci case OPT_RESOLUTION: 433141cc406Sopenharmony_ci case OPT_TL_X: 434141cc406Sopenharmony_ci case OPT_TL_Y: 435141cc406Sopenharmony_ci case OPT_BR_X: 436141cc406Sopenharmony_ci case OPT_BR_Y: 437141cc406Sopenharmony_ci case OPT_NUM_OPTS: 438141cc406Sopenharmony_ci case OPT_CONTRAST: 439141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 440141cc406Sopenharmony_ci *(SANE_Word *) val = s->value[option].w; 441141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 442141cc406Sopenharmony_ci /* string options: */ 443141cc406Sopenharmony_ci case OPT_MODE: 444141cc406Sopenharmony_ci strcpy (val, s->value[option].s); 445141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 446141cc406Sopenharmony_ci } 447141cc406Sopenharmony_ci } 448141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 449141cc406Sopenharmony_ci { 450141cc406Sopenharmony_ci DBG (1, "sane_control_option %d, set value\n", option); 451141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 452141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 453141cc406Sopenharmony_ci/* status = sanei_constrain_value (s->options_list[option], val, info);*/ 454141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 455141cc406Sopenharmony_ci return (status); 456141cc406Sopenharmony_ci switch (option) 457141cc406Sopenharmony_ci { 458141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 459141cc406Sopenharmony_ci case OPT_RESOLUTION: 460141cc406Sopenharmony_ci case OPT_BR_X: 461141cc406Sopenharmony_ci case OPT_BR_Y: 462141cc406Sopenharmony_ci case OPT_TL_X: 463141cc406Sopenharmony_ci case OPT_TL_Y: 464141cc406Sopenharmony_ci if (info && s->value[option].w != *(SANE_Word *) val) 465141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 466141cc406Sopenharmony_ci /* fall through */ 467141cc406Sopenharmony_ci case OPT_NUM_OPTS: 468141cc406Sopenharmony_ci case OPT_CONTRAST: 469141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 470141cc406Sopenharmony_ci s->value[option].w = *(SANE_Word *) val; 471141cc406Sopenharmony_ci DBG (1, "set brightness to\n"); 472141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 473141cc406Sopenharmony_ci case OPT_MODE: 474141cc406Sopenharmony_ci if (s->value[option].s) 475141cc406Sopenharmony_ci free (s->value[option].s); 476141cc406Sopenharmony_ci s->value[option].s = strdup (val); 477141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 478141cc406Sopenharmony_ci } 479141cc406Sopenharmony_ci } 480141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 481141cc406Sopenharmony_ci} 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 484141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 485141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 486141cc406Sopenharmony_ci{ 487141cc406Sopenharmony_ci AS6E_Scan *s = handle; 488141cc406Sopenharmony_ci DBG (2, "sane_get_option_descriptor\n"); 489141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 490141cc406Sopenharmony_ci return (0); 491141cc406Sopenharmony_ci return (&s->options_list[option]); 492141cc406Sopenharmony_ci} 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_civoid 497141cc406Sopenharmony_cisane_close (SANE_Handle handle) 498141cc406Sopenharmony_ci{ 499141cc406Sopenharmony_ci AS6E_Scan *prev, *s; 500141cc406Sopenharmony_ci SANE_Word repeat = 0; 501141cc406Sopenharmony_ci DBG (2, "sane_close\n"); 502141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 503141cc406Sopenharmony_ci prev = 0; 504141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) 505141cc406Sopenharmony_ci { 506141cc406Sopenharmony_ci if (s == handle) 507141cc406Sopenharmony_ci break; 508141cc406Sopenharmony_ci prev = s; 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci if (!s) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci DBG (1, "close: invalid handle %p\n", handle); 513141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci if (s->scanning) 517141cc406Sopenharmony_ci sane_cancel (handle); 518141cc406Sopenharmony_ci write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat)); 519141cc406Sopenharmony_ci close (s->as6e_params.ctloutpipe); 520141cc406Sopenharmony_ci free (s->scan_buffer); 521141cc406Sopenharmony_ci free (s->line_buffer); 522141cc406Sopenharmony_ci if (prev) 523141cc406Sopenharmony_ci prev->next = s->next; 524141cc406Sopenharmony_ci else 525141cc406Sopenharmony_ci first_handle = s; 526141cc406Sopenharmony_ci free (handle); 527141cc406Sopenharmony_ci} 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 530141cc406Sopenharmony_civoid 531141cc406Sopenharmony_cisane_exit (void) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci AS6E_Device *next; 534141cc406Sopenharmony_ci DBG (2, "sane_exit\n"); 535141cc406Sopenharmony_ci while (first_dev != NULL) 536141cc406Sopenharmony_ci { 537141cc406Sopenharmony_ci next = first_dev->next; 538141cc406Sopenharmony_ci free (first_dev); 539141cc406Sopenharmony_ci first_dev = next; 540141cc406Sopenharmony_ci } 541141cc406Sopenharmony_ci if (devlist) 542141cc406Sopenharmony_ci free (devlist); 543141cc406Sopenharmony_ci} 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 546141cc406Sopenharmony_cistatic SANE_Status 547141cc406Sopenharmony_cias6e_open (AS6E_Scan * s) 548141cc406Sopenharmony_ci{ 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci int data_processed, exec_result, as6e_status; 551141cc406Sopenharmony_ci int ctloutpipe[2], ctlinpipe[2], datapipe[2]; 552141cc406Sopenharmony_ci char inpipe_desc[32], outpipe_desc[32], datapipe_desc[32]; 553141cc406Sopenharmony_ci pid_t fork_result; 554141cc406Sopenharmony_ci DBG (1, "as6e_open\n"); 555141cc406Sopenharmony_ci memset (inpipe_desc, '\0', sizeof (inpipe_desc)); 556141cc406Sopenharmony_ci memset (outpipe_desc, '\0', sizeof (outpipe_desc)); 557141cc406Sopenharmony_ci memset (datapipe_desc, '\0', sizeof (datapipe_desc)); 558141cc406Sopenharmony_ci if ((pipe (ctloutpipe) == 0) && (pipe (ctlinpipe) == 0) 559141cc406Sopenharmony_ci && (pipe (datapipe) == 0)) 560141cc406Sopenharmony_ci { 561141cc406Sopenharmony_ci fork_result = fork (); 562141cc406Sopenharmony_ci if (fork_result == (pid_t) - 1) 563141cc406Sopenharmony_ci { 564141cc406Sopenharmony_ci DBG (1, "Fork failure"); 565141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 566141cc406Sopenharmony_ci } 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci if (fork_result == 0) 569141cc406Sopenharmony_ci { /*in child */ 570141cc406Sopenharmony_ci sprintf (inpipe_desc, "%d", ctlinpipe[WRITEPIPE]); 571141cc406Sopenharmony_ci sprintf (outpipe_desc, "%d", ctloutpipe[READPIPE]); 572141cc406Sopenharmony_ci sprintf (datapipe_desc, "%d", datapipe[WRITEPIPE]); 573141cc406Sopenharmony_ci exec_result = 574141cc406Sopenharmony_ci execlp ("as6edriver", "as6edriver", "-s", inpipe_desc, 575141cc406Sopenharmony_ci outpipe_desc, datapipe_desc, (char *) 0); 576141cc406Sopenharmony_ci DBG (1, "The SANE backend was unable to start \"as6edriver\".\n"); 577141cc406Sopenharmony_ci DBG (1, "This must be installed in a directory in your PATH.\n"); 578141cc406Sopenharmony_ci DBG (1, "To acquire the as6edriver program,\n"); 579141cc406Sopenharmony_ci DBG (1, "go to http://as6edriver.sourceforge.net.\n"); 580141cc406Sopenharmony_ci write (ctlinpipe[WRITEPIPE], &exec_result, sizeof (exec_result)); 581141cc406Sopenharmony_ci exit (-1); 582141cc406Sopenharmony_ci } 583141cc406Sopenharmony_ci else 584141cc406Sopenharmony_ci { /*parent process */ 585141cc406Sopenharmony_ci data_processed = 586141cc406Sopenharmony_ci read (ctlinpipe[READPIPE], &as6e_status, sizeof (as6e_status)); 587141cc406Sopenharmony_ci DBG (1, "%d - read %d status = %d\n", getpid (), data_processed, 588141cc406Sopenharmony_ci as6e_status); 589141cc406Sopenharmony_ci if (as6e_status == -2) 590141cc406Sopenharmony_ci { 591141cc406Sopenharmony_ci DBG (1, "Port access denied.\n"); 592141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci if (as6e_status == -1) 595141cc406Sopenharmony_ci { 596141cc406Sopenharmony_ci DBG (1, "Could not contact scanner.\n"); 597141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 598141cc406Sopenharmony_ci } 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci if (as6e_status == 1) 601141cc406Sopenharmony_ci DBG (1, "Using nibble mode.\n"); 602141cc406Sopenharmony_ci if (as6e_status == 2) 603141cc406Sopenharmony_ci DBG (1, "Using byte mode.\n"); 604141cc406Sopenharmony_ci if (as6e_status == 3) 605141cc406Sopenharmony_ci DBG (1, "Using EPP mode.\n"); 606141cc406Sopenharmony_ci s->as6e_params.ctlinpipe = ctlinpipe[READPIPE]; 607141cc406Sopenharmony_ci s->as6e_params.ctloutpipe = ctloutpipe[WRITEPIPE]; 608141cc406Sopenharmony_ci s->as6e_params.datapipe = datapipe[READPIPE]; 609141cc406Sopenharmony_ci s->child_pid = fork_result; 610141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 611141cc406Sopenharmony_ci } /*else */ 612141cc406Sopenharmony_ci } 613141cc406Sopenharmony_ci else 614141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 615141cc406Sopenharmony_ci} 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 619141cc406Sopenharmony_ciSANE_Status 620141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 621141cc406Sopenharmony_ci{ 622141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 623141cc406Sopenharmony_ci size_t len; 624141cc406Sopenharmony_ci FILE *fp = NULL; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci DBG_INIT (); 627141cc406Sopenharmony_ci DBG (2, "sane_init (authorize %s null)\n", (authorize) ? "!=" : "=="); 628141cc406Sopenharmony_ci if (version_code) 629141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 630141cc406Sopenharmony_ci/* fp = sanei_config_open (AS6E_CONFIG_FILE);*/ 631141cc406Sopenharmony_ci if (!fp) 632141cc406Sopenharmony_ci { 633141cc406Sopenharmony_ci return (attach ("as6edriver", 0)); 634141cc406Sopenharmony_ci } 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci while (fgets (dev_name, sizeof (dev_name), fp)) 637141cc406Sopenharmony_ci { 638141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 639141cc406Sopenharmony_ci continue; 640141cc406Sopenharmony_ci len = strlen (dev_name); 641141cc406Sopenharmony_ci if (dev_name[len - 1] == '\n') 642141cc406Sopenharmony_ci dev_name[--len] = '\0'; 643141cc406Sopenharmony_ci if (!len) 644141cc406Sopenharmony_ci continue; /* ignore empty lines */ 645141cc406Sopenharmony_ci/* sanei_config_attach_matching_devices (dev_name, attach_one);*/ 646141cc406Sopenharmony_ci } 647141cc406Sopenharmony_ci fclose (fp); 648141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 649141cc406Sopenharmony_ci} 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 652141cc406Sopenharmony_ci/* 653141cc406Sopenharmony_cistatic SANE_Status 654141cc406Sopenharmony_ciattach_one (const char *dev) 655141cc406Sopenharmony_ci{ 656141cc406Sopenharmony_ci DBG (2, "attach_one\n"); 657141cc406Sopenharmony_ci attach (dev, 0); 658141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 659141cc406Sopenharmony_ci} 660141cc406Sopenharmony_ci */ 661141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 662141cc406Sopenharmony_ciSANE_Status 663141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 664141cc406Sopenharmony_ci{ 665141cc406Sopenharmony_ci static const SANE_Device **devlist = 0; 666141cc406Sopenharmony_ci AS6E_Device *dev; 667141cc406Sopenharmony_ci int i; 668141cc406Sopenharmony_ci DBG (3, "sane_get_devices (local_only = %d)\n", local_only); 669141cc406Sopenharmony_ci if (devlist) 670141cc406Sopenharmony_ci free (devlist); 671141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 672141cc406Sopenharmony_ci if (!devlist) 673141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 674141cc406Sopenharmony_ci i = 0; 675141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 676141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 677141cc406Sopenharmony_ci devlist[i++] = 0; 678141cc406Sopenharmony_ci *device_list = devlist; 679141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 680141cc406Sopenharmony_ci} 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci 683141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_cistatic size_t 686141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 687141cc406Sopenharmony_ci{ 688141cc406Sopenharmony_ci size_t size, max_size = 0; 689141cc406Sopenharmony_ci int i; 690141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 691141cc406Sopenharmony_ci { 692141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 693141cc406Sopenharmony_ci if (size > max_size) 694141cc406Sopenharmony_ci max_size = size; 695141cc406Sopenharmony_ci } 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci return (max_size); 698141cc406Sopenharmony_ci} 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_cistatic void 703141cc406Sopenharmony_ciinitialize_options_list (AS6E_Scan * s) 704141cc406Sopenharmony_ci{ 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci SANE_Int option; 707141cc406Sopenharmony_ci DBG (2, "initialize_options_list\n"); 708141cc406Sopenharmony_ci for (option = 0; option < NUM_OPTIONS; ++option) 709141cc406Sopenharmony_ci { 710141cc406Sopenharmony_ci s->options_list[option].size = sizeof (SANE_Word); 711141cc406Sopenharmony_ci s->options_list[option].cap = 712141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 713141cc406Sopenharmony_ci } 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 716141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 717141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 718141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT; 719141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; 720141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word); 721141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 722141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 723141cc406Sopenharmony_ci s->value[OPT_NUM_OPTS].w = NUM_OPTIONS; 724141cc406Sopenharmony_ci s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE; 725141cc406Sopenharmony_ci s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 726141cc406Sopenharmony_ci s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 727141cc406Sopenharmony_ci s->options_list[OPT_MODE].type = SANE_TYPE_STRING; 728141cc406Sopenharmony_ci s->options_list[OPT_MODE].size = max_string_size (mode_list); 729141cc406Sopenharmony_ci s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 730141cc406Sopenharmony_ci s->options_list[OPT_MODE].constraint.string_list = mode_list; 731141cc406Sopenharmony_ci s->value[OPT_MODE].s = strdup (mode_list[2]); 732141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 733141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 734141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 735141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT; 736141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 737141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 738141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list; 739141cc406Sopenharmony_ci s->value[OPT_RESOLUTION].w = 200; 740141cc406Sopenharmony_ci s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 741141cc406Sopenharmony_ci s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 742141cc406Sopenharmony_ci s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 743141cc406Sopenharmony_ci s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED; 744141cc406Sopenharmony_ci s->options_list[OPT_TL_X].unit = SANE_UNIT_MM; 745141cc406Sopenharmony_ci s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 746141cc406Sopenharmony_ci s->options_list[OPT_TL_X].constraint.range = &x_range; 747141cc406Sopenharmony_ci s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min; 748141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 749141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 750141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 751141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED; 752141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM; 753141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 754141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].constraint.range = &y_range; 755141cc406Sopenharmony_ci s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min; 756141cc406Sopenharmony_ci s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 757141cc406Sopenharmony_ci s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 758141cc406Sopenharmony_ci s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 759141cc406Sopenharmony_ci s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED; 760141cc406Sopenharmony_ci s->options_list[OPT_BR_X].unit = SANE_UNIT_MM; 761141cc406Sopenharmony_ci s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 762141cc406Sopenharmony_ci s->options_list[OPT_BR_X].constraint.range = &x_range; 763141cc406Sopenharmony_ci s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max; 764141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 765141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 766141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 767141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED; 768141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM; 769141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 770141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].constraint.range = &y_range; 771141cc406Sopenharmony_ci s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max; 772141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 773141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 774141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 775141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].type = SANE_TYPE_INT; 776141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE; 777141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 778141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].constraint.range = &brightness_range; 779141cc406Sopenharmony_ci s->value[OPT_BRIGHTNESS].w = 10; 780141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 781141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 782141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 783141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 784141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 785141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 786141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].constraint.range = &contrast_range; 787141cc406Sopenharmony_ci s->value[OPT_CONTRAST].w = -32; 788141cc406Sopenharmony_ci} 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 791141cc406Sopenharmony_cistatic int 792141cc406Sopenharmony_cicheck_for_driver (const char *devname) 793141cc406Sopenharmony_ci{ 794141cc406Sopenharmony_ci#define NAMESIZE 128 795141cc406Sopenharmony_ci struct stat statbuf; 796141cc406Sopenharmony_ci mode_t modes; 797141cc406Sopenharmony_ci char *path; 798141cc406Sopenharmony_ci char dir[NAMESIZE]; 799141cc406Sopenharmony_ci int count = 0, offset = 0, valid; 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci path = getenv ("PATH"); 802141cc406Sopenharmony_ci if (!path) 803141cc406Sopenharmony_ci return 0; 804141cc406Sopenharmony_ci while (path[count] != '\0') 805141cc406Sopenharmony_ci { 806141cc406Sopenharmony_ci memset (dir, '\0', sizeof (dir)); 807141cc406Sopenharmony_ci valid = 1; 808141cc406Sopenharmony_ci while ((path[count] != ':') && (path[count] != '\0')) 809141cc406Sopenharmony_ci { 810141cc406Sopenharmony_ci /* prevent writing data, which are out of bounds */ 811141cc406Sopenharmony_ci if ((unsigned int)(count - offset) < sizeof (dir)) 812141cc406Sopenharmony_ci dir[count - offset] = path[count]; 813141cc406Sopenharmony_ci else 814141cc406Sopenharmony_ci valid = 0; 815141cc406Sopenharmony_ci count++; 816141cc406Sopenharmony_ci } 817141cc406Sopenharmony_ci if (valid == 1) 818141cc406Sopenharmony_ci { 819141cc406Sopenharmony_ci char fullname[NAMESIZE]; 820141cc406Sopenharmony_ci int len = snprintf(fullname, sizeof(fullname), "%s/%s", dir, devname); 821141cc406Sopenharmony_ci if ((len > 0) && (len <= (int)sizeof(fullname))) 822141cc406Sopenharmony_ci { 823141cc406Sopenharmony_ci if (!stat (fullname, &statbuf)) 824141cc406Sopenharmony_ci { 825141cc406Sopenharmony_ci modes = statbuf.st_mode; 826141cc406Sopenharmony_ci if (S_ISREG (modes)) 827141cc406Sopenharmony_ci return (1); /* found as6edriver */ 828141cc406Sopenharmony_ci } 829141cc406Sopenharmony_ci } 830141cc406Sopenharmony_ci } 831141cc406Sopenharmony_ci if (path[count] == '\0') 832141cc406Sopenharmony_ci return (0); /* end of path --no driver found */ 833141cc406Sopenharmony_ci count++; 834141cc406Sopenharmony_ci offset = count; 835141cc406Sopenharmony_ci } 836141cc406Sopenharmony_ci return (0); 837141cc406Sopenharmony_ci} 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 841141cc406Sopenharmony_cistatic SANE_Status 842141cc406Sopenharmony_ciattach (const char *devname, AS6E_Device ** devp) 843141cc406Sopenharmony_ci{ 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci AS6E_Device *dev; 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci/* SANE_Status status; */ 848141cc406Sopenharmony_ci DBG (2, "attach\n"); 849141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 850141cc406Sopenharmony_ci { 851141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devname) == 0) 852141cc406Sopenharmony_ci { 853141cc406Sopenharmony_ci if (devp) 854141cc406Sopenharmony_ci *devp = dev; 855141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 856141cc406Sopenharmony_ci } 857141cc406Sopenharmony_ci } 858141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 859141cc406Sopenharmony_ci if (!dev) 860141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 861141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 862141cc406Sopenharmony_ci dev->sane.name = strdup (devname); 863141cc406Sopenharmony_ci if (!check_for_driver (devname)) 864141cc406Sopenharmony_ci { 865141cc406Sopenharmony_ci free (dev); 866141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 867141cc406Sopenharmony_ci } 868141cc406Sopenharmony_ci 869141cc406Sopenharmony_ci dev->sane.model = "AS6E"; 870141cc406Sopenharmony_ci dev->sane.vendor = "Artec"; 871141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 872141cc406Sopenharmony_ci ++num_devices; 873141cc406Sopenharmony_ci dev->next = first_dev; 874141cc406Sopenharmony_ci first_dev = dev; 875141cc406Sopenharmony_ci if (devp) 876141cc406Sopenharmony_ci *devp = dev; 877141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 878141cc406Sopenharmony_ci} 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 882141cc406Sopenharmony_ciSANE_Status 883141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 884141cc406Sopenharmony_ci{ 885141cc406Sopenharmony_ci SANE_Status status; 886141cc406Sopenharmony_ci AS6E_Device *dev; 887141cc406Sopenharmony_ci AS6E_Scan *s; 888141cc406Sopenharmony_ci DBG (2, "sane_open\n"); 889141cc406Sopenharmony_ci if (devicename[0]) 890141cc406Sopenharmony_ci { 891141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 892141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 893141cc406Sopenharmony_ci break; 894141cc406Sopenharmony_ci if (!dev) 895141cc406Sopenharmony_ci { 896141cc406Sopenharmony_ci status = attach (devicename, &dev); 897141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 898141cc406Sopenharmony_ci return (status); 899141cc406Sopenharmony_ci } 900141cc406Sopenharmony_ci } 901141cc406Sopenharmony_ci else 902141cc406Sopenharmony_ci { 903141cc406Sopenharmony_ci /* empty devicname -> use first device */ 904141cc406Sopenharmony_ci dev = first_dev; 905141cc406Sopenharmony_ci } 906141cc406Sopenharmony_ci if (!dev) 907141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 908141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 909141cc406Sopenharmony_ci if (!s) 910141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 911141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 912141cc406Sopenharmony_ci s->scan_buffer = malloc (SCAN_BUF_SIZE); 913141cc406Sopenharmony_ci if (!s->scan_buffer) 914141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 915141cc406Sopenharmony_ci memset (s->scan_buffer, 0, SCAN_BUF_SIZE); 916141cc406Sopenharmony_ci s->line_buffer = malloc (SCAN_BUF_SIZE); 917141cc406Sopenharmony_ci if (!s->line_buffer) 918141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 919141cc406Sopenharmony_ci memset (s->line_buffer, 0, SCAN_BUF_SIZE); 920141cc406Sopenharmony_ci status = as6e_open (s); 921141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 922141cc406Sopenharmony_ci return status; 923141cc406Sopenharmony_ci initialize_options_list (s); 924141cc406Sopenharmony_ci s->scanning = 0; 925141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 926141cc406Sopenharmony_ci s->next = first_handle; 927141cc406Sopenharmony_ci first_handle = s; 928141cc406Sopenharmony_ci *handle = s; 929141cc406Sopenharmony_ci return (status); 930141cc406Sopenharmony_ci} 931141cc406Sopenharmony_ci 932141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 933141cc406Sopenharmony_ciSANE_Status 934141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 935141cc406Sopenharmony_ci{ 936141cc406Sopenharmony_ci DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); 937141cc406Sopenharmony_ci return (SANE_STATUS_UNSUPPORTED); 938141cc406Sopenharmony_ci} 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci/*---------------------------------------------------------------------------*/ 941141cc406Sopenharmony_ciSANE_Status 942141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 943141cc406Sopenharmony_ci{ 944141cc406Sopenharmony_ci DBG (2, "sane_get_select_fd( %p, %p )\n",(void *) handle, (void *) fd); 945141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 946141cc406Sopenharmony_ci} 947