bfuller I hope the detail below is enough to get you going.
The usbIO.bas file.
Code: Select all
''------Compiled with--------------------------------------------------------------------
'' FreeBASIC Compiler - Version 1.05.0 (01-31-2016), built for linux-x86_64 (64bit)
'' This has only been tested on Linux Mint 18.3
''
'' Note: Comments are double '' to avoid problem with Gede debugger.
''
'' By setting .PrintFlag to 1 detail is printed to Terminal.(Errors are always printed)
''
''This program does the following:
'' 0: Do some Main Thread stuff before creating usbThread.
'' In the usbThread 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 in usbIO.bi
'' 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 usbAccesInit to send init cmnds to possible AccesIO devices.
'' 8: Now .Handle(n) is available to Write & Read Control Transfers to devices attached.
'' 9: usbThread checks flags to confirm all OK, then sits in loop until Quit.
'' 10: WriteOntrak & ReadOnTrak are dedicated to Ontrak ADU70 Load Cell's.
'' Read & WriteAcces are dedicated to AccesIO USB-IDIO-16L. and USB-AO16-4E
'' 11: Quit Deallocates Buffer, and closes Interface's and Libusb.
''---------------------------------------------------------------------------------------
Sub usbPortsInit
With usbPort
''----First init the Lib-----
.Found = libusb_init(0)
If .Found = 0 Then
.usbFlag = 1
If .PrintFlag > 0 Then
version = libusb_get_version()
libusb_version = *version
Print libusb_version.major;".";libusb_version.minor;".";libusb_version.micro;".";libusb_version.nano
EndIf
Else
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
Print Hex(desc.idVendor,4);":";Hex(desc.idProduct,4)
Print "Found MyDev ";MyDev;"; Device Nbr ";pdevice
.Found += 1
''----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
.usbFlag += 1
Exit For
EndIf
End if
Next MyDev
Next i
''------Use .Handle to release from Kernel and get Serial Number----
If .PrintFlag > 0 Then
If .usbFlag = 1 Then
Print "----No devices match the list in usbIO.bi----"
Exit Sub
EndIf
Print "----Claiming MyDev's and getting Serial Numbers----"
EndIf
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
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
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
Print "Load Cell i/f 0 =";.SerialNbr(0)
Print "Load Cell i/f 1 =";.SerialNbr(1)
''----------------------------------------------------
''When the Hd looks for Wt,
''assign the correct usb port (and thus the SerialNbr)
''----------------------------------------------------
Print "Settings.SerialNbr1 ;";Settings.SerialNbr1
Print "Settings.SerialNbr2 ;";Settings.SerialNbr2
If Instr(Settings.SerialNbr1,.SerialNbr(0)) > 0 Then
Status.usbPort(1) = 0
Status.usbPort(2) = 1
Else
If Instr(Settings.SerialNbr1,.SerialNbr(1)) > 0 Then
Status.usbPort(1) = 1
Status.usbPort(2) = 0
EndIf
EndIf
EndIf
End With
End Sub
Sub usbAccesInit
''------------------------------
''This Init's USB-AO16-4E board.
''------------------------------
usbError.Routine = "usbAOinit"
usbError.Module = 1
With libusb_control_setup '' With / End With , saves lots of typing.
If usbPort.Handle(3) > 0 Then
'' First set up the DIO bits
.bmRequestType = &B01000000 '' Direction is Vendor OUT from Host to Device
.bRequest = &H12 '' Tell device it is DIO Config.
.wValue = &H00 '' These only need to be done once
.wIndex = &H00 '' for the life of the program.
.wLength = &H03 '' Only 3 bytes sent / returned
Buffer[0] = &B00000000 '' Data Array (none during init)
Buffer[1] = &B00000000 '' Ignored as it will be set as I/P's
Buffer[2] = &B00000001 '' Direction Control Array O/P 0-7 , I/P 8-15
Buffer[3] = &H00 '' No Data
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(3),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,100)
If usbPort.RetBytes < 0 Then
usbError.Message = "Control Transfer Failed"
usbError.Errer = usbPort.RetBytes
Exit Sub
EndIf
'' Then set up the Analog O/P's
.bmRequestType = &B01000000 '' Direction is Vendor OUT from Host to Device
.bRequest = &HB7 '' Tell device AO is unipolar.(0-10v)
.wValue = &H00 '' 0 for Unipolar 1 for BiPolar
.wIndex = &H00 ''
.wLength = &H00 '' No Data sent
Buffer[0] = &H00
Buffer[1] = &H00
Buffer[2] = &H00
Buffer[3] = &H00
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(3),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,100)
If usbPort.RetBytes < 0 Then
usbError.Message = "Control Transfer Failed"
usbError.Errer = usbPort.RetBytes
Else
usbPort.usbFlag += 1
EndIf
EndIf
End With
End Sub
Sub ReadOntrak
'---------------------------------------------------------
'This Sub reads a Control Transfer from endpoint &h81
'as a result of the request done in WriteOnce previously
'---------------------------------------------------------
With usbPort
If (MyDev = 0) Or (MyDev = 1) Then
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
Cycle.TempCount(MyDev) = Val(.ValString(MyDev)) 'put data in place for other thread.
If .PrintFlag > 0 Then
Print "Value of Read of MyDev ";MyDev;" ";Val(.ValString(MyDev))
EndIf
End If
EndIf
If .RetValue < 0 Then
Print "Read Control Transfer Failed"
EndIf
EndIf
EndIf
End With
End Sub
Sub WriteOntrak
''---------------------------------------------------------
''This Sub writes a Control Transfer request to endpoint 1
''value of 8 is bytes expected, .TxBytes = actual sent.
''---------------------------------------------------------
With usbPort
If (MyDev = 0) Or (MyDev = 1) Then
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
EndIf
End With
End Sub
Sub ReadAcces
usbError.Routine = "ReadAcces"
usbError.Module = 1
If MyDev = 2 Then
If usbPort.Handle(MyDev) > 0 Then
With libusb_control_setup
.bmRequestType = &B11000000 '' Direction is IN from Device to Host
.bRequest = &H11 '' Give Device a Read request.
.wValue = &H00 '' These only need to be done once
.wIndex = &H00 '' for the life of the program.
.wLength = &H04 '' Indicating we expect 4 bytes
Buffer[0] = &H00 '' Reset these so READ values can be filled in.
Buffer[1] = &H00 ''
Buffer[2] = &H00 '' I/P 0-7
Buffer[3] = &H00 '' 8-15
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(MyDev),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,1000)
If IOCtrl.InputDone < 6 Then IOCtrl.InputDone += 1
If usbPort.RetBytes < 0 Then
usbError.Errer = usbPort.RetBytes
Print "Read Control Transfer Failed"
EndIf
IOCtrl.IPValue = Buffer[2] + (Buffer[3] shl 8) '' Combine LoByte & HiByte to create a UShort of 16 bits
For IPCount As UShort = 0 To 15 ''for the I/P bits returned by usbController
If Bit(IOCtrl.IPValue,IPCount) Then ''if bit returned is ON
' + 16 bit 0 input becomes bit 24 (same as IA3125)
IOCtrl.PortBit(IPCount + 16) = 1 ''set the result for Main thread
Else
IOCtrl.PortBit(IPCount + 16) = 0 ''otherwise reset " "
EndIf
Next
If IOCtrl.PortBit(Settings.LevelBit1) < 1 Then
IOCtrl.PortBit(Settings.LevelBit1) = 1
Else
IOCtrl.PortBit(Settings.LevelBit1) = 0
Endif
If IOCtrl.PortBit(Settings.LevelBit2) < 1 Then
IOCtrl.PortBit(Settings.LevelBit2) = 1
Else
IOCtrl.PortBit(Settings.LevelBit2) = 0
Endif
End With
EndIf
EndIf
If MyDev = 3 Then
If usbPort.Handle(MyDev) > 0 Then
With libusb_control_setup
''----Common values set first , then lib call-----
.bmRequestType = &B11000000 '' Direction is IN from Device to Host
.bRequest = &H11 '' Give Device a Read request.
.wValue = &H00 '' These only need to be done once
.wIndex = &H00 '' for the life of the program.
.wLength = &H04 '' Indicating we expect 4 bytes
Buffer[0] = &H00 '' Reset these so READ values can be filled in.
Buffer[1] = &H00 ''
Buffer[2] = &H00 '' I/P 0-7
Buffer[3] = &H00 '' 8-15
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(MyDev),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,1000)
''----If it is the AccesIO USB-AO16-4E.(16 bit I/O + 4 bit A/O)----
IOCtrl.OPValue = Buffer[0]
IOCtrl.IPValue = Buffer[1]
''----------------Combine---------------------------
For IPCount As UShort = 8 To 15 ''for the I/P bits returned by usbController
If Bit(IOCtrl.IPValue,IPCount - 8 ) Then ''if bit returned is ON
IOCtrl.PortBit(IPCount) = 0 ''set the result for Main thread
Else
IOCtrl.PortBit(IPCount) = 1 ''otherwise reset " "
EndIf
Next
If IOCtrl.InputDone < 6 Then IOCtrl.InputDone += 1
If usbPort.RetBytes < 0 Then
usbError.Message = "Control Transfer Failed"
usbError.Errer = usbPort.RetBytes
Else
If usbPort.PrintFlag > 0 Then Print "OpValue ,IpValue = ";IOCtrl.OPValue,IOCtrl.IPValue
EndIf
End With
EndIf
EndIf
End Sub
Sub WriteAcces
usbError.Routine = "WriteAcces"
usbError.Module = 1
If usbPort.Handle(MyDev) > 0 Then
With libusb_control_setup '' With / End With , saves lots of typing.
''------------------------------------------------------
'' If Either Device 2 or 3 we can set the OPValue.
'' MyDev 3 ,the USB-AO16-4E, ignores O/P bits > 7
''------------------------------------------------------
For BitCount As UShort = 0 To 15 '' only for 16 output bits
If IOCtrl.PortBit(BitCount) = 1 Then '' test for On/Off request.
IOCtrl.OPValue = BitReSet(IOCtrl.OPValue,BitCount) ''Acces usb-IDIO-16 requires 0 for O/P ON
Else '' and 1 for O/P OFF
IOCtrl.OPValue = BitSet(IOCtrl.OPValue,BitCount) ''or reset bit
EndIf
Next
If MyDev = 2 Then
If IOCtrl.OPValue <> IOCtrl.OldOPValue Then '' We only Write if there is a change in Bit values.
IOCtrl.OldOPValue = IOCtrl.OPValue '' Save for next comparison.
.bmRequestType = &B01000000 '' Direction is Vendor OUT from Host to Device
.bRequest = &H10 '' Give Device a Write request.
.wValue = &H00 '' These only need to be done once
.wIndex = &H00 '' for the life of the program.
.wLength = &H04 '' Only 4 bytes sent / returned
Buffer[0] = LoByte(IOCtrl.OPValue) ''O/P 0- 7
Buffer[1] = HiByte(IOCtrl.OPValue) ''O/P 8-15
Buffer[2] = &H00 ''I/P 0-7 ignored when setting O/P's
Buffer[3] = &H00 ''I/P 8-15 " "
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(MyDev),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,100)
If usbPort.RetBytes < 0 Then
usbError.Message = "Control Transfer Failed"
usbError.Errer = usbPort.RetBytes
Print "Write Control Transfer Failed"
EndIf
EndIf
EndIf
If MyDev = 3 Then
If IOCtrl.OPValue <> IOCtrl.OldOPValue Then '' We only Write if there is a change in Bit values.
IOCtrl.OldOPValue = IOCtrl.OPValue '' Save for next comparison.
.bmRequestType = &B01000000 '' Direction is Vendor OUT from Host to Device
.bRequest = &H10 '' Give Device a Write request.
.wValue = &H00 '' These only need to be done once
.wIndex = &H00 '' for the life of the program.
.wLength = &H02 '' Only 4 bytes sent / returned
Buffer[0] = LoByte(IOCtrl.OPValue) '' O/P 0- 7
Buffer[1] = &H00 '' O/P 8-15
Buffer[2] = &H00 '' I/P 0-7 ignored when setting O/P''s
Buffer[3] = &H00 '' I/P 8-15 " "
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(MyDev),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,100)
EndIf
For Feeder as Short = 0 to 3
If IOCtrl.AOValue(Feeder) <> IOCtrl.OldAOValue(Feeder) Then
IOCtrl.OldAOValue(Feeder) = IOCtrl.AOValue(Feeder)
.bmRequestType = &B01000000 '' Direction is Vendor OUT from Host to Device
.bRequest = &HB3 '' Give Device a DAC Write (Simple Form) request.
.wValue = IOCtrl.AOValue(Feeder) '' DAC output value
.wIndex = Feeder '' DAC Channel
.wLength = &H00 '' No Data sent
Buffer[0] = &H00
Buffer[1] = &H00
Buffer[2] = &H00 ''
Buffer[3] = &H00 ''
usbPort.RetBytes = libusb_control_transfer(usbPort.Handle(MyDev),.bmRequestType,.bRequest,.wValue,.wIndex,Buffer,.wLength,100)
If usbPort.RetBytes < 0 Then
usbError.Message = "Control Transfer Failed"
usbError.Errer = usbPort.RetBytes
EndIf
EndIf
Next Feeder
EndIf
End With
EndIf
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 )
usbTimer.CalTime = Timer '' Starting Calibration Time of Program
Buffer = Allocate(64)
usbPortsInit '' sets usbFlag if succesfull
usbAccesInit
Sleep 100 '' let things settle before
With usbPort
If .PrintFlag > 0 Then Print "usbFlag;";.usbFlag '' If > 0 Then Initialize was OK
If .usbFlag > 2 Then
Print "usb Thread Running"
Print "------------------"
EndIf
If .usbFlag < 2 Then
print "usb Error "
Threaddetach(ThreadHandle)
print "? Handle =";ThreadHandle
ThreadHandle = 0
.usbFlag = 0 '' Tells Main to quit
Print "Quiting usbThread "
Endif
''----------------------------------------------------------
'' Here write your own code to call each device using
'' usbPort.Handle(MyDev)
''----------------------------------------------------------
While .usbFlag '' Hangs here for duration of Thread
With usbTimer
.mSec = (Timer - usbTimer.CalTime ) * 1000
.StartTime = .mSec
For MyDev = 0 to 3
WriteOntrak
ReadOntrak
ReadAcces
WriteAcces
Next MyDev
.mSec = (Timer - usbTimer.CalTime ) * 1000
.Elapsed = .mSec - .StartTime
IOCtrl.OldBeat = IOCtrl.HeartBeat ''let screen led know Rx was OK.
End With
Wend '' Main program loop cancels .usbFlag
usbTimer.mSec = (Timer - usbTimer.CalTime ) * 1000
Print "Elapsed = ;";usbTimer.mSec - usbTimer.StartTime
End With
usbQuit '' Go release the port.
End Sub