blob: 4c36a7ff6140b9d073817f4f02f8c79d67a09784 [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import dbus
import os
from autotest_lib.client.cros.cellular import cellular
MMPROVIDERS = [ 'org.chromium', 'org.freedesktop' ]
class Modem(object):
MODEM_INTERFACE = 'org.freedesktop.ModemManager.Modem'
SIMPLE_MODEM_INTERFACE = 'org.freedesktop.ModemManager.Modem.Simple'
CDMA_MODEM_INTERFACE = 'org.freedesktop.ModemManager.Modem.Cdma'
GSM_MODEM_INTERFACE = 'org.freedesktop.ModemManager.Modem.Gsm'
GOBI_MODEM_INTERFACE = 'org.chromium.ModemManager.Modem.Gobi'
GSM_CARD_INTERFACE = 'org.freedesktop.ModemManager.Modem.Gsm.Card'
GSM_SMS_INTERFACE = 'org.freedesktop.ModemManager.Modem.Gsm.SMS'
GSM_NETWORK_INTERFACE = 'org.freedesktop.ModemManager.Modem.Gsm.Network'
PROPERTIES_INTERFACE = 'org.freedesktop.DBus.Properties'
GSM_MODEM = 1
CDMA_MODEM = 2
# MM_MODEM_GSM_ACCESS_TECH (not exported)
# From /usr/include/mm/mm-modem.h
_MM_MODEM_GSM_ACCESS_TECH_UNKNOWN = 0
_MM_MODEM_GSM_ACCESS_TECH_GSM = 1
_MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT = 2
_MM_MODEM_GSM_ACCESS_TECH_GPRS = 3
_MM_MODEM_GSM_ACCESS_TECH_EDGE = 4
_MM_MODEM_GSM_ACCESS_TECH_UMTS = 5
_MM_MODEM_GSM_ACCESS_TECH_HSDPA = 6
_MM_MODEM_GSM_ACCESS_TECH_HSUPA = 7
_MM_MODEM_GSM_ACCESS_TECH_HSPA = 8
# Mapping of modem technologies to cellular technologies
_ACCESS_TECH_TO_TECHNOLOGY = {
_MM_MODEM_GSM_ACCESS_TECH_GSM: cellular.Technology.WCDMA,
_MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT: cellular.Technology.WCDMA,
_MM_MODEM_GSM_ACCESS_TECH_GPRS: cellular.Technology.GPRS,
_MM_MODEM_GSM_ACCESS_TECH_EDGE: cellular.Technology.EGPRS,
_MM_MODEM_GSM_ACCESS_TECH_UMTS: cellular.Technology.WCDMA,
_MM_MODEM_GSM_ACCESS_TECH_HSDPA: cellular.Technology.HSDPA,
_MM_MODEM_GSM_ACCESS_TECH_HSUPA: cellular.Technology.HSUPA,
_MM_MODEM_GSM_ACCESS_TECH_HSPA: cellular.Technology.HSDUPA,
}
def __init__(self, manager, path):
self.bus = manager.bus
self.service = manager.service
self.path = path
def Modem(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.MODEM_INTERFACE)
def SimpleModem(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.SIMPLE_MODEM_INTERFACE)
def CdmaModem(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.CDMA_MODEM_INTERFACE)
def GobiModem(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.GOBI_MODEM_INTERFACE)
def GsmModem(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.GSM_MODEM_INTERFACE)
def GsmCard(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.GSM_CARD_INTERFACE)
def GsmSms(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.GSM_SMS_INTERFACE)
def GsmNetwork(self):
obj = self.bus.get_object(self.service, self.path)
return dbus.Interface(obj, Modem.GSM_NETWORK_INTERFACE)
def GetAll(self, iface):
obj = self.bus.get_object(self.service, self.path)
obj_iface = dbus.Interface(obj, Modem.PROPERTIES_INTERFACE)
return obj_iface.GetAll(iface)
def _GetModemInterfaces(self):
return [
Modem.MODEM_INTERFACE,
Modem.SIMPLE_MODEM_INTERFACE,
Modem.CDMA_MODEM_INTERFACE,
Modem.GSM_MODEM_INTERFACE,
Modem.GSM_NETWORK_INTERFACE,
Modem.GOBI_MODEM_INTERFACE]
def GetModemProperties(self):
props = dict()
for iface in self._GetModemInterfaces():
try:
d = self.GetAll(iface)
except dbus.exceptions.DBusException, e:
continue
if d:
for k, v in d.iteritems():
props[k] = v
return props
def GetAccessTechnology(self):
props = self.GetModemProperties()
tech = props.get('AccessTechnology')
return Modem._ACCESS_TECH_TO_TECHNOLOGY[tech]
def _GetRegistrationState(self):
try:
network = self.GsmNetwork()
(status, code, name) = network.GetRegistrationInfo()
# TODO(jglasgow): HOME - 1, ROAMING - 5
return status == 1 or status == 5
except dbus.exceptions.DBusException, e:
pass
cdma_modem = self.CdmaModem()
try:
cdma, evdo = cdma_modem.GetRegistrationState()
return cdma > 0 or evdo > 0
except dbus.exceptions.DBusException, e:
pass
return False
def ModemIsRegistered(self):
"""Ensure that modem is registered on the network."""
return self._GetRegistrationState()
def ModemIsRegisteredUsing(self, technology):
"""Ensure that modem is registered on the network with a technology."""
if not self.ModemIsRegistered():
return False
reported_tech = self.GetAccessTechnology()
# TODO(jglasgow): Remove this mapping. Basestation and
# reported technology should be identical.
BASESTATION_TO_REPORTED_TECHNOLOGY = {
cellular.Technology.GPRS: cellular.Technology.GPRS,
cellular.Technology.EGPRS: cellular.Technology.GPRS,
cellular.Technology.WCDMA: cellular.Technology.HSDUPA,
cellular.Technology.HSDPA: cellular.Technology.HSDUPA,
cellular.Technology.HSUPA: cellular.Technology.HSDUPA,
cellular.Technology.HSDUPA: cellular.Technology.HSDUPA,
cellular.Technology.HSPA_PLUS: cellular.Technology.HSPA_PLUS
}
return BASESTATION_TO_REPORTED_TECHNOLOGY[technology] == reported_tech
class ModemManager(object):
INTERFACE = 'org.freedesktop.ModemManager'
def __init__(self, provider=None):
self.bus = dbus.SystemBus()
self.provider = provider or os.getenv('MMPROVIDER') or 'org.chromium'
self.service = '%s.ModemManager' % self.provider
self.path = '/%s/ModemManager' % (self.provider.replace('.', '/'))
self.manager = dbus.Interface(
self.bus.get_object(self.service, self.path),
ModemManager.INTERFACE)
def EnumerateDevices(manager=None):
""" Enumerate all modems in the system
Args:
manager - the specific manager to use, if None check all known managers
Returns:
a list of (ModemManager object, modem dbus path)
"""
SERVICE_UNKNOWN = 'org.freedesktop.DBus.Error.ServiceUnknown'
if manager:
managers = [manager]
else:
managers = []
for provider in MMPROVIDERS:
try:
managers.append(ModemManager(provider))
except dbus.exceptions.DBusException, e:
if e._dbus_error_name != SERVICE_UNKNOWN:
raise
result = []
for m in managers:
for path in m.manager.EnumerateDevices():
result.append((m, path))
return result
def PickOneModem(modem_pattern, manager=None):
""" Pick a modem
If a machine has a single modem, managed by one one of the
MMPROVIDERS, return the dbus path and a ModemManager object for
that modem.
Args:
modem_pattern - pattern that should match the modem path
manager - the specific manager to use, if None check all known managers
Returns:
Modem object
Raises:
ValueError - if there are no matching modems, or there are more
than one
"""
devices = EnumerateDevices(manager)
matches = [Modem(m, path) for m, path in devices if modem_pattern in path]
if not matches:
raise ValueError("No modems had substring: " + modem_pattern)
if len(matches) > 1:
raise ValueError("Expected only one modem, got: " +
", ".join([modem.path for modem in matches]))
return matches[0]