Voor USB communicatie tussen een PIC en de PC, gebruik ik de DLL libusb0.dll.
De PC progjes maak in in Delphi.
Nu wil ik ook een Visual Basic versie maken.

Heeft iemand ervaring met Visual Basic samen met libusb0.dll ?

Mod's: Even voor de duidelijkheid, dit gaat inderdaad over software. Maar dit is specifiek voor een PIC bedoeld !

Hoe ik met Visual Basic 6 kan communiceren met die DLL.

'k heb het driverproject gedownload, maar sjit dat is een hoop.., ik heb wel een bestand gevonden.
Zipfile/Docs/Function.sgml, daar staat een lang verhaal over welke functie's erzijn.

dit is de eerste die je moet aanroepen:

usb_init

er staat idd niet bij hoe de code dan zou moeten zijn.
maar ik denk, dat je best dit kunt proberen:


Public Declare sub mms_USB_Init Lib "LIBusb0.dll" Alias "usb_init" 

of

Public Declare Function mms_USB_Init Lib "LIBusb0.dll" Alias "usb_init" () As Long

das dan de declaratie van de API, en dan moet je natuurlijk nog het commando zelf geven.


mms_Usb_init

'k wil het best mailen, maar je hebt het toch al?
en trouwens, kwenie zo goed waarvoor het is, maar als je BV zon USB setje van VOTI aan het spelen bent, dat zijn chips van FTDI, die hebben ook een DLL, met veel goede voorbeelden.
http://www.ftdichip.com/Projects/CodeExamples/VB.htm

k wil het best mailen, maar je hebt het toch al?

Als je dit bedoeld, dan weet ik niet wat ik hermee moet: Zipfile/Docs/Function.sgml

Public Declare sub mms_USB_Init Lib "LIBusb0.dll" Alias "usb_init"
of
Public Declare Function mms_USB_Init Lib "LIBusb0.dll" Alias "usb_init" () As Long

Kan je/iemand hier iets meer over vertellen, ik krijg alleen maar fout meldingen ?

[Bericht gewijzigd door MMSoft op ]

is dat de libusb van sourceforge ? ( mensen wat een draak is me dat geworden zeg. vroeger was het simpel klikkerdeklik om iets te downloaden daar. nu ben je 1) verblind door alle toeters en bellen , alle reclame die rond je oren zoeft , en moet je ene half uur lezen om te vinden waar je nu juist moet klikken om iets te krijgen... )

kzal sebiet ne keer kijken om de calls te porteren naar VB.

ik was net ook aant zien om iets te doen met libusb ... en kheb het zelf toch ook nodig.

der is een leuek tool die je kan downloaden (gratis) bij microsoft om in DLL's te neuzen om te kijken welke functies ze exporteren..
dat ding noemt Dependency Walker.

het analyseert eender welke DLL of EXe en toont de lijst van ge-exporteerde calls en ook welke andere libraries die file nodig heeft enzovoort.

hee leuk om te zien welke files een programma allemaal nodig heeft....

[Bericht gewijzigd door free_electron op ]

Op 28 december 2006 17:11:19 schreef free_electron:
is dat de libusb van sourceforge ? vroeger was het simpel klikkerdeklik om iets te downloaden daar. nu ben je 1) verblind door alle toeters en bellen , alle reclame die rond je oren zoeft , en moet je ene half uur lezen om te vinden waar je nu juist moet klikken om iets te krijgen... )
Dependency Walker.

ja dus, libusb.dll versie x.1.12
'k heb ook een versie x.1.17 gevonden, maar om een *.exe te draaien met dat soort rotzooi, nee dankje

Dependency Walker zit standaard bij de enterprise edition van VB6 :)

- wat voor USB gebruik TS, en heeft die fabriekant geen code voorbeelden?
- het werkt al wel in delphi ?, laat die code zien dan :)

@ henry: 'k heb geen vieuwer voor *.sgml, maar als je *.html van maakt wordt het dus dit.

dit heb ik al

' twee woorden uitleg
' shortint in C is een Integer in VB
' Char is een byte in VB

'Device and/or Interface Class codes
    Const USB_CLASS_PER_INTERFACE = 0
    Const USB_CLASS_AUDIO = 1
    Const USB_CLASS_COMM = 2
    Const USB_CLASS_HID = 3
    Const USB_CLASS_PRINTER = 7
    Const USB_CLASS_MASS_STORAGE = 8
    Const USB_CLASS_HUB = 9
    Const USB_CLASS_DATA = 10
    Const USB_CLASS_VENDOR_SPEC = &HFF
'Descriptor types
    Const USB_DT_DEVICE = &H1
    Const USB_DT_CONFIG = &H2
    Const USB_DT_STRING = &H3
    Const USB_DT_INTERFACE = &H4
    Const USB_DT_ENDPOINT = &H5
    Const USB_DT_HID = &H21
    Const USB_DT_REPORT = &H22
    Const USB_DT_PHYSICAL = &H23
    Const USB_DT_HUB = &H29
'Descriptor sizes per descriptor type
    Const USB_DT_DEVICE_SIZE = 18
    Const USB_DT_CONFIG_SIZE = 9
    Const USB_DT_INTERFACE_SIZE = 9
    Const USB_DT_ENDPOINT_SIZE = 7
    Const USB_DT_ENDPOINT_AUDIO_SIZE = 9
    Const USB_DT_HUB_NONVAR_SIZE = 7
'Enpoint Descriptors...
    Const USB_MAXENDPOINTS = 32
    Const USB_ENDPOINT_ADDRESS_MASK = &HF
    Const USB_ENDPOINT_DIR_MASK = &H80
    Const USB_ENDPOINT_TYPE_MASK = &H3
    Const USB_ENDPOINT_TYPE_CONTROL = 0
    Const USB_ENDPOINT_TYPE_ISOCHRONOUS = 1
    Const USB_ENDPOINT_TYPE_BULK = 2
    Const USB_ENDPOINT_TYPE_INTERRUPT = 3
'Diverse
    Const USB_MAXINTERFACES = 32
    Const USB_MAXALTSETTING = 128
    Const USB_MAXCONFIG = 8
