[Pommed-commits] r484 - in trunk: . pommed

jblache at alioth.debian.org jblache at alioth.debian.org
Thu Jun 5 21:21:45 UTC 2008


Author: jblache
Date: 2008-06-05 21:21:44 +0000 (Thu, 05 Jun 2008)
New Revision: 484

Modified:
   trunk/ChangeLog
   trunk/pommed/dbus.c
Log:
Integrate DBus event processing into the event loop.


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-06-04 17:47:20 UTC (rev 483)
+++ trunk/ChangeLog	2008-06-05 21:21:44 UTC (rev 484)
@@ -6,8 +6,9 @@
 	- gpomme: integrate config file monitoring and DBus messaging into
 	the main loop. Get rid of the 10 times per second polling.
 	- pommed: new event loop.
-	- pommed: convert power, kbd and dbus to timers integrated into
-	the event loop.
+	- pommed: convert power and kbd to timers integrated into the
+	event loop.
+	- pommed: integrate DBus into the event loop.
 
 version 1.18:
 	- pommed: add more IDs for Apple external keyboards

Modified: trunk/pommed/dbus.c
===================================================================
--- trunk/pommed/dbus.c	2008-06-04 17:47:20 UTC (rev 483)
+++ trunk/pommed/dbus.c	2008-06-05 21:21:44 UTC (rev 484)
@@ -21,10 +21,13 @@
 
 #include <stdio.h>
 #include <unistd.h>
+#include <stdlib.h>
 #include <stdint.h>
 
 #include <syslog.h>
 
+#include <sys/epoll.h>
+
 #include <dbus/dbus.h>
 
 #include "pommed.h"
@@ -738,94 +741,330 @@
 
 
 static void
