12a97ec55SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
32a97ec55SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
42a97ec55SAndrew Rist * or more contributor license agreements. See the NOTICE file
52a97ec55SAndrew Rist * distributed with this work for additional information
62a97ec55SAndrew Rist * regarding copyright ownership. The ASF licenses this file
72a97ec55SAndrew Rist * to you under the Apache License, Version 2.0 (the
82a97ec55SAndrew Rist * "License"); you may not use this file except in compliance
92a97ec55SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
112a97ec55SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
132a97ec55SAndrew Rist * Unless required by applicable law or agreed to in writing,
142a97ec55SAndrew Rist * software distributed under the License is distributed on an
152a97ec55SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162a97ec55SAndrew Rist * KIND, either express or implied. See the License for the
172a97ec55SAndrew Rist * specific language governing permissions and limitations
182a97ec55SAndrew Rist * under the License.
19cdf0e10cSrcweir *
202a97ec55SAndrew Rist *************************************************************/
212a97ec55SAndrew Rist
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_extensions.hxx"
24cdf0e10cSrcweir #include <cstdarg>
25cdf0e10cSrcweir #include <math.h>
26cdf0e10cSrcweir #include <osl/file.h>
27cdf0e10cSrcweir #include <tools/stream.hxx>
28cdf0e10cSrcweir #include <sane.hxx>
29cdf0e10cSrcweir #include <dlfcn.h>
30cdf0e10cSrcweir #include <stdio.h>
31cdf0e10cSrcweir #include <unistd.h>
32cdf0e10cSrcweir #include <sys/time.h>
33cdf0e10cSrcweir #include <sys/types.h>
34cdf0e10cSrcweir #include <sal/config.h>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
37cdf0e10cSrcweir #include <stdarg.h>
38cdf0e10cSrcweir #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
39cdf0e10cSrcweir #else
40cdf0e10cSrcweir #define dump_state( a, b, c, d ) ;
41cdf0e10cSrcweir #endif
dbg_msg(const char * pString,...)42cdf0e10cSrcweir inline void dbg_msg( const char* pString, ... )
43cdf0e10cSrcweir {
44cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
45cdf0e10cSrcweir va_list ap;
46cdf0e10cSrcweir va_start( ap, pString );
47cdf0e10cSrcweir vfprintf( stderr, pString, ap );
48cdf0e10cSrcweir va_end( ap );
49cdf0e10cSrcweir #else
50cdf0e10cSrcweir (void)pString;
51cdf0e10cSrcweir #endif
52cdf0e10cSrcweir }
53cdf0e10cSrcweir
54cdf0e10cSrcweir #define FAIL_SHUTDOWN_STATE( x, y, z ) \
55cdf0e10cSrcweir if( x != SANE_STATUS_GOOD ) \
56cdf0e10cSrcweir { \
57cdf0e10cSrcweir dump_state( "%s returned error %d (%s)\n", \
58cdf0e10cSrcweir y, x, p_strstatus( x ) ); \
59cdf0e10cSrcweir DeInit(); \
60cdf0e10cSrcweir return z; \
61cdf0e10cSrcweir }
62cdf0e10cSrcweir
63cdf0e10cSrcweir #define FAIL_STATE( x, y, z ) \
64cdf0e10cSrcweir if( x != SANE_STATUS_GOOD ) \
65cdf0e10cSrcweir { \
66cdf0e10cSrcweir dump_state( "%s returned error %d (%s)\n", \
67cdf0e10cSrcweir y, x, p_strstatus( x ) ); \
68cdf0e10cSrcweir return z; \
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
71cdf0e10cSrcweir #define DUMP_STATE( x, y ) \
72cdf0e10cSrcweir if( x != SANE_STATUS_GOOD ) \
73cdf0e10cSrcweir { \
74cdf0e10cSrcweir dump_state( "%s returned error %d (%s)\n", \
75cdf0e10cSrcweir y, x, p_strstatus( x ) ); \
76cdf0e10cSrcweir }
77cdf0e10cSrcweir
78cdf0e10cSrcweir #define CHECK_STATE( x, y ) \
79cdf0e10cSrcweir if( x != SANE_STATUS_GOOD ) \
80cdf0e10cSrcweir { \
81cdf0e10cSrcweir dump_state( "%s returned error %d (%s)\n", \
82cdf0e10cSrcweir y, x, p_strstatus( x ) ); \
83cdf0e10cSrcweir } \
84cdf0e10cSrcweir else
85cdf0e10cSrcweir
86cdf0e10cSrcweir int Sane::nRefCount = 0;
87cdf0e10cSrcweir oslModule Sane::pSaneLib = 0;
88cdf0e10cSrcweir SANE_Int Sane::nVersion = 0;
89cdf0e10cSrcweir SANE_Device** Sane::ppDevices = 0;
90cdf0e10cSrcweir int Sane::nDevices = 0;
91cdf0e10cSrcweir
92cdf0e10cSrcweir SANE_Status (*Sane::p_init)( SANE_Int*,
93cdf0e10cSrcweir SANE_Auth_Callback ) = 0;
94cdf0e10cSrcweir void (*Sane::p_exit)() = 0;
95cdf0e10cSrcweir SANE_Status (*Sane::p_get_devices)( const SANE_Device***,
96cdf0e10cSrcweir SANE_Bool ) = 0;
97cdf0e10cSrcweir SANE_Status (*Sane::p_open)( SANE_String_Const, SANE_Handle ) = 0;
98cdf0e10cSrcweir void (*Sane::p_close)( SANE_Handle ) = 0;
99cdf0e10cSrcweir const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
100cdf0e10cSrcweir SANE_Handle, SANE_Int ) = 0;
101cdf0e10cSrcweir SANE_Status (*Sane::p_control_option)( SANE_Handle, SANE_Int,
102cdf0e10cSrcweir SANE_Action, void*,
103cdf0e10cSrcweir SANE_Int* ) = 0;
104cdf0e10cSrcweir SANE_Status (*Sane::p_get_parameters)( SANE_Handle,
105cdf0e10cSrcweir SANE_Parameters* ) = 0;
106cdf0e10cSrcweir SANE_Status (*Sane::p_start)( SANE_Handle ) = 0;
107cdf0e10cSrcweir SANE_Status (*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
108cdf0e10cSrcweir SANE_Int* ) = 0;
109cdf0e10cSrcweir void (*Sane::p_cancel)( SANE_Handle ) = 0;
110cdf0e10cSrcweir SANE_Status (*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = 0;
111cdf0e10cSrcweir SANE_Status (*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = 0;
112cdf0e10cSrcweir SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = 0;
113cdf0e10cSrcweir
114cdf0e10cSrcweir static sal_Bool bSaneSymbolLoadFailed = sal_False;
115cdf0e10cSrcweir
LoadSymbol(const char * pSymbolname)116cdf0e10cSrcweir inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname );
119cdf0e10cSrcweir if( ! pFunction )
120cdf0e10cSrcweir {
121cdf0e10cSrcweir fprintf( stderr, "Could not load symbol %s\n",
122cdf0e10cSrcweir pSymbolname );
123cdf0e10cSrcweir bSaneSymbolLoadFailed = sal_True;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir return pFunction;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir
ControlOption(int nOption,SANE_Action nAction,void * pData)128cdf0e10cSrcweir SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction,
129cdf0e10cSrcweir void* pData )
130cdf0e10cSrcweir {
131cdf0e10cSrcweir SANE_Status nStatus = SANE_STATUS_GOOD;
132cdf0e10cSrcweir SANE_Int nInfo = 0;
133cdf0e10cSrcweir
134cdf0e10cSrcweir nStatus = p_control_option( maHandle, (SANE_Int)nOption,
135cdf0e10cSrcweir nAction, pData, &nInfo );
136cdf0e10cSrcweir DUMP_STATE( nStatus, "sane_control_option" );
137cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
138cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
139cdf0e10cSrcweir {
140cdf0e10cSrcweir const char* pAction = "Unknown";
141cdf0e10cSrcweir switch( nAction )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir case SANE_ACTION_GET_VALUE:
144cdf0e10cSrcweir pAction = "SANE_ACTION_GET_VALUE";break;
145cdf0e10cSrcweir case SANE_ACTION_SET_VALUE:
146cdf0e10cSrcweir pAction = "SANE_ACTION_SET_VALUE";break;
147cdf0e10cSrcweir case SANE_ACTION_SET_AUTO:
148cdf0e10cSrcweir pAction = "SANE_ACTION_SET_AUTO";break;
149cdf0e10cSrcweir }
150cdf0e10cSrcweir dbg_msg( "Option: \"%s\" action: %s\n",
151cdf0e10cSrcweir ByteString( GetOptionName( nOption ), gsl_getSystemTextEncoding() ).GetBuffer(),
152cdf0e10cSrcweir pAction );
153cdf0e10cSrcweir }
154cdf0e10cSrcweir #endif
155cdf0e10cSrcweir // if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
156cdf0e10cSrcweir if( nInfo & SANE_INFO_RELOAD_OPTIONS )
157cdf0e10cSrcweir ReloadOptions();
158cdf0e10cSrcweir return nStatus;
159cdf0e10cSrcweir }
160cdf0e10cSrcweir
Sane()161cdf0e10cSrcweir Sane::Sane() :
162cdf0e10cSrcweir mppOptions( 0 ),
163cdf0e10cSrcweir mnOptions( 0 ),
164cdf0e10cSrcweir mnDevice( -1 ),
165cdf0e10cSrcweir maHandle( 0 )
166cdf0e10cSrcweir {
167cdf0e10cSrcweir if( ! nRefCount || ! pSaneLib )
168cdf0e10cSrcweir Init();
169cdf0e10cSrcweir nRefCount++;
170cdf0e10cSrcweir };
171cdf0e10cSrcweir
~Sane()172cdf0e10cSrcweir Sane::~Sane()
173cdf0e10cSrcweir {
174cdf0e10cSrcweir if( IsOpen() )
175cdf0e10cSrcweir Close();
176cdf0e10cSrcweir nRefCount--;
177cdf0e10cSrcweir if( ! nRefCount && pSaneLib )
178cdf0e10cSrcweir DeInit();
179cdf0e10cSrcweir }
180cdf0e10cSrcweir
Init()181cdf0e10cSrcweir void Sane::Init()
182cdf0e10cSrcweir {
183cdf0e10cSrcweir ::rtl::OUString sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ) );
184cdf0e10cSrcweir pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
185cdf0e10cSrcweir if( ! pSaneLib )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir sSaneLibName = ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ".1" );
188cdf0e10cSrcweir pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
189cdf0e10cSrcweir }
190cdf0e10cSrcweir // try reasonable places that might not be in the library search path
191cdf0e10cSrcweir if( ! pSaneLib )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir ::rtl::OUString sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION ) );
194cdf0e10cSrcweir osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
195cdf0e10cSrcweir pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
196cdf0e10cSrcweir }
197cdf0e10cSrcweir
198cdf0e10cSrcweir if( pSaneLib )
199cdf0e10cSrcweir {
200cdf0e10cSrcweir bSaneSymbolLoadFailed = sal_False;
201cdf0e10cSrcweir p_init = (SANE_Status(*)(SANE_Int*, SANE_Auth_Callback ))
202cdf0e10cSrcweir LoadSymbol( "sane_init" );
203cdf0e10cSrcweir p_exit = (void(*)())
204cdf0e10cSrcweir LoadSymbol( "sane_exit" );
205cdf0e10cSrcweir p_get_devices = (SANE_Status(*)(const SANE_Device***,
206cdf0e10cSrcweir SANE_Bool ))
207cdf0e10cSrcweir LoadSymbol( "sane_get_devices" );
208cdf0e10cSrcweir p_open = (SANE_Status(*)(SANE_String_Const, SANE_Handle ))
209cdf0e10cSrcweir LoadSymbol( "sane_open" );
210cdf0e10cSrcweir p_close = (void(*)(SANE_Handle))
211cdf0e10cSrcweir LoadSymbol( "sane_close" );
212cdf0e10cSrcweir p_get_option_descriptor = (const SANE_Option_Descriptor*(*)(SANE_Handle,
213cdf0e10cSrcweir SANE_Int))
214cdf0e10cSrcweir LoadSymbol( "sane_get_option_descriptor" );
215cdf0e10cSrcweir p_control_option = (SANE_Status(*)(SANE_Handle, SANE_Int,
216cdf0e10cSrcweir SANE_Action, void*, SANE_Int*))
217cdf0e10cSrcweir LoadSymbol( "sane_control_option" );
218cdf0e10cSrcweir p_get_parameters = (SANE_Status(*)(SANE_Handle,SANE_Parameters*))
219cdf0e10cSrcweir LoadSymbol( "sane_get_parameters" );
220cdf0e10cSrcweir p_start = (SANE_Status(*)(SANE_Handle))
221cdf0e10cSrcweir LoadSymbol( "sane_start" );
222cdf0e10cSrcweir p_read = (SANE_Status(*)(SANE_Handle, SANE_Byte*,
223cdf0e10cSrcweir SANE_Int, SANE_Int* ))
224cdf0e10cSrcweir LoadSymbol( "sane_read" );
225cdf0e10cSrcweir p_cancel = (void(*)(SANE_Handle))
226cdf0e10cSrcweir LoadSymbol( "sane_cancel" );
227cdf0e10cSrcweir p_set_io_mode = (SANE_Status(*)(SANE_Handle, SANE_Bool))
228cdf0e10cSrcweir LoadSymbol( "sane_set_io_mode" );
229cdf0e10cSrcweir p_get_select_fd = (SANE_Status(*)(SANE_Handle, SANE_Int*))
230cdf0e10cSrcweir LoadSymbol( "sane_get_select_fd" );
231cdf0e10cSrcweir p_strstatus = (SANE_String_Const(*)(SANE_Status))
232cdf0e10cSrcweir LoadSymbol( "sane_strstatus" );
233cdf0e10cSrcweir if( bSaneSymbolLoadFailed )
234cdf0e10cSrcweir DeInit();
235cdf0e10cSrcweir else
236cdf0e10cSrcweir {
237cdf0e10cSrcweir SANE_Status nStatus = p_init( &nVersion, 0 );
238cdf0e10cSrcweir FAIL_SHUTDOWN_STATE( nStatus, "sane_init", );
239cdf0e10cSrcweir nStatus = p_get_devices( (const SANE_Device***)&ppDevices,
240cdf0e10cSrcweir SANE_FALSE );
241cdf0e10cSrcweir FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", );
242cdf0e10cSrcweir for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ ) ;
243cdf0e10cSrcweir }
244cdf0e10cSrcweir }
245cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
246cdf0e10cSrcweir else
247cdf0e10cSrcweir fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION,
248cdf0e10cSrcweir dlerror() );
249cdf0e10cSrcweir #endif
250cdf0e10cSrcweir }
251cdf0e10cSrcweir
DeInit()252cdf0e10cSrcweir void Sane::DeInit()
253cdf0e10cSrcweir {
254cdf0e10cSrcweir if( pSaneLib )
255cdf0e10cSrcweir {
256cdf0e10cSrcweir p_exit();
257cdf0e10cSrcweir osl_unloadModule( pSaneLib );
258cdf0e10cSrcweir pSaneLib = 0;
259cdf0e10cSrcweir }
260cdf0e10cSrcweir }
261cdf0e10cSrcweir
ReloadDevices()262cdf0e10cSrcweir void Sane::ReloadDevices()
263cdf0e10cSrcweir {
264cdf0e10cSrcweir if( IsOpen() )
265cdf0e10cSrcweir Close();
266cdf0e10cSrcweir DeInit();
267cdf0e10cSrcweir Init();
268cdf0e10cSrcweir }
269cdf0e10cSrcweir
ReloadOptions()270cdf0e10cSrcweir void Sane::ReloadOptions()
271cdf0e10cSrcweir {
272cdf0e10cSrcweir if( ! IsOpen() )
273cdf0e10cSrcweir return;
274cdf0e10cSrcweir
275cdf0e10cSrcweir SANE_Option_Descriptor* pZero = (SANE_Option_Descriptor*)
276cdf0e10cSrcweir p_get_option_descriptor( maHandle, 0 );
277cdf0e10cSrcweir SANE_Word pOptions[2];
278cdf0e10cSrcweir SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE,
279cdf0e10cSrcweir (void*)pOptions, NULL );
280cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
281cdf0e10cSrcweir fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) );
282cdf0e10cSrcweir
283cdf0e10cSrcweir mnOptions = pOptions[ 0 ];
284cdf0e10cSrcweir if( (size_t)pZero->size > sizeof( SANE_Word ) )
285*4b37ad1dSmseidel fprintf( stderr, "driver returned number of options with larger size than SANE_Word !!!\n" );
286cdf0e10cSrcweir if( mppOptions )
287cdf0e10cSrcweir delete [] mppOptions;
288cdf0e10cSrcweir mppOptions = (const SANE_Option_Descriptor**)new SANE_Option_Descriptor*[ mnOptions ];
289cdf0e10cSrcweir mppOptions[ 0 ] = (SANE_Option_Descriptor*)pZero;
290cdf0e10cSrcweir for( int i = 1; i < mnOptions; i++ )
291cdf0e10cSrcweir mppOptions[ i ] = (SANE_Option_Descriptor*)
292cdf0e10cSrcweir p_get_option_descriptor( maHandle, i );
293cdf0e10cSrcweir
294cdf0e10cSrcweir CheckConsistency( NULL, sal_True );
295cdf0e10cSrcweir
296cdf0e10cSrcweir maReloadOptionsLink.Call( this );
297cdf0e10cSrcweir }
298cdf0e10cSrcweir
Open(const char * name)299cdf0e10cSrcweir sal_Bool Sane::Open( const char* name )
300cdf0e10cSrcweir {
301cdf0e10cSrcweir int i;
302cdf0e10cSrcweir
303cdf0e10cSrcweir SANE_Status nStatus = p_open( (SANE_String_Const)name, &maHandle );
304cdf0e10cSrcweir FAIL_STATE( nStatus, "sane_open", sal_False );
305cdf0e10cSrcweir
306cdf0e10cSrcweir ReloadOptions();
307cdf0e10cSrcweir
308cdf0e10cSrcweir if( mnDevice == -1 )
309cdf0e10cSrcweir {
310cdf0e10cSrcweir ByteString aDevice( name );
311cdf0e10cSrcweir for( i = 0; i < nDevices; i++ )
312cdf0e10cSrcweir {
313cdf0e10cSrcweir if( aDevice.Equals( ppDevices[i]->name ) )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir mnDevice = i;
316cdf0e10cSrcweir break;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir }
319cdf0e10cSrcweir }
320cdf0e10cSrcweir
321cdf0e10cSrcweir return sal_True;
322cdf0e10cSrcweir }
323cdf0e10cSrcweir
Open(int n)324cdf0e10cSrcweir sal_Bool Sane::Open( int n )
325cdf0e10cSrcweir {
326cdf0e10cSrcweir if( n >= 0 && n < nDevices )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir mnDevice = n;
329cdf0e10cSrcweir return Open( (char*)ppDevices[n]->name );
330cdf0e10cSrcweir }
331cdf0e10cSrcweir return sal_False;
332cdf0e10cSrcweir }
333cdf0e10cSrcweir
Close()334cdf0e10cSrcweir void Sane::Close()
335cdf0e10cSrcweir {
336cdf0e10cSrcweir if( maHandle )
337cdf0e10cSrcweir {
338cdf0e10cSrcweir p_close( maHandle );
339cdf0e10cSrcweir delete [] mppOptions;
340cdf0e10cSrcweir mppOptions = 0;
341cdf0e10cSrcweir maHandle = 0;
342cdf0e10cSrcweir mnDevice = -1;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir }
345cdf0e10cSrcweir
GetOptionByName(const char * rName)346cdf0e10cSrcweir int Sane::GetOptionByName( const char* rName )
347cdf0e10cSrcweir {
348cdf0e10cSrcweir int i;
349cdf0e10cSrcweir ByteString aOption( rName );
350cdf0e10cSrcweir for( i = 0; i < mnOptions; i++ )
351cdf0e10cSrcweir {
352cdf0e10cSrcweir if( mppOptions[i]->name && aOption.Equals( mppOptions[i]->name ) )
353cdf0e10cSrcweir return i;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir return -1;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir
GetOptionValue(int n,sal_Bool & rRet)358cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, sal_Bool& rRet )
359cdf0e10cSrcweir {
360cdf0e10cSrcweir if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
361cdf0e10cSrcweir return sal_False;
362cdf0e10cSrcweir SANE_Word nRet;
363cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet );
364cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
365cdf0e10cSrcweir return sal_False;
366cdf0e10cSrcweir
367cdf0e10cSrcweir rRet = nRet;
368cdf0e10cSrcweir return sal_True;
369cdf0e10cSrcweir }
370cdf0e10cSrcweir
GetOptionValue(int n,ByteString & rRet)371cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, ByteString& rRet )
372cdf0e10cSrcweir {
373cdf0e10cSrcweir sal_Bool bSuccess = sal_False;
374cdf0e10cSrcweir if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
375cdf0e10cSrcweir return sal_False;
376cdf0e10cSrcweir char* pRet = new char[mppOptions[n]->size+1];
377cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
378cdf0e10cSrcweir if( nStatus == SANE_STATUS_GOOD )
379cdf0e10cSrcweir {
380cdf0e10cSrcweir bSuccess = sal_True;
381cdf0e10cSrcweir rRet = pRet;
382cdf0e10cSrcweir }
383cdf0e10cSrcweir delete [] pRet;
384cdf0e10cSrcweir return bSuccess;
385cdf0e10cSrcweir }
386cdf0e10cSrcweir
GetOptionValue(int n,double & rRet,int nElement)387cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, double& rRet, int nElement )
388cdf0e10cSrcweir {
389cdf0e10cSrcweir sal_Bool bSuccess = sal_False;
390cdf0e10cSrcweir
391cdf0e10cSrcweir if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
392cdf0e10cSrcweir mppOptions[n]->type != SANE_TYPE_FIXED ) )
393cdf0e10cSrcweir return sal_False;
394cdf0e10cSrcweir
395cdf0e10cSrcweir SANE_Word* pRet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
396cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
397cdf0e10cSrcweir if( nStatus == SANE_STATUS_GOOD )
398cdf0e10cSrcweir {
399cdf0e10cSrcweir bSuccess = sal_True;
400cdf0e10cSrcweir if( mppOptions[n]->type == SANE_TYPE_INT )
401cdf0e10cSrcweir rRet = (double)pRet[ nElement ];
402cdf0e10cSrcweir else
403cdf0e10cSrcweir rRet = SANE_UNFIX( pRet[nElement] );
404cdf0e10cSrcweir }
405cdf0e10cSrcweir delete [] pRet;
406cdf0e10cSrcweir return bSuccess;
407cdf0e10cSrcweir }
408cdf0e10cSrcweir
GetOptionValue(int n,double * pSet)409cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, double* pSet )
410cdf0e10cSrcweir {
411cdf0e10cSrcweir if( ! maHandle || ! ( mppOptions[n]->type == SANE_TYPE_FIXED ||
412cdf0e10cSrcweir mppOptions[n]->type == SANE_TYPE_INT ) )
413cdf0e10cSrcweir return sal_False;
414cdf0e10cSrcweir
415cdf0e10cSrcweir SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
416cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet );
417cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
418cdf0e10cSrcweir {
419cdf0e10cSrcweir delete [] pFixedSet;
420cdf0e10cSrcweir return sal_False;
421cdf0e10cSrcweir }
422cdf0e10cSrcweir for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ )
423cdf0e10cSrcweir {
424cdf0e10cSrcweir if( mppOptions[n]->type == SANE_TYPE_FIXED )
425cdf0e10cSrcweir pSet[i] = SANE_UNFIX( pFixedSet[i] );
426cdf0e10cSrcweir else
427cdf0e10cSrcweir pSet[i] = (double) pFixedSet[i];
428cdf0e10cSrcweir }
429cdf0e10cSrcweir delete [] pFixedSet;
430cdf0e10cSrcweir return sal_True;
431cdf0e10cSrcweir }
432cdf0e10cSrcweir
SetOptionValue(int n,sal_Bool bSet)433cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, sal_Bool bSet )
434cdf0e10cSrcweir {
435cdf0e10cSrcweir if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
436cdf0e10cSrcweir return sal_False;
437cdf0e10cSrcweir SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
438cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nRet );
439cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
440cdf0e10cSrcweir return sal_False;
441cdf0e10cSrcweir return sal_True;
442cdf0e10cSrcweir }
443cdf0e10cSrcweir
SetOptionValue(int n,const String & rSet)444cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, const String& rSet )
445cdf0e10cSrcweir {
446cdf0e10cSrcweir if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
447cdf0e10cSrcweir return sal_False;
448cdf0e10cSrcweir ByteString aSet( rSet, gsl_getSystemTextEncoding() );
449cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, (void*)aSet.GetBuffer() );
450cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
451cdf0e10cSrcweir return sal_False;
452cdf0e10cSrcweir return sal_True;
453cdf0e10cSrcweir }
454cdf0e10cSrcweir
SetOptionValue(int n,double fSet,int nElement)455cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, double fSet, int nElement )
456cdf0e10cSrcweir {
457cdf0e10cSrcweir sal_Bool bSuccess = sal_False;
458cdf0e10cSrcweir
459cdf0e10cSrcweir if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
460cdf0e10cSrcweir mppOptions[n]->type != SANE_TYPE_FIXED ) )
461cdf0e10cSrcweir return sal_False;
462cdf0e10cSrcweir
463cdf0e10cSrcweir SANE_Status nStatus;
464cdf0e10cSrcweir if( mppOptions[n]->size/sizeof(SANE_Word) > 1 )
465cdf0e10cSrcweir {
466cdf0e10cSrcweir SANE_Word* pSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
467cdf0e10cSrcweir nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet );
468cdf0e10cSrcweir if( nStatus == SANE_STATUS_GOOD )
469cdf0e10cSrcweir {
470cdf0e10cSrcweir pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ?
471cdf0e10cSrcweir (SANE_Word)fSet : SANE_FIX( fSet );
472cdf0e10cSrcweir nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pSet );
473cdf0e10cSrcweir }
474cdf0e10cSrcweir delete [] pSet;
475cdf0e10cSrcweir }
476cdf0e10cSrcweir else
477cdf0e10cSrcweir {
478cdf0e10cSrcweir SANE_Word nSetTo =
479cdf0e10cSrcweir mppOptions[n]->type == SANE_TYPE_INT ?
480cdf0e10cSrcweir (SANE_Word)fSet : SANE_FIX( fSet );
481cdf0e10cSrcweir
482cdf0e10cSrcweir nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo );
483cdf0e10cSrcweir if( nStatus == SANE_STATUS_GOOD )
484cdf0e10cSrcweir bSuccess = sal_True;
485cdf0e10cSrcweir }
486cdf0e10cSrcweir return bSuccess;
487cdf0e10cSrcweir }
488cdf0e10cSrcweir
SetOptionValue(int n,double * pSet)489cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, double* pSet )
490cdf0e10cSrcweir {
491cdf0e10cSrcweir if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
492cdf0e10cSrcweir mppOptions[n]->type != SANE_TYPE_FIXED ) )
493cdf0e10cSrcweir return sal_False;
494cdf0e10cSrcweir SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
495cdf0e10cSrcweir for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ )
496cdf0e10cSrcweir {
497cdf0e10cSrcweir if( mppOptions[n]->type == SANE_TYPE_FIXED )
498cdf0e10cSrcweir pFixedSet[i] = SANE_FIX( pSet[i] );
499cdf0e10cSrcweir else
500cdf0e10cSrcweir pFixedSet[i] = (SANE_Word)pSet[i];
501cdf0e10cSrcweir }
502cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet );
503cdf0e10cSrcweir delete [] pFixedSet;
504cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
505cdf0e10cSrcweir return sal_False;
506cdf0e10cSrcweir return sal_True;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir
509cdf0e10cSrcweir enum FrameStyleType {
510cdf0e10cSrcweir FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
511cdf0e10cSrcweir };
512cdf0e10cSrcweir
513cdf0e10cSrcweir #define BYTE_BUFFER_SIZE 32768
514cdf0e10cSrcweir
_ReadValue(FILE * fp,int depth)515cdf0e10cSrcweir static inline sal_uInt8 _ReadValue( FILE* fp, int depth )
516cdf0e10cSrcweir {
517cdf0e10cSrcweir if( depth == 16 )
518cdf0e10cSrcweir {
519cdf0e10cSrcweir sal_uInt16 nWord;
520cdf0e10cSrcweir // data always come in native byte order !
521cdf0e10cSrcweir // 16 bits is not really supported by backends as of now
522cdf0e10cSrcweir // e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
523cdf0e10cSrcweir // against SANE documentation (xscanimage gets the same result
524cdf0e10cSrcweir // as we do
525cdf0e10cSrcweir fread( &nWord, 1, 2, fp );
526cdf0e10cSrcweir return (sal_uInt8)( nWord / 256 );
527cdf0e10cSrcweir }
528cdf0e10cSrcweir sal_uInt8 nByte;
529cdf0e10cSrcweir fread( &nByte, 1, 1, fp );
530cdf0e10cSrcweir return nByte;
531cdf0e10cSrcweir }
532cdf0e10cSrcweir
CheckConsistency(const char * pMes,sal_Bool bInit)533cdf0e10cSrcweir sal_Bool Sane::CheckConsistency( const char* pMes, sal_Bool bInit )
534cdf0e10cSrcweir {
535cdf0e10cSrcweir static SANE_Option_Descriptor** pDescArray = NULL;
536cdf0e10cSrcweir static SANE_Option_Descriptor* pZero = NULL;
537cdf0e10cSrcweir
538cdf0e10cSrcweir if( bInit )
539cdf0e10cSrcweir {
540cdf0e10cSrcweir pDescArray = (SANE_Option_Descriptor**)mppOptions;
541cdf0e10cSrcweir if( mppOptions )
542cdf0e10cSrcweir pZero = (SANE_Option_Descriptor*)mppOptions[0];
543cdf0e10cSrcweir return sal_True;
544cdf0e10cSrcweir }
545cdf0e10cSrcweir
546cdf0e10cSrcweir sal_Bool bConsistent = sal_True;
547cdf0e10cSrcweir
548cdf0e10cSrcweir if( pDescArray != mppOptions )
549cdf0e10cSrcweir bConsistent = sal_False;
550cdf0e10cSrcweir if( pZero != mppOptions[0] )
551cdf0e10cSrcweir bConsistent = sal_False;
552cdf0e10cSrcweir
553cdf0e10cSrcweir if( ! bConsistent )
554cdf0e10cSrcweir dbg_msg( "Sane is not consistent. (%s)\n", pMes );
555cdf0e10cSrcweir
556cdf0e10cSrcweir return bConsistent;
557cdf0e10cSrcweir }
558cdf0e10cSrcweir
Start(BitmapTransporter & rBitmap)559cdf0e10cSrcweir sal_Bool Sane::Start( BitmapTransporter& rBitmap )
560cdf0e10cSrcweir {
561cdf0e10cSrcweir int nStream = 0, nLine = 0, i = 0;
562cdf0e10cSrcweir SANE_Parameters aParams;
563cdf0e10cSrcweir FrameStyleType eType = FrameStyle_Gray;
564cdf0e10cSrcweir sal_Bool bSuccess = sal_True;
565cdf0e10cSrcweir sal_Bool bWidthSet = sal_False;
566cdf0e10cSrcweir
567cdf0e10cSrcweir if( ! maHandle )
568cdf0e10cSrcweir return sal_False;
569cdf0e10cSrcweir
570cdf0e10cSrcweir int nWidthMM = 0;
571cdf0e10cSrcweir int nHeightMM = 0;
572cdf0e10cSrcweir double fTLx, fTLy, fBRx, fBRy, fResl = 0.0;
573cdf0e10cSrcweir int nOption;
574cdf0e10cSrcweir if( ( nOption = GetOptionByName( "tl-x" ) ) != -1 &&
575cdf0e10cSrcweir GetOptionValue( nOption, fTLx, 0 ) &&
576cdf0e10cSrcweir GetOptionUnit( nOption ) == SANE_UNIT_MM )
577cdf0e10cSrcweir {
578cdf0e10cSrcweir if( ( nOption = GetOptionByName( "br-x" ) ) != -1 &&
579cdf0e10cSrcweir GetOptionValue( nOption, fBRx, 0 ) &&
580cdf0e10cSrcweir GetOptionUnit( nOption ) == SANE_UNIT_MM )
581cdf0e10cSrcweir {
582cdf0e10cSrcweir nWidthMM = (int)fabs(fBRx - fTLx);
583cdf0e10cSrcweir }
584cdf0e10cSrcweir }
585cdf0e10cSrcweir if( ( nOption = GetOptionByName( "tl-y" ) ) != -1 &&
586cdf0e10cSrcweir GetOptionValue( nOption, fTLy, 0 ) &&
587cdf0e10cSrcweir GetOptionUnit( nOption ) == SANE_UNIT_MM )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir if( ( nOption = GetOptionByName( "br-y" ) ) != -1 &&
590cdf0e10cSrcweir GetOptionValue( nOption, fBRy, 0 ) &&
591cdf0e10cSrcweir GetOptionUnit( nOption ) == SANE_UNIT_MM )
592cdf0e10cSrcweir {
593cdf0e10cSrcweir nHeightMM = (int)fabs(fBRy - fTLy);
594cdf0e10cSrcweir }
595cdf0e10cSrcweir }
596cdf0e10cSrcweir if( ( nOption = GetOptionByName( "resolution" ) ) != -1 )
597cdf0e10cSrcweir GetOptionValue( nOption, fResl );
598cdf0e10cSrcweir
599cdf0e10cSrcweir sal_uInt8* pBuffer = NULL;
600cdf0e10cSrcweir
601cdf0e10cSrcweir SANE_Status nStatus = SANE_STATUS_GOOD;
602cdf0e10cSrcweir
603cdf0e10cSrcweir rBitmap.lock();
604cdf0e10cSrcweir SvMemoryStream& aConverter = rBitmap.getStream();
605cdf0e10cSrcweir aConverter.Seek( 0 );
606cdf0e10cSrcweir aConverter.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
607cdf0e10cSrcweir
608cdf0e10cSrcweir // write bitmap stream header
609cdf0e10cSrcweir aConverter << 'B' << 'M';
610cdf0e10cSrcweir aConverter << (sal_uInt32) 0;
611cdf0e10cSrcweir aConverter << (sal_uInt32) 0;
612cdf0e10cSrcweir aConverter << (sal_uInt32) 60;
613cdf0e10cSrcweir
614cdf0e10cSrcweir // write BITMAPINFOHEADER
615cdf0e10cSrcweir aConverter << (sal_uInt32)40;
616cdf0e10cSrcweir aConverter << (sal_uInt32)0; // fill in width later
617cdf0e10cSrcweir aConverter << (sal_uInt32)0; // fill in height later
618cdf0e10cSrcweir aConverter << (sal_uInt16)1;
619cdf0e10cSrcweir // create header for 24 bits
620cdf0e10cSrcweir // correct later if necessary
621cdf0e10cSrcweir aConverter << (sal_uInt16)24;
622cdf0e10cSrcweir aConverter << (sal_uInt32)0;
623cdf0e10cSrcweir aConverter << (sal_uInt32)0;
624cdf0e10cSrcweir aConverter << (sal_uInt32)0;
625cdf0e10cSrcweir aConverter << (sal_uInt32)0;
626cdf0e10cSrcweir aConverter << (sal_uInt32)0;
627cdf0e10cSrcweir aConverter << (sal_uInt32)0;
628cdf0e10cSrcweir
629cdf0e10cSrcweir for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
630cdf0e10cSrcweir {
631cdf0e10cSrcweir nStatus = p_start( maHandle );
632cdf0e10cSrcweir DUMP_STATE( nStatus, "sane_start" );
633cdf0e10cSrcweir CheckConsistency( "sane_start" );
634cdf0e10cSrcweir if( nStatus == SANE_STATUS_GOOD )
635cdf0e10cSrcweir {
636cdf0e10cSrcweir nStatus = p_get_parameters( maHandle, &aParams );
637cdf0e10cSrcweir DUMP_STATE( nStatus, "sane_get_parameters" );
638cdf0e10cSrcweir CheckConsistency( "sane_get_parameters" );
639cdf0e10cSrcweir if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0)
640cdf0e10cSrcweir {
641cdf0e10cSrcweir bSuccess = sal_False;
642cdf0e10cSrcweir break;
643cdf0e10cSrcweir }
644cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
645cdf0e10cSrcweir const char* ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
646cdf0e10cSrcweir "SANE_FRAME_RED", "SANE_FRAME_GREEN",
647cdf0e10cSrcweir "SANE_FRAME_BLUE", "Unknown !!!" };
648cdf0e10cSrcweir fprintf( stderr, "Parameters for frame %d:\n", nStream );
649cdf0e10cSrcweir if( aParams.format < 0 || aParams.format > 4 )
650cdf0e10cSrcweir aParams.format = (SANE_Frame)5;
651cdf0e10cSrcweir fprintf( stderr, "format: %s\n", ppFormats[ (int)aParams.format ] );
652cdf0e10cSrcweir fprintf( stderr, "last_frame: %s\n", aParams.last_frame ? "TRUE" : "FALSE" );
653cdf0e10cSrcweir fprintf( stderr, "depth: %d\n", (int)aParams.depth );
654cdf0e10cSrcweir fprintf( stderr, "pixels_per_line: %d\n", (int)aParams.pixels_per_line );
655cdf0e10cSrcweir fprintf( stderr, "bytes_per_line: %d\n", (int)aParams.bytes_per_line );
656cdf0e10cSrcweir #endif
657cdf0e10cSrcweir if( ! pBuffer )
658cdf0e10cSrcweir {
659cdf0e10cSrcweir pBuffer = new sal_uInt8[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ];
660cdf0e10cSrcweir }
661cdf0e10cSrcweir
662cdf0e10cSrcweir if( aParams.last_frame )
663cdf0e10cSrcweir nStream=3;
664cdf0e10cSrcweir
665cdf0e10cSrcweir switch( aParams.format )
666cdf0e10cSrcweir {
667cdf0e10cSrcweir case SANE_FRAME_GRAY:
668cdf0e10cSrcweir eType = FrameStyle_Gray;
669cdf0e10cSrcweir if( aParams.depth == 1 )
670cdf0e10cSrcweir eType = FrameStyle_BW;
671cdf0e10cSrcweir break;
672cdf0e10cSrcweir case SANE_FRAME_RGB:
673cdf0e10cSrcweir eType = FrameStyle_RGB;
674cdf0e10cSrcweir break;
675cdf0e10cSrcweir case SANE_FRAME_RED:
676cdf0e10cSrcweir case SANE_FRAME_GREEN:
677cdf0e10cSrcweir case SANE_FRAME_BLUE:
678cdf0e10cSrcweir eType = FrameStyle_Separated;
679cdf0e10cSrcweir break;
680cdf0e10cSrcweir default:
681cdf0e10cSrcweir fprintf( stderr, "Warning: unknown frame style !!!\n" );
682cdf0e10cSrcweir }
683cdf0e10cSrcweir
684cdf0e10cSrcweir sal_Bool bSynchronousRead = sal_True;
685cdf0e10cSrcweir
686cdf0e10cSrcweir // should be fail safe, but ... ??
687cdf0e10cSrcweir nStatus = p_set_io_mode( maHandle, SANE_FALSE );
688cdf0e10cSrcweir CheckConsistency( "sane_set_io_mode" );
689cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
690cdf0e10cSrcweir {
691cdf0e10cSrcweir bSynchronousRead = sal_False;
692cdf0e10cSrcweir nStatus = p_set_io_mode( maHandle, SANE_TRUE );
693cdf0e10cSrcweir CheckConsistency( "sane_set_io_mode" );
694cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
695cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
696cdf0e10cSrcweir // what ?!?
697cdf0e10cSrcweir fprintf( stderr, "Sane::Start: driver is confused\n" );
698cdf0e10cSrcweir #endif
699cdf0e10cSrcweir }
700cdf0e10cSrcweir
701cdf0e10cSrcweir SANE_Int nLen=0;
702cdf0e10cSrcweir SANE_Int fd = 0;
703cdf0e10cSrcweir
704cdf0e10cSrcweir if( ! bSynchronousRead )
705cdf0e10cSrcweir {
706cdf0e10cSrcweir nStatus = p_get_select_fd( maHandle, &fd );
707cdf0e10cSrcweir DUMP_STATE( nStatus, "sane_get_select_fd" );
708cdf0e10cSrcweir CheckConsistency( "sane_get_select_fd" );
709cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
710cdf0e10cSrcweir bSynchronousRead = sal_True;
711cdf0e10cSrcweir }
712cdf0e10cSrcweir FILE* pFrame = tmpfile();
713cdf0e10cSrcweir if( ! pFrame )
714cdf0e10cSrcweir {
715cdf0e10cSrcweir bSuccess = sal_False;
716cdf0e10cSrcweir break;
717cdf0e10cSrcweir }
718cdf0e10cSrcweir do {
719cdf0e10cSrcweir if( ! bSynchronousRead )
720cdf0e10cSrcweir {
721cdf0e10cSrcweir fd_set fdset;
722cdf0e10cSrcweir struct timeval tv;
723cdf0e10cSrcweir
724cdf0e10cSrcweir FD_ZERO( &fdset );
725cdf0e10cSrcweir FD_SET( (int)fd, &fdset );
726cdf0e10cSrcweir tv.tv_sec = 5;
727cdf0e10cSrcweir tv.tv_usec = 0;
728cdf0e10cSrcweir if( select( fd+1, &fdset, NULL, NULL, &tv ) == 0 )
729*4b37ad1dSmseidel fprintf( stderr, "Timeout on sane_read descriptor\n" );
730cdf0e10cSrcweir }
731cdf0e10cSrcweir nLen = 0;
732cdf0e10cSrcweir nStatus = p_read( maHandle, pBuffer, BYTE_BUFFER_SIZE, &nLen );
733cdf0e10cSrcweir CheckConsistency( "sane_read" );
734cdf0e10cSrcweir if( nLen && ( nStatus == SANE_STATUS_GOOD ||
735cdf0e10cSrcweir nStatus == SANE_STATUS_EOF ) )
736cdf0e10cSrcweir {
737cdf0e10cSrcweir fwrite( pBuffer, 1, nLen, pFrame );
738cdf0e10cSrcweir }
739cdf0e10cSrcweir else
740cdf0e10cSrcweir DUMP_STATE( nStatus, "sane_read" );
741cdf0e10cSrcweir } while( nStatus == SANE_STATUS_GOOD );
742cdf0e10cSrcweir if( nStatus != SANE_STATUS_EOF )
743cdf0e10cSrcweir {
744cdf0e10cSrcweir fclose( pFrame );
745cdf0e10cSrcweir bSuccess = sal_False;
746cdf0e10cSrcweir break;
747cdf0e10cSrcweir }
748cdf0e10cSrcweir
749cdf0e10cSrcweir int nFrameLength = ftell( pFrame );
750cdf0e10cSrcweir fseek( pFrame, 0, SEEK_SET );
751cdf0e10cSrcweir sal_uInt32 nWidth = (sal_uInt32) aParams.pixels_per_line;
752cdf0e10cSrcweir sal_uInt32 nHeight = (sal_uInt32) (nFrameLength / aParams.bytes_per_line);
753cdf0e10cSrcweir if( ! bWidthSet )
754cdf0e10cSrcweir {
755cdf0e10cSrcweir if( ! fResl )
756cdf0e10cSrcweir fResl = 300; // if all else fails that's a good guess
757cdf0e10cSrcweir if( ! nWidthMM )
758cdf0e10cSrcweir nWidthMM = (int)(((double)nWidth / fResl) * 25.4);
759cdf0e10cSrcweir if( ! nHeightMM )
760cdf0e10cSrcweir nHeightMM = (int)(((double)nHeight / fResl) * 25.4);
761cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
762cdf0e10cSrcweir fprintf( stderr, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth, (int)nHeight, (int)nWidthMM, (int)nHeightMM, fResl );
763cdf0e10cSrcweir #endif
764cdf0e10cSrcweir
765cdf0e10cSrcweir aConverter.Seek( 18 );
766cdf0e10cSrcweir aConverter << (sal_uInt32)nWidth;
767cdf0e10cSrcweir aConverter << (sal_uInt32)nHeight;
768cdf0e10cSrcweir aConverter.Seek( 38 );
769cdf0e10cSrcweir aConverter << (sal_uInt32)(1000*nWidth/nWidthMM);
770cdf0e10cSrcweir aConverter << (sal_uInt32)(1000*nHeight/nHeightMM);
771cdf0e10cSrcweir bWidthSet = sal_True;
772cdf0e10cSrcweir }
773cdf0e10cSrcweir aConverter.Seek(60);
774cdf0e10cSrcweir
775cdf0e10cSrcweir if( eType == FrameStyle_BW )
776cdf0e10cSrcweir {
777cdf0e10cSrcweir aConverter.Seek( 10 );
778cdf0e10cSrcweir aConverter << (sal_uInt32)64;
779cdf0e10cSrcweir aConverter.Seek( 28 );
780cdf0e10cSrcweir aConverter << (sal_uInt16) 1;
781cdf0e10cSrcweir aConverter.Seek( 54 );
782cdf0e10cSrcweir // write color table
783cdf0e10cSrcweir aConverter << (sal_uInt16)0xffff;
784cdf0e10cSrcweir aConverter << (sal_uInt8)0xff;
785cdf0e10cSrcweir aConverter << (sal_uInt8)0;
786cdf0e10cSrcweir aConverter << (sal_uInt32)0;
787cdf0e10cSrcweir aConverter.Seek( 64 );
788cdf0e10cSrcweir }
789cdf0e10cSrcweir else if( eType == FrameStyle_Gray )
790cdf0e10cSrcweir {
791cdf0e10cSrcweir aConverter.Seek( 10 );
792cdf0e10cSrcweir aConverter << (sal_uInt32)1084;
793cdf0e10cSrcweir aConverter.Seek( 28 );
794cdf0e10cSrcweir aConverter << (sal_uInt16) 8;
795cdf0e10cSrcweir aConverter.Seek( 54 );
796cdf0e10cSrcweir // write color table
797cdf0e10cSrcweir for( nLine = 0; nLine < 256; nLine++ )
798cdf0e10cSrcweir {
799cdf0e10cSrcweir aConverter << (sal_uInt8)nLine;
800cdf0e10cSrcweir aConverter << (sal_uInt8)nLine;
801cdf0e10cSrcweir aConverter << (sal_uInt8)nLine;
802cdf0e10cSrcweir aConverter << (sal_uInt8)0;
803cdf0e10cSrcweir }
804cdf0e10cSrcweir aConverter.Seek( 1084 );
805cdf0e10cSrcweir }
806cdf0e10cSrcweir
807cdf0e10cSrcweir for( nLine = nHeight-1;
808cdf0e10cSrcweir nLine >= 0; nLine-- )
809cdf0e10cSrcweir {
810cdf0e10cSrcweir fseek( pFrame, nLine * aParams.bytes_per_line, SEEK_SET );
811cdf0e10cSrcweir if( eType == FrameStyle_BW ||
812cdf0e10cSrcweir ( eType == FrameStyle_Gray && aParams.depth == 8 )
813cdf0e10cSrcweir )
814cdf0e10cSrcweir {
815cdf0e10cSrcweir fread( pBuffer, 1, aParams.bytes_per_line, pFrame );
816cdf0e10cSrcweir aConverter.Write( pBuffer, aParams.bytes_per_line );
817cdf0e10cSrcweir }
818cdf0e10cSrcweir else if( eType == FrameStyle_Gray )
819cdf0e10cSrcweir {
820cdf0e10cSrcweir for( i = 0; i < (aParams.pixels_per_line); i++ )
821cdf0e10cSrcweir {
822cdf0e10cSrcweir sal_uInt8 nGray = _ReadValue( pFrame, aParams.depth );
823cdf0e10cSrcweir aConverter << nGray;
824cdf0e10cSrcweir }
825cdf0e10cSrcweir }
826cdf0e10cSrcweir else if( eType == FrameStyle_RGB )
827cdf0e10cSrcweir {
828cdf0e10cSrcweir for( i = 0; i < (aParams.pixels_per_line); i++ )
829cdf0e10cSrcweir {
830cdf0e10cSrcweir sal_uInt8 nRed, nGreen, nBlue;
831cdf0e10cSrcweir nRed = _ReadValue( pFrame, aParams.depth );
832cdf0e10cSrcweir nGreen = _ReadValue( pFrame, aParams.depth );
833cdf0e10cSrcweir nBlue = _ReadValue( pFrame, aParams.depth );
834cdf0e10cSrcweir aConverter << nBlue;
835cdf0e10cSrcweir aConverter << nGreen;
836cdf0e10cSrcweir aConverter << nRed;
837cdf0e10cSrcweir }
838cdf0e10cSrcweir }
839cdf0e10cSrcweir else if( eType == FrameStyle_Separated )
840cdf0e10cSrcweir {
841cdf0e10cSrcweir for( i = 0; i < (aParams.pixels_per_line); i++ )
842cdf0e10cSrcweir {
843cdf0e10cSrcweir sal_uInt8 nValue = _ReadValue( pFrame, aParams.depth );
844cdf0e10cSrcweir switch( aParams.format )
845cdf0e10cSrcweir {
846cdf0e10cSrcweir case SANE_FRAME_RED:
847cdf0e10cSrcweir aConverter.SeekRel( 2 );
848cdf0e10cSrcweir aConverter << nValue;
849cdf0e10cSrcweir break;
850cdf0e10cSrcweir case SANE_FRAME_GREEN:
851cdf0e10cSrcweir aConverter.SeekRel( 1 );
852cdf0e10cSrcweir aConverter << nValue;
853cdf0e10cSrcweir aConverter.SeekRel( 1 );
854cdf0e10cSrcweir break;
855cdf0e10cSrcweir case SANE_FRAME_BLUE:
856cdf0e10cSrcweir aConverter << nValue;
857cdf0e10cSrcweir aConverter.SeekRel( 2 );
858cdf0e10cSrcweir break;
859cdf0e10cSrcweir case SANE_FRAME_GRAY:
860cdf0e10cSrcweir case SANE_FRAME_RGB:
861cdf0e10cSrcweir break;
862cdf0e10cSrcweir }
863cdf0e10cSrcweir }
864cdf0e10cSrcweir }
865cdf0e10cSrcweir int nGap = aConverter.Tell() & 3;
866cdf0e10cSrcweir if( nGap )
867cdf0e10cSrcweir aConverter.SeekRel( 4-nGap );
868cdf0e10cSrcweir }
869cdf0e10cSrcweir fclose( pFrame ); // deletes tmpfile
870cdf0e10cSrcweir if( eType != FrameStyle_Separated )
871cdf0e10cSrcweir break;
872cdf0e10cSrcweir }
873cdf0e10cSrcweir else
874cdf0e10cSrcweir bSuccess = sal_False;
875cdf0e10cSrcweir }
876cdf0e10cSrcweir // get stream length
877cdf0e10cSrcweir aConverter.Seek( STREAM_SEEK_TO_END );
878cdf0e10cSrcweir int nPos = aConverter.Tell();
879cdf0e10cSrcweir
880cdf0e10cSrcweir aConverter.Seek( 2 );
881cdf0e10cSrcweir aConverter << (sal_uInt32) nPos+1;
882cdf0e10cSrcweir aConverter.Seek( 0 );
883cdf0e10cSrcweir
884cdf0e10cSrcweir rBitmap.unlock();
885cdf0e10cSrcweir
886cdf0e10cSrcweir if( bSuccess )
887cdf0e10cSrcweir {
888cdf0e10cSrcweir // only cancel a successful operation
889cdf0e10cSrcweir // sane disrupts memory else
890cdf0e10cSrcweir p_cancel( maHandle );
891cdf0e10cSrcweir CheckConsistency( "sane_cancel" );
892cdf0e10cSrcweir }
893cdf0e10cSrcweir if( pBuffer )
894cdf0e10cSrcweir delete [] pBuffer;
895cdf0e10cSrcweir
896cdf0e10cSrcweir ReloadOptions();
897cdf0e10cSrcweir
898cdf0e10cSrcweir
899cdf0e10cSrcweir dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" );
900cdf0e10cSrcweir
901cdf0e10cSrcweir return bSuccess;
902cdf0e10cSrcweir }
903cdf0e10cSrcweir
GetRange(int n,double * & rpDouble)904cdf0e10cSrcweir int Sane::GetRange( int n, double*& rpDouble )
905cdf0e10cSrcweir {
906cdf0e10cSrcweir if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE &&
907cdf0e10cSrcweir mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
908cdf0e10cSrcweir {
909cdf0e10cSrcweir return -1;
910cdf0e10cSrcweir }
911cdf0e10cSrcweir
912cdf0e10cSrcweir rpDouble = 0;
913cdf0e10cSrcweir int nItems, i;
914cdf0e10cSrcweir sal_Bool bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED ? sal_True : sal_False;
915cdf0e10cSrcweir
916cdf0e10cSrcweir dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name );
917cdf0e10cSrcweir if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE )
918cdf0e10cSrcweir {
919cdf0e10cSrcweir double fMin, fMax, fQuant;
920cdf0e10cSrcweir if( bIsFixed )
921cdf0e10cSrcweir {
922cdf0e10cSrcweir fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min );
923cdf0e10cSrcweir fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max );
924cdf0e10cSrcweir fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant );
925cdf0e10cSrcweir }
926cdf0e10cSrcweir else
927cdf0e10cSrcweir {
928cdf0e10cSrcweir fMin = (double)mppOptions[n]->constraint.range->min;
929cdf0e10cSrcweir fMax = (double)mppOptions[n]->constraint.range->max;
930cdf0e10cSrcweir fQuant = (double)mppOptions[n]->constraint.range->quant;
931cdf0e10cSrcweir }
932cdf0e10cSrcweir if( fQuant != 0.0 )
933cdf0e10cSrcweir {
934cdf0e10cSrcweir dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
935cdf0e10cSrcweir fMin, fQuant, fMax );
936cdf0e10cSrcweir nItems = (int)((fMax - fMin)/fQuant)+1;
937cdf0e10cSrcweir rpDouble = new double[ nItems ];
938cdf0e10cSrcweir double fValue = fMin;
939cdf0e10cSrcweir for( i = 0; i < nItems; i++, fValue += fQuant )
940cdf0e10cSrcweir rpDouble[i] = fValue;
941cdf0e10cSrcweir rpDouble[ nItems-1 ] = fMax;
942cdf0e10cSrcweir return nItems;
943cdf0e10cSrcweir }
944cdf0e10cSrcweir else
945cdf0e10cSrcweir {
946cdf0e10cSrcweir dbg_msg( "normal range [ %lg %lg ]\n",
947cdf0e10cSrcweir fMin, fMax );
948cdf0e10cSrcweir rpDouble = new double[2];
949cdf0e10cSrcweir rpDouble[0] = fMin;
950cdf0e10cSrcweir rpDouble[1] = fMax;
951cdf0e10cSrcweir return 0;
952cdf0e10cSrcweir }
953cdf0e10cSrcweir }
954cdf0e10cSrcweir else
955cdf0e10cSrcweir {
956cdf0e10cSrcweir nItems = mppOptions[n]->constraint.word_list[0];
957cdf0e10cSrcweir rpDouble = new double[nItems];
958cdf0e10cSrcweir for( i=0; i<nItems; i++ )
959cdf0e10cSrcweir {
960cdf0e10cSrcweir rpDouble[i] = bIsFixed ?
961cdf0e10cSrcweir SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) :
962cdf0e10cSrcweir (double)mppOptions[n]->constraint.word_list[i+1];
963cdf0e10cSrcweir }
964cdf0e10cSrcweir dbg_msg( "wordlist [ %lg ... %lg ]\n",
965cdf0e10cSrcweir rpDouble[ 0 ], rpDouble[ nItems-1 ] );
966cdf0e10cSrcweir return nItems;
967cdf0e10cSrcweir }
968cdf0e10cSrcweir }
969cdf0e10cSrcweir
970cdf0e10cSrcweir static const char *ppUnits[] = {
971cdf0e10cSrcweir "",
972cdf0e10cSrcweir "[Pixel]",
973cdf0e10cSrcweir "[Bit]",
974cdf0e10cSrcweir "[mm]",
975cdf0e10cSrcweir "[DPI]",
976cdf0e10cSrcweir "[%]",
977cdf0e10cSrcweir "[usec]"
978cdf0e10cSrcweir };
979cdf0e10cSrcweir
GetOptionUnitName(int n)980cdf0e10cSrcweir String Sane::GetOptionUnitName( int n )
981cdf0e10cSrcweir {
982cdf0e10cSrcweir String aText;
983cdf0e10cSrcweir SANE_Unit nUnit = mppOptions[n]->unit;
984cdf0e10cSrcweir size_t nUnitAsSize = (size_t)nUnit;
98593ed1f29SArmin Le Grand if (nUnitAsSize >= sizeof(ppUnits)/sizeof(ppUnits[0]))
986cdf0e10cSrcweir aText = String::CreateFromAscii( "[unknown units]" );
987cdf0e10cSrcweir else
988cdf0e10cSrcweir aText = String( ppUnits[ nUnit ], gsl_getSystemTextEncoding() );
989cdf0e10cSrcweir return aText;
990cdf0e10cSrcweir }
991cdf0e10cSrcweir
ActivateButtonOption(int n)992cdf0e10cSrcweir sal_Bool Sane::ActivateButtonOption( int n )
993cdf0e10cSrcweir {
994cdf0e10cSrcweir SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, NULL );
995cdf0e10cSrcweir if( nStatus != SANE_STATUS_GOOD )
996cdf0e10cSrcweir return sal_False;
997cdf0e10cSrcweir return sal_True;
998cdf0e10cSrcweir }
999*4b37ad1dSmseidel
1000*4b37ad1dSmseidel /* vim: set noet sw=4 ts=4: */
1001