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