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
# include "../sdk/hginclude/hg_log.h"
# include "ini_file.h"
# 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
# ifdef RUN_TEST
std : : string jsontext ( " { \" device_type \" : \" G100 \" , \" option_count \" :51, \" 1 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-1 \" , \" title \" : \" \\ u6062 \\ u590d \\ u9ed8 \\ u8ba4 \\ u8bbe \\ u7f6e \" , \" desc \" : \" \\ u6062 \\ u590d \\ u9ed8 \\ u8ba4 \\ u8bbe \\ u7f6e \" , \" type \" : \" button \" , \" cur \" : \" button \" , \" default \" : \" button \" , \" size \" :0}, \" 2 \" :{ \" category \" : \" advanced \" , \" name \" : \" cfg-2 \" , \" title \" : \" \\ u5e2e \\ u52a9 \" , \" desc \" : \" \\ u663e \\ u793a \\ u8f6f \\ u4ef6 \\ u5e2e \\ u52a9 \\ u6587 \\ u6863 \" , \" type \" : \" button \" , \" cur \" : \" true \" , \" default \" : \" true \" , \" size \" :4}, \" 3 \" :{ \" category \" : \" base \" , \" name \" : \" grp-1 \" , \" title \" : \" \\ u57fa \\ u672c \\ u8bbe \\ u7f6e \" , \" type \" : \" group \" }, \" 4 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-4 \" , \" title \" : \" \\ u989c \\ u8272 \\ u6a21 \\ u5f0f \" , \" desc \" : \" \\ u8bbe \\ u7f6e \\ u989c \\ u8272 \\ u4f4d \\ u6df1 \" , \" type \" : \" string \" , \" cur \" : \" 24 \\ u4f4d \\ u5f69 \\ u8272 \" , \" default \" : \" 24 \\ u4f4d \\ u5f69 \\ u8272 \" , \" size \" :24, \" range \" :[ \" 24 \\ u4f4d \\ u5f69 \\ u8272 \" , \" 256 \\ u7ea7 \\ u7070 \\ u5ea6 \" , \" \\ u9ed1 \\ u767d \" , \" \\ u989c \\ u8272 \\ u81ea \\ u52a8 \\ u8bc6 \\ u522b \" ]}, \" 5 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-5 \" , \" title \" : \" 24 \\ u4f4d \\ u5f69 \\ u8272 \\ u56fe \\ u50cf- \\ u591a \\ u6d41 \\ u8f93 \\ u51fa \" , \" desc \" : \" \" , \" type \" : \" string \" , \" cur \" : \" \\ u4e0d \\ u9009 \\ u62e9 \\ u8f93 \\ u51fa \\ u6a21 \\ u5f0f \" , \" default \" : \" \\ u4e0d \\ u9009 \\ u62e9 \\ u8f93 \\ u51fa \\ u6a21 \\ u5f0f \" , \" size \" :28, \" range \" :[ \" \\ u4e0d \\ u9009 \\ u62e9 \\ u8f93 \\ u51fa \\ u6a21 \\ u5f0f \" , \" \\ u5f69 \\ u8272+ \\ u7070 \\ u5ea6+ \\ u9ed1 \\ u767d \" , \" \\ u5f69 \\ u8272+ \\ u7070 \\ u5ea6 \" , \" \\ u5f69 \\ u8272+ \\ u9ed1 \\ u767d \" , \" \\ u7070 \\ u5ea6+ \\ u9ed1 \\ u767d \" ], \" depend_or \" :[ \" 4==24 \\ u4f4d \\ u5f69 \\ u8272 \" ]}, \" 6 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-6 \" , \" title \" : \" \\ u7070 \\ u5ea6 \\ u6216 \\ u9ed1 \\ u767d \\ u56fe \\ u50cf - \\ u9664 \\ u8272 \" , \" desc \" : \" \\ u9664 \\ u53bb \\ u56fe \\ u50cf \\ u5f69 \\ u8272 \" , \" type \" : \" string \" , \" cur \" : \" \\ u4e0d \\ u9664 \\ u8272 \" , \" default \" : \" \\ u4e0d \\ u9664 \\ u8272 \" , \" size \" :20, \" range \" :[ \" \\ u4e0d \\ u9664 \\ u8272 \" , \" \\ u9664 \\ u7ea2 \\ u8272 \" , \" \\ u9664 \\ u7eff \\ u8272 \" , \" \\ u9664 \\ u84dd \\ u8272 \" , \" \\ u7ea2 \\ u8272 \\ u589e \\ u5f3a \" , \" \\ u7eff \\ u8272 \\ u589e \\ u5f3a \" , \" \\ u84dd \\ u8272 \\ u589e \\ u5f3a \" ], \" depend_or \" :[ \" 4==256 \\ u7ea7 \\ u7070 \\ u5ea6 \" , \" 4== \\ u9ed1 \\ u767d \" ]}, \" 7 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-7 \" , \" title \" : \" 24 \\ u4f4d \\ u5f69 \\ u8272 \\ u56fe \\ u50cf - \\ u591a \\ u6d41 \\ u8f93 \\ u51fa \\ u9664 \\ u7ea2 \" , \" desc \" : \" \\ u591a \\ u901a \\ u9053 \\ u8f93 \\ u51fa \\ u4e2d \\ uff0c \\ u53bb \\ u9664 \\ u7ea2 \\ u8272 \" , \" type \" : \" bool \" , \" cur \" :false, \" default \" :false, \" size \" :4, \" depend_or \" :[ \" 4==24 \\ u4f4d \\ u5f69 \\ u8272 \" ]}, \" 8 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-8 \" , \" title \" : \" 24 \\ u4f4d \\ u5f69 \\ u8272 \\ u56fe \\ u50cf - \\ u7b54 \\ u9898 \\ u5361 \\ u9664 \\ u7ea2 \" , \" desc \" : \" \\ u7b54 \\ u9898 \\ u5361 \\ u626b \\ u63cf \\ u4e2d \\ u53bb \\ u9664 \\ u7ea2 \\ u8272 \" , \" type \" : \" bool \" , \" cur \" :false, \" default \" :false, \" size \" :4, \" depend_or \" :[ \" 4==24 \\ u4f4d \\ u5f69 \\ u8272 \" ]}, \" 9 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-9 \" , \" title \" : \" \\ u80cc \\ u666f \\ u79fb \\ u9664 \" , \" desc \" : \" \\ u79fb \\ u9664 \\ u5f69 \\ u8272 \\ u56fe \\ u50cf \\ u80cc \\ u666f \" , \" type \" : \" bool \" , \" cur \" :false, \" default \" :false, \" size \" :4, \" depend_or \" :[ \" 4==24 \\ u4f4d \\ u5f69 \\ u8272 \" ]}, \" 10 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-10 \" , \" title \" : \" \\ u80cc \\ u666f \\ u8272 \\ u5f69 \\ u6d6e \\ u52a8 \\ u8303 \\ u56f4 \" , \" desc \" : \" \\ u8bbe \\ u5b9a \\ u80cc \\ u666f \\ u8272 \\ u5f69 \\ u7684 \\ u6d6e \\ u52a8 \\ u8303 \\ u56f4 \\ uff0c \\ u5728 \\ u8be5 \\ u8303 \\ u56f4 \\ u5185 \\ u7684 \\ u90fd \\ u5f53 \\ u4f5c \\ u80cc \\ u666f \\ u79fb \\ u9664 \" , \" type \" : \" int \" , \" cur \" :10, \" default \" :10, \" size \" :4, \" range \" :{ \" min \" :1, \" max \" :40}, \" depend_or \" :[ \" 9==true \" ]}, \" 11 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-11 \" , \" title \" : \" \\ u9ed1 \\ u767d \\ u56fe \\ u50cf \\ u566a \\ u70b9 \\ u4f18 \\ u5316 \" , \" desc \" : \" \\ u566a \\ u70b9 \\ u4f18 \\ u5316 \" , \" type \" : \" bool \" , \" cur \" :false, \" default \" :false, \" size \" :4, \" depend_or \" :[ \" 4== \\ u9ed1 \\ u767d \" ]}, \" 12 \" :{ \" category \" : \" base \" , \" name \" : \" cfg-12 \" , \" title \" : \" \\ u566a \\ u70b9 \\ u4f18 \\ u5316 \\ u5c3a \\ u5bf8 \" , \" desc \" : \" \\ u566a \\ u70b9 \\ u4f18 \\ u5316 \\ u5c3a \\ u5bf8 \" , \" type \" : \" int \" , \" cur \" :30, \" default \" :30, \" size \" :4, \" range \" :{ \" min \" :10, \" max \" :50}, \" depend_or \" :[ \" 11==true \" ]}, \" 13 \
# endif
namespace local_utility
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static char g_unk_err [ 80 ] = { 0 } ;
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 ;
}
const char * error_text ( SANE_Status statu )
{
RETURN_IF ( statu , SANE_STATUS_GOOD ) ;
RETURN_IF ( statu , SANE_STATUS_UNSUPPORTED ) ;
RETURN_IF ( statu , SANE_STATUS_CANCELLED ) ;
RETURN_IF ( statu , SANE_STATUS_DEVICE_BUSY ) ;
RETURN_IF ( statu , SANE_STATUS_INVAL ) ;
RETURN_IF ( statu , SANE_STATUS_EOF ) ;
RETURN_IF ( statu , SANE_STATUS_JAMMED ) ;
RETURN_IF ( statu , SANE_STATUS_NO_DOCS ) ;
RETURN_IF ( statu , SANE_STATUS_COVER_OPEN ) ;
RETURN_IF ( statu , SANE_STATUS_IO_ERROR ) ;
RETURN_IF ( statu , SANE_STATUS_NO_MEM ) ;
RETURN_IF ( statu , SANE_STATUS_ACCESS_DENIED ) ;
2022-05-17 07:04:55 +00:00
RETURN_IF ( statu , SCANNER_ERR_INVALID_PARAMETER ) ;
RETURN_IF ( statu , SCANNER_ERR_USER_CANCELED ) ;
RETURN_IF ( statu , SCANNER_ERR_INSUFFICIENT_MEMORY ) ;
RETURN_IF ( statu , SCANNER_ERR_ACCESS_DENIED ) ;
RETURN_IF ( statu , SCANNER_ERR_IO_PENDING ) ;
RETURN_IF ( statu , SCANNER_ERR_NOT_EXACT ) ;
RETURN_IF ( statu , SCANNER_ERR_CONFIGURATION_CHANGED ) ;
RETURN_IF ( statu , SCANNER_ERR_NOT_OPEN ) ;
RETURN_IF ( statu , SCANNER_ERR_NOT_START ) ;
RETURN_IF ( statu , SCANNER_ERR_NOT_ANY_MORE ) ;
RETURN_IF ( statu , SCANNER_ERR_NO_DATA ) ;
RETURN_IF ( statu , SCANNER_ERR_HAS_DATA_YET ) ;
RETURN_IF ( statu , SCANNER_ERR_OUT_OF_RANGE ) ;
RETURN_IF ( statu , SCANNER_ERR_IO ) ;
RETURN_IF ( statu , SCANNER_ERR_TIMEOUT ) ;
RETURN_IF ( statu , SCANNER_ERR_OPEN_FILE_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_CREATE_FILE_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_WRITE_FILE_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_DATA_DAMAGED ) ;
RETURN_IF ( statu , SCANNER_ERR_USB_INIT_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_USB_REGISTER_PNP_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_USB_CLAIM_INTERFACE_FAILED ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_NOT_FOUND ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_NOT_SUPPORT ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_BUSY ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_SLEEPING ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_COUNT_MODE ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_STOPPED ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_COVER_OPENNED ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_NO_PAPER ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_FEEDING_PAPER ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_DOUBLE_FEEDING ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_PAPER_JAMMED ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_STAPLE_ON ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_PAPER_SKEW ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_SIZE_CHECK ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_DOGEAR ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_NO_IMAGE ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_SCANN_ERROR ) ;
RETURN_IF ( statu , SCANNER_ERR_DEVICE_PC_BUSY ) ;
2022-05-03 03:56:07 +00:00
sprintf ( g_unk_err , " \346 \234 \252 \347 \237 \245 \351 \224 \231 \350 \257 \257 \357 \274 \232 %X " , statu ) ;
return g_unk_err ;
}
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
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static iconv_t iconv_au8 = NULL ;
static iconv_t iconv_u8a = NULL ;
# ifndef WIN32
static std : : string convert ( iconv_t h , const void * in , size_t bytes )
{
std : : string ret ( " " ) ;
if ( h )
{
size_t rest = bytes , buf_size = bytes * 2 , err = 0 , out = buf_size - 1 ;
char * buf = ( char * ) local_utility : : acquire_memory ( buf_size , " local_utility::convert " ) , * src = ( char * ) in , * cur = buf ;
bzero ( buf , buf_size ) ;
err = iconv ( h , ( char * * ) & src , & rest , & cur , & out ) ;
while ( err = = 0 & & rest )
{
if ( buf_size / bytes > 8 )
break ;
free ( buf ) ;
buf_size + = bytes ;
buf = ( char * ) local_utility : : acquire_memory ( buf_size , " local_utility::convert " ) ;
bzero ( buf , buf_size ) ;
out = buf_size - 1 ;
rest = bytes ;
src = ( char * ) in ;
cur = buf ;
err = iconv ( h , ( char * * ) & src , & rest , & cur , & out ) ;
}
if ( err = = 0 )
ret = std : : string ( buf , buf_size - 1 - out ) ;
free ( buf ) ;
}
return ret ;
}
# endif
bool char_transfer_init ( void )
{
# ifdef RUN_TEST
FILE * src = fopen ( " /tmp/hg_g100.txt " , " rb " ) ;
bool found = false ;
if ( src )
{
long len = 0 ;
char * buf = NULL ;
fseek ( src , 0 , SEEK_END ) ;
len = ftell ( src ) ;
fseek ( src , 0 , SEEK_SET ) ;
buf = ( char * ) malloc ( len + 4 ) ;
bzero ( buf , len + 4 ) ;
fread ( buf , 1 , len , src ) ;
fclose ( src ) ;
// try parse ...
json * j = new json ( ) ;
if ( j - > attach_text ( buf ) )
{
jsontext = buf ;
found = true ;
}
delete j ;
free ( buf ) ;
}
if ( found )
2022-05-17 07:04:55 +00:00
hg_log : : log ( LOG_LEVEL_DEBUG_INFO , " Testing configuration loaded from /tmp/hg_g100.txt ^_^ \n " ) ;
2022-05-03 03:56:07 +00:00
else
2022-05-17 07:04:55 +00:00
hg_log : : log ( LOG_LEVEL_DEBUG_INFO , " '/tmp/hg_g100.txt' is not found or data damaged. :( \n " ) ;
2022-05-03 03:56:07 +00:00
# endif
# ifndef WIN32
if ( ! iconv_au8 )
{
iconv_au8 = iconv_open ( " gb2312 " , " utf-8 " ) ;
if ( iconv_au8 = = ( iconv_t ) - 1 )
{
iconv_au8 = NULL ;
return false ;
}
}
if ( ! iconv_u8a )
{
iconv_u8a = iconv_open ( " utf-8 " , " gb2312 " ) ;
if ( iconv_u8a = = ( iconv_t ) - 1 )
{
iconv_u8a = NULL ;
return false ;
}
}
# endif
return true ;
}
std : : string utf8_2_ansi ( const char * utf8 )
{
return utf8 ;
if ( ! iconv_u8a | | ! utf8 | | * utf8 = = 0 )
return " " ;
# ifdef WIN32
return utf8 ;
# else
return convert ( iconv_u8a , utf8 , strlen ( utf8 ) ) ;
# endif
}
std : : string ansi_2_utf8 ( const char * ansi )
{
if ( ! iconv_au8 | | ! ansi | | * ansi = = 0 )
return " " ;
# ifdef WIN32
return ansi ;
# else
return ansi ;
return convert ( iconv_au8 , ansi , strlen ( ansi ) ) ;
# endif
}
void char_transfer_uninit ( void )
{
# ifndef WIN32
if ( iconv_au8 )
{
iconv_close ( iconv_au8 ) ;
iconv_au8 = NULL ;
}
if ( iconv_u8a )
{
iconv_close ( iconv_u8a ) ;
iconv_u8a = NULL ;
}
# endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 ;
}
// 暂不支持科学计数法 1.2e+10
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 ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void init_log ( void )
{
std : : string path ( hg_log : : pe_path ( ) ) ,
val ( " " ) ;
simple_ini ini ;
bool given_path = false ;
2022-05-17 07:04:55 +00:00
hg_log_type logt = LOG_TYPE_FILE ;
hg_log_level logl = LOG_LEVEL_ALL ;
2022-05-03 03:56:07 +00:00
2022-05-17 07:04:55 +00:00
hg_log : : init ( LOG_TYPE_CONSOLE , LOG_LEVEL_DEBUG_INFO ) ;
HG_VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " current path: '%s' \n " , path . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
if ( path . empty ( ) )
path = simple_ini : : temporary_path ( ) ;
// pwd/hgsane.conf
//
// [log]
// type=console // or none or other as file
// level=debug // or warning or fatal or other as all
//
if ( ini . load ( ( path + " /configs/scanner.conf " ) . c_str ( ) ) = = 0 )
{
val = ini . get ( " log " , " type " ) ;
if ( stricmp ( val . c_str ( ) , " console " ) = = 0 )
2022-05-17 07:04:55 +00:00
logt = LOG_TYPE_CONSOLE ;
2022-05-03 03:56:07 +00:00
else if ( stricmp ( val . c_str ( ) , " none " ) = = 0 )
2022-05-17 07:04:55 +00:00
logt = LOG_TYPE_NONE ;
if ( logt = = LOG_TYPE_FILE )
2022-05-03 03:56:07 +00:00
{
val = ini . get ( " log " , " file " ) ;
if ( ! val . empty ( ) )
{
path = val ;
given_path = true ;
}
}
val = ini . get ( " log " , " level " ) ;
if ( stricmp ( val . c_str ( ) , " debug " ) = = 0 )
2022-05-17 07:04:55 +00:00
logl = LOG_LEVEL_DEBUG_INFO ;
2022-05-03 03:56:07 +00:00
else if ( stricmp ( val . c_str ( ) , " warning " ) = = 0 )
2022-05-17 07:04:55 +00:00
logl = LOG_LEVEL_WARNING ;
2022-05-03 03:56:07 +00:00
else if ( stricmp ( val . c_str ( ) , " fatal " ) = = 0 )
2022-05-17 07:04:55 +00:00
logl = LOG_LEVEL_FATAL ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
if ( logt = = LOG_TYPE_FILE & & ! given_path )
2022-05-03 03:56:07 +00:00
{
std : : string child ( " /scanner_log " ) ;
path + = child ;
if ( MKDIR ( path . c_str ( ) , S_IREAD | S_IWRITE | S_IEXEC ) = = 0 | | errno = = EEXIST )
{
path + = " /log.txt " ;
}
else
{
2022-05-17 07:04:55 +00:00
HG_VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " create folder '%s' failed(%d), now try temporary directory \n " , path . c_str ( ) , errno ) ;
2022-05-03 03:56:07 +00:00
path = simple_ini : : temporary_path ( ) + child ;
if ( MKDIR ( path . c_str ( ) , S_IREAD | S_IWRITE | S_IEXEC ) = = 0 | | errno = = EEXIST )
path + = " /log.txt " ;
else
{
2022-05-17 07:04:55 +00:00
HG_VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " create temporary directory '%s' failed(%d), log to console \n " , path . c_str ( ) , errno ) ;
logt = LOG_TYPE_CONSOLE ;
logl = LOG_LEVEL_WARNING ;
2022-05-03 03:56:07 +00:00
}
}
}
hg_log : : init ( logt , logl , & path [ 0 ] ) ;
2022-05-17 07:04:55 +00:00
# ifdef OEM_HANWANG
path = hg_log : : current_time ( ) + " hwsane is starting ... \n " ;
# elif defined(OEM_LISICHENG)
path = hg_log : : current_time ( ) + " lscsane is starting ... \n " ;
# else
2022-05-03 03:56:07 +00:00
path = hg_log : : current_time ( ) + " hgsane is starting ... \n " ;
2022-05-17 07:04:55 +00:00
# endif
hg_log : : log ( LOG_LEVEL_FATAL , path . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 ) ;
RETURN_IF ( ev , SANE_EVENT_WIN_DEBUG_INFO ) ;
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
if ( code = = SANE_EVENT_WIN_DEBUG_INFO )
{
hg_log : : log ( ( hg_log_level ) * len , ( char * ) data ) ;
return 0 ;
}
SANE_Handle h = hg_sane_middleware : : scanner_handle_to_sane ( dev ) ;
2022-05-17 07:04:55 +00:00
HG_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 ui_log_cb ( hg_log_level level , const char * info )
{
}
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-05-17 07:57:09 +00:00
unsigned long long v = hg_scanner_get_version ( ) ;
unsigned short * byt = ( unsigned short * ) & v ;
2022-05-17 07:04:55 +00:00
# ifdef OEM_HANWANG
HG_VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " HanWang scanner driver version: %u.%u.%u.%u \n " , byt [ 3 ] , byt [ 2 ] , byt [ 1 ] , byt [ 0 ] ) ;
2022-05-17 07:57:09 +00:00
HG_VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " hwsane driver version: %u.%u.%u \n " , SANE_CURRENT_MAJOR , SANE_CURRENT_MINOR , VERSION_BUILD ) ;
2022-05-17 07:04:55 +00:00
# elif defined(OEM_LISICHENG)
HG_VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " Lisicheng scanner driver version: %u.%u.%u.%u \n " , byt [ 3 ] , byt [ 2 ] , byt [ 1 ] , byt [ 0 ] ) ;
2022-05-17 07:57:09 +00:00
HG_VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " lscsane driver version: %u.%u.%u \n " , SANE_CURRENT_MAJOR , SANE_CURRENT_MINOR , VERSION_BUILD ) ;
2022-05-17 07:04:55 +00:00
# else
HG_VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " Huagao scanner driver version: %u.%u.%u.%u \n " , byt [ 3 ] , byt [ 2 ] , byt [ 1 ] , byt [ 0 ] ) ;
2022-05-17 07:57:09 +00:00
HG_VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " hgsane driver version: %u.%u.%u \n " , SANE_CURRENT_MAJOR , SANE_CURRENT_MINOR , VERSION_BUILD ) ;
2022-05-17 07:04:55 +00:00
# endif
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 ;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// test
# ifdef RUN_TEST
# include <thread>
# ifdef TEST_DEV
# include "scanner_manager.h"
# endif
static json * jsn_inst = NULL ;
static sane_callback g_cb = NULL ;
void * g_param = NULL ;
static unsigned int scan_count = - 1 ;
static unsigned int scan_count_ = 1 ;
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_initialize ( sane_callback callback , void * param )
2022-05-03 03:56:07 +00:00
{
# ifdef TEST_DEV
hg_scanner_mgr : : instance ( ) ;
# else
jsn_inst = new json ( & jsontext [ 0 ] ) ;
# endif
g_cb = callback ;
g_param = param ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
void hg_scanner_uninitialize ( void )
{
}
long hg_scanner_get_version ( void )
{
return SANE_VERSION_CODE ( 1 , 0 , 311 ) ;
}
static const char * scanner_name = " 华高扫描仪(模拟) " ;
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_enum ( ScannerInfo * scanner_list , long * count , bool local_only )
2022-05-03 03:56:07 +00:00
{
# ifdef TEST_DEV
return hg_scanner_mgr : : instance ( ) - > hg_scanner_enum ( scanner_list , count , local_only ) ;
# endif
if ( ! count )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( * count < 1 )
{
* count = 1 ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INSUFFICIENT_MEMORY ;
2022-05-03 03:56:07 +00:00
}
* count = 1 ;
strcpy ( scanner_list - > name , scanner_name ) ;
strcpy ( scanner_list - > type , " G100 " ) ;
strcpy ( scanner_list - > model , " Multi-color " ) ;
strcpy ( scanner_list - > vendor , " Huagao China. " ) ;
if ( ! jsn_inst )
{
std : : string v ( jsontext ) ;
jsn_inst = new json ( & v [ 0 ] ) ;
}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
static volatile bool run_ = true ;
void * thread_pnp ( void * )
{
2022-05-17 07:04:55 +00:00
ScannerInfo devs [ 4 ] ;
2022-05-03 03:56:07 +00:00
long count = sizeof ( devs ) / sizeof ( devs [ 0 ] ) ;
int ev = SANE_EVENT_DEVICE_ARRIVED ;
while ( run_ )
{
hg_scanner_enum ( devs , & count , true ) ;
for ( int i = 0 ; i < count ; + + i )
{
SANE_Device dev ;
unsigned int len = sizeof ( dev ) ;
dev . name = devs [ i ] . name ;
dev . vendor = devs [ i ] . vendor ;
dev . model = devs [ i ] . model ;
dev . type = devs [ i ] . type ;
local_utility : : ui_cb ( NULL , ev , ( void * ) & dev , & len , NULL ) ;
}
ev = ( rand ( ) % 2 = = 0 ) ? SANE_EVENT_DEVICE_ARRIVED : SANE_EVENT_DEVICE_LEFT ;
count = sizeof ( devs ) / sizeof ( devs [ 0 ] ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 180 * 1000 ) ) ;
}
return 0 ;
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_open ( scanner_handle * h , const char * name , bool shared , const char * user , const char * pwd , const char * check , char * rsc /*rsc[80]*/ )
2022-05-03 03:56:07 +00:00
{
if ( ! h | | ! name )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( strcmp ( name , scanner_name ) )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_FOUND ;
2022-05-03 03:56:07 +00:00
* h = ( scanner_handle ) 0x7e57 ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_close ( scanner_handle h , bool force )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_get_parameter ( scanner_handle h , unsigned param_no , char * json_data , long * len )
2022-05-03 03:56:07 +00:00
{
std : : string v ( " " ) ;
json * child = NULL ;
char key [ 20 ] ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_OUT_OF_RANGE ;
2022-05-03 03:56:07 +00:00
if ( ! len | | ! jsn_inst )
2022-05-17 07:04:55 +00:00
err = SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
else
{
if ( param_no = = 0 )
{
int count = 0 ;
jsn_inst - > get_value ( " option_count " , count ) ;
* len = count ;
2022-05-17 07:04:55 +00:00
err = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
else
{
bzero ( key , 20 ) ;
sprintf ( key , " %d " , param_no ) ;
jsn_inst - > get_value ( key , child ) ;
if ( child )
{
v = child - > to_string ( ) ;
delete child ;
if ( * len < = v . length ( ) )
{
2022-05-17 07:04:55 +00:00
err = SCANNER_ERR_INSUFFICIENT_MEMORY ;
2022-05-03 03:56:07 +00:00
* len = v . length ( ) + 4 ;
}
else
{
strcpy ( json_data , v . c_str ( ) ) ;
* len = v . length ( ) ;
2022-05-17 07:04:55 +00:00
err = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
}
}
}
return err ;
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_set_parameter ( scanner_handle h , unsigned param_no , void * data , long len )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
scanner_err ret = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
//if (param_no == 15)
//{
// int dpi = *((int*)data), regular = (dpi + 50) / 100 * 100;
//
// if (dpi != regular)
// {
// *(SANE_Int*)data = regular;
//
2022-05-17 07:04:55 +00:00
// ret = SCANNER_ERR_NOT_EXACT;
2022-05-03 03:56:07 +00:00
// }
//}
char path [ 20 ] ;
json * child = NULL ;
sprintf ( path , " %d " , param_no ) ;
jsn_inst - > get_value ( path , child ) ;
if ( child )
{
std : : string type ( " " ) , title ( " " ) ;
child - > get_value ( " title " , title ) ;
if ( title = = " 扫描张数 " )
{
if ( strcmp ( ( char * ) data , " 连续扫描 " ) = = 0 )
scan_count = - 1 ;
else
{
scan_count = 0 ;
}
}
else if ( title = = " 扫描数量 " )
scan_count_ = * ( ( int * ) data ) ;
sprintf ( path , " %d/cur " , param_no ) ;
child - > get_value ( " type " , type ) ;
if ( type = = " int " )
{
jsn_inst - > set_value ( path , * ( ( int * ) data ) ) ;
}
else if ( type = = " bool " )
{
jsn_inst - > set_value ( path , * ( ( bool * ) data ) ) ;
}
else if ( type = = " float " )
{
jsn_inst - > set_value ( path , * ( ( double * ) data ) ) ;
}
else if ( type ! = " button " )
{
jsn_inst - > set_value ( path , std : : string ( ( char * ) data ) ) ;
}
delete child ;
}
return ret ;
}
static unsigned long long fake_total = 1920 * 800 * 3 ;
static unsigned long long fake_read = 0 ;
static volatile bool cancel = false ;
static int pic_ind = 0 ;
static bool finished = false ;
# include <thread>
# include <pthread.h>
# include <chrono>
std : : unique_ptr < std : : thread > thread_img_handle ;
typedef struct _img_header
{
int width ; // in pixel
int height ; // in pixel
int bits ; // per channel
int channels ; // RGB - 3; GRAY - 1; ...
int line_bytes ; // bytes of ONE line
unsigned total_bytes ; // total bytes
} IMGHEAD , * LPIMGHEAD ;
void * fake_thread ( void * hs )
{
std : : string path ( local_utility : : get_self_path ( ) ) ;
char file [ 128 ] ;
IMGHEAD imgh ;
SANE_Image img ;
unsigned count = scan_count = = - 1 ? - 1 : scan_count_ ;
scanner_handle h = ( scanner_handle ) hs ;
path + = " /sample/ " ;
local_utility : : ui_cb ( h , SANE_EVENT_WORKING , ( void * ) " scanning ... " , NULL , NULL ) ;
while ( ! cancel )
{
sprintf ( file , " img_%x.txt " , + + pic_ind ) ;
FILE * src = fopen ( ( path + file ) . c_str ( ) , " rb " ) ;
if ( src )
{
fread ( & imgh , sizeof ( imgh ) , 1 , src ) ;
fclose ( src ) ;
sprintf ( file , " img_%x.dat " , pic_ind ) ;
src = fopen ( ( path + file ) . c_str ( ) , " rb " ) ;
if ( src )
{
void * data = malloc ( imgh . total_bytes ) ;
fread ( data , 1 , imgh . total_bytes , src ) ;
fclose ( src ) ;
img . bytes = imgh . total_bytes ;
img . data = ( unsigned char * ) data ;
img . header . bytes_per_line = imgh . line_bytes ;
img . header . depth = 8 ;
img . header . format = SANE_FRAME_RGB ;
img . header . last_frame = true ;
img . header . lines = imgh . height ;
img . header . pixels_per_line = imgh . width ;
local_utility : : ui_cb ( h , SANE_EVENT_IMAGE_OK , & img , ( unsigned int * ) & pic_ind , NULL ) ;
free ( data ) ;
}
else
{
2022-05-17 07:04:55 +00:00
unsigned int err = SCANNER_ERR_OPEN_FILE_FAILED ;
2022-05-03 03:56:07 +00:00
path + = file ;
local_utility : : ui_cb ( h , SANE_EVENT_ERROR , & path [ 0 ] , & err , NULL ) ;
2022-05-17 07:04:55 +00:00
HG_VLOG_2 ( LOG_LEVEL_DEBUG_INFO , 512 , " Open file failed(%d): %s \n " , errno , path . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
break ;
}
}
else
{
2022-05-17 07:04:55 +00:00
unsigned int err = SCANNER_ERR_OPEN_FILE_FAILED ;
2022-05-03 03:56:07 +00:00
path + = file ;
local_utility : : ui_cb ( h , SANE_EVENT_ERROR , & path [ 0 ] , & err , NULL ) ;
2022-05-17 07:04:55 +00:00
HG_VLOG_2 ( LOG_LEVEL_DEBUG_INFO , 512 , " Open file failed(%d): %s \n " , errno , path . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
break ;
}
if ( pic_ind > = count )
break ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 150 + ( rand ( ) % 150 ) ) ) ;
}
if ( cancel )
path = " scan cancled by user " ;
else
path = " scan finished " ;
unsigned ret = cancel ? SANE_STATUS_CANCELLED : SANE_STATUS_GOOD ;
local_utility : : ui_cb ( h , SANE_EVENT_SCAN_FINISHED , & path [ 0 ] , & ret , NULL ) ;
finished = true ;
return 0 ;
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_start ( scanner_handle h , void * async_event , int num )
2022-05-03 03:56:07 +00:00
{
//if (local_utility::cb_ui_)
//{
// if (thread_img_handle.get() && !finished)
2022-05-17 07:04:55 +00:00
// return SCANNER_ERR_DEVICE_BUSY;
2022-05-03 03:56:07 +00:00
//}
finished = false ;
fake_read = 0 ;
cancel = false ;
srand ( time ( NULL ) ) ;
pic_ind = 0 ;
local_utility : : ui_cb ( h , SANE_EVENT_STATUS , ( void * ) " ready to start ... " , NULL , NULL ) ;
if ( local_utility : : cb_ui_ )
{
// thread_img_handle.reset(new std::thread(fake_thread, h));
pthread_t id ;
pthread_create ( & id , NULL , fake_thread , ( void * ) h ) ;
}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_stop ( scanner_handle h )
2022-05-03 03:56:07 +00:00
{
cancel = true ;
//if (local_utility::cb_ui_)
//{
// if (thread_img_handle.get() && thread_img_handle->joinable())
// thread_img_handle->join();
// thread_img_handle.reset();
//}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_get_img_info ( scanner_handle h , SANE_Parameters * bmi , long len )
2022-05-03 03:56:07 +00:00
{
std : : string path ( local_utility : : get_self_path ( ) ) ;
char file [ 128 ] ;
path + = " /sample/ " ;
sprintf ( file , " img_%x.txt " , + + pic_ind ) ;
FILE * src = fopen ( ( path + file ) . c_str ( ) , " rb " ) ;
if ( src )
{
IMGHEAD imgh ;
fread ( & imgh , sizeof ( imgh ) , 1 , src ) ;
fclose ( src ) ;
bmi - > bytes_per_line = imgh . line_bytes ;
bmi - > depth = 8 ;
bmi - > format = SANE_FRAME_RGB ;
bmi - > last_frame = true ;
bmi - > lines = imgh . height ;
bmi - > pixels_per_line = imgh . width ;
}
else
{
bmi - > bytes_per_line = 1920 * 3 ;
bmi - > depth = 8 ;
bmi - > format = SANE_FRAME_RGB ;
bmi - > last_frame = true ;
bmi - > lines = 800 ;
bmi - > pixels_per_line = 1920 ;
}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_read_img_data ( scanner_handle h , unsigned char * data , long * len )
2022-05-03 03:56:07 +00:00
{
// if (*len <= 0 || fake_read >= fake_total)
2022-05-17 07:04:55 +00:00
// return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
if ( cancel )
2022-05-17 07:04:55 +00:00
return ( scanner_err ) SANE_STATUS_CANCELLED ;
2022-05-03 03:56:07 +00:00
std : : string path ( local_utility : : get_self_path ( ) ) ;
char file [ 128 ] ;
static int offset = 0 ;
path + = " /sample/ " ;
sprintf ( file , " img_%x.dat " , + + pic_ind ) ;
FILE * src = fopen ( ( path + file ) . c_str ( ) , " rb " ) ;
if ( src )
{
fseek ( src , offset , SEEK_SET ) ;
size_t r = fread ( data , 1 , * len , src ) ;
if ( r < * len )
offset = 0 ;
else
offset + = r ;
fclose ( src ) ;
* len = r ;
}
else
{
int bytes = 1920 * 800 * 3 - offset ;
if ( bytes > * len )
bytes = * len ;
for ( long i = 0 ; i < bytes ; + + i )
data [ i ] = rand ( ) ;
if ( bytes < = * len )
offset = 0 ;
else
offset + = bytes ;
}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_get_status ( scanner_handle h , int setstutas )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_reset ( scanner_handle h )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
2022-05-17 07:04:55 +00:00
scanner_err hg_scanner_control ( scanner_handle h , unsigned long code , void * data , unsigned * len )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
# endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
hg_sane_middleware * hg_sane_middleware : : inst_ = NULL ;
const SANE_Device * * hg_sane_middleware : : dev_list_ = NULL ;
hg_sane_middleware : : hg_sane_middleware ( void )
{
signal ( SIGUSR1 , & hg_sane_middleware : : device_pnp ) ;
local_utility : : char_transfer_init ( ) ;
hg_scanner_initialize ( local_utility : : ui_cb , NULL ) ;
}
hg_sane_middleware : : ~ hg_sane_middleware ( )
{
local_utility : : char_transfer_uninit ( ) ;
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-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-17 07:04:55 +00:00
//HG_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-17 07:04:55 +00:00
HG_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 ;
}
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_ ;
}
void hg_sane_middleware : : clear ( void )
{
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 // 软件可设置选项
| SANE_CAP_AUTOMATIC ; // 硬件可设置默认值
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-17 07:04:55 +00:00
//HG_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 // 软件可设置选项
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认值
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-17 07:04:55 +00:00
//HG_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 // 软件可设置选项
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认值
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-17 07:04:55 +00:00
//HG_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 // 软件可设置选项
/*| SANE_CAP_AUTOMATIC*/ ; // 硬件可设置默认值
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-17 07:04:55 +00:00
//HG_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 )
{
// 由于目前对多设备的支持还不是刚需,故代码只考虑单设备情况,设备关闭后,清除所有变量
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-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 ) ;
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 ) )
{
constraints . push_back ( local_utility : : utf8_2_ansi ( val . c_str ( ) ) ) ;
while ( range - > next_child ( val ) )
{
constraints . push_back ( local_utility : : utf8_2_ansi ( val . c_str ( ) ) ) ;
}
}
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-17 07:04:55 +00:00
hg_log : : log ( 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-06 05:37:14 +00:00
else if ( strcmp ( ret - > name , KNOWN_OPT_NAME_CUSTOM_AREA_LEFT ) = = 0 | |
strcmp ( ret - > name , KNOWN_OPT_NAME_CUSTOM_AREA_RIGHT ) = = 0 | |
strcmp ( ret - > name , KNOWN_OPT_NAME_CUSTOM_AREA_TOP ) = = 0 | |
strcmp ( ret - > name , KNOWN_OPT_NAME_CUSTOM_AREA_BOTTOM ) = = 0 )
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;
// 关联项
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 ) ;
}
bool hg_sane_middleware : : get_current_value ( scanner_handle handle , int option , void * value , SANE_Value_Type * type )
{
std : : string val ( get_option_json ( handle , option ) ) ;
json * jsn = new json ( ) ;
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-06 05:37:14 +00:00
if ( name = = KNOWN_OPT_NAME_CUSTOM_GAMMA )
{
SANE_Int * v = ( SANE_Int * ) value ;
std : : vector < std : : string > vs ;
jsn - > get_as_array ( " cur " , vs ) ;
for ( int i = 0 ; i < 3 * 256 & & i < vs . size ( ) ; + + i )
v [ i ] = atoi ( vs [ i ] . c_str ( ) ) ;
}
else 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-05-17 07:04:55 +00:00
HG_VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " <--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 ;
}
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 ;
}
}
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
{
count + = 4 ; // 为两次hg_scanner_enum间隙可能新增的设备预留空间
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 ;
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 ;
}
}
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 ;
}
else
{
if ( get_current_value ( handle , option , value ) )
ret = SANE_STATUS_GOOD ;
}
return ret ;
}
else
{
SANE_Option_Descriptor * desc = find_stored_descriptor ( dev . dev_name . c_str ( ) , option ) ;
if ( ! desc )
{
2022-05-17 07:04:55 +00:00
HG_VLOG_MINI_1 ( LOG_LEVEL_WARNING , " Option descriptor %d not found. \n " , option ) ;
2022-05-03 03:56:07 +00:00
return SANE_STATUS_UNSUPPORTED ;
}
else if ( ! value & & desc - > type ! = SANE_TYPE_BUTTON )
{
2022-05-17 07:04:55 +00:00
HG_VLOG_MINI_2 ( LOG_LEVEL_WARNING , " Option descriptor %d(%s) need a value!. \n " , option , desc - > title ) ;
2022-05-03 03:56:07 +00:00
return SANE_STATUS_INVAL ;
}
SANE_Status status = SANE_STATUS_GOOD ;
std : : string v ( hg_sane_middleware : : option_value_2_string ( desc - > type , value ) ) ;
void * pass = value ;
double dv = .0f ;
bool bv = false ;
int size = desc - > size ;
2022-05-17 07:04:55 +00:00
scanner_err err = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
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 ) ;
}
err = hg_scanner_set_parameter ( handle , option , pass , size ) ;
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 ) ;
}
std : : string prev ( v ) ;
v = hg_sane_middleware : : option_value_2_string ( desc - > type , value ) ;
if ( prev = = v )
{
2022-05-17 07:04:55 +00:00
HG_VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " -->Set option(%d - %s) value: %s \n " , option , desc - > title , v . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
else
{
2022-05-17 07:04:55 +00:00
HG_VLOG_4 ( LOG_LEVEL_DEBUG_INFO , 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-17 07:04:55 +00:00
HG_VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " the setting '%s' affects other options value, RELOAD ... \n " , desc - > title ) ;
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 ;
return status ;
}
}
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-17 07:04:55 +00:00
HG_VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " the setting '0x%08x' affects other options value, RELOAD ... \n " , nc ) ;
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>
/// 关联项处理
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-17 07:04:55 +00:00
HG_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-17 07:04:55 +00:00
HG_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 : : init_log ( ) ;
local_utility : : cb_auth_ = authorize ;
hg_sane_middleware : : instance ( ) ;
local_utility : : get_version ( version_code ) ;
return SANE_STATUS_GOOD ;
}
void inner_sane_exit ( void )
{
# ifdef RUN_TEST
run_ = false ;
# endif
local_utility : : stop_work ( ) ;
hg_sane_middleware : : clear ( ) ;
2022-05-17 07:04:55 +00:00
hg_log : : log ( LOG_LEVEL_FATAL , ( hg_log : : current_time ( ) + " hgsane exited. \n " ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
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-17 07:04:55 +00:00
HG_VLOG_MINI_1 ( LOG_LEVEL_ALL , " [%s] - sane_start \n " , hg_log : : format_current_thread_id ( ) . c_str ( ) ) ;
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 )
{
2022-05-17 07:04:55 +00:00
// HG_VLOG_MINI_1(LOG_LEVEL_ALL, "[%s] - sane_read\n", hg_log::format_current_thread_id().c_str());
2022-05-03 03:56:07 +00:00
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-17 07:04:55 +00:00
HG_VLOG_MINI_1 ( LOG_LEVEL_ALL , " [%s] - sane_set_io_mode \n " , hg_log : : format_current_thread_id ( ) . c_str ( ) ) ;
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 )
{
return local_utility : : error_text ( status ) ;
}
SANE_Status inner_sane_init_ex ( SANE_Int * version_code , sane_callback cb , void * param )
{
local_utility : : init_log ( ) ;
local_utility : : cb_ui_ = cb ;
local_utility : : cb_ui_parm_ = param ;
hg_sane_middleware : : instance ( ) ;
local_utility : : get_version ( version_code ) ;
# ifdef RUN_TEST
if ( local_utility : : cb_ui_ )
{
// thread_img_handle.reset(new std::thread(fake_thread, h));
pthread_t id ;
pthread_create ( & id , NULL , thread_pnp , NULL ) ;
}
# endif
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 )
{
//char* f = (char*)local_utility::acquire_memory(strlen(fmt) + 20, "sanei_debug_msg");
//
//strcpy(f, "%s - ");
//strcat(f, fmt);
//strcat(f, "\n");
//hg_log::vlog(strlen(f) + 256, f, be, ap);
//free(f);
}
}