hal/hald/linux block_class_device.c, 1.32, 1.33 common.c, 1.8, 1.9 common.h, 1.3, 1.4 osspec.c, 1.22, 1.23 platform_bus_device.c, NONE, 1.1

David Zeuthen david at pdx.freedesktop.org
Thu Jun 24 14:47:51 PDT 2004


Update of /cvs/hal/hal/hald/linux
In directory pdx:/tmp/cvs-serv30315/hald/linux

Modified Files:
	block_class_device.c common.c common.h osspec.c 
Added Files:
	platform_bus_device.c 
Log Message:
2004-06-24  David Zeuthen  <david at fubar.dk>

	Add floppy support to HAL - tested with x86 legacy floppies and
	an USB floppy drive.

	* tools/device-manager/Const.py.in (BUS_NAMES): Add platform bus

	* hald/linux/common.h: Add read_single_line_grep prototype

	* hald/linux/common.c (read_single_line_grep): New function

	* hald/linux/block_class_device.c (detect_media): Add the
	force_poll parameter to poll on devices with media detection
	explicitly disabled.  Introduce support for non-optical drives
	with block.no_partitions set to TRUE. Remember to clear linux.*
	properties for discs and volumes from block.no_partitions as hot
	unplugging such drives will cause the top-level block device to
	stay as the child is found instead when searching on
	linux.sysfs_path
	(block_class_pre_process): Introduce a nasty hack to read
	/proc/scsi/usb-storage/<scsi-hostnumber> to determine if we're
	a floppy drive and thus should set block.no_partitions to TRUE
	(foreach_block_device): Rename to mtab_foreach_device, split into
	mtab_handle_volume and mtab_handle_storage
	(mtab_handle_volume): New function, handle normal partition based
	volumes in /etc/mtab
	(mtab_handle_storage): New function, handle block.no_partitions
	volumes in /etc/mtab
	(block_class_removed): Make sure to remove the HAL-made child
	if block.no_partitions is TRUE

	* hald/linux/block_class_device.c (disc_remove_from_gdl): Rename
	to volume_remove_from_gdl

	* hald/linux/platform_bus_device.c: New file

	* hald/Makefile.am (hald_SOURCES): Add platform_bus_device.c



Index: block_class_device.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/block_class_device.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- block_class_device.c	20 Jun 2004 14:15:01 -0000	1.32
+++ block_class_device.c	24 Jun 2004 21:47:49 -0000	1.33
@@ -393,9 +393,9 @@
 }
 
 static void
