#!/usr/bin/perl
# This decodes the cartridge memory on LTO tapes
# Robin H. Johnson <robbat2@gentoo.org>
# Usage:
# sg_raw -o - -r 1024 -t 60 -v /dev/nst0 8c 00 00 00 00 00 00 00  00 00 00 00 04 00 00 00 | ./read_attribute.pl -
use strict;
use warnings;
sub decode_id {
	my $id = shift;
	my $s;
	$s = 'Reserved'   if ( ($id >> 8) >= 0x18) ;
	$s = 'Host (vendor-specific)'   if ( ($id >> 8) < 0x18) ;
	$s = 'Medium (vendor-specific)' if ( ($id >> 8) < 0x14) ;
	$s = 'Device (vendor-specific)' if ( ($id >> 8) < 0x10) ;
	$s = 'Medium' if ( ($id >> 8) < 0x08) ;
	$s = 'Host'   if ( ($id >> 8) < 0x0C) ;
	$s = 'Device' if ( ($id >> 8) < 0x04) ;
	my %ATTRIBUTES = (
	0x0000 => "Remaining Capacity in Partition (MB)",
	0x0001 => "Maximum Capacity in Partition (MB)",
	0x0002 => "TapeAlert Flags",
	0x0003 => "Load Count",
	0x0004 => "MAM Space Remaining (bytes)",
	0x0005 => "Assigning Organization",
	0x0006 => "Formatted Density Code",
	0x0007 => "Initialization Count (media formatted)",
	0x0008 => "Volume Identifier",
	0x0009 => "Volume Change Reference",
	0x020A => "Device Make/Serial Number at Last Load",
	0x020B => "Device Make/Serial Number at Load - 1",
	0x020C => "Device Make/Serial Number at Load - 2",
	0x020D => "Device Make/Serial Number at Load - 3",
	0x0220 => "Total Megabytes Written in Medium Life",
	0x0221 => "Total Megabytes Read in Medium Life",
	0x0222 => "Total Megabytes Written in Current/Last Load",
	0x0223 => "Total Megabytes Read in Current/Last Load",
	0x0224 => "Logical position of first encrypted block",
	0x0225 => "Logical position of first unencrypted block after the first encrypted block",
	0x0340 => "Medium Usage History",
	0x0341 => "Partition Usage History",
	0x0400 => "Medium Manufacturer",
	0x0401 => "Medium Serial Number",
	0x0402 => "Medium Length",
	0x0403 => "Medium Width",
	0x0404 => "Assigning Organization",
	0x0405 => "Medium Density Code",
	0x0406 => "Medium Manufacture Date (yyyymmdd)",
	0x0407 => "MAM Capacity (bytes)",
	0x0408 => "Medium Type",
	0x0409 => "Medium Type Information",
	0x040A => "Numeric Medium Serial Number",
	0x0801 => "Application Name",
	0x0802 => "Application Version",
	0x0803 => "User Medium Text Label",
	0x0804 => "Date & Time Last Written (yyyymmddhhmm)",
	0x0805 => "Text Localization Identifier",
	0x0806 => "Barcode",
	0x0807 => "Owning Host Textual Name",
	0x0808 => "Media Pool",
	0x0809 => "Partition User Text Label",
	0x080A => "Load/Unload at Partition",
	0x080B => "Application Format Version",
	0x080C => "Volume Coherency Information",
	0x1000 => "Unique Cartridge Identity (UCI)",
	);
	$s .= ': ';
	$s .= (defined $ATTRIBUTES{$id}) ? $ATTRIBUTES{$id} : 'UNKNOWN';
	return $s;
}
sub scsi_read_attribute {
	my $cmd = '8c 00 00 00 00 00 00 00  00 00 00 00 04 00 00 00';
	#$cmd =~ s/ +//g;
	$cmd = pack('H*',$cmd);
	#my ($result, $sense) = $device->execute($command, $wanted);
}


sub decode_read_attribute {
	my $buf = shift;
	my $offset = 0;
	my ($size) = unpack('N', $buf);
	printf("size=%d %x\n", $size, $size);
	$offset += 4;
	while($offset < length($buf)) {
		my ($id, $tmp, $attrlen) = unpack('nCn', substr($buf, $offset, 5));
		my $ro = $tmp >> 7;
		my $format = $tmp & 0x03;
		$offset += 5;
		my $val = substr($buf, $offset, $attrlen);
		printf( "id=0x%04x writable=%s format=%x attrlen=0x%04x=%-5d - %s\n", $id, $ro ? "RO" : "RW", $format, $attrlen, $attrlen, decode_id($id));
		if($format == 0) {
			print "val=",unpack('H*', $val), "\n";
		} elsif($format == 1 || $format == 2) {
			print "val=",unpack('A*', $val), "\n";
		}
		$offset += $attrlen;
	}
}

sub read_file {
	my $filename = shift;
	open FILE, '<', $filename or die "Cannot open $filename";
	binmode FILE;
	my $buf;
	my $filesize = read FILE, $buf, 2**16;
	printf "filesize=%d\n", $filesize;
	return $buf;
}

decode_read_attribute(read_file($ARGV[0]));

# vim:ts=2 sts=2 sw=2 noet:
