Compare commits

402 Commits
Author SHA1 Message Date
Dan Williams 7f0bf17ab5 Merge request !1509 from 'netlink-completion-use-after-free'
netlink: fix use-after-free calling completion_fn on transaction completion

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1509
2026-10-04 23:10:41 -05:00
Dan Williams 9317cbc470 netlink: fix use-after-free calling completion_fn on transaction completion
'tr' is freed when removed from the hash table so we must cache any of its
member values that we need after removal.

Re-implementation of https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1442

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-10-04 23:07:53 -05:00
Dan Williams b422bd58ef Merge request !1507 from 'CVE-2026-95622-new'
CVE-2026-95622: cbm: don't assert handling unsupported encodings (8-bit and reserved)

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1507
2026-10-04 08:52:00 -05:00
Dan Williams ee761d009d CVE-2026-95622: cbm: don't assert handling unsupported encodings (8-bit and reserved)
A cell broadcast message using unsupported encodings would trigger an
assert in ModemManager and kill the process. A compromised base station
or modem firmware could craft or pass through these messages.

Reported by Yehia Ezzat and Keith Linneman

Impact: Moderate
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (6.5 Medium)
CWE-617 (Reachable Assertion)

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-10-04 08:52:02 -05:00
Dan Williams faa5642962 Merge request !1508 from 'qmi-add-pre-alerting'
broadband-modem-qmi: handle new QMI_VOICE_CALL_STATE_PRE_ALERTING

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1508
2026-10-04 08:48:38 -05:00
Dan Williams ac03e70426 broadband-modem-qmi: handle new QMI_VOICE_CALL_STATE_PRE_ALERTING
From https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/merge_requests/477

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-10-04 08:47:30 -05:00
Dan Williams 338ecc06f2 Merge request !1484 from 'service-killmode-mixed'
service: don't SIGTERM the QMI/MBIM proxies together with the daemon

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1484
2026-09-22 12:34:34 -05:00
Semyon Maryasin 225e66fea9 service: don't SIGTERM the QMI/MBIM proxies together with the daemon
The qmi-proxy/mbim-proxy processes spawned by the daemon live in the
service's cgroup, so with the default KillMode=control-group systemd
sends SIGTERM to them at the same time as to the daemon on every unit
stop. The proxy exits immediately, tearing the control channel from
under the daemon while it is still disabling the modems:

    <msg> caught signal, shutting down...
    <msg> [modem0] state changed (connected -> disabling)
    <msg> [modem0] port 'cdc-wdm0' no longer controllable, reprobing
    <wrn> [/dev/cdc-wdm0] MBIM error: Device must be open to send commands
    <wrn> shutdown failed: timeout waiting for sleep preparation to complete

The consequences of losing the proxy mid-shutdown:
 - the modem disable/disconnect never reaches the device, so an MBIM
   session with an active bearer is left open in the firmware (observed
   to occasionally wedge the MBIM function of a Sierra EM7565 until a
   firmware reset);
 - the port teardown stalls waiting on the dead proxy until the
   shutdown timeout, so stopping the unit always takes the full
   MAX_SHUTDOWN_TIME_SECS instead of a second or two;
 - the port invalidation triggers the device reprobe path in the middle
   of the shutdown.

With KillMode=mixed only the daemon receives SIGTERM; the proxies
survive long enough for a clean disconnect and MBIM/QMI close, and
whatever remains in the cgroup afterwards (an idle, stateless proxy) is
killed when the unit finally stops.

Signed-off-by: Semyon Maryasin <simeon@maryasin.name>
2026-09-22 12:31:25 -05:00
Dan Williams efb6a9833e Merge request !1495 from 'fix-cancellation'
bearer-mbim: fix cancellation when waiting for async SLAAC

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1495
2026-09-20 15:52:15 -05:00
Aleksander Morgado 07893109ea bearer-mbim: avoid deadlock when cancelling async SLAAC logic
g_cancellable_disconnect() must not be called from within the
cancellable callback, or it will deadlock.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-09-20 15:49:48 -05:00
Aleksander Morgado 0082587915 bearer-mbim: fix cancellation when waiting for async SLAAC
The first argument in the GCallback is actually the GCancellable.

  0x00005cf40027c2d3 (ModemManager - mm-bearer-mbim.c: 643)	ip_configuration_async_cleanup
  0x00005cf40027bfb9 (ModemManager - mm-bearer-mbim.c: 671)	ip_configuration_async_cancelled
  0x00007feda3a6fb33 (libgobject-2.0.so.0 - gclosure.c: 895)	_g_closure_invoke_va
  0x00007feda3a87da1 (libgobject-2.0.so.0 - gsignal.c: 3472)	g_signal_emit_valist
  0x00007feda3a88811 (libgobject-2.0.so.0 - gsignal.c: 3622)	g_signal_emit
  0x00007feda3b0f98d (libgio-2.0.so.0 - gcancellable.c: 519)	g_cancellable_cancel
  0x00005cf4001dd8fa (ModemManager - mm-base-bearer.c)	modem_3gpp_registration_state_changed
  0x00007feda3a6f8d2 (libgobject-2.0.so.0 - gclosure.c: 832)	g_closure_invoke
  0x00007feda3a8728a (libgobject-2.0.so.0 - gsignal.c: 3812)	signal_emit_unlocked_R
  0x00007feda3a883d4 (libgobject-2.0.so.0 - gsignal.c: 3565)	g_signal_emit_valist
  0x00007feda3a88811 (libgobject-2.0.so.0 - gsignal.c: 3622)	g_signal_emit
  0x00007feda3a7aac2 (libgobject-2.0.so.0 - gobject.c: 1428)	g_object_dispatch_properties_changed
  0x00007feda3a757b8 (libgobject-2.0.so.0 - gobject.c: 359)	g_object_notify_queue_thaw
  0x00007feda3a773a9 (libgobject-2.0.so.0 - gobject.c: 2793)	g_object_set_valist
  0x00007feda3a77db8 (libgobject-2.0.so.0 - gobject.c: 2957)	g_object_set
  0x00005cf40021492a (ModemManager - mm-iface-modem-3gpp.c: 2347)	update_non_registered_state

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-09-20 15:49:48 -05:00
Dan Williams b2017e5fd1 Merge request !1433 from 'id-mm-max-timeouts'
base-modem: make max timeouts configurable via udev rule

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1433
2026-09-20 15:49:17 -05:00
Filip Pokryvka 30e4577b4d base-modem: make max timeouts configurable via udev rule
Add the ID_MM_MAX_TIMEOUTS udev tag to allow users and system
administrators to configure the maximum number of consecutive
command timeouts before a modem is invalidated and re-probed,
on a per-device basis.

The tag accepts an integer value >= 0, where 0 disables the
timeout monitoring feature entirely. If not set, the existing
default of 10 consecutive timeouts is used.

This is needed for some older modems which become unresponsive
during consecutive data traffic, but come back alive when traffic
is lower. These modems have no further firmware updates available.

This follows the same pattern as other udev-configurable device
properties like ID_MM_MAX_MULTIPLEXED_LINKS.

Signed-off-by: Filip Pokryvka <fpokryvk@redhat.com>
2026-09-20 15:46:50 -05:00
Dan Williams e1f8061541 Merge request !1428 from 'fp/sierra_pco_disable'
Disable PCO on older Sierra modem MC7304

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1428
2026-09-08 12:03:26 -05:00
Filip Pokryvka 69cde63231 Disable PCO on older Sierra modem MC7304
Modem MC7304 has firmware flaw that PCO querry makes it unresponsive (firmware is not upgradable, no new release). There are possibily other older modems affected as well, I have no possibility to check. Add udev rule disabling PCO for affected modem (shares productID with RC7611).

Signed-off-by: Filip Pokryvka <fpokryvk@redhat.com>
2026-09-08 11:59:35 -05:00
Dan Williams 357130472d Merge request !1480 from 'creg_urc'
modem-helpers: fix multiple C*REG events in single URC

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1480

Closes #1087
2026-09-08 11:55:08 -05:00
Dominique Martinet 5e12f3fab5 tests: modem-helpers: test parsing multiple creg
The test_creg_match helper would only parse the first match, but actual
code e.g. parse_unsolicited() in src/mm-port-serial-at.c iterates over
all matches:
this updates the test to loop similarily to what is done in real code.

There were two tests assuming only the first match gets matched, so
their result were updated, and a third test was added matching the URC
received from a SIM7672 modem (including unrelated CNSMOD message)

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2026-09-08 18:52:03 +02:00
Dominique Martinet 04c9797456 modem-helpers: fix multiple C*REG events in single URC
When receiving a message from modem containing multiple CREG events that
have different format, the parsing happens in the order CREG regexes are
registered, and not in the order the modem sent the events.

That means that when receiving the following URC:
<CR><LF>+CEREG:  2<CR><LF><CR><LF>+CNSMOD: 8<CR><LF><CR><LF>+CEREG: 1,AAAA,01234567,7<CR><LF>
we'd incorrectly parse the `CEREG: 1` before `CEREG: 2`, and remember
the state as searching (2) instead of home (1), which can cause trouble
connecting because of waiting for state to go home which would never
happen again.

This fixes that problem by merging all the regexes together, so the
parsing should properly process the events in matching order in
parse_unsolicited()

Unfortunately changing the regex like this means that
mm_3gpp_parse_creg_response() match info handling also needs to be
reworked: matches number are increased for each regex, so we can
reliably know which regex was matched based on match count.
This is actually cleaner than the old approach that just guessed if nth
field with "item_is_lac_not_stat()", but requires careful testing.

This was validated checking that tests fail if any of the indices is
changed by iterating over them all and running the test:
grep -n 'n_matches -' src/mm-modem-helpers.c | sed -e 's/:.*//' \
	| while read lineno; do
		echo $lineno
		git show HEAD:src/mm-modem-helpers.c \
			| awk -v l=$lineno '{ if (NR == l) {
					print $1,$2,$3,$4,$5 - 1,";"
				} else {
					print
			}}' > src/mm-modem-helpers.c
		ninja -C build src/tests/test-modem-helpers || break
		build/src/tests/test-modem-helpers && break
	done

A test case was added to make this work, as the Samsung Wave S8500
sample 'act' doesn't seem to actually be a technology value?

(case 36/42 could actually be merged but were kept separate on purpose
for easier maintenance/testing)

Fixes: #1087
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2026-09-08 18:51:58 +02:00
Dan Williams 76c66944cc Merge request !1483 from 'patch-iccid-len'
Support ICCID length of 18 to 22

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1483
2026-09-04 22:57:34 -05:00
Semyon Maryasin 8d186a8df9 Support ICCID length of 18 to 22
Signed-off-by: Semyon Maryasin <simeon@maryasin.name>
2026-09-04 22:46:49 -05:00
Dan Williams b12f3bee54 Merge request !1490 from 'test-multipart-sms-pdu-type'
test-sms-list: test multipart concatenation differentiating by PDU type

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1490
2026-09-04 22:45:24 -05:00
Dan Williams 4449f2bc42 test-sms-list: test multipart concatenation differentiating by PDU type
Test the fix in MR !1469 that fixes the issue in #840.

If a multi-part PDU is sent from a device to its own number, on receipt
the DELIVER PDU was incorrectly dropped because when comparing the new
parts to existing ones, the comparison found the original SUBMIT PDU.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-09-04 22:46:09 -05:00
Dan Williams 23a87628e9 Merge request !1469 from 'multipart-sms'
broadband-modem: Fix receiving multipart SMS from own number

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1469
2026-09-04 21:37:31 -05:00
Christian Wendt ef88093931 broadband-modem: Fix receiving multipart SMS from own number
Signed-off-by: Christian Wendt <cw@brainaid.dk>
2026-08-31 08:30:13 +02:00
Dan Williams 5e91dd20c0 Merge request !1479 from 'modemmanager-coredump3'
qmi-shared: fix crash when passing a wrong log object

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1479
2026-08-30 10:16:27 -05:00
shuihan-001 efe507c240 qmi-shared: fix crash when passing a wrong log object
The patch resolves a coredump caused by using 'client' instead of 'self'
in mm_obj_warn() call when failing to register tracking events.

Signed-off-by: shuihan-001 <xing1989093@outlook.com>
2026-08-30 10:13:59 -05:00
Dan Williams c920ea6592 Merge request !1482 from 'patch-1'
Sierra Wireless EM7305: support ICCID response without !

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1482
2026-08-30 09:58:15 -05:00
Семён Марьясин a879fb717f Sierra Wireless EM7305: support ICCID response without !
On my modem, AT!ICCID? command gives response without a preceding `!`:

```
AT!ICCID?
ICCID: 8970162010103256136

OK
```

Signed-off-by: Semyon Maryasin <simeon@maryasin.name>
2026-08-30 09:54:17 -05:00
Dan Williams dc16f48f41 Merge request !1481 from 'caps-custom-data-class-str-init'
broadband-modem-mbim: initialize autofreed string to NULL

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1481

Closes #1094
2026-08-30 09:53:58 -05:00
Semyon Maryasin 6a14658a42 broadband-modem-mbim: initialize autofreed string to NULL
device_caps_query_ready() declares caps_custom_data_class_str as
g_autofree without an initializer. On every early error return
(command failure such as a transaction timeout or NotOpened, or a
response parse failure) the variable is never assigned, so the
autofree cleanup runs g_free() on uninitialized stack garbage,
crashing ModemManager with a glibc "invalid free" abort (or SIGSEGV)
whenever the device caps query fails during modem initialization.

Fixes: 19c817cfe9 ("broadband-modem-mbim: consistently handle custom data classes")
Closes: #1094

Signed-off-by: Semyon Maryasin <simeon@maryasin.name>
2026-08-30 09:49:13 -05:00
Dan Williams 53a9ad1aa2 Merge request !1477 from 'dp/libqcdm-write-fix'
libqcdm,tests: fix qcdm_send method for wwan

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1477
2026-08-29 23:32:50 -05:00
Daniele Palmas a838d3b98f libqcdm,tests: fix qcdm_send method for wwan
The qcdm wwan device does not cope well with writing single bytes,
while it does not have any issue if longer chunks are written.

Fix qcdm_send accordingly, since it should not hurt the previously
supported devices.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-08-29 23:29:38 -05:00
Dan Williams cc29b5dac2 Merge request !1489 from 'deprecated-meson-option'
build: add -Ddeprecated=[true|false] to control deprecated symbols

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1489
2026-08-29 23:29:11 -05:00
Dan Williams abf9babb02 build: add -Ddeprecated=[true|false] to control deprecated symbols
Instead of using CFLAGS="-DMM_DISABLE_DEPRECATED" meson ...
which doesn't handle -Werror very well let's make it an explicit
option. Defaults to true, and autodetects previous CFLAGS
mechanism to preserve backwards compatibility.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-08-29 23:29:13 -05:00
Dan Williams 306f6256f8 Merge request !1476 from 'altair-lte-216f-0041'
altair: add ALT3100 USB product ID

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1476
2026-08-17 08:27:28 -05:00
Nikolay Savchenko d446e495eb altair: add ALT3100 USB product ID
Signed-off-by: Nikolay Savchenko <n.savchenko@axioma.lv>
2026-08-03 02:13:16 +03:00
Aleksander Morgado 9a2d5863eb Merge request !1455 from 'fix/inject-assistance-typo'
mm-shared-qmi: fix error message for xtra data injection timeout

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1455
2026-07-21 12:05:19 +02:00
Andrey Skvortsov 893ca6bdb0 mm-shared-qmi: fix error message for xtra data injection timeout
Most likely it was copied from set supl server code.

Signed-off-by: Andrey Skortsov <andrej.skvortzov@gmail.com>
2026-07-21 12:02:41 +02:00
Aleksander Morgado de4306bfda Merge request !1471 from 'aleksander/small-fixes'
libqcdm: minor fix in comment formatting

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1471
2026-07-20 20:19:15 +02:00
Aleksander Morgado 07146dfdfd libqcdm: minor fix in comment formatting
Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-20 18:07:20 +00:00
Aleksander Morgado 3568fb91a8 Merge request !1468 from 'aleksander/vreports3'
cinterion: fix heap double-free during GPS location disablement

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1468
2026-07-13 13:33:37 +02:00
Aleksander Morgado 5bb7ece8b4 cinterion: fix heap double-free during GPS location disablement
https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1077

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-13 11:22:25 +00:00
Aleksander Morgado 8b77e71298 Merge request !1466 from 'aleksander/qcdm-vreports'
QCDM OOB read fixes

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1466
2026-07-13 11:25:58 +02:00
Aleksander Morgado 96cb590724 libqcdm: fix heap out-of-bounds read in qcdm_log_item_evdo_pilot_sets_v2_new
Validate the active, candidate, and remaining count fields in
qcdm_log_item_evdo_pilot_sets_v2_new() before parsing the sets.
Ensure the received buffer is large enough to contain the number of
sets claimed by the counts.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1070

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-13 10:59:28 +02:00
Aleksander Morgado e9932bde9d libqcdm: fix heap out-of-bounds read in qcdm_cmd_pilot_sets_result
Validate the active, candidate, and neighbor count fields in
qcdm_cmd_pilot_sets_result() before parsing the sets.

Ensure that the sum of counts does not exceed the size of the static
sets array in the response structure, and that the calculated size
based on the counts fits within the received buffer len.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1069

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-13 10:59:28 +02:00
Aleksander Morgado 76ca77a897 Merge request !1465 from 'aleksander/vreports2'
Various use-after-free fixes

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1465
2026-07-10 15:02:49 +02:00
Aleksander Morgado 9642ed9ab5 ublox: fix UAF in custom init ready URC handler
Clear the unsolicited message handler in ready_received() before
completing the task. Otherwise, if the modem sends subsequent READY
URCs, the handler would fire again using the freed GTask pointer.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1074

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado db72a182c1 port-serial-at: fix crash if URC handler is cleared mid-dispatch
Update parse_unsolicited() to re-check handler->callback on each
iteration of the match dispatch loop. If a URC handler callback clears
itself during dispatch (e.g. to stop listening), subsequent matches in
the same buffer would attempt to call the NULL pointer, causing a crash.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1074

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado c3e7ffaae0 plugins: fix GError double-frees when returning errors from tasks
Use g_steal_pointer() when passing g_autoptr(GError) to
g_task_return_error() to prevent double-free by the automatic cleanup.

GTask takes ownership of the passed GError. If we use g_autoptr(GError)
locally, it will also call g_error_free() when the function returns,
causing a double-free / heap corruption. Stealing the pointer clears the
local variable and prevents the automatic cleanup.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1073

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado 166d6c5bc8 quectel: fix UAF in RDY URC handler
Defer the validity change (which triggers modem reprobe/removal) to an
idle callback in rdy_handler().

Calling mm_base_modem_set_valid(FALSE) synchronously from the URC
handler triggers the immediate destruction of the modem object while the
serial port is still iterating the unsolicited message handlers. Deferring
the operation to an idle callback and taking a reference to the modem
ensures the modem object is kept alive until parse_unsolicited() has
returned.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1072

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado 46a91399ca shared-qmi: fix UAF on duplicate list-configs indications
Disconnect the 'list-configs' indication handler immediately inside the
callback. If the modem sends a duplicate indication before the whole
config load sequence completes, it could overwrite the stored
'get-config-info' signal handler ID, orphaning the old handler and
leading to a Use-After-Free when the GTask is completed and the
orphaned handler eventually fires.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1071

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado 2b1aaca4a0 ifaces: fix UAFs in signal handlers when hot-unplugging
Use g_signal_connect_object() to connect to child list/object signals
in the 3GPP, Messaging, Voice, and Cell Broadcast interfaces.

Passing the raw D-Bus skeleton pointer as user_data to these signals
can lead to a Use-After-Free if the skeleton is disposed of (e.g. on
hot-unplug) while the parent object or child list survives. By using
g_signal_connect_object(), the signal handlers are automatically
disconnected when the D-Bus skeleton is destroyed.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1068

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado 0280bbae3b time: fix GSource leak and UAF in timezone poll
Introduce a timezone poll session ID to validate timezone load
results. This ensures that when a pending timezone load completes, we
discard the result if a new poll session has been started (e.g. due to
registration state changes) or if polling has been stopped.

This prevents leaking GSource timeout sources and a subsequent
Use-After-Free if the modem is hot-unplugged while a poll is pending.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1067

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 15:00:07 +02:00
Aleksander Morgado 691bb4286d Merge request !1464 from 'aleksander/vreports'
Sanitize user inputs

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1464
2026-07-10 14:35:08 +02:00
Aleksander Morgado 6b3682ed65 voice: validate outgoing and deflect call numbers
Validate the number parameter in Voice.CreateCall and Call.Deflect
D-Bus methods to ensure they do not contain control characters or
semicolons. This prevents AT command injection when the number is
later spliced into ATD or +CTFR commands.

Introduce a common helper mm_utils_is_valid_dial_number() to validate
dial numbers, and add unit tests for it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1067

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Aleksander Morgado 3291e7dd1c sim: validate preferred networks operator codes
Validate preferred network operator codes in the SIM D-Bus interface
handler to ensure they are numeric. This prevents injecting AT
command delimiters (like CR) into this field, which is later spliced
into AT commands (+CPOL).

This change also plugs the network list leak, that was a problem on
its own.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1065

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Aleksander Morgado 50202ad76a sim: validate PIN and PUK codes
Validate PIN and PUK codes in the SIM D-Bus interface handlers to
ensure they are numeric. This prevents injecting AT command
delimiters (like CR) into these fields, which are later spliced
into AT commands (+CPWD, +CLCK, +CPIN).

Introduce a common helper mm_utils_is_numeric() to check if a string
contains only digits, and add unit tests for it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1065

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Aleksander Morgado dd54145d71 ussd: quote USSD command to prevent AT injection
When sending an unencoded USSD command, the user-supplied string was
spliced directly into the +CUSD AT command. If the string contained
CR or semicolons, it could lead to AT command injection.

Use mm_at_quote_string() to properly quote and escape the USSD
command before sending it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1064

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Aleksander Morgado a39d46c637 location: validate SUPL host as FQDN or IP
When parsing a SUPL address, if the host is not a valid IPv4 address,
validate it as a FQDN (allowing only alphanumeric characters, dots,
and hyphens). This prevents injecting AT command delimiters (like CR
or semicolon) into the host string, which is later spliced into
modem-specific AT commands (+XLCSSLP).

Introduce a common helper mm_utils_is_valid_fqdn() to validate FQDNs,
and add unit tests for it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1063

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Aleksander Morgado 1ee3a443b1 sms: sanitize decoded alphanumeric SMS addresses
Alphanumeric SMS addresses decoded from GSM-7 could contain control
characters (like CR/LF), which could lead to AT command injection
if the address is later spliced into an AT+CMGS command during
stored SMS send fallback.

Sanitize the decoded address by removing all control characters.

Introduce a common helper mm_utils_remove_control_characters() to
remove control characters from a string in-place, and add unit
tests for it.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1062

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-07-10 13:43:48 +02:00
Dan Williams 7088f5eaab Merge request !1457 from 'feat/update-man-mmcli'
man,mmcli: add information about 'any' modem index  and --location-monitor

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1457
2026-07-09 16:11:14 -05:00
Andrey Skvortsov 30b76ac3e2 man,mmcli: add description for --location-monitor
Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-07-08 23:09:23 -05:00
Andrey Skvortsov 6bdee3cc68 man,mmcli: add information about 'any' modem index for mmcli
It's possible to use special name 'any' as a modem index. It's
especially useful if system has only single modem.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-07-08 23:09:23 -05:00
Dan Williams d776ea38d2 Merge request !1458 from 'feat/use-any-in-man-mmcli'
man,mmcli: use '-m any' instead of '-m 0' in examples

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1458
2026-07-08 22:24:34 -05:00
Andrey Skvortsov 913f05e0b4 man,mmcli: use '-m any' instead of '-m 0' in examples
Most users have only single modem. Commands with '-m any' will work
even if modem gets new index, because it's restarted or is replugged.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-07-08 22:22:18 -05:00
Dan Williams cc69ce8aaf Merge request !1444 from 'main'
po: add Serbian and Serbian Latin translations

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1444
2026-07-08 22:11:44 -05:00
Марко М. Костић (Marko M. Kostić) 2c3e8aeee0 po: add Serbian and Serbian Latin translations
Signed-off-by: Marko Kostic <marko.m.kostic@gmail.com>
2026-07-08 22:04:01 -05:00
Dan Williams 2b2560c567 Merge request !1462 from 'upd-pt_BR'
po: update Brazilian Portuguese translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1462
2026-07-08 22:01:25 -05:00
Rafael Fontenelle 0fbb9d05d2 po: update Brazilian Portuguese translation
Signed-off-by: Rafael Fontenelle <rafaelff@gnome.org>
2026-07-08 21:59:02 -05:00
Dan Williams 98777e693f Merge request !1461 from 'dp/fix-me310g1-bnd'
ME910G1 and ME310M1 bands support and fixes

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1461
2026-07-07 11:11:51 -05:00
Daniele Palmas 97c24d68e2 telit: add support for ME310M1
ME310M1 supports band format as ME910G1.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-07-07 10:55:13 -05:00
Daniele Palmas 3ca0cba220 telit: add ME910G1 to models
ME910G1 supports decimal format for 4G bands and has also an empty
tdscdma slot between 4G and 4G extended bands commands/responses.

Change shared code and helpers to deal with these differences.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-07-07 10:55:13 -05:00
Daniele Palmas 846048caa5 telit: fix band setting function to properly support multi-tech modems
The assumption that if a modem supports a given access tech, the band
settings for that specific tech should be always given is wrong for
4g, since the 4g bands can be disabled setting the value to 0 in
multi-tech modems like ME310M1.

For example, a 3g + 4g modem could have a setting in which all
the 4g bands are unset and only 3g bands are there: this scenario is
not supported by the current code, but it's legitimate.

Remove this limitation and adapt the code to support bands setting
for multi-tech modems.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-07-07 10:55:13 -05:00
Daniele Palmas 069212e43e telit: add suffix HEX to 4G extended bands regex macro name
In preparation to support regex for 4G extended bands decimal values.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-07-07 10:55:13 -05:00
Daniele Palmas e292401beb telit: tests: fix LN920 current bands configuration
Fix LN920 current bands test configuration by setting
modem_has_hex_format_4g_bands to TRUE.

The current wrong setting does not cause the test failure since the modem
supports also extended settings and function telit_get_ext_4g_mm_bands
considers both standard and extended bands as hex without checking
the flag, since decimal format for extended bands is not supported.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-07-07 10:55:13 -05:00
Dan Williams 545b183934 Merge request !1467 from 'rm520-sahara-firehose'
quectel: add RM520N Sahara/Firehose support

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1467
2026-07-07 10:50:42 -05:00
Lukas Voegl 3dbdc0704d quectel: add RM520N Sahara/Firehose support
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2026-07-03 14:12:48 +02:00
Dan Williams fcc9d19f5e Merge request !1424 from 'fix/multiline-gsv'
location-gps-nmea: add complete sequence to traces at once

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1424
2026-05-26 19:16:43 -05:00
Andrey Skvortsov 13a3ee81a3 libmm-glib: add more tests for MMLocationGpsNmea
Extra tests cover various corner cases.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-05-26 20:56:53 +00:00
Dan Williams c0d9497066 libmm-glib: add tests for MMLocationGpsNmea
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-26 20:56:53 +00:00
Andrey Skvortsov f7da97989b location-gps-nmea: add complete sequence to traces at once
Currently sequence messages are added to traces as they are
received. Therefore content of traces depends at the time, when
request is issued and data is reported. Sometimes not all sequence
traces are reported, because only first record was received yet and it
overwrote previous full sequence trace.

For example,

```
$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68
$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53
$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60

$GLGSV,2,1,08,82,25,135,,76,11,029,,75,21,334,,69,11,201,,1*7A
```

one GSV sentence is missing and second later full sequence is
reported

```
$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68
$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53
$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60

$GLGSV,2,1,08,82,25,135,,76,11,029,,75,21,334,,69,11,201,,1*7A
$GLGSV,2,2,08,84,40,306,,83,79,161,,67,56,056,,68,58,177,,1*7D
```

Therefore client software reports different number of visible
satellites.

Usually sequence sentences are reported consequently in NMEA
stream. Let's cache and join sequence sentences until new trace type
is received. In that case full sequence always overrides
previous full sequence.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-05-26 20:56:53 +00:00
Andrey Skvortsov 38548fedd3 location-gps-nmea: use g_autofree in location_gps_nmea_take_trace to track ownership
It allows simplify error handling.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-05-26 20:56:53 +00:00
Dan Williams 42ca47472a Merge request !1431 from 'add-kk-l10n'
i18n: Add Kazakh translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1431
2026-05-25 10:10:36 -05:00
Baurzhan Muftakhidinov 027c8c068c po: add Kazakh translation
Signed-off-by: Baurzhan Muftakhidinov <baurthefirst@gmail.com>
2026-05-25 10:09:47 -05:00
Dan Williams 62a967131d Merge request !1427 from 'bulgarian'
po: add Bulgarian translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1427
2026-05-24 10:59:27 -05:00
twlvnn 07704018dd po: add Bulgarian translation
Signed-off-by: twlvnn <kraft_werk@tutanota.com>
2026-05-24 10:57:44 -05:00
Dan Williams de5058c283 Merge request !1429 from 'l10n-sv'
po: Update Swedish translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1429
2026-05-24 08:47:15 -05:00
Anders Jonsson fc1b1e9b1e po: Update Swedish translation
Signed-off-by: Anders Jonsson <anders.jonsson@norsjovallen.se>
2026-05-24 08:43:49 -05:00
Dan Williams 87c88dc237 Merge request !1421 from 'xmm7360-assert-cleanup'
intel: XMM7360: convert message parsing g_assert()s to GErrors and split out protocol functions

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1421

Closes #1034
2026-05-24 08:36:57 -05:00
Dan Williams a94dd40a2a intel: XMM7360: convert remaining asserts to error checks
Return useful errors rather than asserting on unexpected responses.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams fd98a809af sierra: enable XMM7160-based devices like Comneon HL7588
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams a486776a44 intel: XMM7360: better handle negative ASN integers from modem
The original code for xmm7360_byte_array_read_asn_int() returned
signed integers both from the function and from the returned
Xmm7360RpcMsgArg, but didn't handle sign extension on the
value returned from the function. That would lead to different
values between the function return and the Xmm7360RpcMsgArg
value, which seems wrong.

Make those two correspond and add checks in various places that
shouldn't ever see negative ints.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams d6fe0722c9 intel: XMM7360: add xmmrpc protocol test infrastructure
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 64d8053413 intel: XMM7360: move Xmm7360RpcMsgArgType UNKNOWN value first in enum
That way UNKNOWN is the zero'd value instead of BYTE; it's easier
to test for and less error-prone if not explicitly set to the right
value.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 4fead86d24 intel: XMM7360: better handling of silly ASN int sizes
xmm7360_byte_array_read_asn_int() would keep bit-shifting a gint into
oblivion if the int's size was > 32-bit. It also didn't handle size 0
ints at all, and while size 24 ints would get stuffed into a 32-bit
variable those probably aren't a thing and if they actually are they
should get specifically handled.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 3f7b39075c intel: XMM7360: move standalone protocol functions to their own file
So we can unit-test all the parsing and building code more easily
without having to link to a bunch of serial port stuff.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 07dc7e7304 intel: XMM7360: return a GError from parse_response_xmm7360()
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 1565e3ada7 intel: XMM7360: convert message parsing g_assert()s to GErrors (#1034)
We shouldn't be g_asserting (and thus crashing) on untrusted input code;
should instead check validity and return an error that upper layers
can reasonbly log and handle.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/1034

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-05-24 08:33:48 -05:00
Dan Williams 174f17f6ea Merge request !1438 from 'mtk_legacy_fix_err_memleak'
broadband-modem-mtk-legacy: fix `GError` memory leak

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1438
2026-05-24 08:15:06 -05:00
Barnabás Pőcze 62cc4de68e broadband-modem-mtk-legacy: fix GError memory leak
If the error matches, then a `+CIMI` command is sent to the device and
processing continues. However, the current error (for the `+CPIN?` command)
is not freed or propagated, fix that.

Fixes: 5c1fcbfe4a ("mtk-legacy: read IMSI if CPIN response is an error")
Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
2026-05-24 08:12:41 -05:00
Dan Williams a02355c5ce Merge request !1448 from 'qmi/handle-shuttingdown'
ModemManager: handle QMI_DMS_OPERATING_MODE_SHUTTING_DOWN similar as OFFLINE

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1448
2026-05-12 12:48:51 -05:00
Alexander Couzens 31cbf9c1be ModemManager: handle QMI_DMS_OPERATING_MODE_SHUTTING_DOWN similar as OFFLINE
Found and tested on Oneplus 6T with postmarketOS.

Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
2026-05-12 12:44:49 -05:00
Dan Williams 56f3ba761a Merge request !1449 from 'RW135'
plugin,rolling: Add udev rules for RW135R modules.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1449
2026-05-12 12:35:26 -05:00
Wenbin f6676cc5f3 plugin,rolling: Add udev rules for RW135R modules.
The Rolling needs to add the udev rules for supporting RW135R modules.

Signed-off-by: Wenbin <ywbjob@163.com>
2026-05-12 12:30:53 -05:00
Dan Williams 50759a2e52 Merge request !1440 from 'dco'
ci: Add build_container as a dependency of verify_dco job

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1440
2026-05-12 11:50:20 -05:00
Sebastian Krzyszkowiak 4a33e408e3 ci: Add build_container as a dependency of verify_dco job
Otherwise it fails for first contributions.

Signed-off-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
2026-05-12 11:47:32 -05:00
Aleksander Morgado 74159e05e2 Merge request !1447 from 'fix-rolling-single-plugin-build'
rolling: fix single plugin build

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1447
2026-04-22 16:40:36 +02:00
Aleksander Morgado 44330936c6 rolling: fix single plugin build
The MTK specific modem object should be included in the 'mtk' shared
utils, so that they're available to other plugins.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-04-22 14:27:38 +00:00
Aleksander Morgado d111c242c9 Merge request !1436 from 'mtk_support'
Rolling: Add modifications related to the rw350-usb project

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1436
2026-04-22 12:34:56 +02:00
xuhongxing b10139f96b Rolling: Add modifications related to the rw350-usb project
1.Modify rule files for the 33f8/0802 MI interface
2.Modify the rolling plugin code to share and reuse code from the mtk plugin

T: Bus=02 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 5 Spd=5000 MxCh= 0
D: Ver= 3.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS= 9 #Cfgs= 1
P: Vendor=33f8 ProdID=0802 Rev=00.01
S: Manufacturer=Rolling Wireless S.a.r.l.
S: Product=USB DATA CARD
C: #Ifs=10 Cfg#= 1 Atr=a0 MxPwr=896mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim
E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim
E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs
E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=06(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=87(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 7 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=07(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=88(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 8 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=08(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=89(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=09(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=8a(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms

Signed-off-by: xuhongxing <James.Xu@fibocom.com>
2026-04-22 18:26:57 +08:00
Aleksander Morgado fa32b5e1e9 Merge request !1445 from 'fix-qmi-wds-enum-missing'
modem-helpers-qmi: add missing QMI_WDS_PDP_TYPE_NON_IP check

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1445
2026-04-15 15:01:23 +02:00
Aleksander Morgado b6d53915a6 port-qmi: add missing QMI_DATA_ENDPOINT_TYPE_ETHERNET
Fixes build with latest libqmi.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-04-15 12:54:09 +00:00
Aleksander Morgado c34b326709 modem-helpers-qmi: add missing QMI_WDS_PDP_TYPE_NON_IP check
Fixes build with latest libqmi.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-04-15 12:46:28 +00:00
Dan Williams e5ce798783 Merge request !1432 from 'cbm-pad'
mm-cbm-part: Try harder to convert message text

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1432

Closes #1042
2026-03-24 21:01:05 -05:00
Guido Günther b59e0acb08 mm-cbm-part: Try harder to convert message text
Current cell broadcast messages from missile warnings in Israel
have an addition `00` at the end to pad for an even byte number.

This breaks conversion making the whole message fail conversion. As this
is a 15 part message in 3 languages the whole notification is lost in
this case.

Try harder to convert the message and recover even partial bits.

Closes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/1042
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2026-03-24 20:53:23 -05:00
Dan Williams eae9ed5485 Merge request !1435 from 'upstream-TX62-W-C-support'
plugins: cinterion: add new USB interface number for TX62-W-C modem

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1435
2026-03-24 12:59:08 -05:00
Lorenzo Medici 49fb75cd94 cinterion: add USB interface number 0x05 for TX62 modem
Signed-off-by: Lorenzo Medici <lorenzo.medici@canonical.com>
2026-03-20 16:24:04 +02:00
Aleksander Morgado 8053db6cc0 Merge request !1426 from 'id-mm-typos'
api,doc: fix a typo in 'Modem.Device' documentation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1426
2026-02-03 12:01:53 +01:00
Aleksander Morgado d8a01479ed api,doc: fix a typo in 'Modem.Device' documentation
Originally reported by Lubomir Rintel.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2026-02-03 11:59:32 +01:00
Aleksander Morgado 66e72979a1 Merge request !1423 from 'local1'
rolling: update RW101 port type hints

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1423
2026-02-03 11:53:53 +01:00
Wenbin 387c41cb04 rolling: update RW101 port type hints
The port type hints for the RW101-cat6 and RW101-cat12 have been
updated, with USB interface #2 now designated as both the AT primary
port and fastboot port.

Signed-off-by: Wenbin <ywbjob@163.com>
2026-02-03 11:49:42 +01:00
Aleksander Morgado 1fc9059407 Merge request !1425 from 'dp/port-hints'
Port hints for various Telit modems

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1425
2026-02-03 10:58:52 +01:00
Daniele Palmas aa2aa54748 telit: add port hints for FN990B40 rmnet and MBIM compositions
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-01-30 16:09:01 +01:00
Daniele Palmas 6131303fb2 telit: add port hints for FE910C04 rmnet and MBIM compositions
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-01-30 16:08:37 +01:00
Daniele Palmas c1386905f3 telit: add port hints for FE990B40 rmnet and MBIM compositions
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-01-30 16:08:12 +01:00
Daniele Palmas 8f4e8bd24c telit: add port hints for FN920C04 rmnet and MBIM compositions
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2026-01-30 16:07:52 +01:00
Dan Williams 089d0e3353 Merge request !1418 from 'feat/inject-time-position'
shared-qmi: handle inject time and inject position requests from the modem

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1418
2026-01-09 17:20:44 -06:00
Andrey Skvortsov c0f0c02ac1 tests: add tests for location-cache
only GGA NMEA sentences are supported by current implementation of
MMLocationGpsRaw. RMC and GLL messages are added, but currently test
are negative.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-01-10 02:04:10 +03:00
Andrey Skvortsov 8b6116fe6c shared-qmi: handle inject position requests from the modem
To be able to have quick position fix GNSS engine needs to know
 - predicted orbits data,
 - current time,
 - approximate position.
Modem sends indications with requests, when it needs corresponding
information. Predicted orbits can be injected using
'mmcli -m any --location-inject-assistance-data=<file>'. But to
accelerate time to first fix after cold start extra information is
needed like time and coarse position.

Inject position requests are received, when GPS session is initiated
using QMI_LOC_START. In inject position request modem sends
information about its last known position. If last known position is
zero, when this is a cold start and inject position is needed to
improve TTFF.
Last position from the modem is cached in ModemManager and is injected
next time, when modem requests it. For example, if modem is restarted.

When timestamp on injected position is too old, than position is
ignored and location engine does cold start. Therefore current time is
used for injected position.

When injected position is far away the actual one (for example, after
flight), after some time location engine falls back to cold start.

Tested on Quectel EG25-G.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-01-10 02:04:10 +03:00
Andrey Skvortsov a108a0fe7c build: Fix meson deprecation warnings
following warnings are fixed:
Dependency udev found: YES 258 (cached)
../meson.build:202: WARNING: Project targets '>= 0.60.0' but uses
   feature deprecated since '0.56.0':
   dependency.get_pkgconfig_variable. use
   dependency.get_variable(pkgconfig : ...) instead
Dependency systemd found: YES 258 (cached)
../meson.build:212: WARNING: Project targets '>= 0.60.0' but uses
   feature deprecated since '0.56.0':
   dependency.get_pkgconfig_variable. use
   dependency.get_variable(pkgconfig : ...) instead
Dependency libsystemd found: YES 258 (cached)
Dependency polkit-gobject-1 found: YES 126 (cached)
../meson.build:245: WARNING: Project targets '>= 0.60.0' but uses
   feature deprecated since '0.56.0':
   dependency.get_pkgconfig_variable. use
   dependency.get_variable(pkgconfig : ...) instead
Dependency mbim-glib found: YES 1.32.0 (cached)
Dependency qmi-glib found: YES 1.37.1 (cached)
../meson.build:302: WARNING: Project targets '>= 0.60.0' but uses
   feature deprecated since '0.56.0':
   dependency.get_pkgconfig_variable. use
   dependency.get_variable(pkgconfig : ...) instead

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-01-10 02:04:10 +03:00
Andrey Skvortsov 8ac3dfb955 location-cache: add class to store cached location
This class allows to preserve cached position across ModemManager restarts.
Cached location can be used to improve time to first fix after device
start by injecting coarse position into location engine. Since there
wasn't any fix yet, position in ModemManager is unknown. To fix this
cached location is saved on disk (/var/lib/ModemManager/location.ini)
when location session is stopped or ModemManager is stopped and loaded
on the next start from the file.

install_emptydir is introduced in meson 0.60.

Distributions has to create directory to store cached location in
packaging, because ModemManager runs under systemd isolation with
limited rights and it can't create this directory by itself.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-01-10 02:04:10 +03:00
Andrey Skvortsov 81101b0147 shared-qmi: handle inject time requests from the modem
To be able to have quick position fix GNSS engine needs to know
 - predicted orbits data,
 - current time,
 - approximate position.
Modem sends indications with requests, when it needs corresponding
information. Predicted orbits can be injected using
'mmcli -m any --location-inject-assistance-data=<file>'. But to
accelerate time to first fix after cold start extra information is
needed like time and coarse position. This commit injects UTC time.

UTC time inject requests are received, when GPS session is initiated
using QMI_LOC_START.

Tested on Quectel EG25-G.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2026-01-10 02:04:10 +03:00
Dan Williams 90e71e2817 Merge request !1420 from 'uml290-network-time-broken'
broadband-modem,pantech: network time broken on UML290

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1420
2026-01-09 06:04:21 -06:00
Dan Williams 061a9956d0 broadband-modem,pantech: network time broken on UML290
UML290 with firmware L0290VWBB12F.248 doesn't support QMI network
time and crashes when asked for AT network time too quickly after
being plugged in.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-01-09 05:59:17 -06:00
Dan Williams 314b6e7761 Merge request !1422 from 'ci-ubuntu-2204'
ci: bump Ubuntu version in CI image for meson >= 0.56 for libqmi

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1422
2026-01-05 22:39:00 -06:00
Dan Williams 0636260a39 ci: bump Ubuntu version in CI image for meson >= 0.56 for libqmi
Latest libqmi requires meson 0.56 or later, which 22.04 has.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2026-01-05 22:36:47 -06:00
Dan Williams 61e2f69d48 Merge request !1415 from 'release-1.25.95'
release: bump version to 1.25.95

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1415
2025-11-24 23:58:16 -06:00
Dan Williams e12e1f4183 release: bump version to 1.25.95
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-11-24 23:55:56 -06:00
Dan Williams 5ca95a64ab Merge request !1410 from 'dp/initial-qmap-mux-id'
port-qmi: allow setting initial mux-id value when using rmnet multiplexing

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1410
2025-11-24 23:53:56 -06:00
Daniele Palmas 4678f3226e telit: add ID_MM_INITIAL_QMAP_MUX_ID udev tag to LE910Cx
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-11-24 23:50:03 -06:00
Daniele Palmas d2de8ff226 port-qmi: allow setting initial mux-id value when using rmnet multiplexing
Qualcomm suggests to use mux id values >= 0x81: though this does not
seem a strict mandatory rule, there are scenarios in which the usage of
a specifix mux id is required otherwise various kind of issues could
happen (e.g. call failure, limited throughput...).

A new ID_MM_INITIAL_QMAP_MUX_ID udev tag allows setting the first initial
mux id value to be used when creating the multiplexed data connection.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-11-24 23:50:03 -06:00
Dan Williams 0f19f10958 Merge request !1417 from 'libqmi-bump-1-37-95'
meson: bump libqmi requirement to 1.37.95

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1417
2025-11-24 23:43:23 -06:00
Dan Williams 3a2a33d3f0 meson: bump libqmi requirement to 1.37.95
Latest libqmi adds QMI_NAS_RADIO_INTERFACE_NO_CHANGE which will
cause failures when building with -Wall if NO_CHANGE isn't handled
in switch() statements. So we add that. But then of course you can't
build with older libqmi because it doesn't have NO_CHANGE.

So just bump the requirement.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-11-24 23:40:27 -06:00
Dan Williams a73b0675b5 Merge request !1413 from 'patch-3'
l10n: Update sl.po

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1413
2025-11-24 23:39:55 -06:00
filmsi 936379a832 Upload Slovenian (sl) po file
Signed-off-by: Martin Srebotnjak <miles@filmsi.net>
2025-11-24 23:37:19 -06:00
Dan Williams d2b7453422 Merge request !1416 from 'qmi-QMI_NAS_RADIO_INTERFACE_NO_CHANGE'
modem-helpers-qmi: update for QMI_NAS_RADIO_INTERFACE_NO_CHANGE

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1416
2025-11-24 23:32:37 -06:00
Dan Williams c1112a2ee4 modem-helpers-qmi: update for QMI_NAS_RADIO_INTERFACE_NO_CHANGE
In latest libqmi.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-11-24 23:30:32 -06:00
Dan Williams ff6a1ec9e6 Merge request !1414 from 'fix/typo'
iface-modem-location: Fix typo in error message

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1414
2025-11-24 23:20:50 -06:00
Andrey Skvortsov 4023c61c71 iface-modem-location: Fix typo in error message
Fixes: 091bf4dbd8 ("shared-qmi: implement LOC-based GPS/A-GPS support")

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-11-05 23:29:36 +03:00
Dan Williams 2a4c7e3a5b Merge request !1409 from 'fix/engine-unlock'
shared-qmi: unlock location engine at modem start

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1409
2025-10-20 15:33:28 -05:00
Andrey Skvortsov 9c4aeeb33a shared-qmi: unlock location engine at modem start
On SDM845 (OP6T) modem always starts with engine lock 'all'.
It doesn't allow to read assistance server settings at the beginning.
QMI call 'Get Predicted Orbits Data Source' (0x0036) fails with general
failure. As a result it's not possible to inject assistance data using
'mmcli -m any --location-inject-assistance-data=<file>'.

Commit 90843b7a0d ("shared-qmi: Lock and unlock GPS engine when
starting and stopping") unlocks engine on GNSS start, that allows
geolocation to work on SDM845, but it locks engine back on GNSS stop.
As a result after GNSS stop it's not possible to inject XTRA data again.

On EG25-G engine lock settings is stored in NV storage and is preserved after
modem restart. By default engine lock is 'none'. But currently on GNSS
stop this value is changed to 'all', that blocks location engine.
If previous ModemManager version is installed after
stopping geolocation and locking the engine, geolocation will not
work, since the engine is still locked and modem restart will not help.

This commit unlocks engine on modem start so all following operations
with an engine succeed. Engine isn't locked back.

Tested on SDM845 (OP6T) and Quectel EG25-G.

Fixes: 90843b7a0d ("shared-qmi: Lock and unlock GPS engine when starting and stopping")

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-10-20 15:30:54 -05:00
Dan Williams f2318ecc7b Merge request !1365 from 'fix-generic-virtual'
Fix generic driver not attaching to virtual ports

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1365
2025-10-20 15:18:57 -05:00
Sonya Sireneva 7e5e6c6912 Fix generic driver not attaching to virtual ports
Since c2e3a8c10e, the generic plugin was
not able to attach to virtual ports, because they have no associated
driver, and the probe fails with "port filtered as couldn't retrieve
driver". It seems that this driver check was accidentially introduced
and is not really necessary, as there isn't a special "XMMRPC driver"
to blacklist.

Signed-off-by: Sonya Sireneva <sleirsgoevy@gmail.com>
2025-10-20 15:16:32 -05:00
Dan Williams a2ed571ccf Merge request !1411 from 'main'
sim-mbim: fix `preload_cancellable` bug that causes a crash

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1411
2025-10-16 07:22:47 -05:00
Rukun Mao 469c686504 sim-mbim: fix preload_cancellable bug that causes a crash
In merge request !1405, when handling subscriber_ready_status_ready()
fails, it exits early and allows preload retry without resetting
`self->priv->preload_cancellable`. When the preload_subscriber_info() runs
again, it fails at g_assert check and causes a crash.
Before !1405, `self->priv->preload_cancellable` is reset within
application_list_query_ready().

Signed-off-by: Rukun Mao <rmao@google.com>
2025-10-15 18:24:19 +00:00
Dan Williams a8280207fc Merge request !1408 from 'main'
fcc-unlock 105b: Add support for Foxconn SDX55 running in USB mode

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1408

Closes #984
2025-10-07 08:18:55 -05:00
Kajetan Krykwiński bf67727c1c fcc-unlock 105b: Add support for Foxconn SDX55 running in USB mode
Signed-off-by: Kajetan Krykwiński <github@kitor.pl>
2025-10-07 08:14:57 -05:00
Dan Williams 7b44ca740c Merge request !1407 from 'mhi-pci-generic-driver'
broadband-modem-mbim: handle mhi-pci-generic as a valid data port driver

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1407
2025-10-07 08:11:56 -05:00
Dan Williams c3ef78cc6c broadband-modem-mbim: handle mhi-pci-generic as a valid data port driver
mhi_wwan_mbim ends up being detected as mhi-pci-generic, so we need to
look for that in addition to cdc_wwan when doing MBIM data port stuff.
Otherwise devices (various Foxconn X55/X72, Cinterion MV3x, Quectel
EM1xx, Telit FN990) that expose the IP_HW0_MBIM MHI channel won't
correctly clean up data ports on startup, and may not correctly
handle bearer multiplexing.

mhi_net is only used for QMI devices with rmnet so it shouldn't
be involved in the MBIM data path at all.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-10-03 16:18:48 -05:00
Dan Williams 72dca00e69 Merge request !1401 from 'dp/fix-mux-bearer-cleanup-assert'
base-manager: fix cleanup of multiplexed bearers

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1401
2025-10-03 12:43:23 -05:00
Daniele Palmas 0edcb916ad base-manager: fix cleanup of multiplexed bearers
Cleaning up multiple active multiplexed bearers causes an assert in
mm_iface_modem_count_bearers since the max number of active bearers
is not properly determined.

Rework the management of the flags in order to better match their
intents, considering that MULTIPLEXED is a subset of ACTIVE/CONNECTED.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-10-03 10:51:59 +02:00
Dan Williams 8d911cdd1a Merge request !1405 from 'main'
sim-mbim: continue preload retry if previous attempt(s) fails

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1405
2025-10-01 15:32:54 -05:00
Rukun Mao 9ec1d25607 sim-mbim: continue preload retry if previous attempt(s) fails
Before the change, preload is attempted once regardless of its
results. When the first attempt fails, it got stuck and can not get valid
SIM info.

Signed-off-by: Rukun Mao <rmao@google.com>
2025-10-01 15:29:58 -05:00
Dan Williams c6740c0a7e Merge request !1406 from 'local_br'
plugin,rolling: Add udev rules for RW101R modules.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1406
2025-09-30 09:01:16 -05:00
Vanillan Wang d2f4ca8a5b plugin,rolling: Add udev rules for RW101R modules.
The Rolling needs to add the udev rules for supporting RW101R modules.

Signed-off-by: Vanillan Wang <vanillanwang@163.com>
2025-09-30 08:58:49 -05:00
Dan Williams 01e9b1ab48 Merge request !1404 from 'fix/whitespaces'
shared-qmi: replace tabs with whitespaces

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1404
2025-09-27 09:04:34 -05:00
Andrey Skvortsov c0933d2f18 shared-qmi: replace tabs with whitespaces
Fixes: 103eb9cf29 ("shared-qmi,modem-helpers-qmi: Add support for NR5G band preference")

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-09-27 09:01:57 -05:00
Dan Williams af622ab19d Merge request !1403 from 'fix/supl-typo'
cli, location: Fix typo in error message

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1403
2025-09-27 09:01:02 -05:00
Andrey Skvortsov 37f73c7b6b cli, location: Fix typo in error message
Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-09-21 15:32:10 +03:00
Dan Williams a1ef6a16c4 Merge request !1400 from 'lr/intel-fibocom-l850-gl'
fibocom: Fix support for Intel-branded Fibocom L850-GL

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1400
2025-09-19 09:50:15 -05:00
Lubomir Rintel 76c055dcef fibocom: Add rules with hints for L850-GL (Intel)
The device would eventually be automatically probed. Add hints anyway,
as not to waste time with the generic probe.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
2025-09-19 09:46:52 -05:00
Lubomir Rintel f79cf7c78e fibocom: Add vendor ID for Intel
Seen on an OEM modem labeled as "Fibocom L850-GL":

  ID 8087:095a Intel Corp. MODEM + 2 CDC-ACM + 3 CDC-NCM + SS

XMM-based modem, detected fine by the plugin:

  [ttyACM2/at] <-- 'AT'
  [ttyACM2/at] <-- '<CR><CR><LF>OK<CR><LF>'
  [ttyACM2/probe] port is AT-capable
  [ttyACM2/probe] probe step: XMM
  [ttyACM0/at] <-- '<CR><LF>OK<CR><LF>'
  [ttyACM0/probe] port is AT-capable
  [ttyACM0/probe] probe step: XMM
  [ttyACM2/at] --> 'AT+XACT=?<CR>'
  [ttyACM0/at] --> 'AT+XACT=?<CR>'
  [ttyACM2/at] <-- 'AT+XACT=?'
  [ttyACM2/at] <-- '<CR><CR><LF>+XACT: (0-6),(0-2),0,1,2,4,5,8,101,102,103,104,105,107,108,112,113,117,118,119,120,126,128,129,130,141,166<CR><LF><CR><LF>OK<CR><LF>'
  [ttyACM2/probe] modem is XMM-based
  [ttyACM0/at] <-- '<CR><LF>+XACT: (0-6),(0-2),0,1,2,4,5,8,101,102,103,104,105,107,108,112,113,117,118,119,120,126,128,129,130,141,166<CR><LF><CR><LF>OK<CR><LF>'
  [ttyACM0/probe] modem is XMM-based
  [device /sys/devices/pci0000:00/0000:00:14.0/usb1/1-3] creating modem with plugin 'fibocom' and '6' ports (8087:095a)
  [plugin/fibocom] (fibocom) XMM-based Fibocom modem found...

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
2025-09-19 09:46:52 -05:00
Dan Williams 186768a071 Merge request !1402 from 'piotrdrag/pl-update-250913'
Update Polish translation 250913

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1402
2025-09-19 09:20:28 -05:00
Piotr Drąg b3b221a458 Update Polish translation
Signed-off-by: Piotr Drąg <piotrdrag@gmail.com>
2025-09-13 11:43:49 +02:00
Dan Williams 6eaf45c194 Merge request !1399 from 'cesq-space'
modem-helpers: handle no space after "+CESQ:"

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1399
2025-09-11 08:27:15 -05:00
Dan Williams ee75d23f00 modem-helpers: handle no space after "+CESQ:"
See https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1277
for more details.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-09-11 08:24:42 -05:00
Dan Williams 672a1e29c8 Merge request !1398 from 'l10n-sv'
po: update Swedish translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1398
2025-09-05 19:13:35 -05:00
Anders Jonsson ae3731ca69 po: update Swedish translation
Signed-off-by: Anders Jonsson <anders.jonsson@norsjovallen.se>
2025-09-05 19:09:34 -05:00
Dan Williams 4821968fb2 Merge request !1396 from 'primary-slot-polkit'
data, polkit: Add policy rule for setting primary sim slot

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1396
2025-09-05 11:34:55 -05:00
Felipe Borges d5bee2bca6 data, polkit: Add policy rule for setting primary sim slot
Needed for exposing the modem's Primary sim slot setting in
GNOME Settings.
See https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/2867

Signed-off-by: Felipe Borges <felipeborges@gnome.org>
2025-09-05 11:31:25 -05:00
Dan Williams 2f6fc0d038 Merge request !1397 from 'piotrdrag/pl-update-250827'
Update Polish translation 250827

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1397
2025-09-05 11:23:36 -05:00
Piotr Drąg 5833887c21 Update Polish translation
Signed-off-by: Piotr Drąg <piotrdrag@gmail.com>
2025-08-28 18:28:06 +02:00
Dan Williams 9405ade83b Merge request !1395 from 'patch-2'
Add Slovenian (sl) to ModemManager

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1395
2025-08-28 09:25:46 -05:00
filmsi f5a650b9bd Upload Slovenian (sl) po file
Signed-off-by: Martin Srebotnjak <miles@filmsi.net>
2025-08-27 14:34:10 -05:00
Dan Williams 9fced3767a Merge request !1389 from 'fix/set-supl-server'
shared-qmi: fix setting URL to supl server

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1389
2025-08-16 16:23:06 -05:00
Andrey Skvortsov 0e1bfdb5b6 shared-qmi: fix setting URL to supl server
Function mm_parse_suple_address returns TRUE on valid input data
regardless of its type (URL or IP). As a result
qmi_message_loc_set_server_input_set_ipv4 was always called on valid
data. If URL was provided, then 0.0.0.0 ip address was sent to the
modem instead of provided URL.

Fixes: 6e84f3d459 ("iface-modem-location: validate SUPL server address")

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-08-16 21:02:14 +00:00
Dan Williams 1547c4d812 Merge request !1340 from 'qmi-gps-sdm670'
GNSS support for SDM670 devices

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1340
2025-08-16 11:36:25 -05:00
Richard Acayan 0d69304702 shared-qmi: Register NMEA types indication callbacks earlier
It might be too late to register the indication callbacks after the
response is received. Register the callbacks when the request is made so
an requested indication will always be handled.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-16 11:32:16 -05:00
Richard Acayan 90843b7a0d shared-qmi: Lock and unlock GPS engine when starting and stopping
Newer modem firmware requires the use of the GPS engine lock, which
controls what the GPS engine can do. Set the GPS engine lock when
appropriate to handle this newer firmware.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-16 11:32:16 -05:00
Richard Acayan b529b69fb6 shared-qmi: always set NMEA types
By default, the Pixel 3a only emits $PQXXX traces, even when all the
desired traces are reported as enabled. A request to set the NMEA types
must still be sent to enable the GGA/GSA/GSV traces. Remove the
optimization that prevents the request from happening automatically.

Signed-off-by: Richard Acayan <mailingradian@gmail.com>
2025-08-16 11:32:16 -05:00
Dan Williams 848c4a95ee Merge request !1393 from 'supl-ip-byte-order-doc'
modem-helpers: document mm_parse_supl_address()

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1393
2025-08-16 11:31:46 -05:00
Dan Williams aca647cf9d modem-helpers: document mm_parse_supl_address()
More specifically, that the returned IP address is in network
byte order.

See https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1390

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-08-16 11:22:02 -05:00
Dan Williams c2a5b54f79 Merge request !1390 from 'fix/set-supl-server-ip'
shared-qmi: fix byteorder for supl server IP

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1390
2025-08-16 10:10:57 -05:00
Andrey Skvortsov f51cc9488b shared-qmi: fix byteorder for supl server IP
It was noted, that when supl server is set using IP address. Modem
doesn't connect to the SUPL server anymore. When IP address is inverted,
then modem connects to SUPL server successfuly.

IP address is stored as uint32_t. According to Telit's documentation [1]
numeric values are encoded in little-endian format in QMI.

After converting IP address from string to binary using inet_pton
IP address is stored in network byte order (big-endian). Therefore it's
needed another convertion from big-endian to host endianness. Final
conversion from host endianness to endianness needed for QMI will be
done in generated
qmi_message_pds_set_agps_config_input_set_location_server_address.

Vendor's Android GNSS hal uses htonl() to convert from struct in_addr
(already in big-endian) before sending QMI request as well [2].

Tested on Quectel EG25-G and SDM845 (OnePlus 6T).

1. FN980 Family Telit Proprietary QMI Command Reference Guide. 4.1.3.1 Byte Ordering
2. https://github.com/ugly-kid-af/device_xiaomi_violet/blob/snow/gps/gnss/GnssAdapter.cpp#L1110

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-08-10 21:05:13 +00:00
Dan Williams 14031a4b1b Merge request !1391 from 'lang'
cbm-part: Use the correct codes for Czech and Danish

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1391
2025-08-08 21:48:29 -05:00
Guido Günther ef757daa1a cbm-part: Use the correct codes for Czech and Danish
Use the ones from the iso639 set 1.

Fixes: 0bd0cad70 ("cbm-part: Handle additional coding schemes and parse languages")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-08-08 21:45:50 -05:00
Dan Williams 5121a9413a Merge request !1382 from 'fix-port-array'
cli: free ignored ports

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1382
2025-08-04 09:51:52 -05:00
Lukas Voegl e8a5ba04d0 cli: free ports only if not NULL
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2025-08-01 11:18:54 +02:00
Lukas Voegl 3b8332a5a8 cli: free ignored ports
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2025-08-01 11:18:54 +02:00
Dan Williams d9d1907157 Merge request !1367 from 'mr/20250530-cinterion'
cinterion: add MV32/MV31 udev rules and AT workarounds

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1367
2025-07-30 13:00:03 -05:00
Florian Eckert 1a9602ab6a cinterion: ignore carrier revision
MV31 MBIM modem firmware revisions are not matched with carrier configs.
Different VoLTE profiles might be selected by the user causing
the carrier config revision to change.

Since fwupd uses this string for firmware updates, it gets confused and
thinks the user has an update available.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-07-30 12:41:22 -05:00
Florian Eckert 5d4b0d3516 cinterion: add hardware revision read via AT for MV31 and MV32
Reading the hardware revision via the mbim interface returns an incorrect
hardware revision string. The output is always set to
'h/w revision: Thales Snapdragon X55'

  Hardware |            manufacturer: Cinterion
...
           |            h/w revision: Thales Snapdragon X55

This is an incorrect value returned by the MBIM interface. The MV31 and MV32
does have a dedicated AT Command to get the correct hardware revision
via 'AT+SKUID'. If the hardware revision is read via the AT command, the
output looks as follows.

  Hardware |            manufacturer: Cinterion
...
           |            h/w revision: V065

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-07-30 12:41:22 -05:00
Florian Eckert a107de32a8 cinterion: add revision read via AT for the MV31 and MV32
Reading the revsion via the mbim interface returns an incorrect firmware
revsion string. This contains a '\n' character so that the revision looks
like this in 'mmcli'.

Hardware  |            manufacturer: Cinterion
          |            model: Cinterion PID 0x00F1 USB Mobile Broadband
          |            firmware revision: FDE.F0.3.0.1.1.DT.005
          |            062
          |            carrier config: DT

The correct string without '\n' is returned via the AT interface. To fix
the error, the 'mbim' revision interface is overwritten with an AT call
if a MV31 or a MV32 is detected. So we get the correct output via 'mmcli'.

Hardware  |            manufacturer: Cinterion
          |            model: Cinterion PID 0x00F1 USB Mobile Broadband
          |            firmware revision: FDE.F0.3.0.1.1.DT.005.062
          |            carrier config: DT

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-07-30 12:41:22 -05:00
Florian Eckert ebebce6111 cinterion: add MV31 to the rules file
Add the missing udev rules for the MV31 from 'Telit' which uses the
cinterion plugin.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-07-30 12:41:22 -05:00
Florian Eckert f4a1c0fcec cinterion: add MV32 to the rules file
Add the missing udev rules for the MV32 from 'Telit' which uses the
cinterion plugin.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-07-30 12:41:22 -05:00
Dan Williams 70ad037146 Merge request !1386 from 'feat/access-to-signal-threshold'
polkit,conf: give access to Signal.SetupThresholds() the same way as for Signal.Setup()

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1386
2025-07-30 12:18:11 -05:00
Andrey Skvortsov 07aca09af2 polkit,conf: give access to Signal.SetupThresholds() the same way as for Signal.Setup()
Otherwise only Setup() method for suboptimal polling is available to
non-privileged users.

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-07-30 12:15:53 -05:00
Dan Williams 41133db361 Merge request !1388 from 'fix/cell-info-docs'
libmm-glib,cell-info: fix documentation for some functions

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1388
2025-07-30 11:29:16 -05:00
Andrey Skvortsov f0a9aba63b libmm-glib,cell-info: fix documentation for some functions
Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-07-30 11:25:07 -05:00
Dan Williams ddea6c02d5 Merge request !1387 from 'fix/typos'
cli,signal: fix typo in debug message for async operations

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1387
2025-07-30 11:23:43 -05:00
Andrey Skvortsov 7ff47d795c cli,signal: fix typo in debug message for async operations
Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
2025-07-30 17:28:45 +03:00
Dan Williams d69dd96174 Merge request !1378 from 'suspend-bearer-timeout'
base-manager: increase suspend timeout for each active bearer

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1378
2025-07-28 09:20:50 -05:00
Dan Williams 01208cc6c0 base-manager: increase suspend timeout for each active bearer
Some modems can take a very long time (~20s) to reply to bearer
disconnect requests especially in marginal signal situations where
the modem must resend messages to the network after internal
timeouts. Give the modem a chance to suspend successfully if
there are active bearers.

Related: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1311#note_2938638

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-07-21 15:12:01 -05:00
Dan Williams 11489152d8 sleep-context: add ability to increase timeout
Track when the timeout was started, so that if it needs to be increased
we can calculate how long the new timeout should be. Then cancel the
original timeout and start a new one with.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-07-21 15:11:16 -05:00
Dan Williams f7897daeb5 broadband-modem,iface-modem: move bearer counting to interface and generalize
Allow counting more kinds of bearers than just multiplexed ones.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-07-21 15:11:16 -05:00
Dan Williams 6c75cbcf74 Merge request !1377 from 'dp/eutran-106-support'
add support for eutran band 106

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1377
2025-07-11 01:09:42 -05:00
Daniele Palmas 0e1ba4c530 modem-helpers-qmi: support EUTRAN bands 85 and 106
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-07-09 10:41:43 +02:00
Daniele Palmas 7fefddab05 libmm-glib,helpers: extend EUTRAN bands to 85 and 106
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-07-09 10:41:43 +02:00
Daniele Palmas b1d5006953 api,enums: add EUTRAN 106 band
Add EUTRAN 106 band with an offset of 1000 since the current numbering
scheme overlaps with MM_MODEM_BAND_CDMA_*.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-07-09 10:41:35 +02:00
Daniele Palmas c070b9015e test,modem-helpers-qmi: add unit tests for bands
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-07-09 10:33:26 +02:00
Dan Williams 0ef7bf3fdb Merge request !1350 from 'local_br'
plugin,mtk: remove the relevant log prints of the device model.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1350
2025-07-04 12:18:31 -05:00
Vanillan Wang 91adec212d plugin,mtk: remove the relevant log prints of the device model.
Rolling devices use mtk plugin, but there are some "FM350" log prints,
which is not appropriate.

Signed-off-by: Vanillan Wang <vanillanwang@163.com>
2025-07-04 12:15:29 -05:00
Dan Williams 1861ae1411 Merge request !1376 from 'main'
broadband-modem: exit with error if enable() is called in enabling state

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1376
2025-07-01 22:41:59 -05:00
Rukun Mao ca4334de94 broadband-modem: exit with error if enable() is called in enabling state
We should not assert. We can error out the latest enabling attempt and let
the previous enabling gracefully reach an end.

Issue log:
"2025-06-22T21:56:52.972448Z NOTICE ModemManager[1842]: <msg> [modem2] state changed (disabled -> enabling)
...
2025-06-22T21:57:53.146572Z ERR ModemManager[1842]: <err> [modem2] port cdc-wdm0 timed out 10 consecutive times, marking modem as invalid
...
2025-06-22T21:57:53.185751Z INFO shill[870]: INFO shill: [modem_info.cc(120)] RemoveModem: /org/freedesktop/ModemManager1/Modem/2
2025-06-22T21:57:53.187595Z INFO ModemManager[1842]: <inf> [modem2] processing user request to enable modem...
"

which led to a crash:
"
0x00007c474ceb979f (libc.so.6 -pthread_kill.c:44)               ??__pthread_kill_implementation
0x00007c474ce6d92c (libc.so.6 -raise.c:26)                      ??raise
0x00007c474ce584aa (libc.so.6 -abort.c:79)                      ??abort
0x00007c474d72b269 (libglib-2.0.so.0 -gtestutils.c:3450)        ??g_assertion_message
0x00007c474d72b2e3 (libglib-2.0.so.0 -gtestutils.c:3476)        ??g_assertion_message_expr
0x00005979074b4b6a (ModemManager -mm-broadband-modem.c)         enable
0x00005979074e3b9c (ModemManager -mm-iface-modem.c:2340)        handle_enable_auth_ready
0x00007c474d591997 (libgio-2.0.so.0 -gtask.c:1309)              g_task_return_now
0x00007c474d590555 (libgio-2.0.so.0 -gtask.c:1378)              g_task_return
0x00005979074a57bd (ModemManager -mm-base-modem.c:2011)         lock_after_authorize_ready
0x00007c474d591997 (libgio-2.0.so.0 -gtask.c:1309)              g_task_return_now
0x00007c474d590555 (libgio-2.0.so.0 -gtask.c:1378)              g_task_return
0x00005979074a3fa8 (ModemManager -mm-base-modem.c:1841)         base_modem_operation_run
...
"

Signed-off-by: Rukun Mao <rmao@google.com>
2025-06-26 20:24:16 +00:00
Dan Williams 2529159cee Merge request !1374 from 'cinterion-add-tdd-lte-bands-disabled-flag'
cinterion: add tdd_lte_bands_disabled flag

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1374

Closes #977
2025-06-25 08:17:22 -05:00
Kirill Buksha e8d781ae0b cinterion: allow missing LTE-TDD bands in SCFG response
Some modems (at least ELS62-E) doesn't support TDD LTE bands and their SCFG
responses doesn't contain LTE-TDD bands.

Signed-off-by: Kirill Buksha <kirbuk200@gmail.com>
2025-06-25 07:55:40 -05:00
Aleksander Morgado 9d11ff4ba9 Merge request !1375 from 'aleksander/fibocom-urcs'
iface-modem: ignore SIM events during a controlled SIM slot switch

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1375
2025-06-25 00:33:29 +02:00
Aleksander Morgado a24b60e52e fibocom: setup several +SIM URCs as hotplug event indications
Treat the following URCs as indications of possible SIM hot swap
events:
  +SIM: Inserted
  +SIM: Removed
  +SIM DROP

Any time any of these is received, a SIM hot swap event is reported,
and the logic can then determine what to do. These should lead to
doing nothing if they happen as part of a controlled SIM slot switch.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2025-06-18 22:10:54 +00:00
Aleksander Morgado 7d4784ed28 iface-modem: ignore SIM events during a controlled SIM slot switch
If there is an ongoing SIM slot switch, we must ignore all SIM hotswap
related events happening during the process. The flag that is set in
the Modem interface private info to track this is never reset back to
FALSE on a successful SIM slot switch, it will be set for as long as
the modem object exists.

After the successful SIM slot switch, a new modem reprobe will be
requested, which leads to the old modem object to be disposed (the one
that had the flag set) and a new modem object created.

The logic that already existed in the MBIM modem object is now
generalized in the Modem interface itself so that SIM events reported
via other protocols are also properly ignored.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
2025-06-18 22:10:54 +00:00
Dan Williams 0b2d7d6388 Merge request !1362 from 'disable-unsolicited-3gpp-events'
Disable unsolicited 3gpp events

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1362
2025-06-16 08:45:50 -05:00
biemster c30052ffc9 iface-modem: disable unsolicited 3GPP events during quick suspend/resume
This introduces the "terse" mode during quick suspend/resume, right now
it is used by 3GPP interface to disable unsolicited events, but in
future it can be used by other interfaces as well.

This prevents device to wake-up from suspend for each unsolicited while
still allowing to wake up on calls or SMS messages.

Signed-off-by: biemster <biemster@gmail.com>
Signed-off-by: Bhushan Shah <bshah@kde.org>
2025-06-16 08:34:57 -05:00
Dan Williams 45d817c50f Merge request !1370 from 'base-manager-shutdown-cleanup'
base-manager: rename manager/device shutdown to manager/device cleanup

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1370
2025-06-16 08:34:33 -05:00
Dan Williams 7029cdba3e base-manager: rename manager/device shutdown to manager/device cleanup
In preparation for a "terse" mode, but also because "shutdown" was
kind of weird since we're not always shutting the modem down; sometimes
we're just putting it in low-power mode.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-06-16 08:30:30 -05:00
Dan Williams 04c5c1c31f Merge request !1373 from 'asan-ci'
Fix some leaks and run daemon asan check in CI

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1373
2025-06-14 16:16:16 -05:00
Guido Günther c21191b59a ci: Use dependencies
This allows the build job to start without waiting for
the dco check

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Guido Günther e97bd6d407 ci: Run daemon tests under ASAN
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Guido Günther aa9447c833 tests: Allow to run some tests under asan
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Guido Günther 04229ca146 modem-helpers: Don't leak in tests
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Guido Günther fc762626ab modem-helpers: Don't leak str when parsing cscb response
We currently overwrite the value without freeing it.

Fixes: d8135be6e ("modem-helpers: Add helpers to parse channel lists")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Guido Günther 8553dc3623 modem-helpers: Don't leak strings when parsing DTMF response
`g_ptr_array_new()` creates an array without a free func,
this means we'd leak the strings when the reference count
drops to 0.

Fixes: 56fe8e7d3 ("modem-helpers: add utility function to split DTMF runs")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 16:10:05 -05:00
Dan Williams 38417c6520 Merge request !1280 from 'intel-rpc-xmm7360'
intel: XMM7360: unlocking/enabling RPC timeout fix and location support

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1280
2025-06-14 16:09:43 -05:00
Maciej S. Szmigiero 0d29f6dfa5 intel: XMM7360: Allow re-trying the first RPC init command command once
It seems that the very first XMM7360 RPC init command often times out after
resuming the laptop from s2idle for unknown reasons.
This makes the modem unusable in such situation until the next sleep/resume
cycle.

Re-trying this RPC command allows the modem to initialize normally.

It's possible that this is a kernel iosm driver or modem firmware issue
but considering that the kernel driver seems orphaned by Intel and one
can't really expect much firmware support for this modem either let's do
the easiest thing and simply allow retrying (once) the very first RPC init
command if it fails or times out.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero 4c319181e2 shared-xmm: Properly stop GPS if it was running on modem init
With the recent addition of serial port scheduler it often happens that
NMEA traces are mistaken for command responses at init time if GPS was left
enabled in the modem.

For this reason, the proper NMEA packet parser needs to be enabled early
at modem init before the code ensures that GPS is stopped (if it is not
supposed to be running of course).

Since this modem disables GPS asynchronously with processing of the
+XLSRSTOP AT command the full GPS stop machinery has be used to reliably
achieve that GPS engine stop.

It's also important to flush the existing serial port data after attaching
the NMEA packet parser but before issuing that stop AT command, otherwise
command processor for the stop command can also be confused by the existing
queued data.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero adb6dc9b44 port-serial: add flush operation
Add a serial port flush operation which can be used to discard either
serial port data received but not read, or serial port written but not
transmitted, or both types of data.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero 0787d04a39 intel: XMM7360: Better NMEA packets parsing
XMM7360 modem NMEA trace packets are wrapped to look like AT command
responses (with "<CR><LF><CR><LF>OK<CR><LF>" at the end).
This wrapping causes problems if a genuine AT command was just sent and
ModemManager is expecting a similarly formatted response to it.

In such case the NMEA trace packet is taken as the response to the AT
command, which usually causes the command to fail due to response parsing
failure.

Fix this by implementing a custom NMEA trace packets parser for these
modems.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero 6c4b90de79 intel: XMM7360: Print raw serial port data when it is actually sent/dispatched
With serial port interlocking just queuing serial port data does not mean
it will be immediately sent - the other serial port could be still busy.

For debugging serial port issues it is often necessary to see the exact
moment the data was sent or received.

Implement debug_log method for MMPortSerialXmmrpcXmm7360 and log raw serial
port data there (just as MMPortSerialAt does) instead of doing this in the
command queuing function.
The debug_log method is called by MMPortSerial base when the data is about
to be actually sent to the serial port.

Additionally, log command response body where it is actually returned to
higher layers rather than in the unsolicited response handler.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero 912e857831 shared-xmm: keep GPS port open if GPS is enabled
We need to keep GPS port open if would not be kept open otherwise (like
it is the case with a locked/non-enabled modem).

Otherwise:
* While GPS can be enabled in that modem state the traces don't reach MM
API consumers since nothing is servicing the serial port.

* Once modem actually gets enabled the queued GPS output in the modem
serial port floods the main port and often confuses the init sequence.

We also have to make sure that we don't stop GPS during the init sequence
if it is supposed to be running, otherwise there will be the same
issue as commit d3a2aebf16 ("mbm: don't stop GPS interface on
reinitialization if it should be running") fixed for mbm.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero a83a9bf437 intel: XMM7360: Re-enable location interface
Seems to work just fine once the port interlocking is being done
and some other fixes are made in the next commit.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero 5059b812fc intel: XMM7360: RPC and AT port interlocking
We have to avoid sending RPC and AT commands at the same time (even thought
they are sent via different serial ports) since apparently this modems does
not like it.

It also looks like this modem does not like to receive a RPC command soon
after an AT one, since such RPC commands sometimes fail to generate any
response.

Prevent this problem by delaying a RPC command if there was an AT command
completed recently.

The sufficient time gap was determined experimentally, but 300 ms seems to
be enough.

RPC commands are relatively rare so this should not be a performance issue.
Otherwise we often never get any response to RPC calls if AT command
happens to be sent at the same time.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero df9f2d0de5 intel: XMM7360: Make compatible with recent binding changes
Commit ec5104c9a8 ("Move log parent and connection property binding
to helper") made it obligatory for MM_TYPE_BASE_BEARER and MM_TYPE_BASE_SIM
derived classes to specify MM_BIND_TO property, but recently merged XMM7360
support wasn't converted before being merged.

This caused XMM7360 to fail to set-up SIM D-Bus object and mmcli to throw
assertions when trying to access that non-existing SIM object.

Add the missing XMM7360 MM_BIND_TO properties.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Maciej S. Szmigiero f9146378b8 .gitignore: ignore clangd cache directory
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-06-14 16:02:23 -05:00
Dan Williams 93a63c85ea Merge request !1368 from 'simtech-audio-format-dbus'
Fix setting call audio format and add Simtech audio properties support

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1368

Closes #996
2025-06-14 15:51:50 -05:00
Dan Williams ad23d5f22c simtech: report call audio properties if audio settings are supported
Suggested by David Timber.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/996

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-06-14 15:39:43 -05:00
Dan Williams 5d663976ea voice: fix setting call audio format
MM should be updating the call audio format and port on ongoing/active
calls, not terminated ones.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-06-14 15:39:43 -05:00
Dan Williams e55dde034b Merge request !1372 from '32bit'
Fix 32bit format specifiers and don't run tests on free'd cbm part

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1372
2025-06-14 15:31:19 -05:00
Guido Günther 5ecf00aaf0 cbm: Don't leak cbm-part in tests
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 15:27:08 -05:00
Guido Günther c89266facb cbm: Don't check language past free
Fixes: 3559f606d ("cbm-part: Fix parsing of language encodings")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 15:27:08 -05:00
Guido Günther 061bc1ff2d intel: Use correct format specifier
The arguments are `gsize` and otherwise emit warnings on e.g. i386

Fixes 4cae04064 ("intel: implement support for RPC-powered xmm7360")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-14 15:27:08 -05:00
Dan Williams 1bc3db766b Merge request !1369 from 'main'
foxconn: add subsystem ID support for T99W696

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1369
2025-06-14 15:26:43 -05:00
Slark Xiao 41f82a4d33 dell: update the foxconn mbim interface
Keep the mm_broadband_modem_mbim_foxconn_new() align with the
new changes in src/plugins/foxconn.

Signed-off-by: Slark Xiao <slark_xiao@163.com>
2025-06-14 15:23:33 -05:00
Slark Xiao bf5458acdd foxconn: add subsystem ID support for T99W696
T99W696 is the first Foxconn PCIE modem whick uses Qualcomm's VID/
PID. Driver ref: https://lore.kernel.org/mhi/20250528092232.16111-1-slark_xiao@163.com

This changes include 2 parts:
i:  Add device for foxconn plugin
ii: Show SSVID/SSPID for parameter "--firmware-status". This helps
    the fwupd get the right firmware upgrade method.

Signed-off-by: Slark Xiao <slark_xiao@163.com>
2025-06-14 15:23:33 -05:00
Guido Günther 8486641f92 Merge request !1371 from 'rel-1.25.1'
build: Bump minimum libqmi dependency and release 1.25.1

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1371
2025-06-04 09:26:37 +00:00
Guido Günther e88e481ca3 build: Bump version to 1.25.1
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-04 10:01:08 +02:00
Guido Günther 32f7e3ec09 build: Bump minimum libqmi dependency to 1.37.1
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-06-04 10:01:08 +02:00
Dan Williams cf7d037ed3 Merge request !1366 from 'mr/20250530-timeout'
mm-port-serial: add new MM_SERIAL_ERROR_SEND_TIMEOUT

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1366
2025-06-02 08:46:40 -05:00
Florian Eckert 6a2cb8dd8e mm-port-probe-at: also check for MM_SERIAL_ERROR_SEND_TIMEOUT
Check here for the new error 'MM_SERIAL_ERROR_SEND_TIMEOUT'.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-06-02 08:43:45 -05:00
Florian Eckert 44b9f74301 mm-port-serial: add new MM_SERIAL_ERROR_SEND_TIMEOUT
This new error code 'MM_SERIAL_ERROR_SEND_TIMEOUT' is used to make it easier
to distinguish why the transmission failed. Until now,
'MM_SERIAL_ERROR_SEND_FAILED' was always returned. This new error code is now
returned for an 'EAGAIN', as this is more likely to be a TIMEOUT.

This makes debugging easier, as a better error analysis is now possible.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-06-02 08:43:45 -05:00
Dan Williams 37f17d4b58 Merge request !1336 from 'dtmf-serialize'
Serialize DTMF requests and allow setting DTMF duration at call creation time

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1336

Closes #970
2025-05-30 18:54:05 -05:00
Dan Williams dad2d49b69 tests: test call DTMF functionality
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 08:06:11 -05:00
Dan Williams ae3d37030a base-call: handle multiple DTMF characters
Send each character through the state machine one at a time. Some
modems (various Quectel ones for example) can process multiple at
the same time, and while that should be easily implemented using
the new changes to send_dtmf() it's not done in any plugin yet.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 08:02:48 -05:00
Dan Williams 56fe8e7d31 modem-helpers: add utility function to split DTMF runs
Split into groups of non-pause characters and single pause characters
by themselves and return as an array of strings.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 08:02:47 -05:00
Dan Williams 957a141e57 base-call: interpret DTMF character ',' as two-second pause
Do what other dialers do and interpret ',' as a short pause, which
helps handle automated menus.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:59:59 -05:00
Dan Williams 2726f8e8a2 base-call: convert DTMF tone handling to a state machine
Generalize the timeout/stop logic that QMI requires into the
base call. We'll use this to implement the pause character (,)
generically.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:59:59 -05:00
Dan Williams 5448a85a2b call: allow setting DTMF tone duration at call creation time
Instead of hard-coding a 500ms DTMF tone duration, let applications
use a specific duration at call setup time.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:59:58 -05:00
Dan Williams 28b1954654 call-list: remove unused modem property
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:57:50 -05:00
Dan Williams b9c49c7b4d base-call: remove usage of MMBaseModem
Split out the things we actually use from MMBaseModem into
separate properties that can be independently implemented
(or just left NULL) for unit tests.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:57:50 -05:00
Dan Williams 8392f30388 base-call: split AT-specific call code into MMCallAt
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-30 07:57:50 -05:00
Dan Williams 3ed7f37876 Merge request !1290 from 'port-scheduler'
port-serial: add command scheduler infrastructure and use it

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1290
2025-05-23 18:58:30 -05:00
Maciej S. Szmigiero 7d410387cf port-scheduler: implement LOG_OBJECT interface and add scheduler logging
Otherwise log functions crash.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-05-23 18:46:53 -05:00
Dan Williams a769bbed6d port-serial: add serial port command scheduler
Add an interface and implementation for a port scheduler that round-
robins between ports the scheduler is attached to, serializing command
execution among one or more MMPortSerial instances.

Theory of operation:

Sources (e.g. MMPort subclasses) register themselves with the scheduler.

Each source notifies the scheduler whenever its command queue depth changes,
for example when new commands are submitted, when commands are completed,
or when commands are canceled.

The scheduler will round-robin between all sources with pending commands,
sleeping when there are no pending commands from any source.

For each source with a pending command the scheduler will emit the
'send-command' signal with that source's ID. The given source should
send the next command in its queue to the modem.

When that command is finished (either successfully or with an error/timeout)
the source must call mm_port_scheduler_notify_command_done() to notify the
scheduler that it may advance to the next source with a pending command, if
any. If the 'send-command' signal and the notify_command_done() call are not
balanced the scheduler may stall.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-23 18:46:53 -05:00
Dan Williams b24615d801 log-object: don't construct log ID with NULL self_id
If the object has an owner ID already but doesn't yet have enough
information to build its log ID, don't cache a less-than-useful
log ID string for it.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-23 18:46:32 -05:00
Maciej S. Szmigiero 42ead88266 log-object: Add possibility to reset logger id
Logger id (the one generated from build_id interface method and owner_id
property) is generated and cached the first time it is required, further
uses just return the cached value.

Add a cache reset method so if the interface implementer knows that its
logger id could have changed it could force its re-generation.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-05-23 18:46:32 -05:00
Dan Williams 39f4cf77f2 Merge request !1361 from 'cbm-lang'
Parse CBM's language when available and export it on DBus

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1361
2025-05-23 14:22:50 -05:00
Guido Günther 87aaebcec0 cli/cbm: Show CBMs language when available
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 68d241b5aa mmcbmmonitor: Print language when available
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 9625c81d39 mm-glib/cbm: Allow to get language
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 95d65ecd8d base-cbm: Export the lang property on DBus
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 0bd0cad705 cbm-part: Handle additional coding schemes and parse languages
We store the language as iso639 as this is what the what TS 23.038
references.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 3559f606d2 cbm-part: Fix parsing of language encodings
According to TS 23.038 the language is stored at the beginning of the
information page not in the "header".

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther cdc6bf9529 cbm-part: Use automatic cleanup
Safer than freeing the the struct in multiple places

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 857efa1fba polkit,conf: Add missing Cell Broadcast SetChannel method
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Guido Günther 5a3b810bc9 polkit,conf: Add missing Cell Broadcast methods
Fixes 62f7b76e8 ("cbm: Add CellBroadcast interface")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-23 14:15:14 -05:00
Dan Williams 9cc5582bf2 Merge request !1355 from 'mtk-unlock-required'
mtk-legacy: read IMSI if CPIN response is an error

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1355

Closes #980
2025-05-23 14:11:58 -05:00
Dan Williams 5c1fcbfe4a mtk-legacy: read IMSI if CPIN response is an error
Some older MTK-based phones (Tecno T528 NEW) reply to +CPIN with
an error but are (obviously) unlocked, otherwise they wouldn't
be able to boot up to the point of talking to a computer. Since
they are actually unlocked they will happily give out the IMSI
even if +CPIN errors.

To work around the +CPIN issue treat the device as unlocked if we
can successfully read the IMSI.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/980

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-23 08:31:04 -05:00
Dan Williams 757df26b29 broadband-modem,modem-helpers: move +CPIN response parsing to modem helpers
Unit test it better, plus remove code duplication in various plugins.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-23 08:31:04 -05:00
Dan Williams c5a2cd3157 Merge request !1364 from 'cbs-policy'
pollkit,cell-broadcast: Use more specific error message

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1364
2025-05-22 19:12:07 -05:00
Guido Günther 3d3182534e pollkit,cell-broadcast: Use more specific error message
Text messages could also be SMS

Fixes 1fb74f266 ("data: Add a policy rule to access the cellbroadcast API")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-22 23:17:47 +02:00
Dan Williams 1192f49868 Merge request !1363 from 'pr/20250521-mbim-qdu'
broadband-modem-mbim: add qdu firmware update check

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1363
2025-05-22 09:10:42 -05:00
Florian Eckert d058dd0775 broadband-modem-mbim: add qdu firmware update check
The manufacturers can offer a firmware update file 'ota.bin' with which
the firmware can be updated in the modem via a manufacturer tool using
windows. The tool is only available for Windows and can therefore not be used
for embedded devices.

A investigation has shown that this tool updates the firmware via 'mbim-qdu'.
The update service 'fwupd' which has a 'modemmanager' plugin can install the
firmware via 'mbim-qdu'. For this to work, the ModemManager must export this
update method via the firmware interface.

As the 'mbim-qdu' is a generic update method, the check is integrated into the
'mm-broadband-modem-mbim' class. If 'mbim-qdu' update method is supported by
the mbim interface and the udev env variable 'ID_MM_MBIM_QDU' is set for this
modem, then the 'mbim-qdu' update is exported via dbus.

The following line must be added to the '77-mm-cinterion-port-types.rules'
udev rules file, for example, so that the mbim-qdu update for the 'MV31' can
be used.

ATTRS{vendor}=="0x1e2d", ATTRS{device}=="0x00b3", ENV{ID_MM_MBIM_QDU}="1"

This is the corresponding output of the 'mmcli' command to show the supported
update method for the 'MV31'.

root@G3-10940 ~ # mmcli -m Modem1 --firmware-status
  Firmware |     method: mbim-qdu
           | device ids: USB\VID_1E2D&PID_00B3&REV_0414&CARRIER_GCF
           |             USB\VID_1E2D&PID_00B3&REV_0414
           |             USB\VID_1E2D&PID_00B3
           |             USB\VID_1E2D
           |    version: T99W175.F0.1.0.0.9.GC.004.063 - 0A000804

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2025-05-22 09:04:40 -05:00
Dan Williams 680aed6acf Merge request !1044 from 'submodule'
Allow to use libqmi and libmbim as meson subprojects

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1044
2025-05-22 08:28:51 -05:00
Guido Günther c04f178dda build: Allow to use libqmi as subproject
This makes it simpler to build ModemManager git

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-22 08:20:19 -05:00
Guido Günther 9cb5a2d090 build: Allow to use libmbim as subproject
This makes it simpler to build ModemManager git

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-22 08:20:19 -05:00
Dan Williams c6d1d020f7 Merge request !1360 from 'bind-to-vs-cbm-crash'
base-cbm: Install properties one by one

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1360
2025-05-22 08:16:58 -05:00
Guido Günther 382c3e114c base-cbm: Install properties one by one
`g_object_class_install_property` picks up `PROP_BIND_TO` resulting in a
crash on the first CBM received.

Fixes: ec5104c9a ("Move log parent and connection property binding to helper")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-22 08:09:56 -05:00
Dan Williams 7ae153880c Merge request !1356 from 'sierra-call-urc-fix'
serial-parsers: don't echo-remove strange call start/end URCs

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1356
2025-05-22 08:09:41 -05:00
Dan Williams c3c6fdc55e serial-parsers: don't echo-remove strange call start/end URCs
Some Sierra devices omit the leading <CR> from call start/end URCs
like NO CARRIER and CONNECT, which caused the echo-removal code to
remove from the response buffer because the leading <CR><LF> did
not exist. That can break call control and hangup handling on
those devices.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-22 08:05:58 -05:00
Dan Williams 24f9309d6e serial-parsers,port-serial-at: move echo removal into serial parser
Mainly because we need somewhere to stash the call end regex, and
it's silly to have a 3rd instance of that in MMPortSerialAt when
we already have one in the serial parsers that MMPortSerialAt
relies on pretty heavily.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-22 08:05:58 -05:00
Dan Williams 7f014add61 broadband-modem,modem-helpers: generalize call end regex creation
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-22 08:05:58 -05:00
Dan Williams 41ceaf6d5e Merge request !1359 from 'cpms-spaces'
modem-helpers: handle spaces in +CPMS query response

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1359

Closes #990
2025-05-22 08:05:28 -05:00
Dan Williams 5888949fa3 modem-helpers: handle spaces in +CPMS query response
Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/990

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-20 09:56:49 -05:00
Dan Williams 847ce9ada5 Merge request !1358 from 'qmi-cbm-fixes'
broadband-modem-qmi: Cellbroadcast channel reading fixes

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1358
2025-05-20 09:18:30 -05:00
Guido Günther 0ccc3fbeec broadband-modem-qmi/cellbroadcast: Allow for G_MAXUINT16
It's a valid channel value. Since start and end are guint16 we can drop
the check altogether.

Fixes: e25dd7db9 ("broadband-modem-qmi: Add support for loading channels")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-20 13:51:54 +02:00
Guido Günther f17430b662 broadband-modem-qmi/cellbroadcast: Return on failure
Return after setting the error

Fixes: e25dd7db9 ("broadband-modem-qmi: Add support for loading channels")

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-20 10:39:15 +02:00
Dan Williams ba8633e48a Merge request !1354 from 'dp/le910q-ecm-upstream'
Add ECM support for Telit LE910Q1

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1354
2025-05-19 09:05:00 -05:00
Daniele Palmas 6a4fdbba42 telit: add ECM bearer for LE910Q1/ELS63-I
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-05-19 08:59:00 -05:00
Daniele Palmas e3acdd8743 broadband-modem-telit: use +COPS to get AcT for LE910Q1/ELS63-I
Use +COPS to retrieve AcT for LE910Q1/ELS63-I since they do not
support #PSNT and +SERVICE.

Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-05-19 08:59:00 -05:00
Daniele Palmas e74a563f87 telit: add port hints for LE910Q1/ELS63-I
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-05-19 08:59:00 -05:00
Daniele Palmas 4da9a26d54 modem-helpers: remove unused variable in mm_3gpp_parse_cmer_test_response
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-05-19 08:59:00 -05:00
Daniele Palmas b0589932d7 broadband-modem: support +CGEREP values different than 2
Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
2025-05-19 08:59:00 -05:00
Dan Williams ec218e7052 Merge request !1346 from 'disconnect-request'
bearer: add new "disconnect-request" logic

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1346
2025-05-16 09:52:04 -05:00
Dominique Martinet 0780526594 base-bearer: set dbus disconnect_request on ignored disconnection
When we get a disconnect event that we wanted to ignore, set the
DisconnectRequest property instead so clients on dbus can act on it.

Also upgrade the logs from dbg to msg (info) as there would be otherwise
no message indicating the disconnect request if it is not acted on.

This was checked with dbus-monitor:
```
$ dbus-monitor  --system "type='signal',sender='org.freedesktop.ModemManager1'"
signal time=1747362238.227804 sender=:1.73798 -> destination=(null destination) serial=741 path=/org/freedesktop/ModemManager1/Bearer/0; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.freedesktop.ModemManager1.Bearer"
   array [
      dict entry(
         string "DisconnectRequest"
         variant             boolean true
      )
   ]
   array [
   ]
```

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2025-05-16 22:06:24 +09:00
Dominique Martinet dea8f27464 api,bearer: new 'DisconnectRequest' property
To report that the bearer has been killed from the modem side and
the connection should be terminated.

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2025-05-16 22:06:24 +09:00
Dominique Martinet 2d29832f89 dispatcher-connection: add new 'disconnect-request' event
When bearer gets an event that should trigger a disconnection but we
cannot disconnect (for example because we're waiting for pppd to close),
we now trigger a new 'disconnect-request' event instead

This was tested with the following hook:
```
$ cat /etc/ModemManager/connection.d/handle-disconnect-request.sh
#!/bin/sh

if [ "$4" != disconnect-request ]; then
	exit 0
fi

iface=$(mmcli -b "$2" -K | awk '/bearer.status.interface/ { print $3 }')

if pkill -f "pppd\>.*\<$iface\>"; then
	logger -t mm-disconnect-request "Killed $iface pppd"
else
	logger -t mm-disconnect-request "No pppd found for $iface"
fi
```

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2025-05-16 22:06:10 +09:00
Dominique Martinet f3aaa113e0 dispatcher-connection: replace 'connected' boolean with a new enum
The next commit will introduce a new dispatcher event.
This commit should not change anything user-facing

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
2025-05-16 15:34:02 +09:00
Dan Williams a4421095f8 Merge request !1353 from 'fix-creg-regex'
modem-helpers: support multi-digit "stat" values in CREG response

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1353

Closes #987
2025-05-14 15:43:04 -05:00
Kirill Buksha 02131bf3bb modem-helpers: fix method for distinguishing lac and stat values
Stat value may be multidigit e.g. 10 or 11.

Signed-off-by: Kirill Buksha <kirbuk200@gmail.com>
2025-05-14 13:54:47 +02:00
Kirill Buksha e5c4cbc79a tests,modem-helpers: add cases for multidigit "stat" value in CREG response
Signed-off-by: Kirill Buksha <kirbuk200@gmail.com>
2025-05-14 13:21:01 +02:00
Kirill Buksha 51b14b8ef8 modem-helpers: support multi-digit "stat" values in CREG response
The 'stat' field in CREG responce may contain multi-digit numbers, such as "10"
meaning "registered for "CSFB not preferred", roaming". Furtermore, some modems
use value "11" to indicate that only emergency services are available.

Signed-off-by: Kirill Buksha <kirbuk200@gmail.com>
2025-05-14 12:45:45 +02:00
Dan Williams bee6bce2fa Merge request !1352 from 'base-sim-auth-fix'
base-sim: Setup auth provider and its cancellable

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1352
2025-05-11 16:21:30 -05:00
Maciej S. Szmigiero 2c66b5ee16 base-sim: Setup auth provider and its cancellable
Otherwise we'll get a NULL pointer dereference segfault in mm_auth when
sending SIM PIN.

Looks like MMBaseSim was accidentally missed during the conversion done
by the commit in the Fixes tag below.

Fixes: ef5cee3ab5 ("auth-provider: move auth provider logic into each class")
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
2025-05-11 16:16:45 -05:00
Dan Williams c99c300ad5 Merge request !1235 from 'intel-rpc-xmm7360'
intel: implement support for RPC-powered xmm7360

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1235
2025-05-09 21:34:26 -05:00
Thomas Vogt 4cae040645 intel: implement support for RPC-powered xmm7360
Signed-off-by: Thomas Vogt <acc-github@tovotu.de>
2025-05-09 07:31:31 +02:00
Dan Williams d165d61a95 Merge request !1266 from 'v6-cgcontrdp'
modem-helpers: add IPv6 support to +CGCONTRDP parsing

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1266
2025-05-08 20:45:37 -05:00
Dan Williams d4c0bbc839 modem-helpers: add IPv6 support to +CGCONTRDP parsing
Add some test responses from the Quectel EG915Q and some other Quectel devices.
Then try to parse those responses.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:37:09 -05:00
Dan Williams 4bb6026e37 Merge request !1341 from 'mbim-multipart-fix'
sms: always use SMS_PART_INVALID_INDEX unstored parts

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1341

Closes #979
2025-05-08 20:36:44 -05:00
Dan Williams 1d5cc0addb broadband-modem-qmi,broadband-modem-mbim: always use SMS_PART_INVALID_INDEX unstored parts
MMSmsList has logic to allow multiple unstored messages as long as
they use SMS_PART_INVALID_INDEX. These messages aren't stored so
they don't have an index.

But the MBIM and QMI modems used index 0 for unstored messages,
meaning there could only ever be one and also that multipart
messages would fail to be combined.

Let's fix that by just using SMS_PART_INVALID_INDEX for every
scenario where an unstored message comes in.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/979

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:25:22 -05:00
Dan Williams 51ff44f1f5 sms-list: remove usage of MMBaseModem
Not used for anything anymore so we can remove the property.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:38 -05:00
Dan Williams 03027b5ec2 base-sms: remove MODEM property
No longer depend on MMBaseModem since everything that specifically
uses it is now removed.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:38 -05:00
Dan Williams 97c189910b base-sms,sms-list: use signals to set multipart reference
Instead of going through the messaging interface, which just asks
the MMSmsList anyway, just go straight to the list.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:38 -05:00
Dan Williams c6af442053 base-sms: reduce possibility of leaking multipart reference
Move error paths after getting a multipart reference to before getting
one, to reduce the possiblity that we get a reference from the MMSmsList
that ultimately doesn't end up getting used.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:38 -05:00
Dan Williams 1781ffaad4 base-sms: pass supported storages in at creation time
They won't change, and this lets us get rid of one more usage of
MMIfaceModemMessaging.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 9c8ec57c24 base-sms: pass SMS default storage at creation time and update as needed
Instead of getting it from the MMIfaceModemMessaging when the
SMS is stored. This flattens dependencies between MMBaseSms and
MMIfaceModemMessaging.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams b81f23e24a base-sms,sms-list,iface-messaging: move MMBaseSms creation to MMBroadbandModem class
This commit moves creation of the MMBaseSms objects out of MMSmsList and up
into MMIfaceModemMessaging (which is already a MMBroadbandModem) and
the MMBroadbandModem subclasses themselves.

This flattens the creation of MMBaseSms objects by passing them down
from the object that creates the SMS parts, rather than having a
convoluted callback scheme relying on MMSmsList and MMBaseSms having
direct knowledge of their owning modem.

The goal is to eventually remove usage of MMBaseModem from MMBaseSms
and MMSmsList so that we can test them more easily.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 9830e3955a base-sms,sms-at: split AT-specific SMS code into MMSmsAt
Simplify MMBaseSms (making it easier to use from testcases) by
splitting the AT-specific code into MMSmsAt rather than keeping
it in the base class.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 6d0e4daf87 base-bearer: remove unused include
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 1283ee8c2a base-sms,iface-modem-messaging: move lock/unlock logic into the interface
Allows us to test things that rely on MMBaseSms more easily..

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 683a33b303 base-sms: determine 3GPP vs. CDMA at creation time
It won't ever change over the lifetime of the BaseSMS.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams 08a65a0bed sms-mbim: remove unused code
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:24:37 -05:00
Dan Williams efcc960b13 Merge request !1344 from 'cbm-remove-modem'
Begin removing usage of MMBaseModem from leaf classes

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1344
2025-05-08 20:10:48 -05:00
Dan Williams 1fa21fcc48 base-cbm,cbm-list,iface-cbm: remove usage of MMBaseModem
CBM isn't as complicated as SMS, and the CBM class itself doesn't
need to be overridden by QMI/MBIM/etc. Now that the log parent
and connection binding no longer require MMBaseModem we can flatten
the CBM object creation and remove usage of MMBaseModem.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:08:06 -05:00
Dan Williams ec5104c9a8 Move log parent and connection property binding to helper
Continues removing usage of MMBaseModem in a bunch of files
by splitting out bits of its usage to separate interfaces.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:08:06 -05:00
Dan Williams ef5cee3ab5 auth-provider: move auth provider logic into each class
Rather than make all of them rely on MMBaseModem for it. This
lets us disentangle dependencies for easier unit testing.

For interfaces, rather than casting directly to MMBaseModem
use intermediate interfaces (MMIfaceAuth and MMIfaceOpLock)
that tests can fake out.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:08:06 -05:00
Dan Williams 7262b46a82 base-modem,auth-provider: move testcase auth bypass to auth provider
The bypass when in testcase mode has nothing to do with the base modem
class; so make it generic.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 20:08:06 -05:00
Dan Williams 02942a04f9 Merge request !1314 from 'quectel-power-down'
quectel: wait for POWERED DOWN URC and decrease other power operation timeouts

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1314
2025-05-08 20:06:24 -05:00
Dan Williams 0bfb11c62c quectel: decrease low-power/power-on/reset wait times to 15 seconds
AT docs for many (most?) device state a max timeout of 15 seconds.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 19:54:54 -05:00
Dan Williams e05af7442c quectel: ensure power down operation waits for POWERED DOWN URC
AT docs for many (most?) Quectel devices state that QPOWD=1 receives
the OK response very quickly but the caller must wait for the
POWERED DOWN URC to avoid data loss. Do that.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 19:54:54 -05:00
Dan Williams bf416a7462 Merge request !1310 from 'disabled-profiles'
bearer: don't choose or activate disabled profiles

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1310
2025-05-08 19:54:43 -05:00
Dan Williams 4d2d01b2c6 broadband-bearer,modem-helpers: don't use or match disabled profiles
When matching profiles ignore disabled ones. When activating a
specific profile index, return an error if that profile is marked
as disabled.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 18:14:24 -05:00
Dan Williams 4b0d3b7147 broadband-modem-qmi: use correct profile index in error message
Instead of using the loop index, use the actual profile index
because they aren't always the same.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 18:14:24 -05:00
Dan Williams 352b8ed53d broadband-modem-qmi: implement disabled 3GPP profiles
Previously, a disabled profile would cause Profile Manager interface
enabling to fail because get_profile_settings_ready() returned an
error for disabled profiles.

But 3GPP profile objects already have support for the enable/disabled
setting, so just hook that up and stop returning an error for disabled
ones.

This allows successful initialization of the 3GPP Profile Manager
on devices that contain disabled profiles.

While we're at it, allow creating disabled profiles, and changing
profiles back and forth from enabled<->disabled.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 18:14:24 -05:00
Dan Williams 27384681a7 Merge request !1311 from 'sleep-wait'
Wait until  device operations complete before dropping suspend inhibitor

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1311

Closes #966
2025-05-08 15:43:50 -05:00
Dan Williams b13bdacf38 broadband-modem: close serial ports in dispose
We want ports to be closed as early as possible; so make sure they
are closed in dispose() which is run explicitly by MMDevice when
cleaning up and removing the modem. Otherwise they could stay
open longer than we want, causing problems for suspend/resume.

This caused problems with suspend because cancelling the
MMBaseModem's cancellable triggered an idle handler that held
a reference to the modem, preventing finalize() from running
until after the suspend code was finished, thus preventing
ports from being closed and cleaned up. Closing them in
dispose() handles this.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 15:41:10 -05:00
Dan Williams 0f97d90490 broadband-modem: remove invalid idle handler during dispose
base_modem_invalid_idle() needs to keep a reference to the
MMBaseModem until its done. But if the modem is cancelled during
removal right before we're trying to forget about it, keeping
that reference can prevent everything getting cleaned up by
MMBaseModem's dispose() until after the mainloop has run again
and all our removal operations are supposedly complete.

MMDevice uses an explicit dispose() trigger that mitigates
most of this (and requires it for other reasons, like breaking
reference cycles between the modem and it's various child
classes) but it's somewhat error-prone to keep the modem
around if we don't really need to.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-08 15:40:25 -05:00
Dan Williams 0cb1c1f157 broadband-modem-qmi,mbim: remove redundant port closes
This will just be done immediately after by MMBaseModem's
dispose() handler.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:59:51 -05:00
Dan Williams 564bdab99e base-manager: convert shutdown to steps
Make the call flow clearer.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:59:51 -05:00
Dan Williams e0c0c68688 base-manager,device: consolidate modem cancelling into mm_device_remove_modem()
Every use of mm_device_remove_modem() was already trying to cancel the
modem's canellable, so let's just put it there and simplify the callers.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:59:51 -05:00
Dan Williams f4cbca56d5 base-manager,sleep-monitor: wait for modem operations before sleeping
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:59:51 -05:00
Dan Williams 6350b0a85f base-modem: clarify port cleanup/close behavior for serial ports
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:59:25 -05:00
Dan Williams 6b25476dbb base-modem: allow port teardown operation to use callbacks if needed
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:54:13 -05:00
Dan Williams c6d1a26a93 port-serial: don't log force-closes if not really being forced close
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 22:54:13 -05:00
Dan Williams 6f942f5774 Merge request !1324 from 'nbiot-act'
modem-helpers: report C*REG=2 AcT 9 as NB-IOT access technology

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1324
2025-05-07 10:59:15 -05:00
Dan Williams 2e27b02004 modem-helpers: report C*REG=2 AcT 9 as NB-IOT access technology
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-07 09:47:47 -05:00
Dan Williams 0ed5ce1ac3 Merge request !1345 from 'reload-reg-after-manual'
broadband-modem: reload registration info after manual registration

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1345

Closes #971
2025-05-01 15:37:10 -05:00
Dan Williams febab17f07 broadband-modem: reload registration info after manual registration
This refreshes operator information after manual registration. QMI and
MBIM implementations return operator info along with registration info
so they handle this easily, while with AT-based devices we must run
additional commands to retrieve that after the manual registration has
finished.

Suggested by: Kirill Buksha <kirill.buksha@axians.rs>
Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/971

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-05-01 15:15:29 -05:00
Dan Williams 8ef4ce4d61 Merge request !1343 from 'l10n-sv'
po: Update Swedish translation

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1343
2025-05-01 15:14:55 -05:00
Anders Jonsson 6fd0ebcaa9 po: Update Swedish translation
Signed-off-by: Anders Jonsson <anders.jonsson@norsjovallen.se>
2025-04-25 10:34:53 -05:00
Dan Williams cd898f4a4d Merge request !1250 from 'probe-allowed-qcdm'
api,modem: new 'IgnoredPorts' property

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1250
2025-04-25 07:39:07 -05:00
Lukas Voegl 39a74ae6fb fibocom: allow QCDM
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2025-04-25 09:37:17 +02:00
Lukas Voegl 436081648b api,modem: new 'IgnoredPorts' property
Expose a new list of 'IgnoredPorts' via D-Bus and therefore remove the use of `MM_MODEM_PORT_TYPE_IGNORED`

Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
2025-04-25 09:37:16 +02:00
Dan Williams 39123f964b Merge request !1342 from 'mtk62xx-detect'
broadband-modem: detect old Mediatek 62xx chipsets as GSM-capable

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1342

Closes #980
2025-04-24 15:09:05 -05:00
Dan Williams 8cf25a97a1 broadband-modem: detect old Mediatek 62xx chipsets as GSM-capable
They don't necessarily reply to +WS46 but like old Motorola ESX
devices they reply to +CGMM with a known string.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/980

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-23 10:11:22 -05:00
Dan Williams 02898fed11 Merge request !1335 from 'call-polling'
iface-modem-voice: recheck call state polling when call is started

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1335
2025-04-21 16:21:28 +00:00
Dan Williams 92e666e1c9 iface-modem-voice: recheck call state polling when call is started
When an outgoing call is created and added to the call list its state
is UNKNOWN. The call list emits the ADDED signal which MMIfaceModemVoice
listens for to check whether to begin polling call state.

But since UNKNOWN is not an in-progress call state polling isn't started.
And nothing was rechecking whether to start polling when the call state
changed to something other than UNKNOWN.

Do that so that we can track call progress as it dials out and is
answered.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-21 16:17:25 +00:00
Dan Williams 19b798fa99 Merge request !1338 from 'cinterion-sxrat-assert'
modem-helpers-cinterion: allow spaces in ^SXRAT test response

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1338

Closes #974
2025-04-16 13:43:32 +00:00
Dan Williams 6b6997362b modem-helpers-cinterion: allow spaces in ^SXRAT test response
^SXRAT: (0-6), (0,2,3), (0,2,3)

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/974

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-13 19:58:30 -05:00
Dan Williams 8fc3f44e76 Merge request !1304 from 'qmi-time-interface'
broadband-modem-qmi: implement Time interface

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1304
2025-04-14 00:48:19 +00:00
Dan Williams 361e9c58c0 broadband-modem-qmi: implement Time interface
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-13 19:26:30 -05:00
Dan Williams 95496539e9 Merge request !1337 from 'fibocom-handle-no-fw-parent'
shared-fibocom: don't assume parent implements the firmware interface

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1337

Closes #975
2025-04-13 13:50:41 +00:00
Dan Williams 046b79a676 shared-fibocom: don't assume parent implements the firmware interface
MMBroadbandModemMbimMtkFibocom doesn't, so don't assert it.

Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/975

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-13 13:47:57 +00:00
Dan Williams e3d7439551 Merge request !1325 from 'cbm/qmi'
broadband-modem-qmi: Add Cell Broadcast support

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1325

Closes #935
2025-04-13 05:05:44 +00:00
Guido Günther 219e8eb103 broadband-modem-qmi: Enable Cell Broadcast
For QMI we have an extra QMI request so use that to make sure receiving
messages is actually enabled.

Closes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1325
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Guido Günther e25dd7db97 broadband-modem-qmi: Add support for loading channels
This allows to retrive the list of configured Cell Broadcast channels.

Closes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1325
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Guido Günther 1ea564f5e8 broadband-modem-qmi: Add support for setting channels
This allows to receive Cell Broadcast messages in the specified channel
range on SDM670 based devices (X12 modem) and SDM845 (X20 modem) without
any AT ports (like the OnePlus 6/6T and Google Pixel 3a).

Helps: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1325
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Guido Günther 9c5f5833e5 broadband-modem-qmi: Add initial interface bits
This allows to receive Cell Broadcast messages.

Tested with single part CBMs only as my setup currently only allows for
these.

Helps: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1325
Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Guido Günther bf8bd7c4ad ci: Build full libqmi
The basic collection is not enough for MM

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Guido Günther 3504a438c2 ci: Move variables to common-variables
This makes it a bit more obvious where the vars are available.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-04-13 05:01:32 +00:00
Dan Williams b9e9a71dc3 Merge request !1334 from 'modem-helpers-act-fix'
modem-helpers: fix checking of CDMA/EVDO access technology

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1334
2025-04-13 04:41:51 +00:00
Dan Williams 9e205f4784 modem-helpers: fix checking of CDMA/EVDO access technology
Missing ! for strncmp() meant the test was backwards and would
erroneously report 1xRTT and EVDOr0 when those access technologies
were not in use.

Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-12 23:37:00 -05:00
Dan Williams 66c3631a2f Merge request !1333 from 'fix-gtk-doc'
Fix gtk-doc build

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1333
2025-04-11 23:13:36 +00:00
Jan Alexander Steffens (heftig) 078a92cd5c docs: Fix gtk-doc build
Fix a duplicate `id` and the inclusions of gdbus docs.

Signed-off-by: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
2025-04-11 03:56:59 +02:00
Dan Williams 67a9e58f30 Merge request !1331 from 'bump-1-25-0'
build: unstable release version bump to 1.25.0

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1331
2025-04-10 01:57:38 +00:00
Dan Williams 8174be2aec build: unstable release version bump to 1.25.0
Signed-off-by: Dan Williams <dan@ioncontrol.co>
2025-04-09 20:42:06 -05:00
277 changed files with 22448 additions and 3758 deletions
+3
View File
@@ -4,3 +4,6 @@
tags tags
/.vscode /.vscode
/cscope.out /cscope.out
/.cache
subprojects/libmbim
subprojects/libqmi
+53 -10
View File
@@ -12,8 +12,8 @@ stages:
.common_variables: .common_variables:
variables: variables:
FDO_UPSTREAM_REPO: mobile-broadband/ModemManager FDO_UPSTREAM_REPO: mobile-broadband/ModemManager
FDO_DISTRIBUTION_VERSION: '20.04' FDO_DISTRIBUTION_VERSION: '22.04'
FDO_DISTRIBUTION_TAG: '2023-01-03.1' FDO_DISTRIBUTION_TAG: '2026-01-05.1'
FDO_DISTRIBUTION_PACKAGES: ca-certificates git gcc meson ninja-build gawk FDO_DISTRIBUTION_PACKAGES: ca-certificates git gcc meson ninja-build gawk
libgettextpo-dev libgirepository1.0-dev libglib2.0-dev libgettextpo-dev libgirepository1.0-dev libglib2.0-dev
libgudev-1.0-dev python3-dbus python3-gi autopoint libgudev-1.0-dev python3-dbus python3-gi autopoint
@@ -24,8 +24,11 @@ stages:
LIBQMI_BRANCH: 'main' LIBQMI_BRANCH: 'main'
LIBQRTR_BRANCH: 'main' LIBQRTR_BRANCH: 'main'
LIBMBIM_BRANCH: 'main' LIBMBIM_BRANCH: 'main'
BUILD_MBIM: true
BUILD_QMI: true
BUILD_QRTR: true
build container: build_container:
extends: extends:
- .fdo.container-build@ubuntu - .fdo.container-build@ubuntu
- .common_variables - .common_variables
@@ -36,11 +39,6 @@ build container:
- tags - tags
- schedules - schedules
before_script:
- export BUILD_MBIM=true
- export BUILD_QMI=true
- export BUILD_QRTR=true
.prepare_deps: &prepare_deps .prepare_deps: &prepare_deps
- > - >
if [ "$BUILD_MBIM" == "true" ]; then if [ "$BUILD_MBIM" == "true" ]; then
@@ -64,7 +62,7 @@ before_script:
if [ "$BUILD_QMI" == "true" ]; then if [ "$BUILD_QMI" == "true" ]; then
git clone --depth 1 --branch ${LIBQMI_BRANCH} https://gitlab.freedesktop.org/mobile-broadband/libqmi.git git clone --depth 1 --branch ${LIBQMI_BRANCH} https://gitlab.freedesktop.org/mobile-broadband/libqmi.git
pushd libqmi pushd libqmi
meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=false -Dbash_completion=false -Dmbim_qmux=$BUILD_MBIM -Dqrtr=$BUILD_QRTR -Dcollection=basic meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=false -Dbash_completion=false -Dmbim_qmux=$BUILD_MBIM -Dqrtr=$BUILD_QRTR
ninja -C build ninja -C build
ninja -C build install ninja -C build install
popd popd
@@ -75,6 +73,8 @@ verify-dco:
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
needs:
- build_container
only: only:
- merge_requests - merge_requests
script: | script: |
@@ -91,6 +91,8 @@ verify-dco:
build-no-qmi: build-no-qmi:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -109,6 +111,8 @@ build-no-qmi:
build-qmi-qrtr-no-mbim: build-qmi-qrtr-no-mbim:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -126,6 +130,8 @@ build-qmi-qrtr-no-mbim:
build-qmi-no-qrtr-no-mbim: build-qmi-no-qrtr-no-mbim:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -144,6 +150,8 @@ build-qmi-no-qrtr-no-mbim:
build-no-qmi-no-mbim: build-no-qmi-no-mbim:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -164,6 +172,8 @@ build-no-qmi-no-mbim:
build-no-qmi-no-mbim-no-tests: build-no-qmi-no-mbim-no-tests:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -183,6 +193,8 @@ build-no-qmi-no-mbim-no-tests:
build-no-deprecated: build-no-deprecated:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -196,13 +208,15 @@ build-no-deprecated:
- export BUILD_QRTR=false - export BUILD_QRTR=false
- export BUILD_QMI=false - export BUILD_QMI=false
- *prepare_deps - *prepare_deps
- CFLAGS="-DMM_DISABLE_DEPRECATED" meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dqmi=false -Dqrtr=false -Dmbim=false - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dqmi=false -Dqrtr=false -Dmbim=false -Ddeprecated=false
- ninja -C build - ninja -C build
- ninja -C build test - ninja -C build test
- ninja -C build install - ninja -C build install
build-no-suspend-resume: build-no-suspend-resume:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -219,6 +233,8 @@ build-no-suspend-resume:
build-suspend-resume-powerd: build-suspend-resume-powerd:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -235,6 +251,8 @@ build-suspend-resume-powerd:
build-single-plugins: build-single-plugins:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -251,6 +269,8 @@ build-single-plugins:
build-single-plugins-builtin: build-single-plugins-builtin:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -267,6 +287,8 @@ build-single-plugins-builtin:
build-debug: build-debug:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -285,6 +307,8 @@ build-debug:
build-release: build-release:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -303,6 +327,8 @@ build-release:
build-release-builtin: build-release-builtin:
stage: build stage: build
needs:
- build_container
extends: extends:
- .fdo.distribution-image@ubuntu - .fdo.distribution-image@ubuntu
- .common_variables - .common_variables
@@ -318,3 +344,20 @@ build-release-builtin:
- ninja -C build test - ninja -C build test
- ninja -C build install - ninja -C build install
- ninja -C build uninstall - ninja -C build uninstall
build-asan:
stage: build
needs:
- build_container
extends:
- .fdo.distribution-image@ubuntu
- .common_variables
only:
- main
- merge_requests
- tags
- schedules
script:
- *prepare_deps
- meson setup build-asan -Db_sanitize=address -Dwerror=true -Dgtk_doc=false -Dqmi=true -Dqrtr=true -Dmbim=true
- meson test -C build-asan --suite=daemon --timeout-multiplier=5 --print-errorlogs
-28
View File
@@ -1,31 +1,3 @@
ModemManager 1.24.2
-------------------------------------------
This is a new stable release of ModemManager.
The most important features and changes in this release are the following:
* Core:
** Wait until bearers are disconnected before allowing system to suspend
** Fix checks for CDMA/EVDO access technology in some modems
** Detect old Mediatek 62xx-based devices as GSM-capable
** Refresh registration info after manual registration for AT-based devices
** Correctly report NB-IOT access technology
** Disable unsolicited 3GPP events during quick suspend/resume
* MBIM:
** Fix re-assembly of multi-part unstored SMS messages
* QMI:
** Fix re-assembly of multi-part unstored SMS messages
* Voice interface:
** Correctly start call state polling on some modems
* Plugins:
** fibocomm: don't assert when checking for firmware interface
** cinterion: allow spaces in ^SXRAT response
ModemManager 1.24.0 ModemManager 1.24.0
------------------------------------------- -------------------------------------------
This is a new stable release of ModemManager. This is a new stable release of ModemManager.
+1
View File
@@ -0,0 +1 @@
mm-enumflags-types.c.template
+1
View File
@@ -0,0 +1 @@
mm-enumflags-types.h.template
+3
View File
@@ -138,6 +138,7 @@ print_bearer_info (MMBearer *bearer)
g_autoptr(MMBearerProperties) properties = NULL; g_autoptr(MMBearerProperties) properties = NULL;
g_autoptr(MMBearerStats) stats = NULL; g_autoptr(MMBearerStats) stats = NULL;
g_autoptr(GError) connection_error = NULL; g_autoptr(GError) connection_error = NULL;
gboolean disconnect_request = FALSE;
gint profile_id; gint profile_id;
gchar *profile_id_str; gchar *profile_id_str;
@@ -147,6 +148,7 @@ print_bearer_info (MMBearer *bearer)
stats = mm_bearer_get_stats (bearer); stats = mm_bearer_get_stats (bearer);
profile_id = mm_bearer_get_profile_id (bearer); profile_id = mm_bearer_get_profile_id (bearer);
connection_error = mm_bearer_get_connection_error (bearer); connection_error = mm_bearer_get_connection_error (bearer);
disconnect_request = mm_bearer_get_disconnect_request (bearer);
profile_id_str = (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) ? g_strdup_printf ("%d", profile_id) : NULL; profile_id_str = (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) ? g_strdup_printf ("%d", profile_id) : NULL;
@@ -156,6 +158,7 @@ print_bearer_info (MMBearer *bearer)
mmcli_output_string (MMC_F_BEARER_STATUS_CONNECTED, mm_bearer_get_connected (bearer) ? "yes" : "no"); mmcli_output_string (MMC_F_BEARER_STATUS_CONNECTED, mm_bearer_get_connected (bearer) ? "yes" : "no");
mmcli_output_string_take (MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME, connection_error ? g_dbus_error_encode_gerror (connection_error) : NULL); mmcli_output_string_take (MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME, connection_error ? g_dbus_error_encode_gerror (connection_error) : NULL);
mmcli_output_string (MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE, connection_error ? connection_error->message : NULL); mmcli_output_string (MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE, connection_error ? connection_error->message : NULL);
mmcli_output_string (MMC_F_BEARER_STATUS_DISCONNECT_REQUEST, disconnect_request ? "yes" : "no");
mmcli_output_string (MMC_F_BEARER_STATUS_SUSPENDED, mm_bearer_get_suspended (bearer) ? "yes" : "no"); mmcli_output_string (MMC_F_BEARER_STATUS_SUSPENDED, mm_bearer_get_suspended (bearer) ? "yes" : "no");
mmcli_output_string (MMC_F_BEARER_STATUS_MULTIPLEXED, mm_bearer_get_multiplexed (bearer) ? "yes" : "no"); mmcli_output_string (MMC_F_BEARER_STATUS_MULTIPLEXED, mm_bearer_get_multiplexed (bearer) ? "yes" : "no");
mmcli_output_string (MMC_F_BEARER_STATUS_INTERFACE, mm_bearer_get_interface (bearer)); mmcli_output_string (MMC_F_BEARER_STATUS_INTERFACE, mm_bearer_get_interface (bearer));
+4
View File
@@ -115,6 +115,7 @@ mmcli_cbm_shutdown (void)
static void static void
print_cbm_info (MMCbm *cbm) print_cbm_info (MMCbm *cbm)
{ {
const gchar *lang;
gchar *channel; gchar *channel;
gchar *update; gchar *update;
gchar *code; gchar *code;
@@ -122,9 +123,12 @@ print_cbm_info (MMCbm *cbm)
update = g_strdup_printf ("%u", mm_cbm_get_update (cbm)); update = g_strdup_printf ("%u", mm_cbm_get_update (cbm));
channel = g_strdup_printf ("%u", mm_cbm_get_channel (cbm)); channel = g_strdup_printf ("%u", mm_cbm_get_channel (cbm));
code = g_strdup_printf ("%u", mm_cbm_get_message_code (cbm)); code = g_strdup_printf ("%u", mm_cbm_get_message_code (cbm));
lang = mm_cbm_get_language (cbm);
mmcli_output_string (MMC_F_CBM_GENERAL_DBUS_PATH, mm_cbm_get_path (cbm)); mmcli_output_string (MMC_F_CBM_GENERAL_DBUS_PATH, mm_cbm_get_path (cbm));
mmcli_output_string (MMC_F_CBM_CONTENT_TEXT, mm_cbm_get_text (cbm)); mmcli_output_string (MMC_F_CBM_CONTENT_TEXT, mm_cbm_get_text (cbm));
if (lang)
mmcli_output_string (MMC_F_CBM_PROPERTIES_LANG, mm_cbm_get_language (cbm));
mmcli_output_string_take (MMC_F_CBM_PROPERTIES_CHANNEL, channel); mmcli_output_string_take (MMC_F_CBM_PROPERTIES_CHANNEL, channel);
mmcli_output_string_take (MMC_F_CBM_PROPERTIES_UPDATE, update); mmcli_output_string_take (MMC_F_CBM_PROPERTIES_UPDATE, update);
mmcli_output_string_take (MMC_F_CBM_PROPERTIES_MESSAGE_CODE, code); mmcli_output_string_take (MMC_F_CBM_PROPERTIES_MESSAGE_CODE, code);
+1 -1
View File
@@ -344,7 +344,7 @@ set_supl_server_process_reply (gboolean result,
const GError *error) const GError *error)
{ {
if (!result) { if (!result) {
g_printerr ("error: couldn't set SUPL servert address: '%s'\n", g_printerr ("error: couldn't set SUPL server address: '%s'\n",
error ? error->message : "unknown error"); error ? error->message : "unknown error");
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
+1 -1
View File
@@ -458,7 +458,7 @@ mmcli_modem_signal_run_synchronous (GDBusConnection *connection)
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
g_debug ("Asynchronously setting up threshold values..."); g_debug ("Synchronously setting up threshold values...");
result = mm_modem_signal_setup_thresholds_sync (ctx->modem_signal, result = mm_modem_signal_setup_thresholds_sync (ctx->modem_signal,
properties, properties,
NULL, NULL,
+11 -1
View File
@@ -316,8 +316,11 @@ print_modem_info (void)
MMModemBand *bands = NULL; MMModemBand *bands = NULL;
guint n_bands = 0; guint n_bands = 0;
MMModemPortInfo *ports = NULL; MMModemPortInfo *ports = NULL;
MMModemPortInfo *ignored_ports = NULL;
guint n_ports = 0; guint n_ports = 0;
guint n_ignored_ports = 0;
gchar *ports_string; gchar *ports_string;
gchar *ignored_ports_string;
MMUnlockRetries *unlock_retries; MMUnlockRetries *unlock_retries;
guint signal_quality = 0; guint signal_quality = 0;
gboolean signal_quality_recent = FALSE; gboolean signal_quality_recent = FALSE;
@@ -343,7 +346,12 @@ print_modem_info (void)
g_free (bands); g_free (bands);
mm_modem_get_ports (ctx->modem, &ports, &n_ports); mm_modem_get_ports (ctx->modem, &ports, &n_ports);
ports_string = mm_common_build_ports_string (ports, n_ports); ports_string = mm_common_build_ports_string (ports, n_ports);
mm_modem_port_info_array_free (ports, n_ports); if (ports)
mm_modem_port_info_array_free (ports, n_ports);
mm_modem_get_ignored_ports (ctx->modem, &ignored_ports, &n_ignored_ports);
ignored_ports_string = mm_common_build_ports_string (ignored_ports, n_ignored_ports);
if (ignored_ports)
mm_modem_port_info_array_free (ignored_ports, n_ignored_ports);
if (mm_modem_get_current_modes (ctx->modem, &allowed_modes, &preferred_mode)) { if (mm_modem_get_current_modes (ctx->modem, &allowed_modes, &preferred_mode)) {
allowed_modes_string = mm_modem_mode_build_string_from_mask (allowed_modes); allowed_modes_string = mm_modem_mode_build_string_from_mask (allowed_modes);
preferred_mode_string = mm_modem_mode_build_string_from_mask (preferred_mode); preferred_mode_string = mm_modem_mode_build_string_from_mask (preferred_mode);
@@ -376,6 +384,7 @@ print_modem_info (void)
mmcli_output_string (MMC_F_SYSTEM_PLUGIN, mm_modem_get_plugin (ctx->modem)); mmcli_output_string (MMC_F_SYSTEM_PLUGIN, mm_modem_get_plugin (ctx->modem));
mmcli_output_string (MMC_F_SYSTEM_PRIMARY_PORT, mm_modem_get_primary_port (ctx->modem)); mmcli_output_string (MMC_F_SYSTEM_PRIMARY_PORT, mm_modem_get_primary_port (ctx->modem));
mmcli_output_string_list (MMC_F_SYSTEM_PORTS, ports_string); mmcli_output_string_list (MMC_F_SYSTEM_PORTS, ports_string);
mmcli_output_string_list (MMC_F_SYSTEM_IGNORED_PORTS, ignored_ports_string);
mmcli_output_string_array (MMC_F_NUMBERS_OWN, (const gchar **) mm_modem_get_own_numbers (ctx->modem), FALSE); mmcli_output_string_array (MMC_F_NUMBERS_OWN, (const gchar **) mm_modem_get_own_numbers (ctx->modem), FALSE);
@@ -540,6 +549,7 @@ print_modem_info (void)
mmcli_output_dump (); mmcli_output_dump ();
g_free (ports_string); g_free (ports_string);
g_free (ignored_ports_string);
g_free (supported_ip_families_string); g_free (supported_ip_families_string);
g_free (current_bands_string); g_free (current_bands_string);
g_free (supported_bands_string); g_free (supported_bands_string);
+3
View File
@@ -120,6 +120,7 @@ static FieldInfo field_infos[] = {
[MMC_F_SYSTEM_PLUGIN] = { "modem.generic.plugin", "plugin", MMC_S_MODEM_SYSTEM, }, [MMC_F_SYSTEM_PLUGIN] = { "modem.generic.plugin", "plugin", MMC_S_MODEM_SYSTEM, },
[MMC_F_SYSTEM_PRIMARY_PORT] = { "modem.generic.primary-port", "primary port", MMC_S_MODEM_SYSTEM, }, [MMC_F_SYSTEM_PRIMARY_PORT] = { "modem.generic.primary-port", "primary port", MMC_S_MODEM_SYSTEM, },
[MMC_F_SYSTEM_PORTS] = { "modem.generic.ports", "ports", MMC_S_MODEM_SYSTEM, }, [MMC_F_SYSTEM_PORTS] = { "modem.generic.ports", "ports", MMC_S_MODEM_SYSTEM, },
[MMC_F_SYSTEM_IGNORED_PORTS] = { "modem.generic.ignored-ports", "ignored ports", MMC_S_MODEM_SYSTEM, },
[MMC_F_NUMBERS_OWN] = { "modem.generic.own-numbers", "own", MMC_S_MODEM_NUMBERS, }, [MMC_F_NUMBERS_OWN] = { "modem.generic.own-numbers", "own", MMC_S_MODEM_NUMBERS, },
[MMC_F_STATUS_LOCK] = { "modem.generic.unlock-required", "lock", MMC_S_MODEM_STATUS, }, [MMC_F_STATUS_LOCK] = { "modem.generic.unlock-required", "lock", MMC_S_MODEM_STATUS, },
[MMC_F_STATUS_UNLOCK_RETRIES] = { "modem.generic.unlock-retries", "unlock retries", MMC_S_MODEM_STATUS, }, [MMC_F_STATUS_UNLOCK_RETRIES] = { "modem.generic.unlock-retries", "unlock retries", MMC_S_MODEM_STATUS, },
@@ -241,6 +242,7 @@ static FieldInfo field_infos[] = {
[MMC_F_BEARER_STATUS_CONNECTED] = { "bearer.status.connected", "connected", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_CONNECTED] = { "bearer.status.connected", "connected", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME] = { "bearer.status.connection-error.name", "connection error name", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME] = { "bearer.status.connection-error.name", "connection error name", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE] = { "bearer.status.connection-error.message", "connection error message", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE] = { "bearer.status.connection-error.message", "connection error message", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_DISCONNECT_REQUEST] = { "bearer.status.disconnect-request", "disconnect request", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_SUSPENDED] = { "bearer.status.suspended", "suspended", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_SUSPENDED] = { "bearer.status.suspended", "suspended", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_MULTIPLEXED] = { "bearer.status.multiplexed", "multiplexed", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_MULTIPLEXED] = { "bearer.status.multiplexed", "multiplexed", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_INTERFACE] = { "bearer.status.interface", "interface", MMC_S_BEARER_STATUS, }, [MMC_F_BEARER_STATUS_INTERFACE] = { "bearer.status.interface", "interface", MMC_S_BEARER_STATUS, },
@@ -296,6 +298,7 @@ static FieldInfo field_infos[] = {
[MMC_F_CBM_PROPERTIES_CHANNEL] = { "cbm.properties.channel", "channel", MMC_S_CBM_PROPERTIES, }, [MMC_F_CBM_PROPERTIES_CHANNEL] = { "cbm.properties.channel", "channel", MMC_S_CBM_PROPERTIES, },
[MMC_F_CBM_PROPERTIES_UPDATE] = { "cbm.properties.update", "update", MMC_S_CBM_PROPERTIES, }, [MMC_F_CBM_PROPERTIES_UPDATE] = { "cbm.properties.update", "update", MMC_S_CBM_PROPERTIES, },
[MMC_F_CBM_PROPERTIES_MESSAGE_CODE] = { "cbm.properties.message-code", "message code", MMC_S_CBM_PROPERTIES, }, [MMC_F_CBM_PROPERTIES_MESSAGE_CODE] = { "cbm.properties.message-code", "message code", MMC_S_CBM_PROPERTIES, },
[MMC_F_CBM_PROPERTIES_LANG ] = { "cbm.properties.lang", "lang", MMC_S_CBM_PROPERTIES, },
[MMC_F_SMS_GENERAL_DBUS_PATH] = { "sms.dbus-path", "path", MMC_S_SMS_GENERAL, }, [MMC_F_SMS_GENERAL_DBUS_PATH] = { "sms.dbus-path", "path", MMC_S_SMS_GENERAL, },
[MMC_F_SMS_CONTENT_NUMBER] = { "sms.content.number", "number", MMC_S_SMS_CONTENT, }, [MMC_F_SMS_CONTENT_NUMBER] = { "sms.content.number", "number", MMC_S_SMS_CONTENT, },
[MMC_F_SMS_CONTENT_TEXT] = { "sms.content.text", "text", MMC_S_SMS_CONTENT, }, [MMC_F_SMS_CONTENT_TEXT] = { "sms.content.text", "text", MMC_S_SMS_CONTENT, },
+3
View File
@@ -114,6 +114,7 @@ typedef enum {
MMC_F_SYSTEM_PLUGIN, MMC_F_SYSTEM_PLUGIN,
MMC_F_SYSTEM_PRIMARY_PORT, MMC_F_SYSTEM_PRIMARY_PORT,
MMC_F_SYSTEM_PORTS, MMC_F_SYSTEM_PORTS,
MMC_F_SYSTEM_IGNORED_PORTS,
/* Numbers section */ /* Numbers section */
MMC_F_NUMBERS_OWN, MMC_F_NUMBERS_OWN,
/* Status section */ /* Status section */
@@ -259,6 +260,7 @@ typedef enum {
MMC_F_BEARER_STATUS_CONNECTED, MMC_F_BEARER_STATUS_CONNECTED,
MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME, MMC_F_BEARER_STATUS_CONNECTION_ERROR_NAME,
MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE, MMC_F_BEARER_STATUS_CONNECTION_ERROR_MESSAGE,
MMC_F_BEARER_STATUS_DISCONNECT_REQUEST,
MMC_F_BEARER_STATUS_SUSPENDED, MMC_F_BEARER_STATUS_SUSPENDED,
MMC_F_BEARER_STATUS_MULTIPLEXED, MMC_F_BEARER_STATUS_MULTIPLEXED,
MMC_F_BEARER_STATUS_INTERFACE, MMC_F_BEARER_STATUS_INTERFACE,
@@ -315,6 +317,7 @@ typedef enum {
MMC_F_CBM_PROPERTIES_CHANNEL, MMC_F_CBM_PROPERTIES_CHANNEL,
MMC_F_CBM_PROPERTIES_UPDATE, MMC_F_CBM_PROPERTIES_UPDATE,
MMC_F_CBM_PROPERTIES_MESSAGE_CODE, MMC_F_CBM_PROPERTIES_MESSAGE_CODE,
MMC_F_CBM_PROPERTIES_LANG,
MMC_F_SMS_GENERAL_DBUS_PATH, MMC_F_SMS_GENERAL_DBUS_PATH,
MMC_F_SMS_CONTENT_NUMBER, MMC_F_SMS_CONTENT_NUMBER,
MMC_F_SMS_CONTENT_TEXT, MMC_F_SMS_CONTENT_TEXT,
+1
View File
@@ -10,6 +10,7 @@ BusName=org.freedesktop.ModemManager1
ExecStart=@sbindir@/ModemManager ExecStart=@sbindir@/ModemManager
StandardError=null StandardError=null
Restart=on-abort Restart=on-abort
KillMode=mixed
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_NET_ADMIN CapabilityBoundingSet=CAP_SYS_ADMIN CAP_NET_ADMIN
ProtectSystem=true ProtectSystem=true
ProtectHome=true ProtectHome=true
+3 -1
View File
@@ -4,6 +4,7 @@
# 2021 Aleksander Morgado <aleksander@aleksander.es> # 2021 Aleksander Morgado <aleksander@aleksander.es>
# 2022 Thilo-Alexander Ginkel <thilo@ginkel.com> # 2022 Thilo-Alexander Ginkel <thilo@ginkel.com>
# 2022 Bjørn Mork <bjorn@mork.no> # 2022 Bjørn Mork <bjorn@mork.no>
# 2025 Kajetan Krykwiński <gitlab@kitor.pl>
# #
# Foxconn SDX55 (Lenovo T99W175) FCC unlock operation # Foxconn SDX55 (Lenovo T99W175) FCC unlock operation
# #
@@ -22,7 +23,8 @@ for PORT in "$@"; do
# match port type in Linux 5.14 and newer # match port type in Linux 5.14 and newer
grep -q MBIM "/sys/class/wwan/$PORT/type" 2>/dev/null || grep -q MBIM "/sys/class/wwan/$PORT/type" 2>/dev/null ||
# match port name in Linux 5.13 # match port name in Linux 5.13
echo "$PORT" | grep -qi MBIM && { echo "$PORT" | grep -qi MBIM ||
echo "$PORT" | grep -q cdc-wdm && {
MBIM_PORT="$PORT" MBIM_PORT="$PORT"
break break
} }
+131
View File
@@ -0,0 +1,131 @@
#!/bin/bash
# SPDX-License-Identifier: CC0-1.0
# 2024 Thomas Vogt
#
# RPC-powered Intel XMM7360 (8086:7360) FCC unlock
if [[ "$FCC_UNLOCK_DEBUG_LOG" == '1' ]]; then
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/var/log/mm-xmm7360-fcc.log 2>&1
fi
# require program name and at least 2 arguments
[ $# -lt 2 ] && exit 1
# first argument is DBus path, not needed here
shift
# second and next arguments are control port names
for PORT in "$@"; do
# support for XMM7360 has been added in 5.18
# match port type, assuming Linux 5.14 and newer
grep -q XMMRPC "/sys/class/wwan/$PORT/type" 2>/dev/null && {
XMMRPC_PORT=$PORT
break
}
done
# fail if no XMMRPC port exposed
[ -n "$XMMRPC_PORT" ] || exit 2
DEVICE=/dev/${XMMRPC_PORT}
log() {
echo "$1"
}
error() {
echo "$1" >&2
}
reverseHexEndianness() {
num="$1"
printf "%s" "${num:6:2}${num:4:2}${num:2:2}${num:0:2}"
}
littleEndianToDec() {
printf "%d" "0x$1"
}
bigEndianToDec() {
littleEndianToDec "$(reverseHexEndianness "$1")"
}
readNBytesAsHex() {
data=$(head "-c$1" <&99 | xxd -p -c0 | tr -d '\n')
printf "%s" "$data"
}
writeHexAsBinary() {
printf "%s" "$1" | xxd -r -p >&99
}
readResponseAsHex() {
length_hex=$(readNBytesAsHex 4)
length=$(bigEndianToDec "$length_hex")
content=$(readNBytesAsHex $length)
printf "%s" "$length_hex$content"
}
rpc_command() {
exec 99<>"$DEVICE"
writeHexAsBinary $1
answer=$(readResponseAsHex) # ignore "async-ack" response
answer=$(readResponseAsHex)
printf "%s" "$answer"
exec 99>&-
}
VENDOR_ID_HASH="3df8c719"
for i in {1..3}; do
log "Attempt #${i} to unlock WWAN modem"
log "Requesting FCC lock state from modem"
# --> (async) csi-fcc-lock-query-req
RESP=$(rpc_command "1c00000002040000001c02040000018e11000101020411000101020400000000")
MODE=$(littleEndianToDec "${RESP: -8}")
STATE=$(littleEndianToDec "${RESP: -20:8}")
log "Got response from modem: state=$STATE, mode=$MODE"
if [ "$MODE" = "0" ]; then
log "FCC lock is deactivated, nothing to do."
exit 0
fi
if [ "$STATE" != "0" ]; then
log "FCC already unlocked, nothing to do."
exit 0
fi
log "Requesting challenge from modem"
# --> (async) csi-fcc-lock-gen-challenge-req
RESP=$(rpc_command "1c00000002040000001c02040000019011000101020411000101020400000000")
HEX_CHALLENGE=$(printf "%s" "${RESP: -8}")
log "Got challenge from modem: $HEX_CHALLENGE"
REVERSE_HEX_CHALLENGE=$(reverseHexEndianness "${HEX_CHALLENGE}")
COMBINED_CHALLENGE="${REVERSE_HEX_CHALLENGE}${VENDOR_ID_HASH}"
RESPONSE_HASH=$(printf "%s" "$COMBINED_CHALLENGE" | xxd -r -p | sha256sum | cut -d ' ' -f 1)
REVERSED_RESPONSE=$(reverseHexEndianness "${RESPONSE_HASH:0:8}")
log "Sending hash to modem: $REVERSED_RESPONSE"
# --> (async) csi-fcc-lock-ver-challenge-req
RESP=$(rpc_command "1c00000002040000001c020400000192110001010204110001010204${REVERSED_RESPONSE}")
UNLOCK_RESPONSE=$(littleEndianToDec "${RESP: -8}")
if [ "$UNLOCK_RESPONSE" = "0" ]; then
error "Unlock failed."
else
log "FCC unlock successful (response $UNLOCK_RESPONSE)"
exit 0
fi
sleep 0.5
done
exit 2
+2
View File
@@ -15,6 +15,7 @@ examples = files(
'1199', '1199',
'14c3', '14c3',
'2c7c', '2c7c',
'8086:7360',
) )
install_data( install_data(
@@ -26,6 +27,7 @@ install_data(
vidpids = { vidpids = {
'105b:e0ab': '105b', '105b:e0ab': '105b',
'105b:e0c3': '105b', '105b:e0c3': '105b',
'05c6:90d5': '105b',
'03f0:4e1d': '1199', '03f0:4e1d': '1199',
'1199:9079': '1199', '1199:9079': '1199',
'413c:81a3': '1199', '413c:81a3': '1199',
@@ -71,6 +71,10 @@
send_interface="org.freedesktop.ModemManager1.Modem" send_interface="org.freedesktop.ModemManager1.Modem"
send_member="SetCurrentModes"/> send_member="SetCurrentModes"/>
<allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem"
send_member="SetPrimarySimSlot"/>
<allow send_destination="org.freedesktop.ModemManager1" <allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem" send_interface="org.freedesktop.ModemManager1.Modem"
send_member="SetCurrentBands"/> send_member="SetCurrentBands"/>
@@ -351,6 +355,10 @@
send_interface="org.freedesktop.ModemManager1.Modem.Signal" send_interface="org.freedesktop.ModemManager1.Modem.Signal"
send_member="Setup"/> send_member="Setup"/>
<allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem.Signal"
send_member="SetupThresholds"/>
<!-- org.freedesktop.ModemManager1.Modem.Time.xml --> <!-- org.freedesktop.ModemManager1.Modem.Time.xml -->
<!-- Protected by the Time policy rule --> <!-- Protected by the Time policy rule -->
@@ -358,6 +366,22 @@
send_interface="org.freedesktop.ModemManager1.Modem.Time" send_interface="org.freedesktop.ModemManager1.Modem.Time"
send_member="GetNetworkTime"/> send_member="GetNetworkTime"/>
<!-- org.freedesktop.ModemManager1.Modem.CellBroadcast.xml -->
<!-- Allowed for everyone -->
<allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem.CellBroadcast"
send_member="List"/>
<!-- Protected by the CellBroadcast policy rule -->
<allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem.CellBroadcast"
send_member="Delete"/>
<!-- Protected by the Device.Control policy rule -->
<allow send_destination="org.freedesktop.ModemManager1"
send_interface="org.freedesktop.ModemManager1.Modem.CellBroadcast"
send_member="SetChannels"/>
</policy> </policy>
<policy user="root"> <policy user="root">
@@ -11,7 +11,7 @@
<action id="org.freedesktop.ModemManager1.CellBroadcast"> <action id="org.freedesktop.ModemManager1.CellBroadcast">
<description>Enable and view Cell Broadcast messages</description> <description>Enable and view Cell Broadcast messages</description>
<message>System policy prevents enabling or viewing this device's text messages.</message> <message>System policy prevents enabling or viewing this device's cell broadcast messages.</message>
<defaults> <defaults>
<allow_inactive>no</allow_inactive> <allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active> <allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
@@ -27,6 +27,15 @@
</defaults> </defaults>
</action> </action>
<action id="org.freedesktop.ModemManager1.Modem.SetPrimarySimSlot">
<description>Set the primary sim slot of a modem</description>
<message>System policy prevents configuring modem properties.</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>@MM_DEFAULT_USER_POLICY@</allow_active>
</defaults>
</action>
<action id="org.freedesktop.ModemManager1.Device.Control"> <action id="org.freedesktop.ModemManager1.Device.Control">
<description>Unlock and control a mobile broadband device</description> <description>Unlock and control a mobile broadband device</description>
<message>System policy prevents unlocking or controlling the mobile broadband device.</message> <message>System policy prevents unlocking or controlling the mobile broadband device.</message>
+59 -26
View File
@@ -176,8 +176,10 @@ in use, like \fIBearer\fR. For example:
.RE .RE
.TP .TP
.B \-m, \-\-modem=[PATH|INDEX] .B \-m, \-\-modem=[PATH|INDEX|any]
Specify a modem. Specify a modem via full D-Bus object path, modem index, or 'any'. 'any' selects
the first available modem regardless of index or path, which can simplify
operation for single-modem systems.
.TP .TP
.B \-b, \-\-bearer=[PATH|INDEX] .B \-b, \-\-bearer=[PATH|INDEX]
Specify a bearer. Specify a bearer.
@@ -496,6 +498,10 @@ This DBus property signal updates are by default disabled.
.B \-\-location\-set\-disable\-signal .B \-\-location\-set\-disable\-signal
Disable reporting location updates via DBus property signals. Disable reporting location updates via DBus property signals.
.TP
.B \-\-location\-monitor
Continuously monitor all available location information.
.SH MESSAGING OPTIONS .SH MESSAGING OPTIONS
All messaging options must be used with \fB\-\-modem\fR or \fB\-m\fR. All messaging options must be used with \fB\-\-modem\fR or \fB\-m\fR.
@@ -764,7 +770,7 @@ Set the list of channels on which cell broadcasts are received (e.g. \fB5370,537
You'll need first to know which the proper path/index is for the SIM in your You'll need first to know which the proper path/index is for the SIM in your
modem: modem:
.Bd -literal -compact .Bd -literal -compact
$ mmcli -m 0 -K | grep "modem.generic.sim" | awk -F ": " '{ print $2 }' $ mmcli -m any -K | grep "modem.generic.sim" | awk -F ": " '{ print $2 }'
/org/freedesktop/ModemManager1/SIM/0 /org/freedesktop/ModemManager1/SIM/0
.Ed .Ed
@@ -778,13 +784,13 @@ And after that, you can just use the SIM index:
You can launch the simple connection process like: You can launch the simple connection process like:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --simple-connect="pin=1234,apn=internet" $ sudo mmcli -m any --simple-connect="pin=1234,apn=internet"
successfully connected the modem successfully connected the modem
.Ed .Ed
Then, you can disconnect it like: Then, you can disconnect it like:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --simple-disconnect $ sudo mmcli -m any --simple-disconnect
successfully disconnected all bearers in the modem successfully disconnected all bearers in the modem
.Ed .Ed
@@ -793,7 +799,7 @@ Then, you can disconnect it like:
Scanning for 3GPP networks may really take a long time, so a specific timeout Scanning for 3GPP networks may really take a long time, so a specific timeout
must be given: must be given:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --3gpp-scan --timeout=300 $ sudo mmcli -m any --3gpp-scan --timeout=300
--------------------- ---------------------
3GPP scan | networks: 21403 - Orange SP (gprs, unknown) 3GPP scan | networks: 21403 - Orange SP (gprs, unknown)
| 21407 - Movistar (gprs, unknown) | 21407 - Movistar (gprs, unknown)
@@ -806,7 +812,7 @@ must be given:
Using the “sm” (SIM), you can do this using: Using the “sm” (SIM), you can do this using:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --messaging-create-sms="text='Hello world',number='+1234567890'" $ sudo mmcli -m any --messaging-create-sms="text='Hello world',number='+1234567890'"
Successfully created new SMS: Successfully created new SMS:
/org/freedesktop/ModemManager1/SMS/21 (unknown) /org/freedesktop/ModemManager1/SMS/21 (unknown)
@@ -829,7 +835,7 @@ Using the “sm” (SIM), you can do this using:
| delivery report: not requested | delivery report: not requested
| message reference: 0 | message reference: 0
$ sudo mmcli -m 0 --messaging-status $ sudo mmcli -m any --messaging-status
---------------------------- ----------------------------
Messaging | supported storages: sm, me Messaging | supported storages: sm, me
| default storage: me | default storage: me
@@ -841,7 +847,7 @@ As you can see below, the important part is the
\fB\-\-messaging\-create\-sms\-with\-data\fR and the \fBPATH\fR provided. \fB\-\-messaging\-create\-sms\-with\-data\fR and the \fBPATH\fR provided.
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 \\ $ sudo mmcli -m any \\
--messaging-create-sms="number='+1234567890'" \\ --messaging-create-sms="number='+1234567890'" \\
--messaging-create-sms-with-data=/path/to/your/file --messaging-create-sms-with-data=/path/to/your/file
Successfully created new SMS: Successfully created new SMS:
@@ -858,7 +864,7 @@ recover the sent file with another \fBmmcli\fR command in their
ModemManager setup: ModemManager setup:
.Bd -literal -compact .Bd -literal -compact
$> sudo mmcli -m 0 --messaging-list-sms $> sudo mmcli -m any --messaging-list-sms
/org/freedesktop/ModemManager1/SMS/0 (received) /org/freedesktop/ModemManager1/SMS/0 (received)
$> sudo mmcli -s 0 --create-file-with-data=/path/to/the/output/file $> sudo mmcli -s 0 --create-file-with-data=/path/to/the/output/file
@@ -872,7 +878,7 @@ if you have more than one modem, just use --list-modems to check the
proper modem index: proper modem index:
.Bd -literal -compact .Bd -literal -compact
$ mmcli -m 0 --location-status $ mmcli -m any --location-status
---------------------------- ----------------------------
Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea
| enabled: none | enabled: none
@@ -884,10 +890,10 @@ ID, GPS raw and GPS-NMEA location sources. None is enabled yet, as we
didn’t enable the modem, which we can do issuing: didn’t enable the modem, which we can do issuing:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --enable $ sudo mmcli -m any --enable
successfully enabled the modem successfully enabled the modem
$ mmcli -m 0 --location-status $ mmcli -m any --location-status
---------------------------- ----------------------------
Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea
| enabled: 3gpp-lac-ci | enabled: 3gpp-lac-ci
@@ -899,7 +905,7 @@ didn’t enable the modem, which we can do issuing:
We can start the GPS engine by enabling the RAW or NMEA GPS location sources: We can start the GPS engine by enabling the RAW or NMEA GPS location sources:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 \\ $ sudo mmcli -m any \\
--location-enable-gps-raw \\ --location-enable-gps-raw \\
--location-enable-gps-nmea --location-enable-gps-nmea
successfully setup location gathering successfully setup location gathering
@@ -908,7 +914,7 @@ We can start the GPS engine by enabling the RAW or NMEA GPS location sources:
If we do check again the status, we’ll see the GPS-specific locations are enabled: If we do check again the status, we’ll see the GPS-specific locations are enabled:
.Bd -literal -compact .Bd -literal -compact
$ mmcli -m 0 --location-status $ mmcli -m any --location-status
-------------------------------- --------------------------------
Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea
| enabled: 3gpp-lac-ci, gps-raw, gps-nmea | enabled: 3gpp-lac-ci, gps-raw, gps-nmea
@@ -922,7 +928,7 @@ If any of the specific outputs is not available, the corresponding section will
be omitted from the output. be omitted from the output.
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 --location-get $ sudo mmcli -m any --location-get
------------------------- -------------------------
3GPP location | Mobile country code: 214 3GPP location | Mobile country code: 214
| Mobile network code: 3 | Mobile network code: 3
@@ -939,6 +945,33 @@ be omitted from the output.
| $GPVTG,,T,,M,,N,,K,N*2C | $GPVTG,,T,,M,,N,,K,N*2C
.Ed .Ed
Location information may be continuously monitored using
\fB\-\-location\-monitor\fR, which watches 'Location' property updates. Note
that these updates must first be enabled with
\fB\-\-location\-set\-enable\-signal\fR.
.Bd -literal -compact
$ sudo mmcli -m 0 --location-set-gps-refresh-rate=10
successfully set GPS refresh rate
$ sudo mmcli -m 0 --location-enable-gps-nmea --location-set-enable-signal
successfully setup location gathering
$ sudo mmcli -m 0 --location-monitor
-----------
GPS | nmea: $GPGSA,A,2,03,04,06,07,09,,,,,,,,1.7,1.4,1.0*3E
| $GPGSV,3,1,11,03,38,123,37,04,56,037,18,06,41,277,21,07,52,209,32*75
| $GPGSV,3,2,11,09,61,320,23,11,17,313,19,30,12,217,24,01,02,168,*77
| $GPGSV,3,3,11,16,21,077,,26,13,047,,40,,,36*79
| $GPGGA,152454.00,3651.420706,N,03101.297031,E,1,05,1.4,128.4,M,32.0,M,,*6A
-----------
GPS | nmea: $GPGSA,A,2,03,04,06,07,09,,,,,,,,1.7,1.4,1.0*3E
| $GPGSV,3,1,11,03,38,123,37,04,56,037,24,06,41,277,20,07,52,209,33*7A
| $GPGSV,3,2,11,09,61,320,23,11,17,313,18,30,12,217,23,01,02,168,*71
| $GPGSV,3,3,11,16,21,077,,26,13,047,,40,,,36*79
| $GPGGA,152504.00,3651.420036,N,03101.297176,E,1,05,1.4,60.7,M,32.0,M,,*56
.Ed
.SS A-GPS support .SS A-GPS support
If A-GPS is enabled before starting the GPS engine, and if a data connection If A-GPS is enabled before starting the GPS engine, and if a data connection
@@ -950,7 +983,7 @@ enabled. An explicit output (RAW or NMEA) is required to be enabled in order
to start the GPS engine. to start the GPS engine.
.Bd -literal -compact .Bd -literal -compact
$ mmcli -m 0 --location-status $ mmcli -m any --location-status
-------------------------------- --------------------------------
Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea, agps-msa, agps-msb Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea, agps-msa, agps-msb
| enabled: 3gpp-lac-ci | enabled: 3gpp-lac-ci
@@ -959,13 +992,13 @@ to start the GPS engine.
GPS | refresh rate: 30 seconds GPS | refresh rate: 30 seconds
| a-gps supl server: supl.google.com:7276 | a-gps supl server: supl.google.com:7276
$ sudo mmcli -m 0 --location-enable-agps-msa $ sudo mmcli -m any --location-enable-agps-msa
successfully setup location gathering successfully setup location gathering
$ sudo mmcli -m 0 --location-enable-gps-nmea $ sudo mmcli -m any --location-enable-gps-nmea
successfully setup location gathering successfully setup location gathering
$ sudo mmcli -m 0 --location-enable-gps-raw $ sudo mmcli -m any --location-enable-gps-raw
successfully setup location gathering successfully setup location gathering
.Ed .Ed
@@ -981,7 +1014,7 @@ one of the servers listed by ModemManager and manually inject it afterwards. The
XTRA assistance data is usually valid for several days. XTRA assistance data is usually valid for several days.
.Bd -literal -compact .Bd -literal -compact
$ mmcli -m 0 --location-status $ mmcli -m any --location-status
-------------------------------- --------------------------------
Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea, agps-msa, agps-msb Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea, agps-msa, agps-msb
| enabled: 3gpp-lac-ci | enabled: 3gpp-lac-ci
@@ -996,13 +1029,13 @@ XTRA assistance data is usually valid for several days.
$ wget -q https://xtrapath3.izatcloud.net/xtra3grcej.bin $ wget -q https://xtrapath3.izatcloud.net/xtra3grcej.bin
$ sudo mmcli -m 0 --location-inject-assistance-data=./xtra3grcej.bin $ sudo mmcli -m any --location-inject-assistance-data=./xtra3grcej.bin
successfully injected assistance data successfully injected assistance data
$ sudo mmcli -m 0 --location-enable-gps-nmea $ sudo mmcli -m any --location-enable-gps-nmea
successfully setup location gathering successfully setup location gathering
$ sudo mmcli -m 0 --location-enable-gps-raw $ sudo mmcli -m any --location-enable-gps-raw
successfully setup location gathering successfully setup location gathering
.Ed .Ed
@@ -1011,7 +1044,7 @@ XTRA assistance data is usually valid for several days.
The channel list can be set as a comma separated list of channels or channel intervals: The channel list can be set as a comma separated list of channels or channel intervals:
.Bd -literal -compact .Bd -literal -compact
$ sudo mmcli -m 0 \\ $ sudo mmcli -m any \\
--cell-broadcast-set-channels=5370,5371,5373-5000 --cell-broadcast-set-channels=5370,5371,5373-5000
successfully set channels in the modem successfully set channels in the modem
.Ed .Ed
@@ -1024,7 +1057,7 @@ example, you could gather all the main status information of the modem
with a single call and then parse it to read single fields: with a single call and then parse it to read single fields:
.Bd -literal -compact .Bd -literal -compact
$ STATUS=$(mmcli -m 0 --output-keyvalue) $ STATUS=$(mmcli -m any --output-keyvalue)
$ echo "${STATUS}" | grep "modem.generic.state " | awk -F ": " '{ print $2 }' $ echo "${STATUS}" | grep "modem.generic.state " | awk -F ": " '{ print $2 }'
failed failed
$ echo "${STATUS}" | grep "modem.generic.state-failed-reason " | awk -F ": " '{ print $2 }' $ echo "${STATUS}" | grep "modem.generic.state-failed-reason " | awk -F ": " '{ print $2 }'
@@ -229,6 +229,7 @@ ID_MM_TTY_BAUDRATE
ID_MM_TTY_FLOW_CONTROL ID_MM_TTY_FLOW_CONTROL
ID_MM_REQUIRED ID_MM_REQUIRED
ID_MM_MAX_MULTIPLEXED_LINKS ID_MM_MAX_MULTIPLEXED_LINKS
ID_MM_INITIAL_QMAP_MUX_ID
<SUBSECTION Deprecated> <SUBSECTION Deprecated>
ID_MM_TTY_BLACKLIST ID_MM_TTY_BLACKLIST
ID_MM_TTY_MANUAL_SCAN_ONLY ID_MM_TTY_MANUAL_SCAN_ONLY
@@ -1448,6 +1448,7 @@ mm_bearer_dup_path
mm_bearer_get_interface mm_bearer_get_interface
mm_bearer_dup_interface mm_bearer_dup_interface
mm_bearer_get_connected mm_bearer_get_connected
mm_bearer_get_disconnect_request
mm_bearer_get_suspended mm_bearer_get_suspended
mm_bearer_get_multiplexed mm_bearer_get_multiplexed
mm_bearer_get_ip_timeout mm_bearer_get_ip_timeout
@@ -2345,6 +2346,7 @@ mm_gdbus_bearer_dup_properties
mm_gdbus_bearer_get_connected mm_gdbus_bearer_get_connected
mm_gdbus_bearer_get_connection_error mm_gdbus_bearer_get_connection_error
mm_gdbus_bearer_dup_connection_error mm_gdbus_bearer_dup_connection_error
mm_gdbus_bearer_get_disconnect_request
mm_gdbus_bearer_get_suspended mm_gdbus_bearer_get_suspended
mm_gdbus_bearer_get_multiplexed mm_gdbus_bearer_get_multiplexed
mm_gdbus_bearer_get_bearer_type mm_gdbus_bearer_get_bearer_type
@@ -2363,6 +2365,7 @@ mm_gdbus_bearer_call_disconnect_sync
mm_gdbus_bearer_interface_info mm_gdbus_bearer_interface_info
mm_gdbus_bearer_set_connected mm_gdbus_bearer_set_connected
mm_gdbus_bearer_set_connection_error mm_gdbus_bearer_set_connection_error
mm_gdbus_bearer_set_disconnect_request
mm_gdbus_bearer_set_interface mm_gdbus_bearer_set_interface
mm_gdbus_bearer_set_ip4_config mm_gdbus_bearer_set_ip4_config
mm_gdbus_bearer_set_ip6_config mm_gdbus_bearer_set_ip6_config
@@ -2822,6 +2825,8 @@ mm_gdbus_modem_get_primary_port
mm_gdbus_modem_dup_primary_port mm_gdbus_modem_dup_primary_port
mm_gdbus_modem_get_ports mm_gdbus_modem_get_ports
mm_gdbus_modem_dup_ports mm_gdbus_modem_dup_ports
mm_gdbus_modem_get_ignored_ports
mm_gdbus_modem_dup_ignored_ports
mm_gdbus_modem_get_revision mm_gdbus_modem_get_revision
mm_gdbus_modem_dup_revision mm_gdbus_modem_dup_revision
mm_gdbus_modem_get_carrier_configuration mm_gdbus_modem_get_carrier_configuration
@@ -2908,6 +2913,7 @@ mm_gdbus_modem_set_own_numbers
mm_gdbus_modem_set_plugin mm_gdbus_modem_set_plugin
mm_gdbus_modem_set_primary_port mm_gdbus_modem_set_primary_port
mm_gdbus_modem_set_ports mm_gdbus_modem_set_ports
mm_gdbus_modem_set_ignored_ports
mm_gdbus_modem_set_revision mm_gdbus_modem_set_revision
mm_gdbus_modem_set_carrier_configuration mm_gdbus_modem_set_carrier_configuration
mm_gdbus_modem_set_carrier_configuration_revision mm_gdbus_modem_set_carrier_configuration_revision
+4 -1
View File
@@ -386,6 +386,7 @@ typedef enum { /*< underscore_name=mm_modem_mode >*/
* @MM_MODEM_BAND_EUTRAN_70: E-UTRAN band 70. Since 1.8. * @MM_MODEM_BAND_EUTRAN_70: E-UTRAN band 70. Since 1.8.
* @MM_MODEM_BAND_EUTRAN_71: E-UTRAN band 71. Since 1.8. * @MM_MODEM_BAND_EUTRAN_71: E-UTRAN band 71. Since 1.8.
* @MM_MODEM_BAND_EUTRAN_85: E-UTRAN band 85. Since 1.20. * @MM_MODEM_BAND_EUTRAN_85: E-UTRAN band 85. Since 1.20.
* @MM_MODEM_BAND_EUTRAN_106: E-UTRAN band 106. Since 1.26.
* @MM_MODEM_BAND_CDMA_BC0: CDMA Band Class 0 (US Cellular 850MHz). Since 1.8. * @MM_MODEM_BAND_CDMA_BC0: CDMA Band Class 0 (US Cellular 850MHz). Since 1.8.
* @MM_MODEM_BAND_CDMA_BC1: CDMA Band Class 1 (US PCS 1900MHz). Since 1.8. * @MM_MODEM_BAND_CDMA_BC1: CDMA Band Class 1 (US PCS 1900MHz). Since 1.8.
* @MM_MODEM_BAND_CDMA_BC2: CDMA Band Class 2 (UK TACS 900MHz). Since 1.8. * @MM_MODEM_BAND_CDMA_BC2: CDMA Band Class 2 (UK TACS 900MHz). Since 1.8.
@@ -652,7 +653,9 @@ typedef enum { /*< underscore_name=mm_modem_band >*/
MM_MODEM_BAND_NGRAN_257 = 557, MM_MODEM_BAND_NGRAN_257 = 557,
MM_MODEM_BAND_NGRAN_258 = 558, MM_MODEM_BAND_NGRAN_258 = 558,
MM_MODEM_BAND_NGRAN_260 = 560, MM_MODEM_BAND_NGRAN_260 = 560,
MM_MODEM_BAND_NGRAN_261 = 561 MM_MODEM_BAND_NGRAN_261 = 561,
/* LTE bands > 97 follow EUTRAN numbering + 1000 as offset */
MM_MODEM_BAND_EUTRAN_106 = 1136
} MMModemBand; } MMModemBand;
/** /**
+2
View File
@@ -521,6 +521,7 @@ typedef enum { /*< underscore_name=mm_connection_error >*/
* @MM_SERIAL_ERROR_NOT_OPEN: The serial port is not open. * @MM_SERIAL_ERROR_NOT_OPEN: The serial port is not open.
* @MM_SERIAL_ERROR_PARSE_FAILED: The serial port specific parsing failed. * @MM_SERIAL_ERROR_PARSE_FAILED: The serial port specific parsing failed.
* @MM_SERIAL_ERROR_FRAME_NOT_FOUND: The serial port reported that the frame marker wasn't found (e.g. for QCDM). Since 1.6. * @MM_SERIAL_ERROR_FRAME_NOT_FOUND: The serial port reported that the frame marker wasn't found (e.g. for QCDM). Since 1.6.
* @MM_SERIAL_ERROR_SEND_TIMEOUT: Could not write once again to the serial device.
* *
* Serial errors that may be reported by ModemManager. * Serial errors that may be reported by ModemManager.
* *
@@ -536,6 +537,7 @@ typedef enum { /*< underscore_name=mm_serial_error >*/
MM_SERIAL_ERROR_NOT_OPEN = 6, /*< nick=NotOpen >*/ MM_SERIAL_ERROR_NOT_OPEN = 6, /*< nick=NotOpen >*/
MM_SERIAL_ERROR_PARSE_FAILED = 7, /*< nick=ParseFailed >*/ MM_SERIAL_ERROR_PARSE_FAILED = 7, /*< nick=ParseFailed >*/
MM_SERIAL_ERROR_FRAME_NOT_FOUND = 8, /*< nick=FrameNotFound >*/ MM_SERIAL_ERROR_FRAME_NOT_FOUND = 8, /*< nick=FrameNotFound >*/
MM_SERIAL_ERROR_SEND_TIMEOUT = 9, /*< nick=SendTimeout >*/
} MMSerialError; } MMSerialError;
/** /**
+43
View File
@@ -323,6 +323,49 @@
*/ */
#define ID_MM_TTY_AT_PROBE_TRIES "ID_MM_TTY_AT_PROBE_TRIES" #define ID_MM_TTY_AT_PROBE_TRIES "ID_MM_TTY_AT_PROBE_TRIES"
/**
* ID_MM_INITIAL_QMAP_MUX_ID:
*
* This is a device-specific tag that allows users to specify the initial value
* of the QMAP multiplexed id to be used.
*
* An integer value greater or equal than 1 and smaller than 255.
*
* This setting does nothing if the modem doesn't support multiplexing.
*
* Since: 1.26
*/
#define ID_MM_INITIAL_QMAP_MUX_ID "ID_MM_INITIAL_QMAP_MUX_ID"
/**
* ID_MM_AT_NETWORK_TIME_BROKEN:
*
* This is a device-specific tag that allows users to prevent ModemManager from
* attempting to read network time using AT commands, even if the device
* supports them.
*
* An integer value of 1 prevents reading network time with AT commands.
*
* Since: 1.26
*/
#define ID_MM_AT_NETWORK_TIME_BROKEN "ID_MM_AT_NETWORK_TIME_BROKEN"
/**
* ID_MM_MAX_TIMEOUTS:
*
* This is a device-specific tag that allows users to specify the maximum number
* of consecutive command timeouts allowed before the modem is marked as invalid
* and re-probed.
*
* An integer value greater or equal than 0 must be given. The value 0 in this
* tag completely disables the timeout monitoring feature.
*
* If not given, the default value of 10 consecutive timeouts is used.
*
* Since: 1.26
*/
#define ID_MM_MAX_TIMEOUTS "ID_MM_MAX_TIMEOUTS"
/* /*
* The following symbols are deprecated. We don't add them to -compat * The following symbols are deprecated. We don't add them to -compat
* because this -tags file is not really part of the installed API. * because this -tags file is not really part of the installed API.
@@ -115,6 +115,16 @@
--> -->
<property name="ConnectionError" type="(ss)" access="read" /> <property name="ConnectionError" type="(ss)" access="read" />
<!--
DisconnectRequest:
Indicates that the bearer is no longer useable and the connection
manager should terminate it as soon as possible.
Since: 1.26
-->
<property name="DisconnectRequest" type="b" access="read" />
<!-- <!--
Suspended: Suspended:
@@ -103,9 +103,15 @@
<!-- <!--
SendDtmf: SendDtmf:
@dtmf: DTMF tone identifier [0-9A-D*#]. @dtmf: A string of DTMF tone identifiers [0-9A-D*#] and/or pause characters [,].
Send a DTMF tone (Dual Tone Multi-Frequency) (only on supported modem). Send one or more DTMF tones (Dual Tone Multi-Frequency) (only on supported modems).
Before 1.26 only the first character in @dtmf was sent to the modem;
all others were discarded.
Since 1.26 up to 50 tone identifiers are accepted and each will be
sent to the modem in the order given. The comma [,] character pauses
DTMF tones for two-seconds then continues with the remaining characters.
Applicable only if state is <link linkend="MM-CALL-STATE-ACTIVE:CAPS"><constant>MM_CALL_STATE_ACTIVE</constant></link>. Applicable only if state is <link linkend="MM-CALL-STATE-ACTIVE:CAPS"><constant>MM_CALL_STATE_ACTIVE</constant></link>.
@@ -119,7 +125,7 @@
DtmfReceived: DtmfReceived:
@dtmf: DTMF tone identifier [0-9A-D*#]. @dtmf: DTMF tone identifier [0-9A-D*#].
Emitted when a DTMF tone is received (only on supported modem) Emitted when a DTMF tone is received (only on supported modems)
Since: 1.6 Since: 1.6
--> -->
@@ -232,5 +238,18 @@
Since: 1.10 Since: 1.10
--> -->
<property name="AudioFormat" type="a{sv}" access="read" /> <property name="AudioFormat" type="a{sv}" access="read" />
<!--
DtmfToneDuration:
The length of DTMF tones, in milliseconds. Valid range is 100ms to
1000ms and is rounded up to the next 100ms if not evenly divisble
by 100. Set the duration by passing this property to
<link linkend="gdbus-method-org-freedesktop-ModemManager1-Voice.CreateCall">CreateCall()</link>
at call creation time.
Since: 1.26
-->
<property name="DtmfToneDuration" type="u" access="read" />
</interface> </interface>
</node> </node>
@@ -65,5 +65,14 @@
--> -->
<property name="Update" type="u" access="read" /> <property name="Update" type="u" access="read" />
<!--
Language:
The language of the CBM as ISO639 two letter code
Since: 1.26
-->
<property name="Language" type="s" access="read" />
</interface> </interface>
</node> </node>
@@ -922,7 +922,7 @@
In Linux for example, this points to a sysfs path of the usb_device In Linux for example, this points to a sysfs path of the usb_device
object. object.
This value may also be set by the user using the MM_ID_PHYSDEV_UID udev This value may also be set by the user using the ID_MM_PHYSDEV_UID udev
tag (e.g. binding the tag to a specific sysfs path). tag (e.g. binding the tag to a specific sysfs path).
Since: 1.0 Since: 1.0
@@ -973,15 +973,27 @@
<!-- <!--
Ports: Ports:
The list of ports in the modem, given as an array of string and unsigned The list of used ports in the modem, given as an array of string and
integer pairs. The string is the port name or path, and the integer is unsigned integer pairs. The string is the port name or path, and the
the port type given as a integer is the port type given as a
<link linkend="MMModemPortType">MMModemPortType</link> value. <link linkend="MMModemPortType">MMModemPortType</link> value.
Since: 1.0 Since: 1.0
--> -->
<property name="Ports" type="a(su)" access="read" /> <property name="Ports" type="a(su)" access="read" />
<!--
IgnoredPorts:
The list of ignored ports in the modem, given as an array of string and
unsigned integer pairs. The string is the port name or path, and the
integer is the port type given as a
<link linkend="MMModemPortType">MMModemPortType</link> value.
Since: 1.26
-->
<property name="IgnoredPorts" type="a(su)" access="read" />
<!-- <!--
EquipmentIdentifier: EquipmentIdentifier:
+21
View File
@@ -517,6 +517,27 @@ PROPERTY_ERROR_DEFINE_FAILABLE (connection_error,
/*****************************************************************************/ /*****************************************************************************/
/**
* mm_bearer_get_disconnect_request:
* @self: A #MMBearer.
*
* Gets whether a disconnect request is pending for this bearer
*
* Returns: %TRUE if the #MMBearer is waiting for disconnection,
* #FALSE otherwise.
*
* Since: 1.26
*/
gboolean
mm_bearer_get_disconnect_request (MMBearer *self)
{
g_return_val_if_fail (MM_IS_BEARER (self), FALSE);
return mm_gdbus_bearer_get_disconnect_request (MM_GDBUS_BEARER (self));
}
/*****************************************************************************/
/** /**
* mm_bearer_connect_finish: * mm_bearer_connect_finish:
* @self: A #MMBearer. * @self: A #MMBearer.
+2
View File
@@ -76,6 +76,8 @@ gchar *mm_bearer_dup_interface (MMBearer *self);
gboolean mm_bearer_get_connected (MMBearer *self); gboolean mm_bearer_get_connected (MMBearer *self);
gboolean mm_bearer_get_disconnect_request (MMBearer *self);
gboolean mm_bearer_get_reload_stats_supported (MMBearer *self); gboolean mm_bearer_get_reload_stats_supported (MMBearer *self);
gboolean mm_bearer_get_suspended (MMBearer *self); gboolean mm_bearer_get_suspended (MMBearer *self);
+78 -3
View File
@@ -44,10 +44,12 @@
G_DEFINE_TYPE (MMCallProperties, mm_call_properties, G_TYPE_OBJECT) G_DEFINE_TYPE (MMCallProperties, mm_call_properties, G_TYPE_OBJECT)
#define PROPERTY_NUMBER "number" #define PROPERTY_NUMBER "number"
#define PROPERTY_DTMF_TONE_DURATION "dtmf-tone-duration"
struct _MMCallPropertiesPrivate { struct _MMCallPropertiesPrivate {
gchar *number; gchar *number;
guint dtmf_tone_duration;
}; };
/*****************************************************************************/ /*****************************************************************************/
@@ -92,6 +94,43 @@ mm_call_properties_get_number (MMCallProperties *self)
/*****************************************************************************/ /*****************************************************************************/
/**
* mm_call_properties_set_dtmf_tone_duration:
* @self: A #MMCallProperties.
* @duration_ms: The desired duration of DTMF tones in milliseconds.
*
* Sets the DTMF tone duration if supported by the modem.
*
* Since: 1.26
*/
void
mm_call_properties_set_dtmf_tone_duration (MMCallProperties *self,
const guint duration_ms)
{
g_return_if_fail (MM_IS_CALL_PROPERTIES (self));
self->priv->dtmf_tone_duration = duration_ms;
}
/**
* mm_call_properties_get_dtmf_tone_duration:
* @self: A #MMCallProperties.
*
* Gets the desired DTMF tone duration in milliseconds.
*
* Returns: the DTMF tone duration in milliseconds.
*
* Since: 1.26
*/
guint
mm_call_properties_get_dtmf_tone_duration (MMCallProperties *self)
{
g_return_val_if_fail (MM_IS_CALL_PROPERTIES (self), 0);
return self->priv->dtmf_tone_duration;
}
/*****************************************************************************/
/* /*
* mm_call_properties_get_dictionary: (skip) * mm_call_properties_get_dictionary: (skip)
*/ */
@@ -114,6 +153,12 @@ mm_call_properties_get_dictionary (MMCallProperties *self)
PROPERTY_NUMBER, PROPERTY_NUMBER,
g_variant_new_string (self->priv->number)); g_variant_new_string (self->priv->number));
if (self->priv->dtmf_tone_duration)
g_variant_builder_add (&builder,
"{sv}",
PROPERTY_DTMF_TONE_DURATION,
g_variant_new_uint32 (self->priv->dtmf_tone_duration));
return g_variant_ref_sink (g_variant_builder_end (&builder)); return g_variant_ref_sink (g_variant_builder_end (&builder));
} }
@@ -126,6 +171,18 @@ consume_string (MMCallProperties *self,
{ {
if (g_str_equal (key, PROPERTY_NUMBER)) { if (g_str_equal (key, PROPERTY_NUMBER)) {
mm_call_properties_set_number (self, value); mm_call_properties_set_number (self, value);
} else if (g_str_equal (key, PROPERTY_DTMF_TONE_DURATION)) {
guint num;
if (!mm_get_uint_from_str (value, &num)) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"Failed to parse DTMF tone duration from value '%s'",
value);
return FALSE;
}
mm_call_properties_set_dtmf_tone_duration (self, num);
} else { } else {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
@@ -189,11 +246,29 @@ consume_variant (MMCallProperties *properties,
GVariant *value, GVariant *value,
GError **error) GError **error)
{ {
if (g_str_equal (key, PROPERTY_NUMBER)) if (g_str_equal (key, PROPERTY_NUMBER)) {
if (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"Invalid properties dictionary; number not a string");
return FALSE;
}
mm_call_properties_set_number ( mm_call_properties_set_number (
properties, properties,
g_variant_get_string (value, NULL)); g_variant_get_string (value, NULL));
else { } else if (g_str_equal (key, PROPERTY_DTMF_TONE_DURATION)) {
if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"Invalid properties dictionary; dtmf-tone-duration not a uint32");
return FALSE;
}
mm_call_properties_set_dtmf_tone_duration (
properties,
g_variant_get_uint32 (value));
} else {
/* Set error */ /* Set error */
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
+4
View File
@@ -68,6 +68,10 @@ void mm_call_properties_set_number (MMCallProperties *self,
const gchar *text); const gchar *text);
const gchar *mm_call_properties_get_number (MMCallProperties *self); const gchar *mm_call_properties_get_number (MMCallProperties *self);
void mm_call_properties_set_dtmf_tone_duration (MMCallProperties *self,
const guint duration_ms);
guint mm_call_properties_get_dtmf_tone_duration (MMCallProperties *self);
/*****************************************************************************/ /*****************************************************************************/
/* ModemManager/libmm-glib/mmcli specific methods */ /* ModemManager/libmm-glib/mmcli specific methods */
+46
View File
@@ -215,6 +215,52 @@ mm_cbm_get_update (MMCbm *self)
/*****************************************************************************/ /*****************************************************************************/
/**
* mm_cbm_get_language:
* @self: A #MMCbm.
*
* Gets the language the message is in as ISO639 two letter code
*
* <warning>The returned value is only valid until the property changes so it is
* only safe to use this function on the thread where @self was constructed. Use
* mm_cbm_dup_language() if on another thread.</warning>
*
* Returns: (transfer none): The message's language, or %NULL if unknown
*
* Since: 1.26
*/
const gchar *
mm_cbm_get_language (MMCbm *self)
{
g_return_val_if_fail (MM_IS_CBM (self), NULL);
RETURN_NON_EMPTY_CONSTANT_STRING (
mm_gdbus_cbm_get_language (MM_GDBUS_CBM (self)));
}
/**
* mm_cbm_dup_language:
* @self: A #MMCbm.
*
* Gets the language the message is in as ISO639 two letter code
*
* Returns: (transfer full): The message lang, or %NULL if it doesn't contain
* any (e.g. contains data instead). The returned value should be freed with
* g_free().
*
* Since: 1.26
*/
gchar *
mm_cbm_dup_language (MMCbm *self)
{
g_return_val_if_fail (MM_IS_CBM (self), NULL);
RETURN_NON_EMPTY_STRING (
mm_gdbus_cbm_dup_language (MM_GDBUS_CBM (self)));
}
/*****************************************************************************/
static void static void
mm_cbm_init (MMCbm *self) mm_cbm_init (MMCbm *self)
{ {
+3
View File
@@ -75,6 +75,9 @@ guint mm_cbm_get_channel (MMCbm *self);
guint mm_cbm_get_message_code (MMCbm *self); guint mm_cbm_get_message_code (MMCbm *self);
guint mm_cbm_get_update (MMCbm *self); guint mm_cbm_get_update (MMCbm *self);
const gchar *mm_cbm_get_language (MMCbm *self);
gchar *mm_cbm_dup_language (MMCbm *self);
G_END_DECLS G_END_DECLS
#endif /* _MM_CBM_H_ */ #endif /* _MM_CBM_H_ */
+2 -2
View File
@@ -94,7 +94,7 @@ mm_cell_info_gsm_set_operator_id (MMCellInfoGsm *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Location Area Code, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -126,7 +126,7 @@ mm_cell_info_gsm_set_lac (MMCellInfoGsm *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Cell Identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
+3 -3
View File
@@ -101,7 +101,7 @@ mm_cell_info_lte_set_operator_id (MMCellInfoLte *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Tracking Area Code, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -133,7 +133,7 @@ mm_cell_info_lte_set_tac (MMCellInfoLte *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Cell Identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -165,7 +165,7 @@ mm_cell_info_lte_set_ci (MMCellInfoLte *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the physical cell identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
+3 -3
View File
@@ -103,7 +103,7 @@ mm_cell_info_nr5g_set_operator_id (MMCellInfoNr5g *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Tracking Area Code, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -135,7 +135,7 @@ mm_cell_info_nr5g_set_tac (MMCellInfoNr5g *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Cell Identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -167,7 +167,7 @@ mm_cell_info_nr5g_set_ci (MMCellInfoNr5g *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the physical cell identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
+2 -2
View File
@@ -96,7 +96,7 @@ mm_cell_info_tdscdma_set_operator_id (MMCellInfoTdscdma *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Location Area Code, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -128,7 +128,7 @@ mm_cell_info_tdscdma_set_lac (MMCellInfoTdscdma *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Cell Identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
+2 -2
View File
@@ -102,7 +102,7 @@ mm_cell_info_umts_set_operator_id (MMCellInfoUmts *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Location Area Code, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
@@ -134,7 +134,7 @@ mm_cell_info_umts_set_lac (MMCellInfoUmts *self,
* Encoded in upper-case hexadecimal format without leading zeros, * Encoded in upper-case hexadecimal format without leading zeros,
* as specified in 3GPP TS 27.007. * as specified in 3GPP TS 27.007.
* *
* Returns: (transfer none): the MCCMNC, or %NULL if not available. * Returns: (transfer none): the Cell Identifier, or %NULL if not available.
* *
* Since: 1.20 * Since: 1.20
*/ */
+3 -1
View File
@@ -1314,7 +1314,9 @@ mm_common_band_is_utran (MMModemBand band)
gboolean gboolean
mm_common_band_is_eutran (MMModemBand band) mm_common_band_is_eutran (MMModemBand band)
{ {
return (band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_71); return ((band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_71) ||
(band == MM_MODEM_BAND_EUTRAN_85) ||
(band == MM_MODEM_BAND_EUTRAN_106));
} }
gboolean gboolean
+61 -29
View File
@@ -45,16 +45,20 @@ G_DEFINE_TYPE (MMLocationGpsNmea, mm_location_gps_nmea, G_TYPE_OBJECT)
struct _MMLocationGpsNmeaPrivate { struct _MMLocationGpsNmeaPrivate {
GHashTable *traces; GHashTable *traces;
GRegex *sequence_regex; gchar *sequence_last_trace;
gchar *sequence_last_trace_type;
GRegex *sequence_regex;
}; };
/*****************************************************************************/ /*****************************************************************************/
static gboolean static gboolean
check_append_or_replace (MMLocationGpsNmea *self, is_sequence_trace_type (MMLocationGpsNmea *self,
const gchar *trace) const gchar *trace,
gboolean *first)
{ {
g_autoptr(GMatchInfo) match_info = NULL; g_autoptr(GMatchInfo) match_info = NULL;
guint index;
if (G_UNLIKELY (!self->priv->sequence_regex)) if (G_UNLIKELY (!self->priv->sequence_regex))
self->priv->sequence_regex = g_regex_new ("\\$..(?:ALM|GSV|RTE|SFI),(\\d),(\\d).*", self->priv->sequence_regex = g_regex_new ("\\$..(?:ALM|GSV|RTE|SFI),(\\d),(\\d).*",
@@ -62,30 +66,31 @@ check_append_or_replace (MMLocationGpsNmea *self,
0, 0,
NULL); NULL);
*first = FALSE;
if (g_regex_match (self->priv->sequence_regex, trace, 0, &match_info)) { if (g_regex_match (self->priv->sequence_regex, trace, 0, &match_info)) {
guint index; if (mm_get_uint_from_match_info (match_info, 2, &index)) {
*first = (index == 1);
/* If we don't have the first element of a sequence, append */
if (mm_get_uint_from_match_info (match_info, 2, &index) && index != 1)
return TRUE; return TRUE;
}
} }
/* By default, replace */
return FALSE; return FALSE;
} }
static gboolean static gboolean
location_gps_nmea_take_trace (MMLocationGpsNmea *self, location_gps_nmea_take_trace (MMLocationGpsNmea *self,
gchar *trace) gchar *_trace)
{ {
gchar *i; gchar *i;
gchar *trace_type; g_autofree gchar *trace_type = NULL;
g_autofree gchar *trace = _trace;
g_autofree gchar *sequence = NULL;
gboolean first;
gboolean sequence_trace;
i = strchr (trace, ','); i = strchr (trace, ',');
if (!i || i == trace) { if (!i || i == trace)
g_free (trace);
return FALSE; return FALSE;
}
trace_type = g_malloc (i - trace + 1); trace_type = g_malloc (i - trace + 1);
memcpy (trace_type, trace, i - trace); memcpy (trace_type, trace, i - trace);
@@ -94,33 +99,58 @@ location_gps_nmea_take_trace (MMLocationGpsNmea *self,
/* Some traces are part of a SEQUENCE; so we need to decide whether we /* Some traces are part of a SEQUENCE; so we need to decide whether we
* completely replace the previous trace, or we append the new one to * completely replace the previous trace, or we append the new one to
* the already existing list */ * the already existing list */
if (check_append_or_replace (self, trace)) { sequence_trace = is_sequence_trace_type (self, trace, &first);
/* Save previous sequence trace, if
* new trace type is different or this is the first sequence trace */
if (self->priv->sequence_last_trace_type &&
self->priv->sequence_last_trace &&
(g_strcmp0 (self->priv->sequence_last_trace_type, trace_type) ||
(sequence_trace && first))) {
g_hash_table_replace (self->priv->traces,
g_steal_pointer (&self->priv->sequence_last_trace_type),
g_steal_pointer (&self->priv->sequence_last_trace));
}
if (!sequence_trace) {
g_hash_table_replace (self->priv->traces,
g_steal_pointer (&trace_type),
g_steal_pointer (&trace));
return TRUE;
}
/* Process the trace as part of a sequence. */
if (first) {
/* Record first record in the sequence */
sequence = g_steal_pointer (&trace);
} else {
/* Append */ /* Append */
const gchar *previous; const gchar *previous = self->priv->sequence_last_trace;
if (!previous)
previous = g_hash_table_lookup (self->priv->traces, trace_type);
previous = g_hash_table_lookup (self->priv->traces, trace_type);
if (previous) { if (previous) {
gchar *sequence;
/* Skip the trace if we already have it there */ /* Skip the trace if we already have it there */
if (strstr (previous, trace)) { if (strstr (previous, trace))
g_free (trace_type);
g_free (trace);
return TRUE; return TRUE;
}
sequence = g_strdup_printf ("%s%s%s", sequence = g_strdup_printf ("%s%s%s",
previous, previous,
g_str_has_suffix (previous, "\r\n") ? "" : "\r\n", g_str_has_suffix (previous, "\r\n") ? "" : "\r\n",
trace); trace);
g_free (trace); } else {
trace = sequence; /* No previous records, record first record in the sequence */
sequence = g_steal_pointer (&trace);
} }
} }
g_hash_table_replace (self->priv->traces, g_clear_pointer (&self->priv->sequence_last_trace, g_free);
trace_type, self->priv->sequence_last_trace = g_steal_pointer (&sequence);
trace);
g_clear_pointer (&self->priv->sequence_last_trace_type, g_free);
self->priv->sequence_last_trace_type = g_steal_pointer (&trace_type);
return TRUE; return TRUE;
} }
@@ -291,6 +321,8 @@ finalize (GObject *object)
g_hash_table_destroy (self->priv->traces); g_hash_table_destroy (self->priv->traces);
if (self->priv->sequence_regex) if (self->priv->sequence_regex)
g_regex_unref (self->priv->sequence_regex); g_regex_unref (self->priv->sequence_regex);
g_free (self->priv->sequence_last_trace);
g_free (self->priv->sequence_last_trace_type);
G_OBJECT_CLASS (mm_location_gps_nmea_parent_class)->finalize (object); G_OBJECT_CLASS (mm_location_gps_nmea_parent_class)->finalize (object);
} }
+42 -1
View File
@@ -47,6 +47,7 @@ struct _MMModemPrivate {
GMutex mutex; GMutex mutex;
PROPERTY_ARRAY_DECLARE (ports) PROPERTY_ARRAY_DECLARE (ports)
PROPERTY_ARRAY_DECLARE (ignored_ports)
PROPERTY_ARRAY_DECLARE (supported_modes) PROPERTY_ARRAY_DECLARE (supported_modes)
PROPERTY_ARRAY_DECLARE (supported_capabilities) PROPERTY_ARRAY_DECLARE (supported_capabilities)
PROPERTY_ARRAY_DECLARE (supported_bands) PROPERTY_ARRAY_DECLARE (supported_bands)
@@ -984,7 +985,7 @@ mm_modem_dup_primary_port (MMModem *self)
* mm_modem_port_info_array_free() when no longer needed. * mm_modem_port_info_array_free() when no longer needed.
* @n_ports: (out): Return location for the number of values in @ports. * @n_ports: (out): Return location for the number of values in @ports.
* *
* Gets the list of ports in the modem. * Gets the list of used ports in the modem.
* *
* Returns: %TRUE if @ports and @n_ports are set, %FALSE otherwise. * Returns: %TRUE if @ports and @n_ports are set, %FALSE otherwise.
* *
@@ -999,6 +1000,44 @@ PROPERTY_ARRAY_DEFINE_DEEP (ports,
/*****************************************************************************/ /*****************************************************************************/
/**
* mm_modem_peek_ignored_ports:
* @self: A #MMModem.
* @ports: (out) (array length=n_ports) (transfer none): Return location for the
* array of #MMModemPortInfo values. Do not free the returned value, it is
* owned by @self.
* @n_ports: (out): Return location for the number of values in @ports.
*
* Gets the list of ignored ports in the modem.
*
* Returns: %TRUE if @ports and @n_ports are set, %FALSE otherwise.
*
* Since: 1.26
*/
/**
* mm_modem_get_ignored_ports:
* @self: A #MMModem.
* @ports: (out) (array length=n_ports): Return location for the array of
* #MMModemPortInfo values. The returned array should be freed with
* mm_modem_port_info_array_free() when no longer needed.
* @n_ports: (out): Return location for the number of values in @ports.
*
* Gets the list of ignored ports in the modem.
*
* Returns: %TRUE if @ports and @n_ports are set, %FALSE otherwise.
*
* Since: 1.26
*/
PROPERTY_ARRAY_DEFINE_DEEP (ignored_ports,
Modem, modem, MODEM,
MMModemPortInfo,
mm_common_ports_variant_to_garray,
mm_common_ports_garray_to_array)
/*****************************************************************************/
/** /**
* mm_modem_get_equipment_identifier: * mm_modem_get_equipment_identifier:
* @self: A #MMModem. * @self: A #MMModem.
@@ -3430,6 +3469,7 @@ mm_modem_init (MMModem *self)
g_mutex_init (&self->priv->mutex); g_mutex_init (&self->priv->mutex);
PROPERTY_INITIALIZE (ports, "ports") PROPERTY_INITIALIZE (ports, "ports")
PROPERTY_INITIALIZE (ignored_ports, "ignored-ports")
PROPERTY_INITIALIZE (supported_modes, "supported-modes") PROPERTY_INITIALIZE (supported_modes, "supported-modes")
PROPERTY_INITIALIZE (supported_capabilities, "supported-capabilities") PROPERTY_INITIALIZE (supported_capabilities, "supported-capabilities")
PROPERTY_INITIALIZE (supported_bands, "supported-bands") PROPERTY_INITIALIZE (supported_bands, "supported-bands")
@@ -3445,6 +3485,7 @@ finalize (GObject *object)
g_mutex_clear (&self->priv->mutex); g_mutex_clear (&self->priv->mutex);
PROPERTY_ARRAY_FINALIZE (ports) PROPERTY_ARRAY_FINALIZE (ports)
PROPERTY_ARRAY_FINALIZE (ignored_ports)
PROPERTY_ARRAY_FINALIZE (supported_modes) PROPERTY_ARRAY_FINALIZE (supported_modes)
PROPERTY_ARRAY_FINALIZE (supported_capabilities) PROPERTY_ARRAY_FINALIZE (supported_capabilities)
PROPERTY_ARRAY_FINALIZE (supported_bands) PROPERTY_ARRAY_FINALIZE (supported_bands)
+8
View File
@@ -138,6 +138,14 @@ gboolean mm_modem_get_ports (MMModem *self,
MMModemPortInfo **ports, MMModemPortInfo **ports,
guint *n_ports); guint *n_ports);
gboolean mm_modem_peek_ignored_ports (MMModem *self,
const MMModemPortInfo **ports,
guint *n_ports);
gboolean mm_modem_get_ignored_ports (MMModem *self,
MMModemPortInfo **ports,
guint *n_ports);
const gchar *mm_modem_get_equipment_identifier (MMModem *self); const gchar *mm_modem_get_equipment_identifier (MMModem *self);
gchar *mm_modem_dup_equipment_identifier (MMModem *self); gchar *mm_modem_dup_equipment_identifier (MMModem *self);
+1
View File
@@ -4,6 +4,7 @@
test_units = [ test_units = [
'common-helpers', 'common-helpers',
'pco', 'pco',
'location-gps-nmea',
] ]
foreach test_unit: test_units foreach test_unit: test_units
+376
View File
@@ -0,0 +1,376 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2026 Dan Williams <dan@ioncontrol.co>
* Copyright (C) 2026 Andrey Skvortsov <andrej.skvortzov@gmail.com>
*/
#include <glib.h>
#include <libmm-glib.h>
#include <string.h>
static gchar *
combine_traces (const gchar *traces[],
const guint num_traces,
gboolean trailing_crlf)
{
guint i;
GString *all = g_string_new ("");
for (i = 0; i < num_traces; i++) {
g_string_append (all, traces[i]);
if (i != num_traces - 1) {
g_string_append_c (all, '\r');
g_string_append_c (all, '\n');
}
}
return g_string_free (all, FALSE);
}
static gchar *
get_trace_type (const gchar *trace)
{
gchar *trace_type = g_strdup (trace);
gchar *p;
p = strchr (trace_type, ',');
g_assert (p);
*p = '\0';
return trace_type;
}
/**************************************************************/
static void
test_round_trip (void)
{
MMLocationGpsNmea *nmea;
g_autofree gchar *combined_traces;
g_autofree gchar **all_traces;
GError *error = NULL;
guint traces_len;
guint i, j;
#define TRACE0 "$GNGGA,001626.000,,,,,0,00,25.5,,,,,,*79"
#define TRACE1 "$GPGSV,2,1,08,04,41,189,,07,49,311,28,08,67,149,25,09,55,237,18,0*68"
#define TRACE2 "$GPGSV,2,2,08,16,31,057,,21,05,153,,27,56,070,,30,19,303,,0*61"
#define TRACE3 "$BDGSV,1,1,00,0*74"
#define TRACE4 "$GNGGA,001626.000,,,,,0,00,25.5,,,,,,*79"
static const char *traces[] = { TRACE0, TRACE1, TRACE2, TRACE3, TRACE4 };
static const char *expected_traces[] = {
TRACE1 "\r\n" TRACE2,
TRACE3,
TRACE4,
};
combined_traces = combine_traces (traces, G_N_ELEMENTS (traces), TRUE);
nmea = mm_location_gps_nmea_new_from_string_variant (g_variant_new_string (combined_traces), &error);
g_assert_no_error (error);
for (i = 0; i < G_N_ELEMENTS (expected_traces); i++) {
g_autofree gchar *trace_type = get_trace_type (expected_traces[i]);
const gchar * trace;
trace = mm_location_gps_nmea_get_trace (nmea, trace_type);
g_assert_cmpstr (trace, ==, expected_traces[i]);
}
all_traces = mm_location_gps_nmea_get_traces (nmea);
traces_len = g_strv_length (all_traces);
g_assert_cmpint (traces_len, ==, G_N_ELEMENTS (expected_traces));
/* For each expected trace type, assert that trace type exists in the
* found traces, and matches the expected trace.
*/
for (i = 0; i < G_N_ELEMENTS (expected_traces); i++) {
g_autofree gchar *expected_type = get_trace_type (expected_traces[i]);
gboolean found = FALSE;
for (j = 0; j < traces_len; j++) {
g_autofree gchar *found_type = get_trace_type (all_traces[j]);
if (!g_strcmp0 (found_type, expected_type)) {
/* Found the trace type; compare */
g_assert_cmpstr (all_traces[j], ==, expected_traces[i]);
found = TRUE;
}
}
g_assert_true (found);
}
}
#undef TRACE0
#undef TRACE1
#undef TRACE2
#undef TRACE3
#undef TRACE4
/**************************************************************/
static void
test_append_sequence (void)
{
MMLocationGpsNmea *nmea;
GError *error = NULL;
g_autofree gchar *combined = NULL;
#define TRACE0 "$GNGGA,001626.000,,,,,0,00,25.5,,,,,,*79"
#define TRACE1 "$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68"
#define TRACE2 "$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53"
#define TRACE3 "$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60"
#define TRACE4 "$BDGSV,1,1,00,0*74"
#define TRACE5 "$GNGGA,001626.000,,,,,0,00,25.6,,,,,,*79"
#define GPGSV_TYPE "$GPGSV"
#define BDGSV_TYPE "$BDGSV"
#define GNGGA_TYPE "$GNGGA"
static const gchar *gpgsvs[] = { TRACE1, TRACE2, TRACE3 };
nmea = mm_location_gps_nmea_new_from_string_variant (g_variant_new_string (TRACE0), &error);
g_assert_no_error (error);
/* No part of the GPGSV sequence should be found in traces until a new
* trace type is added.
*/
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE1));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE2));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE3));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
/* Add a new type, but it's also a sequence so it won't be found yet */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE4));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, BDGSV_TYPE), ==, NULL);
/* New type was just added, now we should find the $GPGSV too */
combined = combine_traces (gpgsvs, G_N_ELEMENTS (gpgsvs), FALSE);
g_assert (combined);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined);
/* Add a non-sequence trace */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE5));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GNGGA_TYPE), ==, TRACE5);
/* And now we should find the $BDGSV */
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, BDGSV_TYPE), ==, TRACE4);
}
#undef TRACE0
#undef TRACE1
#undef TRACE2
#undef TRACE3
#undef TRACE4
#undef TRACE5
/**************************************************************/
static void
test_append_sequence_interleaved (void)
{
MMLocationGpsNmea *nmea;
GError *error = NULL;
g_autofree gchar *combined_start = NULL;
g_autofree gchar *combined_full = NULL;
#define TRACE0 "$GNGGA,001626.000,,,,,0,00,25.5,,,,,,*79"
#define TRACE1 "$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68"
#define TRACE2 "$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53"
#define TRACE3 "$BDGSV,1,1,00,0*74"
#define TRACE4 "$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60"
#define TRACE5 "$GNGGA,001626.000,,,,,0,00,25.6,,,,,,*79"
#define GPGSV_TYPE "$GPGSV"
#define BDGSV_TYPE "$BDGSV"
#define GNGGA_TYPE "$GNGGA"
static const gchar *gpgsvs_start[] = { TRACE1, TRACE2 };
static const gchar *gpgsvs_full[] = { TRACE1, TRACE2, TRACE4 };
nmea = mm_location_gps_nmea_new_from_string_variant (g_variant_new_string (TRACE0), &error);
g_assert_no_error (error);
/* No part of the GPGSV sequence should be found in traces until a new
* trace type is added.
*/
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE1));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE2));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
/* Add a new type, but it's also a sequence so it won't be found yet */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE3));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, BDGSV_TYPE), ==, NULL);
/* New type was just added, now first part of $GPGSV should be available */
combined_start = combine_traces (gpgsvs_start, G_N_ELEMENTS (gpgsvs_start), FALSE);
g_assert (combined_start);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined_start);
/* Add third GPGSV, but it won't be found yet, only previous GPGSV records
* But $BDGSV should be found now.
*/
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE4));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined_start);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, BDGSV_TYPE), ==, TRACE3);
/* Add a non-sequence trace */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE5));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GNGGA_TYPE), ==, TRACE5);
/* New type was just added, now we should find full $GPGSV sequence */
combined_full = combine_traces (gpgsvs_full, G_N_ELEMENTS (gpgsvs_full), FALSE);
g_assert (combined_full);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined_full);
}
#undef TRACE0
#undef TRACE1
#undef TRACE2
#undef TRACE3
#undef TRACE4
#undef TRACE5
/**************************************************************/
static void
test_append_multiple_sequences (void)
{
MMLocationGpsNmea *nmea;
GError *error = NULL;
g_autofree gchar *combined1 = NULL;
g_autofree gchar *combined2 = NULL;
#define TRACE0 "$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68"
#define TRACE1 "$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53"
#define TRACE2 "$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60"
#define TRACE3 "$GPGSV,3,1,12,01,35,282,23,02,68,264,,03,02,243,,08,35,206,,1*69"
#define TRACE4 "$GPGSV,3,2,12,10,46,074,28,14,16,312,,17,,,,22,16,327,,1*59"
#define TRACE5 "$GPGSV,3,3,12,23,07,068,18,24,15,030,,27,14,181,,32,51,120,,1*69"
#define TRACE6 "$GPGSV,3,1,12,01,35,282,25,02,68,264,,03,02,243,,08,35,206,,1*6F"
#define GPGSV_TYPE "$GPGSV"
static const gchar *gpgsvs1[] = { TRACE0, TRACE1, TRACE2 };
static const gchar *gpgsvs2[] = { TRACE3, TRACE4, TRACE5 };
/* No part of the GPGSV sequence should be found in traces until a new
* trace sequence is added.
*/
nmea = mm_location_gps_nmea_new_from_string_variant (g_variant_new_string (TRACE0), &error);
g_assert_no_error (error);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE1));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE2));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
/* Add first record for next sequence, old sequence should be available */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE3));
combined1 = combine_traces (gpgsvs1, G_N_ELEMENTS (gpgsvs1), FALSE);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined1);
/* No part of new the GPGSV sequence should be found in traces until a new
* trace sequence is added.
*/
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE4));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined1);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE5));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined1);
/* Add first record for next sequence, updated sequence should be available */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE6));
combined2 = combine_traces (gpgsvs2, G_N_ELEMENTS (gpgsvs2), FALSE);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined2);
}
#undef TRACE0
#undef TRACE1
#undef TRACE2
#undef TRACE3
#undef TRACE4
#undef TRACE5
#undef TRACE6
/**************************************************************/
static void
test_start_from_incomplete_sequence (void)
{
MMLocationGpsNmea *nmea;
GError *error = NULL;
g_autofree gchar *combined = NULL;
#define TRACE0 "$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60"
#define TRACE1 "$GNGGA,001626.000,,,,,0,00,25.5,,,,,,*79"
#define TRACE2 "$GPGSV,3,1,12,01,35,282,,02,68,264,,03,02,243,,08,35,206,,1*68"
#define TRACE3 "$GPGSV,3,2,12,10,46,074,,14,16,312,,17,,,,22,16,327,,1*53"
#define TRACE4 "$GPGSV,3,3,12,23,07,068,,24,15,030,,27,14,181,,32,51,120,,1*60"
#define TRACE5 "$GNGGA,001626.000,,,,,0,00,25.6,,,,,,*7A"
#define GPGSV_TYPE "$GPGSV"
#define GNGGA_TYPE "$GNGGA"
static const gchar *gpgsvs[] = { TRACE2, TRACE3, TRACE4 };
/* Start sequence not from the first record */
nmea = mm_location_gps_nmea_new_from_string_variant (g_variant_new_string (TRACE0), &error);
g_assert_no_error (error);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, NULL);
/* New type was just added, now we should find $GPGSV sequence */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE1));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GNGGA_TYPE), ==, TRACE1);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, TRACE0);
/* Add first record for next sequence, old sequence should be available */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE2));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, TRACE0);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE3));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, TRACE0);
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE4));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, TRACE0);
/* New type was just added, now we should find new full $GPGSV sequence */
g_assert (mm_location_gps_nmea_add_trace (nmea, TRACE5));
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GNGGA_TYPE), ==, TRACE5);
combined = combine_traces (gpgsvs, G_N_ELEMENTS (gpgsvs), FALSE);
g_assert_cmpstr (mm_location_gps_nmea_get_trace (nmea, GPGSV_TYPE), ==, combined);
}
#undef TRACE0
#undef TRACE1
#undef TRACE2
#undef TRACE3
#undef TRACE4
#undef TRACE5
/**************************************************************/
int main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/MM/Location/GPS/NMEA/round-trip", test_round_trip);
g_test_add_func ("/MM/Location/GPS/NMEA/append-sequence", test_append_sequence);
g_test_add_func ("/MM/Location/GPS/NMEA/append-sequence-interleaved", test_append_sequence_interleaved);
g_test_add_func ("/MM/Location/GPS/NMEA/append-multiple-sequences", test_append_multiple_sequences);
g_test_add_func ("/MM/Location/GPS/NMEA/start-from-incomplete-sequence", test_start_from_incomplete_sequence);
return g_test_run ();
}
+12
View File
@@ -672,12 +672,24 @@ qcdm_cmd_pilot_sets_result (const char *buf, size_t len, int *out_error)
QcdmResult *result = NULL; QcdmResult *result = NULL;
DMCmdPilotSetsRsp *rsp = (DMCmdPilotSetsRsp *) buf; DMCmdPilotSetsRsp *rsp = (DMCmdPilotSetsRsp *) buf;
size_t sets_len; size_t sets_len;
size_t total_count;
qcdm_return_val_if_fail (buf != NULL, NULL); qcdm_return_val_if_fail (buf != NULL, NULL);
if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), out_error)) if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), out_error))
return NULL; return NULL;
/* Validate that the modem-supplied counts fit in the fixed sets[] array
* and in the actually-received response. */
total_count = (size_t) rsp->active_count + rsp->candidate_count + rsp->neighbor_count;
if (total_count > (sizeof (rsp->sets) / sizeof (rsp->sets[0])) ||
((sizeof (*rsp) - sizeof (rsp->sets)) + total_count * sizeof (DMCmdPilotSetsSet)) > len) {
qcdm_err (0, "DM Pilot Sets response counts out of range");
if (out_error)
*out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
return NULL;
}
result = qcdm_result_new (); result = qcdm_result_new ();
sets_len = rsp->active_count * sizeof (DMCmdPilotSetsSet); sets_len = rsp->active_count * sizeof (DMCmdPilotSetsSet);
+16
View File
@@ -88,6 +88,7 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro
QcdmResult *result = NULL; QcdmResult *result = NULL;
DMLogItemEvdoPilotSetsV2 *pilot_sets; DMLogItemEvdoPilotSetsV2 *pilot_sets;
DMCmdLog *log_cmd = (DMCmdLog *) buf; DMCmdLog *log_cmd = (DMCmdLog *) buf;
size_t avail;
size_t sets_len; size_t sets_len;
qcdm_return_val_if_fail (buf != NULL, NULL); qcdm_return_val_if_fail (buf != NULL, NULL);
@@ -97,6 +98,21 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro
pilot_sets = (DMLogItemEvdoPilotSetsV2 *) log_cmd->data; pilot_sets = (DMLogItemEvdoPilotSetsV2 *) log_cmd->data;
/* Ensure the flexible sets[] array actually contains as many entries as
* the header claims; the modem fully controls these counts. check_log_item()
* guarantees len >= sizeof (DMCmdLog) + sizeof (DMLogItemEvdoPilotSetsV2),
* so 'avail' cannot underflow.*/
avail = len - sizeof (DMCmdLog) - sizeof (DMLogItemEvdoPilotSetsV2);
sets_len = ((size_t) pilot_sets->active_count
+ (size_t) pilot_sets->candidate_count
+ (size_t) pilot_sets->remaining_count)
* sizeof (DMLogItemEvdoPilotSetsV2Pilot);
if (sets_len > avail) {
if (out_error)
*out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
return NULL;
}
result = qcdm_result_new (); result = qcdm_result_new ();
sets_len = pilot_sets->active_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot); sets_len = pilot_sets->active_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);
+4 -4
View File
@@ -95,16 +95,16 @@ qcdm_send (int fd, char *buf, size_t len)
while (i < len) { while (i < len) {
errno = 0; errno = 0;
status = write (fd, &buf[i], 1); status = write (fd, &buf[i], len - i);
if (status < 0) { if (status <= 0) {
if (errno == EAGAIN) { if (errno == EAGAIN || status == 0) {
eagain_count--; eagain_count--;
if (eagain_count <= 0) if (eagain_count <= 0)
return FALSE; return FALSE;
} else } else
assert (errno == 0); assert (errno == 0);
} else } else
i++; i += status;
usleep (1000); usleep (1000);
} }
+4 -4
View File
@@ -95,16 +95,16 @@ qcdm_send (int fd, char *buf, size_t len)
while (i < len) { while (i < len) {
errno = 0; errno = 0;
status = write (fd, &buf[i], 1); status = write (fd, &buf[i], len - i);
if (status < 0) { if (status <= 0) {
if (errno == EAGAIN) { if (errno == EAGAIN || status == 0) {
eagain_count--; eagain_count--;
if (eagain_count <= 0) if (eagain_count <= 0)
return FALSE; return FALSE;
} else } else
assert (errno == 0); assert (errno == 0);
} else } else
i++; i += status;
usleep (1000); usleep (1000);
} }
+4 -4
View File
@@ -96,16 +96,16 @@ qcdm_send (int fd, char *buf, size_t len)
while (i < len) { while (i < len) {
errno = 0; errno = 0;
status = write (fd, &buf[i], 1); status = write (fd, &buf[i], len - i);
if (status < 0) { if (status <= 0) {
if (errno == EAGAIN) { if (errno == EAGAIN || status == 0) {
eagain_count--; eagain_count--;
if (eagain_count <= 0) if (eagain_count <= 0)
return FALSE; return FALSE;
} else } else
assert (errno == 0); assert (errno == 0);
} else } else
i++; i += status;
usleep (1000); usleep (1000);
} }
+68 -16
View File
@@ -3,14 +3,14 @@
project( project(
'ModemManager', 'c', 'ModemManager', 'c',
version: '1.24.2', version: '1.25.95',
license: 'GPL2', license: 'GPL2',
default_options: [ default_options: [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
'c_std=gnu89', 'c_std=gnu89',
'warning_level=2', 'warning_level=2',
], ],
meson_version: '>= 0.53.0', meson_version: '>= 0.60.0',
) )
meson_version = meson.version() meson_version = meson.version()
@@ -31,11 +31,13 @@ mm_includedir = get_option('includedir')
mm_libdir = get_option('libdir') mm_libdir = get_option('libdir')
mm_sbindir = get_option('sbindir') mm_sbindir = get_option('sbindir')
mm_sysconfdir = get_option('sysconfdir') mm_sysconfdir = get_option('sysconfdir')
mm_sharedstatedir = get_option('sharedstatedir')
mm_pkgdatadir = mm_datadir / mm_name mm_pkgdatadir = mm_datadir / mm_name
mm_pkgincludedir = mm_includedir / mm_name mm_pkgincludedir = mm_includedir / mm_name
mm_pkglibdir = mm_libdir / mm_name mm_pkglibdir = mm_libdir / mm_name
mm_pkgsysconfdir = mm_sysconfdir / mm_name mm_pkgsysconfdir = mm_sysconfdir / mm_name
mm_pkgsharedstatedir = mm_sharedstatedir / mm_name
mm_glib_name = 'libmm-glib' mm_glib_name = 'libmm-glib'
mm_glib_pkgincludedir = mm_includedir / mm_glib_name mm_glib_pkgincludedir = mm_includedir / mm_glib_name
@@ -142,7 +144,24 @@ if get_option('buildtype').contains('debug')
]) ])
endif endif
add_project_arguments(common_args + cc_args, language: 'c') # Look for existing -DMM_DISABLE_DEPRECATED in CFLAGS
pymodule = import('python3')
python3 = pymodule.find_python()
res = run_command(python3, '-c', 'import os; print(os.environ["CFLAGS"])')
cflags_disable_deprecated = false
if res.returncode() == 0 and res.stdout().contains('-DMM_DISABLE_DEPRECATED')
cflags_disable_deprecated = true
endif
# Handle deprecation enable/disable
if get_option('deprecated')
cc_args += cc.get_supported_arguments('-Wno-deprecated-declarations')
else
if cflags_disable_deprecated == false
cc_args += '-DMM_DISABLE_DEPRECATED'
endif
cc_args += cc.get_supported_arguments('-Wdeprecated-declarations')
endif
glib_version = '2.56' glib_version = '2.56'
@@ -168,21 +187,21 @@ glib_deps = declare_dependency(
# DBus system directory # DBus system directory
dbus_dep = dependency('dbus-1') dbus_dep = dependency('dbus-1')
dbus_interfaces_dir = dbus_dep.get_pkgconfig_variable('interfaces_dir', define_variable: ['datadir', mm_datadir]) dbus_interfaces_dir = dbus_dep.get_variable(pkgconfig: 'interfaces_dir', pkgconfig_define: ['datadir', mm_datadir])
dbus_system_bus_services_dir = dbus_dep.get_pkgconfig_variable('system_bus_services_dir', define_variable: ['datadir', mm_datadir]) dbus_system_bus_services_dir = dbus_dep.get_variable(pkgconfig: 'system_bus_services_dir', pkgconfig_define: ['datadir', mm_datadir])
dbus_policy_dir = get_option('dbus_policy_dir') dbus_policy_dir = get_option('dbus_policy_dir')
if dbus_policy_dir == '' if dbus_policy_dir == ''
dbus_policy_dir = dbus_dep.get_pkgconfig_variable('sysconfdir', define_variable: ['sysconfdir', mm_sysconfdir]) / 'dbus-1/system.d' dbus_policy_dir = dbus_dep.get_variable(pkgconfig: 'sysconfdir', pkgconfig_define: ['sysconfdir', mm_sysconfdir]) / 'dbus-1/system.d'
endif endif
enable_bash_completion = get_option('bash_completion') enable_bash_completion = get_option('bash_completion')
if enable_bash_completion if enable_bash_completion
bash_completion_dep = dependency('bash-completion') bash_completion_dep = dependency('bash-completion')
bash_completion_completionsdir = bash_completion_dep.get_pkgconfig_variable( bash_completion_completionsdir = bash_completion_dep.get_variable(
'completionsdir', pkgconfig: 'completionsdir',
# bash-completion 2.10 changed the substitutions # bash-completion 2.10 changed the substitutions
define_variable: bash_completion_dep.version().version_compare('>= 2.10') ? ['datadir', mm_datadir] : ['prefix', mm_prefix], pkgconfig_define: bash_completion_dep.version().version_compare('>= 2.10') ? ['datadir', mm_datadir] : ['prefix', mm_prefix],
) )
endif endif
@@ -197,7 +216,7 @@ config_h.set('WITH_UDEV', enable_udev)
udev_udevdir = get_option('udevdir') udev_udevdir = get_option('udevdir')
if udev_udevdir == '' if udev_udevdir == ''
assert(enable_udev, 'udevdir must be explicitly given if udev support is disabled') assert(enable_udev, 'udevdir must be explicitly given if udev support is disabled')
udev_udevdir = dependency('udev').get_pkgconfig_variable('udevdir') udev_udevdir = dependency('udev').get_variable(pkgconfig: 'udevdir')
endif endif
udev_rulesdir = udev_udevdir / 'rules.d' udev_rulesdir = udev_udevdir / 'rules.d'
@@ -207,7 +226,7 @@ install_systemdunitdir = (systemd_systemdsystemunitdir != 'no')
if install_systemdunitdir and systemd_systemdsystemunitdir == '' if install_systemdunitdir and systemd_systemdsystemunitdir == ''
systemd_dep = dependency('systemd', not_found_message: 'systemd required but not found, please provide a valid systemd user unit dir or disable it') systemd_dep = dependency('systemd', not_found_message: 'systemd required but not found, please provide a valid systemd user unit dir or disable it')
systemd_systemdsystemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir', define_variable: ['root_prefix', mm_prefix]) systemd_systemdsystemunitdir = systemd_dep.get_variable(pkgconfig: 'systemdsystemunitdir', pkgconfig_define: ['root_prefix', mm_prefix])
endif endif
# Suspend/resume support # Suspend/resume support
@@ -240,7 +259,7 @@ enable_polkit = (polkit_opt != 'no')
if enable_polkit if enable_polkit
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.97', not_found_message: 'PolicyKit development headers are required') polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.97', not_found_message: 'PolicyKit development headers are required')
polkit_gobject_policydir = polkit_gobject_dep.get_pkgconfig_variable('policydir', define_variable: ['prefix', mm_prefix]) polkit_gobject_policydir = polkit_gobject_dep.get_variable(pkgconfig: 'policydir', pkgconfig_define: ['prefix', mm_prefix])
policy_conf = {'MM_DEFAULT_USER_POLICY': (polkit_opt == 'permissive' ? 'yes' : 'auth_self_keep')} policy_conf = {'MM_DEFAULT_USER_POLICY': (polkit_opt == 'permissive' ? 'yes' : 'auth_self_keep')}
endif endif
@@ -259,14 +278,40 @@ config_h.set('WITH_BUILTIN_PLUGINS', enable_builtin_plugins)
# MBIM support (enabled by default) # MBIM support (enabled by default)
enable_mbim = get_option('mbim') enable_mbim = get_option('mbim')
if enable_mbim if enable_mbim
mbim_glib_dep = dependency('mbim-glib', version: '>= 1.32.0') mbim_glib_dep = dependency('mbim-glib', version: '>= 1.32.0',
required: not get_option('subproject-fallback'))
if not mbim_glib_dep.found() and get_option('subproject-fallback')
mbim_glib_proj = subproject('libmbim',
default_options: ['man=false',
'introspection=false',
'bash_completion=false',
])
mbim_glib_dep = mbim_glib_proj.get_variable('libmbim_glib_dep')
endif
# MM should never use deprecated symbols from the libmibm
cc_args += '-DMBIM_DISABLE_DEPRECATED'
endif endif
config_h.set('WITH_MBIM', enable_mbim) config_h.set('WITH_MBIM', enable_mbim)
# QMI support (enabled by default) # QMI support (enabled by default)
enable_qmi = get_option('qmi') enable_qmi = get_option('qmi')
if enable_qmi if enable_qmi
qmi_glib_dep = dependency('qmi-glib', version: '>= 1.36.0') qmi_glib_dep = dependency('qmi-glib', version: '>= 1.37.95',
required: not get_option('subproject-fallback'))
if not qmi_glib_dep.found() and get_option('subproject-fallback')
qmi_glib_proj = subproject('libqmi',
default_options: ['man=false',
'mbim_qmux=false',
'introspection=false',
'bash_completion=false',
])
qmi_glib_dep = qmi_glib_proj.get_variable('libqmi_glib_dep')
endif
# MM should never use deprecated symbols from libqmi
cc_args += '-DQMI_DISABLE_DEPRECATED'
endif endif
config_h.set('WITH_QMI', enable_qmi) config_h.set('WITH_QMI', enable_qmi)
@@ -274,11 +319,18 @@ config_h.set('WITH_QMI', enable_qmi)
enable_qrtr = get_option('qrtr') enable_qrtr = get_option('qrtr')
if enable_qrtr if enable_qrtr
assert(enable_qmi, 'QRTR support requires QMI enabled') assert(enable_qmi, 'QRTR support requires QMI enabled')
assert(qmi_glib_dep.get_pkgconfig_variable('qmi_qrtr_supported').to_int().is_odd(), 'Couldn\'t find QRTR support in qmi-glib.') if qmi_glib_dep.type_name() == 'internal'
qmi_qrtr_supported = qmi_glib_proj.get_variable('enable_qrtr')
else
qmi_qrtr_supported = qmi_glib_dep.get_variable(pkgconfig: 'qmi_qrtr_supported')
endif
assert(qmi_qrtr_supported.to_int().is_odd(), 'Couldn\'t find QRTR support in qmi-glib.')
qrtr_glib_dep = dependency('qrtr-glib', version: '>= 1.0.0') qrtr_glib_dep = dependency('qrtr-glib', version: '>= 1.0.0')
endif endif
config_h.set('WITH_QRTR', enable_qrtr) config_h.set('WITH_QRTR', enable_qrtr)
add_project_arguments(common_args + cc_args, language: 'c')
# Distribution version string # Distribution version string
dist_version = get_option('dist_version') dist_version = get_option('dist_version')
if dist_version != '' if dist_version != ''
@@ -356,7 +408,7 @@ plugins_options_reqs = {
'pantech': {'available': true, 'shared': []}, 'pantech': {'available': true, 'shared': []},
'qcom-soc': {'available': enable_qmi, 'shared': []}, 'qcom-soc': {'available': enable_qmi, 'shared': []},
'quectel': {'available': true, 'shared': ['quectel']}, 'quectel': {'available': true, 'shared': ['quectel']},
'rolling': {'available': true, 'shared': ['fibocom']}, 'rolling': {'available': true, 'shared': ['fibocom', 'mtk']},
'samsung': {'available': true, 'shared': ['icera']}, 'samsung': {'available': true, 'shared': ['icera']},
'sierra-legacy': {'available': true, 'shared': ['icera', 'sierra']}, 'sierra-legacy': {'available': true, 'shared': ['icera', 'sierra']},
'sierra': {'available': true, 'shared': ['xmm']}, 'sierra': {'available': true, 'shared': ['xmm']},
+3
View File
@@ -6,6 +6,7 @@ option('udevdir', type: 'string', value: '', description: 'udev base directory')
option('examples', type: 'boolean', value: true, description: 'install examples') option('examples', type: 'boolean', value: true, description: 'install examples')
option('tests', type: 'boolean', value: true, description: 'enable tests') option('tests', type: 'boolean', value: true, description: 'enable tests')
option('subproject-fallback', type: 'boolean', value: false, description: 'allow to use subprojects')
option('dbus_policy_dir', type: 'string', value: '', description: 'd-bus system policy directory') option('dbus_policy_dir', type: 'string', value: '', description: 'd-bus system policy directory')
@@ -16,6 +17,8 @@ option('systemd_journal', type: 'boolean', value: true, description: 'enable sys
option('polkit', type: 'combo', choices: ['strict', 'permissive', 'no'], value: 'strict', description: 'User auth-polkit configuration option.') option('polkit', type: 'combo', choices: ['strict', 'permissive', 'no'], value: 'strict', description: 'User auth-polkit configuration option.')
option('deprecated', type: 'boolean', value: true, description: 'build with deprecated symbols')
option('at_command_via_dbus', type: 'boolean', value: false, description: 'enable at commands via d-bus') option('at_command_via_dbus', type: 'boolean', value: false, description: 'enable at commands via d-bus')
option('builtin_plugins', type: 'boolean', value: false, description: 'integrate all built plugins within the daemon binary') option('builtin_plugins', type: 'boolean', value: false, description: 'integrate all built plugins within the daemon binary')
+6 -1
View File
@@ -1,5 +1,6 @@
cs bg
ca ca
cs
da da
de de
fi fi
@@ -11,12 +12,16 @@ hu
id id
it it
ka ka
kk
lt lt
nl nl
pl pl
pt_BR pt_BR
ru ru
sk sk
sl
sr
sr@latin
sv sv
tr tr
uk uk
+141
View File
@@ -0,0 +1,141 @@
# Bulgarian translation for ModemManager.
# Copyright (C) 2025 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package.
# twlvnn kraftwerk <kraft_werk@tutanota.com>, 2025, 2026.
#
msgid ""
msgstr ""
"Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n"
"POT-Creation-Date: 2025-09-06 03:33+0000\n"
"PO-Revision-Date: 2026-02-07 11:28+0100\n"
"Last-Translator: \n"
"Language-Team: Bulgarian <Bulgarian>\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.8\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Включвайте и преглеждайте съобщения по мрежата"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"Системната не позволява включването или преглеждането на съобщенията по "
"мрежата на това устройство."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon"
msgstr "Контролирайте демона на мениджъра на модеми"
#: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager."
msgstr "Системата не позволява да се контролира мениджъра на модеми."
#: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Настройте основния слот за SIM карта на модема"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Системата не позволява да се настройват свойствата на модеми."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device"
msgstr "Отключвайте и контролирайте устройства за достъп до мобилни мрежи"
#: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid ""
"System policy prevents unlocking or controlling the mobile broadband device."
msgstr ""
"Системата не позволява да отключвате и контролирате устройства за достъп до "
"мобилни мрежи."
#: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Добавяйте, променяйте и изтривайте контакти за достъп до мобилни мрежи"
#: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts."
msgstr ""
"Системата не позволява добавянето, променянето или изтриването на контактите "
"на това устройство."
#: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages"
msgstr "Изпращайте, запазвайте, променяйте и изтривайте текстови съобщения"
#: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid ""
"System policy prevents sending or manipulating this device's text messages."
msgstr ""
"Системата не позволява изпращането или манипулирането на текстовите "
"съобщения на това устройство."
#: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr ""
"Приемайте входящи гласови повиквания или стартирайте изходящи гласови "
"повиквания."
#: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls."
msgstr "Системата не позволява гласови повиквания."
#: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information"
msgstr "Правете заявки за времето по мрежата и за информация за часовия пояс"
#: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information."
msgstr ""
"Системната политика не позволява заявки за информация за времето по мрежата."
#: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information"
msgstr ""
"Включвайте и преглеждайте информацията за географското местоположение и "
"позициониране"
#: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid ""
"System policy prevents enabling or viewing geographic location information."
msgstr ""
"Системата не позволява включването или преглеждането информация за "
"географското местоположение."
#: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services"
msgstr "Правете заявки и използвайте информация и услуги за мрежата"
#: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid ""
"System policy prevents querying or utilizing network information and "
"services."
msgstr ""
"Системата не позволява да се правят заявки или да се използват информация и "
"услуги за мрежата."
#: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device"
msgstr ""
"Правете заявки и управлявайте фърмуер за устройства за достъп до мобилни "
"мрежи"
#: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware."
msgstr ""
"Системата не позволява да се правят заявки или да се управлява фърмуерът на "
"това устройство."
#: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices"
msgstr "ModemManager трябва да занулира устройства"
+137
View File
@@ -0,0 +1,137 @@
# Kazakh translation for ModemManager.
# Copyright (C) 2026 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package.
# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2026.
#
msgid ""
msgstr ""
"Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n"
"POT-Creation-Date: 2025-09-05 16:31+0000\n"
"PO-Revision-Date: 2026-03-01 12:56+0500\n"
"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
"Language-Team: Kazakh <kk_KZ@googlegroups.com>\n"
"Language: kk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.8\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Ұялы хабар тарату хабарламаларын іске қосу және көру"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"Жүйелік саясат бұл құрылғының ұялы хабар тарату хабарламаларын іске қосуға "
"немесе көруге рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon"
msgstr "Modem Manager қызметін басқару"
#: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager."
msgstr "Жүйелік саясат Modem Manager қызметін басқаруға рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Модемнің негізгі SIM-слотын орнату"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Жүйелік саясат модем қасиеттерін баптауға рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device"
msgstr "Мобильді кең жолақты құрылғының құлпын ашу және оны басқару"
#: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid ""
"System policy prevents unlocking or controlling the mobile broadband device."
msgstr ""
"Жүйелік саясат мобильді кең жолақты құрылғының құлпын ашуға немесе оны "
"басқаруға рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Мобильді кең жолақты контактілерді қосу, өзгерту және өшіру"
#: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid ""
"System policy prevents adding, modifying, or deleting this device's "
"contacts."
msgstr ""
"Жүйелік саясат бұл құрылғының контактілерін қосуға, өзгертуге немесе "
"өшіруге рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages"
msgstr "Мәтіндік хабарламаларды жіберу, сақтау, өзгерту және өшіру"
#: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid ""
"System policy prevents sending or manipulating this device's text messages."
msgstr ""
"Жүйелік саясат бұл құрылғының мәтіндік хабарламаларын жіберуге немесе "
"өңдеуге рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr ""
"Кіріс дауыстық қоңырауларды қабылдау немесе шығыс дауыстық қоңырауларды "
"бастау."
#: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls."
msgstr "Жүйелік саясат дауыстық қоңырауларға рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information"
msgstr "Желі уақыты мен уақыт белдеуі туралы ақпаратты сұрау"
#: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information."
msgstr "Жүйелік саясат желі уақыты туралы ақпаратты сұрауға рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information"
msgstr "Географиялық орналасу мен позициялау ақпаратын іске қосу және көру"
#: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid ""
"System policy prevents enabling or viewing geographic location information."
msgstr ""
"Жүйелік саясат географиялық орналасу ақпаратын іске қосуға немесе көруге "
"рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services"
msgstr "Желі ақпаратын және қызметтерін сұрау және пайдалану"
#: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid ""
"System policy prevents querying or utilizing network information and "
"services."
msgstr ""
"Жүйелік саясат желі ақпаратын және қызметтерін сұрауға немесе пайдалануға "
"рұқсат бермейді."
#: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device"
msgstr "Мобильді кең жолақты құрылғының микробағдарламасын сұрау және басқару"
#: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware."
msgstr ""
"Жүйелік саясат бұл құрылғының микробағдарламасын сұрауға немесе басқаруға "
"рұқсат бермейді."
#: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices"
msgstr "ModemManager-ге құрылғыларды қайта іске қосу қажет"
+32 -22
View File
@@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: ModemManager\n" "Project-Id-Version: ModemManager\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n" "ModemManager/issues\n"
"POT-Creation-Date: 2024-12-02 03:24+0000\n" "POT-Creation-Date: 2025-09-13 03:30+0000\n"
"PO-Revision-Date: 2025-02-09 15:02+0100\n" "PO-Revision-Date: 2025-09-13 11:42+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n" "Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n" "Language: pl\n"
@@ -22,13 +22,15 @@ msgstr ""
#: data/org.freedesktop.ModemManager1.policy.in.in:13 #: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages" msgid "Enable and view Cell Broadcast messages"
msgstr "Włączenie i wyświetlanie wiadomości SMS" msgstr "Włączenie i wyświetlanie wiadomości nadawania komórkowego"
#: data/org.freedesktop.ModemManager1.policy.in.in:14 #: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid "System policy prevents enabling or viewing this device's text messages." msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają włączanie lub wyświetlanie wiadomości SMS " "Ustawienia systemu uniemożliwiają włączanie lub wyświetlanie wiadomości "
"tego urządzenia." "nadawania komórkowego tego urządzenia."
#: data/org.freedesktop.ModemManager1.policy.in.in:22 #: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon" msgid "Control the Modem Manager daemon"
@@ -39,73 +41,81 @@ msgid "System policy prevents controlling the Modem Manager."
msgstr "Ustawienia systemu uniemożliwiają sterowanie usługą ModemManager." msgstr "Ustawienia systemu uniemożliwiają sterowanie usługą ModemManager."
#: data/org.freedesktop.ModemManager1.policy.in.in:31 #: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Ustawienie głównego gniazda SIM modemu"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Ustawienia systemu uniemożliwiają konfigurowanie właściwości modemu."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device" msgid "Unlock and control a mobile broadband device"
msgstr "Odblokowanie i sterowanie urządzeniem komórkowym" msgstr "Odblokowanie i sterowanie urządzeniem komórkowym"
#: data/org.freedesktop.ModemManager1.policy.in.in:32 #: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid "" msgid ""
"System policy prevents unlocking or controlling the mobile broadband device." "System policy prevents unlocking or controlling the mobile broadband device."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają odblokowanie lub sterowanie urządzeniem " "Ustawienia systemu uniemożliwiają odblokowanie lub sterowanie urządzeniem "
"komórkowym." "komórkowym."
#: data/org.freedesktop.ModemManager1.policy.in.in:40 #: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts" msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Dodawanie, modyfikowanie i usuwanie kontaktów urządzenia komórkowego" msgstr "Dodawanie, modyfikowanie i usuwanie kontaktów urządzenia komórkowego"
#: data/org.freedesktop.ModemManager1.policy.in.in:41 #: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid "" msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts." "System policy prevents adding, modifying, or deleting this device's contacts."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają dodawanie, modyfikowanie lub usuwanie " "Ustawienia systemu uniemożliwiają dodawanie, modyfikowanie lub usuwanie "
"kontaktów tego urządzenia." "kontaktów tego urządzenia."
#: data/org.freedesktop.ModemManager1.policy.in.in:49 #: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages" msgid "Send, save, modify, and delete text messages"
msgstr "Wysyłanie, zapisywanie, modyfikowanie i usuwanie wiadomości SMS" msgstr "Wysyłanie, zapisywanie, modyfikowanie i usuwanie wiadomości SMS"
#: data/org.freedesktop.ModemManager1.policy.in.in:50 #: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid "" msgid ""
"System policy prevents sending or manipulating this device's text messages." "System policy prevents sending or manipulating this device's text messages."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają wysyłanie lub manipulowanie wiadomościami " "Ustawienia systemu uniemożliwiają wysyłanie lub manipulowanie wiadomościami "
"SMS tego urządzenia." "SMS tego urządzenia."
#: data/org.freedesktop.ModemManager1.policy.in.in:58 #: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls." msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr "Przyjmowanie połączeń przychodzących lub dzwonienie" msgstr "Przyjmowanie połączeń przychodzących lub dzwonienie"
#: data/org.freedesktop.ModemManager1.policy.in.in:59 #: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls." msgid "System policy prevents voice calls."
msgstr "Ustawienia systemu uniemożliwiają dzwonienie." msgstr "Ustawienia systemu uniemożliwiają dzwonienie."
#: data/org.freedesktop.ModemManager1.policy.in.in:67 #: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information" msgid "Query network time and timezone information"
msgstr "Odpytywanie informacji o czasie sieciowym i strefie czasowej" msgstr "Odpytywanie informacji o czasie sieciowym i strefie czasowej"
#: data/org.freedesktop.ModemManager1.policy.in.in:68 #: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information." msgid "System policy prevents querying network time information."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają odpytywanie informacji o czasie sieciowym." "Ustawienia systemu uniemożliwiają odpytywanie informacji o czasie sieciowym."
#: data/org.freedesktop.ModemManager1.policy.in.in:76 #: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information" msgid "Enable and view geographic location and positioning information"
msgstr "" msgstr ""
"Włączanie i wyświetlanie informacji o położeniu geograficznym " "Włączanie i wyświetlanie informacji o położeniu geograficznym "
"i pozycjonowaniu" "i pozycjonowaniu"
#: data/org.freedesktop.ModemManager1.policy.in.in:77 #: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid "" msgid ""
"System policy prevents enabling or viewing geographic location information." "System policy prevents enabling or viewing geographic location information."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają włączanie lub wyświetlanie informacji " "Ustawienia systemu uniemożliwiają włączanie lub wyświetlanie informacji "
"o położeniu geograficznym." "o położeniu geograficznym."
#: data/org.freedesktop.ModemManager1.policy.in.in:85 #: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services" msgid "Query and utilize network information and services"
msgstr "Odpytywanie i używanie informacji i usług sieciowych" msgstr "Odpytywanie i używanie informacji i usług sieciowych"
#: data/org.freedesktop.ModemManager1.policy.in.in:86 #: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid "" msgid ""
"System policy prevents querying or utilizing network information and " "System policy prevents querying or utilizing network information and "
"services." "services."
@@ -113,17 +123,17 @@ msgstr ""
"Ustawienia systemu uniemożliwiają odpytywanie lub używanie informacji " "Ustawienia systemu uniemożliwiają odpytywanie lub używanie informacji "
"i usług sieciowych." "i usług sieciowych."
#: data/org.freedesktop.ModemManager1.policy.in.in:94 #: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device" msgid "Query and manage firmware on a mobile broadband device"
msgstr "" msgstr ""
"Odpytywanie i zarządzanie oprogramowaniem sprzętowym urządzenia komórkowego" "Odpytywanie i zarządzanie oprogramowaniem sprzętowym urządzenia komórkowego"
#: data/org.freedesktop.ModemManager1.policy.in.in:95 #: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware." msgid "System policy prevents querying or managing this device's firmware."
msgstr "" msgstr ""
"Ustawienia systemu uniemożliwiają odpytywanie lub zarządzanie " "Ustawienia systemu uniemożliwiają odpytywanie lub zarządzanie "
"oprogramowaniem sprzętowym tego urządzenia." "oprogramowaniem sprzętowym tego urządzenia."
#: src/mm-sleep-monitor-systemd.c:125 #: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices" msgid "ModemManager needs to reset devices"
msgstr "Usługa ModemManager musi ponownie uruchomić urządzenia" msgstr "Usługa ModemManager musi ponownie uruchomić urządzenia"
+36 -26
View File
@@ -1,33 +1,35 @@
# Brazilian Portuguese translation for ModemManager. # Brazilian Portuguese translation for ModemManager.
# Copyright (C) 2025 ModemManager's COPYRIGHT HOLDER # Copyright (C) 2026 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package. # This file is distributed under the same license as the ModemManager package.
# Rafael Fontenelle <rafaelff@gnome.org>, 2017-2025. # Rafael Fontenelle <rafaelff@gnome.org>, 2017-2026.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ModemManager main\n" "Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n" "ModemManager/issues\n"
"POT-Creation-Date: 2024-12-02 03:24+0000\n" "POT-Creation-Date: 2025-09-05 16:31+0000\n"
"PO-Revision-Date: 2025-01-13 22:01-0300\n" "PO-Revision-Date: 2026-06-26 22:30-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n" "Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <https://br.gnome.org/traducao>\n" "Language-Team: Brazilian Portuguese <https://br.gnome.org/traducao>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Gtranslator 47.1\n" "X-Generator: Gtranslator 50.0\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13 #: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages" msgid "Enable and view Cell Broadcast messages"
msgstr "Habilitar e visualizar mensagens de transmissão celular" msgstr "Habilitar e visualizar mensagens de transmissão celular"
#: data/org.freedesktop.ModemManager1.policy.in.in:14 #: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid "System policy prevents enabling or viewing this device's text messages." msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr "" msgstr ""
"A política de sistema impede de habilitar ou visualizar as mensagens de " "A política de sistema impede de habilitar ou visualizar as mensagens de "
"texto deste dispositivo." "transmissão celular deste dispositivo."
#: data/org.freedesktop.ModemManager1.policy.in.in:22 #: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon" msgid "Control the Modem Manager daemon"
@@ -38,71 +40,79 @@ msgid "System policy prevents controlling the Modem Manager."
msgstr "A política de sistema impede de controlar o ModemManager." msgstr "A política de sistema impede de controlar o ModemManager."
#: data/org.freedesktop.ModemManager1.policy.in.in:31 #: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Configurar o slot principal do cartão SIM de um modem"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "A política de sistema impede a configuração das propriedades do modem."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device" msgid "Unlock and control a mobile broadband device"
msgstr "Desbloquear e controlar um dispositivo de banda larga móvel" msgstr "Desbloquear e controlar um dispositivo de banda larga móvel"
#: data/org.freedesktop.ModemManager1.policy.in.in:32 #: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid "" msgid ""
"System policy prevents unlocking or controlling the mobile broadband device." "System policy prevents unlocking or controlling the mobile broadband device."
msgstr "" msgstr ""
"A política de sistema impede de desbloquear ou controlar o dispositivo de " "A política de sistema impede de desbloquear ou controlar o dispositivo de "
"banda larga móvel." "banda larga móvel."
#: data/org.freedesktop.ModemManager1.policy.in.in:40 #: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts" msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Adicionar, modificar e excluir contatos de banda larga móvel" msgstr "Adicionar, modificar e excluir contatos de banda larga móvel"
#: data/org.freedesktop.ModemManager1.policy.in.in:41 #: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid "" msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts." "System policy prevents adding, modifying, or deleting this device's contacts."
msgstr "" msgstr ""
"A política de sistema impede de adicionar, modificar ou excluir os contatos " "A política de sistema impede de adicionar, modificar ou excluir os contatos "
"deste dispositivo." "deste dispositivo."
#: data/org.freedesktop.ModemManager1.policy.in.in:49 #: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages" msgid "Send, save, modify, and delete text messages"
msgstr "Enviar, salvar, modificar e excluir mensagens de texto" msgstr "Enviar, salvar, modificar e excluir mensagens de texto"
#: data/org.freedesktop.ModemManager1.policy.in.in:50 #: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid "" msgid ""
"System policy prevents sending or manipulating this device's text messages." "System policy prevents sending or manipulating this device's text messages."
msgstr "" msgstr ""
"A política de sistema impede de enviar ou manipular as mensagens de texto " "A política de sistema impede de enviar ou manipular as mensagens de texto "
"deste dispositivo." "deste dispositivo."
#: data/org.freedesktop.ModemManager1.policy.in.in:58 #: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls." msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr "Aceitar chamadas de voz recebidas ou iniciar chamadas de voz de saída." msgstr "Aceitar chamadas de voz recebidas ou iniciar chamadas de voz de saída."
#: data/org.freedesktop.ModemManager1.policy.in.in:59 #: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls." msgid "System policy prevents voice calls."
msgstr "A política de sistema impede chamadas de voz." msgstr "A política de sistema impede chamadas de voz."
#: data/org.freedesktop.ModemManager1.policy.in.in:67 #: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information" msgid "Query network time and timezone information"
msgstr "Consultar informações de hora e fuso horário da rede" msgstr "Consultar informações de hora e fuso horário da rede"
#: data/org.freedesktop.ModemManager1.policy.in.in:68 #: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information." msgid "System policy prevents querying network time information."
msgstr "" msgstr ""
"A política de sistema impede de consultar informações de horário da rede." "A política de sistema impede de consultar informações de horário da rede."
#: data/org.freedesktop.ModemManager1.policy.in.in:76 #: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information" msgid "Enable and view geographic location and positioning information"
msgstr "Habilitar e ver informações de posicionamento e localização geográfica" msgstr "Habilitar e ver informações de posicionamento e localização geográfica"
#: data/org.freedesktop.ModemManager1.policy.in.in:77 #: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid "" msgid ""
"System policy prevents enabling or viewing geographic location information." "System policy prevents enabling or viewing geographic location information."
msgstr "" msgstr ""
"A política de sistema impede de habilitar ou ver informações de localização " "A política de sistema impede de habilitar ou ver informações de localização "
"geográfica." "geográfica."
#: data/org.freedesktop.ModemManager1.policy.in.in:85 #: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services" msgid "Query and utilize network information and services"
msgstr "Consultar ou utilizar serviços e informações de rede." msgstr "Consultar ou utilizar serviços e informações de rede"
#: data/org.freedesktop.ModemManager1.policy.in.in:86 #: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid "" msgid ""
"System policy prevents querying or utilizing network information and " "System policy prevents querying or utilizing network information and "
"services." "services."
@@ -110,16 +120,16 @@ msgstr ""
"A política de sistema impede de consultar ou utilizar serviços e informações " "A política de sistema impede de consultar ou utilizar serviços e informações "
"de rede." "de rede."
#: data/org.freedesktop.ModemManager1.policy.in.in:94 #: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device" msgid "Query and manage firmware on a mobile broadband device"
msgstr "Consultar e gerenciar firmware em um dispositivo de banda larga móvel" msgstr "Consultar e gerenciar firmware em um dispositivo de banda larga móvel"
#: data/org.freedesktop.ModemManager1.policy.in.in:95 #: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware." msgid "System policy prevents querying or managing this device's firmware."
msgstr "" msgstr ""
"A política de sistema impede de consultar ou gerenciar o firmware do " "A política de sistema impede de consultar ou gerenciar o firmware do "
"dispositivo." "dispositivo."
#: src/mm-sleep-monitor-systemd.c:125 #: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices" msgid "ModemManager needs to reset devices"
msgstr "O ModemManager precisa reiniciar os dispositivos" msgstr "O ModemManager precisa reiniciar os dispositivos"
+140
View File
@@ -0,0 +1,140 @@
# Slovenian translation for ModemManager.
# Copyright (C) 2024 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package.
#
# Martin Srebotnjak <miles@filmsi.net>, 2024, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n"
"POT-Creation-Date: 2025-09-11 03:31+0000\n"
"PO-Revision-Date: 2025-09-11 11:33+0200\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
"n%100==4 ? 3 : 0);\n"
"X-Generator: Poedit 2.2.1\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Omogoči in pokaži oddajna sporočila telefona"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"Sistemska pravila preprečujejo omogočanje ali ogledovanje oddajnih "
"telefonskih sporočil te naprave."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon"
msgstr "Upravljajte prikriti proces upravitelja modema"
#: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager."
msgstr "Sistemska pravila preprečujejo nadzor upravitelja modemov."
#: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Nastavite primarno režo za kartico SIM modema"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Sistemska pravila preprečujejo nastavljanje lastnosti modema."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device"
msgstr "Odklenite in nadzorujte naprave za mobilno širokopasovno povezavo"
#: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid ""
"System policy prevents unlocking or controlling the mobile broadband device."
msgstr ""
"Sistemska pravila preprečujejo odklepanje ali nadzor mobilne širokopasovne "
"naprave."
#: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts"
msgstr ""
"Dodajte, spreminjajte in brišite stike za mobilno širokopasovno povezavo"
#: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts."
msgstr ""
"Sistemska pravila preprečujejo dodajanje, spreminjanje ali brisanje stikov v "
"tej napravi."
#: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages"
msgstr "Pošiljajte, shranjujte, spreminjajte in brišite besedilna sporočila"
#: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid ""
"System policy prevents sending or manipulating this device's text messages."
msgstr ""
"Sistemska pravila preprečujejo pošiljanje besedilnih sporočil te naprave ali "
"manipulacijo z njimi."
#: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr "Sprejmite dohodne glasovne klice ali začnite odhodne glasovne klice."
#: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls."
msgstr "Sistemska pravila preprečujejo glasovne klice."
#: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information"
msgstr "Poizvedujte po omrežnem času in časovnem pasu"
#: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information."
msgstr ""
"Sistemska pravilna preprečujejo poizvedovanje po podatkih o omrežnem času."
#: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information"
msgstr "Omogočite in oglejte si informacije o zemljepisni lokaciji in položaju"
#: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid ""
"System policy prevents enabling or viewing geographic location information."
msgstr ""
"Sistemska pravila preprečujejo omogočanje ali ogled informacij o zemljepisni "
"lokaciji."
#: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services"
msgstr "Poizvedujte in uporabljajte omrežne informacije in storitve"
#: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid ""
"System policy prevents querying or utilizing network information and "
"services."
msgstr ""
"Sistemska pravila preprečujejo poizvedovanje ali uporabo omrežnih informacij "
"in storitev."
#: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device"
msgstr ""
"Poizvedujte in upravljajte vdelano programsko opremo v mobilni širokopasovni "
"napravi"
#: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware."
msgstr ""
"Sistemska pravila preprečujejo poizvedovanje ali upravljanje vdelane "
"programske opreme te naprave."
#: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices"
msgstr "ModemManager mora ponastaviti naprave"
+134
View File
@@ -0,0 +1,134 @@
# Serbian translation for ModemManager.
# Copyright (C) 2026 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package.
# Марко Костић <marko.m.kostic@gmail.com>, 2026.
#
msgid ""
msgstr ""
"Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n"
"POT-Creation-Date: 2025-09-05 16:31+0000\n"
"PO-Revision-Date: 2026-04-11 14:54+0200\n"
"Last-Translator: Марко Костић <marko.m.kostic@gmail.com>\n"
"Language-Team: Serbian <Serbian>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Poedit 3.9\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Омогућите и прегледајте поруке емитовања ћелије"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"Системска правила спречавају омогућавање или преглед порука емитовања у "
"ћелији овог уређаја."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon"
msgstr "Управљајте демоном управника модема"
#: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager."
msgstr "Системска правила спречавају управљање управником модема."
#: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Поставите примарни СИМ слот модема"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Системска правила спречавају подешавање својстава модема."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device"
msgstr "Откључајте и управљајте мобилним широкопојасним уређајем"
#: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid ""
"System policy prevents unlocking or controlling the mobile broadband device."
msgstr ""
"Системска правила спречавају откључавање или управљање мобилним "
"широкопојасним уређајем."
#: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Додајте, мењајте и бришите контакте мобилне широкопојасне мреже"
#: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts."
msgstr ""
"Системска правила спречавају додавање, мењање или брисање контаката овог "
"уређаја."
#: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages"
msgstr "Шаљите, чувајте, мењајте и бришите текстуалне поруке"
#: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid ""
"System policy prevents sending or manipulating this device's text messages."
msgstr ""
"Системска правила спречавају слање или управљање текстуалним порукама овог "
"уређаја."
#: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr ""
"Прихватите долазне говорне позиве или започните одлазне говорне позиве."
#: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls."
msgstr "Системска правила спречавају говорне позиве."
#: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information"
msgstr "Упитајте време мреже и податке о временској зони"
#: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information."
msgstr "Системска правила спречавају упитивање података о времену мреже."
#: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information"
msgstr "Омогућите и прегледајте податке о географском положају и позиционирању"
#: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid ""
"System policy prevents enabling or viewing geographic location information."
msgstr ""
"Системска правила спречавају омогућавање или преглед података о географском "
"положају."
#: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services"
msgstr "Упитајте и користите мрежне податке и услуге"
#: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid ""
"System policy prevents querying or utilizing network information and "
"services."
msgstr ""
"Системска правила спречавају упитивање или коришћење мрежних података и "
"услуга."
#: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device"
msgstr "Упит и управљање фирмвером на мобилном широкопојасном уређају"
#: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware."
msgstr "Системска политика спречава упит или управљање фирмвером овог уређаја."
#: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices"
msgstr "Управник модема мора да поново покрене уређаје"
+136
View File
@@ -0,0 +1,136 @@
# Serbian translation for ModemManager.
# Copyright (C) 2026 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package.
# Marko Kostić <marko.m.kostic@gmail.com>, 2026.
#
msgid ""
msgstr ""
"Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n"
"POT-Creation-Date: 2025-09-05 16:31+0000\n"
"PO-Revision-Date: 2026-04-11 14:54+0200\n"
"Last-Translator: Marko Kostić <marko.m.kostic@gmail.com>\n"
"Language-Team: Serbian <Serbian>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Poedit 3.9\n"
#: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Omogućite i pregledajte poruke emitovanja ćelije"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"Sistemska pravila sprečavaju omogućavanje ili pregled poruka emitovanja u "
"ćeliji ovog uređaja."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon"
msgstr "Upravljajte demonom upravnika modema"
#: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager."
msgstr "Sistemska pravila sprečavaju upravljanje upravnikom modema."
#: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Postavite primarni SIM slot modema"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "Sistemska pravila sprečavaju podešavanje svojstava modema."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device"
msgstr "Otključajte i upravljajte mobilnim širokopojasnim uređajem"
#: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid ""
"System policy prevents unlocking or controlling the mobile broadband device."
msgstr ""
"Sistemska pravila sprečavaju otključavanje ili upravljanje mobilnim "
"širokopojasnim uređajem."
#: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Dodajte, menjajte i brišite kontakte mobilne širokopojasne mreže"
#: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts."
msgstr ""
"Sistemska pravila sprečavaju dodavanje, menjanje ili brisanje kontakata ovog "
"uređaja."
#: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages"
msgstr "Šaljite, čuvajte, menjajte i brišite tekstualne poruke"
#: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid ""
"System policy prevents sending or manipulating this device's text messages."
msgstr ""
"Sistemska pravila sprečavaju slanje ili upravljanje tekstualnim porukama "
"ovog uređaja."
#: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr ""
"Prihvatite dolazne govorne pozive ili započnite odlazne govorne pozive."
#: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls."
msgstr "Sistemska pravila sprečavaju govorne pozive."
#: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information"
msgstr "Upitajte vreme mreže i podatke o vremenskoj zoni"
#: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information."
msgstr "Sistemska pravila sprečavaju upitivanje podataka o vremenu mreže."
#: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information"
msgstr ""
"Omogućite i pregledajte podatke o geografskom položaju i pozicioniranju"
#: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid ""
"System policy prevents enabling or viewing geographic location information."
msgstr ""
"Sistemska pravila sprečavaju omogućavanje ili pregled podataka o geografskom "
"položaju."
#: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services"
msgstr "Upitajte i koristite mrežne podatke i usluge"
#: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid ""
"System policy prevents querying or utilizing network information and "
"services."
msgstr ""
"Sistemska pravila sprečavaju upitivanje ili korišćenje mrežnih podataka i "
"usluga."
#: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device"
msgstr "Upit i upravljanje firmverom na mobilnom širokopojasnom uređaju"
#: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware."
msgstr ""
"Sistemska politika sprečava upit ili upravljanje firmverom ovog uređaja."
#: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices"
msgstr "Upravnik modema mora da ponovo pokrene uređaje"
+44 -23
View File
@@ -1,16 +1,16 @@
# Swedish translation for ModemManager. # Swedish translation for ModemManager.
# Copyright (C) 2017, 2020 ModemManager's COPYRIGHT HOLDER # Copyright © 2017, 2020, 2024, 2025 ModemManager's COPYRIGHT HOLDER
# This file is distributed under the same license as the ModemManager package. # This file is distributed under the same license as the ModemManager package.
# Josef Andersson <l10nl18nsweja@gmail.com>, 2017. # Josef Andersson <l10nl18nsweja@gmail.com>, 2017.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2020. # Anders Jonsson <anders.jonsson@norsjovallen.se>, 2020, 2024, 2025.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ModemManager main\n" "Project-Id-Version: ModemManager main\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/mobile-broadband/"
"ModemManager/issues\n" "ModemManager/issues\n"
"POT-Creation-Date: 2022-07-16 14:32+0200\n" "POT-Creation-Date: 2025-09-07 15:30+0000\n"
"PO-Revision-Date: 2020-09-18 23:56+0200\n" "PO-Revision-Date: 2025-09-07 22:14+0200\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n" "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n" "Language: sv\n"
@@ -18,81 +18,102 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.1\n" "X-Generator: Poedit 3.7\n"
# https://it-ord.computersweden.se/ord/cell-broadcast/
#: data/org.freedesktop.ModemManager1.policy.in.in:13 #: data/org.freedesktop.ModemManager1.policy.in.in:13
msgid "Enable and view Cell Broadcast messages"
msgstr "Aktivera och visa Cell Broadcast-meddelanden"
#: data/org.freedesktop.ModemManager1.policy.in.in:14
msgid ""
"System policy prevents enabling or viewing this device's cell broadcast "
"messages."
msgstr ""
"En systempolicy förhindrar att aktivera eller visa denna enhets Cell "
"Broadcast-meddelanden."
#: data/org.freedesktop.ModemManager1.policy.in.in:22
msgid "Control the Modem Manager daemon" msgid "Control the Modem Manager daemon"
msgstr "Kontrollera demonen för Modem Manager" msgstr "Kontrollera demonen för Modem Manager"
#: data/org.freedesktop.ModemManager1.policy.in.in:14 #: data/org.freedesktop.ModemManager1.policy.in.in:23
msgid "System policy prevents controlling the Modem Manager." msgid "System policy prevents controlling the Modem Manager."
msgstr "En systempolicy förhindrar kontroll av Modem Manager." msgstr "En systempolicy förhindrar kontroll av Modem Manager."
#: data/org.freedesktop.ModemManager1.policy.in.in:22 #: data/org.freedesktop.ModemManager1.policy.in.in:31
msgid "Set the primary sim slot of a modem"
msgstr "Ställ in primärt SIM-fack för ett modem"
#: data/org.freedesktop.ModemManager1.policy.in.in:32
msgid "System policy prevents configuring modem properties."
msgstr "En systempolicy förhindrar konfiguration av modemegenskaper."
#: data/org.freedesktop.ModemManager1.policy.in.in:40
msgid "Unlock and control a mobile broadband device" msgid "Unlock and control a mobile broadband device"
msgstr "Lås upp och kontrollera en mobil bredbandsenhet" msgstr "Lås upp och kontrollera en mobil bredbandsenhet"
#: data/org.freedesktop.ModemManager1.policy.in.in:23 #: data/org.freedesktop.ModemManager1.policy.in.in:41
msgid "" msgid ""
"System policy prevents unlocking or controlling the mobile broadband device." "System policy prevents unlocking or controlling the mobile broadband device."
msgstr "" msgstr ""
"En systempolicy hindrar upplåsning eller kontroll över den mobila " "En systempolicy hindrar upplåsning eller kontroll över den mobila "
"bredbandsenheten." "bredbandsenheten."
#: data/org.freedesktop.ModemManager1.policy.in.in:31 #: data/org.freedesktop.ModemManager1.policy.in.in:49
msgid "Add, modify, and delete mobile broadband contacts" msgid "Add, modify, and delete mobile broadband contacts"
msgstr "Lägg till, ändra och ta bort mobila bredbandskontakter" msgstr "Lägg till, ändra och ta bort mobila bredbandskontakter"
#: data/org.freedesktop.ModemManager1.policy.in.in:32 #: data/org.freedesktop.ModemManager1.policy.in.in:50
msgid "" msgid ""
"System policy prevents adding, modifying, or deleting this device's contacts." "System policy prevents adding, modifying, or deleting this device's contacts."
msgstr "" msgstr ""
"En systempolicy förhindrar att lägga till, ändra och ta bort denna enhets " "En systempolicy förhindrar att lägga till, ändra och ta bort denna enhets "
"kontakter." "kontakter."
#: data/org.freedesktop.ModemManager1.policy.in.in:40 #: data/org.freedesktop.ModemManager1.policy.in.in:58
msgid "Send, save, modify, and delete text messages" msgid "Send, save, modify, and delete text messages"
msgstr "Skicka, spara, ändra och ta bort meddelanden" msgstr "Skicka, spara, ändra och ta bort meddelanden"
#: data/org.freedesktop.ModemManager1.policy.in.in:41 #: data/org.freedesktop.ModemManager1.policy.in.in:59
msgid "" msgid ""
"System policy prevents sending or manipulating this device's text messages." "System policy prevents sending or manipulating this device's text messages."
msgstr "" msgstr ""
"En systempolicy förhindrar att skicka eller ändra denna enhets " "En systempolicy förhindrar att skicka eller ändra denna enhets "
"textmeddelanden." "textmeddelanden."
#: data/org.freedesktop.ModemManager1.policy.in.in:49 #: data/org.freedesktop.ModemManager1.policy.in.in:67
msgid "Accept incoming voice calls or start outgoing voice calls." msgid "Accept incoming voice calls or start outgoing voice calls."
msgstr "Acceptera inkommande röstsamtal eller påbörja utgående röstsamtal." msgstr "Acceptera inkommande röstsamtal eller påbörja utgående röstsamtal."
#: data/org.freedesktop.ModemManager1.policy.in.in:50 #: data/org.freedesktop.ModemManager1.policy.in.in:68
msgid "System policy prevents voice calls." msgid "System policy prevents voice calls."
msgstr "En systempolicy förhindrar röstsamtal." msgstr "En systempolicy förhindrar röstsamtal."
#: data/org.freedesktop.ModemManager1.policy.in.in:58 #: data/org.freedesktop.ModemManager1.policy.in.in:76
msgid "Query network time and timezone information" msgid "Query network time and timezone information"
msgstr "Fråga efter nätverkstid och tidzonsinformation" msgstr "Fråga efter nätverkstid och tidzonsinformation"
#: data/org.freedesktop.ModemManager1.policy.in.in:59 #: data/org.freedesktop.ModemManager1.policy.in.in:77
msgid "System policy prevents querying network time information." msgid "System policy prevents querying network time information."
msgstr "En systempolicy förhindrar frågande av nätverkstidsinformation." msgstr "En systempolicy förhindrar frågande av nätverkstidsinformation."
#: data/org.freedesktop.ModemManager1.policy.in.in:67 #: data/org.freedesktop.ModemManager1.policy.in.in:85
msgid "Enable and view geographic location and positioning information" msgid "Enable and view geographic location and positioning information"
msgstr "Aktivera och visa geografisk plats samt positioneringsinformation" msgstr "Aktivera och visa geografisk plats samt positioneringsinformation"
#: data/org.freedesktop.ModemManager1.policy.in.in:68 #: data/org.freedesktop.ModemManager1.policy.in.in:86
msgid "" msgid ""
"System policy prevents enabling or viewing geographic location information." "System policy prevents enabling or viewing geographic location information."
msgstr "" msgstr ""
"En systempolicy förhindrar aktivering eller visning av geografisk " "En systempolicy förhindrar aktivering eller visning av geografisk "
"platsinformation." "platsinformation."
#: data/org.freedesktop.ModemManager1.policy.in.in:76 #: data/org.freedesktop.ModemManager1.policy.in.in:94
msgid "Query and utilize network information and services" msgid "Query and utilize network information and services"
msgstr "Fråga efter och nyttja nätverksinformation och tjänster" msgstr "Fråga efter och nyttja nätverksinformation och tjänster"
#: data/org.freedesktop.ModemManager1.policy.in.in:77 #: data/org.freedesktop.ModemManager1.policy.in.in:95
msgid "" msgid ""
"System policy prevents querying or utilizing network information and " "System policy prevents querying or utilizing network information and "
"services." "services."
@@ -100,16 +121,16 @@ msgstr ""
"En systempolicy förhindrar frågande och nyttjande av nätverksinformation och " "En systempolicy förhindrar frågande och nyttjande av nätverksinformation och "
"tjänster." "tjänster."
#: data/org.freedesktop.ModemManager1.policy.in.in:85 #: data/org.freedesktop.ModemManager1.policy.in.in:103
msgid "Query and manage firmware on a mobile broadband device" msgid "Query and manage firmware on a mobile broadband device"
msgstr "Fråga efter och hantera fast programvara för en mobil bredbandsenhet" msgstr "Fråga efter och hantera fast programvara för en mobil bredbandsenhet"
#: data/org.freedesktop.ModemManager1.policy.in.in:86 #: data/org.freedesktop.ModemManager1.policy.in.in:104
msgid "System policy prevents querying or managing this device's firmware." msgid "System policy prevents querying or managing this device's firmware."
msgstr "" msgstr ""
"En systempolicy förhindrar att fråga och hantera denna enhets fasta " "En systempolicy förhindrar att fråga och hantera denna enhets fasta "
"programvara." "programvara."
#: src/mm-sleep-monitor-systemd.c:125 #: src/mm-sleep-monitor-systemd.c:133
msgid "ModemManager needs to reset devices" msgid "ModemManager needs to reset devices"
msgstr "ModemManager behöver starta om enheter" msgstr "ModemManager behöver starta om enheter"
+1 -53
View File
@@ -24,58 +24,6 @@
/******************************************************************************/ /******************************************************************************/
static gboolean
read_sysfs_int (const gchar *path,
gint *value)
{
g_autofree gchar *contents = NULL;
gchar *end = NULL;
gint64 parsed;
if (!g_file_get_contents (path, &contents, NULL, NULL))
return FALSE;
parsed = g_ascii_strtoll (contents, &end, 10);
if (end == contents)
return FALSE;
*value = (gint) parsed;
return TRUE;
}
/* Net devices stacked by drivers that create no lower_* adjacency links (e.g. rmnet on Android vendor
* kernels) still report the parent's interface index in 'iflink'. */
static gchar *
get_lower_device_name_by_iflink (const gchar *sysfs_path)
{
g_autofree gchar *ifindex_path = NULL;
g_autofree gchar *iflink_path = NULL;
g_autoptr(GDir) dir = NULL;
const gchar *name;
gint ifindex;
gint iflink;
ifindex_path = g_build_filename (sysfs_path, "ifindex", NULL);
iflink_path = g_build_filename (sysfs_path, "iflink", NULL);
if (!read_sysfs_int (ifindex_path, &ifindex) ||
!read_sysfs_int (iflink_path, &iflink) ||
iflink == ifindex || iflink <= 0)
return NULL;
dir = g_dir_open ("/sys/class/net", 0, NULL);
if (!dir)
return NULL;
while ((name = g_dir_read_name (dir)) != NULL) {
g_autofree gchar *path = NULL;
gint index;
path = g_build_filename ("/sys/class/net", name, "ifindex", NULL);
if (read_sysfs_int (path, &index) && index == iflink)
return g_strdup (name);
}
return NULL;
}
gchar * gchar *
mm_kernel_device_get_lower_device_name (const gchar *sysfs_path) mm_kernel_device_get_lower_device_name (const gchar *sysfs_path)
{ {
@@ -112,7 +60,7 @@ mm_kernel_device_get_lower_device_name (const gchar *sysfs_path)
return g_path_get_basename (real_path); return g_path_get_basename (real_path);
} }
return get_lower_device_name_by_iflink (sysfs_path); return NULL;
} }
/******************************************************************************/ /******************************************************************************/
+2 -13
View File
@@ -338,21 +338,10 @@ kernel_device_get_name (MMKernelDevice *_self)
return mm_kernel_event_properties_get_name (self->priv->properties); return mm_kernel_event_properties_get_name (self->priv->properties);
} }
/* Driver name for devices without one in sysfs, e.g. the virtual rmnet_ipa0 of
* Qualcomm vendor kernels, which is handled like the mainline 'ipa' driver */
#define ID_MM_KERNEL_DRIVER "ID_MM_KERNEL_DRIVER"
static const gchar * static const gchar *
kernel_device_get_driver (MMKernelDevice *_self) kernel_device_get_driver (MMKernelDevice *self)
{ {
MMKernelDeviceUdev *self; return MM_KERNEL_DEVICE_UDEV (self)->priv->driver;
const gchar *driver;
self = MM_KERNEL_DEVICE_UDEV (_self);
if (self->priv->device &&
(driver = g_udev_device_get_property (self->priv->device, ID_MM_KERNEL_DRIVER)) != NULL)
return driver;
return self->priv->driver;
} }
static const gchar * static const gchar *
+138 -16
View File
@@ -46,6 +46,7 @@ sources = files(
'mm-cbm-part.c', 'mm-cbm-part.c',
'mm-charsets.c', 'mm-charsets.c',
'mm-error-helpers.c', 'mm-error-helpers.c',
'mm-location-cache.c',
'mm-log.c', 'mm-log.c',
'mm-log-object.c', 'mm-log-object.c',
'mm-modem-helpers.c', 'mm-modem-helpers.c',
@@ -80,11 +81,16 @@ if enable_systemd_journal
private_deps += libsystemd_dep private_deps += libsystemd_dep
endif endif
c_args = [
'-DPKGSTATEDIR="@0@"'.format(mm_pkgsharedstatedir),
]
libhelpers = static_library( libhelpers = static_library(
'helpers', 'helpers',
sources: sources + enums_sources, sources: sources + enums_sources,
include_directories: incs, include_directories: incs,
dependencies: deps + private_deps, dependencies: deps + private_deps,
c_args: c_args,
) )
libhelpers_dep = declare_dependency( libhelpers_dep = declare_dependency(
@@ -134,6 +140,8 @@ headers = files(
'mm-iface-port-at.h', 'mm-iface-port-at.h',
'mm-port.h', 'mm-port.h',
'mm-port-serial-at.h', 'mm-port-serial-at.h',
'mm-port-scheduler.h',
'mm-port-scheduler-rr.h',
) )
sources = files( sources = files(
@@ -146,6 +154,8 @@ sources = files(
'mm-port-serial-gps.c', 'mm-port-serial-gps.c',
'mm-port-serial-qcdm.c', 'mm-port-serial-qcdm.c',
'mm-serial-parsers.c', 'mm-serial-parsers.c',
'mm-port-scheduler.c',
'mm-port-scheduler-rr.c',
) )
deps = [libkerneldevice_dep] deps = [libkerneldevice_dep]
@@ -206,10 +216,71 @@ libport_dep = declare_dependency(
link_with: libport, link_with: libport,
) )
# auth provider library
sources = files(
'mm-auth-provider.c',
'mm-context.c',
'mm-bind.c',
)
incs = [
top_inc,
kerneldevice_inc,
]
deps = [libmm_glib_dep, libhelpers_dep]
if enable_polkit
deps += polkit_gobject_dep
endif
private_deps = []
libauth = static_library(
'auth',
sources: sources,
include_directories: incs,
dependencies: deps,
c_args: '-DPLUGINDIR="@0@"'.format(mm_prefix / mm_pkglibdir),
)
libauth_dep = declare_dependency(
include_directories: ['.', kerneldevice_inc],
dependencies: deps,
link_with: libauth,
)
# SMS library
sources = files(
'mm-sms-list.c',
'mm-base-sms.c',
)
incs = [
top_inc,
]
deps = [libmm_glib_dep, libhelpers_dep, libauth_dep]
private_deps = []
libsms = static_library(
'sms',
sources: sources,
include_directories: incs,
dependencies: deps,
)
libsms_dep = declare_dependency(
include_directories: ['.'],
dependencies: deps,
link_with: libsms,
)
# Daemon enums, required by plugins # Daemon enums, required by plugins
headers = files( headers = files(
'mm-base-bearer.h', 'mm-base-bearer.h',
'mm-base-modem.h', 'mm-iface-op-lock.h',
'mm-filter.h', 'mm-filter.h',
'mm-port-probe.h', 'mm-port-probe.h',
) )
@@ -250,33 +321,25 @@ daemon_enums_types_dep = declare_dependency(
include_directories: '.', include_directories: '.',
) )
# Additional vendor plugins base_sources = files(
subdir('plugins')
# ModemManager daemon
sources = files(
'main.c',
'mm-auth-provider.c',
'mm-base-bearer.c', 'mm-base-bearer.c',
'mm-base-call.c', 'mm-base-call.c',
'mm-call-at.c',
'mm-base-cbm.c', 'mm-base-cbm.c',
'mm-base-manager.c',
'mm-base-modem-at.c', 'mm-base-modem-at.c',
'mm-base-modem.c', 'mm-base-modem.c',
'mm-base-sim.c', 'mm-base-sim.c',
'mm-base-sms.c', 'mm-sms-at.c',
'mm-bearer-list.c', 'mm-bearer-list.c',
'mm-broadband-bearer.c', 'mm-broadband-bearer.c',
'mm-broadband-modem.c', 'mm-broadband-modem.c',
'mm-call-list.c', 'mm-call-list.c',
'mm-cbm-list.c', 'mm-cbm-list.c',
'mm-context.c',
'mm-device.c', 'mm-device.c',
'mm-dispatcher.c', 'mm-dispatcher.c',
'mm-dispatcher-connection.c', 'mm-dispatcher-connection.c',
'mm-dispatcher-fcc-unlock.c', 'mm-dispatcher-fcc-unlock.c',
'mm-dispatcher-modem-setup.c', 'mm-dispatcher-modem-setup.c',
'mm-filter.c',
'mm-iface-modem-3gpp.c', 'mm-iface-modem-3gpp.c',
'mm-iface-modem-3gpp-profile-manager.c', 'mm-iface-modem-3gpp-profile-manager.c',
'mm-iface-modem-3gpp-ussd.c', 'mm-iface-modem-3gpp-ussd.c',
@@ -292,22 +355,77 @@ sources = files(
'mm-iface-modem-simple.c', 'mm-iface-modem-simple.c',
'mm-iface-modem-time.c', 'mm-iface-modem-time.c',
'mm-iface-modem-voice.c', 'mm-iface-modem-voice.c',
'mm-iface-op-lock.c',
'mm-log-helpers.c', 'mm-log-helpers.c',
'mm-private-boxed-types.c',
'mm-sleep-context.c',
)
# MM base library (used by MM and tests)
incs = [
top_inc,
kerneldevice_inc,
]
deps = [
libmm_glib_dep,
libhelpers_dep,
libauth_dep,
libport_dep,
libqcdm_dep,
daemon_enums_types_dep,
]
private_deps = []
c_args = [
'-DMM_COMPILATION',
'-DPLUGINDIR="@0@"'.format(mm_prefix / mm_pkglibdir),
'-DMODEMSETUPDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'modem-setup.d'),
'-DMODEMSETUPDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'modem-setup.d'),
'-DFCCUNLOCKDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'fcc-unlock.d'),
'-DFCCUNLOCKDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'fcc-unlock.d'),
'-DCONNECTIONDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'connection.d'),
'-DCONNECTIONDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'connection.d'),
]
libmmbase = static_library(
'mmbase',
sources: base_sources + daemon_enums_sources,
include_directories: incs,
dependencies: deps,
c_args: c_args,
)
libmmbase_dep = declare_dependency(
include_directories: ['.', kerneldevice_inc],
dependencies: deps,
link_with: libmmbase,
)
# Additional vendor plugins
subdir('plugins')
# ModemManager daemon
sources = files(
'main.c',
'mm-base-manager.c',
'mm-filter.c',
'mm-plugin.c', 'mm-plugin.c',
'mm-plugin-manager.c', 'mm-plugin-manager.c',
'mm-port-probe.c', 'mm-port-probe.c',
'mm-port-probe-at.c', 'mm-port-probe-at.c',
'mm-private-boxed-types.c',
'mm-sms-list.c',
'mm-sleep-context.c',
) )
sources += daemon_enums_sources sources += daemon_enums_sources
sources += base_sources
deps = [ deps = [
gmodule_dep, gmodule_dep,
libport_dep, libport_dep,
libqcdm_dep, libqcdm_dep,
libsms_dep,
libauth_dep,
] ]
if enable_tests if enable_tests
@@ -316,7 +434,6 @@ endif
c_args = [ c_args = [
'-DMM_COMPILATION', '-DMM_COMPILATION',
'-DPLUGINDIR="@0@"'.format(mm_prefix / mm_pkglibdir),
'-DMODEMSETUPDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'modem-setup.d'), '-DMODEMSETUPDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'modem-setup.d'),
'-DMODEMSETUPDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'modem-setup.d'), '-DMODEMSETUPDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'modem-setup.d'),
'-DFCCUNLOCKDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'fcc-unlock.d'), '-DFCCUNLOCKDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'fcc-unlock.d'),
@@ -395,6 +512,11 @@ install_data(
install_dir: udev_rulesdir, install_dir: udev_rulesdir,
) )
# empty directory for cached position
install_emptydir(
mm_pkgsharedstatedir,
)
if enable_tests if enable_tests
subdir('tests') subdir('tests')
endif endif
+45
View File
@@ -22,6 +22,7 @@
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-utils.h" #include "mm-utils.h"
#include "mm-auth-provider.h" #include "mm-auth-provider.h"
#include "mm-context.h"
#if defined WITH_POLKIT #if defined WITH_POLKIT
# include <polkit/polkit.h> # include <polkit/polkit.h>
@@ -128,6 +129,13 @@ mm_auth_provider_authorize (MMAuthProvider *self,
task = g_task_new (self, cancellable, callback, user_data); task = g_task_new (self, cancellable, callback, user_data);
/* When running in the session bus for tests, default to always allow */
if (mm_context_get_test_session ()) {
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
}
#if defined WITH_POLKIT #if defined WITH_POLKIT
{ {
AuthorizeContext *ctx; AuthorizeContext *ctx;
@@ -218,3 +226,40 @@ mm_auth_provider_class_init (MMAuthProviderClass *class)
} }
MM_DEFINE_SINGLETON_GETTER (MMAuthProvider, mm_auth_provider_get, MM_TYPE_AUTH_PROVIDER) MM_DEFINE_SINGLETON_GETTER (MMAuthProvider, mm_auth_provider_get, MM_TYPE_AUTH_PROVIDER)
/*****************************************************************************/
/* Auth interface */
G_DEFINE_INTERFACE (MMIfaceAuth, mm_iface_auth, G_TYPE_OBJECT)
void
mm_iface_auth_authorize (MMIfaceAuth *self,
GDBusMethodInvocation *invocation,
const gchar *authorization,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_assert (MM_IFACE_AUTH_GET_IFACE (self)->authorize != NULL);
MM_IFACE_AUTH_GET_IFACE (self)->authorize (self,
invocation,
authorization,
callback,
user_data);
}
gboolean
mm_iface_auth_authorize_finish (MMIfaceAuth *self,
GAsyncResult *res,
GError **error)
{
g_assert (MM_IFACE_AUTH_GET_IFACE (self)->authorize_finish != NULL);
return MM_IFACE_AUTH_GET_IFACE (self)->authorize_finish (self, res, error);
}
static void
mm_iface_auth_default_init (MMIfaceAuthInterface *iface)
{
}
+35
View File
@@ -56,4 +56,39 @@ gboolean mm_auth_provider_authorize_finish (MMAuthProvider *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
/*****************************************************************************/
/* Auth interface
*
* Implemented by objects (mainly MMBaseModem) that provide authorization
* capability to other interfaces (MMIfaceModem) since GLib interfaces don't
* have private data to store the singletone.
*/
#define MM_TYPE_IFACE_AUTH mm_iface_auth_get_type ()
G_DECLARE_INTERFACE (MMIfaceAuth, mm_iface_auth, MM, IFACE_AUTH, GObject)
struct _MMIfaceAuthInterface {
GTypeInterface g_iface;
void (* authorize) (MMIfaceAuth *self,
GDBusMethodInvocation *invocation,
const gchar *authorization,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (* authorize_finish) (MMIfaceAuth *self,
GAsyncResult *res,
GError **error);
};
void mm_iface_auth_authorize (MMIfaceAuth *self,
GDBusMethodInvocation *invocation,
const gchar *authorization,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean mm_iface_auth_authorize_finish (MMIfaceAuth *self,
GAsyncResult *res,
GError **error);
#endif /* MM_AUTH_PROVIDER_H */ #endif /* MM_AUTH_PROVIDER_H */
+61 -39
View File
@@ -34,13 +34,14 @@
#include "mm-iface-modem-3gpp-profile-manager.h" #include "mm-iface-modem-3gpp-profile-manager.h"
#include "mm-iface-modem-cdma.h" #include "mm-iface-modem-cdma.h"
#include "mm-base-bearer.h" #include "mm-base-bearer.h"
#include "mm-base-modem-at.h"
#include "mm-base-modem.h" #include "mm-base-modem.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-error-helpers.h" #include "mm-error-helpers.h"
#include "mm-bearer-stats.h" #include "mm-bearer-stats.h"
#include "mm-dispatcher-connection.h" #include "mm-dispatcher-connection.h"
#include "mm-auth-provider.h"
#include "mm-bind.h"
/* We require up to 20s to get a proper IP when using PPP */ /* We require up to 20s to get a proper IP when using PPP */
#define BEARER_IP_TIMEOUT_DEFAULT 20 #define BEARER_IP_TIMEOUT_DEFAULT 20
@@ -54,9 +55,11 @@
#define BEARER_CONNECTION_MONITOR_TIMEOUT 5 #define BEARER_CONNECTION_MONITOR_TIMEOUT 5
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
static void bind_iface_init (MMBindInterface *iface);
G_DEFINE_TYPE_EXTENDED (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON, 0, G_DEFINE_TYPE_EXTENDED (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_BIND, bind_iface_init))
typedef enum { typedef enum {
CONNECTION_FORBIDDEN_REASON_NONE, CONNECTION_FORBIDDEN_REASON_NONE,
@@ -70,6 +73,7 @@ enum {
PROP_0, PROP_0,
PROP_PATH, PROP_PATH,
PROP_CONNECTION, PROP_CONNECTION,
PROP_BIND_TO,
PROP_MODEM, PROP_MODEM,
PROP_STATUS, PROP_STATUS,
PROP_CONFIG, PROP_CONFIG,
@@ -83,6 +87,13 @@ struct _MMBaseBearerPrivate {
GDBusConnection *connection; GDBusConnection *connection;
guint dbus_id; guint dbus_id;
/* The authorization provider */
MMAuthProvider *authp;
GCancellable *authp_cancellable;
/* The object this bearer is bound to */
GObject *bind_to;
/* The modem which owns this BEARER */ /* The modem which owns this BEARER */
MMBaseModem *modem; MMBaseModem *modem;
/* The path where the BEARER object is exported */ /* The path where the BEARER object is exported */
@@ -461,7 +472,7 @@ dispatcher_connection_run_ready (MMDispatcherConnection *dispatcher,
static void static void
bearer_run_dispatcher_scripts (MMBaseBearer *self, bearer_run_dispatcher_scripts (MMBaseBearer *self,
gboolean connected) MMDispatcherConnectionEvent event)
{ {
MMDispatcherConnection *dispatcher; MMDispatcherConnection *dispatcher;
const gchar *interface; const gchar *interface;
@@ -475,7 +486,7 @@ bearer_run_dispatcher_scripts (MMBaseBearer *self,
g_dbus_object_get_object_path (G_DBUS_OBJECT (self->priv->modem)), g_dbus_object_get_object_path (G_DBUS_OBJECT (self->priv->modem)),
self->priv->path, self->priv->path,
interface, interface,
connected, event,
NULL, /* cancellable */ NULL, /* cancellable */
(GAsyncReadyCallback)dispatcher_connection_run_ready, (GAsyncReadyCallback)dispatcher_connection_run_ready,
g_object_ref (self)); g_object_ref (self));
@@ -489,6 +500,7 @@ bearer_reset_interface_status (MMBaseBearer *self)
mm_gdbus_bearer_set_profile_id (MM_GDBUS_BEARER (self), MM_3GPP_PROFILE_ID_UNKNOWN); mm_gdbus_bearer_set_profile_id (MM_GDBUS_BEARER (self), MM_3GPP_PROFILE_ID_UNKNOWN);
mm_gdbus_bearer_set_multiplexed (MM_GDBUS_BEARER (self), FALSE); mm_gdbus_bearer_set_multiplexed (MM_GDBUS_BEARER (self), FALSE);
mm_gdbus_bearer_set_connected (MM_GDBUS_BEARER (self), FALSE); mm_gdbus_bearer_set_connected (MM_GDBUS_BEARER (self), FALSE);
mm_gdbus_bearer_set_disconnect_request (MM_GDBUS_BEARER (self), FALSE);
mm_gdbus_bearer_set_suspended (MM_GDBUS_BEARER (self), FALSE); mm_gdbus_bearer_set_suspended (MM_GDBUS_BEARER (self), FALSE);
mm_gdbus_bearer_set_interface (MM_GDBUS_BEARER (self), NULL); mm_gdbus_bearer_set_interface (MM_GDBUS_BEARER (self), NULL);
mm_gdbus_bearer_set_ip4_config ( mm_gdbus_bearer_set_ip4_config (
@@ -520,7 +532,7 @@ bearer_update_status (MMBaseBearer *self,
g_autoptr(GString) report = NULL; g_autoptr(GString) report = NULL;
/* Report disconnection via dispatcher scripts, before resetting the interface */ /* Report disconnection via dispatcher scripts, before resetting the interface */
bearer_run_dispatcher_scripts (self, FALSE); bearer_run_dispatcher_scripts (self, MM_DISPATCHER_CONNECTION_EVENT_DISCONNECTED);
bearer_reset_interface_status (self); bearer_reset_interface_status (self);
/* Cleanup flag to ignore disconnection reports */ /* Cleanup flag to ignore disconnection reports */
@@ -588,7 +600,7 @@ bearer_update_status_connected (MMBaseBearer *self,
connection_monitor_start (self); connection_monitor_start (self);
/* Run dispatcher scripts */ /* Run dispatcher scripts */
bearer_run_dispatcher_scripts (self, TRUE); bearer_run_dispatcher_scripts (self, MM_DISPATCHER_CONNECTION_EVENT_CONNECTED);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -1118,7 +1130,6 @@ mm_base_bearer_connect (MMBaseBearer *self,
typedef struct { typedef struct {
MMBaseBearer *self; MMBaseBearer *self;
MMBaseModem *modem;
GDBusMethodInvocation *invocation; GDBusMethodInvocation *invocation;
} HandleConnectContext; } HandleConnectContext;
@@ -1126,7 +1137,6 @@ static void
handle_connect_context_free (HandleConnectContext *ctx) handle_connect_context_free (HandleConnectContext *ctx)
{ {
g_object_unref (ctx->invocation); g_object_unref (ctx->invocation);
g_object_unref (ctx->modem);
g_object_unref (ctx->self); g_object_unref (ctx->self);
g_free (ctx); g_free (ctx);
} }
@@ -1147,13 +1157,13 @@ handle_connect_ready (MMBaseBearer *self,
} }
static void static void
handle_connect_auth_ready (MMBaseModem *modem, handle_connect_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleConnectContext *ctx) HandleConnectContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_connect_context_free (ctx); handle_connect_context_free (ctx);
return; return;
@@ -1174,15 +1184,13 @@ handle_connect (MMBaseBearer *self,
ctx = g_new0 (HandleConnectContext, 1); ctx = g_new0 (HandleConnectContext, 1);
ctx->self = g_object_ref (self); ctx->self = g_object_ref (self);
ctx->invocation = g_object_ref (invocation); ctx->invocation = g_object_ref (invocation);
g_object_get (self,
MM_BASE_BEARER_MODEM, &ctx->modem,
NULL);
mm_base_modem_authorize (ctx->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_connect_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_connect_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -1307,7 +1315,6 @@ mm_base_bearer_disconnect (MMBaseBearer *self,
typedef struct { typedef struct {
MMBaseBearer *self; MMBaseBearer *self;
MMBaseModem *modem;
GDBusMethodInvocation *invocation; GDBusMethodInvocation *invocation;
} HandleDisconnectContext; } HandleDisconnectContext;
@@ -1315,7 +1322,6 @@ static void
handle_disconnect_context_free (HandleDisconnectContext *ctx) handle_disconnect_context_free (HandleDisconnectContext *ctx)
{ {
g_object_unref (ctx->invocation); g_object_unref (ctx->invocation);
g_object_unref (ctx->modem);
g_object_unref (ctx->self); g_object_unref (ctx->self);
g_free (ctx); g_free (ctx);
} }
@@ -1336,13 +1342,13 @@ handle_disconnect_ready (MMBaseBearer *self,
} }
static void static void
handle_disconnect_auth_ready (MMBaseModem *modem, handle_disconnect_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleDisconnectContext *ctx) HandleDisconnectContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_disconnect_context_free (ctx); handle_disconnect_context_free (ctx);
return; return;
@@ -1363,15 +1369,13 @@ handle_disconnect (MMBaseBearer *self,
ctx = g_new0 (HandleDisconnectContext, 1); ctx = g_new0 (HandleDisconnectContext, 1);
ctx->self = g_object_ref (self); ctx->self = g_object_ref (self);
ctx->invocation = g_object_ref (invocation); ctx->invocation = g_object_ref (invocation);
g_object_get (self,
MM_BASE_BEARER_MODEM, &ctx->modem,
NULL);
mm_base_modem_authorize (ctx->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_disconnect_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_disconnect_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -1488,11 +1492,14 @@ mm_base_bearer_disconnect_force (MMBaseBearer *self)
return; return;
if (self->priv->ignore_disconnection_reports) { if (self->priv->ignore_disconnection_reports) {
mm_obj_dbg (self, "disconnection should be forced but it's explicitly ignored"); mm_obj_msg (self, "disconnection should be forced, but we can't. Request disconnection instead.");
mm_gdbus_bearer_set_disconnect_request (MM_GDBUS_BEARER(self), TRUE);
bearer_run_dispatcher_scripts (self,
MM_DISPATCHER_CONNECTION_EVENT_DISCONNECT_REQUEST);
return; return;
} }
mm_obj_dbg (self, "forcing disconnection"); mm_obj_msg (self, "forcing disconnection");
/* If currently connecting, try to cancel that operation. */ /* If currently connecting, try to cancel that operation. */
if (self->priv->status == MM_BEARER_STATUS_CONNECTING) { if (self->priv->status == MM_BEARER_STATUS_CONNECTING) {
@@ -1747,17 +1754,15 @@ set_property (GObject *object,
else if (self->priv->path) else if (self->priv->path)
base_bearer_dbus_export (self); base_bearer_dbus_export (self);
break; break;
case PROP_BIND_TO:
g_clear_object (&self->priv->bind_to);
self->priv->bind_to = g_value_dup_object (value);
mm_bind_to (MM_BIND (self), MM_BASE_BEARER_CONNECTION, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
self->priv->modem = g_value_dup_object (value); self->priv->modem = g_value_dup_object (value);
if (self->priv->modem) { if (self->priv->modem) {
/* Set owner ID */
mm_log_object_set_owner_id (MM_LOG_OBJECT (self), mm_log_object_get_id (MM_LOG_OBJECT (self->priv->modem)));
/* Bind the modem's connection (which is set when it is exported,
* and unset when unexported) to the BEARER's connection */
g_object_bind_property (self->priv->modem, MM_BASE_MODEM_CONNECTION,
self, MM_BASE_BEARER_CONNECTION,
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
if (self->priv->config) { if (self->priv->config) {
/* Listen to 3GPP/CDMA registration state changes. We need both /* Listen to 3GPP/CDMA registration state changes. We need both
* 'config' and 'modem' set. */ * 'config' and 'modem' set. */
@@ -1807,6 +1812,9 @@ get_property (GObject *object,
case PROP_CONNECTION: case PROP_CONNECTION:
g_value_set_object (value, self->priv->connection); g_value_set_object (value, self->priv->connection);
break; break;
case PROP_BIND_TO:
g_value_set_object (value, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_value_set_object (value, self->priv->modem); g_value_set_object (value, self->priv->modem);
break; break;
@@ -1835,6 +1843,10 @@ mm_base_bearer_init (MMBaseBearer *self)
/* Each bearer is given a unique id to build its own DBus path */ /* Each bearer is given a unique id to build its own DBus path */
self->priv->dbus_id = id++; self->priv->dbus_id = id++;
/* Setup authorization provider */
self->priv->authp = mm_auth_provider_get ();
self->priv->authp_cancellable = g_cancellable_new ();
self->priv->status = MM_BEARER_STATUS_DISCONNECTED; self->priv->status = MM_BEARER_STATUS_DISCONNECTED;
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE; self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE;
self->priv->reason_cdma = CONNECTION_FORBIDDEN_REASON_NONE; self->priv->reason_cdma = CONNECTION_FORBIDDEN_REASON_NONE;
@@ -1885,7 +1897,10 @@ dispose (GObject *object)
reset_deferred_unregistration (self); reset_deferred_unregistration (self);
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
g_clear_object (&self->priv->bind_to);
g_clear_object (&self->priv->config); g_clear_object (&self->priv->config);
g_cancellable_cancel (self->priv->authp_cancellable);
g_clear_object (&self->priv->authp_cancellable);
G_OBJECT_CLASS (mm_base_bearer_parent_class)->dispose (object); G_OBJECT_CLASS (mm_base_bearer_parent_class)->dispose (object);
} }
@@ -1896,6 +1911,11 @@ log_object_iface_init (MMLogObjectInterface *iface)
iface->build_id = log_object_build_id; iface->build_id = log_object_build_id;
} }
static void
bind_iface_init (MMBindInterface *iface)
{
}
static void static void
mm_base_bearer_class_init (MMBaseBearerClass *klass) mm_base_bearer_class_init (MMBaseBearerClass *klass)
{ {
@@ -1927,6 +1947,8 @@ mm_base_bearer_class_init (MMBaseBearerClass *klass)
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PATH, properties[PROP_PATH]); g_object_class_install_property (object_class, PROP_PATH, properties[PROP_PATH]);
g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO);
properties[PROP_MODEM] = properties[PROP_MODEM] =
g_param_spec_object (MM_BASE_BEARER_MODEM, g_param_spec_object (MM_BASE_BEARER_MODEM,
"Modem", "Modem",
+450 -460
View File
File diff suppressed because it is too large Load Diff
+28 -18
View File
@@ -23,8 +23,8 @@
#define _LIBMM_INSIDE_MM #define _LIBMM_INSIDE_MM
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-base-modem.h"
#include "mm-call-audio-format.h" #include "mm-call-audio-format.h"
#include "mm-port.h"
#define MM_TYPE_BASE_CALL (mm_base_call_get_type ()) #define MM_TYPE_BASE_CALL (mm_base_call_get_type ())
#define MM_BASE_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BASE_CALL, MMBaseCall)) #define MM_BASE_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BASE_CALL, MMBaseCall))
@@ -37,9 +37,13 @@ typedef struct _MMBaseCall MMBaseCall;
typedef struct _MMBaseCallClass MMBaseCallClass; typedef struct _MMBaseCallClass MMBaseCallClass;
typedef struct _MMBaseCallPrivate MMBaseCallPrivate; typedef struct _MMBaseCallPrivate MMBaseCallPrivate;
#define MM_CALL_DIRECTION "direction"
#define MM_CALL_NUMBER "number"
#define MM_CALL_DTMF_TONE_DURATION "dtmf-tone-duration"
#define MM_BASE_CALL_PATH "call-path" #define MM_BASE_CALL_PATH "call-path"
#define MM_BASE_CALL_CONNECTION "call-connection" #define MM_BASE_CALL_CONNECTION "call-connection"
#define MM_BASE_CALL_MODEM "call-modem" #define MM_BASE_CALL_IFACE_MODEM_VOICE "call-iface-modem-voice"
#define MM_BASE_CALL_SKIP_INCOMING_TIMEOUT "call-skip-incoming-timeout" #define MM_BASE_CALL_SKIP_INCOMING_TIMEOUT "call-skip-incoming-timeout"
#define MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING "call-supports-dialing-to-ringing" #define MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING "call-supports-dialing-to-ringing"
#define MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE "call-supports-ringing-to-active" #define MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE "call-supports-ringing-to-active"
@@ -86,27 +90,28 @@ struct _MMBaseCallClass {
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
/* Send a DTMF tone */ /* DTMF tone handling */
void (* send_dtmf) (MMBaseCall *self, void (* send_dtmf) (MMBaseCall *self,
const gchar *dtmf, const gchar *dtmf,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean (* send_dtmf_finish) (MMBaseCall *self, /* Returns the number of DTMF characters sent, or < 1 on error */
GAsyncResult *res, gssize (* send_dtmf_finish) (MMBaseCall *self,
GError **error); GAsyncResult *res,
GError **error);
void (* stop_dtmf) (MMBaseCall *self,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (* stop_dtmf_finish) (MMBaseCall *self,
GAsyncResult *res,
GError **error);
}; };
GType mm_base_call_get_type (void); GType mm_base_call_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseCall, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseCall, g_object_unref)
/* This one can be overridden by plugins */
MMBaseCall *mm_base_call_new (MMBaseModem *modem,
MMCallDirection direction,
const gchar *number,
gboolean skip_incoming_timeout,
gboolean supports_dialing_to_ringing,
gboolean supports_ringing_to_active);
void mm_base_call_export (MMBaseCall *self); void mm_base_call_export (MMBaseCall *self);
void mm_base_call_unexport (MMBaseCall *self); void mm_base_call_unexport (MMBaseCall *self);
@@ -137,4 +142,9 @@ void mm_base_call_received_dtmf (MMBaseCall *self,
void mm_base_call_incoming_refresh (MMBaseCall *self); void mm_base_call_incoming_refresh (MMBaseCall *self);
guint mm_base_call_get_dtmf_tone_duration (MMBaseCall *self);
void mm_base_call_set_dtmf_tone_duration (MMBaseCall *self,
guint duration_ms);
#endif /* MM_BASE_CALL_H */ #endif /* MM_BASE_CALL_H */
+30 -38
View File
@@ -25,26 +25,24 @@
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-base-cbm.h" #include "mm-base-cbm.h"
#include "mm-broadband-modem.h"
#include "mm-iface-modem.h"
#include "mm-iface-modem-cell-broadcast.h"
#include "mm-cbm-part.h" #include "mm-cbm-part.h"
#include "mm-base-modem-at.h"
#include "mm-base-modem.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-error-helpers.h" #include "mm-error-helpers.h"
#include "mm-bind.h"
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
static void bind_iface_init (MMBindInterface *iface);
G_DEFINE_TYPE_EXTENDED (MMBaseCbm, mm_base_cbm, MM_GDBUS_TYPE_CBM_SKELETON, 0, G_DEFINE_TYPE_EXTENDED (MMBaseCbm, mm_base_cbm, MM_GDBUS_TYPE_CBM_SKELETON, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_BIND, bind_iface_init))
enum { enum {
PROP_0, PROP_0,
PROP_PATH, PROP_PATH,
PROP_CONNECTION, PROP_CONNECTION,
PROP_MODEM, PROP_BIND_TO,
PROP_MAX_PARTS, PROP_MAX_PARTS,
PROP_SERIAL, PROP_SERIAL,
PROP_LAST PROP_LAST
@@ -57,8 +55,9 @@ struct _MMBaseCbmPrivate {
GDBusConnection *connection; GDBusConnection *connection;
guint dbus_id; guint dbus_id;
/* The modem which owns this CBM */ /* The object this CBM is bound to */
MMBaseModem *modem; GObject *bind_to;
/* The path where the CBM object is exported */ /* The path where the CBM object is exported */
gchar *path; gchar *path;
@@ -174,6 +173,7 @@ initialize_cbm (MMBaseCbm *self)
"channel", mm_cbm_part_get_channel (part), "channel", mm_cbm_part_get_channel (part),
"update", CBM_SERIAL_MESSAGE_CODE_UPDATE (serial), "update", CBM_SERIAL_MESSAGE_CODE_UPDATE (serial),
"message-code", CBM_SERIAL_MESSAGE_CODE (serial), "message-code", CBM_SERIAL_MESSAGE_CODE (serial),
"language", mm_cbm_part_get_language (part),
NULL); NULL);
} }
@@ -323,15 +323,15 @@ mm_base_cbm_take_part (MMBaseCbm *self,
} }
MMBaseCbm * MMBaseCbm *
mm_base_cbm_new (MMBaseModem *modem) mm_base_cbm_new (GObject *bind_to)
{ {
return MM_BASE_CBM (g_object_new (MM_TYPE_BASE_CBM, return MM_BASE_CBM (g_object_new (MM_TYPE_BASE_CBM,
MM_BASE_CBM_MODEM, modem, MM_BIND_TO, bind_to,
NULL)); NULL));
} }
MMBaseCbm * MMBaseCbm *
mm_base_cbm_new_with_part (MMBaseModem *modem, mm_base_cbm_new_with_part (GObject *bind_to,
MMCbmState state, MMCbmState state,
guint max_parts, guint max_parts,
MMCbmPart *first_part, MMCbmPart *first_part,
@@ -339,13 +339,11 @@ mm_base_cbm_new_with_part (MMBaseModem *modem,
{ {
MMBaseCbm *self; MMBaseCbm *self;
g_assert (MM_IS_IFACE_MODEM_CELL_BROADCAST (modem));
if (state == MM_CBM_STATE_RECEIVED) if (state == MM_CBM_STATE_RECEIVED)
state = MM_CBM_STATE_RECEIVING; state = MM_CBM_STATE_RECEIVING;
/* Create a CBM object as defined by the interface */ /* Create a CBM object as defined by the interface */
self = mm_iface_modem_cell_broadcast_create_cbm (MM_IFACE_MODEM_CELL_BROADCAST (modem)); self = mm_base_cbm_new (bind_to);
g_object_set (self, g_object_set (self,
MM_BASE_CBM_MAX_PARTS, max_parts, MM_BASE_CBM_MAX_PARTS, max_parts,
"state", state, "state", state,
@@ -405,18 +403,10 @@ set_property (GObject *object,
else if (self->priv->path) else if (self->priv->path)
cbm_dbus_export (self); cbm_dbus_export (self);
break; break;
case PROP_MODEM: case PROP_BIND_TO:
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->bind_to);
self->priv->modem = g_value_dup_object (value); self->priv->bind_to = g_value_dup_object (value);
if (self->priv->modem) { mm_bind_to (MM_BIND (self), MM_BASE_CBM_CONNECTION, self->priv->bind_to);
/* Set owner ID */
mm_log_object_set_owner_id (MM_LOG_OBJECT (self), mm_log_object_get_id (MM_LOG_OBJECT (self->priv->modem)));
/* Bind the modem's connection (which is set when it is exported,
* and unset when unexported) to the CBM's connection */
g_object_bind_property (self->priv->modem, MM_BASE_MODEM_CONNECTION,
self, MM_BASE_CBM_CONNECTION,
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
}
break; break;
case PROP_MAX_PARTS: case PROP_MAX_PARTS:
self->priv->max_parts = g_value_get_uint (value); self->priv->max_parts = g_value_get_uint (value);
@@ -445,8 +435,8 @@ get_property (GObject *object,
case PROP_CONNECTION: case PROP_CONNECTION:
g_value_set_object (value, self->priv->connection); g_value_set_object (value, self->priv->connection);
break; break;
case PROP_MODEM: case PROP_BIND_TO:
g_value_set_object (value, self->priv->modem); g_value_set_object (value, self->priv->bind_to);
break; break;
case PROP_MAX_PARTS: case PROP_MAX_PARTS:
g_value_set_uint (value, self->priv->max_parts); g_value_set_uint (value, self->priv->max_parts);
@@ -496,7 +486,7 @@ dispose (GObject *object)
g_clear_object (&self->priv->connection); g_clear_object (&self->priv->connection);
} }
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->bind_to);
G_OBJECT_CLASS (mm_base_cbm_parent_class)->dispose (object); G_OBJECT_CLASS (mm_base_cbm_parent_class)->dispose (object);
} }
@@ -507,6 +497,11 @@ log_object_iface_init (MMLogObjectInterface *iface)
iface->build_id = log_object_build_id; iface->build_id = log_object_build_id;
} }
static void
bind_iface_init (MMBindInterface *iface)
{
}
static void static void
mm_base_cbm_class_init (MMBaseCbmClass *klass) mm_base_cbm_class_init (MMBaseCbmClass *klass)
{ {
@@ -526,6 +521,7 @@ mm_base_cbm_class_init (MMBaseCbmClass *klass)
"GDBus connection to the system bus.", "GDBus connection to the system bus.",
G_TYPE_DBUS_CONNECTION, G_TYPE_DBUS_CONNECTION,
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_CONNECTION, properties[PROP_CONNECTION]);
properties[PROP_PATH] = properties[PROP_PATH] =
g_param_spec_string (MM_BASE_CBM_PATH, g_param_spec_string (MM_BASE_CBM_PATH,
@@ -533,13 +529,9 @@ mm_base_cbm_class_init (MMBaseCbmClass *klass)
"DBus path of the CBM", "DBus path of the CBM",
NULL, NULL,
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PATH, properties[PROP_PATH]);
properties[PROP_MODEM] = g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO);
g_param_spec_object (MM_BASE_CBM_MODEM,
"Modem",
"The Modem which owns this CBM",
MM_TYPE_BASE_MODEM,
G_PARAM_READWRITE);
properties[PROP_MAX_PARTS] = properties[PROP_MAX_PARTS] =
g_param_spec_uint (MM_BASE_CBM_MAX_PARTS, g_param_spec_uint (MM_BASE_CBM_MAX_PARTS,
@@ -547,6 +539,7 @@ mm_base_cbm_class_init (MMBaseCbmClass *klass)
"Maximum number of parts composing this CBM", "Maximum number of parts composing this CBM",
1, 255, 1, 1, 255, 1,
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_MAX_PARTS, properties[PROP_MAX_PARTS]);
properties[PROP_SERIAL] = properties[PROP_SERIAL] =
g_param_spec_uint (MM_BASE_CBM_SERIAL, g_param_spec_uint (MM_BASE_CBM_SERIAL,
@@ -554,8 +547,7 @@ mm_base_cbm_class_init (MMBaseCbmClass *klass)
"The serial of this CBM", "The serial of this CBM",
0, G_MAXUINT16, 0, 0, G_MAXUINT16, 0,
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_SERIAL, properties[PROP_SERIAL]);
g_object_class_install_properties (object_class, PROP_LAST, properties);
} }
guint16 guint16
+2 -4
View File
@@ -23,7 +23,6 @@
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-cbm-part.h" #include "mm-cbm-part.h"
#include "mm-base-modem.h"
/*****************************************************************************/ /*****************************************************************************/
@@ -40,7 +39,6 @@ typedef struct _MMBaseCbmPrivate MMBaseCbmPrivate;
#define MM_BASE_CBM_PATH "cbm-path" #define MM_BASE_CBM_PATH "cbm-path"
#define MM_BASE_CBM_CONNECTION "cbm-connection" #define MM_BASE_CBM_CONNECTION "cbm-connection"
#define MM_BASE_CBM_MODEM "cbm-modem"
#define MM_BASE_CBM_MAX_PARTS "cbm-max-parts" #define MM_BASE_CBM_MAX_PARTS "cbm-max-parts"
#define MM_BASE_CBM_SERIAL "cbm-serial" #define MM_BASE_CBM_SERIAL "cbm-serial"
@@ -56,11 +54,11 @@ struct _MMBaseCbmClass {
GType mm_base_cbm_get_type (void); GType mm_base_cbm_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseCbm, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseCbm, g_object_unref)
MMBaseCbm *mm_base_cbm_new (MMBaseModem *modem); MMBaseCbm *mm_base_cbm_new (GObject *bind_to);
gboolean mm_base_cbm_take_part (MMBaseCbm *self, gboolean mm_base_cbm_take_part (MMBaseCbm *self,
MMCbmPart *part, MMCbmPart *part,
GError **error); GError **error);
MMBaseCbm *mm_base_cbm_new_with_part (MMBaseModem *modem, MMBaseCbm *mm_base_cbm_new_with_part (GObject *bind_to,
MMCbmState state, MMCbmState state,
guint max_parts, guint max_parts,
MMCbmPart *first_part, MMCbmPart *first_part,
+4 -4
View File
@@ -1014,8 +1014,8 @@ device_cleanup_step (GTask *task)
"disabling modem%d", "disabling modem%d",
mm_base_modem_get_dbus_id (ctx->modem)); mm_base_modem_get_dbus_id (ctx->modem));
mm_base_modem_disable (ctx->modem, mm_base_modem_disable (ctx->modem,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MM_OPERATION_LOCK_REQUIRED,
MM_BASE_MODEM_OPERATION_PRIORITY_OVERRIDE, MM_OPERATION_PRIORITY_OVERRIDE,
(GAsyncReadyCallback)cleanup_disable_ready, (GAsyncReadyCallback)cleanup_disable_ready,
task); task);
return; return;
@@ -1058,7 +1058,7 @@ device_cleanup_step (GTask *task)
"settting terse on modem%d", "settting terse on modem%d",
mm_base_modem_get_dbus_id (ctx->modem)); mm_base_modem_get_dbus_id (ctx->modem));
mm_base_modem_terse (ctx->modem, mm_base_modem_terse (ctx->modem,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MM_OPERATION_LOCK_REQUIRED,
(GAsyncReadyCallback)cleanup_terse_ready, (GAsyncReadyCallback)cleanup_terse_ready,
task); task);
return; return;
@@ -1289,7 +1289,7 @@ mm_base_manager_sync (MMBaseManager *self)
/* We just want to start the synchronization, we don't need the result */ /* We just want to start the synchronization, we don't need the result */
if (modem) { if (modem) {
mm_base_modem_sync (modem, mm_base_modem_sync (modem,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MM_OPERATION_LOCK_REQUIRED,
(GAsyncReadyCallback)base_modem_sync_ready, (GAsyncReadyCallback)base_modem_sync_ready,
NULL); NULL);
} }
+175 -109
View File
@@ -39,11 +39,16 @@
#include "mm-daemon-enums-types.h" #include "mm-daemon-enums-types.h"
#include "mm-serial-parsers.h" #include "mm-serial-parsers.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-bind.h"
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
static void auth_iface_init (MMIfaceAuthInterface *iface);
static void op_lock_iface_init (MMIfaceOpLockInterface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MMBaseModem, mm_base_modem, MM_GDBUS_TYPE_OBJECT_SKELETON, G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MMBaseModem, mm_base_modem, MM_GDBUS_TYPE_OBJECT_SKELETON,
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_AUTH, auth_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_OP_LOCK, op_lock_iface_init))
/* If we get 10 consecutive timeouts in a serial port, we consider the modem /* If we get 10 consecutive timeouts in a serial port, we consider the modem
* invalid and we request re-probing. */ * invalid and we request re-probing. */
@@ -150,6 +155,16 @@ struct _MMBaseModemPrivate {
gboolean scheduled_operations_forbidden_forever; gboolean scheduled_operations_forbidden_forever;
}; };
static void mm_base_modem_operation_lock (MMBaseModem *self,
MMOperationPriority priority,
const gchar *description,
GAsyncReadyCallback callback,
gpointer user_data);
static gssize mm_base_modem_operation_lock_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
guint guint
mm_base_modem_get_dbus_id (MMBaseModem *self) mm_base_modem_get_dbus_id (MMBaseModem *self)
{ {
@@ -192,11 +207,13 @@ port_timed_out_cb (MMPort *port,
static MMPort * static MMPort *
base_modem_create_ignored_port (MMBaseModem *self, base_modem_create_ignored_port (MMBaseModem *self,
MMPortType ptype,
const gchar *name) const gchar *name)
{ {
return MM_PORT (g_object_new (MM_TYPE_PORT, return MM_PORT (g_object_new (MM_TYPE_PORT,
MM_PORT_DEVICE, name, MM_PORT_DEVICE, name,
MM_PORT_TYPE, MM_PORT_TYPE_IGNORED, MM_PORT_GROUP, MM_PORT_GROUP_IGNORED,
MM_PORT_TYPE, ptype,
NULL)); NULL));
} }
@@ -328,6 +345,7 @@ base_modem_create_wwan_port (MMBaseModem *self,
return MM_PORT (g_object_new (MM_TYPE_PORT, return MM_PORT (g_object_new (MM_TYPE_PORT,
MM_PORT_DEVICE, name, MM_PORT_DEVICE, name,
MM_PORT_SUBSYS, MM_PORT_SUBSYS_WWAN, MM_PORT_SUBSYS, MM_PORT_SUBSYS_WWAN,
MM_PORT_GROUP, MM_PORT_GROUP_USED,
MM_PORT_TYPE, MM_PORT_TYPE_XMMRPC, MM_PORT_TYPE, MM_PORT_TYPE_XMMRPC,
NULL)); NULL));
@@ -345,6 +363,7 @@ static MMPort *
base_modem_internal_grab_port (MMBaseModem *self, base_modem_internal_grab_port (MMBaseModem *self,
MMKernelDevice *kernel_device, MMKernelDevice *kernel_device,
gboolean link_port, gboolean link_port,
MMPortGroup pgroup,
MMPortType ptype, MMPortType ptype,
MMPortSerialAtFlag at_pflags, MMPortSerialAtFlag at_pflags,
GError **error) GError **error)
@@ -379,8 +398,8 @@ base_modem_internal_grab_port (MMBaseModem *self,
/* Explicitly ignored ports, grab them but explicitly flag them as ignored /* Explicitly ignored ports, grab them but explicitly flag them as ignored
* right away, all the same way (i.e. regardless of subsystem). */ * right away, all the same way (i.e. regardless of subsystem). */
if (ptype == MM_PORT_TYPE_IGNORED) if (pgroup == MM_PORT_GROUP_IGNORED)
port = base_modem_create_ignored_port (self, name); port = base_modem_create_ignored_port (self, ptype, name);
else if (g_str_equal (subsys, "net")) else if (g_str_equal (subsys, "net"))
port = base_modem_create_net_port (self, name); port = base_modem_create_net_port (self, name);
else if (g_str_equal (subsys, "tty")) else if (g_str_equal (subsys, "tty"))
@@ -405,25 +424,38 @@ base_modem_internal_grab_port (MMBaseModem *self,
} }
/* Setup consecutive ports and removal watchers in all control ports */ /* Setup consecutive ports and removal watchers in all control ports */
if (MM_IS_PORT_SERIAL_AT (port)) { if (pgroup == MM_PORT_GROUP_USED) {
mm_obj_dbg (port, "port monitoring enabled in AT port"); if (MM_IS_PORT_SERIAL_AT (port)) {
port_monitoring = TRUE; mm_obj_dbg (port, "port monitoring enabled in AT port");
} else if (MM_IS_PORT_SERIAL_QCDM (port)) { port_monitoring = TRUE;
mm_obj_dbg (port, "port monitoring enabled in QCDM port"); } else if (MM_IS_PORT_SERIAL_QCDM (port)) {
port_monitoring = TRUE; mm_obj_dbg (port, "port monitoring enabled in QCDM port");
} port_monitoring = TRUE;
}
#if defined WITH_QMI #if defined WITH_QMI
else if (MM_IS_PORT_QMI (port)) { else if (MM_IS_PORT_QMI (port)) {
mm_obj_dbg (port, "port monitoring enabled in QMI port"); mm_obj_dbg (port, "port monitoring enabled in QMI port");
port_monitoring = TRUE; port_monitoring = TRUE;
} }
#endif #endif
#if defined WITH_MBIM #if defined WITH_MBIM
else if (MM_IS_PORT_MBIM (port)) { else if (MM_IS_PORT_MBIM (port)) {
mm_obj_dbg (port, "port monitoring enabled in MBIM port"); mm_obj_dbg (port, "port monitoring enabled in MBIM port");
port_monitoring = TRUE; port_monitoring = TRUE;
} }
#endif #endif
}
/* Check if a custom max timeouts value is set via udev */
if (mm_kernel_device_has_global_property (kernel_device, ID_MM_MAX_TIMEOUTS)) {
guint max_timeouts;
max_timeouts = mm_kernel_device_get_global_property_as_int (kernel_device, ID_MM_MAX_TIMEOUTS);
if (max_timeouts != self->priv->max_timeouts) {
mm_obj_dbg (self, "max timeouts overridden via udev: %u", max_timeouts);
self->priv->max_timeouts = max_timeouts;
}
}
if (port_monitoring) { if (port_monitoring) {
if (self->priv->max_timeouts > 0) if (self->priv->max_timeouts > 0)
@@ -447,6 +479,7 @@ base_modem_internal_grab_port (MMBaseModem *self,
if (MM_IS_PORT_SERIAL_AT (port)) { if (MM_IS_PORT_SERIAL_AT (port)) {
mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port), mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port),
mm_serial_parser_v1_parse, mm_serial_parser_v1_parse,
mm_serial_parser_v1_remove_echo,
mm_serial_parser_v1_new (), mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy); mm_serial_parser_v1_destroy);
/* Prefer plugin-provided flags to the generic ones */ /* Prefer plugin-provided flags to the generic ones */
@@ -489,13 +522,14 @@ base_modem_internal_grab_port (MMBaseModem *self,
gboolean gboolean
mm_base_modem_grab_port (MMBaseModem *self, mm_base_modem_grab_port (MMBaseModem *self,
MMKernelDevice *kernel_device, MMKernelDevice *kernel_device,
MMPortGroup pgroup,
MMPortType ptype, MMPortType ptype,
MMPortSerialAtFlag at_pflags, MMPortSerialAtFlag at_pflags,
GError **error) GError **error)
{ {
g_autoptr(GError) inner_error = NULL; g_autoptr(GError) inner_error = NULL;
if (!base_modem_internal_grab_port (self, kernel_device, FALSE, ptype, at_pflags, &inner_error)) { if (!base_modem_internal_grab_port (self, kernel_device, FALSE, pgroup, ptype, at_pflags, &inner_error)) {
/* If the port was REQUIRED via udev tags and we failed to grab it, we will report /* If the port was REQUIRED via udev tags and we failed to grab it, we will report
* a fatal error. */ * a fatal error. */
if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_REQUIRED)) { if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_REQUIRED)) {
@@ -542,6 +576,7 @@ mm_base_modem_grab_link_port (MMBaseModem *self,
port = base_modem_internal_grab_port (self, port = base_modem_internal_grab_port (self,
kernel_device, kernel_device,
TRUE, TRUE,
MM_PORT_GROUP_USED,
MM_PORT_TYPE_NET, MM_PORT_TYPE_NET,
MM_PORT_SERIAL_AT_FLAG_NONE, MM_PORT_SERIAL_AT_FLAG_NONE,
error); error);
@@ -767,7 +802,7 @@ state_operation_ready (MMBaseModem *self,
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
if (ctx->operation_id >= 0) { if (ctx->operation_id >= 0) {
mm_base_modem_operation_unlock (self, ctx->operation_id); mm_iface_op_lock_unlock (MM_IFACE_OP_LOCK (self), ctx->operation_id);
ctx->operation_id = (gssize) -1; ctx->operation_id = (gssize) -1;
} }
@@ -814,12 +849,12 @@ lock_before_state_operation_ready (MMBaseModem *self,
} }
static void static void
state_operation (MMBaseModem *self, state_operation (MMBaseModem *self,
StateOperationType operation_type, StateOperationType operation_type,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
MMBaseModemOperationPriority operation_priority, MMOperationPriority operation_priority,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
StateOperationContext *ctx; StateOperationContext *ctx;
@@ -877,12 +912,12 @@ state_operation (MMBaseModem *self,
} }
g_assert (ctx->operation && ctx->operation_finish); g_assert (ctx->operation && ctx->operation_finish);
if (operation_lock == MM_BASE_MODEM_OPERATION_LOCK_ALREADY_ACQUIRED) { if (operation_lock == MM_OPERATION_LOCK_ALREADY_ACQUIRED) {
state_operation_run (task); state_operation_run (task);
return; return;
} }
g_assert (operation_lock == MM_BASE_MODEM_OPERATION_LOCK_REQUIRED); g_assert (operation_lock == MM_OPERATION_LOCK_REQUIRED);
mm_base_modem_operation_lock (self, mm_base_modem_operation_lock (self,
operation_priority, operation_priority,
operation_description, operation_description,
@@ -904,14 +939,14 @@ mm_base_modem_sync_finish (MMBaseModem *self,
void void
mm_base_modem_sync (MMBaseModem *self, mm_base_modem_sync (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
state_operation (self, state_operation (self,
STATE_OPERATION_TYPE_SYNC, STATE_OPERATION_TYPE_SYNC,
operation_lock, operation_lock,
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT, MM_OPERATION_PRIORITY_DEFAULT,
callback, callback,
user_data); user_data);
} }
@@ -926,14 +961,14 @@ mm_base_modem_terse_finish (MMBaseModem *self,
void void
mm_base_modem_terse (MMBaseModem *self, mm_base_modem_terse (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
state_operation (self, state_operation (self,
STATE_OPERATION_TYPE_TERSE, STATE_OPERATION_TYPE_TERSE,
operation_lock, operation_lock,
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT, MM_OPERATION_PRIORITY_DEFAULT,
callback, callback,
user_data); user_data);
} }
@@ -951,11 +986,11 @@ mm_base_modem_disable_finish (MMBaseModem *self,
} }
void void
mm_base_modem_disable (MMBaseModem *self, mm_base_modem_disable (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
MMBaseModemOperationPriority operation_priority, MMOperationPriority operation_priority,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
state_operation (self, state_operation (self,
STATE_OPERATION_TYPE_DISABLE, STATE_OPERATION_TYPE_DISABLE,
@@ -976,15 +1011,15 @@ mm_base_modem_enable_finish (MMBaseModem *self,
} }
void void
mm_base_modem_enable (MMBaseModem *self, mm_base_modem_enable (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
state_operation (self, state_operation (self,
STATE_OPERATION_TYPE_ENABLE, STATE_OPERATION_TYPE_ENABLE,
operation_lock, operation_lock,
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT, MM_OPERATION_PRIORITY_DEFAULT,
callback, callback,
user_data); user_data);
} }
@@ -1000,15 +1035,15 @@ mm_base_modem_initialize_finish (MMBaseModem *self,
} }
void void
mm_base_modem_initialize (MMBaseModem *self, mm_base_modem_initialize (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
state_operation (self, state_operation (self,
STATE_OPERATION_TYPE_INITIALIZE, STATE_OPERATION_TYPE_INITIALIZE,
operation_lock, operation_lock,
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT, MM_OPERATION_PRIORITY_DEFAULT,
callback, callback,
user_data); user_data);
} }
@@ -1295,25 +1330,28 @@ port_info_cmp (const MMModemPortInfo *a,
return g_strcmp0 (a->name, b->name); return g_strcmp0 (a->name, b->name);
} }
MMModemPortInfo * static MMModemPortInfo *
mm_base_modem_get_port_infos (MMBaseModem *self, parse_port_infos (GHashTable *ports,
guint *n_port_infos) guint *n_port_infos,
MMPortGroup pgroup_filter)
{ {
GHashTableIter iter; GHashTableIter iter;
GArray *port_infos; GArray *port_infos;
MMPort *port; MMPort *port;
if (!self->priv->ports) { if (!ports) {
*n_port_infos = 0; *n_port_infos = 0;
return NULL; return NULL;
} }
*n_port_infos = g_hash_table_size (self->priv->ports); port_infos = g_array_new (FALSE, FALSE, sizeof (MMModemPortInfo));
port_infos = g_array_sized_new (FALSE, FALSE, sizeof (MMModemPortInfo), *n_port_infos); g_hash_table_iter_init (&iter, ports);
g_hash_table_iter_init (&iter, self->priv->ports);
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&port)) { while (g_hash_table_iter_next (&iter, NULL, (gpointer)&port)) {
MMModemPortInfo port_info; MMModemPortInfo port_info;
if (mm_port_get_port_group (port) != pgroup_filter)
continue;
port_info.name = g_strdup (mm_port_get_device (port)); port_info.name = g_strdup (mm_port_get_device (port));
switch (mm_port_get_port_type (port)) { switch (mm_port_get_port_type (port)) {
case MM_PORT_TYPE_NET: case MM_PORT_TYPE_NET:
@@ -1352,11 +1390,25 @@ mm_base_modem_get_port_infos (MMBaseModem *self,
g_array_append_val (port_infos, port_info); g_array_append_val (port_infos, port_info);
} }
g_assert (*n_port_infos == port_infos->len); *n_port_infos = port_infos->len;
g_array_sort (port_infos, (GCompareFunc) port_info_cmp); g_array_sort (port_infos, (GCompareFunc) port_info_cmp);
return (MMModemPortInfo *) g_array_free (port_infos, FALSE); return (MMModemPortInfo *) g_array_free (port_infos, FALSE);
} }
MMModemPortInfo *
mm_base_modem_get_port_infos (MMBaseModem *self,
guint *n_port_infos)
{
return parse_port_infos (self->priv->ports, n_port_infos, MM_PORT_GROUP_USED);
}
MMModemPortInfo *
mm_base_modem_get_ignored_port_infos (MMBaseModem *self,
guint *n_port_infos)
{
return parse_port_infos (self->priv->ports, n_port_infos, MM_PORT_GROUP_IGNORED);
}
static gint static gint
port_cmp (MMPort *a, port_cmp (MMPort *a,
MMPort *b) MMPort *b)
@@ -1498,6 +1550,10 @@ mm_base_modem_organize_ports (MMBaseModem *self,
g_hash_table_iter_init (&iter, self->priv->ports); g_hash_table_iter_init (&iter, self->priv->ports);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) { while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) {
/* Skip ports that should not be used */
if (mm_port_get_port_group (candidate) != MM_PORT_GROUP_USED)
continue;
switch (mm_port_get_port_type (candidate)) { switch (mm_port_get_port_type (candidate)) {
case MM_PORT_TYPE_AT: case MM_PORT_TYPE_AT:
@@ -1775,8 +1831,8 @@ mm_base_modem_organize_ports (MMBaseModem *self,
/*****************************************************************************/ /*****************************************************************************/
/* Authorization */ /* Authorization */
gboolean static gboolean
mm_base_modem_authorize_finish (MMBaseModem *self, mm_base_modem_authorize_finish (MMIfaceAuth *auth,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
@@ -1798,24 +1854,18 @@ authorize_ready (MMAuthProvider *authp,
g_object_unref (task); g_object_unref (task);
} }
void static void
mm_base_modem_authorize (MMBaseModem *self, mm_base_modem_authorize (MMIfaceAuth *auth,
GDBusMethodInvocation *invocation, GDBusMethodInvocation *invocation,
const gchar *authorization, const gchar *authorization,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task; MMBaseModem *self = MM_BASE_MODEM (auth);
GTask *task;
task = g_task_new (self, self->priv->authp_cancellable, callback, user_data); task = g_task_new (self, self->priv->authp_cancellable, callback, user_data);
/* When running in the session bus for tests, default to always allow */
if (mm_context_get_test_session ()) {
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
}
mm_auth_provider_authorize (self->priv->authp, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
authorization, authorization,
@@ -1828,10 +1878,10 @@ mm_base_modem_authorize (MMBaseModem *self,
/* Exclusive operation */ /* Exclusive operation */
typedef struct { typedef struct {
gssize id; gssize id;
MMBaseModemOperationPriority priority; MMOperationPriority priority;
gchar *description; gchar *description;
GTask *wait_task; GTask *wait_task;
} OperationInfo; } OperationInfo;
static void static void
@@ -1844,7 +1894,7 @@ operation_info_free (OperationInfo *info)
/* Exclusive operation lock */ /* Exclusive operation lock */
gssize static gssize
mm_base_modem_operation_lock_finish (MMBaseModem *self, mm_base_modem_operation_lock_finish (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
@@ -1869,7 +1919,7 @@ base_modem_operation_run (MMBaseModem *self)
/* Run the operation in head of the list */ /* Run the operation in head of the list */
mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: lock acquired", mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: lock acquired",
info->id, info->id,
mm_base_modem_operation_priority_get_string (info->priority), mm_operation_priority_get_string (info->priority),
info->description); info->description);
task = g_steal_pointer (&info->wait_task); task = g_steal_pointer (&info->wait_task);
g_task_return_int (task, info->id); g_task_return_int (task, info->id);
@@ -1912,7 +1962,7 @@ abort_pending_operations (MMBaseModem *self)
g_assert (info->wait_task); g_assert (info->wait_task);
mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: aborted early", mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: aborted early",
info->id, info->id,
mm_base_modem_operation_priority_get_string (info->priority), mm_operation_priority_get_string (info->priority),
info->description); info->description);
task = g_steal_pointer (&info->wait_task); task = g_steal_pointer (&info->wait_task);
@@ -1925,12 +1975,12 @@ abort_pending_operations (MMBaseModem *self)
self->priv->scheduled_operations = head; self->priv->scheduled_operations = head;
} }
void static void
mm_base_modem_operation_lock (MMBaseModem *self, mm_base_modem_operation_lock (MMBaseModem *self,
MMBaseModemOperationPriority priority, MMOperationPriority priority,
const gchar *description, const gchar *description,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
OperationInfo *info; OperationInfo *info;
@@ -1957,19 +2007,19 @@ mm_base_modem_operation_lock (MMBaseModem *self,
} else } else
operation_id++; operation_id++;
if (info->priority == MM_BASE_MODEM_OPERATION_PRIORITY_OVERRIDE) { if (info->priority == MM_OPERATION_PRIORITY_OVERRIDE) {
mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: override requested - no new operations will be allowed", mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: override requested - no new operations will be allowed",
info->id, info->id,
mm_base_modem_operation_priority_get_string (info->priority), mm_operation_priority_get_string (info->priority),
info->description); info->description);
g_assert (!self->priv->scheduled_operations_forbidden_forever); g_assert (!self->priv->scheduled_operations_forbidden_forever);
self->priv->scheduled_operations_forbidden_forever = TRUE; self->priv->scheduled_operations_forbidden_forever = TRUE;
abort_pending_operations (self); abort_pending_operations (self);
self->priv->scheduled_operations = g_list_append (self->priv->scheduled_operations, info); self->priv->scheduled_operations = g_list_append (self->priv->scheduled_operations, info);
} else if (info->priority == MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT) { } else if (info->priority == MM_OPERATION_PRIORITY_DEFAULT) {
mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: scheduled", mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: scheduled",
info->id, info->id,
mm_base_modem_operation_priority_get_string (info->priority), mm_operation_priority_get_string (info->priority),
info->description); info->description);
self->priv->scheduled_operations = g_list_append (self->priv->scheduled_operations, info); self->priv->scheduled_operations = g_list_append (self->priv->scheduled_operations, info);
} else } else
@@ -1980,10 +2030,11 @@ mm_base_modem_operation_lock (MMBaseModem *self,
/* Exclusive operation unlock */ /* Exclusive operation unlock */
void static void
mm_base_modem_operation_unlock (MMBaseModem *self, mm_base_modem_operation_unlock (MMIfaceOpLock *_self,
gssize operation_id) gssize operation_id)
{ {
MMBaseModem *self = MM_BASE_MODEM (_self);
OperationInfo *info; OperationInfo *info;
g_assert (self->priv->scheduled_operations); g_assert (self->priv->scheduled_operations);
@@ -1994,7 +2045,7 @@ mm_base_modem_operation_unlock (MMBaseModem *self,
mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: lock released", mm_obj_dbg (self, "[operation %" G_GSSIZE_FORMAT "] %s - %s: lock released",
info->id, info->id,
mm_base_modem_operation_priority_get_string (info->priority), mm_operation_priority_get_string (info->priority),
info->description); info->description);
/* Remove head list item and free its contents */ /* Remove head list item and free its contents */
@@ -2009,9 +2060,9 @@ mm_base_modem_operation_unlock (MMBaseModem *self,
/*****************************************************************************/ /*****************************************************************************/
typedef struct { typedef struct {
GDBusMethodInvocation *invocation; GDBusMethodInvocation *invocation;
MMBaseModemOperationPriority operation_priority; MMOperationPriority operation_priority;
gchar *operation_description; gchar *operation_description;
} AuthorizeAndOperationLockContext; } AuthorizeAndOperationLockContext;
static void static void
@@ -2022,8 +2073,8 @@ authorize_and_operation_lock_context_free (AuthorizeAndOperationLockContext *ctx
g_slice_free (AuthorizeAndOperationLockContext, ctx); g_slice_free (AuthorizeAndOperationLockContext, ctx);
} }
gssize static gssize
mm_base_modem_authorize_and_operation_lock_finish (MMBaseModem *self, mm_base_modem_authorize_and_operation_lock_finish (MMIfaceOpLock *self,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
@@ -2047,35 +2098,35 @@ lock_after_authorize_ready (MMBaseModem *self,
} }
static void static void
authorize_before_lock_ready (MMBaseModem *self, authorize_before_lock_ready (MMIfaceAuth *auth,
GAsyncResult *res, GAsyncResult *res,
GTask *task) GTask *task)
{ {
GError *error = NULL; GError *error = NULL;
AuthorizeAndOperationLockContext *ctx; AuthorizeAndOperationLockContext *ctx;
if (!mm_base_modem_authorize_finish (self, res, &error)) { if (!mm_iface_auth_authorize_finish (auth, res, &error)) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
return; return;
} }
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
mm_base_modem_operation_lock (self, mm_base_modem_operation_lock (MM_BASE_MODEM (auth),
ctx->operation_priority, ctx->operation_priority,
ctx->operation_description, ctx->operation_description,
(GAsyncReadyCallback) lock_after_authorize_ready, (GAsyncReadyCallback) lock_after_authorize_ready,
task); task);
} }
void static void
mm_base_modem_authorize_and_operation_lock (MMBaseModem *self, mm_base_modem_authorize_and_operation_lock (MMIfaceOpLock *self,
GDBusMethodInvocation *invocation, GDBusMethodInvocation *invocation,
const gchar *authorization, const gchar *authorization,
MMBaseModemOperationPriority operation_priority, MMOperationPriority operation_priority,
const gchar *operation_description, const gchar *operation_description,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
AuthorizeAndOperationLockContext *ctx; AuthorizeAndOperationLockContext *ctx;
@@ -2088,7 +2139,7 @@ mm_base_modem_authorize_and_operation_lock (MMBaseModem *self,
ctx->operation_description = g_strdup (operation_description); ctx->operation_description = g_strdup (operation_description);
g_task_set_task_data (task, ctx, (GDestroyNotify)authorize_and_operation_lock_context_free); g_task_set_task_data (task, ctx, (GDestroyNotify)authorize_and_operation_lock_context_free);
mm_base_modem_authorize (self, mm_iface_auth_authorize (MM_IFACE_AUTH (self),
invocation, invocation,
authorization, authorization,
(GAsyncReadyCallback)authorize_before_lock_ready, (GAsyncReadyCallback)authorize_before_lock_ready,
@@ -2630,6 +2681,21 @@ log_object_iface_init (MMLogObjectInterface *iface)
iface->build_id = log_object_build_id; iface->build_id = log_object_build_id;
} }
static void
auth_iface_init (MMIfaceAuthInterface *iface)
{
iface->authorize = mm_base_modem_authorize;
iface->authorize_finish = mm_base_modem_authorize_finish;
}
static void
op_lock_iface_init (MMIfaceOpLockInterface *iface)
{
iface->authorize_and_lock = mm_base_modem_authorize_and_operation_lock;
iface->authorize_and_lock_finish = mm_base_modem_authorize_and_operation_lock_finish;
iface->unlock = mm_base_modem_operation_unlock;
}
static void static void
mm_base_modem_class_init (MMBaseModemClass *klass) mm_base_modem_class_init (MMBaseModemClass *klass)
{ {
@@ -2728,7 +2794,7 @@ mm_base_modem_class_init (MMBaseModemClass *klass)
g_object_class_install_property (object_class, PROP_SUBSYSTEM_DEVICE_ID, properties[PROP_SUBSYSTEM_DEVICE_ID]); g_object_class_install_property (object_class, PROP_SUBSYSTEM_DEVICE_ID, properties[PROP_SUBSYSTEM_DEVICE_ID]);
properties[PROP_CONNECTION] = properties[PROP_CONNECTION] =
g_param_spec_object (MM_BASE_MODEM_CONNECTION, g_param_spec_object (MM_BINDABLE_CONNECTION,
"Connection", "Connection",
"GDBus connection to the system bus.", "GDBus connection to the system bus.",
G_TYPE_DBUS_CONNECTION, G_TYPE_DBUS_CONNECTION,
+40 -90
View File
@@ -36,6 +36,7 @@
#include "mm-port-serial-qcdm.h" #include "mm-port-serial-qcdm.h"
#include "mm-port-serial-gps.h" #include "mm-port-serial-gps.h"
#include "mm-iface-port-at.h" #include "mm-iface-port-at.h"
#include "mm-iface-op-lock.h"
#if defined WITH_QMI #if defined WITH_QMI
#include "mm-port-qmi.h" #include "mm-port-qmi.h"
@@ -56,7 +57,6 @@ typedef struct _MMBaseModem MMBaseModem;
typedef struct _MMBaseModemClass MMBaseModemClass; typedef struct _MMBaseModemClass MMBaseModemClass;
typedef struct _MMBaseModemPrivate MMBaseModemPrivate; typedef struct _MMBaseModemPrivate MMBaseModemPrivate;
#define MM_BASE_MODEM_CONNECTION "base-modem-connection"
#define MM_BASE_MODEM_MAX_TIMEOUTS "base-modem-max-timeouts" #define MM_BASE_MODEM_MAX_TIMEOUTS "base-modem-max-timeouts"
#define MM_BASE_MODEM_VALID "base-modem-valid" #define MM_BASE_MODEM_VALID "base-modem-valid"
#define MM_BASE_MODEM_DEVICE "base-modem-device" #define MM_BASE_MODEM_DEVICE "base-modem-device"
@@ -146,6 +146,7 @@ guint mm_base_modem_get_dbus_id (MMBaseModem *self);
gboolean mm_base_modem_grab_port (MMBaseModem *self, gboolean mm_base_modem_grab_port (MMBaseModem *self,
MMKernelDevice *kernel_device, MMKernelDevice *kernel_device,
MMPortGroup pgroup,
MMPortType ptype, MMPortType ptype,
MMPortSerialAtFlag at_pflags, MMPortSerialAtFlag at_pflags,
GError **error); GError **error);
@@ -192,6 +193,8 @@ GList *mm_base_modem_get_data_ports (MMBaseModem *self);
MMModemPortInfo *mm_base_modem_get_port_infos (MMBaseModem *self, MMModemPortInfo *mm_base_modem_get_port_infos (MMBaseModem *self,
guint *n_port_infos); guint *n_port_infos);
MMModemPortInfo *mm_base_modem_get_ignored_port_infos (MMBaseModem *self,
guint *n_port_infos);
GList *mm_base_modem_find_ports (MMBaseModem *self, GList *mm_base_modem_find_ports (MMBaseModem *self,
MMPortSubsys subsys, MMPortSubsys subsys,
@@ -225,102 +228,49 @@ guint mm_base_modem_get_subsystem_device_id (MMBaseModem *self);
GCancellable *mm_base_modem_peek_cancellable (MMBaseModem *self); GCancellable *mm_base_modem_peek_cancellable (MMBaseModem *self);
/******************************************************************************/
/* Polkit */
void mm_base_modem_authorize (MMBaseModem *self,
GDBusMethodInvocation *invocation,
const gchar *authorization,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean mm_base_modem_authorize_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
/******************************************************************************/
/* Operation lock support */
typedef enum { /*< underscore_name=mm_base_modem_operation_priority >*/
MM_BASE_MODEM_OPERATION_PRIORITY_UNKNOWN,
/* Default operations are scheduled at the end of the list of pending
* operations */
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT,
/* An override operation will make all pending operations be cancelled, and
* it will also disallow adding new operations. This type of operation would
* be the last one expected in a modem object. */
MM_BASE_MODEM_OPERATION_PRIORITY_OVERRIDE,
} MMBaseModemOperationPriority;
void mm_base_modem_operation_lock (MMBaseModem *self,
MMBaseModemOperationPriority priority,
const gchar *description,
GAsyncReadyCallback callback,
gpointer user_data);
gssize mm_base_modem_operation_lock_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
void mm_base_modem_operation_unlock (MMBaseModem *self,
gssize operation_id);
void mm_base_modem_authorize_and_operation_lock (MMBaseModem *self,
GDBusMethodInvocation *invocation,
const gchar *authorization,
MMBaseModemOperationPriority operation_priority,
const gchar *operation_description,
GAsyncReadyCallback callback,
gpointer user_data);
gssize mm_base_modem_authorize_and_operation_lock_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
/******************************************************************************/ /******************************************************************************/
/* State operations */ /* State operations */
typedef enum { void mm_base_modem_initialize (MMBaseModem *self,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MMOperationLock operation_lock,
MM_BASE_MODEM_OPERATION_LOCK_ALREADY_ACQUIRED, GAsyncReadyCallback callback,
} MMBaseModemOperationLock; gpointer user_data);
gboolean mm_base_modem_initialize_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
void mm_base_modem_initialize (MMBaseModem *self, void mm_base_modem_enable (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean mm_base_modem_initialize_finish (MMBaseModem *self, gboolean mm_base_modem_enable_finish (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
void mm_base_modem_enable (MMBaseModem *self, void mm_base_modem_disable (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, MMOperationPriority priority,
gpointer user_data); GAsyncReadyCallback callback,
gboolean mm_base_modem_enable_finish (MMBaseModem *self, gpointer user_data);
GAsyncResult *res, gboolean mm_base_modem_disable_finish (MMBaseModem *self,
GError **error); GAsyncResult *res,
GError **error);
void mm_base_modem_disable (MMBaseModem *self,
MMBaseModemOperationLock operation_lock,
MMBaseModemOperationPriority priority,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean mm_base_modem_disable_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
#if defined WITH_SUSPEND_RESUME #if defined WITH_SUSPEND_RESUME
void mm_base_modem_sync (MMBaseModem *self, void mm_base_modem_sync (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean mm_base_modem_sync_finish (MMBaseModem *self, gboolean mm_base_modem_sync_finish (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
void mm_base_modem_terse (MMBaseModem *self, void mm_base_modem_terse (MMBaseModem *self,
MMBaseModemOperationLock operation_lock, MMOperationLock operation_lock,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
gboolean mm_base_modem_terse_finish (MMBaseModem *self, gboolean mm_base_modem_terse_finish (MMBaseModem *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
#endif #endif
void mm_base_modem_teardown_ports (MMBaseModem *self, void mm_base_modem_teardown_ports (MMBaseModem *self,
+139 -46
View File
@@ -34,18 +34,22 @@
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-error-helpers.h" #include "mm-error-helpers.h"
#include "mm-bind.h"
static void async_initable_iface_init (GAsyncInitableIface *iface); static void async_initable_iface_init (GAsyncInitableIface *iface);
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
static void bind_iface_init (MMBindInterface *iface);
G_DEFINE_TYPE_EXTENDED (MMBaseSim, mm_base_sim, MM_GDBUS_TYPE_SIM_SKELETON, 0, G_DEFINE_TYPE_EXTENDED (MMBaseSim, mm_base_sim, MM_GDBUS_TYPE_SIM_SKELETON, 0,
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_BIND, bind_iface_init))
enum { enum {
PROP_0, PROP_0,
PROP_PATH, PROP_PATH,
PROP_CONNECTION, PROP_CONNECTION,
PROP_BIND_TO,
PROP_MODEM, PROP_MODEM,
PROP_SLOT_NUMBER, PROP_SLOT_NUMBER,
PROP_LAST PROP_LAST
@@ -63,6 +67,13 @@ struct _MMBaseSimPrivate {
GDBusConnection *connection; GDBusConnection *connection;
guint dbus_id; guint dbus_id;
/* The authorization provider */
MMAuthProvider *authp;
GCancellable *authp_cancellable;
/* The object this SIM is bound to */
GObject *bind_to;
/* The modem which owns this SIM */ /* The modem which owns this SIM */
MMBaseModem *modem; MMBaseModem *modem;
/* The path where the SIM object is exported */ /* The path where the SIM object is exported */
@@ -238,18 +249,25 @@ handle_change_pin_ready (MMBaseSim *self,
} }
static void static void
handle_change_pin_auth_ready (MMBaseModem *modem, handle_change_pin_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleChangePinContext *ctx) HandleChangePinContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_change_pin_context_free (ctx); handle_change_pin_context_free (ctx);
return; return;
} }
if (!mm_utils_is_numeric (ctx->old_pin) || !mm_utils_is_numeric (ctx->new_pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_change_pin_context_free (ctx);
return;
}
/* If changing PIN is not implemented, report an error */ /* If changing PIN is not implemented, report an error */
if (!MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin || if (!MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin ||
!MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin_finish) { !MM_BASE_SIM_GET_CLASS (ctx->self)->change_pin_finish) {
@@ -296,11 +314,12 @@ handle_change_pin (MMBaseSim *self,
ctx->old_pin = g_strdup (old_pin); ctx->old_pin = g_strdup (old_pin);
ctx->new_pin = g_strdup (new_pin); ctx->new_pin = g_strdup (new_pin);
mm_base_modem_authorize (self->priv->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_change_pin_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_change_pin_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -421,18 +440,25 @@ handle_enable_pin_ready (MMBaseSim *self,
} }
static void static void
handle_enable_pin_auth_ready (MMBaseModem *modem, handle_enable_pin_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleEnablePinContext *ctx) HandleEnablePinContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_enable_pin_context_free (ctx); handle_enable_pin_context_free (ctx);
return; return;
} }
if (!mm_utils_is_numeric (ctx->pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_enable_pin_context_free (ctx);
return;
}
/* If changing PIN is not implemented, report an error */ /* If changing PIN is not implemented, report an error */
if (!MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin || if (!MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin ||
!MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin_finish) { !MM_BASE_SIM_GET_CLASS (ctx->self)->enable_pin_finish) {
@@ -478,11 +504,12 @@ handle_enable_pin (MMBaseSim *self,
ctx->pin = g_strdup (pin); ctx->pin = g_strdup (pin);
ctx->enabled = enabled; ctx->enabled = enabled;
mm_base_modem_authorize (self->priv->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_enable_pin_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_enable_pin_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -844,18 +871,25 @@ handle_send_pin_ready (MMBaseSim *self,
} }
static void static void
handle_send_pin_auth_ready (MMBaseModem *modem, handle_send_pin_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleSendPinContext *ctx) HandleSendPinContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_send_pin_context_free (ctx); handle_send_pin_context_free (ctx);
return; return;
} }
if (!mm_utils_is_numeric (ctx->pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN must be numeric");
handle_send_pin_context_free (ctx);
return;
}
if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) { if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot send PIN: SIM not currently active"); "Cannot send PIN: SIM not currently active");
@@ -889,11 +923,12 @@ handle_send_pin (MMBaseSim *self,
ctx->invocation = g_object_ref (invocation); ctx->invocation = g_object_ref (invocation);
ctx->pin = g_strdup (pin); ctx->pin = g_strdup (pin);
mm_base_modem_authorize (self->priv->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_send_pin_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_send_pin_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -948,18 +983,25 @@ handle_send_puk_ready (MMBaseSim *self,
} }
static void static void
handle_send_puk_auth_ready (MMBaseModem *modem, handle_send_puk_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleSendPukContext *ctx) HandleSendPukContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_send_puk_context_free (ctx); handle_send_puk_context_free (ctx);
return; return;
} }
if (!mm_utils_is_numeric (ctx->puk) || !mm_utils_is_numeric (ctx->new_pin)) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"PIN/PUK must be numeric");
handle_send_puk_context_free (ctx);
return;
}
if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) { if (!mm_gdbus_sim_get_active (MM_GDBUS_SIM (ctx->self))) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot send PUK: SIM not currently active"); "Cannot send PUK: SIM not currently active");
@@ -996,11 +1038,12 @@ handle_send_puk (MMBaseSim *self,
ctx->puk = g_strdup (puk); ctx->puk = g_strdup (puk);
ctx->new_pin = g_strdup (new_pin); ctx->new_pin = g_strdup (new_pin);
mm_base_modem_authorize (self->priv->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_send_puk_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_send_puk_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -1503,14 +1546,36 @@ handle_set_preferred_networks_ready (MMBaseSim *self,
handle_set_preferred_networks_context_free (ctx); handle_set_preferred_networks_context_free (ctx);
} }
static gboolean
validate_networks_list (GList *networks_list,
GError **error)
{
GList *l;
for (l = networks_list; l; l = g_list_next (l)) {
MMSimPreferredNetwork *network = (MMSimPreferredNetwork *)l->data;
const gchar *operator_code;
operator_code = mm_sim_preferred_network_get_operator_code (network);
if (!mm_utils_is_numeric (operator_code)) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"Invalid operator code: '%s'", operator_code);
return FALSE;
}
}
return TRUE;
}
static void static void
handle_set_preferred_networks_auth_ready (MMBaseModem *modem, handle_set_preferred_networks_auth_ready (MMAuthProvider *authp,
GAsyncResult *res, GAsyncResult *res,
HandleSetPreferredNetworksContext *ctx) HandleSetPreferredNetworksContext *ctx)
{ {
GError *error = NULL; GError *error = NULL;
GList *networks_list = NULL;
if (!mm_base_modem_authorize_finish (modem, res, &error)) { if (!mm_auth_provider_authorize_finish (authp, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error); mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_set_preferred_networks_context_free (ctx); handle_set_preferred_networks_context_free (ctx);
return; return;
@@ -1538,12 +1603,22 @@ handle_set_preferred_networks_auth_ready (MMBaseModem *modem,
return; return;
} }
networks_list = mm_sim_preferred_network_list_new_from_variant (ctx->networks);
if (!validate_networks_list (networks_list, &error)) {
g_list_free_full (networks_list, g_object_unref);
mm_dbus_method_invocation_take_error (ctx->invocation, error);
handle_set_preferred_networks_context_free (ctx);
return;
}
mm_obj_info (ctx->self, "processing user request to set preferred networks..."); mm_obj_info (ctx->self, "processing user request to set preferred networks...");
MM_BASE_SIM_GET_CLASS (ctx->self)->set_preferred_networks ( MM_BASE_SIM_GET_CLASS (ctx->self)->set_preferred_networks (
ctx->self, ctx->self,
mm_sim_preferred_network_list_new_from_variant (ctx->networks), networks_list,
(GAsyncReadyCallback)handle_set_preferred_networks_ready, (GAsyncReadyCallback)handle_set_preferred_networks_ready,
ctx); ctx);
g_list_free_full (networks_list, g_object_unref);
} }
static gboolean static gboolean
@@ -1558,11 +1633,12 @@ handle_set_preferred_networks (MMBaseSim *self,
ctx->invocation = g_object_ref (invocation); ctx->invocation = g_object_ref (invocation);
ctx->networks = g_variant_ref (networks_variant); ctx->networks = g_variant_ref (networks_variant);
mm_base_modem_authorize (self->priv->modem, mm_auth_provider_authorize (self->priv->authp,
invocation, invocation,
MM_AUTHORIZATION_DEVICE_CONTROL, MM_AUTHORIZATION_DEVICE_CONTROL,
(GAsyncReadyCallback)handle_set_preferred_networks_auth_ready, self->priv->authp_cancellable,
ctx); (GAsyncReadyCallback)handle_set_preferred_networks_auth_ready,
ctx);
return TRUE; return TRUE;
} }
@@ -2286,6 +2362,7 @@ load_gid2 (MMBaseSim *self,
MMBaseSim * MMBaseSim *
mm_base_sim_new_initialized (MMBaseModem *modem, mm_base_sim_new_initialized (MMBaseModem *modem,
GObject *bind_to,
guint slot_number, guint slot_number,
gboolean active, gboolean active,
const gchar *sim_identifier, const gchar *sim_identifier,
@@ -2299,6 +2376,7 @@ mm_base_sim_new_initialized (MMBaseModem *modem,
sim = MM_BASE_SIM (g_object_new (MM_TYPE_BASE_SIM, sim = MM_BASE_SIM (g_object_new (MM_TYPE_BASE_SIM,
MM_BASE_SIM_MODEM, modem, MM_BASE_SIM_MODEM, modem,
MM_BIND_TO, bind_to,
MM_BASE_SIM_SLOT_NUMBER, slot_number, MM_BASE_SIM_SLOT_NUMBER, slot_number,
"active", active, "active", active,
"sim-identifier", sim_identifier, "sim-identifier", sim_identifier,
@@ -2888,6 +2966,7 @@ initable_init_async (GAsyncInitable *initable,
void void
mm_base_sim_new (MMBaseModem *modem, mm_base_sim_new (MMBaseModem *modem,
GObject *bind_to,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
@@ -2898,6 +2977,7 @@ mm_base_sim_new (MMBaseModem *modem,
callback, callback,
user_data, user_data,
MM_BASE_SIM_MODEM, modem, MM_BASE_SIM_MODEM, modem,
MM_BIND_TO, bind_to,
"active", TRUE, /* by default always active */ "active", TRUE, /* by default always active */
NULL); NULL);
} }
@@ -2963,18 +3043,14 @@ set_property (GObject *object,
else if (self->priv->path) else if (self->priv->path)
sim_dbus_export (self); sim_dbus_export (self);
break; break;
case PROP_BIND_TO:
g_clear_object (&self->priv->bind_to);
self->priv->bind_to = g_value_dup_object (value);
mm_bind_to (MM_BIND (self), MM_BASE_SIM_CONNECTION, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
self->priv->modem = g_value_dup_object (value); self->priv->modem = g_value_dup_object (value);
if (self->priv->modem) {
/* Set owner ID */
mm_log_object_set_owner_id (MM_LOG_OBJECT (self), mm_log_object_get_id (MM_LOG_OBJECT (self->priv->modem)));
/* Bind the modem's connection (which is set when it is exported,
* and unset when unexported) to the SIM's connection */
g_object_bind_property (self->priv->modem, MM_BASE_MODEM_CONNECTION,
self, MM_BASE_SIM_CONNECTION,
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
}
break; break;
case PROP_SLOT_NUMBER: case PROP_SLOT_NUMBER:
self->priv->slot_number = g_value_get_uint (value); self->priv->slot_number = g_value_get_uint (value);
@@ -3000,6 +3076,9 @@ get_property (GObject *object,
case PROP_CONNECTION: case PROP_CONNECTION:
g_value_set_object (value, self->priv->connection); g_value_set_object (value, self->priv->connection);
break; break;
case PROP_BIND_TO:
g_value_set_object (value, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_value_set_object (value, self->priv->modem); g_value_set_object (value, self->priv->modem);
break; break;
@@ -3022,6 +3101,10 @@ mm_base_sim_init (MMBaseSim *self)
/* Each SIM is given a unique id to build its own DBus path */ /* Each SIM is given a unique id to build its own DBus path */
self->priv->dbus_id = id++; self->priv->dbus_id = id++;
/* Setup authorization provider */
self->priv->authp = mm_auth_provider_get ();
self->priv->authp_cancellable = g_cancellable_new ();
} }
static void static void
@@ -3047,6 +3130,9 @@ dispose (GObject *object)
} }
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
g_clear_object (&self->priv->bind_to);
g_cancellable_cancel (self->priv->authp_cancellable);
g_clear_object (&self->priv->authp_cancellable);
G_OBJECT_CLASS (mm_base_sim_parent_class)->dispose (object); G_OBJECT_CLASS (mm_base_sim_parent_class)->dispose (object);
} }
@@ -3064,6 +3150,11 @@ log_object_iface_init (MMLogObjectInterface *iface)
iface->build_id = log_object_build_id; iface->build_id = log_object_build_id;
} }
static void
bind_iface_init (MMBindInterface *iface)
{
}
static void static void
mm_base_sim_class_init (MMBaseSimClass *klass) mm_base_sim_class_init (MMBaseSimClass *klass)
{ {
@@ -3128,6 +3219,8 @@ mm_base_sim_class_init (MMBaseSimClass *klass)
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]); g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]);
g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO);
properties[PROP_SLOT_NUMBER] = properties[PROP_SLOT_NUMBER] =
g_param_spec_uint (MM_BASE_SIM_SLOT_NUMBER, g_param_spec_uint (MM_BASE_SIM_SLOT_NUMBER,
"Slot number", "Slot number",
+2
View File
@@ -213,6 +213,7 @@ GType mm_base_sim_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSim, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSim, g_object_unref)
void mm_base_sim_new (MMBaseModem *modem, void mm_base_sim_new (MMBaseModem *modem,
GObject *bind_to,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
@@ -228,6 +229,7 @@ gboolean mm_base_sim_initialize_finish (MMBaseSim *self,
GError **error); GError **error);
MMBaseSim *mm_base_sim_new_initialized (MMBaseModem *modem, MMBaseSim *mm_base_sim_new_initialized (MMBaseModem *modem,
GObject *bind_to,
guint slot_number, guint slot_number,
gboolean active, gboolean active,
const gchar *sim_identifier, const gchar *sim_identifier,
+237 -899
View File
File diff suppressed because it is too large Load Diff
+30 -19
View File
@@ -25,7 +25,6 @@
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-sms-part.h" #include "mm-sms-part.h"
#include "mm-base-modem.h"
/*****************************************************************************/ /*****************************************************************************/
@@ -46,12 +45,19 @@ typedef struct _MMBaseSms MMBaseSms;
typedef struct _MMBaseSmsClass MMBaseSmsClass; typedef struct _MMBaseSmsClass MMBaseSmsClass;
typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate;
/* Properties */
#define MM_BASE_SMS_PATH "sms-path" #define MM_BASE_SMS_PATH "sms-path"
#define MM_BASE_SMS_CONNECTION "sms-connection" #define MM_BASE_SMS_CONNECTION "sms-connection"
#define MM_BASE_SMS_MODEM "sms-modem"
#define MM_BASE_SMS_IS_MULTIPART "sms-is-multipart" #define MM_BASE_SMS_IS_MULTIPART "sms-is-multipart"
#define MM_BASE_SMS_MAX_PARTS "sms-max-parts" #define MM_BASE_SMS_MAX_PARTS "sms-max-parts"
#define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference" #define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference"
#define MM_BASE_SMS_IS_3GPP "sms-is-3gpp"
#define MM_BASE_SMS_DEFAULT_STORAGE "sms-default-storage"
#define MM_BASE_SMS_SUPPORTED_STORAGES "sms-supported-storages"
#define MM_BASE_SMS_CONNECTION_PARENT_PROPERTY_NAME "sms-connection-parent-property-name"
/* Signals */
#define MM_BASE_SMS_SET_LOCAL_MULTIPART_REFERENCE "sms-set-local-multipart-reference"
struct _MMBaseSms { struct _MMBaseSms {
MmGdbusSmsSkeleton parent; MmGdbusSmsSkeleton parent;
@@ -85,28 +91,31 @@ struct _MMBaseSmsClass {
gboolean (* delete_finish) (MMBaseSms *self, gboolean (* delete_finish) (MMBaseSms *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
/* Signal */
void (*set_local_multipart_reference) (MMBaseSms *self,
const gchar *number);
}; };
GType mm_base_sms_get_type (void); GType mm_base_sms_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref)
/* This one can be overridden by plugins */ gboolean mm_base_sms_init_from_properties (MMBaseSms *self,
MMBaseSms *mm_base_sms_new (MMBaseModem *modem); MMSmsProperties *properties,
MMBaseSms *mm_base_sms_new_from_properties (MMBaseModem *modem, GError **error);
MMSmsProperties *properties, gboolean mm_base_sms_singlepart_init (MMBaseSms *self,
GError **error); MMSmsState state,
MMBaseSms *mm_base_sms_singlepart_new (MMBaseModem *modem, MMSmsStorage storage,
MMSmsState state, MMSmsPart *part,
MMSmsStorage storage, GError **error);
MMSmsPart *part, gboolean mm_base_sms_multipart_init (MMBaseSms *self,
GError **error); MMSmsState state,
MMBaseSms *mm_base_sms_multipart_new (MMBaseModem *modem, MMSmsStorage storage,
MMSmsState state, guint reference,
MMSmsStorage storage, guint max_parts,
guint reference, MMSmsPart *first_part,
guint max_parts, GError **error);
MMSmsPart *first_part,
GError **error);
gboolean mm_base_sms_multipart_take_part (MMBaseSms *self, gboolean mm_base_sms_multipart_take_part (MMBaseSms *self,
MMSmsPart *part, MMSmsPart *part,
GError **error); GError **error);
@@ -123,6 +132,8 @@ GList *mm_base_sms_get_parts (MMBaseSms *self);
gboolean mm_base_sms_is_multipart (MMBaseSms *self); gboolean mm_base_sms_is_multipart (MMBaseSms *self);
guint mm_base_sms_get_max_parts (MMBaseSms *self); guint mm_base_sms_get_max_parts (MMBaseSms *self);
guint mm_base_sms_get_multipart_reference (MMBaseSms *self); guint mm_base_sms_get_multipart_reference (MMBaseSms *self);
void mm_base_sms_set_multipart_reference (MMBaseSms *self,
guint reference);
gboolean mm_base_sms_multipart_is_complete (MMBaseSms *self); gboolean mm_base_sms_multipart_is_complete (MMBaseSms *self);
gboolean mm_base_sms_multipart_is_assembled (MMBaseSms *self); gboolean mm_base_sms_multipart_is_assembled (MMBaseSms *self);
+14 -4
View File
@@ -33,6 +33,7 @@
#include "mm-bearer-mbim.h" #include "mm-bearer-mbim.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-context.h" #include "mm-context.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMBearerMbim, mm_bearer_mbim, MM_TYPE_BASE_BEARER) G_DEFINE_TYPE (MMBearerMbim, mm_bearer_mbim, MM_TYPE_BASE_BEARER)
@@ -640,9 +641,10 @@ ip_configuration_async_cleanup (GTask *task)
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
g_assert (ctx->async_slaac_cancellation_id); if (ctx->async_slaac_cancellation_id) {
g_cancellable_disconnect (g_task_get_cancellable (task), ctx->async_slaac_cancellation_id); g_cancellable_disconnect (g_task_get_cancellable (task), ctx->async_slaac_cancellation_id);
ctx->async_slaac_cancellation_id = 0; ctx->async_slaac_cancellation_id = 0;
}
g_assert (ctx->async_slaac_notification_id); g_assert (ctx->async_slaac_notification_id);
if (g_signal_handler_is_connected (ctx->mbim, ctx->async_slaac_notification_id)) if (g_signal_handler_is_connected (ctx->mbim, ctx->async_slaac_notification_id))
@@ -666,8 +668,15 @@ ip_configuration_async_timeout (GTask *task)
} }
static void static void
ip_configuration_async_cancelled (GTask *task) ip_configuration_async_cancelled (GCancellable *cancellable,
GTask *task)
{ {
ConnectContext *ctx;
/* Avoid the explicit g_cancellable_disconnect(), which would deadlock */
ctx = g_task_get_task_data (task);
ctx->async_slaac_cancellation_id = 0;
ip_configuration_async_cleanup (task); ip_configuration_async_cleanup (task);
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED,
"Cancelled waiting for SLAAC notification"); "Cancelled waiting for SLAAC notification");
@@ -2020,6 +2029,7 @@ mm_bearer_mbim_new (MMBroadbandModemMbim *modem,
* g_object_new() here */ * g_object_new() here */
bearer = g_object_new (MM_TYPE_BEARER_MBIM, bearer = g_object_new (MM_TYPE_BEARER_MBIM,
MM_BASE_BEARER_MODEM, modem, MM_BASE_BEARER_MODEM, modem,
MM_BIND_TO, G_OBJECT (modem),
MM_BASE_BEARER_CONFIG, config, MM_BASE_BEARER_CONFIG, config,
NULL); NULL);
+2
View File
@@ -37,6 +37,7 @@
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-context.h" #include "mm-context.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMBearerQmi, mm_bearer_qmi, MM_TYPE_BASE_BEARER) G_DEFINE_TYPE (MMBearerQmi, mm_bearer_qmi, MM_TYPE_BASE_BEARER)
@@ -2960,6 +2961,7 @@ mm_bearer_qmi_new (MMBroadbandModemQmi *modem,
* g_object_new() here */ * g_object_new() here */
bearer = g_object_new (MM_TYPE_BEARER_QMI, bearer = g_object_new (MM_TYPE_BEARER_QMI,
MM_BASE_BEARER_MODEM, modem, MM_BASE_BEARER_MODEM, modem,
MM_BIND_TO, G_OBJECT (modem),
MM_BASE_BEARER_CONFIG, config, MM_BASE_BEARER_CONFIG, config,
NULL); NULL);
+62
View File
@@ -0,0 +1,62 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2025 Dan Williams <dan@ioncontrol.co>
*/
#include "mm-bind.h"
#include "mm-log-object.h"
G_DEFINE_INTERFACE (MMBind, mm_bind, MM_TYPE_LOG_OBJECT)
gboolean
mm_bind_to (MMBind *self, const gchar *local_propname, GObject *other_object)
{
if (other_object) {
/* Set log owner ID */
mm_log_object_set_owner_id (MM_LOG_OBJECT (self),
mm_log_object_get_id (MM_LOG_OBJECT (other_object)));
if (local_propname) {
/* Bind the other object's connection property (which is set when it is
* exported, and unset when unexported) to this object's connection
* property.
*/
g_object_bind_property (other_object,
MM_BINDABLE_CONNECTION,
self,
local_propname,
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
}
}
return !!other_object;
}
static void
mm_bind_default_init (MMBindInterface *iface)
{
static gsize initialized = 0;
if (!g_once_init_enter (&initialized))
return;
/* Properties */
g_object_interface_install_property (
iface,
g_param_spec_object (MM_BIND_TO,
"Bind to",
"Bind to this object",
G_TYPE_OBJECT,
G_PARAM_READWRITE));
g_once_init_leave (&initialized, 1);
}
+42
View File
@@ -0,0 +1,42 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2025 Dan Williams <dan@ioncontrol.co>
*/
#ifndef MM_CHILD_H
#define MM_CHILD_H
#include <glib.h>
#include <glib-object.h>
/* Properties */
#define MM_BIND_TO "bind-to"
/* Property name used by an object that wants to allow others
* to bind its connection property.
*/
#define MM_BINDABLE_CONNECTION "bind-connection"
#define MM_TYPE_BIND mm_bind_get_type ()
G_DECLARE_INTERFACE (MMBind, mm_bind, MM, BIND, MMBind)
struct _MMBindInterface
{
GTypeInterface g_iface;
};
gboolean mm_bind_to (MMBind *self,
const gchar *local_propname,
GObject *other_object);
#endif /* MM_LOG_OBJECT_H */
+9 -1
View File
@@ -37,6 +37,7 @@
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-port-enums-types.h" #include "mm-port-enums-types.h"
#include "mm-helper-enums-types.h" #include "mm-helper-enums-types.h"
#include "mm-bind.h"
static void async_initable_iface_init (GAsyncInitableIface *iface); static void async_initable_iface_init (GAsyncInitableIface *iface);
@@ -634,7 +635,13 @@ select_profile_3gpp_get_profile_ready (MMIfaceModem3gppProfileManager *modem,
profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (modem, res, &error); profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (modem, res, &error);
if (!profile) if (!profile)
g_task_return_error (task, error); g_task_return_error (task, error);
else else if (!mm_3gpp_profile_get_enabled (profile)) {
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Profile '%d' is internally disabled",
ctx->profile_id);
} else
g_task_return_int (task, ctx->profile_id); g_task_return_int (task, ctx->profile_id);
g_object_unref (task); g_object_unref (task);
} }
@@ -1960,6 +1967,7 @@ mm_broadband_bearer_new (MMBroadbandModem *modem,
callback, callback,
user_data, user_data,
MM_BASE_BEARER_MODEM, modem, MM_BASE_BEARER_MODEM, modem,
MM_BIND_TO, G_OBJECT (modem),
MM_BASE_BEARER_CONFIG, bearer_properties, MM_BASE_BEARER_CONFIG, bearer_properties,
MM_BROADBAND_BEARER_FLOW_CONTROL, flow_control, MM_BROADBAND_BEARER_FLOW_CONTROL, flow_control,
NULL); NULL);
+76 -42
View File
@@ -153,6 +153,7 @@ struct _MMBroadbandModemMbimPrivate {
gboolean is_ms_sar_supported; gboolean is_ms_sar_supported;
gboolean is_google_carrier_lock_supported; gboolean is_google_carrier_lock_supported;
gboolean is_ms_device_reset_supported; gboolean is_ms_device_reset_supported;
gboolean is_qdu_supported;
/* Process unsolicited notifications */ /* Process unsolicited notifications */
gulong notification_id; gulong notification_id;
@@ -190,7 +191,6 @@ struct _MMBroadbandModemMbimPrivate {
/* Multi-SIM support */ /* Multi-SIM support */
guint32 executor_index; guint32 executor_index;
guint active_slot_index; guint active_slot_index;
gboolean pending_sim_slot_switch_action;
MMUnlockRetries *unlock_retries; MMUnlockRetries *unlock_retries;
}; };
@@ -344,7 +344,7 @@ peek_port_mbim_for_data (MMBroadbandModemMbim *self,
g_assert (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET); g_assert (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
net_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (data)); net_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (data));
if (g_strcmp0 (net_port_driver, "cdc_mbim") != 0 && g_strcmp0 (net_port_driver, "mhi_net")) { if (g_strcmp0 (net_port_driver, "cdc_mbim") && g_strcmp0 (net_port_driver, "mhi-pci-generic")) {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
@@ -354,7 +354,7 @@ peek_port_mbim_for_data (MMBroadbandModemMbim *self,
return NULL; return NULL;
} }
if (!g_strcmp0 (net_port_driver, "mhi_net")) if (!g_strcmp0 (net_port_driver, "mhi-pci-generic"))
return mm_broadband_modem_mbim_peek_port_mbim (self); return mm_broadband_modem_mbim_peek_port_mbim (self);
net_port_parent_path = mm_kernel_device_get_interface_sysfs_path (mm_port_peek_kernel_device (data)); net_port_parent_path = mm_kernel_device_get_interface_sysfs_path (mm_port_peek_kernel_device (data));
@@ -519,7 +519,7 @@ device_caps_query_ready (MbimDevice *device,
GError *error = NULL; GError *error = NULL;
LoadCurrentCapabilitiesContext *ctx; LoadCurrentCapabilitiesContext *ctx;
MbimDataClass caps_data_class = MBIM_DATA_CLASS_NONE; MbimDataClass caps_data_class = MBIM_DATA_CLASS_NONE;
g_autofree gchar *caps_custom_data_class_str; g_autofree gchar *caps_custom_data_class_str = NULL;
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
@@ -3537,6 +3537,12 @@ query_device_services_ready (MbimDevice *device,
continue; continue;
} }
if (service == MBIM_SERVICE_QDU) {
mm_obj_dbg (self, "Qualcomm Device Upgrade method mbim-qdu supported");
self->priv->is_qdu_supported = TRUE;
continue;
}
/* no optional features to check in remaining services */ /* no optional features to check in remaining services */
} }
mbim_device_service_element_array_free (device_services); mbim_device_service_element_array_free (device_services);
@@ -5504,7 +5510,7 @@ basic_connect_notification_subscriber_ready_status (MMBroadbandModemMbim *self,
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
gboolean active_sim_event = FALSE; gboolean active_sim_event = FALSE;
if (self->priv->pending_sim_slot_switch_action) { if (mm_iface_modem_is_primary_sim_slot_switch_ongoing (MM_IFACE_MODEM (self))) {
mm_obj_dbg (self, "ignoring slot status change"); mm_obj_dbg (self, "ignoring slot status change");
return; return;
} }
@@ -6209,7 +6215,7 @@ ms_basic_connect_extensions_notification_slot_info_status (MMBroadbandModemMbim
return; return;
} }
if (self->priv->pending_sim_slot_switch_action) { if (mm_iface_modem_is_primary_sim_slot_switch_ongoing (MM_IFACE_MODEM (self))) {
mm_obj_dbg (self, "ignoring slot status change in SIM slot %d: %s", slot_index + 1, mbim_uicc_slot_state_get_string (slot_state)); mm_obj_dbg (self, "ignoring slot status change in SIM slot %d: %s", slot_index + 1, mbim_uicc_slot_state_get_string (slot_state));
return; return;
} }
@@ -9039,24 +9045,33 @@ add_sms_part (MMBroadbandModemMbim *self,
self, self,
FALSE, FALSE,
&error); &error);
if (part) { if (!part) {
mm_obj_dbg (self, "correctly parsed PDU (%d)", pdu->message_index);
if (expected_index != SMS_PART_INVALID_INDEX && (expected_index != mm_sms_part_get_index (part))) {
/* Some Fibocom L850 modems report an invalid part index (always 1) in the response
* message. Because we know which message part was requested, we can use that value
* instead to workaround this bug. */
mm_obj_dbg (self, "Expected SMS part index '%u' but device reports index '%u': using the expected one",
expected_index, mm_sms_part_get_index (part));
mm_sms_part_set_index (part, expected_index);
}
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
part,
mm_sms_state_from_mbim_message_status (pdu->message_status),
MM_SMS_STORAGE_MT);
} else {
/* Don't treat the error as critical */ /* Don't treat the error as critical */
mm_obj_dbg (self, "error parsing PDU (%d): %s", mm_obj_dbg (self, "error parsing PDU (%d): %s",
pdu->message_index, error->message); pdu->message_index, error->message);
return;
}
mm_obj_dbg (self, "correctly parsed PDU (%d)", pdu->message_index);
if (expected_index != SMS_PART_INVALID_INDEX && (expected_index != mm_sms_part_get_index (part))) {
/* Some Fibocom L850 modems report an invalid part index (always 1) in the response
* message. Because we know which message part was requested, we can use that value
* instead to workaround this bug. */
mm_obj_dbg (self, "Expected SMS part index '%u' but device reports index '%u': using the expected one",
expected_index, mm_sms_part_get_index (part));
mm_sms_part_set_index (part, expected_index);
}
if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)),
part,
mm_sms_state_from_mbim_message_status (pdu->message_status),
MM_SMS_STORAGE_MT,
&error)) {
/* Don't treat the error as critical */
mm_obj_dbg (self, "error adding SMS (%d): %s",
pdu->message_index, error->message);
return;
} }
} }
@@ -9252,9 +9267,14 @@ enable_unsolicited_events_messaging (MMIfaceModemMessaging *_self,
/* Create SMS (Messaging interface) */ /* Create SMS (Messaging interface) */
static MMBaseSms * static MMBaseSms *
messaging_create_sms (MMIfaceModemMessaging *self) messaging_create_sms (MMBroadbandModem *self)
{ {
return mm_sms_mbim_new (MM_BASE_MODEM (self)); MMSmsStorage default_storage;
default_storage = mm_iface_modem_messaging_get_default_storage (MM_IFACE_MODEM_MESSAGING (self));
return mm_sms_mbim_new (MM_BASE_MODEM (self),
mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)),
default_storage);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -9988,8 +10008,6 @@ set_device_slot_mappings_ready (MbimDevice *device,
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
g_assert (self->priv->pending_sim_slot_switch_action);
/* the slot index in MM starts at 1 */ /* the slot index in MM starts at 1 */
slot_number = GPOINTER_TO_UINT (g_task_get_task_data (task)) - 1; slot_number = GPOINTER_TO_UINT (g_task_get_task_data (task)) - 1;
@@ -10000,7 +10018,6 @@ set_device_slot_mappings_ready (MbimDevice *device,
&map_count, &map_count,
&slot_mappings, &slot_mappings,
&error)) { &error)) {
self->priv->pending_sim_slot_switch_action = FALSE;
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
return; return;
@@ -10009,13 +10026,9 @@ set_device_slot_mappings_ready (MbimDevice *device,
for (i = 0; i < map_count; i++) { for (i = 0; i < map_count; i++) {
if (i == self->priv->executor_index) { if (i == self->priv->executor_index) {
if (slot_number != slot_mappings[i]->slot) { if (slot_number != slot_mappings[i]->slot) {
self->priv->pending_sim_slot_switch_action = FALSE;
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND,
"SIM slot switch to '%u' failed", slot_number); "SIM slot switch to '%u' failed", slot_number);
} else { } else {
/* Keep pending_sim_slot_switch_action flag TRUE to cleanly ignore SIM related indications
* during slot switching, We don't want SIM related indications received trigger the update
* of SimSlots property, which may not be what we want as the modem object is being shutdown */
self->priv->active_slot_index = slot_number + 1; self->priv->active_slot_index = slot_number + 1;
g_task_return_boolean (task, TRUE); g_task_return_boolean (task, TRUE);
} }
@@ -10025,7 +10038,6 @@ set_device_slot_mappings_ready (MbimDevice *device,
} }
} }
self->priv->pending_sim_slot_switch_action = FALSE;
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND,
"Can't find executor index '%u'", self->priv->executor_index); "Can't find executor index '%u'", self->priv->executor_index);
g_object_unref (task); g_object_unref (task);
@@ -10077,16 +10089,6 @@ before_set_query_device_slot_mappings_ready (MbimDevice *device,
} }
} }
/* Flag a pending SIM slot switch operation, so that we can ignore slot state updates
* during the process. */
if (self->priv->pending_sim_slot_switch_action) {
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS,
"there is already an ongoing SIM slot switch operation");
g_object_unref (task);
return;
}
self->priv->pending_sim_slot_switch_action = TRUE;
for (i = 0; i < map_count; i++) { for (i = 0; i < map_count; i++) {
if (i == self->priv->executor_index) if (i == self->priv->executor_index)
slot_mappings[i]->slot = slot_number; slot_mappings[i]->slot = slot_number;
@@ -10366,11 +10368,43 @@ modem_firmware_load_update_settings_finish (MMIfaceModemFirmware *self,
return mm_iface_modem_firmware_load_update_settings_in_port_finish (self, res, error); return mm_iface_modem_firmware_load_update_settings_in_port_finish (self, res, error);
} }
static gboolean
modem_is_qdu_supported (MMBaseModem *modem,
MMKernelDevice *kernel_device)
{
return mm_kernel_device_get_global_property_as_boolean (kernel_device, "ID_MM_MBIM_QDU");
}
static void static void
modem_firmware_load_update_settings (MMIfaceModemFirmware *self, modem_firmware_load_update_settings (MMIfaceModemFirmware *self,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task;
MMPortMbim *mbim_port;
MMKernelDevice *kernel_device;
MMModemFirmwareUpdateMethod update_methods;
g_autoptr(MMFirmwareUpdateSettings) update_settings = NULL;
/* Check first if 'mbim-qdu' is supported and selected via udev. If the
* update method 'mbim-qdu' is not supported and not selected via udev,
* then the generic update method 'firehose/sahara' are checked.
*/
update_methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE;
mbim_port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self));
if (mbim_port) {
kernel_device = mm_port_peek_kernel_device (MM_PORT (mbim_port));
if ((MM_BROADBAND_MODEM_MBIM (self)->priv->is_qdu_supported) &&
modem_is_qdu_supported (MM_BASE_MODEM (self), kernel_device)) {
task = g_task_new (self, NULL, callback, user_data);
update_settings = mm_firmware_update_settings_new (update_methods);
mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU);
g_task_return_pointer (task, g_object_ref (update_settings), (GDestroyNotify) g_object_unref);
g_object_unref (task);
return;
}
}
mm_iface_modem_firmware_load_update_settings_in_port ( mm_iface_modem_firmware_load_update_settings_in_port (
self, self,
MM_PORT (mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self))), MM_PORT (mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self))),
@@ -10737,7 +10771,6 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface)
iface->enable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish; iface->enable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish;
iface->disable_unsolicited_events = disable_unsolicited_events_messaging; iface->disable_unsolicited_events = disable_unsolicited_events_messaging;
iface->disable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish; iface->disable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish;
iface->create_sms = messaging_create_sms;
} }
static void static void
@@ -10807,6 +10840,7 @@ mm_broadband_modem_mbim_class_init (MMBroadbandModemMbimClass *klass)
/* Do not initialize the MBIM modem through AT commands */ /* Do not initialize the MBIM modem through AT commands */
broadband_modem_class->enabling_modem_init = NULL; broadband_modem_class->enabling_modem_init = NULL;
broadband_modem_class->enabling_modem_init_finish = NULL; broadband_modem_class->enabling_modem_init_finish = NULL;
broadband_modem_class->create_sms = messaging_create_sms;
#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
g_object_class_install_property (object_class, PROP_QMI_UNSUPPORTED, g_object_class_install_property (object_class, PROP_QMI_UNSUPPORTED,
File diff suppressed because it is too large Load Diff
+233 -215
View File
@@ -28,6 +28,7 @@
#include <ModemManager.h> #include <ModemManager.h>
#define _LIBMM_INSIDE_MM #define _LIBMM_INSIDE_MM
#include <libmm-glib.h> #include <libmm-glib.h>
#include <ModemManager-tags.h>
#include "mm-base-modem-at.h" #include "mm-base-modem-at.h"
#include "mm-broadband-modem.h" #include "mm-broadband-modem.h"
@@ -50,8 +51,10 @@
#include "mm-bearer-list.h" #include "mm-bearer-list.h"
#include "mm-cbm-list.h" #include "mm-cbm-list.h"
#include "mm-cbm-part.h" #include "mm-cbm-part.h"
#include "mm-call-at.h"
#include "mm-sms-list.h" #include "mm-sms-list.h"
#include "mm-sms-part-3gpp.h" #include "mm-sms-part-3gpp.h"
#include "mm-sms-at.h"
#include "mm-call-list.h" #include "mm-call-list.h"
#include "mm-base-sim.h" #include "mm-base-sim.h"
#include "mm-log-object.h" #include "mm-log-object.h"
@@ -63,6 +66,7 @@
#include "libqcdm/src/logs.h" #include "libqcdm/src/logs.h"
#include "libqcdm/src/log-items.h" #include "libqcdm/src/log-items.h"
#include "mm-helper-enums-types.h" #include "mm-helper-enums-types.h"
#include "mm-bind.h"
static void iface_modem_init (MMIfaceModemInterface *iface); static void iface_modem_init (MMIfaceModemInterface *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface); static void iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface);
@@ -200,6 +204,8 @@ struct _MMBroadbandModemPrivate {
MM3gppCmerMode modem_cmer_disable_mode; MM3gppCmerMode modem_cmer_disable_mode;
MM3gppCmerInd modem_cmer_ind; MM3gppCmerInd modem_cmer_ind;
gboolean modem_cgerep_support_checked; gboolean modem_cgerep_support_checked;
MM3gppCgerepMode modem_cgerep_enable_mode;
MM3gppCgerepMode modem_cgerep_disable_mode;
gboolean modem_cgerep_supported; gboolean modem_cgerep_supported;
MMFlowControl flow_control; MMFlowControl flow_control;
@@ -212,7 +218,7 @@ struct _MMBroadbandModemPrivate {
gboolean modem_3gpp_eps_network_supported; gboolean modem_3gpp_eps_network_supported;
gboolean modem_3gpp_5gs_network_supported; gboolean modem_3gpp_5gs_network_supported;
/* Implementation helpers */ /* Implementation helpers */
GPtrArray *modem_3gpp_registration_regex; GRegex *modem_3gpp_registration_regex;
MMModem3gppFacility modem_3gpp_ignored_facility_locks; MMModem3gppFacility modem_3gpp_ignored_facility_locks;
MMBaseBearer *modem_3gpp_initial_eps_bearer; MMBaseBearer *modem_3gpp_initial_eps_bearer;
MMModem3gppPacketServiceState modem_3gpp_packet_service_state; MMModem3gppPacketServiceState modem_3gpp_packet_service_state;
@@ -504,6 +510,7 @@ modem_create_sim (MMIfaceModem *self,
{ {
/* New generic SIM */ /* New generic SIM */
mm_base_sim_new (MM_BASE_MODEM (self), mm_base_sim_new (MM_BASE_MODEM (self),
G_OBJECT (self),
NULL, /* cancellable */ NULL, /* cancellable */
callback, callback,
user_data); user_data);
@@ -1500,32 +1507,6 @@ modem_load_own_numbers (MMIfaceModem *self,
/*****************************************************************************/ /*****************************************************************************/
/* Check if unlock required (Modem interface) */ /* Check if unlock required (Modem interface) */
typedef struct {
const gchar *result;
MMModemLock code;
} CPinResult;
static CPinResult unlock_results[] = {
/* Longer entries first so we catch the correct one with strcmp() */
{ "READY", MM_MODEM_LOCK_NONE },
{ "SIM PIN2", MM_MODEM_LOCK_SIM_PIN2 },
{ "SIM PUK2", MM_MODEM_LOCK_SIM_PUK2 },
{ "SIM PIN", MM_MODEM_LOCK_SIM_PIN },
{ "SIM PUK", MM_MODEM_LOCK_SIM_PUK },
{ "PH-NETSUB PIN", MM_MODEM_LOCK_PH_NETSUB_PIN },
{ "PH-NETSUB PUK", MM_MODEM_LOCK_PH_NETSUB_PUK },
{ "PH-FSIM PIN", MM_MODEM_LOCK_PH_FSIM_PIN },
{ "PH-FSIM PUK", MM_MODEM_LOCK_PH_FSIM_PUK },
{ "PH-CORP PIN", MM_MODEM_LOCK_PH_CORP_PIN },
{ "PH-CORP PUK", MM_MODEM_LOCK_PH_CORP_PUK },
{ "PH-SIM PIN", MM_MODEM_LOCK_PH_SIM_PIN },
{ "PH-NET PIN", MM_MODEM_LOCK_PH_NET_PIN },
{ "PH-NET PUK", MM_MODEM_LOCK_PH_NET_PUK },
{ "PH-SP PIN", MM_MODEM_LOCK_PH_SP_PIN },
{ "PH-SP PUK", MM_MODEM_LOCK_PH_SP_PUK },
{ NULL }
};
static MMModemLock static MMModemLock
modem_load_unlock_required_finish (MMIfaceModem *self, modem_load_unlock_required_finish (MMIfaceModem *self,
GAsyncResult *res, GAsyncResult *res,
@@ -1548,42 +1529,19 @@ cpin_query_ready (MMIfaceModem *self,
GTask *task) GTask *task)
{ {
MMModemLock lock = MM_MODEM_LOCK_UNKNOWN; MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
const gchar *result; const gchar *result;
GError *error = NULL; GError *error = NULL;
result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error) { if (error) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); } else {
return; if (result)
lock = mm_parse_cpin_response (result, TRUE);
g_task_return_int (task, lock);
} }
if (result &&
strstr (result, "+CPIN:")) {
CPinResult *iter = &unlock_results[0];
const gchar *str;
str = strstr (result, "+CPIN:") + 6;
/* Skip possible whitespaces after '+CPIN:' and before the response */
while (*str == ' ')
str++;
/* Some phones (Motorola EZX models) seem to quote the response */
if (str[0] == '"')
str++;
/* Translate the reply */
while (iter->result) {
if (g_str_has_prefix (str, iter->result)) {
lock = iter->code;
break;
}
iter++;
}
}
g_task_return_int (task, lock);
g_object_unref (task); g_object_unref (task);
} }
@@ -3724,20 +3682,33 @@ cgerep_format_check_ready (MMBroadbandModem *self,
GAsyncResult *res, GAsyncResult *res,
GTask *task) GTask *task)
{ {
GError *error = NULL; MM3gppCgerepMode supported_modes = MM_3GPP_CGEREP_MODE_NONE;
const gchar *result; GError *error = NULL;
const gchar *result;
gchar *aux;
result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!result) { if (error || !mm_3gpp_parse_cgerep_test_response (result, self, &supported_modes, &error)) {
mm_obj_dbg (self, "+CGEREP check failed: %s", error->message); mm_obj_dbg (self, "+CGEREP check failed: %s", error->message);
mm_obj_dbg (self, "packet domain event reporting is unsupported"); mm_obj_dbg (self, "packet domain event reporting is unsupported");
g_error_free (error); g_error_free (error);
goto out; goto out;
} }
mm_obj_dbg (self, "packet domain event reporting is supported"); aux = mm_3gpp_cgerep_mode_build_string_from_mask (supported_modes);
mm_obj_dbg (self, "supported +CGEREP modes: %s", aux);
g_free (aux);
self->priv->modem_cgerep_supported = TRUE; self->priv->modem_cgerep_supported = TRUE;
if (supported_modes & MM_3GPP_CGEREP_MODE_BUFFER_URCS_IF_LINK_RESERVED)
self->priv->modem_cgerep_enable_mode = MM_3GPP_CGEREP_MODE_BUFFER_URCS_IF_LINK_RESERVED;
else if (supported_modes & MM_3GPP_CGEREP_MODE_DISCARD_URCS_IF_LINK_RESERVED)
self->priv->modem_cgerep_enable_mode = MM_3GPP_CGEREP_MODE_DISCARD_URCS_IF_LINK_RESERVED;
if (supported_modes & MM_3GPP_CGEREP_MODE_DISCARD_URCS)
self->priv->modem_cgerep_disable_mode = MM_3GPP_CGEREP_MODE_DISCARD_URCS;
out: out:
/* go on with remaining checks */ /* go on with remaining checks */
check_and_setup_3gpp_urc_support (task); check_and_setup_3gpp_urc_support (task);
@@ -4078,7 +4049,7 @@ modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *_self,
ctx->cmer_command = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_enable_mode, self->priv->modem_cmer_ind); ctx->cmer_command = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_enable_mode, self->priv->modem_cmer_ind);
if (self->priv->modem_cgerep_support_checked && self->priv->modem_cgerep_supported) if (self->priv->modem_cgerep_support_checked && self->priv->modem_cgerep_supported)
ctx->cgerep_command = g_strdup ("+CGEREP=2"); ctx->cgerep_command = mm_3gpp_build_cgerep_set_request (self->priv->modem_cgerep_enable_mode);
run_unsolicited_events_setup (task); run_unsolicited_events_setup (task);
} }
@@ -4103,7 +4074,7 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *_self,
ctx->cmer_command = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_disable_mode, MM_3GPP_CMER_IND_NONE); ctx->cmer_command = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_disable_mode, MM_3GPP_CMER_IND_NONE);
if (self->priv->modem_cgerep_support_checked && self->priv->modem_cgerep_supported) if (self->priv->modem_cgerep_support_checked && self->priv->modem_cgerep_supported)
ctx->cgerep_command = g_strdup ("+CGEREP=0"); ctx->cgerep_command = mm_3gpp_build_cgerep_set_request (self->priv->modem_cgerep_disable_mode);
run_unsolicited_events_setup (task); run_unsolicited_events_setup (task);
} }
@@ -5296,32 +5267,28 @@ modem_3gpp_setup_unsolicited_registration_events (MMIfaceModem3gpp *self,
gpointer user_data) gpointer user_data)
{ {
MMPortSerialAt *ports[2]; MMPortSerialAt *ports[2];
GPtrArray *array; g_autoptr(GRegex) regex = NULL;
guint i; guint i;
guint j;
GTask *task; GTask *task;
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
/* Set up CREG unsolicited message handlers in both ports */ /* Set up CREG unsolicited message handlers in both ports */
array = mm_3gpp_creg_regex_get (FALSE); regex = mm_3gpp_creg_regex_get (FALSE);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (!ports[i]) if (!ports[i])
continue; continue;
mm_obj_dbg (self, "setting up 3GPP unsolicited registration messages handlers in %s", mm_obj_dbg (self, "setting up 3GPP unsolicited registration messages handlers in %s",
mm_port_get_device (MM_PORT (ports[i]))); mm_port_get_device (MM_PORT (ports[i])));
for (j = 0; j < array->len; j++) { mm_port_serial_at_add_unsolicited_msg_handler (
mm_port_serial_at_add_unsolicited_msg_handler ( MM_PORT_SERIAL_AT (ports[i]),
MM_PORT_SERIAL_AT (ports[i]), regex,
(GRegex *) g_ptr_array_index (array, j), (MMPortSerialAtUnsolicitedMsgFn)registration_state_changed,
(MMPortSerialAtUnsolicitedMsgFn)registration_state_changed, self,
self, NULL);
NULL);
}
} }
mm_3gpp_creg_regex_destroy (array);
task = g_task_new (self, NULL, callback, user_data); task = g_task_new (self, NULL, callback, user_data);
g_task_return_boolean (task, TRUE); g_task_return_boolean (task, TRUE);
@@ -5345,32 +5312,28 @@ modem_3gpp_cleanup_unsolicited_registration_events (MMIfaceModem3gpp *self,
gpointer user_data) gpointer user_data)
{ {
MMPortSerialAt *ports[2]; MMPortSerialAt *ports[2];
GPtrArray *array; g_autoptr(GRegex) regex = NULL;
guint i; guint i;
guint j;
GTask *task; GTask *task;
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
/* Set up CREG unsolicited message handlers in both ports */ /* Set up CREG unsolicited message handlers in both ports */
array = mm_3gpp_creg_regex_get (FALSE); regex = mm_3gpp_creg_regex_get (FALSE);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (!ports[i]) if (!ports[i])
continue; continue;
mm_obj_dbg (self, "cleaning up unsolicited registration messages handlers in %s", mm_obj_dbg (self, "cleaning up unsolicited registration messages handlers in %s",
mm_port_get_device (MM_PORT (ports[i]))); mm_port_get_device (MM_PORT (ports[i])));
for (j = 0; j < array->len; j++) { mm_port_serial_at_add_unsolicited_msg_handler (
mm_port_serial_at_add_unsolicited_msg_handler ( MM_PORT_SERIAL_AT (ports[i]),
MM_PORT_SERIAL_AT (ports[i]), regex,
(GRegex *) g_ptr_array_index (array, j), NULL,
NULL, NULL,
NULL, NULL);
NULL);
}
} }
mm_3gpp_creg_regex_destroy (array);
task = g_task_new (self, NULL, callback, user_data); task = g_task_new (self, NULL, callback, user_data);
g_task_return_boolean (task, TRUE); g_task_return_boolean (task, TRUE);
@@ -5637,7 +5600,6 @@ registration_status_check_ready (MMBroadbandModem *self,
RunRegistrationChecksContext *ctx; RunRegistrationChecksContext *ctx;
const gchar *response; const gchar *response;
GError *error = NULL; GError *error = NULL;
guint i;
gboolean parsed; gboolean parsed;
gboolean cgreg = FALSE; gboolean cgreg = FALSE;
gboolean cereg = FALSE; gboolean cereg = FALSE;
@@ -5670,18 +5632,10 @@ registration_status_check_ready (MMBroadbandModem *self,
} }
/* Try to match the response */ /* Try to match the response */
for (i = 0; if (!g_regex_match (self->priv->modem_3gpp_registration_regex,
i < self->priv->modem_3gpp_registration_regex->len; response,
i++) { 0,
if (g_regex_match ((GRegex *)g_ptr_array_index (self->priv->modem_3gpp_registration_regex, i), &match_info)) {
response,
0,
&match_info))
break;
g_clear_pointer (&match_info, g_match_info_free);
}
if (!match_info) {
error = g_error_new (MM_CORE_ERROR, error = g_error_new (MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
"Unknown registration status response: '%s'", "Unknown registration status response: '%s'",
@@ -5905,6 +5859,7 @@ modem_3gpp_create_initial_eps_bearer (MMIfaceModem3gpp *self,
* attempt connection through this bearer object. */ * attempt connection through this bearer object. */
bearer = g_object_new (MM_TYPE_BASE_BEARER, bearer = g_object_new (MM_TYPE_BASE_BEARER,
MM_BASE_BEARER_MODEM, MM_BASE_MODEM (self), MM_BASE_BEARER_MODEM, MM_BASE_MODEM (self),
MM_BIND_TO, G_OBJECT (self),
MM_BASE_BEARER_CONFIG, config, MM_BASE_BEARER_CONFIG, config,
"bearer-type", MM_BEARER_TYPE_DEFAULT_ATTACH, "bearer-type", MM_BEARER_TYPE_DEFAULT_ATTACH,
"connected", TRUE, "connected", TRUE,
@@ -6447,6 +6402,7 @@ modem_3gpp_ussd_context_send_unencoded (MMBroadbandModem *self)
{ {
Modem3gppUssdSendContext *ctx; Modem3gppUssdSendContext *ctx;
gchar *at_command = NULL; gchar *at_command = NULL;
gchar *quoted_command;
g_assert (self->priv->pending_ussd_action); g_assert (self->priv->pending_ussd_action);
ctx = g_task_get_task_data (self->priv->pending_ussd_action); ctx = g_task_get_task_data (self->priv->pending_ussd_action);
@@ -6454,9 +6410,11 @@ modem_3gpp_ussd_context_send_unencoded (MMBroadbandModem *self)
/* Build AT command with action unencoded */ /* Build AT command with action unencoded */
ctx->unencoded_used = TRUE; ctx->unencoded_used = TRUE;
ctx->current_is_unencoded = TRUE; ctx->current_is_unencoded = TRUE;
at_command = g_strdup_printf ("+CUSD=1,\"%s\",%d", quoted_command = mm_at_quote_string (ctx->command);
ctx->command, at_command = g_strdup_printf ("+CUSD=1,%s,%d",
MM_MODEM_GSM_USSD_SCHEME_7BIT); quoted_command,
MM_MODEM_GSM_USSD_SCHEME_7BIT);
g_free (quoted_command);
mm_base_modem_at_command (MM_BASE_MODEM (self), mm_base_modem_at_command (MM_BASE_MODEM (self),
at_command, at_command,
@@ -7182,11 +7140,13 @@ modem_messaging_init_current_storages (MMIfaceModemMessaging *self,
* the default one if needed. * the default one if needed.
*/ */
void static void
mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self, modem_messaging_unlock_storages (MMIfaceModemMessaging *_self,
gboolean mem1, gboolean mem1,
gboolean mem2) gboolean mem2)
{ {
MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
if (mem1) { if (mem1) {
g_assert (self->priv->mem1_storage_locked); g_assert (self->priv->mem1_storage_locked);
self->priv->mem1_storage_locked = FALSE; self->priv->mem1_storage_locked = FALSE;
@@ -7198,10 +7158,10 @@ mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self,
} }
} }
gboolean static gboolean
mm_broadband_modem_lock_sms_storages_finish (MMBroadbandModem *self, modem_messaging_lock_storages_finish (MMIfaceModemMessaging *self,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
return g_task_propagate_boolean (G_TASK (res), error); return g_task_propagate_boolean (G_TASK (res), error);
} }
@@ -7243,13 +7203,14 @@ lock_storages_cpms_set_ready (MMBaseModem *_self,
g_object_unref (task); g_object_unref (task);
} }
void static void
mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self, modem_messaging_lock_storages (MMIfaceModemMessaging *_self,
MMSmsStorage mem1, /* reading/listing/deleting */ MMSmsStorage mem1, /* reading/listing/deleting */
MMSmsStorage mem2, /* storing/sending */ MMSmsStorage mem2, /* storing/sending */
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
LockSmsStoragesContext *ctx; LockSmsStoragesContext *ctx;
GTask *task; GTask *task;
gchar *cmd = NULL; gchar *cmd = NULL;
@@ -7264,7 +7225,7 @@ mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self,
self, self,
callback, callback,
user_data, user_data,
mm_broadband_modem_lock_sms_storages, modem_messaging_lock_storages,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_RETRY, MM_CORE_ERROR_RETRY,
"SMS storage currently locked, try again later"); "SMS storage currently locked, try again later");
@@ -7538,13 +7499,13 @@ sms_part_ready (MMBroadbandModem *self,
GTask *task) GTask *task)
{ {
SmsPartContext *ctx; SmsPartContext *ctx;
MMSmsPart *part; MMSmsPart *part;
MM3gppPduInfo *info; MM3gppPduInfo *info;
const gchar *response; const gchar *response;
GError *error = NULL; GError *error = NULL;
/* Always always always unlock mem1 storage. Warned you've been. */ /* Always always always unlock mem1 storage. Warned you've been. */
mm_broadband_modem_unlock_sms_storages (self, TRUE, FALSE); mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (self), TRUE, FALSE);
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error) { if (error) {
@@ -7567,16 +7528,22 @@ sms_part_ready (MMBroadbandModem *self,
} }
part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error); part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error);
if (part) { if (!part) {
mm_obj_dbg (self, "correctly parsed PDU (%d)", ctx->idx);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
part,
MM_SMS_STATE_RECEIVED,
self->priv->modem_messaging_sms_default_storage);
} else {
/* Don't treat the error as critical */ /* Don't treat the error as critical */
mm_obj_dbg (self, "error parsing PDU (%d): %s", ctx->idx, error->message); mm_obj_dbg (self, "error parsing PDU (%d): %s", ctx->idx, error->message);
g_error_free (error); g_error_free (error);
} else {
mm_obj_dbg (self, "correctly parsed PDU (%d)", ctx->idx);
if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)),
part,
MM_SMS_STATE_RECEIVED,
self->priv->modem_messaging_sms_default_storage,
&error)) {
/* Don't treat the error as critical */
mm_obj_dbg (self, "error adding SMS (%d): %s", ctx->idx, error->message);
g_error_free (error);
}
} }
/* All done */ /* All done */
@@ -7586,15 +7553,15 @@ sms_part_ready (MMBroadbandModem *self,
} }
static void static void
indication_lock_storages_ready (MMBroadbandModem *self, indication_lock_storages_ready (MMIfaceModemMessaging *messaging,
GAsyncResult *res, GAsyncResult *res,
GTask *task) GTask *task)
{ {
SmsPartContext *ctx; SmsPartContext *ctx;
gchar *command; gchar *command;
GError *error = NULL; GError *error = NULL;
if (!mm_broadband_modem_lock_sms_storages_finish (self, res, &error)) { if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) {
/* TODO: we should either make this lock() never fail, by automatically /* TODO: we should either make this lock() never fail, by automatically
* retrying after some time, or otherwise retry here. */ * retrying after some time, or otherwise retry here. */
g_task_return_error (task, error); g_task_return_error (task, error);
@@ -7607,7 +7574,7 @@ indication_lock_storages_ready (MMBroadbandModem *self,
/* Retrieve the message */ /* Retrieve the message */
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
command = g_strdup_printf ("+CMGR=%d", ctx->idx); command = g_strdup_printf ("+CMGR=%d", ctx->idx);
mm_base_modem_at_command (MM_BASE_MODEM (self), mm_base_modem_at_command (MM_BASE_MODEM (messaging),
command, command,
10, 10,
FALSE, FALSE,
@@ -7655,11 +7622,11 @@ cmti_received (MMPortSerialAt *port,
g_task_set_task_data (task, ctx, g_free); g_task_set_task_data (task, ctx, g_free);
/* First, request to set the proper storage to read from */ /* First, request to set the proper storage to read from */
mm_broadband_modem_lock_sms_storages (self, mm_iface_modem_messaging_lock_storages (MM_IFACE_MODEM_MESSAGING (self),
storage, storage,
MM_SMS_STORAGE_UNKNOWN, MM_SMS_STORAGE_UNKNOWN,
(GAsyncReadyCallback)indication_lock_storages_ready, (GAsyncReadyCallback)indication_lock_storages_ready,
task); task);
} }
static void static void
@@ -7667,10 +7634,10 @@ cds_received (MMPortSerialAt *port,
GMatchInfo *info, GMatchInfo *info,
MMBroadbandModem *self) MMBroadbandModem *self)
{ {
GError *error = NULL; g_autoptr(GError) error = NULL;
MMSmsPart *part; MMSmsPart *part;
guint length; guint length;
gchar *pdu; gchar *pdu;
mm_obj_dbg (self, "got new non-stored message indication"); mm_obj_dbg (self, "got new non-stored message indication");
@@ -7682,16 +7649,20 @@ cds_received (MMPortSerialAt *port,
return; return;
part = mm_sms_part_3gpp_new_from_pdu (SMS_PART_INVALID_INDEX, pdu, self, &error); part = mm_sms_part_3gpp_new_from_pdu (SMS_PART_INVALID_INDEX, pdu, self, &error);
if (part) { if (!part) {
mm_obj_dbg (self, "correctly parsed non-stored PDU");
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
part,
MM_SMS_STATE_RECEIVED,
MM_SMS_STORAGE_UNKNOWN);
} else {
/* Don't treat the error as critical */ /* Don't treat the error as critical */
mm_obj_dbg (self, "error parsing non-stored PDU: %s", error->message); mm_obj_dbg (self, "error parsing non-stored PDU: %s", error->message);
g_error_free (error); } else {
mm_obj_dbg (self, "correctly parsed non-stored PDU");
if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)),
part,
MM_SMS_STATE_RECEIVED,
MM_SMS_STORAGE_UNKNOWN,
&error)) {
/* Don't treat the error as critical */
mm_obj_dbg (self, "error adding SMS: %s", error->message);
}
} }
} }
@@ -8075,10 +8046,16 @@ sms_text_part_list_ready (MMBroadbandModem *self,
mm_sms_part_set_class (part, -1); mm_sms_part_set_class (part, -1);
mm_obj_dbg (self, "correctly parsed SMS list entry (%d)", idx); mm_obj_dbg (self, "correctly parsed SMS list entry (%d)", idx);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
part, mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)),
sms_state_from_str (stat), part,
ctx->list_storage); sms_state_from_str (stat),
ctx->list_storage,
&error)) {
mm_obj_dbg (self, "failed to add SMS: %s", inner_error->message);
goto next;
}
next: next:
g_match_info_next (match_info, NULL); g_match_info_next (match_info, NULL);
} }
@@ -8117,7 +8094,7 @@ sms_pdu_part_list_ready (MMBroadbandModem *self,
GList *l; GList *l;
/* Always always always unlock mem1 storage. Warned you've been. */ /* Always always always unlock mem1 storage. Warned you've been. */
mm_broadband_modem_unlock_sms_storages (self, TRUE, FALSE); mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (self), TRUE, FALSE);
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (error) { if (error) {
@@ -8140,16 +8117,22 @@ sms_pdu_part_list_ready (MMBroadbandModem *self,
MMSmsPart *part; MMSmsPart *part;
part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error); part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error);
if (part) { if (!part) {
mm_obj_dbg (self, "correctly parsed PDU (%d)", info->index);
mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
part,
sms_state_from_index (info->status),
ctx->list_storage);
} else {
/* Don't treat the error as critical */ /* Don't treat the error as critical */
mm_obj_dbg (self, "error parsing PDU (%d): %s", info->index, error->message); mm_obj_dbg (self, "error parsing PDU (%d): %s", info->index, error->message);
g_clear_error (&error); g_clear_error (&error);
} else {
mm_obj_dbg (self, "correctly parsed PDU (%d)", info->index);
if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self),
mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)),
part,
sms_state_from_index (info->status),
ctx->list_storage,
&error)) {
/* Don't treat the error as critical */
mm_obj_dbg (self, "error adding SMS (%d): %s", info->index, error->message);
g_clear_error (&error);
}
} }
} }
@@ -8161,13 +8144,13 @@ sms_pdu_part_list_ready (MMBroadbandModem *self,
} }
static void static void
list_parts_lock_storages_ready (MMBroadbandModem *self, list_parts_lock_storages_ready (MMIfaceModemMessaging *self,
GAsyncResult *res, GAsyncResult *res,
GTask *task) GTask *task)
{ {
GError *error = NULL; GError *error = NULL;
if (!mm_broadband_modem_lock_sms_storages_finish (self, res, &error)) { if (!mm_iface_modem_messaging_lock_storages_finish (self, res, &error)) {
/* TODO: we should either make this lock() never fail, by automatically /* TODO: we should either make this lock() never fail, by automatically
* retrying after some time, or otherwise retry here. */ * retrying after some time, or otherwise retry here. */
g_task_return_error (task, error); g_task_return_error (task, error);
@@ -8209,20 +8192,33 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self,
mm_obj_dbg (self, "listing SMS parts in storage '%s'", mm_sms_storage_get_string (storage)); mm_obj_dbg (self, "listing SMS parts in storage '%s'", mm_sms_storage_get_string (storage));
/* First, request to set the proper storage to read from */ /* First, request to set the proper storage to read from */
mm_broadband_modem_lock_sms_storages (MM_BROADBAND_MODEM (self), mm_iface_modem_messaging_lock_storages (self,
storage, storage,
MM_SMS_STORAGE_UNKNOWN, MM_SMS_STORAGE_UNKNOWN,
(GAsyncReadyCallback)list_parts_lock_storages_ready, (GAsyncReadyCallback)list_parts_lock_storages_ready,
task); task);
} }
/*****************************************************************************/ /*****************************************************************************/
/* Create SMS (Messaging interface) */ /* Create SMS */
MMBaseSms *
mm_broadband_modem_create_sms (MMBroadbandModem *self)
{
g_assert (MM_BROADBAND_MODEM_GET_CLASS (self)->create_sms != NULL);
return MM_BROADBAND_MODEM_GET_CLASS (self)->create_sms (self);
}
static MMBaseSms * static MMBaseSms *
modem_messaging_create_sms (MMIfaceModemMessaging *self) modem_messaging_create_sms (MMBroadbandModem *self)
{ {
return mm_base_sms_new (MM_BASE_MODEM (self)); MMSmsStorage default_storage;
default_storage = mm_iface_modem_messaging_get_default_storage (MM_IFACE_MODEM_MESSAGING (self));
return mm_sms_at_new (MM_BASE_MODEM (self),
mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)),
default_storage);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -8416,8 +8412,7 @@ set_voice_in_call_unsolicited_events_handlers (MMBroadbandModem *self,
g_autoptr(GRegex) in_call_event_regex = NULL; g_autoptr(GRegex) in_call_event_regex = NULL;
guint i; guint i;
in_call_event_regex = g_regex_new ("\\r\\n(NO CARRIER|BUSY|NO ANSWER|NO DIALTONE)(\\r)?\\r\\n$", in_call_event_regex = mm_call_end_regex_get ();
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
ports[0] = MM_PORT_SERIAL_AT (ports_ctx->primary); ports[0] = MM_PORT_SERIAL_AT (ports_ctx->primary);
ports[1] = MM_PORT_SERIAL_AT (ports_ctx->secondary); ports[1] = MM_PORT_SERIAL_AT (ports_ctx->secondary);
@@ -8891,19 +8886,22 @@ modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self,
static MMBaseCall * static MMBaseCall *
modem_voice_create_call (MMIfaceModemVoice *_self, modem_voice_create_call (MMIfaceModemVoice *_self,
MMCallDirection direction, MMCallDirection direction,
const gchar *number) const gchar *number,
const guint dtmf_tone_duration)
{ {
MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
return mm_base_call_new (MM_BASE_MODEM (self), return mm_call_at_new (MM_BASE_MODEM (self),
direction, G_OBJECT (self),
number, direction,
/* If +CLCC is supported, we want no incoming timeout. number,
* Also, we're able to support detailed call state updates without dtmf_tone_duration,
* additional vendor-specific commands. */ /* If +CLCC is supported, we want no incoming timeout.
self->priv->clcc_supported, /* skip incoming timeout */ * Also, we're able to support detailed call state updates without
self->priv->clcc_supported, /* dialing->ringing supported */ * additional vendor-specific commands. */
self->priv->clcc_supported); /* ringing->active supported */ self->priv->clcc_supported, /* skip incoming timeout */
self->priv->clcc_supported, /* dialing->ringing supported */
self->priv->clcc_supported); /* ringing->active supported */
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -10602,7 +10600,7 @@ cbc_cbm_received (MMPortSerialAt *port,
GMatchInfo *info, GMatchInfo *info,
MMBroadbandModem *self) MMBroadbandModem *self)
{ {
GError *error = NULL; g_autoptr(GError) error = NULL;
MMCbmPart *part; MMCbmPart *part;
guint length; guint length;
gchar *pdu; gchar *pdu;
@@ -10617,15 +10615,19 @@ cbc_cbm_received (MMPortSerialAt *port,
return; return;
part = mm_cbm_part_new_from_pdu (pdu, self, &error); part = mm_cbm_part_new_from_pdu (pdu, self, &error);
if (part) { if (!part) {
mm_obj_dbg (self, "correctly parsed PDU");
mm_iface_modem_cell_broadcast_take_part (MM_IFACE_MODEM_CELL_BROADCAST (self),
part,
MM_CBM_STATE_RECEIVED);
} else {
/* Don't treat the error as critical */ /* Don't treat the error as critical */
mm_obj_dbg (self, "error parsing PDU: %s", error->message); mm_obj_dbg (self, "error parsing PDU: %s", error->message);
g_error_free (error); } else {
mm_obj_dbg (self, "correctly parsed PDU");
if (!mm_iface_modem_cell_broadcast_take_part (MM_IFACE_MODEM_CELL_BROADCAST (self),
G_OBJECT (self),
part,
MM_CBM_STATE_RECEIVED,
&error)) {
/* Don't treat the error as critical */
mm_obj_dbg (self, "error adding CBM: %s", error->message);
}
} }
} }
@@ -10682,15 +10684,6 @@ modem_cell_broadcast_cleanup_unsolicited_events (MMIfaceModemCellBroadcast *self
set_cell_broadcast_unsolicited_events_handlers (self, FALSE, callback, user_data); set_cell_broadcast_unsolicited_events_handlers (self, FALSE, callback, user_data);
} }
/*****************************************************************************/
/* Create CBM (CellBroadcast interface) */
static MMBaseCbm *
modem_cell_broadcast_create_cbm (MMIfaceModemCellBroadcast *self)
{
return mm_base_cbm_new (MM_BASE_MODEM (self));
}
/***********************************************************************************/ /***********************************************************************************/
/* Get channels (CellBroadcast interface) */ /* Get channels (CellBroadcast interface) */
@@ -10962,6 +10955,27 @@ modem_time_check_support (MMIfaceModemTime *self,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
MMIfacePortAt *port;
GError *error = NULL;
port = mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), &error);
if (!port) {
g_task_report_error (self, callback, user_data, modem_time_check_support, error);
return;
}
if (mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (MM_PORT (port)),
ID_MM_AT_NETWORK_TIME_BROKEN)) {
g_task_report_new_error (self,
callback,
user_data,
modem_time_check_support,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
"AT network time tagged as broken");
return;
}
mm_base_modem_at_sequence (MM_BASE_MODEM (self), mm_base_modem_at_sequence (MM_BASE_MODEM (self),
time_check_sequence, time_check_sequence,
NULL, /* response_processor_context */ NULL, /* response_processor_context */
@@ -11673,9 +11687,8 @@ setup_ports (MMBroadbandModem *self)
g_autoptr(GRegex) ciev_regex = NULL; g_autoptr(GRegex) ciev_regex = NULL;
g_autoptr(GRegex) cmti_regex = NULL; g_autoptr(GRegex) cmti_regex = NULL;
g_autoptr(GRegex) cusd_regex = NULL; g_autoptr(GRegex) cusd_regex = NULL;
GPtrArray *array; g_autoptr(GRegex) creg_regex = NULL;
guint i; guint i;
guint j;
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
@@ -11691,7 +11704,7 @@ setup_ports (MMBroadbandModem *self)
NULL); NULL);
/* Cleanup all unsolicited message handlers in all AT ports */ /* Cleanup all unsolicited message handlers in all AT ports */
array = mm_3gpp_creg_regex_get (FALSE); creg_regex = mm_3gpp_creg_regex_get (FALSE);
ciev_regex = mm_3gpp_ciev_regex_get (); ciev_regex = mm_3gpp_ciev_regex_get ();
cmti_regex = mm_3gpp_cmti_regex_get (); cmti_regex = mm_3gpp_cmti_regex_get ();
cusd_regex = mm_3gpp_cusd_regex_get (); cusd_regex = mm_3gpp_cusd_regex_get ();
@@ -11700,14 +11713,11 @@ setup_ports (MMBroadbandModem *self)
if (!ports[i]) if (!ports[i])
continue; continue;
for (j = 0; j < array->len; j++) mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), creg_regex, NULL, NULL, NULL);
mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), (GRegex *)g_ptr_array_index (array, j), NULL, NULL, NULL);
mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), ciev_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), ciev_regex, NULL, NULL, NULL);
mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cmti_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cmti_regex, NULL, NULL, NULL);
mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cusd_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cusd_regex, NULL, NULL, NULL);
} }
mm_3gpp_creg_regex_destroy (array);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -12941,7 +12951,11 @@ enable (MMBaseModem *self,
return; return;
case MM_MODEM_STATE_ENABLING: case MM_MODEM_STATE_ENABLING:
g_assert_not_reached (); /* Enabling can be ongoing when another user enable request arrives,
* just error out gracefully. */
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot enable modem (again): enabling ongoing");
g_object_unref (task);
return; return;
case MM_MODEM_STATE_ENABLED: case MM_MODEM_STATE_ENABLED:
@@ -14228,6 +14242,8 @@ mm_broadband_modem_init (MMBroadbandModem *self)
self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_NONE; self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_NONE;
self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_NONE; self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_NONE;
self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_NONE; self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_NONE;
self->priv->modem_cgerep_enable_mode = MM_3GPP_CGEREP_MODE_NONE;
self->priv->modem_cgerep_disable_mode = MM_3GPP_CGEREP_MODE_NONE;
self->priv->flow_control = MM_FLOW_CONTROL_NONE; self->priv->flow_control = MM_FLOW_CONTROL_NONE;
self->priv->initial_eps_bearer_cid = -1; self->priv->initial_eps_bearer_cid = -1;
} }
@@ -14247,7 +14263,7 @@ finalize (GObject *object)
ports_context_unref (self->priv->in_call_ports_ctx); ports_context_unref (self->priv->in_call_ports_ctx);
if (self->priv->modem_3gpp_registration_regex) if (self->priv->modem_3gpp_registration_regex)
mm_3gpp_creg_regex_destroy (self->priv->modem_3gpp_registration_regex); g_regex_unref (self->priv->modem_3gpp_registration_regex);
g_free (self->priv->carrier_config_mapping); g_free (self->priv->carrier_config_mapping);
@@ -14554,7 +14570,6 @@ iface_modem_cell_broadcast_init (MMIfaceModemCellBroadcastInterface *iface)
iface->cleanup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; iface->cleanup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish;
iface->set_channels = modem_cell_broadcast_set_channels; iface->set_channels = modem_cell_broadcast_set_channels;
iface->set_channels_finish = modem_cell_broadcast_set_channels_finish; iface->set_channels_finish = modem_cell_broadcast_set_channels_finish;
iface->create_cbm = modem_cell_broadcast_create_cbm;
} }
static void static void
@@ -14590,9 +14605,11 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface)
iface->enable_unsolicited_events_finish = modem_messaging_enable_unsolicited_events_finish; iface->enable_unsolicited_events_finish = modem_messaging_enable_unsolicited_events_finish;
iface->cleanup_unsolicited_events = modem_messaging_cleanup_unsolicited_events; iface->cleanup_unsolicited_events = modem_messaging_cleanup_unsolicited_events;
iface->cleanup_unsolicited_events_finish = modem_messaging_setup_cleanup_unsolicited_events_finish; iface->cleanup_unsolicited_events_finish = modem_messaging_setup_cleanup_unsolicited_events_finish;
iface->create_sms = modem_messaging_create_sms;
iface->init_current_storages = modem_messaging_init_current_storages; iface->init_current_storages = modem_messaging_init_current_storages;
iface->init_current_storages_finish = modem_messaging_init_current_storages_finish; iface->init_current_storages_finish = modem_messaging_init_current_storages_finish;
iface->lock_storages = modem_messaging_lock_storages;
iface->lock_storages_finish = modem_messaging_lock_storages_finish;
iface->unlock_storages = modem_messaging_unlock_storages;
} }
static void static void
@@ -14711,6 +14728,7 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
klass->disabling_stopped = disabling_stopped; klass->disabling_stopped = disabling_stopped;
klass->load_initial_eps_bearer_cid = load_initial_eps_bearer_cid; klass->load_initial_eps_bearer_cid = load_initial_eps_bearer_cid;
klass->load_initial_eps_bearer_cid_finish = load_initial_eps_bearer_cid_finish; klass->load_initial_eps_bearer_cid_finish = load_initial_eps_bearer_cid_finish;
klass->create_sms = modem_messaging_create_sms;
g_object_class_override_property (object_class, g_object_class_override_property (object_class,
PROP_MODEM_DBUS_SKELETON, PROP_MODEM_DBUS_SKELETON,
+7 -12
View File
@@ -27,6 +27,7 @@
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-charsets.h" #include "mm-charsets.h"
#include "mm-base-modem.h" #include "mm-base-modem.h"
#include "mm-base-sms.h"
#define MM_TYPE_BROADBAND_MODEM (mm_broadband_modem_get_type ()) #define MM_TYPE_BROADBAND_MODEM (mm_broadband_modem_get_type ())
#define MM_BROADBAND_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM, MMBroadbandModem)) #define MM_BROADBAND_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM, MMBroadbandModem))
@@ -105,6 +106,9 @@ struct _MMBroadbandModemClass {
gint (* load_initial_eps_bearer_cid_finish) (MMBroadbandModem *self, gint (* load_initial_eps_bearer_cid_finish) (MMBroadbandModem *self,
GAsyncResult *res, GAsyncResult *res,
GError **error); GError **error);
/* Create SMS objects */
MMBaseSms * (* create_sms) (MMBroadbandModem *self);
}; };
GType mm_broadband_modem_get_type (void); GType mm_broadband_modem_get_type (void);
@@ -126,18 +130,6 @@ gchar *mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
const gchar *ati1, const gchar *ati1,
GError **error); GError **error);
/* Locking/unlocking SMS storages */
void mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self,
MMSmsStorage mem1, /* reading/listing/deleting */
MMSmsStorage mem2, /* storing/sending */
GAsyncReadyCallback callback,
gpointer user_data);
gboolean mm_broadband_modem_lock_sms_storages_finish (MMBroadbandModem *self,
GAsyncResult *res,
GError **error);
void mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self,
gboolean mem1,
gboolean mem2);
/* Helper to update SIM hot swap */ /* Helper to update SIM hot swap */
gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem *self, gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem *self,
GError **error); GError **error);
@@ -146,4 +138,7 @@ void mm_broadband_modem_sim_hot_swap_ports_context_reset (MMBroadbandModem
/* Helper to manage initial EPS bearer */ /* Helper to manage initial EPS bearer */
gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self); gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self);
/* Helper to create a new modem-specific SMS object */
MMBaseSms *mm_broadband_modem_create_sms (MMBroadbandModem *self);
#endif /* MM_BROADBAND_MODEM_H */ #endif /* MM_BROADBAND_MODEM_H */
+474
View File
@@ -0,0 +1,474 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2015 Riccardo Vangelisti <riccardo.vangelisti@sadel.it>
* Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es>
* Copyright (C) 2019 Purism SPC
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-call-at.h"
#include "mm-base-modem-at.h"
#include "mm-base-modem.h"
#include "mm-modem-helpers.h"
#include "mm-error-helpers.h"
#include "mm-log-object.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMCallAt, mm_call_at, MM_TYPE_BASE_CALL)
typedef enum {
FEATURE_SUPPORT_UNKNOWN,
FEATURE_NOT_SUPPORTED,
FEATURE_SUPPORTED,
} FeatureSupport;
struct _MMCallAtPrivate {
/* The modem which owns this call */
MMBaseModem *modem;
/* DTMF support */
FeatureSupport vtd_supported;
};
/*****************************************************************************/
/* Start the CALL */
static gboolean
call_start_finish (MMBaseCall *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
call_start_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
const gchar *response = NULL;
response = mm_base_modem_at_command_finish (modem, res, &error);
/* check response for error */
if (response && response[0])
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Couldn't start the call: Unhandled response '%s'", response);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
call_start (MMBaseCall *_self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallAt *self = MM_CALL_AT (_self);
GError *error = NULL;
GTask *task;
gchar *cmd;
MMIfacePortAt *port;
task = g_task_new (self, NULL, callback, user_data);
port = mm_base_modem_peek_best_at_port (self->priv->modem, &error);
if (!port) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
cmd = g_strdup_printf ("ATD%s;", mm_gdbus_call_get_number (MM_GDBUS_CALL (self)));
mm_base_modem_at_command_full (self->priv->modem,
port,
cmd,
90,
FALSE, /* no cached */
FALSE, /* no raw */
cancellable,
(GAsyncReadyCallback)call_start_ready,
task);
g_free (cmd);
}
/*****************************************************************************/
/* Accept the call */
static gboolean
call_accept_finish (MMBaseCall *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
call_accept_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
const gchar *response;
response = mm_base_modem_at_command_finish (modem, res, &error);
/* check response for error */
if (response && response[0])
g_set_error (&error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Couldn't accept the call: Unhandled response '%s'", response);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
call_accept (MMBaseCall *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallAt *self = MM_CALL_AT (_self);
GTask *task;
task = g_task_new (self, NULL, callback, user_data);
mm_base_modem_at_command (self->priv->modem,
"ATA",
2,
FALSE,
(GAsyncReadyCallback)call_accept_ready,
task);
}
/*****************************************************************************/
/* Deflect the call */
static gboolean
call_deflect_finish (MMBaseCall *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
call_deflect_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
mm_base_modem_at_command_finish (modem, res, &error);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
call_deflect (MMBaseCall *_self,
const gchar *number,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallAt *self = MM_CALL_AT (_self);
GTask *task;
gchar *cmd;
task = g_task_new (self, NULL, callback, user_data);
cmd = g_strdup_printf ("+CTFR=%s", number);
mm_base_modem_at_command (self->priv->modem,
cmd,
20,
FALSE,
(GAsyncReadyCallback)call_deflect_ready,
task);
g_free (cmd);
}
/*****************************************************************************/
/* Hangup the call */
static gboolean
call_hangup_finish (MMBaseCall *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
chup_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
mm_base_modem_at_command_finish (modem, res, &error);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
chup_fallback (GTask *task)
{
MMCallAt *self;
self = MM_CALL_AT (g_task_get_source_object (task));
mm_base_modem_at_command (self->priv->modem,
"+CHUP",
2,
FALSE,
(GAsyncReadyCallback)chup_ready,
task);
}
static void
chld_hangup_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
MMBaseCall *self;
GError *error = NULL;
self = g_task_get_source_object (task);
mm_base_modem_at_command_finish (modem, res, &error);
if (error) {
mm_obj_warn (self, "couldn't hangup single call with call id '%u': %s",
mm_base_call_get_index (MM_BASE_CALL (self)), error->message);
g_error_free (error);
chup_fallback (task);
return;
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
call_hangup (MMBaseCall *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallAt *self = MM_CALL_AT (_self);
GTask *task;
guint index;
task = g_task_new (self, NULL, callback, user_data);
/* Try to hangup the single call id */
index = mm_base_call_get_index (MM_BASE_CALL (self));
if (index) {
gchar *cmd;
cmd = g_strdup_printf ("+CHLD=1%u", index);
mm_base_modem_at_command (self->priv->modem,
cmd,
2,
FALSE,
(GAsyncReadyCallback)chld_hangup_ready,
task);
g_free (cmd);
return;
}
/* otherwise terminate all */
chup_fallback (task);
}
/*****************************************************************************/
/* Send DTMF tone to call */
static gssize
call_send_dtmf_finish (MMBaseCall *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_int (G_TASK (res), error);
}
static void
call_send_dtmf_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
MMBaseCall *self;
GError *error = NULL;
self = g_task_get_source_object (task);
mm_base_modem_at_command_finish (modem, res, &error);
if (error) {
mm_obj_dbg (self, "couldn't send dtmf: %s", error->message);
g_task_return_error (task, error);
g_object_unref (task);
return;
}
/* We sent one character */
g_task_return_int (task, 1);
g_object_unref (task);
}
static void
send_dtmf_digit (MMCallAt *self,
GTask *task,
const gchar dtmf_digit)
{
g_autofree gchar *cmd = NULL;
cmd = g_strdup_printf ("AT+VTS=%c", dtmf_digit);
mm_base_modem_at_command (self->priv->modem,
cmd,
3,
FALSE,
(GAsyncReadyCallback)call_send_dtmf_ready,
task);
}
static void
call_dtmf_vtd_ready (MMBaseModem *modem,
GAsyncResult *res,
GTask *task)
{
MMCallAt *self;
g_autoptr(GError) error = NULL;
gchar dtmf_digit;
self = g_task_get_source_object (task);
mm_base_modem_at_command_finish (modem, res, &error);
self->priv->vtd_supported = error ? FEATURE_NOT_SUPPORTED : FEATURE_SUPPORTED;
dtmf_digit = (gchar) GPOINTER_TO_UINT (g_task_get_task_data (task));
send_dtmf_digit (self, task, dtmf_digit);
}
static void
call_send_dtmf (MMBaseCall *_self,
const gchar *dtmf,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallAt *self = MM_CALL_AT (_self);
GTask *task;
g_autofree gchar *cmd = NULL;
task = g_task_new (self, NULL, callback, user_data);
if (self->priv->vtd_supported == FEATURE_NOT_SUPPORTED) {
send_dtmf_digit (self, task, dtmf[0]);
return;
}
g_task_set_task_data (task, GUINT_TO_POINTER (dtmf[0]), NULL);
/* Otherwise try to set duration */
cmd = g_strdup_printf ("AT+VTD=%u", mm_base_call_get_dtmf_tone_duration (_self));
mm_base_modem_at_command (self->priv->modem,
cmd,
3,
FALSE,
(GAsyncReadyCallback)call_dtmf_vtd_ready,
task);
}
/*****************************************************************************/
MMBaseCall *
mm_call_at_new (MMBaseModem *modem,
GObject *bind_to,
MMCallDirection direction,
const gchar *number,
const guint dtmf_tone_duration,
gboolean skip_incoming_timeout,
gboolean supports_dialing_to_ringing,
gboolean supports_ringing_to_active)
{
MMBaseCall *call;
call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_AT,
MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
MM_BIND_TO, bind_to,
MM_CALL_DIRECTION, direction,
MM_CALL_NUMBER, number,
MM_CALL_DTMF_TONE_DURATION, dtmf_tone_duration,
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, skip_incoming_timeout,
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, supports_dialing_to_ringing,
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, supports_ringing_to_active,
NULL));
MM_CALL_AT (call)->priv->modem = g_object_ref (modem);
return call;
}
static void
mm_call_at_init (MMCallAt *self)
{
/* Initialize private data */
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CALL_AT, MMCallAtPrivate);
}
static void
dispose (GObject *object)
{
MMCallAt *self = MM_CALL_AT (object);
g_clear_object (&self->priv->modem);
G_OBJECT_CLASS (mm_call_at_parent_class)->dispose (object);
}
static void
mm_call_at_class_init (MMCallAtClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MMBaseCallClass *base_call_class = MM_BASE_CALL_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMCallAtPrivate));
object_class->dispose = dispose;
base_call_class->start = call_start;
base_call_class->start_finish = call_start_finish;
base_call_class->accept = call_accept;
base_call_class->accept_finish = call_accept_finish;
base_call_class->deflect = call_deflect;
base_call_class->deflect_finish = call_deflect_finish;
base_call_class->hangup = call_hangup;
base_call_class->hangup_finish = call_hangup_finish;
base_call_class->send_dtmf = call_send_dtmf;
base_call_class->send_dtmf_finish = call_send_dtmf_finish;
}
+61
View File
@@ -0,0 +1,61 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2015 Riccardo Vangelisti <riccardo.vangelisti@sadel.it>
* Copyright (C) 2019 Purism SPC
*/
#ifndef MM_CALL_AT_H
#define MM_CALL_AT_H
#include <glib.h>
#include <glib-object.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-base-call.h"
#include "mm-base-modem.h"
#define MM_TYPE_CALL_AT (mm_call_at_get_type ())
#define MM_CALL_AT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CALL_AT, MMCallAt))
#define MM_CALL_AT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CALL_AT, MMCallAtClass))
#define MM_IS_CALL_AT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CALL_AT))
#define MM_IS_CALL_AT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CALL_AT))
#define MM_CALL_AT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CALL_AT, MMCallAtClass))
typedef struct _MMCallAt MMCallAt;
typedef struct _MMCallAtClass MMCallAtClass;
typedef struct _MMCallAtPrivate MMCallAtPrivate;
struct _MMCallAt {
MMBaseCall parent;
MMCallAtPrivate *priv;
};
struct _MMCallAtClass {
MMBaseCallClass parent;
};
GType mm_call_at_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCallAt, g_object_unref)
MMBaseCall *mm_call_at_new (MMBaseModem *modem,
GObject *bind_to,
MMCallDirection direction,
const gchar *number,
const guint dtmf_tone_duration,
gboolean skip_incoming_timeout,
gboolean supports_dialing_to_ringing,
gboolean supports_ringing_to_active);
#endif /* MM_CALL_AT_H */
+2 -63
View File
@@ -24,20 +24,12 @@
#define _LIBMM_INSIDE_MM #define _LIBMM_INSIDE_MM
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-iface-modem-messaging.h"
#include "mm-call-list.h" #include "mm-call-list.h"
#include "mm-base-call.h" #include "mm-base-call.h"
#include "mm-log.h" #include "mm-log.h"
G_DEFINE_TYPE (MMCallList, mm_call_list, G_TYPE_OBJECT) G_DEFINE_TYPE (MMCallList, mm_call_list, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_MODEM,
PROP_LAST
};
static GParamSpec *properties[PROP_LAST];
enum { enum {
SIGNAL_CALL_ADDED, SIGNAL_CALL_ADDED,
SIGNAL_CALL_DELETED, SIGNAL_CALL_DELETED,
@@ -46,8 +38,6 @@ enum {
static guint signals[SIGNAL_LAST]; static guint signals[SIGNAL_LAST];
struct _MMCallListPrivate { struct _MMCallListPrivate {
/* The owner modem */
MMBaseModem *modem;
/* List of call objects */ /* List of call objects */
GList *list; GList *list;
}; };
@@ -213,49 +203,10 @@ mm_call_list_add_call (MMCallList *self,
/*****************************************************************************/ /*****************************************************************************/
MMCallList * MMCallList *
mm_call_list_new (MMBaseModem *modem) mm_call_list_new (void)
{ {
/* Create the object */ /* Create the object */
return g_object_new (MM_TYPE_CALL_LIST, return g_object_new (MM_TYPE_CALL_LIST, NULL);
MM_CALL_LIST_MODEM, modem,
NULL);
}
static void
set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MMCallList *self = MM_CALL_LIST (object);
switch (prop_id) {
case PROP_MODEM:
g_clear_object (&self->priv->modem);
self->priv->modem = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MMCallList *self = MM_CALL_LIST (object);
switch (prop_id) {
case PROP_MODEM:
g_value_set_object (value, self->priv->modem);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
} }
static void static void
@@ -272,7 +223,6 @@ dispose (GObject *object)
{ {
MMCallList *self = MM_CALL_LIST (object); MMCallList *self = MM_CALL_LIST (object);
g_clear_object (&self->priv->modem);
g_list_free_full (self->priv->list, g_object_unref); g_list_free_full (self->priv->list, g_object_unref);
self->priv->list = NULL; self->priv->list = NULL;
@@ -287,19 +237,8 @@ mm_call_list_class_init (MMCallListClass *klass)
g_type_class_add_private (object_class, sizeof (MMCallListPrivate)); g_type_class_add_private (object_class, sizeof (MMCallListPrivate));
/* Virtual methods */ /* Virtual methods */
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose; object_class->dispose = dispose;
/* Properties */
properties[PROP_MODEM] =
g_param_spec_object (MM_CALL_LIST_MODEM,
"Modem",
"The Modem which owns this CALL list",
MM_TYPE_BASE_MODEM,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]);
/* Signals */ /* Signals */
signals[SIGNAL_CALL_ADDED] = signals[SIGNAL_CALL_ADDED] =
g_signal_new (MM_CALL_ADDED, g_signal_new (MM_CALL_ADDED,
+1 -4
View File
@@ -19,7 +19,6 @@
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include "mm-base-modem.h"
#include "mm-base-call.h" #include "mm-base-call.h"
#define MM_TYPE_CALL_LIST (mm_call_list_get_type ()) #define MM_TYPE_CALL_LIST (mm_call_list_get_type ())
@@ -33,8 +32,6 @@ typedef struct _MMCallList MMCallList;
typedef struct _MMCallListClass MMCallListClass; typedef struct _MMCallListClass MMCallListClass;
typedef struct _MMCallListPrivate MMCallListPrivate; typedef struct _MMCallListPrivate MMCallListPrivate;
#define MM_CALL_LIST_MODEM "call-list-modem"
#define MM_CALL_ADDED "call-added" #define MM_CALL_ADDED "call-added"
#define MM_CALL_DELETED "call-deleted" #define MM_CALL_DELETED "call-deleted"
@@ -57,7 +54,7 @@ struct _MMCallListClass {
GType mm_call_list_get_type (void); GType mm_call_list_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCallList, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCallList, g_object_unref)
MMCallList *mm_call_list_new (MMBaseModem *modem); MMCallList *mm_call_list_new (void);
GStrv mm_call_list_get_paths (MMCallList *self); GStrv mm_call_list_get_paths (MMCallList *self);
guint mm_call_list_get_count (MMCallList *self); guint mm_call_list_get_count (MMCallList *self);
+140 -95
View File
@@ -31,9 +31,15 @@
#include "mm-call-qmi.h" #include "mm-call-qmi.h"
#include "mm-base-modem.h" #include "mm-base-modem.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMCallQmi, mm_call_qmi, MM_TYPE_BASE_CALL) G_DEFINE_TYPE (MMCallQmi, mm_call_qmi, MM_TYPE_BASE_CALL)
struct _MMCallQmiPrivate {
/* The modem which owns this call */
MMBaseModem *modem;
};
/*****************************************************************************/ /*****************************************************************************/
static gboolean static gboolean
@@ -47,12 +53,7 @@ ensure_qmi_client (MMCallQmi *self,
QmiClient *client; QmiClient *client;
MMPortQmi *port; MMPortQmi *port;
g_object_get (self, port = mm_broadband_modem_qmi_peek_port_qmi (MM_BROADBAND_MODEM_QMI (self->priv->modem));
MM_BASE_CALL_MODEM, &modem,
NULL);
g_assert (MM_IS_BASE_MODEM (modem));
port = mm_broadband_modem_qmi_peek_port_qmi (MM_BROADBAND_MODEM_QMI (modem));
g_object_unref (modem); g_object_unref (modem);
if (!port) { if (!port) {
@@ -330,22 +331,41 @@ call_hangup (MMBaseCall *self,
} }
/*****************************************************************************/ /*****************************************************************************/
/* Send DTMF character */ /* DTMF handling */
typedef struct { static gboolean
QmiClient *client; get_client_and_call_id (MMCallQmi *self,
guint8 call_id; GAsyncReadyCallback callback,
} SendDtmfContext; gpointer user_data,
QmiClient **client,
static void guint *call_id)
send_dtmf_context_free (SendDtmfContext *ctx)
{ {
g_clear_object (&ctx->client); g_return_val_if_fail (client, FALSE);
g_slice_free (SendDtmfContext, ctx); g_return_val_if_fail (call_id, FALSE);
/* Ensure Voice client */
if (!ensure_qmi_client (self,
QMI_SERVICE_VOICE, client,
callback, user_data))
return FALSE;
*call_id = mm_base_call_get_index (MM_BASE_CALL (self));
if (*call_id == 0) {
g_task_report_new_error (self,
callback,
user_data,
(gpointer) __func__,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"Invalid call index");
return FALSE;
}
return TRUE;
} }
static gboolean static gboolean
call_send_dtmf_finish (MMBaseCall *self, call_stop_dtmf_finish (MMBaseCall *call,
GAsyncResult *res, GAsyncResult *res,
GError **error) GError **error)
{ {
@@ -365,35 +385,59 @@ voice_stop_continuous_dtmf_ready (QmiClientVoice *client,
g_prefix_error (&error, "QMI operation failed: "); g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error); g_task_return_error (task, error);
} else if (!qmi_message_voice_stop_continuous_dtmf_output_get_result (output, &error)) { } else if (!qmi_message_voice_stop_continuous_dtmf_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't send DTMF character: "); g_prefix_error (&error, "Couldn't stop DTMF character: ");
g_task_return_error (task, error); g_task_return_error (task, error);
} else { } else {
g_task_return_boolean (task, TRUE); g_task_return_boolean (task, TRUE);
} }
g_object_unref (task); g_object_unref (task);
} }
static gboolean static void
voice_stop_continuous_dtmf (GTask *task) call_stop_dtmf (MMBaseCall *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{ {
SendDtmfContext *ctx; MMCallQmi *self = MM_CALL_QMI (_self);
GError *error = NULL; GTask *task;
g_autoptr (QmiMessageVoiceStopContinuousDtmfInput) input = NULL; QmiClient *client = NULL;
guint call_id = 0;
GError *error = NULL;
g_autoptr (QmiMessageVoiceStopContinuousDtmfInput) input = NULL;
ctx = g_task_get_task_data (task); if (!get_client_and_call_id (self,
callback,
user_data,
&client,
&call_id))
return;
task = g_task_new (self, NULL, callback, user_data);
input = qmi_message_voice_stop_continuous_dtmf_input_new (); input = qmi_message_voice_stop_continuous_dtmf_input_new ();
qmi_message_voice_stop_continuous_dtmf_input_set_data (input, ctx->call_id, &error); if (!qmi_message_voice_stop_continuous_dtmf_input_set_data (input,
call_id,
&error)) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
qmi_client_voice_stop_continuous_dtmf (QMI_CLIENT_VOICE (ctx->client), /* Stop sending DTMF tone */
qmi_client_voice_stop_continuous_dtmf (QMI_CLIENT_VOICE (client),
input, input,
5, 5,
NULL, NULL,
(GAsyncReadyCallback) voice_stop_continuous_dtmf_ready, (GAsyncReadyCallback) voice_stop_continuous_dtmf_ready,
task); task);
}
return G_SOURCE_REMOVE; static gssize
call_send_dtmf_finish (MMBaseCall *call,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_int (G_TASK (res), error);
} }
static void static void
@@ -401,80 +445,55 @@ voice_start_continuous_dtmf_ready (QmiClientVoice *client,
GAsyncResult *res, GAsyncResult *res,
GTask *task) GTask *task)
{ {
g_autoptr(QmiMessageVoiceStartContinuousDtmfOutput) output = NULL; g_autoptr (QmiMessageVoiceStartContinuousDtmfOutput) output = NULL;
GError *error = NULL; GError *error = NULL;
output = qmi_client_voice_start_continuous_dtmf_finish (client, res, &error); output = qmi_client_voice_start_continuous_dtmf_finish (client, res, &error);
if (!output) { if (!output) {
g_prefix_error (&error, "QMI operation failed: "); g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); } else if (!qmi_message_voice_start_continuous_dtmf_output_get_result (output, &error)) {
return;
}
if (!qmi_message_voice_start_continuous_dtmf_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't send DTMF character: "); g_prefix_error (&error, "Couldn't send DTMF character: ");
g_task_return_error (task, error); g_task_return_error (task, error);
} else {
g_task_return_int (task, 1);
}
g_object_unref (task);
}
static void
call_send_dtmf (MMBaseCall *_self,
const gchar *dtmf,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMCallQmi *self = MM_CALL_QMI (_self);
GTask *task;
QmiClient *client = NULL;
guint call_id = 0;
GError *error = NULL;
g_autoptr (QmiMessageVoiceStartContinuousDtmfInput) input = NULL;
if (!get_client_and_call_id (self,
callback,
user_data,
&client,
&call_id))
return;
task = g_task_new (self, NULL, callback, user_data);
input = qmi_message_voice_start_continuous_dtmf_input_new ();
if (!qmi_message_voice_start_continuous_dtmf_input_set_data (input,
call_id,
dtmf[0],
&error)) {
g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
return; return;
} }
/* Disable DTMF press after 500 ms */
g_timeout_add (500, (GSourceFunc) voice_stop_continuous_dtmf, task);
}
static void
call_send_dtmf (MMBaseCall *self,
const gchar *dtmf,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
GError *error = NULL;
SendDtmfContext *ctx;
QmiClient *client = NULL;
guint8 call_id;
g_autoptr (QmiMessageVoiceStartContinuousDtmfInput) input = NULL;
/* Ensure Voice client */
if (!ensure_qmi_client (MM_CALL_QMI (self),
QMI_SERVICE_VOICE, &client,
callback, user_data))
return;
task = g_task_new (self, NULL, callback, user_data);
call_id = mm_base_call_get_index (self);
if (call_id == 0) {
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"Invalid call index");
g_object_unref (task);
return;
}
ctx = g_slice_new0 (SendDtmfContext);
ctx->client = g_object_ref (client);
ctx->call_id = call_id;
g_task_set_task_data (task, ctx, (GDestroyNotify) send_dtmf_context_free);
/* Send DTMF character as ASCII number */ /* Send DTMF character as ASCII number */
input = qmi_message_voice_start_continuous_dtmf_input_new ();
qmi_message_voice_start_continuous_dtmf_input_set_data (input,
call_id,
(guint8) dtmf[0],
&error);
if (error) {
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
"DTMF data build failed");
g_object_unref (task);
return;
}
qmi_client_voice_start_continuous_dtmf (QMI_CLIENT_VOICE (client), qmi_client_voice_start_continuous_dtmf (QMI_CLIENT_VOICE (client),
input, input,
5, 5,
@@ -488,28 +507,52 @@ call_send_dtmf (MMBaseCall *self,
MMBaseCall * MMBaseCall *
mm_call_qmi_new (MMBaseModem *modem, mm_call_qmi_new (MMBaseModem *modem,
MMCallDirection direction, MMCallDirection direction,
const gchar *number) const gchar *number,
const guint dtmf_tone_duration)
{ {
return MM_BASE_CALL (g_object_new (MM_TYPE_CALL_QMI, MMBaseCall *call;
MM_BASE_CALL_MODEM, modem,
"direction", direction, call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_QMI,
"number", number, MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
MM_BIND_TO, modem,
MM_CALL_DIRECTION, direction,
MM_CALL_NUMBER, number,
MM_CALL_DTMF_TONE_DURATION, dtmf_tone_duration,
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, TRUE, MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, TRUE,
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, TRUE, MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, TRUE,
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, TRUE, MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, TRUE,
NULL)); NULL));
MM_CALL_QMI (call)->priv->modem = g_object_ref (modem);
return call;
} }
static void static void
mm_call_qmi_init (MMCallQmi *self) mm_call_qmi_init (MMCallQmi *self)
{ {
/* Initialize private data */
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CALL_QMI, MMCallQmiPrivate);
}
static void
dispose (GObject *object)
{
MMCallQmi *self = MM_CALL_QMI (object);
g_clear_object (&self->priv->modem);
G_OBJECT_CLASS (mm_call_qmi_parent_class)->dispose (object);
} }
static void static void
mm_call_qmi_class_init (MMCallQmiClass *klass) mm_call_qmi_class_init (MMCallQmiClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MMBaseCallClass *base_call_class = MM_BASE_CALL_CLASS (klass); MMBaseCallClass *base_call_class = MM_BASE_CALL_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMCallQmiPrivate));
object_class->dispose = dispose;
base_call_class->start = call_start; base_call_class->start = call_start;
base_call_class->start_finish = call_start_finish; base_call_class->start_finish = call_start_finish;
base_call_class->accept = call_accept; base_call_class->accept = call_accept;
@@ -518,4 +561,6 @@ mm_call_qmi_class_init (MMCallQmiClass *klass)
base_call_class->hangup_finish = call_hangup_finish; base_call_class->hangup_finish = call_hangup_finish;
base_call_class->send_dtmf = call_send_dtmf; base_call_class->send_dtmf = call_send_dtmf;
base_call_class->send_dtmf_finish = call_send_dtmf_finish; base_call_class->send_dtmf_finish = call_send_dtmf_finish;
base_call_class->stop_dtmf = call_stop_dtmf;
base_call_class->stop_dtmf_finish = call_stop_dtmf_finish;
} }
+4 -1
View File
@@ -33,9 +33,11 @@
typedef struct _MMCallQmi MMCallQmi; typedef struct _MMCallQmi MMCallQmi;
typedef struct _MMCallQmiClass MMCallQmiClass; typedef struct _MMCallQmiClass MMCallQmiClass;
typedef struct _MMCallQmiPrivate MMCallQmiPrivate;
struct _MMCallQmi { struct _MMCallQmi {
MMBaseCall parent; MMBaseCall parent;
MMCallQmiPrivate *priv;
}; };
struct _MMCallQmiClass { struct _MMCallQmiClass {
@@ -47,6 +49,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCallQmi, g_object_unref)
MMBaseCall *mm_call_qmi_new (MMBaseModem *modem, MMBaseCall *mm_call_qmi_new (MMBaseModem *modem,
MMCallDirection direction, MMCallDirection direction,
const gchar *number); const gchar *number,
const guint dtmf_tone_duration);
#endif /* MM_CALL_QMI_H */ #endif /* MM_CALL_QMI_H */
+29 -9
View File
@@ -32,14 +32,18 @@
#include "mm-cbm-list.h" #include "mm-cbm-list.h"
#include "mm-base-cbm.h" #include "mm-base-cbm.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-bind.h"
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
static void bind_iface_init (MMBindInterface *iface);
G_DEFINE_TYPE_EXTENDED (MMCbmList, mm_cbm_list, G_TYPE_OBJECT, 0, G_DEFINE_TYPE_EXTENDED (MMCbmList, mm_cbm_list, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_BIND, bind_iface_init))
enum { enum {
PROP_0, PROP_0,
PROP_BIND_TO,
PROP_MODEM, PROP_MODEM,
PROP_LAST PROP_LAST
}; };
@@ -53,6 +57,8 @@ enum {
static guint signals[SIGNAL_LAST]; static guint signals[SIGNAL_LAST];
struct _MMCbmListPrivate { struct _MMCbmListPrivate {
/* The object this CBM list is bound to */
GObject *bind_to;
/* The owner modem */ /* The owner modem */
MMBaseModem *modem; MMBaseModem *modem;
/* List of cbm objects */ /* List of cbm objects */
@@ -173,6 +179,7 @@ cmp_cbm_by_serial_and_id (MMBaseCbm *cbm,
static gboolean static gboolean
take_part (MMCbmList *self, take_part (MMCbmList *self,
GObject *bind_to,
MMCbmPart *part, MMCbmPart *part,
MMCbmState state, MMCbmState state,
GError **error) GError **error)
@@ -196,7 +203,7 @@ take_part (MMCbmList *self,
} }
/* Create new cbm */ /* Create new cbm */
cbm = mm_base_cbm_new_with_part (self->priv->modem, cbm = mm_base_cbm_new_with_part (bind_to,
state, state,
mm_cbm_part_get_num_parts (part), mm_cbm_part_get_num_parts (part),
part, part,
@@ -250,6 +257,7 @@ mm_cbm_list_has_part (MMCbmList *self,
gboolean gboolean
mm_cbm_list_take_part (MMCbmList *self, mm_cbm_list_take_part (MMCbmList *self,
GObject *bind_to,
MMCbmPart *part, MMCbmPart *part,
MMCbmState state, MMCbmState state,
GError **error) GError **error)
@@ -269,7 +277,7 @@ mm_cbm_list_take_part (MMCbmList *self,
return FALSE; return FALSE;
} }
return take_part (self, part, state, error); return take_part (self, bind_to, part, state, error);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -283,11 +291,12 @@ log_object_build_id (MMLogObject *_self)
/*****************************************************************************/ /*****************************************************************************/
MMCbmList * MMCbmList *
mm_cbm_list_new (MMBaseModem *modem) mm_cbm_list_new (MMBaseModem *modem, GObject *bind_to)
{ {
/* Create the object */ /* Create the object */
return g_object_new (MM_TYPE_CBM_LIST, return g_object_new (MM_TYPE_CBM_LIST,
MM_CBM_LIST_MODEM, modem, MM_CBM_LIST_MODEM, modem,
MM_BIND_TO, bind_to,
NULL); NULL);
} }
@@ -300,14 +309,14 @@ set_property (GObject *object,
MMCbmList *self = MM_CBM_LIST (object); MMCbmList *self = MM_CBM_LIST (object);
switch (prop_id) { switch (prop_id) {
case PROP_BIND_TO:
g_clear_object (&self->priv->bind_to);
self->priv->bind_to = g_value_dup_object (value);
mm_bind_to (MM_BIND (self), NULL, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
self->priv->modem = g_value_dup_object (value); self->priv->modem = g_value_dup_object (value);
if (self->priv->modem) {
/* Set owner ID */
mm_log_object_set_owner_id (MM_LOG_OBJECT (self),
mm_log_object_get_id (MM_LOG_OBJECT (self->priv->modem)));
}
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -324,6 +333,9 @@ get_property (GObject *object,
MMCbmList *self = MM_CBM_LIST (object); MMCbmList *self = MM_CBM_LIST (object);
switch (prop_id) { switch (prop_id) {
case PROP_BIND_TO:
g_value_set_object (value, self->priv->bind_to);
break;
case PROP_MODEM: case PROP_MODEM:
g_value_set_object (value, self->priv->modem); g_value_set_object (value, self->priv->modem);
break; break;
@@ -348,6 +360,7 @@ dispose (GObject *object)
MMCbmList *self = MM_CBM_LIST (object); MMCbmList *self = MM_CBM_LIST (object);
g_clear_object (&self->priv->modem); g_clear_object (&self->priv->modem);
g_clear_object (&self->priv->bind_to);
g_list_free_full (self->priv->list, g_object_unref); g_list_free_full (self->priv->list, g_object_unref);
self->priv->list = NULL; self->priv->list = NULL;
@@ -360,6 +373,11 @@ log_object_iface_init (MMLogObjectInterface *iface)
iface->build_id = log_object_build_id; iface->build_id = log_object_build_id;
} }
static void
bind_iface_init (MMBindInterface *iface)
{
}
static void static void
mm_cbm_list_class_init (MMCbmListClass *klass) mm_cbm_list_class_init (MMCbmListClass *klass)
{ {
@@ -381,6 +399,8 @@ mm_cbm_list_class_init (MMCbmListClass *klass)
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]); g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]);
g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO);
/* Signals */ /* Signals */
signals[SIGNAL_ADDED] = signals[SIGNAL_ADDED] =
g_signal_new (MM_CBM_ADDED, g_signal_new (MM_CBM_ADDED,
+3 -1
View File
@@ -57,7 +57,8 @@ struct _MMCbmListClass {
GType mm_cbm_list_get_type (void); GType mm_cbm_list_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCbmList, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCbmList, g_object_unref)
MMCbmList *mm_cbm_list_new (MMBaseModem *modem); MMCbmList *mm_cbm_list_new (MMBaseModem *modem,
GObject *bind_to);
GStrv mm_cbm_list_get_paths (MMCbmList *self); GStrv mm_cbm_list_get_paths (MMCbmList *self);
guint mm_cbm_list_get_count (MMCbmList *self); guint mm_cbm_list_get_count (MMCbmList *self);
@@ -68,6 +69,7 @@ gboolean mm_cbm_list_has_part (MMCbmList *self,
guint8 part_num); guint8 part_num);
gboolean mm_cbm_list_take_part (MMCbmList *self, gboolean mm_cbm_list_take_part (MMCbmList *self,
GObject *bind_to,
MMCbmPart *part, MMCbmPart *part,
MMCbmState state, MMCbmState state,
GError **error); GError **error);
+117 -11
View File
@@ -27,9 +27,17 @@
#include "mm-sms-part-3gpp.h" #include "mm-sms-part-3gpp.h"
#define CBS_DATA_CODING_GROUP_MASK 0b11110000 #define CBS_DATA_CODING_GROUP_MASK 0b11110000
#define CBS_DATA_CODING_LANG_MASK 0b00001111
#define CBS_DATA_CODING_LANG_GSM7 0b00000000 #define CBS_DATA_CODING_LANG_GSM7 0b00000000
#define CBS_DATA_CODING_GSM7 0b00010000 #define CBS_DATA_CODING_GSM7 0b00010000
#define CBS_DATA_CODING_UCS2 0b00010001 #define CBS_DATA_CODING_UCS2 0b00010001
#define CBS_DATA_CODING_OTHER 0b00100000
#define CBS_DATA_CODING_OTHER_CZECH 0b00100000
#define CBS_DATA_CODING_OTHER_HEBREW 0b00100001
#define CBS_DATA_CODING_OTHER_ARABIC 0b00100010
#define CBS_DATA_CODING_OTHER_RUSSIAN 0b00100011
#define CBS_DATA_CODING_OTHER_ICELANDIC 0b00100100
#define CBS_DATA_CODING_UNSPECIFIED 0b00110000
#define CBS_DATA_CODING_GENERAL_NO_CLASS 0b01000000 #define CBS_DATA_CODING_GENERAL_NO_CLASS 0b01000000
#define CBS_DATA_CODING_GENERAL_CLASS 0b01010000 #define CBS_DATA_CODING_GENERAL_CLASS 0b01010000
#define CBS_DATA_CODING_GENERAL_CHARSET_MASK 0b00001100 #define CBS_DATA_CODING_GENERAL_CHARSET_MASK 0b00001100
@@ -46,10 +54,48 @@ struct _MMCbmPart {
guint8 part_num; guint8 part_num;
gchar *text; gchar *text;
gchar *language;
MMSmsEncoding encoding; MMSmsEncoding encoding;
}; };
static gchar *
mm_cbm_part_coding_group_to_language (guint8 group)
{
switch (group & CBS_DATA_CODING_LANG_MASK) {
case 0b0000:
return g_strdup ("de");
case 0b0001:
return g_strdup ("en");
case 0b0010:
return g_strdup ("it");
case 0b0011:
return g_strdup ("fr");
case 0b0100:
return g_strdup ("es");
case 0b0101:
return g_strdup ("nl");
case 0b0110:
return g_strdup ("sv");
case 0b0111:
return g_strdup ("da");
case 0b1000:
return g_strdup ("pt");
case 0b1001:
return g_strdup ("fi");
case 0b1010:
return g_strdup ("no");
case 0b1011:
return g_strdup ("el");
case 0b1110:
return g_strdup ("pl");
case 0b1111:
default:
return NULL;
};
}
MMCbmPart * MMCbmPart *
mm_cbm_part_new_from_pdu (const gchar *hexpdu, mm_cbm_part_new_from_pdu (const gchar *hexpdu,
gpointer log_object, gpointer log_object,
@@ -74,12 +120,13 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
gpointer log_object, gpointer log_object,
GError **error) GError **error)
{ {
MMCbmPart *cbm_part; g_autoptr (MMCbmPart) cbm_part = NULL;
MMCbmGeoScope scope; MMCbmGeoScope scope;
guint offset = 0; guint offset = 0;
guint16 serial, group; guint16 serial, group;
int len; int len;
g_autofree gchar *text = NULL; g_autofree gchar *text = NULL;
gboolean has_lang = FALSE, has_7bit_lang = FALSE;
cbm_part = mm_cbm_part_new (); cbm_part = mm_cbm_part_new ();
@@ -94,7 +141,6 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
check_descr_str, \ check_descr_str, \
pdu_len, \ pdu_len, \
required_size); \ required_size); \
mm_cbm_part_free (cbm_part); \
return NULL; \ return NULL; \
} }
@@ -116,7 +162,6 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
mm_obj_dbg (log_object, " immediate cell cbm scope"); mm_obj_dbg (log_object, " immediate cell cbm scope");
break; break;
default: default:
mm_cbm_part_free (cbm_part);
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
@@ -137,14 +182,40 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
/* Order matches 3GPP TS 23.038 Chapter 5 */ /* Order matches 3GPP TS 23.038 Chapter 5 */
if (group == CBS_DATA_CODING_LANG_GSM7) { if (group == CBS_DATA_CODING_LANG_GSM7) {
cbm_part->encoding = MM_SMS_ENCODING_GSM7; cbm_part->encoding = MM_SMS_ENCODING_GSM7;
cbm_part->language = mm_cbm_part_coding_group_to_language (pdu[offset]);
} else if (pdu[offset] == CBS_DATA_CODING_GSM7) { } else if (pdu[offset] == CBS_DATA_CODING_GSM7) {
PDU_SIZE_CHECK (offset + 4, "cannot skip lang"); has_lang = TRUE;
offset += 3;
cbm_part->encoding = MM_SMS_ENCODING_GSM7; cbm_part->encoding = MM_SMS_ENCODING_GSM7;
} else if (pdu[offset] == CBS_DATA_CODING_UCS2) { } else if (pdu[offset] == CBS_DATA_CODING_UCS2) {
PDU_SIZE_CHECK (offset + 3, "cannot skip lang"); has_7bit_lang = TRUE;
offset += 2;
cbm_part->encoding = MM_SMS_ENCODING_UCS2; cbm_part->encoding = MM_SMS_ENCODING_UCS2;
} else if (group == CBS_DATA_CODING_OTHER) {
switch (group) {
case CBS_DATA_CODING_OTHER_CZECH:
cbm_part->encoding = MM_SMS_ENCODING_GSM7;
cbm_part->language = g_strdup ("cs");
break;
case CBS_DATA_CODING_OTHER_HEBREW:
cbm_part->encoding = MM_SMS_ENCODING_UCS2;
cbm_part->language = g_strdup ("he");
break;
case CBS_DATA_CODING_OTHER_ARABIC:
cbm_part->encoding = MM_SMS_ENCODING_UCS2;
cbm_part->language = g_strdup ("ar");
break;
case CBS_DATA_CODING_OTHER_RUSSIAN:
cbm_part->encoding = MM_SMS_ENCODING_UCS2;
cbm_part->language = g_strdup ("ru");
break;
case CBS_DATA_CODING_OTHER_ICELANDIC:
cbm_part->encoding = MM_SMS_ENCODING_GSM7;
cbm_part->language = g_strdup ("is");
break;
default:
cbm_part->encoding = MM_SMS_ENCODING_GSM7;
}
} else if (group == CBS_DATA_CODING_UNSPECIFIED) {
cbm_part->encoding = MM_SMS_ENCODING_GSM7;
} else if ((group == CBS_DATA_CODING_GENERAL_CLASS) || } else if ((group == CBS_DATA_CODING_GENERAL_CLASS) ||
(group == CBS_DATA_CODING_GENERAL_NO_CLASS) || (group == CBS_DATA_CODING_GENERAL_NO_CLASS) ||
(group == CBS_DATA_CODING_UDH)) { (group == CBS_DATA_CODING_UDH)) {
@@ -154,8 +225,9 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
cbm_part->encoding = MM_SMS_ENCODING_GSM7; cbm_part->encoding = MM_SMS_ENCODING_GSM7;
else if (charset == CBS_DATA_CODING_GENERAL_UCS2) else if (charset == CBS_DATA_CODING_GENERAL_UCS2)
cbm_part->encoding = MM_SMS_ENCODING_UCS2; cbm_part->encoding = MM_SMS_ENCODING_UCS2;
} else { }
mm_cbm_part_free (cbm_part);
if (cbm_part->encoding == MM_SMS_ENCODING_UNKNOWN) {
g_set_error (error, g_set_error (error,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_FAILED, MM_CORE_ERROR_FAILED,
@@ -170,12 +242,45 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
cbm_part->part_num = (pdu[offset] & 0xF0) >> 4; cbm_part->part_num = (pdu[offset] & 0xF0) >> 4;
offset++; offset++;
if (has_lang) {
PDU_SIZE_CHECK (offset + 4, "cannot read lang");
if (pdu[offset+2] != '\r') {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse lang");
return NULL;
}
cbm_part->language = g_strdup_printf ("%c%c", pdu[offset], pdu[offset+1]);
offset += 3;
} else if (has_7bit_lang) {
PDU_SIZE_CHECK (offset + 3, "cannot read 7bit lang");
cbm_part->language = mm_sms_decode_text (&pdu[offset],
2,
MM_SMS_ENCODING_GSM7,
0,
log_object,
NULL);
if (!cbm_part->language) {
g_set_error_literal (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse lang");
return NULL;
}
offset += 2;
}
switch (cbm_part->encoding) { switch (cbm_part->encoding) {
case MM_SMS_ENCODING_GSM7: case MM_SMS_ENCODING_GSM7:
len = ((pdu_len - offset) * 8) / 7; len = ((pdu_len - offset) * 8) / 7;
break; break;
case MM_SMS_ENCODING_UCS2: case MM_SMS_ENCODING_UCS2:
len = pdu_len - offset; len = pdu_len - offset;
/* UCS2 must be even number of bytes but some messages
* eg from 'il' have trailing 00 */
if (len % 2)
len--;
break; break;
case MM_SMS_ENCODING_8BIT: case MM_SMS_ENCODING_8BIT:
case MM_SMS_ENCODING_UNKNOWN: case MM_SMS_ENCODING_UNKNOWN:
@@ -190,12 +295,11 @@ mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
log_object, log_object,
error); error);
if (!text) { if (!text) {
mm_cbm_part_free (cbm_part);
return NULL; return NULL;
} }
cbm_part->text = g_steal_pointer (&text); cbm_part->text = g_steal_pointer (&text);
return cbm_part; return g_steal_pointer (&cbm_part);
} }
MMCbmPart * MMCbmPart *
@@ -207,6 +311,7 @@ mm_cbm_part_new (void)
void void
mm_cbm_part_free (MMCbmPart *part) mm_cbm_part_free (MMCbmPart *part)
{ {
g_clear_pointer (&part->language, g_free);
g_clear_pointer (&part->text, g_free); g_clear_pointer (&part->text, g_free);
g_slice_free (MMCbmPart, part); g_slice_free (MMCbmPart, part);
} }
@@ -223,3 +328,4 @@ PART_GET_FUNC (guint, num_parts)
PART_GET_FUNC (const char *, text) PART_GET_FUNC (const char *, text)
PART_GET_FUNC (guint16, channel) PART_GET_FUNC (guint16, channel)
PART_GET_FUNC (guint16, serial) PART_GET_FUNC (guint16, serial)
PART_GET_FUNC (const char *, language)
+3
View File
@@ -59,11 +59,14 @@ MMCbmPart *mm_cbm_part_new_from_binary_pdu (const guint8 *pdu,
MMCbmPart *mm_cbm_part_new (void); MMCbmPart *mm_cbm_part_new (void);
void mm_cbm_part_free (MMCbmPart *part); void mm_cbm_part_free (MMCbmPart *part);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCbmPart, mm_cbm_part_free)
guint mm_cbm_part_get_part_num (MMCbmPart *part); guint mm_cbm_part_get_part_num (MMCbmPart *part);
guint mm_cbm_part_get_num_parts (MMCbmPart *part); guint mm_cbm_part_get_num_parts (MMCbmPart *part);
const char *mm_cbm_part_get_text (MMCbmPart *part); const char *mm_cbm_part_get_text (MMCbmPart *part);
guint16 mm_cbm_part_get_serial (MMCbmPart *part); guint16 mm_cbm_part_get_serial (MMCbmPart *part);
guint16 mm_cbm_part_get_channel (MMCbmPart *part); guint16 mm_cbm_part_get_channel (MMCbmPart *part);
const char *mm_cbm_part_get_language (MMCbmPart *part);
#endif #endif
+6 -5
View File
@@ -27,6 +27,7 @@
#include "mm-plugin.h" #include "mm-plugin.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-daemon-enums-types.h" #include "mm-daemon-enums-types.h"
#include "mm-bind.h"
static void log_object_iface_init (MMLogObjectInterface *iface); static void log_object_iface_init (MMLogObjectInterface *iface);
@@ -341,7 +342,7 @@ unexport_modem (MMDevice *self)
if (path != NULL) { if (path != NULL) {
g_dbus_object_manager_server_unexport (self->priv->object_manager, path); g_dbus_object_manager_server_unexport (self->priv->object_manager, path);
g_object_set (self->priv->modem, g_object_set (self->priv->modem,
MM_BASE_MODEM_CONNECTION, NULL, MM_BINDABLE_CONNECTION, NULL,
NULL); NULL);
mm_obj_dbg (self, "unexported modem from path '%s'", path); mm_obj_dbg (self, "unexported modem from path '%s'", path);
g_free (path); g_free (path);
@@ -389,7 +390,7 @@ export_modem (MMDevice *self)
path = g_strdup_printf (MM_DBUS_MODEM_PREFIX "/%d", mm_base_modem_get_dbus_id (self->priv->modem)); path = g_strdup_printf (MM_DBUS_MODEM_PREFIX "/%d", mm_base_modem_get_dbus_id (self->priv->modem));
g_object_set (self->priv->modem, g_object_set (self->priv->modem,
"g-object-path", path, "g-object-path", path,
MM_BASE_MODEM_CONNECTION, connection, MM_BINDABLE_CONNECTION, connection,
NULL); NULL);
g_dbus_object_manager_server_export (self->priv->object_manager, g_dbus_object_manager_server_export (self->priv->object_manager,
@@ -436,7 +437,7 @@ mm_device_initialize_modem (MMDevice *self)
mm_obj_dbg (self, "modem initializing..."); mm_obj_dbg (self, "modem initializing...");
mm_base_modem_initialize (modem, mm_base_modem_initialize (modem,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MM_OPERATION_LOCK_REQUIRED,
(GAsyncReadyCallback)initialize_ready, (GAsyncReadyCallback)initialize_ready,
g_object_ref (self)); g_object_ref (self));
} }
@@ -868,8 +869,8 @@ mm_device_inhibit (MMDevice *self,
* an exclusive lock marked as override, so the modem object will not * an exclusive lock marked as override, so the modem object will not
* allow any additional lock request any more. */ * allow any additional lock request any more. */
mm_base_modem_disable (self->priv->modem, mm_base_modem_disable (self->priv->modem,
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, MM_OPERATION_LOCK_REQUIRED,
MM_BASE_MODEM_OPERATION_PRIORITY_OVERRIDE, MM_OPERATION_PRIORITY_OVERRIDE,
(GAsyncReadyCallback)inhibit_disable_ready, (GAsyncReadyCallback)inhibit_disable_ready,
task); task);
} }
+25 -12
View File
@@ -31,8 +31,6 @@
#endif #endif
#define OPERATION_DESCRIPTION "connection status report" #define OPERATION_DESCRIPTION "connection status report"
#define CONNECTED_STRING "connected"
#define DISCONNECTED_STRING "disconnected"
/* Maximum time a connection dispatcher command is allowed to run before /* Maximum time a connection dispatcher command is allowed to run before
* us killing it */ * us killing it */
@@ -51,15 +49,30 @@ G_DEFINE_TYPE (MMDispatcherConnection, mm_dispatcher_connection, MM_TYPE_DISPATC
/*****************************************************************************/ /*****************************************************************************/
typedef struct { typedef struct {
gchar *modem_dbus_path; gchar *modem_dbus_path;
gchar *bearer_dbus_path; gchar *bearer_dbus_path;
gchar *data_port; gchar *data_port;
gboolean connected; MMDispatcherConnectionEvent event;
GList *dispatcher_scripts; GList *dispatcher_scripts;
GFile *current; GFile *current;
guint n_failures; guint n_failures;
} ConnectionRunContext; } ConnectionRunContext;
static gchar *
mm_dispatcher_connection_event_to_string (MMDispatcherConnectionEvent event)
{
switch (event) {
case MM_DISPATCHER_CONNECTION_EVENT_CONNECTED:
return g_strdup ("connected");
case MM_DISPATCHER_CONNECTION_EVENT_DISCONNECTED:
return g_strdup ("disconnected");
case MM_DISPATCHER_CONNECTION_EVENT_DISCONNECT_REQUEST:
return g_strdup ("disconnect-request");
default:
return NULL;
}
}
static void static void
connection_run_context_free (ConnectionRunContext *ctx) connection_run_context_free (ConnectionRunContext *ctx)
{ {
@@ -137,7 +150,7 @@ connection_run_next (GTask *task)
g_ptr_array_add (aux, g_strdup (ctx->modem_dbus_path)); g_ptr_array_add (aux, g_strdup (ctx->modem_dbus_path));
g_ptr_array_add (aux, g_strdup (ctx->bearer_dbus_path)); g_ptr_array_add (aux, g_strdup (ctx->bearer_dbus_path));
g_ptr_array_add (aux, g_strdup (ctx->data_port)); g_ptr_array_add (aux, g_strdup (ctx->data_port));
g_ptr_array_add (aux, g_strdup (ctx->connected ? CONNECTED_STRING : DISCONNECTED_STRING)); g_ptr_array_add (aux, mm_dispatcher_connection_event_to_string (ctx->event));
g_ptr_array_add (aux, NULL); g_ptr_array_add (aux, NULL);
argv = (GStrv) g_ptr_array_free (aux, FALSE); argv = (GStrv) g_ptr_array_free (aux, FALSE);
@@ -168,7 +181,7 @@ mm_dispatcher_connection_run (MMDispatcherConnection *self,
const gchar *modem_dbus_path, const gchar *modem_dbus_path,
const gchar *bearer_dbus_path, const gchar *bearer_dbus_path,
const gchar *data_port, const gchar *data_port,
gboolean connected, MMDispatcherConnectionEvent event,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
@@ -187,7 +200,7 @@ mm_dispatcher_connection_run (MMDispatcherConnection *self,
ctx->modem_dbus_path = g_strdup (modem_dbus_path); ctx->modem_dbus_path = g_strdup (modem_dbus_path);
ctx->bearer_dbus_path = g_strdup (bearer_dbus_path); ctx->bearer_dbus_path = g_strdup (bearer_dbus_path);
ctx->data_port = g_strdup (data_port); ctx->data_port = g_strdup (data_port);
ctx->connected = connected; ctx->event = event;
g_task_set_task_data (task, ctx, (GDestroyNotify)connection_run_context_free); g_task_set_task_data (task, ctx, (GDestroyNotify)connection_run_context_free);
/* Iterate over all enabled dirs and collect all dispatcher script paths */ /* Iterate over all enabled dirs and collect all dispatcher script paths */
+7 -1
View File
@@ -32,13 +32,19 @@ typedef struct _MMDispatcherConnection MMDispatcherConnection;
typedef struct _MMDispatcherConnectionClass MMDispatcherConnectionClass; typedef struct _MMDispatcherConnectionClass MMDispatcherConnectionClass;
typedef struct _MMDispatcherConnectionPrivate MMDispatcherConnectionPrivate; typedef struct _MMDispatcherConnectionPrivate MMDispatcherConnectionPrivate;
typedef enum { /*< underscore_name=mm_dispatcher_connection_event >*/
MM_DISPATCHER_CONNECTION_EVENT_CONNECTED,
MM_DISPATCHER_CONNECTION_EVENT_DISCONNECTED,
MM_DISPATCHER_CONNECTION_EVENT_DISCONNECT_REQUEST,
} MMDispatcherConnectionEvent;
GType mm_dispatcher_connection_get_type (void); GType mm_dispatcher_connection_get_type (void);
MMDispatcherConnection *mm_dispatcher_connection_get (void); MMDispatcherConnection *mm_dispatcher_connection_get (void);
void mm_dispatcher_connection_run (MMDispatcherConnection *self, void mm_dispatcher_connection_run (MMDispatcherConnection *self,
const gchar *modem_dbus_path, const gchar *modem_dbus_path,
const gchar *bearer_dbus_path, const gchar *bearer_dbus_path,
const gchar *data_port, const gchar *data_port,
gboolean connected, MMDispatcherConnectionEvent event,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);

Some files were not shown because too many files have changed in this diff Show More