1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci * epsonds-cmd.c - Epson ESC/I-2 routines. 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Copyright (C) 2015 Tower Technologies 5141cc406Sopenharmony_ci * Author: Alessandro Zummo <a.zummo@towertech.it> 6141cc406Sopenharmony_ci * 7141cc406Sopenharmony_ci * This file is part of the SANE package. 8141cc406Sopenharmony_ci * 9141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 10141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 11141cc406Sopenharmony_ci * published by the Free Software Foundation, version 2. 12141cc406Sopenharmony_ci */ 13141cc406Sopenharmony_ci 14141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci#include "sane/config.h" 17141cc406Sopenharmony_ci#include <ctype.h> 18141cc406Sopenharmony_ci#include <unistd.h> /* sleep */ 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci#include "epsonds.h" 21141cc406Sopenharmony_ci#include "epsonds-io.h" 22141cc406Sopenharmony_ci#include "epsonds-cmd.h" 23141cc406Sopenharmony_ci#include "epsonds-ops.h" 24141cc406Sopenharmony_ci#include "epsonds-net.h" 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_cistatic SANE_Status 27141cc406Sopenharmony_ciesci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len)) 28141cc406Sopenharmony_ci{ 29141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 30141cc406Sopenharmony_ci SANE_Status delayed_status = SANE_STATUS_GOOD; 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci char *start = buf; 34141cc406Sopenharmony_ci char *end = (buf + len) - 1; 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci /* 0 : # 37141cc406Sopenharmony_ci * 1-3: param 38141cc406Sopenharmony_ci * 4- : data 39141cc406Sopenharmony_ci */ 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci while (1) { 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci char param[4]; 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci while (*start != '#' && start < end) 46141cc406Sopenharmony_ci start++; 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci if (*start != '#') 49141cc406Sopenharmony_ci break; 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci param[0] = *++start; 52141cc406Sopenharmony_ci param[1] = *++start; 53141cc406Sopenharmony_ci param[2] = *++start; 54141cc406Sopenharmony_ci param[3] = '\0'; 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci if (strncmp("---", param, 3) == 0) 57141cc406Sopenharmony_ci break; 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci /* ugly hack to skip over GMT in RESA */ 60141cc406Sopenharmony_ci if (strncmp("GMT", param, 3) == 0 && *(start + 5) == 'h') { 61141cc406Sopenharmony_ci start = start + 4 + 0x100; 62141cc406Sopenharmony_ci continue; 63141cc406Sopenharmony_ci } 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci /* find the end of the token */ 66141cc406Sopenharmony_ci { 67141cc406Sopenharmony_ci int tlen; 68141cc406Sopenharmony_ci char *next = start; 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci while (*next != '#' && *next != 0x00 && next < end) 71141cc406Sopenharmony_ci next++; 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci tlen = next - start - 1; 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci if (cb) { 76141cc406Sopenharmony_ci status = cb(userdata, start - 2, tlen); 77141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 78141cc406Sopenharmony_ci delayed_status = status; 79141cc406Sopenharmony_ci } 80141cc406Sopenharmony_ci } 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci start = next; 83141cc406Sopenharmony_ci } 84141cc406Sopenharmony_ci } 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci if (delayed_status != SANE_STATUS_GOOD) 87141cc406Sopenharmony_ci return delayed_status; 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci return status; 90141cc406Sopenharmony_ci} 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_cistatic SANE_Bool 93141cc406Sopenharmony_ciesci2_check_header(const char *cmd, const char *buf, unsigned int *more) 94141cc406Sopenharmony_ci{ 95141cc406Sopenharmony_ci int err; 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci *more = 0; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci if (strncmp(cmd, buf, 4) != 0) { 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci if (strncmp("UNKN", buf, 4) == 0) { 102141cc406Sopenharmony_ci DBG(1, "UNKN reply code received\n"); 103141cc406Sopenharmony_ci } else if (strncmp("INVD", buf, 4) == 0) { 104141cc406Sopenharmony_ci DBG(1, "INVD reply code received\n"); 105141cc406Sopenharmony_ci } else { 106141cc406Sopenharmony_ci DBG(1, "%c%c%c%c, unexpected reply code\n", buf[0], buf[1], buf[2], buf[3]); 107141cc406Sopenharmony_ci } 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci return 0; 110141cc406Sopenharmony_ci } 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci /* INFOx0000100#.... */ 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci /* read the answer len */ 115141cc406Sopenharmony_ci if (buf[4] != 'x') { 116141cc406Sopenharmony_ci DBG(1, "unknown type in header: %c\n", buf[4]); 117141cc406Sopenharmony_ci return 0; 118141cc406Sopenharmony_ci } 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci err = sscanf(&buf[5], "%7x#", more); 121141cc406Sopenharmony_ci if (err != 1) { 122141cc406Sopenharmony_ci DBG(1, "cannot decode length from header\n"); 123141cc406Sopenharmony_ci return 0; 124141cc406Sopenharmony_ci } 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci return 1; 127141cc406Sopenharmony_ci} 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_cistatic SANE_Status esci2_cmd(epsonds_scanner* s, 130141cc406Sopenharmony_ci char *cmd, size_t len, 131141cc406Sopenharmony_ci char *payload, size_t plen, 132141cc406Sopenharmony_ci void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len)) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci SANE_Status status; 135141cc406Sopenharmony_ci unsigned int more; 136141cc406Sopenharmony_ci char header[13], rbuf[64]; /* add one more byte for header buffer to correct buffer overflow issue,*/ 137141cc406Sopenharmony_ci char *buf; 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen); 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci memset(header, 0x00, sizeof(header)); 142141cc406Sopenharmony_ci memset(rbuf, 0x00, sizeof(rbuf)); 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci // extra safety check, will not happen 145141cc406Sopenharmony_ci if (len != 12) { 146141cc406Sopenharmony_ci DBG(1, "%s: command has wrong size (%lu != 12)\n", __func__, len); 147141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 148141cc406Sopenharmony_ci } 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci // merge ParameterBlock size 151141cc406Sopenharmony_ci sprintf(header, "%4.4sx%07x", cmd, (unsigned int)plen); 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci // send RequestBlock, request immediate response if there's no payload 154141cc406Sopenharmony_ci status = eds_txrx(s, header, len, rbuf, (plen > 0) ? 0 : 64); 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci /* pointer to the token's value */ 157141cc406Sopenharmony_ci buf = rbuf + 12; 158141cc406Sopenharmony_ci /* nrd / nrdBUSY */ 159141cc406Sopenharmony_ci DBG(8, "buf = %s\n",buf); 160141cc406Sopenharmony_ci if (strncmp("#nrd", buf, 4) == 0) { 161141cc406Sopenharmony_ci buf += 4; 162141cc406Sopenharmony_ci DBG(8, "buf = %s\n",buf); 163141cc406Sopenharmony_ci if (strncmp("BUSY", buf, 4) == 0) { 164141cc406Sopenharmony_ci DBG(8, "device busy\n"); 165141cc406Sopenharmony_ci DBG(8, "SANE_STATUS:%d\n", SANE_STATUS_DEVICE_BUSY); 166141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 167141cc406Sopenharmony_ci } 168141cc406Sopenharmony_ci } 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 171141cc406Sopenharmony_ci return status; 172141cc406Sopenharmony_ci } 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci /* send ParameterBlock, request response */ 175141cc406Sopenharmony_ci if (plen) { 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci DBG(8, " %12.12s (%lu)\n", header, plen); 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci status = eds_txrx(s, payload, plen, rbuf, 64); 180141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 181141cc406Sopenharmony_ci return status; 182141cc406Sopenharmony_ci } 183141cc406Sopenharmony_ci } 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci /* rxbuf holds the DataHeaderBlock, which should be 186141cc406Sopenharmony_ci * parsed to know if we need to read more data 187141cc406Sopenharmony_ci */ 188141cc406Sopenharmony_ci if (!esci2_check_header(cmd, rbuf, &more)) { 189141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 190141cc406Sopenharmony_ci } 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci /* parse the received header block */ 193141cc406Sopenharmony_ci if (cb) { 194141cc406Sopenharmony_ci status = esci2_parse_block(rbuf + 12, 64 - 12, userdata, cb); 195141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD && status != SANE_STATUS_DEVICE_BUSY) { 196141cc406Sopenharmony_ci DBG(1, "%s: %4s error while parsing received header\n", __func__, cmd); 197141cc406Sopenharmony_ci } 198141cc406Sopenharmony_ci } 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci /* header valid, get the data block if present */ 201141cc406Sopenharmony_ci if (more) { 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci char *pbuf = malloc(more); 204141cc406Sopenharmony_ci if (pbuf) { 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSONDS_NET) { 207141cc406Sopenharmony_ci epsonds_net_request_read(s, more); 208141cc406Sopenharmony_ci } 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_ci ssize_t read = eds_recv(s, pbuf, more, &status); 211141cc406Sopenharmony_ci if (read != more) { 212141cc406Sopenharmony_ci free(pbuf); 213141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 214141cc406Sopenharmony_ci } 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci /* parse the received data block */ 217141cc406Sopenharmony_ci if (cb) { 218141cc406Sopenharmony_ci status = esci2_parse_block(pbuf, more, userdata, cb); 219141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 220141cc406Sopenharmony_ci DBG(1, "%s: %4s error while parsing received data block\n", __func__, cmd); 221141cc406Sopenharmony_ci } 222141cc406Sopenharmony_ci } 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_ci free(pbuf); 225141cc406Sopenharmony_ci 226141cc406Sopenharmony_ci } else { 227141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 228141cc406Sopenharmony_ci } 229141cc406Sopenharmony_ci } 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci return status; 232141cc406Sopenharmony_ci} 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_cistatic SANE_Status esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status (*cb)(void *userdata, char *token, int len)) 235141cc406Sopenharmony_ci{ 236141cc406Sopenharmony_ci return esci2_cmd(s, cmd, 12, NULL, 0, s, cb); 237141cc406Sopenharmony_ci} 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ciSANE_Status esci2_fin(epsonds_scanner *s) 240141cc406Sopenharmony_ci{ 241141cc406Sopenharmony_ci SANE_Status status; 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci DBG(5, "%s\n", __func__); 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci status = esci2_cmd_simple(s, "FIN x0000000", NULL); 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci for(int i = 0; i < 10; i++) { 248141cc406Sopenharmony_ci 249141cc406Sopenharmony_ci if(status == SANE_STATUS_DEVICE_BUSY || status == SANE_STATUS_IO_ERROR) { 250141cc406Sopenharmony_ci status = esci2_cmd_simple(s, "FIN x0000000", NULL); 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci else { 253141cc406Sopenharmony_ci DBG(1, "break\n"); 254141cc406Sopenharmony_ci break; 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci DBG(1, "sleep(5)\n"); 257141cc406Sopenharmony_ci sleep(5); 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci } 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci s->locked = 0; 262141cc406Sopenharmony_ci return status; 263141cc406Sopenharmony_ci} 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ciSANE_Status esci2_can(epsonds_scanner *s) 266141cc406Sopenharmony_ci{ 267141cc406Sopenharmony_ci return esci2_cmd_simple(s, "CAN x0000000", NULL); 268141cc406Sopenharmony_ci} 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_cistatic int decode_value(char *buf, int len) 271141cc406Sopenharmony_ci{ 272141cc406Sopenharmony_ci char tmp[10]; 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci memcpy(tmp, buf, len); 275141cc406Sopenharmony_ci tmp[len] = '\0'; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci if (buf[0] == 'd' && len == 4) { 278141cc406Sopenharmony_ci return strtol(buf + 1, NULL, 10); 279141cc406Sopenharmony_ci } else if (buf[0] == 'i' && len == 8) { 280141cc406Sopenharmony_ci return strtol(buf + 1, NULL, 10); 281141cc406Sopenharmony_ci } else if (buf[0] == 'x' && len == 8) { 282141cc406Sopenharmony_ci return strtol(buf + 1, NULL, 16); 283141cc406Sopenharmony_ci } else if (buf[0] == 'h' && len == 4) { 284141cc406Sopenharmony_ci return strtol(buf + 1, NULL, 16); 285141cc406Sopenharmony_ci } 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci return -1; 288141cc406Sopenharmony_ci} 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci/* h000 */ 291141cc406Sopenharmony_cistatic char *decode_binary(char *buf, int len) 292141cc406Sopenharmony_ci{ 293141cc406Sopenharmony_ci char tmp[6]; 294141cc406Sopenharmony_ci int hl; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci memcpy(tmp, buf, 4); 297141cc406Sopenharmony_ci tmp[4] = '\0'; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci if (buf[0] != 'h') 300141cc406Sopenharmony_ci return NULL; 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci hl = strtol(tmp + 1, NULL, 16); 303141cc406Sopenharmony_ci if (hl > len) 304141cc406Sopenharmony_ci hl = len; 305141cc406Sopenharmony_ci if (hl) { 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci char *v = malloc(hl + 1); 308141cc406Sopenharmony_ci memcpy(v, buf + 4, hl); 309141cc406Sopenharmony_ci v[hl] = '\0'; 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci return v; 312141cc406Sopenharmony_ci } 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ci return NULL; 315141cc406Sopenharmony_ci} 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_cistatic char *decode_string(char *buf, int len) 318141cc406Sopenharmony_ci{ 319141cc406Sopenharmony_ci char *p, *s = decode_binary(buf, len); 320141cc406Sopenharmony_ci if (s == NULL) 321141cc406Sopenharmony_ci return NULL; 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci /* trim white space at the end */ 324141cc406Sopenharmony_ci p = s + strlen(s); 325141cc406Sopenharmony_ci while (*--p == ' ') 326141cc406Sopenharmony_ci *p = '\0'; 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci return s; 329141cc406Sopenharmony_ci} 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_cistatic void debug_token(int level, const char *func, char *token, int len) 332141cc406Sopenharmony_ci{ 333141cc406Sopenharmony_ci char *tdata = malloc(len + 1); 334141cc406Sopenharmony_ci memcpy(tdata, token + 3, len); 335141cc406Sopenharmony_ci tdata[len] = '\0'; 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci DBG(level, "%s: %3.3s / %s / %d\n", func, token, tdata, len); 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci free(tdata); 340141cc406Sopenharmony_ci} 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_cistatic SANE_Status info_cb(void *userdata, char *token, int len) 343141cc406Sopenharmony_ci{ 344141cc406Sopenharmony_ci epsonds_scanner *s = (epsonds_scanner *)userdata; 345141cc406Sopenharmony_ci char *value; 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci /* pointer to the token's value */ 349141cc406Sopenharmony_ci value = token + 3; 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci /* nrd / nrdBUSY */ 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci if (strncmp("nrd", token, 3) == 0) { 354141cc406Sopenharmony_ci if (strncmp("BUSY", value, 4) == 0) { 355141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 356141cc406Sopenharmony_ci } 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci if (strncmp("PRD", token, 3) == 0) { 360141cc406Sopenharmony_ci free(s->hw->model); 361141cc406Sopenharmony_ci s->hw->model = decode_string(value, len); 362141cc406Sopenharmony_ci s->hw->sane.model = s->hw->model; 363141cc406Sopenharmony_ci DBG(1, " product: %s\n", s->hw->model); 364141cc406Sopenharmony_ci } 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci if (strncmp("VER", token, 3) == 0) { 367141cc406Sopenharmony_ci char *v = decode_string(value, len); 368141cc406Sopenharmony_ci DBG(1, " version: %s\n", v); 369141cc406Sopenharmony_ci free(v); 370141cc406Sopenharmony_ci } 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci if (strncmp("S/N", token, 3) == 0) { 373141cc406Sopenharmony_ci char *v = decode_string(value, len); 374141cc406Sopenharmony_ci DBG(1, " serial: %s\n", v); 375141cc406Sopenharmony_ci free(v); 376141cc406Sopenharmony_ci } 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci if (strncmp("ADF", token, 3) == 0) { 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci s->hw->has_adf = 1; 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci if (len == 8) { 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci if (strncmp("TYPEPAGE", value, len) == 0) { 385141cc406Sopenharmony_ci DBG(1, " ADF: page type\n"); 386141cc406Sopenharmony_ci } 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci if (strncmp("TYPEFEED", value, len) == 0) { 389141cc406Sopenharmony_ci DBG(1, " ADF: sheet feed type\n"); 390141cc406Sopenharmony_ci } 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_ci if (strncmp("DPLX1SCN", value, len) == 0) { 393141cc406Sopenharmony_ci DBG(1, " ADF: duplex single pass\n"); 394141cc406Sopenharmony_ci s->hw->adf_singlepass = 1; 395141cc406Sopenharmony_ci } 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_ci if (strncmp("DPLX2SCN", value, len) == 0) { 398141cc406Sopenharmony_ci DBG(1, " ADF: duplex double pass\n"); 399141cc406Sopenharmony_ci s->hw->adf_singlepass = 0; 400141cc406Sopenharmony_ci } 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci if (strncmp("FORDPF1N", value, len) == 0) { 403141cc406Sopenharmony_ci DBG(1, " ADF: order is 1 to N\n"); 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci if (strncmp("FORDPFN1", value, len) == 0) { 407141cc406Sopenharmony_ci DBG(1, " ADF: order is N to 1\n"); 408141cc406Sopenharmony_ci } 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci if (strncmp("ALGNLEFT", value, len) == 0) { 411141cc406Sopenharmony_ci DBG(1, " ADF: left aligned\n"); 412141cc406Sopenharmony_ci s->hw->adf_alignment = 0; 413141cc406Sopenharmony_ci } 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci if (strncmp("ALGNCNTR", value, len) == 0) { 416141cc406Sopenharmony_ci DBG(1, " ADF: center aligned\n"); 417141cc406Sopenharmony_ci s->hw->adf_alignment = 1; 418141cc406Sopenharmony_ci } 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci if (strncmp("ALGNRIGT", value, len) == 0) { 421141cc406Sopenharmony_ci DBG(1, " ADF: right aligned (not supported!)\n"); 422141cc406Sopenharmony_ci s->hw->adf_alignment = 2; 423141cc406Sopenharmony_ci } 424141cc406Sopenharmony_ci } 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci if (len == 4) { 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci if (strncmp("PREF", value, len) == 0) { 429141cc406Sopenharmony_ci DBG(1, " ADF: auto pre-feed\n"); 430141cc406Sopenharmony_ci } 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci if (strncmp("ASCN", value, len) == 0) { 433141cc406Sopenharmony_ci DBG(1, " ADF: auto scan\n"); 434141cc406Sopenharmony_ci } 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci if (strncmp("RCVR", value, len) == 0) { 437141cc406Sopenharmony_ci DBG(1, " ADF: auto recovery\n"); 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci } 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci if (len == 20) { 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci /* ADFAREAi0000850i0001400 */ 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci if (strncmp("AREA", value, 4) == 0) { 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci int min = decode_value(value + 4, 8); 448141cc406Sopenharmony_ci int max = decode_value(value + 4 + 8, 8); 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max); 451141cc406Sopenharmony_ci eds_set_adf_area(s->hw, min, max, 100); 452141cc406Sopenharmony_ci } 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci if (strncmp("AMIN", value, 4) == 0) { 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_ci int min = decode_value(value + 4, 8); 457141cc406Sopenharmony_ci int max = decode_value(value + 4 + 8, 8); 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci DBG(1, " ADF: min %dx%d @ 100dpi\n", min, max); 460141cc406Sopenharmony_ci } 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci if (strncmp("AMAX", value, 4) == 0) { 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci int min = decode_value(value + 4, 8); 465141cc406Sopenharmony_ci int max = decode_value(value + 4 + 8, 8); 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_ci DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max); 468141cc406Sopenharmony_ci } 469141cc406Sopenharmony_ci } 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci if (len == 16) { 477141cc406Sopenharmony_ci 478141cc406Sopenharmony_ci if (strncmp("AREA", value, 4) == 0) { 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci int min = decode_value(value + 4, 4); 481141cc406Sopenharmony_ci int max = decode_value(value + 4 + 4, 8); 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ci DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max); 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci eds_set_adf_area(s->hw, min, max, 100); 486141cc406Sopenharmony_ci } 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_ci if (strncmp("AMAX", value, 4) == 0) { 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci // d 491141cc406Sopenharmony_ci int min = decode_value(value + 4, 4); 492141cc406Sopenharmony_ci // i 493141cc406Sopenharmony_ci int max = decode_value(value + 4 + 4, 8); 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max); 496141cc406Sopenharmony_ci } 497141cc406Sopenharmony_ci } 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ci if (len == 12) { 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci /* RESOi0000600 */ 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci if (strncmp("RESO", value, 4) == 0) { 507141cc406Sopenharmony_ci 508141cc406Sopenharmony_ci int res = decode_value(value + 4, 8); 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci DBG(1, " ADF: basic resolution is %d dpi\n", res); 511141cc406Sopenharmony_ci } 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci /* OVSNd025d035 */ 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci if (strncmp("OVSN", value, 4) == 0) { 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci int x = decode_value(value + 4, 4); 518141cc406Sopenharmony_ci int y = decode_value(value + 4 + 4, 4); 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ci DBG(1, " ADF: overscan %dx%d @ 100dpi\n", x, y); 521141cc406Sopenharmony_ci } 522141cc406Sopenharmony_ci } 523141cc406Sopenharmony_ci } 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci if (strncmp("FB ", token, 3) == 0) { 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci s->hw->has_fb = 1; 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci if (len == 20) { 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci /* AREAi0000850i0001400 */ 532141cc406Sopenharmony_ci if (strncmp("AREA", value, 4) == 0) { 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci int min = decode_value(value + 4, 8); 535141cc406Sopenharmony_ci int max = decode_value(value + 4 + 8, 8); 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci DBG(1, " FB: area %dx%d @ 100dpi\n", min, max); 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_ci eds_set_fbf_area(s->hw, min, max, 100); 540141cc406Sopenharmony_ci } 541141cc406Sopenharmony_ci } 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci if (len == 16) { 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci /* AREAi0000850i0001400 */ 547141cc406Sopenharmony_ci if (strncmp("AREA", value, 4) == 0) { 548141cc406Sopenharmony_ci //d 549141cc406Sopenharmony_ci int min = decode_value(value + 4, 4); 550141cc406Sopenharmony_ci //i 551141cc406Sopenharmony_ci int max = decode_value(value + 4 + 4, 8); 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci DBG(1, " FB: area %dx%d @ 100dpi\n", min, max); 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci eds_set_fbf_area(s->hw, min, max, 100); 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci } 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci if (len == 8) { 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci if (strncmp("ALGNLEFT", value, len) == 0) { 562141cc406Sopenharmony_ci DBG(1, " FB: left aligned\n"); 563141cc406Sopenharmony_ci s->hw->fbf_alignment = 0; 564141cc406Sopenharmony_ci } 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci if (strncmp("ALGNCNTR", value, len) == 0) { 567141cc406Sopenharmony_ci DBG(1, " FB: center aligned\n"); 568141cc406Sopenharmony_ci s->hw->fbf_alignment = 1; 569141cc406Sopenharmony_ci } 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci if (strncmp("ALGNRIGT", value, len) == 0) { 572141cc406Sopenharmony_ci DBG(1, " FB: right aligned (not supported!)\n"); 573141cc406Sopenharmony_ci s->hw->fbf_alignment = 2; 574141cc406Sopenharmony_ci } 575141cc406Sopenharmony_ci } 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci if (len == 12) { 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci /* RESOi0000600 */ 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci if (strncmp("RESO", value, 4) == 0) { 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci int res = decode_value(value + 4, 8); 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci DBG(1, " FB: basic resolution is %d dpi\n", res); 586141cc406Sopenharmony_ci } 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci /* OVSNd025d035 */ 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci if (strncmp("OVSN", value, 4) == 0) { 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci int x = decode_value(value + 4, 4); 593141cc406Sopenharmony_ci int y = decode_value(value + 4 + 4, 4); 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_ci DBG(1, " FB: overscan %dx%d @ 100dpi\n", x, y); 596141cc406Sopenharmony_ci } 597141cc406Sopenharmony_ci } 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci if (len == 4) { 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci if (strncmp("DETX", value, len) == 0) { 602141cc406Sopenharmony_ci DBG(1, " FB: paper width detection\n"); 603141cc406Sopenharmony_ci } 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci if (strncmp("DETY", value, len) == 0) { 606141cc406Sopenharmony_ci DBG(1, " FB: paper height detection\n"); 607141cc406Sopenharmony_ci } 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 612141cc406Sopenharmony_ci} 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ciSANE_Status esci2_info(epsonds_scanner *s) 615141cc406Sopenharmony_ci{ 616141cc406Sopenharmony_ci SANE_Status status; 617141cc406Sopenharmony_ci int i = 4; 618141cc406Sopenharmony_ci 619141cc406Sopenharmony_ci DBG(1, "= gathering device information\n"); 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci do { 622141cc406Sopenharmony_ci status = esci2_cmd_simple(s, "INFOx0000000", &info_cb); 623141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY) { 624141cc406Sopenharmony_ci sleep(2); 625141cc406Sopenharmony_ci } 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci i--; 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci } while (status == SANE_STATUS_DEVICE_BUSY && i); 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci return status; 632141cc406Sopenharmony_ci} 633141cc406Sopenharmony_ci 634141cc406Sopenharmony_ci/* CAPA */ 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_cistatic SANE_Status capa_cb(void *userdata, char *token, int len) 637141cc406Sopenharmony_ci{ 638141cc406Sopenharmony_ci epsonds_scanner *s = (epsonds_scanner *)userdata; 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci char *value = token + 3; 641141cc406Sopenharmony_ci 642141cc406Sopenharmony_ci if (DBG_LEVEL >= 11) { 643141cc406Sopenharmony_ci debug_token(DBG_LEVEL, __func__, token, len); 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci if (len == 4) { 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci if (strncmp("ADFDPLX", token, 3 + 4) == 0) { 649141cc406Sopenharmony_ci DBG(1, " ADF: duplex\n"); 650141cc406Sopenharmony_ci s->hw->adf_is_duplex = 1; 651141cc406Sopenharmony_ci } 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci if (strncmp("ADFSKEW", token, 3 + 4) == 0) { 654141cc406Sopenharmony_ci DBG(1, " ADF: skew correction\n"); 655141cc406Sopenharmony_ci s->hw->adf_has_skew = 1; 656141cc406Sopenharmony_ci } 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_ci if (strncmp("ADFOVSN", token, 3 + 4) == 0) { 659141cc406Sopenharmony_ci DBG(1, " ADF: overscan\n"); 660141cc406Sopenharmony_ci } 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci if (strncmp("ADFPEDT", token, 3 + 4) == 0) { 663141cc406Sopenharmony_ci DBG(1, " ADF: paper end detection\n"); 664141cc406Sopenharmony_ci } 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci if (strncmp("ADFLOAD", token, 3 + 4) == 0) { 667141cc406Sopenharmony_ci DBG(1, " ADF: paper load\n"); 668141cc406Sopenharmony_ci s->hw->adf_has_load = 1; 669141cc406Sopenharmony_ci } 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci if (strncmp("ADFEJCT", token, 3 + 4) == 0) { 672141cc406Sopenharmony_ci DBG(1, " ADF: paper eject\n"); 673141cc406Sopenharmony_ci s->hw->adf_has_eject = 1; 674141cc406Sopenharmony_ci } 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ci if (strncmp("ADFCRP ", token, 3 + 4) == 0) { 677141cc406Sopenharmony_ci DBG(1, " ADF: image cropping\n"); 678141cc406Sopenharmony_ci s->hw->adf_has_crp = 1; 679141cc406Sopenharmony_ci } 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_ci if (strncmp("ADFFAST", token, 3 + 4) == 0) { 682141cc406Sopenharmony_ci DBG(1, " ADF: fast mode available\n"); 683141cc406Sopenharmony_ci } 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci if (strncmp("ADFDFL1", token, 3 + 4) == 0) { 686141cc406Sopenharmony_ci DBG(1, " ADF: double feed detection\n"); 687141cc406Sopenharmony_ci s->hw->adf_has_dfd = 1; 688141cc406Sopenharmony_ci } 689141cc406Sopenharmony_ci } 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ci if (len == 8 && strncmp("ADFDFL1DFL2", token, 3 + 4) == 0) { 692141cc406Sopenharmony_ci DBG(1, " ADF: double feed detection (high sensitivity)\n"); 693141cc406Sopenharmony_ci s->hw->adf_has_dfd = 2; 694141cc406Sopenharmony_ci } 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci if (strncmp("FMT", token, 3) == 0) { 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* a bit ugly... */ 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci if (len >= 8) { 701141cc406Sopenharmony_ci if (strncmp("RAW ", value + 4, 4) == 0) { 702141cc406Sopenharmony_ci s->hw->has_raw = 1; 703141cc406Sopenharmony_ci } 704141cc406Sopenharmony_ci } 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci if (len >= 12) { 707141cc406Sopenharmony_ci if (strncmp("RAW ", value + 8, 4) == 0) { 708141cc406Sopenharmony_ci s->hw->has_raw = 1; 709141cc406Sopenharmony_ci } 710141cc406Sopenharmony_ci } 711141cc406Sopenharmony_ci } 712141cc406Sopenharmony_ci 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci if (strncmp("COLLIST", token, 3 + 4) == 0) 715141cc406Sopenharmony_ci { 716141cc406Sopenharmony_ci char *p = token + 3 + 4; 717141cc406Sopenharmony_ci int count = (len - 4); 718141cc406Sopenharmony_ci int readBytes = 0; 719141cc406Sopenharmony_ci s->hw->has_mono = 0; 720141cc406Sopenharmony_ci while (readBytes < count) { 721141cc406Sopenharmony_ci if (strncmp(p, "M001", 4) == 0) 722141cc406Sopenharmony_ci { 723141cc406Sopenharmony_ci s->hw->has_mono = 1; 724141cc406Sopenharmony_ci } 725141cc406Sopenharmony_ci readBytes+=4; 726141cc406Sopenharmony_ci p+=4; 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci } 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci /* RSMRANGi0000050i0000600 */ 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci if (strncmp("RSMRANG", token, 3 + 4) == 0) { 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci char *p = token + 3 + 4; 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci if (p[0] == 'i') { 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci int min = decode_value(p, 8); 739141cc406Sopenharmony_ci int max = decode_value(p + 8, 8); 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci eds_set_resolution_range(s->hw, min, max); 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci DBG(1, "resolution min/max %d/%d\n", min, max); 744141cc406Sopenharmony_ci } 745141cc406Sopenharmony_ci } 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci /* RSMLISTi0000300i0000600 */ 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci if (strncmp("RSMLIST", token, 3 + 4) == 0) { 750141cc406Sopenharmony_ci 751141cc406Sopenharmony_ci char *p = token + 3 + 4; 752141cc406Sopenharmony_ci 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci int count = (len - 4); 755141cc406Sopenharmony_ci int readBytes = 0; 756141cc406Sopenharmony_ci 757141cc406Sopenharmony_ci while (readBytes < count) { 758141cc406Sopenharmony_ci if(*p == 'i') 759141cc406Sopenharmony_ci { 760141cc406Sopenharmony_ci eds_add_resolution(s->hw, decode_value(p, 8)); 761141cc406Sopenharmony_ci p += 8; 762141cc406Sopenharmony_ci readBytes += 8; 763141cc406Sopenharmony_ci }else if(*p == 'd') 764141cc406Sopenharmony_ci { 765141cc406Sopenharmony_ci eds_add_resolution(s->hw, decode_value(p, 4)); 766141cc406Sopenharmony_ci p += 4; 767141cc406Sopenharmony_ci readBytes +=4; 768141cc406Sopenharmony_ci } 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci } 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 774141cc406Sopenharmony_ci} 775141cc406Sopenharmony_ci 776141cc406Sopenharmony_ciSANE_Status esci2_capa(epsonds_scanner *s) 777141cc406Sopenharmony_ci{ 778141cc406Sopenharmony_ci return esci2_cmd_simple(s, "CAPAx0000000", &capa_cb); 779141cc406Sopenharmony_ci} 780141cc406Sopenharmony_ci 781141cc406Sopenharmony_ci/* STAT */ 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_cistatic SANE_Status stat_cb(void *userdata, char *token, int len) 784141cc406Sopenharmony_ci{ 785141cc406Sopenharmony_ci char *value = token + 3; 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci (void) userdata; 788141cc406Sopenharmony_ci 789141cc406Sopenharmony_ci if (DBG_LEVEL >= 11) { 790141cc406Sopenharmony_ci debug_token(DBG_LEVEL, __func__, token, len); 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci if (strncmp("ERR", token, 3) == 0) { 794141cc406Sopenharmony_ci if (strncmp("ADF PE ", value, len) == 0) { 795141cc406Sopenharmony_ci DBG(1, " PE : paper empty\n"); 796141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 797141cc406Sopenharmony_ci } 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci if (strncmp("ADF OPN", value, len) == 0) { 800141cc406Sopenharmony_ci DBG(1, " conver open\n"); 801141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 802141cc406Sopenharmony_ci } 803141cc406Sopenharmony_ci } 804141cc406Sopenharmony_ci 805141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 806141cc406Sopenharmony_ci} 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ciSANE_Status esci2_stat(epsonds_scanner *s) 809141cc406Sopenharmony_ci{ 810141cc406Sopenharmony_ci return esci2_cmd_simple(s, "STATx0000000", &stat_cb); 811141cc406Sopenharmony_ci} 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci/* RESA */ 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_cistatic SANE_Status resa_cb(void *userdata, char *token, int len) 816141cc406Sopenharmony_ci{ 817141cc406Sopenharmony_ci /* epsonds_scanner *s = (epsonds_scanner *)userdata; */ 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci (void) userdata; 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci if (DBG_LEVEL >= 11) { 822141cc406Sopenharmony_ci debug_token(DBG_LEVEL, __func__, token, len); 823141cc406Sopenharmony_ci } 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 826141cc406Sopenharmony_ci} 827141cc406Sopenharmony_ci 828141cc406Sopenharmony_ciSANE_Status esci2_resa(epsonds_scanner *s) 829141cc406Sopenharmony_ci{ 830141cc406Sopenharmony_ci return esci2_cmd_simple(s, "RESAx0000000", &resa_cb); 831141cc406Sopenharmony_ci} 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci/* PARA */ 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_cistatic SANE_Status para_cb(void *userdata, char *token, int len) 836141cc406Sopenharmony_ci{ 837141cc406Sopenharmony_ci if (DBG_LEVEL >= 11) { 838141cc406Sopenharmony_ci debug_token(DBG_LEVEL, __func__, token, len); 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci (void) userdata; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci if (strncmp("par", token, 3) == 0) { 844141cc406Sopenharmony_ci if (strncmp("FAIL", token + 3, 4) == 0) { 845141cc406Sopenharmony_ci DBG(1, "%s: parameter setting failed\n", __func__); 846141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 847141cc406Sopenharmony_ci } 848141cc406Sopenharmony_ci } 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 851141cc406Sopenharmony_ci} 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ciSANE_Status esci2_para(epsonds_scanner *s, char *parameters, int len) 854141cc406Sopenharmony_ci{ 855141cc406Sopenharmony_ci DBG(8, "%s: %s\n", __func__, parameters); 856141cc406Sopenharmony_ci return esci2_cmd(s, "PARAx0000000", 12, parameters, len, NULL, ¶_cb); 857141cc406Sopenharmony_ci} 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ciSANE_Status esci2_mech(epsonds_scanner *s, char *parameters) 860141cc406Sopenharmony_ci{ 861141cc406Sopenharmony_ci DBG(8, "%s: %s\n", __func__, parameters); 862141cc406Sopenharmony_ci return esci2_cmd(s, "MECHx0000000", 12, parameters, strlen(parameters), NULL, ¶_cb); 863141cc406Sopenharmony_ci} 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ciSANE_Status esci2_trdt(epsonds_scanner *s) 866141cc406Sopenharmony_ci{ 867141cc406Sopenharmony_ci return esci2_cmd_simple(s, "TRDTx0000000", NULL); 868141cc406Sopenharmony_ci} 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_cistatic SANE_Status img_cb(void *userdata, char *token, int len) 872141cc406Sopenharmony_ci{ 873141cc406Sopenharmony_ci struct epsonds_scanner *s = userdata; 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci if (DBG_LEVEL >= 11) { 876141cc406Sopenharmony_ci debug_token(DBG_LEVEL, __func__, token, len); 877141cc406Sopenharmony_ci } 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci /* psti0000256i0000000i0000945 / 24 */ 880141cc406Sopenharmony_ci 881141cc406Sopenharmony_ci /* integer comparison first so it's faster */ 882141cc406Sopenharmony_ci if (len == 24 && strncmp("pst", token, 3) == 0) { 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_ci s->dummy = decode_value(token + 3 + 8, 8); 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_ci DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n", 887141cc406Sopenharmony_ci __func__, 888141cc406Sopenharmony_ci decode_value(token + 3, 8), 889141cc406Sopenharmony_ci decode_value(token + 3 + 8 + 8, 8), 890141cc406Sopenharmony_ci s->dummy); 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 893141cc406Sopenharmony_ci } 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci if (len == 12 && strncmp("pst", token, 3) == 0) { 896141cc406Sopenharmony_ci 897141cc406Sopenharmony_ci s->dummy = decode_value(token + 3 + 4, 4); 898141cc406Sopenharmony_ci 899141cc406Sopenharmony_ci DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n", 900141cc406Sopenharmony_ci __func__, 901141cc406Sopenharmony_ci decode_value(token + 3, 4), 902141cc406Sopenharmony_ci decode_value(token + 3 + 4 + 4, 4), 903141cc406Sopenharmony_ci s->dummy); 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 906141cc406Sopenharmony_ci } 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci if (len == 16 && strncmp("pst", token, 3) == 0) { 909141cc406Sopenharmony_ci 910141cc406Sopenharmony_ci s->dummy = decode_value(token + 3 + 4, 4); 911141cc406Sopenharmony_ci 912141cc406Sopenharmony_ci DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n", 913141cc406Sopenharmony_ci __func__, 914141cc406Sopenharmony_ci decode_value(token + 3, 4), 915141cc406Sopenharmony_ci decode_value(token + 3 + 4 + 4, 8), 916141cc406Sopenharmony_ci s->dummy); 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci if (len == 20 && strncmp("pst", token, 3) == 0) { 922141cc406Sopenharmony_ci 923141cc406Sopenharmony_ci s->dummy = decode_value(token + 3 + 8, 4); 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n", 926141cc406Sopenharmony_ci __func__, 927141cc406Sopenharmony_ci decode_value(token + 3, 8), 928141cc406Sopenharmony_ci decode_value(token + 3 + 8 + 4, 8), 929141cc406Sopenharmony_ci s->dummy); 930141cc406Sopenharmony_ci 931141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 932141cc406Sopenharmony_ci } 933141cc406Sopenharmony_ci 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci // i0001696i0002347 936141cc406Sopenharmony_ci if (len == 16 && strncmp("pen", token, 3) == 0) { 937141cc406Sopenharmony_ci DBG(10, "%s: page end\n", __func__); 938141cc406Sopenharmony_ci s->eof = 1; 939141cc406Sopenharmony_ci if (s->isflatbedScan) 940141cc406Sopenharmony_ci { 941141cc406Sopenharmony_ci s->scanning = 0; 942141cc406Sopenharmony_ci } 943141cc406Sopenharmony_ci DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n", 944141cc406Sopenharmony_ci __func__, 945141cc406Sopenharmony_ci decode_value(token + 3, 8), 946141cc406Sopenharmony_ci decode_value(token + 3 + 8, 8), 947141cc406Sopenharmony_ci s->dummy); 948141cc406Sopenharmony_ci s->width_temp = decode_value(token + 3, 8); 949141cc406Sopenharmony_ci s->height_temp = decode_value(token + 3 + 8, 8); 950141cc406Sopenharmony_ci return SANE_STATUS_EOF; 951141cc406Sopenharmony_ci } 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci // d696i0002347 954141cc406Sopenharmony_ci if (len == 12 && strncmp("pen", token, 3) == 0) { 955141cc406Sopenharmony_ci DBG(10, "%s: page end\n", __func__); 956141cc406Sopenharmony_ci s->eof = 1; 957141cc406Sopenharmony_ci if (s->isflatbedScan) 958141cc406Sopenharmony_ci { 959141cc406Sopenharmony_ci s->scanning = 0; 960141cc406Sopenharmony_ci } 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n", 963141cc406Sopenharmony_ci __func__, 964141cc406Sopenharmony_ci decode_value(token + 3, 4), 965141cc406Sopenharmony_ci decode_value(token + 3 + 4, 8), 966141cc406Sopenharmony_ci s->dummy); 967141cc406Sopenharmony_ci 968141cc406Sopenharmony_ci s->width_temp = decode_value(token + 3, 4); 969141cc406Sopenharmony_ci s->height_temp = decode_value(token + 3 + 4, 8); 970141cc406Sopenharmony_ci return SANE_STATUS_EOF; 971141cc406Sopenharmony_ci } 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci // d696d2347 974141cc406Sopenharmony_ci if (len == 8 && strncmp("pen", token, 3) == 0) { 975141cc406Sopenharmony_ci DBG(10, "%s: page end\n", __func__); 976141cc406Sopenharmony_ci s->eof = 1; 977141cc406Sopenharmony_ci if (s->isflatbedScan) 978141cc406Sopenharmony_ci { 979141cc406Sopenharmony_ci s->scanning = 0; 980141cc406Sopenharmony_ci } 981141cc406Sopenharmony_ci DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n", 982141cc406Sopenharmony_ci __func__, 983141cc406Sopenharmony_ci decode_value(token + 3, 4), 984141cc406Sopenharmony_ci decode_value(token + 3 + 4, 4), 985141cc406Sopenharmony_ci s->dummy); 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci s->width_temp = decode_value(token + 3, 4); 988141cc406Sopenharmony_ci s->height_temp = decode_value(token + 3 + 4, 4); 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci return SANE_STATUS_EOF; 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci 994141cc406Sopenharmony_ci /* typIMGA or typIMGB */ 995141cc406Sopenharmony_ci if (len == 4 && strncmp("typ", token, 3) == 0) { 996141cc406Sopenharmony_ci 997141cc406Sopenharmony_ci if (token[6] == 'B') 998141cc406Sopenharmony_ci s->backside = 1; 999141cc406Sopenharmony_ci else 1000141cc406Sopenharmony_ci s->backside = 0; 1001141cc406Sopenharmony_ci 1002141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci if (strncmp("err", token, 3) == 0) { 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci char *option = token + 3; /* ADF, TPU, FB */ 1008141cc406Sopenharmony_ci char *cause = token + 3 + 4; /* OPN, PJ, PE, ERR, LTF, LOCK, DFED, DTCL, AUT, PERM */ 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci s->scanning = 0; 1011141cc406Sopenharmony_ci s->scanEnd = 1; 1012141cc406Sopenharmony_ci 1013141cc406Sopenharmony_ci DBG(1, "%s: error on option %3.3s, cause %4.4s\n", 1014141cc406Sopenharmony_ci __func__, option, cause); 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci if (cause[0] == 'P' && cause[1] == 'J') 1017141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 1018141cc406Sopenharmony_ci 1019141cc406Sopenharmony_ci if (cause[0] == 'P' && cause[1] == 'E') 1020141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci if (cause[0] == 'O' && cause[1] == 'P' && cause[2] == 'N') 1023141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 1024141cc406Sopenharmony_ci 1025141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1026141cc406Sopenharmony_ci } 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci if (len == 4 && strncmp("atnCAN ", token, 3 + 4) == 0) { 1029141cc406Sopenharmony_ci DBG(1, "%s: cancel request\n", __func__); 1030141cc406Sopenharmony_ci s->canceling = 1; 1031141cc406Sopenharmony_ci s->scanning = 0; 1032141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1033141cc406Sopenharmony_ci } 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci if (len == 4 && strncmp("lftd000", token, 3 + 4) == 0) { 1036141cc406Sopenharmony_ci DBG(1, "%s:lft ok\n", __func__); 1037141cc406Sopenharmony_ci s->scanEnd = 1; 1038141cc406Sopenharmony_ci s->scanning = 0; 1039141cc406Sopenharmony_ci } 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1042141cc406Sopenharmony_ci} 1043141cc406Sopenharmony_ci 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ciSANE_Status 1046141cc406Sopenharmony_ciesci2_img(struct epsonds_scanner *s, SANE_Int *length) 1047141cc406Sopenharmony_ci{ 1048141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1049141cc406Sopenharmony_ci SANE_Status parse_status; 1050141cc406Sopenharmony_ci unsigned int more; 1051141cc406Sopenharmony_ci ssize_t read; 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci DBG(15, "esci2_img start\n"); 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci *length = 0; 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci if (s->canceling) 1058141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci /* request image data */ 1061141cc406Sopenharmony_ci eds_send(s, "IMG x0000000", 12, &status, 64); 1062141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1063141cc406Sopenharmony_ci return status; 1064141cc406Sopenharmony_ci } 1065141cc406Sopenharmony_ci DBG(15, "request img OK\n"); 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci /* receive DataHeaderBlock */ 1068141cc406Sopenharmony_ci memset(s->buf, 0x00, 64); 1069141cc406Sopenharmony_ci eds_recv(s, s->buf, 64, &status); 1070141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1071141cc406Sopenharmony_ci return status; 1072141cc406Sopenharmony_ci } 1073141cc406Sopenharmony_ci DBG(15, "receive img OK\n"); 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci /* check if we need to read any image data */ 1076141cc406Sopenharmony_ci more = 0; 1077141cc406Sopenharmony_ci if (!esci2_check_header("IMG ", (char *)s->buf, &more)) { 1078141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1079141cc406Sopenharmony_ci } 1080141cc406Sopenharmony_ci 1081141cc406Sopenharmony_ci /* this handles eof and errors */ 1082141cc406Sopenharmony_ci parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb); 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_ci if (s->backside) 1085141cc406Sopenharmony_ci { 1086141cc406Sopenharmony_ci s->width_back = s->width_temp; 1087141cc406Sopenharmony_ci s->height_back = s->height_temp; 1088141cc406Sopenharmony_ci }else{ 1089141cc406Sopenharmony_ci s->width_front = s->width_temp; 1090141cc406Sopenharmony_ci s->height_front = s->height_temp; 1091141cc406Sopenharmony_ci 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci /* no more data? return using the status of the esci2_parse_block 1096141cc406Sopenharmony_ci * call, which might hold other error conditions. 1097141cc406Sopenharmony_ci */ 1098141cc406Sopenharmony_ci if (!more) { 1099141cc406Sopenharmony_ci return parse_status; 1100141cc406Sopenharmony_ci } 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_ci /* more data than was accounted for in s->buf */ 1103141cc406Sopenharmony_ci if (more > s->bsz) { 1104141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1105141cc406Sopenharmony_ci } 1106141cc406Sopenharmony_ci /* ALWAYS read image data */ 1107141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSONDS_NET) { 1108141cc406Sopenharmony_ci epsonds_net_request_read(s, more); 1109141cc406Sopenharmony_ci } 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci read = eds_recv(s, s->buf, more, &status); 1112141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1113141cc406Sopenharmony_ci return status; 1114141cc406Sopenharmony_ci } 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci if (read != more) { 1117141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1118141cc406Sopenharmony_ci } 1119141cc406Sopenharmony_ci 1120141cc406Sopenharmony_ci /* handle esci2_parse_block errors */ 1121141cc406Sopenharmony_ci if (parse_status != SANE_STATUS_GOOD) { 1122141cc406Sopenharmony_ci return parse_status; 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci 1125141cc406Sopenharmony_ci DBG(15, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status); 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_ci *length = read; 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci if (s->canceling) { 1130141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1131141cc406Sopenharmony_ci } 1132141cc406Sopenharmony_ci 1133141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1134141cc406Sopenharmony_ci} 1135