-/* $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 {
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:
*
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
};
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,
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.
*/
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);
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);
}
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);
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);
}
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.
_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);
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));
+}