#include <errno.h>
#include "texception.h"
#include "tscanner.h"
#include "tscannerepson.h"
#include "tscannerutil.h"
#include "tsystem.h"
#include "tconvert.h"
#include "trop.h"
#include "TScannerIO/TUSBScannerIO.h"
#include <cassert>
#include <memory>
#include <fstream>
#include <sstream>
using namespace TScannerUtil;
static void sense(bool) {}
static int scsi_maxlen() {
assert(0);
return 0;
}
#define BW_USES_GRAYTONES
#ifndef _WIN32
#define SWAPIT
#endif
#ifdef i386
#undef SWAPIT
#endif
/*
Commands used to drive the scanner:
cmd spec Level
@ Reset B2 B3 B4 B5 A5
Q Sharpness B4 B5 A5
B Halftoning B1 B2 B3 B4 B5 A5
Z Gamma B2 B3 B4 B5 A5
L Brightness B2 B3 B4 B5 A5
t Threshold
H Zoom B2 B3 B4 B5 A5
R Resolution B1 B2 B3 B4 B5 A5
A Set read Area B1 B2 B3 B4 B5 A5
C Linesequence Mode B1 B2 B3 B4 B5 A5
d Line count B4 B5 A5
D Dataformat B1 B2 B3 B4 B5 A5
g Scan speed B4 B5 A5
G Start Scan B1 B2 B3 B4 B5
e Activate ADF
0x19 Load from ADF
0x0C Unload from ADF
*/
/* NOTE: you can find these codes with "man ascii". */
static unsigned char STX = 0x02;
static unsigned char ACK = 0x06;
static unsigned char NAK = 0x15;
static unsigned char CAN = 0x18;
static unsigned char ESC = 0x1B;
static unsigned char PF = 0x19;
/* STATUS bit in readLineData */
static unsigned char FatalError = 1 << 7;
static unsigned char NotReady = 1 << 6;
//-----------------------------------------------------------------------------
#define log
class TScannerExpection final : public TException {
TString m_scannerMsg;
public:
TScannerExpection(const std::vector<std::string> ¬Fatal,
const std::string &fatal)
: TException("Scanner Expection") {
m_scannerMsg = ::to_wstring(fatal);
for (int i = notFatal.size(); i; i--)
m_scannerMsg += L"\n" + ::to_wstring(notFatal[i - 1]);
log("Exception created: " + ::to_string(m_scannerMsg));
}
TString getMessage() const override { return m_scannerMsg; }
};
//-----------------------------------------------------------------------------
namespace {
/*
void log(string s)
{
std::ofstream os("C:\\butta.txt", std::ios::app);
os << s << std::endl;
os.flush();
}
*/
}
//-----------------------------------------------------------------------------
TScannerEpson::TScannerEpson()
: m_scannerIO(new TUSBScannerIO()), m_hasADF(false), m_isOpened(false) {
log("Created");
}
//-----------------------------------------------------------------------------
void TScannerEpson::closeIO() {
log("CloseIO.");
if (m_scannerIO && m_isOpened) m_scannerIO->close();
m_isOpened = false;
}
//-----------------------------------------------------------------------------
TScannerEpson::~TScannerEpson() {
closeIO();
log("Destroyed");
}
//-----------------------------------------------------------------------------
void TScannerEpson::selectDevice() {
log(std::string("selectDevice; isOpened=") + (m_isOpened ? "true" : "false"));
if (!m_scannerIO->open()) {
log("open() failed");
throw TException("unable to get handle to scanner");
}
m_isOpened = true;
/*
char lev0, lev1;
unsigned short lowRes, hiRes, hMax,vMax;
collectInformation(&lev0, &lev1, &lowRes, &hiRes, &hMax, &vMax);
string version = toString(lev0) + "." + toString(lev1);
*/
setName("Scanner EPSON (Internal driver)");
}
//-----------------------------------------------------------------------------
bool TScannerEpson::isDeviceAvailable() { return true; }
//-----------------------------------------------------------------------------
bool TScannerEpson::isDeviceSelected() { return m_isOpened; }
//-----------------------------------------------------------------------------
void TScannerEpson::updateParameters(TScannerParameters ¶meters) {
log("updateParameters()");
char lev0, lev1;
unsigned short lowRes, hiRes, hMax, vMax;
collectInformation(&lev0, &lev1, &lowRes, &hiRes, &hMax, &vMax);
log("collected info. res = " + std::to_string(lowRes) + "/" +
std::to_string(hiRes));
// non supportiamo black & white
parameters.setSupportedTypes(true, true, true);
// param.m_scanArea = TRectD(0, 0, 0, 0);
parameters.setMaxPaperSize((25.4 * hMax) / (float)hiRes,
(25.4 * vMax) / (float)hiRes);
parameters.updatePaperFormat();
// cambio range, default, step, e supported. aggiorno, se necessario, il value
// (n.b. non dovrebbe succedere
// mai, perche' i range sono sempre gli stessi su tutti gli scanner
TScanParam defaultEpsonParam(0., 255., 128., 1.);
parameters.m_brightness.update(defaultEpsonParam);
parameters.m_contrast.update(defaultEpsonParam);
parameters.m_threshold.update(defaultEpsonParam);
if (m_hasADF) {
TScanParam defaultPaperFeederParam(0., 1., 0., 1.);
parameters.m_paperFeeder.update(defaultPaperFeederParam);
} else
parameters.m_paperFeeder.m_supported = false;
// cerco un default per il dpi. il piu' piccolo possibile nella forma 100+k50
float defaultDpi = 100;
while (defaultDpi < lowRes) defaultDpi += 50;
TScanParam defaultDpiParam(lowRes, hiRes, defaultDpi,
hiRes > lowRes ? 1.F : 0.F);
parameters.m_dpi.update(defaultDpiParam);
// parameters.m_twainVersion = "NATIVE";
// parameters.m_manufacturer = "EPSON";
// parameters.m_version = toString(lev0) + "." + toString(lev1);
log("end updateParameters()");
}
//-----------------------------------------------------------------------------
void TScannerEpson::acquire(const TScannerParameters ¶ms, int paperCount) {
log("acquire");
TRectD scanArea = params.getScanArea();
if (scanArea.isEmpty())
throw TException("Scan area is empty, select a paper size");
/*
if ((scanArea.getSize().lx > params.m_maxPaperSize.lx) ||
(scanArea.getSize().ly > params.m_maxPaperSize.ly))
throw TException("Scan area too large, select a correct paper size");
*/
for (int i = 0; i < paperCount; ++i) {
log("paper " + std::to_string(i));
#ifdef _DEBUG
m_scannerIO->trace(true);
#endif
doSettings(params, i == 0);
unsigned int nTimes = 0;
unsigned int bytes_to_read;
bool rc;
unsigned char stx;
#ifdef _DEBUG
m_scannerIO->trace(false);
#endif
TRasterP ras, rasBuffer;
unsigned char *buffer = 0;
log("Scan command");
rc = ESCI_command('G', false); /* 'SCAN' command */
if (!rc) throw TException("Start Scan failed");
log("Scan command OK");
unsigned short offsetx = 0, offsety = 0;
unsigned short dimlx = 0, dimly = 0;
TRectD scanArea =
params.isPreview() ? params.getScanArea() : params.getCropBox();
scanArea2pix(params, offsetx, offsety, dimlx, dimly, scanArea);
tswap(dimlx, dimly);
unsigned int bytes;
switch (params.getScanType()) {
case TScannerParameters::BW:
#ifdef BW_USES_GRAYTONES
ras = TRasterGR8P(dimlx, dimly);
bytes = dimlx * dimly;
rasBuffer = TRasterGR8P(dimlx, dimly);
buffer = rasBuffer->getRawData();
break;
break;
#else
ras = TRasterGR8P(dimlx, dimly);
bytes = tceil(dimlx / 8) * dimly;
rasBuffer = TRasterGR8P(tceil(dimlx / 8), dimly);
// bytes = (dimlx + 7) % 8 * dimly;
// rasBuffer = TRasterGR8P((dimlx + 7) % 8,dimly);
buffer = rasBuffer->getRawData();
break;
#endif
case TScannerParameters::GR8:
#ifdef GRAYTONES_USES_RGB
ras = TRasterGR8P(dimlx, dimly);
bytes = dimlx * dimly * 3;
rasBuffer = TRasterGR8P(dimlx * 3, dimly);
buffer = rasBuffer->getRawData();
break;
#else
ras = TRasterGR8P(dimlx, dimly);
bytes = dimlx * dimly;
rasBuffer = TRasterGR8P(dimlx, dimly);
buffer = rasBuffer->getRawData();
break;
#endif
case TScannerParameters::RGB24:
ras = TRaster32P(dimlx, dimly);
bytes = dimlx * dimly * 3;
rasBuffer = TRasterGR8P(dimlx * 3, dimly);
buffer = rasBuffer->getRawData();
break;
default:
throw TException("Unknown scanner mode");
break;
}
log("sleep");
TSystem::sleep(2000);
log("reading data");
bool areaEnd = false;
unsigned int bytes_read = 0;
while (!areaEnd) {
unsigned short lines, counter;
unsigned char status = 0;
unsigned int retryCount = 0;
do {
ESCI_readLineData(stx, status, counter, lines, areaEnd);
if (status & FatalError) {
retryCount++;
if (retryCount == 1) throw TException("Error scanning");
}
} while (status & FatalError);
bytes_to_read = lines * counter;
if (stx != 0x02) {
std::stringstream os;
os << "header corrupted (" << std::hex << stx << ")" << '\0';
throw TException(os.str());
}
unsigned long reqBytes = bytes_to_read;
std::unique_ptr<unsigned char[]> readBuffer = ESCI_read_data2(reqBytes);
if (!readBuffer) throw TException("Error reading image data");
log("readline: OK");
/*
if (params.getScanType() == TScannerParameters::BW )
{
for (unsigned int i = 0; i< reqBytes;i++)
readBuffer[i] = ~readBuffer[i];
}
*/
memcpy(buffer + bytes_read, readBuffer.get(), reqBytes);
bytes_read += reqBytes;
nTimes++;
if (bytes_read == bytes) break; /* I've read enough bytes */
if (!(stx & 0x20)) sendACK();
}
log("read: OK");
{ /*
FILE *myFile = fopen("C:\\temp\\prova.dmp", "w+");
fwrite(buffer, 1, bytes_to_read, myFile);
fclose(myFile);*/
}
if (params.m_paperFeeder.m_supported &&
(params.m_paperFeeder.m_value == 1.)) {
log("Advance paper");
if (m_settingsMode == OLD_STYLE) ESCI_doADF(0);
log("Advance paper: OK");
}
switch (params.getScanType()) {
case TScannerParameters::BW:
#ifdef BW_USES_GRAYTONES
copyGR8BufferToTRasterBW(buffer, dimlx, dimly, ras, true,
params.m_threshold.m_value);
// copyGR8BufferToTRasterGR8(buffer, dimlx, dimly, ras, true);
break;
#else
copyBWBufferToTRasterGR8(buffer, dimlx, dimly, ras, true, true);
break;
#endif
case TScannerParameters::GR8:
#ifdef GRAYTONES_USES_RGB
copyRGBBufferToTRasterGR8(buffer, dimlx, dimly, dimlx, ras);
break;
#else
copyGR8BufferToTRasterGR8(buffer, dimlx, dimly, ras, true);
break;
#endif
case TScannerParameters::RGB24:
copyRGBBufferToTRaster32(buffer, dimlx, dimly, ras, true);
break;
default:
throw TException("Unknown scanner mode");
break;
}
if (params.getCropBox() != params.getScanArea() && !params.isPreview()) {
TRect scanRect(
TPoint(offsetx, offsety),
TDimension(dimly, dimlx)); // dimLx and ly was has been swapped
scanArea2pix(params, offsetx, offsety, dimlx, dimly,
params.getScanArea());
TRasterP app = ras->create(dimly, dimlx);
TRaster32P app32(app);
TRasterGR8P appGR8(app);
if (app32)
app32->fill(TPixel32::White);
else if (appGR8)
appGR8->fill(TPixelGR8::White);
app->copy(ras, TPoint(dimly - scanRect.y1 - 1, dimlx - scanRect.x1 - 1));
ras = app;
}
TRasterImageP rasImg(ras);
if (ras) {
rasImg->setDpi(params.m_dpi.m_value, params.m_dpi.m_value);
rasImg->setSavebox(ras->getBounds());
}
log("notifying");
notifyImageDone(rasImg);
if (!(params.m_paperFeeder.m_value == 1.) ||
params.isPreview()) // feeder here!
{
if ((paperCount - i) > 1) notifyNextPaper();
} else
notifyAutomaticallyNextPaper();
if (isScanningCanceled()) break;
}
/*Unload Paper if need*/
if ((m_settingsMode == NEW_STYLE) && params.m_paperFeeder.m_supported &&
(params.m_paperFeeder.m_value == 1.)) {
if (!ESCI_command_1b('e', 1, true)) {
std::vector<std::string> notFatal;
throw TScannerExpection(notFatal, "Scanner error (un)loading paper");
}
unsigned char p = 0x0C;
bool status = true;
send(&p, 1);
status = expectACK();
}
log("acquire OK");
}
//-----------------------------------------------------------------------------
bool TScannerEpson::isAreaSupported() { return true; }
//-----------------------------------------------------------------------------
inline unsigned char B0(const unsigned int v) { return (v & 0x000000ff); }
inline unsigned char B1(const unsigned int v) { return (v & 0x0000ff00) >> 8; }
inline unsigned char B2(const unsigned int v) { return (v & 0x00ff0000) >> 16; }
inline unsigned char B3(const unsigned int v) { return (v & 0xff000000) >> 24; }
void TScannerEpson::doSettings(const TScannerParameters ¶ms,
bool firstSheet) {
log("doSettings");
int retryCount = 3;
std::vector<std::string> notFatal;
while (retryCount--) {
if (m_settingsMode == NEW_STYLE) {
if (firstSheet)
if (!resetScanner()) {
notFatal.push_back("Scanner error resetting");
continue;
}
} else {
if (!resetScanner()) {
notFatal.push_back("Scanner error resetting");
continue;
}
}
unsigned char cmd[64];
memset(&cmd, 0, 64);
unsigned char brightness = 0x00;
float bv = params.m_brightness.m_value;
if (bv >= 0 && bv < 43) brightness = 0xFD;
if (bv >= 43 && bv < 86) brightness = 0xFE;
if (bv >= 86 && bv < 128) brightness = 0xFF;
if (bv >= 128 && bv < 171) brightness = 0x00;
if (bv >= 171 && bv < 214) brightness = 0x01;
if (bv >= 214 && bv < 255) brightness = 0x02;
if (bv == 255) brightness = 0x03;
unsigned short dpi = (unsigned short)params.m_dpi.m_value;
unsigned short offsetx, offsety;
unsigned short sizelx, sizely;
TRectD scanArea =
params.isPreview() ? params.getScanArea() : params.getCropBox();
scanArea2pix(params, offsetx, offsety, sizelx, sizely, scanArea);
// the main scan resolution (ESC R)
cmd[0] = B0(dpi);
cmd[1] = B1(dpi);
cmd[2] = B2(dpi);
cmd[3] = B3(dpi);
// the sub scan resolution (ESC R)
cmd[4] = B0(dpi);
cmd[5] = B1(dpi);
cmd[6] = B2(dpi);
cmd[7] = B3(dpi);
// skipping length of main scan (ESC A)
cmd[8] = B0(offsetx);
cmd[9] = B1(offsetx);
cmd[10] = B2(offsetx);
cmd[11] = B3(offsetx);
// skipping length of sub scan (ESC A)
cmd[12] = B0(offsety);
cmd[13] = B1(offsety);
cmd[14] = B2(offsety);
cmd[15] = B3(offsety);
// the length of main scanning (ESC A)
cmd[16] = B0(sizelx);
cmd[17] = B1(sizelx);
cmd[18] = B2(sizelx);
cmd[19] = B3(sizelx);
// the length of sub scanning (ESC A)
cmd[20] = B0(sizely);
cmd[21] = B1(sizely);
cmd[22] = B2(sizely);
cmd[23] = B3(sizely);
#ifdef GRAYTONES_USES_RGB
cmd[24] = 0x13; // scanning color (ESC C)
cmd[25] = 0x08; // data format (ESC D)
#else
switch (params.getScanType()) {
case TScannerParameters::BW:
cmd[24] = 0x00; // scanning BW/Gray (ESC C)
#ifdef BW_USES_GRAYTONES
cmd[25] = 0x08; // data format (ESC D)
#else
cmd[25] = 0x01; // data format (ESC D)
break;
#endif
case TScannerParameters::GR8:
cmd[24] = 0x00; // scanning BW/Gray (ESC C)
cmd[25] = 0x08; // data format (ESC D)
break;
case TScannerParameters::RGB24:
cmd[24] = 0x13; // scanning color (ESC C)
cmd[25] = 0x08; // data format (ESC D)
break;
default:
throw TException("Unknown scanner mode");
break;
}
// cmd[24] = (params.getScanType() == TScannerParameters::RGB24)?0x13:0x00;
// //scanning color (ESC C)
// cmd[25] = (params.getScanType() == TScannerParameters::RGB24)?0x08:0x08; //
// data format (ESC D)
#endif
if (m_settingsMode == NEW_STYLE)
cmd[26] = 0;
else
cmd[26] = (params.m_paperFeeder.m_supported &&
(params.m_paperFeeder.m_value == 1.))
? 0x01
: 0x00; // option control (ESC e)
cmd[27] = 0x00; // scanning mode (ESC g)
cmd[28] = 0xFF; // the number of block line (ESC d)
cmd[29] = 0x02; // gamma (ESC Z)
cmd[30] = brightness; // brightness (ESC L)
cmd[31] = 0x80; // color collection (ESC M)
cmd[32] = 0x01; // half toning processing (ESC B)
cmd[33] = (unsigned char)params.m_threshold.m_value; // threshold (ESC t)
cmd[34] = 0x00; // separate of area (ESC s)
cmd[35] = 0x01; // sharpness control (ESC Q)
cmd[36] = 0x00; // mirroring (ESC K)
cmd[37] = 0x00; // set film type (ESC N)
// other bytes should be set to 0x00 !
if (m_settingsMode == NEW_STYLE)
if (params.m_paperFeeder.m_supported &&
(params.m_paperFeeder.m_value == 1.)) {
unsigned char v = (params.m_paperFeeder.m_value == 1.) ? 0x01 : 0x00;
if (!ESCI_command_1b('e', v, true))
throw TScannerExpection(notFatal, "Scanner error (un)loading paper");
if (v) {
unsigned char p = 0x19;
bool status = true;
send(&p, 1);
status = expectACK();
}
}
unsigned char setParamCmd[2] = {0x1C, 0x57};
int wrote = send(&setParamCmd[0], 2);
if (wrote != 2)
throw TScannerExpection(notFatal,
"Error setting scanner parameters - W -");
if (!expectACK()) {
notFatal.push_back("Error setting scanner parameters - NAK on W -");
continue;
}
wrote = send(&cmd[0], 0x40);
if (wrote != 0x40)
throw TScannerExpection(notFatal,
"Error setting scanner parameters - D -");
if (!expectACK()) {
notFatal.push_back("Error setting scanner parameters - NAK on D -");
continue;
}
// if here, everything is ok, exit from loop
break;
}
if (retryCount <= 0)
throw TScannerExpection(
notFatal, "Error setting scanner parameters, too many retries");
log("doSettings:OK");
}
//-----------------------------------------------------------------------------
void TScannerEpson::collectInformation(char *lev0, char *lev1,
unsigned short *lowRes,
unsigned short *hiRes,
unsigned short *hMax,
unsigned short *vMax) {
log("collectInformation");
unsigned char stx;
int pos = 0;
unsigned short counter;
unsigned char status;
/*
if (!resetScanner())
throw TException("Scanner error resetting");
*/
if (!ESCI_command('I', false))
throw TException("Unable to get scanner info. Is it off ?");
unsigned long s = 4; // 4 bytes cfr Identity Data Block on ESCI Manual!!!
std::unique_ptr<unsigned char[]> buffer2 = ESCI_read_data2(s);
if (!buffer2 || (s != 4)) throw TException("Error reading scanner info");
memcpy(&stx, buffer2.get(), 1);
memcpy(&counter, &(buffer2[2]), 2);
#ifdef SWAPIT
counter = swapUshort(counter);
#endif
#ifdef _DEBUG
memcpy(&status, &(buffer2[1]), 1);
std::stringstream os;
os << "stx = " << stx << " status = " << status << " counter=" << counter
<< '\n'
<< '\0';
#endif
s = counter;
std::unique_ptr<unsigned char[]> buffer = ESCI_read_data2(s);
int len = strlen((const char *)buffer.get());
/*printf("Level %c%c", buffer[0], buffer[1]);*/
if (len > 1) {
*lev0 = buffer[0];
*lev1 = buffer[1];
}
pos = 2;
/* buffer[pos] contains 'R' */
if (len < 3 || buffer[pos] != 'R') {
*lev0 = '0';
*lev1 = '0';
*lowRes = 0;
*hiRes = 0;
*vMax = 0;
*hMax = 0;
throw TException("unable to get information from scanner");
}
*lowRes = (buffer[pos + 2] * 256) + buffer[pos + 1];
*hiRes = *lowRes;
while (buffer[pos] == 'R') {
*hiRes = (buffer[pos + 2] * 256) + buffer[pos + 1];
/* printf("Resolution %c %d", buffer[pos], *hiRes);*/
pos += 3;
}
if (buffer[pos] != 'A') {
*lev0 = '0';
*lev1 = '0';
*lowRes = 0;
*hiRes = 0;
*vMax = 0;
*hMax = 0;
throw TException("unable to get information from scanner");
}
*hMax = (buffer[pos + 2] * 256) + buffer[pos + 1];
*vMax = (buffer[pos + 4] * 256) + buffer[pos + 3];
ESCI_command('f', false);
ESCI_readLineData2(stx, status, counter);
if (status & FatalError)
throw TException("Fatal error reading information from scanner");
s = counter;
buffer = ESCI_read_data2(s);
// name buffer+1A
const char *name = (const char *)(buffer.get() + 0x1A);
if (strncmp(name, "Perfection1640", strlen("Perfection1640"))) {
m_settingsMode = NEW_STYLE;
} else {
m_settingsMode = OLD_STYLE;
}
#if 0
scsi_new_d("ESCI_extended_status");
scsi_len(42);
/* main status*/
scsi_b00(0, "push_button_supported", 0);
scsi_b11(0, "warming_up", 0);
scsi_b33(0, "adf_load_sequence", 0); /* 1 from first sheet; 0 from last or not supp */
scsi_b44(0, "both_sides_on_adf", 0);
scsi_b55(0, "adf_installed_main_status", 0);
scsi_b66(0, "NFlatbed", 0); /*0 if scanner is flatbed else 1 */
scsi_b77(0, "system_error", 0);
/* adf status */
scsi_b77(1, "adf_installed",0);
/*... some other info.., refer to manual if needed*/
/**/
#endif
m_hasADF = !!(buffer[1] & 0x80);
log("collectInformation:OK");
}
//-----------------------------------------------------------------------------
bool TScannerEpson::resetScanner() {
log("resetScanner");
bool ret = ESCI_command('@', true);
log(std::string("resetScanner: ") + (ret ? "OK" : "FAILED"));
return ret;
}
//-----------------------------------------------------------------------------
int TScannerEpson::receive(unsigned char *buffer, int size) {
return m_scannerIO->receive(buffer, size);
}
int TScannerEpson::send(unsigned char *buffer, int size) {
return m_scannerIO->send(buffer, size);
}
int TScannerEpson::sendACK() { return send(&ACK, 1); }
bool TScannerEpson::expectACK() {
log("expectACK");
unsigned char ack = NAK;
int nb = receive(&ack, 1);
#ifdef _DEBUG
if (ack != ACK) {
std::stringstream os;
os << "ack fails ret = 0x" << std::hex << (int)ack << '\n' << '\0';
TSystem::outputDebug(os.str());
}
#endif
log(std::string("expectACK: ") + (ack == ACK ? "ACK" : "FAILED"));
return (ack == ACK);
}
char *TScannerEpson::ESCI_inquiry(char cmd) /* returns 0 if failed */
{
assert(0);
return 0;
}
bool TScannerEpson::ESCI_command(char cmd, bool checkACK) {
unsigned char p[2];
p[0] = ESC;
p[1] = cmd;
bool status;
int count = send(&(p[0]), 2);
status = count == 2;
if (checkACK) status = expectACK();
return status;
}
bool TScannerEpson::ESCI_command_1b(char cmd, unsigned char p0, bool checkACK) {
bool status = false;
if (ESCI_command(cmd, checkACK)) {
unsigned char p = p0;
status = true;
send(&p, 1);
if (checkACK) status = expectACK();
}
return status;
}
bool TScannerEpson::ESCI_command_2b(char cmd, unsigned char p0,
unsigned char p1, bool checkACK) {
bool status = false;
if (ESCI_command(cmd, checkACK)) {
status = true;
unsigned char p[2];
p[0] = p0;
p[1] = p1;
int timeout = 30000;
send(&(p[0]), 2);
if (checkACK) status = expectACK();
}
return status;
}
bool TScannerEpson::ESCI_command_2w(char cmd, unsigned short p0,
unsigned short p1, bool checkACK) {
bool status = false;
if (ESCI_command(cmd, checkACK)) {
status = true;
unsigned short p[2];
p[0] = p0;
p[1] = p1;
const int len = 1;
int timeout = 30000;
send((unsigned char *)(&(p[0])), 4);
if (checkACK) status = expectACK();
}
return status;
}
bool TScannerEpson::ESCI_command_4w(char cmd, unsigned short p0,
unsigned short p1, unsigned short p2,
unsigned short p3, bool checkACK) {
bool status = false;
if (ESCI_command(cmd, checkACK)) {
status = true;
unsigned char p[8];
p[0] = (unsigned char)p0;
p[1] = (unsigned char)(p0 >> 8);
p[2] = (unsigned char)p1;
p[3] = (unsigned char)(p1 >> 8);
p[4] = (unsigned char)p2;
p[5] = (unsigned char)(p2 >> 8);
p[6] = (unsigned char)(p3);
p[7] = (unsigned char)(p3 >> 8);
send((unsigned char *)&(p[0]), 8);
if (checkACK) status = expectACK();
}
return status;
}
std::unique_ptr<unsigned char[]> TScannerEpson::ESCI_read_data2(
unsigned long &size) {
std::unique_ptr<unsigned char[]> buffer(new unsigned char[size]);
memset(buffer.get(), 0, size);
unsigned long bytesToRead = size;
size = receive(buffer.get(), bytesToRead);
return buffer;
}
bool TScannerEpson::ESCI_doADF(bool on) {
// check ref esci documentation page 3-64
unsigned char eject = 0x0c;
int rc = send(&eject, 1);
bool status1 = expectACK();
return status1;
return 1;
if (!ESCI_command_1b('e', 0x01, true)) {
if (on)
throw TException("Scanner error loading paper");
else
throw TException("Scanner error unloading paper");
}
unsigned char p = on ? 0x19 : 0x0C;
send(&p, 1);
bool status = expectACK();
return status;
}
void TScannerEpson::scanArea2pix(const TScannerParameters ¶ms,
unsigned short &offsetx,
unsigned short &offsety,
unsigned short &sizelx, unsigned short &sizely,
const TRectD &scanArea) {
const double f = 25.4;
offsetx = (unsigned short)((scanArea.x0 * params.m_dpi.m_value) / f);
offsety = (unsigned short)((scanArea.y0 * params.m_dpi.m_value) / f);
sizelx =
(unsigned short)(((scanArea.x1 - scanArea.x0) * params.m_dpi.m_value) /
f);
sizelx = (sizelx >> 3) << 3; // questo deve essere multiplo di 8
sizely =
(unsigned short)(((scanArea.y1 - scanArea.y0) * params.m_dpi.m_value) /
f);
}
void TScannerEpson::ESCI_readLineData(unsigned char &stx, unsigned char &status,
unsigned short &counter,
unsigned short &lines, bool &areaEnd) {
unsigned long s = 6;
std::unique_ptr<unsigned char[]> buffer = ESCI_read_data2(s);
if (!buffer) throw TException("Error reading scanner info");
/* PACKET DATA LEN = 6
type offs descr
byte 0 STX
b77 1 fatal_error
b66 1 not_ready
b55 1 area_end
b44 1 option_unit
b33 1 col_attrib_bit_3
b22 1 col_attrib_bit_2
b11 1 extended_commands
drow 2, counter
drow 4 lines
*/
bool fatalError = !!(buffer[1] & 0x80);
bool notReady = !!(buffer[1] & 0x40);
areaEnd = !!(buffer[1] & 0x20);
memcpy(&stx, buffer.get(), 1);
memcpy(&counter, &(buffer[2]), 2);
#ifdef SWAPIT
counter = swapUshort(counter);
#endif
memcpy(&lines, &(buffer[4]), 2);
#ifdef SWAPIT
lines = swapUshort(lines);
#endif
status = buffer[1];
#ifdef _DEBUG
std::stringstream os;
os << "fatal=" << fatalError;
os << " notReady=" << notReady;
os << " areaEnd=" << areaEnd;
os << " stx=" << stx;
os << " counter=" << counter;
os << " lines=" << lines;
os << '\n' << '\0';
TSystem::outputDebug(os.str());
#endif
}
void TScannerEpson::ESCI_readLineData2(unsigned char &stx,
unsigned char &status,
unsigned short &counter) {
unsigned long s = 4;
std::unique_ptr<unsigned char[]> buffer = ESCI_read_data2(s);
if (!buffer) throw TException("Error reading scanner info");
bool fatalError = !!(buffer[1] & 0x80);
bool notReady = !!(buffer[1] & 0x40);
memcpy(&stx, buffer.get(), 1);
memcpy(&counter, &(buffer[2]), 2);
#ifdef SWAPIT
counter = swapUshort(counter);
#endif
status = buffer[1];
#ifdef _DEBUG
std::stringstream os;
os << "fatal=" << fatalError;
os << " notReady=" << notReady;
os << " stx=" << stx;
os << " counter=" << counter;
os << '\n' << '\0';
TSystem::outputDebug(os.str());
#endif
}