1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1998 David F. Skoll
3    Heavily based on "hp.c" driver for HP Scanners, by
4    David Mosberger-Tang.
5 
6    This file is part of the SANE package.
7 
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21    As a special exception, the authors of SANE give permission for
22    additional uses of the libraries contained in this release of SANE.
23 
24    The exception is that, if you link a SANE library with other files
25    to produce an executable, this does not by itself cause the
26    resulting executable to be covered by the GNU General Public
27    License.  Your use of that executable is in no way restricted on
28    account of linking the SANE library code into it.
29 
30    This exception does not, however, invalidate any other reasons why
31    the executable file might be covered by the GNU General Public
32    License.
33 
34    If you submit changes to SANE to the maintainers to be included in
35    a subsequent release, you agree by submitting the changes that
36    those changes may be distributed with this exception intact.
37 
38    If you write modifications of your own for SANE, it is your choice
39    whether to permit this exception to apply to your modifications.
40    If you do not wish that, delete this exception notice.
41 
42    This file implements a SANE backend for the Polaroid Digital
43    Microscope Camera. */
44 
45 #include "../include/sane/config.h"
46 
47 #include <limits.h>
48 #include <stdlib.h>
49 #include <stdarg.h>
50 #include <string.h>
51 
52 #include "../include/_stdint.h"
53 
54 #include "../include/sane/sane.h"
55 #include "../include/sane/saneopts.h"
56 #include "../include/sane/sanei_scsi.h"
57 
58 #define BACKEND_NAME	dmc
59 #include "../include/sane/sanei_backend.h"
60 
61 #ifndef PATH_MAX
62 # define PATH_MAX	1024
63 #endif
64 
65 #include "../include/sane/sanei_config.h"
66 #define DMC_CONFIG_FILE "dmc.conf"
67 
68 #include "dmc.h"
69 
70 /* A linked-list of attached devices and handles */
71 static DMC_Device *FirstDevice = NULL;
72 static DMC_Camera *FirstHandle = NULL;
73 static int NumDevices = 0;
74 static SANE_Device const **devlist = NULL;
75 
76 static SANE_String_Const ValidModes[] = { "Full frame", "Viewfinder",
77 					  "Raw", "Thumbnail",
78 					  "Super-Resolution",
79 					  NULL };
80 
81 static SANE_String_Const ValidBalances[] = { "Daylight", "Incandescent",
82 					     "Fluorescent", NULL };
83 
84 static SANE_Word ValidASAs[] = { 3, 25, 50, 100 };
85 
86 /* Convert between 32-us ticks and milliseconds */
87 #define MS_TO_TICKS(x) (((x) * 1000 + 16) / 32)
88 #define TICKS_TO_MS(x) (((x) * 32) / 1000)
89 
90 /* Macros for stepping along the raw lines for super-resolution mode
91    They are very ugly because they handle boundary conditions at
92    the edges of the image.  Yuck... */
93 
94 #define PREV_RED(i) (((i)/3)*3)
95 #define NEXT_RED(i) (((i) >= BYTES_PER_RAW_LINE-3) ? BYTES_PER_RAW_LINE-3 : \
96 		     PREV_RED(i)+3)
97 #define PREV_GREEN(i) ((i)<1 ? 1 : PREV_RED((i)-1)+1)
98 #define NEXT_GREEN(i) ((i)<1 ? 1 : ((i) >= BYTES_PER_RAW_LINE-2) ? \
99 		       BYTES_PER_RAW_LINE-2 : PREV_GREEN(i)+3)
100 #define PREV_BLUE(i) ((i)<2 ? 2 : PREV_RED((i)-2)+2)
101 #define NEXT_BLUE(i) ((i)<2 ? 2 : ((i) >= BYTES_PER_RAW_LINE-1) ? \
102 		      BYTES_PER_RAW_LINE-1 : PREV_BLUE(i)+3)
103 
104 #define ADVANCE_COEFF(i) (((i)==1) ? 3 : (i)-1);
105 
106 /**********************************************************************
107 //%FUNCTION: DMCRead
108 //%ARGUMENTS:
109 // fd -- file descriptor
110 // typecode -- data type code
111 // qualifier -- data type qualifier
112 // maxlen -- transfer length
113 // buf -- buffer to store data in
114 // len -- set to actual length of data
115 //%RETURNS:
116 // A SANE status code
117 //%DESCRIPTION:
118 // Reads the particular data selected by typecode and qualifier
119 // *********************************************************************/
120 static SANE_Status
DMCRead(int fd, unsigned int typecode, unsigned int qualifier, SANE_Byte *buf, size_t maxlen, size_t *len)121 DMCRead(int fd, unsigned int typecode, unsigned int qualifier,
122 	SANE_Byte *buf, size_t maxlen, size_t *len)
123 {
124     uint8_t readCmd[10];
125     SANE_Status status;
126 
127     readCmd[0] = 0x28;
128     readCmd[1] = 0;
129     readCmd[2] = typecode;
130     readCmd[3] = 0;
131     readCmd[4] = (qualifier >> 8) & 0xFF;
132     readCmd[5] = qualifier & 0xFF;
133     readCmd[6] = (maxlen >> 16) & 0xFF;
134     readCmd[7] = (maxlen >> 8) & 0xFF;
135     readCmd[8] = maxlen & 0xFF;
136     readCmd[9] = 0;
137     DBG(3, "DMCRead: typecode=%x, qualifier=%x, maxlen=%lu\n",
138 	typecode, qualifier, (u_long) maxlen);
139 
140     *len = maxlen;
141     status = sanei_scsi_cmd(fd, readCmd, sizeof(readCmd), buf, len);
142     DBG(3, "DMCRead: Read %lu bytes\n", (u_long) *len);
143     return status;
144 }
145 
146 /**********************************************************************
147 //%FUNCTION: DMCWrite
148 //%ARGUMENTS:
149 // fd -- file descriptor
150 // typecode -- data type code
151 // qualifier -- data type qualifier
152 // maxlen -- transfer length
153 // buf -- buffer to store data in
154 //%RETURNS:
155 // A SANE status code
156 //%DESCRIPTION:
157 // Writes the particular data selected by typecode and qualifier
158 // *********************************************************************/
159 static SANE_Status
DMCWrite(int fd, unsigned int typecode, unsigned int qualifier, SANE_Byte *buf, size_t maxlen)160 DMCWrite(int fd, unsigned int typecode, unsigned int qualifier,
161 	SANE_Byte *buf, size_t maxlen)
162 {
163     uint8_t *writeCmd;
164     SANE_Status status;
165 
166     writeCmd = malloc(maxlen + 10);
167     if (!writeCmd) return SANE_STATUS_NO_MEM;
168 
169     writeCmd[0] = 0x2A;
170     writeCmd[1] = 0;
171     writeCmd[2] = typecode;
172     writeCmd[3] = 0;
173     writeCmd[4] = (qualifier >> 8) & 0xFF;
174     writeCmd[5] = qualifier & 0xFF;
175     writeCmd[6] = (maxlen >> 16) & 0xFF;
176     writeCmd[7] = (maxlen >> 8) & 0xFF;
177     writeCmd[8] = maxlen & 0xFF;
178     writeCmd[9] = 0;
179     memcpy(writeCmd+10, buf, maxlen);
180 
181     DBG(3, "DMCWrite: typecode=%x, qualifier=%x, maxlen=%lu\n",
182 	typecode, qualifier, (u_long) maxlen);
183 
184     status = sanei_scsi_cmd(fd, writeCmd, 10+maxlen, NULL, NULL);
185     free(writeCmd);
186     return status;
187 }
188 
189 /**********************************************************************
190 //%FUNCTION: DMCAttach
191 //%ARGUMENTS:
192 // devname -- name of device file to open
193 // devp -- a DMC_Device structure which we fill in if it's not NULL.
194 //%RETURNS:
195 // SANE_STATUS_GOOD -- We have a Polaroid DMC attached and all looks good.
196 // SANE_STATUS_INVAL -- There's a problem.
197 //%DESCRIPTION:
198 // Verifies that a Polaroid DMC is attached.  Sets up device options in
199 // DMC_Device structure.
200 // *********************************************************************/
201 #define INQ_LEN 255
202 static SANE_Status
DMCAttach(char const *devname, DMC_Device **devp)203 DMCAttach(char const *devname, DMC_Device **devp)
204 {
205     DMC_Device *dev;
206     SANE_Status status;
207     int fd;
208     size_t size;
209     char result[INQ_LEN];
210 
211     uint8_t exposureCalculationResults[16];
212     uint8_t userInterfaceSettings[16];
213 
214     static uint8_t const inquiry[] =
215     { 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00 };
216 
217     static uint8_t const test_unit_ready[] =
218     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
219 
220     static uint8_t const no_viewfinder[] =
221     { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
222 
223     /* If we're already attached, do nothing */
224 
225     for (dev = FirstDevice; dev; dev = dev->next) {
226 	if (!strcmp(dev->sane.name, devname)) {
227 	    if (devp) *devp = dev;
228 	    return SANE_STATUS_GOOD;
229 	}
230     }
231 
232     DBG(3, "DMCAttach: opening `%s'\n", devname);
233     status = sanei_scsi_open(devname, &fd, 0, 0);
234     if (status != SANE_STATUS_GOOD) {
235 	DBG(1, "DMCAttach: open failed (%s)\n", sane_strstatus(status));
236 	return status;
237     }
238 
239     DBG(3, "DMCAttach: sending INQUIRY\n");
240     size = sizeof(result);
241     status = sanei_scsi_cmd(fd, inquiry, sizeof(inquiry), result, &size);
242     if (status != SANE_STATUS_GOOD || size < 32) {
243 	if (status == SANE_STATUS_GOOD) status = SANE_STATUS_INVAL;
244 	DBG(1, "DMCAttach: inquiry failed (%s)\n", sane_strstatus(status));
245 	sanei_scsi_close(fd);
246 	return status;
247     }
248 
249     /* Verify that we have a Polaroid DMC */
250 
251     if (result[0] != 6 ||
252 	strncmp(result+8, "POLAROID", 8) ||
253 	strncmp(result+16, "DMC     ", 8)) {
254 	sanei_scsi_close(fd);
255 	DBG(1, "DMCAttach: Device does not look like a Polaroid DMC\n");
256 	return SANE_STATUS_INVAL;
257     }
258 
259     DBG(3, "DMCAttach: sending TEST_UNIT_READY\n");
260     status = sanei_scsi_cmd(fd, test_unit_ready, sizeof(test_unit_ready),
261 			    NULL, NULL);
262     if (status != SANE_STATUS_GOOD) {
263 	DBG(1, "DMCAttach: test unit ready failed (%s)\n",
264 	    sane_strstatus(status));
265 	sanei_scsi_close(fd);
266 	return status;
267     }
268 
269     /* Read current ASA and shutter speed settings */
270     status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults,
271 		     sizeof(exposureCalculationResults), &size);
272     if (status != SANE_STATUS_GOOD ||
273 	size < sizeof(exposureCalculationResults)) {
274 	DBG(1, "DMCAttach: Couldn't read exposure calculation results (%s)\n",
275 	    sane_strstatus(status));
276 	sanei_scsi_close(fd);
277 	if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR;
278 	return status;
279     }
280 
281     /* Read current white balance settings */
282     status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings,
283 		     sizeof(userInterfaceSettings), &size);
284     if (status != SANE_STATUS_GOOD ||
285 	size < sizeof(userInterfaceSettings)) {
286 	DBG(1, "DMCAttach: Couldn't read user interface settings (%s)\n",
287 	    sane_strstatus(status));
288 	sanei_scsi_close(fd);
289 	if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR;
290 	return status;
291     }
292 
293     /* Shut off viewfinder mode */
294     status = sanei_scsi_cmd(fd, no_viewfinder, sizeof(no_viewfinder),
295 			    NULL, NULL);
296     if (status != SANE_STATUS_GOOD) {
297 	sanei_scsi_close(fd);
298 	return status;
299     }
300     sanei_scsi_close(fd);
301 
302     DBG(3, "DMCAttach: Looks like we have a Polaroid DMC\n");
303 
304     dev = malloc(sizeof(*dev));
305     if (!dev) return SANE_STATUS_NO_MEM;
306     memset(dev, 0, sizeof(*dev));
307 
308     dev->sane.name = strdup(devname);
309     dev->sane.vendor = "Polaroid";
310     dev->sane.model = "DMC";
311     dev->sane.type = "still camera";
312     dev->next = FirstDevice;
313     dev->whiteBalance = userInterfaceSettings[5];
314     if (dev->whiteBalance > WHITE_BALANCE_FLUORESCENT) {
315 	dev->whiteBalance = WHITE_BALANCE_FLUORESCENT;
316     }
317 
318     /* Bright Eyes documentation gives these as shutter speed ranges (ms) */
319     /* dev->shutterSpeedRange.min = 8; */
320     /* dev->shutterSpeedRange.max = 320; */
321 
322     /* User's manual says these are shutter speed ranges (ms) */
323     dev->shutterSpeedRange.min = 8;
324     dev->shutterSpeedRange.max = 1000;
325     dev->shutterSpeedRange.quant = 2;
326     dev->shutterSpeed =
327 	(exposureCalculationResults[10] << 8) +
328 	exposureCalculationResults[11];
329 
330     /* Convert from ticks to ms */
331     dev->shutterSpeed = TICKS_TO_MS(dev->shutterSpeed);
332 
333     dev->asa = exposureCalculationResults[13];
334     if (dev->asa > ASA_100) dev->asa = ASA_100;
335     dev->asa = ValidASAs[dev->asa + 1];
336     FirstDevice = dev;
337     NumDevices++;
338     if (devp) *devp = dev;
339     return SANE_STATUS_GOOD;
340 }
341 
342 /**********************************************************************
343 //%FUNCTION: ValidateHandle
344 //%ARGUMENTS:
345 // handle -- a handle for an opened camera
346 //%RETURNS:
347 // A validated pointer to the camera or NULL if handle is not valid.
348 // *********************************************************************/
349 static DMC_Camera *
ValidateHandle(SANE_Handle handle)350 ValidateHandle(SANE_Handle handle)
351 {
352     DMC_Camera *c;
353     for (c = FirstHandle; c; c = c->next) {
354 	if (c == handle) return c;
355     }
356     DBG(1, "ValidateHandle: invalid handle %p\n", handle);
357     return NULL;
358 }
359 
360 /**********************************************************************
361 //%FUNCTION: DMCInitOptions
362 //%ARGUMENTS:
363 // c -- a DMC camera device
364 //%RETURNS:
365 // SANE_STATUS_GOOD -- OK
366 // SANE_STATUS_INVAL -- There's a problem.
367 //%DESCRIPTION:
368 // Initializes the options in the DMC_Camera structure
369 // *********************************************************************/
370 static SANE_Status
DMCInitOptions(DMC_Camera *c)371 DMCInitOptions(DMC_Camera *c)
372 {
373     int i;
374 
375     /* Image is initially 801x600 */
376     c->tl_x_range.min = 0;
377     c->tl_x_range.max = c->tl_x_range.min;
378     c->tl_x_range.quant = 1;
379     c->tl_y_range.min = 0;
380     c->tl_y_range.max = c->tl_y_range.min;
381     c->tl_y_range.quant = 1;
382 
383     c->br_x_range.min = 800;
384     c->br_x_range.max = c->br_x_range.min;
385     c->br_x_range.quant = 1;
386     c->br_y_range.min = 599;
387     c->br_y_range.max = c->br_y_range.min;
388     c->br_y_range.quant = 1;
389 
390     memset(c->opt, 0, sizeof(c->opt));
391     memset(c->val, 0, sizeof(c->val));
392 
393     for (i=0; i<NUM_OPTIONS; i++) {
394 	c->opt[i].type = SANE_TYPE_INT;
395 	c->opt[i].size = sizeof(SANE_Word);
396 	c->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
397 	c->opt[i].unit = SANE_UNIT_NONE;
398     }
399 
400     c->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
401     c->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
402     c->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
403     c->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
404     c->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
405     c->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE;
406     c->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
407 
408     c->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
409     c->opt[OPT_GEOMETRY_GROUP].name = "";
410     c->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
411     c->opt[OPT_GEOMETRY_GROUP].desc = "";
412     c->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
413     c->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
414 
415     /* top-left x */
416     c->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
417     c->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
418     c->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
419     c->opt[OPT_TL_X].type = SANE_TYPE_INT;
420     c->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
421     c->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
422     c->opt[OPT_TL_X].constraint.range = &c->tl_x_range;
423     c->val[OPT_TL_X].w = c->tl_x_range.min;
424 
425     /* top-left y */
426     c->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
427     c->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
428     c->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
429     c->opt[OPT_TL_Y].type = SANE_TYPE_INT;
430     c->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
431     c->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
432     c->opt[OPT_TL_Y].constraint.range = &c->tl_y_range;
433     c->val[OPT_TL_Y].w = c->tl_y_range.min;
434 
435     /* bottom-right x */
436     c->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
437     c->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
438     c->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
439     c->opt[OPT_BR_X].type = SANE_TYPE_INT;
440     c->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
441     c->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
442     c->opt[OPT_BR_X].constraint.range = &c->br_x_range;
443     c->val[OPT_BR_X].w = c->br_x_range.min;
444 
445     /* bottom-right y */
446     c->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
447     c->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
448     c->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
449     c->opt[OPT_BR_Y].type = SANE_TYPE_INT;
450     c->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
451     c->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
452     c->opt[OPT_BR_Y].constraint.range = &c->br_y_range;
453     c->val[OPT_BR_Y].w = c->br_y_range.min;
454 
455     c->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
456     c->opt[OPT_MODE_GROUP].name = "";
457     c->opt[OPT_MODE_GROUP].title = "Imaging Mode";
458     c->opt[OPT_MODE_GROUP].desc = "";
459     c->opt[OPT_MODE_GROUP].cap = SANE_CAP_ADVANCED;
460     c->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
461 
462     c->opt[OPT_IMAGE_MODE].name = "imagemode";
463     c->opt[OPT_IMAGE_MODE].title = "Image Mode";
464     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";
465     c->opt[OPT_IMAGE_MODE].type = SANE_TYPE_STRING;
466     c->opt[OPT_IMAGE_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
467     c->opt[OPT_IMAGE_MODE].constraint.string_list = ValidModes;
468     c->opt[OPT_IMAGE_MODE].size = 16;
469     c->val[OPT_IMAGE_MODE].s = "Full frame";
470 
471     c->opt[OPT_ASA].name = "asa";
472     c->opt[OPT_ASA].title = "ASA Setting";
473     c->opt[OPT_ASA].desc = "Equivalent ASA setting";
474     c->opt[OPT_ASA].constraint_type = SANE_CONSTRAINT_WORD_LIST;
475     c->opt[OPT_ASA].constraint.word_list = ValidASAs;
476     c->val[OPT_ASA].w = c->hw->asa;
477 
478     c->opt[OPT_SHUTTER_SPEED].name = "shutterspeed";
479     c->opt[OPT_SHUTTER_SPEED].title = "Shutter Speed (ms)";
480     c->opt[OPT_SHUTTER_SPEED].desc = "Shutter Speed in milliseconds";
481     c->opt[OPT_SHUTTER_SPEED].constraint_type = SANE_CONSTRAINT_RANGE;
482     c->opt[OPT_SHUTTER_SPEED].constraint.range = &c->hw->shutterSpeedRange;
483     c->val[OPT_SHUTTER_SPEED].w = c->hw->shutterSpeed;
484 
485     c->opt[OPT_WHITE_BALANCE].name = "whitebalance";
486     c->opt[OPT_WHITE_BALANCE].title = "White Balance";
487     c->opt[OPT_WHITE_BALANCE].desc = "Selects white balance";
488     c->opt[OPT_WHITE_BALANCE].type = SANE_TYPE_STRING;
489     c->opt[OPT_WHITE_BALANCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
490     c->opt[OPT_WHITE_BALANCE].constraint.string_list = ValidBalances;
491     c->opt[OPT_WHITE_BALANCE].size = 16;
492     c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[c->hw->whiteBalance];
493 
494     return SANE_STATUS_GOOD;
495 }
496 
497 /**********************************************************************
498 //%FUNCTION: DMCSetMode
499 //%ARGUMENTS:
500 // c -- a DMC camera device
501 // mode -- Imaging mode
502 //%RETURNS:
503 // SANE_STATUS_GOOD -- OK
504 // SANE_STATUS_INVAL -- There's a problem.
505 //%DESCRIPTION:
506 // Sets the camera's imaging mode.
507 // *********************************************************************/
508 static SANE_Status
DMCSetMode(DMC_Camera *c, int mode)509 DMCSetMode(DMC_Camera *c, int mode)
510 {
511   switch (mode)
512     {
513     case IMAGE_MFI:
514       c->tl_x_range.min = 0;
515       c->tl_x_range.max = 800;
516       c->tl_y_range.min = 0;
517       c->tl_y_range.max = 599;
518       c->br_x_range.min = c->tl_x_range.min;
519       c->br_x_range.max = c->tl_x_range.max;
520       c->br_y_range.min = c->tl_y_range.min;
521       c->br_y_range.max = c->tl_y_range.max;
522       break;
523 
524     case IMAGE_VIEWFINDER:
525       c->tl_x_range.min = 0;
526       c->tl_x_range.max = 269;
527       c->tl_y_range.min = 0;
528       c->tl_y_range.max = 200;
529       c->br_x_range.min = c->tl_x_range.min;
530       c->br_x_range.max = c->tl_x_range.max;
531       c->br_y_range.min = c->tl_y_range.min;
532       c->br_y_range.max = c->tl_y_range.max;
533       break;
534 
535     case IMAGE_RAW:
536       c->tl_x_range.min = 0;
537       c->tl_x_range.max = 1598;
538       c->tl_y_range.min = 0;
539       c->tl_y_range.max = 599;
540       c->br_x_range.min = c->tl_x_range.min;
541       c->br_x_range.max = c->tl_x_range.max;
542       c->br_y_range.min = c->tl_y_range.min;
543       c->br_y_range.max = c->tl_y_range.max;
544       break;
545 
546     case IMAGE_THUMB:
547       c->tl_x_range.min = 0;
548       c->tl_x_range.max = 79;
549       c->tl_y_range.min = 0;
550       c->tl_y_range.max = 59;
551       c->br_x_range.min = c->tl_x_range.min;
552       c->br_x_range.max = c->tl_x_range.max;
553       c->br_y_range.min = c->tl_y_range.min;
554       c->br_y_range.max = c->tl_y_range.max;
555       break;
556 
557     case IMAGE_SUPER_RES:
558       c->tl_x_range.min = 0;
559       c->tl_x_range.max = 1598;
560       c->tl_y_range.min = 0;
561       c->tl_y_range.max = 1199;
562       c->br_x_range.min = c->tl_x_range.min;
563       c->br_x_range.max = c->tl_x_range.max;
564       c->br_y_range.min = c->tl_y_range.min;
565       c->br_y_range.max = c->tl_y_range.max;
566       break;
567 
568     default:
569       return SANE_STATUS_INVAL;
570     }
571     c->imageMode = mode;
572     c->val[OPT_TL_X].w = c->tl_x_range.min;
573     c->val[OPT_TL_Y].w = c->tl_y_range.min;
574     c->val[OPT_BR_X].w = c->br_x_range.min;
575     c->val[OPT_BR_Y].w = c->br_y_range.min;
576     return SANE_STATUS_GOOD;
577 }
578 
579 /**********************************************************************
580 //%FUNCTION: DMCCancel
581 //%ARGUMENTS:
582 // c -- a DMC camera device
583 //%RETURNS:
584 // SANE_STATUS_CANCELLED
585 //%DESCRIPTION:
586 // Cancels DMC image acquisition
587 // *********************************************************************/
588 static SANE_Status
DMCCancel(DMC_Camera *c)589 DMCCancel(DMC_Camera *c)
590 {
591     if (c->fd >= 0) {
592 	sanei_scsi_close(c->fd);
593 	c->fd = -1;
594     }
595     return SANE_STATUS_CANCELLED;
596 }
597 
598 /**********************************************************************
599 //%FUNCTION: DMCSetASA
600 //%ARGUMENTS:
601 // fd -- SCSI file descriptor
602 // asa -- the ASA to set
603 //%RETURNS:
604 // A sane status value
605 //%DESCRIPTION:
606 // Sets the equivalent ASA setting of the camera.
607 // *********************************************************************/
608 static SANE_Status
DMCSetASA(int fd, unsigned int asa)609 DMCSetASA(int fd, unsigned int asa)
610 {
611     uint8_t exposureCalculationResults[16];
612     SANE_Status status;
613     size_t len;
614     int i;
615 
616     DBG(3, "DMCSetAsa: %d\n", asa);
617     for (i=1; i<=ASA_100+1; i++) {
618 	if (asa == (unsigned int) ValidASAs[i]) break;
619     }
620 
621     if (i > ASA_100+1) return SANE_STATUS_INVAL;
622 
623     status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults,
624 		     sizeof(exposureCalculationResults), &len);
625     if (status != SANE_STATUS_GOOD) return status;
626     if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR;
627 
628     exposureCalculationResults[13] = (uint8_t) i - 1;
629 
630     return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults,
631 		    sizeof(exposureCalculationResults));
632 }
633 
634 /**********************************************************************
635 //%FUNCTION: DMCSetWhiteBalance
636 //%ARGUMENTS:
637 // fd -- SCSI file descriptor
638 // mode -- white balance mode
639 //%RETURNS:
640 // A sane status value
641 //%DESCRIPTION:
642 // Sets the equivalent ASA setting of the camera.
643 // *********************************************************************/
644 static SANE_Status
DMCSetWhiteBalance(int fd, int mode)645 DMCSetWhiteBalance(int fd, int mode)
646 {
647     uint8_t userInterfaceSettings[16];
648     SANE_Status status;
649     size_t len;
650 
651     DBG(3, "DMCSetWhiteBalance: %d\n", mode);
652     status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings,
653 		     sizeof(userInterfaceSettings), &len);
654     if (status != SANE_STATUS_GOOD) return status;
655     if (len < sizeof(userInterfaceSettings)) return SANE_STATUS_IO_ERROR;
656 
657     userInterfaceSettings[5] = (uint8_t) mode;
658 
659     return DMCWrite(fd, 0x82, 0x0, userInterfaceSettings,
660 		    sizeof(userInterfaceSettings));
661 }
662 
663 /**********************************************************************
664 //%FUNCTION: DMCSetShutterSpeed
665 //%ARGUMENTS:
666 // fd -- SCSI file descriptor
667 // speed -- shutter speed in ms
668 //%RETURNS:
669 // A sane status value
670 //%DESCRIPTION:
671 // Sets the shutter speed of the camera
672 // *********************************************************************/
673 static SANE_Status
DMCSetShutterSpeed(int fd, unsigned int speed)674 DMCSetShutterSpeed(int fd, unsigned int speed)
675 {
676     uint8_t exposureCalculationResults[16];
677     SANE_Status status;
678     size_t len;
679 
680     DBG(3, "DMCSetShutterSpeed: %u\n", speed);
681     /* Convert from ms to ticks */
682     speed = MS_TO_TICKS(speed);
683 
684     status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults,
685 		     sizeof(exposureCalculationResults), &len);
686     if (status != SANE_STATUS_GOOD) return status;
687     if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR;
688 
689     exposureCalculationResults[10] = (speed >> 8) & 0xFF;
690     exposureCalculationResults[11] = speed & 0xFF;
691 
692     return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults,
693 		    sizeof(exposureCalculationResults));
694 }
695 
696 /**********************************************************************
697 //%FUNCTION: DMCReadTwoSuperResolutionLines
698 //%ARGUMENTS:
699 // c -- DMC Camera
700 // buf -- where to put output.
701 // lastLine -- if true, these are the last two lines in the super-resolution
702 //             image to read.
703 //%RETURNS:
704 // Nothing
705 //%DESCRIPTION:
706 // Reads a single "raw" line from the camera (if needed) and constructs
707 // two "super-resolution" output lines in "buf"
708 // *********************************************************************/
709 static SANE_Status
DMCReadTwoSuperResolutionLines(DMC_Camera *c, SANE_Byte *buf, int lastLine)710 DMCReadTwoSuperResolutionLines(DMC_Camera *c, SANE_Byte *buf, int lastLine)
711 {
712     SANE_Status status;
713     size_t len;
714 
715     SANE_Byte *output, *prev;
716     int redCoeff, greenCoeff, blueCoeff;
717     int red, green, blue;
718     int i;
719 
720     if (c->nextRawLineValid) {
721 	memcpy(c->currentRawLine, c->nextRawLine, BYTES_PER_RAW_LINE);
722     } else {
723 	status = DMCRead(c->fd, 0x00, IMAGE_RAW,
724 			 c->currentRawLine, BYTES_PER_RAW_LINE, &len);
725 	if (status != SANE_STATUS_GOOD) return status;
726     }
727     if (!lastLine) {
728 	status = DMCRead(c->fd, 0x00, IMAGE_RAW,
729 			 c->nextRawLine, BYTES_PER_RAW_LINE, &len);
730 	if (status != SANE_STATUS_GOOD) return status;
731 	c->nextRawLineValid = 1;
732     }
733 
734     redCoeff = 3;
735     greenCoeff = 1;
736     blueCoeff = 2;
737 
738     /* Do the first super-resolution line */
739     output = buf;
740     for (i=0; i<BYTES_PER_RAW_LINE; i++) {
741 	red = redCoeff * c->currentRawLine[PREV_RED(i)] +
742 	    (3-redCoeff) * c->currentRawLine[NEXT_RED(i)];
743 	green = greenCoeff * c->currentRawLine[PREV_GREEN(i)] +
744 	    (3-greenCoeff) * c->currentRawLine[NEXT_GREEN(i)];
745 	blue = blueCoeff * c->currentRawLine[PREV_BLUE(i)] +
746 	    (3-blueCoeff) * c->currentRawLine[NEXT_BLUE(i)];
747 	*output++ = red/3;
748 	*output++ = green/3;
749 	*output++ = blue/3;
750 	redCoeff = ADVANCE_COEFF(redCoeff);
751 	greenCoeff = ADVANCE_COEFF(greenCoeff);
752 	blueCoeff = ADVANCE_COEFF(blueCoeff);
753     }
754 
755     /* Do the next super-resolution line and interpolate vertically */
756     if (lastLine) {
757 	memcpy(buf+BYTES_PER_RAW_LINE*3, buf, BYTES_PER_RAW_LINE*3);
758 	return SANE_STATUS_GOOD;
759     }
760     redCoeff = 3;
761     greenCoeff = 1;
762     blueCoeff = 2;
763 
764     prev = buf;
765     for (i=0; i<BYTES_PER_RAW_LINE; i++) {
766 	red = redCoeff * c->nextRawLine[PREV_RED(i)] +
767 	    (3-redCoeff) * c->nextRawLine[NEXT_RED(i)];
768 	green = greenCoeff * c->nextRawLine[PREV_GREEN(i)] +
769 	    (3-greenCoeff) * c->nextRawLine[NEXT_GREEN(i)];
770 	blue = blueCoeff * c->nextRawLine[PREV_BLUE(i)] +
771 	    (3-blueCoeff) * c->nextRawLine[NEXT_BLUE(i)];
772 	*output++ = (red/3 + *prev++) / 2;
773 	*output++ = (green/3 + *prev++) / 2;
774 	*output++ = (blue/3 + *prev++) / 2;
775 	redCoeff = ADVANCE_COEFF(redCoeff);
776 	greenCoeff = ADVANCE_COEFF(greenCoeff);
777 	blueCoeff = ADVANCE_COEFF(blueCoeff);
778     }
779     return SANE_STATUS_GOOD;
780 }
781 
782 /***********************************************************************
783 //%FUNCTION: attach_one (static function)
784 //%ARGUMENTS:
785 // dev -- device to attach
786 //%RETURNS:
787 // SANE_STATUS_GOOD
788 //%DESCRIPTION:
789 // tries to attach a device found by sanei_config_attach_matching_devices
790 // *********************************************************************/
791 static SANE_Status
attach_one(const char *dev)792 attach_one (const char *dev)
793 {
794   DMCAttach (dev, 0);
795   return SANE_STATUS_GOOD;
796 }
797 
798 /**********************************************************************
799 //%FUNCTION: sane_init
800 //%ARGUMENTS:
801 // version_code -- pointer to where we stick our version code
802 // authorize -- authorization function
803 //%RETURNS:
804 // A sane status value
805 //%DESCRIPTION:
806 // Initializes DMC sane system.
807 // *********************************************************************/
808 SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize)809 sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize)
810 {
811     char dev_name[PATH_MAX];
812     size_t len;
813     FILE *fp;
814 
815     (void) authorize;
816 
817     DBG_INIT();
818     if (version_code) {
819 	*version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
820     }
821 
822     fp = sanei_config_open(DMC_CONFIG_FILE);
823     if (!fp) {
824 	/* default to /dev/camera instead of insisting on config file */
825 	if (DMCAttach ("/dev/camera", NULL) != SANE_STATUS_GOOD) {
826 	    /* OK, try /dev/scanner */
827 	    DMCAttach("/dev/scanner", NULL);
828 	}
829 	return SANE_STATUS_GOOD;
830     }
831 
832     while (sanei_config_read (dev_name, sizeof (dev_name), fp)) {
833 	if (dev_name[0] == '#')	{	/* ignore line comments */
834 	    continue;
835 	}
836 	len = strlen (dev_name);
837 
838 	if (!len) continue;			/* ignore empty lines */
839 
840 	sanei_config_attach_matching_devices(dev_name, attach_one);
841     }
842     fclose (fp);
843     return SANE_STATUS_GOOD;
844 }
845 
846 /**********************************************************************
847 //%FUNCTION: sane_exit
848 //%ARGUMENTS:
849 // None
850 //%RETURNS:
851 // Nothing
852 //%DESCRIPTION:
853 // Cleans up all the SANE information
854 // *********************************************************************/
855 void
sane_exit(void)856 sane_exit(void)
857 {
858     DMC_Device *dev, *next;
859 
860     /* Close all handles */
861     while(FirstHandle) {
862 	sane_close(FirstHandle);
863     }
864 
865     /* Free all devices */
866     dev = FirstDevice;
867     while(dev) {
868 	next = dev->next;
869 	free((char *) dev->sane.model);
870 	free(dev);
871 	dev = next;
872     }
873 
874     if (devlist)
875       free (devlist);
876 }
877 
878 /**********************************************************************
879 //%FUNCTION: sane_get_devices
880 //%ARGUMENTS:
881 // device_list -- set to allocated list of devices
882 // local_only -- ignored
883 //%RETURNS:
884 // A SANE status
885 //%DESCRIPTION:
886 // Returns a list of all known DMC devices
887 // *********************************************************************/
888 SANE_Status
sane_get_devices(SANE_Device const ***device_list, SANE_Bool local_only)889 sane_get_devices(SANE_Device const ***device_list, SANE_Bool local_only)
890 {
891     DMC_Device *dev;
892     int i = 0;
893 
894     (void) local_only;
895 
896     if (devlist) free(devlist);
897     devlist = malloc((NumDevices+1) * sizeof(devlist[0]));
898     if (!devlist) return SANE_STATUS_NO_MEM;
899 
900     for (dev=FirstDevice; dev; dev = dev->next) {
901 	devlist[i++] = &dev->sane;
902     }
903     devlist[i] = NULL;
904 
905     if (device_list) *device_list = devlist;
906 
907     return SANE_STATUS_GOOD;
908 }
909 
910 /**********************************************************************
911 //%FUNCTION: sane_open
912 //%ARGUMENTS:
913 // name -- name of device to open
914 // handle -- set to a handle for the opened device
915 //%RETURNS:
916 // A SANE status
917 //%DESCRIPTION:
918 // Opens a DMC camera device
919 // *********************************************************************/
920 SANE_Status
sane_open(SANE_String_Const name, SANE_Handle *handle)921 sane_open(SANE_String_Const name, SANE_Handle *handle)
922 {
923     SANE_Status status;
924     DMC_Device *dev;
925     DMC_Camera *c;
926 
927     /* If we're given a device name, search for it */
928     if (*name) {
929 	for (dev = FirstDevice; dev; dev = dev->next) {
930 	    if (!strcmp(dev->sane.name, name)) {
931 		break;
932 	    }
933 	}
934 	if (!dev) {
935 	    status = DMCAttach(name, &dev);
936 	    if (status != SANE_STATUS_GOOD) return status;
937 	}
938     } else {
939 	dev = FirstDevice;
940     }
941 
942     if (!dev) return SANE_STATUS_INVAL;
943 
944     c = malloc(sizeof(*c));
945     if (!c) return SANE_STATUS_NO_MEM;
946 
947     memset(c, 0, sizeof(*c));
948 
949     c->fd = -1;
950     c->hw = dev;
951     c->readBuffer = NULL;
952     c->readPtr = NULL;
953     c->imageMode = IMAGE_MFI;
954     c->inViewfinderMode = 0;
955     c->nextRawLineValid = 0;
956 
957     DMCInitOptions(c);
958 
959     c->next = FirstHandle;
960     FirstHandle = c;
961     if (handle) *handle = c;
962     return SANE_STATUS_GOOD;
963 }
964 
965 /**********************************************************************
966 //%FUNCTION: sane_close
967 //%ARGUMENTS:
968 // handle -- handle of device to close
969 //%RETURNS:
970 // A SANE status
971 //%DESCRIPTION:
972 // Closes a DMC camera device
973 // *********************************************************************/
974 void
sane_close(SANE_Handle handle)975 sane_close(SANE_Handle handle)
976 {
977     DMC_Camera *prev, *c;
978     prev = NULL;
979     for (c = FirstHandle; c; c = c->next) {
980 	if (c == handle) break;
981 	prev = c;
982     }
983     if (!c) {
984 	DBG(1, "close: invalid handle %p\n", handle);
985 	return;
986     }
987     DMCCancel(c);
988 
989     if (prev) prev->next = c->next;
990     else FirstHandle = c->next;
991 
992     if (c->readBuffer) {
993 	free(c->readBuffer);
994     }
995     free(c);
996 }
997 
998 /**********************************************************************
999 //%FUNCTION: sane_get_option_descriptor
1000 //%ARGUMENTS:
1001 // handle -- handle of device
1002 // option -- option number to retrieve
1003 //%RETURNS:
1004 // An option descriptor or NULL on error
1005 // *********************************************************************/
1006 SANE_Option_Descriptor const *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)1007 sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
1008 {
1009     DMC_Camera *c = ValidateHandle(handle);
1010     if (!c) return NULL;
1011 
1012     if ((unsigned) option >= NUM_OPTIONS) return NULL;
1013     return c->opt + option;
1014 }
1015 
1016 /**********************************************************************
1017 //%FUNCTION: sane_control_option
1018 //%ARGUMENTS:
1019 // handle -- handle of device
1020 // option -- option number to retrieve
1021 // action -- what to do with the option
1022 // val -- value to set option to
1023 // info -- returned info flags
1024 //%RETURNS:
1025 // SANE status
1026 //%DESCRIPTION:
1027 // Sets or queries option values
1028 // *********************************************************************/
1029 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info)1030 sane_control_option(SANE_Handle handle, SANE_Int option,
1031 		    SANE_Action action, void *val, SANE_Int *info)
1032 {
1033     DMC_Camera *c;
1034     SANE_Word cap;
1035     int i;
1036 
1037     if (info) *info = 0;
1038 
1039     c = ValidateHandle(handle);
1040     if (!c) return SANE_STATUS_INVAL;
1041 
1042     if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY;
1043 
1044     if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL;
1045 
1046     cap = c->opt[option].cap;
1047     if (!SANE_OPTION_IS_ACTIVE(cap)) return SANE_STATUS_INVAL;
1048 
1049     if (action == SANE_ACTION_GET_VALUE) {
1050 	switch(c->opt[option].type) {
1051 	case SANE_TYPE_INT:
1052 	    * (SANE_Int *) val = c->val[option].w;
1053 	    return SANE_STATUS_GOOD;
1054 
1055 	case SANE_TYPE_STRING:
1056 	    strcpy(val, c->val[option].s);
1057 	    return SANE_STATUS_GOOD;
1058 
1059 	default:
1060 	    DBG(3, "impossible option type!\n");
1061 	    return SANE_STATUS_INVAL;
1062 	}
1063     }
1064 
1065     if (action == SANE_ACTION_SET_AUTO) {
1066 	return SANE_STATUS_UNSUPPORTED;
1067     }
1068 
1069     switch(option) {
1070     case OPT_IMAGE_MODE:
1071 	for (i=0; i<NUM_IMAGE_MODES; i++) {
1072 	    if (!strcmp(val, ValidModes[i])) {
1073 		DMCSetMode(c, i);
1074 		c->val[OPT_IMAGE_MODE].s = (SANE_String) ValidModes[i];
1075 		if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1076 		return SANE_STATUS_GOOD;
1077 	    }
1078 	}
1079 	break;
1080     case OPT_WHITE_BALANCE:
1081 	for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) {
1082 	    if (!strcmp(val, ValidBalances[i])) {
1083 		c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[i];
1084 		return SANE_STATUS_GOOD;
1085 	    }
1086 	}
1087 	break;
1088     case OPT_ASA:
1089 	for (i=1; i<= ASA_100+1; i++) {
1090 	    if (* ((SANE_Int *) val) == ValidASAs[i]) {
1091 		c->val[OPT_ASA].w = ValidASAs[i];
1092 		return SANE_STATUS_GOOD;
1093 	    }
1094 	}
1095 	break;
1096     case OPT_SHUTTER_SPEED:
1097 	if (* (SANE_Int *) val < c->hw->shutterSpeedRange.min ||
1098 	    * (SANE_Int *) val > c->hw->shutterSpeedRange.max) {
1099 	    return SANE_STATUS_INVAL;
1100 	}
1101 	c->val[OPT_SHUTTER_SPEED].w = * (SANE_Int *) val;
1102 	/* Do any roundoff */
1103 	c->val[OPT_SHUTTER_SPEED].w =
1104 	    TICKS_TO_MS(MS_TO_TICKS(c->val[OPT_SHUTTER_SPEED].w));
1105 	if (c->val[OPT_SHUTTER_SPEED].w != * (SANE_Int *) val) {
1106 	    if (info) *info |= SANE_INFO_INEXACT;
1107 	}
1108 
1109 	return SANE_STATUS_GOOD;
1110 
1111     default:
1112 	/* Should really be INVAL, but just bit-bucket set requests... */
1113 	return SANE_STATUS_GOOD;
1114     }
1115 
1116     return SANE_STATUS_INVAL;
1117 }
1118 
1119 /**********************************************************************
1120 //%FUNCTION: sane_get_parameters
1121 //%ARGUMENTS:
1122 // handle -- handle of device
1123 // params -- set to device parameters
1124 //%RETURNS:
1125 // SANE status
1126 //%DESCRIPTION:
1127 // Returns parameters for current or next image.
1128 // *********************************************************************/
1129 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)1130 sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
1131 {
1132     DMC_Camera *c = ValidateHandle(handle);
1133     if (!c) return SANE_STATUS_INVAL;
1134 
1135     if (c->fd < 0) {
1136 	int width, height;
1137 	memset(&c->params, 0, sizeof(c->params));
1138 
1139 	width = c->val[OPT_BR_X].w - c->val[OPT_TL_X].w;
1140 	height = c->val[OPT_BR_Y].w - c->val[OPT_TL_Y].w;
1141 	c->params.pixels_per_line = width + 1;
1142 	c->params.lines = height+1;
1143 	c->params.depth = 8;
1144 	c->params.last_frame = SANE_TRUE;
1145 	switch(c->imageMode) {
1146 	case IMAGE_SUPER_RES:
1147 	case IMAGE_MFI:
1148 	case IMAGE_THUMB:
1149 	    c->params.format = SANE_FRAME_RGB;
1150 	    c->params.bytes_per_line = c->params.pixels_per_line * 3;
1151 	    break;
1152 	case IMAGE_RAW:
1153 	case IMAGE_VIEWFINDER:
1154 	    c->params.format = SANE_FRAME_GRAY;
1155 	    c->params.bytes_per_line = c->params.pixels_per_line;
1156 	    break;
1157 	}
1158     }
1159     if (params) *params = c->params;
1160     return SANE_STATUS_GOOD;
1161 }
1162 
1163 /**********************************************************************
1164 //%FUNCTION: sane_start
1165 //%ARGUMENTS:
1166 // handle -- handle of device
1167 //%RETURNS:
1168 // SANE status
1169 //%DESCRIPTION:
1170 // Starts acquisition
1171 // *********************************************************************/
1172 SANE_Status
sane_start(SANE_Handle handle)1173 sane_start(SANE_Handle handle)
1174 {
1175     static uint8_t const acquire[] =
1176     { 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1177 
1178     static uint8_t const viewfinder[] =
1179     { 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1180 
1181     static uint8_t const no_viewfinder[] =
1182     { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1183 
1184     DMC_Camera *c = ValidateHandle(handle);
1185     SANE_Status status;
1186     int i;
1187 
1188     if (!c) return SANE_STATUS_INVAL;
1189 
1190     /* If we're already open, barf -- not sure this is the best status */
1191     if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY;
1192 
1193     /* Get rid of old read buffers */
1194     if (c->readBuffer) {
1195 	free(c->readBuffer);
1196 	c->readBuffer = NULL;
1197 	c->readPtr = NULL;
1198     }
1199 
1200     c->nextRawLineValid = 0;
1201 
1202     /* Refresh parameter list */
1203     status = sane_get_parameters(c, NULL);
1204     if (status != SANE_STATUS_GOOD) return status;
1205 
1206     status = sanei_scsi_open(c->hw->sane.name, &c->fd, NULL, NULL);
1207     if (status != SANE_STATUS_GOOD) {
1208 	c->fd = -1;
1209 	DBG(1, "DMC: Open of `%s' failed: %s\n",
1210 	    c->hw->sane.name, sane_strstatus(status));
1211 	return status;
1212     }
1213 
1214     /* Set ASA and shutter speed if they're no longer current */
1215     if (c->val[OPT_ASA].w != c->hw->asa) {
1216 	status = DMCSetASA(c->fd, c->val[OPT_ASA].w);
1217 	if (status != SANE_STATUS_GOOD) {
1218 	    DMCCancel(c);
1219 	    return status;
1220 	}
1221 	c->hw->asa = c->val[OPT_ASA].w;
1222     }
1223 
1224     if ((unsigned int) c->val[OPT_SHUTTER_SPEED].w != c->hw->shutterSpeed) {
1225 	status = DMCSetShutterSpeed(c->fd, c->val[OPT_SHUTTER_SPEED].w);
1226 	if (status != SANE_STATUS_GOOD) {
1227 	    DMCCancel(c);
1228 	    return status;
1229 	}
1230 	c->hw->shutterSpeed = c->val[OPT_SHUTTER_SPEED].w;
1231     }
1232 
1233     /* Set white balance mode if needed */
1234     for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) {
1235 	if (!strcmp(ValidBalances[i], c->val[OPT_WHITE_BALANCE].s)) {
1236 	    if (i != c->hw->whiteBalance) {
1237 		status = DMCSetWhiteBalance(c->fd, i);
1238 		if (status != SANE_STATUS_GOOD) {
1239 		    DMCCancel(c);
1240 		    return status;
1241 		}
1242 		c->hw->whiteBalance = i;
1243 	    }
1244 	}
1245     }
1246 
1247     /* Flip into viewfinder mode if needed */
1248     if (c->imageMode == IMAGE_VIEWFINDER && !c->inViewfinderMode) {
1249 	status = sanei_scsi_cmd(c->fd, viewfinder, sizeof(viewfinder),
1250 				NULL, NULL);
1251 	if (status != SANE_STATUS_GOOD) {
1252 	    DMCCancel(c);
1253 	    return status;
1254 	}
1255 	c->inViewfinderMode = 1;
1256     }
1257 
1258     /* Flip out of viewfinder mode if needed */
1259     if (c->imageMode != IMAGE_VIEWFINDER && c->inViewfinderMode) {
1260 	status = sanei_scsi_cmd(c->fd, no_viewfinder, sizeof(no_viewfinder),
1261 				NULL, NULL);
1262 	if (status != SANE_STATUS_GOOD) {
1263 	    DMCCancel(c);
1264 	    return status;
1265 	}
1266 	c->inViewfinderMode = 0;
1267     }
1268 
1269 
1270     status = sanei_scsi_cmd(c->fd, acquire, sizeof(acquire), NULL, NULL);
1271     if (status != SANE_STATUS_GOOD) {
1272 	DMCCancel(c);
1273 	return status;
1274     }
1275     c->bytes_to_read = c->params.bytes_per_line * c->params.lines;
1276     return SANE_STATUS_GOOD;
1277 }
1278 
1279 /**********************************************************************
1280 //%FUNCTION: sane_read
1281 //%ARGUMENTS:
1282 // handle -- handle of device
1283 // buf -- destination for data
1284 // max_len -- maximum amount of data to store
1285 // len -- set to actual amount of data stored.
1286 //%RETURNS:
1287 // SANE status
1288 //%DESCRIPTION:
1289 // Reads image data from the camera
1290 // *********************************************************************/
1291 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len)1292 sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len)
1293 {
1294     SANE_Status status;
1295     DMC_Camera *c = ValidateHandle(handle);
1296     size_t size;
1297     SANE_Int i;
1298 
1299     if (!c) return SANE_STATUS_INVAL;
1300 
1301     if (c->fd < 0) return SANE_STATUS_INVAL;
1302 
1303     if (c->bytes_to_read == 0) {
1304 	if (c->readBuffer) {
1305 	    free(c->readBuffer);
1306 	    c->readBuffer = NULL;
1307 	    c->readPtr = NULL;
1308 	}
1309 	DMCCancel(c);
1310 	return SANE_STATUS_EOF;
1311     }
1312 
1313     if (max_len == 0) {
1314 	return SANE_STATUS_GOOD;
1315     }
1316 
1317     if (c->imageMode == IMAGE_SUPER_RES) {
1318 	/* We have to read *two* complete rows... */
1319 	max_len = (max_len / (2*c->params.bytes_per_line)) *
1320 	    (2*c->params.bytes_per_line);
1321 	/* If user is trying to read less than two complete lines, fail */
1322 	if (max_len == 0) return SANE_STATUS_INVAL;
1323 	if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read;
1324 	for (i=0; i<max_len; i += 2*c->params.bytes_per_line) {
1325 	    c->bytes_to_read -= 2*c->params.bytes_per_line;
1326 	    status = DMCReadTwoSuperResolutionLines(c, buf+i,
1327 						    !c->bytes_to_read);
1328 	    if (status != SANE_STATUS_GOOD) return status;
1329 	}
1330 	*len = max_len;
1331 	return SANE_STATUS_GOOD;
1332     }
1333 
1334     if (c->imageMode == IMAGE_MFI || c->imageMode == IMAGE_RAW) {
1335 	/* We have to read complete rows... */
1336 	max_len = (max_len / c->params.bytes_per_line) * c->params.bytes_per_line;
1337 
1338 	/* If user is trying to read less than one complete row, fail */
1339 	if (max_len == 0) return SANE_STATUS_INVAL;
1340 	if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read;
1341 	c->bytes_to_read -= (unsigned int) max_len;
1342 	status = DMCRead(c->fd, 0x00, c->imageMode, buf, max_len, &size);
1343 	*len = size;
1344 	return status;
1345     }
1346 
1347     if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read;
1348     if (c->readPtr) {
1349 	*len = max_len;
1350 	memcpy(buf, c->readPtr, max_len);
1351 	c->readPtr += max_len;
1352 	c->bytes_to_read -= max_len;
1353 	return SANE_STATUS_GOOD;
1354     }
1355 
1356     /* Fill the read buffer completely */
1357     c->readBuffer = malloc(c->bytes_to_read);
1358     if (!c->readBuffer) return SANE_STATUS_NO_MEM;
1359     c->readPtr = c->readBuffer;
1360     status = DMCRead(c->fd, 0x00, c->imageMode, (SANE_Byte *) c->readBuffer,
1361 		     c->bytes_to_read, &size);
1362     *len = size;
1363     if (status != SANE_STATUS_GOOD) return status;
1364     if ((unsigned int) *len != c->bytes_to_read) return SANE_STATUS_IO_ERROR;
1365 
1366     /* Now copy */
1367     *len = max_len;
1368     memcpy(buf, c->readPtr, max_len);
1369     c->readPtr += max_len;
1370     c->bytes_to_read -= max_len;
1371     return SANE_STATUS_GOOD;
1372 }
1373 
1374 /**********************************************************************
1375 //%FUNCTION: sane_cancel
1376 //%ARGUMENTS:
1377 // handle -- handle of device
1378 //%RETURNS:
1379 // Nothing
1380 //%DESCRIPTION:
1381 // A quick cancellation of the scane
1382 // *********************************************************************/
1383 void
sane_cancel(SANE_Handle handle)1384 sane_cancel (SANE_Handle handle)
1385 {
1386     DMC_Camera *c = ValidateHandle(handle);
1387     if (!c) return;
1388 
1389     DMCCancel(c);
1390 }
1391 
1392 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)1393 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1394 {
1395   (void) handle;
1396   (void) non_blocking;
1397 
1398   return SANE_STATUS_UNSUPPORTED;
1399 }
1400 
1401 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int *fd)1402 sane_get_select_fd (SANE_Handle handle, SANE_Int *fd)
1403 {
1404   (void) handle;
1405   (void) fd;
1406 
1407   return SANE_STATUS_UNSUPPORTED;
1408 }
1409