-disc_remove_from_gdl (HalDevice *device, gpointer user_data)
+volume_remove_from_gdl (HalDevice *device, gpointer user_data)
 {
-	g_signal_handlers_disconnect_by_func (device, disc_remove_from_gdl, 
+	g_signal_handlers_disconnect_by_func (device, volume_remove_from_gdl, 
 					      user_data);
 	hal_device_store_remove (hald_get_gdl (), device);
 }
@@ -407,18 +407,21 @@
  *                              it will only have effect if the device is
  *                              in the GDL and is of capability block and
  *                              is not a volume
+ *  @param force_poll           If TRUE, do polling even though 
+ *                              storage.media_check_enabled==FALSE
  *  @return                     TRUE iff the GDL was modified
  */
 static dbus_bool_t
-detect_media (HalDevice * d)
+detect_media (HalDevice * d, dbus_bool_t force_poll)
 {
 	int fd;
 	dbus_bool_t is_cdrom;
 	const char *device_file;
 	HalDevice *child;
 
-	/* respect policy */
-	if (!hal_device_property_get_bool (d, "storage.media_check_enabled"))
+	/* respect policy unless we force */
+	if (!force_poll && 
+	    !hal_device_property_get_bool (d, "storage.media_check_enabled"))
 		return FALSE;
 
 	/* need to be in GDL */
@@ -451,12 +454,146 @@
 			/*HAL_WARNING (("open(\"%s\", O_RDONLY) failed, "
 			  "errno=%d", device_file, errno));*/
 
-			if (errno == ENOMEDIUM) {
-				force_unmount_of_all_childs (d);
+			if (errno == ENOMEDIUM &&
+			    hal_device_property_get_bool (
+				    d, "block.no_partitions") ) {
+				
+
+				child = hal_device_store_match_key_value_string (
+					hald_get_gdl (), "info.parent",
+					hal_device_get_udi (d));
+
+				if (child != NULL ) {
+					force_unmount_of_all_childs (d);
+
+					HAL_INFO (("Removing volume for "
+						   "no_partitions device %s", 
+						   device_file));
+
+					g_signal_connect (child, "callouts_finished",
+							  G_CALLBACK (volume_remove_from_gdl), NULL);
+					hal_callout_device (child, FALSE);
+					
+					close (fd);
+
+					/* GDL was modified */
+					return TRUE;
+				}
+			} 
+			
+		} else if (hal_device_property_get_bool (
+				   d, "block.no_partitions")) {
+
+			/* For drives with partitions, we simply get hotplug
+			 * events so only do something for e.g. floppies */
+
+			/* media in drive; check if the HAL device representing
+			 * the drive already got a child (it can have
+			 * only one child)
+			 */
+
+			child = hal_device_store_match_key_value_string (
+				hald_get_gdl (), "info.parent",
+				hal_device_get_udi (d));
+
+			if (child == NULL) {
+				child = hal_device_store_match_key_value_string
+					(hald_get_tdl (), "info.parent",
+					hal_device_get_udi (d));
 			}
 
-		}
+			if (child == NULL) {				
+				char udi[256];
+
+				HAL_INFO (("Media in no_partitions device %s",
+					   device_file));
+
+				child = hal_device_new ();
+				hal_device_store_add (hald_get_tdl (), child);
+				g_object_unref (child);
+
+				/* copy from parent */
+				hal_device_merge (child, d);
+
+				/* modify some properties */
+				hal_device_property_set_string (
+					child, "info.parent", d->udi);
+				hal_device_property_set_bool (
+					child, "block.is_volume", TRUE);
+				hal_device_property_set_string (
+					child, "info.capabilities",
+					"block volume");
+				hal_device_property_set_string (
+					child, "info.category","volume");
+				hal_device_property_set_string (
+					child, "info.product", "Volume");
+				/* clear these otherwise we'll
+				 * imposter the parent on hotplug
+				 * remove
+				 */
+				hal_device_property_set_string (
+					child, "linux.sysfs_path", "");
+				hal_device_property_set_string (
+					child, "linux.sysfs_path_device", "");
+
+				/* set defaults */
+				hal_device_property_set_string (
+					child, "volume.label", "");
+				hal_device_property_set_string (
+					child, "volume.uuid", "");
+				hal_device_property_set_string (
+					child, "volume.fstype", "");
+				hal_device_property_set_string (
+					child, "volume.mount_point", "");
+				hal_device_property_set_bool (
+					child, "volume.is_mounted", FALSE);
+				hal_device_property_set_bool (
+					child, "volume.is_disc", FALSE);
+
+				/* set UDI as appropriate */
+				strncpy (udi,
+					 hal_device_property_get_string (
+						 d, 
+						 "info.udi"), 256);
+				strncat (udi, "-volume", 256);
+				hal_device_property_set_string (
+					child, "info.udi", udi);
+				hal_device_set_udi (child, udi);
+
+
+				close(fd);
+				
+				detect_fs (child);
+				
+				/* If we have a nice volume label, set it */
+				if (hal_device_has_property (child, 
+							     "volume.label")) {
+					const char *label;
+					
+					label = hal_device_property_get_string
+						(child, "volume.label");
+					
+					if (label != NULL && 
+					    label[0] != '\0') {
+						hal_device_property_set_string
+							(child, "info.product",
+							 label);
+					}
+				}
+
+				/* add new device */
+				g_signal_connect (
+					child, "callouts_finished",
+					G_CALLBACK (device_move_from_tdl_to_gdl), NULL);
+				hal_callout_device (child, TRUE);
 
+				/* GDL was modified */
+				return TRUE;
+
+			} /* no child */
+
+		} /* media in no_partitions device */
+		
 	} /* device is not an optical drive */
 	else {
 		int drive;
@@ -542,7 +679,7 @@
 			if (child != NULL) {
 				HAL_INFO (("Removing volume for optical device %s", device_file));
 				g_signal_connect (child, "callouts_finished",
-						  G_CALLBACK (disc_remove_from_gdl), NULL);
+						  G_CALLBACK (volume_remove_from_gdl), NULL);
 				hal_callout_device (child, FALSE);
 
 				close (fd);
@@ -614,6 +751,13 @@
 						"volume");
 			hal_device_property_set_string (child, "info.product",
 						"Disc");
