#include "HGSaneImpl.hpp" #include "../base/HGInc.h" #include "../base/HGUtility.h" #include "huagao/hgscanner_error.h" HGSaneManagerImpl::HGSaneManagerImpl() { } HGSaneManagerImpl::~HGSaneManagerImpl() { } HGResult HGSaneManagerImpl::Create() { std::string archName; FILE *file = popen("arch", "r"); if (NULL != file) { char str[256] = {0}; if (NULL != fgets(str, 256, file)) { char *p = str; while (0 != *p && '\n' != *p) { archName.push_back(*p); ++p; } } pclose(file); } std::string osName; FILE* fp = popen("cat /etc/issue | cut -d\' \' -f1", "r"); if (NULL != fp) { char buff[1024] = { 0 }; fread(buff, 1024, 1, fp); int len = (int)strlen(buff); for (int i = 0; i < len; ++i) { if (buff[i] == '\n') buff[i] = '\0'; } osName = buff; pclose(fp); } if (archName.empty() || osName.empty()) { return HGBASE_ERR_FAIL; } if (archName == "mips64") archName += "el"; char manuPath[] = "/etc/sane.d/dll.d"; DIR* dir = opendir(manuPath); if (NULL != dir) { struct dirent* dire = NULL; while (dire = readdir(dir)) { if (0 == strcmp(dire->d_name, ".") || 0 == strcmp(dire->d_name, "..")) { continue; } char fileName[256]; sprintf(fileName, "%s/%s", manuPath, dire->d_name); struct stat filebuf; lstat(fileName, &filebuf); if (S_ISDIR(filebuf.st_mode)) { continue; } std::string manuName; FILE *file = fopen(fileName, "r"); if (NULL != file) { char str[256] = {0}; while (NULL != fgets(str, 256, file)) { if ('#' == str[0] || '\n' == str[0]) { continue; } char *p = str; while (0 != *p && '\n' != *p) { manuName.push_back(*p); ++p; } break; } fclose(file); } if (manuName.empty()) { continue; } std::pair pr; pr.first = manuName; char sanePath[256]; if (osName == "NeoKylin") { sprintf(sanePath, "/usr/lib64/sane/libsane-%s.so.1", manuName.c_str()); } else { sprintf(sanePath, "/usr/lib/%s-linux-gnu/sane/libsane-%s.so.1", archName.c_str(), manuName.c_str()); } pr.second = sanePath; if(!filterDeviceSource(pr.first.c_str())) m_vSource.push_back(pr); } closedir(dir); } return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::Destroy() { if (!m_listSourceImpl.empty()) { return HGBASE_ERR_FAIL; } return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::GetSourceCount(HGUInt *count) { if (NULL == count) { return HGBASE_ERR_INVALIDARG; } *count = (HGUInt)m_vSource.size(); return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::GetSourceName(HGUInt index, HGChar* name, HGUInt maxLen) { if (index >= (HGUInt)m_vSource.size() || NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } if (maxLen < m_vSource[index].first.size() + 1) return HGBASE_ERR_FAIL; strcpy(name, m_vSource[index].first.c_str()); return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::OpenSource(HGUInt index, class HGSaneSourceImpl **sourceImpl) { if (index >= (HGUInt)m_vSource.size() || NULL == sourceImpl) { return HGBASE_ERR_INVALIDARG; } HGSaneSourceImpl *newSourceImpl = new HGSaneSourceImpl(this); HGResult ret = newSourceImpl->Open(m_vSource[index].first.c_str(), m_vSource[index].second.c_str()); if (HGBASE_ERR_OK != ret) { delete newSourceImpl; return ret; } m_listSourceImpl.push_back(newSourceImpl); *sourceImpl = newSourceImpl; return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::OpenDefaultSource(HGSaneSourceImpl **sourceImpl) { if (m_vSource.empty() || NULL == sourceImpl) { return HGBASE_ERR_INVALIDARG; } HGSaneSourceImpl *newSourceImpl = new HGSaneSourceImpl(this); HGResult ret = newSourceImpl->Open(m_vSource[0].first.c_str(), m_vSource[0].second.c_str()); if (HGBASE_ERR_OK != ret) { delete newSourceImpl; return ret; } m_listSourceImpl.push_back(newSourceImpl); *sourceImpl = newSourceImpl; return HGBASE_ERR_OK; } HGResult HGSaneManagerImpl::OpenSelectedSource(HGWindow parent, class HGSaneSourceImpl **sourceImpl) { if (NULL == sourceImpl) { return HGBASE_ERR_INVALIDARG; } const char **manuNames = new const char *[m_vSource.size() + 1]; const char **sanePaths = new const char *[m_vSource.size() + 1]; for (int i = 0; i < (int)m_vSource.size(); ++i) { manuNames[i] = m_vSource[i].first.c_str(); sanePaths[i] = m_vSource[i].second.c_str(); } manuNames[m_vSource.size()] = NULL; sanePaths[m_vSource.size()] = NULL; HGDll dll = NULL; SANEAPI saneAPI; char manuName[256]; if (-2 == show_srclist_ui(manuNames, sanePaths, parent, &dll, &saneAPI, manuName, 256)) { delete [] sanePaths; delete [] manuNames; return HGBASE_ERR_NOTSUPPORT; } delete [] sanePaths; delete [] manuNames; if (NULL == dll) { return HGSANE_ERR_FAIL; } HGSaneSourceImpl* newSourceImpl = new HGSaneSourceImpl(this); HGResult ret = newSourceImpl->Init(manuName, dll, &saneAPI); if (HGBASE_ERR_OK != ret) { delete newSourceImpl; HGBase_DestroyDll(dll); return ret; } m_listSourceImpl.push_back(newSourceImpl); *sourceImpl = newSourceImpl; return HGBASE_ERR_OK; } void HGSaneManagerImpl::RemoveSource(class HGSaneSourceImpl* sourceImpl) { std::list::iterator iter; for (iter = m_listSourceImpl.begin(); iter != m_listSourceImpl.end(); ++iter) { if (*iter == sourceImpl) { m_listSourceImpl.erase(iter); delete sourceImpl; break; } } } bool HGSaneManagerImpl::filterDeviceSource(const char *sourceName) { #if !defined(OEM_HANWANG) && !defined(OEM_LISICHENG) && !defined(OEM_CANGTIAN) && !defined(OEM_ZHONGJING) && !defined(OEM_ZIGUANG) && !defined(OEM_NEUTRAL) && !defined(OEM_DELI) std::string oemIden = "hgsane"; #elif defined(OEM_HANWANG) std::string oemIden = "hwsane"; #elif defined(OEM_LISICHENG) std::string oemIden = "lscsane"; #elif defined(OEM_CANGTIAN) std::string oemIden = "ctssane"; #elif defined(OEM_ZHONGJING) std::string oemIden = "zjsane"; #elif defined(OEM_ZIGUANG) std::string oemIden = "zgsane"; #elif defined(OEM_DELI) std::string oemIden = "dlsane"; #elif defined(OEM_NEUTRAL) std::string oemIden = "neusane"; #endif if (sourceName != strstr(sourceName, oemIden.c_str())) { return true; } return false; } HGSaneSourceImpl::HGSaneSourceImpl(HGSaneManagerImpl *managerImpl) { m_managerImpl = managerImpl; m_manuName.clear(); m_dll = NULL; memset(&m_saneApi, 0, sizeof(SANEAPI)); } HGSaneSourceImpl::~HGSaneSourceImpl() { } HGResult HGSaneSourceImpl::Init(const HGChar* saneManu, HGDll dll, const SANEAPI *saneAPI) { assert(NULL == m_dll); if (NULL == saneManu || 0 == *saneManu || NULL == dll || NULL == saneAPI) { return HGBASE_ERR_INVALIDARG; } if (NULL == saneAPI->sane_open_api || NULL == saneAPI->sane_close_api || NULL == saneAPI->sane_start_api || NULL == saneAPI->sane_read_api || NULL == saneAPI->sane_cancel_api || NULL == saneAPI->sane_get_devices_api || NULL == saneAPI->sane_get_option_descriptor_api || NULL == saneAPI->sane_control_option_api || NULL == saneAPI->sane_get_parameters_api || NULL == saneAPI->sane_set_io_mode_api || NULL == saneAPI->sane_strstatus_api || NULL == saneAPI->sane_init_api || NULL == saneAPI->sane_exit_api) { return HGBASE_ERR_INVALIDARG; } if (SANE_STATUS_GOOD != saneAPI->sane_init_api(NULL, NULL)) { return HGSANE_ERR_FAIL; } m_manuName = saneManu; m_dll = dll; memcpy(&m_saneApi, saneAPI, sizeof(SANEAPI)); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::Open(const HGChar* saneManu, const HGChar* sanePath) { assert(NULL == m_dll); if (NULL == saneManu || 0 == *saneManu || NULL == sanePath || 0 == *sanePath) { return HGBASE_ERR_INVALIDARG; } HGChar fileName[260]; HGBase_GetFileName(sanePath, fileName, 260); HGDll dll = NULL; HGResult ret = HGBase_CreateDll(fileName, &dll); if (HGBASE_ERR_OK != ret) { ret = HGBase_CreateDll(sanePath, &dll); if (HGBASE_ERR_OK != ret) { return ret; } } SANEAPI saneAPI; ret = FindFunctions(dll, saneManu, &saneAPI); if (HGBASE_ERR_OK != ret) { HGBase_DestroyDll(dll); dll = NULL; return ret; } if (SANE_STATUS_GOOD != saneAPI.sane_init_api(NULL, NULL)) { HGBase_DestroyDll(m_dll); m_dll = NULL; return HGSANE_ERR_FAIL; } m_manuName = saneManu; m_dll = dll; memcpy(&m_saneApi, &saneAPI, sizeof(SANEAPI)); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::Close() { assert(NULL != m_dll); if (!m_listDeviceImpl.empty()) { return HGBASE_ERR_FAIL; } m_saneApi.sane_exit_api(); HGBase_DestroyDll(m_dll); m_dll = NULL; m_managerImpl->RemoveSource(this); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::GetName(HGChar* name, HGUInt maxLen) { if (NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } if (maxLen < m_manuName.size() + 1) return HGBASE_ERR_FAIL; strcpy(name, m_manuName.c_str()); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::GetDeviceCount(HGUInt* count) { if (NULL == count) { return HGBASE_ERR_INVALIDARG; } const SANE_Device** device_list; if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE)) { return HGSANE_ERR_FAIL; } *count = 0; const SANE_Device** p; for (p = device_list; *p != NULL; ++p) ++(*count); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::GetDeviceName(HGUInt index, HGChar* name, HGUInt maxLen) { if (NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } const SANE_Device** device_list; if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE)) { return HGSANE_ERR_FAIL; } HGUInt count = 0; const SANE_Device** p; for (p = device_list; *p != NULL; ++p) ++count; if (index >= count) return HGBASE_ERR_INVALIDARG; if (NULL == device_list[index]->name) return HGBASE_ERR_FAIL; if (maxLen < strlen(device_list[index]->name) + 1) return HGBASE_ERR_FAIL; strcpy(name, device_list[index]->name); return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::OpenDevice(HGUInt index, HGSaneDeviceImpl** deviceImpl, HGChar* errInfo, HGUInt errInfoLen) { if (NULL == deviceImpl) { return HGBASE_ERR_INVALIDARG; } const SANE_Device** device_list; if (SANE_STATUS_GOOD != m_saneApi.sane_get_devices_api(&device_list, SANE_TRUE)) { return HGSANE_ERR_FAIL; } HGUInt count = 0; const SANE_Device** p; for (p = device_list; *p != NULL; ++p) ++count; if (index >= count) return HGBASE_ERR_INVALIDARG; HGSaneDeviceImpl* newDeviceImpl = new HGSaneDeviceImpl(this); HGResult ret = newDeviceImpl->Open(device_list[index]->name, errInfo, errInfoLen); if (HGBASE_ERR_OK != ret) { delete newDeviceImpl; return ret; } m_listDeviceImpl.push_back(newDeviceImpl); *deviceImpl = newDeviceImpl; return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::OpenSelectedDevice(HGWindow parent, class HGSaneDeviceImpl** deviceImpl) { if (NULL == deviceImpl) { return HGBASE_ERR_INVALIDARG; } std::vector devs; HGUInt count = 0; GetDeviceCount(&count); for (HGUInt i = 0; i < count; ++i) { HGChar name[256] = {0}; GetDeviceName(i, name, 256); SANE_Handle handle = NULL; m_saneApi.sane_open_api(name, &handle); if (NULL != handle) { HGChar sn[256] = {0}; m_saneApi.sane_control_option_api(handle, (SANE_Int)0x8856, SANE_ACTION_GET_VALUE, sn, NULL); DEVQUEUI dev; dev.id = i + 1; dev.name = name; dev.sn = sn; devs.push_back(dev); m_saneApi.sane_close_api(handle); } } int id = choose_scanner(devs); if (-1 == id) { return HGSANE_ERR_FAIL; } SANE_Handle handle = NULL; char devName[256] = {0}; for (int i = 0; i < devs.size(); ++i) { if (devs[i].id == id) { strcpy(devName, devs[i].name.c_str()); m_saneApi.sane_open_api(devs[i].name.c_str(), &handle); break; } } if (NULL == handle) { return HGSANE_ERR_FAIL; } HGSaneDeviceImpl* newDeviceImpl = new HGSaneDeviceImpl(this); HGResult ret = newDeviceImpl->Init(devName, handle); if (HGBASE_ERR_OK != ret) { delete newDeviceImpl; m_saneApi.sane_close_api(handle); return ret; } m_listDeviceImpl.push_back(newDeviceImpl); *deviceImpl = newDeviceImpl; return HGBASE_ERR_OK; } HGResult HGSaneSourceImpl::FindFunctions(HGDll dll, const HGChar* saneManu, SANEAPI *saneAPI) { HGResult ret = HGBASE_ERR_OK; do { HGChar funcName[256]; sprintf(funcName, "sane_%s_init", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_init_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_exit", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_exit_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_get_devices", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_get_devices_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_open", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_open_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_close", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_close_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_start", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_start_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_read", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_read_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_cancel", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_cancel_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_set_io_mode", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_set_io_mode_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_strstatus", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_strstatus_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_get_parameters", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_get_parameters_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_get_option_descriptor", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_get_option_descriptor_api); if (HGBASE_ERR_OK != ret) break; sprintf(funcName, "sane_%s_control_option", saneManu); ret = HGBase_GetDllProcAddress(dll, funcName, (HGPointer*)&saneAPI->sane_control_option_api); if (HGBASE_ERR_OK != ret) break; } while (0); return ret; } void HGSaneSourceImpl::RemoveDevice(class HGSaneDeviceImpl* deviceImpl) { std::list::iterator iter; for (iter = m_listDeviceImpl.begin(); iter != m_listDeviceImpl.end(); ++iter) { if (*iter == deviceImpl) { m_listDeviceImpl.erase(iter); delete deviceImpl; break; } } } HGSaneDeviceImpl *HGSaneDeviceImpl::m_curDevice = NULL; HGSaneDeviceImpl::HGSaneDeviceImpl(HGSaneSourceImpl* sourceImpl) { m_sourceImpl = sourceImpl; m_devName.clear(); m_devHandle = NULL; m_scanNotify = NULL; m_dpi = 0; m_eventFunc = NULL; m_eventParam = NULL; m_imageFunc = NULL; m_imageParam = NULL; m_stopThread = HGFALSE; m_thread = NULL; m_cancelScan = false; } HGSaneDeviceImpl::~HGSaneDeviceImpl() { } HGResult HGSaneDeviceImpl::Init(const HGChar* devName, SANE_Handle handle) { assert(NULL == m_devHandle); if (NULL == devName || NULL == handle) { return HGBASE_ERR_INVALIDARG; } m_devName = devName; m_sourceImpl->m_saneApi.sane_set_io_mode_api(handle, SANE_FALSE); m_devHandle = handle; char* cfg = apply_current_config(m_devName.c_str(), m_devHandle, &m_sourceImpl->m_saneApi); twain_ui_free(cfg); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::Open(const HGChar* devName, HGChar* errInfo, HGUInt errInfoLen) { assert(NULL == m_devHandle); if (NULL == devName) { return HGBASE_ERR_INVALIDARG; } SANE_Handle handle = NULL; SANE_Status stat = m_sourceImpl->m_saneApi.sane_open_api(devName, &handle); if (SANE_STATUS_GOOD != stat) { if (NULL != errInfo) { const char* err = m_sourceImpl->m_saneApi.sane_strstatus_api(stat); if (NULL != err && errInfoLen >= strlen(err) + 1) { strcpy(errInfo, err); } } return HGSANE_ERR_FAIL; } m_devName = devName; m_sourceImpl->m_saneApi.sane_set_io_mode_api(handle, SANE_FALSE); m_devHandle = handle; char* cfg = apply_current_config(m_devName.c_str(), m_devHandle, &m_sourceImpl->m_saneApi); twain_ui_free(cfg); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::Close() { assert(NULL != m_devHandle); m_sourceImpl->m_saneApi.sane_close_api(m_devHandle); m_devHandle = NULL; m_devName.clear(); m_sourceImpl->RemoveDevice(this); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::GetName(HGChar* name, HGUInt maxLen) { if (NULL == name || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } if (maxLen < m_devName.size() + 1) return HGBASE_ERR_FAIL; strcpy(name, m_devName.c_str()); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::GetCustomInfo(HGSaneDeviceCustomInfo *info) { if (NULL == info) { return HGBASE_ERR_INVALIDARG; } memset(info, 0, sizeof(HGSaneDeviceCustomInfo)); GetValueInt32(0x8852, &info->vid); GetValueInt32(0x8853, &info->pid); GetValueStr256(0x8856, info->sn, sizeof(info->sn)); GetValueStr256(0x8855, info->type, sizeof(info->type)); GetValueStr256(0x8857, info->fwVer, sizeof(info->fwVer)); GetValueStr256(0x8858, info->ip, sizeof(info->ip)); GetValueStr256(0x8859, info->mac, sizeof(info->mac)); GetValueStr256(0x884A, info->driverVer, sizeof(info->driverVer)); GetValueStr256(0x884B, info->vendor, sizeof(info->vendor)); GetValueStr256(0x884C, info->copyright, sizeof(info->copyright)); GetValueStr256(0x884D, info->comUrl, sizeof(info->comUrl)); GetValueStr256(0x884E, info->comTel, sizeof(info->comTel)); GetValueStr256(0x884F, info->comAddr, sizeof(info->comAddr)); GetValueStr256(0x8850, info->comGps, sizeof(info->comGps)); GetValueInt32(0x9902, &info->rollerCount); GetValueInt32(0x8849, &info->totalCount); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::Login(const HGChar *user, const HGChar *pwd) { if (NULL == user || strlen(user) >= 32 || NULL == pwd || strlen(pwd) >= 32) { return HGBASE_ERR_INVALIDARG; } HGChar value[256] = {0}; strcpy(value, user); strcpy(value + 32, pwd); return SetValueStr256(0x9900, value); } HGResult HGSaneDeviceImpl::Logout() { HGChar value[256] = {0}; return SetValueStr256(0x9901, value); } HGResult HGSaneDeviceImpl::ClearRollerCount() { return SetValueInt32(0x9902, 0); } HGResult HGSaneDeviceImpl::GetRollerLife(HGInt *rollerLife) { return GetValueInt32(0x885B, rollerLife); } HGResult HGSaneDeviceImpl::GetDriverLog(const HGChar *fileName) { if (NULL == fileName || strlen(fileName) >= 256) { return HGBASE_ERR_INVALIDARG; } char v[256]; strcpy(v, fileName); SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)0x9903, SANE_ACTION_GET_VALUE, (void*)v, NULL); return (SANE_STATUS_GOOD == status) ? HGBASE_ERR_OK : HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::ClearDriverLog() { HGChar value[256] = {0}; return SetValueStr256(0x9903, value); } HGResult HGSaneDeviceImpl::GetDeviceLog(const HGChar *fileName) { if (NULL == fileName || strlen(fileName) >= 256) { return HGBASE_ERR_INVALIDARG; } char v[256]; strcpy(v, fileName); SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)0x9904, SANE_ACTION_GET_VALUE, (void*)v, NULL); return (SANE_STATUS_GOOD == status) ? HGBASE_ERR_OK : HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::ClearDeviceLog() { HGChar value[256] = {0}; return SetValueStr256(0x9904, value); } HGResult HGSaneDeviceImpl::ShowSettingDlg(HGWindow parent) { int pid = 0; if (SANE_STATUS_GOOD != m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)0x8853, SANE_ACTION_GET_VALUE, &pid, NULL)) { return HGSANE_ERR_DEVICEOFFLINE; } m_curDevice = this; int ret = show_setting_ui(m_devHandle, parent, &m_sourceImpl->m_saneApi, m_devName.c_str(), false, UIResultCallback, nullptr); if (0 != ret) { return HGSANE_ERR_FAIL; } return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::Start(HGWindow parent, HGSane_DeviceEventFunc eventFunc, HGPointer eventParam, HGSane_DeviceImageFunc imageFunc, HGPointer imageParam) { if (NULL != m_thread) { return HGSANE_ERR_FAIL; } int pid = 0; if (SANE_STATUS_GOOD != m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)0x8853, SANE_ACTION_GET_VALUE, &pid, NULL)) { return HGSANE_ERR_DEVICEOFFLINE; } m_curDevice = this; int ret = show_progress_ui(parent, UIResultCallback, &m_scanNotify); if (0 != ret) { return HGSANE_ERR_FAIL; } GetDpi(&m_dpi); m_eventFunc = eventFunc; m_eventParam = eventParam; m_imageFunc = imageFunc; m_imageParam = imageParam; GetScanMode(m_oldScanMode, 256); GetScanCount(&m_oldScanCount); m_stopThread = HGFALSE; m_cancelScan = false; HGBase_OpenThread(ThreadFunc, this, &m_thread); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::StartWithSingleScan(HGWindow parent, HGSane_DeviceEventFunc eventFunc, HGPointer eventParam, HGSane_DeviceImageFunc imageFunc, HGPointer imageParam) { if (NULL != m_thread) { return HGSANE_ERR_FAIL; } int pid = 0; if (SANE_STATUS_GOOD != m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)0x8853, SANE_ACTION_GET_VALUE, &pid, NULL)) { return HGSANE_ERR_DEVICEOFFLINE; } m_curDevice = this; int ret = show_progress_ui(parent, UIResultCallback, &m_scanNotify); if (0 != ret) { return HGSANE_ERR_FAIL; } GetDpi(&m_dpi); m_eventFunc = eventFunc; m_eventParam = eventParam; m_imageFunc = imageFunc; m_imageParam = imageParam; GetScanMode(m_oldScanMode, 256); GetScanCount(&m_oldScanCount); HGChar newScanMode[256] = {0}; strcpy(newScanMode, OPTION_VALUE_SMZS_SMZDZS); SetScanMode(newScanMode); SetScanCount(1); m_stopThread = HGFALSE; m_cancelScan = false; HGBase_OpenThread(ThreadFunc, this, &m_thread); return HGBASE_ERR_OK; } void HGSaneDeviceImpl::UIResultCallback(ui_result result) { assert(NULL != m_curDevice); assert(result != UI_RESULT_START_SCAN); if (result == UI_RESULT_CLOSE_NORMAL) { if (NULL != m_curDevice->m_thread) { m_curDevice->m_stopThread = HGTRUE; m_curDevice->m_sourceImpl->m_saneApi.sane_cancel_api(m_curDevice->m_devHandle); HGBase_CloseThread(m_curDevice->m_thread); m_curDevice->m_thread = NULL; if (NULL != m_curDevice->m_eventFunc) m_curDevice->m_eventFunc((HGSaneDevice)m_curDevice, HGSANE_EVENT_TYPE_SCANFINISHED, m_curDevice->m_eventParam); m_curDevice->SetScanMode(m_curDevice->m_oldScanMode); m_curDevice->SetScanCount(m_curDevice->m_oldScanCount); } close_ui(UI_INDICATOR); } else if (result == UI_RESULT_CLOSE_CANCEL) { if (NULL != m_curDevice->m_thread) { m_curDevice->m_cancelScan = true; m_curDevice->m_sourceImpl->m_saneApi.sane_cancel_api(m_curDevice->m_devHandle); } } else if (result == UI_RESULT_CLOSE_SETTING) { close_ui(UI_SETTING); } } void HGAPI HGSaneDeviceImpl::ThreadFunc(HGThread thread, HGPointer param) { (void)thread; HGSaneDeviceImpl *p = (HGSaneDeviceImpl *)param; SANEAPI &saneAPI = m_curDevice->m_sourceImpl->m_saneApi; if (NULL != p->m_eventFunc) p->m_eventFunc((HGSaneDevice)p, HGSANE_EVENT_TYPE_WORKING, p->m_eventParam); if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_WORKING, NULL, 0); SANE_Status stat = saneAPI.sane_start_api(p->m_devHandle); // 获取设置界面选择的双张处理方式 HGUInt doubleImgStat = HGBASE_ERR_OK; p->GetDoubleImgStatus(&doubleImgStat); if (SANE_STATUS_GOOD != stat) { if ((SCANNER_ERR_DEVICE_DOUBLE_FEEDING == stat && HGSANE_ERR_UI_RESERVE_CHECK != doubleImgStat)) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat), (int)stat); if (HGSANE_ERR_UI_DISCARD_STOP == doubleImgStat) return; } else if (SCANNER_ERR_DEVICE_DOUBLE_FEEDING != stat) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat), (int)stat); return; } } // 双张图像处理的返回值 HGUInt doubleImgRet = HGBASE_ERR_OK; bool clickedReserveImg = false; while (!p->m_stopThread) { SANE_Parameters params; memset(¶ms, 0, sizeof(SANE_Parameters)); SANE_Status stat1 = saneAPI.sane_get_parameters_api(p->m_devHandle, ¶ms); if (SANE_STATUS_GOOD != stat1 && SCANNER_ERR_DEVICE_DOUBLE_FEEDING != stat1) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat1), (int)stat1); break; } HGUInt bufferSize = params.bytes_per_line * params.lines; HGByte *buffer = (HGByte *)malloc(bufferSize); if (NULL == buffer) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(SANE_STATUS_NO_MEM), (int)SANE_STATUS_NO_MEM); break; } SANE_Int readSize = 0; SANE_Status stat2 = SANE_STATUS_GOOD; while (SANE_STATUS_EOF != stat2) { SANE_Int len = 0; stat2 = saneAPI.sane_read_api(p->m_devHandle, buffer + readSize, bufferSize - readSize, &len); readSize += len; if (SANE_STATUS_GOOD != stat2) { break; } } if (SANE_STATUS_GOOD == stat2) { // bufferSize空间不够 free(buffer); if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(SANE_STATUS_NO_MEM), (int)SANE_STATUS_NO_MEM); break; } else if (SANE_STATUS_EOF == stat2) { if (0 == readSize) { free(buffer); if (p->m_cancelScan) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(SANE_STATUS_CANCELLED), (int)SANE_STATUS_CANCELLED); } else { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, NULL, 0); } break; } if (readSize != params.bytes_per_line * params.lines) { free(buffer); if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(SANE_STATUS_IO_ERROR), (int)SANE_STATUS_IO_ERROR); break; } } else { free(buffer); if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat2), (int)stat2); break; } if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_IMAGE_OK, NULL, 0); if (nullptr != p->m_imageFunc) { HGUInt imgType = 0; if (params.format == SANE_FRAME_GRAY) { if (1 == params.depth) imgType = HGBASE_IMGTYPE_BINARY; else if (8 == params.depth) imgType = HGBASE_IMGTYPE_GRAY; } else if (params.format == SANE_FRAME_RGB) { imgType = HGBASE_IMGTYPE_RGB; } HGImageInfo imgInfo = { (HGUInt)params.pixels_per_line, (HGUInt)params.lines, imgType, (HGUInt)params.bytes_per_line, HGBASE_IMGORIGIN_TOP }; HGImage img = NULL; HGBase_CreateImageWithData(buffer, &imgInfo, &img); if (NULL != img) { HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi); if (HGBASE_ERR_OK == doubleImgRet && SCANNER_ERR_DEVICE_DOUBLE_FEEDING == stat && HGSANE_ERR_UI_RESERVE_CHECK == doubleImgStat) { // 第一个双张图片 doubleImgRet = p->m_imageFunc((HGSaneDevice)p, img, HGSANE_IMAGE_TYPE_DOUBLE, p->m_imageParam); if (HGSANE_ERR_IMAGE_RESERVE == doubleImgRet) clickedReserveImg = true; } else { // 普通图片或第二个双张图片 p->m_imageFunc((HGSaneDevice)p, img, HGSANE_IMAGE_TYPE_NORMAL, p->m_imageParam); doubleImgRet = HGBASE_ERR_OK; } HGBase_DestroyImage(img); } } free(buffer); buffer = NULL; bufferSize = 0; if (HGSANE_ERR_IMAGE_DISCARD == doubleImgRet) { saneAPI.sane_cancel_api(p->m_devHandle); if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, NULL, 0); break; } if (!p->m_cancelScan) { stat = saneAPI.sane_start_api(p->m_devHandle); if (SANE_STATUS_NO_DOCS == stat) { if (NULL != p->m_scanNotify) { if (clickedReserveImg) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat), (int)stat); else p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, NULL, 0); } break; } else if (SANE_STATUS_GOOD != stat) { if ((SCANNER_ERR_DEVICE_DOUBLE_FEEDING != stat && HGSANE_ERR_UI_RESERVE_CHECK == doubleImgStat) || HGSANE_ERR_UI_RESERVE_CHECK != doubleImgStat) { if (NULL != p->m_scanNotify) p->m_scanNotify((int)SANE_EVENT_SCAN_FINISHED, (void*)saneAPI.sane_strstatus_api(stat), (int)stat); break; } } if (SANE_STATUS_GOOD == stat) { doubleImgRet = HGBASE_ERR_OK; clickedReserveImg = false; } } } } HGResult HGSaneDeviceImpl::SetValueInt32(HGUInt optionId, HGInt value) { SANE_Int v = (SANE_Int)value; SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)optionId, SANE_ACTION_SET_VALUE, &v, NULL); return (SANE_STATUS_GOOD == status) ? HGBASE_ERR_OK : HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::GetValueInt32(HGUInt optionId, HGInt *value) { SANE_Int v = 0; SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)optionId, SANE_ACTION_GET_VALUE, &v, NULL); if (SANE_STATUS_GOOD != status) { return HGBASE_ERR_FAIL; } *value = (HGInt)v; return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::SetValueStr256(HGUInt optionId, const HGChar *value) { if (NULL == value || strlen(value) >= 256) { return HGBASE_ERR_INVALIDARG; } const char *v = value; SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)optionId, SANE_ACTION_SET_VALUE, (void*)v, NULL); return (SANE_STATUS_GOOD == status) ? HGBASE_ERR_OK : HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::GetValueStr256(HGUInt optionId, HGChar *value, HGUInt maxLen) { if (NULL == value || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } char v[256] = {0}; SANE_Status status = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, (SANE_Int)optionId, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD != status) { return HGBASE_ERR_FAIL; } if (maxLen <= strlen(v)) { return HGBASE_ERR_INVALIDARG; } strcpy(value, v); return HGBASE_ERR_OK; } HGResult HGSaneDeviceImpl::GetDpi(HGInt *dpi) { SANE_Int dev_options = 0; SANE_Int method = 0; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); if (strcmp(opt->name, SANE_STD_OPT_NAME_RESOLUTION) == 0) { SANE_Int value = 0; SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, &method); if (ret == SANE_STATUS_GOOD) { *dpi = (HGInt)value; return HGBASE_ERR_OK; } } } return HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::GetScanMode(HGChar *scanMode, HGUInt maxLen) { if (NULL == scanMode || 0 == maxLen) { return HGBASE_ERR_INVALIDARG; } SANE_Int dev_options = 0; SANE_Int method = 0; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); HGChar *value = (char*)malloc(opt->size * 2 + 4); if (strcmp(opt->name, SANE_STD_OPT_NAME_SCAN_MODE) == 0) { SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, value, &method); if (ret == SANE_STATUS_GOOD) { strcpy(scanMode, value); free(value); return HGBASE_ERR_OK; } } free(value); } return HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::GetScanCount(HGInt *scanCount) { SANE_Int dev_options = 0; SANE_Int method = 0; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); if (strcmp(opt->name, SANE_STD_OPT_NAME_SCAN_COUNT) == 0) { SANE_Int value = 0; SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, &method); if (ret == SANE_STATUS_GOOD) { *scanCount = (HGInt)value; return HGBASE_ERR_OK; } } } return HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::SetScanMode(const HGChar *scanMode) { SANE_Int dev_options = 0; SANE_Int method = 0; SANE_String value = nullptr; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); SANE_String value = (SANE_String)malloc(opt->size * 2 + 4); strcpy(value, scanMode); if (strcmp(opt->name, SANE_STD_OPT_NAME_SCAN_MODE) == 0) { SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_SET_VALUE, value, &method); if (ret == SANE_STATUS_GOOD) { free(value); return HGBASE_ERR_OK; } } free(value); } return HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::SetScanCount(HGInt scanCount) { SANE_Int dev_options = 0; SANE_Int method = 0; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); SANE_Int value = (SANE_Int)scanCount; if (strcmp(opt->name, SANE_STD_OPT_NAME_SCAN_COUNT) == 0) { SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, &method); if (ret == SANE_STATUS_GOOD) { return HGBASE_ERR_OK; } } } return HGBASE_ERR_FAIL; } HGResult HGSaneDeviceImpl::GetDoubleImgStatus(HGUInt *status) { SANE_Int dev_options = 0; SANE_Int method = 0; m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); for (int i = 1; i < dev_options; ++i) { const SANE_Option_Descriptor* opt = m_sourceImpl->m_saneApi.sane_get_option_descriptor_api(m_devHandle, i); if (strcmp(opt->name, SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE) == 0) { char *value = (char*)malloc(opt->size * 2 + 4); SANE_Status ret = m_sourceImpl->m_saneApi.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, value, &method); if (ret == SANE_STATUS_GOOD) { if (0 == strcmp(value, OPTION_VALUE_SZTPCL_SCTXBJY)) *status = HGSANE_ERR_UI_RESERVE_CHECK; else if (0 == strcmp(value, OPTION_VALUE_SZTPCL_SCTXBTZSM)) *status = HGSANE_ERR_UI_RESERVE_STOP; else *status = HGSANE_ERR_UI_DISCARD_STOP; free(value); return HGBASE_ERR_OK; } } } return HGBASE_ERR_FAIL; }