-mbpdbus_process_requests(int fd, uint32_t events)
+mbpdbus_reconnect(int fd, uint32_t events)
 {
-  DBusMessage *msg;
-  int nmsg;
-
+  int ret;
   uint64_t dummy;
 
   /* Acknowledge timer */
   read(fd, &dummy, sizeof(dummy));
 
-  if (conn == NULL)
+  ret = mbpdbus_init();
+  if (ret == 0)
+    evloop_remove_timer(fd);
+}
+
+static DBusHandlerResult
+mbpdbus_process_requests(DBusConnection *lconn, DBusMessage *msg, void *data)
+{
+  // Get methods
+  if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "getLevel"))
+    process_lcd_getlevel_call(msg);
+  else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "getLevel"))
+    process_kbd_getlevel_call(msg);
+  else if (dbus_message_is_method_call(msg, "org.pommed.ambient", "getLevel"))
+    process_ambient_getlevel_call(msg);
+  else if (dbus_message_is_method_call(msg, "org.pommed.audio", "getVolume"))
+    process_audio_getvolume_call(msg);
+  else if (dbus_message_is_method_call(msg, "org.pommed.audio", "getMute"))
+    process_audio_getmute_call(msg);
+  // Set methods
+  else if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "levelUp"))
+    process_lcd_backlight_step_call(msg, STEP_UP);
+  else if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "levelDown"))
+    process_lcd_backlight_step_call(msg, STEP_DOWN);
+  else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "inhibit"))
+    process_kbd_backlight_inhibit_call(msg, 1);
+  else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "disinhibit"))
+    process_kbd_backlight_inhibit_call(msg, 0);
+  else if (dbus_message_is_method_call(msg, "org.pommed.audio", "volumeUp"))
+    process_audio_volume_step_call(msg, STEP_UP);
+  else if (dbus_message_is_method_call(msg, "org.pommed.audio", "volumeDown"))
+    process_audio_volume_step_call(msg, STEP_DOWN);
+  else if (dbus_message_is_method_call(msg, "org.pommed.audio", "toggleMute"))
+    process_audio_toggle_mute_call(msg);
+  else if (dbus_message_is_method_call(msg, "org.pommed.cd", "eject"))
+    process_cd_eject_call(msg);
+  else if (dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
     {
-      if (mbpdbus_init() < 0)
-	return;
+      logmsg(LOG_INFO, "DBus disconnected");
+
+      mbpdbus_cleanup();
+
+      dbus_timer = evloop_add_timer(DBUS_TIMEOUT, mbpdbus_reconnect);
+      if (dbus_timer < 0)
+	logmsg(LOG_WARNING, "Could not set up timer for DBus reconnection");
     }
+  else
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
-  logdebug("Processing DBus requests\n");
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
 
-  nmsg = 0;
-  while (1)
+
+/* DBusWatch functions */
+struct pommed_watch
+{
+  DBusWatch *watch;
+  int fd;
+  uint32_t events;
+  int enabled;
+
+  struct pommed_watch *next;
+};
+
+
+static struct pommed_watch *watches;
+
+
+static uint32_t
+dbus_to_epoll(int flags)
+{
+  uint32_t events;
+
+  events = 0;
+
+  if (flags & DBUS_WATCH_READABLE)
+    events |= EPOLLIN;
+
+  if (flags & DBUS_WATCH_WRITABLE)
+    events |= EPOLLOUT | EPOLLET;
+
+  return events;
+}
+
+static int
+epoll_to_dbus(uint32_t events)
+{
+  int flags;
+
+  flags = 0;
+
+  if (events & EPOLLIN)
+    flags |= DBUS_WATCH_READABLE;
+
+  if (events & EPOLLOUT)
+    flags |= DBUS_WATCH_WRITABLE;
+
+  if (events & EPOLLHUP)
+    flags |= DBUS_WATCH_HANGUP;
+
+  if (events & EPOLLERR)
+    flags |= DBUS_WATCH_ERROR;
+
+  return flags;
+}
+
+static void
+mbpdbus_process_watch(int fd, uint32_t events)
+{
+  int flags;
+  uint32_t wanted;
+
+  DBusDispatchStatus ds;
+
+  struct pommed_watch *w;
+
+  logdebug("DBus process watch\n");
+
+  for (w = watches; w != NULL; w = w->next)
     {
-      logdebug("Checking messages\n");
+      if (!w->enabled)
+	continue;
 
-      dbus_connection_read_write(conn, 0);
+      if (w->fd == fd)
+	{
+	  wanted = events & w->events;
 
-      msg = dbus_connection_pop_message(conn);
+	  if (wanted != 0)
+	    {
+	      flags = epoll_to_dbus(wanted);
 
-      if (msg == NULL)
+	      dbus_watch_handle(w->watch, flags);
+
+	      /* Get out of the loop, as DBus will remove the watches
+	       * and our linked list can become invalid under our feet
+	       */
+	      if (events & (EPOLLERR | EPOLLHUP))
+		break;
+	    }
+	}
+    }
+
+  do
+    {
+      ds = dbus_connection_dispatch(conn);
+    }
+  while (ds != DBUS_DISPATCH_COMPLETE);
+}
+
+static dbus_bool_t
+mbpdbus_add_watch(DBusWatch *watch, void *data)
+{
+  uint32_t events;
+  int fd;
+  int ret;
+
+  struct pommed_watch *w;
+
+  logdebug("DBus add watch\n");
+
+  fd = dbus_watch_get_unix_fd(watch);
+
+  events = 0;
+  for (w = watches; w != NULL; w = w->next)
+    {
+      if (w->enabled && (w->fd == fd))
+	events |= w->events;
+    }
+
+  if (events != 0)
+    {
+      ret = evloop_remove(fd);
+      if (ret < 0)
 	{
-	  break;
+	  logmsg(LOG_ERR, "Could not remove previous watch on same fd");
+
+	  return FALSE;
 	}
+    }
 
-      // Get methods
-      if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "getLevel"))
-	process_lcd_getlevel_call(msg);
-      else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "getLevel"))
-	process_kbd_getlevel_call(msg);
-      else if (dbus_message_is_method_call(msg, "org.pommed.ambient", "getLevel"))
-	process_ambient_getlevel_call(msg);
-      else if (dbus_message_is_method_call(msg, "org.pommed.audio", "getVolume"))
-	process_audio_getvolume_call(msg);
-      else if (dbus_message_is_method_call(msg, "org.pommed.audio", "getMute"))
-	process_audio_getmute_call(msg);
-      // Set methods
-      else if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "levelUp"))
-        process_lcd_backlight_step_call(msg, STEP_UP);
-      else if (dbus_message_is_method_call(msg, "org.pommed.lcdBacklight", "levelDown"))
-        process_lcd_backlight_step_call(msg, STEP_DOWN);
-      else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "inhibit"))
-        process_kbd_backlight_inhibit_call(msg, 1);
-      else if (dbus_message_is_method_call(msg, "org.pommed.kbdBacklight", "disinhibit"))
-        process_kbd_backlight_inhibit_call(msg, 0);
-      else if (dbus_message_is_method_call(msg, "org.pommed.audio", "volumeUp"))
-        process_audio_volume_step_call(msg, STEP_UP);
-      else if (dbus_message_is_method_call(msg, "org.pommed.audio", "volumeDown"))
-        process_audio_volume_step_call(msg, STEP_DOWN);
-      else if (dbus_message_is_method_call(msg, "org.pommed.audio", "toggleMute"))
-        process_audio_toggle_mute_call(msg);
-      else if (dbus_message_is_method_call(msg, "org.pommed.cd", "eject"))
-        process_cd_eject_call(msg);
-      else if (dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
+  w = (struct pommed_watch *)malloc(sizeof(struct pommed_watch));
+  if (w == NULL)
+    {
+      logmsg(LOG_ERR, "Could not allocate memory for a new DBus watch");
+
+      return FALSE;
+    }
+
+  w->watch = watch;
+  w->fd = fd;
+  w->enabled = 1;
+
+  w->events = dbus_to_epoll(dbus_watch_get_flags(watch));
+  w->events |= EPOLLERR | EPOLLHUP;
+
+  events |= w->events;
+
+  ret = evloop_add(fd, events, mbpdbus_process_watch);
+  if (ret < 0)
+    {
+      free(w);
+
+      return FALSE;
+    }
+
+  w->next = watches;
+  watches = w;
+
+  return TRUE;
+}
+
+static void
+mbpdbus_remove_watch(DBusWatch *watch, void *data)
+{
+  uint32_t events;
+  int fd;
+  int ret;
+
+  struct pommed_watch *w;
+  struct pommed_watch *p;
+
+  logdebug("DBus remove watch %p\n", watch);
+
+  fd = dbus_watch_get_unix_fd(watch);
+  events = 0;
+
+  for (p = NULL, w = watches; w != NULL; p = w, w = w->next)
+    {
+      if (w->watch == watch)
 	{
-	  logmsg(LOG_INFO, "DBus disconnected");
+	  if (p != NULL)
+	    p->next = w->next;
+	  else
+	    watches = w->next;
 
-	  mbpdbus_cleanup();
+	  free(w);
 
-	  dbus_message_unref(msg);
+	  continue;
+	}
 
-	  return;
+      if (w->enabled && (w->fd == fd))
+	events |= w->events;
+    }
+
+  ret = evloop_remove(fd);
+  if (ret < 0)
+    return;
+
+  if (events == 0)
+    return;
+
+  ret = evloop_add(fd, events, mbpdbus_process_watch);
+  if (ret < 0)
+    logmsg(LOG_WARNING, "Could not re-add watch");
+}
+
+static void
+mbpdbus_toggle_watch(DBusWatch *watch, void *data)
+{
+  uint32_t events;
+  int fd;
+  int ret;
+
+  struct pommed_watch *w;
+
+  logdebug("DBus toggle watch\n");
+
+  fd = dbus_watch_get_unix_fd(watch);
+  events = 0;
+
+  for (w = watches; w != NULL; w = w->next)
+    {
+      if (w->watch == watch)
+	{
+	  if (!dbus_watch_get_enabled(watch))
+	    w->enabled = 0;
+	  else
+	    {
+	      w->enabled = 1;
+	      events |= w->events;
+	    }
+
+	  continue;
 	}
 
-      dbus_message_unref(msg);
-
-      nmsg++;
+      if (w->enabled && (w->fd == fd))
+	events |= events;
     }
 
-  if (nmsg > 0)
-    dbus_connection_flush(conn);
+  ret = evloop_remove(fd);
+  if (ret < 0)
+    return;
 
-  logdebug("Done with DBus requests\n");
+  if (events == 0)
+    return;
+
+  ret = evloop_add(fd, events, mbpdbus_process_watch);
+  if (ret < 0)
+    logmsg(LOG_WARNING, "Could not re-add watch");
 }
 
