Merge branch 'genesys-logging-improvements' into 'master'

genesys: Miscellaneous logging improvements

See merge request sane-project/backends!237
merge-requests/237/merge
Povilas Kanapickas 2019-11-10 12:12:41 +00:00
commit a15d960228
5 zmienionych plików z 232 dodań i 219 usunięć

Wyświetl plik

@ -114,7 +114,11 @@ void SaneException::set_msg(const char* format, std::va_list vlist)
const char* status_msg = sane_strstatus(status_); const char* status_msg = sane_strstatus(status_);
std::size_t status_msg_len = std::strlen(status_msg); std::size_t status_msg_len = std::strlen(status_msg);
int msg_len = std::vsnprintf(nullptr, 0, format, vlist); std::va_list vlist2;
va_copy(vlist2, vlist);
int msg_len = std::vsnprintf(nullptr, 0, format, vlist2);
va_end(vlist2);
if (msg_len < 0) { if (msg_len < 0) {
const char* formatting_error_msg = "(error formatting arguments)"; const char* formatting_error_msg = "(error formatting arguments)";
msg_.reserve(std::strlen(formatting_error_msg) + 3 + status_msg_len); msg_.reserve(std::strlen(formatting_error_msg) + 3 + status_msg_len);
@ -178,4 +182,34 @@ void DebugMessageHelper::vstatus(const char* format, ...)
va_end(args); va_end(args);
} }
void DebugMessageHelper::log(unsigned level, const char* msg)
{
DBG(level, "%s: %s\n", func_, msg);
}
void DebugMessageHelper::vlog(unsigned level, const char* format, ...)
{
std::string msg;
std::va_list args;
va_start(args, format);
int msg_len = std::vsnprintf(nullptr, 0, format, args);
va_end(args);
if (msg_len < 0) {
DBG(level, "%s: error formatting error message: %s\n", func_, format);
return;
}
msg.resize(msg_len + 1, ' ');
va_start(args, format);
std::vsnprintf(&msg.front(), msg.size(), format, args);
va_end(args);
msg.resize(msg_len, ' '); // strip the null character
DBG(level, "%s: %s\n", func_, msg.c_str());
}
} // namespace genesys } // namespace genesys

Wyświetl plik

