blob: a3150ae74bfb23fe18f3f2d000a966ca6fa93541 [file] [log] [blame]
# 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 dbus.types
import logging
import modem
import pm_constants
import utils
from autotest_lib.client.cros.cellular import mm1_constants
class ModemCdma(modem.Modem):
"""
Pseudomodem implementation of the
org.freedesktop.ModemManager1.Modem.ModemCdma and
org.freedesktop.ModemManager1.Modem.Simple interfaces. This class provides
access to specific actions that may be performed in modems with CDMA
capabilities.
"""
class CdmaNetwork(object):
"""
Stores carrier specific information needed for a CDMA network.
"""
def __init__(self,
sid=99998,
nid=0,
activated=True,
mdn='5555555555',
standard='evdo'):
self.sid = sid
self.nid = nid
self.standard = standard
self.activated = activated
self._mdn = mdn
@property
def mdn(self):
"""
@returns: The 'Mobile Directory Number' assigned to this modem by
the carrier. If not activated, the first 6 digits will
contain '0'.
"""
if self.activated:
return self._mdn
return '000000' + self._mdn[6:]
def __init__(self,
state_machine_factory=None,
home_network=CdmaNetwork(),
bus=None,
device='pseudomodem0',
roaming_networks=None,
config=None):
self.home_network = home_network
self.cdma_activate_step = None
modem.Modem.__init__(self,
state_machine_factory,
bus=bus,
device=device,
roaming_networks=roaming_networks,
config=config)
def _InitializeProperties(self):
ip = modem.Modem._InitializeProperties(self)
if self.home_network and self.home_network.activated:
activation_state = \
mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED
else:
activation_state = \
mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED
ip[mm1_constants.I_MODEM_CDMA] = {
'Meid' : 'A100000DCE2CA0',
'Esn' : 'EDD1EDD1',
'Sid' : dbus.types.UInt32(0),
'Nid' : dbus.types.UInt32(0),
'Cdma1xRegistrationState' : (
dbus.types.UInt32(
mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)),
'EvdoRegistrationState' : (
dbus.types.UInt32(
mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)),
'ActivationState' : dbus.types.UInt32(activation_state)
}
props = ip[mm1_constants.I_MODEM]
props['SupportedCapabilities'] = [
dbus.types.UInt32(mm1_constants.MM_MODEM_CAPABILITY_CDMA_EVDO)
]
props['CurrentCapabilities'] = (
dbus.types.UInt32(mm1_constants.MM_MODEM_CAPABILITY_CDMA_EVDO))
props['MaxBearers'] = dbus.types.UInt32(1)
props['MaxActiveBearers'] = dbus.types.UInt32(1)
props['EquipmentIdentifier'] = ip[mm1_constants.I_MODEM_CDMA]['Meid']
props['AccessTechnologies'] = (
dbus.types.UInt32(mm1_constants.MM_MODEM_ACCESS_TECHNOLOGY_EVDO0))
props['SupportedModes'] = [
dbus.types.Struct(
[dbus.types.UInt32(mm1_constants.MM_MODEM_MODE_3G),
dbus.types.UInt32(mm1_constants.MM_MODEM_MODE_4G)],
signature='uu')
]
props['CurrentModes'] = props['SupportedModes'][0]
props['SupportedBands'] = [
dbus.types.UInt32(
mm1_constants.MM_MODEM_BAND_CDMA_BC0_CELLULAR_800),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC1_PCS_1900),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC2_TACS),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC3_JTACS),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC4_KOREAN_PCS),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC5_NMT450),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC6_IMT2000),
dbus.types.UInt32(
mm1_constants.MM_MODEM_BAND_CDMA_BC7_CELLULAR_700),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC8_1800),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC9_900),
dbus.types.UInt32(
mm1_constants.MM_MODEM_BAND_CDMA_BC10_SECONDARY_800),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC11_PAMR_400)
]
props['CurrentBands'] = [
dbus.types.UInt32(
mm1_constants.MM_MODEM_BAND_CDMA_BC0_CELLULAR_800),
dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC1_PCS_1900),
]
if self.home_network:
props['OwnNumbers'] = [self.home_network.mdn]
else:
props['OwnNumbers'] = []
return ip
@utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb')
@dbus.service.method(mm1_constants.I_MODEM_CDMA, in_signature='s',
async_callbacks=('return_cb', 'raise_cb'))
def Activate(self, carrier, return_cb, raise_cb):
"""
Provisions the modem for use with a given carrier using the modem's
OTA activation functionality, if any.
@param carrier: Automatic activation code.
@param return_cb: Asynchronous success callback.
@param raise_cb: Asynchronous failure callback. Has to take an instance
of Exception or Error.
Emits:
ActivationStateChanged
"""
logging.info('ModemCdma.Activate')
machine = self._state_machine_factory.CreateMachine(
pm_constants.STATE_MACHINE_CDMA_ACTIVATE,
self,
return_cb,
raise_cb)
machine.Start()
@utils.log_dbus_method()
@dbus.service.method(mm1_constants.I_MODEM_CDMA, in_signature='a{sv}')
def ActivateManual(self, properties):
"""
Sets the modem provisioning data directly, without contacting the
carrier over the air. Some modems will reboot after this call is made.
@param properties: A dictionary of properties to set on the modem,
including "mdn" and "min".
Emits:
ActivationStateChanged
"""
raise NotImplementedError()
@dbus.service.signal(mm1_constants.I_MODEM_CDMA, signature='uua{sv}')
def ActivationStateChanged(
self,
activation_state,
activation_error,
status_changes):
"""
The device activation state changed.
@param activation_state: Current activation state, given as a
MMModemCdmaActivationState.
@param activation_error: Carrier-specific error code, given as a
MMCdmaActivationError.
@param status_changes: Properties that have changed as a result of this
activation state chage, including "mdn" and "min".
"""
logging.info('ModemCdma: activation state changed: state: %u, error: '
'%u, status_changes: %s',
activation_state,
activation_error,
str(status_changes))
def IsPendingActivation(self):
"""
@returns: True, if a CdmaActivationMachine is currently active.
"""
return self.cdma_activate_step and \
not self.cdma_activate_step.cancelled
def ChangeActivationState(self, state, error):
"""
Changes the activation state of this modem to the one provided.
If the requested state is MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED and
a cdma_activation_machine.CdmaActivationMachine associated with this
modem is currently active, then this method won't update the DBus
properties until after the modem has reset.
@param state: Requested activation state, given as a
MMModemCdmaActivationState.
@param error: Carrier-specific error code, given as a
MMCdmaActivationError.
"""
status_changes = {}
if state == mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
self.home_network.activated = True
status_changes['mdn'] = [self.home_network.mdn]
self.Set(mm1_constants.I_MODEM, 'OwnNumbers', status_changes['mdn'])
if self.IsPendingActivation():
logging.info("A CdmaActivationMachine is currently active. "
"Deferring setting the 'ActivationState' property"
" to ACTIVATED until after the reset is "
"complete.")
return
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'ActivationState', state)
self.ActivationStateChanged(state, error, status_changes)
def GetHomeNetwork(self):
"""
@returns: A instance of CdmaNetwork that represents the
current home network that is assigned to this modem.
"""
return self.home_network
def SetRegistered(self, network):
"""
Sets the modem to be registered on the given network. Configures the
'ActivationState', 'Sid', and 'Nid' properties accordingly.
@param network: An instance of CdmaNetwork.
"""
logging.info('ModemCdma.SetRegistered')
if network:
state = mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_HOME
sid = network.sid
nid = network.nid
if network.activated:
activation_state = \
mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED
else:
activation_state = \
mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED
else:
state = mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
sid = 0
nid = 0
activation_state = \
mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'ActivationState',
activation_state)
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Sid', sid)
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Nid', nid)
self.SetRegistrationState(state)
def SetRegistrationState(self, state):
"""
Sets the CDMA1x and EVDO registration states to the provided value.
@param state: A MMModemCdmaRegistrationState value.
"""
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Cdma1xRegistrationState',
state)
self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'EvdoRegistrationState',
state)
# Inherited from modem.Modem.
def RegisterWithNetwork(
self, operator_id="", return_cb=None, raise_cb=None):
""" Overridden from superclass.
@param operator_id: See superclass.
@param return_cb: See superclass.
@param raise_cb: See superclass.
"""
logging.info('ModemCdma.RegisterWithNetwork')
machine = self._state_machine_factory.CreateMachine(
pm_constants.STATE_MACHINE_REGISTER_CDMA,
self,
operator_id,
return_cb,
raise_cb)
machine.Start()
def UnregisterWithNetwork(self):
""" Overridden from superclass. """
logging.info('ModemCdma.UnregisterWithNetwork')
if self.Get(mm1_constants.I_MODEM, 'State') != \
mm1_constants.MM_MODEM_STATE_REGISTERED:
logging.info('Currently not registered. Nothing to do.')
return
logging.info('Setting state to ENABLED.')
self.ChangeState(mm1_constants.MM_MODEM_STATE_ENABLED,
mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED)
logging.info('Unregistering.')
self.SetRegistered(None)
# Inherited from modem_simple.ModemSimple.
@utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb')
def Connect(self, properties, return_cb, raise_cb):
"""
Overridden from superclass.
@param properties
@param return_cb
@param raise_cb
"""
logging.info('ModemCdma.Connect')
machine = self._state_machine_factory.CreateMachine(
pm_constants.STATE_MACHINE_CONNECT_CDMA,
self,
properties,
return_cb,
raise_cb)
machine.Start()
# Inherited from modem_simple.ModemSimple.
@utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb')
def Disconnect(self, bearer_path, return_cb, raise_cb, *return_cb_args):
"""
Overridden from superclass.
@param bearer_path
@param return_cb
@param raise_cb
@param return_cb_args
"""
logging.info('ModemCdma.Disconnect: %s', bearer_path)
machine = self._state_machine_factory.CreateMachine(
pm_constants.STATE_MACHINE_DISCONNECT,
self,
bearer_path,
return_cb,
raise_cb,
return_cb_args)
machine.Start()
# Inherited from modem_simple.ModemSimple.
@utils.log_dbus_method()
def GetStatus(self):
""" Overridden from superclass. """
modem_props = self.GetAll(mm1_constants.I_MODEM)
cdma_props = self.GetAll(mm1_constants.I_MODEM_CDMA)
retval = {}
retval['state'] = modem_props['State']
if retval['state'] >= mm1_constants.MM_MODEM_STATE_REGISTERED:
retval['signal-quality'] = modem_props['SignalQuality'][0]
retval['bands'] = modem_props['CurrentBands']
retval['cdma-cdma1x-registration-state'] = \
cdma_props['Cdma1xRegistrationState']
retval['cdma-evdo-registration-state'] = \
cdma_props['EvdoRegistrationState']
retval['cdma-sid'] = cdma_props['Sid']
retval['cdma-nid'] = cdma_props['Nid']
return retval