kopia lustrzana https://gitlab.com/sane-project/backends
850 wiersze
19 KiB
C
850 wiersze
19 KiB
C
/*
|
|
* 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
|
|
esci_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 = e2_cmd_simple(s, params, 2);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
params[0] = x;
|
|
params[1] = y;
|
|
|
|
return e2_cmd_simple(s, params, 2);
|
|
}
|
|
|
|
/* ESC R */
|
|
SANE_Status
|
|
esci_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 = e2_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 e2_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
|
|
esci_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 = e2_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 e2_cmd_simple(s, params, 8);
|
|
}
|
|
|
|
/*
|
|
* Sends the "set color correction coefficients" command with the
|
|
* currently selected parameters to the scanner.
|
|
*/
|
|
|
|
SANE_Status
|
|
esci_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 = e2_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(11, "%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 e2_cmd_simple(s, params, 9);
|
|
}
|
|
|
|
SANE_Status
|
|
esci_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(11, "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 = e2_cmd_simple(s, params, 2);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = e2_cmd_simple(s, gamma, 257);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/* ESC F - Request Status
|
|
* -> ESC f
|
|
* <- Information block
|
|
*/
|
|
|
|
SANE_Status
|
|
esci_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;
|
|
|
|
e2_send(s, params, 2, 4, &status);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = e2_recv_info_block(s, params, 4, NULL);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
if (scanner_status)
|
|
*scanner_status = params[0];
|
|
|
|
DBG(1, "status: %02x\n", params[0]);
|
|
|
|
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
|
|
esci_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 = e2_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: %lu\n", (u_long) le32atoh(&buf[4]));
|
|
DBG(1, " min resolution : %lu\n", (u_long) le32atoh(&buf[8]));
|
|
DBG(1, " max resolution : %lu\n", (u_long) le32atoh(&buf[12]));
|
|
DBG(1, " max pixel num : %lu\n", (u_long) le32atoh(&buf[16]));
|
|
DBG(1, " scan area : %lux%lu\n",
|
|
(u_long) le32atoh(&buf[20]), (u_long) le32atoh(&buf[24]));
|
|
|
|
DBG(1, " adf area : %lux%lu\n",
|
|
(u_long) le32atoh(&buf[28]), (u_long) le32atoh(&buf[32]));
|
|
|
|
DBG(1, " tpu area : %lux%lu\n",
|
|
(u_long) le32atoh(&buf[36]), (u_long) 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
|
|
esci_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 = e2_txrx(s, params, 2, buf, 16);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
DBG(1, "global status : 0x%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 : 0x%02x\n", buf[1]);
|
|
|
|
if (buf[1] & FSF_STATUS_ADF_IST)
|
|
DBG(11, " installed\n");
|
|
else
|
|
DBG(11, " not installed\n");
|
|
|
|
if (buf[1] & FSF_STATUS_ADF_EN)
|
|
DBG(11, " enabled\n");
|
|
else
|
|
DBG(11, " 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 : 0x%02x\n", buf[2]);
|
|
|
|
if (buf[2] & FSF_STATUS_TPU_IST)
|
|
DBG(11, " installed\n");
|
|
else
|
|
DBG(11, " not installed\n");
|
|
|
|
if (buf[2] & FSF_STATUS_TPU_EN)
|
|
DBG(11, " enabled\n");
|
|
else
|
|
DBG(11, " 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, "device type : 0x%02x\n", buf[3] & 0xC0);
|
|
DBG(1, "main body status: 0x%02x\n", buf[3] & 0x3F);
|
|
|
|
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
|
|
esci_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(10, "resolution of main scan : %lu\n", (u_long) le32atoh(&buf[0]));
|
|
DBG(10, "resolution of sub scan : %lu\n", (u_long) le32atoh(&buf[4]));
|
|
DBG(10, "offset length of main scan : %lu\n", (u_long) le32atoh(&buf[8]));
|
|
DBG(10, "offset length of sub scan : %lu\n", (u_long) le32atoh(&buf[12]));
|
|
DBG(10, "scanning length of main scan: %lu\n", (u_long) le32atoh(&buf[16]));
|
|
DBG(10, "scanning length of sub scan : %lu\n", (u_long) le32atoh(&buf[20]));
|
|
DBG(10, "scanning color : %d\n", buf[24]);
|
|
DBG(10, "data format : %d\n", buf[25]);
|
|
DBG(10, "option control : %d\n", buf[26]);
|
|
DBG(10, "scanning mode : %d\n", buf[27]);
|
|
DBG(10, "block line number : %d\n", buf[28]);
|
|
DBG(10, "gamma correction : %d\n", buf[29]);
|
|
DBG(10, "brightness : %d\n", buf[30]);
|
|
DBG(10, "color correction : %d\n", buf[31]);
|
|
DBG(10, "halftone processing : %d\n", buf[32]);
|
|
DBG(10, "threshold : %d\n", buf[33]);
|
|
DBG(10, "auto area segmentation : %d\n", buf[34]);
|
|
DBG(10, "sharpness control : %d\n", buf[35]);
|
|
DBG(10, "mirroring : %d\n", buf[36]);
|
|
DBG(10, "film type : %d\n", buf[37]);
|
|
DBG(10, "main lamp lighting mode : %d\n", buf[38]);
|
|
|
|
status = e2_cmd_simple(s, params, 2);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = e2_cmd_simple(s, buf, 64);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
esci_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 = e2_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
|
|
esci_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 = e2_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
|
|
esci_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 = e2_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
|
|
esci_request_identity(SANE_Handle handle, unsigned char **buf, size_t *len)
|
|
{
|
|
Epson_Scanner *s = (Epson_Scanner *) handle;
|
|
unsigned char params[2];
|
|
|
|
DBG(8, "%s\n", __func__);
|
|
|
|
if (!s->hw->cmd->request_identity)
|
|
return SANE_STATUS_INVAL;
|
|
|
|
params[0] = ESC;
|
|
params[1] = s->hw->cmd->request_identity;
|
|
|
|
return e2_cmd_info_block(s, params, 2, 0, buf, len);
|
|
}
|
|
|
|
|
|
/*
|
|
* Request information from scanner
|
|
*/
|
|
SANE_Status
|
|
esci_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(8, "%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 = e2_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
|
|
esci_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 = e2_cmd_simple(s, params, 2);
|
|
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
esci_feed(Epson_Scanner * s)
|
|
{
|
|
unsigned char params[1];
|
|
|
|
DBG(8, "%s\n", __func__);
|
|
|
|
if (!s->hw->cmd->feed)
|
|
return SANE_STATUS_UNSUPPORTED;
|
|
|
|
params[0] = s->hw->cmd->feed;
|
|
|
|
return e2_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
|
|
esci_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 e2_cmd_simple(s, params, 1);
|
|
}
|
|
|
|
SANE_Status
|
|
esci_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 = e2_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 (%lu)\n", __func__,
|
|
(u_long) 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;
|
|
}
|