[Xfce4-commits] <xfce4-cellmodem-plugin:master> Apply SMS patches

Alvaro Lopes noreply at xfce.org
Tue Oct 13 21:28:02 CEST 2009


Updating branch refs/heads/master
         to dab2591457a582657de98b1f415f4a4f58d497c7 (commit)
       from 88797e9040978fdf32f31680134ffa141664d83f (commit)

commit dab2591457a582657de98b1f415f4a4f58d497c7
Author: Alvaro Lopes <alvieboy at alvie.com>
Date:   Mon Oct 12 09:48:11 2009 +0100

    Apply SMS patches

 panel-plugin/Makefile.am            |   40 ++-
 panel-plugin/cellmodem.c            |  894 ++++++++++++++++++++++++++++++-----
 panel-plugin/cellmodem.h            |   45 ++-
 panel-plugin/leds.c                 |   81 +++-
 panel-plugin/leds.h                 |   11 +-
 panel-plugin/modem_driver_generic.c |    3 +-
 panel-plugin/preferences.c          |  190 +++++++-
 panel-plugin/preferences.h          |   18 +
 8 files changed, 1114 insertions(+), 168 deletions(-)

diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am
index 2349234..e4753d9 100644
--- a/panel-plugin/Makefile.am
+++ b/panel-plugin/Makefile.am
@@ -1,12 +1,23 @@
 plugindir = $(libexecdir)/xfce4/panel-plugins
+
 plugin_PROGRAMS = xfce4-cellmodem-plugin
 
+if HAVE_SMS_SUPPORT
+
+noinst_PROGRAMS=test-sms
+
+endif
+
 xfce4_cellmodem_plugin_CFLAGS = \
         -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
 	@LIBXFCE4PANEL_CFLAGS@
 
 xfce4_cellmodem_plugin_LDADD = \
 	@LIBXFCE4PANEL_LIBS@ 
+	
+#SMS_SOURCES=
+#SMS_HEADERS=
+
 
 xfce4_cellmodem_plugin_SOURCES = \
 	cellmodem.c modem_driver.c \
@@ -15,8 +26,8 @@ xfce4_cellmodem_plugin_SOURCES = \
 	preferences.c \
 	pin_helper.c \
 	leds.c \
-	autodetect.c
-
+	autodetect.c 
+	
 noinst_HEADERS = \
 	cellmodem.h \
 	leds.h \
@@ -28,8 +39,31 @@ noinst_HEADERS = \
 	preferences.h \
 	big_leds.xpm \
 	med_leds.xpm \
-	autodetect.h
+	autodetect.h 
+	
+if HAVE_SMS_SUPPORT
 
+xfce4_cellmodem_plugin_SOURCES+= sms.c \
+	sms_tables.c \
+	sms_dialog.c
+
+noinst_HEADERS+= sms.h \
+	sms_tables.h \
+	sms_dialog.h
+
+endif
+
+if HAVE_SMS_SUPPORT
+
+test_sms_CFLAGS = -DCORE_SMS_DEBUG \
+        -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
+	@LIBXFCE4PANEL_CFLAGS@
+
+test_sms_SOURCES=sms.c test-sms.c sms_tables.c sms_dialog.c
+
+test_sms_LDADD = \
+	@LIBXFCE4PANEL_LIBS@ 
+endif
 
 desktop_in_in_files = cellmodem.desktop.in.in
 desktop_in_files = $(desktop_in_in_files:.desktop.in.in=.desktop.in)
diff --git a/panel-plugin/cellmodem.c b/panel-plugin/cellmodem.c
index 88ad323..e25c160 100644
--- a/panel-plugin/cellmodem.c
+++ b/panel-plugin/cellmodem.c
@@ -22,6 +22,12 @@
 #include "preferences.h"
 #include "pin_helper.h"
 
+#ifdef HAVE_SMS_SUPPORT
+#include "sms.h"
+#include "sms_dialog.h"
+#endif
+
+
 #ifdef DEBUG_ENABLED
 
 char cellmodem_logbuf[8192];
@@ -37,18 +43,26 @@ static gboolean cellmodem_t_send_at_command (cellmodem_t * monitor,
 					     const gchar * expect);
 static gboolean get_network_info (cellmodem_t * monitor);
 static void cellmodem_t_is_registered (cellmodem_t * monitor);
-
 static void cellmodem_t_identify_network (cellmodem_t * monitor);
-static gboolean cellmodem_t_close_modem (cellmodem_t *
-					 monitor /*, gboolean failure */ );
-static gboolean reschedule_open (cellmodem_t *
-				 monitor /*, gboolean failure */ );
+static gboolean cellmodem_t_close_modem (cellmodem_t * monitor);
+static gboolean cellmodem_t_reschedule_open (cellmodem_t * monitor);
 static gboolean cellmodem_t_at_command_timeout (cellmodem_t * monitor);
-static void cellmodem_t_cancel_pending_at_command_timeout (cellmodem_t *
-							   monitor);
+static void cellmodem_t_cancel_pending_at_command_timeout (cellmodem_t * monitor);
 static void cellmodem_t_get_quality (cellmodem_t * monitor);
+
+#ifdef HAVE_SMS_SUPPORT
+
+static void cellmodem_t_get_cmgf_status (cellmodem_t * monitor);
+static void cellmodem_t_get_cmgl_read (cellmodem_t * monitor);
+static void cellmodem_t_switch_to_sms_pdu_mode (cellmodem_t * monitor);
+static void cellmodem_t_set_cmgf (cellmodem_t * monitor);
+static void cellmodem_t_get_cpms (cellmodem_t * monitor);
+
+#endif
+ /*FOLD00 */
 static void cellmodem_t_get_pin_status (cellmodem_t * monitor);
-static void cellmodem_t_send_pin (cellmodem_t * monitor, const gchar * pin);
+static void cellmodem_t_send_pin (cellmodem_t * monitor, const gchar * pin,
+				  gboolean save);
 static void cellmodem_t_set_tooltip_info (cellmodem_t * monitor);
 static void cellmodem_t_get_ohcip_status (cellmodem_t * monitor);
 static gboolean cellmodem_button_event (GtkEventBox * box,
@@ -57,7 +71,20 @@ static gboolean cellmodem_button_event (GtkEventBox * box,
 static gboolean cellmodem_t_open_modem (cellmodem_t * monitor);
 static void cellmodem_t_switch_status (cellmodem_t * monitor,
 				       modem_status_t status);
+static void cellmodem_t_set_ok (cellmodem_t * monitor);
+static gboolean cellmodem_t_start_work_from_timer (cellmodem_t * monitor);
+static void cellmodem_t_schedule_timer (cellmodem_t * monitor);
+
+
+/**
+ * Schedule a command or series of commands to be run as soon as possible,
+ * but outside the main loop
+ */
 
+static gboolean cellmodem_t_schedule_command (cellmodem_t * monitor,
+					      void (*cellmodem_function)
+					      (cellmodem_t *), void *data);
+static void cellmodem_t_unschedule (cellmodem_t * monitor);
 
 
 /* End Proto */
@@ -75,16 +102,29 @@ static void
 cellmodem_t_set_error (cellmodem_t * monitor)
 {
   led_t_set_color (monitor->status_led, LED_RED);
-  led_t_set_flashing (monitor->status_led, TRUE);
+  led_t_set_flashing (monitor->status_led, LED_FLASH_NORMAL);
   led_t_set_color (monitor->network_led, LED_OFF);
-  led_t_set_flashing (monitor->network_led, FALSE);
+  led_t_set_flashing (monitor->network_led, LED_NO_FLASH);
+}
+static void
+cellmodem_t_set_has_new_messages (cellmodem_t * monitor)
+{
+  cellmodem_t_set_ok (monitor);
+  cellmodem_t_set_tooltip_info (monitor);
 }
 
 static void
 cellmodem_t_set_ok (cellmodem_t * monitor)
 {
   led_t_set_color (monitor->status_led, LED_GREEN);
-  led_t_set_flashing (monitor->status_led, FALSE);
+#ifdef HAVE_SMS_SUPPORT
+  if (!monitor->no_sms_support && (monitor->sms_unread_messages > 0))
+    {
+      led_t_set_flashing (monitor->status_led, LED_FLASH_FAST_TWICE);
+    }
+  else
+#endif
+    led_t_set_flashing (monitor->status_led, LED_NO_FLASH);
 }
 
 static gboolean
@@ -130,7 +170,7 @@ cellmodem_t_switch_to_error_and_restart (cellmodem_t * monitor,
 
   cellmodem_t_switch_status (monitor, MODEM_ERROR);
   cellmodem_t_set_tooltip_info (monitor);
-  reschedule_open (monitor);
+  cellmodem_t_reschedule_open (monitor);
 }
 
 
@@ -149,13 +189,17 @@ cellmodem_t_switch_status (cellmodem_t * monitor, modem_status_t status)
     case MODEM_WAIT_CPIN_RESPONSE:
     case MODEM_WAIT_COPS_RESPONSE:
     case MODEM_WAIT_PINE_RESPONSE:
+      monitor->pin_sent = TRUE;
     case MODEM_CLOSED:
       cellmodem_t_set_ok (monitor);
       break;
     case MODEM_WAIT_CREG_RESPONSE:
     case MODEM_WAIT_REGISTRATION:
+#ifdef HAVE_SMS_SUPPORT
     case MODEM_WAIT_CMGF_RESPONSE:
     case MODEM_WAIT_SET_CMGF_RESPONSE:
+    case MODEM_WAIT_CMGL_READ_RESPONSE:
+#endif
     case MODEM_WAIT_OHCIP_RESPONSE:
       break;
     }
@@ -401,7 +445,8 @@ cellmodem_t_setup_widgets (cellmodem_t * monitor, gboolean destroy)
 
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (monitor->qualpbar),
+      gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR
+					(monitor->qualpbar),
 					GTK_PROGRESS_BOTTOM_TO_TOP);
 
       monitor->gbox = gtk_hbox_new (FALSE, 0);
