2022-08-10 03:10:20 +00:00
# include " GScan439Android.h "
# include "IUsb.h"
# include "UsbScanEx.h"
# include <iostream>
2023-03-13 08:53:10 +00:00
# include "aes.h"
# include "hex.h"
# include "modes.h"
2022-08-10 03:10:20 +00:00
using namespace std ;
static std : : mutex mx_ctrl ;
# define m_max(a, b) (((a) > (b)) ? (a) : (b))
# define m_min(a, b) (((a) < (b)) ? (a) : (b))
static int read_reg ( std : : shared_ptr < IUsb > & usb , int addr )
{
std : : lock_guard < std : : mutex > lck ( mx_ctrl ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 50 ) ) ;
if ( usb . get ( ) & & usb - > is_connected ( ) ) {
int val = 0 ;
usb - > control_msg ( 0xc0 , USB_REQ_GET_DEV_REGS , addr , 0 , 4 , & val ) ;
return val ;
}
else
FileTools : : writelog ( log_ERROR , " read_reg error usb disconnect " ) ;
return 0 ;
}
static void write_reg ( std : : shared_ptr < IUsb > & usb , int addr , int val )
{
std : : lock_guard < std : : mutex > lck ( mx_ctrl ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 50 ) ) ;
if ( usb . get ( ) & & usb - > is_connected ( ) )
{
usb - > control_msg ( 0x40 , USB_REQ_SET_DEV_REGS , addr , 0 , 4 , & val ) ;
}
else
FileTools : : writelog ( log_ERROR , " write_reg error usb disconnect " ) ;
}
static void scanner_control ( std : : shared_ptr < IUsb > & usb , int cmd )
{
write_reg ( usb , 0 , cmd ) ;
}
GScan439Android : : GScan439Android ( ) : m_readimgpool ( 1 )
{
im_data . reset ( new std : : vector < char > ( ) ) ;
m_status = - 1 ;
m_pImages . reset ( new ImageMatQueue ( ) ) ;
}
GScan439Android : : ~ GScan439Android ( )
{
if ( m_usbthread . get ( ) & & m_usbthread - > joinable ( ) )
{
b_usbthread = false ;
m_usbthread - > join ( ) ;
m_usbthread . reset ( ) ;
}
imgs . ShutDown ( ) ;
m_imagedata . ShutDown ( ) ;
}
void GScan439Android : : open ( int vid , int pid )
{
if ( m_usb . get ( ) & & m_usb - > is_connected ( ) )
return ;
auto lsusb = UsbScan_List : : find_vid_pid ( vid , pid ) ;
if ( ! lsusb . empty ( ) )
{
m_usb = * lsusb . begin ( ) ;
m_usb - > open ( ) ;
if ( m_usb - > is_open ( ) )
m_usb - > set_usbhotplug_callback ( usbhotplug_callback , this ) ;
}
}
void GScan439Android : : regist_deviceevent_callback ( deviceevent_callback callback , void * usrdata )
{
huagods = usrdata ;
dev_callback = callback ;
}
void GScan439Android : : DogEar_callback ( std : : function < void ( int ) > fun )
{
}
int GScan439Android : : aquire_bmpdata ( std : : vector < unsigned char > & bmpdata )
{
FileTools : : writelog ( log_lv : : log_DEBUG , " aquire_bmpdata start " ) ;
StopWatch sw ;
while ( true )
{
if ( m_pImages - > empty ( ) ) {
DoEvents ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 10 ) ) ;
if ( sw . elapsed_s ( ) > 30.00 )
{
if ( m_usbthread . get ( ) & & m_usbthread - > joinable ( ) ) {
m_status = DEV_STOP ;
m_usbthread - > join ( ) ;
m_usbthread . reset ( ) ;
}
Stop_scan ( ) ; //ֹͣɨ<D6B9> <C9A8>
ResetScanner ( ) ;
auto rollernew = Get_Roller_num ( ) ;
set_scannum ( abs ( rollernew - roller_num ) ) ;
FileTools : : writelog ( log_lv : : log_DEBUG , " aquire_bmpdata timeout " ) ;
return HARDWARE_ERROR ;
}
if ( ! is_scan ( ) ) {
auto rollernew = Get_Roller_num ( ) ;
set_scannum ( abs ( rollernew - roller_num ) ) ;
FileTools : : writelog ( log_lv : : log_DEBUG , " aquire_bmpdata stop " ) ;
if ( m_status = = DEV_WRONG ) {
return get_ErrorCode ( ) ;
}
return - 1 ;
}
}
else {
if ( m_pImages - > valid ( ) ) {
bmpdata = * ( m_pImages - > popBmpdata ( ) ) ;
UpdateScanInfo ( get_imgnReaded ( ) , countNTransfered ( ) ) ;
FileTools : : writelog ( log_lv : : log_DEBUG , " aquire_bmpdata quit " ) ;
return 0 ;
}
DoEvents ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 2 ) ) ;
}
}
}
BOOL GScan439Android : : IsConnected ( )
{
return m_usb . get ( ) & & m_usb - > is_connected ( ) ;
}
std : : string GScan439Android : : GetFWVersion ( )
{
static std : : string fw ; // = "12312312";
if ( m_usb . get ( ) & & m_usb - > is_connected ( ) & & fw . empty ( ) )
{
write_reg ( m_usb , SR_GET_FWVERSION , 0 ) ;
fw . resize ( 512 ) ;
m_usb - > read_bulk ( & fw [ 0 ] , 512 ) ;
//read_data(&fw[0], fw.length(), 100);
}
return fw ;
}
std : : string GScan439Android : : GetSerialNum ( )
{
static std : : string sn ; // = "12333123123123";
if ( m_usb . get ( ) & & m_usb - > is_connected ( ) & & sn . empty ( ) )
{
write_reg ( m_usb , SR_GET_SERIALNUM , 0 ) ;
sn . resize ( 512 ) ;
m_usb - > read_bulk ( & sn [ 0 ] , 512 ) ;
//read_data(&sn[0], sn.length(), 100);
}
return sn ;
}
std : : string GScan439Android : : GetMacAdder ( )
{
return std : : string ( ) ;
}
std : : uint32_t GScan439Android : : GetMotorFPGA ( )
{
return std : : uint32_t ( ) ;
}
std : : uint32_t GScan439Android : : GetScanFPGA ( )
{
return std : : uint32_t ( ) ;
}
bool GScan439Android : : is_scan ( )
{
return m_status = = DEV_ISRUNNING | | ( m_imagedata . Size ( ) > 0 ) ;
}
BOOL GScan439Android : : Get_Scanner_PaperOn ( )
{
return read_reg ( m_usb , SR_GET_PAPERON ) ;
}
int GScan439Android : : Get_Roller_num ( )
{
return read_reg ( m_usb , SR_GET_ROLLER_NUM ) ;
}
void GScan439Android : : config_params ( GScanCap & param )
{
m_param = param ;
HGScanConfig cfg ;
cfg . value = 0 ;
PaperStatus ps = { param . papertype , param . paperAlign } ;
cfg . g200params . paper = SupPaperTyps . count ( ps ) > 0 ? SupPaperTyps [ ps ] : 0 ;
2022-11-15 03:55:44 +00:00
if ( param . filter ! = 3 | | param . enhance_color ! = 0 | | param . hsvcorrect | | param . hsvFilter ! = 0 | | param . fadeback ! = 0 )
2022-08-10 03:10:20 +00:00
cfg . g200params . color = 1 ; //color
else
{
cfg . g200params . color = SupPixelTypes . count ( param . pixtype ) > 0 ? SupPixelTypes [ param . pixtype ] : 2 ;
}
cfg . g200params . dpi = param . resolution_dst > = 300 ? 2 : 1 ; // SupResolutions.count(param.resolution_native) > 0 ? SupResolutions[param.resolution_native] : 1;
param . resolution_native = param . resolution_dst > = 300 ? 300 : 200 ;
cfg . g200params . double_feed_enbale = ( unsigned int ) param . hardwarecaps . en_doublefeed ;
//cfg.g200params.stable_enbale = 0;
cfg . g200params . stable_enbale = ( unsigned int ) param . hardwarecaps . en_stapledetect ;
cfg . g200params . screw_detect_enable = ( unsigned int ) param . hardwarecaps . en_skrewdetect ;
cfg . g200params . screw_detect_level = ( unsigned int ) cfg . g200params . screw_detect_enable ? secrewMaps [ param . hardwarecaps . skrewdetectlevel ] : 0 ;
cfg . g200params . enable_sizecheck = param . en_sizecheck = = 1 ? 1 : 0 ;
write_reg ( m_usb , SR_CONFIG_SCAN_PARAM , cfg . value ) ;
m_pImages - > setparam ( param ) ;
}
void GScan439Android : : Scanner_StartScan ( UINT16 count )
{
error_index = 0 ;
roller_num = read_reg ( m_usb , SR_GET_ROLLER_NUM ) ;
Set_ErrorCode ( 0 ) ;
getimgnum = 0 ;
aquirenum = 0 ;
imagecount = 0 ;
reset ( ) ;
m_status = DEV_ISRUNNING ;
//if (read_reg(m_usb, SR_GET_SLEEP_STAUTUS) != 1)
//{
// m_status = DEV_WRONG;
// Set_ErrorCode(SLEEPING);
// scanflag = false;
// return;
//}
if ( ! Get_Scanner_PaperOn ( ) )
{
m_status = DEV_WRONG ;
Set_ErrorCode ( NO_FEED ) ;
scanflag = false ;
return ;
}
int state = read_reg ( m_usb , SR_GET_ANDROID_STATE ) ;
2023-03-13 08:53:10 +00:00
if ( state = = 5 )
{
if ( read_reg ( m_usb , SR_GET_LOCK_STATES ) ) {
std : : string keys ;
//m_token = "1AFE734C123F5FFCAD1113AD99A99011";
if ( m_token . length ( ) ! = 32 )
{
if ( m_token . length ( ) > 32 )
{
keys = m_token . substr ( 0 , 32 ) ;
}
else
{
auto fillstr = [ ] ( std : : string str ) - > std : : string {
for ( int i = 0 ; i < 32 - str . length ( ) ; )
str + = " 0 " ;
return str . c_str ( ) ;
} ;
keys = fillstr ( m_token ) ;
}
}
else
keys = m_token ;
//keys = m_token;
std : : uint8_t key [ CryptoPP : : AES : : DEFAULT_KEYLENGTH ] = { 0 } ;
for ( int i = 0 ; i < 16 ; i + + )
{
key [ i ] = _strtoi64 ( keys . substr ( i * 2 , 2 ) . c_str ( ) , nullptr , 16 ) ;
}
std : : string plain = GetSerialNum ( ) ;
plain . resize ( 14 ) ;
std : : string cipher ;
std : : string encoded ;
CryptoPP : : ECB_Mode < CryptoPP : : AES > : : Encryption encode ;
encode . SetKey ( key , 16 ) ;
//CryptoPP::StringSource(plain, true, new CryptoPP::StreamTransformationFilter(encode, new CryptoPP::StringSink(cipher), CryptoPP::BlockPaddingSchemeDef::W3C_PADDING));
//encoded.clear();
//CryptoPP::StringSource(cipher, true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(encoded)));
CryptoPP : : StringSink * str_cip = new CryptoPP : : StringSink ( cipher ) ;
CryptoPP : : StreamTransformationFilter * ecb_filter = new CryptoPP : : StreamTransformationFilter ( encode , str_cip , CryptoPP : : BlockPaddingSchemeDef : : W3C_PADDING ) ;
CryptoPP : : StringSource * source_plain = new CryptoPP : : StringSource ( plain , true , ecb_filter ) ;
encoded . clear ( ) ;
CryptoPP : : StringSink * str_encode = new CryptoPP : : StringSink ( encoded ) ;
CryptoPP : : HexEncoder * hex_encode = new CryptoPP : : HexEncoder ( str_encode ) ;
CryptoPP : : StringSource * source_cipher = new CryptoPP : : StringSource ( cipher , true , hex_encode ) ;
free ( str_cip ) ;
free ( ecb_filter ) ;
free ( source_plain ) ;
free ( str_encode ) ;
free ( hex_encode ) ;
free ( source_cipher ) ;
write_reg ( m_usb , SR_DECODE_TOKEN , encoded . length ( ) ) ;
m_usb - > write_bulk ( & encoded [ 0 ] , encoded . length ( ) ) ;
m_token = " null " ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1000 ) ) ;
}
}
state = read_reg ( m_usb , SR_GET_ANDROID_STATE ) ;
2022-08-10 03:10:20 +00:00
if ( state ! = 0 )
{
if ( state = = 1 ) Set_ErrorCode ( OPEN_COVER ) ;
else if ( state = = 2 ) Set_ErrorCode ( PAPER_JAM ) ;
else if ( state = = 3 ) Set_ErrorCode ( NO_FEED ) ;
2023-03-13 08:53:10 +00:00
else if ( state = = 5 ) Set_ErrorCode ( DEVICE_LOCKED ) ;
2022-08-10 03:10:20 +00:00
else Set_ErrorCode ( HARDWARE_ERROR ) ;
scanflag = false ;
m_status = DEV_WRONG ;
return ;
}
write_reg ( m_usb , 0x1000 , m_param . is_duplex ? m_param . scannum / 2 : m_param . scannum ) ;
scanner_control ( m_usb , SC_START ) ;
if ( ! m_usbthread . get ( ) ) {
b_usbthread = true ;
m_usbthread . reset ( new thread ( & GScan439Android : : usbmainloop , this ) ) ;
}
m_pImages - > setscanflags ( true ) ;
m_pImages - > run ( ) ;
}
void GScan439Android : : Stop_scan ( )
{
scanner_control ( m_usb , SC_STOP ) ;
if ( ( m_status = = DEV_WRONG ) | | ( m_status = = DEV_STOP ) )
return ;
m_status = DEV_STOP ;
}
int GScan439Android : : notifyscan ( )
{
return 1 ;
}
void GScan439Android : : ResetScanner ( )
{
}
bool GScan439Android : : Get_IsImageQueueEmpty ( )
{
return m_pImages - > empty ( ) & & m_status = = DEV_STOP ;
}
void GScan439Android : : reset ( )
{
m_status = DEV_STOP ;
m_pImages - > clear ( ) ;
//scanner_control(m_usb, SC_INIT);
}
void GScan439Android : : clear_hwerror ( )
{
//scanner_control(m_usb, SC_INIT);
}
UINT32 GScan439Android : : get_ErrorCode ( )
{
return Error_Code ;
}
void GScan439Android : : Set_ErrorCode ( UINT32 value )
{
Error_Code = value ;
}
int GScan439Android : : get_scanned_num ( )
{
return 0 ;
}
void GScan439Android : : set_sleep_time ( int mode )
{
}
bool GScan439Android : : set_scannercode ( std : : string str )
{
return false ;
}
std : : string GScan439Android : : get_scannercode ( )
{
return std : : string ( ) ;
}
void GScan439Android : : usbhotplug_callback ( bool isconnect , void * userdata )
{
GScan439Android * This = ( GScan439Android * ) userdata ;
This - > usbhotplug ( isconnect ) ;
}
void GScan439Android : : usbhotplug ( bool isleft )
{
FileTools : : writelog ( log_ERROR , " enable usb callback " ) ;
if ( isleft ) {
m_status = DEV_WRONG ;
Error_Code = USB_DISCONNECTED ;
m_pImages - > setscanflags ( false ) ;
scanflag = false ;
if ( m_usb . get ( ) )
m_usb . reset ( ) ;
if ( huagods )
dev_callback ( USB_DISCONNECTED , huagods ) ;
}
}
int GScan439Android : : read_data ( void * data , int length , int timeout )
{
if ( ! m_usb . get ( ) & & ! m_usb - > is_connected ( ) )
{
FileTools : : writelog ( log_INFO , " if (!m_usb.get() && !m_usb->is_connected()) " ) ;
return 0 ;
}
timeout = std : : max ( 1000 , timeout ) ;
int readed = 0 ;
int reading = 0 ;
const int buffer_size = 512 * 1024 ;
StopWatch sw ;
FileTools : : writelog ( log_INFO , " read_data timeout = " + to_string ( timeout ) ) ;
while ( readed < length ) {
if ( sw . elapsed_ms ( ) < timeout & & m_usb . get ( ) )
{
reading = std : : max ( 0 , std : : min ( length - readed , buffer_size ) ) ;
reading = m_usb - > read_bulk ( ( unsigned char * ) data + readed , reading ) ;
if ( reading > 0 ) {
readed + = reading ;
sw . reset ( ) ;
}
}
else
{
FileTools : : writelog ( log_INFO , " read usb image data time out ,time = " + std : : to_string ( sw . elapsed_ms ( ) ) ) ;
break ;
}
}
return readed ;
}
void GScan439Android : : usbmainloop ( )
{
unsigned char buff [ 32 ] ;
while ( b_usbthread )
{
if ( ! m_usb . get ( ) | | ! m_usb - > is_connected ( ) )
{
this_thread : : sleep_for ( chrono : : milliseconds ( 20 ) ) ;
continue ;
}
memset ( buff , 0 , sizeof ( buff ) ) ;
auto length = m_usb - > read_int ( buff , sizeof ( buff ) ) ;
if ( ( ( length ) = = sizeof ( buff ) ) ) //|| im_dev_count()
{
HGEIntInfo info = * ( HGEIntInfo * ) & buff ;
if ( codeconvter ( info ) > 0 & & get_ErrorCode ( ) = = 0 )
{
Set_ErrorCode ( codeconvter ( info ) ) ;
}
if ( codeconvter ( info ) = = - 1 )
{
m_readimgpool . enqueue ( [ this ] {
StopWatch stoptime ;
while ( stoptime . elapsed_s ( ) < 3 ) {
if ( read_reg ( m_usb , SR_IM_COUNT ) > 0 )
{
readimg ( ) ;
stoptime . reset ( ) ;
}
this_thread : : sleep_for ( chrono : : milliseconds ( 200 ) ) ;
}
m_status = get_ErrorCode ( ) = = 0 ? DEV_STOP : DEV_WRONG ;
m_pImages - > setscanflags ( false ) ; } ) ;
}
switch ( info . From )
{
case IMG :
m_readimgpool . enqueue ( [ this ] {
if ( read_reg ( m_usb , SR_IM_COUNT ) > 0 )
readimg ( ) ;
} ) ;
break ;
case MtBoard :
FileTools : : writelog ( log_ERROR , " Got MotorBoard error code = " + to_string ( info . Code ) ) ;
break ;
case FPGA :
FileTools : : writelog ( log_ERROR , " Got FPGA Error code = " + to_string ( info . Code ) ) ;
break ;
case V4L2 :
FileTools : : writelog ( log_ERROR , " Got V4L2 Error code = " + to_string ( info . Code ) ) ;
scanner_control ( m_usb , SC_STOP ) ;
break ;
case STOPSCAN :
FileTools : : writelog ( log_INFO , " StopScan " ) ;
break ;
default :
FileTools : : writelog ( log_ERROR , " Got Unkown error code ! From = " + to_string ( info . From ) + " Code = " + to_string ( info . Code ) ) ;
break ;
}
//this_thread::sleep_for(chrono::microseconds(10));
}
}
}
void GScan439Android : : readimg ( )
{
if ( read_reg ( m_usb , SR_IM_TXING ) )
{
FileTools : : writelog ( log_ERROR , " Read image TXING " ) ;
return ;
}
if ( read_reg ( m_usb , SR_IM_COUNT ) > 0 & & getStatus ( ) )
{
unsigned int len = read_reg ( m_usb , SR_IM_FRONT_SIZE ) ;
if ( len > 0 )
{
write_reg ( m_usb , SR_IM_TX , 1 ) ;
im_data - > resize ( len ) ;
static int indeximg = 0 ;
auto nreaded = tranxferimg ( len , im_data ) ;
if ( nreaded = = len )
{
m_pImages - > pushMat ( std : : shared_ptr < IDecode > ( new G400Decode ( im_data ) ) ) ;
this_thread : : sleep_for ( chrono : : milliseconds ( 10 ) ) ;
write_reg ( m_usb , SR_IM_POP , 1 ) ;
FileTools : : writelog ( log_ERROR , " Enqueue image " + to_string ( + + indeximg ) + " size " + to_string ( nreaded ) ) ;
UpdateScanInfo ( countNReaded ( ) , get_imgTransfered ( ) ) ;
}
else
{
FileTools : : writelog ( log_ERROR , " error :read image data len error " ) ;
}
}
else
FileTools : : writelog ( log_ERROR , " error :Get front image data len ZERO " ) ;
}
else
FileTools : : writelog ( log_ERROR , " image queue empty or not scanning " ) ;
}
int GScan439Android : : tranxferimg ( unsigned int datalen , std : : shared_ptr < std : : vector < char > > data )
{
unsigned int timeout = 3000 ;
unsigned int readed = 0 ;
unsigned int reading = 0 ;
const int buffer_size = 512 * 1024 ;
StopWatch sw ;
while ( readed < datalen )
{
if ( sw . elapsed_ms ( ) < timeout & & m_usb . get ( ) )
{
reading = m_max ( 0 , m_min ( datalen - readed , buffer_size ) ) ;
reading = m_usb - > read_bulk ( ( unsigned char * ) data - > data ( ) + readed , reading ) ;
if ( reading > 0 )
{
readed + = reading ;
sw . reset ( ) ;
}
else
FileTools : : writelog ( log_ERROR , " Read Image size zero " ) ;
}
else
{
FileTools : : writelog ( log_ERROR , " Read Image timeout " ) ;
break ;
}
}
return readed ;
}
int GScan439Android : : codeconvter ( HGEIntInfo code )
{
if ( code . From = = HGType : : FPGA )
{
switch ( code . Code )
{
default :
break ;
}
}
if ( code . From = = HGType : : MtBoard )
{
switch ( code . Code )
{
case 0x00002 :
return NO_FEED ;
case 0x00004 :
return OPEN_COVER ;
case 0x00008 :
return FEED_IN_ERROR ;
case 0x00010 :
return PAPER_JAM ;
case 0x00020 :
return DETECT_DOUBLE_FEED ;
case 0x00040 :
return DETECT_STAPLE ;
case 0x00080 :
return PAPER_SKEW ;
case 0x10000 :
return AQUIRE_IMAGE_TIMEOUT ;
case 0x20000 :
return SIZE_ERROR ;
case 0x40000 :
return PAPER_HOLE ;
case 0x80000 :
return MLTOP_TIMEOUT ;
default :
break ;
}
}
if ( code . From = = HGType : : V4L2 )
{
switch ( code . Code )
{
case 0 :
return V4L2_AQULRE_ERROR ;
case 1 :
return V4L2_IMAGE_EMPTY ;
default :
break ;
}
}
if ( code . From = = HGType : : STOPSCAN )
{
switch ( code . Code )
{
case 0 :
return - 1 ;
case 1 :
if ( m_status = = DEV_ISRUNNING )
m_status = DEV_STOP ;
return 0 ;
default :
break ;
}
}
return 0 ;
}
bool GScan439Android : : getStatus ( )
{
return 1 ;
int val = read_reg ( m_usb , SR_STATUS ) & 0x3 ;
bool ret = ( val > 0 ) & & ( val < 4 ) ;
return ret ;
}