'Standard requests
    Const USB_REQ_GET_STATUS = &H0
    Const USB_REQ_CLEAR_FEATURE = &H1
    Const USB_REQ_SET_FEATURE = &H3
    Const USB_REQ_SET_ADDRESS = &H5
    Const USB_REQ_GET_DESCRIPTOR = &H6
    Const USB_REQ_SET_DESCRIPTOR = &H7
    Const USB_REQ_GET_CONFIGURATION = &H8
    Const USB_REQ_SET_CONFIGURATION = &H9
    Const USB_REQ_GET_INTERFACE = &HA
    Const USB_REQ_SET_INTERFACE = &HB
    Const USB_REQ_SYNCH_FRAME = &HC
    Const USB_TYPE_STANDARD = 0
    Const USB_TYPE_CLASS = &H20       ' (0x01 << 5)  waarschijnlijk shift left ...
    Const USB_TYPE_VENDOR = &H40      ' (0x02 << 5) dus ik heb de boel al geshift
    Const USB_TYPE_RESERVED = &H60     '(0x03 << 5) hier
    Const USB_RECIP_DEVICE = &H0
    Const USB_RECIP_INTERFACE = &H1
    Const USB_RECIP_ENDPOINT = &H2
    Const USB_RECIP_OTHER = &H3
    Const LIBUSB_PATH_MAX = 512
    Const USB_ENDPOINT_IN = &H80
    Const USB_ENDPOINT_OUT = &H0
    Const USB_ERROR_BEGIN = 500000
' Data structures
Type USB_Descriptor_Header
     bLength As Byte
     bDescriptorType As Byte
End Type
Type USB_String_descriptor
     bLength As Byte
     bDescriptorType As Byte
     wdata As Integer
End Type
Type USB_Hid_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bcdHID As Integer
     bCountrycode As Byte
     bNumdescriptors As Byte
End Type
Type USB_Endpoint_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bEndpointaddress As Byte
     bmAttributes As Byte
     wMaxPacketSize As Integer
     bInterval As Byte
     bRefresh As Byte
     bSynchAddress As Byte
     '  hier zit een klotepointer naar een andere struct :    *extra as Byte
     extralen As Integer
End Type

Type USB_Device
     filename(LIBUSB_PATH_MAX) As Byte
     Bus As Byte ' USB_Bus
     Descriptor As Byte ' dit is een geforwarde struct :  USB_Device_Descriptor
     Config As Byte ' dit is een geforwarde struct : USB_Config_Descriptor
End Type

Type USB_Bus
     DirName(LIBUSB_PATH_MAX) As Byte
     Devices As Byte ' geforwarde struct: USB_Device
     Location As Single
End Type
 
Type USB_Device_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bcdUSB As Long ' short
     bDeviceClass As Byte
     bDeviceSubClass As Byte
     bDeviceProtocol As Byte
     bMaxPacketSize0 As Byte
     idVendor As Integer
     idProduct As Integer
     bcdDevice As Integer
     iManufacturer As Byte
     iProduct As Byte
     iSerialNumber As Byte
     bNumConfigurations As Byte
End Type
 
Type USB_Config_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     wTotalLength As Integer
     bNumInterfaces As Byte
     bConfigurationValue As Byte
     iConfiguration As Byte
     bmAttributes As Byte
     MaxPower As Byte
     Interface As Byte ' geforwarde struct USB_Interface
     Extra As Byte
     extralen As Long
End Type
 
Type USB_Interface
     AltSetting As Byte 'geforwarde struct USB_Interface_Descriptor
     Num_AltSetting As Integer
End Type
 
Type USB_Interface_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bInterfaceNumber As Byte
     bAlternateSetting As Byte
     bNumEndpoints As Byte
     bInterfaceClass As Byte
     bInterfaceSubClass As Byte
     bInterfaceProtocol As Byte
     iInterface As Byte
     EndPoint As Byte 'geforwarde struct USB_EndPoint_Descriptor
     Extra As Byte
     extralen As Integer
End Type

Type USB_dev_handle
     zever As Byte  ' efkese zever gedclareerd omdat ik hier de definieite niet van terugvind in de .h file
End Type

' procedures
Declare Sub USB_Init Lib "libusb0.dll" ()
Declare Function USB_Find_Busses Lib "libusb0.dll" () As Integer
Declare Function USB_Find_Devices Lib "libusb0.dll" () As Integer
Declare Function USB_Get_Busses Lib "libusb0.dll" () As USB_Bus
Declare Function USB_Open Lib "libusb0.dll" _
        (ByRef Device As USB_Device) As USB_dev_handle
Declare Function USB_Close Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle) As Integer
Declare Function USB_Set_Configuration Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Configuration As Integer) As Integer
Declare Function USB_Set_AltInterface Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Alternate As Integer) As Integer
Declare Function USB_ResetEp Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Long) As Integer
Declare Function USB_Clear_Halt Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Long) As Integer
Declare Function USB_Reset Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle) As Integer
Declare Function USB_Claim_Interface Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Interface As Integer) As Integer
Declare Function USB_Release_Interface Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Interface As Integer) As Integer
Declare Function USB_Control_Msg Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal RequestType As Integer, _
         ByVal Request As Integer, _
         ByVal Value As Integer, _
         ByVal Index As Integer, _
         ByRef Bytes As String, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Get_String Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Index As Integer, _
         ByVal LangId As Integer, _
         ByRef Buf As String, _
         ByVal BufLen As Long) As Integer
Declare Function USB_Get_String_Simple Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal Index As Integer, _
         ByRef Buf As String, _
         ByVal BufLen As Long) As Integer
Declare Function USB_Get_Descriptor Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal sType As String, _
         ByVal Index As String, _
         ByRef Buf, _
         ByVal Size As Integer) As Integer
Declare Function USB_Get_Descriptor_By_EndPoint Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByVal sType As String, _
         ByVal Index As String, _
         ByRef Buf, _
         ByVal Size As Integer) As Integer
Declare Function USB_Bulk_Write Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As String, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Bulk_Read Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Interrupt_Write Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Interrupt_Read Lib "libusb0.dll" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer

das inderdaad waar ik bang voor was ....
er wordt weer gebruik gemaakt van bizarre dingen (lees : vuiligheid) die gewoonweg niet te porteren vallen.

dit ding retourneert een soort 'linked list' ...

en dit is ook al helemaal onnozel :


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

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

dit begrijp ik niet :