+			/* clear these otherwise we'll imposter the parent
+			 * on hotplug remove
+			 */
+			hal_device_property_set_string (
+				child, "linux.sysfs_path", "");
+			hal_device_property_set_string (
+				child, "linux.sysfs_path_device", "");
 
 			/* set defaults */
 			hal_device_property_set_string (
@@ -1104,6 +1248,8 @@
 		const char *sysfs_path;
 		char attr_path[SYSFS_PATH_MAX];
 		struct sysfs_attribute *attr;
+		int scsi_host;
+		char *scsi_protocol;
 		
 		sysfs_path = hal_device_property_get_string (
 			d, "linux.sysfs_path");
@@ -1169,6 +1315,43 @@
 					      type));
 			}
 		}
+
+		/* Check for (USB) floppy - Yuck, this is pretty ugly in
+		 * quite a few ways!! Reading /proc-files, looking at
+		 * some hardcoded string from the kernel etc. etc.
+		 *
+		 * @todo : Get Protocol into sysfs or something more sane
+		 * giving us the type of the SCSI device
+		 */
+		scsi_host = hal_device_property_get_int (
+			parent, "scsi_device.host");
+		scsi_protocol = read_single_line_grep (
+			"     Protocol: ", 
+			"/proc/scsi/usb-storage/%d", 
+			scsi_host);
+		if (scsi_protocol != NULL &&
+		    strcmp (scsi_protocol,
+			    "Uniform Floppy Interface (UFI)") == 0) {
+
+			/* Indeed a (USB) floppy drive */
+
+			hal_device_property_set_string (d, 
+							"storage.drive_type", 
+							"floppy");
+
+			/* Indeed no partitions */
+			hal_device_property_set_bool (d, 
+						      "block.no_partitions",
+						      TRUE);
+
+			/* My experiments with my USB LaCie Floppy disk
+			 * drive is that polling indeed work (Yay!), so
+			 * we don't set storage.media_check_enabled to 
+			 * FALSE - for devices where this doesn't work,
+			 * we can override it with .fdi files
+			 */
+		}
+
 	} else {
 		/** @todo block device on non-IDE and non-SCSI device;
 		 *  how to find the name and the media-type? 
@@ -1186,7 +1369,8 @@
 		has_removable_media);
 
 	if (hal_device_has_property (stordev, "storage.drive_type") &&
-	    strcmp (hal_device_property_get_string (stordev, "storage.drive_type"), 
+	    strcmp (hal_device_property_get_string (stordev, 
+						    "storage.drive_type"), 
 		    "cdrom") == 0) {
 		hal_device_property_set_bool (d, "block.no_partitions", TRUE);
 		cdrom_check (stordev, device_file);
@@ -1237,7 +1421,7 @@
 	}
 
 	/* check for media on the device */
-	detect_media (d);
+	detect_media (d, FALSE);
 
 	/* Check the mtab to see if the device is mounted */
 	etc_mtab_process_all_block_devices (TRUE);
@@ -1435,21 +1619,179 @@
 static dbus_bool_t have_setup_watcher = FALSE;
 
 static gboolean
-foreach_block_device (HalDeviceStore *store, HalDevice *d,
-		      gpointer user_data)
+mtab_handle_storage (HalDevice *d)
 {
-	const char *bus;
+	HalDevice *child;
 	int major, minor;
 	dbus_bool_t found_mount_point;
-	struct mount_point_s *mp;
+	struct mount_point_s *mp = NULL;
 	int i;
+	
+	if (!hal_device_property_get_bool (d, "block.no_partitions"))
+		return TRUE;
 
-	bus = hal_device_property_get_string (d, "info.bus");
-	if (bus == NULL ||
-	    strncmp (bus, "block", 5) != 0 ||
-	    !hal_device_property_get_bool (d, "block.is_volume"))
+	if (!hal_device_has_property (d, "storage.media_check_enabled"))
 		return TRUE;
 
+	if (hal_device_property_get_bool (d, "storage.media_check_enabled"))
+		return TRUE;
+
+	HAL_INFO (("FOOO Checking for %s", 
+		   hal_device_property_get_string (d, "block.device")));
+
+	/* Only handle storage devices where block.no_parition==TRUE and
+	 * where we can't check for media. Typically this is only legacy
+	 * floppy drives on x86 boxes.
+	 *
+	 * So, in this very specific situation we maintain a child volume
+	 * exactly when media is mounted.
+	 */
+
+	major = hal_device_property_get_int (d, "block.major");
+	minor = hal_device_property_get_int (d, "block.minor");
+
+	child = hal_device_store_match_key_value_string (
+		hald_get_gdl (), "info.parent",
+		hal_device_get_udi (d));
+
+	/* Search all mount points */
+	found_mount_point = FALSE;
+	for (i = 0; i < num_mount_points; i++) {
+		mp = &mount_points[i];
+			
+		if (mp->major == major && mp->minor == minor) {
+
+			if (child == NULL ) {
+				char udi[256];
+
+				/* is now mounted, and we didn't have a child,
+				 * so add the child */
+				HAL_INFO (("%s now mounted at %s, "
+					   "major:minor=%d:%d, "
+					   "fstype=%s, udi=%s", 
+					   mp->device, mp->mount_point, 
+					   mp->major, mp->minor, 
+					   mp->fs_type, d->udi));
+
+				child = hal_device_new ();
+				hal_device_store_add (hald_get_tdl (), child);
+				g_object_unref (child);
+
+				/* copy from parent */
+				hal_device_merge (child, d);
+
+				/* modify some properties */
+				hal_device_property_set_string (
+					child, "info.parent", d->udi);
+				hal_device_property_set_bool (
+					child, "block.is_volume", TRUE);
+				hal_device_property_set_string (
+					child, "info.capabilities",
+					"block volume");
+				hal_device_property_set_string (
+					child, "info.category","volume");
+				hal_device_property_set_string (
+					child, "info.product", "Volume");
+				/* clear these otherwise we'll
+				 * imposter the parent on hotplug
+				 * remove
+				 */
+				hal_device_property_set_string (
+					child, "linux.sysfs_path", "");
+				hal_device_property_set_string (
+					child, "linux.sysfs_path_device", "");
+
+				/* set defaults */
+				hal_device_property_set_string (
+					child, "volume.label", "");
+				hal_device_property_set_string (
+					child, "volume.uuid", "");
+				hal_device_property_set_string (
+					child, "volume.fstype",
+					mp->fs_type);
+				hal_device_property_set_string (
+					child, "volume.mount_point",
+					mp->mount_point);
+				hal_device_property_set_bool (
+					child, "volume.is_mounted", TRUE);
+				hal_device_property_set_bool (
+					child, "volume.is_disc", FALSE);
+
+				/* set UDI as appropriate */
+				strncpy (udi,
+					 hal_device_property_get_string (
+						 d, 
+						 "info.udi"), 256);
+				strncat (udi, "-volume", 256);
+				hal_device_property_set_string (
+					child, "info.udi", udi);
+				hal_device_set_udi (child, udi);
+				
+				detect_fs (child);
+				
+				/* If we have a nice volume label, set it */
+				if (hal_device_has_property (child, 
+							     "volume.label")) {
+					const char *label;
+					
+					label = hal_device_property_get_string
+						(child, "volume.label");
+					
+					if (label != NULL && 
+					    label[0] != '\0') {
+						hal_device_property_set_string
+							(child, "info.product",
+							 label);
+					}
+				}
+
+				/* add new device */
+				g_signal_connect (
+					child, "callouts_finished",
+					G_CALLBACK (device_move_from_tdl_to_gdl), NULL);
+				hal_callout_device (child, TRUE);
+
+				/* GDL was modified */
+				return TRUE;
+
+			}
+		}
+	}
+
+	/* No mount point found */
+	if (!found_mount_point) {
+		if (child != NULL ) {
+			/* We had a child, but is no longer mounted, go
+			 * remove the child */
+			HAL_INFO (("%s not mounted anymore at %s, "
+				   "major:minor=%d:%d, "
+				   "fstype=%s, udi=%s", 
+				   mp->device, mp->mount_point, 
+				   mp->major, mp->minor, 
+				   mp->fs_type, d->udi));
+			
+			g_signal_connect (child, "callouts_finished",
+					  G_CALLBACK (volume_remove_from_gdl), NULL);
+			hal_callout_device (child, FALSE);
+					
+			/* GDL was modified */
+			return TRUE;
+		}
+
+		
+	}
+
+	return TRUE;
+}
+
+static gboolean
+mtab_handle_volume (HalDevice *d)
+{
+	int major, minor;
+	dbus_bool_t found_mount_point;
+	struct mount_point_s *mp;
+	int i;
+
 	major = hal_device_property_get_int (d, "block.major");
 	minor = hal_device_property_get_int (d, "block.minor");
 
@@ -1548,6 +1890,21 @@
 	return TRUE;
 }
 
+
+static gboolean
+mtab_foreach_device (HalDeviceStore *store, HalDevice *d,
+		     gpointer user_data)
+{
+	if (hal_device_has_capability (d, "volume")) {
+		return mtab_handle_volume (d);
+	} else if (hal_device_has_capability (d, "storage")) {
+		return mtab_handle_storage (d);
+	}
+
+	return TRUE;
+}
+
+
 /** Load /etc/mtab and process all HAL block devices and set properties
  *  according to mount status. Also, optionally, sets up a watcher to do
  *  this whenever /etc/mtab changes
@@ -1575,7 +1932,7 @@
 	else
 		HAL_INFO (("processing /etc/mtab"));
 
-	hal_device_store_foreach (hald_get_gdl (), foreach_block_device, NULL);
+	hal_device_store_foreach (hald_get_gdl (), mtab_foreach_device, NULL);
 }
 
 
@@ -1600,14 +1957,32 @@
 
 static void
 block_class_removed (ClassDeviceHandler* self, 
-		      const char *sysfs_path, 
-		      HalDevice *d)
+		     const char *sysfs_path, 
+		     HalDevice *d)
 {
+	HalDevice *child;
+
 	if (hal_device_has_property (d, "block.is_volume")) {
 		if (hal_device_property_get_bool (d, "block.is_volume")) {
 			force_unmount (d);
 		} else {
 			force_unmount_of_all_childs (d);
+
+			/* if we have no partitions our child is just
+			 * made up here in HAL, so remove it
+			 */
+			if (hal_device_property_get_bool (d, "block.no_partitions")) {
+				child = hal_device_store_match_key_value_string (
+					hald_get_gdl (), "info.parent",
+					hal_device_get_udi (d));
+
+				if (child != NULL) {
+					g_signal_connect (child, "callouts_finished",
+							  G_CALLBACK (volume_remove_from_gdl), NULL);
+					hal_callout_device (child, FALSE);
+				}
+			}
+
 		}
 	}
 }
