kopia lustrzana https://gitlab.com/sane-project/backends
backend in progress
rodzic
175a8b0042
commit
51ba313173
|
@ -829,8 +829,9 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
|
|||
case SANE_ACTION_SET_VALUE:
|
||||
|
||||
if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap))
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
{
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
/* Make sure boolean values are only TRUE or FALSE */
|
||||
if (lexmark_device->opt[option].type == SANE_TYPE_BOOL)
|
||||
{
|
||||
|
|
|
@ -1,9 +1,256 @@
|
|||
#define BUILD 1
|
||||
#include "lexmark_x2600.h"
|
||||
|
||||
#define BUILD 1
|
||||
#define LEXMARK_X2600_CONFIG_FILE "lexmark_x2600.conf"
|
||||
#define MAX_OPTION_STRING_SIZE 255
|
||||
|
||||
static Lexmark_Device *first_device = 0;
|
||||
static SANE_Int num_devices = 0;
|
||||
static const SANE_Device **devlist = 0;
|
||||
|
||||
static SANE_Bool initialized = SANE_FALSE;
|
||||
|
||||
static SANE_Int dpi_list[] = {
|
||||
5, 75, 100, 200, 300, 600
|
||||
};
|
||||
|
||||
static SANE_String_Const mode_list[] = {
|
||||
SANE_VALUE_SCAN_MODE_COLOR,
|
||||
SANE_VALUE_SCAN_MODE_GRAY,
|
||||
NULL
|
||||
};
|
||||
|
||||
static SANE_Range x_range = {
|
||||
1, /* minimum */
|
||||
5078, /* maximum */
|
||||
2 /* quantization : 16 is required so we
|
||||
never have an odd width */
|
||||
};
|
||||
|
||||
static SANE_Range y_range = {
|
||||
1, /* minimum */
|
||||
7015, /* maximum */
|
||||
/* 7032, for X74 */
|
||||
2 /* quantization */
|
||||
};
|
||||
|
||||
SANE_Status
|
||||
sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
|
||||
usb_write_then_read_twice (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size)
|
||||
{
|
||||
size_t buf_size;
|
||||
SANE_Byte buf[3];
|
||||
SANE_Status status;
|
||||
|
||||
status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
init_options (Lexmark_Device * dev)
|
||||
{
|
||||
|
||||
SANE_Option_Descriptor *od;
|
||||
|
||||
DBG (2, "init_options: dev = %p\n", (void *) dev);
|
||||
|
||||
/* number of options */
|
||||
od = &(dev->opt[OPT_NUM_OPTS]);
|
||||
od->name = SANE_NAME_NUM_OPTIONS;
|
||||
od->title = SANE_TITLE_NUM_OPTIONS;
|
||||
od->desc = SANE_DESC_NUM_OPTIONS;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
|
||||
|
||||
/* mode - sets the scan mode: Color, Gray, or Line Art */
|
||||
od = &(dev->opt[OPT_MODE]);
|
||||
od->name = SANE_NAME_SCAN_MODE;
|
||||
od->title = SANE_TITLE_SCAN_MODE;
|
||||
od->desc = SANE_DESC_SCAN_MODE;;
|
||||
od->type = SANE_TYPE_STRING;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = MAX_OPTION_STRING_SIZE;
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
od->constraint.string_list = mode_list;
|
||||
dev->val[OPT_MODE].s = malloc (od->size);
|
||||
if (!dev->val[OPT_MODE].s)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
strcpy (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR);
|
||||
|
||||
/* resolution */
|
||||
od = &(dev->opt[OPT_RESOLUTION]);
|
||||
od->name = SANE_NAME_SCAN_RESOLUTION;
|
||||
od->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
od->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_DPI;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
od->constraint.word_list = dpi_list;
|
||||
dev->val[OPT_RESOLUTION].w = 200;
|
||||
|
||||
/* preview mode */
|
||||
od = &(dev->opt[OPT_PREVIEW]);
|
||||
od->name = SANE_NAME_PREVIEW;
|
||||
od->title = SANE_TITLE_PREVIEW;
|
||||
od->desc = SANE_DESC_PREVIEW;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->type = SANE_TYPE_BOOL;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
dev->val[OPT_PREVIEW].w = SANE_FALSE;
|
||||
|
||||
/* "Geometry" group: */
|
||||
od = &(dev->opt[OPT_GEOMETRY_GROUP]);
|
||||
od->name = "";
|
||||
od->title = SANE_I18N ("Geometry");
|
||||
od->desc = "";
|
||||
od->type = SANE_TYPE_GROUP;
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->size = 0;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
|
||||
/* top-left x */
|
||||
od = &(dev->opt[OPT_TL_X]);
|
||||
od->name = SANE_NAME_SCAN_TL_X;
|
||||
od->title = SANE_TITLE_SCAN_TL_X;
|
||||
od->desc = SANE_DESC_SCAN_TL_X;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->unit = SANE_UNIT_PIXEL;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &x_range;
|
||||
dev->val[OPT_TL_X].w = 0;
|
||||
|
||||
/* top-left y */
|
||||
od = &(dev->opt[OPT_TL_Y]);
|
||||
od->name = SANE_NAME_SCAN_TL_Y;
|
||||
od->title = SANE_TITLE_SCAN_TL_Y;
|
||||
od->desc = SANE_DESC_SCAN_TL_Y;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->unit = SANE_UNIT_PIXEL;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &y_range;
|
||||
dev->val[OPT_TL_Y].w = 0;
|
||||
|
||||
/* bottom-right x */
|
||||
od = &(dev->opt[OPT_BR_X]);
|
||||
od->name = SANE_NAME_SCAN_BR_X;
|
||||
od->title = SANE_TITLE_SCAN_BR_X;
|
||||
od->desc = SANE_DESC_SCAN_BR_X;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->unit = SANE_UNIT_PIXEL;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &x_range;
|
||||
dev->val[OPT_BR_X].w = 1700;
|
||||
|
||||
/* bottom-right y */
|
||||
od = &(dev->opt[OPT_BR_Y]);
|
||||
od->name = SANE_NAME_SCAN_BR_Y;
|
||||
od->title = SANE_TITLE_SCAN_BR_Y;
|
||||
od->desc = SANE_DESC_SCAN_BR_Y;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->unit = SANE_UNIT_PIXEL;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &y_range;
|
||||
dev->val[OPT_BR_Y].w = 2338;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* callback function for sanei_usb_attach_matching_devices
|
||||
*/
|
||||
static SANE_Status
|
||||
attach_one (SANE_String_Const devname)
|
||||
{
|
||||
Lexmark_Device *lexmark_device;
|
||||
SANE_Int dn;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (2, "attachLexmark: devname=%s\n", devname);
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
/* already attached devices */
|
||||
if (strcmp (lexmark_device->sane.name, devname) == 0)
|
||||
{
|
||||
lexmark_device->missing = SANE_FALSE;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
|
||||
lexmark_device = (Lexmark_Device *) malloc (sizeof (Lexmark_Device));
|
||||
if (lexmark_device == NULL)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
status = sanei_usb_open (devname, &dn);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
else
|
||||
DBG (2, "attachLexmark: device `%s' successfully opened\n", devname);
|
||||
|
||||
lexmark_device->sane.name = strdup (devname);
|
||||
lexmark_device->sane.vendor = "Lexmark";
|
||||
lexmark_device->sane.model = "X2600 series";
|
||||
lexmark_device->sane.type = "flat bed";
|
||||
|
||||
/* Make the pointer to the read buffer null here */
|
||||
lexmark_device->read_buffer = NULL;
|
||||
/* mark device as present */
|
||||
lexmark_device->missing = SANE_FALSE;
|
||||
|
||||
sanei_usb_close (lexmark_device->devnum);
|
||||
|
||||
/* insert it a the start of the chained list */
|
||||
lexmark_device->next = first_device;
|
||||
first_device = lexmark_device;
|
||||
num_devices++;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize)
|
||||
{
|
||||
FILE *fp;
|
||||
SANE_Char config_line[PATH_MAX];
|
||||
const char *lp;
|
||||
|
||||
DBG_INIT ();
|
||||
DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
|
||||
version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
|
||||
|
@ -15,84 +262,419 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
|
|||
|
||||
sanei_usb_init ();
|
||||
|
||||
return probe_lexmark_devices ();
|
||||
}
|
||||
fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE);
|
||||
if (!fp)
|
||||
{
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
while (sanei_config_read (config_line, sizeof (config_line), fp))
|
||||
{
|
||||
if (config_line[0] == '#')
|
||||
continue; /* ignore line comments */
|
||||
|
||||
SANE_Status
|
||||
sane_get_devices (const SANE_Device __sane_unused__ ***dl, SANE_Bool __sane_unused__ local)
|
||||
{
|
||||
lp = sanei_config_skip_whitespace (config_line);
|
||||
/* skip empty lines */
|
||||
if (*lp == 0)
|
||||
continue;
|
||||
|
||||
DBG (4, "attach_matching_devices(%s)\n", config_line);
|
||||
sanei_usb_attach_matching_devices (config_line, attach_one);
|
||||
}
|
||||
|
||||
DBG (4, "finished reading configure file\n");
|
||||
fclose (fp);
|
||||
initialized = SANE_TRUE;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_open (SANE_String_Const __sane_unused__ name, SANE_Handle __sane_unused__ *h)
|
||||
sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only)
|
||||
{
|
||||
SANE_Int index;
|
||||
Lexmark_Device *lexmark_device;
|
||||
|
||||
DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n",
|
||||
(void *) device_list, local_only);
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
|
||||
devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
|
||||
if (!devlist)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
|
||||
index = 0;
|
||||
lexmark_device = first_device;
|
||||
while (lexmark_device != NULL)
|
||||
{
|
||||
if (lexmark_device->missing == SANE_FALSE)
|
||||
{
|
||||
devlist[index] = &(lexmark_device->sane);
|
||||
index++;
|
||||
}
|
||||
lexmark_device = lexmark_device->next;
|
||||
}
|
||||
devlist[index] = 0;
|
||||
|
||||
*device_list = devlist;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
||||
{
|
||||
Lexmark_Device *lexmark_device;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (2, "sane_open: devicename=\"%s\", handle=%p\n", devicename,
|
||||
(void *) handle);
|
||||
|
||||
/* walk the linked list of scanner device until there is a match
|
||||
* with the device name */
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
DBG (2, "sane_open: devname from list: %s\n",
|
||||
lexmark_device->sane.name);
|
||||
if (strcmp (devicename, "") == 0
|
||||
|| strcmp (devicename, "lexmark") == 0
|
||||
|| strcmp (devicename, lexmark_device->sane.name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
*handle = lexmark_device;
|
||||
|
||||
status = init_options (lexmark_device);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const SANE_Option_Descriptor *
|
||||
sane_get_option_descriptor (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt)
|
||||
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||
{
|
||||
return NULL;
|
||||
Lexmark_Device *lexmark_device;
|
||||
|
||||
DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n",
|
||||
(void *) handle, option);
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
if (lexmark_device == handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lexmark_device)
|
||||
return NULL;
|
||||
|
||||
if (lexmark_device->opt[option].name)
|
||||
{
|
||||
DBG (2, "sane_get_option_descriptor: name=%s\n",
|
||||
lexmark_device->opt[option].name);
|
||||
}
|
||||
|
||||
return &(lexmark_device->opt[option]);
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_control_option (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt, SANE_Action __sane_unused__ act,
|
||||
void __sane_unused__ *val, SANE_Word __sane_unused__ *info)
|
||||
sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
|
||||
void * value, SANE_Word * info)
|
||||
{
|
||||
Lexmark_Device *lexmark_device;
|
||||
SANE_Status status;
|
||||
SANE_Word w;
|
||||
|
||||
DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
|
||||
(void *) handle, option, action, (void *) value, (void *) info);
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
if (lexmark_device == handle)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (value == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case SANE_ACTION_SET_VALUE:
|
||||
if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap))
|
||||
{
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
/* Make sure boolean values are only TRUE or FALSE */
|
||||
if (lexmark_device->opt[option].type == SANE_TYPE_BOOL)
|
||||
{
|
||||
if (!
|
||||
((*(SANE_Bool *) value == SANE_FALSE)
|
||||
|| (*(SANE_Bool *) value == SANE_TRUE)))
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* Check range constraints */
|
||||
if (lexmark_device->opt[option].constraint_type ==
|
||||
SANE_CONSTRAINT_RANGE)
|
||||
{
|
||||
status =
|
||||
sanei_constrain_value (&(lexmark_device->opt[option]), value,
|
||||
info);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
switch (option)
|
||||
{
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value,
|
||||
lexmark_device->opt[option].name);
|
||||
lexmark_device->val[option].w = *(SANE_Word *) value;
|
||||
if (lexmark_device->val[OPT_TL_X].w >
|
||||
lexmark_device->val[OPT_BR_X].w)
|
||||
{
|
||||
w = lexmark_device->val[OPT_TL_X].w;
|
||||
lexmark_device->val[OPT_TL_X].w =
|
||||
lexmark_device->val[OPT_BR_X].w;
|
||||
lexmark_device->val[OPT_BR_X].w = w;
|
||||
if (info)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS;
|
||||
}
|
||||
if (lexmark_device->val[OPT_TL_Y].w >
|
||||
lexmark_device->val[OPT_BR_Y].w)
|
||||
{
|
||||
w = lexmark_device->val[OPT_TL_Y].w;
|
||||
lexmark_device->val[OPT_TL_Y].w =
|
||||
lexmark_device->val[OPT_BR_Y].w;
|
||||
lexmark_device->val[OPT_BR_Y].w = w;
|
||||
if (info)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE:
|
||||
strcpy (lexmark_device->val[option].s, value);
|
||||
if (info)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (info != NULL)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS;
|
||||
|
||||
break;
|
||||
case SANE_ACTION_GET_VALUE:
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_PREVIEW:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
*(SANE_Word *) value = lexmark_device->val[option].w;
|
||||
DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value,
|
||||
lexmark_device->opt[option].name);
|
||||
break;
|
||||
case OPT_MODE:
|
||||
strcpy (value, lexmark_device->val[option].s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_get_parameters (SANE_Handle __sane_unused__ h, SANE_Parameters __sane_unused__ *parms)
|
||||
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
||||
{
|
||||
Lexmark_Device *lexmark_device;
|
||||
SANE_Parameters *device_params;
|
||||
SANE_Int res, width_px;
|
||||
SANE_Int channels, bitsperchannel;
|
||||
|
||||
DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle,
|
||||
(void *) params);
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
if (lexmark_device == handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lexmark_device)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
res = lexmark_device->val[OPT_RESOLUTION].w;
|
||||
|
||||
device_params = &(lexmark_device->params);
|
||||
|
||||
/* 24 bit colour = 8 bits/channel for each of the RGB channels */
|
||||
channels = 3;
|
||||
bitsperchannel = 8;
|
||||
if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR)
|
||||
!= 0)
|
||||
channels = 1;
|
||||
|
||||
/* geometry in pixels */
|
||||
width_px =
|
||||
lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w;
|
||||
DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n",
|
||||
lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w,
|
||||
lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w);
|
||||
|
||||
DBG (7, "sane_get_parameters: res=(%d)\n", res);
|
||||
|
||||
device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY
|
||||
if (channels == 1)
|
||||
device_params->format = SANE_FRAME_GRAY;
|
||||
|
||||
device_params->last_frame = SANE_TRUE;
|
||||
device_params->lines = -1;
|
||||
device_params->depth = bitsperchannel;
|
||||
device_params->pixels_per_line = width_px;
|
||||
device_params->bytes_per_line =
|
||||
(SANE_Int) ((7 + device_params->pixels_per_line) / 8);
|
||||
|
||||
if (params != 0)
|
||||
{
|
||||
params->format = device_params->format;
|
||||
params->last_frame = device_params->last_frame;
|
||||
params->lines = device_params->lines;
|
||||
params->depth = device_params->depth;
|
||||
params->pixels_per_line = device_params->pixels_per_line;
|
||||
params->bytes_per_line = device_params->bytes_per_line;
|
||||
}
|
||||
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_start (SANE_Handle __sane_unused__ h)
|
||||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
Lexmark_Device *lexmark_device;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (2, "sane_start: handle=%p\n", (void *) handle);
|
||||
|
||||
if (!initialized)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = lexmark_device->next)
|
||||
{
|
||||
if (lexmark_device == handle)
|
||||
break;
|
||||
}
|
||||
|
||||
// launch scan commands
|
||||
static SANE_Byte cmd[] = { 0x80, 0x00, 0x00, 0xFF };
|
||||
|
||||
status = usb_write_then_read_twice(lexmark_device, cmd, 4);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = usb_write_then_read_twice(lexmark_device, cmd, 4);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = usb_write_then_read_twice(lexmark_device, cmd, 4);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "USB IO Error in sane_start, cannot launch scan");
|
||||
return status;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_read (SANE_Handle __sane_unused__ h, SANE_Byte __sane_unused__ *buf, SANE_Int __sane_unused__ maxlen, SANE_Int __sane_unused__ *lenp)
|
||||
sane_read (SANE_Handle handle, SANE_Byte * data,
|
||||
SANE_Int max_length, SANE_Int * length)
|
||||
{
|
||||
DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n",
|
||||
(void *) handle, (void *) data, max_length, (void *) length);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ non_blocking)
|
||||
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||
{
|
||||
DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n",
|
||||
(void *) handle, non_blocking);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ *fdp)
|
||||
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
|
||||
{
|
||||
return SANE_STATUS_GOOD;
|
||||
DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", (void *) handle,
|
||||
fd ? "!=" : "=");
|
||||
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
void
|
||||
sane_cancel (SANE_Handle __sane_unused__ h)
|
||||
sane_cancel (SANE_Handle handle)
|
||||
{
|
||||
|
||||
DBG (2, "sane_cancel: handle = %p\n", (void *) handle);
|
||||
}
|
||||
|
||||
void
|
||||
sane_close (SANE_Handle __sane_unused__ h)
|
||||
sane_close (SANE_Handle handle)
|
||||
{
|
||||
|
||||
DBG (2, "sane_close: handle=%p\n", (void *) handle);
|
||||
}
|
||||
|
||||
void
|
||||
sane_exit (void)
|
||||
{
|
||||
Lexmark_Device *lexmark_device, *next_lexmark_device;
|
||||
|
||||
DBG (2, "sane_exit\n");
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
for (lexmark_device = first_device; lexmark_device;
|
||||
lexmark_device = next_lexmark_device)
|
||||
{
|
||||
next_lexmark_device = lexmark_device->next;
|
||||
free (lexmark_device);
|
||||
}
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
|
||||
sanei_usb_exit();
|
||||
initialized = SANE_FALSE;
|
||||
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
probe_lexmark_devices (void)
|
||||
{
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,19 @@
|
|||
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "../include/_stdint.h"
|
||||
#include "../include/sane/sane.h"
|
||||
#include "../include/sane/sanei.h"
|
||||
|
@ -12,4 +25,75 @@
|
|||
#include "../include/sane/sanei_backend.h"
|
||||
|
||||
|
||||
typedef struct Read_Buffer
|
||||
{
|
||||
SANE_Int gray_offset;
|
||||
SANE_Int max_gray_offset;
|
||||
SANE_Int region;
|
||||
SANE_Int red_offset;
|
||||
SANE_Int green_offset;
|
||||
SANE_Int blue_offset;
|
||||
SANE_Int max_red_offset;
|
||||
SANE_Int max_green_offset;
|
||||
SANE_Int max_blue_offset;
|
||||
SANE_Byte *data;
|
||||
SANE_Byte *readptr;
|
||||
SANE_Byte *writeptr;
|
||||
SANE_Byte *max_writeptr;
|
||||
size_t size;
|
||||
size_t linesize;
|
||||
SANE_Bool empty;
|
||||
SANE_Int image_line_no;
|
||||
SANE_Int bit_counter;
|
||||
SANE_Int max_lineart_offset;
|
||||
}
|
||||
Read_Buffer;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OPT_NUM_OPTS = 0,
|
||||
OPT_MODE,
|
||||
OPT_RESOLUTION,
|
||||
OPT_PREVIEW,
|
||||
|
||||
OPT_GEOMETRY_GROUP,
|
||||
OPT_TL_X, /* top-left x */
|
||||
OPT_TL_Y, /* top-left y */
|
||||
OPT_BR_X, /* bottom-right x */
|
||||
OPT_BR_Y, /* bottom-right y */
|
||||
|
||||
/* must come last: */
|
||||
NUM_OPTIONS
|
||||
}
|
||||
Lexmark_Options;
|
||||
|
||||
typedef struct Lexmark_Device
|
||||
{
|
||||
struct Lexmark_Device *next;
|
||||
SANE_Bool missing; /**< devices has been unplugged or swtiched off */
|
||||
|
||||
SANE_Device sane;
|
||||
SANE_Option_Descriptor opt[NUM_OPTIONS];
|
||||
Option_Value val[NUM_OPTIONS];
|
||||
SANE_Parameters params;
|
||||
SANE_Int devnum;
|
||||
long data_size;
|
||||
SANE_Bool initialized;
|
||||
SANE_Bool eof;
|
||||
SANE_Int x_dpi;
|
||||
SANE_Int y_dpi;
|
||||
long data_ctr;
|
||||
SANE_Bool device_cancelled;
|
||||
SANE_Int cancel_ctr;
|
||||
SANE_Byte *transfer_buffer;
|
||||
size_t bytes_read;
|
||||
size_t bytes_remaining;
|
||||
size_t bytes_in_buffer;
|
||||
SANE_Byte *read_pointer;
|
||||
Read_Buffer *read_buffer;
|
||||
}
|
||||
Lexmark_Device;
|
||||
|
||||
|
||||
#endif /* LEXMARK_X2600_H */
|
||||
|
|
Ładowanie…
Reference in New Issue