1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 1998 David F. Skoll 3141cc406Sopenharmony_ci Heavily based on "hp.c" driver for HP Scanners, by 4141cc406Sopenharmony_ci David Mosberger-Tang. 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci This file implements a SANE backend for the Polaroid Digital 43141cc406Sopenharmony_ci Microscope Camera. */ 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci#include "../include/sane/config.h" 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#include <limits.h> 48141cc406Sopenharmony_ci#include <stdlib.h> 49141cc406Sopenharmony_ci#include <stdarg.h> 50141cc406Sopenharmony_ci#include <string.h> 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#include "../include/_stdint.h" 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci#include "../include/sane/sane.h" 55141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 56141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#define BACKEND_NAME dmc 59141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#ifndef PATH_MAX 62141cc406Sopenharmony_ci# define PATH_MAX 1024 63141cc406Sopenharmony_ci#endif 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 66141cc406Sopenharmony_ci#define DMC_CONFIG_FILE "dmc.conf" 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci#include "dmc.h" 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci/* A linked-list of attached devices and handles */ 71141cc406Sopenharmony_cistatic DMC_Device *FirstDevice = NULL; 72141cc406Sopenharmony_cistatic DMC_Camera *FirstHandle = NULL; 73141cc406Sopenharmony_cistatic int NumDevices = 0; 74141cc406Sopenharmony_cistatic SANE_Device const **devlist = NULL; 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_cistatic SANE_String_Const ValidModes[] = { "Full frame", "Viewfinder", 77141cc406Sopenharmony_ci "Raw", "Thumbnail", 78141cc406Sopenharmony_ci "Super-Resolution", 79141cc406Sopenharmony_ci NULL }; 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_cistatic SANE_String_Const ValidBalances[] = { "Daylight", "Incandescent", 82141cc406Sopenharmony_ci "Fluorescent", NULL }; 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_cistatic SANE_Word ValidASAs[] = { 3, 25, 50, 100 }; 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci/* Convert between 32-us ticks and milliseconds */ 87141cc406Sopenharmony_ci#define MS_TO_TICKS(x) (((x) * 1000 + 16) / 32) 88141cc406Sopenharmony_ci#define TICKS_TO_MS(x) (((x) * 32) / 1000) 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci/* Macros for stepping along the raw lines for super-resolution mode 91141cc406Sopenharmony_ci They are very ugly because they handle boundary conditions at 92141cc406Sopenharmony_ci the edges of the image. Yuck... */ 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci#define PREV_RED(i) (((i)/3)*3) 95141cc406Sopenharmony_ci#define NEXT_RED(i) (((i) >= BYTES_PER_RAW_LINE-3) ? BYTES_PER_RAW_LINE-3 : \ 96141cc406Sopenharmony_ci PREV_RED(i)+3) 97141cc406Sopenharmony_ci#define PREV_GREEN(i) ((i)<1 ? 1 : PREV_RED((i)-1)+1) 98141cc406Sopenharmony_ci#define NEXT_GREEN(i) ((i)<1 ? 1 : ((i) >= BYTES_PER_RAW_LINE-2) ? \ 99141cc406Sopenharmony_ci BYTES_PER_RAW_LINE-2 : PREV_GREEN(i)+3) 100141cc406Sopenharmony_ci#define PREV_BLUE(i) ((i)<2 ? 2 : PREV_RED((i)-2)+2) 101141cc406Sopenharmony_ci#define NEXT_BLUE(i) ((i)<2 ? 2 : ((i) >= BYTES_PER_RAW_LINE-1) ? \ 102141cc406Sopenharmony_ci BYTES_PER_RAW_LINE-1 : PREV_BLUE(i)+3) 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci#define ADVANCE_COEFF(i) (((i)==1) ? 3 : (i)-1); 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/********************************************************************** 107141cc406Sopenharmony_ci//%FUNCTION: DMCRead 108141cc406Sopenharmony_ci//%ARGUMENTS: 109141cc406Sopenharmony_ci// fd -- file descriptor 110141cc406Sopenharmony_ci// typecode -- data type code 111141cc406Sopenharmony_ci// qualifier -- data type qualifier 112141cc406Sopenharmony_ci// maxlen -- transfer length 113141cc406Sopenharmony_ci// buf -- buffer to store data in 114141cc406Sopenharmony_ci// len -- set to actual length of data 115141cc406Sopenharmony_ci//%RETURNS: 116141cc406Sopenharmony_ci// A SANE status code 117141cc406Sopenharmony_ci//%DESCRIPTION: 118141cc406Sopenharmony_ci// Reads the particular data selected by typecode and qualifier 119141cc406Sopenharmony_ci// *********************************************************************/ 120141cc406Sopenharmony_cistatic SANE_Status 121141cc406Sopenharmony_ciDMCRead(int fd, unsigned int typecode, unsigned int qualifier, 122141cc406Sopenharmony_ci SANE_Byte *buf, size_t maxlen, size_t *len) 123141cc406Sopenharmony_ci{ 124141cc406Sopenharmony_ci uint8_t readCmd[10]; 125141cc406Sopenharmony_ci SANE_Status status; 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci readCmd[0] = 0x28; 128141cc406Sopenharmony_ci readCmd[1] = 0; 129141cc406Sopenharmony_ci readCmd[2] = typecode; 130141cc406Sopenharmony_ci readCmd[3] = 0; 131141cc406Sopenharmony_ci readCmd[4] = (qualifier >> 8) & 0xFF; 132141cc406Sopenharmony_ci readCmd[5] = qualifier & 0xFF; 133141cc406Sopenharmony_ci readCmd[6] = (maxlen >> 16) & 0xFF; 134141cc406Sopenharmony_ci readCmd[7] = (maxlen >> 8) & 0xFF; 135141cc406Sopenharmony_ci readCmd[8] = maxlen & 0xFF; 136141cc406Sopenharmony_ci readCmd[9] = 0; 137141cc406Sopenharmony_ci DBG(3, "DMCRead: typecode=%x, qualifier=%x, maxlen=%lu\n", 138141cc406Sopenharmony_ci typecode, qualifier, (u_long) maxlen); 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ci *len = maxlen; 141141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, readCmd, sizeof(readCmd), buf, len); 142141cc406Sopenharmony_ci DBG(3, "DMCRead: Read %lu bytes\n", (u_long) *len); 143141cc406Sopenharmony_ci return status; 144141cc406Sopenharmony_ci} 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci/********************************************************************** 147141cc406Sopenharmony_ci//%FUNCTION: DMCWrite 148141cc406Sopenharmony_ci//%ARGUMENTS: 149141cc406Sopenharmony_ci// fd -- file descriptor 150141cc406Sopenharmony_ci// typecode -- data type code 151141cc406Sopenharmony_ci// qualifier -- data type qualifier 152141cc406Sopenharmony_ci// maxlen -- transfer length 153141cc406Sopenharmony_ci// buf -- buffer to store data in 154141cc406Sopenharmony_ci//%RETURNS: 155141cc406Sopenharmony_ci// A SANE status code 156141cc406Sopenharmony_ci//%DESCRIPTION: 157141cc406Sopenharmony_ci// Writes the particular data selected by typecode and qualifier 158141cc406Sopenharmony_ci// *********************************************************************/ 159141cc406Sopenharmony_cistatic SANE_Status 160141cc406Sopenharmony_ciDMCWrite(int fd, unsigned int typecode, unsigned int qualifier, 161141cc406Sopenharmony_ci SANE_Byte *buf, size_t maxlen) 162141cc406Sopenharmony_ci{ 163141cc406Sopenharmony_ci uint8_t *writeCmd; 164141cc406Sopenharmony_ci SANE_Status status; 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_ci writeCmd = malloc(maxlen + 10); 167141cc406Sopenharmony_ci if (!writeCmd) return SANE_STATUS_NO_MEM; 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci writeCmd[0] = 0x2A; 170141cc406Sopenharmony_ci writeCmd[1] = 0; 171141cc406Sopenharmony_ci writeCmd[2] = typecode; 172141cc406Sopenharmony_ci writeCmd[3] = 0; 173141cc406Sopenharmony_ci writeCmd[4] = (qualifier >> 8) & 0xFF; 174141cc406Sopenharmony_ci writeCmd[5] = qualifier & 0xFF; 175141cc406Sopenharmony_ci writeCmd[6] = (maxlen >> 16) & 0xFF; 176141cc406Sopenharmony_ci writeCmd[7] = (maxlen >> 8) & 0xFF; 177141cc406Sopenharmony_ci writeCmd[8] = maxlen & 0xFF; 178141cc406Sopenharmony_ci writeCmd[9] = 0; 179141cc406Sopenharmony_ci memcpy(writeCmd+10, buf, maxlen); 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci DBG(3, "DMCWrite: typecode=%x, qualifier=%x, maxlen=%lu\n", 182141cc406Sopenharmony_ci typecode, qualifier, (u_long) maxlen); 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, writeCmd, 10+maxlen, NULL, NULL); 185141cc406Sopenharmony_ci free(writeCmd); 186141cc406Sopenharmony_ci return status; 187141cc406Sopenharmony_ci} 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_ci/********************************************************************** 190141cc406Sopenharmony_ci//%FUNCTION: DMCAttach 191141cc406Sopenharmony_ci//%ARGUMENTS: 192141cc406Sopenharmony_ci// devname -- name of device file to open 193141cc406Sopenharmony_ci// devp -- a DMC_Device structure which we fill in if it's not NULL. 194141cc406Sopenharmony_ci//%RETURNS: 195141cc406Sopenharmony_ci// SANE_STATUS_GOOD -- We have a Polaroid DMC attached and all looks good. 196141cc406Sopenharmony_ci// SANE_STATUS_INVAL -- There's a problem. 197141cc406Sopenharmony_ci//%DESCRIPTION: 198141cc406Sopenharmony_ci// Verifies that a Polaroid DMC is attached. Sets up device options in 199141cc406Sopenharmony_ci// DMC_Device structure. 200141cc406Sopenharmony_ci// *********************************************************************/ 201141cc406Sopenharmony_ci#define INQ_LEN 255 202141cc406Sopenharmony_cistatic SANE_Status 203141cc406Sopenharmony_ciDMCAttach(char const *devname, DMC_Device **devp) 204141cc406Sopenharmony_ci{ 205141cc406Sopenharmony_ci DMC_Device *dev; 206141cc406Sopenharmony_ci SANE_Status status; 207141cc406Sopenharmony_ci int fd; 208141cc406Sopenharmony_ci size_t size; 209141cc406Sopenharmony_ci char result[INQ_LEN]; 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci uint8_t exposureCalculationResults[16]; 212141cc406Sopenharmony_ci uint8_t userInterfaceSettings[16]; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci static uint8_t const inquiry[] = 215141cc406Sopenharmony_ci { 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci static uint8_t const test_unit_ready[] = 218141cc406Sopenharmony_ci { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci static uint8_t const no_viewfinder[] = 221141cc406Sopenharmony_ci { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ci /* If we're already attached, do nothing */ 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci for (dev = FirstDevice; dev; dev = dev->next) { 226141cc406Sopenharmony_ci if (!strcmp(dev->sane.name, devname)) { 227141cc406Sopenharmony_ci if (devp) *devp = dev; 228141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci } 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci DBG(3, "DMCAttach: opening `%s'\n", devname); 233141cc406Sopenharmony_ci status = sanei_scsi_open(devname, &fd, 0, 0); 234141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 235141cc406Sopenharmony_ci DBG(1, "DMCAttach: open failed (%s)\n", sane_strstatus(status)); 236141cc406Sopenharmony_ci return status; 237141cc406Sopenharmony_ci } 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci DBG(3, "DMCAttach: sending INQUIRY\n"); 240141cc406Sopenharmony_ci size = sizeof(result); 241141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, inquiry, sizeof(inquiry), result, &size); 242141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size < 32) { 243141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) status = SANE_STATUS_INVAL; 244141cc406Sopenharmony_ci DBG(1, "DMCAttach: inquiry failed (%s)\n", sane_strstatus(status)); 245141cc406Sopenharmony_ci sanei_scsi_close(fd); 246141cc406Sopenharmony_ci return status; 247141cc406Sopenharmony_ci } 248141cc406Sopenharmony_ci 249141cc406Sopenharmony_ci /* Verify that we have a Polaroid DMC */ 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci if (result[0] != 6 || 252141cc406Sopenharmony_ci strncmp(result+8, "POLAROID", 8) || 253141cc406Sopenharmony_ci strncmp(result+16, "DMC ", 8)) { 254141cc406Sopenharmony_ci sanei_scsi_close(fd); 255141cc406Sopenharmony_ci DBG(1, "DMCAttach: Device does not look like a Polaroid DMC\n"); 256141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 257141cc406Sopenharmony_ci } 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci DBG(3, "DMCAttach: sending TEST_UNIT_READY\n"); 260141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, test_unit_ready, sizeof(test_unit_ready), 261141cc406Sopenharmony_ci NULL, NULL); 262141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 263141cc406Sopenharmony_ci DBG(1, "DMCAttach: test unit ready failed (%s)\n", 264141cc406Sopenharmony_ci sane_strstatus(status)); 265141cc406Sopenharmony_ci sanei_scsi_close(fd); 266141cc406Sopenharmony_ci return status; 267141cc406Sopenharmony_ci } 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci /* Read current ASA and shutter speed settings */ 270141cc406Sopenharmony_ci status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, 271141cc406Sopenharmony_ci sizeof(exposureCalculationResults), &size); 272141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || 273141cc406Sopenharmony_ci size < sizeof(exposureCalculationResults)) { 274141cc406Sopenharmony_ci DBG(1, "DMCAttach: Couldn't read exposure calculation results (%s)\n", 275141cc406Sopenharmony_ci sane_strstatus(status)); 276141cc406Sopenharmony_ci sanei_scsi_close(fd); 277141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR; 278141cc406Sopenharmony_ci return status; 279141cc406Sopenharmony_ci } 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci /* Read current white balance settings */ 282141cc406Sopenharmony_ci status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings, 283141cc406Sopenharmony_ci sizeof(userInterfaceSettings), &size); 284141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || 285141cc406Sopenharmony_ci size < sizeof(userInterfaceSettings)) { 286141cc406Sopenharmony_ci DBG(1, "DMCAttach: Couldn't read user interface settings (%s)\n", 287141cc406Sopenharmony_ci sane_strstatus(status)); 288141cc406Sopenharmony_ci sanei_scsi_close(fd); 289141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR; 290141cc406Sopenharmony_ci return status; 291141cc406Sopenharmony_ci } 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci /* Shut off viewfinder mode */ 294141cc406Sopenharmony_ci status = sanei_scsi_cmd(fd, no_viewfinder, sizeof(no_viewfinder), 295141cc406Sopenharmony_ci NULL, NULL); 296141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 297141cc406Sopenharmony_ci sanei_scsi_close(fd); 298141cc406Sopenharmony_ci return status; 299141cc406Sopenharmony_ci } 300141cc406Sopenharmony_ci sanei_scsi_close(fd); 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci DBG(3, "DMCAttach: Looks like we have a Polaroid DMC\n"); 303141cc406Sopenharmony_ci 304141cc406Sopenharmony_ci dev = malloc(sizeof(*dev)); 305141cc406Sopenharmony_ci if (!dev) return SANE_STATUS_NO_MEM; 306141cc406Sopenharmony_ci memset(dev, 0, sizeof(*dev)); 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci dev->sane.name = strdup(devname); 309141cc406Sopenharmony_ci dev->sane.vendor = "Polaroid"; 310141cc406Sopenharmony_ci dev->sane.model = "DMC"; 311141cc406Sopenharmony_ci dev->sane.type = "still camera"; 312141cc406Sopenharmony_ci dev->next = FirstDevice; 313141cc406Sopenharmony_ci dev->whiteBalance = userInterfaceSettings[5]; 314141cc406Sopenharmony_ci if (dev->whiteBalance > WHITE_BALANCE_FLUORESCENT) { 315141cc406Sopenharmony_ci dev->whiteBalance = WHITE_BALANCE_FLUORESCENT; 316141cc406Sopenharmony_ci } 317141cc406Sopenharmony_ci 318141cc406Sopenharmony_ci /* Bright Eyes documentation gives these as shutter speed ranges (ms) */ 319141cc406Sopenharmony_ci /* dev->shutterSpeedRange.min = 8; */ 320141cc406Sopenharmony_ci /* dev->shutterSpeedRange.max = 320; */ 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci /* User's manual says these are shutter speed ranges (ms) */ 323141cc406Sopenharmony_ci dev->shutterSpeedRange.min = 8; 324141cc406Sopenharmony_ci dev->shutterSpeedRange.max = 1000; 325141cc406Sopenharmony_ci dev->shutterSpeedRange.quant = 2; 326141cc406Sopenharmony_ci dev->shutterSpeed = 327141cc406Sopenharmony_ci (exposureCalculationResults[10] << 8) + 328141cc406Sopenharmony_ci exposureCalculationResults[11]; 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci /* Convert from ticks to ms */ 331141cc406Sopenharmony_ci dev->shutterSpeed = TICKS_TO_MS(dev->shutterSpeed); 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci dev->asa = exposureCalculationResults[13]; 334141cc406Sopenharmony_ci if (dev->asa > ASA_100) dev->asa = ASA_100; 335141cc406Sopenharmony_ci dev->asa = ValidASAs[dev->asa + 1]; 336141cc406Sopenharmony_ci FirstDevice = dev; 337141cc406Sopenharmony_ci NumDevices++; 338141cc406Sopenharmony_ci if (devp) *devp = dev; 339141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 340141cc406Sopenharmony_ci} 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci/********************************************************************** 343141cc406Sopenharmony_ci//%FUNCTION: ValidateHandle 344141cc406Sopenharmony_ci//%ARGUMENTS: 345141cc406Sopenharmony_ci// handle -- a handle for an opened camera 346141cc406Sopenharmony_ci//%RETURNS: 347141cc406Sopenharmony_ci// A validated pointer to the camera or NULL if handle is not valid. 348141cc406Sopenharmony_ci// *********************************************************************/ 349141cc406Sopenharmony_cistatic DMC_Camera * 350141cc406Sopenharmony_ciValidateHandle(SANE_Handle handle) 351141cc406Sopenharmony_ci{ 352141cc406Sopenharmony_ci DMC_Camera *c; 353141cc406Sopenharmony_ci for (c = FirstHandle; c; c = c->next) { 354141cc406Sopenharmony_ci if (c == handle) return c; 355141cc406Sopenharmony_ci } 356141cc406Sopenharmony_ci DBG(1, "ValidateHandle: invalid handle %p\n", handle); 357141cc406Sopenharmony_ci return NULL; 358141cc406Sopenharmony_ci} 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci/********************************************************************** 361141cc406Sopenharmony_ci//%FUNCTION: DMCInitOptions 362141cc406Sopenharmony_ci//%ARGUMENTS: 363141cc406Sopenharmony_ci// c -- a DMC camera device 364141cc406Sopenharmony_ci//%RETURNS: 365141cc406Sopenharmony_ci// SANE_STATUS_GOOD -- OK 366141cc406Sopenharmony_ci// SANE_STATUS_INVAL -- There's a problem. 367141cc406Sopenharmony_ci//%DESCRIPTION: 368141cc406Sopenharmony_ci// Initializes the options in the DMC_Camera structure 369141cc406Sopenharmony_ci// *********************************************************************/ 370141cc406Sopenharmony_cistatic SANE_Status 371141cc406Sopenharmony_ciDMCInitOptions(DMC_Camera *c) 372141cc406Sopenharmony_ci{ 373141cc406Sopenharmony_ci int i; 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci /* Image is initially 801x600 */ 376141cc406Sopenharmony_ci c->tl_x_range.min = 0; 377141cc406Sopenharmony_ci c->tl_x_range.max = c->tl_x_range.min; 378141cc406Sopenharmony_ci c->tl_x_range.quant = 1; 379141cc406Sopenharmony_ci c->tl_y_range.min = 0; 380141cc406Sopenharmony_ci c->tl_y_range.max = c->tl_y_range.min; 381141cc406Sopenharmony_ci c->tl_y_range.quant = 1; 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci c->br_x_range.min = 800; 384141cc406Sopenharmony_ci c->br_x_range.max = c->br_x_range.min; 385141cc406Sopenharmony_ci c->br_x_range.quant = 1; 386141cc406Sopenharmony_ci c->br_y_range.min = 599; 387141cc406Sopenharmony_ci c->br_y_range.max = c->br_y_range.min; 388141cc406Sopenharmony_ci c->br_y_range.quant = 1; 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci memset(c->opt, 0, sizeof(c->opt)); 391141cc406Sopenharmony_ci memset(c->val, 0, sizeof(c->val)); 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci for (i=0; i<NUM_OPTIONS; i++) { 394141cc406Sopenharmony_ci c->opt[i].type = SANE_TYPE_INT; 395141cc406Sopenharmony_ci c->opt[i].size = sizeof(SANE_Word); 396141cc406Sopenharmony_ci c->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 397141cc406Sopenharmony_ci c->opt[i].unit = SANE_UNIT_NONE; 398141cc406Sopenharmony_ci } 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 401141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 402141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 403141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 404141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 405141cc406Sopenharmony_ci c->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 406141cc406Sopenharmony_ci c->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 409141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].name = ""; 410141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 411141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].desc = ""; 412141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 413141cc406Sopenharmony_ci c->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* top-left x */ 416141cc406Sopenharmony_ci c->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 417141cc406Sopenharmony_ci c->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 418141cc406Sopenharmony_ci c->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 419141cc406Sopenharmony_ci c->opt[OPT_TL_X].type = SANE_TYPE_INT; 420141cc406Sopenharmony_ci c->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; 421141cc406Sopenharmony_ci c->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 422141cc406Sopenharmony_ci c->opt[OPT_TL_X].constraint.range = &c->tl_x_range; 423141cc406Sopenharmony_ci c->val[OPT_TL_X].w = c->tl_x_range.min; 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci /* top-left y */ 426141cc406Sopenharmony_ci c->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 427141cc406Sopenharmony_ci c->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 428141cc406Sopenharmony_ci c->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 429141cc406Sopenharmony_ci c->opt[OPT_TL_Y].type = SANE_TYPE_INT; 430141cc406Sopenharmony_ci c->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; 431141cc406Sopenharmony_ci c->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 432141cc406Sopenharmony_ci c->opt[OPT_TL_Y].constraint.range = &c->tl_y_range; 433141cc406Sopenharmony_ci c->val[OPT_TL_Y].w = c->tl_y_range.min; 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci /* bottom-right x */ 436141cc406Sopenharmony_ci c->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 437141cc406Sopenharmony_ci c->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 438141cc406Sopenharmony_ci c->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 439141cc406Sopenharmony_ci c->opt[OPT_BR_X].type = SANE_TYPE_INT; 440141cc406Sopenharmony_ci c->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; 441141cc406Sopenharmony_ci c->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 442141cc406Sopenharmony_ci c->opt[OPT_BR_X].constraint.range = &c->br_x_range; 443141cc406Sopenharmony_ci c->val[OPT_BR_X].w = c->br_x_range.min; 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci /* bottom-right y */ 446141cc406Sopenharmony_ci c->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 447141cc406Sopenharmony_ci c->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 448141cc406Sopenharmony_ci c->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 449141cc406Sopenharmony_ci c->opt[OPT_BR_Y].type = SANE_TYPE_INT; 450141cc406Sopenharmony_ci c->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; 451141cc406Sopenharmony_ci c->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 452141cc406Sopenharmony_ci c->opt[OPT_BR_Y].constraint.range = &c->br_y_range; 453141cc406Sopenharmony_ci c->val[OPT_BR_Y].w = c->br_y_range.min; 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 456141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].name = ""; 457141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].title = "Imaging Mode"; 458141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].desc = ""; 459141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].cap = SANE_CAP_ADVANCED; 460141cc406Sopenharmony_ci c->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].name = "imagemode"; 463141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].title = "Image Mode"; 464141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].desc = "Selects image mode: 800x600 full frame, 270x201 viewfinder mode, 1599x600 \"raw\" image, 80x60 thumbnail image or 1599x1200 \"super-resolution\" image"; 465141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].type = SANE_TYPE_STRING; 466141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 467141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].constraint.string_list = ValidModes; 468141cc406Sopenharmony_ci c->opt[OPT_IMAGE_MODE].size = 16; 469141cc406Sopenharmony_ci c->val[OPT_IMAGE_MODE].s = "Full frame"; 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci c->opt[OPT_ASA].name = "asa"; 472141cc406Sopenharmony_ci c->opt[OPT_ASA].title = "ASA Setting"; 473141cc406Sopenharmony_ci c->opt[OPT_ASA].desc = "Equivalent ASA setting"; 474141cc406Sopenharmony_ci c->opt[OPT_ASA].constraint_type = SANE_CONSTRAINT_WORD_LIST; 475141cc406Sopenharmony_ci c->opt[OPT_ASA].constraint.word_list = ValidASAs; 476141cc406Sopenharmony_ci c->val[OPT_ASA].w = c->hw->asa; 477141cc406Sopenharmony_ci 478141cc406Sopenharmony_ci c->opt[OPT_SHUTTER_SPEED].name = "shutterspeed"; 479141cc406Sopenharmony_ci c->opt[OPT_SHUTTER_SPEED].title = "Shutter Speed (ms)"; 480141cc406Sopenharmony_ci c->opt[OPT_SHUTTER_SPEED].desc = "Shutter Speed in milliseconds"; 481141cc406Sopenharmony_ci c->opt[OPT_SHUTTER_SPEED].constraint_type = SANE_CONSTRAINT_RANGE; 482141cc406Sopenharmony_ci c->opt[OPT_SHUTTER_SPEED].constraint.range = &c->hw->shutterSpeedRange; 483141cc406Sopenharmony_ci c->val[OPT_SHUTTER_SPEED].w = c->hw->shutterSpeed; 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].name = "whitebalance"; 486141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].title = "White Balance"; 487141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].desc = "Selects white balance"; 488141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].type = SANE_TYPE_STRING; 489141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 490141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].constraint.string_list = ValidBalances; 491141cc406Sopenharmony_ci c->opt[OPT_WHITE_BALANCE].size = 16; 492141cc406Sopenharmony_ci c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[c->hw->whiteBalance]; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 495141cc406Sopenharmony_ci} 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci/********************************************************************** 498141cc406Sopenharmony_ci//%FUNCTION: DMCSetMode 499141cc406Sopenharmony_ci//%ARGUMENTS: 500141cc406Sopenharmony_ci// c -- a DMC camera device 501141cc406Sopenharmony_ci// mode -- Imaging mode 502141cc406Sopenharmony_ci//%RETURNS: 503141cc406Sopenharmony_ci// SANE_STATUS_GOOD -- OK 504141cc406Sopenharmony_ci// SANE_STATUS_INVAL -- There's a problem. 505141cc406Sopenharmony_ci//%DESCRIPTION: 506141cc406Sopenharmony_ci// Sets the camera's imaging mode. 507141cc406Sopenharmony_ci// *********************************************************************/ 508141cc406Sopenharmony_cistatic SANE_Status 509141cc406Sopenharmony_ciDMCSetMode(DMC_Camera *c, int mode) 510141cc406Sopenharmony_ci{ 511141cc406Sopenharmony_ci switch (mode) 512141cc406Sopenharmony_ci { 513141cc406Sopenharmony_ci case IMAGE_MFI: 514141cc406Sopenharmony_ci c->tl_x_range.min = 0; 515141cc406Sopenharmony_ci c->tl_x_range.max = 800; 516141cc406Sopenharmony_ci c->tl_y_range.min = 0; 517141cc406Sopenharmony_ci c->tl_y_range.max = 599; 518141cc406Sopenharmony_ci c->br_x_range.min = c->tl_x_range.min; 519141cc406Sopenharmony_ci c->br_x_range.max = c->tl_x_range.max; 520141cc406Sopenharmony_ci c->br_y_range.min = c->tl_y_range.min; 521141cc406Sopenharmony_ci c->br_y_range.max = c->tl_y_range.max; 522141cc406Sopenharmony_ci break; 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci case IMAGE_VIEWFINDER: 525141cc406Sopenharmony_ci c->tl_x_range.min = 0; 526141cc406Sopenharmony_ci c->tl_x_range.max = 269; 527141cc406Sopenharmony_ci c->tl_y_range.min = 0; 528141cc406Sopenharmony_ci c->tl_y_range.max = 200; 529141cc406Sopenharmony_ci c->br_x_range.min = c->tl_x_range.min; 530141cc406Sopenharmony_ci c->br_x_range.max = c->tl_x_range.max; 531141cc406Sopenharmony_ci c->br_y_range.min = c->tl_y_range.min; 532141cc406Sopenharmony_ci c->br_y_range.max = c->tl_y_range.max; 533141cc406Sopenharmony_ci break; 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci case IMAGE_RAW: 536141cc406Sopenharmony_ci c->tl_x_range.min = 0; 537141cc406Sopenharmony_ci c->tl_x_range.max = 1598; 538141cc406Sopenharmony_ci c->tl_y_range.min = 0; 539141cc406Sopenharmony_ci c->tl_y_range.max = 599; 540141cc406Sopenharmony_ci c->br_x_range.min = c->tl_x_range.min; 541141cc406Sopenharmony_ci c->br_x_range.max = c->tl_x_range.max; 542141cc406Sopenharmony_ci c->br_y_range.min = c->tl_y_range.min; 543141cc406Sopenharmony_ci c->br_y_range.max = c->tl_y_range.max; 544141cc406Sopenharmony_ci break; 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci case IMAGE_THUMB: 547141cc406Sopenharmony_ci c->tl_x_range.min = 0; 548141cc406Sopenharmony_ci c->tl_x_range.max = 79; 549141cc406Sopenharmony_ci c->tl_y_range.min = 0; 550141cc406Sopenharmony_ci c->tl_y_range.max = 59; 551141cc406Sopenharmony_ci c->br_x_range.min = c->tl_x_range.min; 552141cc406Sopenharmony_ci c->br_x_range.max = c->tl_x_range.max; 553141cc406Sopenharmony_ci c->br_y_range.min = c->tl_y_range.min; 554141cc406Sopenharmony_ci c->br_y_range.max = c->tl_y_range.max; 555141cc406Sopenharmony_ci break; 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci case IMAGE_SUPER_RES: 558141cc406Sopenharmony_ci c->tl_x_range.min = 0; 559141cc406Sopenharmony_ci c->tl_x_range.max = 1598; 560141cc406Sopenharmony_ci c->tl_y_range.min = 0; 561141cc406Sopenharmony_ci c->tl_y_range.max = 1199; 562141cc406Sopenharmony_ci c->br_x_range.min = c->tl_x_range.min; 563141cc406Sopenharmony_ci c->br_x_range.max = c->tl_x_range.max; 564141cc406Sopenharmony_ci c->br_y_range.min = c->tl_y_range.min; 565141cc406Sopenharmony_ci c->br_y_range.max = c->tl_y_range.max; 566141cc406Sopenharmony_ci break; 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci default: 569141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 570141cc406Sopenharmony_ci } 571141cc406Sopenharmony_ci c->imageMode = mode; 572141cc406Sopenharmony_ci c->val[OPT_TL_X].w = c->tl_x_range.min; 573141cc406Sopenharmony_ci c->val[OPT_TL_Y].w = c->tl_y_range.min; 574141cc406Sopenharmony_ci c->val[OPT_BR_X].w = c->br_x_range.min; 575141cc406Sopenharmony_ci c->val[OPT_BR_Y].w = c->br_y_range.min; 576141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 577141cc406Sopenharmony_ci} 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci/********************************************************************** 580141cc406Sopenharmony_ci//%FUNCTION: DMCCancel 581141cc406Sopenharmony_ci//%ARGUMENTS: 582141cc406Sopenharmony_ci// c -- a DMC camera device 583141cc406Sopenharmony_ci//%RETURNS: 584141cc406Sopenharmony_ci// SANE_STATUS_CANCELLED 585141cc406Sopenharmony_ci//%DESCRIPTION: 586141cc406Sopenharmony_ci// Cancels DMC image acquisition 587141cc406Sopenharmony_ci// *********************************************************************/ 588141cc406Sopenharmony_cistatic SANE_Status 589141cc406Sopenharmony_ciDMCCancel(DMC_Camera *c) 590141cc406Sopenharmony_ci{ 591141cc406Sopenharmony_ci if (c->fd >= 0) { 592141cc406Sopenharmony_ci sanei_scsi_close(c->fd); 593141cc406Sopenharmony_ci c->fd = -1; 594141cc406Sopenharmony_ci } 595141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 596141cc406Sopenharmony_ci} 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci/********************************************************************** 599141cc406Sopenharmony_ci//%FUNCTION: DMCSetASA 600141cc406Sopenharmony_ci//%ARGUMENTS: 601141cc406Sopenharmony_ci// fd -- SCSI file descriptor 602141cc406Sopenharmony_ci// asa -- the ASA to set 603141cc406Sopenharmony_ci//%RETURNS: 604141cc406Sopenharmony_ci// A sane status value 605141cc406Sopenharmony_ci//%DESCRIPTION: 606141cc406Sopenharmony_ci// Sets the equivalent ASA setting of the camera. 607141cc406Sopenharmony_ci// *********************************************************************/ 608141cc406Sopenharmony_cistatic SANE_Status 609141cc406Sopenharmony_ciDMCSetASA(int fd, unsigned int asa) 610141cc406Sopenharmony_ci{ 611141cc406Sopenharmony_ci uint8_t exposureCalculationResults[16]; 612141cc406Sopenharmony_ci SANE_Status status; 613141cc406Sopenharmony_ci size_t len; 614141cc406Sopenharmony_ci int i; 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci DBG(3, "DMCSetAsa: %d\n", asa); 617141cc406Sopenharmony_ci for (i=1; i<=ASA_100+1; i++) { 618141cc406Sopenharmony_ci if (asa == (unsigned int) ValidASAs[i]) break; 619141cc406Sopenharmony_ci } 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci if (i > ASA_100+1) return SANE_STATUS_INVAL; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, 624141cc406Sopenharmony_ci sizeof(exposureCalculationResults), &len); 625141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 626141cc406Sopenharmony_ci if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR; 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci exposureCalculationResults[13] = (uint8_t) i - 1; 629141cc406Sopenharmony_ci 630141cc406Sopenharmony_ci return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults, 631141cc406Sopenharmony_ci sizeof(exposureCalculationResults)); 632141cc406Sopenharmony_ci} 633141cc406Sopenharmony_ci 634141cc406Sopenharmony_ci/********************************************************************** 635141cc406Sopenharmony_ci//%FUNCTION: DMCSetWhiteBalance 636141cc406Sopenharmony_ci//%ARGUMENTS: 637141cc406Sopenharmony_ci// fd -- SCSI file descriptor 638141cc406Sopenharmony_ci// mode -- white balance mode 639141cc406Sopenharmony_ci//%RETURNS: 640141cc406Sopenharmony_ci// A sane status value 641141cc406Sopenharmony_ci//%DESCRIPTION: 642141cc406Sopenharmony_ci// Sets the equivalent ASA setting of the camera. 643141cc406Sopenharmony_ci// *********************************************************************/ 644141cc406Sopenharmony_cistatic SANE_Status 645141cc406Sopenharmony_ciDMCSetWhiteBalance(int fd, int mode) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci uint8_t userInterfaceSettings[16]; 648141cc406Sopenharmony_ci SANE_Status status; 649141cc406Sopenharmony_ci size_t len; 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci DBG(3, "DMCSetWhiteBalance: %d\n", mode); 652141cc406Sopenharmony_ci status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings, 653141cc406Sopenharmony_ci sizeof(userInterfaceSettings), &len); 654141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 655141cc406Sopenharmony_ci if (len < sizeof(userInterfaceSettings)) return SANE_STATUS_IO_ERROR; 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci userInterfaceSettings[5] = (uint8_t) mode; 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci return DMCWrite(fd, 0x82, 0x0, userInterfaceSettings, 660141cc406Sopenharmony_ci sizeof(userInterfaceSettings)); 661141cc406Sopenharmony_ci} 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci/********************************************************************** 664141cc406Sopenharmony_ci//%FUNCTION: DMCSetShutterSpeed 665141cc406Sopenharmony_ci//%ARGUMENTS: 666141cc406Sopenharmony_ci// fd -- SCSI file descriptor 667141cc406Sopenharmony_ci// speed -- shutter speed in ms 668141cc406Sopenharmony_ci//%RETURNS: 669141cc406Sopenharmony_ci// A sane status value 670141cc406Sopenharmony_ci//%DESCRIPTION: 671141cc406Sopenharmony_ci// Sets the shutter speed of the camera 672141cc406Sopenharmony_ci// *********************************************************************/ 673141cc406Sopenharmony_cistatic SANE_Status 674141cc406Sopenharmony_ciDMCSetShutterSpeed(int fd, unsigned int speed) 675141cc406Sopenharmony_ci{ 676141cc406Sopenharmony_ci uint8_t exposureCalculationResults[16]; 677141cc406Sopenharmony_ci SANE_Status status; 678141cc406Sopenharmony_ci size_t len; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci DBG(3, "DMCSetShutterSpeed: %u\n", speed); 681141cc406Sopenharmony_ci /* Convert from ms to ticks */ 682141cc406Sopenharmony_ci speed = MS_TO_TICKS(speed); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, 685141cc406Sopenharmony_ci sizeof(exposureCalculationResults), &len); 686141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 687141cc406Sopenharmony_ci if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR; 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci exposureCalculationResults[10] = (speed >> 8) & 0xFF; 690141cc406Sopenharmony_ci exposureCalculationResults[11] = speed & 0xFF; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults, 693141cc406Sopenharmony_ci sizeof(exposureCalculationResults)); 694141cc406Sopenharmony_ci} 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci/********************************************************************** 697141cc406Sopenharmony_ci//%FUNCTION: DMCReadTwoSuperResolutionLines 698141cc406Sopenharmony_ci//%ARGUMENTS: 699141cc406Sopenharmony_ci// c -- DMC Camera 700141cc406Sopenharmony_ci// buf -- where to put output. 701141cc406Sopenharmony_ci// lastLine -- if true, these are the last two lines in the super-resolution 702141cc406Sopenharmony_ci// image to read. 703141cc406Sopenharmony_ci//%RETURNS: 704141cc406Sopenharmony_ci// Nothing 705141cc406Sopenharmony_ci//%DESCRIPTION: 706141cc406Sopenharmony_ci// Reads a single "raw" line from the camera (if needed) and constructs 707141cc406Sopenharmony_ci// two "super-resolution" output lines in "buf" 708141cc406Sopenharmony_ci// *********************************************************************/ 709141cc406Sopenharmony_cistatic SANE_Status 710141cc406Sopenharmony_ciDMCReadTwoSuperResolutionLines(DMC_Camera *c, SANE_Byte *buf, int lastLine) 711141cc406Sopenharmony_ci{ 712141cc406Sopenharmony_ci SANE_Status status; 713141cc406Sopenharmony_ci size_t len; 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci SANE_Byte *output, *prev; 716141cc406Sopenharmony_ci int redCoeff, greenCoeff, blueCoeff; 717141cc406Sopenharmony_ci int red, green, blue; 718141cc406Sopenharmony_ci int i; 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci if (c->nextRawLineValid) { 721141cc406Sopenharmony_ci memcpy(c->currentRawLine, c->nextRawLine, BYTES_PER_RAW_LINE); 722141cc406Sopenharmony_ci } else { 723141cc406Sopenharmony_ci status = DMCRead(c->fd, 0x00, IMAGE_RAW, 724141cc406Sopenharmony_ci c->currentRawLine, BYTES_PER_RAW_LINE, &len); 725141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci if (!lastLine) { 728141cc406Sopenharmony_ci status = DMCRead(c->fd, 0x00, IMAGE_RAW, 729141cc406Sopenharmony_ci c->nextRawLine, BYTES_PER_RAW_LINE, &len); 730141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 731141cc406Sopenharmony_ci c->nextRawLineValid = 1; 732141cc406Sopenharmony_ci } 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci redCoeff = 3; 735141cc406Sopenharmony_ci greenCoeff = 1; 736141cc406Sopenharmony_ci blueCoeff = 2; 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci /* Do the first super-resolution line */ 739141cc406Sopenharmony_ci output = buf; 740141cc406Sopenharmony_ci for (i=0; i<BYTES_PER_RAW_LINE; i++) { 741141cc406Sopenharmony_ci red = redCoeff * c->currentRawLine[PREV_RED(i)] + 742141cc406Sopenharmony_ci (3-redCoeff) * c->currentRawLine[NEXT_RED(i)]; 743141cc406Sopenharmony_ci green = greenCoeff * c->currentRawLine[PREV_GREEN(i)] + 744141cc406Sopenharmony_ci (3-greenCoeff) * c->currentRawLine[NEXT_GREEN(i)]; 745141cc406Sopenharmony_ci blue = blueCoeff * c->currentRawLine[PREV_BLUE(i)] + 746141cc406Sopenharmony_ci (3-blueCoeff) * c->currentRawLine[NEXT_BLUE(i)]; 747141cc406Sopenharmony_ci *output++ = red/3; 748141cc406Sopenharmony_ci *output++ = green/3; 749141cc406Sopenharmony_ci *output++ = blue/3; 750141cc406Sopenharmony_ci redCoeff = ADVANCE_COEFF(redCoeff); 751141cc406Sopenharmony_ci greenCoeff = ADVANCE_COEFF(greenCoeff); 752141cc406Sopenharmony_ci blueCoeff = ADVANCE_COEFF(blueCoeff); 753141cc406Sopenharmony_ci } 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci /* Do the next super-resolution line and interpolate vertically */ 756141cc406Sopenharmony_ci if (lastLine) { 757141cc406Sopenharmony_ci memcpy(buf+BYTES_PER_RAW_LINE*3, buf, BYTES_PER_RAW_LINE*3); 758141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 759141cc406Sopenharmony_ci } 760141cc406Sopenharmony_ci redCoeff = 3; 761141cc406Sopenharmony_ci greenCoeff = 1; 762141cc406Sopenharmony_ci blueCoeff = 2; 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_ci prev = buf; 765141cc406Sopenharmony_ci for (i=0; i<BYTES_PER_RAW_LINE; i++) { 766141cc406Sopenharmony_ci red = redCoeff * c->nextRawLine[PREV_RED(i)] + 767141cc406Sopenharmony_ci (3-redCoeff) * c->nextRawLine[NEXT_RED(i)]; 768141cc406Sopenharmony_ci green = greenCoeff * c->nextRawLine[PREV_GREEN(i)] + 769141cc406Sopenharmony_ci (3-greenCoeff) * c->nextRawLine[NEXT_GREEN(i)]; 770141cc406Sopenharmony_ci blue = blueCoeff * c->nextRawLine[PREV_BLUE(i)] + 771141cc406Sopenharmony_ci (3-blueCoeff) * c->nextRawLine[NEXT_BLUE(i)]; 772141cc406Sopenharmony_ci *output++ = (red/3 + *prev++) / 2; 773141cc406Sopenharmony_ci *output++ = (green/3 + *prev++) / 2; 774141cc406Sopenharmony_ci *output++ = (blue/3 + *prev++) / 2; 775141cc406Sopenharmony_ci redCoeff = ADVANCE_COEFF(redCoeff); 776141cc406Sopenharmony_ci greenCoeff = ADVANCE_COEFF(greenCoeff); 777141cc406Sopenharmony_ci blueCoeff = ADVANCE_COEFF(blueCoeff); 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 780141cc406Sopenharmony_ci} 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci/*********************************************************************** 783141cc406Sopenharmony_ci//%FUNCTION: attach_one (static function) 784141cc406Sopenharmony_ci//%ARGUMENTS: 785141cc406Sopenharmony_ci// dev -- device to attach 786141cc406Sopenharmony_ci//%RETURNS: 787141cc406Sopenharmony_ci// SANE_STATUS_GOOD 788141cc406Sopenharmony_ci//%DESCRIPTION: 789141cc406Sopenharmony_ci// tries to attach a device found by sanei_config_attach_matching_devices 790141cc406Sopenharmony_ci// *********************************************************************/ 791141cc406Sopenharmony_cistatic SANE_Status 792141cc406Sopenharmony_ciattach_one (const char *dev) 793141cc406Sopenharmony_ci{ 794141cc406Sopenharmony_ci DMCAttach (dev, 0); 795141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 796141cc406Sopenharmony_ci} 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci/********************************************************************** 799141cc406Sopenharmony_ci//%FUNCTION: sane_init 800141cc406Sopenharmony_ci//%ARGUMENTS: 801141cc406Sopenharmony_ci// version_code -- pointer to where we stick our version code 802141cc406Sopenharmony_ci// authorize -- authorization function 803141cc406Sopenharmony_ci//%RETURNS: 804141cc406Sopenharmony_ci// A sane status value 805141cc406Sopenharmony_ci//%DESCRIPTION: 806141cc406Sopenharmony_ci// Initializes DMC sane system. 807141cc406Sopenharmony_ci// *********************************************************************/ 808141cc406Sopenharmony_ciSANE_Status 809141cc406Sopenharmony_cisane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) 810141cc406Sopenharmony_ci{ 811141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 812141cc406Sopenharmony_ci size_t len; 813141cc406Sopenharmony_ci FILE *fp; 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci (void) authorize; 816141cc406Sopenharmony_ci 817141cc406Sopenharmony_ci DBG_INIT(); 818141cc406Sopenharmony_ci if (version_code) { 819141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 820141cc406Sopenharmony_ci } 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci fp = sanei_config_open(DMC_CONFIG_FILE); 823141cc406Sopenharmony_ci if (!fp) { 824141cc406Sopenharmony_ci /* default to /dev/camera instead of insisting on config file */ 825141cc406Sopenharmony_ci if (DMCAttach ("/dev/camera", NULL) != SANE_STATUS_GOOD) { 826141cc406Sopenharmony_ci /* OK, try /dev/scanner */ 827141cc406Sopenharmony_ci DMCAttach("/dev/scanner", NULL); 828141cc406Sopenharmony_ci } 829141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 830141cc406Sopenharmony_ci } 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { 833141cc406Sopenharmony_ci if (dev_name[0] == '#') { /* ignore line comments */ 834141cc406Sopenharmony_ci continue; 835141cc406Sopenharmony_ci } 836141cc406Sopenharmony_ci len = strlen (dev_name); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci if (!len) continue; /* ignore empty lines */ 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci sanei_config_attach_matching_devices(dev_name, attach_one); 841141cc406Sopenharmony_ci } 842141cc406Sopenharmony_ci fclose (fp); 843141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 844141cc406Sopenharmony_ci} 845141cc406Sopenharmony_ci 846141cc406Sopenharmony_ci/********************************************************************** 847141cc406Sopenharmony_ci//%FUNCTION: sane_exit 848141cc406Sopenharmony_ci//%ARGUMENTS: 849141cc406Sopenharmony_ci// None 850141cc406Sopenharmony_ci//%RETURNS: 851141cc406Sopenharmony_ci// Nothing 852141cc406Sopenharmony_ci//%DESCRIPTION: 853141cc406Sopenharmony_ci// Cleans up all the SANE information 854141cc406Sopenharmony_ci// *********************************************************************/ 855141cc406Sopenharmony_civoid 856141cc406Sopenharmony_cisane_exit(void) 857141cc406Sopenharmony_ci{ 858141cc406Sopenharmony_ci DMC_Device *dev, *next; 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci /* Close all handles */ 861141cc406Sopenharmony_ci while(FirstHandle) { 862141cc406Sopenharmony_ci sane_close(FirstHandle); 863141cc406Sopenharmony_ci } 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci /* Free all devices */ 866141cc406Sopenharmony_ci dev = FirstDevice; 867141cc406Sopenharmony_ci while(dev) { 868141cc406Sopenharmony_ci next = dev->next; 869141cc406Sopenharmony_ci free((char *) dev->sane.model); 870141cc406Sopenharmony_ci free(dev); 871141cc406Sopenharmony_ci dev = next; 872141cc406Sopenharmony_ci } 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ci if (devlist) 875141cc406Sopenharmony_ci free (devlist); 876141cc406Sopenharmony_ci} 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci/********************************************************************** 879141cc406Sopenharmony_ci//%FUNCTION: sane_get_devices 880141cc406Sopenharmony_ci//%ARGUMENTS: 881141cc406Sopenharmony_ci// device_list -- set to allocated list of devices 882141cc406Sopenharmony_ci// local_only -- ignored 883141cc406Sopenharmony_ci//%RETURNS: 884141cc406Sopenharmony_ci// A SANE status 885141cc406Sopenharmony_ci//%DESCRIPTION: 886141cc406Sopenharmony_ci// Returns a list of all known DMC devices 887141cc406Sopenharmony_ci// *********************************************************************/ 888141cc406Sopenharmony_ciSANE_Status 889141cc406Sopenharmony_cisane_get_devices(SANE_Device const ***device_list, SANE_Bool local_only) 890141cc406Sopenharmony_ci{ 891141cc406Sopenharmony_ci DMC_Device *dev; 892141cc406Sopenharmony_ci int i = 0; 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci (void) local_only; 895141cc406Sopenharmony_ci 896141cc406Sopenharmony_ci if (devlist) free(devlist); 897141cc406Sopenharmony_ci devlist = malloc((NumDevices+1) * sizeof(devlist[0])); 898141cc406Sopenharmony_ci if (!devlist) return SANE_STATUS_NO_MEM; 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci for (dev=FirstDevice; dev; dev = dev->next) { 901141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 902141cc406Sopenharmony_ci } 903141cc406Sopenharmony_ci devlist[i] = NULL; 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci if (device_list) *device_list = devlist; 906141cc406Sopenharmony_ci 907141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 908141cc406Sopenharmony_ci} 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci/********************************************************************** 911141cc406Sopenharmony_ci//%FUNCTION: sane_open 912141cc406Sopenharmony_ci//%ARGUMENTS: 913141cc406Sopenharmony_ci// name -- name of device to open 914141cc406Sopenharmony_ci// handle -- set to a handle for the opened device 915141cc406Sopenharmony_ci//%RETURNS: 916141cc406Sopenharmony_ci// A SANE status 917141cc406Sopenharmony_ci//%DESCRIPTION: 918141cc406Sopenharmony_ci// Opens a DMC camera device 919141cc406Sopenharmony_ci// *********************************************************************/ 920141cc406Sopenharmony_ciSANE_Status 921141cc406Sopenharmony_cisane_open(SANE_String_Const name, SANE_Handle *handle) 922141cc406Sopenharmony_ci{ 923141cc406Sopenharmony_ci SANE_Status status; 924141cc406Sopenharmony_ci DMC_Device *dev; 925141cc406Sopenharmony_ci DMC_Camera *c; 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci /* If we're given a device name, search for it */ 928141cc406Sopenharmony_ci if (*name) { 929141cc406Sopenharmony_ci for (dev = FirstDevice; dev; dev = dev->next) { 930141cc406Sopenharmony_ci if (!strcmp(dev->sane.name, name)) { 931141cc406Sopenharmony_ci break; 932141cc406Sopenharmony_ci } 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci if (!dev) { 935141cc406Sopenharmony_ci status = DMCAttach(name, &dev); 936141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci } else { 939141cc406Sopenharmony_ci dev = FirstDevice; 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci if (!dev) return SANE_STATUS_INVAL; 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci c = malloc(sizeof(*c)); 945141cc406Sopenharmony_ci if (!c) return SANE_STATUS_NO_MEM; 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci memset(c, 0, sizeof(*c)); 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci c->fd = -1; 950141cc406Sopenharmony_ci c->hw = dev; 951141cc406Sopenharmony_ci c->readBuffer = NULL; 952141cc406Sopenharmony_ci c->readPtr = NULL; 953141cc406Sopenharmony_ci c->imageMode = IMAGE_MFI; 954141cc406Sopenharmony_ci c->inViewfinderMode = 0; 955141cc406Sopenharmony_ci c->nextRawLineValid = 0; 956141cc406Sopenharmony_ci 957141cc406Sopenharmony_ci DMCInitOptions(c); 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci c->next = FirstHandle; 960141cc406Sopenharmony_ci FirstHandle = c; 961141cc406Sopenharmony_ci if (handle) *handle = c; 962141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 963141cc406Sopenharmony_ci} 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci/********************************************************************** 966141cc406Sopenharmony_ci//%FUNCTION: sane_close 967141cc406Sopenharmony_ci//%ARGUMENTS: 968141cc406Sopenharmony_ci// handle -- handle of device to close 969141cc406Sopenharmony_ci//%RETURNS: 970141cc406Sopenharmony_ci// A SANE status 971141cc406Sopenharmony_ci//%DESCRIPTION: 972141cc406Sopenharmony_ci// Closes a DMC camera device 973141cc406Sopenharmony_ci// *********************************************************************/ 974141cc406Sopenharmony_civoid 975141cc406Sopenharmony_cisane_close(SANE_Handle handle) 976141cc406Sopenharmony_ci{ 977141cc406Sopenharmony_ci DMC_Camera *prev, *c; 978141cc406Sopenharmony_ci prev = NULL; 979141cc406Sopenharmony_ci for (c = FirstHandle; c; c = c->next) { 980141cc406Sopenharmony_ci if (c == handle) break; 981141cc406Sopenharmony_ci prev = c; 982141cc406Sopenharmony_ci } 983141cc406Sopenharmony_ci if (!c) { 984141cc406Sopenharmony_ci DBG(1, "close: invalid handle %p\n", handle); 985141cc406Sopenharmony_ci return; 986141cc406Sopenharmony_ci } 987141cc406Sopenharmony_ci DMCCancel(c); 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci if (prev) prev->next = c->next; 990141cc406Sopenharmony_ci else FirstHandle = c->next; 991141cc406Sopenharmony_ci 992141cc406Sopenharmony_ci if (c->readBuffer) { 993141cc406Sopenharmony_ci free(c->readBuffer); 994141cc406Sopenharmony_ci } 995141cc406Sopenharmony_ci free(c); 996141cc406Sopenharmony_ci} 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci/********************************************************************** 999141cc406Sopenharmony_ci//%FUNCTION: sane_get_option_descriptor 1000141cc406Sopenharmony_ci//%ARGUMENTS: 1001141cc406Sopenharmony_ci// handle -- handle of device 1002141cc406Sopenharmony_ci// option -- option number to retrieve 1003141cc406Sopenharmony_ci//%RETURNS: 1004141cc406Sopenharmony_ci// An option descriptor or NULL on error 1005141cc406Sopenharmony_ci// *********************************************************************/ 1006141cc406Sopenharmony_ciSANE_Option_Descriptor const * 1007141cc406Sopenharmony_cisane_get_option_descriptor(SANE_Handle handle, SANE_Int option) 1008141cc406Sopenharmony_ci{ 1009141cc406Sopenharmony_ci DMC_Camera *c = ValidateHandle(handle); 1010141cc406Sopenharmony_ci if (!c) return NULL; 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) return NULL; 1013141cc406Sopenharmony_ci return c->opt + option; 1014141cc406Sopenharmony_ci} 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci/********************************************************************** 1017141cc406Sopenharmony_ci//%FUNCTION: sane_control_option 1018141cc406Sopenharmony_ci//%ARGUMENTS: 1019141cc406Sopenharmony_ci// handle -- handle of device 1020141cc406Sopenharmony_ci// option -- option number to retrieve 1021141cc406Sopenharmony_ci// action -- what to do with the option 1022141cc406Sopenharmony_ci// val -- value to set option to 1023141cc406Sopenharmony_ci// info -- returned info flags 1024141cc406Sopenharmony_ci//%RETURNS: 1025141cc406Sopenharmony_ci// SANE status 1026141cc406Sopenharmony_ci//%DESCRIPTION: 1027141cc406Sopenharmony_ci// Sets or queries option values 1028141cc406Sopenharmony_ci// *********************************************************************/ 1029141cc406Sopenharmony_ciSANE_Status 1030141cc406Sopenharmony_cisane_control_option(SANE_Handle handle, SANE_Int option, 1031141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int *info) 1032141cc406Sopenharmony_ci{ 1033141cc406Sopenharmony_ci DMC_Camera *c; 1034141cc406Sopenharmony_ci SANE_Word cap; 1035141cc406Sopenharmony_ci int i; 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci if (info) *info = 0; 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci c = ValidateHandle(handle); 1040141cc406Sopenharmony_ci if (!c) return SANE_STATUS_INVAL; 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY; 1043141cc406Sopenharmony_ci 1044141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci cap = c->opt[option].cap; 1047141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE(cap)) return SANE_STATUS_INVAL; 1048141cc406Sopenharmony_ci 1049141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) { 1050141cc406Sopenharmony_ci switch(c->opt[option].type) { 1051141cc406Sopenharmony_ci case SANE_TYPE_INT: 1052141cc406Sopenharmony_ci * (SANE_Int *) val = c->val[option].w; 1053141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci case SANE_TYPE_STRING: 1056141cc406Sopenharmony_ci strcpy(val, c->val[option].s); 1057141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1058141cc406Sopenharmony_ci 1059141cc406Sopenharmony_ci default: 1060141cc406Sopenharmony_ci DBG(3, "impossible option type!\n"); 1061141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1062141cc406Sopenharmony_ci } 1063141cc406Sopenharmony_ci } 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci if (action == SANE_ACTION_SET_AUTO) { 1066141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1067141cc406Sopenharmony_ci } 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci switch(option) { 1070141cc406Sopenharmony_ci case OPT_IMAGE_MODE: 1071141cc406Sopenharmony_ci for (i=0; i<NUM_IMAGE_MODES; i++) { 1072141cc406Sopenharmony_ci if (!strcmp(val, ValidModes[i])) { 1073141cc406Sopenharmony_ci DMCSetMode(c, i); 1074141cc406Sopenharmony_ci c->val[OPT_IMAGE_MODE].s = (SANE_String) ValidModes[i]; 1075141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1076141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1077141cc406Sopenharmony_ci } 1078141cc406Sopenharmony_ci } 1079141cc406Sopenharmony_ci break; 1080141cc406Sopenharmony_ci case OPT_WHITE_BALANCE: 1081141cc406Sopenharmony_ci for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) { 1082141cc406Sopenharmony_ci if (!strcmp(val, ValidBalances[i])) { 1083141cc406Sopenharmony_ci c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[i]; 1084141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1085141cc406Sopenharmony_ci } 1086141cc406Sopenharmony_ci } 1087141cc406Sopenharmony_ci break; 1088141cc406Sopenharmony_ci case OPT_ASA: 1089141cc406Sopenharmony_ci for (i=1; i<= ASA_100+1; i++) { 1090141cc406Sopenharmony_ci if (* ((SANE_Int *) val) == ValidASAs[i]) { 1091141cc406Sopenharmony_ci c->val[OPT_ASA].w = ValidASAs[i]; 1092141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1093141cc406Sopenharmony_ci } 1094141cc406Sopenharmony_ci } 1095141cc406Sopenharmony_ci break; 1096141cc406Sopenharmony_ci case OPT_SHUTTER_SPEED: 1097141cc406Sopenharmony_ci if (* (SANE_Int *) val < c->hw->shutterSpeedRange.min || 1098141cc406Sopenharmony_ci * (SANE_Int *) val > c->hw->shutterSpeedRange.max) { 1099141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1100141cc406Sopenharmony_ci } 1101141cc406Sopenharmony_ci c->val[OPT_SHUTTER_SPEED].w = * (SANE_Int *) val; 1102141cc406Sopenharmony_ci /* Do any roundoff */ 1103141cc406Sopenharmony_ci c->val[OPT_SHUTTER_SPEED].w = 1104141cc406Sopenharmony_ci TICKS_TO_MS(MS_TO_TICKS(c->val[OPT_SHUTTER_SPEED].w)); 1105141cc406Sopenharmony_ci if (c->val[OPT_SHUTTER_SPEED].w != * (SANE_Int *) val) { 1106141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_INEXACT; 1107141cc406Sopenharmony_ci } 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci default: 1112141cc406Sopenharmony_ci /* Should really be INVAL, but just bit-bucket set requests... */ 1113141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1114141cc406Sopenharmony_ci } 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1117141cc406Sopenharmony_ci} 1118141cc406Sopenharmony_ci 1119141cc406Sopenharmony_ci/********************************************************************** 1120141cc406Sopenharmony_ci//%FUNCTION: sane_get_parameters 1121141cc406Sopenharmony_ci//%ARGUMENTS: 1122141cc406Sopenharmony_ci// handle -- handle of device 1123141cc406Sopenharmony_ci// params -- set to device parameters 1124141cc406Sopenharmony_ci//%RETURNS: 1125141cc406Sopenharmony_ci// SANE status 1126141cc406Sopenharmony_ci//%DESCRIPTION: 1127141cc406Sopenharmony_ci// Returns parameters for current or next image. 1128141cc406Sopenharmony_ci// *********************************************************************/ 1129141cc406Sopenharmony_ciSANE_Status 1130141cc406Sopenharmony_cisane_get_parameters(SANE_Handle handle, SANE_Parameters *params) 1131141cc406Sopenharmony_ci{ 1132141cc406Sopenharmony_ci DMC_Camera *c = ValidateHandle(handle); 1133141cc406Sopenharmony_ci if (!c) return SANE_STATUS_INVAL; 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci if (c->fd < 0) { 1136141cc406Sopenharmony_ci int width, height; 1137141cc406Sopenharmony_ci memset(&c->params, 0, sizeof(c->params)); 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci width = c->val[OPT_BR_X].w - c->val[OPT_TL_X].w; 1140141cc406Sopenharmony_ci height = c->val[OPT_BR_Y].w - c->val[OPT_TL_Y].w; 1141141cc406Sopenharmony_ci c->params.pixels_per_line = width + 1; 1142141cc406Sopenharmony_ci c->params.lines = height+1; 1143141cc406Sopenharmony_ci c->params.depth = 8; 1144141cc406Sopenharmony_ci c->params.last_frame = SANE_TRUE; 1145141cc406Sopenharmony_ci switch(c->imageMode) { 1146141cc406Sopenharmony_ci case IMAGE_SUPER_RES: 1147141cc406Sopenharmony_ci case IMAGE_MFI: 1148141cc406Sopenharmony_ci case IMAGE_THUMB: 1149141cc406Sopenharmony_ci c->params.format = SANE_FRAME_RGB; 1150141cc406Sopenharmony_ci c->params.bytes_per_line = c->params.pixels_per_line * 3; 1151141cc406Sopenharmony_ci break; 1152141cc406Sopenharmony_ci case IMAGE_RAW: 1153141cc406Sopenharmony_ci case IMAGE_VIEWFINDER: 1154141cc406Sopenharmony_ci c->params.format = SANE_FRAME_GRAY; 1155141cc406Sopenharmony_ci c->params.bytes_per_line = c->params.pixels_per_line; 1156141cc406Sopenharmony_ci break; 1157141cc406Sopenharmony_ci } 1158141cc406Sopenharmony_ci } 1159141cc406Sopenharmony_ci if (params) *params = c->params; 1160141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1161141cc406Sopenharmony_ci} 1162141cc406Sopenharmony_ci 1163141cc406Sopenharmony_ci/********************************************************************** 1164141cc406Sopenharmony_ci//%FUNCTION: sane_start 1165141cc406Sopenharmony_ci//%ARGUMENTS: 1166141cc406Sopenharmony_ci// handle -- handle of device 1167141cc406Sopenharmony_ci//%RETURNS: 1168141cc406Sopenharmony_ci// SANE status 1169141cc406Sopenharmony_ci//%DESCRIPTION: 1170141cc406Sopenharmony_ci// Starts acquisition 1171141cc406Sopenharmony_ci// *********************************************************************/ 1172141cc406Sopenharmony_ciSANE_Status 1173141cc406Sopenharmony_cisane_start(SANE_Handle handle) 1174141cc406Sopenharmony_ci{ 1175141cc406Sopenharmony_ci static uint8_t const acquire[] = 1176141cc406Sopenharmony_ci { 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 1177141cc406Sopenharmony_ci 1178141cc406Sopenharmony_ci static uint8_t const viewfinder[] = 1179141cc406Sopenharmony_ci { 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci static uint8_t const no_viewfinder[] = 1182141cc406Sopenharmony_ci { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 1183141cc406Sopenharmony_ci 1184141cc406Sopenharmony_ci DMC_Camera *c = ValidateHandle(handle); 1185141cc406Sopenharmony_ci SANE_Status status; 1186141cc406Sopenharmony_ci int i; 1187141cc406Sopenharmony_ci 1188141cc406Sopenharmony_ci if (!c) return SANE_STATUS_INVAL; 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci /* If we're already open, barf -- not sure this is the best status */ 1191141cc406Sopenharmony_ci if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY; 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci /* Get rid of old read buffers */ 1194141cc406Sopenharmony_ci if (c->readBuffer) { 1195141cc406Sopenharmony_ci free(c->readBuffer); 1196141cc406Sopenharmony_ci c->readBuffer = NULL; 1197141cc406Sopenharmony_ci c->readPtr = NULL; 1198141cc406Sopenharmony_ci } 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci c->nextRawLineValid = 0; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci /* Refresh parameter list */ 1203141cc406Sopenharmony_ci status = sane_get_parameters(c, NULL); 1204141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 1205141cc406Sopenharmony_ci 1206141cc406Sopenharmony_ci status = sanei_scsi_open(c->hw->sane.name, &c->fd, NULL, NULL); 1207141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1208141cc406Sopenharmony_ci c->fd = -1; 1209141cc406Sopenharmony_ci DBG(1, "DMC: Open of `%s' failed: %s\n", 1210141cc406Sopenharmony_ci c->hw->sane.name, sane_strstatus(status)); 1211141cc406Sopenharmony_ci return status; 1212141cc406Sopenharmony_ci } 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci /* Set ASA and shutter speed if they're no longer current */ 1215141cc406Sopenharmony_ci if (c->val[OPT_ASA].w != c->hw->asa) { 1216141cc406Sopenharmony_ci status = DMCSetASA(c->fd, c->val[OPT_ASA].w); 1217141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1218141cc406Sopenharmony_ci DMCCancel(c); 1219141cc406Sopenharmony_ci return status; 1220141cc406Sopenharmony_ci } 1221141cc406Sopenharmony_ci c->hw->asa = c->val[OPT_ASA].w; 1222141cc406Sopenharmony_ci } 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci if ((unsigned int) c->val[OPT_SHUTTER_SPEED].w != c->hw->shutterSpeed) { 1225141cc406Sopenharmony_ci status = DMCSetShutterSpeed(c->fd, c->val[OPT_SHUTTER_SPEED].w); 1226141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1227141cc406Sopenharmony_ci DMCCancel(c); 1228141cc406Sopenharmony_ci return status; 1229141cc406Sopenharmony_ci } 1230141cc406Sopenharmony_ci c->hw->shutterSpeed = c->val[OPT_SHUTTER_SPEED].w; 1231141cc406Sopenharmony_ci } 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci /* Set white balance mode if needed */ 1234141cc406Sopenharmony_ci for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) { 1235141cc406Sopenharmony_ci if (!strcmp(ValidBalances[i], c->val[OPT_WHITE_BALANCE].s)) { 1236141cc406Sopenharmony_ci if (i != c->hw->whiteBalance) { 1237141cc406Sopenharmony_ci status = DMCSetWhiteBalance(c->fd, i); 1238141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1239141cc406Sopenharmony_ci DMCCancel(c); 1240141cc406Sopenharmony_ci return status; 1241141cc406Sopenharmony_ci } 1242141cc406Sopenharmony_ci c->hw->whiteBalance = i; 1243141cc406Sopenharmony_ci } 1244141cc406Sopenharmony_ci } 1245141cc406Sopenharmony_ci } 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci /* Flip into viewfinder mode if needed */ 1248141cc406Sopenharmony_ci if (c->imageMode == IMAGE_VIEWFINDER && !c->inViewfinderMode) { 1249141cc406Sopenharmony_ci status = sanei_scsi_cmd(c->fd, viewfinder, sizeof(viewfinder), 1250141cc406Sopenharmony_ci NULL, NULL); 1251141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1252141cc406Sopenharmony_ci DMCCancel(c); 1253141cc406Sopenharmony_ci return status; 1254141cc406Sopenharmony_ci } 1255141cc406Sopenharmony_ci c->inViewfinderMode = 1; 1256141cc406Sopenharmony_ci } 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci /* Flip out of viewfinder mode if needed */ 1259141cc406Sopenharmony_ci if (c->imageMode != IMAGE_VIEWFINDER && c->inViewfinderMode) { 1260141cc406Sopenharmony_ci status = sanei_scsi_cmd(c->fd, no_viewfinder, sizeof(no_viewfinder), 1261141cc406Sopenharmony_ci NULL, NULL); 1262141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1263141cc406Sopenharmony_ci DMCCancel(c); 1264141cc406Sopenharmony_ci return status; 1265141cc406Sopenharmony_ci } 1266141cc406Sopenharmony_ci c->inViewfinderMode = 0; 1267141cc406Sopenharmony_ci } 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci status = sanei_scsi_cmd(c->fd, acquire, sizeof(acquire), NULL, NULL); 1271141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1272141cc406Sopenharmony_ci DMCCancel(c); 1273141cc406Sopenharmony_ci return status; 1274141cc406Sopenharmony_ci } 1275141cc406Sopenharmony_ci c->bytes_to_read = c->params.bytes_per_line * c->params.lines; 1276141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1277141cc406Sopenharmony_ci} 1278141cc406Sopenharmony_ci 1279141cc406Sopenharmony_ci/********************************************************************** 1280141cc406Sopenharmony_ci//%FUNCTION: sane_read 1281141cc406Sopenharmony_ci//%ARGUMENTS: 1282141cc406Sopenharmony_ci// handle -- handle of device 1283141cc406Sopenharmony_ci// buf -- destination for data 1284141cc406Sopenharmony_ci// max_len -- maximum amount of data to store 1285141cc406Sopenharmony_ci// len -- set to actual amount of data stored. 1286141cc406Sopenharmony_ci//%RETURNS: 1287141cc406Sopenharmony_ci// SANE status 1288141cc406Sopenharmony_ci//%DESCRIPTION: 1289141cc406Sopenharmony_ci// Reads image data from the camera 1290141cc406Sopenharmony_ci// *********************************************************************/ 1291141cc406Sopenharmony_ciSANE_Status 1292141cc406Sopenharmony_cisane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) 1293141cc406Sopenharmony_ci{ 1294141cc406Sopenharmony_ci SANE_Status status; 1295141cc406Sopenharmony_ci DMC_Camera *c = ValidateHandle(handle); 1296141cc406Sopenharmony_ci size_t size; 1297141cc406Sopenharmony_ci SANE_Int i; 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci if (!c) return SANE_STATUS_INVAL; 1300141cc406Sopenharmony_ci 1301141cc406Sopenharmony_ci if (c->fd < 0) return SANE_STATUS_INVAL; 1302141cc406Sopenharmony_ci 1303141cc406Sopenharmony_ci if (c->bytes_to_read == 0) { 1304141cc406Sopenharmony_ci if (c->readBuffer) { 1305141cc406Sopenharmony_ci free(c->readBuffer); 1306141cc406Sopenharmony_ci c->readBuffer = NULL; 1307141cc406Sopenharmony_ci c->readPtr = NULL; 1308141cc406Sopenharmony_ci } 1309141cc406Sopenharmony_ci DMCCancel(c); 1310141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1311141cc406Sopenharmony_ci } 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci if (max_len == 0) { 1314141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1315141cc406Sopenharmony_ci } 1316141cc406Sopenharmony_ci 1317141cc406Sopenharmony_ci if (c->imageMode == IMAGE_SUPER_RES) { 1318141cc406Sopenharmony_ci /* We have to read *two* complete rows... */ 1319141cc406Sopenharmony_ci max_len = (max_len / (2*c->params.bytes_per_line)) * 1320141cc406Sopenharmony_ci (2*c->params.bytes_per_line); 1321141cc406Sopenharmony_ci /* If user is trying to read less than two complete lines, fail */ 1322141cc406Sopenharmony_ci if (max_len == 0) return SANE_STATUS_INVAL; 1323141cc406Sopenharmony_ci if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; 1324141cc406Sopenharmony_ci for (i=0; i<max_len; i += 2*c->params.bytes_per_line) { 1325141cc406Sopenharmony_ci c->bytes_to_read -= 2*c->params.bytes_per_line; 1326141cc406Sopenharmony_ci status = DMCReadTwoSuperResolutionLines(c, buf+i, 1327141cc406Sopenharmony_ci !c->bytes_to_read); 1328141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 1329141cc406Sopenharmony_ci } 1330141cc406Sopenharmony_ci *len = max_len; 1331141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1332141cc406Sopenharmony_ci } 1333141cc406Sopenharmony_ci 1334141cc406Sopenharmony_ci if (c->imageMode == IMAGE_MFI || c->imageMode == IMAGE_RAW) { 1335141cc406Sopenharmony_ci /* We have to read complete rows... */ 1336141cc406Sopenharmony_ci max_len = (max_len / c->params.bytes_per_line) * c->params.bytes_per_line; 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci /* If user is trying to read less than one complete row, fail */ 1339141cc406Sopenharmony_ci if (max_len == 0) return SANE_STATUS_INVAL; 1340141cc406Sopenharmony_ci if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; 1341141cc406Sopenharmony_ci c->bytes_to_read -= (unsigned int) max_len; 1342141cc406Sopenharmony_ci status = DMCRead(c->fd, 0x00, c->imageMode, buf, max_len, &size); 1343141cc406Sopenharmony_ci *len = size; 1344141cc406Sopenharmony_ci return status; 1345141cc406Sopenharmony_ci } 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; 1348141cc406Sopenharmony_ci if (c->readPtr) { 1349141cc406Sopenharmony_ci *len = max_len; 1350141cc406Sopenharmony_ci memcpy(buf, c->readPtr, max_len); 1351141cc406Sopenharmony_ci c->readPtr += max_len; 1352141cc406Sopenharmony_ci c->bytes_to_read -= max_len; 1353141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1354141cc406Sopenharmony_ci } 1355141cc406Sopenharmony_ci 1356141cc406Sopenharmony_ci /* Fill the read buffer completely */ 1357141cc406Sopenharmony_ci c->readBuffer = malloc(c->bytes_to_read); 1358141cc406Sopenharmony_ci if (!c->readBuffer) return SANE_STATUS_NO_MEM; 1359141cc406Sopenharmony_ci c->readPtr = c->readBuffer; 1360141cc406Sopenharmony_ci status = DMCRead(c->fd, 0x00, c->imageMode, (SANE_Byte *) c->readBuffer, 1361141cc406Sopenharmony_ci c->bytes_to_read, &size); 1362141cc406Sopenharmony_ci *len = size; 1363141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 1364141cc406Sopenharmony_ci if ((unsigned int) *len != c->bytes_to_read) return SANE_STATUS_IO_ERROR; 1365141cc406Sopenharmony_ci 1366141cc406Sopenharmony_ci /* Now copy */ 1367141cc406Sopenharmony_ci *len = max_len; 1368141cc406Sopenharmony_ci memcpy(buf, c->readPtr, max_len); 1369141cc406Sopenharmony_ci c->readPtr += max_len; 1370141cc406Sopenharmony_ci c->bytes_to_read -= max_len; 1371141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1372141cc406Sopenharmony_ci} 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci/********************************************************************** 1375141cc406Sopenharmony_ci//%FUNCTION: sane_cancel 1376141cc406Sopenharmony_ci//%ARGUMENTS: 1377141cc406Sopenharmony_ci// handle -- handle of device 1378141cc406Sopenharmony_ci//%RETURNS: 1379141cc406Sopenharmony_ci// Nothing 1380141cc406Sopenharmony_ci//%DESCRIPTION: 1381141cc406Sopenharmony_ci// A quick cancellation of the scane 1382141cc406Sopenharmony_ci// *********************************************************************/ 1383141cc406Sopenharmony_civoid 1384141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1385141cc406Sopenharmony_ci{ 1386141cc406Sopenharmony_ci DMC_Camera *c = ValidateHandle(handle); 1387141cc406Sopenharmony_ci if (!c) return; 1388141cc406Sopenharmony_ci 1389141cc406Sopenharmony_ci DMCCancel(c); 1390141cc406Sopenharmony_ci} 1391141cc406Sopenharmony_ci 1392141cc406Sopenharmony_ciSANE_Status 1393141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 1394141cc406Sopenharmony_ci{ 1395141cc406Sopenharmony_ci (void) handle; 1396141cc406Sopenharmony_ci (void) non_blocking; 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1399141cc406Sopenharmony_ci} 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ciSANE_Status 1402141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int *fd) 1403141cc406Sopenharmony_ci{ 1404141cc406Sopenharmony_ci (void) handle; 1405141cc406Sopenharmony_ci (void) fd; 1406141cc406Sopenharmony_ci 1407141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1408141cc406Sopenharmony_ci} 1409