mirror of http://192.168.1.51:8099/lmh188/twain3.0
606 lines
14 KiB
C++
606 lines
14 KiB
C++
#include "GScan439Android.h"
|
||
#include "IUsb.h"
|
||
#include "UsbScanEx.h"
|
||
#include <iostream>
|
||
|
||
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;
|
||
if (param.filter != 3 || param.enhance_color != 0 || param.hsvcorrect)
|
||
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);
|
||
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);
|
||
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;
|
||
}
|