summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog31
-rw-r--r--agents/linux26/sysfs/hal_monitor.c121
-rw-r--r--agents/linux26/sysfs/main.c65
-rw-r--r--agents/linux26/sysfs/main.h4
-rwxr-xr-xexamples/volumed/volumed.py99
-rw-r--r--hald/main.c73
-rw-r--r--libhal/libhal.c8
7 files changed, 353 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index e5886b73..b295ff5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2003-12-08 David Zeuthen <david@fubar.dk>
+
+ * agents/linux26/sysfs/hal_monitor.c:
+ (etc_mtab_process_all_block_devices): s/volume./block./
+ (udev_filter_func): new function for filtering D-BUS messages from udev
+ (setup_udev_listener): setup filter for udev messages
+ (hal_monitor_enter): Listen to D-BUS messages
+
+ * agents/linux26/sysfs/main.c:
+ (hal_sysfs_probe): Use global sysfs path
+ (device_hotplug_add): Use global sysfs path
+ (device_hotplug_remove): Use global sysfs path
+ (drivers_collect): Use global sysfs path
+ (mainloop_integration): Save D-BUS connection object for later use
+ (main): Get sysfs mount path once and for all
+
+ * agents/linux26/sysfs/main.h: Add dbus_connection and sysfs_mount_path
+ as extern variables
+
+ * hald/main.c:
+ (device_query_capability): new function
+ (filter_function): add check for Device.QueryCapability
+
+ * libhal/libhal.c: Minor formatting stuff
+
+ * examples/volumed/volumed.py: Crude example of volume manager now
+ that we got udev integration in place. It doesn't really mount anything
+ but prints out when it should mount. You'll need a very recent udev
+ from BitKeeper with D-BUS enabled (got the patch accepted today)
+
+
2003-12-06 David Zeuthen <david@fubar.dk>
* tools/device-manager/hal-device-manager.glade: Forgot to add file
diff --git a/agents/linux26/sysfs/hal_monitor.c b/agents/linux26/sysfs/hal_monitor.c
index 246c9f91..966ef110 100644
--- a/agents/linux26/sysfs/hal_monitor.c
+++ b/agents/linux26/sysfs/hal_monitor.c
@@ -304,13 +304,13 @@ void etc_mtab_process_all_block_devices(dbus_bool_t setup_watcher)
*/
/* Yay! Found a mount point; set properties accordingly */
- hal_device_set_property_string(udi, "volume.device",
+ hal_device_set_property_string(udi, "block.device",
mp->device);
- hal_device_set_property_string(udi, "volume.mountPoint",
+ hal_device_set_property_string(udi, "block.mountPoint",
mp->mount_point);
- hal_device_set_property_string(udi, "volume.fileSystem",
+ hal_device_set_property_string(udi, "block.fileSystem",
mp->fs_type);
- hal_device_set_property_bool(udi, "volume.isMounted", TRUE);
+ hal_device_set_property_bool(udi, "block.isMounted", TRUE);
found_mount_point = TRUE;
}
@@ -319,10 +319,9 @@ void etc_mtab_process_all_block_devices(dbus_bool_t setup_watcher)
/* No mount point found; (possibly) remove all information */
if( !found_mount_point )
{
- hal_device_set_property_bool(udi, "volume.isMounted", FALSE);
- hal_device_remove_property(udi, "volume.mountPoint");
- hal_device_remove_property(udi, "volume.fileSystem");
- hal_device_remove_property(udi, "volume.device");
+ hal_device_set_property_bool(udi, "block.isMounted", FALSE);
+ hal_device_remove_property(udi, "block.mountPoint");
+ hal_device_remove_property(udi, "block.fileSystem");
}
}
@@ -625,12 +624,113 @@ static void device_removed(const char* udi)
ethmon_remove(udi);
}
+
+static DBusHandlerResult udev_filter_func(DBusConnection* connection,
+ DBusMessage* message,
+ void* user_data)
+{
+ char* filename;
+ char* sysfs_path;
+ char sysfs_dev_path[SYSFS_PATH_MAX];
+ char* udi;
+ const char* object_path;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ object_path = dbus_message_get_path(message);
+
+ /*printf("*** in udev_filter_func, object_path=%s\n", object_path);*/
+
+ if( dbus_message_is_signal(message, "org.kernel.udev.NodeMonitor",
+ "NodeCreated") )
+ {
+ if( dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &filename,
+ DBUS_TYPE_STRING, &sysfs_path,
+ DBUS_TYPE_INVALID) )
+ {
+ strncpy(sysfs_dev_path, sysfs_mount_path, SYSFS_PATH_MAX);
+ strncat(sysfs_dev_path, sysfs_path, SYSFS_PATH_MAX);
+ printf("NodeCreated: %s %s\n", filename, sysfs_dev_path);
+
+ udi = find_udi_from_sysfs_path(sysfs_dev_path,
+ HAL_LINUX_HOTPLUG_TIMEOUT);
+ if( udi!=NULL )
+ {
+ hal_device_set_property_string(udi, "block.device", filename);
+ }
+ }
+ }
+ else if( dbus_message_is_signal(message, "org.kernel.udev.NodeMonitor",
+ "NodeDeleted") )
+ {
+ if( dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &filename,
+ DBUS_TYPE_STRING, &sysfs_path,
+ DBUS_TYPE_INVALID) )
+ {
+ /* This is left intentionally blank since this means that a
+ * block device is removed and we'll catch that other places..
+
+ strncpy(sysfs_dev_path, sysfs_mount_path, SYSFS_PATH_MAX);
+ strncat(sysfs_dev_path, sysfs_path, SYSFS_PATH_MAX);
+ printf("NodeDeleted: %s %s\n", filename, sysfs_dev_path);
+
+ udi = find_udi_from_sysfs_path(sysfs_dev_path,
+ HAL_LINUX_HOTPLUG_TIMEOUT);
+ if( udi!=NULL )
+ {
+ hal_device_remove_property(udi, "block.device");
+ }
+ */
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static void setup_udev_listener()
+{
+ DBusError error;
+ DBusConnection* connection;
+
+ /* Add filter for listening to udev */
+ if( !dbus_connection_add_filter(dbus_connection,
+ udev_filter_func, NULL, NULL) )
+ {
+ fprintf(stderr, "%s %d : Error creating connection handler\r\n",
+ __FILE__, __LINE__);
+ // TODO: clean up
+ return 1;
+ }
+
+ dbus_error_init(&error);
+ dbus_bus_add_match(dbus_connection,
+ "type='signal',"
+ "interface='org.kernel.udev.NodeMonitor',"
+ /*"sender='org.kernel.udev',"*/
+ "path='/org/kernel/udev/NodeMonitor'", &error);
+
+ if( dbus_error_is_set(&error) )
+ {
+ fprintf(stderr, "%s %d : Error subscribing to signals, "
+ "error=%s\r\n",
+ __FILE__, __LINE__, error.message);
+ // TODO: clean up
+ return 1;
+ }
+}
+
/** Enter monitor mode
*
* @param loop G-Lib mainloop
*/
void hal_monitor_enter(GMainLoop* loop)
{
+ DBusError error;
+
syslog(LOG_INFO, "Entering monitor mode..");
/* Find possible mount point for block devices and setup
@@ -646,5 +746,10 @@ void hal_monitor_enter(GMainLoop* loop)
hal_functions.device_removed = device_removed;
hal_functions.device_new_capability = device_new_capability;
+ /* Setup listener for udev signals */
+ setup_udev_listener();
+
+
+
g_main_loop_run(loop);
}
diff --git a/agents/linux26/sysfs/main.c b/agents/linux26/sysfs/main.c
index 30f9f90d..52eb2092 100644
--- a/agents/linux26/sysfs/main.c
+++ b/agents/linux26/sysfs/main.c
@@ -431,10 +431,10 @@ tryagain:
return computed_udi;
}
-/** Given a sysfs-path for a device, this functions finds the HAL device
- * representing the parent of the given device by truncating the sysfs
- * path. There may not be a parent device, in which case this function
- * returns #NULL.
+/** Given a sysfs-path for a device, this functions finds the HAL
+ * device representing the the given device by looking at the sysfs
+ * path. There may not be a such a device, in which case this
+ * function returns #NULL.
*
* Optionally, the caller may specify for many how seconds to try. This is
* useful for hotplug situations where the many hotplug events for a
@@ -840,19 +840,13 @@ static void hal_sysfs_probe()
{
int rc;
char path[SYSFS_PATH_MAX];
- char sysfs_path[SYSFS_PATH_MAX];
struct sysfs_directory* current;
struct sysfs_directory* dir;
is_probing = TRUE;
- /* get mount path */
- rc = sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX);
- if( rc!=0 )
- DIE(("Couldn't get mount path for sysfs"));
-
/* traverse /sys/devices */
- snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, SYSFS_DEVICES_DIR);
+ snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_mount_path, SYSFS_DEVICES_DIR);
dir = sysfs_open_directory(path);
if( dir==NULL )
{
@@ -898,7 +892,6 @@ static void device_hotplug_add(char* bus)
int rc;
const char* devpath;
char path[SYSFS_PATH_MAX];
- char sysfs_path[SYSFS_PATH_MAX];
if( strcmp(bus, "input")==0 )
{
@@ -912,12 +905,7 @@ static void device_hotplug_add(char* bus)
if( devpath==NULL )
return;
- /* get mount path for sysfs */
- rc = sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX);
- if( rc!=0 )
- DIE(("Couldn't get mount path for sysfs"));
-
- snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, devpath);
+ snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_mount_path, devpath);
if( strcmp(bus, "usb")==0 )
{
@@ -966,7 +954,6 @@ static void device_hotplug_remove(char* bus)
const char* devpath;
const char* device_udi = NULL;
char path[SYSFS_PATH_MAX];
- char sysfs_path[SYSFS_PATH_MAX];
char** device_udis;
int num_device_udis;
@@ -983,14 +970,7 @@ static void device_hotplug_remove(char* bus)
if( devpath==NULL )
return;
- /* get mount path for sysfs */
- rc = sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX);
- if( rc!=0 )
- {
- DIE(("Couldn't get mount path for sysfs"));
- }
-
- snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, devpath);
+ snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_mount_path, devpath);
if( strcmp(bus, "usb")==0 )
{
@@ -1117,21 +1097,13 @@ void drivers_collect(const char* bus_name)
{
int rc;
char path[SYSFS_PATH_MAX];
- char sysfs_path[SYSFS_PATH_MAX];
struct sysfs_directory* current;
struct sysfs_link* current2;
struct sysfs_directory* dir;
struct sysfs_directory* dir2;
- /* get mount path for sysfs */
- rc = sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX);
- if( rc!=0 )
- {
- DIE(("Couldn't get mount path for sysfs"));
- }
-
/* traverse /sys/bus/<bus>/drivers */
- snprintf(path, SYSFS_PATH_MAX, "%s/bus/%s/drivers", sysfs_path, bus_name);
+ snprintf(path, SYSFS_PATH_MAX, "%s/bus/%s/drivers", sysfs_mount_path, bus_name);
dir = sysfs_open_directory(path);
if( dir==NULL )
DIE(("Error opening sysfs directory at %s\n", path));
@@ -1165,13 +1137,20 @@ void drivers_collect(const char* bus_name)
}
+/** D-BUS connection object for out connection */
+DBusConnection* dbus_connection;
+
+/** Mount path for sysfs */
+char sysfs_mount_path[SYSFS_PATH_MAX];
+
/** D-BUS mainloop integration for libhal.
*
- * @param dbus_connection D-BUS connection to integrate
+ * @param connection D-BUS connection to integrate
*/
-static void mainloop_integration(DBusConnection* dbus_connection)
+static void mainloop_integration(DBusConnection* connection)
{
- dbus_connection_setup_with_g_main(dbus_connection, NULL);
+ dbus_connection = connection;
+ dbus_connection_setup_with_g_main(connection, NULL);
}
/** Usage */
@@ -1211,12 +1190,20 @@ LibHalFunctions hal_functions = {mainloop_integration,
*/
int main(int argc, char* argv[])
{
+ int rc;
GMainLoop* loop;
fprintf(stderr, "hal-sysfs-agent " PACKAGE_VERSION "\r\n");
loop = g_main_loop_new(NULL, FALSE);
+ /* get mount path for sysfs */
+ rc = sysfs_get_mnt_path(sysfs_mount_path, SYSFS_PATH_MAX);
+ if( rc!=0 )
+ {
+ DIE(("Couldn't get mount path for sysfs"));
+ }
+
if( hal_initialize(&hal_functions) )
{
fprintf(stderr, "error: hal_initialize failed\r\n");
diff --git a/agents/linux26/sysfs/main.h b/agents/linux26/sysfs/main.h
index bbb37ad7..957dc7a8 100644
--- a/agents/linux26/sysfs/main.h
+++ b/agents/linux26/sysfs/main.h
@@ -104,6 +104,10 @@ void drivers_collect(const char* bus_name);
extern LibHalFunctions hal_functions;
+extern DBusConnection* dbus_connection;
+
+extern char sysfs_mount_path[SYSFS_PATH_MAX];
+
/* @} */
#endif /* MAIN_H */
diff --git a/examples/volumed/volumed.py b/examples/volumed/volumed.py
new file mode 100755
index 00000000..5ace4793
--- /dev/null
+++ b/examples/volumed/volumed.py
@@ -0,0 +1,99 @@
+#!/usr/bin/python
+
+import dbus
+import gtk
+import time
+
+# This is just a very very crude example of what a volume daemon could
+# look like... It actually doesn't mount anything; it only prints out
+# messages when it should mount/unmount stuff.
+#
+# A volume daemon should also support optical and floppy disks, it should
+# handle multi-session cdroms and much more. Maybe someone will write
+# this one day...
+#
+
+def get_mount_point(udi, device_name):
+ """Given a the UDI for a device and the name of the device file,
+ determine a name for the mount point"""
+ return '/mnt/somewhere/unique%f'%(time.time())
+
+def attempt_mount(udi):
+ """See if a block device has enough information so we can mount it"""
+ dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
+ if (not mount_dict.has_key(udi)) and dobj.PropertyExists('block.device'):
+ device = dobj.GetProperty('block.device')
+ mount_point = get_mount_point(udi, device)
+ print "mounting device=%s at %s udi=%s"%(device, mount_point, udi)
+ mount_dict[udi] = mount_point
+
+def unmount(udi):
+ """Unmount a device"""
+ mount_point = mount_dict[udi]
+ print "unmounting %s"%mount_point
+ del mount_dict[udi]
+
+def device_changed(dbus_if, member, svc, obj_path, message):
+ """Called when properties on a HAL device changes"""
+ print member
+ udi = obj_path
+ if udi in vol_list:
+ attempt_mount(udi)
+
+def gdl_changed(dbus_if, member, svc, obj_path, message):
+ """Called when a HAL device is added, removed or it got a
+ new capability"""
+ print member
+ if member=='NewCapability':
+ [udi, cap] = message.get_args_list()
+ if cap=='volume':
+ if not udi in vol_list:
+ vol_list.append(udi)
+ bus.add_signal_receiver(device_changed,
+ 'org.freedesktop.Hal.Device',
+ 'org.freedesktop.Hal',
+ udi)
+ attempt_mount(udi)
+
+ print " %s %s"%(cap,udi)
+
+ elif member=='DeviceRemoved':
+ [udi] = message.get_args_list()
+ if udi in vol_list:
+ vol_list.remove(udi)
+ bus.remove_signal_receiver(device_changed,
+ 'org.freedesktop.Hal.Device',
+ 'org.freedesktop.Hal',
+ udi)
+ unmount(udi)
+
+ elif member=='DeviceAdded':
+ [udi] = message.get_args_list()
+ dobj = hal_service.get_object(udi, 'org.freedesktop.Hal.Device')
+ if dobj.QueryCapability('volume'):
+ vol_list.append(udi)
+ bus.add_signal_receiver(device_changed,
+ 'org.freedesktop.Hal.Device',
+ 'org.freedesktop.Hal',
+ udi)
+ attempt_mount(udi)
+
+def main():
+ """Entry point"""
+ global bus, hal_service, vol_list, mount_dict
+
+ vol_list = []
+ mount_dict = {}
+
+ bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
+ hal_service = bus.get_service('org.freedesktop.Hal')
+
+ bus.add_signal_receiver(gdl_changed,
+ 'org.freedesktop.Hal.Manager',
+ 'org.freedesktop.Hal',
+ '/org/freedesktop/Hal/Manager')
+
+ gtk.mainloop()
+
+if __name__=='__main__':
+ main()
diff --git a/hald/main.c b/hald/main.c
index 65790c1c..5229767b 100644
--- a/hald/main.c
+++ b/hald/main.c
@@ -1135,6 +1135,73 @@ static DBusHandlerResult device_property_exists(DBusConnection* connection,
}
+/** Determine if a device got a capability
+ *
+ * <pre>
+ * bool Device.QueryCapability(string capability_name)
+ *
+ * raises org.freedesktop.Hal.NoSuchDevice,
+ * </pre>
+ *
+ * @param connection D-BUS connection
+ * @param message Message
+ * @return What to do with the message
+ */
+static DBusHandlerResult device_query_capability(DBusConnection* connection,
+ DBusMessage* message)
+{
+ dbus_bool_t rc;
+ const char* udi;
+ const char* caps;
+ char* capability;
+ HalDevice* d;
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter iter;
+
+ LOG_TRACE(("entering"));
+
+ udi = dbus_message_get_path(message);
+
+ d = ds_device_find(udi);
+ if( d==NULL )
+ {
+ raise_no_such_device(connection, message, udi);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ dbus_error_init(&error);
+ if( !dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &capability,
+ DBUS_TYPE_INVALID) )
+ {
+ raise_syntax(connection, message, "QueryCapability");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ reply = dbus_message_new_method_return(message);
+ if( reply==NULL )
+ DIE(("No memory"));
+
+ rc = FALSE;
+ caps = ds_property_get_string(d, "Capabilities");
+ if( caps!=NULL )
+ {
+ if( strstr(caps, capability)!=NULL )
+ rc = TRUE;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+ dbus_message_iter_append_boolean(&iter, rc);
+
+ if( !dbus_connection_send(connection, reply, NULL) )
+ DIE(("No memory"));
+
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
/** Enable a device.
*
* <pre>
@@ -1846,6 +1913,12 @@ static DBusHandlerResult filter_function(DBusConnection* connection,
{
return device_add_capability(connection, message);
}
+ else if( dbus_message_is_method_call(message,
+ "org.freedesktop.Hal.Device",
+ "QueryCapability") )
+ {
+ return device_query_capability(connection, message);
+ }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
diff --git a/libhal/libhal.c b/libhal/libhal.c
index 3bf3a135..6f22397d 100644
--- a/libhal/libhal.c
+++ b/libhal/libhal.c
@@ -451,6 +451,8 @@ static DBusHandlerResult filter_func(DBusConnection* connection,
object_path = dbus_message_get_path(message);
+ /*printf("*** in filter_func, object_path=%s\n", object_path);*/
+
if( dbus_message_is_signal(message, "org.freedesktop.Hal.Manager",
"DeviceAdded") )
{
@@ -631,7 +633,11 @@ int hal_initialize(const LibHalFunctions* cb_functions)
}
// TODO: narrow in instead of match *all* signals
- dbus_bus_add_match(connection, "type='signal',interface='org.freedesktop.Hal.Manager',sender='org.freedesktop.Hal',path='/org/freedesktop/Hal/Manager'", &error);
+ dbus_bus_add_match(connection,
+ "type='signal',"
+ "interface='org.freedesktop.Hal.Manager',"
+ "sender='org.freedesktop.Hal',"
+ "path='/org/freedesktop/Hal/Manager'", &error);
if( dbus_error_is_set(&error) )
{
fprintf(stderr, "%s %d : Error subscribing to signals, "