Converting 1.x to 2.0 Lab


Lab Overview
Connecting and Disconnecting
Sending Data
Receiving Data
AppleTalk Specific Changes
Other Things To Try...
Where To Go From Here...
Notes

Introduction
This lab is designed to show some of the differences between 1.x OS communications and 2.0 OS communications on the Newton. It takes code written for the original (1.x) communications class and alters it to take advantage of the 2.0 system enhancements and changes. Unlike previous labs then, the starting code will be a working sample which will be modified to be 2.0 savvy (at least as far as the communications code goes). The lab we will work with is based on the AppleTalk network protocol. For those who are unfamiliar with AppleTalk you may want to read the Introduction To AppleTalk article.

Included in this lab is the user proto, debugProto. This is essentially a debugger of last resort. It can be used to trace and record values to the Notepad application as your endpoint code runs. For more details on using it and other debugging tips, see the article Debugging Endpoints.

Prerequisites
To do this lab you must have the following:
Files Needed
You must have the files in the Converting 1.x to 2.0 Lab folder on the machine which has NTK on it:. These include the following folders:
1.x ADSP Lab
2.0 ADSP Lab Solution
Code Overview
Since we will be adapting a 1.x application (the ADSP lab from the 1.x communications class), we will start by looking at its structure.

Fundamentally it is a very ordinary Newton application. The endpoint frame is kept in the ep slot in the base view. It is defined at runtime by calling the method MBaseEndpoint which returns an endpoint frame. When the user taps the Connect button, the MConnect method will be called after the MLookup method is called to get the AppleTalk address by calling NetChooser. When the user sends data by tapping the Send button, the MSend method is called. The inputSpec is defined in the endpoint definition as sGetData and is set after a successful connection is made. Tapping the Disconnect button calls the MDisconnect method which also disposes of the endpoint object.

Recall that we are defining the ep variable at runtime so we can change it.

Trying the Solution (and the old version)
You may want to try running the old application to demonstrate that it will still work on the 2.0 Newton. Of course, since Newtons were not network visible under the 1.x OS, you cannot test it unless you have AppleTalk up and running on a desktop machine. The 1.x ADSP lab folder can be downloaded from the Converting 1.x to 2.0 Lab folder. To run the application, download it to your Newton and (if you have a desktop machine and Claris Works), launch the MAC ADSP document and select Wait For Connection from the Session menu. If you don't have Claris Works you will need a communications program which supports AppleTalk connections. Next, with the Newton plugged into your AppleTalk port (remember to be have AppleTalk running on your desktop machine) start the Lab8 ADSP application on the Newton and tap the Connect button. You should see a machine called Every Person in the list which appears in the NetChooser dialog. If you select it and then close the NetChooser dialog the program should connect to the selected machine and you should then be able to send and receive data between your Newton and your desktop machine.

While 1.x endpoint code will continue to work in compiled form, NTK will not recognize 1.x endpoint code when compiling for a 2.0 platform.

If you don't have a working AppleTalk network on a desktop machine you can try downloading the 2.0 ADSP Lab Solution (available from the course ftp site in the Converting 1.x to 2.0 Lab folder) to two 2.0 OS Newtons and connecting them together. Once the program is installed on both machines and the machines are cabled together, tap the Listen button on one of the Newtons followed by the Connect button on the other Newton. Once the connection is established (the connecting Newton should see the other Newton in the list of AppleTalk devices as Newton Server) you can send messages between the two Newtons.

We will start this lab by looking at the changes in connecting and disconnecting endpoints in the 2.0 OS. The section Connecting and Disconnecting changes the original code so that the endpoint is defined, instantiated, bound and connected using the 2.0 definitions and calls. Similarly when disconnecting we can (and will) take advantage of the asynchronous call capability to avoid the problems of disconnecting which occurred in the 1.x system.

The section Sending Data will convert the 1.x code for outputting strings.

The section Receiving Data will change the inputSpec for the lab to a 2.0 inputSpec.

In the section AppleTalk Specific Changes we will talk specifically about changes to the AppleTalk endpoint type between the 1.x and 2.0 system.

As with other endpoint labs you may want to look see the article Debugging Endpoints before trying this lab, if for no other reason than to look at the debugProto user prototype for doing simple tracing when the serial (AppleTalk) port is in use.

For details on 2.0 AppleTalk endpoints not covered in this lab, see the article Endpoint Flavors.

Defining The Endpoint
Before the endpoint can be connected we must of course define it. While the code in viewSetupDoneScript calls MBaseEndpoint to construct an endpoint frame and assigns it to the ep slot, the frame returned changes under 2.0. The first step therefore is to change MBaseEndpoint to define a 2.0 AppleTalk endpoint. To do this you must make the following changes:
Change the proto from protoEndpoint to protoBasicEndpoint
Change the configOptions to use the 2.0 template format
Change the exception handler to call our method MDisconnect if there is an exception other than -16005
You may also want to review the changes to the endpoint exception handling in order to update the ExceptionHandler method for the endpoint. When making the call to MDisconnect in the exception handler, use the 2.0 routine AddDeferredCall.

