Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Networking With Open Transport / Part 1 - Open Transport Essentials
Chapter 8 - Ports


Using Ports

This section describes how to obtain port information, and how to register as an Open Transport client.

Obtaining Port Information

If your application manipulates ports, you may need port information to locate a specific port or to find out how what ports are registered on your computer. Open Transport registers all ports on your computer and creates a port structure for each port. You can then use the various Open Transport port functions to access these structures and get information from them. The port structure is described in "The Port Structure".

If you want to find out the port associated with a given provider, you can use the OTGetProviderPortRef function. If you don't know which port structure you want or if you want to provide a list of user-readable port names to your user, you can use the OTGetIndexedPort function to iterate through all the ports available on a computer, obtaining the port structure of each.

There are also two functions you can use to find the port structure for a specific port: If you know its port name, you can use the OTFindPort function, or if you know its port reference, you can use the OTFindPortByRef function.

If you want to use the OTFindPortByRef function, you need a port reference. There are several ways you can get one: Another application might have passed it to you, another application could have put it into a port structure that you can access by using the OTGetIndexedPort function, or you can create one.

To create a port reference, you use the OTCreatePortRef function. You must know all the port's hardware characteristics: its device and bus type, its slot number, and its multiport identifier (if it has one). You cannot use wildcards to fill in any element you don't know. Possible device and bus types are described in "The Port Reference".

For example, if you want to find out the port name of the Ethernet port in NuBus slot 13, you can use this line of code to create a port reference for this port:

OTPortRef ref = OTCreatePortRef(kOTNuBus, kOTEthernetDevice, 13, 0);
If you then pass the result of this call to the OTFindPortByRef function, OTFindPortByRef fills a buffer with the port structure that has this port reference and returns a pointer to the buffer. You can examine the port structure's fields for its port name.

Open Transport has predefined variants of the OTCreatePortRef function for the most commonly used hardware devices such as the NuBus, PCI, and PCMCIA devices. These are found in the section describing the function OTCreatePortRef .

If you want to extract information from a port reference, you have to use specific Open Transport functions: OTGetDeviceTypeFromPortRef, OTGetBusTypeFromPortRef, OTGetPortIConFromPortRef, OTGetUserPortNameFromPortRef, and OTGetSlotFromPortRef.

Note
Listing 8-1 shows the user-defined function OTFindSerialPorts. This function uses the OTGetIndexedPort function to find all valid ports. For each port, it gets and examines the device type and, if it's a serial port and not an alias, it calls the user-defined PrintSerialPort function to output information about the port. (Note that you don't want to include aliases to the serial ports in the list, otherwise a standard machine will have 3 serial ports, "serialA", "serialB"and "serial". The PrintSerialPort function uses the OTGetUserPortNameFromPortRef function to print the user name for each port.Note that the slot numbers for NuBus(TM) cards are physical; that is, they are the slot numbers returned by the Slot Manager and not the slots seen in various network configuration applications. Physical slot numbers depend on the type of card installed. For example, NuBus cards number their slots 9 to 13, which appear in the AppleTalk or TCP control panels as slots 1 to 5. For PCI cards, however, the slot numbers are their logical slot IDs as defined in the port structure. For cards in a PCI bus, it is not possible, a priori, to create a port reference that corresponds to a known card, so applications must iterate through the port registry to find appropriate PCI ports.
Listing 8-1 Finding all serial ports