@ -98,7 +98,7 @@ private:
do { \ do { \
SANE_Status tmp_status = function; \ SANE_Status tmp_status = function; \
if (tmp_status != SANE_STATUS_GOOD) { \ if (tmp_status != SANE_STATUS_GOOD) { \
throw SaneException(tmp_status); \ throw ::genesys::SaneException(tmp_status); \
} \ } \
} while (false) } while (false)
@ -124,24 +124,43 @@ public:
void clear() { msg_[0] = '\n'; } void clear() { msg_[0] = '\n'; }
void log(unsigned level, const char* msg);
void vlog(unsigned level, const char* format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
;
private: private:
const char* func_ = nullptr; const char* func_ = nullptr;
char msg_[MAX_BUF_SIZE]; char msg_[MAX_BUF_SIZE];
unsigned num_exceptions_on_enter_ = 0; unsigned num_exceptions_on_enter_ = 0;
}; };
#define DBG_HELPER(var) DebugMessageHelper var(__func__)
#define DBG_HELPER_ARGS(var, ...) DebugMessageHelper var(__func__, __VA_ARGS__) #if defined(__GNUC__) || defined(__clang__)
#define GENESYS_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__FUNCSIG__)
#define GENESYS_CURRENT_FUNCTION __FUNCSIG__
#else
#define GENESYS_CURRENT_FUNCTION __func__
#endif
#define DBG_HELPER(var) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION)
#define DBG_HELPER_ARGS(var, ...) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION, __VA_ARGS__)
template<class F> template<class F>
SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function) SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function)
{ {
try { try {
return function(); function();
return SANE_STATUS_GOOD;
} catch (const SaneException& exc) { } catch (const SaneException& exc) {
DBG(DBG_error, "%s: got error: %s\n", func, exc.what());
return exc.status(); return exc.status();
} catch (const std::bad_alloc& exc) { } catch (const std::bad_alloc& exc) {
(void) exc; (void) exc;
DBG(DBG_error, "%s: failed to allocate memory\n", func);
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} catch (const std::exception& exc) { } catch (const std::exception& exc) {
DBG(DBG_error, "%s: got uncaught exception: %s\n", func, exc.what()); DBG(DBG_error, "%s: got uncaught exception: %s\n", func, exc.what());

Wyświetl plik

@ -182,6 +182,7 @@ static const SANE_Range expiration_range = {
const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev) const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev)
{ {
DBG_HELPER(dbg);
for (const auto& sensor : *s_sensors) { for (const auto& sensor : *s_sensors) {
if (dev->model->sensor_id == sensor.sensor_id) { if (dev->model->sensor_id == sensor.sensor_id) {
return sensor; return sensor;
@ -193,6 +194,8 @@ const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev)
Genesys_Sensor* find_sensor_impl(Genesys_Device* dev, unsigned dpi, unsigned channels, Genesys_Sensor* find_sensor_impl(Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method) ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
static_cast<unsigned>(scan_method));
for (auto& sensor : *s_sensors) { for (auto& sensor : *s_sensors) {
if (dev->model->sensor_id == sensor.sensor_id && sensor.resolutions.matches(dpi) && if (dev->model->sensor_id == sensor.sensor_id && sensor.resolutions.matches(dpi) &&
sensor.matches_channel_count(channels) && sensor.method == scan_method) sensor.matches_channel_count(channels) && sensor.method == scan_method)
@ -206,12 +209,16 @@ Genesys_Sensor* find_sensor_impl(Genesys_Device* dev, unsigned dpi, unsigned cha
bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels, bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method) ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
static_cast<unsigned>(scan_method));
return find_sensor_impl(dev, dpi, channels, scan_method) != nullptr; return find_sensor_impl(dev, dpi, channels, scan_method) != nullptr;
} }
const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels, const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method) ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
static_cast<unsigned>(scan_method));
const auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method); const auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method);
if (sensor) if (sensor)
return *sensor; return *sensor;
@ -222,6 +229,8 @@ Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigne
unsigned channels, unsigned channels,
ScanMethod scan_method) ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
static_cast<unsigned>(scan_method));
auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method); auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method);
if (sensor) if (sensor)
return *sensor; return *sensor;
@ -232,6 +241,7 @@ Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigne
std::vector<std::reference_wrapper<const Genesys_Sensor>> std::vector<std::reference_wrapper<const Genesys_Sensor>>
sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method) sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "scan_method: %d", static_cast<unsigned>(scan_method));
std::vector<std::reference_wrapper<const Genesys_Sensor>> ret; std::vector<std::reference_wrapper<const Genesys_Sensor>> ret;
for (const Genesys_Sensor& sensor : sanei_genesys_find_sensors_all_for_write(dev, scan_method)) { for (const Genesys_Sensor& sensor : sanei_genesys_find_sensors_all_for_write(dev, scan_method)) {
ret.push_back(sensor); ret.push_back(sensor);
@ -242,6 +252,7 @@ std::vector<std::reference_wrapper<const Genesys_Sensor>>
std::vector<std::reference_wrapper<Genesys_Sensor>> std::vector<std::reference_wrapper<Genesys_Sensor>>
sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method) sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method)
{ {
DBG_HELPER_ARGS(dbg, "scan_method: %d", static_cast<unsigned>(scan_method));
std::vector<std::reference_wrapper<Genesys_Sensor>> ret; std::vector<std::reference_wrapper<Genesys_Sensor>> ret;
for (auto& sensor : *s_sensors) { for (auto& sensor : *s_sensors) {
if (dev->model->sensor_id == sensor.sensor_id && sensor.method == scan_method) { if (dev->model->sensor_id == sensor.sensor_id && sensor.method == scan_method) {
@ -251,9 +262,10 @@ std::vector<std::reference_wrapper<Genesys_Sensor>>
return ret; return ret;
} }
void void sanei_genesys_init_structs (Genesys_Device * dev)
sanei_genesys_init_structs (Genesys_Device * dev)
{ {
DBG_HELPER(dbg);
bool gpo_ok = false; bool gpo_ok = false;
bool motor_ok = false; bool motor_ok = false;
bool fe_ok = false; bool fe_ok = false;
@ -917,7 +929,7 @@ static void genesys_send_offset_and_shading(Genesys_Device* dev, const Genesys_S
void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
int pixels_per_line) int pixels_per_line)
{ {
DBG_HELPER(dbg); DBG_HELPER_ARGS(dbg, "pixels_per_line: %d", pixels_per_line);
if (dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) { if (dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) {
return; return;
@ -1647,6 +1659,7 @@ static void genesys_dummy_dark_shading(Genesys_Device* dev, const Genesys_Sensor
static void genesys_repark_sensor_before_shading(Genesys_Device* dev) static void genesys_repark_sensor_before_shading(Genesys_Device* dev)
{ {
DBG_HELPER(dbg);
if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) { if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) {
// rewind keeps registers and slopes table intact from previous scan but is not // rewind keeps registers and slopes table intact from previous scan but is not
// available on all supported chipsets (or may cause scan artifacts, see #7) // available on all supported chipsets (or may cause scan artifacts, see #7)
@ -1666,6 +1679,7 @@ static void genesys_repark_sensor_before_shading(Genesys_Device* dev)
static void genesys_repark_sensor_after_white_shading(Genesys_Device* dev) static void genesys_repark_sensor_after_white_shading(Genesys_Device* dev)
{ {
DBG_HELPER(dbg);
if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) { if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) {
dev->cmd_set->slow_back_home(dev, true); dev->cmd_set->slow_back_home(dev, true);
} }
@ -4346,29 +4360,20 @@ check_present (SANE_String_Const devname) noexcept
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
static SANE_Status static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may_wait)
attach (SANE_String_Const devname, Genesys_Device ** devp, bool may_wait)
{ {
DBG_HELPER_ARGS(dbg, "devp %s nullptr, may_wait = %d", devp ? "!=" : "==", may_wait); DBG_HELPER_ARGS(dbg, " devname: %s, may_wait = %d", devname, may_wait);
Genesys_Device *dev = nullptr; Genesys_Device *dev = nullptr;
if (devp) { if (!devname) {
*devp = nullptr; throw SaneException("devname must not be nullptr");
}
if (!devname)
{
DBG(DBG_error, "%s: devname == nullptr\n", __func__);
return SANE_STATUS_INVAL;
} }
for (auto& dev : *s_devices) { for (auto& dev : *s_devices) {
if (dev.file_name == devname) { if (dev.file_name == devname) {
if (devp)
*devp = &dev;
DBG(DBG_info, "%s: device `%s' was already in device list\n", __func__, devname); DBG(DBG_info, "%s: device `%s' was already in device list\n", __func__, devname);
return SANE_STATUS_GOOD; return &dev;
} }
} }
@ -4405,9 +4410,8 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, bool may_wait)
} }
if (found_usb_dev == nullptr) { if (found_usb_dev == nullptr) {
DBG(DBG_error, "%s: vendor 0x%xd product 0x%xd is not supported by this backend\n", __func__, throw SaneException("vendor 0x%xd product 0x%xd is not supported by this backend",
vendor, product); vendor, product);
return SANE_STATUS_INVAL;
} }
s_devices->emplace_back(); s_devices->emplace_back();
@ -4423,31 +4427,17 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, bool may_wait)
DBG(DBG_info, "%s: found %s flatbed scanner %s at %s\n", __func__, dev->model->vendor, DBG(DBG_info, "%s: found %s flatbed scanner %s at %s\n", __func__, dev->model->vendor,
dev->model->model, dev->file_name.c_str()); dev->model->model, dev->file_name.c_str());
if (devp) {
*devp = dev;
}
usb_dev.close(); usb_dev.close();
return SANE_STATUS_GOOD; return dev;
} }
static SANE_Status // this function is passed to C API and must not throw
attach_one_device_impl(SANE_String_Const devname) static SANE_Status attach_one_device(SANE_String_Const devname) noexcept
{
Genesys_Device *dev;
SANE_Status status = attach(devname, &dev, false);
if (status != SANE_STATUS_GOOD) {
DBG(DBG_info, "%s: failed to attach: %s\n", __func__, sane_strstatus(status));
return status;
}
return status;
}
static SANE_Status attach_one_device(SANE_String_Const devname)
{ {
DBG_HELPER(dbg);
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return attach_one_device_impl(devname); attach_device_by_name(devname, false);
}); });
} }
@ -4466,24 +4456,19 @@ config_attach_genesys(SANEI_Config __sane_unused__ *config, const char *devname)
} }
/* probes for scanner to attach to the backend */ /* probes for scanner to attach to the backend */
static SANE_Status static void probe_genesys_devices (void)
probe_genesys_devices (void)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
SANEI_Config config; SANEI_Config config;
SANE_Status status = SANE_STATUS_GOOD;
// set configuration options structure : no option for this backend // set configuration options structure : no option for this backend
config.descriptors = nullptr; config.descriptors = nullptr;
config.values = nullptr; config.values = nullptr;
config.count = 0; config.count = 0;
/* generic configure and attach function */ TIE(sanei_configure_attach(GENESYS_CONFIG_FILE, &config, config_attach_genesys));
status = sanei_configure_attach (GENESYS_CONFIG_FILE, &config,
config_attach_genesys);
DBG(DBG_info, "%s: %zu devices currently attached\n", __func__, s_devices->size()); DBG(DBG_info, "%s: %zu devices currently attached\n", __func__, s_devices->size());
return status;
} }
/** /**
@ -4672,8 +4657,7 @@ static void genesys_buffer_image(Genesys_Scanner *s)
/* -------------------------- SANE API functions ------------------------- */ /* -------------------------- SANE API functions ------------------------- */
SANE_Status void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
{ {
DBG_INIT (); DBG_INIT ();
DBG_HELPER_ARGS(dbg, "authorize %s null", authorize ? "!=" : "=="); DBG_HELPER_ARGS(dbg, "authorize %s null", authorize ? "!=" : "==");
@ -4716,7 +4700,7 @@ sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
); );
// cold-plug case :detection of allready connected scanners // cold-plug case :detection of allready connected scanners
return probe_genesys_devices (); probe_genesys_devices();
} }
@ -4724,7 +4708,7 @@ extern "C" SANE_Status sane_init(SANE_Int * version_code, SANE_Auth_Callback aut
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_init_impl(version_code, authorize); sane_init_impl(version_code, authorize);
}); });
} }
@ -4743,8 +4727,7 @@ extern "C" void sane_exit()
catch_all_exceptions(__func__, [](){ sane_exit_impl(); }); catch_all_exceptions(__func__, [](){ sane_exit_impl(); });
} }
SANE_Status void sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only)
sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only)
{ {
DBG_HELPER_ARGS(dbg, "local_only = %s", local_only ? "true" : "false"); DBG_HELPER_ARGS(dbg, "local_only = %s", local_only ? "true" : "false");
@ -4781,20 +4764,17 @@ sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only)
s_sane_devices_ptrs->push_back(nullptr); s_sane_devices_ptrs->push_back(nullptr);
*const_cast<SANE_Device***>(device_list) = s_sane_devices_ptrs->data(); *const_cast<SANE_Device***>(device_list) = s_sane_devices_ptrs->data();
return SANE_STATUS_GOOD;
} }
extern "C" SANE_Status sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only) extern "C" SANE_Status sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_get_devices_impl(device_list, local_only); sane_get_devices_impl(device_list, local_only);
}); });
} }
SANE_Status static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
{ {
DBG_HELPER_ARGS(dbg, "devicename = %s", devicename); DBG_HELPER_ARGS(dbg, "devicename = %s", devicename);
Genesys_Device* dev = nullptr; Genesys_Device* dev = nullptr;
@ -4812,20 +4792,16 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
} }
} }
if (!dev) if (!dev) {
{ DBG(DBG_info, "%s: couldn't find `%s' in devlist, trying attach\n", __func__,
DBG(DBG_info, "%s: couldn't find `%s' in devlist, trying attach\n", __func__, devicename); devicename);
SANE_Status status = attach(devicename, &dev, true); dbg.status("attach_device_by_name");
if (status != SANE_STATUS_GOOD) { dev = attach_device_by_name(devicename, true);
DBG(DBG_info, "%s: failed to attach: %s\n", __func__, sane_strstatus(status)); dbg.clear();
return status; } else {
}
}
else
DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->model->name); DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->model->name);
} }
else } else {
{
// empty devicename or "genesys" -> use first device // empty devicename or "genesys" -> use first device
if (!s_devices->empty()) { if (!s_devices->empty()) {
dev = &s_devices->front(); dev = &s_devices->front();
@ -4833,8 +4809,9 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
} }
} }
if (!dev) if (!dev) {
return SANE_STATUS_INVAL; throw SaneException("could not find the device to open: %s", devicename);
}
if (dev->model->flags & GENESYS_FLAG_UNTESTED) if (dev->model->flags & GENESYS_FLAG_UNTESTED)
{ {
@ -4892,15 +4869,13 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
sanei_genesys_read_calibration(s->dev->calibration_cache, s->dev->calib_file); sanei_genesys_read_calibration(s->dev->calibration_cache, s->dev->calib_file);
}); });
} }
return SANE_STATUS_GOOD;
} }
extern "C" SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle* handle) extern "C" SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle* handle)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_open_impl(devicename, handle); sane_open_impl(devicename, handle);
}); });
} }
@ -4977,6 +4952,7 @@ extern "C" void sane_close(SANE_Handle handle)
const SANE_Option_Descriptor * const SANE_Option_Descriptor *
sane_get_option_descriptor_impl(SANE_Handle handle, SANE_Int option) sane_get_option_descriptor_impl(SANE_Handle handle, SANE_Int option)
{ {
DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
if (static_cast<unsigned>(option) >= NUM_OPTIONS) { if (static_cast<unsigned>(option) >= NUM_OPTIONS) {
@ -4999,16 +4975,37 @@ sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
return ret; return ret;
} }
/* gets an option , called by sane_control_option */ static void print_option(DebugMessageHelper& dbg, const Genesys_Scanner& s, int option, void* val)
static SANE_Status
get_option_value (Genesys_Scanner * s, int option, void *val)
{ {
DBG_HELPER(dbg); switch (s.opt[option].type) {
case SANE_TYPE_INT: {
dbg.vlog(DBG_proc, "value: %d", *reinterpret_cast<SANE_Word*>(val));
return;
}
case SANE_TYPE_BOOL: {
dbg.vlog(DBG_proc, "value: %s", *reinterpret_cast<SANE_Bool*>(val) ? "true" : "false");
return;
}
case SANE_TYPE_FIXED: {
dbg.vlog(DBG_proc, "value: %f", SANE_UNFIX(*reinterpret_cast<SANE_Word*>(val)));
return;
}
case SANE_TYPE_STRING: {
dbg.vlog(DBG_proc, "value: %s", reinterpret_cast<char*>(val));
return;
}
default: break;
}
dbg.log(DBG_proc, "value: (non-printable)");
}
static void get_option_value(Genesys_Scanner* s, int option, void* val)
{
DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
unsigned int i; unsigned int i;
SANE_Word* table = nullptr; SANE_Word* table = nullptr;
std::vector<uint16_t> gamma_table; std::vector<uint16_t> gamma_table;
unsigned option_size = 0; unsigned option_size = 0;
SANE_Status status = SANE_STATUS_GOOD;
const Genesys_Sensor* sensor = nullptr; const Genesys_Sensor* sensor = nullptr;
if (sanei_genesys_has_sensor(s->dev, s->dev->settings.xres, s->dev->settings.get_channels(), if (sanei_genesys_has_sensor(s->dev, s->dev->settings.xres, s->dev->settings.get_channels(),
@ -5199,7 +5196,7 @@ get_option_value (Genesys_Scanner * s, int option, void *val)
default: default:
DBG(DBG_warn, "%s: can't get unknown option %d\n", __func__, option); DBG(DBG_warn, "%s: can't get unknown option %d\n", __func__, option);
} }
return status; print_option(dbg, *s, option, val);
} }
/** @brief set calibration file value /** @brief set calibration file value
@ -5229,12 +5226,11 @@ static void set_calibration_value(Genesys_Scanner* s, const char* val)
} }
/* sets an option , called by sane_control_option */ /* sets an option , called by sane_control_option */
static SANE_Status static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int* myinfo)
set_option_value (Genesys_Scanner * s, int option, void *val,
SANE_Int * myinfo)
{ {
DBG_HELPER(dbg); DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
SANE_Status status = SANE_STATUS_GOOD; print_option(dbg, *s, option, val);
SANE_Word *table; SANE_Word *table;
unsigned int i; unsigned int i;
unsigned option_size = 0; unsigned option_size = 0;
@ -5562,13 +5558,11 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
default: default:
DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option); DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option);
} }
return status;
} }
/* sets and gets scanner option values */ /* sets and gets scanner option values */
SANE_Status void sane_control_option_impl(SANE_Handle handle, SANE_Int option,
sane_control_option_impl(SANE_Handle handle, SANE_Int option,
SANE_Action action, void *val, SANE_Int * info) SANE_Action action, void *val, SANE_Int * info)
{ {
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
@ -5578,75 +5572,52 @@ sane_control_option_impl(SANE_Handle handle, SANE_Int option,
DBG_HELPER_ARGS(dbg, "action = %s, option = %s (%d)", action_str, DBG_HELPER_ARGS(dbg, "action = %s, option = %s (%d)", action_str,
s->opt[option].name, option); s->opt[option].name, option);
SANE_Status status = SANE_STATUS_GOOD;
SANE_Word cap; SANE_Word cap;
SANE_Int myinfo = 0; SANE_Int myinfo = 0;
if (info) if (info) {
*info = 0; *info = 0;
if (s->scanning)
{
DBG(DBG_warn, "%s: don't call this function while scanning (option = %s (%d))\n", __func__,
s->opt[option].name, option);
return SANE_STATUS_DEVICE_BUSY;
} }
if (option >= NUM_OPTIONS || option < 0)
{ if (s->scanning) {
DBG(DBG_warn, "%s: option %d >= NUM_OPTIONS || option < 0\n", __func__, option); throw SaneException(SANE_STATUS_DEVICE_BUSY,
return SANE_STATUS_INVAL; "don't call this function while scanning (option = %s (%d))",
s->opt[option].name, option);
}
if (option >= NUM_OPTIONS || option < 0) {
throw SaneException("option %d >= NUM_OPTIONS || option < 0", option);
} }
cap = s->opt[option].cap; cap = s->opt[option].cap;
if (!SANE_OPTION_IS_ACTIVE (cap)) if (!SANE_OPTION_IS_ACTIVE (cap)) {
{ throw SaneException("option %d is inactive", option);
DBG(DBG_warn, "%s: option %d is inactive\n", __func__, option);
return SANE_STATUS_INVAL;
} }
switch (action) switch (action) {
{
case SANE_ACTION_GET_VALUE: case SANE_ACTION_GET_VALUE:
status = get_option_value (s, option, val); get_option_value(s, option, val);
break; break;
case SANE_ACTION_SET_VALUE: case SANE_ACTION_SET_VALUE:
if (!SANE_OPTION_IS_SETTABLE (cap)) if (!SANE_OPTION_IS_SETTABLE (cap)) {
{ throw SaneException("option %d is not settable", option);
DBG(DBG_warn, "%s: option %d is not settable\n", __func__, option);
return SANE_STATUS_INVAL;
} }
status = sanei_constrain_value (s->opt + option, val, &myinfo); TIE(sanei_constrain_value(s->opt + option, val, &myinfo));
if (status != SANE_STATUS_GOOD)
{
DBG(DBG_warn, "%s: sanei_constrain_value returned %s\n", __func__,
sane_strstatus(status));
return status;
}
status = set_option_value (s, option, val, &myinfo); set_option_value(s, option, val, &myinfo);
break; break;
case SANE_ACTION_SET_AUTO: case SANE_ACTION_SET_AUTO:
DBG(DBG_error, throw SaneException("SANE_ACTION_SET_AUTO unsupported since no option "
"%s: SANE_ACTION_SET_AUTO unsupported since no option has SANE_CAP_AUTOMATIC\n", "has SANE_CAP_AUTOMATIC");
__func__);
status = SANE_STATUS_INVAL;
break;
default: default:
DBG(DBG_warn, "%s: unknown action %d for option %d\n", __func__, action, option); throw SaneException("unknown action %d for option %d", action, option);
status = SANE_STATUS_INVAL;
break;
} }
if (info) if (info)
*info = myinfo; *info = myinfo;
return status;
} }
extern "C" SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, extern "C" SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option,
@ -5654,11 +5625,11 @@ extern "C" SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option,
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_control_option_impl(handle, option, action, val, info); sane_control_option_impl(handle, option, action, val, info);
}); });
} }
SANE_Status sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params) void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
@ -5682,33 +5653,27 @@ SANE_Status sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params
params->lines = -1; params->lines = -1;
} }
} }
debug_dump(DBG_proc, *params);
return SANE_STATUS_GOOD;
} }
extern "C" SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters* params) extern "C" SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters* params)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_get_parameters_impl(handle, params); sane_get_parameters_impl(handle, params);
}); });
} }
SANE_Status sane_start_impl(SANE_Handle handle) void sane_start_impl(SANE_Handle handle)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
SANE_Status status=SANE_STATUS_GOOD;
if (s->pos_top_left_x >= s->pos_bottom_right_x) if (s->pos_top_left_x >= s->pos_bottom_right_x) {
{ throw SaneException("top left x >= bottom right x");
DBG(DBG_error0, "%s: top left x >= bottom right x --- exiting\n", __func__);
return SANE_STATUS_INVAL;
} }
if (s->pos_top_left_y >= s->pos_bottom_right_y) if (s->pos_top_left_y >= s->pos_bottom_right_y) {
{ throw SaneException("top left y >= bottom right y");
DBG(DBG_error0, "%s: top left y >= bottom right y --- exiting\n", __func__);
return SANE_STATUS_INVAL;
} }
/* First make sure we have a current parameter set. Some of the /* First make sure we have a current parameter set. Some of the
@ -5738,16 +5703,18 @@ SANE_Status sane_start_impl(SANE_Handle handle)
/* check if we need to skip this page, sheetfed scanners /* check if we need to skip this page, sheetfed scanners
* can go to next doc while flatbed ones can't */ * can go to next doc while flatbed ones can't */
if (s->swskip > 0 && IS_ACTIVE(OPT_SWSKIP)) { if (s->swskip > 0 && IS_ACTIVE(OPT_SWSKIP)) {
status = sanei_magic_isBlank(&s->params, auto status = sanei_magic_isBlank(&s->params,
s->dev->img_buffer.data(), s->dev->img_buffer.data(),
SANE_UNFIX(s->swskip)); SANE_UNFIX(s->swskip));
if(status == SANE_STATUS_NO_DOCS)
{ if (status == SANE_STATUS_NO_DOCS && s->dev->model->is_sheetfed) {
if (s->dev->model->is_sheetfed) {
DBG(DBG_info, "%s: blank page, recurse\n", __func__); DBG(DBG_info, "%s: blank page, recurse\n", __func__);
return sane_start(handle); sane_start(handle);
return;
} }
return status;
if (status != SANE_STATUS_GOOD) {
throw SaneException(status);
} }
} }
@ -5770,57 +5737,45 @@ SANE_Status sane_start_impl(SANE_Handle handle)
catch_all_exceptions(__func__, [&](){ genesys_derotate(s); }); catch_all_exceptions(__func__, [&](){ genesys_derotate(s); });
} }
} }
return status;
} }
extern "C" SANE_Status sane_start(SANE_Handle handle) extern "C" SANE_Status sane_start(SANE_Handle handle)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_start_impl(handle); sane_start_impl(handle);
}); });
} }
SANE_Status void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
{ {
DBG_HELPER(dbg); DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
Genesys_Device *dev; Genesys_Device *dev;
size_t local_len; size_t local_len;
if (!s) if (!s) {
{ throw SaneException("handle is nullptr");
DBG(DBG_error, "%s: handle is null!\n", __func__);
return SANE_STATUS_INVAL;
} }
dev=s->dev; dev=s->dev;
if (!dev) if (!dev) {
{ throw SaneException("dev is nullptr");
DBG(DBG_error, "%s: dev is null!\n", __func__);
return SANE_STATUS_INVAL;
} }
if (!buf) if (!buf) {
{ throw SaneException("buf is nullptr");
DBG(DBG_error, "%s: buf is null!\n", __func__);
return SANE_STATUS_INVAL;
} }
if (!len) if (!len) {
{ throw SaneException("len is nullptr");
DBG(DBG_error, "%s: len is null!\n", __func__);
return SANE_STATUS_INVAL;
} }
*len = 0; *len = 0;
if (!s->scanning) if (!s->scanning) {
{ throw SaneException(SANE_STATUS_CANCELLED,
DBG(DBG_warn, "%s: scan was cancelled, is over or has not been initiated yet\n", __func__); "scan was cancelled, is over or has not been initiated yet");
return SANE_STATUS_CANCELLED;
} }
DBG(DBG_proc, "%s: start, %d maximum bytes required\n", __func__, max_len); DBG(DBG_proc, "%s: start, %d maximum bytes required\n", __func__, max_len);
@ -5839,7 +5794,7 @@ sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int*
dev->cmd_set->slow_back_home(dev, false); dev->cmd_set->slow_back_home(dev, false);
dev->parking = true; dev->parking = true;
} }
return SANE_STATUS_EOF; throw SaneException(SANE_STATUS_EOF);
} }
local_len = max_len; local_len = max_len;
@ -5903,14 +5858,13 @@ sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int*
fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n"); fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n");
} }
DBG(DBG_proc, "%s: %d bytes returned\n", __func__, *len); DBG(DBG_proc, "%s: %d bytes returned\n", __func__, *len);
return SANE_STATUS_GOOD;
} }
extern "C" SANE_Status sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len) extern "C" SANE_Status sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_read_impl(handle, buf, max_len, len); sane_read_impl(handle, buf, max_len, len);
}); });
} }
@ -5955,50 +5909,44 @@ extern "C" void sane_cancel(SANE_Handle handle)
catch_all_exceptions(__func__, [=]() { sane_cancel_impl(handle); }); catch_all_exceptions(__func__, [=]() { sane_cancel_impl(handle); });
} }
SANE_Status void sane_set_io_mode_impl(SANE_Handle handle, SANE_Bool non_blocking)
sane_set_io_mode_impl(SANE_Handle handle, SANE_Bool non_blocking)
{ {
DBG_HELPER_ARGS(dbg, "handle = %p, non_blocking = %s", handle, DBG_HELPER_ARGS(dbg, "handle = %p, non_blocking = %s", handle,
non_blocking == SANE_TRUE ? "true" : "false"); non_blocking == SANE_TRUE ? "true" : "false");
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle); Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
if (!s->scanning) if (!s->scanning) {
{ throw SaneException("not scanning");
DBG(DBG_error, "%s: not scanning\n", __func__); }
return SANE_STATUS_INVAL; if (non_blocking) {
throw SaneException(SANE_STATUS_UNSUPPORTED);
} }
if (non_blocking)
return SANE_STATUS_UNSUPPORTED;
return SANE_STATUS_GOOD;
} }
extern "C" SANE_Status sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking) extern "C" SANE_Status sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_set_io_mode_impl(handle, non_blocking); sane_set_io_mode_impl(handle, non_blocking);
}); });
} }
SANE_Status void sane_get_select_fd_impl(SANE_Handle handle, SANE_Int* fd)
sane_get_select_fd_impl(SANE_Handle handle, SANE_Int * fd)
{ {
DBG_HELPER_ARGS(dbg, "handle = %p, fd = %p", handle, reinterpret_cast<void*>(fd)); DBG_HELPER_ARGS(dbg, "handle = %p, fd = %p", handle, reinterpret_cast<void*>(fd));
Genesys_Scanner *s = (Genesys_Scanner*) handle; Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
if (!s->scanning) if (!s->scanning) {
{ throw SaneException("not scanning");
DBG(DBG_error, "%s: not scanning\n", __func__);
return SANE_STATUS_INVAL;
} }
return SANE_STATUS_UNSUPPORTED; throw SaneException(SANE_STATUS_UNSUPPORTED);
} }
extern "C" SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int* fd) extern "C" SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int* fd)
{ {
return wrap_exceptions_to_status_code(__func__, [=]() return wrap_exceptions_to_status_code(__func__, [=]()
{ {
return sane_get_select_fd_impl(handle, fd); sane_get_select_fd_impl(handle, fd);
}); });
} }

