Telephony (call and SMS) support
The telephony protocol defines record and message types for non-modem-hardware-specific telephony interactions.
Implementation. The protocol is (as of October 2022) implemented entirely within the
SqueakPhone Smalltalk image, in class CallManager
, HayesModemActor
,
SamsungGalaxyS7ModemActor
, and so on.
Available modem devices
A ModemPresent
record is asserted for each modem available to the telephony subsystem. The
type
field can, for example, be the symbol hayes
for a Hayes modem, samsung-galaxy-s7
for
a Samsung Galaxy S7, and so on. Each modem variant speaks a variant-specific
protocol across the dataspace
reference in the ModemPresent
record. Finally,
the devicePath
is a Linux device path representative of the modem, for example
/dev/umts_boot0
or /dev/EG25.AT
.
ModemPresent = <modem @type symbol @devicePath string @dataspace #:any> .
Telephony addresses (telephone numbers)
An Address
represents a phone number. The numberType
selects the numbering plan; the
number
is the actual address. Numbering plans are complex! The GSM specifications are the
place to go for details. In general, using international
with numbers like +31 6 ...
is the
best way forward.
Address = <address @numberType NumberType @number string> .
NumberType = =unknown / =international / =national / =gsm0338 .
Ongoing calls
An ActiveCall
assertion describes an active, ongoing call.
The callId
is a modem-specific call identification number. (TODO: if two modems are active,
their callId
s may clash.) The direction
is mo
for calls placed by the local phone
endpoint, i.e. those dialed by the local user, and mt
for calls placed by a remote phone,
i.e. incoming calls, those answered by the local user. The type
field describes whether the
call is for voice or data; usually, this will be voice
, but data
is reported by some modems
when using mobile data connections. As you might imagine, fax
-type calls are uncommon. The
peer
field describes the other phone's network address (phone number). Finally, state
describes the state of the call.
ActiveCall = <call-state @callId CallId @direction CallDirection @type CallType @peer Address @state CallState> .
CallId = int .
CallDirection = =mo / =mt .
CallType = =voice / =data / =fax .
CallState = =hold / =original / =connect / =incoming / =waiting / =end / =alerting .
Answering an incoming call
When an ActiveCall
record is asserted by the modem, if it has direction mt
and state
incoming
, the system should let the user choose to answer the call (or ignore it, etc.). If
the user chooses to answer, an AnswerCall
message tells the modem to do the necessary. The
callId
is the same value as in the ActiveCall
assertion.
# Message. Triggers call answering.
AnswerCall = <answer-call @callId int> .
Rejecting and/or disconnecting a call
Sending a DisconnectCall
message causes the modem to release an active call, either without
answering it (rejection) or while it is established (disconnection). The callId
is taken from
the ActiveCall
assertion, or is the symbol all
to request disconnection of all active
calls. The cause
field describes the release reason; it should usually be normal
, but
busy
or callRejected
may also be appropriate.
DisconnectCall = <disconnect-call @callId CallIdSelector @cause ReleaseCause> .
CallIdSelector = @specificCall int / @allCalls =all .
ReleaseCause =
/ =unassignedNumber
/ =normal
/ =busy
/ =noUserResponding
/ =callRejected
/ =destinationOutOfOrder
/ =normalUnspecified
/ =incompatibleDestination
.
Placing an outbound call
Sending a PlaceCall
message causes the matching modem (named by its devicePath
, which
should match a ModemPresent
assertion) to place an outbound call to the named peer
(a phone
number).
# Message. Starts an outgoing call.
PlaceCall = <place-call @devicePath string @peer Address> .
Whole-device call state
Many applications don't care about precise details of individual calls, but only whether or not
some ongoing call is active (alerting, connected, ringing etc.). Those applications may monitor
the CallInProgress
assertion.
CallInProgress = <call-in-progress> .
Whole-device ringing state
A PhoneRinging
assertion means that an incoming call is signalling the user, asking for a
decision about whether to answer, reject, or ignore the call.
PhoneRinging = <phone-ringing> .
A PeerRinging
assertion means that, during the establishment phase of an outgoing call, the
remote party's phone should be ringing.
PeerRinging = <peer-ringing> .
SMS deliveries and transmissions
An SmsDelivery
message indicates that an incoming SMS message has been received. The smsc
is the message relay server that forwarded the message on to us; this is usually some carrier-
and even plan-specific address, see the GSM specifications for details. The peer
is the
sender's phone number. The timestamp
describes the time associated with the SMS, and the
body
is the message itself.
SmsDelivery = <sms-delivery @smsc Address @peer Address @timestamp time.Stamp @body string> .
To send an SMS message, assert an SmsTransmission
record with the correct smsc
, the
peer
's destination phone number, and the body
of the message to send. The continuation
field should be a reference to an entity that expects the ok
symbol as a message when the
transmission has been processed by the modem.
# Assertion. An outgoing SMS should be transmitted.
SmsTransmission = <sms-transmission @smsc Address @peer Address @body string @continuation #:=ok > .
Speakerphone mode
The user may choose to assert a Speakerphone
record in order to request that the local audio
hardware switch profile to speakerphone mode during a call.
Speakerphone = <speakerphone> .