1141cc406Sopenharmony_ci/*************************************************************************** 2141cc406Sopenharmony_ci * SANE - Scanner Access Now Easy. 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci dc210.c 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci 11/11/98 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This file (C) 1998 Brian J. Murrell 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This file is part of the SANE package. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 13141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 14141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 15141cc406Sopenharmony_ci License, or (at your option) any later version. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 18141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 19141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20141cc406Sopenharmony_ci General Public License for more details. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 23141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 24141cc406Sopenharmony_ci 25141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 26141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 29141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 30141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 31141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 32141cc406Sopenharmony_ci account of linking the SANE library code into it. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 35141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 36141cc406Sopenharmony_ci License. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 39141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 40141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 43141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 44141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci *************************************************************************** 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci This file implements a SANE backend for the Kodak DC-210 49141cc406Sopenharmony_ci digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci (feedback to: sane-dc210@interlinx.bc.ca 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci This backend is based somewhat on the dc25 backend included in this 54141cc406Sopenharmony_ci package by Peter Fales 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci ***************************************************************************/ 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#include "../include/sane/config.h" 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#include <stdlib.h> 61141cc406Sopenharmony_ci#include <string.h> 62141cc406Sopenharmony_ci#include <stdio.h> 63141cc406Sopenharmony_ci#include <unistd.h> 64141cc406Sopenharmony_ci#include <fcntl.h> 65141cc406Sopenharmony_ci#include <limits.h> 66141cc406Sopenharmony_ci#include "../include/sane/sanei_jpeg.h" 67141cc406Sopenharmony_ci#include <sys/ioctl.h> 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#include "../include/sane/sane.h" 70141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 71141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci#define BACKEND_NAME dc210 74141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#include "dc210.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#ifndef PATH_MAX 79141cc406Sopenharmony_ci# define PATH_MAX 1024 80141cc406Sopenharmony_ci#endif 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci#define MAGIC (void *)0xab730324 83141cc406Sopenharmony_ci#define DC210_CONFIG_FILE "dc210.conf" 84141cc406Sopenharmony_ci#define THUMBSIZE 20736 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#ifdef B115200 87141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE B115200 88141cc406Sopenharmony_ci#else 89141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE B38400 90141cc406Sopenharmony_ci#endif 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci#if defined (__sgi) 93141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/ttyd1" /* Irix */ 94141cc406Sopenharmony_ci#elif defined (__sun) 95141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/term/a" /* Solaris */ 96141cc406Sopenharmony_ci#elif defined (hpux) 97141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/tty1d0" /* HP-UX */ 98141cc406Sopenharmony_ci#elif defined (__osf__) 99141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/tty00" /* Digital UNIX */ 100141cc406Sopenharmony_ci#else 101141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/ttyS0" /* Linux */ 102141cc406Sopenharmony_ci#endif 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_cistatic SANE_Bool is_open = 0; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_thumbnails; 107141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_snap; 108141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_lowres; 109141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_erase; 110141cc406Sopenharmony_cistatic SANE_Bool dumpinquiry; 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_cistatic struct jpeg_decompress_struct cinfo; 113141cc406Sopenharmony_cistatic djpeg_dest_ptr dest_mgr = NULL; 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_cistatic unsigned long cmdrespause = 250000UL; /* pause after sending cmd */ 116141cc406Sopenharmony_cistatic unsigned long breakpause = 1000000UL; /* pause after sending break */ 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_cistatic int bytes_in_buffer; 119141cc406Sopenharmony_cistatic int bytes_read_from_buffer; 120141cc406Sopenharmony_cistatic int total_bytes_read; 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_cistatic DC210 Camera; 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_cistatic SANE_Range image_range = { 125141cc406Sopenharmony_ci 0, 126141cc406Sopenharmony_ci 14, 127141cc406Sopenharmony_ci 0 128141cc406Sopenharmony_ci}; 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_cistatic SANE_Option_Descriptor sod[] = { 131141cc406Sopenharmony_ci { 132141cc406Sopenharmony_ci SANE_NAME_NUM_OPTIONS, 133141cc406Sopenharmony_ci SANE_TITLE_NUM_OPTIONS, 134141cc406Sopenharmony_ci SANE_DESC_NUM_OPTIONS, 135141cc406Sopenharmony_ci SANE_TYPE_INT, 136141cc406Sopenharmony_ci SANE_UNIT_NONE, 137141cc406Sopenharmony_ci sizeof (SANE_Word), 138141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT, 139141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 140141cc406Sopenharmony_ci {NULL} 141141cc406Sopenharmony_ci } 142141cc406Sopenharmony_ci , 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci#define D25_OPT_IMAGE_SELECTION 1 145141cc406Sopenharmony_ci { 146141cc406Sopenharmony_ci "", 147141cc406Sopenharmony_ci "Image Selection", 148141cc406Sopenharmony_ci "Selection of the image to load.", 149141cc406Sopenharmony_ci SANE_TYPE_GROUP, 150141cc406Sopenharmony_ci SANE_UNIT_NONE, 151141cc406Sopenharmony_ci 0, 152141cc406Sopenharmony_ci 0, 153141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 154141cc406Sopenharmony_ci {NULL} 155141cc406Sopenharmony_ci } 156141cc406Sopenharmony_ci , 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci#define DC210_OPT_IMAGE_NUMBER 2 159141cc406Sopenharmony_ci { 160141cc406Sopenharmony_ci "image", 161141cc406Sopenharmony_ci "Image Number", 162141cc406Sopenharmony_ci "Select Image Number to load from camera", 163141cc406Sopenharmony_ci SANE_TYPE_INT, 164141cc406Sopenharmony_ci SANE_UNIT_NONE, 165141cc406Sopenharmony_ci 4, 166141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 167141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 168141cc406Sopenharmony_ci {(void *) & image_range} 169141cc406Sopenharmony_ci } 170141cc406Sopenharmony_ci , 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_ci#define DC210_OPT_THUMBS 3 173141cc406Sopenharmony_ci { 174141cc406Sopenharmony_ci "thumbs", 175141cc406Sopenharmony_ci "Load Thumbnail", 176141cc406Sopenharmony_ci "Load the image as thumbnail.", 177141cc406Sopenharmony_ci SANE_TYPE_BOOL, 178141cc406Sopenharmony_ci SANE_UNIT_NONE, 179141cc406Sopenharmony_ci sizeof (SANE_Word), 180141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 181141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 182141cc406Sopenharmony_ci {NULL} 183141cc406Sopenharmony_ci } 184141cc406Sopenharmony_ci , 185141cc406Sopenharmony_ci#define DC210_OPT_SNAP 4 186141cc406Sopenharmony_ci { 187141cc406Sopenharmony_ci "snap", 188141cc406Sopenharmony_ci "Snap new picture", 189141cc406Sopenharmony_ci "Take new picture and download it", 190141cc406Sopenharmony_ci SANE_TYPE_BOOL, 191141cc406Sopenharmony_ci SANE_UNIT_NONE, 192141cc406Sopenharmony_ci sizeof (SANE_Word), 193141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ , 194141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 195141cc406Sopenharmony_ci {NULL} 196141cc406Sopenharmony_ci } 197141cc406Sopenharmony_ci , 198141cc406Sopenharmony_ci#define DC210_OPT_LOWRES 5 199141cc406Sopenharmony_ci { 200141cc406Sopenharmony_ci "lowres", 201141cc406Sopenharmony_ci "Low Resolution", 202141cc406Sopenharmony_ci "Resolution of new pictures", 203141cc406Sopenharmony_ci SANE_TYPE_BOOL, 204141cc406Sopenharmony_ci SANE_UNIT_NONE, 205141cc406Sopenharmony_ci sizeof (SANE_Word), 206141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE 207141cc406Sopenharmony_ci /* | SANE_CAP_ADVANCED */ , 208141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 209141cc406Sopenharmony_ci {NULL} 210141cc406Sopenharmony_ci } 211141cc406Sopenharmony_ci , 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci#define DC210_OPT_ERASE 6 214141cc406Sopenharmony_ci { 215141cc406Sopenharmony_ci "erase", 216141cc406Sopenharmony_ci "Erase", 217141cc406Sopenharmony_ci "Erase the picture after downloading", 218141cc406Sopenharmony_ci SANE_TYPE_BOOL, 219141cc406Sopenharmony_ci SANE_UNIT_NONE, 220141cc406Sopenharmony_ci sizeof (SANE_Word), 221141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 222141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 223141cc406Sopenharmony_ci {NULL} 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci , 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci#define DC210_OPT_DEFAULT 7 228141cc406Sopenharmony_ci { 229141cc406Sopenharmony_ci "default-enhancements", 230141cc406Sopenharmony_ci "Defaults", 231141cc406Sopenharmony_ci "Set default values for enhancement controls.", 232141cc406Sopenharmony_ci SANE_TYPE_BUTTON, 233141cc406Sopenharmony_ci SANE_UNIT_NONE, 234141cc406Sopenharmony_ci 0, 235141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 236141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 237141cc406Sopenharmony_ci {NULL} 238141cc406Sopenharmony_ci } 239141cc406Sopenharmony_ci , 240141cc406Sopenharmony_ci#define DC210_OPT_INIT_DC210 8 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci "camera-init", 243141cc406Sopenharmony_ci "Re-establish Communications", 244141cc406Sopenharmony_ci "Re-establish communications with camera (in case of timeout, etc.)", 245141cc406Sopenharmony_ci SANE_TYPE_BUTTON, 246141cc406Sopenharmony_ci SANE_UNIT_NONE, 247141cc406Sopenharmony_ci 0, 248141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 249141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 250141cc406Sopenharmony_ci {NULL} 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci}; 253141cc406Sopenharmony_ci 254141cc406Sopenharmony_cistatic SANE_Parameters parms = { 255141cc406Sopenharmony_ci SANE_FRAME_RGB, 256141cc406Sopenharmony_ci 0, 257141cc406Sopenharmony_ci 0, /* Number of bytes returned per scan line: */ 258141cc406Sopenharmony_ci 0, /* Number of pixels per scan line. */ 259141cc406Sopenharmony_ci 0, /* Number of lines for the current scan. */ 260141cc406Sopenharmony_ci 8, /* Number of bits per sample. */ 261141cc406Sopenharmony_ci}; 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ci 266141cc406Sopenharmony_cistatic unsigned char shoot_pck[] = SHOOT_PCK; 267141cc406Sopenharmony_cistatic unsigned char init_pck[] = INIT_PCK; 268141cc406Sopenharmony_cistatic unsigned char thumb_pck[] = THUMBS_PCK; 269141cc406Sopenharmony_cistatic unsigned char pic_pck[] = PICS_PCK; 270141cc406Sopenharmony_cistatic unsigned char pic_info_pck[] = PICS_INFO_PCK; 271141cc406Sopenharmony_cistatic unsigned char info_pck[] = INFO_PCK; 272141cc406Sopenharmony_cistatic unsigned char erase_pck[] = ERASE_PCK; 273141cc406Sopenharmony_cistatic unsigned char res_pck[] = RES_PCK; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_cistatic struct pkt_speed speeds[] = SPEEDS; 276141cc406Sopenharmony_cistatic struct termios tty_orig; 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci#include <sys/time.h> 279141cc406Sopenharmony_ci#include <unistd.h> 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_cistatic int 282141cc406Sopenharmony_cisend_pck (int fd, unsigned char *pck) 283141cc406Sopenharmony_ci{ 284141cc406Sopenharmony_ci int n; 285141cc406Sopenharmony_ci unsigned char r = 0xf0; /* prime the loop with a "camera busy" */ 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci /* keep trying if camera says it's busy */ 288141cc406Sopenharmony_ci while (r == 0xf0) 289141cc406Sopenharmony_ci { 290141cc406Sopenharmony_ci /* 291141cc406Sopenharmony_ci * Not quite sure why we need this, but the program works a whole 292141cc406Sopenharmony_ci * lot better (at least on the DC210) with this short delay. 293141cc406Sopenharmony_ci */ 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_ci if (write (fd, (char *) pck, 8) != 8) 296141cc406Sopenharmony_ci { 297141cc406Sopenharmony_ci DBG (2, "send_pck: error: write returned -1\n"); 298141cc406Sopenharmony_ci return -1; 299141cc406Sopenharmony_ci } 300141cc406Sopenharmony_ci /* need to wait before we read command result */ 301141cc406Sopenharmony_ci usleep (cmdrespause); 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci if ((n = read (fd, (char *) &r, 1)) != 1) 304141cc406Sopenharmony_ci { 305141cc406Sopenharmony_ci DBG (2, "send_pck: error: read returned -1\n"); 306141cc406Sopenharmony_ci return -1; 307141cc406Sopenharmony_ci } 308141cc406Sopenharmony_ci } 309141cc406Sopenharmony_ci return (r == 0xd1) ? 0 : -1; 310141cc406Sopenharmony_ci} 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_cistatic int 313141cc406Sopenharmony_ciinit_dc210 (DC210 * camera) 314141cc406Sopenharmony_ci{ 315141cc406Sopenharmony_ci struct termios tty_new; 316141cc406Sopenharmony_ci int speed_index; 317141cc406Sopenharmony_ci 318141cc406Sopenharmony_ci for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++) 319141cc406Sopenharmony_ci { 320141cc406Sopenharmony_ci if (speeds[speed_index].baud == camera->baud) 321141cc406Sopenharmony_ci { 322141cc406Sopenharmony_ci init_pck[2] = speeds[speed_index].pkt_code[0]; 323141cc406Sopenharmony_ci init_pck[3] = speeds[speed_index].pkt_code[1]; 324141cc406Sopenharmony_ci break; 325141cc406Sopenharmony_ci } 326141cc406Sopenharmony_ci } 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci if (init_pck[2] == 0) 329141cc406Sopenharmony_ci { 330141cc406Sopenharmony_ci DBG (2, "unsupported baud rate.\n"); 331141cc406Sopenharmony_ci return -1; 332141cc406Sopenharmony_ci } 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_ci /* 335141cc406Sopenharmony_ci Open device file. 336141cc406Sopenharmony_ci */ 337141cc406Sopenharmony_ci if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1) 338141cc406Sopenharmony_ci { 339141cc406Sopenharmony_ci DBG (2, "init_dc210: error: could not open %s for read/write\n", 340141cc406Sopenharmony_ci camera->tty_name); 341141cc406Sopenharmony_ci return -1; 342141cc406Sopenharmony_ci } 343141cc406Sopenharmony_ci /* 344141cc406Sopenharmony_ci Save old device information to restore when we are done. 345141cc406Sopenharmony_ci */ 346141cc406Sopenharmony_ci if (tcgetattr (camera->fd, &tty_orig) == -1) 347141cc406Sopenharmony_ci { 348141cc406Sopenharmony_ci DBG (2, "init_dc210: error: could not get attributes\n"); 349141cc406Sopenharmony_ci return -1; 350141cc406Sopenharmony_ci } 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios)); 353141cc406Sopenharmony_ci /* 354141cc406Sopenharmony_ci We need the device to be raw. 8 bits even parity on 9600 baud to start. 355141cc406Sopenharmony_ci */ 356141cc406Sopenharmony_ci#ifdef HAVE_CFMAKERAW 357141cc406Sopenharmony_ci cfmakeraw (&tty_new); 358141cc406Sopenharmony_ci#else 359141cc406Sopenharmony_ci /* Modified to set the port REALLY as required. Code inspired by 360141cc406Sopenharmony_ci the gPhoto2 serial port setup */ 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci /* input control settings */ 363141cc406Sopenharmony_ci tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | 364141cc406Sopenharmony_ci IXANY | IXON | IXOFF | INPCK | ISTRIP); 365141cc406Sopenharmony_ci tty_new.c_iflag |= (BRKINT | IGNPAR); 366141cc406Sopenharmony_ci /* output control settings */ 367141cc406Sopenharmony_ci tty_new.c_oflag &= ~OPOST; 368141cc406Sopenharmony_ci /* hardware control settings */ 369141cc406Sopenharmony_ci tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8; 370141cc406Sopenharmony_ci tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB); 371141cc406Sopenharmony_ci# if defined(__sgi) 372141cc406Sopenharmony_ci tty_new.c_cflag &= ~CNEW_RTSCTS; 373141cc406Sopenharmony_ci# else 374141cc406Sopenharmony_ci/* OS/2 doesn't have CRTSCTS - will this work for them? */ 375141cc406Sopenharmony_ci# ifdef CRTSCTS 376141cc406Sopenharmony_ci tty_new.c_cflag &= ~CRTSCTS; 377141cc406Sopenharmony_ci# endif 378141cc406Sopenharmony_ci# endif 379141cc406Sopenharmony_ci tty_new.c_cflag |= CLOCAL | CREAD; 380141cc406Sopenharmony_ci#endif 381141cc406Sopenharmony_ci /* line discipline settings */ 382141cc406Sopenharmony_ci tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | 383141cc406Sopenharmony_ci ECHOK | IEXTEN); 384141cc406Sopenharmony_ci tty_new.c_cc[VMIN] = 0; 385141cc406Sopenharmony_ci tty_new.c_cc[VTIME] = 5; 386141cc406Sopenharmony_ci cfsetospeed (&tty_new, B9600); 387141cc406Sopenharmony_ci cfsetispeed (&tty_new, B9600); 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci DBG (2, "init_dc210: error: could not set attributes\n"); 392141cc406Sopenharmony_ci return -1; 393141cc406Sopenharmony_ci } 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci /* send a break to get it back to a known state */ 396141cc406Sopenharmony_ci /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK, 397141cc406Sopenharmony_ci * and TCSBRKP, but that is system dependent. e.g. on irix a non-zero 398141cc406Sopenharmony_ci * value does a drain instead of a break. A zero value is universally 399141cc406Sopenharmony_ci * used to send a break. 400141cc406Sopenharmony_ci */ 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci#ifdef HAVE_TCSENDBREAK 403141cc406Sopenharmony_ci tcsendbreak (camera->fd, 0); 404141cc406Sopenharmony_ci# if defined(__sgi) 405141cc406Sopenharmony_ci tcdrain (camera->fd); 406141cc406Sopenharmony_ci# endif 407141cc406Sopenharmony_ci# elif defined(TCSBRKP) 408141cc406Sopenharmony_ci ioctl (camera->fd, TCSBRKP, 0); 409141cc406Sopenharmony_ci# elif defined(TCSBRK) 410141cc406Sopenharmony_ci ioctl (camera->fd, TCSBRK, 0); 411141cc406Sopenharmony_ci#endif 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci /* and wait for it to recover from the break */ 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci#ifdef HAVE_USLEEP 416141cc406Sopenharmony_ci usleep (breakpause); 417141cc406Sopenharmony_ci#else 418141cc406Sopenharmony_ci sleep (1); 419141cc406Sopenharmony_ci#endif 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci if (send_pck (camera->fd, init_pck) == -1) 422141cc406Sopenharmony_ci { 423141cc406Sopenharmony_ci /* 424141cc406Sopenharmony_ci * The camera always powers up at 9600, so we try 425141cc406Sopenharmony_ci * that first. However, it may be already set to 426141cc406Sopenharmony_ci * a different speed. Try the entries in the table: 427141cc406Sopenharmony_ci */ 428141cc406Sopenharmony_ci 429141cc406Sopenharmony_ci for (speed_index = NELEMS (speeds) - 1; speed_index > 0; speed_index--) 430141cc406Sopenharmony_ci { 431141cc406Sopenharmony_ci int x; 432141cc406Sopenharmony_ci DBG (3, "init_dc210: changing speed to %d\n", 433141cc406Sopenharmony_ci (int) speeds[speed_index].baud); 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci cfsetospeed (&tty_new, speeds[speed_index].baud); 436141cc406Sopenharmony_ci cfsetispeed (&tty_new, speeds[speed_index].baud); 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) 439141cc406Sopenharmony_ci { 440141cc406Sopenharmony_ci DBG (2, "init_dc210: error: could not set attributes\n"); 441141cc406Sopenharmony_ci return -1; 442141cc406Sopenharmony_ci } 443141cc406Sopenharmony_ci for (x = 0; x < 3; x++) 444141cc406Sopenharmony_ci if (send_pck (camera->fd, init_pck) != -1) 445141cc406Sopenharmony_ci break; 446141cc406Sopenharmony_ci } 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci if (speed_index == 0) 449141cc406Sopenharmony_ci { 450141cc406Sopenharmony_ci tcsetattr (camera->fd, TCSANOW, &tty_orig); 451141cc406Sopenharmony_ci DBG (2, "init_dc210: error: no suitable baud rate\n"); 452141cc406Sopenharmony_ci return -1; 453141cc406Sopenharmony_ci } 454141cc406Sopenharmony_ci } 455141cc406Sopenharmony_ci /* 456141cc406Sopenharmony_ci Set speed to requested speed. 457141cc406Sopenharmony_ci */ 458141cc406Sopenharmony_ci cfsetospeed (&tty_new, Camera.baud); 459141cc406Sopenharmony_ci cfsetispeed (&tty_new, Camera.baud); 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) 462141cc406Sopenharmony_ci { 463141cc406Sopenharmony_ci DBG (2, "init_dc210: error: could not set attributes\n"); 464141cc406Sopenharmony_ci return -1; 465141cc406Sopenharmony_ci } 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_ci return camera->fd; 468141cc406Sopenharmony_ci} 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_cistatic void 471141cc406Sopenharmony_ciclose_dc210 (int fd) 472141cc406Sopenharmony_ci{ 473141cc406Sopenharmony_ci /* 474141cc406Sopenharmony_ci * Put the camera back to 9600 baud 475141cc406Sopenharmony_ci */ 476141cc406Sopenharmony_ci 477141cc406Sopenharmony_ci if (close (fd) == -1) 478141cc406Sopenharmony_ci { 479141cc406Sopenharmony_ci DBG (4, "close_dc210: error: could not close device\n"); 480141cc406Sopenharmony_ci } 481141cc406Sopenharmony_ci} 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ciint 484141cc406Sopenharmony_ciget_info (DC210 * camera) 485141cc406Sopenharmony_ci{ 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci char f[] = "get_info"; 488141cc406Sopenharmony_ci unsigned char buf[256]; 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci if (send_pck (camera->fd, info_pck) == -1) 491141cc406Sopenharmony_ci { 492141cc406Sopenharmony_ci DBG (2, "%s: error: send_pck returned -1\n", f); 493141cc406Sopenharmony_ci return -1; 494141cc406Sopenharmony_ci } 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci DBG (9, "%s: read info packet\n", f); 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci if (read_data (camera->fd, buf, 256) == -1) 499141cc406Sopenharmony_ci { 500141cc406Sopenharmony_ci DBG (2, "%s: error: read_data returned -1\n", f); 501141cc406Sopenharmony_ci return -1; 502141cc406Sopenharmony_ci } 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci if (end_of_data (camera->fd) == -1) 505141cc406Sopenharmony_ci { 506141cc406Sopenharmony_ci DBG (2, "%s: error: end_of_data returned -1\n", f); 507141cc406Sopenharmony_ci return -1; 508141cc406Sopenharmony_ci } 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci camera->model = buf[1]; 511141cc406Sopenharmony_ci camera->ver_major = buf[2]; 512141cc406Sopenharmony_ci camera->ver_minor = buf[3]; 513141cc406Sopenharmony_ci camera->pic_taken = buf[56] << 8 | buf[57]; 514141cc406Sopenharmony_ci camera->pic_left = buf[72] << 8 | buf[73]; 515141cc406Sopenharmony_ci camera->flags.low_res = buf[22]; 516141cc406Sopenharmony_ci camera->flags.low_batt = buf[8]; 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_ci return 0; 519141cc406Sopenharmony_ci} 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_cistatic int 522141cc406Sopenharmony_ciread_data (int fd, unsigned char *buf, int sz) 523141cc406Sopenharmony_ci{ 524141cc406Sopenharmony_ci unsigned char ccsum; 525141cc406Sopenharmony_ci unsigned char rcsum; 526141cc406Sopenharmony_ci unsigned char c; 527141cc406Sopenharmony_ci int n; 528141cc406Sopenharmony_ci int r = 0; 529141cc406Sopenharmony_ci int i; 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci/* read the control byte */ 532141cc406Sopenharmony_ci if (read (fd, &c, 1) != 1) 533141cc406Sopenharmony_ci { 534141cc406Sopenharmony_ci DBG (2, 535141cc406Sopenharmony_ci "read_data: error: read for packet control byte returned bad status\n"); 536141cc406Sopenharmony_ci return -1; 537141cc406Sopenharmony_ci } 538141cc406Sopenharmony_ci if (c != 1) 539141cc406Sopenharmony_ci { 540141cc406Sopenharmony_ci DBG (2, "read_data: error: incorrect packet control byte: %02x\n", c); 541141cc406Sopenharmony_ci return -1; 542141cc406Sopenharmony_ci } 543141cc406Sopenharmony_ci for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r) 544141cc406Sopenharmony_ci ; 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci if (r <= 0) 547141cc406Sopenharmony_ci { 548141cc406Sopenharmony_ci DBG (2, "read_data: error: read returned -1\n"); 549141cc406Sopenharmony_ci return -1; 550141cc406Sopenharmony_ci } 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci if (n < sz || read (fd, &rcsum, 1) != 1) 553141cc406Sopenharmony_ci { 554141cc406Sopenharmony_ci DBG (2, "read_data: error: buffer underrun or no checksum\n"); 555141cc406Sopenharmony_ci return -1; 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci for (i = 0, ccsum = 0; i < n; i++) 559141cc406Sopenharmony_ci ccsum ^= buf[i]; 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci if (ccsum != rcsum) 562141cc406Sopenharmony_ci { 563141cc406Sopenharmony_ci DBG (2, "read_data: error: bad checksum (%02x !=%02x)\n", rcsum, ccsum); 564141cc406Sopenharmony_ci return -1; 565141cc406Sopenharmony_ci } 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci c = 0xd2; 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci if (write (fd, (char *) &c, 1) != 1) 570141cc406Sopenharmony_ci { 571141cc406Sopenharmony_ci DBG (2, "read_data: error: write ack\n"); 572141cc406Sopenharmony_ci return -1; 573141cc406Sopenharmony_ci } 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci return 0; 576141cc406Sopenharmony_ci} 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_cistatic int 579141cc406Sopenharmony_ciend_of_data (int fd) 580141cc406Sopenharmony_ci{ 581141cc406Sopenharmony_ci unsigned char c; 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci do 584141cc406Sopenharmony_ci { /* loop until the camera isn't busy */ 585141cc406Sopenharmony_ci if (read (fd, &c, 1) != 1) 586141cc406Sopenharmony_ci { 587141cc406Sopenharmony_ci DBG (2, "end_of_data: error: read returned -1\n"); 588141cc406Sopenharmony_ci return -1; 589141cc406Sopenharmony_ci } 590141cc406Sopenharmony_ci if (c == 0) /* got successful end of data */ 591141cc406Sopenharmony_ci return 0; /* return success */ 592141cc406Sopenharmony_ci sleep (1); /* not too fast */ 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci while (c == 0xf0); 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci /* Accck! Not busy, but not a good end of data either */ 597141cc406Sopenharmony_ci if (c != 0) 598141cc406Sopenharmony_ci { 599141cc406Sopenharmony_ci DBG (2, "end_of_data: error: bad EOD from camera (%02x)\n", 600141cc406Sopenharmony_ci (unsigned) c); 601141cc406Sopenharmony_ci return -1; 602141cc406Sopenharmony_ci } 603141cc406Sopenharmony_ci return 0; /* should never get here but shut gcc -Wall up */ 604141cc406Sopenharmony_ci} 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_cistatic int 607141cc406Sopenharmony_cierase (int fd) 608141cc406Sopenharmony_ci{ 609141cc406Sopenharmony_ci if (send_pck (fd, erase_pck) == -1) 610141cc406Sopenharmony_ci { 611141cc406Sopenharmony_ci DBG (3, "erase: error: send_pck returned -1\n"); 612141cc406Sopenharmony_ci return -1; 613141cc406Sopenharmony_ci } 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci if (end_of_data (fd) == -1) 616141cc406Sopenharmony_ci { 617141cc406Sopenharmony_ci DBG (3, "erase: error: end_of_data returned -1\n"); 618141cc406Sopenharmony_ci return -1; 619141cc406Sopenharmony_ci } 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci return 0; 622141cc406Sopenharmony_ci} 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_cistatic int 625141cc406Sopenharmony_cichange_res (int fd, unsigned char res) 626141cc406Sopenharmony_ci{ 627141cc406Sopenharmony_ci char f[] = "change_res"; 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci DBG (127, "%s called\n", f); 630141cc406Sopenharmony_ci if (res != 0 && res != 1) 631141cc406Sopenharmony_ci { 632141cc406Sopenharmony_ci DBG (3, "%s: error: unsupported resolution\n", f); 633141cc406Sopenharmony_ci return -1; 634141cc406Sopenharmony_ci } 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci /* cameras resolution semantics are opposite of ours */ 637141cc406Sopenharmony_ci res = !res; 638141cc406Sopenharmony_ci DBG (127, "%s: setting res to %d\n", f, res); 639141cc406Sopenharmony_ci res_pck[2] = res; 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_ci if (send_pck (fd, res_pck) == -1) 642141cc406Sopenharmony_ci { 643141cc406Sopenharmony_ci DBG (4, "%s: error: send_pck returned -1\n", f); 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci if (end_of_data (fd) == -1) 647141cc406Sopenharmony_ci { 648141cc406Sopenharmony_ci DBG (4, "%s: error: end_of_data returned -1\n", f); 649141cc406Sopenharmony_ci } 650141cc406Sopenharmony_ci return 0; 651141cc406Sopenharmony_ci} 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ciSANE_Status 654141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 655141cc406Sopenharmony_ci{ 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci char f[] = "sane_init"; 658141cc406Sopenharmony_ci char dev_name[PATH_MAX], *p; 659141cc406Sopenharmony_ci size_t len; 660141cc406Sopenharmony_ci FILE *fp; 661141cc406Sopenharmony_ci int baud; 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci DBG_INIT (); 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci if (version_code) 666141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 667141cc406Sopenharmony_ci 668141cc406Sopenharmony_ci fp = sanei_config_open (DC210_CONFIG_FILE); 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci /* defaults */ 671141cc406Sopenharmony_ci Camera.baud = DEFAULT_BAUD_RATE; 672141cc406Sopenharmony_ci Camera.tty_name = DEFAULT_TTY; 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci if (!fp) 675141cc406Sopenharmony_ci { 676141cc406Sopenharmony_ci /* default to /dev/whatever instead of insisting on config file */ 677141cc406Sopenharmony_ci DBG (1, "%s: missing config file '%s'\n", f, DC210_CONFIG_FILE); 678141cc406Sopenharmony_ci } 679141cc406Sopenharmony_ci else 680141cc406Sopenharmony_ci { 681141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 682141cc406Sopenharmony_ci { 683141cc406Sopenharmony_ci dev_name[sizeof (dev_name) - 1] = '\0'; 684141cc406Sopenharmony_ci DBG (20, "%s: config- %s\n", f, dev_name); 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci if (dev_name[0] == '#') 687141cc406Sopenharmony_ci continue; /* ignore line comments */ 688141cc406Sopenharmony_ci len = strlen (dev_name); 689141cc406Sopenharmony_ci if (!len) 690141cc406Sopenharmony_ci continue; /* ignore empty lines */ 691141cc406Sopenharmony_ci if (strncmp (dev_name, "port=", 5) == 0) 692141cc406Sopenharmony_ci { 693141cc406Sopenharmony_ci p = strchr (dev_name, '/'); 694141cc406Sopenharmony_ci if (p) 695141cc406Sopenharmony_ci Camera.tty_name = strdup (p); 696141cc406Sopenharmony_ci DBG (20, "Config file port=%s\n", Camera.tty_name); 697141cc406Sopenharmony_ci } 698141cc406Sopenharmony_ci else if (strncmp (dev_name, "baud=", 5) == 0) 699141cc406Sopenharmony_ci { 700141cc406Sopenharmony_ci baud = atoi (&dev_name[5]); 701141cc406Sopenharmony_ci switch (baud) 702141cc406Sopenharmony_ci { 703141cc406Sopenharmony_ci case 9600: 704141cc406Sopenharmony_ci Camera.baud = B9600; 705141cc406Sopenharmony_ci break; 706141cc406Sopenharmony_ci case 19200: 707141cc406Sopenharmony_ci Camera.baud = B19200; 708141cc406Sopenharmony_ci break; 709141cc406Sopenharmony_ci case 38400: 710141cc406Sopenharmony_ci Camera.baud = B38400; 711141cc406Sopenharmony_ci break; 712141cc406Sopenharmony_ci#ifdef B57600 713141cc406Sopenharmony_ci case 57600: 714141cc406Sopenharmony_ci Camera.baud = B57600; 715141cc406Sopenharmony_ci break; 716141cc406Sopenharmony_ci#endif 717141cc406Sopenharmony_ci#ifdef B115200 718141cc406Sopenharmony_ci case 115200: 719141cc406Sopenharmony_ci Camera.baud = B115200; 720141cc406Sopenharmony_ci break; 721141cc406Sopenharmony_ci#endif 722141cc406Sopenharmony_ci } 723141cc406Sopenharmony_ci DBG (20, "Config file baud=%d\n", Camera.baud); 724141cc406Sopenharmony_ci } 725141cc406Sopenharmony_ci else if (strcmp (dev_name, "dumpinquiry") == 0) 726141cc406Sopenharmony_ci { 727141cc406Sopenharmony_ci dumpinquiry = SANE_TRUE; 728141cc406Sopenharmony_ci } 729141cc406Sopenharmony_ci else if (strncmp (dev_name, "cmdrespause=", 12) == 0) 730141cc406Sopenharmony_ci { 731141cc406Sopenharmony_ci cmdrespause = atoi (&dev_name[12]); 732141cc406Sopenharmony_ci DBG (20, "Config file cmdrespause=%lu\n", cmdrespause); 733141cc406Sopenharmony_ci } 734141cc406Sopenharmony_ci else if (strncmp (dev_name, "breakpause=", 11) == 0) 735141cc406Sopenharmony_ci { 736141cc406Sopenharmony_ci breakpause = atoi (&dev_name[11]); 737141cc406Sopenharmony_ci DBG (20, "Config file breakpause=%lu\n", breakpause); 738141cc406Sopenharmony_ci } 739141cc406Sopenharmony_ci } 740141cc406Sopenharmony_ci fclose (fp); 741141cc406Sopenharmony_ci } 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci if (init_dc210 (&Camera) == -1) 744141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci if (get_info (&Camera) == -1) 747141cc406Sopenharmony_ci { 748141cc406Sopenharmony_ci DBG (2, "error: could not get info\n"); 749141cc406Sopenharmony_ci close_dc210 (Camera.fd); 750141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 751141cc406Sopenharmony_ci } 752141cc406Sopenharmony_ci if (Camera.pic_taken == 0) 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; 755141cc406Sopenharmony_ci image_range.min = 0; 756141cc406Sopenharmony_ci image_range.max = 0; 757141cc406Sopenharmony_ci } 758141cc406Sopenharmony_ci else 759141cc406Sopenharmony_ci { 760141cc406Sopenharmony_ci sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 761141cc406Sopenharmony_ci image_range.min = 1; 762141cc406Sopenharmony_ci image_range.max = Camera.pic_taken; 763141cc406Sopenharmony_ci } 764141cc406Sopenharmony_ci 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci /* load the current images array */ 767141cc406Sopenharmony_ci Camera.Pictures = get_pictures_info (); 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci if (Camera.pic_taken == 0) 770141cc406Sopenharmony_ci { 771141cc406Sopenharmony_ci Camera.current_picture_number = 0; 772141cc406Sopenharmony_ci parms.bytes_per_line = 0; 773141cc406Sopenharmony_ci parms.pixels_per_line = 0; 774141cc406Sopenharmony_ci parms.lines = 0; 775141cc406Sopenharmony_ci } 776141cc406Sopenharmony_ci else 777141cc406Sopenharmony_ci { 778141cc406Sopenharmony_ci Camera.current_picture_number = 1; 779141cc406Sopenharmony_ci if (Camera.Pictures[Camera.current_picture_number - 1].low_res) 780141cc406Sopenharmony_ci { 781141cc406Sopenharmony_ci parms.bytes_per_line = 640 * 3; 782141cc406Sopenharmony_ci parms.pixels_per_line = 640; 783141cc406Sopenharmony_ci parms.lines = 480; 784141cc406Sopenharmony_ci } 785141cc406Sopenharmony_ci else 786141cc406Sopenharmony_ci { 787141cc406Sopenharmony_ci parms.bytes_per_line = 1152 * 3; 788141cc406Sopenharmony_ci parms.pixels_per_line = 1152; 789141cc406Sopenharmony_ci parms.lines = 864; 790141cc406Sopenharmony_ci } 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci if (dumpinquiry) 794141cc406Sopenharmony_ci { 795141cc406Sopenharmony_ci DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n"); 796141cc406Sopenharmony_ci DBG (0, "Model...........: DC%x\n", Camera.model); 797141cc406Sopenharmony_ci DBG (0, "Firmware version: %d.%d\n", Camera.ver_major, 798141cc406Sopenharmony_ci Camera.ver_minor); 799141cc406Sopenharmony_ci DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken, 800141cc406Sopenharmony_ci Camera.pic_taken + Camera.pic_left); 801141cc406Sopenharmony_ci DBG (0, "Resolution......: %s\n", 802141cc406Sopenharmony_ci Camera.flags.low_res ? "low" : "high"); 803141cc406Sopenharmony_ci DBG (0, "Battery state...: %s\n", 804141cc406Sopenharmony_ci Camera.flags.low_batt ? "low" : "good"); 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 808141cc406Sopenharmony_ci} 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_civoid 811141cc406Sopenharmony_cisane_exit (void) 812141cc406Sopenharmony_ci{ 813141cc406Sopenharmony_ci} 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci/* Device select/open/close */ 816141cc406Sopenharmony_ci 817141cc406Sopenharmony_cistatic const SANE_Device dev[] = { 818141cc406Sopenharmony_ci { 819141cc406Sopenharmony_ci "0", 820141cc406Sopenharmony_ci "Kodak", 821141cc406Sopenharmony_ci "DC-210", 822141cc406Sopenharmony_ci "still camera"}, 823141cc406Sopenharmony_ci}; 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ciSANE_Status 826141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 827141cc406Sopenharmony_ci SANE_Bool __sane_unused__ local_only) 828141cc406Sopenharmony_ci{ 829141cc406Sopenharmony_ci static const SANE_Device *devlist[] = { 830141cc406Sopenharmony_ci dev + 0, 0 831141cc406Sopenharmony_ci }; 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci DBG (127, "sane_get_devices called\n"); 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci *device_list = devlist; 836141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 837141cc406Sopenharmony_ci} 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ciSANE_Status 840141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 841141cc406Sopenharmony_ci{ 842141cc406Sopenharmony_ci int i; 843141cc406Sopenharmony_ci 844141cc406Sopenharmony_ci DBG (127, "sane_open for device %s\n", devicename); 845141cc406Sopenharmony_ci if (!devicename[0]) 846141cc406Sopenharmony_ci { 847141cc406Sopenharmony_ci i = 0; 848141cc406Sopenharmony_ci } 849141cc406Sopenharmony_ci else 850141cc406Sopenharmony_ci { 851141cc406Sopenharmony_ci for (i = 0; i < NELEMS (dev); ++i) 852141cc406Sopenharmony_ci { 853141cc406Sopenharmony_ci if (strcmp (devicename, dev[i].name) == 0) 854141cc406Sopenharmony_ci { 855141cc406Sopenharmony_ci break; 856141cc406Sopenharmony_ci } 857141cc406Sopenharmony_ci } 858141cc406Sopenharmony_ci } 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci if (i >= NELEMS (dev)) 861141cc406Sopenharmony_ci { 862141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 863141cc406Sopenharmony_ci } 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci if (is_open) 866141cc406Sopenharmony_ci { 867141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 868141cc406Sopenharmony_ci } 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci is_open = 1; 871141cc406Sopenharmony_ci *handle = MAGIC; 872141cc406Sopenharmony_ci 873141cc406Sopenharmony_ci DBG (3, "sane_open: pictures taken=%d\n", Camera.pic_taken); 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 876141cc406Sopenharmony_ci} 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_civoid 879141cc406Sopenharmony_cisane_close (SANE_Handle handle) 880141cc406Sopenharmony_ci{ 881141cc406Sopenharmony_ci DBG (127, "sane_close called\n"); 882141cc406Sopenharmony_ci if (handle == MAGIC) 883141cc406Sopenharmony_ci is_open = 0; 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci DBG (127, "sane_close returning\n"); 886141cc406Sopenharmony_ci} 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 889141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 890141cc406Sopenharmony_ci{ 891141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 892141cc406Sopenharmony_ci return NULL; /* wrong device */ 893141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (sod)) 894141cc406Sopenharmony_ci return NULL; 895141cc406Sopenharmony_ci return &sod[option]; 896141cc406Sopenharmony_ci} 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ciSANE_Status 899141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 900141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 901141cc406Sopenharmony_ci{ 902141cc406Sopenharmony_ci SANE_Int myinfo = 0; 903141cc406Sopenharmony_ci SANE_Status status; 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", 906141cc406Sopenharmony_ci handle, sod[option].title, 907141cc406Sopenharmony_ci (action == 908141cc406Sopenharmony_ci SANE_ACTION_SET_VALUE ? "SET" : (action == 909141cc406Sopenharmony_ci SANE_ACTION_GET_VALUE ? "GET" : 910141cc406Sopenharmony_ci "SETAUTO")), value, (void *)info); 911141cc406Sopenharmony_ci 912141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 913141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown handle ... */ 914141cc406Sopenharmony_ci 915141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (sod)) 916141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown option ... */ 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci switch (action) 919141cc406Sopenharmony_ci { 920141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 921141cc406Sopenharmony_ci status = sanei_constrain_value (sod + option, value, &myinfo); 922141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 923141cc406Sopenharmony_ci { 924141cc406Sopenharmony_ci DBG (1, "Constraint error in control_option\n"); 925141cc406Sopenharmony_ci return status; 926141cc406Sopenharmony_ci } 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci switch (option) 929141cc406Sopenharmony_ci { 930141cc406Sopenharmony_ci case DC210_OPT_IMAGE_NUMBER: 931141cc406Sopenharmony_ci Camera.current_picture_number = *(SANE_Word *) value; 932141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 933141cc406Sopenharmony_ci /* get the image's resolution */ 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci if (Camera.Pictures[Camera.current_picture_number - 1].low_res) 936141cc406Sopenharmony_ci { 937141cc406Sopenharmony_ci parms.bytes_per_line = 640 * 3; 938141cc406Sopenharmony_ci parms.pixels_per_line = 640; 939141cc406Sopenharmony_ci parms.lines = 480; 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci else 942141cc406Sopenharmony_ci { 943141cc406Sopenharmony_ci parms.bytes_per_line = 1152 * 3; 944141cc406Sopenharmony_ci parms.pixels_per_line = 1152; 945141cc406Sopenharmony_ci parms.lines = 864; 946141cc406Sopenharmony_ci } 947141cc406Sopenharmony_ci break; 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci case DC210_OPT_THUMBS: 950141cc406Sopenharmony_ci dc210_opt_thumbnails = !!*(SANE_Word *) value; 951141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci if (dc210_opt_thumbnails) 954141cc406Sopenharmony_ci { 955141cc406Sopenharmony_ci /* 956141cc406Sopenharmony_ci * DC210 thumbnail are 96x72x8x3 957141cc406Sopenharmony_ci */ 958141cc406Sopenharmony_ci parms.bytes_per_line = 96 * 3; 959141cc406Sopenharmony_ci parms.pixels_per_line = 96; 960141cc406Sopenharmony_ci parms.lines = 72; 961141cc406Sopenharmony_ci } 962141cc406Sopenharmony_ci else 963141cc406Sopenharmony_ci { 964141cc406Sopenharmony_ci if (Camera.Pictures[Camera.current_picture_number - 1].low_res) 965141cc406Sopenharmony_ci { 966141cc406Sopenharmony_ci parms.bytes_per_line = 640 * 3; 967141cc406Sopenharmony_ci parms.pixels_per_line = 640; 968141cc406Sopenharmony_ci parms.lines = 480; 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci else 971141cc406Sopenharmony_ci { 972141cc406Sopenharmony_ci parms.bytes_per_line = 1152 * 3; 973141cc406Sopenharmony_ci parms.pixels_per_line = 1152; 974141cc406Sopenharmony_ci parms.lines = 864; 975141cc406Sopenharmony_ci } 976141cc406Sopenharmony_ci } 977141cc406Sopenharmony_ci break; 978141cc406Sopenharmony_ci 979141cc406Sopenharmony_ci case DC210_OPT_SNAP: 980141cc406Sopenharmony_ci dc210_opt_snap = !!*(SANE_Word *) value; 981141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 982141cc406Sopenharmony_ci /* if we are snapping a new one */ 983141cc406Sopenharmony_ci if (dc210_opt_snap) 984141cc406Sopenharmony_ci { 985141cc406Sopenharmony_ci /* activate the resolution setting */ 986141cc406Sopenharmony_ci sod[DC210_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; 987141cc406Sopenharmony_ci /* and de-activate the image number selector */ 988141cc406Sopenharmony_ci sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; 989141cc406Sopenharmony_ci } 990141cc406Sopenharmony_ci else 991141cc406Sopenharmony_ci { 992141cc406Sopenharmony_ci /* deactivate the resolution setting */ 993141cc406Sopenharmony_ci sod[DC210_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; 994141cc406Sopenharmony_ci /* and activate the image number selector */ 995141cc406Sopenharmony_ci sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci /* set params according to resolution settings */ 998141cc406Sopenharmony_ci if (dc210_opt_lowres) 999141cc406Sopenharmony_ci { 1000141cc406Sopenharmony_ci parms.bytes_per_line = 640 * 3; 1001141cc406Sopenharmony_ci parms.pixels_per_line = 640; 1002141cc406Sopenharmony_ci parms.lines = 480; 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci else 1005141cc406Sopenharmony_ci { 1006141cc406Sopenharmony_ci parms.bytes_per_line = 1152 * 3; 1007141cc406Sopenharmony_ci parms.pixels_per_line = 1152; 1008141cc406Sopenharmony_ci parms.lines = 864; 1009141cc406Sopenharmony_ci } 1010141cc406Sopenharmony_ci break; 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci case DC210_OPT_LOWRES: 1013141cc406Sopenharmony_ci dc210_opt_lowres = !!*(SANE_Word *) value; 1014141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci if (!dc210_opt_thumbnails) 1017141cc406Sopenharmony_ci { 1018141cc406Sopenharmony_ci 1019141cc406Sopenharmony_ci/* XXX - change the number of pictures left depending on resolution 1020141cc406Sopenharmony_ci perhaps just call get_info again? 1021141cc406Sopenharmony_ci */ 1022141cc406Sopenharmony_ci if (dc210_opt_lowres) 1023141cc406Sopenharmony_ci { 1024141cc406Sopenharmony_ci parms.bytes_per_line = 640 * 3; 1025141cc406Sopenharmony_ci parms.pixels_per_line = 640; 1026141cc406Sopenharmony_ci parms.lines = 480; 1027141cc406Sopenharmony_ci } 1028141cc406Sopenharmony_ci else 1029141cc406Sopenharmony_ci { 1030141cc406Sopenharmony_ci parms.bytes_per_line = 1152 * 3; 1031141cc406Sopenharmony_ci parms.pixels_per_line = 1152; 1032141cc406Sopenharmony_ci parms.lines = 864; 1033141cc406Sopenharmony_ci } 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci } 1036141cc406Sopenharmony_ci break; 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci case DC210_OPT_ERASE: 1039141cc406Sopenharmony_ci dc210_opt_erase = !!*(SANE_Word *) value; 1040141cc406Sopenharmony_ci break; 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci case DC210_OPT_DEFAULT: 1043141cc406Sopenharmony_ci DBG (1, "Fixme: Set all defaults here!\n"); 1044141cc406Sopenharmony_ci break; 1045141cc406Sopenharmony_ci case DC210_OPT_INIT_DC210: 1046141cc406Sopenharmony_ci if ((Camera.fd = init_dc210 (&Camera)) == -1) 1047141cc406Sopenharmony_ci { 1048141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1049141cc406Sopenharmony_ci } 1050141cc406Sopenharmony_ci break; 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci default: 1053141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1054141cc406Sopenharmony_ci } 1055141cc406Sopenharmony_ci break; 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 1058141cc406Sopenharmony_ci switch (option) 1059141cc406Sopenharmony_ci { 1060141cc406Sopenharmony_ci case 0: 1061141cc406Sopenharmony_ci *(SANE_Word *) value = NELEMS (sod); 1062141cc406Sopenharmony_ci break; 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci case DC210_OPT_IMAGE_NUMBER: 1065141cc406Sopenharmony_ci *(SANE_Word *) value = Camera.current_picture_number; 1066141cc406Sopenharmony_ci break; 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci case DC210_OPT_THUMBS: 1069141cc406Sopenharmony_ci *(SANE_Word *) value = dc210_opt_thumbnails; 1070141cc406Sopenharmony_ci break; 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci case DC210_OPT_SNAP: 1073141cc406Sopenharmony_ci *(SANE_Word *) value = dc210_opt_snap; 1074141cc406Sopenharmony_ci break; 1075141cc406Sopenharmony_ci 1076141cc406Sopenharmony_ci case DC210_OPT_LOWRES: 1077141cc406Sopenharmony_ci *(SANE_Word *) value = dc210_opt_lowres; 1078141cc406Sopenharmony_ci break; 1079141cc406Sopenharmony_ci 1080141cc406Sopenharmony_ci case DC210_OPT_ERASE: 1081141cc406Sopenharmony_ci *(SANE_Word *) value = dc210_opt_erase; 1082141cc406Sopenharmony_ci break; 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_ci default: 1085141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1086141cc406Sopenharmony_ci } 1087141cc406Sopenharmony_ci break; 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 1090141cc406Sopenharmony_ci switch (option) 1091141cc406Sopenharmony_ci { 1092141cc406Sopenharmony_ci default: 1093141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ 1094141cc406Sopenharmony_ci } 1095141cc406Sopenharmony_ci } 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci if (info) 1098141cc406Sopenharmony_ci *info = myinfo; 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1101141cc406Sopenharmony_ci} 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_ciSANE_Status 1104141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1105141cc406Sopenharmony_ci{ 1106141cc406Sopenharmony_ci int rc = SANE_STATUS_GOOD; 1107141cc406Sopenharmony_ci 1108141cc406Sopenharmony_ci DBG (127, "sane_get_params called\n"); 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 1111141cc406Sopenharmony_ci rc = SANE_STATUS_INVAL; /* Unknown handle ... */ 1112141cc406Sopenharmony_ci 1113141cc406Sopenharmony_ci parms.last_frame = SANE_TRUE; /* Have no idea what this does */ 1114141cc406Sopenharmony_ci *params = parms; 1115141cc406Sopenharmony_ci DBG (127, "sane_get_params return %d\n", rc); 1116141cc406Sopenharmony_ci return rc; 1117141cc406Sopenharmony_ci} 1118141cc406Sopenharmony_ci 1119141cc406Sopenharmony_citypedef struct 1120141cc406Sopenharmony_ci{ 1121141cc406Sopenharmony_ci struct jpeg_source_mgr pub; 1122141cc406Sopenharmony_ci JOCTET *buffer; 1123141cc406Sopenharmony_ci} 1124141cc406Sopenharmony_cimy_source_mgr; 1125141cc406Sopenharmony_citypedef my_source_mgr *my_src_ptr; 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_ciMETHODDEF (void) 1128141cc406Sopenharmony_cisanei_jpeg_init_source (j_decompress_ptr __sane_unused__ cinfo) 1129141cc406Sopenharmony_ci{ 1130141cc406Sopenharmony_ci /* nothing to do */ 1131141cc406Sopenharmony_ci} 1132141cc406Sopenharmony_ci 1133141cc406Sopenharmony_ciMETHODDEF (boolean) sanei_jpeg_fill_input_buffer (j_decompress_ptr cinfo) 1134141cc406Sopenharmony_ci{ 1135141cc406Sopenharmony_ci 1136141cc406Sopenharmony_ci my_src_ptr src = (my_src_ptr) cinfo->src; 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci if (read_data (Camera.fd, src->buffer, 1024) == -1) 1139141cc406Sopenharmony_ci { 1140141cc406Sopenharmony_ci DBG (5, "sane_start: read_data failed\n"); 1141141cc406Sopenharmony_ci src->buffer[0] = (JOCTET) 0xFF; 1142141cc406Sopenharmony_ci src->buffer[1] = (JOCTET) JPEG_EOI; 1143141cc406Sopenharmony_ci return FALSE; 1144141cc406Sopenharmony_ci } 1145141cc406Sopenharmony_ci src->pub.next_input_byte = src->buffer; 1146141cc406Sopenharmony_ci src->pub.bytes_in_buffer = 1024; 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci return TRUE; 1149141cc406Sopenharmony_ci} 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ciMETHODDEF (void) 1152141cc406Sopenharmony_cisanei_jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes) 1153141cc406Sopenharmony_ci{ 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci my_src_ptr src = (my_src_ptr) cinfo->src; 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci if (num_bytes > 0) 1158141cc406Sopenharmony_ci { 1159141cc406Sopenharmony_ci while (num_bytes > (long) src->pub.bytes_in_buffer) 1160141cc406Sopenharmony_ci { 1161141cc406Sopenharmony_ci num_bytes -= (long) src->pub.bytes_in_buffer; 1162141cc406Sopenharmony_ci (void) sanei_jpeg_fill_input_buffer (cinfo); 1163141cc406Sopenharmony_ci } 1164141cc406Sopenharmony_ci } 1165141cc406Sopenharmony_ci src->pub.next_input_byte += (size_t) num_bytes; 1166141cc406Sopenharmony_ci src->pub.bytes_in_buffer -= (size_t) num_bytes; 1167141cc406Sopenharmony_ci} 1168141cc406Sopenharmony_ci 1169141cc406Sopenharmony_ciMETHODDEF (void) 1170141cc406Sopenharmony_cisanei_jpeg_term_source (j_decompress_ptr __sane_unused__ cinfo) 1171141cc406Sopenharmony_ci{ 1172141cc406Sopenharmony_ci /* no work necessary here */ 1173141cc406Sopenharmony_ci} 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ciSANE_Status 1176141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1177141cc406Sopenharmony_ci{ 1178141cc406Sopenharmony_ci 1179141cc406Sopenharmony_ci DBG (127, "sane_start called\n"); 1180141cc406Sopenharmony_ci if (handle != MAGIC || !is_open || 1181141cc406Sopenharmony_ci (Camera.current_picture_number == 0 && dc210_opt_snap == SANE_FALSE)) 1182141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown handle ... */ 1183141cc406Sopenharmony_ci 1184141cc406Sopenharmony_ci if (Camera.scanning) 1185141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci if (dc210_opt_snap) 1188141cc406Sopenharmony_ci { 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci /* 1191141cc406Sopenharmony_ci * Don't allow picture unless there is room in the 1192141cc406Sopenharmony_ci * camera. 1193141cc406Sopenharmony_ci */ 1194141cc406Sopenharmony_ci if (Camera.pic_left == 0) 1195141cc406Sopenharmony_ci { 1196141cc406Sopenharmony_ci DBG (3, "No room to store new picture\n"); 1197141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1198141cc406Sopenharmony_ci } 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci if (snap_pic (Camera.fd) != SANE_STATUS_GOOD) 1202141cc406Sopenharmony_ci { 1203141cc406Sopenharmony_ci DBG (1, "Failed to snap new picture\n"); 1204141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1205141cc406Sopenharmony_ci } 1206141cc406Sopenharmony_ci } 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci if (dc210_opt_thumbnails) 1209141cc406Sopenharmony_ci { 1210141cc406Sopenharmony_ci 1211141cc406Sopenharmony_ci thumb_pck[3] = (unsigned char) Camera.current_picture_number - 1; 1212141cc406Sopenharmony_ci thumb_pck[4] = 1; 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci if (send_pck (Camera.fd, thumb_pck) == -1) 1215141cc406Sopenharmony_ci { 1216141cc406Sopenharmony_ci DBG (4, "sane_start: error: send_pck returned -1\n"); 1217141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1218141cc406Sopenharmony_ci } 1219141cc406Sopenharmony_ci 1220141cc406Sopenharmony_ci parms.bytes_per_line = 96 * 3; 1221141cc406Sopenharmony_ci parms.pixels_per_line = 96; 1222141cc406Sopenharmony_ci parms.lines = 72; 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci bytes_in_buffer = 0; 1225141cc406Sopenharmony_ci bytes_read_from_buffer = 0; 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci } 1228141cc406Sopenharmony_ci else 1229141cc406Sopenharmony_ci { 1230141cc406Sopenharmony_ci my_src_ptr src; 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci struct jpeg_error_mgr jerr; 1233141cc406Sopenharmony_ci 1234141cc406Sopenharmony_ci pic_pck[3] = (unsigned char) Camera.current_picture_number - 1; 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci if (send_pck (Camera.fd, pic_pck) == -1) 1237141cc406Sopenharmony_ci { 1238141cc406Sopenharmony_ci DBG (4, "sane_start: error: send_pck returned -1\n"); 1239141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1240141cc406Sopenharmony_ci } 1241141cc406Sopenharmony_ci cinfo.err = jpeg_std_error (&jerr); 1242141cc406Sopenharmony_ci jpeg_create_decompress (&cinfo); 1243141cc406Sopenharmony_ci 1244141cc406Sopenharmony_ci cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); 1245141cc406Sopenharmony_ci src = (my_src_ptr) cinfo.src; 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) & 1248141cc406Sopenharmony_ci cinfo, 1249141cc406Sopenharmony_ci JPOOL_PERMANENT, 1250141cc406Sopenharmony_ci 1024 * 1251141cc406Sopenharmony_ci sizeof (JOCTET)); 1252141cc406Sopenharmony_ci src->pub.init_source = sanei_jpeg_init_source; 1253141cc406Sopenharmony_ci src->pub.fill_input_buffer = sanei_jpeg_fill_input_buffer; 1254141cc406Sopenharmony_ci src->pub.skip_input_data = sanei_jpeg_skip_input_data; 1255141cc406Sopenharmony_ci src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */ 1256141cc406Sopenharmony_ci src->pub.term_source = sanei_jpeg_term_source; 1257141cc406Sopenharmony_ci src->pub.bytes_in_buffer = 0; 1258141cc406Sopenharmony_ci src->pub.next_input_byte = NULL; 1259141cc406Sopenharmony_ci 1260141cc406Sopenharmony_ci (void) jpeg_read_header (&cinfo, TRUE); 1261141cc406Sopenharmony_ci dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo); 1262141cc406Sopenharmony_ci (void) jpeg_start_decompress (&cinfo); 1263141cc406Sopenharmony_ci } 1264141cc406Sopenharmony_ci 1265141cc406Sopenharmony_ci Camera.scanning = SANE_TRUE; /* don't overlap scan requests */ 1266141cc406Sopenharmony_ci total_bytes_read = 0; 1267141cc406Sopenharmony_ci 1268141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1269141cc406Sopenharmony_ci} 1270141cc406Sopenharmony_ci 1271141cc406Sopenharmony_ciSANE_Status 1272141cc406Sopenharmony_cisane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data, 1273141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 1274141cc406Sopenharmony_ci{ 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_ci static char buffer[1024]; 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_ci if (dc210_opt_thumbnails) 1279141cc406Sopenharmony_ci { 1280141cc406Sopenharmony_ci if (total_bytes_read == THUMBSIZE) 1281141cc406Sopenharmony_ci { 1282141cc406Sopenharmony_ci if (dc210_opt_erase) 1283141cc406Sopenharmony_ci { 1284141cc406Sopenharmony_ci if (erase (Camera.fd) == -1) 1285141cc406Sopenharmony_ci { 1286141cc406Sopenharmony_ci DBG (1, "Failed to erase memory\n"); 1287141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1288141cc406Sopenharmony_ci } 1289141cc406Sopenharmony_ci Camera.pic_taken--; 1290141cc406Sopenharmony_ci Camera.pic_left++; 1291141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1292141cc406Sopenharmony_ci image_range.max--; 1293141cc406Sopenharmony_ci } 1294141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1295141cc406Sopenharmony_ci } 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci *length = 0; 1298141cc406Sopenharmony_ci if (!(bytes_in_buffer - bytes_read_from_buffer)) 1299141cc406Sopenharmony_ci { 1300141cc406Sopenharmony_ci if (read_data (Camera.fd, (unsigned char *) buffer, 1024) == -1) 1301141cc406Sopenharmony_ci { 1302141cc406Sopenharmony_ci DBG (5, "sane_read: read_data failed\n"); 1303141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1304141cc406Sopenharmony_ci } 1305141cc406Sopenharmony_ci bytes_in_buffer = 1024; 1306141cc406Sopenharmony_ci bytes_read_from_buffer = 0; 1307141cc406Sopenharmony_ci } 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci while (bytes_read_from_buffer < bytes_in_buffer && 1310141cc406Sopenharmony_ci max_length && total_bytes_read < THUMBSIZE) 1311141cc406Sopenharmony_ci { 1312141cc406Sopenharmony_ci *data++ = buffer[bytes_read_from_buffer++]; 1313141cc406Sopenharmony_ci (*length)++; 1314141cc406Sopenharmony_ci max_length--; 1315141cc406Sopenharmony_ci total_bytes_read++; 1316141cc406Sopenharmony_ci } 1317141cc406Sopenharmony_ci 1318141cc406Sopenharmony_ci if (total_bytes_read == THUMBSIZE) 1319141cc406Sopenharmony_ci { 1320141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1321141cc406Sopenharmony_ci { 1322141cc406Sopenharmony_ci DBG (4, "sane_read: end_of_data error\n"); 1323141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci else 1326141cc406Sopenharmony_ci { 1327141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1328141cc406Sopenharmony_ci } 1329141cc406Sopenharmony_ci } 1330141cc406Sopenharmony_ci else 1331141cc406Sopenharmony_ci { 1332141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1333141cc406Sopenharmony_ci } 1334141cc406Sopenharmony_ci } 1335141cc406Sopenharmony_ci else 1336141cc406Sopenharmony_ci { 1337141cc406Sopenharmony_ci int lines = 0; 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci if (cinfo.output_scanline >= cinfo.output_height) 1340141cc406Sopenharmony_ci { 1341141cc406Sopenharmony_ci /* clean up comms with the camera */ 1342141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1343141cc406Sopenharmony_ci { 1344141cc406Sopenharmony_ci DBG (2, "sane_read: error: end_of_data returned -1\n"); 1345141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1346141cc406Sopenharmony_ci } 1347141cc406Sopenharmony_ci if (dc210_opt_erase) 1348141cc406Sopenharmony_ci { 1349141cc406Sopenharmony_ci DBG (127, "sane_read bp%d, erase image\n", __LINE__); 1350141cc406Sopenharmony_ci if (erase (Camera.fd) == -1) 1351141cc406Sopenharmony_ci { 1352141cc406Sopenharmony_ci DBG (1, "Failed to erase memory\n"); 1353141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1354141cc406Sopenharmony_ci } 1355141cc406Sopenharmony_ci Camera.pic_taken--; 1356141cc406Sopenharmony_ci Camera.pic_left++; 1357141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1358141cc406Sopenharmony_ci image_range.max--; 1359141cc406Sopenharmony_ci } 1360141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1361141cc406Sopenharmony_ci } 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci/* XXX - we should read more than 1 line at a time here */ 1364141cc406Sopenharmony_ci lines = 1; 1365141cc406Sopenharmony_ci (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines); 1366141cc406Sopenharmony_ci (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) data); 1367141cc406Sopenharmony_ci *length = cinfo.output_width * cinfo.output_components * lines; 1368141cc406Sopenharmony_ci 1369141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1370141cc406Sopenharmony_ci 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci} 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_civoid 1375141cc406Sopenharmony_cisane_cancel (SANE_Handle __sane_unused__ handle) 1376141cc406Sopenharmony_ci{ 1377141cc406Sopenharmony_ci DBG (127, "sane_cancel() called\n"); 1378141cc406Sopenharmony_ci if (Camera.scanning) 1379141cc406Sopenharmony_ci Camera.scanning = SANE_FALSE; /* done with scan */ 1380141cc406Sopenharmony_ci else 1381141cc406Sopenharmony_ci DBG (127, "sane_cancel() aborted, scanner not scanning\n"); 1382141cc406Sopenharmony_ci} 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ciSANE_Status 1385141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, 1386141cc406Sopenharmony_ci SANE_Bool __sane_unused__ non_blocking) 1387141cc406Sopenharmony_ci{ 1388141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1389141cc406Sopenharmony_ci} 1390141cc406Sopenharmony_ci 1391141cc406Sopenharmony_ciSANE_Status 1392141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) 1393141cc406Sopenharmony_ci{ 1394141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1395141cc406Sopenharmony_ci} 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_cistatic PictureInfo * 1398141cc406Sopenharmony_ciget_pictures_info (void) 1399141cc406Sopenharmony_ci{ 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ci char f[] = "get_pictures_info"; 1402141cc406Sopenharmony_ci unsigned int p; 1403141cc406Sopenharmony_ci PictureInfo *pics; 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci if ((pics = (PictureInfo *) malloc (Camera.pic_taken * 1406141cc406Sopenharmony_ci sizeof (PictureInfo))) == NULL) 1407141cc406Sopenharmony_ci { 1408141cc406Sopenharmony_ci DBG (4, "%s: error: allocate memory for pictures array\n", f); 1409141cc406Sopenharmony_ci return NULL; 1410141cc406Sopenharmony_ci } 1411141cc406Sopenharmony_ci 1412141cc406Sopenharmony_ci for (p = 0; p < (unsigned int) Camera.pic_taken; p++) 1413141cc406Sopenharmony_ci { 1414141cc406Sopenharmony_ci if (get_picture_info (pics + p, p) == -1) 1415141cc406Sopenharmony_ci { 1416141cc406Sopenharmony_ci free (pics); 1417141cc406Sopenharmony_ci return NULL; 1418141cc406Sopenharmony_ci } 1419141cc406Sopenharmony_ci } 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_ci return pics; 1422141cc406Sopenharmony_ci} 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_cistatic int 1425141cc406Sopenharmony_ciget_picture_info (PictureInfo * pic, int p) 1426141cc406Sopenharmony_ci{ 1427141cc406Sopenharmony_ci 1428141cc406Sopenharmony_ci char f[] = "get_picture_info"; 1429141cc406Sopenharmony_ci static char buffer[256]; 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_ci DBG (4, "%s: info for pic #%d\n", f, p); 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci pic_info_pck[3] = (unsigned char) p; 1434141cc406Sopenharmony_ci 1435141cc406Sopenharmony_ci if (send_pck (Camera.fd, pic_info_pck) == -1) 1436141cc406Sopenharmony_ci { 1437141cc406Sopenharmony_ci DBG (4, "%s: error: send_pck returned -1\n", f); 1438141cc406Sopenharmony_ci return -1; 1439141cc406Sopenharmony_ci } 1440141cc406Sopenharmony_ci 1441141cc406Sopenharmony_ci if (read_data (Camera.fd, (unsigned char *) buffer, 256) == -1) 1442141cc406Sopenharmony_ci { 1443141cc406Sopenharmony_ci DBG (2, "%s: error: read_data returned -1\n", f); 1444141cc406Sopenharmony_ci return -1; 1445141cc406Sopenharmony_ci } 1446141cc406Sopenharmony_ci 1447141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1448141cc406Sopenharmony_ci { 1449141cc406Sopenharmony_ci DBG (2, "%s: error: end_of_data returned -1\n", f); 1450141cc406Sopenharmony_ci return -1; 1451141cc406Sopenharmony_ci } 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci if (buffer[3] == 0) 1454141cc406Sopenharmony_ci { 1455141cc406Sopenharmony_ci pic->low_res = SANE_TRUE; 1456141cc406Sopenharmony_ci } 1457141cc406Sopenharmony_ci else if (buffer[3] == 1) 1458141cc406Sopenharmony_ci { 1459141cc406Sopenharmony_ci pic->low_res = SANE_FALSE; 1460141cc406Sopenharmony_ci } 1461141cc406Sopenharmony_ci else 1462141cc406Sopenharmony_ci { 1463141cc406Sopenharmony_ci DBG (2, "%s: error: unknown resolution code %u\n", f, buffer[3]); 1464141cc406Sopenharmony_ci return -1; 1465141cc406Sopenharmony_ci } 1466141cc406Sopenharmony_ci pic->size = (buffer[8] & 0xFF) << 24; 1467141cc406Sopenharmony_ci pic->size |= (buffer[9] & 0xFF) << 16; 1468141cc406Sopenharmony_ci pic->size |= (buffer[10] & 0xFF) << 8; 1469141cc406Sopenharmony_ci pic->size |= (buffer[11] & 0xFF); 1470141cc406Sopenharmony_ci 1471141cc406Sopenharmony_ci return 0; 1472141cc406Sopenharmony_ci} 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_cistatic SANE_Status 1475141cc406Sopenharmony_cisnap_pic (int fd) 1476141cc406Sopenharmony_ci{ 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci char f[] = "snap_pic"; 1479141cc406Sopenharmony_ci 1480141cc406Sopenharmony_ci /* make sure camera is set to our settings state */ 1481141cc406Sopenharmony_ci if (change_res (Camera.fd, dc210_opt_lowres) == -1) 1482141cc406Sopenharmony_ci { 1483141cc406Sopenharmony_ci DBG (1, "%s: Failed to set resolution\n", f); 1484141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1485141cc406Sopenharmony_ci } 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci /* take the picture */ 1488141cc406Sopenharmony_ci if (send_pck (fd, shoot_pck) == -1) 1489141cc406Sopenharmony_ci { 1490141cc406Sopenharmony_ci DBG (4, "%s: error: send_pck returned -1\n", f); 1491141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1492141cc406Sopenharmony_ci } 1493141cc406Sopenharmony_ci else 1494141cc406Sopenharmony_ci { 1495141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1496141cc406Sopenharmony_ci { 1497141cc406Sopenharmony_ci DBG (2, "%s: error: end_of_data returned -1\n", f); 1498141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1499141cc406Sopenharmony_ci } 1500141cc406Sopenharmony_ci } 1501141cc406Sopenharmony_ci Camera.pic_taken++; 1502141cc406Sopenharmony_ci Camera.pic_left--; 1503141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1504141cc406Sopenharmony_ci image_range.max++; 1505141cc406Sopenharmony_ci sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 1506141cc406Sopenharmony_ci 1507141cc406Sopenharmony_ci /* add this one to the Pictures array */ 1508141cc406Sopenharmony_ci if ((Camera.Pictures = 1509141cc406Sopenharmony_ci (PictureInfo *) realloc (Camera.Pictures, 1510141cc406Sopenharmony_ci Camera.pic_taken * sizeof (PictureInfo))) == 1511141cc406Sopenharmony_ci NULL) 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci DBG (4, "%s: error: allocate memory for pictures array\n", f); 1514141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1515141cc406Sopenharmony_ci } 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci if (get_picture_info (Camera.Pictures + Camera.pic_taken, 1518141cc406Sopenharmony_ci Camera.pic_taken) == -1) 1519141cc406Sopenharmony_ci { 1520141cc406Sopenharmony_ci DBG (1, "%s: Failed to get new picture info\n", f); 1521141cc406Sopenharmony_ci /* XXX - I guess we should try to erase the image here */ 1522141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1523141cc406Sopenharmony_ci } 1524141cc406Sopenharmony_ci 1525141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1526141cc406Sopenharmony_ci} 1527