@@ -409,7 +454,8 @@ cellmodem_t_setup_widgets (cellmodem_t * monitor, gboolean destroy)
     }
   else
     {
-      gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (monitor->qualpbar),
+      gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR
+					(monitor->qualpbar),
 					GTK_PROGRESS_LEFT_TO_RIGHT);
 
       monitor->gbox = gtk_vbox_new (FALSE, 0);
@@ -468,7 +514,8 @@ cellmodem_t_setup_widgets (cellmodem_t * monitor, gboolean destroy)
   gtk_widget_show (monitor->eventbox);
   gtk_widget_set_size_request (monitor->eventbox, -1, -1);
 
-  gtk_signal_connect (GTK_OBJECT (monitor->eventbox), "button-press-event",
+  gtk_signal_connect (GTK_OBJECT (monitor->eventbox),
+		      "button-press-event",
 		      G_CALLBACK (cellmodem_button_event), monitor);
 
 }
@@ -497,10 +544,17 @@ cellmodem_t_new (XfcePanelPlugin * plugin)
   monitor->options.low_threshold = 40;
   monitor->options.max_quality = MAX_QUAL;
   monitor->options.check_for_sms = FALSE;
-  monitor->options.sms_check_interval = 10;
-
+  monitor->options.speed = B460800;
+  monitor->pin_sent = FALSE;
 
+#ifdef HAVE_SMS_SUPPORT
+  monitor->options.sms_check_interval = 10;
   monitor->no_sms_support = FALSE;
+  monitor->sms_got_read_messages = FALSE;
+  monitor->sms_list = NULL;
+#endif
+  monitor->scheduled_function = NULL;
+  monitor->no_opsys_support = FALSE;
 
   /* Setup colors */
 
@@ -526,51 +580,88 @@ cellmodem_t_new (XfcePanelPlugin * plugin)
 static void
 cellmodem_t_set_tooltip_info (cellmodem_t * monitor)
 {
-  gchar buffer[512];
+  GString *buffer;
+  buffer = g_string_sized_new (128);
 
   gint qp = monitor->quality * 100;
   gint q = monitor->signal_strength;
 
   if (cellmodem_t_in_error_status (monitor))
     {
-      g_snprintf (buffer, 512, _("Error detected:\n%s"), monitor->lasterror);
+      g_string_append_printf (buffer, _("Error detected:\n%s"),
+			      monitor->lasterror);
     }
   else
     {
       switch (monitor->registration_status)
 	{
 	case REGISTRATION_NOT_REGISTERED:
-	  g_snprintf (buffer, 512, _("Not registered"));
+	  g_string_append_printf (buffer, _("Not registered"));
 	  break;
 	case REGISTRATION_NEEDS_PIN:
-	  g_snprintf (buffer, 512, _("Modem needs PIN"));
+	  g_string_append_printf (buffer, _("Modem needs PIN"));
 	  break;
 	case REGISTRATION_REGISTERING:
-	  g_snprintf (buffer, 512, _("Registering"));
+	  g_string_append_printf (buffer, _("Registering"));
 	  break;
 	case REGISTRATION_GPRS:
-	  g_snprintf (buffer, 512,
-		      _("Registered [GPRS] to %s\nQuality: %d (%d%%)"),
-		      monitor->network, q, qp);
+	  g_string_append_printf (buffer,
+				  _
+				  ("Registered [GPRS] to %s\nQuality: %d (%d%%)"),
+				  monitor->network, q, qp);
 	  break;
 	case REGISTRATION_UMTS:
-	  g_snprintf (buffer, 512,
-		      _("Registered [UMTS] to %s\nQuality: %d (%d%%)"),
-		      monitor->network, q, qp);
+	  g_string_append_printf (buffer,
+				  _
+				  ("Registered [UMTS] to %s\nQuality: %d (%d%%)"),
+				  monitor->network, q, qp);
 	  break;
 	case REGISTRATION_HSDPA:
-	  g_snprintf (buffer, 512,
-		      _("Registered [HSDPA] to %s\nQuality: %d (%d%%)"),
-		      monitor->network, q, qp);
+	  g_string_append_printf (buffer,
+				  _
+				  ("Registered [HSDPA] to %s\nQuality: %d (%d%%)"),
+				  monitor->network, q, qp);
 	  break;
 	case REGISTRATION_UNKNOWN:
-	  g_snprintf (buffer, 512, _("Registered to %s\nQuality: %d (%d%%)"),
-		      monitor->network, q, qp);
+	  g_string_append_printf (buffer,
+				  _
+				  ("Registered to %s\nQuality: %d (%d%%)"),
+				  monitor->network, q, qp);
 	  break;
 	}
     }
 
-  gtk_tooltips_set_tip (monitor->tooltips, monitor->eventbox, buffer, NULL);
+#ifdef HAVE_SMS_SUPPORT
+  if (monitor->no_sms_support)
+    {
+      g_string_append_printf (buffer, _("\nNo SMS support"));
+    }
+  else
+    {
+      if (monitor->sms_got_read_messages)
+	{
+	  g_string_append_printf (buffer,
+				  "\n%d SMS messages",
+				  monitor->
+				  sms_read_messages +
+				  monitor->sms_unread_messages);
+	  if (monitor->sms_unread_messages)
+	    {
+	      g_string_append_printf (buffer,
+				      " (%d unread)",
+				      monitor->sms_unread_messages);
+	    }
+	}
+      else
+	{
+	  g_string_append_printf (buffer, _("\nSMS not checked yet"));
+	}
+    }
+#endif
+
+  gtk_tooltips_set_tip (monitor->tooltips, monitor->eventbox,
+			buffer->str, NULL);
+  g_string_free (buffer, TRUE);
 }
 
 
@@ -602,8 +693,8 @@ cellmodem_t_update_progressbar (cellmodem_t * monitor)
 
   if (monitor->registration_status == REGISTRATION_NOT_REGISTERED)
     {
-      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (monitor->qualpbar),
-				     0.0);
+      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR
+				     (monitor->qualpbar), 0.0);
       cellmodem_t_set_bar_color (monitor, NULL);
     }
   else
@@ -687,28 +778,46 @@ cellmodem_t_close_modem (cellmodem_t * monitor /*, gboolean failure */ )
 }
 
 static void
-pin_callback (const gchar * pin, void *pvt)
+pin_callback (const gchar * pin, gboolean save, void *pvt)
 {
   cellmodem_t *monitor = (cellmodem_t *) pvt;
 
-  cellmodem_t_send_pin (monitor, pin);
+  if (NULL != monitor->request_save_pin)
+    g_free (monitor->request_save_pin);
+
+  if (save)
+    {
+      monitor->request_save_pin = g_strdup (pin);
+    }
+  else
+    {
+      monitor->request_save_pin = NULL;
+    }
+
+
+  cellmodem_t_send_pin (monitor, pin, save);
 }
 
 static void
 cellmodem_t_request_pin (cellmodem_t * monitor)
 {
-  /*
-     if ( monitor->options.ask_for_pin )
-     pin_helper_launch( GTK_WIDGET(monitor->plugin), pin_callback, monitor );
-     else {
-   */
-  cellmodem_t_switch_status (monitor, MODEM_CLOSED);
-  cellmodem_t_switch_network_status (monitor, REGISTRATION_NEEDS_PIN);
-
-  /* End here */
+  if (monitor->request_save_pin == NULL || monitor->pin_sent == TRUE)
+    {
+      cellmodem_t_switch_status (monitor, MODEM_CLOSED);
+      cellmodem_t_switch_network_status (monitor, REGISTRATION_NEEDS_PIN);
 
-  cellmodem_t_close_modem (monitor);
+      /* End here */
 
+      cellmodem_t_close_modem (monitor);
+    }
+  else
+    {
+      /* Try sending the saved PIN. */
+      if (monitor->request_save_pin != NULL)
+	{
+	  pin_callback (monitor->request_save_pin, TRUE, monitor);
+	}
+    }
 }
 
 
