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