For the moment leave the inputSpec as it is, we will return to it later.

Change NetworkChooserDone
While the buttonClickScript for the Connect button still calls MLookup which still calls NetChooser in the same way as it did in the 1.x system, you probably want to take advantage of the 2.0 system routine MakeAppleTalkOption to form the NBP address returned from NetChooser into an option which can be used to connect the endpoint. Replace the call to MSetNBPAddress with this routine and then call MConnect. (In other words, MSetNBPAddress can be deleted.)


Change MConnect
Make the following changes to the MConnect method:
Add a bind phase after instantiating the endpoint
Make the call to Connect asynchronous with a callback to a new method, MConnectCompProc
Remember to add code to "back out gracefully" if any stage of the connect fails. This includes code to destroy the endpoint if binding fails or to unbind and destroy the endpoint if queuing the asynchronous call to Connect fails. To add the callback you must define a callbackSpec frame and pass it into the Connect method as described on pp. 4-35 and 4-45 in NPG: Communications.

Note that you no longer need to open the AppleTalk driver.


Create MConnectCompProc
This is the callback routine from the asynchronous Connect call (the name is unimportant, MConnectCompProc is simply what we called our method). It should have the following form:
MConnectCompProc : func(options, result) begin...end
and must be able to handle errors as well as successful connections. The vConnected slot should be set to true if the endpoint is successfully connected as it is used to ensure that we don't throw an error by trying to send data over an unconnected endpoint. You may also want to start the viewIdleScript as it updates the status of the endpoint periodically.

Note that there are two possible levels of failure when calling Connect asynchronously.

Also, in the connection process we should be change how power off handling is done in the following ways:

1. To register a power off handler the call RegPowerOff replaces the 1.x routine AddPowerOffHandler. RegPowerOff has the following form:
RegPowerOff(appSymbol, method)

2. Because we are connecting asynchronously, we do the registration in the completion routine, not in the method MConnect.

3. The PowerOffScript method is now passed information about the kind of power off situation (e.g., sleeping versus user shutdown) and can notify the system that it must reach a certain state (such as disconnected) before shutting down, thus requesting that the system "ask again" before shutting down. PowerOffScript has the following format:
PowerOffScript(what, why)

Change MDisconnect
Change MDisconnect so that it makes the call to Disconnect asynchronously. This saves having the make a deferred call as was advisable in the 1.x system in order to make sure the endpoint was disconnected before we disposed of it. The asynchronous call should have a callback such as MDisconnectCompProc. If the call to MDisconnect throws an exception, make sure the endpoint is unbound and disposed of (you may want to simply call MDisconnectCompProc). Since we no longer need the to make a deferred call to Disconnect, we can also delete the Abort call and, as mentioned below in the section on Receiving Data, we will change how to terminate the current inputSpec.


Create MDisconnectCompProc
This is the callback routine from the call to Disconnect. It should do the following things:
Handle errors from the attempt to disconnect
Turn off the idle script
Unbind the endpoint
Dispose of the endpoint
Set vConnected to nil
At this point you should be able to check your ability to connect and disconnect the endpoint though since we have not modified the code to send and receive data you should be careful not to click the Send or Listen buttons.


Add Code To Listen
Since the Newton is now network visible (i.e., it can register an NBP name for itself on the network), we can change this application to allow another Newton or a desktop machine to connect to our Newton. To do this we will need to change the user interface to allow the user to start listening for incoming connections as well as code to call the Listen method instead of the Connect method.

To begin with add a new button next to the Connect button in the ADSP Demo layout which has the text Listen in it. In its buttonClickScript, build an AppleTalk address option for your Newton which uses the vNBPType slot for the type (ADSP) and the string Newton Server (or whatever other name you want your Newton to have) for the NBP name. The 2.0 routine MakeAppleTalkOption will be useful for this. Next call MListen and pass it the address option you created.
Create the methods MListen and MListenCompProc as the listen call will be asynchronous. MListen has one argument (the NBP address option ) and will look a lot like MConnect in that it will attempt to instantiate and bind the endpoint before calling Listen asynchronously and it must be prepared to back out gracefully if any of these phases fails. For demo purposes, a timeout of 45 seconds is probably good enough as you should be connecting as soon as you begin listening. For release software you may need a much longer timeout as you may want the Newton to be listening for a longer time for a connection (or alternatively, if you timeout, issue another Listen call).

Be aware that any AppleTalk connection will use quite a lot of power.