@@ -1620,10 +1995,10 @@
 	/** @todo FIXME GDL was modifed so we have to break here because we
          *        are iterating over devices and this will break it
          */
-		if (detect_media (device))
-			return FALSE;
-		else
-			return TRUE;
+	if (detect_media (device, FALSE))
+		return FALSE;
+	else
+		return TRUE;
 }
 
 static void

Index: common.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/common.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- common.c	20 Jun 2004 13:27:45 -0000	1.8
+++ common.c	24 Jun 2004 21:47:49 -0000	1.9
@@ -278,6 +278,61 @@
 
 /** Read the first line of a file and return it.
  *
+ *  @param  begin               Return to line that begins with this string
+ *  @param  filename_format     Name of file, printf-style formatted
+ *  @return                     Pointer to string right after the begin string
+ *                              or #NULL if the file could not be opened or
+ *                              there is no matching lines. The result is only
+ *                              valid until the next invocation of this 
+ *                              function.
+ */
+char *
+read_single_line_grep (char *begin, char *filename_format, ...)
+{
+	FILE *f;
+	int i;
+	int len;
+	char filename[512];
+	static char buf[512];
+	va_list args;
+	size_t begin_len;
+
+	begin_len = strlen (begin);
+
+	va_start (args, filename_format);
+	vsnprintf (filename, 512, filename_format, args);
+	va_end (args);
+
+	f = fopen (filename, "rb");
+	if (f == NULL)
+		return NULL;
+
+	do {
+		if (fgets (buf, 512, f) == NULL) {
+			fclose (f);
+			return NULL;
+		}
+
+		if (strncmp (buf, begin, begin_len) == 0) {
+			len = strlen (buf);
+			for (i = len - 1; i > 0; --i) {
+				if (buf[i] == '\n' || buf[i] == '\r')
+					buf[i] = '\0';
+				else
+					break;
+			}
+
+			break;
+		}
+	} while (TRUE);
+
+	fclose (f);
+
+	return buf + begin_len;
+}
+
+/** Read the first line of a file and return it.
+ *
  *  @param  filename_format     Name of file, printf-style formatted
  *  @return                     Pointer to string or #NULL if the file could
  *                              not be opened. The result is only valid until

Index: common.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux/common.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- common.h	26 Apr 2004 20:08:58 -0000	1.3
+++ common.h	24 Jun 2004 21:47:49 -0000	1.4
@@ -48,6 +48,8 @@
 
 char *read_single_line (char *filename_format, ...);
 
+char *read_single_line_grep (char *begin, char *filename_format, ...);
+
 const char *get_last_element (const char *s);
 
 /* returns the path of the udevinfo program */

