Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Apr 2002 00:54:46 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Peter Haight <peterh@sapros.com>
Cc:        Nick Hibma <n_hibma@van-laarhoven.org>, <hardware@FreeBSD.ORG>
Subject:   Re: Reading from the USB ugen device. 
Message-ID:  <20020417003939.B8131-100000@gamplex.bde.org>
In-Reply-To: <200204151747.g3FHlPRg037046@wartch.sapros.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 15 Apr 2002, Peter Haight wrote:

> >> From what you told me and a brief look at the USB spec, I'm guessing it
> >> isn't a coincidence that it is failing on that read where I'm expecting 64
> >> bytes (the max size of a USB packet payload). I'm guessing that in short
> >> read mode, the driver gets a full length packet and is expecting another
> >> data packet but it never comes because that's the end of the data, so it
> >> doesn't return from the read until it gets a timeout.
> >
> >No. If you read 64 byes in 64 bytes with short_XFER switched on you will
> >be reading 64 bytes and then 0 bytes.
>
> Ok. But why does this happen:
>
> read(3, 0x8091800, 1024)
> read -1 bytes
>
> At that same point in the protocol if I do:
> read(3, 0x8091800, 64)
> read 64 bytes
>
> I would expect:
> read(3, 0x8091800, 1024)
> read 64 bytes

This might be caused by longstanding brokenness in sys_generic.c.  E.g.,
in dofileread():

	cnt = nbyte;
	if ((error = fo_read(fp, &auio, fp->f_cred, flags, td))) {
		if (auio.uio_resid != cnt && (error == ERESTART ||
					      ^^^^^^^^^^^^^^^^^^^^
		    error == EINTR || error == EWOULDBLOCK))
		    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
			error = 0;
	}
	cnt -= auio.uio_resid;

The underlined code arranges for the correct i/o count for non-null
i/o to actually be returned to the application if the next lowest level
of read() returned ERESTART, EINTR or EWOULDBLOCK.  All other cases
are broken -- both POSIX and POLA specify that if any i/o was done,
then read()/write() shall return a count of the amount done (usually
but not necessarily a short count).  Try removing this and all other
similar "&&" clauses in sys_generic.c.

There are surprisingly few files where this actually matters.  For
regular files on most filesystems, the filesystem unwinds the i/o, so
the auio.uio_resid != cnt case is not even seen here.  But i/o is
normally unwindable for devices.

Here the problem may be the more immediate one that usb returns EIO
instead of EWOULDBLOCK when it can't proceed.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hardware" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020417003939.B8131-100000>