Home | History | Annotate | Download | only in state_machines
      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 import state_machine
      6 
      7 class NetworkOperatorMachine(state_machine.StateMachine):
      8     """
      9     This state machine controls the network operator that the modem connects to,
     10     and also the technology used to associate with the network.
     11 
     12     """
     13 
     14     OPERATOR_FORMAT_CODE = {
     15             'LONG_ALPHANUMERIC': '0',
     16             'SHORT_ALPHANUMERIC': '1',
     17             'NUMERIC': '2',
     18     }
     19 
     20     OPERATOR_FORMAT_STATE = {
     21             '0': 'LONG_ALPHANUMERIC',
     22             '1': 'SHORT_ALPHANUMERIC',
     23             '2': 'NUMERIC',
     24     }
     25 
     26     TECHNOLOGY_CODE = {
     27             'GSM': '0',
     28             'GSM_COMPAT' : '1',
     29             'UTRAN': '2',
     30             'GSM_EGPRS': '3',
     31             'UTRAN_HSDPA': '4',
     32             'UTRAN_HSUPA': '5',
     33             'UTRAN_HSDPA_HSUPA': '6',
     34             'E_UTRAN': '7',
     35     }
     36 
     37     def __init__(self, state, transceiver, modem_conf):
     38         """
     39         @param state: The GlobalState object shared by all state machines.
     40 
     41         @param transceiver: The ATTransceiver object to interact with.
     42 
     43         @param modem_conf: A ModemConfiguration object containing the
     44                 configuration data for the current modem.
     45 
     46         """
     47         super(NetworkOperatorMachine, self).__init__(state, transceiver,
     48                                                      modem_conf)
     49 
     50         # Register all responses.
     51         self._add_response_function('wm_response_operator_name')
     52         self._add_response_function('wm_response_operator_name_none')
     53 
     54 
     55         # Load configuration
     56         self._operators = modem_conf.network_operators
     57         self._default_operator_index = modem_conf.network_operator_default_index
     58 
     59         # Initialize state
     60         self._state['operator_index'] = self._default_operator_index
     61         self._state['automatic_registration'] = 'TRUE'
     62         self._state['access_technology'] = self._extract_technology(
     63                 self._default_operator_index)
     64 
     65     def get_well_known_name(self):
     66         """ Returns the well known name for this machine. """
     67         return 'network_operator_machine'
     68 
     69 
     70     # ##########################################################################
     71     # State machine API functions.
     72     def set_operator_format(self, format_code):
     73         """
     74         Sets the operator name reporting format.
     75 
     76         @param format_code: The format in which operator is reported.
     77                 Type: str.  Valid arguments are ['0', '1', '2'], as specified by
     78                 the AT specification.
     79 
     80         """
     81         operator_format = self.OPERATOR_FORMAT_STATE.get(format_code)
     82         if not operator_format:
     83             self._raise_runtime_error(self._tag_with_name(
     84                 'Unknown operator format code |%s|' % format_code))
     85 
     86         self._update_state({'operator_format': operator_format})
     87         self._respond_ok()
     88 
     89 
     90     def set_operator_autoselect(self):
     91         """
     92         Enable automatic selection and registration to the default operator.
     93 
     94         """
     95         self._update_state({'automatic_registration': 'TRUE'})
     96 
     97         technology = self._extract_technology(self._default_operator_index)
     98         self._update_state({'operator_index': self._default_operator_index,
     99                             'access_technology': technology})
    100 
    101         self._task_loop.post_task_after_delay(
    102                 self._registration_machine().register,
    103                 0)
    104 
    105         self._respond_ok()
    106 
    107 
    108     def get_operator_name(self):
    109         """ Report the current operator selected. """
    110         operator_format = self._state['operator_format']
    111         format_code = self.OPERATOR_FORMAT_CODE[operator_format]
    112         operator_index = self._state['operator_index']
    113 
    114         if operator_index == self._state.INVALID_VALUE:
    115             # No operator has been selected.
    116             self._respond(self.wm_response_operator_name_none, 0,
    117                           format_code)
    118         else:
    119             self._respond(self.wm_response_operator_name, 0,
    120                           format_code,
    121                           self._extract_operator_name(operator_index,
    122                                                       operator_format))
    123         self._respond_ok()
    124 
    125     # ##########################################################################
    126     # API methods for other state machines.
    127     def get_current_technology_code(self):
    128         """
    129         Return the currently selected technology encoded correctly for the
    130         +COPS? response.
    131 
    132         """
    133         return self.TECHNOLOGY_CODE[self._state['access_technology']]
    134 
    135 
    136     # ##########################################################################
    137     # Helper methods.
    138     def _extract_operator_name(self, index, operator_format):
    139         try:
    140             operator = self._operators[index]
    141         except IndexError as e:
    142             self._raise_runtime_error(
    143                     'Not sufficient names in operator name list. '
    144                     'Requested index: %s. Operator list: %s' %
    145                     (index, str(self._operators)))
    146         return operator[operator_format]
    147 
    148 
    149     def _extract_technology(self, index):
    150         try:
    151             operator = self._operators[index]
    152         except IndexError as e:
    153             self._raise_runtime_error(
    154                     'Not sufficient names in operator name list. '
    155                     'Requested index: %d. Operator list: %s' %
    156                     (index, str(self._operators)))
    157         return operator['TECHNOLOGY']
    158 
    159 
    160     def _registration_machine(self):
    161         # This machine may not have been created when __init__ is executed.
    162         # Obtain a fresh handle everytime we want to use it.
    163         return self._transceiver.get_state_machine(
    164                 'network_registration_machine')
    165