DIRECTORY
DESFace USING [ Key ],
PupTypes USING [ PupAddress ],
RPC USING [ Conversation, ShortROPE ],
RPCPkt USING [ Machine ];

Lark: CEDAR DEFINITIONS = {

-- *************************** Types ****************************** --

SHHH: TYPE = RPC.Conversation;
ROPE: TYPE = RPC.ShortROPE;
EncryptionKey: TYPE = DESFace.Key;

VoiceSocket: TYPE = PupTypes.PupAddress;
Machine: TYPE = RPCPkt.Machine;
noMachine: Machine = [[0], [0]];

Device: TYPE = MACHINE DEPENDENT {
microphonePTT (0), -- mike switch --
hookSwitch (1), -- switch on local handset
speakerSwitch (2), -- switch on speaker box --
touchPad (3), -- DTMF generator/detector (downstroke) --
keyboard (4), -- standard keyboard --
auxiliaryKeyboard (5), -- extra device
locator (6), -- as yet undefined --
ringDetect (7), -- on back door --
revertRelay (8), -- on Teleset, controls Tip, Ring, and receiver --
offHookRelay (9), -- on Telewall, controls Tip and Ring only --
sideTone (10), -- on Teleset --
ringEnable (11), -- volume bypass on speaker --
led (12), -- lamp on speaker box --
crossBar (13), -- analog crossbar switch --
timeslot (14), -- to set timeslots --
voiceMode (15), -- program modes --
inGain1 (16), -- table indicies --
inGain2 (17),
outGain1 (18),
outGain2 (19),
echoSuppression (20),
nothing (21),
clearCrosspoint (22), -- Event is row/column pair --
setCrosspoint (23), -- Event is row/column pair --
revertHookswitch (24), -- reverts A/A1, etc. --
aRelay (25), -- controls A/A1 --
tones (26), -- See description of notification in ToneSpec --
delay (27), -- Event is number of deciseconds to delay --
spMode (28), -- speakerphone mode --
touchPadUp (29), -- DTMF generator/detector (upstroke) --
keyboardUp (30), -- upstroke
auxiliaryKeyboardUp (31),  -- upstroke
lastPlusOne (32), -- not used, but update when increasing number of devices.
(255) -- byte wide --
};


Event: TYPE = CHARACTER;

firstChar:	Event = '\000;
lastChar:	Event = '\177;

b0:		Event = '\200;
b1:		Event = '\201;
b2:		Event = '\202;
b3:		Event = '\203;
b4:		Event = '\204;
b5:		Event = '\205;
b6:		Event = '\206;
b7:		Event = '\207;
b8:		Event = '\210;
b9:		Event = '\211;
bA:		Event = '\212;
bB:		Event = '\213;
bC:		Event = '\214;
bD:		Event = '\215;
bStar:		Event = '\216;
bThorp:	Event = '\217;

enabled:	Event = '\220;
disabled:	Event = '\221;
reset:		Event = '\222;

ts0:		Event = '\223;
ts12:		Event = '\224;

tab0:		Event = '\225;
tab1:		Event = '\226;
tab2:		Event = '\227;
tab3:		Event = '\230;
tab4:		Event = '\231;
tab5:		Event = '\232;
tab6:		Event = '\233;
tab7:		Event = '\234;
tab8:		Event = '\235;
tab9:		Event = '\236;

o3i1:		Event = '\237;
o2i2:		Event = '\240;
o1i1:		Event = '\241;

inbound:	Event = '\242;
outbound: Event = '\243;

endNum:	Event = '\244;

notify: Event = '\245;


CommandEvent: TYPE = MACHINE DEPENDENT RECORD [
device: Device,
event: Event
];

StatusEvent: TYPE = MACHINE DEPENDENT RECORD [
time: CARDINAL,
device: Device,
event: Event
];


DTMFEvent: TYPE = Event[b0..bThorp];
CharacterEvent: TYPE = Event[firstChar..lastChar];


Passel:	TYPE = [0..32);


StatusEvents: TYPE = REF StatusEventSequence;

StatusEventSequence: TYPE= RECORD[
e: PACKED SEQUENCE length: Passel OF StatusEvent
];

CommandEvents: TYPE = REF CommandEventSequence;

CommandEventSequence: TYPE= RECORD[
e: PACKED SEQUENCE length: Passel OF CommandEvent
];

Hertz: TYPE = [0..3500); -- Voice bandpass --
Milliseconds: TYPE = [0..10000);


Protocol: TYPE = MACHINE DEPENDENT {interactive (0), nWay (1), recordOnly (2), (7)};

Encoding: TYPE = MACHINE DEPENDENT {muLaw (0), (7)}_muLaw;

VoiceBuffer: TYPE = MACHINE DEPENDENT {in1 (0), in2 (1), out1 (2), out2 (3), out3 (4), (7)};


ConnectionSpec: TYPE = REF ConnectionSpecRec;

ConnectionSpecRec: TYPE = MACHINE DEPENDENT RECORD [
protocol: Protocol,
encoding: Encoding,
blankA: [0..1777B] _ 0,
sampleRate: INTEGER,
packetSize: INTEGER,
blankB: [0..17777B] _ 0,
buffer: VoiceBuffer,
blankC: [0..7777B] _ 0,
keyIndex: [0..17B],
localSocket: VoiceSocket,
remoteSocket: VoiceSocket
];


Genre: TYPE = MACHINE DEPENDENT { Alto (0), Lark1(1), (255) };

LarkModel: TYPE = MACHINE DEPENDENT RECORD [
genre: Genre,
hardwareVersion: [0..256),
softwareVersion: CARDINAL
];

KeyTable: TYPE = REF KeyTableBody;
KeyTableBody: TYPE = RECORD [
s: SEQUENCE size: [0..20B] OF EncryptionKey
];

EchoParameters: TYPE = REF EchoParameterRecord;
EchoParameterRecord: TYPE = MACHINE DEPENDENT RECORD [
blankA: [0..17777B] _ 0,
buffer: VoiceBuffer,
blankB: [0..37777B] _ 0,
buffer2Controlled: BOOL,
buffer1Controlled: BOOL,
decayTime: CARDINAL,
gain: ARRAY [0..5) OF CARDINAL
];

ToneSpec: TYPE  = REF ToneSpecRec;
ToneSpecRec: TYPE = RECORD [
notification: CommandEvent _ [nothing, 0C], -- what to use when notifying.
volume: CARDINAL, -- "WaveTable": entire sequence played at one volume, for now
totalTime: CARDINAL, -- duration of one total performance in millisec
tones: LIST OF Tone
];

Tone: TYPE = RECORD [
f1: CARDINAL,	-- Hertz.
f2: CARDINAL,	-- Hertz.
on, off: CARDINAL,	-- Tone will be played at f2 Hz. for on ms.; then off ms. of silence.
repetitions: CARDINAL_1  -- specifies number of repetitions of this toned
];

-- ************************ Smarts=>Lark procedures ********************** --


Reset: PROC [shh: SHHH, rName: ROPE];

SpecifyTones: PROC[ shh: SHHH,
queueIt: BOOLEAN_TRUE,
tones: ToneSpec _ NIL
]
RETURNS [ok: BOOLEAN -- FALSE means no room in queue --];


Feep: PROC[ shh: SHHH,
on, off: Milliseconds,
waveTable: CARDINAL,
queueIt: BOOLEAN_TRUE,
notify: CommandEvent _ [nothing, 0C],
events: CommandEvents
]
RETURNS [ok: BOOLEAN -- FALSE means no room in queue --];


Commands: PROC [shh: SHHH, events: CommandEvents];


Connect: PROC [shh: SHHH, specs: ConnectionSpec];


Disconnect: PROC [shh: SHHH, buffer: VoiceBuffer];


PleaseRegister: PROC [shh: SHHH];


WhatIsStatus: PROC [shh: SHHH, which: CARDINAL]
RETURNS [next: CARDINAL, events: StatusEvents];


WhatAreConnections: PROC [shh: SHHH, which: CARDINAL]
RETURNS [next: CARDINAL, specs: ConnectionSpec];


WhatAreTones: PROC [shh: SHHH] RETURNS [BOOLEAN];

SetKeyTable: PROC [shh: SHHH, table: KeyTable];

CommandString: PROC [shh: SHHH, device: Device, commands: ROPE];

PleaseLogin: PROC[shh: SHHH] RETURNS [will: BOOL];

EchoSupression: PROC [shh: SHHH, echo: EchoParameters];

SetHostNumber: PROC [shh: SHHH, host: Machine];


}.

