########################################################################### 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->_usb_open; return $self; } #################### private ############################################## sub _usb_open{ my $self = shift; Win32::API->Import($self->{CFG}{dll}, 'usb_open',"T","I") or die $^E; my $addr = $self->{struct_usb_device}{config}; $self->{struct_usb_device}{config} = do{ Win32::API::Struct->typedef( "usb_config_descriptor", "UCHAR", "bLength", "UCHAR", "bDescriptorType", "USHORT", "wTotalLength", "UCHAR", "bNumInterfaces", "UCHAR", "bConfigurationValue", "UCHAR", "iConfiguration", "UCHAR", "bmAttributes", "UCHAR", "MaxPower", "LPLONG","interface", "UCHAR", "extra", "INT", "extralen" ); my $cfg = Win32::API::Struct->new("usb_config_descriptor"); my $mem = ReadMemory($addr, 1+1+2+1+1+1+1+1+4+1+4); my %hunt = (); @hunt{( "bLength", "bDescriptorType", "wTotalLength", "bNumInterfaces", "bConfigurationValue", "iConfiguration", "bmAttributes", "MaxPower", "interface", "extra", "extralen" )} = unpack "CCvCCCCCVCV", $mem; foreach my $k (keys %hunt ){$cfg->{$k} = $hunt{$k}} $cfg; }; my $ifaddr = $self->{struct_usb_device}{config}{interface}; $self->{struct_usb_device}{config}{interface} = do{ Win32::API::Struct->typedef( 'usb_interface', "INT_PTR","altsetting", "INT","num_altsetting", ); my $if = Win32::API::Struct->new('usb_interface'); ($if->{altsetting}, $if->{num_altsetting}) = unpack "VV", ReadMemory($ifaddr,8); $if; }; my $ifdescraddr = $self->{struct_usb_device}{config}{interface}{altsetting}; $self->{struct_usb_device}{config}{interface}{altsetting} = do{ Win32::API::Struct->typedef( 'usb_interface_descriptor', "UCHAR", "bLength", "UCHAR", "bDescriptorType", "UCHAR", "bInterfaceNumber", "UCHAR", "bAlternateSetting", "UCHAR", "bNumEndpoints", "UCHAR", "bInterfaceClass", "UCHAR", "bInterfaceSubClass", "UCHAR", "bInterfaceProtocol", "UCHAR","iInterface", "INT_PTR","endpoint", # usb_endpoint_descriptor "UCHAR","extra", "INT", "extralen" ); my $o = Win32::API::Struct->new('usb_interface_descriptor'); my %hunt = (); @hunt{( "bLength", "bDescriptorType", "bInterfaceNumber", "bAlternateSetting", "bNumEndpoints", "bInterfaceClass", "bInterfaceSubClass", "bInterfaceProtocol", "iInterface", "endpoint", # usb_endpoint_descriptor "extra", "extralen" )} = unpack "C9VCV", ReadMemory($ifdescraddr,18); foreach my $k(keys %hunt){$o->{$k} = $hunt{$k} } $o; }; my $epdescraddr = $self->{struct_usb_device}{config}{interface}{altsetting}{endpoint}; $self->{struct_usb_device}{config}{interface}{altsetting}{endpoint} = do{ Win32::API::Struct->typedef( 'usb_endpoint_descriptor', "UCHAR","bLength", "UCHAR","bDescriptorType", "UCHAR","bEndpointAddress", "UCHAR","bmAttributes", "USHORT","wMaxPacketSize", "UCHAR","bInterval", "UCHAR","bRefresh", "UCHAR","bSynchAddress", "PUCHAR","extra", #/* Extra descriptors */ "INT","extralen" ); my $o = Win32::API::Struct->new('usb_endpoint_descriptor'); my %h = (); @h{( "bLength", "bDescriptorType", "bEndpointAddress", "bmAttributes", "wMaxPacketSize", "bInterval", "bRefresh", "bSynchAddress", "extra", #/* Extra descriptors */ "extralen" )} = unpack "CCCvCCCVV", ReadMemory($epdescraddr, 1+1+1+1+2+1+1+1+4+4); foreach my $k(keys %h){$o->{$k} = $h{$k}} $o; }; # usb_open($self->{struct_usb_device}); } 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","next", "INT_PTR","prev", "CHAR","dirname[512]", "INT_PTR","devices", # struct usb_device "ULONG","location", "INT_PTR","rot_dev" # struct usb_device ); my $struct_usb_bus = Win32::API::Struct->new( 'usb_bus'); foreach my $k( keys %usb_bus){ $struct_usb_bus->{$k} = $usb_bus{$k} } $self->{struct_usb_bus} = $struct_usb_bus; #struct usb_bus #{ # struct usb_bus *next, *prev; # char dirname[LIBUSB_PATH_MAX]; # struct usb_device *devices; # unsigned long location; # struct usb_device *root_dev; #}; } sub _get_fst_device{ my $self = shift; # Erstes Device an Addr {devices} auslesen my $mem_usb_device = ReadMemory($self->{struct_usb_bus}{devices}, 524 + 18 + 4 + 4 +1 +1 +4); my %usb_device; @usb_device{qw( next prev filename 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; 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" } Win32::API::Struct->typedef( "usb_device", "INT_PTR","next", "INT_PTR","prev", "CHAR","filename[512]", "INT_PTR","bus", "UCHAR","bLength", "UCHAR","bDescriptorType", "USHORT","bcdUSB", "UCHAR","bDeviceClass", "UCHAR","bDeviceSubClass", "UCHAR","bDeviceProtocol", "UCHAR","bMaxPacketSize0", "USHORT","idVendor", "USHORT","idProduct", "USHORT","bcdDevice", "UCHAR","iManufacturer", "UCHAR","iProduct", "UCHAR","iSerialNumber", "UCHAR","bNumConfigurations", "INT_PTR","config", "LPVOID","dev", "UCHAR","devnum", "UCHAR","num_children", "INT_PTR","children" ); my $struct_usb_device = Win32::API::Struct->new( 'usb_device'); foreach my $k( keys %usb_device ){ $struct_usb_device->{$k} = $usb_device{$k} } $self->{struct_usb_device} = $struct_usb_device; #struct usb_device #{ # struct usb_device *next, *prev; # char filename[LIBUSB_PATH_MAX]; # struct usb_bus *bus; # struct usb_device_descriptor descriptor; # struct usb_config_descriptor *config; # void *dev; /* Darwin support */ # unsigned char devnum; # unsigned char num_children; # struct usb_device **children; #}; } # 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 $lusb->{usb_device}{filename}; # \\.\libusb0-0001--0xffff-0x1122 print Dumper $lusb;