[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

CD speed discovery



Heya,

So, I've managed to get around getting the speed problem sorted.
Patch attached. I snuck in a patch to open the CD drive O_EXCL, to avoid
colliding with a running application using the CD.

Cheers

PS: libbacon's CD drive discovery code is much cleaner with HAL support
http://www.hadess.net/files/patches/hald-dvd-support/libbacon-hal-with-speed.patch
---
Bastien Nocera <hadess hadess net> 
A problem shared is a problem halved, so is your problem really yours or
just half of someone else's?
Index: linux/linux_class_block.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/linux_class_block.c,v
retrieving revision 1.21
diff -u -r1.21 linux_class_block.c
--- linux/linux_class_block.c	17 Jan 2004 01:59:51 -0000	1.21
+++ linux/linux_class_block.c	17 Jan 2004 17:31:01 -0000
@@ -514,6 +514,8 @@
 
                 if (capabilities >= 0)
                 {
+		    int read_speed, write_speed;
+
                     if (capabilities & CDC_CD_R)
                     {
                         ds_add_capability(d, "storage.cdr");
@@ -557,16 +559,22 @@
                         ds_add_capability(d, "storage.dvdram");
                         ds_property_set_bool(d, "storage.dvdram", TRUE);
                     }
-                }
-                
-                /* while we're at it, check if we support media changed */
-                if( ioctl(fd, CDROM_MEDIA_CHANGED)>=0 )
-                {
-                    ds_property_set_bool(d, 
-                         "storage.cdrom.support_media_changed", TRUE);
-                }
 
-                close (fd);
+		    /* while we're at it, check if we support media changed */
+		    if( ioctl(fd, CDROM_MEDIA_CHANGED)>=0 )
+		    {
+		        ds_property_set_bool(d,
+			    "storage.cdrom.support_media_changed", TRUE);
+		    }
+
+		    if( get_read_write_speed(fd, &read_speed, &write_speed) >= 0 )
+		    {
+			ds_property_set_int(d, "storage.cdrom.read_speed", read_speed);
+			if (read_speed)
+			    ds_property_set_int(d, "storage.cdrom.write_speed", write_speed);
+		    }
+		} 
+		close (fd);
 		    }
         }
 
@@ -1196,12 +1204,12 @@
         int drive;
         dbus_bool_t got_disc = FALSE;
 
-        fd = open(device_file, O_RDONLY|O_NONBLOCK);
+        fd = open(device_file, O_RDONLY|O_NONBLOCK|O_EXCL);
 
         if( fd==-1 )
         {
             /* open failed */
-            HAL_WARNING(("open(\"%s\", O_RDONLY|O_NONBLOCK) failed, "
+            HAL_WARNING(("open(\"%s\", O_RDONLY|O_NONBLOCK|O_EXCL) failed, "
                          "errno=%d", device_file, errno));
             return FALSE;
         }
Index: linux/linux_dvd_rw_utils.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/linux_dvd_rw_utils.c,v
retrieving revision 1.1
diff -u -r1.1 linux_dvd_rw_utils.c
--- linux/linux_dvd_rw_utils.c	17 Jan 2004 01:59:51 -0000	1.1
+++ linux/linux_dvd_rw_utils.c	17 Jan 2004 17:31:02 -0000
@@ -250,3 +250,120 @@
 	return retval;
 }
 
+static unsigned char *
+pull_page2a_from_fd (int fd)
+{
+	ScsiCommand *cmd;
+	unsigned char header[12], *page2A;
+	unsigned int len, bdlen;
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	scsi_command_init (cmd, 0, 0x5A); /* MODE SENSE */
+	scsi_command_init (cmd, 1, 0x08); /* Disable Block Descriptors */
+	scsi_command_init (cmd, 2, 0x2A); /* Capabilities and Mechanical Status */
+	scsi_command_init (cmd, 8, sizeof (header)); /* header only to start with */
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, header, sizeof (header)))
+	{
+		/* MODE SENSE failed */
+		scsi_command_free (cmd);
+		return NULL;
+	}
+
+	len = (header[0] << 8 | header[1]) + 2;
+	bdlen = header[6] << 8 | header[7];
+
+	/* should never happen as we set "DBD" above */
+	if (bdlen)
+	{
+		if (len < (8 + bdlen + 30))
+		{
+			/* LUN impossible to bear with */
+			scsi_command_free (cmd);
+			return NULL;
+		}
+	} else if (len < (8 + 2 + (unsigned int) header[9])) {
+		/* SANYO does this. */
+		len = 8+2+header[9];
+	}
+
+	page2A = (unsigned char *)malloc(len);
+	if (page2A == NULL)
+	{
+		/* ENOMEM */
+		scsi_command_free (cmd);
+		return NULL;
+	}
+
+	scsi_command_init (cmd, 0, 0x5A); /* MODE SENSE */
+	scsi_command_init (cmd, 1, 0x08); /* Disable Block Descriptors */
+	scsi_command_init (cmd, 2, 0x2A); /* Capabilities and Mechanical Status */
+	scsi_command_init (cmd, 7, len >> 8);
+	scsi_command_init (cmd, 8, len); /* Real length */
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, page2A, len))
+	{
+		/* MODE SENSE failed */
+		scsi_command_free (cmd);
+		free (page2A);
+		return NULL;
+	}
+
+	scsi_command_free (cmd);
+
+	len -= 2;
+	/* paranoia */
+	if (len < ((unsigned int) page2A[0] << 8 | page2A[1]))
+	{
+		page2A[0] = len >> 8;
+		page2A[1] = len;
+	}
+
+	return page2A;
+}
+
+int
+get_read_write_speed (int fd, int *read_speed, int *write_speed)
+{
+	unsigned char *page2A;
+	int len, hlen;
+	unsigned char *p;
+
+	*read_speed = 0;
+	*write_speed =0;
+
+	page2A = pull_page2a_from_fd (fd);
+	if (page2A == NULL)
+	{
+		printf ("Failed to get Page 2A\n");
+		/* Failed to get Page 2A */
+		return -1;
+	}
+
+	len  = (page2A[0] << 8 | page2A[1]) + 2;
+	hlen = 8 + (page2A[6] << 8 | page2A[7]);
+	p = page2A + hlen;
+
+	/* Values guessed from the cd_mode_page_2A struct
+	 * in cdrecord's libscg/scg/scsireg.h */
+	if (len < (hlen + 30) || p[1] < (30 - 2))
+	{
+		/* no MMC-3 "Current Write Speed" present,
+		 * try to use the MMC-2 one */
+		if (len < (hlen + 20) || p[1] < (20 -2))
+			*write_speed = p[18] << 8 | p[19];
+		else
+			*write_speed = 0;
+	} else {
+		*write_speed = p[28] << 8 | p[29];
+	}
+
+	*read_speed = p[8] << 8 | p[9];
+
+	free (page2A);
+
+	return 0;
+}
+
Index: linux/linux_dvd_rw_utils.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux/linux_dvd_rw_utils.h,v
retrieving revision 1.1
diff -u -r1.1 linux_dvd_rw_utils.h
--- linux/linux_dvd_rw_utils.h	17 Jan 2004 01:59:51 -0000	1.1
+++ linux/linux_dvd_rw_utils.h	17 Jan 2004 17:31:02 -0000
@@ -10,5 +10,6 @@
 #define LINUX_DVD_RW_UTILS_H
 
 int get_dvd_r_rw_profile (int fd);
+int get_read_write_speed (int fd, int *read_speed, int *write_speed);
 
 #endif /* LINUX_DVD_RW_UTILS_H */

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]