1 /*.............................................................................
2  * Project : SANE library for Plustek flatbed scanners.
3  *.............................................................................
4  */
5 
6 /** @file plustek-usbio.c
7  *  @brief Some I/O stuff.
8  *
9  * Based on sources acquired from Plustek Inc.<br>
10  * Copyright (C) 2001-2007 Gerhard Jaeger <gerhard@gjaeger.de>
11  *
12  * History:
13  * History:
14  * - 0.40 - starting version of the USB support
15  * - 0.41 - moved some functions to a sane library (sanei_lm983x.c)
16  * - 0.42 - no changes
17  * - 0.43 - no changes
18  * - 0.44 - added dump registers and dumpPic functions
19  *        - beautified output of ASIC detection
20  * - 0.45 - fixed dumpRegs
21  *        - added dimension stuff to dumpPic
22  * - 0.46 - disabled reset prior to the detection of Merlin
23  * - 0.47 - no changes
24  * - 0.48 - cleanup
25  * - 0.49 - no changes
26  * - 0.50 - usbio_DetectLM983x() now returns error if register
27  *          could not be red
28  *        - usbio_ResetLM983x() checks for reg7 value before writing
29  * - 0.51 - allow dumpRegs to be called without valid fd
30  * - 0.52 - no changes
31  * .
32  * <hr>
33  * This file is part of the SANE package.
34  *
35  * This program is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU General Public License as
37  * published by the Free Software Foundation; either version 2 of the
38  * License, or (at your option) any later version.
39  *
40  * This program is distributed in the hope that it will be useful, but
41  * WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43  * General Public License for more details.
44  *
45  * You should have received a copy of the GNU General Public License
46  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
47  *
48  * As a special exception, the authors of SANE give permission for
49  * additional uses of the libraries contained in this release of SANE.
50  *
51  * The exception is that, if you link a SANE library with other files
52  * to produce an executable, this does not by itself cause the
53  * resulting executable to be covered by the GNU General Public
54  * License.  Your use of that executable is in no way restricted on
55  * account of linking the SANE library code into it.
56  *
57  * This exception does not, however, invalidate any other reasons why
58  * the executable file might be covered by the GNU General Public
59  * License.
60  *
61  * If you submit changes to SANE to the maintainers to be included in
62  * a subsequent release, you agree by submitting the changes that
63  * those changes may be distributed with this exception intact.
64  *
65  * If you write modifications of your own for SANE, it is your choice
66  * whether to permit this exception to apply to your modifications.
67  * If you do not wish that, delete this exception notice.
68  * <hr>
69  */
70 
71 #include "../include/sane/sanei_usb.h"
72 #include "../include/sane/sanei_lm983x.h"
73 
74 #define _UIO(func)                            \
75     {                                         \
76         SANE_Status status;                   \
77         status = func;                        \
78         if (status != SANE_STATUS_GOOD) {     \
79             DBG( _DBG_ERROR, "UIO error\n" ); \
80             return SANE_FALSE;                \
81         }                                     \
82     }
83 
84 #define usbio_ReadReg(fd, reg, value) \
85   sanei_lm983x_read (fd, reg, value, 1, 0)
86 
87 typedef struct {
88 
89 	u_char depth;
90 	u_long x;
91 	u_long y;
92 } PicDef, *pPicDef;
93 
94 static PicDef dPix;
95 
96 /**
97  */
dumpPic( char* name, SANE_Byte *buffer, u_long len, int is_gray )98 static void dumpPic( char* name, SANE_Byte *buffer, u_long len, int is_gray )
99 {
100 	u_short type;
101 	FILE   *fp;
102 
103 	if( DBG_LEVEL < _DBG_DPIC )
104 		return;
105 
106 	if( NULL == buffer ) {
107 
108 		DBG( _DBG_DPIC, "Creating file '%s'\n", name );
109 
110 		fp = fopen( name, "w+b" );
111 
112 		if( NULL != fp ) {
113 
114 			if( 0 != dPix.x ) {
115 
116 				if (is_gray)
117 					type = 5;
118 				else
119 					type = 6;
120 
121 				DBG( _DBG_DPIC, "> X=%lu, Y=%lu, depth=%u\n",
122 				                 dPix.x, dPix.y, dPix.depth );
123 				if( dPix.depth > 8 )
124 					fprintf( fp, "P%u\n%lu %lu\n65535\n", type, dPix.x, dPix.y);
125     			else
126 					fprintf( fp, "P%u\n%lu %lu\n255\n", type, dPix.x, dPix.y);
127 			}
128     	}
129 	} else {
130 		fp = fopen( name, "a+b" );
131 	}
132 
133 	if( NULL == fp ) {
134 		DBG( _DBG_DPIC, "Can not open file '%s'\n", name );
135 		return;
136 	}
137 
138 	fwrite( buffer, 1, len, fp );
139 	fclose( fp );
140 }
141 
142 /**
143  */
dumpPicInit( ScanParam *sd, char* name )144 static void dumpPicInit( ScanParam *sd, char* name )
145 {
146 	dPix.x = sd->Size.dwPhyBytes;
147 
148 	if( sd->bDataType == SCANDATATYPE_Color )
149 		dPix.x /= 3;
150 
151 	if( sd->bBitDepth > 8 )
152 		dPix.x /= 2;
153 
154 	dPix.y	   = sd->Size.dwLines;
155 	dPix.depth = sd->bBitDepth;
156 
157 	if( sd->bDataType == SCANDATATYPE_Color )
158 		dumpPic(name, NULL, 0, 0);
159 	else
160 		dumpPic(name, NULL, 0, 1);
161 }
162 
163 /**
164  * dump the LM983x registers
165  */
dumpregs( int fd, SANE_Byte *cmp )166 static void dumpregs( int fd, SANE_Byte *cmp )
167 {
168 	char      buf[256], b2[10];
169 	SANE_Byte regs[0x80];
170 	int       i;
171 
172 	if( DBG_LEVEL < _DBG_DREGS )
173 		return;
174 
175 	buf[0] = '\0';
176 
177 	if( fd >= 0 ) {
178 		usbio_ReadReg(fd, 0x01, &regs[0x01]);
179 		usbio_ReadReg(fd, 0x02, &regs[0x02]);
180 		usbio_ReadReg(fd, 0x03, &regs[0x03]);
181 		usbio_ReadReg(fd, 0x04, &regs[0x04]);
182 		usbio_ReadReg(fd, 0x07, &regs[0x07]);
183 
184 		sanei_lm983x_read( fd, 0x08, &regs[0x8], 0x80-0x8, SANE_TRUE );
185 
186 		for( i = 0x0; i < 0x80; i++ ) {
187 
188 			if((i%16) ==0 ) {
189 
190 				if( buf[0] )
191 					DBG( _DBG_DREGS, "%s\n", buf );
192 				sprintf( buf, "0x%02x:", i );
193 			}
194 
195 			if((i%8)==0)
196 				strcat( buf, " ");
197 
198 			/* the dataport read returns with "0 Bytes read", of course. */
199 			if((i == 0) || (i == 5) || (i == 6))
200 				strcat( buf, "XX ");
201 			else {
202 
203 				sprintf( b2, "%02x ", regs[i]);
204 				strcat( buf, b2 );
205 			}
206 		}
207 		DBG( _DBG_DREGS, "%s\n", buf );
208 	}
209 
210 	if( cmp ) {
211 
212 		buf[0] = '\0';
213 
214 		DBG( _DBG_DREGS, "Internal setting:\n" );
215 		for( i = 0x0; i < 0x80; i++ ) {
216 
217 			if((i%16) ==0 ) {
218 
219 				if( buf[0] )
220 					DBG( _DBG_DREGS, "%s\n", buf );
221 				sprintf( buf, "0x%02x:", i );
222 			}
223 
224 			if((i%8)==0)
225 				strcat( buf, " ");
226 
227 			if((i == 0) || (i == 5) || (i == 6))
228 				strcat( buf, "XX ");
229 			else {
230 				sprintf( b2, "%02x ", cmp[i]);
231 				strcat( buf, b2 );
232 			}
233 		}
234 		DBG( _DBG_DREGS, "%s\n", buf );
235 	}
236 }
237 
238 /**
239  * function to read the contents of a LM983x register and regarding some
240  * extra stuff, like flushing register 2 when writing register 0x58, etc
241  *
242  * @param handle -
243  * @param reg    -
244  * @param value  -
245  * @return
246  */
usbio_WriteReg( SANE_Int handle, SANE_Byte reg, SANE_Byte value )247 static SANE_Bool usbio_WriteReg( SANE_Int handle,
248                                  SANE_Byte reg, SANE_Byte value )
249 {
250 	int       i;
251 	SANE_Byte data;
252 
253 	/* retry loop... */
254 	for( i = 0; i < 100; i++ ) {
255 
256 		sanei_lm983x_write_byte( handle, reg, value );
257 
258 		/* Flush register 0x02 when register 0x58 is written */
259 		if( 0x58 == reg ) {
260 			_UIO( usbio_ReadReg( handle, 2, &data ));
261 			_UIO( usbio_ReadReg( handle, 2, &data ));
262 		}
263 
264 		if( reg != 7 )
265 			return SANE_TRUE;
266 
267 		/* verify register 7 */
268 		_UIO( usbio_ReadReg( handle, 7, &data ));
269 		if( data == value ) {
270 			return SANE_TRUE;
271 		}
272 	}
273 
274 	return SANE_FALSE;
275 }
276 
277 /** try and read register 0x69 from a LM983x to find out which version we have.
278  */
usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )279 static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )
280 {
281 	char        buf[256];
282 	SANE_Byte   value;
283 	SANE_Status res;
284 
285 	DBG( _DBG_INFO, "usbio_DetectLM983x\n");
286 
287 	res = usbio_ReadReg(fd, 0x69, &value);
288 	if( res != SANE_STATUS_GOOD ) {
289 		DBG( _DBG_ERROR, " * could not read version register!\n");
290 		return res;
291 	}
292 
293 	value &= 7;
294 	if (version)
295 		*version = value;
296 
297 	res = SANE_STATUS_GOOD;
298 
299 	sprintf( buf, "usbio_DetectLM983x: found " );
300 
301 	switch((SANE_Int)value ) {
302 
303 		case 4:	 strcat( buf, "LM9832/3" ); break;
304 		case 3:	 strcat( buf, "LM9831" );   break;
305 		case 2:	 strcat( buf, "LM9830 --> unsupported!!!" );
306 				 res =  SANE_STATUS_INVAL;
307 				 break;
308 		default: DBG( _DBG_INFO, "Unknown chip v%d", value );
309 				 res = SANE_STATUS_INVAL;
310 				 break;
311 	}
312 
313 	DBG( _DBG_INFO, "%s\n", buf );
314 	return res;
315 }
316 
317 /** well, this is more or less a reset function, for LM9831 based devices
318  * we issue a real reset command, while for LM9832/3 based devices, checking
319  * and resetting register 7 will be enough...
320  */
usbio_ResetLM983x( Plustek_Device *dev )321 static SANE_Status usbio_ResetLM983x( Plustek_Device *dev )
322 {
323 	SANE_Byte value;
324 	HWDef    *hw = &dev->usbDev.HwSetting;
325 
326 	if( _LM9831 == hw->chip ) {
327 
328 		DBG( _DBG_INFO," * resetting LM9831 device!\n");
329 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
330 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07,0x20));
331 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
332 		_UIO( usbio_ReadReg( dev->fd, 0x07, &value));
333 		if (value != 0) {
334  			DBG( _DBG_ERROR, "usbio_ResetLM983x: reset was not "
335 			                 "successful, status=%d\n", value );
336 			return SANE_STATUS_INVAL;
337 		}
338 
339 	} else {
340 		_UIO( usbio_ReadReg( dev->fd, 0x07, &value));
341 		if (value != 0 ) {
342 			DBG( _DBG_INFO," * setting device to idle state!\n");
343 			_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
344 		}
345 	}
346 	return SANE_STATUS_GOOD;
347 }
348 
349 /* END PLUSTEK-USBIO.C ......................................................*/
350