TweetFollow Us on Twitter

Jun 98 Tips

Volume Number: 14 (1998)
Issue Number: 6
Column Tag: Tips & Tidbits

June 1998 Tips & Tidbits

by Steve Sisak

Over the past few months we've had a few tips submitted on how to open a serial port or detect if it is in use. Unfortunately, we haven't received one that was sufficiently correct or complete to publish as a winner. Since this seems like an interesting topic (and one that lots of people get wrong), I'm going to try a new format: a terse mini-article with enough information to get you started and pointers to more information.

If you like this format, have a good idea for a topic but don't know the answer, or have other ideas how to make this space more useful, please send mail to tips@mactech.com. I'll be glad to pay the standard reward and give you credit for a really good question (assuming I can find the answer and it's generally useful).

Serial Port TidBits

If you've ever tried to write an application which uses the serial port on a Macintosh, you've probably discovered that (1) it didn't work on the first try, (2) the information on what to do was scattered all over the place and (3) it still didn't work in all cases.

In case you haven't, the information for how to correctly open and use the serial drivers is scattered across Inside Macintosh, the Communication Toolbox documentation, the ARA SDK and various tech notes. There are also several misleading and obsolete descriptions in Inside Macintosh Vols. I-VI.

The most authoritative sources are Inside Macintosh: Devices and Tech note 1119, by Quinn (The Eskimo!) which pulls most of the relevant information together in one place.

Listing the Serial Ports

In the beginning, every Macintosh had exactly 2 serial ports named "Modem Port" and "Printer Port" and the names of their drivers were hard coded -- these days PowerBooks often have only one port and/or a built-in modem, NuBus and PCI cards make it possible for the user to add ports, and software creates "virtual" ports to make it possible for multiple programs to share the same physical port.

To determine how many ports a machine has and what their human-readable name are, you need to use the Communications Resource Manager (CRM), which is part of the Communications Toolbox (one of those managers that Apple has declared obsolete, but hasn't gotten around to replacing yet).

For each port, the CRM maintains a CRMSerialRecord containing the following information:

typedef struct CRMSerialRecord {
  short         version;
  StringHandle   inputDriverName;
  StringHandle   outputDriverName;
  StringHandle   name;
  CRMIconHandle  deviceIcon;
  long           ratedSpeed;
  long           maxSpeed;
  long           reserved;
} CRMSerialRecord, *CRMSerialPtr;

To iterate over the available ports, you use the function CRMSearch(). The following code fragment finds a port by name -- you can easily adapt it to build a menu, etc.:

CRMSerialPtr FindPortInfo(ConstStr255Param name)
{
  CRMRec      crmRec;
  CRMRecPtr    crm   = &crmRec;

  // Get the search started
  crmRec.crmDeviceType = crmSerialDevice;  crmRec.crmDeviceID   = 0;

  while ((crm = CRMSearch(crm)) != nil)
  {
    CRMSerialPtr portInfo = 
      (CRMSerialPtr) crm->crmAttributes;
    
    if (EqualString(*portInfo->name, name, false, true))
    {
      return portInfo;
    }
  }
  
  return nil;
}

Opening, Initializing and Closing a Serial port

There is a specific sequence of calls you must use to open, configure and close a serial port. It is listed in Inside Macintosh: Devices on page 7-11. If you do not make the calls in this order, strange things will happen.

The sequence is:

  1. Open the output driver, then the input driver; always open both.
  2. (optional) allocate a buffer larger than the default 64-byte buffer and call SerSetBuf.
  3. Set the handshaking mode.
  4. Set the baud rate and data format.
  5. Read and/or write the desired data.
  6. Call KillIO on both drivers to terminate any pending IO.
  7. Restore the default input buffers.
  8. Close the input driver, then the output driver.

Determining If a Serial Driver is Open

Determining if a serial driver is open in use is a little bit tricky and a lot of software gets it wrong. The problem is twofold: first, OpenDriver() doesn't bother to check if a driver is already open -- it just returns noErr and the reference number of the already-open driver. If you use it (or worse, close it when you're done) Bad Things(tm) will happen.

To get around this you must walk the device list in low memory to see if a driver is already open before trying to open it again.

The following routine finds the index of a driver in the unit table (or -1 if it doesn't exist):

short FindDriverIndex(ConstStr255Param name)
{
  StringPtr    driverName;
  short      index;
  AuxDCEHandle  entry;
  AuxDCEHandle*  table = (AuxDCEHandle*) LMGetUTableBase();
  short      count = LMGetUnitNtryCount();
  
  for (index = 0; index < count; index++)
  {
    if ((entry = table[index]) != nil)
    {
      if ((**entry).dCtlFlags & dRAMBasedMask)
      {
        driverName = (**((DRVRHeaderHandle)((**entry).dCtlDriver))).drvrName;
      }
      else
      {
        driverName = (*((DRVRHeaderPtr)((**entry).dCtlDriver))).drvrName;
      }
      
      if (EqualString(driverName, name, false, true))
      {
        return index;
      }
    }
  }
  
  return -1;
}

To check if a port is open, we can write:

Boolean  IsDriverOpen(ConstStr255Param name)
{
  short index = FindDriverIndex(name);
  
  if (index >= 0)
  {
    AuxDCEHandle dce = 
      ((AuxDCEHandle*) LMGetUTableBase())[index];
    
    if ((**dce).dCtlFlags & dOpenedMask)
    {
      return true;
    }
  }
  
  return false;
}

NOTE: LMGetUTableBase() is missing from some versions of the Universal Headers you may have to implement it yourself (or use newer headers).

Now for the second half of the problem -- the Serial Port Arbitrator, included with the Appletalk Remote Access server and other software allows a port to be opened "passively" meaning that a server may have a the port open to look for an incoming call, but will relinquish it if another application wants to use it.

In this case OpenDriver will return portInUse (-97) if the driver is open or noErr if it is not. (in either case, it will return a valid refNum). However, software which walks the device table will incorrectly think that the driver is open and report an error.

The correct procedure here is to use Gestalt to determine if the Serial Port Arbitrator is present and, if it is, then just call OpenDriver(), otherwise, walk the Unit Table:

Boolean  HaveSerialPortArbitration(void)
{
  long  result;
  OSErr  err;
  
  err = Gestalt(gestaltArbitorAttr, &result);
  
  return (err == noErr) && (result & (1 << gestaltSerialArbitrationExists));
}

OSErr OpenSerialDriver(ConstStr255Param name, short* refNum)
{
  if (!HaveSerialPortArbitration())
  {
    short index = FindDriverIndex(name);

    if (index >= 0)  // Driver is already open
    {
      *refNum = ~index;
      return portInUse;
    }
  }
  
  return OpenDriver(name, refNum);
}

Reading from a Serial Port

You can read from a serial port just like a file by using PBRead or FSRead, however you can't seek and if you try to read more bytes are actually available, you will hang the machine in SyncWait() until the number of bytes you requested is actually available.

To avoid this, you can make a status call to the input driver with csCode = 2 to find out how many bytes are available in the drivers buffer and then only request that many bytes.

Correction to May Tip -- Wrapper for ParamText

The tip "Wrapper for ParamText" incorrectly states that one cannot pass nil arguments to ParamText(). In fact, ParamText() has always accepted nil arguments, and leaves the corresponding parameters unchanged.

I use this feature frequently in order to conserve stack space. I can set all 4 parameters using only one Str255, as long as I do it one at a time.

Actually, this example only sets 3 params:

  void
ReportError( short doingIx, const char *what )
{
Str255          str;

  if( spareMem )
    DisposeHandle( spareMem );
  spareMem = NULL;

  CtoPstrcpy( str, (const unsigned char *)what, sizeof str );
  ParamText( str, NULL, NULL, NULL );

  GetErrString( doingIx, str );
  ParamText( NULL, str, NULL, NULL );

  /* Eww. But I don't have to ParamText menu item text every command,
    which might slow things down if we're being scripted.
  */

  if( doingIx == doingMenuCmd ) {
    str[0] = 0;
  if( tg.doingItem )
      GetID( tg.doingItem, str );
    ParamText( NULL, NULL, NULL, str );
  }

  else if( doingIx == doingMenuAct ) {
    str[0] = 0;
    if( tg.doingItem && tg.doingMenu )
    GetMenuItemText( GetMenu(tg.doingMenu), tg.doingItem, str );
    ParamText( NULL, NULL, NULL, str );
  }

  VerifyAlert( 144 );
  InitCursor();
  StopAlert( 144, DefaultFilter );
}

Tony Nelson
tonyn@tiac.net

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

iDefrag 5.0.0 - Disk defragmentation and...
iDefrag helps defragment and optimize your disk for improved performance. Features include: Supports HFS and HFS+ (Mac OS Extended). Supports case sensitive and journaled filesystems. Supports... Read more
PCalc 4.2 - Full-featured scientific cal...
PCalc is a full-featured, scriptable scientific calculator with support for hexadecimal, octal, and binary calculations, as well as an RPN mode, programmable functions, and an extensive set of unit... Read more
FileZilla 3.10.2 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.10.2: Note: Now requires a 64-bit Intel processor.... Read more
The Hit List 1.1.11 - Advanced reminder...
The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more
Bartender 1.2.32 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more
ClamXav 2.7.5 - Free virus checker, base...
ClamXav is a free virus checker for OS X. It uses the tried, tested, and very popular ClamAV open source antivirus engine as a back end. I hope you like and use ClamXav a lot and that it helps keep... Read more
xScope 4.1.2 - Onscreen graphic measurem...
xScope is powerful set of tools that are ideal for measuring, inspecting, and testing on-screen graphics and layouts. Its tools float above your desktop windows and can be accessed via a toolbar,... Read more
MacFamilyTree 7.3.3 - Create and explore...
MacFamilyTree gives genealogy a facelift: it's modern, interactive, incredibly fast, and easy to use. We're convinced that generations of chroniclers would have loved to trade in their genealogy... Read more
Skype 7.5.0.738 - Voice-over-internet ph...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
PushPal 3.0 - Mirror Android notificatio...
PushPal is a client for Pushbullet, which automatically shows you all of your phone's notifications right on your computer. This means you can see who's calling or read text messages even if your... Read more

It Came From Canada: Jurojin: Immortal N...
At this point it’s pretty safe to say that no MOBA is going to dethrone Dota 2 and League of Legends anytime soon. After all, if Batman can’t do it, nobody can. However, with a genre as popular and profitable as this one, there’s still room for... | Read more »
Tiny Farm – Animals, Tractors and Advent...
Tiny Farm – Animals, Tractors and Adventures! Review By Amy Solomon on March 3rd, 2015 Our Rating: :: LIVELY LANDSCAPESUniversal App - Designed for iPhone and iPad Tiny Farm – Animals, Tractors and Adventures! includes farm-related... | Read more »
This Week at 148Apps: February 23-27, 20...
Final February Fun at 148Apps   How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you’re looking for. The ones we love become Editor’s Choice, standing out... | Read more »
GDC 2015 – Does Not Commute is Definitel...
GDC 2015 – Does Not Commute is Definitely a Game You Should Keep an Eye on Posted by Rob Rich on March 2nd, 2015 [ permalink ] We were teased about Mediocre Games’ (Smash Hit, | Read more »
F84 Games & POW! Announce Stan Lee V...
F84 Games has announced that it is working with legendary comic creator Stan Lee and POW! Entertainment to produce Stan Lee’s Hero Command. The game will be a action adventure of heroic proportions. | Read more »
Setlyst Keeps Your Set Straight So You C...
Setlyst Keeps Your Set Straight So You Can Focus On Rocking Out. Posted by Jessica Fisher on March 2nd, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Space is Vast, So Space Agency Has a Vas...
Space is Vast, So Space Agency Has a Vast New Update! Posted by Jessica Fisher on March 2nd, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Size DOES Matter Review
Size DOES Matter Review By Campbell Bird on March 2nd, 2015 Our Rating: :: HARD TO BEATUniversal App - Designed for iPhone and iPad This rhythm game has a unique control scheme and performance system that make it feel like a true... | Read more »
The first ever action 3D card battler Al...
On the other hand, you probably haven’t played an action 3D card battler – until now. Step forward, All Star Legion. All Star Legion is a 3D QTE-based action RPG card battler, but fear not – the game itself isn’t as convoluted as its description.... | Read more »
Travel Back to the 1980s With the Making...
Headup Games has released a hilarious making of video for its upcoming title, Pixel Heroes: Byte & Magic. The game is a RPG/Roguelike where you control three heroes set to save the township of Pixton from an evil cult called The Sons of Dawn.... | Read more »

Price Scanner via MacPrices.net

Sale! 15-inch 2.2GHz Retina MacBook Pro for $...
 Best Buy has the 15″ 2.2GHz Retina MacBook Pro on sale for $1774.99 $1799.99, or $225 off MSRP. Choose free home shipping or free local store pickup (if available). Price valid for online orders... Read more
27-inch 3.5GHz 5K iMac in stock today and on...
 B&H Photo has the 27″ 3.5GHz 5K iMac in stock today and on sale for $2299 including free shipping plus NY sales tax only. Their price is $200 off MSRP, and it’s the lowest price available for... Read more
Apple Launches Free Web-Based Pages and Other...
Apple’s new Web-only access to iWork productivity apps is a free level of iCloud service available to anyone, including people who don’t own or use Apple devices. The service includes access to Apple... Read more
Survey Reveals Solid State Disk (SSD) Technol...
In a recent SSD technology use survey, Kroll Ontrack, a firm specializing in data recovery, found that while nearly 90 percent of respondents leverage the performance and reliability benefits of SSD... Read more
Save up to $600 with Apple refurbished Mac Pr...
The Apple Store is offering Apple Certified Refurbished Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Updated Mac Price Trackers
We’ve updated our Mac Price Trackers with the latest information on prices, bundles, and availability on systems from Apple’s authorized internet/catalog resellers: - 15″ MacBook Pros - 13″ MacBook... Read more
Apple CEO Tim Cook to Deliver 2015 George Was...
Apple CEO Tim Cook will deliver the George Washington University’s Commencement address to GWU grads on May 17, at which time he will also be awarded an honorary doctorate of public service from the... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz... Read more
Save up to $50 on iPad Air 2s, NY tax only, f...
 B&H Photo has iPad Air 2s on sale for $50 off MSRP including free shipping plus NY sales tax only: - 16GB iPad Air 2 WiFi: $469.99 $30 off - 64GB iPad Air 2 WiFi: $549 $50 off - 128GB iPad Air 2... Read more
16GB iPad Air 2 on sale for $447, save $52
Walmart has the 16GB iPad Air 2 WiFi on sale for $446.99 on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale price for online orders only,... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* Pay Automation Engineer - iOS System...
**Job Summary** At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring passion and dedication to your job Read more
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.