+static void
+mbpdbus_data_free(void *data)
+{
+  /* NOTHING */
+}
 
+
 int
 mbpdbus_init(void)
 {
   int ret;
 
+  watches = NULL;
+  dbus_timer = -1;
+
   dbus_error_init(&err);
 
   conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
@@ -862,26 +1101,29 @@
       return -1;
     }
 
-  dbus_timer = evloop_add_timer(DBUS_TIMEOUT, mbpdbus_process_requests);
-  if (ret < 0)
+  ret = dbus_connection_set_watch_functions(conn, mbpdbus_add_watch, mbpdbus_remove_watch,
+					    mbpdbus_toggle_watch, NULL, mbpdbus_data_free);
+  if (!ret)
     {
       mbpdbus_cleanup();
 
       return -1;
     }
 
+  dbus_connection_add_filter(conn, mbpdbus_process_requests, NULL, NULL);
+
   return 0;
 }
 
 void
 mbpdbus_cleanup(void)
 {
+  if (dbus_timer > 0)
+    evloop_remove_timer(dbus_timer);
+
   if (conn == NULL)
     return;
 
-  if (dbus_timer != -1)
-    evloop_remove_timer(dbus_timer);
-
   dbus_error_free(&err);
 
   /* This is a shared connection owned by libdbus




More information about the Pommed-commits mailing list