1 /** @file plustek-pp_wrapper.c
2 * @brief The interface to the parport driver-code and the kernel module.
3 *
4 * Based on sources acquired from Plustek Inc.<br>
5 * Copyright (C) 2001-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6 *
7 * History:
8 * - 0.40 - initial version
9 * - 0.41 - added _PTDRV_ADJUST call
10 * - 0.42 - added setmap function
11 * - fixed the stopscan problem, that causes a crash in the kernel module
12 * - 0.43 - added initialized setting
13 * - cleanup
14 * .
15 * <hr>
16 * This file is part of the SANE package.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License as
20 * published by the Free Software Foundation; either version 2 of the
21 * License, or (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 *
31 * As a special exception, the authors of SANE give permission for
32 * additional uses of the libraries contained in this release of SANE.
33 *
34 * The exception is that, if you link a SANE library with other files
35 * to produce an executable, this does not by itself cause the
36 * resulting executable to be covered by the GNU General Public
37 * License. Your use of that executable is in no way restricted on
38 * account of linking the SANE library code into it.
39 *
40 * This exception does not, however, invalidate any other reasons why
41 * the executable file might be covered by the GNU General Public
42 * License.
43 *
44 * If you submit changes to SANE to the maintainers to be included in
45 * a subsequent release, you agree by submitting the changes that
46 * those changes may be distributed with this exception intact.
47 *
48 * If you write modifications of your own for SANE, it is your choice
49 * whether to permit this exception to apply to your modifications.
50 * If you do not wish that, delete this exception notice.
51 * <hr>
52 */
53
54 /******************* wrapper functions for parport device ********************/
55
56 #ifndef _BACKEND_ENABLED
57
PtDrvInit( char *dev_name, unsigned short model_override )58 static int PtDrvInit( char *dev_name, unsigned short model_override )
59 {
60 _VAR_NOT_USED( dev_name );
61 _VAR_NOT_USED( model_override );
62 DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
63 return -1;
64 }
65
PtDrvShutdown( void )66 static int PtDrvShutdown( void )
67 {
68 return 0;
69 }
70
PtDrvOpen( void )71 static int PtDrvOpen( void )
72 {
73 DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
74 return -1;
75 }
76
PtDrvClose( void )77 static int PtDrvClose( void )
78 {
79 DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
80 return 0;
81 }
82
PtDrvIoctl( unsigned int cmd, void *arg )83 static int PtDrvIoctl( unsigned int cmd, void *arg )
84 {
85 DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
86 _VAR_NOT_USED( cmd );
87 if( arg == NULL )
88 return -2;
89 return -1;
90 }
91
PtDrvRead( unsigned char *buffer, int count )92 static int PtDrvRead( unsigned char *buffer, int count )
93 {
94 DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
95 _VAR_NOT_USED( count );
96 if( buffer == NULL )
97 return -2;
98 return -1;
99 }
100 #endif /* _BACKEND_ENABLED */
101
102 /**
103 */
ppDev_open( const char *dev_name, void *misc )104 static int ppDev_open( const char *dev_name, void *misc )
105 {
106 int result;
107 int handle;
108 CompatAdjDef compatAdj;
109 PPAdjDef adj;
110 unsigned short version = _PTDRV_IOCTL_VERSION;
111 Plustek_Device *dev = (Plustek_Device *)misc;
112
113 if( dev->adj.direct_io ) {
114 result = PtDrvInit( dev_name, dev->adj.mov );
115 if( 0 != result ) {
116 DBG( _DBG_ERROR, "open: PtDrvInit failed: %d\n", result );
117 return -1;
118 }
119 }
120
121 if( dev->adj.direct_io )
122 handle = PtDrvOpen();
123 else
124 handle = open( dev_name, O_RDONLY );
125
126 if ( handle < 0 ) {
127 DBG( _DBG_ERROR, "open: can't open %s as a device\n", dev_name );
128 return handle;
129 }
130
131 if( dev->adj.direct_io )
132 result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
133 else
134 result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
135
136 if( result < 0 ) {
137
138 if( -9019 == result ) {
139
140 DBG( _DBG_INFO, "Version 0x%04x not supported, trying "
141 "compatibility version 0x%04x\n",
142 _PTDRV_IOCTL_VERSION, _PTDRV_COMPAT_IOCTL_VERSION);
143
144 version = _PTDRV_COMPAT_IOCTL_VERSION;
145
146 if( dev->adj.direct_io )
147 result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
148 else
149 result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
150
151 if( result < 0 ) {
152
153 if( dev->adj.direct_io )
154 PtDrvClose();
155 else
156 close( dev->fd );
157
158 DBG( _DBG_ERROR,
159 "ioctl PT_DRV_OPEN_DEVICE failed(%d)\n", result );
160
161 if( -9019 == result ) {
162 DBG( _DBG_ERROR,
163 "Version problem, please recompile driver!\n" );
164 }
165 } else {
166
167 DBG( _DBG_INFO, "Using compatibility version\n" );
168
169 compatAdj.lampOff = dev->adj.lampOff;
170 compatAdj.lampOffOnEnd = dev->adj.lampOffOnEnd;
171 compatAdj.warmup = dev->adj.warmup;
172
173 memcpy( &compatAdj.pos, &dev->adj.pos, sizeof(OffsDef));
174 memcpy( &compatAdj.neg, &dev->adj.neg, sizeof(OffsDef));
175 memcpy( &compatAdj.tpa, &dev->adj.tpa, sizeof(OffsDef));
176
177 if( dev->adj.direct_io )
178 PtDrvIoctl( _PTDRV_ADJUST, &compatAdj );
179 else
180 ioctl( handle, _PTDRV_ADJUST, &compatAdj );
181 return handle;
182 }
183 }
184 return result;
185 }
186
187 memset( &adj, 0, sizeof(PPAdjDef));
188
189 adj.lampOff = dev->adj.lampOff;
190 adj.lampOffOnEnd = dev->adj.lampOffOnEnd;
191 adj.warmup = dev->adj.warmup;
192
193 memcpy( &adj.pos, &dev->adj.pos, sizeof(OffsDef));
194 memcpy( &adj.neg, &dev->adj.neg, sizeof(OffsDef));
195 memcpy( &adj.tpa, &dev->adj.tpa, sizeof(OffsDef));
196
197 adj.rgamma = dev->adj.rgamma;
198 adj.ggamma = dev->adj.ggamma;
199 adj.bgamma = dev->adj.bgamma;
200 adj.graygamma = dev->adj.graygamma;
201
202 if( dev->adj.direct_io )
203 PtDrvIoctl( _PTDRV_ADJUST, &adj );
204 else
205 ioctl( handle, _PTDRV_ADJUST, &adj );
206
207 dev->initialized = SANE_TRUE;
208 return handle;
209 }
210
211 /**
212 */
ppDev_close( Plustek_Device *dev )213 static int ppDev_close( Plustek_Device *dev )
214 {
215 if( dev->adj.direct_io )
216 return PtDrvClose();
217 else
218 return close( dev->fd );
219 }
220
221 /**
222 */
ppDev_getCaps( Plustek_Device *dev )223 static int ppDev_getCaps( Plustek_Device *dev )
224 {
225 if( dev->adj.direct_io )
226 return PtDrvIoctl( _PTDRV_GET_CAPABILITIES, &dev->caps );
227 else
228 return ioctl( dev->fd, _PTDRV_GET_CAPABILITIES, &dev->caps );
229 }
230
231 /**
232 */
ppDev_getLensInfo( Plustek_Device *dev, pLensInfo lens )233 static int ppDev_getLensInfo( Plustek_Device *dev, pLensInfo lens )
234 {
235 if( dev->adj.direct_io )
236 return PtDrvIoctl( _PTDRV_GET_LENSINFO, lens );
237 else
238 return ioctl( dev->fd, _PTDRV_GET_LENSINFO, lens );
239 }
240
241 /**
242 */
ppDev_getCropInfo( Plustek_Device *dev, pCropInfo crop )243 static int ppDev_getCropInfo( Plustek_Device *dev, pCropInfo crop )
244 {
245 if( dev->adj.direct_io )
246 return PtDrvIoctl( _PTDRV_GET_CROPINFO, crop );
247 else
248 return ioctl( dev->fd, _PTDRV_GET_CROPINFO, crop );
249 }
250
251 /**
252 */
ppDev_putImgInfo( Plustek_Device *dev, pImgDef img )253 static int ppDev_putImgInfo( Plustek_Device *dev, pImgDef img )
254 {
255 if( dev->adj.direct_io )
256 return PtDrvIoctl( _PTDRV_PUT_IMAGEINFO, img );
257 else
258 return ioctl( dev->fd, _PTDRV_PUT_IMAGEINFO, img );
259 }
260
261 /**
262 */
ppDev_setScanEnv( Plustek_Device *dev, pScanInfo sinfo )263 static int ppDev_setScanEnv( Plustek_Device *dev, pScanInfo sinfo )
264 {
265 if( dev->adj.direct_io )
266 return PtDrvIoctl( _PTDRV_SET_ENV, sinfo );
267 else
268 return ioctl( dev->fd, _PTDRV_SET_ENV, sinfo );
269 }
270
271 /**
272 */
ppDev_startScan( Plustek_Device *dev, pStartScan start )273 static int ppDev_startScan( Plustek_Device *dev, pStartScan start )
274 {
275 if( dev->adj.direct_io )
276 return PtDrvIoctl( _PTDRV_START_SCAN, start );
277 else
278 return ioctl( dev->fd, _PTDRV_START_SCAN, start );
279 }
280
281 /** function to send a gamma table to the kernel module. As the default table
282 * entry is 16-bit, but the maps are 8-bit, we have to copy the values...
283 */
ppDev_setMap( Plustek_Device *dev, SANE_Word *map, SANE_Word length, SANE_Word channel )284 static int ppDev_setMap( Plustek_Device *dev, SANE_Word *map,
285 SANE_Word length, SANE_Word channel )
286 {
287 SANE_Byte *buf;
288 SANE_Word i;
289 MapDef m;
290
291 m.len = length;
292 m.map_id = channel;
293
294 m.map = (void *)map;
295
296 DBG(_DBG_INFO,"Setting map[%u] at 0x%08lx\n", channel, (unsigned long)map);
297
298 buf = (SANE_Byte*)malloc( m.len );
299
300 if( !buf )
301 return _E_ALLOC;
302
303 for( i = 0; i < m.len; i++ ) {
304 buf[i] = (SANE_Byte)map[i];
305
306 if( map[i] > 0xFF )
307 buf[i] = 0xFF;
308 }
309
310 m.map = buf;
311
312 if( dev->adj.direct_io )
313 PtDrvIoctl( _PTDRV_SETMAP, &m );
314 else
315 ioctl( dev->fd, _PTDRV_SETMAP, &m );
316
317 /* we ignore the return values */
318 free( buf );
319 return 0;
320 }
321
322 /**
323 */
ppDev_stopScan( Plustek_Device *dev, short *mode )324 static int ppDev_stopScan( Plustek_Device *dev, short *mode )
325 {
326 int retval, tmp;
327
328 /* save this one... */
329 tmp = *mode;
330
331 if( dev->adj.direct_io )
332 retval = PtDrvIoctl( _PTDRV_STOP_SCAN, mode );
333 else
334 retval = ioctl( dev->fd, _PTDRV_STOP_SCAN, mode );
335
336 /* ... and use it here */
337 if( 0 == tmp ) {
338 if( dev->adj.direct_io )
339 PtDrvIoctl( _PTDRV_CLOSE_DEVICE, 0 );
340 else
341 ioctl( dev->fd, _PTDRV_CLOSE_DEVICE, 0);
342 }else
343 sleep( 1 );
344
345 return retval;
346 }
347
348 /**
349 */
ppDev_readImage( Plustek_Device *dev, SANE_Byte *buf, unsigned long data_length )350 static int ppDev_readImage( Plustek_Device *dev,
351 SANE_Byte *buf, unsigned long data_length )
352 {
353 if( dev->adj.direct_io )
354 return PtDrvRead( buf, data_length );
355 else
356 return read( dev->fd, buf, data_length );
357 }
358
359 /* END PLUSTEK-PP_WRAPPER.C .................................................*/
360