diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
commit | 6e9c41a892ed0e0da326e0278b3221ce3f5713b8 (patch) | |
tree | 2e301d871bbeeb44aa57ff9cc070fcf3be484487 /backend/canon630u.c |
Initial import of sane-backends version 1.0.24-1.2
Diffstat (limited to 'backend/canon630u.c')
-rw-r--r-- | backend/canon630u.c | 1044 |
1 files changed, 1044 insertions, 0 deletions
diff --git a/backend/canon630u.c b/backend/canon630u.c new file mode 100644 index 0000000..6bd3431 --- /dev/null +++ b/backend/canon630u.c @@ -0,0 +1,1044 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2002, Nathan Rutman <nathan@gordian.com> + Copyright (C) 2001, Marcio Luis Teixeira + + Parts copyright (C) 1996, 1997 Andreas Beck + Parts copyright (C) 2000, 2001 Michael Herder <crapsite@gmx.net> + Parts copyright (C) 2001 Henning Meier-Geinitz <henning@meier-geinitz.de> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. */ + +#define BUILD 1 +#define MM_IN_INCH 25.4 + +#include "../include/sane/config.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/types.h> + +#include "../include/sane/sane.h" +#include "../include/sane/sanei.h" +#include "../include/sane/saneopts.h" +#include "../include/sane/sanei_config.h" +#include "../include/sane/sanei_usb.h" +#define BACKEND_NAME canon630u +#define CANONUSB_CONFIG_FILE "canon630u.conf" +#include "../include/sane/sanei_backend.h" + +#include "canon630u-common.c" + +typedef struct Canon_Device +{ + struct Canon_Device *next; + SANE_String name; + SANE_Device sane; +} +Canon_Device; + +typedef struct Canon_Scanner +{ + struct Canon_Scanner *next; + Canon_Device *device; + CANON_Handle scan; +} +Canon_Scanner; + +static int num_devices = 0; +static const SANE_Device **devlist = NULL; +static Canon_Device *first_dev = NULL; +static Canon_Scanner *first_handle = NULL; + +static SANE_Parameters parms = { + SANE_FRAME_RGB, + 0, + 0, /* Number of bytes returned per scan line: */ + 0, /* Number of pixels per scan line. */ + 0, /* Number of lines for the current scan. */ + 8 /* Number of bits per sample. */ +}; + + +struct _SANE_Option +{ + SANE_Option_Descriptor *descriptor; + SANE_Status (*callback) (struct _SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, + SANE_Int * info); +}; + +typedef struct _SANE_Option SANE_Option; + + +/*-----------------------------------------------------------------*/ + +static SANE_Word getNumberOfOptions (void); /* Forward declaration */ + +/* +This read-only option returns the number of options available for +the device. It should be the first option in the options array +declared below. +*/ + +static SANE_Option_Descriptor optionNumOptionsDescriptor = { + SANE_NAME_NUM_OPTIONS, + SANE_TITLE_NUM_OPTIONS, + SANE_DESC_NUM_OPTIONS, + SANE_TYPE_INT, + SANE_UNIT_NONE, + sizeof (SANE_Word), + SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_NONE, + {NULL} +}; + +static SANE_Status +optionNumOptionsCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + option = option; + handle = handle; + info = info; /* Eliminate warning about unused parameters */ + + if (action != SANE_ACTION_GET_VALUE) + return SANE_STATUS_INVAL; + *(SANE_Word *) value = getNumberOfOptions (); + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ + +/* +This option lets the user force scanner calibration. Normally, this is +done only once, at first scan after powerup. + */ + +static SANE_Word optionCalibrateValue = SANE_FALSE; + +static SANE_Option_Descriptor optionCalibrateDescriptor = { + "cal", + SANE_I18N ("Calibrate Scanner"), + SANE_I18N ("Force scanner calibration before scan"), + SANE_TYPE_BOOL, + SANE_UNIT_NONE, + sizeof (SANE_Word), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_NONE, + {NULL} +}; + +static SANE_Status +optionCalibrateCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + handle = handle; + option = option; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + *info |= SANE_INFO_RELOAD_PARAMS; + optionCalibrateValue = *(SANE_Bool *) value; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Word *) value = optionCalibrateValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ + +/* +This option lets the user select the scan resolution. The Canon fb630u +scanner supports the following resolutions: 75, 150, 300, 600, 1200 +*/ + +static const SANE_Word optionResolutionList[] = { + 4, /* Number of elements */ + 75, 150, 300, 600 /* Resolution list */ + /* also 600x1200, but ignore that for now. */ +}; + +static SANE_Option_Descriptor optionResolutionDescriptor = { + SANE_NAME_SCAN_RESOLUTION, + SANE_TITLE_SCAN_RESOLUTION, + SANE_DESC_SCAN_RESOLUTION, + SANE_TYPE_INT, + SANE_UNIT_DPI, + sizeof (SANE_Word), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC, + SANE_CONSTRAINT_WORD_LIST, + {(const SANE_String_Const *) optionResolutionList} +}; + +static SANE_Word optionResolutionValue = 75; + +static SANE_Status +optionResolutionCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + SANE_Status status; + SANE_Word autoValue = 75; + + handle = handle; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + status = + sanei_constrain_value (option->descriptor, (void *) &autoValue, info); + if (status != SANE_STATUS_GOOD) + return status; + optionResolutionValue = autoValue; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_SET_VALUE: + *info |= SANE_INFO_RELOAD_PARAMS; + optionResolutionValue = *(SANE_Word *) value; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Word *) value = optionResolutionValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ + +#ifdef GRAY +/* +This option lets the user select a gray scale scan +*/ +static SANE_Word optionGrayscaleValue = SANE_FALSE; + +static SANE_Option_Descriptor optionGrayscaleDescriptor = { + "gray", + SANE_I18N ("Grayscale scan"), + SANE_I18N ("Do a grayscale rather than color scan"), + SANE_TYPE_BOOL, + SANE_UNIT_NONE, + sizeof (SANE_Word), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_NONE, + {NULL} +}; + +static SANE_Status +optionGrayscaleCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + handle = handle; + option = option; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + *info |= SANE_INFO_RELOAD_PARAMS; + optionGrayscaleValue = *(SANE_Bool *) value; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Word *) value = optionGrayscaleValue; + break; + } + return SANE_STATUS_GOOD; +} +#endif /* GRAY */ + +/*-----------------------------------------------------------------*/ + +/* Analog Gain setting */ +static const SANE_Range aGainRange = { + 0, /* minimum */ + 64, /* maximum */ + 1 /* quantization */ +}; + +static SANE_Int optionAGainValue = 1; + +static SANE_Option_Descriptor optionAGainDescriptor = { + "gain", + SANE_I18N ("Analog Gain"), + SANE_I18N ("Increase or decrease the analog gain of the CCD array"), + SANE_TYPE_INT, + SANE_UNIT_NONE, + sizeof (SANE_Int), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, + SANE_CONSTRAINT_RANGE, + {(const SANE_String_Const *) &aGainRange} +}; + +static SANE_Status +optionAGainCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + option = option; + handle = handle; + info = info; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionAGainValue = *(SANE_Int *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Int *) value = optionAGainValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ + +/* Scanner gamma setting */ +static SANE_Fixed optionGammaValue = SANE_FIX (1.6); + +static SANE_Option_Descriptor optionGammaDescriptor = { + "gamma", + SANE_I18N ("Gamma Correction"), + SANE_I18N ("Selects the gamma corrected transfer curve"), + SANE_TYPE_FIXED, + SANE_UNIT_NONE, + sizeof (SANE_Int), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, + SANE_CONSTRAINT_NONE, + {NULL} +}; + + +static SANE_Status +optionGammaCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + option = option; + handle = handle; + info = info; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionGammaValue = *(SANE_Fixed *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Fixed *) value = optionGammaValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ + +/* +Scan range +*/ + +static const SANE_Range widthRange = { + 0, /* minimum */ + SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */ + 0 /* quantization */ +}; + +static const SANE_Range heightRange = { + 0, /* minimum */ + SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600), /* maximum */ + 0 /* quantization */ +}; + +/*-----------------------------------------------------------------*/ +/* +This option controls the top-left-x corner of the scan +*/ + +static SANE_Fixed optionTopLeftXValue = 0; + +static SANE_Option_Descriptor optionTopLeftXDescriptor = { + SANE_NAME_SCAN_TL_X, + SANE_TITLE_SCAN_TL_X, + SANE_DESC_SCAN_TL_X, + SANE_TYPE_FIXED, + SANE_UNIT_MM, + sizeof (SANE_Fixed), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_RANGE, + {(const SANE_String_Const *) &widthRange} +}; + +static SANE_Status +optionTopLeftXCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + option = option; + handle = handle; + value = value; /* Eliminate warning about unused parameters */ + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionTopLeftXValue = *(SANE_Fixed *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Fixed *) value = optionTopLeftXValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ +/* +This option controls the top-left-y corner of the scan +*/ + +static SANE_Fixed optionTopLeftYValue = 0; + +static SANE_Option_Descriptor optionTopLeftYDescriptor = { + SANE_NAME_SCAN_TL_Y, + SANE_TITLE_SCAN_TL_Y, + SANE_DESC_SCAN_TL_Y, + SANE_TYPE_FIXED, + SANE_UNIT_MM, + sizeof (SANE_Fixed), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_RANGE, + {(const SANE_String_Const *) &heightRange} +}; + +static SANE_Status +optionTopLeftYCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + /* Eliminate warnings about unused parameters */ + option = option; + handle = handle; + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionTopLeftYValue = *(SANE_Fixed *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Fixed *) value = optionTopLeftYValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ +/* +This option controls the bot-right-x corner of the scan +Default to 215.9mm, max. +*/ + +static SANE_Fixed optionBotRightXValue = SANE_FIX (215.9); + +static SANE_Option_Descriptor optionBotRightXDescriptor = { + SANE_NAME_SCAN_BR_X, + SANE_TITLE_SCAN_BR_X, + SANE_DESC_SCAN_BR_X, + SANE_TYPE_FIXED, + SANE_UNIT_MM, + sizeof (SANE_Fixed), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_RANGE, + {(const SANE_String_Const *) &widthRange} +}; + +static SANE_Status +optionBotRightXCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + /* Eliminate warnings about unused parameters */ + option = option; + handle = handle; + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionBotRightXValue = *(SANE_Fixed *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Fixed *) value = optionBotRightXValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ +/* +This option controls the bot-right-y corner of the scan +Default to 296.3mm, max +*/ + +static SANE_Fixed optionBotRightYValue = SANE_FIX (296.3); + +static SANE_Option_Descriptor optionBotRightYDescriptor = { + SANE_NAME_SCAN_BR_Y, + SANE_TITLE_SCAN_BR_Y, + SANE_DESC_SCAN_BR_Y, + SANE_TYPE_FIXED, + SANE_UNIT_MM, + sizeof (SANE_Fixed), + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, + SANE_CONSTRAINT_RANGE, + {(const SANE_String_Const *) &heightRange} +}; + +static SANE_Status +optionBotRightYCallback (SANE_Option * option, SANE_Handle handle, + SANE_Action action, void *value, SANE_Int * info) +{ + /* Eliminate warnings about unused parameters */ + option = option; + handle = handle; + + switch (action) + { + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_INVAL; + break; + case SANE_ACTION_SET_VALUE: + optionBotRightYValue = *(SANE_Fixed *) value; + *info |= SANE_INFO_RELOAD_PARAMS; + break; + case SANE_ACTION_GET_VALUE: + *(SANE_Fixed *) value = optionBotRightYValue; + break; + } + return SANE_STATUS_GOOD; +} + +/*-----------------------------------------------------------------*/ +/* +The following array binds the option descriptors to +their respective callback routines +*/ + +static SANE_Option so[] = { + {&optionNumOptionsDescriptor, optionNumOptionsCallback}, + {&optionResolutionDescriptor, optionResolutionCallback}, + {&optionCalibrateDescriptor, optionCalibrateCallback}, +#ifdef GRAY + {&optionGrayscaleDescriptor, optionGrayscaleCallback}, +#endif + {&optionAGainDescriptor, optionAGainCallback}, + {&optionGammaDescriptor, optionGammaCallback}, + {&optionTopLeftXDescriptor, optionTopLeftXCallback}, + {&optionTopLeftYDescriptor, optionTopLeftYCallback}, + {&optionBotRightXDescriptor, optionBotRightXCallback}, + {&optionBotRightYDescriptor, optionBotRightYCallback} +}; + +static SANE_Word +getNumberOfOptions (void) +{ + return NELEMS (so); +} + + +/* +This routine dispatches the control message to the appropriate +callback routine, it outght to be called by sane_control_option +after any driver specific validation. +*/ +static SANE_Status +dispatch_control_option (SANE_Handle handle, SANE_Int option, + SANE_Action action, void *value, SANE_Int * info) +{ + SANE_Option *op = so + option; + SANE_Int myinfo = 0; + SANE_Status status = SANE_STATUS_GOOD; + + if (option < 0 || option >= NELEMS (so)) + return SANE_STATUS_INVAL; /* Unknown option ... */ + + if ((action == SANE_ACTION_SET_VALUE) && + ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0)) + return SANE_STATUS_INVAL; + + if ((action == SANE_ACTION_GET_VALUE) && + ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0)) + return SANE_STATUS_INVAL; + + if ((action == SANE_ACTION_SET_AUTO) && + ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0)) + return SANE_STATUS_INVAL; + + if (action == SANE_ACTION_SET_VALUE) + { + status = sanei_constrain_value (op->descriptor, value, &myinfo); + if (status != SANE_STATUS_GOOD) + return status; + } + + status = (op->callback) (op, handle, action, value, &myinfo); + + if (info) + *info = myinfo; + + return status; +} + + +static SANE_Status +attach_scanner (const char *devicename, Canon_Device ** devp) +{ + CANON_Handle scan; + Canon_Device *dev; + SANE_Status status; + + DBG (3, "attach_scanner: %s\n", devicename); + + for (dev = first_dev; dev; dev = dev->next) + { + if (strcmp (dev->sane.name, devicename) == 0) + { + if (devp) + *devp = dev; + return SANE_STATUS_GOOD; + } + } + + dev = malloc (sizeof (*dev)); + if (!dev) + return SANE_STATUS_NO_MEM; + memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */ + + DBG (4, "attach_scanner: opening %s\n", devicename); + + status = CANON_open_device (&scan, devicename); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); + free (dev); + return status; + } + dev->name = strdup (devicename); + dev->sane.name = dev->name; + dev->sane.vendor = "CANON"; + dev->sane.model = CANON_get_device_name (&scan); + dev->sane.type = "flatbed scanner"; + CANON_close_device (&scan); + + ++num_devices; + dev->next = first_dev; + first_dev = dev; + + if (devp) + *devp = dev; + return SANE_STATUS_GOOD; +} + + +/* callback function for sanei_usb_attach_matching_devices +*/ +static SANE_Status +attach_one (const char *name) +{ + attach_scanner (name, 0); + return SANE_STATUS_GOOD; +} + + +/* + Find our devices + */ +SANE_Status +sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) +{ + char config_line[PATH_MAX]; + size_t len; + FILE *fp; + + DBG_INIT (); + +#if 0 + DBG_LEVEL = 10; +#endif + + DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", + version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); + DBG (1, "sane_init: SANE Canon630u backend version %d.%d.%d from %s\n", + SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); + + if (version_code) + *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); + + sanei_usb_init (); + + fp = sanei_config_open (CANONUSB_CONFIG_FILE); + if (!fp) + { + /* no config-file: try these */ + attach_scanner ("/dev/scanner", 0); + attach_scanner ("/dev/usbscanner", 0); + attach_scanner ("/dev/usb/scanner", 0); + return SANE_STATUS_GOOD; + } + + DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE); + + while (sanei_config_read (config_line, sizeof (config_line), fp)) + { + if (config_line[0] == '#') + continue; /* ignore line comments */ + + len = strlen (config_line); + + if (!len) + continue; /* ignore empty lines */ + + DBG (4, "attach_matching_devices(%s)\n", config_line); + sanei_usb_attach_matching_devices (config_line, attach_one); + } + + DBG (4, "finished reading configure file\n"); + + fclose (fp); + + return SANE_STATUS_GOOD; +} + + +void +sane_exit (void) +{ + Canon_Device *dev, *next; + + DBG (3, "sane_exit\n"); + + for (dev = first_dev; dev; dev = next) + { + next = dev->next; + free (dev->name); + free (dev); + } + + if (devlist) + free (devlist); + return; +} + + +SANE_Status +sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) +{ + Canon_Device *dev; + int i; + + DBG (3, "sane_get_devices(local_only = %d)\n", local_only); + + if (devlist) + free (devlist); + + devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); + if (!devlist) + return SANE_STATUS_NO_MEM; + + i = 0; + + for (dev = first_dev; i < num_devices; dev = dev->next) + devlist[i++] = &dev->sane; + + devlist[i++] = 0; + + *device_list = devlist; + + return SANE_STATUS_GOOD; +} + + +SANE_Status +sane_open (SANE_String_Const devicename, SANE_Handle * handle) +{ + Canon_Device *dev; + SANE_Status status; + Canon_Scanner *scanner; + + DBG (3, "sane_open\n"); + + if (devicename[0]) /* search for devicename */ + { + DBG (4, "sane_open: devicename=%s\n", devicename); + + for (dev = first_dev; dev; dev = dev->next) + if (strcmp (dev->sane.name, devicename) == 0) + break; + + if (!dev) + { + status = attach_scanner (devicename, &dev); + if (status != SANE_STATUS_GOOD) + return status; + } + } + else + { + DBG (2, "sane_open: no devicename, opening first device\n"); + dev = first_dev; + } + + if (!dev) + return SANE_STATUS_INVAL; + + scanner = malloc (sizeof (*scanner)); + if (!scanner) + return SANE_STATUS_NO_MEM; + + memset (scanner, 0, sizeof (*scanner)); + scanner->device = dev; + + status = CANON_open_device (&scanner->scan, dev->sane.name); + if (status != SANE_STATUS_GOOD) + { + free (scanner); + return status; + } + + *handle = scanner; + + /* insert newly opened handle into list of open handles: */ + scanner->next = first_handle; + + first_handle = scanner; + + return SANE_STATUS_GOOD; +} + + +void +sane_close (SANE_Handle handle) +{ + Canon_Scanner *prev, *scanner; + SANE_Status res; + + DBG (3, "sane_close\n"); + + if (!first_handle) + { + DBG (1, "ERROR: sane_close: no handles opened\n"); + return; + } + + /* remove handle from list of open handles: */ + + prev = NULL; + + for (scanner = first_handle; scanner; scanner = scanner->next) + { + if (scanner == handle) + break; + + prev = scanner; + } + + if (!scanner) + { + DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); + return; /* oops, not a handle we know about */ + } + + if (prev) + prev->next = scanner->next; + else + first_handle = scanner->next; + + res = CANON_close_device (&scanner->scan); + + free (scanner); +} + + +const SANE_Option_Descriptor * +sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) +{ + handle = handle; /* Eliminate compiler warning */ + + DBG (3, "sane_get_option_descriptor: option = %d\n", option); + if (option < 0 || option >= NELEMS (so)) + return NULL; + return so[option].descriptor; +} + +SANE_Status +sane_control_option (SANE_Handle handle, SANE_Int option, + SANE_Action action, void *value, SANE_Int * info) +{ + handle = handle; /* Eliminate compiler warning */ + + DBG (3, + "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", + handle, option, action, value, (void *)info); + + return dispatch_control_option (handle, option, action, value, info); +} + + +SANE_Status +sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) +{ + int rc = SANE_STATUS_GOOD; + int w = + SANE_UNFIX (optionBotRightXValue - + optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue; + int h = + SANE_UNFIX (optionBotRightYValue - + optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue; + + handle = handle; /* Eliminate compiler warning */ + + DBG (3, "sane_get_parameters\n"); + parms.depth = 8; + parms.last_frame = SANE_TRUE; + parms.pixels_per_line = w; + parms.lines = h; + +#ifdef GRAY + if (optionGrayscaleValue == SANE_TRUE) + { + parms.format = SANE_FRAME_GRAY; + parms.bytes_per_line = w; + } + else +#endif + { + parms.format = SANE_FRAME_RGB; + parms.bytes_per_line = w * 3; + } + *params = parms; + return rc; +} + + +SANE_Status +sane_start (SANE_Handle handle) +{ + Canon_Scanner *scanner = handle; + SANE_Status res; + + DBG (3, "sane_start\n"); + + res = CANON_set_scan_parameters (&scanner->scan, + optionCalibrateValue, +#ifdef GRAY + optionGrayscaleValue, +#else + SANE_FALSE, +#endif + SANE_UNFIX (optionTopLeftXValue) / + MM_IN_INCH * 600, + SANE_UNFIX (optionTopLeftYValue) / + MM_IN_INCH * 600, + SANE_UNFIX (optionBotRightXValue) / + MM_IN_INCH * 600, + SANE_UNFIX (optionBotRightYValue) / + MM_IN_INCH * 600, + optionResolutionValue, + optionAGainValue, + SANE_UNFIX (optionGammaValue)); + + if (res != SANE_STATUS_GOOD) + return res; + + return CANON_start_scan (&scanner->scan); +} + + +SANE_Status +sane_read (SANE_Handle handle, SANE_Byte * data, + SANE_Int max_length, SANE_Int * length) +{ + Canon_Scanner *scanner = handle; + return CANON_read (&scanner->scan, data, max_length, length); +} + + +void +sane_cancel (SANE_Handle handle) +{ + DBG (3, "sane_cancel: handle = %p\n", handle); + DBG (3, "sane_cancel: cancelling is unsupported in this backend\n"); +} + + +SANE_Status +sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) +{ + DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, + non_blocking); + if (non_blocking != SANE_FALSE) + return SANE_STATUS_UNSUPPORTED; + return SANE_STATUS_GOOD; +} + + +SANE_Status +sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) +{ + handle = handle; /* silence gcc */ + fd = fd; /* silence gcc */ + return SANE_STATUS_UNSUPPORTED; +} |