[comp.sys.mac.programmer] Opening the serial driver.

alain@atr-la.atr.co.jp (Alain de Cheveigne) (12/31/89)

I'm updating some code according to TN 249 to use OpenDriver() instead
of RamSDOpen().  I hope in this way to detect when some other terminal
program has opened the line, to avoid opening twice.  The code I use is:

	/* MPW C 3.0 */
	/* test to see if another program owns the serial port */
	short refnum = aoutRefNum;
	result = opendriver("AOut",&refnum);
	if (result == portInUse) {		/* port already open */
		dont_close_serial = true;	/* no need to close on exit */
		return;
	} 

	[test for portNotCf]

	if (result != noErr) {
		errMsg("result: %d", result);	/* say what's wrong */
		error = true;
		return;
	}

	[code to open "AIn"]

The result of opendriver() is always -43, which corresponds to fnfErr
in Errors.h of CInterfaces.  I don't know what that means.  I tried
installing the SERD resources in the program file, with no success.

Questions:

1) What am I doing wrong?

2) If I get OpenDriver() to work, should I still use SerSetBuf(),
SerHShake(), SerReset(), etc., or are they also superseded?

3) If I don't get it to work, is there any objection to keeping with
RamSDOpen()?  

I think Tim Maroney suggested some time back that one can test whether
the port is open with a status call, and open only if that call fails.

4) If the port is already open, I don't need to open, and I don't
close on exit.  I expect other programs to act the same.  What happens
if I opened first, then the other program starts, then I quit.  Is
there anyway of knowing if the other program still needs the port?

5) My program works fine over serial lines.  I'd like it to work over
ethernet, and maybe AppleTalk.  Is there any chance that someone will
come out with a piece of software that will emulate a serial port over
ethernet or AppleTalk?  It would open a window, establish a connection
to a host and let me log in, and from then on the serial port (A or B)
would be redirected through this channel.  I wouldn't need to modify
my code.  

Is this in the CTB?  If so, is there something I should do to be
compatible?  Or shall I really have to modify my code?

Thanks for any help.  If I get good e-mail, I'll summarize.


Alain de Cheveigne,
alain@atr-la.atr.co.jp

svc@well.UUCP (Leonard Rosenthol) (01/02/90)

In article <3903@atr-la.atr.co.jp> alain@atr-la.atr.co.jp (Alain de Cheveigne) writes:
>
>
>I'm updating some code according to TN 249 to use OpenDriver() instead
>of RamSDOpen().  I hope in this way to detect when some other terminal
>program has opened the line, to avoid opening twice.  The code I use is:
>
>	short refnum = aoutRefNum;
>	result = opendriver("AOut",&refnum);
			    ^^^^^^
	I don't use MPW C, but at least in Think C, that would look more like
"\pAOut" so that the compiler knew you wanted a Pascal string. Even if that
call to opendriver took a C string, you would then be missing the NULL. Since
the name opendriver is getting is probably some form of garbage, you get a
fnfErr since it can't open it.

>	if (result == portInUse) {		/* port already open */
>		dont_close_serial = true;	/* no need to close on exit */
>		return;
>	} 
>
	This may be a problem.  When changing MicroPhone II over to use the
OpenDriver call instead of RAMSDOpen, we discovered (much to our dismay) that
we were no longer getting back a 'portInUse' error!   MacDTS has confirmed for
us that they is indeed the case that OpenDriver does not know anything about
'ports in use' and therefore does not return this error code. The solution, of
course (according to DTS) - Use the Comm Toolbox!

>Questions:
>
>1) What am I doing wrong?
>
	See above.

>2) If I get OpenDriver() to work, should I still use SerSetBuf(),
>SerHShake(), SerReset(), etc., or are they also superseded?
>
	The rest of your code stays the same, you are simply doing your own
open.  All RAMSDOpen did was a special case of OpenDriver (like GetIcon is
a special call to GetResource) and so you bypass the middle man, and make 
yourself more compat for the future.