struct usb_device {
  struct usb_device *next, *prev;

hoe kan een structuur nu een referentie naar zijn eigen bevatten ?

en hoe kan de ene struct een referentie naar een andere bevatten die dan weer naar de eerste wijst ...

das om onnozel van te worden...

dat placeholder mechanisme snap ik maar dat kan nooit 1 char zijn. elke pointer is een 32 bit getal..... dus dat kan niks anders dan een long zijn.

tis een miserieding tot en met. ik heb ook al de source van de dll proberen te bestuderen. daar staat nergens geen lijn commentaar in wat het doet , hoe het werkt ... tis triestig. ik dacht dat de bedoleing van copen source was dat iederen kon zien hoe het werkte. maar zoals het nu is kan je telkens het warmm water ( ik zou eerder durven spreken van 'water op kamertemperatuur' terug uitvinden.

ik begin er stillekesaan genoeg van te krijgen.

nog iets waar ik niet aan uit kan:


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;

waarom is de voorlaatste lijn geen pointer ?

[Bericht gewijzigd door free_electron op ]

Ik heb een tijdje terug de vertaling gemaakt van C naar delphi, dit is ook de code die mmsoft een aantal posts naar boven heeft staan.

In delphi is het, net als in VB, ook niet mogelijk om binnen een structure (record in delphi) een pointer naar een structure van hetzelfde type aan te maken. Vandaar de enigzins "dirty" oplossing, gewoon een untyped pointer. Voor de DLL maakt dat helemaal niets uit.
Er zijn vast wel dergelijke truucjes te bedenken voor VB dacht ik zo?

Om even een simpel voorbeeldje te geven in delphi:



  Tusb_dev_handle = pointer;
  Pusb_dev_handle = ^Tusb_dev_handle;

  Tusb_device = Record
    next : pointer;
    prev : pointer;
    filename : array [0..511] of char;
    bus : pointer;
    descriptor : Tusb_device_descriptor;
    config : pointer;
    dev : pointer;// void *dev;		/* Darwin support */
    devnum : char;
    num_children : char;
    children : pointer;
  end;
  Pusb_device = ^Tusb_device;


  Tusb_bus = Record
    next : pointer;
    prev : pointer;
    dirname : array [0..511] of char;
    devices : pointer;
    location : longint;
    root_dev : pointer;
  end;
  Pusb_bus = ^Tusb_bus;

function usb_find_busses  : integer;  stdcall; external 'libusb0.dll';
function usb_find_devices : integer;  stdcall; external 'libusb0.dll';
function usb_get_busses   : Pusb_bus; stdcall; external 'libusb0.dll';
function usb_open (dev : Pusb_device): Pusb_dev_handle; stdcall; external 'libusb0.dll';


function TUSB_Device.OpenDevice(vendorID, productID : word): Pusb_dev_handle;
var
  bus : Pusb_bus;
  dev : Pusb_device;
  found : boolean;
  udev : Pusb_dev_handle;
begin
  found := false;
  usb_find_busses;
  usb_find_devices;
  bus := usb_get_busses;
  while bus <> NIL do
  begin
    dev := bus.devices;
    while dev <> NIL do
    begin
      if (dev.descriptor.idVendor = vendorID) and (dev.descriptor.idProduct = productID) then
      begin
        found := true;
        udev := usb_open(dev);
      end;
      dev := dev.next;
    end;
    bus := bus.next;
  end;
  if found then
    result := udev
  else
    result := NIL;
end;

Op 4 januari 2007 00:16:52 schreef KillerB the Supreme:
Ik heb een tijdje terug de vertaling gemaakt van C naar delphi, dit is ook de code die mmsoft een aantal posts naar boven heeft staan.

Er zijn vast wel dergelijke truucjes te bedenken voor VB dacht ik zo?

de vraag is dan : als je daar gewoon een pointer doorgeeft : waar staat de data dan ? ( met andere woorden : wordt er genoeg memory gealloceeerd om de boel te stockeren ? ) das immers de reden dat je een pointer naar een structuur doorgeeft : je zorgt daar dat er genoeg memory is om de boel te stockeren. gans die boel is een linked list die groeit en krimpt in functie van het aantal devices wat ingeplugd is.

het blijft een vreemde manier om dingen door te geven.
veel simpeler was geweest om al die miserie af te handelen IN de dll.

er is ook geen 'pointer' datatype in vb. je moet door middel van copymame en varptr de boel achterhalen en moven naar waar je wilt ( copymem is ene windows api call )

dit betekent dat er een klets glue code moet gemaakt worden in vb om die data te retrieven.

het is veel simpeler (denk ik) om in ene tussen dll een nieuwe API te definieren die de boel platklopt

api :

usb_init

usb_finddevices ( retourneert een integer die aangeeft hoeveel er gevonden zijn , bijvoorbeel 3 geeft aan dat er 4 devices zijn ( 0 tot en met 3 ))

usb_info(device nummer,datablock) device nummer zit dan tussen 0 en de waarde die je bekomen hebt uit usb_finddevices

usb_info (device nummer,datablock)
stockeert in 'datablock' een fixed size string met daarin comma delimited data (of desnoods fixed size velden) : gans die usb descriptor zit daar in.
als het device ondertussen unplugged is komt er een lege string terug.

usb_open(device ) opnieuw een nummer uit de lijst. . retourneert 0 of 1 ( 1=success ) ( 0 = failed )

en dan heb je gewoon send en receive. die je het device nummer, het aantal bytes en een pointer naar het datablok

usb_send(device_nummer,endpoint,aantalbytes,datablock)

usb_close(device)

tis properder en veel simpeler om te gebruiken , en het pint je niet vast op vuile 'c' constructies die niet porteerbaar zijn naar andere talen.

ik ben bang voor memory leak problems als die geneste lists niet proper kunnen gepasseerd worden.

nog een vraag :
wat betekent die ^ in de volgende code :


Tusb_dev_handle = pointer;
  Pusb_dev_handle = ^Tusb_dev_handle;

[Bericht gewijzigd door free_electron op ]

Op 4 januari 2007 02:45:27 schreef free_electron:

de vraag is dan : als je daar gewoon een pointer doorgeeft : waar staat de data dan ? ( met andere woorden : wordt er genoeg memory gealloceeerd om de boel te stockeren ? ) das immers de reden dat je een pointer naar een structuur doorgeeft : je zorgt daar dat er genoeg memory is om de boel te stockeren. gans die boel is een linked list die groeit en krimpt in functie van het aantal devices wat ingeplugd is.

het blijft een vreemde manier om dingen door te geven.
veel simpeler was geweest om al die miserie af te handelen IN de dll.

Het wordt ook juist allemaal afgehandeld in de DLL. Dat is het hele idee erachter. De pointers verwijzen naar geheugen dat gealloceerd is in de DLL. Je hoeft zelf dus helemaal niets te alloceren, alleen de pointers naar de betreffende structures.

Op 4 januari 2007 02:45:27 schreef free_electron:

nog een vraag :
wat betekent die ^ in de volgende code :


Tusb_dev_handle = pointer;
  Pusb_dev_handle = ^Tusb_dev_handle;

^ wil zeggen dat Pusb_dev_handle een pointer is naar een structure van het type Tusb_dev_handle. De eerste typedeclaratie van Tusb_dev_handle is wat verwarrend, het is eigenlijk een handle, ipv een pointer (maar dat komt op het zelfde neer, 4 bytes). Anders gezegd, Pusb_dev_handle is dus een pointer naar een devicehandle.

Delphi is best makkelijk in pointers, het symbool ^ "wijst" ergens heen, dit is sneller te begrijpen als de * van C. In C wordt de * ook gebruikt voor dereferencing, erg verwarrend. Delphi heeft daarvoor het @ symbool. Als je @ al vertaald naar "at" (en niet ape-staartje ;)) dan snap je direct dat er gedereferenced wordt.

kzal vandaag nog ne keer ene poging wagen om het in VB te doen.

die dephi code is tenminste een stuk leesbaarder dan usb.h ...

kheb ondertussen bij Intel wat code gehaald in zuivere VB geschreven om ook USB te doen ZONDER externe DLL.
blijkt dat je dat kan via API calls naar windows zelf .....

oh zonder dll??? daar ben ik ook wel geinteresseerd in! gewoon standaard win-aapjes?

bon we zijn een stuk verder.
ik heb een paar support routines geschreven om in het memory te kunnen rondkoteren. zo kan ik 'kijken' wat er echt terugkeert en dat te mappen op mijn structuren.


Option Explicit
' twee woorden uitleg :
' shortint in C is een Integer in VB
' Char is een byte in VB
' pointers komen ALTIJD terug als long !
' functienamen in DLL's zijn CASE sensitive !! 
' de enige manier om dit te forceren is het gebruik van ALIAS in de
' functiedeclaratie. dit zorgt er voor dat niet accidenteel een naam 
' van case verandert door een user typo...
' VB strings zijn ALTIJD unicode !!! let daar geweldig mee op.

