Here a version with usb running in it's own Thread.
Worth noting that I have had usb running in it's own thread on my Industrial machines for about a year now,
and NO problems.
Code: Select all
#include once "fbthread.bi"
#include once "libusb-1.0.bi"
#Include once "usbPort.bi"
''------Compiled with--------------------------------------------------------------------
'' FreeBASIC Compiler - Version 1.05.0 (01-31-2016), built for linux-x86_64 (64bit)
''
'' Note: Comments are double '' to avoid clash with Gede debugger.
''
''This program does the following:
'' 1: Initialize Libusb
'' 2: Gets List of usb devices attached
'' 3: Uses 0-7 idVendor/idProduct's to find matches in list.
'' 4: Opens matches found and assign's .Handle(n)
'' 5: Uses .Handle(n) to check if Kernel has control, then releases it.
'' 6: Uses .Handle(n) to Claim Interface & load ascii string desc to get iSerialNumber.
'' 7: Uses Control Transfer to send a request
'' 8: Now .Handle(n) is available to Write & Read Control Transfers to devices attached.
'' 9: WriteOnce & ReadOnce are dedicated to Ontrak ADU70 Load Cell's
'' 10: Deallocates Buffer, and closes Interface's and Libusb
'' By setting .PrintFlag to 1 detail is printed to Terminal.(Errors are always printed)
'' Fill in your own .Vendor / .Product at lines 176-183
'' This has only been tested on Linux Mint 18.3
''---------------------------------------------------------------------------------------
Sub usbInitialize
With usbPort
.PrintFlag = 1
''----First init the Lib-----
.Found = libusb_init(0)
If .Found = 0 Then
.usbFlag = 1
Else
If .PrintFlag > 0 Then Print "libusb_Init = Failed"
Exit Sub
EndIf
If .Found = 0 Then
For cnt = 0 to 7
.Handle(cnt) = 0
Next
cnt = 0
''-----Get list of all usb devices (always succeeds)----------
cnt = libusb_get_device_list(NULL, @ppList)
If .PrintFlag > 0 Then Print "----Reading all usb devices to assign pDevice to MyDev numbers----"
For i = 0 to cnt-1
pDevice = ppList[i]
''-----Load found device one at a time------
.RetValue = libusb_get_device_descriptor(pDevice, @desc)
If .PrintFlag > 0 Then Print "Load desc.;";Hex(desc.idVendor,4);":";Hex(desc.idProduct,4);" From Device";i
''-----Check 8 possible matches-------------
For MyDev = 0 to 7
If Hex(desc.idVendor,4) = .Vendor(MyDev) And Hex(desc.idProduct,4) = .Product(MyDev) Then
''----If not been selected before, assign desc to this Hd number----
If .Handle(MyDev) = 0 Then
If .PrintFlag > 0 Then Print Hex(desc.idVendor,4);":";Hex(desc.idProduct,4)
If .PrintFlag > 0 Then Print "Found MyDev ";MyDev;"; Device Nbr ";pdevice
''----Open device(i) with .Handle(Hd)----
.RetValue = libusb_open(pDevice, @pHandle)
'---If an error opening------
If .RetValue < 0 Then
Print "dev_handle ;"; pHandle
Print "Error Detail ;";.RetValue
Print *(libusb_error_name(.RetValue))
Return
EndIf
.Handle(MyDev) = pHandle
pHandle = 0
Exit For
EndIf
End if
Next MyDev
Next i
''------Use .Handle to release from Kernel and get Serial Number----
If .PrintFlag > 0 Then Print "----Claiming MyDev's and getting Serial Numbers----"
For i = 0 to 7
If .Handle(i) > 0 Then
.usbFlag += 1
.RetValue = libusb_kernel_driver_active(.Handle(i),0) ''check if kernel has attached a driver
If .RetValue > 0 Then ''if so
.RetValue = libusb_detach_kernel_driver(.Handle(i), 0) ''detach it
If .PrintFlag > 0 Then Print "Detach from Kernel"
Endif
.RetValue = libusb_claim_interface(.Handle(i), 0) ''now we can claim the interface
If .RetValue = 0 Then
.usbFlag += 1 ''This allows usbThread to proceed
If .PrintFlag > 0 Then Print "Claimed I/F ";i
Else
Print "Claim I/F Fail "
Return
EndIf
ReAllocate(Buffer,64)
''------value 3 in call = index of descriptor for iSerialNumber--------
.RetValue = libusb_get_string_descriptor_ascii(.Handle(i),3,Buffer,64)
MyDev = i
''---RetValue = number of char's in iSerialNumber string------
If .RetValue > 0 Then
Dim Nbr as Ushort
If .PrintFlag > 0 Then Print "Chr's in Serial =";.RetValue
.SerialNbr(MyDev) = ""
For Nbr = 0 to .RetValue
.SerialNbr(MyDev) += Chr(Buffer[Nbr])
Next
Else
If .PrintFlag > 0 Then Print "----string_descriptor not supported on this device----"
EndIf
If .PrintFlag > 0 Then Print .SerialNbr(MyDev)
EndIf
Next
If cnt > 0 Then libusb_free_device_list(ppList,1)
'' If Initialize succeeded Then set EndFlag to allow usbThread to run.
If .usbFlag > 2 Then .EndFlag= 1
EndIf
End With
End Sub
Sub ReadOnce
'---------------------------------------------------------
'This Sub reads a Control Transfer from endpoint &h81
'as a result of the request done in WriteOnce previously
'---------------------------------------------------------
With usbPort
If .Handle(MyDev) > 0 Then
.RetValue = libusb_interrupt_transfer(.Handle(MyDev), &H81, Buffer, 64, @.RxBytes, 500 )
If .PrintFlag > 0 Then Print "Bytes Rx = ";.RxBytes
If .RetValue = 0 Then
If .RxBytes = 64 Then
.ValString(MyDev) = ""
For i as Integer = 1 to .RxBytes-1 '-1 for zero terminated string
If (Buffer[i] > 47) And (Buffer[i] < 58) Then 'if 0-9
.ValString(MyDev) += Chr(Buffer[i])
EndIf
If (i > 8) and Buffer[i] = 0 Then Exit For 'dont read trailing zeroes
Next
If .PrintFlag > 0 Then
Print "Value of Read of MyDev ";MyDev;" ";Val(.ValString(MyDev))
Else
Print Val(.ValString(MyDev));";";
EndIf
End If
EndIf
If .RetValue < 0 Then
Print "Read Control Transfer Failed"
EndIf
EndIf
End With
End Sub
Sub WriteOnce
''---------------------------------------------------------
''This Sub writes a Control Transfer request to endpoint 1
''value of 8 is bytes expected, .TxBytes = actual sent.
''---------------------------------------------------------
With usbPort
ReAllocate(Buffer,64)
Buffer[0] = &H01
Buffer[1] = 82 '' 'R'
Buffer[2] = 68 '' 'D'
If .Handle(MyDev) > 0 Then
.RetValue = libusb_interrupt_transfer(.Handle(MyDev), &H01, Buffer, 8, @.TxBytes, 500 )
If .RetValue < 0 Then
Print "Write Control Transfer Failed"
Print "Bytes Sent = ";.TxBytes
Return
EndIf
If .PrintFlag > 0 Then Print "Bytes Tx = ";.TxBytes
EndIf
End With
End Sub
Sub usbQuit
With usbPort
Dim i as uShort
'----First must release i/f Then close device------------
For i = 0 To 7
If .Handle(i) > 0 Then
.RetValue = libusb_release_interface(.Handle(i), 0)
libusb_close(.Handle(i))
If .RetValue = 0 Then
If .PrintFlag > 0 Then Print "I/F ";i;" Release=; Success"
Else
Print "I/F ";i;" Release=; Failed"
EndIf
EndIf
Next
Deallocate Buffer
Print "Buffer Closed"
Print "libusb Closed"
Libusb_exit(0)
Print "libusb exited"
.EndFlag = -1
End With
End Sub
Sub usbthread( ByVal userdata As Any Ptr )
Buffer = Allocate(64)
usbInitialize '' sets usbFlag if succesfull
Sleep 100 '' let things settle before
With usbPort
Print "usbFlag;";.usbFlag '' If > 0 Then Initialize was OK
If .usbFlag > 2 Then
Print "usb Thread Running"
Print "------------------"
EndIf
If .usbFlag < 1 Then
print "usb Error "
Threaddetach(ThreadHandle)
print "? Handle =";ThreadHandle
ThreadHandle = 0
.usbFlag = 0 '' Tells Main to quit
Print "Quiting Program "
Exit Sub
Endif
''----------------------------------------------------------
'' Here write your own code to call each device using
'' usbPort.Handle(MyDev)
''----------------------------------------------------------
While .usbFlag '' Hangs here for duration of Thread
'MyDev = 1
'WriteOnce
'ReadOnce
'MyDev = 2
'WriteOnce
'ReadOnce
Wend '' Main program loop cancels .usbFlag
End With
usbQuit '' Go release the port.
End Sub
ThreadHandle = ThreadCreate(@usbThread,CPtr(Any Ptr,Null)) ''Start usb I/O in another thread.
If ThreadHandle = 0 Then
Print "Failure to create Thread for usb."
End 10 ''If it Failed then Quit.
EndIf
''--------------------------------------------------------
''Main Program Loop which is independant of usbThread Loop
''--------------------------------------------------------
Do
If Inkey <> "" Then exit do
Loop
usbPort.usbFlag = 0 ''usbFlag tells usbThread to quit.
Print "Wait for Thread to Quit"
While usbPort.EndFlag > 0 ''EndFlag tells Main that it has quit.
ThreadWait(ThreadHandle) ''Don't terminate program with usbThread still running.
Wend
Print "Gotit"
Sleep
Notice I have shifted the Vendor detail into this .bi file.
Code: Select all
Type usbPort
Handle(0 to 7) As Long Ptr
Found As Short
usbFlag As Short
EndFlag As Short
PrintFlag As Short
RxBytes As Long
TxBytes As Long
RetValue As Long
ChrByte As String * 1
ValString(0 to 7) As String * 24
SerialNbr(0 to 7) As String * 6
Vendor (0 to 7) As String * 4
Product(0 to 7) As String * 4
End Type
Dim Shared usbPort as usbPort
''-----------------------------------------------------------------------------------
'' After confirming with lsusb (in Linux Terminal) assign .Vendor / .Product Numbers
''-----------------------------------------------------------------------------------
With usbPort
.Vendor(0) = "0A07":.Product(0) = "0046" 'Ontrak ADU70 24 bit A2D Load Cell interface
.Vendor(1) = "0A07":.Product(1) = "0046" ' ditto
.Vendor(2) = "1605":.Product(2) = "8018" 'AccesIO USB-IDIO-16L.(32 bit I/O Board)
.Vendor(3) = "1605":.Product(3) = "8077" 'AccesIO USB-AO16-4E. (16 bit I/O + 4 bit A/O)
.Vendor(4) = "":.Product(4) = ""
.Vendor(5) = "":.Product(5) = ""
.Vendor(6) = "":.Product(6) = ""
.Vendor(7) = "":.Product(7) = ""
End With
'------------------------------------
Dim shared Buffer As UByte Ptr
Dim shared as Any Ptr ThreadHandle
Dim shared as libusb_device Ptr dev
dim shared as libusb_device_descriptor desc
dim shared as libusb_device_handle ptr pHandle
dim shared as libusb_device ptr pDevice
dim shared as libusb_device ptr ptr ppList
dim shared as ssize_t cnt = 0, i = 0
dim shared as short ix = 0 , MyDev = 0
declare sub usbinitialize()
declare sub WriteOnce()
declare sub ReadOnce()
declare sub usbQuit ()
Regards