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.
merge-requests/1/head
Jan Hauffa 2011-04-24 20:21:41 +02:00 zatwierdzone przez m. allan noah
rodzic 6865eaf6ed
commit 7fda9bbf93
5 zmienionych plików z 375 dodań i 178 usunięć

Wyświetl plik

@ -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 ();

Wyświetl plik

@ -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

Wyświetl plik

@ -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))

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);