1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci ----- 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci This file is part of the canon_pp backend, supporting Canon FBX30P 42141cc406Sopenharmony_ci and NX40P scanners 43141cc406Sopenharmony_ci */ 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci#ifdef _AIX 46141cc406Sopenharmony_ci#include <lalloca.h> /* MUST come first for AIX! */ 47141cc406Sopenharmony_ci#endif 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci#define BACKEND_NAME canon_pp 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci#define THREE_BITS 0xE0 52141cc406Sopenharmony_ci#define TWO_BITS 0xC0 53141cc406Sopenharmony_ci#define MM_PER_IN 25.4 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#ifndef NOSANE 56141cc406Sopenharmony_ci#include "../include/sane/config.h" 57141cc406Sopenharmony_ci#endif 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include <string.h> 60141cc406Sopenharmony_ci#include <math.h> 61141cc406Sopenharmony_ci#include <unistd.h> 62141cc406Sopenharmony_ci#include <sys/stat.h> 63141cc406Sopenharmony_ci#include <sys/types.h> 64141cc406Sopenharmony_ci#include <stdlib.h> 65141cc406Sopenharmony_ci#include <errno.h> 66141cc406Sopenharmony_ci#include <ieee1284.h> 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci#include "../include/sane/sane.h" 69141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#include "canon_pp-dev.h" 72141cc406Sopenharmony_ci#include "canon_pp-io.h" 73141cc406Sopenharmony_ci#include "canon_pp.h" 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci/* #include "../include/sane/sanei_pio.h" */ 76141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 77141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 78141cc406Sopenharmony_ci/* #include "../include/sane/sanei_debug.h" */ 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci/* Prototypes */ 82141cc406Sopenharmony_cistatic SANE_Status init_device(struct parport *pp); 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci/* create a calibration file and give it initial values */ 85141cc406Sopenharmony_cistatic int init_cal(char *file); 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_cistatic SANE_Status fix_weights_file(CANONP_Scanner *cs); 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_cistatic SANE_Status detect_mode(CANONP_Scanner *cs); 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci/* Global Variables (ack!) */ 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci/* The first device in a linked list of devices */ 94141cc406Sopenharmony_cistatic CANONP_Scanner *first_dev = NULL; 95141cc406Sopenharmony_ci/* The default scanner to open */ 96141cc406Sopenharmony_cistatic char *def_scanner = NULL; 97141cc406Sopenharmony_ci/* The number of devices */ 98141cc406Sopenharmony_cistatic int num_devices = 0; 99141cc406Sopenharmony_ci/* ieee1284 parallel ports */ 100141cc406Sopenharmony_cistruct parport_list pl; 101141cc406Sopenharmony_ci/* leftover from the last read */ 102141cc406Sopenharmony_cistatic SANE_Byte *read_leftover = NULL; 103141cc406Sopenharmony_ci/* leftover from the last read */ 104141cc406Sopenharmony_cistatic SANE_Bool force_nibble = SANE_FALSE; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/* Constants */ 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_ci/* Colour Modes */ 109141cc406Sopenharmony_cistatic const SANE_String_Const cmodes[] = { 110141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 111141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 112141cc406Sopenharmony_ci NULL }; 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci/* bit depths */ 115141cc406Sopenharmony_cistatic const SANE_String_Const depths[] = { "8", "12", NULL }; 116141cc406Sopenharmony_ci/* resolutions */ 117141cc406Sopenharmony_cistatic const SANE_Int res300[] = {3, 75, 150, 300}; 118141cc406Sopenharmony_cistatic const SANE_Int res600[] = {4, 75, 150, 300, 600}; 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_ci/************************************************************************* 122141cc406Sopenharmony_ci * 123141cc406Sopenharmony_ci * sane_init() 124141cc406Sopenharmony_ci * 125141cc406Sopenharmony_ci * Initialises data for the list of scanners, stored in canon-p.conf. 126141cc406Sopenharmony_ci * 127141cc406Sopenharmony_ci * Scanners are not sent any commands until sane_open() is called. 128141cc406Sopenharmony_ci * 129141cc406Sopenharmony_ci *************************************************************************/ 130141cc406Sopenharmony_ci SANE_Status 131141cc406Sopenharmony_cisane_init (SANE_Int *vc, SANE_Auth_Callback cb) 132141cc406Sopenharmony_ci{ 133141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 134141cc406Sopenharmony_ci int i, tmp; 135141cc406Sopenharmony_ci int tmp_im = INITMODE_AUTO; 136141cc406Sopenharmony_ci FILE *fp; 137141cc406Sopenharmony_ci char line[81]; /* plus 1 for a null */ 138141cc406Sopenharmony_ci char *tmp_wf, *tmp_port; 139141cc406Sopenharmony_ci CANONP_Scanner *s_tmp; 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci DBG_INIT(); 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION 145141cc406Sopenharmony_ci DBG(2, ">> sane_init (version %s null, authorize %s null): " PACKAGE " " VERSION "\n", 146141cc406Sopenharmony_ci (vc) ? "!=" : "==", (cb) ? "!=" : "=="); 147141cc406Sopenharmony_ci#endif 148141cc406Sopenharmony_ci 149141cc406Sopenharmony_ci if(vc) 150141cc406Sopenharmony_ci *vc = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_ci DBG(2,"sane_init: >> ieee1284_find_ports\n"); 153141cc406Sopenharmony_ci /* Find lp ports */ 154141cc406Sopenharmony_ci tmp = ieee1284_find_ports(&pl, 0); 155141cc406Sopenharmony_ci DBG(2,"sane_init: %d << ieee1284_find_ports\n", tmp); 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci if (tmp != E1284_OK) 158141cc406Sopenharmony_ci { 159141cc406Sopenharmony_ci DBG(1,"sane_init: Error trying to get port list\n"); 160141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 161141cc406Sopenharmony_ci } 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_ci if (pl.portc < 1) 165141cc406Sopenharmony_ci { 166141cc406Sopenharmony_ci DBG(1,"sane_init: Error, no parallel ports found.\n"); 167141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 168141cc406Sopenharmony_ci } 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_ci DBG(10,"sane_init: %i parallel port(s) found.\n", pl.portc); 171141cc406Sopenharmony_ci /* Setup data structures for each port */ 172141cc406Sopenharmony_ci for(i=0; i<pl.portc; i++) 173141cc406Sopenharmony_ci { 174141cc406Sopenharmony_ci DBG(10,"sane_init: port %s\n", pl.portv[i]->name); 175141cc406Sopenharmony_ci status = init_device(pl.portv[i]); 176141cc406Sopenharmony_ci /* Now's a good time to quit if we got an error */ 177141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 178141cc406Sopenharmony_ci } 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci /* This should never be true here */ 181141cc406Sopenharmony_ci if (num_devices == 0) 182141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci /* just to be extra sure, the line will always have an end: */ 185141cc406Sopenharmony_ci line[sizeof(line)-1] = '\0'; 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci /* 188141cc406Sopenharmony_ci * Read information from config file: pixel weight location and default 189141cc406Sopenharmony_ci * port. 190141cc406Sopenharmony_ci */ 191141cc406Sopenharmony_ci if((fp = sanei_config_open(CANONP_CONFIG_FILE))) 192141cc406Sopenharmony_ci { 193141cc406Sopenharmony_ci while(sanei_config_read(line, sizeof (line) - 1, fp)) 194141cc406Sopenharmony_ci { 195141cc406Sopenharmony_ci DBG(100, "sane_init: >%s<\n", line); 196141cc406Sopenharmony_ci if(line[0] == '#') /* ignore line comments */ 197141cc406Sopenharmony_ci continue; 198141cc406Sopenharmony_ci if(!strlen(line)) 199141cc406Sopenharmony_ci continue; /* ignore empty lines */ 200141cc406Sopenharmony_ci 201141cc406Sopenharmony_ci if(strncmp(line,"calibrate ", 10) == 0) 202141cc406Sopenharmony_ci { 203141cc406Sopenharmony_ci /* warning: pointer trickyness ahead 204141cc406Sopenharmony_ci * Do not free tmp_port! */ 205141cc406Sopenharmony_ci DBG(40, "sane_init: calibrate line, %s\n", 206141cc406Sopenharmony_ci line); 207141cc406Sopenharmony_ci tmp_wf = strdup(line+10); 208141cc406Sopenharmony_ci tmp_port = strstr(tmp_wf, " "); 209141cc406Sopenharmony_ci if ((tmp_port == tmp_wf) || (tmp_port == NULL)) 210141cc406Sopenharmony_ci { 211141cc406Sopenharmony_ci /* They have used an old style config 212141cc406Sopenharmony_ci * file which does not specify scanner 213141cc406Sopenharmony_ci * Assume first port */ 214141cc406Sopenharmony_ci DBG(1, "sane_init: old config line:" 215141cc406Sopenharmony_ci "\"%s\". Please add " 216141cc406Sopenharmony_ci "a port argument.\n", 217141cc406Sopenharmony_ci line); 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci /* first_dev should never be null here 220141cc406Sopenharmony_ci * because we found at least one 221141cc406Sopenharmony_ci * parallel port above */ 222141cc406Sopenharmony_ci first_dev->weights_file = tmp_wf; 223141cc406Sopenharmony_ci DBG(100, "sane_init: Successfully " 224141cc406Sopenharmony_ci "parsed (old) cal, " 225141cc406Sopenharmony_ci "weight file is " 226141cc406Sopenharmony_ci "'%s'.\n", tmp_wf); 227141cc406Sopenharmony_ci continue; 228141cc406Sopenharmony_ci 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci /* Now find which scanner wants 232141cc406Sopenharmony_ci * this calibration file */ 233141cc406Sopenharmony_ci s_tmp = first_dev; 234141cc406Sopenharmony_ci DBG(100, "sane_init: Finding scanner on port " 235141cc406Sopenharmony_ci "'%s'\n", tmp_port+1); 236141cc406Sopenharmony_ci while (s_tmp != NULL) 237141cc406Sopenharmony_ci { 238141cc406Sopenharmony_ci if (!strcmp(s_tmp->params.port->name, 239141cc406Sopenharmony_ci tmp_port+1)) 240141cc406Sopenharmony_ci { 241141cc406Sopenharmony_ci DBG(100, "sane_init: Found!\n"); 242141cc406Sopenharmony_ci /* Now terminate the weight 243141cc406Sopenharmony_ci * file string */ 244141cc406Sopenharmony_ci *tmp_port = '\0'; 245141cc406Sopenharmony_ci s_tmp->weights_file = tmp_wf; 246141cc406Sopenharmony_ci DBG(100, "sane_init: Parsed " 247141cc406Sopenharmony_ci "cal, for port" 248141cc406Sopenharmony_ci " '%s', weight" 249141cc406Sopenharmony_ci " file is '%s'" 250141cc406Sopenharmony_ci ".\n", 251141cc406Sopenharmony_ci s_tmp->params. 252141cc406Sopenharmony_ci port->name, 253141cc406Sopenharmony_ci tmp_wf); 254141cc406Sopenharmony_ci break; 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci s_tmp = s_tmp->next; 257141cc406Sopenharmony_ci } 258141cc406Sopenharmony_ci if (s_tmp == NULL) 259141cc406Sopenharmony_ci { 260141cc406Sopenharmony_ci /* we made it all the way through the 261141cc406Sopenharmony_ci * list and didn't find the port */ 262141cc406Sopenharmony_ci free(tmp_wf); 263141cc406Sopenharmony_ci DBG(10, "sane_init: calibrate line is " 264141cc406Sopenharmony_ci "for unknown port!\n"); 265141cc406Sopenharmony_ci } 266141cc406Sopenharmony_ci continue; 267141cc406Sopenharmony_ci } 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci if(strncmp(line,"ieee1284 ", 9) == 0) 271141cc406Sopenharmony_ci { 272141cc406Sopenharmony_ci DBG(100, "sane_init: Successfully parsed " 273141cc406Sopenharmony_ci "default scanner.\n"); 274141cc406Sopenharmony_ci /* this will be our default scanner */ 275141cc406Sopenharmony_ci def_scanner = strdup(line+9); 276141cc406Sopenharmony_ci continue; 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci if(strncmp(line,"force_nibble", 12) == 0) 280141cc406Sopenharmony_ci { 281141cc406Sopenharmony_ci DBG(100, "sane_init: force_nibble " 282141cc406Sopenharmony_ci "requested.\n"); 283141cc406Sopenharmony_ci force_nibble = SANE_TRUE; 284141cc406Sopenharmony_ci continue; 285141cc406Sopenharmony_ci } 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci if(strncmp(line,"init_mode ", 10) == 0) 288141cc406Sopenharmony_ci { 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci /* parse what sort of initialisation mode to 291141cc406Sopenharmony_ci * use */ 292141cc406Sopenharmony_ci if (strncmp(line+10, "FB620P", 6) == 0) 293141cc406Sopenharmony_ci tmp_im = INITMODE_20P; 294141cc406Sopenharmony_ci else if (strncmp(line+10, "FB630P", 6) == 0) 295141cc406Sopenharmony_ci tmp_im = INITMODE_30P; 296141cc406Sopenharmony_ci else if (strncmp(line+10, "AUTO", 4) == 0) 297141cc406Sopenharmony_ci tmp_im = INITMODE_AUTO; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci /* now work out which port it blongs to */ 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci tmp_port = strstr(line+10, " "); 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci if (tmp_port == NULL) 304141cc406Sopenharmony_ci { 305141cc406Sopenharmony_ci /* first_dev should never be null here 306141cc406Sopenharmony_ci * because we found at least one 307141cc406Sopenharmony_ci * parallel port above */ 308141cc406Sopenharmony_ci first_dev->init_mode = tmp_im; 309141cc406Sopenharmony_ci DBG(100, "sane_init: Parsed init-1.\n"); 310141cc406Sopenharmony_ci continue; 311141cc406Sopenharmony_ci } 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ci s_tmp = first_dev; 315141cc406Sopenharmony_ci while (s_tmp != NULL) 316141cc406Sopenharmony_ci { 317141cc406Sopenharmony_ci if (!strcmp(s_tmp->params.port->name, 318141cc406Sopenharmony_ci tmp_port+1)) 319141cc406Sopenharmony_ci { 320141cc406Sopenharmony_ci s_tmp->init_mode = tmp_im; 321141cc406Sopenharmony_ci DBG(100, "sane_init: Parsed " 322141cc406Sopenharmony_ci "init.\n"); 323141cc406Sopenharmony_ci break; 324141cc406Sopenharmony_ci } 325141cc406Sopenharmony_ci s_tmp = s_tmp->next; 326141cc406Sopenharmony_ci } 327141cc406Sopenharmony_ci if (s_tmp == NULL) 328141cc406Sopenharmony_ci { 329141cc406Sopenharmony_ci /* we made it all the way through the 330141cc406Sopenharmony_ci * list and didn't find the port */ 331141cc406Sopenharmony_ci DBG(10, "sane_init: init_mode line is " 332141cc406Sopenharmony_ci "for unknown port!\n"); 333141cc406Sopenharmony_ci } 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci continue; 336141cc406Sopenharmony_ci } 337141cc406Sopenharmony_ci DBG(1, "sane_init: Unknown configuration command!"); 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci } 340141cc406Sopenharmony_ci fclose (fp); 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci /* There should now be a LL of ports starting at first_dev */ 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci for (s_tmp = first_dev; s_tmp != NULL; s_tmp = s_tmp->next) 346141cc406Sopenharmony_ci { 347141cc406Sopenharmony_ci /* Assume there's no scanner present until proven otherwise */ 348141cc406Sopenharmony_ci s_tmp->scanner_present = SANE_FALSE; 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_ci /* Try to detect if there's a scanner there, and if so, 351141cc406Sopenharmony_ci * what sort of scanner it is */ 352141cc406Sopenharmony_ci status = detect_mode(s_tmp); 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 355141cc406Sopenharmony_ci { 356141cc406Sopenharmony_ci DBG(10,"sane_init: Error detecting port mode on %s!\n", 357141cc406Sopenharmony_ci s_tmp->params.port->name); 358141cc406Sopenharmony_ci s_tmp->scanner_present = SANE_FALSE; 359141cc406Sopenharmony_ci continue; 360141cc406Sopenharmony_ci } 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci /* detect_mode succeeded, so the port is open. This beholdens 363141cc406Sopenharmony_ci * us to call ieee1284_close in any of the remaining error 364141cc406Sopenharmony_ci * cases in this loop. */ 365141cc406Sopenharmony_ci#if 0 366141cc406Sopenharmony_ci tmp = sanei_canon_pp_detect(s_tmp->params.port, 367141cc406Sopenharmony_ci s_tmp->init_mode); 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci 370141cc406Sopenharmony_ci if (tmp && (s_tmp->ieee1284_mode != M1284_NIBBLE)) 371141cc406Sopenharmony_ci { 372141cc406Sopenharmony_ci /* A failure, try again in nibble mode... */ 373141cc406Sopenharmony_ci DBG(1, "sane_init: Failed on ECP mode, falling " 374141cc406Sopenharmony_ci "back to nibble mode\n"); 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci s_tmp->ieee1284_mode = M1284_NIBBLE; 377141cc406Sopenharmony_ci sanei_canon_pp_set_ieee1284_mode(s_tmp->ieee1284_mode); 378141cc406Sopenharmony_ci tmp = sanei_canon_pp_detect(s_tmp->params.port, 379141cc406Sopenharmony_ci s_tmp->init_mode); 380141cc406Sopenharmony_ci } 381141cc406Sopenharmony_ci /* still no go? */ 382141cc406Sopenharmony_ci if (tmp) 383141cc406Sopenharmony_ci { 384141cc406Sopenharmony_ci DBG(1,"sane_init: couldn't find a scanner on port " 385141cc406Sopenharmony_ci "%s\n", s_tmp->params.port->name); 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci ieee1284_close(s_tmp->params.port); 388141cc406Sopenharmony_ci continue; 389141cc406Sopenharmony_ci } 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci#endif 392141cc406Sopenharmony_ci /* all signs point to yes, try it out */ 393141cc406Sopenharmony_ci if (ieee1284_claim(s_tmp->params.port) != E1284_OK) { 394141cc406Sopenharmony_ci DBG(10, "sane_init: Couldn't claim port %s.\n", 395141cc406Sopenharmony_ci s_tmp->params.port->name); 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_ci ieee1284_close(s_tmp->params.port); 398141cc406Sopenharmony_ci continue; 399141cc406Sopenharmony_ci } 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci DBG(2, "sane_init: >> initialise\n"); 402141cc406Sopenharmony_ci tmp = sanei_canon_pp_initialise(&(s_tmp->params), 403141cc406Sopenharmony_ci s_tmp->init_mode); 404141cc406Sopenharmony_ci DBG(2, "sane_init: << %d initialise\n", tmp); 405141cc406Sopenharmony_ci if (tmp) { 406141cc406Sopenharmony_ci DBG(10, "sane_init: Couldn't contact scanner on port " 407141cc406Sopenharmony_ci "%s. Probably no scanner there?\n", 408141cc406Sopenharmony_ci s_tmp->params.port->name); 409141cc406Sopenharmony_ci ieee1284_release(s_tmp->params.port); 410141cc406Sopenharmony_ci ieee1284_close(s_tmp->params.port); 411141cc406Sopenharmony_ci s_tmp->scanner_present = SANE_FALSE; 412141cc406Sopenharmony_ci continue; 413141cc406Sopenharmony_ci } 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* put it back to sleep until we're ready to 416141cc406Sopenharmony_ci * open for business again - this will only work 417141cc406Sopenharmony_ci * if we actually have a scanner there! */ 418141cc406Sopenharmony_ci DBG(100, "sane_init: And back to sleep again\n"); 419141cc406Sopenharmony_ci sanei_canon_pp_sleep_scanner(s_tmp->params.port); 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci /* leave the port open but not claimed - this is regardless 422141cc406Sopenharmony_ci * of the return value of initialise */ 423141cc406Sopenharmony_ci ieee1284_release(s_tmp->params.port); 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci /* Finally, we're sure there's a scanner there! Now we 426141cc406Sopenharmony_ci * just have to load the weights file...*/ 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci if (fix_weights_file(s_tmp) != SANE_STATUS_GOOD) { 429141cc406Sopenharmony_ci DBG(1, "sane_init: Eeek! fix_weights_file failed for " 430141cc406Sopenharmony_ci "scanner on port %s!\n", 431141cc406Sopenharmony_ci s_tmp->params.port->name); 432141cc406Sopenharmony_ci /* non-fatal.. scans will look ugly as sin unless 433141cc406Sopenharmony_ci * they calibrate */ 434141cc406Sopenharmony_ci } 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci /* Cocked, locked and ready to rock */ 437141cc406Sopenharmony_ci s_tmp->hw.model = s_tmp->params.name; 438141cc406Sopenharmony_ci s_tmp->scanner_present = SANE_TRUE; 439141cc406Sopenharmony_ci } 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci DBG(2, "<< sane_init\n"); 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci return status; 444141cc406Sopenharmony_ci} 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci/************************************************************************* 448141cc406Sopenharmony_ci * 449141cc406Sopenharmony_ci * sane_get_devices() 450141cc406Sopenharmony_ci * 451141cc406Sopenharmony_ci * Gives a list of devices available. In our case, that's the linked 452141cc406Sopenharmony_ci * list produced by sane_init. 453141cc406Sopenharmony_ci * 454141cc406Sopenharmony_ci *************************************************************************/ 455141cc406Sopenharmony_ci SANE_Status 456141cc406Sopenharmony_cisane_get_devices (const SANE_Device ***dl, SANE_Bool local) 457141cc406Sopenharmony_ci{ 458141cc406Sopenharmony_ci static const SANE_Device **devlist; 459141cc406Sopenharmony_ci CANONP_Scanner *dev; 460141cc406Sopenharmony_ci int i; 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci DBG(2, ">> sane_get_devices (%p, %d)\n", (const void*)dl, local); 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci if (dl == NULL) 465141cc406Sopenharmony_ci { 466141cc406Sopenharmony_ci DBG(1, "sane_get_devices: ERROR: devlist pointer is NULL!"); 467141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 468141cc406Sopenharmony_ci } 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci if (devlist != NULL) 471141cc406Sopenharmony_ci { 472141cc406Sopenharmony_ci /* this has been called already */ 473141cc406Sopenharmony_ci *dl = devlist; 474141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 475141cc406Sopenharmony_ci } 476141cc406Sopenharmony_ci devlist = malloc((num_devices + 1) * sizeof(*devlist)); 477141cc406Sopenharmony_ci if (devlist == NULL) 478141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci i = 0; 481141cc406Sopenharmony_ci for (dev = first_dev; dev != NULL; dev = dev->next) 482141cc406Sopenharmony_ci { 483141cc406Sopenharmony_ci if (dev->scanner_present == SANE_TRUE) 484141cc406Sopenharmony_ci { 485141cc406Sopenharmony_ci devlist[i] = &(dev->hw); 486141cc406Sopenharmony_ci i++; 487141cc406Sopenharmony_ci } 488141cc406Sopenharmony_ci } 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci devlist[i] = NULL; 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci *dl = devlist; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci DBG(2, "<< sane_get_devices\n"); 495141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 496141cc406Sopenharmony_ci} 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci/************************************************************************* 500141cc406Sopenharmony_ci * 501141cc406Sopenharmony_ci * sane_open() 502141cc406Sopenharmony_ci * 503141cc406Sopenharmony_ci * Open the scanner described by name. Ask libieee1284 to claim the port 504141cc406Sopenharmony_ci * and call Simon's init code. Also configure data structures. 505141cc406Sopenharmony_ci * 506141cc406Sopenharmony_ci *************************************************************************/ 507141cc406Sopenharmony_ci SANE_Status 508141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle *h) 509141cc406Sopenharmony_ci{ 510141cc406Sopenharmony_ci CANONP_Scanner *cs; 511141cc406Sopenharmony_ci SANE_Range *tmp_range; 512141cc406Sopenharmony_ci int tmp; 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci DBG(2, ">> sane_open (h=%p, name=\"%s\")\n", (void *)h, name); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci if ((h == NULL) || (name == NULL)) 517141cc406Sopenharmony_ci { 518141cc406Sopenharmony_ci DBG(2,"sane_open: Null pointer received!\n"); 519141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 520141cc406Sopenharmony_ci } 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci if (!strlen(name)) 523141cc406Sopenharmony_ci { 524141cc406Sopenharmony_ci DBG(10,"sane_open: Empty name given, assuming first/" 525141cc406Sopenharmony_ci "default scanner\n"); 526141cc406Sopenharmony_ci if (def_scanner == NULL) 527141cc406Sopenharmony_ci name = first_dev->params.port->name; 528141cc406Sopenharmony_ci else 529141cc406Sopenharmony_ci name = def_scanner; 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci /* we don't _have_ to fit this name, so _don't_ fail if it's 532141cc406Sopenharmony_ci * not there */ 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci cs = first_dev; 535141cc406Sopenharmony_ci while((cs != NULL) && strcmp(cs->params.port->name, name)) 536141cc406Sopenharmony_ci cs = cs->next; 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci /* if we didn't find the port they want, or there's no scanner 539141cc406Sopenharmony_ci * there, we just want to find _any_ scanner */ 540141cc406Sopenharmony_ci if ((cs == NULL) || (cs->scanner_present != SANE_TRUE)) 541141cc406Sopenharmony_ci { 542141cc406Sopenharmony_ci cs = first_dev; 543141cc406Sopenharmony_ci while((cs != NULL) && 544141cc406Sopenharmony_ci (cs->scanner_present == SANE_FALSE)) 545141cc406Sopenharmony_ci cs = cs->next; 546141cc406Sopenharmony_ci } 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci } else { 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci /* they're dead keen for this name, so _do_ fail if it's 551141cc406Sopenharmony_ci * not there */ 552141cc406Sopenharmony_ci cs = first_dev; 553141cc406Sopenharmony_ci while((cs != NULL) && strcmp(cs->params.port->name, name)) 554141cc406Sopenharmony_ci cs = cs->next; 555141cc406Sopenharmony_ci } 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci if (cs == NULL) 559141cc406Sopenharmony_ci { 560141cc406Sopenharmony_ci DBG(2,"sane_open: No scanner found or requested port " 561141cc406Sopenharmony_ci "doesn't exist (%s)\n", name); 562141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 563141cc406Sopenharmony_ci } 564141cc406Sopenharmony_ci if (cs->scanner_present == SANE_FALSE) 565141cc406Sopenharmony_ci { 566141cc406Sopenharmony_ci DBG(1,"sane_open: Request to open port with no scanner " 567141cc406Sopenharmony_ci "(%s)\n", name); 568141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 569141cc406Sopenharmony_ci } 570141cc406Sopenharmony_ci if (cs->opened == SANE_TRUE) 571141cc406Sopenharmony_ci { 572141cc406Sopenharmony_ci DBG(2,"sane_open; Oi!, That scanner's already open.\n"); 573141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 574141cc406Sopenharmony_ci } 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci /* If the scanner has already been opened once, we don't have to do 577141cc406Sopenharmony_ci * this setup again */ 578141cc406Sopenharmony_ci if (cs->setup == SANE_TRUE) 579141cc406Sopenharmony_ci { 580141cc406Sopenharmony_ci cs->opened = SANE_TRUE; 581141cc406Sopenharmony_ci *h = (SANE_Handle)cs; 582141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 583141cc406Sopenharmony_ci } 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci tmp = ieee1284_claim(cs->params.port); 586141cc406Sopenharmony_ci if (tmp != E1284_OK) { 587141cc406Sopenharmony_ci DBG(1, "sane_open: Could not claim port!\n"); 588141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 589141cc406Sopenharmony_ci } 590141cc406Sopenharmony_ci 591141cc406Sopenharmony_ci /* I put the scanner to sleep before, better wake it back up */ 592141cc406Sopenharmony_ci 593141cc406Sopenharmony_ci DBG(2, "sane_open: >> initialise\n"); 594141cc406Sopenharmony_ci tmp = sanei_canon_pp_initialise(&(cs->params), cs->init_mode); 595141cc406Sopenharmony_ci DBG(2, "sane_open: << %d initialise\n", tmp); 596141cc406Sopenharmony_ci if (tmp != 0) { 597141cc406Sopenharmony_ci DBG(1, "sane_open: initialise returned %d, something is " 598141cc406Sopenharmony_ci "wrong with the scanner!\n", tmp); 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci DBG(1, "sane_open: Can't contact scanner. Try power " 601141cc406Sopenharmony_ci "cycling scanner, and unplug any " 602141cc406Sopenharmony_ci "printers\n"); 603141cc406Sopenharmony_ci ieee1284_release(cs->params.port); 604141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 605141cc406Sopenharmony_ci } 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci if (cs->weights_file != NULL) 608141cc406Sopenharmony_ci DBG(2, "sane_open: >> load_weights(%s, %p)\n", 609141cc406Sopenharmony_ci cs->weights_file, 610141cc406Sopenharmony_ci (const void *)(&(cs->params))); 611141cc406Sopenharmony_ci else 612141cc406Sopenharmony_ci DBG(2, "sane_open: >> load_weights(NULL, %p)\n", 613141cc406Sopenharmony_ci (const void *)(&(cs->params))); 614141cc406Sopenharmony_ci tmp = sanei_canon_pp_load_weights(cs->weights_file, &(cs->params)); 615141cc406Sopenharmony_ci DBG(2, "sane_open: << %d load_weights\n", tmp); 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci if (tmp != 0) { 618141cc406Sopenharmony_ci DBG(1, "sane_open: WARNING: Error on load_weights: " 619141cc406Sopenharmony_ci "returned %d. This could be due to a corrupt " 620141cc406Sopenharmony_ci "calibration file. Try recalibrating and if " 621141cc406Sopenharmony_ci "problems persist, please report the problem " 622141cc406Sopenharmony_ci "to the canon_pp maintainer\n", tmp); 623141cc406Sopenharmony_ci cs->cal_valid = SANE_FALSE; 624141cc406Sopenharmony_ci } else { 625141cc406Sopenharmony_ci cs->cal_valid = SANE_TRUE; 626141cc406Sopenharmony_ci DBG(10, "sane_open: loadweights successful, uploading gamma" 627141cc406Sopenharmony_ci " profile...\n"); 628141cc406Sopenharmony_ci tmp = sanei_canon_pp_adjust_gamma(&(cs->params)); 629141cc406Sopenharmony_ci if (tmp != 0) 630141cc406Sopenharmony_ci DBG(1, "sane_open: WARNING: adjust_gamma returned " 631141cc406Sopenharmony_ci "%d!\n", tmp); 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci DBG(10, "sane_open: after adjust_gamma Status = %i\n", 634141cc406Sopenharmony_ci sanei_canon_pp_check_status(cs->params.port)); 635141cc406Sopenharmony_ci } 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci /* Configure ranges etc */ 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci /* Resolution - determined by magic number */ 641141cc406Sopenharmony_ci 642141cc406Sopenharmony_ci if (cs->params.scanheadwidth == 2552) 643141cc406Sopenharmony_ci cs->opt[OPT_RESOLUTION].constraint.word_list = res300; 644141cc406Sopenharmony_ci else 645141cc406Sopenharmony_ci cs->opt[OPT_RESOLUTION].constraint.word_list = res600; 646141cc406Sopenharmony_ci 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci /* TL-X */ 649141cc406Sopenharmony_ci if(!(tmp_range = malloc(sizeof(*tmp_range)))) 650141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 651141cc406Sopenharmony_ci (*tmp_range).min = 0; 652141cc406Sopenharmony_ci (*tmp_range).max = 215; 653141cc406Sopenharmony_ci cs->opt[OPT_TL_X].constraint.range = tmp_range; 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci /* TL-Y */ 656141cc406Sopenharmony_ci if(!(tmp_range = malloc(sizeof(*tmp_range)))) 657141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 658141cc406Sopenharmony_ci (*tmp_range).min = 0; 659141cc406Sopenharmony_ci (*tmp_range).max = 296; 660141cc406Sopenharmony_ci cs->opt[OPT_TL_Y].constraint.range = tmp_range; 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci /* BR-X */ 663141cc406Sopenharmony_ci if(!(tmp_range = malloc(sizeof(*tmp_range)))) 664141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 665141cc406Sopenharmony_ci (*tmp_range).min = 3; 666141cc406Sopenharmony_ci (*tmp_range).max = 216; 667141cc406Sopenharmony_ci cs->opt[OPT_BR_X].constraint.range = tmp_range; 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci /* BR-Y */ 670141cc406Sopenharmony_ci if(!(tmp_range = malloc(sizeof(*tmp_range)))) 671141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 672141cc406Sopenharmony_ci (*tmp_range).min = 1; 673141cc406Sopenharmony_ci (*tmp_range).max = 297; 674141cc406Sopenharmony_ci cs->opt[OPT_BR_Y].constraint.range = tmp_range; 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci cs->opened = SANE_TRUE; 678141cc406Sopenharmony_ci cs->setup = SANE_TRUE; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci *h = (SANE_Handle)cs; 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci DBG(2, "<< sane_open\n"); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 685141cc406Sopenharmony_ci} 686141cc406Sopenharmony_ci 687141cc406Sopenharmony_ci/************************************************************************* 688141cc406Sopenharmony_ci * 689141cc406Sopenharmony_ci * sane_get_option_descriptor() 690141cc406Sopenharmony_ci * 691141cc406Sopenharmony_ci * Return the structure for option number opt. 692141cc406Sopenharmony_ci * 693141cc406Sopenharmony_ci *************************************************************************/ 694141cc406Sopenharmony_ci const SANE_Option_Descriptor * 695141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle h, SANE_Int opt) 696141cc406Sopenharmony_ci{ 697141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 698141cc406Sopenharmony_ci /*DBG(2, ">> sane_get_option_descriptor (h=%p, opt=%d)\n", h, opt);*/ 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci if (h == NULL) { 701141cc406Sopenharmony_ci DBG(10,"sane_get_option_descriptor: WARNING: h==NULL!\n"); 702141cc406Sopenharmony_ci return NULL; 703141cc406Sopenharmony_ci } 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci if ((unsigned)opt >= NUM_OPTIONS) { 706141cc406Sopenharmony_ci DBG(10,"sane_get_option_descriptor: Note: opt >= " 707141cc406Sopenharmony_ci "NUM_OPTIONS!\n"); 708141cc406Sopenharmony_ci return NULL; 709141cc406Sopenharmony_ci } 710141cc406Sopenharmony_ci 711141cc406Sopenharmony_ci if (cs->opened == SANE_FALSE) 712141cc406Sopenharmony_ci { 713141cc406Sopenharmony_ci DBG(1,"sane_get_option_descriptor: That scanner (%p) ain't " 714141cc406Sopenharmony_ci "open yet\n", h); 715141cc406Sopenharmony_ci return NULL; 716141cc406Sopenharmony_ci } 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci /*DBG(2, "<< sane_get_option_descriptor\n");*/ 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci return (cs->opt + opt); 721141cc406Sopenharmony_ci} 722141cc406Sopenharmony_ci 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci/************************************************************************* 725141cc406Sopenharmony_ci * 726141cc406Sopenharmony_ci * sane_control_option() 727141cc406Sopenharmony_ci * 728141cc406Sopenharmony_ci * Set a value for one of the options provided. 729141cc406Sopenharmony_ci * 730141cc406Sopenharmony_ci *************************************************************************/ 731141cc406Sopenharmony_ciSANE_Status 732141cc406Sopenharmony_cisane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, 733141cc406Sopenharmony_ci void *val, SANE_Word *info) 734141cc406Sopenharmony_ci{ 735141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 736141cc406Sopenharmony_ci int i = 0, tmp, maxresi; 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci DBG(2, ">> sane_control_option (h=%p, opt=%d, act=%d)\n", 739141cc406Sopenharmony_ci h,opt,act); 740141cc406Sopenharmony_ci /* Do some sanity checks on the parameters 741141cc406Sopenharmony_ci * note that val can be null for buttons */ 742141cc406Sopenharmony_ci if ((h == NULL) || ((val == NULL) && (opt != OPT_CAL))) 743141cc406Sopenharmony_ci /* || (info == NULL)) - Don't check this any more.. 744141cc406Sopenharmony_ci * frontends seem to like passing a null */ 745141cc406Sopenharmony_ci { 746141cc406Sopenharmony_ci DBG(1,"sane_control_option: Frontend passed me a null! " 747141cc406Sopenharmony_ci "(h=%p,val=%p,info=%p)\n",(void*)h, 748141cc406Sopenharmony_ci val,(void*)info); 749141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 750141cc406Sopenharmony_ci } 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci if (((unsigned)opt) >= NUM_OPTIONS) 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci DBG(1,"sane_control_option: I don't do option %d.\n", opt); 755141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 756141cc406Sopenharmony_ci } 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci if (cs->opened == SANE_FALSE) 759141cc406Sopenharmony_ci { 760141cc406Sopenharmony_ci DBG(1,"sane_control_option: That scanner (%p) ain't " 761141cc406Sopenharmony_ci "open yet\n", h); 762141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 763141cc406Sopenharmony_ci } 764141cc406Sopenharmony_ci 765141cc406Sopenharmony_ci if (cs->scanning == SANE_TRUE) 766141cc406Sopenharmony_ci { 767141cc406Sopenharmony_ci DBG(1,"sane_control_option: That scanner (%p) is scanning!\n", 768141cc406Sopenharmony_ci h); 769141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 770141cc406Sopenharmony_ci } 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci switch(act) 773141cc406Sopenharmony_ci { 774141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 775141cc406Sopenharmony_ci switch (opt) 776141cc406Sopenharmony_ci { 777141cc406Sopenharmony_ci case OPT_COLOUR_MODE: 778141cc406Sopenharmony_ci strcpy((char *)val, 779141cc406Sopenharmony_ci cmodes[cs->vals[opt]]); 780141cc406Sopenharmony_ci break; 781141cc406Sopenharmony_ci case OPT_DEPTH: 782141cc406Sopenharmony_ci strcpy((char *)val, 783141cc406Sopenharmony_ci depths[cs->vals[opt]]); 784141cc406Sopenharmony_ci break; 785141cc406Sopenharmony_ci case OPT_RESOLUTION: 786141cc406Sopenharmony_ci *((int *)val) = res600[cs->vals[opt]]; 787141cc406Sopenharmony_ci break; 788141cc406Sopenharmony_ci default: 789141cc406Sopenharmony_ci *((int *)val) = cs->vals[opt]; 790141cc406Sopenharmony_ci break; 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci break; 793141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 794141cc406Sopenharmony_ci /* val has been checked for NULL if opt != OPT_CAL */ 795141cc406Sopenharmony_ci if (opt != OPT_CAL) i = *((int *)val); 796141cc406Sopenharmony_ci if (info != NULL) *info = 0; 797141cc406Sopenharmony_ci switch (opt) { 798141cc406Sopenharmony_ci case OPT_NUM_OPTIONS: 799141cc406Sopenharmony_ci /* you can't set that! */ 800141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 801141cc406Sopenharmony_ci case OPT_RESOLUTION: 802141cc406Sopenharmony_ci i = cs->vals[opt]; 803141cc406Sopenharmony_ci cs->vals[opt] = 1; 804141cc406Sopenharmony_ci maxresi = cs->opt[OPT_RESOLUTION]. 805141cc406Sopenharmony_ci constraint.word_list[0]; 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci while ((cs->vals[opt] <= maxresi) && 808141cc406Sopenharmony_ci (res600[cs->vals[opt]] 809141cc406Sopenharmony_ci < *((int *)val))) 810141cc406Sopenharmony_ci { 811141cc406Sopenharmony_ci cs->vals[opt] += 1; 812141cc406Sopenharmony_ci } 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci if (res600[cs->vals[opt]] != 815141cc406Sopenharmony_ci *((int *)val)) 816141cc406Sopenharmony_ci { 817141cc406Sopenharmony_ci if (info != NULL) *info |= 818141cc406Sopenharmony_ci SANE_INFO_INEXACT; 819141cc406Sopenharmony_ci } 820141cc406Sopenharmony_ci break; 821141cc406Sopenharmony_ci case OPT_COLOUR_MODE: 822141cc406Sopenharmony_ci cs->vals[opt] = 0; 823141cc406Sopenharmony_ci while ((cmodes[cs->vals[opt]] != NULL) 824141cc406Sopenharmony_ci && strcmp(cmodes[cs->vals[opt]], 825141cc406Sopenharmony_ci (char *)val)) 826141cc406Sopenharmony_ci { 827141cc406Sopenharmony_ci cs->vals[opt] += 1; 828141cc406Sopenharmony_ci } 829141cc406Sopenharmony_ci if (info != NULL) *info |= 830141cc406Sopenharmony_ci SANE_INFO_RELOAD_PARAMS; 831141cc406Sopenharmony_ci break; 832141cc406Sopenharmony_ci case OPT_DEPTH: 833141cc406Sopenharmony_ci cs->vals[opt] = 0; 834141cc406Sopenharmony_ci while ((depths[cs->vals[opt]] != NULL) 835141cc406Sopenharmony_ci && strcmp(depths[cs->vals[opt]], 836141cc406Sopenharmony_ci (char *)val)) 837141cc406Sopenharmony_ci { 838141cc406Sopenharmony_ci cs->vals[opt] += 1; 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci if (info != NULL) *info |= 841141cc406Sopenharmony_ci SANE_INFO_RELOAD_PARAMS; 842141cc406Sopenharmony_ci break; 843141cc406Sopenharmony_ci case OPT_TL_X: 844141cc406Sopenharmony_ci case OPT_BR_X: 845141cc406Sopenharmony_ci case OPT_TL_Y: 846141cc406Sopenharmony_ci case OPT_BR_Y: 847141cc406Sopenharmony_ci if ((i<cs->opt[opt].constraint.range->min) || (i>cs->opt[opt].constraint.range->max)) 848141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 849141cc406Sopenharmony_ci cs->vals[opt] = i; 850141cc406Sopenharmony_ci break; 851141cc406Sopenharmony_ci case OPT_CAL: 852141cc406Sopenharmony_ci /* Call the calibration code */ 853141cc406Sopenharmony_ci if ((cs->weights_file==NULL) || 854141cc406Sopenharmony_ci cs->cal_readonly 855141cc406Sopenharmony_ci ) 856141cc406Sopenharmony_ci DBG(2, ">> calibrate(x, " 857141cc406Sopenharmony_ci "NULL)\n"); 858141cc406Sopenharmony_ci else 859141cc406Sopenharmony_ci DBG(2, ">> calibrate(x," 860141cc406Sopenharmony_ci "%s)\n", 861141cc406Sopenharmony_ci cs->weights_file); 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci if (cs->cal_readonly) tmp = 864141cc406Sopenharmony_ci sanei_canon_pp_calibrate( 865141cc406Sopenharmony_ci &(cs->params), 866141cc406Sopenharmony_ci NULL); 867141cc406Sopenharmony_ci else tmp = sanei_canon_pp_calibrate( 868141cc406Sopenharmony_ci &(cs->params), 869141cc406Sopenharmony_ci cs->weights_file); 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci DBG(2, "<< %d calibrate\n", 872141cc406Sopenharmony_ci tmp); 873141cc406Sopenharmony_ci if (tmp != 0) { 874141cc406Sopenharmony_ci DBG(1, "sane_control_option: " 875141cc406Sopenharmony_ci "WARNING: " 876141cc406Sopenharmony_ci "calibrate " 877141cc406Sopenharmony_ci "returned %d!", 878141cc406Sopenharmony_ci tmp); 879141cc406Sopenharmony_ci cs->cal_valid = 880141cc406Sopenharmony_ci SANE_FALSE; 881141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 882141cc406Sopenharmony_ci } else { 883141cc406Sopenharmony_ci cs->cal_valid = 884141cc406Sopenharmony_ci SANE_TRUE; 885141cc406Sopenharmony_ci } 886141cc406Sopenharmony_ci 887141cc406Sopenharmony_ci break; 888141cc406Sopenharmony_ci /*case OPT_PREVIEW: 889141cc406Sopenharmony_ci if (i) cs->vals[opt] = 1; 890141cc406Sopenharmony_ci else cs->vals[opt] = 0; 891141cc406Sopenharmony_ci break;*/ 892141cc406Sopenharmony_ci default: 893141cc406Sopenharmony_ci /* Should never happen */ 894141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 895141cc406Sopenharmony_ci } 896141cc406Sopenharmony_ci break; 897141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 898141cc406Sopenharmony_ci DBG(2, "sane_control_option: attempt at " 899141cc406Sopenharmony_ci "automatic control! (unsupported)\n"); 900141cc406Sopenharmony_ci /* Auto? are they mad? I'm not that smart! */ 901141cc406Sopenharmony_ci /* fall through. */ 902141cc406Sopenharmony_ci default: 903141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 904141cc406Sopenharmony_ci } 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci 907141cc406Sopenharmony_ci DBG(2, "<< sane_control_option\n"); 908141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 909141cc406Sopenharmony_ci} 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci 912141cc406Sopenharmony_ci/************************************************************************* 913141cc406Sopenharmony_ci * 914141cc406Sopenharmony_ci * sane_get_parameters() 915141cc406Sopenharmony_ci * 916141cc406Sopenharmony_ci * Get information about the next packet. If a scan hasn't started, results 917141cc406Sopenharmony_ci * only have to be best guesses. 918141cc406Sopenharmony_ci * 919141cc406Sopenharmony_ci *************************************************************************/ 920141cc406Sopenharmony_ci SANE_Status 921141cc406Sopenharmony_cisane_get_parameters (SANE_Handle h, SANE_Parameters *params) 922141cc406Sopenharmony_ci{ 923141cc406Sopenharmony_ci int res, max_width, max_height, max_res; 924141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 925141cc406Sopenharmony_ci DBG(2, ">> sane_get_parameters (h=%p, params=%p)\n", (void*)h, 926141cc406Sopenharmony_ci (void*)params); 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci if (h == NULL) return SANE_STATUS_INVAL; 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci if (cs->opened == SANE_FALSE) 931141cc406Sopenharmony_ci { 932141cc406Sopenharmony_ci DBG(1,"sane_get_parameters: That scanner (%p) ain't " 933141cc406Sopenharmony_ci "open yet\n", h); 934141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 935141cc406Sopenharmony_ci } 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci /* We use 600 res list here because the 300 res list is just a shorter 938141cc406Sopenharmony_ci * version, so this will always work. */ 939141cc406Sopenharmony_ci res = res600[cs->vals[OPT_RESOLUTION]]; 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci /* 942141cc406Sopenharmony_ci * These don't change whether we're scanning or not 943141cc406Sopenharmony_ci * NOTE: Assumes options don't change after scanning commences, which 944141cc406Sopenharmony_ci * is part of the standard 945141cc406Sopenharmony_ci */ 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci /* Copy the options stored in the vals into the scaninfo */ 948141cc406Sopenharmony_ci params->pixels_per_line = 949141cc406Sopenharmony_ci ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) * res) / MM_PER_IN; 950141cc406Sopenharmony_ci params->lines = ((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) * res) 951141cc406Sopenharmony_ci / MM_PER_IN; 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci /* FIXME: Magic numbers ahead! */ 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci max_res = cs->params.scanheadwidth == 2552 ? 300 : 600; 956141cc406Sopenharmony_ci 957141cc406Sopenharmony_ci /* x values have to be divisible by 4 (round down) */ 958141cc406Sopenharmony_ci params->pixels_per_line -= (params->pixels_per_line%4); 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci /* Can't scan less than 64 */ 961141cc406Sopenharmony_ci if (params->pixels_per_line < 64) params->pixels_per_line = 64; 962141cc406Sopenharmony_ci 963141cc406Sopenharmony_ci max_width = cs->params.scanheadwidth / (max_res / res); 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci max_height = (cs->params.scanheadwidth == 2552 ? 3508 : 7016) / 966141cc406Sopenharmony_ci (max_res / res); 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci if(params->pixels_per_line > max_width) 969141cc406Sopenharmony_ci params->pixels_per_line = max_width; 970141cc406Sopenharmony_ci if(params->lines > max_height) params->lines = max_height; 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci params->depth = cs->vals[OPT_DEPTH] ? 16 : 8; 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci switch (cs->vals[OPT_COLOUR_MODE]) 976141cc406Sopenharmony_ci { 977141cc406Sopenharmony_ci case 0: 978141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 979141cc406Sopenharmony_ci break; 980141cc406Sopenharmony_ci case 1: 981141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 982141cc406Sopenharmony_ci break; 983141cc406Sopenharmony_ci default: 984141cc406Sopenharmony_ci /* shouldn't happen */ 985141cc406Sopenharmony_ci break; 986141cc406Sopenharmony_ci } 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci if (!(params->pixels_per_line)) { 990141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 991141cc406Sopenharmony_ci params->lines = 0; 992141cc406Sopenharmony_ci } 993141cc406Sopenharmony_ci 994141cc406Sopenharmony_ci /* Always the "last frame" */ 995141cc406Sopenharmony_ci params->last_frame = SANE_TRUE; 996141cc406Sopenharmony_ci 997141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line * (params->depth/8) * 998141cc406Sopenharmony_ci (cs->vals[OPT_COLOUR_MODE] ? 3 : 1); 999141cc406Sopenharmony_ci 1000141cc406Sopenharmony_ci DBG(10, "get_params: bytes_per_line=%d, pixels_per_line=%d, lines=%d\n" 1001141cc406Sopenharmony_ci "max_res=%d, res=%d, max_height=%d, br_y=%d, tl_y=%d, " 1002141cc406Sopenharmony_ci "mm_per_in=%f\n", 1003141cc406Sopenharmony_ci params->bytes_per_line, params->pixels_per_line, params->lines, 1004141cc406Sopenharmony_ci max_res, res, max_height, cs->vals[OPT_BR_Y], 1005141cc406Sopenharmony_ci cs->vals[OPT_TL_Y], MM_PER_IN); 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci DBG(2, "<< sane_get_parameters\n"); 1008141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1009141cc406Sopenharmony_ci} 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci/************************************************************************* 1013141cc406Sopenharmony_ci * 1014141cc406Sopenharmony_ci * sane_start() 1015141cc406Sopenharmony_ci * 1016141cc406Sopenharmony_ci * Starts scanning an image. 1017141cc406Sopenharmony_ci * 1018141cc406Sopenharmony_ci *************************************************************************/ 1019141cc406Sopenharmony_ci SANE_Status 1020141cc406Sopenharmony_cisane_start (SANE_Handle h) 1021141cc406Sopenharmony_ci{ 1022141cc406Sopenharmony_ci unsigned int i, res, max_width, max_height, max_res, tmp; 1023141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 1024141cc406Sopenharmony_ci DBG(2, ">> sane_start (h=%p)\n", h); 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci if (h == NULL) return SANE_STATUS_INVAL; 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci if (cs->scanning) return SANE_STATUS_DEVICE_BUSY; 1029141cc406Sopenharmony_ci if (cs->opened == SANE_FALSE) 1030141cc406Sopenharmony_ci { 1031141cc406Sopenharmony_ci DBG(1,"sane_start: That scanner (%p) ain't " 1032141cc406Sopenharmony_ci "open yet\n", h); 1033141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1034141cc406Sopenharmony_ci } 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci /* We use 600 res list here because the 300 res list is just a shorter 1038141cc406Sopenharmony_ci * version, so this will always work. */ 1039141cc406Sopenharmony_ci res = res600[cs->vals[OPT_RESOLUTION]]; 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci /* Copy the options stored in the vals into the scaninfo */ 1042141cc406Sopenharmony_ci cs->scan.width = ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) * res) 1043141cc406Sopenharmony_ci / MM_PER_IN; 1044141cc406Sopenharmony_ci cs->scan.height = ((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) * res) 1045141cc406Sopenharmony_ci / MM_PER_IN; 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci cs->scan.xoffset = (cs->vals[OPT_TL_X] * res) / MM_PER_IN; 1048141cc406Sopenharmony_ci cs->scan.yoffset = (cs->vals[OPT_TL_Y] * res) / MM_PER_IN; 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci /* 1051141cc406Sopenharmony_ci * These values have to pass the requirements of not exceeding 1052141cc406Sopenharmony_ci * dimensions (simple clipping) and both width values have to be some 1053141cc406Sopenharmony_ci * integer multiple of 4 1054141cc406Sopenharmony_ci */ 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci /* FIXME: Magic numbers ahead! */ 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci max_res = cs->params.scanheadwidth == 2552 ? 300 : 600; 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci /* x values have to be divisible by 4 (round down) */ 1061141cc406Sopenharmony_ci cs->scan.width -= (cs->scan.width%4); 1062141cc406Sopenharmony_ci cs->scan.xoffset -= (cs->scan.xoffset%4); 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci /* Can't scan less than 64 */ 1065141cc406Sopenharmony_ci if (cs->scan.width < 64) cs->scan.width = 64; 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci max_width = cs->params.scanheadwidth / (max_res / res); 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci max_height = (cs->params.scanheadwidth == 2552 ? 3508 : 7016) / 1070141cc406Sopenharmony_ci (max_res / res); 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci if (cs->scan.width > max_width) cs->scan.width = max_width; 1073141cc406Sopenharmony_ci if (cs->scan.width + cs->scan.xoffset > max_width) cs->scan.xoffset = 1074141cc406Sopenharmony_ci max_width - cs->scan.width; 1075141cc406Sopenharmony_ci if (cs->scan.height > max_height) cs->scan.height = max_height; 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci /* We pass a value to init_scan which is the power of 2 that 75 1078141cc406Sopenharmony_ci * is multiplied by for the resolution. ie: 1079141cc406Sopenharmony_ci * 75 -> 0 1080141cc406Sopenharmony_ci * 150 -> 1 1081141cc406Sopenharmony_ci * 300 -> 2 1082141cc406Sopenharmony_ci * 600 -> 4 1083141cc406Sopenharmony_ci * 1084141cc406Sopenharmony_ci * This rather strange parameter is a result of the way the scanner 1085141cc406Sopenharmony_ci * takes its resolution argument 1086141cc406Sopenharmony_ci */ 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci i = 0; 1089141cc406Sopenharmony_ci while (res > 75) 1090141cc406Sopenharmony_ci { 1091141cc406Sopenharmony_ci i++; 1092141cc406Sopenharmony_ci res = res >> 1; 1093141cc406Sopenharmony_ci } 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci /* FIXME? xres == yres for now. */ 1096141cc406Sopenharmony_ci cs->scan.xresolution = i; 1097141cc406Sopenharmony_ci cs->scan.yresolution = i; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci if (((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) <= 0) || 1100141cc406Sopenharmony_ci ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) <= 0)) 1101141cc406Sopenharmony_ci { 1102141cc406Sopenharmony_ci DBG(1,"sane_start: height = %d, Width = %d. " 1103141cc406Sopenharmony_ci "Can't scan void range!", 1104141cc406Sopenharmony_ci cs->scan.height, cs->scan.width); 1105141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1106141cc406Sopenharmony_ci } 1107141cc406Sopenharmony_ci 1108141cc406Sopenharmony_ci cs->scan.mode = cs->vals[OPT_COLOUR_MODE]; 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci DBG(10, ">> init_scan()\n"); 1111141cc406Sopenharmony_ci tmp = sanei_canon_pp_init_scan(&(cs->params), &(cs->scan)); 1112141cc406Sopenharmony_ci DBG(10, "<< %d init_scan\n", tmp); 1113141cc406Sopenharmony_ci 1114141cc406Sopenharmony_ci if (tmp != 0) { 1115141cc406Sopenharmony_ci DBG(1,"sane_start: WARNING: init_scan returned %d!", tmp); 1116141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1117141cc406Sopenharmony_ci } 1118141cc406Sopenharmony_ci cs->scanning = SANE_TRUE; 1119141cc406Sopenharmony_ci cs->cancelled = SANE_FALSE; 1120141cc406Sopenharmony_ci cs->sent_eof = SANE_FALSE; 1121141cc406Sopenharmony_ci cs->lines_scanned = 0; 1122141cc406Sopenharmony_ci cs->bytes_sent = 0; 1123141cc406Sopenharmony_ci 1124141cc406Sopenharmony_ci DBG(2, "<< sane_start\n"); 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1127141cc406Sopenharmony_ci} 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci 1130141cc406Sopenharmony_ci/************************************************************************* 1131141cc406Sopenharmony_ci * 1132141cc406Sopenharmony_ci * sane_read() 1133141cc406Sopenharmony_ci * 1134141cc406Sopenharmony_ci * Reads some information from the buffer. 1135141cc406Sopenharmony_ci * 1136141cc406Sopenharmony_ci *************************************************************************/ 1137141cc406Sopenharmony_ci SANE_Status 1138141cc406Sopenharmony_cisane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) 1139141cc406Sopenharmony_ci{ 1140141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 1141141cc406Sopenharmony_ci image_segment *is; 1142141cc406Sopenharmony_ci unsigned int lines, bytes, bpl; 1143141cc406Sopenharmony_ci unsigned int i; 1144141cc406Sopenharmony_ci short *shortptr; 1145141cc406Sopenharmony_ci SANE_Byte *charptr; 1146141cc406Sopenharmony_ci int tmp; 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci static SANE_Byte *lbuf; 1149141cc406Sopenharmony_ci static unsigned int bytesleft; 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci DBG(2, ">> sane_read (h=%p, buf=%p, maxlen=%d)\n", h, 1152141cc406Sopenharmony_ci (const void *)buf, maxlen); 1153141cc406Sopenharmony_ci 1154141cc406Sopenharmony_ci /* default to returning 0 - for errors */ 1155141cc406Sopenharmony_ci *lenp = 0; 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci if ((h == NULL) || (buf == NULL) || (lenp == NULL)) 1158141cc406Sopenharmony_ci { 1159141cc406Sopenharmony_ci DBG(1, "sane_read: This frontend's passing me dodgy gear! " 1160141cc406Sopenharmony_ci "(h=%p, buf=%p, lenp=%p)\n", 1161141cc406Sopenharmony_ci (void*)h, (void*)buf, (void*)lenp); 1162141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1163141cc406Sopenharmony_ci } 1164141cc406Sopenharmony_ci 1165141cc406Sopenharmony_ci /* Now we have to see if we have some leftover from last time */ 1166141cc406Sopenharmony_ci 1167141cc406Sopenharmony_ci if (read_leftover != NULL) 1168141cc406Sopenharmony_ci { 1169141cc406Sopenharmony_ci /* feed some more data in until we've run out - don't care 1170141cc406Sopenharmony_ci * whether or not we _think_ the scanner is scanning now, 1171141cc406Sopenharmony_ci * because we may still have data left over to send */ 1172141cc406Sopenharmony_ci DBG(200, "sane_read: didn't send it all last time\n"); 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci /* Now feed it some data from lbuf */ 1175141cc406Sopenharmony_ci if (bytesleft <= (unsigned int)maxlen) 1176141cc406Sopenharmony_ci { 1177141cc406Sopenharmony_ci /* enough buffer to send the lot */ 1178141cc406Sopenharmony_ci memcpy(buf, read_leftover, bytesleft); 1179141cc406Sopenharmony_ci free(lbuf); 1180141cc406Sopenharmony_ci *lenp = bytesleft; 1181141cc406Sopenharmony_ci lbuf = NULL; 1182141cc406Sopenharmony_ci read_leftover = NULL; 1183141cc406Sopenharmony_ci bytesleft = 0; 1184141cc406Sopenharmony_ci cs->bytes_sent += bytesleft; 1185141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci } else { 1188141cc406Sopenharmony_ci /* only enough to send maxlen */ 1189141cc406Sopenharmony_ci memcpy(buf, read_leftover, maxlen); 1190141cc406Sopenharmony_ci read_leftover += maxlen; 1191141cc406Sopenharmony_ci bytesleft -= maxlen; 1192141cc406Sopenharmony_ci *lenp = maxlen; 1193141cc406Sopenharmony_ci cs->bytes_sent += maxlen; 1194141cc406Sopenharmony_ci DBG(100, "sane_read: sent %d bytes, still have %d to " 1195141cc406Sopenharmony_ci "go\n", maxlen, bytesleft); 1196141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1197141cc406Sopenharmony_ci } 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci } 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci /* Has the last scan ended (other than by cancelling)? */ 1203141cc406Sopenharmony_ci if (((unsigned)cs->scan.height <= (unsigned)cs->lines_scanned) 1204141cc406Sopenharmony_ci || (cs->sent_eof) || !(cs->scanning)) 1205141cc406Sopenharmony_ci { 1206141cc406Sopenharmony_ci cs->sent_eof = SANE_TRUE; 1207141cc406Sopenharmony_ci cs->scanning = SANE_FALSE; 1208141cc406Sopenharmony_ci cs->cancelled = SANE_FALSE; 1209141cc406Sopenharmony_ci cs->lines_scanned = 0; 1210141cc406Sopenharmony_ci cs->bytes_sent = 0; 1211141cc406Sopenharmony_ci read_leftover = NULL; 1212141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1213141cc406Sopenharmony_ci } 1214141cc406Sopenharmony_ci 1215141cc406Sopenharmony_ci /* At this point we have to read more data from the scanner - or the 1216141cc406Sopenharmony_ci * scan has been cancelled, which means we have to call read_segment 1217141cc406Sopenharmony_ci * to leave the scanner consistent */ 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci /* Decide how many lines we can fit into this buffer */ 1220141cc406Sopenharmony_ci if (cs->vals[OPT_DEPTH] == 0) 1221141cc406Sopenharmony_ci bpl = cs->scan.width * (cs->vals[OPT_COLOUR_MODE] ? 3 : 1); 1222141cc406Sopenharmony_ci else 1223141cc406Sopenharmony_ci bpl = cs->scan.width * (cs->vals[OPT_COLOUR_MODE] ? 6 : 2); 1224141cc406Sopenharmony_ci 1225141cc406Sopenharmony_ci /* New way: scan a whole scanner buffer full, and return as much as 1226141cc406Sopenharmony_ci * the frontend wants. It's faster and more reliable since the 1227141cc406Sopenharmony_ci * scanners crack the shits if we ask for too many small packets */ 1228141cc406Sopenharmony_ci lines = (BUF_MAX * 4 / 5) / bpl; 1229141cc406Sopenharmony_ci 1230141cc406Sopenharmony_ci if (lines > (cs->scan.height - cs->lines_scanned)) 1231141cc406Sopenharmony_ci lines = cs->scan.height - cs->lines_scanned; 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci if (!lines) 1234141cc406Sopenharmony_ci { 1235141cc406Sopenharmony_ci /* can't fit a whole line into the buffer 1236141cc406Sopenharmony_ci * (should never happen!) */ 1237141cc406Sopenharmony_ci lines = 1; 1238141cc406Sopenharmony_ci } 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci bytes = lines * bpl; 1241141cc406Sopenharmony_ci 1242141cc406Sopenharmony_ci /* Allocate a local buffer to hold the data while we play */ 1243141cc406Sopenharmony_ci if ((lbuf = malloc(bytes)) == NULL) 1244141cc406Sopenharmony_ci { 1245141cc406Sopenharmony_ci DBG(10, "sane_read: Not enough memory to hold a " 1246141cc406Sopenharmony_ci "local buffer. You're doomed\n"); 1247141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1248141cc406Sopenharmony_ci } 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci 1251141cc406Sopenharmony_ci /* This call required a lot of debugging information.. */ 1252141cc406Sopenharmony_ci DBG(10, "sane_read: Here's what we're sending read_segment:\n"); 1253141cc406Sopenharmony_ci DBG(10, "scanner setup: shw=%d xres=%d yres=%d %d %d id=%s\n", 1254141cc406Sopenharmony_ci cs->params.scanheadwidth, 1255141cc406Sopenharmony_ci cs->params.natural_xresolution, 1256141cc406Sopenharmony_ci cs->params.natural_yresolution, 1257141cc406Sopenharmony_ci cs->params.max_xresolution, 1258141cc406Sopenharmony_ci cs->params.max_yresolution, 1259141cc406Sopenharmony_ci (cs->params.id_string)+8); 1260141cc406Sopenharmony_ci DBG(10, "scan_params->: width=%d, height=%d, xoffset=%d, " 1261141cc406Sopenharmony_ci "yoffset=%d\n\txresolution=%d, yresolution=%d, " 1262141cc406Sopenharmony_ci "mode=%d, (lines=%d)\n", 1263141cc406Sopenharmony_ci cs->scan.width, cs->scan.height, 1264141cc406Sopenharmony_ci cs->scan.xoffset, cs->scan.yoffset, 1265141cc406Sopenharmony_ci cs->scan.xresolution, cs->scan.yresolution, 1266141cc406Sopenharmony_ci cs->scan.mode, lines); 1267141cc406Sopenharmony_ci 1268141cc406Sopenharmony_ci DBG(2, ">> read_segment(x, x, x, %d, %d, %d)\n", 1269141cc406Sopenharmony_ci lines, cs->cal_valid, 1270141cc406Sopenharmony_ci cs->scan.height - cs->lines_scanned); 1271141cc406Sopenharmony_ci tmp = sanei_canon_pp_read_segment(&is, &(cs->params), &(cs->scan), 1272141cc406Sopenharmony_ci lines, cs->cal_valid, 1273141cc406Sopenharmony_ci cs->scan.height - cs->lines_scanned); 1274141cc406Sopenharmony_ci DBG(2, "<< %d read_segment\n", tmp); 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_ci if (tmp != 0) { 1277141cc406Sopenharmony_ci if (cs->cancelled) 1278141cc406Sopenharmony_ci { 1279141cc406Sopenharmony_ci DBG(10, "sane_read: cancelling.\n"); 1280141cc406Sopenharmony_ci cs->sent_eof = SANE_TRUE; 1281141cc406Sopenharmony_ci cs->scanning = SANE_FALSE; 1282141cc406Sopenharmony_ci read_leftover = NULL; 1283141cc406Sopenharmony_ci sanei_canon_pp_abort_scan(&(cs->params)); 1284141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1285141cc406Sopenharmony_ci } 1286141cc406Sopenharmony_ci DBG(1, "sane_read: WARNING: read_segment returned %d!\n", tmp); 1287141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1288141cc406Sopenharmony_ci } 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci DBG(10, "sane_read: bpl=%d, lines=%d, bytes=%d\n", bpl, lines, bytes); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci cs->lines_scanned += lines; 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci /* translate data out of buffer */ 1295141cc406Sopenharmony_ci if (cs->vals[OPT_DEPTH] == 0) 1296141cc406Sopenharmony_ci { 1297141cc406Sopenharmony_ci /* 8bpp */ 1298141cc406Sopenharmony_ci for(i = 0; i < bytes; i++) 1299141cc406Sopenharmony_ci { 1300141cc406Sopenharmony_ci charptr = lbuf + i; 1301141cc406Sopenharmony_ci if (cs->vals[OPT_COLOUR_MODE]) 1302141cc406Sopenharmony_ci { 1303141cc406Sopenharmony_ci if (i % 3 == 0) charptr += 2; 1304141cc406Sopenharmony_ci if (i % 3 == 2) charptr -= 2; 1305141cc406Sopenharmony_ci } 1306141cc406Sopenharmony_ci *charptr = *((char *)(is->image_data) + (i*2)); 1307141cc406Sopenharmony_ci } 1308141cc406Sopenharmony_ci } 1309141cc406Sopenharmony_ci else 1310141cc406Sopenharmony_ci { 1311141cc406Sopenharmony_ci /* 16bpp */ 1312141cc406Sopenharmony_ci for(i = 0; i < (bytes/2); i++) 1313141cc406Sopenharmony_ci { 1314141cc406Sopenharmony_ci shortptr = ((short *)lbuf + i); 1315141cc406Sopenharmony_ci if (cs->vals[OPT_COLOUR_MODE]) 1316141cc406Sopenharmony_ci { 1317141cc406Sopenharmony_ci if (i % 3 == 0) shortptr += 2; 1318141cc406Sopenharmony_ci if (i % 3 == 2) shortptr -= 2; 1319141cc406Sopenharmony_ci } 1320141cc406Sopenharmony_ci *shortptr = MAKE_SHORT( 1321141cc406Sopenharmony_ci *((char *)(is->image_data) + (i*2)), 1322141cc406Sopenharmony_ci *((char *)(is->image_data) + (i*2)+1) 1323141cc406Sopenharmony_ci ); 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci } 1326141cc406Sopenharmony_ci 1327141cc406Sopenharmony_ci /* Free data structures allocated in read_segment */ 1328141cc406Sopenharmony_ci free(is->image_data); 1329141cc406Sopenharmony_ci free(is); 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci /* Now feed it some data from lbuf */ 1332141cc406Sopenharmony_ci if (bytes <= (unsigned int)maxlen) 1333141cc406Sopenharmony_ci { 1334141cc406Sopenharmony_ci /* enough buffer to send the lot */ 1335141cc406Sopenharmony_ci memcpy(buf, lbuf, bytes); 1336141cc406Sopenharmony_ci *lenp = bytes; 1337141cc406Sopenharmony_ci free(lbuf); 1338141cc406Sopenharmony_ci lbuf = NULL; 1339141cc406Sopenharmony_ci read_leftover = NULL; 1340141cc406Sopenharmony_ci bytesleft = 0; 1341141cc406Sopenharmony_ci cs->bytes_sent += bytes; 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci } else { 1344141cc406Sopenharmony_ci /* only enough to send maxlen */ 1345141cc406Sopenharmony_ci memcpy(buf, lbuf, maxlen); 1346141cc406Sopenharmony_ci *lenp = maxlen; 1347141cc406Sopenharmony_ci read_leftover = lbuf + maxlen; 1348141cc406Sopenharmony_ci bytesleft = bytes - maxlen; 1349141cc406Sopenharmony_ci cs->bytes_sent += maxlen; 1350141cc406Sopenharmony_ci DBG(100, "sane_read: sent %d bytes, still have %d to go\n", 1351141cc406Sopenharmony_ci maxlen, bytesleft); 1352141cc406Sopenharmony_ci } 1353141cc406Sopenharmony_ci 1354141cc406Sopenharmony_ci if ((unsigned)cs->lines_scanned >= cs->scan.height) 1355141cc406Sopenharmony_ci { 1356141cc406Sopenharmony_ci /* The scan is over! Don't need to call anything in the 1357141cc406Sopenharmony_ci * hardware, it will sort itself out */ 1358141cc406Sopenharmony_ci DBG(10, "sane_read: Scan is finished.\n"); 1359141cc406Sopenharmony_ci cs->scanning = SANE_FALSE; 1360141cc406Sopenharmony_ci cs->lines_scanned = 0; 1361141cc406Sopenharmony_ci cs->bytes_sent = 0; 1362141cc406Sopenharmony_ci } 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci DBG(2, "<< sane_read\n"); 1365141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1366141cc406Sopenharmony_ci} 1367141cc406Sopenharmony_ci 1368141cc406Sopenharmony_ci 1369141cc406Sopenharmony_ci/************************************************************************* 1370141cc406Sopenharmony_ci * 1371141cc406Sopenharmony_ci * sane_cancel() 1372141cc406Sopenharmony_ci * 1373141cc406Sopenharmony_ci * Cancels a scan in progress 1374141cc406Sopenharmony_ci * 1375141cc406Sopenharmony_ci *************************************************************************/ 1376141cc406Sopenharmony_ci void 1377141cc406Sopenharmony_cisane_cancel (SANE_Handle h) 1378141cc406Sopenharmony_ci{ 1379141cc406Sopenharmony_ci /* Note: assume handle is valid apart from NULLs */ 1380141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci DBG(2, ">> sane_cancel (h=%p)\n", h); 1383141cc406Sopenharmony_ci if (h == NULL) return; 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci read_leftover = NULL; 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci if (!(cs->scanning)) 1388141cc406Sopenharmony_ci { 1389141cc406Sopenharmony_ci DBG(2, "<< sane_cancel (not scanning)\n"); 1390141cc406Sopenharmony_ci return; 1391141cc406Sopenharmony_ci } 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci cs->cancelled = SANE_TRUE; 1394141cc406Sopenharmony_ci cs->params.abort_now = 1; 1395141cc406Sopenharmony_ci 1396141cc406Sopenharmony_ci DBG(2, "<< sane_cancel\n"); 1397141cc406Sopenharmony_ci} 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci 1400141cc406Sopenharmony_ci/************************************************************************* 1401141cc406Sopenharmony_ci * 1402141cc406Sopenharmony_ci * sane_close() 1403141cc406Sopenharmony_ci * 1404141cc406Sopenharmony_ci * Closes a scanner handle. Scanner is assumed to be free after this. 1405141cc406Sopenharmony_ci * 1406141cc406Sopenharmony_ci *************************************************************************/ 1407141cc406Sopenharmony_ci void 1408141cc406Sopenharmony_cisane_close (SANE_Handle h) 1409141cc406Sopenharmony_ci{ 1410141cc406Sopenharmony_ci /* Note: assume handle is valid apart from NULLs */ 1411141cc406Sopenharmony_ci CANONP_Scanner *cs = ((CANONP_Scanner *)h); 1412141cc406Sopenharmony_ci DBG(2, ">> sane_close (h=%p)\n", h); 1413141cc406Sopenharmony_ci if (h == NULL) return; 1414141cc406Sopenharmony_ci 1415141cc406Sopenharmony_ci if (cs->opened == SANE_FALSE) 1416141cc406Sopenharmony_ci { 1417141cc406Sopenharmony_ci DBG(1,"sane_close: That scanner (%p) ain't " 1418141cc406Sopenharmony_ci "open yet\n", h); 1419141cc406Sopenharmony_ci return; 1420141cc406Sopenharmony_ci } 1421141cc406Sopenharmony_ci 1422141cc406Sopenharmony_ci /* Put scanner back in transparent mode */ 1423141cc406Sopenharmony_ci sanei_canon_pp_close_scanner(&(cs->params)); 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci cs->opened = SANE_FALSE; 1426141cc406Sopenharmony_ci 1427141cc406Sopenharmony_ci /* if it was scanning, it's not any more */ 1428141cc406Sopenharmony_ci cs->scanning = SANE_FALSE; 1429141cc406Sopenharmony_ci cs->sent_eof = SANE_TRUE; 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_ci ieee1284_release(cs->params.port); 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci DBG(2, "<< sane_close\n"); 1434141cc406Sopenharmony_ci} 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ci/************************************************************************* 1438141cc406Sopenharmony_ci * 1439141cc406Sopenharmony_ci * sane_exit() 1440141cc406Sopenharmony_ci * 1441141cc406Sopenharmony_ci * Shut it down! 1442141cc406Sopenharmony_ci * 1443141cc406Sopenharmony_ci *************************************************************************/ 1444141cc406Sopenharmony_ci void 1445141cc406Sopenharmony_cisane_exit (void) 1446141cc406Sopenharmony_ci{ 1447141cc406Sopenharmony_ci CANONP_Scanner *dev, *next; 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci DBG(2, ">> sane_exit\n"); 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci for (dev = first_dev; dev != NULL; dev = next) 1452141cc406Sopenharmony_ci { 1453141cc406Sopenharmony_ci next = dev->next; 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci /* These were only created if the scanner has been init'd */ 1456141cc406Sopenharmony_ci 1457141cc406Sopenharmony_ci /* Should normally nullify pointers after freeing, but in 1458141cc406Sopenharmony_ci * this case we're about to free the whole structure so 1459141cc406Sopenharmony_ci * there's not a lot of point. */ 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci /* Constraints (mostly) allocated when the scanner is opened */ 1462141cc406Sopenharmony_ci if(dev->opt[OPT_TL_X].constraint.range) 1463141cc406Sopenharmony_ci free((void *)(dev->opt[OPT_TL_X].constraint.range)); 1464141cc406Sopenharmony_ci if(dev->opt[OPT_TL_Y].constraint.range) 1465141cc406Sopenharmony_ci free((void *)(dev->opt[OPT_TL_Y].constraint.range)); 1466141cc406Sopenharmony_ci if(dev->opt[OPT_BR_X].constraint.range) 1467141cc406Sopenharmony_ci free((void *)(dev->opt[OPT_BR_X].constraint.range)); 1468141cc406Sopenharmony_ci if(dev->opt[OPT_BR_Y].constraint.range) 1469141cc406Sopenharmony_ci free((void *)(dev->opt[OPT_BR_Y].constraint.range)); 1470141cc406Sopenharmony_ci 1471141cc406Sopenharmony_ci /* Weights file now on a per-scanner basis */ 1472141cc406Sopenharmony_ci if (dev->weights_file != NULL) 1473141cc406Sopenharmony_ci free(dev->weights_file); 1474141cc406Sopenharmony_ci 1475141cc406Sopenharmony_ci if (dev->scanner_present) 1476141cc406Sopenharmony_ci { 1477141cc406Sopenharmony_ci if (dev->opened == SANE_TRUE) 1478141cc406Sopenharmony_ci { 1479141cc406Sopenharmony_ci /* naughty boys, should have closed first */ 1480141cc406Sopenharmony_ci ieee1284_release(dev->params.port); 1481141cc406Sopenharmony_ci } 1482141cc406Sopenharmony_ci ieee1284_close(dev->params.port); 1483141cc406Sopenharmony_ci } 1484141cc406Sopenharmony_ci 1485141cc406Sopenharmony_ci free (dev); 1486141cc406Sopenharmony_ci } 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci first_dev = NULL; 1489141cc406Sopenharmony_ci def_scanner = NULL; 1490141cc406Sopenharmony_ci read_leftover = NULL; 1491141cc406Sopenharmony_ci num_devices = 0; 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci /* FIXEDME: this created a segfault in DLL code. */ 1494141cc406Sopenharmony_ci /* Bug was fixed in libieee1284 0.1.5 */ 1495141cc406Sopenharmony_ci ieee1284_free_ports(&pl); 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci DBG(2, "<< sane_exit\n"); 1498141cc406Sopenharmony_ci} 1499141cc406Sopenharmony_ci 1500141cc406Sopenharmony_ci 1501141cc406Sopenharmony_ci/************************************************************************* 1502141cc406Sopenharmony_ci * 1503141cc406Sopenharmony_ci * init_device() 1504141cc406Sopenharmony_ci * 1505141cc406Sopenharmony_ci * (Not part of the SANE API) 1506141cc406Sopenharmony_ci * 1507141cc406Sopenharmony_ci * Initialises a CANONP_Scanner data structure for a new device. 1508141cc406Sopenharmony_ci * NOTE: The device is not ready to scan until initialise() has been 1509141cc406Sopenharmony_ci * called in scan library! 1510141cc406Sopenharmony_ci * 1511141cc406Sopenharmony_ci *************************************************************************/ 1512141cc406Sopenharmony_cistatic SANE_Status init_device(struct parport *pp) 1513141cc406Sopenharmony_ci{ 1514141cc406Sopenharmony_ci int i; 1515141cc406Sopenharmony_ci static const char *hw_vendor = "CANON"; 1516141cc406Sopenharmony_ci static const char *hw_type = "flatbed scanner"; 1517141cc406Sopenharmony_ci static const char *opt_names[] = { 1518141cc406Sopenharmony_ci SANE_NAME_NUM_OPTIONS, 1519141cc406Sopenharmony_ci SANE_NAME_SCAN_RESOLUTION, 1520141cc406Sopenharmony_ci SANE_NAME_SCAN_MODE, 1521141cc406Sopenharmony_ci SANE_NAME_BIT_DEPTH, 1522141cc406Sopenharmony_ci SANE_NAME_SCAN_TL_X, 1523141cc406Sopenharmony_ci SANE_NAME_SCAN_TL_Y, 1524141cc406Sopenharmony_ci SANE_NAME_SCAN_BR_X, 1525141cc406Sopenharmony_ci SANE_NAME_SCAN_BR_Y, 1526141cc406Sopenharmony_ci SANE_NAME_QUALITY_CAL 1527141cc406Sopenharmony_ci#if 0 1528141cc406Sopenharmony_ci SANE_NAME_GAMMA_R, 1529141cc406Sopenharmony_ci SANE_NAME_GAMMA_G, 1530141cc406Sopenharmony_ci SANE_NAME_GAMMA_B 1531141cc406Sopenharmony_ci#endif 1532141cc406Sopenharmony_ci }; 1533141cc406Sopenharmony_ci static const char *opt_titles[] = { 1534141cc406Sopenharmony_ci SANE_TITLE_NUM_OPTIONS, 1535141cc406Sopenharmony_ci SANE_TITLE_SCAN_RESOLUTION, 1536141cc406Sopenharmony_ci SANE_TITLE_SCAN_MODE, 1537141cc406Sopenharmony_ci SANE_TITLE_BIT_DEPTH, 1538141cc406Sopenharmony_ci SANE_TITLE_SCAN_TL_X, 1539141cc406Sopenharmony_ci SANE_TITLE_SCAN_TL_Y, 1540141cc406Sopenharmony_ci SANE_TITLE_SCAN_BR_X, 1541141cc406Sopenharmony_ci SANE_TITLE_SCAN_BR_Y, 1542141cc406Sopenharmony_ci SANE_TITLE_QUALITY_CAL 1543141cc406Sopenharmony_ci#if 0 1544141cc406Sopenharmony_ci SANE_TITLE_GAMMA_R, 1545141cc406Sopenharmony_ci SANE_TITLE_GAMMA_G, 1546141cc406Sopenharmony_ci SANE_TITLE_GAMMA_B 1547141cc406Sopenharmony_ci#endif 1548141cc406Sopenharmony_ci }; 1549141cc406Sopenharmony_ci static const char *opt_descs[] = { 1550141cc406Sopenharmony_ci SANE_DESC_NUM_OPTIONS, 1551141cc406Sopenharmony_ci SANE_DESC_SCAN_RESOLUTION, 1552141cc406Sopenharmony_ci SANE_DESC_SCAN_MODE, 1553141cc406Sopenharmony_ci SANE_DESC_BIT_DEPTH, 1554141cc406Sopenharmony_ci SANE_DESC_SCAN_TL_X, 1555141cc406Sopenharmony_ci SANE_DESC_SCAN_TL_Y, 1556141cc406Sopenharmony_ci SANE_DESC_SCAN_BR_X, 1557141cc406Sopenharmony_ci SANE_DESC_SCAN_BR_Y, 1558141cc406Sopenharmony_ci SANE_DESC_QUALITY_CAL 1559141cc406Sopenharmony_ci#if 0 1560141cc406Sopenharmony_ci SANE_DESC_GAMMA_R, 1561141cc406Sopenharmony_ci SANE_DESC_GAMMA_G, 1562141cc406Sopenharmony_ci SANE_DESC_GAMMA_B 1563141cc406Sopenharmony_ci#endif 1564141cc406Sopenharmony_ci }; 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci CANONP_Scanner *cs = NULL; 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci DBG(2, ">> init_device\n"); 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci cs = malloc(sizeof(*cs)); 1571141cc406Sopenharmony_ci if (cs == NULL) 1572141cc406Sopenharmony_ci { 1573141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1574141cc406Sopenharmony_ci } 1575141cc406Sopenharmony_ci memset(cs, 0, sizeof(*cs)); 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci#if 0 1578141cc406Sopenharmony_ci if ((cs->params.port = malloc(sizeof(*(cs->params.port)))) == NULL) 1579141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1580141cc406Sopenharmony_ci 1581141cc406Sopenharmony_ci memcpy(cs->params.port, pp, sizeof(*pp)); 1582141cc406Sopenharmony_ci#endif 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci cs->params.port = pp; 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci /* ensure these are null to start off with, otherwise they might be 1587141cc406Sopenharmony_ci * erroneously free'd. Note that we set everything to 0 above 1588141cc406Sopenharmony_ci * but that's not *always* the same thing */ 1589141cc406Sopenharmony_ci cs->params.blackweight = NULL; 1590141cc406Sopenharmony_ci cs->params.redweight = NULL; 1591141cc406Sopenharmony_ci cs->params.greenweight = NULL; 1592141cc406Sopenharmony_ci cs->params.blueweight = NULL; 1593141cc406Sopenharmony_ci 1594141cc406Sopenharmony_ci /* Set some sensible defaults */ 1595141cc406Sopenharmony_ci cs->hw.name = cs->params.port->name; 1596141cc406Sopenharmony_ci cs->hw.vendor = hw_vendor; 1597141cc406Sopenharmony_ci cs->hw.type = hw_type; 1598141cc406Sopenharmony_ci cs->opened = SANE_FALSE; 1599141cc406Sopenharmony_ci cs->scanning = SANE_FALSE; 1600141cc406Sopenharmony_ci cs->cancelled = SANE_FALSE; 1601141cc406Sopenharmony_ci cs->sent_eof = SANE_TRUE; 1602141cc406Sopenharmony_ci cs->lines_scanned = 0; 1603141cc406Sopenharmony_ci cs->bytes_sent = 0; 1604141cc406Sopenharmony_ci cs->init_mode = INITMODE_AUTO; 1605141cc406Sopenharmony_ci 1606141cc406Sopenharmony_ci DBG(10, "init_device: [configuring options]\n"); 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci /* take a punt at each option, then we change it later */ 1609141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; i++) 1610141cc406Sopenharmony_ci { 1611141cc406Sopenharmony_ci cs->opt[i].name = opt_names[i]; 1612141cc406Sopenharmony_ci cs->opt[i].title = opt_titles[i]; 1613141cc406Sopenharmony_ci cs->opt[i].desc = opt_descs[i]; 1614141cc406Sopenharmony_ci cs->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1615141cc406Sopenharmony_ci cs->opt[i].type = SANE_TYPE_INT; 1616141cc406Sopenharmony_ci cs->opt[i].size = sizeof(SANE_Int); 1617141cc406Sopenharmony_ci } 1618141cc406Sopenharmony_ci 1619141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: num_options\n"); 1620141cc406Sopenharmony_ci /* The number of options option */ 1621141cc406Sopenharmony_ci 1622141cc406Sopenharmony_ci cs->opt[OPT_NUM_OPTIONS].unit = SANE_UNIT_NONE; 1623141cc406Sopenharmony_ci cs->opt[OPT_NUM_OPTIONS].cap = SANE_CAP_SOFT_DETECT; 1624141cc406Sopenharmony_ci cs->vals[OPT_NUM_OPTIONS] = NUM_OPTIONS; 1625141cc406Sopenharmony_ci 1626141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: resolution\n"); 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ci /* The resolution of scanning (X res == Y res for now)*/ 1629141cc406Sopenharmony_ci cs->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1630141cc406Sopenharmony_ci cs->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1631141cc406Sopenharmony_ci /* should never point at first element (wordlist size) */ 1632141cc406Sopenharmony_ci cs->vals[OPT_RESOLUTION] = 1; 1633141cc406Sopenharmony_ci 1634141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: colour mode\n"); 1635141cc406Sopenharmony_ci 1636141cc406Sopenharmony_ci /* The colour mode (0=grey 1=rgb) */ 1637141cc406Sopenharmony_ci cs->opt[OPT_COLOUR_MODE].type = SANE_TYPE_STRING; 1638141cc406Sopenharmony_ci cs->opt[OPT_COLOUR_MODE].size = 20; 1639141cc406Sopenharmony_ci cs->opt[OPT_COLOUR_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1640141cc406Sopenharmony_ci /* Set this one here because it doesn't change by scanner (yet) */ 1641141cc406Sopenharmony_ci cs->opt[OPT_COLOUR_MODE].constraint.string_list = cmodes; 1642141cc406Sopenharmony_ci 1643141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: bit depth\n"); 1644141cc406Sopenharmony_ci 1645141cc406Sopenharmony_ci /* The bit depth */ 1646141cc406Sopenharmony_ci cs->opt[OPT_DEPTH].type = SANE_TYPE_STRING; 1647141cc406Sopenharmony_ci cs->opt[OPT_DEPTH].size = 20; 1648141cc406Sopenharmony_ci cs->opt[OPT_DEPTH].cap |= SANE_CAP_EMULATED; 1649141cc406Sopenharmony_ci cs->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1650141cc406Sopenharmony_ci cs->opt[OPT_DEPTH].constraint.string_list = depths; 1651141cc406Sopenharmony_ci 1652141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: tl-x\n"); 1653141cc406Sopenharmony_ci 1654141cc406Sopenharmony_ci /* The top-left-x */ 1655141cc406Sopenharmony_ci cs->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1656141cc406Sopenharmony_ci cs->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: tl-y\n"); 1659141cc406Sopenharmony_ci 1660141cc406Sopenharmony_ci /* The top-left-y */ 1661141cc406Sopenharmony_ci cs->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1662141cc406Sopenharmony_ci cs->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1663141cc406Sopenharmony_ci 1664141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: br-x\n"); 1665141cc406Sopenharmony_ci 1666141cc406Sopenharmony_ci /* The bottom-right-x */ 1667141cc406Sopenharmony_ci cs->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1668141cc406Sopenharmony_ci cs->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1669141cc406Sopenharmony_ci /* default scan width */ 1670141cc406Sopenharmony_ci cs->vals[OPT_BR_X] = 100; 1671141cc406Sopenharmony_ci 1672141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: br-y\n"); 1673141cc406Sopenharmony_ci 1674141cc406Sopenharmony_ci /* The bottom-right-y */ 1675141cc406Sopenharmony_ci cs->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1676141cc406Sopenharmony_ci cs->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1677141cc406Sopenharmony_ci cs->vals[OPT_BR_Y] = 100; 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_ci DBG(100, "init_device: configuring opt: calibrate\n"); 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci /* The calibration button */ 1682141cc406Sopenharmony_ci cs->opt[OPT_CAL].type = SANE_TYPE_BUTTON; 1683141cc406Sopenharmony_ci cs->opt[OPT_CAL].constraint_type = SANE_CONSTRAINT_NONE; 1684141cc406Sopenharmony_ci if (cs->cal_readonly) 1685141cc406Sopenharmony_ci cs->opt[OPT_CAL].cap |= SANE_CAP_INACTIVE; 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci#if 0 1688141cc406Sopenharmony_ci /* the gamma values (once we do them) */ 1689141cc406Sopenharmony_ci cs->opt[OPT_GAMMA_R].caps |= SANE_CAP_ADVANCED; 1690141cc406Sopenharmony_ci cs->opt[OPT_GAMMA_G].caps |= SANE_CAP_ADVANCED; 1691141cc406Sopenharmony_ci cs->opt[OPT_GAMMA_B].caps |= SANE_CAP_ADVANCED; 1692141cc406Sopenharmony_ci#endif 1693141cc406Sopenharmony_ci 1694141cc406Sopenharmony_ci /* 1695141cc406Sopenharmony_ci * NOTE: Ranges and lists are actually set when scanner is opened, 1696141cc406Sopenharmony_ci * because that's when we find out what sort of scanner it is 1697141cc406Sopenharmony_ci */ 1698141cc406Sopenharmony_ci 1699141cc406Sopenharmony_ci DBG(100, "init_device: done opts\n"); 1700141cc406Sopenharmony_ci 1701141cc406Sopenharmony_ci /* add it to the head of the tree */ 1702141cc406Sopenharmony_ci cs->next = first_dev; 1703141cc406Sopenharmony_ci first_dev = cs; 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci num_devices++; 1706141cc406Sopenharmony_ci 1707141cc406Sopenharmony_ci DBG(2, "<< init_device\n"); 1708141cc406Sopenharmony_ci 1709141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1710141cc406Sopenharmony_ci} 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci/************************************************************************* 1714141cc406Sopenharmony_ci * 1715141cc406Sopenharmony_ci * These two are optional ones... maybe if I get really keen? 1716141cc406Sopenharmony_ci * 1717141cc406Sopenharmony_ci *************************************************************************/ 1718141cc406Sopenharmony_ci SANE_Status 1719141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) 1720141cc406Sopenharmony_ci{ 1721141cc406Sopenharmony_ci DBG(2, ">> sane_set_io_mode (%p, %d) (not really supported)\n", 1722141cc406Sopenharmony_ci h, non_blocking); 1723141cc406Sopenharmony_ci 1724141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) 1725141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci DBG(2, "<< sane_set_io_mode\n"); 1728141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1729141cc406Sopenharmony_ci} 1730141cc406Sopenharmony_ci 1731141cc406Sopenharmony_ci SANE_Status 1732141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle h, SANE_Int *fdp) 1733141cc406Sopenharmony_ci{ 1734141cc406Sopenharmony_ci DBG(2, ">> sane_get_select_fd (%p, %p) (not supported)\n", h, 1735141cc406Sopenharmony_ci (const void *)fdp); 1736141cc406Sopenharmony_ci DBG(2, "<< sane_get_select_fd\n"); 1737141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1738141cc406Sopenharmony_ci} 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci/************************************************************************* 1742141cc406Sopenharmony_ci * 1743141cc406Sopenharmony_ci * init_cal(): Try to create a calibration file 1744141cc406Sopenharmony_ci * has to be changed. 1745141cc406Sopenharmony_ci * 1746141cc406Sopenharmony_ci ************************************************************************/ 1747141cc406Sopenharmony_cistatic int init_cal(char *file) 1748141cc406Sopenharmony_ci{ 1749141cc406Sopenharmony_ci char *tmp, *path; 1750141cc406Sopenharmony_ci int f, i; 1751141cc406Sopenharmony_ci 1752141cc406Sopenharmony_ci if ((f = open(file, O_CREAT | O_WRONLY, 0600)) < 0) 1753141cc406Sopenharmony_ci { 1754141cc406Sopenharmony_ci if (errno == ENOENT) 1755141cc406Sopenharmony_ci { 1756141cc406Sopenharmony_ci /* we need to try and make ~/.sane perhaps - 1757141cc406Sopenharmony_ci * find the last / in the file path, and try 1758141cc406Sopenharmony_ci * to create it */ 1759141cc406Sopenharmony_ci if ((tmp = strrchr(file, '/')) == NULL) 1760141cc406Sopenharmony_ci return -1; 1761141cc406Sopenharmony_ci path = strdup(file); 1762141cc406Sopenharmony_ci *(path + (tmp-file)) = '\0'; 1763141cc406Sopenharmony_ci i = mkdir(path, 0777); 1764141cc406Sopenharmony_ci free(path); 1765141cc406Sopenharmony_ci if (i) return -1; 1766141cc406Sopenharmony_ci /* Path has been created, now try this again.. */ 1767141cc406Sopenharmony_ci if ((f = open(file, O_CREAT | O_WRONLY, 0600)) < 0) 1768141cc406Sopenharmony_ci return -1; 1769141cc406Sopenharmony_ci } 1770141cc406Sopenharmony_ci else 1771141cc406Sopenharmony_ci { 1772141cc406Sopenharmony_ci /* Error is something like access denied - too 1773141cc406Sopenharmony_ci * hard to fix, so i give up... */ 1774141cc406Sopenharmony_ci return -1; 1775141cc406Sopenharmony_ci } 1776141cc406Sopenharmony_ci } 1777141cc406Sopenharmony_ci /* should probably set defaults here.. */ 1778141cc406Sopenharmony_ci close(f); 1779141cc406Sopenharmony_ci return 0; 1780141cc406Sopenharmony_ci} 1781141cc406Sopenharmony_ci 1782141cc406Sopenharmony_ci/************************************************************************* 1783141cc406Sopenharmony_ci * 1784141cc406Sopenharmony_ci * fix_weights_file(): Ensures that the weights_file setting for a given 1785141cc406Sopenharmony_ci * scanner is valid 1786141cc406Sopenharmony_ci * 1787141cc406Sopenharmony_ci ************************************************************************/ 1788141cc406Sopenharmony_cistatic SANE_Status fix_weights_file(CANONP_Scanner *cs) 1789141cc406Sopenharmony_ci{ 1790141cc406Sopenharmony_ci static const char default_weights_file_prefix[] = 1791141cc406Sopenharmony_ci "~/.sane/canon_pp-calibration-"; 1792141cc406Sopenharmony_ci char *tmp, *myhome; 1793141cc406Sopenharmony_ci int i; 1794141cc406Sopenharmony_ci struct stat *f_stat; 1795141cc406Sopenharmony_ci 1796141cc406Sopenharmony_ci 1797141cc406Sopenharmony_ci if (cs == NULL) 1798141cc406Sopenharmony_ci { 1799141cc406Sopenharmony_ci DBG(0, "fix_weights_file: FATAL: NULL passed by my code, " 1800141cc406Sopenharmony_ci "please report this!\n"); 1801141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1802141cc406Sopenharmony_ci } 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci /* Assume this is false and then correct it */ 1805141cc406Sopenharmony_ci cs->cal_readonly = SANE_FALSE; 1806141cc406Sopenharmony_ci 1807141cc406Sopenharmony_ci if (cs->weights_file == NULL) 1808141cc406Sopenharmony_ci { 1809141cc406Sopenharmony_ci /* Form is ~/.sane/canon_pp-calibration-parport0 or -0x378 */ 1810141cc406Sopenharmony_ci i = strlen(default_weights_file_prefix) + 1811141cc406Sopenharmony_ci strlen(cs->params.port->name); 1812141cc406Sopenharmony_ci if ((cs->weights_file = malloc(i + 1)) == NULL) 1813141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1814141cc406Sopenharmony_ci sprintf(cs->weights_file, "%s%s", default_weights_file_prefix, 1815141cc406Sopenharmony_ci cs->params.port->name); 1816141cc406Sopenharmony_ci } 1817141cc406Sopenharmony_ci 1818141cc406Sopenharmony_ci /* Get the user's home dir if they used ~ */ 1819141cc406Sopenharmony_ci if (cs->weights_file[0] == '~') 1820141cc406Sopenharmony_ci { 1821141cc406Sopenharmony_ci if ((myhome = getenv("HOME")) == NULL) 1822141cc406Sopenharmony_ci { 1823141cc406Sopenharmony_ci DBG(0,"fix_weights_file: FATAL: ~ used, but $HOME not" 1824141cc406Sopenharmony_ci " set!\n"); 1825141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1826141cc406Sopenharmony_ci } 1827141cc406Sopenharmony_ci i = strlen(myhome) + strlen(&cs->weights_file[1]); 1828141cc406Sopenharmony_ci if ((tmp = malloc(i + 1)) == NULL) 1829141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1830141cc406Sopenharmony_ci sprintf(tmp, "%s%s", myhome, &cs->weights_file[1]); 1831141cc406Sopenharmony_ci 1832141cc406Sopenharmony_ci free(cs->weights_file); 1833141cc406Sopenharmony_ci cs->weights_file = tmp; 1834141cc406Sopenharmony_ci tmp = NULL; 1835141cc406Sopenharmony_ci } 1836141cc406Sopenharmony_ci 1837141cc406Sopenharmony_ci if ((f_stat = malloc(sizeof(*f_stat))) == NULL) 1838141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci if(stat(cs->weights_file, f_stat)) 1841141cc406Sopenharmony_ci { 1842141cc406Sopenharmony_ci /* this non-intuitive if basically is if we got some error that 1843141cc406Sopenharmony_ci * wasn't no-such-file, or we can't create the file.. */ 1844141cc406Sopenharmony_ci if ((errno != ENOENT) || init_cal(cs->weights_file)) 1845141cc406Sopenharmony_ci { 1846141cc406Sopenharmony_ci /* Some nasty error returned. Give up. */ 1847141cc406Sopenharmony_ci DBG(2,"fix_weights_file: error stating cal file" 1848141cc406Sopenharmony_ci " (%s)\n", strerror(errno)); 1849141cc406Sopenharmony_ci DBG(2,"fix_weights_file: Changes to cal data won't" 1850141cc406Sopenharmony_ci " be saved!\n"); 1851141cc406Sopenharmony_ci free(cs->weights_file); 1852141cc406Sopenharmony_ci cs->weights_file = NULL; 1853141cc406Sopenharmony_ci } 1854141cc406Sopenharmony_ci } 1855141cc406Sopenharmony_ci else 1856141cc406Sopenharmony_ci { 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci /* No error returned.. Check read/writability */ 1859141cc406Sopenharmony_ci i = open(cs->weights_file, O_RDWR | O_APPEND); 1860141cc406Sopenharmony_ci if (i <= 0) 1861141cc406Sopenharmony_ci { 1862141cc406Sopenharmony_ci DBG(10,"fix_weighs_file: Note: Changes to cal data " 1863141cc406Sopenharmony_ci "won't be saved!\n"); 1864141cc406Sopenharmony_ci i = open(cs->weights_file, O_RDONLY); 1865141cc406Sopenharmony_ci if (i <= 0) 1866141cc406Sopenharmony_ci { 1867141cc406Sopenharmony_ci /* 1868141cc406Sopenharmony_ci * Open failed (do i care why?) 1869141cc406Sopenharmony_ci */ 1870141cc406Sopenharmony_ci DBG(2,"fix_weights_file: error opening cal " 1871141cc406Sopenharmony_ci "(%s)\n", strerror(errno)); 1872141cc406Sopenharmony_ci free(cs->weights_file); 1873141cc406Sopenharmony_ci cs->weights_file = NULL; 1874141cc406Sopenharmony_ci } 1875141cc406Sopenharmony_ci else 1876141cc406Sopenharmony_ci { 1877141cc406Sopenharmony_ci DBG(2,"fix_weights_file: file is read-only, " 1878141cc406Sopenharmony_ci "changes won't be saved\n"); 1879141cc406Sopenharmony_ci cs->cal_readonly = SANE_TRUE; 1880141cc406Sopenharmony_ci close(i); 1881141cc406Sopenharmony_ci } 1882141cc406Sopenharmony_ci } 1883141cc406Sopenharmony_ci else 1884141cc406Sopenharmony_ci { 1885141cc406Sopenharmony_ci /* good! */ 1886141cc406Sopenharmony_ci DBG(10,"fix_weights_file: Calibration file is good " 1887141cc406Sopenharmony_ci "for opening!\n"); 1888141cc406Sopenharmony_ci close(i); 1889141cc406Sopenharmony_ci } 1890141cc406Sopenharmony_ci } 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci /* cleanup */ 1893141cc406Sopenharmony_ci free(f_stat); 1894141cc406Sopenharmony_ci 1895141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1896141cc406Sopenharmony_ci} 1897141cc406Sopenharmony_ci 1898141cc406Sopenharmony_ci/* detect_mode 1899141cc406Sopenharmony_ci * PRE: 1900141cc406Sopenharmony_ci * cs->params.port is not open 1901141cc406Sopenharmony_ci * POST: 1902141cc406Sopenharmony_ci * cs->params.port is left opened iff SANE_STATUS_GOOD returned. 1903141cc406Sopenharmony_ci */ 1904141cc406Sopenharmony_ci 1905141cc406Sopenharmony_ciSANE_Status detect_mode(CANONP_Scanner *cs) 1906141cc406Sopenharmony_ci{ 1907141cc406Sopenharmony_ci 1908141cc406Sopenharmony_ci int capabilities, tmp; 1909141cc406Sopenharmony_ci 1910141cc406Sopenharmony_ci /* Open then claim parallel port using libieee1284 */ 1911141cc406Sopenharmony_ci DBG(10,"detect_mode: Opening port %s\n", (cs->params.port->name)); 1912141cc406Sopenharmony_ci 1913141cc406Sopenharmony_ci tmp = ieee1284_open(cs->params.port, 0, &capabilities); 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci if (tmp != E1284_OK) 1916141cc406Sopenharmony_ci { 1917141cc406Sopenharmony_ci switch (tmp) 1918141cc406Sopenharmony_ci { 1919141cc406Sopenharmony_ci case E1284_INVALIDPORT: 1920141cc406Sopenharmony_ci DBG(1, "detect_mode: Invalid port.\n"); 1921141cc406Sopenharmony_ci break; 1922141cc406Sopenharmony_ci case E1284_SYS: 1923141cc406Sopenharmony_ci DBG(1, "detect_mode: System error: %s\n", 1924141cc406Sopenharmony_ci strerror(errno)); 1925141cc406Sopenharmony_ci break; 1926141cc406Sopenharmony_ci case E1284_INIT: 1927141cc406Sopenharmony_ci DBG(1, "detect_mode: Initialisation error.\n"); 1928141cc406Sopenharmony_ci break; 1929141cc406Sopenharmony_ci default: 1930141cc406Sopenharmony_ci DBG(1, "detect_mode: Unknown error.\n"); 1931141cc406Sopenharmony_ci break; 1932141cc406Sopenharmony_ci } 1933141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1934141cc406Sopenharmony_ci } 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci DBG(10,"detect_mode: Claiming port.\n"); 1937141cc406Sopenharmony_ci 1938141cc406Sopenharmony_ci if (ieee1284_claim(cs->params.port) != E1284_OK) 1939141cc406Sopenharmony_ci { 1940141cc406Sopenharmony_ci DBG(1,"detect_mode: Unable to claim port\n"); 1941141cc406Sopenharmony_ci ieee1284_close(cs->params.port); 1942141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1943141cc406Sopenharmony_ci } 1944141cc406Sopenharmony_ci 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci /* Check that compatibility-mode (required) is supported */ 1947141cc406Sopenharmony_ci if (!(capabilities & CAP1284_COMPAT)) 1948141cc406Sopenharmony_ci { 1949141cc406Sopenharmony_ci DBG(0,"detect_mode: Compatibility mode (required) not " 1950141cc406Sopenharmony_ci "supported.\n"); 1951141cc406Sopenharmony_ci ieee1284_release(cs->params.port); 1952141cc406Sopenharmony_ci ieee1284_close(cs->params.port); 1953141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1954141cc406Sopenharmony_ci } 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci /* Check capabilities which will enchance speed */ 1957141cc406Sopenharmony_ci if (capabilities & CAP1284_ECP) 1958141cc406Sopenharmony_ci DBG(2, "detect_mode: Port supports ECP-H.\n"); 1959141cc406Sopenharmony_ci else if (capabilities & CAP1284_ECPSWE) 1960141cc406Sopenharmony_ci DBG(2, "detect_mode: Port supports ECP-S.\n"); 1961141cc406Sopenharmony_ci if (capabilities & CAP1284_IRQ) 1962141cc406Sopenharmony_ci DBG(2, "detect_mode: Port supports interrupts.\n"); 1963141cc406Sopenharmony_ci if (capabilities & CAP1284_DMA) 1964141cc406Sopenharmony_ci DBG(2, "detect_mode: Port supports DMA.\n"); 1965141cc406Sopenharmony_ci 1966141cc406Sopenharmony_ci /* Check whether ECP mode is possible */ 1967141cc406Sopenharmony_ci if (capabilities & CAP1284_ECP) 1968141cc406Sopenharmony_ci { 1969141cc406Sopenharmony_ci cs->ieee1284_mode = M1284_ECP; 1970141cc406Sopenharmony_ci DBG(10, "detect_mode: Using ECP-H Mode\n"); 1971141cc406Sopenharmony_ci } 1972141cc406Sopenharmony_ci else if (capabilities & CAP1284_ECPSWE) 1973141cc406Sopenharmony_ci { 1974141cc406Sopenharmony_ci cs->ieee1284_mode = M1284_ECPSWE; 1975141cc406Sopenharmony_ci DBG(10, "detect_mode: Using ECP-S Mode\n"); 1976141cc406Sopenharmony_ci } 1977141cc406Sopenharmony_ci else if (capabilities & CAP1284_NIBBLE) 1978141cc406Sopenharmony_ci { 1979141cc406Sopenharmony_ci cs->ieee1284_mode = M1284_NIBBLE; 1980141cc406Sopenharmony_ci DBG(10, "detect_mode: Using nibble mode\n"); 1981141cc406Sopenharmony_ci } 1982141cc406Sopenharmony_ci else 1983141cc406Sopenharmony_ci { 1984141cc406Sopenharmony_ci DBG(0, "detect_mode: No supported parport modes available!\n"); 1985141cc406Sopenharmony_ci ieee1284_release(cs->params.port); 1986141cc406Sopenharmony_ci ieee1284_close(cs->params.port); 1987141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1988141cc406Sopenharmony_ci } 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_ci /* Check to make sure ECP mode really is supported */ 1991141cc406Sopenharmony_ci /* Have disabled the hardware ECP check because it's always supported 1992141cc406Sopenharmony_ci * by libieee1284 now, and it's too prone to hitting a ppdev bug 1993141cc406Sopenharmony_ci */ 1994141cc406Sopenharmony_ci 1995141cc406Sopenharmony_ci /* Disabled check entirely.. check now in initialise when we 1996141cc406Sopenharmony_ci * actually do a read */ 1997141cc406Sopenharmony_ci#if 0 1998141cc406Sopenharmony_ci if ((cs->ieee1284_mode == M1284_ECP) || 1999141cc406Sopenharmony_ci (cs->ieee1284_mode == M1284_ECPSWE)) 2000141cc406Sopenharmony_ci { 2001141cc406Sopenharmony_ci DBG(1, "detect_mode: attempting a 0 byte read, if we hang " 2002141cc406Sopenharmony_ci "here, it's a ppdev bug!\n"); 2003141cc406Sopenharmony_ci /* 2004141cc406Sopenharmony_ci * 29/06/02 2005141cc406Sopenharmony_ci * NOTE: 2006141cc406Sopenharmony_ci * This causes an infinite loop in ppdev on 2.4.18. 2007141cc406Sopenharmony_ci * Not checking on hardware ECP mode should work-around 2008141cc406Sopenharmony_ci * effectively. 2009141cc406Sopenharmony_ci * 2010141cc406Sopenharmony_ci * I have sent email to twaugh about it, should be fixed in 2011141cc406Sopenharmony_ci * 2.4.19 and above. 2012141cc406Sopenharmony_ci */ 2013141cc406Sopenharmony_ci if (ieee1284_ecp_read_data(cs->params.port, 0, NULL, 0) == 2014141cc406Sopenharmony_ci E1284_NOTIMPL) 2015141cc406Sopenharmony_ci { 2016141cc406Sopenharmony_ci DBG(10, "detect_mode: Your version of libieee1284 " 2017141cc406Sopenharmony_ci "doesn't support ECP mode - defaulting" 2018141cc406Sopenharmony_ci " to nibble mode instead.\n"); 2019141cc406Sopenharmony_ci cs->ieee1284_mode = M1284_NIBBLE; 2020141cc406Sopenharmony_ci } 2021141cc406Sopenharmony_ci } 2022141cc406Sopenharmony_ci#endif 2023141cc406Sopenharmony_ci 2024141cc406Sopenharmony_ci if (force_nibble == SANE_TRUE) { 2025141cc406Sopenharmony_ci DBG(10, "detect_mode: Nibble mode force in effect.\n"); 2026141cc406Sopenharmony_ci cs->ieee1284_mode = M1284_NIBBLE; 2027141cc406Sopenharmony_ci } 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci ieee1284_release(cs->params.port); 2030141cc406Sopenharmony_ci 2031141cc406Sopenharmony_ci sanei_canon_pp_set_ieee1284_mode(cs->ieee1284_mode); 2032141cc406Sopenharmony_ci 2033141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2034141cc406Sopenharmony_ci} 2035