1 /* $NetBSD: ss_mustek.c,v 1.9 1997/10/18 19:51:10 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Joachim Koenig-Baltes. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Joachim Koenig-Baltes. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * special driver for MUSTEK flatbed scanners MFS 06000CX and MFS 12000CX 34 * these scanners come with their own scsi card, containing an NCR53C400 35 * SCSI controller chip. I'm in the progress of writing a driver for this 36 * card to work under NetBSD-current. I've hooked it up to a Seagate ST01 37 * hostadapter in the meantime, giving 350KB/sec for higher resolutions! 38 * 39 * I tried to connect it to my Adaptec 1542B, but with no success. It seems, 40 * it does not like synchronous negotiation between Hostadapter and other 41 * targets, but I could not turn this off for the 1542B. 42 * 43 * There is also an other reason why you would not like to connect it to your 44 * favourite SCSI host adapter: The Mustek DOES NOT DISCONNECT. It will block 45 * other traffic from the bus while a transfer is active. 46 */ 47 48 #include <sys/types.h> 49 #include <sys/param.h> 50 #include <sys/kernel.h> 51 #include <sys/systm.h> 52 #include <sys/fcntl.h> 53 #include <sys/errno.h> 54 #include <sys/ioctl.h> 55 #include <sys/malloc.h> 56 #include <sys/buf.h> 57 #include <sys/proc.h> 58 #include <sys/user.h> 59 #include <sys/device.h> 60 #include <sys/conf.h> /* for cdevsw */ 61 #include <sys/scanio.h> 62 63 #include <dev/scsipi/scsi_all.h> 64 #include <dev/scsipi/scsipi_all.h> 65 #include <dev/scsipi/scsi_scanner.h> 66 #include <dev/scsipi/scsiconf.h> 67 #include <dev/scsipi/ssvar.h> 68 #include <dev/scsipi/ss_mustek.h> 69 70 #define MUSTEK_RETRIES 4 71 72 int mustek_get_params __P((struct ss_softc *)); 73 int mustek_set_params __P((struct ss_softc *, struct scan_io *)); 74 int mustek_trigger_scanner __P((struct ss_softc *)); 75 void mustek_minphys __P((struct ss_softc *, struct buf *)); 76 int mustek_read __P((struct ss_softc *, struct buf *)); 77 int mustek_rewind_scanner __P((struct ss_softc *)); 78 79 /* only used internally */ 80 int mustek_get_status __P((struct ss_softc *, int, int)); 81 void mustek_compute_sizes __P((struct ss_softc *)); 82 83 /* 84 * structure for the special handlers 85 */ 86 struct ss_special mustek_special = { 87 mustek_set_params, 88 mustek_trigger_scanner, 89 mustek_get_params, 90 mustek_minphys, 91 mustek_read, 92 mustek_rewind_scanner, 93 NULL, /* no adf support right now */ 94 NULL /* no adf support right now */ 95 }; 96 97 /* 98 * mustek_attach: attach special functions to ss 99 */ 100 void 101 mustek_attach(ss, sa) 102 struct ss_softc *ss; 103 struct scsipibus_attach_args *sa; 104 { 105 #ifdef SCSIDEBUG 106 struct scsipi_link *sc_link = sa->sa_sc_link; 107 #endif 108 109 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_attach: start\n")); 110 ss->sio.scan_scanner_type = 0; 111 112 printf("\n%s: ", ss->sc_dev.dv_xname); 113 114 /* first, check the model which determines resolutions */ 115 if (!bcmp(sa->sa_inqbuf.product, "MFS-06000CX", 11)) { 116 ss->sio.scan_scanner_type = MUSTEK_06000CX; 117 printf("Mustek 6000CX Flatbed 3-pass color scanner, 3 - 600 dpi\n"); 118 } 119 if (!bcmp(sa->sa_inqbuf.product, "MFS-12000CX", 11)) { 120 ss->sio.scan_scanner_type = MUSTEK_12000CX; 121 printf("Mustek 12000CX Flatbed 3-pass color scanner, 6 - 1200 dpi\n"); 122 } 123 124 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_attach: scanner_type = %d\n", 125 ss->sio.scan_scanner_type)); 126 127 /* install special handlers */ 128 ss->special = &mustek_special; 129 130 /* 131 * populate the scanio struct with legal values 132 * the default should come from user space 133 */ 134 ss->sio.scan_width = 1200; 135 ss->sio.scan_height = 1200; 136 ss->sio.scan_x_resolution = 99; 137 ss->sio.scan_y_resolution = 99; 138 ss->sio.scan_x_origin = 0; 139 ss->sio.scan_y_origin = 0; 140 ss->sio.scan_brightness = 100; 141 ss->sio.scan_contrast = 100; 142 ss->sio.scan_quality = 100; 143 ss->sio.scan_image_mode = SIM_GRAYSCALE; 144 145 mustek_compute_sizes(ss); 146 } 147 148 int 149 mustek_get_params (ss) 150 struct ss_softc *ss; 151 { 152 153 return (0); 154 } 155 156 /* 157 * check the parameters if the mustek is capable of fulfilling it 158 * but don't send the command to the scanner in case the user wants 159 * to change parameters by more than one call 160 */ 161 int 162 mustek_set_params(ss, sio) 163 struct ss_softc *ss; 164 struct scan_io *sio; 165 { 166 int error; 167 168 /* 169 * if the scanner is triggered, then rewind it 170 */ 171 if (ss->flags & SSF_TRIGGERED) { 172 error = mustek_rewind_scanner(ss); 173 if (error) 174 return (error); 175 } 176 177 /* size constraints: 8.5" horizontally and 14" vertically */ 178 #ifdef MUSTEK_INCH_SPEC 179 /* sizes must be a multiple of 1/8" */ 180 sio->scan_x_origin -= sio->scan_x_origin % 150; 181 sio->scan_y_origin -= sio->scan_y_origin % 150; 182 sio->scan_width -= sio->scan_width % 150; 183 sio->scan_height -= sio->scan_height % 150; 184 #endif 185 if (sio->scan_width == 0 || 186 sio->scan_x_origin + sio->scan_width > 10200 || 187 sio->scan_height == 0 || 188 sio->scan_y_origin + sio->scan_height > 16800) 189 return (EINVAL); 190 191 /* 192 * for now, only realize the values for the MUSTEK_06000CX 193 * in the future, values for the MUSTEK_12000CX will be implemented 194 */ 195 196 /* 197 * resolution (dpi) must be <= 300 and a multiple of 3 or 198 * between 300 and 600 and a multiple of 30 199 */ 200 sio->scan_x_resolution -= sio->scan_x_resolution <= 300 ? 201 sio->scan_x_resolution % 3 : sio->scan_x_resolution % 30; 202 sio->scan_y_resolution -= sio->scan_y_resolution <= 300 ? 203 sio->scan_y_resolution % 3 : sio->scan_y_resolution % 30; 204 if (sio->scan_x_resolution < 3 || sio->scan_x_resolution > 600 || 205 sio->scan_x_resolution != sio->scan_y_resolution) 206 return (EINVAL); 207 208 /* assume brightness values are between 64 and 136 in steps of 3 */ 209 sio->scan_brightness -= (sio->scan_brightness - 64) % 3; 210 if (sio->scan_brightness < 64 || sio->scan_brightness > 136) 211 return (EINVAL); 212 213 /* contrast values must be between 16 and 184 in steps of 7 */ 214 sio->scan_contrast -= (sio->scan_contrast - 16) % 7; 215 if (sio->scan_contrast < 16 || sio->scan_contrast > 184) 216 return (EINVAL); 217 218 /* 219 * velocity: between 0 (fast) and 4 (slow) which will be mapped 220 * to 100% = 4, 80% = 3, 60% = 2, 40% = 1, 20% = 0 221 * must be a multiple of 20 222 */ 223 sio->scan_quality -= sio->scan_quality % 20; 224 if (sio->scan_quality < 20 || sio->scan_quality > 100) 225 return (EINVAL); 226 227 switch (sio->scan_image_mode) { 228 case SIM_BINARY_MONOCHROME: 229 case SIM_DITHERED_MONOCHROME: 230 case SIM_GRAYSCALE: 231 case SIM_RED: 232 case SIM_GREEN: 233 case SIM_BLUE: 234 break; 235 default: 236 return (EINVAL); 237 } 238 239 /* change ss_softc to the new values, but save ro-variables */ 240 sio->scan_scanner_type = ss->sio.scan_scanner_type; 241 bcopy(sio, &ss->sio, sizeof(struct scan_io)); 242 243 mustek_compute_sizes(ss); 244 245 return (0); 246 } 247 248 /* 249 * trim the requested transfer to a multiple of the line size 250 * this is called only from ssread() which guarantees, scanner is triggered 251 * In the future, it will trim the transfer to not read to much at a time 252 * because the mustek cannot disconnect. It will be calculated by the 253 * resolution, the velocity and the number of bytes per line. 254 */ 255 void 256 mustek_minphys(ss, bp) 257 struct ss_softc *ss; 258 struct buf *bp; 259 { 260 #ifdef SCSIDEBUG 261 struct scsipi_link *sc_link = ss->sc_link; 262 #endif 263 264 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_minphys: before: %ld\n", 265 bp->b_bcount)); 266 bp->b_bcount -= bp->b_bcount % 267 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8); 268 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_minphys: after: %ld\n", 269 bp->b_bcount)); 270 } 271 272 /* 273 * trigger the scanner to start a scan operation 274 * this includes sending the mode- and window-data, starting the scanner 275 * and getting the image size info 276 */ 277 int 278 mustek_trigger_scanner(ss) 279 struct ss_softc *ss; 280 { 281 struct mustek_mode_select_cmd mode_cmd; 282 struct mustek_mode_select_data mode_data; 283 struct mustek_set_window_cmd window_cmd; 284 struct mustek_set_window_data window_data; 285 struct mustek_start_scan_cmd start_scan_cmd; 286 struct scsipi_link *sc_link = ss->sc_link; 287 int pixel_tlx, pixel_tly, pixel_brx, pixel_bry, paperlength; 288 int error; 289 290 mustek_compute_sizes(ss); 291 292 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner\n")); 293 294 /* 295 * set the window params and send the scsi command 296 */ 297 bzero(&window_cmd, sizeof(window_cmd)); 298 window_cmd.opcode = MUSTEK_SET_WINDOW; 299 window_cmd.length = sizeof(window_data); 300 301 bzero(&window_data, sizeof(window_data)); 302 window_data.frame.header = MUSTEK_LINEART_BACKGROUND | MUSTEK_UNIT_SPEC; 303 #ifdef MUSTEK_INCH_SPEC 304 /* the positional values are all 1 byte because 256 / 8 = 32" */ 305 pixel_tlx = ss->sio.scan_x_origin / 150; 306 pixel_tly = ss->sio.scan_y_origin / 150; 307 pixel_brx = pixel_tlx + ss->sio.scan_width / 150; 308 pixel_bry = pixel_tly + ss->sio.scan_height / 150; 309 #else 310 pixel_tlx = (ss->sio.scan_x_origin * ss->sio.scan_x_resolution) / 1200; 311 pixel_tly = (ss->sio.scan_y_origin * ss->sio.scan_y_resolution) / 1200; 312 pixel_brx = pixel_tlx + 313 (ss->sio.scan_width * ss->sio.scan_x_resolution) / 1200; 314 pixel_bry = pixel_tly + 315 (ss->sio.scan_height * ss->sio.scan_y_resolution) / 1200; 316 #endif 317 _lto2l(pixel_tlx, window_data.frame.tl_x); 318 _lto2l(pixel_tly, window_data.frame.tl_y); 319 _lto2l(pixel_brx, window_data.frame.br_x); 320 _lto2l(pixel_bry, window_data.frame.br_y); 321 322 #if MUSTEK_WINDOWS >= 1 323 window_data.window1 = window_data.frame; 324 window_data.window1.header = MUSTEK_WINDOW_MASK | MUSTEK_UNIT_SPEC; 325 #endif 326 327 /* send the set window command to the scanner */ 328 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_set_parms: set_window\n")); 329 error = scsipi_command(sc_link, 330 (struct scsipi_generic *) &window_cmd, 331 sizeof(window_cmd), (u_char *) &window_data, sizeof(window_data), 332 MUSTEK_RETRIES, 5000, NULL, SCSI_DATA_OUT); 333 if (error) 334 return (error); 335 336 /* 337 * do what it takes to actualize the mode 338 */ 339 bzero(&mode_cmd, sizeof(mode_cmd)); 340 mode_cmd.opcode = MUSTEK_MODE_SELECT; 341 _lto2b(sizeof(mode_data), mode_cmd.length); 342 343 bzero(&mode_data, sizeof(mode_data)); 344 mode_data.mode = 345 MUSTEK_MODE_MASK | MUSTEK_HT_PATTERN_BUILTIN | MUSTEK_UNIT_SPEC; 346 if (ss->sio.scan_x_resolution <= 300) { 347 mode_data.resolution = ss->sio.scan_x_resolution / 3; 348 } else { 349 /* 350 * the resolution values is computed by modulo 100, but not 351 * for 600dpi, where the value is 100 (a bit tricky, but ...) 352 */ 353 mode_data.resolution = 354 ((ss->sio.scan_x_resolution - 1) % 100) + 1; 355 } 356 mode_data.brightness = (ss->sio.scan_brightness - 64) / 3; 357 mode_data.contrast = (ss->sio.scan_contrast - 16) / 7; 358 mode_data.grain = 0; 359 mode_data.velocity = ss->sio.scan_quality / 20 - 1; 360 #ifdef MUSTEK_INCH_SPEC 361 paperlength = 14 * 8; /* 14" */ 362 #else 363 paperlength = 14 * ss->sio.scan_y_resolution; /* 14" */ 364 #endif 365 _lto2l(paperlength, mode_data.paperlength); 366 367 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: mode_select\n")); 368 /* send the command to the scanner */ 369 error = scsipi_command(sc_link, 370 (struct scsipi_generic *) &mode_cmd, 371 sizeof(mode_cmd), (u_char *) &mode_data, sizeof(mode_data), 372 MUSTEK_RETRIES, 5000, NULL, SCSI_DATA_OUT); 373 if (error) 374 return (error); 375 376 /* 377 * now construct and send the start command 378 */ 379 bzero(&start_scan_cmd,sizeof(start_scan_cmd)); 380 start_scan_cmd.opcode = MUSTEK_START_STOP; 381 start_scan_cmd.mode = MUSTEK_SCAN_START; 382 if (ss->sio.scan_x_resolution <= 300) 383 start_scan_cmd.mode |= MUSTEK_RES_STEP_1; 384 else 385 start_scan_cmd.mode |= MUSTEK_RES_STEP_10; 386 switch (ss->sio.scan_image_mode) { 387 case SIM_BINARY_MONOCHROME: 388 case SIM_DITHERED_MONOCHROME: 389 start_scan_cmd.mode |= MUSTEK_BIT_MODE | MUSTEK_GRAY_FILTER; 390 break; 391 case SIM_GRAYSCALE: 392 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GRAY_FILTER; 393 break; 394 case SIM_RED: 395 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_RED_FILTER; 396 break; 397 case SIM_GREEN: 398 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_GREEN_FILTER; 399 break; 400 case SIM_BLUE: 401 start_scan_cmd.mode |= MUSTEK_GRAY_MODE | MUSTEK_BLUE_FILTER; 402 break; 403 } 404 405 /* send the command to the scanner */ 406 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: start_scan\n")); 407 error = scsipi_command(sc_link, 408 (struct scsipi_generic *) &start_scan_cmd, 409 sizeof(start_scan_cmd), NULL, 0, 410 MUSTEK_RETRIES, 5000, NULL, 0); 411 if (error) 412 return (error); 413 414 /* 415 * now check if scanner ready this time with update of size info 416 * we wait here so that if the user issues a read directly afterwards, 417 * the scanner will respond directly (otherwise we had to sleep with 418 * a buffer locked in memory) 419 */ 420 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_trigger_scanner: get_status\n")); 421 error = mustek_get_status(ss, 60, 1); 422 if (error) 423 return (error); 424 425 return (0); 426 } 427 428 /* 429 * stop a scan operation in progress 430 */ 431 int 432 mustek_rewind_scanner(ss) 433 struct ss_softc *ss; 434 { 435 struct mustek_start_scan_cmd cmd; 436 struct scsipi_link *sc_link = ss->sc_link; 437 int error; 438 439 if (ss->sio.scan_window_size != 0) { 440 /* 441 * only if not all data has been read, the scanner has to be 442 * stopped 443 */ 444 bzero(&cmd, sizeof(cmd)); 445 cmd.opcode = MUSTEK_START_STOP; 446 cmd.mode = MUSTEK_SCAN_STOP; 447 448 /* send the command to the scanner */ 449 SC_DEBUG(sc_link, SDEV_DB1, 450 ("mustek_rewind_scanner: stop_scan\n")); 451 error = scsipi_command(sc_link, 452 (struct scsipi_generic *) &cmd, 453 sizeof(cmd), NULL, 0, MUSTEK_RETRIES, 5000, NULL, 0); 454 if (error) 455 return (error); 456 } 457 458 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_rewind_scanner: end\n")); 459 460 return (0); 461 } 462 463 /* 464 * read the requested number of bytes/lines from the scanner 465 */ 466 int 467 mustek_read(ss, bp) 468 struct ss_softc *ss; 469 struct buf *bp; 470 { 471 struct mustek_read_cmd cmd; 472 struct scsipi_link *sc_link = ss->sc_link; 473 u_long lines_to_read; 474 475 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_read: start\n")); 476 477 bzero(&cmd, sizeof(cmd)); 478 cmd.opcode = MUSTEK_READ; 479 480 /* instead of the bytes, the mustek wants the number of lines */ 481 lines_to_read = bp->b_bcount / 482 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8); 483 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_read: read %ld lines\n", 484 lines_to_read)); 485 _lto3b(lines_to_read, cmd.length); 486 487 /* 488 * go ask the adapter to do all this for us 489 */ 490 if (scsipi_command(sc_link, 491 (struct scsipi_generic *) &cmd, sizeof(cmd), 492 (u_char *) bp->b_data, bp->b_bcount, MUSTEK_RETRIES, 10000, bp, 493 SCSI_NOSLEEP | SCSI_DATA_IN) != SUCCESSFULLY_QUEUED) 494 printf("%s: not queued\n", ss->sc_dev.dv_xname); 495 else { 496 ss->sio.scan_lines -= lines_to_read; 497 ss->sio.scan_window_size -= bp->b_bcount; 498 } 499 500 return (0); 501 } 502 503 /* 504 * check if the scanner is ready to take commands 505 * wait timeout seconds and try only every second 506 * if update, then update picture size info 507 * 508 * returns EBUSY if scanner not ready 509 */ 510 int 511 mustek_get_status(ss, timeout, update) 512 struct ss_softc *ss; 513 int timeout, update; 514 { 515 struct mustek_get_status_cmd cmd; 516 struct mustek_get_status_data data; 517 struct scsipi_link *sc_link = ss->sc_link; 518 int error, lines, bytes_per_line; 519 520 bzero(&cmd, sizeof(cmd)); 521 cmd.opcode = MUSTEK_GET_STATUS; 522 cmd.length = sizeof(data); 523 524 while (1) { 525 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_get_status: stat_cmd\n")); 526 error = scsipi_command(sc_link, 527 (struct scsipi_generic *) &cmd, sizeof(cmd), 528 (u_char *) &data, sizeof(data), MUSTEK_RETRIES, 529 5000, NULL, SCSI_DATA_IN); 530 if (error) 531 return (error); 532 if ((data.ready_busy == MUSTEK_READY) || 533 (timeout-- <= 0)) 534 break; 535 /* please wait a second */ 536 tsleep((caddr_t)mustek_get_status, PRIBIO + 1, "mtkrdy", hz); 537 } 538 539 if (update) { 540 bytes_per_line = _2ltol(data.bytes_per_line); 541 lines = _3ltol(data.lines); 542 if (lines != ss->sio.scan_lines) { 543 printf("mustek: lines actual(%d) != computed(%ld)\n", 544 lines, ss->sio.scan_lines); 545 return (EIO); 546 } 547 if (bytes_per_line * lines != ss->sio.scan_window_size) { 548 printf("mustek: win-size actual(%d) != computed(%ld)\n", 549 bytes_per_line * lines, ss->sio.scan_window_size); 550 return (EIO); 551 } 552 553 SC_DEBUG(sc_link, SDEV_DB1, 554 ("mustek_get_size: bpl=%ld, lines=%ld\n", 555 (ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8, 556 ss->sio.scan_lines)); 557 SC_DEBUG(sc_link, SDEV_DB1, ("window size = %ld\n", 558 ss->sio.scan_window_size)); 559 } 560 561 SC_DEBUG(sc_link, SDEV_DB1, ("mustek_get_status: end\n")); 562 if (data.ready_busy == MUSTEK_READY) 563 return (0); 564 else 565 return (EBUSY); 566 } 567 568 /* 569 * mustek_compute_sizes: compute window_size and lines for the picture 570 * this function is called from different places in the code 571 */ 572 void 573 mustek_compute_sizes(ss) 574 struct ss_softc *ss; 575 { 576 577 switch (ss->sio.scan_image_mode) { 578 case SIM_BINARY_MONOCHROME: 579 case SIM_DITHERED_MONOCHROME: 580 ss->sio.scan_bits_per_pixel = 1; 581 break; 582 case SIM_GRAYSCALE: 583 case SIM_RED: 584 case SIM_GREEN: 585 case SIM_BLUE: 586 ss->sio.scan_bits_per_pixel = 8; 587 break; 588 } 589 590 /* 591 * horizontal number of bytes is always a multiple of 2, 592 * in 8-bit mode at least 593 */ 594 ss->sio.scan_pixels_per_line = 595 (ss->sio.scan_width * ss->sio.scan_x_resolution) / 1200; 596 if (ss->sio.scan_bits_per_pixel == 1) 597 /* make it a multiple of 16, and thus of 2 bytes */ 598 ss->sio.scan_pixels_per_line = 599 (ss->sio.scan_pixels_per_line + 15) & 0xfffffff0; 600 else 601 ss->sio.scan_pixels_per_line = 602 (ss->sio.scan_pixels_per_line + 1) & 0xfffffffe; 603 604 ss->sio.scan_lines = 605 (ss->sio.scan_height * ss->sio.scan_y_resolution) / 1200; 606 ss->sio.scan_window_size = ss->sio.scan_lines * 607 ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8); 608 } 609