• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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