twain3.0/huagao/Device/GScan439Android.cpp

606 lines
14 KiB
C++
Raw Normal View History

#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||param.hsvFilter!=0||param.fadeback!=0)
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;
}