Index: osspec.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/osspec.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- osspec.c	23 Jun 2004 21:34:51 -0000	1.22
+++ osspec.c	24 Jun 2004 21:47:49 -0000	1.23
@@ -68,6 +68,7 @@
 extern BusDeviceHandler ide_host_bus_handler;
 extern BusDeviceHandler ide_bus_handler;
 extern BusDeviceHandler macio_bus_handler;
+extern BusDeviceHandler platform_bus_handler;
 
 /*
  * NOTE!  Order can be significant here, especially at startup time
@@ -97,6 +98,7 @@
 	&ide_host_bus_handler,
         &ide_bus_handler,
 	&macio_bus_handler,
+	&platform_bus_handler,
 	NULL
 };
 
@@ -424,6 +426,7 @@
 static void
 remove_callouts_finished (HalDevice *d, gpointer user_data)
 {
+	HAL_INFO (("in remove_callouts_finished for udi=%s", d->udi));
 	hal_device_store_remove (hald_get_gdl (), d);
 }
 
@@ -446,6 +449,7 @@
 		g_signal_connect (d, "callouts_finished",
 				  G_CALLBACK (remove_callouts_finished), NULL);
 
+		HAL_INFO (("in remove_device for udi=%s", d->udi));
 		hal_callout_device (d, FALSE);
 	}
 }

--- NEW FILE: platform_bus_device.c ---
/***************************************************************************
 * CVSID: $Id: platform_bus_device.c,v 1.1 2004/06/24 21:47:49 david Exp $
 *
 * Platform bus devices
 *
 * Copyright (C) 2003 David Zeuthen, <david at fubar.dk>
 *
 * Licensed under the Academic Free License version 2.0
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <assert.h>
#include <unistd.h>
#include <stdarg.h>

#include "../logger.h"
#include "../device_store.h"
#include "bus_device.h"
#include "common.h"


static dbus_bool_t
platform_device_accept (BusDeviceHandler *self, const char *path, 
			struct sysfs_device *device)
{
	if (strcmp (device->bus, "platform") != 0)
		return FALSE;

	/* Only support floppies */
	if (strncmp (device->bus_id, "floppy", 6) != 0)
		return FALSE;

	return TRUE;
}

