\n";
sub _smartctl_needs_type {
my ($out) = @_;
return ($out =~ /Please specify device type with the -d option/i ||
$out =~ /Unknown USB bridge/i);
}
sub _smartctl_no_smart {
my ($out) = @_;
return ($out =~ /Read Device Identity failed/i ||
$out =~ /unsupported scsi opcode/i ||
$out =~ /Device does not support SMART/i ||
$out =~ /SMART support is:\s*Unavailable/i ||
$out =~ /mandatory SMART command failed/i);
}
my $cmd = "smartctl -a " . "e_path($device) . " 2>&1";
my $out = &backquote_command($cmd);
my $used_cmd = $cmd;
my $note;
# If smartctl requests a device type or indicates SMART unsupported, try common USB bridge options
if (_smartctl_needs_type($out) || _smartctl_no_smart($out)) {
my @types = qw(sat,auto sat scsi auto usbjmicron usbprolific usbcypress usbsunplus);
my $best_out = $out;
my $best_cmd = $cmd;
foreach my $t (@types) {
my $try_cmd = "smartctl -a -d $t " . "e_path($device) . " 2>&1";
my $try_out = &backquote_command($try_cmd);
# If it still needs a type, keep trying
if (_smartctl_needs_type($try_out)) {
$best_out = $try_out;
$best_cmd = $try_cmd;
next;
}
# If SMART commands fail, try permissive once
if (_smartctl_no_smart($try_out)) {
my $perm_cmd = "smartctl -a -T permissive -d $t " . "e_path($device) . " 2>&1";
my $perm_out = &backquote_command($perm_cmd);
if (!_smartctl_needs_type($perm_out) && !_smartctl_no_smart($perm_out)) {
$out = $perm_out;
$used_cmd = $perm_cmd;
last;
}
$best_out = $perm_out;
$best_cmd = $perm_cmd;
next;
}
# Success
$out = $try_out;
$used_cmd = $try_cmd;
last;
}
if ($used_cmd eq $cmd) {
$out = $best_out;
$used_cmd = $best_cmd;
if (_smartctl_no_smart($out)) {
$note = "SMART may not be supported by this USB device or bridge.";
}
}
}
if ($note) {
print "
$note
\n";
}
print "
" . &html_escape("Command: $used_cmd\n\n$out") . "\n";
print "