2022-05-03 03:56:07 +00:00
# include "sane_hg_mdw.h"
# include "json.h"
# include <stdarg.h>
# include <time.h>
# include <fcntl.h>
# include <sys/stat.h>
2022-05-09 06:48:42 +00:00
# include <mutex>
2022-05-03 03:56:07 +00:00
# ifdef WIN32
# include <windows.h>
# include <direct.h>
# define pthread_t DWORD
# define pthread_self GetCurrentThreadId
# define MKDIR(a, b) mkdir(a)
# else
# define MKDIR(a, b) mkdir(a, b)
# include <pthread.h>
# endif
2022-05-20 06:46:25 +00:00
# include "../../sdk/include/sane/sane_option_definitions.h"
2022-05-23 03:52:53 +00:00
# include "sane_option.h"
2022-05-20 06:46:25 +00:00
2022-05-03 03:56:07 +00:00
# ifndef VERSION_BUILD
# define VERSION_BUILD 22030
# endif
# ifndef SIGUSR1
# define SIGUSR1 10
# endif
// copy to /usr/lib/x86_64-linux-gnu/sane
// export SANE_DEBUG_DLL=5
# ifndef iconv_t
# define iconv_t void*
# endif
2022-06-01 03:04:10 +00:00
static std : : string g_sane_path = " " ;
2022-05-03 03:56:07 +00:00
namespace local_utility
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-05-17 07:04:55 +00:00
SANE_Status scanner_err_2_sane_statu ( int hgerr )
2022-05-03 03:56:07 +00:00
{
# define RETURN_MATCH_ERROR(hg, sane) \
if ( hgerr = = hg ) \
return sane ;
2022-05-17 07:04:55 +00:00
RETURN_MATCH_ERROR ( SCANNER_ERR_OK , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_INVALID_PARAMETER , SANE_STATUS_INVAL ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_INSUFFICIENT_MEMORY , SANE_STATUS_NO_MEM ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_ACCESS_DENIED , SANE_STATUS_ACCESS_DENIED ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_IO_PENDING , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_EXACT , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_CONFIGURATION_CHANGED , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_OPEN , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_START , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NO_DATA , SANE_STATUS_EOF ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_HAS_DATA_YET , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_OUT_OF_RANGE , SANE_STATUS_NO_MEM ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_IO , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_TIMEOUT , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NOT_FOUND , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NOT_SUPPORT , SANE_STATUS_UNSUPPORTED ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_BUSY , SANE_STATUS_DEVICE_BUSY ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_COVER_OPENNED , SANE_STATUS_COVER_OPEN ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NO_PAPER , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_PAPER_JAMMED , SANE_STATUS_JAMMED ) ;
2022-05-03 03:56:07 +00:00
return ( SANE_Status ) hgerr ;
}
2022-06-15 03:05:36 +00:00
int sane_statu_2_scanner_err ( int statu )
{
# define RETURN_MATCH_ERROR(hg, sane) \
if ( statu = = sane ) \
return hg ;
RETURN_MATCH_ERROR ( SCANNER_ERR_OK , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_INVALID_PARAMETER , SANE_STATUS_INVAL ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_INSUFFICIENT_MEMORY , SANE_STATUS_NO_MEM ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_ACCESS_DENIED , SANE_STATUS_ACCESS_DENIED ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_IO_PENDING , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_EXACT , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_CONFIGURATION_CHANGED , SANE_STATUS_GOOD ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_OPEN , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NOT_START , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_NO_DATA , SANE_STATUS_EOF ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_HAS_DATA_YET , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_OUT_OF_RANGE , SANE_STATUS_NO_MEM ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_IO , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_TIMEOUT , SANE_STATUS_IO_ERROR ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NOT_FOUND , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NOT_SUPPORT , SANE_STATUS_UNSUPPORTED ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_BUSY , SANE_STATUS_DEVICE_BUSY ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_COVER_OPENNED , SANE_STATUS_COVER_OPEN ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_NO_PAPER , SANE_STATUS_NO_DOCS ) ;
RETURN_MATCH_ERROR ( SCANNER_ERR_DEVICE_PAPER_JAMMED , SANE_STATUS_JAMMED ) ;
return statu ;
}
2022-05-03 03:56:07 +00:00
void * acquire_memory ( size_t bytes , const char * info )
{
//if (!info)
// info = "";
//hg_sane_middleware::log(strlen(info) + 80, "allocate memory with %u bytes from %s\n", bytes, info);
return malloc ( bytes ) ;
}
2022-05-18 09:41:05 +00:00
void free_memory ( void * m )
{
if ( m )
free ( m ) ;
}
2022-05-03 03:56:07 +00:00
2022-05-30 03:04:26 +00:00
2022-05-03 03:56:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-05-30 03:04:26 +00:00
// json parser ...
2022-05-03 03:56:07 +00:00
bool is_space ( char ch )
{
return ch = = ' ' | | ch = = ' \t ' ;
}
bool is_digital ( char ch )
{
return ch > = ' 0 ' & & ch < = ' 9 ' ;
}
bool is_hex_num ( char ch )
{
if ( is_digital ( ch ) )
return true ;
return ( ch > = ' a ' & & ch < = ' f ' ) | | ( ch > = ' A ' & & ch < = ' F ' ) ;
}
bool to_num ( char ch , int & v , bool hex )
{
if ( is_digital ( ch ) )
{
v = ch - ' 0 ' ;
return true ;
}
if ( hex )
{
if ( ch > = ' a ' & & ch < = ' f ' )
{
v = ch - ' a ' + 10 ;
}
else if ( ch > = ' A ' & & ch < = ' F ' )
{
v = ch - ' A ' + 10 ;
}
else
{
hex = false ;
}
}
return hex ;
}
bool skip_space ( const char * & str )
{
const char * bgn = str ;
while ( is_space ( * str ) )
str + + ;
return str > bgn ;
}
2022-05-30 03:34:47 +00:00
// 暂不支持科学计数<E8AEA1> <E695B0> ?1.2e+10
2022-05-03 03:56:07 +00:00
bool get_number ( const char * & str , double & val )
{
const char * bgn = str ;
double val_race = 10.0f ,
val_sign = 1.0f ,
digit_race = 1.0f ,
digit_race_race = 1.0f ;
val = .0f ;
if ( * str = = ' - ' )
{
str + + ;
val_sign = - 1.0f ;
}
if ( * str = = ' . ' )
{
str + + ;
digit_race = digit_race_race = .1f ;
val_race = 1.0f ;
}
bgn = str ;
while ( * str & & is_digital ( * str ) )
{
int v = 0 ;
val * = val_race ;
to_num ( * str + + , v , false ) ;
val + = v * digit_race ;
digit_race * = digit_race_race ;
}
if ( * str = = ' . ' )
{
if ( digit_race_race < 1.0f )
return false ;
digit_race = digit_race_race = .1f ;
val_race = 1.0f ;
while ( * str & & is_digital ( * str ) )
{
int v = 0 ;
val * = val_race ;
to_num ( * str + + , v , false ) ;
val + = v * digit_race ;
digit_race * = digit_race_race ;
}
}
return str > bgn ;
}
bool get_limit ( const char * & str , std : : string & l , std : : string & r )
{
// set l = "a", r = "b" in text "[a, b]"
bool ret = * str = = ' [ ' ;
if ( ret )
{
str + + ;
skip_space ( str ) ;
l = str ;
size_t pos = l . find ( " ] " ) ;
if ( pos = = - 1 )
return false ;
l . erase ( pos ) ;
pos = l . find ( " , " ) ;
if ( pos = = - 1 )
return false ;
r = l . substr ( pos + 1 ) ;
l . erase ( pos ) ;
}
return ret ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static sane_callback cb_ui_ = NULL ;
static void * cb_ui_parm_ = NULL ;
static SANE_Auth_Callback cb_auth_ = NULL ;
2022-05-09 06:48:42 +00:00
static std : : mutex cb_lock_ ;
2022-05-03 03:56:07 +00:00
static std : : string sane_event ( SANE_Event ev )
{
RETURN_IF ( ev , SANE_EVENT_NONE ) ;
RETURN_IF ( ev , SANE_EVENT_SUPPORT_ASYNC_IO ) ;
RETURN_IF ( ev , SANE_EVENT_IS_MEMORY_ENOUGH ) ;
RETURN_IF ( ev , SANE_EVENT_NEED_AUTH ) ;
RETURN_IF ( ev , SANE_EVENT_DEVICE_ARRIVED ) ;
RETURN_IF ( ev , SANE_EVENT_DEVICE_LEFT ) ;
RETURN_IF ( ev , SANE_EVENT_STATUS ) ;
RETURN_IF ( ev , SANE_EVENT_ERROR ) ;
RETURN_IF ( ev , SANE_EVENT_WORKING ) ;
RETURN_IF ( ev , SANE_EVENT_IMAGE_OK ) ;
RETURN_IF ( ev , SANE_EVENT_SCAN_FINISHED ) ;
RETURN_IF ( ev , SANE_EVENT_ABOUT_INFORMATION ) ;
RETURN_IF ( ev , SANE_EVENT_SCANNER_CLOSED ) ;
char unk [ 20 ] ;
sprintf ( unk , " %d " , ev ) ;
return unk ;
}
int ui_cb ( scanner_handle dev , int code , void * data , unsigned int * len , void * unused )
{
2022-05-09 06:48:42 +00:00
std : : lock_guard < std : : mutex > lck ( cb_lock_ ) ;
2022-05-03 03:56:07 +00:00
if ( SANE_EVENT_SUPPORT_ASYNC_IO = = code )
2022-05-17 07:04:55 +00:00
return cb_ui_ ? SCANNER_ERR_OK : SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
SANE_Handle h = hg_sane_middleware : : scanner_handle_to_sane ( dev ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_ALL , " sane callback invoked of event %s \n " , sane_event ( ( SANE_Event ) code ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
if ( cb_ui_ )
{
return cb_ui_ ( h , code , data , len , cb_ui_parm_ ) ;
}
else if ( cb_auth_ & & code = = SANE_EVENT_NEED_AUTH )
{
SANEAUTH * auth = ( SANEAUTH * ) data ;
cb_auth_ ( auth - > resource , auth - > name , auth - > pwd ) ;
}
return 0 ;
}
void get_version ( SANE_Int * version_code )
{
if ( version_code )
* version_code = SANE_VERSION_CODE ( SANE_CURRENT_MAJOR , SANE_CURRENT_MINOR , VERSION_BUILD ) ; // leading-char '1' is used for avoid compiler considering '0118' as an octal number :)
}
2022-06-18 00:55:15 +00:00
void set_callback ( sane_callback cb , void * param )
{
std : : lock_guard < std : : mutex > lck ( cb_lock_ ) ;
cb_ui_ = cb ;
cb_ui_parm_ = param ;
}
2022-05-03 03:56:07 +00:00
void stop_work ( void )
{
2022-05-09 06:48:42 +00:00
std : : lock_guard < std : : mutex > lck ( cb_lock_ ) ;
2022-05-03 03:56:07 +00:00
cb_ui_ = NULL ;
cb_ui_parm_ = NULL ;
cb_auth_ = NULL ;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
hg_sane_middleware * hg_sane_middleware : : inst_ = NULL ;
const SANE_Device * * hg_sane_middleware : : dev_list_ = NULL ;
2022-05-23 03:52:53 +00:00
hg_sane_middleware : : hg_sane_middleware ( void ) : opt_0_ ( nullptr ) , std_opt_ ( nullptr )
2022-05-03 03:56:07 +00:00
{
2022-05-30 03:04:26 +00:00
char sane_ver [ 40 ] = { 0 } ;
sprintf ( sane_ver , " %u.%u.%u " , SANE_CURRENT_MAJOR , SANE_CURRENT_MINOR , VERSION_BUILD ) ;
2022-05-03 03:56:07 +00:00
signal ( SIGUSR1 , & hg_sane_middleware : : device_pnp ) ;
2022-05-30 03:04:26 +00:00
hg_scanner_set_sane_info ( GET_BACKEND_NAME , sane_ver ) ;
2022-05-03 03:56:07 +00:00
hg_scanner_initialize ( local_utility : : ui_cb , NULL ) ;
2022-05-30 09:36:42 +00:00
# ifndef WIN32
char path [ 512 ] = { 0 } ;
size_t pos = 0 ;
2022-06-01 03:04:10 +00:00
g_sane_path = get_file_path ( ( std : : string ( GET_BACKEND_NAME ) + " .so " ) . c_str ( ) , path ) ;
pos = g_sane_path . rfind ( ' / ' ) ;
2022-05-30 09:36:42 +00:00
if ( pos + + ! = std : : string : : npos )
2022-06-01 03:04:10 +00:00
g_sane_path . erase ( pos ) ;
2022-05-30 09:36:42 +00:00
# endif
2022-05-03 03:56:07 +00:00
}
hg_sane_middleware : : ~ hg_sane_middleware ( )
{
for ( size_t i = 0 ; i < opts_ . size ( ) ; + + i )
{
2022-05-18 09:41:05 +00:00
local_utility : : free_memory ( opts_ [ i ] . desc ) ;
2022-05-03 03:56:07 +00:00
}
for ( size_t i = 0 ; i < openning_ . size ( ) ; + + i )
hg_scanner_close ( openning_ [ i ] . handle , true ) ;
hg_scanner_uninitialize ( ) ;
2022-05-20 06:46:25 +00:00
if ( opt_0_ )
local_utility : : free_memory ( opt_0_ ) ;
2022-05-23 03:52:53 +00:00
if ( std_opt_ )
delete std_opt_ ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
const SANE_Device * * hg_sane_middleware : : to_sane_device ( ScannerInfo * hgscanner , int count )
2022-05-03 03:56:07 +00:00
{
// 将多级指针安排在一个连续的内存空间存放
SANE_Device * * ret = NULL , * dev = NULL ;
SANE_String val = NULL ;
unsigned long bytes = ( count + 1 ) * ( sizeof ( SANE_Device ) + sizeof ( SANE_Device * ) ) , total = 0 ;
// calculate space ...
for ( int i = 0 ; i < count ; + + i )
{
bytes + = ALIGN_INT ( strlen ( hgscanner [ i ] . name ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( hgscanner [ i ] . vendor ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( hgscanner [ i ] . model ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( hgscanner [ i ] . type ) + 1 ) ;
}
bytes = ALIGN_INT ( bytes + 16 ) ;
dev = ( SANE_Device * ) local_utility : : acquire_memory ( bytes , " hg_sane_middleware::to_sane_device " ) ;
total = bytes ;
if ( ! dev )
return NULL ;
memset ( dev , 0 , bytes ) ;
ret = ( SANE_Device * * ) dev ;
dev = ( SANE_Device * ) ( ( SANE_Device * * ) dev + count + 1 ) ;
val = ( SANE_String ) ( dev + count ) ;
# define COPY_DEVICE_MEMBER(m) \
dev - > m = val ; \
strcpy ( val , hgscanner [ i ] . m ) ; \
bytes = ALIGN_INT ( strlen ( val ) + 1 ) ; \
val + = bytes ;
for ( int i = 0 ; i < count ; + + i , + + dev )
{
ret [ i ] = dev ;
COPY_DEVICE_MEMBER ( name ) ;
COPY_DEVICE_MEMBER ( vendor ) ;
COPY_DEVICE_MEMBER ( model ) ;
COPY_DEVICE_MEMBER ( type ) ;
}
2022-05-30 03:04:26 +00:00
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u / %u\n", val - (char*)ret, total);
2022-05-03 03:56:07 +00:00
return ( const SANE_Device * * ) ret ;
}
void hg_sane_middleware : : free_sane_device ( SANE_Device * * dev )
{
char * mem = ( char * ) dev ;
if ( mem )
{
free ( mem ) ;
}
}
void hg_sane_middleware : : device_pnp ( int sig )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " Device list changed (%d)... " , sig ) ;
2022-05-03 03:56:07 +00:00
}
SANE_Fixed hg_sane_middleware : : double_2_sane_fixed ( double v )
{
return SANE_FIX ( v ) ;
}
double hg_sane_middleware : : sane_fixed_2_double ( SANE_Fixed v )
{
return SANE_UNFIX ( v ) ;
}
std : : string hg_sane_middleware : : option_value_2_string ( SANE_Value_Type type , void * val )
{
std : : string ret ( " unknown " ) ;
char buf [ 40 ] ;
switch ( type )
{
case SANE_TYPE_BOOL :
ret = * ( SANE_Bool * ) val ? " true " : " false " ;
break ;
case SANE_TYPE_INT :
2022-05-09 06:48:42 +00:00
sprintf ( buf , " %d " , * ( SANE_Word * ) val ) ;
2022-05-03 03:56:07 +00:00
ret = buf ;
break ;
case SANE_TYPE_FIXED :
2022-05-09 06:48:42 +00:00
sprintf ( buf , " %f " , hg_sane_middleware : : sane_fixed_2_double ( * ( SANE_Word * ) val ) ) ;
2022-05-03 03:56:07 +00:00
ret = buf ;
break ;
case SANE_TYPE_STRING :
ret = ( char * ) val ;
break ;
case SANE_TYPE_BUTTON :
ret = " Button " ;
break ;
case SANE_TYPE_GROUP :
ret = " Group " ;
break ;
default :
break ;
}
return ret ;
}
2022-06-16 08:03:55 +00:00
std : : string hg_sane_middleware : : sane_path ( void )
{
return g_sane_path ;
}
2022-05-03 03:56:07 +00:00
hg_sane_middleware * hg_sane_middleware : : instance ( void )
{
if ( ! hg_sane_middleware : : inst_ )
hg_sane_middleware : : inst_ = new hg_sane_middleware ( ) ;
return hg_sane_middleware : : inst_ ;
}
2022-06-18 00:55:15 +00:00
void hg_sane_middleware : : set_callback ( sane_callback cb , void * param )
{
local_utility : : set_callback ( cb , param ) ;
}
2022-05-03 03:56:07 +00:00
void hg_sane_middleware : : clear ( void )
{
2022-06-15 03:05:36 +00:00
local_utility : : stop_work ( ) ;
2022-05-03 03:56:07 +00:00
if ( hg_sane_middleware : : inst_ )
{
delete hg_sane_middleware : : inst_ ;
hg_sane_middleware : : inst_ = NULL ;
}
}
scanner_handle hg_sane_middleware : : sane_handle_to_scanner ( SANE_Handle h )
{
int bits = sizeof ( h ) / 2 * 8 ;
unsigned long long v = ( unsigned long long ) h ;
v ^ = v > > bits ;
return ( scanner_handle ) ( v ) ;
}
SANE_Handle hg_sane_middleware : : scanner_handle_to_sane ( scanner_handle h )
{
int bits = sizeof ( h ) / 2 * 8 ;
unsigned long long v = ( unsigned long long ) h ;
v ^ = v > > bits ;
return ( SANE_Handle ) ( v ) ;
}
SANE_Option_Descriptor * hg_sane_middleware : : string_option_to_SANE_descriptor ( const char * name , const char * title , const char * desc
, const std : : vector < std : : string > & values )
{
int bytes = sizeof ( SANE_Option_Descriptor ) + sizeof ( char * ) ;
SANE_Option_Descriptor * sod = NULL ;
char * str = NULL , * * str_arr = NULL ;
bytes + = ALIGN_INT ( strlen ( name ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( title ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( desc ) + 1 ) ;
bytes + = sizeof ( SANE_Option_Descriptor ) ;
bytes + = sizeof ( char * ) ;
for ( size_t i = 0 ; i < values . size ( ) ; + + i )
bytes + = ALIGN_INT ( values [ i ] . length ( ) + 1 ) ;
bytes + = sizeof ( char * ) * ( values . size ( ) + 1 ) ;
sod = ( SANE_Option_Descriptor * ) local_utility : : acquire_memory ( bytes , " hg_sane_middleware::string_option_to_SANE_descriptor " ) ;
bzero ( sod , bytes ) ;
str = ( char * ) sod ;
str + = sizeof ( SANE_Option_Descriptor ) ;
sod - > name = str ;
strcpy ( str , name ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > title = str ;
strcpy ( str , title ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > desc = str ;
strcpy ( str , desc ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > type = SANE_TYPE_STRING ;
sod - > unit = SANE_UNIT_NONE ;
sod - > size = values . size ( ) ;
sod - > cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
2022-05-30 03:34:47 +00:00
| SANE_CAP_AUTOMATIC ; // 硬件可设置默认<E9BB98> <E8AEA4> ?
2022-05-03 03:56:07 +00:00
if ( values . size ( ) )
{
sod - > constraint_type = SANE_CONSTRAINT_STRING_LIST ;
sod - > constraint . string_list = ( char * * ) str ;
str_arr = ( char * * ) str ;
str + = ( values . size ( ) + 1 ) * sizeof ( char * ) ;
for ( size_t i = 0 ; i < values . size ( ) ; + + i )
{
str_arr [ i ] = str ;
strcpy ( str , values [ i ] . c_str ( ) ) ;
str + = ALIGN_INT ( values [ i ] . length ( ) + 1 ) ;
}
}
2022-05-30 03:04:26 +00:00
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
2022-05-03 03:56:07 +00:00
return sod ;
}
SANE_Option_Descriptor * hg_sane_middleware : : number_option_to_SANE_descriptor ( const char * name , const char * title , const char * desc
, bool double_val , double * lower , double * upper )
{
int bytes = sizeof ( SANE_Option_Descriptor ) + sizeof ( SANE_Range ) ;
SANE_Option_Descriptor * sod = NULL ;
char * str = NULL ;
bytes + = ALIGN_INT ( strlen ( name ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( title ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( desc ) + 1 ) ;
bytes + = sizeof ( SANE_Option_Descriptor ) ;
bytes + = sizeof ( SANE_Range * ) + sizeof ( SANE_Range ) ;
sod = ( SANE_Option_Descriptor * ) local_utility : : acquire_memory ( bytes , " hg_sane_middleware::number_option_to_SANE_descriptor " ) ;
bzero ( sod , bytes ) ;
str = ( char * ) sod ;
str + = sizeof ( SANE_Option_Descriptor ) ;
sod - > name = str ;
strcpy ( str , name ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > title = str ;
strcpy ( str , title ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > desc = str ;
strcpy ( str , desc ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > type = double_val ? SANE_TYPE_FIXED : SANE_TYPE_INT ;
sod - > unit = SANE_UNIT_NONE ;
sod - > size = sizeof ( SANE_Word ) ;
sod - > cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
2022-05-30 03:34:47 +00:00
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认<E9BB98> <E8AEA4> ?
2022-05-03 03:56:07 +00:00
if ( lower | | upper )
{
sod - > size = sizeof ( SANE_Range ) ;
sod - > constraint_type = SANE_CONSTRAINT_RANGE ;
sod - > constraint . range = ( SANE_Range * ) str ;
if ( lower )
{
if ( double_val )
( * ( SANE_Range * ) str ) . min = hg_sane_middleware : : double_2_sane_fixed ( * lower ) ;
else
( * ( SANE_Range * ) str ) . min = * lower ;
}
if ( upper )
{
if ( double_val )
( * ( SANE_Range * ) str ) . max = hg_sane_middleware : : double_2_sane_fixed ( * upper ) ;
else
( * ( SANE_Range * ) str ) . max = * upper ;
}
( * ( SANE_Range * ) str ) . quant = 0 ;
str = ( char * ) ( ( SANE_Range * ) str + 1 ) ;
}
2022-05-30 03:04:26 +00:00
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
2022-05-03 03:56:07 +00:00
return sod ;
}
SANE_Option_Descriptor * hg_sane_middleware : : number_option_to_SANE_descriptor ( const char * name , const char * title , const char * desc
, const std : : vector < int > & values )
{
int bytes = sizeof ( SANE_Option_Descriptor ) + sizeof ( SANE_Range ) ;
SANE_Option_Descriptor * sod = NULL ;
char * str = NULL ;
bytes + = ALIGN_INT ( strlen ( name ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( title ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( desc ) + 1 ) ;
bytes + = sizeof ( SANE_Option_Descriptor ) ;
bytes + = sizeof ( SANE_Word * ) + sizeof ( SANE_Word ) * ( values . size ( ) + 1 ) ;
sod = ( SANE_Option_Descriptor * ) local_utility : : acquire_memory ( bytes , " hg_sane_middleware::number_option_to_SANE_descriptor " ) ;
bzero ( sod , bytes ) ;
str = ( char * ) sod ;
str + = sizeof ( SANE_Option_Descriptor ) ;
sod - > name = str ;
strcpy ( str , name ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > title = str ;
strcpy ( str , title ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > desc = str ;
strcpy ( str , desc ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > type = SANE_TYPE_INT ;
sod - > unit = SANE_UNIT_NONE ;
sod - > size = sizeof ( SANE_Word ) ;
sod - > cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
2022-05-30 03:34:47 +00:00
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认<E9BB98> <E8AEA4> ?
2022-05-03 03:56:07 +00:00
if ( values . size ( ) )
{
SANE_Word * val = ( SANE_Word * ) str ;
sod - > constraint . word_list = val ;
sod - > constraint_type = SANE_CONSTRAINT_WORD_LIST ;
* val + + = values . size ( ) ;
for ( size_t i = 0 ; i < values . size ( ) ; + + i )
val [ i ] = values [ i ] ;
str = ( char * ) ( val + values . size ( ) ) ;
}
2022-05-30 03:04:26 +00:00
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
2022-05-03 03:56:07 +00:00
return sod ;
}
SANE_Option_Descriptor * hg_sane_middleware : : number_option_to_SANE_descriptor ( const char * name , const char * title , const char * desc
, const std : : vector < double > & values )
{
int bytes = sizeof ( SANE_Option_Descriptor ) + sizeof ( SANE_Range ) ;
SANE_Option_Descriptor * sod = NULL ;
char * str = NULL ;
bytes + = ALIGN_INT ( strlen ( name ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( title ) + 1 ) ;
bytes + = ALIGN_INT ( strlen ( desc ) + 1 ) ;
bytes + = sizeof ( SANE_Option_Descriptor ) ;
bytes + = sizeof ( SANE_Word * ) + sizeof ( SANE_Word ) * ( values . size ( ) + 1 ) ;
sod = ( SANE_Option_Descriptor * ) local_utility : : acquire_memory ( bytes , " hg_sane_middleware::number_option_to_SANE_descriptor " ) ;
bzero ( sod , bytes ) ;
str = ( char * ) sod ;
str + = sizeof ( SANE_Option_Descriptor ) ;
sod - > name = str ;
strcpy ( str , name ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > title = str ;
strcpy ( str , title ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > desc = str ;
strcpy ( str , desc ) ;
str + = ALIGN_INT ( strlen ( str ) + 1 ) ;
sod - > type = SANE_TYPE_FIXED ;
sod - > unit = SANE_UNIT_NONE ;
sod - > size = sizeof ( SANE_Word ) ;
sod - > cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
2022-05-30 03:34:47 +00:00
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认<E9BB98> <E8AEA4> ?
2022-05-03 03:56:07 +00:00
if ( values . size ( ) )
{
SANE_Word * val = ( SANE_Word * ) str ;
sod - > constraint . word_list = val ;
sod - > constraint_type = SANE_CONSTRAINT_WORD_LIST ;
* val + + = values . size ( ) ;
for ( size_t i = 0 ; i < values . size ( ) ; + + i )
val [ i ] = hg_sane_middleware : : double_2_sane_fixed ( values [ i ] ) ;
str = ( char * ) ( val + values . size ( ) ) ;
}
2022-05-30 03:04:26 +00:00
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
2022-05-03 03:56:07 +00:00
return sod ;
}
2022-05-18 09:41:05 +00:00
void hg_sane_middleware : : on_device_closed ( scanner_handle h )
{
2022-05-30 03:34:47 +00:00
// 由于目前对多设备的支持还不是刚需, 故代码只考虑单设备情况, 设备关闭后, 清除所有变<E69C89> <E58F98> ?
2022-05-18 09:41:05 +00:00
for ( size_t i = 0 ; i < opts_ . size ( ) ; + + i )
{
local_utility : : free_memory ( opts_ [ i ] . desc ) ;
}
opts_ . clear ( ) ;
for ( size_t i = 0 ; i < openning_ . size ( ) ; + + i )
{
if ( openning_ [ i ] . handle = = h )
{
openning_ . erase ( openning_ . begin ( ) + i ) ;
i - - ;
}
}
cur_vals_ . clear ( ) ;
slave_options_ . clear ( ) ;
master_options_ . clear ( ) ;
2022-05-23 03:52:53 +00:00
if ( std_opt_ )
delete std_opt_ ;
std_opt_ = nullptr ;
2022-05-18 09:41:05 +00:00
}
2022-05-03 03:56:07 +00:00
SANE_Status hg_sane_middleware : : open ( SANE_String_Const devicename , SANE_Handle * handle , const char * name , const char * pwd , const char * method , char * rsc )
{
scanner_handle h = NULL ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
if ( handle = = NULL )
return SANE_STATUS_INVAL ;
err = hg_scanner_open ( & h , devicename , false , NULL , NULL , NULL , rsc ) ;
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
OPENDEV od ;
od . dev_name = devicename ;
od . handle = h ;
od . scan_count = - 1 ;
openning_ . push_back ( od ) ;
* handle = hg_sane_middleware : : scanner_handle_to_sane ( h ) ;
2022-05-23 03:52:53 +00:00
if ( ! local_utility : : cb_ui_ )
{
long count = 0 ;
hg_scanner_get_parameter ( h , 0 , NULL , & count ) ;
std_opt_ = new sane_std_opts ( count ) ;
}
2022-05-03 03:56:07 +00:00
return SANE_STATUS_GOOD ;
}
2022-05-17 07:04:55 +00:00
else if ( err = = SCANNER_ERR_ACCESS_DENIED )
2022-05-03 03:56:07 +00:00
{
return SANE_STATUS_ACCESS_DENIED ;
}
else
return SANE_STATUS_UNSUPPORTED ;
}
SANE_Option_Descriptor * hg_sane_middleware : : from_json ( scanner_handle h , json * jsn , int opt_no )
{
std : : string name ( " " ) , title ( " " ) , desc ( " " ) , val ( " " ) ;
std : : vector < std : : string > constraints ;
double lower = .0f , upper = .0f ;
bool db_val = false ;
2022-05-06 05:37:14 +00:00
jsn - > get_value ( " name " , name ) ;
jsn - > get_value ( " title " , title ) ;
jsn - > get_value ( " desc " , desc ) ;
2022-05-03 03:56:07 +00:00
if ( ! jsn - > get_value ( " type " , val ) )
return NULL ;
SANE_Option_Descriptor * ret = NULL ;
if ( val = = " string " )
{
json * range = NULL ;
std : : vector < std : : string > constraints ;
jsn - > get_value ( " range " , range ) ;
if ( range )
{
if ( range - > first_child ( val ) )
{
2022-05-30 03:04:26 +00:00
constraints . push_back ( val ) ;
2022-05-03 03:56:07 +00:00
while ( range - > next_child ( val ) )
{
2022-05-30 03:04:26 +00:00
constraints . push_back ( val ) ;
2022-05-03 03:56:07 +00:00
}
}
delete range ;
}
ret = hg_sane_middleware : : string_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, constraints ) ;
}
else if ( val = = " int " | | val = = " float " )
{
json * range = NULL ;
jsn - > get_value ( " range " , range ) ;
if ( range )
{
if ( val = = " int " )
{
int l = 0 ;
if ( range - > get_value ( " min " , l ) )
{
int u = 0 ;
range - > get_value ( " max " , u ) ;
lower = l ;
upper = u ;
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, false , & lower , & upper ) ;
}
else
{
std : : vector < int > constraints ;
if ( range - > first_child ( val ) )
{
constraints . push_back ( atoi ( val . c_str ( ) ) ) ;
while ( range - > next_child ( val ) )
{
constraints . push_back ( atoi ( val . c_str ( ) ) ) ;
}
}
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, constraints ) ;
}
}
else
{
if ( range - > get_value ( " min " , lower ) )
{
range - > get_value ( " max " , upper ) ;
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, true , & lower , & upper ) ;
}
else
{
std : : vector < double > constraints ;
if ( range - > first_child ( val ) )
{
constraints . push_back ( atof ( val . c_str ( ) ) ) ;
while ( range - > next_child ( val ) )
{
constraints . push_back ( atof ( val . c_str ( ) ) ) ;
}
}
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, constraints ) ;
}
}
delete range ;
}
else
{
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, false , NULL , NULL ) ;
}
}
else if ( val = = " bool " )
{
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, false , NULL , NULL ) ;
ret - > type = SANE_TYPE_BOOL ;
}
else if ( val = = " button " )
{
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, false , NULL , NULL ) ;
ret - > type = SANE_TYPE_BUTTON ;
}
else if ( val = = " group " )
{
ret = hg_sane_middleware : : number_option_to_SANE_descriptor ( name . c_str ( ) , title . c_str ( ) , desc . c_str ( )
, false , NULL , NULL ) ;
ret - > type = SANE_TYPE_GROUP ;
}
// fill the 'size' field, for SANE_ACTION_GET action ...
if ( ret )
{
int bytes = 0 ;
jsn - > get_value ( " size " , bytes ) ;
ret - > size = bytes ;
val = " " ;
jsn - > get_value ( " category " , val ) ;
if ( val = = " advanced " )
{
ret - > cap | = SANE_CAP_ADVANCED ;
}
2022-05-03 08:44:13 +00:00
if ( strcmp ( ret - > title , " \345 \210 \206 \350 \276 \250 \347 \216 \207 " ) = = 0 )
2022-05-03 03:56:07 +00:00
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_DEBUG_INFO , " set \345 \210 \206 \350 \276 \250 \347 \216 \207 unit to DPI \n " ) ;
2022-05-03 03:56:07 +00:00
ret - > unit = SANE_UNIT_DPI ;
}
2022-05-23 03:52:53 +00:00
else if ( strcmp ( ret - > name , SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT ) = = 0 | |
strcmp ( ret - > name , SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT ) = = 0 | |
strcmp ( ret - > name , SANE_STD_OPT_NAME_CUSTOM_AREA_TOP ) = = 0 | |
strcmp ( ret - > name , SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM ) = = 0 )
2022-05-06 05:37:14 +00:00
ret - > unit = SANE_UNIT_MM ;
2022-05-03 03:56:07 +00:00
//bool enabled = true;
//if (jsn->get_value("enable", enabled) && !enabled)
// ret->cap |= SANE_CAP_INACTIVE;
2022-05-30 03:34:47 +00:00
// 关联<E585B3> <E88194> ?
2022-05-03 03:56:07 +00:00
json * depend = NULL ;
SLAVEOP so ;
if ( jsn - > get_value ( " depend_or " , depend ) )
{
so . is_enable = & hg_sane_middleware : : is_enable_or ;
}
else if ( jsn - > get_value ( " depend_and " , depend ) )
{
so . is_enable = & hg_sane_middleware : : is_enable_and ;
}
if ( depend )
{
if ( parse_depends ( depend , so ) )
{
so . enable_now = ( ret - > cap & SANE_CAP_INACTIVE ) ! = SANE_CAP_INACTIVE ;
so . option_no = opt_no ;
// initializing status ...
if ( so . master . size ( ) )
{
std : : string master ( get_option_json ( h , so . master [ 0 ] . option_no ) ) ;
json * m = new json ( ) ;
if ( m - > attach_text ( & master [ 0 ] ) )
{
bool integer = false ;
master = " " ;
m - > get_value ( " type " , master ) ;
integer = master = = " int " ;
master = " " ;
m - > get_value_as_string ( " cur " , master , integer ) ;
so . enable_now = so . is_enable ( so . master , cur_vals_ ) ;
if ( ! so . enable_now )
ret - > cap | = SANE_CAP_INACTIVE ;
}
delete m ;
}
slave_options_ . push_back ( so ) ;
}
delete depend ;
}
}
return ret ;
}
scanner_handle hg_sane_middleware : : find_openning_device ( SANE_Handle h , bool rmv , OPENDEV * dev )
{
scanner_handle handle = hg_sane_middleware : : sane_handle_to_scanner ( h ) ;
std : : vector < OPENDEV > : : iterator it = std : : find ( openning_ . begin ( ) , openning_ . end ( ) , handle ) ;
if ( it = = openning_ . end ( ) )
handle = NULL ;
else
{
if ( dev )
* dev = * it ;
if ( rmv )
openning_ . erase ( it ) ;
}
return handle ;
}
std : : string hg_sane_middleware : : get_option_json ( scanner_handle handle , int opt_no )
{
char * json_txt = NULL ;
long length = 0 ;
2022-05-17 07:04:55 +00:00
scanner_err err = hg_scanner_get_parameter ( handle , opt_no , json_txt , & length ) ;
2022-05-03 03:56:07 +00:00
std : : string ret ( " " ) ;
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_INSUFFICIENT_MEMORY )
2022-05-03 03:56:07 +00:00
{
json_txt = ( char * ) local_utility : : acquire_memory ( ALIGN_INT ( length + 4 ) , " hg_sane_middleware::get_option_json " ) ;
bzero ( json_txt , length + 4 ) ;
err = hg_scanner_get_parameter ( handle , opt_no , json_txt , & length ) ;
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
ret = json_txt ;
}
free ( json_txt ) ;
}
return ret ;
}
SANE_Option_Descriptor * hg_sane_middleware : : find_stored_descriptor ( const char * name , int option )
{
for ( size_t i = 0 ; i < opts_ . size ( ) ; + + i )
{
if ( opts_ [ i ] . dev_name = = name & & opts_ [ i ] . option_no = = option )
return opts_ [ i ] . desc ;
}
return NULL ;
}
SANE_Option_Descriptor * hg_sane_middleware : : find_stored_descriptor ( SANE_Handle handle , int option )
{
OPENDEV dev ;
scanner_handle h = find_openning_device ( handle , false , & dev ) ;
if ( ! h )
return NULL ;
else
return find_stored_descriptor ( dev . dev_name . c_str ( ) , option ) ;
}
2022-06-15 03:05:36 +00:00
void hg_sane_middleware : : reload_current_value ( scanner_handle handle , std : : vector < int > * changed )
{
long count = 0 ;
if ( changed )
changed - > clear ( ) ;
hg_scanner_get_parameter ( handle , 0 , NULL , & count ) ;
for ( int i = 1 ; i < count ; + + i )
{
std : : string val ( get_option_json ( handle , i ) ) ;
json * jsn = new json ( ) ;
if ( jsn - > attach_text ( & val [ 0 ] ) & &
jsn - > get_value ( " type " , val ) )
{
if ( refresh_current_value ( i , jsn ) )
changed - > push_back ( i ) ;
}
delete jsn ;
}
}
bool hg_sane_middleware : : get_current_value ( scanner_handle handle , int option , void * value , SANE_Value_Type * type )
2022-05-03 03:56:07 +00:00
{
std : : string val ( get_option_json ( handle , option ) ) ;
2022-06-15 03:05:36 +00:00
json * jsn = new json ( ) ;
2022-05-03 03:56:07 +00:00
int estimate = 20 ;
bool ret = false ;
if ( jsn - > attach_text ( & val [ 0 ] ) & &
jsn - > get_value ( " type " , val ) )
{
SANE_Value_Type t = SANE_TYPE_STRING ;
2022-05-06 05:37:14 +00:00
std : : string name ( " " ) ;
2022-05-03 03:56:07 +00:00
2022-05-06 05:37:14 +00:00
jsn - > get_value ( " name " , name ) ;
2022-05-03 03:56:07 +00:00
ret = true ;
2022-05-23 03:52:53 +00:00
if ( val = = " int " )
2022-05-03 03:56:07 +00:00
{
int v = 0 ;
jsn - > get_value ( " cur " , v ) ;
* ( ( SANE_Int * ) value ) = v ;
t = SANE_TYPE_INT ;
}
else if ( val = = " bool " )
{
bool yesorno = false ;
jsn - > get_value ( " cur " , yesorno ) ;
* ( SANE_Bool * ) value = yesorno ;
t = SANE_TYPE_BOOL ;
}
else if ( val = = " float " )
{
double v = .0f ;
jsn - > get_value ( " cur " , v ) ;
* ( ( SANE_Fixed * ) value ) = hg_sane_middleware : : double_2_sane_fixed ( v ) ;
t = SANE_TYPE_FIXED ;
}
else
{
val = " " ;
jsn - > get_value ( " cur " , val ) ;
strcpy ( ( char * ) value , val . c_str ( ) ) ;
estimate + = val . length ( ) ;
}
if ( type )
* type = t ;
refresh_current_value ( option , jsn ) ;
jsn - > get_value ( " title " , val ) ;
2022-06-18 00:55:15 +00:00
VLOG_MINI_3 ( LOG_LEVEL_ALL , " <--Get option(%d - %s) value: %s \n " , option , val . c_str ( ) , hg_sane_middleware : : option_value_2_string ( t , value ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
delete jsn ;
return ret ;
}
2022-05-20 06:46:25 +00:00
void * hg_sane_middleware : : get_default_value ( scanner_handle handle , int option )
{
std : : string val ( get_option_json ( handle , option ) ) ;
2022-06-15 03:05:36 +00:00
void * data = nullptr ;
json * jsn = new json ( ) ;
2022-05-20 06:46:25 +00:00
if ( jsn - > attach_text ( & val [ 0 ] ) & &
jsn - > get_value ( " type " , val ) )
{
if ( val = = " bool " )
{
bool v = false ;
jsn - > get_value ( " default " , v ) ;
data = local_utility : : acquire_memory ( sizeof ( v ) , " " ) ;
memcpy ( data , & v , sizeof ( v ) ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " option %d default value is: %s \n " , option , v ? " true " : " false " ) ;
2022-05-20 06:46:25 +00:00
}
else if ( val = = " int " )
{
int v = 0 ;
jsn - > get_value ( " default " , v ) ;
data = local_utility : : acquire_memory ( sizeof ( v ) , " " ) ;
memcpy ( data , & v , sizeof ( v ) ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " option %d default value is: %d \n " , option , v ) ;
2022-05-20 06:46:25 +00:00
}
else if ( val = = " float " )
{
double v = .0f ;
jsn - > get_value ( " default " , v ) ;
data = local_utility : : acquire_memory ( sizeof ( v ) , " " ) ;
memcpy ( data , & v , sizeof ( v ) ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " option %d default value is: %f \n " , option , v ) ;
2022-05-20 06:46:25 +00:00
}
else if ( val = = " string " )
{
int size = 0 ;
jsn - > get_value ( " size " , size ) ;
val = " " ;
jsn - > get_value ( " default " , val ) ;
if ( size < val . length ( ) )
size = val . length ( ) ;
data = local_utility : : acquire_memory ( size + 4 , " " ) ;
strcpy ( ( char * ) data , val . c_str ( ) ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " option %d default value is: %s \n " , option , ( char * ) data ) ;
2022-05-20 06:46:25 +00:00
}
else
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " option %d type is '%s' and cannot be set value. \n " , option , val . c_str ( ) ) ;
2022-05-20 06:46:25 +00:00
}
}
delete jsn ;
2022-05-03 03:56:07 +00:00
2022-06-15 03:05:36 +00:00
if ( ! data & & std_opt_ )
2022-05-03 03:56:07 +00:00
{
2022-06-15 03:05:36 +00:00
data = std_opt_ - > get_default_value ( handle , option ) ;
2022-05-03 03:56:07 +00:00
}
2022-06-15 03:05:36 +00:00
return data ;
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware : : get_devices ( const SANE_Device * * * device_list , SANE_Bool local_only )
{
if ( ! device_list )
return SANE_STATUS_INVAL ;
2022-05-17 07:04:55 +00:00
ScannerInfo * dev = NULL ;
2022-05-03 03:56:07 +00:00
long count = 0 ;
2022-05-17 07:04:55 +00:00
scanner_err hgerr = hg_scanner_enum ( dev , & count , local_only ) ;
2022-05-03 03:56:07 +00:00
SANE_Status ret = SANE_STATUS_GOOD ;
2022-05-17 07:04:55 +00:00
if ( hgerr = = SCANNER_ERR_INSUFFICIENT_MEMORY )
2022-05-03 03:56:07 +00:00
{
2022-05-30 03:34:47 +00:00
count + = 4 ; // 为两次hg_scanner_enum间隙可能新增的设备预留空<E79599> <E7A9BA> ?
2022-05-17 07:04:55 +00:00
dev = ( ScannerInfo * ) local_utility : : acquire_memory ( sizeof ( ScannerInfo ) * count , " hg_sane_middleware::get_devices " ) ;
2022-05-03 03:56:07 +00:00
hgerr = hg_scanner_enum ( dev , & count , local_only ) ;
2022-05-17 07:04:55 +00:00
if ( hgerr ! = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
free ( dev ) ;
dev = NULL ;
}
}
2022-05-17 07:04:55 +00:00
if ( hgerr = = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
* device_list = hg_sane_middleware : : to_sane_device ( dev , count ) ;
if ( dev )
free ( dev ) ;
}
else
2022-05-17 07:04:55 +00:00
ret = local_utility : : scanner_err_2_sane_statu ( hgerr ) ;
2022-05-03 03:56:07 +00:00
if ( hg_sane_middleware : : dev_list_ )
free ( hg_sane_middleware : : dev_list_ ) ;
hg_sane_middleware : : dev_list_ = * device_list ;
return ret ;
}
SANE_Status hg_sane_middleware : : open_device ( SANE_String_Const devicename , SANE_Handle * handle )
{
char rsc [ 128 ] ;
SANE_Status ret = SANE_STATUS_GOOD ;
bzero ( rsc , sizeof ( rsc ) ) ;
ret = open ( devicename , handle , NULL , NULL , NULL , rsc ) ;
if ( ret = = SANE_STATUS_ACCESS_DENIED & & rsc [ 0 ] )
{
SANEAUTH auth ;
bzero ( & auth , sizeof ( auth ) ) ;
auth . resource = rsc ;
if ( local_utility : : ui_cb ( NULL , SANE_EVENT_NEED_AUTH , ( void * ) & auth , NULL , NULL ) )
{
return SANE_STATUS_CANCELLED ;
}
ret = open ( devicename , handle , auth . name , auth . pwd , auth . method , rsc ) ;
}
return ret ;
}
SANE_Status hg_sane_middleware : : close_device ( SANE_Handle h )
{
scanner_handle hs = find_openning_device ( h , true ) ;
SANE_Status err = SANE_STATUS_GOOD ;
if ( hs )
2022-05-17 07:04:55 +00:00
err = local_utility : : scanner_err_2_sane_statu ( hg_scanner_close ( hs , true ) ) ;
2022-05-18 09:41:05 +00:00
if ( err = = SANE_STATUS_GOOD )
on_device_closed ( hs ) ;
2022-05-03 03:56:07 +00:00
return err ;
}
SANE_Status hg_sane_middleware : : get_image_parameters ( SANE_Handle handle , SANE_Parameters * params )
{
scanner_handle h = find_openning_device ( handle ) ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_NOT_START ;
2022-05-03 03:56:07 +00:00
if ( ! params )
return SANE_STATUS_INVAL ;
err = hg_scanner_get_img_info ( h , params , sizeof ( * params ) ) ;
2022-05-17 07:04:55 +00:00
return local_utility : : scanner_err_2_sane_statu ( err ) ;
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware : : start ( SANE_Handle h , void * async_event )
{
OPENDEV dev ;
scanner_handle hs = find_openning_device ( h , false , & dev ) ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( hs )
err = hg_scanner_start ( hs , async_event , dev . scan_count ) ;
2022-05-17 07:04:55 +00:00
return local_utility : : scanner_err_2_sane_statu ( err ) ;
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware : : read ( SANE_Handle h , void * buf , int * bytes )
{
scanner_handle hs = find_openning_device ( h ) ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
long r = bytes ? * bytes : 0 ;
if ( bytes & & hs )
{
err = hg_scanner_read_img_data ( hs , ( unsigned char * ) buf , & r ) ;
* bytes = r ;
}
2022-05-17 07:04:55 +00:00
return local_utility : : scanner_err_2_sane_statu ( err ) ;
2022-05-03 03:56:07 +00:00
}
SANE_Status hg_sane_middleware : : stop ( SANE_Handle h )
{
scanner_handle hs = find_openning_device ( h ) ;
if ( hs )
hg_scanner_stop ( hs ) ;
return SANE_STATUS_GOOD ;
}
SANE_Option_Descriptor * hg_sane_middleware : : get_option_descriptor ( SANE_Handle h , SANE_Int option )
{
OPENDEV dev ;
scanner_handle handle = find_openning_device ( h , false , & dev ) ;
SANE_Option_Descriptor * ret = NULL ;
if ( ! handle )
return NULL ;
2022-05-20 06:46:25 +00:00
if ( option = = 0 )
{
if ( ! opt_0_ )
{
opt_0_ = ( SANE_Option_Descriptor * ) local_utility : : acquire_memory ( sizeof ( SANE_Option_Descriptor ) , " " ) ;
opt_0_ - > cap = SANE_CAP_SOFT_DETECT ;
opt_0_ - > name = " option-count " ;
opt_0_ - > title = " " ;
opt_0_ - > desc = " Number of options " ;
opt_0_ - > type = SANE_TYPE_INT ;
opt_0_ - > size = sizeof ( SANE_TYPE_INT ) ;
}
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_DEBUG_INFO , " get_option_descriptor(0) \n " ) ;
2022-05-20 06:46:25 +00:00
return opt_0_ ;
}
2022-05-03 03:56:07 +00:00
ret = find_stored_descriptor ( dev . dev_name . c_str ( ) , option ) ;
if ( ! ret )
{
std : : string json_txt ( get_option_json ( handle , option ) ) ;
if ( json_txt . length ( ) )
{
json * jsn = new json ( ) ;
if ( jsn - > attach_text ( & json_txt [ 0 ] ) )
{
ret = from_json ( handle , jsn , option ) ;
if ( ret )
{
DEVOPT devopt ;
devopt . dev_name = dev . dev_name ;
devopt . option_no = option ;
devopt . desc = ret ;
opts_ . push_back ( devopt ) ;
refresh_current_value ( option , jsn ) ;
}
}
delete jsn ;
}
}
2022-05-23 03:52:53 +00:00
if ( ret )
{
if ( std_opt_ )
std_opt_ - > init_known_opt ( option , ret ) ;
}
else if ( std_opt_ )
ret = std_opt_ - > get_option ( option ) ;
2022-05-03 03:56:07 +00:00
return ret ;
}
SANE_Status hg_sane_middleware : : set_option ( SANE_Handle h , SANE_Int option , SANE_Action action , void * value , SANE_Int * after_do )
{
OPENDEV dev ;
scanner_handle handle = find_openning_device ( h , false , & dev ) ;
if ( ! handle | | ( action = = SANE_ACTION_GET_VALUE & & ! value ) )
return SANE_STATUS_INVAL ;
if ( action = = SANE_ACTION_GET_VALUE )
{
if ( after_do )
* after_do = 0 ;
SANE_Status ret = SANE_STATUS_IO_ERROR ;
if ( option = = 0 )
{
long count = 0 ;
hg_scanner_get_parameter ( handle , option , NULL , & count ) ;
* ( ( SANE_Int * ) value ) = count ;
ret = SANE_STATUS_GOOD ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_WARNING , " get option count = %d. \n " , count ) ;
2022-05-03 03:56:07 +00:00
}
else
{
2022-05-23 03:52:53 +00:00
if ( std_opt_ & & std_opt_ - > is_known_option ( option ) )
{
std_opt_ - > get_value ( h , option , value ) ;
ret = SANE_STATUS_GOOD ;
}
else if ( get_current_value ( handle , option , value ) )
2022-05-03 03:56:07 +00:00
ret = SANE_STATUS_GOOD ;
}
return ret ;
}
else
{
SANE_Option_Descriptor * desc = find_stored_descriptor ( dev . dev_name . c_str ( ) , option ) ;
2022-05-20 06:46:25 +00:00
bool release_value = false ;
2022-05-23 03:52:53 +00:00
scanner_err err = SCANNER_ERR_OK ;
SANE_Status status = SANE_STATUS_GOOD ;
std : : string prev ( " " ) , v ( " " ) ;
2022-05-03 03:56:07 +00:00
2022-05-23 03:52:53 +00:00
if ( std_opt_ & & std_opt_ - > is_known_option ( option , & desc ) )
2022-05-03 03:56:07 +00:00
{
2022-05-23 03:52:53 +00:00
SANE_Option_Descriptor * known = std_opt_ - > get_option ( option ) ;
prev = hg_sane_middleware : : option_value_2_string ( known - > type , value ) ;
err = std_opt_ - > set_value ( handle , option , value ) ;
v = hg_sane_middleware : : option_value_2_string ( known - > type , value ) ;
2022-05-03 03:56:07 +00:00
}
2022-05-23 03:52:53 +00:00
else
2022-05-03 03:56:07 +00:00
{
2022-05-23 03:52:53 +00:00
if ( ! desc )
2022-05-20 06:46:25 +00:00
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_FATAL , " Option descriptor %d not found. \n " , option ) ;
2022-05-23 03:52:53 +00:00
return SANE_STATUS_UNSUPPORTED ;
2022-05-20 06:46:25 +00:00
}
2022-05-23 03:52:53 +00:00
else if ( ! value & & desc - > type ! = SANE_TYPE_BUTTON )
2022-05-20 06:46:25 +00:00
{
2022-05-23 03:52:53 +00:00
if ( action = = SANE_ACTION_SET_AUTO ) // we assume the driver can set the option properbly, and no work to do
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_WARNING , " Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value. \n " , option , desc - > title ) ;
2022-05-20 06:46:25 +00:00
2022-05-23 03:52:53 +00:00
value = get_default_value ( handle , option ) ;
if ( ! value )
return SANE_STATUS_GOOD ;
release_value = true ;
}
else
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_WARNING , " Option descriptor %d(%s) need a value!. \n " , option , desc - > title ) ;
2022-05-20 06:46:25 +00:00
2022-05-23 03:52:53 +00:00
return SANE_STATUS_INVAL ;
}
}
2022-05-03 03:56:07 +00:00
2022-05-23 03:52:53 +00:00
void * pass = value ;
double dv = .0f ;
bool bv = false ;
int size = desc - > size ;
2022-05-03 03:56:07 +00:00
2022-05-23 03:52:53 +00:00
prev = hg_sane_middleware : : option_value_2_string ( desc - > type , value ) ;
if ( desc - > type = = SANE_TYPE_BOOL )
{
bv = * ( ( SANE_Bool * ) value ) = = SANE_TRUE ;
pass = & bv ;
size = sizeof ( bv ) ;
}
else if ( desc - > type = = SANE_TYPE_FIXED )
{
dv = hg_sane_middleware : : sane_fixed_2_double ( * ( ( SANE_Fixed * ) value ) ) ;
pass = & dv ;
size = sizeof ( dv ) ;
}
2022-05-03 03:56:07 +00:00
2022-05-23 03:52:53 +00:00
err = hg_scanner_set_parameter ( handle , option , pass , size ) ;
2022-05-03 03:56:07 +00:00
2022-05-23 03:52:53 +00:00
if ( desc - > type = = SANE_TYPE_BOOL )
{
* ( ( SANE_Bool * ) value ) = bv ? SANE_TRUE : SANE_FALSE ;
}
else if ( desc - > type = = SANE_TYPE_FIXED )
{
* ( ( SANE_Fixed * ) value ) = hg_sane_middleware : : double_2_sane_fixed ( dv ) ;
}
v = hg_sane_middleware : : option_value_2_string ( desc - > type , value ) ;
2022-05-03 03:56:07 +00:00
}
if ( prev = = v )
{
2022-06-18 00:55:15 +00:00
VLOG_MINI_3 ( LOG_LEVEL_ALL , " -->Set option(%d - %s) value: %s \n " , option , desc - > title , v . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
else
{
2022-06-18 00:55:15 +00:00
VLOG_4 ( LOG_LEVEL_ALL , 512 , " -->Set option(%d - %s) value: %s(Applied: %s) \n " , option , desc - > title , prev . c_str ( ) , v . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
err = ( scanner_err ) something_after_do ( handle , dev . dev_name . c_str ( ) , option , v . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
else if ( err = = SCANNER_ERR_NOT_EXACT )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
err = ( scanner_err ) ( something_after_do ( handle , dev . dev_name . c_str ( ) , option , v . c_str ( ) ) | SANE_INFO_INEXACT ) ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
else if ( err = = SCANNER_ERR_CONFIGURATION_CHANGED )
2022-05-03 03:56:07 +00:00
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " the setting '%s' affects other options value, RELOAD ... \n " , desc - > title ) ;
2022-05-17 07:04:55 +00:00
on_SCANNER_ERR_CONFIGURATION_CHANGED ( handle , dev . dev_name . c_str ( ) ) ;
err = ( scanner_err ) SANE_INFO_RELOAD_OPTIONS ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
else if ( err = = SCANNER_ERR_ACCESS_DENIED )
2022-05-03 03:56:07 +00:00
status = SANE_STATUS_ACCESS_DENIED ;
else
status = SANE_STATUS_INVAL ;
if ( after_do )
* after_do = err ;
2022-05-20 06:46:25 +00:00
if ( release_value )
local_utility : : free_memory ( value ) ;
2022-05-03 03:56:07 +00:00
return status ;
}
}
2022-06-15 03:05:36 +00:00
bool hg_sane_middleware : : get_cur_value ( SANE_Handle handle , int option , void * value , SANE_Value_Type * type )
{
scanner_handle h = find_openning_device ( handle ) ;
if ( ! h )
return false ;
return get_current_value ( h , option , value , type ) ;
}
void * hg_sane_middleware : : get_def_value ( SANE_Handle handle , int option )
{
scanner_handle h = find_openning_device ( handle ) ;
if ( ! h )
return NULL ;
return get_default_value ( h , option ) ;
}
2022-05-03 03:56:07 +00:00
SANE_Status hg_sane_middleware : : io_control ( SANE_Handle h , unsigned long code , void * data , unsigned * len )
{
OPENDEV od ;
scanner_handle handle = find_openning_device ( h , false , & od ) ;
// commented at 2022-03-23 for getting app about info before open any device
//
//if (!handle)
// return SANE_STATUS_INVAL;
int ret = hg_scanner_control ( handle , code , data , len ) ;
2022-05-17 07:04:55 +00:00
if ( ret = = SCANNER_ERR_CONFIGURATION_CHANGED )
2022-05-03 03:56:07 +00:00
{
int nc = code ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " the setting '0x%08x' affects other options value, RELOAD ... \n " , nc ) ;
2022-05-17 07:04:55 +00:00
on_SCANNER_ERR_CONFIGURATION_CHANGED ( handle , od . dev_name . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
return local_utility : : scanner_err_2_sane_statu ( ret ) ;
2022-05-03 03:56:07 +00:00
}
/// <summary>
2022-05-30 03:34:47 +00:00
/// 关联项处<E9A1B9> <E5A484> ?
2022-05-03 03:56:07 +00:00
bool hg_sane_middleware : : compare_val_equal ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return strcmp ( cur_val , limit_l ) = = 0 ;
}
bool hg_sane_middleware : : compare_val_not_equal ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return ! hg_sane_middleware : : compare_val_equal ( cur_val , limit_l , limit_r ) ;
}
bool hg_sane_middleware : : compare_val_great ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return atof ( cur_val ) > atof ( limit_l ) ;
}
bool hg_sane_middleware : : compare_val_not_less ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return ! hg_sane_middleware : : compare_val_less ( cur_val , limit_l , limit_r ) ;
}
bool hg_sane_middleware : : compare_val_less ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return atof ( cur_val ) < atof ( limit_l ) ;
}
bool hg_sane_middleware : : compare_val_not_great ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return ! hg_sane_middleware : : compare_val_great ( cur_val , limit_l , limit_r ) ;
}
bool hg_sane_middleware : : compare_val_between ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return atof ( limit_l ) < atof ( cur_val ) & & atof ( cur_val ) < atof ( limit_r ) ;
}
bool hg_sane_middleware : : compare_val_not_between ( const char * cur_val , const char * limit_l , const char * limit_r )
{
return ! hg_sane_middleware : : compare_val_between ( cur_val , limit_l , limit_r ) ;
}
bool hg_sane_middleware : : is_enable_and ( const std : : vector < MASTEROP > & master , std : : vector < CURVAL > & curvals )
{
// NOTE: logical operator '&&' should get all master's value to check, here we only consider ONE master !!!!
bool enabled = true ;
for ( size_t i = 0 ; enabled & & i < master . size ( ) ; + + i )
{
std : : vector < CURVAL > : : iterator it = std : : find ( curvals . begin ( ) , curvals . end ( ) , master [ i ] . option_no ) ;
if ( it = = curvals . end ( ) )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_WARNING , " option %d's current value is not found, other options depend it maybe in wrong status. \n " , master [ i ] . option_no ) ;
2022-05-03 03:56:07 +00:00
continue ;
}
enabled & = master [ i ] . compare_val ( it - > val . c_str ( ) , master [ i ] . limit_l . c_str ( ) , master [ i ] . limit_r . c_str ( ) ) ;
}
return enabled ;
}
bool hg_sane_middleware : : is_enable_or ( const std : : vector < MASTEROP > & master , std : : vector < CURVAL > & curvals )
{
bool enabled = false ;
for ( size_t i = 0 ; ! enabled & & i < master . size ( ) ; + + i )
{
std : : vector < CURVAL > : : iterator it = std : : find ( curvals . begin ( ) , curvals . end ( ) , master [ i ] . option_no ) ;
if ( it = = curvals . end ( ) )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_WARNING , " option %d's current value is not found, other options depend it maybe in wrong status. \n " , master [ i ] . option_no ) ;
2022-05-03 03:56:07 +00:00
continue ;
}
enabled | = master [ i ] . compare_val ( it - > val . c_str ( ) , master [ i ] . limit_l . c_str ( ) , master [ i ] . limit_r . c_str ( ) ) ;
}
return enabled ;
}
bool hg_sane_middleware : : parse_master_option ( const char * depend_str , MASTEROP & mo )
{
bool ret = true ;
double num = .0f ;
mo . option_no = 0 ;
mo . compare_val = & hg_sane_middleware : : compare_val_equal ;
mo . limit_l = mo . limit_r = " " ;
local_utility : : skip_space ( depend_str ) ;
ret = local_utility : : get_number ( depend_str , num ) ;
if ( ret )
{
mo . option_no = num ;
local_utility : : skip_space ( depend_str ) ;
if ( * depend_str = = ' = ' )
{
depend_str + + ;
if ( * depend_str = = ' = ' )
{
depend_str + + ;
if ( * depend_str = = ' [ ' )
{
ret = local_utility : : get_limit ( depend_str , mo . limit_l , mo . limit_r ) ;
mo . compare_val = & hg_sane_middleware : : compare_val_between ;
}
else
{
mo . compare_val = & hg_sane_middleware : : compare_val_equal ;
mo . limit_l = depend_str ;
}
}
else
{
ret = false ;
}
}
else if ( * depend_str = = ' > ' )
{
depend_str + + ;
if ( * depend_str = = ' = ' )
{
depend_str + + ;
mo . compare_val = & hg_sane_middleware : : compare_val_not_less ;
}
else
{
mo . compare_val = & hg_sane_middleware : : compare_val_great ;
}
mo . limit_l = depend_str ;
}
else if ( * depend_str = = ' < ' )
{
depend_str + + ;
if ( * depend_str = = ' = ' )
{
depend_str + + ;
mo . compare_val = & hg_sane_middleware : : compare_val_not_great ;
}
else
{
mo . compare_val = & hg_sane_middleware : : compare_val_less ;
}
mo . limit_l = depend_str ;
}
else if ( * depend_str = = ' ! ' )
{
depend_str + + ;
if ( * depend_str = = ' = ' )
{
depend_str + + ;
if ( * depend_str = = ' [ ' )
{
ret = local_utility : : get_limit ( depend_str , mo . limit_l , mo . limit_r ) ;
mo . compare_val = & hg_sane_middleware : : compare_val_not_between ;
}
else
{
mo . compare_val = & hg_sane_middleware : : compare_val_not_equal ;
mo . limit_l = depend_str ;
}
}
else
{
ret = false ;
}
}
else
{
ret = false ;
}
}
return ret ;
}
bool hg_sane_middleware : : parse_depends ( json * jsn , SLAVEOP & so )
{
std : : string val ( " " ) ;
bool ret = jsn - > first_child ( val ) ;
while ( ret )
{
MASTEROP mo ;
ret = parse_master_option ( val . c_str ( ) , mo ) ;
if ( ! ret )
break ;
so . master . push_back ( mo ) ;
if ( std : : find ( master_options_ . begin ( ) , master_options_ . end ( ) , mo . option_no ) = = master_options_ . end ( ) )
{
master_options_ . push_back ( mo . option_no ) ;
std : : sort ( master_options_ . begin ( ) , master_options_ . end ( ) ) ;
}
ret = jsn - > next_child ( val ) ;
}
return so . master . size ( ) > 0 ;
}
bool hg_sane_middleware : : is_associatived ( const SLAVEOP & slave , int master_opt )
{
bool result = false ;
for ( size_t i = 0 ; i < slave . master . size ( ) ; + + i )
{
if ( slave . master [ i ] . option_no = = master_opt )
{
result = true ;
break ;
}
}
return result ;
}
bool hg_sane_middleware : : set_stored_option_enabled ( const char * dev_name , int option , bool enable , int * size )
{
SANE_Option_Descriptor * opt = find_stored_descriptor ( dev_name , option ) ;
bool ret = false ;
if ( opt )
{
if ( size )
* size = opt - > size ;
ret = true ;
if ( enable )
opt - > cap & = ~ SANE_CAP_INACTIVE ;
else
opt - > cap | = SANE_CAP_INACTIVE ;
}
return ret ;
}
int hg_sane_middleware : : something_after_do ( scanner_handle h , const char * dev_name , int option_no , const char * cur_val )
{
int after = 0 ;
OPTENABLE oe ;
std : : vector < OPTENABLE > changed_options ;
refresh_current_value ( option_no , cur_val ) ;
if ( std : : find ( master_options_ . begin ( ) , master_options_ . end ( ) , option_no ) = = master_options_ . end ( ) )
{
return after ;
}
oe . opt_no = option_no ;
oe . enable = true ;
changed_options . push_back ( oe ) ;
for ( size_t i = 0 ; i < changed_options . size ( ) ; + + i )
{
for ( size_t slave = 0 ; slave < slave_options_ . size ( ) ; + + slave )
{
if ( slave_options_ [ slave ] . option_no = = changed_options [ i ] . opt_no | |
! is_associatived ( slave_options_ [ slave ] , changed_options [ i ] . opt_no ) )
continue ;
bool enable = changed_options [ i ] . enable ;
int bytes = 0 ;
if ( enable )
enable = slave_options_ [ slave ] . is_enable ( slave_options_ [ slave ] . master , cur_vals_ ) ;
if ( enable = = slave_options_ [ slave ] . enable_now )
continue ;
slave_options_ [ slave ] . enable_now = enable ;
if ( ! set_stored_option_enabled ( dev_name , slave_options_ [ slave ] . option_no , enable , & bytes ) )
continue ;
OPTEN * op = get_control_enalbe_data ( slave_options_ [ slave ] ) ;
hg_scanner_control ( h , HG_CONTROL_CODE_OPTION_ENABLE , op , NULL ) ;
free_control_enable_data ( op ) ;
if ( std : : find ( changed_options . begin ( ) , changed_options . end ( ) , slave_options_ [ slave ] . option_no ) ! = changed_options . end ( ) )
continue ;
oe . opt_no = slave_options_ [ slave ] . option_no ;
oe . enable = slave_options_ [ slave ] . enable_now ;
changed_options . push_back ( oe ) ;
}
}
if ( changed_options . size ( ) > 1 )
after = SANE_INFO_RELOAD_OPTIONS ;
return after ;
}
bool hg_sane_middleware : : refresh_current_value ( int opt , json * jsn )
{
std : : vector < CURVAL > : : iterator it = std : : find ( cur_vals_ . begin ( ) , cur_vals_ . end ( ) , opt ) ;
if ( it = = cur_vals_ . end ( ) )
{
CURVAL cv ;
jsn - > get_value ( " type " , cv . type ) ;
cv . opt_no = opt ;
jsn - > get_value_as_string ( " cur " , cv . val , cv . type = = " int " ) ;
cur_vals_ . push_back ( cv ) ;
return false ;
}
else
{
std : : string old ( it - > val ) ;
jsn - > get_value_as_string ( " cur " , it - > val , it - > type = = " int " ) ;
return old ! = it - > val ;
}
}
bool hg_sane_middleware : : refresh_current_value ( int opt , const char * val )
{
std : : vector < CURVAL > : : iterator it = std : : find ( cur_vals_ . begin ( ) , cur_vals_ . end ( ) , opt ) ;
if ( it ! = cur_vals_ . end ( ) )
{
bool ret = strcmp ( it - > val . c_str ( ) , val ) = = 0 ;
it - > val = val ;
return ret ;
}
return false ;
}
OPTEN * hg_sane_middleware : : get_control_enalbe_data ( const SLAVEOP & slave )
{
std : : vector < int > master ;
OPTEN * opt = NULL ;
size_t size = sizeof ( OPTEN ) ;
for ( size_t i = 0 ; i < slave . master . size ( ) ; + + i )
{
if ( std : : find ( master . begin ( ) , master . end ( ) , slave . master [ i ] . option_no ) = = master . end ( ) )
master . push_back ( slave . master [ i ] . option_no ) ;
}
size + = master . size ( ) * sizeof ( OPTVAL ) ;
opt = ( OPTEN * ) malloc ( size ) ;
bzero ( opt , size ) ;
opt - > enabled = slave . enable_now ;
opt - > opt_num = slave . option_no ;
opt - > master_count = 0 ;
for ( size_t i = 0 ; i < master . size ( ) ; + + i )
{
std : : vector < CURVAL > : : iterator m = std : : find ( cur_vals_ . begin ( ) , cur_vals_ . end ( ) , master [ i ] ) ;
if ( m = = cur_vals_ . end ( ) )
continue ;
opt - > master [ opt - > master_count ] . opt_num = master [ i ] ;
if ( m - > type = = " string " )
{
opt - > master [ opt - > master_count ] . data = malloc ( m - > val . length ( ) + 4 ) ;
strcpy ( ( char * ) opt - > master [ opt - > master_count ] . data , m - > val . c_str ( ) ) ;
}
else
{
opt - > master [ opt - > master_count ] . data = malloc ( sizeof ( double ) ) ;
if ( m - > type = = " bool " )
* ( ( bool * ) opt - > master [ opt - > master_count ] . data ) = ( m - > val = = " true " ) ;
else if ( m - > type = = " int " )
* ( ( int * ) opt - > master [ opt - > master_count ] . data ) = atoi ( m - > val . c_str ( ) ) ;
else
* ( ( double * ) opt - > master [ opt - > master_count ] . data ) = atof ( m - > val . c_str ( ) ) ;
opt - > master_count + + ;
}
}
return opt ;
}
void hg_sane_middleware : : free_control_enable_data ( OPTEN * opt )
{
if ( opt )
{
for ( int i = 0 ; i < opt - > master_count ; + + i )
{
if ( opt - > master [ i ] . data )
free ( opt - > master [ i ] . data ) ;
}
free ( opt ) ;
}
}
2022-05-17 07:04:55 +00:00
void hg_sane_middleware : : on_SCANNER_ERR_CONFIGURATION_CHANGED ( scanner_handle handle , const char * dev_name )
2022-05-03 03:56:07 +00:00
{
std : : vector < int > changed ;
reload_current_value ( handle , & changed ) ;
if ( changed . size ( ) )
{
for ( size_t i = 0 ; i < changed . size ( ) ; + + i )
{
std : : vector < CURVAL > : : iterator it = std : : find ( cur_vals_ . begin ( ) , cur_vals_ . end ( ) , changed [ i ] ) ;
if ( it ! = cur_vals_ . end ( ) )
something_after_do ( handle , dev_name , it - > opt_no , it - > val . c_str ( ) ) ;
}
}
}
/// </summary>
/// <summary>
/// 导出接口
/// </summary>
extern " C " { // avoid compiler exporting name in C++ style !!!
SANE_Status inner_sane_init ( SANE_Int * version_code , SANE_Auth_Callback authorize )
{
local_utility : : cb_auth_ = authorize ;
hg_sane_middleware : : instance ( ) ;
local_utility : : get_version ( version_code ) ;
return SANE_STATUS_GOOD ;
}
void inner_sane_exit ( void )
{
hg_sane_middleware : : clear ( ) ;
}
SANE_Status inner_sane_get_devices ( const SANE_Device * * * device_list , SANE_Bool local_only )
{
SANE_Status code = hg_sane_middleware : : instance ( ) - > get_devices ( device_list , local_only ) ;
return code ;
}
SANE_Status inner_sane_open ( SANE_String_Const devicename , SANE_Handle * handle )
{
return hg_sane_middleware : : instance ( ) - > open_device ( devicename , handle ) ;
}
void inner_sane_close ( SANE_Handle handle )
{
hg_sane_middleware : : instance ( ) - > close_device ( handle ) ;
}
const SANE_Option_Descriptor *
inner_sane_get_option_descriptor ( SANE_Handle handle , SANE_Int option )
{
return hg_sane_middleware : : instance ( ) - > get_option_descriptor ( handle , option ) ;
}
SANE_Status inner_sane_control_option ( SANE_Handle handle , SANE_Int option , SANE_Action action , void * value , SANE_Int * info )
{
return hg_sane_middleware : : instance ( ) - > set_option ( handle , option , action , value , info ) ;
}
SANE_Status inner_sane_get_parameters ( SANE_Handle handle , SANE_Parameters * params )
{
return hg_sane_middleware : : instance ( ) - > get_image_parameters ( handle , params ) ;
}
SANE_Status inner_sane_start ( SANE_Handle handle )
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_ALL , " sane_start \n " ) ;
2022-05-03 03:56:07 +00:00
return hg_sane_middleware : : instance ( ) - > start ( handle , NULL ) ;
}
SANE_Status inner_sane_read ( SANE_Handle handle , SANE_Byte * data , SANE_Int max_length , SANE_Int * length )
{
if ( ! length )
length = & max_length ;
else
* length = max_length ;
return hg_sane_middleware : : instance ( ) - > read ( handle , data , length ) ;
}
void inner_sane_cancel ( SANE_Handle handle )
{
hg_sane_middleware : : instance ( ) - > stop ( handle ) ;
}
SANE_Status inner_sane_set_io_mode ( SANE_Handle handle , SANE_Bool non_blocking )
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_ALL , " sane_set_io_mode \n " ) ;
2022-05-03 03:56:07 +00:00
return non_blocking ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD ;
}
SANE_Status inner_sane_get_select_fd ( SANE_Handle handle , SANE_Int * fd )
{
return SANE_STATUS_UNSUPPORTED ;
}
SANE_String_Const inner_sane_strstatus ( SANE_Status status )
{
2022-05-30 03:04:26 +00:00
return hg_scanner_err_name ( status ) ;
2022-05-03 03:56:07 +00:00
}
SANE_Status inner_sane_init_ex ( SANE_Int * version_code , sane_callback cb , void * param )
{
2022-06-18 00:55:15 +00:00
local_utility : : set_callback ( cb , param ) ;
2022-05-03 03:56:07 +00:00
hg_sane_middleware : : instance ( ) ;
local_utility : : get_version ( version_code ) ;
return SANE_STATUS_GOOD ;
}
SANE_Status inner_sane_io_control ( SANE_Handle h , unsigned long code , void * data , unsigned * len )
{
return hg_sane_middleware : : instance ( ) - > io_control ( h , code , data , len ) ;
}
void sanei_debug_msg ( int level , int max_level , const char * be , const char * fmt , va_list ap )
{
}
}
2022-05-27 01:24:28 +00:00
# ifdef WIN32
2022-06-18 08:47:21 +00:00
HMODULE g_my_inst = NULL ;
2022-05-27 01:24:28 +00:00
BOOL WINAPI DllMain ( HINSTANCE inst , DWORD reason , LPVOID reserved )
{
if ( reason = = DLL_PROCESS_ATTACH )
{
2022-06-18 08:47:21 +00:00
g_my_inst = inst ;
2022-06-01 03:04:10 +00:00
if ( g_sane_path . empty ( ) )
2022-05-27 01:24:28 +00:00
{
char path [ MAX_PATH ] = { 0 } ;
GetModuleFileNameA ( inst , path , _countof ( path ) - 1 ) ;
if ( strrchr ( path , ' \\ ' ) )
{
strrchr ( path , ' \\ ' ) [ 1 ] = 0 ;
2022-06-01 03:04:10 +00:00
g_sane_path = path ;
2022-05-27 01:24:28 +00:00
}
}
}
2022-06-15 03:05:36 +00:00
else if ( reason = = DLL_PROCESS_DETACH )
{
inner_sane_exit ( ) ;
}
2022-05-27 01:24:28 +00:00
return TRUE ;
}
# endif