Once MListen is defined, a callback routine called MListenCompProc (or whatever name you give it) must be added to handle the asynchronous connection. It must Accept the pending connection (something which is not necessary in the MConnectCompProc) as well as doing the following things:
Handle errors in the attempt to connect
Register a power off handler
Turn on the idle proc to update status
Set vConnected to true if the connection is accepted
Set the current inputSpec (add this later)
Once the MListenCompProc is defined you should be able to test the connect and disconnect code by connecting two Newtons and then disconnecting them.

For more details on how to write this code, see the Endpoint Details article or the Endpoint Flavors article depending on whether you are looking for generic endpoint issues (such as the formation of templates) or AppleTalk specifics. Of course you should have handy your copy of NPG: Communications as you'll need to refer to it to get the specifics of the calls correct.

This is perhaps the easiest change to make when converting to 2.0 code. Since we are sending a string we will still call the endpoint method Output as before in the MSend method but Output now has three arguments instead of two. The three arguments to Output are now the endpoint (as before), an options frame (instead of flags) and an outputSpec frame if we want to control output formats. In the case of sending string data as we are doing in this lab, the second and third arguments can be ignored and we can simply pass nils for them.

In addition there is one other change, we get rid of the call to FlushOutput. Since it was almost always called after a call to Output, it was functionally incorporated into Output.

The 2.0 system still uses inputSpecs to handle input but the format and options available have changed somewhat. For the purposes of this lab there are only minor changes however you may want to see the InputSpec Animation to get a better sense of some of the options available.

As mentioned previously, the inputSpec for this lab is defined in the endpoint frame described in the MBaseEndpoint method as sGetData. The discardAfter slot in the inputSpec has not changed however the other slots in the frame have changed at least somewhat. The first change is that the inputForm slot has been changed name to form. This is because the inputSpec is now only one kind of frame using this format. There is also an outputSpec for handling output and a callbackSpec frame for handling callbacks routines for asynchronous calls. While there are also more possible forms which can be received in the 2.0 system, for our example, the 'string symbol will do.

The next change to the inputSpec is the deletion of the endCharacter slot. Instead a termination slot is specified which can have several possible termination conditions including various strings, numbers of bytes, or end-of-packet markers. This slot should be a frame specifying the particular end condition or conditions. Some or all of these can be specified in the same termination frame. For our application there is no need of anything as elaborate as this. Instead the frame will simply have a single endSequence slot which is an array with a single element which is a unicodeCR since that is the termination condition which we want to trigger the call to the InputScript.

InputScript has changed in that it now has the following structure:

InputScript:func(endpoint, data, terminator, options)
begin
...
end


but we do not need to use any of the arguments passed in other than the endpoint and the data.

There are other slots which may be added to the inputSpec as detailed on pp. 4-36 to 4-38 of NPG: Communications but they are not necessary for the current lab and so will be left as a resource for the reader (but see the Other Things To Try... section below).

Once the inputSpec is defined, we need to make it the current inputSpec. This code belongs in the MConnect and MListen methods described above. Since we support both active connection and passive listening for connections and since in the 2.0 OS an inputSpec continues to be active until terminated, we must call the Cancel method to make sure the old inputSpec is terminated before setting another one. In other words when the user taps on either the Connect or Listen button we may have had an inputSpec active and should first cancel the old inputSpec before setting a new one. Cancel should also be called in the MDisconnect before disconnecting and disposing the endpoint.

For more on how to form and use inputSpecs see the Endpoint Details article.


This section is something of a laundry list of changes which have been made to AppleTalk endpoints. As such it repeats material which is available in the article Endpoint Flavors.

Opening and Closing AppleTalk Driver
In the 1.x OS, it was necessary to explicitly open the AppleTalk drivers before making any call to AppleTalk routines (such as NetChooser) and close them when you are done. As mentioned in a note below, this is no longer necessary as long as you bind and unbind the endpoint before making any AppleTalk calls as the Bind and Unbind methods open and close the AppleTalk drivers automatically. However, since there may be times when you want to get information about an AppleTalk network without using an endpoint (say when you want to display nodes in the current zone but not send or receive data), you may still call OpenAppleTalk and CloseAppleTalk explicitly. You should be careful if you do this to close the driver as many times as you open it (so make sure you know what triggers the code which opens the drivers).

Specifying AppleTalk Options
As mentioned above, the options for AppleTalk endpoints (as with all the other endpoint options) now take the form of data templates. For more on templates see the article Endpoint Details. For specifics of AppleTalk endpoint options, see pp. 5-67 to 5-71 of NPG: Communications.

Buffer Size Option
One of the most important options available is the AppleTalk Buffer Size Option (kCMOAppleTalkBuffer). This allows you to specify the size in bytes of the buffer used in, out and attention buffers. By default these buffers are 511, 511 and 0 bytes in size. This option is passed into the Connect or Listen methods. Unless you are terribly concerned about throughput while using AppleTalk and/or are quite familiar with its internal workings, it is recommended that you not change the defaults.

