hal/hald/linux2/probing linux_dvd_rw_utils.c, 1.4, 1.5 linux_dvd_rw_utils.h, 1.2, 1.3 probe-volume.c, 1.22, 1.23

David Zeuthen david at freedesktop.org
Fri Jan 20 19:26:34 PST 2006


Update of /cvs/hal/hal/hald/linux2/probing
In directory gabe:/tmp/cvs-serv19372/hald/linux2/probing

Modified Files:
	linux_dvd_rw_utils.c linux_dvd_rw_utils.h probe-volume.c 
Log Message:
2006-01-20  David Zeuthen  <davidz at redhat.com>

        * doc/spec/hal-spec.xml.in: Add docs for volume.disc.capacity

2006-01-20  William Jon McCann  <mccann at jhu.edu>

        * hald/linux2/probing/probe-volume.c (main):
        * hald/linux2/probing/linux_dvd_rw_utils.c (get_disc_capacity_cd)
        (get_disc_capacity_cdr, get_disc_capacity_dvdr_from_type)
        (get_disc_capacity_for_type): Add probing for disc capacity.

        Fixes fd.o bug #2233



Index: linux_dvd_rw_utils.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/linux_dvd_rw_utils.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- linux_dvd_rw_utils.c	16 Jan 2006 12:22:16 -0000	1.4
+++ linux_dvd_rw_utils.c	21 Jan 2006 03:26:30 -0000	1.5
@@ -1,4 +1,5 @@
-/*
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ *
  * This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
  *
  * Use-it-on-your-own-risk, GPL bless...
@@ -6,6 +7,8 @@
  * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
 */
 
+#include <glib.h>
+
 #define CREAM_ON_ERRNO(s)	do {				\
     switch ((s)[2]&0x0F)					\
     {	case 2:	if ((s)[12]==4) errno=EAGAIN;	break;		\
@@ -461,6 +464,282 @@
 	return 0;
 }
 
