diff options
author | Harald Hoyer <harald@redhat.com> | 2010-10-07 17:02:21 +0200 |
---|---|---|
committer | Harald Hoyer <harald@redhat.com> | 2010-10-07 17:43:05 +0200 |
commit | d7cd2b16110c806128747ee245aaa883dd52039d (patch) | |
tree | 17bb6d7c144febf6aa09059d5f5886ea6619e423 /extras/cdrom_id | |
parent | d7628fbfcd04727cfd229c0a8a2f084b8c531ab6 (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/cdrom_id')
-rw-r--r-- | extras/cdrom_id/cdrom_id.c | 81 |
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; } |