Home | History | Annotate | Download | only in pseudomodem
      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 
      5 import logging
      6 
      7 import pm_errors
      8 import state_machine
      9 
     10 from autotest_lib.client.cros.cellular import mm1_constants
     11 
     12 class DisableMachine(state_machine.StateMachine):
     13     """
     14     DisableMachine handles the state transitions involved in bringing the modem
     15     to the DISABLED state.
     16 
     17     """
     18     def __init__(self, modem, return_cb, raise_cb):
     19         super(DisableMachine, self).__init__(modem)
     20         self.return_cb = return_cb
     21         self.raise_cb = raise_cb
     22 
     23 
     24     def _HandleConnectedState(self):
     25         logging.info('DisableMachine: Modem is CONNECTED.')
     26         assert self._modem.connect_step is None
     27         # TODO(armansito): Pass a different raise_cb here to handle
     28         # disconnect failure
     29         logging.info('DisableMachine: Starting Disconnect.')
     30         self._modem.Disconnect(mm1_constants.ROOT_PATH, DisableMachine.Step,
     31                                DisableMachine.Step, self)
     32         return True
     33 
     34 
     35     def _HandleConnectingState(self):
     36         logging.info('DisableMachine: Modem is CONNECTING.')
     37         assert self._modem.connect_step
     38         logging.info('DisableMachine: Canceling connect.')
     39         self._modem.connect_step.Cancel()
     40         return True
     41 
     42 
     43     def _HandleDisconnectingState(self):
     44         logging.info('DisableMachine: Modem is DISCONNECTING.')
     45         assert self._modem.disconnect_step
     46         logging.info('DisableMachine: Waiting for disconnect.')
     47         # wait until disconnect ends
     48         return True
     49 
     50 
     51     def _HandleRegisteredState(self):
     52         logging.info('DisableMachine: Modem is REGISTERED.')
     53         assert not self._modem.IsPendingRegister()
     54         assert not self._modem.IsPendingEnable()
     55         assert not self._modem.IsPendingConnect()
     56         assert not self._modem.IsPendingDisconnect()
     57         self._modem.UnregisterWithNetwork()
     58         logging.info('DisableMachine: Setting state to DISABLING.')
     59         reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED
     60         self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason)
     61         return True
     62 
     63 
     64     def _HandleSearchingState(self):
     65         logging.info('DisableMachine: Modem is SEARCHING.')
     66         assert self._modem.register_step
     67         assert not self._modem.IsPendingEnable()
     68         assert not self._modem.IsPendingConnect()
     69         logging.info('DisableMachine: Canceling register.')
     70         self._modem.register_step.Cancel()
     71         return True
     72 
     73 
     74     def _HandleEnabledState(self):
     75         logging.info('DisableMachine: Modem is ENABLED.')
     76         assert not self._modem.IsPendingRegister()
     77         assert not self._modem.IsPendingEnable()
     78         assert not self._modem.IsPendingConnect()
     79         logging.info('DisableMachine: Setting state to DISABLING.')
     80         reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED
     81         self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLING, reason)
     82         return True
     83 
     84 
     85     def _HandleDisablingState(self):
     86         logging.info('DisableMachine: Modem is DISABLING.')
     87         assert not self._modem.IsPendingRegister()
     88         assert not self._modem.IsPendingEnable()
     89         assert not self._modem.IsPendingConnect()
     90         assert not self._modem.IsPendingDisconnect()
     91         logging.info('DisableMachine: Setting state to DISABLED.')
     92         reason = mm1_constants.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED
     93         self._modem.ChangeState(mm1_constants.MM_MODEM_STATE_DISABLED, reason)
     94         self._modem.disable_step = None
     95         if self.return_cb:
     96             self.return_cb()
     97         return False
     98 
     99 
    100     def _GetModemStateFunctionMap(self):
    101         return {
    102             mm1_constants.MM_MODEM_STATE_CONNECTED:
    103                     DisableMachine._HandleConnectedState,
    104             mm1_constants.MM_MODEM_STATE_CONNECTING:
    105                     DisableMachine._HandleConnectingState,
    106             mm1_constants.MM_MODEM_STATE_DISCONNECTING:
    107                     DisableMachine._HandleDisconnectingState,
    108             mm1_constants.MM_MODEM_STATE_REGISTERED:
    109                     DisableMachine._HandleRegisteredState,
    110             mm1_constants.MM_MODEM_STATE_SEARCHING:
    111                     DisableMachine._HandleSearchingState,
    112             mm1_constants.MM_MODEM_STATE_ENABLED:
    113                     DisableMachine._HandleEnabledState,
    114             mm1_constants.MM_MODEM_STATE_DISABLING:
    115                     DisableMachine._HandleDisablingState
    116         }
    117 
    118 
    119     def _ShouldStartStateMachine(self):
    120         if self._modem.disable_step and self._modem.disable_step != self:
    121             # There is already a disable operation in progress.
    122             message = 'Modem disable already in progress.'
    123             logging.info(message)
    124             raise pm_errors.MMCoreError(pm_errors.MMCoreError.IN_PROGRESS,
    125                                         message)
    126         elif self._modem.disable_step is None:
    127             # There is no disable operation going in, cancelled or otherwise.
    128             state = self._modem.Get(mm1_constants.I_MODEM, 'State')
    129             if state == mm1_constants.MM_MODEM_STATE_DISABLED:
    130                 # The reason we're not raising an error here is that
    131                 # shill will make multiple successive calls to disable
    132                 # but WON'T check for raised errors, which causes
    133                 # problems. Treat this particular case as success.
    134                 logging.info('Already in a disabled state. Ignoring.')
    135                 if self.return_cb:
    136                     self.return_cb()
    137                 return False
    138 
    139             invalid_states = [
    140                 mm1_constants.MM_MODEM_STATE_FAILED,
    141                 mm1_constants.MM_MODEM_STATE_UNKNOWN,
    142                 mm1_constants.MM_MODEM_STATE_INITIALIZING,
    143                 mm1_constants.MM_MODEM_STATE_LOCKED
    144             ]
    145             if state in invalid_states:
    146                 raise pm_errors.MMCoreError(
    147                         pm_errors.MMCoreError.WRONG_STATE,
    148                         ('Modem disable cannot be initiated while in state'
    149                          ' %u.') % state)
    150             if self._modem.connect_step:
    151                 logging.info('There is an ongoing Connect, canceling it.')
    152                 self._modem.connect_step.Cancel()
    153             if self._modem.register_step:
    154                 logging.info('There is an ongoing Register, canceling it.')
    155                 self._modem.register_step.Cancel()
    156             if self._modem.enable_step:
    157                 # This needs to be done here, because the case where an enable
    158                 # cycle has been initiated but it hasn't triggered any state
    159                 # transitions yet would not be detected in a state handler.
    160                 logging.info('There is an ongoing Enable, canceling it.')
    161                 logging.info('This should bring the modem to a disabled state.'
    162                              ' DisableMachine will not start.')
    163                 self._modem.enable_step.Cancel()
    164                 assert self._modem.Get(mm1_constants.I_MODEM, 'State') == \
    165                     mm1_constants.MM_MODEM_STATE_DISABLED
    166             if self._modem.Get(mm1_constants.I_MODEM, 'State') == \
    167                     mm1_constants.MM_MODEM_STATE_DISABLED:
    168                 if self.return_cb:
    169                     self.return_cb()
    170                 return False
    171 
    172             logging.info('Starting Disable.')
    173             self._modem.disable_step = self
    174         return True
    175