summaryrefslogtreecommitdiff
path: root/extras
diff options
context:
space:
mode:
authorHarald Hoyer <harald@redhat.com>2010-10-07 17:02:21 +0200
committerHarald Hoyer <harald@redhat.com>2010-10-07 17:43:05 +0200
commitd7cd2b16110c806128747ee245aaa883dd52039d (patch)
tree17bb6d7c144febf6aa09059d5f5886ea6619e423 /extras
parentd7628fbfcd04727cfd229c0a8a2f084b8c531ab6 (diff)
cdrom_id: request the drive profile features with a dynamic length
Some drives don't like huge feature buffers, so we query twice. First run for the current profile and to get the length. Second time we query the whole profile feature set.
Diffstat (limited to 'extras')
-rw-r--r--extras/cdrom_id/cdrom_id.c81
1 files changed, 53 insertions, 28 deletions
diff --git a/extras/cdrom_id/cdrom_id.c b/extras/cdrom_id/cdrom_id.c
index 1b43fe43ae..ec001cde71 100644
--- a/extras/cdrom_id/cdrom_id.c
+++ b/extras/cdrom_id/cdrom_id.c
@@ -398,12 +398,12 @@ static int cd_profiles(struct udev *udev, int fd)
unsigned int i;
int err;
+ /* First query the current profile */
scsi_cmd_init(udev, &sc, features, sizeof(features));
scsi_cmd_set(udev, &sc, 0, 0x46);
- scsi_cmd_set(udev, &sc, 7, (sizeof(features) >> 8) & 0xff);
- scsi_cmd_set(udev, &sc, 8, sizeof(features) & 0xff);
+ scsi_cmd_set(udev, &sc, 8, 8);
scsi_cmd_set(udev, &sc, 9, 0);
- err = scsi_cmd_run(udev, &sc, fd, features, sizeof(features));
+ err = scsi_cmd_run(udev, &sc, fd, features, 8);
if ((err != 0)) {
info_scsi_cmd_err(udev, "GET CONFIGURATION", err);
/* handle pre-MMC2 drives which do not support GET CONFIGURATION */
@@ -415,31 +415,6 @@ static int cd_profiles(struct udev *udev, int fd)
return -1;
}
- len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3];
- info(udev, "GET CONFIGURATION: size of features buffer 0x%04x\n", len);
-
- if (len > sizeof(features)) {
- info(udev, "can not get features in a single query, truncating\n");
- len = sizeof(features);
- }
-
- /* device features */
- for (i = 8; i+4 < len; i += (4 + features[i+3])) {
- unsigned int feature;
-
- feature = features[i] << 8 | features[i+1];
-
- switch (feature) {
- case 0x00:
- info(udev, "GET CONFIGURATION: feature 'profiles', with %i entries\n", features[i+3] / 4);
- feature_profiles(udev, &features[i]+4, features[i+3]);
- break;
- default:
- info(udev, "GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes\n", feature, features[i+3]);
- break;
- }
- }
-
cur_profile = features[6] << 8 | features[7];
if (cur_profile > 0) {
info(udev, "current profile 0x%02x\n", cur_profile);
@@ -553,6 +528,56 @@ static int cd_profiles(struct udev *udev, int fd)
info(udev, "profile 0x%02x <ignored>\n", cur_profile);
break;
}
+
+
+ len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3];
+ info(udev, "GET CONFIGURATION: size of features buffer 0x%04x\n", len);
+
+ if (len > sizeof(features)) {
+ info(udev, "can not get features in a single query, truncating\n");
+ len = sizeof(features);
+ } else if (len <= 8) {
+ len = sizeof(features);
+ }
+
+ /* Now get the full feature buffer */
+ scsi_cmd_init(udev, &sc, features, len);
+ scsi_cmd_set(udev, &sc, 0, 0x46);
+ scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff);
+ scsi_cmd_set(udev, &sc, 8, len & 0xff);
+ scsi_cmd_set(udev, &sc, 9, 0);
+ err = scsi_cmd_run(udev, &sc, fd, features, len);
+ if ((err != 0)) {
+ info_scsi_cmd_err(udev, "GET CONFIGURATION", err);
+ return -1;
+ }
+
+ /* parse the length once more, in case the drive decided to have other features suddenly :) */
+ len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3];
+ info(udev, "GET CONFIGURATION: size of features buffer 0x%04x\n", len);
+
+ if (len > sizeof(features)) {
+ info(udev, "can not get features in a single query, truncating\n");
+ len = sizeof(features);
+ }
+
+ /* device features */
+ for (i = 8; i+4 < len; i += (4 + features[i+3])) {
+ unsigned int feature;
+
+ feature = features[i] << 8 | features[i+1];
+
+ switch (feature) {
+ case 0x00:
+ info(udev, "GET CONFIGURATION: feature 'profiles', with %i entries\n", features[i+3] / 4);
+ feature_profiles(udev, &features[i]+4, features[i+3]);
+ break;
+ default:
+ info(udev, "GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes\n", feature, features[i+3]);
+ break;
+ }
+ }
+
return 0;
}