If the SMS part is from a multipart message we'll need to create a PDU with a
proper User Data Header.
This patch is based on a previous implementation by:
Roberto Majadas <roberto.majadas@openshine.com>
Call managers all want to be able to set the operator ID and/or name as soon as
we get registered. We will consider now that whenever we get into registered
state we already have operator code and name updated to the proper values.
Applications shouldn't, though, just rely on those values to be valid as long as
we're registered, as the modem may re-register automatically in some other
network (e.g. going from a roaming network to the home network).
This change involves not setting the state to REGISTERED until operator name
and code loading sequences have been run. We will still signal in the log the
change, with a new 'registering' intermediate state indication.
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".