1 /* -*- mode: C; c-file-style: "gnu" -*- */
4 * \file src/dbus-pcbmain.c
6 * \brief PCB HID main loop integration.
8 * Adapted from dbus-gmain.c from dbus-glib bindings:
10 * Copyright (C) 2002, 2003 CodeFactory AB
12 * Copyright (C) 2005 Red Hat, Inc.
14 * Licensed under the Academic Free License version 2.1
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #define DBUS_API_SUBJECT_TO_CHANGE
37 #include <dbus/dbus.h>
41 #include "dbus-pcbmain.h"
43 typedef struct _IOWatchHandler IOWatchHandler
;
44 typedef struct _TimeoutHandler TimeoutHandler
;
46 struct _IOWatchHandler
48 DBusWatch
*dbus_watch
;
52 struct _TimeoutHandler
54 DBusTimeout
*dbus_timeout
;
61 block_hook_cb (hidval data
)
63 DBusConnection
*connection
= (DBusConnection
*) data
.ptr
;
64 if (dbus_connection_get_dispatch_status (connection
) !=
65 DBUS_DISPATCH_DATA_REMAINS
)
68 // TODO: IS THIS NEEDED?
69 // dbus_connection_ref (connection);
71 /* Only dispatch once - we don't want to starve other mainloop users */
72 dbus_connection_dispatch (connection
);
74 // dbus_connection_unref (connection);
79 io_watch_handler_dbus_freed (void *data
)
81 IOWatchHandler
*handler
;
82 handler
= (IOWatchHandler
*)data
;
84 // Remove the watch registered with the HID
85 gui
->unwatch_file (handler
->pcb_watch
);
91 io_watch_handler_cb (hidval pcb_watch
,
92 int fd
, unsigned int condition
, hidval data
)
94 IOWatchHandler
*handler
;
95 unsigned int dbus_condition
= 0;
97 handler
= (IOWatchHandler
*) data
.ptr
;
99 // TODO: IS THIS NEEDED?
101 // dbus_connection_ref (connection);
103 if (condition
& PCB_WATCH_READABLE
)
104 dbus_condition
|= DBUS_WATCH_READABLE
;
105 if (condition
& PCB_WATCH_WRITABLE
)
106 dbus_condition
|= DBUS_WATCH_WRITABLE
;
107 if (condition
& PCB_WATCH_ERROR
)
108 dbus_condition
|= DBUS_WATCH_ERROR
;
109 if (condition
& PCB_WATCH_HANGUP
)
110 dbus_condition
|= DBUS_WATCH_HANGUP
;
112 /* We don't touch the handler after this, because DBus
113 * may have disabled the watch and thus killed the handler
115 dbus_watch_handle (handler
->dbus_watch
, dbus_condition
);
119 // dbus_connection_unref (connection);
126 timeout_handler_dbus_freed (void *data
)
128 TimeoutHandler
*handler
;
129 handler
= (TimeoutHandler
*)data
;
131 // Remove the timeout registered with the HID
132 gui
->stop_timer (handler
->pcb_timer
);
138 timeout_handler_cb (hidval data
)
140 TimeoutHandler
*handler
;
141 handler
= (TimeoutHandler
*)data
.ptr
;
143 // Re-add the timeout, as PCB will remove the current one
144 // Do this before calling to dbus, incase DBus removes the timeout.
145 // We can't touch handler after libdbus has been run for this reason.
147 gui
->add_timer (timeout_handler_cb
, handler
->interval
, data
);
149 dbus_timeout_handle (handler
->dbus_timeout
);
154 watch_add (DBusWatch
* dbus_watch
, void *data
)
156 IOWatchHandler
*handler
;
158 unsigned int pcb_condition
;
159 unsigned int dbus_flags
;
162 // We won't create a watch until it becomes enabled.
163 if (!dbus_watch_get_enabled (dbus_watch
))
166 dbus_flags
= dbus_watch_get_flags (dbus_watch
);
168 pcb_condition
= PCB_WATCH_ERROR
| PCB_WATCH_HANGUP
;
169 if (dbus_flags
& DBUS_WATCH_READABLE
)
170 pcb_condition
|= PCB_WATCH_READABLE
;
171 if (dbus_flags
& DBUS_WATCH_WRITABLE
)
172 pcb_condition
|= PCB_WATCH_READABLE
;
174 #if HAVE_DBUS_WATCH_GET_UNIX_FD
175 fd
= dbus_watch_get_unix_fd (dbus_watch
);
177 fd
= dbus_watch_get_fd (dbus_watch
);
180 handler
= (IOWatchHandler
*)malloc (sizeof (IOWatchHandler
));
181 temp
.ptr
= (void *)handler
;
182 handler
->dbus_watch
= dbus_watch
;
184 gui
->watch_file (fd
, pcb_condition
, io_watch_handler_cb
, temp
);
186 dbus_watch_set_data (dbus_watch
, handler
, io_watch_handler_dbus_freed
);
191 watch_remove (DBusWatch
* dbus_watch
, void *data
)
193 // Free the associated data. Its destroy callback removes the watch
194 dbus_watch_set_data (dbus_watch
, NULL
, NULL
);
198 watch_toggled (DBusWatch
* dbus_watch
, void *data
)
200 /* Simply add/remove the watch completely */
201 if (dbus_watch_get_enabled (dbus_watch
))
202 watch_add (dbus_watch
, data
);
204 watch_remove (dbus_watch
, data
);
209 timeout_add (DBusTimeout
* timeout
, void *data
)
211 TimeoutHandler
*handler
;
214 // We won't create a timeout until it becomes enabled.
215 if (!dbus_timeout_get_enabled (timeout
))
218 //FIXME: Need to store the interval, as PCB requires us
219 // to manually re-add the timer each time it expires.
220 // This is non-ideal, and hopefully can be changed?
222 handler
= (TimeoutHandler
*)malloc (sizeof (TimeoutHandler
));
223 temp
.ptr
= (void *)handler
;
224 handler
->dbus_timeout
= timeout
;
225 handler
->interval
= dbus_timeout_get_interval (timeout
);
227 gui
->add_timer (timeout_handler_cb
, handler
->interval
, temp
);
229 dbus_timeout_set_data (timeout
, handler
, timeout_handler_dbus_freed
);
234 timeout_remove (DBusTimeout
* timeout
, void *data
)
236 // Free the associated data. Its destroy callback removes the timer
237 dbus_timeout_set_data (timeout
, NULL
, NULL
);
241 timeout_toggled (DBusTimeout
* timeout
, void *data
)
243 /* Simply add/remove the timeout completely */
244 if (dbus_timeout_get_enabled (timeout
))
245 timeout_add (timeout
, data
);
247 timeout_remove (timeout
, data
);
251 dispatch_status_changed (DBusConnection
* conn
, DBusDispatchStatus new_status
,
254 // TODO: Can use this eventually to add one-shot idle work-functions to dispatch
255 // remaining IO. It could possibly replace the block_hook polling mechanism.
256 // (We could use a one-shot block_book to dispatch the work though.)
258 // *** NO DISPATCHING TO BE DONE INSIDE THIS FUNCTION ***
265 * Sets the watch and timeout functions of a #DBusConnection
266 * to integrate the connection with the GUI HID's main loop.
268 * @param connection the connection
271 pcb_dbus_connection_setup_with_mainloop (DBusConnection
* connection
)
273 //ConnectionSetup *cs;
276 /* FIXME we never free the slot, so its refcount just keeps growing,
277 * which is kind of broken.
279 //dbus_connection_allocate_data_slot (&connection_slot);
280 //if (connection_slot < 0)
284 cs
= connection_setup_new (connection
);
286 if (!dbus_connection_set_data (connection
, connection_slot
, cs
,
287 (DBusFreeFunction
) connection_setup_free
))
291 if (!dbus_connection_set_watch_functions (connection
,
294 watch_toggled
, NULL
, NULL
))
298 if (!dbus_connection_set_timeout_functions (connection
,
301 timeout_toggled
, NULL
, NULL
))
305 dbus_connection_set_dispatch_status_function (connection
,
306 dispatch_status_changed
,
310 /* Register a new mainloop hook to mop up any unfinished IO. */
311 temp
.ptr
= (void *)connection
;
312 gui
->add_block_hook (block_hook_cb
, temp
);
317 "Not enough memory to set up DBusConnection for use with PCB\n");
321 pcb_dbus_connection_finish_with_mainloop (DBusConnection
* connection
)
323 //ConnectionSetup *cs;
325 //cs = dbus_connection_get_data (connection, connection_slot );
327 // Replace the stored data with NULL, thus freeing the old data
328 // DBus will call the function connection_setup_free() which we registered earlier
329 //dbus_connection_set_data (connection, connection_slot, NULL, NULL );
331 //dbus_connection_free_data_slot( &connection_slot );
333 if (!dbus_connection_set_watch_functions (connection
,
334 NULL
, NULL
, NULL
, NULL
, NULL
))
337 if (!dbus_connection_set_timeout_functions (connection
,
338 NULL
, NULL
, NULL
, NULL
, NULL
))
341 dbus_connection_set_dispatch_status_function (connection
, NULL
, NULL
, NULL
);
345 "Not enough memory when cleaning up DBusConnection mainloop integration\n");