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