New upstream version 0.3.0

This commit is contained in:
Arnaud Ferraris
2021-05-28 13:58:11 +02:00
20 changed files with 639 additions and 47 deletions

View File

@@ -3,6 +3,9 @@ need_libusb = true
usb_vid = 0x2c7c usb_vid = 0x2c7c
usb_pid = 0x0125 usb_pid = 0x0125
# Delay between setting GPIO and PWRKEY sequence, set in microseconds
poweron_delay = 100000
# Uncomment the following if you need to change the modem detection timeout on # Uncomment the following if you need to change the modem detection timeout on
# resume and/or the time during which suspend is blocked after modem boot # resume and/or the time during which suspend is blocked after modem boot
#[suspend] #[suspend]
@@ -39,17 +42,14 @@ configure = [
{ cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" }, { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
{ cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" }, { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" }, { cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" }, { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" }, { cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" }, { cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
] ]
suspend = [ suspend = [
{ cmd = "QGPSEND" }, { cmd = "QGPSEND" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "1" }
] ]
resume = [ resume = [
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" },
{ cmd = "QGPS", value = "1" } { cmd = "QGPS", value = "1" }
] ]
reset = [ { cmd = "CFUN", value = "1,1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ]

View File

@@ -3,6 +3,9 @@ need_libusb = true
usb_vid = 0x2c7c usb_vid = 0x2c7c
usb_pid = 0x0125 usb_pid = 0x0125
# Delay between setting GPIO and PWRKEY sequence, set in microseconds
poweron_delay = 100000
# Uncomment the following if you need to change the modem detection timeout on # Uncomment the following if you need to change the modem detection timeout on
# resume and/or the time during which suspend is blocked after modem boot # resume and/or the time during which suspend is blocked after modem boot
#[suspend] #[suspend]
@@ -39,17 +42,14 @@ configure = [
{ cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" }, { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
{ cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" }, { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" }, { cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" }, { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" }, { cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" }, { cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
] ]
suspend = [ suspend = [
{ cmd = "QGPSEND" }, { cmd = "QGPSEND" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "1" }
] ]
resume = [ resume = [
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" },
{ cmd = "QGPS", value = "1" } { cmd = "QGPS", value = "1" }
] ]
reset = [ { cmd = "CFUN", value = "1,1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ]

View File

@@ -1,3 +1,7 @@
[manager]
# Delay between setting GPIO and PWRKEY sequence, set in microseconds
poweron_delay = 100000
# Uncomment the following if you need to change the modem detection timeout on # Uncomment the following if you need to change the modem detection timeout on
# resume and/or the time during which suspend is blocked after modem boot # resume and/or the time during which suspend is blocked after modem boot
#[suspend] #[suspend]
@@ -32,17 +36,14 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" }, { cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" }, { cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "apready", expect = "1,0,500" }, { cmd = "QCFG", subcmd = "apready", expect = "1,0,500" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" }, { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" }, { cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" }, { cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
] ]
suspend = [ suspend = [
{ cmd = "QGPSEND" }, { cmd = "QGPSEND" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "1" }
] ]
resume = [ resume = [
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" },
{ cmd = "QGPS", value = "1" } { cmd = "QGPS", value = "1" }
] ]
reset = [ { cmd = "CFUN", value = "1,1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ]

View File

@@ -8,7 +8,7 @@
project ( project (
'eg25-manager', 'eg25-manager',
'c', 'c',
version : '0.2.0', version : '0.3.0',
license : 'GPLv3+', license : 'GPLv3+',
meson_version : '>= 0.50.0', meson_version : '>= 0.50.0',
default_options : default_options :
@@ -47,13 +47,18 @@ eg25_datadir = join_paths(full_datadir, meson.project_name())
add_global_arguments('-D@0@="@1@"'.format('EG25_CONFDIR', eg25_confdir), language : 'c') add_global_arguments('-D@0@="@1@"'.format('EG25_CONFDIR', eg25_confdir), language : 'c')
add_global_arguments('-D@0@="@1@"'.format('EG25_DATADIR', eg25_datadir), language : 'c') add_global_arguments('-D@0@="@1@"'.format('EG25_DATADIR', eg25_datadir), language : 'c')
mmglib_dep = dependency('mm-glib', required : false)
if mmglib_dep.found()
add_global_arguments('-DHAVE_MMGLIB=1', language : 'c')
endif
mgr_deps = [ mgr_deps = [
dependency('glib-2.0'), dependency('glib-2.0'),
dependency('gio-unix-2.0'), dependency('gio-unix-2.0'),
dependency('gudev-1.0'), dependency('gudev-1.0'),
dependency('libgpiod'), dependency('libgpiod'),
dependency('libusb-1.0'), dependency('libusb-1.0'),
dependency('mm-glib'), mmglib_dep,
] ]
subdir('data') subdir('data')

View File

@@ -76,12 +76,18 @@ static gboolean send_at_command(struct EG25Manager *manager)
g_message("Sending command: %s", g_strstrip(command)); g_message("Sending command: %s", g_strstrip(command));
} else if (manager->modem_state < EG25_STATE_CONFIGURED) { } else if (manager->modem_state < EG25_STATE_CONFIGURED) {
MMModemState modem_state = mm_modem_get_state(manager->mm_modem); if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
#ifdef HAVE_MMGLIB
MMModemState modem_state = mm_modem_get_state(manager->mm_modem);
if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED) if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED)
modem_update_state(manager, modem_state); modem_update_state(manager, modem_state);
else else
manager->modem_state = EG25_STATE_CONFIGURED;
#endif
} else {
manager->modem_state = EG25_STATE_CONFIGURED; manager->modem_state = EG25_STATE_CONFIGURED;
}
} else if (manager->modem_state == EG25_STATE_SUSPENDING) { } else if (manager->modem_state == EG25_STATE_SUSPENDING) {
modem_suspend_post(manager); modem_suspend_post(manager);
} else if (manager->modem_state == EG25_STATE_RESETTING) { } else if (manager->modem_state == EG25_STATE_RESETTING) {

View File

@@ -0,0 +1,11 @@
#!/bin/bash
DEST="$1"
OBJ_PATH="$2"
METHOD="$3"
shift 3
dbus-send "$@" --print-reply --dest="$DEST" "$OBJ_PATH" "$METHOD" | \
grep -v '^method return' | \
sed -e 's/^[[:space:]]\+string "</</' \
-e 's_</node>"_</node>_'

View File

@@ -0,0 +1,13 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.ofono.Manager"><method name="GetModems"><arg name="modems" type="a(oa{sv})" direction="out"/>
</method><signal name="ModemAdded"><arg name="path" type="o"/>
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="ModemRemoved"><arg name="path" type="o"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,50 @@
#
# Copyright (C) 2018 Purism SPC
#
# This file is part of Calls.
#
# Calls 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 3 of the License, or
# (at your option) any later version.
#
# Calls 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.
#
# You should have received a copy of the GNU General Public License
# along with Calls. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Bob Ham <bob.ham@puri.sm>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
gnome = import('gnome')
dbus_interfaces = ['manager', 'modem']
gdbofono_src = []
gdbofono_headers = []
foreach iface: dbus_interfaces
src = gnome.gdbus_codegen(
'gdbo-' + iface,
iface + '.xml',
interface_prefix: 'org.ofono.',
namespace: 'GDBO'
)
gdbofono_src += src
gdbofono_headers += src[1]
endforeach
gdbofono_deps = [
dependency('gio-2.0'),
dependency('gio-unix-2.0'),
]
gdbofono_lib = static_library(
'gdbofono',
gdbofono_src,
dependencies: gdbofono_deps
)

View File

@@ -0,0 +1,249 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.ofono.Modem"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.SimManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="ChangePin"><arg name="type" type="s" direction="in"/>
<arg name="oldpin" type="s" direction="in"/>
<arg name="newpin" type="s" direction="in"/>
</method><method name="EnterPin"><arg name="type" type="s" direction="in"/>
<arg name="pin" type="s" direction="in"/>
</method><method name="ResetPin"><arg name="type" type="s" direction="in"/>
<arg name="puk" type="s" direction="in"/>
<arg name="newpin" type="s" direction="in"/>
</method><method name="LockPin"><arg name="type" type="s" direction="in"/>
<arg name="pin" type="s" direction="in"/>
</method><method name="UnlockPin"><arg name="type" type="s" direction="in"/>
<arg name="pin" type="s" direction="in"/>
</method><method name="GetIcon"><arg name="id" type="y" direction="in"/>
<arg name="icon" type="ay" direction="out"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.VoiceCallManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="Dial"><arg name="number" type="s" direction="in"/>
<arg name="hide_callerid" type="s" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method><method name="DialLast"></method><method name="DialMemory"><arg name="memory_location" type="u" direction="in"/>
</method><method name="Transfer"></method><method name="SwapCalls"></method><method name="ReleaseAndAnswer"></method><method name="ReleaseAndSwap"></method><method name="HoldAndAnswer"></method><method name="HangupAll"></method><method name="PrivateChat"><arg name="call" type="o" direction="in"/>
<arg name="calls" type="ao" direction="out"/>
</method><method name="CreateMultiparty"><arg name="calls" type="ao" direction="out"/>
</method><method name="HangupMultiparty"></method><method name="SendTones"><arg name="SendTones" type="s" direction="in"/>
</method><method name="GetCalls"><arg name="calls_with_properties" type="a(oa{sv})" direction="out"/>
</method><signal name="Forwarded"><arg name="type" type="s"/>
</signal>
<signal name="BarringActive"><arg name="type" type="s"/>
</signal>
<signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="CallAdded"><arg name="path" type="o"/>
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="CallRemoved"><arg name="path" type="o"/>
</signal>
</interface>
<interface name="org.ofono.AllowedAccessPoints"><method name="GetAllowedAccessPoints"><arg name="apnlist" type="as" direction="out"/>
</method></interface>
<interface name="org.ofono.SimAuthentication"><method name="GetApplications"><arg name="applications" type="a{oa{sv}}" direction="out"/>
</method><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method></interface>
<interface name="org.ofono.SimToolkit"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SelectItem"><arg name="item" type="y" direction="in"/>
<arg name="agent" type="o" direction="in"/>
</method><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.CallForwarding"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="DisableAll"><arg name="type" type="s" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.RadioSettings"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.TextTelephony"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.Phonebook"><method name="Import"><arg name="entries" type="s" direction="out"/>
</method></interface>
<interface name="org.ofono.MessageManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="SendMessage"><arg name="to" type="s" direction="in"/>
<arg name="text" type="s" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method><method name="GetMessages"><arg name="messages" type="a(oa{sv})" direction="out"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="IncomingMessage"><arg name="message" type="s"/>
<arg name="info" type="a{sv}"/>
</signal>
<signal name="ImmediateMessage"><arg name="message" type="s"/>
<arg name="info" type="a{sv}"/>
</signal>
<signal name="MessageAdded"><arg name="path" type="o"/>
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="MessageRemoved"><arg name="path" type="o"/>
</signal>
</interface>
<interface name="org.ofono.PushNotification"><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
</method></interface>
<interface name="org.ofono.SmartMessaging"><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
</method><method name="SendBusinessCard"><arg name="to" type="s" direction="in"/>
<arg name="card" type="ay" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method><method name="SendAppointment"><arg name="to" type="s" direction="in"/>
<arg name="appointment" type="ay" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method></interface>
<interface name="org.ofono.MessageWaiting"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.CallSettings"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="property" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.CallBarring"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
<arg name="pin2" type="s" direction="in"/>
</method><method name="DisableAll"><arg name="password" type="s" direction="in"/>
</method><method name="DisableAllIncoming"><arg name="password" type="s" direction="in"/>
</method><method name="DisableAllOutgoing"><arg name="password" type="s" direction="in"/>
</method><method name="ChangePassword"><arg name="old" type="s" direction="in"/>
<arg name="new" type="s" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.SupplementaryServices"><method name="Initiate"><arg name="command" type="s" direction="in"/>
<arg name="result_name" type="s" direction="out"/>
<arg name="value" type="v" direction="out"/>
</method><method name="Respond"><arg name="reply" type="s" direction="in"/>
<arg name="result" type="s" direction="out"/>
</method><method name="Cancel"></method><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><signal name="NotificationReceived"><arg name="message" type="s"/>
</signal>
<signal name="RequestReceived"><arg name="message" type="s"/>
</signal>
<signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.CallMeter"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
<arg name="password" type="s" direction="in"/>
</method><method name="Reset"><arg name="passoword" type="s" direction="in"/>
</method><signal name="PropertyChanged"><arg name="property" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="NearMaximumWarning"></signal>
</interface>
<interface name="org.ofono.CallVolume"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="property" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.NetworkRegistration"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="Register"></method><method name="GetOperators"><arg name="operators_with_properties" type="a(oa{sv})" direction="out"/>
</method><method name="Scan"><arg name="operators_with_properties" type="a(oa{sv})" direction="out"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.CellBroadcast"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="property" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="IncomingBroadcast"><arg name="message" type="s"/>
<arg name="channel" type="q"/>
</signal>
<signal name="EmergencyBroadcast"><arg name="message" type="s"/>
<arg name="dict" type="a{sv}"/>
</signal>
</interface>
<interface name="org.ofono.AssistedSatelliteNavigation"><method name="SendPositioningElement"><arg name="xml_elements" type="(null)" direction="in"/>
</method><method name="RegisterPositioningRequestAgent"><arg name="agent" type="o" direction="in"/>
</method><method name="UnregisterPositioningRequestAgent"><arg name="agent" type="o" direction="in"/>
</method></interface>
<interface name="org.ofono.ConnectionManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><method name="AddContext"><arg name="type" type="s" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method><method name="RemoveContext"><arg name="path" type="o" direction="in"/>
</method><method name="DeactivateAll"></method><method name="GetContexts"><arg name="contexts_with_properties" type="a(oa{sv})" direction="out"/>
</method><method name="ResetContexts"></method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="ContextAdded"><arg name="path" type="o"/>
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="ContextRemoved"><arg name="path" type="o"/>
</signal>
</interface>
</node>

37
src/libgdbofono/modem.xml Normal file
View File

@@ -0,0 +1,37 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.ofono.Modem"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
<arg name="value" type="v" direction="in"/>
</method><signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
</interface>
<interface name="org.ofono.VoiceCallManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
</method><method name="Dial"><arg name="number" type="s" direction="in"/>
<arg name="hide_callerid" type="s" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method><method name="DialLast"></method><method name="DialMemory"><arg name="memory_location" type="u" direction="in"/>
</method><method name="Transfer"></method><method name="SwapCalls"></method><method name="ReleaseAndAnswer"></method><method name="ReleaseAndSwap"></method><method name="HoldAndAnswer"></method><method name="HangupAll"></method><method name="PrivateChat"><arg name="call" type="o" direction="in"/>
<arg name="calls" type="ao" direction="out"/>
</method><method name="CreateMultiparty"><arg name="calls" type="ao" direction="out"/>
</method><method name="HangupMultiparty"></method><method name="SendTones"><arg name="SendTones" type="s" direction="in"/>
</method><method name="GetCalls"><arg name="calls_with_properties" type="a(oa{sv})" direction="out"/>
</method><signal name="Forwarded"><arg name="type" type="s"/>
</signal>
<signal name="BarringActive"><arg name="type" type="s"/>
</signal>
<signal name="PropertyChanged"><arg name="name" type="s"/>
<arg name="value" type="v"/>
</signal>
<signal name="CallAdded"><arg name="path" type="o"/>
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="CallRemoved"><arg name="path" type="o"/>
</signal>
</interface>
</node>

View File

@@ -7,7 +7,12 @@
#include "at.h" #include "at.h"
#include "gpio.h" #include "gpio.h"
#include "manager.h" #include "manager.h"
#ifdef HAVE_MMGLIB
#include "mm-iface.h" #include "mm-iface.h"
#endif
#include "ofono-iface.h"
#include "suspend.h" #include "suspend.h"
#include "udev.h" #include "udev.h"
@@ -34,7 +39,10 @@ static gboolean quit_app(struct EG25Manager *manager)
g_message("Request to quit..."); g_message("Request to quit...");
at_destroy(manager); at_destroy(manager);
#ifdef HAVE_MMGLIB
mm_iface_destroy(manager); mm_iface_destroy(manager);
#endif
ofono_iface_destroy(manager);
suspend_destroy(manager); suspend_destroy(manager);
udev_destroy(manager); udev_destroy(manager);
@@ -86,6 +94,9 @@ static gboolean modem_start(struct EG25Manager *manager)
if (should_boot) { if (should_boot) {
g_message("Starting modem..."); g_message("Starting modem...");
// Modem might crash on boot (especially with worn battery) if we don't delay here
if (manager->poweron_delay > 0)
g_usleep(manager->poweron_delay);
gpio_sequence_poweron(manager); gpio_sequence_poweron(manager);
manager->modem_state = EG25_STATE_POWERED; manager->modem_state = EG25_STATE_POWERED;
} else { } else {
@@ -95,6 +106,7 @@ static gboolean modem_start(struct EG25Manager *manager)
return FALSE; return FALSE;
} }
#ifdef HAVE_MMGLIB
void modem_update_state(struct EG25Manager *manager, MMModemState state) void modem_update_state(struct EG25Manager *manager, MMModemState state)
{ {
switch (state) { switch (state) {
@@ -111,6 +123,7 @@ void modem_update_state(struct EG25Manager *manager, MMModemState state)
break; break;
} }
} }
#endif
void modem_configure(struct EG25Manager *manager) void modem_configure(struct EG25Manager *manager)
{ {
@@ -131,6 +144,14 @@ void modem_reset(struct EG25Manager *manager)
if (manager->reset_timer) if (manager->reset_timer)
return; return;
/*
* If we are managing the modem through lets say ofono, we should not
* reset the modem based on the availability of USB ID
* TODO: Improve ofono plugin and add support for fetching USB ID
*/
if (manager->modem_iface != MODEM_IFACE_MODEMMANAGER)
return;
if (manager->modem_recovery_timer) { if (manager->modem_recovery_timer) {
g_source_remove(manager->modem_recovery_timer); g_source_remove(manager->modem_recovery_timer);
manager->modem_recovery_timer = 0; manager->modem_recovery_timer = 0;
@@ -300,11 +321,25 @@ int main(int argc, char *argv[])
toml_value = toml_int_in(toml_manager, "usb_pid"); toml_value = toml_int_in(toml_manager, "usb_pid");
if (toml_value.ok) if (toml_value.ok)
manager.usb_pid = toml_value.u.i; manager.usb_pid = toml_value.u.i;
toml_value = toml_int_in(toml_manager, "poweron_delay");
if (toml_value.ok) {
if (toml_value.u.i >= 0 && toml_value.u.i <= G_MAXULONG) {
// Safe to cast into gulong
manager.poweron_delay = (gulong) toml_value.u.i;
} else {
// Changed from initialized default value but not in range
g_message("Configured poweron_delay out of range, using default");
}
}
} }
at_init(&manager, toml_table_in(toml_config, "at")); at_init(&manager, toml_table_in(toml_config, "at"));
gpio_init(&manager, toml_table_in(toml_config, "gpio")); gpio_init(&manager, toml_table_in(toml_config, "gpio"));
#ifdef HAVE_MMGLIB
mm_iface_init(&manager, toml_table_in(toml_config, "mm-iface")); mm_iface_init(&manager, toml_table_in(toml_config, "mm-iface"));
#endif
ofono_iface_init(&manager);
suspend_init(&manager, toml_table_in(toml_config, "suspend")); suspend_init(&manager, toml_table_in(toml_config, "suspend"));
udev_init(&manager, toml_table_in(toml_config, "udev")); udev_init(&manager, toml_table_in(toml_config, "udev"));

View File

@@ -9,7 +9,10 @@
#include <glib.h> #include <glib.h>
#include <gpiod.h> #include <gpiod.h>
#include <gudev/gudev.h> #include <gudev/gudev.h>
#ifdef HAVE_MMGLIB
#include <libmm-glib.h> #include <libmm-glib.h>
#endif
#include <libgdbofono/gdbo-manager.h>
#include "toml.h" #include "toml.h"
@@ -27,12 +30,19 @@ enum EG25State {
EG25_STATE_FINISHING EG25_STATE_FINISHING
}; };
enum ModemIface {
MODEM_IFACE_NONE = 0,
MODEM_IFACE_MODEMMANAGER,
MODEM_IFACE_OFONO
};
struct EG25Manager { struct EG25Manager {
GMainLoop *loop; GMainLoop *loop;
guint reset_timer; guint reset_timer;
gboolean use_libusb; gboolean use_libusb;
guint usb_vid; guint usb_vid;
guint usb_pid; guint usb_pid;
gulong poweron_delay;
int at_fd; int at_fd;
guint at_source; guint at_source;
@@ -41,9 +51,15 @@ struct EG25Manager {
enum EG25State modem_state; enum EG25State modem_state;
gchar *modem_usb_id; gchar *modem_usb_id;
enum ModemIface modem_iface;
guint mm_watch; guint mm_watch;
#ifdef HAVE_MMGLIB
MMManager *mm_manager; MMManager *mm_manager;
MMModem *mm_modem; MMModem *mm_modem;
#endif
guint ofono_watch;
GDBOManager *ofono_manager;
GDBusConnection *ofono_connection;
GDBusProxy *suspend_proxy; GDBusProxy *suspend_proxy;
int suspend_delay_fd; int suspend_delay_fd;
@@ -67,4 +83,6 @@ void modem_suspend_pre(struct EG25Manager *data);
void modem_suspend_post(struct EG25Manager *data); void modem_suspend_post(struct EG25Manager *data);
void modem_resume_pre(struct EG25Manager *data); void modem_resume_pre(struct EG25Manager *data);
void modem_resume_post(struct EG25Manager *data); void modem_resume_post(struct EG25Manager *data);
#ifdef HAVE_MMGLIB
void modem_update_state(struct EG25Manager *data, MMModemState state); void modem_update_state(struct EG25Manager *data, MMModemState state);
#endif

View File

@@ -4,17 +4,27 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
executable (
'eg25manager', subdir('libgdbofono')
[
src = [
'at.c', 'at.h', 'at.c', 'at.h',
'gpio.c', 'gpio.h', 'gpio.c', 'gpio.h',
'manager.c', 'manager.h', 'manager.c', 'manager.h',
'mm-iface.c', 'mm-iface.h', 'ofono-iface.c', 'ofono-iface.h',
'suspend.c', 'suspend.h', 'suspend.c', 'suspend.h',
'toml.c', 'toml.h', 'toml.c', 'toml.h',
'udev.c', 'udev.h', 'udev.c', 'udev.h',
], ]
if mmglib_dep.found()
src += ['mm-iface.c', 'mm-iface.h']
endif
executable (
'eg25manager',
src,
dependencies : mgr_deps, dependencies : mgr_deps,
link_with: gdbofono_lib,
install : true install : true
) )

View File

@@ -163,6 +163,12 @@ static void mm_appeared_cb(GDBusConnection *connection,
{ {
g_message("ModemManager appeared on D-Bus"); g_message("ModemManager appeared on D-Bus");
if (manager->modem_iface != MODEM_IFACE_NONE) {
g_critical("Modem interface already found! Make sure to only run either of ModemManager or oFono.");
return;
}
manager->modem_iface = MODEM_IFACE_MODEMMANAGER;
mm_manager_new(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, mm_manager_new(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
NULL, (GAsyncReadyCallback)mm_manager_new_cb, manager); NULL, (GAsyncReadyCallback)mm_manager_new_cb, manager);
} }

150
src/ofono-iface.c Normal file
View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2020 Oliver Smith <ollieparanoid@postmarketos.org>
* Copyright (C) 2021 Bhushan Shah <bshah@kde.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "ofono-iface.h"
#include <string.h>
#include <libgdbofono/gdbo-manager.h>
#include <libgdbofono/gdbo-modem.h>
#define OFONO_SERVICE "org.ofono"
static void modem_added_cb(GDBOManager *manager_proxy,
const gchar *path,
GVariant *properties,
struct EG25Manager *manager)
{
GVariant *modem_path;
g_debug("Adding ofono modem '%s'", path);
if (manager->modem_state == EG25_STATE_RESUMING) {
if (manager->modem_recovery_timer) {
g_source_remove(manager->modem_recovery_timer);
manager->modem_recovery_timer = 0;
}
modem_resume_post(manager);
manager->modem_state = EG25_STATE_CONFIGURED;
}
if (manager->modem_state < EG25_STATE_ACQUIRED)
manager->modem_state = EG25_STATE_ACQUIRED;
if (manager->modem_state < EG25_STATE_CONFIGURED)
modem_configure(manager);
modem_path = g_variant_lookup_value(properties, "SystemPath", G_VARIANT_TYPE_STRING);
if (manager->modem_usb_id)
g_free(manager->modem_usb_id);
manager->modem_usb_id = g_strdup(strrchr(g_variant_dup_string(modem_path, NULL), '/') + 1);
}
static void modem_removed_cb(GDBOManager *manager_proxy,
const gchar *path,
struct EG25Manager *manager)
{
}
static void get_modems_cb(GDBOManager *manager_proxy,
GAsyncResult *res,
struct EG25Manager *manager)
{
gboolean ok;
GVariant *modems;
GVariantIter *modems_iter = NULL;
g_autoptr(GError) error = NULL;
const gchar *path;
GVariant *properties;
ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems,
res, &error);
if (!ok) {
g_warning("Error getting modems from ofono manager: %s", error->message);
return;
}
g_variant_get(modems, "a(oa{sv})", &modems_iter);
while(g_variant_iter_loop(modems_iter, "(&o@a{sv})", &path, &properties)) {
g_debug("Got modem object path '%s'", path);
modem_added_cb(manager_proxy, path, properties, manager);
}
g_variant_iter_free(modems_iter);
g_variant_unref(modems);
}
static void ofono_appeared_cb(GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
struct EG25Manager *manager)
{
GError *error = NULL;
g_message("oFono appeared on D-Bus");
if (manager->modem_iface != MODEM_IFACE_NONE) {
g_critical("Modem interface already found! Make sure to only run either of ModemManager or oFono.");
return;
}
/* now connect to oFono! */
manager->ofono_connection = connection;
manager->ofono_manager = gdbo_manager_proxy_new_sync(connection,
G_DBUS_PROXY_FLAGS_NONE,
OFONO_SERVICE,
"/",
NULL,
&error);
if (!manager->ofono_manager) {
g_critical("Error creating ofono object manager proxy: %s", error->message);
return;
}
manager->modem_iface = MODEM_IFACE_OFONO;
g_signal_connect(manager->ofono_manager, "modem-added",
G_CALLBACK(modem_added_cb), manager);
g_signal_connect(manager->ofono_manager, "modem-removed",
G_CALLBACK(modem_removed_cb), manager);
gdbo_manager_call_get_modems(manager->ofono_manager,
NULL,
(GAsyncReadyCallback) get_modems_cb,
manager);
}
static void ofono_vanished_cb(GDBusConnection *connection,
const gchar *name,
struct EG25Manager *manager)
{
g_message("oFono vanished from D-Bus");
if (manager->modem_iface == MODEM_IFACE_OFONO) {
manager->modem_iface = MODEM_IFACE_NONE;
ofono_iface_destroy(manager);
}
}
void ofono_iface_init(struct EG25Manager *manager)
{
manager->ofono_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, OFONO_SERVICE,
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
(GBusNameAppearedCallback)ofono_appeared_cb,
(GBusNameVanishedCallback)ofono_vanished_cb,
manager, NULL);
}
void ofono_iface_destroy(struct EG25Manager *manager)
{
if (manager->modem_usb_id) {
g_free(manager->modem_usb_id);
manager->modem_usb_id = NULL;
}
if (manager->ofono_watch != 0) {
g_bus_unwatch_name(manager->ofono_watch);
manager->ofono_watch = 0;
}
}

12
src/ofono-iface.h Normal file
View File

@@ -0,0 +1,12 @@
/*
* Copyright (C) 2020 Oliver Smith <ollieparanoid@postmarketos.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include "manager.h"
void ofono_iface_init(struct EG25Manager *data);
void ofono_iface_destroy(struct EG25Manager *data);

View File

@@ -170,11 +170,18 @@ static void signal_cb(GDBusProxy *proxy,
g_message("system is resuming"); g_message("system is resuming");
take_inhibitor(manager, FALSE); take_inhibitor(manager, FALSE);
modem_resume_pre(manager); modem_resume_pre(manager);
if (manager->mm_modem) { if (
#ifdef HAVE_MMGLIB
manager->mm_modem ||
#endif
manager->modem_iface == MODEM_IFACE_OFONO) {
/* /*
* On some systems ModemManager doesn't handle suspend/resume, so * On some systems ModemManager doesn't handle suspend/resume, so
* we still have a valid/managed modem when resuming. In this case, * we still have a valid/managed modem when resuming. In this case,
* do the whole resume sequence immediately. * do the whole resume sequence immediately.
*
* If modem is managed by ofono, we also do resume sequence immediately
* as ofono handles resuming from sleep itself.
*/ */
manager->modem_state = EG25_STATE_CONFIGURED; manager->modem_state = EG25_STATE_CONFIGURED;
modem_resume_post(manager); modem_resume_post(manager);

View File

@@ -1 +1,5 @@
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{MINOR}=="0", RUN+="/usr/bin/eg25-configure-usb %p" ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/control}="auto"
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/autosuspend_delay_ms}="3000"
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/wakeup}="enabled"
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{avoid_reset_quirk}="1"
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/persist}="0"

View File

@@ -1,21 +0,0 @@
#!/bin/sh
DEVPATH=/sys/$1
USB_ID=
[ -d ${DEVPATH} ] || exit 1
while [ ! "${USB_ID}" ]; do
if [ -f ${DEVPATH}/avoid_reset_quirk ]; then
USB_ID=$(basename ${DEVPATH})
break
fi
DEVPATH=$(dirname ${DEVPATH})
done
# Avoid USB resets
echo "auto" > /sys/bus/usb/devices/${USB_ID}/power/control
echo "3000" > /sys/bus/usb/devices/${USB_ID}/power/autosuspend_delay_ms
echo "enabled" > /sys/bus/usb/devices/${USB_ID}/power/wakeup
echo "1" > /sys/bus/usb/devices/${USB_ID}/avoid_reset_quirk
echo "0" > /sys/bus/usb/devices/${USB_ID}/power/persist

View File

@@ -4,5 +4,4 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
# #
install_data ('eg25-configure-usb', install_dir: bindir)
install_data ('80-modem-eg25.rules', install_dir: udevrulesdir) install_data ('80-modem-eg25.rules', install_dir: udevrulesdir)