These days more and more devices are showing up that support a
number of different access technology families in the same hardware,
like Qualcomm Gobi (CDMA and GSM), Pantech UM190 (CDMA and GSM),
Pantech UML290 (CDMA and LTE), LG VL600 (CDMA and LTE), Sierra
320U (GSM and LTE), etc. The previous scheme of having device
classes based on access technology family simply cannot handle
this hardware and attempting to add LTE to both the CDMA and GSM
device classes would result in a bunch of code duplication that
we don't want. There's a better way...
Instead, combine both CDMA and GSM device classes into a generic
"Modem" device class that provides capabilities indicating what
access technology families a modem supports, and what families
it supports immediately without a firmware reload. (Gobi devices
for example require a firmware reload before they can switch
between GSM and CDMA). This provides the necessary flexibility
to the client and allows us to keep the API stable when the
same consolidation change is made in ModemManager.
The current code doesn't yet allow multi-mode operation internally,
but the API is now what we want it to be and won't need to be
changed.
deactivate_quickly is misnamed these days; it was originally used
for quickly tearing down a device for sleep and such. But these
days it's used for the bulk of device deactivation. Only the wifi
class used the actual deactivate method. So combine the two and
make device implementations less complicated.
It's the thing that owns the secrets anyway, and it simplifies things to
have the secrets handling there instead of half in NMActRequest and
half in NMManager. It also means we can get rid of the ugly signals
that NMSettingsConnection had to emit to get agent's secrets, and
we can consolidate the requests for the persistent secrets that the
NMSettingsConnection owned into NMSettingsConnection itself instead
of also in NMAgentManager.
Since the NMActRequest and the NMVPNConnection classes already tracked
the underlying NMSettingsConnection representing the activation, its
trivial to just have them ask the NMSettingsConnection for secrets
instead of talking to the NMAgentManager. Thus, only the
NMSettingsConnection now has to know about the agent manager, and it
presents a cleaner interface to other objects further up the chain,
instead of having bits of the secrets request splattered around the
activation request, the VPN connection, the NMManager, etc.
When a user makes an explicit request for secrets via GetSecrets
or activates a device, don't ask other users' agents for secrets.
Restrict secrets request to agents owned by the user that made the
initial activate or GetSecrets request.
Automatic activations still request secrets from any available agent.
Given connection details, complete the connection as well as possible
using the given specific object and device, add it to system
settings, and activate it all in one method.
Instead of a bizare mechanism of signals back to the manager
object that used to be required because of the user/system settings
split, let each place that needs secrets request those secrets
itself. This flattens the secrets request process a ton and
the code flow significantly.
Previously the get secrets flow was something like this:
nm_act_request_get_secrets ()
nm_secrets_provider_interface_get_secrets ()
emits manager-get-secrets signal
provider_get_secerts ()
system_get_secrets ()
system_get_secrets_idle_cb ()
nm_sysconfig_connection_get_secrets ()
system_get_secrets_reply_cb ()
nm_secrets_provider_interface_get_secrets_result ()
signal failure or success
now instead we do something like this:
nm_agent_manager_get_secrets ()
nm_agent_manager_get_secrets ()
request_start_secrets ()
nm_sysconfig_connection_get_secrets ()
return failure or success to callback
Use the interfaces kernel index when we can to avoid unecessary
iface->index lookups; and let callers figure out which address
family they really want to flush.
Some stuff we build (the DHCP manager) gets built independently
so that we can use it for unit tests. For that, we need to build
the logging bits separately too, since the independent DHCP
library can't use them if they are embedded in NM.
Due to various ordering issues in ModemManager, when the Enable()
call fails because a PIN is required, MM will disable the modem
and *then* complete the dbus call. That means that NM gets the
Enable property change before the Enable() call completes, and NM
would then transition the device to DISCONNECTED. What we
really want to do is get the response from MM and then figure out
whether to fail activation or get secrets, not go to DISCONNECTED.
To fix this, ignore Enabled property changes to FALSE while
activating so we can handle it ourselves. There are still a few
fixes left in nm-applet to make the secrets request for PINs work
on-the-fly, but saved in the connection works fine.
NM shouldn't really be calling Enable(False) except in response to
direct user requests to turn off WWAN, much like rfkill, since
Enable(False) /is/ essentially rfkill for 3G. Instead, we should
be powering up the modem before trying to use it, and only
disconnecting after we're done. Let the user do enable/disable
when they want to.
This also fixes issues with other devices like GPS potentially
using the modem-manager at the same time as NM and ensures that NM
won't punch the modem in the face while GPS is using it.
Previously, ppp code would flip device state to _NEED_AUTH before
asking for secrets update; this is not the case anymore after landing
of f28a0df4a66e8f6c98327691c9c90df0604bbd28; hence, we need to
allow update of secrets in all ACTIVATING stages.
This patch updates this behaviour for all device classes with ppp
support.
NM didn't pass it to MM anyway, so it was mainly unused, but the band settings
were still wrong. Fix that (and still preserve ABI) by adding a new property
for allowed bands that can actually hold all the bands instead of limiting
to 16-bits. Clean up some of the deprecation stuff at the same time to make
it clearer what's deprecated and what to do about it.
So that Bluetooth can use them. They used to be NMDevice subclasses, but
we need them to be generic objects that both bluetooth and the normal
modem stack can use. All because GObject can't do multiple inheritance,
but that would probably be even messier.
So now that we have generic modem objects, we can create the actual
NMDevice subclasses that will wrap them for non-BT modems, and then
also have NMDeviceBt wrap them too for DUN.
Instead of doing this in every device subclass, do it in the NMDevice
superclass. nm_device_can_activate() already did the same logic that
each of the subclass device_state_changed() handlers were doing to
figure out whether they could do the transition from unavailable
to disconnected, so just use that in NMDevice and kill lots of code.