@@ -795,7 +904,7 @@ cellmodem_t_registration_callback (gboolean success, GString * response,
     }
   else
     {
-      reschedule_open (monitor);
+      cellmodem_t_reschedule_open (monitor);
       /* Check for PIN ????? */
       // cellmodem_t_get_pin_status( monitor );
       /*else
@@ -888,8 +997,8 @@ cellmodem_t_identify_callback (gboolean success, GString * response,
 		}
 	      return;
 	    default:
-	      cellmodem_t_switch_network_status (monitor,
-						 REGISTRATION_UNKNOWN);
+	      cellmodem_t_switch_network_status
+		(monitor, REGISTRATION_UNKNOWN);
 	    }
 	}
     }
@@ -907,6 +1016,24 @@ cellmodem_t_identify_callback (gboolean success, GString * response,
   cellmodem_t_get_quality (monitor);
 }
 
+gchar *
+cellmodem_t_get_saved_pin (cellmodem_t * monitor)
+{
+  return monitor->request_save_pin;
+}
+
+int
+cellmodem_t_save_or_release_pin (cellmodem_t * monitor, gchar * pin)
+{
+  /*if (NULL!=monitor->request_save_pin)
+     g_free(monitor->request_save_pin);
+
+     monitor->request_save_pin = NULL;
+   */
+
+  cellmodem_write_config (monitor->plugin, monitor);
+}
+
 /**
  * @brief [cellmodem_t pseudo-member] Callback for PIN status request
  *
@@ -929,6 +1056,12 @@ cellmodem_t_pin_callback (gboolean success, GString * response, void *pvt)
     {
       /* Error */
       CELLMODEM_DEBUG (2, "Modem error detected (%p)", pvt);
+
+      if (NULL != monitor->request_save_pin)
+	{
+	  g_free (monitor->request_save_pin);
+	  monitor->request_save_pin = NULL;
+	}
       cellmodem_t_switch_to_error_and_restart (monitor,
 					       _
 					       ("Error in modem reply to CPIN"));
@@ -945,12 +1078,16 @@ cellmodem_t_pin_callback (gboolean success, GString * response, void *pvt)
       if (strncmp (start, "SIM PIN", 7) == 0)
 	{
 	  /* If we can ask for pin, we do */
-
 	  cellmodem_t_request_pin (monitor);
 	  return;
 	}
       if (strncmp (start, "READY", 5) == 0)
 	{
+	  /* If user requested to save pin, save it */
+
+	  cellmodem_t_save_or_release_pin (monitor,
+					   monitor->request_save_pin);
+
 	  cellmodem_t_is_registered (monitor);
 	  return;
 	}
@@ -967,14 +1104,14 @@ cellmodem_t_pin_callback (gboolean success, GString * response, void *pvt)
 					       _
 					       ("Invalid CPIN reply from modem"));
 
-      reschedule_open (monitor);
+      cellmodem_t_reschedule_open (monitor);
     }
   if (failure)
     cellmodem_t_switch_to_error_and_restart (monitor,
 					     _
 					     ("Unsupportted CPIN reply from modem"));
   else
-    reschedule_open (monitor);
+    cellmodem_t_reschedule_open (monitor);
 }
 
 /**
@@ -1039,6 +1176,8 @@ ohcip_out:
   cellmodem_t_get_quality (monitor);
 }
 
+#ifdef HAVE_SMS_SUPPORT
+
 /**
  * @brief [cellmodem_t pseudo-member] Callback for CMGF status request
  *
@@ -1051,7 +1190,6 @@ ohcip_out:
  * @return Nothing
  */
 
-#if 0
 static void
 cellmodem_t_cmgf_callback (gboolean success, GString * response, void *pvt)
 {
@@ -1090,21 +1228,22 @@ cellmodem_t_cmgf_callback (gboolean success, GString * response, void *pvt)
     {
       cellmodem_t_switch_to_error_and_restart (monitor,
 					       _
-					       ("Invalid OHCIP reply from modem"));
+					       ("Invalid CMFG reply from modem"));
       return;
     }
   if (failure)
     {
       cellmodem_t_switch_to_error_and_restart (monitor,
 					       _
-					       ("Unsupportted OHCIP reply from modem"));
+					       ("Unsupportted CMFG reply from modem"));
       return;
     }
-ohcip_out:
-  cellmodem_t_get_quality (monitor);
+
+  cellmodem_t_get_cpms (monitor);
 }
 
 #endif
+
 /**
  * @brief [cellmodem_t pseudo-member] Callback for SET CMGF request
  *
@@ -1117,7 +1256,8 @@ ohcip_out:
  * @return Nothing
  */
 
-#if 0
+#ifdef HAVE_SMS_SUPPORT
+
 static void
 cellmodem_t_set_cmgf_callback (gboolean success, GString * response,
 			       void *pvt)
@@ -1132,6 +1272,7 @@ cellmodem_t_set_cmgf_callback (gboolean success, GString * response,
     }
   //
 }
+
 #endif
 
 static void
@@ -1155,7 +1296,7 @@ cellmodem_t_setpin_callback (gboolean success, GString * response, void *pvt)
 
   cellmodem_t_switch_status (monitor, MODEM_CLOSED);
 
-  reschedule_open (monitor /*, FALSE */ );
+  cellmodem_t_reschedule_open (monitor /*, FALSE */ );
 }
 
 
@@ -1211,10 +1352,20 @@ cellmodem_t_quality_callback (gboolean success, GString * response, void *pvt)
 					       ("Invalid CSQ reply from modem"));
       return;
     }
+#ifdef HAVE_SMS_SUPPORT
+
+  if (!monitor->no_sms_support)
+    {
+      cellmodem_t_get_cmgf_status (monitor);
+      return;
+    }
+
+#endif
+
   CELLMODEM_DEBUG (3, "Got quality, restarting");
   /* cellmodem_t_close_modem( monitor, FALSE ); - reschedule will close */
   cellmodem_t_switch_status (monitor, MODEM_CLOSED);
-  reschedule_open (monitor /*, FALSE */ );
+  cellmodem_t_reschedule_open (monitor /*, FALSE */ );
 }
 
 /**
@@ -1231,7 +1382,8 @@ cellmodem_t_quality_callback (gboolean success, GString * response, void *pvt)
 static void
 cellmodem_t_is_registered (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_registration_callback,
+  cellmodem_t_send_at_command (monitor,
+			       &cellmodem_t_registration_callback,
 			       "+CREG?", "+CREG:");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CREG_RESPONSE);
 }
@@ -1276,8 +1428,8 @@ cellmodem_t_identify_network (cellmodem_t * monitor)
 static void
 cellmodem_t_get_quality (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_quality_callback, "+CSQ",
-			       "+CSQ:");
+  cellmodem_t_send_at_command (monitor, &cellmodem_t_quality_callback,
+			       "+CSQ", "+CSQ:");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CSQ_RESPONSE);
 }
 
@@ -1298,8 +1450,8 @@ cellmodem_t_get_quality (cellmodem_t * monitor)
 static void
 cellmodem_t_get_pin_status (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_pin_callback, "+CPIN?",
-			       "+CPIN:");
+  cellmodem_t_send_at_command (monitor, &cellmodem_t_pin_callback,
+			       "+CPIN?", "+CPIN:");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CPIN_RESPONSE);
 
 }
@@ -1323,6 +1475,8 @@ cellmodem_t_get_ohcip_status (cellmodem_t * monitor)
   cellmodem_t_switch_status (monitor, MODEM_WAIT_OHCIP_RESPONSE);
 }
 
+#ifdef HAVE_SMS_SUPPORT
+
 /**
  * @brief [cellmodem_t member] Request SMS response type from modem
  *
@@ -1333,17 +1487,300 @@ cellmodem_t_get_ohcip_status (cellmodem_t * monitor)
  *
  * @return Nothing
  */
-#if 0
+
 static void
 cellmodem_t_get_cmgf_status (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_cmgf_callback, "+CMGF?",
-			       "+CMGF: ");
+  cellmodem_t_send_at_command (monitor, &cellmodem_t_cmgf_callback,
+			       "+CMGF?", "+CMGF: ");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CMGF_RESPONSE);
 }
