From 7c786be7f1b2588cd4ab242084d4baffdc679bc2 Mon Sep 17 00:00:00 2001 From: kstailey Date: Sat, 8 Mar 1997 18:59:41 +0000 Subject: [PATCH] way more generic SET_WINDOW... --- sys/scsi/ss.c | 222 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 164 insertions(+), 58 deletions(-) diff --git a/sys/scsi/ss.c b/sys/scsi/ss.c index 9b942464cda..b582673f039 100644 --- a/sys/scsi/ss.c +++ b/sys/scsi/ss.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ss.c,v 1.14 1997/03/08 05:39:00 kstailey Exp $ */ +/* $OpenBSD: ss.c,v 1.15 1997/03/08 18:59:41 kstailey Exp $ */ /* $NetBSD: ss.c,v 1.10 1996/05/05 19:52:55 christos Exp $ */ /* - * Copyright (c) 1995 Kenneth Stailey. All rights reserved. + * Copyright (c) 1995, 1997 Kenneth Stailey. All rights reserved. * modified for configurable scanner support by Joachim Koenig * * Redistribution and use in source and binary forms, with or without @@ -65,18 +65,22 @@ #define MODE_CONTROL 3 struct quirkdata { + char *name; u_int quirks; #define SS_Q_NEEDS_WINDOW_DESC_LEN 0x0001 /* needs special WDL */ #define SS_Q_USES_HALFTONE 0x0002 /* uses non-zero halftone */ #define SS_Q_NEEDS_RIF_SET 0x0004 -#define SS_Q_NEEDS_PADDING_TYPE 0x0008 /* needs special padding type */ +#define SS_Q_NEEDS_PADDING_TYPE 0x0008 /* does not pad to byte boundary */ #define SS_Q_USES_BIT_ORDERING 0x0010 /* uses non-zero bit ordering */ -#define SS_Q_GET_BUFFER_SIZE 0x0020 /* use GET_BUFFER_SIZE while reading */ +#define SS_Q_VENDOR_UNIQUE_SETWINDOW 0x0020 /* 40 bytes of parms is not enough */ +#define SS_Q_GET_BUFFER_SIZE 0x0040 /* use GET_BUFFER_SIZE while reading */ long window_descriptor_length; u_int8_t halftone_pattern[2]; int pad_type; long bit_ordering; + int (*vendor_unique_sw)__P((struct ss_softc *, struct scan_io *, + struct scsi_set_window *, void *)); }; struct ss_quirk_inquiry_pattern { @@ -84,6 +88,18 @@ struct ss_quirk_inquiry_pattern { struct quirkdata quirkdata; }; +void ssstrategy __P((struct buf *)); +void ssstart __P((void *)); +void ssminphys __P((struct buf *)); + +void ss_identify_scanner __P((struct ss_softc *, struct scsi_inquiry_data *)); +int ss_set_window __P((struct ss_softc *, struct scan_io *)); + +int ricoh_is410_sw __P((struct ss_softc *, struct scan_io *, + struct scsi_set_window *, void *)); +int umax_uc630_sw __P((struct ss_softc *, struct scan_io *, + struct scsi_set_window *, void *)); + /* * WDL: * @@ -96,20 +112,35 @@ struct ss_quirk_inquiry_pattern { struct ss_quirk_inquiry_pattern ss_quirk_patterns[] = { {{T_SCANNER, T_FIXED, "RICOH ", "IS410 ", " "}, { + "Ricoh IS-410", SS_Q_NEEDS_WINDOW_DESC_LEN | SS_Q_USES_HALFTONE | - SS_Q_USES_BIT_ORDERING, - 320, { 2, 0x0a }, 0, 7 - }}, -#ifdef NOTYET - {{T_SCANNER, T_FIXED, - "FUJITSU ", "M3096Gm ", " "}, { - SS_Q_ + SS_Q_USES_BIT_ORDERING | + SS_Q_VENDOR_UNIQUE_SETWINDOW, + 320, { 2, 0x0a }, 0, 7, + ricoh_is410_sw }}, {{T_SCANNER, T_FIXED, "UMAX ", "UC630 ", " "}, { + "UMAX UC-630", + SS_Q_NEEDS_WINDOW_DESC_LEN | + SS_Q_USES_HALFTONE | + SS_Q_VENDOR_UNIQUE_SETWINDOW, + 0x2e, { 0, 1 }, 0, 0, + umax_uc630_sw + }}, {{T_SCANNER, T_FIXED, "UMAX ", "UG630 ", " "}, { + "UMAX UG-630", + SS_Q_NEEDS_WINDOW_DESC_LEN | + SS_Q_USES_HALFTONE | + SS_Q_VENDOR_UNIQUE_SETWINDOW, + 0x2e, { 0, 1 }, 0, 0, + umax_uc630_sw + }}, +#ifdef NOTYET + {{T_SCANNER, T_FIXED, + "FUJITSU ", "M3096Gm ", " "}, { }}, #endif }; @@ -126,13 +157,6 @@ struct cfdriver ss_cd = { NULL, "ss", DV_DULL }; -void ssstrategy __P((struct buf *)); -void ssstart __P((void *)); -void ssminphys __P((struct buf *)); - -void ss_identify_scanner __P((struct ss_softc *, struct scsi_inquiry_data *)); -int ss_set_window __P((struct ss_softc *, struct scan_io *)); - struct scsi_device ss_switch = { NULL, ssstart, @@ -207,6 +231,29 @@ ssattach(parent, self, aux) ss->buf_queue.b_actb = &ss->buf_queue.b_actf; } +void +ss_identify_scanner(ss, inqbuf) + struct ss_softc *ss; + struct scsi_inquiry_data *inqbuf; +{ + struct ss_quirk_inquiry_pattern *finger; + int priority; + /* + * look for non-standard scanners with help of the quirk table + * and install functions for special handling + */ + finger = (struct ss_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf, + (caddr_t)ss_quirk_patterns, + sizeof(ss_quirk_patterns)/sizeof(ss_quirk_patterns[0]), + sizeof(ss_quirk_patterns[0]), &priority); + if (priority != 0) { + ss->quirkdata = &finger->quirkdata; + printf("%s\n", ss->quirkdata->name); + } else { + printf("generic scanner\n"); /* good luck 8c{)] */ + } +} + /* * open the device. */ @@ -486,8 +533,8 @@ ssioctl(dev, cmd, addr, flag, p) switch (cmd) { case SCIOCGET: + /* call special handler, if any */ if (ss->special->get_params) { - /* call special handler */ error = (ss->special->get_params)(ss); if (error) return (error); @@ -497,8 +544,8 @@ ssioctl(dev, cmd, addr, flag, p) case SCIOCSET: sio = (struct scan_io *)addr; + /* call special handler, if any */ if (ss->special->set_params) { - /* call special handler */ error = (ss->special->set_params)(ss, sio); if (error) return (error); @@ -508,8 +555,8 @@ ssioctl(dev, cmd, addr, flag, p) } break; case SCIOCRESTART: + /* call special handler, if any */ if (ss->special->rewind_scanner ) { - /* call special handler */ error = (ss->special->rewind_scanner)(ss); if (error) return (error); @@ -518,10 +565,9 @@ ssioctl(dev, cmd, addr, flag, p) return (EOPNOTSUPP); ss->flags &= ~SSF_TRIGGERED; break; -#ifdef NOTYET - case SCAN_USE_ADF: - break; -#endif + case SCIOC_USE_ADF: + /* XXX add Automatic Document Feeder Support */ + return (EOPNOTSUPP); default: if (SSMODE(dev) != MODE_CONTROL) return (ENOTTY); @@ -532,13 +578,22 @@ ssioctl(dev, cmd, addr, flag, p) } int -ss_set_window(sc, sio) - struct ss_softc *sc; +ss_set_window(ss, sio) + struct ss_softc *ss; struct scan_io *sio; { struct scsi_set_window window_cmd; - struct scsi_window_data window_data; - struct scsi_link *sc_link; + struct { + struct scsi_window_data window_data; + /* vendor_unique must provide enough space for worst case + * (currently Ricoh IS-410.) 40 + 280 = 320 which is the size + * of its window descriptor length + */ + u_int8_t vendor_unique[280]; + } wd; +#define window_data wd.window_data +#define vendor_unique wd.vendor_unique + struct scsi_link *sc_link = ss->sc_link;; /* * The CDB for SET WINDOW goes in here. @@ -549,8 +604,8 @@ ss_set_window(sc, sio) _lto3l(sizeof(window_data), window_cmd.len); bzero(&window_data, sizeof(window_data)); - if (sc->quirkdata->quirks & SS_Q_NEEDS_WINDOW_DESC_LEN) - _lto2l(sc->quirkdata->window_descriptor_length, + if (ss->quirkdata->quirks & SS_Q_NEEDS_WINDOW_DESC_LEN) + _lto2l(ss->quirkdata->window_descriptor_length, window_data.window_desc_len); else _lto2l(40L, window_data.window_desc_len); @@ -575,46 +630,97 @@ ss_set_window(sc, sio) window_data.image_comp = sio->scan_image_mode; } window_data.bits_per_pixel = sio->scan_bits_per_pixel; - if (sc->quirkdata->quirks & SS_Q_USES_HALFTONE) { + if (ss->quirkdata->quirks & SS_Q_USES_HALFTONE) { window_data.halftone_pattern[0] = - sc->quirkdata->halftone_pattern[0]; + ss->quirkdata->halftone_pattern[0]; window_data.halftone_pattern[1] = - sc->quirkdata->halftone_pattern[1]; + ss->quirkdata->halftone_pattern[1]; } /* else leave halftone set to zero. */ /* leave rif set to zero. */ - if (sc->quirkdata->quirks & SS_Q_NEEDS_PADDING_TYPE) - window_data.pad_type = sc->quirkdata->pad_type; + if (ss->quirkdata->quirks & SS_Q_NEEDS_PADDING_TYPE) + window_data.pad_type = ss->quirkdata->pad_type; else window_data.pad_type = 3; /* 3 = pad to byte boundary */ - if (sc->quirkdata->quirks & SS_Q_USES_BIT_ORDERING) - _lto2l(sc->quirkdata->bit_ordering, window_data.bit_ordering); + if (ss->quirkdata->quirks & SS_Q_USES_BIT_ORDERING) + _lto2l(ss->quirkdata->bit_ordering, window_data.bit_ordering); /* else leave bit_ordering set to zero. */ /* leave compression type & argument set to zero. */ - /* XXX many scanners require a vendor-specific portion */ +#undef window_data - /* send the command to the scanner */ - return (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &window_cmd, - sizeof(window_cmd), (u_char *) &window_data, sizeof(window_data), - 4, 5000, NULL, SCSI_DATA_OUT)); + if (ss->quirkdata->quirks &SS_Q_VENDOR_UNIQUE_SETWINDOW) + return ((*ss->quirkdata->vendor_unique_sw)(ss, sio, + &window_cmd, (void*)&wd)); + else + /* send the command to the scanner */ + return (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &window_cmd, + sizeof(window_cmd), (u_char *) &wd.window_data, + sizeof(wd.window_data), 4, 5000, NULL, SCSI_DATA_OUT)); } -void -ss_identify_scanner(ss, inqbuf) +int +ricoh_is410_sw(ss, sio, wcmd, vwd) struct ss_softc *ss; - struct scsi_inquiry_data *inqbuf; + struct scan_io *sio; + struct scsi_set_window *wcmd; + void *vwd; { - struct ss_quirk_inquiry_pattern *finger; - int priority; - /* - * look for non-standard scanners with help of the quirk table - * and install functions for special handling - */ - finger = (struct ss_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf, - (caddr_t)ss_quirk_patterns, - sizeof(ss_quirk_patterns)/sizeof(ss_quirk_patterns[0]), - sizeof(ss_quirk_patterns[0]), &priority); - if (priority != 0) - ss->quirkdata = &finger->quirkdata; + struct ricoh_is410_window_data { + struct scsi_window_data window_data; + u_int8_t res1; + u_int8_t res2; + u_int8_t mrif:1; /* reverse image format (grayscale negative) */ + u_int8_t filtering:3; + u_int8_t gamma_id:4; + } *rwd = (struct ricoh_is410_window_data*)vwd; + struct scsi_link *sc_link = ss->sc_link;; + + rwd->mrif = 1; /* force grayscale to match PGM */ + + /* send the command to the scanner */ + return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)wcmd, + sizeof(struct scsi_set_window), (u_char *)rwd, + sizeof(struct ricoh_is410_window_data), 4, 5000, NULL, + SCSI_DATA_OUT)); } +int +umax_uc630_sw(ss, sio, wcmd, vwd) + struct ss_softc *ss; + struct scan_io *sio; + struct scsi_set_window *wcmd; + void *vwd; + +{ + struct umax_uc630_window_data { + struct scsi_window_data window_data; + u_int8_t speed; + u_int8_t select_color; + u_int8_t highlight; + u_int8_t shadow; + u_int8_t paper_length[2]; + } *uwd = (struct umax_uc630_window_data*)vwd; + struct scsi_link *sc_link = ss->sc_link;; + + uwd->speed = 1; /* speed: fastest speed that doesn't smear */ + switch (sio->scan_image_mode) { /* UMAX has three-pass color. */ + case SIM_RED: /* This selects which filter to use. */ + uwd->select_color = 0x80; + break; + case SIM_GREEN: + uwd->select_color = 0x40; + break; + case SIM_BLUE: + uwd->select_color = 0x20; + break; + } + uwd->highlight = 50; /* 50 = highest; 0 = lowest */ + /* leave shadow set to zero. */ + /* XXX paper length is for ADF */ + + /* send the command to the scanner */ + return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)wcmd, + sizeof(struct scsi_set_window), (u_char *)uwd, + sizeof(struct umax_uc630_window_data), 4, 5000, NULL, + SCSI_DATA_OUT)); +} -- 2.20.1