/* LarkImpl.c
Dan Swinehart October 14, 1982 1:25 PM
L. Stewart October 27, 1982 11:15 PM
L. Stewart November 9, 1982 9:58 AM, use ctxQ
L. Stewart December 8, 1982 3:57 PM, silent DTMF events
L. Stewart December 20, 1982 10:04 AM, more space for EventReport
L. Stewart December 27, 1982 11:07 PM, ELoad, less space for E.R.
L. Stewart January 1, 1983 4:11 PM, remove AllocZero
L. Stewart January 17, 1983 3:47 PM, Lark.mesa revisions
*/
#include <Alloc.h>
#include <Queue.h>
#include <Ec.h>
#include <Env.h>
#include <Signal.h>
#include <rpc.h>
#include <rpcinternal.h>
#include <rpclupine.h>
#include <encrypt.h>
#include <LarkNet.h>
/* runtime */
extern CallSwat();
extern InitOS();
extern Move2();
extern MoveBlock();
extern Swab();
extern Zero();
/* RPC package */
extern AddToDispatcherSpecs();
extern AddType();
extern int CallFormatted();
extern int diagnoseBinding;
extern int ExportFailed;
extern ExportInterface();
extern int ImportFailed;
extern int ImportInterface();
extern struct VersionRange *matchAllVersions;
extern RPCInitialize();
extern RPCInitializeCtx();
extern int *StartDispatcherSpecs();
extern StartNProcess();
extern int StdDispatcher();
extern struct ShortSTRING *ToRope();
/* Alloc package */
extern int *Allocate();
extern Free();
/* Lark package */
/* in LarkEventsImpl.c */
extern InitEventReport();
extern EventReport();
extern EventProcess();
extern AudioStuff();
extern AudioProcess();
extern AudCmd();
extern StartNet();
extern StopNet();
/* context package */
extern Block();
extern CallContext();
extern Dismiss();
/* signaller package */
extern int CONT();
/* chario package */
extern wf();
extern wf1();
extern wf2();
extern wf3();
extern wf4();
/* pup package */
extern GetPupHost();
extern ELoad();
/* unknown */
extern int mySoc;
/* (Forward) Interface procedures to which Server, below, dispatches */
extern Reset(); /* in LarkAud.c */
extern GenerateTones(); /* in LarkAud.c */
extern Feep();
extern Commands();
extern Connect();
extern Disconnect();
extern PleaseRegister();
extern WhatIsStatus();
extern WhatAreConnections();
extern WhatAreTones();
/* End of interface procedures */
extern struct ZN *sysZone;
extern struct EncryptionKey nullKeyB;
extern struct Queue ctxQ;
struct ShortSTRING *spNl, *spDT;
static struct ShortSTRING *sp1, *sp2, *sp6;
static struct ShortSTRING *sp9, *spSt, *sp3St, *sp5Sq, *spSt3, *spX;
static struct ShortSTRING *spD1, *spRegister;
static struct ShortSTRING *spSq, *sp1Sq, *sp1X;
static int nilst[2];
struct Conversation *shhhh;
/* Place holder for later encrypted conversations */
int *smartsHandle;
int DEBUG;
int handle;
static struct Seal sl;
static struct InterfaceName clientInterface;
static int args[10]; /* prob not needed */
static int inProg;
int pNil[2];
struct ShortSTRING *instance, *serverRname, *myRname;
struct Model *myModel;
static int lyib, encrpcb;
Main() {
InitOS(); /* Sets up sysZone */
inProg = 0;
DEBUG = false;
shhhh = unencrypted;
Options();
RPCInitialize(&ctxQ, sysZone);
spNl = (struct ShortSTRING *) nilst;
Zero(nilst, 2);
sp1 = ToRope("$$$$W");
sp2 = ToRope("$$$$WW");
sp6 = ToRope("$$$$WWWWWW");
sp9 = ToRope("$$$$WWWWWWWWW");
spSt = ToRope("$$$$S");
sp1Sq = ToRope("$$$$WT");
spSq = ToRope("$$$$K");
sp3St = ToRope("$$$$WWWS");
sp5Sq = ToRope("$$$$WWWWWK");
spSt3 = ToRope("$$$$SSS");
spRegister = ToRope("$$$$DWDSS");
spX = ToRope("$$$$X"); /* Connection spec */
sp1X = ToRope("$$$$WX"); /* INTEGER, ConnectionSpec */
spD1 = ToRope("$$$$D");
spDT = ToRope("$$$$DT");
InitEventReport();
/* EventProcess is temporary until the interrupt procedures get fixed up */
StartNProcess("EventProcess", sysZone, &ctxQ, &EventProcess, 200, 10);
StartNProcess("EventReport", sysZone, &ctxQ, &EventReport, 350, 90);
StartNProcess("AudioProcess", sysZone, &ctxQ, &AudioProcess, 350, 90);
AudioStuff();
for (;;) {
CallContext(ctxQ.head);
};
};
static Options()
{
lyib = encrpcb = false;
wf("type 1 to encrypt, 0 to not encrypt\r");
encrpcb = (GetChar() == '1') ? true: false;
wf("type 1 to use Einstein.Lark, 0 to use Morley.Lark\r");
lyib = (GetChar() == '1') ? true: false;
};
Initialize()
{
RPCInitializeCtx(true);
ELoad();
diagnoseBinding = true;
AddType('Z', 0); /* Get things started */
AddType('X', dBlock( /* Connection specification */
16, /* eltSize: word elements */
0, /* overhead: 14 words (all overhead!) */
14, /* length: Sequence length field, not a sequence */
false, /* atLen: length is 0 */
true)); /* eltWd: all Swabbed, have to reverse some of them */
AddType('K', dBlock( /* LarkModel specification */
16, /* one word elements */
1, /* sequence only */
0,
true, /* length is in record at word 0 */
false)); /* deviceStates: sequence of pairs of bytes */
AddType('T', dBlock( /* events: int time; char device, event; */
32,
1,
0,
true,
false));
handle = 0;
Zero(&clientInterface, lenInterfaceName);
clientInterface.type = ToRope("$$$$LarkSmarts.Lark");
/* clientInterface.instance = 0; */
/* Use broadcast binding methods. */
clientInterface.instance = ToRope((lyib) ? "$$$$Einstein.Lark" : "$$$$Morley.Lark");
Move2(&clientInterface.version, matchAllVersions);
{ /* Implicit loop until ENABLE succeeds */
if (ENABLE(ImportFailed, &CONT, &sl))
CallSwat(ecPup1+100);
while (!AgentInitialize()) CallSwat(ecLarkImpl+23);
handle = ImportInterface(&clientInterface);
DISABLE(&sl);
wf("Identify[...] = ");
args[0] = (int) Swab(GetPupHost()); /* netAddress */
serverRname = CallFormatted(handle, iIdentify, sp1, spSt3, args);
myRname = args[2];
instance = args[3];
wf3("[serverRname: %r, myRname: %r, instance: %r]\r", serverRname, myRname, instance);
shhhh = StartConversation(myRname, &nullKeyB, serverRname, slCBCCheck);
wf1("StartConversation[...] = %xH\r", shhhh);
if (encrpcb) AttachConversation(handle, shhhh);
Server(instance);
myModel = (struct Model *) Allocate(sysZone, lenModel);
myModel->genre = 1; /* Lark1 */
myModel->hardwareVersion = 5; /* or something */
myModel->softwareVersion = 6; /* or something */
/* Now register in (once, for now) */
args[0] = (int) pNil; /* oldHandle: none yet */
args[1] = (int) Swab(GetPupHost()); /* netAddress: */
args[2] = (int) myModel; /* model: */
args[3] = (int) instance
args[4] = (int) myRname; /* <<not sure this still belongs here.>> */
wf("Register[...] = ");
smartsHandle = CallFormatted(handle, iRegister, spRegister, spD1, args);
wf2("%xH, %xH]\r", smartsHandle[0], smartsHandle[1]);
}; /* endloop */
};
static Server(instance)
struct ShortSTRING *instance;
{
struct InterfaceName *interface;
int *specs;
interface = (struct InterfaceName *) Allocate(sysZone, lenInterfaceName);
interface->type = ToRope("$$$$Lark.Lark");
interface->instance = instance;
Move2(&interface->version, matchAllVersions);
specs = StartDispatcherSpecs(10);
AddToDispatcherSpecs(specs, iReset, &Reset, spSt, spNl);
AddToDispatcherSpecs(specs, iGenerateTones, &GenerateTones, sp9, sp1);
AddToDispatcherSpecs(specs, iFeep, &Feep, sp5Sq, sp1);
AddToDispatcherSpecs(specs, iCommands, &Commands, spSq, spNl);
AddToDispatcherSpecs(specs, iConnect, &Connect, spX, spNl);
AddToDispatcherSpecs(specs, iDisconnect, &Disconnect, sp2, spNl);
AddToDispatcherSpecs(specs, iPleaseRegister, &PleaseRegister, spNl, spNl);
AddToDispatcherSpecs(specs, iWhatIsStatus, &WhatIsStatus, sp1, sp1Sq);
AddToDispatcherSpecs(specs, iWhatAreConnections, &WhatAreConnections, sp1, sp1X);
AddToDispatcherSpecs(specs, iWhatAreTones, &WhatAreTones, spNl, sp1);
ExportInterface(interface, &StdDispatcher, specs);
};
/* Actual calls via RPC */
int Feep(on, off, waveTable, queueIt, notify, events)
int on, off, waveTable, queueIt, notify;
struct EvSeq *events;
{
int i, len, thisNotify;
char d, e, c;
thisNotify = 0;
for (i = 0; i < events->length; i += 1) {
if ((i + 1) == events->length) thisNotify = notify;
Block();
d = events->evs[i].device;
e = events->evs[i].event;
if ((e >= 128) && (e <= 137)) c = e - 128 + '0';
else switch (e) {
case 138: c = 'A'; break;
case 139: c = 'B'; break;
case 140: c = 'C'; break;
case 141: c = 'D'; break;
case 142: c = '*'; break;
case 143: c = '#'; break;
default: {
PlayTone(0, 0, 40, ((e * 10) - 40) & 0x00ff, 1, queueIt, waveTable, thisNotify);
queueIt = true;
continue;
};
};
LocPlayDTMF(c, on, off, queueIt, waveTable, thisNotify);
queueIt = true;
};
Free(sysZone, events);
return (1); /* a Mesa TRUE */
};
Commands(events)
struct EvSeq *events;
{
AudCmd(events);
Free(sysZone, events);
};
Connect(specs)
struct CSpecs *specs;
{
if (inProg) CallSwat(ecLarkImpl+6);
inProg = 1;
StartNet(specs);
Free(sysZone, specs);
inProg = 0;
};