+
+static int
+get_disc_capacity_cd (int fd,
+		      guint64 *size)
+{
+	ScsiCommand *cmd;
+	int retval;
+	guint64 block_size;
+	guint64 num_blocks;
+	unsigned char header [8];
+
+	retval = -1;
+
+	cmd = scsi_command_new_from_fd (fd);
+	scsi_command_init (cmd, 0, 0x25);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, header, 8)) {
+		/* READ CDROM CAPACITY failed */
+		goto done;
+	}
+
+	num_blocks = (header [0] << 24) | (header [1] << 16) | (header [2] << 8) | header [3];
+	num_blocks++;
+	block_size = header [4] << 24 | header [5] << 16 | header [6] << 8 | header [7];
+
+	if (size) {
+		*size = num_blocks * block_size;
+	}
+	retval = 0;
+
+ done:
+	scsi_command_free (cmd);
+
+	return retval;
+}
+
+static int
+get_disc_capacity_cdr (int fd,
+		       guint64 *size)
+{
+	ScsiCommand *cmd;
+	int retval;
+	guint64 secs;
+	unsigned char toc [8];
+	unsigned char *atip;
+	int len;
+
+	retval = -1;
+
+	cmd = scsi_command_new_from_fd (fd);
+	/* READ_TOC */
+	scsi_command_init (cmd, 0, 0x43);
+	/* FMT_ATIP */
+	scsi_command_init (cmd, 2, 4 & 0x0F);
+	scsi_command_init (cmd, 6, 0);
+	scsi_command_init (cmd, 8, 4);
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, toc, 4)) {
+		/* READ TOC failed */
+		goto done;
+	}
+
+	len = 2 + (toc [0] << 8 | toc [1]);
+
+	atip = (unsigned char *) malloc (len);
+
+	scsi_command_init (cmd, 0, 0x43);
+	scsi_command_init (cmd, 2, 4 & 0x0F);
+	scsi_command_init (cmd, 6, 0);
+	scsi_command_init (cmd, 7, len >> 8);
+	scsi_command_init (cmd, 8, len);
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, atip, len)) {
+		/* READ TOC failed */
+		free (atip);
+		goto done;
+	}
+
+	secs = atip [12] * 60 + atip [13] + (atip [14] / 75 + 1);
+
+	if (size) {
+		*size = (1 + secs * 7 / 48) * 1024 * 1024;
+	}
+	retval = 0;
+
+	free (atip);
+ done:
+	scsi_command_free (cmd);
+
+	return retval;
+}
+
+static int
+get_disc_capacity_dvdr_from_type (int fd,
+				  int type,
+				  guint64 *size)
+{
+	ScsiCommand *cmd;
+	unsigned char formats [260];
+	unsigned char buf [32];
+	guint64 blocks;
+	guint64 nwa;
+	int i;
+	int len;
+	int obligatory;
+	int retval;
+	int next_track;
+
+	retval = -1;
+	blocks = 0;
+	next_track = 1;
+
+	cmd = scsi_command_new_from_fd (fd);
+
+ retry:
+	if (type == 0x1A || type == 0x14 || type == 0x13 || type == 0x12) {
+
+		/* READ FORMAT CAPACITIES */
+		scsi_command_init (cmd, 0, 0x23);
+		scsi_command_init (cmd, 8, 12);
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, formats, 12)) {
+			/* READ FORMAT CAPACITIES failed */
+			goto done;
+		}
+
+		len = formats [3];
+		if (len & 7 || len < 16) {
+			/* Length isn't sane */
+			goto done;
+		}
+
+		scsi_command_init (cmd, 0, 0x23);
+		scsi_command_init (cmd, 7, (4 + len) >> 8);
+		scsi_command_init (cmd, 8, (4 + len) & 0xFF);
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, formats, 4 + len)) {
+			/* READ FORMAT CAPACITIES failed */
+			goto done;
+		}
+
+		if (len != formats [3]) {
+			/* Parameter length inconsistency */
+			goto done;
+		}
+	}
+
+	obligatory = 0x00;
+
+	switch (type) {
+    	case 0x1A:		/* DVD+RW */
+		obligatory = 0x26;
+	case 0x13:		/* DVD-RW Restricted Overwrite */
+	case 0x14:		/* DVD-RW Sequential */
+		for (i = 8, len = formats [3]; i < len; i += 8) {
+			if ((formats [4 + i + 4] >> 2) == obligatory) {
+				break;
+			}
+		}
+
+		if (i == len) {
+			/* Can't find obligatory format descriptor */
+			goto done;
+		}
+
+		blocks  = formats [4 + i + 0] << 24;
+		blocks |= formats [4 + i + 1] << 16;
+		blocks |= formats [4 + i + 2] << 8;
+		blocks |= formats [4 + i + 3];
+		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
+		if (nwa > 2048) {
+			blocks *= nwa / 2048;
+		} else if (nwa < 2048) {
+			blocks /= 2048 / nwa;
+		}
+
+		retval = 0;
+		break;
+
+	case 0x12:		/* DVD-RAM */
+
+		blocks  = formats [4 + 0] << 24;
+		blocks |= formats [4 + 1] << 16;
+		blocks |= formats [4 + 2] << 8;
+		blocks |= formats [4 + 3];
+		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
+		if (nwa > 2048) {
+			blocks *= nwa / 2048;
+		} else if (nwa < 2048) {
+			blocks /= 2048 / nwa;
+		}
+
+		retval = 0;
+		break;
+
+	case 0x11:		/* DVD-R */
+	case 0x1B:		/* DVD+R */
+	case 0x2B:		/* DVD+R Double Layer */
+
+		/* READ TRACK INFORMATION */
+		scsi_command_init (cmd, 0, 0x52);
+		scsi_command_init (cmd, 1, 1);
+		scsi_command_init (cmd, 4, next_track >> 8);
+		scsi_command_init (cmd, 5, next_track & 0xFF);
+		scsi_command_init (cmd, 8, sizeof (buf));
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, buf, sizeof (buf))) {
+			/* READ TRACK INFORMATION failed */
+			if (next_track > 0) {
+				goto done;
+			} else {
+				next_track = 1;
+				goto retry;
+			}
+		}
+
+		blocks = buf [24] << 24;
+		blocks |= buf [25] << 16;
+		blocks |= buf [26] << 8;
+		blocks |= buf [27];
+
+		retval = 0;
+		break;
+	default:
+		blocks = 0;
+		break;
+	}
+
+ done:
+	scsi_command_free (cmd);
+
+	if (size) {
+		*size = blocks * 2048;
+	}
+
+	return retval;
+}
+
+int
+get_disc_capacity_for_type (int fd,
+			    int type,
+			    guint64 *size)
+{
+	int retval;
+
+	retval = -1;
+
+	switch (type) {
+	case 0x8:
+		retval = get_disc_capacity_cd (fd, size);
+		break;
+	case 0x9:
+	case 0xa:
+		retval = get_disc_capacity_cdr (fd, size);
+		break;
+	case 0x10:
+		retval = get_disc_capacity_cd (fd, size);
+		break;
+	case 0x11:
+	case 0x13:
+	case 0x14:
+	case 0x1B:
+	case 0x2B:
+	case 0x1A:
+	case 0x12:
+		retval = get_disc_capacity_dvdr_from_type (fd, type, size);
+		break;
+	default:
+		retval = -1;
+	}
+
+	return retval;
+}
+
 int
 get_disc_type (int fd)
 {

Index: linux_dvd_rw_utils.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/linux_dvd_rw_utils.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- linux_dvd_rw_utils.h	16 Jan 2006 12:22:16 -0000	1.2
+++ linux_dvd_rw_utils.h	21 Jan 2006 03:26:30 -0000	1.3
@@ -9,8 +9,11 @@
 #ifndef LINUX_DVD_RW_UTILS_H
 #define LINUX_DVD_RW_UTILS_H
 
+#include <glib.h>
+
 int get_dvd_r_rw_profile (int fd);
 int get_read_write_speed (int fd, int *read_speed, int *write_speed, char **write_speeds);
+int get_disc_capacity_for_type (int fd, int type, guint64 *capacity);
 int get_disc_type (int fd);
 int disc_is_appendable (int fd);
 int disc_is_rewritable (int fd);

Index: probe-volume.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/probe-volume.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- probe-volume.c	15 Nov 2005 03:32:36 -0000	1.22
+++ probe-volume.c	21 Jan 2006 03:26:30 -0000	1.23
@@ -1,4 +1,5 @@
-/***************************************************************************
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ ***************************************************************************
  * CVSID: $Id$
  *
  * probe-volume.c : Probe for volume type (filesystems etc.)
@@ -354,7 +355,8 @@
 
 	if (is_disc) {
 		int type;
-		struct cdrom_tochdr ; /* toc_hdr; */
+		guint64 capacity;
+		struct cdrom_tochdr; /* toc_hdr; */
 
 		/* defaults */
 		libhal_device_set_property_string (ctx, udi, "volume.disc.type", "unknown", &error);
@@ -454,6 +456,11 @@
 			}
 		}
 
+		if (get_disc_capacity_for_type (fd, type, &capacity) == 0) {
+			dbg ("volume.disc.capacity = %llu", capacity);
+			libhal_device_set_property_uint64 (ctx, udi, "volume.disc.capacity", capacity, &error);
+		}
+
 		/* On some hardware the get_disc_type call fails, so we use this as a backup */
 		if (disc_is_rewritable (fd)) {
 			libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);




More information about the hal-commit mailing list