1141cc406Sopenharmony_ci/** @file plustek-pp_wrapper.c
2141cc406Sopenharmony_ci *  @brief The interface to the parport driver-code and the kernel module.
3141cc406Sopenharmony_ci *
4141cc406Sopenharmony_ci * Based on sources acquired from Plustek Inc.<br>
5141cc406Sopenharmony_ci * Copyright (C) 2001-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6141cc406Sopenharmony_ci *
7141cc406Sopenharmony_ci * History:
8141cc406Sopenharmony_ci * - 0.40 - initial version
9141cc406Sopenharmony_ci * - 0.41 - added _PTDRV_ADJUST call
10141cc406Sopenharmony_ci * - 0.42 - added setmap function
11141cc406Sopenharmony_ci *        - fixed the stopscan problem, that causes a crash in the kernel module
12141cc406Sopenharmony_ci * - 0.43 - added initialized setting
13141cc406Sopenharmony_ci *        - cleanup
14141cc406Sopenharmony_ci * .
15141cc406Sopenharmony_ci * <hr>
16141cc406Sopenharmony_ci * This file is part of the SANE package.
17141cc406Sopenharmony_ci *
18141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or
19141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as
20141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the
21141cc406Sopenharmony_ci * License, or (at your option) any later version.
22141cc406Sopenharmony_ci *
23141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
24141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
25141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26141cc406Sopenharmony_ci * General Public License for more details.
27141cc406Sopenharmony_ci *
28141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License
29141cc406Sopenharmony_ci * along with this program.  If not, see <https://www.gnu.org/licenses/>.
30141cc406Sopenharmony_ci *
31141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for
32141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE.
33141cc406Sopenharmony_ci *
34141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files
35141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the
36141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public
37141cc406Sopenharmony_ci * License.  Your use of that executable is in no way restricted on
38141cc406Sopenharmony_ci * account of linking the SANE library code into it.
39141cc406Sopenharmony_ci *
40141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why
41141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public
42141cc406Sopenharmony_ci * License.
43141cc406Sopenharmony_ci *
44141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in
45141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that
46141cc406Sopenharmony_ci * those changes may be distributed with this exception intact.
47141cc406Sopenharmony_ci *
48141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice
49141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications.
50141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice.
51141cc406Sopenharmony_ci * <hr>
52141cc406Sopenharmony_ci */
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ci/******************* wrapper functions for parport device ********************/
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci#ifndef _BACKEND_ENABLED
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_cistatic int PtDrvInit( char *dev_name, unsigned short model_override )
59141cc406Sopenharmony_ci{
60141cc406Sopenharmony_ci	_VAR_NOT_USED( dev_name );
61141cc406Sopenharmony_ci	_VAR_NOT_USED( model_override );
62141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
63141cc406Sopenharmony_ci	return -1;
64141cc406Sopenharmony_ci}
65141cc406Sopenharmony_ci
66141cc406Sopenharmony_cistatic int PtDrvShutdown( void )
67141cc406Sopenharmony_ci{
68141cc406Sopenharmony_ci	return 0;
69141cc406Sopenharmony_ci}
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_cistatic int PtDrvOpen( void )
72141cc406Sopenharmony_ci{
73141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
74141cc406Sopenharmony_ci	return -1;
75141cc406Sopenharmony_ci}
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_cistatic int PtDrvClose( void )
78141cc406Sopenharmony_ci{
79141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
80141cc406Sopenharmony_ci	return 0;
81141cc406Sopenharmony_ci}
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_cistatic int PtDrvIoctl( unsigned int cmd, void *arg )
84141cc406Sopenharmony_ci{
85141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
86141cc406Sopenharmony_ci	_VAR_NOT_USED( cmd );
87141cc406Sopenharmony_ci	if( arg == NULL )
88141cc406Sopenharmony_ci		return -2;
89141cc406Sopenharmony_ci	return -1;
90141cc406Sopenharmony_ci}
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_cistatic int PtDrvRead( unsigned char *buffer, int count )
93141cc406Sopenharmony_ci{
94141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" );
95141cc406Sopenharmony_ci	_VAR_NOT_USED( count );
96141cc406Sopenharmony_ci	if( buffer == NULL )
97141cc406Sopenharmony_ci		return -2;
98141cc406Sopenharmony_ci	return -1;
99141cc406Sopenharmony_ci}
100141cc406Sopenharmony_ci#endif /* _BACKEND_ENABLED */
101141cc406Sopenharmony_ci
102141cc406Sopenharmony_ci/**
103141cc406Sopenharmony_ci */
104141cc406Sopenharmony_cistatic int ppDev_open( const char *dev_name, void *misc )
105141cc406Sopenharmony_ci{
106141cc406Sopenharmony_ci	int 		    result;
107141cc406Sopenharmony_ci	int			    handle;
108141cc406Sopenharmony_ci	CompatAdjDef    compatAdj;
109141cc406Sopenharmony_ci	PPAdjDef        adj;
110141cc406Sopenharmony_ci	unsigned short  version = _PTDRV_IOCTL_VERSION;
111141cc406Sopenharmony_ci	Plustek_Device *dev     = (Plustek_Device *)misc;
112141cc406Sopenharmony_ci
113141cc406Sopenharmony_ci	if( dev->adj.direct_io ) {
114141cc406Sopenharmony_ci		result = PtDrvInit( dev_name, dev->adj.mov );
115141cc406Sopenharmony_ci		if( 0 != result ) {
116141cc406Sopenharmony_ci			DBG( _DBG_ERROR, "open: PtDrvInit failed: %d\n", result );
117141cc406Sopenharmony_ci			return -1;
118141cc406Sopenharmony_ci		}
119141cc406Sopenharmony_ci	}
120141cc406Sopenharmony_ci
121141cc406Sopenharmony_ci	if( dev->adj.direct_io )
122141cc406Sopenharmony_ci		handle = PtDrvOpen();
123141cc406Sopenharmony_ci	else
124141cc406Sopenharmony_ci		handle = open( dev_name, O_RDONLY );
125141cc406Sopenharmony_ci
126141cc406Sopenharmony_ci	if ( handle  < 0 ) {
127141cc406Sopenharmony_ci	    DBG( _DBG_ERROR, "open: can't open %s as a device\n", dev_name );
128141cc406Sopenharmony_ci    	return handle;
129141cc406Sopenharmony_ci	}
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci	if( dev->adj.direct_io )
132141cc406Sopenharmony_ci		result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
133141cc406Sopenharmony_ci	else
134141cc406Sopenharmony_ci		result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_ci	if( result < 0 ) {
137141cc406Sopenharmony_ci
138141cc406Sopenharmony_ci        if( -9019 == result ) {
139141cc406Sopenharmony_ci
140141cc406Sopenharmony_ci			DBG( _DBG_INFO, "Version 0x%04x not supported, trying "
141141cc406Sopenharmony_ci                            "compatibility version 0x%04x\n",
142141cc406Sopenharmony_ci                            _PTDRV_IOCTL_VERSION, _PTDRV_COMPAT_IOCTL_VERSION);
143141cc406Sopenharmony_ci
144141cc406Sopenharmony_ci			version = _PTDRV_COMPAT_IOCTL_VERSION;
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci			if( dev->adj.direct_io )
147141cc406Sopenharmony_ci				result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
148141cc406Sopenharmony_ci			else
149141cc406Sopenharmony_ci				result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
150141cc406Sopenharmony_ci
151141cc406Sopenharmony_ci			if( result < 0 ) {
152141cc406Sopenharmony_ci
153141cc406Sopenharmony_ci				if( dev->adj.direct_io )
154141cc406Sopenharmony_ci					PtDrvClose();
155141cc406Sopenharmony_ci				else
156141cc406Sopenharmony_ci					close( dev->fd );
157141cc406Sopenharmony_ci
158141cc406Sopenharmony_ci				DBG( _DBG_ERROR,
159141cc406Sopenharmony_ci					 "ioctl PT_DRV_OPEN_DEVICE failed(%d)\n", result );
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci		        if( -9019 == result ) {
162141cc406Sopenharmony_ci	    			DBG( _DBG_ERROR,
163141cc406Sopenharmony_ci						 "Version problem, please recompile driver!\n" );
164141cc406Sopenharmony_ci				}
165141cc406Sopenharmony_ci			} else {
166141cc406Sopenharmony_ci
167141cc406Sopenharmony_ci				DBG( _DBG_INFO, "Using compatibility version\n" );
168141cc406Sopenharmony_ci
169141cc406Sopenharmony_ci				compatAdj.lampOff      = dev->adj.lampOff;
170141cc406Sopenharmony_ci				compatAdj.lampOffOnEnd = dev->adj.lampOffOnEnd;
171141cc406Sopenharmony_ci				compatAdj.warmup       = dev->adj.warmup;
172141cc406Sopenharmony_ci
173141cc406Sopenharmony_ci				memcpy( &compatAdj.pos, &dev->adj.pos, sizeof(OffsDef));
174141cc406Sopenharmony_ci				memcpy( &compatAdj.neg, &dev->adj.neg, sizeof(OffsDef));
175141cc406Sopenharmony_ci				memcpy( &compatAdj.tpa, &dev->adj.tpa, sizeof(OffsDef));
176141cc406Sopenharmony_ci
177141cc406Sopenharmony_ci				if( dev->adj.direct_io )
178141cc406Sopenharmony_ci					PtDrvIoctl( _PTDRV_ADJUST, &compatAdj );
179141cc406Sopenharmony_ci				else
180141cc406Sopenharmony_ci					ioctl( handle, _PTDRV_ADJUST, &compatAdj );
181141cc406Sopenharmony_ci				return handle;
182141cc406Sopenharmony_ci			}
183141cc406Sopenharmony_ci		}
184141cc406Sopenharmony_ci		return result;
185141cc406Sopenharmony_ci    }
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_ci	memset( &adj, 0, sizeof(PPAdjDef));
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_ci	adj.lampOff      = dev->adj.lampOff;
190141cc406Sopenharmony_ci	adj.lampOffOnEnd = dev->adj.lampOffOnEnd;
191141cc406Sopenharmony_ci	adj.warmup       = dev->adj.warmup;
192141cc406Sopenharmony_ci
193141cc406Sopenharmony_ci	memcpy( &adj.pos, &dev->adj.pos, sizeof(OffsDef));
194141cc406Sopenharmony_ci	memcpy( &adj.neg, &dev->adj.neg, sizeof(OffsDef));
195141cc406Sopenharmony_ci	memcpy( &adj.tpa, &dev->adj.tpa, sizeof(OffsDef));
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ci	adj.rgamma    = dev->adj.rgamma;
198141cc406Sopenharmony_ci	adj.ggamma    = dev->adj.ggamma;
199141cc406Sopenharmony_ci	adj.bgamma    = dev->adj.bgamma;
200141cc406Sopenharmony_ci	adj.graygamma = dev->adj.graygamma;
201141cc406Sopenharmony_ci
202141cc406Sopenharmony_ci	if( dev->adj.direct_io )
203141cc406Sopenharmony_ci		PtDrvIoctl( _PTDRV_ADJUST, &adj );
204141cc406Sopenharmony_ci	else
205141cc406Sopenharmony_ci		ioctl( handle, _PTDRV_ADJUST, &adj );
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci	dev->initialized = SANE_TRUE;
208141cc406Sopenharmony_ci	return handle;
209141cc406Sopenharmony_ci}
210141cc406Sopenharmony_ci
211141cc406Sopenharmony_ci/**
212141cc406Sopenharmony_ci */
213141cc406Sopenharmony_cistatic int ppDev_close( Plustek_Device *dev )
214141cc406Sopenharmony_ci{
215141cc406Sopenharmony_ci	if( dev->adj.direct_io )
216141cc406Sopenharmony_ci		return PtDrvClose();
217141cc406Sopenharmony_ci	else
218141cc406Sopenharmony_ci		return close( dev->fd );
219141cc406Sopenharmony_ci}
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_ci/**
222141cc406Sopenharmony_ci */
223141cc406Sopenharmony_cistatic int ppDev_getCaps( Plustek_Device *dev )
224141cc406Sopenharmony_ci{
225141cc406Sopenharmony_ci	if( dev->adj.direct_io )
226141cc406Sopenharmony_ci		return PtDrvIoctl( _PTDRV_GET_CAPABILITIES, &dev->caps );
227141cc406Sopenharmony_ci	else
228141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_GET_CAPABILITIES, &dev->caps );
229141cc406Sopenharmony_ci}
230141cc406Sopenharmony_ci
231141cc406Sopenharmony_ci/**
232141cc406Sopenharmony_ci */
233141cc406Sopenharmony_cistatic int ppDev_getLensInfo( Plustek_Device *dev, pLensInfo lens )
234141cc406Sopenharmony_ci{
235141cc406Sopenharmony_ci	if( dev->adj.direct_io )
236141cc406Sopenharmony_ci		return  PtDrvIoctl( _PTDRV_GET_LENSINFO, lens );
237141cc406Sopenharmony_ci	else
238141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_GET_LENSINFO, lens );
239141cc406Sopenharmony_ci}
240141cc406Sopenharmony_ci
241141cc406Sopenharmony_ci/**
242141cc406Sopenharmony_ci */
243141cc406Sopenharmony_cistatic int ppDev_getCropInfo( Plustek_Device *dev, pCropInfo crop )
244141cc406Sopenharmony_ci{
245141cc406Sopenharmony_ci	if( dev->adj.direct_io )
246141cc406Sopenharmony_ci		return PtDrvIoctl( _PTDRV_GET_CROPINFO, crop );
247141cc406Sopenharmony_ci	else
248141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_GET_CROPINFO, crop );
249141cc406Sopenharmony_ci}
250141cc406Sopenharmony_ci
251141cc406Sopenharmony_ci/**
252141cc406Sopenharmony_ci */
253141cc406Sopenharmony_cistatic int ppDev_putImgInfo( Plustek_Device *dev, pImgDef img )
254141cc406Sopenharmony_ci{
255141cc406Sopenharmony_ci	if( dev->adj.direct_io )
256141cc406Sopenharmony_ci		return PtDrvIoctl( _PTDRV_PUT_IMAGEINFO, img );
257141cc406Sopenharmony_ci	else
258141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_PUT_IMAGEINFO, img );
259141cc406Sopenharmony_ci}
260141cc406Sopenharmony_ci
261141cc406Sopenharmony_ci/**
262141cc406Sopenharmony_ci */
263141cc406Sopenharmony_cistatic int ppDev_setScanEnv( Plustek_Device *dev, pScanInfo sinfo )
264141cc406Sopenharmony_ci{
265141cc406Sopenharmony_ci	if( dev->adj.direct_io )
266141cc406Sopenharmony_ci		return PtDrvIoctl( _PTDRV_SET_ENV, sinfo );
267141cc406Sopenharmony_ci	else
268141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_SET_ENV, sinfo );
269141cc406Sopenharmony_ci}
270141cc406Sopenharmony_ci
271141cc406Sopenharmony_ci/**
272141cc406Sopenharmony_ci */
273141cc406Sopenharmony_cistatic int ppDev_startScan( Plustek_Device *dev, pStartScan start )
274141cc406Sopenharmony_ci{
275141cc406Sopenharmony_ci	if( dev->adj.direct_io )
276141cc406Sopenharmony_ci		return PtDrvIoctl( _PTDRV_START_SCAN, start );
277141cc406Sopenharmony_ci	else
278141cc406Sopenharmony_ci		return ioctl( dev->fd, _PTDRV_START_SCAN, start );
279141cc406Sopenharmony_ci}
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_ci/** function to send a gamma table to the kernel module. As the default table
282141cc406Sopenharmony_ci *  entry is 16-bit, but the maps are 8-bit, we have to copy the values...
283141cc406Sopenharmony_ci */
284141cc406Sopenharmony_cistatic int ppDev_setMap( Plustek_Device *dev, SANE_Word *map,
285141cc406Sopenharmony_ci						 SANE_Word length, SANE_Word channel )
286141cc406Sopenharmony_ci{
287141cc406Sopenharmony_ci	SANE_Byte *buf;
288141cc406Sopenharmony_ci	SANE_Word  i;
289141cc406Sopenharmony_ci	MapDef     m;
290141cc406Sopenharmony_ci
291141cc406Sopenharmony_ci	m.len    = length;
292141cc406Sopenharmony_ci	m.map_id = channel;
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci	m.map = (void *)map;
295141cc406Sopenharmony_ci
296141cc406Sopenharmony_ci	DBG(_DBG_INFO,"Setting map[%u] at 0x%08lx\n", channel, (unsigned long)map);
297141cc406Sopenharmony_ci
298141cc406Sopenharmony_ci	buf = (SANE_Byte*)malloc( m.len );
299141cc406Sopenharmony_ci
300141cc406Sopenharmony_ci	if( !buf )
301141cc406Sopenharmony_ci		return _E_ALLOC;
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci	for( i = 0; i < m.len; i++ ) {
304141cc406Sopenharmony_ci		buf[i] = (SANE_Byte)map[i];
305141cc406Sopenharmony_ci
306141cc406Sopenharmony_ci		if( map[i] > 0xFF )
307141cc406Sopenharmony_ci			buf[i] = 0xFF;
308141cc406Sopenharmony_ci	}
309141cc406Sopenharmony_ci
310141cc406Sopenharmony_ci	m.map = buf;
311141cc406Sopenharmony_ci
312141cc406Sopenharmony_ci	if( dev->adj.direct_io )
313141cc406Sopenharmony_ci		PtDrvIoctl( _PTDRV_SETMAP, &m );
314141cc406Sopenharmony_ci	else
315141cc406Sopenharmony_ci		ioctl( dev->fd, _PTDRV_SETMAP, &m );
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_ci	/* we ignore the return values */
318141cc406Sopenharmony_ci	free( buf );
319141cc406Sopenharmony_ci	return 0;
320141cc406Sopenharmony_ci}
321141cc406Sopenharmony_ci
322141cc406Sopenharmony_ci/**
323141cc406Sopenharmony_ci */
324141cc406Sopenharmony_cistatic int ppDev_stopScan( Plustek_Device *dev, short *mode )
325141cc406Sopenharmony_ci{
326141cc406Sopenharmony_ci	int retval, tmp;
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci	/* save this one... */
329141cc406Sopenharmony_ci	tmp = *mode;
330141cc406Sopenharmony_ci
331141cc406Sopenharmony_ci	if( dev->adj.direct_io )
332141cc406Sopenharmony_ci		retval = PtDrvIoctl( _PTDRV_STOP_SCAN, mode );
333141cc406Sopenharmony_ci	else
334141cc406Sopenharmony_ci		retval = ioctl( dev->fd, _PTDRV_STOP_SCAN, mode );
335141cc406Sopenharmony_ci
336141cc406Sopenharmony_ci	/* ... and use it here */
337141cc406Sopenharmony_ci	if( 0 == tmp ) {
338141cc406Sopenharmony_ci		if( dev->adj.direct_io )
339141cc406Sopenharmony_ci			PtDrvIoctl( _PTDRV_CLOSE_DEVICE, 0 );
340141cc406Sopenharmony_ci		else
341141cc406Sopenharmony_ci			ioctl( dev->fd, _PTDRV_CLOSE_DEVICE, 0);
342141cc406Sopenharmony_ci	}else
343141cc406Sopenharmony_ci		sleep( 1 );
344141cc406Sopenharmony_ci
345141cc406Sopenharmony_ci	return retval;
346141cc406Sopenharmony_ci}
347141cc406Sopenharmony_ci
348141cc406Sopenharmony_ci/**
349141cc406Sopenharmony_ci */
350141cc406Sopenharmony_cistatic int ppDev_readImage( Plustek_Device *dev,
351141cc406Sopenharmony_ci                            SANE_Byte *buf, unsigned long data_length )
352141cc406Sopenharmony_ci{
353141cc406Sopenharmony_ci	if( dev->adj.direct_io )
354141cc406Sopenharmony_ci		return PtDrvRead( buf, data_length );
355141cc406Sopenharmony_ci	else
356141cc406Sopenharmony_ci		return read( dev->fd, buf, data_length );
357141cc406Sopenharmony_ci}
358141cc406Sopenharmony_ci
359141cc406Sopenharmony_ci/* END PLUSTEK-PP_WRAPPER.C .................................................*/
360