[brasero] Reworked and hopefully enhanced drive and medium probing code.



commit ad3f8527ec926706f0d03247579895aec119bf18
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Wed Sep 9 16:08:26 2009 +0200

    Reworked and hopefully enhanced drive and medium probing code.
    Use a mutex when probing drive
    Don't rely any more on GIO when checking whether a medium is inside

 libbrasero-media/brasero-drive.c          |  464 +++++++++++++++++++----------
 libbrasero-media/brasero-medium.c         |   16 +-
 libbrasero-media/scsi-error.c             |    4 +
 libbrasero-media/scsi-error.h             |    1 +
 libbrasero-media/scsi-get-configuration.h |    1 +
 libbrasero-media/scsi-sense-data.c        |    6 +
 6 files changed, 339 insertions(+), 153 deletions(-)
---
diff --git a/libbrasero-media/brasero-drive.c b/libbrasero-media/brasero-drive.c
index 4a6a37d..08ab4e7 100644
--- a/libbrasero-media/brasero-drive.c
+++ b/libbrasero-media/brasero-drive.c
@@ -70,6 +70,8 @@ struct _BraseroDrivePrivate
 	GDrive *gdrive;
 
 	GThread *probe;
+	GMutex *mutex;
+	GCond *cond;
 	gint probe_id;
 
 	BraseroMedium *medium;
@@ -85,6 +87,7 @@ struct _BraseroDrivePrivate
 	GCancellable *cancel;
 
 	guint probed:1;
+	guint has_medium:1;
 	guint probe_cancelled:1;
 };
 
@@ -225,7 +228,7 @@ brasero_drive_eject (BraseroDrive *drive,
 			return TRUE;
 	}
 	else
-		BRASERO_BURN_LOG ("No GDrive");
+		BRASERO_MEDIA_LOG ("No GDrive");
 
 	if (!priv->medium)
 		return FALSE;
@@ -712,15 +715,6 @@ brasero_drive_can_write (BraseroDrive *drive)
 }
 
 static void
