| # 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 |