Device-USB

 view release on metacpan or  search on metacpan

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

=item *

CLASS_MASS_STORAGE

=item *

CLASS_HUB

=item *

CLASS_DATA

=item *

CLASS_VENDOR_SPEC

=back

=head2 FUNCTIONS

=over 4

=cut

#
#  Internal-only, one-time init function.
my $init_ref;
$init_ref = sub
{
    libusb_init();
    $init_ref = sub {};
};

=item new

Create a new Device::USB object for accessing the library.

=cut

sub new
{
    my $class = shift;

    $init_ref->();

    return bless {}, $class;
}

=item debug_mode

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 );
    return;
}


=item find_busses

Returns the number of changes since previous call to the function: the
number of busses added or removed.

=cut

sub find_busses
{
    my $self = shift;
    return libusb_find_busses();
}

=item find_devices

Returns the number of changes since previous call to the function: the
number of devices added or removed. Should be called after find_busses.

=cut

sub find_devices
{
    my $self = shift;
    return libusb_find_devices();
}

=item find_device

Find a particular USB device based on the vendor and product ids. If more
than one device has the same product id from the same vendor, the first one
found is returned.

=over 4

=item vendor

the vendor id

=item product

product id for that vendor

=back

returns a device reference or undef if none was found.

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


=over 4

=item DeviceUSBDebugLevel()


=item libusb_init()


=item libusb_find_busses()


=item libusb_find_devices()


=item libusb_get_busses()


=item libusb_open(void *dev)


=item libusb_close(void *dev)


=item libusb_set_configuration(void *dev, int configuration)


=item libusb_set_altinterface(void *dev, int alternate)


=item libusb_clear_halt(void *dev, unsigned int ep)


=item libusb_reset(void *dev)


=item libusb_get_driver_np(void *dev, int interface, char *name, unsigned int namelen)


=item libusb_detach_kernel_driver_np(void *dev, int interface)


=item libusb_claim_interface(void *dev, int interface)


=item libusb_release_interface(void *dev, int interface)


=item libusb_control_msg(void *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout)


=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)


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


=item lib_get_usb_busses()

Return the complete list of information after finding busses and devices.

Before calling this function, remember to call find_busses and find_devices.

returns a reference to an array of busses.

=item lib_list_busses()

Return the complete list of information after finding busses and devices.

By using this function, you do not need to do the find_* calls yourself.

returns a reference to an array of busses.

=item lib_find_usb_device( int vendor, int product )

Find a particular device

   vendor  - the vendor id
   product - product id for that vendor

returns a pointer to the device if it is found, NULL otherwise.

=item lib_debug_mode( int unsafe_level )

Set debugging level: 0: off, 1: some messages, 2: verbose
Values outside range are forced into range.

=back

=head1 DIAGNOSTICS

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

=head1 DEPENDENCIES

This module depends on the Carp, Inline and Inline::C modules, as well as
the strict and warnings pragmas. Obviously, libusb must be available since
that is the entire reason for the module's existence.

=head1 AUTHOR

G. Wade Johnson (gwadej at cpan dot org)

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

        printf( "libusb_control_msg( %#04x, %#04x, %#04x, %#04x, %p, %d, %d )\n",
            requesttype, request, value, index, bytes, size, timeout
        );
        /* maybe need to add support for printing the bytes string. */
    }
    retval = usb_control_msg((usb_dev_handle *)dev, requesttype, request, value, index, bytes, size, timeout);
    if(DeviceUSBDebugLevel())
    {
        printf( "\t => %d\n",retval );
    }

    /* quiet compiler warnings. */
    (void)i;
    (void)ax;
    (void)items;
    /*
     * For some reason, I could not get this string transferred back to the Perl side
     * through a direct copy like in get_simple_string. So, I resorted to returning
     * it on the stack and doing the fixup on the Perl side.
     */
    Inline_Stack_Reset;
    Inline_Stack_Push(sv_2mortal(newSViv(retval)));
    if(retval > 0)
    {
        Inline_Stack_Push(sv_2mortal(newSVpv(bytes, retval)));
    }
    else
    {
        Inline_Stack_Push(sv_2mortal(newSVpv(bytes, 0)));
    }
    Inline_Stack_Done;
}

int libusb_get_string(void *dev, int index, int langid, char *buf, size_t buflen)
{
    if(DeviceUSBDebugLevel())
    {
        printf( "libusb_get_string( %d, %d, %p, %lu )\n",
            index, langid, buf, (unsigned long)buflen
        );
    }
    return usb_get_string((usb_dev_handle *)dev, index, langid, buf, buflen);
}

