Subject: Some experience about Epson GT-9700F usb scanner.
To: None <tech-kern@netbsd.org>
From: enami tsugutomo <enami@but-b.or.jp>
List: tech-kern
Date: 12/02/2001 18:34:35
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)