[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
CD speed discovery
- From: Bastien Nocera <hadess hadess net>
- To: Freedesktop Hackers <xdg-list freedesktop org>
- Cc: David Zeuthen <david fubar dk>
- Subject: CD speed discovery
- Date: Sat, 17 Jan 2004 17:44:48 +0000
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]