-brasero_drive_init (BraseroDrive *object)
-{
-	BraseroDrivePrivate *priv;
-
-	priv = BRASERO_DRIVE_PRIVATE (object);
-	priv->cancel = g_cancellable_new ();
-}
-
-static void
 brasero_drive_medium_probed (BraseroMedium *medium,
 			     BraseroDrive *self)
 {
@@ -731,6 +725,13 @@ brasero_drive_medium_probed (BraseroMedium *medium,
 	/* only when it is probed */
 	/* NOTE: BraseroMedium calls GDK_THREADS_ENTER/LEAVE() around g_signal_emit () */
 	priv->probed = TRUE;
+
+	if (brasero_medium_get_status (priv->medium) == BRASERO_MEDIUM_NONE) {
+		g_object_unref (priv->medium);
+		priv->medium = NULL;
+		return;
+	}
+
 	g_signal_emit (self,
 		       drive_signals [MEDIUM_INSERTED],
 		       0,
@@ -752,75 +753,25 @@ brasero_drive_probing (BraseroDrive *drive)
 	return priv->probed != TRUE;
 }
 
-/**
- * brasero_drive_reprobe:
- * @drive: a #BraseroDrive
- *
- * Reprobes the drive contents. Useful when an operation has just been performed
- * (blanking, burning, ...) and medium status should be updated.
- *
- * NOTE: This operation does not block.
- *
- **/
-
-void
-brasero_drive_reprobe (BraseroDrive *drive)
-{
-	BraseroDrivePrivate *priv;
-	BraseroMedium *medium;
-
-	g_return_if_fail (drive != NULL);
-	g_return_if_fail (BRASERO_IS_DRIVE (drive));
-
-	priv = BRASERO_DRIVE_PRIVATE (drive);
-
-	if (priv->gdrive) {
-		/* reprobe the contents of the drive system wide */
-		g_drive_poll_for_media (priv->gdrive, NULL, NULL, NULL);
-	}
-
-	if (!priv->medium)
-		return;
-
-	BRASERO_MEDIA_LOG ("Reprobing inserted medium");
-
-	/* remove current medium */
-	medium = priv->medium;
-	priv->medium = NULL;
-
-	g_signal_emit (drive,
-		       drive_signals [MEDIUM_REMOVED],
-		       0,
-		       medium);
-	g_object_unref (medium);
-	priv->probed = FALSE;
-
-	/* try to get a new one */
-	priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
-				     "drive", drive,
-				     NULL);
-	g_signal_connect (priv->medium,
-			  "probed",
-			  G_CALLBACK (brasero_drive_medium_probed),
-			  drive);
-}
-
-static void
-brasero_drive_check_medium_inside_gdrive (BraseroDrive *self)
+static gboolean
+brasero_drive_probed_inside (gpointer data)
 {
+	BraseroDrive *self;
 	BraseroDrivePrivate *priv;
 
+	self = BRASERO_DRIVE (data);
 	priv = BRASERO_DRIVE_PRIVATE (self);
 
-	BRASERO_MEDIA_LOG ("Contents changed %i", g_drive_has_media (priv->gdrive));
+	g_mutex_lock (priv->mutex);
+	priv->probe_id = 0;
+	g_mutex_unlock (priv->mutex);
 
-	if (g_drive_has_media (priv->gdrive)) {
+	if (priv->has_medium) {
 		if (priv->medium)
-			return;
+			return FALSE;
 
 		BRASERO_MEDIA_LOG ("Medium inserted");
 
-		priv->probed = FALSE;
 		priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
 					     "drive", self,
 					     NULL);
@@ -842,35 +793,211 @@ brasero_drive_check_medium_inside_gdrive (BraseroDrive *self)
 			       drive_signals [MEDIUM_REMOVED],
 			       0,
 			       medium);
+
 		g_object_unref (medium);
 		priv->probed = TRUE;
 	}
 	else
 		priv->probed = TRUE;
+
+	return FALSE;
+}
+
+static gpointer
+brasero_drive_probe_inside_thread (gpointer data)
+{
+	gint counter = 0;
+	const gchar *device;
+	BraseroScsiErrCode code;
+	BraseroDrivePrivate *priv;
+	BraseroDeviceHandle *handle;
+	BraseroDrive *drive = BRASERO_DRIVE (data);
+
+	priv = BRASERO_DRIVE_PRIVATE (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 */
+	device = brasero_drive_get_device (drive);
+	BRASERO_MEDIA_LOG ("Trying to open device %s", device);
+
+	handle = brasero_device_handle_open (device, FALSE, &code);
+	while (!handle && counter <= BRASERO_DRIVE_OPEN_ATTEMPTS) {
+		sleep (1);
+
+		if (priv->probe_cancelled) {
+			BRASERO_MEDIA_LOG ("Open () cancelled");
+			goto end;
+		}
+
+		counter ++;
+		handle = brasero_device_handle_open (device, FALSE, &code);
+	}
+
+	if (priv->probe_cancelled) {
+		BRASERO_MEDIA_LOG ("Open () cancelled");
+		goto end;
+	}
+
+	if (!handle) {
+		BRASERO_MEDIA_LOG ("Open () failed: medium busy");
+		goto end;
+	}
+
+	while (brasero_spc1_test_unit_ready (handle, &code) != BRASERO_SCSI_OK) {
+		if (code == BRASERO_SCSI_NO_MEDIUM) {
+			BRASERO_MEDIA_LOG ("No medium inserted");
+
+			priv->has_medium = FALSE;
+			goto end;
+		}
+
+		if (code != BRASERO_SCSI_NOT_READY) {
+			brasero_device_handle_close (handle);
+			BRASERO_MEDIA_LOG ("Device does not respond");
+			goto end;
+		}
+
+		sleep (2);
+
+		if (priv->probe_cancelled) {
+			brasero_device_handle_close (handle);
+			BRASERO_MEDIA_LOG ("Device probing cancelled");
+			goto end;
+		}
+	}
+
+	BRASERO_MEDIA_LOG ("Medium inserted");
+	brasero_device_handle_close (handle);
+
+	priv->has_medium = TRUE;
+
+end:
+
+	g_mutex_lock (priv->mutex);
+
+	if (!priv->probe_cancelled)
+		priv->probe_id = g_idle_add (brasero_drive_probed_inside, drive);
+
+	priv->probe = NULL;
+	g_cond_broadcast (priv->cond);
+	g_mutex_unlock (priv->mutex);
+
+	g_thread_exit (0);
+
+	return NULL;
+}
+
+static void
+brasero_drive_probe_inside (BraseroDrive *drive)
+{
+	BraseroDrivePrivate *priv;
+
+	priv = BRASERO_DRIVE_PRIVATE (drive);
+
+	priv->probed = FALSE;
+
+	/* Check that a probe is not already being performed */
+	g_mutex_lock (priv->mutex);
+	if (!priv->probe) {
+		BRASERO_MEDIA_LOG ("Setting new probe");
+
+		if (priv->probe_id) {
+			/* Remove the result reporting as
+			 * the status seem to have changed */
+			g_source_remove (priv->probe_id);
+			priv->probe_id = 0;
+		}
+
+		priv->probe = g_thread_create (brasero_drive_probe_inside_thread,
+					       drive,
+					       FALSE,
+					       NULL);
+	}
+	else
+		BRASERO_MEDIA_LOG ("Ongoing probe");
+	g_mutex_unlock (priv->mutex);
 }
 
 static void
 brasero_drive_medium_gdrive_changed_cb (BraseroDrive *gdrive,
 					BraseroDrive *drive)
 {
-	brasero_drive_check_medium_inside_gdrive (drive);
+	brasero_drive_probe_inside (drive);
 }
 
 static void
-brasero_drive_update_gdrive (BraseroDrive *drive)
+brasero_drive_update_gdrive (BraseroDrive *drive,
+                             GDrive *gdrive)
 {
 	BraseroDrivePrivate *priv;
 
 	priv = BRASERO_DRIVE_PRIVATE (drive);
+	if (priv->gdrive) {
+		g_signal_handlers_disconnect_by_func (priv->gdrive,
+						      brasero_drive_medium_gdrive_changed_cb,
+						      drive);
+		g_object_unref (priv->gdrive);
+	}
 
-	/* If it's not a fake drive then connect to signal for any
-	 * change and check medium inside */
-	g_signal_connect (priv->gdrive,
-			  "changed",
-			  G_CALLBACK (brasero_drive_medium_gdrive_changed_cb),
-			  drive);
+	BRASERO_MEDIA_LOG ("Setting GDrive %p", gdrive);
 
-	brasero_drive_check_medium_inside_gdrive (drive);
+	if (gdrive) {
+		priv->gdrive = g_object_ref (gdrive);
+
+		/* If it's not a fake drive then connect to signal for any
+		 * change and check medium inside */
+		g_signal_connect (priv->gdrive,
+				  "changed",
+				  G_CALLBACK (brasero_drive_medium_gdrive_changed_cb),
+				  drive);
+	}
+
+	brasero_drive_probe_inside (drive);
+}
+
+/**
+ * brasero_drive_reprobe:
+ * @drive: a #BraseroDrive
+ *
+ * Reprobes the drive contents. Useful when an operation has just been performed
+ * (blanking, burning, ...) and medium status should be updated.
+ *
+ * NOTE: This operation does not block.
+ *
+ **/
+
+void
+brasero_drive_reprobe (BraseroDrive *drive)
+{
+	BraseroDrivePrivate *priv;
+	BraseroMedium *medium;
+
+	g_return_if_fail (drive != NULL);
+	g_return_if_fail (BRASERO_IS_DRIVE (drive));
+
+	priv = BRASERO_DRIVE_PRIVATE (drive);
+
+	if (priv->gdrive) {
+		/* reprobe the contents of the drive system wide */
+		g_drive_poll_for_media (priv->gdrive, NULL, NULL, NULL);
+	}
+
+	if (!priv->medium)
+		return;
+
+	BRASERO_MEDIA_LOG ("Reprobing inserted medium");
+
+	/* remove current medium */
+	medium = priv->medium;
+	priv->medium = NULL;
+
+	g_signal_emit (drive,
+		       drive_signals [MEDIUM_REMOVED],
+		       0,
+		       medium);
+	g_object_unref (medium);
+
+	brasero_drive_probe_inside (drive);
 }
 
 static gboolean
@@ -880,9 +1007,11 @@ brasero_drive_probed (gpointer data)
 
 	priv = BRASERO_DRIVE_PRIVATE (data);
 
-	g_thread_join (priv->probe);
-	priv->probe = NULL;
+	g_mutex_lock (priv->mutex);
 	priv->probe_id = 0;
+	g_mutex_unlock (priv->mutex);
+
+	brasero_drive_probe_inside (BRASERO_DRIVE (data));
 
 	return FALSE;
 }
