1# Lint as: python2, python3 2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import dbus 7import dbus.types 8import logging 9 10from autotest_lib.client.cros.cellular.pseudomodem import modem 11from autotest_lib.client.cros.cellular.pseudomodem import pm_constants 12from autotest_lib.client.cros.cellular.pseudomodem import utils 13 14from autotest_lib.client.cros.cellular import mm1_constants 15 16class ModemCdma(modem.Modem): 17 """ 18 Pseudomodem implementation of the 19 org.freedesktop.ModemManager1.Modem.ModemCdma and 20 org.freedesktop.ModemManager1.Modem.Simple interfaces. This class provides 21 access to specific actions that may be performed in modems with CDMA 22 capabilities. 23 24 """ 25 26 class CdmaNetwork(object): 27 """ 28 Stores carrier specific information needed for a CDMA network. 29 30 """ 31 def __init__(self, 32 sid=99998, 33 nid=0, 34 activated=True, 35 mdn='5555555555', 36 standard='evdo'): 37 self.sid = sid 38 self.nid = nid 39 self.standard = standard 40 self.activated = activated 41 self._mdn = mdn 42 43 44 @property 45 def mdn(self): 46 """ 47 @returns: The 'Mobile Directory Number' assigned to this modem by 48 the carrier. If not activated, the first 6 digits will 49 contain '0'. 50 51 """ 52 if self.activated: 53 return self._mdn 54 return '000000' + self._mdn[6:] 55 56 57 def __init__(self, 58 state_machine_factory=None, 59 home_network=CdmaNetwork(), 60 bus=None, 61 device='pseudomodem0', 62 roaming_networks=None, 63 config=None): 64 self.home_network = home_network 65 self.cdma_activate_step = None 66 modem.Modem.__init__(self, 67 state_machine_factory, 68 bus=bus, 69 device=device, 70 roaming_networks=roaming_networks, 71 config=config) 72 73 74 def _InitializeProperties(self): 75 ip = modem.Modem._InitializeProperties(self) 76 if self.home_network and self.home_network.activated: 77 activation_state = \ 78 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED 79 else: 80 activation_state = \ 81 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED 82 ip[mm1_constants.I_MODEM_CDMA] = { 83 'Meid' : 'A100000DCE2CA0', 84 'Esn' : 'EDD1EDD1', 85 'Sid' : dbus.types.UInt32(0), 86 'Nid' : dbus.types.UInt32(0), 87 'Cdma1xRegistrationState' : ( 88 dbus.types.UInt32( 89 mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)), 90 'EvdoRegistrationState' : ( 91 dbus.types.UInt32( 92 mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)), 93 'ActivationState' : dbus.types.UInt32(activation_state) 94 } 95 props = ip[mm1_constants.I_MODEM] 96 props['SupportedCapabilities'] = [ 97 dbus.types.UInt32(mm1_constants.MM_MODEM_CAPABILITY_CDMA_EVDO) 98 ] 99 props['CurrentCapabilities'] = ( 100 dbus.types.UInt32(mm1_constants.MM_MODEM_CAPABILITY_CDMA_EVDO)) 101 props['MaxBearers'] = dbus.types.UInt32(1) 102 props['MaxActiveBearers'] = dbus.types.UInt32(1) 103 props['EquipmentIdentifier'] = ip[mm1_constants.I_MODEM_CDMA]['Meid'] 104 props['AccessTechnologies'] = ( 105 dbus.types.UInt32(mm1_constants.MM_MODEM_ACCESS_TECHNOLOGY_EVDO0)) 106 props['SupportedModes'] = [ 107 dbus.types.Struct( 108 [dbus.types.UInt32(mm1_constants.MM_MODEM_MODE_3G), 109 dbus.types.UInt32(mm1_constants.MM_MODEM_MODE_4G)], 110 signature='uu') 111 ] 112 props['CurrentModes'] = props['SupportedModes'][0] 113 props['SupportedBands'] = [ 114 dbus.types.UInt32( 115 mm1_constants.MM_MODEM_BAND_CDMA_BC0_CELLULAR_800), 116 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC1_PCS_1900), 117 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC2_TACS), 118 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC3_JTACS), 119 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC4_KOREAN_PCS), 120 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC5_NMT450), 121 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC6_IMT2000), 122 dbus.types.UInt32( 123 mm1_constants.MM_MODEM_BAND_CDMA_BC7_CELLULAR_700), 124 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC8_1800), 125 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC9_900), 126 dbus.types.UInt32( 127 mm1_constants.MM_MODEM_BAND_CDMA_BC10_SECONDARY_800), 128 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC11_PAMR_400) 129 ] 130 props['CurrentBands'] = [ 131 dbus.types.UInt32( 132 mm1_constants.MM_MODEM_BAND_CDMA_BC0_CELLULAR_800), 133 dbus.types.UInt32(mm1_constants.MM_MODEM_BAND_CDMA_BC1_PCS_1900), 134 ] 135 if self.home_network: 136 props['OwnNumbers'] = [self.home_network.mdn] 137 else: 138 props['OwnNumbers'] = [] 139 140 return ip 141 142 143 @utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb') 144 @dbus.service.method(mm1_constants.I_MODEM_CDMA, in_signature='s', 145 async_callbacks=('return_cb', 'raise_cb')) 146 def Activate(self, carrier, return_cb, raise_cb): 147 """ 148 Provisions the modem for use with a given carrier using the modem's 149 OTA activation functionality, if any. 150 151 @param carrier: Automatic activation code. 152 @param return_cb: Asynchronous success callback. 153 @param raise_cb: Asynchronous failure callback. Has to take an instance 154 of Exception or Error. 155 Emits: 156 ActivationStateChanged 157 158 """ 159 logging.info('ModemCdma.Activate') 160 machine = self._state_machine_factory.CreateMachine( 161 pm_constants.STATE_MACHINE_CDMA_ACTIVATE, 162 self, 163 return_cb, 164 raise_cb) 165 machine.Start() 166 167 168 @utils.log_dbus_method() 169 @dbus.service.method(mm1_constants.I_MODEM_CDMA, in_signature='a{sv}') 170 def ActivateManual(self, properties): 171 """ 172 Sets the modem provisioning data directly, without contacting the 173 carrier over the air. Some modems will reboot after this call is made. 174 175 @param properties: A dictionary of properties to set on the modem, 176 including "mdn" and "min". 177 Emits: 178 ActivationStateChanged 179 180 """ 181 raise NotImplementedError() 182 183 184 @dbus.service.signal(mm1_constants.I_MODEM_CDMA, signature='uua{sv}') 185 def ActivationStateChanged( 186 self, 187 activation_state, 188 activation_error, 189 status_changes): 190 """ 191 The device activation state changed. 192 193 @param activation_state: Current activation state, given as a 194 MMModemCdmaActivationState. 195 @param activation_error: Carrier-specific error code, given as a 196 MMCdmaActivationError. 197 @param status_changes: Properties that have changed as a result of this 198 activation state chage, including "mdn" and "min". 199 200 """ 201 logging.info('ModemCdma: activation state changed: state: %u, error: ' 202 '%u, status_changes: %s', 203 activation_state, 204 activation_error, 205 str(status_changes)) 206 207 208 def IsPendingActivation(self): 209 """ 210 @returns: True, if a CdmaActivationMachine is currently active. 211 212 """ 213 return self.cdma_activate_step and \ 214 not self.cdma_activate_step.cancelled 215 216 217 def ChangeActivationState(self, state, error): 218 """ 219 Changes the activation state of this modem to the one provided. 220 221 If the requested state is MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED and 222 a cdma_activation_machine.CdmaActivationMachine associated with this 223 modem is currently active, then this method won't update the DBus 224 properties until after the modem has reset. 225 226 @param state: Requested activation state, given as a 227 MMModemCdmaActivationState. 228 @param error: Carrier-specific error code, given as a 229 MMCdmaActivationError. 230 231 """ 232 status_changes = {} 233 if state == mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED: 234 self.home_network.activated = True 235 status_changes['mdn'] = [self.home_network.mdn] 236 self.Set(mm1_constants.I_MODEM, 'OwnNumbers', status_changes['mdn']) 237 238 if self.IsPendingActivation(): 239 logging.info("A CdmaActivationMachine is currently active. " 240 "Deferring setting the 'ActivationState' property" 241 " to ACTIVATED until after the reset is " 242 "complete.") 243 return 244 245 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'ActivationState', state) 246 self.ActivationStateChanged(state, error, status_changes) 247 248 249 def GetHomeNetwork(self): 250 """ 251 @returns: A instance of CdmaNetwork that represents the 252 current home network that is assigned to this modem. 253 254 """ 255 return self.home_network 256 257 258 def SetRegistered(self, network): 259 """ 260 Sets the modem to be registered on the given network. Configures the 261 'ActivationState', 'Sid', and 'Nid' properties accordingly. 262 263 @param network: An instance of CdmaNetwork. 264 265 """ 266 logging.info('ModemCdma.SetRegistered') 267 if network: 268 state = mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_HOME 269 sid = network.sid 270 nid = network.nid 271 if network.activated: 272 activation_state = \ 273 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED 274 else: 275 activation_state = \ 276 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED 277 else: 278 state = mm1_constants.MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN 279 sid = 0 280 nid = 0 281 activation_state = \ 282 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED 283 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'ActivationState', 284 activation_state) 285 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Sid', sid) 286 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Nid', nid) 287 self.SetRegistrationState(state) 288 289 290 def SetRegistrationState(self, state): 291 """ 292 Sets the CDMA1x and EVDO registration states to the provided value. 293 294 @param state: A MMModemCdmaRegistrationState value. 295 296 """ 297 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'Cdma1xRegistrationState', 298 state) 299 self.SetUInt32(mm1_constants.I_MODEM_CDMA, 'EvdoRegistrationState', 300 state) 301 302 303 # Inherited from modem.Modem. 304 def RegisterWithNetwork( 305 self, operator_id="", return_cb=None, raise_cb=None): 306 """ Overridden from superclass. 307 308 @param operator_id: See superclass. 309 @param return_cb: See superclass. 310 @param raise_cb: See superclass. 311 312 """ 313 logging.info('ModemCdma.RegisterWithNetwork') 314 machine = self._state_machine_factory.CreateMachine( 315 pm_constants.STATE_MACHINE_REGISTER_CDMA, 316 self, 317 operator_id, 318 return_cb, 319 raise_cb) 320 machine.Start() 321 322 323 def UnregisterWithNetwork(self): 324 """ Overridden from superclass. """ 325 logging.info('ModemCdma.UnregisterWithNetwork') 326 if self.Get(mm1_constants.I_MODEM, 'State') != \ 327 mm1_constants.MM_MODEM_STATE_REGISTERED: 328 logging.info('Currently not registered. Nothing to do.') 329 return 330 logging.info('Setting state to ENABLED.') 331 self.ChangeState(mm1_constants.MM_MODEM_STATE_ENABLED, 332 mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED) 333 logging.info('Unregistering.') 334 self.SetRegistered(None) 335 336 337 # Inherited from modem_simple.ModemSimple. 338 @utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb') 339 def Connect(self, properties, return_cb, raise_cb): 340 """ 341 Overridden from superclass. 342 343 @param properties 344 @param return_cb 345 @param raise_cb 346 347 """ 348 logging.info('ModemCdma.Connect') 349 machine = self._state_machine_factory.CreateMachine( 350 pm_constants.STATE_MACHINE_CONNECT_CDMA, 351 self, 352 properties, 353 return_cb, 354 raise_cb) 355 machine.Start() 356 357 358 # Inherited from modem_simple.ModemSimple. 359 @utils.log_dbus_method(return_cb_arg='return_cb', raise_cb_arg='raise_cb') 360 def Disconnect(self, bearer_path, return_cb, raise_cb, *return_cb_args): 361 """ 362 Overridden from superclass. 363 364 @param bearer_path 365 @param return_cb 366 @param raise_cb 367 @param return_cb_args 368 369 """ 370 logging.info('ModemCdma.Disconnect: %s', bearer_path) 371 machine = self._state_machine_factory.CreateMachine( 372 pm_constants.STATE_MACHINE_DISCONNECT, 373 self, 374 bearer_path, 375 return_cb, 376 raise_cb, 377 return_cb_args) 378 machine.Start() 379 380 381 # Inherited from modem_simple.ModemSimple. 382 @utils.log_dbus_method() 383 def GetStatus(self): 384 """ Overridden from superclass. """ 385 modem_props = self.GetAll(mm1_constants.I_MODEM) 386 cdma_props = self.GetAll(mm1_constants.I_MODEM_CDMA) 387 retval = {} 388 retval['state'] = modem_props['State'] 389 if retval['state'] >= mm1_constants.MM_MODEM_STATE_REGISTERED: 390 retval['signal-quality'] = modem_props['SignalQuality'][0] 391 retval['bands'] = modem_props['CurrentBands'] 392 retval['cdma-cdma1x-registration-state'] = \ 393 cdma_props['Cdma1xRegistrationState'] 394 retval['cdma-evdo-registration-state'] = \ 395 cdma_props['EvdoRegistrationState'] 396 retval['cdma-sid'] = cdma_props['Sid'] 397 retval['cdma-nid'] = cdma_props['Nid'] 398 return retval 399