+
+#endif
+ /*FOLD00 */
+#ifdef HAVE_SMS_SUPPORT
+static void
+cellmodem_t_cpms_callback (gboolean success, GString * response, void *pvt)
+{
+  cellmodem_t *monitor = (cellmodem_t *) pvt;
+  gboolean failure = FALSE;
+
+  if (!success || response == NULL || response->str == NULL)
+    {
+      return;
+    }
+
+  /* +CPMS: "SM",6,25,"SM",6,25,"SM",6,25 */
+
+  if (strncmp (response->str, "+CPMS: ", 7) == 0)
+    {
+      gchar *start = response->str + 7;
+      CELLMODEM_DEBUG (4, "CPMS: '%s'", start);
+
+
+      // Split
+
+      gchar **tokens = g_strsplit (start, ",", 15);	/* Should only be 9 max, but lets be safe */
+
+      guint num_tokens = g_strv_length (tokens);
+
+      if ((num_tokens % 3) != 0)
+	{
+	  /* Invalid. */
+	  CELLMODEM_DEBUG (3,
+			   "Num tokens not multiple of 3 (%u)\n", num_tokens);
+	  failure = TRUE;
+	}
+      else
+	{
+	  /* Locate the SM module. */
+	  guint scan;
+
+	  for (scan = 0; scan < num_tokens; scan += 3)
+	    {
+	      if (strncmp (tokens[scan], "\"SM\"", 4) == 0)
+		{
+		  /* Found it */
+		  if (*tokens[scan + 1])
+		    {
+		      gchar *endptr;
+		      gulong num = strtoul (tokens[scan + 1],
+					    &endptr,
+					    10);
+		      if (*endptr == 0)
+			{
+			  monitor->
+			    sms_storage_number_of_messages = (guint) num;
+			  CELLMODEM_DEBUG
+			    (4, "Number of messages: %u\n", (guint) num);
+			  if (monitor->sms_got_read_messages)
+			    {
+			      monitor->
+				sms_unread_messages
+				= (guint) num - monitor->sms_read_messages;
+			      if (monitor->sms_unread_messages > 0)
+				{
+				  cellmodem_t_set_has_new_messages (monitor);
+				}
+			    }
+			  break;
+			}
+		      else
+			{
+			  failure = TRUE;
+			  break;
+			}
+		    }
+		  else
+		    {
+		      failure = TRUE;
+		      break;
+		    }
+		}
+	    }
+
+	  if (FALSE == failure)
+	    {
+	      /* Move on */
+	    }
+
+	}
+
+      g_strfreev (tokens);
+
+    }
+  else
+    {
+      failure = TRUE;
+    }
+
+
+  if (failure)
+    {
+      cellmodem_t_switch_to_error_and_restart (monitor,
+					       _
+					       ("Invalid CPMS reply from modem"));
+      return;
+    }
+
+  if (monitor->sms_got_read_messages)
+    {
+      // Skip this step
+      cellmodem_t_switch_status (monitor, MODEM_CLOSED);
+
+      cellmodem_t_reschedule_open (monitor);
+
+    }
+  else
+    {
+      cellmodem_t_get_cmgl_read (monitor);
+    }
+
+}
+#endif
+
+
+
+#ifdef HAVE_SMS_SUPPORT
+
+
+
+static gboolean
+cellmodem_t_cmgl_handle_cmgl_line (cellmodem_t * monitor, const char *line)
+{
+  /* Ignore the response for now. We should check here if message is read or unread */
+  CELLMODEM_DEBUG (4, "CGML line: %s", line);
+  return TRUE;
+}
+
+
+static gboolean
+cellmodem_t_cmgl_handle_pdu_line (cellmodem_t * monitor, const char *line)
+{
+  sms_entry_t *this_sms = sms_create_from_pdu_line (line);
+
+  if (NULL == this_sms)
+    {
+      /* Could not parse PDU??? */
+      return FALSE;
+    }
+
+  monitor->sms_list = g_list_append (monitor->sms_list, this_sms);
+
+  return TRUE;
+}
+
+static gboolean
+is_pdu_line (const char *line)
+{
+  const char *aptr;
+  if ((strlen (line) % 2) != 0)
+    {
+      return FALSE;
+    }
+  for (aptr = line; *aptr != '\0'; aptr++)
+    {
+      if (((*aptr) >= '0' && (*aptr) <= '9') ||
+	  ((*aptr) >= 'A' && (*aptr) <= 'F'))
+	{
+	  continue;
+	}
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+cellmodem_t_get_cmgl_read_callback (gboolean success, GString * response,
+				    void *pvt)
+{
+  cellmodem_t *monitor = (cellmodem_t *) pvt;
+  gboolean failure = FALSE;
+  sms_cmgl_state_t state = EXPECT_CMGL_LINE;
+  guint line_num;
+  const char *line;
+
+
+  if (!success || response == NULL || response->str == NULL)
+    {
+      /* Seems not to support SMS. */
+      cellmodem_t_switch_to_error_and_restart (monitor,
+					       _
+					       ("Error in modem reply to CMGL"));
+      return;
+    }
+
+  monitor->sms_got_read_messages = TRUE;
+
+
+  /* Handle messages */
+
+  gchar **lines = g_strsplit (response->str, "\n", 512);	/* Not so many, but... */
+  guint num_lines = g_strv_length (lines);
+
+  guint num_sms = 0;
+
+  CELLMODEM_DEBUG (4, "Handling messages, %u lines", num_lines);
+
+  for (line_num = 0; line_num < num_lines; line_num++)
+    {
+      if (failure)
+	break;
+
+      line = lines[line_num];
+      if (strlen (line) < 3)
+	{
+	  continue;
+	}
+
+      switch (state)
+	{
+	case EXPECT_CMGL_LINE:
+	  if (strncmp (line, "+CMGL: ", 7) == 0)
+	    {
+	      failure =
+		!cellmodem_t_cmgl_handle_cmgl_line (monitor, line + 7);
+	    }
+	  else
+	    {
+	      CELLMODEM_DEBUG (2,
+			       "Expecting +CMGL: , but got something else: '%s'",
+			       line);
+	      failure = TRUE;
+	    }
+	  state = EXPECT_PDU_LINE;
+
+	  break;
+
+	case EXPECT_PDU_LINE:
+
+	  if (is_pdu_line (line))
+	    {
+	      failure = !cellmodem_t_cmgl_handle_pdu_line (monitor, line);
+
+	      if (!failure)
+		num_sms++;
+
+	    }
+	  else
+	    {
+	      CELLMODEM_DEBUG (2,
+			       "Expecting PDU line, but got something else");
+	      failure = TRUE;
+	    }
+	  state = EXPECT_CMGL_LINE;
+	default:
+	  break;
+	};
+    }
+
+  if (!failure)
+    {
+      monitor->sms_read_messages = num_sms;
+      monitor->sms_unread_messages =
+	monitor->sms_storage_number_of_messages - num_sms;
+
+      if (monitor->sms_unread_messages)
+	{
+	  cellmodem_t_set_has_new_messages (monitor);
+	}
+    }
+
+
+
+
+  cellmodem_t_switch_status (monitor, MODEM_CLOSED);
+  cellmodem_t_reschedule_open (monitor /*, FALSE */ );
+
+}
+
+
 #endif
 
 
+
+#ifdef HAVE_SMS_SUPPORT
+
 /**
  * @brief [cellmodem_t member] Request SMS storage status from modem
  *
@@ -1354,16 +1791,25 @@ cellmodem_t_get_cmgf_status (cellmodem_t * monitor)
  *
  * @return Nothing
  */
-#if 0
+
 static void
 cellmodem_t_get_cpms (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_cpms_callback, "+CPMS?",
-			       "+CPMS: ");
+  cellmodem_t_send_at_command (monitor, &cellmodem_t_cpms_callback,
+			       "+CPMS?", "+CPMS: ");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CMGF_RESPONSE);
 }
 #endif
 
+#ifdef HAVE_SMS_SUPPORT
+
+static void
+free_sms_list (gpointer entry, gpointer userdata)
+{
+  sms_free_entry ((sms_entry_t *) entry);
+}
+
+ /*FOLD00 */
 /**
  * @brief [cellmodem_t member] Request SMS already read from modem
  *
@@ -1374,16 +1820,37 @@ cellmodem_t_get_cpms (cellmodem_t * monitor)
  *
  * @return Nothing
  */
-#if 0
 static void
 cellmodem_t_get_cmgl_read (cellmodem_t * monitor)
 {
-  cellmodem_t_send_at_command (monitor, &cellmodem_t_cmgl_callback, "+CPMS?",
-			       "+CPMS: ");
+  /* Clear the SMS list */
+
+  if (NULL != monitor->sms_list)
+    {
+      g_list_foreach (monitor->sms_list, free_sms_list, NULL);
+      g_list_free (monitor->sms_list);
+      monitor->sms_list = NULL;
+    }
+
+  cellmodem_t_send_at_command (monitor,
+			       &cellmodem_t_get_cmgl_read_callback,
+			       "+CMGL=1?", "+CMGL: ");
   cellmodem_t_switch_status (monitor, MODEM_WAIT_CMGL_READ_RESPONSE);
 }
 #endif
 
