| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | /* sane - Scanner Access Now Easy.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    ScanMaker 3840 Backend | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |    Copyright (C) 2005-7 Earle F. Philhower, III | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |    earle@ziplabel.com - http://www.ziplabel.com
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU General Public License as | 
					
						
							|  |  |  |    published by the Free Software Foundation; either version 2 of the | 
					
						
							|  |  |  |    License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |    General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 
					
						
							|  |  |  |    MA 02111-1307, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    As a special exception, the authors of SANE give permission for | 
					
						
							|  |  |  |    additional uses of the libraries contained in this release of SANE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The exception is that, if you link a SANE library with other files | 
					
						
							|  |  |  |    to produce an executable, this does not by itself cause the | 
					
						
							|  |  |  |    resulting executable to be covered by the GNU General Public | 
					
						
							|  |  |  |    License.  Your use of that executable is in no way restricted on | 
					
						
							|  |  |  |    account of linking the SANE library code into it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This exception does not, however, invalidate any other reasons why | 
					
						
							|  |  |  |    the executable file might be covered by the GNU General Public | 
					
						
							|  |  |  |    License. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    If you submit changes to SANE to the maintainers to be included in | 
					
						
							|  |  |  |    a subsequent release, you agree by submitting the changes that | 
					
						
							|  |  |  |    those changes may be distributed with this exception intact. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    If you write modifications of your own for SANE, it is your choice | 
					
						
							|  |  |  |    whether to permit this exception to apply to your modifications. | 
					
						
							|  |  |  |    If you do not wish that, delete this exception notice. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../include/sane/config.h"
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <limits.h>
 | 
					
						
							|  |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../include/sane/sane.h"
 | 
					
						
							|  |  |  | #include "../include/sane/saneopts.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BACKENDNAME sm3840
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_backend.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_usb.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "sm3840.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "sm3840_scan.c"
 | 
					
						
							|  |  |  | #include "sm3840_lib.c"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static double sm3840_unit_convert (SANE_Int val); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int num_devices; | 
					
						
							|  |  |  | static SM3840_Device *first_dev; | 
					
						
							|  |  |  | static SM3840_Scan *first_handle; | 
					
						
							|  |  |  | static const SANE_Device **devlist = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_String_Const mode_list[] = { | 
					
						
							| 
									
										
										
										
											2010-02-11 04:48:21 +00:00
										 |  |  |   SANE_VALUE_SCAN_MODE_GRAY, | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_COLOR, | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_LINEART, | 
					
						
							|  |  |  |   SANE_VALUE_SCAN_MODE_HALFTONE, | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |   0 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Word resolution_list[] = { | 
					
						
							|  |  |  |   4, 1200, 600, 300, 150 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Word bpp_list[] = { | 
					
						
							|  |  |  |   2, 8, 16 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range x_range = { | 
					
						
							|  |  |  |   SANE_FIX (0), | 
					
						
							|  |  |  |   SANE_FIX (215.91),		/* 8.5 inches */ | 
					
						
							|  |  |  |   SANE_FIX (0) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range y_range = { | 
					
						
							|  |  |  |   SANE_FIX (0), | 
					
						
							|  |  |  |   SANE_FIX (297.19),		/* 11.7 inches */ | 
					
						
							|  |  |  |   SANE_FIX (0) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range brightness_range = { | 
					
						
							|  |  |  |   1, | 
					
						
							|  |  |  |   4096, | 
					
						
							|  |  |  |   1.0 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range contrast_range = { | 
					
						
							|  |  |  |   SANE_FIX (0.1), | 
					
						
							|  |  |  |   SANE_FIX (9.9), | 
					
						
							|  |  |  |   SANE_FIX (0.1) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SANE_Range lamp_range = { | 
					
						
							|  |  |  |   1, | 
					
						
							|  |  |  |   15, | 
					
						
							|  |  |  |   1 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | static const SANE_Range threshold_range = { | 
					
						
							|  |  |  |   0, | 
					
						
							|  |  |  |   255, | 
					
						
							|  |  |  |   1 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | min (int a, int b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (a < b) | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, | 
					
						
							|  |  |  | 	   SANE_Int * len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   unsigned char c, d; | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   DBG (2, "+sane-read:%p %p %d %p\n", (unsigned char *) s, buf, max_len, | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |        (unsigned char *) len); | 
					
						
							|  |  |  |   DBG (2, | 
					
						
							| 
									
										
										
										
											2008-02-03 10:34:20 +00:00
										 |  |  |        "+sane-read:remain:%lu offset:%lu linesleft:%d linebuff:%p linesread:%d\n", | 
					
						
							|  |  |  |        (u_long)s->remaining, (u_long)s->offset, s->linesleft, s->line_buffer, s->linesread); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!s->scanning) | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!s->remaining) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!s->linesleft) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  *len = 0; | 
					
						
							|  |  |  | 	  s->scanning = 0; | 
					
						
							|  |  |  | 	  /* Move to home position */ | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  | 	  reset_scanner ((p_usb_dev_handle)s->udev); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 	  /* Send lamp timeout */ | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  | 	  set_lamp_timer ((p_usb_dev_handle)s->udev, s->sm3840_params.lamp); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  /* Free memory */ | 
					
						
							|  |  |  | 	  if (s->save_scan_line) | 
					
						
							|  |  |  | 	    free (s->save_scan_line); | 
					
						
							|  |  |  | 	  s->save_scan_line = NULL; | 
					
						
							|  |  |  | 	  if (s->save_dpi1200_remap) | 
					
						
							|  |  |  | 	    free (s->save_dpi1200_remap); | 
					
						
							|  |  |  | 	  s->save_dpi1200_remap = NULL; | 
					
						
							|  |  |  | 	  if (s->save_color_remap) | 
					
						
							|  |  |  | 	    free (s->save_color_remap); | 
					
						
							|  |  |  | 	  s->save_color_remap = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  return SANE_STATUS_EOF; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       record_line ((s->linesread == 0) ? 1 : 0, | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  | 		   (p_usb_dev_handle) s->udev, | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 		   s->line_buffer, | 
					
						
							|  |  |  | 		   s->sm3840_params.dpi, | 
					
						
							|  |  |  | 		   s->sm3840_params.scanpix, | 
					
						
							|  |  |  | 		   s->sm3840_params.gray, | 
					
						
							|  |  |  | 		   (s->sm3840_params.bpp == 16) ? 1 : 0, | 
					
						
							|  |  |  | 		   &s->save_i, | 
					
						
							|  |  |  | 		   &s->save_scan_line, | 
					
						
							|  |  |  | 		   &s->save_dpi1200_remap, &s->save_color_remap); | 
					
						
							|  |  |  |       s->remaining = s->sm3840_params.linelen; | 
					
						
							|  |  |  |       s->offset = 0; | 
					
						
							|  |  |  |       s->linesread++; | 
					
						
							|  |  |  |       s->linesleft--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   /* Need to software emulate 1-bpp modes, simple threshold and error */ | 
					
						
							|  |  |  |   /* diffusion dither implemented. */ | 
					
						
							|  |  |  |   if (s->sm3840_params.lineart || s->sm3840_params.halftone) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       d = 0; | 
					
						
							|  |  |  |       for (i = 0; i < min (max_len * 8, s->remaining); i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  d = d << 1; | 
					
						
							|  |  |  | 	  if (s->sm3840_params.halftone) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      c = (*(unsigned char *) (s->offset + s->line_buffer + i)); | 
					
						
							|  |  |  | 	      if (c + s->save_dither_err < 128) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  d |= 1; | 
					
						
							|  |  |  | 		  s->save_dither_err += c; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  s->save_dither_err += c - 255; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if ((*(unsigned char *) (s->offset + s->line_buffer + i)) < s->threshold ) | 
					
						
							|  |  |  | 		d |= 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  if (i % 8 == 7) | 
					
						
							|  |  |  | 	    *(buf++) = d; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       *len = i / 8; | 
					
						
							|  |  |  |       s->offset += i; | 
					
						
							|  |  |  |       s->remaining -= i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       memcpy (buf, s->offset + s->line_buffer, min (max_len, s->remaining)); | 
					
						
							|  |  |  |       *len = min (max_len, s->remaining); | 
					
						
							|  |  |  |       s->offset += min (max_len, s->remaining); | 
					
						
							|  |  |  |       s->remaining -= min (max_len, s->remaining); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "-sane_read\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_cancel (SANE_Handle h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "trying to cancel...\n"); | 
					
						
							|  |  |  |   if (s->scanning) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!s->cancelled) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* Move to home position */ | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  | 	  reset_scanner ((p_usb_dev_handle) s->udev); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 	  /* Send lamp timeout */ | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  | 	  set_lamp_timer ((p_usb_dev_handle) s->udev, s->sm3840_params.lamp); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  /* Free memory */ | 
					
						
							|  |  |  | 	  if (s->save_scan_line) | 
					
						
							|  |  |  | 	    free (s->save_scan_line); | 
					
						
							|  |  |  | 	  s->save_scan_line = NULL; | 
					
						
							|  |  |  | 	  if (s->save_dpi1200_remap) | 
					
						
							|  |  |  | 	    free (s->save_dpi1200_remap); | 
					
						
							|  |  |  | 	  s->save_dpi1200_remap = NULL; | 
					
						
							|  |  |  | 	  if (s->save_color_remap) | 
					
						
							|  |  |  | 	    free (s->save_color_remap); | 
					
						
							|  |  |  | 	  s->save_color_remap = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  s->scanning = 0; | 
					
						
							|  |  |  | 	  s->cancelled = SANE_TRUE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_start (SANE_Handle handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* First make sure we have a current parameter set.  Some of the
 | 
					
						
							|  |  |  |    * parameters will be overwritten below, but that's OK.  */ | 
					
						
							|  |  |  |   DBG (2, "sane_start\n"); | 
					
						
							|  |  |  |   status = sane_get_parameters (s, 0); | 
					
						
							|  |  |  |   if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  |     return status; | 
					
						
							|  |  |  |   DBG (1, "Got params again...\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->scanning = SANE_TRUE; | 
					
						
							|  |  |  |   s->cancelled = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->line_buffer = malloc (s->sm3840_params.linelen); | 
					
						
							|  |  |  |   s->remaining = 0; | 
					
						
							|  |  |  |   s->offset = 0; | 
					
						
							|  |  |  |   s->linesleft = s->sm3840_params.scanlines; | 
					
						
							|  |  |  |   s->linesread = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->save_i = 0; | 
					
						
							|  |  |  |   s->save_scan_line = NULL; | 
					
						
							|  |  |  |   s->save_dpi1200_remap = NULL; | 
					
						
							|  |  |  |   s->save_color_remap = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   s->save_dither_err = 0; | 
					
						
							|  |  |  |   s->threshold = s->sm3840_params.threshold; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-06 01:37:36 +00:00
										 |  |  |   setup_scan ((p_usb_dev_handle) s->udev, &(s->sm3840_params)); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static double | 
					
						
							|  |  |  | sm3840_unit_convert (SANE_Int val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   double d; | 
					
						
							|  |  |  |   d = SANE_UNFIX (val); | 
					
						
							|  |  |  |   d /= MM_PER_INCH; | 
					
						
							|  |  |  |   return d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "sane_get_parameters\n"); | 
					
						
							|  |  |  |   if (!s->scanning) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       memset (&s->sane_params, 0, sizeof (s->sane_params)); | 
					
						
							|  |  |  |       /* Copy from options to sm3840_params */ | 
					
						
							|  |  |  |       s->sm3840_params.gray = | 
					
						
							| 
									
										
										
										
											2010-02-11 04:48:21 +00:00
										 |  |  | 	(!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |       s->sm3840_params.halftone = | 
					
						
							| 
									
										
										
										
											2010-02-11 04:48:21 +00:00
										 |  |  | 	(!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE)) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |       s->sm3840_params.lineart = | 
					
						
							| 
									
										
										
										
											2010-02-11 04:48:21 +00:00
										 |  |  | 	(!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |       s->sm3840_params.dpi = s->value[OPT_RESOLUTION].w; | 
					
						
							|  |  |  |       s->sm3840_params.bpp = s->value[OPT_BIT_DEPTH].w; | 
					
						
							|  |  |  |       s->sm3840_params.gain = SANE_UNFIX (s->value[OPT_CONTRAST].w); | 
					
						
							|  |  |  |       s->sm3840_params.offset = s->value[OPT_BRIGHTNESS].w; | 
					
						
							|  |  |  |       s->sm3840_params.lamp = s->value[OPT_LAMP_TIMEOUT].w; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |       s->sm3840_params.threshold = s->value[OPT_THRESHOLD].w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (s->sm3840_params.lineart || s->sm3840_params.halftone) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  s->sm3840_params.gray = 1; | 
					
						
							|  |  |  | 	  s->sm3840_params.bpp = 8; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       s->sm3840_params.top = sm3840_unit_convert (s->value[OPT_TL_Y].w); | 
					
						
							|  |  |  |       s->sm3840_params.left = sm3840_unit_convert (s->value[OPT_TL_X].w); | 
					
						
							|  |  |  |       s->sm3840_params.width = | 
					
						
							|  |  |  | 	sm3840_unit_convert (s->value[OPT_BR_X].w) - s->sm3840_params.left; | 
					
						
							|  |  |  |       s->sm3840_params.height = | 
					
						
							|  |  |  | 	sm3840_unit_convert (s->value[OPT_BR_Y].w) - s->sm3840_params.top; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Legalize and calculate pixel sizes */ | 
					
						
							|  |  |  |       prepare_params (&(s->sm3840_params)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Copy into sane_params */ | 
					
						
							|  |  |  |       s->sane_params.pixels_per_line = s->sm3840_params.scanpix; | 
					
						
							|  |  |  |       s->sane_params.lines = s->sm3840_params.scanlines; | 
					
						
							|  |  |  |       s->sane_params.format = | 
					
						
							|  |  |  | 	s->sm3840_params.gray ? SANE_FRAME_GRAY : SANE_FRAME_RGB; | 
					
						
							|  |  |  |       s->sane_params.bytes_per_line = s->sm3840_params.linelen; | 
					
						
							|  |  |  |       s->sane_params.depth = s->sm3840_params.bpp; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (s->sm3840_params.lineart || s->sm3840_params.halftone) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  s->sane_params.bytes_per_line += 7; | 
					
						
							|  |  |  | 	  s->sane_params.bytes_per_line /= 8; | 
					
						
							|  |  |  | 	  s->sane_params.depth = 1; | 
					
						
							|  |  |  | 	  s->sane_params.pixels_per_line = s->sane_params.bytes_per_line * 8; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |       s->sane_params.last_frame = SANE_TRUE; | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |     }				/*!scanning */ | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (params) | 
					
						
							|  |  |  |     *params = s->sane_params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_control_option (SANE_Handle handle, SANE_Int option, | 
					
						
							|  |  |  | 		     SANE_Action action, void *val, SANE_Int * info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							|  |  |  |   SANE_Status status = 0; | 
					
						
							|  |  |  |   SANE_Word cap; | 
					
						
							|  |  |  |   DBG (2, "sane_control_option\n"); | 
					
						
							|  |  |  |   if (info) | 
					
						
							|  |  |  |     *info = 0; | 
					
						
							|  |  |  |   if (s->scanning) | 
					
						
							|  |  |  |     return SANE_STATUS_DEVICE_BUSY; | 
					
						
							|  |  |  |   if (option >= NUM_OPTIONS) | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |   cap = s->options_list[option].cap; | 
					
						
							|  |  |  |   if (!SANE_OPTION_IS_ACTIVE (cap)) | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |   if (action == SANE_ACTION_GET_VALUE) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sane_control_option %d, get value\n", option); | 
					
						
							|  |  |  |       switch (option) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* word options: */ | 
					
						
							|  |  |  | 	case OPT_RESOLUTION: | 
					
						
							|  |  |  | 	case OPT_BIT_DEPTH: | 
					
						
							|  |  |  | 	case OPT_TL_X: | 
					
						
							|  |  |  | 	case OPT_TL_Y: | 
					
						
							|  |  |  | 	case OPT_BR_X: | 
					
						
							|  |  |  | 	case OPT_BR_Y: | 
					
						
							|  |  |  | 	case OPT_NUM_OPTS: | 
					
						
							|  |  |  | 	case OPT_CONTRAST: | 
					
						
							|  |  |  | 	case OPT_BRIGHTNESS: | 
					
						
							|  |  |  | 	case OPT_LAMP_TIMEOUT: | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | 	case OPT_THRESHOLD: | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 	  *(SANE_Word *) val = s->value[option].w; | 
					
						
							|  |  |  | 	  return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | 	  /* string options: */ | 
					
						
							|  |  |  | 	case OPT_MODE: | 
					
						
							|  |  |  | 	  strcpy (val, s->value[option].s); | 
					
						
							|  |  |  | 	  return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (action == SANE_ACTION_SET_VALUE) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sane_control_option %d, set value\n", option); | 
					
						
							|  |  |  |       if (!SANE_OPTION_IS_SETTABLE (cap)) | 
					
						
							|  |  |  | 	return (SANE_STATUS_INVAL); | 
					
						
							|  |  |  |       if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  | 	return (status); | 
					
						
							|  |  |  |       status = sanei_constrain_value (s->options_list + option, val, info); | 
					
						
							|  |  |  |       switch (option) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* (mostly) side-effect-free word options: */ | 
					
						
							|  |  |  | 	case OPT_RESOLUTION: | 
					
						
							|  |  |  | 	case OPT_BIT_DEPTH: | 
					
						
							|  |  |  | 	case OPT_BR_X: | 
					
						
							|  |  |  | 	case OPT_BR_Y: | 
					
						
							|  |  |  | 	case OPT_TL_X: | 
					
						
							|  |  |  | 	case OPT_TL_Y: | 
					
						
							|  |  |  | 	  if (info) | 
					
						
							|  |  |  | 	    *info |= SANE_INFO_RELOAD_PARAMS; | 
					
						
							|  |  |  | 	  /* fall through */ | 
					
						
							|  |  |  | 	case OPT_NUM_OPTS: | 
					
						
							|  |  |  | 	case OPT_CONTRAST: | 
					
						
							|  |  |  | 	case OPT_BRIGHTNESS: | 
					
						
							|  |  |  | 	case OPT_LAMP_TIMEOUT: | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | 	case OPT_THRESHOLD: | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 	  s->value[option].w = *(SANE_Word *) val; | 
					
						
							|  |  |  | 	  return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | 	case OPT_MODE: | 
					
						
							|  |  |  | 	  if (s->value[option].s) | 
					
						
							|  |  |  | 	    free (s->value[option].s); | 
					
						
							|  |  |  | 	  s->value[option].s = strdup (val); | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 	  if (info) | 
					
						
							|  |  |  | 	    *info |= SANE_INFO_RELOAD_PARAMS; | 
					
						
							|  |  |  | 	  return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (SANE_STATUS_INVAL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | const SANE_Option_Descriptor * | 
					
						
							|  |  |  | sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							|  |  |  |   DBG (2, "sane_get_option_descriptor\n"); | 
					
						
							|  |  |  |   if ((unsigned) option >= NUM_OPTIONS) | 
					
						
							|  |  |  |     return (0); | 
					
						
							|  |  |  |   return (&s->options_list[option]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_close (SANE_Handle handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *prev, *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (2, "sane_close\n"); | 
					
						
							|  |  |  |   /* remove handle from list of open handles: */ | 
					
						
							|  |  |  |   prev = 0; | 
					
						
							|  |  |  |   for (s = first_handle; s; s = s->next) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (s == handle) | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |       prev = s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (!s) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "close: invalid handle %p\n", handle); | 
					
						
							|  |  |  |       return;			/* oops, not a handle we know about */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (s->scanning) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sane_cancel (handle); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sanei_usb_close (s->udev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (s->line_buffer) | 
					
						
							|  |  |  |     free (s->line_buffer); | 
					
						
							|  |  |  |   if (s->save_scan_line) | 
					
						
							|  |  |  |     free (s->save_scan_line); | 
					
						
							|  |  |  |   if (s->save_dpi1200_remap) | 
					
						
							|  |  |  |     free (s->save_dpi1200_remap); | 
					
						
							|  |  |  |   if (s->save_color_remap) | 
					
						
							|  |  |  |     free (s->save_color_remap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (prev) | 
					
						
							|  |  |  |     prev->next = s->next; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     first_handle = s; | 
					
						
							|  |  |  |   free (handle); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sane_exit (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Device *next; | 
					
						
							|  |  |  |   DBG (2, "sane_exit\n"); | 
					
						
							|  |  |  |   while (first_dev != NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       next = first_dev->next; | 
					
						
							|  |  |  |       free (first_dev); | 
					
						
							|  |  |  |       first_dev = next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (devlist) | 
					
						
							|  |  |  |     free (devlist); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DBG_INIT (); | 
					
						
							|  |  |  |   if (version_code) | 
					
						
							| 
									
										
										
										
											2008-11-26 21:21:31 +00:00
										 |  |  |     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |   if (authorize) | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |     DBG (2, "Unused authorize\n"); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   sanei_usb_init (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SANE_Status | 
					
						
							| 
									
										
										
										
											2005-03-16 08:09:19 +00:00
										 |  |  | add_sm_device (SANE_String_Const devname, SANE_String_Const modname) | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SM3840_Device *dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dev = calloc (sizeof (*dev), 1); | 
					
						
							|  |  |  |   if (!dev) | 
					
						
							|  |  |  |     return (SANE_STATUS_NO_MEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset (dev, 0, sizeof (*dev)); | 
					
						
							|  |  |  |   dev->sane.name = strdup (devname); | 
					
						
							| 
									
										
										
										
											2005-03-16 08:09:19 +00:00
										 |  |  |   dev->sane.model = modname; | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |   dev->sane.vendor = "Microtek"; | 
					
						
							|  |  |  |   dev->sane.type = "flatbed scanner"; | 
					
						
							|  |  |  |   ++num_devices; | 
					
						
							|  |  |  |   dev->next = first_dev; | 
					
						
							|  |  |  |   first_dev = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-16 08:09:19 +00:00
										 |  |  | static SANE_Status | 
					
						
							|  |  |  | add_sm3840_device (SANE_String_Const devname) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return add_sm_device (devname, "ScanMaker 3840"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SANE_Status | 
					
						
							|  |  |  | add_sm4800_device (SANE_String_Const devname) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return add_sm_device (devname, "ScanMaker 4800"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   static const SANE_Device **devlist = 0; | 
					
						
							|  |  |  |   SM3840_Device *dev; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DBG (3, "sane_get_devices (local_only = %d)\n", local_only); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (first_dev) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       dev = first_dev->next; | 
					
						
							|  |  |  |       free (first_dev); | 
					
						
							|  |  |  |       first_dev = dev; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   first_dev = NULL; | 
					
						
							|  |  |  |   num_devices = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-16 08:09:19 +00:00
										 |  |  |   /* If we get enough scanners should use an array, but for now */ | 
					
						
							|  |  |  |   /* do it one-by-one... */ | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |   sanei_usb_find_devices (0x05da, 0x30d4, add_sm3840_device); | 
					
						
							| 
									
										
										
										
											2005-03-16 08:09:19 +00:00
										 |  |  |   sanei_usb_find_devices (0x05da, 0x30cf, add_sm4800_device); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (devlist) | 
					
						
							|  |  |  |     free (devlist); | 
					
						
							|  |  |  |   devlist = calloc ((num_devices + 1) * sizeof (devlist[0]), 1); | 
					
						
							|  |  |  |   if (!devlist) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  |   i = 0; | 
					
						
							|  |  |  |   for (dev = first_dev; i < num_devices; dev = dev->next) | 
					
						
							|  |  |  |     devlist[i++] = &dev->sane; | 
					
						
							|  |  |  |   devlist[i++] = 0; | 
					
						
							|  |  |  |   if (device_list) | 
					
						
							|  |  |  |     *device_list = devlist; | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static size_t | 
					
						
							|  |  |  | max_string_size (const SANE_String_Const strings[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   size_t size, max_size = 0; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   for (i = 0; strings[i]; ++i) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       size = strlen (strings[i]) + 1; | 
					
						
							|  |  |  |       if (size > max_size) | 
					
						
							|  |  |  | 	max_size = size; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (max_size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | initialize_options_list (SM3840_Scan * s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SANE_Int option; | 
					
						
							|  |  |  |   DBG (2, "initialize_options_list\n"); | 
					
						
							|  |  |  |   for (option = 0; option < NUM_OPTIONS; ++option) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       s->options_list[option].size = sizeof (SANE_Word); | 
					
						
							|  |  |  |       s->options_list[option].cap = | 
					
						
							|  |  |  | 	SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word); | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; | 
					
						
							|  |  |  |   s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; | 
					
						
							|  |  |  |   s->value[OPT_NUM_OPTS].w = NUM_OPTIONS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE; | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE; | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE; | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].type = SANE_TYPE_STRING; | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].size = max_string_size (mode_list); | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; | 
					
						
							|  |  |  |   s->options_list[OPT_MODE].constraint.string_list = mode_list; | 
					
						
							|  |  |  |   s->value[OPT_MODE].s = strdup (mode_list[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; | 
					
						
							|  |  |  |   s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list; | 
					
						
							|  |  |  |   s->value[OPT_RESOLUTION].w = 300; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; | 
					
						
							|  |  |  |   s->options_list[OPT_BIT_DEPTH].constraint.word_list = bpp_list; | 
					
						
							|  |  |  |   s->value[OPT_BIT_DEPTH].w = 8; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_X].constraint.range = &x_range; | 
					
						
							|  |  |  |   s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_TL_Y].constraint.range = &y_range; | 
					
						
							|  |  |  |   s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_X].constraint.range = &x_range; | 
					
						
							|  |  |  |   s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_BR_Y].constraint.range = &y_range; | 
					
						
							|  |  |  |   s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].type = SANE_TYPE_FIXED; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_CONTRAST].constraint.range = &contrast_range; | 
					
						
							|  |  |  |   s->value[OPT_CONTRAST].w = SANE_FIX (3.5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_BRIGHTNESS].constraint.range = &brightness_range; | 
					
						
							|  |  |  |   s->value[OPT_BRIGHTNESS].w = 1800; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].name = "lamp-timeout"; | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].title = SANE_I18N ("Lamp timeout"); | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].desc = | 
					
						
							|  |  |  |     SANE_I18N ("Minutes until lamp is turned off after scan"); | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_LAMP_TIMEOUT].constraint.range = &lamp_range; | 
					
						
							|  |  |  |   s->value[OPT_LAMP_TIMEOUT].w = 15; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   s->options_list[OPT_THRESHOLD].name = "threshold"; | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].title = SANE_I18N ("Threshold"); | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].desc = | 
					
						
							|  |  |  |     SANE_I18N ("Threshold value for lineart mode"); | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].type = SANE_TYPE_INT; | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].unit = SANE_UNIT_NONE; | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; | 
					
						
							|  |  |  |   s->options_list[OPT_THRESHOLD].constraint.range = &threshold_range; | 
					
						
							|  |  |  |   s->value[OPT_THRESHOLD].w = 128; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_open (SANE_String_Const devicename, SANE_Handle * handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  |   SM3840_Device *dev; | 
					
						
							|  |  |  |   SM3840_Scan *s; | 
					
						
							|  |  |  |   DBG (2, "sane_open\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Make sure we have first_dev */ | 
					
						
							|  |  |  |   sane_get_devices (NULL, 0); | 
					
						
							|  |  |  |   if (devicename[0]) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (dev = first_dev; dev; dev = dev->next) | 
					
						
							|  |  |  | 	if (strcmp (dev->sane.name, devicename) == 0) | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* empty devicename -> use first device */ | 
					
						
							|  |  |  |       dev = first_dev; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-03-08 21:49:23 +00:00
										 |  |  |   DBG (2, "using device: %s %p\n", dev->sane.name, (unsigned char *) dev); | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  |   if (!dev) | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |   s = calloc (sizeof (*s), 1); | 
					
						
							|  |  |  |   if (!s) | 
					
						
							|  |  |  |     return SANE_STATUS_NO_MEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = sanei_usb_open (dev->sane.name, &(s->udev)); | 
					
						
							| 
									
										
										
										
											2008-02-20 17:27:53 +00:00
										 |  |  |   if (status != SANE_STATUS_GOOD) | 
					
						
							|  |  |  |     return status; | 
					
						
							| 
									
										
										
										
											2005-02-20 20:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   initialize_options_list (s); | 
					
						
							|  |  |  |   s->scanning = 0; | 
					
						
							|  |  |  |   /* insert newly opened handle into list of open handles: */ | 
					
						
							|  |  |  |   s->next = first_handle; | 
					
						
							|  |  |  |   first_handle = s; | 
					
						
							|  |  |  |   *handle = s; | 
					
						
							|  |  |  |   return (SANE_STATUS_GOOD); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*--------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SM3840_Scan *s = handle; | 
					
						
							|  |  |  |   DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); | 
					
						
							|  |  |  |   if (s->scanning) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (non_blocking == SANE_FALSE) | 
					
						
							|  |  |  | 	return SANE_STATUS_GOOD; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	return (SANE_STATUS_UNSUPPORTED); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return SANE_STATUS_INVAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*---------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DBG (2, "sane_get_select_fd( %p, %p )\n", (void *) handle, (void *) fd); | 
					
						
							|  |  |  |   return SANE_STATUS_UNSUPPORTED; | 
					
						
							|  |  |  | } |