[brasero] Use MMC command to get the drive capabilities instead of HAL
- From: Philippe Rouquier <philippr src gnome org>
- To: svn-commits-list gnome org
- Subject: [brasero] Use MMC command to get the drive capabilities instead of HAL
- Date: Fri, 10 Jul 2009 14:03:56 +0000 (UTC)
commit 14f88a647b494b2580b5717d9587cb05014e61c7
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date: Wed Jul 8 20:16:26 2009 +0200
Use MMC command to get the drive capabilities instead of HAL
libbrasero-media/brasero-drive.c | 262 +++++++++++++++++++++++++----
libbrasero-media/brasero-drive.h | 2 +-
libbrasero-media/scsi-get-configuration.h | 4 +-
libbrasero-media/scsi-sg.c | 3 +
4 files changed, 237 insertions(+), 34 deletions(-)
---
diff --git a/libbrasero-media/brasero-drive.c b/libbrasero-media/brasero-drive.c
index acf7011..60c519a 100644
--- a/libbrasero-media/brasero-drive.c
+++ b/libbrasero-media/brasero-drive.c
@@ -50,7 +50,13 @@
#include "brasero-drive.h"
#include "burn-hal-watch.h"
+#include "scsi-device.h"
+#include "scsi-utils.h"
+#include "scsi-spc1.h"
#include "scsi-mmc1.h"
+#include "scsi-mmc2.h"
+#include "scsi-status-page.h"
+#include "scsi-mode-pages.h"
#if defined(HAVE_STRUCT_USCSI_CMD)
#define BLOCK_DEVICE "block.solaris.raw_device"
@@ -63,6 +69,9 @@ struct _BraseroDrivePrivate
{
GDrive *gdrive;
+ GThread *probe;
+ gint probe_id;
+
BraseroMedium *medium;
BraseroDriveCaps caps;
@@ -77,7 +86,7 @@ struct _BraseroDrivePrivate
GCancellable *cancel;
guint probed:1;
-
+ guint probe_cancelled:1;
};
#define BRASERO_DRIVE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DRIVE, BraseroDrivePrivate))
@@ -97,6 +106,8 @@ enum {
G_DEFINE_TYPE (BraseroDrive, brasero_drive, G_TYPE_OBJECT);
+#define BRASERO_DRIVE_OPEN_ATTEMPTS 5
+
/**
* This is private API. The function is defined in brasero-volume.c
*/
@@ -768,31 +779,6 @@ brasero_drive_init_hal (BraseroDrive *drive)
priv->path = NULL;
}
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.cdr", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_CDR;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.cdrw", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_CDRW;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdr", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDR;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdrw", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDRW;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdplusr", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdplusrw", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdplusrdl", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS_DL;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdplusrwdl", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.dvdram", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_DVDRAM;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.bdr", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_BDR;
- if (libhal_device_get_property_bool (ctx, priv->udi, "storage.cdrom.bdre", NULL))
- priv->caps |= BRASERO_DRIVE_CAPS_BDRW;
-
- BRASERO_MEDIA_LOG ("Drive caps are %d", priv->caps);
-
/* Also get its parent to retrieve the bus, host, lun values */
priv->bus = -1;
priv->lun = -1;
@@ -817,15 +803,16 @@ brasero_drive_init_hal (BraseroDrive *drive)
}
}
-static void
-brasero_drive_init_real (BraseroDrive *drive)
+static gboolean
+brasero_drive_probed (gpointer data)
{
+ BraseroDrive *drive = BRASERO_DRIVE (data);
BraseroDrivePrivate *priv;
- priv = BRASERO_DRIVE_PRIVATE (drive);
+ priv = BRASERO_DRIVE_PRIVATE (data);
- priv->block_path = g_drive_get_identifier (priv->gdrive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
- BRASERO_MEDIA_LOG ("Initializing drive %s", priv->block_path);
+ g_thread_join (priv->probe);
+ priv->probe = NULL;
/* Put HAL initialization first to make sure the device path is set */
brasero_drive_init_hal (drive);
@@ -838,6 +825,208 @@ brasero_drive_init_real (BraseroDrive *drive)
drive);
brasero_drive_check_medium_inside_gdrive (drive);
+
+ priv->probe_id = 0;
+ return FALSE;
+}
+
+static gboolean
+brasero_drive_get_caps_profiles (BraseroDrive *self,
+ BraseroDeviceHandle *handle,
+ BraseroScsiErrCode *code)
+{
+ BraseroScsiGetConfigHdr *hdr = NULL;
+ BraseroScsiProfileDesc *profiles;
+ BraseroScsiFeatureDesc *desc;
+ BraseroDrivePrivate *priv;
+ BraseroScsiResult result;
+ int profiles_num;
+ int size;
+
+ priv = BRASERO_DRIVE_PRIVATE (self);
+
+ BRASERO_MEDIA_LOG ("Checking supported profiles");
+ result = brasero_mmc2_get_configuration_feature (handle,
+ BRASERO_SCSI_FEAT_PROFILES,
+ &hdr,
+ &size,
+ code);
+ if (result != BRASERO_SCSI_OK) {
+ BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
+ return FALSE;
+ }
+
+ /* Go through all features available */
+ desc = hdr->desc;
+ profiles = (BraseroScsiProfileDesc *) desc->data;
+ profiles_num = desc->add_len / sizeof (BraseroScsiProfileDesc);
+
+ while (profiles_num) {
+ switch (BRASERO_GET_16 (profiles->number)) {
+ case BRASERO_SCSI_PROF_CDR:
+ priv->caps |= BRASERO_DRIVE_CAPS_CDR;
+ break;
+ case BRASERO_SCSI_PROF_CDRW:
+ priv->caps |= BRASERO_DRIVE_CAPS_CDRW;
+ break;
+ case BRASERO_SCSI_PROF_DVD_R:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDR;
+ break;
+ case BRASERO_SCSI_PROF_DVD_RW_SEQUENTIAL:
+ case BRASERO_SCSI_PROF_DVD_RW_RESTRICTED:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDRW;
+ break;
+ case BRASERO_SCSI_PROF_DVD_RAM:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDRAM;
+ break;
+ case BRASERO_SCSI_PROF_DVD_R_PLUS_DL:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS_DL;
+ break;
+ case BRASERO_SCSI_PROF_DVD_RW_PLUS_DL:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL;
+ break;
+ case BRASERO_SCSI_PROF_DVD_R_PLUS:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS;
+ break;
+ case BRASERO_SCSI_PROF_DVD_RW_PLUS:
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS;
+ break;
+ case BRASERO_SCSI_PROF_BR_R_SEQUENTIAL:
+ case BRASERO_SCSI_PROF_BR_R_RANDOM:
+ priv->caps |= BRASERO_DRIVE_CAPS_BDR;
+ break;
+ case BRASERO_SCSI_PROF_BD_RW:
+ priv->caps |= BRASERO_DRIVE_CAPS_BDRW;
+ break;
+ default:
+ break;
+ }
+
+ if (priv->probe_cancelled)
+ break;
+
+ /* Move the pointer to the next features */
+ profiles ++;
+ profiles_num --;
+ }
+
+ g_free (hdr);
+ return TRUE;
+}
+
+static void
+brasero_drive_get_caps_2A (BraseroDrive *self,
+ BraseroDeviceHandle *handle,
+ BraseroScsiErrCode *code)
+{
+ BraseroScsiStatusPage *page_2A = NULL;
+ BraseroScsiModeData *data = NULL;
+ BraseroDrivePrivate *priv;
+ BraseroScsiResult result;
+ int size = 0;
+
+ priv = BRASERO_DRIVE_PRIVATE (self);
+
+ result = brasero_spc1_mode_sense_get_page (handle,
+ BRASERO_SPC_PAGE_STATUS,
+ &data,
+ &size,
+ code);
+ if (result != BRASERO_SCSI_OK) {
+ BRASERO_MEDIA_LOG ("MODE SENSE failed");
+ return;
+ }
+
+ page_2A = (BraseroScsiStatusPage *) &data->page;
+
+ if (page_2A->wr_CDR != 0)
+ priv->caps |= BRASERO_DRIVE_CAPS_CDR;
+ if (page_2A->wr_CDRW != 0)
+ priv->caps |= BRASERO_DRIVE_CAPS_CDRW;
+ if (page_2A->wr_DVDR != 0)
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDR;
+ if (page_2A->wr_DVDRAM != 0)
+ priv->caps |= BRASERO_DRIVE_CAPS_DVDRAM;
+
+ g_free (data);
+}
+
+static gpointer
+brasero_drive_probe_thread (gpointer data)
+{
+ gint counter = 0;
+ const gchar *path;
+ BraseroScsiErrCode code;
+ BraseroDrivePrivate *priv;
+ BraseroDeviceHandle *handle;
+ BraseroDrive *drive = BRASERO_DRIVE (data);
+
+ priv = BRASERO_DRIVE_PRIVATE (drive);
+ path = brasero_drive_get_device (drive);
+ if (!path)
+ path = brasero_drive_get_block_device (drive);
+
+ /* the drive might be busy (a burning is going on) so we don't block
+ * but we re-try to open it every second */
+ BRASERO_MEDIA_LOG ("Trying to open device %s", path);
+
+ handle = brasero_device_handle_open (path, FALSE, &code);
+ while (!handle && counter <= BRASERO_DRIVE_OPEN_ATTEMPTS) {
+ sleep (1);
+
+ if (priv->probe_cancelled) {
+ BRASERO_MEDIA_LOG ("Open () cancelled");
+ priv->probe = NULL;
+ return NULL;
+ }
+
+ counter ++;
+ handle = brasero_device_handle_open (path, FALSE, &code);
+ }
+
+ if (priv->probe_cancelled) {
+ BRASERO_MEDIA_LOG ("Open () cancelled");
+ priv->probe = NULL;
+ return NULL;
+ }
+
+ if (handle) {
+ BRASERO_MEDIA_LOG ("Open () succeeded");
+
+ if (!brasero_drive_get_caps_profiles (drive, handle, &code))
+ brasero_drive_get_caps_2A (drive, handle, &code);
+
+ brasero_device_handle_close (handle);
+
+ BRASERO_MEDIA_LOG ("Drive caps are %d", priv->caps);
+ }
+ else
+ BRASERO_MEDIA_LOG ("Open () failed: medium busy");
+
+ priv->probe_id = g_idle_add (brasero_drive_probed, drive);
+ return NULL;
+}
+
+static void
+brasero_drive_init_real (BraseroDrive *drive)
+{
+ BraseroDrivePrivate *priv;
+
+ priv = BRASERO_DRIVE_PRIVATE (drive);
+
+ priv->block_path = g_drive_get_identifier (priv->gdrive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+
+ BRASERO_MEDIA_LOG ("Initializing drive %s", priv->block_path);
+
+ /* NOTE: why a thread? Because in case of a damaged medium, brasero can
+ * block on some functions until timeout and if we do this in the main
+ * thread then our whole UI blocks. This medium won't be exported by the
+ * BraseroDrive that exported until it returns PROBED signal.
+ * One (good) side effect is that it also improves start time. */
+ priv->probe = g_thread_create (brasero_drive_probe_thread,
+ drive,
+ TRUE,
+ NULL);
}
static void
@@ -907,6 +1096,17 @@ brasero_drive_finalize (GObject *object)
priv = BRASERO_DRIVE_PRIVATE (object);
+ if (priv->probe) {
+ priv->probe_cancelled = TRUE;
+ g_thread_join (priv->probe);
+ priv->probe = 0;
+ }
+
+ if (priv->probe_id) {
+ g_source_remove (priv->probe_id);
+ priv->probe_id = 0;
+ }
+
if (priv->path) {
libhal_free_string (priv->path);
priv->path = NULL;
diff --git a/libbrasero-media/brasero-drive.h b/libbrasero-media/brasero-drive.h
index 7d786a3..3888680 100644
--- a/libbrasero-media/brasero-drive.h
+++ b/libbrasero-media/brasero-drive.h
@@ -48,7 +48,7 @@ typedef enum {
BRASERO_DRIVE_CAPS_DVDRW_PLUS = 1 << 5,
BRASERO_DRIVE_CAPS_DVDR_PLUS_DL = 1 << 6,
BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL = 1 << 7,
- BRASERO_DRIVE_CAPS_DVDRAM = 1 << 9,
+ BRASERO_DRIVE_CAPS_DVDRAM = 1 << 10,
BRASERO_DRIVE_CAPS_BDR = 1 << 8,
BRASERO_DRIVE_CAPS_BDRW = 1 << 9
} BraseroDriveCaps;
diff --git a/libbrasero-media/scsi-get-configuration.h b/libbrasero-media/scsi-get-configuration.h
index e50944b..3cf1f89 100644
--- a/libbrasero-media/scsi-get-configuration.h
+++ b/libbrasero-media/scsi-get-configuration.h
@@ -131,8 +131,8 @@ BRASERO_SCSI_FEAT_LAYER_JUMP = 0x0033,
BRASERO_SCSI_FEAT_WRT_CDRW = 0x0037,
BRASERO_SCSI_FEAT_BDR_POW = 0x0038,
/* reserved */
-BRASERO_SCSI_FEAT_WRT_DVDRW_DL = 0x003A,
-BRASERO_SCSI_FEAT_WRT_DVD_DL = 0x003B,
+BRASERO_SCSI_FEAT_WRT_DVDRW_PLUS_DL = 0x003A,
+BRASERO_SCSI_FEAT_WRT_DVDR_PLUS_DL = 0x003B,
/* reserved */
BRASERO_SCSI_FEAT_RD_BD = 0x0040,
BRASERO_SCSI_FEAT_WRT_BD = 0x0041,
diff --git a/libbrasero-media/scsi-sg.c b/libbrasero-media/scsi-sg.c
index 0029077..c8362c1 100644
--- a/libbrasero-media/scsi-sg.c
+++ b/libbrasero-media/scsi-sg.c
@@ -174,8 +174,10 @@ brasero_device_handle_open (const gchar *path,
if (exclusive)
flags |= O_EXCL;
+ BRASERO_MEDIA_LOG ("Getting handle");
fd = open (path, flags);
if (fd < 0) {
+ BRASERO_MEDIA_LOG ("No handle: %s", strerror (errno));
if (code) {
if (errno == EAGAIN
|| errno == EWOULDBLOCK
@@ -191,6 +193,7 @@ brasero_device_handle_open (const gchar *path,
handle = g_new (BraseroDeviceHandle, 1);
handle->fd = fd;
+ BRASERO_MEDIA_LOG ("Handle ready");
return handle;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]