Serial port, unix calls, some thoughts
John M McIntosh
johnmci at smalltalkconsulting.com
Tue May 27 05:34:32 UTC 2003
Dan asked me to add a better degree of serial support to the mac os-x
VM, and it seems one just uses the Unix calls for this, versus apple
specific stuff.
Now in looking at this I was thinking here I've all these calls like
cfgetispeed, cfgetospeed, cfmakeraw, cfsetispeed, cfsetospeed, open,
close, read, write, ioctl
tcdrain, tcFlow,t cFlush, tcgetattr, tcsetattr, tcsendbreak
So I was thinking, why not make the actual primitives really sparse to
avoid C code that would require
support and VM changes, and then produce implementation specific
subclasses like so?
SerialPortExtended
SerialPortExtendedUnix
SerialPortExtendedUnixOSX
Which deal with implementation issues. Usually in the past we would
code up a generic plugin routine, which calls
a platform specific routine, which then requires maintenance usually
done by only a few VM maintainers hidden in the
sourceforge source tree, versus an easily accessible chunk of Smalltalk
code.
So for example
SerialPortExtendedUnix >>cancel
"tcflush does a cancel and zaps the pending inbound and outbound bytes"
| error |
error _ self primitiveSerialPortUnixTcflush: fd action: self tcioflush.
error isZero ifFalse: [SerialPortExtendedError signal: error asString]
SerialPlugin>>primitiveSerialPortUnixTcflush: fd action: aNumber
| error |
self primitive: 'primitiveSerialPortUnixTcflush'
parameters: #(SmallInteger SmallInteger).
self cCode: 'error = tcflush(fd,aNumber); if (error == -1) error =
errno' inSmalltalk: [error _ 1].
^ error asSmallIntegerObj
Mmm in the past this might have been just a call to a generic flush,
which calls the unix serial port code, which does
the tcflush(fd,TCIOFLUSH). Now if some squeaker really wanted to do a
tcflush(fd,TCOFLUSH) instead then well it's
easy to add that method call and primitive hookup, even to make it an
enhancement and lobby to get it into
the base image. However past thinking would require a VM change, by the
powers that be, or by managing your own personal VM.
{I'll note that I do capture errno in the C code, versus looking for it
in the smalltalk, however my concern is that
going to get errno after the fact might return zero because someother
unix call(s) could be made before our
process thread could retrieve it.}
On the downside, if for example your termios structure is different
that the OSX one why then you need a
different subclass of the basetermios class which allows you to
put/extract bytes/ints from the structure.
Normally that problem would be hidden away in the C code and your
platform specific vm would deal with the issues, so all is not happy.
Another example would be CTS/DTR control by exposing SerHShake for os9,
and ioctl for os-x/unix.
which then exposes all sorts of other support so if someone really
wants to see TIOCM_CAR then they
can without having someone build a new vm.
In some respects this begs the question about using FFI more since once
could do a lot more with FFI.
For the open,close,read,write,ioctl calls, any thoughts on where they
should go? They aren't serial port
specific, do we have a lightweight unix plugin we can hide them in?
PS as another example consider <primitive: 'primitiveFileRead' module:
'FilePlugin'>
it really resolves after some time into a call to fread. But doesn't
return or check ferror(). So on an I/O
error by the time things migrate up to smalltalk objects one can't
discover why the error occurred. If that was a sparse
method call, someone might have gotten motivated and posted a changeset
to call ferror()? in the non-existent
StandardFileStreamUnix class when they discovered fread returned zero.
So thoughts?
--
========================================================================
===
John M. McIntosh <johnmci at smalltalkconsulting.com> 1-800-477-2659
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
========================================================================
===
More information about the Squeak-dev
mailing list
|