| # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import connect_machine |
| import dbus |
| import dbus.types |
| import disconnect_machine |
| import gobject |
| import logging |
| import mm1 |
| import modem |
| import pseudomodem |
| import register_machine |
| |
| class Modem3gpp(modem.Modem): |
| """ |
| Pseudomodem implementation of the |
| org.freedesktop.ModemManager1.Modem.Modem3gpp and |
| org.freedesktop.ModemManager1.Modem.Simple interfaces. This class provides |
| access to specific actions that may be performed in modems with 3GPP |
| capabilities. |
| |
| """ |
| |
| class GsmNetwork(object): |
| def __init__(self, |
| operator_long, |
| operator_short, |
| operator_code, |
| status, |
| access_technology): |
| self.status = status |
| self.operator_long = operator_long |
| self.operator_short = operator_short |
| self.operator_code = operator_code |
| self.access_technology = access_technology |
| |
| def _InitializeProperties(self): |
| ip = modem.Modem._InitializeProperties(self) |
| ip[mm1.I_MODEM_3GPP] = { |
| 'Imei' : '00112342342', |
| 'RegistrationState' : ( |
| dbus.types.UInt32(mm1.MM_MODEM_3GPP_REGISTRATION_STATE_IDLE)), |
| 'OperatorCode' : '', |
| 'OperatorName' : '', |
| 'EnabledFacilityLocks' : ( |
| dbus.types.UInt32(mm1.MM_MODEM_3GPP_FACILITY_NONE)) |
| } |
| |
| props = ip[mm1.I_MODEM] |
| props['ModemCapabilities'] = dbus.types.UInt32( |
| mm1.MM_MODEM_CAPABILITY_GSM_UMTS | mm1.MM_MODEM_CAPABILITY_LTE) |
| props['CurrentCapabilities'] = dbus.types.UInt32( |
| mm1.MM_MODEM_CAPABILITY_GSM_UMTS | mm1.MM_MODEM_CAPABILITY_LTE) |
| props['MaxBearers'] = dbus.types.UInt32(3) |
| props['MaxActiveBearers'] = dbus.types.UInt32(2) |
| props['EquipmentIdentifier'] = ip[mm1.I_MODEM_3GPP]['Imei'] |
| props['AccessTechnologies'] = dbus.types.UInt32(( |
| mm1.MM_MODEM_ACCESS_TECHNOLOGY_GSM | |
| mm1.MM_MODEM_ACCESS_TECHNOLOGY_UMTS)) |
| props['SupportedModes'] = dbus.types.UInt32(mm1.MM_MODEM_MODE_ANY) |
| props['AllowedModes'] = props['SupportedModes'] |
| props['PreferredMode'] = dbus.types.UInt32(mm1.MM_MODEM_MODE_NONE) |
| props['SupportedBands'] = [ |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_EGSM), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_DCS), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_PCS), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_G850), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U2100), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U1800), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U17IV), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U800), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U850) |
| ] |
| props['Bands'] = [ |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_EGSM), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_DCS), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_PCS), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_G850), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U2100), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U800), |
| dbus.types.UInt32(mm1.MM_MODEM_BAND_U850) |
| ] |
| return ip |
| |
| def SetRegistrationState(self, state): |
| self.SetUInt32( |
| mm1.I_MODEM_3GPP, 'RegistrationState', dbus.types.UInt32(state)) |
| |
| @dbus.service.method(mm1.I_MODEM_3GPP, in_signature='s') |
| def Register(self, operator_id, *args): |
| """ |
| Request registration with a given modem network. |
| |
| Args: |
| operator_id -- The operator ID to register. An empty string can be |
| used to register to the home network. |
| *args -- Args can optionally contain an operator name. |
| |
| """ |
| logging.info('Modem3gpp.Register: %s', operator_id) |
| if operator_id: |
| assert self.sim |
| assert self.Get(mm1.I_MODEM, 'Sim') != mm1.ROOT_PATH |
| if operator_id == self.sim.Get(mm1.I_SIM, 'OperatorIdentifier'): |
| state = mm1.MM_MODEM_3GPP_REGISTRATION_STATE_HOME |
| else: |
| state = mm1.MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING |
| else: |
| state = mm1.MM_MODEM_3GPP_REGISTRATION_STATE_HOME |
| |
| logging.info('Modem3gpp.Register: Setting registration state to %s.', |
| mm1.RegistrationStateToString(state)) |
| self.SetRegistrationState(state) |
| logging.info('Modem3gpp.Register: Setting state to REGISTERED.') |
| self.ChangeState(mm1.MM_MODEM_STATE_REGISTERED, |
| mm1.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED) |
| self.Set(mm1.I_MODEM_3GPP, 'OperatorCode', operator_id) |
| if args: |
| self.Set(mm1.I_MODEM_3GPP, 'OperatorName', args[0]) |
| |
| @dbus.service.method(mm1.I_MODEM_3GPP, out_signature='aa{sv}') |
| def Scan(self): |
| """ |
| Scan for available networks. |
| |
| Returns: |
| An array of dictionaries with each array element describing a |
| mobile network found in the scan. See the ModemManager reference |
| manual for the list of keys that may be included in the returned |
| dictionary. |
| |
| """ |
| state = self.Get(mm1.I_MODEM, 'State') |
| if state < mm1.MM_MODEM_STATE_ENABLED: |
| raise mm1.MMCoreError(mm1.MMCoreError.WRONG_STATE, |
| 'Modem not enabled, cannot scan for networks.') |
| |
| sim_path = self.Get(mm1.I_MODEM, 'Sim') |
| if not self.sim: |
| assert sim_path == mm1.ROOT_PATH |
| raise mm1.MMMobileEquipmentError( |
| mm1.MMMobileEquipmentError.SIM_NOT_INSERTED, |
| 'Cannot scan for networks because no SIM is inserted.') |
| assert sim_path != mm1.ROOT_PATH |
| |
| # TODO(armansito): check here for SIM lock? |
| |
| scanned = [network.__dict__ for network in self.roaming_networks] |
| |
| # get home network |
| sim_props = self.sim.GetAll(mm1.I_SIM) |
| scanned.append({ |
| 'status': mm1.MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE, |
| 'operator-long': sim_props['OperatorName'], |
| 'operator-short': sim_props['OperatorName'], |
| 'operator-code': sim_props['OperatorIdentifier'], |
| 'access-technology': self.sim.access_technology |
| }) |
| return scanned |
| |
| def RegisterWithNetwork(self): |
| register_machine.RegisterMachine(self).Step() |
| |
| def UnregisterWithNetwork(self): |
| logging.info('Modem3gpp.UnregisterWithHomeNetwork') |
| logging.info('Setting registration state to IDLE.') |
| self.SetRegistrationState(mm1.MM_MODEM_3GPP_REGISTRATION_STATE_IDLE) |
| logging.info('Setting state to ENABLED.') |
| self.ChangeState(mm1.MM_MODEM_STATE_ENABLED, |
| mm1.MM_MODEM_STATE_CHANGE_REASON_USER_REQUESTED) |
| self.Set(mm1.I_MODEM_3GPP, 'OperatorName', '') |
| self.Set(mm1.I_MODEM_3GPP, 'OperatorCode', '') |
| |
| def Connect(self, properties, return_cb, raise_cb): |
| logging.info('Connect') |
| connect_machine.ConnectMachine( |
| self, properties, return_cb, raise_cb).Step() |
| |
| def Disconnect(self, bearer_path, return_cb, raise_cb, *return_cb_args): |
| logging.info('Disconnect: %s' % bearer_path) |
| disconnect_machine.DisconnectMachine( |
| self, bearer_path, return_cb, raise_cb, return_cb_args).Step() |
| |
| def GetStatus(self): |
| modem_props = self.GetAll(mm1.I_MODEM) |
| m3gpp_props = self.GetAll(mm1.I_MODEM_3GPP) |
| retval = {} |
| retval['state'] = modem_props['State'] |
| if retval['state'] == mm1.MM_MODEM_STATE_REGISTERED: |
| retval['signal-quality'] = modem_props['SignalQuality'][0] |
| retval['bands'] = modem_props['Bands'] |
| retval['access-technology'] = self.sim.access_technology |
| retval['m3gpp-registration-state'] = \ |
| m3gpp_props['RegistrationState'] |
| retval['m3gpp-operator-code'] = m3gpp_props['OperatorCode'] |
| retval['m3gpp-operator-name'] = m3gpp_props['OperatorName'] |
| return retval |
| # TODO(armansito): implement |
| # org.freedesktop.ModemManager1.Modem.Modem3gpp.Ussd, if needed |
| # (in a separate class?) |