+#ifdef HAVE_SMS_SUPPORT
+
+static void
+cellmodem_t_switch_to_sms_pdu_mode (cellmodem_t * monitor)
+{
+  cellmodem_t_set_cmgf (monitor);
+}
+#endif
+
+
+
+#ifdef HAVE_SMS_SUPPORT
 /**
  * @brief [cellmodem_t member] Set SMS response type from modem (PDU mode).
  * This is only called if the card supports SMS and its in text mode. See ETSI 07.05
@@ -1395,7 +1862,7 @@ cellmodem_t_get_cmgl_read (cellmodem_t * monitor)
  *
  * @return Nothing
  */
-#if 0
+
 static void
 cellmodem_t_set_cmgf (cellmodem_t * monitor)
 {
@@ -1406,7 +1873,7 @@ cellmodem_t_set_cmgf (cellmodem_t * monitor)
 #endif
 
 static void
-cellmodem_t_send_pin (cellmodem_t * monitor, const gchar * pin)
+cellmodem_t_send_pin (cellmodem_t * monitor, const gchar * pin, gboolean save)
 {
   GString *g = g_string_new ("+CPIN=");
   g_string_append (g, pin);
@@ -1414,10 +1881,20 @@ cellmodem_t_send_pin (cellmodem_t * monitor, const gchar * pin)
   if (cellmodem_t_open_modem (monitor) == TRUE)
     {
 
-      cellmodem_t_send_at_command (monitor, &cellmodem_t_setpin_callback,
+      cellmodem_t_send_at_command (monitor,
+				   &cellmodem_t_setpin_callback,
 				   g->str, NULL);
       g_string_free (g, TRUE);
 
+      if (NULL != monitor->request_save_pin)
+	g_free (monitor->request_save_pin);
+      monitor->request_save_pin = NULL;
+
+      if (save)
+	{
+	  monitor->request_save_pin = g_strdup (pin);
+	}
+
       cellmodem_t_switch_status (monitor, MODEM_WAIT_PINE_RESPONSE);
     }
   else
@@ -1527,6 +2004,10 @@ cellmodem_t_modem_handle_response (cellmodem_t * monitor, char *buffer)
   g_string_append (monitor->resp.reply_buffer, bstart);
   g_string_append (monitor->resp.reply_buffer, "\n");
 
+  /* Reset expectation. We accept everything till we got an OK */
+
+  monitor->resp.reply_expect = NULL;
+
   CELLMODEM_DEBUG (6, "Finished handling");
   return TRUE;
 }
@@ -1608,7 +2089,8 @@ cellmodem_t_modem_callback (GIOChannel * chan, GIOCondition c, gpointer data)
 	{
 	  CELLMODEM_DEBUG (7, "Handling command from modem");
 	  size_t dist = eol - monitor->line_buffer;
-	  gchar *line = g_strndup (monitor->line_buffer, dist + 1);
+	  gchar *line = g_strndup (monitor->line_buffer,
+				   dist + 1);
 	  line[dist + 1] = 0;
 	  memmove (monitor->line_buffer, eol + 1,
 		   (monitor->line_buffer_size) - dist - 1);
@@ -1678,7 +2160,6 @@ cellmodem_t_send_at_command (cellmodem_t * monitor,
   return TRUE;
 }
 
-
 static gboolean
 cellmodem_t_at_command_timeout (cellmodem_t * monitor)
 {
@@ -1734,20 +2215,112 @@ cellmodem_t_open_modem (cellmodem_t * monitor)
 }
 
 
+static void
+cellmodem_t_unschedule (cellmodem_t * monitor)
+{
+  monitor->scheduled_function = NULL;
+  if (monitor->scheduled_function_reinstate_timer)
+    {
+      cellmodem_t_schedule_timer (monitor);
+    }
+}
+
 static gboolean
-reschedule_open (cellmodem_t * monitor /*, gboolean failure */ )
+cellmodem_t_schedule_command (cellmodem_t * monitor,
+			      void (*cellmodem_function) (cellmodem_t *),
+			      void *data)
+{
+  if (monitor->scheduled_function != NULL)
+    {
+      return FALSE;		/* No support for more than one scheduled */
+    }
+
+  monitor->scheduled_function = cellmodem_function;
+  monitor->scheduled_function_arg0 = data;
+
+  /* If we can run it right now, do it */
+
+  if (monitor->modem_status == MODEM_CLOSED)
+    {
+      /* Cancel any pending timeout. */
+      if (monitor->info_timeout_id > 0)
+	{
+	  g_source_remove (monitor->info_timeout_id);
+	  monitor->scheduled_function_reinstate_timer = TRUE;
+	}
+      else
+	{
+	  monitor->scheduled_function_reinstate_timer = FALSE;
+	}
+
+
+      monitor->scheduled_function (data);
+
+      /* It will have to call unschedule() when it is done. */
+    }
+  return TRUE;
+}
+
+
+/**
+ * Schedule a timer to start work
+ */
+
+static void
+cellmodem_t_schedule_timer (cellmodem_t * monitor)
 {
-  CELLMODEM_DEBUG (7, "RESCHEDULING OPEN");
-  cellmodem_t_close_modem (monitor /*, failure */ );
 
   if (monitor->info_timeout_id > 0)
     {
       g_source_remove (monitor->info_timeout_id);
     }
 
+
+  /* If we have an scheduled function here, call it */
+  if (NULL != monitor->scheduled_function)
+    {
+      monitor->scheduled_function (monitor->scheduled_function_arg0);
+      monitor->scheduled_function = NULL;
+    }
+
   monitor->info_timeout_id = g_timeout_add (OPEN_TIMEOUT,
-					    (GSourceFunc) get_network_info,
+					    (GSourceFunc)
+					    cellmodem_t_start_work_from_timer,
 					    monitor);
+}
+
+/**
+ * Start work from outside a timer. Cancels any pending timer
+ */
+
+static void
+cellmodem_t_start_work (cellmodem_t * monitor)
+{
+  if (monitor->info_timeout_id > 0)
+    {
+      g_source_remove (monitor->info_timeout_id);
+    }
+
+  cellmodem_t_start_work_from_timer (monitor);
+
+}
+
+static gboolean
+cellmodem_t_start_work_from_timer (cellmodem_t * monitor)
+{
+
+  get_network_info (monitor);
+
+}
+
+
+static gboolean
+cellmodem_t_reschedule_open (cellmodem_t * monitor /*, gboolean failure */ )
+{
+  CELLMODEM_DEBUG (7, "RESCHEDULING OPEN");
+  cellmodem_t_close_modem (monitor /*, failure */ );
+
+  cellmodem_t_schedule_timer (monitor);
 
   return FALSE;			/* Cancel this timer */
 }
@@ -1780,11 +2353,26 @@ get_network_info (cellmodem_t * monitor)
  Configuration stuff
  */
 
+#define READ_TEXT_ENTRY(name,var) \
+	if (NULL != monitor->var)  \
+	g_free (monitor->var);  \
+	\
+	text = xfce_rc_read_entry (rc, name, NULL);  \
+	if (NULL != text && *text)                              \
+	{                                                       \
+	monitor->var = g_strdup (text);    \
+	}                                                       \
+	else                                                    \
+	{                                                       \
+	monitor->var = NULL;               \
+	}
+
 static void
 cellmodem_read_config (XfcePanelPlugin * plugin, cellmodem_t * monitor)
 {
   char *file;
   const char *text;
+  const char *saved_pin;
   XfceRc *rc;
 
   if (!(file = xfce_panel_plugin_lookup_rc_file (plugin)))
@@ -1806,35 +2394,23 @@ cellmodem_read_config (XfcePanelPlugin * plugin, cellmodem_t * monitor)
   monitor->options.display_tooltip_info =
     xfce_rc_read_bool_entry (rc, "display_tooltip_info", FALSE);
 
-
-  if (NULL != monitor->options.modem_device)
-    g_free (monitor->options.modem_device);
-
-  text = xfce_rc_read_entry (rc, "modem_device", NULL);
-  if (NULL != text && *text)
-    {
-      monitor->options.modem_device = g_strdup (text);
-    }
-  else
-    {
-
-      monitor->options.modem_device = NULL;
-    }
-
-  if (NULL != monitor->options.modem_driver)
-    g_free (monitor->options.modem_driver);
-
-  text = xfce_rc_read_entry (rc, "modem_driver", NULL);
-  if (NULL != text && *text)
-    {
-      monitor->options.modem_driver = g_strdup (text);
-    }
-  else
-    {
-      monitor->options.modem_driver = NULL;
-    }
-
-
+  READ_TEXT_ENTRY ("modem_driver", options.modem_driver);
+  READ_TEXT_ENTRY ("modem_device", options.modem_device);
+  READ_TEXT_ENTRY ("saved_pin", request_save_pin);
+  /*
+     if (NULL != monitor->options.modem_driver)
+     g_free (monitor->options.modem_driver);
+
+     text = xfce_rc_read_entry (rc, "modem_driver", NULL);
+     if (NULL != text && *text)
+     {
+     monitor->options.modem_driver = g_strdup (text);
+     }
+     else
+     {
+     monitor->options.modem_driver = NULL;
+     }
+   */
   monitor->options.low_threshold =
     xfce_rc_read_int_entry (rc, "low_threshold", 40);
   monitor->options.critical_threshold =
@@ -1846,7 +2422,10 @@ cellmodem_read_config (XfcePanelPlugin * plugin, cellmodem_t * monitor)
     xfce_rc_read_bool_entry (rc, "check_for_sms", FALSE);
   monitor->options.sms_check_interval =
     xfce_rc_read_int_entry (rc, "sms_check_interval", 10);
-
+#ifdef DEBUG_ENABLED
+  cellmodem_debug_level =
+    xfce_rc_read_int_entry (rc, "debug_level", MAX_QUAL);
+#endif
 
   xfce_rc_close (rc);
 
@@ -1880,8 +2459,20 @@ cellmodem_write_config (XfcePanelPlugin * plugin, cellmodem_t * monitor)
   xfce_rc_write_bool_entry (rc, "display_tooltip_info",
 			    monitor->options.display_tooltip_info);
 
-  xfce_rc_write_entry (rc, "modem_device", monitor->options.modem_device);
-  xfce_rc_write_entry (rc, "modem_driver", monitor->options.modem_driver);
+  if (NULL != monitor->options.modem_device)
+    xfce_rc_write_entry (rc, "modem_device", monitor->options.modem_device);
+  else
+    xfce_rc_write_entry (rc, "modem_device", "");
+
+  if (NULL != monitor->options.modem_driver)
+    xfce_rc_write_entry (rc, "modem_driver", monitor->options.modem_driver);
+  else
+    xfce_rc_write_entry (rc, "modem_driver", "");
+
+  if (NULL != monitor->request_save_pin)
+    xfce_rc_write_entry (rc, "saved_pin", monitor->request_save_pin);
+  else
+    xfce_rc_write_entry (rc, "saved_pin", "");
 
   xfce_rc_write_int_entry (rc, "low_threshold",
 			   monitor->options.low_threshold);
@@ -1893,7 +2484,9 @@ cellmodem_write_config (XfcePanelPlugin * plugin, cellmodem_t * monitor)
 			    monitor->options.check_for_sms);
   xfce_rc_write_int_entry (rc, "sms_check_interval",
 			   monitor->options.sms_check_interval);
-
+#ifdef DEBUG_ENABLED
+  xfce_rc_write_int_entry (rc, "debug_level", cellmodem_debug_level);
+#endif
   CELLMODEM_DEBUG (7, "Done saving configuration");
   xfce_rc_close (rc);
 }
@@ -1960,6 +2553,19 @@ cellmodem_t_initialize_modem (cellmodem_t * monitor)
   get_network_info (monitor);
 }
 
+ /*FOLD00 */
+#ifdef HAVE_SMS_SUPPORT
+static void
+cb_destroy_sms_display_dialog (GtkWindow * win, cellmodem_t * monitor)
+{
+  if (monitor->sms_dlg)
+    {
+      sms_dialog_t_free (monitor->sms_dlg);
+    }
+  monitor->sms_dlg = NULL;
+}
+#endif
+
 static gboolean
 cellmodem_button_event (GtkEventBox * box, GdkEventButton * button,
 			cellmodem_t * monitor)
@@ -1973,6 +2579,46 @@ cellmodem_button_event (GtkEventBox * box, GdkEventButton * button,
     {
       pin_helper_launch (GTK_WIDGET (monitor->plugin), pin_callback, monitor);
     }
+  else
+    {
+#ifdef HAVE_SMS_SUPPORT
+      CELLMODEM_DEBUG (4, "Check SMS");
+      if (!monitor->no_sms_support)
+	{
+	  CELLMODEM_DEBUG (4, "Check SMS count %d/%d",
+			   monitor->sms_read_messages,
+			   monitor->sms_unread_messages);
+
+	  if (monitor->sms_read_messages + monitor->sms_unread_messages > 0)
+	    {
+	      /* Launch SMS menu */
+
+	      if (NULL == monitor->sms_dlg)
+		{
+		  monitor->sms_dlg =
+		    sms_dialog_new (GTK_WIDGET (monitor->plugin));
+
+		  sms_dialog_t_update_list
+		    (monitor->sms_dlg, monitor->sms_list, TRUE);
+
+		  /* Warn us when it is destroyed */
+
+		  g_signal_connect (monitor->
+				    sms_dlg->
+				    window,
+				    "destroy",
+				    G_CALLBACK
+				    (cb_destroy_sms_display_dialog), monitor);
+
+
+		  gtk_widget_show (monitor->sms_dlg->window);
+		}
+
+	    }
+	}
+#endif
+    }
+
   return TRUE;
 }
 
@@ -1980,10 +2626,10 @@ cellmodem_button_event (GtkEventBox * box, GdkEventButton * button,
 #ifdef DEBUG_ENABLED
 
 int
-init_logging ()
+init_logging ()		
 {
   openlog ("cellmodem", LOG_PID, LOG_USER);
-  cellmodem_debug_level = 9;
+  cellmodem_debug_level = 4;
   return 0;
 }
 
@@ -2010,12 +2656,12 @@ cellmodem_t_construct (XfcePanelPlugin * plugin)
 
   cellmodem_t_update_monitors (monitor);
 
-  g_signal_connect (plugin, "free-data", G_CALLBACK (cellmodem_t_delete),
-		    monitor);
+  g_signal_connect (plugin, "free-data",
+		    G_CALLBACK (cellmodem_t_delete), monitor);
   g_signal_connect (plugin, "save", G_CALLBACK (cellmodem_write_config),
 		    monitor);
-  g_signal_connect (plugin, "size-changed", G_CALLBACK (cellmodem_set_size),
-		    monitor);
+  g_signal_connect (plugin, "size-changed",
+		    G_CALLBACK (cellmodem_set_size), monitor);
 
   xfce_panel_plugin_menu_show_configure (plugin);
 
diff --git a/panel-plugin/cellmodem.h b/panel-plugin/cellmodem.h
index 8dc552f..30b0f40 100644
--- a/panel-plugin/cellmodem.h
+++ b/panel-plugin/cellmodem.h
@@ -36,6 +36,10 @@
 #include <libxfcegui4/libxfcegui4.h>
 #include <libxfce4panel/xfce-panel-plugin.h>
 #include "leds.h"
+#ifdef HAVE_SMS_SUPPORT
+#include "sms_dialog.h"
+#endif
+
 
 #ifdef DEBUG_ENABLED
 #include <syslog.h>
@@ -55,12 +59,12 @@ extern int cellmodem_debug_level;
 #ifdef DEBUG_ENABLED
 #define CELLMODEM_DEBUG(dl, x...) do { \
 	if ( dl <= cellmodem_debug_level ) { \
-	char *tmp=cellmodem_logbuf; tmp+=sprintf(cellmodem_logbuf,"%s [%d] : ", __FUNCTION__, __LINE__); \
-    tmp+=sprintf(tmp,x); \
-    sprintf(tmp,"\n"); \
+	char *tmp=cellmodem_logbuf; tmp+=sprintf(cellmodem_logbuf,"%s [%d] (%d): ", __FUNCTION__, __LINE__,cellmodem_debug_level); \
+	tmp+=sprintf(tmp,x); \
+	sprintf(tmp,"\n"); \
 	syslog(LOG_DEBUG, "%s", cellmodem_logbuf ); \
 	}\
-    } while (0)
+	} while (0)
 #else
 #define CELLMODEM_DEBUG(x...)
 #endif