Stewart, July 18, 1983 11:09 am, added SetHostNumber
���h��Lark.mesa
Copyright c 1984 by Xerox Corporation.  All rights reserved.
Last modified by Swinehart and Owicki, December 7, 1982 1:47 pm
Last modified by Swinehart, December 20, 1984 1:27:11 pm PST
Last modified by Stewart, July 18, 1983 12:58 pm
External interface to Lark (Etherphone) Capabilities (Smarts=>Lark)
This interface is a Lark private affair and makes no distinction between the
front and back doors.  Such a distinction must be handled by the Smarts.
Kinds of keystrokes and other "digital" actions that a Lark user might initiate,
including keyboard and touchpad buttons, switch-hook actions, etc.  An event must
be associated with a Device in order to be unambiguously interpreted.
Ascii range
DTMF pushbuttons
Switches (i.e., offhood, onhook)
Time slots
Table indices
Voice software modes
Echo suppression modes
<<TEMP: Synthesized telephone number terminator>>
tag field in Generate tones
Typically, devices and events will be combined
Subset of events corresponding to "touch-tones"
Sequences have these kinds of domain types, so that instances of them will
fit in a single RPC packet.
This is basically an Event "string", maxLength=length
Good for sending character sequence, as in the Display command, below.
There may be more than one way to transmit voice, depending.
We will probably also experiment with a number of encodings.
If a Smarts says this to a Lark, it informs the Lark what connections
to establish (see Connect, below.)  If a Lark says this to a Smarts, it
is a report of what connections presently exist.
Some more stuff that the Lark tells the Smarts when Registering.
f1, f2: frequencies of two sinusoidal tones; f2 may be zero to request a single tone
on, off: noisy and silent intervals during each repetition.
repetitions: should be fairly small; longer sequences should be produced by queuing
multiple specifications, not too far ahead; prevents pollution after server crash.
waveTable, an index into Lark's available waveform tables for tone generation.
Also, more complex tone sequences can be specified using a queue of Tones requests.
queueIt: add specification to a list of sequential tone specs
~queueIt: supercede all pending tones with this one (e.g., scope=silence)
notify: issue a "tones" event when this entry terminates.

