From 933b53608dcaec5ffac09ea9caa1cb334d960cfb Mon Sep 17 00:00:00 2001 From: Charles Quarra Date: Fri, 18 Nov 2022 23:40:01 +0000 Subject: [PATCH] Adds support for total and roller counters --- backend/canon_dr-cmd.h | 3 +- backend/canon_dr.c | 107 +++++++++++++++++++++++++++++++++++++++++ backend/canon_dr.h | 7 +++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/backend/canon_dr-cmd.h b/backend/canon_dr-cmd.h index e3414c895..523368991 100644 --- a/backend/canon_dr-cmd.h +++ b/backend/canon_dr-cmd.h @@ -255,7 +255,8 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) /*counters*/ #define R_COUNTERS_len 0x80 -#define get_R_COUNTERS_scans(in) getnbyte(in + 0x04, 4) +#define get_R_COUNTERS_total(in) getnbyte(in + 0x04, 4) +#define get_R_COUNTERS_last_srv(in) getnbyte(in + 0x44, 4) /*endorser unread?*/ diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 2efd8e7e0..4eec58511 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -1001,6 +1001,13 @@ attach_one (const char *device_name, int connType) return ret; } + /* enable/read the lifecycle counters */ + ret = init_counters (s); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "attach_one: unable to detect lifecycle counters, continuing\n"); + return ret; + } + /* sets SANE option 'values' to good defaults */ ret = init_user (s); if (ret != SANE_STATUS_GOOD) { @@ -1929,6 +1936,29 @@ init_panel (struct scanner *s) return ret; } +/* + * This function enables the lifecycle counters if available + */ +static SANE_Status +init_counters (struct scanner *s) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + DBG (10, "init_counters: start\n"); + + ret = read_counters(s); + if(ret){ + DBG (5, "init_counters: disabling lifecycle counters\n"); + s->can_read_lifecycle_counters = 0; + return ret; + } + + s->can_read_lifecycle_counters = 1; + DBG (10, "init_counters: finish\n"); + + return ret; +} + /* * set good default user values. * struct is already initialized to 0. @@ -2859,6 +2889,34 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + if(option==OPT_ROLLERCOUNTER){ + opt->name = "roller-counter"; + opt->title = "Roller Counter"; + opt->desc = "Scans since last roller replacement"; + opt->type = SANE_TYPE_INT; + opt->unit = SANE_UNIT_NONE; + opt->constraint_type = SANE_CONSTRAINT_NONE; + + if (s->can_read_lifecycle_counters) + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + + if(option==OPT_TOTALCOUNTER){ + opt->name = "total-counter"; + opt->title = "Total Counter"; + opt->desc = "Total scan count of the device"; + opt->type = SANE_TYPE_INT; + opt->unit = SANE_UNIT_NONE; + opt->constraint_type = SANE_CONSTRAINT_NONE; + + if (s->can_read_lifecycle_counters) + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + if(option==OPT_ADF_LOADED){ opt->name = "adf-loaded"; opt->title = "ADF Loaded"; @@ -3173,6 +3231,16 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->panel_counter; return ret; + case OPT_ROLLERCOUNTER: + ret = read_counters(s); + *val_p = s->roller_counter; + return ret; + + case OPT_TOTALCOUNTER: + ret = read_counters(s); + *val_p = s->total_counter; + return ret; + case OPT_ADF_LOADED: ret = read_sensors(s,OPT_ADF_LOADED); *val_p = s->sensor_adf_loaded; @@ -3925,6 +3993,45 @@ ssm_do (struct scanner *s) return ret; } +static SANE_Status +read_counters(struct scanner *s) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + unsigned char cmd[READ_len]; + size_t cmdLen = READ_len; + + unsigned char in[R_COUNTERS_len]; + size_t inLen = R_COUNTERS_len; + + DBG(10, "read_counters: start\n"); + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, READ_code); + set_R_datatype_code(cmd, SR_datatype_counters); + set_R_xfer_length(cmd, inLen); + + ret = do_cmd( + s, 1, 0, + cmd, cmdLen, + NULL, 0, + in, &inLen + ); + + if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF){ + + s->total_counter = get_R_COUNTERS_total(in); + s->roller_counter = s->total_counter - get_R_COUNTERS_last_srv(in); + + DBG(10, "read_counters: total counter: %d roller_counter %d \n",s->total_counter,s->roller_counter); + ret = SANE_STATUS_GOOD; + }else{ + DBG(10, "read_counters: ERROR: %d\n",ret); + } + + return ret; +} + static SANE_Status read_sensors(struct scanner *s,SANE_Int option) { diff --git a/backend/canon_dr.h b/backend/canon_dr.h index 7afbb9042..fa38cd444 100644 --- a/backend/canon_dr.h +++ b/backend/canon_dr.h @@ -60,6 +60,8 @@ enum scanner_Option OPT_COUNTONLY, OPT_BYPASSMODE, OPT_COUNTER, + OPT_ROLLERCOUNTER, + OPT_TOTALCOUNTER, OPT_ADF_LOADED, OPT_CARD_LOADED, @@ -207,6 +209,7 @@ struct scanner int can_read_sensors; int can_read_panel; int can_write_panel; + int can_read_lifecycle_counters; int rgb_format; /* meaning unknown */ int padding; /* meaning unknown */ @@ -379,6 +382,8 @@ struct scanner int panel_counter; int sensor_adf_loaded; int sensor_card_loaded; + int roller_counter; + int total_counter; /* values which are used to track the frontend's access to sensors */ char panel_read[OPT_COUNTER - OPT_START + 1]; @@ -542,6 +547,7 @@ static SANE_Status init_inquire (struct scanner *s); static SANE_Status init_vpd (struct scanner *s); static SANE_Status init_model (struct scanner *s); static SANE_Status init_panel (struct scanner *s); +static SANE_Status init_counters (struct scanner *s); static SANE_Status init_user (struct scanner *s); static SANE_Status init_options (struct scanner *s); @@ -589,6 +595,7 @@ static SANE_Status update_params (struct scanner *s, int calib); static SANE_Status update_i_params (struct scanner *s); static SANE_Status clean_params (struct scanner *s); +static SANE_Status read_counters(struct scanner *s); static SANE_Status read_sensors(struct scanner *s, SANE_Int option); static SANE_Status read_panel(struct scanner *s, SANE_Int option); static SANE_Status send_panel(struct scanner *s);