15eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow#!/usr/bin/python
25eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
35eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow# Use of this source code is governed by a BSD-style license that can be
45eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow# found in the LICENSE file.
55eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow"""Implement a modem proxy to talk to a ModemManager1 modem."""
65eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
7e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Lefrom autotest_lib.client.common_lib import error
85eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgowfrom autotest_lib.client.cros.cellular import cellular
95eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgowfrom autotest_lib.client.cros.cellular import mm1
10e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Lefrom autotest_lib.client.cros.cellular import mm1_constants
115eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgowimport dbus
12341d22c6c3a1561bd30695463fc40110645400e9Byron Kubertimport cellular_logging
13341d22c6c3a1561bd30695463fc40110645400e9Byron Kubert
14341d22c6c3a1561bd30695463fc40110645400e9Byron Kubertlog = cellular_logging.SetupCellularLogging('modem1')
15341d22c6c3a1561bd30695463fc40110645400e9Byron Kubert
16341d22c6c3a1561bd30695463fc40110645400e9Byron KubertMODEM_TIMEOUT = 60
175eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
185eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
195eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgowclass Modem(object):
205eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    """An object which talks to a ModemManager1 modem."""
215eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    # MM_MODEM_GSM_ACCESS_TECH (not exported)
225eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    # From /usr/include/mm/mm-modem.h
235eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    _MM_MODEM_GSM_ACCESS_TECH_UNKNOWN = 0
24387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_GSM = 1 << 1
25387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT = 1 << 2
26387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_GPRS = 1 << 3
27387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_EDGE = 1 << 4
28387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_UMTS = 1 << 5
29387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_HSDPA = 1 << 6
30387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_HSUPA = 1 << 7
31387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    _MM_MODEM_GSM_ACCESS_TECH_HSPA = 1 << 8
325eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
335eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    # Mapping of modem technologies to cellular technologies
345eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    _ACCESS_TECH_TO_TECHNOLOGY = {
355eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_GSM: cellular.Technology.WCDMA,
365eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT: cellular.Technology.WCDMA,
375eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_GPRS: cellular.Technology.GPRS,
385eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_EDGE: cellular.Technology.EGPRS,
395eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_UMTS: cellular.Technology.WCDMA,
405eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_HSDPA: cellular.Technology.HSDPA,
415eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_HSUPA: cellular.Technology.HSUPA,
425eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        _MM_MODEM_GSM_ACCESS_TECH_HSPA: cellular.Technology.HSDUPA,
435eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    }
445eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
455eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def __init__(self, manager, path):
465eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.manager = manager
475eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.bus = manager.bus
485eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.service = manager.service
495eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.path = path
505eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
515eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def Modem(self):
525eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
535eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return dbus.Interface(obj, mm1.MODEM_INTERFACE)
545eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
555eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def SimpleModem(self):
565eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
575eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return dbus.Interface(obj, mm1.MODEM_SIMPLE_INTERFACE)
585eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
595eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def GsmModem(self):
605eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
615eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return dbus.Interface(obj, mm1.MODEM_MODEM3GPP_INTERFACE)
625eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
635eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def CdmaModem(self):
645eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
655eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return dbus.Interface(obj, mm1.MODEM_MODEMCDMA_INTERFACE)
665eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
675eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def Sim(self):
685eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
695eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return dbus.Interface(obj, mm1.SIM_INTERFACE)
705eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
71494cb655cf158c37c6f84c37954b683df8928f0aArman Uguray    def PropertiesInterface(self):
725eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        obj = self.bus.get_object(self.service, self.path)
73494cb655cf158c37c6f84c37954b683df8928f0aArman Uguray        return dbus.Interface(obj, dbus.PROPERTIES_IFACE)
74494cb655cf158c37c6f84c37954b683df8928f0aArman Uguray
75494cb655cf158c37c6f84c37954b683df8928f0aArman Uguray    def GetAll(self, iface):
76494cb655cf158c37c6f84c37954b683df8928f0aArman Uguray        obj_iface = self.PropertiesInterface()
775eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return obj_iface.GetAll(iface)
785eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
795eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def _GetModemInterfaces(self):
805eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return [
81387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MODEM_INTERFACE,
825eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            mm1.MODEM_SIMPLE_INTERFACE,
835eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            mm1.MODEM_MODEM3GPP_INTERFACE,
845eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            mm1.MODEM_MODEMCDMA_INTERFACE
855eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            ]
865eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
876d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le    @staticmethod
886d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le    def _CopyPropertiesCheckUnique(src, dest):
896d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le        """Copies properties from |src| to |dest| and makes sure there are no
906d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le           duplicate properties that have different values."""
916d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le        for key, value in src.iteritems():
926d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            if key in dest and value != dest[key]:
936d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le                raise KeyError('Duplicate property %s, different values '
946d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le                               '("%s", "%s")' % (key, value, dest[key]))
956d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            dest[key] = value
966d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le
975eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def GetModemProperties(self):
985eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        """Returns all DBus Properties of all the modem interfaces."""
995eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        props = dict()
1005eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        for iface in self._GetModemInterfaces():
1015eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            try:
1026d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le                iface_props = self.GetAll(iface)
1035eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            except dbus.exceptions.DBusException:
1045eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow                continue
1056d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            if iface_props:
1066d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le                self._CopyPropertiesCheckUnique(iface_props, props)
1076d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le
1086d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le        try:
1096d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            sim_obj = self.bus.get_object(self.service, props['Sim'])
1106d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            sim_props_iface = dbus.Interface(sim_obj, dbus.PROPERTIES_IFACE)
1116d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            sim_props = sim_props_iface.GetAll(mm1.SIM_INTERFACE)
1125fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan
1135fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            # SIM cards may store an empty operator name or store a value
1145fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            # different from the one obtained OTA. Rename the 'OperatorName'
1155fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            # property obtained from the SIM card to 'SimOperatorName' in
1165fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            # order to avoid a potential conflict with the 'OperatorName'
1175fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            # property obtained from the Modem3gpp interface.
1185fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan            if 'OperatorName' in sim_props:
1195fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan                sim_props['SimOperatorName'] = sim_props.pop('OperatorName')
1205fbcd3729ff6d1dbe89c45196769cbee1f101604Ben Chan
1216d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            self._CopyPropertiesCheckUnique(sim_props, props)
1226d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le        except dbus.exceptions.DBusException:
1236d4ffa9931f9e32036519e4f678aa9ae8fb6e4aeThieu Le            pass
1245eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1255eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return props
1265eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1275eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def GetAccessTechnology(self):
128387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        """Returns the modem access technology."""
1295eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        props = self.GetModemProperties()
130387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        tech = props['AccessTechnologies']
1315eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return Modem._ACCESS_TECH_TO_TECHNOLOGY[tech]
1325eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
133387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    def GetCurrentTechnologyFamily(self):
134387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        """Returns the modem technology family."""
135341d22c6c3a1561bd30695463fc40110645400e9Byron Kubert        props = self.GetAll(mm1.MODEM_INTERFACE)
136336aa10fb58c00d574b8018c0df844bd4ddee8d1Thieu Le        capabilities = props.get('SupportedCapabilities')
137336aa10fb58c00d574b8018c0df844bd4ddee8d1Thieu Le        if self._IsCDMAModem(capabilities):
138387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            return cellular.TechnologyFamily.CDMA
139336aa10fb58c00d574b8018c0df844bd4ddee8d1Thieu Le        if self._Is3GPPModem(capabilities):
140336aa10fb58c00d574b8018c0df844bd4ddee8d1Thieu Le            return cellular.TechnologyFamily.UMTS
141336aa10fb58c00d574b8018c0df844bd4ddee8d1Thieu Le        raise error.TestError('Invalid modem type')
142387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le
143387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    def GetVersion(self):
144387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        """Returns the modem version information."""
145387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        return self.GetModemProperties()['Revision']
146387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le
147a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le    def _IsCDMAModem(self, capabilities):
148a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le        return mm1_constants.MM_MODEM_CAPABILITY_CDMA_EVDO in capabilities
149a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le
150a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le    def _Is3GPPModem(self, capabilities):
151a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le        for capability in capabilities:
152a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le            if (capability &
153a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le                    (mm1_constants.MM_MODEM_CAPABILITY_LTE |
154a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le                     mm1_constants.MM_MODEM_CAPABILITY_LTE_ADVANCED |
155a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le                     mm1_constants.MM_MODEM_CAPABILITY_GSM_UMTS)):
156a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le                return True
157a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le        return False
158a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le
159e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le    def _CDMAModemIsRegistered(self):
160e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        modem_status = self.SimpleModem().GetStatus()
161e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        cdma1x_state = modem_status.get(
162e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                'cdma-cdma1x-registration-state',
163e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
164e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        evdo_state = modem_status.get(
165e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                'cdma-evdo-registration-state',
166e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
167e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        return (cdma1x_state !=
168e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN or
169e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                evdo_state !=
170e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
171e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le
172e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le    def _3GPPModemIsRegistered(self):
173e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        modem_status = self.SimpleModem().GetStatus()
174e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        state = modem_status.get('m3gpp-registration-state')
175e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        return (state == mm1_constants.MM_MODEM_3GPP_REGISTRATION_STATE_HOME or
176e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le                state == mm1_constants.MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
1775eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1785eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def ModemIsRegistered(self):
1795eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        """Ensure that modem is registered on the network."""
180e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        props = self.GetAll(mm1.MODEM_INTERFACE)
181e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        capabilities = props.get('SupportedCapabilities')
182a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le        if self._IsCDMAModem(capabilities):
183e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le            return self._CDMAModemIsRegistered()
184a2aeab3e16a451360f5938219d779d23f6e70b69Thieu Le        elif self._Is3GPPModem(capabilities):
185e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le            return self._3GPPModemIsRegistered()
186e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le        else:
187e3b3fcfcc68ffd116e90785cab1f2f62a15f5892Thieu Le            raise error.TestError('Invalid modem type')
1885eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1895eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def ModemIsRegisteredUsing(self, technology):
1905eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        """Ensure that modem is registered on the network with a technology."""
1915eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        if not self.ModemIsRegistered():
1925eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            return False
1935eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1945eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        reported_tech = self.GetAccessTechnology()
1955eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
1965eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        # TODO(jglasgow): Remove this mapping.  Basestation and
1975eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        # reported technology should be identical.
1985eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        BASESTATION_TO_REPORTED_TECHNOLOGY = {
1995eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.GPRS: cellular.Technology.GPRS,
2005eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.EGPRS: cellular.Technology.GPRS,
2015eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.WCDMA: cellular.Technology.HSDUPA,
2025eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.HSDPA: cellular.Technology.HSDUPA,
2035eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.HSUPA: cellular.Technology.HSDUPA,
2045eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.HSDUPA: cellular.Technology.HSDUPA,
2055eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            cellular.Technology.HSPA_PLUS: cellular.Technology.HSPA_PLUS
2065eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        }
2075eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2085eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return BASESTATION_TO_REPORTED_TECHNOLOGY[technology] == reported_tech
2095eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2100d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan    def IsConnectingOrDisconnecting(self):
2110d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan        props = self.GetAll(mm1.MODEM_INTERFACE)
2120d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan        return props['State'] in [
2130d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan            mm1.MM_MODEM_STATE_CONNECTING,
2140d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan            mm1.MM_MODEM_STATE_DISCONNECTING
2150d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan        ]
2160d5aaa5de685a05ea80aeb4358f59fc79632c813Ben Chan
2175eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def IsEnabled(self):
218387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        props = self.GetAll(mm1.MODEM_INTERFACE)
219387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        return props['State'] in [
220387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_ENABLED,
221387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_SEARCHING,
222387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_REGISTERED,
223387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_DISCONNECTING,
224387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_CONNECTING,
225387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le            mm1.MM_MODEM_STATE_CONNECTED
226387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        ]
227387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le
228387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le    def IsDisabled(self):
229387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        props = self.GetAll(mm1.MODEM_INTERFACE)
230387e410e7dd63062c7dc008c5cf0a6729619dd97Thieu Le        return props['State'] == mm1.MM_MODEM_STATE_DISABLED
2315eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2324e2d4cf8a1b1a5117b92d9a86070f5a2a88cceaaThieu Le    def Enable(self, enable, **kwargs):
233a4d78927f60e2a5b9bac88ba3f9adc75d72b5f7fThieu Le        self.Modem().Enable(enable, timeout=MODEM_TIMEOUT, **kwargs)
2345eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2355eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def Connect(self, props):
236a4d78927f60e2a5b9bac88ba3f9adc75d72b5f7fThieu Le        self.SimpleModem().Connect(props, timeout=MODEM_TIMEOUT)
2375eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2385eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def Disconnect(self):
239a4d78927f60e2a5b9bac88ba3f9adc75d72b5f7fThieu Le        self.SimpleModem().Disconnect('/', timeout=MODEM_TIMEOUT)
2405eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2415eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2425eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgowclass ModemManager(object):
2435eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    """An object which talks to a ModemManager1 service."""
2445eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2455eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def __init__(self):
2465eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.bus = dbus.SystemBus()
2475eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.service = mm1.MODEM_MANAGER_INTERFACE
2485eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.path = mm1.OMM
2495eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.manager = dbus.Interface(
2505eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            self.bus.get_object(self.service, self.path),
2515eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            mm1.MODEM_MANAGER_INTERFACE)
2525eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        self.objectmanager = dbus.Interface(
2535eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow            self.bus.get_object(self.service, self.path), mm1.OFDOM)
2545eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2555eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def EnumerateDevices(self):
2565eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        devices = self.objectmanager.GetManagedObjects()
2575eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return devices.keys()
2585eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow
2595eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow    def GetModem(self, path):
2605eff4080ae483fb090c1e361f9bab5a367398e8fJason Glasgow        return Modem(self, path)
26198327a403c6d0ca8060a2f60b8af14e9ea40d4b4Thieu Le
26298327a403c6d0ca8060a2f60b8af14e9ea40d4b4Thieu Le    def SetDebugLogging(self):
26398327a403c6d0ca8060a2f60b8af14e9ea40d4b4Thieu Le        self.manager.SetLogging('DEBUG')
264