Device-USB

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

t/07-list_devices_if.t
t/08-get_busses.t
t/09-usb-bus.t
t/10-usb-device-accessors.t
t/11-usb-device-methods.t
t/12-constants.t
t/13-bus_find_device_if.t
t/14-bus_list_devices_if.t
t/15-usb_dev_configuration.t
t/16-usb_dev_interface.t
t/17-usb_dev_endpoint.t
t/18-usb_device-configurations.t
t/TestTools.pm
xt/boilerplate.t
xt/critic.t
xt/hasversion.t
xt/podcoverage.t
xt/pod.t
USB.pm
META.json                                Module JSON meta-data (added by MakeMaker)

lib/Device/USB.pm  view on Meta::CPAN

This class method enables low-level debugging messages from the library
interface code.

=over 4

=item level

0 disables debugging, 1 enables some debug messages, and 2 enables verbose
debug messages

Any other values are forced to the nearest endpoint.

=back

=cut

sub debug_mode
{
    my ($class, $level) = @_;

    lib_debug_mode( $level );

lib/Device/USB.pm  view on Meta::CPAN


=item libusb_get_string(void *dev, int index, int langid, char *buf, size_t buflen)


=item libusb_get_string_simple(void *dev, int index, char *buf, size_t buflen)


=item libusb_get_descriptor(void *dev, unsigned char type, unsigned char index, char *buf, int size)


=item libusb_get_descriptor_by_endpoint(void *dev, int ep, unsigned char type, unsigned char index, char *buf, int size)


=item libusb_bulk_write(void *dev, int ep, char *bytes, int size, int timeout)


=item libusb_bulk_read(void *dev, int ep, char *bytes, int size, int timeout)


=item libusb_interrupt_write(void *dev, int ep, char *bytes, int size, int timeout)

lib/Device/USB.pm  view on Meta::CPAN

        );
    }
    return usb_get_string_simple((usb_dev_handle *)dev, index, buf, buflen);
}

int libusb_get_descriptor(void *dev, unsigned char type, unsigned char index, char *buf, int size)
{
    return usb_get_descriptor((usb_dev_handle *)dev, type, index, buf, size);
}

int libusb_get_descriptor_by_endpoint(void *dev, int ep, unsigned char type, unsigned char index, char *buf, int size)
{
    return usb_get_descriptor_by_endpoint((usb_dev_handle *)dev, ep, type, index, buf, size);
}

int libusb_bulk_write(void *dev, int ep, char *bytes, int size, int timeout)
{
    return usb_bulk_write((usb_dev_handle *)dev, ep, bytes, size, timeout);
}

int libusb_bulk_read(void *dev, int ep, char *bytes, int size, int timeout)
{
    return usb_bulk_read((usb_dev_handle *)dev, ep, bytes, size, timeout);

lib/Device/USB.pm  view on Meta::CPAN

    hashStoreBcd( hash, "bcdDevice", dev->descriptor.bcdDevice );
    hashStoreInt( hash, "iManufacturer", dev->descriptor.iManufacturer );
    hashStoreInt( hash, "iProduct", dev->descriptor.iProduct );
    hashStoreInt( hash, "iSerialNumber", dev->descriptor.iSerialNumber );
    hashStoreInt( hash, "bNumConfigurations", dev->descriptor.bNumConfigurations );

    return newRV_noinc( (SV*)hash );
}

/*
 * Given a pointer to a usb_endpoint_descriptor struct, create a reference
 * to a Device::USB::DevEndpoint object that represents it.
 */
static SV* build_endpoint( struct usb_endpoint_descriptor* endpt )
{
    HV* hash = newHV();

    hashStoreInt( hash, "bDescriptorType", endpt->bDescriptorType );
    hashStoreInt( hash, "bEndpointAddress", endpt->bEndpointAddress );
    hashStoreInt( hash, "bmAttributes", endpt->bmAttributes );
    hashStoreInt( hash, "wMaxPacketSize", endpt->wMaxPacketSize );
    hashStoreInt( hash, "bInterval", endpt->bInterval );
    hashStoreInt( hash, "bRefresh", endpt->bRefresh );
    hashStoreInt( hash, "bSynchAddress", endpt->bSynchAddress );

    return sv_bless( newRV_noinc( (SV*)hash ),
        gv_stashpv( "Device::USB::DevEndpoint", 1 )
    );
}

