diff --git a/3rdparty/cyusb/inc/CyAPI.h b/3rdparty/cyusb/inc/CyAPI.h new file mode 100644 index 00000000..3f7959a5 --- /dev/null +++ b/3rdparty/cyusb/inc/CyAPI.h @@ -0,0 +1,462 @@ +//______________________________________________________________________________ +// +// Copyright (c) Cypress Semiconductor, 2003 +// All rights reserved. +// +//______________________________________________________________________________ + +#ifndef CyUSBH +#define CyUSBH + +#ifndef __USB200_H__ +#define __USB200_H__ +#include + +#pragma pack(push,1) /// + +typedef struct _USB_DEVICE_DESCRIPTOR { //设备描述符 + UCHAR bLength; //长度 + UCHAR bDescriptorType; //描述符类型 + USHORT bcdUSB; //USB + UCHAR bDeviceClass; //设备类 + UCHAR bDeviceSubClass; //设备派生类 + UCHAR bDeviceProtocol; //设备协议 + UCHAR bMaxPacketSize0; //最大数据包尺寸 + USHORT idVendor; //厂商ID + USHORT idProduct; //产品ID + USHORT bcdDevice; //设备 + UCHAR iManufacturer; //制造商 + UCHAR iProduct; //产品 + UCHAR iSerialNumber; //序列号 + UCHAR bNumConfigurations;//配置 +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct _USB_ENDPOINT_DESCRIPTOR { //端点描述符 + UCHAR bLength; //长度 + UCHAR bDescriptorType; //描述符类型 + UCHAR bEndpointAddress; //端点地址 + UCHAR bmAttributes; //端点属性 + USHORT wMaxPacketSize; //最大数据包尺寸 + UCHAR bInterval; //间隔 +} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR { //配置描述符 + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +typedef struct _USB_INTERFACE_DESCRIPTOR { //接口描述符 + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; +} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; + +typedef struct _USB_STRING_DESCRIPTOR { //字符串描述符 + UCHAR bLength; + UCHAR bDescriptorType; + WCHAR bString[1]; +} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR; + +typedef struct _USB_COMMON_DESCRIPTOR { //USB串口描述符 + UCHAR bLength; + UCHAR bDescriptorType; +} USB_COMMON_DESCRIPTOR, *PUSB_COMMON_DESCRIPTOR; +#pragma pack(pop) +#endif +//______________________________________________________________________________ + +class CCyIsoPktInfo { //包信息 +public: + LONG Status; //包状态 + LONG Length; //包长度 +}; + +//______________________________________________________________________________ + + +// {AE18AA60-7F6A-11d4-97DD-00010229B959} +static GUID CYUSBDRV_GUID = {0xae18aa60, 0x7f6a, 0x11d4, 0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59}; + +typedef enum {TGT_DEVICE, TGT_INTFC, TGT_ENDPT, TGT_OTHER } CTL_XFER_TGT_TYPE; +typedef enum {REQ_STD, REQ_CLASS, REQ_VENDOR } CTL_XFER_REQ_TYPE; +typedef enum {DIR_TO_DEVICE, DIR_FROM_DEVICE } CTL_XFER_DIR_TYPE; +typedef enum {XMODE_BUFFERED, XMODE_DIRECT } XFER_MODE_TYPE; + +const int MAX_ENDPTS = 16; +const int MAX_INTERFACES = 8; +const int USB_STRING_MAXLEN = 256; + + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyEndPoint ABSTRACT Class +// +//////////////////////////////////////////////////////////////////////////////// +class CCyUSBEndPoint +{ +protected: + bool WaitForIO(OVERLAPPED *ovLapStatus); + + virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); //直接传输模式 + virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); //缓冲传输模式 + + +public: + + CCyUSBEndPoint(void); + CCyUSBEndPoint(CCyUSBEndPoint& ept); + CCyUSBEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + HANDLE hDevice; + + // The fields of an EndPoint Descriptor + UCHAR DscLen; + UCHAR DscType; + UCHAR Address; + UCHAR Attributes; + USHORT MaxPktSize; + USHORT PktsPerFrame; + UCHAR Interval; + + // Other fields + ULONG TimeOut; + ULONG UsbdStatus; + ULONG NtStatus; + + DWORD bytesWritten; + DWORD LastError; + bool bIn; + + XFER_MODE_TYPE XferMode; + + bool XferData(PUCHAR buf, LONG &len, CCyIsoPktInfo* pktInfos = NULL); + bool XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos, bool pktMode); + virtual PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov) = 0; + virtual bool FinishDataXfer(PUCHAR buf, LONG &len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos = NULL); + bool WaitForXfer(OVERLAPPED *ov, ULONG tOut); + ULONG GetXferSize(void); + void SetXferSize(ULONG xfer); + + bool Reset(void); + bool Abort(void); + +private: + + + +}; + + +//////////////////////////////////////////////////////////////////////////////// +// +// The Control Endpoint Class +// +//////////////////////////////////////////////////////////////////////////////// +class CCyControlEndPoint : public CCyUSBEndPoint +{ +private: + +public: + CCyControlEndPoint(void); + CCyControlEndPoint(CCyControlEndPoint& ept); + CCyControlEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + CTL_XFER_TGT_TYPE Target; + CTL_XFER_REQ_TYPE ReqType; + CTL_XFER_DIR_TYPE Direction; + + UCHAR ReqCode; + WORD Value; + WORD Index; + + bool Read(PUCHAR buf, LONG &len); + bool Write(PUCHAR buf, LONG &len); + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The Isoc Endpoint Class +// +//////////////////////////////////////////////////////////////////////////////// +class CCyIsocEndPoint : public CCyUSBEndPoint +{ + +protected: + virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + +public: + CCyIsocEndPoint(void); + CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); + CCyIsoPktInfo* CreatePktInfos(LONG bufLen, int &packets); + +}; + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The Bulk Endpoint Class +// +//////////////////////////////////////////////////////////////////////////////// +class CCyBulkEndPoint : public CCyUSBEndPoint +{ +public: + CCyBulkEndPoint(void); + CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The Interrupt Endpoint Class +// +//////////////////////////////////////////////////////////////////////////////// +class CCyInterruptEndPoint : public CCyUSBEndPoint +{ +public: + CCyInterruptEndPoint(void); + CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The Interface Class +// +//////////////////////////////////////////////////////////////////////////////// + +class CCyUSBInterface +{ +private: +protected: +public: + CCyUSBEndPoint *EndPoints[MAX_ENDPTS]; // Holds pointers to all the interface's endpoints, plus a pointer to the Control endpoint zero + + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; // Not counting the control endpoint + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; + + UCHAR bAltSettings; + USHORT wTotalLength; // Needed in case Intfc has additional (non-endpt) descriptors + + + CCyUSBInterface(HANDLE h, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor); + CCyUSBInterface(CCyUSBInterface& ifc); // Copy Constructor + ~CCyUSBInterface(void); + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// The Config Class +// +//////////////////////////////////////////////////////////////////////////////// + +class CCyUSBConfig +{ +private: + +protected: +public: + CCyUSBInterface *Interfaces[MAX_INTERFACES]; + + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; + + UCHAR AltInterfaces; + + + CCyUSBConfig(void); + CCyUSBConfig(CCyUSBConfig& cfg); // Copy Constructor + CCyUSBConfig(HANDLE h, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr); + ~CCyUSBConfig(void); + + + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// The USB Device Class - This is the main class that contains members of all the +// other classes. +// +// To use the library, create an instance of this Class and call it's Open method +// +//////////////////////////////////////////////////////////////////////////////// + +class CCyUSBDevice +{ +// The public members are accessible (i.e. corruptible) by the user of the library +// Algorithms of the class don't rely on any public members. Instead, they use the +// private members of the class for their calculations. + +public: + + CCyUSBDevice(HANDLE hnd = NULL, GUID guid = CYUSBDRV_GUID, BOOL bOpen = true); + ~CCyUSBDevice(void); + + CCyUSBEndPoint **EndPoints; // Shortcut to USBCfgs[CfgNum]->Interfaces[IntfcIndex]->Endpoints + CCyUSBEndPoint *EndPointOf(UCHAR addr); + + CCyControlEndPoint *ControlEndPt; + CCyIsocEndPoint *IsocInEndPt; + CCyIsocEndPoint *IsocOutEndPt; + CCyBulkEndPoint *BulkInEndPt; + CCyBulkEndPoint *BulkOutEndPt; + CCyInterruptEndPoint *InterruptInEndPt; + CCyInterruptEndPoint *InterruptOutEndPt; + + USHORT StrLangID; + ULONG UsbdStatus; + ULONG NtStatus; + ULONG DriverVersion; + ULONG USBDIVersion; + char DeviceName[USB_STRING_MAXLEN]; + char FriendlyName[USB_STRING_MAXLEN]; + wchar_t Manufacturer[USB_STRING_MAXLEN]; + wchar_t Product[USB_STRING_MAXLEN]; + wchar_t SerialNumber[USB_STRING_MAXLEN]; + + CHAR DevPath[USB_STRING_MAXLEN]; + + USHORT BcdUSB; + USHORT VendorID; + USHORT ProductID; + UCHAR USBAddress; + UCHAR DevClass; + UCHAR DevSubClass; + UCHAR DevProtocol; + UCHAR MaxPacketSize; + USHORT BcdDevice; + + UCHAR ConfigValue; + UCHAR ConfigAttrib; + UCHAR MaxPower; + + UCHAR IntfcClass; + UCHAR IntfcSubClass; + UCHAR IntfcProtocol; + bool bHighSpeed; + + DWORD BytesXfered; + + + UCHAR DeviceCount(void); + UCHAR ConfigCount(void); + UCHAR IntfcCount(void); + UCHAR AltIntfcCount(void); + UCHAR EndPointCount(void); + + UCHAR Config(void) { return CfgNum; } // Normally 0 + void SetConfig(UCHAR cfg); + + UCHAR Interface(void) { return IntfcNum; } // Usually 0 + // No SetInterface method since only 1 intfc per device (per Windows) + + UCHAR AltIntfc(void); + bool SetAltIntfc(UCHAR alt); + + GUID DriverGUID(void) { return DrvGuid; } + HANDLE DeviceHandle(void) { return hDevice; } + void UsbdStatusString(ULONG stat, PCHAR s); + bool CreateHandle(UCHAR dev); + void DestroyHandle(); + + bool Open(UCHAR dev); + void Close(void); + bool Reset(void); + bool ReConnect(void); + bool Suspend(void); + bool Resume(void); + bool IsOpen(void) { return (hDevice != INVALID_HANDLE_VALUE); } + + UCHAR PowerState(void); + + + void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR descr); + void GetConfigDescriptor(PUSB_CONFIGURATION_DESCRIPTOR descr); + void GetIntfcDescriptor(PUSB_INTERFACE_DESCRIPTOR descr); + CCyUSBConfig GetUSBConfig(int index); + + +private: + + USB_DEVICE_DESCRIPTOR USBDeviceDescriptor; + PUSB_CONFIGURATION_DESCRIPTOR USBConfigDescriptors[2]; + + CCyUSBConfig *USBCfgs[2]; + + HANDLE hWnd; + HANDLE hDevice; + HANDLE hDevNotification; + HANDLE hHndNotification; + + GUID DrvGuid; + + UCHAR Devices; + UCHAR Interfaces; + UCHAR AltInterfaces; + UCHAR Configs; + + UCHAR DevNum; + UCHAR CfgNum; + UCHAR IntfcNum; // The current selected interface's bInterfaceNumber + UCHAR IntfcIndex; // The entry in the Config's interfaces table matching to IntfcNum and AltSetting + + void GetDevDescriptor(void); + void GetCfgDescriptor(int descIndex); + void GetString(wchar_t *s, UCHAR sIndex); + void SetStringDescrLanguage(void); + void SetAltIntfcParams(UCHAR alt); + bool IoControl(ULONG cmd, PUCHAR buf, ULONG len); + + void SetEndPointPtrs(void); + void GetDeviceName(void); + void GetFriendlyName(void); + void GetDriverVer(void); + void GetUSBDIVer(void); + void GetSpeed(void); + void GetUSBAddress(void); + //void CloseEndPtHandles(void); + + bool RegisterForPnpEvents(HANDLE h); +}; + +//--------------------------------------------------------------------------- +#endif diff --git a/3rdparty/cyusb/lib/windows/x64/CyAPI.lib b/3rdparty/cyusb/lib/windows/x64/CyAPI.lib new file mode 100644 index 00000000..47939865 Binary files /dev/null and b/3rdparty/cyusb/lib/windows/x64/CyAPI.lib differ diff --git a/3rdparty/cyusb/lib/windows/x86/CyAPI.lib b/3rdparty/cyusb/lib/windows/x86/CyAPI.lib new file mode 100644 index 00000000..a888ef76 Binary files /dev/null and b/3rdparty/cyusb/lib/windows/x86/CyAPI.lib differ diff --git a/huagao/Device/CyUsbEx.cpp b/huagao/Device/CyUsbEx.cpp new file mode 100644 index 00000000..a4e819a0 --- /dev/null +++ b/huagao/Device/CyUsbEx.cpp @@ -0,0 +1,128 @@ +#include "CyUsbEx.h" +#include "CyAPI.h" + +CyUsbEx::CyUsbEx(int index) +{ + m_index = index; + m_timeout = 100; +} + +bool CyUsbEx::open() +{ + if (is_open()) + return true; + + m_usb.reset(new CCyUSBDevice()); + m_usb->Open(m_index); + m_usb->Reset(); + if (m_usb->IsOpen()) + { + if (m_usb->BulkOutEndPt) + m_usb->BulkOutEndPt->TimeOut = m_timeout; + + if (m_usb->BulkInEndPt) + m_usb->BulkInEndPt->TimeOut = m_timeout; + + if (m_usb->InterruptInEndPt) + m_usb->InterruptInEndPt->TimeOut = 400; + } + + return is_open(); +} + +bool CyUsbEx::close() +{ + if (is_open()) + { + m_usb->Close(); + m_usb.reset(); + } + + return true; +} + +bool CyUsbEx::is_open() +{ + if (m_usb.get() != NULL) + return m_usb->IsOpen(); + + return false; +} + +bool CyUsbEx::is_connected() +{ + return is_open(); +} + +void CyUsbEx::set_timeout(int timeout) +{ + m_timeout = timeout; +} + +int CyUsbEx::read_bulk(void* data, int len) +{ + LONG llen = len; + m_usb->BulkInEndPt->XferData((UCHAR*)data, llen); + return llen; +} + + + +int CyUsbEx::write_bulk(void* data, int len) +{ + LONG llen = len; + m_usb->BulkOutEndPt->XferData((UCHAR*)data, llen); + return llen; +} + +int CyUsbEx::read_int(void* data, int len) +{ + LONG llen = len; + m_usb->InterruptInEndPt->XferData((UCHAR*)data, llen); + return llen; +} + +int CyUsbEx::control_msg(int rtype, int req, int value, int index, int len, void* data) +{ + if (!m_usb.get() || !m_usb->ControlEndPt) + return -1; + + m_usb->ControlEndPt->Index = index; + m_usb->ControlEndPt->Value = value; + m_usb->ControlEndPt->ReqType = (CTL_XFER_REQ_TYPE)((rtype >> 5) & 0x03); + m_usb->ControlEndPt->Direction = (CTL_XFER_DIR_TYPE)(rtype >> 7);// + m_usb->ControlEndPt->Target = (CTL_XFER_TGT_TYPE)(rtype & 0x3); + m_usb->ControlEndPt->ReqCode = req; + LONG llen = len; + m_usb->ControlEndPt->XferData((UCHAR*)data, llen); + return llen; +} + +void CyUsbEx::set_usbhotplug_callback(usbhotplug_callback callback, void* userdata) +{ + return; +} + +std::list> CyUsbList::find_all() +{ + std::list> usblists; + CCyUSBDevice usbDevice; + for (int i = 0; i < usbDevice.DeviceCount(); i++) + usblists.push_back(std::shared_ptr(new CyUsbEx(i))); + return usblists; +} + +std::list> CyUsbList::find_vid_pid(int vid, int pid) +{ + std::list> usblists; + CCyUSBDevice usbDevice; + for (int i = 0; i < usbDevice.DeviceCount(); i++) { + usbDevice.Open(i); + if (usbDevice.IsOpen() && (usbDevice.VendorID == vid) && (usbDevice.ProductID == pid)) { + usblists.push_back(std::shared_ptr(new CyUsbEx(i))); + usbDevice.Close(); + } + } + return usblists; +} + diff --git a/huagao/Device/CyUsbEx.h b/huagao/Device/CyUsbEx.h new file mode 100644 index 00000000..b775fbb9 --- /dev/null +++ b/huagao/Device/CyUsbEx.h @@ -0,0 +1,37 @@ +#pragma once +#include "IUsb.h" +#include +#include + + + +class CCyUSBDevice; + +class CyUsbList { +public: + static std::list> find_all(); + static std::list> find_vid_pid(int vid, int pid); +}; + +class CyUsbEx : + public IUsb +{ +public: + CyUsbEx(int index); + // 通过 IUsb 继承 + virtual bool open() override; + virtual bool close() override; + virtual bool is_open() override; + virtual bool is_connected() override; + virtual void set_timeout(int timeout) override; + virtual int read_bulk(void* data, int len) override; + virtual int write_bulk(void* data, int len) override; + virtual int read_int(void* data, int len) override; + virtual int control_msg(int rtype, int req, int value, int index, int len, void* data) override; + virtual void set_usbhotplug_callback(usbhotplug_callback callback = NULL, void* userdata = NULL) override; + +private: + std::shared_ptr m_usb; + int m_index; + int m_timeout; +}; diff --git a/huagao/Device/GScan.h b/huagao/Device/GScan.h index c5179481..26ac153c 100644 --- a/huagao/Device/GScan.h +++ b/huagao/Device/GScan.h @@ -72,15 +72,19 @@ typedef enum tagUsbSupported { // PC繁忙或出错 PC_SCAN_BUSY_or_ERROR = 73, //摺角 - DOG_EAR=74, + DOG_EAR = 74, //幅面检测错误 - SIZE_ERROR=75, + SIZE_ERROR = 75, //取图超时 - AQUIRE_IMAGE_TIMEOUT=76, + AQUIRE_IMAGE_TIMEOUT = 76, //获取图片与扫描张数不匹配 - LOSE_IMAGE=77, + LOSE_IMAGE = 77, //usb读取数据错误 - USB_BULK_ERROR=78, + USB_BULK_ERROR = 78, + //v4l2取图失败 + V4L2_AQULRE_ERROR = 79, + //扫描仪内部图片丢失 + V4L2_IMAGE_EMPTY = 80, //USB 未连接 USB_DISCONNECTED = 200, //用户点击停止 @@ -109,7 +113,9 @@ static map msgs = { {UsbSupported::SIZE_ERROR,"幅面检测异常!"}, {UsbSupported::AQUIRE_IMAGE_TIMEOUT,"取图超时!"}, {UsbSupported::LOSE_IMAGE,"上传图片与扫描张数不匹配!"}, - {UsbSupported::USB_BULK_ERROR,"USB数据读取错误!"} + {UsbSupported::USB_BULK_ERROR,"USB数据读取错误!"}, + {UsbSupported::V4L2_AQULRE_ERROR,"扫描仪取图失败!"}, + {UsbSupported::V4L2_IMAGE_EMPTY,"扫描仪图像处理异常!"}, }; enum tagEventIndex diff --git a/huagao/Device/GScanO1003399.cpp b/huagao/Device/GScanO1003399.cpp new file mode 100644 index 00000000..4f094ca8 --- /dev/null +++ b/huagao/Device/GScanO1003399.cpp @@ -0,0 +1,652 @@ +#include "GScanO1003399.h" +#include "ImageProcess/ImageApplyHeaders.h" +#include "ImageMultiOutput.h" +#include "scn_config.h" +#include "PaperSize.h" +#include "GScan.h" + +static std::mutex mx_ctrl; + +static int scanner_read_reg(std::shared_ptr& usb, int addr) +{ + int val = 0; + std::lock_guard lck(mx_ctrl); + usb->control_msg(0xc0, USB_REQ_GET_DEV_REGS, addr, 0, 4, &val); + return val; +} + +static void scanner_write_reg(std::shared_ptr& usb, int addr, int val) +{ + std::lock_guard lck(mx_ctrl); + usb->control_msg(0x40, USB_REQ_SET_DEV_REGS, addr, 0, 4, &val); +} + +static void scanner_cmd(std::shared_ptr& usb, int cmd) +{ + scanner_write_reg(usb, 0, cmd); +} + + + +GScanO1003399::GScanO1003399(): + m_imgthread(1) +{ + im_data.reset(new std::vector()); + open(0, 0); + + devState = DEV_STOP; +} + +GScanO1003399::~GScanO1003399() +{ + if (m_usbthread.get() && m_usbthread->joinable()) + { + b_usbthread = false; + m_usbthread->join(); + m_usbthread.reset(); + } + if (fu_rx.valid()) + fu_rx.wait(); +} + +void GScanO1003399::open(int vid, int pid) +{ + //auto lsusb=CyUsbList::find_vid_pid(vid, pid); + //if (!lsusb.empty()) + //{ + // m_usb = *lsusb.begin(); + // m_usb->open(); + //} + if (m_usb.get()&&m_usb->is_connected()) + return; + auto lsusb = CyUsbList::find_all(); + if (!lsusb.empty()) + { + m_usb = *lsusb.begin(); + m_usb->open(); + } +} + +void GScanO1003399::regist_deviceevent_callback(deviceevent_callback callback, void* usrdata) +{ +} + +void GScanO1003399::DogEar_callback(std::function fun) +{ +} +static int aquirenum = 0; +static int getimgnum = 0; +int GScanO1003399::aquire_bmpdata(std::vector& bmpdata) +{ + StopWatch sw; + while (true) + { + if ((m_imagedata.Size() < 1)&&(!is_runing())) + { + DoEvents(); + this_thread::sleep_for(chrono::milliseconds(1)); + if (!is_runing()) + { + if (devState == DEV_WRONG) + return get_ErrorCode(); + return -1; + } + if (sw.elapsed_s() > 30.0) + { + devState = DEV_STOP; + if (fu_rx.valid()) + fu_rx.wait(); + Stop_scan(); + ResetScanner(); + return AQUIRE_IMAGE_TIMEOUT; + } + } + else + { + if ((m_imagedata.Size() > 0)) + { + FileTools::writelog(log_INFO, "aquire_bmpdata num =" + to_string(aquirenum++)); + bmpdata = *(m_imagedata.Take()); + UpdateScanInfo(get_imgnReaded(), countNTransfered()); + return 0; + } + DoEvents(); + this_thread::sleep_for(chrono::milliseconds(2)); + } + + } + +} + +BOOL GScanO1003399::IsConnected() +{ + return m_usb.get()&&m_usb->is_connected(); +} + +std::string GScanO1003399::GetFWVersion() +{ + std::string fw; + if (m_usb.get() && m_usb->is_connected()) + { + scanner_write_reg(m_usb, SR_GET_FWVERSION, 0); + fw.resize(10); + read_data(&fw[0], fw.length(), 200); + } + return fw; +} + +std::string GScanO1003399::GetSerialNum() +{ + std::string sn; + if (m_usb.get() && m_usb->is_connected()) + { + scanner_write_reg(m_usb, SR_GET_SERIALNUM, 0); + sn.resize(14); + read_data(&sn[0], sn.length(), 200); + } + return sn; +} + +std::uint32_t GScanO1003399::GetMotorFPGA() +{ + return std::uint32_t(); +} + +std::uint32_t GScanO1003399::GetScanFPGA() +{ + return std::uint32_t(); +} + +bool GScanO1003399::is_scan() +{ + //return devState==DEV_ISRUNNING; + return is_runing() || (m_imagedata.Size() > 0); +} + +BOOL GScanO1003399::Get_Scanner_PaperOn() +{ + return scanner_read_reg(m_usb, SR_PAPER_READY); +} + +int GScanO1003399::Get_Roller_num() +{ + return 0; +} + +void GScanO1003399::config_params(GScanCap& param) +{ + m_param = param; + HGScanConfig cfg; + cfg = { 0 }; +#ifdef G200 + + 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 = SupResolutions.count(param.resolution_native)>0 ? SupResolutions[param.resolution_native] : 1; + cfg.g200params.double_feed_enbale = (unsigned int)param.hardwarecaps.en_doublefeed; + 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; + cfg.g200params.unused_one = cfg.g200params.sizeerror_errorratio = 0; + param.resolution_dst >= 240.0f ? 1 : 0; + +#else + + cfg.g400params.doubleFeeded = param.hardwarecaps.en_doublefeed == 0 ? 0 : 1; + cfg.g400params.dpi = G400_DPI::G400_D200;//gcap.resolution_dst <= 200.0f ? G400_DPI::G400_D200 : (gcap.resolution_dst <= 300.0f ? G400_DPI::G400_D300 : G400_DPI::G400_D600); + cfg.g400params.enableLed = 1; + if (param.filter != 3 || param.enhance_color) + cfg.g400params.isColor = 1; + else + cfg.g400params.isColor = SupPixelTypes[param.pixtype]; + cfg.g400params.enableStable = 0;//gcap.hardwarecaps.en_stapledetect==0?0:1; + cfg.g400params.isCorrect = 1;//1 机器校正 + PaperStatus ps = { param.papertype,param.paperAlign }; + cfg.g400params.pageSize = SupPaperTyps[ps]; + CSize size; +#ifdef G300 + size = Device::PaperSize().GetPaperSize(TwSS::A4, 200.0f, gcap.paperAlign);//G300 最大支持A4幅面 +#else + size = Device::PaperSize().GetPaperSize(param.papertype, 200.0f, param.paperAlign); +#endif// G300 + cfg.g400params.dstHeight = (int)((size.cy + 200) / 100); + cfg.g400params.reversed1 = cfg.g400params.reversed2 = 0; +#endif // G200 + config_scanparam(cfg); + config_imgprocparam({0}); + GScanCap_3399 param39{ 0 }; + param39.AutoCrop_threshold = param.AutoCrop_threshold; + param39.autodescrew = param.autodescrew; + param39.automaticcolor = param.automaticcolor; + param39.automaticcolortype = param39.automaticcolortype; + param39.brightness = param.brightness; + param39.contrast = param.contrast; + param39.detachnoise = param.detachnoise; + param39.discardblank_percent = param.discardblank_percent; + param39.en_fold = param.en_fold; + param39.en_sizecheck = param.en_sizecheck; + param39.enhance_color = param.enhance_color; + param39.fillbackground = param.fillbackground; + param39.fillhole = param.fillhole; + param39.filter = param.filter; + param39.gamma = param.gamma; + param39.hardwarecaps = param.hardwarecaps; + param39.hsvcorrect = param.hsvcorrect; + param39.imageRotateDegree = param.imageRotateDegree; + param39.indent = param.indent; + param39.is_autocontrast = param.is_autocontrast; + param39.is_autocrop = param.is_autocrop; + param39.is_autodiscradblank_normal = param.is_autodiscradblank_normal; + param39.is_autodiscradblank_vince = param.is_autodiscradblank_vince; + param39.is_autotext = param.is_autotext; + param39.is_backrotate180 = param.is_backrotate180; + param39.is_convex = param.is_convex; + param39.is_dogeardetection = param.is_dogeardetection; + param39.is_duplex = param.is_duplex; + param39.is_switchfrontback = param.is_switchfrontback; + param39.multi_output_red = param.multi_output_red; + param39.noise = param.noise; + param39.paperAlign = param.paperAlign; + param39.papertype = param.papertype; + param39.pixtype = param.pixtype; + param39.resolution_dst = param.resolution_dst; + param39.resolution_native = param.resolution_native; + param39.scannum = param.scannum; + param39.sharpen = param.sharpen; + param39.threshold = param.threshold; + m_usb->write_bulk(¶m39, sizeof(param39)); + +} + +void GScanO1003399::Scanner_StartScan(UINT16 count) +{ + + scanflag = true; + Set_ErrorCode(0); + getimgnum = 0; + aquirenum = 0; + + reset(); + devState = DEV_ISRUNNING; + if (scan_mode()) + { + devState = DEV_WRONG; + Set_ErrorCode(COUNT_MODE); + return; + } + //if (!Get_Scanner_PaperOn()) + //{ + // devState = DEV_WRONG; + // Set_ErrorCode(NO_FEED); + // return; + //} + + start(); + if (!m_usbthread.get()) { + b_usbthread = true; + m_usbthread.reset(new thread(&GScanO1003399::usb_run, this)); + } +} + +void GScanO1003399::Stop_scan() +{ + if (devState != DEV_ISRUNNING) + return; + stop(); + scanflag = false; + if (fu_rx.valid()) + fu_rx.wait(); + devState == DEV_ISRUNNING ? devState = DEV_STOP : devState = DEV_WRONG; +} + +int GScanO1003399::notifyscan() +{ + return 0; +} + +void GScanO1003399::ResetScanner() +{ + +} + +bool GScanO1003399::Get_IsImageQueueEmpty() +{ + return m_imagedata.Size() < 1; +} + +void GScanO1003399::reset() +{ + devState = DEV_STOP; + m_imagedata.Clear(); +} + +void GScanO1003399::clear_hwerror() +{ +} + +UINT32 GScanO1003399::get_ErrorCode() +{ + return Error_Code; +} + +void GScanO1003399::Set_ErrorCode(UINT32 value) +{ + Error_Code = value; +} + +int GScanO1003399::get_scanned_num() +{ + return 0; +} + +void GScanO1003399::set_sleep_time(int mode) +{ +} + +bool GScanO1003399::set_scannercode(std::string str) +{ + return false; +} + +std::string GScanO1003399::get_scannercode() +{ + return std::string(); +} + +void GScanO1003399::usb_run() +{ + unsigned char buff[64]; + 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; + switch (info.From) + { + case IMG: + if (is_runing()) + im_rx(); + 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)); + break; + default: + FileTools::writelog(log_ERROR, "Got Unkown error code ! From =" + to_string(info.From) + " Code = " + to_string(info.Code)); + break; + } + if ((codeconvter(info) != 0)) + { + scanflag = false; + devState = codeconvter(info) == -1 ? DEV_STOP : DEV_WRONG; + } + if (codeconvter(info) > 0) + { + Set_ErrorCode(codeconvter(info)); + stop(); + } + this_thread::sleep_for(chrono::microseconds(10)); + } + + } +} + +void GScanO1003399::start() +{ + scanner_cmd(m_usb, SC_START); +} + +void GScanO1003399::stop() +{ + scanner_cmd(m_usb, SC_STOP); +} + +bool GScanO1003399::is_runing() +{ + return scanner_read_reg(m_usb, SR_STATUS) & 0x01; +} + +int GScanO1003399::scan_mode() +{ + return scanner_read_reg(m_usb, SR_OS) & 0x01; +} + +int GScanO1003399::count() +{ + return scanner_read_reg(m_usb, SR_SCAN_COUNT); +} + +void GScanO1003399::abort_dev_tx() +{ + scanner_write_reg(m_usb, SR_IM_ABORT, 1); //!< to-list +} + +void GScanO1003399::config_scanparam(const HG_ScanConfig& cfg) +{ + scanner_write_reg(m_usb, SR_CONFIG_SCAN_PARAM, cfg.value); +} + +void GScanO1003399::config_imgprocparam(const HGImgProcParms& imgprocparams) +{ + scanner_write_reg(m_usb, SR_CONFIF_IMGPROCPARAM,imgprocparams.value); +} + +bool GScanO1003399::is_rx() +{ + return false; +} + +bool GScanO1003399::rx_cmd() +{ + scanner_write_reg(m_usb, 8, 1); + return true; +} + +bool GScanO1003399::is_dev_tx() +{ + return scanner_read_reg(m_usb, SR_IM_TXING); +} + +void GScanO1003399::im_rx() +{ + if (!is_rx() && !is_dev_tx()) + { + fu_rx = m_imgthread.enqueue([this] { + do + { + /* code */ + auto &buffi = im_data; + int count = front_datasize(); + buffi->resize(count); + rx_cmd(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + count = read_data(buffi->data(), count, count / (0.01 * 1024 * 1024)); + pop_dev_im(); + vector mats; + auto& buffs = G400Decode(buffi).getImageBuffs(); + UpdateScanInfo(countNReaded(), get_imgTransfered()); + imgproce(buffs); + } while (im_dev_count()); + }); + } +} + +int GScanO1003399::read_data(void* data, int length, int timeout) +{ + int readed = 0; + int reading = 0; + const int buffer_size = 2 * 1024 * 1024; + StopWatch sw; + while (readed < length && sw.elapsed_ms() < timeout) { + 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; + } + } + return readed; +} + +void GScanO1003399::pop_dev_im() +{ + scanner_write_reg(m_usb, SR_IM_POP, 1); //!< to-list +} + +int GScanO1003399::front_datasize() +{ + return scanner_read_reg(m_usb, SR_IM_FRONT_SIZE); +} + +int GScanO1003399::im_dev_count() +{ + return scanner_read_reg(m_usb, SR_IM_COUNT); //!< to-list ; +} + +void GScanO1003399::imgproce(std::vector>>& buffs) +{ + vector mats; + for (auto& buf : buffs) { + cv::ImreadModes rmc; + //int rm; + if (m_param.filter != 3 || m_param.enhance_color || m_param.hsvcorrect) { + rmc = cv::IMREAD_COLOR; + //rm = 1; + } + else { + rmc = m_param.pixtype == 2 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE; + //rm = scanParam.pixtype == 2 ? 1 : 6; + } + try + { + cv::Mat mat = cv::imdecode(*buf, rmc); + if (mat.empty()) { + FileTools::writelog(log_ERROR, "decode image data error"); + continue; + } + buf.reset(); + mats.push_back(mat); + FileTools::writelog(log_INFO, "push_back image num= " + to_string(getimgnum++)); + } + catch (const std::exception& e) + { + //writelog(e.what()); + FileTools::writelog(log_ERROR, e.what()); + } + } + buffs.clear(); + if (m_param.automaticcolor) + { + CImageApplyColorRecognition(m_param.automaticcolortype == 1 ? CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray : CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono).apply(mats,m_param.is_duplex); + + } + for (int i = 0; i < mats.size(); i++) { + //if (!m_param.is_duplex && i == 1) { + // mats[i].release(); + // break; + //} + if (!mats[i].empty()) { + IMat2Bmp idata; + if (m_param.pixtype == 1 && m_param.hsvcorrect) + if (mats[i].channels() == 3) + cvtColor(mats[i], mats[i], cv::COLOR_BGR2GRAY); + idata = (m_param.pixtype == 0 || (((m_param.automaticcolortype == 0) && (m_param.automaticcolor == true)) && (mats[i].channels() == 1))) ? (IMat2Bmp)Mat2BmpBw(mats[i], m_param.resolution_dst) : Mat2Bmp(mats[i], m_param.resolution_dst); + //if (!m_param.multi_output_red) + // mats[i].release(); + + m_imagedata.Put(idata.getBmpDataBuffer()); + } + } + + if (m_param.multi_output_red) { + for (int i = 0; i < mats.size(); i++) { + if (!mats[i].empty()) { + ImageMultiOutput m_mlt; + cv::Mat ret = m_mlt.GetMultiFilterMat(mats[i], 2); + mats[i].release(); + if (!ret.empty()) { + if (!m_param.is_duplex && i == 1) { + ret.release(); + break; + } + Mat2Bmp mb(ret, m_param.resolution_dst); + m_imagedata.Put(mb.getBmpDataBuffer()); + ret.release(); + } + } + } + } + mats.clear(); +} + +int GScanO1003399::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; + default: + break; + } + } + if (code.From == HGType::V4L2) + { + switch (code.Code) + { + case 0: + return V4L2_AQULRE_ERROR; + case 1: + return V4L2_IMAGE_EMPTY; + default: + break; + } + } + + return 0; +} diff --git a/huagao/Device/GScanO1003399.h b/huagao/Device/GScanO1003399.h new file mode 100644 index 00000000..58941b8e --- /dev/null +++ b/huagao/Device/GScanO1003399.h @@ -0,0 +1,85 @@ +#pragma once +#include "stdafx.h" +#include "IGDevice.h" +#include "GScan.h" +#include "CyUsbEx.h" +#include "IConfig.h" +#include "G400ScanConfig.h" +#include +#include +#include +#include "ThreadPool.h" +#include "StopWatch.h" +#include "ImageMatQueue.h" +#include "opencv2/opencv.hpp" + + + +class GScanO1003399 :public IScanner +{ +public: + GScanO1003399(); + virtual ~GScanO1003399(); + virtual void open(int vid, int pid) override; + virtual void regist_deviceevent_callback(deviceevent_callback callback, void* usrdata = 0) override; + virtual void DogEar_callback(std::function fun) override; + virtual int aquire_bmpdata(std::vector& bmpdata) override; + virtual BOOL IsConnected() override; + virtual std::string GetFWVersion() override; + virtual std::string GetSerialNum() override; + virtual std::uint32_t GetMotorFPGA() override; + virtual std::uint32_t GetScanFPGA() override; + virtual bool is_scan() override; + virtual BOOL Get_Scanner_PaperOn() override; + virtual int Get_Roller_num() override; + virtual void config_params(GScanCap& param) override; + virtual void Scanner_StartScan(UINT16 count) override; + virtual void Stop_scan() override; + virtual int notifyscan() override; + virtual void ResetScanner() override; + virtual bool Get_IsImageQueueEmpty() override; + virtual void reset() override; + virtual void clear_hwerror() override; + virtual UINT32 get_ErrorCode() override; + virtual void Set_ErrorCode(UINT32 value) override; + virtual int get_scanned_num() override; + virtual void set_sleep_time(int mode) override; + virtual bool set_scannercode(std::string str) override; + virtual std::string get_scannercode() override; + +private: + void usb_run(); + void im_rx(); + void start(); + void stop(); + bool is_runing(); + int scan_mode(); + int count(); + void abort_dev_tx(); + void config_scanparam(const HG_ScanConfig& cfg); + void config_imgprocparam(const HGImgProcParms& imgprocparams); + bool is_rx(); + bool rx_cmd(); + bool is_dev_tx(); + int read_data(void* data, int length, int timeout); + void pop_dev_im(); + int front_datasize(); + int im_dev_count(); + void imgproce(std::vector>>& buffs); + int codeconvter(HGEIntInfo code); + +private: + volatile int devState; + volatile int Error_Code; + volatile bool scanflag; + GScanCap m_param; + std::shared_ptr m_usb; + volatile bool b_usbthread; + std::future fu_rx; + ThreadPool m_imgthread; + std::shared_ptr m_usbthread; + std::shared_ptr> im_data; + BlockingQueue>> m_imagedata; + +}; + diff --git a/huagao/Device/IConfig.h b/huagao/Device/IConfig.h index 90e019c2..3715fa70 100644 --- a/huagao/Device/IConfig.h +++ b/huagao/Device/IConfig.h @@ -6,6 +6,8 @@ #include "PaperSize.h" #define FOR_LANXUM +using u32 = unsigned int; + static std::map SupPaperTyps = { #ifdef G200 #ifdef FOR_LANXUM @@ -26,9 +28,15 @@ static std::map SupPaperTyps = { {{TwSS::USLedger,PaperAlign::Rot0},12}, {{TwSS::USLegal,PaperAlign::Rot0},13}, {{TwSS::None,PaperAlign::Rot0},0}, +#ifdef G1003399 + {{TwSS::USStatement,PaperAlign::Rot0},17}, + {{TwSS::MaxSize,PaperAlign::Rot0},19}, + {{TwSS::Trigeminy,PaperAlign::Rot0},17} +#else {{TwSS::USStatement,PaperAlign::Rot0},16}, {{TwSS::MaxSize,PaperAlign::Rot0},16}, {{TwSS::Trigeminy,PaperAlign::Rot0},16} +#endif #else {{TwSS::A3,PaperAlign::Rot0},0}, {{TwSS::A4,PaperAlign::Rot0},1}, @@ -102,6 +110,108 @@ static std::map secrewMaps = { {4,3}, {5,4} }; + + +enum HGType +{ + MtBoard = 1, + FPGA, + V4L2, + IMG, + STOPSCAN, +}; + +struct HGEIntInfo +{ + HGType From; + unsigned int Code; +}; + +#define USB_REQ_GET_FPGA_REGS 0x40 +#define USB_REQ_SET_FPGA_REGS 0x41 +#define USB_REQ_GET_MOTOR_REGS 0x42 +#define USB_REQ_SET_MOTOR_REGS 0x43 + +#define USB_REQ_GET_DEV_STATUS 0x60 +#define USB_REQ_GET_DEV_CONFIGURATION 0x61 +#define USB_REQ_SET_DEV_CONFIGURATION 0x62 +#define USB_REQ_GET_DEV_REGS 0x63 +#define USB_REQ_SET_DEV_REGS 0x64 + +enum Scanner_Reg_Defs +{ + SR_CMD, + SR_STATUS, + SR_SCAN_COUNT, + SR_OS, + SR_SENSORS, + SR_MOTOR, + SR_IM_TYPE, + SR_IM_COUNT, + SR_IM_TX, + SR_IM_FRONT_SIZE, + SR_IM_CLEAR, + SR_IM_TXING, + SR_IM_POP, + SR_IM_ABORT, + SR_COUNT, + SR_CONFIG_SCAN_PARAM, + SR_GET_FWVERSION, + SR_SET_FWERSION, + SR_GET_SERIALNUM, + SR_SET_SERIALNUM, + SR_CONFIF_IMGPROCPARAM, + SR_PAPER_READY, +}; + +enum Scanner_Cmd_Defs +{ + SC_START, + SC_STOP, + SC_CLEAR, + SC_COUNT +}; + +typedef union HG_ImgProcParms +{ + unsigned int value; + struct + { + u32 papertype : 5; + u32 scanside : 3; + u32 res : 10; + u32 rotate : 2; + u32 autodescrew : 1; + u32 fillbackground : 1; + u32 filter : 4; + u32 enhancecolor : 2; + u32 fillhole : 1; + u32 reversed : 3; + }imgprocparams; +}HGImgProcParms; + + +///用于CIS 自动校正参数保存 +typedef struct +{ + u32 gainF[6]; + u32 gainB[6]; + u32 offsetsF[6]; + u32 offsetsB[6]; + u32 expF[3]; + u32 expB[3]; + u32 sp; +}HGCISConfig; + + +typedef struct +{ + HGCISConfig colorCorrect; + HGCISConfig color; + HGCISConfig grayCorrect; + HGCISConfig gray; +}HGCorrectConfigs; + typedef union Config_Param { unsigned int value; struct { @@ -121,6 +231,39 @@ typedef union Config_Param { }; } ConfigParam; +typedef union HG_ScanConfig +{ + unsigned int value; + struct + { + unsigned int paper : 5; + unsigned int color : 1; + unsigned int dpi : 2; + unsigned int double_feed_enbale : 1; + unsigned int stable_enbale : 1; + unsigned int screw_detect_enable : 1; + unsigned int screw_detect_level : 3;//第十四位 + unsigned int unused_one : 6; + unsigned int pc_correct : 1; + unsigned int enable_sizecheck : 1; + unsigned int enabledsp_cache : 1; + unsigned int sizeerror_errorratio : 9; + }g200params; + struct + { + unsigned int pageSize : 5; + unsigned int isColor : 1; + unsigned int dpi : 2; + unsigned int doubleFeeded : 1; + unsigned int enableStable : 1; + unsigned int enableLed : 1; + unsigned int reversed1 : 6; + unsigned int isCorrect : 1; + unsigned int dstHeight : 8; + unsigned int reversed2 : 6; + }g400params; +}HGScanConfig; + class IConfig { public: diff --git a/huagao/Device/IUsb.h b/huagao/Device/IUsb.h index a286b467..91af68db 100644 --- a/huagao/Device/IUsb.h +++ b/huagao/Device/IUsb.h @@ -6,7 +6,7 @@ class IUsb public: virtual ~IUsb() {} virtual bool open() = 0; - virtual void set_usbhotplug_callback(usbhotplug_callback callback=NULL,void* userdata=NULL)=0; + virtual void set_usbhotplug_callback(usbhotplug_callback callback=0,void* userdata=0)=0; virtual bool close() = 0; virtual bool is_open() = 0; virtual bool is_connected() = 0; diff --git a/huagao/Device/PublicFunc.h b/huagao/Device/PublicFunc.h index d87c2891..4e2f315f 100644 --- a/huagao/Device/PublicFunc.h +++ b/huagao/Device/PublicFunc.h @@ -84,7 +84,8 @@ const std::string AUTOCROP_THRESHOLD = "AutoCrop_Threshold"; const std::string NOISE = "Noise"; const std::string LOWPOWERMODE = "ilowpowermode"; - +#pragma pack(push) +#pragma pack(4) /****************** **参数保存结构体** *******************/ @@ -186,7 +187,7 @@ typedef struct Scan_Rect { int y; }ScanRect; -enum PaperAlign :byte { +enum PaperAlign :uint8_t { Rot0 = 0, Rot270 = 3, AutoTextOrientation = 5 @@ -212,12 +213,12 @@ typedef enum SharpenBlur :short { struct GScanCap { - byte papertype; /**< the current paper source ADF or Flatbed*/ + uint8_t papertype; /**< the current paper source ADF or Flatbed*/ PaperAlign paperAlign; - byte en_sizecheck; /**< 尺寸检测*/ + uint8_t en_sizecheck; /**< 尺寸检测*/ float imageRotateDegree; - byte is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/ - byte en_fold; /**<对折*/ + uint8_t is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/ + uint8_t en_fold; /**<对折*/ int pixtype; /**< type of pixels to transfer image as */ int automaticcolor; /**<顔色自動識別*/ int automaticcolortype; /**<顔色自動識別后非彩色上傳類型*/ @@ -228,34 +229,79 @@ struct GScanCap float contrast; /**< Contrast */ float brightness; /**< Brightness */ float threshold; /**< Threshold */ - byte is_autocontrast; /**< 自动对比度*/ - byte is_autocrop; /**< 自动裁切*/ - byte is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/ + uint8_t is_autocontrast; /**< 自动对比度*/ + uint8_t is_autocrop; /**< 自动裁切*/ + uint8_t is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/ int discardblank_percent; /**<跳过空白页阀值*/ - byte is_autodiscradblank_vince;/**自动丢弃空白页发票*/ - byte is_switchfrontback; /**交换正反面*/ - byte autodescrew; /**< 自动纠偏*/ - byte multi_output_red; /*多流输出*/ - byte hsvcorrect; /**<答题卡除红*/ - byte filter; /**< 除色*/ - byte sharpen; - byte enhance_color; /**< 颜色增强*/ - byte fillbackground; /**< 填黑框*/ + uint8_t is_autodiscradblank_vince;/**自动丢弃空白页发票*/ + uint8_t is_switchfrontback; /**交换正反面*/ + uint8_t autodescrew; /**< 自动纠偏*/ + uint8_t multi_output_red; /*多流输出*/ + uint8_t hsvcorrect; /**<答题卡除红*/ + uint8_t filter; /**< 除色*/ + uint8_t sharpen; + uint8_t enhance_color; /**< 颜色增强*/ + uint8_t fillbackground; /**< 填黑框*/ bool is_convex; /**< 填黑框模式,true为凸多边形填充,false为凹多边形填充,默认true*/ int noise; /**< 除噪像素,能够消除noise宽度的背景竖条纹干扰,默认40*/ int indent; /**< 轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5*/ int AutoCrop_threshold; /**< 自动裁剪二值化阈值,取值范围(0, 255),默认40*/ unsigned short scannum; /**< 扫描张数*/ - byte is_backrotate180; /**< 背面旋转180*/ - byte is_dogeardetection; /**<折角检测*/ + uint8_t is_backrotate180; /**< 背面旋转180*/ + uint8_t is_dogeardetection; /**<折角检测*/ HardwareCaps hardwarecaps; /**< 硬件扫描参数*/ FillHole fillhole; DetachNoise detachnoise; /**< 黑白降噪*/ - byte is_autotext; /**< 自动文本方向识别*/ + uint8_t is_autotext; /**< 自动文本方向识别*/ std::string Caption; std::string SavePath; }; + +struct GScanCap_3399 +{ + uint8_t papertype; /**< the current paper source ADF or Flatbed*/ + PaperAlign paperAlign; + uint8_t en_sizecheck; /**< 尺寸检测*/ + float imageRotateDegree; + uint8_t is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/ + uint8_t en_fold; /**<对折*/ + int pixtype; /**< type of pixels to transfer image as */ + int automaticcolor; /**<顔色自動識別*/ + int automaticcolortype; /**<顔色自動識別后非彩色上傳類型*/ + //ScanRect scanrect; + float resolution_dst; /**< horizontal resolution */ + float resolution_native; + float gamma; /**< Gamma */ + float contrast; /**< Contrast */ + float brightness; /**< Brightness */ + float threshold; /**< Threshold */ + uint8_t is_autocontrast; /**< 自动对比度*/ + uint8_t is_autocrop; /**< 自动裁切*/ + uint8_t is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/ + int discardblank_percent; /**<跳过空白页阀值*/ + uint8_t is_autodiscradblank_vince;/**自动丢弃空白页发票*/ + uint8_t is_switchfrontback; /**交换正反面*/ + uint8_t autodescrew; /**< 自动纠偏*/ + uint8_t multi_output_red; /*多流输出*/ + uint8_t hsvcorrect; /**<答题卡除红*/ + uint8_t filter; /**< 除色*/ + uint8_t sharpen; + uint8_t enhance_color; /**< 颜色增强*/ + uint8_t fillbackground; /**< 填黑框*/ + bool is_convex; /**< 填黑框模式,true为凸多边形填充,false为凹多边形填充,默认true*/ + int noise; /**< 除噪像素,能够消除noise宽度的背景竖条纹干扰,默认40*/ + int indent; /**< 轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5*/ + int AutoCrop_threshold; /**< 自动裁剪二值化阈值,取值范围(0, 255),默认40*/ + unsigned short scannum; /**< 扫描张数*/ + uint8_t is_backrotate180; /**< 背面旋转180*/ + uint8_t is_dogeardetection; /**<折角检测*/ + HardwareCaps hardwarecaps; /**< 硬件扫描参数*/ + FillHole fillhole; + DetachNoise detachnoise; /**< 黑白降噪*/ + uint8_t is_autotext; /**< 自动文本方向识别*/ +}; + typedef struct Paper_Status { Paper_Status(unsigned int paper, unsigned int orentate) :Paper(paper), Orentate(orentate) {} Paper_Status():Paper(0), Orentate(0){} @@ -296,6 +342,7 @@ enum G400_DPI { G400_D600 }; +#pragma pack(pop) #define CAPTION_LEN 256 #define TWAIN_IMAGE_FILE_LIST_NAME TEXT(".dat") diff --git a/huagao/Device/ThreadPool.h b/huagao/Device/ThreadPool.h new file mode 100644 index 00000000..41832030 --- /dev/null +++ b/huagao/Device/ThreadPool.h @@ -0,0 +1,98 @@ +#ifndef THREAD_POOL_H +#define THREAD_POOL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ThreadPool { +public: + ThreadPool(size_t); + template + auto enqueue(F&& f, Args&&... args) + -> std::future::type>; + ~ThreadPool(); +private: + // need to keep track of threads so we can join them + std::vector< std::thread > workers; + // the task queue + std::queue< std::function > tasks; + + // synchronization + std::mutex queue_mutex; + std::condition_variable condition; + bool stop; +}; + +// the constructor just launches some amount of workers +inline ThreadPool::ThreadPool(size_t threads) + : stop(false) +{ + for(size_t i = 0;i task; + + { + std::unique_lock lock(this->queue_mutex); + this->condition.wait(lock, + [this]{ return this->stop || !this->tasks.empty(); }); + if(this->stop && this->tasks.empty()) + return; + task = std::move(this->tasks.front()); + this->tasks.pop(); + } + + task(); + } + } + ); +} + +// add new work item to the pool +template +auto ThreadPool::enqueue(F&& f, Args&&... args) + -> std::future::type> +{ + using return_type = typename std::result_of::type; + + auto task = std::make_shared< std::packaged_task >( + std::bind(std::forward(f), std::forward(args)...) + ); + + std::future res = task->get_future(); + { + std::unique_lock lock(queue_mutex); + + // don't allow enqueueing after stopping the pool + if(stop) + throw std::runtime_error("enqueue on stopped ThreadPool"); + + tasks.emplace([task](){ (*task)(); }); + } + condition.notify_one(); + return res; +} + +// the destructor joins all threads +inline ThreadPool::~ThreadPool() +{ + { + std::unique_lock lock(queue_mutex); + stop = true; + } + condition.notify_all(); + for(std::thread &worker: workers) + worker.join(); +} + +#endif diff --git a/huagao/huagaods.cpp b/huagao/huagaods.cpp index 3acf1c75..8f4f59dd 100644 --- a/huagao/huagaods.cpp +++ b/huagao/huagaods.cpp @@ -16,6 +16,7 @@ #include "Device/PublicFunc.h" #include "Device/GScanO200.h" #include "Device/GScanO400.h" +#include "Device/GScanO1003399.h" #include "Device/filetools.h" #include "Device/GScanVirtual.h" #include @@ -96,7 +97,7 @@ static constexpr const Identity srcIdent( #endif #ifdef G200 -#ifdef ISG100 +#if defined (ISG100) || defined (G1003399) #ifdef LANXUM "G62S Series", #else // ISG100 @@ -126,7 +127,7 @@ static constexpr const Identity srcIdent( #endif #ifdef G200 -#ifdef ISG100 +#if defined (ISG100) || defined (G1003399) #ifdef MAKEHUAGAO "HUAGOSCAN G100 TWAIN" #elif defined LANXUM //!LANXUM @@ -345,19 +346,24 @@ void HuagaoDs::showmsg(std::string caption, std::string text, int retcode) if (scanner.get()) { int losemun = scanner->get_lose_image_num(); int num = 0; + bool is_duplex = m_scanparam->is_duplex; +#ifdef G1003399 + is_duplex = false; +#endif // G1003399 + if ((retcode == 64 || retcode == 8 || retcode == 16) && losemun > 0)//64 ->SStop losemun--; if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince)) { - if (m_scanparam->is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red) + if (is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); - else if (m_scanparam->is_duplex && m_scanparam->en_fold) + else if (is_duplex && m_scanparam->en_fold) num = scanner->get_imgnReaded() - scanner->get_imgTransfered(); - else if (m_scanparam->is_duplex && m_scanparam->multi_output_red) + else if (is_duplex && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 4 - scanner->get_imgTransfered(); - else if ((!m_scanparam->is_duplex) && m_scanparam->multi_output_red) + else if ((!is_duplex) && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); - else if (!m_scanparam->is_duplex) + else if (!is_duplex) num = scanner->get_imgnReaded() - scanner->get_imgTransfered(); else num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); @@ -770,6 +776,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) { showmsg("警告", msgs[(UsbSupported)202]); return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } +#ifndef G1003399 auto usblist = UsbScan_List::find_all_usb(); if (!usblist.empty()) { @@ -790,16 +797,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) { } } } - FileTools::writelog(log_INFO, "open ds find device vid=" + to_string(vid) + "\tpid=" + to_string(pid)); - m_haveError = false; - updataGscanCap(); - bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); - BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header()); - bmInfo.biHeight = 2000; - bmInfo.biWidth = 2000; - bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); - m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); + FileTools::writelog(log_INFO, "open ds find device vid=" + to_string(vid) + "\tpid=" + to_string(pid)); if (vid == 0 || pid == 0) { //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE); @@ -811,6 +810,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) { return checkDeviceOnline(); } scanner->open(vid, pid); +#else + scanner.reset(new GScanO1003399()); +#endif // G1003399 + if (!scanner->IsConnected()) { //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE); @@ -826,8 +829,6 @@ Result HuagaoDs::identityOpenDs(const Identity&) { scanner->regist_deviceevent_callback(DeviceEvent_callback, this); auto dgcall = [&](int pagenum) { - CString text; - text.Format(_T("74 %d"), pagenum); //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE); showmsg("警告", "在" + to_string(pagenum) + "检测到折角!"); scanner->Stop_scan(); @@ -837,6 +838,15 @@ Result HuagaoDs::identityOpenDs(const Identity&) { }; scanner->DogEar_callback(dgcall); } + + m_haveError = false; + updataGscanCap(); + bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); + BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header()); + bmInfo.biHeight = 2000; + bmInfo.biWidth = 2000; + bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); + m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); //MessageBox(NULL, L"2", L"", 0); // init caps // there are caps a minimal source must support @@ -1916,15 +1926,20 @@ Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) { if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince)) { int num = 0; - if (m_scanparam->is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red) + bool is_duplex = m_scanparam->is_duplex; +#ifdef G1003399 + is_duplex = false; +#endif // G1003399 + + if (is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); - else if (m_scanparam->is_duplex && m_scanparam->en_fold) + else if (is_duplex && m_scanparam->en_fold) num = scanner->get_imgnReaded() - scanner->get_imgTransfered(); - else if (m_scanparam->is_duplex && m_scanparam->multi_output_red) + else if (is_duplex && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 4 - scanner->get_imgTransfered(); - else if ((!m_scanparam->is_duplex) && m_scanparam->multi_output_red) + else if ((!is_duplex) && m_scanparam->multi_output_red) num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); - else if (!m_scanparam->is_duplex) + else if (!is_duplex) num = scanner->get_imgnReaded() - scanner->get_imgTransfered(); else num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered(); @@ -1991,13 +2006,13 @@ Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) { if (!ui.showUi()) { // this is an exception when we want to set state explicitly, notifyXferReady can be called only in enabled state // with hidden UI, the usual workflow DsState::Enabled -> notifyXferReady() -> DsState::XferReady is a single step -//#ifndef G200 +#ifndef G200 while (!scanner->Get_Scanner_PaperOn()) { if (MessageBox(NULL, L"检测到无纸,请添加纸张", L"提示", MB_YESNO | MB_SYSTEMMODAL) == IDNO) return seqError(); } - //#endif // !G200 +#endif // !G200 auto ret = startScan(); diff --git a/huagao/stdafx.h b/huagao/stdafx.h index e915f785..04a82056 100644 Binary files a/huagao/stdafx.h and b/huagao/stdafx.h differ