>3) If I don't get it to work, is there any objection to keeping with
>RamSDOpen()?  
>
	At least under System 6.x, it works fine.  I can not say for 7.0

>4) If the port is already open, I don't need to open, and I don't
>close on exit.  I expect other programs to act the same.  What happens
>if I opened first, then the other program starts, then I quit.  Is
>there anyway of knowing if the other program still needs the port?
>
	You would be doing the right thing by not opening, if already in use.
Others might not be so nice and will steal your port, which may/will give you
OSErrs when trying to read or write to the port.
	There is currently no form of 'port contention' handling under System
6.x, but I know that the CTB team has been working with the IAC group so that
apps will be able to talk to each other and handle port contentions in the
future.

>5) My program works fine over serial lines.  I'd like it to work over
>ethernet, and maybe AppleTalk.  Is there any chance that someone will
>come out with a piece of software that will emulate a serial port over
>ethernet or AppleTalk?  It would open a window, establish a connection
>to a host and let me log in, and from then on the serial port (A or B)
>would be redirected through this channel.  I wouldn't need to modify
>my code.  
>
>Is this in the CTB?  If so, is there something I should do to be
>compatible?  Or shall I really have to modify my code?
>
	Welcome to the CommToolbox!  This is probably the most important of
the functions of the CTB and that is to make the transport mechanism of data
more transparent to applications.  This means that given the proper tools, you
app could speak serial, ADSP, Telnet, LAT, etc. and now care!
	It will require you to change many parts of your code and there all
new routines and new calling conventions.  I would suggest that you get yourself
a copy of the CTB from ADPA and get playing!

-- 
+--------------------------------------------------+
Leonard Rosenthol        |  GEnie : MACgician
Lazerware, inc.          |  MacNet: MACgician
UUCP: svc@well.UUCP      |  ALink : D0025

oster@dewey.soe.berkeley.edu (David Phillip Oster) (01/02/90)

In article <15278@well.UUCP> svc@well.UUCP (Leonard Rosenthol) writes:
_>In article <3903@atr-la.atr.co.jp> alain@atr-la.atr.co.jp (Alain de Cheveigne) writes:
_>>
_>>	result = opendriver("AOut",&refnum);
_>			    ^^^^^^
_>	I don't use MPW C, but at least in Think C, that would look more like
_>"\pAOut" so that the compiler knew you wanted a Pascal string. 
 "\p.AOut" is actually the correct value for THINK C.

--- David Phillip Oster            --  No, I come from Boston. I just work
Arpa: oster@dewey.soe.berkeley.edu --  in cyberspace.
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu

beard@ux1.lbl.gov (Patrick C Beard) (01/03/90)

In article <3903@atr-la.atr.co.jp> alain@atr-la.atr.co.jp (Alain de Cheveigne) writes:
>
>
>I'm updating some code according to TN 249 to use OpenDriver() instead
>of RamSDOpen().  I hope in this way to detect when some other terminal
>program has opened the line, to avoid opening twice.  The code I use is:
>	/* MPW C 3.0 */
>	/* test to see if another program owns the serial port */
>	short refnum = aoutRefNum;
>	result = opendriver("AOut",&refnum);
>The result of opendriver() is always -43, which corresponds to fnfErr
>in Errors.h of CInterfaces.
>1) What am I doing wrong?
>

MPW C has lower case equivalents that accept C strings everybody.
Therefore, the call opendriver(char*,short*) takes a  C (i.e. null
terminated) string.  The reason you are getting a fnfErr return code
is that the names for the serial drivers are ".AIn" & ".AOut".  They
have "." characters to avoid conflicts with file names (hopefully).
Therefore, the call

	result = opendriver(".AOut", &refnum);

should work.  The equivalent call using pascal strings is

	result = OpenDriver("\p.AOut", &refnum);

which is more "portable" (between Think and MPW C).  I, for one, will
never use the lower case calls because no other development system
offers them, and I try to keep my strings in pascal form as much as
possible to avoid having to conversions.

