From 46876064d7ccff723d422a8c42fb2da94f61f3fe Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:31 +0200 Subject: [PATCH 1/6] genesys: Improve error logging --- backend/genesys/error.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/genesys/error.h b/backend/genesys/error.h index d2fc74e10..8c2834638 100644 --- a/backend/genesys/error.h +++ b/backend/genesys/error.h @@ -139,9 +139,11 @@ SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function) try { return function(); } catch (const SaneException& exc) { + DBG(DBG_error, "%s: got error: %s\n", func, exc.what()); return exc.status(); } catch (const std::bad_alloc& exc) { (void) exc; + DBG(DBG_error, "%s: failed to allocate memory\n", func); return SANE_STATUS_NO_MEM; } catch (const std::exception& exc) { DBG(DBG_error, "%s: got uncaught exception: %s\n", func, exc.what()); From 6d7365ba897890ec75eaa83c9981393677239fac Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:32 +0200 Subject: [PATCH 2/6] genesys: Return errors as exceptions --- backend/genesys/error.h | 3 +- backend/genesys/genesys.cpp | 322 +++++++++++++----------------------- 2 files changed, 115 insertions(+), 210 deletions(-) diff --git a/backend/genesys/error.h b/backend/genesys/error.h index 8c2834638..265eb5e7a 100644 --- a/backend/genesys/error.h +++ b/backend/genesys/error.h @@ -137,7 +137,8 @@ template SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function) { try { - return function(); + function(); + return SANE_STATUS_GOOD; } catch (const SaneException& exc) { DBG(DBG_error, "%s: got error: %s\n", func, exc.what()); return exc.status(); diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index bd4011ad5..12f3f11b7 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -4351,29 +4351,20 @@ check_present (SANE_String_Const devname) noexcept return SANE_STATUS_GOOD; } -static SANE_Status -attach (SANE_String_Const devname, Genesys_Device ** devp, bool may_wait) +static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may_wait) { - DBG_HELPER_ARGS(dbg, "devp %s nullptr, may_wait = %d", devp ? "!=" : "==", may_wait); + DBG_HELPER_ARGS(dbg, " may_wait = %d", may_wait); Genesys_Device *dev = nullptr; - if (devp) { - *devp = nullptr; - } - - if (!devname) - { - DBG(DBG_error, "%s: devname == nullptr\n", __func__); - return SANE_STATUS_INVAL; + if (!devname) { + throw SaneException("devname must not be nullptr"); } for (auto& dev : *s_devices) { if (dev.file_name == devname) { - if (devp) - *devp = &dev; DBG(DBG_info, "%s: device `%s' was already in device list\n", __func__, devname); - return SANE_STATUS_GOOD; + return &dev; } } @@ -4410,9 +4401,8 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, bool may_wait) } if (found_usb_dev == nullptr) { - DBG(DBG_error, "%s: vendor 0x%xd product 0x%xd is not supported by this backend\n", __func__, - vendor, product); - return SANE_STATUS_INVAL; + throw SaneException("vendor 0x%xd product 0x%xd is not supported by this backend", + vendor, product); } s_devices->emplace_back(); @@ -4428,31 +4418,16 @@ 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, dev->model->model, dev->file_name.c_str()); - if (devp) { - *devp = dev; - } - usb_dev.close(); - return SANE_STATUS_GOOD; + return dev; } -static SANE_Status -attach_one_device_impl(SANE_String_Const devname) -{ - 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) +// this function is passed to C API and must not throw +static SANE_Status attach_one_device(SANE_String_Const devname) noexcept { return wrap_exceptions_to_status_code(__func__, [=]() { - return attach_one_device_impl(devname); + attach_device_by_name(devname, false); }); } @@ -4471,24 +4446,19 @@ config_attach_genesys(SANEI_Config __sane_unused__ *config, const char *devname) } /* probes for scanner to attach to the backend */ -static SANE_Status -probe_genesys_devices (void) +static void probe_genesys_devices (void) { DBG_HELPER(dbg); SANEI_Config config; - SANE_Status status = SANE_STATUS_GOOD; // set configuration options structure : no option for this backend config.descriptors = nullptr; config.values = nullptr; config.count = 0; - /* generic configure and attach function */ - status = sanei_configure_attach (GENESYS_CONFIG_FILE, &config, - config_attach_genesys); + TIE(sanei_configure_attach(GENESYS_CONFIG_FILE, &config, config_attach_genesys)); DBG(DBG_info, "%s: %zu devices currently attached\n", __func__, s_devices->size()); - return status; } /** @@ -4677,8 +4647,7 @@ static void genesys_buffer_image(Genesys_Scanner *s) /* -------------------------- SANE API functions ------------------------- */ -SANE_Status -sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize) +void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT (); DBG_HELPER_ARGS(dbg, "authorize %s null", authorize ? "!=" : "=="); @@ -4721,7 +4690,7 @@ sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize) ); // cold-plug case :detection of allready connected scanners - return probe_genesys_devices (); + probe_genesys_devices(); } @@ -4729,7 +4698,7 @@ extern "C" SANE_Status sane_init(SANE_Int * version_code, SANE_Auth_Callback aut { return wrap_exceptions_to_status_code(__func__, [=]() { - return sane_init_impl(version_code, authorize); + sane_init_impl(version_code, authorize); }); } @@ -4748,8 +4717,7 @@ extern "C" void sane_exit() catch_all_exceptions(__func__, [](){ sane_exit_impl(); }); } -SANE_Status -sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only) +void sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only) { DBG_HELPER_ARGS(dbg, "local_only = %s", local_only ? "true" : "false"); @@ -4786,20 +4754,17 @@ sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_only) s_sane_devices_ptrs->push_back(nullptr); *const_cast(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) { 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 -sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle) +static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle) { DBG_HELPER_ARGS(dbg, "devicename = %s", devicename); Genesys_Device* dev = nullptr; @@ -4817,20 +4782,16 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle) } } - if (!dev) - { - DBG(DBG_info, "%s: couldn't find `%s' in devlist, trying attach\n", __func__, devicename); - SANE_Status status = attach(devicename, &dev, true); - if (status != SANE_STATUS_GOOD) { - DBG(DBG_info, "%s: failed to attach: %s\n", __func__, sane_strstatus(status)); - return status; - } - } - else - DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->model->name); - } - else - { + if (!dev) { + DBG(DBG_info, "%s: couldn't find `%s' in devlist, trying attach\n", __func__, + devicename); + dbg.status("attach_device_by_name"); + dev = attach_device_by_name(devicename, true); + dbg.clear(); + } else { + DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->model->name); + } + } else { // empty devicename or "genesys" -> use first device if (!s_devices->empty()) { dev = &s_devices->front(); @@ -4838,8 +4799,9 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle) } } - if (!dev) - return SANE_STATUS_INVAL; + if (!dev) { + throw SaneException("could not find the device to open: %s", devicename); + } if (dev->model->flags & GENESYS_FLAG_UNTESTED) { @@ -4897,15 +4859,13 @@ sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle) 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) { return wrap_exceptions_to_status_code(__func__, [=]() { - return sane_open_impl(devicename, handle); + sane_open_impl(devicename, handle); }); } @@ -5004,16 +4964,13 @@ sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) return ret; } -/* gets an option , called by sane_control_option */ -static SANE_Status -get_option_value (Genesys_Scanner * s, int option, void *val) +static void get_option_value(Genesys_Scanner* s, int option, void* val) { DBG_HELPER(dbg); unsigned int i; SANE_Word* table = nullptr; std::vector gamma_table; unsigned option_size = 0; - SANE_Status status = SANE_STATUS_GOOD; const Genesys_Sensor* sensor = nullptr; if (sanei_genesys_has_sensor(s->dev, s->dev->settings.xres, s->dev->settings.get_channels(), @@ -5204,7 +5161,6 @@ get_option_value (Genesys_Scanner * s, int option, void *val) default: DBG(DBG_warn, "%s: can't get unknown option %d\n", __func__, option); } - return status; } /** @brief set calibration file value @@ -5234,12 +5190,9 @@ static void set_calibration_value(Genesys_Scanner* s, const char* val) } /* sets an option , called by sane_control_option */ -static SANE_Status -set_option_value (Genesys_Scanner * s, int option, void *val, - SANE_Int * myinfo) +static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int* myinfo) { DBG_HELPER(dbg); - SANE_Status status = SANE_STATUS_GOOD; SANE_Word *table; unsigned int i; unsigned option_size = 0; @@ -5567,14 +5520,12 @@ set_option_value (Genesys_Scanner * s, int option, void *val, default: DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option); } - return status; } /* sets and gets scanner option values */ -SANE_Status -sane_control_option_impl(SANE_Handle handle, SANE_Int option, - SANE_Action action, void *val, SANE_Int * info) +void sane_control_option_impl(SANE_Handle handle, SANE_Int option, + SANE_Action action, void *val, SANE_Int * info) { Genesys_Scanner* s = reinterpret_cast(handle); auto action_str = (action == SANE_ACTION_GET_VALUE) ? "get" : @@ -5583,75 +5534,52 @@ sane_control_option_impl(SANE_Handle handle, SANE_Int option, DBG_HELPER_ARGS(dbg, "action = %s, option = %s (%d)", action_str, s->opt[option].name, option); - SANE_Status status = SANE_STATUS_GOOD; SANE_Word cap; SANE_Int myinfo = 0; - if (info) - *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 (info) { + *info = 0; } - if (option >= NUM_OPTIONS || option < 0) - { - DBG(DBG_warn, "%s: option %d >= NUM_OPTIONS || option < 0\n", __func__, option); - return SANE_STATUS_INVAL; + + if (s->scanning) { + throw SaneException(SANE_STATUS_DEVICE_BUSY, + "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; - if (!SANE_OPTION_IS_ACTIVE (cap)) - { - DBG(DBG_warn, "%s: option %d is inactive\n", __func__, option); - return SANE_STATUS_INVAL; + if (!SANE_OPTION_IS_ACTIVE (cap)) { + throw SaneException("option %d is inactive", option); } - switch (action) - { - case SANE_ACTION_GET_VALUE: - status = get_option_value (s, option, val); - break; + switch (action) { + case SANE_ACTION_GET_VALUE: + get_option_value(s, option, val); + break; - case SANE_ACTION_SET_VALUE: - if (!SANE_OPTION_IS_SETTABLE (cap)) - { - DBG(DBG_warn, "%s: option %d is not settable\n", __func__, option); - return SANE_STATUS_INVAL; - } + case SANE_ACTION_SET_VALUE: + if (!SANE_OPTION_IS_SETTABLE (cap)) { + throw SaneException("option %d is not settable", option); + } - status = 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; - } + TIE(sanei_constrain_value(s->opt + option, val, &myinfo)); - status = set_option_value (s, option, val, &myinfo); - break; + set_option_value(s, option, val, &myinfo); + break; - case SANE_ACTION_SET_AUTO: - DBG(DBG_error, - "%s: SANE_ACTION_SET_AUTO unsupported since no option has SANE_CAP_AUTOMATIC\n", - __func__); - status = SANE_STATUS_INVAL; - break; - - default: - DBG(DBG_warn, "%s: unknown action %d for option %d\n", __func__, action, option); - status = SANE_STATUS_INVAL; - break; + case SANE_ACTION_SET_AUTO: + throw SaneException("SANE_ACTION_SET_AUTO unsupported since no option " + "has SANE_CAP_AUTOMATIC"); + default: + throw SaneException("unknown action %d for option %d", action, option); } if (info) *info = myinfo; - - return status; } extern "C" SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, @@ -5659,11 +5587,11 @@ extern "C" SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, { 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); Genesys_Scanner* s = reinterpret_cast(handle); @@ -5687,33 +5615,26 @@ SANE_Status sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params params->lines = -1; } } - - return SANE_STATUS_GOOD; } extern "C" SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters* params) { 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); Genesys_Scanner* s = reinterpret_cast(handle); - SANE_Status status=SANE_STATUS_GOOD; - if (s->pos_top_left_x >= s->pos_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_x >= s->pos_bottom_right_x) { + throw SaneException("top left x >= bottom right x"); } - if (s->pos_top_left_y >= s->pos_bottom_right_y) - { - DBG(DBG_error0, "%s: top left y >= bottom right y --- exiting\n", __func__); - return SANE_STATUS_INVAL; + if (s->pos_top_left_y >= s->pos_bottom_right_y) { + throw SaneException("top left y >= bottom right y"); } /* First make sure we have a current parameter set. Some of the @@ -5743,16 +5664,18 @@ SANE_Status sane_start_impl(SANE_Handle handle) /* check if we need to skip this page, sheetfed scanners * can go to next doc while flatbed ones can't */ if (s->swskip > 0 && IS_ACTIVE(OPT_SWSKIP)) { - status = sanei_magic_isBlank(&s->params, - s->dev->img_buffer.data(), - SANE_UNFIX(s->swskip)); - if(status == SANE_STATUS_NO_DOCS) - { - if (s->dev->model->is_sheetfed) { - DBG(DBG_info, "%s: blank page, recurse\n", __func__); - return sane_start(handle); - } - return status; + auto status = sanei_magic_isBlank(&s->params, + s->dev->img_buffer.data(), + SANE_UNFIX(s->swskip)); + + if (status == SANE_STATUS_NO_DOCS && s->dev->model->is_sheetfed) { + DBG(DBG_info, "%s: blank page, recurse\n", __func__); + sane_start(handle); + return; + } + + if (status != SANE_STATUS_GOOD) { + throw SaneException(status); } } @@ -5775,57 +5698,45 @@ SANE_Status sane_start_impl(SANE_Handle handle) catch_all_exceptions(__func__, [&](){ genesys_derotate(s); }); } } - - return status; } extern "C" SANE_Status sane_start(SANE_Handle handle) { return wrap_exceptions_to_status_code(__func__, [=]() { - return sane_start_impl(handle); + sane_start_impl(handle); }); } -SANE_Status -sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len) +void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len) { DBG_HELPER(dbg); Genesys_Scanner* s = reinterpret_cast(handle); Genesys_Device *dev; size_t local_len; - if (!s) - { - DBG(DBG_error, "%s: handle is null!\n", __func__); - return SANE_STATUS_INVAL; + if (!s) { + throw SaneException("handle is nullptr"); } dev=s->dev; - if (!dev) - { - DBG(DBG_error, "%s: dev is null!\n", __func__); - return SANE_STATUS_INVAL; + if (!dev) { + throw SaneException("dev is nullptr"); } - if (!buf) - { - DBG(DBG_error, "%s: buf is null!\n", __func__); - return SANE_STATUS_INVAL; + if (!buf) { + throw SaneException("buf is nullptr"); } - if (!len) - { - DBG(DBG_error, "%s: len is null!\n", __func__); - return SANE_STATUS_INVAL; + if (!len) { + throw SaneException("len is nullptr"); } *len = 0; - if (!s->scanning) - { - DBG(DBG_warn, "%s: scan was cancelled, is over or has not been initiated yet\n", __func__); - return SANE_STATUS_CANCELLED; + if (!s->scanning) { + throw SaneException(SANE_STATUS_CANCELLED, + "scan was cancelled, is over or has not been initiated yet"); } DBG(DBG_proc, "%s: start, %d maximum bytes required\n", __func__, max_len); @@ -5844,7 +5755,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->parking = true; } - return SANE_STATUS_EOF; + throw SaneException(SANE_STATUS_EOF); } local_len = max_len; @@ -5908,14 +5819,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"); } 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) { return wrap_exceptions_to_status_code(__func__, [=]() { - return sane_read_impl(handle, buf, max_len, len); + sane_read_impl(handle, buf, max_len, len); }); } @@ -5960,50 +5870,44 @@ extern "C" void sane_cancel(SANE_Handle handle) catch_all_exceptions(__func__, [=]() { sane_cancel_impl(handle); }); } -SANE_Status -sane_set_io_mode_impl(SANE_Handle handle, SANE_Bool non_blocking) +void sane_set_io_mode_impl(SANE_Handle handle, SANE_Bool non_blocking) { DBG_HELPER_ARGS(dbg, "handle = %p, non_blocking = %s", handle, non_blocking == SANE_TRUE ? "true" : "false"); Genesys_Scanner* s = reinterpret_cast(handle); - if (!s->scanning) - { - DBG(DBG_error, "%s: not scanning\n", __func__); - return SANE_STATUS_INVAL; + if (!s->scanning) { + throw SaneException("not scanning"); + } + 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) { 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 -sane_get_select_fd_impl(SANE_Handle handle, SANE_Int * fd) +void sane_get_select_fd_impl(SANE_Handle handle, SANE_Int* fd) { DBG_HELPER_ARGS(dbg, "handle = %p, fd = %p", handle, reinterpret_cast(fd)); - Genesys_Scanner *s = (Genesys_Scanner*) handle; + Genesys_Scanner* s = reinterpret_cast(handle); - if (!s->scanning) - { - DBG(DBG_error, "%s: not scanning\n", __func__); - return SANE_STATUS_INVAL; + if (!s->scanning) { + throw SaneException("not scanning"); } - return SANE_STATUS_UNSUPPORTED; + throw SaneException(SANE_STATUS_UNSUPPORTED); } extern "C" SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int* fd) { return wrap_exceptions_to_status_code(__func__, [=]() { - return sane_get_select_fd_impl(handle, fd); + sane_get_select_fd_impl(handle, fd); }); } From 9ca0a109381ebe7d9a4d737bee8cd3b5020811d3 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:33 +0200 Subject: [PATCH 3/6] genesys: Improve class method identifiers in debug messages --- backend/genesys/error.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/genesys/error.h b/backend/genesys/error.h index 265eb5e7a..b1311a4d6 100644 --- a/backend/genesys/error.h +++ b/backend/genesys/error.h @@ -130,8 +130,17 @@ private: 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 SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function) From 1faa3223089cad06d99061cc8c9706079aa08e24 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:34 +0200 Subject: [PATCH 4/6] genesys: Add a way to log messages using DBG_HELPER --- backend/genesys/error.cpp | 36 +++++++++++++++++++++++++++++++++++- backend/genesys/error.h | 7 +++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/genesys/error.cpp b/backend/genesys/error.cpp index c886d42af..6c921c11c 100644 --- a/backend/genesys/error.cpp +++ b/backend/genesys/error.cpp @@ -114,7 +114,11 @@ void SaneException::set_msg(const char* format, std::va_list vlist) const char* status_msg = sane_strstatus(status_); 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) { const char* formatting_error_msg = "(error formatting arguments)"; msg_.reserve(std::strlen(formatting_error_msg) + 3 + status_msg_len); @@ -178,4 +182,34 @@ void DebugMessageHelper::vstatus(const char* format, ...) 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 diff --git a/backend/genesys/error.h b/backend/genesys/error.h index b1311a4d6..b9f2e2849 100644 --- a/backend/genesys/error.h +++ b/backend/genesys/error.h @@ -124,6 +124,13 @@ public: 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: const char* func_ = nullptr; char msg_[MAX_BUF_SIZE]; From 87b5a78e377b5febc2acb79974e30029586bb974 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:35 +0200 Subject: [PATCH 5/6] genesys: Add more logging --- backend/genesys/genesys.cpp | 56 +++++++++++++++++++++++++++++++++---- backend/genesys/low.cpp | 11 ++++++++ backend/genesys/low.h | 1 + 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 12f3f11b7..dbca37a89 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -182,6 +182,7 @@ static const SANE_Range expiration_range = { const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev) { + DBG_HELPER(dbg); for (const auto& sensor : *s_sensors) { if (dev->model->sensor_id == sensor.sensor_id) { 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, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels, + static_cast(scan_method)); for (auto& sensor : *s_sensors) { if (dev->model->sensor_id == sensor.sensor_id && sensor.resolutions.matches(dpi) && 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, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels, + static_cast(scan_method)); return find_sensor_impl(dev, dpi, channels, scan_method) != nullptr; } const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels, + static_cast(scan_method)); const auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method); if (sensor) return *sensor; @@ -222,6 +229,8 @@ Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigne unsigned channels, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels, + static_cast(scan_method)); auto* sensor = find_sensor_impl(dev, dpi, channels, scan_method); if (sensor) return *sensor; @@ -232,6 +241,7 @@ Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigne std::vector> sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "scan_method: %d", static_cast(scan_method)); std::vector> ret; for (const Genesys_Sensor& sensor : sanei_genesys_find_sensors_all_for_write(dev, scan_method)) { ret.push_back(sensor); @@ -242,6 +252,7 @@ std::vector> std::vector> sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method) { + DBG_HELPER_ARGS(dbg, "scan_method: %d", static_cast(scan_method)); std::vector> ret; for (auto& sensor : *s_sensors) { if (dev->model->sensor_id == sensor.sensor_id && sensor.method == scan_method) { @@ -251,9 +262,10 @@ std::vector> return ret; } -void -sanei_genesys_init_structs (Genesys_Device * dev) +void sanei_genesys_init_structs (Genesys_Device * dev) { + DBG_HELPER(dbg); + bool gpo_ok = false; bool motor_ok = false; bool fe_ok = false; @@ -922,7 +934,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, 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) { return; @@ -1652,6 +1664,7 @@ static void genesys_dummy_dark_shading(Genesys_Device* dev, const Genesys_Sensor static void genesys_repark_sensor_before_shading(Genesys_Device* dev) { + DBG_HELPER(dbg); if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) { // 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) @@ -1671,6 +1684,7 @@ static void genesys_repark_sensor_before_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) { dev->cmd_set->slow_back_home(dev, true); } @@ -4353,7 +4367,7 @@ check_present (SANE_String_Const devname) noexcept static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may_wait) { - DBG_HELPER_ARGS(dbg, " may_wait = %d", may_wait); + DBG_HELPER_ARGS(dbg, " devname: %s, may_wait = %d", devname, may_wait); Genesys_Device *dev = nullptr; @@ -4425,6 +4439,7 @@ static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may // this function is passed to C API and must not throw static SANE_Status attach_one_device(SANE_String_Const devname) noexcept { + DBG_HELPER(dbg); return wrap_exceptions_to_status_code(__func__, [=]() { attach_device_by_name(devname, false); @@ -4942,6 +4957,7 @@ extern "C" void sane_close(SANE_Handle handle) const SANE_Option_Descriptor * sane_get_option_descriptor_impl(SANE_Handle handle, SANE_Int option) { + DBG_HELPER(dbg); Genesys_Scanner* s = reinterpret_cast(handle); if (static_cast(option) >= NUM_OPTIONS) { @@ -4964,9 +4980,33 @@ sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) return ret; } +static void print_option(DebugMessageHelper& dbg, const Genesys_Scanner& s, int option, void* val) +{ + switch (s.opt[option].type) { + case SANE_TYPE_INT: { + dbg.vlog(DBG_proc, "value: %d", *reinterpret_cast(val)); + return; + } + case SANE_TYPE_BOOL: { + dbg.vlog(DBG_proc, "value: %s", *reinterpret_cast(val) ? "true" : "false"); + return; + } + case SANE_TYPE_FIXED: { + dbg.vlog(DBG_proc, "value: %f", SANE_UNFIX(*reinterpret_cast(val))); + return; + } + case SANE_TYPE_STRING: { + dbg.vlog(DBG_proc, "value: %s", reinterpret_cast(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(dbg); + DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option); unsigned int i; SANE_Word* table = nullptr; std::vector gamma_table; @@ -5161,6 +5201,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val) default: DBG(DBG_warn, "%s: can't get unknown option %d\n", __func__, option); } + print_option(dbg, *s, option, val); } /** @brief set calibration file value @@ -5192,7 +5233,9 @@ static void set_calibration_value(Genesys_Scanner* s, const char* val) /* sets an option , called by sane_control_option */ static void 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); + print_option(dbg, *s, option, val); + SANE_Word *table; unsigned int i; unsigned option_size = 0; @@ -5615,6 +5658,7 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params) params->lines = -1; } } + debug_dump(DBG_proc, *params); } extern "C" SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters* params) diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index 90df0bb64..fbcc87ee1 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -2654,4 +2654,15 @@ void debug_dump(unsigned level, const Genesys_Sensor& sensor) 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(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 diff --git a/backend/genesys/low.h b/backend/genesys/low.h index 3d0080737..5147f5242 100644 --- a/backend/genesys/low.h +++ b/backend/genesys/low.h @@ -638,6 +638,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 GenesysRegisterSettingSet& regs); void debug_dump(unsigned level, const Genesys_Sensor& sensor); +void debug_dump(unsigned level, const SANE_Parameters& params); } // namespace genesys From d2aaa822f36c0643323eb6abe6f2c7c04591c990 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 27 Oct 2019 11:48:36 +0200 Subject: [PATCH 6/6] genesys: Allow use of TIE() macro outside the genesys namespace --- backend/genesys/error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/genesys/error.h b/backend/genesys/error.h index b9f2e2849..5aba8cf54 100644 --- a/backend/genesys/error.h +++ b/backend/genesys/error.h @@ -98,7 +98,7 @@ private: do { \ SANE_Status tmp_status = function; \ if (tmp_status != SANE_STATUS_GOOD) { \ - throw SaneException(tmp_status); \ + throw ::genesys::SaneException(tmp_status); \ } \ } while (false)