/*
 * Given a pointer to an array of usb_endpoint_descriptor structs, create a
 * reference to a Perl array containing the same data.
 */
static SV* list_endpoints( struct usb_endpoint_descriptor* endpt, unsigned count )
{
    AV* array = newAV();
    unsigned i = 0;

    for(i=0; i < count; ++i)
    {
        av_push( array, build_endpoint( endpt+i ) );
    }

    return newRV_noinc( (SV*)array );
}


/*
 * Build the object that contains the interface descriptor.
 *
 * inter - the usb_interface_descriptor describing this interface.

lib/Device/USB.pm  view on Meta::CPAN

    HV* hash = newHV();

    hashStoreInt( hash, "bDescriptorType", inter->bDescriptorType );
    hashStoreInt( hash, "bInterfaceNumber", inter->bInterfaceNumber );
    hashStoreInt( hash, "bAlternateSetting", inter->bAlternateSetting );
    hashStoreInt( hash, "bNumEndpoints", inter->bNumEndpoints );
    hashStoreInt( hash, "bInterfaceClass", inter->bInterfaceClass );
    hashStoreInt( hash, "bInterfaceSubClass", inter->bInterfaceSubClass );
    hashStoreInt( hash, "bInterfaceProtocol", inter->bInterfaceProtocol );
    hashStoreInt( hash, "iInterface", inter->iInterface );
    hashStoreSV( hash, "endpoints",
        list_endpoints( inter->endpoint, inter->bNumEndpoints )
    );
    /* TODO: handle the 'extra' data */

    return sv_bless( newRV_noinc( (SV*)hash ),
        gv_stashpv( "Device::USB::DevInterface", 1 )
    );
}

