1141cc406Sopenharmony_ci/*************************************************************************** 2141cc406Sopenharmony_ci * _S_A_N_E - Scanner Access Now Easy. 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci dc240.c 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci 03/12/01 - Peter Fales 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci Based on the dc210 driver, (C) 1998 Brian J. Murrell (which is 9141cc406Sopenharmony_ci based on dc25 driver (C) 1998 by Peter Fales) 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This file (C) 2001 by Peter Fales 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This file is part of the SANE package. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 16141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 17141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 18141cc406Sopenharmony_ci License, or (at your option) any later version. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 21141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23141cc406Sopenharmony_ci General Public License for more details. 24141cc406Sopenharmony_ci 25141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 26141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 29141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 32141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 33141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 34141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 35141cc406Sopenharmony_ci account of linking the SANE library code into it. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 38141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 39141cc406Sopenharmony_ci License. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 42141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 43141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 46141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 47141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci *************************************************************************** 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci This file implements a SANE backend for the Kodak DC-240 52141cc406Sopenharmony_ci digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci (feedback to: dc240-devel@fales-lorenz.net) 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci This backend is based somewhat on the dc25 backend included in this 57141cc406Sopenharmony_ci package by Peter Fales, and the dc210 backend by Brian J. Murrell 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci ***************************************************************************/ 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#include "../include/sane/config.h" 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci#include <stdlib.h> 64141cc406Sopenharmony_ci#include <string.h> 65141cc406Sopenharmony_ci#include <stdio.h> 66141cc406Sopenharmony_ci#include <unistd.h> 67141cc406Sopenharmony_ci#include <fcntl.h> 68141cc406Sopenharmony_ci#include <limits.h> 69141cc406Sopenharmony_ci#include "../include/sane/sanei_jpeg.h" 70141cc406Sopenharmony_ci#include <sys/ioctl.h> 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci#include "../include/sane/sane.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 74141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#define BACKEND_NAME dc240 77141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#include "dc240.h" 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#ifndef PATH_MAX 82141cc406Sopenharmony_ci# define PATH_MAX 1024 83141cc406Sopenharmony_ci#endif 84141cc406Sopenharmony_ci 85141cc406Sopenharmony_ci#define MAGIC (void *)0xab730324 86141cc406Sopenharmony_ci#define DC240_CONFIG_FILE "dc240.conf" 87141cc406Sopenharmony_ci#define THUMBSIZE 20736 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci#ifdef B115200 90141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE B115200 91141cc406Sopenharmony_ci#else 92141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE B38400 93141cc406Sopenharmony_ci#endif 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci#if defined (__sgi) 96141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/ttyd1" /* Irix */ 97141cc406Sopenharmony_ci#elif defined (__sun) 98141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/term/a" /* Solaris */ 99141cc406Sopenharmony_ci#elif defined (hpux) 100141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/tty1d0" /* HP-UX */ 101141cc406Sopenharmony_ci#elif defined (__osf__) 102141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/tty00" /* Digital UNIX */ 103141cc406Sopenharmony_ci#else 104141cc406Sopenharmony_ci# define DEFAULT_TTY "/dev/ttyS0" /* Linux */ 105141cc406Sopenharmony_ci#endif 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_cistatic SANE_Bool is_open = 0; 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_thumbnails; 110141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_snap; 111141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_lowres; 112141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_erase; 113141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_autoinc; 114141cc406Sopenharmony_cistatic SANE_Bool dumpinquiry; 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_cistatic struct jpeg_decompress_struct cinfo; 117141cc406Sopenharmony_cistatic djpeg_dest_ptr dest_mgr = NULL; 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_cistatic unsigned long cmdrespause = 250000UL; /* pause after sending cmd */ 120141cc406Sopenharmony_cistatic unsigned long breakpause = 1000000UL; /* pause after sending break */ 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_cistatic DC240 Camera; 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_cistatic SANE_Range image_range = { 125141cc406Sopenharmony_ci 0, 126141cc406Sopenharmony_ci 0, 127141cc406Sopenharmony_ci 0 128141cc406Sopenharmony_ci}; 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_cistatic SANE_String **folder_list; 131141cc406Sopenharmony_cistatic SANE_Int current_folder = 0; 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_cistatic SANE_Option_Descriptor sod[] = { 134141cc406Sopenharmony_ci { 135141cc406Sopenharmony_ci SANE_NAME_NUM_OPTIONS, 136141cc406Sopenharmony_ci SANE_TITLE_NUM_OPTIONS, 137141cc406Sopenharmony_ci SANE_DESC_NUM_OPTIONS, 138141cc406Sopenharmony_ci SANE_TYPE_INT, 139141cc406Sopenharmony_ci SANE_UNIT_NONE, 140141cc406Sopenharmony_ci sizeof (SANE_Word), 141141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT, 142141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 143141cc406Sopenharmony_ci {NULL} 144141cc406Sopenharmony_ci } 145141cc406Sopenharmony_ci , 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci#define DC240_OPT_IMAGE_SELECTION 1 148141cc406Sopenharmony_ci { 149141cc406Sopenharmony_ci "", 150141cc406Sopenharmony_ci "Image Selection", 151141cc406Sopenharmony_ci "Selection of the image to load.", 152141cc406Sopenharmony_ci SANE_TYPE_GROUP, 153141cc406Sopenharmony_ci SANE_UNIT_NONE, 154141cc406Sopenharmony_ci 0, 155141cc406Sopenharmony_ci 0, 156141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 157141cc406Sopenharmony_ci {NULL} 158141cc406Sopenharmony_ci } 159141cc406Sopenharmony_ci , 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci#define DC240_OPT_FOLDER 2 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci "folder", 164141cc406Sopenharmony_ci "Folder", 165141cc406Sopenharmony_ci "Select folder within camera", 166141cc406Sopenharmony_ci SANE_TYPE_STRING, 167141cc406Sopenharmony_ci SANE_UNIT_NONE, 168141cc406Sopenharmony_ci 256, 169141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 170141cc406Sopenharmony_ci SANE_CONSTRAINT_STRING_LIST, 171141cc406Sopenharmony_ci {NULL} 172141cc406Sopenharmony_ci } 173141cc406Sopenharmony_ci , 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci#define DC240_OPT_IMAGE_NUMBER 3 176141cc406Sopenharmony_ci { 177141cc406Sopenharmony_ci "image", 178141cc406Sopenharmony_ci "Image Number", 179141cc406Sopenharmony_ci "Select Image Number to load from camera", 180141cc406Sopenharmony_ci SANE_TYPE_INT, 181141cc406Sopenharmony_ci SANE_UNIT_NONE, 182141cc406Sopenharmony_ci 4, 183141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 184141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE, 185141cc406Sopenharmony_ci {(SANE_String_Const *) & image_range} /* this is ANSI conformant! */ 186141cc406Sopenharmony_ci } 187141cc406Sopenharmony_ci , 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_ci#define DC240_OPT_THUMBS 4 190141cc406Sopenharmony_ci { 191141cc406Sopenharmony_ci "thumbs", 192141cc406Sopenharmony_ci "Load Thumbnail", 193141cc406Sopenharmony_ci "Load the image as thumbnail.", 194141cc406Sopenharmony_ci SANE_TYPE_BOOL, 195141cc406Sopenharmony_ci SANE_UNIT_NONE, 196141cc406Sopenharmony_ci sizeof (SANE_Word), 197141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 198141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 199141cc406Sopenharmony_ci {NULL} 200141cc406Sopenharmony_ci } 201141cc406Sopenharmony_ci , 202141cc406Sopenharmony_ci#define DC240_OPT_SNAP 5 203141cc406Sopenharmony_ci { 204141cc406Sopenharmony_ci "snap", 205141cc406Sopenharmony_ci "Snap new picture", 206141cc406Sopenharmony_ci "Take new picture and download it", 207141cc406Sopenharmony_ci SANE_TYPE_BOOL, 208141cc406Sopenharmony_ci SANE_UNIT_NONE, 209141cc406Sopenharmony_ci sizeof (SANE_Word), 210141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ , 211141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 212141cc406Sopenharmony_ci {NULL} 213141cc406Sopenharmony_ci } 214141cc406Sopenharmony_ci , 215141cc406Sopenharmony_ci#define DC240_OPT_LOWRES 6 216141cc406Sopenharmony_ci { 217141cc406Sopenharmony_ci "lowres", 218141cc406Sopenharmony_ci "Low Resolution", 219141cc406Sopenharmony_ci "Resolution of new pictures", 220141cc406Sopenharmony_ci SANE_TYPE_BOOL, 221141cc406Sopenharmony_ci SANE_UNIT_NONE, 222141cc406Sopenharmony_ci sizeof (SANE_Word), 223141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE 224141cc406Sopenharmony_ci /* | SANE_CAP_ADVANCED */ , 225141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 226141cc406Sopenharmony_ci {NULL} 227141cc406Sopenharmony_ci } 228141cc406Sopenharmony_ci , 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci#define DC240_OPT_ERASE 7 231141cc406Sopenharmony_ci { 232141cc406Sopenharmony_ci "erase", 233141cc406Sopenharmony_ci "Erase", 234141cc406Sopenharmony_ci "Erase the picture after downloading", 235141cc406Sopenharmony_ci SANE_TYPE_BOOL, 236141cc406Sopenharmony_ci SANE_UNIT_NONE, 237141cc406Sopenharmony_ci sizeof (SANE_Word), 238141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 239141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 240141cc406Sopenharmony_ci {NULL} 241141cc406Sopenharmony_ci } 242141cc406Sopenharmony_ci , 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_ci#define DC240_OPT_DEFAULT 8 245141cc406Sopenharmony_ci { 246141cc406Sopenharmony_ci "default-enhancements", 247141cc406Sopenharmony_ci "Defaults", 248141cc406Sopenharmony_ci "Set default values for enhancement controls.", 249141cc406Sopenharmony_ci SANE_TYPE_BUTTON, 250141cc406Sopenharmony_ci SANE_UNIT_NONE, 251141cc406Sopenharmony_ci 0, 252141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 253141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 254141cc406Sopenharmony_ci {NULL} 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci , 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci#define DC240_OPT_INIT_DC240 9 259141cc406Sopenharmony_ci { 260141cc406Sopenharmony_ci "camera-init", 261141cc406Sopenharmony_ci "Re-establish Communications", 262141cc406Sopenharmony_ci "Re-establish communications with camera (in case of timeout, etc.)", 263141cc406Sopenharmony_ci SANE_TYPE_BUTTON, 264141cc406Sopenharmony_ci SANE_UNIT_NONE, 265141cc406Sopenharmony_ci 0, 266141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, 267141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 268141cc406Sopenharmony_ci {NULL} 269141cc406Sopenharmony_ci } 270141cc406Sopenharmony_ci , 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci#define DC240_OPT_AUTOINC 10 273141cc406Sopenharmony_ci { 274141cc406Sopenharmony_ci "autoinc", 275141cc406Sopenharmony_ci "Auto Increment", 276141cc406Sopenharmony_ci "Increment image number after each scan", 277141cc406Sopenharmony_ci SANE_TYPE_BOOL, 278141cc406Sopenharmony_ci SANE_UNIT_NONE, 279141cc406Sopenharmony_ci sizeof (SANE_Word), 280141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, 281141cc406Sopenharmony_ci SANE_CONSTRAINT_NONE, 282141cc406Sopenharmony_ci {NULL} 283141cc406Sopenharmony_ci } 284141cc406Sopenharmony_ci , 285141cc406Sopenharmony_ci 286141cc406Sopenharmony_ci}; 287141cc406Sopenharmony_ci 288141cc406Sopenharmony_cistatic SANE_Parameters parms = { 289141cc406Sopenharmony_ci SANE_FRAME_RGB, 290141cc406Sopenharmony_ci 0, 291141cc406Sopenharmony_ci 0, /* Number of bytes returned per scan line: */ 292141cc406Sopenharmony_ci 0, /* Number of pixels per scan line. */ 293141cc406Sopenharmony_ci 0, /* Number of lines for the current scan. */ 294141cc406Sopenharmony_ci 8, /* Number of bits per sample. */ 295141cc406Sopenharmony_ci}; 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_cistatic SANE_Byte shoot_pck[] = SHOOT_PCK; 301141cc406Sopenharmony_cistatic SANE_Byte init_pck[] = INIT_PCK; 302141cc406Sopenharmony_cistatic SANE_Byte thumb_pck[] = THUMBS_PCK; 303141cc406Sopenharmony_cistatic SANE_Byte pic_pck[] = PICS_PCK; 304141cc406Sopenharmony_cistatic SANE_Byte pic_info_pck[] = PICS_INFO_PCK; 305141cc406Sopenharmony_cistatic SANE_Byte info_pck[] = INFO_PCK; 306141cc406Sopenharmony_cistatic SANE_Byte erase_pck[] = ERASE_PCK; 307141cc406Sopenharmony_cistatic SANE_Byte res_pck[] = RES_PCK; 308141cc406Sopenharmony_cistatic SANE_Byte open_card_pck[] = OPEN_CARD_PCK; 309141cc406Sopenharmony_cistatic SANE_Byte read_dir_pck[] = READ_DIR_PCK; 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_cistatic struct pkt_speed speeds[] = SPEEDS; 312141cc406Sopenharmony_cistatic struct termios tty_orig; 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ciSANE_Byte dir_buf2[2 + CAMDIRENTRYSIZE * DIRENTRIES]; 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_cistatic struct cam_dirlist *dir_head = NULL; 317141cc406Sopenharmony_ci 318141cc406Sopenharmony_cistatic SANE_Byte info_buf[256]; 319141cc406Sopenharmony_cistatic SANE_Byte name_buf[60]; 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci#include <sys/time.h> 322141cc406Sopenharmony_ci#include <unistd.h> 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_cistatic SANE_Int 325141cc406Sopenharmony_cisend_pck (SANE_Int fd, SANE_Byte * pck) 326141cc406Sopenharmony_ci{ 327141cc406Sopenharmony_ci SANE_Int n; 328141cc406Sopenharmony_ci SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci DBG (127, "send_pck<%x %x %x %x %x %x %x %x>\n", 331141cc406Sopenharmony_ci pck[0], pck[1], pck[2], pck[3], pck[4], pck[5], pck[6], pck[7]); 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci /* keep trying if camera says it's busy */ 334141cc406Sopenharmony_ci while (r == 0xf0) 335141cc406Sopenharmony_ci { 336141cc406Sopenharmony_ci if (write (fd, (char *) pck, 8) != 8) 337141cc406Sopenharmony_ci { 338141cc406Sopenharmony_ci DBG (1, "send_pck: error: write returned -1\n"); 339141cc406Sopenharmony_ci return -1; 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci /* need to wait before we read command result */ 342141cc406Sopenharmony_ci usleep (cmdrespause); 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci if ((n = read (fd, (char *) &r, 1)) != 1) 345141cc406Sopenharmony_ci { 346141cc406Sopenharmony_ci DBG (1, "send_pck: error: read returned -1\n"); 347141cc406Sopenharmony_ci return -1; 348141cc406Sopenharmony_ci } 349141cc406Sopenharmony_ci } 350141cc406Sopenharmony_ci DBG (127, "send_pck: read one byte result from camera = %x\n", r); 351141cc406Sopenharmony_ci return (r == 0xd1) ? 0 : -1; 352141cc406Sopenharmony_ci} 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_cistatic SANE_Int 355141cc406Sopenharmony_ciinit_dc240 (DC240 * camera) 356141cc406Sopenharmony_ci{ 357141cc406Sopenharmony_ci struct termios tty_new; 358141cc406Sopenharmony_ci SANE_Int speed_index; 359141cc406Sopenharmony_ci SANE_Char buf[5], n; 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci DBG (1, "DC-240 Backend 05/16/01\n"); 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++) 364141cc406Sopenharmony_ci { 365141cc406Sopenharmony_ci if (speeds[speed_index].baud == camera->baud) 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci init_pck[2] = speeds[speed_index].pkt_code[0]; 368141cc406Sopenharmony_ci init_pck[3] = speeds[speed_index].pkt_code[1]; 369141cc406Sopenharmony_ci break; 370141cc406Sopenharmony_ci } 371141cc406Sopenharmony_ci } 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci if (init_pck[2] == 0) 374141cc406Sopenharmony_ci { 375141cc406Sopenharmony_ci DBG (1, "unsupported baud rate.\n"); 376141cc406Sopenharmony_ci return -1; 377141cc406Sopenharmony_ci } 378141cc406Sopenharmony_ci 379141cc406Sopenharmony_ci /* 380141cc406Sopenharmony_ci Open device file. 381141cc406Sopenharmony_ci */ 382141cc406Sopenharmony_ci if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1) 383141cc406Sopenharmony_ci { 384141cc406Sopenharmony_ci DBG (1, "init_dc240: error: could not open %s for read/write\n", 385141cc406Sopenharmony_ci camera->tty_name); 386141cc406Sopenharmony_ci return -1; 387141cc406Sopenharmony_ci } 388141cc406Sopenharmony_ci /* 389141cc406Sopenharmony_ci Save old device information to restore when we are done. 390141cc406Sopenharmony_ci */ 391141cc406Sopenharmony_ci if (tcgetattr (camera->fd, &tty_orig) == -1) 392141cc406Sopenharmony_ci { 393141cc406Sopenharmony_ci DBG (1, "init_dc240: error: could not get attributes\n"); 394141cc406Sopenharmony_ci return -1; 395141cc406Sopenharmony_ci } 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_ci memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios)); 398141cc406Sopenharmony_ci /* 399141cc406Sopenharmony_ci We need the device to be raw. 8 bits even parity on 9600 baud to start. 400141cc406Sopenharmony_ci */ 401141cc406Sopenharmony_ci#ifdef HAVE_CFMAKERAW 402141cc406Sopenharmony_ci cfmakeraw (&tty_new); 403141cc406Sopenharmony_ci#else 404141cc406Sopenharmony_ci /* Modified to set the port REALLY as required (9600, 8b, 1sb, NO parity). 405141cc406Sopenharmony_ci Code inspired by the gPhoto2 serial port setup */ 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci /* input control settings */ 408141cc406Sopenharmony_ci tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | 409141cc406Sopenharmony_ci IXANY | IXON | IXOFF | INPCK | ISTRIP); 410141cc406Sopenharmony_ci tty_new.c_iflag |= (BRKINT | IGNPAR); 411141cc406Sopenharmony_ci /* output control settings */ 412141cc406Sopenharmony_ci tty_new.c_oflag &= ~OPOST; 413141cc406Sopenharmony_ci /* hardware control settings */ 414141cc406Sopenharmony_ci tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8; 415141cc406Sopenharmony_ci tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB); 416141cc406Sopenharmony_ci# if defined(__sgi) 417141cc406Sopenharmony_ci tty_new.c_cflag &= ~CNEW_RTSCTS; 418141cc406Sopenharmony_ci# else 419141cc406Sopenharmony_ci/* OS/2 doesn't have CRTSCTS - will this work for them? */ 420141cc406Sopenharmony_ci# ifdef CRTSCTS 421141cc406Sopenharmony_ci tty_new.c_cflag &= ~CRTSCTS; 422141cc406Sopenharmony_ci# endif 423141cc406Sopenharmony_ci# endif 424141cc406Sopenharmony_ci tty_new.c_cflag |= CLOCAL | CREAD; 425141cc406Sopenharmony_ci#endif 426141cc406Sopenharmony_ci /* line discipline settings */ 427141cc406Sopenharmony_ci tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | 428141cc406Sopenharmony_ci ECHOK | IEXTEN); 429141cc406Sopenharmony_ci tty_new.c_cc[VMIN] = 0; 430141cc406Sopenharmony_ci tty_new.c_cc[VTIME] = 5; 431141cc406Sopenharmony_ci cfsetospeed (&tty_new, B9600); 432141cc406Sopenharmony_ci cfsetispeed (&tty_new, B9600); 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) 435141cc406Sopenharmony_ci { 436141cc406Sopenharmony_ci DBG (1, "init_dc240: error: could not set attributes\n"); 437141cc406Sopenharmony_ci return -1; 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci /* send a break to get it back to a known state */ 441141cc406Sopenharmony_ci /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK, 442141cc406Sopenharmony_ci * and TCSBRKP, but that is system dependent. e.g. on irix a non-zero 443141cc406Sopenharmony_ci * value does a drain instead of a break. A zero value is universally 444141cc406Sopenharmony_ci * used to send a break. 445141cc406Sopenharmony_ci */ 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci#ifdef HAVE_TCSENDBREAK 448141cc406Sopenharmony_ci tcsendbreak (camera->fd, 0); 449141cc406Sopenharmony_ci# if defined(__sgi) 450141cc406Sopenharmony_ci tcdrain (camera->fd); 451141cc406Sopenharmony_ci# endif 452141cc406Sopenharmony_ci# elif defined(TCSBRKP) 453141cc406Sopenharmony_ci ioctl (camera->fd, TCSBRKP, 0); 454141cc406Sopenharmony_ci# elif defined(TCSBRK) 455141cc406Sopenharmony_ci ioctl (camera->fd, TCSBRK, 0); 456141cc406Sopenharmony_ci#endif 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci /* and wait for it to recover from the break */ 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci#ifdef HAVE_USLEEP 461141cc406Sopenharmony_ci usleep (breakpause); 462141cc406Sopenharmony_ci#else 463141cc406Sopenharmony_ci sleep (1); 464141cc406Sopenharmony_ci#endif 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci /* We seem to get some garbage following the break, so 467141cc406Sopenharmony_ci * read anything pending */ 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_ci n = read (camera->fd, buf, 5); 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0], 472141cc406Sopenharmony_ci buf[1], buf[2], buf[3], buf[4]); 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci if (send_pck (camera->fd, init_pck) == -1) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci /* 477141cc406Sopenharmony_ci * The camera always powers up at 9600, so we try 478141cc406Sopenharmony_ci * that first. However, it may be already set to 479141cc406Sopenharmony_ci * a different speed. Try the entries in the table: 480141cc406Sopenharmony_ci */ 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci tcsetattr (camera->fd, TCSANOW, &tty_orig); 483141cc406Sopenharmony_ci DBG (1, "init_dc240: error: no response from camera\n"); 484141cc406Sopenharmony_ci return -1; 485141cc406Sopenharmony_ci } 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci n = read (camera->fd, buf, 5); 488141cc406Sopenharmony_ci DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0], 489141cc406Sopenharmony_ci buf[1], buf[2], buf[3], buf[4]); 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci /* 492141cc406Sopenharmony_ci Set speed to requested speed. 493141cc406Sopenharmony_ci */ 494141cc406Sopenharmony_ci cfsetospeed (&tty_new, Camera.baud); 495141cc406Sopenharmony_ci cfsetispeed (&tty_new, Camera.baud); 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) 498141cc406Sopenharmony_ci { 499141cc406Sopenharmony_ci DBG (1, "init_dc240: error: could not set attributes\n"); 500141cc406Sopenharmony_ci return -1; 501141cc406Sopenharmony_ci } 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci if (send_pck (camera->fd, open_card_pck) == -1) 505141cc406Sopenharmony_ci { 506141cc406Sopenharmony_ci DBG (1, "init_dc240: error: send_pck returned -1\n"); 507141cc406Sopenharmony_ci return -1; 508141cc406Sopenharmony_ci } 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci if (end_of_data (camera->fd) == -1) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci DBG (1, "init_dc240: error: end_of_data returned -1\n"); 513141cc406Sopenharmony_ci return -1; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci return camera->fd; 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_ci} 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_cistatic void 521141cc406Sopenharmony_ciclose_dc240 (SANE_Int fd) 522141cc406Sopenharmony_ci{ 523141cc406Sopenharmony_ci /* 524141cc406Sopenharmony_ci * Put the camera back to 9600 baud 525141cc406Sopenharmony_ci */ 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci if (close (fd) == -1) 528141cc406Sopenharmony_ci { 529141cc406Sopenharmony_ci DBG (1, "close_dc240: error: could not close device\n"); 530141cc406Sopenharmony_ci } 531141cc406Sopenharmony_ci} 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ciint 534141cc406Sopenharmony_ciget_info (DC240 * camera) 535141cc406Sopenharmony_ci{ 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci SANE_Char f[] = "get_info"; 538141cc406Sopenharmony_ci SANE_Byte buf[256]; 539141cc406Sopenharmony_ci SANE_Int n; 540141cc406Sopenharmony_ci struct cam_dirlist *e; 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci if (send_pck (camera->fd, info_pck) == -1) 543141cc406Sopenharmony_ci { 544141cc406Sopenharmony_ci DBG (1, "%s: error: send_pck returned -1\n", f); 545141cc406Sopenharmony_ci return -1; 546141cc406Sopenharmony_ci } 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci DBG (9, "%s: read info packet\n", f); 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci if (read_data (camera->fd, buf, 256) == -1) 551141cc406Sopenharmony_ci { 552141cc406Sopenharmony_ci DBG (1, "%s: error: read_data returned -1\n", f); 553141cc406Sopenharmony_ci return -1; 554141cc406Sopenharmony_ci } 555141cc406Sopenharmony_ci 556141cc406Sopenharmony_ci if (end_of_data (camera->fd) == -1) 557141cc406Sopenharmony_ci { 558141cc406Sopenharmony_ci DBG (1, "%s: error: end_of_data returned -1\n", f); 559141cc406Sopenharmony_ci return -1; 560141cc406Sopenharmony_ci } 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci camera->model = buf[1]; 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci if (camera->model != 0x5) 565141cc406Sopenharmony_ci { 566141cc406Sopenharmony_ci DBG (0, 567141cc406Sopenharmony_ci "Camera model (%d) is not DC-240 (5). " 568141cc406Sopenharmony_ci "Only the DC-240 is supported by this driver.\n", camera->model); 569141cc406Sopenharmony_ci } 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci camera->ver_major = buf[2]; 572141cc406Sopenharmony_ci camera->ver_minor = buf[3]; 573141cc406Sopenharmony_ci camera->pic_taken = buf[14] << 8 | buf[15]; 574141cc406Sopenharmony_ci DBG (4, "pic_taken=%d\n", camera->pic_taken); 575141cc406Sopenharmony_ci camera->pic_left = buf[64] << 8 | buf[65]; 576141cc406Sopenharmony_ci DBG (4, "pictures left (at current res)=%d\n", camera->pic_left); 577141cc406Sopenharmony_ci camera->flags.low_batt = buf[8]; 578141cc406Sopenharmony_ci DBG (4, "battery=%d (0=OK, 1=weak, 2=empty)\n", camera->flags.low_batt); 579141cc406Sopenharmony_ci DBG (4, "AC adapter status=%d\n", buf[9]); 580141cc406Sopenharmony_ci dc240_opt_lowres = !buf[79]; 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci if (Camera.pic_taken == 0) 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; 585141cc406Sopenharmony_ci image_range.min = 0; 586141cc406Sopenharmony_ci image_range.max = 0; 587141cc406Sopenharmony_ci } 588141cc406Sopenharmony_ci else 589141cc406Sopenharmony_ci { 590141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 591141cc406Sopenharmony_ci image_range.min = 1; 592141cc406Sopenharmony_ci image_range.max = Camera.pic_taken; 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_ci n = read_dir ("\\PCCARD\\DCIM\\*.*"); 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci /* If we've already got a folder_list, free it up before starting 598141cc406Sopenharmony_ci * the new one 599141cc406Sopenharmony_ci */ 600141cc406Sopenharmony_ci if (folder_list != NULL) 601141cc406Sopenharmony_ci { 602141cc406Sopenharmony_ci int tmp; 603141cc406Sopenharmony_ci for (tmp = 0; folder_list[tmp]; tmp++) 604141cc406Sopenharmony_ci { 605141cc406Sopenharmony_ci free (folder_list[tmp]); 606141cc406Sopenharmony_ci } 607141cc406Sopenharmony_ci free (folder_list); 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci folder_list = (SANE_String * *)malloc ((n + 1) * sizeof (SANE_String *)); 611141cc406Sopenharmony_ci for (e = dir_head, n = 0; e; e = e->next, n++) 612141cc406Sopenharmony_ci { 613141cc406Sopenharmony_ci folder_list[n] = (SANE_String *) strdup (e->name); 614141cc406Sopenharmony_ci if (strchr ((char *) folder_list[n], ' ')) 615141cc406Sopenharmony_ci { 616141cc406Sopenharmony_ci *strchr ((char *) folder_list[n], ' ') = '\0'; 617141cc406Sopenharmony_ci } 618141cc406Sopenharmony_ci } 619141cc406Sopenharmony_ci folder_list[n] = NULL; 620141cc406Sopenharmony_ci sod[DC240_OPT_FOLDER].constraint.string_list = 621141cc406Sopenharmony_ci (SANE_String_Const *) folder_list; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci return 0; 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci} 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci/* NEW */ 628141cc406Sopenharmony_cistatic SANE_Int 629141cc406Sopenharmony_ciread_data (SANE_Int fd, SANE_Byte * buf, SANE_Int sz) 630141cc406Sopenharmony_ci{ 631141cc406Sopenharmony_ci SANE_Byte ccsum; 632141cc406Sopenharmony_ci SANE_Byte rcsum; 633141cc406Sopenharmony_ci SANE_Byte c; 634141cc406Sopenharmony_ci SANE_Int retries = 0; 635141cc406Sopenharmony_ci SANE_Int n; 636141cc406Sopenharmony_ci SANE_Int r = 0; 637141cc406Sopenharmony_ci SANE_Int i; 638141cc406Sopenharmony_ci 639141cc406Sopenharmony_ci while (retries++ < 5) 640141cc406Sopenharmony_ci { 641141cc406Sopenharmony_ci 642141cc406Sopenharmony_ci /* 643141cc406Sopenharmony_ci * If this is not the first time through, then it must be 644141cc406Sopenharmony_ci * a retry - signal the camera that we didn't like what 645141cc406Sopenharmony_ci * we got. In either case, start filling the packet 646141cc406Sopenharmony_ci */ 647141cc406Sopenharmony_ci if (retries != 1) 648141cc406Sopenharmony_ci { 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci DBG (2, "Attempt retry %d\n", retries); 651141cc406Sopenharmony_ci c = 0xe3; 652141cc406Sopenharmony_ci if (write (fd, (char *) &c, 1) != 1) 653141cc406Sopenharmony_ci { 654141cc406Sopenharmony_ci DBG (1, "read_data: error: write ack\n"); 655141cc406Sopenharmony_ci return -1; 656141cc406Sopenharmony_ci } 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_ci } 659141cc406Sopenharmony_ci 660141cc406Sopenharmony_ci /* read the control byte */ 661141cc406Sopenharmony_ci if (read (fd, &c, 1) != 1) 662141cc406Sopenharmony_ci { 663141cc406Sopenharmony_ci DBG (3, 664141cc406Sopenharmony_ci "read_data: error: " 665141cc406Sopenharmony_ci "read for packet control byte returned bad stat!us\n"); 666141cc406Sopenharmony_ci return -1; 667141cc406Sopenharmony_ci } 668141cc406Sopenharmony_ci if (c != 1 && c != 0) 669141cc406Sopenharmony_ci { 670141cc406Sopenharmony_ci DBG (1, "read_data: error: incorrect packet control byte: %02x\n", 671141cc406Sopenharmony_ci c); 672141cc406Sopenharmony_ci return -1; 673141cc406Sopenharmony_ci } 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; 676141cc406Sopenharmony_ci n += r); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci if (r <= 0) 679141cc406Sopenharmony_ci { 680141cc406Sopenharmony_ci DBG (2, "read_data: warning: read returned -1\n"); 681141cc406Sopenharmony_ci continue; 682141cc406Sopenharmony_ci } 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci if (n < sz || read (fd, &rcsum, 1) != 1) 685141cc406Sopenharmony_ci { 686141cc406Sopenharmony_ci DBG (2, "read_data: warning: buffer underrun or no checksum\n"); 687141cc406Sopenharmony_ci continue; 688141cc406Sopenharmony_ci } 689141cc406Sopenharmony_ci 690141cc406Sopenharmony_ci for (i = 0, ccsum = 0; i < n; i++) 691141cc406Sopenharmony_ci ccsum ^= buf[i]; 692141cc406Sopenharmony_ci 693141cc406Sopenharmony_ci if (ccsum != rcsum) 694141cc406Sopenharmony_ci { 695141cc406Sopenharmony_ci DBG (2, 696141cc406Sopenharmony_ci "read_data: warning: " 697141cc406Sopenharmony_ci "bad checksum (got %02x != expected %02x)\n", rcsum, ccsum); 698141cc406Sopenharmony_ci continue; 699141cc406Sopenharmony_ci } 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci /* If we got this far, then the packet is OK */ 702141cc406Sopenharmony_ci break; 703141cc406Sopenharmony_ci 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci } 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci c = 0xd2; 708141cc406Sopenharmony_ci 709141cc406Sopenharmony_ci if (write (fd, (char *) &c, 1) != 1) 710141cc406Sopenharmony_ci { 711141cc406Sopenharmony_ci DBG (1, "read_data: error: write ack\n"); 712141cc406Sopenharmony_ci return -1; 713141cc406Sopenharmony_ci } 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci return 0; 716141cc406Sopenharmony_ci} 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_cistatic SANE_Int 719141cc406Sopenharmony_ciend_of_data (SANE_Int fd) 720141cc406Sopenharmony_ci{ 721141cc406Sopenharmony_ci SANE_Int n; 722141cc406Sopenharmony_ci SANE_Byte c; 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci do 725141cc406Sopenharmony_ci { /* loop until the camera isn't busy */ 726141cc406Sopenharmony_ci if ((n = read (fd, &c, 1)) == -1) 727141cc406Sopenharmony_ci { 728141cc406Sopenharmony_ci DBG (1, "end_of_data: error: read returned -1\n"); 729141cc406Sopenharmony_ci return -1; 730141cc406Sopenharmony_ci } 731141cc406Sopenharmony_ci if (n == 1 && c == 0) /* got successful end of data */ 732141cc406Sopenharmony_ci return 0; /* return success */ 733141cc406Sopenharmony_ci if (n == 1) 734141cc406Sopenharmony_ci { 735141cc406Sopenharmony_ci DBG (127, "end_of_data: got %x while waiting\n", c); 736141cc406Sopenharmony_ci } 737141cc406Sopenharmony_ci else 738141cc406Sopenharmony_ci { 739141cc406Sopenharmony_ci DBG (127, "end_of_data: waiting...\n"); 740141cc406Sopenharmony_ci } 741141cc406Sopenharmony_ci sleep (1); /* not too fast */ 742141cc406Sopenharmony_ci } 743141cc406Sopenharmony_ci/* It's not documented, but we see a d1 after snapping a picture */ 744141cc406Sopenharmony_ci while (c == 0xf0 || c == 0xd1); 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci /* Accck! Not busy, but not a good end of data either */ 747141cc406Sopenharmony_ci if (c != 0) 748141cc406Sopenharmony_ci { 749141cc406Sopenharmony_ci DBG (1, "end_of_data: error: bad EOD from camera (%02x)\n", 750141cc406Sopenharmony_ci (unsigned) c); 751141cc406Sopenharmony_ci return -1; 752141cc406Sopenharmony_ci } 753141cc406Sopenharmony_ci return 0; /* should never get here but shut gcc -Wall up */ 754141cc406Sopenharmony_ci} 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_cistatic SANE_Int 757141cc406Sopenharmony_cierase (SANE_Int fd) 758141cc406Sopenharmony_ci{ 759141cc406Sopenharmony_ci if (send_pck (fd, erase_pck) == -1) 760141cc406Sopenharmony_ci { 761141cc406Sopenharmony_ci DBG (1, "erase: error: send_pck returned -1\n"); 762141cc406Sopenharmony_ci return -1; 763141cc406Sopenharmony_ci } 764141cc406Sopenharmony_ci 765141cc406Sopenharmony_ci if (send_data (name_buf) == -1) 766141cc406Sopenharmony_ci { 767141cc406Sopenharmony_ci DBG (1, "erase: error: send_data returned -1\n"); 768141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci if (end_of_data (fd) == -1) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci DBG (1, "erase: error: end_of_data returned -1\n"); 774141cc406Sopenharmony_ci return -1; 775141cc406Sopenharmony_ci } 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci return 0; 778141cc406Sopenharmony_ci} 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_cistatic SANE_Int 781141cc406Sopenharmony_cichange_res (SANE_Int fd, SANE_Byte res) 782141cc406Sopenharmony_ci{ 783141cc406Sopenharmony_ci SANE_Char f[] = "change_res"; 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci DBG (127, "%s called, low_res=%d\n", f, res); 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci if (res != 0 && res != 1) 788141cc406Sopenharmony_ci { 789141cc406Sopenharmony_ci DBG (1, "%s: error: unsupported resolution\n", f); 790141cc406Sopenharmony_ci return -1; 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci /* cameras resolution semantics are opposite of ours */ 794141cc406Sopenharmony_ci res = !res; 795141cc406Sopenharmony_ci DBG (127, "%s: setting res to %d\n", f, res); 796141cc406Sopenharmony_ci res_pck[2] = res; 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci if (send_pck (fd, res_pck) == -1) 799141cc406Sopenharmony_ci { 800141cc406Sopenharmony_ci DBG (1, "%s: error: send_pck returned -1\n", f); 801141cc406Sopenharmony_ci } 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci if (end_of_data (fd) == -1) 804141cc406Sopenharmony_ci { 805141cc406Sopenharmony_ci DBG (1, "%s: error: end_of_data returned -1\n", f); 806141cc406Sopenharmony_ci } 807141cc406Sopenharmony_ci return 0; 808141cc406Sopenharmony_ci} 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ciSANE_Status 811141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 812141cc406Sopenharmony_ci{ 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci SANE_Char f[] = "sane_init"; 815141cc406Sopenharmony_ci SANE_Char dev_name[PATH_MAX], *p; 816141cc406Sopenharmony_ci size_t len; 817141cc406Sopenharmony_ci FILE *fp; 818141cc406Sopenharmony_ci SANE_Int baud; 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_ci DBG_INIT (); 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci if (version_code) 823141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci fp = sanei_config_open (DC240_CONFIG_FILE); 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci /* defaults */ 828141cc406Sopenharmony_ci Camera.baud = DEFAULT_BAUD_RATE; 829141cc406Sopenharmony_ci Camera.tty_name = DEFAULT_TTY; 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci if (!fp) 832141cc406Sopenharmony_ci { 833141cc406Sopenharmony_ci /* default to /dev/whatever instead of insisting on config file */ 834141cc406Sopenharmony_ci DBG (1, "%s: missing config file '%s'\n", f, DC240_CONFIG_FILE); 835141cc406Sopenharmony_ci } 836141cc406Sopenharmony_ci else 837141cc406Sopenharmony_ci { 838141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 839141cc406Sopenharmony_ci { 840141cc406Sopenharmony_ci dev_name[sizeof (dev_name) - 1] = '\0'; 841141cc406Sopenharmony_ci DBG (20, "%s: config- %s\n", f, dev_name); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci if (dev_name[0] == '#') 844141cc406Sopenharmony_ci continue; /* ignore line comments */ 845141cc406Sopenharmony_ci len = strlen (dev_name); 846141cc406Sopenharmony_ci if (!len) 847141cc406Sopenharmony_ci continue; /* ignore empty lines */ 848141cc406Sopenharmony_ci if (strncmp (dev_name, "port=", 5) == 0) 849141cc406Sopenharmony_ci { 850141cc406Sopenharmony_ci p = strchr (dev_name, '/'); 851141cc406Sopenharmony_ci if (p) 852141cc406Sopenharmony_ci Camera.tty_name = strdup (p); 853141cc406Sopenharmony_ci DBG (20, "Config file port=%s\n", Camera.tty_name); 854141cc406Sopenharmony_ci } 855141cc406Sopenharmony_ci else if (strncmp (dev_name, "baud=", 5) == 0) 856141cc406Sopenharmony_ci { 857141cc406Sopenharmony_ci baud = atoi (&dev_name[5]); 858141cc406Sopenharmony_ci switch (baud) 859141cc406Sopenharmony_ci { 860141cc406Sopenharmony_ci case 9600: 861141cc406Sopenharmony_ci Camera.baud = B9600; 862141cc406Sopenharmony_ci break; 863141cc406Sopenharmony_ci case 19200: 864141cc406Sopenharmony_ci Camera.baud = B19200; 865141cc406Sopenharmony_ci break; 866141cc406Sopenharmony_ci case 38400: 867141cc406Sopenharmony_ci Camera.baud = B38400; 868141cc406Sopenharmony_ci break; 869141cc406Sopenharmony_ci#ifdef B57600 870141cc406Sopenharmony_ci case 57600: 871141cc406Sopenharmony_ci Camera.baud = B57600; 872141cc406Sopenharmony_ci break; 873141cc406Sopenharmony_ci#endif 874141cc406Sopenharmony_ci#ifdef B115200 875141cc406Sopenharmony_ci case 115200: 876141cc406Sopenharmony_ci Camera.baud = B115200; 877141cc406Sopenharmony_ci break; 878141cc406Sopenharmony_ci#endif 879141cc406Sopenharmony_ci } 880141cc406Sopenharmony_ci DBG (20, "Config file baud=%d\n", Camera.baud); 881141cc406Sopenharmony_ci } 882141cc406Sopenharmony_ci else if (strcmp (dev_name, "dumpinquiry") == 0) 883141cc406Sopenharmony_ci { 884141cc406Sopenharmony_ci dumpinquiry = SANE_TRUE; 885141cc406Sopenharmony_ci } 886141cc406Sopenharmony_ci else if (strncmp (dev_name, "cmdrespause=", 12) == 0) 887141cc406Sopenharmony_ci { 888141cc406Sopenharmony_ci cmdrespause = atoi (&dev_name[12]); 889141cc406Sopenharmony_ci DBG (20, "Config file cmdrespause=%lu\n", cmdrespause); 890141cc406Sopenharmony_ci } 891141cc406Sopenharmony_ci else if (strncmp (dev_name, "breakpause=", 11) == 0) 892141cc406Sopenharmony_ci { 893141cc406Sopenharmony_ci breakpause = atoi (&dev_name[11]); 894141cc406Sopenharmony_ci DBG (20, "Config file breakpause=%lu\n", breakpause); 895141cc406Sopenharmony_ci } 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci fclose (fp); 898141cc406Sopenharmony_ci } 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci if (init_dc240 (&Camera) == -1) 901141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci if (get_info (&Camera) == -1) 904141cc406Sopenharmony_ci { 905141cc406Sopenharmony_ci DBG (1, "error: could not get info\n"); 906141cc406Sopenharmony_ci close_dc240 (Camera.fd); 907141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 908141cc406Sopenharmony_ci } 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci /* load the current images array */ 911141cc406Sopenharmony_ci get_pictures_info (); 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci if (Camera.pic_taken == 0) 914141cc406Sopenharmony_ci { 915141cc406Sopenharmony_ci Camera.current_picture_number = 0; 916141cc406Sopenharmony_ci parms.bytes_per_line = 0; 917141cc406Sopenharmony_ci parms.pixels_per_line = 0; 918141cc406Sopenharmony_ci parms.lines = 0; 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci else 921141cc406Sopenharmony_ci { 922141cc406Sopenharmony_ci Camera.current_picture_number = 1; 923141cc406Sopenharmony_ci set_res (Camera.Pictures[Camera.current_picture_number - 1].low_res); 924141cc406Sopenharmony_ci } 925141cc406Sopenharmony_ci 926141cc406Sopenharmony_ci if (dumpinquiry) 927141cc406Sopenharmony_ci { 928141cc406Sopenharmony_ci DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n"); 929141cc406Sopenharmony_ci DBG (0, "Model...........: DC%s\n", "240"); 930141cc406Sopenharmony_ci DBG (0, "Firmware version: %d.%d\n", Camera.ver_major, 931141cc406Sopenharmony_ci Camera.ver_minor); 932141cc406Sopenharmony_ci DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken, 933141cc406Sopenharmony_ci Camera.pic_taken + Camera.pic_left); 934141cc406Sopenharmony_ci DBG (0, "Battery state...: %s\n", 935141cc406Sopenharmony_ci Camera.flags.low_batt == 0 ? "good" : (Camera.flags.low_batt == 936141cc406Sopenharmony_ci 1 ? "weak" : "empty")); 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 940141cc406Sopenharmony_ci} 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_civoid 943141cc406Sopenharmony_cisane_exit (void) 944141cc406Sopenharmony_ci{ 945141cc406Sopenharmony_ci} 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci/* Device select/open/close */ 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_cistatic const SANE_Device dev[] = { 950141cc406Sopenharmony_ci { 951141cc406Sopenharmony_ci "0", 952141cc406Sopenharmony_ci "Kodak", 953141cc406Sopenharmony_ci "DC-240", 954141cc406Sopenharmony_ci "still camera"}, 955141cc406Sopenharmony_ci}; 956141cc406Sopenharmony_ci 957141cc406Sopenharmony_cistatic const SANE_Device *devlist[] = { 958141cc406Sopenharmony_ci dev + 0, 0 959141cc406Sopenharmony_ci}; 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ciSANE_Status 962141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool 963141cc406Sopenharmony_ci __sane_unused__ local_only) 964141cc406Sopenharmony_ci{ 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci DBG (127, "sane_get_devices called\n"); 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci *device_list = devlist; 969141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 970141cc406Sopenharmony_ci} 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ciSANE_Status 973141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 974141cc406Sopenharmony_ci{ 975141cc406Sopenharmony_ci SANE_Int i; 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci DBG (127, "sane_open for device %s\n", devicename); 978141cc406Sopenharmony_ci if (!devicename[0]) 979141cc406Sopenharmony_ci { 980141cc406Sopenharmony_ci i = 0; 981141cc406Sopenharmony_ci } 982141cc406Sopenharmony_ci else 983141cc406Sopenharmony_ci { 984141cc406Sopenharmony_ci for (i = 0; i < NELEMS (dev); ++i) 985141cc406Sopenharmony_ci { 986141cc406Sopenharmony_ci if (strcmp (devicename, dev[i].name) == 0) 987141cc406Sopenharmony_ci { 988141cc406Sopenharmony_ci break; 989141cc406Sopenharmony_ci } 990141cc406Sopenharmony_ci } 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci if (i >= NELEMS (dev)) 994141cc406Sopenharmony_ci { 995141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci if (is_open) 999141cc406Sopenharmony_ci { 1000141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1001141cc406Sopenharmony_ci } 1002141cc406Sopenharmony_ci 1003141cc406Sopenharmony_ci is_open = 1; 1004141cc406Sopenharmony_ci *handle = MAGIC; 1005141cc406Sopenharmony_ci 1006141cc406Sopenharmony_ci DBG (4, "sane_open: pictures taken=%d\n", Camera.pic_taken); 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1009141cc406Sopenharmony_ci} 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_civoid 1012141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1013141cc406Sopenharmony_ci{ 1014141cc406Sopenharmony_ci DBG (127, "sane_close called\n"); 1015141cc406Sopenharmony_ci if (handle == MAGIC) 1016141cc406Sopenharmony_ci is_open = 0; 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci DBG (127, "sane_close returning\n"); 1019141cc406Sopenharmony_ci} 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1022141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1023141cc406Sopenharmony_ci{ 1024141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 1025141cc406Sopenharmony_ci return NULL; /* wrong device */ 1026141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (sod)) 1027141cc406Sopenharmony_ci return NULL; 1028141cc406Sopenharmony_ci return &sod[option]; 1029141cc406Sopenharmony_ci} 1030141cc406Sopenharmony_ci 1031141cc406Sopenharmony_cistatic SANE_Int myinfo = 0; 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ciSANE_Status 1034141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1035141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 1036141cc406Sopenharmony_ci{ 1037141cc406Sopenharmony_ci SANE_Status status; 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci if (option < 0 || option >= NELEMS (sod)) 1040141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown option ... */ 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci /* Need to put this DBG line after the range check on option */ 1043141cc406Sopenharmony_ci DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", 1044141cc406Sopenharmony_ci handle, sod[option].title, 1045141cc406Sopenharmony_ci (action == 1046141cc406Sopenharmony_ci SANE_ACTION_SET_VALUE ? "SET" : (action == 1047141cc406Sopenharmony_ci SANE_ACTION_GET_VALUE ? "GET" : 1048141cc406Sopenharmony_ci "SETAUTO")), value, (void *) info); 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 1051141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown handle ... */ 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci switch (action) 1054141cc406Sopenharmony_ci { 1055141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci /* Can't set disabled options */ 1058141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (sod[option].cap)) 1059141cc406Sopenharmony_ci { 1060141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1061141cc406Sopenharmony_ci } 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci /* initialize info to zero - we'll OR in various values later */ 1064141cc406Sopenharmony_ci if (info) 1065141cc406Sopenharmony_ci *info = 0; 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci status = sanei_constrain_value (sod + option, value, &myinfo); 1068141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1069141cc406Sopenharmony_ci { 1070141cc406Sopenharmony_ci DBG (2, "Constraint error in control_option\n"); 1071141cc406Sopenharmony_ci return status; 1072141cc406Sopenharmony_ci } 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_ci switch (option) 1075141cc406Sopenharmony_ci { 1076141cc406Sopenharmony_ci case DC240_OPT_IMAGE_NUMBER: 1077141cc406Sopenharmony_ci if (*(SANE_Word *) value <= Camera.pic_taken) 1078141cc406Sopenharmony_ci Camera.current_picture_number = *(SANE_Word *) value; 1079141cc406Sopenharmony_ci else 1080141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1081141cc406Sopenharmony_ci 1082141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_ci /* get the image's resolution, unless the camera has no 1085141cc406Sopenharmony_ci * pictures yet 1086141cc406Sopenharmony_ci */ 1087141cc406Sopenharmony_ci if (Camera.pic_taken != 0) 1088141cc406Sopenharmony_ci { 1089141cc406Sopenharmony_ci set_res (Camera. 1090141cc406Sopenharmony_ci Pictures[Camera.current_picture_number - 1].low_res); 1091141cc406Sopenharmony_ci } 1092141cc406Sopenharmony_ci break; 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci case DC240_OPT_THUMBS: 1095141cc406Sopenharmony_ci dc240_opt_thumbnails = !!*(SANE_Word *) value; 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci /* Thumbnail forces an image size change: */ 1098141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci if (Camera.pic_taken != 0) 1101141cc406Sopenharmony_ci { 1102141cc406Sopenharmony_ci set_res (Camera. 1103141cc406Sopenharmony_ci Pictures[Camera.current_picture_number - 1].low_res); 1104141cc406Sopenharmony_ci } 1105141cc406Sopenharmony_ci break; 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci case DC240_OPT_SNAP: 1108141cc406Sopenharmony_ci switch (*(SANE_Bool *) value) 1109141cc406Sopenharmony_ci { 1110141cc406Sopenharmony_ci case SANE_TRUE: 1111141cc406Sopenharmony_ci dc240_opt_snap = SANE_TRUE; 1112141cc406Sopenharmony_ci break; 1113141cc406Sopenharmony_ci case SANE_FALSE: 1114141cc406Sopenharmony_ci dc240_opt_snap = SANE_FALSE; 1115141cc406Sopenharmony_ci break; 1116141cc406Sopenharmony_ci default: 1117141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1118141cc406Sopenharmony_ci } 1119141cc406Sopenharmony_ci 1120141cc406Sopenharmony_ci /* Snap forces new image size and changes image range */ 1121141cc406Sopenharmony_ci 1122141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1123141cc406Sopenharmony_ci /* if we are snapping a new one */ 1124141cc406Sopenharmony_ci if (dc240_opt_snap) 1125141cc406Sopenharmony_ci { 1126141cc406Sopenharmony_ci /* activate the resolution setting */ 1127141cc406Sopenharmony_ci sod[DC240_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; 1128141cc406Sopenharmony_ci /* and de-activate the image number selector */ 1129141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; 1130141cc406Sopenharmony_ci } 1131141cc406Sopenharmony_ci else 1132141cc406Sopenharmony_ci { 1133141cc406Sopenharmony_ci /* deactivate the resolution setting */ 1134141cc406Sopenharmony_ci sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; 1135141cc406Sopenharmony_ci /* and activate the image number selector */ 1136141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 1137141cc406Sopenharmony_ci } 1138141cc406Sopenharmony_ci /* set params according to resolution settings */ 1139141cc406Sopenharmony_ci set_res (dc240_opt_lowres); 1140141cc406Sopenharmony_ci 1141141cc406Sopenharmony_ci break; 1142141cc406Sopenharmony_ci 1143141cc406Sopenharmony_ci case DC240_OPT_LOWRES: 1144141cc406Sopenharmony_ci dc240_opt_lowres = !!*(SANE_Word *) value; 1145141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1146141cc406Sopenharmony_ci 1147141cc406Sopenharmony_ci/* XXX - change the number of pictures left depending on resolution 1148141cc406Sopenharmony_ci perhaps just call get_info again? 1149141cc406Sopenharmony_ci*/ 1150141cc406Sopenharmony_ci set_res (dc240_opt_lowres); 1151141cc406Sopenharmony_ci 1152141cc406Sopenharmony_ci break; 1153141cc406Sopenharmony_ci 1154141cc406Sopenharmony_ci case DC240_OPT_ERASE: 1155141cc406Sopenharmony_ci dc240_opt_erase = !!*(SANE_Word *) value; 1156141cc406Sopenharmony_ci break; 1157141cc406Sopenharmony_ci 1158141cc406Sopenharmony_ci case DC240_OPT_AUTOINC: 1159141cc406Sopenharmony_ci dc240_opt_autoinc = !!*(SANE_Word *) value; 1160141cc406Sopenharmony_ci break; 1161141cc406Sopenharmony_ci 1162141cc406Sopenharmony_ci case DC240_OPT_FOLDER: 1163141cc406Sopenharmony_ci DBG (1, "FIXME set folder not implemented yet\n"); 1164141cc406Sopenharmony_ci break; 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci case DC240_OPT_DEFAULT: 1167141cc406Sopenharmony_ci dc240_opt_thumbnails = 0; 1168141cc406Sopenharmony_ci dc240_opt_snap = 0; 1169141cc406Sopenharmony_ci 1170141cc406Sopenharmony_ci /* deactivate the resolution setting */ 1171141cc406Sopenharmony_ci sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; 1172141cc406Sopenharmony_ci /* and activate the image number selector */ 1173141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci DBG (1, "Fixme: Set all defaults here!\n"); 1178141cc406Sopenharmony_ci break; 1179141cc406Sopenharmony_ci 1180141cc406Sopenharmony_ci case DC240_OPT_INIT_DC240: 1181141cc406Sopenharmony_ci if ((Camera.fd = init_dc240 (&Camera)) == -1) 1182141cc406Sopenharmony_ci { 1183141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1184141cc406Sopenharmony_ci } 1185141cc406Sopenharmony_ci if (get_info (&Camera) == -1) 1186141cc406Sopenharmony_ci { 1187141cc406Sopenharmony_ci DBG (1, "error: could not get info\n"); 1188141cc406Sopenharmony_ci close_dc240 (Camera.fd); 1189141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1190141cc406Sopenharmony_ci } 1191141cc406Sopenharmony_ci 1192141cc406Sopenharmony_ci /* load the current images array */ 1193141cc406Sopenharmony_ci get_pictures_info (); 1194141cc406Sopenharmony_ci 1195141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1196141cc406Sopenharmony_ci break; 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci default: 1199141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1200141cc406Sopenharmony_ci } 1201141cc406Sopenharmony_ci break; 1202141cc406Sopenharmony_ci 1203141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 1204141cc406Sopenharmony_ci /* Can't return status for disabled options */ 1205141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (sod[option].cap)) 1206141cc406Sopenharmony_ci { 1207141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1208141cc406Sopenharmony_ci } 1209141cc406Sopenharmony_ci 1210141cc406Sopenharmony_ci switch (option) 1211141cc406Sopenharmony_ci { 1212141cc406Sopenharmony_ci case 0: 1213141cc406Sopenharmony_ci *(SANE_Word *) value = NELEMS (sod); 1214141cc406Sopenharmony_ci break; 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci case DC240_OPT_IMAGE_NUMBER: 1217141cc406Sopenharmony_ci *(SANE_Word *) value = Camera.current_picture_number; 1218141cc406Sopenharmony_ci break; 1219141cc406Sopenharmony_ci 1220141cc406Sopenharmony_ci case DC240_OPT_THUMBS: 1221141cc406Sopenharmony_ci *(SANE_Word *) value = dc240_opt_thumbnails; 1222141cc406Sopenharmony_ci break; 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci case DC240_OPT_SNAP: 1225141cc406Sopenharmony_ci *(SANE_Word *) value = dc240_opt_snap; 1226141cc406Sopenharmony_ci break; 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci case DC240_OPT_LOWRES: 1229141cc406Sopenharmony_ci *(SANE_Word *) value = dc240_opt_lowres; 1230141cc406Sopenharmony_ci break; 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci case DC240_OPT_ERASE: 1233141cc406Sopenharmony_ci *(SANE_Word *) value = dc240_opt_erase; 1234141cc406Sopenharmony_ci break; 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci case DC240_OPT_AUTOINC: 1237141cc406Sopenharmony_ci *(SANE_Word *) value = dc240_opt_autoinc; 1238141cc406Sopenharmony_ci break; 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci case DC240_OPT_FOLDER: 1241141cc406Sopenharmony_ci strcpy ((char *) value, (char *) folder_list[current_folder]); 1242141cc406Sopenharmony_ci break; 1243141cc406Sopenharmony_ci 1244141cc406Sopenharmony_ci default: 1245141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1246141cc406Sopenharmony_ci } 1247141cc406Sopenharmony_ci break; 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 1250141cc406Sopenharmony_ci switch (option) 1251141cc406Sopenharmony_ci { 1252141cc406Sopenharmony_ci default: 1253141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ 1254141cc406Sopenharmony_ci } 1255141cc406Sopenharmony_ci } 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci if (info && action == SANE_ACTION_SET_VALUE) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci *info = myinfo; 1260141cc406Sopenharmony_ci myinfo = 0; 1261141cc406Sopenharmony_ci } 1262141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1263141cc406Sopenharmony_ci} 1264141cc406Sopenharmony_ci 1265141cc406Sopenharmony_ciSANE_Status 1266141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1267141cc406Sopenharmony_ci{ 1268141cc406Sopenharmony_ci SANE_Int rc = SANE_STATUS_GOOD; 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci DBG (127, "sane_get_params called, wid=%d,height=%d\n", 1271141cc406Sopenharmony_ci parms.pixels_per_line, parms.lines); 1272141cc406Sopenharmony_ci 1273141cc406Sopenharmony_ci if (handle != MAGIC || !is_open) 1274141cc406Sopenharmony_ci rc = SANE_STATUS_INVAL; /* Unknown handle ... */ 1275141cc406Sopenharmony_ci 1276141cc406Sopenharmony_ci parms.last_frame = SANE_TRUE; /* Have no idea what this does */ 1277141cc406Sopenharmony_ci *params = parms; 1278141cc406Sopenharmony_ci DBG (127, "sane_get_params return %d\n", rc); 1279141cc406Sopenharmony_ci return rc; 1280141cc406Sopenharmony_ci} 1281141cc406Sopenharmony_ci 1282141cc406Sopenharmony_citypedef struct 1283141cc406Sopenharmony_ci{ 1284141cc406Sopenharmony_ci struct jpeg_source_mgr pub; 1285141cc406Sopenharmony_ci JOCTET *buffer; 1286141cc406Sopenharmony_ci} 1287141cc406Sopenharmony_cimy_source_mgr; 1288141cc406Sopenharmony_citypedef my_source_mgr *my_src_ptr; 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ciMETHODDEF (void) 1291141cc406Sopenharmony_cijpeg_init_source (j_decompress_ptr __sane_unused__ cinfo) 1292141cc406Sopenharmony_ci{ 1293141cc406Sopenharmony_ci /* nothing to do */ 1294141cc406Sopenharmony_ci} 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ciMETHODDEF (boolean) jpeg_fill_input_buffer (j_decompress_ptr cinfo) 1297141cc406Sopenharmony_ci{ 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci my_src_ptr src = (my_src_ptr) cinfo->src; 1300141cc406Sopenharmony_ci 1301141cc406Sopenharmony_ci if (read_data (Camera.fd, src->buffer, 512) == -1) 1302141cc406Sopenharmony_ci { 1303141cc406Sopenharmony_ci DBG (5, "sane_start: read_data failed\n"); 1304141cc406Sopenharmony_ci src->buffer[0] = (JOCTET) 0xFF; 1305141cc406Sopenharmony_ci src->buffer[1] = (JOCTET) JPEG_EOI; 1306141cc406Sopenharmony_ci return FALSE; 1307141cc406Sopenharmony_ci } 1308141cc406Sopenharmony_ci src->pub.next_input_byte = src->buffer; 1309141cc406Sopenharmony_ci src->pub.bytes_in_buffer = 512; 1310141cc406Sopenharmony_ci 1311141cc406Sopenharmony_ci return TRUE; 1312141cc406Sopenharmony_ci} 1313141cc406Sopenharmony_ci 1314141cc406Sopenharmony_ciMETHODDEF (void) jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes) 1315141cc406Sopenharmony_ci{ 1316141cc406Sopenharmony_ci 1317141cc406Sopenharmony_ci my_src_ptr src = (my_src_ptr) cinfo->src; 1318141cc406Sopenharmony_ci 1319141cc406Sopenharmony_ci if (num_bytes > 0) 1320141cc406Sopenharmony_ci { 1321141cc406Sopenharmony_ci while (num_bytes > (long) src->pub.bytes_in_buffer) 1322141cc406Sopenharmony_ci { 1323141cc406Sopenharmony_ci num_bytes -= (long) src->pub.bytes_in_buffer; 1324141cc406Sopenharmony_ci (void) jpeg_fill_input_buffer (cinfo); 1325141cc406Sopenharmony_ci } 1326141cc406Sopenharmony_ci } 1327141cc406Sopenharmony_ci src->pub.next_input_byte += (size_t) num_bytes; 1328141cc406Sopenharmony_ci src->pub.bytes_in_buffer -= (size_t) num_bytes; 1329141cc406Sopenharmony_ci} 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_cistatic SANE_Byte linebuffer[HIGHRES_WIDTH * 3]; 1332141cc406Sopenharmony_cistatic SANE_Int linebuffer_size = 0; 1333141cc406Sopenharmony_cistatic SANE_Int linebuffer_index = 0; 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci 1336141cc406Sopenharmony_ciMETHODDEF (void) 1337141cc406Sopenharmony_cijpeg_term_source (j_decompress_ptr __sane_unused__ cinfo) 1338141cc406Sopenharmony_ci{ 1339141cc406Sopenharmony_ci /* no work necessary here */ 1340141cc406Sopenharmony_ci} 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ciSANE_Status 1343141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1344141cc406Sopenharmony_ci{ 1345141cc406Sopenharmony_ci SANE_Int i; 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci DBG (127, "sane_start called\n"); 1348141cc406Sopenharmony_ci if (handle != MAGIC || !is_open || 1349141cc406Sopenharmony_ci (Camera.current_picture_number == 0 && dc240_opt_snap == SANE_FALSE)) 1350141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* Unknown handle ... */ 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci if (Camera.scanning) 1353141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci/* 1356141cc406Sopenharmony_ci * This shouldn't normally happen, but we allow it as a special case 1357141cc406Sopenharmony_ci * when batch/autoinc are in effect. The first illegal picture number 1358141cc406Sopenharmony_ci * terminates the scan 1359141cc406Sopenharmony_ci */ 1360141cc406Sopenharmony_ci if (Camera.current_picture_number > Camera.pic_taken) 1361141cc406Sopenharmony_ci { 1362141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1363141cc406Sopenharmony_ci } 1364141cc406Sopenharmony_ci 1365141cc406Sopenharmony_ci if (dc240_opt_snap) 1366141cc406Sopenharmony_ci { 1367141cc406Sopenharmony_ci /* 1368141cc406Sopenharmony_ci * Don't allow picture unless there is room in the 1369141cc406Sopenharmony_ci * camera. 1370141cc406Sopenharmony_ci */ 1371141cc406Sopenharmony_ci if (Camera.pic_left == 0) 1372141cc406Sopenharmony_ci { 1373141cc406Sopenharmony_ci DBG (3, "No room to store new picture\n"); 1374141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1375141cc406Sopenharmony_ci } 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ci if (snap_pic (Camera.fd) == SANE_STATUS_INVAL) 1379141cc406Sopenharmony_ci { 1380141cc406Sopenharmony_ci DBG (1, "Failed to snap new picture\n"); 1381141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1382141cc406Sopenharmony_ci } 1383141cc406Sopenharmony_ci } 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci if (dc240_opt_thumbnails) 1386141cc406Sopenharmony_ci { 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci if (send_pck (Camera.fd, thumb_pck) == -1) 1389141cc406Sopenharmony_ci { 1390141cc406Sopenharmony_ci DBG (1, "sane_start: error: send_pck returned -1\n"); 1391141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1392141cc406Sopenharmony_ci } 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci /* Picture size should have been set when thumbnails were 1395141cc406Sopenharmony_ci * selected. But, check just in case 1396141cc406Sopenharmony_ci */ 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci if (parms.pixels_per_line != 160 || 1399141cc406Sopenharmony_ci parms.bytes_per_line != 160 * 3 || parms.lines != 120) 1400141cc406Sopenharmony_ci { 1401141cc406Sopenharmony_ci DBG (1, "sane_start: fixme! thumbnail image size is wrong\n"); 1402141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1403141cc406Sopenharmony_ci } 1404141cc406Sopenharmony_ci } 1405141cc406Sopenharmony_ci else 1406141cc406Sopenharmony_ci { 1407141cc406Sopenharmony_ci if (send_pck (Camera.fd, pic_pck) == -1) 1408141cc406Sopenharmony_ci { 1409141cc406Sopenharmony_ci DBG (1, "sane_start: error: send_pck returned -1\n"); 1410141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1411141cc406Sopenharmony_ci } 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci } 1414141cc406Sopenharmony_ci { 1415141cc406Sopenharmony_ci my_src_ptr src; 1416141cc406Sopenharmony_ci 1417141cc406Sopenharmony_ci struct jpeg_error_mgr jerr; 1418141cc406Sopenharmony_ci SANE_Int n; 1419141cc406Sopenharmony_ci SANE_Char f[] = "sane_start"; 1420141cc406Sopenharmony_ci SANE_Char path[256]; 1421141cc406Sopenharmony_ci struct cam_dirlist *e; 1422141cc406Sopenharmony_ci name_buf[0] = 0x80; 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci for (n = 1, e = dir_head; e; n++, e = e->next) 1425141cc406Sopenharmony_ci { 1426141cc406Sopenharmony_ci if (n == Camera.current_picture_number) 1427141cc406Sopenharmony_ci break; 1428141cc406Sopenharmony_ci } 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci strcpy (path, "\\PCCARD\\DCIM\\"); 1431141cc406Sopenharmony_ci strcat (path, (char *) folder_list[current_folder]); 1432141cc406Sopenharmony_ci strcat (path, "\\"); 1433141cc406Sopenharmony_ci strcat (path, e->name); 1434141cc406Sopenharmony_ci path[strlen (path) - 3] = '\0'; 1435141cc406Sopenharmony_ci strcat (path, ".JPG"); 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ci DBG (9, "%s: pic to read is %d name is %s\n", f, n, path); 1438141cc406Sopenharmony_ci 1439141cc406Sopenharmony_ci strcpy ((char *) &name_buf[1], path); 1440141cc406Sopenharmony_ci for (i = 49; i <= 56; i++) 1441141cc406Sopenharmony_ci { 1442141cc406Sopenharmony_ci name_buf[i] = 0xff; 1443141cc406Sopenharmony_ci } 1444141cc406Sopenharmony_ci 1445141cc406Sopenharmony_ci if (send_data (name_buf) == -1) 1446141cc406Sopenharmony_ci { 1447141cc406Sopenharmony_ci DBG (1, "%s: error: send_data returned -1\n", f); 1448141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1449141cc406Sopenharmony_ci } 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci cinfo.err = jpeg_std_error (&jerr); 1452141cc406Sopenharmony_ci jpeg_create_decompress (&cinfo); 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ci cinfo.src = 1455141cc406Sopenharmony_ci (struct jpeg_source_mgr *) (*cinfo.mem-> 1456141cc406Sopenharmony_ci alloc_small) ((j_common_ptr) & cinfo, 1457141cc406Sopenharmony_ci JPOOL_PERMANENT, 1458141cc406Sopenharmony_ci sizeof (my_source_mgr)); 1459141cc406Sopenharmony_ci src = (my_src_ptr) cinfo.src; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) & 1462141cc406Sopenharmony_ci cinfo, 1463141cc406Sopenharmony_ci JPOOL_PERMANENT, 1464141cc406Sopenharmony_ci 1024 * 1465141cc406Sopenharmony_ci sizeof (JOCTET)); 1466141cc406Sopenharmony_ci src->pub.init_source = jpeg_init_source; 1467141cc406Sopenharmony_ci src->pub.fill_input_buffer = jpeg_fill_input_buffer; 1468141cc406Sopenharmony_ci src->pub.skip_input_data = jpeg_skip_input_data; 1469141cc406Sopenharmony_ci src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */ 1470141cc406Sopenharmony_ci src->pub.term_source = jpeg_term_source; 1471141cc406Sopenharmony_ci src->pub.bytes_in_buffer = 0; 1472141cc406Sopenharmony_ci src->pub.next_input_byte = NULL; 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci (void) jpeg_read_header (&cinfo, TRUE); 1475141cc406Sopenharmony_ci dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo); 1476141cc406Sopenharmony_ci (void) jpeg_start_decompress (&cinfo); 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci linebuffer_size = 0; 1479141cc406Sopenharmony_ci linebuffer_index = 0; 1480141cc406Sopenharmony_ci } 1481141cc406Sopenharmony_ci 1482141cc406Sopenharmony_ci Camera.scanning = SANE_TRUE; /* don't overlap scan requests */ 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1485141cc406Sopenharmony_ci} 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ciSANE_Status 1488141cc406Sopenharmony_cisane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data, 1489141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 1490141cc406Sopenharmony_ci{ 1491141cc406Sopenharmony_ci SANE_Int lines = 0; 1492141cc406Sopenharmony_ci SANE_Char filename_buf[256]; 1493141cc406Sopenharmony_ci 1494141cc406Sopenharmony_ci if (Camera.scanning == SANE_FALSE) 1495141cc406Sopenharmony_ci { 1496141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1497141cc406Sopenharmony_ci } 1498141cc406Sopenharmony_ci 1499141cc406Sopenharmony_ci /* If there is anything in the buffer, satisfy the read from there */ 1500141cc406Sopenharmony_ci if (linebuffer_size && linebuffer_index < linebuffer_size) 1501141cc406Sopenharmony_ci { 1502141cc406Sopenharmony_ci *length = linebuffer_size - linebuffer_index; 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci if (*length > max_length) 1505141cc406Sopenharmony_ci { 1506141cc406Sopenharmony_ci *length = max_length; 1507141cc406Sopenharmony_ci } 1508141cc406Sopenharmony_ci memcpy (data, linebuffer + linebuffer_index, *length); 1509141cc406Sopenharmony_ci linebuffer_index += *length; 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1512141cc406Sopenharmony_ci } 1513141cc406Sopenharmony_ci 1514141cc406Sopenharmony_ci if (cinfo.output_scanline >= cinfo.output_height) 1515141cc406Sopenharmony_ci { 1516141cc406Sopenharmony_ci *length = 0; 1517141cc406Sopenharmony_ci 1518141cc406Sopenharmony_ci /* clean up comms with the camera */ 1519141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1520141cc406Sopenharmony_ci { 1521141cc406Sopenharmony_ci DBG (1, "sane_read: error: end_of_data returned -1\n"); 1522141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1523141cc406Sopenharmony_ci } 1524141cc406Sopenharmony_ci if (dc240_opt_erase) 1525141cc406Sopenharmony_ci { 1526141cc406Sopenharmony_ci DBG (127, "sane_read bp%d, erase image\n", __LINE__); 1527141cc406Sopenharmony_ci if (erase (Camera.fd) == -1) 1528141cc406Sopenharmony_ci { 1529141cc406Sopenharmony_ci DBG (1, "Failed to erase memory\n"); 1530141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1531141cc406Sopenharmony_ci } 1532141cc406Sopenharmony_ci Camera.pic_taken--; 1533141cc406Sopenharmony_ci Camera.pic_left++; 1534141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1535141cc406Sopenharmony_ci image_range.max--; 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1538141cc406Sopenharmony_ci strcpy ((char *) filename_buf, 1539141cc406Sopenharmony_ci strrchr ((char *) name_buf + 1, '\\') + 1); 1540141cc406Sopenharmony_ci strcpy (strrchr ((char *) filename_buf, '.'), "JPG"); 1541141cc406Sopenharmony_ci dir_delete ((SANE_String) filename_buf); 1542141cc406Sopenharmony_ci 1543141cc406Sopenharmony_ci } 1544141cc406Sopenharmony_ci if (dc240_opt_autoinc) 1545141cc406Sopenharmony_ci { 1546141cc406Sopenharmony_ci if (Camera.current_picture_number <= Camera.pic_taken) 1547141cc406Sopenharmony_ci { 1548141cc406Sopenharmony_ci Camera.current_picture_number++; 1549141cc406Sopenharmony_ci 1550141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1551141cc406Sopenharmony_ci 1552141cc406Sopenharmony_ci /* get the image's resolution */ 1553141cc406Sopenharmony_ci set_res (Camera.Pictures[Camera.current_picture_number - 1]. 1554141cc406Sopenharmony_ci low_res); 1555141cc406Sopenharmony_ci } 1556141cc406Sopenharmony_ci DBG (4, "Increment count to %d (total %d)\n", 1557141cc406Sopenharmony_ci Camera.current_picture_number, Camera.pic_taken); 1558141cc406Sopenharmony_ci } 1559141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1560141cc406Sopenharmony_ci } 1561141cc406Sopenharmony_ci 1562141cc406Sopenharmony_ci/* XXX - we should read more than 1 line at a time here */ 1563141cc406Sopenharmony_ci lines = 1; 1564141cc406Sopenharmony_ci (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines); 1565141cc406Sopenharmony_ci (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) linebuffer); 1566141cc406Sopenharmony_ci 1567141cc406Sopenharmony_ci *length = cinfo.output_width * cinfo.output_components * lines; 1568141cc406Sopenharmony_ci linebuffer_size = *length; 1569141cc406Sopenharmony_ci linebuffer_index = 0; 1570141cc406Sopenharmony_ci 1571141cc406Sopenharmony_ci if (*length > max_length) 1572141cc406Sopenharmony_ci { 1573141cc406Sopenharmony_ci *length = max_length; 1574141cc406Sopenharmony_ci } 1575141cc406Sopenharmony_ci memcpy (data, linebuffer + linebuffer_index, *length); 1576141cc406Sopenharmony_ci linebuffer_index += *length; 1577141cc406Sopenharmony_ci 1578141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1579141cc406Sopenharmony_ci} 1580141cc406Sopenharmony_ci 1581141cc406Sopenharmony_civoid 1582141cc406Sopenharmony_cisane_cancel (SANE_Handle __sane_unused__ handle) 1583141cc406Sopenharmony_ci{ 1584141cc406Sopenharmony_ci unsigned char cancel_byte[] = { 0xe4 }; 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci if (Camera.scanning) 1587141cc406Sopenharmony_ci { 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci /* Flush any pending data from the camera before continuing */ 1590141cc406Sopenharmony_ci { 1591141cc406Sopenharmony_ci SANE_Int n; 1592141cc406Sopenharmony_ci SANE_Char flush[1024]; 1593141cc406Sopenharmony_ci do 1594141cc406Sopenharmony_ci { 1595141cc406Sopenharmony_ci sleep (1); 1596141cc406Sopenharmony_ci n = read (Camera.fd, flush, 1024); 1597141cc406Sopenharmony_ci if (n > 0) 1598141cc406Sopenharmony_ci { 1599141cc406Sopenharmony_ci DBG (127, "%s: flushed %d bytes\n", "sane_cancel", n); 1600141cc406Sopenharmony_ci } 1601141cc406Sopenharmony_ci else 1602141cc406Sopenharmony_ci { 1603141cc406Sopenharmony_ci DBG (127, "%s: nothing to flush\n", "sane_cancel"); 1604141cc406Sopenharmony_ci } 1605141cc406Sopenharmony_ci } 1606141cc406Sopenharmony_ci while (n > 0); 1607141cc406Sopenharmony_ci } 1608141cc406Sopenharmony_ci 1609141cc406Sopenharmony_ci if (cinfo.output_scanline < cinfo.output_height) 1610141cc406Sopenharmony_ci { 1611141cc406Sopenharmony_ci write (Camera.fd, cancel_byte, 1); 1612141cc406Sopenharmony_ci } 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci Camera.scanning = SANE_FALSE; /* done with scan */ 1615141cc406Sopenharmony_ci } 1616141cc406Sopenharmony_ci else 1617141cc406Sopenharmony_ci DBG (4, "sane_cancel: not scanning - nothing to do\n"); 1618141cc406Sopenharmony_ci} 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ciSANE_Status 1621141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool 1622141cc406Sopenharmony_ci __sane_unused__ non_blocking) 1623141cc406Sopenharmony_ci{ 1624141cc406Sopenharmony_ci /* sane_set_io_mode() is only valid during a scan */ 1625141cc406Sopenharmony_ci if (Camera.scanning) 1626141cc406Sopenharmony_ci { 1627141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) 1628141cc406Sopenharmony_ci { 1629141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1630141cc406Sopenharmony_ci } 1631141cc406Sopenharmony_ci else 1632141cc406Sopenharmony_ci { 1633141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1634141cc406Sopenharmony_ci } 1635141cc406Sopenharmony_ci } 1636141cc406Sopenharmony_ci else 1637141cc406Sopenharmony_ci { 1638141cc406Sopenharmony_ci /* We aren't currently scanning */ 1639141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1640141cc406Sopenharmony_ci } 1641141cc406Sopenharmony_ci} 1642141cc406Sopenharmony_ci 1643141cc406Sopenharmony_ciSANE_Status 1644141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) 1645141cc406Sopenharmony_ci{ 1646141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1647141cc406Sopenharmony_ci} 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci/* 1650141cc406Sopenharmony_ci * get_pictures_info - load information about all pictures currently in 1651141cc406Sopenharmony_ci * camera: Mainly the mapping of picture number 1652141cc406Sopenharmony_ci * to picture name, and the resolution of each picture. 1653141cc406Sopenharmony_ci */ 1654141cc406Sopenharmony_cistatic PictureInfo * 1655141cc406Sopenharmony_ciget_pictures_info (void) 1656141cc406Sopenharmony_ci{ 1657141cc406Sopenharmony_ci SANE_Char f[] = "get_pictures_info"; 1658141cc406Sopenharmony_ci SANE_Char path[256]; 1659141cc406Sopenharmony_ci SANE_Int num_pictures; 1660141cc406Sopenharmony_ci SANE_Int p; 1661141cc406Sopenharmony_ci PictureInfo *pics; 1662141cc406Sopenharmony_ci 1663141cc406Sopenharmony_ci if (Camera.Pictures) 1664141cc406Sopenharmony_ci { 1665141cc406Sopenharmony_ci free (Camera.Pictures); 1666141cc406Sopenharmony_ci Camera.Pictures = NULL; 1667141cc406Sopenharmony_ci } 1668141cc406Sopenharmony_ci 1669141cc406Sopenharmony_ci strcpy (path, "\\PCCARD\\DCIM\\"); 1670141cc406Sopenharmony_ci strcat (path, (char *) folder_list[current_folder]); 1671141cc406Sopenharmony_ci strcat (path, "\\*.*"); 1672141cc406Sopenharmony_ci 1673141cc406Sopenharmony_ci num_pictures = read_dir (path); 1674141cc406Sopenharmony_ci if (num_pictures != Camera.pic_taken) 1675141cc406Sopenharmony_ci { 1676141cc406Sopenharmony_ci DBG (2, 1677141cc406Sopenharmony_ci "%s: warning: Number of pictures in directory (%d) doesn't match camera status table (%d). Using directory count\n", 1678141cc406Sopenharmony_ci f, num_pictures, Camera.pic_taken); 1679141cc406Sopenharmony_ci Camera.pic_taken = num_pictures; 1680141cc406Sopenharmony_ci image_range.max = num_pictures; 1681141cc406Sopenharmony_ci } 1682141cc406Sopenharmony_ci 1683141cc406Sopenharmony_ci if ((pics = (PictureInfo *) malloc (Camera.pic_taken * 1684141cc406Sopenharmony_ci sizeof (PictureInfo))) == NULL) 1685141cc406Sopenharmony_ci { 1686141cc406Sopenharmony_ci DBG (1, "%s: error: allocate memory for pictures array\n", f); 1687141cc406Sopenharmony_ci return NULL; 1688141cc406Sopenharmony_ci } 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci for (p = 0; p < Camera.pic_taken; p++) 1691141cc406Sopenharmony_ci { 1692141cc406Sopenharmony_ci if (get_picture_info (pics + p, p) == -1) 1693141cc406Sopenharmony_ci { 1694141cc406Sopenharmony_ci free (pics); 1695141cc406Sopenharmony_ci return NULL; 1696141cc406Sopenharmony_ci } 1697141cc406Sopenharmony_ci } 1698141cc406Sopenharmony_ci 1699141cc406Sopenharmony_ci Camera.Pictures = pics; 1700141cc406Sopenharmony_ci return pics; 1701141cc406Sopenharmony_ci} 1702141cc406Sopenharmony_ci 1703141cc406Sopenharmony_cistatic SANE_Int 1704141cc406Sopenharmony_ciget_picture_info (PictureInfo * pic, SANE_Int p) 1705141cc406Sopenharmony_ci{ 1706141cc406Sopenharmony_ci 1707141cc406Sopenharmony_ci SANE_Char f[] = "get_picture_info"; 1708141cc406Sopenharmony_ci SANE_Int n; 1709141cc406Sopenharmony_ci struct cam_dirlist *e; 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci DBG (4, "%s: info for pic #%d\n", f, p); 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci for (n = 0, e = dir_head; e && n < p; n++, e = e->next) 1714141cc406Sopenharmony_ci ; 1715141cc406Sopenharmony_ci 1716141cc406Sopenharmony_ci DBG (4, "Name is %s\n", e->name); 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci read_info (e->name); 1719141cc406Sopenharmony_ci 1720141cc406Sopenharmony_ci /* Validate picture info 1721141cc406Sopenharmony_ci * byte 0 - 1 == picture info 1722141cc406Sopenharmony_ci * byte 1 - 5 == DC240 Camera 1723141cc406Sopenharmony_ci * byte 2 - 3 == JFIF file 1724141cc406Sopenharmony_ci * byte 6 - 0 == Image is complete 1725141cc406Sopenharmony_ci */ 1726141cc406Sopenharmony_ci if (info_buf[0] != 1 || info_buf[1] != 5 || info_buf[2] != 3 1727141cc406Sopenharmony_ci || info_buf[6] != 0) 1728141cc406Sopenharmony_ci { 1729141cc406Sopenharmony_ci 1730141cc406Sopenharmony_ci DBG (1, "%s: error: Image %s does not come from a DC-240.\n", f, 1731141cc406Sopenharmony_ci e->name); 1732141cc406Sopenharmony_ci return -1; 1733141cc406Sopenharmony_ci } 1734141cc406Sopenharmony_ci 1735141cc406Sopenharmony_ci pic->low_res = info_buf[3] == 0 ? SANE_TRUE : SANE_FALSE; 1736141cc406Sopenharmony_ci 1737141cc406Sopenharmony_ci /* 1738141cc406Sopenharmony_ci * byte 12 - Year MSB 1739141cc406Sopenharmony_ci * byte 13 - Year LSB 1740141cc406Sopenharmony_ci * byte 14 - Month 1741141cc406Sopenharmony_ci * byte 15 - Day 1742141cc406Sopenharmony_ci * byte 16 - Hour 1743141cc406Sopenharmony_ci * byte 17 - Minute 1744141cc406Sopenharmony_ci * byte 18 - Second 1745141cc406Sopenharmony_ci */ 1746141cc406Sopenharmony_ci DBG (1, "Picture %d taken %02d/%02d/%02d %02d:%02d:%02d\n", 1747141cc406Sopenharmony_ci p, info_buf[14], 1748141cc406Sopenharmony_ci info_buf[15], (info_buf[12] << 8) + info_buf[13], 1749141cc406Sopenharmony_ci info_buf[16], info_buf[17], info_buf[18]); 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci return 0; 1752141cc406Sopenharmony_ci} 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci/* 1755141cc406Sopenharmony_ci * snap_pic - take a picture (and call get_pictures_info to re-create 1756141cc406Sopenharmony_ci * the directory related data structures) 1757141cc406Sopenharmony_ci */ 1758141cc406Sopenharmony_cistatic SANE_Status 1759141cc406Sopenharmony_cisnap_pic (SANE_Int fd) 1760141cc406Sopenharmony_ci{ 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci SANE_Char f[] = "snap_pic"; 1763141cc406Sopenharmony_ci 1764141cc406Sopenharmony_ci#if 0 1765141cc406Sopenharmony_ci/* Just checking... It looks like after snapping the picture, we 1766141cc406Sopenharmony_ci * get two "d1" ACK responses back, even though the documentation seems 1767141cc406Sopenharmony_ci * to say that there should only be one. I thought the first one could 1768141cc406Sopenharmony_ci * have been an unread response from an earlier command, so I 1769141cc406Sopenharmony_ci * I tried flushing any data here. Still seeing the multiple 1770141cc406Sopenharmony_ci * d1 bytes, however... 1771141cc406Sopenharmony_ci */ 1772141cc406Sopenharmony_ci { 1773141cc406Sopenharmony_ci SANE_Int n; 1774141cc406Sopenharmony_ci SANE_Char flush[10]; 1775141cc406Sopenharmony_ci n = read (Camera.fd, flush, 10); 1776141cc406Sopenharmony_ci if (n > 0) 1777141cc406Sopenharmony_ci { 1778141cc406Sopenharmony_ci DBG (127, "%s: flushed %d bytes\n", f, n); 1779141cc406Sopenharmony_ci } 1780141cc406Sopenharmony_ci else 1781141cc406Sopenharmony_ci { 1782141cc406Sopenharmony_ci DBG (127, "%s: nothing to flush\n", f); 1783141cc406Sopenharmony_ci } 1784141cc406Sopenharmony_ci } 1785141cc406Sopenharmony_ci#endif 1786141cc406Sopenharmony_ci 1787141cc406Sopenharmony_ci /* make sure camera is set to our settings state */ 1788141cc406Sopenharmony_ci if (change_res (Camera.fd, dc240_opt_lowres) == -1) 1789141cc406Sopenharmony_ci { 1790141cc406Sopenharmony_ci DBG (1, "%s: Failed to set resolution\n", f); 1791141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1792141cc406Sopenharmony_ci } 1793141cc406Sopenharmony_ci 1794141cc406Sopenharmony_ci /* take the picture */ 1795141cc406Sopenharmony_ci if (send_pck (fd, shoot_pck) == -1) 1796141cc406Sopenharmony_ci { 1797141cc406Sopenharmony_ci DBG (1, "%s: error: send_pck returned -1\n", f); 1798141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1799141cc406Sopenharmony_ci } 1800141cc406Sopenharmony_ci else 1801141cc406Sopenharmony_ci { 1802141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1803141cc406Sopenharmony_ci { 1804141cc406Sopenharmony_ci DBG (1, "%s: error: end_of_data returned -1\n", f); 1805141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1806141cc406Sopenharmony_ci } 1807141cc406Sopenharmony_ci } 1808141cc406Sopenharmony_ci Camera.pic_taken++; 1809141cc406Sopenharmony_ci Camera.pic_left--; 1810141cc406Sopenharmony_ci Camera.current_picture_number = Camera.pic_taken; 1811141cc406Sopenharmony_ci image_range.max++; 1812141cc406Sopenharmony_ci sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; 1813141cc406Sopenharmony_ci 1814141cc406Sopenharmony_ci /* add this one to the Pictures array */ 1815141cc406Sopenharmony_ci 1816141cc406Sopenharmony_ci if (get_pictures_info () == NULL) 1817141cc406Sopenharmony_ci { 1818141cc406Sopenharmony_ci DBG (1, "%s: Failed to get new picture info\n", f); 1819141cc406Sopenharmony_ci /* XXX - I guess we should try to erase the image here */ 1820141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1821141cc406Sopenharmony_ci } 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1824141cc406Sopenharmony_ci} 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci/* 1827141cc406Sopenharmony_ci * read_dir - read a list of file names from the specified directory 1828141cc406Sopenharmony_ci * and create a linked list of file name entries in 1829141cc406Sopenharmony_ci * alphabetical order. The first entry in the list will 1830141cc406Sopenharmony_ci * be "picture #1", etc. 1831141cc406Sopenharmony_ci */ 1832141cc406Sopenharmony_cistatic SANE_Int 1833141cc406Sopenharmony_ciread_dir (SANE_String dir) 1834141cc406Sopenharmony_ci{ 1835141cc406Sopenharmony_ci SANE_Int retval = 0; 1836141cc406Sopenharmony_ci SANE_Byte buf[256]; 1837141cc406Sopenharmony_ci SANE_Byte *next_buf; 1838141cc406Sopenharmony_ci SANE_Int i, entries; 1839141cc406Sopenharmony_ci SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ 1840141cc406Sopenharmony_ci SANE_Char f[] = "read_dir"; 1841141cc406Sopenharmony_ci struct cam_dirlist *e, *next; 1842141cc406Sopenharmony_ci 1843141cc406Sopenharmony_ci /* Free up current list */ 1844141cc406Sopenharmony_ci for (e = dir_head; e; e = next) 1845141cc406Sopenharmony_ci { 1846141cc406Sopenharmony_ci DBG (127, "%s: free entry %s\n", f, e->name); 1847141cc406Sopenharmony_ci next = e->next; 1848141cc406Sopenharmony_ci free (e); 1849141cc406Sopenharmony_ci } 1850141cc406Sopenharmony_ci dir_head = NULL; 1851141cc406Sopenharmony_ci 1852141cc406Sopenharmony_ci if (send_pck (Camera.fd, read_dir_pck) == -1) 1853141cc406Sopenharmony_ci { 1854141cc406Sopenharmony_ci DBG (1, "%s: error: send_pck returned -1\n", f); 1855141cc406Sopenharmony_ci return -1; 1856141cc406Sopenharmony_ci } 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci buf[0] = 0x80; 1859141cc406Sopenharmony_ci strcpy ((char *) &buf[1], dir); 1860141cc406Sopenharmony_ci for (i = 49; i <= 56; i++) 1861141cc406Sopenharmony_ci { 1862141cc406Sopenharmony_ci buf[i] = 0xff; 1863141cc406Sopenharmony_ci } 1864141cc406Sopenharmony_ci 1865141cc406Sopenharmony_ci if (send_data (buf) == -1) 1866141cc406Sopenharmony_ci { 1867141cc406Sopenharmony_ci DBG (1, "%s: error: send_data returned -1\n", f); 1868141cc406Sopenharmony_ci return -1; 1869141cc406Sopenharmony_ci } 1870141cc406Sopenharmony_ci 1871141cc406Sopenharmony_ci 1872141cc406Sopenharmony_ci if (read_data (Camera.fd, (SANE_Byte *) & dir_buf2, 256) == -1) 1873141cc406Sopenharmony_ci { 1874141cc406Sopenharmony_ci DBG (1, "%s: error: read_data returned -1\n", f); 1875141cc406Sopenharmony_ci return -1; 1876141cc406Sopenharmony_ci } 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci entries = (dir_buf2[0] << 8) + dir_buf2[1]; 1879141cc406Sopenharmony_ci DBG (127, "%s: result of dir read is %x, number of entries=%d\n", f, r, 1880141cc406Sopenharmony_ci entries); 1881141cc406Sopenharmony_ci 1882141cc406Sopenharmony_ci if (entries > 1001) 1883141cc406Sopenharmony_ci { 1884141cc406Sopenharmony_ci DBG (1, "%s: error: more than 999 pictures not supported yet\n", f); 1885141cc406Sopenharmony_ci return -1; 1886141cc406Sopenharmony_ci } 1887141cc406Sopenharmony_ci 1888141cc406Sopenharmony_ci /* Determine if it's time to read another 256 byte buffer from the camera */ 1889141cc406Sopenharmony_ci 1890141cc406Sopenharmony_ci next_buf = ((SANE_Byte *) & dir_buf2) + 256; 1891141cc406Sopenharmony_ci while (dir_buf2 + 2 + CAMDIRENTRYSIZE * entries >= (SANE_Byte *) next_buf) 1892141cc406Sopenharmony_ci { 1893141cc406Sopenharmony_ci 1894141cc406Sopenharmony_ci DBG (127, "%s: reading additional directory buffer\n", f); 1895141cc406Sopenharmony_ci if (read_data (Camera.fd, next_buf, 256) == -1) 1896141cc406Sopenharmony_ci { 1897141cc406Sopenharmony_ci DBG (1, "%s: error: read_data returned -1\n", f); 1898141cc406Sopenharmony_ci return -1; 1899141cc406Sopenharmony_ci } 1900141cc406Sopenharmony_ci next_buf += 256; 1901141cc406Sopenharmony_ci } 1902141cc406Sopenharmony_ci 1903141cc406Sopenharmony_ci for (i = 0; i < entries; i++) 1904141cc406Sopenharmony_ci 1905141cc406Sopenharmony_ci { 1906141cc406Sopenharmony_ci /* Hack: I don't know what attr is used for, so setting it 1907141cc406Sopenharmony_ci * to zero is a convenient way to put in the null terminator 1908141cc406Sopenharmony_ci */ 1909141cc406Sopenharmony_ci get_attr (i) = 0; 1910141cc406Sopenharmony_ci DBG (127, "%s: entry=%s\n", f, get_name (i)); 1911141cc406Sopenharmony_ci 1912141cc406Sopenharmony_ci if ((get_name (i))[0] == '.') 1913141cc406Sopenharmony_ci { 1914141cc406Sopenharmony_ci continue; 1915141cc406Sopenharmony_ci } 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci if (dir_insert 1918141cc406Sopenharmony_ci ((struct cam_dirent *) &dir_buf2[2 + CAMDIRENTRYSIZE * i]) != 0) 1919141cc406Sopenharmony_ci { 1920141cc406Sopenharmony_ci DBG (1, "%s: error: failed to insert dir entry\n", f); 1921141cc406Sopenharmony_ci return -1; 1922141cc406Sopenharmony_ci } 1923141cc406Sopenharmony_ci retval++; 1924141cc406Sopenharmony_ci } 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1927141cc406Sopenharmony_ci { 1928141cc406Sopenharmony_ci DBG (1, "%s: error: end_of_data returned -1\n", f); 1929141cc406Sopenharmony_ci return -1; 1930141cc406Sopenharmony_ci } 1931141cc406Sopenharmony_ci 1932141cc406Sopenharmony_ci return retval; 1933141cc406Sopenharmony_ci} 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci/* 1936141cc406Sopenharmony_ci * read_info - read the info block from camera for the specified file 1937141cc406Sopenharmony_ci */ 1938141cc406Sopenharmony_cistatic SANE_Int 1939141cc406Sopenharmony_ciread_info (SANE_String fname) 1940141cc406Sopenharmony_ci{ 1941141cc406Sopenharmony_ci SANE_Byte buf[256]; 1942141cc406Sopenharmony_ci SANE_Int i; 1943141cc406Sopenharmony_ci SANE_Char f[] = "read_info"; 1944141cc406Sopenharmony_ci SANE_Char path[256]; 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci strcpy (path, "\\PCCARD\\DCIM\\"); 1947141cc406Sopenharmony_ci strcat (path, (char *) folder_list[current_folder]); 1948141cc406Sopenharmony_ci strcat (path, "\\"); 1949141cc406Sopenharmony_ci strcat (path, fname); 1950141cc406Sopenharmony_ci path[strlen (path) - 3] = '\0'; 1951141cc406Sopenharmony_ci strcat (path, ".JPG"); 1952141cc406Sopenharmony_ci 1953141cc406Sopenharmony_ci if (send_pck (Camera.fd, pic_info_pck) == -1) 1954141cc406Sopenharmony_ci { 1955141cc406Sopenharmony_ci DBG (1, "%s: error: send_pck returned -1\n", f); 1956141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1957141cc406Sopenharmony_ci } 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci buf[0] = 0x80; 1960141cc406Sopenharmony_ci strcpy ((char *) &buf[1], path); 1961141cc406Sopenharmony_ci for (i = 49; i <= 56; i++) 1962141cc406Sopenharmony_ci { 1963141cc406Sopenharmony_ci buf[i] = 0xff; 1964141cc406Sopenharmony_ci } 1965141cc406Sopenharmony_ci 1966141cc406Sopenharmony_ci if (send_data (buf) == -1) 1967141cc406Sopenharmony_ci { 1968141cc406Sopenharmony_ci DBG (1, "%s: error: send_data returned -1\n", f); 1969141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1970141cc406Sopenharmony_ci } 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_ci if (read_data (Camera.fd, info_buf, 256) != 0) 1973141cc406Sopenharmony_ci { 1974141cc406Sopenharmony_ci DBG (1, "%s: error: Failed in read_data\n", f); 1975141cc406Sopenharmony_ci return -1; 1976141cc406Sopenharmony_ci } 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci DBG (9, "%s: data type=%d, cam type=%d, file type=%d\n", f, 1979141cc406Sopenharmony_ci info_buf[0], info_buf[1], info_buf[2]); 1980141cc406Sopenharmony_ci 1981141cc406Sopenharmony_ci if (end_of_data (Camera.fd) == -1) 1982141cc406Sopenharmony_ci { 1983141cc406Sopenharmony_ci DBG (1, "%s: error: end_of_data returned -1\n", f); 1984141cc406Sopenharmony_ci return -1; 1985141cc406Sopenharmony_ci } 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci return 0; 1988141cc406Sopenharmony_ci} 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_ci 1991141cc406Sopenharmony_ci/* 1992141cc406Sopenharmony_ci * send_data - Send a data block - assumes all data blocks to camera 1993141cc406Sopenharmony_ci * are 60 bytes long 1994141cc406Sopenharmony_ci */ 1995141cc406Sopenharmony_ci 1996141cc406Sopenharmony_cistatic SANE_Int 1997141cc406Sopenharmony_cisend_data (SANE_Byte * buf) 1998141cc406Sopenharmony_ci{ 1999141cc406Sopenharmony_ci SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ 2000141cc406Sopenharmony_ci SANE_Int i, n; 2001141cc406Sopenharmony_ci SANE_Byte csum; 2002141cc406Sopenharmony_ci SANE_Char f[] = "send_data"; 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci for (i = 1, csum = 0; i < 59; i++) 2005141cc406Sopenharmony_ci { 2006141cc406Sopenharmony_ci csum ^= buf[i]; 2007141cc406Sopenharmony_ci } 2008141cc406Sopenharmony_ci buf[59] = csum; 2009141cc406Sopenharmony_ci DBG (127, "%s: about to send data block\n", f); 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci /* keep trying if camera says it's busy */ 2012141cc406Sopenharmony_ci while (r == 0xf0) 2013141cc406Sopenharmony_ci { 2014141cc406Sopenharmony_ci if (write (Camera.fd, (char *) buf, 60) != 60) 2015141cc406Sopenharmony_ci { 2016141cc406Sopenharmony_ci DBG (1, "%s: error: write returned -1\n", f); 2017141cc406Sopenharmony_ci return -1; 2018141cc406Sopenharmony_ci } 2019141cc406Sopenharmony_ci 2020141cc406Sopenharmony_ci /* need to wait before we read command result */ 2021141cc406Sopenharmony_ci#ifdef HAVE_USLEEP 2022141cc406Sopenharmony_ci usleep (cmdrespause); 2023141cc406Sopenharmony_ci#else 2024141cc406Sopenharmony_ci sleep (1); 2025141cc406Sopenharmony_ci#endif 2026141cc406Sopenharmony_ci 2027141cc406Sopenharmony_ci if ((n = read (Camera.fd, (char *) &r, 1)) != 1) 2028141cc406Sopenharmony_ci { 2029141cc406Sopenharmony_ci DBG (1, "%s: error: read returned -1\n", f); 2030141cc406Sopenharmony_ci return -1; 2031141cc406Sopenharmony_ci } 2032141cc406Sopenharmony_ci } 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci if (r != 0xd2) 2035141cc406Sopenharmony_ci { 2036141cc406Sopenharmony_ci DBG (1, "%s: error: bad response to send_data (%d)\n", f, r); 2037141cc406Sopenharmony_ci return -1; 2038141cc406Sopenharmony_ci } 2039141cc406Sopenharmony_ci 2040141cc406Sopenharmony_ci return 0; 2041141cc406Sopenharmony_ci} 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ci/* 2044141cc406Sopenharmony_ci * dir_insert - Add (in alphabetical order) a directory entry to the 2045141cc406Sopenharmony_ci * current list of entries. 2046141cc406Sopenharmony_ci */ 2047141cc406Sopenharmony_cistatic SANE_Int 2048141cc406Sopenharmony_cidir_insert (struct cam_dirent *entry) 2049141cc406Sopenharmony_ci{ 2050141cc406Sopenharmony_ci struct cam_dirlist *cur, *e; 2051141cc406Sopenharmony_ci 2052141cc406Sopenharmony_ci cur = (struct cam_dirlist *) malloc (sizeof (struct cam_dirlist)); 2053141cc406Sopenharmony_ci if (cur == NULL) 2054141cc406Sopenharmony_ci { 2055141cc406Sopenharmony_ci DBG (1, "dir_insert: error: could not malloc entry\n"); 2056141cc406Sopenharmony_ci return -1; 2057141cc406Sopenharmony_ci } 2058141cc406Sopenharmony_ci 2059141cc406Sopenharmony_ci strcpy (cur->name, entry->name); 2060141cc406Sopenharmony_ci DBG (127, "dir_insert: name is %s\n", cur->name); 2061141cc406Sopenharmony_ci 2062141cc406Sopenharmony_ci cur->next = NULL; 2063141cc406Sopenharmony_ci 2064141cc406Sopenharmony_ci if (dir_head == NULL) 2065141cc406Sopenharmony_ci { 2066141cc406Sopenharmony_ci dir_head = cur; 2067141cc406Sopenharmony_ci } 2068141cc406Sopenharmony_ci else if (strcmp (cur->name, dir_head->name) < 0) 2069141cc406Sopenharmony_ci { 2070141cc406Sopenharmony_ci cur->next = dir_head; 2071141cc406Sopenharmony_ci dir_head = cur; 2072141cc406Sopenharmony_ci return 0; 2073141cc406Sopenharmony_ci } 2074141cc406Sopenharmony_ci else 2075141cc406Sopenharmony_ci { 2076141cc406Sopenharmony_ci for (e = dir_head; e->next; e = e->next) 2077141cc406Sopenharmony_ci { 2078141cc406Sopenharmony_ci if (strcmp (e->next->name, cur->name) > 0) 2079141cc406Sopenharmony_ci { 2080141cc406Sopenharmony_ci cur->next = e->next; 2081141cc406Sopenharmony_ci e->next = cur; 2082141cc406Sopenharmony_ci return 0; 2083141cc406Sopenharmony_ci } 2084141cc406Sopenharmony_ci } 2085141cc406Sopenharmony_ci e->next = cur; 2086141cc406Sopenharmony_ci } 2087141cc406Sopenharmony_ci return 0; 2088141cc406Sopenharmony_ci} 2089141cc406Sopenharmony_ci 2090141cc406Sopenharmony_ci/* 2091141cc406Sopenharmony_ci * dir_delete - Delete a directory entry from the linked list of file 2092141cc406Sopenharmony_ci * names 2093141cc406Sopenharmony_ci */ 2094141cc406Sopenharmony_cistatic SANE_Int 2095141cc406Sopenharmony_cidir_delete (SANE_String fname) 2096141cc406Sopenharmony_ci{ 2097141cc406Sopenharmony_ci struct cam_dirlist *cur, *e; 2098141cc406Sopenharmony_ci 2099141cc406Sopenharmony_ci DBG (127, "dir_delete: %s\n", fname); 2100141cc406Sopenharmony_ci 2101141cc406Sopenharmony_ci if (strcmp (fname, dir_head->name) == 0) 2102141cc406Sopenharmony_ci { 2103141cc406Sopenharmony_ci cur = dir_head; 2104141cc406Sopenharmony_ci dir_head = dir_head->next; 2105141cc406Sopenharmony_ci free (cur); 2106141cc406Sopenharmony_ci return 0; 2107141cc406Sopenharmony_ci } 2108141cc406Sopenharmony_ci 2109141cc406Sopenharmony_ci for (e = dir_head; e->next; e = e->next) 2110141cc406Sopenharmony_ci { 2111141cc406Sopenharmony_ci if (strcmp (fname, e->next->name) == 0) 2112141cc406Sopenharmony_ci { 2113141cc406Sopenharmony_ci cur = e->next; 2114141cc406Sopenharmony_ci e->next = e->next->next; 2115141cc406Sopenharmony_ci free (cur); 2116141cc406Sopenharmony_ci return (0); 2117141cc406Sopenharmony_ci } 2118141cc406Sopenharmony_ci } 2119141cc406Sopenharmony_ci DBG (1, "dir_delete: Couldn't find entry %s in dir list\n", fname); 2120141cc406Sopenharmony_ci return -1; 2121141cc406Sopenharmony_ci} 2122141cc406Sopenharmony_ci 2123141cc406Sopenharmony_ci/* 2124141cc406Sopenharmony_ci * set_res - set picture size depending on resolution settings 2125141cc406Sopenharmony_ci */ 2126141cc406Sopenharmony_cistatic void 2127141cc406Sopenharmony_ciset_res (SANE_Int lowres) 2128141cc406Sopenharmony_ci{ 2129141cc406Sopenharmony_ci if (dc240_opt_thumbnails) 2130141cc406Sopenharmony_ci { 2131141cc406Sopenharmony_ci parms.bytes_per_line = 160 * 3; 2132141cc406Sopenharmony_ci parms.pixels_per_line = 160; 2133141cc406Sopenharmony_ci parms.lines = 120; 2134141cc406Sopenharmony_ci } 2135141cc406Sopenharmony_ci else if (lowres) 2136141cc406Sopenharmony_ci { 2137141cc406Sopenharmony_ci parms.bytes_per_line = LOWRES_WIDTH * 3; 2138141cc406Sopenharmony_ci parms.pixels_per_line = LOWRES_WIDTH; 2139141cc406Sopenharmony_ci parms.lines = LOWRES_HEIGHT; 2140141cc406Sopenharmony_ci } 2141141cc406Sopenharmony_ci else 2142141cc406Sopenharmony_ci { 2143141cc406Sopenharmony_ci parms.bytes_per_line = HIGHRES_WIDTH * 3; 2144141cc406Sopenharmony_ci parms.pixels_per_line = HIGHRES_WIDTH; 2145141cc406Sopenharmony_ci parms.lines = HIGHRES_HEIGHT; 2146141cc406Sopenharmony_ci } 2147141cc406Sopenharmony_ci} 2148