@@ -81,8 +85,11 @@ typedef enum
   MODEM_WAIT_REGISTRATION,
   MODEM_WAIT_PINE_RESPONSE,
   MODEM_WAIT_OHCIP_RESPONSE,
+#ifdef HAVE_SMS_SUPPORT
   MODEM_WAIT_CMGF_RESPONSE,
   MODEM_WAIT_SET_CMGF_RESPONSE,
+  MODEM_WAIT_CMGL_READ_RESPONSE,
+#endif
   MODEM_CLOSED
 } modem_status_t;
 
@@ -97,6 +104,15 @@ typedef enum
   REGISTRATION_NEEDS_PIN
 } registration_type_t;
 
+#ifdef HAVE_SMS_SUPPORT
+typedef enum
+{
+  EXPECT_CMGL_LINE,
+  EXPECT_PDU_LINE
+} sms_cmgl_state_t;
+
+#endif
+
 
 typedef struct
 {
@@ -106,7 +122,7 @@ typedef struct
   GString *reply_buffer;
 } modem_response_data_t;
 
-typedef struct
+typedef struct cellmodem_t
 {
   XfcePanelPlugin *plugin;
   GtkTooltips *tooltips;
@@ -139,15 +155,34 @@ typedef struct
   /* Last error we got */
   gchar *lasterror;
 
+  void (*scheduled_function) (struct cellmodem_t *);
+  void *scheduled_function_arg0;
+  gboolean scheduled_function_reinstate_timer;
+
+
+#ifdef HAVE_SMS_SUPPORT
   /* Set to true if modem does not support SMS */
   gboolean no_sms_support;
   guint sms_read_messages;
+  gboolean sms_got_read_messages;
   guint sms_unread_messages;
+  guint sms_storage_number_of_messages;
+
+  GList *sms_list;
+
+  sms_dialog_t *sms_dlg;
+
+#endif
+
+  gboolean no_opsys_support;
 
   modem_response_data_t resp;
 
   gint info_timeout_id;
   gint at_timeout_id;
+  gboolean pin_sent;
+  gchar *request_save_pin;
+
 } cellmodem_t;
 
 
