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