The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Device::SCSI - Perl module to control SCSI devices

VERSION

version 1.004

SYNOPSIS

  use Device::SCSI;

  my @devices = Device::SCSI->enumerate;

  my $device = Device::SCSI->new($devices[0]);
  my %inquiry = %{ $device->inquiry };
  my ($result, $sense) = $device->execute($command, $wanted, $data);
  $device->close;

DESCRIPTION

This Perl library uses Perl5 objects to make it easy to perform low-level SCSI I/O from Perl, avoiding all the black magic and fighting with C. The object-oriented interface allows for the application to use more than one SCSI device simultaneously (although this is more likely to be used by the application to cache the devices it needs in a hash.)

As well as the general purpose execute() method, there are also a number of other helper methods that can aid in querying the device and debugging. Note that the goats and black candles usually required to solve SCSI problems will need to be provided by yourself.

IMPLEMENTATION

Not surprisingly, SCSI varies sufficiently from OS to OS that each one needs to be dealt with separately. This package provides the OS-neutral processing. The OS-specific code is provided in a module under "Device::SCSI::" that has the same name as $^O does on your architecture. The Linux driver is called Device::SCSI::linux, for example.

The generic class is actually made a subclass of the OS-specific class, not the other way round as one might have expected. In other words, it takes the opportunity to select its parent after it has started.

METHODS

new

 $device = Device::SCSI->new;

 $device = Device::SCSI->new($unit_name);

Creates a new SCSI object. If $unit_name is given, it will try to open it. On failure, it returns undef, otherwise the object.

enumerate

 my @units = Device::SCSI->enumerate;

Returns a list of all the unit names that can be given to new() and open(). There is no guarantee that all these devices will be available (indeed, this is unlikely to be the case) and you should iterate over this list, open()ing and inquiry()ing devices until you find the one you want.

open

 $device->open($device_name);

Attempts to open a SCSI device, and returns $device if it can, or undef if it can't. Reasons for not being able to open a device include it not actually existing on your system, or you don't have sufficient permissions to use /dev/sg? devices. (Many systems require you to be root to use these.)

close

$device->close;

Closes the SCSI device after use. The device will also be closed if the handle goes out of scope.

execute

 # Reading from the device only
 my ($result, $sense) = $device->execute($command, $wanted);

 # Writing (and possibly reading) from the device
 my ($result, $sense) = $device->execute($command, $wanted, $data);

This method sends a raw SCSI command to the device in question. $command should be a 10 or a 12 character string containing the SCSI command. You will often use pack() to create this. $wanted indicates how many bytes of data you expect to receive from the device. If you are sending data to the device, you also need to provide that data in $data.

The data (if any) returned from the device will be in $result, and the sense data will appear the array ref $sense. If there is any serious error, for example if the device cannot be contacted (and the kernel has not paniced from such hardware failure) then an exception may be thrown.

inquiry

 %inquiry = %{ $device->inquiry };

This method provides a simple way to query the device via SCSI INQUIRY command to identify it. A hash ref will be returned with the following keys:

DEVICE

A number identifying the type of device, for example 1 for a tape drive, or 5 for a CD-ROM.

VENDOR

The vendor name, "HP", or "SONY" for example.

PRODUCT

The device product name, e.g. "HP35470A", "CD-ROM CDU-8003A".

REVISION

The firmware revision of the device, e.g. "1109" or "1.9a".

WARNINGS

Playing directly with SCSI devices can be hazardous and lead to loss of data. Since such things can normally only be done as the superuser (or by the superuser changing the permissions on /dev/sg? to allow mere mortals access) the usual caveats about working as root on raw devices applies. The author cannot be held responsible for loss of data or other damages.

SEE ALSO

The Linux SCSI-Programming-HOWTO (In /usr/doc/HOWTO/ on Debian Linux, similar places for other distributions) details the gory details of the generic SCSI interface that this talks to. Perl advocates will easily notice how much shorter this Perl is compared to the C versions detailed in that document.

To do anything more than a bit of hacking, you'll need the SCSI standards documents. Drafts are apparently available via anonymous FTP from:

  ftp://ftp.cs.tulane.edupub/scsi
  ftp://ftp.symbios.com/pub/standards
  ftp://ftp.cs.uni-sb.de/pub/misc/doc/scsi

There's a Usenet group dedicated to SCSI:

  news:comp.periphs.scsi - Discussion of SCSI-based peripheral devices.

BUGS

This is some of my very early Perl, dating back to 2000, so the code quality is not great. It does however work, despite the lack of a test suite to prove it.

AUTHOR

Peter Corlett <abuse@cabal.org.uk>

COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Peter Corlett.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.