2022-07-19 03:51:00 +00:00
|
|
|
#include "HGLibDeviceImpl.hpp"
|
|
|
|
#include "base/HGInc.h"
|
|
|
|
#include "base/HGInfo.h"
|
2022-07-19 09:09:52 +00:00
|
|
|
#include "base/HGImage.h"
|
2022-07-19 03:51:00 +00:00
|
|
|
#include "HGString.h"
|
|
|
|
|
|
|
|
HGLock HGLibDeviceImpl::m_lock = NULL;
|
|
|
|
HGLibDeviceHotPlugEventFunc HGLibDeviceImpl::m_hotPlugEventFunc = NULL;
|
|
|
|
HGPointer HGLibDeviceImpl::m_hotPlugEventParam = NULL;
|
|
|
|
HGBool HGLibDeviceImpl::m_init = HGFALSE;
|
|
|
|
std::vector<std::string> HGLibDeviceImpl::m_devNameList;
|
2022-07-19 09:09:52 +00:00
|
|
|
std::map<SANE_Handle, HGLibDeviceImpl*> HGLibDeviceImpl::m_deviceList;
|
2022-07-19 03:51:00 +00:00
|
|
|
|
|
|
|
HGLibDeviceImpl::HGLibDeviceImpl()
|
|
|
|
{
|
2022-07-19 09:09:52 +00:00
|
|
|
m_devHandle = NULL;
|
|
|
|
m_devName.clear();
|
|
|
|
m_scanning = HGFALSE;
|
|
|
|
m_scanEvent = NULL;
|
|
|
|
m_eventFunc = NULL;
|
|
|
|
m_eventParam = NULL;
|
|
|
|
m_imageFunc = NULL;
|
|
|
|
m_imageParam = NULL;
|
2022-07-19 03:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HGLibDeviceImpl::~HGLibDeviceImpl()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::Init(HGLibDeviceHotPlugEventFunc func, HGPointer param)
|
|
|
|
{
|
|
|
|
if (m_init)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(NULL == m_lock);
|
|
|
|
HGBase_CreateLock(&m_lock);
|
|
|
|
assert(NULL == m_hotPlugEventFunc);
|
|
|
|
m_hotPlugEventFunc = func;
|
|
|
|
m_hotPlugEventParam = param;
|
|
|
|
|
|
|
|
SANE_Int version_code = 0;
|
|
|
|
if (SANE_STATUS_GOOD != sane_init_ex(&version_code, sane_ex_callback, NULL))
|
|
|
|
{
|
|
|
|
m_hotPlugEventFunc = NULL;
|
|
|
|
m_hotPlugEventParam = NULL;
|
|
|
|
HGBase_DestroyLock(m_lock);
|
|
|
|
m_lock = NULL;
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_init = HGTRUE;
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::Deinit()
|
|
|
|
{
|
|
|
|
if (!m_init)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
2022-07-19 09:09:52 +00:00
|
|
|
if (!m_deviceList.empty())
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
2022-07-19 03:51:00 +00:00
|
|
|
sane_exit();
|
2022-07-19 09:09:52 +00:00
|
|
|
m_devNameList.clear();
|
2022-07-19 03:51:00 +00:00
|
|
|
m_hotPlugEventFunc = NULL;
|
|
|
|
m_hotPlugEventParam = NULL;
|
|
|
|
HGBase_DestroyLock(m_lock);
|
|
|
|
m_lock = NULL;
|
|
|
|
m_init = HGFALSE;
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGChar** HGLibDeviceImpl::GetNameList()
|
|
|
|
{
|
2022-07-19 09:09:52 +00:00
|
|
|
HGChar** nameList = NULL;
|
|
|
|
|
|
|
|
HGBase_EnterLock(m_lock);
|
|
|
|
nameList = (HGChar **)malloc((m_devNameList.size() + 1) * sizeof(HGChar *));
|
|
|
|
if (NULL != nameList)
|
|
|
|
{
|
|
|
|
nameList[m_devNameList.size()] = NULL;
|
|
|
|
for (int i = 0; i < (int)m_devNameList.size(); ++i)
|
|
|
|
{
|
|
|
|
nameList[i] = (HGChar *)malloc(m_devNameList[i].size() + 1);
|
|
|
|
if (NULL != nameList[i])
|
|
|
|
strcpy(nameList[i], m_devNameList[i].c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HGBase_LeaveLock(m_lock);
|
|
|
|
|
|
|
|
return nameList;
|
2022-07-19 03:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::ReleaseNameList(HGChar** deviceName)
|
|
|
|
{
|
|
|
|
if (NULL == deviceName)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
2022-07-19 09:09:52 +00:00
|
|
|
HGChar** p = deviceName;
|
|
|
|
while (0 != *p)
|
2022-07-19 03:51:00 +00:00
|
|
|
{
|
2022-07-19 09:09:52 +00:00
|
|
|
free(*p);
|
|
|
|
++p;
|
2022-07-19 03:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
free(deviceName);
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
2022-07-19 09:09:52 +00:00
|
|
|
HGLibDeviceImpl* HGLibDeviceImpl::Open(const HGChar* deviceName)
|
|
|
|
{
|
|
|
|
SANE_Handle devHandle = NULL;
|
|
|
|
sane_open(deviceName, &devHandle);
|
|
|
|
if (NULL == devHandle)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGLibDeviceImpl* deviceImpl = new HGLibDeviceImpl;
|
|
|
|
deviceImpl->m_devHandle = devHandle;
|
|
|
|
deviceImpl->m_devName = deviceName;
|
|
|
|
m_deviceList[devHandle] = deviceImpl;
|
|
|
|
return deviceImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::Close()
|
|
|
|
{
|
|
|
|
assert(NULL != m_devHandle);
|
|
|
|
assert(!m_devName.empty());
|
|
|
|
|
|
|
|
StopScan();
|
|
|
|
sane_close(m_devHandle);
|
|
|
|
m_devHandle = NULL;
|
|
|
|
m_devName.clear();
|
|
|
|
|
|
|
|
std::map<SANE_Handle, HGLibDeviceImpl*>::iterator iter;
|
|
|
|
for (iter = m_deviceList.begin(); iter != m_deviceList.end(); ++iter)
|
|
|
|
{
|
|
|
|
if (iter->second == this)
|
|
|
|
{
|
|
|
|
m_deviceList.erase(iter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::SetParam(const HGLibDeviceSetParam* param, HGUInt count)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGLibDeviceGetParamGroup* HGLibDeviceImpl::GetParamGroupList(HGUInt* count)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::ReleaseParamGroupList(HGLibDeviceGetParamGroup* paramGroup, HGUInt count)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::ResetParam()
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::StartScan(HGLibDeviceScanEventFunc eventFunc, HGPointer eventParam,
|
|
|
|
HGLibDeviceScanImageFunc imageFunc, HGPointer imageParam)
|
|
|
|
{
|
|
|
|
if (m_scanning)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBase_CreateEvent(HGFALSE, HGFALSE, &m_scanEvent);
|
|
|
|
assert(NULL != m_scanEvent);
|
|
|
|
m_eventFunc = eventFunc;
|
|
|
|
m_eventParam = eventParam;
|
|
|
|
m_imageFunc = imageFunc;
|
|
|
|
m_imageParam = imageParam;
|
|
|
|
|
|
|
|
SANE_Status status = sane_start(m_devHandle);
|
|
|
|
if (SANE_STATUS_GOOD != status)
|
|
|
|
{
|
|
|
|
m_eventFunc = NULL;
|
|
|
|
m_eventParam = NULL;
|
|
|
|
m_imageFunc = NULL;
|
|
|
|
m_imageParam = NULL;
|
|
|
|
HGBase_DestroyEvent(m_scanEvent);
|
|
|
|
m_scanEvent = NULL;
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_scanning = HGTRUE;
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBool HGLibDeviceImpl::StopScan()
|
|
|
|
{
|
|
|
|
if (!m_scanning)
|
|
|
|
{
|
|
|
|
return HGFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sane_cancel(m_devHandle);
|
|
|
|
|
|
|
|
assert(NULL != m_scanEvent);
|
|
|
|
HGBase_WaitEvent(m_scanEvent);
|
|
|
|
HGBase_DestroyEvent(m_scanEvent);
|
|
|
|
m_scanEvent = NULL;
|
|
|
|
|
|
|
|
m_eventFunc = NULL;
|
|
|
|
m_eventParam = NULL;
|
|
|
|
m_imageFunc = NULL;
|
|
|
|
m_imageParam = NULL;
|
|
|
|
|
|
|
|
m_scanning = HGFALSE;
|
|
|
|
return HGTRUE;
|
|
|
|
}
|
|
|
|
|
2022-07-19 03:51:00 +00:00
|
|
|
int HGLibDeviceImpl::sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param)
|
|
|
|
{
|
|
|
|
switch (code)
|
|
|
|
{
|
|
|
|
case SANE_EVENT_DEVICE_ARRIVED:
|
|
|
|
{
|
|
|
|
SANE_Device* sane_dev = (SANE_Device*)data;
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_ARRIVED, name=%s", Utf8ToStdString(sane_dev->name).c_str());
|
|
|
|
|
|
|
|
HGBase_EnterLock(m_lock);
|
|
|
|
m_devNameList.push_back(sane_dev->name);
|
|
|
|
HGBase_LeaveLock(m_lock);
|
|
|
|
|
|
|
|
if (NULL != m_hotPlugEventFunc)
|
|
|
|
m_hotPlugEventFunc(HGLIB_DEVHOTPLUG_EVENT_ARRIVE, sane_dev->name, m_hotPlugEventParam);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_DEVICE_LEFT:
|
|
|
|
{
|
|
|
|
SANE_Device* sane_dev = (SANE_Device*)data;
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_LEFT, name=%s", Utf8ToStdString(sane_dev->name).c_str());
|
|
|
|
|
|
|
|
HGBase_EnterLock(m_lock);
|
|
|
|
for (int i = 0; i < (int)m_devNameList.size(); ++i)
|
|
|
|
{
|
|
|
|
if (0 == strcmp(sane_dev->name, m_devNameList[i].c_str()))
|
|
|
|
{
|
|
|
|
m_devNameList.erase(m_devNameList.begin() + i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HGBase_LeaveLock(m_lock);
|
2022-07-19 09:09:52 +00:00
|
|
|
|
|
|
|
if (NULL != m_hotPlugEventFunc)
|
|
|
|
m_hotPlugEventFunc(HGLIB_DEVHOTPLUG_EVENT_REMOVE, sane_dev->name, m_hotPlugEventParam);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_WORKING:
|
|
|
|
{
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_WORKING, msg=%s", Utf8ToStdString((char*)data).c_str());
|
|
|
|
|
|
|
|
HGLibDeviceImpl* deviceImpl = m_deviceList[hdev];
|
|
|
|
if (NULL != deviceImpl->m_eventFunc)
|
|
|
|
{
|
|
|
|
deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_BEGIN,
|
|
|
|
HGFALSE, NULL, deviceImpl->m_eventParam);
|
|
|
|
deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_INFO,
|
|
|
|
HGFALSE, (const char*)data, deviceImpl->m_eventParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_SCAN_FINISHED:
|
|
|
|
{
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_SCAN_FINISHED, msg=%s", Utf8ToStdString((char*)data).c_str());
|
|
|
|
|
|
|
|
HGLibDeviceImpl* deviceImpl = m_deviceList[hdev];
|
|
|
|
if (NULL != deviceImpl->m_eventFunc)
|
|
|
|
{
|
|
|
|
deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_INFO,
|
|
|
|
(0 != *len), (const char*)data, deviceImpl->m_eventParam);
|
|
|
|
deviceImpl->m_eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_END,
|
|
|
|
HGFALSE, NULL, deviceImpl->m_eventParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
HGBase_SetEvent(deviceImpl->m_scanEvent);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_STATUS:
|
|
|
|
{
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_STATUS, msg=%s", Utf8ToStdString((char*)data).c_str());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_ERROR:
|
|
|
|
{
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_ERROR, msg=%s", Utf8ToStdString((char*)data).c_str());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SANE_EVENT_IMAGE_OK:
|
|
|
|
{
|
|
|
|
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_IMAGE_OK");
|
|
|
|
|
|
|
|
SANE_Image* sane_img = (SANE_Image*)data;
|
|
|
|
|
|
|
|
HGLibDeviceImpl* deviceImpl = m_deviceList[hdev];
|
|
|
|
if (NULL != deviceImpl->m_imageFunc)
|
|
|
|
{
|
|
|
|
HGUInt imgType = 0;
|
|
|
|
if (sane_img->header.format == SANE_FRAME_GRAY)
|
|
|
|
{
|
|
|
|
if (1 == sane_img->header.depth)
|
|
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
|
|
|
else if (8 == sane_img->header.depth)
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
|
|
}
|
|
|
|
else if (sane_img->header.format == SANE_FRAME_RGB)
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
|
|
|
HGByte* data = sane_img->data;
|
|
|
|
HGImageInfo imgInfo = { (HGUInt)sane_img->header.pixels_per_line, (HGUInt)sane_img->header.lines,
|
|
|
|
imgType, (HGUInt)sane_img->header.bytes_per_line, HGBASE_IMGORIGIN_TOP };
|
|
|
|
|
|
|
|
HGImage img = NULL;
|
|
|
|
HGBase_CreateImageFromData(data, &imgInfo, NULL, 0, HGBASE_IMGORIGIN_TOP, &img);
|
|
|
|
if (NULL != img)
|
|
|
|
{
|
|
|
|
deviceImpl->m_imageFunc((HGLibDevice)deviceImpl, (HGLibImage)img, deviceImpl->m_imageParam);
|
|
|
|
HGBase_DestroyImage(img);
|
|
|
|
}
|
|
|
|
}
|
2022-07-19 03:51:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|