1# Copyright (c) 2013 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# Setup wardmodem package root and other autotest paths.
6import common
7
8import state_machine
9
10class ModemPowerLevelMachine(state_machine.StateMachine):
11    """
12    The state machine that determines the functionality level of the modem.
13
14    Setting the funtionality to different levels enables/disables various
15    operations one can perform with the modem.
16
17    """
18
19    def __init__(self, state, transceiver, modem_conf):
20        """
21        @param state: The GlobalState object shared by all state machines.
22
23        @param transceiver: The ATTransceiver object to interact with.
24
25        @param modem_conf: A ModemConfiguration object containing the
26                configuration data for the current modem.
27
28        """
29        super(ModemPowerLevelMachine, self).__init__(state, transceiver,
30                                                     modem_conf)
31
32        # Register all wardmodem responses used.
33        self._add_response_function('wm_response_power_level_minimal')
34        self._add_response_function('wm_response_power_level_full')
35        self._add_response_function('wm_response_power_level_low')
36        self._add_response_function('wm_response_power_level_factory_test')
37        self._add_response_function('wm_response_power_level_offline')
38
39        # Load configuration for this state machine.
40        self._allowed_levels = modem_conf.modem_power_level_allowed_levels
41        self._reset_by_default = modem_conf.modem_power_level_reset_by_default
42
43        self._state['power_level'] = modem_conf.modem_power_level_initial_level
44        self._logger.debug(self._tag_with_name('Initialized power level to %s' %
45                                               self._state['power_level']))
46
47
48    def get_well_known_name(self):
49        """ Returns the well known name for this machine. """
50        return 'modem_power_level_machine'
51
52
53    # ##########################################################################
54    # State machine API functions.
55    def soft_reset(self):
56        """
57        Soft reset the modem.
58        """
59        # In the future, we might want to simulate a reset by hiding the udev
60        # device exposed to the modemmanager.
61        self._logger.info(self._tag_with_name('Soft reset called.'))
62        pass
63
64
65    def get_current_level(self):
66        """ Return the current power level. """
67        level = self._state['power_level']
68        if level == 'MINIMUM':
69            self._respond(self.wm_response_power_level_minimum)
70        elif level == 'FULL':
71            self._respond(self.wm_response_power_level_full)
72        elif level == 'LOW':
73            self._respond(self.wm_response_power_level_low)
74        elif level == 'FACTORY_TEST':
75            self._respond(self.wm_response_power_level_factory_test)
76        elif level == 'OFFLINE':
77            self._respond(self.wm_response_power_level_offline)
78        else:
79            self._raise_runtime_error('Read invalid current power level value '
80                                      '|%s|', level)
81        self._respond_ok()
82
83
84    def set_level_minimum(self):
85        """ Set the power level to MINIMUM. """
86        self._set_level('MINIMUM')
87        self._task_loop.post_task(
88                self._registration_machine().deregister)
89
90
91    def set_level_full(self):
92        """ Set the power level to FULL. """
93        self._set_level('FULL')
94        if self._state['automatic_registration'] == 'TRUE':
95            self._task_loop.post_task(
96                    self._registration_machine().register)
97
98
99
100    def set_level_low(self):
101        """ Set the power level to LOW. """
102        self._set_level('LOW')
103        self._task_loop.post_task(
104                self._registration_machine().deregister)
105
106
107    # ##########################################################################
108    # Helper functions.
109    def _set_level(self, level, reset_code=None):
110        """
111        Set the power/functionality level to the specified value.
112
113        @param level: Integer level to set the power to.
114
115        @param reset_code: If '1', a soft reset is called on the device. Default
116                value used is specified in the configuration file.
117
118        """
119        if reset_code is None:
120            reset = self._reset_by_default
121        elif reset_code not in ['0', '1']:
122            self._raise_runtime_error("Expected reset to be '0' or '1', found "
123                                      "|%s|" % str(reset))
124        else:
125            reset = (reset_code == '1')
126
127        if level not in self._allowed_levels:
128            self._respond_error()
129            return
130
131        if reset or level == 'RESET':
132            self.soft_reset()
133        if level == 'FULL':
134            self._update_state({'power_level': level})
135        elif level == 'LOW' or level == 'MINIMUM':
136            self._update_state({
137                'power_level': level,
138                'registration_status': 'NOT_REGISTERED',
139                'call_status': 'DISCONNECTED',
140                'level_call': 0})
141        self._respond_ok()
142
143
144    # ##########################################################################
145    # Helper methods.
146    def _registration_machine(self):
147        # This machine may not have been created when __init__ is executed.
148        # Obtain a fresh handle everytime we want to use it.
149        return self._transceiver.get_state_machine(
150                'network_registration_machine')
151