ZIP.c

/*------------------------------------------------------------------------------
#
#   ZIP.c : this module contains the Zone Information Protocol functions
#   to get zone names for both AppleTalk Phase 1 and Phase 2.
#
#
#   Versions:   1.0                 10/91
#   Built with MPW 3.2
#
#   C.Buttin - Apple Computer Europe            
#
------------------------------------------------------------------------------*/
#include <Memory.h>
#include <ToolUtils.h>
#include <Devices.h>
#include <AppleTalk.h>
 
 
/* GetZones :   returns the list of zones
   If Phase 2 driver available 
        issues XPP calls
   else
        issues ATP calls
    Input :
        - a buffer to contain the list
        - buffer size
    Output :
        - total number of zones
                    or
          -1 : buffer was to small
                    or
          error : an error occured */ 
 
pascal short GetZones(Ptr buffer,short bufsize);
 
/* GetZoneName :    Extract a zone name from the buffer list
    Input : 
        - buffer containing the zone list
        - index of the zone to be retrieved
        - Pascal string to receive the zone name (empty string if error) */
pascal void GetZoneName(char* buffer,short zoneNumber,char* zoneName);
 
/* XPP functions */
/* InitXPP : Open the .XPP driver */
pascal OSErr InitXPP(short *driverNum);
 
/* XPPGetZoneList : returns the list of zones
    Input :
        - a buffer to contain the list
        - buffer size
    Output :
        - total number of zones
                    or
          -1 : buffer was to small
                    or
          error : an error occured */
pascal short XPPGetZoneList(Ptr buffer,short bufsize,short driverNum);
 
/* ATP functions */
/* InitATP : Open the .ATP driver */
pascal OSErr InitATP(void );
 
/* ATPGetZoneList : returns the list of zones
    Input :
        - a buffer to contain the list
        - buffer size
    Output :
        - total number of zones
                    or
          -1 : buffer was to small
                    or
          error : an error occured */
                pascal short ATPGetZoneList(Ptr buffer,short bufsize);
 
 
 
pascal short GetZones(Ptr buffer,short bufsize)
{
    SysEnvRec   theConfig;              
    short       driverNum;
    OSErr       error;
 
    SysEnvirons(1, &theConfig);
    if (theConfig.atDrvrVersNum < 53)   {       /* phase 1 calls */
        if ((error = InitATP()) == noErr)
            return(ATPGetZoneList(buffer,bufsize));
        else
            return error;
        }
    else    {                                   /* phase 2 calls */
        if ((error = InitXPP(&driverNum)) == noErr)
            return  XPPGetZoneList(buffer,bufsize,driverNum);
        else
            return error;
            }
}
 
                            /* XPP functions */
                            
                            
pascal OSErr InitXPP(short *driverNum)
{
    OSErr   error;
    
    /* open .MPP driver  and .ATP driver */
    if ((error = InitATP()) != noErr)
        return error;
    /* Open .XPP driver */
    return OpenXPP(driverNum) ;
} /* InitXPP */
 
                            
pascal short XPPGetZoneList(Ptr buffer,short bufsize,short driverNum)
{
    Ptr         theBufferPtr;
    short       numzone;
    short       dataSize;
    Ptr         p;
    OSErr       error;
    XCallParam  XPPBlock;
    
    Debugger();
    
    numzone = 0;
    dataSize = 0;
    p = (Ptr)buffer;
    theBufferPtr = NewPtr(578);     /* ZIP buffer (must be 578 bytes) */                                       
    /* set XPP record */
    XPPBlock.zipInfoField[0] = 0;        /* ALWAYS 0 on first call. contains state info
                                       on subsequent calls */
    XPPBlock.zipInfoField[1] = 0;        /* ALWAYS 0 on first call. contains state info
                                       on subsequent calls */ 
    /* initialization for loop */
    XPPBlock.ioRefNum = driverNum;
    XPPBlock.zipLastFlag = 0;
    XPPBlock.csCode = xCall;
    XPPBlock.xppSubCode = zipGetZoneList;
    XPPBlock.xppTimeout = 3;
    XPPBlock.xppRetry = 4;
    XPPBlock.zipBuffPtr = theBufferPtr;
    do {
        if ((error = GetZoneList((XPPParmBlkPtr)&XPPBlock, false)) != noErr) {
            DisposPtr(theBufferPtr);
            return error;
            }
        /* Get the actual number of zones */
        numzone = numzone + XPPBlock.zipNumZones;
        dataSize = 33 * numzone;            /* 33 char. for each zone */        
        if (bufsize - dataSize <= 0)    {   /* buffer overflow */
            DisposPtr(theBufferPtr);
            return -1;
            }
        /* copy to buffer */
        BlockMove(theBufferPtr,p,(long)33*XPPBlock.zipNumZones);
        p = (Ptr)buffer + dataSize;
        }
    while (XPPBlock.zipLastFlag == 0);  /* ZIP sets user bytes to 0, while all
                                           the data have not been provided */
    DisposPtr(theBufferPtr);
    return numzone;
    
} /* XPPGetZoneList */
 
                            /** ATP functions **/
                            
