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