On a similar note, does anybody have a library of pascal string manipulation
code lying around?  I guess it would be nice to have all of the regular
C string functions cast in a form to manipulate pascal strings.  I've always
wondered, what do Pascal programmers use to do things like sprintf?




-------------------------------------------------------------------------------
-  Patrick Beard, Macintosh Programmer                        (beard@lbl.gov) -
-  Berkeley Systems, Inc.  ".......<dead air>.......Good day!" - Paul Harvey  -
-------------------------------------------------------------------------------

alain@atr-la.atr.co.jp (Alain de Cheveigne) (01/03/90)

In article <3903@atr-la.atr.co.jp>, alain@atr-la.atr.co.jp (Alain de
Cheveigne) writes:
>I'm updating some code according to TN 249 to use OpenDriver() instead
>of RamSDOpen().  I hope in this way to detect when some other terminal
>program has opened the line, to avoid opening twice.  The code I use is:
[code deleted]
>The result of opendriver() is always -43, which corresponds to fnfErr
>in Errors.h of CInterfaces.  I don't know what that means.  I tried
>installing the SERD resources in the program file, with no success.

Thanks to all who answered my queries.  The trouble was with the driver
names, which I took from the October version of the tech note.  This code
works:

	/* test to see if another program owns the serial port */
	if (SerStatus(OREF,&status) == noErr) {	/* already open */
		dont_close_serial = true;	/* don't close on exit */
		return;
	} /* else */

	/* open serial port drivers */
	refnum = aoutRefNum;
	result = opendriver(".AOut",&refnum);

	[test result for portInUse, portNotCf] [and do what ?]
	[test for other errors]
	[open .Ain]

I use the MPW C 3.0 lower-case version of the opendriver() call, which
accepts C strings.  The standard and probably preferable version would
be: OpenDriver("\p.Aout",&refnum).

The December version of TN 249 corrects the spelling of the drivers.
But the spelling of the constants, and the way they're used in the
call (a pointer to a constant?) are off, at least for MPW C.  And
OpenDriver() doesn't answer portInUse when the port is in use.  Tech
note writers: keep up the good work, you're almost there!

The status call technique suggested by Tim (see code) works.

>Questions:
>[...]
>2) If I get OpenDriver() to work, should I still use SerSetBuf(),
>SerHShake(), SerReset(), etc., or are they also superseded?

They're still ok.

>4) If the port is already open, I don't need to open, and I don't
>close on exit.  I expect other programs to act the same.  What happens
>if I opened first, then the other program starts, then I quit.  Is
>there anyway of knowing if the other program still needs the port?

There seems to be no way.  A pity.  Would be easy if the drivers kept
a count of the number of times they are "opened".  The count would
decrement at each "close", and the driver would close when the count
reaches 0.

The reason for this is to allow several terminal programs to share the
port.  For example, I'm working on a specialized terminal program.  I
don't want to redo a vt-100 or tektronix emulation.  Even if I did, it
would never be as good or complete as Versaterm.  Versaterm is never
going to offer the services my program offers.  I'd like the user to
have both, switching from one to the other under Multifinder.

This model works fine (I use it every day) if a) the programs refrain
from swiping bytes from the background, and b) their interaction with
the host is simple enough.  I'll elaborate if anyone is interested.

By the way, I've just tried removing the RAMSDClose() from my program.
It leaves the port open on exit.  No ill effects yet.  Any objections?


>5) My program works fine over serial lines.  I'd like it to work over
>ethernet, and maybe AppleTalk.  Is there any chance that someone will
>come out with a piece of software that will emulate a serial port over
>ethernet or AppleTalk?  It would open a window, establish a connection
>to a host and let me log in, and from then on the serial port (A or B)
>would be redirected through this channel.  I wouldn't need to modify
>my code.  

Many people recommended the CTB, but it seems it is not exactly the
simple "adaptor" I had in mind.  Seems I can use it only if I modify
my code.  I'll investigate as soon as I can get my hands on it.

I'm a bit disappointed.  I wish I could plug in any off-the-shelf
terminal program (including my own) into an ethernet.


Alain de Cheveigne,
alai@atr-la.atr.co.jp