If notification.device is 'nothing', ToneSpec is to be played only once.
Notification: If notification.device is 'tones', notification will be reported as an event after completion of the first tone in the list.
totalTime field is not used by Lark. (ToneSpecs are used by other parts of the Etherphone system.)
Pause: not used by Lark.
Cancel any tone sequence in progress.  Clear the  display (or set it to a distinctive
"out of service" state).  Forget about any conversation in progress.  Hang up any
automatically switched audio devices (Speakerphone, etc.)  Remember the identity
of your "smarts".  rName is for use in LarkSmarts.Register (cf.)
Always accept, whether or not a conversation is in progress; return immediately,

Standard DTMF is special; this function avoids long Tones[] sequences.
on, off: "make"/"break" intervals for each code.
waveTable, queueIt: as above.
events: a "string" of DTMF events to be "feeped".  This is for back-door dialing, end-to-end
signalling for remote control of systems, etc.  Each DTMF event reported via
LarkSmarts.RecordEvent may also have to be echoed by the Lark program, depending
on the nature of the keyboard.
notify: issue a "tones" event when all digits have been sent.
Commands.
Use the sockets and the protocol type from |spec| to establish a conversation between
yourself and the indicated other party (ies).  If a conversation is already underway,
replace it with this one, without disrupting existing conversations (a good trick, but
needed, since host number, socket number are likely to change.)
Drop all connections corresponding to id, return to idle state.  A Connect call with a zero-length
socket sequence should behave the same way.  The buffer parameter should match the
connection specification that is being abandoned.
This is a Smarts request for the Lark to Register, thus providing a status update.
<< If it works out, the Lark should call LarkSmarts.Register BEFORE returning from
PleaseRegister.  That may tie all the monitors in knots, or make error management yucky
on one end or other, whence a return from PleaseRegister will be taken as a promise
to register soon.  Alternatively, the procedure could return registration info. >>
This is a Smarts request for the Lark to send in its entire state.
A which = 0 indicates that the Lark should start over.  Thereafter, LarkSmarts should
make the next call with which = next.
This is a Smarts request for the Lark to send in its outstanding connections.
A which = 0 indicates that the Lark should start over.  Thereafter, LarkSmarts should
make the next call with which = next
This is a Smarts request for the Lark to send in its outstanding tones.
For now just returns that there are some.
After responding in the affirmative, Lark should collect user name and password information
(somehow), locally, use the Agent to obtain new authentication based on the password, issue LarkSmarts.LogIn to identify the new Rname, then begin using a new conversation based on the new authentication.
Here is where to put extensions to the Lark Protocol.  After extending it and gaining some experience with the extensions, the intent is to eliminate many of the earlier procedures.
�Ê
��˜�Jšœ	™	Jšœ
Ïmœ1™<Jšœ?™?Jšœ<™<Jšœ0™0J˜�JšœC™CJšœL™LJšœH™HJ˜�šÏk	˜	Jšœžœ	˜Jšœ	žœ˜Jšžœžœ˜&Jšœžœ
˜J˜�—Jšœžœ˜J˜�JšÏcF˜FJ˜�Jšžœžœžœ˜Jšžœžœžœ˜Jšœžœ˜"J˜�Jšœ
žœ˜(Jšœ	žœ˜J˜ J˜�šœžœžœž	œ˜"JšœŸ˜$JšœŸ˜*JšœŸ˜.JšœŸ*˜8JšœŸ˜%JšœŸ˜&Jšœ
Ÿ˜#JšœŸ˜"JšœŸ2˜CJšœŸ-˜?JšœŸ˜JšœŸ˜/Jšœ
Ÿ˜#JšœŸ˜+JšœŸ˜%JšœŸ˜#JšœŸ˜"J˜
J˜J˜J˜J˜
JšœŸ˜4JšœŸ˜2JšœŸ˜/Jšœ
Ÿ˜ JšœŸ1˜=JšœŸ-˜9Jšœ
Ÿ˜$JšœŸ%˜9JšœŸ˜JšœŸ˜&JšœŸ:˜LJšœŸ˜J˜J˜�—JšœP™PJšœQ™QJšœE™EJ˜�Jšœžœž	œ˜J˜�Jšœ™J˜J˜J˜�Jšœ™J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜�Jšœ ™ J˜J˜J˜J˜�Jšœ
™
J˜J˜J˜�Jšœ
™
J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜�Jšœ™J˜J˜J˜J˜�Jšœ™J˜J˜J˜�Jšœ1™1J˜J˜�Jšœ™J˜J˜�Jšœ.™.J˜�š	œžœžœž	œžœ˜/J˜J˜J˜J˜�—š	œ
žœžœž	œžœ˜.Jšœžœ˜J˜J˜J˜J˜�—Jšœ/™/J˜�Jšœžœ˜$Jšœžœ˜2J˜�JšœJ™JJšœ™J˜�Jšœžœ˜J˜�Jšœ5™5JšœF™FJ˜�Jšœžœžœ˜-J˜�šœžœžœ˜"Jšœžœžœžœ˜0J˜J˜�—Jšœžœžœ˜/J˜�šœžœžœ˜#Jšœžœžœžœ
˜1J˜J˜�—JšœžœŸ˜-Jšœžœ˜ J˜�Jšœ<™<Jšœ<™<J˜�Jšœ
žœžœž	œ2˜TJ˜�Jšœ
žœžœž	œ˜:J˜�Jšœ
žœžœž	œ7˜\J˜�JšœE™EJšœG™GJšœ0™0J˜�Jšœžœžœ˜-J˜�š	œžœžœž	œžœ˜4J˜J˜J˜Jšœžœ˜Jšœžœ˜Jšœ˜J˜Jšœ˜J˜J˜J˜J˜J˜�—Jšœ@™@J˜�Jšœžœžœž	œ˜>J˜�š	œžœžœž	œžœ˜,J˜
J˜Jšœž˜J˜J˜�—Jšœ
žœžœ˜"šœžœžœ˜Jšœžœžœ˜+Jšœ˜—J˜�Jšœžœžœ˜/š	œžœžœž	œžœ˜6Jšœ˜J˜Jšœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœžœž˜J˜—J˜�JšœT™TJšœ;™;JšœS™SJšœR™RJšœN™NJšœS™SJšœ=™=JšœI™IJšœ9™9J™�Jšœ
žœžœ
˜"šœ
žœžœ˜šœ,Ÿ˜JJ™H—JšœžœŸ=˜OJšœžœŸ0˜EJšœžœžœ˜J˜J™ŠJ™b—J˜�šœžœžœ˜JšœžœŸ	˜JšœžœŸ	˜Jšœ	žœŸE˜XJšœ
žœŸ2˜IJ˜J™—J˜�JšŸM˜MJ˜�JšœU™UJšœQ™QJšœP™PJšœ@™@J˜�JšÏnœžœžœ	žœ˜%J˜�JšœP™PJ™�š œžœžœ˜Jšœ	žœžœ˜Jšœž˜J˜—JšžœžœŸ"œ˜9J˜�JšœF™FJšœ0™0Jšœ™Jšœ\™\JšœL™LJšœP™PJšœ™Jšœ=™=J˜�š œžœžœ˜J˜Jšœžœ˜Jšœ	žœžœ˜J˜%J˜J˜JšžœžœŸ"œ˜9—J˜�Jšœ	™	J˜�Jš œžœžœ˜2J˜�JšœU™UJšœU™UJšœV™VJšœ?™?J˜�Jš œžœžœ˜1J˜�Jšœb™bJšœR™RJšœ1™1J˜�Jš 
œžœžœ˜2J˜�JšœR™RJšœR™RJšœW™WJšœS™SJšœR™RJ˜�Jš œžœžœ˜!J˜�JšœB™BJšœU™UJšœ%™%J˜�š œžœžœ	žœ˜/Jšžœžœ˜/J˜�—JšœM™MJšœU™UJšœ$™$J˜�š œžœžœ	žœ˜5Jšžœžœ˜0J˜�—JšœG™GJšœ)™)J˜�Jš
 œžœžœžœžœ˜1J˜�Jš œžœžœ˜/J˜�Jš 
œžœžœžœ˜@J˜�JšŸ\œÌ™¨Jš
 œžœžœžœžœ˜2J˜�Jš œžœžœ˜7J˜�Jš 
œžœžœ˜/J˜�J™µJ˜�J˜J˜�J˜4—�…—����ì��8s��