 Const LIBUSB_PATH_MAX = 512
 

'Device and/or Interface Class codes
    Const USB_CLASS_PER_INTERFACE = 0
    Const USB_CLASS_AUDIO = 1
    Const USB_CLASS_COMM = 2
    Const USB_CLASS_HID = 3
    Const USB_CLASS_PRINTER = 7
    Const USB_CLASS_MASS_STORAGE = 8
    Const USB_CLASS_HUB = 9
    Const USB_CLASS_DATA = 10
    Const USB_CLASS_VENDOR_SPEC = &HFF
'Descriptor types
    Const USB_DT_DEVICE = &H1
    Const USB_DT_CONFIG = &H2
    Const USB_DT_STRING = &H3
    Const USB_DT_INTERFACE = &H4
    Const USB_DT_ENDPOINT = &H5
    Const USB_DT_HID = &H21
    Const USB_DT_REPORT = &H22
    Const USB_DT_PHYSICAL = &H23
    Const USB_DT_HUB = &H29
'Descriptor sizes per descriptor type
    Const USB_DT_DEVICE_SIZE = 18
    Const USB_DT_CONFIG_SIZE = 9
    Const USB_DT_INTERFACE_SIZE = 9
    Const USB_DT_ENDPOINT_SIZE = 7
    Const USB_DT_ENDPOINT_AUDIO_SIZE = 9
    Const USB_DT_HUB_NONVAR_SIZE = 7
'Enpoint Descriptors...
    Const USB_MAXENDPOINTS = 32
    Const USB_ENDPOINT_ADDRESS_MASK = &HF
    Const USB_ENDPOINT_DIR_MASK = &H80
    Const USB_ENDPOINT_TYPE_MASK = &H3
    Const USB_ENDPOINT_TYPE_CONTROL = 0
    Const USB_ENDPOINT_TYPE_ISOCHRONOUS = 1
    Const USB_ENDPOINT_TYPE_BULK = 2
    Const USB_ENDPOINT_TYPE_INTERRUPT = 3
'Diverse
    Const USB_MAXINTERFACES = 32
    Const USB_MAXALTSETTING = 128
    Const USB_MAXCONFIG = 8
'Standard requests
    Const USB_REQ_GET_STATUS = &H0
    Const USB_REQ_CLEAR_FEATURE = &H1
    Const USB_REQ_SET_FEATURE = &H3
    Const USB_REQ_SET_ADDRESS = &H5
    Const USB_REQ_GET_DESCRIPTOR = &H6
    Const USB_REQ_SET_DESCRIPTOR = &H7
    Const USB_REQ_GET_CONFIGURATION = &H8
    Const USB_REQ_SET_CONFIGURATION = &H9
    Const USB_REQ_GET_INTERFACE = &HA
    Const USB_REQ_SET_INTERFACE = &HB
    Const USB_REQ_SYNCH_FRAME = &HC
    Const USB_TYPE_STANDARD = 0
    Const USB_TYPE_CLASS = &H20       ' (0x01 << 5)  waarschijnlijk shift left ...
    Const USB_TYPE_VENDOR = &H40      ' (0x02 << 5) dus ik heb de boel al geshift
    Const USB_TYPE_RESERVED = &H60     '(0x03 << 5) hier
    Const USB_RECIP_DEVICE = &H0
    Const USB_RECIP_INTERFACE = &H1
    Const USB_RECIP_ENDPOINT = &H2
    Const USB_RECIP_OTHER = &H3
   
