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
;
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
;
126 // Remove the timeout registered with the HID
127 gui
->stop_timer (handler
->pcb_timer
);
133 timeout_handler_cb (hidval data
)
135 TimeoutHandler
*handler
;
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
;
156 // We won't create a watch until it becomes enabled.
157 if (!dbus_watch_get_enabled (dbus_watch
))
160 dbus_flags
= dbus_watch_get_flags (dbus_watch
);
162 pcb_condition
= PCB_WATCH_ERROR
| PCB_WATCH_HANGUP
;
163 if (dbus_flags
& DBUS_WATCH_READABLE
)
164 pcb_condition
|= PCB_WATCH_READABLE
;
165 if (dbus_flags
& DBUS_WATCH_WRITABLE
)
166 pcb_condition
|= PCB_WATCH_READABLE
;
168 #if HAVE_DBUS_WATCH_GET_UNIX_FD
169 fd
= dbus_watch_get_unix_fd (dbus_watch
);
171 fd
= dbus_watch_get_fd (dbus_watch
);
174 handler
= malloc (sizeof (IOWatchHandler
));
175 handler
->dbus_watch
= dbus_watch
;
177 gui
->watch_file (fd
, pcb_condition
, io_watch_handler_cb
,
178 (hidval
) (void *) handler
);
180 dbus_watch_set_data (dbus_watch
, handler
, io_watch_handler_dbus_freed
);
185 watch_remove (DBusWatch
* dbus_watch
, void *data
)
187 // Free the associated data. Its destroy callback removes the watch
188 dbus_watch_set_data (dbus_watch
, NULL
, NULL
);
192 watch_toggled (DBusWatch
* dbus_watch
, void *data
)
194 /* Simply add/remove the watch completely */
195 if (dbus_watch_get_enabled (dbus_watch
))
196 watch_add (dbus_watch
, data
);
198 watch_remove (dbus_watch
, data
);
203 timeout_add (DBusTimeout
* timeout
, void *data
)
205 TimeoutHandler
*handler
;
207 // We won't create a timeout until it becomes enabled.
208 if (!dbus_timeout_get_enabled (timeout
))
211 //FIXME: Need to store the interval, as PCB requires us
212 // to manually re-add the timer each time it expires.
213 // This is non-ideal, and hopefully can be changed?
215 handler
= malloc (sizeof (TimeoutHandler
));
216 handler
->dbus_timeout
= timeout
;
217 handler
->interval
= dbus_timeout_get_interval (timeout
);
219 gui
->add_timer (timeout_handler_cb
, handler
->interval
,
220 (hidval
) (void *) handler
);
222 dbus_timeout_set_data (timeout
, handler
, timeout_handler_dbus_freed
);
227 timeout_remove (DBusTimeout
* timeout
, void *data
)
229 // Free the associated data. Its destroy callback removes the timer
230 dbus_timeout_set_data (timeout
, NULL
, NULL
);
234 timeout_toggled (DBusTimeout
* timeout
, void *data
)
236 /* Simply add/remove the timeout completely */
237 if (dbus_timeout_get_enabled (timeout
))
238 timeout_add (timeout
, data
);
240 timeout_remove (timeout
, data
);
244 dispatch_status_changed (DBusConnection
* conn
, DBusDispatchStatus new_status
,
247 // TODO: Can use this eventually to add one-shot idle work-functions to dispatch
248 // remaining IO. It could possibly replace the block_hook polling mechanism.
249 // (We could use a one-shot block_book to dispatch the work though.)
251 // *** NO DISPATCHING TO BE DONE INSIDE THIS FUNCTION ***
258 * Sets the watch and timeout functions of a #DBusConnection
259 * to integrate the connection with the GUI HID's main loop.
261 * @param connection the connection
264 pcb_dbus_connection_setup_with_mainloop (DBusConnection
* connection
)
266 //ConnectionSetup *cs;
268 /* FIXME we never free the slot, so its refcount just keeps growing,
269 * which is kind of broken.
271 //dbus_connection_allocate_data_slot (&connection_slot);
272 //if (connection_slot < 0)
276 cs
= connection_setup_new (connection
);
278 if (!dbus_connection_set_data (connection
, connection_slot
, cs
,
279 (DBusFreeFunction
) connection_setup_free
))
283 if (!dbus_connection_set_watch_functions (connection
,
286 watch_toggled
, NULL
, NULL
))
290 if (!dbus_connection_set_timeout_functions (connection
,
293 timeout_toggled
, NULL
, NULL
))
297 dbus_connection_set_dispatch_status_function (connection
,
298 dispatch_status_changed
,
302 /* Register a new mainloop hook to mop up any unfinished IO. */
303 gui
->add_block_hook (block_hook_cb
, (hidval
) (void *) connection
);
308 "Not enough memory to set up DBusConnection for use with PCB\n");
312 pcb_dbus_connection_finish_with_mainloop (DBusConnection
* connection
)
314 //ConnectionSetup *cs;
316 //cs = dbus_connection_get_data (connection, connection_slot );
318 // Replace the stored data with NULL, thus freeing the old data
319 // DBus will call the function connection_setup_free() which we registered earlier
320 //dbus_connection_set_data (connection, connection_slot, NULL, NULL );
322 //dbus_connection_free_data_slot( &connection_slot );
324 if (!dbus_connection_set_watch_functions (connection
,
325 NULL
, NULL
, NULL
, NULL
, NULL
))
328 if (!dbus_connection_set_timeout_functions (connection
,
329 NULL
, NULL
, NULL
, NULL
, NULL
))
332 dbus_connection_set_dispatch_status_function (connection
, NULL
, NULL
, NULL
);
336 "Not enough memory when cleaning up DBusConnection mainloop integration\n");