From 7fda9bbf93f4565e1334ebafd0b6caf13d462de4 Mon Sep 17 00:00:00 2001 From: Jan Hauffa Date: Sun, 24 Apr 2011 20:21:41 +0200 Subject: [PATCH] Introduce support for multiple scanners. Keep all state local and ensure that all resources are freed by sane_exit. Ensure that each function returns only those error codes that are valid according to the SANE standard. --- backend/mustek_usb2.c | 322 ++++++++++++++++++++++++++----------- backend/mustek_usb2.h | 31 +++- backend/mustek_usb2_asic.c | 179 +++++++++++++-------- backend/mustek_usb2_asic.h | 7 +- backend/mustek_usb2_high.c | 14 +- 5 files changed, 375 insertions(+), 178 deletions(-) diff --git a/backend/mustek_usb2.c b/backend/mustek_usb2.c index a17f47147..f26fcc4e4 100644 --- a/backend/mustek_usb2.c +++ b/backend/mustek_usb2.c @@ -64,7 +64,9 @@ #include "mustek_usb2.h" -static const SANE_Device **devlist = NULL; +static Scanner_Handle * first_handle = NULL; +static Scanner_Device * first_device = NULL; +static SANE_Device ** devlist; static const SANE_Range u8_range = { 0, /* minimum */ @@ -72,18 +74,6 @@ static const SANE_Range u8_range = { 0 /* quantization */ }; -static SANE_Range x_range = { - SANE_FIX (0.0), - SANE_FIX (8.3 * MM_PER_INCH), - SANE_FIX (0.0) -}; - -static SANE_Range y_range = { - SANE_FIX (0.0), - SANE_FIX (11.6 * MM_PER_INCH), - SANE_FIX (0.0) -}; - static SANE_String_Const mode_list[] = { SANE_I18N ("Color48"), SANE_I18N ("Color24"), @@ -105,38 +95,44 @@ static SANE_String_Const source_list[] = { NULL }; -static const Scanner_Model mustek_A2nu2_model = { - "Mustek", /* device vendor string */ - "BearPaw 2448TA Pro", /* device model name */ +static const Scanner_Model models[] = { + { + "Mustek", /* device vendor string */ + "BearPaw 2448TA Pro", /* device model name */ - {5 /* count */, 1200, 600, 300, 150, 75}, /* possible resolutions */ + 0x055f, 0x0409, /* USB vendor and product ID */ - SANE_FIX (8.5 * MM_PER_INCH), /* size of scan area in mm (x) */ - SANE_FIX (11.8 * MM_PER_INCH), /* size of scan area in mm (y) */ + {5 /* count */, 1200, 600, 300, 150, 75}, /* possible resolutions */ - SANE_FIX (1.46 * MM_PER_INCH), /* size of scan area in TA mode in mm (x) */ - SANE_FIX (6.45 * MM_PER_INCH), /* size of scan area in TA mode in mm (y) */ + /* x and y size of scan area in mm */ + {SANE_FIX (0.0), SANE_FIX (8.5 * MM_PER_INCH), SANE_FIX (0.0)}, + {SANE_FIX (0.0), SANE_FIX (11.8 * MM_PER_INCH), SANE_FIX (0.0)}, - SANE_FALSE, /* invert order of the CCD/CIS colors? */ + /* x and y size of scan area in TA mode in mm */ + {SANE_FIX (0.0), SANE_FIX (1.46 * MM_PER_INCH), SANE_FIX (0.0)}, + {SANE_FIX (0.0), SANE_FIX (6.45 * MM_PER_INCH), SANE_FIX (0.0)}, - 5, /* number of buttons */ + SANE_FALSE, /* invert order of the CCD/CIS colors? */ - /* button names */ - {SANE_NAME_SCAN, SANE_NAME_COPY, SANE_NAME_FAX, SANE_NAME_EMAIL, - "panel"}, + 5, /* number of buttons */ - /* button titles */ - {SANE_TITLE_SCAN, SANE_TITLE_COPY, SANE_TITLE_FAX, SANE_TITLE_EMAIL, - "Panel button"}, + /* button names */ + {SANE_NAME_SCAN, SANE_NAME_COPY, SANE_NAME_FAX, SANE_NAME_EMAIL, + "panel"}, - /* button descriptions */ - {SANE_DESC_SCAN, SANE_DESC_COPY, SANE_DESC_FAX, SANE_DESC_EMAIL, - SANE_I18N ("Panel button")} + /* button titles */ + {SANE_TITLE_SCAN, SANE_TITLE_COPY, SANE_TITLE_FAX, SANE_TITLE_EMAIL, + "Panel button"}, + + /* button descriptions */ + {SANE_DESC_SCAN, SANE_DESC_COPY, SANE_DESC_FAX, SANE_DESC_EMAIL, + SANE_I18N ("Panel button")} + } }; static void -calc_parameters (Mustek_Scanner * s, TARGETIMAGE * pTarget) +calc_parameters (Scanner_Handle * s, TARGETIMAGE * pTarget) { SANE_String val; float x1, y1, x2, y2; @@ -240,7 +236,7 @@ calc_parameters (Mustek_Scanner * s, TARGETIMAGE * pTarget) } static void -update_button_status (Mustek_Scanner * s) +update_button_status (Scanner_Handle * s) { SANE_Byte key; if (Scanner_GetKeyStatus (&s->state, &key) == SANE_STATUS_GOOD) @@ -263,7 +259,7 @@ max_string_size (SANE_String_Const *strings) } static SANE_Status -init_options (Mustek_Scanner * s) +init_options (Scanner_Handle * s) { SANE_Status status; SANE_Bool hasTA; @@ -326,8 +322,8 @@ init_options (Mustek_Scanner * s) s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].size = sizeof (SANE_Word); s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; - s->opt[OPT_RESOLUTION].constraint.word_list = s->model.dpi_values; - s->val[OPT_RESOLUTION].w = s->model.dpi_values[1]; + s->opt[OPT_RESOLUTION].constraint.word_list = s->model->dpi_values; + s->val[OPT_RESOLUTION].w = s->model->dpi_values[1]; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; @@ -365,9 +361,6 @@ init_options (Mustek_Scanner * s) s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; - x_range.max = s->model.x_size; - y_range.max = s->model.y_size; - /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; @@ -376,7 +369,7 @@ init_options (Mustek_Scanner * s) s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].size = sizeof (SANE_Word); s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; - s->opt[OPT_TL_X].constraint.range = &x_range; + s->opt[OPT_TL_X].constraint.range = &s->model->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ @@ -387,7 +380,7 @@ init_options (Mustek_Scanner * s) s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].size = sizeof (SANE_Word); s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; - s->opt[OPT_TL_Y].constraint.range = &y_range; + s->opt[OPT_TL_Y].constraint.range = &s->model->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ @@ -398,8 +391,8 @@ init_options (Mustek_Scanner * s) s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].size = sizeof (SANE_Word); s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; - s->opt[OPT_BR_X].constraint.range = &x_range; - s->val[OPT_BR_X].w = x_range.max; + s->opt[OPT_BR_X].constraint.range = &s->model->x_range; + s->val[OPT_BR_X].w = s->model->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; @@ -409,8 +402,8 @@ init_options (Mustek_Scanner * s) s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].size = sizeof (SANE_Word); s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; - s->opt[OPT_BR_Y].constraint.range = &y_range; - s->val[OPT_BR_Y].w = y_range.max; + s->opt[OPT_BR_Y].constraint.range = &s->model->y_range; + s->val[OPT_BR_Y].w = s->model->y_range.max; /* "sensors" group */ s->opt[OPT_SENSORS_GROUP].title = SANE_TITLE_SENSORS; @@ -424,11 +417,11 @@ init_options (Mustek_Scanner * s) for (i = OPT_BUTTON_1; i <= OPT_BUTTON_5; i++) { SANE_Int idx = i - OPT_BUTTON_1; - if (idx < s->model.buttons) + if (idx < s->model->buttons) { - s->opt[i].name = s->model.button_name[idx]; - s->opt[i].title = s->model.button_title[idx]; - s->opt[i].desc = s->model.button_desc[idx]; + s->opt[i].name = s->model->button_name[idx]; + s->opt[i].title = s->model->button_title[idx]; + s->opt[i].desc = s->model->button_desc[idx]; s->opt[i].cap = SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; } @@ -453,6 +446,98 @@ init_options (Mustek_Scanner * s) return SANE_STATUS_GOOD; } +static SANE_Status +attach_scanner (SANE_String_Const devname) +{ + Scanner_Device * device; + DBG (DBG_INFO, "attach_scanner: devname = %s\n", devname); + + for (device = first_device; device; device = device->next) + { + if (strcmp (devname, device->name) == 0) + { + device->present = SANE_TRUE; + return SANE_STATUS_GOOD; + } + } + + device = malloc (sizeof (*device)); + if (!device) + return SANE_STATUS_NO_MEM; + device->name = strdup (devname); + device->model = NULL; + device->present = SANE_TRUE; + device->next = first_device; + first_device = device; + + return SANE_STATUS_GOOD; +} + +static SANE_Status +probe_devices(unsigned int * num_devices) +{ + SANE_Status status; + Scanner_Device * device, * prev_device; + unsigned int i, n; + + for (i = 0; i < (sizeof (models[0]) / sizeof(models)); i++) + { + status = Asic_FindDevices (models[i].vendor_id, models[i].product_id, + attach_scanner); + if (status != SANE_STATUS_GOOD) + break; + + /* Assign model data to all newly attached devices. */ + for (device = first_device; device; device = device->next) + { + if (device->model) + break; + device->model = &models[i]; + } + } + + /* Remove all devices that are no longer present. */ + n = 0; + prev_device = NULL; + device = first_device; + while (device) + { + if (!device->present) + { + Scanner_Device * next = device->next; + if (prev_device) + prev_device->next = next; + else + first_device = next; + free (device->name); + free (device); + device = next; + } + else + { + n++; + device->present = SANE_FALSE; + device = device->next; + prev_device = device; + } + } + + if (num_devices) + *num_devices = n; + + return status; +} + +static void +free_devlist (void) +{ + SANE_Device ** devlist_ptr; + for (devlist_ptr = devlist; *devlist_ptr; devlist_ptr++) + free (*devlist_ptr); + free (devlist); + devlist = NULL; +} + /****************************** SANE API functions ****************************/ @@ -460,6 +545,7 @@ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { + SANE_Status status; DBG_INIT (); DBG_ENTER (); DBG (DBG_ERR, "SANE Mustek USB2 backend version %d.%d build %d from %s\n", @@ -468,17 +554,30 @@ sane_init (SANE_Int * version_code, if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); + status = probe_devices (NULL); + DBG_LEAVE (); - return SANE_STATUS_GOOD; + return status; } void sane_exit (void) { + Scanner_Device * device; DBG_ENTER (); - free (devlist); - devlist = NULL; + while (first_handle) + sane_close (first_handle); + + while (first_device) + { + device = first_device; + free (first_device->name); + first_device = first_device->next; + free (device); + } + + free_devlist (); DBG_LEAVE (); } @@ -487,44 +586,65 @@ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { + SANE_Status status; + unsigned int num_devices; + Scanner_Device * device; + SANE_Device ** devlist_ptr; DBG_ENTER (); - free (devlist); - devlist = calloc (2, sizeof (devlist[0])); + status = probe_devices (&num_devices); + if (status != SANE_STATUS_GOOD) + return status; + + free_devlist (); + devlist = malloc ((num_devices + 1) * sizeof (*devlist)); if (!devlist) return SANE_STATUS_NO_MEM; - /* HOLD: This is ugly (only one scanner!) and should go to sane_init */ - if (Scanner_IsPresent ()) + devlist_ptr = devlist; + for (device = first_device; device; device = device->next) { - SANE_Device *sane_device = malloc (sizeof (*sane_device)); + SANE_Device * sane_device = malloc (sizeof (*sane_device)); if (!sane_device) return SANE_STATUS_NO_MEM; - sane_device->name = strdup (device_name); - sane_device->vendor = "Mustek"; - sane_device->model = "BearPaw 2448 TA Pro"; - sane_device->type = "flatbed scanner"; - devlist[0] = sane_device; + sane_device->name = device->name; + sane_device->vendor = device->model->vendor_name; + sane_device->model = device->model->model_name; + sane_device->type = SANE_I18N ("flatbed scanner"); + *devlist_ptr++ = sane_device; } - *device_list = devlist; + *devlist_ptr = NULL; + *device_list = (const SANE_Device **) devlist; DBG_LEAVE (); return SANE_STATUS_GOOD; } SANE_Status -sane_open (SANE_String_Const devicename, SANE_Handle * handle) +sane_open (SANE_String_Const devname, SANE_Handle * handle) { SANE_Status status; - Mustek_Scanner *s; + Scanner_Handle * s; + Scanner_Device * device; DBG_ENTER (); - DBG (DBG_FUNC, "devicename=%s\n", devicename); + DBG (DBG_FUNC, "devname=%s\n", devname); + + /* Look up the device name in the list of detected devices. If the device name + is an empty string, use the first device. */ + for (device = first_device; device; device = device->next) + { + if ((devname[0] == '\0') || (strcmp (devname, device->name) == 0)) + break; + } + if (!device) + return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); - s->model = mustek_A2nu2_model; + s->model = device->model; + s->state.chip.device_name = device->name; Scanner_Init (&s->state); @@ -545,9 +665,24 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) void sane_close (SANE_Handle handle) { - Mustek_Scanner *s = handle; + Scanner_Handle * s, * prev_handle = NULL; DBG_ENTER (); + for (s = first_handle; s; s = s->next) + { + if (s == (Scanner_Handle *) handle) + break; + prev_handle = s; + } + if (!s) + { + DBG (DBG_ERR, "attempting to close invalid handle %p\n", handle); + return; + } + + if (s->bIsScanning) + sane_cancel (handle); + Scanner_PowerControl (&s->state, SANE_FALSE, SANE_FALSE); Scanner_BackHome (&s->state); @@ -557,7 +692,13 @@ sane_close (SANE_Handle handle) free (s->val[OPT_MODE].s); free (s->val[OPT_SOURCE].s); - free (handle); + /* Remove from list of open handles. */ + if (prev_handle) + prev_handle->next = s->next; + else + first_handle = s->next; + + free (s); DBG_LEAVE (); } @@ -565,7 +706,7 @@ sane_close (SANE_Handle handle) const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; if ((option >= NUM_OPTIONS) || (option < 0)) return NULL; @@ -580,7 +721,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SANE_Status status; - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; SANE_Word cap; SANE_Int myinfo = 0; TARGETIMAGE target; @@ -591,15 +732,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option, (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); - if (s->bIsScanning) - { - DBG (DBG_ERR, "scanner is busy\n"); - return SANE_STATUS_DEVICE_BUSY; - } if ((option >= NUM_OPTIONS) || (option < 0)) { DBG (DBG_ERR, "option index out of range\n"); - return SANE_STATUS_INVAL; + return SANE_STATUS_UNSUPPORTED; } cap = s->opt[option].cap; @@ -705,24 +841,30 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]); - x_range.max = s->model.x_size; - y_range.max = s->model.y_size; + s->opt[OPT_TL_X].constraint.range = &s->model->x_range; + s->opt[OPT_TL_Y].constraint.range = &s->model->y_range; + s->opt[OPT_BR_X].constraint.range = &s->model->x_range; + s->opt[OPT_BR_Y].constraint.range = &s->model->y_range; } else if (strcmp (s->val[option].s, source_list[SS_NEGATIVE]) == 0) { s->opt[OPT_MODE].size = max_string_size (negative_mode_list); s->opt[OPT_MODE].constraint.string_list = negative_mode_list; s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]); - x_range.max = s->model.x_size_ta; - y_range.max = s->model.y_size_ta; + s->opt[OPT_TL_X].constraint.range = &s->model->x_range_ta; + s->opt[OPT_TL_Y].constraint.range = &s->model->y_range_ta; + s->opt[OPT_BR_X].constraint.range = &s->model->x_range_ta; + s->opt[OPT_BR_Y].constraint.range = &s->model->y_range_ta; } else if (strcmp (s->val[option].s, source_list[SS_POSITIVE]) == 0) { s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]); - x_range.max = s->model.x_size_ta; - y_range.max = s->model.y_size_ta; + s->opt[OPT_TL_X].constraint.range = &s->model->x_range_ta; + s->opt[OPT_TL_Y].constraint.range = &s->model->y_range_ta; + s->opt[OPT_BR_X].constraint.range = &s->model->x_range_ta; + s->opt[OPT_BR_Y].constraint.range = &s->model->y_range_ta; } } myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; @@ -737,7 +879,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, else { DBG (DBG_ERR, "unknown action %d for option %d\n", action, option); - return SANE_STATUS_INVAL; + return SANE_STATUS_UNSUPPORTED; } DBG_LEAVE (); @@ -747,7 +889,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; DBG_ENTER (); DBG (DBG_INFO, "params.format = %d\n", s->params.format); @@ -767,7 +909,7 @@ SANE_Status sane_start (SANE_Handle handle) { SANE_Status status; - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; TARGETIMAGE target; DBG_ENTER (); @@ -823,7 +965,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; unsigned short lines; SANE_Int bytes_read; DBG_ENTER (); @@ -848,7 +990,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, s->bIsReading = SANE_TRUE; status = Scanner_GetRows (&s->state, s->scan_buf, &lines, - s->model.isRGBInvert); + s->model->isRGBInvert); if (status != SANE_STATUS_GOOD) { s->bIsReading = SANE_FALSE; @@ -896,7 +1038,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, void sane_cancel (SANE_Handle handle) { - Mustek_Scanner *s = handle; + Scanner_Handle * s = handle; int i; DBG_ENTER (); diff --git a/backend/mustek_usb2.h b/backend/mustek_usb2.h index dcca06b8d..1d99e7087 100644 --- a/backend/mustek_usb2.h +++ b/backend/mustek_usb2.h @@ -99,13 +99,17 @@ typedef struct /** Device model name. */ SANE_String_Const model_name; + /** USB vendor and product ID */ + unsigned short vendor_id; + unsigned short product_id; + /** @name Scanner model parameters */ /*@{ */ SANE_Word dpi_values[MAX_RESOLUTIONS]; /* possible resolutions */ - SANE_Fixed x_size; /* size of scan area in mm */ - SANE_Fixed y_size; - SANE_Fixed x_size_ta; /* size of scan area in TA mode in mm */ - SANE_Fixed y_size_ta; + SANE_Range x_range; /* size of scan area in mm */ + SANE_Range y_range; + SANE_Range x_range_ta; /* size of scan area in TA mode in mm */ + SANE_Range y_range_ta; SANE_Bool isRGBInvert; /* order of the CCD/CIS colors: RGB if SANE_False, BGR otherwise */ @@ -118,21 +122,32 @@ typedef struct /*@} */ } Scanner_Model; -typedef struct Mustek_Scanner +typedef struct Scanner_Device { - struct Mustek_Scanner *next; + struct Scanner_Device * next; + const Scanner_Model * model; + SANE_String name; + SANE_Bool present; +} Scanner_Device; + +typedef struct Scanner_Handle +{ + struct Scanner_Handle * next; + + const Scanner_Model * model; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; - Scanner_Model model; + Scanner_State state; + SANE_Bool bIsScanning; SANE_Bool bIsReading; SANE_Word read_rows; /* number of image lines left to read */ SANE_Byte * scan_buf; SANE_Byte * scan_buf_start; SANE_Int scan_buf_len; -} Mustek_Scanner; +} Scanner_Handle; #endif diff --git a/backend/mustek_usb2_asic.c b/backend/mustek_usb2_asic.c index 351a47c2c..465c3cc8c 100644 --- a/backend/mustek_usb2_asic.c +++ b/backend/mustek_usb2_asic.c @@ -130,7 +130,7 @@ SwitchBank (ASIC * chip, unsigned short reg) if (bank > SELECT_REGISTER_BANK2) { DBG (DBG_ERR, "invalid register %d\n", reg); - return SANE_STATUS_INVAL; + return SANE_STATUS_IO_ERROR; } if (chip->RegisterBankStatus != bank) @@ -1783,18 +1783,21 @@ SetExtraSettings (ASIC * chip, unsigned short wXResolution, /* ---------------------- high level ASIC functions ------------------------ */ -/* HOLD: We don't want to have global vid/pids */ -static const unsigned short ProductID = 0x0409; -static const unsigned short VendorID = 0x055f; - -SANE_String_Const device_name; - -static SANE_Status -attach_one_scanner (SANE_String_Const devname) +SANE_Status +Asic_FindDevices (unsigned short wVendorID, unsigned short wProductID, + SANE_Status (* attach) (SANE_String_Const devname)) { - DBG (DBG_INFO, "attach_one_scanner: devname = %s\n", devname); - device_name = devname; - return SANE_STATUS_GOOD; + SANE_Status status; + DBG_ASIC_ENTER (); + + sanei_usb_init (); + status = sanei_usb_find_devices (wVendorID, wProductID, attach); + if (status != SANE_STATUS_GOOD) + DBG (DBG_ERR, "sanei_usb_find_devices failed: %s\n", + sane_strstatus (status)); + + DBG_ASIC_LEAVE (); + return status; } SANE_Status @@ -1806,29 +1809,16 @@ Asic_Open (ASIC * chip) if (chip->firmwarestate > FS_OPENED) { DBG (DBG_ASIC, "chip already open, fd=%d\n", chip->fd); - return SANE_STATUS_INVAL; + return SANE_STATUS_DEVICE_BUSY; } - device_name = NULL; sanei_usb_init (); - status = sanei_usb_find_devices (VendorID, ProductID, attach_one_scanner); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_ERR, "sanei_usb_find_devices failed: %s\n", - sane_strstatus (status)); - return status; - } - if (!device_name) - { - DBG (DBG_ERR, "no scanner found\n"); - return SANE_STATUS_INVAL; - } - status = sanei_usb_open (device_name, &chip->fd); + status = sanei_usb_open (chip->device_name, &chip->fd); if (status != SANE_STATUS_GOOD) { DBG (DBG_ERR, "sanei_usb_open of %s failed: %s\n", - device_name, sane_strstatus (status)); + chip->device_name, sane_strstatus (status)); return status; } @@ -1869,7 +1859,7 @@ Asic_Open (ASIC * chip) return status; } - DBG (DBG_INFO, "device %s successfully opened\n", device_name); + DBG (DBG_INFO, "device %s successfully opened\n", chip->device_name); DBG_ASIC_LEAVE (); return SANE_STATUS_GOOD; } @@ -1927,10 +1917,15 @@ Asic_TurnLamp (ASIC * chip, SANE_Bool isLampOn) { DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1); @@ -1948,10 +1943,15 @@ Asic_TurnTA (ASIC * chip, SANE_Bool isTAOn) { DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1); @@ -2065,10 +2065,15 @@ Asic_SetWindow (ASIC * chip, SCANSOURCE lsLightSource, lsLightSource, ScanType, bScanBits, wXResolution, wYResolution, wX, wY, wWidth, wHeight); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } status = PrepareScanChip (chip); @@ -2126,8 +2131,7 @@ Asic_SetWindow (ASIC * chip, SCANSOURCE lsLightSource, MOTOR1_SERIAL_INTERFACE_G10_8_ENABLE); SendData (chip, ES01_9A_AFEControl, AD9826_AFE); - if (ScanType == SCAN_TYPE_NORMAL) - SetAFEGainOffset (chip); + SetAFEGainOffset (chip); SendData (chip, ES01_DB_PH_RESET_EDGE_TIMING_ADJUST, 0x00); SendData (chip, ES01_DC_CLEAR_EDGE_TO_PH_TG_EDGE_WIDTH, 0); SendData (chip, ES01_00_ADAFEConfiguration, 0x70); @@ -2189,19 +2193,19 @@ Asic_SetWindow (ASIC * chip, SCANSOURCE lsLightSource, SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT, SHADING_4_INT_12_DEC_ES01); - SetPackAddress (chip, wWidth, wX, XRatioAdderDouble, - XRatioTypeDouble, 0, &ValidPixelNumber); - SetExtraSettings (chip, wXResolution, wCCD_PixelNumber, - (ScanType == SCAN_TYPE_NORMAL) ? SANE_FALSE : SANE_TRUE); + SetPackAddress (chip, wWidth, wX, XRatioAdderDouble, XRatioTypeDouble, 0, + &ValidPixelNumber); if (ScanType == SCAN_TYPE_NORMAL) { + SetExtraSettings (chip, wXResolution, wCCD_PixelNumber, SANE_FALSE); SetMotorStepTable (chip, &pMotorStepsTable, wY, wHeight * SENSOR_DPI / wYResolution * wMultiMotorStep, wYResolution); } else { + SetExtraSettings (chip, wXResolution, wCCD_PixelNumber, SANE_TRUE); SetMotorStepTableForCalibration (chip, &pMotorStepsTable, wHeight * SENSOR_DPI / wYResolution * wMultiMotorStep); } @@ -2271,17 +2275,20 @@ Asic_SetWindow (ASIC * chip, SCANSOURCE lsLightSource, CalMotorTable.AccStepBeforeScan = pMotorStepsTable.wScanAccSteps; CalMotorTable.DecStepAfterScan = pMotorStepsTable.bScanDecSteps; CalMotorTable.pMotorTable = pMotorTable; - if (ScanType == SCAN_TYPE_NORMAL) - CalculateScanMotorTable (&CalMotorTable); - else - CalculateMoveMotorTable (&CalMotorTable); CurrentPhase.MoveType = bMotorMoveType; CurrentPhase.MotorDriverIs3967 = 0; + if (ScanType == SCAN_TYPE_NORMAL) - CurrentPhase.MotorCurrent = CalculateMotorCurrent (EndSpeed); + { + CalculateScanMotorTable (&CalMotorTable); + CurrentPhase.MotorCurrent = CalculateMotorCurrent (EndSpeed); + } else - CurrentPhase.MotorCurrent = 200; + { + CalculateMoveMotorTable (&CalMotorTable); + CurrentPhase.MotorCurrent = 200; + } SetMotorCurrentAndPhase (chip, &CurrentPhase); DBG (DBG_ASIC, "MotorCurrent=%d,LinePixelReport=%d\n", @@ -2335,10 +2342,15 @@ Asic_ScanStart (ASIC * chip) SANE_Status status; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } status = GetChipStatus(chip, 0x1c | 0x20, NULL); @@ -2367,7 +2379,7 @@ Asic_ScanStop (ASIC * chip) if (chip->firmwarestate < FS_OPENED) { DBG (DBG_ERR, "scanner is not open\n"); - return SANE_STATUS_INVAL; + return SANE_STATUS_CANCELLED; } if (chip->firmwarestate < FS_SCANNING) return SANE_STATUS_GOOD; @@ -2419,7 +2431,7 @@ Asic_ReadImage (ASIC * chip, SANE_Byte * pBuffer, unsigned short LinesCount) if (chip->firmwarestate != FS_SCANNING) { DBG (DBG_ERR, "scanner is not scanning\n"); - return SANE_STATUS_INVAL; + return SANE_STATUS_CANCELLED; } dwXferBytes = (unsigned int) LinesCount * chip->dwBytesCountPerRow; @@ -2442,10 +2454,15 @@ Asic_CheckFunctionKey (ASIC * chip, SANE_Byte * key) SANE_Byte bBuffer_1, bBuffer_2; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } SendData (chip, ES01_97_GPIOControl0_7, 0x00); @@ -2488,10 +2505,15 @@ Asic_IsTAConnected (ASIC * chip, SANE_Bool * hasTA) SANE_Byte bBuffer_1 = 0xff; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } SendData (chip, ES01_97_GPIOControl0_7, 0x00); @@ -2523,7 +2545,7 @@ Asic_ReadCalibrationData (ASIC * chip, SANE_Byte * pBuffer, if (chip->firmwarestate != FS_SCANNING) { DBG (DBG_ERR, "scanner is not scanning\n"); - return SANE_STATUS_INVAL; + return SANE_STATUS_CANCELLED; } if (separateColors) @@ -2585,10 +2607,15 @@ Asic_MotorMove (ASIC * chip, SANE_Bool isForward, unsigned int dwTotalSteps) SANE_Byte bActionType; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } bActionType = isForward ? ACTION_TYPE_FORWARD : ACTION_TYPE_BACKWARD; @@ -2606,10 +2633,15 @@ Asic_CarriageHome (ASIC * chip) SANE_Bool LampHome; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } status = IsCarriageHome (chip, &LampHome); @@ -2634,10 +2666,15 @@ Asic_SetShadingTable (ASIC * chip, unsigned short * pWhiteShading, double dbXRatioAdderDouble; DBG_ASIC_ENTER (); - if (chip->firmwarestate != FS_OPENED) + if (chip->firmwarestate < FS_OPENED) { - DBG (DBG_ERR, "scanner is busy or not open\n"); - return SANE_STATUS_INVAL; + DBG (DBG_ERR, "scanner is not open\n"); + return SANE_STATUS_CANCELLED; + } + if (chip->firmwarestate > FS_OPENED) + { + DBG (DBG_ERR, "scanner is busy\n"); + return SANE_STATUS_DEVICE_BUSY; } if (wXResolution > (SENSOR_DPI / 2)) diff --git a/backend/mustek_usb2_asic.h b/backend/mustek_usb2_asic.h index 900e3d017..ef63c4a84 100644 --- a/backend/mustek_usb2_asic.h +++ b/backend/mustek_usb2_asic.h @@ -191,6 +191,7 @@ typedef struct typedef struct { + SANE_String_Const device_name; int fd; /* file descriptor of scanner */ FIRMWARESTATE firmwarestate; @@ -967,10 +968,12 @@ typedef struct #define ES01_2CF_VALID_PIXEL_PARAMETER_OF_SEGMENT16 0x2CF -extern SANE_String_Const device_name; - void SetAFEGainOffset (ASIC * chip); +SANE_Status Asic_FindDevices (unsigned short wVendorID, + unsigned short wProductID, + SANE_Status (* attach) + (SANE_String_Const devname)); SANE_Status Asic_Open (ASIC * chip); SANE_Status Asic_Close (ASIC * chip); void Asic_Initialize (ASIC * chip); diff --git a/backend/mustek_usb2_high.c b/backend/mustek_usb2_high.c index 63e7c3326..39a13f0f1 100644 --- a/backend/mustek_usb2_high.c +++ b/backend/mustek_usb2_high.c @@ -957,7 +957,7 @@ Scanner_GetRows (Scanner_State * st, SANE_Byte * pBlock, if (!st->bOpened || !st->bPrepared) { DBG (DBG_FUNC, "invalid state\n"); - return SANE_STATUS_INVAL; + return SANE_STATUS_CANCELLED; } switch (st->Target.cmColorMode) @@ -1269,7 +1269,6 @@ AdjustAD (Scanner_State * st) for (i = 0; i < 10; i++) { DBG (DBG_FUNC, "first AD offset adjustment loop\n"); - SetAFEGainOffset (&st->chip); status = Asic_ScanStart (&st->chip); if (status != SANE_STATUS_GOOD) goto out; @@ -1320,6 +1319,8 @@ AdjustAD (Scanner_State * st) } } + SetAFEGainOffset (&st->chip); + if (!(wMinValue[0] > 15 || wMinValue[0] < 5 || wMinValue[1] > 15 || wMinValue[1] < 5 || wMinValue[2] > 15 || wMinValue[2] < 5)) @@ -1346,7 +1347,6 @@ AdjustAD (Scanner_State * st) for (i = 0; i < 10; i++) { - SetAFEGainOffset (&st->chip); status = Asic_ScanStart (&st->chip); if (status != SANE_STATUS_GOOD) goto out; @@ -1403,6 +1403,8 @@ AdjustAD (Scanner_State * st) st->chip.AD.Direction[j]); } + SetAFEGainOffset (&st->chip); + if (!((wMaxValue[0] - wMinValue[0]) > MAX_LEVEL_RANGE || (wMaxValue[0] - wMinValue[0]) < MIN_LEVEL_RANGE || (wMaxValue[1] - wMinValue[1]) > MAX_LEVEL_RANGE || @@ -1415,7 +1417,6 @@ AdjustAD (Scanner_State * st) for (i = 0; i < 8; i++) { DBG (DBG_FUNC, "second AD offset adjustment loop\n"); - SetAFEGainOffset (&st->chip); status = Asic_ScanStart (&st->chip); if (status != SANE_STATUS_GOOD) goto out; @@ -1462,6 +1463,8 @@ AdjustAD (Scanner_State * st) st->chip.AD.Direction[j]); } + SetAFEGainOffset (&st->chip); + if (!(wMinValue[0] > 20 || wMinValue[0] < 10 || wMinValue[1] > 20 || wMinValue[1] < 10 || wMinValue[2] > 20 || wMinValue[2] < 10)) @@ -1520,7 +1523,6 @@ FindTopLeft (Scanner_State * st, unsigned short * pwStartX, if (status != SANE_STATUS_GOOD) goto out; - SetAFEGainOffset (&st->chip); status = Asic_ScanStart (&st->chip); if (status != SANE_STATUS_GOOD) goto out; @@ -1705,7 +1707,6 @@ LineCalibration16Bits (Scanner_State * st) } /* read white level data */ - SetAFEGainOffset (&st->chip); status = Asic_SetWindow (&st->chip, st->Target.ssScanSource, SCAN_TYPE_CALIBRATE_LIGHT, 48, st->Target.wXDpi, 600, st->Target.wX, 0, wCalWidth, wCalHeight); @@ -1726,7 +1727,6 @@ LineCalibration16Bits (Scanner_State * st) goto out1; /* read dark level data */ - SetAFEGainOffset (&st->chip); status = Asic_SetWindow (&st->chip, st->Target.ssScanSource, SCAN_TYPE_CALIBRATE_DARK, 48, st->Target.wXDpi, 600, st->Target.wX, 0, wCalWidth, wCalHeight);