1/* lexmark-low.c: scanner-interface file for low Lexmark scanners. 2 3 (C) 2005 Fred Odendaal 4 (C) 2006-2013 Stéphane Voltz <stef.dev@free.fr> 5 (C) 2010 "Torsten Houwaart" <ToHo@gmx.de> X74 support 6 7 This file is part of the SANE package. 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <https://www.gnu.org/licenses/>. 21 22 As a special exception, the authors of SANE give permission for 23 additional uses of the libraries contained in this release of SANE. 24 25 The exception is that, if you link a SANE library with other files 26 to produce an executable, this does not by itself cause the 27 resulting executable to be covered by the GNU General Public 28 License. Your use of that executable is in no way restricted on 29 account of linking the SANE library code into it. 30 31 This exception does not, however, invalidate any other reasons why 32 the executable file might be covered by the GNU General Public 33 License. 34 35 If you submit changes to SANE to the maintainers to be included in 36 a subsequent release, you agree by submitting the changes that 37 those changes may be distributed with this exception intact. 38 39 If you write modifications of your own for SANE, it is your choice 40 whether to permit this exception to apply to your modifications. 41 If you do not wish that, delete this exception notice. 42 43 **************************************************************************/ 44 45#undef BACKEND_NAME 46#define BACKEND_NAME lexmark_low 47 48#include "lexmark.h" 49 50#include "lexmark_sensors.c" 51#include "lexmark_models.c" 52 53/* numbre of ranges for offset */ 54#define OFFSET_RANGES 5 55 56typedef enum 57{ 58 black = 0, 59 white 60} 61region_type; 62 63#define HomeTolerance 32 64 65 66#define LOBYTE(x) ((uint8_t)((x) & 0xFF)) 67#define HIBYTE(x) ((uint8_t)((x) >> 8)) 68 69/* Static low function proto-types */ 70static SANE_Status low_usb_bulk_write (SANE_Int devnum, 71 SANE_Byte * cmd, size_t * size); 72static SANE_Status low_usb_bulk_read (SANE_Int devnum, 73 SANE_Byte * buf, size_t * size); 74static SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs); 75static SANE_Bool low_is_home_line (Lexmark_Device * dev, 76 unsigned char *buffer); 77static SANE_Status low_get_start_loc (SANE_Int resolution, 78 SANE_Int * vert_start, 79 SANE_Int * hor_start, SANE_Int offset, 80 Lexmark_Device * dev); 81static void low_rewind (Lexmark_Device * dev, SANE_Byte * regs); 82static SANE_Status low_start_mvmt (SANE_Int devnum); 83static SANE_Status low_stop_mvmt (SANE_Int devnum); 84static SANE_Status low_clr_c6 (SANE_Int devnum); 85static SANE_Status low_simple_scan (Lexmark_Device * dev, 86 SANE_Byte * regs, 87 int xoffset, 88 int pixels, 89 int yoffset, 90 int lines, SANE_Byte ** data); 91static void low_set_scan_area (SANE_Int res, 92 SANE_Int tlx, 93 SANE_Int tly, 94 SANE_Int brx, 95 SANE_Int bry, 96 SANE_Int offset, 97 SANE_Bool half_step, 98 SANE_Byte * regs, Lexmark_Device * dev); 99 100/* Static Read Buffer Proto-types */ 101static SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline); 102static SANE_Status read_buffer_free (Read_Buffer * rb); 103static size_t read_buffer_bytes_available (Read_Buffer * rb); 104static SANE_Status read_buffer_add_byte (Read_Buffer * rb, 105 SANE_Byte * byte_pointer); 106static SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb, 107 SANE_Byte * byte_pointer); 108static SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb, 109 SANE_Byte * byte_pointer, 110 SANE_Byte threshold); 111static size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, 112 size_t rqst_size); 113static SANE_Bool read_buffer_is_empty (Read_Buffer * rb); 114 115 116/* 117 * RTS88XX START 118 * 119 * these rts88xx functions will be spin off in a separate lib 120 * so that they can be reused. 121 */ 122 123/* 124 * registers helpers to avoid direct access 125 */ 126static SANE_Bool 127rts88xx_is_color (SANE_Byte * regs) 128{ 129 if ((regs[0x2f] & 0x11) == 0x11) 130 return SANE_TRUE; 131 return SANE_FALSE; 132} 133 134static void 135rts88xx_set_gray_scan (SANE_Byte * regs) 136{ 137 regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20; 138} 139 140#if 0 141static void 142rts88xx_set_color_scan (SANE_Byte * regs) 143{ 144 regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10; 145} 146#endif 147 148static void 149rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, 150 SANE_Byte blue) 151{ 152 /* offset for odd pixels */ 153 regs[0x02] = red; 154 regs[0x03] = green; 155 regs[0x04] = blue; 156 157 /* offset for even pixels */ 158 regs[0x05] = red; 159 regs[0x06] = green; 160 regs[0x07] = blue; 161} 162 163static void 164rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, 165 SANE_Byte blue) 166{ 167 regs[0x08] = red; 168 regs[0x09] = green; 169 regs[0x0a] = blue; 170} 171 172/* set # of head moves per CIS read */ 173static int 174rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency) 175{ 176 regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f); 177 return 0; 178} 179 180/* 181 * read one register at given index 182 */ 183static SANE_Status 184rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) 185{ 186 SANE_Status status = SANE_STATUS_GOOD; 187 unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 }; 188 size_t size; 189 190 cmd[1] = index; 191 192 size = 4; 193#ifdef FAKE_USB 194 status = SANE_STATUS_GOOD; 195#else 196 status = sanei_usb_write_bulk (devnum, cmd, &size); 197#endif 198 if (status != SANE_STATUS_GOOD) 199 { 200 DBG (5, "rts88xx_read_reg: bulk write failed\n"); 201 return status; 202 } 203 size = 1; 204#ifdef FAKE_USB 205 status = SANE_STATUS_GOOD; 206#else 207 status = sanei_usb_read_bulk (devnum, reg, &size); 208#endif 209 if (status != SANE_STATUS_GOOD) 210 { 211 DBG (5, "rts88xx_read_reg: bulk read failed\n"); 212 return status; 213 } 214 DBG (15, "rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg); 215 return status; 216} 217 218/* 219 * write one register at given index 220 */ 221static SANE_Status 222rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) 223{ 224 SANE_Status status = SANE_STATUS_GOOD; 225 unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01 }; 226 size_t size; 227 228 cmd[1] = index; 229 230 size = 4; 231#ifdef FAKE_USB 232 status = SANE_STATUS_GOOD; 233#else 234 status = sanei_usb_write_bulk (devnum, cmd, &size); 235#endif 236 if (status != SANE_STATUS_GOOD) 237 { 238 DBG (5, "rts88xx_write_reg: bulk write failed\n"); 239 return status; 240 } 241 size = 1; 242#ifdef FAKE_USB 243 status = SANE_STATUS_GOOD; 244#else 245 status = sanei_usb_write_bulk (devnum, reg, &size); 246#endif 247 if (status != SANE_STATUS_GOOD) 248 { 249 DBG (5, "rts88xx_write_reg: bulk write failed\n"); 250 return status; 251 } 252 DBG (15, "rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg); 253 return status; 254} 255 256/* 257 * write length consecutive registers, starting at index 258 * register 0xb3 is never wrote in bulk register write, so we split 259 * write if it belongs to the register set sent 260 */ 261static SANE_Status 262rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source, 263 SANE_Int length) 264{ 265 size_t size = 0; 266 267 /* when writing several registers at a time, we avoid writing 0xb3 268 register */ 269 if ((start + length > 0xb3) && (length > 1)) 270 { 271 size = 0xb3 - start; 272 if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD) 273 { 274 DBG (5, "rts88xx_write_regs : write registers part 1 failed ...\n"); 275 return SANE_STATUS_IO_ERROR; 276 } 277 278 /* skip 0xB3 register */ 279 size++; 280 start = 0xb4; 281 source = source + size; 282 } 283 size = length - size; 284 if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD) 285 { 286 DBG (5, "rts88xx_write_regs : write registers part 2 failed ...\n"); 287 return SANE_STATUS_IO_ERROR; 288 } 289 290 return SANE_STATUS_GOOD; 291 292} 293 294/* 295 * reads 'needed' bytes of scanned data into 'data'. Actual number of bytes get 296 * is returned in 'size' 297 */ 298static SANE_Status 299rts88xx_read_data (SANE_Int devnum, size_t needed, SANE_Byte * data, 300 size_t * size) 301{ 302 SANE_Byte read_cmd[] = { 0x91, 0x00, 0x00, 0x00 }; 303 size_t cmd_size; 304 SANE_Status status = SANE_STATUS_GOOD; 305 306 /* this block would deserve to be a function */ 307 if (needed > MAX_XFER_SIZE) 308 *size = MAX_XFER_SIZE; 309 else 310 *size = needed; 311 read_cmd[3] = (*size) & 0xff; 312 read_cmd[2] = (*size >> 8) & 0xff; 313 read_cmd[1] = (*size >> 16) & 0xff; 314 315 /* send header for 'get scanned data' */ 316 cmd_size = 4; 317 status = low_usb_bulk_write (devnum, read_cmd, &cmd_size); 318 if (status != SANE_STATUS_GOOD) 319 { 320 *size = 0; 321 DBG (5, "rts88xx_read_data : header sending failed ...\n"); 322 return status; 323 } 324 /* get actual scanned data */ 325 status = low_usb_bulk_read (devnum, data, size); 326 if (status != SANE_STATUS_GOOD) 327 { 328 *size = 0; 329 DBG (5, "rts88xx_read_data : data reading failed ...\n"); 330 } 331 return status; 332} 333 334/* starts scan by sending color depth, stopping head, the starting it */ 335static SANE_Status 336rts88xx_commit (SANE_Int devnum, SANE_Byte depth) 337{ 338 SANE_Status status; 339 SANE_Byte reg; 340 341 DBG (2, "rts88xx_commit: start\n"); 342 343 /* send color depth depth ?? 344 * X1100 -> 0x0f 345 * X1100/B2 -> 0x0d 346 * X1200 -> 0x01 */ 347 reg = depth; 348 rts88xx_write_reg (devnum, 0x2c, ®); 349 350 /* stop before starting */ 351 low_stop_mvmt (devnum); 352 353 /* effective start */ 354 status = low_start_mvmt (devnum); 355 356 DBG (2, "rts88xx_commit: end\n"); 357 358 return status; 359} 360 361/* 362 * RTS88XX END 363 */ 364 365 366 367/* 368 * sets the scanner idle 369 */ 370static SANE_Status 371lexmark_low_set_idle (SANE_Int devnum) 372{ 373 SANE_Byte regs[14] = 374 { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 375 0x00, 0x60 376 }; 377 if (rts88xx_write_regs (devnum, 16, regs, 14) != SANE_STATUS_GOOD) 378 { 379 DBG (5, "lexmark_low_set_idle : register write failed ...\n"); 380 return SANE_STATUS_IO_ERROR; 381 } 382 return SANE_STATUS_GOOD; 383} 384 385 386/* wake up scanner */ 387#if 0 388static SANE_Status 389lexmark_low_wake_up (Lexmark_Device * dev) 390{ 391 SANE_Byte regs[5] = { 0x12, 0x14, 0x16, 0x18, 0x1a }; 392 SANE_Byte values[5] = { 0x0f, 0x00, 0x07, 0x00, 0x00 }; 393 int i; 394 395 /* send the wake-up sequence, one reg at at time */ 396 for (i = 0; i < 10; i++) 397 { 398 if (rts88xx_write_reg (dev->devnum, regs[i], values + i) != 399 SANE_STATUS_GOOD) 400 { 401 DBG (5, 402 "lexmark_low_wake_up : register write pass %d failed ...\n", 403 i); 404 return SANE_STATUS_IO_ERROR; 405 } 406 } 407 return SANE_STATUS_GOOD; 408} 409#endif 410 411 412/** 413 * 414 */ 415#ifdef DEEP_DEBUG 416static void 417write_pnm_file (char *title, int pixels, int lines, int color, 418 unsigned char *data) 419{ 420 FILE *fdbg; 421 int x, y; 422 423 fdbg = fopen (title, "wb"); 424 if (fdbg == NULL) 425 return; 426 427 if (color) 428 { 429 fprintf (fdbg, "P6\n%d %d\n255\n", pixels, lines); 430 for (y = 0; y < lines; y++) 431 { 432 for (x = 0; x < pixels; x += 2) 433 { 434 fputc (data[y * pixels * 3 + x + 1], fdbg); 435 fputc (data[y * pixels * 3 + x + 1 + pixels], fdbg); 436 fputc (data[y * pixels * 3 + x + 1 + pixels * 2], fdbg); 437 fputc (data[y * pixels * 3 + x], fdbg); 438 fputc (data[y * pixels * 3 + x + pixels], fdbg); 439 fputc (data[y * pixels * 3 + x + pixels * 2], fdbg); 440 } 441 } 442 } 443 else 444 { 445 fprintf (fdbg, "P5\n%d %d\n255\n", pixels, lines); 446 fwrite (data, pixels, lines, fdbg); 447 } 448 fclose (fdbg); 449} 450#endif 451 452/* 453 * mid level hardware functions 454 */ 455/* 456 * model init 457 */ 458SANE_Status 459sanei_lexmark_low_init (Lexmark_Device * dev) 460{ 461 int i; 462 SANE_Status status; 463 464 DBG_INIT (); 465 466 status = SANE_STATUS_UNSUPPORTED; 467 DBG (2, "low_init: start\n"); 468 469 /* clear all registers first */ 470 for (i = 0; i < 255; i++) 471 { 472 dev->shadow_regs[i] = 0; 473 } 474 475 /* set up per model constant values */ 476 dev->shadow_regs[0xf3] = 0xf8; 477 dev->shadow_regs[0xf4] = 0x7f; 478 479 switch (dev->model.sensor_type) 480 { 481 case X74_SENSOR: 482 dev->shadow_regs[0x00] = 0x04; 483 dev->shadow_regs[0x01] = 0x43; 484 dev->shadow_regs[0x0b] = 0x70; 485 dev->shadow_regs[0x12] = 0x0f; 486 dev->shadow_regs[0x16] = 0x07; 487 dev->shadow_regs[0x1d] = 0x20; 488 dev->shadow_regs[0x28] = 0xe0; 489 dev->shadow_regs[0x29] = 0xe3; 490 dev->shadow_regs[0x2a] = 0xeb; 491 dev->shadow_regs[0x2b] = 0x0d; 492 dev->shadow_regs[0x2e] = 0x40; 493 dev->shadow_regs[0x2e] = 0x86; 494 dev->shadow_regs[0x2f] = 0x01; 495 dev->shadow_regs[0x30] = 0x48; 496 dev->shadow_regs[0x31] = 0x06; 497 dev->shadow_regs[0x33] = 0x01; 498 dev->shadow_regs[0x34] = 0x50; 499 dev->shadow_regs[0x35] = 0x01; 500 dev->shadow_regs[0x36] = 0x50; 501 dev->shadow_regs[0x37] = 0x01; 502 dev->shadow_regs[0x38] = 0x50; 503 dev->shadow_regs[0x3a] = 0x20; 504 dev->shadow_regs[0x3c] = 0x88; 505 dev->shadow_regs[0x3d] = 0x08; 506 dev->shadow_regs[0x65] = 0x80; 507 dev->shadow_regs[0x66] = 0x64; 508 dev->shadow_regs[0x6c] = 0xc8; 509 dev->shadow_regs[0x72] = 0x1a; 510 dev->shadow_regs[0x74] = 0x23; 511 dev->shadow_regs[0x75] = 0x03; 512 dev->shadow_regs[0x79] = 0x40; 513 dev->shadow_regs[0x7A] = 0x01; 514 dev->shadow_regs[0x8d] = 0x01; 515 dev->shadow_regs[0x8e] = 0x60; 516 dev->shadow_regs[0x8f] = 0x80; 517 dev->shadow_regs[0x93] = 0x02; 518 dev->shadow_regs[0x94] = 0x0e; 519 dev->shadow_regs[0xa3] = 0xcc; 520 dev->shadow_regs[0xa4] = 0x27; 521 dev->shadow_regs[0xa5] = 0x24; 522 dev->shadow_regs[0xc2] = 0x80; 523 dev->shadow_regs[0xc3] = 0x01; 524 dev->shadow_regs[0xc4] = 0x20; 525 dev->shadow_regs[0xc5] = 0x0a; 526 dev->shadow_regs[0xc8] = 0x04; 527 dev->shadow_regs[0xc9] = 0x39; 528 dev->shadow_regs[0xca] = 0x0a; 529 dev->shadow_regs[0xe2] = 0x70; 530 dev->shadow_regs[0xe3] = 0x17; 531 dev->shadow_regs[0xf3] = 0xe0; 532 dev->shadow_regs[0xf4] = 0xff; 533 dev->shadow_regs[0xf5] = 0x01; 534 status = SANE_STATUS_GOOD; 535 break; 536 case X1100_B2_SENSOR: 537 dev->shadow_regs[0x01] = 0x43; 538 dev->shadow_regs[0x0b] = 0x70; 539 dev->shadow_regs[0x11] = 0x01; 540 dev->shadow_regs[0x12] = 0x0f; 541 dev->shadow_regs[0x13] = 0x01; 542 dev->shadow_regs[0x15] = 0x01; 543 dev->shadow_regs[0x16] = 0x0f; 544 dev->shadow_regs[0x1d] = 0x20; 545 dev->shadow_regs[0x28] = 0xeb; 546 dev->shadow_regs[0x29] = 0xee; 547 dev->shadow_regs[0x2a] = 0xf7; 548 dev->shadow_regs[0x2b] = 0x01; 549 dev->shadow_regs[0x2e] = 0x86; 550 dev->shadow_regs[0x30] = 0x48; 551 dev->shadow_regs[0x33] = 0x01; 552 dev->shadow_regs[0x3a] = 0x20; 553 dev->shadow_regs[0x3b] = 0x37; 554 dev->shadow_regs[0x3c] = 0x88; 555 dev->shadow_regs[0x3d] = 0x08; 556 dev->shadow_regs[0x40] = 0x80; 557 dev->shadow_regs[0x72] = 0x05; 558 dev->shadow_regs[0x74] = 0x0e; 559 dev->shadow_regs[0x8b] = 0xff; 560 dev->shadow_regs[0x8c] = 0x02; 561 dev->shadow_regs[0x8d] = 0x01; 562 dev->shadow_regs[0x8e] = 0x60; 563 dev->shadow_regs[0x8f] = 0x80; 564 dev->shadow_regs[0x94] = 0x0e; 565 dev->shadow_regs[0xa3] = 0xcc; 566 dev->shadow_regs[0xa4] = 0x27; 567 dev->shadow_regs[0xa5] = 0x24; 568 dev->shadow_regs[0xb0] = 0xb2; 569 dev->shadow_regs[0xb2] = 0x04; 570 dev->shadow_regs[0xc2] = 0x80; 571 dev->shadow_regs[0xc4] = 0x20; 572 dev->shadow_regs[0xc8] = 0x04; 573 dev->shadow_regs[0xc9] = 0x3b; 574 dev->shadow_regs[0xed] = 0xc2; 575 dev->shadow_regs[0xee] = 0x02; 576 status = SANE_STATUS_GOOD; 577 break; 578 case X1100_2C_SENSOR: 579 dev->shadow_regs[0x00] = 0x00; 580 dev->shadow_regs[0x01] = 0x43; 581 dev->shadow_regs[0x0b] = 0x70; 582 dev->shadow_regs[0x0c] = 0x28; 583 dev->shadow_regs[0x0d] = 0xa4; 584 dev->shadow_regs[0x11] = 0x01; 585 dev->shadow_regs[0x12] = 0x0f; 586 dev->shadow_regs[0x13] = 0x01; 587 dev->shadow_regs[0x15] = 0x01; 588 dev->shadow_regs[0x16] = 0x0f; 589 dev->shadow_regs[0x17] = 0x00; 590 dev->shadow_regs[0x1d] = 0x20; 591 dev->shadow_regs[0x28] = 0xf5; 592 dev->shadow_regs[0x29] = 0xf7; 593 dev->shadow_regs[0x2a] = 0xf5; 594 dev->shadow_regs[0x2b] = 0x17; 595 dev->shadow_regs[0x2d] = 0x41; 596 dev->shadow_regs[0x2e] = 0x86; 597 dev->shadow_regs[0x2f] = 0x11; 598 dev->shadow_regs[0x30] = 0x48; 599 dev->shadow_regs[0x31] = 0x01; 600 dev->shadow_regs[0x33] = 0x01; 601 dev->shadow_regs[0x34] = 0x50; 602 dev->shadow_regs[0x35] = 0x01; 603 dev->shadow_regs[0x36] = 0x50; 604 dev->shadow_regs[0x37] = 0x01; 605 dev->shadow_regs[0x38] = 0x50; 606 dev->shadow_regs[0x3a] = 0x20; 607 dev->shadow_regs[0x3b] = 0x37; 608 dev->shadow_regs[0x3c] = 0x88; 609 dev->shadow_regs[0x3d] = 0x08; 610 dev->shadow_regs[0x40] = 0x80; 611 dev->shadow_regs[0x47] = 0x01; 612 dev->shadow_regs[0x48] = 0x1a; 613 dev->shadow_regs[0x49] = 0x5b; 614 dev->shadow_regs[0x4a] = 0x1b; 615 dev->shadow_regs[0x4b] = 0x5b; 616 dev->shadow_regs[0x4c] = 0x05; 617 dev->shadow_regs[0x4d] = 0x3f; 618 dev->shadow_regs[0x60] = 0x2f; 619 dev->shadow_regs[0x61] = 0x36; 620 dev->shadow_regs[0x62] = 0x30; 621 dev->shadow_regs[0x63] = 0x36; 622 dev->shadow_regs[0x65] = 0x80; 623 dev->shadow_regs[0x66] = 0x64; 624 dev->shadow_regs[0x6c] = 0xc8; 625 dev->shadow_regs[0x6d] = 0x00; 626 dev->shadow_regs[0x72] = 0x35; 627 dev->shadow_regs[0x74] = 0x4e; 628 dev->shadow_regs[0x75] = 0x03; 629 dev->shadow_regs[0x79] = 0x40; 630 dev->shadow_regs[0x7a] = 0x01; 631 dev->shadow_regs[0x85] = 0x02; 632 dev->shadow_regs[0x86] = 0x33; 633 dev->shadow_regs[0x87] = 0x0f; 634 dev->shadow_regs[0x88] = 0x24; 635 dev->shadow_regs[0x8b] = 0xff; 636 dev->shadow_regs[0x8c] = 0x02; 637 dev->shadow_regs[0x8d] = 0x01; 638 dev->shadow_regs[0x8e] = 0x60; 639 dev->shadow_regs[0x8f] = 0x80; 640 dev->shadow_regs[0x91] = 0x19; 641 dev->shadow_regs[0x92] = 0x20; 642 dev->shadow_regs[0x93] = 0x02; 643 dev->shadow_regs[0x94] = 0x0e; 644 dev->shadow_regs[0xa3] = 0x0d; 645 dev->shadow_regs[0xa4] = 0x5e; 646 dev->shadow_regs[0xa5] = 0x23; 647 dev->shadow_regs[0xb0] = 0x2c; 648 dev->shadow_regs[0xb1] = 0x07; 649 dev->shadow_regs[0xb2] = 0x04; 650 dev->shadow_regs[0xc2] = 0x80; 651 dev->shadow_regs[0xc3] = 0x01; 652 dev->shadow_regs[0xc4] = 0x20; 653 dev->shadow_regs[0xc5] = 0x0a; 654 dev->shadow_regs[0xc8] = 0x04; 655 dev->shadow_regs[0xc9] = 0x3b; 656 dev->shadow_regs[0xca] = 0x0a; 657 dev->shadow_regs[0xe2] = 0xf8; 658 dev->shadow_regs[0xe3] = 0x2a; 659 status = SANE_STATUS_GOOD; 660 break; 661 case X1200_USB2_SENSOR: 662 dev->shadow_regs[0x01] = 0x43; 663 dev->shadow_regs[0x11] = 0x01; 664 dev->shadow_regs[0x12] = 0x0f; 665 dev->shadow_regs[0x13] = 0x01; 666 dev->shadow_regs[0x15] = 0x01; 667 dev->shadow_regs[0x16] = 0x0f; 668 dev->shadow_regs[0x17] = 0x00; 669 dev->shadow_regs[0x1d] = 0x20; 670 dev->shadow_regs[0x28] = 0xf5; 671 dev->shadow_regs[0x29] = 0xf7; 672 dev->shadow_regs[0x2a] = 0xf5; 673 dev->shadow_regs[0x2b] = 0x17; 674 dev->shadow_regs[0x2d] = 0x41; 675 dev->shadow_regs[0x2e] = 0x86; 676 dev->shadow_regs[0x30] = 0x48; 677 dev->shadow_regs[0x31] = 0x01; 678 dev->shadow_regs[0x33] = 0x01; 679 dev->shadow_regs[0x34] = 0x50; 680 dev->shadow_regs[0x35] = 0x01; 681 dev->shadow_regs[0x36] = 0x50; 682 dev->shadow_regs[0x37] = 0x01; 683 dev->shadow_regs[0x38] = 0x50; 684 dev->shadow_regs[0x3c] = 0x88; 685 dev->shadow_regs[0x3d] = 0x08; 686 dev->shadow_regs[0x66] = 0x64; 687 dev->shadow_regs[0x67] = 0x00; 688 dev->shadow_regs[0x6c] = 0xc8; 689 dev->shadow_regs[0x6d] = 0x00; 690 dev->shadow_regs[0x72] = 0x35; 691 dev->shadow_regs[0x74] = 0x4e; 692 dev->shadow_regs[0x75] = 0x03; 693 dev->shadow_regs[0x7a] = 0x01; 694 dev->shadow_regs[0x93] = 0x0a; 695 dev->shadow_regs[0x94] = 0x0e; 696 697 dev->shadow_regs[0xc3] = 0x01; 698 dev->shadow_regs[0xc4] = 0x20; 699 dev->shadow_regs[0xc5] = 0x0a; 700 dev->shadow_regs[0xc8] = 0x04; 701 dev->shadow_regs[0xc9] = 0x3b; 702 dev->shadow_regs[0xca] = 0x0a; 703 dev->shadow_regs[0xe2] = 0xf8; 704 dev->shadow_regs[0xe3] = 0x2a; 705 status = SANE_STATUS_GOOD; 706 break; 707 case A920_SENSOR: 708 dev->shadow_regs[0x01] = 0x43; 709 dev->shadow_regs[0x0b] = 0x70; 710 dev->shadow_regs[0x0c] = 0x28; 711 dev->shadow_regs[0x0d] = 0xa4; 712 dev->shadow_regs[0x11] = 0x01; 713 dev->shadow_regs[0x12] = 0x0f; 714 dev->shadow_regs[0x13] = 0x01; 715 dev->shadow_regs[0x15] = 0x01; 716 dev->shadow_regs[0x16] = 0x07; 717 dev->shadow_regs[0x1d] = 0x20; 718 dev->shadow_regs[0x28] = 0xf5; 719 dev->shadow_regs[0x29] = 0xf7; 720 dev->shadow_regs[0x2a] = 0xf5; 721 dev->shadow_regs[0x2b] = 0x17; 722 dev->shadow_regs[0x2e] = 0x86; 723 dev->shadow_regs[0x30] = 0x48; 724 dev->shadow_regs[0x31] = 0x01; 725 dev->shadow_regs[0x33] = 0x01; 726 dev->shadow_regs[0x3a] = 0x20; 727 dev->shadow_regs[0x3b] = 0x37; 728 dev->shadow_regs[0x3c] = 0x88; 729 dev->shadow_regs[0x3d] = 0x08; 730 dev->shadow_regs[0x47] = 0x21; 731 dev->shadow_regs[0x48] = 0x1a; 732 dev->shadow_regs[0x49] = 0x5b; 733 dev->shadow_regs[0x4a] = 0x1b; 734 dev->shadow_regs[0x4b] = 0x5b; 735 dev->shadow_regs[0x4c] = 0x05; 736 dev->shadow_regs[0x4d] = 0x3f; 737 dev->shadow_regs[0x65] = 0x80; 738 dev->shadow_regs[0x86] = 0x14; 739 dev->shadow_regs[0x87] = 0x06; 740 dev->shadow_regs[0x89] = 0xf5; 741 dev->shadow_regs[0x8d] = 0x01; 742 dev->shadow_regs[0x8e] = 0x60; 743 dev->shadow_regs[0x8f] = 0x80; 744 dev->shadow_regs[0x94] = 0x0e; 745 dev->shadow_regs[0xa3] = 0x0d; 746 dev->shadow_regs[0xa4] = 0x5e; 747 dev->shadow_regs[0xa5] = 0x23; 748 dev->shadow_regs[0xb0] = 0x2c; 749 dev->shadow_regs[0xb1] = 0x0f; 750 dev->shadow_regs[0xc2] = 0x80; 751 dev->shadow_regs[0xc4] = 0x20; 752 dev->shadow_regs[0xc8] = 0x04; 753 status = SANE_STATUS_GOOD; 754 break; 755 case X1200_SENSOR: 756 dev->shadow_regs[0x01] = 0x43; 757 dev->shadow_regs[0x0b] = 0x70; 758 dev->shadow_regs[0x0c] = 0x28; 759 dev->shadow_regs[0x0d] = 0xa4; 760 dev->shadow_regs[0x11] = 0x01; 761 dev->shadow_regs[0x12] = 0x0f; 762 dev->shadow_regs[0x13] = 0x01; 763 dev->shadow_regs[0x15] = 0x01; 764 dev->shadow_regs[0x16] = 0x0f; 765 dev->shadow_regs[0x1d] = 0x20; 766 dev->shadow_regs[0x28] = 0xe9; 767 dev->shadow_regs[0x29] = 0xeb; 768 dev->shadow_regs[0x2a] = 0xe9; 769 dev->shadow_regs[0x2b] = 0x0b; 770 dev->shadow_regs[0x2d] = 0x01; 771 dev->shadow_regs[0x2e] = 0x86; 772 dev->shadow_regs[0x2f] = 0x11; 773 dev->shadow_regs[0x30] = 0x48; 774 dev->shadow_regs[0x33] = 0x01; 775 dev->shadow_regs[0x34] = 0x50; 776 dev->shadow_regs[0x35] = 0x01; 777 dev->shadow_regs[0x36] = 0x50; 778 dev->shadow_regs[0x37] = 0x01; 779 dev->shadow_regs[0x38] = 0x50; 780 dev->shadow_regs[0x3a] = 0x20; 781 dev->shadow_regs[0x3b] = 0x37; 782 dev->shadow_regs[0x3c] = 0x88; 783 dev->shadow_regs[0x3d] = 0x08; 784 dev->shadow_regs[0x40] = 0x80; 785 dev->shadow_regs[0x47] = 0x01; 786 dev->shadow_regs[0x48] = 0x1a; 787 dev->shadow_regs[0x49] = 0x5b; 788 dev->shadow_regs[0x4a] = 0x1b; 789 dev->shadow_regs[0x4b] = 0x5b; 790 dev->shadow_regs[0x4c] = 0x05; 791 dev->shadow_regs[0x4d] = 0x3f; 792 dev->shadow_regs[0x60] = 0x12; 793 dev->shadow_regs[0x62] = 0x81; 794 dev->shadow_regs[0x63] = 0x03; 795 dev->shadow_regs[0x65] = 0x80; 796 dev->shadow_regs[0x66] = 0x64; 797 dev->shadow_regs[0x6c] = 0xc8; 798 dev->shadow_regs[0x72] = 0x1e; 799 dev->shadow_regs[0x74] = 0x3c; 800 dev->shadow_regs[0x75] = 0x03; 801 dev->shadow_regs[0x79] = 0x40; 802 dev->shadow_regs[0x7a] = 0x01; 803 dev->shadow_regs[0x85] = 0x20; 804 dev->shadow_regs[0x86] = 0x1e; 805 dev->shadow_regs[0x87] = 0x39; 806 dev->shadow_regs[0x8b] = 0xff; 807 dev->shadow_regs[0x8c] = 0x02; 808 dev->shadow_regs[0x8d] = 0x01; 809 dev->shadow_regs[0x8e] = 0x60; 810 dev->shadow_regs[0x8f] = 0x80; 811 dev->shadow_regs[0x92] = 0x92; 812 dev->shadow_regs[0x93] = 0x02; 813 dev->shadow_regs[0x94] = 0x0e; 814 dev->shadow_regs[0xa3] = 0x0d; 815 dev->shadow_regs[0xa4] = 0x5e; 816 dev->shadow_regs[0xa5] = 0x23; 817 dev->shadow_regs[0xb0] = 0x2c; 818 dev->shadow_regs[0xb1] = 0x07; 819 dev->shadow_regs[0xb2] = 0x04; 820 dev->shadow_regs[0xc2] = 0x80; 821 dev->shadow_regs[0xc3] = 0x01; 822 dev->shadow_regs[0xc4] = 0x20; 823 dev->shadow_regs[0xc5] = 0x0a; 824 dev->shadow_regs[0xc8] = 0x04; 825 dev->shadow_regs[0xc9] = 0x3b; 826 dev->shadow_regs[0xca] = 0x0a; 827 dev->shadow_regs[0xe2] = 0xf8; 828 dev->shadow_regs[0xe3] = 0x2a; 829 dev->shadow_regs[0xf3] = 0xff; 830 dev->shadow_regs[0xf4] = 0x0f; 831 break; 832 } 833 DBG (5, "sanei_lexmark_low_init: init done for model %s/%s\n", 834 dev->model.model, dev->model.name); 835 DBG (2, "low_init: done\n"); 836 return status; 837} 838 839void 840sanei_lexmark_low_destroy (Lexmark_Device * dev) 841{ 842 /* free the read buffer */ 843 if (dev->read_buffer != NULL) 844 read_buffer_free (dev->read_buffer); 845} 846 847 848SANE_Status 849low_usb_bulk_write (SANE_Int devnum, SANE_Byte * cmd, size_t * size) 850{ 851 SANE_Status status; 852 size_t cmd_size; 853 854 cmd_size = *size; 855#ifdef FAKE_USB 856 status = SANE_STATUS_GOOD; 857#else 858 status = sanei_usb_write_bulk (devnum, cmd, size); 859#endif 860 if (status != SANE_STATUS_GOOD) 861 { 862 DBG (5, 863 "low_usb_bulk_write: returned %s (size = %lu, expected %lu)\n", 864 sane_strstatus (status), (u_long) * size, (u_long) cmd_size); 865 /* F.O. should reset the pipe here... */ 866 } 867 return status; 868} 869 870SANE_Status 871low_usb_bulk_read (SANE_Int devnum, SANE_Byte * buf, size_t * size) 872{ 873 SANE_Status status; 874 size_t exp_size; 875 876 exp_size = *size; 877#ifdef FAKE_USB 878 status = SANE_STATUS_GOOD; 879#else 880 status = sanei_usb_read_bulk (devnum, buf, size); 881#endif 882 if (status != SANE_STATUS_GOOD) 883 { 884 DBG (5, 885 "low_usb_bulk_read: returned %s (size = %lu, expected %lu)\n", 886 sane_strstatus (status), (u_long) * size, (u_long) exp_size); 887 /* F.O. should reset the pipe here... */ 888 } 889 DBG (7, "low_usb_bulk_read: returned size = %lu (required %lu)\n", 890 (u_long) * size, (u_long) exp_size); 891 return status; 892} 893 894 895SANE_Status 896low_start_mvmt (SANE_Int devnum) 897{ 898 SANE_Status status; 899 SANE_Byte reg; 900 901 reg = 0x68; 902 rts88xx_write_reg (devnum, 0xb3, ®); 903 status = rts88xx_write_reg (devnum, 0xb3, ®); 904 return status; 905} 906 907SANE_Status 908low_stop_mvmt (SANE_Int devnum) 909{ 910 SANE_Status status; 911 SANE_Byte reg; 912 913 /* Stop scanner - clear reg 0xb3: */ 914 reg = 0x02; 915 rts88xx_write_reg (devnum, 0xb3, ®); 916 rts88xx_write_reg (devnum, 0xb3, ®); 917 reg = 0x00; 918 rts88xx_write_reg (devnum, 0xb3, ®); 919 status = rts88xx_write_reg (devnum, 0xb3, ®); 920 return status; 921} 922 923SANE_Status 924low_clr_c6 (SANE_Int devnum) 925{ 926 SANE_Status status; 927 SANE_Byte reg; 928 929 /* Clear register 0xC6 */ 930 /* cmd_size = 0x05; 931 return low_usb_bulk_write (devnum, clearC6_command_block, &cmd_size); */ 932 933 reg = 0x00; 934 status = rts88xx_write_reg (devnum, 0xc6, ®); 935 return status; 936} 937 938/* stops current scan */ 939static SANE_Status 940low_cancel (SANE_Int devnum) 941{ 942 SANE_Status status; 943 944 DBG (2, "low_cancel: start\n"); 945 status = low_stop_mvmt (devnum); 946 if (status != SANE_STATUS_GOOD) 947 return status; 948 status = low_clr_c6 (devnum); 949 if (status != SANE_STATUS_GOOD) 950 return status; 951 DBG (2, "low_cancel: end.\n"); 952 return status; 953} 954 955static SANE_Status 956low_start_scan (SANE_Int devnum, SANE_Byte * regs) 957{ 958 SANE_Status status; 959 960 DBG (2, "low_start_scan: start\n"); 961 962 /* writes registers to scanner */ 963 regs[0x32] = 0x00; 964 status = low_write_all_regs (devnum, regs); 965 if (status != SANE_STATUS_GOOD) 966 return status; 967 regs[0x32] = 0x40; 968 status = low_write_all_regs (devnum, regs); 969 if (status != SANE_STATUS_GOOD) 970 return status; 971 972 /* Stop scanner - clear reg 0xb3: */ 973 /* status = low_stop_mvmt (devnum); 974 if (status != SANE_STATUS_GOOD) 975 return status; */ 976 977 /* then start */ 978 status = rts88xx_commit (devnum, regs[0x2c]); 979 DBG (2, "low_start_scan: end.\n"); 980 return status; 981} 982 983/* wait for scan data being available */ 984static SANE_Status 985low_poll_data (SANE_Int devnum) 986{ 987 SANE_Status status; 988 int loops = 0; 989 size_t size; 990 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; 991 SANE_Byte result[3]; 992 SANE_Word count; 993 994 /* Poll the available byte count until not 0 */ 995 while (loops < 1000) 996 { 997 /* 10 ms sleep */ 998 usleep (10000); 999 1000 /* as stated in sanei_lexmark_low_search_home_bwd, we read 1001 * available data count twice */ 1002 size = 4; 1003 status = low_usb_bulk_write (devnum, command4_block, &size); 1004 if (status != SANE_STATUS_GOOD) 1005 return status; 1006 size = 0x3; 1007 status = low_usb_bulk_read (devnum, result, &size); 1008 if (status != SANE_STATUS_GOOD) 1009 return status; 1010 size = 4; 1011 /* read available data size again */ 1012 status = low_usb_bulk_write (devnum, command4_block, &size); 1013 if (status != SANE_STATUS_GOOD) 1014 return status; 1015 size = 0x3; 1016 status = low_usb_bulk_read (devnum, result, &size); 1017 if (status != SANE_STATUS_GOOD) 1018 return status; 1019 count = result[0] + (result[1] << 8) + (result[2] << 16); 1020 if (count != 0) 1021 { 1022 DBG (15, "low_poll_data: %d bytes available\n", count); 1023 return SANE_STATUS_GOOD; 1024 } 1025 loops++; 1026 } 1027 return SANE_STATUS_IO_ERROR; 1028} 1029 1030/** 1031 * do a simple scan with the given registers. data buffer is allocated within 1032 * the function 1033 */ 1034static SANE_Status 1035low_simple_scan (Lexmark_Device * dev, SANE_Byte * regs, int xoffset, 1036 int pixels, int yoffset, int lines, SANE_Byte ** data) 1037{ 1038 SANE_Status status = SANE_STATUS_GOOD; 1039 static SANE_Byte reg; 1040 size_t size, read, needed; 1041 int i, bpl, yend; 1042 1043 DBG (2, "low_simple_scan: start\n"); 1044 DBG (15, "low_simple_scan: x=%d, pixels=%d (ex=%d), y=%d, lines=%d\n", 1045 xoffset, pixels, xoffset + pixels * regs[0x7a], yoffset, lines); 1046 1047 /* set up registers */ 1048 regs[0x60] = LOBYTE (yoffset); 1049 regs[0x61] = HIBYTE (yoffset); 1050 yend = yoffset + lines; 1051 if ((dev->model.motor_type == A920_MOTOR 1052 || dev->model.motor_type == X74_MOTOR) && rts88xx_is_color (regs) 1053 && dev->val[OPT_RESOLUTION].w == 600) 1054 yend *= 2; 1055 regs[0x62] = LOBYTE (yend); 1056 regs[0x63] = HIBYTE (yend); 1057 1058 regs[0x66] = LOBYTE (xoffset); 1059 regs[0x67] = HIBYTE (xoffset); 1060 1061 regs[0x6c] = LOBYTE (xoffset + pixels * regs[0x7a]); 1062 regs[0x6d] = HIBYTE (xoffset + pixels * regs[0x7a]); 1063 1064 /* allocate memory */ 1065 if (rts88xx_is_color (regs)) 1066 bpl = 3 * pixels; 1067 else 1068 bpl = pixels; 1069 *data = (SANE_Byte *) malloc (bpl * lines); 1070 if (*data == NULL) 1071 { 1072 DBG (2, 1073 "low_simple_scan: failed to allocate %d bytes !\n", bpl * lines); 1074 return SANE_STATUS_NO_MEM; 1075 } 1076 1077 /* start scan */ 1078 status = low_cancel (dev->devnum); 1079 if (status != SANE_STATUS_GOOD) 1080 return status; 1081 1082 1083 status = low_start_scan (dev->devnum, regs); 1084 if (status != SANE_STATUS_GOOD) 1085 return status; 1086 1087 /* wait for data */ 1088 status = low_poll_data (dev->devnum); 1089 if (status != SANE_STATUS_GOOD) 1090 { 1091 DBG (1, "low_simple_scan: time-out while waiting for data.\n"); 1092 return status; 1093 } 1094 1095 /* data reading loop */ 1096 needed = bpl * lines; 1097 DBG (1, "low_simple_scan: bpl=%d, lines=%d, needed=%lu.\n", bpl, lines, 1098 (u_long) needed); 1099 read = 0; 1100 do 1101 { 1102 /* this block would deserve to be a function */ 1103 status = 1104 rts88xx_read_data (dev->devnum, needed - read, (*data) + read, &size); 1105 if (status != SANE_STATUS_GOOD) 1106 return status; 1107 read += size; 1108 } 1109 while (read < needed); 1110 1111 /* if needed, wait for motor to stop */ 1112 if (regs[0xc3] & 0x80) 1113 { 1114 i = 0; 1115 do 1116 { 1117 if (rts88xx_read_reg (dev->devnum, 0xb3, ®) != SANE_STATUS_GOOD) 1118 { 1119 DBG (5, "low_simple_scan: register read failed ...\n"); 1120 return SANE_STATUS_IO_ERROR; 1121 } 1122 usleep (100000); 1123 i++; 1124 } 1125 while ((reg & 0x08) && (i < 100)); 1126 if (reg & 0x08) 1127 { 1128 DBG (5, 1129 "low_simple_scan : timeout waiting for motor to stop ...\n"); 1130 return SANE_STATUS_IO_ERROR; 1131 } 1132 } 1133 1134 /* stop scan */ 1135 status = low_cancel (dev->devnum); 1136 if (status != SANE_STATUS_GOOD) 1137 { 1138 DBG (1, "low_simple_scan: cancel failed.\n"); 1139 return status; 1140 } 1141 1142 DBG (2, "low_simple_scan: end.\n"); 1143 return status; 1144} 1145 1146/* 1147 * open USB device ,read initial registers values and probe sensor 1148 */ 1149SANE_Status 1150sanei_lexmark_low_open_device (Lexmark_Device * dev) 1151{ 1152 /* This function calls the Sane Interface to open this usb device. 1153 It also needlessly does what the Windows driver does and reads 1154 the entire register set - this may be removed. */ 1155 1156 SANE_Status result; 1157 static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF }; 1158 size_t size; 1159 SANE_Byte variant = 0; 1160 SANE_Byte shadow_regs[255]; 1161 int sx, ex; 1162 int sy, ey; 1163 int i; 1164 char msg[2048]; 1165 1166 1167#ifdef FAKE_USB 1168 result = SANE_STATUS_GOOD; 1169 shadow_regs[0x00] = 0x91; 1170 shadow_regs[0xb0] = 0x2c; 1171 shadow_regs[0x10] = 0x97; 1172 shadow_regs[0x10] = 0x87; 1173 shadow_regs[0xf3] = 0xf8; 1174 shadow_regs[0xf4] = 0x7f; 1175#else 1176 result = sanei_usb_open (dev->sane.name, &(dev->devnum)); 1177#endif 1178 DBG (2, "sanei_lexmark_low_open_device: devnum=%d\n", dev->devnum); 1179 1180 size = 4; 1181 low_usb_bulk_write (dev->devnum, command_block, &size); 1182 size = 0xFF; 1183 memset (shadow_regs, 0, sizeof (shadow_regs)); 1184 low_usb_bulk_read (dev->devnum, shadow_regs, &size); 1185 1186 if (DBG_LEVEL > 2) 1187 { 1188 DBG (2, "sanei_lexmark_low_open_device: initial registers values\n"); 1189 for (i = 0; i < 255; i++) 1190 { 1191 sprintf (msg + i * 5, "0x%02x ", shadow_regs[i]); 1192 } 1193 DBG (3, "%s\n", msg); 1194 } 1195 1196 /* it seems that at first read after reset, registers hold information 1197 * about the scanner. Register 0x00 is overwritten with 0, so only first read 1198 * after USB plug-in gives this value */ 1199 if (shadow_regs[0] == 0x91) 1200 { 1201 sx = shadow_regs[0x67] * 256 + shadow_regs[0x66]; 1202 ex = shadow_regs[0x6d] * 256 + shadow_regs[0x6c]; 1203 DBG (7, "startx=%d, endx=%d, pixels=%d, coef=%d, r2f=0x%02x\n", sx, ex, 1204 ex - sx, dev->shadow_regs[0x7a], shadow_regs[0x2f]); 1205 sy = shadow_regs[0x61] * 256 + shadow_regs[0x60]; 1206 ey = shadow_regs[0x63] * 256 + shadow_regs[0x62]; 1207 DBG (7, "starty=%d, endy=%d, lines=%d\n", sy, ey, ey - sy); 1208 } 1209 1210 /* we use register 0xb0 to identify details about models */ 1211 /* this register isn't overwritten during normal operation */ 1212 if (shadow_regs[0xb0] == 0x2c && dev->model.sensor_type == X1100_B2_SENSOR) 1213 { 1214 variant = shadow_regs[0xb0]; 1215 } 1216 /* now the same with register 0x10 */ 1217 /* which most likely signals USB2.0/USB1.1 */ 1218 if ((dev->model.sensor_type == X1200_SENSOR) && (shadow_regs[0x10] == 0x97)) 1219 { 1220 variant = shadow_regs[0x10]; 1221 } 1222 1223 /* if find a case where default model given is inappropriate, reassign it 1224 * since we have now the information to get the real one. 1225 * We could avoid this if attach() did open and read registers, not init */ 1226 if (variant != 0) 1227 { 1228 DBG (3, 1229 "sanei_lexmark_low_open_device: reassign model/sensor for variant 0x%02x\n", 1230 variant); 1231 sanei_lexmark_low_assign_model (dev, dev->sane.name, 1232 dev->model.vendor_id, 1233 dev->model.product_id, variant); 1234 /* since model has changed, run init again */ 1235 sanei_lexmark_low_init (dev); 1236 } 1237 DBG (2, "sanei_lexmark_low_open_device: end\n"); 1238 return result; 1239} 1240 1241void 1242sanei_lexmark_low_close_device (Lexmark_Device * dev) 1243{ 1244 /* put scanner in idle state */ 1245 lexmark_low_set_idle (dev->devnum); 1246 1247 /* This function calls the Sane USB library to close this usb device */ 1248#ifndef FAKE_USB 1249 sanei_usb_close (dev->devnum); 1250#endif 1251 return; 1252} 1253 1254 1255/* This function writes the contents of the given registers to the 1256 scanner. */ 1257SANE_Status 1258low_write_all_regs (SANE_Int devnum, SANE_Byte * regs) 1259{ 1260 int i; 1261 SANE_Status status; 1262 size_t size; 1263 static SANE_Byte command_block1[0xb7]; 1264 static SANE_Byte command_block2[0x4f]; 1265 command_block1[0] = 0x88; 1266 command_block1[1] = 0x00; 1267 command_block1[2] = 0x00; 1268 command_block1[3] = 0xb3; 1269 for (i = 0; i < 0xb3; i++) 1270 { 1271 command_block1[i + 4] = regs[i]; 1272 } 1273 command_block2[0] = 0x88; 1274 command_block2[1] = 0xb4; 1275 command_block2[2] = 0x00; 1276 command_block2[3] = 0x4b; 1277 for (i = 0; i < 0x4b; i++) 1278 { 1279 command_block2[i + 4] = regs[i + 0xb4]; 1280 } 1281 size = 0xb7; 1282 1283#ifdef DEEP_DEBUG 1284 fprintf (stderr, "write_all(0x00,255)="); 1285 for (i = 0; i < 255; i++) 1286 { 1287 fprintf (stderr, "0x%02x ", regs[i]); 1288 } 1289 fprintf (stderr, "\n"); 1290#endif 1291 1292 status = low_usb_bulk_write (devnum, command_block1, &size); 1293 if (status != SANE_STATUS_GOOD) 1294 return status; 1295 size = 0x4f; 1296 status = low_usb_bulk_write (devnum, command_block2, &size); 1297 if (status != SANE_STATUS_GOOD) 1298 return status; 1299 return SANE_STATUS_GOOD; 1300} 1301 1302 1303SANE_Bool 1304low_is_home_line (Lexmark_Device * dev, unsigned char *buffer) 1305{ 1306 /* 1307 This function assumes the buffer has a size of 2500 bytes.It is 1308 destructive to the buffer. 1309 1310 Here is what it does: 1311 1312 Go through the buffer finding low and high values, which are computed by 1313 comparing to the average: 1314 average = (lowest value + highest value)/2 1315 High bytes are changed to 0xFF (white), lower or equal bytes are changed 1316 to 0x00 (black),so that the buffer only contains white (0xFF) or black 1317 (0x00) values. 1318 1319 Next, we go through the buffer. We use a tolerance of 5 bytes on each end 1320 of the buffer and check a region from bytes 5 to 2495. We start assuming 1321 we are in a white region and look for the start of a black region. We save 1322 this index as the transition from white to black. We also save where we 1323 change from black back to white. We continue checking for transitions 1324 until the end of the check region. If we don't have exactly two 1325 transitions when we reach the end we return SANE_FALSE. 1326 1327 The final check compares the transition indices to the nominal values 1328 plus or minus the tolerance. For the first transition (white to black 1329 index) the value must lie in the range 1235-30 (1205) to 1235+30 (1265). 1330 For the second transition (black to white) the value must lie in the range 1331 1258-30 (1228) to 1258+30 (1288). If the indices are out of range we 1332 return SANE_FALSE. Otherwise, we return SANE_TRUE. 1333 */ 1334 1335 1336 unsigned char max_byte = 0; 1337 unsigned char min_byte = 0xFF; 1338 unsigned char average; 1339 int i; 1340 int home_point1; 1341 int home_point2; 1342 region_type region; 1343 int transition_counter; 1344 int index1 = 0; 1345 int index2 = 0; 1346 int low_range, high_range; 1347 1348#ifdef DEEP_DEBUG 1349 static int numero = 0; 1350 char titre[80]; 1351 FILE *trace = NULL; 1352 sprintf (titre, "lgn%03d.pnm", numero); 1353 trace = fopen (titre, "wb"); 1354 if (trace) 1355 { 1356 fprintf (trace, "P5\n2500 1\n255\n"); 1357 fwrite (buffer, 2500, 1, trace); 1358 fclose (trace); 1359 } 1360 numero++; 1361#endif 1362 1363 DBG (15, "low_is_home_line: start\n"); 1364 /* Find the max and the min */ 1365 for (i = 0; i < 2500; i++) 1366 { 1367 if (*(buffer + i) > max_byte) 1368 max_byte = *(buffer + i); 1369 if (*(buffer + i) < min_byte) 1370 min_byte = *(buffer + i); 1371 } 1372 1373 /* The average */ 1374 average = ((max_byte + min_byte) / 2); 1375 1376 /* Set bytes as white (0xFF) or black (0x00) */ 1377 for (i = 0; i < 2500; i++) 1378 { 1379 if (*(buffer + i) > average) 1380 *(buffer + i) = 0xFF; 1381 else 1382 *(buffer + i) = 0x00; 1383 } 1384 1385 region = white; 1386 transition_counter = 0; 1387 1388 /* Go through the check region - bytes 5 to 2495 */ 1389 /* XXX STEF XXX shrink the area to where the dot should be 1390 * +-100 around the 1250 expected location */ 1391 for (i = 1150; i <= 1350; i++) 1392 { 1393 /* Check for transition to black */ 1394 if ((region == white) && (*(buffer + i) == 0)) 1395 { 1396 if (transition_counter < 2) 1397 { 1398 region = black; 1399 index1 = i; 1400 transition_counter++; 1401 } 1402 else 1403 { 1404 DBG (15, "low_is_home_line: no transition to black \n"); 1405 return SANE_FALSE; 1406 } 1407 } 1408 /* Check for transition to white */ 1409 else if ((region == black) && (*(buffer + i) == 0xFF)) 1410 { 1411 if (transition_counter < 2) 1412 { 1413 region = white; 1414 index2 = i; 1415 transition_counter++; 1416 } 1417 else 1418 { 1419 DBG (15, "low_is_home_line: no transition to white \n"); 1420 return SANE_FALSE; 1421 } 1422 } 1423 } 1424 1425 /* Check that the number of transitions is 2 */ 1426 if (transition_counter != 2) 1427 { 1428 DBG (15, "low_is_home_line: transitions!=2 (%d)\n", transition_counter); 1429 return SANE_FALSE; 1430 } 1431 1432 1433 1434 1435 /* Check that the 1st index is in range */ 1436 home_point1 = dev->model.HomeEdgePoint1; 1437 low_range = home_point1 - HomeTolerance; 1438 high_range = home_point1 + HomeTolerance; 1439 1440 if ((index1 < low_range) || (index1 > high_range)) 1441 { 1442 DBG (15, "low_is_home_line: index1=%d out of range\n", index1); 1443 return SANE_FALSE; 1444 } 1445 1446 1447 /* Check that the 2nd index is in range */ 1448 home_point2 = dev->model.HomeEdgePoint2; 1449 low_range = home_point2 - HomeTolerance; 1450 high_range = home_point2 + HomeTolerance; 1451 1452 if ((index2 < low_range) || (index2 > high_range)) 1453 { 1454 DBG (15, "low_is_home_line: index2=%d out of range.\n", index2); 1455 return SANE_FALSE; 1456 } 1457 1458 /* We made it this far, so its a good home line. Return True */ 1459 DBG (15, "low_is_home_line: success\n"); 1460 return SANE_TRUE; 1461} 1462 1463void 1464sanei_lexmark_low_move_fwd (SANE_Int distance, Lexmark_Device * dev, 1465 SANE_Byte * regs) 1466{ 1467 /* 1468 This function moves the scan head forward with the highest vertical 1469 resolution of 1200dpi. The distance moved is given by the distance 1470 parameter. 1471 1472 As an example, given a distance parameter of 600, the scan head will 1473 move 600/1200", or 1/2" forward. 1474 */ 1475 1476 static SANE_Byte pollstopmoving_command_block[] = 1477 { 0x80, 0xb3, 0x00, 0x01 }; 1478 1479 1480 size_t cmd_size; 1481 SANE_Int devnum; 1482 SANE_Bool scan_head_moving; 1483 SANE_Byte read_result; 1484 1485 DBG (2, "sanei_lexmark_low_move_fwd: \n"); 1486 devnum = dev->devnum; 1487 1488 1489 /* registers set-up */ 1490 regs[0x2c] = 0x00; 1491 regs[0x2d] = 0x41; 1492 regs[0x65] = 0x80; 1493 switch (dev->model.sensor_type) 1494 { 1495 case X74_SENSOR: 1496 rts88xx_set_scan_frequency (regs, 0); 1497 regs[0x93] = 0x06; 1498 break; 1499 case X1100_B2_SENSOR: 1500 regs[0x8b] = 0x00; 1501 regs[0x8c] = 0x00; 1502 regs[0x93] = 0x06; 1503 break; 1504 case X1100_2C_SENSOR: 1505 rts88xx_set_scan_frequency (regs, 0); 1506 regs[0x93] = 0x06; 1507 break; 1508 case A920_SENSOR: 1509 rts88xx_set_scan_frequency (regs, 0); 1510 regs[0x8b] = 0xff; 1511 regs[0x8c] = 0x02; 1512 regs[0x93] = 0x0e; 1513 break; 1514 case X1200_SENSOR: 1515 dev->shadow_regs[0x2d] = 0x01; 1516 rts88xx_set_scan_frequency (regs, 0); 1517 break; 1518 case X1200_USB2_SENSOR: 1519 dev->shadow_regs[0x2d] = 0x4f; 1520 rts88xx_set_scan_frequency (regs, 0); 1521 break; 1522 } 1523 1524 /* set grayscale scan + nodata/nochannel? */ 1525 regs[0x2f] = 0xa1; 1526 1527 /* set ? */ 1528 regs[0x34] = 0x50; 1529 regs[0x35] = 0x01; 1530 regs[0x36] = 0x50; 1531 regs[0x37] = 0x01; 1532 regs[0x38] = 0x50; 1533 /* set motor resolution divisor */ 1534 regs[0x39] = 0x00; 1535 /* set vertical start/end positions */ 1536 regs[0x60] = LOBYTE (distance - 1); 1537 regs[0x61] = HIBYTE (distance - 1); 1538 regs[0x62] = LOBYTE (distance); 1539 regs[0x63] = HIBYTE (distance); 1540 /* set horizontal start position */ 1541 regs[0x66] = 0x64; 1542 regs[0x67] = 0x00; 1543 /* set horizontal end position */ 1544 regs[0x6c] = 0xc8; 1545 regs[0x6d] = 0x00; 1546 /* set horizontal resolution */ 1547 regs[0x79] = 0x40; 1548 regs[0x7a] = 0x01; 1549 /* don't buffer data for this scan */ 1550 regs[0xb2] = 0x04; 1551 /* Motor enable & Coordinate space denominator */ 1552 regs[0xc3] = 0x81; 1553 /* Movement direction & step size */ 1554 regs[0xc6] = 0x09; 1555 /* ? */ 1556 regs[0x80] = 0x00; 1557 regs[0x81] = 0x00; 1558 regs[0x82] = 0x00; 1559 regs[0xc5] = 0x0a; 1560 1561 1562 switch (dev->model.motor_type) 1563 { 1564 case X1100_MOTOR: 1565 case A920_MOTOR: 1566 /* step size range2 */ 1567 regs[0xc9] = 0x3b; 1568 /* ? */ 1569 regs[0xca] = 0x0a; 1570 /* motor curve stuff */ 1571 regs[0xe0] = 0x00; 1572 regs[0xe1] = 0x00; 1573 regs[0xe4] = 0x00; 1574 regs[0xe5] = 0x00; 1575 regs[0xe7] = 0x00; 1576 regs[0xe8] = 0x00; 1577 regs[0xe2] = 0x09; 1578 regs[0xe3] = 0x1a; 1579 regs[0xe6] = 0xdc; 1580 regs[0xe9] = 0x1b; 1581 regs[0xec] = 0x07; 1582 regs[0xef] = 0x03; 1583 break; 1584 case X74_MOTOR: 1585 regs[0xc5] = 0x41; 1586 /* step size range2 */ 1587 regs[0xc9] = 0x39; 1588 /* ? */ 1589 regs[0xca] = 0x40; 1590 /* motor curve stuff */ 1591 regs[0xe0] = 0x00; 1592 regs[0xe1] = 0x00; 1593 regs[0xe2] = 0x09; 1594 regs[0xe3] = 0x1a; 1595 regs[0xe4] = 0x00; 1596 regs[0xe5] = 0x00; 1597 regs[0xe6] = 0x64; 1598 regs[0xe7] = 0x00; 1599 regs[0xe8] = 0x00; 1600 regs[0xe9] = 0x32; 1601 regs[0xec] = 0x0c; 1602 regs[0xef] = 0x08; 1603 break; 1604 } 1605 1606 1607 /* prepare for register write */ 1608 low_clr_c6 (devnum); 1609 low_stop_mvmt (devnum); 1610 1611/* Move Forward without scanning: */ 1612 regs[0x32] = 0x00; 1613 low_write_all_regs (devnum, regs); 1614 regs[0x32] = 0x40; 1615 low_write_all_regs (devnum, regs); 1616 1617 /* Stop scanner - clear reg 0xb3: */ 1618 /* low_stop_mvmt (devnum); */ 1619 1620 rts88xx_commit (devnum, regs[0x2c]); 1621 1622 /* Poll for scanner stopped - return value(3:0) = 0: */ 1623 scan_head_moving = SANE_TRUE; 1624 while (scan_head_moving) 1625 { 1626#ifdef FAKE_USB 1627 scan_head_moving = SANE_FALSE; 1628#else 1629 cmd_size = 0x04; 1630 low_usb_bulk_write (devnum, pollstopmoving_command_block, &cmd_size); 1631 cmd_size = 0x1; 1632 low_usb_bulk_read (devnum, &read_result, &cmd_size); 1633 if ((read_result & 0xF) == 0x0) 1634 { 1635 scan_head_moving = SANE_FALSE; 1636 } 1637#endif 1638 } 1639 1640 /* this is needed to find the start line properly */ 1641 if (dev->model.sensor_type == X74_SENSOR) 1642 low_stop_mvmt (devnum); 1643 1644 DBG (2, "sanei_lexmark_low_move_fwd: end.\n"); 1645} 1646 1647SANE_Bool 1648sanei_lexmark_low_search_home_fwd (Lexmark_Device * dev) 1649{ 1650 /* This function actually searches backwards one line looking for home */ 1651 1652 SANE_Int devnum; 1653 int i; 1654 SANE_Byte poll_result[3]; 1655 SANE_Byte *buffer; 1656 SANE_Byte temp_byte; 1657 1658 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; 1659 1660 static SANE_Byte command5_block[] = { 0x91, 0x00, 0x09, 0xc4 }; 1661 1662 size_t cmd_size; 1663 SANE_Bool got_line; 1664 SANE_Bool ret_val; 1665 1666 devnum = dev->devnum; 1667 1668 DBG (2, "sanei_lexmark_low_search_home_fwd:\n"); 1669 1670 /* set up registers according to the sensor type */ 1671 switch (dev->model.sensor_type) 1672 { 1673 case X74_SENSOR: 1674 dev->shadow_regs[0x2c] = 0x03; 1675 dev->shadow_regs[0x2d] = 0x45; 1676 dev->shadow_regs[0x2f] = 0x21; 1677 dev->shadow_regs[0x30] = 0x48; 1678 dev->shadow_regs[0x31] = 0x06; 1679 dev->shadow_regs[0x34] = 0x05; 1680 dev->shadow_regs[0x35] = 0x05; 1681 dev->shadow_regs[0x36] = 0x09; 1682 dev->shadow_regs[0x37] = 0x09; 1683 dev->shadow_regs[0x38] = 0x0d; 1684 dev->shadow_regs[0x40] = 0x80; 1685 dev->shadow_regs[0x75] = 0x00; 1686 dev->shadow_regs[0x8b] = 0xff; 1687 dev->shadow_regs[0x93] = 0x06; 1688 break; 1689 case X1100_B2_SENSOR: 1690 dev->shadow_regs[0x2c] = 0x0f; 1691 dev->shadow_regs[0x2d] = 0x51; 1692 dev->shadow_regs[0x2f] = 0x21; 1693 dev->shadow_regs[0x34] = 0x04; 1694 dev->shadow_regs[0x35] = 0x04; 1695 dev->shadow_regs[0x36] = 0x08; 1696 dev->shadow_regs[0x37] = 0x08; 1697 dev->shadow_regs[0x38] = 0x0b; 1698 dev->shadow_regs[0x93] = 0x06; 1699 break; 1700 case X1100_2C_SENSOR: 1701 dev->shadow_regs[0x2c] = 0x0d; 1702 dev->shadow_regs[0x2d] = 0x4f; 1703 dev->shadow_regs[0x34] = 0x05; 1704 dev->shadow_regs[0x35] = 0x05; 1705 dev->shadow_regs[0x36] = 0x09; 1706 dev->shadow_regs[0x37] = 0x09; 1707 dev->shadow_regs[0x38] = 0x0d; 1708 dev->shadow_regs[0x40] = 0x80; 1709 dev->shadow_regs[0x72] = 0x35; 1710 dev->shadow_regs[0x74] = 0x4e; 1711 1712 dev->shadow_regs[0x85] = 0x20; /* 05 */ 1713 dev->shadow_regs[0x86] = 0x00; /* 05 */ 1714 dev->shadow_regs[0x87] = 0x00; /* 05 */ 1715 dev->shadow_regs[0x88] = 0x00; /* 45 */ 1716 dev->shadow_regs[0x89] = 0x00; 1717 dev->shadow_regs[0x8b] = 0xff; 1718 1719 dev->shadow_regs[0x93] = 0x06; /* 0e */ 1720 1721 dev->shadow_regs[0x75] = 0x00; /* */ 1722 dev->shadow_regs[0x91] = 0x00; /* 60 */ 1723 dev->shadow_regs[0x92] = 0x00; /* 8d */ 1724 dev->shadow_regs[0xb1] = 0x00; /* */ 1725 dev->shadow_regs[0xc5] = 0x00; /* */ 1726 dev->shadow_regs[0xca] = 0x00; /* */ 1727 dev->shadow_regs[0xc3] = 0x01; /* */ 1728 break; 1729 case A920_SENSOR: 1730 dev->shadow_regs[0x2c] = 0x0d; 1731 dev->shadow_regs[0x2d] = 0x4f; 1732 dev->shadow_regs[0x34] = 0x05; 1733 dev->shadow_regs[0x35] = 0x05; 1734 dev->shadow_regs[0x36] = 0x09; 1735 dev->shadow_regs[0x37] = 0x09; 1736 dev->shadow_regs[0x38] = 0x0d; 1737 dev->shadow_regs[0x40] = 0x80; 1738 dev->shadow_regs[0x72] = 0x35; 1739 dev->shadow_regs[0x74] = 0x4e; 1740 dev->shadow_regs[0x85] = 0x05; 1741 dev->shadow_regs[0x88] = 0x45; 1742 dev->shadow_regs[0x89] = 0x00; 1743 dev->shadow_regs[0x8b] = 0xff; 1744 dev->shadow_regs[0x91] = 0x60; 1745 dev->shadow_regs[0x92] = 0x8d; 1746 dev->shadow_regs[0x93] = 0x0e; 1747 break; 1748 case X1200_SENSOR: 1749 dev->shadow_regs[0x2c] = 0x01; 1750 dev->shadow_regs[0x2d] = 0x03; 1751 dev->shadow_regs[0x34] = 0x04; 1752 dev->shadow_regs[0x35] = 0x04; 1753 dev->shadow_regs[0x36] = 0x08; 1754 dev->shadow_regs[0x37] = 0x08; 1755 dev->shadow_regs[0x38] = 0x0b; 1756 dev->shadow_regs[0x66] = 0x88; 1757 dev->shadow_regs[0x6c] = 0x10; 1758 dev->shadow_regs[0x6d] = 0x14; 1759 dev->shadow_regs[0x75] = 0x00; 1760 dev->shadow_regs[0x93] = 0x06; 1761 dev->shadow_regs[0xc5] = 0x00; 1762 dev->shadow_regs[0xca] = 0x00; 1763 break; 1764 case X1200_USB2_SENSOR: 1765 dev->shadow_regs[0x0b] = 0x70; 1766 dev->shadow_regs[0x0c] = 0x28; 1767 dev->shadow_regs[0x0d] = 0xa4; 1768 dev->shadow_regs[0x2c] = 0x0d; 1769 dev->shadow_regs[0x2d] = 0x4f; 1770 dev->shadow_regs[0x2f] = 0x21; 1771 dev->shadow_regs[0x32] = 0x40; 1772 dev->shadow_regs[0x34] = 0x05; 1773 dev->shadow_regs[0x35] = 0x05; 1774 dev->shadow_regs[0x36] = 0x09; 1775 dev->shadow_regs[0x37] = 0x09; 1776 dev->shadow_regs[0x38] = 0x0d; 1777 dev->shadow_regs[0x3a] = 0x20; 1778 dev->shadow_regs[0x3b] = 0x37; 1779 dev->shadow_regs[0x40] = 0x80; 1780 dev->shadow_regs[0x47] = 0x01; 1781 dev->shadow_regs[0x48] = 0x1a; 1782 dev->shadow_regs[0x49] = 0x5b; 1783 dev->shadow_regs[0x4a] = 0x1b; 1784 dev->shadow_regs[0x4b] = 0x5b; 1785 dev->shadow_regs[0x4c] = 0x05; 1786 dev->shadow_regs[0x4d] = 0x3f; 1787 dev->shadow_regs[0x75] = 0x00; 1788 dev->shadow_regs[0x85] = 0x03; 1789 dev->shadow_regs[0x86] = 0x33; 1790 dev->shadow_regs[0x87] = 0x8f; 1791 dev->shadow_regs[0x88] = 0x34; 1792 dev->shadow_regs[0x8b] = 0xff; 1793 dev->shadow_regs[0x8e] = 0x60; 1794 dev->shadow_regs[0x8f] = 0x80; 1795 dev->shadow_regs[0x91] = 0x59; 1796 dev->shadow_regs[0x92] = 0x10; 1797 dev->shadow_regs[0x93] = 0x06; 1798 dev->shadow_regs[0xa3] = 0x0d; 1799 dev->shadow_regs[0xa4] = 0x5e; 1800 dev->shadow_regs[0xa5] = 0x23; 1801 dev->shadow_regs[0xb1] = 0x07; 1802 dev->shadow_regs[0xc2] = 0x80; 1803 dev->shadow_regs[0xc5] = 0x00; 1804 dev->shadow_regs[0xca] = 0x00; 1805 break; 1806 } 1807 dev->shadow_regs[0x65] = 0x80; 1808 dev->shadow_regs[0x8c] = 0x02; 1809 dev->shadow_regs[0x8d] = 0x01; 1810 dev->shadow_regs[0xb2] = 0x00; 1811 dev->shadow_regs[0xed] = 0x00; 1812 dev->shadow_regs[0xee] = 0x00; 1813 1814 rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain, 1815 dev->sensor->default_gain, dev->sensor->default_gain); 1816 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); 1817 1818 /* set grayscale scan */ 1819 rts88xx_set_gray_scan (dev->shadow_regs); 1820 1821 /* set motor resolution divisor */ 1822 dev->shadow_regs[0x39] = 0x07; 1823 1824 /* set vertical start/end positions */ 1825 dev->shadow_regs[0x60] = 0x01; 1826 dev->shadow_regs[0x61] = 0x00; 1827 dev->shadow_regs[0x62] = 0x02; 1828 dev->shadow_regs[0x63] = 0x00; 1829 1830 /* set # of head moves per CIS read */ 1831 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 1832 1833 /* set horizontal start position */ 1834 dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */ 1835 dev->shadow_regs[0x67] = 0x00; 1836 /* set horizontal end position */ 1837 dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200 */ 1838 dev->shadow_regs[0x6d] = 0x13; 1839 /* set horizontal resolution */ 1840 dev->shadow_regs[0x79] = 0x40; 1841 dev->shadow_regs[0x7a] = 0x02; 1842 /* Motor disable & Coordinate space denominator */ 1843 dev->shadow_regs[0xc3] = 0x01; 1844 /* Movement direction & step size */ 1845 dev->shadow_regs[0xc6] = 0x01; 1846 1847 switch (dev->model.motor_type) 1848 { 1849 case A920_MOTOR: 1850 case X1100_MOTOR: 1851 /* step size range2 */ 1852 dev->shadow_regs[0xc9] = 0x3b; 1853 /* step size range0 */ 1854 dev->shadow_regs[0xe2] = 0x01; 1855 /* ? */ 1856 dev->shadow_regs[0xe3] = 0x03; 1857 break; 1858 case X74_MOTOR: 1859 dev->shadow_regs[0xc4] = 0x20; 1860 dev->shadow_regs[0xc5] = 0x00; 1861 dev->shadow_regs[0xc8] = 0x04; 1862 /* step size range2 */ 1863 dev->shadow_regs[0xc9] = 0x39; 1864 dev->shadow_regs[0xca] = 0x00; 1865 /* motor curve stuff */ 1866 dev->shadow_regs[0xe0] = 0x29; 1867 dev->shadow_regs[0xe1] = 0x17; 1868 dev->shadow_regs[0xe2] = 0x8f; 1869 dev->shadow_regs[0xe3] = 0x06; 1870 dev->shadow_regs[0xe4] = 0x61; 1871 dev->shadow_regs[0xe5] = 0x16; 1872 dev->shadow_regs[0xe6] = 0x64; 1873 dev->shadow_regs[0xe7] = 0xb5; 1874 dev->shadow_regs[0xe8] = 0x08; 1875 dev->shadow_regs[0xe9] = 0x32; 1876 dev->shadow_regs[0xec] = 0x0c; 1877 dev->shadow_regs[0xef] = 0x08; 1878 break; 1879 } 1880 1881 /* Stop the scanner */ 1882 low_stop_mvmt (devnum); 1883 1884 /* write regs out twice */ 1885 dev->shadow_regs[0x32] = 0x00; 1886 low_write_all_regs (devnum, dev->shadow_regs); 1887 dev->shadow_regs[0x32] = 0x40; 1888 low_write_all_regs (devnum, dev->shadow_regs); 1889 1890 /* Start Scan */ 1891 rts88xx_commit (devnum, dev->shadow_regs[0x2c]); 1892 1893 /* Poll the available byte count until not 0 */ 1894 got_line = SANE_FALSE; 1895 while (!got_line) 1896 { 1897 cmd_size = 4; 1898 low_usb_bulk_write (devnum, command4_block, &cmd_size); 1899 cmd_size = 0x3; 1900 low_usb_bulk_read (devnum, poll_result, &cmd_size); 1901 if (! 1902 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) 1903 { 1904 /* if result != 00 00 00 we got data */ 1905 got_line = SANE_TRUE; 1906 } 1907 } 1908 1909 /* create buffer for scan data */ 1910 buffer = calloc (2500, sizeof (char)); 1911 if (buffer == NULL) 1912 { 1913 return SANE_FALSE; 1914 } 1915 1916 /* Tell the scanner to send the data */ 1917 /* Write: 91 00 09 c4 */ 1918 cmd_size = 4; 1919 low_usb_bulk_write (devnum, command5_block, &cmd_size); 1920 /* Read it */ 1921 cmd_size = 0x09c4; 1922 low_usb_bulk_read (devnum, buffer, &cmd_size); 1923 1924 /* Reverse order of bytes in words of buffer */ 1925 for (i = 0; i < 2500; i = i + 2) 1926 { 1927 temp_byte = *(buffer + i); 1928 *(buffer + i) = *(buffer + i + 1); 1929 *(buffer + i + 1) = temp_byte; 1930 } 1931 1932 /* check for home position */ 1933 ret_val = low_is_home_line (dev, buffer); 1934 1935 if (ret_val) 1936 DBG (2, "sanei_lexmark_low_search_home_fwd: !!!HOME POSITION!!!\n"); 1937 1938 /* free the buffer */ 1939 free (buffer); 1940 DBG (2, "sanei_lexmark_low_search_home_fwd: end.\n"); 1941 1942 return ret_val; 1943} 1944 1945SANE_Bool 1946sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev) 1947{ 1948/* This function must only be called if the scan head is past the home dot. 1949 It could damage the scanner if not. 1950 1951 This function tells the scanner to do a grayscale scan backwards with a 1952 300dpi resolution. It reads 2500 bytes of data between horizontal 1953 coordinates 0x6a and 0x13f2. 1954 1955 The scan is set to read between vertical coordinates from 0x0a to 0x0f46, 1956 or 3900 lines. This equates to 13" at 300dpi, so we must stop the scan 1957 before it bangs against the end. A line limit is set so that a maximum of 1958 0x0F3C (13"*300dpi) lines can be read. 1959 1960 To read the scan data we create a buffer space large enough to hold 10 1961 lines of data. For each read we poll twice, ignoring the first poll. This 1962 is required for timing. We repeat the double poll until there is data 1963 available. The number of lines (or number of buffers in our buffer space) 1964 is calculated from the size of the data available from the scanner. The 1965 number of buffers is calculated as the space required to hold 1.5 times 1966 the size of the data available from the scanner. 1967 1968 After data is read from the scanner each line is checked if it is on the 1969 home dot. Lines are continued to be read until we are no longer on the home 1970 dot. */ 1971 1972 1973 SANE_Int devnum; 1974 SANE_Status status; 1975 int i, j; 1976 SANE_Byte poll_result[3]; 1977 SANE_Byte *buffer; 1978 SANE_Byte *buffer_start; 1979 SANE_Byte temp_byte; 1980 1981 SANE_Int buffer_count = 0; 1982 SANE_Int size_requested; 1983 SANE_Int size_returned; 1984 SANE_Int no_of_buffers; 1985 SANE_Int buffer_limit = 0xF3C; 1986 1987 SANE_Int high_byte, mid_byte, low_byte; 1988 SANE_Int home_line_count; 1989 SANE_Bool in_home_region; 1990 1991 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; 1992 1993 static SANE_Byte command5_block[] = { 0x91, 0x00, 0xff, 0xc0 }; 1994#ifdef DEEP_DEBUG 1995 FILE *img = NULL; 1996#endif 1997 1998 size_t cmd_size; 1999 SANE_Bool got_line; 2000 2001 devnum = dev->devnum; 2002 2003 DBG (2, "sanei_lexmark_low_search_home_bwd:\n"); 2004 2005 /* set up registers */ 2006 switch (dev->model.sensor_type) 2007 { 2008 case X74_SENSOR: 2009 dev->shadow_regs[0x2c] = 0x03; 2010 dev->shadow_regs[0x2d] = 0x45; 2011 dev->shadow_regs[0x34] = 0x09; 2012 dev->shadow_regs[0x35] = 0x09; 2013 dev->shadow_regs[0x36] = 0x11; 2014 dev->shadow_regs[0x37] = 0x11; 2015 dev->shadow_regs[0x38] = 0x19; 2016 dev->shadow_regs[0x85] = 0x00; 2017 dev->shadow_regs[0x93] = 0x06; 2018 dev->shadow_regs[0x40] = 0x80; 2019 /* important for detection of b/w transitions */ 2020 dev->shadow_regs[0x75] = 0x00; 2021 dev->shadow_regs[0x8b] = 0xff; 2022 break; 2023 case X1100_B2_SENSOR: 2024 dev->shadow_regs[0x2c] = 0x0f; 2025 dev->shadow_regs[0x2d] = 0x51; 2026 dev->shadow_regs[0x34] = 0x07; 2027 dev->shadow_regs[0x35] = 0x07; 2028 dev->shadow_regs[0x36] = 0x0f; 2029 dev->shadow_regs[0x37] = 0x0f; 2030 dev->shadow_regs[0x38] = 0x15; 2031 dev->shadow_regs[0x85] = 0x20; 2032 dev->shadow_regs[0x93] = 0x06; 2033 break; 2034 case X1100_2C_SENSOR: 2035 dev->shadow_regs[0x2c] = 0x0d; 2036 dev->shadow_regs[0x2d] = 0x4f; 2037 dev->shadow_regs[0x34] = 0x09; 2038 dev->shadow_regs[0x35] = 0x09; 2039 dev->shadow_regs[0x36] = 0x11; 2040 dev->shadow_regs[0x37] = 0x11; 2041 dev->shadow_regs[0x38] = 0x19; 2042 dev->shadow_regs[0x85] = 0x20; 2043 dev->shadow_regs[0x93] = 0x06; 2044 break; 2045 case A920_SENSOR: 2046 dev->shadow_regs[0x2c] = 0x0d; 2047 dev->shadow_regs[0x2d] = 0x4f; 2048 dev->shadow_regs[0x34] = 0x09; 2049 dev->shadow_regs[0x35] = 0x09; 2050 dev->shadow_regs[0x36] = 0x11; 2051 dev->shadow_regs[0x37] = 0x11; 2052 dev->shadow_regs[0x38] = 0x19; 2053 dev->shadow_regs[0x85] = 0x05; 2054 dev->shadow_regs[0x93] = 0x0e; 2055 break; 2056 case X1200_SENSOR: 2057 dev->shadow_regs[0x2c] = 0x01; 2058 dev->shadow_regs[0x2d] = 0x03; 2059 dev->shadow_regs[0x34] = 0x07; 2060 dev->shadow_regs[0x35] = 0x07; 2061 dev->shadow_regs[0x36] = 0x0f; 2062 dev->shadow_regs[0x37] = 0x0f; 2063 dev->shadow_regs[0x38] = 0x15; 2064 break; 2065 2066 case X1200_USB2_SENSOR: 2067 dev->shadow_regs[0x2c] = 0x0d; 2068 dev->shadow_regs[0x2d] = 0x4f; 2069 dev->shadow_regs[0x34] = 0x09; 2070 dev->shadow_regs[0x35] = 0x09; 2071 dev->shadow_regs[0x36] = 0x11; 2072 dev->shadow_regs[0x37] = 0x11; 2073 dev->shadow_regs[0x38] = 0x19; 2074 dev->shadow_regs[0x85] = 0x03; 2075 dev->shadow_regs[0x93] = 0x06; 2076 break; 2077 } 2078 rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain, 2079 dev->sensor->default_gain, dev->sensor->default_gain); 2080 dev->shadow_regs[0x65] = 0x80; 2081 dev->shadow_regs[0x8b] = 0xff; 2082 dev->shadow_regs[0x8c] = 0x02; 2083 dev->shadow_regs[0xb2] = 0x00; 2084 2085 /* set calibration */ 2086 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); 2087 2088 /* set grayscale scan */ 2089 dev->shadow_regs[0x2f] = 0x21; 2090 /* set motor resolution divisor */ 2091 dev->shadow_regs[0x39] = 0x03; 2092 /* set vertical start/end positions */ 2093 dev->shadow_regs[0x60] = 0x0a; 2094 dev->shadow_regs[0x61] = 0x00; 2095 dev->shadow_regs[0x62] = 0x46; 2096 dev->shadow_regs[0x63] = 0x0f; 2097 /* set # of head moves per CIS read */ 2098 rts88xx_set_scan_frequency (dev->shadow_regs, 2); 2099 /* set horizontal start position */ 2100 dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */ 2101 dev->shadow_regs[0x67] = 0x00; 2102 /* set horizontal end position */ 2103 dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200, 13f2 for X1200/rev. 97 */ 2104 dev->shadow_regs[0x6d] = 0x13; 2105 /* set horizontal resolution */ 2106 dev->shadow_regs[0x79] = 0x40; 2107 dev->shadow_regs[0x7a] = 0x02; 2108 2109 /* Movement direction & step size */ 2110 dev->shadow_regs[0xc6] = 0x01; 2111 /* Motor enable & Coordinate space denominator */ 2112 dev->shadow_regs[0xc3] = 0x81; 2113 2114 switch (dev->model.motor_type) 2115 { 2116 case X74_MOTOR: 2117 dev->shadow_regs[0xc4] = 0x20; 2118 dev->shadow_regs[0xc5] = 0x00; 2119 dev->shadow_regs[0xc8] = 0x04; 2120 /* step size range2 */ 2121 dev->shadow_regs[0xc9] = 0x39; 2122 dev->shadow_regs[0xca] = 0x00; 2123 /* motor curve stuff */ 2124 dev->shadow_regs[0xe0] = 0x29; 2125 dev->shadow_regs[0xe1] = 0x17; 2126 dev->shadow_regs[0xe2] = 0x8f; 2127 dev->shadow_regs[0xe3] = 0x06; 2128 dev->shadow_regs[0xe4] = 0x61; 2129 dev->shadow_regs[0xe5] = 0x16; 2130 dev->shadow_regs[0xe6] = 0x64; 2131 dev->shadow_regs[0xe7] = 0xb5; 2132 dev->shadow_regs[0xe8] = 0x08; 2133 dev->shadow_regs[0xe9] = 0x32; 2134 dev->shadow_regs[0xec] = 0x0c; 2135 dev->shadow_regs[0xef] = 0x08; 2136 break; 2137 case A920_MOTOR: 2138 case X1100_MOTOR: 2139 /* ? */ 2140 dev->shadow_regs[0xc5] = 0x19; 2141 /* step size range2 */ 2142 dev->shadow_regs[0xc9] = 0x3a; 2143 /* ? */ 2144 dev->shadow_regs[0xca] = 0x08; 2145 /* motor curve stuff */ 2146 dev->shadow_regs[0xe0] = 0xe3; 2147 dev->shadow_regs[0xe1] = 0x18; 2148 dev->shadow_regs[0xe2] = 0x03; 2149 dev->shadow_regs[0xe3] = 0x06; 2150 dev->shadow_regs[0xe4] = 0x2b; 2151 dev->shadow_regs[0xe5] = 0x17; 2152 dev->shadow_regs[0xe6] = 0xdc; 2153 dev->shadow_regs[0xe7] = 0xb3; 2154 dev->shadow_regs[0xe8] = 0x07; 2155 dev->shadow_regs[0xe9] = 0x1b; 2156 dev->shadow_regs[0xec] = 0x07; 2157 dev->shadow_regs[0xef] = 0x03; 2158 break; 2159 } 2160 2161 /* Stop the scanner */ 2162 low_stop_mvmt (devnum); 2163 2164 /* write regs out twice */ 2165 dev->shadow_regs[0x32] = 0x00; 2166 low_write_all_regs (devnum, dev->shadow_regs); 2167 dev->shadow_regs[0x32] = 0x40; 2168 low_write_all_regs (devnum, dev->shadow_regs); 2169 2170 /* Start Scan */ 2171 status = rts88xx_commit (devnum, dev->shadow_regs[0x2c]); 2172 2173 /* create buffer to hold up to 10 lines of scan data */ 2174 buffer = calloc (10 * 2500, sizeof (char)); 2175 if (buffer == NULL) 2176 { 2177 return SANE_FALSE; 2178 } 2179 2180 home_line_count = 0; 2181 in_home_region = SANE_FALSE; 2182 2183#ifdef DEEP_DEBUG 2184 img = fopen ("find_bwd.pnm", "wb"); 2185 fprintf (img, "P5\n2500 100\n255\n"); 2186#endif 2187 while (buffer_count < buffer_limit) 2188 { 2189 size_returned = 0; 2190 got_line = SANE_FALSE; 2191 while (!got_line) 2192 { 2193 /* always poll twice (needed for timing) - disregard 1st poll */ 2194 cmd_size = 4; 2195 status = low_usb_bulk_write (devnum, command4_block, &cmd_size); 2196 if (status != SANE_STATUS_GOOD) 2197 return SANE_FALSE; 2198 cmd_size = 0x3; 2199 status = low_usb_bulk_read (devnum, poll_result, &cmd_size); 2200 if (status != SANE_STATUS_GOOD) 2201 return SANE_FALSE; 2202 cmd_size = 4; 2203 status = low_usb_bulk_write (devnum, command4_block, &cmd_size); 2204 if (status != SANE_STATUS_GOOD) 2205 return SANE_FALSE; 2206 cmd_size = 0x3; 2207 status = low_usb_bulk_read (devnum, poll_result, &cmd_size); 2208 if (status != SANE_STATUS_GOOD) 2209 return SANE_FALSE; 2210 if (! 2211 (poll_result[0] == 0 && poll_result[1] == 0 2212 && poll_result[2] == 0)) 2213 { 2214 /* if result != 00 00 00 we got data */ 2215 got_line = SANE_TRUE; 2216 high_byte = poll_result[2] << 16; 2217 mid_byte = poll_result[1] << 8; 2218 low_byte = poll_result[0]; 2219 size_returned = high_byte + mid_byte + low_byte; 2220 } 2221 } 2222 2223 /*size_requested = size_returned;*/ 2224 size_requested = 2500; 2225 no_of_buffers = size_returned * 3; 2226 no_of_buffers = no_of_buffers / 2500; 2227 no_of_buffers = no_of_buffers >> 1; 2228 /* force 1 buffer at a time to improve accuracy, which slow downs search */ 2229 no_of_buffers = 1; 2230 2231 if (no_of_buffers < 1) 2232 no_of_buffers = 1; 2233 else if (no_of_buffers > 10) 2234 no_of_buffers = 10; 2235 buffer_count = buffer_count + no_of_buffers; 2236 2237 size_requested = no_of_buffers * 2500; 2238 2239 /* Tell the scanner to send the data */ 2240 /* Write: 91 <size_requested> */ 2241 command5_block[1] = (SANE_Byte) (size_requested >> 16); 2242 command5_block[2] = (SANE_Byte) (size_requested >> 8); 2243 command5_block[3] = (SANE_Byte) (size_requested & 0xFF); 2244 2245 cmd_size = 4; 2246 status = low_usb_bulk_write (devnum, command5_block, &cmd_size); 2247 if (status != SANE_STATUS_GOOD) 2248 return SANE_FALSE; 2249 /* Read it */ 2250 cmd_size = size_requested; 2251 status = low_usb_bulk_read (devnum, buffer, &cmd_size); 2252 if (status != SANE_STATUS_GOOD) 2253 return SANE_FALSE; 2254 for (i = 0; i < no_of_buffers; i++) 2255 { 2256 buffer_start = buffer + (i * 2500); 2257 /* Reverse order of bytes in words of buffer */ 2258 for (j = 0; j < 2500; j = j + 2) 2259 { 2260 temp_byte = *(buffer_start + j); 2261 *(buffer_start + j) = *(buffer_start + j + 1); 2262 *(buffer_start + j + 1) = temp_byte; 2263 } 2264#ifdef DEEP_DEBUG 2265 fwrite (buffer + (i * 2500), 2500, 1, img); 2266#endif 2267 if (low_is_home_line (dev, buffer_start)) 2268 { 2269 home_line_count++; 2270 if (home_line_count > 7) 2271 in_home_region = SANE_TRUE; 2272 } 2273 if (in_home_region) 2274 { 2275 /* slow down scanning : on purpose backtracking */ 2276 if (home_line_count) 2277 sleep (1); 2278 free (buffer); 2279#ifdef DEEP_DEBUG 2280 fflush (img); 2281 i = ftell (img) / 2500; 2282 rewind (img); 2283 DBG (2, "sanei_lexmark_low_search_home_bwd: offset=%d\n", i); 2284 fprintf (img, "P5\n2500 %03d\n", i); 2285 fclose (img); 2286#endif 2287 low_stop_mvmt (devnum); 2288 DBG (2, 2289 "sanei_lexmark_low_search_home_bwd: in home region, end.\n"); 2290 return SANE_TRUE; 2291 } 2292 } 2293 } /* end while (buffer_count > buffer_limit); */ 2294 free (buffer); 2295#ifdef DEEP_DEBUG 2296 fflush (img); 2297 i = ftell (img) / 2500; 2298 rewind (img); 2299 fprintf (img, "P5\n2500 %03d\n", i); 2300 fclose (img); 2301#endif 2302 low_stop_mvmt (devnum); 2303 2304 DBG (2, "sanei_lexmark_low_search_home_bwd: end.\n"); 2305 2306 return SANE_FALSE; 2307} 2308 2309SANE_Status 2310low_get_start_loc (SANE_Int resolution, SANE_Int * vert_start, 2311 SANE_Int * hor_start, SANE_Int offset, 2312 Lexmark_Device * dev) 2313{ 2314 SANE_Int start_600; 2315 2316 switch (dev->model.sensor_type) 2317 { 2318 case X1100_2C_SENSOR: 2319 case X1200_USB2_SENSOR: 2320 case A920_SENSOR: 2321 case X1200_SENSOR: 2322 start_600 = 195 - offset; 2323 *hor_start = 0x68; 2324 break; 2325 case X1100_B2_SENSOR: 2326 start_600 = 195 - offset; 2327 switch (resolution) 2328 { 2329 case 75: 2330 *hor_start = 0x68; 2331 break; 2332 case 150: 2333 *hor_start = 0x68; 2334 break; 2335 case 300: 2336 *hor_start = 0x6a; 2337 break; 2338 case 600: 2339 *hor_start = 0x6b; 2340 break; 2341 case 1200: 2342 *hor_start = 0x6b; 2343 break; 2344 default: 2345 /* If we're here we have an invalid resolution */ 2346 return SANE_STATUS_INVAL; 2347 } 2348 break; 2349 case X74_SENSOR: 2350 start_600 = 268 - offset; 2351 switch (resolution) 2352 { 2353 case 75: 2354 *hor_start = 0x48; 2355 break; 2356 case 150: 2357 *hor_start = 0x48; 2358 break; 2359 case 300: 2360 *hor_start = 0x4a; 2361 break; 2362 case 600: 2363 *hor_start = 0x4b; 2364 break; 2365 default: 2366 /* If we're here we have an invalid resolution */ 2367 return SANE_STATUS_INVAL; 2368 } 2369 break; 2370 default: 2371 /* If we're here we have an unknown dev->model.sensor_type */ 2372 return SANE_STATUS_INVAL; 2373 } 2374 /* Calculate vertical start distance at 600dpi */ 2375 switch (resolution) 2376 { 2377 case 75: 2378 *vert_start = start_600 / 8; 2379 break; 2380 case 150: 2381 *vert_start = start_600 / 4; 2382 break; 2383 case 300: 2384 *vert_start = start_600 / 2; 2385 break; 2386 case 600: 2387 *vert_start = start_600; 2388 break; 2389 case 1200: 2390 *vert_start = start_600 * 2; 2391 break; 2392 default: 2393 /* If we're here we have an invalid resolution */ 2394 return SANE_STATUS_INVAL; 2395 } 2396 2397 return SANE_STATUS_GOOD; 2398} 2399 2400void 2401low_set_scan_area (SANE_Int res, 2402 SANE_Int tlx, 2403 SANE_Int tly, 2404 SANE_Int brx, 2405 SANE_Int bry, 2406 SANE_Int offset, 2407 SANE_Bool half_step, 2408 SANE_Byte * regs, Lexmark_Device * dev) 2409{ 2410 2411 SANE_Int vert_start = 0; 2412 SANE_Int hor_start = 0; 2413 SANE_Int vert_end; 2414 SANE_Int hor_end; 2415 2416 low_get_start_loc (res, &vert_start, &hor_start, offset, dev); 2417 2418 /* convert pixel height to vertical location coordinates */ 2419 vert_end = vert_start + (bry * res) / 600; 2420 vert_start += (tly * res) / 600; 2421 2422 /* scan area size : for A920, 600 color scans are done at 1200 y dpi */ 2423 /* this follow what was found in usb logs */ 2424 if (half_step) 2425 { 2426 vert_end = vert_end * 2; 2427 vert_start = vert_start * 2; 2428 } 2429 2430 /* set vertical start position registers */ 2431 regs[0x60] = LOBYTE (vert_start); 2432 regs[0x61] = HIBYTE (vert_start); 2433 /* set vertical end position registers */ 2434 regs[0x62] = LOBYTE (vert_end); 2435 regs[0x63] = HIBYTE (vert_end); 2436 2437 /* convert pixel width to horizontal location coordinates */ 2438 2439 hor_end = hor_start + brx; 2440 hor_start += tlx; 2441 2442 regs[0x66] = LOBYTE (hor_start); 2443 regs[0x67] = HIBYTE (hor_start); 2444 /* set horizontal end position registers */ 2445 regs[0x6c] = LOBYTE (hor_end); 2446 regs[0x6d] = HIBYTE (hor_end); 2447 2448 /* Debug */ 2449 DBG (2, "low_set_scan_area: vert_start: %d (tly=%d)\n", vert_start, tly); 2450 DBG (2, "low_set_scan_area: vert_end: %d\n", vert_end); 2451 DBG (2, "low_set_scan_area: hor_start: %d\n", hor_start); 2452 DBG (2, "low_set_scan_area: hor_end: %d\n", hor_end); 2453 2454} 2455 2456SANE_Int 2457sanei_lexmark_low_find_start_line (Lexmark_Device * dev) 2458{ 2459 /* 2460 This function scans forward 59 lines, reading 88 bytes per line from the 2461 middle of the horizontal line: pixel 0xa84 to pixel 0x9d4. It scans with 2462 the following parameters: 2463 dir=fwd 2464 mode=grayscale 2465 h.res=300 dpi 2466 v.res=600 dpi 2467 hor. pixels = (0xa84 - 0x9d4)/2 = 0x58 = 88 2468 vert. pixels = 0x3e - 0x03 = 0x3b = 59 2469 data = 88x59=5192=0x1448 2470 2471 It assumes we are in the start dot, or just before it. We are reading 2472 enough lines at 600dpi to read past the dot. We return the number of 2473 entirely white lines read consecutively, so we know how far past the 2474 dot we are. 2475 2476 To find the number of consecutive white lines we do the following: 2477 2478 Byte swap the order of the bytes in the buffer. 2479 2480 Go through the buffer finding low and high values, which are computed by 2481 comparing to the weighted average: 2482 weighted_average = (lowest value + (highest value - lowest value)/4) 2483 Low bytes are changed to 0xFF (white), higher of equal bytes are changed 2484 to 0x00 (black),so that the buffer only contains white (0xFF) or black 2485 (0x00) values. 2486 2487 Next, we go through the buffer a line (88 bytes) at a time for 59 lines 2488 to read the entire buffer. For each byte in a line we check if the 2489 byte is black. If it is we increment the black byte counter. 2490 2491 After each line we check the black byte counter. If it is greater than 0 2492 we increment the black line count and set the white line count to 0. If 2493 there were no black bytes in the line we set the black line count to 0 2494 and increment the white line count. 2495 2496 When all lines have been processed we return the white line count. 2497 */ 2498 2499 2500 int blackLineCount = 0; 2501 int whiteLineCount = 0; 2502 int blackByteCounter = 0; 2503 unsigned char max_byte = 0; 2504 unsigned char min_byte = 0xFF; 2505 unsigned char weighted_average; 2506 int i, j; 2507#ifdef DEEP_DEBUG 2508 FILE *fdbg = NULL; 2509#endif 2510 2511 SANE_Byte poll_result[3]; 2512 SANE_Byte *buffer; 2513 SANE_Byte temp_byte; 2514 2515 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; 2516 2517 static SANE_Byte command5_block[] = { 0x91, 0x00, 0x14, 0x48 }; 2518 2519 size_t cmd_size; 2520 SANE_Bool got_line; 2521 2522 DBG (2, "sanei_lexmark_low_find_start_line:\n"); 2523 2524 2525 /* set up registers */ 2526 switch (dev->model.sensor_type) 2527 { 2528 case X74_SENSOR: 2529 dev->shadow_regs[0x2c] = 0x04; 2530 dev->shadow_regs[0x2d] = 0x46; 2531 dev->shadow_regs[0x34] = 0x05; 2532 dev->shadow_regs[0x35] = 0x05; 2533 dev->shadow_regs[0x36] = 0x0b; 2534 dev->shadow_regs[0x37] = 0x0b; 2535 dev->shadow_regs[0x38] = 0x11; 2536 dev->shadow_regs[0x40] = 0x40; 2537 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); 2538 break; 2539 case X1100_B2_SENSOR: 2540 dev->shadow_regs[0x2c] = 0x0f; 2541 dev->shadow_regs[0x2d] = 0x51; 2542 dev->shadow_regs[0x34] = 0x0d; 2543 dev->shadow_regs[0x35] = 0x0d; 2544 dev->shadow_regs[0x36] = 0x1d; 2545 dev->shadow_regs[0x37] = 0x1d; 2546 dev->shadow_regs[0x38] = 0x29; 2547 dev->shadow_regs[0x65] = 0x80; 2548 dev->shadow_regs[0x85] = 0x00; 2549 dev->shadow_regs[0x93] = 0x06; 2550 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); 2551 break; 2552 case X1100_2C_SENSOR: 2553 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); 2554 dev->shadow_regs[0x28] = 0xf5; 2555 dev->shadow_regs[0x29] = 0xf7; 2556 dev->shadow_regs[0x2a] = 0xf5; 2557 dev->shadow_regs[0x2b] = 0x17; 2558 2559 dev->shadow_regs[0x2c] = 0x0d; 2560 dev->shadow_regs[0x2d] = 0x4f; 2561 dev->shadow_regs[0x31] = 0x01; 2562 dev->shadow_regs[0x34] = 0x11; 2563 dev->shadow_regs[0x35] = 0x11; 2564 dev->shadow_regs[0x36] = 0x21; 2565 dev->shadow_regs[0x37] = 0x21; 2566 dev->shadow_regs[0x38] = 0x31; 2567 dev->shadow_regs[0x72] = 0x35; 2568 dev->shadow_regs[0x74] = 0x4e; 2569 dev->shadow_regs[0x85] = 0x02; 2570 dev->shadow_regs[0x86] = 0x33; 2571 dev->shadow_regs[0x87] = 0x0f; 2572 dev->shadow_regs[0x88] = 0x24; 2573 dev->shadow_regs[0x91] = 0x19; 2574 dev->shadow_regs[0x92] = 0x20; 2575 dev->shadow_regs[0xea] = 0x00; 2576 dev->shadow_regs[0xeb] = 0x00; 2577 break; 2578 case A920_SENSOR: 2579 dev->shadow_regs[0x2c] = 0x0d; 2580 dev->shadow_regs[0x2d] = 0x4f; 2581 dev->shadow_regs[0x34] = 0x11; 2582 dev->shadow_regs[0x35] = 0x11; 2583 dev->shadow_regs[0x36] = 0x21; 2584 dev->shadow_regs[0x37] = 0x21; 2585 dev->shadow_regs[0x38] = 0x31; 2586 dev->shadow_regs[0x85] = 0x05; 2587 dev->shadow_regs[0x88] = 0x44; 2588 dev->shadow_regs[0x92] = 0x85; 2589 dev->shadow_regs[0x93] = 0x0e; 2590 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); 2591 break; 2592 case X1200_SENSOR: 2593 dev->shadow_regs[0x2c] = 0x01; 2594 dev->shadow_regs[0x2d] = 0x03; 2595 dev->shadow_regs[0x34] = 0x0d; 2596 dev->shadow_regs[0x35] = 0x0d; 2597 dev->shadow_regs[0x36] = 0x1d; 2598 dev->shadow_regs[0x37] = 0x1d; 2599 dev->shadow_regs[0x38] = 0x29; 2600 dev->shadow_regs[0xea] = 0x00; 2601 dev->shadow_regs[0xeb] = 0x00; 2602 dev->shadow_regs[0x40] = 0x80; 2603 dev->shadow_regs[0x50] = 0x00; 2604 dev->shadow_regs[0x81] = 0x00; 2605 dev->shadow_regs[0x82] = 0x00; 2606 dev->shadow_regs[0x85] = 0x00; 2607 dev->shadow_regs[0x86] = 0x00; 2608 dev->shadow_regs[0x87] = 0xff; 2609 dev->shadow_regs[0x88] = 0x02; 2610 dev->shadow_regs[0x92] = 0x00; 2611 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); 2612 break; 2613 case X1200_USB2_SENSOR: 2614 dev->shadow_regs[0x2c] = 0x01; 2615 dev->shadow_regs[0x2d] = 0x03; 2616 dev->shadow_regs[0x34] = 0x0d; 2617 dev->shadow_regs[0x35] = 0x0d; 2618 dev->shadow_regs[0x36] = 0x1d; 2619 dev->shadow_regs[0x37] = 0x1d; 2620 dev->shadow_regs[0x38] = 0x29; 2621 dev->shadow_regs[0xea] = 0x00; 2622 dev->shadow_regs[0xeb] = 0x00; 2623 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); 2624 break; 2625 } 2626 2627 /* set offset to a safe value */ 2628 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); 2629 /* set grayscale scan */ 2630 dev->shadow_regs[0x2f] = 0x21; 2631 /* set motor resolution divisor */ 2632 dev->shadow_regs[0x39] = 0x01; 2633 /* set vertical start/end positions */ 2634 dev->shadow_regs[0x60] = 0x03; 2635 dev->shadow_regs[0x61] = 0x00; 2636 dev->shadow_regs[0x62] = 0x3e; 2637 dev->shadow_regs[0x63] = 0x00; 2638 /* set # of head moves per CIS read */ 2639 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 2640 /* set horizontal start position */ 2641 dev->shadow_regs[0x66] = 0xd4; /* 0xf2 for X1200 */ 2642 dev->shadow_regs[0x67] = 0x09; 2643 /* set horizontal end position */ 2644 dev->shadow_regs[0x6c] = 0x84; /* 0xa2 for X1200 */ 2645 dev->shadow_regs[0x6d] = 0x0a; 2646 /* set horizontal resolution */ 2647 dev->shadow_regs[0x79] = 0x40; 2648 dev->shadow_regs[0x7a] = 0x02; 2649 /* set for ? */ 2650 /* Motor enable & Coordinate space denominator */ 2651 dev->shadow_regs[0xc3] = 0x81; 2652 2653 2654 2655 2656 2657 switch (dev->model.motor_type) 2658 { 2659 case X1100_MOTOR: 2660 case A920_MOTOR: 2661 /* set for ? */ 2662 dev->shadow_regs[0xc5] = 0x22; 2663 /* Movement direction & step size */ 2664 dev->shadow_regs[0xc6] = 0x09; 2665 /* step size range2 */ 2666 dev->shadow_regs[0xc9] = 0x3b; 2667 /* set for ? */ 2668 dev->shadow_regs[0xca] = 0x1f; 2669 dev->shadow_regs[0xe0] = 0xf7; 2670 dev->shadow_regs[0xe1] = 0x16; 2671 /* step size range0 */ 2672 dev->shadow_regs[0xe2] = 0x87; 2673 /* ? */ 2674 dev->shadow_regs[0xe3] = 0x13; 2675 dev->shadow_regs[0xe4] = 0x1b; 2676 dev->shadow_regs[0xe5] = 0x16; 2677 dev->shadow_regs[0xe6] = 0xdc; 2678 dev->shadow_regs[0xe7] = 0x00; 2679 dev->shadow_regs[0xe8] = 0x00; 2680 dev->shadow_regs[0xe9] = 0x1b; 2681 dev->shadow_regs[0xec] = 0x07; 2682 dev->shadow_regs[0xef] = 0x03; 2683 break; 2684 case X74_MOTOR: 2685 dev->shadow_regs[0xc4] = 0x20; 2686 dev->shadow_regs[0xc5] = 0x22; 2687 /* Movement direction & step size */ 2688 dev->shadow_regs[0xc6] = 0x0b; 2689 2690 dev->shadow_regs[0xc8] = 0x04; 2691 dev->shadow_regs[0xc9] = 0x39; 2692 dev->shadow_regs[0xca] = 0x1f; 2693 2694 /* bounds of movement range0 */ 2695 dev->shadow_regs[0xe0] = 0x2f; 2696 dev->shadow_regs[0xe1] = 0x11; 2697 /* step size range0 */ 2698 dev->shadow_regs[0xe2] = 0x9f; 2699 /* ? */ 2700 dev->shadow_regs[0xe3] = 0x0f; 2701 /* bounds of movement range1 */ 2702 dev->shadow_regs[0xe4] = 0xcb; 2703 2704 dev->shadow_regs[0xe5] = 0x10; 2705 /* step size range1 */ 2706 dev->shadow_regs[0xe6] = 0x64; 2707 /* bounds of movement range2 */ 2708 dev->shadow_regs[0xe7] = 0x00; 2709 dev->shadow_regs[0xe8] = 0x00; 2710 /* step size range2 */ 2711 dev->shadow_regs[0xe9] = 0x32; 2712 /* bounds of movement range3 */ 2713 dev->shadow_regs[0xea] = 0x00; 2714 dev->shadow_regs[0xeb] = 0x00; 2715 /* step size range3 */ 2716 dev->shadow_regs[0xec] = 0x0c; 2717 /* bounds of movement range4 -only for 75dpi grayscale */ 2718 dev->shadow_regs[0xed] = 0x00; 2719 dev->shadow_regs[0xee] = 0x00; 2720 /* step size range4 */ 2721 dev->shadow_regs[0xef] = 0x08; 2722 break; 2723 } 2724 2725 2726 /* Stop the scanner */ 2727 low_stop_mvmt (dev->devnum); 2728 2729 /* write regs out twice */ 2730 dev->shadow_regs[0x32] = 0x00; 2731 low_write_all_regs (dev->devnum, dev->shadow_regs); 2732 dev->shadow_regs[0x32] = 0x40; 2733 low_write_all_regs (dev->devnum, dev->shadow_regs); 2734 2735 /* Start Scan */ 2736 rts88xx_commit (dev->devnum, dev->shadow_regs[0x2c]); 2737 2738 /* Poll the available byte count until not 0 */ 2739 got_line = SANE_FALSE; 2740 while (!got_line) 2741 { 2742 cmd_size = 4; 2743 low_usb_bulk_write (dev->devnum, command4_block, &cmd_size); 2744 cmd_size = 0x3; 2745 low_usb_bulk_read (dev->devnum, poll_result, &cmd_size); 2746 if (! 2747 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) 2748 { 2749 /* if result != 00 00 00 we got data */ 2750 got_line = SANE_TRUE; 2751 } 2752#ifdef FAKE_USB 2753 got_line = SANE_TRUE; 2754#endif 2755 } 2756 2757 2758 /* create buffer for scan data */ 2759 buffer = calloc (5192, sizeof (char)); 2760 if (buffer == NULL) 2761 { 2762 return -1; 2763 } 2764 2765 /* Tell the scanner to send the data */ 2766 /* Write: 91 00 14 48 */ 2767 cmd_size = 4; 2768 low_usb_bulk_write (dev->devnum, command5_block, &cmd_size); 2769 /* Read it */ 2770 cmd_size = 0x1448; 2771 low_usb_bulk_read (dev->devnum, buffer, &cmd_size); 2772 2773 /* Stop the scanner */ 2774 low_stop_mvmt (dev->devnum); 2775 2776 2777 /* Reverse order of bytes in words of buffer */ 2778 for (i = 0; i < 5192; i = i + 2) 2779 { 2780 temp_byte = *(buffer + i); 2781 *(buffer + i) = *(buffer + i + 1); 2782 *(buffer + i + 1) = temp_byte; 2783 } 2784 2785#ifdef DEEP_DEBUG 2786 fdbg = fopen ("find_start.pnm", "wb"); 2787 if (fdbg != NULL) 2788 { 2789 fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59); 2790 fwrite (buffer, 5192, 1, fdbg); 2791 fclose (fdbg); 2792 } 2793#endif 2794 2795 /* Find the max and the min */ 2796 for (i = 0; i < 5192; i++) 2797 { 2798 if (*(buffer + i) > max_byte) 2799 max_byte = *(buffer + i); 2800 if (*(buffer + i) < min_byte) 2801 min_byte = *(buffer + i); 2802 } 2803 2804 weighted_average = min_byte + ((max_byte - min_byte) / 4); 2805 2806 /* Set bytes as black (0x00) or white (0xFF) */ 2807 for (i = 0; i < 5192; i++) 2808 { 2809 if (*(buffer + i) > weighted_average) 2810 *(buffer + i) = 0xFF; 2811 else 2812 *(buffer + i) = 0x00; 2813 } 2814 2815#ifdef DEEP_DEBUG 2816 fdbg = fopen ("find_start_after.pnm", "wb"); 2817 if (fdbg != NULL) 2818 { 2819 fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59); 2820 fwrite (buffer, 5192, 1, fdbg); 2821 fclose (fdbg); 2822 } 2823#endif 2824 2825 /* Go through 59 lines */ 2826 for (j = 0; j < 59; j++) 2827 { 2828 blackByteCounter = 0; 2829 /* Go through 88 bytes per line */ 2830 for (i = 0; i < 88; i++) 2831 { 2832 /* Is byte black? */ 2833 if (*(buffer + (j * 88) + i) == 0) 2834 { 2835 blackByteCounter++; 2836 } 2837 } /* end for line */ 2838 if (blackByteCounter > 0) 2839 { 2840 /* This was a black line */ 2841 blackLineCount++; 2842 whiteLineCount = 0; 2843 } 2844 else 2845 { 2846 /* This is a white line */ 2847 whiteLineCount++; 2848 blackLineCount = 0; 2849 } 2850 } /* end for buffer */ 2851 2852 free (buffer); 2853 /* Stop the scanner. 2854 This is needed to get the right distance to the scanning area */ 2855 if (dev->model.sensor_type == X74_SENSOR) 2856 low_stop_mvmt (dev->devnum); 2857 2858 DBG (2, "sanei_lexmark_low_find_start_line: end.\n"); 2859 return whiteLineCount; 2860} 2861 2862 2863SANE_Status 2864sanei_lexmark_low_set_scan_regs (Lexmark_Device * dev, SANE_Int resolution, 2865 SANE_Int offset, SANE_Bool calibrated) 2866{ 2867 SANE_Bool isColourScan; 2868 2869 DBG (2, "sanei_lexmark_low_set_scan_regs:\n"); 2870 2871 DBG (7, "sanei_lexmark_low_set_scan_regs: resolution=%d DPI\n", resolution); 2872 2873 /* colour mode */ 2874 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 2875 isColourScan = SANE_TRUE; 2876 else 2877 isColourScan = SANE_FALSE; 2878 2879 /* set up registers */ 2880 switch (dev->model.sensor_type) 2881 { 2882 case X74_SENSOR: 2883 dev->shadow_regs[0x2c] = 0x03; 2884 dev->shadow_regs[0x2d] = 0x45; 2885 break; 2886 case X1100_B2_SENSOR: 2887 dev->shadow_regs[0x2c] = 0x0f; 2888 dev->shadow_regs[0x2d] = 0x51; 2889 break; 2890 case X1100_2C_SENSOR: 2891 dev->shadow_regs[0x2c] = 0x0d; 2892 dev->shadow_regs[0x2d] = 0x4f; 2893 break; 2894 case A920_SENSOR: 2895 dev->shadow_regs[0x2c] = 0x0d; 2896 dev->shadow_regs[0x2d] = 0x4f; 2897 break; 2898 case X1200_SENSOR: 2899 dev->shadow_regs[0x2c] = 0x01; 2900 dev->shadow_regs[0x2d] = 0x03; 2901 break; 2902 case X1200_USB2_SENSOR: 2903 dev->shadow_regs[0x2c] = 0x01; 2904 dev->shadow_regs[0x2d] = 0x03; 2905 break; 2906 } 2907 2908 low_set_scan_area (resolution, 2909 dev->val[OPT_TL_X].w, 2910 dev->val[OPT_TL_Y].w, 2911 dev->val[OPT_BR_X].w, 2912 dev->val[OPT_BR_Y].w, 2913 offset, 2914 (dev->model.motor_type == A920_MOTOR 2915 || dev->model.motor_type == X74_MOTOR) && isColourScan 2916 && (resolution == 600), dev->shadow_regs, dev); 2917 2918 /* may be we could use a sensor descriptor that would held the max horiz dpi */ 2919 if (dev->val[OPT_RESOLUTION].w < 600) 2920 dev->shadow_regs[0x7a] = 600 / dev->val[OPT_RESOLUTION].w; 2921 else 2922 dev->shadow_regs[0x7a] = 1; 2923 2924 /* 75dpi x 75dpi */ 2925 if (resolution == 75) 2926 { 2927 DBG (5, "sanei_lexmark_low_set_scan_regs(): 75 DPI resolution\n"); 2928 2929 if (isColourScan) 2930 { 2931 switch (dev->model.sensor_type) 2932 { 2933 case X74_SENSOR: 2934 2935 dev->shadow_regs[0x34] = 0x04; 2936 dev->shadow_regs[0x36] = 0x03; 2937 dev->shadow_regs[0x38] = 0x03; 2938 2939 dev->shadow_regs[0x79] = 0x08; 2940 2941 dev->shadow_regs[0x80] = 0x0d; 2942 dev->shadow_regs[0x81] = 0x0e; 2943 dev->shadow_regs[0x82] = 0x02; 2944 2945 dev->shadow_regs[0x85] = 0x00; 2946 dev->shadow_regs[0x86] = 0x00; 2947 dev->shadow_regs[0x87] = 0x00; 2948 dev->shadow_regs[0x88] = 0x00; 2949 2950 dev->shadow_regs[0x91] = 0x00; 2951 dev->shadow_regs[0x92] = 0x00; 2952 dev->shadow_regs[0x93] = 0x06;; 2953 2954 break; 2955 2956 case X1100_B2_SENSOR: 2957 dev->shadow_regs[0x34] = 0x05; 2958 dev->shadow_regs[0x36] = 0x05; 2959 dev->shadow_regs[0x38] = 0x05; 2960 2961 dev->shadow_regs[0x80] = 0x0c; 2962 dev->shadow_regs[0x81] = 0x0c; 2963 dev->shadow_regs[0x82] = 0x09; 2964 2965 dev->shadow_regs[0x85] = 0x00; 2966 dev->shadow_regs[0x86] = 0x00; 2967 dev->shadow_regs[0x87] = 0x00; 2968 dev->shadow_regs[0x88] = 0x00; 2969 2970 dev->shadow_regs[0x91] = 0x8c; 2971 dev->shadow_regs[0x92] = 0x40; 2972 dev->shadow_regs[0x93] = 0x06; 2973 break; 2974 2975 case X1100_2C_SENSOR: 2976 dev->shadow_regs[0x34] = 0x03; 2977 dev->shadow_regs[0x36] = 0x04; 2978 dev->shadow_regs[0x38] = 0x03; 2979 2980 dev->shadow_regs[0x80] = 0x00; 2981 dev->shadow_regs[0x81] = 0x02; 2982 dev->shadow_regs[0x82] = 0x03; 2983 2984 dev->shadow_regs[0x85] = 0x20; 2985 dev->shadow_regs[0x86] = 0x00; 2986 dev->shadow_regs[0x87] = 0x00; 2987 dev->shadow_regs[0x88] = 0x00; 2988 2989 dev->shadow_regs[0x91] = 0x00; 2990 dev->shadow_regs[0x92] = 0x00; 2991 dev->shadow_regs[0x93] = 0x06; 2992 break; 2993 2994 case A920_SENSOR: 2995 dev->shadow_regs[0x34] = 0x02; 2996 dev->shadow_regs[0x36] = 0x04; 2997 dev->shadow_regs[0x38] = 0x03; 2998 2999 dev->shadow_regs[0x80] = 0x07; 3000 dev->shadow_regs[0x81] = 0x0f; 3001 dev->shadow_regs[0x82] = 0x03; 3002 3003 dev->shadow_regs[0x85] = 0x05; 3004 dev->shadow_regs[0x86] = 0x14; 3005 dev->shadow_regs[0x87] = 0x06; 3006 dev->shadow_regs[0x88] = 0x44; 3007 3008 dev->shadow_regs[0x91] = 0x60; 3009 dev->shadow_regs[0x92] = 0x85; 3010 dev->shadow_regs[0x93] = 0x0e; 3011 break; 3012 3013 case X1200_SENSOR: 3014 dev->shadow_regs[0x34] = 0x02; 3015 dev->shadow_regs[0x36] = 0x03; 3016 dev->shadow_regs[0x38] = 0x01; 3017 3018 dev->shadow_regs[0x79] = 0x20; 3019 3020 dev->shadow_regs[0x80] = 0x08; 3021 dev->shadow_regs[0x81] = 0x02; 3022 dev->shadow_regs[0x82] = 0x0d; 3023 3024 dev->shadow_regs[0x85] = 0x20; 3025 dev->shadow_regs[0x86] = 0x1e; 3026 dev->shadow_regs[0x87] = 0x39; 3027 dev->shadow_regs[0x88] = 0x00; 3028 3029 dev->shadow_regs[0x91] = 0x00; 3030 /* dev->shadow_regs[0x92] = 0x92; */ 3031 dev->shadow_regs[0x93] = 0x06; 3032 break; 3033 3034 case X1200_USB2_SENSOR: 3035 dev->shadow_regs[0x34] = 0x04; 3036 dev->shadow_regs[0x36] = 0x05; 3037 dev->shadow_regs[0x38] = 0x04; 3038 3039 dev->shadow_regs[0x80] = 0x01; 3040 dev->shadow_regs[0x81] = 0x0a; 3041 dev->shadow_regs[0x82] = 0x0b; 3042 break; 3043 } 3044 3045 switch (dev->model.motor_type) 3046 { 3047 case X74_MOTOR: 3048 dev->shadow_regs[0xc2] = 0x80; 3049 /* ? */ 3050 dev->shadow_regs[0xc4] = 0x20; 3051 dev->shadow_regs[0xc5] = 0x0c; 3052 dev->shadow_regs[0xc6] = 0x0b; 3053 3054 dev->shadow_regs[0xc8] = 0x04; 3055 dev->shadow_regs[0xc9] = 0x39; 3056 dev->shadow_regs[0xca] = 0x01; 3057 3058 /* bounds of movement range0 */ 3059 dev->shadow_regs[0xe0] = 0x1b; 3060 dev->shadow_regs[0xe1] = 0x0a; 3061 /* step size range0 */ 3062 dev->shadow_regs[0xe2] = 0x4f; 3063 /* ? */ 3064 dev->shadow_regs[0xe3] = 0x01; 3065 /* bounds of movement range1 */ 3066 dev->shadow_regs[0xe4] = 0xb3; 3067 3068 dev->shadow_regs[0xe5] = 0x09; 3069 /* step size range1 */ 3070 dev->shadow_regs[0xe6] = 0x0d; 3071 /* bounds of movement range2 */ 3072 dev->shadow_regs[0xe7] = 0xe5; 3073 dev->shadow_regs[0xe8] = 0x02; 3074 /* step size range2 */ 3075 dev->shadow_regs[0xe9] = 0x05; 3076 /* bounds of movement range3 */ 3077 dev->shadow_regs[0xea] = 0xa0; 3078 dev->shadow_regs[0xeb] = 0x01; 3079 /* step size range3 */ 3080 dev->shadow_regs[0xec] = 0x01; 3081 /* bounds of movement range4 */ 3082 dev->shadow_regs[0xed] = 0x00; 3083 dev->shadow_regs[0xee] = 0x00; 3084 /* step size range4 */ 3085 dev->shadow_regs[0xef] = 0x01; 3086 break; 3087 case A920_MOTOR: 3088 case X1100_MOTOR: 3089 /* ? */ 3090 dev->shadow_regs[0xc5] = 0x0a; 3091 /* bounds of movement range0 */ 3092 dev->shadow_regs[0xe0] = 0x2b; 3093 dev->shadow_regs[0xe1] = 0x0a; 3094 /* step size range0 */ 3095 dev->shadow_regs[0xe2] = 0x7f; 3096 /* ? */ 3097 dev->shadow_regs[0xe3] = 0x01; 3098 /* bounds of movement range1 */ 3099 dev->shadow_regs[0xe4] = 0xbb; 3100 dev->shadow_regs[0xe5] = 0x09; 3101 /* step size range1 */ 3102 dev->shadow_regs[0xe6] = 0x0e; 3103 /* bounds of movement range2 */ 3104 dev->shadow_regs[0xe7] = 0x2b; 3105 dev->shadow_regs[0xe8] = 0x03; 3106 /* step size range2 */ 3107 dev->shadow_regs[0xe9] = 0x05; 3108 /* bounds of movement range3 */ 3109 dev->shadow_regs[0xea] = 0xa0; 3110 dev->shadow_regs[0xeb] = 0x01; 3111 /* step size range3 */ 3112 dev->shadow_regs[0xec] = 0x01; 3113 /* step size range4 */ 3114 dev->shadow_regs[0xef] = 0x01; 3115 break; 3116 } 3117 3118 /* set colour scan */ 3119 dev->shadow_regs[0x2f] = 0x11; 3120 3121 dev->shadow_regs[0x35] = 0x01; 3122 dev->shadow_regs[0x37] = 0x01; 3123 /* Motor enable & Coordinate space denominator */ 3124 dev->shadow_regs[0xc3] = 0x83; 3125 } 3126 else /* 75 dpi gray */ 3127 { 3128 switch (dev->model.sensor_type) 3129 { 3130 case X74_SENSOR: 3131 3132 dev->shadow_regs[0x34] = 0x01; 3133 dev->shadow_regs[0x35] = 0x01; 3134 dev->shadow_regs[0x36] = 0x02; 3135 dev->shadow_regs[0x37] = 0x02; 3136 dev->shadow_regs[0x38] = 0x03; 3137 dev->shadow_regs[0x39] = 0x0f; 3138 3139 dev->shadow_regs[0x40] = 0x80; 3140 3141 dev->shadow_regs[0x79] = 0x08; 3142 3143 dev->shadow_regs[0x85] = 0x00; 3144 dev->shadow_regs[0x86] = 0x00; 3145 dev->shadow_regs[0x87] = 0x00; 3146 dev->shadow_regs[0x88] = 0x00; 3147 3148 dev->shadow_regs[0x8c] = 0x02; 3149 dev->shadow_regs[0x8d] = 0x01; 3150 dev->shadow_regs[0x8e] = 0x60; 3151 dev->shadow_regs[0x8f] = 0x80; 3152 3153 dev->shadow_regs[0x91] = 0x00; 3154 dev->shadow_regs[0x92] = 0x00; 3155 dev->shadow_regs[0x93] = 0x06; 3156 3157 break; 3158 3159 case X1100_B2_SENSOR: 3160 dev->shadow_regs[0x34] = 0x02; 3161 dev->shadow_regs[0x35] = 0x02; 3162 dev->shadow_regs[0x36] = 0x04; 3163 dev->shadow_regs[0x37] = 0x04; 3164 dev->shadow_regs[0x38] = 0x06; 3165 3166 dev->shadow_regs[0x85] = 0x20; 3167 dev->shadow_regs[0x86] = 0x00; 3168 dev->shadow_regs[0x87] = 0x00; 3169 dev->shadow_regs[0x88] = 0x00; 3170 3171 dev->shadow_regs[0x91] = 0x00; 3172 dev->shadow_regs[0x92] = 0x00; 3173 dev->shadow_regs[0x93] = 0x06; 3174 break; 3175 case X1100_2C_SENSOR: 3176 dev->shadow_regs[0x34] = 0x01; 3177 dev->shadow_regs[0x35] = 0x01; 3178 dev->shadow_regs[0x36] = 0x02; 3179 dev->shadow_regs[0x37] = 0x02; 3180 dev->shadow_regs[0x38] = 0x03; /* these are half of B2 sensor */ 3181 3182 dev->shadow_regs[0x85] = 0x20; 3183 dev->shadow_regs[0x86] = 0x00; 3184 dev->shadow_regs[0x87] = 0x00; 3185 dev->shadow_regs[0x88] = 0x00; 3186 3187 dev->shadow_regs[0x91] = 0x00; 3188 dev->shadow_regs[0x92] = 0x00; 3189 dev->shadow_regs[0x92] = 0x00; 3190 dev->shadow_regs[0x93] = 0x06; 3191 break; 3192 case A920_SENSOR: 3193 dev->shadow_regs[0x34] = 0x01; 3194 dev->shadow_regs[0x35] = 0x01; 3195 dev->shadow_regs[0x36] = 0x02; 3196 dev->shadow_regs[0x37] = 0x02; 3197 dev->shadow_regs[0x38] = 0x03; 3198 3199 dev->shadow_regs[0x85] = 0x0d; 3200 dev->shadow_regs[0x86] = 0x14; 3201 dev->shadow_regs[0x87] = 0x06; 3202 dev->shadow_regs[0x88] = 0x45; 3203 3204 dev->shadow_regs[0x91] = 0x60; 3205 dev->shadow_regs[0x92] = 0x8d; 3206 dev->shadow_regs[0x93] = 0x0e; 3207 break; 3208 case X1200_SENSOR: 3209 dev->shadow_regs[0x34] = 0x01; 3210 dev->shadow_regs[0x35] = 0x01; 3211 dev->shadow_regs[0x36] = 0x02; 3212 dev->shadow_regs[0x37] = 0x02; 3213 dev->shadow_regs[0x38] = 0x02; 3214 3215 dev->shadow_regs[0x79] = 0x20; 3216 3217 dev->shadow_regs[0x85] = 0x00; 3218 dev->shadow_regs[0x86] = 0x00; 3219 dev->shadow_regs[0x87] = 0xff; 3220 dev->shadow_regs[0x88] = 0x02; 3221 3222 dev->shadow_regs[0x92] = 0x00; 3223 break; 3224 case X1200_USB2_SENSOR: 3225 dev->shadow_regs[0x34] = 0x01; 3226 dev->shadow_regs[0x35] = 0x01; 3227 dev->shadow_regs[0x36] = 0x02; 3228 dev->shadow_regs[0x37] = 0x02; 3229 dev->shadow_regs[0x38] = 0x02; 3230 3231 dev->shadow_regs[0x79] = 0x20; 3232 3233 dev->shadow_regs[0x85] = 0x00; 3234 dev->shadow_regs[0x86] = 0x00; 3235 dev->shadow_regs[0x87] = 0xff; 3236 dev->shadow_regs[0x88] = 0x02; 3237 3238 dev->shadow_regs[0x92] = 0x00; 3239 break; 3240 } 3241 switch (dev->model.motor_type) 3242 { 3243 case X74_MOTOR: 3244 /* ? */ 3245 dev->shadow_regs[0xc4] = 0x20; 3246 dev->shadow_regs[0xc5] = 0x0a; 3247 dev->shadow_regs[0xc6] = 0x0b; 3248 3249 dev->shadow_regs[0xc8] = 0x04; 3250 dev->shadow_regs[0xc9] = 0x39; 3251 dev->shadow_regs[0xca] = 0x01; 3252 3253 /* bounds of movement range0 */ 3254 dev->shadow_regs[0xe0] = 0x07; 3255 dev->shadow_regs[0xe1] = 0x18; 3256 /* step size range0 */ 3257 dev->shadow_regs[0xe2] = 0xe7; 3258 /* ? */ 3259 dev->shadow_regs[0xe3] = 0x03; 3260 /* bounds of movement range1 */ 3261 dev->shadow_regs[0xe4] = 0xe7; 3262 dev->shadow_regs[0xe5] = 0x14; 3263 /* step size range1 */ 3264 dev->shadow_regs[0xe6] = 0x64; 3265 /* bounds of movement range2 */ 3266 dev->shadow_regs[0xe7] = 0xcb; 3267 dev->shadow_regs[0xe8] = 0x08; 3268 /* step size range2 */ 3269 dev->shadow_regs[0xe9] = 0x32; 3270 /* bounds of movement range3 */ 3271 dev->shadow_regs[0xea] = 0xe3; 3272 dev->shadow_regs[0xeb] = 0x04; 3273 /* step size range3 */ 3274 dev->shadow_regs[0xec] = 0x0c; 3275 /* bounds of movement range4 */ 3276 dev->shadow_regs[0xed] = 0x00; 3277 dev->shadow_regs[0xee] = 0x00; 3278 /* step size range4 */ 3279 dev->shadow_regs[0xef] = 0x08; 3280 break; 3281 case A920_MOTOR: 3282 case X1100_MOTOR: 3283 /* ? */ 3284 dev->shadow_regs[0xc5] = 0x10; 3285 /* Movement direction & step size */ 3286 dev->shadow_regs[0xc6] = 0x09; 3287 3288 dev->shadow_regs[0xc9] = 0x3b; 3289 dev->shadow_regs[0xca] = 0x01; 3290 /* bounds of movement range0 */ 3291 dev->shadow_regs[0xe0] = 0x4d; 3292 dev->shadow_regs[0xe1] = 0x1c; 3293 /* step size range0 */ 3294 dev->shadow_regs[0xe2] = 0x71; 3295 /* ? */ 3296 dev->shadow_regs[0xe3] = 0x02; 3297 /* bounds of movement range1 */ 3298 dev->shadow_regs[0xe4] = 0x6d; 3299 dev->shadow_regs[0xe5] = 0x15; 3300 /* step size range1 */ 3301 dev->shadow_regs[0xe6] = 0xdc; 3302 /* bounds of movement range2 */ 3303 dev->shadow_regs[0xe7] = 0xad; 3304 dev->shadow_regs[0xe8] = 0x07; 3305 /* step size range2 */ 3306 dev->shadow_regs[0xe9] = 0x1b; 3307 /* bounds of movement range3 */ 3308 dev->shadow_regs[0xea] = 0xe1; 3309 dev->shadow_regs[0xeb] = 0x03; 3310 /* step size range3 */ 3311 dev->shadow_regs[0xec] = 0x07; 3312 /* bounds of movement range4 -only for 75dpi grayscale */ 3313 dev->shadow_regs[0xed] = 0xc2; 3314 dev->shadow_regs[0xee] = 0x02; 3315 /* step size range4 */ 3316 dev->shadow_regs[0xef] = 0x03; 3317 break; 3318 } 3319 3320 /* set grayscale scan */ 3321 dev->shadow_regs[0x2f] = 0x21; 3322 3323 /* set ? only for colour? */ 3324 dev->shadow_regs[0x80] = 0x00; 3325 dev->shadow_regs[0x81] = 0x00; 3326 dev->shadow_regs[0x82] = 0x00; 3327 /* Motor enable & Coordinate space denominator */ 3328 dev->shadow_regs[0xc3] = 0x81; 3329 3330 } 3331 3332 /* set motor resolution divisor */ 3333 dev->shadow_regs[0x39] = 0x0f; 3334 3335 /* set # of head moves per CIS read */ 3336 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 3337 3338 /* set horizontal resolution */ 3339 if (dev->model.sensor_type != X1200_SENSOR) 3340 dev->shadow_regs[0x79] = 0x08; 3341 3342 } 3343 3344 /* 150dpi x 150dpi */ 3345 if (resolution == 150) 3346 { 3347 DBG (5, "sanei_lexmark_low_set_scan_regs(): 150 DPI resolution\n"); 3348 3349 if (isColourScan) 3350 { 3351 3352 switch (dev->model.sensor_type) 3353 { 3354 case X74_SENSOR: 3355 dev->shadow_regs[0x34] = 0x08; 3356 dev->shadow_regs[0x36] = 0x06; 3357 dev->shadow_regs[0x38] = 0x05; 3358 dev->shadow_regs[0x39] = 0x07; 3359 3360 /* resolution divisor */ 3361 dev->shadow_regs[0x79] = 0x08; 3362 3363 dev->shadow_regs[0x80] = 0x0a; 3364 dev->shadow_regs[0x81] = 0x0c; 3365 dev->shadow_regs[0x82] = 0x04; 3366 3367 dev->shadow_regs[0x85] = 0x00; 3368 dev->shadow_regs[0x86] = 0x00; 3369 dev->shadow_regs[0x87] = 0x00; 3370 dev->shadow_regs[0x88] = 0x00; 3371 3372 dev->shadow_regs[0x91] = 0x00; 3373 dev->shadow_regs[0x92] = 0x00; 3374 dev->shadow_regs[0x93] = 0x06; 3375 break; 3376 case X1100_B2_SENSOR: 3377 dev->shadow_regs[0x34] = 0x0b; 3378 dev->shadow_regs[0x36] = 0x0b; 3379 dev->shadow_regs[0x38] = 0x0a; 3380 3381 dev->shadow_regs[0x80] = 0x05; 3382 dev->shadow_regs[0x81] = 0x05; 3383 dev->shadow_regs[0x82] = 0x0a; 3384 3385 dev->shadow_regs[0x85] = 0x83; 3386 dev->shadow_regs[0x86] = 0x7e; 3387 dev->shadow_regs[0x87] = 0xad; 3388 dev->shadow_regs[0x88] = 0x35; 3389 3390 dev->shadow_regs[0x91] = 0xfe; 3391 dev->shadow_regs[0x92] = 0xdf; 3392 dev->shadow_regs[0x93] = 0x0e; 3393 break; 3394 case X1100_2C_SENSOR: 3395 dev->shadow_regs[0x34] = 0x05; 3396 dev->shadow_regs[0x36] = 0x07; 3397 dev->shadow_regs[0x38] = 0x05; 3398 3399 dev->shadow_regs[0x80] = 0x00; 3400 dev->shadow_regs[0x81] = 0x02; 3401 dev->shadow_regs[0x82] = 0x06; 3402 3403 dev->shadow_regs[0x85] = 0x20; 3404 dev->shadow_regs[0x86] = 0x00; 3405 dev->shadow_regs[0x87] = 0x00; 3406 dev->shadow_regs[0x88] = 0x00; 3407 3408 dev->shadow_regs[0x91] = 0x00; 3409 dev->shadow_regs[0x92] = 0x00; 3410 dev->shadow_regs[0x93] = 0x06; 3411 break; 3412 case A920_SENSOR: 3413 dev->shadow_regs[0x34] = 0x03; 3414 dev->shadow_regs[0x36] = 0x08; 3415 dev->shadow_regs[0x38] = 0x05; 3416 3417 dev->shadow_regs[0x80] = 0x0e; 3418 dev->shadow_regs[0x81] = 0x07; 3419 dev->shadow_regs[0x82] = 0x02; 3420 3421 dev->shadow_regs[0x85] = 0x05; 3422 dev->shadow_regs[0x86] = 0x14; 3423 dev->shadow_regs[0x87] = 0x06; 3424 dev->shadow_regs[0x88] = 0x04; 3425 3426 dev->shadow_regs[0x91] = 0xe0; 3427 dev->shadow_regs[0x92] = 0x85; 3428 dev->shadow_regs[0x93] = 0x0e; 3429 break; 3430 case X1200_SENSOR: 3431 dev->shadow_regs[0x34] = 0x04; 3432 dev->shadow_regs[0x36] = 0x05; 3433 dev->shadow_regs[0x38] = 0x02; 3434 /* data compression 3435 dev->shadow_regs[0x40] = 0x90; 3436 dev->shadow_regs[0x50] = 0x20; */ 3437 /* no data compression */ 3438 dev->shadow_regs[0x40] = 0x80; 3439 dev->shadow_regs[0x50] = 0x00; 3440 3441 dev->shadow_regs[0x79] = 0x20; 3442 3443 dev->shadow_regs[0x80] = 0x00; 3444 dev->shadow_regs[0x81] = 0x07; 3445 dev->shadow_regs[0x82] = 0x0b; 3446 3447 dev->shadow_regs[0x85] = 0x20; 3448 dev->shadow_regs[0x86] = 0x1e; 3449 dev->shadow_regs[0x87] = 0x39; 3450 dev->shadow_regs[0x88] = 0x00; 3451 3452 dev->shadow_regs[0x92] = 0x92; 3453 3454 break; 3455 case X1200_USB2_SENSOR: 3456 dev->shadow_regs[0x34] = 0x04; 3457 dev->shadow_regs[0x36] = 0x05; 3458 dev->shadow_regs[0x38] = 0x02; 3459 3460 dev->shadow_regs[0x40] = 0x80; 3461 dev->shadow_regs[0x50] = 0x00; 3462 3463 dev->shadow_regs[0x79] = 0x20; 3464 3465 dev->shadow_regs[0x80] = 0x00; 3466 dev->shadow_regs[0x81] = 0x07; 3467 dev->shadow_regs[0x82] = 0x0b; 3468 3469 dev->shadow_regs[0x85] = 0x20; 3470 dev->shadow_regs[0x86] = 0x1e; 3471 dev->shadow_regs[0x87] = 0x39; 3472 dev->shadow_regs[0x88] = 0x00; 3473 3474 dev->shadow_regs[0x92] = 0x92; 3475 break; 3476 } /* switch */ 3477 switch (dev->model.motor_type) 3478 { 3479 case X74_MOTOR: 3480 dev->shadow_regs[0xc2] = 0x80; 3481 /* ? */ 3482 dev->shadow_regs[0xc4] = 0x20; 3483 3484 dev->shadow_regs[0xc5] = 0x0e; 3485 /* Movement direction & step size */ 3486 dev->shadow_regs[0xc6] = 0x0b; 3487 dev->shadow_regs[0xc7] = 0x00; 3488 dev->shadow_regs[0xc8] = 0x04; 3489 dev->shadow_regs[0xc9] = 0x39; 3490 dev->shadow_regs[0xca] = 0x03; 3491 3492 /* bounds of movement range0 */ 3493 dev->shadow_regs[0xe0] = 0x41; 3494 dev->shadow_regs[0xe1] = 0x09; 3495 /* step size range0 */ 3496 dev->shadow_regs[0xe2] = 0x89; 3497 /* ? */ 3498 dev->shadow_regs[0xe3] = 0x02; 3499 /* bounds of movement range1 */ 3500 dev->shadow_regs[0xe4] = 0x0d; 3501 3502 dev->shadow_regs[0xe5] = 0x09; 3503 /* step size range1 */ 3504 dev->shadow_regs[0xe6] = 0x0d; 3505 /* bounds of movement range2 */ 3506 dev->shadow_regs[0xe7] = 0xe8; 3507 dev->shadow_regs[0xe8] = 0x02; 3508 /* step size range2 */ 3509 dev->shadow_regs[0xe9] = 0x05; 3510 /* bounds of movement range3 */ 3511 dev->shadow_regs[0xea] = 0x00; 3512 dev->shadow_regs[0xeb] = 0x00; 3513 /* step size range3 */ 3514 dev->shadow_regs[0xec] = 0x01; 3515 /* bounds of movement range4 */ 3516 dev->shadow_regs[0xed] = 0x00; 3517 dev->shadow_regs[0xee] = 0x00; 3518 /* step size range4 */ 3519 dev->shadow_regs[0xef] = 0x01; 3520 break; 3521 case X1100_MOTOR: 3522 case A920_MOTOR: 3523 /* ? */ 3524 dev->shadow_regs[0xc5] = 0x0e; 3525 /* ? */ 3526 dev->shadow_regs[0xc9] = 0x3a; 3527 dev->shadow_regs[0xca] = 0x03; 3528 /* bounds of movement range0 */ 3529 dev->shadow_regs[0xe0] = 0x61; 3530 dev->shadow_regs[0xe1] = 0x0a; 3531 /* step size range0 */ 3532 dev->shadow_regs[0xe2] = 0xed; 3533 /* ? */ 3534 dev->shadow_regs[0xe3] = 0x02; 3535 /* bounds of movement range1 */ 3536 dev->shadow_regs[0xe4] = 0x29; 3537 dev->shadow_regs[0xe5] = 0x0a; 3538 /* step size range1 */ 3539 dev->shadow_regs[0xe6] = 0x0e; 3540 /* bounds of movement range2 */ 3541 dev->shadow_regs[0xe7] = 0x29; 3542 dev->shadow_regs[0xe8] = 0x03; 3543 /* step size range2 */ 3544 dev->shadow_regs[0xe9] = 0x05; 3545 /* bounds of movement range3 */ 3546 dev->shadow_regs[0xea] = 0x00; 3547 dev->shadow_regs[0xeb] = 0x00; 3548 /* step size range3 */ 3549 dev->shadow_regs[0xec] = 0x01; 3550 /* step size range4 */ 3551 dev->shadow_regs[0xef] = 0x01; 3552 break; 3553 } 3554 /* set colour scan */ 3555 dev->shadow_regs[0x2f] = 0x11; 3556 3557 dev->shadow_regs[0x35] = 0x01; 3558 dev->shadow_regs[0x37] = 0x01; 3559 /* Motor enable & Coordinate space denominator */ 3560 dev->shadow_regs[0xc3] = 0x83; 3561 3562 } /* if (isColourScan) */ 3563 else 3564 { 3565 switch (dev->model.sensor_type) 3566 { 3567 case X74_SENSOR: 3568 3569 dev->shadow_regs[0x34] = 0x02; 3570 dev->shadow_regs[0x35] = 0x02; 3571 dev->shadow_regs[0x36] = 0x04; 3572 dev->shadow_regs[0x37] = 0x04; 3573 dev->shadow_regs[0x38] = 0x06; 3574 dev->shadow_regs[0x39] = 0x07; 3575 /* Motor enable & Coordinate space denominator */ 3576 dev->shadow_regs[0x40] = 0x40; 3577 3578 /* resolution divisor */ 3579 dev->shadow_regs[0x79] = 0x08; 3580 3581 dev->shadow_regs[0x85] = 0x00; 3582 dev->shadow_regs[0x86] = 0x00; 3583 dev->shadow_regs[0x87] = 0x00; 3584 dev->shadow_regs[0x88] = 0x00; 3585 3586 dev->shadow_regs[0x91] = 0x00; 3587 dev->shadow_regs[0x92] = 0x00; 3588 dev->shadow_regs[0x93] = 0x06; 3589 break; 3590 case X1100_B2_SENSOR: 3591 dev->shadow_regs[0x34] = 0x04; 3592 dev->shadow_regs[0x35] = 0x04; 3593 dev->shadow_regs[0x36] = 0x07; 3594 dev->shadow_regs[0x37] = 0x07; 3595 dev->shadow_regs[0x38] = 0x0a; 3596 3597 3598 dev->shadow_regs[0x85] = 0x00; 3599 dev->shadow_regs[0x86] = 0x00; 3600 dev->shadow_regs[0x87] = 0x00; 3601 dev->shadow_regs[0x88] = 0x00; 3602 3603 dev->shadow_regs[0x91] = 0x00; 3604 dev->shadow_regs[0x92] = 0x00; 3605 dev->shadow_regs[0x93] = 0x06; 3606 break; 3607 case X1100_2C_SENSOR: 3608 dev->shadow_regs[0x34] = 0x02; 3609 dev->shadow_regs[0x35] = 0x02; 3610 dev->shadow_regs[0x36] = 0x04; 3611 dev->shadow_regs[0x37] = 0x04; 3612 dev->shadow_regs[0x38] = 0x05; 3613 3614 dev->shadow_regs[0x85] = 0x20; 3615 dev->shadow_regs[0x86] = 0x00; 3616 dev->shadow_regs[0x87] = 0x00; 3617 dev->shadow_regs[0x88] = 0x00; 3618 3619 dev->shadow_regs[0x91] = 0x00; 3620 dev->shadow_regs[0x92] = 0x00; 3621 dev->shadow_regs[0x93] = 0x06; 3622 break; 3623 case A920_SENSOR: 3624 dev->shadow_regs[0x34] = 0x02; 3625 dev->shadow_regs[0x35] = 0x02; 3626 dev->shadow_regs[0x36] = 0x04; 3627 dev->shadow_regs[0x37] = 0x04; 3628 dev->shadow_regs[0x38] = 0x05; 3629 3630 dev->shadow_regs[0x85] = 0x0d; 3631 dev->shadow_regs[0x86] = 0x14; 3632 dev->shadow_regs[0x87] = 0x06; 3633 dev->shadow_regs[0x88] = 0x45; 3634 3635 dev->shadow_regs[0x91] = 0x60; 3636 dev->shadow_regs[0x92] = 0x8d; 3637 dev->shadow_regs[0x93] = 0x0e; 3638 break; 3639 case X1200_SENSOR: 3640 dev->shadow_regs[0x34] = 0x01; 3641 dev->shadow_regs[0x35] = 0x01; 3642 dev->shadow_regs[0x36] = 0x02; 3643 dev->shadow_regs[0x37] = 0x02; 3644 dev->shadow_regs[0x38] = 0x03; 3645 3646 /* dev->shadow_regs[0x40] = 0x90; 3647 dev->shadow_regs[0x50] = 0x20; */ 3648 /* no data compression */ 3649 dev->shadow_regs[0x40] = 0x80; 3650 dev->shadow_regs[0x50] = 0x00; 3651 3652 dev->shadow_regs[0x79] = 0x20; 3653 3654 dev->shadow_regs[0x85] = 0x00; 3655 dev->shadow_regs[0x86] = 0x00; 3656 dev->shadow_regs[0x87] = 0xff; 3657 dev->shadow_regs[0x88] = 0x02; 3658 3659 dev->shadow_regs[0x92] = 0x92; 3660 break; 3661 case X1200_USB2_SENSOR: 3662 dev->shadow_regs[0x34] = 0x01; 3663 dev->shadow_regs[0x35] = 0x01; 3664 dev->shadow_regs[0x36] = 0x02; 3665 dev->shadow_regs[0x37] = 0x02; 3666 dev->shadow_regs[0x38] = 0x03; 3667 3668 dev->shadow_regs[0x40] = 0x80; 3669 dev->shadow_regs[0x50] = 0x00; 3670 3671 dev->shadow_regs[0x79] = 0x20; 3672 3673 dev->shadow_regs[0x85] = 0x00; 3674 dev->shadow_regs[0x86] = 0x00; 3675 dev->shadow_regs[0x87] = 0xff; 3676 dev->shadow_regs[0x88] = 0x02; 3677 3678 dev->shadow_regs[0x92] = 0x92; 3679 break; 3680 } /* switch */ 3681 switch (dev->model.motor_type) 3682 { 3683 case X74_MOTOR: 3684 /* ? */ 3685 dev->shadow_regs[0xc4] = 0x20; 3686 dev->shadow_regs[0xc5] = 0x14; 3687 /* Movement direction & step size */ 3688 dev->shadow_regs[0xc6] = 0x0b; 3689 3690 dev->shadow_regs[0xc8] = 0x04; 3691 dev->shadow_regs[0xc9] = 0x39; 3692 dev->shadow_regs[0xca] = 0x01; 3693 3694 /* bounds of movement range0 */ 3695 dev->shadow_regs[0xe0] = 0x09; 3696 dev->shadow_regs[0xe1] = 0x18; 3697 /* step size range0 */ 3698 dev->shadow_regs[0xe2] = 0xe9; 3699 /* ? */ 3700 dev->shadow_regs[0xe3] = 0x03; 3701 /* bounds of movement range1 */ 3702 dev->shadow_regs[0xe4] = 0x79; 3703 3704 dev->shadow_regs[0xe5] = 0x16; 3705 /* step size range1 */ 3706 dev->shadow_regs[0xe6] = 0x64; 3707 /* bounds of movement range2 */ 3708 dev->shadow_regs[0xe7] = 0xcd; 3709 dev->shadow_regs[0xe8] = 0x08; 3710 /* step size range2 */ 3711 dev->shadow_regs[0xe9] = 0x32; 3712 /* bounds of movement range3 */ 3713 dev->shadow_regs[0xea] = 0xe5; 3714 dev->shadow_regs[0xeb] = 0x04; 3715 /* step size range3 */ 3716 dev->shadow_regs[0xec] = 0x0c; 3717 /* bounds of movement range4 */ 3718 dev->shadow_regs[0xed] = 0x00; 3719 dev->shadow_regs[0xee] = 0x00; 3720 /* step size range4 */ 3721 dev->shadow_regs[0xef] = 0x08; 3722 break; 3723 case X1100_MOTOR: 3724 case A920_MOTOR: 3725 /* ? */ 3726 dev->shadow_regs[0xc5] = 0x16; 3727 /* Movement direction & step size */ 3728 dev->shadow_regs[0xc6] = 0x09; 3729 /* ? */ 3730 dev->shadow_regs[0xc9] = 0x3b; 3731 dev->shadow_regs[0xca] = 0x01; 3732 /* bounds of movement range0 */ 3733 dev->shadow_regs[0xe0] = 0xdd; 3734 dev->shadow_regs[0xe1] = 0x18; 3735 /* step size range0 */ 3736 dev->shadow_regs[0xe2] = 0x01; 3737 /* ? */ 3738 dev->shadow_regs[0xe3] = 0x03; 3739 /* bounds of movement range1 */ 3740 dev->shadow_regs[0xe4] = 0x6d; 3741 dev->shadow_regs[0xe5] = 0x15; 3742 /* step size range1 */ 3743 dev->shadow_regs[0xe6] = 0xdc; 3744 /* bounds of movement range2 */ 3745 dev->shadow_regs[0xe7] = 0xad; 3746 dev->shadow_regs[0xe8] = 0x07; 3747 /* step size range2 */ 3748 dev->shadow_regs[0xe9] = 0x1b; 3749 /* bounds of movement range3 */ 3750 dev->shadow_regs[0xea] = 0xe1; 3751 dev->shadow_regs[0xeb] = 0x03; 3752 /* step size range3 */ 3753 dev->shadow_regs[0xec] = 0x07; 3754 /* step size range4 */ 3755 dev->shadow_regs[0xef] = 0x03; 3756 break; 3757 } 3758 3759 /* set grayscale scan */ 3760 dev->shadow_regs[0x2f] = 0x21; 3761 /* set motor resolution divisor */ 3762 dev->shadow_regs[0x39] = 0x07; 3763 /* set ? only for colour? */ 3764 dev->shadow_regs[0x80] = 0x00; 3765 dev->shadow_regs[0x81] = 0x00; 3766 dev->shadow_regs[0x82] = 0x00; 3767 3768 /* Motor enable & Coordinate space denominator */ 3769 dev->shadow_regs[0xc3] = 0x81; 3770 } /* else (greyscale) */ 3771 3772 3773 3774 3775 /* set # of head moves per CIS read */ 3776 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 3777 3778 /* hum, horizontal resolution different for X1200 ? */ 3779 /* if (dev->model.sensor_type != X1200_SENSOR) 3780 dev->shadow_regs[0x79] = 0x20; */ 3781 3782 } 3783 3784 /*300dpi x 300dpi */ 3785 if (resolution == 300) 3786 { 3787 DBG (5, "sanei_lexmark_low_set_scan_regs(): 300 DPI resolution\n"); 3788 3789 if (isColourScan) 3790 { 3791 3792 switch (dev->model.sensor_type) 3793 { 3794 case X74_SENSOR: 3795 dev->shadow_regs[0x34] = 0x08; 3796 dev->shadow_regs[0x36] = 0x06; 3797 dev->shadow_regs[0x38] = 0x05; 3798 dev->shadow_regs[0x39] = 0x07; 3799 3800 dev->shadow_regs[0x80] = 0x08; 3801 dev->shadow_regs[0x81] = 0x0a; 3802 dev->shadow_regs[0x82] = 0x03; 3803 3804 dev->shadow_regs[0x85] = 0x00; 3805 dev->shadow_regs[0x86] = 0x00; 3806 dev->shadow_regs[0x87] = 0x00; 3807 dev->shadow_regs[0x88] = 0x00; 3808 3809 dev->shadow_regs[0x91] = 0x00; 3810 dev->shadow_regs[0x92] = 0x00; 3811 dev->shadow_regs[0x93] = 0x06; 3812 break; 3813 case X1100_B2_SENSOR: 3814 dev->shadow_regs[0x34] = 0x15; 3815 dev->shadow_regs[0x36] = 0x15; 3816 dev->shadow_regs[0x38] = 0x14; 3817 /* set motor resolution divisor */ 3818 dev->shadow_regs[0x39] = 0x03; 3819 3820 dev->shadow_regs[0x80] = 0x0a; 3821 dev->shadow_regs[0x81] = 0x0a; 3822 dev->shadow_regs[0x82] = 0x06; 3823 3824 dev->shadow_regs[0x85] = 0x83; 3825 dev->shadow_regs[0x86] = 0x7e; 3826 dev->shadow_regs[0x87] = 0xad; 3827 dev->shadow_regs[0x88] = 0x35; 3828 3829 dev->shadow_regs[0x91] = 0xfe; 3830 dev->shadow_regs[0x92] = 0xdf; 3831 dev->shadow_regs[0x93] = 0x0e; 3832 break; 3833 case X1100_2C_SENSOR: 3834 dev->shadow_regs[0x34] = 0x08; 3835 dev->shadow_regs[0x36] = 0x0d; 3836 dev->shadow_regs[0x38] = 0x09; 3837 /* set motor resolution divisor */ 3838 dev->shadow_regs[0x39] = 0x03; 3839 3840 dev->shadow_regs[0x80] = 0x0e; 3841 dev->shadow_regs[0x81] = 0x04; 3842 dev->shadow_regs[0x82] = 0x0a; 3843 3844 dev->shadow_regs[0x85] = 0x20; 3845 dev->shadow_regs[0x86] = 0x00; 3846 dev->shadow_regs[0x87] = 0x00; 3847 dev->shadow_regs[0x88] = 0x00; 3848 3849 dev->shadow_regs[0x91] = 0x00; 3850 dev->shadow_regs[0x92] = 0x00; 3851 dev->shadow_regs[0x93] = 0x06; 3852 break; 3853 case A920_SENSOR: 3854 dev->shadow_regs[0x34] = 0x06; 3855 dev->shadow_regs[0x36] = 0x10; 3856 dev->shadow_regs[0x38] = 0x09; 3857 /* set motor resolution divisor */ 3858 dev->shadow_regs[0x39] = 0x03; 3859 3860 dev->shadow_regs[0x80] = 0x0c; 3861 dev->shadow_regs[0x81] = 0x02; 3862 dev->shadow_regs[0x82] = 0x04; 3863 3864 dev->shadow_regs[0x85] = 0x05; 3865 dev->shadow_regs[0x86] = 0x14; 3866 dev->shadow_regs[0x87] = 0x06; 3867 dev->shadow_regs[0x88] = 0x04; 3868 3869 dev->shadow_regs[0x91] = 0xe0; 3870 dev->shadow_regs[0x92] = 0x85; 3871 dev->shadow_regs[0x93] = 0x0e; 3872 break; 3873 case X1200_SENSOR: 3874 dev->shadow_regs[0x34] = 0x07; 3875 dev->shadow_regs[0x36] = 0x09; 3876 dev->shadow_regs[0x38] = 0x04; 3877 /* set motor resolution divisor */ 3878 dev->shadow_regs[0x39] = 0x03; 3879 3880 /* data compression 3881 dev->shadow_regs[0x40] = 0x90; 3882 dev->shadow_regs[0x50] = 0x20; */ 3883 /* no data compression */ 3884 dev->shadow_regs[0x40] = 0x80; 3885 dev->shadow_regs[0x50] = 0x00; 3886 3887 dev->shadow_regs[0x80] = 0x00; 3888 dev->shadow_regs[0x81] = 0x0e; 3889 dev->shadow_regs[0x82] = 0x06; 3890 break; 3891 case X1200_USB2_SENSOR: 3892 dev->shadow_regs[0x34] = 0x07; 3893 dev->shadow_regs[0x36] = 0x09; 3894 dev->shadow_regs[0x38] = 0x04; 3895 /* set motor resolution divisor */ 3896 dev->shadow_regs[0x39] = 0x03; 3897 3898 dev->shadow_regs[0x40] = 0x80; 3899 dev->shadow_regs[0x50] = 0x00; 3900 3901 dev->shadow_regs[0x80] = 0x00; 3902 dev->shadow_regs[0x81] = 0x0e; 3903 dev->shadow_regs[0x82] = 0x06; 3904 break; 3905 } 3906 switch (dev->model.motor_type) 3907 { 3908 case X74_MOTOR: 3909 /* ? */ 3910 dev->shadow_regs[0xc4] = 0x20; 3911 dev->shadow_regs[0xc5] = 0x12; 3912 /* Movement direction & step size */ 3913 dev->shadow_regs[0xc6] = 0x09; 3914 3915 dev->shadow_regs[0xc8] = 0x04; 3916 dev->shadow_regs[0xc9] = 0x39; 3917 dev->shadow_regs[0xca] = 0x0f; 3918 3919 /* bounds of movement range0 */ 3920 dev->shadow_regs[0xe0] = 0x5d; 3921 dev->shadow_regs[0xe1] = 0x05; 3922 /* step size range0 */ 3923 dev->shadow_regs[0xe2] = 0xed; 3924 /* ? */ 3925 dev->shadow_regs[0xe3] = 0x02; 3926 /* bounds of movement range1 */ 3927 dev->shadow_regs[0xe4] = 0x29; 3928 dev->shadow_regs[0xe5] = 0x05; 3929 /* step size range1 */ 3930 dev->shadow_regs[0xe6] = 0x0d; 3931 /* bounds of movement range2 */ 3932 dev->shadow_regs[0xe7] = 0x00; 3933 dev->shadow_regs[0xe8] = 0x00; 3934 /* step size range2 */ 3935 dev->shadow_regs[0xe9] = 0x05; 3936 /* bounds of movement range3 */ 3937 dev->shadow_regs[0xea] = 0x00; 3938 dev->shadow_regs[0xeb] = 0x00; 3939 /* step size range3 */ 3940 dev->shadow_regs[0xec] = 0x01; 3941 /* bounds of movement range4 -only for 75dpi grayscale */ 3942 dev->shadow_regs[0xed] = 0x00; 3943 dev->shadow_regs[0xee] = 0x00; 3944 /* step size range4 */ 3945 dev->shadow_regs[0xef] = 0x01; 3946 break; 3947 case A920_MOTOR: 3948 case X1100_MOTOR: 3949 /* ? */ 3950 dev->shadow_regs[0xc5] = 0x17; 3951 /* Movement direction & step size */ 3952 dev->shadow_regs[0xc6] = 0x09; 3953 /* ? */ 3954 dev->shadow_regs[0xc9] = 0x3a; 3955 dev->shadow_regs[0xca] = 0x0a; 3956 /* bounds of movement range0 */ 3957 dev->shadow_regs[0xe0] = 0x75; 3958 dev->shadow_regs[0xe1] = 0x0a; 3959 /* step size range0 */ 3960 dev->shadow_regs[0xe2] = 0xdd; 3961 /* ? */ 3962 dev->shadow_regs[0xe3] = 0x05; 3963 /* bounds of movement range1 */ 3964 dev->shadow_regs[0xe4] = 0x59; 3965 dev->shadow_regs[0xe5] = 0x0a; 3966 /* step size range1 */ 3967 dev->shadow_regs[0xe6] = 0x0e; 3968 /* bounds of movement range2 */ 3969 dev->shadow_regs[0xe7] = 0x00; 3970 dev->shadow_regs[0xe8] = 0x00; 3971 /* step size range2 */ 3972 dev->shadow_regs[0xe9] = 0x05; 3973 /* bounds of movement range3 */ 3974 dev->shadow_regs[0xea] = 0x00; 3975 dev->shadow_regs[0xeb] = 0x00; 3976 /* step size range3 */ 3977 dev->shadow_regs[0xec] = 0x01; 3978 /* step size range4 */ 3979 dev->shadow_regs[0xef] = 0x01; 3980 break; 3981 } 3982 3983 dev->shadow_regs[0x35] = 0x01; 3984 dev->shadow_regs[0x37] = 0x01; 3985 3986 /* set colour scan */ 3987 dev->shadow_regs[0x2f] = 0x11; 3988 3989 /* Motor enable & Coordinate space denominator */ 3990 dev->shadow_regs[0xc3] = 0x83; 3991 3992 } 3993 else /* greyscale */ 3994 { 3995 3996 switch (dev->model.sensor_type) 3997 { 3998 case X74_SENSOR: 3999 dev->shadow_regs[0x34] = 0x04; 4000 dev->shadow_regs[0x35] = 0x04; 4001 dev->shadow_regs[0x36] = 0x08; 4002 dev->shadow_regs[0x37] = 0x08; 4003 dev->shadow_regs[0x38] = 0x0c; 4004 4005 dev->shadow_regs[0x85] = 0x00; 4006 dev->shadow_regs[0x86] = 0x00; 4007 dev->shadow_regs[0x87] = 0x00; 4008 dev->shadow_regs[0x88] = 0x00; 4009 4010 dev->shadow_regs[0x91] = 0x00; 4011 dev->shadow_regs[0x92] = 0x00; 4012 dev->shadow_regs[0x93] = 0x06; 4013 break; 4014 case X1100_B2_SENSOR: 4015 dev->shadow_regs[0x34] = 0x08; 4016 dev->shadow_regs[0x35] = 0x08; 4017 dev->shadow_regs[0x36] = 0x0f; 4018 dev->shadow_regs[0x37] = 0x0f; 4019 dev->shadow_regs[0x38] = 0x16; 4020 4021 dev->shadow_regs[0x85] = 0x00; 4022 dev->shadow_regs[0x86] = 0x00; 4023 dev->shadow_regs[0x87] = 0x00; 4024 dev->shadow_regs[0x88] = 0x00; 4025 4026 dev->shadow_regs[0x91] = 0x00; 4027 dev->shadow_regs[0x92] = 0x00; 4028 dev->shadow_regs[0x93] = 0x06; 4029 break; 4030 case X1100_2C_SENSOR: 4031 dev->shadow_regs[0x34] = 0x04; 4032 dev->shadow_regs[0x35] = 0x04; 4033 dev->shadow_regs[0x36] = 0x07; 4034 dev->shadow_regs[0x37] = 0x07; 4035 dev->shadow_regs[0x38] = 0x0a; 4036 4037 dev->shadow_regs[0x85] = 0x20; 4038 dev->shadow_regs[0x86] = 0x00; 4039 dev->shadow_regs[0x87] = 0x00; 4040 dev->shadow_regs[0x88] = 0x00; 4041 4042 dev->shadow_regs[0x91] = 0x00; 4043 dev->shadow_regs[0x92] = 0x00; 4044 dev->shadow_regs[0x93] = 0x06; 4045 break; 4046 case A920_SENSOR: 4047 dev->shadow_regs[0x34] = 0x03; 4048 dev->shadow_regs[0x35] = 0x03; 4049 dev->shadow_regs[0x36] = 0x06; 4050 dev->shadow_regs[0x37] = 0x06; 4051 dev->shadow_regs[0x38] = 0x09; 4052 4053 dev->shadow_regs[0x85] = 0x05; 4054 dev->shadow_regs[0x86] = 0x14; 4055 dev->shadow_regs[0x87] = 0x06; 4056 dev->shadow_regs[0x88] = 0x04; 4057 4058 dev->shadow_regs[0x91] = 0xe0; 4059 dev->shadow_regs[0x92] = 0x85; 4060 dev->shadow_regs[0x93] = 0x0e; 4061 break; 4062 case X1200_SENSOR: 4063 dev->shadow_regs[0x34] = 0x02; 4064 dev->shadow_regs[0x35] = 0x02; 4065 dev->shadow_regs[0x36] = 0x04; 4066 dev->shadow_regs[0x37] = 0x04; 4067 dev->shadow_regs[0x38] = 0x06; 4068 break; 4069 case X1200_USB2_SENSOR: 4070 dev->shadow_regs[0x34] = 0x02; 4071 dev->shadow_regs[0x35] = 0x02; 4072 dev->shadow_regs[0x36] = 0x04; 4073 dev->shadow_regs[0x37] = 0x04; 4074 dev->shadow_regs[0x38] = 0x06; 4075 break; 4076 } 4077 switch (dev->model.motor_type) 4078 { 4079 case X74_MOTOR: 4080 /* ? */ 4081 dev->shadow_regs[0xc4] = 0x20; 4082 dev->shadow_regs[0xc5] = 0x1c; 4083 /* Movement direction & step size */ 4084 dev->shadow_regs[0xc6] = 0x0b; 4085 4086 dev->shadow_regs[0xc8] = 0x04; 4087 dev->shadow_regs[0xc9] = 0x39; 4088 dev->shadow_regs[0xca] = 0x05; 4089 4090 /* bounds of movement range0 */ 4091 dev->shadow_regs[0xe0] = 0x29; 4092 dev->shadow_regs[0xe1] = 0x17; 4093 /* step size range0 */ 4094 dev->shadow_regs[0xe2] = 0x8f; 4095 /* ? */ 4096 dev->shadow_regs[0xe3] = 0x06; 4097 /* bounds of movement range1 */ 4098 dev->shadow_regs[0xe4] = 0x61; 4099 4100 dev->shadow_regs[0xe5] = 0x16; 4101 /* step size range1 */ 4102 dev->shadow_regs[0xe6] = 0x64; 4103 /* bounds of movement range2 */ 4104 dev->shadow_regs[0xe7] = 0xb5; 4105 dev->shadow_regs[0xe8] = 0x08; 4106 /* step size range2 */ 4107 dev->shadow_regs[0xe9] = 0x32; 4108 /* bounds of movement range3 */ 4109 dev->shadow_regs[0xea] = 0x00; 4110 dev->shadow_regs[0xeb] = 0x00; 4111 /* step size range3 */ 4112 dev->shadow_regs[0xec] = 0x0c; 4113 /* bounds of movement range4 -only for 75dpi grayscale */ 4114 dev->shadow_regs[0xed] = 0x00; 4115 dev->shadow_regs[0xee] = 0x00; 4116 /* step size range4 */ 4117 dev->shadow_regs[0xef] = 0x08; 4118 break; 4119 case A920_MOTOR: 4120 case X1100_MOTOR: 4121 /* ? */ 4122 dev->shadow_regs[0xc5] = 0x19; 4123 /* Movement direction & step size */ 4124 dev->shadow_regs[0xc6] = 0x09; 4125 /* ? */ 4126 dev->shadow_regs[0xc9] = 0x3a; 4127 dev->shadow_regs[0xca] = 0x08; 4128 /* bounds of movement range0 */ 4129 dev->shadow_regs[0xe0] = 0xe3; 4130 dev->shadow_regs[0xe1] = 0x18; 4131 /* step size range0 */ 4132 dev->shadow_regs[0xe2] = 0x03; 4133 /* ? */ 4134 dev->shadow_regs[0xe3] = 0x06; 4135 /* bounds of movement range1 */ 4136 dev->shadow_regs[0xe4] = 0x2b; 4137 dev->shadow_regs[0xe5] = 0x17; 4138 /* step size range1 */ 4139 dev->shadow_regs[0xe6] = 0xdc; 4140 /* bounds of movement range2 */ 4141 dev->shadow_regs[0xe7] = 0xb3; 4142 dev->shadow_regs[0xe8] = 0x07; 4143 /* step size range2 */ 4144 dev->shadow_regs[0xe9] = 0x1b; 4145 /* bounds of movement range3 */ 4146 dev->shadow_regs[0xea] = 0x00; 4147 dev->shadow_regs[0xeb] = 0x00; 4148 /* step size range3 */ 4149 dev->shadow_regs[0xec] = 0x07; 4150 /* step size range4 */ 4151 dev->shadow_regs[0xef] = 0x03; 4152 break; 4153 } /* switch motortype */ 4154 /* set grayscale scan */ 4155 dev->shadow_regs[0x2f] = 0x21; 4156 /* set motor resolution divisor */ 4157 dev->shadow_regs[0x39] = 0x03; 4158 4159 /* set ? only for colour? */ 4160 dev->shadow_regs[0x80] = 0x00; 4161 dev->shadow_regs[0x81] = 0x00; 4162 dev->shadow_regs[0x82] = 0x00; 4163 /* Motor enable & Coordinate space denominator */ 4164 dev->shadow_regs[0xc3] = 0x81; 4165 4166 4167 } /* else (gray) */ 4168 4169 /* set # of head moves per CIS read */ 4170 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 4171 /* set horizontal resolution */ 4172 dev->shadow_regs[0x79] = 0x20; 4173 } 4174 4175 /* 600dpi x 600dpi */ 4176 if (resolution == 600) 4177 { 4178 DBG (5, "sanei_lexmark_low_set_scan_regs(): 600 DPI resolution\n"); 4179 4180 4181 4182 if (isColourScan) 4183 { 4184 /* 600 dpi color doesn't work for X74 yet */ 4185 if (dev->model.sensor_type == X74_SENSOR) 4186 return SANE_STATUS_INVAL; 4187 4188 switch (dev->model.sensor_type) 4189 { 4190 case X74_SENSOR: 4191 dev->shadow_regs[0x34] = 0x10; 4192 dev->shadow_regs[0x35] = 0x01; 4193 dev->shadow_regs[0x36] = 0x0c; 4194 dev->shadow_regs[0x37] = 0x01; 4195 dev->shadow_regs[0x38] = 0x09; 4196 4197 dev->shadow_regs[0x80] = 0x02; 4198 dev->shadow_regs[0x81] = 0x08; 4199 dev->shadow_regs[0x82] = 0x08; 4200 4201 4202 dev->shadow_regs[0x85] = 0x00; 4203 dev->shadow_regs[0x86] = 0x00; 4204 dev->shadow_regs[0x87] = 0x00; 4205 dev->shadow_regs[0x88] = 0x00; 4206 4207 dev->shadow_regs[0x91] = 0x00; 4208 dev->shadow_regs[0x92] = 0x00; 4209 dev->shadow_regs[0x93] = 0x06; 4210 break; 4211 4212 /*dev->shadow_regs[0x34] = 0x08; 4213 dev->shadow_regs[0x35] = 0x01; 4214 dev->shadow_regs[0x36] = 0x06; 4215 dev->shadow_regs[0x37] = 0x01; 4216 dev->shadow_regs[0x38] = 0x05; 4217 4218 4219 dev->shadow_regs[0x80] = 0x09; 4220 dev->shadow_regs[0x81] = 0x0c; 4221 dev->shadow_regs[0x82] = 0x04; 4222 4223 4224 dev->shadow_regs[0x85] = 0x00; 4225 dev->shadow_regs[0x86] = 0x00; 4226 dev->shadow_regs[0x87] = 0x00; 4227 dev->shadow_regs[0x88] = 0x00; 4228 4229 dev->shadow_regs[0x91] = 0x00; 4230 dev->shadow_regs[0x92] = 0x00; 4231 dev->shadow_regs[0x93] = 0x06; 4232 break; */ 4233 4234 4235 4236 case X1100_B2_SENSOR: 4237 dev->shadow_regs[0x34] = 0x15; 4238 dev->shadow_regs[0x36] = 0x15; 4239 dev->shadow_regs[0x38] = 0x14; 4240 4241 dev->shadow_regs[0x80] = 0x02; 4242 dev->shadow_regs[0x81] = 0x02; 4243 dev->shadow_regs[0x82] = 0x08; 4244 4245 dev->shadow_regs[0x85] = 0x83; 4246 dev->shadow_regs[0x86] = 0x7e; 4247 dev->shadow_regs[0x87] = 0xad; 4248 dev->shadow_regs[0x88] = 0x35; 4249 4250 dev->shadow_regs[0x91] = 0xfe; 4251 dev->shadow_regs[0x92] = 0xdf; 4252 dev->shadow_regs[0x93] = 0x0e; 4253 break; 4254 case X1100_2C_SENSOR: 4255 dev->shadow_regs[0x34] = 0x08; 4256 dev->shadow_regs[0x36] = 0x0d; 4257 dev->shadow_regs[0x38] = 0x09; 4258 4259 dev->shadow_regs[0x80] = 0x0e; 4260 dev->shadow_regs[0x81] = 0x02; 4261 dev->shadow_regs[0x82] = 0x0a; 4262 4263 dev->shadow_regs[0x85] = 0x20; 4264 dev->shadow_regs[0x86] = 0x00; 4265 dev->shadow_regs[0x87] = 0x00; 4266 dev->shadow_regs[0x88] = 0x00; 4267 4268 dev->shadow_regs[0x91] = 0x00; 4269 dev->shadow_regs[0x92] = 0x00; 4270 dev->shadow_regs[0x93] = 0x06; 4271 break; 4272 case A920_SENSOR: 4273 dev->shadow_regs[0x34] = 0x06; 4274 dev->shadow_regs[0x36] = 0x0f; 4275 dev->shadow_regs[0x38] = 0x09; 4276 4277 dev->shadow_regs[0x79] = 0x40; 4278 4279 dev->shadow_regs[0x80] = 0x0e; 4280 dev->shadow_regs[0x81] = 0x0e; 4281 dev->shadow_regs[0x82] = 0x00; 4282 4283 dev->shadow_regs[0x85] = 0x05; 4284 dev->shadow_regs[0x86] = 0x14; 4285 dev->shadow_regs[0x87] = 0x06; 4286 dev->shadow_regs[0x88] = 0x04; 4287 4288 dev->shadow_regs[0x91] = 0x60; 4289 dev->shadow_regs[0x92] = 0x85; 4290 dev->shadow_regs[0x93] = 0x0e; 4291 break; 4292 case X1200_SENSOR: 4293 dev->shadow_regs[0x34] = 0x07; 4294 dev->shadow_regs[0x36] = 0x0a; 4295 dev->shadow_regs[0x38] = 0x04; 4296 4297 /* data compression 4298 dev->shadow_regs[0x40] = 0x90; 4299 dev->shadow_regs[0x50] = 0x20; */ 4300 4301 /* no data compression */ 4302 dev->shadow_regs[0x40] = 0x80; 4303 dev->shadow_regs[0x50] = 0x00; 4304 4305 dev->shadow_regs[0x80] = 0x02; 4306 dev->shadow_regs[0x81] = 0x00; 4307 dev->shadow_regs[0x82] = 0x06; 4308 break; 4309 case X1200_USB2_SENSOR: 4310 dev->shadow_regs[0x34] = 0x0d; 4311 dev->shadow_regs[0x36] = 0x13; 4312 dev->shadow_regs[0x38] = 0x10; 4313 4314 dev->shadow_regs[0x80] = 0x04; 4315 dev->shadow_regs[0x81] = 0x0e; 4316 dev->shadow_regs[0x82] = 0x08; 4317 4318 dev->shadow_regs[0x85] = 0x02; 4319 dev->shadow_regs[0x86] = 0x3b; 4320 dev->shadow_regs[0x87] = 0x0f; 4321 dev->shadow_regs[0x88] = 0x24; 4322 4323 dev->shadow_regs[0x91] = 0x19; 4324 dev->shadow_regs[0x92] = 0x30; 4325 dev->shadow_regs[0x93] = 0x0e; 4326 dev->shadow_regs[0xc5] = 0x17; 4327 dev->shadow_regs[0xc6] = 0x09; 4328 dev->shadow_regs[0xca] = 0x0a; 4329 break; 4330 } 4331 switch (dev->model.motor_type) 4332 { 4333 case X74_MOTOR: 4334 /* Motor enable & Coordinate space denominator */ 4335 dev->shadow_regs[0xc3] = 0x81; 4336 /* ? */ 4337 dev->shadow_regs[0xc4] = 0x20; 4338 dev->shadow_regs[0xc5] = 0x21; 4339 /* Movement direction & step size */ 4340 dev->shadow_regs[0xc6] = 0x09; 4341 dev->shadow_regs[0xc8] = 0x04; 4342 dev->shadow_regs[0xc9] = 0x39; 4343 dev->shadow_regs[0xca] = 0x20; 4344 /* bounds of movement range0 */ 4345 dev->shadow_regs[0xe0] = 0x00; 4346 dev->shadow_regs[0xe1] = 0x00; 4347 /* step size range0 */ 4348 dev->shadow_regs[0xe2] = 0xbf; 4349 /* ? */ 4350 dev->shadow_regs[0xe3] = 0x05; 4351 /* bounds of movement range1 */ 4352 dev->shadow_regs[0xe4] = 0x00; 4353 dev->shadow_regs[0xe5] = 0x00; 4354 /* step size range1 */ 4355 dev->shadow_regs[0xe6] = 0x0d; 4356 /* bounds of movement range2 */ 4357 dev->shadow_regs[0xe7] = 0x00; 4358 dev->shadow_regs[0xe8] = 0x00; 4359 /* step size range2 */ 4360 dev->shadow_regs[0xe9] = 0x05; 4361 /* bounds of movement range3 */ 4362 dev->shadow_regs[0xea] = 0x00; 4363 dev->shadow_regs[0xeb] = 0x00; 4364 /* step size range3 */ 4365 dev->shadow_regs[0xec] = 0x01; 4366 /* bounds of movement range4 -only for 75dpi grayscale */ 4367 dev->shadow_regs[0xed] = 0x00; 4368 dev->shadow_regs[0xee] = 0x00; 4369 /* step size range4 */ 4370 dev->shadow_regs[0xef] = 0x01; 4371 break; 4372 case A920_MOTOR: 4373 case X1100_MOTOR: 4374 /* Motor enable & Coordinate space denominator */ 4375 dev->shadow_regs[0xc3] = 0x86; 4376 /* ? */ 4377 dev->shadow_regs[0xc5] = 0x27; 4378 /* Movement direction & step size */ 4379 dev->shadow_regs[0xc6] = 0x0c; 4380 /* ? */ 4381 dev->shadow_regs[0xc9] = 0x3a; 4382 dev->shadow_regs[0xca] = 0x1a; 4383 /* bounds of movement range0 */ 4384 dev->shadow_regs[0xe0] = 0x57; 4385 dev->shadow_regs[0xe1] = 0x0a; 4386 /* step size range0 */ 4387 dev->shadow_regs[0xe2] = 0xbf; 4388 /* ? */ 4389 dev->shadow_regs[0xe3] = 0x05; 4390 /* bounds of movement range1 */ 4391 dev->shadow_regs[0xe4] = 0x3b; 4392 dev->shadow_regs[0xe5] = 0x0a; 4393 /* step size range1 */ 4394 dev->shadow_regs[0xe6] = 0x0e; 4395 /* bounds of movement range2 */ 4396 dev->shadow_regs[0xe7] = 0x00; 4397 dev->shadow_regs[0xe8] = 0x00; 4398 /* step size range2 */ 4399 dev->shadow_regs[0xe9] = 0x05; 4400 /* bounds of movement range3 */ 4401 dev->shadow_regs[0xea] = 0x00; 4402 dev->shadow_regs[0xeb] = 0x00; 4403 /* step size range3 */ 4404 dev->shadow_regs[0xec] = 0x01; 4405 /* step size range4 */ 4406 dev->shadow_regs[0xef] = 0x01; 4407 break; 4408 } 4409 /* set colour scan */ 4410 dev->shadow_regs[0x2f] = 0x11; 4411 4412 dev->shadow_regs[0x35] = 0x01; 4413 dev->shadow_regs[0x37] = 0x01; 4414 4415 /* set motor resolution divisor */ 4416 dev->shadow_regs[0x39] = 0x03; 4417 /* set # of head moves per CIS read */ 4418 rts88xx_set_scan_frequency (dev->shadow_regs, 2); 4419 4420 4421 } 4422 else 4423 { 4424 switch (dev->model.sensor_type) 4425 { 4426 case X74_SENSOR: 4427 dev->shadow_regs[0x2c] = 0x04; 4428 dev->shadow_regs[0x2d] = 0x46; 4429 dev->shadow_regs[0x34] = 0x05; 4430 dev->shadow_regs[0x35] = 0x05; 4431 dev->shadow_regs[0x36] = 0x0b; 4432 dev->shadow_regs[0x37] = 0x0b; 4433 dev->shadow_regs[0x38] = 0x11; 4434 dev->shadow_regs[0x40] = 0x40; 4435 4436 dev->shadow_regs[0x85] = 0x00; 4437 dev->shadow_regs[0x86] = 0x00; 4438 dev->shadow_regs[0x87] = 0x00; 4439 dev->shadow_regs[0x88] = 0x00; 4440 4441 dev->shadow_regs[0x91] = 0x00; 4442 dev->shadow_regs[0x92] = 0x00; 4443 dev->shadow_regs[0x93] = 0x06; 4444 break; 4445 case X1100_B2_SENSOR: 4446 dev->shadow_regs[0x34] = 0x11; 4447 dev->shadow_regs[0x35] = 0x11; 4448 dev->shadow_regs[0x36] = 0x21; 4449 dev->shadow_regs[0x37] = 0x21; 4450 dev->shadow_regs[0x38] = 0x31; 4451 4452 dev->shadow_regs[0x85] = 0x00; 4453 dev->shadow_regs[0x86] = 0x00; 4454 dev->shadow_regs[0x87] = 0x00; 4455 dev->shadow_regs[0x88] = 0x00; 4456 4457 dev->shadow_regs[0x91] = 0x00; 4458 dev->shadow_regs[0x92] = 0x00; 4459 dev->shadow_regs[0x93] = 0x06; 4460 break; 4461 case X1100_2C_SENSOR: 4462 dev->shadow_regs[0x34] = 0x07; 4463 dev->shadow_regs[0x35] = 0x07; 4464 dev->shadow_regs[0x36] = 0x0d; 4465 dev->shadow_regs[0x37] = 0x0d; 4466 dev->shadow_regs[0x38] = 0x13; 4467 4468 dev->shadow_regs[0x85] = 0x20; 4469 dev->shadow_regs[0x86] = 0x00; 4470 dev->shadow_regs[0x87] = 0x00; 4471 dev->shadow_regs[0x88] = 0x00; 4472 4473 dev->shadow_regs[0x91] = 0x00; 4474 dev->shadow_regs[0x92] = 0x00; 4475 dev->shadow_regs[0x93] = 0x06; 4476 break; 4477 case A920_SENSOR: 4478 dev->shadow_regs[0x34] = 0x05; 4479 dev->shadow_regs[0x35] = 0x05; 4480 dev->shadow_regs[0x36] = 0x0b; 4481 dev->shadow_regs[0x37] = 0x0b; 4482 dev->shadow_regs[0x38] = 0x11; 4483 4484 dev->shadow_regs[0x85] = 0x05; 4485 dev->shadow_regs[0x86] = 0x14; 4486 dev->shadow_regs[0x87] = 0x06; 4487 dev->shadow_regs[0x88] = 0x04; 4488 4489 dev->shadow_regs[0x91] = 0xe0; 4490 dev->shadow_regs[0x92] = 0x85; 4491 dev->shadow_regs[0x93] = 0x0e; 4492 break; 4493 case X1200_SENSOR: 4494 dev->shadow_regs[0x34] = 0x03; 4495 dev->shadow_regs[0x35] = 0x03; 4496 dev->shadow_regs[0x36] = 0x07; 4497 dev->shadow_regs[0x37] = 0x07; 4498 dev->shadow_regs[0x38] = 0x0b; 4499 4500 /* data compression 4501 dev->shadow_regs[0x40] = 0x90; 4502 dev->shadow_regs[0x50] = 0x20; */ 4503 /* no data compression */ 4504 dev->shadow_regs[0x40] = 0x80; 4505 dev->shadow_regs[0x50] = 0x00; 4506 4507 dev->shadow_regs[0x85] = 0x00; 4508 dev->shadow_regs[0x86] = 0x00; 4509 dev->shadow_regs[0x87] = 0xff; 4510 dev->shadow_regs[0x88] = 0x02; 4511 4512 dev->shadow_regs[0x92] = 0x00; 4513 4514 break; 4515 case X1200_USB2_SENSOR: 4516 dev->shadow_regs[0x34] = 0x03; 4517 dev->shadow_regs[0x35] = 0x03; 4518 dev->shadow_regs[0x36] = 0x07; 4519 dev->shadow_regs[0x37] = 0x07; 4520 dev->shadow_regs[0x38] = 0x0b; 4521 4522 dev->shadow_regs[0x40] = 0x80; 4523 dev->shadow_regs[0x50] = 0x00; 4524 4525 dev->shadow_regs[0x85] = 0x00; 4526 dev->shadow_regs[0x86] = 0x00; 4527 dev->shadow_regs[0x87] = 0xff; 4528 dev->shadow_regs[0x88] = 0x02; 4529 4530 dev->shadow_regs[0x92] = 0x00; 4531 break; 4532 } 4533 switch (dev->model.motor_type) 4534 { 4535 case X74_MOTOR: 4536 /* set # of head moves per CIS read */ 4537 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 4538 /* ? */ 4539 dev->shadow_regs[0xc4] = 0x20; 4540 dev->shadow_regs[0xc5] = 0x22; 4541 /* Movement direction & step size */ 4542 dev->shadow_regs[0xc6] = 0x0b; 4543 4544 dev->shadow_regs[0xc8] = 0x04; 4545 dev->shadow_regs[0xc9] = 0x39; 4546 dev->shadow_regs[0xca] = 0x1f; 4547 4548 /* bounds of movement range0 */ 4549 dev->shadow_regs[0xe0] = 0x2f; 4550 dev->shadow_regs[0xe1] = 0x11; 4551 /* step size range0 */ 4552 dev->shadow_regs[0xe2] = 0x9f; 4553 /* ? */ 4554 dev->shadow_regs[0xe3] = 0x0f; 4555 /* bounds of movement range1 */ 4556 dev->shadow_regs[0xe4] = 0xcb; 4557 4558 dev->shadow_regs[0xe5] = 0x10; 4559 /* step size range1 */ 4560 dev->shadow_regs[0xe6] = 0x64; 4561 /* bounds of movement range2 */ 4562 dev->shadow_regs[0xe7] = 0x00; 4563 dev->shadow_regs[0xe8] = 0x00; 4564 /* step size range2 */ 4565 dev->shadow_regs[0xe9] = 0x32; 4566 /* bounds of movement range3 */ 4567 dev->shadow_regs[0xea] = 0x00; 4568 dev->shadow_regs[0xeb] = 0x00; 4569 /* step size range3 */ 4570 dev->shadow_regs[0xec] = 0x0c; 4571 /* bounds of movement range4 -only for 75dpi grayscale */ 4572 dev->shadow_regs[0xed] = 0x00; 4573 dev->shadow_regs[0xee] = 0x00; 4574 /* step size range4 */ 4575 dev->shadow_regs[0xef] = 0x08; 4576 break; 4577 case X1100_MOTOR: 4578 case A920_MOTOR: 4579 /* set ? only for colour? */ 4580 dev->shadow_regs[0x80] = 0x00; 4581 dev->shadow_regs[0x81] = 0x00; 4582 dev->shadow_regs[0x82] = 0x00; 4583 /* ? */ 4584 dev->shadow_regs[0xc5] = 0x22; 4585 /* Movement direction & step size */ 4586 dev->shadow_regs[0xc6] = 0x09; 4587 /* ? */ 4588 dev->shadow_regs[0xc9] = 0x3b; 4589 dev->shadow_regs[0xca] = 0x1f; 4590 /* bounds of movement range0 */ 4591 dev->shadow_regs[0xe0] = 0xf7; 4592 dev->shadow_regs[0xe1] = 0x16; 4593 /* step size range0 */ 4594 dev->shadow_regs[0xe2] = 0x87; 4595 /* ? */ 4596 dev->shadow_regs[0xe3] = 0x13; 4597 /* bounds of movement range1 */ 4598 dev->shadow_regs[0xe4] = 0x1b; 4599 dev->shadow_regs[0xe5] = 0x16; 4600 /* step size range1 */ 4601 dev->shadow_regs[0xe6] = 0xdc; 4602 /* bounds of movement range2 */ 4603 dev->shadow_regs[0xe7] = 0x00; 4604 dev->shadow_regs[0xe8] = 0x00; 4605 /* step size range2 */ 4606 dev->shadow_regs[0xe9] = 0x1b; 4607 /* bounds of movement range3 */ 4608 dev->shadow_regs[0xea] = 0x00; 4609 dev->shadow_regs[0xeb] = 0x00; 4610 /* step size range3 */ 4611 dev->shadow_regs[0xec] = 0x07; 4612 /* step size range4 */ 4613 dev->shadow_regs[0xef] = 0x03; 4614 break; 4615 } 4616 4617 /* set grayscale scan */ 4618 dev->shadow_regs[0x2f] = 0x21; 4619 4620 /* set motor resolution divisor */ 4621 dev->shadow_regs[0x39] = 0x01; 4622 4623 /* set # of head moves per CIS read */ 4624 rts88xx_set_scan_frequency (dev->shadow_regs, 1); 4625 4626 /* Motor enable & Coordinate space denominator */ 4627 dev->shadow_regs[0xc3] = 0x81; 4628 } /* else (grayscale) */ 4629 4630 /* set horizontal resolution */ 4631 dev->shadow_regs[0x79] = 0x40; 4632 4633 } 4634 /*600dpi x 1200dpi */ 4635 if (resolution == 1200) 4636 { 4637 DBG (5, "sanei_lexmark_low_set_scan_regs(): 1200 DPI resolution\n"); 4638 4639 /* 1200 dpi doesn't work for X74 yet */ 4640 if (dev->model.sensor_type == X74_SENSOR) 4641 return SANE_STATUS_INVAL; 4642 4643 if (isColourScan) 4644 { 4645 /* set colour scan */ 4646 dev->shadow_regs[0x2f] = 0x11; 4647 /* set motor resolution divisor */ 4648 dev->shadow_regs[0x39] = 0x01; 4649 /* set # of head moves per CIS read */ 4650 rts88xx_set_scan_frequency (dev->shadow_regs, 2); 4651 4652 if (dev->model.sensor_type == X1100_B2_SENSOR) 4653 { 4654 /* set ? */ 4655 dev->shadow_regs[0x34] = 0x29; 4656 dev->shadow_regs[0x36] = 0x29; 4657 dev->shadow_regs[0x38] = 0x28; 4658 /* set ? */ 4659 dev->shadow_regs[0x80] = 0x04; 4660 dev->shadow_regs[0x81] = 0x04; 4661 dev->shadow_regs[0x82] = 0x08; 4662 dev->shadow_regs[0x85] = 0x83; 4663 dev->shadow_regs[0x86] = 0x7e; 4664 dev->shadow_regs[0x87] = 0xad; 4665 dev->shadow_regs[0x88] = 0x35; 4666 dev->shadow_regs[0x91] = 0xfe; 4667 dev->shadow_regs[0x92] = 0xdf; 4668 } 4669 else 4670 { /* A920 case */ 4671 dev->shadow_regs[0x34] = 0x0c; 4672 dev->shadow_regs[0x36] = 0x1e; 4673 dev->shadow_regs[0x38] = 0x10; 4674 4675 dev->shadow_regs[0x80] = 0x0c; 4676 dev->shadow_regs[0x81] = 0x08; 4677 dev->shadow_regs[0x82] = 0x0c; 4678 4679 dev->shadow_regs[0x85] = 0x05; 4680 dev->shadow_regs[0x86] = 0x14; 4681 dev->shadow_regs[0x87] = 0x06; 4682 dev->shadow_regs[0x88] = 0x04; 4683 4684 dev->shadow_regs[0x91] = 0x60; 4685 dev->shadow_regs[0x92] = 0x85; 4686 } 4687 4688 dev->shadow_regs[0x35] = 0x01; 4689 dev->shadow_regs[0x37] = 0x01; 4690 /* set motor resolution divisor */ 4691 dev->shadow_regs[0x39] = 0x01; 4692 dev->shadow_regs[0x93] = 0x0e; 4693 4694 /* Motor enable & Coordinate space denominator */ 4695 dev->shadow_regs[0xc3] = 0x86; 4696 /* ? */ 4697 dev->shadow_regs[0xc5] = 0x41; 4698 /* Movement direction & step size */ 4699 dev->shadow_regs[0xc6] = 0x0c; 4700 /* ? */ 4701 dev->shadow_regs[0xc9] = 0x3a; 4702 dev->shadow_regs[0xca] = 0x40; 4703 /* bounds of movement range0 */ 4704 dev->shadow_regs[0xe0] = 0x00; 4705 dev->shadow_regs[0xe1] = 0x00; 4706 /* step size range0 */ 4707 dev->shadow_regs[0xe2] = 0x85; 4708 /* ? */ 4709 dev->shadow_regs[0xe3] = 0x0b; 4710 /* bounds of movement range1 */ 4711 dev->shadow_regs[0xe4] = 0x00; 4712 dev->shadow_regs[0xe5] = 0x00; 4713 /* step size range1 */ 4714 dev->shadow_regs[0xe6] = 0x0e; 4715 /* bounds of movement range2 */ 4716 dev->shadow_regs[0xe7] = 0x00; 4717 dev->shadow_regs[0xe8] = 0x00; 4718 /* step size range2 */ 4719 dev->shadow_regs[0xe9] = 0x05; 4720 /* bounds of movement range3 */ 4721 dev->shadow_regs[0xea] = 0x00; 4722 dev->shadow_regs[0xeb] = 0x00; 4723 /* step size range3 */ 4724 dev->shadow_regs[0xec] = 0x01; 4725 /* step size range4 */ 4726 dev->shadow_regs[0xef] = 0x01; 4727 } 4728 else 4729 { 4730 /* set grayscale scan */ 4731 dev->shadow_regs[0x2f] = 0x21; 4732 /* set ? */ 4733 dev->shadow_regs[0x34] = 0x22; 4734 dev->shadow_regs[0x35] = 0x22; 4735 dev->shadow_regs[0x36] = 0x42; 4736 dev->shadow_regs[0x37] = 0x42; 4737 dev->shadow_regs[0x38] = 0x62; 4738 /* set motor resolution divisor */ 4739 dev->shadow_regs[0x39] = 0x01; 4740 /* set # of head moves per CIS read */ 4741 rts88xx_set_scan_frequency (dev->shadow_regs, 0); 4742 4743 /* set ? only for colour? */ 4744 dev->shadow_regs[0x80] = 0x00; 4745 dev->shadow_regs[0x81] = 0x00; 4746 dev->shadow_regs[0x82] = 0x00; 4747 dev->shadow_regs[0x85] = 0x00; 4748 dev->shadow_regs[0x86] = 0x00; 4749 dev->shadow_regs[0x87] = 0x00; 4750 dev->shadow_regs[0x88] = 0x00; 4751 dev->shadow_regs[0x91] = 0x00; 4752 dev->shadow_regs[0x92] = 0x00; 4753 dev->shadow_regs[0x93] = 0x06; 4754 /* Motor enable & Coordinate space denominator */ 4755 dev->shadow_regs[0xc3] = 0x81; 4756 /* ? */ 4757 dev->shadow_regs[0xc5] = 0x41; 4758 /* Movement direction & step size */ 4759 dev->shadow_regs[0xc6] = 0x09; 4760 /* ? */ 4761 dev->shadow_regs[0xc9] = 0x3a; 4762 dev->shadow_regs[0xca] = 0x40; 4763 /* bounds of movement range0 */ 4764 dev->shadow_regs[0xe0] = 0x00; 4765 dev->shadow_regs[0xe1] = 0x00; 4766 /* step size range0 */ 4767 dev->shadow_regs[0xe2] = 0xc7; 4768 /* ? */ 4769 dev->shadow_regs[0xe3] = 0x29; 4770 /* bounds of movement range1 */ 4771 dev->shadow_regs[0xe4] = 0x00; 4772 dev->shadow_regs[0xe5] = 0x00; 4773 /* step size range1 */ 4774 dev->shadow_regs[0xe6] = 0xdc; 4775 /* bounds of movement range2 */ 4776 dev->shadow_regs[0xe7] = 0x00; 4777 dev->shadow_regs[0xe8] = 0x00; 4778 /* step size range2 */ 4779 dev->shadow_regs[0xe9] = 0x1b; 4780 /* bounds of movement range3 */ 4781 dev->shadow_regs[0xea] = 0x00; 4782 dev->shadow_regs[0xeb] = 0x00; 4783 /* step size range3 */ 4784 dev->shadow_regs[0xec] = 0x07; 4785 /* step size range4 */ 4786 dev->shadow_regs[0xef] = 0x03; 4787 } 4788 4789 /* set horizontal resolution */ 4790 dev->shadow_regs[0x79] = 0x40; 4791 } 4792 4793 /* is calibration has been done, we override fixed settings with detected ones */ 4794 if (calibrated) 4795 { 4796 /* override fixed values with ones from calibration */ 4797 if (rts88xx_is_color (dev->shadow_regs)) 4798 { 4799 rts88xx_set_offset (dev->shadow_regs, 4800 dev->offset.red, 4801 dev->offset.green, dev->offset.blue); 4802 rts88xx_set_gain (dev->shadow_regs, 4803 dev->gain.red, dev->gain.green, dev->gain.blue); 4804 } 4805 else 4806 { 4807 rts88xx_set_offset (dev->shadow_regs, 4808 dev->offset.gray, 4809 dev->offset.gray, dev->offset.gray); 4810 rts88xx_set_gain (dev->shadow_regs, 4811 dev->gain.gray, dev->gain.gray, dev->gain.gray); 4812 } 4813 } 4814 DBG (2, "sanei_lexmark_low_set_scan_regs: end.\n"); 4815 return SANE_STATUS_GOOD; 4816} 4817 4818SANE_Status 4819sanei_lexmark_low_start_scan (Lexmark_Device * dev) 4820{ 4821 SANE_Int devnum; 4822 4823 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; 4824 4825 static SANE_Byte command5_block[] = { 0x80, 0xb3, 0x00, 0x01 }; 4826 4827 SANE_Byte poll_result[3]; 4828 SANE_Byte read_result; 4829 SANE_Bool scan_head_moving; 4830 size_t size; 4831 4832 devnum = dev->devnum; 4833 4834 dev->transfer_buffer = NULL; /* No data xferred yet */ 4835 DBG (2, "sanei_lexmark_low_start_scan:\n"); 4836 4837 4838 /* 80 b3 00 01 - poll for scanner not moving */ 4839 scan_head_moving = SANE_TRUE; 4840 while (scan_head_moving) 4841 { 4842 size = 4; 4843 low_usb_bulk_write (devnum, command5_block, &size); 4844 size = 0x1; 4845 low_usb_bulk_read (devnum, &read_result, &size); 4846 if ((read_result & 0xF) == 0x0) 4847 { 4848 scan_head_moving = SANE_FALSE; 4849 } 4850 /* F.O. Should be a timeout here so we don't hang if something breaks */ 4851#ifdef FAKE_USB 4852 scan_head_moving = SANE_FALSE; 4853#endif 4854 } 4855 4856 /* Clear C6 */ 4857 low_clr_c6 (devnum); 4858 /* Stop the scanner */ 4859 low_stop_mvmt (devnum); 4860 4861 /*Set regs x2 */ 4862 dev->shadow_regs[0x32] = 0x00; 4863 low_write_all_regs (devnum, dev->shadow_regs); 4864 dev->shadow_regs[0x32] = 0x40; 4865 low_write_all_regs (devnum, dev->shadow_regs); 4866 4867 /* Start Scan */ 4868 rts88xx_commit (devnum, dev->shadow_regs[0x2c]); 4869 4870 /* We start with 0 bytes remaining to be read */ 4871 dev->bytes_remaining = 0; 4872 /* and 0 bytes in the transfer buffer */ 4873 dev->bytes_in_buffer = 0; 4874 dev->bytes_read = 0; 4875 4876 /* Poll the available byte count until not 0 */ 4877 while (1) 4878 { 4879 size = 4; 4880 low_usb_bulk_write (devnum, command4_block, &size); 4881 size = 0x3; 4882 low_usb_bulk_read (devnum, poll_result, &size); 4883 if (! 4884 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) 4885 { 4886 /* if result != 00 00 00 we got data */ 4887 4888 /* data_size should be used to set bytes_remaining */ 4889 /* data_size is set from sane_get_parameters () */ 4890 dev->bytes_remaining = dev->data_size; 4891 /* Initialize the read buffer */ 4892 read_buffer_init (dev, dev->params.bytes_per_line); 4893 return SANE_STATUS_GOOD; 4894 4895 } 4896 size = 4; 4897 /* I'm not sure why the Windows driver does this - probably a timeout? */ 4898 low_usb_bulk_write (devnum, command5_block, &size); 4899 size = 0x1; 4900 low_usb_bulk_read (devnum, &read_result, &size); 4901 if (read_result != 0x68) 4902 { 4903 dev->bytes_remaining = 0; 4904 return SANE_STATUS_IO_ERROR; 4905 } 4906 } 4907 4908 DBG (2, "sanei_lexmark_low_start_scan: end.\n"); 4909 return SANE_STATUS_GOOD; 4910} 4911 4912long 4913sanei_lexmark_low_read_scan_data (SANE_Byte * data, SANE_Int size, 4914 Lexmark_Device * dev) 4915{ 4916 SANE_Bool isColourScan, isGrayScan; 4917 static SANE_Byte command1_block[] = { 0x91, 0x00, 0xff, 0xc0 }; 4918 size_t cmd_size, xfer_request; 4919 long bytes_read; 4920 SANE_Bool even_byte; 4921 SANE_Status status; 4922 int i, k, val; 4923 4924 DBG (2, "sanei_lexmark_low_read_scan_data:\n"); 4925 4926 /* colour mode */ 4927 isGrayScan = SANE_FALSE; 4928 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 4929 isColourScan = SANE_TRUE; 4930 else 4931 { 4932 isColourScan = SANE_FALSE; 4933 /* grayscale mode */ 4934 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) 4935 isGrayScan = SANE_TRUE; 4936 } 4937 4938 /* Check if we have a transfer buffer. Create one and fill it if we don't */ 4939 if (dev->transfer_buffer == NULL) 4940 { 4941 if (dev->bytes_remaining > 0) 4942 { 4943 if (dev->bytes_remaining > MAX_XFER_SIZE) 4944 xfer_request = MAX_XFER_SIZE; 4945 else 4946 xfer_request = dev->bytes_remaining; 4947 4948 command1_block[2] = (SANE_Byte) (xfer_request >> 8); 4949 command1_block[3] = (SANE_Byte) (xfer_request & 0xFF); 4950 4951 /* wait for data */ 4952 status = low_poll_data (dev->devnum); 4953 if (status != SANE_STATUS_GOOD) 4954 { 4955 DBG (1, 4956 "sanei_lexmark_low_read_scan_data: time-out while waiting for data.\n"); 4957 return status; 4958 } 4959 4960 /* Create buffer to hold the amount we will request */ 4961 dev->transfer_buffer = (SANE_Byte *) malloc (MAX_XFER_SIZE); 4962 if (dev->transfer_buffer == NULL) 4963 return SANE_STATUS_NO_MEM; 4964 4965 /* Fill it */ 4966 /* Write: 91 00 (xfer_size) */ 4967 cmd_size = 4; 4968 low_usb_bulk_write (dev->devnum, command1_block, &cmd_size); 4969 4970 /* Read: xfer_size bytes */ 4971 cmd_size = xfer_request; 4972 low_usb_bulk_read (dev->devnum, dev->transfer_buffer, &cmd_size); 4973 4974 /* apply shading coefficients */ 4975 k = dev->bytes_read % dev->read_buffer->linesize; 4976 for (i = 0; i < (int) cmd_size; i++) 4977 { 4978 val = dev->transfer_buffer[i]; 4979 val = (int) ((float) val * dev->shading_coeff[k] + 0.5); 4980 if (val > 255) 4981 val = 255; 4982 dev->transfer_buffer[i] = val; 4983 k++; 4984 if ((size_t) k == dev->read_buffer->linesize) 4985 k = 0; 4986 } 4987 4988 /* advance by the amount actually read from device */ 4989 dev->bytes_read += cmd_size; 4990 dev->bytes_remaining -= cmd_size; 4991 dev->bytes_in_buffer = cmd_size; 4992 dev->read_pointer = dev->transfer_buffer; 4993 DBG (2, "sanei_lexmark_low_read_scan_data:\n"); 4994 DBG (2, " Filled a buffer from the scanner\n"); 4995 DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining); 4996 DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer); 4997 DBG (2, " read_pointer: %p\n", (void *) dev->read_pointer); 4998 } 4999 } 5000 5001 DBG (5, "READ BUFFER INFO: \n"); 5002 DBG (5, " write ptr: %p\n", (void *) dev->read_buffer->writeptr); 5003 DBG (5, " read ptr: %p\n", (void *) dev->read_buffer->readptr); 5004 DBG (5, " max write ptr: %p\n", (void *) dev->read_buffer->max_writeptr); 5005 DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size); 5006 DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize); 5007 DBG (5, " empty: %d\n", dev->read_buffer->empty); 5008 DBG (5, " line no: %d\n", dev->read_buffer->image_line_no); 5009 5010 5011 /* If there is space in the read buffer, copy the transfer buffer over */ 5012 if (read_buffer_bytes_available (dev->read_buffer) >= dev->bytes_in_buffer) 5013 { 5014 even_byte = SANE_TRUE; 5015 while (dev->bytes_in_buffer) 5016 { 5017 5018 /* Colour Scan */ 5019 if (isColourScan) 5020 { 5021 if (even_byte) 5022 read_buffer_add_byte (dev->read_buffer, 5023 dev->read_pointer + 1); 5024 else 5025 read_buffer_add_byte (dev->read_buffer, 5026 dev->read_pointer - 1); 5027 even_byte = !even_byte; 5028 } 5029 /* Gray Scan */ 5030 else if (isGrayScan) 5031 { 5032 if (even_byte) 5033 read_buffer_add_byte_gray (dev->read_buffer, 5034 dev->read_pointer + 1); 5035 else 5036 read_buffer_add_byte_gray (dev->read_buffer, 5037 dev->read_pointer - 1); 5038 even_byte = !even_byte; 5039 } 5040 /* Lineart Scan */ 5041 else 5042 { 5043 if (even_byte) 5044 read_buffer_add_bit_lineart (dev->read_buffer, 5045 dev->read_pointer + 1, 5046 dev->threshold); 5047 else 5048 read_buffer_add_bit_lineart (dev->read_buffer, 5049 dev->read_pointer - 1, 5050 dev->threshold); 5051 even_byte = !even_byte; 5052 } 5053 dev->read_pointer = dev->read_pointer + sizeof (SANE_Byte); 5054 dev->bytes_in_buffer--; 5055 } 5056 /* free the transfer buffer */ 5057 free (dev->transfer_buffer); 5058 dev->transfer_buffer = NULL; 5059 } 5060 5061 DBG (5, "READ BUFFER INFO: \n"); 5062 DBG (5, " write ptr: %p\n", (void *) dev->read_buffer->writeptr); 5063 DBG (5, " read ptr: %p\n", (void *) dev->read_buffer->readptr); 5064 DBG (5, " max write ptr: %p\n", (void *) dev->read_buffer->max_writeptr); 5065 DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size); 5066 DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize); 5067 DBG (5, " empty: %d\n", dev->read_buffer->empty); 5068 DBG (5, " line no: %d\n", dev->read_buffer->image_line_no); 5069 5070 /* Read blocks out of read buffer */ 5071 bytes_read = read_buffer_get_bytes (dev->read_buffer, data, size); 5072 5073 DBG (2, "sanei_lexmark_low_read_scan_data:\n"); 5074 DBG (2, " Copying lines from buffer to data\n"); 5075 DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining); 5076 DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer); 5077 DBG (2, " read_pointer: %p\n", (void *) dev->read_buffer->readptr); 5078 DBG (2, " bytes_read %lu\n", (u_long) bytes_read); 5079 5080 /* if no more bytes to xfer and read buffer empty we're at the end */ 5081 if ((dev->bytes_remaining == 0) && read_buffer_is_empty (dev->read_buffer)) 5082 { 5083 if (!dev->eof) 5084 { 5085 DBG (2, 5086 "sanei_lexmark_low_read_scan_data: EOF- parking the scanner\n"); 5087 dev->eof = SANE_TRUE; 5088 low_rewind (dev, dev->shadow_regs); 5089 } 5090 else 5091 { 5092 DBG (2, "ERROR: Why are we trying to set eof more than once?\n"); 5093 } 5094 } 5095 5096 DBG (2, "sanei_lexmark_low_read_scan_data: end.\n"); 5097 return bytes_read; 5098} 5099 5100void 5101low_rewind (Lexmark_Device * dev, SANE_Byte * regs) 5102{ 5103 SANE_Int new_location; 5104 SANE_Int location; 5105 SANE_Int scale; 5106 5107 DBG (2, "low_rewind: \n"); 5108 5109 /* We rewind at 1200dpi resolution. We rely on content of shadow registers 5110 to compute the number of lines at 1200 dpi to go back */ 5111 5112 /* first move to start of scanning area */ 5113 scale = 600 / dev->val[OPT_RESOLUTION].w; 5114 new_location = ((dev->val[OPT_BR_Y].w / scale) * scale) * 2; 5115 5116 /* then add distance to go to the "origin dot" */ 5117 if (rts88xx_is_color (regs)) 5118 new_location += 400; 5119 else 5120 new_location += 420; 5121 5122 if (dev->model.sensor_type == X74_SENSOR) 5123 new_location += 150; 5124 5125 5126 location = new_location - 1; 5127 DBG (2, "low_rewind: %d=>new_location=%d\n", dev->val[OPT_BR_Y].w, 5128 new_location); 5129 5130 /* stops any pending scan */ 5131 low_clr_c6 (dev->devnum); 5132 low_cancel (dev->devnum); 5133 5134 /* set regs for rewind */ 5135 regs[0x2f] = 0xa1; 5136 regs[0x32] = 0x00; 5137 regs[0x39] = 0x00; 5138 5139 /* all other regs are always the same. these ones change with parameters */ 5140 /* the following 4 regs are the location 61,60 and the location+1 63,62 */ 5141 5142 regs[0x60] = LOBYTE (location); 5143 regs[0x61] = HIBYTE (location); 5144 regs[0x62] = LOBYTE (new_location); 5145 regs[0x63] = HIBYTE (new_location); 5146 5147 switch (dev->model.motor_type) 5148 { 5149 case X74_MOTOR: 5150 regs[0xc3] = 0x81; 5151 regs[0xc6] = 0x03; 5152 regs[0xc9] = 0x39; 5153 regs[0xe0] = 0x81; 5154 regs[0xe1] = 0x16; 5155 regs[0xe2] = 0xe1; 5156 regs[0xe3] = 0x04; 5157 regs[0xe4] = 0xe7; 5158 regs[0xe5] = 0x14; 5159 regs[0xe6] = 0x64; 5160 regs[0xe7] = 0xd5; 5161 regs[0xe8] = 0x08; 5162 regs[0xe9] = 0x32; 5163 regs[0xea] = 0xed; 5164 regs[0xeb] = 0x04; 5165 regs[0xec] = 0x0c; 5166 regs[0xef] = 0x08; 5167 break; 5168 case X1100_MOTOR: 5169 case A920_MOTOR: 5170 /* set regs for rewind */ 5171 regs[0x79] = 0x40; 5172 regs[0xb2] = 0x04; 5173 regs[0xc3] = 0x81; 5174 regs[0xc6] = 0x01; 5175 regs[0xc9] = 0x3b; 5176 regs[0xe0] = 0x2b; 5177 regs[0xe1] = 0x17; 5178 regs[0xe2] = 0xe7; 5179 regs[0xe3] = 0x03; 5180 regs[0xe6] = 0xdc; 5181 regs[0xe7] = 0xb3; 5182 regs[0xe8] = 0x07; 5183 regs[0xe9] = 0x1b; 5184 regs[0xea] = 0x00; 5185 regs[0xeb] = 0x00; 5186 regs[0xec] = 0x07; 5187 regs[0xef] = 0x03; 5188 break; 5189 } 5190 5191 5192 /* starts scan */ 5193 low_start_scan (dev->devnum, regs); 5194 DBG (2, "low_rewind: end.\n"); 5195} 5196 5197 5198SANE_Status 5199read_buffer_init (Lexmark_Device * dev, int bytesperline) 5200{ 5201 size_t no_lines_in_buffer; 5202 5203 DBG (2, "read_buffer_init: Start\n"); 5204 5205 dev->read_buffer = (Read_Buffer *) malloc (sizeof (Read_Buffer)); 5206 if (dev->read_buffer == NULL) 5207 return SANE_STATUS_NO_MEM; 5208 dev->read_buffer->linesize = bytesperline; 5209 dev->read_buffer->gray_offset = 0; 5210 dev->read_buffer->max_gray_offset = bytesperline - 1; 5211 dev->read_buffer->region = RED; 5212 dev->read_buffer->red_offset = 0; 5213 dev->read_buffer->green_offset = 1; 5214 dev->read_buffer->blue_offset = 2; 5215 dev->read_buffer->max_red_offset = bytesperline - 3; 5216 dev->read_buffer->max_green_offset = bytesperline - 2; 5217 dev->read_buffer->max_blue_offset = bytesperline - 1; 5218 no_lines_in_buffer = 3 * MAX_XFER_SIZE / bytesperline; 5219 dev->read_buffer->size = bytesperline * no_lines_in_buffer; 5220 dev->read_buffer->data = (SANE_Byte *) malloc (dev->read_buffer->size); 5221 if (dev->read_buffer->data == NULL) 5222 return SANE_STATUS_NO_MEM; 5223 dev->read_buffer->readptr = dev->read_buffer->data; 5224 dev->read_buffer->writeptr = dev->read_buffer->data; 5225 dev->read_buffer->max_writeptr = dev->read_buffer->data + 5226 (no_lines_in_buffer - 1) * bytesperline; 5227 dev->read_buffer->empty = SANE_TRUE; 5228 dev->read_buffer->image_line_no = 0; 5229 dev->read_buffer->bit_counter = 0; 5230 dev->read_buffer->max_lineart_offset = dev->params.pixels_per_line - 1; 5231 return SANE_STATUS_GOOD; 5232} 5233 5234SANE_Status 5235read_buffer_free (Read_Buffer * read_buffer) 5236{ 5237 DBG (2, "read_buffer_free:\n"); 5238 if (read_buffer) 5239 { 5240 free (read_buffer->data); 5241 free (read_buffer); 5242 read_buffer = NULL; 5243 } 5244 return SANE_STATUS_GOOD; 5245} 5246 5247size_t 5248read_buffer_bytes_available (Read_Buffer * rb) 5249{ 5250 5251 DBG (2, "read_buffer_bytes_available:\n"); 5252 5253 if (rb->empty) 5254 return rb->size; 5255 else if (rb->writeptr < rb->readptr) 5256 return (size_t)(rb->readptr - rb->writeptr) < rb->linesize ? 0 : 5257 (size_t)(rb->readptr - rb->writeptr) - rb->linesize; 5258 else 5259 return (size_t)(rb->writeptr - rb->readptr) < rb->linesize ? 0 : 5260 rb->size - (size_t)(rb->writeptr - rb->readptr) - rb->linesize; 5261} 5262 5263SANE_Status 5264read_buffer_add_byte (Read_Buffer * rb, SANE_Byte * byte_pointer) 5265{ 5266 5267 /* DBG(2, "read_buffer_add_byte:\n"); */ 5268 /* F.O. Need to fix the endian byte ordering here */ 5269 5270 switch (rb->region) 5271 { 5272 case RED: 5273 *(rb->writeptr + rb->red_offset) = *byte_pointer; 5274 if (rb->red_offset == rb->max_red_offset) 5275 { 5276 rb->red_offset = 0; 5277 rb->region = GREEN; 5278 } 5279 else 5280 rb->red_offset = rb->red_offset + (3 * sizeof (SANE_Byte)); 5281 return SANE_STATUS_GOOD; 5282 case GREEN: 5283 *(rb->writeptr + rb->green_offset) = *byte_pointer; 5284 if (rb->green_offset == rb->max_green_offset) 5285 { 5286 rb->green_offset = 1; 5287 rb->region = BLUE; 5288 } 5289 else 5290 rb->green_offset = rb->green_offset + (3 * sizeof (SANE_Byte)); 5291 return SANE_STATUS_GOOD; 5292 case BLUE: 5293 *(rb->writeptr + rb->blue_offset) = *byte_pointer; 5294 if (rb->blue_offset == rb->max_blue_offset) 5295 { 5296 rb->image_line_no++; 5297 /* finished a line. read_buffer no longer empty */ 5298 rb->empty = SANE_FALSE; 5299 rb->blue_offset = 2; 5300 rb->region = RED; 5301 if (rb->writeptr == rb->max_writeptr) 5302 rb->writeptr = rb->data; /* back to beginning of buffer */ 5303 else 5304 rb->writeptr = rb->writeptr + rb->linesize; /* next line */ 5305 } 5306 else 5307 rb->blue_offset = rb->blue_offset + (3 * sizeof (SANE_Byte)); 5308 return SANE_STATUS_GOOD; 5309 } 5310 return SANE_STATUS_GOOD; 5311} 5312 5313SANE_Status 5314read_buffer_add_byte_gray (Read_Buffer * rb, SANE_Byte * byte_pointer) 5315{ 5316 5317 /* DBG(2, "read_buffer_add_byte_gray:\n"); */ 5318 5319 *(rb->writeptr + rb->gray_offset) = *byte_pointer; 5320 5321 if (rb->gray_offset == rb->max_gray_offset) 5322 { 5323 rb->image_line_no++; 5324 /* finished a line. read_buffer no longer empty */ 5325 rb->empty = SANE_FALSE; 5326 rb->gray_offset = 0; 5327 5328 if (rb->writeptr == rb->max_writeptr) 5329 rb->writeptr = rb->data; /* back to beginning of buffer */ 5330 else 5331 rb->writeptr = rb->writeptr + rb->linesize; /* next line */ 5332 } 5333 else 5334 rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte)); 5335 return SANE_STATUS_GOOD; 5336} 5337 5338SANE_Status 5339read_buffer_add_bit_lineart (Read_Buffer * rb, SANE_Byte * byte_pointer, 5340 SANE_Byte threshold) 5341{ 5342 SANE_Byte tmpByte; 5343 SANE_Byte *currentBytePtr; 5344 SANE_Int bitIndex; 5345 5346 /* DBG(2, "read_buffer_add_bit_lineart:\n"); */ 5347 5348 /* threshold = 0x80; */ 5349 tmpByte = 0; 5350 /* Create a bit by comparing incoming byte to threshold */ 5351 if (*byte_pointer <= threshold) 5352 { 5353 tmpByte = 128; 5354 } 5355 5356 /* Calculate the bit index in the current byte */ 5357 bitIndex = rb->bit_counter % 8; 5358 /* Move the bit to its correct position in the temporary byte */ 5359 tmpByte = tmpByte >> bitIndex; 5360 /* Get the pointer to the current byte */ 5361 currentBytePtr = rb->writeptr + rb->gray_offset; 5362 5363 /* If this is the first write to this byte, clear the byte */ 5364 if (bitIndex == 0) 5365 *currentBytePtr = 0; 5366 /* Set the value of the bit in the current byte */ 5367 *currentBytePtr = *currentBytePtr | tmpByte; 5368 5369 /* last bit in the line? */ 5370 if (rb->bit_counter == rb->max_lineart_offset) 5371 { 5372 /* Check if we're at the last byte of the line - error if not */ 5373 if (rb->gray_offset != rb->max_gray_offset) 5374 { 5375 DBG (5, "read_buffer_add_bit_lineart:\n"); 5376 DBG (5, " Last bit of line is not last byte.\n"); 5377 DBG (5, " Bit Index: %d, Byte Index: %d. \n", rb->bit_counter, 5378 rb->max_gray_offset); 5379 return SANE_STATUS_INVAL; 5380 } 5381 rb->image_line_no++; 5382 /* line finished read_buffer no longer empty */ 5383 rb->empty = SANE_FALSE; 5384 rb->gray_offset = 0; 5385 /* are we at the last line in the read buffer ? */ 5386 if (rb->writeptr == rb->max_writeptr) 5387 rb->writeptr = rb->data; /* back to beginning of buffer */ 5388 else 5389 rb->writeptr = rb->writeptr + rb->linesize; /* next line */ 5390 /* clear the bit counter */ 5391 rb->bit_counter = 0; 5392 } 5393 /* last bit in the byte? */ 5394 else if (bitIndex == 7) 5395 { 5396 /* Not at the end of the line, but byte done. Increment byte offset */ 5397 rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte)); 5398 /* increment bit counter */ 5399 rb->bit_counter++; 5400 } 5401 else 5402 { 5403 /* else increment bit counter */ 5404 rb->bit_counter++; 5405 } 5406 5407 return SANE_STATUS_GOOD; 5408} 5409 5410 5411size_t 5412read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, size_t rqst_size) 5413{ 5414 /* Read_Buffer *rb; */ 5415 size_t available_bytes; 5416 5417 /* rb = read_buffer; */ 5418 if (rb->empty) 5419 return 0; 5420 else if (rb->writeptr > rb->readptr) 5421 { 5422 available_bytes = rb->writeptr - rb->readptr; 5423 if (available_bytes <= rqst_size) 5424 { 5425 /* We can read from the read pointer up to the write pointer */ 5426 memcpy (buffer, rb->readptr, available_bytes); 5427 rb->readptr = rb->writeptr; 5428 rb->empty = SANE_TRUE; 5429 return available_bytes; 5430 } 5431 else 5432 { 5433 /* We can read from the full request size */ 5434 memcpy (buffer, rb->readptr, rqst_size); 5435 rb->readptr = rb->readptr + rqst_size; 5436 return rqst_size; 5437 } 5438 } 5439 else 5440 { 5441 /* The read pointer is ahead of the write pointer. Its wrapped around. */ 5442 /* We can read to the end of the buffer and make a recursive call to */ 5443 /* read any available lines at the beginning of the buffer */ 5444 available_bytes = rb->data + rb->size - rb->readptr; 5445 if (available_bytes <= rqst_size) 5446 { 5447 /* We can read from the read pointer up to the end of the buffer */ 5448 memcpy (buffer, rb->readptr, available_bytes); 5449 rb->readptr = rb->data; 5450 if (rb->writeptr == rb->readptr) 5451 rb->empty = SANE_TRUE; 5452 return available_bytes + 5453 read_buffer_get_bytes (rb, buffer + available_bytes, 5454 rqst_size - available_bytes); 5455 } 5456 else 5457 { 5458 /* We can read from the full request size */ 5459 memcpy (buffer, rb->readptr, rqst_size); 5460 rb->readptr = rb->readptr + rqst_size; 5461 return rqst_size; 5462 } 5463 } 5464} 5465 5466SANE_Bool 5467read_buffer_is_empty (Read_Buffer * read_buffer) 5468{ 5469 return read_buffer->empty; 5470} 5471 5472/* 5473 * average a width*height rgb/monochrome area 5474 * return values in given pointers 5475 */ 5476static int 5477average_area (SANE_Byte * regs, SANE_Byte * data, int width, int height, 5478 int *ra, int *ga, int *ba) 5479{ 5480 int x, y; 5481 int global = 0; 5482 int rc, gc, bc; 5483 5484 *ra = 0; 5485 *ga = 0; 5486 *ba = 0; 5487 rc = 0; 5488 gc = 0; 5489 bc = 0; 5490 if (rts88xx_is_color (regs)) 5491 { 5492 for (x = 0; x < width; x++) 5493 for (y = 0; y < height; y++) 5494 { 5495 rc += data[3 * width * y + x]; 5496 gc += data[3 * width * y + width + x]; 5497 bc += data[3 * width * y + 2 * width + x]; 5498 } 5499 global = (rc + gc + bc) / (3 * width * height); 5500 *ra = rc / (width * height); 5501 *ga = gc / (width * height); 5502 *ba = bc / (width * height); 5503 } 5504 else 5505 { 5506 for (x = 0; x < width; x++) 5507 for (y = 0; y < height; y++) 5508 { 5509 gc += data[width * y + x]; 5510 } 5511 global = gc / (width * height); 5512 *ga = gc / (width * height); 5513 } 5514 DBG (7, "average_area: global=%d, red=%d, green=%d, blue=%d\n", global, *ra, 5515 *ga, *ba); 5516 return global; 5517} 5518 5519/** 5520 * we scan a dark area with gain minimum to detect offset 5521 */ 5522SANE_Status 5523sanei_lexmark_low_offset_calibration (Lexmark_Device * dev) 5524{ 5525 SANE_Byte regs[255]; /* we have our own copy of shadow registers */ 5526 SANE_Status status = SANE_STATUS_GOOD; 5527 int i, lines = 8, yoffset = 2; 5528 int pixels; 5529 int failed = 0; 5530 /* offsets */ 5531 int ro = 0, go = 0, bo = 0; 5532 /* averages */ 5533 int ra, ga, ba, average; 5534 SANE_Byte *data = NULL; 5535 SANE_Byte top[OFFSET_RANGES] = { 0, 0x7f, 0x9f, 0xbf, 0xff }; 5536#ifdef DEEP_DEBUG 5537 char title[20]; 5538#endif 5539 5540 DBG (2, "sanei_lexmark_low_offset_calibration: start\n"); 5541 /* copy registers */ 5542 for (i = 0; i < 255; i++) 5543 regs[i] = dev->shadow_regs[i]; 5544 5545 /* we clear movement bit */ 5546 regs[0xc3] = regs[0xc3] & 0x7f; 5547 5548 pixels = 5549 (dev->sensor->offset_endx - dev->sensor->offset_startx) / regs[0x7a]; 5550 5551 /* there are 4 ranges of offset: 5552 00-7F : almost no offset 5553 80-9F : high noise 5554 A0-BF : high noise 5555 C0-FF : high noise 5556 we start with the highest one and decrease until 5557 overall offset is ok 5558 First loop may have such an high offset that scanned data overflow 5559 and gives a low average. So we always skip its results 5560 */ 5561 5562 /* minimal gains */ 5563 DBG (3, 5564 "sanei_lexmark_low_offset_calibration: setting gains to (1,1,1).\n"); 5565 rts88xx_set_gain (regs, 1, 1, 1); 5566 5567 i = OFFSET_RANGES; 5568 average = 255; 5569 5570 /* loop on ranges until one fits. Then adjust offset, first loop is 5571 * always done. TODO detect overflow by 'noise looking' data pattern */ 5572 while (((i > 0) && (average > dev->sensor->offset_threshold)) 5573 || (i == OFFSET_RANGES)) 5574 { 5575 /* next range */ 5576 i--; 5577 5578 /* sets to top of range */ 5579 ro = top[i]; 5580 go = top[i]; 5581 bo = top[i]; 5582 rts88xx_set_offset (regs, ro, ro, ro); 5583 DBG (3, 5584 "sanei_lexmark_low_offset_calibration: setting offsets to (%d,%d,%d).\n", 5585 ro, ro, ro); 5586 5587 status = 5588 low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, 5589 yoffset, lines, &data); 5590 if (status != SANE_STATUS_GOOD) 5591 { 5592 DBG (1, 5593 "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n"); 5594 if (data != NULL) 5595 free (data); 5596 return status; 5597 } 5598#ifdef DEEP_DEBUG 5599 sprintf (title, "offset%02x.pnm", ro); 5600 write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data); 5601#endif 5602 average = average_area (regs, data, pixels, lines, &ra, &ga, &ba); 5603 free (data); 5604 } 5605 if (i == 0) 5606 { 5607 DBG (2, "sanei_lexmark_low_offset_calibration: failed !\n"); 5608 failed = 1; 5609 } 5610 5611 /* increase gain and scan again */ 5612 /* increase gain for fine offset tuning */ 5613 rts88xx_set_gain (regs, 6, 6, 6); 5614 status = 5615 low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, yoffset, 5616 lines, &data); 5617 if (status != SANE_STATUS_GOOD) 5618 { 5619 DBG (1, 5620 "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n"); 5621 if (data != NULL) 5622 free (data); 5623 return status; 5624 } 5625 average_area (regs, data, pixels, lines, &ra, &ga, &ba); 5626#ifdef DEEP_DEBUG 5627 write_pnm_file ("offset-final.pnm", pixels, lines, rts88xx_is_color (regs), 5628 data); 5629#endif 5630 5631 /* this "law" is a guess, may (should?) be changed ... */ 5632 if (!failed) 5633 { 5634 if (ro > ra) 5635 dev->offset.red = ro - ra; 5636 if (go > ga) 5637 { 5638 dev->offset.green = go - ga; 5639 dev->offset.gray = go - ga; 5640 } 5641 if (bo > ba) 5642 dev->offset.blue = bo - ba; 5643 } 5644 else 5645 { 5646 dev->offset.red = dev->sensor->offset_fallback; 5647 dev->offset.green = dev->sensor->offset_fallback; 5648 dev->offset.blue = dev->sensor->offset_fallback; 5649 } 5650 DBG (7, 5651 "sanei_lexmark_low_offset_calibration: offset=(0x%02x,0x%02x,0x%02x).\n", 5652 dev->offset.red, dev->offset.green, dev->offset.blue); 5653 5654 DBG (2, "sanei_lexmark_low_offset_calibration: end.\n"); 5655 free (data); 5656 return status; 5657} 5658 5659/* 5660 * we scan a white area until average is good enough 5661 * level is good enough when it maximize the range value of output: 5662 * ie max-min is maximum 5663 */ 5664SANE_Status 5665sanei_lexmark_low_gain_calibration (Lexmark_Device * dev) 5666{ 5667 SANE_Byte regs[255]; /* we have our own copy of shadow registers */ 5668 SANE_Status status = SANE_STATUS_GOOD; 5669 int i, lines = 4, yoffset = 1; 5670 int sx, ex; 5671 int pixels; 5672 /* averages */ 5673 int ra, ga, ba; 5674 SANE_Byte *data = NULL; 5675 int red, green, blue; 5676#ifdef DEEP_DEBUG 5677 char title[20]; 5678#endif 5679 5680 DBG (2, "sanei_lexmark_low_gain_calibration: start\n"); 5681 /* copy registers */ 5682 for (i = 0; i < 255; i++) 5683 regs[i] = dev->shadow_regs[i]; 5684 5685 /* we clear movement bit */ 5686 regs[0xc3] = regs[0xc3] & 0x7f; 5687 sx = regs[0x67] * 256 + regs[0x66]; 5688 ex = regs[0x6d] * 256 + regs[0x6c]; 5689 pixels = (ex - sx) / regs[0x7a]; 5690 5691 5692 /* set up initial gains */ 5693 red = 6; 5694 green = 6; 5695 blue = 6; 5696 rts88xx_set_gain (regs, red, green, blue); 5697 5698 /* init loop */ 5699 i = 0; 5700 ra = 0; 5701 ba = 0; 5702 ga = 0; 5703 5704 status = low_cancel (dev->devnum); 5705 if (status != SANE_STATUS_GOOD) 5706 return status; 5707 5708 /* we do a simple scan all 3 averages give the chosen level */ 5709 while (((rts88xx_is_color (regs) 5710 && ((ra < dev->sensor->red_gain_target) 5711 || (ga < dev->sensor->green_gain_target) 5712 || (ba < dev->sensor->blue_gain_target))) 5713 || (!rts88xx_is_color (regs) 5714 && (ga < dev->sensor->gray_gain_target))) && (i < 25)) 5715 { 5716 status = low_simple_scan (dev, regs, sx, pixels, yoffset, lines, &data); 5717 if (status != SANE_STATUS_GOOD) 5718 { 5719 DBG (1, 5720 "sanei_lexmark_low_gain_calibration: low_simple_scan failed!\n"); 5721 if (data != NULL) 5722 free (data); 5723 return status; 5724 } 5725#ifdef DEEP_DEBUG 5726 sprintf (title, "gain%02d.pnm", i); 5727 write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data); 5728#endif 5729 average_area (regs, data, pixels, lines, &ra, &ga, &ba); 5730 free (data); 5731 if (ra < dev->sensor->red_gain_target) 5732 red++; 5733 if (ga < dev->sensor->green_gain_target 5734 || (dev->sensor->gray_gain_target && !rts88xx_is_color (regs))) 5735 green++; 5736 if (ba < dev->sensor->blue_gain_target) 5737 blue++; 5738 rts88xx_set_gain (regs, red, green, blue); 5739 i++; 5740 } 5741 dev->gain.red = red; 5742 dev->gain.green = green; 5743 dev->gain.blue = blue; 5744 dev->gain.gray = green; 5745 DBG (7, 5746 "sanei_lexmark_low_gain_calibration: gain=(0x%02x,0x%02x,0x%02x).\n", 5747 dev->gain.red, dev->gain.green, dev->gain.blue); 5748 DBG (2, "sanei_lexmark_low_gain_calibration: end.\n"); 5749 return status; 5750} 5751 5752/** 5753 * there is no hardware shading correction. So we have to do it in software. 5754 * We do it by scanning a pure white area which is before scanning area. Then 5755 * we compute per pixel coefficient to move the scanned value to the target 5756 * value. These coefficients are used later to correct scanned data. 5757 * The scan is done with all the final scan settings but the height and vertical 5758 * start position. 5759 */ 5760SANE_Status 5761sanei_lexmark_low_shading_calibration (Lexmark_Device * dev) 5762{ 5763 SANE_Byte regs[255]; /* we have our own copy of shadow registers */ 5764 int i, j, pixels, bpl; 5765 int sx, ex; 5766 SANE_Byte *data = NULL; 5767 SANE_Status status; 5768 /* enough 75 dpi lines to "go off" home position dot, 5769 and include shading area */ 5770 int lines = 4 + 4; 5771 int lineoffset = 1; 5772 int linetotal = lines + lineoffset; 5773 int yoffset; 5774 int x, y; 5775 float rtarget, btarget, gtarget; 5776 5777 DBG (2, "sanei_lexmark_low_shading_calibration: start\n"); 5778 /* copy registers */ 5779 for (i = 0; i < 255; i++) 5780 regs[i] = dev->shadow_regs[i]; 5781 5782 /* allocate memory for scan */ 5783 sx = regs[0x67] * 256 + regs[0x66]; 5784 ex = regs[0x6d] * 256 + regs[0x6c]; 5785 5786 5787 DBG (7, "startx=%d, endx=%d, coef=%d, r2f=0x%02x\n", 5788 sx, ex, regs[0x7a], regs[0x2f]); 5789 5790 pixels = (ex - sx) / regs[0x7a]; 5791 if (rts88xx_is_color (regs)) 5792 bpl = 3 * pixels; 5793 else 5794 bpl = pixels; 5795 5796 /* adjust the target area to the scanning resolution */ 5797 lines = (8 * lines) / regs[0x7a]; 5798 lineoffset = (8 * lineoffset) / regs[0x7a]; 5799 linetotal = (8 * linetotal) / regs[0x7a]; 5800 5801 data = (SANE_Byte *) malloc (bpl * lines); 5802 DBG (7, "pixels=%d, lines=%d, size=%d\n", pixels, lines, bpl * lines); 5803 if (data == NULL) 5804 { 5805 DBG (2, 5806 "sanei_lexmark_low_shading_calibration: failed to allocate %d bytes !\n", 5807 bpl * lines); 5808 return SANE_STATUS_NO_MEM; 5809 } 5810 if (dev->shading_coeff != NULL) 5811 free (dev->shading_coeff); 5812 dev->shading_coeff = (float *) malloc (bpl * sizeof (float)); 5813 if (dev->shading_coeff == NULL) 5814 { 5815 DBG (2, 5816 "sanei_lexmark_low_shading_calibration: failed to allocate %d floats !\n", 5817 bpl); 5818 free (data); 5819 return SANE_STATUS_NO_MEM; 5820 } 5821 5822 /* we set movement bit this time */ 5823 regs[0xc3] = regs[0xc3] | 0x80; 5824 5825 /* execute scan */ 5826 status = low_simple_scan (dev, regs, sx, pixels, lineoffset, lines, &data); 5827 if (status != SANE_STATUS_GOOD) 5828 { 5829 DBG (1, 5830 "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n"); 5831 if (data != NULL) 5832 free (data); 5833 return status; 5834 } 5835 5836 yoffset = -1; 5837 /* the very first lines of the scan may include the dark dot used 5838 * locate park position. We find the first line free of it in the scan. 5839 * We can't use is_home_line since it modifies data. 5840 */ 5841 for (y = 0; (y < lines) && (yoffset == y - 1); y++) 5842 { 5843 if (rts88xx_is_color (regs)) 5844 { 5845 for (x = 0; x < 3 * pixels; x++) 5846 { 5847 if (data[x + y * 3 * pixels] < 30) 5848 yoffset = y; 5849 } 5850 } 5851 else 5852 { 5853 for (x = 0; x < pixels; x++) 5854 { 5855 if (data[x + y * pixels] < 30) 5856 yoffset = y; 5857 } 5858 } 5859 } 5860 /* make sure we are really out of the dot */ 5861 yoffset++; 5862 5863 /* yoffset is index of last dot line, go to first white line */ 5864 if (yoffset >= lines - 1) 5865 { 5866 DBG (7, 5867 "sanei_lexmark_low_shading_calibration: failed to detect yoffset.\n"); 5868 /* fail safe fallback, picture will be altered at dot position, 5869 but scanner is safe */ 5870 yoffset = lines - 2; 5871 } 5872 else 5873 yoffset++; 5874 DBG (7, "sanei_lexmark_low_shading_calibration: yoffset=%d.\n", yoffset); 5875 5876#ifdef DEEP_DEBUG 5877 write_pnm_file ("shading.pnm", pixels, lines, rts88xx_is_color (regs), 5878 data); 5879#endif 5880 5881 /* computes coefficients */ 5882 /* there are 8 lines usable for shading calibration at 150 dpi, between 5883 bottom of "home position" dot and the start of the scanner's window 5884 assembly, we only use 7 of them */ 5885 if (yoffset + (8 * 4) / regs[0x7a] < lines) 5886 lines = yoffset + (8 * 4) / regs[0x7a]; 5887 rtarget = dev->sensor->red_shading_target; 5888 gtarget = dev->sensor->green_shading_target; 5889 btarget = dev->sensor->blue_shading_target; 5890 for (i = 0; i < pixels; i++) 5891 { 5892 /* we computes the coefficient needed to move the scanned value to 5893 the target value */ 5894 if (rts88xx_is_color (dev->shadow_regs)) 5895 { 5896 /* RED */ 5897 dev->shading_coeff[i] = 0; 5898 for (j = yoffset; j < lines; j++) 5899 dev->shading_coeff[i] += data[i + j * bpl]; 5900 dev->shading_coeff[i] = 5901 (rtarget / (dev->shading_coeff[i] / (lines - yoffset))); 5902 5903 /* GREEN */ 5904 dev->shading_coeff[i + pixels] = 0; 5905 for (j = yoffset; j < lines; j++) 5906 dev->shading_coeff[i + pixels] += data[i + j * bpl + pixels]; 5907 dev->shading_coeff[i + pixels] = 5908 ((gtarget / dev->shading_coeff[i + pixels]) * (lines - yoffset)); 5909 5910 /* BLUE */ 5911 dev->shading_coeff[i + 2 * pixels] = 0; 5912 for (j = yoffset; j < lines; j++) 5913 dev->shading_coeff[i + 2 * pixels] += 5914 data[i + j * bpl + 2 * pixels]; 5915 dev->shading_coeff[i + 2 * pixels] = 5916 ((btarget / dev->shading_coeff[i + 2 * pixels]) * 5917 (lines - yoffset)); 5918 } 5919 else 5920 { 5921 dev->shading_coeff[i] = 0; 5922 for (j = yoffset; j < lines; j++) 5923 { 5924 dev->shading_coeff[i] += data[i + j * bpl]; 5925 } 5926 dev->shading_coeff[i] = 5927 (rtarget / dev->shading_coeff[i]) * (lines - yoffset); 5928 } 5929 } 5930 free(data); 5931 5932 /* do the scan backward to go back to start position */ 5933 regs[0xc6] &= 0xF7; 5934 lines = (8 * 8) / regs[0x7a]; 5935 /* it should use linetotal to account for the lineoffset */ 5936 if (dev->model.sensor_type == X74_SENSOR) 5937 lines = linetotal; 5938 5939 /* execute scan */ 5940 status = low_simple_scan (dev, regs, sx, pixels, 1, lines, &data); 5941 if (status != SANE_STATUS_GOOD) 5942 { 5943 DBG (1, 5944 "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n"); 5945 if(data!=NULL) 5946 free(data); 5947 return status; 5948 } 5949 5950#ifdef DEEP_DEBUG 5951 write_pnm_file ("shading_bwd.pnm", pixels, lines, rts88xx_is_color (regs), 5952 data); 5953#endif 5954 free (data); 5955 5956 DBG (2, "sanei_lexmark_low_shading_calibration: end.\n"); 5957 return status; 5958} 5959 5960 5961SANE_Status 5962sanei_lexmark_low_calibration (Lexmark_Device * dev) 5963{ 5964 SANE_Status status; 5965 5966 DBG (2, "sanei_lexmark_low_calibration: start.\n"); 5967 status = sanei_lexmark_low_offset_calibration (dev); 5968 if (status != SANE_STATUS_GOOD) 5969 return status; 5970 5971 /* we put the offset just computed in scanning regs */ 5972 if (rts88xx_is_color (dev->shadow_regs)) 5973 { 5974 rts88xx_set_offset (dev->shadow_regs, 5975 dev->offset.red, 5976 dev->offset.green, dev->offset.blue); 5977 } 5978 else 5979 { 5980 rts88xx_set_offset (dev->shadow_regs, 5981 dev->offset.gray, 5982 dev->offset.gray, dev->offset.gray); 5983 } 5984 5985 /* if manual gain settings, no gain calibration */ 5986 if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) 5987 { 5988 if (rts88xx_is_color (dev->shadow_regs)) 5989 { 5990 dev->gain.red = dev->val[OPT_RED_GAIN].w; 5991 dev->gain.green = dev->val[OPT_GREEN_GAIN].w; 5992 dev->gain.blue = dev->val[OPT_BLUE_GAIN].w; 5993 } 5994 else 5995 dev->gain.gray = dev->val[OPT_GRAY_GAIN].w; 5996 } 5997 else 5998 { 5999 status = sanei_lexmark_low_gain_calibration (dev); 6000 if (status != SANE_STATUS_GOOD) 6001 return status; 6002 } 6003 6004 /* put the calibrated or manual settings before shading calibration 6005 which must be done with final setting values */ 6006 if (rts88xx_is_color (dev->shadow_regs)) 6007 { 6008 rts88xx_set_gain (dev->shadow_regs, dev->gain.red, dev->gain.green, 6009 dev->gain.blue); 6010 } 6011 else 6012 { 6013 rts88xx_set_gain (dev->shadow_regs, dev->gain.gray, dev->gain.gray, 6014 dev->gain.gray); 6015 } 6016 6017 status = sanei_lexmark_low_shading_calibration (dev); 6018 6019 if (status != SANE_STATUS_GOOD) 6020 return status; 6021 6022 DBG (2, "sanei_lexmark_low_calibration: end.\n"); 6023 return SANE_STATUS_GOOD; 6024} 6025 6026/* assign sensor data */ 6027static SANE_Status 6028sanei_lexmark_low_assign_sensor (Lexmark_Device * dev) 6029{ 6030 int dn; 6031 6032 /* init sensor data */ 6033 dn = 0; 6034 while (sensor_list[dn].id != 0 6035 && sensor_list[dn].id != dev->model.sensor_type) 6036 dn++; 6037 if (sensor_list[dn].id == 0) 6038 { 6039 DBG (1, 6040 "sanei_lexmark_low_assign_sensor: unknown sensor %d\n", 6041 dev->model.sensor_type); 6042 return SANE_STATUS_UNSUPPORTED; 6043 } 6044 dev->sensor = &(sensor_list[dn]); 6045 DBG (1, "sanei_lexmark_low_assign_sensor: assigned sensor number %d\n", 6046 dev->model.sensor_type); 6047 return SANE_STATUS_GOOD; 6048} 6049 6050/* assign model description, based on USB id, and register content when 6051 * available */ 6052SANE_Status 6053sanei_lexmark_low_assign_model (Lexmark_Device * dev, 6054 SANE_String_Const devname, SANE_Int vendor, 6055 SANE_Int product, SANE_Byte mainboard) 6056{ 6057 int dn; 6058 SANE_Bool found = SANE_FALSE; 6059 6060 DBG_INIT (); 6061 6062 DBG (2, "sanei_lexmark_low_assign_model: start\n"); 6063 DBG (3, 6064 "sanei_lexmark_low_assign_model: assigning %04x:%04x, variant %d\n", 6065 vendor, product, mainboard); 6066 6067 dn = 0; 6068 /* walk the list of known devices */ 6069 while (!found && model_list[dn].vendor_id != 0) 6070 { 6071 /* no mainboard id given (at attach time) */ 6072 if (mainboard == 0 6073 && vendor == model_list[dn].vendor_id 6074 && product == model_list[dn].product_id) 6075 found = SANE_TRUE; 6076 /* mainboard given (init time) */ 6077 if (mainboard != 0 6078 && mainboard == model_list[dn].mainboard_id 6079 && vendor == model_list[dn].vendor_id 6080 && product == model_list[dn].product_id) 6081 found = SANE_TRUE; 6082 6083 if (!found) 6084 dn++; 6085 } 6086 6087 /* we hit the end of list, so we don't know about the current model */ 6088 if (!found) 6089 { 6090 DBG (1, 6091 "sanei_lexmark_low_assign_model: unknown device 0x%04x:0x%04x\n", 6092 vendor, product); 6093 return SANE_STATUS_UNSUPPORTED; 6094 } 6095 6096 dev->sane.name = strdup (devname); 6097 dev->sane.vendor = model_list[dn].vendor; 6098 dev->sane.model = model_list[dn].model; 6099 dev->model = model_list[dn]; 6100 dev->sane.type = "flatbed scanner"; 6101 6102 DBG (3, "sanei_lexmark_low_assign_model: assigned %s\n", dev->model.model); 6103 6104 /* init sensor data */ 6105 DBG (2, "sanei_lexmark_low_assign_model: end.\n"); 6106 return sanei_lexmark_low_assign_sensor (dev); 6107} 6108