static char *
platform_device_compute_udi (HalDevice *d, int append_num)
{
	static char buf[256];

	if (append_num == -1)
		sprintf (buf, "/org/freedesktop/Hal/devices/legacy_floppy_%d",
			 hal_device_property_get_int (d, "storage.legacy_floppy.number"));
	else
		sprintf (buf, "/org/freedesktop/Hal/devices/legacy_floppy_%d/%d",
			 hal_device_property_get_int (d, "storage.legacy_floppy.number"),
			 append_num);

	return buf;
}

static void
platform_device_got_udi (BusDeviceHandler *self,
			HalDevice *d,
			const char *udi)
{
	hal_device_property_set_string (d, "block.storage_device", udi);
}

static void 
platform_device_pre_process (BusDeviceHandler *self,
			     HalDevice *d,
			     const char *sysfs_path,
			     struct sysfs_device *device)
{
	int major;
	int minor;
	int number;
	char device_file[256];
	char fd_sysfs_path[256];

	sscanf (device->bus_id, "floppy%d", &number);
	hal_device_property_set_int (d, "storage.legacy_floppy.number", 
				     number);

	hal_device_property_set_string (d, "info.product",
					"Legacy Floppy Drive");
	hal_device_property_set_string (d, "info.vendor",
					"");

	/* All the following is a little but of cheating, but hey, what
	 * can you do when the kernel doesn't properly export legacy
	 * floppy drives properly.
	 *
	 * @todo Fix the kernel to support legacy floppies properly in
	 * sysfs
	 */

