1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci ----- 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci This file is part of the canon_pp backend, supporting Canon CanoScan 42141cc406Sopenharmony_ci Parallel scanners and also distributed as part of the stand-alone driver. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci Low Level Function library for Canon CanoScan Parallel Scanners by 45141cc406Sopenharmony_ci Simon Krix <kinsei@users.sourceforge.net> 46141cc406Sopenharmony_ci */ 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#ifndef NOSANE 49141cc406Sopenharmony_ci#include "../include/sane/config.h" 50141cc406Sopenharmony_ci#endif 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#include <sys/time.h> 53141cc406Sopenharmony_ci#include <unistd.h> 54141cc406Sopenharmony_ci#include <ieee1284.h> 55141cc406Sopenharmony_ci#include "canon_pp-io.h" 56141cc406Sopenharmony_ci#include "canon_pp-dev.h" 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#ifdef NOSANE 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci/* No SANE, Things that only apply to stand-alone */ 61141cc406Sopenharmony_ci#include <stdio.h> 62141cc406Sopenharmony_ci#include <stdarg.h> 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_cistatic void DBG(int level, const char *format, ...) 65141cc406Sopenharmony_ci{ 66141cc406Sopenharmony_ci va_list args; 67141cc406Sopenharmony_ci va_start(args, format); 68141cc406Sopenharmony_ci if (level < 50) vfprintf(stderr, format, args); 69141cc406Sopenharmony_ci va_end(args); 70141cc406Sopenharmony_ci} 71141cc406Sopenharmony_ci#else 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci/* Fix problem with DBG macro definition having a - in the name */ 74141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 75141cc406Sopenharmony_ci#include "canon_pp.h" 76141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 77141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#endif 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci/* 0x00 = Nibble Mode (M1284_NIBBLE) 82141cc406Sopenharmony_ci 0x10 = ECP Mode (M1284_ECP) 83141cc406Sopenharmony_ci The scanner driver seems not to support ECP RLE mode 84141cc406Sopenharmony_ci (which is a huge bummer because compression would be 85141cc406Sopenharmony_ci ace) nor EPP mode. 86141cc406Sopenharmony_ci */ 87141cc406Sopenharmony_cistatic int ieee_mode = M1284_NIBBLE; 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci/* For super-verbose debugging */ 90141cc406Sopenharmony_ci/* #define DUMP_PACKETS 1 */ 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci/* Some sort of initialisation command */ 93141cc406Sopenharmony_cistatic unsigned char cmd_init[10] = { 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0 }; 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci/************* Local Prototypes ******************/ 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci/* Used by wake_scanner */ 98141cc406Sopenharmony_cistatic int scanner_reset(struct parport *port); 99141cc406Sopenharmony_cistatic void scanner_chessboard_control(struct parport *port); 100141cc406Sopenharmony_cistatic void scanner_chessboard_data(struct parport *port, int mode); 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci/* Used by read_data */ 103141cc406Sopenharmony_cistatic int ieee_transfer(struct parport *port, int length, 104141cc406Sopenharmony_ci unsigned char *data); 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/* Low level functions */ 107141cc406Sopenharmony_cistatic int readstatus(struct parport *port); 108141cc406Sopenharmony_cistatic int expect(struct parport *port, const char *step, int s, 109141cc406Sopenharmony_ci int mask, unsigned int delay); 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci/* Port-level functions */ 112141cc406Sopenharmony_cistatic void outdata(struct parport *port, int d); 113141cc406Sopenharmony_cistatic void outcont(struct parport *port, int d, int mask); 114141cc406Sopenharmony_cistatic void outboth(struct parport *port, int d, int c); 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci/************************************/ 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci/* 119141cc406Sopenharmony_ci * IEEE 1284 defines many values for m, 120141cc406Sopenharmony_ci * but these scanners only support 2: nibble and ECP modes. 121141cc406Sopenharmony_ci * And no data compression either (argh!) 122141cc406Sopenharmony_ci * 0 = Nibble-mode reverse channel transfer 123141cc406Sopenharmony_ci * 16 = ECP-mode 124141cc406Sopenharmony_ci */ 125141cc406Sopenharmony_civoid sanei_canon_pp_set_ieee1284_mode(int m) 126141cc406Sopenharmony_ci{ 127141cc406Sopenharmony_ci ieee_mode = m; 128141cc406Sopenharmony_ci} 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ciint sanei_canon_pp_wake_scanner(struct parport *port, int mode) 131141cc406Sopenharmony_ci{ 132141cc406Sopenharmony_ci /* The scanner tristates the printer's control lines 133141cc406Sopenharmony_ci (essentially disabling the passthrough port) and exits 134141cc406Sopenharmony_ci from Transparent Mode ready for communication. */ 135141cc406Sopenharmony_ci int i = 0; 136141cc406Sopenharmony_ci int tmp; 137141cc406Sopenharmony_ci int max_cycles = 3; 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci tmp = readstatus(port); 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci /* Reset only works on 30/40 models */ 142141cc406Sopenharmony_ci if (mode != INITMODE_20P) 143141cc406Sopenharmony_ci { 144141cc406Sopenharmony_ci if ((tmp != READY)) 145141cc406Sopenharmony_ci { 146141cc406Sopenharmony_ci DBG(40, "Scanner not ready (0x%x). Attempting to " 147141cc406Sopenharmony_ci "reset...\n", tmp); 148141cc406Sopenharmony_ci scanner_reset(port); 149141cc406Sopenharmony_ci /* give it more of a chance to reset in this case */ 150141cc406Sopenharmony_ci max_cycles = 5; 151141cc406Sopenharmony_ci } 152141cc406Sopenharmony_ci } else { 153141cc406Sopenharmony_ci DBG(0, "WARNING: Don't know how to reset an FBx20P, you may " 154141cc406Sopenharmony_ci "have to power cycle\n"); 155141cc406Sopenharmony_ci } 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci do 158141cc406Sopenharmony_ci { 159141cc406Sopenharmony_ci i++; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci /* Send the wakeup sequence */ 162141cc406Sopenharmony_ci scanner_chessboard_control(port); 163141cc406Sopenharmony_ci scanner_chessboard_data(port, mode); 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci if (expect(port, NULL, 0x03, 0x1f, 800000) && 166141cc406Sopenharmony_ci (mode == INITMODE_AUTO)) 167141cc406Sopenharmony_ci { 168141cc406Sopenharmony_ci /* 630 Style init failed, try 620 style */ 169141cc406Sopenharmony_ci scanner_chessboard_control(port); 170141cc406Sopenharmony_ci scanner_chessboard_data(port, INITMODE_20P); 171141cc406Sopenharmony_ci } 172141cc406Sopenharmony_ci 173141cc406Sopenharmony_ci if (expect(port, "Scanner wakeup reply 1", 0x03, 0x1f, 50000)) 174141cc406Sopenharmony_ci { 175141cc406Sopenharmony_ci outboth(port, 0x04, 0x0d); 176141cc406Sopenharmony_ci usleep(100000); 177141cc406Sopenharmony_ci outcont(port, 0x07, 0x0f); 178141cc406Sopenharmony_ci usleep(100000); 179141cc406Sopenharmony_ci } 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci } while ((i < max_cycles) && expect(port, "Scanner wakeup reply 2", 182141cc406Sopenharmony_ci 0x03, 0x1f, 100000)); 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci /* Block just after chessboarding 185141cc406Sopenharmony_ci Reply 1 (S3 and S4 on, S5 and S7 off) */ 186141cc406Sopenharmony_ci outcont(port, 0, HOSTBUSY); /* C1 off */ 187141cc406Sopenharmony_ci /* Reply 2 - If it ain't happening by now, it ain't gonna happen. */ 188141cc406Sopenharmony_ci if (expect(port, "Reply 2", 0xc, 0x1f, 800000)) 189141cc406Sopenharmony_ci return -1; 190141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); /* C1 on */ 191141cc406Sopenharmony_ci if (expect(port, "Reply 3", 0x0b, 0x1f, 800000)) 192141cc406Sopenharmony_ci return -1; 193141cc406Sopenharmony_ci outboth(port, 0, NSELECTIN | NINIT | HOSTCLK); /* Clear D, C3+, C1- */ 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci /* If we had to try the wakeup cycle more than once, we should wait 196141cc406Sopenharmony_ci * here for 10 seconds to let the scanner pull itself together - 197141cc406Sopenharmony_ci * it can actually take longer, but I can't wait that long! */ 198141cc406Sopenharmony_ci if (i > 1) 199141cc406Sopenharmony_ci { 200141cc406Sopenharmony_ci DBG(10, "Had to reset scanner, waiting for the " 201141cc406Sopenharmony_ci "head to get back.\n"); 202141cc406Sopenharmony_ci usleep(10000000); 203141cc406Sopenharmony_ci } 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci return 0; 206141cc406Sopenharmony_ci} 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ciint sanei_canon_pp_write(struct parport *port, int length, unsigned char *data) 210141cc406Sopenharmony_ci{ 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci#ifdef DUMP_PACKETS 213141cc406Sopenharmony_ci ssize_t count; 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_ci DBG(10,"Sending: "); 216141cc406Sopenharmony_ci for (count = 0; count < length; count++) 217141cc406Sopenharmony_ci { 218141cc406Sopenharmony_ci DBG(10,"%02x ", data[count]); 219141cc406Sopenharmony_ci if (count % 20 == 19) 220141cc406Sopenharmony_ci DBG(10,"\n "); 221141cc406Sopenharmony_ci } 222141cc406Sopenharmony_ci if (count % 20 != 19) DBG(10,"\n"); 223141cc406Sopenharmony_ci#endif 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci DBG(100, "NEW Send Command (length %i):\n", length); 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci switch (ieee_mode) 228141cc406Sopenharmony_ci { 229141cc406Sopenharmony_ci case M1284_BECP: 230141cc406Sopenharmony_ci case M1284_ECPRLE: 231141cc406Sopenharmony_ci case M1284_ECPSWE: 232141cc406Sopenharmony_ci case M1284_ECP: 233141cc406Sopenharmony_ci ieee1284_negotiate(port, ieee_mode); 234141cc406Sopenharmony_ci if (ieee1284_ecp_write_data(port, 0, (char *)data, 235141cc406Sopenharmony_ci length) != length) 236141cc406Sopenharmony_ci return -1; 237141cc406Sopenharmony_ci break; 238141cc406Sopenharmony_ci case M1284_NIBBLE: 239141cc406Sopenharmony_ci if (ieee1284_compat_write(port, 0, (char *)data, 240141cc406Sopenharmony_ci length) != length) 241141cc406Sopenharmony_ci return -1; 242141cc406Sopenharmony_ci break; 243141cc406Sopenharmony_ci default: 244141cc406Sopenharmony_ci DBG(0, "Invalid mode in write!\n"); 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci DBG(100, "<< write"); 248141cc406Sopenharmony_ci 249141cc406Sopenharmony_ci return 0; 250141cc406Sopenharmony_ci} 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ciint sanei_canon_pp_read(struct parport *port, int length, unsigned char *data) 253141cc406Sopenharmony_ci{ 254141cc406Sopenharmony_ci int count, offset; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci DBG(200, "NEW read_data (%i bytes):\n", length); 257141cc406Sopenharmony_ci ieee1284_negotiate(port, ieee_mode); 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci /* This is special; Nibble mode needs a little 260141cc406Sopenharmony_ci extra help from us. */ 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci if (ieee_mode == M1284_NIBBLE) 263141cc406Sopenharmony_ci { 264141cc406Sopenharmony_ci /* Interrupt phase */ 265141cc406Sopenharmony_ci outcont(port, NSELECTIN, HOSTBUSY | NSELECTIN); 266141cc406Sopenharmony_ci if (expect(port, "Read Data 1", 0, NDATAAVAIL, 6000000)) 267141cc406Sopenharmony_ci { 268141cc406Sopenharmony_ci DBG(10,"Error 1\n"); 269141cc406Sopenharmony_ci ieee1284_terminate(port); 270141cc406Sopenharmony_ci return 1; 271141cc406Sopenharmony_ci } 272141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci if (expect(port, "Read Data 2", NACK, NACK, 1000000)) 275141cc406Sopenharmony_ci { 276141cc406Sopenharmony_ci DBG(1,"Error 2\n"); 277141cc406Sopenharmony_ci ieee1284_terminate(port); 278141cc406Sopenharmony_ci return 1; 279141cc406Sopenharmony_ci } 280141cc406Sopenharmony_ci if (expect(port, "Read Data 3 (Ready?)", 0, PERROR, 1000000)) 281141cc406Sopenharmony_ci { 282141cc406Sopenharmony_ci DBG(1,"Error 3\n"); 283141cc406Sopenharmony_ci ieee1284_terminate(port); 284141cc406Sopenharmony_ci return 1; 285141cc406Sopenharmony_ci } 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci /* Host-Busy Data Available phase */ 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci if ((readstatus(port) & NDATAAVAIL) == NDATAAVAIL) 290141cc406Sopenharmony_ci { 291141cc406Sopenharmony_ci DBG(1,"No data to read.\n"); 292141cc406Sopenharmony_ci ieee1284_terminate(port); 293141cc406Sopenharmony_ci return 1; 294141cc406Sopenharmony_ci } 295141cc406Sopenharmony_ci } 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci offset = 0; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci DBG(100, "-> ieee_transfer(%d) *\n", length); 300141cc406Sopenharmony_ci count = ieee_transfer(port, length, data); 301141cc406Sopenharmony_ci DBG(100, "<- (%d)\n", count); 302141cc406Sopenharmony_ci /* Early-out if it was not implemented */ 303141cc406Sopenharmony_ci if (count == E1284_NOTIMPL) 304141cc406Sopenharmony_ci return 2; 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci length -= count; 307141cc406Sopenharmony_ci offset+= count; 308141cc406Sopenharmony_ci while (length > 0) 309141cc406Sopenharmony_ci { 310141cc406Sopenharmony_ci /* If 0 bytes were transferred, it's a legal 311141cc406Sopenharmony_ci "No data" condition (I think). Otherwise, 312141cc406Sopenharmony_ci it may have run out of buffer.. keep reading*/ 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ci if (count < 0) { 315141cc406Sopenharmony_ci DBG(10, "Couldn't read enough data (need %d more " 316141cc406Sopenharmony_ci "of %d)\n", length+count,length+offset); 317141cc406Sopenharmony_ci ieee1284_terminate(port); 318141cc406Sopenharmony_ci return 1; 319141cc406Sopenharmony_ci } 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci DBG(100, "-> ieee_transfer(%d)\n", length); 322141cc406Sopenharmony_ci count = ieee_transfer(port, length, data+offset); 323141cc406Sopenharmony_ci DBG(100, "<- (%d)\n", count); 324141cc406Sopenharmony_ci length-=count; 325141cc406Sopenharmony_ci offset+= count; 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci#ifdef DUMP_PACKETS 330141cc406Sopenharmony_ci if (length <= 60) 331141cc406Sopenharmony_ci { 332141cc406Sopenharmony_ci DBG(10,"Read: "); 333141cc406Sopenharmony_ci for (count = 0; count < length; count++) 334141cc406Sopenharmony_ci { 335141cc406Sopenharmony_ci DBG(10,"%02x ", data[count]); 336141cc406Sopenharmony_ci if (count % 20 == 19) 337141cc406Sopenharmony_ci DBG(10,"\n "); 338141cc406Sopenharmony_ci } 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci if (count % 20 != 19) DBG(10,"\n"); 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci else 343141cc406Sopenharmony_ci { 344141cc406Sopenharmony_ci DBG(10,"Read: %i bytes\n", length); 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci#endif 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci if (ieee_mode == M1284_NIBBLE) 349141cc406Sopenharmony_ci ieee1284_terminate(port); 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci return 0; 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci} 354141cc406Sopenharmony_ci 355141cc406Sopenharmony_cistatic int ieee_transfer(struct parport *port, int length, unsigned char *data) 356141cc406Sopenharmony_ci{ 357141cc406Sopenharmony_ci int result = 0; 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci DBG(100, "IEEE transfer (%i bytes)\n", length); 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci switch (ieee_mode) 362141cc406Sopenharmony_ci { 363141cc406Sopenharmony_ci case M1284_BECP: 364141cc406Sopenharmony_ci case M1284_ECP: 365141cc406Sopenharmony_ci case M1284_ECPRLE: 366141cc406Sopenharmony_ci case M1284_ECPSWE: 367141cc406Sopenharmony_ci result = ieee1284_ecp_read_data(port, 0, (char *)data, 368141cc406Sopenharmony_ci length); 369141cc406Sopenharmony_ci break; 370141cc406Sopenharmony_ci case M1284_NIBBLE: 371141cc406Sopenharmony_ci result = ieee1284_nibble_read(port, 0, (char *)data, 372141cc406Sopenharmony_ci length); 373141cc406Sopenharmony_ci break; 374141cc406Sopenharmony_ci default: 375141cc406Sopenharmony_ci DBG(1, "Internal error: Wrong mode for transfer.\n" 376141cc406Sopenharmony_ci "Please email stauff1@users.sourceforge.net\n" 377141cc406Sopenharmony_ci "or kinsei@users.sourceforge.net\n"); 378141cc406Sopenharmony_ci } 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci return result; 381141cc406Sopenharmony_ci} 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ciint sanei_canon_pp_check_status(struct parport *port) 384141cc406Sopenharmony_ci{ 385141cc406Sopenharmony_ci int status; 386141cc406Sopenharmony_ci unsigned char data[2]; 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci DBG(200, "* Check Status:\n"); 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci if (sanei_canon_pp_read(port, 2, data)) 391141cc406Sopenharmony_ci return -1; 392141cc406Sopenharmony_ci 393141cc406Sopenharmony_ci status = data[0] | (data[1] << 8); 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci switch(status) 396141cc406Sopenharmony_ci { 397141cc406Sopenharmony_ci case 0x0606: 398141cc406Sopenharmony_ci DBG(200, "Ready - 0x0606\n"); 399141cc406Sopenharmony_ci return 0; 400141cc406Sopenharmony_ci break; 401141cc406Sopenharmony_ci case 0x1414: 402141cc406Sopenharmony_ci DBG(200, "Busy - 0x1414\n"); 403141cc406Sopenharmony_ci return 1; 404141cc406Sopenharmony_ci break; 405141cc406Sopenharmony_ci case 0x0805: 406141cc406Sopenharmony_ci DBG(200, "Resetting - 0x0805\n"); 407141cc406Sopenharmony_ci return 3; 408141cc406Sopenharmony_ci break; 409141cc406Sopenharmony_ci case 0x1515: 410141cc406Sopenharmony_ci DBG(1, "!! Invalid Command - 0x1515\n"); 411141cc406Sopenharmony_ci return 2; 412141cc406Sopenharmony_ci break; 413141cc406Sopenharmony_ci case 0x0000: 414141cc406Sopenharmony_ci DBG(200, "Nothing - 0x0000"); 415141cc406Sopenharmony_ci return 4; 416141cc406Sopenharmony_ci break; 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci default: 419141cc406Sopenharmony_ci DBG(1, "!! Unknown status - %04x\n", status); 420141cc406Sopenharmony_ci return 100; 421141cc406Sopenharmony_ci } 422141cc406Sopenharmony_ci} 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci/* Send a raw byte to the printer port */ 426141cc406Sopenharmony_cistatic void outdata(struct parport *port, int d) 427141cc406Sopenharmony_ci{ 428141cc406Sopenharmony_ci ieee1284_write_data(port, d & 0xff); 429141cc406Sopenharmony_ci} 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci/* Send the low nibble of d to the control port. 432141cc406Sopenharmony_ci The mask affects which bits are changed. */ 433141cc406Sopenharmony_cistatic void outcont(struct parport *port, int d, int mask) 434141cc406Sopenharmony_ci{ 435141cc406Sopenharmony_ci static int control_port_status = 0; 436141cc406Sopenharmony_ci control_port_status = (control_port_status & ~mask) | (d & mask); 437141cc406Sopenharmony_ci ieee1284_write_control(port, (control_port_status & 0x0f)); 438141cc406Sopenharmony_ci} 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci/* Send a byte to both ports */ 441141cc406Sopenharmony_cistatic void outboth(struct parport *port, int d, int c) 442141cc406Sopenharmony_ci{ 443141cc406Sopenharmony_ci ieee1284_write_data(port, d & 0xff); 444141cc406Sopenharmony_ci outcont(port, c, 0x0f); 445141cc406Sopenharmony_ci} 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci/* readstatus(): 448141cc406Sopenharmony_ci Returns the LOGIC value of the S register (ie: all input lines) 449141cc406Sopenharmony_ci shifted right to to make it easier to read. Note: S5 is inverted 450141cc406Sopenharmony_ci by ieee1284_read_status so we don't need to */ 451141cc406Sopenharmony_cistatic int readstatus(struct parport *port) 452141cc406Sopenharmony_ci{ 453141cc406Sopenharmony_ci return (ieee1284_read_status(port) & 0xf8) >> 3; 454141cc406Sopenharmony_ci} 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_cistatic void scanner_chessboard_control(struct parport *port) 457141cc406Sopenharmony_ci{ 458141cc406Sopenharmony_ci /* Wiggle C1 and C3 (twice) */ 459141cc406Sopenharmony_ci outboth(port, 0x0, 13); 460141cc406Sopenharmony_ci usleep(10); 461141cc406Sopenharmony_ci outcont(port, 7, 0xf); 462141cc406Sopenharmony_ci usleep(10); 463141cc406Sopenharmony_ci outcont(port, 13, 0xf); 464141cc406Sopenharmony_ci usleep(10); 465141cc406Sopenharmony_ci outcont(port, 7, 0xf); 466141cc406Sopenharmony_ci usleep(10); 467141cc406Sopenharmony_ci} 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_cistatic void scanner_chessboard_data(struct parport *port, int mode) 470141cc406Sopenharmony_ci{ 471141cc406Sopenharmony_ci int count; 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci /* initial weirdness here for 620P - seems to go quite fast, 474141cc406Sopenharmony_ci * just ignore it! */ 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci for (count = 0; count < 2; count++) 477141cc406Sopenharmony_ci { 478141cc406Sopenharmony_ci /* Wiggle data lines (4 times) while strobing C1 */ 479141cc406Sopenharmony_ci /* 33 here for *30P, 55 for *20P */ 480141cc406Sopenharmony_ci if (mode == INITMODE_20P) 481141cc406Sopenharmony_ci outdata(port, 0x55); 482141cc406Sopenharmony_ci else 483141cc406Sopenharmony_ci outdata(port, 0x33); 484141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); 485141cc406Sopenharmony_ci usleep(10); 486141cc406Sopenharmony_ci outcont(port, 0, HOSTBUSY); 487141cc406Sopenharmony_ci usleep(10); 488141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); 489141cc406Sopenharmony_ci usleep(10); 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci if (mode == INITMODE_20P) 492141cc406Sopenharmony_ci outdata(port, 0xaa); 493141cc406Sopenharmony_ci else 494141cc406Sopenharmony_ci outdata(port, 0xcc); 495141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); 496141cc406Sopenharmony_ci usleep(10); 497141cc406Sopenharmony_ci outcont(port, 0, HOSTBUSY); 498141cc406Sopenharmony_ci usleep(10); 499141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY); 500141cc406Sopenharmony_ci usleep(10); 501141cc406Sopenharmony_ci } 502141cc406Sopenharmony_ci} 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci/* Reset the scanner. At least, it works 50% of the time. */ 505141cc406Sopenharmony_cistatic int scanner_reset(struct parport *port) 506141cc406Sopenharmony_ci{ 507141cc406Sopenharmony_ci 508141cc406Sopenharmony_ci /* Resetting only works for the *30Ps, sorry */ 509141cc406Sopenharmony_ci if (readstatus(port) == 0x0b) 510141cc406Sopenharmony_ci { 511141cc406Sopenharmony_ci /* Init Block 1 - composed of a 0-byte IEEE read */ 512141cc406Sopenharmony_ci ieee1284_negotiate(port, 0x0); 513141cc406Sopenharmony_ci ieee1284_terminate(port); 514141cc406Sopenharmony_ci ieee1284_negotiate(port, 0x0); 515141cc406Sopenharmony_ci ieee1284_terminate(port); 516141cc406Sopenharmony_ci scanner_chessboard_data(port, 1); 517141cc406Sopenharmony_ci scanner_chessboard_data(port, 1); 518141cc406Sopenharmony_ci scanner_chessboard_data(port, 1); 519141cc406Sopenharmony_ci scanner_chessboard_data(port, 1); 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci scanner_chessboard_data(port, 0); 522141cc406Sopenharmony_ci scanner_chessboard_data(port, 0); 523141cc406Sopenharmony_ci scanner_chessboard_data(port, 0); 524141cc406Sopenharmony_ci scanner_chessboard_data(port, 0); 525141cc406Sopenharmony_ci } 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci /* Reset Block 2 =============== */ 528141cc406Sopenharmony_ci outboth(port, 0x04, 0x0d); 529141cc406Sopenharmony_ci 530141cc406Sopenharmony_ci /* Specifically, we want this: 00111 on S */ 531141cc406Sopenharmony_ci if (expect(port, "Reset 2 response 1", 0x7, 0x1f, 500000)) 532141cc406Sopenharmony_ci return 1; 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci outcont(port, 0, HOSTCLK); 535141cc406Sopenharmony_ci usleep(5); 536141cc406Sopenharmony_ci outcont(port, 0x0f, 0xf); /* All lines must be 1. */ 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci /* All lines 1 */ 539141cc406Sopenharmony_ci if (expect(port, "Reset 2 response 2 (READY)", 540141cc406Sopenharmony_ci 0x1f, 0x1f, 500000)) 541141cc406Sopenharmony_ci return 1; 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci outcont(port, 0, HOSTBUSY); 544141cc406Sopenharmony_ci usleep(100000); /* a short pause */ 545141cc406Sopenharmony_ci outcont(port, HOSTBUSY, HOSTBUSY | NSELECTIN); 546141cc406Sopenharmony_ci 547141cc406Sopenharmony_ci return 0; 548141cc406Sopenharmony_ci} 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci/* A timed version of expect, which will wait for delay before erroring 551141cc406Sopenharmony_ci This is the one and only one we should be using */ 552141cc406Sopenharmony_cistatic int expect(struct parport *port, const char *msg, int s, 553141cc406Sopenharmony_ci int mask, unsigned int delay) 554141cc406Sopenharmony_ci{ 555141cc406Sopenharmony_ci struct timeval tv; 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci tv.tv_sec = delay / 1000000; 558141cc406Sopenharmony_ci tv.tv_usec = delay % 1000000; 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_ci if (ieee1284_wait_status(port, mask << 3, s << 3, &tv)) 561141cc406Sopenharmony_ci { 562141cc406Sopenharmony_ci if (msg) DBG(10, "Timeout: %s (0x%02x in 0x%02x) - Status " 563141cc406Sopenharmony_ci "= 0x%02x\n", msg, s, mask, readstatus(port)); 564141cc406Sopenharmony_ci return 1; 565141cc406Sopenharmony_ci } 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci return 0; 568141cc406Sopenharmony_ci} 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ciint sanei_canon_pp_scanner_init(struct parport *port) 571141cc406Sopenharmony_ci{ 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci int tries = 0; 574141cc406Sopenharmony_ci int tmp = 0; 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci /* Put the scanner in nibble mode */ 577141cc406Sopenharmony_ci ieee1284_negotiate(port, 0x0); 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci /* No data to read yet - return to idle mode */ 580141cc406Sopenharmony_ci ieee1284_terminate(port); 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci /* In Windows, this is always ECP (or an attempt at it) */ 583141cc406Sopenharmony_ci if (sanei_canon_pp_write(port, 10, cmd_init)) 584141cc406Sopenharmony_ci return -1; 585141cc406Sopenharmony_ci /* Note that we don't really mind what the status was as long as it 586141cc406Sopenharmony_ci * wasn't a read error (returns -1) */ 587141cc406Sopenharmony_ci /* In fact, the 620P gives an error on that last command, but they 588141cc406Sopenharmony_ci * keep going anyway */ 589141cc406Sopenharmony_ci if (sanei_canon_pp_check_status(port) < 0) 590141cc406Sopenharmony_ci return -1; 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci /* Try until it's ready */ 593141cc406Sopenharmony_ci sanei_canon_pp_write(port, 10, cmd_init); 594141cc406Sopenharmony_ci while ((tries < 3) && (tmp = sanei_canon_pp_check_status(port))) 595141cc406Sopenharmony_ci { 596141cc406Sopenharmony_ci if (tmp < 0) 597141cc406Sopenharmony_ci return -1; 598141cc406Sopenharmony_ci DBG(10, "scanner_init: Giving the scanner a snooze...\n"); 599141cc406Sopenharmony_ci usleep(500000); 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci tries++; 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci sanei_canon_pp_write(port, 10, cmd_init); 604141cc406Sopenharmony_ci } 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci if (tries == 3) return 1; 607141cc406Sopenharmony_ci 608141cc406Sopenharmony_ci return 0; 609141cc406Sopenharmony_ci} 610