[Librem-5-dev] Adding AT commands to activate call audio over USB endpoint

Aleksander Morgado aleksander at aleksander.es
Thu Aug 9 08:45:20 PDT 2018


Hey

>>>> We're using a SIMCom SIM7100 modem which has the ability to exchange
>>>> call audio data over a USB serial endpoint⁰.  To enable this, the modem
>>>> needs an AT command after the call has connected, AT+CPCMREG=1, and a
>>>> command after call has disconnected, AT+CPCMREG=0.
>>>>
>>>
>>> Would these commands be needed as soon as a call is started (even if
>>> not established)? or just when established?
>>
>> After you send ATD.  The SIMCom docs say after your receive "VOICE CALL:
>> BEGIN" but it also says "If you want hear the ring back tone, you can
>> run "AT+CPCMREG=1" command after ATDXXX;" which is what we'd want.  I've
>> tested sending it immediately after ATD and that works.
>>
>>> Also, how would it work for received calls, at which point should the
>>> command be executed?
>>
>> I believe you get "VOICE CALL: BEGIN" when you answer the call so after
>> that.
>>
>> To summarise:
>>
>> --------------------------------------------------
>>   Command    |         When            | Call type
>> --------------------------------------------------
>> AT+CPCMREG=1 | After ATD               | outgoing
>> AT+CPCMREG=1 | After VOICE CALL: BEGIN | incoming
>> AT+CPCMREG=0 | After VOICE CALL: END   |   both
>> --------------------------------------------------
>>
>
> Ok.
>
>
>>
>>>> Not knowing the internals of ModemManager too well, I'm wondering if
>>>> anyone could advise on an appropriate way to add these AT commands for
>>>> our particular modem?
>>
>>> The way to do this would be to define a new async command in the Voice
>>> interface struct (mm-iface-modem-voice.h) and then in the same voice
>>> interface implementation setup the logic to call that command whenever
>>> needed, but only if it is implemented (e.g. in this case we would have
>>> NULL defaults as others modems don't need this). Once that logic is in
>>> place, we would need a new "simcom" plugin (there is none right now),
>>> which creates a new MMBroadbandModemSimcom that implements the voice
>>> interface and subclasses the specific command.
>>
>> I'm still trying to get my head around this.  There doesn't seem to be
>> anything similar in the voice interface, can you suggest another
>> interface with some similar functionality?
>>
>
> All interfaces are really organized in the same way: they provide a
> common logic with steps that maybe subclassed by plugins. Take for
> example the Voice interface, there is a method called
> enable_unsolicited_events() in the interface. This method is
> implemented by MMBroadbandModem in some specific way (e.g. running
> +CLIP=1 to show caller number on RING), and is then subclassed by the
> u-blox plugin to not only run the parent +CLIP=1 but also to also
> enable detailed call states with +UCALLSTAT=1. In your case, all the
> core logic is probably based on the MMBroadbandModem implementation
> (unless you're using QMI... are you?) so a new "simcom" plugin could
> subclass any specific step from any of the defined interfaces.
>
>> I don't understand the setup function you suggest.  What would this do?
>> If there is a SIMCom-specific subclass for the modem which adds the
>> AT+CPCMREG calls to the existing ATD calls or "VOICE CALL" handlers,
>> what would the MMIfaceModemVoice setup function do?
>>
>
> Forget about the Voice interface, this kind of logic should go in the
> Call interface instead. The "setup" command I was suggesting was
> something that would be called in the cases you listed above, e.g.
> just after ATD is executed or just after a call is accepted. This
> would fit within the logic of the Call interface, implemented by
> MMBaseCall; check the class definition in mm-base-call.h.
>
> But if you don't want to add any new subclass-able "setup" method,
> that would be ok as well. Instead you could just create a custom
> MMCallSimcom object and subclass methods of the parent MMBaseCall
> object:
>   * Subclass MMBaseCall start() so that the parent start() is first
> called, and only then you run AT+CPCMREG=1.
>   * Subclass MMBaseCall accept() so that the parent accept() is first
> called, and only then you run AT+CPCMREG=1.
>   * Subclass MMBaseCall hangup() so that you run AT+CPCMREG=0 and then
> the parent hangup() is called.
>   * You may also need to setup URC handlers for the VOICE CALL
> notifications, e.g. if VOICE CALL: END is the only way you have to get
> reported of terminated calls, so that you call AT+CPCMREG=0 also in
> that case.
>
> My "aleksander/next" branch in git has several voice related changes,
> including the MMUbloxCall subclass to support UCALLSTAT, that may help
> a bit:
> https://gitlab.freedesktop.org/mobile-broadband/ModemManager/tree/aleksander/next
>

Dan wrote something similar for Huawei devices, which require
AT^DDSETEX to enable the audio channel, see:
https://gitlab.freedesktop.org/mobile-broadband/ModemManager/commit/7a4ef42d98a1672d43818d42a8c62b0b544f7812
That is not yet in git master, though.

I'm rebasing Dan's dcbw/huawei-voice branch on top of my
aleksander/voice-fixes branch this week.

-- 
Aleksander
https://aleksander.es


More information about the Librem-5-dev mailing list