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