1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci * ESC/I commands for Epson scanners 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Based on Kazuhiro Sasayama previous 5141cc406Sopenharmony_ci * Work on epson.[ch] file from the SANE package. 6141cc406Sopenharmony_ci * Please see those files for original copyrights. 7141cc406Sopenharmony_ci * 8141cc406Sopenharmony_ci * Copyright (C) 2006 Tower Technologies 9141cc406Sopenharmony_ci * Author: Alessandro Zummo <a.zummo@towertech.it> 10141cc406Sopenharmony_ci * 11141cc406Sopenharmony_ci * This file is part of the SANE package. 12141cc406Sopenharmony_ci * 13141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 14141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 15141cc406Sopenharmony_ci * published by the Free Software Foundation, version 2. 16141cc406Sopenharmony_ci */ 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci#include "sane/config.h" 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci#include <byteorder.h> 23141cc406Sopenharmony_ci#include <math.h> 24141cc406Sopenharmony_ci#include <sys/types.h> 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci#include "epson2.h" 27141cc406Sopenharmony_ci#include "epson2-io.h" 28141cc406Sopenharmony_ci#include "epson2-commands.h" 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci/* ESC H, set zoom */ 32141cc406Sopenharmony_ciSANE_Status 33141cc406Sopenharmony_ciesci_set_zoom(Epson_Scanner * s, unsigned char x, unsigned char y) 34141cc406Sopenharmony_ci{ 35141cc406Sopenharmony_ci SANE_Status status; 36141cc406Sopenharmony_ci unsigned char params[2]; 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci DBG(8, "%s: x = %d, y = %d\n", __func__, x, y); 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci if (!s->hw->cmd->set_zoom) { 41141cc406Sopenharmony_ci DBG(1, "%s: not supported\n", __func__); 42141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 43141cc406Sopenharmony_ci } 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci params[0] = ESC; 46141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_zoom; 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 49141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 50141cc406Sopenharmony_ci return status; 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci params[0] = x; 53141cc406Sopenharmony_ci params[1] = y; 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci return e2_cmd_simple(s, params, 2); 56141cc406Sopenharmony_ci} 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci/* ESC R */ 59141cc406Sopenharmony_ciSANE_Status 60141cc406Sopenharmony_ciesci_set_resolution(Epson_Scanner * s, int x, int y) 61141cc406Sopenharmony_ci{ 62141cc406Sopenharmony_ci SANE_Status status; 63141cc406Sopenharmony_ci unsigned char params[4]; 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci DBG(8, "%s: x = %d, y = %d\n", __func__, x, y); 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci if (!s->hw->cmd->set_resolution) { 68141cc406Sopenharmony_ci DBG(1, "%s: not supported\n", __func__); 69141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 70141cc406Sopenharmony_ci } 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci params[0] = ESC; 73141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_resolution; 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 76141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 77141cc406Sopenharmony_ci return status; 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci params[0] = x; 80141cc406Sopenharmony_ci params[1] = x >> 8; 81141cc406Sopenharmony_ci params[2] = y; 82141cc406Sopenharmony_ci params[3] = y >> 8; 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci return e2_cmd_simple(s, params, 4); 85141cc406Sopenharmony_ci} 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci/* 88141cc406Sopenharmony_ci * Sends the "set scan area" command to the scanner with the currently selected 89141cc406Sopenharmony_ci * scan area. This scan area must be already corrected for "color shuffling" if 90141cc406Sopenharmony_ci * necessary. 91141cc406Sopenharmony_ci */ 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ciSANE_Status 94141cc406Sopenharmony_ciesci_set_scan_area(Epson_Scanner * s, int x, int y, int width, int height) 95141cc406Sopenharmony_ci{ 96141cc406Sopenharmony_ci SANE_Status status; 97141cc406Sopenharmony_ci unsigned char params[8]; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci DBG(8, "%s: x = %d, y = %d, w = %d, h = %d\n", 100141cc406Sopenharmony_ci __func__, x, y, width, height); 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci if (!s->hw->cmd->set_scan_area) { 103141cc406Sopenharmony_ci DBG(1, "%s: not supported\n", __func__); 104141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 105141cc406Sopenharmony_ci } 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_ci /* verify the scan area */ 108141cc406Sopenharmony_ci if (x < 0 || y < 0 || width <= 0 || height <= 0) 109141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci params[0] = ESC; 112141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_scan_area; 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 115141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 116141cc406Sopenharmony_ci return status; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci params[0] = x; 119141cc406Sopenharmony_ci params[1] = x >> 8; 120141cc406Sopenharmony_ci params[2] = y; 121141cc406Sopenharmony_ci params[3] = y >> 8; 122141cc406Sopenharmony_ci params[4] = width; 123141cc406Sopenharmony_ci params[5] = width >> 8; 124141cc406Sopenharmony_ci params[6] = height; 125141cc406Sopenharmony_ci params[7] = height >> 8; 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci return e2_cmd_simple(s, params, 8); 128141cc406Sopenharmony_ci} 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_cistatic int 131141cc406Sopenharmony_ciget_roundup_index(double frac[], int n) 132141cc406Sopenharmony_ci{ 133141cc406Sopenharmony_ci int i, index = -1; 134141cc406Sopenharmony_ci double max_val = 0.0; 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci for (i = 0; i < n; i++) { 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci if (frac[i] < 0) 139141cc406Sopenharmony_ci continue; 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci if (max_val < frac[i]) { 142141cc406Sopenharmony_ci index = i; 143141cc406Sopenharmony_ci max_val = frac[i]; 144141cc406Sopenharmony_ci } 145141cc406Sopenharmony_ci } 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci return index; 148141cc406Sopenharmony_ci} 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_cistatic int 151141cc406Sopenharmony_ciget_rounddown_index(double frac[], int n) 152141cc406Sopenharmony_ci{ 153141cc406Sopenharmony_ci int i, index = -1; 154141cc406Sopenharmony_ci double min_val = 1.0; 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci for (i = 0; i < n; i++) { 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci if (frac[i] > 0) 159141cc406Sopenharmony_ci continue; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci if (min_val > frac[i]) { 162141cc406Sopenharmony_ci index = i; 163141cc406Sopenharmony_ci min_val = frac[i]; 164141cc406Sopenharmony_ci } 165141cc406Sopenharmony_ci } 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci return index; 168141cc406Sopenharmony_ci} 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_cistatic unsigned char 171141cc406Sopenharmony_ciint2cpt(int val) 172141cc406Sopenharmony_ci{ 173141cc406Sopenharmony_ci if (val >= 0) { 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci if (val > 127) 176141cc406Sopenharmony_ci val = 127; 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci return (unsigned char) val; 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci } else { 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci val = -val; 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci if (val > 127) 185141cc406Sopenharmony_ci val = 127; 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci return (unsigned char) (0x80 | val); 188141cc406Sopenharmony_ci } 189141cc406Sopenharmony_ci} 190141cc406Sopenharmony_ci 191141cc406Sopenharmony_cistatic void 192141cc406Sopenharmony_ciround_cct(double org_cct[], int rnd_cct[]) 193141cc406Sopenharmony_ci{ 194141cc406Sopenharmony_ci int loop = 0; 195141cc406Sopenharmony_ci int i, j, sum[3]; 196141cc406Sopenharmony_ci double mult_cct[9], frac[9]; 197141cc406Sopenharmony_ci 198141cc406Sopenharmony_ci for (i = 0; i < 9; i++) { 199141cc406Sopenharmony_ci mult_cct[i] = org_cct[i] * 32; 200141cc406Sopenharmony_ci rnd_cct[i] = (int) floor(mult_cct[i] + 0.5); 201141cc406Sopenharmony_ci } 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci do { 204141cc406Sopenharmony_ci for (i = 0; i < 3; i++) { 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci int k = i * 3; 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci if ((rnd_cct[k] == 11) && 209141cc406Sopenharmony_ci (rnd_cct[k] == rnd_cct[k + 1]) && 210141cc406Sopenharmony_ci (rnd_cct[k] == rnd_cct[k + 2])) { 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci rnd_cct[k + i]--; 213141cc406Sopenharmony_ci mult_cct[k + i] = rnd_cct[k + i]; 214141cc406Sopenharmony_ci } 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci for (i = 0; i < 3; i++) { 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci int k = i * 3; 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci for (sum[i] = j = 0; j < 3; j++) 222141cc406Sopenharmony_ci sum[i] += rnd_cct[k + j]; 223141cc406Sopenharmony_ci } 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci for (i = 0; i < 9; i++) 226141cc406Sopenharmony_ci frac[i] = mult_cct[i] - rnd_cct[i]; 227141cc406Sopenharmony_ci 228141cc406Sopenharmony_ci for (i = 0; i < 3; i++) { 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci int k = i * 3; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci if (sum[i] < 32) { 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci int index = get_roundup_index(&frac[k], 3); 235141cc406Sopenharmony_ci if (index != -1) { 236141cc406Sopenharmony_ci rnd_cct[k + index]++; 237141cc406Sopenharmony_ci mult_cct[k + index] = rnd_cct[k + index]; 238141cc406Sopenharmony_ci sum[i]++; 239141cc406Sopenharmony_ci } 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci } else if (sum[i] > 32) { 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci int index = get_rounddown_index(&frac[k], 3); 244141cc406Sopenharmony_ci if (index != -1) { 245141cc406Sopenharmony_ci rnd_cct[k + index]--; 246141cc406Sopenharmony_ci mult_cct[k + index] = rnd_cct[k + index]; 247141cc406Sopenharmony_ci sum[i]--; 248141cc406Sopenharmony_ci } 249141cc406Sopenharmony_ci } 250141cc406Sopenharmony_ci } 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_ci while ((++loop < 2) 254141cc406Sopenharmony_ci && ((sum[0] != 32) || (sum[1] != 32) || (sum[2] != 32))); 255141cc406Sopenharmony_ci} 256141cc406Sopenharmony_ci 257141cc406Sopenharmony_cistatic void 258141cc406Sopenharmony_ciprofile_to_colorcoeff(double *profile, unsigned char *color_coeff) 259141cc406Sopenharmony_ci{ 260141cc406Sopenharmony_ci int cc_idx[] = { 4, 1, 7, 3, 0, 6, 5, 2, 8 }; 261141cc406Sopenharmony_ci int i, color_table[9]; 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci round_cct(profile, color_table); 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ci for (i = 0; i < 9; i++) 266141cc406Sopenharmony_ci color_coeff[i] = int2cpt(color_table[cc_idx[i]]); 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci/* 271141cc406Sopenharmony_ci * Sends the "set color correction coefficients" command with the 272141cc406Sopenharmony_ci * currently selected parameters to the scanner. 273141cc406Sopenharmony_ci */ 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ciSANE_Status 276141cc406Sopenharmony_ciesci_set_color_correction_coefficients(Epson_Scanner * s, SANE_Word *table) 277141cc406Sopenharmony_ci{ 278141cc406Sopenharmony_ci SANE_Status status; 279141cc406Sopenharmony_ci unsigned char params[2]; 280141cc406Sopenharmony_ci unsigned char data[9]; 281141cc406Sopenharmony_ci double cct[9]; 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 284141cc406Sopenharmony_ci if (!s->hw->cmd->set_color_correction_coefficients) { 285141cc406Sopenharmony_ci DBG(1, "%s: not supported\n", __func__); 286141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 287141cc406Sopenharmony_ci } 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci params[0] = ESC; 290141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_color_correction_coefficients; 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 293141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 294141cc406Sopenharmony_ci return status; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci cct[0] = SANE_UNFIX(table[0]); 297141cc406Sopenharmony_ci cct[1] = SANE_UNFIX(table[1]); 298141cc406Sopenharmony_ci cct[2] = SANE_UNFIX(table[2]); 299141cc406Sopenharmony_ci cct[3] = SANE_UNFIX(table[3]); 300141cc406Sopenharmony_ci cct[4] = SANE_UNFIX(table[4]); 301141cc406Sopenharmony_ci cct[5] = SANE_UNFIX(table[5]); 302141cc406Sopenharmony_ci cct[6] = SANE_UNFIX(table[6]); 303141cc406Sopenharmony_ci cct[7] = SANE_UNFIX(table[7]); 304141cc406Sopenharmony_ci cct[8] = SANE_UNFIX(table[8]); 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci profile_to_colorcoeff(cct, data); 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci DBG(11, "%s: %d,%d,%d %d,%d,%d %d,%d,%d\n", __func__, 309141cc406Sopenharmony_ci data[0] , data[1], data[2], data[3], 310141cc406Sopenharmony_ci data[4], data[5], data[6], data[7], data[8]); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci return e2_cmd_simple(s, data, 9); 313141cc406Sopenharmony_ci} 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ciSANE_Status 316141cc406Sopenharmony_ciesci_set_gamma_table(Epson_Scanner * s) 317141cc406Sopenharmony_ci{ 318141cc406Sopenharmony_ci SANE_Status status; 319141cc406Sopenharmony_ci unsigned char params[2]; 320141cc406Sopenharmony_ci unsigned char gamma[257]; 321141cc406Sopenharmony_ci int n; 322141cc406Sopenharmony_ci int table; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci/* static const char gamma_cmds[] = { 'M', 'R', 'G', 'B' }; */ 325141cc406Sopenharmony_ci static const char gamma_cmds[] = { 'R', 'G', 'B' }; 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 328141cc406Sopenharmony_ci if (!s->hw->cmd->set_gamma_table) 329141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci params[0] = ESC; 332141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_gamma_table; 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_ci /* Print the gamma tables before sending them to the scanner */ 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci if (DBG_LEVEL >= 16) { 337141cc406Sopenharmony_ci int c, i, j; 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci for (c = 0; c < 3; c++) { 340141cc406Sopenharmony_ci for (i = 0; i < 256; i += 16) { 341141cc406Sopenharmony_ci char gammaValues[16 * 3 + 1], newValue[4]; 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci gammaValues[0] = '\0'; 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci for (j = 0; j < 16; j++) { 346141cc406Sopenharmony_ci sprintf(newValue, " %02x", 347141cc406Sopenharmony_ci s->gamma_table[c][i + j]); 348141cc406Sopenharmony_ci strcat(gammaValues, newValue); 349141cc406Sopenharmony_ci } 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci DBG(16, "gamma table[%d][%d] %s\n", c, i, 352141cc406Sopenharmony_ci gammaValues); 353141cc406Sopenharmony_ci } 354141cc406Sopenharmony_ci } 355141cc406Sopenharmony_ci } 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci for (table = 0; table < 3; table++) { 358141cc406Sopenharmony_ci gamma[0] = gamma_cmds[table]; 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_ci for (n = 0; n < 256; ++n) 361141cc406Sopenharmony_ci gamma[n + 1] = s->gamma_table[table][n]; 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 364141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 365141cc406Sopenharmony_ci return status; 366141cc406Sopenharmony_ci 367141cc406Sopenharmony_ci status = e2_cmd_simple(s, gamma, 257); 368141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 369141cc406Sopenharmony_ci return status; 370141cc406Sopenharmony_ci } 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci return status; 373141cc406Sopenharmony_ci} 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci/* ESC F - Request Status 376141cc406Sopenharmony_ci * -> ESC f 377141cc406Sopenharmony_ci * <- Information block 378141cc406Sopenharmony_ci */ 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ciSANE_Status 381141cc406Sopenharmony_ciesci_request_status(SANE_Handle handle, unsigned char *scanner_status) 382141cc406Sopenharmony_ci{ 383141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 384141cc406Sopenharmony_ci SANE_Status status; 385141cc406Sopenharmony_ci unsigned char params[2]; 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci if (s->hw->cmd->request_status == 0) 390141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_ci params[0] = ESC; 393141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_status; 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci e2_send(s, params, 2, 4, &status); 396141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 397141cc406Sopenharmony_ci return status; 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci status = e2_recv_info_block(s, params, 4, NULL); 400141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 401141cc406Sopenharmony_ci return status; 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci if (scanner_status) 404141cc406Sopenharmony_ci *scanner_status = params[0]; 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci DBG(1, "status: %02x\n", params[0]); 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci if (params[0] & STATUS_NOT_READY) 409141cc406Sopenharmony_ci DBG(1, " scanner in use on another interface\n"); 410141cc406Sopenharmony_ci else 411141cc406Sopenharmony_ci DBG(1, " ready\n"); 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci if (params[0] & STATUS_FER) 414141cc406Sopenharmony_ci DBG(1, " system error\n"); 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci if (params[0] & STATUS_OPTION) 417141cc406Sopenharmony_ci DBG(1, " option equipment is installed\n"); 418141cc406Sopenharmony_ci else 419141cc406Sopenharmony_ci DBG(1, " no option equipment installed\n"); 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci if (params[0] & STATUS_EXT_COMMANDS) 422141cc406Sopenharmony_ci DBG(1, " support extended commands\n"); 423141cc406Sopenharmony_ci else 424141cc406Sopenharmony_ci DBG(1, " does NOT support extended commands\n"); 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci if (params[0] & STATUS_RESERVED) 427141cc406Sopenharmony_ci DBG(0, 428141cc406Sopenharmony_ci " a reserved bit is set, please contact the author.\n"); 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci return status; 431141cc406Sopenharmony_ci} 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci/* extended commands */ 434141cc406Sopenharmony_ci 435141cc406Sopenharmony_ci/* FS I, Request Extended Identity 436141cc406Sopenharmony_ci * -> FS I 437141cc406Sopenharmony_ci * <- Extended identity data (80) 438141cc406Sopenharmony_ci * 439141cc406Sopenharmony_ci * Request the properties of the scanner. 440141cc406Sopenharmony_ci */ 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ciSANE_Status 443141cc406Sopenharmony_ciesci_request_extended_identity(SANE_Handle handle, unsigned char *buf) 444141cc406Sopenharmony_ci{ 445141cc406Sopenharmony_ci unsigned char model[17]; 446141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 447141cc406Sopenharmony_ci SANE_Status status; 448141cc406Sopenharmony_ci unsigned char params[2]; 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci if (buf == NULL) 453141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_identity == 0) 456141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci params[0] = FS; 459141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_extended_identity; 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci status = e2_txrx(s, params, 2, buf, 80); 462141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 463141cc406Sopenharmony_ci return status; 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci DBG(1, " command level : %c%c\n", buf[0], buf[1]); 466141cc406Sopenharmony_ci DBG(1, " basic resolution: %lu\n", (unsigned long) le32atoh(&buf[4])); 467141cc406Sopenharmony_ci DBG(1, " min resolution : %lu\n", (unsigned long) le32atoh(&buf[8])); 468141cc406Sopenharmony_ci DBG(1, " max resolution : %lu\n", (unsigned long) le32atoh(&buf[12])); 469141cc406Sopenharmony_ci DBG(1, " max pixel num : %lu\n", (unsigned long) le32atoh(&buf[16])); 470141cc406Sopenharmony_ci DBG(1, " scan area : %lux%lu\n", 471141cc406Sopenharmony_ci (unsigned long) le32atoh(&buf[20]), (unsigned long) le32atoh(&buf[24])); 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci DBG(1, " adf area : %lux%lu\n", 474141cc406Sopenharmony_ci (unsigned long) le32atoh(&buf[28]), (unsigned long) le32atoh(&buf[32])); 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci DBG(1, " tpu area : %lux%lu\n", 477141cc406Sopenharmony_ci (unsigned long) le32atoh(&buf[36]), (unsigned long) le32atoh(&buf[40])); 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_ci DBG(1, " capabilities (1): 0x%02x\n", buf[44]); 480141cc406Sopenharmony_ci DBG(1, " capabilities (2): 0x%02x\n", buf[45]); 481141cc406Sopenharmony_ci DBG(1, " input depth : %d\n", buf[66]); 482141cc406Sopenharmony_ci DBG(1, " max output depth: %d\n", buf[67]); 483141cc406Sopenharmony_ci DBG(1, " rom version : %c%c%c%c\n", 484141cc406Sopenharmony_ci buf[62], buf[63], buf[64], buf[65]); 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci memcpy(model, &buf[46], 16); 487141cc406Sopenharmony_ci model[16] = '\0'; 488141cc406Sopenharmony_ci DBG(1, " model name : %s\n", model); 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci DBG(1, "options:\n"); 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci if (le32atoh(&buf[28]) > 0) 493141cc406Sopenharmony_ci DBG(1, " ADF detected\n"); 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci if (le32atoh(&buf[36]) > 0) 496141cc406Sopenharmony_ci DBG(1, " TPU detected\n"); 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci if (buf[44]) 499141cc406Sopenharmony_ci DBG(1, "capabilities (1):\n"); 500141cc406Sopenharmony_ci 501141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_DLF) 502141cc406Sopenharmony_ci DBG(1, " main lamp change is supported\n"); 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_NOTFBF) 505141cc406Sopenharmony_ci DBG(1, " the device is NOT flatbed\n"); 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_ADFT) 508141cc406Sopenharmony_ci DBG(1, " page type ADF is installed\n"); 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_ADFS) 511141cc406Sopenharmony_ci DBG(1, " ADF is duplex capable\n"); 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_ADFO) 514141cc406Sopenharmony_ci DBG(1, " page type ADF loads from the first sheet\n"); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_LID) 517141cc406Sopenharmony_ci DBG(1, " lid type option is installed\n"); 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_TPIR) 520141cc406Sopenharmony_ci DBG(1, " infrared scanning is supported\n"); 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci if (buf[44] & EXT_IDTY_CAP1_PB) 523141cc406Sopenharmony_ci DBG(1, " push button is supported\n"); 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_ci if (buf[45]) 527141cc406Sopenharmony_ci DBG(1, "capabilities (2):\n"); 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci if (buf[45] & EXT_IDTY_CAP2_AFF) 530141cc406Sopenharmony_ci DBG(1, " ADF has auto form feed\n"); 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci if (buf[45] & EXT_IDTY_CAP2_DFD) 533141cc406Sopenharmony_ci DBG(1, " ADF has double feed detection\n"); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci if (buf[45] & EXT_IDTY_CAP2_ADFAS) 536141cc406Sopenharmony_ci DBG(1, " ADF has auto scan\n"); 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 539141cc406Sopenharmony_ci} 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci/* FS F, request scanner status */ 542141cc406Sopenharmony_ciSANE_Status 543141cc406Sopenharmony_ciesci_request_scanner_status(SANE_Handle handle, unsigned char *buf) 544141cc406Sopenharmony_ci{ 545141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 546141cc406Sopenharmony_ci SANE_Status status; 547141cc406Sopenharmony_ci unsigned char params[2]; 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 550141cc406Sopenharmony_ci 551141cc406Sopenharmony_ci if (!s->hw->extended_commands) 552141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci if (buf == NULL) 555141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci params[0] = FS; 558141cc406Sopenharmony_ci params[1] = 'F'; 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_ci status = e2_txrx(s, params, 2, buf, 16); 561141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 562141cc406Sopenharmony_ci return status; 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci DBG(1, "global status : 0x%02x\n", buf[0]); 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci if (buf[0] & FSF_STATUS_MAIN_FER) 567141cc406Sopenharmony_ci DBG(1, " system error\n"); 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci if (buf[0] & FSF_STATUS_MAIN_NR) 570141cc406Sopenharmony_ci DBG(1, " not ready\n"); 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci if (buf[0] & FSF_STATUS_MAIN_WU) 573141cc406Sopenharmony_ci DBG(1, " scanner is warming up\n"); 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci if (buf[0] & FSF_STATUS_MAIN_CWU) 576141cc406Sopenharmony_ci DBG(1, " warmup can be cancelled\n"); 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci DBG(1, "adf status : 0x%02x\n", buf[1]); 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_IST) 582141cc406Sopenharmony_ci DBG(11, " installed\n"); 583141cc406Sopenharmony_ci else 584141cc406Sopenharmony_ci DBG(11, " not installed\n"); 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_EN) 587141cc406Sopenharmony_ci DBG(11, " enabled\n"); 588141cc406Sopenharmony_ci else 589141cc406Sopenharmony_ci DBG(11, " not enabled\n"); 590141cc406Sopenharmony_ci 591141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_ERR) 592141cc406Sopenharmony_ci DBG(1, " error\n"); 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_PE) 595141cc406Sopenharmony_ci DBG(1, " paper empty\n"); 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_PJ) 598141cc406Sopenharmony_ci DBG(1, " paper jam\n"); 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_OPN) 601141cc406Sopenharmony_ci DBG(1, " cover open\n"); 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_ADF_PAG) 604141cc406Sopenharmony_ci DBG(1, " duplex capable\n"); 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci DBG(1, "tpu status : 0x%02x\n", buf[2]); 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci if (buf[2] & FSF_STATUS_TPU_IST) 610141cc406Sopenharmony_ci DBG(11, " installed\n"); 611141cc406Sopenharmony_ci else 612141cc406Sopenharmony_ci DBG(11, " not installed\n"); 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci if (buf[2] & FSF_STATUS_TPU_EN) 615141cc406Sopenharmony_ci DBG(11, " enabled\n"); 616141cc406Sopenharmony_ci else 617141cc406Sopenharmony_ci DBG(11, " not enabled\n"); 618141cc406Sopenharmony_ci 619141cc406Sopenharmony_ci if (buf[2] & FSF_STATUS_TPU_ERR) 620141cc406Sopenharmony_ci DBG(1, " error\n"); 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci if (buf[1] & FSF_STATUS_TPU_OPN) 623141cc406Sopenharmony_ci DBG(1, " cover open\n"); 624141cc406Sopenharmony_ci 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci DBG(1, "device type : 0x%02x\n", buf[3] & 0xC0); 627141cc406Sopenharmony_ci DBG(1, "main body status: 0x%02x\n", buf[3] & 0x3F); 628141cc406Sopenharmony_ci 629141cc406Sopenharmony_ci if (buf[3] & FSF_STATUS_MAIN2_PE) 630141cc406Sopenharmony_ci DBG(1, " paper empty\n"); 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_ci if (buf[3] & FSF_STATUS_MAIN2_PJ) 633141cc406Sopenharmony_ci DBG(1, " paper jam\n"); 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci if (buf[3] & FSF_STATUS_MAIN2_OPN) 636141cc406Sopenharmony_ci DBG(1, " cover open\n"); 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 639141cc406Sopenharmony_ci} 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_ciSANE_Status 642141cc406Sopenharmony_ciesci_set_scanning_parameter(SANE_Handle handle, unsigned char *buf) 643141cc406Sopenharmony_ci{ 644141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 645141cc406Sopenharmony_ci SANE_Status status; 646141cc406Sopenharmony_ci unsigned char params[2]; 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci if (buf == NULL) 651141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci params[0] = FS; 654141cc406Sopenharmony_ci params[1] = 'W'; 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci DBG(10, "resolution of main scan : %lu\n", (unsigned long) le32atoh(&buf[0])); 657141cc406Sopenharmony_ci DBG(10, "resolution of sub scan : %lu\n", (unsigned long) le32atoh(&buf[4])); 658141cc406Sopenharmony_ci DBG(10, "offset length of main scan : %lu\n", (unsigned long) le32atoh(&buf[8])); 659141cc406Sopenharmony_ci DBG(10, "offset length of sub scan : %lu\n", (unsigned long) le32atoh(&buf[12])); 660141cc406Sopenharmony_ci DBG(10, "scanning length of main scan: %lu\n", (unsigned long) le32atoh(&buf[16])); 661141cc406Sopenharmony_ci DBG(10, "scanning length of sub scan : %lu\n", (unsigned long) le32atoh(&buf[20])); 662141cc406Sopenharmony_ci DBG(10, "scanning color : %d\n", buf[24]); 663141cc406Sopenharmony_ci DBG(10, "data format : %d\n", buf[25]); 664141cc406Sopenharmony_ci DBG(10, "option control : %d\n", buf[26]); 665141cc406Sopenharmony_ci DBG(10, "scanning mode : %d\n", buf[27]); 666141cc406Sopenharmony_ci DBG(10, "block line number : %d\n", buf[28]); 667141cc406Sopenharmony_ci DBG(10, "gamma correction : %d\n", buf[29]); 668141cc406Sopenharmony_ci DBG(10, "brightness : %d\n", buf[30]); 669141cc406Sopenharmony_ci DBG(10, "color correction : %d\n", buf[31]); 670141cc406Sopenharmony_ci DBG(10, "halftone processing : %d\n", buf[32]); 671141cc406Sopenharmony_ci DBG(10, "threshold : %d\n", buf[33]); 672141cc406Sopenharmony_ci DBG(10, "auto area segmentation : %d\n", buf[34]); 673141cc406Sopenharmony_ci DBG(10, "sharpness control : %d\n", buf[35]); 674141cc406Sopenharmony_ci DBG(10, "mirroring : %d\n", buf[36]); 675141cc406Sopenharmony_ci DBG(10, "film type : %d\n", buf[37]); 676141cc406Sopenharmony_ci DBG(10, "main lamp lighting mode : %d\n", buf[38]); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 679141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 680141cc406Sopenharmony_ci return status; 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci status = e2_cmd_simple(s, buf, 64); 683141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 684141cc406Sopenharmony_ci DBG(1, "%s: invalid scanning parameters\n", __func__); 685141cc406Sopenharmony_ci return status; 686141cc406Sopenharmony_ci } 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 689141cc406Sopenharmony_ci} 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ci/* FS S */ 692141cc406Sopenharmony_ci 693141cc406Sopenharmony_ciSANE_Status 694141cc406Sopenharmony_ciesci_get_scanning_parameter(SANE_Handle handle, unsigned char *buf) 695141cc406Sopenharmony_ci{ 696141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 697141cc406Sopenharmony_ci SANE_Status status; 698141cc406Sopenharmony_ci unsigned char params[2]; 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci if (buf == NULL) 703141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci params[0] = FS; 706141cc406Sopenharmony_ci params[1] = 'S'; 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci status = e2_txrx(s, params, 2, buf, 64); 709141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 710141cc406Sopenharmony_ci return status; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci DBG(10, "resolution of main scan : %lu\n", 713141cc406Sopenharmony_ci (u_long) le32atoh(&buf[0])); 714141cc406Sopenharmony_ci DBG(10, "resolution of sub scan : %lu\n", 715141cc406Sopenharmony_ci (u_long) le32atoh(&buf[4])); 716141cc406Sopenharmony_ci DBG(10, "offset length of main scan : %lu\n", 717141cc406Sopenharmony_ci (u_long) le32atoh(&buf[8])); 718141cc406Sopenharmony_ci DBG(10, "offset length of sub scan : %lu\n", 719141cc406Sopenharmony_ci (u_long) le32atoh(&buf[12])); 720141cc406Sopenharmony_ci DBG(10, "scanning length of main scan: %lu\n", 721141cc406Sopenharmony_ci (u_long) le32atoh(&buf[16])); 722141cc406Sopenharmony_ci DBG(10, "scanning length of sub scan : %lu\n", 723141cc406Sopenharmony_ci (u_long) le32atoh(&buf[20])); 724141cc406Sopenharmony_ci DBG(10, "scanning color : %d\n", buf[24]); 725141cc406Sopenharmony_ci DBG(10, "data format : %d\n", buf[25]); 726141cc406Sopenharmony_ci DBG(10, "option control : %d\n", buf[26]); 727141cc406Sopenharmony_ci DBG(10, "scanning mode : %d\n", buf[27]); 728141cc406Sopenharmony_ci DBG(10, "block line number : %d\n", buf[28]); 729141cc406Sopenharmony_ci DBG(10, "gamma correction : %d\n", buf[29]); 730141cc406Sopenharmony_ci DBG(10, "brightness : %d\n", buf[30]); 731141cc406Sopenharmony_ci DBG(10, "color correction : %d\n", buf[31]); 732141cc406Sopenharmony_ci DBG(10, "halftone processing : %d\n", buf[32]); 733141cc406Sopenharmony_ci DBG(10, "threshold : %d\n", buf[33]); 734141cc406Sopenharmony_ci DBG(10, "auto area segmentation : %d\n", buf[34]); 735141cc406Sopenharmony_ci DBG(10, "sharpness control : %d\n", buf[35]); 736141cc406Sopenharmony_ci DBG(10, "mirroring : %d\n", buf[36]); 737141cc406Sopenharmony_ci DBG(10, "film type : %d\n", buf[37]); 738141cc406Sopenharmony_ci DBG(10, "main lamp lighting mode : %d\n", buf[38]); 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 741141cc406Sopenharmony_ci} 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci/* ESC # */ 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ciSANE_Status 746141cc406Sopenharmony_ciesci_enable_infrared(SANE_Handle handle) 747141cc406Sopenharmony_ci{ 748141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 749141cc406Sopenharmony_ci SANE_Status status; 750141cc406Sopenharmony_ci int i; 751141cc406Sopenharmony_ci unsigned char params[2]; 752141cc406Sopenharmony_ci unsigned char buf[64]; 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci unsigned char seq[32] = { 755141cc406Sopenharmony_ci 0xCA, 0xFB, 0x77, 0x71, 0x20, 0x16, 0xDA, 0x09, 756141cc406Sopenharmony_ci 0x5F, 0x57, 0x09, 0x12, 0x04, 0x83, 0x76, 0x77, 757141cc406Sopenharmony_ci 0x3C, 0x73, 0x9C, 0xBE, 0x7A, 0xE0, 0x52, 0xE2, 758141cc406Sopenharmony_ci 0x90, 0x0D, 0xFF, 0x9A, 0xEF, 0x4C, 0x2C, 0x81 759141cc406Sopenharmony_ci }; 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci status = esci_get_scanning_parameter(handle, buf); 764141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 765141cc406Sopenharmony_ci return status; 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci for (i = 0; i < 32; i++) { 768141cc406Sopenharmony_ci buf[i] = seq[i] ^ buf[i]; 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci params[0] = ESC; 772141cc406Sopenharmony_ci params[1] = '#'; 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 775141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 776141cc406Sopenharmony_ci return status; 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ci status = e2_cmd_simple(s, buf, 32); 779141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 780141cc406Sopenharmony_ci return status; 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 783141cc406Sopenharmony_ci} 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ciSANE_Status 786141cc406Sopenharmony_ciesci_request_command_parameter(SANE_Handle handle, unsigned char *buf) 787141cc406Sopenharmony_ci{ 788141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 789141cc406Sopenharmony_ci SANE_Status status; 790141cc406Sopenharmony_ci unsigned char params[2]; 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci if (s->hw->cmd->request_condition == 0) 795141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci params[0] = ESC; 798141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_condition; 799141cc406Sopenharmony_ci 800141cc406Sopenharmony_ci status = e2_cmd_info_block(s, params, 2, 45, &buf, NULL); 801141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 802141cc406Sopenharmony_ci return status; 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci DBG(1, "scanning parameters:\n"); 805141cc406Sopenharmony_ci DBG(1, "color : %d\n", buf[1]); 806141cc406Sopenharmony_ci DBG(1, "resolution : %dx%d\n", 807141cc406Sopenharmony_ci buf[4] << 8 | buf[3], buf[6] << 8 | buf[5]); 808141cc406Sopenharmony_ci DBG(1, "halftone : %d\n", buf[19]); 809141cc406Sopenharmony_ci DBG(1, "brightness : %d\n", buf[21]); 810141cc406Sopenharmony_ci DBG(1, "color correction : %d\n", buf[28]); 811141cc406Sopenharmony_ci DBG(1, "gamma : %d\n", buf[23]); 812141cc406Sopenharmony_ci DBG(1, "sharpness : %d\n", buf[30]); 813141cc406Sopenharmony_ci DBG(1, "threshold : %d\n", buf[38]); 814141cc406Sopenharmony_ci DBG(1, "data format : %d\n", buf[17]); 815141cc406Sopenharmony_ci DBG(1, "mirroring : %d\n", buf[34]); 816141cc406Sopenharmony_ci DBG(1, "option unit control : %d\n", buf[42]); 817141cc406Sopenharmony_ci DBG(1, "film type : %d\n", buf[44]); 818141cc406Sopenharmony_ci DBG(1, "auto area segmentation : %d\n", buf[36]); 819141cc406Sopenharmony_ci DBG(1, "line counter : %d\n", buf[40]); 820141cc406Sopenharmony_ci DBG(1, "scanning mode : %d\n", buf[32]); 821141cc406Sopenharmony_ci DBG(1, "zoom : %d,%d\n", buf[26], buf[25]); 822141cc406Sopenharmony_ci DBG(1, "scan area : %d,%d %d,%d\n", 823141cc406Sopenharmony_ci buf[9] << 8 | buf[8], buf[11] << 8 | buf[10], 824141cc406Sopenharmony_ci buf[13] << 8 | buf[12], buf[15] << 8 | buf[14]); 825141cc406Sopenharmony_ci return status; 826141cc406Sopenharmony_ci} 827141cc406Sopenharmony_ci 828141cc406Sopenharmony_ci/* ESC q - Request Focus Position 829141cc406Sopenharmony_ci * -> ESC q 830141cc406Sopenharmony_ci * <- Information block 831141cc406Sopenharmony_ci * <- Focus position status (2) 832141cc406Sopenharmony_ci * 0 - Error status 833141cc406Sopenharmony_ci * 1 - Focus position 834141cc406Sopenharmony_ci */ 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ciSANE_Status 837141cc406Sopenharmony_ciesci_request_focus_position(SANE_Handle handle, unsigned char *position) 838141cc406Sopenharmony_ci{ 839141cc406Sopenharmony_ci SANE_Status status; 840141cc406Sopenharmony_ci unsigned char *buf; 841141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci unsigned char params[2]; 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci if (s->hw->cmd->request_focus_position == 0) 848141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci params[0] = ESC; 851141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_focus_position; 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci status = e2_cmd_info_block(s, params, 2, 2, &buf, NULL); 854141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 855141cc406Sopenharmony_ci return status; 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci if (buf[0] & 0x01) 858141cc406Sopenharmony_ci DBG(1, "autofocus error\n"); 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci *position = buf[1]; 861141cc406Sopenharmony_ci DBG(8, " focus position = 0x%x\n", buf[1]); 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci free(buf); 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci return status; 866141cc406Sopenharmony_ci} 867141cc406Sopenharmony_ci 868141cc406Sopenharmony_ci/* ESC ! - Request Push Button Status 869141cc406Sopenharmony_ci * -> ESC ! 870141cc406Sopenharmony_ci * <- Information block 871141cc406Sopenharmony_ci * <- Push button status (1) 872141cc406Sopenharmony_ci */ 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ciSANE_Status 875141cc406Sopenharmony_ciesci_request_push_button_status(SANE_Handle handle, unsigned char *bstatus) 876141cc406Sopenharmony_ci{ 877141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 878141cc406Sopenharmony_ci SANE_Status status; 879141cc406Sopenharmony_ci unsigned char params[2]; 880141cc406Sopenharmony_ci unsigned char *buf; 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_ci if (s->hw->cmd->request_push_button_status == 0) { 885141cc406Sopenharmony_ci DBG(1, "push button status unsupported\n"); 886141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci 889141cc406Sopenharmony_ci params[0] = ESC; 890141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_push_button_status; 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci status = e2_cmd_info_block(s, params, 2, 1, &buf, NULL); 893141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 894141cc406Sopenharmony_ci return status; 895141cc406Sopenharmony_ci 896141cc406Sopenharmony_ci DBG(1, "push button status = %d\n", buf[0]); 897141cc406Sopenharmony_ci *bstatus = buf[0]; 898141cc406Sopenharmony_ci 899141cc406Sopenharmony_ci free(buf); 900141cc406Sopenharmony_ci 901141cc406Sopenharmony_ci return status; 902141cc406Sopenharmony_ci} 903141cc406Sopenharmony_ci 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci/* 906141cc406Sopenharmony_ci * Request Identity information from scanner and fill in information 907141cc406Sopenharmony_ci * into dev and/or scanner structures. 908141cc406Sopenharmony_ci * XXX information should be parsed separately. 909141cc406Sopenharmony_ci */ 910141cc406Sopenharmony_ciSANE_Status 911141cc406Sopenharmony_ciesci_request_identity(SANE_Handle handle, unsigned char **buf, size_t *len) 912141cc406Sopenharmony_ci{ 913141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 914141cc406Sopenharmony_ci unsigned char params[2]; 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci if (!s->hw->cmd->request_identity) 919141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci params[0] = ESC; 922141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_identity; 923141cc406Sopenharmony_ci 924141cc406Sopenharmony_ci return e2_cmd_info_block(s, params, 2, 0, buf, len); 925141cc406Sopenharmony_ci} 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci/* 929141cc406Sopenharmony_ci * Request information from scanner 930141cc406Sopenharmony_ci */ 931141cc406Sopenharmony_ciSANE_Status 932141cc406Sopenharmony_ciesci_request_identity2(SANE_Handle handle, unsigned char **buf) 933141cc406Sopenharmony_ci{ 934141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 935141cc406Sopenharmony_ci SANE_Status status; 936141cc406Sopenharmony_ci size_t len; 937141cc406Sopenharmony_ci unsigned char params[2]; 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci if (s->hw->cmd->request_identity2 == 0) 942141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci params[0] = ESC; 945141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_identity2; 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci status = e2_cmd_info_block(s, params, 2, 0, buf, &len); 948141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 949141cc406Sopenharmony_ci return status; 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci return status; 952141cc406Sopenharmony_ci} 953141cc406Sopenharmony_ci 954141cc406Sopenharmony_ci/* Send the "initialize scanner" command to the device and reset it */ 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ciSANE_Status 957141cc406Sopenharmony_ciesci_reset(Epson_Scanner * s) 958141cc406Sopenharmony_ci{ 959141cc406Sopenharmony_ci SANE_Status status; 960141cc406Sopenharmony_ci unsigned char params[2]; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci if (!s->hw->cmd->initialize_scanner) 965141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci params[0] = ESC; 968141cc406Sopenharmony_ci params[1] = s->hw->cmd->initialize_scanner; 969141cc406Sopenharmony_ci 970141cc406Sopenharmony_ci if (s->fd == -1) 971141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci status = e2_cmd_simple(s, params, 2); 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci return status; 976141cc406Sopenharmony_ci} 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ciSANE_Status 979141cc406Sopenharmony_ciesci_feed(Epson_Scanner * s) 980141cc406Sopenharmony_ci{ 981141cc406Sopenharmony_ci unsigned char params[1]; 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci if (!s->hw->cmd->feed) 986141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci params[0] = s->hw->cmd->feed; 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci return e2_cmd_simple(s, params, 1); 991141cc406Sopenharmony_ci} 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci 994141cc406Sopenharmony_ci/* 995141cc406Sopenharmony_ci * Eject the current page from the ADF. The scanner is opened prior to 996141cc406Sopenharmony_ci * sending the command and closed afterwards. 997141cc406Sopenharmony_ci */ 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ciSANE_Status 1000141cc406Sopenharmony_ciesci_eject(Epson_Scanner * s) 1001141cc406Sopenharmony_ci{ 1002141cc406Sopenharmony_ci unsigned char params[1]; 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 1005141cc406Sopenharmony_ci 1006141cc406Sopenharmony_ci if (!s->hw->cmd->eject) 1007141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1008141cc406Sopenharmony_ci 1009141cc406Sopenharmony_ci if (s->fd == -1) 1010141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci params[0] = s->hw->cmd->eject; 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci return e2_cmd_simple(s, params, 1); 1015141cc406Sopenharmony_ci} 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_ciSANE_Status 1018141cc406Sopenharmony_ciesci_request_extended_status(SANE_Handle handle, unsigned char **data, 1019141cc406Sopenharmony_ci size_t * data_len) 1020141cc406Sopenharmony_ci{ 1021141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 1022141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1023141cc406Sopenharmony_ci unsigned char params[2]; 1024141cc406Sopenharmony_ci unsigned char *buf; 1025141cc406Sopenharmony_ci size_t buf_len; 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci DBG(8, "%s\n", __func__); 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_status == 0) 1030141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1031141cc406Sopenharmony_ci 1032141cc406Sopenharmony_ci params[0] = ESC; 1033141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_extended_status; 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci /* This command returns 33 bytes of data on old scanners 1036141cc406Sopenharmony_ci * and 42 (CMD_SIZE_EXT_STATUS) on new ones. 1037141cc406Sopenharmony_ci */ 1038141cc406Sopenharmony_ci status = e2_cmd_info_block(s, params, 2, CMD_SIZE_EXT_STATUS, 1039141cc406Sopenharmony_ci &buf, &buf_len); 1040141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1041141cc406Sopenharmony_ci return status; 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci switch (buf_len) { 1044141cc406Sopenharmony_ci case 33: 1045141cc406Sopenharmony_ci case 42: 1046141cc406Sopenharmony_ci break; 1047141cc406Sopenharmony_ci default: 1048141cc406Sopenharmony_ci DBG(1, "%s: unknown reply length (%lu)\n", __func__, 1049141cc406Sopenharmony_ci (unsigned long) buf_len); 1050141cc406Sopenharmony_ci break; 1051141cc406Sopenharmony_ci } 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci DBG(4, "main = %02x, ADF = %02x, TPU = %02x, main 2 = %02x\n", 1054141cc406Sopenharmony_ci buf[0], buf[1], buf[6], buf[11]); 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci if (buf[0] & EXT_STATUS_FER) 1057141cc406Sopenharmony_ci DBG(1, "system error\n"); 1058141cc406Sopenharmony_ci 1059141cc406Sopenharmony_ci if (buf[0] & EXT_STATUS_WU) 1060141cc406Sopenharmony_ci DBG(1, "scanner is warming up\n"); 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_ERR) 1063141cc406Sopenharmony_ci DBG(1, "ADF: other error\n"); 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_PE) 1066141cc406Sopenharmony_ci DBG(1, "ADF: no paper\n"); 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_PJ) 1069141cc406Sopenharmony_ci DBG(1, "ADF: paper jam\n"); 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_OPN) 1072141cc406Sopenharmony_ci DBG(1, "ADF: cover open\n"); 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_ci if (buf[6] & EXT_STATUS_ERR) 1075141cc406Sopenharmony_ci DBG(1, "TPU: other error\n"); 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci /* give back a pointer to the payload 1078141cc406Sopenharmony_ci * if the user requested it, otherwise 1079141cc406Sopenharmony_ci * free it. 1080141cc406Sopenharmony_ci */ 1081141cc406Sopenharmony_ci 1082141cc406Sopenharmony_ci if (data) 1083141cc406Sopenharmony_ci *data = buf; 1084141cc406Sopenharmony_ci else 1085141cc406Sopenharmony_ci free(buf); 1086141cc406Sopenharmony_ci 1087141cc406Sopenharmony_ci if (data_len) 1088141cc406Sopenharmony_ci *data_len = buf_len; 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci return status; 1091141cc406Sopenharmony_ci} 1092