#pragma segment Main
pascal OSErr InitATP(void)
{
    OSErr error;
    
    if ((error = MPPOpen()) != noErr)
        return error;
    /* open .ATP driver */
    return (ATPLoad());
}   /* InitATP */
 
pascal short ATPGetZoneList(Ptr buffer,short bufsize)
{
    short numzone;
    short node;
    BDSElement bdsp;
    short dataSize;
    ATPParamBlock ATPBlock;         /* to build parameter block for ATP */
    OSErr   error;
 
    /* Get the address of a bridge (node value of the address) */
    if ((node = GetBridgeAddress()) == 0)
        return 0;
    
    dataSize = 0;
    numzone = 0;
    
    /* set ATP record */
 
    ATPBlock.SREQ.ioCompletion = nil;       /* no completion routine */
    ATPBlock.SREQ.addrBlock.aNet = 0;       /* set destination address : current net */
    ATPBlock.SREQ.addrBlock.aNode = node;   /* bridge address */
    ATPBlock.SREQ.addrBlock.aSocket = 6;    /* ZIP socket */
    ATPBlock.SREQ.atpFlags = 0;             /* Control flags : ALO Request */
    ATPBlock.SREQ.filler = 1;               /* numOfBuffs : ZIP expects 1 */   
    ATPBlock.SREQ.timeOutVal = 1;           /* timeout interval (in seconds) */
    ATPBlock.SREQ.retryCount = 5;           /* number of retries */
    ATPBlock.SREQ.reqPointer = nil;         /* number of retries */
    ATPBlock.SREQ.reqLength = 0;           
 
    do {
        if (bufsize - dataSize <= 0)        /* buffer overflow */
            return -1;
 
        bdsp.buffPtr = buffer+dataSize;     /* set the received buffer */
        bdsp.buffSize = bufsize - dataSize;
    
        ATPBlock.SREQ.userData = 0x08000000+numzone+1;  /* specify GetZoneList from zone n */
        ATPBlock.SREQ.bdsPointer = (Ptr)&bdsp;          /* response BDS */   
 
        if ((error = PSendRequest((ATPPBPtr)&ATPBlock,false)) != noErr)
            return error;
    
/* Get the actual number of zones */
        numzone = numzone + LoWord(bdsp.userBytes);
        dataSize = dataSize + bdsp.dataSize;
        }
    while (HiWord(bdsp.userBytes) == 0);    /* ZIP sets user bytes to 0, while all
                                                the data have not been provided */
    return(numzone);
} /* ATPGetZoneList */
 
pascal void GetZoneName(char* buffer,short zoneNumber,char* zoneName)
{
    short   i,j,lgzone;
    
    for (i = 1; i <= zoneNumber;i++) {
        lgzone = *buffer;
        for (j = 0;j <= lgzone;j++)     /* build zone name */
            if (i == zoneNumber)
                *zoneName++ = *buffer++;
            else
                buffer++;
        }
} /* GetZoneName */