kopia lustrzana https://gitlab.com/sane-project/backends
* epson2: restructured code once more, splitted
in multiple files, added networking support, added FS G extended handshaking mode, make proper use of extended commands when possible * sanei/sanei_tcp.c: read now wait until all the requested data is available.merge-requests/1/head
rodzic
99770af682
commit
bf5a1290f7
|
@ -1,3 +1,12 @@
|
|||
2006-12-18 Alessandro Zummo <a.zummo@towertech.it>
|
||||
|
||||
* epson2: restructured code once more, splitted
|
||||
in multiple files, added networking
|
||||
support, added FS G extended handshaking mode,
|
||||
make proper use of extended commands when possible
|
||||
* sanei/sanei_tcp.c: read now wait until all
|
||||
the requested data is available.
|
||||
|
||||
2006-12-13 Alessandro Zummo <a.zummo@towertech.it>
|
||||
|
||||
* coolscan2: fixed coolscan2 infrared to work
|
||||
|
|
|
@ -99,6 +99,7 @@ DISTFILES = abaton.c abaton.conf.in abaton.h agfafocus.c agfafocus.conf.in \
|
|||
dell1600n_net.conf.in dll.aliases dll.c dll.conf.in dmc.c dmc.conf.in dmc.h \
|
||||
epson.c epson_scsi.c epson_usb.c epson.conf.in epson.h epson_scsi.h \
|
||||
epson_usb.h epson2_net.c epson2_net.h epson2.c epson2_scsi.c epson2.conf.in\
|
||||
epson2-io.c epson2-io.h epson2-commands.c epson2-commands.h\
|
||||
fujitsu.c fujitsu.conf.in fujitsu.h fujitsu-scsi.h \
|
||||
gphoto2.c gphoto2.conf.in gphoto2.h \
|
||||
gt68xx.c gt68xx.h gt68xx_high.c gt68xx_high.h gt68xx_mid.c gt68xx_mid.h \
|
||||
|
@ -310,7 +311,7 @@ EXTRA_genesys = genesys_gl646 genesys_gl841
|
|||
EXTRA_hp = hp-accessor hp-device hp-handle hp-hpmem hp-option hp-scl
|
||||
EXTRA_umax_pp = umax_pp_low umax_pp_mid
|
||||
EXTRA_epson = epson_scsi epson_usb
|
||||
EXTRA_epson2 = epson2_scsi epson_usb epson2_net
|
||||
EXTRA_epson2 = epson2_scsi epson_usb epson2_net epson2-io epson2-commands
|
||||
EXTRA_lexmark = lexmark-x1100
|
||||
EXTRA_pixma = pixma_io_sanei pixma_common pixma_mp150 pixma_mp730 pixma_mp750
|
||||
|
||||
|
|
|
@ -0,0 +1,849 @@
|
|||
/*
|
||||
* ESC/I commands for Epson scanners
|
||||
*
|
||||
* Based on Kazuhiro Sasayama previous
|
||||
* Work on epson.[ch] file from the SANE package.
|
||||
* Please see those files for original copyrights.
|
||||
*
|
||||
* Copyright (C) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* This file is part of the SANE package.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include <sane/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <byteorder.h>
|
||||
|
||||
#include "epson2.h"
|
||||
#include "epson2-io.h"
|
||||
#include "epson2-commands.h"
|
||||
|
||||
|
||||
/* ESC H, set zoom */
|
||||
SANE_Status
|
||||
set_zoom(Epson_Scanner * s, unsigned char x, unsigned char y)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s: x = %d, y = %d\n", __func__, x, y);
|
||||
|
||||
if (!s->hw->cmd->set_zoom) {
|
||||
DBG(1, "%s: not supported\n", __func__);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->set_zoom;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
params[0] = x;
|
||||
params[1] = y;
|
||||
|
||||
return epson2_cmd_simple(s, params, 2);
|
||||
}
|
||||
|
||||
/* ESC R */
|
||||
SANE_Status
|
||||
set_resolution(Epson_Scanner * s, int x, int y)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[4];
|
||||
|
||||
DBG(8, "%s: x = %d, y = %d\n", __func__, x, y);
|
||||
|
||||
if (!s->hw->cmd->set_resolution) {
|
||||
DBG(1, "%s: not supported\n", __func__);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->set_resolution;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
params[0] = x;
|
||||
params[1] = x >> 8;
|
||||
params[2] = y;
|
||||
params[3] = y >> 8;
|
||||
|
||||
return epson2_cmd_simple(s, params, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends the "set scan area" command to the scanner with the currently selected
|
||||
* scan area. This scan area must be already corrected for "color shuffling" if
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
set_scan_area(Epson_Scanner * s, int x, int y, int width, int height)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[8];
|
||||
|
||||
DBG(8, "%s: x = %d, y = %d, w = %d, h = %d\n",
|
||||
__func__, x, y, width, height);
|
||||
|
||||
if (!s->hw->cmd->set_scan_area) {
|
||||
DBG(1, "%s: not supported\n", __func__);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* verify the scan area */
|
||||
if (x < 0 || y < 0 || width <= 0 || height <= 0)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->set_scan_area;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
params[0] = x;
|
||||
params[1] = x >> 8;
|
||||
params[2] = y;
|
||||
params[3] = y >> 8;
|
||||
params[4] = width;
|
||||
params[5] = width >> 8;
|
||||
params[6] = height;
|
||||
params[7] = height >> 8;
|
||||
|
||||
return epson2_cmd_simple(s, params, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends the "set color correction coefficients" command with the
|
||||
* currently selected parameters to the scanner.
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
set_color_correction_coefficients(Epson_Scanner * s)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
signed char cct[9];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
if (!s->hw->cmd->set_color_correction_coefficients) {
|
||||
DBG(1, "%s: not supported\n", __func__);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->set_color_correction_coefficients;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
cct[0] = s->val[OPT_CCT_1].w;
|
||||
cct[1] = s->val[OPT_CCT_2].w;
|
||||
cct[2] = s->val[OPT_CCT_3].w;
|
||||
cct[3] = s->val[OPT_CCT_4].w;
|
||||
cct[4] = s->val[OPT_CCT_5].w;
|
||||
cct[5] = s->val[OPT_CCT_6].w;
|
||||
cct[6] = s->val[OPT_CCT_7].w;
|
||||
cct[7] = s->val[OPT_CCT_8].w;
|
||||
cct[8] = s->val[OPT_CCT_9].w;
|
||||
|
||||
DBG(10, "%s: %d,%d,%d %d,%d,%d %d,%d,%d\n", __func__,
|
||||
cct[0], cct[1], cct[2], cct[3],
|
||||
cct[4], cct[5], cct[6], cct[7], cct[8]);
|
||||
|
||||
return epson2_cmd_simple(s, params, 9);
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
set_gamma_table(Epson_Scanner * s)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
unsigned char gamma[257];
|
||||
int n;
|
||||
int table;
|
||||
|
||||
/* static const char gamma_cmds[] = { 'M', 'R', 'G', 'B' }; */
|
||||
static const char gamma_cmds[] = { 'R', 'G', 'B' };
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
if (!s->hw->cmd->set_gamma_table)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->set_gamma_table;
|
||||
|
||||
/* Print the gamma tables before sending them to the scanner */
|
||||
|
||||
if (DBG_LEVEL >= 10) {
|
||||
int c, i, j;
|
||||
|
||||
for (c = 0; c < 3; c++) {
|
||||
for (i = 0; i < 256; i += 16) {
|
||||
char gammaValues[16 * 3 + 1], newValue[4];
|
||||
|
||||
gammaValues[0] = '\0';
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
sprintf(newValue, " %02x",
|
||||
s->gamma_table[c][i + j]);
|
||||
strcat(gammaValues, newValue);
|
||||
}
|
||||
DBG(10, "gamma table[%d][%d] %s\n", c, i,
|
||||
gammaValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When handling inverted images, we must also invert the user
|
||||
* supplied gamma function. This is *not* just 255-gamma -
|
||||
* this gives a negative image.
|
||||
*/
|
||||
|
||||
for (table = 0; table < 3; table++) {
|
||||
gamma[0] = gamma_cmds[table];
|
||||
|
||||
if (s->invert_image) {
|
||||
for (n = 0; n < 256; ++n) {
|
||||
gamma[n + 1] =
|
||||
255 - s->gamma_table[table][255 - n];
|
||||
}
|
||||
} else {
|
||||
for (n = 0; n < 256; ++n) {
|
||||
gamma[n + 1] = s->gamma_table[table][n];
|
||||
}
|
||||
}
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
status = epson2_cmd_simple(s, gamma, 257);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ESC F - Request Status
|
||||
* -> ESC f
|
||||
* <- Information block
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
request_status(SANE_Handle handle, unsigned char *scanner_status)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_status == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_status;
|
||||
|
||||
epson2_send(s, params, 2, 4, &status);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
status = epson2_recv_info_block(s, params, 4, NULL);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
if (scanner_status)
|
||||
*scanner_status = params[0];
|
||||
|
||||
DBG(1, "status:\n");
|
||||
|
||||
if (params[0] & STATUS_NOT_READY)
|
||||
DBG(1, " scanner in use on another interface\n");
|
||||
else
|
||||
DBG(1, " ready\n");
|
||||
|
||||
if (params[0] & STATUS_FER)
|
||||
DBG(1, " system error\n");
|
||||
|
||||
if (params[0] & STATUS_OPTION)
|
||||
DBG(1, " option equipment is installed\n");
|
||||
else
|
||||
DBG(1, " no option equipment installed\n");
|
||||
|
||||
if (params[0] & STATUS_EXT_COMMANDS)
|
||||
DBG(1, " support extended commands\n");
|
||||
else
|
||||
DBG(1, " does NOT support extended commands\n");
|
||||
|
||||
if (params[0] & STATUS_RESERVED)
|
||||
DBG(0,
|
||||
" a reserved bit is set, please contact the author.\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* extended commands */
|
||||
|
||||
/* FS I, Request Extended Identity
|
||||
* -> FS I
|
||||
* <- Extended identity data (80)
|
||||
*
|
||||
* Request the properties of the scanner.
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
request_extended_identity(SANE_Handle handle, unsigned char *buf)
|
||||
{
|
||||
unsigned char model[17];
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (buf == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
if (s->hw->cmd->request_extended_identity == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = FS;
|
||||
params[1] = s->hw->cmd->request_extended_identity;
|
||||
|
||||
status = epson2_txrx(s, params, 2, buf, 80);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
DBG(1, " command level : %c%c\n", buf[0], buf[1]);
|
||||
DBG(1, " basic resolution: %d\n", le32atoh(&buf[4]));
|
||||
DBG(1, " min resolution : %d\n", le32atoh(&buf[8]));
|
||||
DBG(1, " max resolution : %d\n", le32atoh(&buf[12]));
|
||||
DBG(1, " max pixel num : %d\n", le32atoh(&buf[16]));
|
||||
DBG(1, " scan area : %dx%d\n",
|
||||
le32atoh(&buf[20]), le32atoh(&buf[24]));
|
||||
|
||||
DBG(1, " adf area : %dx%d\n",
|
||||
le32atoh(&buf[28]), le32atoh(&buf[32]));
|
||||
|
||||
DBG(1, " tpu area : %dx%d\n",
|
||||
le32atoh(&buf[36]), le32atoh(&buf[40]));
|
||||
|
||||
DBG(1, " main status : 0x%02x\n", buf[44]);
|
||||
DBG(1, " input depth : %d\n", buf[66]);
|
||||
DBG(1, " max output depth: %d\n", buf[67]);
|
||||
DBG(1, " rom version : %c%c%c%c\n",
|
||||
buf[62], buf[63], buf[64], buf[65]);
|
||||
|
||||
memcpy(model, &buf[46], 16);
|
||||
model[16] = '\0';
|
||||
DBG(1, " model name : %s\n", model);
|
||||
|
||||
DBG(1, "options:\n");
|
||||
|
||||
if (le32atoh(&buf[28]) > 0)
|
||||
DBG(1, " ADF detected\n");
|
||||
|
||||
if (le32atoh(&buf[36]) > 0)
|
||||
DBG(1, " TPU detected\n");
|
||||
|
||||
DBG(1, "status:\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_DLF)
|
||||
DBG(1, " main lamp change is supported\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_NOTFBF)
|
||||
DBG(1, " the device is NOT flatbed\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_ADFT)
|
||||
DBG(1, " page type ADF is installed\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_ADFS)
|
||||
DBG(1, " ADF is duplex capable\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_ADFO)
|
||||
DBG(1, " page type ADF loads from the first sheet\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_LID)
|
||||
DBG(1, " lid type option is installed\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_TPIR)
|
||||
DBG(1, " infrared scanning is supported\n");
|
||||
|
||||
if (buf[44] & EXT_IDTY_STATUS_PB)
|
||||
DBG(1, " push button is supported\n");
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* FS F, request scanner status */
|
||||
SANE_Status
|
||||
request_scanner_status(SANE_Handle handle, unsigned char *buf)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (!s->hw->extended_commands)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
if (buf == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
params[0] = FS;
|
||||
params[1] = 'F';
|
||||
|
||||
status = epson2_txrx(s, params, 2, buf, 16);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
DBG(1, "global status : %02x\n", buf[0]);
|
||||
|
||||
if (buf[0] & FSF_STATUS_MAIN_FER)
|
||||
DBG(1, " system error\n");
|
||||
|
||||
if (buf[0] & FSF_STATUS_MAIN_NR)
|
||||
DBG(1, " not ready\n");
|
||||
|
||||
if (buf[0] & FSF_STATUS_MAIN_WU)
|
||||
DBG(1, " scanner is warming up\n");
|
||||
|
||||
|
||||
DBG(1, "adf status : %02x\n", buf[1]);
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_IST)
|
||||
DBG(1, " installed\n");
|
||||
else
|
||||
DBG(1, " not installed\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_EN)
|
||||
DBG(1, " enabled\n");
|
||||
else
|
||||
DBG(1, " not enabled\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_ERR)
|
||||
DBG(1, " error\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_PE)
|
||||
DBG(1, " paper empty\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_PJ)
|
||||
DBG(1, " paper jam\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_OPN)
|
||||
DBG(1, " cover open\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_ADF_PAG)
|
||||
DBG(1, " duplex capable\n");
|
||||
|
||||
|
||||
DBG(1, "tpu status : %02x\n", buf[2]);
|
||||
|
||||
if (buf[2] & FSF_STATUS_TPU_IST)
|
||||
DBG(1, " installed\n");
|
||||
else
|
||||
DBG(1, " not installed\n");
|
||||
|
||||
if (buf[2] & FSF_STATUS_TPU_EN)
|
||||
DBG(1, " enabled\n");
|
||||
else
|
||||
DBG(1, " not enabled\n");
|
||||
|
||||
if (buf[2] & FSF_STATUS_TPU_ERR)
|
||||
DBG(1, " error\n");
|
||||
|
||||
if (buf[1] & FSF_STATUS_TPU_OPN)
|
||||
DBG(1, " cover open\n");
|
||||
|
||||
|
||||
DBG(1, "main body status: %02x\n", buf[3]);
|
||||
|
||||
if (buf[3] & FSF_STATUS_MAIN2_PE)
|
||||
DBG(1, " paper empty\n");
|
||||
|
||||
if (buf[3] & FSF_STATUS_MAIN2_PJ)
|
||||
DBG(1, " paper jam\n");
|
||||
|
||||
if (buf[3] & FSF_STATUS_MAIN2_OPN)
|
||||
DBG(1, " cover open\n");
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
set_scanning_parameter(SANE_Handle handle, unsigned char *buf)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (buf == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
params[0] = FS;
|
||||
params[1] = 'W';
|
||||
|
||||
DBG(9, "resolution of main scan : %d\n", le32atoh(&buf[0]));
|
||||
DBG(9, "resolution of sub scan : %d\n", le32atoh(&buf[4]));
|
||||
DBG(9, "offset length of main scan : %d\n", le32atoh(&buf[8]));
|
||||
DBG(9, "offset length of sub scan : %d\n", le32atoh(&buf[12]));
|
||||
DBG(9, "scanning length of main scan: %d\n", le32atoh(&buf[16]));
|
||||
DBG(9, "scanning length of sub scan : %d\n", le32atoh(&buf[20]));
|
||||
DBG(9, "scanning color : %d\n", buf[24]);
|
||||
DBG(9, "data format : %d\n", buf[25]);
|
||||
DBG(9, "option control : %d\n", buf[26]);
|
||||
DBG(9, "scanning mode : %d\n", buf[27]);
|
||||
DBG(9, "block line number : %d\n", buf[28]);
|
||||
DBG(9, "gamma correction : %d\n", buf[29]);
|
||||
DBG(9, "brightness : %d\n", buf[30]);
|
||||
DBG(9, "color correction : %d\n", buf[31]);
|
||||
DBG(9, "halftone processing : %d\n", buf[32]);
|
||||
DBG(9, "threshold : %d\n", buf[33]);
|
||||
DBG(9, "auto area segmentation : %d\n", buf[34]);
|
||||
DBG(9, "sharpness control : %d\n", buf[35]);
|
||||
DBG(9, "mirroring : %d\n", buf[36]);
|
||||
DBG(9, "film type : %d\n", buf[37]);
|
||||
DBG(9, "main lamp lighting mode : %d\n", buf[38]);
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
status = epson2_cmd_simple(s, buf, 64);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
request_command_parameter(SANE_Handle handle, unsigned char *buf)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_condition == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_condition;
|
||||
|
||||
status = epson2_cmd_info_block(s, params, 2, 45, &buf, NULL);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
DBG(1, "scanning parameters:\n");
|
||||
DBG(1, "color : %d\n", buf[1]);
|
||||
DBG(1, "resolution : %dx%d\n",
|
||||
buf[4] << 8 | buf[3], buf[6] << 8 | buf[5]);
|
||||
DBG(1, "halftone : %d\n", buf[19]);
|
||||
DBG(1, "brightness : %d\n", buf[21]);
|
||||
DBG(1, "color correction : %d\n", buf[28]);
|
||||
DBG(1, "gamma : %d\n", buf[23]);
|
||||
DBG(1, "sharpness : %d\n", buf[30]);
|
||||
DBG(1, "threshold : %d\n", buf[38]);
|
||||
DBG(1, "data format : %d\n", buf[17]);
|
||||
DBG(1, "mirroring : %d\n", buf[34]);
|
||||
DBG(1, "option unit control : %d\n", buf[42]);
|
||||
DBG(1, "film type : %d\n", buf[44]);
|
||||
DBG(1, "auto area segmentation : %d\n", buf[36]);
|
||||
DBG(1, "line counter : %d\n", buf[40]);
|
||||
DBG(1, "scanning mode : %d\n", buf[32]);
|
||||
DBG(1, "zoom : %d,%d\n", buf[26], buf[25]);
|
||||
DBG(1, "scan area : %d,%d %d,%d\n",
|
||||
buf[9] << 8 | buf[8], buf[11] << 8 | buf[10],
|
||||
buf[13] << 8 | buf[12], buf[15] << 8 | buf[14]);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ESC q - Request Focus Position
|
||||
* -> ESC q
|
||||
* <- Information block
|
||||
* <- Focus position status (2)
|
||||
* 0 - Error status
|
||||
* 1 - Focus position
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
request_focus_position(SANE_Handle handle, unsigned char *position)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char *buf;
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_focus_position == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_focus_position;
|
||||
|
||||
status = epson2_cmd_info_block(s, params, 2, 2, &buf, NULL);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
if (buf[0] & 0x01)
|
||||
DBG(1, "autofocus error\n");
|
||||
|
||||
*position = buf[1];
|
||||
DBG(8, " focus position = 0x%x\n", buf[1]);
|
||||
|
||||
free(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ESC ! - Request Push Button Status
|
||||
* -> ESC !
|
||||
* <- Information block
|
||||
* <- Push button status (1)
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
request_push_button_status(SANE_Handle handle, unsigned char *bstatus)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
unsigned char *buf;
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_push_button_status == 0) {
|
||||
DBG(1, "push button status unsupported\n");
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_push_button_status;
|
||||
|
||||
status = epson2_cmd_info_block(s, params, 2, 1, &buf, NULL);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
DBG(1, "push button status = %d\n", buf[0]);
|
||||
*bstatus = buf[0];
|
||||
|
||||
free(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Request Identity information from scanner and fill in information
|
||||
* into dev and/or scanner structures.
|
||||
* XXX information should be parsed separately.
|
||||
*/
|
||||
SANE_Status
|
||||
request_identity(SANE_Handle handle, unsigned char **buf, size_t *len)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(1, "%s\n", __func__);
|
||||
|
||||
if (!s->hw->cmd->request_identity)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_identity;
|
||||
|
||||
return epson2_cmd_info_block(s, params, 2, 0, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Request information from scanner
|
||||
*/
|
||||
SANE_Status
|
||||
request_identity2(SANE_Handle handle, unsigned char **buf)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status;
|
||||
size_t len;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(5, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_identity2 == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_identity2;
|
||||
|
||||
status = epson2_cmd_info_block(s, params, 2, 0, buf, &len);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Send the "initialize scanner" command to the device and reset it */
|
||||
|
||||
SANE_Status
|
||||
reset(Epson_Scanner * s)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (!s->hw->cmd->initialize_scanner)
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->initialize_scanner;
|
||||
|
||||
if (s->fd == -1)
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
feed(Epson_Scanner * s)
|
||||
{
|
||||
unsigned char params[1];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (!s->hw->cmd->feed) {
|
||||
DBG(5, "feed is not supported\n");
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
params[0] = s->hw->cmd->feed;
|
||||
|
||||
return epson2_cmd_simple(s, params, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Eject the current page from the ADF. The scanner is opened prior to
|
||||
* sending the command and closed afterwards.
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
eject(Epson_Scanner * s)
|
||||
{
|
||||
unsigned char params[1];
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (!s->hw->cmd->eject)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
if (s->fd == -1)
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
params[0] = s->hw->cmd->eject;
|
||||
|
||||
return epson2_cmd_simple(s, params, 1);
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
request_extended_status(SANE_Handle handle, unsigned char **data,
|
||||
size_t * data_len)
|
||||
{
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
unsigned char params[2];
|
||||
unsigned char *buf;
|
||||
size_t buf_len;
|
||||
|
||||
DBG(8, "%s\n", __func__);
|
||||
|
||||
if (s->hw->cmd->request_extended_status == 0)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = s->hw->cmd->request_extended_status;
|
||||
|
||||
/* This command returns 33 bytes of data on old scanners
|
||||
* and 42 (CMD_SIZE_EXT_STATUS) on new ones.
|
||||
*/
|
||||
status = epson2_cmd_info_block(s, params, 2, CMD_SIZE_EXT_STATUS,
|
||||
&buf, &buf_len);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
switch (buf_len) {
|
||||
case 33:
|
||||
case 42:
|
||||
break;
|
||||
default:
|
||||
DBG(1, "%s: unknown reply length (%d)\n", __func__, buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(4, "main = %02x, ADF = %02x, TPU = %02x, main 2 = %02x\n",
|
||||
buf[0], buf[1], buf[6], buf[11]);
|
||||
|
||||
if (buf[0] & EXT_STATUS_FER)
|
||||
DBG(1, "system error\n");
|
||||
|
||||
if (buf[0] & EXT_STATUS_WU)
|
||||
DBG(1, "scanner is warming up\n");
|
||||
|
||||
if (buf[1] & EXT_STATUS_ERR)
|
||||
DBG(1, "ADF: other error\n");
|
||||
|
||||
if (buf[1] & EXT_STATUS_PE)
|
||||
DBG(1, "ADF: no paper\n");
|
||||
|
||||
if (buf[1] & EXT_STATUS_PJ)
|
||||
DBG(1, "ADF: paper jam\n");
|
||||
|
||||
if (buf[1] & EXT_STATUS_OPN)
|
||||
DBG(1, "ADF: cover open\n");
|
||||
|
||||
if (buf[6] & EXT_STATUS_ERR)
|
||||
DBG(1, "TPU: other error\n");
|
||||
|
||||
/* give back a pointer to the payload
|
||||
* if the user requested it, otherwise
|
||||
* free it.
|
||||
*/
|
||||
|
||||
if (data)
|
||||
*data = buf;
|
||||
else
|
||||
free(buf);
|
||||
|
||||
if (data_len)
|
||||
*data_len = buf_len;
|
||||
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Prototypes for Epson ESC/I commands
|
||||
*
|
||||
* Based on Kazuhiro Sasayama previous
|
||||
* Work on epson.[ch] file from the SANE package.
|
||||
* Please see those files for original copyrights.
|
||||
*
|
||||
* Copyright (C) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* This file is part of the SANE package.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
/* simple scanner commands, ESC <x> */
|
||||
|
||||
#define set_focus_position(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_focus_position, v)
|
||||
#define set_color_mode(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_color_mode, v)
|
||||
#define set_data_format(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_data_format, v)
|
||||
#define set_halftoning(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_halftoning, v)
|
||||
#define set_gamma(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_gamma, v)
|
||||
#define set_color_correction(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_color_correction, v)
|
||||
#define set_lcount(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_lcount, v)
|
||||
#define set_bright(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_bright, v)
|
||||
#define mirror_image(s,v) epson2_esc_cmd( s,(s)->hw->cmd->mirror_image, v)
|
||||
#define set_speed(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_speed, v)
|
||||
#define set_sharpness(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_outline_emphasis, v)
|
||||
#define set_auto_area_segmentation(s,v) epson2_esc_cmd( s,(s)->hw->cmd->control_auto_area_segmentation, v)
|
||||
#define set_film_type(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_film_type, v)
|
||||
#define set_exposure_time(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_exposure_time, v)
|
||||
#define set_bay(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_bay, v)
|
||||
#define set_threshold(s,v) epson2_esc_cmd( s,(s)->hw->cmd->set_threshold, v)
|
||||
#define control_extension(s,v) epson2_esc_cmd( s,(s)->hw->cmd->control_an_extension, v)
|
||||
|
||||
SANE_Status set_zoom(Epson_Scanner * s, unsigned char x, unsigned char y);
|
||||
SANE_Status set_resolution(Epson_Scanner * s, int x, int y);
|
||||
SANE_Status set_scan_area(Epson_Scanner * s, int x, int y, int width,
|
||||
int height);
|
||||
SANE_Status set_color_correction_coefficients(Epson_Scanner * s);
|
||||
SANE_Status set_gamma_table(Epson_Scanner * s);
|
||||
|
||||
SANE_Status request_status(SANE_Handle handle, unsigned char *scanner_status);
|
||||
SANE_Status request_extended_identity(SANE_Handle handle, unsigned char *buf);
|
||||
SANE_Status request_scanner_status(SANE_Handle handle, unsigned char *buf);
|
||||
SANE_Status set_scanning_parameter(SANE_Handle handle, unsigned char *buf);
|
||||
SANE_Status request_command_parameter(SANE_Handle handle, unsigned char *buf);
|
||||
SANE_Status request_focus_position(SANE_Handle handle,
|
||||
unsigned char *position);
|
||||
SANE_Status request_push_button_status(SANE_Handle handle,
|
||||
unsigned char *bstatus);
|
||||
SANE_Status request_identity(SANE_Handle handle, unsigned char **buf, size_t *len);
|
||||
|
||||
SANE_Status request_identity2(SANE_Handle handle, unsigned char **buf);
|
||||
SANE_Status reset(Epson_Scanner * s);
|
||||
SANE_Status feed(Epson_Scanner * s);
|
||||
SANE_Status eject(Epson_Scanner * s);
|
||||
SANE_Status request_extended_status(SANE_Handle handle, unsigned char **data,
|
||||
size_t * data_len);
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* I/O routines for Epson scanners
|
||||
*
|
||||
* Based on Kazuhiro Sasayama previous
|
||||
* Work on epson.[ch] file from the SANE package.
|
||||
* Please see those files for original copyrights.
|
||||
*
|
||||
* Copyright (C) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* This file is part of the SANE package.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include <sane/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <byteorder.h>
|
||||
|
||||
#include "epson2.h"
|
||||
#include "epson2-io.h"
|
||||
|
||||
#include <sane/sanei_scsi.h>
|
||||
#include <sane/sanei_usb.h>
|
||||
#include <sane/sanei_pio.h>
|
||||
#include <sane/sanei_tcp.h>
|
||||
|
||||
#include "epson2_scsi.h"
|
||||
#include "epson_usb.h"
|
||||
#include "epson2_net.h"
|
||||
|
||||
/* flaming hack to get USB scanners
|
||||
* working without timeouts under linux
|
||||
* (cribbed from fujitsu.c)
|
||||
*/
|
||||
unsigned int r_cmd_count = 0;
|
||||
unsigned int w_cmd_count = 0;
|
||||
|
||||
int
|
||||
epson2_send(Epson_Scanner * s, void *buf, size_t buf_size, size_t reply_len,
|
||||
SANE_Status * status)
|
||||
{
|
||||
DBG(15, "%s: size = %lu, reply = %lu\n",
|
||||
__func__, (u_long) buf_size, (u_long) reply_len);
|
||||
|
||||
if (buf_size == 2) {
|
||||
char *cmd = buf;
|
||||
|
||||
switch (cmd[0]) {
|
||||
case ESC:
|
||||
DBG(9, "%s: ESC %c\n", __func__, cmd[1]);
|
||||
break;
|
||||
|
||||
case FS:
|
||||
DBG(9, "%s: FS %c\n", __func__, cmd[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= 125) {
|
||||
unsigned int k;
|
||||
const unsigned char *s = buf;
|
||||
|
||||
for (k = 0; k < buf_size; k++) {
|
||||
DBG(125, "buf[%d] %02x %c\n", k, s[k],
|
||||
isprint(s[k]) ? s[k] : '.');
|
||||
}
|
||||
}
|
||||
|
||||
if (s->hw->connection == SANE_EPSON_NET) {
|
||||
if (reply_len == 0) {
|
||||
DBG(0,
|
||||
"Cannot send this command to a networked scanner\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
return sanei_epson_net_write(s, 0x2000, buf, buf_size,
|
||||
reply_len, status);
|
||||
} else if (s->hw->connection == SANE_EPSON_SCSI) {
|
||||
return sanei_epson2_scsi_write(s->fd, buf, buf_size, status);
|
||||
} else if (s->hw->connection == SANE_EPSON_PIO) {
|
||||
size_t n;
|
||||
|
||||
if (buf_size == (n = sanei_pio_write(s->fd, buf, buf_size)))
|
||||
*status = SANE_STATUS_GOOD;
|
||||
else
|
||||
*status = SANE_STATUS_INVAL;
|
||||
|
||||
return n;
|
||||
|
||||
} else if (s->hw->connection == SANE_EPSON_USB) {
|
||||
size_t n;
|
||||
n = buf_size;
|
||||
*status = sanei_usb_write_bulk(s->fd, buf, &n);
|
||||
w_cmd_count++;
|
||||
DBG(20, "%s: cmd count, r = %d, w = %d\n",
|
||||
__func__, r_cmd_count, w_cmd_count);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
*status = SANE_STATUS_INVAL;
|
||||
return 0;
|
||||
/* never reached */
|
||||
}
|
||||
|
||||
ssize_t
|
||||
epson2_recv(Epson_Scanner * s, void *buf, ssize_t buf_size,
|
||||
SANE_Status * status)
|
||||
{
|
||||
ssize_t n = 0;
|
||||
|
||||
DBG(15, "%s: size = %d, buf = %p\n", __func__, buf_size, buf);
|
||||
|
||||
if (s->hw->connection == SANE_EPSON_NET) {
|
||||
n = sanei_epson_net_read(s, buf, buf_size, status);
|
||||
} else if (s->hw->connection == SANE_EPSON_SCSI) {
|
||||
n = sanei_epson2_scsi_read(s->fd, buf, buf_size, status);
|
||||
} else if (s->hw->connection == SANE_EPSON_PIO) {
|
||||
if (buf_size ==
|
||||
(n = sanei_pio_read(s->fd, buf, (size_t) buf_size)))
|
||||
*status = SANE_STATUS_GOOD;
|
||||
else
|
||||
*status = SANE_STATUS_INVAL;
|
||||
} else if (s->hw->connection == SANE_EPSON_USB) {
|
||||
/* !!! only report an error if we don't read anything */
|
||||
n = buf_size; /* buf_size gets overwritten */
|
||||
*status =
|
||||
sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf,
|
||||
(size_t *) & n);
|
||||
r_cmd_count += (n + 63) / 64; /* add # of packets, rounding up */
|
||||
DBG(20, "%s: cmd count, r = %d, w = %d\n",
|
||||
__func__, r_cmd_count, w_cmd_count);
|
||||
|
||||
if (n > 0)
|
||||
*status = SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (n < buf_size) {
|
||||
DBG(1, "%s: expected = %lu, got = %ld\n", __func__,
|
||||
(u_long) buf_size, (long) n);
|
||||
*status = SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* dump buffer if appropriate */
|
||||
if (DBG_LEVEL >= 127 && n > 0) {
|
||||
int k;
|
||||
const unsigned char *s = buf;
|
||||
|
||||
for (k = 0; k < n; k++)
|
||||
DBG(127, "buf[%d] %02x %c\n", k, s[k],
|
||||
isprint(s[k]) ? s[k] : '.');
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Simple function to exchange a fixed amount of
|
||||
* data with the scanner
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
epson2_txrx(Epson_Scanner * s, unsigned char *txbuf, size_t txlen,
|
||||
unsigned char *rxbuf, size_t rxlen)
|
||||
{
|
||||
SANE_Status status;
|
||||
|
||||
epson2_send(s, txbuf, txlen, rxlen, &status);
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
epson2_recv(s, rxbuf, rxlen, &status);
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This function should be used to send codes that only requires the scanner
|
||||
* to give back an ACK or a NAK.
|
||||
*/
|
||||
SANE_Status
|
||||
epson2_cmd_simple(Epson_Scanner * s, void *buf, size_t buf_size)
|
||||
{
|
||||
unsigned char result;
|
||||
SANE_Status status;
|
||||
|
||||
DBG(12, "%s: size = %d\n", __func__, buf_size);
|
||||
|
||||
status = epson2_txrx(s, buf, buf_size, &result, 1);
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
if (result == ACK)
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
if (result == NAK) {
|
||||
DBG(3, "%s: NAK\n", __func__);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
DBG(1, "%s: result is neither ACK nor NAK but 0x%02x\n", __func__,
|
||||
result);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* receives a 4 or 6 bytes information block from the scanner*/
|
||||
SANE_Status
|
||||
epson2_recv_info_block(Epson_Scanner * s, unsigned char *scanner_status,
|
||||
size_t info_size, size_t * payload_size)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char info[6];
|
||||
|
||||
if (s->hw->connection == SANE_EPSON_PIO)
|
||||
epson2_recv(s, info, 1, &status);
|
||||
else
|
||||
epson2_recv(s, info, info_size, &status);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
/* check for explicit NAK */
|
||||
if (info[0] == NAK) {
|
||||
DBG(1, "%s: command not supported\n", __func__);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* check the first byte: if it's not STX, bail out */
|
||||
if (info[0] != STX) {
|
||||
DBG(1, "%s: expecting STX, got %02X\n", __func__, info[0]);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* if connection is PIO read the remaining bytes. */
|
||||
if (s->hw->connection == SANE_EPSON_PIO) {
|
||||
epson2_recv(s, &info[1], info_size - 1, &status);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (scanner_status)
|
||||
*scanner_status = info[1];
|
||||
|
||||
if (payload_size) {
|
||||
*payload_size = le16atoh(&info[2]);
|
||||
|
||||
if (info_size == 6)
|
||||
*payload_size *= le16atoh(&info[4]);
|
||||
|
||||
DBG(14, "%s: payload length: %d\n", __func__, *payload_size);
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* This function can be called for commands that
|
||||
* will be answered by the scanner with an info block of 4 bytes
|
||||
* and a variable payload. The payload is passed back to the caller
|
||||
* in **buf. The caller must free it if != NULL,
|
||||
* even if the status != SANE_STATUS_GOOD.
|
||||
*/
|
||||
|
||||
SANE_Status
|
||||
epson2_cmd_info_block(SANE_Handle handle, unsigned char *params,
|
||||
unsigned char params_len, size_t reply_len,
|
||||
unsigned char **buf, size_t * buf_len)
|
||||
{
|
||||
SANE_Status status;
|
||||
Epson_Scanner *s = (Epson_Scanner *) handle;
|
||||
size_t len;
|
||||
|
||||
DBG(13, "%s, params len = %d, reply len = %d, buf = %p\n",
|
||||
__func__, params_len, reply_len, (void *) buf);
|
||||
|
||||
if (buf == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
/* initialize */
|
||||
*buf = NULL;
|
||||
|
||||
/* send command, we expect the info block + reply_len back */
|
||||
epson2_send(s, params, params_len,
|
||||
reply_len ? reply_len + 4 : 0, &status);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
goto end;
|
||||
|
||||
status = epson2_recv_info_block(s, NULL, 4, &len);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
goto end;
|
||||
|
||||
/* do we need to provide the length of the payload? */
|
||||
if (buf_len)
|
||||
*buf_len = len;
|
||||
|
||||
/* no payload, stop here */
|
||||
if (len == 0)
|
||||
goto end;
|
||||
|
||||
/* if a reply_len has been specified and the actual
|
||||
* length differs, throw a warning
|
||||
*/
|
||||
if (reply_len && (len != reply_len)) {
|
||||
DBG(1, "%s: mismatched len - expected %d, got %d\n",
|
||||
__func__, reply_len, len);
|
||||
}
|
||||
|
||||
/* allocate and receive the payload */
|
||||
*buf = malloc(len);
|
||||
|
||||
if (*buf) {
|
||||
memset(*buf, 0x00, len);
|
||||
epson2_recv(s, *buf, len, &status); /* receive actual data */
|
||||
} else
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
end:
|
||||
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status));
|
||||
|
||||
if (*buf) {
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* This is used for ESC commands with a single byte parameter. Scanner
|
||||
* will answer with ACK/NAK.
|
||||
*/
|
||||
SANE_Status
|
||||
epson2_esc_cmd(Epson_Scanner * s, unsigned char cmd, unsigned char val)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char params[2];
|
||||
|
||||
DBG(8, "%s: cmd = 0x%02x, val = %d\n", __func__, cmd, val);
|
||||
if (!cmd)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
params[0] = ESC;
|
||||
params[1] = cmd;
|
||||
|
||||
status = epson2_cmd_simple(s, params, 2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
|
||||
params[0] = val;
|
||||
|
||||
return epson2_cmd_simple(s, params, 1);
|
||||
}
|
||||
|
||||
/* Send an ACK to the scanner */
|
||||
|
||||
SANE_Status
|
||||
epson2_ack(Epson_Scanner * s)
|
||||
{
|
||||
SANE_Status status;
|
||||
epson2_send(s, S_ACK, 1, 0, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
epson2_ack_next(Epson_Scanner * s, size_t reply_len)
|
||||
{
|
||||
SANE_Status status;
|
||||
epson2_send(s, S_ACK, 1, reply_len, &status);
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Prototypes for epson2 I/O functions
|
||||
*
|
||||
* Based on Kazuhiro Sasayama previous
|
||||
* Work on epson.[ch] file from the SANE package.
|
||||
* Please see those files for original copyrights.
|
||||
*
|
||||
* Copyright (C) 2006 Tower Technologies
|
||||
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* This file is part of the SANE package.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#ifndef epson2_io_h
|
||||
#define epson2_io_h
|
||||
|
||||
extern unsigned int r_cmd_count;
|
||||
extern unsigned int w_cmd_count;
|
||||
|
||||
|
||||
SANE_Status epson2_cmd_simple(Epson_Scanner * s, void *buf, size_t buf_size);
|
||||
int epson2_send(Epson_Scanner * s, void *buf, size_t buf_size,
|
||||
size_t reply_len, SANE_Status * status);
|
||||
ssize_t epson2_recv(Epson_Scanner * s, void *buf, ssize_t buf_size,
|
||||
SANE_Status * status);
|
||||
|
||||
SANE_Status
|
||||
epson2_txrx(Epson_Scanner * s, unsigned char *txbuf, size_t txlen,
|
||||
unsigned char *rxbuf, size_t rxlen);
|
||||
|
||||
SANE_Status
|
||||
epson2_recv_info_block(Epson_Scanner * s, unsigned char *scanner_status,
|
||||
size_t info_size, size_t * payload_size);
|
||||
|
||||
SANE_Status
|
||||
epson2_cmd_info_block(SANE_Handle handle, unsigned char *params,
|
||||
unsigned char params_len, size_t reply_len,
|
||||
unsigned char **buf, size_t * buf_len);
|
||||
|
||||
SANE_Status epson2_ack(Epson_Scanner * s);
|
||||
SANE_Status epson2_ack_next(Epson_Scanner * s, size_t reply_len);
|
||||
|
||||
SANE_Status
|
||||
epson2_esc_cmd(Epson_Scanner * s, unsigned char cmd, unsigned char val);
|
||||
#endif /* epson2_io_h */
|
3315
backend/epson2.c
3315
backend/epson2.c
Plik diff jest za duży
Load Diff
|
@ -18,10 +18,40 @@
|
|||
#ifndef epson2_h
|
||||
#define epson2_h
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#undef BACKEND_NAME
|
||||
#define BACKEND_NAME epson2
|
||||
#define DEBUG_NOT_STATIC
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sane/sane.h>
|
||||
#include <sane/sanei_backend.h>
|
||||
#include <sane/sanei_debug.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define __func__ __FUNCTION__
|
||||
#else
|
||||
#define __func__ "(undef)"
|
||||
/* I cast my vote for C99... :) */
|
||||
#endif
|
||||
|
||||
#define EPSON2_CONFIG_FILE "epson2.conf"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX (1024)
|
||||
#endif
|
||||
|
||||
#ifndef XtNumber
|
||||
#define XtNumber(x) (sizeof(x) / sizeof(x[0]))
|
||||
#define XtOffset(p_type, field) ((size_t)&(((p_type)NULL)->field))
|
||||
#define XtOffsetOf(s_type, field) XtOffset(s_type*, field)
|
||||
#endif
|
||||
|
||||
#define NUM_OF_HEX_ELEMENTS (16) /* number of hex numbers per line for data dump */
|
||||
#define DEVICE_NAME_LEN (16) /* length of device name in extended status */
|
||||
|
||||
|
||||
/* some string constants that are used in the config file */
|
||||
|
||||
#define SANE_EPSON_CONFIG_USB "usb"
|
||||
|
@ -46,6 +76,9 @@
|
|||
|
||||
#define SANE_EPSON_MAX_RETRIES 120 /* how often do we retry during warmup ? */
|
||||
|
||||
#ifndef MM_PER_INCH
|
||||
#define MM_PER_INCH 25.4
|
||||
#endif
|
||||
|
||||
/* NOTE: you can find these codes with "man ascii". */
|
||||
#define STX 0x02
|
||||
|
@ -164,13 +197,13 @@ typedef struct
|
|||
unsigned char set_color_correction_coefficients; /* B3 and later */
|
||||
unsigned char request_extended_status; /* get extended status from scanner */
|
||||
unsigned char control_an_extension; /* for extension control */
|
||||
unsigned char eject; /* for extension control */
|
||||
unsigned char eject; /* for extension control */
|
||||
unsigned char feed;
|
||||
unsigned char request_push_button_status;
|
||||
unsigned char control_auto_area_segmentation;
|
||||
unsigned char set_film_type; /* for extension control */
|
||||
unsigned char set_film_type; /* for extension control */
|
||||
unsigned char set_exposure_time; /* F5 only */
|
||||
unsigned char set_bay; /* F5 only */
|
||||
unsigned char set_bay; /* F5 only */
|
||||
unsigned char set_threshold;
|
||||
unsigned char set_focus_position; /* B8 only */
|
||||
unsigned char request_focus_position; /* B8 only */
|
||||
|
@ -202,32 +235,6 @@ typedef enum
|
|||
SANE_EPSON_NET /* network interface */
|
||||
} Epson_Connection_Type;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u_short opt_resolution;
|
||||
u_char sensor;
|
||||
u_char scan_order;
|
||||
u_char line_dist1;
|
||||
u_char line_dist2;
|
||||
|
||||
u_short main_res1;
|
||||
u_short main_res2;
|
||||
u_short main_res3;
|
||||
u_short main_res4;
|
||||
u_short main_res5;
|
||||
u_short main_res6;
|
||||
u_short main_res7;
|
||||
|
||||
u_short sub_res1;
|
||||
u_short sub_res2;
|
||||
u_short sub_res3;
|
||||
u_short sub_res4;
|
||||
u_short sub_res5;
|
||||
u_short sub_res6;
|
||||
} Epson_Identity2;
|
||||
|
||||
|
||||
struct Epson_Device
|
||||
{
|
||||
struct Epson_Device *next;
|
||||
|
@ -259,7 +266,7 @@ struct Epson_Device
|
|||
SANE_Int use_extension; /* use the installed extension */
|
||||
SANE_Bool TPU; /* TPU is installed */
|
||||
SANE_Bool ADF; /* ADF is installed */
|
||||
SANE_Bool duplexSupport; /* does the ADF handle duplex scanning */
|
||||
SANE_Bool duplex; /* does the ADF handle duplex scanning */
|
||||
SANE_Bool focusSupport; /* does this scanner have support for "set focus position" ? */
|
||||
SANE_Bool color_shuffle; /* does this scanner need color shuffling */
|
||||
SANE_Int maxDepth; /* max. color depth */
|
||||
|
@ -273,14 +280,6 @@ struct Epson_Device
|
|||
|
||||
SANE_Bool wait_for_button; /* do we have to wait until the scanner button is pressed? */
|
||||
|
||||
SANE_Int fbf_max_x;
|
||||
SANE_Int fbf_max_y;
|
||||
SANE_Int adf_max_x;
|
||||
SANE_Int adf_max_y;
|
||||
|
||||
SANE_Int devtype;
|
||||
|
||||
SANE_Bool local;
|
||||
SANE_Bool extended_commands;
|
||||
|
||||
EpsonCmd cmd;
|
||||
|
@ -318,6 +317,13 @@ struct Epson_Scanner
|
|||
SANE_Int left, top, lcount;
|
||||
unsigned char *netbuf, *netptr;
|
||||
size_t netlen;
|
||||
|
||||
|
||||
/* extended image data handshaking */
|
||||
SANE_Int ext_block_len;
|
||||
SANE_Int ext_last_len;
|
||||
SANE_Int ext_blocks;
|
||||
SANE_Int ext_counter;
|
||||
};
|
||||
|
||||
typedef struct Epson_Scanner Epson_Scanner;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include <sane/sane.h>
|
||||
#include <sane/saneopts.h>
|
||||
#include <sane/sanei_debug.h>
|
||||
#include <sane/sanei_tcp.h>
|
||||
#include <sane/sanei_config.h>
|
||||
#include <sane/sanei_backend.h>
|
||||
|
@ -23,6 +22,13 @@
|
|||
#include "epson2.h"
|
||||
#include "epson2_net.h"
|
||||
|
||||
#include "byteorder.h"
|
||||
|
||||
#undef BACKEND_NAME
|
||||
#define BACKEND_NAME epson2_net
|
||||
|
||||
#include <sane/sanei_debug.h>
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
@ -38,6 +44,29 @@
|
|||
#include <string.h> /* for memset and memcpy */
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, size_t wanted,
|
||||
SANE_Status * status)
|
||||
{
|
||||
size_t size, read = 0;
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
|
||||
|
||||
while (read < wanted) {
|
||||
size = sanei_tcp_read(s->fd, buf + read, wanted - read);
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
read += size;
|
||||
}
|
||||
|
||||
if (read < wanted)
|
||||
*status = SANE_STATUS_IO_ERROR;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
int
|
||||
sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, size_t wanted,
|
||||
|
@ -46,62 +75,69 @@ sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, size_t wanted,
|
|||
size_t size, read = 0;
|
||||
unsigned char header[12];
|
||||
|
||||
if (s->netbuf != s->netptr ) {
|
||||
/* if (s->netlen == wanted) {*/
|
||||
DBG(4, "reading %d from buffer at %p\n", wanted, s->netptr);
|
||||
memcpy(buf, s->netptr + s->netlen - wanted, wanted);
|
||||
read = wanted;
|
||||
/* } */
|
||||
/* read from buffer, if available */
|
||||
if (s->netptr != s->netbuf) {
|
||||
DBG(4, "reading %d from buffer at %p, %d available\n",
|
||||
wanted, s->netptr, s->netlen);
|
||||
|
||||
free(s->netbuf);
|
||||
s->netbuf = s->netptr = NULL;
|
||||
s->netlen = 0;
|
||||
memcpy(buf, s->netptr, wanted);
|
||||
read = wanted;
|
||||
|
||||
s->netlen -= wanted;
|
||||
|
||||
if (s->netlen == 0) {
|
||||
DBG(4, "%s: freeing %p\n", __func__, s->netbuf);
|
||||
free(s->netbuf);
|
||||
s->netbuf = s->netptr = NULL;
|
||||
s->netlen = 0;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/* receive net header */
|
||||
sanei_tcp_read(s->fd, header, 12);
|
||||
|
||||
if (header[0] != 'I' || header[1] != 'S') {
|
||||
DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]);
|
||||
/* return 0;*/
|
||||
*status = SANE_STATUS_IO_ERROR;
|
||||
return 0;
|
||||
}
|
||||
size = (header[6] << 24) | (header[7] << 16) | (header[8] << 8) | header[9];
|
||||
size = be32atoh(&header[6]);
|
||||
|
||||
DBG(4, "%s: wanted %d, got %d\n", __FUNCTION__, wanted, size);
|
||||
DBG(4, "%s: wanted = %d, available = %d\n", __FUNCTION__, wanted, size);
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
|
||||
if (size == wanted) {
|
||||
DBG(4, "direct read\n");
|
||||
sanei_tcp_read(s->fd, buf, size);
|
||||
DBG(4, "%s: full read\n", __func__);
|
||||
read = sanei_tcp_read(s->fd, buf, size);
|
||||
|
||||
if (s->netbuf)
|
||||
if (s->netbuf) {
|
||||
free(s->netbuf);
|
||||
|
||||
s->netbuf = NULL;
|
||||
s->netlen = 0;
|
||||
read = wanted;
|
||||
s->netbuf = NULL;
|
||||
s->netlen = 0;
|
||||
}
|
||||
} else if (wanted < size && s->netlen == size) {
|
||||
/* unsigned int k; */
|
||||
DBG(4, "%s: partial read\n", __func__);
|
||||
|
||||
sanei_tcp_read(s->fd, s->netbuf, size);
|
||||
|
||||
/* for (k = 0; k < size; k++) {
|
||||
DBG(0, "buf[%d] %02x %c\n", k, s->netbuf[k], isprint(s->netbuf[k]) ? s->netbuf[k] : '.');
|
||||
}
|
||||
*/
|
||||
s->netlen = size - wanted;
|
||||
s->netptr += wanted;
|
||||
read = wanted;
|
||||
DBG(4, "0,4 %02x %02x", s->netbuf[0], s->netbuf[4]);
|
||||
DBG(4, "storing %d to buffer at %p, next read at %p\n", size, s->netbuf, s->netptr);
|
||||
|
||||
memcpy(buf, s->netbuf , wanted);
|
||||
DBG(4, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]);
|
||||
DBG(4, "storing %d to buffer at %p, next read at %p, %d bytes left\n",
|
||||
size, s->netbuf, s->netptr, s->netlen);
|
||||
|
||||
memcpy(buf, s->netbuf, wanted);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
size_t buf_size, size_t reply_len, SANE_Status *status)
|
||||
|
@ -135,32 +171,23 @@ sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *b
|
|||
h1[4] = 0x00;
|
||||
h1[5] = 0x0C; /* Don't know what's that */
|
||||
|
||||
DBG(9, "H1 [0-3]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]);
|
||||
DBG(9, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]);
|
||||
|
||||
if((cmd >> 8) == 0x20) {
|
||||
h1[6] = (buf_size + 8) >> 24;
|
||||
h1[7] = (buf_size + 8) >> 16;
|
||||
h1[8] = (buf_size + 8) >> 8;
|
||||
h1[9] = (buf_size + 8);
|
||||
htobe32a(&h1[6], buf_size + 8);
|
||||
|
||||
DBG(9, "H1 [6-9]: %02x %02x %02x %02x\n", h1[6], h1[7], h1[8], h1[9]);
|
||||
htobe32a(&h2[0], buf_size);
|
||||
htobe32a(&h2[4], reply_len);
|
||||
|
||||
h2[0] = (buf_size) >> 24;
|
||||
h2[1] = (buf_size) >> 16;
|
||||
h2[2] = (buf_size) >> 8;
|
||||
h2[3] = buf_size;
|
||||
|
||||
h2[4] = reply_len >> 24;
|
||||
h2[5] = reply_len >> 16;
|
||||
h2[6] = reply_len >> 8;
|
||||
h2[7] = reply_len;
|
||||
|
||||
DBG(9, "H2(%d): %02x %02x %02x %02x\n", buf_size, h2[0], h2[1], h2[2], h2[3]);
|
||||
DBG(9, "H2(%d): %02x %02x %02x %02x\n", reply_len, h2[4], h2[5], h2[6], h2[7]);
|
||||
DBG(9, "H1[6]: %02x %02x %02x %02x (%d)\n", h1[6], h1[7], h1[8], h1[9], buf_size + 8);
|
||||
DBG(9, "H2[0]: %02x %02x %02x %02x (%d)\n", h2[0], h2[1], h2[2], h2[3], buf_size);
|
||||
DBG(9, "H2[4]: %02x %02x %02x %02x (%d)\n", h2[4], h2[5], h2[6], h2[7], reply_len);
|
||||
}
|
||||
|
||||
if (buf_size && (cmd >> 8) == 0x20) {
|
||||
memcpy(payload, buf, buf_size);
|
||||
if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) {
|
||||
if (buf_size)
|
||||
memcpy(payload, buf, buf_size);
|
||||
|
||||
sanei_tcp_write(s->fd, packet, 12 + 8 + buf_size);
|
||||
}
|
||||
else
|
||||
|
@ -178,6 +205,8 @@ sanei_epson_net_lock(struct Epson_Scanner *s)
|
|||
SANE_Status status;
|
||||
unsigned char buf[1];
|
||||
|
||||
DBG(1, "%s\n", __func__);
|
||||
|
||||
sanei_epson_net_write(s, 0x2100, NULL, 0, 0, &status);
|
||||
sanei_epson_net_read(s, buf, 1, &status);
|
||||
return status;
|
||||
|
@ -187,9 +216,10 @@ SANE_Status
|
|||
sanei_epson_net_unlock(struct Epson_Scanner *s)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char buf[1];
|
||||
|
||||
DBG(1, "%s\n", __func__);
|
||||
|
||||
sanei_epson_net_write(s, 0x2101, NULL, 0, 0, &status);
|
||||
sanei_epson_net_read(s, buf, 1, &status);
|
||||
/* sanei_epson_net_read(s, buf, 1, &status); */
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ extern int sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, siz
|
|||
extern int sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
size_t buf_size, size_t reply_len,
|
||||
SANE_Status *status);
|
||||
|
||||
extern int
|
||||
sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, size_t wanted,
|
||||
SANE_Status * status);
|
||||
extern SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s);
|
||||
extern SANE_Status sanei_epson_net_unlock(struct Epson_Scanner *s);
|
||||
|
||||
|
|
|
@ -104,5 +104,5 @@ sanei_tcp_write(int fd, const u_char * buf, int count)
|
|||
ssize_t
|
||||
sanei_tcp_read(int fd, u_char * buf, int count)
|
||||
{
|
||||
return recv(fd, buf, count, 0);
|
||||
return recv(fd, buf, count, MSG_WAITALL);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue