[comp.sys.sgi] ioctl

acl3k@agate.cs.Virginia.EDU (Allan Christian Long) (05/22/91)

	I'm trying to convert a tracking library from SunOS to IRIX.
I managed to get it to compile, but it isn't working.  Specifically,
the an ioctl call is giving me an "Invalid argument error".  The
call looks like this:

	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)

The first parameter is a file descriptor and the third is a pointer to
a long.  FIONREAD is a parameter from the termio.h file.  I have RTFM'ed
until I'm blue in the face, but I can't find FIONREAD mentioned anywhere
in any of the manuals.  The SunOS manual has a page on "filio" that
describes this parameter, but there is no filio page for IRIX.
	Could someone please point me in the direction of a man page or
something?


A. Chris Long, Jr.  			acl3k@virginia.edu
Rebooting sig, please wait...

rpw3@rigden.wpd.sgi.com (Rob Warnock) (05/22/91)

In article <1991May21.224750.535@murdoch.acc.Virginia.EDU>
acl3k@agate.cs.Virginia.EDU (Allan Christian Long) writes:
+---------------
| an ioctl call is giving me an "Invalid argument error".  The
| call looks like this:
| 
| 	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)
| 
| The first parameter is a file descriptor and the third is a pointer to
| a long.  FIONREAD is a parameter from the termio.h file.  I have RTFM'ed
| until I'm blue in the face, but I can't find FIONREAD mentioned anywhere
| in any of the manuals.  The SunOS manual has a page on "filio" that
| describes this parameter, but there is no filio page for IRIX.
+---------------

In /usr/include/sys/ioctl.h, one finds:

	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */

Sadly, this is about all that exists. The rest does indeed seem to have
fallen between the cracks. (*sigh*) It should be in at least *one* of
ioctl(2), fcntl(2), socket(2), termio(7), or streamio(7), but isn't.

And the comment in ioctl.h is even a bit misleading. Well, the SunOS
filio(2) man page should be good enough. FIONREAD is the same on all
systems I know of -- that support it, that is, not all do. It returns
the number of bytes immediately available for reading (i.e., without
blocking) from the file descriptor. In Irix, it *should* work on plain
files, pipes, sockets, and terminal devices (TTYs and PTYs). What kind
of device is "trackerPtr->fileDescriptor"? If it's a special 3rd-party
beast, perhaps the Irix device driver doesn't support FIONREAD...


-Rob

p.s. I just checked, and on Irix 3.3.2, FIONREAD is not supported on
pipes or plain files. You get errno=25. Weird. (Bug?)

-----
Rob Warnock, MS-1L/515		rpw3@sgi.com		rpw3@pei.com
Silicon Graphics, Inc.		(415)335-1673		Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311

silvert@cs.dal.ca (Bill Silvert) (05/22/91)

In article <1991May21.224750.535@murdoch.acc.Virginia.EDU> acl3k@agate.cs.Virginia.EDU (Allan Christian Long) writes:
>
>	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)
>
>The first parameter is a file descriptor and the third is a pointer to
>a long.  FIONREAD is a parameter from the termio.h file.  I have RTFM'ed
>until I'm blue in the face, but I can't find FIONREAD mentioned anywhere
>in any of the manuals.  The SunOS manual has a page on "filio" that
>describes this parameter, but there is no filio page for IRIX.

On my PI with Irix 3.3.1 the value of FIONREAD is defined in
sys/ioctl.h, not in sys/termio.h -- termio.h  defines oFIONREAD, but you
need to look at ioctl.h and figure out the cryptic low-level code there
to get the value of FIONREAD.

As a general rule, I find that grepping my way through /usr/include and
/usr/include/sys is the best way to solve these header problems.
-- 
William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography
P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2.  Tel. (902)426-1577
UUCP=..!{uunet|watmath}!dalcs!biome!silvert
BITNET=silvert%biome%dalcs@dalac	InterNet=silvert%biome@cs.dal.ca

acl3k@jade.cs.Virginia.EDU (Allan Christian Long) (05/22/91)

In article <1991May22.143844.6858@cs.dal.ca> silvert%biome@cs.dal.ca writes:
>In article <1991May21.224750.535@murdoch.acc.Virginia.EDU> acl3k@agate.cs.Virginia.EDU (Allan Christian Long) writes:
>>
>>	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)
>>
>>The first parameter is a file descriptor and the third is a pointer to
>>a long.  FIONREAD is a parameter from the termio.h file.  I have RTFM'ed
>>until I'm blue in the face, but I can't find FIONREAD mentioned anywhere
>>in any of the manuals.  The SunOS manual has a page on "filio" that
>>describes this parameter, but there is no filio page for IRIX.
>
>On my PI with Irix 3.3.1 the value of FIONREAD is defined in
>sys/ioctl.h, not in sys/termio.h -- termio.h  defines oFIONREAD, but you
>need to look at ioctl.h and figure out the cryptic low-level code there
>to get the value of FIONREAD.
You're right, it was in ioctl.h, not termio.h.

>
>As a general rule, I find that grepping my way through /usr/include and
>/usr/include/sys is the best way to solve these header problems.
The problem is that the prototype for ioctl is

	int ioctl (int fildes, int request, ...);

That says what the first and second parameters should be, but I need to
find out about the rest, which are dependent upon what request is.  The
entry for FIONREAD in ioctl.h is

	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */

I tried changing charToRead to an int, but that didn't help.  I need
documentation for FIONREAD, more than what it says in the header file.

>-- 
>William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography
>P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2.  Tel. (902)426-1577
>UUCP=..!{uunet|watmath}!dalcs!biome!silvert
>BITNET=silvert%biome%dalcs@dalac	InterNet=silvert%biome@cs.dal.ca


A. Chris Long, Jr.			acl3k@virginia.edu

vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (05/23/91)

> On my PI with Irix 3.3.1 the value of FIONREAD is defined in
> sys/ioctl.h, not in sys/termio.h -- termio.h  defines oFIONREAD,


Be careful.  The "old versions" of the ioctl's, including oTCGETA and
oFIONREA are going to go away as soon as possible.  They would have
disappeared from 4.0, except for things I characterize as politics.  They
were intended only to bridge a little binary compatibility.  I seem to
recall defining oFIONREAD to be compatible with a previous release of UNIX
for the IRIS 3000/2000 series; it has been a while.


Vernon Schryver,  vjs@sgi.com.

acl3k@agate.cs.Virginia.EDU (Allan Christian Long) (05/23/91)

In article <105553@sgi.sgi.com> rpw3@sgi.com (Rob Warnock) writes:
>In article <1991May21.224750.535@murdoch.acc.Virginia.EDU>
>acl3k@agate.cs.Virginia.EDU (Allan Christian Long) writes:
>+---------------
>| an ioctl call is giving me an "Invalid argument error".  The
>| call looks like this:
>| 
>| 	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)
>| 
>| The first parameter is a file descriptor and the third is a pointer to
>| a long.  FIONREAD is a parameter from the termio.h file.  I have RTFM'ed
>| until I'm blue in the face, but I can't find FIONREAD mentioned anywhere
>| in any of the manuals.  The SunOS manual has a page on "filio" that
>| describes this parameter, but there is no filio page for IRIX.
>+---------------
>
>In /usr/include/sys/ioctl.h, one finds:
>
>	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */
>
>Sadly, this is about all that exists. The rest does indeed seem to have
>fallen between the cracks. (*sigh*) It should be in at least *one* of
>ioctl(2), fcntl(2), socket(2), termio(7), or streamio(7), but isn't.
>
>And the comment in ioctl.h is even a bit misleading. Well, the SunOS
>filio(2) man page should be good enough. FIONREAD is the same on all
>systems I know of -- that support it, that is, not all do. It returns
>the number of bytes immediately available for reading (i.e., without
>blocking) from the file descriptor. In Irix, it *should* work on plain
>files, pipes, sockets, and terminal devices (TTYs and PTYs). What kind
>of device is "trackerPtr->fileDescriptor"? If it's a special 3rd-party
>beast, perhaps the Irix device driver doesn't support FIONREAD...
>

I wrote the worlds simplest ioctl program that just opens a file and
does ioctl(fildes, FIONREAD, &numChars) on it (where fildes and numChars
are defined appropriately).  I tried it on regular terminals and it gave
error 22, which is EINVAL -- "Request or the third argument is not valid
for this device." (quoting from the ioctl man page)  The device that I
really want to be able to use this on is a Polhemus 3D tracker hooked up
to a serial port.  I've been hooking it up to port 2 and using device
/dev/ttyd2.
	Is there any other way to find out how many bytes there are
to read from a serial line?

>
>-Rob
>
>p.s. I just checked, and on Irix 3.3.2, FIONREAD is not supported on
>pipes or plain files. You get errno=25. Weird. (Bug?)
>Mountain View, CA  94039-7311

If it makes any difference, I'm running this on a 4D/310 VGX running
IRIX 3.3.2.

	Thanks.


A. Chris Long, Jr.			acl3k@virginia.edu

rpw3@rigden.wpd.sgi.com (Rob Warnock) (05/23/91)

In article <105553@sgi.sgi.com> I wrote:
+-+-------------
| | an ioctl call is giving me an "Invalid argument error".  The
| | call looks like this:
| | 	if (ioctl(trackerPtr->fileDescriptor, FIONREAD, &charsToRead) < 0)
| +---------------
| ... I just checked, and on Irix 3.3.2, FIONREAD is not supported on
| pipes or plain files. You get errno=25.
+---------------

As a work-around, you might try using select() in polling mode as a (partial)
replacement for icotl(,FIONREAD,). A select() "poll" can be done by providing
a "timeout" argument (a pointer to a "struct timeval"), but making the "timval"
structure pointed to contain all zeros. See the select(2) man page.


-Rob

-----
Rob Warnock, MS-1L/515		rpw3@sgi.com		rpw3@pei.com
Silicon Graphics, Inc.		(415)335-1673		Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311

rpw3@rigden.wpd.sgi.com (Rob Warnock) (05/23/91)

In article <1991May22.161432.25064@murdoch.acc.Virginia.EDU>
acl3k@jade.cs.Virginia.EDU (Allan Christian Long) writes:
+---------------
| The problem is that the prototype for ioctl is
| 	int ioctl (int fildes, int request, ...);
| That says what the first and second parameters should be, but I need to
| find out about the rest, which are dependent upon what request is.  The
| entry for FIONREAD in ioctl.h is
| 	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */
| I tried changing charToRead to an int, but that didn't help.  I need
| documentation for FIONREAD, more than what it says in the header file.
+---------------

The third arg for FIONREAD is the *address* of an integer, that is:

	int num_bytes_avail_to_read;

	err = ioctl(file_descriptor, FIONREAD, &num_bytes_avail_to_read);

Note that the number of bytes actually avilable to read without blocking
may change (increase) between the time you do the FIONREAD and the time you
actually do the read(). For this reason, I never use the return value
(in "num_bytes_avail_to_read", above) for anything but a binary flag to
say there's something available to read without blocking. I do the read
full-sized and use the return value from the read() to say how much was
actually there:

	int n;
	char buf[BUFSIZ];	/* or whatever size */

	if (ioctl(s, FIONREAD, &n) < 0) {    /* "s" is the file descriptor */
		...handle error...
	}
	if (n > 0) {
		n = read(s, buf, sizeof buf);
		if (n < 0) {
			...handle error...
		}
		...
	}

If this is all you are using FIONREAD for, you can alternatively use select(2),
though a bit more awkwardly:

     #include <sys/types.h>
     #include <sys/time.h>

	fdset in_set;
	struct timeval t0;
	int err;

	t0.tv_sec = 0;
	t0.tv_usec = 0;
	FD_ZERO(&in_set);
	FD_SET(s, &in_set);
	err = select(s + 1, &in_set, (fd_set *)0, (fd_set *)0, &t0);
	if (err < 0) {
		...handle error...
	}
	if (FD_ISSET(s, &in_set)) {
		n = read(s, buf, sizeof buf);
		if (n < 0) {
			...handle error...
		}
		...
	}

Of course, if there is only one file descriptor being polled, as in the
example above, the return value from the select() can be checked (err > 0)
instead of the FD_ISSET(). But using FD_ISSET() generalizes nicely to
multiple-channel polls:

	err = select(...)
	if (err < 0) {
		...handle error...
	}
	if (err > 0) {		/* SOME channel is ready */
		if (FD_ISSET(fd1, &in_set)) {
			n = read(fd1, ...);
			...
		}
		if (FD_ISSET(fd2, &in_set)) {
			n = read(fd2, ...);
			...
		}
		...and so on...
	}


-Rob

-----
Rob Warnock, MS-1L/515		rpw3@sgi.com		rpw3@pei.com
Silicon Graphics, Inc.		(415)335-1673		Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311

acl3k@pine.cs.Virginia.EDU (Allan Christian Long) (05/24/91)

In article <105737@sgi.sgi.com> rpw3@sgi.com (Rob Warnock) writes:
>In article <1991May22.161432.25064@murdoch.acc.Virginia.EDU>
>acl3k@jade.cs.Virginia.EDU (Allan Christian Long) writes:
>+---------------
>| The problem is that the prototype for ioctl is
>| 	int ioctl (int fildes, int request, ...);
>| That says what the first and second parameters should be, but I need to
>| find out about the rest, which are dependent upon what request is.  The
>| entry for FIONREAD in ioctl.h is
>| 	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */
>| I tried changing charToRead to an int, but that didn't help.  I need
>| documentation for FIONREAD, more than what it says in the header file.
>+---------------
>
>The third arg for FIONREAD is the *address* of an integer, that is:
>
>	int num_bytes_avail_to_read;
>
>	err = ioctl(file_descriptor, FIONREAD, &num_bytes_avail_to_read);

I tried a call exactly like this, but I always got error 22 (invalid
argument).  

[stuff about how # of bytes can change right after the ioctl call and
how you can use read() since it returns the number of bytes actually read]

If I were writing a program from scratch, this would probably be fine.
I may not have mentioned, tho, that what I'm doing is porting a tracker
library from SunOS to IRIX (a library that I didn't write).  I COULD use
read, but it would require some rewiring of the library that would be
somewhat difficult.  What I'd really like to have is a way to tell how
many bytes there are to be read without actually reading them.
	Thanks to everyone who has responded.  I'm still open to suggestions.
If I don't get any soon, I'll probably go ahead and rewrite part of the
library to use read() and/or select().

- Chris


A. Chris Long, Jr.			acl3k@virginia.edu
If only we could overcome our tools...

acl3k@agate.cs.Virginia.EDU (Allan Christian Long) (05/25/91)

	First, I'd like to thank everyone who replied to my postings
(via email and postings), as well as the people at SGI technical support.
I called them a couple times and everyone I talked to was very helpful.
	As a result of some source code an SGI engineer sent me,
I discovered that the problem was the compiler.  I was using GNU gcc,
which for some reason or another doesn't compile the ioctl FIONREAD
call correctly.  After recompiling that part of my code with the MIPS
cc compiler, the ioctl problem went away.  (Now I have another problem,
but that's a different story.  Has anybody ever connected a Polhemus
to an Iris?)
	I guess this goes to show you can't trust any piece of software.

- Chris


A. Chris Long, Jr.			acl3k@virginia.edu
If only we could overcome our tools...