    Const USB_ENDPOINT_IN = &H80
    Const USB_ENDPOINT_OUT = &H0
    Const USB_ERROR_BEGIN = 500000
' Data structures
Type USB_Descriptor_Header
     bLength As Byte
     bDescriptorType As Byte
End Type
Type USB_String_descriptor
     bLength As Byte
     bDescriptorType As Byte
     wdata As Integer          ' dit wordt gebruikt als plaeholder voor de array . is eigenlijk ene pointer
End Type
Type USB_Hid_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bcdHID As Integer
     bCountrycode As Byte
     bNumdescriptors As Byte
End Type
Type USB_Endpoint_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bEndpointaddress As Byte
     bmAttributes As Byte
     wMaxPacketSize As Integer
     bInterval As Byte
     bRefresh As Byte
     bSynchAddress As Byte
     extra As Byte              ' Dit is ene placeholder. is eigenlijk een pointer naar de data ararray
     extralen As Integer
End Type
Type USB_Interface_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bInterfaceNumber As Byte
     bAlternateSetting As Byte
     bNumEndpoints As Byte
     bInterfaceClass As Byte
     bInterfaceSubClass As Byte
     bInterfaceProtocol As Byte
     iInterface As Byte
     EndPoint As Long 'dit is ene pointer naar een type : USB_EndPoint_Descriptor
     extra As Byte
     extralen As Integer
End Type
Type USB_Interface
     AltSetting As Long 'dit is een pointer naar een type : USB_Interface_Descriptor
     Num_AltSetting As Integer
End Type
Type USB_Config_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     wTotalLength As Integer
     bNumInterfaces As Byte
     bConfigurationValue As Byte
     iConfiguration As Byte
     bmAttributes As Byte
     MaxPower As Byte
     Interface As Long ' pointer naar een type : USB_Interface
     extra As Byte     ' pointer naar extra descriptors
     extralen As Long
End Type
Type USB_Device_Descriptor
     bLength As Byte
     bDescriptorType As Byte
     bcdUSB As Integer
     bDeviceClass As Byte
     bDeviceSubClass As Byte
     bDeviceProtocol As Byte
     bMaxPacketSize0 As Byte
     idVendor As Integer
     idProduct As Integer
     bcdDevice As Integer
     iManufacturer As Byte
     iProduct As Byte
     iSerialNumber As Byte
     bNumConfigurations As Byte
End Type
Type USB_Ctrl_Setup
  bRequestType As Byte
  bRequest As Byte
  wValue As Integer
  wIndex As Integer
  wLength As Integer
End Type
Type USB_Device
     next_dev As Long  ' pointer naar een type : USB_device
     prev_dev As Long  ' pointer naar een type : USB_device
     filename(LIBUSB_PATH_MAX) As Byte
     Bus As Long       ' pointer naar een type : USB_Bus
     Descriptor As USB_Device_Descriptor ' dit is een geforwarde struct :  USB_Device_Descriptor
     Config As USB_Config_Descriptor     ' dit is een geforwarde struct : USB_Config_Descriptor
     dummy As Long ' dummy pointer voor darwin support
     devnum As Byte
     num_children As Byte
     children As Long     ' dit is een pointer naar een array van types : usb_device . het aantal zit in 'num_children
End Type
Type USB_Bus
     next_dev As Long   ' pointers naar een zelfde type : usb_bus
     prev_dev As Long   ' pointers naar een zelfde type : usb_bus
     DirName(LIBUSB_PATH_MAX) As Byte
     Devices As Long ' pointer naar een type : USB_Device
     Location As Single
     root_device As Long ' pointer naar het root device type : usb_device
End Type
Type usb_dll
     major As Long
     minor As Long
     micro As Long
     nano As Long
End Type
Type usb_driver
     major As Long
     minor As Long
     micro As Long
     nano As Long
End Type
Type usb_version
     dll As usb_dll
     driver As usb_driver
End Type

Type USB_dev_handle
     pointer As Long ' dit is een pointer naar interne data in libusb.dll
End Type

' procedures
' opgelet ! de functinamen MOETEN lowercase zijn !!! ik heb aliassen gebruikt om de boel te forceren

Declare Sub USB_Init Lib "libusb0.dll" Alias "usb_init" ()
Declare Function USB_Find_Busses Lib "libusb0.dll" Alias "usb_find_busses" () As Integer
Declare Function USB_Find_Devices Lib "libusb0.dll" Alias "usb_find_devices" () As Integer
Declare Function USB_get_busses Lib "libusb0.dll" Alias "usb_get_busses" () As Long ' dit geeft een pointer naar USB_Bus
Declare Function USB_open Lib "libusb0.dll" Alias "usb_open" _
        (ByRef Device As USB_Device) As Long ' pointer naar een USB_dev_handle
Declare Function USB_close Lib "libusb0.dll" Alias "usb_close" _
        (ByRef Device As USB_dev_handle) As Integer
Declare Function USB_set_configuration Lib "libusb0.dll" Alias "usb_set_configuration" _
        (ByRef Device As USB_dev_handle, _
         ByVal Configuration As Integer) As Integer
Declare Function USB_set_altinterface Lib "libusb0.dll" Alias "usb_set_altinterface" _
        (ByRef Device As USB_dev_handle, _
         ByVal Alternate As Integer) As Integer
Declare Function USB_resetep Lib "libusb0.dll" Alias "usb_resetep" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Long) As Integer
Declare Function USB_clear_Halt Lib "libusb0.dll" Alias "usb_clear_Halt" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Long) As Integer
Declare Function USB_reset Lib "libusb0.dll" Alias "usb_reset" _
        (ByRef Device As USB_dev_handle) As Integer
Declare Function USB_Claim_Interface Lib "libusb0.dll" Alias "usb_claim_interface" _
        (ByRef Device As USB_dev_handle, _
         ByVal Interface As Integer) As Integer
Declare Function USB_release_Interface Lib "libusb0.dll" Alias "usb_release_Interface" _
        (ByRef Device As USB_dev_handle, _
         ByVal Interface As Integer) As Integer
Declare Function USB_control_Msg Lib "libusb0.dll" Alias "usb_control_msg" _
        (ByRef Device As USB_dev_handle, _
         ByVal RequestType As Integer, _
         ByVal Request As Integer, _
         ByVal Value As Integer, _
         ByVal Index As Integer, _
         ByRef Bytes As String, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_get_string Lib "libusb0.dll" Alias "usb_get_string" _
        (ByRef Device As USB_dev_handle, _
         ByVal Index As Integer, _
         ByVal LangId As Integer, _
         ByRef Buf As String, _
         ByVal BufLen As Long) As Integer
Declare Function USB_get_string_simple Lib "libusb0.dll" Alias "usb_get_string_simple" _
        (ByRef Device As USB_dev_handle, _
         ByVal Index As Integer, _
         ByRef Buf As String, _
         ByVal BufLen As Long) As Integer
Declare Function USB_get_descriptor Lib "libusb0.dll" Alias "usb_get_descriptor" _
        (ByRef Device As USB_dev_handle, _
         ByVal sType As String, _
         ByVal Index As String, _
         ByRef Buf, _
         ByVal Size As Integer) As Integer
Declare Function USB_get_descriptor_by_endPoint Lib "libusb0.dll" Alias "usb_get_descriptor_by_endPoint" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByVal sType As String, _
         ByVal Index As String, _
         ByRef Buf, _
         ByVal Size As Integer) As Integer
Declare Function USB_Bulk_Write Lib "libusb0.dll" Alias "usb_bulk_write" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As String, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Bulk_Read Lib "libusb0.dll" Alias "usb_bulk_read" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Interrupt_Write Lib "libusb0.dll" Alias "usb_interrupt_write" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer
Declare Function USB_Interrupt_Read Lib "libusb0.dll" Alias "usb_interrupt_read" _
        (ByRef Device As USB_dev_handle, _
         ByVal EndPoint As Integer, _
         ByRef Bytes As Byte, _
         ByVal Size As Integer, _
         ByVal TimeOut As Integer) As Integer

'-----------------------------------------------------------------------------------------------
' Hieronder staan routines die mij toestaan in het geheugen rond te 'koteren'
' Dump is een routine die memory dumpt . kwestie van te zien wat er werkelijk terugkeert ...
' copymemeory is een kernel call die mij toestaat om vanaf een gegeven address ( de pointer )
' een klets geheugen te kopieren naar ergenst anders

