[BACK]Return to ss_scanjet.c CVS log [TXT][DIR] Up to [local] / sys / scsi

Annotation of sys/scsi/ss_scanjet.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ss_scanjet.c,v 1.31 2007/06/01 20:59:04 moritz Exp $  */
        !             2: /*     $NetBSD: ss_scanjet.c,v 1.6 1996/05/18 22:58:01 christos Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Kenneth Stailey.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *      This product includes software developed by Kenneth Stailey.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * special functions for the HP ScanJet IIc and IIcx
        !            35:  */
        !            36:
        !            37: #include <sys/types.h>
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/fcntl.h>
        !            41: #include <sys/errno.h>
        !            42: #include <sys/ioctl.h>
        !            43: #include <sys/malloc.h>
        !            44: #include <sys/buf.h>
        !            45: #include <sys/proc.h>
        !            46: #include <sys/user.h>
        !            47: #include <sys/device.h>
        !            48: #include <sys/conf.h>          /* for cdevsw */
        !            49: #include <sys/scanio.h>
        !            50:
        !            51: #include <scsi/scsi_all.h>
        !            52: #include <scsi/scsi_scanner.h>
        !            53: #include <scsi/scsiconf.h>
        !            54: #include <scsi/ssvar.h>
        !            55:
        !            56: #define SCANJET_RETRIES 4
        !            57:
        !            58: int scanjet_set_params(struct ss_softc *, struct scan_io *);
        !            59: int scanjet_trigger_scanner(struct ss_softc *);
        !            60: int scanjet_read(struct ss_softc *, struct buf *);
        !            61:
        !            62: /* only used internally */
        !            63: int scanjet_ctl_write(struct ss_softc *, char *, u_int, int);
        !            64: int scanjet_ctl_read(struct ss_softc *, char *, u_int, int);
        !            65: int scanjet_set_window(struct ss_softc *, int);
        !            66: int scanjet_compute_sizes(struct ss_softc *, int);
        !            67: /* Maybe move to libkern? */
        !            68: #define atoi local_atoi
        !            69: __inline static int atoi(const char *);
        !            70:
        !            71:
        !            72: /*
        !            73:  * structure for the special handlers
        !            74:  */
        !            75: struct ss_special scanjet_special = {
        !            76:        scanjet_set_params,
        !            77:        scanjet_trigger_scanner,
        !            78:        NULL,
        !            79:        NULL,                   /* no special minphys */
        !            80:        scanjet_read,           /* scsi 6-byte read */
        !            81:        NULL,                   /* no "rewind" code (yet?) */
        !            82:        NULL,                   /* no adf support right now */
        !            83:        NULL                    /* no adf support right now */
        !            84: };
        !            85:
        !            86: /*
        !            87:  * scanjet_attach: attach special functions to ss
        !            88:  */
        !            89: void
        !            90: scanjet_attach(ss, sa)
        !            91:        struct ss_softc *ss;
        !            92:        struct scsi_attach_args *sa;
        !            93: {
        !            94: #ifdef SCSIDEBUG
        !            95:        struct scsi_link *sc_link = sa->sa_sc_link;
        !            96: #endif
        !            97:        int error;
        !            98:
        !            99:        SC_DEBUG(sc_link, SDEV_DB1, ("scanjet_attach: start\n"));
        !           100:        ss->sio.scan_scanner_type = 0;
        !           101:
        !           102:        printf("\n%s: ", ss->sc_dev.dv_xname);
        !           103:
        !           104:        /* first, check the model (which determines nothing yet) */
        !           105:
        !           106:        if (!bcmp(sa->sa_inqbuf->product, "C1750A", 6)) {
        !           107:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           108:                printf("HP ScanJet IIc");
        !           109:        }
        !           110:        /* The IIp is a grayscale-only HP SCL scanner */
        !           111:        if (!bcmp(sa->sa_inqbuf->product, "C1790A", 6)) {
        !           112:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           113:                printf("HP ScanJet IIp");
        !           114:        }
        !           115:        if (!bcmp(sa->sa_inqbuf->product, "C2500A", 6)) {
        !           116:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           117:                printf("HP ScanJet IIcx");
        !           118:        }
        !           119:        /* The 3p is a grayscale-only HP SCL scanner */
        !           120:        if (!bcmp(sa->sa_inqbuf->product, "C2570A", 6)) {
        !           121:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           122:                printf("HP ScanJet 3p");
        !           123:        }
        !           124:        /* The 3c/4c/6100C report as the same? */
        !           125:        if (!bcmp(sa->sa_inqbuf->product, "C2520A", 6)) {
        !           126:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           127:                printf("HP ScanJet 3c/4c/6100C");
        !           128:        }
        !           129:        if (!bcmp(sa->sa_inqbuf->product, "C1130A", 6)) {
        !           130:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           131:                printf("HP ScanJet 4p");
        !           132:        }
        !           133:        if (!bcmp(sa->sa_inqbuf->product, "C5110A", 6)) {
        !           134:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           135:                printf("HP ScanJet 5p");
        !           136:        }
        !           137:        if (!bcmp(sa->sa_inqbuf->product, "C6290A", 6)) {
        !           138:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           139:                printf("HP ScanJet 4100C");
        !           140:        }
        !           141:        if (!bcmp(sa->sa_inqbuf->product, "C5190A", 6)) {
        !           142:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           143:                printf("HP ScanJet 5100C");
        !           144:        }
        !           145:        if (!bcmp(sa->sa_inqbuf->product, "C7190A", 6)) {
        !           146:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           147:                printf("HP ScanJet 5200C");
        !           148:        }
        !           149:        if (!bcmp(sa->sa_inqbuf->product, "C6270A", 6)) {
        !           150:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           151:                printf("HP ScanJet 6200C");
        !           152:        }
        !           153:        if (!bcmp(sa->sa_inqbuf->product, "C7670A", 6)) {
        !           154:                ss->sio.scan_scanner_type = HP_SCANJET_IIC;
        !           155:                printf("HP ScanJet 6300C");
        !           156:        }
        !           157:
        !           158:        SC_DEBUG(sc_link, SDEV_DB1, ("scanjet_attach: scanner_type = %d\n",
        !           159:            ss->sio.scan_scanner_type));
        !           160:
        !           161:        /* now install special handlers */
        !           162:        ss->special = scanjet_special;
        !           163:
        !           164:        /*
        !           165:         * fill in the rest of the scan_io struct by calling
        !           166:         * set_window and compute_sizes routines
        !           167:         */
        !           168:        error = scanjet_set_window(ss, SCSI_POLL);
        !           169:        if (error) {
        !           170:                printf(" set_window failed\n");
        !           171:                return;
        !           172:        }
        !           173:
        !           174:        error = scanjet_compute_sizes(ss, SCSI_POLL);
        !           175:        if (error) {
        !           176:                printf(" compute_sizes failed\n");
        !           177:                return;
        !           178:        }
        !           179:
        !           180:        printf("\n");
        !           181: }
        !           182:
        !           183: /*
        !           184:  * check the parameters if the scanjet is capable of fulfilling it
        !           185:  * but don't send the command to the scanner in case the user wants
        !           186:  * to change parameters by more than one call
        !           187:  */
        !           188: int
        !           189: scanjet_set_params(ss, sio)
        !           190:        struct ss_softc *ss;
        !           191:        struct scan_io *sio;
        !           192: {
        !           193:        int error;
        !           194:
        !           195: #if 0
        !           196:        /*
        !           197:         * if the scanner is triggered, then rewind it
        !           198:         */
        !           199:        if (ss->flags & SSF_TRIGGERED) {
        !           200:                error = scanjet_rewind_scanner(ss);
        !           201:                if (error)
        !           202:                        return (error);
        !           203:        }
        !           204: #endif
        !           205:
        !           206:        /* size constraints... */
        !           207:        if (sio->scan_width == 0                                 ||
        !           208:            sio->scan_x_origin + sio->scan_width > 10200 || /* 8.5" */
        !           209:            sio->scan_height == 0                                ||
        !           210:            sio->scan_y_origin + sio->scan_height > 16800)  /* 14" */
        !           211:                return (EINVAL);
        !           212:
        !           213:        /* resolution (dpi)... */
        !           214:        if (sio->scan_x_resolution < 100 ||
        !           215:            sio->scan_x_resolution > 400 ||
        !           216:            sio->scan_y_resolution < 100 ||
        !           217:            sio->scan_y_resolution > 400)
        !           218:                return (EINVAL);
        !           219:
        !           220:        switch (sio->scan_image_mode) {
        !           221:        case SIM_BINARY_MONOCHROME:
        !           222:        case SIM_DITHERED_MONOCHROME:
        !           223:        case SIM_GRAYSCALE:
        !           224:        case SIM_COLOR:
        !           225:                break;
        !           226:        default:
        !           227:                return (EINVAL);
        !           228:        }
        !           229:
        !           230:        /* change ss_softc to the new values, but save ro-variables */
        !           231:        sio->scan_scanner_type = ss->sio.scan_scanner_type;
        !           232:        bcopy(sio, &ss->sio, sizeof(struct scan_io));
        !           233:
        !           234:        error = scanjet_set_window(ss, 0);
        !           235:        if (error) {
        !           236:                uprintf("%s: set_window failed\n", ss->sc_dev.dv_xname);
        !           237:                return (error);
        !           238:        }
        !           239:        error = scanjet_compute_sizes(ss, 0);
        !           240:        if (error) {
        !           241:                uprintf("%s: compute_sizes failed\n", ss->sc_dev.dv_xname);
        !           242:                return (error);
        !           243:        }
        !           244:
        !           245:        return (0);
        !           246: }
        !           247:
        !           248: /*
        !           249:  * trigger the scanner to start a scan operation
        !           250:  * this includes sending the mode- and window-data,
        !           251:  * and starting the scanner
        !           252:  */
        !           253: int
        !           254: scanjet_trigger_scanner(ss)
        !           255:        struct ss_softc *ss;
        !           256: {
        !           257:        static char *escape_codes = "\033*f0S";
        !           258:        int error;
        !           259:
        !           260:        error = scanjet_set_window(ss, 0);
        !           261:        if (error) {
        !           262:                uprintf("%s: set_window failed\n", ss->sc_dev.dv_xname);
        !           263:                return (error);
        !           264:        }
        !           265:        error = scanjet_compute_sizes(ss, 0);
        !           266:        if (error) {
        !           267:                uprintf("%s: compute_sizes failed\n", ss->sc_dev.dv_xname);
        !           268:                return (error);
        !           269:        }
        !           270:
        !           271:        /* send "trigger" operation */
        !           272:        error = scanjet_ctl_write(ss, escape_codes, strlen(escape_codes), 0);
        !           273:        if (error) {
        !           274:                uprintf("%s: trigger_scanner failed\n", ss->sc_dev.dv_xname);
        !           275:                return (error);
        !           276:        }
        !           277:
        !           278:        return (0);
        !           279: }
        !           280:
        !           281: int
        !           282: scanjet_read(ss, bp)
        !           283:        struct ss_softc *ss;
        !           284:        struct buf *bp;
        !           285: {
        !           286:        struct scsi_rw_scanner cmd;
        !           287:        struct scsi_link *sc_link = ss->sc_link;
        !           288:
        !           289:        /*
        !           290:         *  Fill out the scsi command
        !           291:         */
        !           292:        bzero(&cmd, sizeof(cmd));
        !           293:        cmd.opcode = READ;
        !           294:
        !           295:        /*
        !           296:         * Handle "fixed-block-mode" tape drives by using the
        !           297:         * block count instead of the length.
        !           298:         */
        !           299:        _lto3b(bp->b_bcount, cmd.len);
        !           300:
        !           301:        /*
        !           302:         * go ask the adapter to do all this for us
        !           303:         */
        !           304:        if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, sizeof(cmd),
        !           305:            (u_char *) bp->b_data, bp->b_bcount, SCANJET_RETRIES, 100000, bp,
        !           306:            SCSI_NOSLEEP | SCSI_DATA_IN) != SUCCESSFULLY_QUEUED)
        !           307:                printf("%s: not queued\n", ss->sc_dev.dv_xname);
        !           308:        else {
        !           309:                if (bp->b_bcount >= ss->sio.scan_window_size)
        !           310:                        ss->sio.scan_window_size = 0;
        !           311:                else
        !           312:                        ss->sio.scan_window_size -= bp->b_bcount;
        !           313:        }
        !           314:
        !           315:        return (0);
        !           316: }
        !           317:
        !           318:
        !           319: /*
        !           320:  * Do a synchronous write.  Used to send control messages.
        !           321:  */
        !           322: int
        !           323: scanjet_ctl_write(ss, buf, size, flags)
        !           324:        struct ss_softc *ss;
        !           325:        char *buf;
        !           326:        u_int size;
        !           327:        int flags;
        !           328: {
        !           329:        struct scsi_rw_scanner cmd;
        !           330:
        !           331:        bzero(&cmd, sizeof(cmd));
        !           332:        cmd.opcode = WRITE;
        !           333:        _lto3b(size, cmd.len);
        !           334:        return (scsi_scsi_cmd(ss->sc_link, (struct scsi_generic *) &cmd,
        !           335:            sizeof(cmd), (u_char *) buf, size, 0, 100000, NULL,
        !           336:            flags | SCSI_DATA_OUT));
        !           337: }
        !           338:
        !           339:
        !           340: /*
        !           341:  * Do a synchronous read.  Used to read responses to control messages.
        !           342:  */
        !           343: int
        !           344: scanjet_ctl_read(ss, buf, size, flags)
        !           345:        struct ss_softc *ss;
        !           346:        char *buf;
        !           347:        u_int size;
        !           348:        int flags;
        !           349: {
        !           350:        struct scsi_rw_scanner cmd;
        !           351:
        !           352:        bzero(&cmd, sizeof(cmd));
        !           353:        cmd.opcode = READ;
        !           354:        _lto3b(size, cmd.len);
        !           355:        return (scsi_scsi_cmd(ss->sc_link, (struct scsi_generic *) &cmd,
        !           356:            sizeof(cmd), (u_char *) buf, size, 0, 100000, NULL,
        !           357:            flags | SCSI_DATA_IN));
        !           358: }
        !           359:
        !           360:
        !           361: #ifdef SCANJETDEBUG
        !           362: static void show_es(char *es)
        !           363: {
        !           364:        char *p = es;
        !           365:
        !           366:        while (*p) {
        !           367:                if (*p == '\033')
        !           368:                        printf("[Esc]");
        !           369:                else
        !           370:                        printf("%c", *p);
        !           371:                ++p;
        !           372:        }
        !           373:        printf("\n");
        !           374: }
        !           375: #endif
        !           376:
        !           377: /*
        !           378:  * simulate SCSI_SET_WINDOW for ScanJets
        !           379:  */
        !           380: int
        !           381: scanjet_set_window(ss, flags)
        !           382:        struct ss_softc *ss;
        !           383:        int flags;
        !           384: {
        !           385:        char escape_codes[128];
        !           386:        size_t len;
        !           387:        int n;
        !           388:
        !           389:        snprintf(escape_codes, sizeof escape_codes,
        !           390:            "\033*f%ldP\033*f%ldQ\033*f%ldX\033*f%ldY\033*a%dR\033*a%dS",
        !           391:            ss->sio.scan_width / 4,
        !           392:            ss->sio.scan_height / 4,
        !           393:            ss->sio.scan_x_origin / 4,
        !           394:            ss->sio.scan_y_origin / 4,
        !           395:            ss->sio.scan_x_resolution,
        !           396:            ss->sio.scan_y_resolution);
        !           397:
        !           398:        switch (ss->sio.scan_image_mode) {
        !           399:        case SIM_BINARY_MONOCHROME:
        !           400:                ss->sio.scan_bits_per_pixel = 1;
        !           401:                /*
        !           402:                 * Use line art mode (\033*aoT) and make image data be
        !           403:                 * min-is-white ala PBM (\033*a0I).
        !           404:                 */
        !           405:                strlcat(escape_codes, "\033*a0T\033*a0I", sizeof escape_codes);
        !           406:                break;
        !           407:        case SIM_DITHERED_MONOCHROME:
        !           408:                ss->sio.scan_bits_per_pixel = 1;
        !           409:                /*
        !           410:                 * Use dithered mode (\033*a3T) and make image data be
        !           411:                 * min-is-white ala PBM (\033*a0I).
        !           412:                 */
        !           413:                strlcat(escape_codes, "\033*a3T\033*a0I", sizeof escape_codes);
        !           414:                break;
        !           415:        case SIM_GRAYSCALE:
        !           416:                ss->sio.scan_bits_per_pixel = 8;
        !           417:                /*
        !           418:                 * Use grayscale mode (\033*a4T) and make image data be
        !           419:                 * min-is-black ala PGM (\033*a1I)
        !           420:                 */
        !           421:                strlcat(escape_codes, "\033*a4T\033*a1I", sizeof escape_codes);
        !           422:                break;
        !           423:        case SIM_COLOR:
        !           424:                ss->sio.scan_bits_per_pixel = 24;
        !           425:                /*
        !           426:                 * Use RGB color mode (\033*a5T), make image data be
        !           427:                 * min-is-black ala PPM (\033*a1I) and use pass-through matrix,
        !           428:                 * i.e. disable NTSC (\033*u2T).
        !           429:                 */
        !           430:                strlcat(escape_codes, "\033*a5T\033*a1I\033*u2T",
        !           431:                    sizeof escape_codes);
        !           432:                break;
        !           433:        }
        !           434:
        !           435:        /*
        !           436:         * If the escape sequence has been truncated at this point, appending
        !           437:         * the next sequence will also cause truncation, and this time we pay
        !           438:         * attention.
        !           439:         */
        !           440:        len = strlen(escape_codes);
        !           441:        n = snprintf(escape_codes + len, sizeof escape_codes - len,
        !           442:            "\033*a%dG\033*a%dL\033*a%dK",
        !           443:            ss->sio.scan_bits_per_pixel,
        !           444:            (int)(ss->sio.scan_brightness) - 128,
        !           445:            (int)(ss->sio.scan_contrast) - 128);
        !           446:
        !           447:        if (n >= sizeof escape_codes - len)
        !           448:                return (ENOMEM);
        !           449:        len += n;
        !           450:
        !           451:        return (scanjet_ctl_write(ss, escape_codes, len, flags));
        !           452: }
        !           453:
        !           454: /* atoi() is from /sys/arch/amiga/dev/ite.c
        !           455:    and is only used in scanjet_compute_sizes */
        !           456:
        !           457: __inline static int
        !           458: atoi(cp)
        !           459:        const char *cp;
        !           460: {
        !           461:        int n;
        !           462:
        !           463:        for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
        !           464:                n = n * 10 + *cp - '0';
        !           465:
        !           466:        return (n);
        !           467: }
        !           468:
        !           469: int
        !           470: scanjet_compute_sizes(ss, flags)
        !           471:        struct ss_softc *ss;
        !           472:        int flags;
        !           473: {
        !           474:        int error;
        !           475:        static char *wfail = "%s: interrogate write failed\n";
        !           476:        static char *rfail = "%s: interrogate read failed\n";
        !           477:        static char *dfail = "%s: bad data returned\n";
        !           478:        static char *mono  = "\033*s1025E"; /* bytes wide  */
        !           479:        static char *color = "\033*s1024E"; /* pixels wide */
        !           480:        static char *high  = "\033*s1026E"; /* pixels high */
        !           481:        char response[20];
        !           482:        char *p;
        !           483:
        !           484:        /*
        !           485:         * Deal with the fact that the HP ScanJet IIc uses 1/300" not 1/1200"
        !           486:         * as its base unit of measurement.  PINT uses 1/1200" (yes I know
        !           487:         * ScanJet II's use decipoints as well but 1200 % 720 != 0)
        !           488:         */
        !           489:        ss->sio.scan_width = (ss->sio.scan_width + 3) & 0xfffffffc;
        !           490:        ss->sio.scan_height = (ss->sio.scan_height + 3) & 0xfffffffc;
        !           491:
        !           492:        switch (ss->sio.scan_image_mode) {
        !           493:        case SIM_BINARY_MONOCHROME:
        !           494:        case SIM_DITHERED_MONOCHROME:
        !           495:                error = scanjet_ctl_write(ss, mono, strlen(mono), flags);
        !           496:                break;
        !           497:        case SIM_GRAYSCALE:
        !           498:        case SIM_COLOR:
        !           499:                error = scanjet_ctl_write(ss, color, strlen(color), flags);
        !           500:                break;
        !           501:        default:
        !           502:                error = EIO;
        !           503:                break;
        !           504:        }
        !           505:        if (error) {
        !           506:                uprintf(wfail, ss->sc_dev.dv_xname);
        !           507:                return (error);
        !           508:        }
        !           509:        error = scanjet_ctl_read(ss, response, 20, flags);
        !           510:        if (error) {
        !           511:                uprintf(rfail, ss->sc_dev.dv_xname);
        !           512:                return (error);
        !           513:        }
        !           514:        p = strchr(response, 'd');
        !           515:        if (p == NULL) {
        !           516:                uprintf(dfail, ss->sc_dev.dv_xname);
        !           517:                return (EIO);
        !           518:        }
        !           519:        ss->sio.scan_pixels_per_line = atoi(p + 1);
        !           520:        if (ss->sio.scan_image_mode < SIM_GRAYSCALE)
        !           521:                ss->sio.scan_pixels_per_line *= 8;
        !           522:
        !           523:        error = scanjet_ctl_write(ss, high, strlen(high), flags);
        !           524:        if (error) {
        !           525:                uprintf(wfail, ss->sc_dev.dv_xname);
        !           526:                return (error);
        !           527:        }
        !           528:        error = scanjet_ctl_read(ss, response, 20, flags);
        !           529:        if (error) {
        !           530:                uprintf(rfail, ss->sc_dev.dv_xname);
        !           531:                return (error);
        !           532:        }
        !           533:        p = strchr(response, 'd');
        !           534:        if (p == NULL) {
        !           535:                uprintf(dfail, ss->sc_dev.dv_xname);
        !           536:                return (EIO);
        !           537:        }
        !           538:        ss->sio.scan_lines = atoi(p + 1);
        !           539:
        !           540:        ss->sio.scan_window_size = ss->sio.scan_lines *
        !           541:            ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
        !           542:
        !           543:        return (0);
        !           544: }

CVSweb