diff --git a/panel-plugin/leds.c b/panel-plugin/leds.c
index a962f6c..0254d5d 100644
--- a/panel-plugin/leds.c
+++ b/panel-plugin/leds.c
@@ -34,6 +34,9 @@ static gboolean leds_initialized = FALSE;
 static GdkPixbuf *whole_leds;
 static GSList *flashing_leds;
 static gint flash_timer;
+static gboolean leds_on = FALSE;
+static gint fast_flash_timer = -1;
+static gint fast_flash_count = 0;
 
 #ifdef BIG_LEGS
 
@@ -52,6 +55,9 @@ static int led_v_size = 6;
 
 GdkPixbuf *pixleds[NUMBER_OF_LEDS];
 
+
+static void led_t_flip_fast_flash (led_t * led, gpointer data);
+
 static gboolean
 initialize_leds ()
 {
@@ -78,22 +84,72 @@ initialize_leds ()
   return TRUE;
 }
 
+
+
+static gboolean
+do_fast_flash_leds (gpointer data)
+{
+  g_slist_foreach (flashing_leds, (GFunc) led_t_flip_fast_flash, NULL);
+  if (fast_flash_count == 3)
+    {
+      g_source_remove (fast_flash_timer);
+      fast_flash_timer = -1;
+      return FALSE;
+    }
+
+  fast_flash_count++;
+
+  return TRUE;
+}
+
 static gboolean
 do_flash_leds (gpointer data)
 {
+  leds_on = !leds_on;
+
   g_slist_foreach (flashing_leds, (GFunc) led_t_flip_flash, NULL);
 
+  if (fast_flash_timer == -1 && leds_on)
+    {
+      /* Start the new timer */
+      fast_flash_count = 0;
+      fast_flash_timer = g_timeout_add (150,
+					(GSourceFunc) do_fast_flash_leds,
+					NULL);
+    }
   return TRUE;
 }
 
-
 void
 led_t_flip_flash (led_t * led, gpointer data)
 {
-  if (!led->flashing)
+  if (LED_NO_FLASH == led->flashing)
+    return;
+
+  if (LED_FLASH_NORMAL == led->flashing)
+    {
+      led->flash_on = leds_on;	// ~(led->flash_on);
+
+      if (led->flash_on)
+	{
+	  gtk_image_set_from_pixbuf (GTK_IMAGE (led->image),
+				     pixleds[(int) led->color]);
+	}
+      else
+	{
+	  gtk_image_set_from_pixbuf (GTK_IMAGE (led->image),
+				     pixleds[LED_OFF]);
+	}
+    }
+}
+
+void
+led_t_flip_fast_flash (led_t * led, gpointer data)
+{
+  if (LED_FLASH_FAST_TWICE != led->flashing)
     return;
 
-  led->flash_on = ~(led->flash_on);
+  led->flash_on = !led->flash_on;
 
   if (led->flash_on)
     {
@@ -127,15 +183,24 @@ led_t_set_color (led_t * led, led_color_t color)
 }
 
 
-void
-led_t_set_flashing (led_t * led, gboolean flashing)
+static inline gboolean
+is_flash (led_flash_type_t f)
 {
-  if ((led->flashing ^ flashing) == 0)
-    return;			/* Already in that state */
+  return (f != LED_NO_FLASH);
+}
 
+void
+led_t_set_flashing (led_t * led, led_flash_type_t flashing)
+{
+  led_flash_type_t saveflash = led->flashing;
   led->flashing = flashing;
 
-  if (flashing)
+  if ((is_flash (flashing) ^ is_flash (saveflash)) == 0)
+    return;
+
+
+
+  if (flashing != LED_NO_FLASH)
     {
       /* Add to the list */
 
diff --git a/panel-plugin/leds.h b/panel-plugin/leds.h
index d7ef191..0bc357a 100644
--- a/panel-plugin/leds.h
+++ b/panel-plugin/leds.h
@@ -30,10 +30,17 @@ typedef enum
   LED_BLUE = 4,
 } led_color_t;
 
+typedef enum
+{
+  LED_NO_FLASH,
+  LED_FLASH_NORMAL,
+  LED_FLASH_FAST_TWICE
+} led_flash_type_t;
+
 typedef struct
 {
   GtkWidget *image;
-  gboolean flashing;
+  led_flash_type_t flashing;
   led_color_t color;
   gboolean flash_on;
 } led_t;
@@ -42,7 +49,7 @@ typedef struct
 
 led_t *led_t_new ();
 void led_t_set_color (led_t * led, led_color_t color);
-void led_t_set_flashing (led_t * led, gboolean flashing);
+void led_t_set_flashing (led_t * led, led_flash_type_t flashing);
 void led_t_destroy (led_t * led);
 void led_t_flip_flash (led_t * led, gpointer data);
 
diff --git a/panel-plugin/modem_driver_generic.c b/panel-plugin/modem_driver_generic.c
index ee085bb..1c17952 100644
--- a/panel-plugin/modem_driver_generic.c
+++ b/panel-plugin/modem_driver_generic.c
@@ -177,6 +177,7 @@ generic_writeln (modem_instance_t instance, const gchar * data)
 	}
 
       g_string_free (g, TRUE);
+      g_io_channel_flush (modem->channel, &error);
       g_io_channel_unref (modem->channel);
       modem->channel = NULL;
       return FALSE;
@@ -257,7 +258,7 @@ struct modem_driver_t modem_driver_generic = {
 };
 
 struct modem_driver_t modem_driver_nohsdpa = {
-  .name = "Generic Driver",
+  .name = "Generic Driver without HSDPA",
   .description = "Generic GPRS/UMTS Driver [no HSDPA]",
   .capabilities = 0,
   .open = &generic_open,
diff --git a/panel-plugin/preferences.c b/panel-plugin/preferences.c
index 4273e83..d65a022 100644
--- a/panel-plugin/preferences.c
+++ b/panel-plugin/preferences.c
@@ -21,32 +21,114 @@
 #include "autodetect.h"
 
 speed_names_t speeds[] = {
-  {.name = "1200",.speed = B1200},
-  {.name = "2400",.speed = B2400},
-  {.name = "4800",.speed = B4800},
-  {.name = "9600",.speed = B9600},
-  {.name = "19200",.speed = B19200},
-  {.name = "38400",.speed = B38400},
-  {.name = "57600",.speed = B57600},
-  {.name = "115200",.speed = B115200},
-  {.name = "230400",.speed = B230400},
-  {.name = "460800",.speed = B460800},
-  {.name = "500000",.speed = B500000},
-  {.name = "576000",.speed = B576000},
-  {.name = "921600",.speed = B921600},
-  {.name = "1000000",.speed = B1000000},
-  {.name = "1152000",.speed = B1152000},
-  {.name = "1500000",.speed = B1500000},
-  {.name = "2000000",.speed = B2000000},
-  {.name = "2500000",.speed = B2500000},
-  {.name = "3000000",.speed = B3000000},
-  {.name = "3500000",.speed = B3500000},
-  {.name = "4000000",.speed = B4000000},
+  {.name = "1200",.speed = B1200}
+  ,
+  {.name = "2400",.speed = B2400}
+  ,
+  {.name = "4800",.speed = B4800}
+  ,
+  {.name = "9600",.speed = B9600}
+  ,
+  {.name = "19200",.speed = B19200}
+  ,
+  {.name = "38400",.speed = B38400}
+  ,
+  {.name = "57600",.speed = B57600}
+  ,
+  {.name = "115200",.speed = B115200}
+  ,
+  {.name = "230400",.speed = B230400}
+  ,
+  {.name = "460800",.speed = B460800}
+  ,
+  {.name = "500000",.speed = B500000}
+  ,
+  {.name = "576000",.speed = B576000}
+  ,
+  {.name = "921600",.speed = B921600}
+  ,
+  {.name = "1000000",.speed = B1000000}
+  ,
+  {.name = "1152000",.speed = B1152000}
+  ,
+  {.name = "1500000",.speed = B1500000}
+  ,
+  {.name = "2000000",.speed = B2000000}
+  ,
+  {.name = "2500000",.speed = B2500000}
+  ,
+  {.name = "3000000",.speed = B3000000}
+  ,
+  {.name = "3500000",.speed = B3500000}
+  ,
+  {.name = "4000000",.speed = B4000000}
+  ,
   {.name = NULL,.speed = B0}
 };
 
+/*
+ As seen in pharscape:
+
+ AT_OPSYS=n
+
+Where n is a value between 0 and 5
+
+AT_OPSYS=0     #Only connect to GSM networks
+AT_OPSYS=1     #Only connect to UMTS networks
+AT_OPSYS=2     #If you have a choice - GPRS first
+AT_OPSYS=3     #If you have a choice - UMTS first
+AT_OPSYS=4     #Which ever network you connect to stay with it.
+AT_OPSYS=5     #Automatic - let V3G decide
+*/
+
+
+static network_type_t network_types[] = {
+  {
+   .description = NULL,
+   .opsys_single = 5,
+   .opsys_dual = MAKE_OPSYS_DUAL (0, 0)},
+  {
+   .description = NULL,
+   .opsys_single = 0,
+   .opsys_dual = MAKE_OPSYS_DUAL (0, 2)},
+  {
+   .description = NULL,
+   .opsys_single = 1,
+   .opsys_dual = MAKE_OPSYS_DUAL (1, 2)},
+  {
+   .description = NULL,
+   .opsys_single = 2,
+   .opsys_dual = MAKE_OPSYS_DUAL (2, 2)},
+  {
+   .description = NULL,
+   .opsys_single = 3,
+   .opsys_dual = MAKE_OPSYS_DUAL (3, 2)},
+  {
+   .description = NULL,
+   .opsys_single = 4,
+   .opsys_dual = MAKE_OPSYS_DUAL (4, 2)},
+  {
+   .description = NULL}
+};
+
 
 static void
+init_network_types ()
+{
+  /* This is ugly, but N_ seems to be ignored by the intltool utilities */
+  int i = 0;
+
+  if (NULL != network_types[i].description)
+    return;
+
+  network_types[i++].description = _("Any kind of network");
+  network_types[i++].description = _("GPRS network only");
+  network_types[i++].description = _("UMTS network only");
+  network_types[i++].description = _("GPRS if available");
+  network_types[i++].description = _("UMTS if available");
+  network_types[i++].description = _("First available and stay with it");
+}
+static void
 fill_speeds (GtkWidget * dlg)
 {
   speed_names_t *iter;
@@ -57,6 +139,16 @@ fill_speeds (GtkWidget * dlg)
 }
 
 static void
+fill_networks (GtkWidget * dlg)
+{
+  network_type_t *iter;
+  for (iter = network_types; iter->description; iter++)
+    {
+      gtk_combo_box_append_text (GTK_COMBO_BOX (dlg), iter->description);
+    }
+}
+
+static void
 cellmodem_t_dialog_response (GtkWidget * dlg, int response,
 			     cellmodem_t * monitor)
 {
@@ -131,10 +223,10 @@ update_dialog (cellmodem_dialog_t * dialog)
 			     monitor->options.critical_threshold);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->maxqual_entry),
 			     monitor->options.max_quality);
