1/* sane - Scanner Access Now Easy. 2 Copyright (C) 1999,2000 Tom Martone 3 This file is part of a SANE backend for Bell and Howell Copiscan II 4 Scanners using the Remote SCSI Controller(RSC). 5 6 This file is part of the SANE package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <https://www.gnu.org/licenses/>. 20 21 As a special exception, the authors of SANE give permission for 22 additional uses of the libraries contained in this release of SANE. 23 24 The exception is that, if you link a SANE library with other files 25 to produce an executable, this does not by itself cause the 26 resulting executable to be covered by the GNU General Public 27 License. Your use of that executable is in no way restricted on 28 account of linking the SANE library code into it. 29 30 This exception does not, however, invalidate any other reasons why 31 the executable file might be covered by the GNU General Public 32 License. 33 34 If you submit changes to SANE to the maintainers to be included in 35 a subsequent release, you agree by submitting the changes that 36 those changes may be distributed with this exception intact. 37 38 If you write modifications of your own for SANE, it is your choice 39 whether to permit this exception to apply to your modifications. 40 If you do not wish that, delete this exception notice. 41 42*/ 43#include "../include/sane/config.h" 44#include <limits.h> 45#include <errno.h> 46#include <fcntl.h> 47#include <ctype.h> 48#include <stdlib.h> 49#include <string.h> 50#include <stdio.h> 51#include <unistd.h> 52#include <sys/types.h> 53#include "../include/sane/sane.h" 54#include "../include/sane/saneopts.h" 55#include "../include/sane/sanei_scsi.h" 56#include "../include/sane/sanei_config.h" 57 58#define BACKEND_NAME bh 59#include "../include/sane/sanei_backend.h" 60#define BUILD 4 61 62#include "bh.h" 63 64#define MIN(x,y) ((x)<(y) ? (x) : (y)) 65#define MAX(x,y) ((x)>(y) ? (x) : (y)) 66 67static const SANE_Device **devlist = 0; 68static int num_devices = 0; 69static BH_Device *first_dev = NULL; 70static BH_Scanner *first_handle = NULL; 71static SANE_Char inquiry_data[255] = "Bell+Howell scanner"; 72static SANE_Int disable_optional_frames = 0; 73static SANE_Int fake_inquiry = 0; 74 75static int allblank(const char *s) 76{ 77 while (s && *s) 78 if (!isspace(*s++)) 79 return 0; 80 81 return 1; 82} 83 84static size_t 85max_string_size (const SANE_String_Const strings[]) 86{ 87 size_t size, max_size = 0; 88 int i; 89 90 for (i = 0; strings[i]; ++i) 91 { 92 size = strlen (strings[i]) + 1; 93 if (size > max_size) 94 max_size = size; 95 } 96 97 return max_size; 98} 99 100static void 101trim_spaces(char *s, size_t n) 102{ 103 for (s += (n-1); n > 0; n--, s--) 104 { 105 if (*s && !isspace(*s)) 106 break; 107 *s = '\0'; 108 } 109} 110 111static SANE_String_Const 112print_devtype (SANE_Byte devtype) 113{ 114 static SANE_String devtypes[] = 115 { 116 "disk", 117 "tape", 118 "printer", 119 "processor", 120 "CD-writer", 121 "CD-drive", 122 "scanner", 123 "optical-drive", 124 "jukebox", 125 "communicator" 126 }; 127 128 return (devtype > 0 && devtype < NELEMS(devtypes)) ? 129 devtypes[devtype] : 130 "unknown-device"; 131} 132 133static SANE_String_Const 134print_barcodetype (SANE_Int i) 135{ 136 return (i > 0 && i < NELEMS(barcode_search_bar_list)) ? 137 barcode_search_bar_list[i] : 138 (SANE_String_Const) "unknown"; 139} 140 141static SANE_String_Const 142print_orientation (SANE_Int i) 143{ 144 switch(i) 145 { 146 case 0: 147 case 7: 148 return "vertical upwards"; 149 case 1: 150 case 2: 151 return "horizontal right"; 152 case 3: 153 case 4: 154 return "vertical downwards"; 155 case 5: 156 case 6: 157 return "horizontal left"; 158 default: 159 return "unknown"; 160 } 161} 162 163static SANE_String_Const 164print_read_type (SANE_Int i) 165{ 166 static char buf[32]; 167 SANE_Int n; 168 169 /* translate BH_SCSI_READ_TYPE_ codes to a human-readable string */ 170 if (i == BH_SCSI_READ_TYPE_FRONT) 171 { 172 strcpy(buf, "front page"); 173 } 174 else if (i == BH_SCSI_READ_TYPE_BACK) 175 { 176 strcpy(buf, "back page"); 177 } 178 else if (i > BH_SCSI_READ_TYPE_FRONT && 179 i <= BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS) 180 { 181 n = i - BH_SCSI_READ_TYPE_FRONT; 182 sprintf(buf, "front section %d", n); 183 } 184 else if (i > BH_SCSI_READ_TYPE_BACK && 185 i <= BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS) 186 { 187 n = i - BH_SCSI_READ_TYPE_BACK; 188 sprintf(buf, "back section %d", n); 189 } 190 else if (i == BH_SCSI_READ_TYPE_FRONT_BARCODE) 191 { 192 strcpy(buf, "front page barcode"); 193 } 194 else if (i == BH_SCSI_READ_TYPE_BACK_BARCODE) 195 { 196 strcpy(buf, "back page barcode"); 197 } 198 else if (i > BH_SCSI_READ_TYPE_FRONT_BARCODE && 199 i <= BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS) 200 { 201 n = i - BH_SCSI_READ_TYPE_FRONT_BARCODE; 202 sprintf(buf, "front barcode section %d", n); 203 } 204 else if (i > BH_SCSI_READ_TYPE_BACK_BARCODE && 205 i <= BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS) 206 { 207 n = i - BH_SCSI_READ_TYPE_BACK_BARCODE; 208 sprintf(buf, "back barcode section %d", n); 209 } 210 else if (i == BH_SCSI_READ_TYPE_FRONT_PATCHCODE) 211 { 212 strcpy(buf, "front page patchcode"); 213 } 214 else if (i == BH_SCSI_READ_TYPE_BACK_PATCHCODE) 215 { 216 strcpy(buf, "back page patchcode"); 217 } 218 else if (i > BH_SCSI_READ_TYPE_FRONT_PATCHCODE && 219 i <= BH_SCSI_READ_TYPE_FRONT_PATCHCODE + NUM_SECTIONS) 220 { 221 n = i - BH_SCSI_READ_TYPE_FRONT_PATCHCODE; 222 sprintf(buf, "front patchcode section %d", n); 223 } 224 else if (i > BH_SCSI_READ_TYPE_BACK_PATCHCODE && 225 i <= BH_SCSI_READ_TYPE_BACK_PATCHCODE + NUM_SECTIONS) 226 { 227 n = i - BH_SCSI_READ_TYPE_BACK_PATCHCODE; 228 sprintf(buf, "back patchcode section %d", n); 229 } 230 else if (i == BH_SCSI_READ_TYPE_FRONT_ICON) 231 { 232 strcpy(buf, "front page icon"); 233 } 234 else if (i == BH_SCSI_READ_TYPE_BACK_ICON) 235 { 236 strcpy(buf, "back page icon"); 237 } 238 else if (i == BH_SCSI_READ_TYPE_SENDBARFILE) 239 { 240 strcpy(buf, "transmit bar/patch codes"); 241 } 242 else 243 { 244 strcpy(buf, "unknown"); 245 } 246 247 return buf; 248} 249 250static SANE_Int 251get_rotation_id(char *s) 252{ 253 SANE_Int i; 254 255 for (i = 0; rotation_list[i]; i++) 256 if (strcmp(s, rotation_list[i]) == 0) 257 break; 258 259 /* unknown strings are treated as '0' */ 260 return rotation_list[i] ? i : 0; 261} 262 263static SANE_Int 264get_compression_id(char *s) 265{ 266 SANE_Int i; 267 268 for (i = 0; compression_list[i]; i++) 269 if (strcmp(s, compression_list[i]) == 0) 270 break; 271 272 /* unknown strings are treated as 'none' */ 273 return compression_list[i] ? i : 0; 274} 275 276static SANE_Int 277get_barcode_id(char *s) 278{ 279 SANE_Int i; 280 281 for (i = 0; barcode_search_bar_list[i]; i++) 282 if (strcmp(s, barcode_search_bar_list[i]) == 0) 283 break; 284 285 /* unknown strings are treated as 'none' */ 286 return barcode_search_bar_list[i] ? i : 0; 287} 288 289static SANE_Int 290get_scan_mode_id(char *s) 291{ 292 SANE_Int i; 293 294 for (i = 0; scan_mode_list[i]; i++) 295 if (strcmp(s, scan_mode_list[i]) == 0) 296 break; 297 298 /* unknown strings are treated as 'lineart' */ 299 return scan_mode_list[i] ? i : 0; 300} 301 302static SANE_Int 303get_paper_id(char *s) 304{ 305 SANE_Int i; 306 307 for (i = 0; paper_list[i]; i++) 308 if (strcmp(s, paper_list[i]) == 0) 309 break; 310 311 /* unknown strings are treated as 'custom' */ 312 return paper_list[i] ? i : 0; 313} 314 315static SANE_Int 316get_barcode_search_mode(char *s) 317{ 318 SANE_Int i; 319 320 if (strcmp(s, "horizontal") == 0) 321 { 322 i = 1; 323 } 324 else if (strcmp(s, "vertical") == 0) 325 { 326 i = 2; 327 } 328 else if (strcmp(s, "vert-horiz") == 0) 329 { 330 i = 6; 331 } 332 else if (strcmp(s, "horiz-vert") == 0) 333 { 334 i = 9; 335 } 336 else 337 { 338 /* unknown strings are treated as 'horiz-vert' */ 339 DBG(1, "get_barcode_search_mode: unrecognized string `%s'\n", s); 340 i = 9; 341 } 342 343 return i; 344} 345 346static void 347appendStdList(BH_Info *sc, SANE_Int res) 348{ 349 /* append entry to resolution list - a SANE_WORD_LIST */ 350 sc->resStdList[sc->resStdList[0]+1] = res; 351 sc->resStdList[0]++; 352} 353 354static void 355ScannerDump(BH_Scanner *s) 356{ 357 int i; 358 BH_Info *info; 359 SANE_Device *sdev; 360 361 info = &s->hw->info; 362 sdev = &s->hw->sane; 363 364 DBG (1, "SANE Device: '%s' Vendor: '%s' Model: '%s' Type: '%s'\n", 365 sdev->name, 366 sdev->vendor, 367 sdev->model, 368 sdev->type); 369 370 DBG (1, "Type: '%s' Vendor: '%s' Product: '%s' Revision: '%s'\n", 371 print_devtype(info->devtype), 372 info->vendor, 373 info->product, 374 info->revision); 375 376 DBG (1, "Automatic Document Feeder:%s\n", 377 info->canADF ? " <Installed>" : " <Not Installed>"); 378 379 DBG (1, "Colors:%s%s\n", info->colorBandW ? " <Black and White>" : "", 380 info->colorHalftone ? " <Halftone>" : ""); 381 382 DBG (1, "Data processing:%s%s%s%s%s%s\n", 383 info->canWhiteFrame ? " <White Frame>" : "", 384 info->canBlackFrame ? " <Black Frame>" : "", 385 info->canEdgeExtract ? " <Edge Extraction>" : "", 386 info->canNoiseFilter ? " <Noise Filter>" : "", 387 info->canSmooth ? " <Smooth>" : "", 388 info->canLineBold ? " <Line Bolding>" : ""); 389 390 DBG (1, "Compression:%s%s%s\n", 391 info->comprG3_1D ? " <Group 3, 1D>" : "", 392 info->comprG3_2D ? " <Group 3, 2D>" : "", 393 info->comprG4 ? " <Group 4>" : ""); 394 395 DBG (1, "Optional Features:%s%s%s%s\n", 396 info->canBorderRecog ? " <Border Recognition>" : "", 397 info->canBarCode ? " <BarCode Decoding>" : "", 398 info->canIcon ? " <Icon Generation>" : "", 399 info->canSection ? " <Section Support>" : ""); 400 401 DBG (1, "Max bytes per scan-line: %d (%d pixels)\n", 402 info->lineMaxBytes, 403 info->lineMaxBytes * 8); 404 405 DBG (1, "Basic resolution (X/Y): %d/%d\n", 406 info->resBasicX, 407 info->resBasicY); 408 409 DBG (1, "Maximum resolution (X/Y): %d/%d\n", 410 info->resMaxX, 411 info->resMaxY); 412 413 DBG (1, "Minimum resolution (X/Y): %d/%d\n", 414 info->resMinX, 415 info->resMinY); 416 417 DBG (1, "Standard Resolutions:\n"); 418 for (i = 0; i < info->resStdList[0]; i++) 419 DBG (1, " %d\n", info->resStdList[i+1]); 420 421 DBG (1, "Window Width/Height (in basic res) %d/%d (%.2f/%.2f inches)\n", 422 info->winWidth, 423 info->winHeight, 424 (info->resBasicX != 0) ? ((float) info->winWidth) / info->resBasicX : 0.0, 425 (info->resBasicY) ? ((float) info->winHeight) / info->resBasicY : 0.0); 426 427 DBG (1, "Summary:%s%s%s\n", 428 info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", 429 info->canACE ? " (ACE capable)" : "", 430 info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); 431 432 sprintf(inquiry_data, "Vendor: %s Product: %s Rev: %s %s%s%s\n", 433 info->vendor, 434 info->product, 435 info->revision, 436 info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", 437 info->canACE ? " (ACE capable)" : "", 438 info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); 439 440 DBG (5, "autoborder_default=%d\n", info->autoborder_default); 441 DBG (5, "batch_default=%d\n", info->batch_default); 442 DBG (5, "deskew_default=%d\n", info->deskew_default); 443 DBG (5, "check_adf_default=%d\n", info->check_adf_default); 444 DBG (5, "duplex_default=%d\n", info->duplex_default); 445 DBG (5, "timeout_adf_default=%d\n", info->timeout_adf_default); 446 DBG (5, "timeout_manual_default=%d\n", info->timeout_manual_default); 447 DBG (5, "control_panel_default=%d\n", info->control_panel_default); 448 449} 450 451static SANE_Status 452test_unit_ready (int fd) 453{ 454 static SANE_Byte cmd[6]; 455 SANE_Status status; 456 DBG (3, "test_unit_ready called\n"); 457 458 cmd[0] = BH_SCSI_TEST_UNIT_READY; 459 memset (cmd, 0, sizeof (cmd)); 460 status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 461 462 return status; 463} 464 465static SANE_Status 466object_position (BH_Scanner *s) 467{ 468 static SANE_Byte cmd[10]; 469 SANE_Status status; 470 DBG (3, "object_position called\n"); 471 472 memset (cmd, 0, sizeof (cmd)); 473 cmd[0] = BH_SCSI_OBJECT_POSITION; 474 cmd[1] = 0x01; 475 status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); 476 477 return status; 478} 479 480static SANE_Status 481read_barcode_data (BH_Scanner *s, FILE *fp) 482{ 483 static SANE_Byte cmd[10]; 484 SANE_Status status; 485 SANE_Int num_found = 0; 486 double w, l, x, y, res; 487 struct barcode_data buf; 488 size_t buf_size = sizeof(buf); 489 DBG (3, "read_barcode_data called\n"); 490 491 memset (&cmd, 0, sizeof (cmd)); 492 cmd[0] = BH_SCSI_READ_SCANNED_DATA; 493 cmd[2] = s->readlist[s->readptr]; 494 _lto3b(buf_size, &cmd[6]); /* transfer length */ 495 496 s->barcode_not_found = SANE_FALSE; 497 do { 498 memset (&buf, 0, sizeof(buf)); 499 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); 500 if (status != SANE_STATUS_GOOD) 501 break; 502 if (s->barcode_not_found == SANE_TRUE) 503 break; 504 505 num_found++; 506 507 buf.barcodedata[sizeof(buf.barcodedata)-1] = '\0'; 508 509 /* calculate the bounding rectangle */ 510 x = MIN((int) _2btol(buf.posxb), (int) _2btol(buf.posxa)); 511 y = MIN((int) _2btol(buf.posyb), (int) _2btol(buf.posyd)); 512 w = MAX((int) _2btol(buf.posxd), (int) _2btol(buf.posxd)) - x; 513 l = MAX((int) _2btol(buf.posya), (int) _2btol(buf.posyc)) - y; 514 /* convert from pixels to mm */ 515 res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 516 if (res <= 0.0) 517 { 518 /* avoid divide by zero */ 519 DBG(1, "read_barcode_data: warning: " 520 "encountered bad resolution value '%f', replacing with '%f'\n", 521 res, 200.0); 522 res = 200.0; 523 } 524 x = x * MM_PER_INCH / res; 525 y = y * MM_PER_INCH / res; 526 w = w * MM_PER_INCH / res; 527 l = l * MM_PER_INCH / res; 528 /* add a bit of a border around the edges */ 529 x = MAX(0.0, x - BH_DECODE_FUDGE); 530 y = MAX(0.0, y - BH_DECODE_FUDGE); 531 w += (BH_DECODE_FUDGE * 4); 532 l += (BH_DECODE_FUDGE * 4); 533 534 /* write the decoded barcode data into the file */ 535 fprintf(fp, "<barcode>\n <section>%s</section>\n", 536 print_read_type((int) s->readlist[s->readptr])); 537 fprintf(fp, " <type>%s</type>\n <status-flag>%d</status-flag>\n", 538 print_barcodetype((int) _2btol(buf.barcodetype)), 539 (int) _2btol(buf.statusflag)); 540 fprintf(fp, " <orientation>%s</orientation>\n", 541 print_orientation((int) _2btol(buf.barcodeorientation))); 542 fprintf(fp, " <location>\n <tl><x>%d</x><y>%d</y></tl>\n", 543 (int) _2btol(buf.posxb), (int) _2btol(buf.posyb)); 544 fprintf(fp, " <tr><x>%d</x><y>%d</y></tr>\n", 545 (int) _2btol(buf.posxd), (int) _2btol(buf.posyd)); 546 fprintf(fp, " <bl><x>%d</x><y>%d</y></bl>\n", 547 (int) _2btol(buf.posxa), (int) _2btol(buf.posya)); 548 fprintf(fp, " <br><x>%d</x><y>%d</y></br>\n </location>\n", 549 (int) _2btol(buf.posxc), (int) _2btol(buf.posyc)); 550 fprintf(fp, " <rectangle>%.2fx%.2f+%.2f+%.2f</rectangle>\n", 551 w, l, x, y); 552 fprintf(fp, " <search-time>%d</search-time>\n <length>%d</length>\n", 553 (int) _2btol(buf.barcodesearchtime), 554 (int) buf.barcodelen); 555 fprintf(fp, " <data>%s</data>\n</barcode>\n", 556 buf.barcodedata); 557 } while (num_found <= BH_DECODE_TRIES); 558 559 DBG (3, "read_barcode_data: found %d barcodes, returning %s\n", 560 num_found, sane_strstatus(status)); 561 562 return status; 563} 564 565static SANE_Status 566read_icon_data (BH_Scanner *s) 567{ 568 static SANE_Byte cmd[10]; 569 SANE_Status status; 570 struct icon_data buf; 571 size_t buf_size = sizeof(buf); 572 DBG (3, "read_icon_data called\n"); 573 574 memset (&cmd, 0, sizeof (cmd)); 575 cmd[0] = BH_SCSI_READ_SCANNED_DATA; 576 cmd[2] = s->readlist[s->readptr]; 577 _lto3b(buf_size, &cmd[6]); /* transfer length */ 578 579 memset (&buf, 0, sizeof(buf)); 580 581 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); 582 583 /* set the fields in the scanner handle for later reference */ 584 s->iconwidth = _4btol(buf.iconwidth); 585 s->iconlength = _4btol(buf.iconlength); 586 587 DBG(3, "read_icon_data: windowwidth:%lu, windowlength:%lu\n", 588 _4btol(buf.windowwidth), 589 _4btol(buf.windowlength)); 590 DBG(3, "read_icon_data: iconwidth:%lu, iconlength:%lu, iconwidth(bytes):%lu\n", 591 _4btol(buf.iconwidth), 592 _4btol(buf.iconlength), 593 _4btol(buf.iconwidthbytes)); 594 DBG(3, "read_icon_data: bitordering:%02x, icondatalen:%lu\n", 595 buf.bitordering, 596 _4btol(buf.icondatalen)); 597 598 DBG (3, "read_icon_data returning %d\n", status); 599 600 return status; 601} 602 603static SANE_Status 604read_barfile (BH_Scanner *s, void *buf, size_t *buf_size) 605{ 606 SANE_Status status = SANE_STATUS_GOOD; 607 size_t nread; 608 DBG (3, "read_barfile called (%lu bytes)\n", (u_long) *buf_size); 609 610 if (s->barf != NULL) 611 { 612 /* this function needs to set InvalidBytes so it looks 613 * like a B&H scsi EOF 614 */ 615 if ((nread = fread(buf, 1, *buf_size, s->barf)) < *buf_size) 616 { 617 /* set InvalidBytes */ 618 s->InvalidBytes = *buf_size - nread; 619 620 if (ferror(s->barf)) 621 { 622 status = SANE_STATUS_IO_ERROR; 623 fclose(s->barf); 624 s->barf = NULL; 625 unlink(s->barfname); 626 } 627 else if (feof(s->barf)) 628 { 629 /* it also needs to close the file and delete it when EOF is 630 * reached. 631 */ 632 fclose(s->barf); 633 s->barf = NULL; 634 unlink(s->barfname); 635 } 636 } 637 } 638 else 639 { 640 /* set InvalidBytes */ 641 s->InvalidBytes = *buf_size; 642 } 643 644 return status; 645} 646 647static SANE_Status 648read_data (BH_Scanner *s, void *buf, size_t *buf_size) 649{ 650 static SANE_Byte cmd[10]; 651 SANE_Status status; 652 DBG (3, "read_data called (%lu bytes)\n", (u_long) *buf_size); 653 654 if (s->readlist[s->readptr] == BH_SCSI_READ_TYPE_SENDBARFILE) 655 { 656 /* call special barcode data read function. */ 657 status = read_barfile(s, buf, buf_size); 658 } 659 else 660 { 661 memset (&cmd, 0, sizeof (cmd)); 662 cmd[0] = BH_SCSI_READ_SCANNED_DATA; 663 cmd[2] = s->readlist[s->readptr]; 664 _lto3b(*buf_size, &cmd[6]); /* transfer length */ 665 666 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, buf_size); 667 } 668 669 return status; 670} 671 672static SANE_Status 673mode_select_measurement (BH_Scanner *s) 674{ 675 static struct { 676 SANE_Byte cmd[6]; 677 struct mode_page_03 mp; 678 } select_cmd; 679 SANE_Status status; 680 681 DBG (3, "mode_select_measurement called (bmu:%d mud:%d)\n", 682 s->bmu, s->mud); 683 684 memset (&select_cmd, 0, sizeof (select_cmd)); 685 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 686 select_cmd.cmd[1] = 0x10; 687 select_cmd.cmd[4] = sizeof(select_cmd.mp); 688 689 select_cmd.mp.pagecode = BH_MODE_MEASUREMENT_PAGE_CODE; 690 select_cmd.mp.paramlen = 0x06; 691 select_cmd.mp.bmu = s->bmu; 692 _lto2b(s->mud, select_cmd.mp.mud); 693 694 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 695 696 return status; 697} 698 699static SANE_Status 700mode_select_timeout (BH_Scanner *s) 701{ 702 static struct { 703 SANE_Byte cmd[6]; 704 struct mode_page_20 mp; 705 } select_cmd; 706 SANE_Status status; 707 708 DBG (3, "mode_select_timeout called\n"); 709 710 memset (&select_cmd, 0, sizeof (select_cmd)); 711 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 712 select_cmd.cmd[1] = 0x10; 713 select_cmd.cmd[4] = sizeof(select_cmd.mp); 714 715 select_cmd.mp.pagecode = BH_MODE_TIMEOUT_PAGE_CODE; 716 select_cmd.mp.paramlen = 0x06; 717 select_cmd.mp.timeoutmanual = _OPT_VAL_WORD(s, OPT_TIMEOUT_MANUAL); 718 select_cmd.mp.timeoutadf = _OPT_VAL_WORD(s, OPT_TIMEOUT_ADF); 719 720 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 721 722 return status; 723} 724 725static SANE_Status 726mode_select_icon (BH_Scanner *s) 727{ 728 static struct { 729 SANE_Byte cmd[6]; 730 struct mode_page_21 mp; 731 } select_cmd; 732 SANE_Status status; 733 734 DBG (3, "mode_select_icon called\n"); 735 736 memset (&select_cmd, 0, sizeof (select_cmd)); 737 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 738 select_cmd.cmd[1] = 0x10; 739 select_cmd.cmd[4] = sizeof(select_cmd.mp); 740 741 select_cmd.mp.pagecode = BH_MODE_ICON_PAGE_CODE; 742 select_cmd.mp.paramlen = 0x06; 743 _lto2b(_OPT_VAL_WORD(s, OPT_ICON_WIDTH), select_cmd.mp.iconwidth); 744 _lto2b(_OPT_VAL_WORD(s, OPT_ICON_LENGTH), select_cmd.mp.iconlength); 745 746 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 747 748 return status; 749} 750 751static SANE_Status 752mode_select_barcode_priority (BH_Scanner *s) 753{ 754 static struct { 755 SANE_Byte cmd[6]; 756 struct mode_page_30 mp; 757 } select_cmd; 758 SANE_Status status; 759 int i; 760 761 DBG (3, "mode_select_barcode_priority called\n"); 762 763 memset (&select_cmd, 0, sizeof (select_cmd)); 764 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 765 select_cmd.cmd[1] = 0x10; 766 select_cmd.cmd[4] = sizeof(select_cmd.mp); 767 768 select_cmd.mp.pagecode = BH_MODE_BARCODE_PRIORITY_PAGE_CODE; 769 select_cmd.mp.paramlen = 0x06; 770 771 for (i = 0; i < NUM_SEARCH_BARS; i++) 772 { 773 /* anything after a 'none' is ignored */ 774 if ((select_cmd.mp.priority[i] = s->search_bars[i]) == 0) break; 775 } 776 777 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 778 779 return status; 780} 781 782static SANE_Status 783mode_select_barcode_param1 (BH_Scanner *s) 784{ 785 static struct { 786 SANE_Byte cmd[6]; 787 struct mode_page_31 mp; 788 } select_cmd; 789 SANE_Status status; 790 791 DBG (3, "mode_select_barcode_param1 called\n"); 792 793 memset (&select_cmd, 0, sizeof (select_cmd)); 794 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 795 select_cmd.cmd[1] = 0x10; 796 select_cmd.cmd[4] = sizeof(select_cmd.mp); 797 798 select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM1_PAGE_CODE; 799 select_cmd.mp.paramlen = 0x06; 800 801 _lto2b((SANE_Int)_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BARCODE_HMIN), select_cmd.mp.minbarheight); 802 select_cmd.mp.searchcount = _OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_COUNT); 803 select_cmd.mp.searchmode = 804 get_barcode_search_mode(_OPT_VAL_STRING(s, OPT_BARCODE_SEARCH_MODE)); 805 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_TIMEOUT), select_cmd.mp.searchtimeout); 806 807 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 808 809 return status; 810} 811 812static SANE_Status 813mode_select_barcode_param2 (BH_Scanner *s) 814{ 815 static struct { 816 SANE_Byte cmd[6]; 817 struct mode_page_32 mp; 818 } select_cmd; 819 SANE_Status status; 820 size_t len; 821 822 DBG (3, "mode_select_barcode_param2 called\n"); 823 824 /* first we'll do a mode sense, then we'll overwrite with 825 * our new values, and then do a mode select 826 */ 827 memset (&select_cmd, 0, sizeof (select_cmd)); 828 select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; 829 select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM2_PAGE_CODE; 830 select_cmd.cmd[4] = sizeof(select_cmd.mp); 831 832 len = sizeof(select_cmd.mp); 833 status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), 834 &select_cmd.mp, &len); 835 836 if (status == SANE_STATUS_GOOD) 837 { 838 DBG(8, "mode_select_barcode_param2: sensed values: relmax:%d barmin:%d barmax:%d\n", 839 (int) _2btol(select_cmd.mp.relmax), 840 (int) _2btol(select_cmd.mp.barmin), 841 (int) _2btol(select_cmd.mp.barmax)); 842 843 memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); 844 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 845 select_cmd.cmd[1] = 0x10; 846 select_cmd.cmd[4] = sizeof(select_cmd.mp); 847 848 select_cmd.mp.modedatalen = 0x00; 849 select_cmd.mp.mediumtype = 0x00; 850 select_cmd.mp.devicespecificparam = 0x00; 851 select_cmd.mp.blockdescriptorlen = 0x00; 852 853 select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM2_PAGE_CODE; 854 select_cmd.mp.paramlen = 0x06; 855 856 /* only overwrite the default values if the option is non-zero */ 857 if (_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX) != 0) 858 { 859 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), select_cmd.mp.relmax); 860 } 861 if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN) != 0) 862 { 863 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), select_cmd.mp.barmin); 864 } 865 if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX) != 0) 866 { 867 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX), select_cmd.mp.barmax); 868 } 869 870 DBG(8, "mode_select_barcode_param2: param values: relmax:%d barmin:%d barmax:%d\n", 871 (int) _OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), 872 (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), 873 (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMAX)); 874 875 DBG(8, "mode_select_barcode_param2: select values: relmax:%d barmin:%d barmax:%d\n", 876 (int) _2btol(select_cmd.mp.relmax), 877 (int) _2btol(select_cmd.mp.barmin), 878 (int) _2btol(select_cmd.mp.barmax)); 879 880 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 881 } 882 883 return status; 884} 885 886static SANE_Status 887mode_select_barcode_param3 (BH_Scanner *s) 888{ 889 static struct { 890 SANE_Byte cmd[6]; 891 struct mode_page_33 mp; 892 } select_cmd; 893 SANE_Status status; 894 size_t len; 895 896 DBG (3, "mode_select_barcode_param3 called\n"); 897 898 /* first we'll do a mode sense, then we'll overwrite with 899 * our new values, and then do a mode select 900 */ 901 memset (&select_cmd, 0, sizeof (select_cmd)); 902 select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; 903 select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM3_PAGE_CODE; 904 select_cmd.cmd[4] = sizeof(select_cmd.mp); 905 906 len = sizeof(select_cmd.mp); 907 status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), 908 &select_cmd.mp, &len); 909 910 if (status == SANE_STATUS_GOOD) 911 { 912 DBG(8, "mode_select_barcode_param3: sensed values: contrast:%d patchmode:%d\n", 913 (int) _2btol(select_cmd.mp.barcodecontrast), 914 (int) _2btol(select_cmd.mp.patchmode)); 915 916 memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); 917 select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; 918 select_cmd.cmd[1] = 0x10; 919 select_cmd.cmd[4] = sizeof(select_cmd.mp); 920 921 select_cmd.mp.modedatalen = 0x00; 922 select_cmd.mp.mediumtype = 0x00; 923 select_cmd.mp.devicespecificparam = 0x00; 924 select_cmd.mp.blockdescriptorlen = 0x00; 925 926 select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM3_PAGE_CODE; 927 select_cmd.mp.paramlen = 0x06; 928 929 /* only overwrite the default values if the option is non-zero */ 930 if (_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST) != 0) 931 { 932 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), select_cmd.mp.barcodecontrast); 933 } 934 if (_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE) != 0) 935 { 936 _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE), select_cmd.mp.patchmode); 937 } 938 939 DBG(8, "mode_select_barcode_param3: param values: contrast:%d patchmode:%d\n", 940 (int) _OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), 941 (int) _OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE)); 942 943 DBG(8, "mode_select_barcode_param3: select values: contrast:%d patchmode:%d\n", 944 (int) _2btol(select_cmd.mp.barcodecontrast), 945 (int) _2btol(select_cmd.mp.patchmode)); 946 947 status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); 948 } 949 950 return status; 951} 952 953static SANE_Status 954inquiry (int fd, void *buf, size_t *buf_size, SANE_Byte evpd, SANE_Byte page_code) 955{ 956 static SANE_Byte cmd[6]; 957 SANE_Status status; 958 DBG (3, "inquiry called\n"); 959 960 memset (cmd, 0, sizeof (cmd)); 961 cmd[0] = BH_SCSI_INQUIRY; 962 cmd[1] = evpd; 963 cmd[2] = page_code; 964 cmd[4] = *buf_size; 965 966 status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); 967 968 return status; 969} 970 971static SANE_Status 972set_window (BH_Scanner *s, SANE_Byte batchmode) 973{ 974 static struct { 975 SANE_Byte cmd[10]; 976 SANE_Byte hdr[8]; 977 struct window_data window; 978 } set_window_cmd; 979 SANE_Status status; 980 SANE_Int width, length, i, format, rotation, deskew ; 981 982 DBG (3, "set_window called\n"); 983 984 /* set to thousandths for set_window */ 985 s->bmu = BH_UNIT_INCH; 986 s->mud = 1000; 987 status = mode_select_measurement(s); 988 if (status != SANE_STATUS_GOOD) 989 return status; 990 991 memset (&set_window_cmd, 0, sizeof (set_window_cmd)); 992 set_window_cmd.cmd[0] = BH_SCSI_SET_WINDOW; 993 DBG(3, "set_window: sizeof(hdr) %d, sizeof(window): %d\n", 994 (int)sizeof(set_window_cmd.hdr), (int)sizeof(set_window_cmd.window)); 995 996 _lto3b(sizeof(set_window_cmd.hdr) + sizeof(set_window_cmd.window), 997 &set_window_cmd.cmd[6]); 998 999 _lto2b(256, &set_window_cmd.hdr[6]); 1000 1001 set_window_cmd.window.windowid = 0; 1002 set_window_cmd.window.autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER); 1003 DBG (5, "autoborder set to=%d\n", set_window_cmd.window.autoborder); 1004 _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.xres); 1005 _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.yres); 1006 _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X), set_window_cmd.window.ulx); 1007 _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y), set_window_cmd.window.uly); 1008 1009 width = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X) - 1010 _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X)); 1011 length = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y) - 1012 _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y)); 1013 1014 _lto4b(width, set_window_cmd.window.windowwidth); 1015 _lto4b(length, set_window_cmd.window.windowlength); 1016 1017 /* brightness (1-255) 0 is default, aka 128. Ignored with ACE scanners */ 1018 set_window_cmd.window.brightness = _OPT_VAL_WORD(s, OPT_BRIGHTNESS); 1019 /* threshold (1-255) 0 is default, aka 128. Ignored with ACE scanners */ 1020 set_window_cmd.window.threshold = _OPT_VAL_WORD(s, OPT_THRESHOLD); 1021 /*!!! contrast (not used) */ 1022 /*!!! set_window_cmd.window.contrast = _OPT_VAL_WORD(s, OPT_CONTRAST); */ 1023 /* imagecomposition 0x00 lineart, 0x01 dithered/halftone, 0x02 grayscale*/ 1024 set_window_cmd.window.imagecomposition = 1025 get_scan_mode_id(_OPT_VAL_STRING(s, OPT_SCAN_MODE)); 1026 1027 set_window_cmd.window.bitsperpixel = 0x01; 1028 /*!!! halftone code (not used) */ 1029 /*!!! halftone id (not used) */ 1030 1031 set_window_cmd.window.paddingtype = 0x03; /* truncate byte */ 1032 if (_OPT_VAL_WORD(s, OPT_NEGATIVE) == SANE_TRUE) { 1033 /* reverse image format (valid when bitsperpixel=1) 1034 * 0x00 normal, 0x01 reversed. This is bit 7 of paddingtype. 1035 */ 1036 set_window_cmd.window.paddingtype |= 0x80; 1037 } 1038 1039 set_window_cmd.window.bitordering[0] = 0x00; 1040 1041 /* we must always sent plain gray data in preview mode */ 1042 format = (_OPT_VAL_WORD(s, OPT_PREVIEW)) ? 1043 BH_COMP_NONE : 1044 get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1045 1046 switch (format) 1047 { 1048 case BH_COMP_G31D: 1049 set_window_cmd.window.compressiontype = 0x01; 1050 set_window_cmd.window.compressionarg = 0x00; 1051 set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1052 break; 1053 case BH_COMP_G32D: 1054 set_window_cmd.window.compressiontype = 0x02; 1055 set_window_cmd.window.compressionarg = 0x04; 1056 set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1057 break; 1058 case BH_COMP_G42D: 1059 set_window_cmd.window.compressiontype = 0x03; 1060 set_window_cmd.window.compressionarg = 0x00; 1061 set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ 1062 break; 1063 case BH_COMP_NONE: 1064 default: 1065 set_window_cmd.window.compressiontype = 0x00; 1066 set_window_cmd.window.compressionarg = 0x00; 1067 set_window_cmd.window.bitordering[1] = 0x00; /* n/a */ 1068 break; 1069 } 1070 1071 /* rotation and deskew settings, if autoborder is turned on */ 1072 if(set_window_cmd.window.autoborder){ /*--- setting byte 46 of the window descriptor block only works with autoborder */ 1073 rotation = get_rotation_id(_OPT_VAL_STRING(s, OPT_ROTATION)); 1074 if (_OPT_VAL_WORD(s, OPT_DESKEW) == SANE_TRUE) deskew = BH_DESKEW_ENABLE; 1075 else deskew = BH_DESKEW_DISABLE; 1076 set_window_cmd.window.border_rotation = ( rotation | deskew ); /*--- deskew assumes autoborder */ 1077 } 1078 1079 /* remote - 0x00 ACE set in window; 0x01 ACE set by control panel */ 1080 set_window_cmd.window.remote = _OPT_VAL_WORD(s, OPT_CONTROL_PANEL); 1081 if (set_window_cmd.window.remote == 0x00) { 1082 /* acefunction (ignored on non-ACE scanners) */ 1083 set_window_cmd.window.acefunction = _OPT_VAL_WORD(s, OPT_ACE_FUNCTION); 1084 /* acesensitivity (ignored on non-ACE scanners) */ 1085 set_window_cmd.window.acesensitivity = _OPT_VAL_WORD(s, OPT_ACE_SENSITIVITY); 1086 } 1087 1088 set_window_cmd.window.batchmode = batchmode; 1089 1090 /* fill in the section descriptor blocks */ 1091 for (i = 0; i < s->num_sections; i++) 1092 { 1093 BH_SectionBlock *b; 1094 1095 b = &set_window_cmd.window.sectionblock[i]; 1096 1097 _lto4b(s->sections[i].left, b->ul_x); 1098 _lto4b(s->sections[i].top, b->ul_y); 1099 _lto4b(s->sections[i].width, b->width); 1100 _lto4b(s->sections[i].length, b->length); 1101 b->compressiontype = s->sections[i].compressiontype; 1102 b->compressionarg = s->sections[i].compressionarg; 1103 } 1104 1105 status = sanei_scsi_cmd (s->fd, &set_window_cmd, sizeof (set_window_cmd), 0, 0); 1106 DBG (5, "sanei_scsi_cmd executed, status=%d\n", status ); 1107 if (status != SANE_STATUS_GOOD) 1108 return status; 1109 1110 /* set to points for reading */ 1111 s->bmu = BH_UNIT_POINT; 1112 s->mud = 1; 1113 status = mode_select_measurement(s); 1114 1115 return status; 1116} 1117 1118static SANE_Status 1119get_window (BH_Scanner *s, SANE_Int *w, SANE_Int *h, SANE_Bool backpage) 1120{ 1121 SANE_Byte cmd[10]; 1122 static struct { 1123 SANE_Byte hdr[8]; 1124 struct window_data window; 1125 } get_window_data; 1126 SANE_Status status; 1127 SANE_Int x, y, i = 0, get_window_delay = 1; 1128 SANE_Bool autoborder; 1129 size_t len; 1130 1131 DBG (3, "get_window called\n"); 1132 1133 autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER) == 1; 1134 1135 while (1) 1136 { 1137 i++; 1138 memset (&cmd, 0, sizeof (cmd)); 1139 memset (&get_window_data, 0, sizeof (get_window_data)); 1140 1141 cmd[0] = BH_SCSI_GET_WINDOW; 1142 _lto3b(sizeof(get_window_data), &cmd[6]); 1143 1144 _lto2b(256, &get_window_data.hdr[6]); 1145 1146 get_window_data.window.windowid = (backpage == SANE_TRUE) ? 1 : 0; 1147 1148 len = sizeof(get_window_data); 1149 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 1150 &get_window_data, &len); 1151 if (status == SANE_STATUS_GOOD) 1152 { 1153 x =_4btol(get_window_data.window.ulx); 1154 y =_4btol(get_window_data.window.uly); 1155 *w =_4btol(get_window_data.window.windowwidth); 1156 *h =_4btol(get_window_data.window.windowlength); 1157 1158 if (autoborder) 1159 { 1160 /* we try repeatedly until we get the autoborder bit set */ 1161 if (get_window_data.window.autoborder != 1 && 1162 i < BH_AUTOBORDER_TRIES) 1163 { 1164 DBG (5, "waiting %d second[s], try: %d\n",get_window_delay,i); 1165 sleep(get_window_delay); /*--- page 4-5 of B&H Copiscan 8000 ESC OEM Tech Manual */ 1166 /*--- requires at least 50ms wait between each GET WINDOW command */ 1167 /*--- experience shows that this can take 3 to 4 seconds */ 1168 continue; 1169 } 1170 if (get_window_data.window.autoborder != 1) 1171 { 1172 DBG(1, "Automatic Border Detection not done within %d tries\n", 1173 BH_AUTOBORDER_TRIES); 1174 status = SANE_STATUS_IO_ERROR; 1175 } 1176 DBG (0, "page dimension: wide:%d high:%d \n",*w,*h); 1177 } 1178 DBG (3, "*** Window size: %dx%d+%d+%d\n", *w, *h, x, y); 1179 DBG (5, "*** get_window found autoborder=%02xh\n", get_window_data.window.autoborder); 1180 DBG (5, "*** get_window found border_rotation=%02xh\n", get_window_data.window.border_rotation); 1181 } 1182 1183 /* we are 'outta here' */ 1184 break; 1185 } 1186 1187 return status; 1188} 1189 1190static SANE_Status 1191get_parameters (SANE_Handle handle, SANE_Parameters *params) 1192{ 1193 BH_Scanner *s = handle; 1194 SANE_Int width, length, res, comp; 1195 double br_x, tl_x, br_y, tl_y; 1196 SANE_Frame format; 1197 1198 DBG(3, "get_parameters called\n"); 1199 1200 memset (&s->params, 0, sizeof (s->params)); 1201 1202 res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 1203 1204 /* make best-effort guess at what parameters will look like once 1205 the scan starts. */ 1206 1207 br_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X); 1208 br_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y); 1209 tl_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X); 1210 tl_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y); 1211 1212 width = (br_x - tl_x + 1) * res / 1000.0; 1213 length = (br_y - tl_y + 1) * res / 1000.0; 1214 1215 /* figure out the default image format for front/back pages */ 1216 comp = get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1217 switch (comp) 1218 { 1219 case BH_COMP_G31D: 1220 format = SANE_FRAME_G31D; 1221 break; 1222 case BH_COMP_G32D: 1223 format = SANE_FRAME_G32D; 1224 break; 1225 case BH_COMP_G42D: 1226 format = SANE_FRAME_G42D; 1227 break; 1228 case BH_COMP_NONE: 1229 default: 1230 format = SANE_FRAME_GRAY; 1231 break; 1232 } 1233 1234 if (s->scanning) 1235 { 1236 SANE_Int w, l, status; 1237 SANE_Byte itemtype; 1238 1239 itemtype = s->readlist[s->readptr]; 1240 /* update parameters based on the current item */ 1241 1242 status = SANE_STATUS_GOOD; 1243 if (itemtype == BH_SCSI_READ_TYPE_FRONT) 1244 { 1245 DBG (3, "get_parameters: sending GET WINDOW (front)\n"); 1246 status = get_window (s, &w, &l, SANE_FALSE); 1247 if (status == SANE_STATUS_GOOD) 1248 { 1249 width = w; 1250 length = l; 1251 } 1252 } 1253 else if (itemtype == BH_SCSI_READ_TYPE_BACK) 1254 { 1255 DBG (3, "get_parameters: sending GET WINDOW (back)\n"); 1256 status = get_window (s, &w, &l, SANE_TRUE); 1257 if (status == SANE_STATUS_GOOD) 1258 { 1259 width = w; 1260 length = l; 1261 } 1262 } 1263 else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || 1264 itemtype == BH_SCSI_READ_TYPE_BACK_ICON) 1265 { 1266 /* the icon is never compressed */ 1267 format = SANE_FRAME_GRAY; 1268 width = s->iconwidth; 1269 length = s->iconlength; 1270 } 1271 else if (itemtype > BH_SCSI_READ_TYPE_FRONT && 1272 itemtype <= (BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS)) 1273 { 1274 /* a front section */ 1275 SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_FRONT; 1276 1277 format = s->sections[sectnum - 1].format; 1278 /* convert from thousandths to pixels */ 1279 width = s->sections[sectnum - 1].width * res / 1000.0; 1280 length = s->sections[sectnum - 1].length * res / 1000.0; 1281 } 1282 else if (itemtype > BH_SCSI_READ_TYPE_BACK && 1283 itemtype <= (BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS)) 1284 { 1285 /* a back section */ 1286 SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_BACK; 1287 1288 format = s->sections[sectnum - 1].format; 1289 /* convert from thousandths to pixels */ 1290 width = s->sections[sectnum - 1].width * res / 1000.0; 1291 length = s->sections[sectnum - 1].length * res / 1000.0; 1292 } 1293 else if ( (itemtype >= BH_SCSI_READ_TYPE_BACK_BARCODE && 1294 itemtype <= (BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS)) || 1295 (itemtype >= BH_SCSI_READ_TYPE_FRONT_BARCODE && 1296 itemtype <= (BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS)) ) 1297 { 1298 /* decoded barcode data */ 1299 format = SANE_FRAME_TEXT; 1300 width = 8; 1301 length = -1; 1302 } 1303 else if (itemtype == BH_SCSI_READ_TYPE_SENDBARFILE) 1304 { 1305 /* decoded barcode data file */ 1306 format = SANE_FRAME_TEXT; 1307 width = 8; 1308 length = -1; 1309 } 1310 else 1311 { 1312 format = SANE_FRAME_GRAY; 1313 width = 8; 1314 length = -1; 1315 DBG(1, "get_parameters: unrecognized read itemtype: %d\n", 1316 itemtype); 1317 } 1318 1319 if (status != SANE_STATUS_GOOD) 1320 { 1321 DBG(1, "get_parameters: failed\n"); 1322 return status; 1323 } 1324 } 1325 1326 if (res <= 0 || width <= 0) 1327 { 1328 DBG(1, "get_parameters:illegal parameters res=%d, width=%d, length=%d\n", 1329 res, width, length); 1330 return SANE_STATUS_INVAL; 1331 } 1332 1333 /* we disable our compression/barcode formats in preview as well 1334 * as with the disable_optional_frames configuration option. NOTE: 1335 * we may still be delivering 'wierd' data and lying about it being _GRAY! 1336 */ 1337 if (format != SANE_FRAME_GRAY && 1338 (_OPT_VAL_WORD(s, OPT_PREVIEW) || disable_optional_frames)) 1339 { 1340 DBG(1, "get_parameters: warning: delivering %s data as gray", 1341 sane_strframe(format)); 1342 format = SANE_FRAME_GRAY; 1343 } 1344 1345 s->params.format = format; 1346 s->params.depth = 1; 1347 s->params.last_frame = SANE_TRUE; 1348 s->params.pixels_per_line = width; 1349 s->params.lines = length; 1350 s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; 1351 /* The Bell and Howell truncates to the byte */ 1352 s->params.pixels_per_line = s->params.bytes_per_line * 8; 1353 1354 if (params) 1355 *params = s->params; 1356 1357 DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " 1358 "lines=%d, dpi=%d\n", 1359 (int) s->params.format, 1360 s->params.pixels_per_line, 1361 s->params.bytes_per_line, 1362 s->params.lines, 1363 res); 1364 1365 return SANE_STATUS_GOOD; 1366} 1367 1368static SANE_Status 1369section_parse(const char *val, BH_Section *sect, SANE_Int res, SANE_Int comp) 1370{ 1371 SANE_Status status = SANE_STATUS_INVAL; 1372 char buf[255+1], *x, *y, *w, *l, *f, *ep; 1373 const char *seps = "x+:"; 1374 double mm, fpixels; 1375 u_long pixels; 1376 1377 DBG(3, "section_parse called\n"); 1378 1379 /* a section option looks something like this: 1380 * <width>x<length>+<tl-x>+<tl-y>:<functioncodes> 1381 * Example: 1382 * 76.2x25.4+50.8+0:frontbar:back:front 1383 * the width, length, tl-x, and tl-y are in mm. 1384 * the function codes are one or more of: 1385 * front, back, frontbar, backbar, frontpatch, backpatch 1386 */ 1387 if (strlen(val) > sizeof(buf) - 1) 1388 { 1389 DBG(1, "section_parse: option string too long\n"); 1390 status = SANE_STATUS_INVAL; 1391 } 1392 else 1393 { 1394 do { 1395 strcpy(buf, val); 1396 1397 x = y = w = l = f = NULL; 1398 w = strtok(buf, seps); 1399 if (w) l = strtok(NULL, seps); 1400 if (l) x = strtok(NULL, seps); 1401 if (x) y = strtok(NULL, seps); 1402 if (y) f = strtok(NULL, seps); 1403 if (!x || !y || !w || !l) break; 1404 1405 mm = strtod(x, &ep); 1406 if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1407 sect->left = mm * 1000.0 / MM_PER_INCH; 1408 1409 mm = strtod(y, &ep); 1410 if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1411 sect->top = mm * 1000.0 / MM_PER_INCH; 1412 1413 mm = strtod(w, &ep); 1414 if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1415 sect->width = mm * 1000.0 / MM_PER_INCH; 1416 /* the window width must be truncated to 16 bit points */ 1417 fpixels = sect->width * res / 1000.0; 1418 pixels = fpixels / 16; 1419 sect->width = pixels * 16 * 1000 / res; 1420 1421 mm = strtod(l, &ep); 1422 if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; 1423 sect->length = mm * 1000.0 / MM_PER_INCH; 1424 1425 status = SANE_STATUS_GOOD; 1426 while (f) 1427 { 1428 /* parse the function modifiers and set flags */ 1429 if (strcmp(f, "front") == 0) 1430 sect->flags |= BH_SECTION_FRONT_IMAGE; 1431 else if (strcmp(f, "frontbar") == 0) 1432 sect->flags |= BH_SECTION_FRONT_BAR; 1433 else if (strcmp(f, "frontpatch") == 0) 1434 sect->flags |= BH_SECTION_FRONT_PATCH; 1435 else if (strcmp(f, "back") == 0) 1436 sect->flags |= BH_SECTION_BACK_IMAGE; 1437 else if (strcmp(f, "backbar") == 0) 1438 sect->flags |= BH_SECTION_BACK_BAR; 1439 else if (strcmp(f, "backpatch") == 0) 1440 sect->flags |= BH_SECTION_BACK_PATCH; 1441 else if (strcmp(f, "g42d") == 0) 1442 comp = BH_COMP_G42D; 1443 else if (strcmp(f, "g32d") == 0) 1444 comp = BH_COMP_G32D; 1445 else if (strcmp(f, "g31d") == 0) 1446 comp = BH_COMP_G31D; 1447 else if (strcmp(f, "none") == 0) 1448 comp = BH_COMP_NONE; 1449 else 1450 DBG(1, "section_parse: ignoring unrecognized function " 1451 "code '%s'\n", f); 1452 1453 f = strtok(NULL, seps); 1454 } 1455 1456 switch (comp) 1457 { 1458 case BH_COMP_G31D: 1459 sect->compressiontype = 0x01; 1460 sect->compressionarg = 0x00; 1461 sect->format = SANE_FRAME_G31D; 1462 break; 1463 case BH_COMP_G32D: 1464 sect->compressiontype = 0x02; 1465 sect->compressionarg = 0x04; 1466 sect->format = SANE_FRAME_G32D; 1467 break; 1468 case BH_COMP_G42D: 1469 sect->compressiontype = 0x03; 1470 sect->compressionarg = 0x00; 1471 sect->format = SANE_FRAME_G42D; 1472 break; 1473 case BH_COMP_NONE: 1474 default: 1475 sect->compressiontype = 0x00; 1476 sect->compressionarg = 0x00; 1477 sect->format = SANE_FRAME_GRAY; 1478 break; 1479 } 1480 1481 DBG(3, "section_parse: converted '%s' (mm) to " 1482 "%ldx%ld+%ld+%ld (thousandths) " 1483 "flags=%02x compression=[%d,%d] frame=%s\n", 1484 val, 1485 sect->width, sect->length, sect->left, sect->top, 1486 sect->flags, 1487 sect->compressiontype, sect->compressionarg, 1488 sane_strframe(sect->format)); 1489 1490 } while (0); /* perform 'loop' once */ 1491 } 1492 1493 return status; 1494} 1495 1496static SANE_Status 1497setup_sections (BH_Scanner *s, const char *val) 1498{ 1499 SANE_Status status = SANE_STATUS_GOOD; 1500 SANE_Int sectnum = 0; 1501 char buf[255+1], *section; 1502 1503 DBG(3, "setup_sections called\n"); 1504 1505 memset(s->sections, '\0', sizeof(s->sections)); 1506 if (strlen(val) > sizeof(buf) - 1) 1507 { 1508 DBG(1, "setup_sections: option string too long\n"); 1509 status = SANE_STATUS_INVAL; 1510 } 1511 else 1512 { 1513 strcpy(buf, val); 1514 1515 section = strtok(buf, ","); 1516 while (section != NULL && sectnum < NUM_SECTIONS) 1517 { 1518 if (!allblank(section)) 1519 { 1520 SANE_Int res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 1521 SANE_Int format = 1522 get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); 1523 1524 status = section_parse(section, &s->sections[sectnum], 1525 res, format); 1526 if (status != SANE_STATUS_GOOD) 1527 { 1528 DBG(1, 1529 "setup_sections: error parsing section `%s'\n", 1530 section); 1531 break; 1532 } 1533 1534 sectnum++; 1535 } 1536 section += strlen(section) + 1; 1537 if (section > buf + strlen(val)) break; 1538 1539 section = strtok(section, ","); 1540 } 1541 } 1542 s->num_sections = sectnum; 1543 1544 return status; 1545} 1546 1547static SANE_Status 1548start_setup (BH_Scanner *s) 1549{ 1550 SANE_Status status; 1551 SANE_Bool duplex; 1552 SANE_Int i, imagecnt; 1553 SANE_Byte batchmode; 1554 1555 DBG(3, "start_setup called\n"); 1556 1557 duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); 1558 1559 /* get the _SECTION option, parse it and fill in the sections */ 1560 status = setup_sections(s, _OPT_VAL_STRING(s, OPT_SECTION)); 1561 if (status != SANE_STATUS_GOOD) 1562 { 1563 DBG(1, "start_setup: setup_sections failed: %s\n", 1564 sane_strstatus(status)); 1565 return status; 1566 } 1567 1568 /* see whether we'll be decoding barcodes and 1569 * set the barcodes flag appropriately 1570 */ 1571 if (s->search_bars[0] == 0) 1572 { 1573 s->barcodes = SANE_FALSE; 1574 } 1575 else 1576 { 1577 s->barcodes = SANE_TRUE; 1578 } 1579 1580 /* see whether we'll be handling icons (thumbnails) 1581 * set the icons flag appropriately 1582 */ 1583 if (_OPT_VAL_WORD(s, OPT_ICON_WIDTH) >= 8 && 1584 _OPT_VAL_WORD(s, OPT_ICON_LENGTH) >= 8) 1585 { 1586 s->icons = SANE_TRUE; 1587 } 1588 else 1589 { 1590 s->icons = SANE_FALSE; 1591 } 1592 1593 1594 /* calculate a new readlist for this 'batch' */ 1595 s->readptr = s->readcnt = 0; 1596 1597 /* always read the front image */ 1598 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT; 1599 1600 /* read back page only if duplex is true */ 1601 if (duplex == SANE_TRUE) 1602 { 1603 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK; 1604 } 1605 1606 /* add image section reads to the readlist */ 1607 for (i = 0; i < s->num_sections; i++) 1608 { 1609 SANE_Word flags = s->sections[i].flags; 1610 1611 if (flags & BH_SECTION_FRONT_IMAGE) 1612 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT + i + 1; 1613 if (flags & BH_SECTION_BACK_IMAGE) 1614 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK + i + 1; 1615 } 1616 1617 1618 /* icons (thumbnails) */ 1619 if (s->icons) 1620 { 1621 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_ICON; 1622 /* read back icon only if duplex is true */ 1623 if (duplex == SANE_TRUE) 1624 { 1625 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_ICON; 1626 } 1627 } 1628 1629 /* NOTE: It is important that all of the image data comes before 1630 * the barcode/patchcode data. 1631 */ 1632 /* barcodes */ 1633 imagecnt = s->readcnt; 1634 if (s->barcodes) 1635 { 1636 if (s->num_sections == 0) 1637 { 1638 /* we only decode the entire page(s) if there are no 1639 * sections defined 1640 */ 1641 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_BARCODE; 1642 /* read back barcode only if duplex is true */ 1643 if (duplex == SANE_TRUE) 1644 { 1645 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_BARCODE; 1646 } 1647 } 1648 else 1649 { 1650 /* add barcode section reads to the readlist */ 1651 for (i = 0; i < s->num_sections; i++) 1652 { 1653 SANE_Word flags = s->sections[i].flags; 1654 1655 if (flags & BH_SECTION_FRONT_BAR) 1656 s->readlist[s->readcnt++] = 1657 BH_SCSI_READ_TYPE_FRONT_BARCODE + i + 1; 1658 if (flags & BH_SECTION_BACK_BAR) 1659 s->readlist[s->readcnt++] = 1660 BH_SCSI_READ_TYPE_BACK_BARCODE + i + 1; 1661 } 1662 } 1663 } 1664 1665 /* patchcodes */ 1666 if (s->patchcodes) 1667 { 1668 if (s->num_sections == 0) 1669 { 1670 /* we only decode the entire page(s) if there are no 1671 * sections defined 1672 */ 1673 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_PATCHCODE; 1674 /* read back patchcode only if duplex is true */ 1675 if (duplex == SANE_TRUE) 1676 { 1677 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_PATCHCODE; 1678 } 1679 } 1680 else 1681 { 1682 /* add patchcode section reads to the readlist */ 1683 for (i = 0; i < s->num_sections; i++) 1684 { 1685 SANE_Word flags = s->sections[i].flags; 1686 1687 if (flags & BH_SECTION_FRONT_PATCH) 1688 s->readlist[s->readcnt++] = 1689 BH_SCSI_READ_TYPE_FRONT_PATCHCODE + i + 1; 1690 if (flags & BH_SECTION_BACK_PATCH) 1691 s->readlist[s->readcnt++] = 1692 BH_SCSI_READ_TYPE_BACK_PATCHCODE + i + 1; 1693 } 1694 } 1695 } 1696 1697 /* add the special item to the read list which transfers the barcode 1698 * file that's built as a result of processing barcode and patchcode 1699 * readitems. NOTE: this one must be last! 1700 */ 1701 if (s->readcnt > imagecnt) 1702 { 1703 s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_SENDBARFILE; 1704 } 1705 1706 if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) 1707 { 1708 /* if batchmode is enabled, then call set_window to 1709 * abort the batch (even though there might not (and probably 1710 * isn't) a batch in progress). This avoids a batch start error 1711 * in the case where a previous batch was not aborted. 1712 */ 1713 DBG(5, "start_setup: calling set_window to abort batch\n"); 1714 set_window(s, BH_BATCH_ABORT); 1715 1716 batchmode = BH_BATCH_ENABLE; 1717 } 1718 else 1719 { 1720 batchmode = BH_BATCH_DISABLE; 1721 } 1722 1723 DBG(5, "start_setup: duplex=%s, barcodes=%s, patchcodes=%s, " 1724 "icons=%s, batch=%s\n", 1725 (duplex == SANE_TRUE) ? "yes" : "no", 1726 (s->barcodes == SANE_TRUE) ? "yes" : "no", 1727 (s->patchcodes == SANE_TRUE) ? "yes" : "no", 1728 (s->icons == SANE_TRUE) ? "yes" : "no", 1729 (batchmode == BH_BATCH_ENABLE) ? "yes" : "no"); 1730 DBG(5, "start_setup: sections=%d\n", s->num_sections); 1731 for (i = 0; i < s->num_sections; i++) 1732 { 1733 DBG(5, "start_setup: " 1734 "[%d] %lux%lu+%lu+%lu flags=%02x compression=[%d,%d]\n", 1735 i+1, 1736 s->sections[i].width, s->sections[i].length, 1737 s->sections[i].left, s->sections[i].top, 1738 s->sections[i].flags, 1739 s->sections[i].compressiontype, s->sections[i].compressionarg); 1740 } 1741 DBG(5, "start_setup: read list length=%d\n", s->readcnt); 1742 for (i = 0; i < s->readcnt; i++) 1743 { 1744 DBG(5, "start_setup: [%d] %s\n", i+1, print_read_type(s->readlist[i])); 1745 } 1746 1747 DBG(5, "start_setup: sending SET WINDOW\n"); 1748 status = set_window(s, batchmode); 1749 if (status != SANE_STATUS_GOOD) 1750 { 1751 DBG(1, "start_setup: SET WINDOW failed: %s\n", 1752 sane_strstatus(status)); 1753 return status; 1754 } 1755 1756 DBG(5, "start_setup: sending mode_select_timeout\n"); 1757 status = mode_select_timeout(s); 1758 if (status != SANE_STATUS_GOOD) 1759 { 1760 DBG(1, "start_setup: mode_select_timeout failed: %s\n", 1761 sane_strstatus(status)); 1762 return status; 1763 } 1764 1765 if (s->icons == SANE_TRUE) 1766 { 1767 DBG(5, "start_setup: sending mode_select_icon\n"); 1768 status = mode_select_icon(s); 1769 if (status != SANE_STATUS_GOOD) 1770 { 1771 DBG(1, "start_setup: mode_select_icon failed: %s\n", 1772 sane_strstatus(status)); 1773 return status; 1774 } 1775 } 1776 1777 if (s->barcodes == SANE_TRUE) 1778 { 1779 DBG(5, "start_setup: sending mode_select_barcode_priority\n"); 1780 status = mode_select_barcode_priority(s); 1781 if (status != SANE_STATUS_GOOD) 1782 { 1783 DBG(1, "start_setup: mode_select_barcode_priority failed: %s\n", 1784 sane_strstatus(status)); 1785 return status; 1786 } 1787 1788 DBG(5, "start_setup: sending mode_select_barcode_param1\n"); 1789 status = mode_select_barcode_param1(s); 1790 if (status != SANE_STATUS_GOOD) 1791 { 1792 DBG(1, "start_setup: mode_select_barcode_param1 failed: %s\n", 1793 sane_strstatus(status)); 1794 return status; 1795 } 1796 1797 DBG(5, "start_setup: sending mode_select_barcode_param2\n"); 1798 status = mode_select_barcode_param2(s); 1799 if (status != SANE_STATUS_GOOD) 1800 { 1801 DBG(1, "start_setup: mode_select_barcode_param2 failed: %s\n", 1802 sane_strstatus(status)); 1803 return status; 1804 } 1805 1806 DBG(5, "start_setup: sending mode_select_barcode_param3\n"); 1807 status = mode_select_barcode_param3(s); 1808 if (status != SANE_STATUS_GOOD) 1809 { 1810 DBG(1, "start_setup: mode_select_barcode_param3 failed: %s\n", 1811 sane_strstatus(status)); 1812 return status; 1813 } 1814 } 1815 1816 return status; 1817} 1818 1819static SANE_Status 1820start_scan (BH_Scanner *s) 1821{ 1822 static SANE_Byte cmd[8]; 1823 SANE_Status status = SANE_STATUS_GOOD; 1824 SANE_Bool check_adf, duplex; 1825 DBG (3, "start_scan called\n"); 1826 1827 /* SANE front ends will call this function between 'FRAMES'. 1828 * A single scan on the B&H may result in up to 56 different 1829 * things to read (20 are SANE image frames, 36 are non-SANE 1830 * data - decoded bar/patch codes). 1831 */ 1832 1833 if (s->readcnt > 1 && s->scanning == SANE_TRUE) 1834 { 1835 DBG(3, "start_scan: any more items in the readlist?\n"); 1836 /* we've been reading data from this scan, so we just 1837 * move on to the next item in the readlist without 1838 * starting a new scan. 1839 */ 1840 s->readptr++; 1841 if (s->readptr < s->readcnt) 1842 { 1843 SANE_Byte itemtype; 1844 1845 for (; s->readptr < s->readcnt; s->readptr++) 1846 { 1847 1848 itemtype = s->readlist[s->readptr]; 1849 1850 DBG(3, "start_scan: advance readlist(%d, %d)\n", 1851 s->readptr, 1852 (int) itemtype); 1853 1854 /* 'dance' by the non-SANE data streams 1855 * like bar/patch code data 1856 */ 1857 if (!BH_HAS_IMAGE_DATA(itemtype)) 1858 { 1859 int fd; 1860 FILE *fp; 1861 1862 strncpy(s->barfname, "/tmp/bhXXXXXX", sizeof(s->barfname)); 1863 s->barfname[sizeof(s->barfname)-1] = '\0'; 1864 fd = mkstemp(s->barfname); 1865 1866 if (fd !=-1 && (fp = fdopen(fd, "w")) != NULL) 1867 { 1868 fprintf(fp, "<xml-stream>\n"); 1869 1870 for (; 1871 s->readptr < s->readcnt && 1872 status == SANE_STATUS_GOOD; 1873 s->readptr++) 1874 { 1875 if (s->readlist[s->readptr] == 1876 BH_SCSI_READ_TYPE_SENDBARFILE) { 1877 break; 1878 } 1879 status = read_barcode_data(s, fp); 1880 if (status != SANE_STATUS_GOOD) break; 1881 } 1882 1883 fprintf(fp, "</xml-stream>\n"); 1884 1885 /* close file; re-open for read(setting s->barfd) */ 1886 fclose(fp); 1887 if ((s->barf = fopen(s->barfname, "r")) == NULL) 1888 { 1889 DBG(1, "sane_start: error opening barfile `%s'\n", 1890 s->barfname); 1891 status = SANE_STATUS_IO_ERROR; 1892 } 1893 } 1894 else 1895 { 1896 DBG(1, "sane_start: error opening barfile `%s'\n", 1897 s->barfname); 1898 if (fd !=-1) 1899 { 1900 close(fd); 1901 unlink(s->barfname); 1902 } 1903 status = SANE_STATUS_IO_ERROR; 1904 } 1905 } 1906 else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || 1907 itemtype == BH_SCSI_READ_TYPE_BACK_ICON) 1908 { 1909 /* read the icon header setting the iconwidth and iconlength 1910 * to the actual values so get_parameters will have them. 1911 * Subsequent calls to sane_read will get pure image data 1912 * since the icon header has been consumed. 1913 */ 1914 1915 status = read_icon_data(s); 1916 } 1917 1918 if (status == SANE_STATUS_GOOD) 1919 { 1920 /* update our parameters to reflect the new item */ 1921 status = get_parameters (s, 0); 1922 } 1923 1924 if (status != SANE_STATUS_GOOD) s->scanning = SANE_FALSE; 1925 1926 return status; 1927 } 1928 /* if we reach here, we're finished with the readlist and 1929 * will drop through to start a new scan 1930 */ 1931 } 1932 } 1933 1934 s->readptr = 0; 1935 1936 check_adf = _OPT_VAL_WORD(s, OPT_CHECK_ADF); 1937 duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); 1938 1939 memset (&cmd, 0, sizeof (cmd)); 1940 cmd[0] = BH_SCSI_START_SCAN; 1941 cmd[4] = (duplex == SANE_TRUE) ? 2 : 1; 1942 1943 cmd[6] = 0; 1944 cmd[7] = 1; 1945 1946 if (check_adf) 1947 { 1948 status = object_position(s); 1949 if (status != SANE_STATUS_GOOD) 1950 { 1951 DBG(3, "object_position: returned %d\n", status); 1952 return status; 1953 } 1954 } 1955 1956 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); 1957 if (status == SANE_STATUS_GOOD) 1958 { 1959 s->scanning = SANE_TRUE; 1960 1961 /* update our parameters, 1962 * now that we're scanning we'll do a GET_WINDOW 1963 */ 1964 status = get_parameters (s, 0); 1965 if (status != SANE_STATUS_GOOD) 1966 { 1967 s->scanning = SANE_FALSE; 1968 } 1969 } 1970 1971 return status; 1972} 1973 1974/* a sensible sense handler, courtesy of Franck; 1975 arg is a pointer to the associated BH_Scanner structure */ 1976static SANE_Status 1977sense_handler (int scsi_fd, u_char *result, void *arg) 1978{ 1979 BH_Scanner *s = (BH_Scanner *) arg; 1980 u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData; 1981 u_long InvalidBytes; 1982 char *sense_str = "", *as_str = ""; 1983 SANE_Int i; 1984 SANE_Status status = SANE_STATUS_INVAL; 1985 SANE_Char print_sense[(16 * 3) + 1]; 1986 1987 (void) scsi_fd; /* get rid of compiler warning */ 1988 ErrorCode = result[0] & 0x7F; 1989 ValidData = (result[0] & 0x80) != 0; 1990 sense = result[2] & 0x0f; /* Key */ 1991 asc = result[12]; /* Code */ 1992 ascq = result[13]; /* Qual */ 1993 EOM = (result[2] & 0x40) != 0; /* End Of Media */ 1994 ILI = (result[2] & 0x20) != 0; /* Invalid Length Indicator */ 1995 InvalidBytes = ValidData ? _4btol(&result[3]) : 0; 1996 1997 DBG(3, "sense_handler: result=%x, sense=%x, asc=%x, ascq=%x\n", 1998 result[0], sense, asc, ascq); 1999 DBG(3, "sense_handler: ErrorCode %02x ValidData: %d " 2000 "EOM: %d ILI: %d InvalidBytes: %lu\n", 2001 ErrorCode, ValidData, EOM, ILI, InvalidBytes); 2002 2003 memset(print_sense, '\0', sizeof(print_sense)); 2004 for (i = 0; i < 16; i++) 2005 { 2006 sprintf(print_sense + strlen(print_sense), "%02x ", result[i]); 2007 } 2008 DBG(5, "sense_handler: sense=%s\n", print_sense); 2009 2010 if (ErrorCode != 0x70 && ErrorCode != 0x71) 2011 { 2012 DBG (3, "sense_handler: error code is invalid.\n"); 2013 return SANE_STATUS_IO_ERROR; /* error code is invalid */ 2014 } 2015 2016 /* handle each sense key; 2017 * RSC supports 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0B 2018 */ 2019 switch (sense) 2020 { 2021 case 0x00: 2022 /* no sense */ 2023 sense_str = "No sense."; 2024 status = SANE_STATUS_GOOD; 2025 if (ILI && asc == 0x00 && ascq == 0x05) 2026 { 2027 /* from read_data function */ 2028 as_str = "ILI bit is set."; 2029 if (s != NULL) 2030 { 2031 s->InvalidBytes = InvalidBytes; 2032 } 2033 status = SANE_STATUS_GOOD; 2034 } 2035 else if (EOM && asc == 0x00 && ascq == 0x02) 2036 { 2037 /* from adfStatus or startScan function */ 2038 as_str = "Out of paper in the hopper."; 2039 status = SANE_STATUS_NO_DOCS; 2040 } 2041 else if (EOM) 2042 { 2043 /* from adfStatus or startScan function */ 2044 as_str = "Out of paper in the hopper."; 2045 status = SANE_STATUS_NO_DOCS; 2046 } 2047 break; 2048 case 0x01: 2049 /* recovered error */ 2050 sense_str = "Recovered error."; 2051 status = SANE_STATUS_GOOD; 2052 break; 2053 case 0x02: 2054 /* not ready */ 2055 sense_str = "Not ready."; 2056 status = SANE_STATUS_DEVICE_BUSY; 2057 if (asc == 0x40 && ascq == 0x01) 2058 { 2059 as_str = "P.O.D. error: Scanner not found."; 2060 status = SANE_STATUS_INVAL; 2061 } 2062 else if (asc == 0x40 && ascq == 0x02) 2063 { 2064 as_str = "P.O.D. error: Scanner not ready(paper in transport)."; 2065 status = SANE_STATUS_DEVICE_BUSY; 2066 } 2067 else if (asc == 0x40 && ascq == 0x03) 2068 { 2069 as_str = "P.O.D. error: Unknown scanner."; 2070 status = SANE_STATUS_INVAL; 2071 } 2072 break; 2073 case 0x03: 2074 /* medium error */ 2075 sense_str = "Medium error."; 2076 status = SANE_STATUS_IO_ERROR; 2077 if (asc == 0x00 && ascq == 0x00) 2078 { 2079 as_str = "Scanner error: paper jam detected."; 2080 status = SANE_STATUS_JAMMED; 2081 } 2082 break; 2083 case 0x04: 2084 /* hardware error */ 2085 sense_str = "Hardware error."; 2086 status = SANE_STATUS_IO_ERROR; 2087 if (asc == 0x60 && ascq == 0x00) 2088 { 2089 as_str = "Scanner error: illumination lamps failure."; 2090 status = SANE_STATUS_IO_ERROR; 2091 } 2092 else if (asc == 0x80 && ascq == 0x03) 2093 { 2094 as_str = "Communication error between RSC and scanner."; 2095 status = SANE_STATUS_IO_ERROR; 2096 } 2097 else if (asc == 0x80 && ascq == 0x06) 2098 { 2099 as_str = "Scanner error: page detected but lamps are off."; 2100 status = SANE_STATUS_IO_ERROR; 2101 } 2102 else if (asc == 0x80 && ascq == 0x07) 2103 { 2104 as_str = "Scanner error: camera white level problem."; 2105 status = SANE_STATUS_IO_ERROR; 2106 } 2107 else if (asc == 0x80 && ascq == 0x08) 2108 { 2109 /* could be caught from start_scan or read_data */ 2110 /* stop button pressed */ 2111 as_str = "Scanner error: operator pressed the Stop key."; 2112 status = SANE_STATUS_NO_DOCS; 2113 } 2114 else if (asc == 0x80 && ascq == 0x12) 2115 { 2116 as_str = "Scanner error: transport motor failure."; 2117 status = SANE_STATUS_IO_ERROR; 2118 } 2119 else if (asc == 0x80 && ascq == 0x15) 2120 { 2121 as_str = "Scanner error: device / page sensor(s) bouncing."; 2122 status = SANE_STATUS_IO_ERROR; 2123 } 2124 else if (asc == 0x80 && ascq == 0x16) 2125 { 2126 as_str = "Scanner error: feeder is not attached."; 2127 status = SANE_STATUS_IO_ERROR; 2128 } 2129 else if (asc == 0x80 && ascq == 0x18) 2130 { 2131 as_str = "Scanner error: logic system general failure."; 2132 status = SANE_STATUS_IO_ERROR; 2133 } 2134 else if (asc == 0x80 && ascq == 0x34) 2135 { 2136 as_str = "Scanner error: no dual logic communication."; 2137 status = SANE_STATUS_IO_ERROR; 2138 } 2139 break; 2140 case 0x05: 2141 /* illegal request */ 2142 sense_str = "Illegal request."; 2143 status = SANE_STATUS_INVAL; 2144 if (asc == 0x1a && ascq == 0x00) 2145 { 2146 as_str = "Parameter list length error."; 2147 status = SANE_STATUS_INVAL; 2148 } 2149 else if (asc == 0x20 && ascq == 0x00) 2150 { 2151 as_str = "Invalid command operation code."; 2152 status = SANE_STATUS_INVAL; 2153 } 2154 else if (asc == 0x24 && ascq == 0x00) 2155 { 2156 /* caught from object_position (via reverse engineering) */ 2157 /* Not supported? */ 2158 as_str = "Invalid field in CDB."; 2159 status = SANE_STATUS_INVAL; 2160 } 2161 else if (asc == 0x25 && ascq == 0x00) 2162 { 2163 as_str = "Unsupported LUN."; 2164 status = SANE_STATUS_INVAL; 2165 } 2166 else if (asc == 0x26 && ascq == 0x00) 2167 { 2168 /* caught from mode_select (as well as others) */ 2169 /* Bar/Patch code detection support not installed */ 2170 /* See Appendix A, Section A.5 */ 2171 as_str = "Invalid field in parameter list."; 2172 status = SANE_STATUS_INVAL; 2173 } 2174 else if (asc == 0x2c && ascq == 0x00) 2175 { 2176 /* we were getting this in read_data during the time 2177 that the ADF was misbehaving. Hopefully we will 2178 not see it anymore. 2179 */ 2180 as_str = "Command out of sequence."; 2181 status = SANE_STATUS_INVAL; 2182 } 2183 else if (asc == 0x2c && ascq == 0x01) 2184 { 2185 as_str = "Too many windows defined."; 2186 status = SANE_STATUS_INVAL; 2187 } 2188 else if (asc == 0x2c && ascq == 0x02) 2189 { 2190 as_str = "Batch start error."; 2191 status = SANE_STATUS_INVAL; 2192 } 2193 else if (asc == 0x2c && ascq == 0x03) 2194 { 2195 as_str = "Batch abort error."; 2196 status = SANE_STATUS_INVAL; 2197 } 2198 else if (asc == 0x3d && ascq == 0x00) 2199 { 2200 as_str = "Invalid bits in IDENTIFY message."; 2201 status = SANE_STATUS_INVAL; 2202 } 2203 break; 2204 case 0x06: 2205 /* unit attention */ 2206 sense_str = "Unit attention."; 2207 status = SANE_STATUS_IO_ERROR; 2208 if (asc == 0x04 && ascq == 0x01) 2209 { 2210 as_str = "Reset detected, LUN is becoming ready."; 2211 status = SANE_STATUS_DEVICE_BUSY; 2212 } 2213 break; 2214 case 0x07: 2215 /* data protect */ 2216 sense_str = "Data protect."; 2217 status = SANE_STATUS_IO_ERROR; 2218 break; 2219 case 0x08: 2220 /* blank check */ 2221 sense_str = "Blank check."; 2222 status = SANE_STATUS_IO_ERROR; 2223 break; 2224 case 0x09: 2225 /* vendor specific */ 2226 sense_str = "Vendor specific."; 2227 status = SANE_STATUS_IO_ERROR; 2228 break; 2229 case 0x0A: 2230 /* copy aborted */ 2231 sense_str = "Copy aborted."; 2232 status = SANE_STATUS_IO_ERROR; 2233 break; 2234 case 0x0B: 2235 /* aborted command */ 2236 sense_str = "Aborted command."; 2237 status = SANE_STATUS_IO_ERROR; 2238 if (asc == 0x00 && ascq == 0x00) 2239 { 2240 as_str = "Aborted command (unspecified error)."; 2241 status = SANE_STATUS_IO_ERROR; 2242 } 2243 else if (asc == 0x08 && ascq == 0x01) 2244 { 2245 /* caught from start_scan */ 2246 /* manual feed timeout */ 2247 as_str = "SCSI Time-out, paper Time-out (SCAN command)."; 2248 status = SANE_STATUS_NO_DOCS; 2249 } 2250 else if (asc == 0x47 && ascq == 0x00) 2251 { 2252 as_str = "SCSI parity error."; 2253 status = SANE_STATUS_IO_ERROR; 2254 } 2255 else if (asc == 0x80 && ascq == 0x00) 2256 { 2257 as_str = "Aborted command due to memory error."; 2258 status = SANE_STATUS_IO_ERROR; 2259 } 2260 else if (asc == 0x80 && ascq == 0x01) 2261 { 2262 /* caught from read_data */ 2263 /* section border error; border is outside the main window */ 2264 /* See Appendix A, Section A.4 */ 2265 as_str = "Section Read error (out of border)."; 2266 status = SANE_STATUS_INVAL; 2267 } 2268 else if (asc == 0x80 && ascq == 0x02) 2269 { 2270 /* caught from read_data */ 2271 /* No code found; no barcode data is found */ 2272 /* See Appendix A, Section A.5 */ 2273 s->barcode_not_found = SANE_TRUE; 2274 as_str = "No Bar/Patch Code found."; 2275 status = SANE_STATUS_GOOD; 2276 } 2277 else if (asc == 0x80 && ascq == 0x03) 2278 { 2279 as_str = "Icon Read error (out of border)."; 2280 status = SANE_STATUS_INVAL; 2281 } 2282 break; 2283 case 0x0C: 2284 /* equal */ 2285 sense_str = "Equal."; 2286 status = SANE_STATUS_IO_ERROR; 2287 break; 2288 case 0x0D: 2289 /* volume overflow */ 2290 sense_str = "Volume overflow."; 2291 status = SANE_STATUS_IO_ERROR; 2292 break; 2293 case 0x0E: 2294 /* miscompare */ 2295 sense_str = "Miscompare."; 2296 status = SANE_STATUS_IO_ERROR; 2297 break; 2298 case 0x0F: 2299 /* reserved */ 2300 sense_str = "Reserved."; 2301 status = SANE_STATUS_IO_ERROR; 2302 break; 2303 default: 2304 sense_str = "Unhandled case."; 2305 status = SANE_STATUS_IO_ERROR; 2306 break; 2307 } 2308 2309 DBG(3, "sense_handler: '%s' '%s' return:%d\n", 2310 sense_str, as_str, status); 2311 2312 return status; 2313} 2314 2315static SANE_Status 2316init_options (BH_Scanner * s) 2317{ 2318 int i; 2319 DBG (3, "init_options called\n"); 2320 2321 memset (s->opt, 0, sizeof (s->opt)); 2322 memset (s->val, 0, sizeof (s->val)); 2323 2324 for (i = 0; i < NUM_OPTIONS; ++i) 2325 { 2326 s->opt[i].size = sizeof (SANE_Word); 2327 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2328 } 2329 2330 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2331 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2332 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2333 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2334 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 2335 2336 /* "Scan Mode" group: */ 2337 s->opt[OPT_MODE_GROUP].name = ""; 2338 s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP; 2339 s->opt[OPT_MODE_GROUP].desc = ""; 2340 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2341 s->opt[OPT_MODE_GROUP].cap = 0; 2342 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2343 2344 /* Preview: */ 2345 s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2346 s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2347 s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2348 s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2349 s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; 2350 s->val[OPT_PREVIEW].w = 0; 2351 2352 /* Inquiry */ 2353 s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY; 2354 s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY; 2355 s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY; 2356 s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING; 2357 s->opt[OPT_INQUIRY].size = sizeof(inquiry_data); 2358 s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE; 2359 s->val[OPT_INQUIRY].s = strdup(inquiry_data); 2360 s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT; 2361 2362 /* scan mode */ 2363 s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE; 2364 s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE; 2365 s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE; 2366 s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING; 2367 s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_list); 2368 s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2369 s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_list; 2370 s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]); 2371 2372 /* Standard resolutions */ 2373 s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2374 s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 2375 s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2376 s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 2377 s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 2378 s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2379 s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList; 2380 s->val[OPT_RESOLUTION].w = s->hw->info.res_default; 2381 2382 /* compression */ 2383 s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION; 2384 s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION; 2385 s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION; 2386 s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING; 2387 s->opt[OPT_COMPRESSION].size = max_string_size (compression_list); 2388 s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2389 s->opt[OPT_COMPRESSION].constraint.string_list = compression_list; 2390 s->val[OPT_COMPRESSION].s = strdup (compression_list[0]); 2391 2392 if (s->hw->info.colorHalftone == SANE_FALSE) 2393 { 2394 s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_min_list); 2395 s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_min_list; 2396 } 2397 2398 if (s->hw->info.comprG3_1D == SANE_FALSE || 2399 s->hw->info.comprG3_2D == SANE_FALSE || 2400 s->hw->info.comprG4 == SANE_FALSE) 2401 { 2402 s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; 2403 } 2404 2405 /* "Geometry" group: */ 2406 s->opt[OPT_GEOMETRY_GROUP].name = ""; 2407 s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP; 2408 s->opt[OPT_GEOMETRY_GROUP].desc = ""; 2409 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2410 s->opt[OPT_GEOMETRY_GROUP].cap = 0; 2411 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2412 2413 /* Autoborder: */ 2414 s->opt[OPT_AUTOBORDER].name = SANE_NAME_AUTOBORDER; 2415 s->opt[OPT_AUTOBORDER].title = SANE_TITLE_AUTOBORDER; 2416 s->opt[OPT_AUTOBORDER].desc = SANE_DESC_AUTOBORDER; 2417 s->opt[OPT_AUTOBORDER].type = SANE_TYPE_BOOL; 2418 s->opt[OPT_AUTOBORDER].constraint_type = SANE_CONSTRAINT_NONE; 2419 s->val[OPT_AUTOBORDER].w = s->hw->info.autoborder_default; 2420 2421 /* Paper Size */ 2422 s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; 2423 s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; 2424 s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; 2425 s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; 2426 s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list); 2427 s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2428 s->opt[OPT_PAPER_SIZE].constraint.string_list = paper_list; 2429 s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]); 2430 2431 /* rotation */ 2432 s->opt[OPT_ROTATION].name = SANE_NAME_ROTATION; 2433 s->opt[OPT_ROTATION].title = SANE_TITLE_ROTATION; 2434 s->opt[OPT_ROTATION].desc = SANE_DESC_ROTATION; 2435 s->opt[OPT_ROTATION].type = SANE_TYPE_STRING; 2436 s->opt[OPT_ROTATION].size = max_string_size (rotation_list); 2437 s->opt[OPT_ROTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2438 s->opt[OPT_ROTATION].constraint.string_list = rotation_list; 2439 s->val[OPT_ROTATION].s = strdup (rotation_list[0]); 2440 2441 /* Deskew: */ 2442 s->opt[OPT_DESKEW].name = SANE_NAME_DESKEW; 2443 s->opt[OPT_DESKEW].title = SANE_TITLE_DESKEW; 2444 s->opt[OPT_DESKEW].desc = SANE_DESC_DESKEW; 2445 s->opt[OPT_DESKEW].type = SANE_TYPE_BOOL; 2446 s->opt[OPT_DESKEW].constraint_type = SANE_CONSTRAINT_NONE; 2447 s->val[OPT_DESKEW].w = s->hw->info.deskew_default; 2448 2449 /* top-left x */ 2450 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2451 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2452 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2453 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2454 s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2455 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2456 s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range); 2457 s->val[OPT_TL_X].w = SANE_FIX(0.0); 2458 2459 /* top-left y */ 2460 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2461 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2462 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2463 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2464 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2465 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2466 s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range); 2467 s->val[OPT_TL_Y].w = SANE_FIX(0.0); 2468 2469 /* bottom-right x */ 2470 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2471 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2472 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2473 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2474 s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2475 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2476 s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range); 2477 s->val[OPT_BR_X].w = s->hw->info.x_range.max; 2478 2479 /* bottom-right y */ 2480 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2481 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2482 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2483 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2484 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2485 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2486 s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range); 2487 s->val[OPT_BR_Y].w = s->hw->info.y_range.max; 2488 2489 if (s->hw->info.canBorderRecog == SANE_FALSE) 2490 { 2491 s->opt[OPT_AUTOBORDER].cap |= SANE_CAP_INACTIVE; 2492 } 2493 2494 /* "Feeder" group: */ 2495 s->opt[OPT_FEEDER_GROUP].name = ""; 2496 s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP; 2497 s->opt[OPT_FEEDER_GROUP].desc = ""; 2498 s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP; 2499 s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED; 2500 s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2501 2502 /* scan source */ 2503 s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE; 2504 s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 2505 s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 2506 s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING; 2507 s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list); 2508 s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2509 s->opt[OPT_SCAN_SOURCE].constraint.string_list = scan_source_list; 2510 s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]); 2511 2512 /* Batch: */ 2513 s->opt[OPT_BATCH].name = SANE_NAME_BATCH; 2514 s->opt[OPT_BATCH].title = SANE_TITLE_BATCH; 2515 s->opt[OPT_BATCH].desc = SANE_DESC_BATCH; 2516 s->opt[OPT_BATCH].type = SANE_TYPE_BOOL; 2517 s->opt[OPT_BATCH].constraint_type = SANE_CONSTRAINT_NONE; 2518 s->val[OPT_BATCH].w = s->hw->info.batch_default; 2519 2520 /* Check ADF: */ 2521 s->opt[OPT_CHECK_ADF].name = SANE_NAME_CHECK_ADF; 2522 s->opt[OPT_CHECK_ADF].title = SANE_TITLE_CHECK_ADF; 2523 s->opt[OPT_CHECK_ADF].desc = SANE_DESC_CHECK_ADF; 2524 s->opt[OPT_CHECK_ADF].type = SANE_TYPE_BOOL; 2525 s->opt[OPT_CHECK_ADF].constraint_type = SANE_CONSTRAINT_NONE; 2526 s->val[OPT_CHECK_ADF].w = s->hw->info.check_adf_default; 2527 2528 /* Duplex: */ 2529 s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; 2530 s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; 2531 s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; 2532 s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; 2533 s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE; 2534 s->val[OPT_DUPLEX].w = s->hw->info.duplex_default; 2535 2536 /* timeout adf */ 2537 s->opt[OPT_TIMEOUT_ADF].name = SANE_NAME_TIMEOUT_ADF; 2538 s->opt[OPT_TIMEOUT_ADF].title = SANE_TITLE_TIMEOUT_ADF; 2539 s->opt[OPT_TIMEOUT_ADF].desc = SANE_DESC_TIMEOUT_ADF; 2540 s->opt[OPT_TIMEOUT_ADF].type = SANE_TYPE_INT; 2541 s->opt[OPT_TIMEOUT_ADF].unit = SANE_UNIT_NONE; 2542 s->opt[OPT_TIMEOUT_ADF].constraint_type = SANE_CONSTRAINT_RANGE; 2543 s->opt[OPT_TIMEOUT_ADF].constraint.range = &u8_range; 2544 s->val[OPT_TIMEOUT_ADF].w = s->hw->info.timeout_adf_default; 2545 2546 /* timeout manual */ 2547 s->opt[OPT_TIMEOUT_MANUAL].name = SANE_NAME_TIMEOUT_MANUAL; 2548 s->opt[OPT_TIMEOUT_MANUAL].title = SANE_TITLE_TIMEOUT_MANUAL; 2549 s->opt[OPT_TIMEOUT_MANUAL].desc = SANE_DESC_TIMEOUT_MANUAL; 2550 s->opt[OPT_TIMEOUT_MANUAL].type = SANE_TYPE_INT; 2551 s->opt[OPT_TIMEOUT_MANUAL].unit = SANE_UNIT_NONE; 2552 s->opt[OPT_TIMEOUT_MANUAL].constraint_type = SANE_CONSTRAINT_RANGE; 2553 s->opt[OPT_TIMEOUT_MANUAL].constraint.range = &u8_range; 2554 s->val[OPT_TIMEOUT_MANUAL].w = s->hw->info.timeout_manual_default; 2555 2556 if (s->hw->info.canCheckADF == SANE_FALSE) 2557 { 2558 s->opt[OPT_CHECK_ADF].cap |= SANE_CAP_INACTIVE; 2559 } 2560 2561 if (s->hw->info.canDuplex == SANE_FALSE) 2562 { 2563 s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; 2564 } 2565 2566 if (s->hw->info.canADF == SANE_FALSE) 2567 { 2568 s->opt[OPT_TIMEOUT_ADF].cap |= SANE_CAP_INACTIVE; 2569 } 2570 2571 /* "Enhancement" group: */ 2572 s->opt[OPT_ENHANCEMENT_GROUP].name = ""; 2573 s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP; 2574 s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 2575 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2576 s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 2577 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2578 2579 /* Control Panel: */ 2580 s->opt[OPT_CONTROL_PANEL].name = SANE_NAME_CONTROL_PANEL; 2581 s->opt[OPT_CONTROL_PANEL].title = SANE_TITLE_CONTROL_PANEL; 2582 s->opt[OPT_CONTROL_PANEL].desc = SANE_DESC_CONTROL_PANEL; 2583 s->opt[OPT_CONTROL_PANEL].type = SANE_TYPE_BOOL; 2584 s->opt[OPT_CONTROL_PANEL].constraint_type = SANE_CONSTRAINT_NONE; 2585 s->val[OPT_CONTROL_PANEL].w = s->hw->info.control_panel_default; 2586 2587 /* Ace_Function */ 2588 s->opt[OPT_ACE_FUNCTION].name = SANE_NAME_ACE_FUNCTION; 2589 s->opt[OPT_ACE_FUNCTION].title = SANE_TITLE_ACE_FUNCTION; 2590 s->opt[OPT_ACE_FUNCTION].desc = SANE_DESC_ACE_FUNCTION; 2591 s->opt[OPT_ACE_FUNCTION].type = SANE_TYPE_INT; 2592 s->opt[OPT_ACE_FUNCTION].unit = SANE_UNIT_NONE; 2593 s->opt[OPT_ACE_FUNCTION].constraint_type = SANE_CONSTRAINT_RANGE; 2594 s->opt[OPT_ACE_FUNCTION].constraint.range = &ace_function_range; 2595 s->val[OPT_ACE_FUNCTION].w = 0; 2596 2597 /* Ace_Sensitivity */ 2598 s->opt[OPT_ACE_SENSITIVITY].name = SANE_NAME_ACE_SENSITIVITY; 2599 s->opt[OPT_ACE_SENSITIVITY].title = SANE_TITLE_ACE_SENSITIVITY; 2600 s->opt[OPT_ACE_SENSITIVITY].desc = SANE_DESC_ACE_SENSITIVITY; 2601 s->opt[OPT_ACE_SENSITIVITY].type = SANE_TYPE_INT; 2602 s->opt[OPT_ACE_SENSITIVITY].unit = SANE_UNIT_NONE; 2603 s->opt[OPT_ACE_SENSITIVITY].constraint_type = SANE_CONSTRAINT_RANGE; 2604 s->opt[OPT_ACE_SENSITIVITY].constraint.range = &ace_sensitivity_range; 2605 s->val[OPT_ACE_SENSITIVITY].w = 4; 2606 2607 /* Brightness */ 2608 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2609 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2610 s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2611 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 2612 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 2613 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2614 s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; 2615 s->val[OPT_BRIGHTNESS].w = 0; 2616 2617 /* Threshold */ 2618 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2619 s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2620 s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2621 s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 2622 s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 2623 s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 2624 s->opt[OPT_THRESHOLD].constraint.range = &u8_range; 2625 s->val[OPT_THRESHOLD].w = 0; 2626 2627 /* Contrast */ 2628 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 2629 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 2630 s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 2631 s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; 2632 s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; 2633 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2634 s->opt[OPT_CONTRAST].constraint.range = &u8_range; 2635 s->val[OPT_CONTRAST].w = 0; 2636 2637 /* Negative: */ 2638 s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; 2639 s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; 2640 s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; 2641 s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; 2642 s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE; 2643 s->val[OPT_NEGATIVE].w = SANE_FALSE; 2644 2645 /* Contrast is not used in any case; why did we add it? */ 2646 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2647 if (s->hw->info.control_panel_default == SANE_TRUE) 2648 { 2649 s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 2650 s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 2651 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2652 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2653 } 2654 else if (s->hw->info.canACE == SANE_FALSE) 2655 { 2656 s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 2657 s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 2658 } 2659 else 2660 { 2661 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2662 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2663 } 2664 2665 /* "ICON" group: */ 2666 s->opt[OPT_ICON_GROUP].name = ""; 2667 s->opt[OPT_ICON_GROUP].title = SANE_TITLE_ICON_GROUP; 2668 s->opt[OPT_ICON_GROUP].desc = ""; 2669 s->opt[OPT_ICON_GROUP].type = SANE_TYPE_GROUP; 2670 s->opt[OPT_ICON_GROUP].cap = SANE_CAP_ADVANCED; 2671 s->opt[OPT_ICON_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2672 2673 /* Icon_Width */ 2674 s->opt[OPT_ICON_WIDTH].name = SANE_NAME_ICON_WIDTH; 2675 s->opt[OPT_ICON_WIDTH].title = SANE_TITLE_ICON_WIDTH; 2676 s->opt[OPT_ICON_WIDTH].desc = SANE_DESC_ICON_WIDTH; 2677 s->opt[OPT_ICON_WIDTH].type = SANE_TYPE_INT; 2678 s->opt[OPT_ICON_WIDTH].unit = SANE_UNIT_PIXEL; 2679 s->opt[OPT_ICON_WIDTH].constraint_type = SANE_CONSTRAINT_RANGE; 2680 s->opt[OPT_ICON_WIDTH].constraint.range = &icon_range; 2681 s->val[OPT_ICON_WIDTH].w = 0; 2682 2683 /* Icon_Length */ 2684 s->opt[OPT_ICON_LENGTH].name = SANE_NAME_ICON_LENGTH; 2685 s->opt[OPT_ICON_LENGTH].title = SANE_TITLE_ICON_LENGTH; 2686 s->opt[OPT_ICON_LENGTH].desc = SANE_DESC_ICON_LENGTH; 2687 s->opt[OPT_ICON_LENGTH].type = SANE_TYPE_INT; 2688 s->opt[OPT_ICON_LENGTH].unit = SANE_UNIT_PIXEL; 2689 s->opt[OPT_ICON_LENGTH].constraint_type = SANE_CONSTRAINT_RANGE; 2690 s->opt[OPT_ICON_LENGTH].constraint.range = &icon_range; 2691 s->val[OPT_ICON_LENGTH].w = 0; 2692 2693 if (s->hw->info.canIcon == SANE_FALSE) 2694 { 2695 s->opt[OPT_ICON_GROUP].cap |= SANE_CAP_INACTIVE; 2696 s->opt[OPT_ICON_WIDTH].cap |= SANE_CAP_INACTIVE; 2697 s->opt[OPT_ICON_LENGTH].cap |= SANE_CAP_INACTIVE; 2698 } 2699 2700 /* "Barcode" group: */ 2701 s->opt[OPT_BARCODE_GROUP].name = ""; 2702 s->opt[OPT_BARCODE_GROUP].title = SANE_TITLE_BARCODE_GROUP; 2703 s->opt[OPT_BARCODE_GROUP].desc = ""; 2704 s->opt[OPT_BARCODE_GROUP].type = SANE_TYPE_GROUP; 2705 s->opt[OPT_BARCODE_GROUP].cap = SANE_CAP_ADVANCED; 2706 s->opt[OPT_BARCODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2707 2708 /* Add <name> to barcode search priority. */ 2709 s->opt[OPT_BARCODE_SEARCH_BAR].name = SANE_NAME_BARCODE_SEARCH_BAR; 2710 s->opt[OPT_BARCODE_SEARCH_BAR].title = SANE_TITLE_BARCODE_SEARCH_BAR; 2711 s->opt[OPT_BARCODE_SEARCH_BAR].desc = SANE_DESC_BARCODE_SEARCH_BAR; 2712 s->opt[OPT_BARCODE_SEARCH_BAR].type = SANE_TYPE_STRING; 2713 s->opt[OPT_BARCODE_SEARCH_BAR].unit = SANE_UNIT_NONE; 2714 s->opt[OPT_BARCODE_SEARCH_BAR].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2715 s->opt[OPT_BARCODE_SEARCH_BAR].constraint.string_list = barcode_search_bar_list; 2716 s->opt[OPT_BARCODE_SEARCH_BAR].size = max_string_size (barcode_search_bar_list); 2717 s->val[OPT_BARCODE_SEARCH_BAR].s = strdup (barcode_search_bar_list[0]); 2718 2719 /* Barcode search count (1-7, default 1). */ 2720 s->opt[OPT_BARCODE_SEARCH_COUNT].name = SANE_NAME_BARCODE_SEARCH_COUNT; 2721 s->opt[OPT_BARCODE_SEARCH_COUNT].title = SANE_TITLE_BARCODE_SEARCH_COUNT; 2722 s->opt[OPT_BARCODE_SEARCH_COUNT].desc = SANE_DESC_BARCODE_SEARCH_COUNT; 2723 s->opt[OPT_BARCODE_SEARCH_COUNT].type = SANE_TYPE_INT; 2724 s->opt[OPT_BARCODE_SEARCH_COUNT].unit = SANE_UNIT_NONE; 2725 s->opt[OPT_BARCODE_SEARCH_COUNT].constraint_type = SANE_CONSTRAINT_RANGE; 2726 s->opt[OPT_BARCODE_SEARCH_COUNT].constraint.range = &barcode_search_count_range; 2727 s->val[OPT_BARCODE_SEARCH_COUNT].w = 3; 2728 2729 /* Barcode search mode. horiz-vert, horizontal, vertical, vert-horiz */ 2730 s->opt[OPT_BARCODE_SEARCH_MODE].name = SANE_NAME_BARCODE_SEARCH_MODE; 2731 s->opt[OPT_BARCODE_SEARCH_MODE].title = SANE_TITLE_BARCODE_SEARCH_MODE; 2732 s->opt[OPT_BARCODE_SEARCH_MODE].desc = SANE_DESC_BARCODE_SEARCH_MODE; 2733 s->opt[OPT_BARCODE_SEARCH_MODE].type = SANE_TYPE_STRING; 2734 s->opt[OPT_BARCODE_SEARCH_MODE].size = max_string_size (barcode_search_mode_list); 2735 s->opt[OPT_BARCODE_SEARCH_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2736 s->opt[OPT_BARCODE_SEARCH_MODE].constraint.string_list = barcode_search_mode_list; 2737 s->val[OPT_BARCODE_SEARCH_MODE].s = strdup(barcode_search_mode_list[0]); 2738 2739 /* Patch code min height (def=5mm) */ 2740 s->opt[OPT_BARCODE_HMIN].name = SANE_NAME_BARCODE_HMIN; 2741 s->opt[OPT_BARCODE_HMIN].title = SANE_TITLE_BARCODE_HMIN; 2742 s->opt[OPT_BARCODE_HMIN].desc = SANE_DESC_BARCODE_HMIN; 2743 s->opt[OPT_BARCODE_HMIN].type = SANE_TYPE_INT; 2744 s->opt[OPT_BARCODE_HMIN].unit = SANE_UNIT_MM; 2745 s->opt[OPT_BARCODE_HMIN].constraint_type = SANE_CONSTRAINT_RANGE; 2746 s->opt[OPT_BARCODE_HMIN].constraint.range = &barcode_hmin_range; 2747 s->val[OPT_BARCODE_HMIN].w = 5; 2748 2749 /* Barcode search timeout in ms (20-65535,default is 10000). */ 2750 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].name = SANE_NAME_BARCODE_SEARCH_TIMEOUT; 2751 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].title = SANE_TITLE_BARCODE_SEARCH_TIMEOUT; 2752 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].desc = SANE_DESC_BARCODE_SEARCH_TIMEOUT; 2753 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].type = SANE_TYPE_INT; 2754 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].unit = SANE_UNIT_MICROSECOND; 2755 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; 2756 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint.range = &barcode_search_timeout_range; 2757 s->val[OPT_BARCODE_SEARCH_TIMEOUT].w = 10000; 2758 2759 /* Specify image sections and functions */ 2760 s->opt[OPT_SECTION].name = SANE_NAME_SECTION; 2761 s->opt[OPT_SECTION].title = SANE_TITLE_SECTION; 2762 s->opt[OPT_SECTION].desc = SANE_DESC_SECTION; 2763 s->opt[OPT_SECTION].type = SANE_TYPE_STRING; 2764 s->opt[OPT_SECTION].unit = SANE_UNIT_NONE; 2765 s->opt[OPT_SECTION].constraint_type = SANE_CONSTRAINT_NONE; 2766 s->opt[OPT_SECTION].size = 255; 2767 s->val[OPT_SECTION].s = strdup (""); 2768 2769 /* Barcode_Relmax */ 2770 s->opt[OPT_BARCODE_RELMAX].name = SANE_NAME_BARCODE_RELMAX; 2771 s->opt[OPT_BARCODE_RELMAX].title = SANE_TITLE_BARCODE_RELMAX; 2772 s->opt[OPT_BARCODE_RELMAX].desc = SANE_DESC_BARCODE_RELMAX; 2773 s->opt[OPT_BARCODE_RELMAX].type = SANE_TYPE_INT; 2774 s->opt[OPT_BARCODE_RELMAX].unit = SANE_UNIT_NONE; 2775 s->opt[OPT_BARCODE_RELMAX].constraint_type = SANE_CONSTRAINT_RANGE; 2776 s->opt[OPT_BARCODE_RELMAX].constraint.range = &u8_range; 2777 s->val[OPT_BARCODE_RELMAX].w = 0; 2778 2779 /* Barcode_Barmin */ 2780 s->opt[OPT_BARCODE_BARMIN].name = SANE_NAME_BARCODE_BARMIN; 2781 s->opt[OPT_BARCODE_BARMIN].title = SANE_TITLE_BARCODE_BARMIN; 2782 s->opt[OPT_BARCODE_BARMIN].desc = SANE_DESC_BARCODE_BARMIN; 2783 s->opt[OPT_BARCODE_BARMIN].type = SANE_TYPE_INT; 2784 s->opt[OPT_BARCODE_BARMIN].unit = SANE_UNIT_NONE; 2785 s->opt[OPT_BARCODE_BARMIN].constraint_type = SANE_CONSTRAINT_RANGE; 2786 s->opt[OPT_BARCODE_BARMIN].constraint.range = &u8_range; 2787 s->val[OPT_BARCODE_BARMIN].w = 0; 2788 2789 /* Barcode_Barmax */ 2790 s->opt[OPT_BARCODE_BARMAX].name = SANE_NAME_BARCODE_BARMAX; 2791 s->opt[OPT_BARCODE_BARMAX].title = SANE_TITLE_BARCODE_BARMAX; 2792 s->opt[OPT_BARCODE_BARMAX].desc = SANE_DESC_BARCODE_BARMAX; 2793 s->opt[OPT_BARCODE_BARMAX].type = SANE_TYPE_INT; 2794 s->opt[OPT_BARCODE_BARMAX].unit = SANE_UNIT_NONE; 2795 s->opt[OPT_BARCODE_BARMAX].constraint_type = SANE_CONSTRAINT_RANGE; 2796 s->opt[OPT_BARCODE_BARMAX].constraint.range = &u8_range; 2797 s->val[OPT_BARCODE_BARMAX].w = 0; 2798 2799 /* Barcode_Contrast */ 2800 s->opt[OPT_BARCODE_CONTRAST].name = SANE_NAME_BARCODE_CONTRAST; 2801 s->opt[OPT_BARCODE_CONTRAST].title = SANE_TITLE_BARCODE_CONTRAST; 2802 s->opt[OPT_BARCODE_CONTRAST].desc = SANE_DESC_BARCODE_CONTRAST; 2803 s->opt[OPT_BARCODE_CONTRAST].type = SANE_TYPE_INT; 2804 s->opt[OPT_BARCODE_CONTRAST].unit = SANE_UNIT_NONE; 2805 s->opt[OPT_BARCODE_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2806 s->opt[OPT_BARCODE_CONTRAST].constraint.range = &barcode_contrast_range; 2807 s->val[OPT_BARCODE_CONTRAST].w = 3; 2808 2809 /* Barcode_Patchmode */ 2810 s->opt[OPT_BARCODE_PATCHMODE].name = SANE_NAME_BARCODE_PATCHMODE; 2811 s->opt[OPT_BARCODE_PATCHMODE].title = SANE_TITLE_BARCODE_PATCHMODE; 2812 s->opt[OPT_BARCODE_PATCHMODE].desc = SANE_DESC_BARCODE_PATCHMODE; 2813 s->opt[OPT_BARCODE_PATCHMODE].type = SANE_TYPE_INT; 2814 s->opt[OPT_BARCODE_PATCHMODE].unit = SANE_UNIT_NONE; 2815 s->opt[OPT_BARCODE_PATCHMODE].constraint_type = SANE_CONSTRAINT_RANGE; 2816 s->opt[OPT_BARCODE_PATCHMODE].constraint.range = &barcode_patchmode_range; 2817 s->val[OPT_BARCODE_PATCHMODE].w = 0; 2818 2819 if (s->hw->info.canSection == SANE_FALSE) 2820 { 2821 s->opt[OPT_SECTION].cap |= SANE_CAP_INACTIVE; 2822 } 2823 2824 if (s->hw->info.canBarCode == SANE_FALSE) 2825 { 2826 s->opt[OPT_BARCODE_GROUP].cap |= SANE_CAP_INACTIVE; 2827 s->opt[OPT_BARCODE_SEARCH_BAR].cap |= SANE_CAP_INACTIVE; 2828 s->opt[OPT_BARCODE_SEARCH_COUNT].cap |= SANE_CAP_INACTIVE; 2829 s->opt[OPT_BARCODE_SEARCH_MODE].cap |= SANE_CAP_INACTIVE; 2830 s->opt[OPT_BARCODE_HMIN].cap |= SANE_CAP_INACTIVE; 2831 s->opt[OPT_BARCODE_SEARCH_TIMEOUT].cap |= SANE_CAP_INACTIVE; 2832 s->opt[OPT_BARCODE_RELMAX].cap |= SANE_CAP_INACTIVE; 2833 s->opt[OPT_BARCODE_BARMIN].cap |= SANE_CAP_INACTIVE; 2834 s->opt[OPT_BARCODE_BARMAX].cap |= SANE_CAP_INACTIVE; 2835 s->opt[OPT_BARCODE_CONTRAST].cap |= SANE_CAP_INACTIVE; 2836 s->opt[OPT_BARCODE_PATCHMODE].cap |= SANE_CAP_INACTIVE; 2837 } 2838 2839 return SANE_STATUS_GOOD; 2840} 2841 2842static SANE_Status 2843attach (const char *devnam, BH_Device ** devp) 2844{ 2845 SANE_Status status; 2846 BH_Device *dev; 2847 struct inquiry_standard_data ibuf; 2848 struct inquiry_vpd_data vbuf; 2849 struct inquiry_jis_data jbuf; 2850 size_t buf_size; 2851 int fd = -1; 2852 double mm; 2853 2854 DBG (3, "attach called\n"); 2855 2856 for (dev = first_dev; dev; dev = dev->next) 2857 { 2858 if (strcmp (dev->sane.name, devnam) == 0) 2859 { 2860 if (devp) 2861 *devp = dev; 2862 return SANE_STATUS_GOOD; 2863 } 2864 } 2865 2866#ifdef FAKE_INQUIRY 2867 if (fake_inquiry) 2868 { 2869 DBG (3, "attach: faking inquiry of %s\n", devnam); 2870 2871 memset (&ibuf, 0, sizeof (ibuf)); 2872 ibuf.devtype = 6; 2873 memcpy(ibuf.vendor, "**FAKE**", 8); 2874 memcpy(ibuf.product, "COPISCAN II 6338", 16); 2875 memcpy(ibuf.revision, "0016", 4); 2876 2877 DBG (1, "attach: reported devtype='%d', vendor='%.8s', " 2878 "product='%.16s', revision='%.4s'\n", 2879 ibuf.devtype, ibuf.vendor, 2880 ibuf.product, ibuf.revision); 2881 2882 memset (&vbuf, 0, sizeof (vbuf)); 2883 memset (&jbuf, 0, sizeof (jbuf)); 2884 } 2885 else 2886#endif 2887 { 2888 DBG (3, "attach: opening %s\n", devnam); 2889 status = sanei_scsi_open (devnam, &fd, sense_handler, NULL); 2890 if (status != SANE_STATUS_GOOD) 2891 { 2892 DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); 2893 return status; 2894 } 2895 2896 DBG (3, "attach: sending TEST_UNIT_READY\n"); 2897 status = test_unit_ready (fd); 2898 if (status != SANE_STATUS_GOOD) 2899 { 2900 DBG (1, "attach: test unit ready failed (%s)\n", 2901 sane_strstatus (status)); 2902 sanei_scsi_close (fd); 2903 return status; 2904 } 2905 2906 DBG (3, "attach: sending INQUIRY (standard data)\n"); 2907 memset (&ibuf, 0, sizeof (ibuf)); 2908 buf_size = sizeof(ibuf); 2909 status = inquiry (fd, &ibuf, &buf_size, 0, 2910 BH_INQUIRY_STANDARD_PAGE_CODE); 2911 if (status != SANE_STATUS_GOOD) 2912 { 2913 DBG (1, "attach: inquiry (standard data) failed: %s\n", 2914 sane_strstatus (status)); 2915 sanei_scsi_close (fd); 2916 return status; 2917 } 2918 2919 DBG (1, "attach: reported devtype='%d', vendor='%.8s', " 2920 "product='%.16s', revision='%.4s'\n", 2921 ibuf.devtype, ibuf.vendor, 2922 ibuf.product, ibuf.revision); 2923 2924 if (ibuf.devtype != 6 2925 || strncmp ((char *)ibuf.vendor, "B&H SCSI", 8) != 0 2926 || strncmp ((char *)ibuf.product, "COPISCAN ", 9) != 0) 2927 { 2928 DBG (1, 2929 "attach: device is not a recognized Bell and Howell scanner\n"); 2930 sanei_scsi_close (fd); 2931 return SANE_STATUS_INVAL; 2932 } 2933 2934 DBG (3, "attach: sending INQUIRY (vpd data)\n"); 2935 memset (&vbuf, 0, sizeof (vbuf)); 2936 buf_size = sizeof(vbuf); 2937 status = inquiry (fd, &vbuf, &buf_size, 1, 2938 BH_INQUIRY_VPD_PAGE_CODE); 2939 if (status != SANE_STATUS_GOOD) 2940 { 2941 DBG (1, "attach: inquiry (vpd data) failed: %s\n", 2942 sane_strstatus (status)); 2943 sanei_scsi_close (fd); 2944 return status; 2945 } 2946 2947 DBG (3, "attach: sending INQUIRY (jis data)\n"); 2948 memset (&jbuf, 0, sizeof (jbuf)); 2949 buf_size = sizeof(jbuf); 2950 status = inquiry (fd, &jbuf, &buf_size, 1, 2951 BH_INQUIRY_JIS_PAGE_CODE); 2952 if (status != SANE_STATUS_GOOD) 2953 { 2954 DBG (1, "attach: inquiry (jis data) failed: %s\n", 2955 sane_strstatus (status)); 2956 sanei_scsi_close (fd); 2957 return status; 2958 } 2959 2960 sanei_scsi_close (fd); 2961 } 2962 2963 dev = malloc (sizeof (*dev)); 2964 if (!dev) 2965 return SANE_STATUS_NO_MEM; 2966 memset (dev, 0, sizeof (*dev)); 2967 2968 2969 dev->info.devtype = ibuf.devtype; 2970 sprintf(dev->info.vendor, "%.8s", ibuf.vendor); 2971 trim_spaces(dev->info.vendor, sizeof(dev->info.vendor)); 2972 sprintf(dev->info.product, "%.16s", ibuf.product); 2973 trim_spaces(dev->info.product, sizeof(dev->info.product)); 2974 sprintf(dev->info.revision, "%.4s", ibuf.revision); 2975 trim_spaces(dev->info.revision, sizeof(dev->info.revision)); 2976 2977 dev->sane.name = strdup (devnam); 2978 dev->sane.vendor = strdup(dev->info.vendor); 2979 dev->sane.model = strdup(dev->info.product);; 2980 dev->sane.type = strdup(print_devtype(dev->info.devtype)); 2981 2982 /* set capabilities from vpd */ 2983 dev->info.canADF = vbuf.adf & 0x01; 2984 dev->info.colorBandW = vbuf.imagecomposition & 0x01; 2985 dev->info.colorHalftone = vbuf.imagecomposition & 0x02; 2986 dev->info.canWhiteFrame = vbuf.imagedataprocessing[1] & 0x01; 2987 dev->info.canBlackFrame = vbuf.imagedataprocessing[1] & 0x02; 2988 dev->info.canEdgeExtract = vbuf.imagedataprocessing[1] & 0x04; 2989 dev->info.canNoiseFilter = vbuf.imagedataprocessing[1] & 0x08; 2990 dev->info.canSmooth = vbuf.imagedataprocessing[1] & 0x10; 2991 dev->info.canLineBold = vbuf.imagedataprocessing[1] & 0x20; 2992 dev->info.comprG3_1D = vbuf.compression & 0x01; 2993 dev->info.comprG3_2D = vbuf.compression & 0x02; 2994 dev->info.comprG4 = vbuf.compression & 0x04; 2995 dev->info.canBorderRecog = vbuf.sizerecognition & 0x01; 2996 dev->info.canBarCode = vbuf.optionalfeatures & 0x01; 2997 dev->info.canIcon = vbuf.optionalfeatures & 0x02; 2998 dev->info.canSection = vbuf.optionalfeatures & 0x04; 2999 dev->info.lineMaxBytes = _2btol(vbuf.xmaxoutputbytes); 3000 3001#ifdef FAKE_INQUIRY 3002 if (fake_inquiry) 3003 { 3004 dev->info.canADF = SANE_FALSE; 3005 dev->info.colorBandW = SANE_TRUE; 3006 dev->info.colorHalftone = SANE_TRUE; 3007 dev->info.canWhiteFrame = SANE_TRUE; 3008 dev->info.canBlackFrame = SANE_TRUE; 3009 dev->info.canEdgeExtract = SANE_TRUE; 3010 dev->info.canNoiseFilter = SANE_TRUE; 3011 dev->info.canSmooth = SANE_TRUE; 3012 dev->info.canLineBold = SANE_TRUE; 3013 dev->info.comprG3_1D = SANE_TRUE; 3014 dev->info.comprG3_2D = SANE_TRUE; 3015 dev->info.comprG4 = SANE_TRUE; 3016 dev->info.canBorderRecog = SANE_TRUE; 3017 dev->info.canBarCode = SANE_TRUE; 3018 dev->info.canIcon = SANE_TRUE; 3019 dev->info.canSection = SANE_TRUE; 3020 dev->info.lineMaxBytes = 450; 3021 } 3022#endif 3023 3024 /* set capabilities from jis */ 3025 dev->info.resBasicX = _2btol(jbuf.basicxres); 3026 dev->info.resBasicY = _2btol(jbuf.basicyres); 3027 dev->info.resMaxX = _2btol(jbuf.maxxres); 3028 dev->info.resMaxY = _2btol(jbuf.maxyres); 3029 dev->info.resMinX = _2btol(jbuf.minxres); 3030 dev->info.resMinY = _2btol(jbuf.minyres); 3031 3032 /* set the length of the list to zero first, then append standard resolutions */ 3033 dev->info.resStdList[0] = 0; 3034 if (jbuf.standardres[0] & 0x80) appendStdList(&dev->info, 60); 3035 if (jbuf.standardres[0] & 0x40) appendStdList(&dev->info, 75); 3036 if (jbuf.standardres[0] & 0x20) appendStdList(&dev->info, 100); 3037 if (jbuf.standardres[0] & 0x10) appendStdList(&dev->info, 120); 3038 if (jbuf.standardres[0] & 0x08) appendStdList(&dev->info, 150); 3039 if (jbuf.standardres[0] & 0x04) appendStdList(&dev->info, 160); 3040 if (jbuf.standardres[0] & 0x02) appendStdList(&dev->info, 180); 3041 if (jbuf.standardres[0] & 0x01) appendStdList(&dev->info, 200); 3042 if (jbuf.standardres[1] & 0x80) appendStdList(&dev->info, 240); 3043 if (jbuf.standardres[1] & 0x40) appendStdList(&dev->info, 300); 3044 if (jbuf.standardres[1] & 0x20) appendStdList(&dev->info, 320); 3045 if (jbuf.standardres[1] & 0x10) appendStdList(&dev->info, 400); 3046 if (jbuf.standardres[1] & 0x08) appendStdList(&dev->info, 480); 3047 if (jbuf.standardres[1] & 0x04) appendStdList(&dev->info, 600); 3048 if (jbuf.standardres[1] & 0x02) appendStdList(&dev->info, 800); 3049 if (jbuf.standardres[1] & 0x01) appendStdList(&dev->info, 1200); 3050 if (dev->info.resStdList[0] == 0) 3051 { 3052 /* make a default standard resolutions for 200 and 300dpi */ 3053 DBG(1, "attach: no standard resolutions reported\n"); 3054 dev->info.resStdList[0] = 2; 3055 dev->info.resStdList[1] = 200; 3056 dev->info.resStdList[2] = 300; 3057 dev->info.resBasicX = dev->info.resBasicY = 300; 3058 } 3059 3060 dev->info.winWidth = _4btol(jbuf.windowwidth); 3061 dev->info.winHeight = _4btol(jbuf.windowlength); 3062 3063 if (dev->info.winWidth <= 0) 3064 { 3065 dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5); 3066 DBG(1, "attach: invalid window width reported, using %d\n", dev->info.winWidth); 3067 } 3068 if (dev->info.winHeight <= 0) 3069 { 3070 dev->info.winHeight = dev->info.resBasicY * 14; 3071 DBG(1, "attach: invalid window height reported, using %d\n", dev->info.winHeight); 3072 } 3073 3074 mm = (dev->info.resBasicX > 0) ? 3075 ((double) dev->info.winWidth / (double) dev->info.resBasicX * MM_PER_INCH) : 3076 0.0; 3077 dev->info.x_range.min = SANE_FIX(0.0); 3078 dev->info.x_range.max = SANE_FIX(mm); 3079 dev->info.x_range.quant = SANE_FIX(0.0); 3080 3081 mm = (dev->info.resBasicY > 0) ? 3082 ((double) dev->info.winHeight / (double) dev->info.resBasicY * MM_PER_INCH) : 3083 0.0; 3084 dev->info.y_range.min = SANE_FIX(0.0); 3085 dev->info.y_range.max = SANE_FIX(mm); 3086 dev->info.y_range.quant = SANE_FIX(0.0); 3087 3088 /* set additional discovered/guessed capabilities */ 3089 3090 /* if all of the ACE capabilities are present, declare it ACE capable */ 3091 dev->info.canACE = dev->info.canEdgeExtract && 3092 dev->info.canNoiseFilter && 3093 dev->info.canSmooth && 3094 dev->info.canLineBold; 3095 3096 /* if the model is known to be a duplex, declare it duplex capable */ 3097 if (strcmp(dev->info.product, "COPISCAN II 6338") == 0) 3098 { 3099 dev->info.canDuplex = SANE_TRUE; 3100 } 3101 else 3102 { 3103 dev->info.canDuplex = SANE_FALSE; 3104 } 3105 3106 /* the paper sensor requires RSC revision 1.4 or higher and an 3107 * installed feeder. NOTE: It also requires SW-4 on and the 3108 * AccufeedPlus feeder, but we cannot discover that. 3109 */ 3110 if (strcmp(dev->info.revision, "0014") >= 0) 3111 { 3112 dev->info.canCheckADF = dev->info.canADF; 3113 } 3114 else 3115 { 3116 dev->info.canCheckADF = SANE_FALSE; 3117 } 3118 3119 /* set option defaults based on inquiry information */ 3120 dev->info.res_default = dev->info.resBasicX; 3121 dev->info.autoborder_default = dev->info.canBorderRecog; 3122 dev->info.batch_default = SANE_FALSE; 3123 dev->info.deskew_default = SANE_FALSE; 3124 dev->info.check_adf_default = SANE_FALSE; 3125 dev->info.duplex_default = SANE_FALSE; 3126 dev->info.timeout_adf_default = 0; 3127 dev->info.timeout_manual_default = 0; 3128 dev->info.control_panel_default = dev->info.canACE; 3129 3130 ++num_devices; 3131 dev->next = first_dev; 3132 first_dev = dev; 3133 3134 if (devp) 3135 *devp = dev; 3136 3137 return SANE_STATUS_GOOD; 3138} 3139 3140static SANE_Status 3141attach_one(const char *devnam) 3142{ 3143 attach (devnam, NULL); 3144 return SANE_STATUS_GOOD; 3145} 3146 3147SANE_Status 3148sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) 3149{ 3150 char devnam[PATH_MAX] = "/dev/scanner"; 3151 FILE *fp; 3152 3153 (void) authorize; /* get rid of compiler warning */ 3154 3155 DBG_INIT(); 3156 DBG(3, "sane_init called\n"); 3157 DBG(1, "Bell+Howell SANE backend %d.%d build %d %s endian\n", 3158 SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, 3159 _is_host_little_endian() ? "little" : "big"); 3160 3161 if (version_code) 3162 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 3163 3164 fp = sanei_config_open(BH_CONFIG_FILE); 3165 if (fp) 3166 { 3167 char line[PATH_MAX]; 3168 const char *lp; 3169 size_t len; 3170 3171 /* read config file */ 3172 while (sanei_config_read (line, sizeof (line), fp)) 3173 { 3174 if (line[0] == '#') /* ignore line comments */ 3175 continue; 3176 len = strlen (line); 3177 3178 if (!len) 3179 continue; /* ignore empty lines */ 3180 3181 lp = sanei_config_skip_whitespace (line); 3182 3183 DBG(16, 3184 "sane_init: processing config file line '%s'\n", 3185 line); 3186 if (strncmp(lp, "option", 6) == 0 && 3187 (isspace (lp[6]) || lp[6] == '\0')) 3188 { 3189 lp += 6; 3190 lp = sanei_config_skip_whitespace (lp); 3191 3192 if (strncmp(lp, "disable-optional-frames", 23) == 0) 3193 { 3194 DBG(1, "sane_init: configuration option " 3195 "'disable-optional-frames' set\n"); 3196 disable_optional_frames = 1; 3197 } 3198 else if (strncmp(lp, "fake-inquiry", 12) == 0) 3199 { 3200 DBG(1, "sane_init: configuration option " 3201 "'fake-inquiry' set\n"); 3202 fake_inquiry = 1; 3203 } 3204 else 3205 { 3206 DBG(1, "sane_init: ignoring unknown " 3207 "configuration option '%s'\n", 3208 lp); 3209 } 3210 } 3211 else 3212 { 3213 DBG(16, 3214 "sane_init: found a device: line '%s'\n", 3215 lp); 3216 strncpy (devnam, lp, sizeof(devnam)); 3217 devnam[sizeof(devnam)-1] = '\0'; 3218 3219 sanei_config_attach_matching_devices(devnam, 3220 attach_one); 3221 } 3222 } 3223 fclose (fp); 3224 } 3225 else 3226 { 3227 /* configure the /dev/scanner device in the absence of config file */ 3228 sanei_config_attach_matching_devices ("/dev/scanner", attach_one); 3229 } 3230 3231 return SANE_STATUS_GOOD; 3232} 3233 3234SANE_Status 3235sane_get_devices (const SANE_Device ***device_list, SANE_Bool local) 3236{ 3237 BH_Device *dev; 3238 int i; 3239 DBG(3, "sane_get_devices called\n"); 3240 3241 (void) local; /* get rid of compiler warning */ 3242 if (devlist) 3243 free (devlist); 3244 devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 3245 if (!devlist) 3246 return SANE_STATUS_NO_MEM; 3247 3248 i = 0; 3249 for (dev = first_dev; dev; dev = dev->next) 3250 devlist[i++] = &dev->sane; 3251 devlist[i++] = 0; 3252 3253 *device_list = devlist; 3254 3255 return SANE_STATUS_GOOD; 3256} 3257 3258SANE_Status 3259sane_open (SANE_String_Const devnam, SANE_Handle *handle) 3260{ 3261 SANE_Status status; 3262 BH_Device *dev; 3263 BH_Scanner *s; 3264 DBG(3, "sane_open called\n"); 3265 3266 if (devnam[0] != '\0') 3267 { 3268 for (dev = first_dev; dev; dev = dev->next) 3269 { 3270 if (strcmp (dev->sane.name, devnam) == 0) 3271 break; 3272 } 3273 3274 if (!dev) 3275 { 3276 status = attach (devnam, &dev); 3277 if (status != SANE_STATUS_GOOD) 3278 return status; 3279 } 3280 } 3281 else 3282 { 3283 dev = first_dev; 3284 } 3285 3286 if (!dev) 3287 return SANE_STATUS_INVAL; 3288 3289 s = malloc (sizeof (*s)); 3290 if (!s) 3291 return SANE_STATUS_NO_MEM; 3292 memset (s, 0, sizeof (*s)); 3293 3294 s->fd = -1; 3295 s->hw = dev; 3296 3297 s->bmu = BH_UNIT_POINT; 3298 s->mud = 1; 3299 3300 ScannerDump(s); 3301 3302 init_options (s); 3303 3304 s->next = first_handle; 3305 first_handle = s; 3306 3307 /* initialize our parameters */ 3308 get_parameters(s, 0); 3309 3310 *handle = s; 3311 3312#ifdef FAKE_INQUIRY 3313 if (fake_inquiry) 3314 { 3315 DBG (1, "sane_open: faking open of %s\n", 3316 s->hw->sane.name); 3317 } 3318 else 3319#endif 3320 { 3321 status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s); 3322 if (status != SANE_STATUS_GOOD) 3323 { 3324 DBG (1, "sane_open: open of %s failed: %s\n", 3325 s->hw->sane.name, sane_strstatus (status)); 3326 return status; 3327 } 3328 } 3329 3330 return SANE_STATUS_GOOD; 3331} 3332 3333const SANE_Option_Descriptor * 3334sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 3335{ 3336 BH_Scanner *s = handle; 3337 DBG(3, "sane_get_option_descriptor called (option:%d)\n", option); 3338 3339 if ((unsigned) option >= NUM_OPTIONS) 3340 return 0; 3341 3342 return (s->opt + option); 3343} 3344 3345SANE_Status 3346sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, 3347 void *val, SANE_Word *info) 3348{ 3349 BH_Scanner *s = handle; 3350 SANE_Status status; 3351 SANE_Word cap; 3352 SANE_String_Const name; 3353 3354 DBG(3, "sane_control_option called\n"); 3355 3356 name = s->opt[option].name ? s->opt[option].name : "(nil)"; 3357 3358 if (info) 3359 *info = 0; 3360 3361 if (s->scanning && action == SANE_ACTION_SET_VALUE) 3362 return SANE_STATUS_DEVICE_BUSY; 3363 if (option >= NUM_OPTIONS) 3364 return SANE_STATUS_INVAL; 3365 3366 cap = s->opt[option].cap; 3367 if (!SANE_OPTION_IS_ACTIVE (cap)) 3368 return SANE_STATUS_INVAL; 3369 3370 if (action == SANE_ACTION_GET_VALUE) 3371 { 3372 DBG(16, "sane_control_option: get_value %s [#%d]\n", name, option); 3373 switch (option) 3374 { 3375 /* word options: */ 3376 case OPT_RESOLUTION: 3377 case OPT_TL_X: 3378 case OPT_TL_Y: 3379 case OPT_BR_X: 3380 case OPT_BR_Y: 3381 case OPT_TIMEOUT_ADF: 3382 case OPT_TIMEOUT_MANUAL: 3383 case OPT_ACE_FUNCTION: 3384 case OPT_ACE_SENSITIVITY: 3385 case OPT_BRIGHTNESS: 3386 case OPT_THRESHOLD: 3387 case OPT_CONTRAST: 3388 case OPT_ICON_WIDTH: 3389 case OPT_ICON_LENGTH: 3390 case OPT_BARCODE_SEARCH_COUNT: 3391 case OPT_BARCODE_HMIN: 3392 case OPT_BARCODE_SEARCH_TIMEOUT: 3393 case OPT_BARCODE_RELMAX: 3394 case OPT_BARCODE_BARMIN: 3395 case OPT_BARCODE_BARMAX: 3396 case OPT_BARCODE_CONTRAST: 3397 case OPT_BARCODE_PATCHMODE: 3398 case OPT_NUM_OPTS: 3399 *(SANE_Word *) val = s->val[option].w; 3400 return SANE_STATUS_GOOD; 3401 3402 /* string options: */ 3403 case OPT_INQUIRY: 3404 case OPT_SCAN_SOURCE: 3405 case OPT_SCAN_MODE: 3406 case OPT_COMPRESSION: 3407 case OPT_PAPER_SIZE: 3408 case OPT_ROTATION: 3409 case OPT_BARCODE_SEARCH_BAR: 3410 case OPT_BARCODE_SEARCH_MODE: 3411 case OPT_SECTION: 3412 strcpy (val, s->val[option].s); 3413 return SANE_STATUS_GOOD; 3414 3415 /* boolean options: */ 3416 case OPT_PREVIEW: 3417 case OPT_AUTOBORDER: 3418 case OPT_DESKEW: 3419 case OPT_BATCH: 3420 case OPT_CHECK_ADF: 3421 case OPT_DUPLEX: 3422 case OPT_CONTROL_PANEL: 3423 case OPT_NEGATIVE: 3424 *(SANE_Word *) val = s->val[option].w; 3425 return SANE_STATUS_GOOD; 3426 3427 default: 3428 DBG(1, "sane_control_option:invalid option number %d\n", option); 3429 return SANE_STATUS_INVAL; 3430 } 3431 } 3432 else if (action == SANE_ACTION_SET_VALUE) 3433 { 3434 switch (s->opt[option].type) 3435 { 3436 case SANE_TYPE_BOOL: 3437 case SANE_TYPE_INT: 3438 DBG(16, "sane_control_option: set_value %s [#%d] to %d\n", 3439 name, option, *(SANE_Word *) val); 3440 break; 3441 3442 case SANE_TYPE_FIXED: 3443 DBG(16, "sane_control_option: set_value %s [#%d] to %f\n", 3444 name, option, SANE_UNFIX(*(SANE_Word *) val)); 3445 break; 3446 3447 case SANE_TYPE_STRING: 3448 DBG(16, "sane_control_option: set_value %s [#%d] to %s\n", 3449 name, option, (char *) val); 3450 break; 3451 3452 default: 3453 DBG(16, "sane_control_option: set_value %s [#%d]\n", 3454 name, option); 3455 } 3456 3457 if (!SANE_OPTION_IS_SETTABLE (cap)) 3458 return SANE_STATUS_INVAL; 3459 3460 status = sanei_constrain_value (s->opt + option, val, info); 3461 if (status != SANE_STATUS_GOOD) 3462 return status; 3463 3464 switch (option) 3465 { 3466 /* (mostly) side-effect-free word options: */ 3467 case OPT_TL_X: 3468 case OPT_TL_Y: 3469 case OPT_BR_X: 3470 case OPT_BR_Y: 3471 /* make sure that paper-size is set to custom */ 3472 if (s->val[option].w != *(SANE_Word *) val) 3473 { 3474 if (info) *info |= SANE_INFO_RELOAD_PARAMS; 3475 3476 if (get_paper_id(_OPT_VAL_STRING(s, OPT_PAPER_SIZE)) != 0) 3477 { 3478 if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3479 3480 /* set paper size to 'custom' */ 3481 free (s->val[OPT_PAPER_SIZE].s); 3482 s->val[OPT_PAPER_SIZE].s = strdup(paper_list[0]); 3483 } 3484 } 3485 /* fall through */ 3486 case OPT_RESOLUTION: 3487 if (info && s->val[option].w != *(SANE_Word *) val) 3488 *info |= SANE_INFO_RELOAD_PARAMS; 3489 /* fall through */ 3490 case OPT_TIMEOUT_ADF: 3491 case OPT_TIMEOUT_MANUAL: 3492 case OPT_ACE_FUNCTION: 3493 case OPT_ACE_SENSITIVITY: 3494 case OPT_BRIGHTNESS: 3495 case OPT_THRESHOLD: 3496 case OPT_CONTRAST: 3497 case OPT_ICON_WIDTH: 3498 case OPT_ICON_LENGTH: 3499 case OPT_BARCODE_SEARCH_COUNT: 3500 case OPT_BARCODE_HMIN: 3501 case OPT_BARCODE_SEARCH_TIMEOUT: 3502 case OPT_BARCODE_RELMAX: 3503 case OPT_BARCODE_BARMIN: 3504 case OPT_BARCODE_BARMAX: 3505 case OPT_BARCODE_CONTRAST: 3506 case OPT_BARCODE_PATCHMODE: 3507 case OPT_NUM_OPTS: 3508 s->val[option].w = *(SANE_Word *) val; 3509 return SANE_STATUS_GOOD; 3510 3511 /* string options */ 3512 case OPT_BARCODE_SEARCH_BAR: 3513 /*!!! we're supporting only a single barcode type via the option */ 3514 s->search_bars[0] = get_barcode_id(val); 3515 /* fall through */ 3516 case OPT_SCAN_SOURCE: 3517 case OPT_COMPRESSION: 3518 case OPT_ROTATION: 3519 case OPT_BARCODE_SEARCH_MODE: 3520 case OPT_SECTION: 3521 if (s->val[option].s) 3522 free (s->val[option].s); 3523 s->val[option].s = strdup (val); 3524 return SANE_STATUS_GOOD; 3525 3526 /* boolean options: */ 3527 case OPT_AUTOBORDER: 3528 /*!!! autoborder true disables geometry controls 3529 * and sets them to defaults? 3530 */ 3531 /* fall through */ 3532 case OPT_PREVIEW: 3533 case OPT_BATCH: 3534 case OPT_DESKEW: 3535 case OPT_CHECK_ADF: 3536 case OPT_DUPLEX: 3537 case OPT_NEGATIVE: 3538 s->val[option].w = *(SANE_Word *) val; 3539 return SANE_STATUS_GOOD; 3540 3541 /* options with side effects */ 3542 case OPT_CONTROL_PANEL: 3543 /* a boolean option */ 3544 /* control-panel true enables/disables some enhancement controls */ 3545 if (s->val[option].w != *(SANE_Word *) val) 3546 { 3547 if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3548 3549 s->val[option].w = *(SANE_Word *) val; 3550 3551 if (*(SANE_Word *) val == SANE_TRUE) 3552 { 3553 if (s->hw->info.canACE == SANE_TRUE) 3554 { 3555 s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; 3556 s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; 3557 } 3558 else 3559 { 3560 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3561 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 3562 } 3563 } 3564 else 3565 { 3566 if (s->hw->info.canACE == SANE_TRUE) 3567 { 3568 s->opt[OPT_ACE_FUNCTION].cap &= ~SANE_CAP_INACTIVE; 3569 s->opt[OPT_ACE_SENSITIVITY].cap &= ~SANE_CAP_INACTIVE; 3570 } 3571 else 3572 { 3573 s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3574 s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 3575 } 3576 } 3577 } 3578 return SANE_STATUS_GOOD; 3579 3580 case OPT_SCAN_MODE: 3581 /* a string option */ 3582 /* scan mode != lineart disables compression, setting it to 3583 * 'none' 3584 */ 3585 if (strcmp (s->val[option].s, (SANE_String) val)) 3586 { 3587 if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3588 if (get_scan_mode_id((SANE_String) val) != 0) 3589 { 3590 /* scan mode is not lineart, disable compression 3591 * and set compression to 'none' 3592 */ 3593 s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; 3594 if (s->val[OPT_COMPRESSION].s && 3595 get_compression_id(s->val[OPT_COMPRESSION].s) != 0) 3596 { 3597 free (s->val[OPT_COMPRESSION].s); 3598 s->val[OPT_COMPRESSION].s = strdup(compression_list[0]); 3599 } 3600 } 3601 else 3602 { 3603 /* scan mode is lineart, enable compression */ 3604 s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE; 3605 } 3606 free (s->val[option].s); 3607 s->val[option].s = strdup (val); 3608 } 3609 return SANE_STATUS_GOOD; 3610 3611 case OPT_PAPER_SIZE: 3612 /* a string option */ 3613 /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */ 3614 if (strcmp (s->val[option].s, (SANE_String) val)) 3615 { 3616 SANE_Int paper_id = get_paper_id((SANE_String) val); 3617 3618 /* paper_id 0 is a special case (custom) that 3619 * disables the paper size control of geometry 3620 */ 3621 if (paper_id != 0) 3622 { 3623 double left, x_max, y_max, x, y; 3624 3625 x_max = SANE_UNFIX(s->hw->info.x_range.max); 3626 y_max = SANE_UNFIX(s->hw->info.y_range.max); 3627 /* a dimension of 0.0 (or less) is replaced with the max value */ 3628 x = (paper_sizes[paper_id].width <= 0.0) ? x_max : 3629 paper_sizes[paper_id].width; 3630 y = (paper_sizes[paper_id].length <= 0.0) ? y_max : 3631 paper_sizes[paper_id].length; 3632 3633 if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 3634 3635 /* set geometry options based on paper size */ 3636 /* set geometry options based on paper size */ 3637 if (s->hw->info.canADF) 3638 { 3639 /* when the feeder is used the paper is centered in the 3640 * hopper; with the manual feed it is aligned left. 3641 */ 3642 left = (x_max - x) / 2.0; 3643 if (left < 0.0) left = 0.0; 3644 } 3645 else 3646 { 3647 left = 0.0; 3648 } 3649 3650 s->val[OPT_TL_X].w = SANE_FIX(left); 3651 s->val[OPT_TL_Y].w = SANE_FIX(0.0); 3652 s->val[OPT_BR_X].w = SANE_FIX(MIN(x + left, x_max)); 3653 s->val[OPT_BR_Y].w = SANE_FIX(MIN(y, y_max)); 3654 } 3655 free (s->val[option].s); 3656 s->val[option].s = strdup (val); 3657 } 3658 return SANE_STATUS_GOOD; 3659 3660 default: 3661 DBG(1, "sane_control_option:invalid option number %d\n", option); 3662 return SANE_STATUS_INVAL; 3663 } 3664 } 3665 3666 return SANE_STATUS_INVAL; 3667} 3668 3669SANE_Status 3670sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) 3671{ 3672 BH_Scanner *s = handle; 3673 SANE_Int status = SANE_STATUS_GOOD; 3674 3675 DBG(3, "sane_get_parameters called\n"); 3676 3677 if (params) 3678 { 3679 SANE_Int res; 3680 3681 if (!s->scanning) 3682 { 3683 /* update our parameters ONLY if we're not scanning */ 3684 status = get_parameters(s, 0); 3685 } 3686 3687 *params = s->params; 3688 3689 res = _OPT_VAL_WORD(s, OPT_RESOLUTION); 3690 3691 DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " 3692 "lines=%d, dpi=%d\n", 3693 (int) s->params.format, 3694 s->params.pixels_per_line, 3695 s->params.bytes_per_line, 3696 s->params.lines, 3697 res); 3698 } 3699 3700 return status; 3701} 3702 3703SANE_Status 3704sane_start (SANE_Handle handle) 3705{ 3706 BH_Scanner *s = handle; 3707 SANE_Status status; 3708 3709 DBG(3, "sane_start called\n"); 3710 s->cancelled = SANE_FALSE; 3711 3712 if (s->scanning == SANE_FALSE) 3713 { 3714 /* get preliminary parameters */ 3715 status = get_parameters (s, 0); 3716 if (status != SANE_STATUS_GOOD) 3717 { 3718 DBG (1, "sane_start: get_parameters failed: %s\n", 3719 sane_strstatus (status)); 3720 return status; 3721 } 3722 3723 /* Do the setup once per 'batch'. The SANE standard requires the 3724 * frontend to call sane_cancel once all desired frames have been 3725 * acquired. That is when scanning is set back to SANE_FALSE and 3726 * the 'batch' is considered done. 3727 */ 3728 status = start_setup (s); 3729 if (status != SANE_STATUS_GOOD) 3730 { 3731 DBG (1, "sane_start: start_setup failed: %s\n", 3732 sane_strstatus (status)); 3733 return status; 3734 } 3735 } 3736 3737 status = start_scan (s); 3738 if (status != SANE_STATUS_GOOD) 3739 { 3740 DBG (1, "sane_start: start_scan failed: %s\n", 3741 sane_strstatus (status)); 3742 return status; 3743 } 3744 3745 return SANE_STATUS_GOOD; 3746} 3747 3748SANE_Status 3749sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) 3750{ 3751 BH_Scanner *s = handle; 3752 SANE_Status status; 3753 size_t nread; 3754 3755 DBG(3, "sane_read called\n"); 3756 3757 *len = 0; 3758 3759 if (s->cancelled) { 3760 DBG (3, "sane_read: cancelled!\n"); 3761 return SANE_STATUS_CANCELLED; 3762 } 3763 3764 if (!s->scanning) { 3765 DBG (3, "sane_read: scanning is false!\n"); 3766 sane_cancel(s); 3767 return SANE_STATUS_CANCELLED; 3768 } 3769 3770 nread = maxlen; 3771 3772 DBG (3, "sane_read: request %lu bytes\n", (u_long) nread); 3773 /* set InvalidBytes to 0 before read; sense_handler will set it 3774 * to non-zero if we do the last partial read. 3775 */ 3776 s->InvalidBytes = 0; 3777 status = read_data (s, buf, &nread); 3778 if (status != SANE_STATUS_GOOD) 3779 { 3780 DBG (1, "sane_read: read_data failed %s\n", 3781 sane_strstatus(status)); 3782 sane_cancel (s); 3783 return status; 3784 } 3785 nread = maxlen - s->InvalidBytes; 3786 DBG (3, "sane_read: got %lu bytes\n", (u_long) nread); 3787 *len = nread; 3788 3789 return (maxlen != 0 && nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_GOOD; 3790} 3791 3792SANE_Status 3793sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 3794{ 3795#ifdef NONBLOCKSUPPORTED 3796 BH_Scanner *s = handle; 3797#endif 3798 DBG(3, "sane_set_io_mode called: non_blocking=%d\n", non_blocking); 3799 3800#ifdef NONBLOCKSUPPORTED 3801 if (s->fd < 0) 3802 { 3803 return SANE_STATUS_INVAL; 3804 } 3805 3806 if (fcntl (s->fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) 3807 { 3808 DBG(1, "sane_set_io_mode: error setting io mode\n"); 3809 return SANE_STATUS_IO_ERROR; 3810 } 3811 3812 return SANE_STATUS_GOOD; 3813#else 3814 (void) handle; /* get rid of compiler warning */ 3815 return (non_blocking == 1) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; 3816#endif 3817} 3818 3819SANE_Status 3820sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) 3821{ 3822#ifdef NONBLOCKSUPPORTED 3823 BH_Scanner *s = handle; 3824#endif 3825 DBG(3, "sane_get_select_fd called\n"); 3826 3827#ifdef NONBLOCKSUPPORTED 3828 if (s->fd < 0) 3829 { 3830 return SANE_STATUS_INVAL; 3831 } 3832 *fd = s->fd; 3833 3834 return SANE_STATUS_GOOD; 3835#else 3836 (void) handle; (void) fd; /* get rid of compiler warning */ 3837 return SANE_STATUS_UNSUPPORTED; 3838#endif 3839} 3840 3841void 3842sane_cancel (SANE_Handle handle) 3843{ 3844 BH_Scanner *s = (BH_Scanner *) handle; 3845 DBG(3, "sane_cancel called\n"); 3846 if (s->scanning) 3847 { 3848 /* if batchmode is enabled, then call set_window to 3849 * abort the batch 3850 */ 3851 if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) 3852 { 3853 DBG(5, "sane_cancel: calling set_window to abort batch\n"); 3854 set_window(s, BH_BATCH_ABORT); 3855 } 3856 } 3857 s->scanning = SANE_FALSE; 3858 s->cancelled = SANE_TRUE; 3859} 3860 3861void 3862sane_close (SANE_Handle handle) 3863{ 3864 BH_Scanner *s = (BH_Scanner *) handle; 3865 DBG(3, "sane_close called\n"); 3866 3867 if (s->fd != -1) 3868 sanei_scsi_close (s->fd); 3869 s->fd = -1; 3870 free (s); 3871} 3872 3873void 3874sane_exit (void) 3875{ 3876 BH_Device *dev, *next; 3877 DBG(3, "sane_exit called\n"); 3878 3879 for (dev = first_dev; dev; dev = next) 3880 { 3881 next = dev->next; 3882 free (dev); 3883 } 3884 3885 if (devlist) 3886 free (devlist); 3887} 3888