1 /***************************************************************************
4 * dbus.c : D-BUS interface of HAL daemon
6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 **************************************************************************/
38 #include <dbus/dbus.h>
39 #include <dbus/dbus-glib-lowlevel.h>
42 #include "hald_dbus.h"
44 #include "device_store.h"
45 #include "device_info.h"
49 #include "hald_runner.h"
51 #define HALD_DBUS_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR
53 static DBusConnection
*dbus_connection
= NULL
;
56 raise_error (DBusConnection
*connection
,
57 DBusMessage
*in_reply_to
,
58 const char *error_name
,
59 char *format
, ...) __attribute__((format (printf
, 4, 5)));
62 * @defgroup DaemonErrors Error conditions
64 * @brief Various error messages the HAL daemon can raise
70 * @param connection D-Bus connection
71 * @param in_reply_to message to report error on
72 * @param error_name D-Bus error name
73 * @param format printf-style format for error message
76 raise_error (DBusConnection
*connection
,
77 DBusMessage
*in_reply_to
,
78 const char *error_name
,
85 va_start(args
, format
);
86 vsnprintf(buf
, sizeof buf
, format
, args
);
90 reply
= dbus_message_new_error (in_reply_to
, error_name
, buf
);
93 if (!dbus_connection_send (connection
, reply
, NULL
))
95 dbus_message_unref (reply
);
98 /** Raise the org.freedesktop.Hal.NoSuchDevice error
100 * @param connection D-Bus connection
101 * @param in_reply_to message to report error on
102 * @param udi Unique device id given
105 raise_no_such_device (DBusConnection
*connection
,
106 DBusMessage
*in_reply_to
, const char *udi
)
109 connection
, in_reply_to
,
110 "org.freedesktop.Hal.NoSuchDevice",
111 "No device with id %s",
116 /** Raise the org.freedesktop.Hal.NoSuchProperty error
118 * @param connection D-Bus connection
119 * @param in_reply_to message to report error on
120 * @param device_id Id of the device
121 * @param key Key of the property that didn't exist
124 raise_no_such_property (DBusConnection
*connection
,
125 DBusMessage
*in_reply_to
,
126 const char *device_id
, const char *key
)
129 connection
, in_reply_to
,
130 "org.freedesktop.Hal.NoSuchProperty",
131 "No property %s on device with id %s",
136 /** Raise the org.freedesktop.Hal.TypeMismatch error
138 * @param connection D-Bus connection
139 * @param in_reply_to message to report error on
140 * @param device_id Id of the device
141 * @param key Key of the property
144 raise_property_type_error (DBusConnection
*connection
,
145 DBusMessage
*in_reply_to
,
146 const char *device_id
, const char *key
)
149 connection
, in_reply_to
,
150 "org.freedesktop.Hal.TypeMismatch",
151 "Type mismatch setting property %s on device with id %s",
156 /** Raise the org.freedesktop.Hal.SyntaxError error
158 * @param connection D-Bus connection
159 * @param in_reply_to message to report error on
160 * @param method_name Name of the method that was invoked with
161 * the wrong signature
164 raise_syntax (DBusConnection
*connection
,
165 DBusMessage
*in_reply_to
, const char *method_name
)
168 connection
, in_reply_to
,
169 "org.freedesktop.Hal.SyntaxError",
170 "There is a syntax error in the invocation of the method %s",
175 /** Raise the org.freedesktop.Hal.DeviceNotLocked error
177 * @param connection D-Bus connection
178 * @param in_reply_to message to report error on
179 * @param device device which isn't locked
182 raise_device_not_locked (DBusConnection
*connection
,
183 DBusMessage
*in_reply_to
,
187 connection
, in_reply_to
,
188 "org.freedesktop.Hal.DeviceNotLocked",
189 "The device %s is not locked",
190 hal_device_get_udi (device
)
194 /** Raise the org.freedesktop.Hal.DeviceAlreadyLocked error
196 * @param connection D-Bus connection
197 * @param in_reply_to message to report error on
198 * @param device device which isn't locked
201 raise_device_already_locked (DBusConnection
*connection
,
202 DBusMessage
*in_reply_to
,
208 reason
= hal_device_property_get_string (device
, "info.locked.reason");
209 HAL_WARNING (("Device %s is already locked: %s",
210 hal_device_get_udi (device
), reason
));
213 reply
= dbus_message_new_error (in_reply_to
,
214 "org.freedesktop.Hal.DeviceAlreadyLocked",
217 if (reply
== NULL
|| !dbus_connection_send (connection
, reply
, NULL
))
220 dbus_message_unref (reply
);
223 /** Raise the org.freedesktop.Hal.BranchAlreadyClaimed error
225 * @param connection D-Bus connection
226 * @param in_reply_to message to report error on
227 * @param udi branch which isn't claimed
230 raise_branch_already_claimed (DBusConnection
*connection
,
231 DBusMessage
*in_reply_to
,
235 const char *claim_service
;
237 claim_service
= hal_device_property_get_string (device
, "info.claimed.service");
238 HAL_WARNING (("Branch %s is already claimed by: %s",
239 hal_device_get_udi (device
), claim_service
));
242 reply
= dbus_message_new_error (in_reply_to
,
243 "org.freedesktop.Hal.BranchAlreadyClaimed",
246 if (reply
== NULL
|| !dbus_connection_send (connection
, reply
, NULL
))
249 dbus_message_unref (reply
);
252 /** Raise the org.freedesktop.Hal.BranchNotClaimed error
254 * @param connection D-Bus connection
255 * @param in_reply_to message to report error on
256 * @param udi branch which isn't claimed
259 raise_branch_not_claimed (DBusConnection
*connection
,
260 DBusMessage
*in_reply_to
,
264 connection
, in_reply_to
,
265 "org.freedesktop.Hal.BranchNotClaimed",
266 "The branch %s is not claimed",
267 hal_device_get_udi (device
)
271 /** Raise the org.freedesktop.Hal.PermissionDenied error
273 * @param connection D-Bus connection
274 * @param in_reply_to message to report error on
275 * @param message what you're not allowed to do
278 raise_permission_denied (DBusConnection
*connection
,
279 DBusMessage
*in_reply_to
,
283 connection
, in_reply_to
,
284 "org.freedesktop.Hal.PermissionDenied",
285 "Permission denied: %s",
293 * @defgroup ManagerInterface D-BUS interface org.freedesktop.Hal.Manager
295 * @brief D-BUS interface for querying device objects
301 foreach_device_get_udi (HalDeviceStore
*store
, HalDevice
*device
,
304 DBusMessageIter
*iter
= user_data
;
307 udi
= hal_device_get_udi (device
);
308 dbus_message_iter_append_basic (iter
, DBUS_TYPE_STRING
, &udi
);
316 * array{object_reference} Manager.GetAllDevices()
319 * @param connection D-BUS connection
320 * @param message Message
321 * @return What to do with the message
324 manager_get_all_devices (DBusConnection
* connection
,
325 DBusMessage
* message
)
328 DBusMessageIter iter
;
329 DBusMessageIter iter_array
;
331 reply
= dbus_message_new_method_return (message
);
335 dbus_message_iter_init_append (reply
, &iter
);
336 dbus_message_iter_open_container (&iter
,
338 DBUS_TYPE_STRING_AS_STRING
,
341 hal_device_store_foreach (hald_get_gdl (),
342 foreach_device_get_udi
,
345 dbus_message_iter_close_container (&iter
, &iter_array
);
347 if (!dbus_connection_send (connection
, reply
, NULL
))
350 dbus_message_unref (reply
);
352 return DBUS_HANDLER_RESULT_HANDLED
;
358 DBusMessageIter
*iter
;
362 foreach_device_match_get_udi (HalDeviceStore
*store
, HalDevice
*device
,
365 DeviceMatchInfo
*info
= user_data
;
366 const char *dev_value
;
368 if (hal_device_property_get_type (device
,
369 info
->key
) != DBUS_TYPE_STRING
)
372 dev_value
= hal_device_property_get_string (device
, info
->key
);
374 if (dev_value
!= NULL
&& strcmp (dev_value
, info
->value
) == 0) {
376 udi
= hal_device_get_udi (device
);
377 dbus_message_iter_append_basic (info
->iter
,
386 foreach_device_match_get_udi_tdl (HalDeviceStore
*store
, HalDevice
*device
,
389 DeviceMatchInfo
*info
= user_data
;
390 const char *dev_value
;
392 /* skip devices in the TDL that hasn't got a real UDI yet */
393 if (strncmp (device
->udi
, "/org/freedesktop/Hal/devices/temp",
394 sizeof ("/org/freedesktop/Hal/devices/temp")) == 0)
397 if (hal_device_property_get_type (device
,
398 info
->key
) != DBUS_TYPE_STRING
)
401 dev_value
= hal_device_property_get_string (device
, info
->key
);
403 if (dev_value
!= NULL
&& strcmp (dev_value
, info
->value
) == 0) {
405 udi
= hal_device_get_udi (device
);
407 dbus_message_iter_append_basic (info
->iter
,
415 /** Find devices in the GDL where a single string property matches a given
416 * value. Also returns devices in the TDL that has a non-tmp UDI.
419 * array{object_reference} Manager.FindDeviceStringMatch(string key,
423 * @param connection D-BUS connection
424 * @param message Message
425 * @return What to do with the message
428 manager_find_device_string_match (DBusConnection
* connection
,
429 DBusMessage
* message
)
432 DBusMessageIter iter
;
433 DBusMessageIter iter_array
;
437 DeviceMatchInfo info
;
439 HAL_TRACE (("entering"));
441 dbus_error_init (&error
);
442 if (!dbus_message_get_args (message
, &error
,
443 DBUS_TYPE_STRING
, &key
,
444 DBUS_TYPE_STRING
, &value
,
445 DBUS_TYPE_INVALID
)) {
446 raise_syntax (connection
, message
,
447 "Manager.FindDeviceStringMatch");
448 return DBUS_HANDLER_RESULT_HANDLED
;
451 reply
= dbus_message_new_method_return (message
);
455 dbus_message_iter_init_append (reply
, &iter
);
456 dbus_message_iter_open_container (&iter
,
458 DBUS_TYPE_STRING_AS_STRING
,
463 info
.iter
= &iter_array
;
465 hal_device_store_foreach (hald_get_gdl (),
466 foreach_device_match_get_udi
,
469 /* Also returns devices in the TDL that has a non-tmp UDI */
470 hal_device_store_foreach (hald_get_tdl (),
471 foreach_device_match_get_udi_tdl
,
474 dbus_message_iter_close_container (&iter
, &iter_array
);
476 if (!dbus_connection_send (connection
, reply
, NULL
))
479 dbus_message_unref (reply
);
481 return DBUS_HANDLER_RESULT_HANDLED
;
485 const char *capability
;
486 DBusMessageIter
*iter
;
487 } DeviceCapabilityInfo
;
490 foreach_device_by_capability (HalDeviceStore
*store
, HalDevice
*device
, gpointer user_data
)
492 DeviceCapabilityInfo
*info
= (DeviceCapabilityInfo
*) user_data
;
494 if (hal_device_has_capability (device
, info
->capability
)) {
495 dbus_message_iter_append_basic (info
->iter
,
503 /** Find devices in the GDL with a given capability.
506 * array{object_reference} Manager.FindDeviceByCapability(string capability)
509 * @param connection D-BUS connection
510 * @param message Message
511 * @return What to do with the message
514 manager_find_device_by_capability (DBusConnection
* connection
,
515 DBusMessage
* message
)
518 DBusMessageIter iter
;
519 DBusMessageIter iter_array
;
521 const char *capability
;
522 DeviceCapabilityInfo info
;
524 HAL_TRACE (("entering"));
526 dbus_error_init (&error
);
527 if (!dbus_message_get_args (message
, &error
,
528 DBUS_TYPE_STRING
, &capability
,
529 DBUS_TYPE_INVALID
)) {
530 raise_syntax (connection
, message
,
531 "Manager.FindDeviceByCapability");
532 return DBUS_HANDLER_RESULT_HANDLED
;
535 reply
= dbus_message_new_method_return (message
);
539 dbus_message_iter_init_append (reply
, &iter
);
540 dbus_message_iter_open_container (&iter
,
542 DBUS_TYPE_STRING_AS_STRING
,
545 info
.capability
= capability
;
546 info
.iter
= &iter_array
;
548 hal_device_store_foreach (hald_get_gdl (),
549 foreach_device_by_capability
,
552 dbus_message_iter_close_container (&iter
, &iter_array
);
554 if (!dbus_connection_send (connection
, reply
, NULL
))
557 dbus_message_unref (reply
);
559 return DBUS_HANDLER_RESULT_HANDLED
;
563 /** Determine if a device exists.
566 * bool Manager.DeviceExists(string udi)
569 * @param connection D-BUS connection
570 * @param message Message
571 * @return What to do with the message
574 manager_device_exists (DBusConnection
* connection
, DBusMessage
* message
)
577 DBusMessageIter iter
;
583 dbus_error_init (&error
);
584 if (!dbus_message_get_args (message
, &error
,
585 DBUS_TYPE_STRING
, &udi
,
586 DBUS_TYPE_INVALID
)) {
587 raise_syntax (connection
, message
, "Manager.DeviceExists");
588 return DBUS_HANDLER_RESULT_HANDLED
;
591 HAL_TRACE (("entering, udi=%s", udi
));
593 d
= hal_device_store_find (hald_get_gdl (), udi
);
596 d
= hal_device_store_find (hald_get_tdl (), udi
);
598 reply
= dbus_message_new_method_return (message
);
599 dbus_message_iter_init_append (reply
, &iter
);
601 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &b
);
606 if (!dbus_connection_send (connection
, reply
, NULL
))
609 dbus_message_unref (reply
);
610 return DBUS_HANDLER_RESULT_HANDLED
;
613 /** Send signal DeviceAdded(string udi) on the org.freedesktop.Hal.Manager
614 * interface on the object /org/freedesktop/Hal/Manager.
616 * @param device The HalDevice added
619 manager_send_signal_device_added (HalDevice
*device
)
621 const char *udi
= hal_device_get_udi (device
);
622 DBusMessage
*message
;
623 DBusMessageIter iter
;
625 if (dbus_connection
== NULL
)
628 HAL_TRACE (("entering, udi=%s", udi
));
630 message
= dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
631 "org.freedesktop.Hal.Manager",
634 dbus_message_iter_init_append (message
, &iter
);
635 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &udi
);
637 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
638 DIE (("error broadcasting message"));
640 dbus_message_unref (message
);
646 /** Send signal DeviceRemoved(string udi) on the org.freedesktop.Hal.Manager
647 * interface on the object /org/freedesktop/Hal/Manager.
649 * @param device The HalDevice removed
652 manager_send_signal_device_removed (HalDevice
*device
)
654 const char *udi
= hal_device_get_udi (device
);
655 DBusMessage
*message
;
656 DBusMessageIter iter
;
658 if (dbus_connection
== NULL
)
661 HAL_TRACE (("entering, udi=%s", udi
));
663 message
= dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
664 "org.freedesktop.Hal.Manager",
667 dbus_message_iter_init_append (message
, &iter
);
668 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &udi
);
670 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
671 DIE (("error broadcasting message"));
673 dbus_message_unref (message
);
678 /** Send signal NewCapability(string udi, string capability) on the
679 * org.freedesktop.Hal.Manager interface on the object
680 * /org/freedesktop/Hal/Manager.
682 * @param udi Unique Device Id
683 * @param capability Capability
686 manager_send_signal_new_capability (HalDevice
*device
,
687 const char *capability
)
689 const char *udi
= hal_device_get_udi (device
);
690 DBusMessage
*message
;
691 DBusMessageIter iter
;
693 if (dbus_connection
== NULL
)
696 HAL_TRACE (("entering, udi=%s, cap=%s", udi
, capability
));
698 message
= dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
699 "org.freedesktop.Hal.Manager",
702 dbus_message_iter_init_append (message
, &iter
);
703 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &udi
);
704 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &capability
);
706 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
707 DIE (("error broadcasting message"));
709 dbus_message_unref (message
);
717 * @defgroup DeviceInterface D-BUS interface org.freedesktop.Hal.Device
719 * @brief D-BUS interface for generic device operations
724 foreach_property_append (HalDevice
*device
, HalProperty
*p
,
727 DBusMessageIter
*iter
;
728 DBusMessageIter iter_dict_entry
;
732 iter
= (DBusMessageIter
*)user_data
;
734 dbus_message_iter_open_container (iter
,
735 DBUS_TYPE_DICT_ENTRY
,
739 key
= hal_property_get_key (p
);
740 type
= hal_property_get_type (p
);
742 dbus_message_iter_append_basic (&iter_dict_entry
, DBUS_TYPE_STRING
, &key
);
745 case HAL_PROPERTY_TYPE_STRING
:
747 DBusMessageIter iter_var
;
750 v
= hal_property_get_string (p
);
752 dbus_message_iter_open_container (&iter_dict_entry
,
754 DBUS_TYPE_STRING_AS_STRING
,
757 dbus_message_iter_append_basic (&iter_var
,
761 dbus_message_iter_close_container (&iter_dict_entry
,
765 case HAL_PROPERTY_TYPE_INT32
:
767 DBusMessageIter iter_var
;
770 v
= hal_property_get_int (p
);
772 dbus_message_iter_open_container (&iter_dict_entry
,
774 DBUS_TYPE_INT32_AS_STRING
,
777 dbus_message_iter_append_basic (&iter_var
,
781 dbus_message_iter_close_container (&iter_dict_entry
,
785 case HAL_PROPERTY_TYPE_UINT64
:
787 DBusMessageIter iter_var
;
790 v
= hal_property_get_uint64 (p
);
792 dbus_message_iter_open_container (&iter_dict_entry
,
794 DBUS_TYPE_UINT64_AS_STRING
,
797 dbus_message_iter_append_basic (&iter_var
,
801 dbus_message_iter_close_container (&iter_dict_entry
,
805 case HAL_PROPERTY_TYPE_DOUBLE
:
807 DBusMessageIter iter_var
;
810 v
= hal_property_get_double (p
);
812 dbus_message_iter_open_container (&iter_dict_entry
,
814 DBUS_TYPE_DOUBLE_AS_STRING
,
817 dbus_message_iter_append_basic (&iter_var
,
821 dbus_message_iter_close_container (&iter_dict_entry
,
825 case HAL_PROPERTY_TYPE_BOOLEAN
:
827 DBusMessageIter iter_var
;
830 v
= hal_property_get_bool (p
);
832 dbus_message_iter_open_container (&iter_dict_entry
,
834 DBUS_TYPE_BOOLEAN_AS_STRING
,
837 dbus_message_iter_append_basic (&iter_var
,
841 dbus_message_iter_close_container (&iter_dict_entry
,
845 case HAL_PROPERTY_TYPE_STRLIST
:
847 DBusMessageIter iter_var
, iter_array
;
850 dbus_message_iter_open_container (&iter_dict_entry
,
852 DBUS_TYPE_ARRAY_AS_STRING
853 DBUS_TYPE_STRING_AS_STRING
,
856 dbus_message_iter_open_container (&iter_var
,
858 DBUS_TYPE_STRING_AS_STRING
,
861 for (iter
= hal_property_get_strlist (p
); iter
!= NULL
; iter
= iter
->next
) {
864 v
= (const char *) iter
->data
;
866 dbus_message_iter_append_basic (&iter_array
,
871 dbus_message_iter_close_container (&iter_var
,
874 dbus_message_iter_close_container (&iter_dict_entry
,
880 HAL_WARNING (("Unknown property type 0x%04x", type
));
884 dbus_message_iter_close_container (iter
, &iter_dict_entry
);
892 /** Get all properties on a device.
895 * map{string, any} Device.GetAllProperties()
897 * raises org.freedesktop.Hal.NoSuchDevice
900 * @param connection D-BUS connection
901 * @param message Message
902 * @return What to do with the message
905 device_get_all_properties (DBusConnection
* connection
,
906 DBusMessage
* message
)
909 DBusMessageIter iter
;
910 DBusMessageIter iter_dict
;
914 udi
= dbus_message_get_path (message
);
916 HAL_TRACE (("entering, udi=%s", udi
));
918 d
= hal_device_store_find (hald_get_gdl (), udi
);
920 d
= hal_device_store_find (hald_get_tdl (), udi
);
923 raise_no_such_device (connection
, message
, udi
);
924 return DBUS_HANDLER_RESULT_HANDLED
;
927 reply
= dbus_message_new_method_return (message
);
931 dbus_message_iter_init_append (reply
, &iter
);
933 dbus_message_iter_open_container (&iter
,
935 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
936 DBUS_TYPE_STRING_AS_STRING
937 DBUS_TYPE_VARIANT_AS_STRING
938 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
,
941 hal_device_property_foreach (d
,
942 foreach_property_append
,
945 dbus_message_iter_close_container (&iter
, &iter_dict
);
947 if (!dbus_connection_send (connection
, reply
, NULL
))
950 dbus_message_unref (reply
);
952 return DBUS_HANDLER_RESULT_HANDLED
;
956 #include <sys/stat.h>
958 user_at_console(unsigned long uid
)
962 return ((stat("/dev/vt/console_user", &st
) == 0) && (st
.st_uid
== uid
));
967 sender_has_privileges (DBusConnection
*connection
, DBusMessage
*message
)
970 unsigned long user_uid
;
971 const char *user_base_svc
;
976 user_base_svc
= dbus_message_get_sender (message
);
977 if (user_base_svc
== NULL
) {
978 HAL_WARNING (("Cannot determine base service of caller"));
982 HAL_DEBUG (("base_svc = %s", user_base_svc
));
984 dbus_error_init (&error
);
985 user_uid
= dbus_bus_get_unix_user (connection
, user_base_svc
, &error
);
986 if (user_uid
== (unsigned long) -1 || dbus_error_is_set (&error
)) {
987 HAL_WARNING (("Could not get uid for connection: %s %s", error
.name
, error
.message
));
988 dbus_error_free (&error
);
992 HAL_INFO (("uid for caller is %ld", user_uid
));
994 if (user_uid
!= 0 && user_uid
!= geteuid()) {
996 if (dbus_message_is_method_call (message
,
997 "org.freedesktop.Hal.Device",
999 if (user_at_console(user_uid
)) {
1005 HAL_WARNING (("uid %d is not privileged", user_uid
));
1016 /** Set multiple properties on a device in an atomic fashion.
1019 * Device.GetAllProperties(map{string, any} properties)
1021 * raises org.freedesktop.Hal.NoSuchDevice
1024 * @param connection D-BUS connection
1025 * @param message Message
1026 * @return What to do with the message
1028 static DBusHandlerResult
1029 device_set_multiple_properties (DBusConnection
*connection
, DBusMessage
*message
, dbus_bool_t local_interface
)
1032 DBusMessageIter iter
;
1033 DBusMessageIter dict_iter
;
1037 udi
= dbus_message_get_path (message
);
1039 HAL_TRACE (("entering, udi=%s", udi
));
1041 d
= hal_device_store_find (hald_get_gdl (), udi
);
1043 d
= hal_device_store_find (hald_get_tdl (), udi
);
1046 raise_no_such_device (connection
, message
, udi
);
1047 return DBUS_HANDLER_RESULT_HANDLED
;
1050 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
1051 raise_permission_denied (connection
, message
, "SetProperty: not privileged");
1052 return DBUS_HANDLER_RESULT_HANDLED
;
1055 dbus_message_iter_init (message
, &iter
);
1057 if (dbus_message_iter_get_arg_type (&iter
) != DBUS_TYPE_ARRAY
&&
1058 dbus_message_iter_get_element_type (&iter
) != DBUS_TYPE_DICT_ENTRY
) {
1059 HAL_ERROR (("error, expecting an array of dict entries", __FILE__
, __LINE__
));
1060 raise_syntax (connection
, message
, udi
);
1061 return DBUS_HANDLER_RESULT_HANDLED
;
1064 dbus_message_iter_recurse (&iter
, &dict_iter
);
1066 /* update atomically */
1067 device_property_atomic_update_begin ();
1069 while (dbus_message_iter_get_arg_type (&dict_iter
) == DBUS_TYPE_DICT_ENTRY
)
1071 DBusMessageIter dict_entry_iter
, var_iter
, array_iter
;
1076 dbus_message_iter_recurse (&dict_iter
, &dict_entry_iter
);
1077 dbus_message_iter_get_basic (&dict_entry_iter
, &key
);
1079 dbus_message_iter_next (&dict_entry_iter
);
1080 dbus_message_iter_recurse (&dict_entry_iter
, &var_iter
);
1081 change_type
= dbus_message_iter_get_arg_type (&var_iter
);
1085 switch (change_type
) {
1086 case DBUS_TYPE_ARRAY
:
1087 if (dbus_message_iter_get_element_type (&var_iter
) != DBUS_TYPE_STRING
) {
1090 dbus_message_iter_recurse (&var_iter
, &array_iter
);
1092 hal_device_property_strlist_clear (d
, key
);
1094 while (dbus_message_iter_get_arg_type (&array_iter
) == DBUS_TYPE_STRING
) {
1096 dbus_message_iter_get_basic (&array_iter
, &v
);
1097 HAL_INFO ((" strlist elem %s -> %s", key
, v
));
1098 rc
= hal_device_property_strlist_append (d
, key
, v
);
1099 dbus_message_iter_next (&array_iter
);
1103 case DBUS_TYPE_STRING
:
1106 dbus_message_iter_get_basic (&var_iter
, &v
);
1107 HAL_INFO (("%s -> %s", key
, v
));
1108 rc
= hal_device_property_set_string (d
, key
, v
);
1111 case DBUS_TYPE_INT32
:
1114 dbus_message_iter_get_basic (&var_iter
, &v
);
1115 HAL_INFO (("%s -> %d", key
, v
));
1116 rc
= hal_device_property_set_int (d
, key
, v
);
1119 case DBUS_TYPE_UINT64
:
1122 dbus_message_iter_get_basic (&var_iter
, &v
);
1123 HAL_INFO (("%s -> %lld", key
, v
));
1124 rc
= hal_device_property_set_uint64 (d
, key
, v
);
1127 case DBUS_TYPE_DOUBLE
:
1130 dbus_message_iter_get_basic (&var_iter
, &v
);
1131 HAL_INFO (("%s -> %g", key
, v
));
1132 rc
= hal_device_property_set_double (d
, key
, v
);
1135 case DBUS_TYPE_BOOLEAN
:
1138 dbus_message_iter_get_basic (&var_iter
, &v
);
1139 HAL_INFO (("%s -> %s", key
, v
? "True" : "False"));
1140 rc
= hal_device_property_set_bool (d
, key
, v
);
1148 /* TODO: error out on rc==FALSE? */
1150 dbus_message_iter_next (&dict_iter
);
1153 device_property_atomic_update_end ();
1156 reply
= dbus_message_new_method_return (message
);
1158 DIE (("No memory"));
1160 if (!dbus_connection_send (connection
, reply
, NULL
))
1161 DIE (("No memory"));
1163 dbus_message_unref (reply
);
1164 return DBUS_HANDLER_RESULT_HANDLED
;
1168 /** Get a property on a device.
1171 * any Device.GetProperty(string key)
1172 * string Device.GetPropertyString(string key)
1173 * int Device.GetPropertyInteger(string key)
1174 * bool Device.GetPropertyBoolean(string key)
1175 * double Device.GetPropertyDouble(string key)
1177 * raises org.freedesktop.Hal.NoSuchDevice,
1178 * org.freedesktop.Hal.NoSuchProperty
1181 * @param connection D-BUS connection
1182 * @param message Message
1183 * @return What to do with the message
1186 device_get_property (DBusConnection
* connection
, DBusMessage
* message
)
1189 DBusMessageIter iter
;
1197 udi
= dbus_message_get_path (message
);
1199 HAL_TRACE (("entering, udi=%s", udi
));
1201 d
= hal_device_store_find (hald_get_gdl (), udi
);
1203 d
= hal_device_store_find (hald_get_tdl (), udi
);
1206 raise_no_such_device (connection
, message
, udi
);
1207 return DBUS_HANDLER_RESULT_HANDLED
;
1210 dbus_error_init (&error
);
1211 if (!dbus_message_get_args (message
, &error
,
1212 DBUS_TYPE_STRING
, &key
,
1213 DBUS_TYPE_INVALID
)) {
1214 raise_syntax (connection
, message
, "GetProperty");
1215 return DBUS_HANDLER_RESULT_HANDLED
;
1218 p
= hal_device_property_find (d
, key
);
1220 raise_no_such_property (connection
, message
, udi
, key
);
1221 return DBUS_HANDLER_RESULT_HANDLED
;
1224 reply
= dbus_message_new_method_return (message
);
1226 DIE (("No memory"));
1228 dbus_message_iter_init_append (reply
, &iter
);
1230 type
= hal_property_get_type (p
);
1232 case HAL_PROPERTY_TYPE_STRING
:
1235 s
= hal_property_get_string (p
);
1236 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &s
);
1239 case HAL_PROPERTY_TYPE_INT32
:
1242 i
= hal_property_get_int (p
);
1243 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_INT32
, &i
);
1246 case HAL_PROPERTY_TYPE_UINT64
:
1249 ul
= hal_property_get_uint64 (p
);
1250 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_UINT64
, &ul
);
1253 case HAL_PROPERTY_TYPE_DOUBLE
:
1256 d
= hal_property_get_double (p
);
1257 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_DOUBLE
, &d
);
1260 case HAL_PROPERTY_TYPE_BOOLEAN
:
1263 b
= hal_property_get_bool (p
);
1264 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &b
);
1267 case HAL_PROPERTY_TYPE_STRLIST
:
1270 DBusMessageIter iter_array
;
1272 dbus_message_iter_open_container (&iter
,
1274 DBUS_TYPE_STRING_AS_STRING
,
1277 for (l
= hal_property_get_strlist (p
); l
!= NULL
; l
= g_slist_next (l
)) {
1278 dbus_message_iter_append_basic (&iter_array
, DBUS_TYPE_STRING
, &(l
->data
));
1281 dbus_message_iter_close_container (&iter
, &iter_array
);
1286 HAL_WARNING (("Unknown property type %d", type
));
1290 if (!dbus_connection_send (connection
, reply
, NULL
))
1291 DIE (("No memory"));
1293 dbus_message_unref (reply
);
1295 return DBUS_HANDLER_RESULT_HANDLED
;
1299 /** Get the type of a property on a device.
1302 * int Device.GetPropertyType(string key)
1304 * raises org.freedesktop.Hal.NoSuchDevice,
1305 * org.freedesktop.Hal.NoSuchProperty
1308 * @param connection D-BUS connection
1309 * @param message Message
1310 * @return What to do with the message
1313 device_get_property_type (DBusConnection
* connection
,
1314 DBusMessage
* message
)
1317 DBusMessageIter iter
;
1325 udi
= dbus_message_get_path (message
);
1327 HAL_TRACE (("entering, udi=%s", udi
));
1329 d
= hal_device_store_find (hald_get_gdl (), udi
);
1331 d
= hal_device_store_find (hald_get_tdl (), udi
);
1334 raise_no_such_device (connection
, message
, udi
);
1335 return DBUS_HANDLER_RESULT_HANDLED
;
1338 dbus_error_init (&error
);
1339 if (!dbus_message_get_args (message
, &error
,
1340 DBUS_TYPE_STRING
, &key
,
1341 DBUS_TYPE_INVALID
)) {
1342 raise_syntax (connection
, message
, "GetPropertyType");
1343 return DBUS_HANDLER_RESULT_HANDLED
;
1346 p
= hal_device_property_find (d
, key
);
1348 raise_no_such_property (connection
, message
, udi
, key
);
1349 return DBUS_HANDLER_RESULT_HANDLED
;
1352 reply
= dbus_message_new_method_return (message
);
1354 DIE (("No memory"));
1356 i
= hal_property_get_type (p
);
1357 dbus_message_iter_init_append (reply
, &iter
);
1358 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_INT32
, &i
);
1360 if (!dbus_connection_send (connection
, reply
, NULL
))
1361 DIE (("No memory"));
1363 dbus_message_unref (reply
);
1365 return DBUS_HANDLER_RESULT_HANDLED
;
1368 /** Set a property on a device.
1371 * void Device.SetProperty(string key, any value)
1372 * void Device.SetPropertyString(string key, string value)
1373 * void Device.SetPropertyInteger(string key, int value)
1374 * void Device.SetPropertyBoolean(string key, bool value)
1375 * void Device.SetPropertyDouble(string key, double value)
1377 * raises org.freedesktop.Hal.NoSuchDevice,
1378 * org.freedesktop.Hal.NoSuchProperty
1379 * org.freedesktop.Hal.TypeMismatch
1382 * @param connection D-BUS connection
1383 * @param message Message
1384 * @return What to do with the message
1387 device_set_property (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
1394 DBusMessageIter iter
;
1397 HAL_TRACE (("entering"));
1399 udi
= dbus_message_get_path (message
);
1401 dbus_message_iter_init (message
, &iter
);
1402 type
= dbus_message_iter_get_arg_type (&iter
);
1403 if (type
!= DBUS_TYPE_STRING
) {
1404 raise_syntax (connection
, message
, "SetProperty");
1405 return DBUS_HANDLER_RESULT_HANDLED
;
1407 dbus_message_iter_get_basic (&iter
, &key
);
1409 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
1410 raise_permission_denied (connection
, message
, "SetProperty: not privileged");
1411 return DBUS_HANDLER_RESULT_HANDLED
;
1414 HAL_DEBUG (("udi=%s, key=%s", udi
, key
));
1416 device
= hal_device_store_find (hald_get_gdl (), udi
);
1418 device
= hal_device_store_find (hald_get_tdl (), udi
);
1420 if (device
== NULL
) {
1421 raise_no_such_device (connection
, message
, udi
);
1422 return DBUS_HANDLER_RESULT_HANDLED
;
1424 dbus_message_iter_next (&iter
);
1426 /** @todo check permissions of the sender vs property to be modified */
1428 type
= dbus_message_iter_get_arg_type (&iter
);
1432 case DBUS_TYPE_STRING
:
1435 dbus_message_iter_get_basic (&iter
, &v
);
1436 rc
= hal_device_property_set_string (device
, key
, v
);
1439 case DBUS_TYPE_INT32
:
1442 dbus_message_iter_get_basic (&iter
, &v
);
1443 rc
= hal_device_property_set_int (device
, key
, v
);
1446 case DBUS_TYPE_UINT64
:
1449 dbus_message_iter_get_basic (&iter
, &v
);
1450 rc
= hal_device_property_set_uint64 (device
, key
, v
);
1453 case DBUS_TYPE_DOUBLE
:
1456 dbus_message_iter_get_basic (&iter
, &v
);
1457 rc
= hal_device_property_set_double (device
, key
, v
);
1460 case DBUS_TYPE_BOOLEAN
:
1463 dbus_message_iter_get_basic (&iter
, &v
);
1464 rc
= hal_device_property_set_bool (device
, key
, v
);
1468 HAL_WARNING (("Unsupported property type %d", type
));
1473 raise_property_type_error (connection
, message
, udi
, key
);
1474 return DBUS_HANDLER_RESULT_HANDLED
;
1477 reply
= dbus_message_new_method_return (message
);
1479 DIE (("No memory"));
1481 if (!dbus_connection_send (connection
, reply
, NULL
))
1482 DIE (("No memory"));
1484 dbus_message_unref (reply
);
1485 return DBUS_HANDLER_RESULT_HANDLED
;
1488 /** This function is used to modify the Capabilities property. The reason
1489 * for having a dedicated function is that the HAL daemon will broadcast
1490 * a signal on the Manager interface to tell applications that the device
1491 * have got a new capability.
1493 * This is useful as capabilities can be merged after the device is created.
1494 * One example of this is networking cards under Linux 2.6; the net.ethernet
1495 * capability is not merged when the device is initially found by looking in
1496 * /sys/devices; it is merged when the /sys/classes tree is searched.
1498 * Note that the signal is emitted every time this method is invoked even
1499 * though the capability already existed. This is useful in the above
1500 * scenario when the PCI class says ethernet networking card but we yet
1501 * don't have enough information to fill in the net.* and net.ethernet.*
1502 * fields since this only happens when we visit the /sys/classes tree.
1505 * void Device.AddCapability(string capability)
1507 * raises org.freedesktop.Hal.NoSuchDevice,
1508 * raises org.freedesktop.Hal.PermissionDenied,
1511 * @param connection D-BUS connection
1512 * @param message Message
1513 * @return What to do with the message
1516 device_add_capability (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
1519 const char *capability
;
1524 HAL_TRACE (("entering"));
1526 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
1527 raise_permission_denied (connection
, message
, "AddCapability: not privileged");
1528 return DBUS_HANDLER_RESULT_HANDLED
;
1531 udi
= dbus_message_get_path (message
);
1533 d
= hal_device_store_find (hald_get_gdl (), udi
);
1535 d
= hal_device_store_find (hald_get_tdl (), udi
);
1538 raise_no_such_device (connection
, message
, udi
);
1539 return DBUS_HANDLER_RESULT_HANDLED
;
1542 dbus_error_init (&error
);
1543 if (!dbus_message_get_args (message
, &error
,
1544 DBUS_TYPE_STRING
, &capability
,
1545 DBUS_TYPE_INVALID
)) {
1546 raise_syntax (connection
, message
, "AddCapability");
1547 return DBUS_HANDLER_RESULT_HANDLED
;
1551 hal_device_add_capability (d
, capability
);
1553 reply
= dbus_message_new_method_return (message
);
1555 DIE (("No memory"));
1557 if (!dbus_connection_send (connection
, reply
, NULL
))
1558 DIE (("No memory"));
1560 dbus_message_unref (reply
);
1561 return DBUS_HANDLER_RESULT_HANDLED
;
1566 static DBusHandlerResult
1567 device_string_list_append_prepend (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t do_prepend
)
1577 HAL_TRACE (("entering"));
1579 udi
= dbus_message_get_path (message
);
1581 d
= hal_device_store_find (hald_get_gdl (), udi
);
1583 d
= hal_device_store_find (hald_get_tdl (), udi
);
1586 raise_no_such_device (connection
, message
, udi
);
1587 return DBUS_HANDLER_RESULT_HANDLED
;
1590 dbus_error_init (&error
);
1591 if (!dbus_message_get_args (message
, &error
,
1592 DBUS_TYPE_STRING
, &key
,
1593 DBUS_TYPE_STRING
, &value
,
1594 DBUS_TYPE_INVALID
)) {
1595 raise_syntax (connection
, message
, do_prepend
? "StringListPrepend" : "StringListAppend");
1596 return DBUS_HANDLER_RESULT_HANDLED
;
1600 ret
= hal_device_property_strlist_prepend (d
, key
, value
);
1602 ret
= hal_device_property_strlist_append (d
, key
, value
);
1604 raise_property_type_error (connection
, message
, udi
, key
);
1605 return DBUS_HANDLER_RESULT_HANDLED
;
1608 reply
= dbus_message_new_method_return (message
);
1610 DIE (("No memory"));
1612 if (!dbus_connection_send (connection
, reply
, NULL
))
1613 DIE (("No memory"));
1615 dbus_message_unref (reply
);
1616 return DBUS_HANDLER_RESULT_HANDLED
;
1620 static DBusHandlerResult
1621 device_string_list_remove (DBusConnection
* connection
, DBusMessage
* message
)
1631 HAL_TRACE (("entering"));
1633 udi
= dbus_message_get_path (message
);
1635 d
= hal_device_store_find (hald_get_gdl (), udi
);
1637 d
= hal_device_store_find (hald_get_tdl (), udi
);
1640 raise_no_such_device (connection
, message
, udi
);
1641 return DBUS_HANDLER_RESULT_HANDLED
;
1644 dbus_error_init (&error
);
1645 if (!dbus_message_get_args (message
, &error
,
1646 DBUS_TYPE_STRING
, &key
,
1647 DBUS_TYPE_STRING
, &value
,
1648 DBUS_TYPE_INVALID
)) {
1649 raise_syntax (connection
, message
, "StringListRemove");
1650 return DBUS_HANDLER_RESULT_HANDLED
;
1653 ret
= hal_device_property_strlist_remove (d
, key
, value
);
1655 raise_property_type_error (connection
, message
, udi
, key
);
1656 return DBUS_HANDLER_RESULT_HANDLED
;
1659 reply
= dbus_message_new_method_return (message
);
1661 DIE (("No memory"));
1663 if (!dbus_connection_send (connection
, reply
, NULL
))
1664 DIE (("No memory"));
1666 dbus_message_unref (reply
);
1667 return DBUS_HANDLER_RESULT_HANDLED
;
1672 /** Remove a property on a device.
1675 * void Device.RemoveProperty(string key)
1677 * raises org.freedesktop.Hal.NoSuchDevice,
1678 * org.freedesktop.Hal.NoSuchProperty
1679 * org.freedesktop.Hal.PermissionDenied
1682 * @param connection D-BUS connection
1683 * @param message Message
1684 * @return What to do with the message
1687 device_remove_property (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
1695 HAL_TRACE (("entering"));
1697 udi
= dbus_message_get_path (message
);
1699 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
1700 raise_permission_denied (connection
, message
, "RemoveProperty: not privileged");
1701 return DBUS_HANDLER_RESULT_HANDLED
;
1704 d
= hal_device_store_find (hald_get_gdl (), udi
);
1706 d
= hal_device_store_find (hald_get_tdl (), udi
);
1709 raise_no_such_device (connection
, message
, udi
);
1710 return DBUS_HANDLER_RESULT_HANDLED
;
1713 dbus_error_init (&error
);
1714 if (!dbus_message_get_args (message
, &error
,
1715 DBUS_TYPE_STRING
, &key
,
1716 DBUS_TYPE_INVALID
)) {
1717 raise_syntax (connection
, message
, "RemoveProperty");
1718 return DBUS_HANDLER_RESULT_HANDLED
;
1721 if (!hal_device_property_remove (d
, key
)) {
1722 raise_no_such_property (connection
, message
, udi
, key
);
1723 return DBUS_HANDLER_RESULT_HANDLED
;
1727 reply
= dbus_message_new_method_return (message
);
1729 DIE (("No memory"));
1731 if (!dbus_connection_send (connection
, reply
, NULL
))
1732 DIE (("No memory"));
1734 dbus_message_unref (reply
);
1735 return DBUS_HANDLER_RESULT_HANDLED
;
1739 /** Determine if a property exists
1742 * bool Device.PropertyExists(string key)
1744 * raises org.freedesktop.Hal.NoSuchDevice,
1747 * @param connection D-BUS connection
1748 * @param message Message
1749 * @return What to do with the message
1752 device_property_exists (DBusConnection
* connection
, DBusMessage
* message
)
1759 DBusMessageIter iter
;
1762 HAL_TRACE (("entering"));
1764 udi
= dbus_message_get_path (message
);
1766 d
= hal_device_store_find (hald_get_gdl (), udi
);
1768 d
= hal_device_store_find (hald_get_tdl (), udi
);
1771 raise_no_such_device (connection
, message
, udi
);
1772 return DBUS_HANDLER_RESULT_HANDLED
;
1775 dbus_error_init (&error
);
1776 if (!dbus_message_get_args (message
, &error
,
1777 DBUS_TYPE_STRING
, &key
,
1778 DBUS_TYPE_INVALID
)) {
1779 raise_syntax (connection
, message
, "RemoveProperty");
1780 return DBUS_HANDLER_RESULT_HANDLED
;
1783 reply
= dbus_message_new_method_return (message
);
1785 DIE (("No memory"));
1787 b
= hal_device_has_property (d
, key
);
1788 dbus_message_iter_init_append (reply
, &iter
);
1789 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &b
);
1791 if (!dbus_connection_send (connection
, reply
, NULL
))
1792 DIE (("No memory"));
1794 dbus_message_unref (reply
);
1795 return DBUS_HANDLER_RESULT_HANDLED
;
1799 /** Determine if a device has a capability
1802 * bool Device.QueryCapability(string capability_name)
1804 * raises org.freedesktop.Hal.NoSuchDevice,
1807 * @param connection D-BUS connection
1808 * @param message Message
1809 * @return What to do with the message
1812 device_query_capability (DBusConnection
* connection
,
1813 DBusMessage
* message
)
1822 DBusMessageIter iter
;
1824 HAL_TRACE (("entering"));
1826 udi
= dbus_message_get_path (message
);
1828 d
= hal_device_store_find (hald_get_gdl (), udi
);
1830 d
= hal_device_store_find (hald_get_tdl (), udi
);
1833 raise_no_such_device (connection
, message
, udi
);
1834 return DBUS_HANDLER_RESULT_HANDLED
;
1837 dbus_error_init (&error
);
1838 if (!dbus_message_get_args (message
, &error
,
1839 DBUS_TYPE_STRING
, &capability
,
1840 DBUS_TYPE_INVALID
)) {
1841 raise_syntax (connection
, message
, "QueryCapability");
1842 return DBUS_HANDLER_RESULT_HANDLED
;
1845 reply
= dbus_message_new_method_return (message
);
1847 DIE (("No memory"));
1850 caps
= hal_device_property_get_strlist (d
, "info.capabilities");
1854 for (iter
= caps
; iter
!= NULL
; iter
=g_slist_next(iter
)) {
1855 if (strcmp (iter
->data
, capability
) == 0) {
1862 dbus_message_iter_init_append (reply
, &iter
);
1863 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &rc
);
1865 if (!dbus_connection_send (connection
, reply
, NULL
))
1866 DIE (("No memory"));
1868 dbus_message_unref (reply
);
1869 return DBUS_HANDLER_RESULT_HANDLED
;
1872 static GHashTable
*services_with_locks
= NULL
;
1874 /** Grab an advisory lock on a device.
1877 * bool Device.Lock(string reason)
1879 * raises org.freedesktop.Hal.NoSuchDevice,
1880 * org.freedesktop.Hal.DeviceAlreadyLocked
1883 * @param connection D-BUS connection
1884 * @param message Message
1885 * @return What to do with the message
1888 device_lock (DBusConnection
* connection
,
1889 DBusMessage
* message
)
1894 dbus_bool_t already_locked
;
1899 HAL_TRACE (("entering"));
1901 udi
= dbus_message_get_path (message
);
1903 d
= hal_device_store_find (hald_get_gdl (), udi
);
1905 d
= hal_device_store_find (hald_get_tdl (), udi
);
1908 raise_no_such_device (connection
, message
, udi
);
1909 return DBUS_HANDLER_RESULT_HANDLED
;
1912 already_locked
= hal_device_property_get_bool (d
, "info.locked");
1914 if (already_locked
) {
1915 raise_device_already_locked (connection
, message
, d
);
1916 return DBUS_HANDLER_RESULT_HANDLED
;
1919 dbus_error_init (&error
);
1920 if (!dbus_message_get_args (message
, &error
,
1921 DBUS_TYPE_STRING
, &reason
,
1922 DBUS_TYPE_INVALID
)) {
1923 raise_syntax (connection
, message
, "Lock");
1924 return DBUS_HANDLER_RESULT_HANDLED
;
1927 reply
= dbus_message_new_method_return (message
);
1929 DIE (("No memory"));
1931 sender
= dbus_message_get_sender (message
);
1933 hal_device_property_set_bool (d
, "info.locked", TRUE
);
1934 hal_device_property_set_string (d
, "info.locked.reason", reason
);
1935 hal_device_property_set_string (d
, "info.locked.dbus_name",
1938 if (services_with_locks
== NULL
) {
1939 services_with_locks
=
1940 g_hash_table_new_full (g_str_hash
,
1946 g_hash_table_insert (services_with_locks
, g_strdup (sender
),
1949 if (!dbus_connection_send (connection
, reply
, NULL
))
1950 DIE (("No memory"));
1952 dbus_message_unref (reply
);
1953 return DBUS_HANDLER_RESULT_HANDLED
;
1956 /** Release an advisory lock on a device.
1959 * bool Device.Unlock()
1961 * raises org.freedesktop.Hal.NoSuchDevice,
1962 * org.freedesktop.Hal.DeviceNotLocked,
1963 * org.freedesktop.Hal.PermissionDenied
1966 * @param connection D-BUS connection
1967 * @param message Message
1968 * @return What to do with the message
1971 device_unlock (DBusConnection
* connection
,
1972 DBusMessage
* message
)
1981 HAL_TRACE (("entering"));
1983 udi
= dbus_message_get_path (message
);
1985 d
= hal_device_store_find (hald_get_gdl (), udi
);
1987 d
= hal_device_store_find (hald_get_tdl (), udi
);
1990 raise_no_such_device (connection
, message
, udi
);
1991 return DBUS_HANDLER_RESULT_HANDLED
;
1994 dbus_error_init (&error
);
1995 if (!dbus_message_get_args (message
, &error
,
1996 DBUS_TYPE_INVALID
)) {
1997 raise_syntax (connection
, message
, "Unlock");
1998 return DBUS_HANDLER_RESULT_HANDLED
;
2001 reply
= dbus_message_new_method_return (message
);
2003 DIE (("No memory"));
2005 rc
= hal_device_property_get_bool (d
, "info.locked");
2008 raise_device_not_locked (connection
, message
, d
);
2009 return DBUS_HANDLER_RESULT_HANDLED
;
2012 sender
= dbus_message_get_sender (message
);
2014 if (strcmp (sender
, hal_device_property_get_string (
2015 d
, "info.locked.dbus_name")) != 0) {
2018 reason
= g_strdup_printf ("Service '%s' does not own the "
2019 "lock on %s", sender
,
2020 hal_device_get_udi (d
));
2022 raise_permission_denied (connection
, message
, reason
);
2026 return DBUS_HANDLER_RESULT_HANDLED
;
2029 if (g_hash_table_lookup (services_with_locks
, sender
))
2030 g_hash_table_remove (services_with_locks
, sender
);
2032 HAL_WARNING (("Service '%s' was not in the list of services "
2033 "with locks!", sender
));
2036 hal_device_property_remove (d
, "info.locked");
2037 hal_device_property_remove (d
, "info.locked.reason");
2038 hal_device_property_remove (d
, "info.locked.dbus_name");
2040 /* FIXME? Pointless? */
2041 if (!dbus_connection_send (connection
, reply
, NULL
))
2042 DIE (("No memory"));
2044 dbus_message_unref (reply
);
2045 return DBUS_HANDLER_RESULT_HANDLED
;
2048 static GHashTable
*services_with_claims
= NULL
;
2053 * bool Manager.ClaimBranch(string udi, string claim_service)
2056 * @param connection D-BUS connection
2057 * @param message Message
2058 * @return What to do with the message
2061 manager_claim_branch (DBusConnection
* connection
, DBusMessage
* message
)
2064 DBusMessageIter iter
;
2068 const char *claim_service
;
2070 dbus_bool_t already_claimed
;
2073 dbus_error_init (&error
);
2074 if (!dbus_message_get_args (message
, &error
,
2075 DBUS_TYPE_STRING
, &udi
,
2076 DBUS_TYPE_STRING
, &claim_service
,
2077 DBUS_TYPE_INVALID
)) {
2078 raise_syntax (connection
, message
, "Manager.ClaimBranch");
2079 return DBUS_HANDLER_RESULT_HANDLED
;
2082 HAL_TRACE (("entering, udi=%s", udi
));
2084 d
= hal_device_store_find (hald_get_gdl (), udi
);
2087 raise_no_such_device (connection
, message
, udi
);
2088 return DBUS_HANDLER_RESULT_HANDLED
;
2091 already_claimed
= hal_device_property_get_bool (d
, "info.claimed");
2092 if (already_claimed
) {
2093 raise_branch_already_claimed (connection
, message
, d
);
2094 return DBUS_HANDLER_RESULT_HANDLED
;
2097 reply
= dbus_message_new_method_return (message
);
2099 DIE (("No memory"));
2101 sender
= dbus_message_get_sender (message
);
2103 dbus_error_init (&error
);
2104 uid
= dbus_bus_get_unix_user (connection
, sender
, &error
);
2105 if (uid
== (unsigned long) -1 || dbus_error_is_set (&error
)) {
2106 HAL_WARNING (("Could not get uid for connection: %s %s", error
.name
, error
.message
));
2107 dbus_error_free (&error
);
2108 dbus_message_unref (reply
);
2109 raise_no_such_device (connection
, message
, udi
);
2110 return DBUS_HANDLER_RESULT_HANDLED
;
2113 hal_util_branch_claim (hald_get_gdl (), d
, TRUE
, claim_service
, uid
);
2114 hal_device_property_set_string (d
, "info.claimed.dbus_name", sender
);
2116 if (services_with_claims
== NULL
) {
2117 services_with_claims
=
2118 g_hash_table_new_full (g_str_hash
,
2124 g_hash_table_insert (services_with_claims
, g_strdup (sender
),
2127 if (!dbus_connection_send (connection
, reply
, NULL
))
2128 DIE (("No memory"));
2130 dbus_message_unref (reply
);
2131 return DBUS_HANDLER_RESULT_HANDLED
;
2134 /** Unclaim a branch.
2137 * bool Manager.UnclaimBranch(string udi)
2140 * @param connection D-BUS connection
2141 * @param message Message
2142 * @return What to do with the message
2145 manager_unclaim_branch (DBusConnection
* connection
, DBusMessage
* message
)
2148 DBusMessageIter iter
;
2152 const char *claim_service
;
2154 dbus_bool_t already_claimed
;
2156 dbus_error_init (&error
);
2157 if (!dbus_message_get_args (message
, &error
,
2158 DBUS_TYPE_STRING
, &udi
,
2159 DBUS_TYPE_INVALID
)) {
2160 raise_syntax (connection
, message
, "Manager.UnclaimBranch");
2161 return DBUS_HANDLER_RESULT_HANDLED
;
2164 HAL_TRACE (("entering, udi=%s", udi
));
2166 d
= hal_device_store_find (hald_get_gdl (), udi
);
2169 raise_no_such_device (connection
, message
, udi
);
2170 return DBUS_HANDLER_RESULT_HANDLED
;
2173 already_claimed
= hal_device_property_get_bool (d
, "info.claimed");
2174 if (!already_claimed
) {
2175 raise_branch_not_claimed (connection
, message
, d
);
2176 return DBUS_HANDLER_RESULT_HANDLED
;
2179 reply
= dbus_message_new_method_return (message
);
2181 DIE (("No memory"));
2183 if (strcmp (sender
, hal_device_property_get_string (
2184 d
, "info.claimed.dbus_name")) != 0) {
2187 reason
= g_strdup_printf ("Service '%s' does not own the "
2188 "claim on %s", sender
,
2189 hal_device_get_udi (d
));
2191 raise_permission_denied (connection
, message
, reason
);
2195 return DBUS_HANDLER_RESULT_HANDLED
;
2198 if (g_hash_table_lookup (services_with_claims
, sender
))
2199 g_hash_table_remove (services_with_claims
, sender
);
2201 HAL_WARNING (("Service '%s' was not in the list of services "
2202 "with claims!", sender
));
2205 hal_util_branch_claim (hald_get_gdl (), d
, FALSE
, NULL
, 0);
2206 hal_device_property_remove (d
, "info.claimed.dbus_name");
2208 if (!dbus_connection_send (connection
, reply
, NULL
))
2209 DIE (("No memory"));
2211 dbus_message_unref (reply
);
2212 return DBUS_HANDLER_RESULT_HANDLED
;
2216 /** Counter for atomic updating */
2217 static int atomic_count
= 0;
2219 /** Number of updates pending */
2220 static int num_pending_updates
= 0;
2222 /** Structure for queing updates */
2223 typedef struct PendingUpdate_s
{
2224 char *udi
; /**< udi of device */
2225 char *key
; /**< key of property; free when done */
2226 dbus_bool_t removed
; /**< true iff property was removed */
2227 dbus_bool_t added
; /**< true iff property was added */
2228 struct PendingUpdate_s
*next
; /**< next update or #NULL */
2231 static PendingUpdate
*pending_updates_head
= NULL
;
2233 /** Begin an atomic update - this is useful for updating several properties
2236 * Note that an atomic update is recursive - use with caution!
2239 device_property_atomic_update_begin (void)
2244 /** End an atomic update.
2246 * Note that an atomic update is recursive - use with caution!
2249 device_property_atomic_update_end (void)
2251 PendingUpdate
*pu_iter
= NULL
;
2252 PendingUpdate
*pu_iter_next
= NULL
;
2253 PendingUpdate
*pu_iter2
= NULL
;
2257 if (atomic_count
< 0) {
2258 HAL_WARNING (("*** atomic_count = %d < 0 !!", atomic_count
));
2262 if (atomic_count
== 0 && num_pending_updates
> 0) {
2263 DBusMessage
*message
;
2264 DBusMessageIter iter
;
2265 DBusMessageIter iter_array
;
2267 for (pu_iter
= pending_updates_head
;
2268 pu_iter
!= NULL
; pu_iter
= pu_iter_next
) {
2269 int num_updates_this
;
2271 pu_iter_next
= pu_iter
->next
;
2273 /* see if we've already processed this */
2274 if (pu_iter
->udi
== NULL
)
2275 goto already_processed
;
2277 /* count number of updates for this device */
2278 num_updates_this
= 0;
2279 for (pu_iter2
= pu_iter
; pu_iter2
!= NULL
; pu_iter2
= pu_iter2
->next
) {
2280 if (strcmp (pu_iter2
->udi
, pu_iter
->udi
) == 0)
2284 /* prepare message */
2285 message
= dbus_message_new_signal (pu_iter
->udi
,
2286 "org.freedesktop.Hal.Device",
2287 "PropertyModified");
2288 dbus_message_iter_init_append (message
, &iter
);
2289 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_INT32
,
2292 dbus_message_iter_open_container (&iter
,
2294 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2295 DBUS_TYPE_STRING_AS_STRING
2296 DBUS_TYPE_BOOLEAN_AS_STRING
2297 DBUS_TYPE_BOOLEAN_AS_STRING
2298 DBUS_STRUCT_END_CHAR_AS_STRING
,
2301 for (pu_iter2
= pu_iter
; pu_iter2
!= NULL
;
2302 pu_iter2
= pu_iter2
->next
) {
2303 if (strcmp (pu_iter2
->udi
, pu_iter
->udi
) == 0) {
2304 DBusMessageIter iter_struct
;
2305 dbus_message_iter_open_container (&iter_array
,
2309 dbus_message_iter_append_basic
2313 dbus_message_iter_append_basic
2316 &(pu_iter2
->removed
));
2317 dbus_message_iter_append_basic
2320 &(pu_iter2
->added
));
2322 dbus_message_iter_close_container (&iter_array
, &iter_struct
);
2324 /* signal this is already processed */
2325 g_free (pu_iter2
->key
);
2326 if (pu_iter2
!= pu_iter
) {
2327 g_free (pu_iter2
->udi
);
2328 pu_iter2
->udi
= NULL
;
2333 g_free (pu_iter
->udi
);
2334 dbus_message_iter_close_container (&iter
, &iter_array
);
2336 if (dbus_connection
!= NULL
) {
2337 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
2338 DIE (("error broadcasting message"));
2341 dbus_message_unref (message
);
2346 } /* for all updates */
2348 num_pending_updates
= 0;
2349 pending_updates_head
= NULL
;
2356 device_send_signal_property_modified (HalDevice
*device
, const char *key
,
2357 dbus_bool_t added
, dbus_bool_t removed
)
2359 const char *udi
= hal_device_get_udi (device
);
2360 DBusMessage
*message
;
2361 DBusMessageIter iter
;
2364 HAL_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
2366 in_gdl ? "true" : "false",
2367 removed ? "true" : "false",
2368 added ? "true" : "false"));
2371 if (atomic_count
> 0) {
2374 pu
= g_new0 (PendingUpdate
, 1);
2375 pu
->udi
= g_strdup (udi
);
2376 pu
->key
= g_strdup (key
);
2377 pu
->removed
= removed
;
2379 pu
->next
= pending_updates_head
;
2381 pending_updates_head
= pu
;
2382 num_pending_updates
++;
2385 DBusMessageIter iter_struct
;
2386 DBusMessageIter iter_array
;
2388 if (dbus_connection
== NULL
)
2391 message
= dbus_message_new_signal (udi
,
2392 "org.freedesktop.Hal.Device",
2393 "PropertyModified");
2395 dbus_message_iter_init_append (message
, &iter
);
2397 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_INT32
, &i
);
2399 dbus_message_iter_open_container (&iter
,
2401 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2402 DBUS_TYPE_STRING_AS_STRING
2403 DBUS_TYPE_BOOLEAN_AS_STRING
2404 DBUS_TYPE_BOOLEAN_AS_STRING
2405 DBUS_STRUCT_END_CHAR_AS_STRING
,
2408 dbus_message_iter_open_container (&iter_array
,
2413 dbus_message_iter_append_basic (&iter_struct
, DBUS_TYPE_STRING
, &key
);
2414 dbus_message_iter_append_basic (&iter_struct
, DBUS_TYPE_BOOLEAN
, &removed
);
2415 dbus_message_iter_append_basic (&iter_struct
, DBUS_TYPE_BOOLEAN
, &added
);
2417 dbus_message_iter_close_container (&iter_array
, &iter_struct
);
2418 dbus_message_iter_close_container (&iter
, &iter_array
);
2420 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
2421 DIE (("error broadcasting message"));
2423 dbus_message_unref (message
);
2429 /** Emits a condition on a device; the device has to be in the GDL for
2430 * this function to have effect.
2432 * Is intended for non-continuous events on the device like
2433 * ProcesserOverheating, BlockDeviceGotDevice, e.g. conditions that
2434 * are exceptional and may not be inferred by looking at properties
2435 * (though some may).
2437 * This function accepts a number of parameters that are passed along
2438 * in the D-BUS message. The recipient is supposed to extract the parameters
2439 * himself, by looking at the HAL specification.
2441 * @param udi The UDI for this device
2442 * @param condition_name Name of condition
2443 * @param first_arg_type Type of the first argument
2444 * @param ... value of first argument, list of additional
2445 * type-value pairs. Must be terminated with
2449 device_send_signal_condition (HalDevice
*device
, const char *condition_name
, const char *condition_details
)
2451 const char *udi
= hal_device_get_udi (device
);
2452 DBusMessage
*message
;
2453 DBusMessageIter iter
;
2455 if (dbus_connection
== NULL
)
2458 message
= dbus_message_new_signal (udi
,
2459 "org.freedesktop.Hal.Device",
2461 dbus_message_iter_init_append (message
, &iter
);
2462 dbus_message_iter_append_basic (&iter
,
2465 dbus_message_iter_append_basic (&iter
,
2467 &condition_details
);
2469 if (!dbus_connection_send (dbus_connection
, message
, NULL
))
2470 DIE (("error broadcasting message"));
2472 dbus_message_unref (message
);
2480 reinit_dbus (gpointer user_data
)
2482 HAL_INFO (("entering!"));
2483 if (hald_dbus_init ())
2490 service_deleted (DBusMessage
*message
)
2492 char *old_service_name
;
2493 char *new_service_name
;
2496 if (!dbus_message_get_args (message
, NULL
,
2497 DBUS_TYPE_STRING
, &old_service_name
,
2498 DBUS_TYPE_STRING
, &new_service_name
,
2499 DBUS_TYPE_INVALID
)) {
2500 HAL_ERROR (("Invalid NameOwnerChanged signal from bus!"));
2504 if (services_with_locks
!= NULL
) {
2505 d
= g_hash_table_lookup (services_with_locks
, new_service_name
);
2508 hal_device_property_remove (d
, "info.locked");
2509 hal_device_property_remove (d
, "info.locked.reason");
2510 hal_device_property_remove (d
, "info.locked.dbus_name");
2512 g_hash_table_remove (services_with_locks
, new_service_name
);
2516 if (services_with_claims
!= NULL
) {
2517 d
= g_hash_table_lookup (services_with_claims
, new_service_name
);
2520 hal_util_branch_claim (hald_get_gdl (), d
, FALSE
, NULL
, 0);
2521 hal_device_property_remove (d
, "info.claimed.dbus_name");
2523 g_hash_table_remove (services_with_claims
, new_service_name
);
2528 static DBusHandlerResult
2529 device_rescan (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2534 DBusMessageIter iter
;
2537 HAL_INFO (("entering, local_interface=%d", local_interface
));
2539 udi
= dbus_message_get_path (message
);
2541 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
2542 raise_permission_denied (connection
, message
, "Rescan: not privileged");
2543 return DBUS_HANDLER_RESULT_HANDLED
;
2546 HAL_DEBUG (("udi=%s", udi
));
2548 device
= hal_device_store_find (hald_get_gdl (), udi
);
2550 device
= hal_device_store_find (hald_get_tdl (), udi
);
2552 if (device
== NULL
) {
2553 raise_no_such_device (connection
, message
, udi
);
2554 return DBUS_HANDLER_RESULT_HANDLED
;
2557 res
= osspec_device_rescan (device
);
2559 reply
= dbus_message_new_method_return (message
);
2561 DIE (("No memory"));
2562 dbus_message_iter_init_append (reply
, &iter
);
2563 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &res
);
2565 if (!dbus_connection_send (connection
, reply
, NULL
))
2566 DIE (("No memory"));
2568 dbus_message_unref (reply
);
2569 return DBUS_HANDLER_RESULT_HANDLED
;
2572 static DBusHandlerResult
2573 device_reprobe (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2577 DBusMessageIter iter
;
2581 HAL_TRACE (("entering"));
2583 udi
= dbus_message_get_path (message
);
2585 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
2586 raise_permission_denied (connection
, message
, "Reprobe: not privileged");
2587 return DBUS_HANDLER_RESULT_HANDLED
;
2590 HAL_DEBUG (("udi=%s", udi
));
2592 device
= hal_device_store_find (hald_get_gdl (), udi
);
2594 device
= hal_device_store_find (hald_get_tdl (), udi
);
2596 if (device
== NULL
) {
2597 raise_no_such_device (connection
, message
, udi
);
2598 return DBUS_HANDLER_RESULT_HANDLED
;
2601 res
= osspec_device_reprobe (device
);
2603 reply
= dbus_message_new_method_return (message
);
2605 DIE (("No memory"));
2606 dbus_message_iter_init_append (reply
, &iter
);
2607 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &res
);
2609 if (!dbus_connection_send (connection
, reply
, NULL
))
2610 DIE (("No memory"));
2612 dbus_message_unref (reply
);
2613 return DBUS_HANDLER_RESULT_HANDLED
;
2617 static DBusHandlerResult
2618 device_emit_condition (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2622 DBusMessageIter iter
;
2625 const char *condition_name
;
2626 const char *condition_details
;
2629 HAL_TRACE (("entering"));
2631 udi
= dbus_message_get_path (message
);
2633 if (!local_interface
) {
2634 raise_permission_denied (connection
, message
, "EmitCondition: only allowed for helpers");
2635 return DBUS_HANDLER_RESULT_HANDLED
;
2638 HAL_DEBUG (("udi=%s", udi
));
2640 dbus_error_init (&error
);
2641 if (!dbus_message_get_args (message
, &error
,
2642 DBUS_TYPE_STRING
, &condition_name
,
2643 DBUS_TYPE_STRING
, &condition_details
,
2644 DBUS_TYPE_INVALID
)) {
2645 raise_syntax (connection
, message
, "EmitCondition");
2646 return DBUS_HANDLER_RESULT_HANDLED
;
2650 device
= hal_device_store_find (hald_get_gdl (), udi
);
2652 device
= hal_device_store_find (hald_get_tdl (), udi
);
2654 if (device
== NULL
) {
2655 raise_no_such_device (connection
, message
, udi
);
2656 return DBUS_HANDLER_RESULT_HANDLED
;
2659 device_send_signal_condition (device
, condition_name
, condition_details
);
2663 reply
= dbus_message_new_method_return (message
);
2665 DIE (("No memory"));
2666 dbus_message_iter_init_append (reply
, &iter
);
2667 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &res
);
2669 if (!dbus_connection_send (connection
, reply
, NULL
))
2670 DIE (("No memory"));
2672 dbus_message_unref (reply
);
2673 return DBUS_HANDLER_RESULT_HANDLED
;
2678 DBusConnection
*connection
;
2679 char *interface_name
;
2680 char *introspection_xml
;
2682 } HelperInterfaceHandler
;
2684 static GSList
*helper_interface_handlers
= NULL
;
2686 static DBusHandlerResult
2687 device_claim_interface (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2691 DBusMessageIter iter
;
2694 const char *interface_name
;
2695 const char *introspection_xml
;
2698 HAL_TRACE (("entering"));
2700 udi
= dbus_message_get_path (message
);
2702 if (!local_interface
) {
2703 raise_permission_denied (connection
, message
, "ClaimInterface: only allowed for helpers");
2704 return DBUS_HANDLER_RESULT_HANDLED
;
2707 HAL_DEBUG (("udi=%s", udi
));
2709 dbus_error_init (&error
);
2710 if (!dbus_message_get_args (message
, &error
,
2711 DBUS_TYPE_STRING
, &interface_name
,
2712 DBUS_TYPE_STRING
, &introspection_xml
,
2713 DBUS_TYPE_INVALID
)) {
2714 raise_syntax (connection
, message
, "ClaimInterface");
2715 return DBUS_HANDLER_RESULT_HANDLED
;
2718 device
= hal_device_store_find (hald_get_gdl (), udi
);
2720 device
= hal_device_store_find (hald_get_tdl (), udi
);
2722 if (device
== NULL
) {
2723 raise_no_such_device (connection
, message
, udi
);
2724 return DBUS_HANDLER_RESULT_HANDLED
;
2729 HAL_INFO (("Local connection 0x%x to handle interface '%s' on udi '%s'",
2734 hal_device_property_strlist_add (device
, "info.interfaces", interface_name
);
2736 HelperInterfaceHandler
*hih
= g_new0 (HelperInterfaceHandler
, 1);
2737 hih
->connection
= connection
;
2738 hih
->interface_name
= g_strdup (interface_name
);
2739 hih
->introspection_xml
= g_strdup (introspection_xml
);
2740 hih
->udi
= g_strdup (udi
);
2741 helper_interface_handlers
= g_slist_append (helper_interface_handlers
, hih
);
2744 reply
= dbus_message_new_method_return (message
);
2746 DIE (("No memory"));
2747 dbus_message_iter_init_append (reply
, &iter
);
2748 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &res
);
2750 if (!dbus_connection_send (connection
, reply
, NULL
))
2751 DIE (("No memory"));
2753 dbus_message_unref (reply
);
2754 return DBUS_HANDLER_RESULT_HANDLED
;
2759 static DBusHandlerResult
2760 addon_is_ready (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2764 DBusMessageIter iter
;
2769 HAL_TRACE (("entering"));
2771 udi
= dbus_message_get_path (message
);
2773 if (!local_interface
) {
2774 raise_permission_denied (connection
, message
, "AddonIsReady: only allowed for helpers");
2775 return DBUS_HANDLER_RESULT_HANDLED
;
2778 HAL_DEBUG (("udi=%s", udi
));
2780 dbus_error_init (&error
);
2781 if (!dbus_message_get_args (message
, &error
,
2782 DBUS_TYPE_INVALID
)) {
2783 raise_syntax (connection
, message
, "AddonIsReady");
2784 return DBUS_HANDLER_RESULT_HANDLED
;
2787 device
= hal_device_store_find (hald_get_gdl (), udi
);
2789 device
= hal_device_store_find (hald_get_tdl (), udi
);
2791 if (device
== NULL
) {
2792 raise_no_such_device (connection
, message
, udi
);
2793 return DBUS_HANDLER_RESULT_HANDLED
;
2796 if (hal_device_inc_num_ready_addons (device
)) {
2797 if (hal_device_are_all_addons_ready (device
)) {
2798 manager_send_signal_device_added (device
);
2804 HAL_INFO (("AddonIsReady on udi '%s'", udi
));
2806 reply
= dbus_message_new_method_return (message
);
2808 DIE (("No memory"));
2809 dbus_message_iter_init_append (reply
, &iter
);
2810 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_BOOLEAN
, &res
);
2812 if (!dbus_connection_send (connection
, reply
, NULL
))
2813 DIE (("No memory"));
2815 dbus_message_unref (reply
);
2816 return DBUS_HANDLER_RESULT_HANDLED
;
2821 * Create new device in tdl. Return temporary udi.
2824 manager_new_device (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2827 DBusMessageIter iter
;
2834 dbus_error_init (&error
);
2836 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
2837 raise_permission_denied (connection
, message
, "NewDevice: not privileged");
2838 return DBUS_HANDLER_RESULT_HANDLED
;
2841 reply
= dbus_message_new_method_return (message
);
2843 DIE (("No memory"));
2845 dbus_message_iter_init_append (reply
, &iter
);
2846 d
= hal_device_new ();
2848 gettimeofday(&tv
, NULL
);
2849 for (i
= 0; i
< 1000000 ; i
++) {
2850 udi
= g_strdup_printf ("/org/freedesktop/Hal/devices/tmp%05x", ((unsigned) tv
.tv_usec
& 0xfffff)) + i
;
2851 if (!hal_device_store_find (hald_get_tdl (), udi
)) break;
2857 raise_error (connection
, message
, "org.freedesktop.Hal.NoSpace", "NewDevice: no space for device");
2858 return DBUS_HANDLER_RESULT_HANDLED
;
2861 hal_device_set_udi (d
, udi
);
2862 hal_device_property_set_string (d
, "info.udi", udi
);
2863 hal_device_store_add (hald_get_tdl (), d
);
2864 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_STRING
, &udi
);
2867 if (!dbus_connection_send (connection
, reply
, NULL
))
2868 DIE (("No memory"));
2870 dbus_message_unref (reply
);
2872 return DBUS_HANDLER_RESULT_HANDLED
;
2880 manager_remove_done (HalDevice
*d
, gpointer userdata1
, gpointer userdata2
)
2882 HAL_INFO (("Remove callouts completed udi=%s", d
->udi
));
2884 if (!hal_device_store_remove (hald_get_gdl (), d
)) {
2885 HAL_WARNING (("Error removing device"));
2891 * Remove device. Looks in gdl and tdl.
2894 manager_remove (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2897 DBusMessageIter iter
;
2903 dbus_error_init (&error
);
2905 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
2906 raise_permission_denied (connection
, message
, "Remove: not privileged");
2907 return DBUS_HANDLER_RESULT_HANDLED
;
2910 if (!dbus_message_get_args (message
, &error
,
2911 DBUS_TYPE_STRING
, &udi
,
2912 DBUS_TYPE_INVALID
)) {
2913 raise_syntax (connection
, message
, "Remove");
2914 return DBUS_HANDLER_RESULT_HANDLED
;
2917 reply
= dbus_message_new_method_return (message
);
2919 DIE (("No memory"));
2921 dbus_message_iter_init_append (reply
, &iter
);
2923 d
= hal_device_store_find (hald_get_gdl (), udi
);
2925 hal_device_store_find (hald_get_tdl (), udi
);
2929 raise_no_such_device (connection
, message
, udi
);
2930 return DBUS_HANDLER_RESULT_HANDLED
;
2934 * run "info.callouts.remove" ?
2936 * (auto) stop "info.addons" ?
2940 hal_util_callout_device_remove (d
, manager_remove_done
, NULL
, NULL
);
2943 hal_device_store_remove (in_tdl
? hald_get_tdl () : hald_get_gdl (), d
);
2946 if (!dbus_connection_send (connection
, reply
, NULL
))
2947 DIE (("No memory"));
2949 dbus_message_unref (reply
);
2951 return DBUS_HANDLER_RESULT_HANDLED
;
2959 manager_commit_done (HalDevice
*d
, gpointer userdata1
, gpointer userdata2
)
2961 HAL_INFO (("Add callouts completed udi=%s", d
->udi
));
2965 * Preprobing helper.
2968 manager_commit_preprobing_done (HalDevice
*d
, gpointer userdata1
, gpointer userdata2
)
2970 if (hal_device_property_get_bool (d
, "info.ignore")) {
2971 /* Leave the device here with info.ignore==TRUE so we won't pick up children
2972 * Also remove category and all capabilities
2974 hal_device_property_remove (d
, "info.category");
2975 hal_device_property_remove (d
, "info.capabilities");
2976 hal_device_property_set_string (d
, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
2977 hal_device_property_set_string (d
, "info.product", "Ignored Device");
2979 HAL_INFO (("Preprobing merged info.ignore==TRUE"));
2984 /* Merge properties from .fdi files */
2985 di_search_and_merge (d
, DEVICE_INFO_TYPE_INFORMATION
);
2986 di_search_and_merge (d
, DEVICE_INFO_TYPE_POLICY
);
2988 hal_util_callout_device_add (d
, manager_commit_done
, NULL
, NULL
);
2993 * Move device from tdl to gdl. Runs helpers and callouts.
2996 manager_commit_to_gdl (DBusConnection
* connection
, DBusMessage
* message
, dbus_bool_t local_interface
)
2999 DBusMessageIter iter
;
3002 char udi
[256], *udi0
, *tmp_udi
;
3004 dbus_error_init (&error
);
3006 if (!local_interface
&& !sender_has_privileges (connection
, message
)) {
3007 raise_permission_denied (connection
, message
, "CommitToGdl: not privileged");
3008 return DBUS_HANDLER_RESULT_HANDLED
;
3011 if (!dbus_message_get_args (message
, &error
,
3012 DBUS_TYPE_STRING
, &tmp_udi
,
3013 DBUS_TYPE_STRING
, &udi0
,
3014 DBUS_TYPE_INVALID
)) {
3015 raise_syntax (connection
, message
, "CommitToGdl");
3016 return DBUS_HANDLER_RESULT_HANDLED
;
3019 reply
= dbus_message_new_method_return (message
);
3021 DIE (("No memory"));
3023 dbus_message_iter_init_append (reply
, &iter
);
3025 /* look it up in tdl */
3027 d
= hal_device_store_find (hald_get_tdl (), tmp_udi
);
3029 raise_no_such_device (connection
, message
, tmp_udi
);
3030 return DBUS_HANDLER_RESULT_HANDLED
;
3033 /* sanity check & avoid races */
3034 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof udi
, "%s", udi0
);
3036 if (hal_device_store_find (hald_get_gdl (), udi
)) {
3038 hal_device_store_remove (hald_get_tdl (), d
);
3040 raise_error (connection
, message
, "org.freedesktop.Hal.DeviceExists", "CommitToGdl: Device exists: %s", udi
);
3041 return DBUS_HANDLER_RESULT_HANDLED
;
3045 hal_device_property_remove (d
, "info.udi");
3046 hal_device_set_udi (d
, udi
);
3047 hal_device_property_set_string (d
, "info.udi", udi
);
3050 * 'RequireEnable' property?
3052 * run "info.callouts.preprobe"?
3053 * remove "info.ignore" devices?
3054 * fdi "information"?
3056 * run "info.callouts.add"?
3058 * (auto) start "info.addons"?
3061 /* Process preprobe fdi files */
3062 di_search_and_merge (d
, DEVICE_INFO_TYPE_PREPROBE
);
3063 hal_util_callout_device_preprobe (d
, manager_commit_preprobing_done
, NULL
, NULL
);
3065 /* move from tdl to gdl */
3066 hal_device_store_remove (hald_get_tdl (), d
);
3067 hal_device_store_add (hald_get_gdl (), d
);
3069 if (!dbus_connection_send (connection
, reply
, NULL
))
3070 DIE (("No memory"));
3072 dbus_message_unref (reply
);
3074 return DBUS_HANDLER_RESULT_HANDLED
;
3084 DBusMessage
*message
;
3085 DBusConnection
*connection
;
3089 hald_exec_method_cb (HalDevice
*d
, guint32 exit_type
,
3090 gint return_code
, gchar
**error
,
3091 gpointer data1
, gpointer data2
);
3095 hald_exec_method_free_mi (MethodInvocation
*mi
)
3097 /* hald_runner_run_method() assumes ownership of mi->message.. so we don't free it here */
3099 g_free (mi
->execpath
);
3100 g_strfreev (mi
->extra_env
);
3101 g_free (mi
->mstdin
);
3102 g_free (mi
->member
);
3103 g_free (mi
->interface
);
3107 /* returns FALSE if we don't actually invoke anything */
3109 hald_exec_method_do_invocation (MethodInvocation
*mi
)
3116 d
= hal_device_store_find (hald_get_gdl (), mi
->udi
);
3118 d
= hal_device_store_find (hald_get_tdl (), mi
->udi
);
3122 hald_runner_run_method(d
,
3128 hald_exec_method_cb
,
3129 (gpointer
) mi
->message
,
3130 (gpointer
) mi
->connection
);
3134 HAL_WARNING (("In-queue method call on non-existant device"));
3136 raise_no_such_device (mi
->connection
, mi
->message
, mi
->udi
);
3143 static GHashTable
*udi_to_method_queue
= NULL
;
3147 device_is_executing_method (HalDevice
*d
, const char *interface_name
, const char *method_name
)
3155 if (g_hash_table_lookup_extended (udi_to_method_queue
, d
->udi
, &origkey
, (gpointer
) &queue
)) {
3157 if (queue
!= NULL
) {
3158 MethodInvocation
*mi
;
3159 mi
= (MethodInvocation
*) queue
->data
;
3160 if ((strcmp (mi
->interface
, interface_name
) == 0) &&
3161 (strcmp (mi
->member
, method_name
) == 0)) {
3172 hald_exec_method_process_queue (const char *udi
);
3175 hald_exec_method_enqueue (MethodInvocation
*mi
)
3180 if (udi_to_method_queue
== NULL
) {
3181 udi_to_method_queue
= g_hash_table_new_full (g_str_hash
,
3187 if (g_hash_table_lookup_extended (udi_to_method_queue
, mi
->udi
, &origkey
, (gpointer
) &queue
)) {
3188 HAL_INFO (("enqueue"));
3189 queue
= g_list_append (queue
, mi
);
3190 g_hash_table_replace (udi_to_method_queue
, g_strdup (mi
->udi
), queue
);
3192 HAL_INFO (("no need to enqueue"));
3193 queue
= g_list_append (NULL
, mi
);
3194 g_hash_table_insert (udi_to_method_queue
, g_strdup (mi
->udi
), queue
);
3196 hald_exec_method_do_invocation (mi
);
3202 hald_exec_method_process_queue (const char *udi
)
3206 MethodInvocation
*mi
;
3208 if (g_hash_table_lookup_extended (udi_to_method_queue
, udi
, &origkey
, (gpointer
) &queue
)) {
3210 /* clean the top of the list */
3211 if (queue
!= NULL
) {
3212 mi
= (MethodInvocation
*) queue
->data
;
3213 queue
= g_list_delete_link (queue
, queue
);
3214 if (queue
== NULL
) {
3215 g_hash_table_remove (udi_to_method_queue
, udi
);
3216 HAL_INFO (("No more methods in queue"));
3219 /* if method was Volume.Unmount() then refresh mount state */
3220 if (strcmp (mi
->interface
, "org.freedesktop.Hal.Device.Volume") == 0 &&
3221 strcmp (mi
->member
, "Unmount") == 0) {
3224 HAL_INFO (("Refreshing mount state for %s since Unmount() completed", mi
->udi
));
3226 d
= hal_device_store_find (hald_get_gdl (), mi
->udi
);
3228 d
= hal_device_store_find (hald_get_tdl (), mi
->udi
);
3232 osspec_refresh_mount_state_for_block_device (d
);
3234 HAL_WARNING ((" Cannot find device object for %s", mi
->udi
));
3238 hald_exec_method_free_mi (mi
);
3241 /* process the rest of the list */
3242 if (queue
!= NULL
) {
3243 HAL_INFO (("Execing next method in queue"));
3244 g_hash_table_replace (udi_to_method_queue
, g_strdup (udi
), queue
);
3246 mi
= (MethodInvocation
*) queue
->data
;
3247 if (!hald_exec_method_do_invocation (mi
)) {
3248 /* the device went away before we got to it... */
3249 hald_exec_method_process_queue (mi
->udi
);
3256 hald_exec_method_cb (HalDevice
*d
, guint32 exit_type
,
3257 gint return_code
, gchar
**error
,
3258 gpointer data1
, gpointer data2
)
3260 dbus_int32_t result
;
3261 DBusMessage
*reply
= NULL
;
3262 DBusMessage
*message
;
3263 DBusMessageIter iter
;
3264 DBusConnection
*conn
;
3265 gchar
*exp_name
= NULL
;
3266 gchar
*exp_detail
= NULL
;
3267 gboolean invalid_name
= FALSE
;
3269 hald_exec_method_process_queue (d
->udi
);
3271 message
= (DBusMessage
*) data1
;
3272 conn
= (DBusConnection
*) data2
;
3274 if (exit_type
== HALD_RUN_SUCCESS
&& error
!= NULL
&&
3275 error
[0] != NULL
&& error
[1] != NULL
) {
3276 exp_name
= error
[0];
3277 if (error
[0] != NULL
) {
3278 exp_detail
= error
[1];
3280 HAL_INFO (("failed with '%s' '%s'", exp_name
, exp_detail
));
3283 if (exit_type
!= HALD_RUN_SUCCESS
) {
3284 reply
= dbus_message_new_error (message
, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
3286 if (!dbus_connection_send (conn
, reply
, NULL
))
3287 DIE (("No memory"));
3289 dbus_message_unref (reply
);
3290 } else if (exp_name
!= NULL
&& exp_detail
!= NULL
) {
3291 if (!is_valid_interface_name (exp_name
)) {
3293 * error name may be invalid,
3294 * if so we need a generic HAL error name;
3295 * otherwise, dbus will be messed up.
3297 invalid_name
= TRUE
;
3298 exp_detail
= g_strconcat (exp_name
, " \n ", exp_detail
, NULL
);
3299 exp_name
= "org.freedesktop.Hal.Device.UnknownError";
3301 reply
= dbus_message_new_error (message
, exp_name
, exp_detail
);
3302 if (reply
== NULL
) {
3303 /* error name may be invalid - assume caller fucked up and use a generic HAL error name */
3304 reply
= dbus_message_new_error (message
, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
3305 if (reply
== NULL
) {
3306 DIE (("No memory"));
3310 if (!dbus_connection_send (conn
, reply
, NULL
))
3311 DIE (("No memory"));
3313 dbus_message_unref (reply
);
3316 result
= (dbus_int32_t
) return_code
;
3318 reply
= dbus_message_new_method_return (message
);
3320 DIE (("No memory"));
3322 dbus_message_iter_init_append (reply
, &iter
);
3323 dbus_message_iter_append_basic (&iter
, DBUS_TYPE_INT32
, &result
);
3326 if (!dbus_connection_send (conn
, reply
, NULL
))
3327 DIE (("No memory"));
3330 dbus_message_unref (reply
);
3334 g_free (exp_detail
);
3335 dbus_message_unref (message
);
3338 static DBusHandlerResult
3339 hald_exec_method (HalDevice
*d
, DBusConnection
*connection
, dbus_bool_t local_interface
,
3340 DBusMessage
*message
, const char *execpath
)
3344 DBusMessageIter iter
;
3346 char uid_export
[128];
3347 char sender_export
[128];
3348 MethodInvocation
*mi
;
3350 /* add calling uid */
3351 extra_env
[0] = NULL
;
3352 extra_env
[1] = NULL
;
3353 if (local_interface
) {
3354 extra_env
[0] = "HAL_METHOD_INVOKED_BY_UID=0";
3355 extra_env
[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
3359 sender
= dbus_message_get_sender (message
);
3360 if (sender
!= NULL
) {
3364 dbus_error_init (&error
);
3365 uid
= dbus_bus_get_unix_user (connection
, sender
, &error
);
3366 if (!dbus_error_is_set (&error
)) {
3367 sprintf (uid_export
, "HAL_METHOD_INVOKED_BY_UID=%lu", uid
);
3368 extra_env
[0] = uid_export
;
3370 snprintf (sender_export
, sizeof (sender_export
),
3371 "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=%s", sender
);
3372 extra_env
[1] = sender_export
;
3376 if (extra_env
[0] == NULL
)
3377 extra_env
[0] = "HAL_METHOD_INVOKED_BY_UID=nobody";
3378 if (extra_env
[1] == NULL
)
3379 extra_env
[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
3382 extra_env
[2] = NULL
;
3384 /* prepare stdin with parameters */
3385 stdin_str
= g_string_sized_new (256); /* default size for passing params; can grow */
3386 dbus_message_iter_init (message
, &iter
);
3387 while ((type
= dbus_message_iter_get_arg_type (&iter
)) != DBUS_TYPE_INVALID
) {
3389 case DBUS_TYPE_BYTE
:
3391 unsigned char value
;
3392 dbus_message_iter_get_basic (&iter
, &value
);
3393 g_string_append_printf (stdin_str
, "%u", value
);
3396 case DBUS_TYPE_INT16
:
3399 dbus_message_iter_get_basic (&iter
, &value
);
3400 g_string_append_printf (stdin_str
, "%d", value
);
3403 case DBUS_TYPE_UINT16
:
3405 dbus_uint16_t value
;
3406 dbus_message_iter_get_basic (&iter
, &value
);
3407 g_string_append_printf (stdin_str
, "%u", value
);
3410 case DBUS_TYPE_INT32
:
3413 dbus_message_iter_get_basic (&iter
, &value
);
3414 g_string_append_printf (stdin_str
, "%d", value
);
3417 case DBUS_TYPE_UINT32
:
3419 dbus_uint32_t value
;
3420 dbus_message_iter_get_basic (&iter
, &value
);
3421 g_string_append_printf (stdin_str
, "%u", value
);
3424 case DBUS_TYPE_INT64
:
3427 dbus_message_iter_get_basic (&iter
, &value
);
3428 g_string_append_printf (stdin_str
, "%lld", (long long int) value
);
3431 case DBUS_TYPE_UINT64
:
3433 dbus_uint64_t value
;
3434 dbus_message_iter_get_basic (&iter
, &value
);
3435 g_string_append_printf (stdin_str
, "%llu", (long long unsigned int) value
);
3438 case DBUS_TYPE_DOUBLE
:
3441 dbus_message_iter_get_basic (&iter
, &value
);
3442 g_string_append_printf (stdin_str
, "%g", value
);
3445 case DBUS_TYPE_BOOLEAN
:
3448 dbus_message_iter_get_basic (&iter
, &value
);
3449 g_string_append (stdin_str
, value
? "true" : "false");
3452 case DBUS_TYPE_STRING
:
3455 dbus_message_iter_get_basic (&iter
, &value
);
3456 g_string_append (stdin_str
, value
);
3460 case DBUS_TYPE_ARRAY
:
3462 DBusMessageIter iter_strlist
;
3463 if (dbus_message_iter_get_element_type (&iter
) != DBUS_TYPE_STRING
)
3466 dbus_message_iter_recurse (&iter
, &iter_strlist
);
3467 while (dbus_message_iter_get_arg_type (&iter_strlist
) == DBUS_TYPE_STRING
) {
3469 dbus_message_iter_get_basic (&iter_strlist
, &value
);
3470 g_string_append (stdin_str
, value
);
3471 g_string_append (stdin_str
, "\t");
3472 dbus_message_iter_next(&iter_strlist
);
3481 g_string_append_c (stdin_str
, '\n');
3482 dbus_message_iter_next (&iter
);
3485 mi
= g_new0 (MethodInvocation
, 1);
3486 mi
->udi
= g_strdup (d
->udi
);
3487 mi
->execpath
= g_strdup (execpath
);
3488 mi
->extra_env
= g_strdupv (extra_env
);
3489 mi
->mstdin
= g_strdup (stdin_str
->str
);
3490 mi
->message
= message
;
3491 mi
->connection
= connection
;
3492 mi
->member
= g_strdup (dbus_message_get_member (message
));
3493 mi
->interface
= g_strdup (dbus_message_get_interface (message
));
3494 hald_exec_method_enqueue (mi
);
3496 dbus_message_ref (message
);
3497 g_string_free (stdin_str
, TRUE
);
3499 return DBUS_HANDLER_RESULT_HANDLED
;
3502 g_string_free (stdin_str
, TRUE
);
3503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
3507 foreach_device_get_xml_node (HalDeviceStore
*store
, HalDevice
*device
,
3510 GString
*xml
= user_data
;
3511 const char *udi
, *name
;
3513 udi
= hal_device_get_udi (device
);
3514 name
= strrchr(udi
, '/')+1;
3516 xml
= g_string_append(xml
, " <node name=\"");
3517 xml
= g_string_append(xml
, name
);
3518 xml
= g_string_append(xml
, "\"/>\n");
3523 static DBusHandlerResult
3524 do_introspect (DBusConnection
*connection
,
3525 DBusMessage
*message
,
3526 dbus_bool_t local_interface
)
3533 HAL_TRACE (("entering do_introspect"));
3535 path
= dbus_message_get_path (message
);
3537 xml
= g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
3538 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
3540 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
3541 " <method name=\"Introspect\">\n"
3542 " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
3546 if (strcmp (path
, "/") == 0) {
3548 xml
= g_string_append (xml
,
3549 " <node name=\"org\"/>\n");
3551 } else if (strcmp (path
, "/org") == 0) {
3553 xml
= g_string_append (xml
,
3554 " <node name=\"freedesktop\"/>\n");
3556 } else if (strcmp (path
, "/org/freedesktop") == 0) {
3558 xml
= g_string_append (xml
,
3559 " <node name=\"Hal\"/>\n");
3561 } else if (strcmp (path
, "/org/freedesktop/Hal") == 0) {
3563 xml
= g_string_append (xml
,
3564 " <node name=\"Manager\"/>\n"
3565 " <node name=\"devices\"/>\n");
3567 } else if (strcmp (path
, "/org/freedesktop/Hal/devices") == 0) {
3569 hal_device_store_foreach (hald_get_gdl (),
3570 foreach_device_get_xml_node
,
3573 } else if (strcmp (path
, "/org/freedesktop/Hal/Manager") == 0) {
3575 xml
= g_string_append (xml
,
3576 " <interface name=\"org.freedesktop.Hal.Manager\">\n"
3577 " <method name=\"GetAllDevices\">\n"
3578 " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
3580 " <method name=\"DeviceExists\">\n"
3581 " <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
3582 " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
3584 " <method name=\"FindDeviceStringMatch\">\n"
3585 " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
3586 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3587 " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
3589 " <method name=\"FindDeviceByCapability\">\n"
3590 " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
3591 " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
3593 " <method name=\"ClaimBranch\">\n"
3594 " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
3595 " <arg name=\"claim_service\" direction=\"in\" type=\"s\"/>\n"
3596 " <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
3598 " <method name=\"UnclaimBranch\">\n"
3599 " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
3600 " <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
3602 " <method name=\"NewDevice\">\n"
3603 " <arg name=\"temporary_udi\" direction=\"out\" type=\"s\"/>\n"
3605 " <method name=\"Remove\">\n"
3606 " <arg name=\"udi\" direction=\"in\" type=\"s\"/>\n"
3608 " <method name=\"CommitToGdl\">\n"
3609 " <arg name=\"temporary_udi\" direction=\"in\" type=\"s\"/>\n"
3610 " <arg name=\"global_udi\" direction=\"in\" type=\"s\"/>\n"
3616 d
= hal_device_store_find (hald_get_gdl (), path
);
3618 d
= hal_device_store_find (hald_get_tdl (), path
);
3621 raise_no_such_device (connection
, message
, path
);
3622 return DBUS_HANDLER_RESULT_HANDLED
;
3625 xml
= g_string_append (xml
,
3626 " <interface name=\"org.freedesktop.Hal.Device\">\n"
3627 " <method name=\"GetAllProperties\">\n"
3628 " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"
3630 " <method name=\"SetMultipleProperties\">\n"
3631 " <arg name=\"properties\" direction=\"in\" type=\"a{sv}\"/>\n"
3633 " <method name=\"GetProperty\">\n"
3634 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3635 " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"
3637 " <method name=\"GetPropertyString\">\n"
3638 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3639 " <arg name=\"value\" direction=\"out\" type=\"s\"/>\n"
3641 " <method name=\"GetPropertyStringList\">\n"
3642 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3643 " <arg name=\"value\" direction=\"out\" type=\"as\"/>\n"
3645 " <method name=\"GetPropertyInteger\">\n"
3646 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3647 " <arg name=\"value\" direction=\"out\" type=\"i\"/>\n"
3649 " <method name=\"GetPropertyBoolean\">\n"
3650 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3651 " <arg name=\"value\" direction=\"out\" type=\"b\"/>\n"
3653 " <method name=\"GetPropertyDouble\">\n"
3654 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3655 " <arg name=\"value\" direction=\"out\" type=\"d\"/>\n"
3657 " <method name=\"SetProperty\">\n"
3658 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3659 " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"
3661 " <method name=\"SetPropertyString\">\n"
3662 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3663 " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
3665 " <method name=\"SetPropertyStringList\">\n"
3666 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3667 " <arg name=\"value\" direction=\"in\" type=\"as\"/>\n"
3669 " <method name=\"SetPropertyInteger\">\n"
3670 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3671 " <arg name=\"value\" direction=\"in\" type=\"i\"/>\n"
3673 " <method name=\"SetPropertyBoolean\">\n"
3674 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3675 " <arg name=\"value\" direction=\"in\" type=\"b\"/>\n"
3677 " <method name=\"SetPropertyDouble\">\n"
3678 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3679 " <arg name=\"value\" direction=\"in\" type=\"d\"/>\n"
3682 " <method name=\"RemoveProperty\">\n"
3683 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3685 " <method name=\"GetPropertyType\">\n"
3686 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3687 " <arg name=\"type\" direction=\"out\" type=\"i\"/>\n"
3689 " <method name=\"PropertyExists\">\n"
3690 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3691 " <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
3693 " <method name=\"AddCapability\">\n"
3694 " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
3696 " <method name=\"QueryCapability\">\n"
3697 " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
3698 " <arg name=\"does_it_have_capability\" direction=\"out\" type=\"b\"/>\n"
3700 " <method name=\"Lock\">\n"
3701 " <arg name=\"reason\" direction=\"in\" type=\"s\"/>\n"
3702 " <arg name=\"acquired_lock\" direction=\"out\" type=\"b\"/>\n"
3704 " <method name=\"Unlock\">\n"
3705 " <arg name=\"released_lock\" direction=\"out\" type=\"b\"/>\n"
3708 " <method name=\"StringListAppend\">\n"
3709 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3710 " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
3712 " <method name=\"StringListPrepend\">\n"
3713 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3714 " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
3716 " <method name=\"StringListRemove\">\n"
3717 " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
3718 " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
3720 " <method name=\"EmitCondition\">\n"
3721 " <arg name=\"condition_name\" direction=\"in\" type=\"s\"/>\n"
3722 " <arg name=\"condition_details\" direction=\"in\" type=\"s\"/>\n"
3723 " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
3726 " <method name=\"Rescan\">\n"
3727 " <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
3729 " <method name=\"Reprobe\">\n"
3730 " <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
3733 " <method name=\"ClaimInterface\">\n"
3734 " <arg name=\"interface_name\" direction=\"in\" type=\"s\"/>\n"
3735 " <arg name=\"introspection_xml\" direction=\"in\" type=\"s\"/>\n"
3736 " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
3739 " <method name=\"AddonIsReady\">\n"
3740 " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
3748 interfaces
= hal_device_property_get_strlist (d
, "info.interfaces");
3749 for (i
= interfaces
; i
!= NULL
; i
= g_slist_next (i
)) {
3750 const char *ifname
= (const char *) i
->data
;
3751 char *method_names_prop
;
3752 char *method_signatures_prop
;
3753 char *method_argnames_prop
;
3754 GSList
*method_names
;
3755 GSList
*method_signatures
;
3756 GSList
*method_argnames
;
3761 g_string_append_printf (xml
, " <interface name=\"%s\">\n", ifname
);
3763 method_names_prop
= g_strdup_printf ("%s.method_names", ifname
);
3764 method_signatures_prop
= g_strdup_printf ("%s.method_signatures", ifname
);
3765 method_argnames_prop
= g_strdup_printf ("%s.method_argnames", ifname
);
3767 method_names
= hal_device_property_get_strlist (d
, method_names_prop
);
3768 method_signatures
= hal_device_property_get_strlist (d
, method_signatures_prop
);
3769 method_argnames
= hal_device_property_get_strlist (d
, method_argnames_prop
);
3771 /* consult local list */
3772 if (method_names
== NULL
) {
3775 for (i
= helper_interface_handlers
; i
!= NULL
; i
= g_slist_next (i
)) {
3776 HelperInterfaceHandler
*hih
= i
->data
;
3777 if (strcmp (hih
->udi
, path
) == 0) {
3778 xml
= g_string_append (xml
, hih
->introspection_xml
);
3784 for (j
= method_names
, k
= method_signatures
, l
= method_argnames
;
3785 j
!= NULL
&& k
!= NULL
&& l
!= NULL
;
3786 j
= g_slist_next (j
), k
= g_slist_next (k
), l
= g_slist_next (l
)) {
3789 const char *argnames
;
3798 args
= g_strsplit (argnames
, " ", 0);
3800 g_string_append_printf (xml
, " <method name=\"%s\">\n", name
);
3802 for (n
= 0, m
= 0; n
< strlen (sig
) && args
[m
] != NULL
; n
++, m
++) {
3805 if (n
== strlen (sig
) - 1) {
3806 HAL_WARNING (("Broken signature for method %s "
3807 "on interface %s for object %s",
3808 name
, ifname
, path
));
3811 g_string_append_printf (
3813 " <arg name=\"%s\" direction=\"in\" type=\"a%c\"/>\n",
3814 args
[m
], sig
[n
+ 1]);
3819 g_string_append_printf (
3821 " <arg name=\"%s\" direction=\"in\" type=\"%c\"/>\n",
3826 xml
= g_string_append (
3828 " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n");
3829 xml
= g_string_append (
3836 xml
= g_string_append (xml
, " </interface>\n");
3838 g_free (method_names_prop
);
3839 g_free (method_signatures_prop
);
3840 g_free (method_argnames_prop
);
3845 reply
= dbus_message_new_method_return (message
);
3847 xml
= g_string_append (xml
, "</node>\n");
3848 xml_string
= g_string_free (xml
, FALSE
);
3850 dbus_message_append_args (reply
,
3851 DBUS_TYPE_STRING
, &xml_string
,
3854 g_free (xml_string
);
3857 DIE (("No memory"));
3859 if (!dbus_connection_send (connection
, reply
, NULL
))
3860 DIE (("No memory"));
3862 dbus_message_unref (reply
);
3863 return DBUS_HANDLER_RESULT_HANDLED
;
3867 reply_from_fwd_message (DBusPendingCall
*pending_call
,
3870 DBusMessage
*reply_from_addon
;
3871 DBusMessage
*method_from_caller
;
3874 /*HAL_INFO (("in reply_from_fwd_message : user_data = 0x%x", user_data));*/
3876 method_from_caller
= (DBusMessage
*) user_data
;
3877 reply_from_addon
= dbus_pending_call_steal_reply (pending_call
);
3879 reply
= dbus_message_copy (reply_from_addon
);
3880 dbus_message_set_destination (reply
, dbus_message_get_sender (method_from_caller
));
3881 dbus_message_set_reply_serial (reply
, dbus_message_get_serial (method_from_caller
));
3883 if (dbus_connection
!= NULL
)
3884 dbus_connection_send (dbus_connection
, reply
, NULL
);
3886 dbus_message_unref (reply_from_addon
);
3887 dbus_message_unref (reply
);
3888 dbus_message_unref (method_from_caller
);
3889 dbus_pending_call_unref (pending_call
);
3892 static DBusHandlerResult
3893 hald_dbus_filter_handle_methods (DBusConnection
*connection
, DBusMessage
*message
,
3894 void *user_data
, dbus_bool_t local_interface
)
3896 /*HAL_INFO (("connection=0x%x obj_path=%s interface=%s method=%s local_interface=%d",
3898 dbus_message_get_path (message),
3899 dbus_message_get_interface (message),
3900 dbus_message_get_member (message),
3901 local_interface));*/
3903 if (dbus_message_is_method_call (message
,
3904 "org.freedesktop.Hal.Manager",
3906 strcmp (dbus_message_get_path (message
),
3907 "/org/freedesktop/Hal/Manager") == 0) {
3908 return manager_get_all_devices (connection
, message
);
3909 } else if (dbus_message_is_method_call (message
,
3910 "org.freedesktop.Hal.Manager",
3912 strcmp (dbus_message_get_path (message
),
3913 "/org/freedesktop/Hal/Manager") == 0) {
3914 return manager_device_exists (connection
, message
);
3915 } else if (dbus_message_is_method_call (message
,
3916 "org.freedesktop.Hal.Manager",
3917 "FindDeviceStringMatch") &&
3918 strcmp (dbus_message_get_path (message
),
3919 "/org/freedesktop/Hal/Manager") == 0) {
3920 return manager_find_device_string_match (connection
,
3922 } else if (dbus_message_is_method_call
3923 (message
, "org.freedesktop.Hal.Manager",
3924 "FindDeviceByCapability")
3925 && strcmp (dbus_message_get_path (message
),
3926 "/org/freedesktop/Hal/Manager") == 0) {
3927 return manager_find_device_by_capability (connection
,
3929 } else if (dbus_message_is_method_call (message
,
3930 "org.freedesktop.Hal.Manager",
3932 strcmp (dbus_message_get_path (message
),
3933 "/org/freedesktop/Hal/Manager") == 0) {
3934 return manager_claim_branch (connection
, message
);
3935 } else if (dbus_message_is_method_call (message
,
3936 "org.freedesktop.Hal.Manager",
3938 strcmp (dbus_message_get_path (message
),
3939 "/org/freedesktop/Hal/Manager") == 0) {
3940 return manager_unclaim_branch (connection
, message
);
3941 } else if (dbus_message_is_method_call (message
,
3942 "org.freedesktop.Hal.Manager",
3944 strcmp (dbus_message_get_path (message
),
3945 "/org/freedesktop/Hal/Manager") == 0) {
3946 return manager_new_device (connection
, message
, local_interface
);
3947 } else if (dbus_message_is_method_call (message
,
3948 "org.freedesktop.Hal.Manager",
3950 strcmp (dbus_message_get_path (message
),
3951 "/org/freedesktop/Hal/Manager") == 0) {
3952 return manager_remove (connection
, message
, local_interface
);
3953 } else if (dbus_message_is_method_call (message
,
3954 "org.freedesktop.Hal.Manager",
3956 strcmp (dbus_message_get_path (message
),
3957 "/org/freedesktop/Hal/Manager") == 0) {
3958 return manager_commit_to_gdl (connection
, message
, local_interface
);
3959 } else if (dbus_message_is_method_call (message
,
3960 "org.freedesktop.Hal.Device",
3961 "GetAllProperties")) {
3962 return device_get_all_properties (connection
, message
);
3963 } else if (dbus_message_is_method_call (message
,
3964 "org.freedesktop.Hal.Device",
3965 "SetMultipleProperties")) {
3966 return device_set_multiple_properties (connection
, message
, local_interface
);
3967 } else if (dbus_message_is_method_call (message
,
3968 "org.freedesktop.Hal.Device",
3970 return device_get_property (connection
, message
);
3971 } else if (dbus_message_is_method_call (message
,
3972 "org.freedesktop.Hal.Device",
3973 "GetPropertyString")) {
3974 return device_get_property (connection
, message
);
3975 } else if (dbus_message_is_method_call (message
,
3976 "org.freedesktop.Hal.Device",
3977 "GetPropertyStringList")) {
3978 return device_get_property (connection
, message
);
3979 } else if (dbus_message_is_method_call (message
,
3980 "org.freedesktop.Hal.Device",
3981 "GetPropertyInteger")) {
3982 return device_get_property (connection
, message
);
3983 } else if (dbus_message_is_method_call (message
,
3984 "org.freedesktop.Hal.Device",
3985 "GetPropertyBoolean")) {
3986 return device_get_property (connection
, message
);
3987 } else if (dbus_message_is_method_call (message
,
3988 "org.freedesktop.Hal.Device",
3989 "GetPropertyDouble")) {
3990 return device_get_property (connection
, message
);
3991 } else if (dbus_message_is_method_call (message
,
3992 "org.freedesktop.Hal.Device",
3994 return device_set_property (connection
, message
, local_interface
);
3995 } else if (dbus_message_is_method_call (message
,
3996 "org.freedesktop.Hal.Device",
3997 "SetPropertyString")) {
3998 return device_set_property (connection
, message
, local_interface
);
3999 } else if (dbus_message_is_method_call (message
,
4000 "org.freedesktop.Hal.Device",
4001 "SetPropertyInteger")) {
4002 return device_set_property (connection
, message
, local_interface
);
4003 } else if (dbus_message_is_method_call (message
,
4004 "org.freedesktop.Hal.Device",
4005 "SetPropertyBoolean")) {
4006 return device_set_property (connection
, message
, local_interface
);
4007 } else if (dbus_message_is_method_call (message
,
4008 "org.freedesktop.Hal.Device",
4009 "SetPropertyDouble")) {
4010 return device_set_property (connection
, message
, local_interface
);
4011 } else if (dbus_message_is_method_call (message
,
4012 "org.freedesktop.Hal.Device",
4013 "RemoveProperty")) {
4014 return device_remove_property (connection
, message
, local_interface
);
4015 } else if (dbus_message_is_method_call (message
,
4016 "org.freedesktop.Hal.Device",
4017 "GetPropertyType")) {
4018 return device_get_property_type (connection
, message
);
4019 } else if (dbus_message_is_method_call (message
,
4020 "org.freedesktop.Hal.Device",
4021 "PropertyExists")) {
4022 return device_property_exists (connection
, message
);
4023 } else if (dbus_message_is_method_call (message
,
4024 "org.freedesktop.Hal.Device",
4026 return device_add_capability (connection
, message
, local_interface
);
4027 } else if (dbus_message_is_method_call (message
,
4028 "org.freedesktop.Hal.Device",
4029 "QueryCapability")) {
4030 return device_query_capability (connection
, message
);
4031 } else if (dbus_message_is_method_call (message
,
4032 "org.freedesktop.Hal.Device",
4034 return device_lock (connection
, message
);
4035 } else if (dbus_message_is_method_call (message
,
4036 "org.freedesktop.Hal.Device",
4038 return device_unlock (connection
, message
);
4039 } else if (dbus_message_is_method_call (message
,
4040 "org.freedesktop.Hal.Device",
4041 "StringListAppend")) {
4042 return device_string_list_append_prepend (connection
, message
, FALSE
);
4043 } else if (dbus_message_is_method_call (message
,
4044 "org.freedesktop.Hal.Device",
4045 "StringListPrepend")) {
4046 return device_string_list_append_prepend (connection
, message
, TRUE
);
4047 } else if (dbus_message_is_method_call (message
,
4048 "org.freedesktop.Hal.Device",
4049 "StringListRemove")) {
4050 return device_string_list_remove (connection
, message
);
4051 } else if (dbus_message_is_method_call (message
,
4052 "org.freedesktop.Hal.Device",
4054 return device_rescan (connection
, message
, local_interface
);
4055 } else if (dbus_message_is_method_call (message
,
4056 "org.freedesktop.Hal.Device",
4058 return device_reprobe (connection
, message
, local_interface
);
4059 } else if (dbus_message_is_method_call (message
,
4060 "org.freedesktop.Hal.Device",
4062 return device_emit_condition (connection
, message
, local_interface
);
4063 } else if (dbus_message_is_method_call (message
,
4064 "org.freedesktop.Hal.Device",
4065 "ClaimInterface")) {
4066 return device_claim_interface (connection
, message
, local_interface
);
4068 } else if (dbus_message_is_method_call (message
,
4069 "org.freedesktop.Hal.Device",
4070 "ReleaseInterface")) {
4071 return device_release_interface (connection
, message
, local_interface
);
4073 } else if (dbus_message_is_method_call (message
,
4074 "org.freedesktop.Hal.Device",
4076 return addon_is_ready (connection
, message
, local_interface
);
4077 } else if (dbus_message_is_method_call (message
,
4078 "org.freedesktop.DBus.Introspectable",
4080 return do_introspect (connection
, message
, local_interface
);
4082 const char *interface
;
4085 const char *signature
;
4088 /* check for device-specific interfaces that individual objects may support */
4090 udi
= dbus_message_get_path (message
);
4091 interface
= dbus_message_get_interface (message
);
4092 method
= dbus_message_get_member (message
);
4093 signature
= dbus_message_get_signature (message
);
4098 d
= hal_device_store_find (hald_get_gdl (), udi
);
4100 d
= hal_device_store_find (hald_get_tdl (), udi
);
4103 if (d
!= NULL
&& interface
!= NULL
) {
4106 for (i
= helper_interface_handlers
; i
!= NULL
; i
= g_slist_next (i
)) {
4107 HelperInterfaceHandler
*hih
= i
->data
;
4108 if (strcmp (hih
->udi
, udi
) == 0 &&
4109 strcmp (hih
->interface_name
, interface
) == 0) {
4110 DBusPendingCall
*pending_call
;
4113 /*HAL_INFO (("forwarding method to connection 0x%x", hih->connection));*/
4115 dbus_message_ref (message
);
4117 /* send a copy of the message */
4118 copy
= dbus_message_copy (message
);
4119 if (!dbus_connection_send_with_reply (hih
->connection
,
4123 /* TODO: handle error */
4125 /*HAL_INFO (("connection=%x message=%x", connection, message));*/
4126 dbus_pending_call_set_notify (pending_call
,
4127 reply_from_fwd_message
,
4132 dbus_message_unref (copy
);
4134 return DBUS_HANDLER_RESULT_HANDLED
;
4139 if (d
!= NULL
&& interface
!= NULL
&& method
!= NULL
&& signature
!= NULL
) {
4143 interfaces
= hal_device_property_get_strlist (d
, "info.interfaces");
4144 for (i
= interfaces
; i
!= NULL
; i
= g_slist_next (i
)) {
4145 const char *ifname
= (const char *) i
->data
;
4147 if (strcmp (ifname
, interface
) == 0) {
4149 GSList
*method_names
;
4152 s
= g_strdup_printf ("%s.method_names", interface
);
4153 method_names
= hal_device_property_get_strlist (d
, s
);
4155 for (i
= method_names
, num
= 0; i
!= NULL
; i
= g_slist_next (i
), num
++) {
4156 const char *methodname
= (const char *) i
->data
;
4157 if (strcmp (methodname
, method
) == 0) {
4158 const char *execpath
;
4161 s
= g_strdup_printf ("%s.method_execpaths", interface
);
4162 execpath
= hal_device_property_get_strlist_elem (d
, s
, num
);
4164 s
= g_strdup_printf ("%s.method_signatures", interface
);
4165 sig
= hal_device_property_get_strlist_elem (d
, s
, num
);
4168 if (execpath
!= NULL
&& sig
!= NULL
&&
4169 strcmp (sig
, signature
) == 0) {
4171 HAL_INFO (("OK for method '%s' with signature '%s' on interface '%s' for UDI '%s' and execpath '%s'", method
, signature
, interface
, udi
, execpath
));
4173 return hald_exec_method (d
, connection
, local_interface
,
4185 return osspec_filter_function (connection
, message
, user_data
);
4189 /** Message handler for method invocations. All invocations on any object
4190 * or interface is routed through this function.
4192 * @param connection D-BUS connection
4193 * @param message Message
4194 * @param user_data User data
4195 * @return What to do with the message
4198 hald_dbus_filter_function (DBusConnection
* connection
,
4199 DBusMessage
* message
, void *user_data
)
4201 if (dbus_message_is_signal (message
, DBUS_INTERFACE_LOCAL
, "Disconnected") &&
4202 strcmp (dbus_message_get_path (message
), DBUS_PATH_LOCAL
) == 0) {
4204 /* this is a local message; e.g. from libdbus in this process */
4206 HAL_INFO (("Got disconnected from the system message bus; "
4207 "retrying to reconnect every 3000 ms"));
4208 dbus_connection_unref (dbus_connection
);
4209 dbus_connection
= NULL
;
4211 g_timeout_add (3000, reinit_dbus
, NULL
);
4213 } else if (dbus_message_is_signal (message
,
4214 DBUS_INTERFACE_DBUS
,
4215 "NameOwnerChanged")) {
4217 if (services_with_locks
!= NULL
|| services_with_claims
!= NULL
)
4218 service_deleted (message
);
4220 return hald_dbus_filter_handle_methods (connection
, message
, user_data
, FALSE
);
4222 return DBUS_HANDLER_RESULT_HANDLED
;
4227 static DBusHandlerResult
4228 local_server_message_handler (DBusConnection
*connection
,
4229 DBusMessage
*message
,
4232 /*HAL_INFO (("local_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
4233 dbus_message_get_destination (message),
4234 dbus_message_get_path (message),
4235 dbus_message_get_interface (message),
4236 dbus_message_get_member (message)));*/
4238 if (dbus_message_is_method_call (message
, "org.freedesktop.DBus", "AddMatch")) {
4241 /* cheat, and handle AddMatch since libhal will try to invoke this method */
4242 reply
= dbus_message_new_method_return (message
);
4244 DIE (("No memory"));
4245 if (!dbus_connection_send (connection
, reply
, NULL
))
4246 DIE (("No memory"));
4247 dbus_message_unref (reply
);
4248 return DBUS_HANDLER_RESULT_HANDLED
;
4249 } else if (dbus_message_is_signal (message
, DBUS_INTERFACE_LOCAL
, "Disconnected") &&
4250 strcmp (dbus_message_get_path (message
), DBUS_PATH_LOCAL
) == 0) {
4254 HAL_INFO (("Client to local_server was disconnected"));
4256 for (i
= helper_interface_handlers
; i
!= NULL
; i
= j
) {
4257 HelperInterfaceHandler
*hih
= i
->data
;
4259 j
= g_slist_next (i
);
4261 if (hih
->connection
== connection
) {
4262 g_free (hih
->interface_name
);
4263 g_free (hih
->introspection_xml
);
4266 helper_interface_handlers
= g_slist_remove_link (helper_interface_handlers
, i
);
4270 dbus_connection_unref (connection
);
4271 return DBUS_HANDLER_RESULT_HANDLED
;
4272 } else if (dbus_message_get_type (message
) == DBUS_MESSAGE_TYPE_SIGNAL
) {
4275 /* it's a signal, just forward it onto the system message bus */
4276 copy
= dbus_message_copy (message
);
4277 if (dbus_connection
!= NULL
) {
4278 dbus_connection_send (dbus_connection
, copy
, NULL
);
4280 dbus_message_unref (copy
);
4282 return hald_dbus_filter_handle_methods (connection
, message
, user_data
, TRUE
);
4285 return DBUS_HANDLER_RESULT_HANDLED
;
4289 local_server_unregister_handler (DBusConnection
*connection
, void *user_data
)
4291 HAL_INFO (("unregistered"));
4295 local_server_handle_connection (DBusServer
*server
,
4296 DBusConnection
*new_connection
,
4299 DBusObjectPathVTable vtable
= { &local_server_unregister_handler
,
4300 &local_server_message_handler
,
4301 NULL
, NULL
, NULL
, NULL
};
4303 HAL_INFO (("%d: Got a connection", getpid ()));
4304 HAL_INFO (("dbus_connection_get_is_connected = %d", dbus_connection_get_is_connected (new_connection
)));
4306 /*dbus_connection_add_filter (new_connection, server_filter_function, NULL, NULL);*/
4308 dbus_connection_register_fallback (new_connection
,
4312 dbus_connection_ref (new_connection
);
4313 dbus_connection_setup_with_g_main (new_connection
, NULL
);
4317 static DBusServer
*local_server
= NULL
;
4320 hald_dbus_local_server_addr (void)
4322 if (local_server
== NULL
)
4325 return dbus_server_get_address (local_server
);
4329 hald_dbus_local_server_init (void)
4337 /* setup a server listening on a socket so we can do point to point
4338 * connections for programs spawned by hald
4340 dbus_error_init (&error
);
4341 if ((local_server
= dbus_server_listen (HALD_DBUS_ADDRESS
, &error
)) == NULL
) {
4342 HAL_ERROR (("Cannot create D-BUS server"));
4345 server_addr
= dbus_server_get_address (local_server
);
4346 HAL_INFO (("local server is listening at %s", server_addr
));
4347 dbus_free (server_addr
);
4348 dbus_server_setup_with_g_main (local_server
, NULL
);
4349 dbus_server_set_new_connection_function (local_server
, local_server_handle_connection
, NULL
, NULL
);
4358 hald_dbus_init (void)
4360 DBusError dbus_error
;
4362 HAL_INFO (("entering"));
4364 dbus_connection_set_change_sigpipe (TRUE
);
4366 dbus_error_init (&dbus_error
);
4367 dbus_connection
= dbus_bus_get (DBUS_BUS_SYSTEM
, &dbus_error
);
4368 if (dbus_connection
== NULL
) {
4369 HAL_ERROR (("dbus_bus_get(): %s", dbus_error
.message
));
4373 dbus_connection_setup_with_g_main (dbus_connection
, NULL
);
4374 dbus_connection_set_exit_on_disconnect (dbus_connection
, FALSE
);
4376 dbus_bus_request_name (dbus_connection
, "org.freedesktop.Hal",
4378 if (dbus_error_is_set (&dbus_error
)) {
4379 HAL_ERROR (("dbus_bus_request_name(): %s",
4380 dbus_error
.message
));
4384 dbus_connection_add_filter (dbus_connection
, hald_dbus_filter_function
, NULL
, NULL
);
4386 dbus_bus_add_match (dbus_connection
,
4388 ",interface='"DBUS_INTERFACE_DBUS
"'"
4389 ",sender='"DBUS_SERVICE_DBUS
"'"
4390 ",member='NameOwnerChanged'",