1141cc406Sopenharmony_ci/* SANE - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de> 4141cc406Sopenharmony_ci Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org> 5141cc406Sopenharmony_ci Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de> 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; either version 2 of the 12141cc406Sopenharmony_ci License, or (at your option) any later version. 13141cc406Sopenharmony_ci 14141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 15141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 16141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17141cc406Sopenharmony_ci General Public License for more details. 18141cc406Sopenharmony_ci 19141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 20141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 23141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 24141cc406Sopenharmony_ci 25141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 26141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 27141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 28141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 29141cc406Sopenharmony_ci account of linking the SANE library code into it. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 32141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 33141cc406Sopenharmony_ci License. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 36141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 37141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 40141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 41141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 42141cc406Sopenharmony_ci */ 43141cc406Sopenharmony_ci#include "../include/sane/config.h" 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci#include <stdio.h> 46141cc406Sopenharmony_ci#include <stdlib.h> 47141cc406Sopenharmony_ci#include <string.h> 48141cc406Sopenharmony_ci#include <time.h> /* localtime(C90) */ 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci#include "pixma_rename.h" 51141cc406Sopenharmony_ci#include "pixma_common.h" 52141cc406Sopenharmony_ci#include "pixma_io.h" 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#ifdef __GNUC__ 56141cc406Sopenharmony_ci# define UNUSED(v) (void) v 57141cc406Sopenharmony_ci#else 58141cc406Sopenharmony_ci# define UNUSED(v) 59141cc406Sopenharmony_ci#endif 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#define IMAGE_BLOCK_SIZE (0xc000) 62141cc406Sopenharmony_ci#define CMDBUF_SIZE 512 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci#define MP10_PID 0x261f 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#define MP730_PID 0x262f 67141cc406Sopenharmony_ci#define MP700_PID 0x2630 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#define MP5_PID 0x2635 /* untested */ 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#define MP360_PID 0x263c 72141cc406Sopenharmony_ci#define MP370_PID 0x263d 73141cc406Sopenharmony_ci#define MP390_PID 0x263e 74141cc406Sopenharmony_ci#define MP375R_PID 0x263f /* untested */ 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#define MP740_PID 0x264c /* Untested */ 77141cc406Sopenharmony_ci#define MP710_PID 0x264d 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#define MF5630_PID 0x264e /* Untested */ 80141cc406Sopenharmony_ci#define MF5650_PID 0x264f 81141cc406Sopenharmony_ci#define MF5730_PID 0x265d /* Untested */ 82141cc406Sopenharmony_ci#define MF5750_PID 0x265e /* Untested */ 83141cc406Sopenharmony_ci#define MF5770_PID 0x265f 84141cc406Sopenharmony_ci#define MF3110_PID 0x2660 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#define IR1020_PID 0x26e6 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_cienum mp730_state_t 89141cc406Sopenharmony_ci{ 90141cc406Sopenharmony_ci state_idle, 91141cc406Sopenharmony_ci state_warmup, 92141cc406Sopenharmony_ci state_scanning, 93141cc406Sopenharmony_ci state_transfering, 94141cc406Sopenharmony_ci state_finished 95141cc406Sopenharmony_ci}; 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_cienum mp730_cmd_t 98141cc406Sopenharmony_ci{ 99141cc406Sopenharmony_ci cmd_start_session = 0xdb20, 100141cc406Sopenharmony_ci cmd_select_source = 0xdd20, 101141cc406Sopenharmony_ci cmd_gamma = 0xee20, 102141cc406Sopenharmony_ci cmd_scan_param = 0xde20, 103141cc406Sopenharmony_ci cmd_status = 0xf320, 104141cc406Sopenharmony_ci cmd_abort_session = 0xef20, 105141cc406Sopenharmony_ci cmd_time = 0xeb80, 106141cc406Sopenharmony_ci cmd_read_image = 0xd420, 107141cc406Sopenharmony_ci cmd_error_info = 0xff20, 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci cmd_activate = 0xcf60, 110141cc406Sopenharmony_ci cmd_calibrate = 0xe920 111141cc406Sopenharmony_ci}; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_citypedef struct mp730_t 114141cc406Sopenharmony_ci{ 115141cc406Sopenharmony_ci enum mp730_state_t state; 116141cc406Sopenharmony_ci pixma_cmdbuf_t cb; 117141cc406Sopenharmony_ci unsigned raw_width; 118141cc406Sopenharmony_ci uint8_t current_status[12]; 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci uint8_t *buf, *imgbuf, *lbuf; 121141cc406Sopenharmony_ci unsigned imgbuf_len; 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci unsigned last_block:1; 124141cc406Sopenharmony_ci} mp730_t; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_cistatic void mp730_finish_scan (pixma_t * s); 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_cistatic int 130141cc406Sopenharmony_cihas_paper (pixma_t * s) 131141cc406Sopenharmony_ci{ 132141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 133141cc406Sopenharmony_ci return (mp->current_status[1] == 0); 134141cc406Sopenharmony_ci} 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_cistatic void 137141cc406Sopenharmony_cidrain_bulk_in (pixma_t * s) 138141cc406Sopenharmony_ci{ 139141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 140141cc406Sopenharmony_ci while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) >= 0); 141141cc406Sopenharmony_ci} 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_cistatic int 144141cc406Sopenharmony_ciabort_session (pixma_t * s) 145141cc406Sopenharmony_ci{ 146141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 147141cc406Sopenharmony_ci return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); 148141cc406Sopenharmony_ci} 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_cistatic int 151141cc406Sopenharmony_ciquery_status (pixma_t * s) 152141cc406Sopenharmony_ci{ 153141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 154141cc406Sopenharmony_ci uint8_t *data; 155141cc406Sopenharmony_ci int error; 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci data = pixma_newcmd (&mp->cb, cmd_status, 0, 12); 158141cc406Sopenharmony_ci error = pixma_exec (s, &mp->cb); 159141cc406Sopenharmony_ci if (error >= 0) 160141cc406Sopenharmony_ci { 161141cc406Sopenharmony_ci memcpy (mp->current_status, data, 12); 162141cc406Sopenharmony_ci PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u\n", 163141cc406Sopenharmony_ci data[1], data[8], data[7])); 164141cc406Sopenharmony_ci } 165141cc406Sopenharmony_ci return error; 166141cc406Sopenharmony_ci} 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_cistatic int 169141cc406Sopenharmony_ciactivate (pixma_t * s, uint8_t x) 170141cc406Sopenharmony_ci{ 171141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 172141cc406Sopenharmony_ci uint8_t *data = pixma_newcmd (&mp->cb, cmd_activate, 10, 0); 173141cc406Sopenharmony_ci data[0] = 1; 174141cc406Sopenharmony_ci data[3] = x; 175141cc406Sopenharmony_ci return pixma_exec (s, &mp->cb); 176141cc406Sopenharmony_ci} 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_cistatic int 179141cc406Sopenharmony_cistart_session (pixma_t * s) 180141cc406Sopenharmony_ci{ 181141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 182141cc406Sopenharmony_ci return pixma_exec_short_cmd (s, &mp->cb, cmd_start_session); 183141cc406Sopenharmony_ci} 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_cistatic int 186141cc406Sopenharmony_ciselect_source (pixma_t * s) 187141cc406Sopenharmony_ci{ 188141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 189141cc406Sopenharmony_ci uint8_t *data = pixma_newcmd (&mp->cb, cmd_select_source, 10, 0); 190141cc406Sopenharmony_ci switch (s->param->source) 191141cc406Sopenharmony_ci { 192141cc406Sopenharmony_ci case PIXMA_SOURCE_ADF: 193141cc406Sopenharmony_ci data[0] = 2; 194141cc406Sopenharmony_ci break; 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci case PIXMA_SOURCE_ADFDUP: 197141cc406Sopenharmony_ci data[0] = 2; 198141cc406Sopenharmony_ci data[5] = 3; 199141cc406Sopenharmony_ci break; 200141cc406Sopenharmony_ci 201141cc406Sopenharmony_ci default: 202141cc406Sopenharmony_ci data[0] = 1; 203141cc406Sopenharmony_ci break; 204141cc406Sopenharmony_ci } 205141cc406Sopenharmony_ci return pixma_exec (s, &mp->cb); 206141cc406Sopenharmony_ci} 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_cistatic int 209141cc406Sopenharmony_cisend_scan_param (pixma_t * s) 210141cc406Sopenharmony_ci{ 211141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 212141cc406Sopenharmony_ci uint8_t *data; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x2e, 0); 215141cc406Sopenharmony_ci pixma_set_be16 (s->param->xdpi | 0x1000, data + 0x04); 216141cc406Sopenharmony_ci pixma_set_be16 (s->param->ydpi | 0x1000, data + 0x06); 217141cc406Sopenharmony_ci pixma_set_be32 (s->param->x, data + 0x08); 218141cc406Sopenharmony_ci pixma_set_be32 (s->param->y, data + 0x0c); 219141cc406Sopenharmony_ci pixma_set_be32 (mp->raw_width, data + 0x10); 220141cc406Sopenharmony_ci pixma_set_be32 (s->param->h, data + 0x14); 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci if (s->param->channels == 1) 223141cc406Sopenharmony_ci { 224141cc406Sopenharmony_ci if (s->param->depth == 1) 225141cc406Sopenharmony_ci data[0x18] = 0x01; 226141cc406Sopenharmony_ci else 227141cc406Sopenharmony_ci data[0x18] = 0x04; 228141cc406Sopenharmony_ci } 229141cc406Sopenharmony_ci else 230141cc406Sopenharmony_ci data[0x18] = 0x08; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci data[0x19] = s->param->channels * s->param->depth; /* bits per pixel, for lineart should be 0x01 */ 233141cc406Sopenharmony_ci data[0x1e] = (s->param->depth == 1) ? 0x80 : 0x00; /* modify for lineart: 0x80 NEW */ 234141cc406Sopenharmony_ci data[0x1f] = (s->param->depth == 1) ? 0x80 : 0x7f; /* modify for lineart: 0x80 */ 235141cc406Sopenharmony_ci data[0x20] = (s->param->depth == 1) ? 0x01 : 0xff; /* modify for lineart: 0x01 */ 236141cc406Sopenharmony_ci data[0x23] = 0x81; 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci return pixma_exec (s, &mp->cb); 239141cc406Sopenharmony_ci} 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_cistatic int 242141cc406Sopenharmony_cicalibrate (pixma_t * s) 243141cc406Sopenharmony_ci{ 244141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 245141cc406Sopenharmony_ci return pixma_exec_short_cmd (s, &mp->cb, cmd_calibrate); 246141cc406Sopenharmony_ci} 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_cistatic int 249141cc406Sopenharmony_ciread_image_block (pixma_t * s, uint8_t * header, uint8_t * data) 250141cc406Sopenharmony_ci{ 251141cc406Sopenharmony_ci static const uint8_t cmd[10] = /* 0xd420 cmd */ 252141cc406Sopenharmony_ci { 0xd4, 0x20, 0, 0, 0, 0, 0, IMAGE_BLOCK_SIZE / 256, 4, 0 }; 253141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 254141cc406Sopenharmony_ci const int hlen = 2 + 4; 255141cc406Sopenharmony_ci int error, datalen; 256141cc406Sopenharmony_ci 257141cc406Sopenharmony_ci mp->state = state_transfering; 258141cc406Sopenharmony_ci mp->cb.reslen = 259141cc406Sopenharmony_ci pixma_cmd_transaction (s, cmd, sizeof (cmd), mp->cb.buf, 512); 260141cc406Sopenharmony_ci datalen = mp->cb.reslen; 261141cc406Sopenharmony_ci if (datalen < 0) 262141cc406Sopenharmony_ci return datalen; 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci memcpy (header, mp->cb.buf, hlen); 265141cc406Sopenharmony_ci if (datalen >= hlen) 266141cc406Sopenharmony_ci { 267141cc406Sopenharmony_ci datalen -= hlen; 268141cc406Sopenharmony_ci memcpy (data, mp->cb.buf + hlen, datalen); 269141cc406Sopenharmony_ci data += datalen; 270141cc406Sopenharmony_ci if (mp->cb.reslen == 512) 271141cc406Sopenharmony_ci { 272141cc406Sopenharmony_ci error = pixma_read (s->io, data, IMAGE_BLOCK_SIZE - 512 + hlen); 273141cc406Sopenharmony_ci if (error < 0) 274141cc406Sopenharmony_ci return error; 275141cc406Sopenharmony_ci datalen += error; 276141cc406Sopenharmony_ci } 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci mp->state = state_scanning; 280141cc406Sopenharmony_ci mp->cb.expected_reslen = 0; 281141cc406Sopenharmony_ci error = pixma_check_result (&mp->cb); 282141cc406Sopenharmony_ci if (error < 0) 283141cc406Sopenharmony_ci return error; 284141cc406Sopenharmony_ci if (mp->cb.reslen < hlen) 285141cc406Sopenharmony_ci return PIXMA_EPROTO; 286141cc406Sopenharmony_ci return datalen; 287141cc406Sopenharmony_ci} 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_cistatic int 290141cc406Sopenharmony_cisend_time (pixma_t * s) 291141cc406Sopenharmony_ci{ 292141cc406Sopenharmony_ci /* Why does a scanner need a time? */ 293141cc406Sopenharmony_ci time_t now; 294141cc406Sopenharmony_ci struct tm *t; 295141cc406Sopenharmony_ci uint8_t *data; 296141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci data = pixma_newcmd (&mp->cb, cmd_time, 20, 0); 299141cc406Sopenharmony_ci pixma_get_time (&now, NULL); 300141cc406Sopenharmony_ci t = localtime (&now); 301141cc406Sopenharmony_ci strftime ((char *) data, 16, "%y/%m/%d %H:%M", t); 302141cc406Sopenharmony_ci PDBG (pixma_dbg (3, "Sending time: '%s'\n", (char *) data)); 303141cc406Sopenharmony_ci return pixma_exec (s, &mp->cb); 304141cc406Sopenharmony_ci} 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_cistatic int 307141cc406Sopenharmony_cihandle_interrupt (pixma_t * s, int timeout) 308141cc406Sopenharmony_ci{ 309141cc406Sopenharmony_ci uint8_t buf[16]; 310141cc406Sopenharmony_ci int len; 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); 313141cc406Sopenharmony_ci if (len == PIXMA_ETIMEDOUT) 314141cc406Sopenharmony_ci return 0; 315141cc406Sopenharmony_ci if (len < 0) 316141cc406Sopenharmony_ci return len; 317141cc406Sopenharmony_ci switch (s->cfg->pid) 318141cc406Sopenharmony_ci { 319141cc406Sopenharmony_ci case MP360_PID: 320141cc406Sopenharmony_ci case MP370_PID: 321141cc406Sopenharmony_ci case MP375R_PID: 322141cc406Sopenharmony_ci case MP390_PID: 323141cc406Sopenharmony_ci case MF5630_PID: 324141cc406Sopenharmony_ci case MF5650_PID: 325141cc406Sopenharmony_ci case MF5730_PID: 326141cc406Sopenharmony_ci case MF5750_PID: 327141cc406Sopenharmony_ci case MF5770_PID: 328141cc406Sopenharmony_ci case MF3110_PID: 329141cc406Sopenharmony_ci case IR1020_PID: 330141cc406Sopenharmony_ci if (len != 16) 331141cc406Sopenharmony_ci { 332141cc406Sopenharmony_ci PDBG (pixma_dbg 333141cc406Sopenharmony_ci (1, "WARNING:unexpected interrupt packet length %d\n", len)); 334141cc406Sopenharmony_ci return PIXMA_EPROTO; 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci if (buf[12] & 0x40) 337141cc406Sopenharmony_ci query_status (s); 338141cc406Sopenharmony_ci if (buf[10] & 0x40) 339141cc406Sopenharmony_ci send_time (s); 340141cc406Sopenharmony_ci /* FIXME: following is unverified! */ 341141cc406Sopenharmony_ci if (buf[15] & 1) 342141cc406Sopenharmony_ci s->events = PIXMA_EV_BUTTON2; /* b/w scan */ 343141cc406Sopenharmony_ci if (buf[15] & 2) 344141cc406Sopenharmony_ci s->events = PIXMA_EV_BUTTON1; /* color scan */ 345141cc406Sopenharmony_ci break; 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci case MP5_PID: 348141cc406Sopenharmony_ci case MP10_PID: 349141cc406Sopenharmony_ci case MP700_PID: 350141cc406Sopenharmony_ci case MP730_PID: 351141cc406Sopenharmony_ci case MP710_PID: 352141cc406Sopenharmony_ci case MP740_PID: 353141cc406Sopenharmony_ci if (len != 8) 354141cc406Sopenharmony_ci { 355141cc406Sopenharmony_ci PDBG (pixma_dbg 356141cc406Sopenharmony_ci (1, "WARNING:unexpected interrupt packet length %d\n", len)); 357141cc406Sopenharmony_ci return PIXMA_EPROTO; 358141cc406Sopenharmony_ci } 359141cc406Sopenharmony_ci if (buf[7] & 0x10) 360141cc406Sopenharmony_ci s->events = PIXMA_EV_BUTTON1; 361141cc406Sopenharmony_ci if (buf[5] & 8) 362141cc406Sopenharmony_ci send_time (s); 363141cc406Sopenharmony_ci break; 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci default: 366141cc406Sopenharmony_ci PDBG (pixma_dbg (1, "WARNING:unknown interrupt, please report!\n")); 367141cc406Sopenharmony_ci PDBG (pixma_hexdump (1, buf, len)); 368141cc406Sopenharmony_ci } 369141cc406Sopenharmony_ci return 1; 370141cc406Sopenharmony_ci} 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_cistatic int 373141cc406Sopenharmony_cihas_ccd_sensor (pixma_t * s) 374141cc406Sopenharmony_ci{ 375141cc406Sopenharmony_ci return (s->cfg->pid == MP360_PID || 376141cc406Sopenharmony_ci s->cfg->pid == MP370_PID || 377141cc406Sopenharmony_ci s->cfg->pid == MP375R_PID || 378141cc406Sopenharmony_ci s->cfg->pid == MP390_PID || 379141cc406Sopenharmony_ci s->cfg->pid == MF5630_PID || 380141cc406Sopenharmony_ci s->cfg->pid == MF5650_PID || 381141cc406Sopenharmony_ci s->cfg->pid == MF5730_PID || 382141cc406Sopenharmony_ci s->cfg->pid == MF5750_PID || 383141cc406Sopenharmony_ci s->cfg->pid == MF5770_PID); 384141cc406Sopenharmony_ci} 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_cistatic int 387141cc406Sopenharmony_ciread_error_info (pixma_t * s, void *buf, unsigned size) 388141cc406Sopenharmony_ci{ 389141cc406Sopenharmony_ci unsigned len = 16; 390141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 391141cc406Sopenharmony_ci uint8_t *data; 392141cc406Sopenharmony_ci int error; 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len); 395141cc406Sopenharmony_ci error = pixma_exec (s, &mp->cb); 396141cc406Sopenharmony_ci if (error < 0) 397141cc406Sopenharmony_ci return error; 398141cc406Sopenharmony_ci if (buf && len < size) 399141cc406Sopenharmony_ci { 400141cc406Sopenharmony_ci size = len; 401141cc406Sopenharmony_ci /* NOTE: I've absolutely no idea what the returned data mean. */ 402141cc406Sopenharmony_ci memcpy (buf, data, size); 403141cc406Sopenharmony_ci error = len; 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci return error; 406141cc406Sopenharmony_ci} 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_cistatic int 409141cc406Sopenharmony_cistep1 (pixma_t * s) 410141cc406Sopenharmony_ci{ 411141cc406Sopenharmony_ci int error; 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_ci error = query_status (s); 414141cc406Sopenharmony_ci if (error < 0) 415141cc406Sopenharmony_ci return error; 416141cc406Sopenharmony_ci if ((s->param->source == PIXMA_SOURCE_ADF 417141cc406Sopenharmony_ci || s->param->source == PIXMA_SOURCE_ADFDUP) 418141cc406Sopenharmony_ci && !has_paper (s)) 419141cc406Sopenharmony_ci return PIXMA_ENO_PAPER; 420141cc406Sopenharmony_ci if (has_ccd_sensor (s)) 421141cc406Sopenharmony_ci { 422141cc406Sopenharmony_ci switch (s->cfg->pid) 423141cc406Sopenharmony_ci { 424141cc406Sopenharmony_ci case MF5630_PID: 425141cc406Sopenharmony_ci case MF5650_PID: 426141cc406Sopenharmony_ci case MF5730_PID: 427141cc406Sopenharmony_ci case MF5750_PID: 428141cc406Sopenharmony_ci case MF5770_PID: 429141cc406Sopenharmony_ci /* MF57x0: Wait 10 sec before starting for 1st page only */ 430141cc406Sopenharmony_ci if (s->param->adf_pageid == 0) 431141cc406Sopenharmony_ci { 432141cc406Sopenharmony_ci int tmo = 10; /* like Windows driver, 10 sec CCD calibration ? */ 433141cc406Sopenharmony_ci while (--tmo >= 0) 434141cc406Sopenharmony_ci { 435141cc406Sopenharmony_ci error = handle_interrupt (s, 1000); 436141cc406Sopenharmony_ci if (s->cancel) 437141cc406Sopenharmony_ci return PIXMA_ECANCELED; 438141cc406Sopenharmony_ci if (error != PIXMA_ECANCELED && error < 0) 439141cc406Sopenharmony_ci return error; 440141cc406Sopenharmony_ci PDBG (pixma_dbg (2, "CCD Calibration ends in %d sec.\n", tmo)); 441141cc406Sopenharmony_ci } 442141cc406Sopenharmony_ci } 443141cc406Sopenharmony_ci break; 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci default: 446141cc406Sopenharmony_ci break; 447141cc406Sopenharmony_ci } 448141cc406Sopenharmony_ci 449141cc406Sopenharmony_ci activate (s, 0); 450141cc406Sopenharmony_ci error = calibrate (s); 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci switch (s->cfg->pid) 453141cc406Sopenharmony_ci { 454141cc406Sopenharmony_ci case MF5630_PID: 455141cc406Sopenharmony_ci case MF5650_PID: 456141cc406Sopenharmony_ci case MF5730_PID: 457141cc406Sopenharmony_ci case MF5750_PID: 458141cc406Sopenharmony_ci case MF5770_PID: 459141cc406Sopenharmony_ci /* MF57x0: calibration returns PIXMA_STATUS_FAILED */ 460141cc406Sopenharmony_ci if (error == PIXMA_ECANCELED) 461141cc406Sopenharmony_ci error = read_error_info (s, NULL, 0); 462141cc406Sopenharmony_ci break; 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci default: 465141cc406Sopenharmony_ci break; 466141cc406Sopenharmony_ci } 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci // ignore result from calibrate() 469141cc406Sopenharmony_ci // don't interrupt @ PIXMA_STATUS_BUSY 470141cc406Sopenharmony_ci error = 0; 471141cc406Sopenharmony_ci } 472141cc406Sopenharmony_ci if (error >= 0) 473141cc406Sopenharmony_ci error = activate (s, 0); 474141cc406Sopenharmony_ci if (error >= 0) 475141cc406Sopenharmony_ci error = activate (s, 4); 476141cc406Sopenharmony_ci return error; 477141cc406Sopenharmony_ci} 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_cistatic void 480141cc406Sopenharmony_cipack_rgb (const uint8_t * src, unsigned nlines, unsigned w, uint8_t * dst) 481141cc406Sopenharmony_ci{ 482141cc406Sopenharmony_ci unsigned w2, stride; 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci w2 = 2 * w; 485141cc406Sopenharmony_ci stride = 3 * w; 486141cc406Sopenharmony_ci for (; nlines != 0; nlines--) 487141cc406Sopenharmony_ci { 488141cc406Sopenharmony_ci unsigned x; 489141cc406Sopenharmony_ci for (x = 0; x != w; x++) 490141cc406Sopenharmony_ci { 491141cc406Sopenharmony_ci *dst++ = src[x + 0]; 492141cc406Sopenharmony_ci *dst++ = src[x + w]; 493141cc406Sopenharmony_ci *dst++ = src[x + w2]; 494141cc406Sopenharmony_ci } 495141cc406Sopenharmony_ci src += stride; 496141cc406Sopenharmony_ci } 497141cc406Sopenharmony_ci} 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_cistatic int 500141cc406Sopenharmony_cimp730_open (pixma_t * s) 501141cc406Sopenharmony_ci{ 502141cc406Sopenharmony_ci mp730_t *mp; 503141cc406Sopenharmony_ci uint8_t *buf; 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_ci mp = (mp730_t *) calloc (1, sizeof (*mp)); 506141cc406Sopenharmony_ci if (!mp) 507141cc406Sopenharmony_ci return PIXMA_ENOMEM; 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci buf = (uint8_t *) malloc (CMDBUF_SIZE); 510141cc406Sopenharmony_ci if (!buf) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci free (mp); 513141cc406Sopenharmony_ci return PIXMA_ENOMEM; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci s->subdriver = mp; 517141cc406Sopenharmony_ci mp->state = state_idle; 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci mp->cb.buf = buf; 520141cc406Sopenharmony_ci mp->cb.size = CMDBUF_SIZE; 521141cc406Sopenharmony_ci mp->cb.res_header_len = 2; 522141cc406Sopenharmony_ci mp->cb.cmd_header_len = 10; 523141cc406Sopenharmony_ci mp->cb.cmd_len_field_ofs = 7; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci PDBG (pixma_dbg (3, "Trying to clear the interrupt buffer...\n")); 526141cc406Sopenharmony_ci if (handle_interrupt (s, 200) == 0) 527141cc406Sopenharmony_ci { 528141cc406Sopenharmony_ci PDBG (pixma_dbg (3, " no packets in buffer\n")); 529141cc406Sopenharmony_ci } 530141cc406Sopenharmony_ci return 0; 531141cc406Sopenharmony_ci} 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_cistatic void 534141cc406Sopenharmony_cimp730_close (pixma_t * s) 535141cc406Sopenharmony_ci{ 536141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci mp730_finish_scan (s); 539141cc406Sopenharmony_ci free (mp->cb.buf); 540141cc406Sopenharmony_ci free (mp->buf); 541141cc406Sopenharmony_ci free (mp); 542141cc406Sopenharmony_ci s->subdriver = NULL; 543141cc406Sopenharmony_ci} 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_cistatic unsigned 546141cc406Sopenharmony_cicalc_raw_width (pixma_t * s, const pixma_scan_param_t * sp) 547141cc406Sopenharmony_ci{ 548141cc406Sopenharmony_ci unsigned raw_width; 549141cc406Sopenharmony_ci /* FIXME: Does MP730 need the alignment? */ 550141cc406Sopenharmony_ci /* TODO test: MP710/740 */ 551141cc406Sopenharmony_ci if (sp->channels == 1) 552141cc406Sopenharmony_ci { 553141cc406Sopenharmony_ci if (sp->depth == 8) /* grayscale */ 554141cc406Sopenharmony_ci { 555141cc406Sopenharmony_ci if (s->cfg->pid == MP5_PID || 556141cc406Sopenharmony_ci s->cfg->pid == MP10_PID || 557141cc406Sopenharmony_ci s->cfg->pid == MP700_PID || 558141cc406Sopenharmony_ci s->cfg->pid == MP730_PID || 559141cc406Sopenharmony_ci s->cfg->pid == MP360_PID || 560141cc406Sopenharmony_ci s->cfg->pid == MP370_PID || 561141cc406Sopenharmony_ci s->cfg->pid == MP375R_PID || 562141cc406Sopenharmony_ci s->cfg->pid == MP390_PID || 563141cc406Sopenharmony_ci s->cfg->pid == IR1020_PID) 564141cc406Sopenharmony_ci raw_width = ALIGN_SUP (sp->w, 4); 565141cc406Sopenharmony_ci else 566141cc406Sopenharmony_ci raw_width = ALIGN_SUP (sp->w, 12); 567141cc406Sopenharmony_ci } 568141cc406Sopenharmony_ci else /* depth = 1 : LINEART */ 569141cc406Sopenharmony_ci raw_width = ALIGN_SUP (sp->w, 16); 570141cc406Sopenharmony_ci } 571141cc406Sopenharmony_ci else 572141cc406Sopenharmony_ci raw_width = ALIGN_SUP (sp->w, 4); 573141cc406Sopenharmony_ci return raw_width; 574141cc406Sopenharmony_ci} 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_cistatic int 577141cc406Sopenharmony_cimp730_check_param (pixma_t * s, pixma_scan_param_t * sp) 578141cc406Sopenharmony_ci{ 579141cc406Sopenharmony_ci uint8_t k = 1; 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci /* check if channels is 3, or if depth is 1 then channels also 1 else set depth to 8 */ 582141cc406Sopenharmony_ci if ((sp->channels==3) || !(sp->channels==1 && sp->depth==1)) 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci sp->depth=8; 585141cc406Sopenharmony_ci } 586141cc406Sopenharmony_ci /* for MP5, MP10, MP360/370, MP700/730 in grayscale & lineart modes, max scan res is 600 dpi */ 587141cc406Sopenharmony_ci if (s->cfg->pid == MP5_PID || 588141cc406Sopenharmony_ci s->cfg->pid == MP10_PID || 589141cc406Sopenharmony_ci s->cfg->pid == MP700_PID || 590141cc406Sopenharmony_ci s->cfg->pid == MP730_PID || 591141cc406Sopenharmony_ci s->cfg->pid == MP360_PID || 592141cc406Sopenharmony_ci s->cfg->pid == MP370_PID || 593141cc406Sopenharmony_ci s->cfg->pid == MP375R_PID || 594141cc406Sopenharmony_ci s->cfg->pid == MP390_PID) 595141cc406Sopenharmony_ci { 596141cc406Sopenharmony_ci if (sp->channels == 1) 597141cc406Sopenharmony_ci k = sp->xdpi / MIN (sp->xdpi, 600); 598141cc406Sopenharmony_ci } 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci sp->x /= k; 601141cc406Sopenharmony_ci sp->y /= k; 602141cc406Sopenharmony_ci sp->h /= k; 603141cc406Sopenharmony_ci sp->xdpi /= k; 604141cc406Sopenharmony_ci sp->ydpi = sp->xdpi; 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci sp->w = calc_raw_width (s, sp); 607141cc406Sopenharmony_ci sp->w /= k; 608141cc406Sopenharmony_ci sp->line_size = (calc_raw_width (s, sp) * sp->channels * sp->depth) / 8; 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci return 0; 611141cc406Sopenharmony_ci} 612141cc406Sopenharmony_ci 613141cc406Sopenharmony_cistatic int 614141cc406Sopenharmony_cimp730_scan (pixma_t * s) 615141cc406Sopenharmony_ci{ 616141cc406Sopenharmony_ci int error, n; 617141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 618141cc406Sopenharmony_ci uint8_t *buf; 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci if (mp->state != state_idle) 621141cc406Sopenharmony_ci return PIXMA_EBUSY; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci /* clear interrupt packets buffer */ 624141cc406Sopenharmony_ci while (handle_interrupt (s, 0) > 0) 625141cc406Sopenharmony_ci { 626141cc406Sopenharmony_ci } 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci mp->raw_width = calc_raw_width (s, s->param); 629141cc406Sopenharmony_ci PDBG (pixma_dbg (3, "raw_width = %u\n", mp->raw_width)); 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci n = IMAGE_BLOCK_SIZE / s->param->line_size + 1; 632141cc406Sopenharmony_ci buf = (uint8_t *) malloc ((n + 1) * s->param->line_size + IMAGE_BLOCK_SIZE); 633141cc406Sopenharmony_ci if (!buf) 634141cc406Sopenharmony_ci return PIXMA_ENOMEM; 635141cc406Sopenharmony_ci mp->buf = buf; 636141cc406Sopenharmony_ci mp->lbuf = buf; 637141cc406Sopenharmony_ci mp->imgbuf = buf + n * s->param->line_size; 638141cc406Sopenharmony_ci mp->imgbuf_len = 0; 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci error = step1 (s); 641141cc406Sopenharmony_ci if (error >= 0) 642141cc406Sopenharmony_ci error = start_session (s); 643141cc406Sopenharmony_ci if (error >= 0) 644141cc406Sopenharmony_ci mp->state = state_scanning; 645141cc406Sopenharmony_ci if (error >= 0) 646141cc406Sopenharmony_ci error = select_source (s); 647141cc406Sopenharmony_ci if (error >= 0) 648141cc406Sopenharmony_ci error = send_scan_param (s); 649141cc406Sopenharmony_ci if (error < 0) 650141cc406Sopenharmony_ci { 651141cc406Sopenharmony_ci mp730_finish_scan (s); 652141cc406Sopenharmony_ci return error; 653141cc406Sopenharmony_ci } 654141cc406Sopenharmony_ci mp->last_block = 0; 655141cc406Sopenharmony_ci return 0; 656141cc406Sopenharmony_ci} 657141cc406Sopenharmony_ci 658141cc406Sopenharmony_cistatic int 659141cc406Sopenharmony_cimp730_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) 660141cc406Sopenharmony_ci{ 661141cc406Sopenharmony_ci int error, n; 662141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 663141cc406Sopenharmony_ci unsigned block_size, bytes_received; 664141cc406Sopenharmony_ci uint8_t header[16]; 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci do 667141cc406Sopenharmony_ci { 668141cc406Sopenharmony_ci do 669141cc406Sopenharmony_ci { 670141cc406Sopenharmony_ci if (s->cancel) 671141cc406Sopenharmony_ci return PIXMA_ECANCELED; 672141cc406Sopenharmony_ci if (mp->last_block) /* end of image */ 673141cc406Sopenharmony_ci return 0; 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci error = read_image_block (s, header, mp->imgbuf + mp->imgbuf_len); 676141cc406Sopenharmony_ci if (error < 0) 677141cc406Sopenharmony_ci return error; 678141cc406Sopenharmony_ci 679141cc406Sopenharmony_ci bytes_received = error; 680141cc406Sopenharmony_ci block_size = pixma_get_be16 (header + 4); 681141cc406Sopenharmony_ci mp->last_block = ((header[2] & 0x28) == 0x28); 682141cc406Sopenharmony_ci if (mp->last_block) 683141cc406Sopenharmony_ci { /* end of image */ 684141cc406Sopenharmony_ci mp->state = state_finished; 685141cc406Sopenharmony_ci } 686141cc406Sopenharmony_ci if ((header[2] & ~0x38) != 0) 687141cc406Sopenharmony_ci { 688141cc406Sopenharmony_ci PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); 689141cc406Sopenharmony_ci PDBG (pixma_hexdump (1, header, 16)); 690141cc406Sopenharmony_ci } 691141cc406Sopenharmony_ci PASSERT (bytes_received == block_size); 692141cc406Sopenharmony_ci 693141cc406Sopenharmony_ci if (block_size == 0) 694141cc406Sopenharmony_ci { 695141cc406Sopenharmony_ci /* no image data at this moment. */ 696141cc406Sopenharmony_ci /*pixma_sleep(100000); *//* FIXME: too short, too long? */ 697141cc406Sopenharmony_ci handle_interrupt (s, 100); 698141cc406Sopenharmony_ci } 699141cc406Sopenharmony_ci } 700141cc406Sopenharmony_ci while (block_size == 0); 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci /* TODO: simplify! */ 703141cc406Sopenharmony_ci mp->imgbuf_len += bytes_received; 704141cc406Sopenharmony_ci n = mp->imgbuf_len / s->param->line_size; 705141cc406Sopenharmony_ci /* n = number of full lines (rows) we have in the buffer. */ 706141cc406Sopenharmony_ci if (n != 0) 707141cc406Sopenharmony_ci { 708141cc406Sopenharmony_ci if (s->param->channels != 1 && 709141cc406Sopenharmony_ci s->cfg->pid != MF5630_PID && 710141cc406Sopenharmony_ci s->cfg->pid != MF5650_PID && 711141cc406Sopenharmony_ci s->cfg->pid != MF5730_PID && 712141cc406Sopenharmony_ci s->cfg->pid != MF5750_PID && 713141cc406Sopenharmony_ci s->cfg->pid != MF5770_PID && 714141cc406Sopenharmony_ci s->cfg->pid != MF3110_PID && 715141cc406Sopenharmony_ci s->cfg->pid != IR1020_PID) 716141cc406Sopenharmony_ci { 717141cc406Sopenharmony_ci /* color, and not an MF57x0 nor MF3110 */ 718141cc406Sopenharmony_ci pack_rgb (mp->imgbuf, n, mp->raw_width, mp->lbuf); 719141cc406Sopenharmony_ci } 720141cc406Sopenharmony_ci else 721141cc406Sopenharmony_ci /* grayscale/lineart or MF57x0 or MF3110 */ 722141cc406Sopenharmony_ci memcpy (mp->lbuf, mp->imgbuf, n * s->param->line_size); 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci block_size = n * s->param->line_size; 725141cc406Sopenharmony_ci mp->imgbuf_len -= block_size; 726141cc406Sopenharmony_ci memcpy (mp->imgbuf, mp->imgbuf + block_size, mp->imgbuf_len); 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci } 729141cc406Sopenharmony_ci while (n == 0); 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci ib->rptr = mp->lbuf; 732141cc406Sopenharmony_ci ib->rend = mp->lbuf + block_size; 733141cc406Sopenharmony_ci return ib->rend - ib->rptr; 734141cc406Sopenharmony_ci} 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_cistatic void 737141cc406Sopenharmony_cimp730_finish_scan (pixma_t * s) 738141cc406Sopenharmony_ci{ 739141cc406Sopenharmony_ci int error, aborted = 0; 740141cc406Sopenharmony_ci mp730_t *mp = (mp730_t *) s->subdriver; 741141cc406Sopenharmony_ci 742141cc406Sopenharmony_ci switch (mp->state) 743141cc406Sopenharmony_ci { 744141cc406Sopenharmony_ci case state_transfering: 745141cc406Sopenharmony_ci drain_bulk_in (s); 746141cc406Sopenharmony_ci /* fall through */ 747141cc406Sopenharmony_ci case state_scanning: 748141cc406Sopenharmony_ci case state_warmup: 749141cc406Sopenharmony_ci aborted = 1; 750141cc406Sopenharmony_ci error = abort_session (s); 751141cc406Sopenharmony_ci if (error < 0) 752141cc406Sopenharmony_ci PDBG (pixma_dbg 753141cc406Sopenharmony_ci (1, "WARNING:abort_session() failed %s\n", 754141cc406Sopenharmony_ci pixma_strerror (error))); 755141cc406Sopenharmony_ci /* fall through */ 756141cc406Sopenharmony_ci case state_finished: 757141cc406Sopenharmony_ci query_status (s); 758141cc406Sopenharmony_ci query_status (s); 759141cc406Sopenharmony_ci activate (s, 0); 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci // MF57x0 devices don't require abort_session() after the last page 762141cc406Sopenharmony_ci if (!aborted && 763141cc406Sopenharmony_ci (s->param->source == PIXMA_SOURCE_ADF || 764141cc406Sopenharmony_ci s->param->source == PIXMA_SOURCE_ADFDUP) && 765141cc406Sopenharmony_ci has_paper (s) && 766141cc406Sopenharmony_ci (s->cfg->pid == MF5630_PID || 767141cc406Sopenharmony_ci s->cfg->pid == MF5650_PID || 768141cc406Sopenharmony_ci s->cfg->pid == MF5730_PID || 769141cc406Sopenharmony_ci s->cfg->pid == MF5750_PID || 770141cc406Sopenharmony_ci s->cfg->pid == MF5770_PID || 771141cc406Sopenharmony_ci s->cfg->pid == IR1020_PID)) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci error = abort_session (s); 774141cc406Sopenharmony_ci if (error < 0) 775141cc406Sopenharmony_ci PDBG (pixma_dbg 776141cc406Sopenharmony_ci (1, "WARNING:abort_session() failed %s\n", 777141cc406Sopenharmony_ci pixma_strerror (error))); 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci mp->buf = mp->lbuf = mp->imgbuf = NULL; 781141cc406Sopenharmony_ci mp->state = state_idle; 782141cc406Sopenharmony_ci /* fall through */ 783141cc406Sopenharmony_ci case state_idle: 784141cc406Sopenharmony_ci break; 785141cc406Sopenharmony_ci } 786141cc406Sopenharmony_ci} 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_cistatic void 789141cc406Sopenharmony_cimp730_wait_event (pixma_t * s, int timeout) 790141cc406Sopenharmony_ci{ 791141cc406Sopenharmony_ci /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for 792141cc406Sopenharmony_ci * instance. */ 793141cc406Sopenharmony_ci while (s->events == 0 && handle_interrupt (s, timeout) > 0) 794141cc406Sopenharmony_ci { 795141cc406Sopenharmony_ci } 796141cc406Sopenharmony_ci} 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_cistatic int 799141cc406Sopenharmony_cimp730_get_status (pixma_t * s, pixma_device_status_t * status) 800141cc406Sopenharmony_ci{ 801141cc406Sopenharmony_ci int error; 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci error = query_status (s); 804141cc406Sopenharmony_ci if (error < 0) 805141cc406Sopenharmony_ci return error; 806141cc406Sopenharmony_ci status->hardware = PIXMA_HARDWARE_OK; 807141cc406Sopenharmony_ci status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; 808141cc406Sopenharmony_ci return 0; 809141cc406Sopenharmony_ci} 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_cistatic const pixma_scan_ops_t pixma_mp730_ops = { 813141cc406Sopenharmony_ci mp730_open, 814141cc406Sopenharmony_ci mp730_close, 815141cc406Sopenharmony_ci mp730_scan, 816141cc406Sopenharmony_ci mp730_fill_buffer, 817141cc406Sopenharmony_ci mp730_finish_scan, 818141cc406Sopenharmony_ci mp730_wait_event, 819141cc406Sopenharmony_ci mp730_check_param, 820141cc406Sopenharmony_ci mp730_get_status 821141cc406Sopenharmony_ci}; 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci/* TODO: implement adftpu_min_dpi & adftpu_max_dpi for grayscale & lineart */ 824141cc406Sopenharmony_ci#define DEVICE(name, model, pid, dpi, w, h, cap) { \ 825141cc406Sopenharmony_ci name, /* name */ \ 826141cc406Sopenharmony_ci model, /* model */ \ 827141cc406Sopenharmony_ci 0x04a9, pid, /* vid pid */ \ 828141cc406Sopenharmony_ci 1, /* iface */ \ 829141cc406Sopenharmony_ci &pixma_mp730_ops, /* ops */ \ 830141cc406Sopenharmony_ci 0, 0, /* min_xdpi & min_xdpi_16 not used in this subdriver */ \ 831141cc406Sopenharmony_ci dpi, dpi, /* xdpi, ydpi */ \ 832141cc406Sopenharmony_ci 0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \ 833141cc406Sopenharmony_ci 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ 834141cc406Sopenharmony_ci w, h, /* width, height */ \ 835141cc406Sopenharmony_ci PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ 836141cc406Sopenharmony_ci} 837141cc406Sopenharmony_ciconst pixma_config_t pixma_mp730_devices[] = { 838141cc406Sopenharmony_ci/* TODO: check area limits */ 839141cc406Sopenharmony_ci DEVICE ("PIXUS MP5/SmartBase MPC190/imageCLASS MPC190","MP5", MP5_PID, 600, 636, 868, PIXMA_CAP_LINEART),/* color scan can do 600x1200 */ 840141cc406Sopenharmony_ci DEVICE ("PIXUS MP10/SmartBase MPC200/imageCLASS MPC200","MP10", MP10_PID, 600, 636, 868, PIXMA_CAP_LINEART),/* color scan can do 600x1200 */ 841141cc406Sopenharmony_ci DEVICE ("PIXMA MP360", "MP360", MP360_PID, 1200, 636, 868, PIXMA_CAP_LINEART), 842141cc406Sopenharmony_ci DEVICE ("PIXMA MP370", "MP370", MP370_PID, 1200, 636, 868, PIXMA_CAP_LINEART), 843141cc406Sopenharmony_ci DEVICE ("PIXMA MP375R", "MP375R", MP375R_PID, 1200, 636, 868, PIXMA_CAP_LINEART), 844141cc406Sopenharmony_ci DEVICE ("PIXMA MP390", "MP390", MP390_PID, 1200, 636, 868, PIXMA_CAP_LINEART), 845141cc406Sopenharmony_ci DEVICE ("PIXMA MP700", "MP700", MP700_PID, 1200, 638, 877 /*1035 */ , PIXMA_CAP_LINEART), 846141cc406Sopenharmony_ci DEVICE ("PIXMA MP710", "MP710", MP710_PID, 1200, 637, 868, PIXMA_CAP_LINEART), 847141cc406Sopenharmony_ci DEVICE ("PIXMA MP730", "MP730", MP730_PID, 1200, 637, 868, PIXMA_CAP_ADF | PIXMA_CAP_LINEART), 848141cc406Sopenharmony_ci DEVICE ("PIXMA MP740", "MP740", MP740_PID, 1200, 637, 868, PIXMA_CAP_ADF | PIXMA_CAP_LINEART), 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci DEVICE ("Canon imageCLASS MF5630", "MF5630", MF5630_PID, 1200, 636, 868, PIXMA_CAP_ADF), 851141cc406Sopenharmony_ci DEVICE ("Canon laserBase MF5650", "MF5650", MF5650_PID, 1200, 636, 868, PIXMA_CAP_ADF), 852141cc406Sopenharmony_ci DEVICE ("Canon imageCLASS MF5730", "MF5730", MF5730_PID, 1200, 636, 868, PIXMA_CAP_ADF), 853141cc406Sopenharmony_ci DEVICE ("Canon imageCLASS MF5750", "MF5750", MF5750_PID, 1200, 636, 868, PIXMA_CAP_ADF), 854141cc406Sopenharmony_ci DEVICE ("Canon imageCLASS MF5770", "MF5770", MF5770_PID, 1200, 636, 868, PIXMA_CAP_ADF), 855141cc406Sopenharmony_ci DEVICE ("Canon imageCLASS MF3110", "MF3110", MF3110_PID, 600, 636, 868, 0), 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci DEVICE ("Canon iR 1020/1024/1025", "iR1020", IR1020_PID, 600, 636, 868, PIXMA_CAP_ADFDUP), 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ci DEVICE (NULL, NULL, 0, 0, 0, 0, 0) 860141cc406Sopenharmony_ci}; 861