Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Device::SMBus -- an interface for I2C and/or SMBus under Linux

by bikeNomad (Priest)
on Jul 25, 2001 at 09:20 UTC ( [id://99568]=sourcecode: print w/replies, xml ) Need Help??
Category: Miscellaneous
Author/Contact Info bikeNomad, Ned Konz, ned@bike-nomad.com
Description: This lets you (if you're using Linux) access hardware connected via an I2C or SMBus interface, like (for instance) CPU temperature sensors. It uses Inline. You must have the lm_sensors library installed in your Linux system.
package Device::SMBus;

use 5.005;
use strict;
use warnings;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;

@Device::SMBus::ISA       = qw(Exporter);
@Device::SMBus::EXPORT_OK = qw( );
@Device::SMBus::EXPORT    = qw( );

use IO::File;
use Fcntl;

BEGIN
{
    $Device::SMBus::VERSION = '0.01';
}

use Inline(
    C => Config => INC => '-I/usr/local/include',
    AUTO_INCLUDE => '#include <linux/i2c.h>
            #include <linux/i2c-dev.h>',
    CCFLAGS => '-O2',    # necessary for inline functions
);

use Inline C => 'DATA' => NAME => 'Device::SMBus',
  VERSION => $VERSION;

use constant I2C_SLAVE => 0x0703;

sub new
{
    my $class  = shift;
    my $device = shift;
    my $fh     = IO::File->new( $device, O_RDWR );
    if ( !$fh )
    {
        warn "Device::SMBus open error on $device: $!\n";
        return undef;
    }
    my $self = {
        _fh         => $fh,
        _fn         => $fh->fileno(),
        _lastDevice => -1,
    };
    bless( $self, $class );
}

sub DESTROY
{
    my $self = shift;
    $self->{_fh}->close();
}

sub selectDevice
{
    my $self   = shift;
    my $devno  = shift;
    my $oldDev = $self->{_lastDevice};
    $self->{_lastDevice} = $devno;
    ( $oldDev != $devno ) ? $self->{_fh}->ioctl( I2C_SLAVE, $devno ) :
+ 1;
}

# return (data, errno) in array context,
# or just data (-1 for error).

sub readWordData
{
    my $self   = shift;
    my $cmd    = shift;
    my $retval = _readWordData( $self->{_fn}, $cmd );
    return wantarray ? ( $retval, ( ( $retval == -1 ) ? $! : 0 ) ) : $
+retval;
}

sub writeWordData
{
    my $self  = shift;
    my $cmd   = shift;
    my $value = shift;
    return _writeWordData( $self->{_fn}, $cmd, $value );
}

sub readBlockData
{
    my $self   = shift;
    my $cmd    = shift;
    my $data   = ' ' x 32;
    my $retval = _readBlockData( $self->{_fn}, $cmd, $data );
    return ( $retval < 0 ) ? undef: $data;
}

1;

__DATA__

__C__

int _writeQuick(int file, int value)
{
    return i2c_smbus_write_quick(file, value);
}

int _readByte(int file)
{
    return i2c_smbus_read_byte(file);
}

int _writeByte(int file, int value)
{
    return i2c_smbus_write_byte(file, value);
}

int _readByteData(int file, int command)
{
    return i2c_smbus_read_byte_data(file, command);
}

int _writeByteData(int file, int command, int value)
{
    return i2c_smbus_write_byte_data(file, command, value);
}

int _readWordData(int file, int command)
{
    return i2c_smbus_read_word_data(file, command);
}

int _writeWordData(int file, int command, int value)
{
    return i2c_smbus_write_word_data(file, command, value);
}

int _processCall(int file, int command, int value)
{
    return i2c_smbus_process_call(file, command, value);
}

int _readBlockData(int file, int command, SV* output)
{
    char buf[ 32 ];
    int retval;
    retval = i2c_smbus_read_block_data(file, command, buf);
    if (retval == -1)
        return retval;
    sv_setpvn(output, buf, retval);
    return retval;
}

int _writeBlockData(int file, int command, SV* value)
{
    STRLEN len;
    char *buf = SvPV(value, len);
    return i2c_smbus_write_block_data(file, command, len, buf);
}

int _writeI2CBlockData(int file, int command, SV* value)
{
    STRLEN len;
    char *buf = SvPV(value, len);
    return i2c_smbus_write_i2c_block_data(file, command, len, buf);
}

=pod

=head1 NAME

Device::SMBus - Perl extension to access the SMBus via Linux ioctls.

=head1 SYNOPSIS

  use Device::SMBus;
  my $smbus = Device::SMBus->new('/dev/i2c-0');
  $smbus->selectDevice( $deviceNumber );
  my $data = $smbus->readWordData( $command );
  $smbus->writeWordData( $command, $data );
  # etc.

=head1 DESCRIPTION

This provides a thin wrapper for the Linux I2C and SMBus ioctls.

=head2 EXPORT

None by default.

=head1 AUTHOR

Ned Konz, ned@bike-nomad.com

=head1 SEE ALSO

L<Inline>

L<perl>

=cut

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://99568]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2024-04-19 08:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found