Subject: Re: Some experience about Epson GT-9700F usb scanner.
To: enami tsugutomo <enami@but-b.or.jp>
From: Lennart Augustsson <lennart@augustsson.net>
List: tech-kern
Date: 12/02/2001 12:05:25
Ah, I actually have a clue what might be going wrong. It's probably the
data toggles that are not set right.
I'll cook up a fix later today.
-- Lennart
enami tsugutomo wrote:
> Here is my brief experience about Epson GT-9700F usb scanner.
>
> - Unless ehcidebug is set to some value other than 0, attach phase
> fails as follows:
>
> usbd_transfer_cb: short transfer 0<4
> uscanner0 at uhub2 port 1
> uscanner0: EPSON EPSON Scanner, rev 2.00/1.01, addr 2
> usbd_transfer_cb: short transfer 0<9
> uscanner0: setting config no failed
>
> The controller is NEC's.
>
> - If connected to uhci controller, it attaches successfully. And it
> works like many times of `scanimage -L' (from sane-backend pkg)
> successfully returns the name of GT-9700F as available scanner
> (i.e., reset and some other sequence like identify can be sent many
> times and scanner response normally). And I can scan once. After
> that, it waits ACK (of ESC/I protocol, Epson's scanner control
> language) from scanner after sending 2 byte reset sequence. When
> this occurs, NAK bit is set in TD's status field (after read
> operation is started). E.g.,
>
> 5<T,VF> 398807ff<NAK,ACTIVE,IOC,SPD>,errcnt=3,actlen=0
> pid=69,addr=2,endpt=1,D=0,maxlen=4
>
> - And I finanly found that if I defer actual device close operation
> until detach time (see the diff attached below. the diff includes
> some garbage tho), the scanner works fine (with both uhci and ehci,
> not tested with ohci controller yet). But I'm not sure if this
> should be integrated in main tree or not. Especially if there is
> another fix...
>
> enami.
>
> Index: uscanner.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/dev/usb/uscanner.c,v
> retrieving revision 1.21
> diff -c -r1.21 uscanner.c
> *** uscanner.c 2001/12/01 09:42:39 1.21
> --- uscanner.c 2001/12/02 09:07:48
> ***************
> *** 72,78 ****
> #ifdef USCANNER_DEBUG
> #define DPRINTF(x) if (uscannerdebug) logprintf x
> #define DPRINTFN(n,x) if (uscannerdebug>(n)) logprintf x
> ! int uscannerdebug = 0;
> #else
> #define DPRINTF(x)
> #define DPRINTFN(n,x)
> --- 72,78 ----
> #ifdef USCANNER_DEBUG
> #define DPRINTF(x) if (uscannerdebug) logprintf x
> #define DPRINTFN(n,x) if (uscannerdebug>(n)) logprintf x
> ! int uscannerdebug = 6;
> #else
> #define DPRINTF(x)
> #define DPRINTFN(n,x)
> ***************
> *** 80,87 ****
>
> /* Table of scanners that may work with this driver. */
> static const struct scanner_id {
> ! uint16_t vendor;
> ! uint16_t product;
> } scanner_ids [] = {
> /* Acer Peripherals */
> { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U },
> --- 80,89 ----
>
> /* Table of scanners that may work with this driver. */
> static const struct scanner_id {
> ! uint16_t si_vendor;
> ! uint16_t si_product;
> ! int si_quirks;
> ! #define USCANNERQ_DEFERCLOSE 0x0001
> } scanner_ids [] = {
> /* Acer Peripherals */
> { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U },
> ***************
> *** 155,161 ****
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640 },
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U },
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650 },
> ! { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F },
>
> /* UMAX */
> { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U },
> --- 157,163 ----
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640 },
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U },
> { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650 },
> ! { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F, USCANNERQ_DEFERCLOSE },
>
> /* UMAX */
> { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U },
> ***************
> *** 178,184 ****
> { 0, 0 }
> };
>
> ! #define USCANNER_BUFFERSIZE 1024
>
> struct uscanner_softc {
> USBBASEDEVICE sc_dev; /* base device */
> --- 180,186 ----
> { 0, 0 }
> };
>
> ! #define USCANNER_BUFFERSIZE 4096
>
> struct uscanner_softc {
> USBBASEDEVICE sc_dev; /* base device */
> ***************
> *** 201,207 ****
> --- 203,214 ----
>
> u_char sc_state;
> #define USCANNER_OPEN 0x01 /* opened */
> + #define USCANNER_SETUP 0x02 /* setup is done */
> + #define USCANNER_ATTACHED 0x04 /* attached */
>
> + u_char sc_flags;
> + #define USCANNERF_DEFERCLOSE 0x01
> +
> int sc_refcnt;
> u_char sc_dying;
> };
> ***************
> *** 235,262 ****
> };
> #endif
>
> Static int uscanner_do_read(struct uscanner_softc *, struct uio *, int);
> Static int uscanner_do_write(struct uscanner_softc *, struct uio *, int);
> Static void uscanner_do_close(struct uscanner_softc *);
>
> #define USCANNERUNIT(n) (minor(n))
>
> USB_DECLARE_DRIVER(uscanner);
>
> USB_MATCH(uscanner)
> {
> USB_MATCH_START(uscanner, uaa);
> - int i;
>
> if (uaa->iface != NULL)
> return UMATCH_NONE;
>
> ! for (i = 0; scanner_ids[i].vendor != 0; i++) {
> ! if (scanner_ids[i].vendor == uaa->vendor &&
> ! scanner_ids[i].product == uaa->product) {
> ! return (UMATCH_VENDOR_PRODUCT);
> ! }
> ! }
>
> return (UMATCH_NONE);
> }
> --- 242,281 ----
> };
> #endif
>
> + Static const struct scanner_id *uscanner_lookup(struct usb_attach_arg *);
> Static int uscanner_do_read(struct uscanner_softc *, struct uio *, int);
> Static int uscanner_do_write(struct uscanner_softc *, struct uio *, int);
> + Static int uscanner_do_open(struct uscanner_softc *);
> Static void uscanner_do_close(struct uscanner_softc *);
>
> #define USCANNERUNIT(n) (minor(n))
>
> USB_DECLARE_DRIVER(uscanner);
>
> + Static const struct scanner_id *
> + uscanner_lookup(struct usb_attach_arg *uaa)
> + {
> + int i;
> +
> + for (i = 0; scanner_ids[i].si_vendor != 0; i++) {
> + if (scanner_ids[i].si_vendor == uaa->vendor &&
> + scanner_ids[i].si_product == uaa->product) {
> + return (&scanner_ids[i]);
> + }
> + }
> +
> + return (NULL);
> + }
> +
> USB_MATCH(uscanner)
> {
> USB_MATCH_START(uscanner, uaa);
>
> if (uaa->iface != NULL)
> return UMATCH_NONE;
>
> ! if (uscanner_lookup(uaa) != NULL)
> ! return (UMATCH_VENDOR_PRODUCT);
>
> return (UMATCH_NONE);
> }
> ***************
> *** 266,271 ****
> --- 285,291 ----
> USB_ATTACH_START(uscanner, sc, uaa);
> usb_interface_descriptor_t *id = 0;
> usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
> + const struct scanner_id *si;
> char devinfo[1024];
> int i;
> usbd_status err;
> ***************
> *** 274,279 ****
> --- 294,303 ----
> USB_ATTACH_SETUP;
> printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
>
> + si = uscanner_lookup(uaa);
> + if (si == NULL)
> + panic("uscanner_attach: impossible");
> +
> sc->sc_udev = uaa->device;
>
> err = usbd_set_config_no(uaa->device, 1, 1); /* XXX */
> ***************
> *** 286,292 ****
> /* XXX We only check the first interface */
> err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
> if (!err && sc->sc_iface)
> ! id = usbd_get_interface_descriptor(sc->sc_iface);
> if (err || id == 0) {
> printf("%s: could not get interface descriptor, err=%d,id=%p\n",
> USBDEVNAME(sc->sc_dev), err, id);
> --- 310,316 ----
> /* XXX We only check the first interface */
> err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
> if (!err && sc->sc_iface)
> ! id = usbd_get_interface_descriptor(sc->sc_iface);
> if (err || id == 0) {
> printf("%s: could not get interface descriptor, err=%d,id=%p\n",
> USBDEVNAME(sc->sc_dev), err, id);
> ***************
> *** 323,328 ****
> --- 347,355 ----
>
> sc->sc_bulkin = ed_bulkin->bEndpointAddress;
> sc->sc_bulkout = ed_bulkout->bEndpointAddress;
> + if (si->si_quirks & USCANNERQ_DEFERCLOSE)
> + sc->sc_flags |= USCANNERF_DEFERCLOSE;
> + sc->sc_state |= USCANNER_ATTACHED;
>
> #ifdef __FreeBSD__
> /* the main device, ctrl endpoint */
> ***************
> *** 345,358 ****
> {
> struct uscanner_softc *sc;
> int unit = USCANNERUNIT(dev);
> - usbd_status err;
>
> USB_GET_SC_OPEN(uscanner, unit, sc);
>
> DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n",
> flag, mode, unit));
>
> ! if (sc->sc_dying)
> return (ENXIO);
>
> if (sc->sc_state & USCANNER_OPEN)
> --- 372,384 ----
> {
> struct uscanner_softc *sc;
> int unit = USCANNERUNIT(dev);
>
> USB_GET_SC_OPEN(uscanner, unit, sc);
>
> DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n",
> flag, mode, unit));
>
> ! if (sc->sc_dying || (sc->sc_state & USCANNER_ATTACHED) == 0)
> return (ENXIO);
>
> if (sc->sc_state & USCANNER_OPEN)
> ***************
> *** 360,365 ****
> --- 386,402 ----
>
> sc->sc_state |= USCANNER_OPEN;
>
> + if ((sc->sc_state & USCANNER_SETUP) == 0)
> + uscanner_do_open(sc);
> +
> + return (0); /* success */
> + }
> +
> + int
> + uscanner_do_open(struct uscanner_softc *sc)
> + {
> + usbd_status err;
> +
> sc->sc_bulkin_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
> sc->sc_bulkout_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
> /* No need to check buffers for NULL since we have WAITOK */
> ***************
> *** 396,401 ****
> --- 433,439 ----
> return (ENOMEM);
> }
>
> + sc->sc_state |= USCANNER_SETUP;
> return (0); /* success */
> }
>
> ***************
> *** 420,427 ****
> }
> #endif
>
> ! uscanner_do_close(sc);
>
> return (0);
> }
>
> --- 458,468 ----
> }
> #endif
>
> ! if ((sc->sc_flags & USCANNERF_DEFERCLOSE) == 0)
> ! uscanner_do_close(sc);
>
> + sc->sc_state &= ~USCANNER_OPEN;
> +
> return (0);
> }
>
> ***************
> *** 457,463 ****
> sc->sc_bulkout_buffer = NULL;
> }
>
> ! sc->sc_state &= ~USCANNER_OPEN;
> }
>
> Static int
> --- 498,504 ----
> sc->sc_bulkout_buffer = NULL;
> }
>
> ! sc->sc_state &= ~USCANNER_SETUP;
> }
>
> Static int
> ***************
> *** 468,476 ****
> {
> u_int32_t n, tn;
> usbd_status err;
> ! int error = 0;
>
> ! DPRINTFN(5, ("%s: uscannerread\n", USBDEVNAME(sc->sc_dev)));
>
> if (sc->sc_dying)
> return (EIO);
> --- 509,518 ----
> {
> u_int32_t n, tn;
> usbd_status err;
> ! int error = 0, i;
>
> ! DPRINTFN(5, ("%s: uscannerread: resid %d\n", USBDEVNAME(sc->sc_dev),
> ! uio->uio_resid));
>
> if (sc->sc_dying)
> return (EIO);
> ***************
> *** 492,499 ****
> else
> error = EIO;
> break;
> }
> ! DPRINTFN(1, ("uscannerread: got %d bytes\n", tn));
> error = uiomove(sc->sc_bulkin_buffer, tn, uio);
> if (error || tn < n)
> break;
> --- 534,546 ----
> else
> error = EIO;
> break;
> + }
> + DPRINTFN(1, ("uscannerread: got %d bytes", tn));
> + for (i = 0; i < 16 && i < tn; i++) {
> + DPRINTFN(1, (" 0x%x",
> + ((u_char *)sc->sc_bulkin_buffer)[i]));
> }
> ! DPRINTFN(1, ("\n"));
> error = uiomove(sc->sc_bulkin_buffer, tn, uio);
> if (error || tn < n)
> break;
> ***************
> *** 528,534 ****
> int flag;
> {
> u_int32_t n;
> ! int error = 0;
> usbd_status err;
>
> DPRINTFN(5, ("%s: uscanner_do_write\n", USBDEVNAME(sc->sc_dev)));
> --- 575,581 ----
> int flag;
> {
> u_int32_t n;
> ! int error = 0, i;
> usbd_status err;
>
> DPRINTFN(5, ("%s: uscanner_do_write\n", USBDEVNAME(sc->sc_dev)));
> ***************
> *** 540,549 ****
> error = uiomove(sc->sc_bulkout_buffer, n, uio);
> if (error)
> break;
> ! DPRINTFN(1, ("uscanner_do_write: transfer %d bytes\n", n));
> err = usbd_bulk_transfer(
> sc->sc_bulkout_xfer, sc->sc_bulkout_pipe,
> ! 0, USBD_NO_TIMEOUT,
> sc->sc_bulkout_buffer, &n,
> "uscnwb");
> if (err) {
> --- 587,601 ----
> error = uiomove(sc->sc_bulkout_buffer, n, uio);
> if (error)
> break;
> ! DPRINTFN(1, ("uscanner_do_write: transfer %d bytes", n));
> ! for (i = 0; i < 16 && i < n; i++) {
> ! DPRINTFN(1, (" 0x%x",
> ! ((u_char *)sc->sc_bulkout_buffer)[i]));
> ! }
> ! DPRINTFN(1, ("\n"));
> err = usbd_bulk_transfer(
> sc->sc_bulkout_xfer, sc->sc_bulkout_pipe,
> ! /* USBD_FORCE_SHORT_XFER */0, USBD_NO_TIMEOUT,
> sc->sc_bulkout_buffer, &n,
> "uscnwb");
> if (err) {
> ***************
> *** 615,620 ****
> --- 667,675 ----
> #endif
>
> sc->sc_dying = 1;
> +
> + if ((sc->sc_state & USCANNER_SETUP) != 0)
> + uscanner_do_close(sc);
>
> /* Abort all pipes. Causes processes waiting for transfer to wake. */
> if (sc->sc_bulkin_pipe)