1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-pcbmain.c PCB HID main loop integration
4 * Adapted from dbus-gmain.c from dbus-glib bindings:
5 * Copyright (C) 2002, 2003 CodeFactory AB
6 * Copyright (C) 2005 Red Hat, Inc.
8 * Licensed under the Academic Free License version 2.1
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #define DBUS_API_SUBJECT_TO_CHANGE
32 #include <dbus/dbus.h>
36 #include "dbus-pcbmain.h"
38 typedef struct _IOWatchHandler IOWatchHandler
;
39 typedef struct _TimeoutHandler TimeoutHandler
;
41 struct _IOWatchHandler
43 DBusWatch
*dbus_watch
;
47 struct _TimeoutHandler
49 DBusTimeout
*dbus_timeout
;
56 block_hook_cb (hidval data
)
58 DBusConnection
*connection
= (DBusConnection
*) data
.ptr
;
59 if (dbus_connection_get_dispatch_status (connection
) !=
60 DBUS_DISPATCH_DATA_REMAINS
)
63 // TODO: IS THIS NEEDED?
64 // dbus_connection_ref (connection);
66 /* Only dispatch once - we don't want to starve other mainloop users */
67 dbus_connection_dispatch (connection
);
69 // dbus_connection_unref (connection);
74 io_watch_handler_dbus_freed (void *data
)
76 IOWatchHandler
*handler
;
77 handler
= (IOWatchHandler
*)data
;
79 // Remove the watch registered with the HID
80 gui
->unwatch_file (handler
->pcb_watch
);
86 io_watch_handler_cb (hidval pcb_watch
,
87 int fd
, unsigned int condition
, hidval data
)
89 IOWatchHandler
*handler
;
90 unsigned int dbus_condition
= 0;
92 handler
= (IOWatchHandler
*) data
.ptr
;
94 // TODO: IS THIS NEEDED?
96 // dbus_connection_ref (connection);
98 if (condition
& PCB_WATCH_READABLE
)
99 dbus_condition
|= DBUS_WATCH_READABLE
;
100 if (condition
& PCB_WATCH_WRITABLE
)
101 dbus_condition
|= DBUS_WATCH_WRITABLE
;
102 if (condition
& PCB_WATCH_ERROR
)
103 dbus_condition
|= DBUS_WATCH_ERROR
;
104 if (condition
& PCB_WATCH_HANGUP
)
105 dbus_condition
|= DBUS_WATCH_HANGUP
;
107 /* We don't touch the handler after this, because DBus
108 * may have disabled the watch and thus killed the handler
110 dbus_watch_handle (handler
->dbus_watch
, dbus_condition
);
114 // dbus_connection_unref (connection);
121 timeout_handler_dbus_freed (void *data
)
123 TimeoutHandler
*handler
;
124 handler
= (TimeoutHandler
*)data
;
126 // Remove the timeout registered with the HID
127 gui
->stop_timer (handler
->pcb_timer
);
133 timeout_handler_cb (hidval data
)
135 TimeoutHandler
*handler
;
136 handler
= (TimeoutHandler
*)data
.ptr
;
138 // Re-add the timeout, as PCB will remove the current one
139 // Do this before calling to dbus, incase DBus removes the timeout.
140 // We can't touch handler after libdbus has been run for this reason.
142 gui
->add_timer (timeout_handler_cb
, handler
->interval
, data
);
144 dbus_timeout_handle (handler
->dbus_timeout
);
149 watch_add (DBusWatch
* dbus_watch
, void *data
)
151 IOWatchHandler
*handler
;
153 unsigned int pcb_condition
;
154 unsigned int dbus_flags
;
157 // We won't create a watch until it becomes enabled.
158 if (!dbus_watch_get_enabled (dbus_watch
))
161 dbus_flags
= dbus_watch_get_flags (dbus_watch
);
163 pcb_condition
= PCB_WATCH_ERROR
| PCB_WATCH_HANGUP
;
164 if (dbus_flags
& DBUS_WATCH_READABLE
)
165 pcb_condition
|= PCB_WATCH_READABLE
;
166 if (dbus_flags
& DBUS_WATCH_WRITABLE
)
167 pcb_condition
|= PCB_WATCH_READABLE
;
169 #if HAVE_DBUS_WATCH_GET_UNIX_FD
170 fd
= dbus_watch_get_unix_fd (dbus_watch
);
172 fd
= dbus_watch_get_fd (dbus_watch
);
175 handler
= (IOWatchHandler
*)malloc (sizeof (IOWatchHandler
));
176 temp
.ptr
= (void *)handler
;
177 handler
->dbus_watch
= dbus_watch
;
179 gui
->watch_file (fd
, pcb_condition
, io_watch_handler_cb
, temp
);
181 dbus_watch_set_data (dbus_watch
, handler
, io_watch_handler_dbus_freed
);
186 watch_remove (DBusWatch
* dbus_watch
, void *data
)
188 // Free the associated data. Its destroy callback removes the watch
189 dbus_watch_set_data (dbus_watch
, NULL
, NULL
);
193 watch_toggled (DBusWatch
* dbus_watch
, void *data
)
195 /* Simply add/remove the watch completely */
196 if (dbus_watch_get_enabled (dbus_watch
))
197 watch_add (dbus_watch
, data
);
199 watch_remove (dbus_watch
, data
);
204 timeout_add (DBusTimeout
* timeout
, void *data
)
206 TimeoutHandler
*handler
;
209 // We won't create a timeout until it becomes enabled.
210 if (!dbus_timeout_get_enabled (timeout
))
213 //FIXME: Need to store the interval, as PCB requires us
214 // to manually re-add the timer each time it expires.
215 // This is non-ideal, and hopefully can be changed?
217 handler
= (TimeoutHandler
*)malloc (sizeof (TimeoutHandler
));
218 temp
.ptr
= (void *)handler
;
219 handler
->dbus_timeout
= timeout
;
220 handler
->interval
= dbus_timeout_get_interval (timeout
);
222 gui
->add_timer (timeout_handler_cb
, handler
->interval
, temp
);
224 dbus_timeout_set_data (timeout
, handler
, timeout_handler_dbus_freed
);
229 timeout_remove (DBusTimeout
* timeout
, void *data
)
231 // Free the associated data. Its destroy callback removes the timer
232 dbus_timeout_set_data (timeout
, NULL
, NULL
);
236 timeout_toggled (DBusTimeout
* timeout
, void *data
)
238 /* Simply add/remove the timeout completely */
239 if (dbus_timeout_get_enabled (timeout
))
240 timeout_add (timeout
, data
);
242 timeout_remove (timeout
, data
);
246 dispatch_status_changed (DBusConnection
* conn
, DBusDispatchStatus new_status
,
249 // TODO: Can use this eventually to add one-shot idle work-functions to dispatch
250 // remaining IO. It could possibly replace the block_hook polling mechanism.
251 // (We could use a one-shot block_book to dispatch the work though.)
253 // *** NO DISPATCHING TO BE DONE INSIDE THIS FUNCTION ***
260 * Sets the watch and timeout functions of a #DBusConnection
261 * to integrate the connection with the GUI HID's main loop.
263 * @param connection the connection
266 pcb_dbus_connection_setup_with_mainloop (DBusConnection
* connection
)
268 //ConnectionSetup *cs;
271 /* FIXME we never free the slot, so its refcount just keeps growing,
272 * which is kind of broken.
274 //dbus_connection_allocate_data_slot (&connection_slot);
275 //if (connection_slot < 0)
279 cs
= connection_setup_new (connection
);
281 if (!dbus_connection_set_data (connection
, connection_slot
, cs
,
282 (DBusFreeFunction
) connection_setup_free
))
286 if (!dbus_connection_set_watch_functions (connection
,
289 watch_toggled
, NULL
, NULL
))
293 if (!dbus_connection_set_timeout_functions (connection
,
296 timeout_toggled
, NULL
, NULL
))
300 dbus_connection_set_dispatch_status_function (connection
,
301 dispatch_status_changed
,
305 /* Register a new mainloop hook to mop up any unfinished IO. */
306 temp
.ptr
= (void *)connection
;
307 gui
->add_block_hook (block_hook_cb
, temp
);
312 "Not enough memory to set up DBusConnection for use with PCB\n");
316 pcb_dbus_connection_finish_with_mainloop (DBusConnection
* connection
)
318 //ConnectionSetup *cs;
320 //cs = dbus_connection_get_data (connection, connection_slot );
322 // Replace the stored data with NULL, thus freeing the old data
323 // DBus will call the function connection_setup_free() which we registered earlier
324 //dbus_connection_set_data (connection, connection_slot, NULL, NULL );
326 //dbus_connection_free_data_slot( &connection_slot );
328 if (!dbus_connection_set_watch_functions (connection
,
329 NULL
, NULL
, NULL
, NULL
, NULL
))
332 if (!dbus_connection_set_timeout_functions (connection
,
333 NULL
, NULL
, NULL
, NULL
, NULL
))
336 dbus_connection_set_dispatch_status_function (connection
, NULL
, NULL
, NULL
);
340 "Not enough memory when cleaning up DBusConnection mainloop integration\n");