' bijvoorbeeld ik krijg ene pointer terug naar een of andere structuur die 10 byte lang is
' ik maak iets gelijkaardig in visual basic aan.
'  laat ons zeggen x is de geretrouneerde pointer
'  type my_type
'     a1 as long ' 4 byte
'     a2 as long ' 4 byte
'     a3 as integer ' 2 byte
'  end type
'  dim y as my_type
'  copymemory(y,x,10)  ' kopieer 10 bytes vanaf pointer 'x' naar 'y'
'                      ' aangezien variableen altijd via pointer toorgegeven worden in vb gebeurt dit.
'                        de structuur wordt dus mooi overgekopieerd
'                        en ik kan gewoon a2 opvragen .... dat geeft mij dan byte 4 tot en met 7 uit de 10 byte array

Private Declare Function lstrlenA Lib "kernel32" (ByVal lpString As Long) As Long
Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (pTo As Any, _
         uFrom As Any, _
         ByVal lSize As Long)

' dump is een routine die memory dumpt . kwestie van te zien wat er werkelijk terugkeert ...
Public Function Dump(ByVal Buffer As Long, ByVal Block_Size As Long) As String
   Dim Internal_Buffer() As Byte ' make internal storage space
   Dim Internal_Block_Size
   Dim Result As String          ' this holds the 'dump' in user readable form
   Dim i As Long, j As Long
   ReDim Internal_Buffer(0 To Block_Size - 1) As Byte
   Call CopyMemory(Internal_Buffer(0), ByVal Buffer, Block_Size)
   Result = String(81, "=") & vbCrLf & "Buffer Address = 0x" & Hex$(Buffer) & _
            " : Block_Size = 0x" & Hex$(Block_Size) & " (" & Block_Size & ")d"
   If Block_Size Mod 16 = 0 Then    ' boundary needs to be correct
      Internal_Block_Size = Block_Size
   Else
      Internal_Block_Size = ((Block_Size \ 16) + 1) * 16
   End If
   For i = 0 To (Internal_Block_Size - 1)
      If (i Mod 16) = 0 Then Result = Result & vbCrLf & Right$("00000000" & Hex$(Buffer + i), 8) _
                                      & "  " & Right$("0000" & Hex$(i), 4) & "  "
      If i < Block_Size Then
         Result = Result & Right$("0" & Hex(Internal_Buffer(i)), 2)
      Else
         Result = Result & "  "
      End If
      If (i Mod 16) = 15 Then
         Result = Result & "  "
         For j = (i - 15) To i
            If j < Block_Size Then
               If Internal_Buffer(j) >= 32 And Internal_Buffer(j) <= 126 Then
                  Result = Result & Chr$(Internal_Buffer(j))
               Else
                  Result = Result & "."
               End If
            End If
         Next j
         ElseIf (i Mod 8) = 7 Then ' Insert '-'
            Result = Result & "-"
      Else ' Insert space
         Result = Result & " "
      End If
   Next i
   Dump = Result & vbCrLf & String(81, "=") & vbCrLf
End Function
Public Function PointerToStringA(ByVal lpStringA As Long) As String
   Dim Buffer() As Byte
   Dim nLen As Long
   If lpStringA Then
      nLen = lstrlenA(ByVal lpStringA)
      If nLen Then
         ReDim Buffer(0 To (nLen - 1)) As Byte
         CopyMemory Buffer(0), ByVal lpStringA, nLen
         PointerToStringA = StrConv(Buffer, vbUnicode)
      End If
   End If
End Function

Public Function PointerToStringW(ByVal lpStringW As Long) As String
   Dim Buffer() As Byte
   Dim nLen As Long
   If lpStringW Then
      nLen = lstrlenW(lpStringW) * 2
      If nLen Then
         ReDim Buffer(0 To (nLen - 1)) As Byte
         CopyMemory Buffer(0), ByVal lpStringW, nLen
         PointerToStringW = Buffer
      End If
   End If
End Function
Public Function PointerToDWord(ByVal lpDWord As Long) As Long
   Dim nRet As Long
   If lpDWord Then
      CopyMemory nRet, ByVal lpDWord, 4
      PointerToDWord = nRet
   End If
End Function

