在SANE组件中处理第三方SANE-APP定义的与华高参数不一致的属性

This commit is contained in:
gb 2022-05-23 11:52:53 +08:00
parent 724276309e
commit c040b59488
10 changed files with 558 additions and 118 deletions

View File

@ -50,6 +50,7 @@ hg_scanner::hg_scanner(ScannerSerial serial
wait_usb_.set_debug_info("USB");
wait_img_.set_debug_info("Image");
wait_usb_result_.set_debug_info("start");
thread_usb_read_.reset(new std::thread(&hg_scanner::thread_handle_usb, this));
thread_img_handle_.reset(new std::thread(&hg_scanner::thread_image_handle, this));
}
@ -604,16 +605,6 @@ int hg_scanner::restore(int setting_no)
std::string val("");
sprintf(key, "%d", setting_no);
setting_jsn_.at(key).at("name").get_to(val);
if (val == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
custom_gamma_val_->pt_count_r = custom_gamma_val_->pt_count_g = custom_gamma_val_->pt_count_b = 0;
for (int i = 0; i < ARRAY_SIZE(custom_gamma_val_->table); ++i)
custom_gamma_val_->table[i] = i & 0x0ff;
return SCANNER_ERR_OK;
}
setting_jsn_.at(key).at("type").get_to(val);
if (val == "string")
{
@ -657,16 +648,6 @@ bool hg_scanner::get_default_value(void* buf, json* jsn)
{
std::string type("");
jsn->at("name").get_to(type);
if (type == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
SANE_Int* gma = (SANE_Int*)buf;
for (size_t i = 0; i < sizeof(custom_gamma_val_); ++i)
gma[i] = i & 0x0ff;
return true;
}
jsn->at("type").get_to(type);
if (type == "bool")
{
@ -757,7 +738,8 @@ void hg_scanner::working_begin(void*)
void hg_scanner::working_done(void*)
{
imgs_.Clear();
final_imgs_.Clear();
if(user_cancel_)
final_imgs_.Clear();
while (paths_.Size())
{
remove(paths_.Take().c_str());
@ -1646,9 +1628,6 @@ void hg_scanner::init_settings(const char* json_setting_text)
std::string val("");
sprintf(key, "%d", sn);
setting_jsn_.at(key).at("name").get_to(val);
if (val == KNOWN_OPT_NAME_CUSTOM_GAMMA)
continue;
#ifdef MAPPING_FUNCTION_IN_BASE
setting_jsn_.at(key).at("title").get_to(val);
@ -1710,6 +1689,9 @@ int hg_scanner::try_third_app_handle_start(bool& handled)
handled = !async_io_;
if (handled)
{
while (wait_usb_result_.try_wait())
std::this_thread::sleep_for(std::chrono::milliseconds(3));
if (!wait_img_.is_waiting() || !wait_usb_.is_waiting() || final_imgs_.Size())
ret = SCANNER_ERR_OK;
else if (final_img_index_)
@ -1724,6 +1706,19 @@ int hg_scanner::try_third_app_handle_start(bool& handled)
return ret;
}
int hg_scanner::try_third_app_after_start(int err)
{
if (!async_io_)
{
if (wait_usb_result_.wait(500))
{
if (status_ != SCANNER_ERR_DEVICE_BUSY && status_ != SCANNER_ERR_OK)
err = status_;
}
}
return err;
}
int hg_scanner::notify_ui_working_status(const char* msg, int ev, int status)
{
unsigned int s = status;
@ -2097,17 +2092,12 @@ int hg_scanner::get_setting(int setting_no, char* json_txt_buf, int* len)
HG_VLOG_MINI_2(LOG_LEVEL_FATAL, "!!!option(%d - %s) is not found.\n", setting_no, sn);
text = setting_jsn_.at(sn).dump();
setting_jsn_.at(sn).at("name").get_to(name);
if (name == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
is_gamma = true;
add = 4 * sizeof(custom_gamma_val_);
}
else if (name == KNOWN_OPT_NAME_CUSTOM_AREA_LEFT || name == KNOWN_OPT_NAME_CUSTOM_AREA_RIGHT)
if (name == SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT || name == SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT)
{
is_area_x = true;
add = 20;
}
else if (name == KNOWN_OPT_NAME_CUSTOM_AREA_TOP || name == KNOWN_OPT_NAME_CUSTOM_AREA_BOTTOM)
else if (name == SANE_STD_OPT_NAME_CUSTOM_AREA_TOP || name == SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM)
{
is_area_y = true;
add = 20;
@ -2211,8 +2201,8 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
if (ret == SCANNER_ERR_NO_DATA /*&& final_img_index_ == 0*/)
{
if (status_ != SCANNER_ERR_OK)
ret = status_;
if (status_ != SCANNER_ERR_OK && status_ != SCANNER_ERR_DEVICE_BUSY)
ret = SCANNER_ERR_NO_DATA;
else
{
ii->depth = 8;

View File

@ -217,6 +217,7 @@ protected:
volatile bool user_cancel_;
platform_event wait_usb_;
platform_event wait_img_;
platform_event wait_usb_result_;
usb_io* io_;
std::mutex io_lock_;
bool online_;
@ -259,6 +260,7 @@ protected:
void init_settings(const char* json_setting_text);
int on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作
int try_third_app_handle_start(bool& handled);
int try_third_app_after_start(int err);
// callback to ui ...
int notify_ui_working_status(const char* msg, int ev = SANE_EVENT_STATUS, int status = SCANNER_ERR_OK);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,7 @@
#include "ini_file.h"
#include "../../sdk/include/sane/sane_option_definitions.h"
#include "sane_option.h"
#ifndef VERSION_BUILD
#define VERSION_BUILD 22030
@ -1015,7 +1016,7 @@ scanner_err hg_scanner_control(scanner_handle h, unsigned long code, void* data,
hg_sane_middleware* hg_sane_middleware::inst_ = NULL;
const SANE_Device** hg_sane_middleware::dev_list_ = NULL;
hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr)
hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), std_opt_(nullptr)
{
signal(SIGUSR1, &hg_sane_middleware::device_pnp);
local_utility::char_transfer_init();
@ -1034,6 +1035,8 @@ hg_sane_middleware::~hg_sane_middleware()
hg_scanner_uninitialize();
if (opt_0_)
local_utility::free_memory(opt_0_);
if (std_opt_)
delete std_opt_;
}
const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, int count)
@ -1407,6 +1410,9 @@ void hg_sane_middleware::on_device_closed(scanner_handle h)
cur_vals_.clear();
slave_options_.clear();
master_options_.clear();
if (std_opt_)
delete std_opt_;
std_opt_ = nullptr;
}
SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc)
{
@ -1427,6 +1433,13 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle*
openning_.push_back(od);
*handle = hg_sane_middleware::scanner_handle_to_sane(h);
if (!local_utility::cb_ui_)
{
long count = 0;
hg_scanner_get_parameter(h, 0, NULL, &count);
std_opt_ = new sane_std_opts(count);
}
return SANE_STATUS_GOOD;
}
else if (err == SCANNER_ERR_ACCESS_DENIED)
@ -1576,10 +1589,10 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, json* js
hg_log::log(LOG_LEVEL_DEBUG_INFO, "set \345\210\206\350\276\250\347\216\207 unit to DPI\n");
ret->unit = SANE_UNIT_DPI;
}
else if (strcmp(ret->name, KNOWN_OPT_NAME_CUSTOM_AREA_LEFT) == 0 ||
strcmp(ret->name, KNOWN_OPT_NAME_CUSTOM_AREA_RIGHT) == 0 ||
strcmp(ret->name, KNOWN_OPT_NAME_CUSTOM_AREA_TOP) == 0 ||
strcmp(ret->name, KNOWN_OPT_NAME_CUSTOM_AREA_BOTTOM) == 0)
else if (strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP) == 0 ||
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) == 0)
ret->unit = SANE_UNIT_MM;
//bool enabled = true;
@ -1706,16 +1719,7 @@ bool hg_sane_middleware::get_current_value(scanner_handle handle, int option, vo
jsn->get_value("name", name);
ret = true;
if (name == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
SANE_Int* v = (SANE_Int*)value;
std::vector<std::string> vs;
jsn->get_as_array("cur", vs);
for (int i = 0; i < 3 * 256 && i < vs.size(); ++i)
v[i] = atoi(vs[i].c_str());
}
else if (val == "int")
if (val == "int")
{
int v = 0;
jsn->get_value("cur", v);
@ -2005,6 +2009,14 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h,
}
}
if (ret)
{
if (std_opt_)
std_opt_->init_known_opt(option, ret);
}
else if (std_opt_)
ret = std_opt_->get_option(option);
return ret;
}
SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_Action action, void* value, SANE_Int* after_do)
@ -2032,7 +2044,12 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
}
else
{
if(get_current_value(handle, option, value))
if (std_opt_ && std_opt_->is_known_option(option))
{
std_opt_->get_value(h, option, value);
ret = SANE_STATUS_GOOD;
}
else if(get_current_value(handle, option, value))
ret = SANE_STATUS_GOOD;
}
@ -2042,74 +2059,75 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, SANE_Int option, SANE_
{
SANE_Option_Descriptor* desc = find_stored_descriptor(dev.dev_name.c_str(), option);
bool release_value = false;
if (!desc)
{
HG_VLOG_MINI_1(LOG_LEVEL_FATAL, "Option descriptor %d not found.\n", option);
return SANE_STATUS_UNSUPPORTED;
}
else if (!value && desc->type != SANE_TYPE_BUTTON)
{
if (action == SANE_ACTION_SET_AUTO) // we assume the driver can set the option properbly, and no work to do
{
HG_VLOG_MINI_2(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title);
value = get_default_value(handle, option);
if(!value)
return SANE_STATUS_GOOD;
release_value = true;
}
else
{
HG_VLOG_MINI_2(LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title);
return SANE_STATUS_INVAL;
}
}
if (desc->name == "duplex") // conver SANE_Bool to char*
{
bool dup = (*(SANE_Bool*)value) == SANE_TRUE;
value = local_utility::acquire_memory(desc->size + 4, "");
strcpy((char*)value, dup ? OPTION_VALUE_SMYM_SM : OPTION_VALUE_SMYM_DM);
release_value = true;
}
scanner_err err = SCANNER_ERR_OK;
SANE_Status status = SANE_STATUS_GOOD;
std::string v(hg_sane_middleware::option_value_2_string(desc->type, value));
void* pass = value;
double dv = .0f;
bool bv = false;
int size = desc->size;
scanner_err err = SCANNER_ERR_OK;
if (desc->type == SANE_TYPE_BOOL)
std::string prev(""), v("");
if (std_opt_ && std_opt_->is_known_option(option, &desc))
{
bv = *((SANE_Bool*)value) == SANE_TRUE;
pass = &bv;
size = sizeof(bv);
SANE_Option_Descriptor* known = std_opt_->get_option(option);
prev = hg_sane_middleware::option_value_2_string(known->type, value);
err = std_opt_->set_value(handle, option, value);
v = hg_sane_middleware::option_value_2_string(known->type, value);
}
else if (desc->type == SANE_TYPE_FIXED)
else
{
dv = hg_sane_middleware::sane_fixed_2_double(*((SANE_Fixed*)value));
pass = &dv;
size = sizeof(dv);
if (!desc)
{
HG_VLOG_MINI_1(LOG_LEVEL_FATAL, "Option descriptor %d not found.\n", option);
return SANE_STATUS_UNSUPPORTED;
}
else if (!value && desc->type != SANE_TYPE_BUTTON)
{
if (action == SANE_ACTION_SET_AUTO) // we assume the driver can set the option properbly, and no work to do
{
HG_VLOG_MINI_2(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title);
value = get_default_value(handle, option);
if (!value)
return SANE_STATUS_GOOD;
release_value = true;
}
else
{
HG_VLOG_MINI_2(LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title);
return SANE_STATUS_INVAL;
}
}
void* pass = value;
double dv = .0f;
bool bv = false;
int size = desc->size;
prev = hg_sane_middleware::option_value_2_string(desc->type, value);
if (desc->type == SANE_TYPE_BOOL)
{
bv = *((SANE_Bool*)value) == SANE_TRUE;
pass = &bv;
size = sizeof(bv);
}
else if (desc->type == SANE_TYPE_FIXED)
{
dv = hg_sane_middleware::sane_fixed_2_double(*((SANE_Fixed*)value));
pass = &dv;
size = sizeof(dv);
}
err = hg_scanner_set_parameter(handle, option, pass, size);
if (desc->type == SANE_TYPE_BOOL)
{
*((SANE_Bool*)value) = bv ? SANE_TRUE : SANE_FALSE;
}
else if (desc->type == SANE_TYPE_FIXED)
{
*((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(dv);
}
v = hg_sane_middleware::option_value_2_string(desc->type, value);
}
err = hg_scanner_set_parameter(handle, option, pass, size);
if (desc->type == SANE_TYPE_BOOL)
{
*((SANE_Bool*)value) = bv ? SANE_TRUE : SANE_FALSE;
}
else if (desc->type == SANE_TYPE_FIXED)
{
*((SANE_Fixed*)value) = hg_sane_middleware::double_2_sane_fixed(dv);
}
std::string prev(v);
v = hg_sane_middleware::option_value_2_string(desc->type, value);
if (prev == v)
{
HG_VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "-->Set option(%d - %s) value: %s\n", option, desc->title, v.c_str());

View File

@ -25,6 +25,7 @@
#endif
class json;
class sane_std_opts;
class hg_sane_middleware
{
typedef struct _device_option
@ -35,6 +36,7 @@ class hg_sane_middleware
}DEVOPT;
std::vector<DEVOPT> opts_;
SANE_Option_Descriptor* opt_0_;
sane_std_opts* std_opt_;
typedef struct _openning_scanner_option
{

362
hgsane/sane_option.cpp Normal file
View File

@ -0,0 +1,362 @@
#include "sane_option.h"
#include <sane/sane_option_definitions.h>
#include "../sdk/hginclude/hg_log.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
static struct _paper_size
{
const char* title;
int width;
int height;
}g_paper[] =
{
{OPTION_VALUE_ZZCC_A3, 297, 420},
{OPTION_VALUE_ZZCC_8K, 297, 420},
{OPTION_VALUE_ZZCC_A4HX,297, 210},
{OPTION_VALUE_ZZCC_B4, 257, 364},
{OPTION_VALUE_ZZCC_B5HX,250, 176}, // {PAPER_B5, {182, 257}},
{OPTION_VALUE_ZZCC_A4, 210, 297},
{OPTION_VALUE_ZZCC_16K, 210, 285}, // {PAPER_16K, {185, 260}}
{OPTION_VALUE_ZZCC_A5HX,210, 148},
{OPTION_VALUE_ZZCC_B5, 176, 250}, // {PAPER_B5, {182, 257}},
{OPTION_VALUE_ZZCC_B6HX,176, 125},
{OPTION_VALUE_ZZCC_A5, 148, 210},
{OPTION_VALUE_ZZCC_A6HX,148, 105},
{OPTION_VALUE_ZZCC_B6, 125, 176},
{OPTION_VALUE_ZZCC_A6, 105, 148}
};
static void match_paper(char* buf, int cx, int cy)
{
unsigned long fc0 = -1, fc1 = 0;
int index = -1;
fc0 = 1600 + 40000;
for (size_t i = 0; i < ARRAY_SIZE(g_paper); ++i)
{
fc1 = (cx - g_paper[i].width) * (cx - g_paper[i].width);
fc1 += (cy - g_paper[i].height) * (cy - g_paper[i].height);
if (fc1 < fc0)
{
fc0 = fc1;
index = i;
}
}
if (index == -1)
strcpy(buf, OPTION_VALUE_ZZCC_PPYSCC);
else
strcpy(buf, g_paper[index].title);
HG_VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "match paper(%u * %u) to '%s'\n", cx, cy, (char*)buf);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// sane_std_opts
sane_std_opts::sane_std_opts(int opt_base) : opt_num_base_(opt_base), page_height_(0), page_width_(0)
{}
sane_std_opts::~sane_std_opts()
{
for (size_t i = 0; i < known_opts_.size(); ++i)
{
char* buf = (char*)known_opts_[i].known.desc;
delete[] buf;
}
known_opts_.clear();
}
SANE_Option_Descriptor* sane_std_opts::get_known_option(int opt, int* ind)
{
if (ind)
*ind = -1;
for (size_t i = 0; i < known_opts_.size(); ++i)
{
if (known_opts_[i].known.opt == opt)
{
if (ind)
*ind = i;
return known_opts_[i].known.desc;
}
}
return nullptr;
}
SANE_Option_Descriptor* sane_std_opts::get_known_option(const char* name, int* ind)
{
if (ind)
*ind = -1;
for (size_t i = 0; i < known_opts_.size(); ++i)
{
if (strcmp(known_opts_[i].known.desc->name, name) == 0)
{
if (ind)
*ind = i;
return known_opts_[i].known.desc;
}
}
return nullptr;
}
void sane_std_opts::to_known_opt_value(OPTMAP* opmap, const void* data, void* known_data)
{
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAGE) == 0)
{
*((SANE_Bool*)known_data) = strcmp((char*)data, OPTION_VALUE_SMYM_DM) == 0 ? SANE_FALSE : SANE_TRUE;
}
else if (strcmp(opmap->user.desc->name, OPTION_TITLE_SMYM) == 0)
{
bool ok = false;
for (size_t i = 0; i < ARRAY_SIZE(g_paper); ++i)
{
if (strcmp((char*)data, g_paper[i].title) == 0)
{
page_width_ = g_paper[i].width;
page_height_ = g_paper[i].height;
ok = true;
break;
}
}
if (!ok)
{
page_width_ = 2338;
page_height_ = 3307;
}
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_W) == 0)
*((SANE_Int*)known_data) = page_width_;
else if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_H) == 0)
*((SANE_Int*)known_data) = page_height_;
}
}
void* sane_std_opts::from_known_opt_value(OPTMAP* opmap, const void* known_data, long* len)
{
void* buf = nullptr;
int size = opmap->user.desc->size;
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAGE) == 0)
{
buf = local_utility::acquire_memory(size + 4, "");
memset(buf, 0, size + 4);
if (len)
*len = size;
if (*((const SANE_Bool*)known_data) == SANE_TRUE)
strcpy((char*)buf, OPTION_VALUE_SMYM_SM);
else
strcpy((char*)buf, OPTION_VALUE_SMYM_DM);
}
else if (strcmp(opmap->user.desc->title, OPTION_TITLE_ZZCC) == 0)
{
int cx = page_width_,
cy = page_height_;
buf = local_utility::acquire_memory(size + 4, "");
memset(buf, 0, size + 4);
if (len)
*len = size;
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_W) == 0)
page_width_ = cx = *((SANE_Int*)known_data);
else
page_height_ = cy = *((SANE_Int*)known_data);
match_paper((char*)buf, cx, cy);
}
return buf;
}
json* sane_std_opts::get_opt_json(scanner_handle h, int opt)
{
char* buf = nullptr;
long len = 0;
json* jsn = nullptr;
if (hg_scanner_get_parameter(h, opt, buf, &len) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
buf = new char[len + 8];
memset(buf, 0, len + 8);
if (hg_scanner_get_parameter(h, opt, buf, &len) == SCANNER_ERR_OK)
{
jsn = new json();
if (!jsn->attach_text(buf))
{
delete jsn;
jsn = nullptr;
}
}
delete[] buf;
}
return jsn;
}
void* sane_std_opts::get_current_value(scanner_handle h, int opt)
{
json* jsn = sane_std_opts::get_opt_json(h, opt);
void* ret = nullptr;
if (jsn)
{
std::string val("");
int size = 0;
jsn->get_value("type", val);
jsn->get_value("size", size);
if (val == "string")
{
jsn->get_value("cur", val);
if (size < val.length())
size = val.length() + 4;
ret = local_utility::acquire_memory(size, "");
strcpy((char*)ret, val.c_str());
}
else if (val == "bool")
{
bool v = false;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Bool), "");
*((SANE_Bool*)ret) = v ? SANE_TRUE : SANE_FALSE;
}
else if (val == "int")
{
int v = 0;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Int), "");
*((SANE_Int*)ret) = v;
}
else if (val == "float")
{
double v = .0f;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Fixed), "");
*((SANE_Fixed*)ret) = SANE_FIX(v);
}
delete jsn;
}
return ret;
}
void sane_std_opts::init_known_opt(int option, SANE_Option_Descriptor* desc)
{
if (strcmp(desc->title, OPTION_TITLE_SMYM) == 0)
{
// duplex
if (!get_known_option(SANE_STD_OPT_NAME_PAGE))
{
OPTMAP om;
int size = sizeof(SANE_Option_Descriptor);
om.user.opt = option;
om.user.desc = desc;
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page to be simplex or duplex";
om.known.desc->name = SANE_STD_OPT_NAME_PAGE;
om.known.desc->size = sizeof(SANE_Bool);
om.known.desc->title = "Duplex";
om.known.desc->type = SANE_TYPE_BOOL;
om.known.desc->unit = SANE_UNIT_NONE;
known_opts_.push_back(om);
}
}
else if (strcmp(desc->title, OPTION_TITLE_ZZCC) == 0)
{
// page-width && page-height
if (!get_known_option(SANE_STD_OPT_NAME_PAPER_W))
{
OPTMAP om;
int size = sizeof(SANE_Option_Descriptor);
om.user.opt = option;
om.user.desc = desc;
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page width";
om.known.desc->name = SANE_STD_OPT_NAME_PAPER_W;
om.known.desc->size = sizeof(SANE_Int);
om.known.desc->title = "Page Width";
om.known.desc->type = SANE_TYPE_INT;
om.known.desc->unit = SANE_UNIT_MM;
known_opts_.push_back(om);
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page height";
om.known.desc->name = SANE_STD_OPT_NAME_PAPER_H;
om.known.desc->size = sizeof(SANE_Int);
om.known.desc->title = "Page Height";
om.known.desc->type = SANE_TYPE_INT;
om.known.desc->unit = SANE_UNIT_MM;
known_opts_.push_back(om);
}
}
}
SANE_Option_Descriptor* sane_std_opts::get_option(int option)
{
return get_known_option(option);
}
bool sane_std_opts::is_known_option(int opt, SANE_Option_Descriptor** user)
{
int ind = -1;
SANE_Option_Descriptor* sod = get_known_option(opt, &ind);
if (user && ind != -1)
*user = known_opts_[ind].user.desc;
return sod != nullptr;
}
scanner_err sane_std_opts::get_value(scanner_handle h, int opt, void* buf)
{
int ind = -1;
scanner_err statu = SCANNER_ERR_INVALID_PARAMETER;
if (get_known_option(opt, &ind))
{
OPTMAP* op = &known_opts_[ind];
void* data = sane_std_opts::get_current_value(h, op->user.opt);
if (data)
{
to_known_opt_value(op, data, buf);
local_utility::free_memory(data);
}
}
return statu;
}
scanner_err sane_std_opts::set_value(scanner_handle h, int opt, void* buf)
{
int ind = -1;
scanner_err statu = SCANNER_ERR_INVALID_PARAMETER;
if (get_known_option(opt, &ind))
{
OPTMAP* op = &known_opts_[ind];
long len = 0;
void* data = from_known_opt_value(op, buf, &len);
HG_VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "%d->%d: %s\n", opt, op->user.opt, (char*)data);
statu = hg_scanner_set_parameter(h, op->user.opt, data, len);
if (statu == SCANNER_ERR_NOT_EXACT)
to_known_opt_value(op, data, buf);
if (data)
local_utility::free_memory(data);
}
return statu;
}

