/* 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; };