maak een formpje aan met 4 command buttons
(command1 tot en met command4) en een label ( dat label noem je usrmsg


Private Sub Command1_Click()
    USB_Init
End Sub
Private Sub Command2_Click()
    Dim x As Long
    x = USB_Find_Busses()
    msg "USB_find_busses returned : " & x
End Sub
Private Sub Command3_Click()
    Dim x As Long
    x = USB_Find_Devices()
    msg "USB_find_devices returned : " & x
End Sub
Private Sub Command4_Click()
    Dim x As Long
    Dim my_usb_bus As USB_Bus   ' maak een variabele aan van het type usb_bus
    x = USB_get_busses()        ' x bevat nu een pointer naar een array van type USB_Bus
    msg "pointer returned " & x ' toon het addresss
    Debug.Print Dump(x, &H2FF)  ' kijk eens wat er in zit ....
End Sub
Sub msg(txt$)
    usrmsg.Caption = txt$
End Sub
Private Sub Command5_Click()
   usb_get_devices
End Sub
Private Sub Form_Load()
    usrmsg.Width = Me.Width
End Sub

dat staat je to om al de bus te proben en het aantal devices te retrieven.

nu de rest nog ...

der moet wat 'glue' code gemaakt worden om door middel van copymemory de boel te kunnen 'afwandelen'.

das voor de komende uren... eerst eten :p

Op 4 januari 2007 17:10:24 schreef free_electron:
kheb ondertussen bij Intel wat code gehaald in zuivere VB geschreven om ook USB te doen ZONDER externe DLL.
blijkt dat je dat kan via API calls naar windows zelf .....

'k wordt ook nieuwsgieurig?
linkie?

een update


' Define some local variables
Dim my_bus As USB_Bus
Dim my_usb_device As USB_Device
Dim x As Long
Dim bus_name, device_name
Dim manstring As String * 20
Dim ret As Integer

Private Sub Command1_Click()
    Dim device As Long
    Dim ptr_device As USB_Device
    Dim handle As USB_dev_handle
    USB_Init
    msg "Called USB_init"
    x = USB_Find_Busses()
    msg "Calling USB_find_busses returned : " & x
    x = USB_Find_Devices()
    msg "Calling USB_find_Devices returned : " & x
    my_bus = my_USB_get_busses
    msg "Bus name = " & my_bus.DirName & vbCrLf
    msg vbCrLf & "The address of the first devices is " & Hex$(my_bus.Devices)
    device = my_bus.Devices
    
    While device <> 0
         Call CopyMemory(my_usb_device, ByVal device, &H230)
             ' 230 hex (560 bytes) is the exact size of the information held in a
             ' USB_device datablock. so that is how many need to be retrieved from the
             ' memory pointed at by 'device'
         msg "This device is called " & my_usb_device.filename & vbCrLf
         msg "-- Length             : " & Hex$(my_usb_device.Descriptor.bLength)
         msg "-- Descriptortype     : " & Hex$(my_usb_device.Descriptor.bDescriptorType)
         msg "-- bcdUSB             : " & Hex$(my_usb_device.Descriptor.bcdUSB)
         msg "-- Device class       : " & Hex$(my_usb_device.Descriptor.bDeviceClass)
         msg "-- Device Subclass    : " & Hex$(my_usb_device.Descriptor.bDeviceSubClass)
         msg "-- Device Protocol    : " & Hex$(my_usb_device.Descriptor.bDeviceClass)
         msg "-- Max Packetsize     : " & Hex$(my_usb_device.Descriptor.bDeviceClass)
         msg "-- Vendor ID          : " & Hex$(my_usb_device.Descriptor.idVendor)
         msg "-- Product ID         : " & Hex$(my_usb_device.Descriptor.idProduct)
         msg "-- bcdDevice          : " & Hex$(my_usb_device.Descriptor.bcdDevice)
         msg "-- iManufacturer      : " & Hex$(my_usb_device.Descriptor.iManufacturer)
         msg "-- iProduct           : " & Hex$(my_usb_device.Descriptor.iProduct)
         msg "-- iSerialnumber      : " & Hex$(my_usb_device.Descriptor.iSerialNumber)
         msg "-- bNumConfigurations : " & Hex$(my_usb_device.Descriptor.bNumConfigurations)
                
     '  handle = USB_open(my_usb_device)  ' <<< hier zit ik vast
         
     '    msg "----- Device Opened     : Handle  " & Hex$(handle.pointer)
     '    ret = USB_get_string_simple(handle, my_usb_device.Descriptor.iManufacturer, manstring, 20)
     '    msg "----- Manufacturer name : " & manstring
     '    ret = USB_close(handle)
         
         msg vbCrLf & "The next device sits at address " & Hex$(my_usb_device.next_dev)
         device = my_usb_device.next_dev
    Wend
    Debug.Print "stop"
End Sub
Sub msg(txt$)
    Text1.Text = Text1.Text & txt$ & vbCrLf
    Debug.Print txt$
End Sub

ik zit vast bij het openen. ik krijg steeds ' bad dll calling convention. ik krijg nog kop nog staart aan wat die usb_open routine daar precies verwacht ...

my_usb_device is van het type usb_device. net wat die usb_open verwacht ... en toch lukt het niet ...

ok . probleem is al voor 90 % opgelost nu.

het blijkt dat de calls die in libusb0 zitten geen
STDcalls zijn zoals windows die wil hebben , maar C-calls. ( cdecl calls ) vandaar ook mijn 'bad dll calling cinvention probleem' en das niet oplosbaar.

windows staat je toe om cdecl te gebruiken maar dat werkt enkel en alleen met programmas die in c geschreven zijn. ( onderandere die ganse miserie met pointers en linked lists )

er is een oplossing. Stefan ( die kerel die libusb gemaakt heeft ) heeft een library die WEL stdcalls gebruikt. dit is een wrapper rond libusb0 die de translatie doet. ( je kan met visual studio C dergelijke wrappers semi-automatisch aanmaken ).

ik heb ondertussen de dll en de code.

enig probleem is dat er 2 functies zijn die NIET porteerbaar zijn naar STDcalls en dat zijn net die functies die je toelaten om de device paramters te lezen.

goed nieuws : der wordt aan gewerkt nu :)

van zodra ik ene klets werkende code heb post ik die.

He das raar, ik heb daar ook problemen mee gehad, maar ik moest juist stdcall toevoegen aan de dll declaratie onder delphi. cdecl, safecall, pascal en register werkte allemaal niet.

Misschien een opmerking Free, ik stuur een pointer naar de structure mee bij het open commando, dus niet de structure zelf (hoewel dat in principe ook een pointer is maargoed). Ik weet niet hoe je dat nu precies in VB doet.

