Initial commit.
This commit is contained in:
30
Makefile.am
Normal file
30
Makefile.am
Normal file
@@ -0,0 +1,30 @@
|
||||
SUBDIRS = src plugins introspection
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = ModemManager.pc
|
||||
|
||||
dbusservicedir = $(DBUS_SYS_DIR)
|
||||
dbusservice_DATA = org.freedesktop.ModemManager.conf
|
||||
|
||||
dbusactivationdir = $(datadir)/dbus-1/system-services
|
||||
dbusactivation_in_files = org.freedesktop.ModemManager.service.in
|
||||
dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
|
||||
|
||||
%service: %service.in
|
||||
$(edit) $< >$@
|
||||
|
||||
edit = @sed \
|
||||
-e 's|@sbindir[@]|$(sbindir)|g' \
|
||||
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
|
||||
-e 's|@localstatedir[@]|$(localstatedir)|g' \
|
||||
-e 's|@libexecdir[@]|$(libexecdir)|g'
|
||||
|
||||
DISTCLEANFILES = \
|
||||
ModemManager.pc \
|
||||
$(dbusactivation_DATA)
|
||||
|
||||
|
||||
EXTRA_DIST = \
|
||||
ModemManager.pc.in \
|
||||
$(dbusservice_DATA) \
|
||||
$(dbusactivation_in_files)
|
12
ModemManager.pc.in
Normal file
12
ModemManager.pc.in
Normal file
@@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
libgnome_serverdir=@libexecdir@
|
||||
|
||||
Name: ModemManager
|
||||
Description: DBus service to interact with modems.
|
||||
Requires: dbus-glib-1 glib-2.0
|
||||
Version: @VERSION@
|
||||
Cflags: -I${includedir}/ModemManager
|
||||
Libs: -L${libdir} -lmm
|
20
autogen.sh
Executable file
20
autogen.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
REQUIRED_AUTOMAKE_VERSION=1.7
|
||||
PKG_NAME=ModemManager
|
||||
|
||||
(test -f $srcdir/configure.in \
|
||||
&& test -f $srcdir/src/mm-modem.c) || {
|
||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
||||
echo " top-level $PKG_NAME directory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
(cd $srcdir;
|
||||
autoreconf --install --symlink &&
|
||||
autoreconf &&
|
||||
./configure --enable-maintainer-mode $@
|
||||
)
|
24
configure.in
Normal file
24
configure.in
Normal file
@@ -0,0 +1,24 @@
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
AC_INIT(ModemManager, 0.1, tambet@gmail.com, ModemManager)
|
||||
AM_INIT_AUTOMAKE([])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
dnl Required programs
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
PKG_CHECK_MODULES(MM, dbus-glib-1 >= 0.75 glib-2.0 >= 2.14 gmodule-2.0 gobject-2.0 hal)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
plugins/Makefile
|
||||
introspection/Makefile
|
||||
ModemManager.pc
|
||||
])
|
||||
AC_OUTPUT
|
4
introspection/Makefile.am
Normal file
4
introspection/Makefile.am
Normal file
@@ -0,0 +1,4 @@
|
||||
EXTRA_DIST = \
|
||||
mm-manager.xml \
|
||||
mm-modem.xml
|
||||
|
19
introspection/mm-manager.xml
Normal file
19
introspection/mm-manager.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<node name="/">
|
||||
<interface name="org.freedesktop.ModemManager">
|
||||
<method name="EnumerateDevices">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_enumerate_devices"/>
|
||||
<arg name="devices" type="ao" direction="out"/>
|
||||
</method>
|
||||
|
||||
<signal name="DeviceAdded">
|
||||
<arg name="device" type="o"/>
|
||||
</signal>
|
||||
|
||||
<signal name="DeviceRemoved">
|
||||
<arg name="device" type="o"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
85
introspection/mm-modem.xml
Normal file
85
introspection/mm-modem.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<node name="/">
|
||||
<interface name="org.freedesktop.ModemManager.Modem">
|
||||
<method name="Enable">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_enable"/>
|
||||
<arg name="enable" type="b" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="SetPin">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_set_pin"/>
|
||||
<arg name="secret" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="Register">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_register"/>
|
||||
<arg name="network_id" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="Connect">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_connect"/>
|
||||
<arg name="number" type="s" direction="in"/>
|
||||
<arg name="apn" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="Disconnect">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_disconnect"/>
|
||||
</method>
|
||||
|
||||
<method name="Scan">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_scan"/>
|
||||
<arg name="results" type="aa{ss}" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="GetSignalQuality">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_get_signal_quality"/>
|
||||
<arg name="quality" type="u" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="SetBand">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_set_band"/>
|
||||
<arg name="band" type="u" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="GetBand">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_get_band"/>
|
||||
<arg name="band" type="u" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="SetNetworkMode">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_set_network_mode"/>
|
||||
<arg name="mode" type="u" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="GetNetworkMode">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_get_network_mode"/>
|
||||
<arg name="mode" type="u" direction="out"/>
|
||||
</method>
|
||||
|
||||
|
||||
<property name="DataDevice" type="s" access="read"/>
|
||||
<property name="Driver" type="s" access="read"/>
|
||||
<property name="Type" type="u" access="read"/>
|
||||
|
||||
<signal name="SignalQuality">
|
||||
<arg name="quality" type="u"/>
|
||||
</signal>
|
||||
|
||||
<signal name="NetworkMode">
|
||||
<arg name="mode" type="u"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
19
org.freedesktop.ModemManager.conf
Normal file
19
org.freedesktop.ModemManager.conf
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.ModemManager"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.ModemManager"/>
|
||||
<allow send_interface="org.freedesktop.ModemManager"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="org.freedesktop.ModemManager"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.ModemManager"/>
|
||||
<allow send_interface="org.freedesktop.ModemManager"/>
|
||||
</policy>
|
||||
|
||||
<limit name="max_replies_per_connection">512</limit>
|
||||
</busconfig>
|
4
org.freedesktop.ModemManager.service.in
Normal file
4
org.freedesktop.ModemManager.service.in
Normal file
@@ -0,0 +1,4 @@
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.ModemManager
|
||||
Exec=@sbindir@/modem-manager
|
||||
User=root
|
14
plugins/Makefile.am
Normal file
14
plugins/Makefile.am
Normal file
@@ -0,0 +1,14 @@
|
||||
pkglib_LTLIBRARIES = \
|
||||
libmm-plugin-huawei.la
|
||||
|
||||
libmm_plugin_huawei_la_SOURCES = \
|
||||
mm-modem-huawei.c \
|
||||
mm-modem-huawei.h \
|
||||
mm-plugin-huawei.c \
|
||||
mm-plugin-huawei.h
|
||||
|
||||
libmm_plugin_huawei_la_CPPFLAGS = \
|
||||
$(MM_CFLAGS) \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
libmm_plugin_huawei_la_LDFLAGS = -modeule -avoid-version
|
556
plugins/mm-modem-huawei.c
Normal file
556
plugins/mm-modem-huawei.c
Normal file
@@ -0,0 +1,556 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mm-modem-huawei.h"
|
||||
#include "mm-modem-error.h"
|
||||
#include "mm-callback-info.h"
|
||||
|
||||
static MMModem *parent_class_iface = NULL;
|
||||
|
||||
static void modem_init (MMModem *modem_class);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMModemHuawei, mm_modem_huawei, MM_TYPE_GENERIC_GSM,
|
||||
0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init))
|
||||
|
||||
#define MM_MODEM_HUAWEI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiPrivate))
|
||||
|
||||
typedef struct {
|
||||
MMSerial *monitor_device;
|
||||
} MMModemHuaweiPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_MONITOR_DEVICE,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
MMModem *
|
||||
mm_modem_huawei_new (const char *data_device,
|
||||
const char *monitor_device,
|
||||
const char *driver)
|
||||
{
|
||||
g_return_val_if_fail (data_device != NULL, NULL);
|
||||
g_return_val_if_fail (monitor_device != NULL, NULL);
|
||||
g_return_val_if_fail (driver != NULL, NULL);
|
||||
|
||||
return MM_MODEM (g_object_new (MM_TYPE_MODEM_HUAWEI,
|
||||
MM_SERIAL_DEVICE, data_device,
|
||||
MM_MODEM_DRIVER, driver,
|
||||
MM_MODEM_HUAWEI_MONITOR_DEVICE, monitor_device,
|
||||
NULL));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
parse_monitor_line (MMModem *modem, char *buf)
|
||||
{
|
||||
char **lines;
|
||||
char **iter;
|
||||
|
||||
lines = g_strsplit (buf, "\r\n", 0);
|
||||
|
||||
for (iter = lines; iter && *iter; iter++) {
|
||||
char *line = *iter;
|
||||
|
||||
g_strstrip (line);
|
||||
if (strlen (line) < 1 || line[0] != '^')
|
||||
continue;
|
||||
|
||||
line += 1;
|
||||
|
||||
if (!strncmp (line, "RSSI:", 5)) {
|
||||
int quality = atoi (line + 5);
|
||||
|
||||
if (quality == 99)
|
||||
/* 99 means unknown */
|
||||
quality = 0;
|
||||
else
|
||||
/* Normalize the quality */
|
||||
quality = quality * 100 / 31;
|
||||
|
||||
g_debug ("Signal quality: %d", quality);
|
||||
mm_modem_signal_quality (modem, (guint32) quality);
|
||||
} else if (!strncmp (line, "MODE:", 5)) {
|
||||
MMModemNetworkMode mode = 0;
|
||||
int a;
|
||||
int b;
|
||||
|
||||
if (sscanf (line + 5, "%d,%d", &a, &b)) {
|
||||
if (a == 3 && b == 2)
|
||||
mode = MM_MODEM_NETWORK_MODE_GPRS;
|
||||
else if (a == 3 && b == 3)
|
||||
mode = MM_MODEM_NETWORK_MODE_EDGE;
|
||||
else if (a == 5 && b == 4)
|
||||
mode = MM_MODEM_NETWORK_MODE_3G;
|
||||
else if (a ==5 && b == 5)
|
||||
mode = MM_MODEM_NETWORK_MODE_HSDPA;
|
||||
|
||||
if (mode) {
|
||||
g_debug ("Mode: %d", mode);
|
||||
mm_modem_network_mode (modem, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (lines);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
monitor_device_got_data (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
gsize bytes_read;
|
||||
char buf[4096];
|
||||
GIOStatus status;
|
||||
|
||||
if (condition & G_IO_IN) {
|
||||
do {
|
||||
status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL);
|
||||
|
||||
if (bytes_read) {
|
||||
buf[bytes_read] = '\0';
|
||||
parse_monitor_line (MM_MODEM (data), buf);
|
||||
}
|
||||
} while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN);
|
||||
}
|
||||
|
||||
if (condition & G_IO_HUP || condition & G_IO_ERR) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
enable (MMModem *modem,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (modem);
|
||||
|
||||
if (enable) {
|
||||
GIOChannel *channel;
|
||||
|
||||
mm_serial_open (priv->monitor_device);
|
||||
channel = mm_serial_get_io_channel (priv->monitor_device);
|
||||
g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP,
|
||||
monitor_device_got_data, modem);
|
||||
|
||||
g_io_channel_unref (channel);
|
||||
} else
|
||||
mm_serial_close (priv->monitor_device);
|
||||
|
||||
parent_class_iface->enable (modem, enable, callback, user_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_syscfg (const char *reply, int *mode_a, int *mode_b, guint32 *band, int *unknown1, int *unknown2)
|
||||
{
|
||||
if (strncmp (reply, "^SYSCFG:", 8))
|
||||
return FALSE;
|
||||
|
||||
if (sscanf (reply + 8, "%d,%d,%x,%d,%d", mode_a, mode_b, band, unknown1, unknown2))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
get_network_mode_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
int a, b, u1, u2;
|
||||
guint32 band;
|
||||
|
||||
if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
|
||||
if (a == 2 && b == 1)
|
||||
info->uint_result = MM_MODEM_NETWORK_MODE_PREFER_2G;
|
||||
else if (a == 2 && b == 2)
|
||||
info->uint_result = MM_MODEM_NETWORK_MODE_PREFER_3G;
|
||||
else if (a == 13 && b == 1)
|
||||
info->uint_result = MM_MODEM_NETWORK_MODE_GPRS;
|
||||
else if (a == 14 && b == 2)
|
||||
info->uint_result = MM_MODEM_NETWORK_MODE_3G;
|
||||
}
|
||||
|
||||
if (info->uint_result == 0)
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not parse network mode results");
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
get_network_mode (MMModem *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_uint_new (modem, callback, user_data);
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_network_mode_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting network mode failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_network_mode_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* Success */
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting network mode failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
set_network_mode_get_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
int a, b, u1, u2;
|
||||
guint32 band;
|
||||
guint id = 0;
|
||||
|
||||
if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
|
||||
char *responses[] = { "OK", "ERROR", NULL };
|
||||
char *command;
|
||||
|
||||
a = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-a"));
|
||||
b = GPOINTER_TO_INT (mm_callback_info_get_data (info, "mode-b"));
|
||||
command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
|
||||
|
||||
if (mm_serial_send_command_string (serial, command))
|
||||
id = mm_serial_wait_for_reply (serial, 3, responses, responses, set_network_mode_done, info);
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not set network mode");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_network_mode (MMModem *modem,
|
||||
MMModemNetworkMode mode,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
switch (mode) {
|
||||
case MM_MODEM_NETWORK_MODE_ANY:
|
||||
/* Do nothing */
|
||||
mm_callback_info_schedule (info);
|
||||
return;
|
||||
break;
|
||||
case MM_MODEM_NETWORK_MODE_GPRS:
|
||||
case MM_MODEM_NETWORK_MODE_EDGE:
|
||||
mm_callback_info_set_data (info, "mode-a", GINT_TO_POINTER (13), NULL);
|
||||
mm_callback_info_set_data (info, "mode-b", GINT_TO_POINTER (1), NULL);
|
||||
break;
|
||||
case MM_MODEM_NETWORK_MODE_3G:
|
||||
case MM_MODEM_NETWORK_MODE_HSDPA:
|
||||
mm_callback_info_set_data (info, "mode-a", GINT_TO_POINTER (14), NULL);
|
||||
mm_callback_info_set_data (info, "mode-b", GINT_TO_POINTER (2), NULL);
|
||||
break;
|
||||
case MM_MODEM_NETWORK_MODE_PREFER_2G:
|
||||
mm_callback_info_set_data (info, "mode-a", GINT_TO_POINTER (2), NULL);
|
||||
mm_callback_info_set_data (info, "mode-b", GINT_TO_POINTER (1), NULL);
|
||||
break;
|
||||
case MM_MODEM_NETWORK_MODE_PREFER_3G:
|
||||
mm_callback_info_set_data (info, "mode-a", GINT_TO_POINTER (2), NULL);
|
||||
mm_callback_info_set_data (info, "mode-b", GINT_TO_POINTER (2), NULL);
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Invalid mode.");
|
||||
mm_callback_info_schedule (info);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, set_network_mode_get_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting network mode failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_band_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
int a, b, u1, u2;
|
||||
guint32 band;
|
||||
|
||||
info->uint_result = 0xdeadbeaf;
|
||||
|
||||
if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
|
||||
if (band == 0x3FFFFFFF)
|
||||
info->uint_result = MM_MODEM_BAND_ANY;
|
||||
else if (band == 0x400380)
|
||||
info->uint_result = MM_MODEM_BAND_DCS;
|
||||
else if (band == 0x200000)
|
||||
info->uint_result = MM_MODEM_BAND_PCS;
|
||||
}
|
||||
|
||||
if (info->uint_result == 0xdeadbeaf) {
|
||||
info->uint_result = 0;
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not parse band results");
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
get_band (MMModem *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_uint_new (modem, callback, user_data);
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_band_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting band failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_band_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* Success */
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting band failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
set_band_get_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
int a, b, u1, u2;
|
||||
guint32 band;
|
||||
guint id = 0;
|
||||
|
||||
if (parse_syscfg (reply, &a, &b, &band, &u1, &u2)) {
|
||||
char *responses[] = { "OK", "ERROR", NULL };
|
||||
char *command;
|
||||
|
||||
band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
|
||||
command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
|
||||
|
||||
if (mm_serial_send_command_string (serial, command))
|
||||
id = mm_serial_wait_for_reply (serial, 3, responses, responses, set_band_done, info);
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not set band");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_band (MMModem *modem,
|
||||
MMModemBand band,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
switch (band) {
|
||||
case MM_MODEM_BAND_ANY:
|
||||
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (0x3FFFFFFF), NULL);
|
||||
break;
|
||||
case MM_MODEM_BAND_EGSM:
|
||||
case MM_MODEM_BAND_DCS:
|
||||
case MM_MODEM_BAND_U2100:
|
||||
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (0x400380), NULL);
|
||||
break;
|
||||
case MM_MODEM_BAND_PCS:
|
||||
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (0x200000), NULL);
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Invalid band.");
|
||||
mm_callback_info_schedule (info);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT^SYSCFG?"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, set_band_get_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting band failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
modem_init (MMModem *modem_class)
|
||||
{
|
||||
parent_class_iface = g_type_interface_peek_parent (modem_class);
|
||||
|
||||
/* interface implementation */
|
||||
modem_class->enable = enable;
|
||||
modem_class->set_network_mode = set_network_mode;
|
||||
modem_class->get_network_mode = get_network_mode;
|
||||
modem_class->set_band = set_band;
|
||||
modem_class->get_band = get_band;
|
||||
}
|
||||
|
||||
static void
|
||||
mm_modem_huawei_init (MMModemHuawei *self)
|
||||
{
|
||||
}
|
||||
|
||||
static GObject*
|
||||
constructor (GType type,
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
MMModemHuaweiPrivate *priv;
|
||||
|
||||
object = G_OBJECT_CLASS (mm_modem_huawei_parent_class)->constructor (type,
|
||||
n_construct_params,
|
||||
construct_params);
|
||||
if (!object)
|
||||
return NULL;
|
||||
|
||||
priv = MM_MODEM_HUAWEI_GET_PRIVATE (object);
|
||||
|
||||
if (!priv->monitor_device) {
|
||||
g_warning ("No monitor device provided");
|
||||
g_object_unref (object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MONITOR_DEVICE:
|
||||
/* Construct only */
|
||||
priv->monitor_device = MM_SERIAL (g_object_new (MM_TYPE_SERIAL,
|
||||
MM_SERIAL_DEVICE, g_value_get_string (value),
|
||||
NULL));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MONITOR_DEVICE:
|
||||
g_value_set_string (value, mm_serial_get_device (priv->monitor_device));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
MMModemHuaweiPrivate *priv = MM_MODEM_HUAWEI_GET_PRIVATE (object);
|
||||
|
||||
if (priv->monitor_device)
|
||||
g_object_unref (priv->monitor_device);
|
||||
|
||||
G_OBJECT_CLASS (mm_modem_huawei_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_modem_huawei_class_init (MMModemHuaweiClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (MMModemHuaweiPrivate));
|
||||
|
||||
/* Virtual methods */
|
||||
object_class->constructor = constructor;
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* Properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_MONITOR_DEVICE,
|
||||
g_param_spec_string (MM_MODEM_HUAWEI_MONITOR_DEVICE,
|
||||
"MonitorDevice",
|
||||
"Monitor device",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
31
plugins/mm-modem-huawei.h
Normal file
31
plugins/mm-modem-huawei.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_MODEM_HUAWEI_H
|
||||
#define MM_MODEM_HUAWEI_H
|
||||
|
||||
#include "mm-generic-gsm.h"
|
||||
|
||||
#define MM_TYPE_MODEM_HUAWEI (mm_modem_huawei_get_type ())
|
||||
#define MM_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuawei))
|
||||
#define MM_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
|
||||
#define MM_IS_MODEM_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_HUAWEI))
|
||||
#define MM_IS_MODEM_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MODEM_HUAWEI))
|
||||
#define MM_MODEM_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MODEM_HUAWEI, MMModemHuaweiClass))
|
||||
|
||||
#define MM_MODEM_HUAWEI_MONITOR_DEVICE "monitor-device"
|
||||
|
||||
typedef struct {
|
||||
MMGenericGsm parent;
|
||||
} MMModemHuawei;
|
||||
|
||||
typedef struct {
|
||||
MMGenericGsmClass parent;
|
||||
} MMModemHuaweiClass;
|
||||
|
||||
GType mm_modem_huawei_get_type (void);
|
||||
|
||||
MMModem *mm_modem_huawei_new (const char *data_device,
|
||||
const char *monitor_device,
|
||||
const char *driver);
|
||||
|
||||
#endif /* MM_MODEM_HUAWEI_H */
|
155
plugins/mm-plugin-huawei.c
Normal file
155
plugins/mm-plugin-huawei.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
#include "mm-plugin-huawei.h"
|
||||
#include "mm-modem-huawei.h"
|
||||
|
||||
static void plugin_init (MMPlugin *plugin_class);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMPluginHuawei, mm_plugin_huawei, G_TYPE_OBJECT,
|
||||
0, G_IMPLEMENT_INTERFACE (MM_TYPE_PLUGIN, plugin_init))
|
||||
|
||||
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
|
||||
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
|
||||
|
||||
G_MODULE_EXPORT MMPlugin *
|
||||
mm_plugin_create (void)
|
||||
{
|
||||
return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_HUAWEI, NULL));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
get_name (MMPlugin *plugin)
|
||||
{
|
||||
return "Huawei";
|
||||
}
|
||||
|
||||
static char **
|
||||
list_supported_udis (MMPlugin *plugin, LibHalContext *hal_ctx)
|
||||
{
|
||||
char **supported = NULL;
|
||||
char **devices;
|
||||
int num_devices;
|
||||
int i;
|
||||
|
||||
devices = libhal_find_device_by_capability (hal_ctx, "modem", &num_devices, NULL);
|
||||
if (devices) {
|
||||
GPtrArray *array;
|
||||
|
||||
array = g_ptr_array_new ();
|
||||
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
char *udi = devices[i];
|
||||
|
||||
if (mm_plugin_supports_udi (plugin, hal_ctx, udi))
|
||||
g_ptr_array_add (array, g_strdup (udi));
|
||||
}
|
||||
|
||||
if (array->len > 0) {
|
||||
g_ptr_array_add (array, NULL);
|
||||
supported = (char **) g_ptr_array_free (array, FALSE);
|
||||
} else
|
||||
g_ptr_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
g_strfreev (devices);
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supports_udi (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
|
||||
{
|
||||
char **capabilities;
|
||||
char **iter;
|
||||
gboolean supported = FALSE;
|
||||
|
||||
capabilities = libhal_device_get_property_strlist (hal_ctx, udi, "modem.command_sets", NULL);
|
||||
for (iter = capabilities; iter && *iter && !supported; iter++) {
|
||||
if (!strcmp (*iter, "GSM-07.07")) {
|
||||
char *parent_udi;
|
||||
|
||||
parent_udi = libhal_device_get_property_string (hal_ctx, udi, "info.parent", NULL);
|
||||
if (parent_udi) {
|
||||
int vendor;
|
||||
int product;
|
||||
|
||||
vendor = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.vendor_id", NULL);
|
||||
product = libhal_device_get_property_int (hal_ctx, parent_udi, "usb.product_id", NULL);
|
||||
|
||||
if (vendor == 0x12d1 && (product == 0x1001 || product == 0x1003 || product == 0x1004))
|
||||
supported = TRUE;
|
||||
|
||||
libhal_free_string (parent_udi);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_strfreev (capabilities);
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_driver_name (LibHalContext *ctx, const char *udi)
|
||||
{
|
||||
char *parent_udi;
|
||||
char *driver = NULL;
|
||||
|
||||
parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
|
||||
if (parent_udi) {
|
||||
driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
|
||||
libhal_free_string (parent_udi);
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
static MMModem *
|
||||
create_modem (MMPlugin *plugin, LibHalContext *hal_ctx, const char *udi)
|
||||
{
|
||||
char *data_device;
|
||||
char *monitor_device;
|
||||
char *driver;
|
||||
MMModem *modem;
|
||||
|
||||
data_device = libhal_device_get_property_string (hal_ctx, udi, "serial.device", NULL);
|
||||
g_return_val_if_fail (data_device != NULL, NULL);
|
||||
|
||||
driver = get_driver_name (hal_ctx, udi);
|
||||
g_return_val_if_fail (driver != NULL, NULL);
|
||||
|
||||
/* FIXME: Get monitoring device from HAL */
|
||||
monitor_device = "/dev/ttyUSB1";
|
||||
|
||||
modem = MM_MODEM (mm_modem_huawei_new (data_device, monitor_device, driver));
|
||||
|
||||
g_free (data_device);
|
||||
g_free (driver);
|
||||
|
||||
return modem;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
plugin_init (MMPlugin *plugin_class)
|
||||
{
|
||||
/* interface implementation */
|
||||
plugin_class->get_name = get_name;
|
||||
plugin_class->list_supported_udis = list_supported_udis;
|
||||
plugin_class->supports_udi = supports_udi;
|
||||
plugin_class->create_modem = create_modem;
|
||||
}
|
||||
|
||||
static void
|
||||
mm_plugin_huawei_init (MMPluginHuawei *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
mm_plugin_huawei_class_init (MMPluginHuaweiClass *klass)
|
||||
{
|
||||
}
|
26
plugins/mm-plugin-huawei.h
Normal file
26
plugins/mm-plugin-huawei.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_PLUGIN_HUAWEI_H
|
||||
#define MM_PLUGIN_HUAWEI_H
|
||||
|
||||
#include "mm-plugin.h"
|
||||
#include "mm-generic-gsm.h"
|
||||
|
||||
#define MM_TYPE_PLUGIN_HUAWEI (mm_plugin_huawei_get_type ())
|
||||
#define MM_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuawei))
|
||||
#define MM_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
|
||||
#define MM_IS_PLUGIN_HUAWEI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_HUAWEI))
|
||||
#define MM_IS_PLUGIN_HUAWEI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_HUAWEI))
|
||||
#define MM_PLUGIN_HUAWEI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_HUAWEI, MMPluginHuaweiClass))
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} MMPluginHuawei;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
} MMPluginHuaweiClass;
|
||||
|
||||
GType mm_plugin_huawei_get_type (void);
|
||||
|
||||
#endif /* MM_PLUGIN_HUAWEI_H */
|
39
src/Makefile.am
Normal file
39
src/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
sbin_PROGRAMS = modem-manager
|
||||
|
||||
modem_manager_CPPFLAGS = \
|
||||
$(MM_CFLAGS) \
|
||||
-DPLUGINDIR=\"$(pkglibdir)\"
|
||||
|
||||
modem_manager_LDADD = \
|
||||
$(MM_LIBS)
|
||||
|
||||
modem_manager_SOURCES = \
|
||||
main.c \
|
||||
mm-callback-info.c \
|
||||
mm-callback-info.h \
|
||||
mm-generic-cdma.c \
|
||||
mm-generic-cdma.h \
|
||||
mm-generic-gsm.c \
|
||||
mm-generic-gsm.h \
|
||||
mm-manager.c \
|
||||
mm-manager.h \
|
||||
mm-modem.c \
|
||||
mm-modem.h \
|
||||
mm-modem-error.c \
|
||||
mm-modem-error.h \
|
||||
mm-plugin.c \
|
||||
mm-plugin.h \
|
||||
mm-serial.c \
|
||||
mm-serial.h
|
||||
|
||||
mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml
|
||||
dbus-binding-tool --prefix=mm_manager --mode=glib-server --output=$@ $<
|
||||
|
||||
mm-modem-glue.h: $(top_srcdir)/introspection/mm-modem.xml
|
||||
dbus-binding-tool --prefix=mm_modem --mode=glib-server --output=$@ $<
|
||||
|
||||
BUILT_SOURCES = \
|
||||
mm-manager-glue.h \
|
||||
mm-modem-glue.h
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
166
src/main.c
Normal file
166
src/main.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <syslog.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include "mm-manager.h"
|
||||
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer ignored)
|
||||
{
|
||||
int syslog_priority;
|
||||
|
||||
switch (log_level) {
|
||||
case G_LOG_LEVEL_ERROR:
|
||||
syslog_priority = LOG_CRIT;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_CRITICAL:
|
||||
syslog_priority = LOG_ERR;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_WARNING:
|
||||
syslog_priority = LOG_WARNING;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_MESSAGE:
|
||||
syslog_priority = LOG_NOTICE;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_DEBUG:
|
||||
syslog_priority = LOG_DEBUG;
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_INFO:
|
||||
default:
|
||||
syslog_priority = LOG_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
syslog (syslog_priority, "%s", message);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
logging_setup (void)
|
||||
{
|
||||
openlog (G_LOG_DOMAIN, LOG_CONS, LOG_DAEMON);
|
||||
g_log_set_handler (G_LOG_DOMAIN,
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
logging_shutdown (void)
|
||||
{
|
||||
closelog ();
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_cb (DBusGProxy *proxy, gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = (GMainLoop *) user_data;
|
||||
|
||||
g_message ("disconnected from the system bus, exiting.");
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dbus_init (GMainLoop *loop)
|
||||
{
|
||||
DBusGConnection *connection;
|
||||
DBusGProxy *proxy;
|
||||
GError *err = NULL;
|
||||
int request_name_result;
|
||||
|
||||
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
|
||||
if (!connection) {
|
||||
g_warning ("Could not get the system bus. Make sure "
|
||||
"the message bus daemon is running! Message: %s",
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (connection,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus");
|
||||
|
||||
if (!dbus_g_proxy_call (proxy, "RequestName", &err,
|
||||
G_TYPE_STRING, MM_DBUS_SERVICE,
|
||||
G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_UINT, &request_name_result,
|
||||
G_TYPE_INVALID)) {
|
||||
g_warning ("Could not acquire the %s service.\n"
|
||||
" Message: '%s'", MM_DBUS_SERVICE, err->message);
|
||||
g_error_free (err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
g_warning ("Could not acquire the NetworkManagerSystemSettings service "
|
||||
"as it is already taken. Return: %d",
|
||||
request_name_result);
|
||||
goto err;
|
||||
}
|
||||
|
||||
g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), loop);
|
||||
|
||||
return TRUE;
|
||||
|
||||
err:
|
||||
dbus_g_connection_unref (connection);
|
||||
g_object_unref (proxy);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GOptionContext *opt_ctx;
|
||||
GError *error = NULL;
|
||||
GMainLoop *loop;
|
||||
MMManager *manager;
|
||||
gboolean debug = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Output to console rather than syslog", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
opt_ctx = g_option_context_new (NULL);
|
||||
g_option_context_set_summary (opt_ctx, "DBus system service to communicate with modems.");
|
||||
g_option_context_add_main_entries (opt_ctx, entries, NULL);
|
||||
|
||||
if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) {
|
||||
g_warning ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_option_context_free (opt_ctx);
|
||||
|
||||
g_type_init ();
|
||||
|
||||
if (!debug)
|
||||
logging_setup ();
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (!dbus_init (loop))
|
||||
return -1;
|
||||
|
||||
manager = mm_manager_new ();
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_object_unref (manager);
|
||||
logging_shutdown ();
|
||||
|
||||
return 0;
|
||||
}
|
98
src/mm-callback-info.c
Normal file
98
src/mm-callback-info.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include "mm-callback-info.h"
|
||||
#include "mm-modem-error.h"
|
||||
|
||||
static void
|
||||
callback_info_done (gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
info->pending_id = 0;
|
||||
|
||||
if (info->callback)
|
||||
info->callback (info->modem, info->error, info->user_data);
|
||||
else if (info->uint_callback)
|
||||
info->uint_callback (info->modem, info->uint_result, info->error, info->user_data);
|
||||
|
||||
if (info->error)
|
||||
g_error_free (info->error);
|
||||
|
||||
g_object_unref (info->modem);
|
||||
g_datalist_clear (&info->qdata);
|
||||
|
||||
g_slice_free (MMCallbackInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
callback_info_do (gpointer user_data)
|
||||
{
|
||||
/* Nothing here, everything is done in callback_info_done to make sure the info->callback
|
||||
always gets called, even if the pending call gets cancelled. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
mm_callback_info_schedule (MMCallbackInfo *info)
|
||||
{
|
||||
info->pending_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, callback_info_do, info, callback_info_done);
|
||||
}
|
||||
|
||||
void
|
||||
mm_callback_info_cancel (MMCallbackInfo *info)
|
||||
{
|
||||
if (info->pending_id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Call cancelled");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
MMCallbackInfo *
|
||||
mm_callback_info_new (MMModem *modem, MMModemFn callback, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = g_slice_new0 (MMCallbackInfo);
|
||||
g_datalist_init (&info->qdata);
|
||||
info->modem = g_object_ref (modem);
|
||||
info->callback = callback;
|
||||
info->user_data = user_data;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
MMCallbackInfo *
|
||||
mm_callback_info_uint_new (MMModem *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = g_slice_new0 (MMCallbackInfo);
|
||||
g_datalist_init (&info->qdata);
|
||||
info->modem = g_object_ref (modem);
|
||||
info->uint_callback = callback;
|
||||
info->user_data = user_data;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
mm_callback_info_set_data (MMCallbackInfo *info,
|
||||
const char *key,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
g_datalist_id_set_data_full (&info->qdata, g_quark_from_string (key), data,
|
||||
data ? destroy : (GDestroyNotify) NULL);
|
||||
}
|
||||
|
||||
gpointer
|
||||
mm_callback_info_get_data (MMCallbackInfo *info, const char *key)
|
||||
{
|
||||
GQuark quark;
|
||||
|
||||
quark = g_quark_try_string (key);
|
||||
|
||||
return quark ? g_datalist_id_get_data (&info->qdata, quark) : NULL;
|
||||
}
|
38
src/mm-callback-info.h
Normal file
38
src/mm-callback-info.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_CALLBACK_INFO_H
|
||||
#define MM_CALLBACK_INFO_H
|
||||
|
||||
#include "mm-modem.h"
|
||||
|
||||
typedef struct {
|
||||
GData *qdata;
|
||||
MMModem *modem;
|
||||
MMModemFn callback;
|
||||
MMModemUIntFn uint_callback;
|
||||
guint32 uint_result;
|
||||
gpointer user_data;
|
||||
GError *error;
|
||||
guint pending_id;
|
||||
} MMCallbackInfo;
|
||||
|
||||
MMCallbackInfo *mm_callback_info_new (MMModem *modem,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
MMCallbackInfo *mm_callback_info_uint_new (MMModem *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_callback_info_schedule (MMCallbackInfo *info);
|
||||
void mm_callback_info_cancel (MMCallbackInfo *info);
|
||||
|
||||
void mm_callback_info_set_data (MMCallbackInfo *info,
|
||||
const char *key,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
gpointer mm_callback_info_get_data (MMCallbackInfo *info,
|
||||
const char *key);
|
||||
|
||||
#endif /* MM_CALLBACK_INFO_H */
|
259
src/mm-generic-cdma.c
Normal file
259
src/mm-generic-cdma.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include "mm-generic-cdma.h"
|
||||
#include "mm-modem-error.h"
|
||||
#include "mm-callback-info.h"
|
||||
|
||||
static void modem_init (MMModem *modem_class);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMGenericCdma, mm_generic_cdma, MM_TYPE_SERIAL,
|
||||
0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init))
|
||||
|
||||
#define MM_GENERIC_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_GENERIC_CDMA, MMGenericCdmaPrivate))
|
||||
|
||||
typedef struct {
|
||||
char *driver;
|
||||
} MMGenericCdmaPrivate;
|
||||
|
||||
MMModem *
|
||||
mm_generic_cdma_new (const char *serial_device, const char *driver)
|
||||
{
|
||||
g_return_val_if_fail (serial_device != NULL, NULL);
|
||||
g_return_val_if_fail (driver != NULL, NULL);
|
||||
|
||||
return MM_MODEM (g_object_new (MM_TYPE_GENERIC_CDMA,
|
||||
MM_SERIAL_DEVICE, serial_device,
|
||||
MM_MODEM_DRIVER, driver,
|
||||
NULL));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
init_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization timed out.");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization failed");
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
flash_done (MMSerial *serial, gpointer user_data)
|
||||
{
|
||||
char *responses[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
if (mm_serial_send_command_string (serial, "AT E0"))
|
||||
id = mm_serial_wait_for_reply (serial, 10, responses, responses, init_done, user_data);
|
||||
|
||||
if (!id) {
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Turning modem echo off failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enable (MMModem *modem,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
if (!enable) {
|
||||
mm_serial_close (MM_SERIAL (modem));
|
||||
mm_callback_info_schedule (info);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mm_serial_open (MM_SERIAL (modem))) {
|
||||
guint id;
|
||||
|
||||
id = mm_serial_flash (MM_SERIAL (modem), 100, flash_done, info);
|
||||
if (!id)
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not communicate with serial device.");
|
||||
} else
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not open serial device.");
|
||||
|
||||
if (info->error)
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
dial_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case 1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: Busy");
|
||||
break;
|
||||
case 2:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No dial tone");
|
||||
break;
|
||||
case 3:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No carrier");
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing timed out");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
connect (MMModem *modem,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *command;
|
||||
char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
command = g_strconcat ("ATDT", number, NULL);
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), command))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, responses, dial_done, info);
|
||||
|
||||
g_free (command);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect (MMModem *modem,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
mm_serial_close (MM_SERIAL (modem));
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
modem_init (MMModem *modem_class)
|
||||
{
|
||||
/* interface implementation */
|
||||
modem_class->enable = enable;
|
||||
modem_class->connect = connect;
|
||||
modem_class->disconnect = disconnect;
|
||||
}
|
||||
|
||||
static void
|
||||
mm_generic_cdma_init (MMGenericCdma *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case MM_MODEM_PROP_DRIVER:
|
||||
/* Construct only */
|
||||
MM_GENERIC_CDMA_GET_PRIVATE (object)->driver = g_value_dup_string (value);
|
||||
break;
|
||||
case MM_MODEM_PROP_DATA_DEVICE:
|
||||
case MM_MODEM_PROP_TYPE:
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case MM_MODEM_PROP_DATA_DEVICE:
|
||||
g_value_set_string (value, mm_serial_get_device (MM_SERIAL (object)));
|
||||
break;
|
||||
case MM_MODEM_PROP_DRIVER:
|
||||
g_value_set_string (value, MM_GENERIC_CDMA_GET_PRIVATE (object)->driver);
|
||||
break;
|
||||
case MM_MODEM_PROP_TYPE:
|
||||
g_value_set_uint (value, MM_MODEM_TYPE_CDMA);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->driver);
|
||||
|
||||
G_OBJECT_CLASS (mm_generic_cdma_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_generic_cdma_class_init (MMGenericCdmaClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (MMGenericCdmaPrivate));
|
||||
|
||||
/* Virtual methods */
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* Properties */
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_DATA_DEVICE,
|
||||
MM_MODEM_DATA_DEVICE);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_DRIVER,
|
||||
MM_MODEM_DRIVER);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_TYPE,
|
||||
MM_MODEM_TYPE);
|
||||
|
||||
mm_modem_install_dbus_info (G_TYPE_FROM_CLASS (klass));
|
||||
}
|
29
src/mm-generic-cdma.h
Normal file
29
src/mm-generic-cdma.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_GENERIC_CDMA_H
|
||||
#define MM_GENERIC_CDMA_H
|
||||
|
||||
#include "mm-modem.h"
|
||||
#include "mm-serial.h"
|
||||
|
||||
#define MM_TYPE_GENERIC_CDMA (mm_generic_cdma_get_type ())
|
||||
#define MM_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdma))
|
||||
#define MM_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
|
||||
#define MM_IS_GENERIC_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_CDMA))
|
||||
#define MM_IS_GENERIC_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_CDMA))
|
||||
#define MM_GENERIC_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_CDMA, MMGenericCdmaClass))
|
||||
|
||||
typedef struct {
|
||||
MMSerial parent;
|
||||
} MMGenericCdma;
|
||||
|
||||
typedef struct {
|
||||
MMSerialClass parent;
|
||||
} MMGenericCdmaClass;
|
||||
|
||||
GType mm_generic_cdma_get_type (void);
|
||||
|
||||
MMModem *mm_generic_cdma_new (const char *serial_device,
|
||||
const char *driver);
|
||||
|
||||
#endif /* MM_GENERIC_CDMA_H */
|
705
src/mm-generic-gsm.c
Normal file
705
src/mm-generic-gsm.c
Normal file
@@ -0,0 +1,705 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mm-generic-gsm.h"
|
||||
#include "mm-modem-error.h"
|
||||
#include "mm-callback-info.h"
|
||||
|
||||
static void modem_init (MMModem *modem_class);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMGenericGsm, mm_generic_gsm, MM_TYPE_SERIAL,
|
||||
0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init))
|
||||
|
||||
#define MM_GENERIC_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_GENERIC_GSM, MMGenericGsmPrivate))
|
||||
|
||||
typedef struct {
|
||||
char *driver;
|
||||
guint32 pending_id;
|
||||
} MMGenericGsmPrivate;
|
||||
|
||||
static void register_auto (MMModem *modem, MMCallbackInfo *info);
|
||||
|
||||
MMModem *
|
||||
mm_generic_gsm_new (const char *serial_device, const char *driver)
|
||||
{
|
||||
g_return_val_if_fail (serial_device != NULL, NULL);
|
||||
g_return_val_if_fail (driver != NULL, NULL);
|
||||
|
||||
return MM_MODEM (g_object_new (MM_TYPE_GENERIC_GSM,
|
||||
MM_SERIAL_DEVICE, serial_device,
|
||||
MM_MODEM_DRIVER, driver,
|
||||
NULL));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
check_pin_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case 1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_PIN_NEEDED, "%s", "PIN needed");
|
||||
break;
|
||||
case 2:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_PUK_NEEDED, "%s", "PUK needed");
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking timed out.");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
check_pin (MMSerial *serial, gpointer user_data)
|
||||
{
|
||||
char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
|
||||
char *terminators[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
if (mm_serial_send_command_string (serial, "AT+CPIN?"))
|
||||
id = mm_serial_wait_for_reply (serial, 3, responses, terminators, check_pin_done, user_data);
|
||||
|
||||
if (!id) {
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
check_pin (serial, user_data);
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization timed out.");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Modem initialization failed");
|
||||
}
|
||||
|
||||
if (info->error)
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
flash_done (MMSerial *serial, gpointer user_data)
|
||||
{
|
||||
char *responses[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
if (mm_serial_send_command_string (serial, "AT E0"))
|
||||
id = mm_serial_wait_for_reply (serial, 10, responses, responses, init_done, user_data);
|
||||
|
||||
if (!id) {
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Turning modem echo off failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enable (MMModem *modem,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
if (!enable) {
|
||||
mm_serial_close (MM_SERIAL (modem));
|
||||
mm_callback_info_schedule (info);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mm_serial_open (MM_SERIAL (modem))) {
|
||||
guint id;
|
||||
|
||||
id = mm_serial_flash (MM_SERIAL (modem), 100, flash_done, info);
|
||||
if (!id)
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not communicate with serial device.");
|
||||
} else
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not open serial device.");
|
||||
|
||||
if (info->error)
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
set_pin_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Did not receive response for secret");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_INVALID_SECRET, "%s", "Invalid secret");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
set_pin (MMModem *modem,
|
||||
const char *pin,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *command;
|
||||
char *responses[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
command = g_strdup_printf ("AT+CPIN=\"%s\"", pin);
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), command))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 3, responses, responses, set_pin_done, info);
|
||||
|
||||
g_free (command);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "PIN checking failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
register_manual_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration timed out");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
register_manual (MMModem *modem, const char *network_id, MMCallbackInfo *info)
|
||||
{
|
||||
char *command;
|
||||
char *responses[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
command = g_strdup_printf ("AT+COPS=1,2,\"%s\"", network_id);
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), command))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 30, responses, responses,
|
||||
register_manual_done, info);
|
||||
|
||||
g_free (command);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Manual registration failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
automatic_registration_again (gpointer data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) data;
|
||||
|
||||
register_auto (MM_MODEM (mm_callback_info_get_data (info, "modem")), info);
|
||||
|
||||
mm_callback_info_set_data (info, "modem", NULL, NULL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_auto_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
g_message ("Registered on Home network");
|
||||
break;
|
||||
case 1:
|
||||
g_message ("Registered on Roaming network");
|
||||
break;
|
||||
case 2:
|
||||
mm_callback_info_set_data (info, "modem", g_object_ref (serial), g_object_unref);
|
||||
MM_GENERIC_GSM_GET_PRIVATE (serial)->pending_id = g_timeout_add (1000, automatic_registration_again, info);
|
||||
return;
|
||||
break;
|
||||
case 3:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Automatic registration failed: not registered and not searching.");
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration timed out");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
register_auto (MMModem *modem, MMCallbackInfo *info)
|
||||
{
|
||||
char *responses[] = { "+CREG: 0,1", "+CREG: 0,5", "+CREG: 0,2", "+CREG: 0,0", NULL };
|
||||
char *terminators[] = { "OK", "ERROR", "ERR", NULL };
|
||||
guint id = 0;
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CREG?"))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, terminators,
|
||||
register_auto_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Automatic registration failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_register (MMModem *modem,
|
||||
const char *network_id,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
if (network_id)
|
||||
register_manual (modem, network_id, info);
|
||||
else
|
||||
register_auto (modem, info);
|
||||
}
|
||||
|
||||
static void
|
||||
dial_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case 1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: Busy");
|
||||
break;
|
||||
case 2:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No dial tone");
|
||||
break;
|
||||
case 3:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dial failed: No carrier");
|
||||
break;
|
||||
case -1:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing timed out");
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed");
|
||||
break;
|
||||
}
|
||||
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dial (MMModem *modem, guint cid, const char *number, MMCallbackInfo *info)
|
||||
{
|
||||
char *command;
|
||||
char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
|
||||
guint id = 0;
|
||||
|
||||
if (cid) {
|
||||
GString *str;
|
||||
|
||||
str = g_string_new ("ATD");
|
||||
if (g_str_has_suffix (number, "#"))
|
||||
str = g_string_append_len (str, number, strlen (number) - 1);
|
||||
else
|
||||
str = g_string_append (str, number);
|
||||
|
||||
g_string_append_printf (str, "***%d#", cid);
|
||||
command = g_string_free (str, FALSE);
|
||||
} else
|
||||
command = g_strconcat ("ATDT", number, NULL);
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), command))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 60, responses, responses, dial_done, info);
|
||||
|
||||
g_free (command);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Dialing failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_apn_done (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
const char *number = (char *) mm_callback_info_get_data (info, "number");
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
dial (MM_MODEM (serial), 1, number, info);
|
||||
break;
|
||||
default:
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting APN failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->error)
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
set_apn (MMModem *modem, const char *apn, MMCallbackInfo *info)
|
||||
{
|
||||
char *command;
|
||||
char *responses[] = { "OK", "ERROR", NULL };
|
||||
guint cid = 1;
|
||||
guint id = 0;
|
||||
|
||||
command = g_strdup_printf ("AT+CGDCONT=%d, \"IP\", \"%s\"", cid, apn);
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), command))
|
||||
id = mm_serial_wait_for_reply (MM_SERIAL (modem), 3, responses, responses, set_apn_done, info);
|
||||
|
||||
g_free (command);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Setting APN failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connect (MMModem *modem,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
|
||||
if (apn) {
|
||||
mm_callback_info_set_data (info, "number", g_strdup (number), g_free);
|
||||
set_apn (modem, apn, info);
|
||||
} else
|
||||
dial (modem, 0, number, info);
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect (MMModem *modem,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (modem, callback, user_data);
|
||||
mm_serial_close (MM_SERIAL (modem));
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
scan_callback_wrapper (MMModem *modem,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
MMModemScanFn scan_fn;
|
||||
GPtrArray *results;
|
||||
gpointer data;
|
||||
|
||||
scan_fn = (MMModemScanFn) mm_callback_info_get_data (info, "scan-callback");
|
||||
results = (GPtrArray *) mm_callback_info_get_data (info, "scan-results");
|
||||
data = mm_callback_info_get_data (info, "scan-data");
|
||||
|
||||
scan_fn (modem, results, error, data);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_scan_data (gpointer data)
|
||||
{
|
||||
GPtrArray *results = (GPtrArray *) data;
|
||||
|
||||
g_ptr_array_foreach (results, (GFunc) g_hash_table_destroy, NULL);
|
||||
g_ptr_array_free (results, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
scan_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
GPtrArray *results;
|
||||
|
||||
results = g_ptr_array_new ();
|
||||
|
||||
if (!strncmp (reply, "+COPS: ", 7)) {
|
||||
/* Got valid reply */
|
||||
GRegex *r;
|
||||
GMatchInfo *match_info;
|
||||
GError *err = NULL;
|
||||
|
||||
reply += 7;
|
||||
|
||||
/* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|",|\d|) */
|
||||
r = g_regex_new ("\\((\\d),\"(.+)\",\"(.+)\",\"(.+)\",(\\d)\\)", G_REGEX_UNGREEDY, 0, &err);
|
||||
if (err) {
|
||||
g_error ("Invalid regular expression: %s", err->message);
|
||||
g_error_free (err);
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not parse scan results.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_regex_match (r, reply, 0, &match_info);
|
||||
while (g_match_info_matches (match_info)) {
|
||||
GHashTable *hash;
|
||||
|
||||
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
g_hash_table_insert (hash, g_strdup ("status"), g_match_info_fetch (match_info, 1));
|
||||
g_hash_table_insert (hash, g_strdup ("operator-long"), g_match_info_fetch (match_info, 2));
|
||||
g_hash_table_insert (hash, g_strdup ("operator-short"), g_match_info_fetch (match_info, 3));
|
||||
g_hash_table_insert (hash, g_strdup ("operator-num"), g_match_info_fetch (match_info, 4));
|
||||
|
||||
g_ptr_array_add (results, hash);
|
||||
g_match_info_next (match_info, NULL);
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_unref (r);
|
||||
} else
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Could not parse scan results");
|
||||
|
||||
mm_callback_info_set_data (info, "scan-results", results, destroy_scan_data);
|
||||
|
||||
out:
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
scan (MMModem *modem,
|
||||
MMModemScanFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_new (modem, scan_callback_wrapper, NULL);
|
||||
info->user_data = info;
|
||||
mm_callback_info_set_data (info, "scan-callback", callback, NULL);
|
||||
mm_callback_info_set_data (info, "scan-data", user_data, NULL);
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+COPS=?"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 60, terminators, scan_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Scanning failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_signal_quality_done (MMSerial *serial, const char *reply, gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||
guint32 result = 0;
|
||||
|
||||
if (!strncmp (reply, "+CSQ: ", 6)) {
|
||||
/* Got valid reply */
|
||||
int quality;
|
||||
int ber;
|
||||
|
||||
reply += 6;
|
||||
|
||||
if (sscanf (reply, "%d,%d", &quality, &ber)) {
|
||||
/* 99 means unknown */
|
||||
if (quality != 99)
|
||||
/* Normalize the quality */
|
||||
result = quality * 100 / 31;
|
||||
} else
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not parse signal quality results");
|
||||
} else
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||
"%s", "Could not parse signal quality results");
|
||||
|
||||
info->uint_result = result;
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
get_signal_quality (MMModem *modem,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
char *terminators = "\r\n";
|
||||
guint id = 0;
|
||||
|
||||
info = mm_callback_info_uint_new (modem, callback, user_data);
|
||||
|
||||
if (mm_serial_send_command_string (MM_SERIAL (modem), "AT+CSQ"))
|
||||
id = mm_serial_get_reply (MM_SERIAL (modem), 10, terminators, get_signal_quality_done, info);
|
||||
|
||||
if (!id) {
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "%s", "Getting signal quality failed.");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
modem_init (MMModem *modem_class)
|
||||
{
|
||||
/* interface implementation */
|
||||
modem_class->enable = enable;
|
||||
modem_class->set_pin = set_pin;
|
||||
modem_class->do_register = do_register;
|
||||
modem_class->connect = connect;
|
||||
modem_class->disconnect = disconnect;
|
||||
modem_class->scan = scan;
|
||||
modem_class->get_signal_quality = get_signal_quality;
|
||||
}
|
||||
|
||||
static void
|
||||
mm_generic_gsm_init (MMGenericGsm *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case MM_MODEM_PROP_DRIVER:
|
||||
/* Construct only */
|
||||
MM_GENERIC_GSM_GET_PRIVATE (object)->driver = g_value_dup_string (value);
|
||||
break;
|
||||
case MM_MODEM_PROP_DATA_DEVICE:
|
||||
case MM_MODEM_PROP_TYPE:
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case MM_MODEM_PROP_DATA_DEVICE:
|
||||
g_value_set_string (value, mm_serial_get_device (MM_SERIAL (object)));
|
||||
break;
|
||||
case MM_MODEM_PROP_DRIVER:
|
||||
g_value_set_string (value, MM_GENERIC_GSM_GET_PRIVATE (object)->driver);
|
||||
break;
|
||||
case MM_MODEM_PROP_TYPE:
|
||||
g_value_set_uint (value, MM_MODEM_TYPE_GSM);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object);
|
||||
|
||||
if (priv->pending_id) {
|
||||
g_source_remove (priv->pending_id);
|
||||
priv->pending_id = 0;
|
||||
}
|
||||
|
||||
g_free (priv->driver);
|
||||
|
||||
G_OBJECT_CLASS (mm_generic_gsm_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_generic_gsm_class_init (MMGenericGsmClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (MMGenericGsmPrivate));
|
||||
|
||||
/* Virtual methods */
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* Properties */
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_DATA_DEVICE,
|
||||
MM_MODEM_DATA_DEVICE);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_DRIVER,
|
||||
MM_MODEM_DRIVER);
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
MM_MODEM_PROP_TYPE,
|
||||
MM_MODEM_TYPE);
|
||||
|
||||
mm_modem_install_dbus_info (G_TYPE_FROM_CLASS (klass));
|
||||
}
|
29
src/mm-generic-gsm.h
Normal file
29
src/mm-generic-gsm.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_GENERIC_GSM_H
|
||||
#define MM_GENERIC_GSM_H
|
||||
|
||||
#include "mm-modem.h"
|
||||
#include "mm-serial.h"
|
||||
|
||||
#define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ())
|
||||
#define MM_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsm))
|
||||
#define MM_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
|
||||
#define MM_IS_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_GENERIC_GSM))
|
||||
#define MM_IS_GENERIC_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_GENERIC_GSM))
|
||||
#define MM_GENERIC_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsmClass))
|
||||
|
||||
typedef struct {
|
||||
MMSerial parent;
|
||||
} MMGenericGsm;
|
||||
|
||||
typedef struct {
|
||||
MMSerialClass parent;
|
||||
} MMGenericGsmClass;
|
||||
|
||||
GType mm_generic_gsm_get_type (void);
|
||||
|
||||
MMModem *mm_generic_gsm_new (const char *serial_device,
|
||||
const char *driver);
|
||||
|
||||
#endif /* MM_GENERIC_GSM_H */
|
457
src/mm-manager.c
Normal file
457
src/mm-manager.c
Normal file
@@ -0,0 +1,457 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
#include <libhal.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include "mm-manager.h"
|
||||
#include "mm-modem-error.h"
|
||||
#include "mm-generic-gsm.h"
|
||||
#include "mm-generic-cdma.h"
|
||||
#include "mm-plugin.h"
|
||||
|
||||
static gboolean impl_manager_enumerate_devices (MMManager *manager,
|
||||
GPtrArray **devices,
|
||||
GError **err);
|
||||
|
||||
#include "mm-manager-glue.h"
|
||||
|
||||
G_DEFINE_TYPE (MMManager, mm_manager, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
DEVICE_ADDED,
|
||||
DEVICE_REMOVED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#define MM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MANAGER, MMManagerPrivate))
|
||||
|
||||
typedef struct {
|
||||
DBusGConnection *connection;
|
||||
LibHalContext *hal_ctx;
|
||||
GSList *plugins;
|
||||
GHashTable *modems;
|
||||
} MMManagerPrivate;
|
||||
|
||||
static MMPlugin *
|
||||
load_plugin (const char *path)
|
||||
{
|
||||
MMPlugin *plugin = NULL;
|
||||
GModule *module;
|
||||
MMPluginCreateFunc plugin_create_func;
|
||||
int *major_plugin_version, *minor_plugin_version;
|
||||
|
||||
module = g_module_open (path, G_MODULE_BIND_LAZY);
|
||||
if (!module) {
|
||||
g_warning ("Could not load plugin %s: %s", path, g_module_error ());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (module, "mm_plugin_major_version", (gpointer *) &major_plugin_version)) {
|
||||
g_warning ("Could not load plugin %s: Missing major version info", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*major_plugin_version != MM_PLUGIN_MAJOR_VERSION) {
|
||||
g_warning ("Could not load plugin %s: Plugin major version %d, %d is required",
|
||||
path, *major_plugin_version, MM_PLUGIN_MAJOR_VERSION);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (module, "mm_plugin_minor_version", (gpointer *) &minor_plugin_version)) {
|
||||
g_warning ("Could not load plugin %s: Missing minor version info", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*minor_plugin_version != MM_PLUGIN_MINOR_VERSION) {
|
||||
g_warning ("Could not load plugin %s: Plugin minor version %d, %d is required",
|
||||
path, *minor_plugin_version, MM_PLUGIN_MINOR_VERSION);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (module, "mm_plugin_create", (gpointer *) &plugin_create_func)) {
|
||||
g_warning ("Could not load plugin %s: %s", path, g_module_error ());
|
||||
goto out;
|
||||
}
|
||||
|
||||
plugin = (*plugin_create_func) ();
|
||||
if (plugin) {
|
||||
g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
|
||||
g_message ("Loaded plugin %s", mm_plugin_get_name (plugin));
|
||||
} else
|
||||
g_warning ("Could not load plugin %s: initialization failed", path);
|
||||
|
||||
out:
|
||||
if (!plugin)
|
||||
g_module_close (module);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
static void
|
||||
load_plugins (MMManager *manager)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
GDir *dir;
|
||||
const char *fname;
|
||||
|
||||
if (!g_module_supported ()) {
|
||||
g_warning ("GModules are not supported on your platform!");
|
||||
return;
|
||||
}
|
||||
|
||||
dir = g_dir_open (PLUGINDIR, 0, NULL);
|
||||
if (!dir) {
|
||||
g_warning ("No plugins found");
|
||||
return;
|
||||
}
|
||||
|
||||
while ((fname = g_dir_read_name (dir)) != NULL) {
|
||||
char *path;
|
||||
MMPlugin *plugin;
|
||||
|
||||
if (!strstr (fname, G_MODULE_SUFFIX))
|
||||
continue;
|
||||
|
||||
path = g_module_build_path (PLUGINDIR, fname);
|
||||
plugin = load_plugin (path);
|
||||
g_free (path);
|
||||
|
||||
if (plugin)
|
||||
priv->plugins = g_slist_append (priv->plugins, plugin);
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
}
|
||||
|
||||
MMManager *
|
||||
mm_manager_new (void)
|
||||
{
|
||||
return g_object_new (MM_TYPE_MANAGER, NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_driver_name (LibHalContext *ctx, const char *udi)
|
||||
{
|
||||
char *parent_udi;
|
||||
char *driver = NULL;
|
||||
|
||||
parent_udi = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
|
||||
if (parent_udi) {
|
||||
driver = libhal_device_get_property_string (ctx, parent_udi, "info.linux.driver", NULL);
|
||||
libhal_free_string (parent_udi);
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
static MMModem *
|
||||
create_generic_modem (MMManager *manager, const char *udi)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
MMModem *modem;
|
||||
char **capabilities;
|
||||
char **iter;
|
||||
char *serial_device;
|
||||
char *driver;
|
||||
gboolean type_gsm = FALSE;
|
||||
gboolean type_cdma = FALSE;
|
||||
|
||||
capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "modem.command_sets", NULL);
|
||||
for (iter = capabilities; iter && *iter; iter++) {
|
||||
if (!strcmp (*iter, "GSM-07.07")) {
|
||||
type_gsm = TRUE;
|
||||
break;
|
||||
}
|
||||
if (!strcmp (*iter, "IS-707-A")) {
|
||||
type_cdma = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev (capabilities);
|
||||
|
||||
if (!type_gsm && !type_cdma)
|
||||
return NULL;
|
||||
|
||||
serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL);
|
||||
g_return_val_if_fail (serial_device != NULL, NULL);
|
||||
|
||||
driver = get_driver_name (priv->hal_ctx, udi);
|
||||
g_return_val_if_fail (driver != NULL, NULL);
|
||||
|
||||
if (type_gsm)
|
||||
modem = mm_generic_gsm_new (serial_device, driver);
|
||||
else
|
||||
modem = mm_generic_cdma_new (serial_device, driver);
|
||||
|
||||
g_free (serial_device);
|
||||
g_free (driver);
|
||||
|
||||
return modem;
|
||||
}
|
||||
|
||||
static void
|
||||
add_modem (MMManager *manager, const char *udi, MMModem *modem)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
g_debug ("Added modem %s", udi);
|
||||
g_hash_table_insert (priv->modems, g_strdup (udi), modem);
|
||||
dbus_g_connection_register_g_object (priv->connection, udi, G_OBJECT (modem));
|
||||
|
||||
g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
|
||||
}
|
||||
|
||||
static MMModem *
|
||||
modem_exists (MMManager *manager, const char *udi)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
return (MMModem *) g_hash_table_lookup (priv->modems, udi);
|
||||
}
|
||||
|
||||
static void
|
||||
create_initial_modems_from_plugins (MMManager *manager)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
GSList *iter;
|
||||
|
||||
for (iter = priv->plugins; iter; iter = iter->next) {
|
||||
MMPlugin *plugin = MM_PLUGIN (iter->data);
|
||||
GSList *udis;
|
||||
GSList *udi_iter;
|
||||
|
||||
udis = mm_plugin_list_supported_udis (plugin, priv->hal_ctx);
|
||||
for (udi_iter = udis; udi_iter; udi_iter = udi_iter->next) {
|
||||
char *udi = (char *) udi_iter->data;
|
||||
MMModem *modem;
|
||||
|
||||
if (modem_exists (manager, udi)) {
|
||||
g_warning ("Modem for UDI %s already exists, ignoring", udi);
|
||||
continue;
|
||||
}
|
||||
|
||||
modem = mm_plugin_create_modem (plugin, priv->hal_ctx, udi);
|
||||
if (modem)
|
||||
add_modem (manager, udi, modem);
|
||||
else
|
||||
g_warning ("Plugin failed to create modem for UDI %s", udi);
|
||||
}
|
||||
|
||||
g_slist_foreach (udis, (GFunc) g_free, NULL);
|
||||
g_slist_free (udis);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_initial_modems_generic (MMManager *manager)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
char **devices;
|
||||
int num_devices;
|
||||
int i;
|
||||
DBusError err;
|
||||
|
||||
dbus_error_init (&err);
|
||||
devices = libhal_find_device_by_capability (priv->hal_ctx, "modem", &num_devices, &err);
|
||||
if (dbus_error_is_set (&err)) {
|
||||
g_warning ("Could not list HAL devices: %s", err.message);
|
||||
dbus_error_free (&err);
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
char *udi = devices[i];
|
||||
MMModem *modem;
|
||||
|
||||
if (modem_exists (manager, udi))
|
||||
/* Already exists, most likely handled by a plugin */
|
||||
continue;
|
||||
|
||||
modem = create_generic_modem (manager, udi);
|
||||
if (modem)
|
||||
add_modem (manager, g_strdup (udi), modem);
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (devices);
|
||||
}
|
||||
|
||||
static void
|
||||
create_initial_modems (MMManager *manager)
|
||||
{
|
||||
create_initial_modems_from_plugins (manager);
|
||||
create_initial_modems_generic (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
enumerate_devices_cb (gpointer key, gpointer val, gpointer user_data)
|
||||
{
|
||||
GPtrArray **devices = (GPtrArray **) user_data;
|
||||
|
||||
g_ptr_array_add (*devices, g_strdup ((char *) key));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
impl_manager_enumerate_devices (MMManager *manager,
|
||||
GPtrArray **devices,
|
||||
GError **err)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
*devices = g_ptr_array_sized_new (g_hash_table_size (priv->modems));
|
||||
g_hash_table_foreach (priv->modems, enumerate_devices_cb, devices);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added (LibHalContext *ctx, const char *udi)
|
||||
{
|
||||
MMManager *manager = MM_MANAGER (libhal_ctx_get_user_data (ctx));
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
GSList *iter;
|
||||
MMModem *modem = NULL;
|
||||
|
||||
if (modem_exists (manager, udi))
|
||||
/* Shouldn't happen */
|
||||
return;
|
||||
|
||||
for (iter = priv->plugins; iter && modem == NULL; iter = iter->next) {
|
||||
MMPlugin *plugin = MM_PLUGIN (iter->data);
|
||||
|
||||
if (mm_plugin_supports_udi (plugin, ctx, udi)) {
|
||||
modem = mm_plugin_create_modem (plugin, ctx, udi);
|
||||
if (modem)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modem)
|
||||
/* None of the plugins supported the udi, try generic devices */
|
||||
modem = create_generic_modem (manager, udi);
|
||||
|
||||
if (modem)
|
||||
add_modem (manager, udi, modem);
|
||||
}
|
||||
|
||||
static void
|
||||
device_removed (LibHalContext *ctx, const char *udi)
|
||||
{
|
||||
MMManager *manager = MM_MANAGER (libhal_ctx_get_user_data (ctx));
|
||||
MMModem *modem;
|
||||
|
||||
modem = modem_exists (manager, udi);
|
||||
if (modem) {
|
||||
g_debug ("Removed modem %s", udi);
|
||||
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
|
||||
g_hash_table_remove (MM_MANAGER_GET_PRIVATE (manager)->modems, udi);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_new_capability (LibHalContext *ctx, const char *udi, const char *capability)
|
||||
{
|
||||
device_added (ctx, udi);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_manager_init (MMManager *manager)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
GError *err = NULL;
|
||||
DBusError dbus_error;
|
||||
|
||||
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
|
||||
if (!priv->connection)
|
||||
g_error ("Could not connect to system bus.");
|
||||
|
||||
dbus_g_connection_register_g_object (priv->connection,
|
||||
MM_DBUS_PATH,
|
||||
G_OBJECT (manager));
|
||||
|
||||
priv->hal_ctx = libhal_ctx_new ();
|
||||
if (!priv->hal_ctx)
|
||||
g_error ("Could not get connection to the HAL service.");
|
||||
|
||||
libhal_ctx_set_dbus_connection (priv->hal_ctx, dbus_g_connection_get_connection (priv->connection));
|
||||
|
||||
dbus_error_init (&dbus_error);
|
||||
if (!libhal_ctx_init (priv->hal_ctx, &dbus_error))
|
||||
g_error ("libhal_ctx_init() failed: %s\n"
|
||||
"Make sure the hal daemon is running?",
|
||||
dbus_error.message);
|
||||
|
||||
load_plugins (manager);
|
||||
|
||||
libhal_ctx_set_user_data (priv->hal_ctx, manager);
|
||||
libhal_ctx_set_device_added (priv->hal_ctx, device_added);
|
||||
libhal_ctx_set_device_removed (priv->hal_ctx, device_removed);
|
||||
libhal_ctx_set_device_new_capability (priv->hal_ctx, device_new_capability);
|
||||
|
||||
create_initial_modems (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (object);
|
||||
|
||||
g_hash_table_destroy (priv->modems);
|
||||
|
||||
g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (priv->plugins);
|
||||
|
||||
if (priv->hal_ctx) {
|
||||
libhal_ctx_shutdown (priv->hal_ctx, NULL);
|
||||
libhal_ctx_free (priv->hal_ctx);
|
||||
}
|
||||
|
||||
if (priv->connection)
|
||||
dbus_g_connection_unref (priv->connection);
|
||||
|
||||
G_OBJECT_CLASS (mm_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mm_manager_class_init (MMManagerClass *manager_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (MMManagerPrivate));
|
||||
|
||||
/* Virtual methods */
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* Signals */
|
||||
signals[DEVICE_ADDED] =
|
||||
g_signal_new ("device-added",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (MMManagerClass, device_added),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
signals[DEVICE_REMOVED] =
|
||||
g_signal_new ("device-removed",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (MMManagerClass, device_removed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (manager_class),
|
||||
&dbus_glib_mm_manager_object_info);
|
||||
|
||||
dbus_g_error_domain_register (MM_MODEM_ERROR, NULL, MM_TYPE_MODEM_ERROR);
|
||||
}
|
36
src/mm-manager.h
Normal file
36
src/mm-manager.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_MANAGER_H
|
||||
#define MM_MANAGER_H
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib-object.h>
|
||||
#include "mm-modem.h"
|
||||
|
||||
#define MM_TYPE_MANAGER (mm_manager_get_type ())
|
||||
#define MM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MANAGER, MMManager))
|
||||
#define MM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MANAGER, MMManagerClass))
|
||||
#define MM_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MANAGER))
|
||||
#define MM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), MM_TYPE_MANAGER))
|
||||
#define MM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MANAGER, MMManagerClass))
|
||||
|
||||
#define MM_DBUS_SERVICE "org.freedesktop.ModemManager"
|
||||
#define MM_DBUS_PATH "/org/freedesktop/ModemManager"
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} MMManager;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
/* Signals */
|
||||
void (*device_added) (MMManager *manager, MMModem *device);
|
||||
void (*device_removed) (MMManager *manager, MMModem *device);
|
||||
} MMManagerClass;
|
||||
|
||||
GType mm_manager_get_type (void);
|
||||
|
||||
MMManager *mm_manager_new (void);
|
||||
|
||||
#endif /* MM_MANAGER_H */
|
37
src/mm-modem-error.c
Normal file
37
src/mm-modem-error.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include "mm-modem-error.h"
|
||||
|
||||
GQuark
|
||||
mm_modem_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
|
||||
if (ret == 0)
|
||||
ret = g_quark_from_static_string ("mm_modem_error");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
|
||||
|
||||
GType
|
||||
mm_modem_error_get_type (void)
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if (etype == 0) {
|
||||
static const GEnumValue values[] = {
|
||||
ENUM_ENTRY (MM_MODEM_ERROR_GENERAL, "GeneralError"),
|
||||
ENUM_ENTRY (MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, "OperationNotSupported"),
|
||||
ENUM_ENTRY (MM_MODEM_ERROR_PIN_NEEDED, "PINNeeded"),
|
||||
ENUM_ENTRY (MM_MODEM_ERROR_PUK_NEEDED, "PUKNeeded"),
|
||||
ENUM_ENTRY (MM_MODEM_ERROR_INVALID_SECRET, "InvalidSecret"),
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
etype = g_enum_register_static ("MMModemError", values);
|
||||
}
|
||||
|
||||
return etype;
|
||||
}
|
22
src/mm-modem-error.h
Normal file
22
src/mm-modem-error.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_MODEM_ERROR_H
|
||||
#define MM_MODEM_ERROR_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
enum {
|
||||
MM_MODEM_ERROR_GENERAL = 0,
|
||||
MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
MM_MODEM_ERROR_PIN_NEEDED,
|
||||
MM_MODEM_ERROR_PUK_NEEDED,
|
||||
MM_MODEM_ERROR_INVALID_SECRET
|
||||
};
|
||||
|
||||
#define MM_MODEM_ERROR (mm_modem_error_quark ())
|
||||
#define MM_TYPE_MODEM_ERROR (mm_modem_error_get_type ())
|
||||
|
||||
GQuark mm_modem_error_quark (void);
|
||||
GType mm_modem_error_get_type (void);
|
||||
|
||||
#endif /* MM_MODEM_ERROR_H */
|
460
src/mm-modem.c
Normal file
460
src/mm-modem.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <string.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include "mm-modem.h"
|
||||
#include "mm-modem-error.h"
|
||||
#include "mm-callback-info.h"
|
||||
|
||||
static void impl_modem_enable (MMModem *modem, gboolean enable, DBusGMethodInvocation *context);
|
||||
static void impl_modem_set_pin (MMModem *modem, const char *pin, DBusGMethodInvocation *context);
|
||||
static void impl_modem_register (MMModem *modem, const char *network_id, DBusGMethodInvocation *context);
|
||||
static void impl_modem_connect (MMModem *modem, const char *number, const char *apn, DBusGMethodInvocation *context);
|
||||
static void impl_modem_disconnect (MMModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_modem_scan (MMModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_modem_get_signal_quality (MMModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_modem_set_band (MMModem *modem, guint32 band, DBusGMethodInvocation *context);
|
||||
static void impl_modem_get_band (MMModem *modem, DBusGMethodInvocation *context);
|
||||
static void impl_modem_set_network_mode (MMModem *modem, guint32 mode, DBusGMethodInvocation *context);
|
||||
static void impl_modem_get_network_mode (MMModem *modem, DBusGMethodInvocation *context);
|
||||
|
||||
#include "mm-modem-glue.h"
|
||||
|
||||
enum {
|
||||
SIGNAL_QUALITY,
|
||||
NETWORK_MODE,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
async_op_not_supported (MMModem *self,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_new (self, callback, user_data);
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
"%s", "Operation not supported");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
async_call_done (MMModem *modem, GError *error, gpointer user_data)
|
||||
{
|
||||
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
|
||||
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
else
|
||||
dbus_g_method_return (context);
|
||||
}
|
||||
|
||||
static void
|
||||
uint_op_not_supported (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MMCallbackInfo *info;
|
||||
|
||||
info = mm_callback_info_uint_new (self, callback, user_data);
|
||||
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
|
||||
"%s", "Operation not supported");
|
||||
mm_callback_info_schedule (info);
|
||||
}
|
||||
|
||||
static void
|
||||
uint_call_done (MMModem *modem, guint32 result, GError *error, gpointer user_data)
|
||||
{
|
||||
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
|
||||
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
else
|
||||
dbus_g_method_return (context, result);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_enable (MMModem *self,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->enable)
|
||||
MM_MODEM_GET_INTERFACE (self)->enable (self, enable, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_enable (MMModem *modem,
|
||||
gboolean enable,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_enable (modem, enable, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_set_pin (MMModem *self,
|
||||
const char *pin,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
g_return_if_fail (pin != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->set_pin)
|
||||
MM_MODEM_GET_INTERFACE (self)->set_pin (self, pin, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_set_pin (MMModem *modem,
|
||||
const char *pin,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_set_pin (modem, pin, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_register (MMModem *self,
|
||||
const char *network_id,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->do_register)
|
||||
MM_MODEM_GET_INTERFACE (self)->do_register (self, network_id, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_register (MMModem *modem,
|
||||
const char *network_id,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
const char *id;
|
||||
|
||||
/* DBus does not support NULL strings, so the caller should pass an empty string
|
||||
for manual registration. */
|
||||
if (strlen (network_id) < 1)
|
||||
id = NULL;
|
||||
else
|
||||
id = network_id;
|
||||
|
||||
mm_modem_register (modem, id, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_connect (MMModem *self,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
g_return_if_fail (number != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->connect)
|
||||
MM_MODEM_GET_INTERFACE (self)->connect (self, number, apn, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_connect (MMModem *modem,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
const char *real_apn;
|
||||
|
||||
/* DBus does not support NULL strings, so the caller should pass an empty string
|
||||
for no APN. */
|
||||
if (strlen (apn) < 1)
|
||||
real_apn = NULL;
|
||||
else
|
||||
real_apn = apn;
|
||||
|
||||
mm_modem_connect (modem, number, real_apn, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_disconnect (MMModem *self,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->disconnect)
|
||||
MM_MODEM_GET_INTERFACE (self)->disconnect (self, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_disconnect (MMModem *modem,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_disconnect (modem, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_scan (MMModem *self,
|
||||
MMModemScanFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->scan)
|
||||
MM_MODEM_GET_INTERFACE (self)->scan (self, callback, user_data);
|
||||
else
|
||||
/* FIXME */ ;
|
||||
}
|
||||
|
||||
static void
|
||||
impl_scan_done (MMModem *modem, GPtrArray *results, GError *error, gpointer user_data)
|
||||
{
|
||||
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
|
||||
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
else
|
||||
dbus_g_method_return (context, results);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_scan (MMModem *modem,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_scan (modem, impl_scan_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_get_signal_quality (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->get_signal_quality)
|
||||
MM_MODEM_GET_INTERFACE (self)->get_signal_quality (self, callback, user_data);
|
||||
else
|
||||
uint_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_get_signal_quality (MMModem *modem, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_get_signal_quality (modem, uint_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_set_band (MMModem *self,
|
||||
MMModemBand band,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->set_band)
|
||||
MM_MODEM_GET_INTERFACE (self)->set_band (self, band, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_set_band (MMModem *modem, guint32 band, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_set_band (modem, band, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_get_band (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->get_band)
|
||||
MM_MODEM_GET_INTERFACE (self)->get_band (self, callback, user_data);
|
||||
else
|
||||
uint_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_get_band (MMModem *modem, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_get_band (modem, uint_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_set_network_mode (MMModem *self,
|
||||
MMModemNetworkMode mode,
|
||||
MMModemFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->set_network_mode)
|
||||
MM_MODEM_GET_INTERFACE (self)->set_network_mode (self, mode, callback, user_data);
|
||||
else
|
||||
async_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_set_network_mode (MMModem *modem, guint32 mode, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_set_network_mode (modem, mode, async_call_done, context);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_get_network_mode (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
if (MM_MODEM_GET_INTERFACE (self)->get_network_mode)
|
||||
MM_MODEM_GET_INTERFACE (self)->get_network_mode (self, callback, user_data);
|
||||
else
|
||||
uint_op_not_supported (self, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_modem_get_network_mode (MMModem *modem, DBusGMethodInvocation *context)
|
||||
{
|
||||
mm_modem_get_network_mode (modem, uint_call_done, context);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mm_modem_install_dbus_info (GType type)
|
||||
{
|
||||
dbus_g_object_type_install_info (type, &dbus_glib_mm_modem_object_info);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_signal_quality (MMModem *self,
|
||||
guint32 quality)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_QUALITY], 0, quality);
|
||||
}
|
||||
|
||||
void
|
||||
mm_modem_network_mode (MMModem *self,
|
||||
MMModemNetworkMode mode)
|
||||
{
|
||||
g_return_if_fail (MM_IS_MODEM (self));
|
||||
|
||||
g_signal_emit (self, signals[NETWORK_MODE], 0, mode);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
mm_modem_init (gpointer g_iface)
|
||||
{
|
||||
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
/* Properties */
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_string (MM_MODEM_DATA_DEVICE,
|
||||
"DataDevice",
|
||||
"DataDevice",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_string (MM_MODEM_DRIVER,
|
||||
"Driver",
|
||||
"Driver",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_uint (MM_MODEM_TYPE,
|
||||
"Type",
|
||||
"Type",
|
||||
0, G_MAXUINT32, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/* Signals */
|
||||
signals[SIGNAL_QUALITY] =
|
||||
g_signal_new ("signal-quality",
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (MMModem, signal_quality),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
|
||||
signals[NETWORK_MODE] =
|
||||
g_signal_new ("network-mode",
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (MMModem, network_mode),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
GType
|
||||
mm_modem_get_type (void)
|
||||
{
|
||||
static GType modem_type = 0;
|
||||
|
||||
if (!G_UNLIKELY (modem_type)) {
|
||||
const GTypeInfo modem_info = {
|
||||
sizeof (MMModem), /* class_size */
|
||||
mm_modem_init, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL
|
||||
};
|
||||
|
||||
modem_type = g_type_register_static (G_TYPE_INTERFACE,
|
||||
"MMModem",
|
||||
&modem_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (modem_type, G_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return modem_type;
|
||||
}
|
196
src/mm-modem.h
Normal file
196
src/mm-modem.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_MODEM_H
|
||||
#define MM_MODEM_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define MM_TYPE_MODEM (mm_modem_get_type ())
|
||||
#define MM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM, MMModem))
|
||||
#define MM_IS_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM))
|
||||
#define MM_MODEM_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM, MMModem))
|
||||
|
||||
#define MM_MODEM_DATA_DEVICE "data-device"
|
||||
#define MM_MODEM_DRIVER "driver"
|
||||
#define MM_MODEM_TYPE "type"
|
||||
|
||||
#define MM_MODEM_TYPE_GSM 1
|
||||
#define MM_MODEM_TYPE_CDMA 2
|
||||
|
||||
typedef enum {
|
||||
MM_MODEM_PROP_FIRST = 0x1000,
|
||||
|
||||
MM_MODEM_PROP_DATA_DEVICE = MM_MODEM_PROP_FIRST,
|
||||
MM_MODEM_PROP_DRIVER,
|
||||
MM_MODEM_PROP_TYPE
|
||||
} MMModemProp;
|
||||
|
||||
typedef enum {
|
||||
MM_MODEM_NETWORK_MODE_ANY = 0,
|
||||
MM_MODEM_NETWORK_MODE_GPRS = 1,
|
||||
MM_MODEM_NETWORK_MODE_EDGE = 2,
|
||||
MM_MODEM_NETWORK_MODE_3G = 3,
|
||||
MM_MODEM_NETWORK_MODE_HSDPA = 4,
|
||||
MM_MODEM_NETWORK_MODE_PREFER_2G = 5,
|
||||
MM_MODEM_NETWORK_MODE_PREFER_3G = 6
|
||||
} MMModemNetworkMode;
|
||||
|
||||
typedef enum {
|
||||
MM_MODEM_BAND_ANY = 0,
|
||||
MM_MODEM_BAND_EGSM = 1, /* 900 MHz */
|
||||
MM_MODEM_BAND_DCS = 2, /* 1800 MHz */
|
||||
MM_MODEM_BAND_PCS = 3, /* 1900 MHz */
|
||||
MM_MODEM_BAND_G850 = 4, /* 850 MHz */
|
||||
MM_MODEM_BAND_U2100 = 5, /* WCDMA 2100 MHz (Class I) */
|
||||
MM_MODEM_BAND_U1700 = 6, /* WCDMA 3GPP UMTS1800 MHz (Class III) */
|
||||
MM_MODEM_BAND_17IV = 7, /* WCDMA 3GPP AWS 1700/2100 MHz (Class IV) */
|
||||
MM_MODEM_BAND_U800 = 8, /* WCDMA 3GPP UMTS800 MHz (Class VI) */
|
||||
MM_MODEM_BAND_U850 = 9, /* WCDMA 3GPP UMTS850 MHz (Class V) */
|
||||
MM_MODEM_BAND_U900 = 10, /* WCDMA 3GPP UMTS900 MHz (Class VIII) */
|
||||
MM_MODEM_BAND_U17IX = 11 /* WCDMA 3GPP UMTS MHz (Class IX) */
|
||||
} MMModemBand;
|
||||
|
||||
typedef struct _MMModem MMModem;
|
||||
|
||||
typedef void (*MMModemFn) (MMModem *modem,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMModemUIntFn) (MMModem *modem,
|
||||
guint32 result,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMModemScanFn) (MMModem *modem,
|
||||
GPtrArray *results,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
struct _MMModem {
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/* Methods */
|
||||
void (*enable) (MMModem *self,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*set_pin) (MMModem *self,
|
||||
const char *pin,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
/* 'register' is a reserved word */
|
||||
void (*do_register) (MMModem *self,
|
||||
const char *network_id,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*connect) (MMModem *self,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*disconnect) (MMModem *self,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*scan) (MMModem *self,
|
||||
MMModemScanFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*get_signal_quality) (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*set_band) (MMModem *self,
|
||||
MMModemBand band,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*get_band) (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*set_network_mode) (MMModem *self,
|
||||
MMModemNetworkMode mode,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (*get_network_mode) (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
/* Signals */
|
||||
void (*signal_quality) (MMModem *self,
|
||||
guint32 quality);
|
||||
|
||||
void (*network_mode) (MMModem *self,
|
||||
MMModemNetworkMode mode);
|
||||
};
|
||||
|
||||
GType mm_modem_get_type (void);
|
||||
|
||||
void mm_modem_enable (MMModem *self,
|
||||
gboolean enable,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_set_pin (MMModem *self,
|
||||
const char *pin,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_register (MMModem *self,
|
||||
const char *network_id,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_connect (MMModem *self,
|
||||
const char *number,
|
||||
const char *apn,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_disconnect (MMModem *self,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_scan (MMModem *self,
|
||||
MMModemScanFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_get_signal_quality (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_set_band (MMModem *self,
|
||||
MMModemBand band,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_get_band (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_set_network_mode (MMModem *self,
|
||||
MMModemNetworkMode mode,
|
||||
MMModemFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_modem_get_network_mode (MMModem *self,
|
||||
MMModemUIntFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
/* Protected */
|
||||
|
||||
void mm_modem_install_dbus_info (GType type);
|
||||
|
||||
void mm_modem_signal_quality (MMModem *self,
|
||||
guint32 quality);
|
||||
|
||||
void mm_modem_network_mode (MMModem *self,
|
||||
MMModemNetworkMode mode);
|
||||
|
||||
#endif /* MM_MODEM_H */
|
81
src/mm-plugin.c
Normal file
81
src/mm-plugin.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#include "mm-plugin.h"
|
||||
|
||||
const char *
|
||||
mm_plugin_get_name (MMPlugin *plugin)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
|
||||
|
||||
return MM_PLUGIN_GET_INTERFACE (plugin)->get_name (plugin);
|
||||
}
|
||||
|
||||
char **
|
||||
mm_plugin_list_supported_udis (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
|
||||
g_return_val_if_fail (hal_ctx != NULL, NULL);
|
||||
|
||||
return MM_PLUGIN_GET_INTERFACE (plugin)->list_supported_udis (plugin, hal_ctx);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_plugin_supports_udi (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE);
|
||||
g_return_val_if_fail (hal_ctx != NULL, FALSE);
|
||||
g_return_val_if_fail (udi != NULL, FALSE);
|
||||
|
||||
return MM_PLUGIN_GET_INTERFACE (plugin)->supports_udi (plugin, hal_ctx, udi);
|
||||
}
|
||||
|
||||
MMModem *
|
||||
mm_plugin_create_modem (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi)
|
||||
{
|
||||
g_return_val_if_fail (MM_IS_PLUGIN (plugin), NULL);
|
||||
g_return_val_if_fail (hal_ctx != NULL, NULL);
|
||||
g_return_val_if_fail (udi != NULL, NULL);
|
||||
|
||||
return MM_PLUGIN_GET_INTERFACE (plugin)->create_modem (plugin, hal_ctx, udi);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
mm_plugin_init (gpointer g_iface)
|
||||
{
|
||||
}
|
||||
|
||||
GType
|
||||
mm_plugin_get_type (void)
|
||||
{
|
||||
static GType plugin_type = 0;
|
||||
|
||||
if (!G_UNLIKELY (plugin_type)) {
|
||||
const GTypeInfo plugin_info = {
|
||||
sizeof (MMPlugin), /* class_size */
|
||||
mm_plugin_init, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL
|
||||
};
|
||||
|
||||
plugin_type = g_type_register_static (G_TYPE_INTERFACE,
|
||||
"MMPlugin",
|
||||
&plugin_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (plugin_type, G_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return plugin_type;
|
||||
}
|
55
src/mm-plugin.h
Normal file
55
src/mm-plugin.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_PLUGIN_H
|
||||
#define MM_PLUGIN_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <libhal.h>
|
||||
#include <mm-modem.h>
|
||||
|
||||
#define MM_PLUGIN_MAJOR_VERSION 1
|
||||
#define MM_PLUGIN_MINOR_VERSION 0
|
||||
|
||||
#define MM_TYPE_PLUGIN (mm_plugin_get_type ())
|
||||
#define MM_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN, MMPlugin))
|
||||
#define MM_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN))
|
||||
#define MM_PLUGIN_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_PLUGIN, MMPlugin))
|
||||
|
||||
typedef struct _MMPlugin MMPlugin;
|
||||
|
||||
typedef MMPlugin *(*MMPluginCreateFunc) (void);
|
||||
|
||||
struct _MMPlugin {
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/* Methods */
|
||||
const char *(*get_name) (MMPlugin *self);
|
||||
|
||||
char **(*list_supported_udis) (MMPlugin *self,
|
||||
LibHalContext *hal_ctx);
|
||||
|
||||
gboolean (*supports_udi) (MMPlugin *self,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi);
|
||||
|
||||
MMModem *(*create_modem) (MMPlugin *self,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi);
|
||||
};
|
||||
|
||||
GType mm_plugin_get_type (void);
|
||||
|
||||
const char *mm_plugin_get_name (MMPlugin *plugin);
|
||||
|
||||
char **mm_plugin_list_supported_udis (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx);
|
||||
|
||||
gboolean mm_plugin_supports_udi (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi);
|
||||
|
||||
MMModem *mm_plugin_create_modem (MMPlugin *plugin,
|
||||
LibHalContext *hal_ctx,
|
||||
const char *udi);
|
||||
|
||||
#endif /* MM_PLUGIN_H */
|
1117
src/mm-serial.c
Normal file
1117
src/mm-serial.c
Normal file
File diff suppressed because it is too large
Load Diff
85
src/mm-serial.h
Normal file
85
src/mm-serial.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef MM_SERIAL_H
|
||||
#define MM_SERIAL_H
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#define MM_TYPE_SERIAL (mm_serial_get_type ())
|
||||
#define MM_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SERIAL, MMSerial))
|
||||
#define MM_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SERIAL, MMSerialClass))
|
||||
#define MM_IS_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SERIAL))
|
||||
#define MM_IS_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SERIAL))
|
||||
#define MM_SERIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SERIAL, MMSerialClass))
|
||||
|
||||
#define MM_SERIAL_DEVICE "device"
|
||||
#define MM_SERIAL_BAUD "baud"
|
||||
#define MM_SERIAL_BITS "bits"
|
||||
#define MM_SERIAL_PARITY "parity"
|
||||
#define MM_SERIAL_STOPBITS "stopbits"
|
||||
#define MM_SERIAL_SEND_DELAY "send-delay"
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} MMSerial;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
} MMSerialClass;
|
||||
|
||||
GType mm_serial_get_type (void);
|
||||
|
||||
typedef void (*MMSerialGetReplyFn) (MMSerial *serial,
|
||||
const char *reply,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMSerialWaitForReplyFn) (MMSerial *serial,
|
||||
int reply_index,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMSerialWaitQuietFn) (MMSerial *serial,
|
||||
gboolean timed_out,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*MMSerialFlashFn) (MMSerial *serial,
|
||||
gpointer user_data);
|
||||
|
||||
const char *mm_serial_get_device (MMSerial *serial);
|
||||
|
||||
gboolean mm_serial_open (MMSerial *self);
|
||||
|
||||
void mm_serial_close (MMSerial *self);
|
||||
gboolean mm_serial_send_command (MMSerial *self,
|
||||
GByteArray *command);
|
||||
|
||||
gboolean mm_serial_send_command_string (MMSerial *self,
|
||||
const char *str);
|
||||
|
||||
guint mm_serial_get_reply (MMSerial *self,
|
||||
guint timeout,
|
||||
const char *terminators,
|
||||
MMSerialGetReplyFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
guint mm_serial_wait_for_reply (MMSerial *self,
|
||||
guint timeout,
|
||||
char **responses,
|
||||
char **terminators,
|
||||
MMSerialWaitForReplyFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
void mm_serial_wait_quiet (MMSerial *self,
|
||||
guint timeout,
|
||||
guint quiet_time,
|
||||
MMSerialWaitQuietFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
guint mm_serial_flash (MMSerial *self,
|
||||
guint32 flash_time,
|
||||
MMSerialFlashFn callback,
|
||||
gpointer user_data);
|
||||
|
||||
GIOChannel *mm_serial_get_io_channel (MMSerial *self);
|
||||
|
||||
#endif /* MM_SERIAL_H */
|
Reference in New Issue
Block a user