########################################################################### package Win32::API::LibUSB; ########################################################################### # for Delevopement use Data::Dumper; $Data::Dumper::Sortkeys = 1; ########################################################################### use strict; use warnings; use Win32::API qw(ReadMemory IsBadReadPtr); sub new{ my $class = shift; my %cfg = ( dll => 'libusb0', vid => 0, pid => 0, @_); my $self = bless{ CFG => \%cfg }, $class; my $usb_init = Win32::API->new($cfg{dll}, "void usb_init()" ) or die $^E; my $usb_find_busses = Win32::API->new($cfg{dll}, "int usb_find_busses()" ) or die $^E; my $usb_find_devices = Win32::API->new($cfg{dll}, "int usb_find_devices()" ) or die $^E; $usb_init->Call; eval{$usb_find_busses->Call} || die "No USBus found!\n"; eval{ $usb_find_devices->Call} || die "Device not found, make sure, your device for LibUSB ist installed and connected!\n"; $self->_get_busses; $self->_get_fst_device; $self->_get_configuration; $self->_get_interface; $self->_usb_open; return $self; } #################### private ############################################## sub _usb_open{ my $self = shift; Win32::API->Import($self->{CFG}{dll}, 'usb_open',"T","I") or die $^E; Win32::API::Struct->typedef( 'usb_device', # "INT_PTR","next", # "INT_PTR","prev", # "CHAR","filename", # "INT_PTR","usb_bus", # "CHAR","bLength", # "CHAR","bDescriptorType", # "SHORT","bcdUSB", # "CHAR","bDeviceClass", # "CHAR","bDeviceSubClass", # "CHAR","bDeviceProtocol", # "CHAR","bMaxPacketSize0", # "SHORT","idVendor", # "SHORT","idProduct", # "SHORT","bcdDevice", # "CHAR","iManufacturer", # "CHAR","iProduct", # "CHAR","iSerialNumber", # "CHAR","bNumConfigurations", # "INT_PTR","config", # "INT_PTR","dev", # "CHAR","devnum", # "CHAR","num_children", # "INT_PTR","children" ); my $dev = Win32::API::Struct->new( 'usb_device'); $dev->{usb_bus} = do{ Win32::API::Struct->typedef( 'usb_bus', 'INT_PTR','devices' ); my $o = Win32::API::Struct->new('usb_bus'); #foreach my $k(keys %{$self->{usb_bus}}){ # $o->{$k} = $self->{usb_bus}{$k}; #} $o; }; $dev->{config} = do{ Win32::API::Struct->typedef( 'config', 'CHAR', 'bLength', 'CHAR','bDescriptorType', 'SHORT','wTotalLength', 'CHAR','bNumInterfaces', 'CHAR','bConfigurationValue', 'CHAR','iConfiguration', 'CHAR','bmAttributes', 'CHAR','MaxPower', 'INT_PTR','interface', 'CHAR','extra', 'INT','extralen' ); my $o = Win32::API::Struct->new('config'); #foreach my $k(keys %{$self->{usb_config_descriptor}}){ # $o->{$k} = $self->{usb_config_descriptor}{$k}; #} $o; }; #usb_open($dev); $self->dd($dev); } sub _get_interface{ my $self = shift; my $mem_interface = unpack "V", ReadMemory( $self->{usb_config_descriptor}{interface}, 4); } sub _get_configuration{ my $self = shift; my $mem_config_descriptor = ReadMemory($self->{usb_device}{config}, 1+1+2+1+1+1+1+1+4+1+4); my %usb_config_descriptor; @usb_config_descriptor{qw( bLength bDescriptorType wTotalLength bNumInterfaces bConfigurationValue iConfiguration bmAttributes MaxPower interface extra extralen )} = unpack "CCvCCCCCVCV", $mem_config_descriptor; $self->{usb_config_descriptor} = \%usb_config_descriptor; } sub _get_busses{ my $self = shift; my $usb_get_busses = Win32::API->new('libusb0', 'int usb_get_busses()'); my $bus_addr = $usb_get_busses->Call(); #print $bus_addr,"\n"; my $mem_usb_bus = ReadMemory($bus_addr, 532); my %usb_bus; @usb_bus{qw(next prev dirname devices location root_dev)} = unpack "VVZ512VVV", $mem_usb_bus; Win32::API::Struct->typedef( 'usb_bus', "INT_PTR","devices" ); my $usb_bus = Win32::API::Struct->new( 'usb_bus'); #$self->dd($usb_bus); $self->{usb_bus} = \%usb_bus; } sub _get_fst_device{ my $self = shift; # Erstes Device an Addr {devices} auslesen my $mem_usb_device = ReadMemory($self->{usb_bus}{devices}, 524 + 18 + 4 + 4 +1 +1 +4); my %usb_device; @usb_device{qw( next prev filename usb_bus bLength bDescriptorType bcdUSB bDeviceClass bDeviceSubClass bDeviceProtocol bMaxPacketSize0 idVendor idProduct bcdDevice iManufacturer iProduct iSerialNumber bNumConfigurations config dev devnum num_children children )} = unpack "VVZ512VCCvCCCCvvvCCCCVVCCV", $mem_usb_device; $self->{usb_device} = \%usb_device; if( $usb_device{idVendor} != $self->{CFG}{vid}){ die "Vendor-ID 'vid' stimmt nicht ueberein!\n" } if( $usb_device{idProduct} != $self->{CFG}{pid}){ die "Product-ID 'pid' stimmt nicht ueberein!\n" } } # Dump & Die sub dd{ my $self = shift; my $r = shift || $self; die Dumper $r; } 1;######################################################################### package main; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my $lusb = Win32::API::LibUSB->new( dll => 'libusb0', vid => 0xFFFF, pid => 0x1122 ) or die $@; print Dumper $lusb;