je kan vb die pointer mooi aanmaken maar die staat ergens op de stack van het vb programma. intern in libusb kan je daar niet aan ( dat blok is locked omdat het niet tot het libusb0 process behoort. daarvoor dient die stdcall : dat is een grensoverschrijdend mechanisme.

je hebt een interne pointer nodig in libusb. tijdens de passing gebeurt er translatie omdat vb ALTIJD van een STDcall uit gaat. ( je kan niet anders . er is gene manier om cdecl te passeren omdat dat 'not the microsoft way' is. microsoft heeft daar ene appnote over : alle shared libraries , met andere woorden libraries die je wilt delen ( niet alle dll's zijn shared. je kan perfect dll maken voor je eigen gebruik. dan trek je je daar niks van aan. ) ) moeten die stdcall exporteren.

bijkomend voordeel : stdcalls zijn thread safe. cdecl calls niet !

ter verduidleijking. ik kan die call doen , maar de parameter passing lukt niet. VB doet daar ene translatie omdat hij van stdcall uit gaat.

enfin we wijken af.

ik pruts vandaag wel verder.

ik ga 3 files maken
1) een .bas die de interfacing doet op de 'normale manier en ook een wrapper heeft zoals ik die zou willen daarrond. ( met ene interne structuur die alle informatie bevat over de usb bus zodat je niet telkens moet modderen. )

usbstart : dit start usb en probed de bus. alle gevonden informatie wordt in een type gegooid


type t_usb
    vid,vip,maxpower,manufacturere(string), product(string),packetsize,numberofendpoints
 etcetera etcetera etcetera
end type
dim usb as t_usb

een usb_device class die bulk_read , bulkwrite en alle transacties bevat die je wilt doen

dan wordt het heeel eenvoudig om usb te doen:


dim my_device as usb_device
dim blokje_data(128) as integer

for x = lbound(usb) to ubound(usb)
    if usb(x).vid = my_vid then
       if isb(x).vip = my_vip then
          found = x
       end if
    end if
next x
my_device.target = found
my_device.endpoint = 2
my_device.bulkwrite (blokje_data,128)

als je my_device niet meer nodig hebt :
set my_device = vbnull

de class handelt dan al de zever van openen , claimen en sluiten mooi af.

en het wordt heel eenvoudig om met 37 of meer device tegelijkertijd bezig te zijn.

ik geef een voorbeeld.

stle je hebt 4 van die usb naar serial convertors aan je pc hangen ( ftdi chip ) al die dingen hebben allemaal dezelfde vid en vip alleen heb je zelf de product string aangepast. je hebt ene die aan je scoop hangt , ene aan je multimeter etc. de string in dat spul is ook 'scoop' of 'multimeter'

de boel wordt dan heeel simpel


dim my_dmm as usb_device
dim my_scope as usb_device

for x = lbound(usb) to ubound(usb)
    if usb(x).vid = my_vid then
       if usb(x).vip = my_vip then
          if usb(x).productstring = "scoop" then scope =x
          if usb(x).productstring = "multimeter" then dmm=x
       end if
    end if
next x

my_dmm=dmm
my_scope=scope

hop en we zijn weg. de poorten zijn geclaimed ,staan open en we kunnen transport doen.

in princiepe moet het mogelijk zijn om tegen die ftdi te praten. ik meen mij te herinneren dat tx en rx een apart endpoint zijn ( dus niet het control endpoint )

dus in het geval van een ftdi245 is dat gewoon bytes prammen van en anaar het juiste endpoint. van het control endpoint trek je je niks aan. ( das al geinitialiseerd door hun driver )

ditto voor pic en andere processoren met een usb aan boor.d
van het control endpoint trek je je niks aa. gewoon bulk transport naar de interne fifo's.

als mijn opzet slaagt wordt usb dan zelfs simpeler om te gebruiken dan een seriele poort.

-edit- ik heb hier en daar opgekuist.. nu ik op een andere computer zit me ene kleiner scherm (minder horizontale pixels.. ipv 1680 maar 1280 ... ) zag ik dat de boel wel heel erg breed was :p )

Op 6 januari 2007 17:43:18 schreef free_electron:
[...] daarvoor dient die stdcall : dat is een grensoverschrijdend mechanisme.

bijkomend voordeel : stdcalls zijn thread safe. cdecl calls niet !

Hier heeft stdcall allemaal niets mee te maken hoor. Het is net als cdecl een calling convention, oftewel een standaard om functies aan te roepen. Beiden pushen paramerers op de stack om aan een functie mee te geven. Bij stdcall ruimt de functie zelf deze parameters weer op, bij C is dit de taak van de code die de functie aanroept.

Dat is het enige verschil, het heeft niets met grenzen of thread safe te maken. Het is puur de manier van aanroepen.

De C calling convention heeft als voordeel dat je een variabel aantal parameters kunt meegeven. Bij stdcall kan dit niet (makkelijk). Er is zelfs een windows API die de C calling convetion gebruikt, wsprintf namelijk. De rest is stdcall, gewoon omdat dat als standaard is gekozen (het heet niet voor niets standard calling convention).

Het probleem is gewoon dat VB alleen stdcall ondersteund, maar daar is technisch gezien geen reden voor.

Een wrapper DLL zou prima moeten werken, er is geen verschil in hoe parameters behandeld worden tussen C of stdcall convention, alleen hoe ze opgeruimd worden. Als de wrapper de functies aanroept en de stack opruimt erna heb je de functies als stdcall.

Op 6 januari 2007 20:34:41 schreef free_electron:
wat ik mij laten vertellen heb door een van onze locale c-guru's is dat windows op de hoogte is van stdcalls en die 'opkuis' niet laat onderbreken ( der gebeurt daar een en ander onder de motorkap. )

bij cdecl is de user zelf verantwoordelijk . als er een switch optreed net voor de opkuis en de aanroepende doet iets verkeerd is het hommeles ... bij de terugkeer.

Ik heb nog nooit van zoiets gehoord en het lijkt me ook heel sterk. Windows kan niet zien wanneer je een 'stdcall' doet omdat het niet een speciaal iets is wat afgevangen kan worden. Het is gewoon een call instructie naar een bepaald adres, of het nou stdcall of C is. Het kan net zo goed een functie call zijn binnen het programma. Windows kan ook aan een DLL niet zien of een functie stdcall of C is. De 'opkuis' is 1 instructie (add esp, x ; x aan de stack pointer toevoegen) en 1 instructie kan niet onderbroken worden. Een context switch zou geen probleem moeten zijn, ik weet niet precies hoe windows dit regelt maar de stack blijft altijd intact, ook al zou windows tussendoor dingen op de stack zetten. De stack pointer wijst altijd na de data die erop staat. Zelfs al zou het opruimen van de stack onderbroken worden, context switches zouden altijd transparant moeten zijn voor applicaties.

Waar loopt ie dan precies vast? Ik kan kijken wat er in delphi gebeurt met een bepaalde dll call, misschien kunnen we achterhalen wat er misgaat.

Gebruik je nu wel of niet de DLL ?

ik gebruik libusb dll inderdaad.
rechtstreeks onder windows kan je alleen hid calls doen of calls naar device die ene driver hebben.... dus die 'intel' code is eigenlijk alleen bruikbaar als je ene driver hebt ... en das net wat ik wil omzielen. drivers schrijven... brrrrrr....

voor driverloze lukt dat niet blijkbaar. je kan daar vanuit 'user space' niet komen.

Libusb lost dat op door libusb.sys. Dat is een kernel mode driver die een doorgeefluik naar de user mode wereld bevat.

als alles goed gaat is de boel tegen eind vanavond klaar
( ik ben de documentatie aant schrijven. ) en dan post ik het.

er zijn 3 dingen klaar

een .bas file (met commentaar) dat de interfacing doet.
een voorbeeldprogramma nagenoeg identiek aan test_usb.exe wat de ganse bus 'probed' en alle parameters ophaalt en toont.

een .cls ( een class ) die al het werk doet .

Methods:

my_device.start (index,vid,pid)
my_device.bulkwrite (endpoint,buffer,size)
my_device.bulkread (endpoint,buffer,count)
... ... ....
my_device.release

Properties :

my_device.vendor (read only property)
my_device.product (read only property)
my_device.serial (read only property)
my_device.error_string ( read only property )

Events :
my_device.error

een voorbeeldje


dim my_device as new usb_device

index=0
no_more=0
do 
  if my_device.start (index,&h341,&hcd00) =1 then
     my_device.release
     debug.print my_device.serial
     index=index+1
  else
     no_more=1
  end if
loop until no_more =1

bovenstaande code 'wandelt' door alle device met een zelfde VID en PID. stel je hebt 5 van die dingen aangesloten ( 5 dezelfde memorysticks bijvoorbeeld )

de bovenstaande code zal ze een voor een openen en hun serie nummers afprinten.

stel dat je totaal niks weet van wat er aangesloten is:
dan geef je gewoon geen vid en vip mee. ( die parameters zijn optional )


dim my_device as new usb_device
dim index 

index=0
while my_device.start(index) =1 
     debug.print "------ Device " & index & " -----------
     debug.print "VID    : " & my_device.vid
     debug.print "PID    : " & my_device.pid
     debug.print "Vendor : " & my_device.vendor
     debug.print "Product: " & my_device.product
     debug.print "Serial : " & my_device.serial
     index=index+1
     my_device.release
wend

zo simpel ist ( nu dan toch :p )