static OSStatus OTFindSerialPorts(void)
{
   OSStatus err;
   Boolean portValid;
   SInt32 portIndex;
   OTPortRecord portRecord;
   UInt16 deviceType;
/* Start portIndex at 0 and call OTGetIndexedPort until */
/* there are no more ports. */
   portIndex = 0;
   err = kOTNoError;
   do {
      portValid = OTGetIndexedPort(&portRecord, portIndex);

   /* Get the deviceType; and, if it's a serial port */
   /* and not an alias, call PrintSerialPort */
      if (portValid) {
         deviceType = OTGetDeviceTypeFromPortRef(portRecord.fRef);
         if (deviceType == kOTSerialDevice && 
                  (portRecord.fInfoFlags & kOTPortIsAlias) == 0) {
            err = PrintSerialPortInfo(&portRecord);
         }
      }
      portIndex += 1;
   } while ( portValid && err == kOTNoError);
   return err;
}
static OSStatus PrintSerialPortInfo(const OTPortRecord *portRecord)
{
   Str255 userVisibleName;
   
/* You must be running PPC codeto call OTGetUserPortNameFromPortRef */
/* on a PPC machine. */
   
   OTGetUserPortNameFromPortRef(portRecord->fRef, userVisibleName);
   
   printf("Found a serial port with port reference $%08lx:\n",
                                 portRecord->fRef);
   printf("  User visible name is                       "%#s".\n",
                                    userVisibleName);
   printf("  String to pass to OTCreateConfiguration is "%s".\n", 
                                 portRecord->fPortName);
   printf("  Name of provider module is                 "%s".\n", 
                                 portRecord->fModuleName);
   printf("\n");
   return kOTNoError;
}

Requesting a Port to Yield Ownership

There may be times when you need to use a particular port (normally, a serial port or modem) that is owned by another application. You can use the OTYieldPortRequest function to request the owner of a port to yield the use of the port to you. (Check the kOTPortCanYield bit in the port record's flags field to determine whether the port supports yielding.) Open Transport then issues a kOTYieldPortRequest event to each provider of any registered clients for that port for acceptance or refusal. If the owner has not registered as a client of Open Transport, compliance is assured.

If the current owner wants to deny the request, it puts a negative error code into the fDenyReason field in the port close structure indicating its reason for refusal. The OTYieldPortRequest function then returns with this error code as its result and with a buffer listing all the clients that have refused the request, (normally only one).

If the OTYieldPortRequest function returns without an error, the port is available for your use. You can then bind it with a queue length (qlen) greater than 0 or establish a connection with it. If you don't use the port within a short period of time (typically 10 seconds), the port automatically stops being available for your use and reverts to its original owner.

You can force a passive client to yield by using a value of NULL in the OTYieldPortRequest function's buffer parameter. When the function returns without an error, the port is available. Note that a port can only be yielded in this manner if its current client is passively listening; it cannot be yielded if a connection is in progress.

Providers owned by unregistered clients need to be prepared to receive kOTProviderIsDisconnected and kOTProviderIsReconnected events when the connection between the provider and port is unexpectedly disconnected and reconnected due to a successful yield request.

Registering as an Open Transport Client

You can use the OTRegisterAsClient function to register your application as an Open Transport client and provide Open Transport with a notifier function for sending messages to you. Once you are registered as a client, Open Transport can notify you of system events, such as the port transition events that occur when a particular port is disabled or closed and when it is reenabled. By registering, you also provide Open Transport with a user-readable name to use when informing the user of port transition events.

If you use the OTRegisterAsClient function to register a notifier for client events, you would receive the events such as kOTPortDisabled, kOTPortEnabled, kOTPortOffline, kOTPortOnline, kOTClosePortRequest, kOTYieldPortRequest, and kOTNewPortRegistered to keep you informed. For information about port events, see "Port-Related Events".

The OTRegisterAsClient function is optional. If you do not want to receive these events, you do not have to call this function.

Calling the CloseOpenTransport function automatically unregisters you as a client. If you want to unregister prior to calling CloseOpenTransport, you can call the OTUnregisterAsClient function.

Note
Client notifiers are distinct from a provider notifier. Provider notifiers tell you about events related to that specific provider. Client notifiers are sent events about the Open Transport system as a whole.


Subtopics
Obtaining Port Information
Requesting a Port to Yield Ownership
Registering as an Open Transport Client

Previous Book Contents Book Index Next

© Apple Computer, Inc.
15 JAN 1998