aboutsummaryrefslogtreecommitdiff
path: root/test/mm-test.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/mm-test.py')
-rwxr-xr-xtest/mm-test.py527
1 files changed, 527 insertions, 0 deletions
diff --git a/test/mm-test.py b/test/mm-test.py
new file mode 100755
index 0000000..99a355f
--- /dev/null
+++ b/test/mm-test.py
@@ -0,0 +1,527 @@
+#!/usr/bin/python
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details:
+#
+# Copyright (C) 2008 Novell, Inc.
+# Copyright (C) 2009 Red Hat, Inc.
+#
+
+import sys, dbus, time, os, string, subprocess, socket
+
+DBUS_INTERFACE_PROPERTIES='org.freedesktop.DBus.Properties'
+MM_DBUS_SERVICE='org.freedesktop.ModemManager'
+MM_DBUS_PATH='/org/freedesktop/ModemManager'
+MM_DBUS_INTERFACE='org.freedesktop.ModemManager'
+MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
+MM_DBUS_INTERFACE_MODEM_CDMA='org.freedesktop.ModemManager.Modem.Cdma'
+MM_DBUS_INTERFACE_MODEM_GSM_CARD='org.freedesktop.ModemManager.Modem.Gsm.Card'
+MM_DBUS_INTERFACE_MODEM_GSM_NETWORK='org.freedesktop.ModemManager.Modem.Gsm.Network'
+MM_DBUS_INTERFACE_MODEM_SIMPLE='org.freedesktop.ModemManager.Modem.Simple'
+
+def get_cdma_band_class(band_class):
+ if band_class == 1:
+ return "800MHz"
+ elif band_class == 2:
+ return "1900MHz"
+ else:
+ return "Unknown"
+
+def get_reg_state(state):
+ if state == 1:
+ return "registered (roaming unknown)"
+ elif state == 2:
+ return "registered on home network"
+ elif state == 3:
+ return "registered on roaming network"
+ else:
+ return "unknown"
+
+def cdma_inspect(proxy, dump_private):
+ cdma = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_CDMA)
+
+ esn = "<private>"
+ if dump_private:
+ try:
+ esn = cdma.GetEsn()
+ except dbus.exceptions.DBusException:
+ esn = "<unavailable>"
+
+ print ""
+ print "ESN: %s" % esn
+
+ try:
+ (cdma_1x_state, evdo_state) = cdma.GetRegistrationState()
+ print "1x State: %s" % get_reg_state (cdma_1x_state)
+ print "EVDO State: %s" % get_reg_state (evdo_state)
+ except dbus.exceptions.DBusException, e:
+ print "Error reading registration state: %s" % e
+
+ try:
+ quality = cdma.GetSignalQuality()
+ print "Signal quality: %d" % quality
+ except dbus.exceptions.DBusException, e:
+ print "Error reading signal quality: %s" % e
+
+ try:
+ info = cdma.GetServingSystem()
+ print "Class: %s" % get_cdma_band_class(info[0])
+ print "Band: %s" % info[1]
+ print "SID: %d" % info[2]
+ except dbus.exceptions.DBusException, e:
+ print "Error reading serving system: %s" % e
+
+def cdma_connect(proxy, user, password):
+ # Modem.Simple interface
+ simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
+ try:
+ simple.Connect({'number':"#777"}, timeout=92)
+ print "\nConnected!"
+ return True
+ except Exception, e:
+ print "Error connecting: %s" % e
+ return False
+
+
+def get_gsm_network_mode(modem):
+ mode = modem.GetNetworkMode()
+ if mode == 0x0:
+ mode = "Unknown"
+ elif mode == 0x1:
+ mode = "Any"
+ elif mode == 0x2:
+ mode = "GPRS"
+ elif mode == 0x4:
+ mode = "EDGE"
+ elif mode == 0x8:
+ mode = "UMTS"
+ elif mode == 0x10:
+ mode = "HSDPA"
+ elif mode == 0x20:
+ mode = "2G Preferred"
+ elif mode == 0x40:
+ mode = "3G Preferred"
+ elif mode == 0x80:
+ mode = "2G Only"
+ elif mode == 0x100:
+ mode = "3G Only"
+ elif mode == 0x200:
+ mode = "HSUPA"
+ elif mode == 0x400:
+ mode = "HSPA"
+ else:
+ mode = "(Unknown)"
+
+ print "Mode: %s" % mode
+
+def get_gsm_band(modem):
+ band = modem.GetBand()
+ if band == 0x0:
+ band = "Unknown"
+ elif band == 0x1:
+ band = "Any"
+ elif band == 0x2:
+ band = "EGSM (900 MHz)"
+ elif band == 0x4:
+ band = "DCS (1800 MHz)"
+ elif band == 0x8:
+ band = "PCS (1900 MHz)"
+ elif band == 0x10:
+ band = "G850 (850 MHz)"
+ elif band == 0x20:
+ band = "U2100 (WCSMA 2100 MHZ, Class I)"
+ elif band == 0x40:
+ band = "U1700 (WCDMA 3GPP UMTS1800 MHz, Class III)"
+ elif band == 0x80:
+ band = "17IV (WCDMA 3GPP AWS 1700/2100 MHz, Class IV)"
+ elif band == 0x100:
+ band = "U800 (WCDMA 3GPP UMTS800 MHz, Class VI)"
+ elif band == 0x200:
+ band = "U850 (WCDMA 3GPP UMT850 MHz, Class V)"
+ elif band == 0x400:
+ band = "U900 (WCDMA 3GPP UMTS900 MHz, Class VIII)"
+ elif band == 0x800:
+ band = "U17IX (WCDMA 3GPP UMTS MHz, Class IX)"
+ else:
+ band = "(invalid)"
+
+ print "Band: %s" % band
+
+
+def gsm_inspect(proxy, dump_private, do_scan):
+ # Gsm.Card interface
+ card = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_CARD)
+
+ imei = "<private>"
+ imsi = "<private>"
+ if dump_private:
+ try:
+ imei = card.GetImei()
+ except dbus.exceptions.DBusException:
+ imei = "<unavailable>"
+ try:
+ imsi = card.GetImsi()
+ except dbus.exceptions.DBusException:
+ imsi = "<unavailable>"
+
+ print "IMEI: %s" % imei
+ print "IMSI: %s" % imsi
+
+ # Gsm.Network interface
+ net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
+ try:
+ quality = net.GetSignalQuality()
+ print "Signal quality: %d" % quality
+ except dbus.exceptions.DBusException, e:
+ print "Error reading signal quality: %s" % e
+
+ if not do_scan:
+ return
+
+ print "Scanning..."
+ try:
+ results = net.Scan(timeout=120)
+ except dbus.exceptions.DBusException, e:
+ print "Error scanning: %s" % e
+ results = {}
+
+ for r in results:
+ status = r['status']
+ if status == "1":
+ status = "available"
+ elif status == "2":
+ status = "current"
+ elif status == "3":
+ status = "forbidden"
+ else:
+ status = "(Unknown)"
+
+ access_tech = ""
+ try:
+ access_tech_num = r['access-tech']
+ if access_tech_num == "0":
+ access_tech = "(GSM)"
+ elif access_tech_num == "1":
+ access_tech = "(Compact GSM)"
+ elif access_tech_num == "2":
+ access_tech = "(UMTS)"
+ elif access_tech_num == "3":
+ access_tech = "(EDGE)"
+ elif access_tech_num == "4":
+ access_tech = "(HSDPA)"
+ elif access_tech_num == "5":
+ access_tech = "(HSUPA)"
+ elif access_tech_num == "6":
+ access_tech = "(HSPA)"
+ except KeyError:
+ pass
+
+ if r.has_key('operator-long') and len(r['operator-long']):
+ print "%s: %s %s" % (r['operator-long'], status, access_tech)
+ elif r.has_key('operator-short') and len(r['operator-short']):
+ print "%s: %s %s" % (r['operator-short'], status, access_tech)
+ else:
+ print "%s: %s %s" % (r['operator-num'], status, access_tech)
+
+def gsm_connect(proxy, apn, user, password):
+ # Modem.Simple interface
+ simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
+ try:
+ opts = {'number':"*99#"}
+ if apn is not None:
+ opts['apn'] = apn
+ if user is not None:
+ opts['username'] = user
+ if password is not None:
+ opts['password'] = password
+ simple.Connect(opts, timeout=120)
+ print "\nConnected!"
+ return True
+ except Exception, e:
+ print "Error connecting: %s" % e
+ return False
+
+def pppd_find():
+ paths = ["/usr/local/sbin/pppd", "/usr/sbin/pppd", "/sbin/pppd"]
+ for p in paths:
+ if os.path.exists(p):
+ return p
+ return None
+
+def ppp_start(device, user, password, tmpfile):
+ path = pppd_find()
+ if not path:
+ return None
+
+ args = [path]
+ args += ["nodetach"]
+ args += ["lock"]
+ args += ["nodefaultroute"]
+ args += ["debug"]
+ if user:
+ args += ["user"]
+ args += [user]
+ args += ["noipdefault"]
+ args += ["115200"]
+ args += ["noauth"]
+ args += ["crtscts"]
+ args += ["modem"]
+ args += ["usepeerdns"]
+ args += ["ipparam"]
+
+ ipparam = ""
+ if user:
+ ipparam += user
+ ipparam += "+"
+ if password:
+ ipparam += password
+ ipparam += "+"
+ ipparam += tmpfile
+ args += [ipparam]
+
+ args += ["plugin"]
+ args += ["mm-test-pppd-plugin.so"]
+
+ args += [device]
+
+ return subprocess.Popen(args, close_fds=True, cwd="/", env={})
+
+def ppp_wait(p, tmpfile):
+ i = 0
+ while p.poll() == None and i < 30:
+ time.sleep(1)
+ if os.path.exists(tmpfile):
+ f = open(tmpfile, 'r')
+ stuff = f.read(500)
+ idx = string.find(stuff, "DONE")
+ f.close()
+ if idx >= 0:
+ return True
+ i += 1
+ return False
+
+def ppp_stop(p):
+ import signal
+ p.send_signal(signal.SIGTERM)
+ p.wait()
+
+def ntop_helper(ip):
+ ip = socket.ntohl(ip)
+ n1 = ip >> 24 & 0xFF
+ n2 = ip >> 16 & 0xFF
+ n3 = ip >> 8 & 0xFF
+ n4 = ip & 0xFF
+ a = "%c%c%c%c" % (n1, n2, n3, n4)
+ return socket.inet_ntop(socket.AF_INET, a)
+
+def static_start(iface, modem):
+ (addr_num, dns1_num, dns2_num, dns3_num) = modem.GetIP4Config()
+ addr = ntop_helper(addr_num)
+ dns1 = ntop_helper(dns1_num)
+ dns2 = ntop_helper(dns2_num)
+ configure_iface(iface, addr, 0, dns1, dns2)
+
+def down_iface(iface):
+ ip = ["ip", "addr", "flush", "dev", iface]
+ print " ".join(ip)
+ subprocess.call(ip)
+ ip = ["ip", "link", "set", iface, "down"]
+ print " ".join(ip)
+ subprocess.call(ip)
+
+def configure_iface(iface, addr, gw, dns1, dns2):
+ print "\n\n******************************"
+ print "iface: %s" % iface
+ print "addr: %s" % addr
+ print "gw: %s" % gw
+ print "dns1: %s" % dns1
+ print "dns2: %s" % dns2
+
+ ifconfig = ["ifconfig", iface, "%s/32" % addr]
+ if gw != 0:
+ ifconfig += ["pointopoint", gw]
+ print " ".join(ifconfig)
+ print "\n******************************\n"
+
+ subprocess.call(ifconfig)
+
+def file_configure_iface(tmpfile):
+ addr = None
+ gw = None
+ iface = None
+ dns1 = None
+ dns2 = None
+
+ f = open(tmpfile, 'r')
+ lines = f.readlines()
+ for l in lines:
+ if l.startswith("addr"):
+ addr = l[len("addr"):].strip()
+ if l.startswith("gateway"):
+ gw = l[len("gateway"):].strip()
+ if l.startswith("iface"):
+ iface = l[len("iface"):].strip()
+ if l.startswith("dns1"):
+ dns1 = l[len("dns1"):].strip()
+ if l.startswith("dns2"):
+ dns2 = l[len("dns2"):].strip()
+ f.close()
+
+ configure_iface(iface, addr, gw, dns1, dns2)
+ return iface
+
+def try_ping(iface):
+ cmd = ["ping", "-I", iface, "-c", "4", "-i", "3", "-w", "20", "4.2.2.1"]
+ print " ".join(cmd)
+ retcode = subprocess.call(cmd)
+ if retcode != 0:
+ print "PING: failed"
+ else:
+ print "PING: success"
+
+
+dump_private = False
+connect = False
+apn = None
+user = None
+password = None
+do_ip = False
+do_scan = True
+x = 1
+while x < len(sys.argv):
+ if sys.argv[x] == "--private":
+ dump_private = True
+ elif sys.argv[x] == "--connect":
+ connect = True
+ elif (sys.argv[x] == "--user" or sys.argv[x] == "--username"):
+ x += 1
+ user = sys.argv[x]
+ elif sys.argv[x] == "--apn":
+ x += 1
+ apn = sys.argv[x]
+ elif sys.argv[x] == "--password":
+ x += 1
+ password = sys.argv[x]
+ elif sys.argv[x] == "--ip":
+ do_ip = True
+ if os.geteuid() != 0:
+ print "You probably want to be root to use --ip"
+ sys.exit(1)
+ elif sys.argv[x] == "--no-scan":
+ do_scan = False
+ x += 1
+
+bus = dbus.SystemBus()
+
+# Get available modems:
+manager_proxy = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager')
+manager_iface = dbus.Interface(manager_proxy, dbus_interface='org.freedesktop.ModemManager')
+modems = manager_iface.EnumerateDevices()
+
+if not modems:
+ print "No modems found"
+ sys.exit(1)
+
+for m in modems:
+ connect_success = False
+ data_device = None
+
+ proxy = bus.get_object(MM_DBUS_SERVICE, m)
+
+ # Properties
+ props_iface = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Properties')
+
+ type = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Type')
+ if type == 1:
+ print "GSM modem"
+ elif type == 2:
+ print "CDMA modem"
+ else:
+ print "Invalid modem type: %d" % type
+
+ print "Driver: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Driver'))
+ print "Modem device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice'))
+ data_device = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Device')
+ print "Data device: '%s'" % data_device
+
+ # Modem interface
+ modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
+
+ try:
+ modem.Enable(True)
+ except dbus.exceptions.DBusException, e:
+ print "Error enabling modem: %s" % e
+ sys.exit(1)
+
+ info = modem.GetInfo()
+ print "Vendor: %s" % info[0]
+ print "Model: %s" % info[1]
+ print "Version: %s" % info[2]
+
+ if type == 1:
+ gsm_inspect(proxy, dump_private, do_scan)
+ if connect == True:
+ connect_success = gsm_connect(proxy, apn, user, password)
+ elif type == 2:
+ cdma_inspect(proxy, dump_private)
+ if connect == True:
+ connect_success = cdma_connect(proxy, user, password)
+ print
+
+ if connect_success and do_ip:
+ tmpfile = "/tmp/mm-test-%d.tmp" % os.getpid()
+ success = False
+ try:
+ ip_method = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'IpMethod')
+ if ip_method == 0:
+ # ppp
+ p = ppp_start(data_device, user, password, tmpfile)
+ if ppp_wait(p, tmpfile):
+ data_device = file_configure_iface(tmpfile)
+ success = True
+ elif ip_method == 1:
+ # static
+ static_start(data_device, modem)
+ success = True
+ elif ip_method == 2:
+ # dhcp
+ pass
+ except Exception, e:
+ print "Error setting up IP: %s" % e
+
+ if success:
+ try_ping(data_device)
+ print "Waiting for 30s..."
+ time.sleep(30)
+
+ print "Disconnecting..."
+ try:
+ if ip_method == 0:
+ ppp_stop(p)
+ try:
+ os.remove(tmpfile)
+ except:
+ pass
+ elif ip_method == 1:
+ # static
+ down_iface(data_device)
+ elif ip_method == 2:
+ # dhcp
+ down_iface(data_device)
+
+ modem.Disconnect()
+ except Exception, e:
+ print "Error tearing down IP: %s" % e
+
+ time.sleep(5)
+
+ modem.Enable(False)
+