way more generic SET_WINDOW...
authorkstailey <kstailey@openbsd.org>
Sat, 8 Mar 1997 18:59:41 +0000 (18:59 +0000)
committerkstailey <kstailey@openbsd.org>
Sat, 8 Mar 1997 18:59:41 +0000 (18:59 +0000)
sys/scsi/ss.c

index 9b94246..b582673 100644 (file)
@@ -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
 #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));
+}