Wyświetl plik

@ -2660,4 +2660,15 @@ void debug_dump(unsigned level, const Genesys_Sensor& sensor)
DBG(level, " gamma.blue : %f\n", sensor.gamma[2]); DBG(level, " gamma.blue : %f\n", sensor.gamma[2]);
} }
void debug_dump(unsigned level, const SANE_Parameters& params)
{
DBG(level, "params:\n");
DBG(level, " format: %d:\n", static_cast<unsigned>(params.format));
DBG(level, " last_frame: %d:\n", params.last_frame);
DBG(level, " bytes_per_line: %d:\n", params.bytes_per_line);
DBG(level, " pixels_per_line: %d:\n", params.pixels_per_line);
DBG(level, " lines: %d:\n", params.lines);
DBG(level, " depth: %d:\n", params.depth);
}
} // namespace genesys } // namespace genesys

Wyświetl plik

@ -620,6 +620,7 @@ void debug_dump(unsigned level, const Genesys_Current_Setup& setup);
void debug_dump(unsigned level, const Genesys_Register_Set& regs); void debug_dump(unsigned level, const Genesys_Register_Set& regs);
void debug_dump(unsigned level, const GenesysRegisterSettingSet& regs); void debug_dump(unsigned level, const GenesysRegisterSettingSet& regs);
void debug_dump(unsigned level, const Genesys_Sensor& sensor); void debug_dump(unsigned level, const Genesys_Sensor& sensor);
void debug_dump(unsigned level, const SANE_Parameters& params);
} // namespace genesys } // namespace genesys