Home | History | Annotate | Download | only in wardmodem
      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 logging
      6 import os
      7 import pprint
      8 import sys
      9 
     10 import wardmodem_exceptions as wme
     11 
     12 CONF_DIR_NAME = 'configurations'
     13 DEFAULT_CONF_FILE = 'base.conf'
     14 MODEM_CONF_FILE = {
     15         'e362': 'e362.conf',
     16 }
     17 
     18 class ModemConfiguration(object):
     19     """
     20     All modem specific configuration needed by WardModem.
     21 
     22     This class serves the dual purpose of loading the configuration data needed
     23     by different parts of wardmodem in a single place, and providing
     24     documentation regarding the configuration parameters available in the file.
     25 
     26     """
     27 
     28     def __init__(self, modem=None):
     29         """
     30         @param modem The modem for which the configuration needs to be loaded.
     31                 |modem| can be None. In that case, only the configuration for
     32                 the base modem is loaded.
     33                 Otherwise, |modem| must be a key in |MODEM_CONF_FILE|.
     34         """
     35         self._logger = logging.getLogger(__name__)
     36 
     37         if modem and modem not in MODEM_CONF_FILE:
     38             raise wme.WardModemSetupException('Unknown modem: |%s|' % modem)
     39 
     40         # TODO(pprabhu) Figure out if it makes sense to use Configurable to
     41         # (de)serialize configuration. See crbug.com/252475
     42         # First load the default configuration
     43         self._logger.info('Loading basic configuration.')
     44         self.base_conf = self._load_conf(DEFAULT_CONF_FILE)
     45         self._logger.debug('Basic configuration:\n%s',
     46                            pprint.pformat(self.base_conf))
     47 
     48         # Now load the plugin conf data.
     49         self.plugin_conf = {}
     50         if modem:
     51             self._logger.info('Loading modem specific configuration for modem '
     52                               '|%s|', modem)
     53             self.plugin_conf = self._load_conf(MODEM_CONF_FILE[modem])
     54         self._logger.debug('Plugin configuration:\n%s',
     55                            pprint.pformat(self.plugin_conf))
     56 
     57         self._populate_config()
     58 
     59 
     60     def _populate_config(self):
     61         """
     62         Assign configuration data loaded into self variable for easy access.
     63 
     64         """
     65         # The basic map from AT commands to wardmodem actions common to all
     66         # modems.
     67         self.base_at_to_wm_action_map = self.base_conf['at_to_wm_action_map']
     68 
     69         # The map from AT commands to wardmodem actions specific to the current
     70         # modem.
     71         self.plugin_at_to_wm_action_map = (
     72                 self.plugin_conf.get('at_to_wm_action_map', {}))
     73 
     74         # The basic map from wardmodem responses to AT commands common to all
     75         # modems.
     76         self.base_wm_response_to_at_map = (
     77                 self.base_conf['wm_response_to_at_map'])
     78 
     79         # The map from wardmodem responses to AT commands specific to the
     80         # current modem.
     81         self.plugin_wm_response_to_at_map = (
     82                 self.plugin_conf.get('wm_response_to_at_map', {}))
     83 
     84         # State-less request response map.
     85         self.base_wm_request_response_map = (
     86                 self.base_conf.get('wm_request_response_map', {}))
     87         self.plugin_wm_request_response_map = (
     88                 self.plugin_conf.get('wm_request_response_map', {}))
     89 
     90         # The state machines loaded by all modems.
     91         self.base_state_machines = self.base_conf['state_machines']
     92 
     93         # The state machines specific to the current modem.
     94         self.plugin_state_machines =  self.plugin_conf.get('state_machines', [])
     95 
     96         # The fallback state machine for unmatched AT commands.
     97         self._load_variable('fallback_machine', strict=False, default='')
     98         self._load_variable('fallback_function', strict=False, default='')
     99 
    100 
    101         # The modemmanager plugin to be used for the modem.
    102         self._load_variable('mm_plugin')
    103 
    104         # The string to be prepended to all AT commands from modemmanager to
    105         # modem.
    106         self._load_variable('mm_to_modem_at_prefix')
    107 
    108         # The string to be appended to all AT commands from modemmanager to
    109         # modem.
    110         self._load_variable('mm_to_modem_at_suffix')
    111 
    112         # The string to be prepended to all AT commands from modem to
    113         # modemmanager.
    114         self._load_variable('modem_to_mm_at_prefix')
    115 
    116         # The string to be appended to all AT commands from modem to
    117         # modemmanager.
    118         self._load_variable('modem_to_mm_at_suffix')
    119 
    120         # ######################################################################
    121         # Configuration data for various state machines.
    122         self._load_variable('modem_power_level_allowed_levels')
    123         self._load_variable('modem_power_level_initial_level')
    124         self._load_variable('modem_power_level_reset_by_default')
    125 
    126         self._load_variable('network_identity_default_mcc')
    127         self._load_variable('network_identity_default_mnc')
    128         self._load_variable('network_identity_default_msin')
    129         self._load_variable('network_identity_default_mdn')
    130 
    131         self._load_variable('network_operators')
    132         self._load_variable('network_operator_default_index')
    133 
    134         self._load_variable('level_indicators_items')
    135         self._load_variable('level_indicators_defaults')
    136 
    137 
    138     def _load_variable(self, varname, strict=True, default=None):
    139         """
    140         Load a variable from the configuration files.
    141 
    142         Implement the most common way of loading variables from configuration.
    143 
    144         @param varname: The name of the variable to load.
    145 
    146         @param strict: If True, we expect some value to be available.
    147 
    148         @param default: Value to assign if none can be loaded. Only makes sense
    149                 when |strint| is False.
    150 
    151         """
    152         if strict:
    153             value = self.plugin_conf.get(varname, self.base_conf[varname])
    154         else:
    155             value = self.plugin_conf.get(varname,
    156                                          self.base_conf.get(varname, default))
    157         setattr(self, varname, value)
    158 
    159 
    160     def _load_conf(self, conf_file):
    161         """
    162         Load the configuration data from file.
    163 
    164         @param conf_file Name of the file to load from.
    165 
    166         @return The conf data loaded from file.
    167 
    168         """
    169         # The configuration file is an executable python file. Since the file
    170         # name is known only at run-time, we must find the module directory and
    171         # manually point execfile to the directory for loading the configuration
    172         # file.
    173         current_module = sys.modules[__name__]
    174         dir_name = os.path.dirname(current_module.__file__)
    175         full_path = os.path.join(dir_name, CONF_DIR_NAME, conf_file)
    176         conf = {}
    177         execfile(full_path, conf)
    178         # These entries added by execfile are a nuisance in pprint'ing
    179         del conf['__builtins__']
    180         return conf
    181