62
hgsane/sane_option.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <string>
#include <stdio.h>
#ifdef WIN32
#define bzero(b, s) memset(b, 0, s)
#else
#include <iconv.h>
#endif
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include "sane/sane_ex.h"
#include "json.h"
namespace local_utility
{
void* acquire_memory(size_t bytes, const char* info);
void free_memory(void* m);
};
class sane_std_opts
{
typedef struct _sane_opt
{
SANE_Option_Descriptor* desc;
int opt;
}SANEOPT;
typedef struct _opt_map
{
SANEOPT known;
SANEOPT user;
}OPTMAP;
std::vector<OPTMAP> known_opts_;
int opt_num_base_;
int page_width_;
int page_height_;
SANE_Option_Descriptor* get_known_option(int opt, int* ind = nullptr);
SANE_Option_Descriptor* get_known_option(const char* name, int* ind = nullptr);
void to_known_opt_value(OPTMAP* opmap, const void* data, void* known_data);
void* from_known_opt_value(OPTMAP* opmap, const void* known_data, long* len);
public:
sane_std_opts(int opt_base);
~sane_std_opts();
public:
static json* get_opt_json(scanner_handle h, int opt); // call delete to free the returned object
static void* get_current_value(scanner_handle h, int opt); // call local_utility::free_memory to free the returned buffer
public:
void init_known_opt(int option, SANE_Option_Descriptor* desc);
SANE_Option_Descriptor* get_option(int option);
bool is_known_option(int opt, SANE_Option_Descriptor** user = nullptr);
scanner_err get_value(scanner_handle h, int opt, void* buf); // call this ONLY when is_known_option returnning true
scanner_err set_value(scanner_handle h, int opt, void* buf); // call this ONLY when is_known_option returnning true
};