3 (c) 2010 Gregor Riepl <onitake@gmail.com>
5 Tethering utility for Maemo
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
28 #include <hildon/hildon.h>
29 #include <dbus/dbus-glib-lowlevel.h>
34 #define MTETHERD_STATUS_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, TYPE_MTETHERD_STATUS_PLUGIN, MTetherDStatusPluginPrivate))
36 struct _MTetherDStatusPluginPrivate {
37 GtkWidget *enable_button;
40 DBusGConnection *dbus_connection;
41 LibHalContext *hal_context;
44 static const char *USBDEV_PATH = "/org/freedesktop/Hal/devices/usb_device_1d6b_2_musb_hdrc";
45 static const char *USBNET_MODULE = "g_ether";
48 #define IMAGE_DIR "/usr/share/pixmaps"
51 #define SBIN_DIR "/usr/sbin"
54 HD_DEFINE_PLUGIN_MODULE(MTetherDStatusPlugin, mtetherd_status_plugin, HD_TYPE_STATUS_MENU_ITEM);
56 static void mtetherd_status_plugin_class_finalize(MTetherDStatusPluginClass *klass) { }
58 static void mtetherd_status_plugin_finalize(GObject *object) {
59 g_message("Destroying mtetherd status plugin");
61 MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(object);
63 if (plugin && plugin->priv) {
64 if (plugin->priv->hal_context) {
65 libhal_ctx_shutdown(plugin->priv->hal_context, NULL);
66 libhal_ctx_free(plugin->priv->hal_context);
68 if (plugin->priv->dbus_connection) {
69 dbus_g_connection_unref(plugin->priv->dbus_connection);
74 static void mtetherd_status_plugin_class_init(MTetherDStatusPluginClass *klass) {
75 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
77 gobject_class->finalize = mtetherd_status_plugin_finalize;
78 g_type_class_add_private(klass, sizeof(MTetherDStatusPluginPrivate));
81 static gboolean get_usbnet_enabled(MTetherDStatusPlugin *plugin) {
82 g_message("Scanning /proc/modules");
83 //hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Scanning /proc/modules");
85 FILE *fp = fopen("/proc/modules", "r");
89 gboolean found = FALSE;
91 while (!found && getline(&line, NULL, fp) != -1) {
92 g_message("Checking if '%s' contains g_ether...", line);
93 if (strncmp(line, USBNET_MODULE, sizeof(USBNET_MODULE) - 1) == 0) {
94 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Found g_ether");
104 static gboolean launch_usbnet_script(gboolean enable) {
107 arg = SBIN_DIR "mtetherd-usbnet-enable.sh";
109 arg = SBIN_DIR "mtetherd-usbnet-disable.sh";
111 g_debug("Launching %s", arg);
112 const char *command[] = { "/usr/bin/sudo", arg, NULL };
115 if (execv(command[0], (char **const) command) == -1) {
118 } else if (pid == -1) {
126 static void enable_button_set_text(GtkWidget *button, gboolean enabled) {
128 hildon_button_set_text(HILDON_BUTTON(button), "Toggle USB Networking", "Enabled");
130 hildon_button_set_text(HILDON_BUTTON(button), "Toggle USB Networking", "Disabled");
134 static void enable_button_clicked(GtkWidget *button, gpointer data) {
135 MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(data);
137 if (plugin && plugin->priv && button == plugin->priv->enable_button) {
138 if (plugin->priv->net_on) {
139 if (!launch_usbnet_script(FALSE)) {
140 g_error("Error starting USB networking");
143 if (!launch_usbnet_script(TRUE)) {
144 g_error("Error starting USB networking");
150 static void mtetherd_status_plugin_usb_plugged_show(MTetherDStatusPlugin *plugin) {
152 if (plugin->priv && plugin->priv->hal_context) {
154 dbus_error_init(&derr);
155 dbus_bool_t plugged = libhal_device_get_property_bool(plugin->priv->hal_context, USBDEV_PATH, "button.state.value", &derr);
156 if (dbus_error_is_set(&derr)) {
157 g_warning("Error getting USB plugged status (%s): %s", derr.name, derr.message);
158 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Error getting USB plugged status (%s): %s", derr.name, derr.message);
159 dbus_error_free(&derr);
161 plugin->priv->usb_on = plugged;
162 if (plugin->priv->usb_on) {
163 gtk_widget_show(GTK_WIDGET(plugin));
165 gtk_widget_hide(GTK_WIDGET(plugin));
170 //gtk_widget_show(GTK_WIDGET(plugin));
175 static void mtetherd_status_plugin_mapped(GtkWidget *widget, gpointer data) {
176 hildon_banner_show_informationf(widget, NULL, "Plugin mapped");
177 MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(widget);
179 if (plugin && plugin->priv) {
180 plugin->priv->net_on = get_usbnet_enabled(plugin);
181 if (plugin->priv->enable_button) {
182 enable_button_set_text(plugin->priv->enable_button, plugin->priv->net_on);
187 static gboolean mtetherd_status_plugin_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
188 g_message("Got event %d", event->type);
192 static void mtetherd_status_plugin_device_condition(LibHalContext *ctx, const char *udi, const char *condition, const char *detail) {
193 MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(libhal_ctx_get_user_data(ctx));
196 g_message("Got HAL condition %s on %s: %s", condition, udi, detail);
197 //hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Got HAL condition %s on %s: %s", condition, udi, detail);
198 if (strcmp(USBDEV_CONDITION, "ButtonPressed") == 0) {
199 if (strcmp(USBDEV_PATH, udi) == 0) {
200 mtetherd_status_plugin_usb_plugged_show(plugin);
202 } else if (strcmp("DeviceAdded", condition) == 0) {
203 if (strcmp(USBDEV_PATH, detail) == 0) {
204 plugin->priv->net_on = TRUE;
205 enable_button_set_text(plugin->priv->enable_button, plugin->priv->net_on);
207 } else if (strcmp("DeviceRemoved", condition) == 0) {
208 if (strcmp(USBDEV_PATH, detail) == 0) {
209 plugin->priv->net_on = FALSE;
210 enable_button_set_text(plugin->priv->enable_button, plugin->priv->net_on);
216 static void mtetherd_status_plugin_init(MTetherDStatusPlugin *plugin) {
217 plugin->priv = MTETHERD_STATUS_PLUGIN_GET_PRIVATE(plugin);
219 plugin->priv->usb_on = FALSE;
220 plugin->priv->net_on = FALSE;
222 plugin->priv->enable_button = hildon_button_new(HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
223 if (plugin->priv->enable_button) {
225 GdkPixbuf *icon = gdk_pixbuf_new_from_file(IMAGE_DIR "/mtetherd-net-icon.png", &err);
227 g_warning("Can't load mtetherd icon: %s", err->message);
228 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Can't load mtetherd icon: %s", err->message);
233 GtkWidget *image = gtk_image_new_from_pixbuf(icon);
234 hildon_button_set_image(HILDON_BUTTON(plugin->priv->enable_button), image);
235 hildon_button_set_image_position(HILDON_BUTTON(plugin->priv->enable_button), GTK_POS_LEFT);
236 g_object_unref(icon);
238 gboolean enabled = get_usbnet_enabled(plugin);
239 enable_button_set_text(plugin->priv->enable_button, enabled);
240 g_signal_connect(plugin->priv->enable_button, "clicked", G_CALLBACK(enable_button_clicked), plugin);
241 gtk_container_add(GTK_CONTAINER(plugin), plugin->priv->enable_button);
242 gtk_widget_show_all(plugin->priv->enable_button);
244 //g_signal_connect(plugin, "expose-event", G_CALLBACK(mtetherd_status_plugin_event), NULL);
246 //hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Initialized mtetherd status plugin");
248 plugin->priv->dbus_connection = hd_status_plugin_item_get_dbus_g_connection(HD_STATUS_PLUGIN_ITEM(plugin), DBUS_BUS_SYSTEM, &err);
250 g_warning("Can't open DBUS connection: %s", err->message);
251 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Error opening DBUS connection: %s", err->message);
255 g_message("Got DBUS Glib connection: %p", plugin->priv->dbus_connection);
257 if (plugin->priv->dbus_connection) {
258 plugin->priv->hal_context = libhal_ctx_new();
259 if (plugin->priv->hal_context) {
260 if (libhal_ctx_set_dbus_connection(plugin->priv->hal_context, dbus_g_connection_get_connection(plugin->priv->dbus_connection))) {
261 if (!libhal_ctx_set_user_data(plugin->priv->hal_context, plugin)) {
262 g_warning("Can't set user data of HAL context");
263 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Can't set user data of HAL context");
265 if (!libhal_ctx_set_device_condition(plugin->priv->hal_context, mtetherd_status_plugin_device_condition)) {
266 g_warning("Error assigning device condition callback");
267 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Error assigning device condition callback");
270 dbus_error_init(&derr);
271 if (!libhal_ctx_init(plugin->priv->hal_context, &derr)) {
272 if (dbus_error_is_set(&derr)) {
273 g_warning("Error initializing HAL context (%s): %s", derr.name, derr.message);
274 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Error initializing HAL context (%s): %s", derr.name, derr.message);
275 dbus_error_free(&derr);
277 g_warning("Error initializing HAL context: unknown error");
278 //hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Error initializing HAL context: unknown error");
280 libhal_ctx_free(plugin->priv->hal_context);
281 plugin->priv->hal_context = NULL;
284 g_warning("Can't set DBUS connection of HAL context");
285 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Can't set DBUS connection of HAL context");
286 libhal_ctx_free(plugin->priv->hal_context);
287 plugin->priv->hal_context = NULL;
290 g_warning("Can't allocate HAL context");
291 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Can't allocate HAL context");
295 mtetherd_status_plugin_usb_plugged_show(plugin);