/*
 * Given a pointer to an array of usb_interface structs, create a

lib/Device/USB/DevEndpoint.pm  view on Meta::CPAN


require 5.006;
use warnings;
use strict;
use Carp;

=encoding utf8

=head1 Device::USB::DevEndpoint

This class encapsulates a USB Device endpoint and the methods that object
would support.

=head1 NAME

Device::USB::DevEndpoint - Access a device endpoint returned by libusb.

=head1 VERSION

Version 0.38

=cut

our $VERSION=0.38;

=head1 SYNOPSIS

Device::USB:DevEndpoint provides a Perl object for accessing an endpoint
of an interface of a USB device using the libusb library.

    use Device::USB;

    my $usb = Device::USB->new();
    my $dev = $usb->find_device( $VENDOR, $PRODUCT );

    printf "Device: %04X:%04X\n", $dev->idVendor(), $dev->idProduct();
    $dev->open();

    my $cfg = $dev->config()->[0];
    my $inter = $cfg->interfaces()->[0]->[0];
    my $ep = $inter->endpoints()->[0];
    print "Endpoint:", $inter->bEndpointAddress(),
       " name: ", $dev->get_string_simple($iter->iInterface()), "\n";

See USB specification for an explanation of the attributes of an
endpoint.

=head1 DESCRIPTION

This module defines a Perl object that represents the data associated with
a USB interface endpoint. The object provides read-only access to the
important data associated with the endpoint.

=head2 METHODS

There are several accessor methods that return data from the interface.
Each is named after the field that they return. These accessors include:

=cut

# I need to build a lot of accessors
sub _make_descr_accessor

lib/Device/USB/DevInterface.pm  view on Meta::CPAN

    my $usb = Device::USB->new();
    my $dev = $usb->find_device( $VENDOR, $PRODUCT );

    printf "Device: %04X:%04X\n", $dev->idVendor(), $dev->idProduct();
    $dev->open();

    my $cfg = $dev->config()->[0];
    my $inter = $cfg->interfaces()->[0];
    print "Interface:", $inter->bInterfaceNumber(),
       " name: ", $dev->get_string_simple($iter->iInterface()), 
       ": endpoint count: ", $inter->nNumEndpoints(), "\n";

See USB specification for an explanation of the attributes of an
interface.

=head1 DESCRIPTION

This module defines a Perl object that represents the data associated with
a USB device configuration's interface. The object provides read-only access
to the important data associated with the interface.

lib/Device/USB/DevInterface.pm  view on Meta::CPAN


The 0-based number of this interface.

=item bAlternateSetting

Value used to select this alternate setting for the interface specified
in bInterfaceNumber.

=item bNumEndpoints

Number of endpoints (excluding endpoint 0) available on this interface.
If the value  is 0, only the control interface is supported.

=item bInterfaceClass

Class code as specified by the USB-IF. A value of 0xff is a vendor-specific
interface class.

=item bInterfaceSubClass

Subclass code specified by the USB-IF. If bInterfaceClass is not 0xff,

lib/Device/USB/DevInterface.pm  view on Meta::CPAN

=cut

_make_descr_accessor( 'bInterfaceNumber' );
_make_descr_accessor( 'bAlternateSetting' );
_make_descr_accessor( 'bNumEndpoints' );
_make_descr_accessor( 'bInterfaceClass' );
_make_descr_accessor( 'bInterfaceSubClass' );
_make_descr_accessor( 'bInterfaceProtocol' );
_make_descr_accessor( 'iInterface' );

=item endpoints

Returns a list of endpoint objects associated with this interface.

=cut

sub endpoints
{
    my $self = shift;
    return wantarray ? @{$self->{endpoints}} : $self->{endpoints};
}

=back

=head1 DIAGNOSTICS

This is an explanation of the diagnostic and error messages this module
can generate.

=head1 DEPENDENCIES

lib/Device/USB/Device.pm  view on Meta::CPAN

{
    my $self = shift;
    my $alternate = shift;
    $self->_assert_open();

    return Device::USB::libusb_set_altinterface( $self->{handle}, $alternate );
}

=item clear_halt

Clears any halt status on the supplied endpoint.

=over 4

=item alternate

the integer specified bEndpointAddress descriptor field.

=back

returns 0 on success or <0 on error

lib/Device/USB/Device.pm  view on Meta::CPAN


    my $retlen = Device::USB::libusb_get_descriptor(
        $self->{handle}, $type, $index, $buf, MAX_BUFFER_SIZE
    );

    return if $retlen < 0;

    return substr( $buf, 0, $retlen );
}

=item get_descriptor_by_endpoint

Retrieve an endpoint-specific descriptor from the device

=over 4

=item ep

Endpoint to query.

=item type

The type of descriptor to retrieve.

lib/Device/USB/Device.pm  view on Meta::CPAN


=back

TODO: This method needs major rewrite to be Perl-ish.
I need to provide a better way to specify the type (or at least document
which are available), and I need to return a Perl data structure, not
a buffer of binary data.      

=cut

sub get_descriptor_by_endpoint
{
    my $self = shift;
    my $ep = shift;
    my $type = shift;
    my $index = shift;

    $self->_assert_open();

    my $buf = "\0" x MAX_BUFFER_SIZE;

    my $retlen = Device::USB::libusb_get_descriptor_by_endpoint(
        $self->{handle}, $ep, $type, $index, $buf, MAX_BUFFER_SIZE
    );

    return if $retlen < 0;

    return substr( $buf, 0, $retlen );
}

=item bulk_read

Perform a bulk read request from the specified endpoint.

=over 4

=item ep

The number of the endpoint to read

=item bytes

Buffer into which to write the requested data.

=item size

Max size to read into the buffer.

=item timeout

lib/Device/USB/Device.pm  view on Meta::CPAN

    );

    # stick back in the bytes parameter.
    $_[1] = substr( $bytes, 0, $retlen );

    return $retlen;
}

=item interrupt_read

Perform a interrupt read request from the specified endpoint.

=over 4

=item ep

The number of the endpoint to read

=item bytes

Buffer into which to write the requested data.

=item size

Max size to read into the buffer.

=item timeout

lib/Device/USB/Device.pm  view on Meta::CPAN

    );

    # stick back in the bytes parameter.
    $_[1] = substr( $bytes, 0, $retlen );

    return $retlen;
}

=item bulk_write

Perform a bulk write request to the specified endpoint.

=over 4

=item ep

The number of the endpoint to write

=item bytes

Buffer from which to write the requested data.

=item timeout

Maximum time to wait (in milliseconds)

=back

lib/Device/USB/Device.pm  view on Meta::CPAN


    $self->_assert_open();

    return Device::USB::libusb_bulk_write(
        $self->{handle}, $ep, $bytes, length $bytes, $timeout
    );
}

=item interrupt_write

Perform a interrupt write request to the specified endpoint.

=over 4

=item ep

The number of the endpoint to write

=item bytes

Buffer from which to write the requested data.

=item timeout

Maximum time to wait (in milliseconds)

=back

t/11-usb-device-methods.t  view on Meta::CPAN

#

# Synthetics
can_ok( "Device::USB::Device",
        qw/DESTROY manufacturer product serial_number/ );

# libusb methods
can_ok( "Device::USB::Device",
        qw/open set_configuration set_altinterface clear_halt reset
           claim_interface release_interface control_msg get_string
           get_string_simple get_descriptor get_descriptor_by_endpoint
           bulk_read interrupt_read bulk_write interrupt_write/ );

t/16-usb_dev_interface.t  view on Meta::CPAN

}
else
{
    fail( "Unable to create USB object." );
}

my @devices = $usb->list_devices();
isnt( scalar @devices, 0, "USB devices found" );

can_ok( "Device::USB::DevInterface",
        qw/bInterfaceNumber endpoints bNumEndpoints
        iInterface bInterfaceClass bInterfaceSubClass bInterfaceProtocol/
);

foreach my $dev (@devices)
{
    my $filename = $dev->filename();
    my $cfgno = 0;
    foreach my $cfg ($dev->configurations())
    {
        foreach my $if (map { @{$_} } $cfg->interfaces())
        {
            my $ifno = $if->bInterfaceNumber();
            isa_ok( $if, "Device::USB::DevInterface" );
            like( $if->bInterfaceNumber(), qr/^\d+$/, "$filename:$cfgno:$ifno: Interface Number" );
            like( $if->bAlternateSetting(), qr/^\d+$/, "$filename:$cfgno:$ifno: Alternate Setting" );
            is( $if->bNumEndpoints(), scalar @{$if->endpoints()}, "$filename:$cfgno:$ifno: endpoint count" );
            like( $if->bInterfaceClass(), qr/^\d+$/, "$filename:$cfgno:$ifno: Interface Class" );
            like( $if->bInterfaceSubClass(), qr/^\d+$/, "$filename:$cfgno:$ifno: Interface Sub Class" );
            like( $if->bInterfaceProtocol(), qr/^\d+$/, "$filename:$cfgno:$ifno: Interface Protocol" );
            like( $if->iInterface(), qr/^\d+$/, "$filename:$cfgno:$ifno: Interface string index" );
        }
        ++$cfgno;
    }
}

t/17-usb_dev_endpoint.t  view on Meta::CPAN


use Test::More;
use Device::USB;
use strict;
use warnings;
use constant TESTS_PER_ENDPOINT => 7;

my $usb = Device::USB->new();
if(defined $usb)
{
    my $endpoint_count = 0;
    foreach my $dev ($usb->list_devices())
    {
        foreach my $config ($dev->configurations())
        {
            my @interfaces = map {@{$_}} $config->interfaces();
            $endpoint_count += $_->bNumEndpoints() foreach @interfaces;
        }
    }
    if($endpoint_count)
    {
        plan tests => 2 + TESTS_PER_ENDPOINT * $endpoint_count;
    }
    else
    {
        plan skip_all => 'No devices found.';
    }
}
else
{
    fail( "Unable to create USB object." );
}

t/17-usb_dev_endpoint.t  view on Meta::CPAN


foreach my $dev (@devices)
{
    my $filename = $dev->filename();
    my $cfgno = 0;
    foreach my $cfg ($dev->configurations())
    {
        foreach my $if (map { @{$_} } $cfg->interfaces())
        {
            my $ifno = $if->bInterfaceNumber();
            foreach my $ep ($if->endpoints())
            {
                my $descr = "$filename:$cfgno:$ifno:".$ep->bEndpointAddress();
                isa_ok( $ep, "Device::USB::DevEndpoint" );
                like( $ep->bEndpointAddress(), qr/^\d+$/, "$descr: Endpoint Address" );
                like( $ep->bmAttributes(), qr/^\d+$/, "$descr: Attributes" );
                like( $ep->wMaxPacketSize(), qr/^\d+$/, "$descr: Max Packet Size" );
                like( $ep->bInterval(), qr/^\d+$/, "$descr: Interval" );
                like( $ep->bRefresh(), qr/^\d+$/, "$descr: Refresh" );
                like( $ep->bSynchAddress(), qr/^\d+$/, "$descr: Synch Address" );
            }



( run in 0.394 second using v1.01-cache-2.11-cpan-cc502c75498 )