Bytes Available Option
Unlike the 1.x system you can now get the number of bytes available (waiting in the receive buffer) after connection using this option. Use the Option method to get this information.

MakeAppleTalkOption
To ease the construction of common options for specific flavors of endpoints, the 2.0 system has a number of routines available for constructing option frames. For the AppleTalk endpoint the MakeAppleTalkOption takes an NBP string and creates an option describing the node address which can be added to the options being passed to Connect.

For more details on these and other AppleTalk specific items, see the article Endpoint Flavors or the documentation on pp. 5-67 to 5-78 of NPG: Communications.


Some additional things you may want to try which highlight some of the differences between the 1.x and 2.0 systems include the following:

1. Frames may be sent using the Output method (OutputFrame is undefined for protoBasicEndpoint). You might use this to send frames between Newtons or between a Newton and a desktop program built using FDIL (Frame Desktop Integration Library). For more information on Output, see the documentation on pp. 4-16 of NPG: Communications. For more on the FDIL see the article FDIL Detailed or, for a brief summary, see the DIL section in the 1.x To 2.0 Communications Overview article.

2. Change MSend so that output is done asynchronously. Use the OutputSpec frame to add a callback. Another thing to try is to change the values of the form slot of the OutputSpec and see what its effect is on the data which is received by the desktop program. See the table on pp. 4-6 to 4-7 for a list of possible form choices.

3. Change the inputSpec so that it looks for a keyword (such as Logout) or is triggered whenever so many characters are received (say 80).

4. Check your exception handling by doing something like unplugging your AppleTalk connection and tapping the Send button.

Unfortunately, we can't connect AppleTalk through another serial port.


For more details on AppleTalk endpoints, see the article Endpoint Flavors. For more about constructing and using endpoints, the article Endpoint Details covers most of the common uses of endpoints. For more on inputSpecs, see the InputSpec Animation which is a QuickTime movie demonstrating a number of different input scenarios possible with 2.0 inputSpecs.

To see an example of simple serial endpoint code look at the Simple Endpoint Lab. For an example of modem communications, try the Basic Modem Walkthrough Lab. The Asynchronous Endpoint Lab demonstrates a completely asynchronous endpoint application. Finally the Other Features Lab uses the new protoFSM user prototype to build a moderately elaborate protocol.

For more information about the DILs, see the DIL Overview Article or the CDIL Detailed or FDIL Details articles.

Finally, the Apple documentation for the 2.0 system, the Newton Programmer's Guide: Communications may be downloaded from the Newton Technical Information web site while the DILs documentation is available from the DIL web page. And of course the DTS sample code available at the Newton Technical Information web site.


If we defined ep in the layout in NTK (i.e., if instead of being defined as nil, it was defined as being a frame proto'ed from protoBasicEndpoint), then we would be unable to change or add any slots in the frame without cloning the entire frame. By defining ep at runtime it is loaded into dynamic memory and so it may be changed freely. For more on this see the Simple Endpoint Lab.



The hook for protoEndpoint only exists in the 1.x platform files. If you use any 2.0 platform file, you will get a compile-time error when referencing protoEndpoint. Similarly, attempting to call 1.x methods (such as OutputFrame or FlushOutput) will cause a runtime error since they are not defined for protoBasicEndpoint. Using NTK 1.6 or later you can select from among the platform files available on you development system in the Project Settings dialog available under the Project menu.



In the 2.0 OS, when the Bind method is called for an AppleTalk endpoint the AppleTalk drivers are automatically opened and when Unbind is called, they are closed.



When making an asynchronous call there are two phases: queuing the request and having the request executed. Queuing the request simply puts the request in a queue for later execution. If the attempt to queue the request fails for some obscure reason, the system will throw an exception. On the other hand, if the call is queued successfully but the attempt to execute the request actually fails (say because of a timeout or a cable has been unplugged) then the callback routine will be called with an error frame for the result argument.



The two things which use power on the Newton are preventing the Newton from sleeping and active communications. AppleTalk does both. We register a power off handler to prevent the Newton from going to sleep (and thus terminating the connection) once the connection is established. In addition AppleTalk is a fairly "chatty" protocol; there are a lot of messages going back and forth between the Newton and the network when running AppleTalk. This means that connections which are up for a long time will use a tremendous amount of power.



Unlike serial endpoints, we cannot connect AppleTalk through a serial PCMCIA card. This makes debugging more difficult.

Navigation graphic, see text links

Developer Services | Technical Information | Tools | Sample Code

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help


Copyright Apple Computer, Inc.
Maintained online by commscourse@newton.apple.com
Updated 26-Sep-96 by dcd