+#ifdef HAVE_SMS_SUPPORT
   gtk_spin_button_set_value (GTK_SPIN_BUTTON
 			     (dialog->sms_check_interval_entry),
 			     monitor->options.sms_check_interval);
-
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->check_sms_entry),
 				monitor->options.check_for_sms);
 
@@ -143,6 +235,11 @@ update_dialog (cellmodem_dialog_t * dialog)
       gtk_widget_set_sensitive (GTK_WIDGET (dialog->sms_check_interval_entry),
 				FALSE);
     }
+#endif
+#ifdef DEBUG_ENABLED
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->debug_level_entry),
+			     cellmodem_debug_level);
+#endif
 }
 
 
@@ -226,6 +323,17 @@ cb_critical_entry_changed (GtkSpinButton * button,
     gtk_spin_button_get_value_as_int (button);
 }
 
+#ifdef DEBUG_ENABLED
+
+static void
+cb_debug_level_entry_changed (GtkSpinButton * button,
+			      cellmodem_dialog_t * dialog)
+{
+  cellmodem_debug_level = gtk_spin_button_get_value_as_int (button);
+}
+#endif
+
+#ifdef HAVE_SMS_SUPPORT
 static void
 cb_sms_check_interval_entry_changed (GtkSpinButton * button,
 				     cellmodem_dialog_t * dialog)
@@ -244,6 +352,8 @@ cb_check_sms_entry_toggled (GtkCheckButton * button,
 			    dialog->monitor->options.check_for_sms);
 }
 
+#endif
+
 static void
 autodetect_dialog_callback (GtkDialog * dlg, int response,
 			    cellmodem_dialog_t * dialog)
@@ -367,6 +477,8 @@ cellmodem_create_options (XfcePanelPlugin * plugin, cellmodem_t * monitor)
 
   cellmodem_dialog_t *dialog;
 
+  init_network_types ();
+
   dialog = g_new0 (cellmodem_dialog_t, 1);
 
   dialog->monitor = monitor;
@@ -465,7 +577,6 @@ cellmodem_create_options (XfcePanelPlugin * plugin, cellmodem_t * monitor)
   g_signal_connect (dialog->device_entry, "changed",
 		    G_CALLBACK (cb_device_entry_changed), dialog);
 
-
   MAKEHBOX (hbox);
   GtkWidget *autodetect_button =
     gtk_button_new_with_label (_("Autodetect modem..."));
@@ -513,9 +624,38 @@ cellmodem_create_options (XfcePanelPlugin * plugin, cellmodem_t * monitor)
   g_signal_connect (dialog->critical_entry, "value-changed",
 		    G_CALLBACK (cb_critical_entry_changed), dialog);
 
+  MAKEHBOX (hbox);
+  MAKELABEL (label, _("Connect to:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, 0, FALSE, FALSE);
+  /* Create a combo with the network types */
+
+  dialog->networktype_combo = gtk_combo_box_new_text ();
 
-  /* Toggle buttons. */
+  fill_networks (dialog->networktype_combo);
 
+  gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->networktype_combo), 0);
+  gtk_widget_show (dialog->networktype_combo);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->networktype_combo, FALSE, FALSE,
+		      0);
+
+
+
+#ifdef DEBUG_ENABLED
+  MAKEHBOX (hbox);
+  MAKELABEL (label, _("Debug level:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, 0, FALSE, FALSE);
+
+  dialog->debug_level_entry = gtk_spin_button_new_with_range (0, 9, 1);
+  gtk_widget_show (dialog->debug_level_entry);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->debug_level_entry, FALSE, FALSE,
+		      0);
+
+  g_signal_connect (dialog->debug_level_entry, "value-changed",
+		    G_CALLBACK (cb_debug_level_entry_changed), dialog);
+#endif
+
+  /* Toggle buttons. */
+#ifdef HAVE_SMS_SUPPORT
   MAKEHBOX (hbox);
 
   dialog->check_sms_entry =
@@ -537,7 +677,7 @@ cellmodem_create_options (XfcePanelPlugin * plugin, cellmodem_t * monitor)
 		    G_CALLBACK (cb_check_sms_entry_toggled), dialog);
   g_signal_connect (dialog->sms_check_interval_entry, "value-changed",
 		    G_CALLBACK (cb_sms_check_interval_entry_changed), dialog);
-
+#endif
 
   update_dialog (dialog);
 
diff --git a/panel-plugin/preferences.h b/panel-plugin/preferences.h
index 89f14f0..9584b9e 100644
--- a/panel-plugin/preferences.h
+++ b/panel-plugin/preferences.h
@@ -32,8 +32,17 @@ typedef struct
   GtkWidget *autodetect_dialog;
   GtkWidget *device_combo;
   GtkWidget *speed_entry;
+
+  GtkWidget *networktype_combo;
+
+#ifdef HAVE_SMS_SUPPORT
   GtkWidget *check_sms_entry;
   GtkWidget *sms_check_interval_entry;
+#endif
+
+#ifdef DEBUG_ENABLED
+  GtkWidget *debug_level_entry;
+#endif
   cellmodem_t *monitor;
 
   GList *devices;
@@ -46,6 +55,15 @@ typedef struct
   speed_t speed;
 } speed_names_t;
 
+typedef struct
+{
+  const char *description;
+  unsigned int opsys_single;	/* Used when _OPSYS only accepts one value */
+  unsigned int opsys_dual;	/* Used when _OPSYS accepts two values */
+} network_type_t;
+
+#define MAKE_OPSYS_DUAL( hi, low ) ( ((hi)<<8) + (low) )
+
 void
 cellmodem_create_options (XfcePanelPlugin * plugin, cellmodem_t * monitor);
 



More information about the Xfce4-commits mailing list