Some modems return the +COPS operator name in hex-encoded current
character set (as set with +CSCS). Others return the operator name
in ASCII when set to UCS2, while yet others return the ASCII name
with trash at the end (*cough* Huawei *cough*). Handle that better
by not crashing.
The `g_variant_new_from_data()' method uses the original array during its
operation, so we need to make sure it is valid as long as the method needs
it, or we'll end up with Valgrind complaining a bit:
==4834== Invalid read of size 1
==4834== at 0x36ADC75DA5: g_variant_get_byte (in /usr/lib64/libglib-2.0.so.0.3200.4)
==4834== by 0x3161ABED8C: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161ABEEA2: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161ABE844: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161ABE91E: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161ABEEA2: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161AC232E: g_dbus_message_to_blob (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161AB750A: ??? (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161AB9FEF: g_dbus_connection_send_message (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x3161ABDB22: g_dbus_connection_emit_signal (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x4C5B8BD: _mm_gdbus_sms_emit_changed (mm-gdbus-sms.c:2291)
==4834== by 0x36ADC47694: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
==4834== Address 0x939efa0 is 0 bytes inside a block of size 512 free'd
==4834== at 0x4A079AE: free (vg_replace_malloc.c:427)
==4834== by 0x36ADC4D37E: g_free (in /usr/lib64/libglib-2.0.so.0.3200.4)
==4834== by 0x36ADC1CF40: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
==4834== by 0x43C88E: assemble_sms (mm-sms.c:1260)
==4834== by 0x43CAD6: mm_sms_multipart_take_part (mm-sms.c:1329)
==4834== by 0x43E2EF: take_multipart (mm-sms-list.c:268)
==4834== by 0x43E546: mm_sms_list_take_part (mm-sms-list.c:328)
==4834== by 0x454C8F: mm_iface_modem_messaging_take_part (mm-iface-modem-messaging.c:353)
==4834== by 0x461DF6: sms_pdu_part_list_ready (mm-broadband-modem.c:5007)
==4834== by 0x3161A6CFB6: g_simple_async_result_complete (in /usr/lib64/libgio-2.0.so.0.3200.4)
==4834== by 0x432F82: at_command_parse_response (mm-base-modem-at.c:490)
==4834== by 0x489F96: handle_response (mm-at-serial-port.c:161)
Avoids this kind of issues:
[mm-sms-list.c:334] mm_sms_list_take_part(): SMS part at 'me/0' is from a singlepart SMS
[mm-iface-modem-messaging.c:475] sms_added(): Added received SMS at '/org/freedesktop/ModemManager1/SMS/31'
[mm-broadband-modem.c:4791] sms_pdu_part_list_ready(): Error parsing PDU (1): PDU too short (2): 41 < 79
GLib-WARNING **: GError set over the top of a previous GError or uninitialized memory.
This indicates a bug in someone's code. You must ensure an error is NULL before it's set.
The overwriting error message was: PDU too short (3): 28 < (210 + 14), user data length: '203'
[mm-broadband-modem.c:4791] sms_pdu_part_list_ready(): Error parsing PDU (2): PDU too short (3): 28 < (210 + 14), user data length: '203'
Sometimes the 'Mode Preference' TLV in the SSP response will have incorrect
values. The following log is for a Gobi3k modem which is *only* GMS/UMTS.
ModemManager[13415]: [/dev/cdc-wdm0] Received message...
>>>>>> QMUX:
>>>>>> length = 44
>>>>>> flags = 0x80
>>>>>> service = "nas"
>>>>>> client = 2
>>>>>> QMI:
>>>>>> flags = "response"
>>>>>> transaction = 1
>>>>>> tlv_length = 32
>>>>>> message = "Get System Selection Preference" (0x0034)
>>>>>> TLV:
>>>>>> type = "Result" (0x02)
>>>>>> length = 4
>>>>>> value = 00:00:00:00
>>>>>> translated = SUCCESS
>>>>>> TLV:
>>>>>> type = "Emergency mode" (0x10)
>>>>>> length = 1
>>>>>> value = 00
>>>>>> translated = 0
>>>>>> TLV:
>>>>>> type = "Mode Preference" (0x11)
>>>>>> length = 2
>>>>>> value = 0F:00
>>>>>> translated = 15
>>>>>> TLV:
>>>>>> type = "Band Preference" (0x12)
>>>>>> length = 8
>>>>>> value = FF:FF:FF:3F:FF:FF:FF:FF
>>>>>> translated = 18446744070488326143
>>>>>> TLV:
>>>>>> type = "Roaming Preference" (0x14)
>>>>>> length = 2
>>>>>> value = FF:00
>>>>>> translated = 255
Instead of setting to '1' only the bits related to GSM/UMTS in the "Mode
Preference" TLV, the modem sets all the bits it knows of to '1', including the
CDMA/EVDO ones. It is not easy to detect this properly, because the modem didn't
set to '1' the bits it didn't know of (e.g. LTE or TD-SCDMA), so we *cannot*
assume that 0x000F actually means 'unknown'.
So, we now will pass these returned values through the "DMS Get Capabilities"
filter, as we did for the Technology Preference result. The final reported
current capabilities will be either:
* The intersection between the capabilities loaded by "NAS Get System Selection
Preference" and "DMS Get Capabilities" or,
* The intersection between the capabilities loaded by "NAS Get Technology
Preference" and "DMS Get Capabilities".
For 'modem' (not 'current') capabilities, we still rely only on "DMS Get
Capabilities".
Modem plugins may set the 'modem' property before the 'config' property when
creating a bearer. set_signal_handlers() should thus be called after both
properties are set such that modem_{3gpp,cdma}_registration_state_changed
checks roaming allowance correctly when launching a connection.
Based on a draft patch by:
Ben Chan <benchan@chromium.org>
ModemManager configure script currenty requires glib 2.30.2 or later,
bud g_variant_new_fixed_array requires at least glib 2.32. To maintain
the compatibility with glib 2.30, this patch modifies the code to use
g_variant_new_from_data instead of g_variant_new_fixed_array.
For those who don't care about the QMI support through libqmi-glib, or if you're
stuck with glib 2.30 (libqmi-glib requires 2.32), this configure switch allows
disabling the QMI support completely.
The logic to detect cdc-wdm ports is still in place, but the QMI probing is
never launched at them. Also, all QMI-related objects won't be compiled.
Modems have a maximum of bearers allowed to be connected at a time, number which
is given by the number of available ports that may be used for data connections.
When Simple.Connect() tries to launch a connection, it will try to find first an
existing bearer with the required parameters (e.g. APN, IP type). If such bearer
is found, it will just use it. If no such bearer is found, it will try to create
one. When trying to create one, if there is no more room for bearers in the
modem, we will remove the first disconnected bearer that we find, if any, before
trying to create the new one. This logic now makes sure that no connected bearer
gets removed in order to create a new one, and also that only one existing gets
removed if possible (not every bearer as we did previously).
Further logic to connect multiple bearers at a time cannot be done using the
Simple interface.
Huawei modems will probe interface 0 always first; if we try to probe another
interface meanwhile the supports check will give us a MM_CORE_ERROR_RETRY error,
indicating that we need to defer the probing of the port.