@@ -1015,6 +1144,8 @@ brasero_drive_probe_thread (gpointer data)
 {
 	gint counter = 0;
 	const gchar *device;
+	BraseroScsiResult res;
+	BraseroScsiInquiry hdr;
 	BraseroScsiErrCode code;
 	BraseroDrivePrivate *priv;
 	BraseroDeviceHandle *handle;
@@ -1033,8 +1164,7 @@ brasero_drive_probe_thread (gpointer data)
 
 		if (priv->probe_cancelled) {
 			BRASERO_MEDIA_LOG ("Open () cancelled");
-			priv->probe = NULL;
-			return NULL;
+			goto end;
 		}
 
 		counter ++;
@@ -1043,56 +1173,86 @@ brasero_drive_probe_thread (gpointer data)
 
 	if (priv->probe_cancelled) {
 		BRASERO_MEDIA_LOG ("Open () cancelled");
-		priv->probe = NULL;
-		return NULL;
+		goto end;
 	}
 
-	if (handle) {
-		BraseroScsiInquiry hdr;
-		BraseroScsiResult res;
-
-		BRASERO_MEDIA_LOG ("Open () succeeded");
-
-		/* get additional information like the name */
-		res = brasero_spc1_inquiry (handle, &hdr, NULL);
-		if (res == BRASERO_SCSI_OK) {
-			gchar *name_utf8;
-			gchar *vendor;
-			gchar *model;
-			gchar *name;
-
-			vendor = g_strndup ((gchar *) hdr.vendor, sizeof (hdr.vendor));
-			model = g_strndup ((gchar *) hdr.name, sizeof (hdr.name));
-			name = g_strdup_printf ("%s %s", g_strstrip (vendor), g_strstrip (model));
-			g_free (vendor);
-			g_free (model);
-
-			/* make sure that's proper UTF-8 */
-			name_utf8 = g_convert_with_fallback (name,
-			                                     -1,
-			                                     "ASCII",
-			                                     "UTF-8",
-			                                     "_",
-			                                     NULL,
-			                                     NULL,
-			                                     NULL);
-			g_free (name);
-
-			priv->name = name_utf8;
+	if (!handle) {
+		BRASERO_MEDIA_LOG ("Open () failed: medium busy");
+		goto end;
+	}
+
+	while (brasero_spc1_test_unit_ready (handle, &code) != BRASERO_SCSI_OK) {
+		if (code == BRASERO_SCSI_NO_MEDIUM) {
+			BRASERO_MEDIA_LOG ("No medium inserted");
+			break;
 		}
 
-		/* Get supported medium types */
-		if (!brasero_drive_get_caps_profiles (drive, handle, &code))
-			brasero_drive_get_caps_2A (drive, handle, &code);
+		if (code != BRASERO_SCSI_NOT_READY) {
+			brasero_device_handle_close (handle);
+			BRASERO_MEDIA_LOG ("Device does not respond");
+			goto end;
+		}
 
-		brasero_device_handle_close (handle);
+		sleep (2);
 
-		BRASERO_MEDIA_LOG ("Drive caps are %d", priv->caps);
+		if (priv->probe_cancelled) {
+			brasero_device_handle_close (handle);
+			BRASERO_MEDIA_LOG ("Device probing cancelled");
+			goto end;
+		}
 	}
-	else
-		BRASERO_MEDIA_LOG ("Open () failed: medium busy");
 
-	priv->probe_id = g_idle_add (brasero_drive_probed, drive);
+	BRASERO_MEDIA_LOG ("Device ready");
+
+	/* get additional information like the name */
+	res = brasero_spc1_inquiry (handle, &hdr, NULL);
+	if (res == BRASERO_SCSI_OK) {
+		gchar *name_utf8;
+		gchar *vendor;
+		gchar *model;
+		gchar *name;
+
+		vendor = g_strndup ((gchar *) hdr.vendor, sizeof (hdr.vendor));
+		model = g_strndup ((gchar *) hdr.name, sizeof (hdr.name));
+		name = g_strdup_printf ("%s %s", g_strstrip (vendor), g_strstrip (model));
+		g_free (vendor);
+		g_free (model);
+
+		/* make sure that's proper UTF-8 */
+		name_utf8 = g_convert_with_fallback (name,
+		                                     -1,
+		                                     "ASCII",
+		                                     "UTF-8",
+		                                     "_",
+		                                     NULL,
+		                                     NULL,
+		                                     NULL);
+		g_free (name);
+
+		priv->name = name_utf8;
+	}
+
+	/* Get supported medium types */
+	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);
+
+end:
+
+	g_mutex_lock (priv->mutex);
+
+	if (!priv->probe_cancelled)
+		priv->probe_id = g_idle_add (brasero_drive_probed, drive);
+
+	priv->probe = NULL;
+	g_cond_broadcast (priv->cond);
+	g_mutex_unlock (priv->mutex);
+
+	g_thread_exit (0);
+
 	return NULL;
 }
 
@@ -1121,10 +1281,12 @@ brasero_drive_init_real_device (BraseroDrive *drive,
 	 * 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. */
+	g_mutex_lock (priv->mutex);
 	priv->probe = g_thread_create (brasero_drive_probe_thread,
 				       drive,
-				       TRUE,
+				       FALSE,
 				       NULL);
+	g_mutex_unlock (priv->mutex);
 }
 
 static void
@@ -1149,30 +1311,7 @@ brasero_drive_set_property (GObject *object,
 			break;
 
 		gdrive = g_value_get_object (value);
-		if (priv->gdrive) {
-			g_signal_handlers_disconnect_by_func (priv->gdrive,
-							      brasero_drive_medium_gdrive_changed_cb,
-							      object);
-			g_object_unref (priv->gdrive);
-		}
-
-		BRASERO_MEDIA_LOG ("Setting GDrive %p", gdrive);
-
-		if (gdrive) {
-			priv->gdrive = g_object_ref (gdrive);
-			brasero_drive_update_gdrive (BRASERO_DRIVE (object));
-		}
-		else if (!priv->medium) {
-			priv->probed = FALSE;
-			priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
-						     "drive", object,
-						     NULL);
-
-			g_signal_connect (priv->medium,
-					  "probed",
-					  G_CALLBACK (brasero_drive_medium_probed),
-					  object);
-		}
+		brasero_drive_update_gdrive (BRASERO_DRIVE (object), gdrive);
 		break;
 	case PROP_DEVICE:
 		if (!g_value_get_string (value)) {
@@ -1219,6 +1358,18 @@ brasero_drive_get_property (GObject *object,
 }
 
 static void
+brasero_drive_init (BraseroDrive *object)
+{
+	BraseroDrivePrivate *priv;
+
+	priv = BRASERO_DRIVE_PRIVATE (object);
+	priv->cancel = g_cancellable_new ();
+
+	priv->mutex = g_mutex_new ();
+	priv->cond = g_cond_new ();
+}
+
+static void
 brasero_drive_finalize (GObject *object)
 {
 	BraseroDrivePrivate *priv;
@@ -1227,17 +1378,28 @@ brasero_drive_finalize (GObject *object)
 
 	BRASERO_MEDIA_LOG ("Finalizing BraseroDrive");
 
+	g_mutex_lock (priv->mutex);
 	if (priv->probe) {
 		priv->probe_cancelled = TRUE;
-		g_thread_join (priv->probe);
-		priv->probe = 0;
+		g_cond_wait (priv->cond, priv->mutex);
 	}
+	g_mutex_unlock (priv->mutex);
 
 	if (priv->probe_id) {
 		g_source_remove (priv->probe_id);
 		priv->probe_id = 0;
 	}
 
+	if (priv->mutex) {
+		g_mutex_free (priv->mutex);
+		priv->mutex = NULL;
+	}
+
+	if (priv->cond) {
+		g_cond_free (priv->cond);
+		priv->cond = NULL;
+	}
+
 	if (priv->medium) {
 		g_signal_emit (object,
 			       drive_signals [MEDIUM_REMOVED],
diff --git a/libbrasero-media/brasero-medium.c b/libbrasero-media/brasero-medium.c
index 65eabc1..46762d4 100644
--- a/libbrasero-media/brasero-medium.c
+++ b/libbrasero-media/brasero-medium.c
@@ -2325,8 +2325,10 @@ brasero_medium_get_medium_type (BraseroMedium *self,
 
 		/* If this fails it means that this drive is probably older than
 		 * MMC1 spec or does not conform to it. */
-		if (result != TRUE)
+		if (result != TRUE) {
+			priv->info = BRASERO_MEDIUM_NONE;
 			return FALSE;
+		}
 
 		/* The only thing here left to determine is if that's a WRITABLE
 		 * or a REWRITABLE. To determine that information, we need to
@@ -2370,6 +2372,10 @@ brasero_medium_get_medium_type (BraseroMedium *self,
 	}
 
 	switch (profile) {
+	case BRASERO_SCSI_PROF_EMPTY:
+		priv->info = BRASERO_MEDIUM_NONE;
+		return FALSE;
+
 	case BRASERO_SCSI_PROF_CDROM:
 		priv->info = BRASERO_MEDIUM_CDROM;
 		priv->type = types [1];
@@ -2981,7 +2987,13 @@ brasero_medium_probe_thread (gpointer self)
 		/* NOTE: if we wanted to know the status we'd need to read the 
 		 * error code variable which is currently NULL */
 		while (brasero_spc1_test_unit_ready (handle, &code) != BRASERO_SCSI_OK) {
-			if (code != BRASERO_SCSI_NOT_READY) {
+			if (code == BRASERO_SCSI_NO_MEDIUM) {
+				brasero_device_handle_close (handle);
+				BRASERO_MEDIA_LOG ("No medium inserted");
+				priv->info = BRASERO_MEDIUM_NONE;
+				goto end;
+			}
+			else if (code != BRASERO_SCSI_NOT_READY) {
 				brasero_device_handle_close (handle);
 				BRASERO_MEDIA_LOG ("Device does not respond");
 				goto end;
diff --git a/libbrasero-media/scsi-error.c b/libbrasero-media/scsi-error.c
index 7edae5f..3358544 100644
--- a/libbrasero-media/scsi-error.c
+++ b/libbrasero-media/scsi-error.c
@@ -61,6 +61,10 @@ brasero_scsi_strerror (BraseroScsiErrCode code)
 	if (code > BRASERO_SCSI_ERROR_LAST || code < 0)
 		return NULL;
 
+	/* FIXME: this is for errors that don't have any message yet */
+	if (code > BRASERO_SCSI_ERRNO)
+		return NULL;
+
 	if (code == BRASERO_SCSI_ERRNO)
 		return g_strerror (errno);
 
diff --git a/libbrasero-media/scsi-error.h b/libbrasero-media/scsi-error.h
index 61d744a..73b768b 100644
--- a/libbrasero-media/scsi-error.h
+++ b/libbrasero-media/scsi-error.h
@@ -59,6 +59,7 @@ typedef enum {
 	BRASERO_SCSI_KEY_NOT_ESTABLISHED,
 	BRASERO_SCSI_INVALID_TRACK_MODE,
 	BRASERO_SCSI_ERRNO,
+	BRASERO_SCSI_NO_MEDIUM,
 	BRASERO_SCSI_ERROR_LAST
 } BraseroScsiErrCode;
 
diff --git a/libbrasero-media/scsi-get-configuration.h b/libbrasero-media/scsi-get-configuration.h
index 3cf1f89..b7fe7b1 100644
--- a/libbrasero-media/scsi-get-configuration.h
+++ b/libbrasero-media/scsi-get-configuration.h
@@ -38,6 +38,7 @@
 G_BEGIN_DECLS
 
 typedef enum {
+BRASERO_SCSI_PROF_EMPTY				= 0x0000,
 BRASERO_SCSI_PROF_NON_REMOVABLE		= 0x0001,
 BRASERO_SCSI_PROF_REMOVABLE		= 0x0002,
 BRASERO_SCSI_PROF_MO_ERASABLE		= 0x0003,
diff --git a/libbrasero-media/scsi-sense-data.c b/libbrasero-media/scsi-sense-data.c
index e88e89d..633e91d 100644
--- a/libbrasero-media/scsi-sense-data.c
+++ b/libbrasero-media/scsi-sense-data.c
@@ -57,6 +57,7 @@
 #define SENSE_CODE_UNIT_ATTENTION			0x06
 
 #define ASC_CODE_NOT_READY				0x04
+#define ASC_CODE_NO_MEDIUM			0x3A
 #define ASC_CODE_PARAMETER				0x26
 #define ASC_CODE_PROTECTION_KEY				0x6F
 
@@ -110,6 +111,11 @@ brasero_sense_data_not_ready (uchar *sense_data, BraseroScsiErrCode *err)
 	BraseroScsiResult res = BRASERO_SCSI_FAILURE;
 
 	switch (SENSE_DATA_ASC (sense_data)) {
+		case ASC_CODE_NO_MEDIUM:
+			/* No need to use BRASERO_SCSI_SET_ERRCODE
+			 * as this is not necessarily an error */
+			*err = BRASERO_SCSI_NO_MEDIUM;
+			break;
 		case ASC_CODE_NOT_READY:
 			BRASERO_SCSI_SET_ERRCODE (err, BRASERO_SCSI_NOT_READY);
 			break;



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