	snprintf (fd_sysfs_path, sizeof (fd_sysfs_path), "%s/block/fd%d", 
		  sysfs_mount_path, number);

	if (!class_device_get_device_file (fd_sysfs_path, 
					   device_file, 
					   sizeof (device_file))) {
		HAL_ERROR (("Could not get device file floppy %d", number));
		return;
	}
	
	class_device_get_major_minor (fd_sysfs_path, &major, &minor);

	hal_device_property_set_string (d, "block.device", device_file);
	hal_device_property_set_bool (d, "block.is_volume", FALSE);
	hal_device_property_set_int (d, "block.major", major);
	hal_device_property_set_int (d, "block.minor", minor);
	hal_device_property_set_bool (d, "block.no_partitions", TRUE);

	hal_device_property_set_string (d, "storage.bus", "platform");
	hal_device_property_set_string (d, "storage.drive_type", "floppy");
	hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
	hal_device_property_set_bool (d, "storage.removable", TRUE);
	hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
	hal_device_property_set_bool (d, "storage.automount_enabled", FALSE);
	
	hal_device_property_set_string (d, "storage.vendor", "");
	hal_device_property_set_string (d, "storage.model", "Floppy Drive");

	hal_device_add_capability (d, "block");
	hal_device_add_capability (d, "storage");
	hal_device_add_capability (d, "storage.floppy");
}


/** Method specialisations for bustype pci */
BusDeviceHandler platform_bus_handler = {
	bus_device_init,              /**< init function */
	bus_device_shutdown,          /**< shutdown function */
	bus_device_tick,              /**< timer function */
	platform_device_accept,       /**< accept function */
 	bus_device_visit,             /**< visitor function */
	bus_device_removed,           /**< device is removed */
	platform_device_compute_udi,  /**< UDI computing function */
	platform_device_pre_process,  /**< add more properties */
	platform_device_got_udi,      /**< got UDI */
	"platform",                   /**< sysfs bus name */
	"platform"                    /**< namespace */
};


/** @} */





More information about the hal-commit mailing list