Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

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

by bikeNomad (Priest)
on Jul 25, 2001 at 09:20 UTC ( #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

Comment on Device::SMBus -- an interface for I2C and/or SMBus under Linux
Download Code

Back to Code Catacombs

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2015-07-30 09:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (270 votes), past polls