#include "HGLibDeviceImpl.hpp" #include "base/HGInc.h" #include "base/HGInfo.h" #include "base/HGImage.h" #include "HGString.h" const char* GROUP_NAME[] = { NULL, "grp-1", "grp-2", "grp-3", "grp-4" }; const char* OPTION_NAME[] = { NULL, SANE_STD_OPT_NAME_IS_MULTI_OUT, SANE_STD_OPT_NAME_MULTI_OUT_TYPE, SANE_STD_OPT_NAME_COLOR_MODE, SANE_STD_OPT_NAME_BINARY_THRESHOLD, SANE_STD_OPT_NAME_FILTER, SANE_STD_OPT_NAME_RID_MULTIOUT_RED, SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED, SANE_STD_OPT_NAME_ERASE_BACKGROUND, SANE_STD_OPT_NAME_BKG_COLOR_RANGE, SANE_STD_OPT_NAME_SHARPEN, SANE_STD_OPT_NAME_RID_MORR, SANE_STD_OPT_NAME_RID_GRID, SANE_STD_OPT_NAME_ERROR_EXTENSION, SANE_STD_OPT_NAME_NOISE_OPTIMIZE, SANE_STD_OPT_NAME_NOISE_SIZE, SANE_STD_OPT_NAME_PAPER, SANE_STD_OPT_NAME_CUSTOM_AREA, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM, SANE_STD_OPT_NAME_SIZE_CHECK, SANE_STD_OPT_NAME_PAGE, SANE_STD_OPT_NAME_DISCARD_BLANK_SENS, SANE_STD_OPT_NAME_FEED_STRENGTH, SANE_STD_OPT_NAME_TIME_TO_SLEEP, SANE_STD_OPT_NAME_RESOLUTION, SANE_STD_OPT_NAME_IMAGE_QUALITY, SANE_STD_OPT_NAME_EXCHANGE, SANE_STD_OPT_NAME_SPLIT, SANE_STD_OPT_NAME_ANTI_SKEW, SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA, SANE_STD_OPT_NAME_BRIGHTNESS, SANE_STD_OPT_NAME_CONTRAST, SANE_STD_OPT_NAME_GAMMA, SANE_STD_OPT_NAME_IS_PHOTO_MODE, SANE_STD_OPT_NAME_ERASE_BLACK_FRAME, SANE_STD_OPT_NAME_DARK_SAMPLE, SANE_STD_OPT_NAME_THRESHOLD, SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL, SANE_STD_OPT_NAME_MARGIN, SANE_STD_OPT_NAME_FILL_BKG_MODE, SANE_STD_OPT_NAME_IS_ANTI_PERMEATE, SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL, SANE_STD_OPT_NAME_RID_HOLE_L, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L, SANE_STD_OPT_NAME_RID_HOLE_R, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R, SANE_STD_OPT_NAME_RID_HOLE_T, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T, SANE_STD_OPT_NAME_RID_HOLE_B, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B, SANE_STD_OPT_NAME_IS_FILL_COLOR, SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK, SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE, SANE_STD_OPT_NAME_IS_CHECK_STAPLE, SANE_STD_OPT_NAME_SCAN_MODE, SANE_STD_OPT_NAME_SCAN_COUNT, SANE_STD_OPT_NAME_TEXT_DIRECTION, SANE_STD_OPT_NAME_IS_ROTATE_BKG_180, SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR, SANE_STD_OPT_NAME_DOG_EAR_SIZE, SANE_STD_OPT_NAME_IS_CHECK_ASKEW, SANE_STD_OPT_NAME_ASKEW_RANGE, SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH, SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE, SANE_STD_OPT_NAME_WAIT_TO_SCAN, SANE_STD_OPT_NAME_REVERSE_01, SANE_STD_OPT_NAME_FOLD_TYPE, SANE_STD_OPT_NAME_COLOR_CORRECTION, SANE_STD_OPT_NAME_WAIT_SCAN_EXIT }; const char* OPTION_ENUMVALUE[] = { NULL, OPTION_VALUE_DLSCLX_W, OPTION_VALUE_DLSCLX_CS_HD_HB, OPTION_VALUE_DLSCLX_CS_HD, OPTION_VALUE_DLSCLX_CS_HB, OPTION_VALUE_DLSCLX_HD_HB, OPTION_VALUE_YSMS_24WCS, OPTION_VALUE_YSMS_256JHD, OPTION_VALUE_YSMS_HB, OPTION_VALUE_YSMS_YSZDSB, OPTION_VALUE_HDHHBTX_CSYZQ_BCS, OPTION_VALUE_HDHHBTX_CSYZQ_CHS, OPTION_VALUE_HDHHBTX_CSYZQ_CLS, OPTION_VALUE_HDHHBTX_CSYZQ_CHULANSE, OPTION_VALUE_HDHHBTX_CSYZQ_HSZQ, OPTION_VALUE_HDHHBTX_CSYZQ_LSZQ, OPTION_VALUE_HDHHBTX_CSYZQ_LANSEZENGQIANG, OPTION_VALUE_RHYMH_W, OPTION_VALUE_RHYMH_RH, OPTION_VALUE_RHYMH_JYBRH, OPTION_VALUE_RHYMH_MH, OPTION_VALUE_RHYMH_JYBMH, OPTION_VALUE_ZZCC_A3, OPTION_VALUE_ZZCC_8K, OPTION_VALUE_ZZCC_A4, OPTION_VALUE_ZZCC_A4HX, OPTION_VALUE_ZZCC_16K, OPTION_VALUE_ZZCC_16KHX, OPTION_VALUE_ZZCC_A5, OPTION_VALUE_ZZCC_A5HX, OPTION_VALUE_ZZCC_A6, OPTION_VALUE_ZZCC_A6HX, OPTION_VALUE_ZZCC_B4, OPTION_VALUE_ZZCC_B5, OPTION_VALUE_ZZCC_B5HX, OPTION_VALUE_ZZCC_B6, OPTION_VALUE_ZZCC_B6HX, OPTION_VALUE_ZZCC_Letter, OPTION_VALUE_ZZCC_LetterHX, OPTION_VALUE_ZZCC_DoubleLetter, OPTION_VALUE_ZZCC_LEGAL, OPTION_VALUE_ZZCC_PPYSCC, OPTION_VALUE_ZZCC_ZDSMCCZDCQ, OPTION_VALUE_ZZCC_ZDSMCC, OPTION_VALUE_ZZCC_SLSJ, OPTION_VALUE_SMYM_DM, OPTION_VALUE_SMYM_SM, OPTION_VALUE_SMYM_TGKBYTY, OPTION_VALUE_SMYM_TGKBYFPZ, OPTION_VALUE_SMYM_DZ, OPTION_VALUE_HZ_W, OPTION_VALUE_HZ_SDYX, OPTION_VALUE_HZ_HZYX, OPTION_VALUE_BJTCFS_TDBX, OPTION_VALUE_BJTCFS_ADBX, OPTION_VALUE_FZSTDJ_R, OPTION_VALUE_FZSTDJ_JR, OPTION_VALUE_FZSTDJ_YB, OPTION_VALUE_FZSTDJ_JQ, OPTION_VALUE_FZSTDJ_Q, OPTION_VALUE_SZTPCL_DQTXBTZSM, OPTION_VALUE_SZTPCL_DQTXBJXSM, OPTION_VALUE_SZTPCL_SCTXBTZSM, OPTION_VALUE_SZTPCL_SCTXBJXSM, OPTION_VALUE_SMZS_LXSM, OPTION_VALUE_SMZS_SMZDZS, OPTION_VALUE_WGFX_0, OPTION_VALUE_WGFX_90, OPTION_VALUE_WGFX_180, OPTION_VALUE_WGFX__90, OPTION_VALUE_WGFX_ZDWBFXSB, OPTION_VALUE_FZQD_R, OPTION_VALUE_FZQD_YB, OPTION_VALUE_FZQD_Q, OPTION_VALUE_XMSJ_BXM, OPTION_VALUE_XMSJ_WFZ, OPTION_VALUE_XMSJ_SFZ, OPTION_VALUE_XMSJ_BXS, OPTION_VALUE_XMSJ_YXS, OPTION_VALUE_XMSJ_LXS, OPTION_VALUE_XMSJ_SXS, OPTION_VALUE_ZYDZ, OPTION_VALUE_SXDZ, OPTION_VALUE_ZDDZ, "15s", "30s", "60s", "2min", "4min", "8min" }; struct DeviceParam { DeviceParam() { valueType = 0; intValue = 0; doubleValue = 0; boolValue = false; rangeType = 0; intValueMin = 0; intValueMax = 0; doubleValueMin = 0; doubleValueMax = 0; } // 配置名 std::string option; int valueType; std::string stringValue; int intValue; double doubleValue; bool boolValue; int rangeType; std::vector stringValueList; std::vector intValueList; std::vector doubleValueList; int intValueMin; int intValueMax; double doubleValueMin; double doubleValueMax; }; struct DeviceParamsGroup { std::string groupName; std::vector devParams; }; HGLibDeviceHotPlugEventFunc HGLibDeviceImpl::m_hotPlugEventFunc = NULL; HGPointer HGLibDeviceImpl::m_hotPlugEventParam = NULL; HGBool HGLibDeviceImpl::m_init = HGFALSE; std::map HGLibDeviceImpl::m_deviceList; HGLibDeviceImpl::HGLibDeviceImpl() { m_lock = NULL; HGBase_CreateLock(&m_lock); m_devHandle = NULL; m_devName.clear(); m_dpi = 0; m_scanning = HGFALSE; m_scanEvent = NULL; m_eventFunc = NULL; m_eventParam = NULL; m_imageFunc = NULL; m_imageParam = NULL; m_statusCode = SANE_STATUS_GOOD; } HGLibDeviceImpl::~HGLibDeviceImpl() { HGBase_DestroyLock(m_lock); m_lock = NULL; } HGBool HGLibDeviceImpl::Init(HGLibDeviceHotPlugEventFunc func, HGPointer param) { if (m_init) { return HGFALSE; } 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; return HGFALSE; } m_init = HGTRUE; return HGTRUE; } HGBool HGLibDeviceImpl::Deinit() { if (!m_init) { return HGFALSE; } if (!m_deviceList.empty()) { return HGFALSE; } sane_exit(); m_hotPlugEventFunc = NULL; m_hotPlugEventParam = NULL; m_init = HGFALSE; return HGTRUE; } HGChar** HGLibDeviceImpl::GetNameList() { const SANE_Device **device = NULL; sane_get_devices(&device, SANE_TRUE); if (NULL == device) { return NULL; } std::vector devNameList; const SANE_Device** p = device; while (NULL != *p) { devNameList.push_back((*p)->name); ++p; } if (devNameList.empty()) { return NULL; } HGChar** nameList = (HGChar **)malloc((devNameList.size() + 1) * sizeof(HGChar *)); if (NULL != nameList) { nameList[devNameList.size()] = NULL; for (int i = 0; i < (int)devNameList.size(); ++i) { nameList[i] = (HGChar *)malloc(devNameList[i].size() + 1); if (NULL != nameList[i]) strcpy(nameList[i], devNameList[i].c_str()); } } return nameList; } HGBool HGLibDeviceImpl::ReleaseNameList(HGChar** deviceName) { if (NULL == deviceName) { return HGFALSE; } HGChar** p = deviceName; while (0 != *p) { free(*p); ++p; } free(deviceName); return HGTRUE; } 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::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::GetSN(HGChar* sn, HGUInt maxLen) { if (NULL == sn || 0 == maxLen) { return HGFALSE; } assert(NULL != m_devHandle); std::string serialNum; unsigned int serialNumLen = 0; m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_SERIAL, NULL, &serialNumLen); if (SANE_STATUS_NO_MEM == m_statusCode && serialNumLen) { serialNum.resize(serialNumLen); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_SERIAL, &serialNum[0], &serialNumLen); } if (serialNum.empty() || maxLen < serialNum.size() + 1) { return HGFALSE; } strcpy(sn, serialNum.c_str()); return HGTRUE; } HGBool HGLibDeviceImpl::GetFWVersion(HGChar* fwVersion, HGUInt maxLen) { if (NULL == fwVersion || 0 == maxLen) { return HGFALSE; } assert(NULL != m_devHandle); std::string versionNum; unsigned int versionNumLen = 0; m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_HARDWARE_VERSION, NULL, &versionNumLen); if (SANE_STATUS_NO_MEM == m_statusCode && versionNumLen) { versionNum.resize(versionNumLen); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_HARDWARE_VERSION, &versionNum[0], &versionNumLen); } if (versionNum.empty() || maxLen < versionNum.size() + 1) { return HGFALSE; } strcpy(fwVersion, versionNum.c_str()); return HGTRUE; } HGBool HGLibDeviceImpl::SetParam(HGUInt option, const HGVoid* data) { assert(NULL != m_devHandle); if (NULL == data) return HGFALSE; const char *optionName = GetOptionName(option); if (NULL == optionName) return HGFALSE; HGBool ret = HGFALSE; SANE_Int num_dev_options = 0; m_statusCode = sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(optionName, name)) { if (SANE_TYPE_STRING == desp->type) { SANE_Char* value = (SANE_Char*)GetOptionEnumValue(*(HGUInt*)data); if (NULL != value) { m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, value, NULL); if (SANE_STATUS_GOOD == m_statusCode) ret = HGTRUE; } } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = (SANE_Int)(*(HGInt*)data); m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL); if (SANE_STATUS_GOOD == m_statusCode) ret = HGTRUE; } else if (SANE_TYPE_FIXED == desp->type) { SANE_Fixed value = SANE_FIX(*(HGDouble*)data); m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL); if (SANE_STATUS_GOOD == m_statusCode) ret = HGTRUE; } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = (SANE_Bool)(*(HGBool*)data); m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL); if (SANE_STATUS_GOOD == m_statusCode) ret = HGTRUE; } break; } } return ret; } HGLibDeviceParamGroup* HGLibDeviceImpl::GetParamGroupList(HGUInt* count) { assert(NULL != m_devHandle); if (NULL == count) return NULL; std::vector devParams; SANE_Int num_dev_options = 0; m_statusCode = sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (SANE_TYPE_GROUP == desp->type) { DeviceParamsGroup group; group.groupName = name; devParams.push_back(group); } else if (SANE_TYPE_STRING == desp->type) { char value[256] = { 0 }; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, value, NULL); DeviceParam devParam; devParam.option = name; devParam.valueType = HGLIB_OPTION_VALUETYPE_ENUM; devParam.stringValue = value; assert(SANE_CONSTRAINT_STRING_LIST == desp->constraint_type); devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_ENUMLIST; const SANE_String_Const* p = desp->constraint.string_list; while (NULL != *p) { devParam.stringValueList.push_back(*p); ++p; } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.option = name; devParam.valueType = HGLIB_OPTION_VALUETYPE_INT; devParam.intValue = (int)value; if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_INTLIST; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.intValueList.push_back(p[i + 1]); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_INTRANGE; devParam.intValueMin = desp->constraint.range->min; devParam.intValueMax = desp->constraint.range->max; } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } else if (SANE_TYPE_FIXED == desp->type) { SANE_Word value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.option = name; devParam.valueType = HGLIB_OPTION_VALUETYPE_DOUBLE; devParam.doubleValue = SANE_UNFIX(value); if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.doubleValueList.push_back(SANE_UNFIX(p[i + 1])); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_DOUBLERANGE; devParam.doubleValueMin = SANE_UNFIX(desp->constraint.range->min); devParam.doubleValueMax = SANE_UNFIX(desp->constraint.range->max); } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.option = name; devParam.valueType = HGLIB_OPTION_VALUETYPE_BOOL; devParam.boolValue = (bool)value; devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_NULL; assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } } *count = (HGUInt)devParams.size(); HGLibDeviceParamGroup* paramGroup = (HGLibDeviceParamGroup*)malloc((*count) * sizeof(HGLibDeviceParamGroup)); if (NULL != paramGroup) { for (int i = 0; i < (int)devParams.size(); ++i) { paramGroup[i].group = GetGroupName(devParams[i].groupName.c_str()); paramGroup[i].paramCount = (HGUInt)devParams[i].devParams.size(); paramGroup[i].param = (HGLibDeviceParam*)malloc(paramGroup[i].paramCount * sizeof(HGLibDeviceParam)); if (NULL != paramGroup[i].param) { for (int j = 0; j < (int)devParams[i].devParams.size(); ++j) { HGLibDeviceParam& dest = paramGroup[i].param[j]; DeviceParam& src = devParams[i].devParams[j]; dest.option = GetOptionName(src.option.c_str()); dest.type = src.valueType; if (HGLIB_OPTION_VALUETYPE_INT == dest.type) dest.intValue = src.intValue; else if (HGLIB_OPTION_VALUETYPE_DOUBLE == dest.type) dest.doubleValue = src.doubleValue; else if (HGLIB_OPTION_VALUETYPE_BOOL == dest.type) dest.boolValue = (HGBool)src.boolValue; else if (HGLIB_OPTION_VALUETYPE_ENUM == dest.type) dest.enumValue = GetOptionEnumValue(src.stringValue.c_str()); dest.rangeType = src.rangeType; if (HGLIB_OPTION_VALUERANGETYPE_INTLIST == dest.rangeType) { dest.intValueList.count = (HGUInt)src.intValueList.size(); dest.intValueList.value = (HGInt *)malloc(dest.intValueList.count * sizeof(HGInt)); if (NULL != dest.intValueList.value) { for (int k = 0; k < (int)src.intValueList.size(); ++k) { dest.intValueList.value[k] = src.intValueList[k]; } } } else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST == dest.rangeType) { dest.doubleValueList.count = (HGUInt)src.doubleValueList.size(); dest.doubleValueList.value = (HGDouble*)malloc(dest.doubleValueList.count * sizeof(HGDouble)); if (NULL != dest.doubleValueList.value) { for (int k = 0; k < (int)src.doubleValueList.size(); ++k) { dest.doubleValueList.value[k] = src.doubleValueList[k]; } } } else if (HGLIB_OPTION_VALUERANGETYPE_INTRANGE == dest.rangeType) { dest.intValueRange.minValue = src.intValueMin; dest.intValueRange.maxValue = src.intValueMax; } else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLERANGE == dest.rangeType) { dest.doubleValueRange.minValue = src.doubleValueMin; dest.doubleValueRange.maxValue = src.doubleValueMax; } else if (HGLIB_OPTION_VALUERANGETYPE_ENUMLIST == dest.rangeType) { dest.enumValueList.count = (HGUInt)src.stringValueList.size(); dest.enumValueList.value = (HGUInt*)malloc(dest.enumValueList.count * sizeof(HGUInt)); if (NULL != dest.enumValueList.value) { for (int k = 0; k < (int)src.stringValueList.size(); ++k) { dest.enumValueList.value[k] = GetOptionEnumValue(src.stringValueList[k].c_str()); } } } } } } } return paramGroup; } HGLibDeviceParam* HGLibDeviceImpl::GetParam(HGUInt option) { assert(NULL != m_devHandle); const char* optionName = GetOptionName(option); if (NULL == optionName) return NULL; HGLibDeviceParam* param = NULL; SANE_Int num_dev_options = 0; m_statusCode = sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(optionName, name)) { DeviceParam devParam; devParam.option = name; if (SANE_TYPE_STRING == desp->type) { char value[256] = { 0 }; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, value, NULL); devParam.valueType = HGLIB_OPTION_VALUETYPE_ENUM; devParam.stringValue = value; assert(SANE_CONSTRAINT_STRING_LIST == desp->constraint_type); devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_ENUMLIST; const SANE_String_Const* p = desp->constraint.string_list; while (NULL != *p) { devParam.stringValueList.push_back(*p); ++p; } } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); devParam.valueType = HGLIB_OPTION_VALUETYPE_INT; devParam.intValue = (int)value; if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_INTLIST; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.intValueList.push_back(p[i + 1]); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_INTRANGE; devParam.intValueMin = desp->constraint.range->min; devParam.intValueMax = desp->constraint.range->max; } } else if (SANE_TYPE_FIXED == desp->type) { SANE_Word value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); devParam.valueType = HGLIB_OPTION_VALUETYPE_DOUBLE; devParam.doubleValue = SANE_UNFIX(value); if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.doubleValueList.push_back(SANE_UNFIX(p[i + 1])); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_DOUBLERANGE; devParam.doubleValueMin = SANE_UNFIX(desp->constraint.range->min); devParam.doubleValueMax = SANE_UNFIX(desp->constraint.range->max); } } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = 0; m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL); devParam.valueType = HGLIB_OPTION_VALUETYPE_BOOL; devParam.boolValue = (bool)value; devParam.rangeType = HGLIB_OPTION_VALUERANGETYPE_NULL; } assert(0 != devParam.valueType); param = (HGLibDeviceParam*)malloc(sizeof(HGLibDeviceParam)); if (NULL != param) { param->option = GetOptionName(devParam.option.c_str()); param->type = devParam.valueType; if (HGLIB_OPTION_VALUETYPE_INT == param->type) param->intValue = devParam.intValue; else if (HGLIB_OPTION_VALUETYPE_DOUBLE == param->type) param->doubleValue = devParam.doubleValue; else if (HGLIB_OPTION_VALUETYPE_BOOL == param->type) param->boolValue = (HGBool)devParam.boolValue; else if (HGLIB_OPTION_VALUETYPE_ENUM == param->type) param->enumValue = GetOptionEnumValue(devParam.stringValue.c_str()); param->rangeType = devParam.rangeType; if (HGLIB_OPTION_VALUERANGETYPE_INTLIST == param->rangeType) { param->intValueList.count = (HGUInt)devParam.intValueList.size(); param->intValueList.value = (HGInt*)malloc(param->intValueList.count * sizeof(HGInt)); if (NULL != param->intValueList.value) { for (int k = 0; k < (int)devParam.intValueList.size(); ++k) { param->intValueList.value[k] = devParam.intValueList[k]; } } } else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST == param->rangeType) { param->doubleValueList.count = (HGUInt)devParam.doubleValueList.size(); param->doubleValueList.value = (HGDouble*)malloc(param->doubleValueList.count * sizeof(HGDouble)); if (NULL != param->doubleValueList.value) { for (int k = 0; k < (int)devParam.doubleValueList.size(); ++k) { param->doubleValueList.value[k] = devParam.doubleValueList[k]; } } } else if (HGLIB_OPTION_VALUERANGETYPE_INTRANGE == param->rangeType) { param->intValueRange.minValue = devParam.intValueMin; param->intValueRange.maxValue = devParam.intValueMax; } else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLERANGE == param->rangeType) { param->doubleValueRange.minValue = devParam.doubleValueMin; param->doubleValueRange.maxValue = devParam.doubleValueMax; } else if (HGLIB_OPTION_VALUERANGETYPE_ENUMLIST == param->rangeType) { param->enumValueList.count = (HGUInt)devParam.stringValueList.size(); param->enumValueList.value = (HGUInt*)malloc(param->enumValueList.count * sizeof(HGUInt)); if (NULL != param->enumValueList.value) { for (int k = 0; k < (int)devParam.stringValueList.size(); ++k) { param->enumValueList.value[k] = GetOptionEnumValue(devParam.stringValueList[k].c_str()); } } } } break; } } return param; } HGBool HGLibDeviceImpl::ReleaseParamGroupList(HGLibDeviceParamGroup* paramGroup, HGUInt count) { if (NULL == paramGroup || 0 == count) { return HGFALSE; } for (HGUInt i = 0; i < count; ++i) { for (HGUInt j = 0; j < paramGroup[i].paramCount; ++j) { if (HGLIB_OPTION_VALUERANGETYPE_INTLIST == paramGroup[i].param[j].rangeType) free(paramGroup[i].param[j].intValueList.value); else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST == paramGroup[i].param[j].rangeType) free(paramGroup[i].param[j].doubleValueList.value); else if (HGLIB_OPTION_VALUERANGETYPE_ENUMLIST == paramGroup[i].param[j].rangeType) free(paramGroup[i].param[j].enumValueList.value); } free(paramGroup[i].param); } free(paramGroup); return HGTRUE; } HGBool HGLibDeviceImpl::ReleaseParam(HGLibDeviceParam* param) { if (NULL == param) { return HGFALSE; } if (HGLIB_OPTION_VALUERANGETYPE_INTLIST == param->rangeType) free(param->intValueList.value); else if (HGLIB_OPTION_VALUERANGETYPE_DOUBLELIST == param->rangeType) free(param->doubleValueList.value); else if (HGLIB_OPTION_VALUERANGETYPE_ENUMLIST == param->rangeType) free(param->enumValueList.value); free(param); return HGTRUE; } HGBool HGLibDeviceImpl::ResetParam() { assert(NULL != m_devHandle); HGBool ret = HGFALSE; SANE_Int num_dev_options = 0; m_statusCode = sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(SANE_STD_OPT_NAME_RESTORE, name) && SANE_TYPE_BUTTON == desp->type) { m_statusCode = sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, NULL, NULL); if (SANE_STATUS_GOOD == m_statusCode) ret = HGTRUE; break; } } return ret; } HGBool HGLibDeviceImpl::IsPaperOn() { SANE_Bool isOn = SANE_FALSE; unsigned int len = sizeof(SANE_Bool); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_PAPER_ON, &isOn, &len); if (SANE_STATUS_GOOD == m_statusCode && isOn) return HGTRUE; return HGFALSE; } HGInt HGLibDeviceImpl::GetStatus() { SANE_Bool isOn = SANE_FALSE; unsigned int len = sizeof(SANE_Bool); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_GET_PAPER_ON, &isOn, &len); if (SANE_STATUS_GOOD == m_statusCode) return isOn ? 1 : 0; return -1; } HGBool HGLibDeviceImpl::Restart() { SANE_Power stat = SANE_POWER_RESTART; unsigned int len = sizeof(SANE_Power); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_SET_POWER_LEVEL, &stat, &len); if (SANE_STATUS_GOOD == m_statusCode) return HGTRUE; return HGFALSE; } HGBool HGLibDeviceImpl::ShutDown() { SANE_Power stat = SANE_POWER_SHUTDOWN; unsigned int len = sizeof(SANE_Power); m_statusCode = sane_io_control(m_devHandle, IO_CTRL_CODE_SET_POWER_LEVEL, &stat, &len); if (SANE_STATUS_GOOD == m_statusCode) return HGTRUE; return HGFALSE; } HGBool HGLibDeviceImpl::StartScan(HGLibDeviceScanEventFunc eventFunc, HGPointer eventParam, HGLibDeviceScanImageFunc imageFunc, HGPointer imageParam) { HGBool ret = HGFALSE; HGBase_EnterLock(m_lock); if (!m_scanning) { HGLibDeviceParam* devParam = GetParam(HGLIB_OPTION_NAME_FBL); if (NULL != devParam && devParam->type == HGLIB_OPTION_VALUETYPE_INT) { m_dpi = devParam->intValue; ReleaseParam(devParam); } HGBase_CreateEvent(HGFALSE, HGFALSE, &m_scanEvent); assert(NULL != m_scanEvent); m_eventFunc = eventFunc; m_eventParam = eventParam; m_imageFunc = imageFunc; m_imageParam = imageParam; m_scanning = HGTRUE; m_statusCode = sane_start(m_devHandle); if (SANE_STATUS_GOOD != m_statusCode) { m_scanning = HGFALSE; m_eventFunc = NULL; m_eventParam = NULL; m_imageFunc = NULL; m_imageParam = NULL; HGBase_DestroyEvent(m_scanEvent); m_scanEvent = NULL; m_dpi = 0; } else { ret = HGTRUE; } } HGBase_LeaveLock(m_lock); return ret; } HGBool HGLibDeviceImpl::StopScan() { HGBool ret = HGFALSE; HGBase_EnterLock(m_lock); if (m_scanning) { sane_cancel(m_devHandle); 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; m_dpi = 0; ret = HGTRUE; } HGBase_LeaveLock(m_lock); return ret; } HGBool HGLibDeviceImpl::StopScanAsyn() { HGBool ret = HGFALSE; HGBase_EnterLock(m_lock); if (m_scanning) { sane_cancel(m_devHandle); ret = HGTRUE; } HGBase_LeaveLock(m_lock); return ret; } HGInt HGLibDeviceImpl::GetOperateCode() { return m_statusCode; } const char* HGLibDeviceImpl::GetGroupName(HGUInt group) { if (group > HGLIB_GROUP_NAME_PAPERFEEDING) return NULL; return GROUP_NAME[group]; } HGUInt HGLibDeviceImpl::GetGroupName(const char* group) { if (NULL == group) return 0; HGUInt ret = 0; for (int i = 1; i < sizeof(GROUP_NAME) / sizeof(const char*); ++i) { if (0 == strcmp(group, GROUP_NAME[i])) { ret = i; break; } } return ret; } const char* HGLibDeviceImpl::GetOptionName(HGUInt option) { if (option > HGLIB_OPTION_NAME_DZSMTCSJ) return NULL; return OPTION_NAME[option]; } HGUInt HGLibDeviceImpl::GetOptionName(const char* option) { if (NULL == option) return 0; HGUInt ret = 0; for (int i = 1; i < sizeof(OPTION_NAME) / sizeof(const char*); ++i) { if (0 == strcmp(option, OPTION_NAME[i])) { ret = i; break; } } return ret; } const char* HGLibDeviceImpl::GetOptionEnumValue(HGUInt enumValue) { if (enumValue > HGLIB_OPTION_ENUMVALUE_DZSMTCSJ_8MIN) return NULL; return OPTION_ENUMVALUE[enumValue]; } HGUInt HGLibDeviceImpl::GetOptionEnumValue(const char* enumValue) { if (NULL == enumValue) return 0; HGUInt ret = 0; for (int i = 1; i < sizeof(OPTION_ENUMVALUE) / sizeof(const char*); ++i) { if (0 == strcmp(enumValue, OPTION_ENUMVALUE[i])) { ret = i; break; } } return ret; } 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()); 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()); 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); } HGLibDeviceScanEventFunc eventFunc = deviceImpl->m_eventFunc; HGPointer eventParam = deviceImpl->m_eventParam; HGBase_SetEvent(deviceImpl->m_scanEvent); HGBase_EnterLock(deviceImpl->m_lock); HGBase_DestroyEvent(deviceImpl->m_scanEvent); deviceImpl->m_scanEvent = NULL; deviceImpl->m_eventFunc = NULL; deviceImpl->m_eventParam = NULL; deviceImpl->m_imageFunc = NULL; deviceImpl->m_imageParam = NULL; deviceImpl->m_scanning = HGFALSE; deviceImpl->m_dpi = 0; HGBase_LeaveLock(deviceImpl->m_lock); if (NULL != eventFunc) { eventFunc((HGLibDevice)deviceImpl, HGLIB_DEVSCAN_EVENT_END, HGFALSE, NULL, eventParam); } } 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) { HGBase_SetImageDpi(img, deviceImpl->m_dpi, deviceImpl->m_dpi); deviceImpl->m_imageFunc((HGLibDevice)deviceImpl, (HGLibImage)img, deviceImpl->m_imageParam); HGBase_DestroyImage(img); } } } break; } return 0; }