int libusb_get_string_simple(void *dev, int index, char *buf, size_t buflen)
{
    if(DeviceUSBDebugLevel())
    {
        printf( "libusb_get_string_simple( %d, %p, %lu )\n",
            index, buf, (unsigned long)buflen
        );
    }
    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);
}

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

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


/* ------------------------------------------------------------
 * Provide Perl-ish interface for accessing busses and devices.
 */

/*
 * Utility function to store BCD encoded number as an appropriate string
 * in a hash under the supplied key.
 */
static void hashStoreBcd( HV *hash, const char *key, long value )
{
    int major = (value >> 8) & 0xff;
    int minor = (value >> 4) & 0xf;
    int subminor = value & 0xf;

    // should not be able to exceed 6.
    char buffer[10] = "";

    sprintf( buffer, "%d.%d%d", major, minor, subminor );

    (void) hv_store( hash, key, strlen( key ), newSVpv( buffer, strlen( buffer ) ), 0 );
}

/*
 * Utility function to store an integer value in a hash under the supplied key.
 */
static void hashStoreInt( HV *hash, const char *key, long value )
{
    (void) hv_store( hash, key, strlen( key ), newSViv( value ), 0 );
}

/*
 * Utility function to store a C-style string in a hash under the supplied key.
 */
static void hashStoreString( HV *hash, const char *key, const char *value )
{
    (void) hv_store( hash, key, strlen( key ), newSVpv( value, strlen( value ) ), 0 );
}

/*
 * Utility function to store an SV in a hash under the supplied key.
 */
static void hashStoreSV( HV *hash, const char *key, SV *value )
{
    (void) hv_store( hash, key, strlen( key ), value, 0 );
}

/*
 * Given a pointer to an array of usb_device, create a hash
 * reference containing the descriptor information.
 */
static SV* build_descriptor(struct usb_device *dev)
{
    HV* hash = newHV();

    hashStoreInt( hash, "bDescriptorType", dev->descriptor.bDescriptorType );
    hashStoreBcd( hash, "bcdUSB", dev->descriptor.bcdUSB );
    hashStoreInt( hash, "bDeviceClass", dev->descriptor.bDeviceClass );
    hashStoreInt( hash, "bDeviceSubClass", dev->descriptor.bDeviceSubClass );
    hashStoreInt( hash, "bDeviceProtocol", dev->descriptor.bDeviceProtocol );
    hashStoreInt( hash, "bMaxPacketSize0", dev->descriptor.bMaxPacketSize0 );
    hashStoreInt( hash, "idVendor", dev->descriptor.idVendor );
    hashStoreInt( hash, "idProduct", dev->descriptor.idProduct );
    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.
 *
 * returns the appropriate pointer to a reference.
 */
static SV* build_interface( struct usb_interface_descriptor* inter )
{
    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
 * reference to a Perl array containing the same data.
 */
static SV* list_interfaces( struct usb_interface* ints, unsigned count )
{
    AV* array = newAV();
    unsigned i = 0;

    for(i=0; i < count; ++i)
    {
        AV* inters = newAV();
        unsigned j = 0;
        for(j=0; j < ints[i].num_altsetting; ++j)
        {
            av_push( inters, build_interface( (ints[i].altsetting+j) ) );
        }
        av_push( array, newRV_noinc( (SV*)inters ) );
    }

    return newRV_noinc( (SV*)array );
}

/*
 * Given a pointer to a usb_config_descriptor struct, create a Perl
 * object that contains the same data.
 */
static SV* build_configuration( struct usb_config_descriptor *cfg )
{
    HV* hash = newHV();
    hashStoreInt( hash, "bDescriptorType", cfg->bDescriptorType );
    hashStoreInt( hash, "wTotalLength", cfg->wTotalLength );
    hashStoreInt( hash, "bNumInterfaces", cfg->bNumInterfaces );
    hashStoreInt( hash, "bConfigurationValue", cfg->bConfigurationValue );
    hashStoreInt( hash, "iConfiguration", cfg->iConfiguration );
    hashStoreInt( hash, "bmAttributes", cfg->bmAttributes );
    hashStoreInt( hash, "MaxPower", cfg->MaxPower*2 );
    hashStoreSV( hash, "interfaces",
        list_interfaces( cfg->interface, cfg->bNumInterfaces )
    );

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

/*
 * Given a pointer to an array of usb_config_descriptor structs, create a
 * reference to a Perl array containing the same data.
 */
static SV* list_configurations(struct usb_config_descriptor *cfg, unsigned count )
{



( run in 1.259 second using v1.01-cache-2.11-cpan-524268b4103 )