How can I use an OCX to access an USB device?

Windows specific questions.
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

How can I use an OCX to access an USB device?

Post by Manfred »

I would like to control an USB device (the DDS signal generator from SoftMark) from my own programs. Softmark provides an ActiveX driver for their USB devices, named USB.OCX, and a sample VisualBasic program showing how to send commands to the device through this OCX. They give no further information. My question is: Can I use this OCX from FreeBasic, and if so, how?

My background includes 30 years of occasional programming, more than half of it done in Basic, starting with a Casio FX702 computer and evolving through a Sinclair ZX81, Commodore Vic20, to AtariBasic, GWBasic and then many years of QuickBasic. I have never used VisualBasic, though, and I'm a bloody beginner with FreeBasic. Other languages used have been assembly of several different microprocessors and microcontrollers, plus Fortran (yes, I'm getting old!), Pascal, and a very little C++.
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

there is hardware subforum. your question will have better response there.
you can use COM/Activex with disphelper or my axsuite2.
search the forum for sample code, or submit VB code to discuss
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

Loe,
thanks fort that help. I downloaded your axsuite2 moments ago, and will try to understand how all that works. A first glimpse into the example provided wasn't enough for me to understand it, though...

I posted this topic here in in the Windows section instead of Hardware, because the issue for me is 100% Windows-related. Softmark doesn't provide any information about how to access their modules on a hardware level. They only provide that OCX, and tell everybody to use this OCX, which in turn performs the hardware access.

The sample VisualBasic program provided by Softmark first links to the provided OCX file in this way:

Object = "{3E9848A7-C355-43EA-9E8A-DFBC10F00516}#1.0#0"; "USB.OCX"

That OCX file is present on the system, of course, and has been previously registered in the Windows registry.

After that, it sets up the GUI (which I don't need at this point), does some data handling which I can easily translate myself into FB and adapt to my needs, and then it writes the data to the hardware in this way:

USB1.WR_P0 (Data_To_Port0)
USB1.WR_P1 (Data_To_Port1)

And it polls for the presence of the hardware in this way:

Text2 = USB1.Find_USB_Device

I understand these are calls to procedures and functions implemented within USB.OCX. And these two procedures and one function are all I need. No actual data needs to be read.

So, this is what I need to implement in FB: Somehow gaining access to those two procedures and one function implemented in USB.OCX.

I will try to work my way through your axsuite2, but if you can quickly tell me "it can be done in this way", or "no, that can't be done", it would be a great help!

Manfred.
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

to use COM/Activex with axsuite2, there are 3 main step:
1. creating an object.
for COM/Activex non control you can use following command

Code: Select all

axcreateobject(ProgID,ObjPtr)
ProgID: Program ID or Class ID (CLSID)
Dim Obj Ptr as lpunknown 'change lp unknown with interface vtable ptr

it similar to

Code: Select all

Object = "{3E9848A7-C355-43EA-9E8A-DFBC10F00516}
where object is ObjPtr and {...} as Class ID

2.using an object
you can use created object in 3 way (sorted from fastest to easiest):

Code: Select all

-vtable
ObjPtr->lpvtbl->method(ObjPtr,par1,par2,...,parn)

-invoke/dispatch
axcall ObjPtr.method,par1,par2,...,parn

-automation
objcall ObjPtr,"Method1@npar.method2@npar",par1,par2,...,parn
-invoke and automation use variant ptr parameter,
-vtable only for dual interface

it similar to

Code: Select all

USB1.WR_P0 (Data_To_Port0) 
USB1.WR_P1 (Data_To_Port1)
3. Release unused object

Code: Select all

-vtable
ObjPtr->lpvtbl->release(ObjPtr)

-invoke/dispatch
axcall ObjPtr.release

-automation
objcall ObjPtr,"release"
it similar if any, to

Code: Select all

USB1.Release
if you submit snippet VB code it will easier
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

Loe,
thanks, but this whole thing seems to be way above my level. I'm just an old style BASIC hobby programmer, I have no idea what is meant by an "object" in this context, and I can't make sense of what you explain, even if you are so nicely trying to make it clear! I simply lack too much of the basic knowledge about modern programming. I'm at the IF...THEN...ELSE level, and the code you write in your explanation doesn't resemble BASIC for me at all!

A small anecdote: Since your axsuite2 seems to be geared toward FBedit, I downloaded and installed that one. I was using FBJelly instead. But so far in FBedit I haven't even been able to get a "hello world" program to compile! I just get errors and more errors. I found FBJelly much more friendly, because at least "hello world" worked on the first try...

It looks like I had better forgetting the whole thing about ActiveX, specific Windows stuff, also forget about the SoftMark USB DDS module, and instead build my own DDS hardware, using a COM port for control. I can access the COM port directly from any Basic, including FB, without any complications. Designing and building the new DDS hardware will take me a lot less time than trying to figure out this ActiveX stuff to control the SoftMark hardware.

The only way I could get this ActiveX working, perhaps, is if you could tell me exactly, character by character, how I can link to that USB.OCX file provided by SoftMark, and send the control bytes to it. Otherwise I prefer to forget about the whole thing. Unfortunately I have no source code of that OCX, and no other information or explanation, except for the VB sample program. And in that program, the only interesting lines for this matter are the ones I already posted. The whole rest of it is only the GUI generation, and the math that calculates the values for the variables "Data_To_Port0" and "Data_To_Port1".

I have written to SoftMark asking for further information, and gotten no reply at all, so it doesn't look like they are willing to help. That confirms that I should better make my own DDS hardware. Unless you can magically tell me precisely how to make that USB.OCX work for me, with a practical piece of code that I can emded in a "traditional Basic" program that calculates the data to be sent.

Thanks a lot, in any case!
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

The only way I could get this ActiveX working, perhaps, is if you could tell me exactly, character by character, how I can link to that USB.OCX file provided by SoftMark, and send the control bytes to it.
***OK, then you can use automation instead.
*change to vtable call

Code: Select all


#Include Once "windows.bi"
'#Include once "axobj.bi"  'use axsuite include file
#Include once"win/ocidl.bi"
#Include Once "usbocx_vtbl.bi"

dim shared AxScode as scode
dim shared AxPexcepinfo as excepinfo
dim shared AxPuArgErr AS uinteger


'CLSCTX_INPROC_SERVER   = 1    ' The code that creates and manages objects of this class is a DLL that runs in the same process as the caller of the function specifying the class context.
'CLSCTX_INPROC_HANDLER  = 2    ' The code that manages objects of this class is an in-process handler.
'CLSCTX_LOCAL_SERVER    = 4    ' The EXE code that creates and manages objects of this class runs on same machine but is loaded in a separate process space.
'CLSCTX_REMOTE_SERVER   = 16   ' A remote machine context.
'CLSCTX_SERVER          = 21   ' CLSCTX_INPROC_SERVER OR CLSCTX_LOCAL_SERVER OR CLSCTX_REMOTE_SERVER
'CLSCTX_ALL             = 23   ' CLSCTX_INPROC_HANDLER OR CLSCTX_SERVER
SUB AXCreateObject (BYVAL strProgID AS LPOLESTR,byref ppv as lpvoid,ByVal clsctx As Integer=21)
	Dim pUnknown AS lpunknown         ' IUnknown pointer
	dim pDispatch AS lpdispatch       ' IDispatch pointer
	'dim IID_NULL as IID               ' Null GUID
	'dim IID_IUnknown as IID           ' Iunknown GUID
	'Dim IID_IDispatch as IID          ' IDispatch GUID
	dim ClassID AS CLSID         	  ' CLSID
	
	IF *strProgID = "" Then
		
		AxScode = E_INVALIDARG
		EXIT SUB
	END IF
	' Standard interface GUIDs
	'IIDFromString("{00000000-0000-0000-0000-000000000000}",@IID_NULL)
	'IIDFromString("{00000000-0000-0000-c000-000000000046}",@IID_IUnknown)
	'IIDFromString("{00020400-0000-0000-c000-000000000046}",@IID_IDispatch)
	' Exit if strProgID is a null string
	' Convert the ProgID in a CLSID
	AxScode=CLSIDFromProgID(strProgID,@ClassID)
	' If it fails, see if it is a CLSID
	IF AxScode<>0 THEN AxScode=IIDFromString(strProgID,@ClassID)
	' If not a valid ProgID or CLSID return an error
	IF AxScode<>0 Then		
		AxScode = E_INVALIDARG
		EXIT SUB
	END IF
	' Create an instance of the object
	AxScode = CoCreateInstance(@ClassID,null,clsctx, @IID_IUnknown, @pUnknown)
	IF AxScode<>0 OR pUnknown=0 THEN EXIT Sub
	
	' Ask for the dispatch interface
	AxScode = IUnknown_QueryInterface(pUnknown, @IID_IDispatch, @pDispatch)
	' If it fails, return the Iunknown interface
	IF AxScode<>0 OR pDispatch=0 Then		
		ppv = pUnknown
		AxScode = S_OK
		EXIT SUB
	END IF
	' Release the IUnknown interface
	IUnknown_Release(pUnknown)
	' Return a pointer to the dispatch interface
	ppv = pDispatch
	AxScode=S_OK
END Sub

Dim usb1 As _USB
Dim As Short Data_To_Port0,Data_To_Port1
Dim As Long lret

AxScode=CoInitialize(null)
  
'creating usb1 object
AXCreateObject("USB_ActiveX.USB",usb1)
If axscode<>s_ok Then
        Print "usb.ocx not found"
        Sleep
        End
Endif

'find usb device
usb1->lpvtbl->Find_USB_Device(usb1,@lret)
If lret Then
	Print "USB device Found"
Else
	Print "USB device Not Found"
	Print "Press any key"
	'just to hold console until keypress
	Sleep
	usb1->lpvtbl->release(usb1)
	end
EndIf

'send data to device
usb1->lpvtbl->WR_P0(usb1,@Data_To_Port0)
usb1->lpvtbl->WR_P1(usb1,@Data_To_Port1)


Print "Press any key"
'just to hold console until keypress
Sleep
usb1->lpvtbl->release(usb1)
 
off course I can not test above code, but hope it will explain you better.
good luck
Last edited by Loe on Jul 09, 2010 2:24, edited 2 times in total.
bfuller
Posts: 362
Joined: Jun 02, 2007 12:35
Location: Sydney, Australia

Post by bfuller »

Heh Manfred,
I'm just an old style BASIC hobby programmer
the FreeBasic community and these forums have many members just like you. Don't give up, you will find the learning curve is pretty smooth, enjoyable and rewarding in the end. As suggested earlier, have a browse around in the "Hardware" subforum, you will find quite a few examples of how people have interfaced to various pieces of hardware using USB, Serial and Parallel ports. They all have their unique challenges but a lot of the USB things actually use the HID (Human Interface Device---like a mouse or keyboard etc) method.

Please dont' give up. Good luck.
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

Loe,

I tried that, and here are the errors reported by the compiler:
-----
FreeBASIC Compiler - Version 0.20.0 (08-10-2008) for win32 (target:win32)
Copyright (C) 2004-2008 The FreeBASIC development team.

C:/Program Files/FBjelly/DDStest.bas(14) error 41: Variable not declared, ObjGet in 'vret=*ObjGet USB1,"Find_USB_Device"'

C:/Program Files/FBjelly/DDStest.bas(22) error 41: Variable not declared, vlet in 'vlet(vvar0,Data_To_Port0)'

C:/Program Files/FBjelly/DDStest.bas(23) error 67: Array not dimensioned, before '(' in 'vlet(vvar1,Data_To_Port1)'

C:/Program Files/FBjelly/DDStest.bas(26) error 41: Variable not declared, ObjCall in 'ObjCall USB1,"WR_P0@1",@vvar0 '@1 is number of parameter passing'

C:/Program Files/FBjelly/DDStest.bas(27) error 10: Expected '=', found 'USB1' in 'ObjCall USB1,"WR_P1@1",@vvar1 '@n, change n to number of parameters'

C:/Program Files/FBjelly/DDStest.bas(32) error 10: Expected '=', found 'USB1' in 'ObjCall USB1,"Release" 'release unused object'
------------

What little I understand here, is that obviously the compiler doesn't find the function ObjGet nor vlet, nor ObjCall, etc, and is taking them for undefined variables. I assume that these functions reside in AXsuite, right? But the include line for axsuite IS working - when I comment it out, I get other errors. What can be wrong there?

Also I don't understand how this example is supposed to find the USB.OCX. The original VB code states the filename, complete, like "USB.OCX", and then calls the functions in it by USB1 and the function name. Why that USB1? Your FB code instead does not reference the filename at all. How can it find that file?

And what does that {3E9848A7-C355-43EA-9E8A-DFBC10F00516} mean? Is this some reference in the registry? Can the compiler find teh OCX file via that strange thing? If so, does it matter that you stripped the last characaters of that code or identifier or whatever, in your example? Anyway I tried adding them back in, and got the same behavior.

For now, I'm trying just to get the beast to report whether the DDS hardware is connected, via the "Find_USB_Device" function. It's the simplest thing, so I think it's good to start with that and go from there. But so far, no luck. I have been trying (blindly) to change some things, such as swapping the "USB.OCX" filename for "USB1", without any results so far. And I understand next to nothing of this whole affair...

Bfuller: Thanks for your encouragement! But this stuff is so complex, and may I say, so needlessly complex! I wish it was possible to use the USB ports directly, and that SoftMark would publish the information about how to access its hardware. Then one might do this job as simply as

SendUSB byte1, byte2

or something like that, maybe adding an address for the USB device or so. A true high level language should work like that!

Or how about this dream code:

Open USB1 for random as 1
Put #1, byte1
Put #1, byte2

One can dream, right?
bfuller
Posts: 362
Joined: Jun 02, 2007 12:35
Location: Sydney, Australia

Post by bfuller »

And what does that {3E9848A7-C355-43EA-9E8A-DFBC10F00516} mean?
Maybe this post http://www.freebasic.net/forum/viewtopic.php?t=13652 will help explain. Seems the number is related to your USB device and is different on each computer---so your "Registry" line of thought seems to be on the right track. If you go into Control Panel/Device Manager and look in details of USB or HID devices you can find such numbers---but don't ask me to explain, my knowledge is shallow also.
Last edited by bfuller on Jul 07, 2010 1:56, edited 1 time in total.
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

But the include line for axsuite IS working - when I comment it out, I get other errors. What can be wrong there?
I think you have wrong axsuite, get axsuite2 here
http://www.freebasic.net/arch/file.php?id=44
then refer to axsuite.pdf about how to install and use axsuite.
Also I don't understand how this example is supposed to find the USB.OCX.
if the OCX have installed properly, axcreateobject command will use windows registry to find it and link the COM/ActiveX object for you.
*to check list of registered COM/ActiveX you can use axsuite.exe.
And what does that {3E9848A7-C355-43EA-9E8A-DFBC10F00516} mean? Is this some reference in the registry?
This is GUID=globally unique identifier, yes its a refference to your Activex/COM information in registry.

as bfuller said, dont give up and good luck
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

Bfuller,
I had seen that program already. But I don't think I can use it, because I don't have any information about what exactly needs to be sent over the USB to the DDS device! So I'm pretty much forced to use the OCX provided by the hardware manufacturer instead of accessing the hardware more directly.

Loe,
the file I downloaded is axsuite2pkg.zip, sized 1,233,679 bytes. I think this is the correct one.
I got somewhat stuck with the installation, and assumed that this would somehow fix itself - which obviously it didn't!

The txt file asks me to place certain files in a certain FBEdit directory. I was using Jelly instead of FBEdit. So I downloaded FBEdit, installed it, but so far I just cannot seem to compile anything using it, not even a "hello world" type program! So I would like to keep using Jelly. Can I use axsuite with Jelly? If yes, then how?

I assumed that the files that have to be installed in FBEdit are just help and auxiliary files, and not necessary for compilation, so I went ahead and tried compiling your code in Jelly. Obviosuly, like everything I'm doing in this matter, my assumption has to be wrong!

Will keep trying, but probably the hardware will be obsolete, and Windows too (not to speak of myself!), by the time I find out how to get this working!
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

Hi Manfred,
I got somewhat stuck with the installation, and assumed that this would somehow fix itself - which obviously it didn't!
soryy if installation was stuck,

I have copy necessary function/sub in axsuite to above sample code in previous post. would you please to try again above sample and let me know the result. thank you
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

Loe,
this code compiles perfectly, without any errors or warnings. But when executing it, it reports "USB.OCX not found".

I tried adding those few strange characters to the end of the ID, which are present in the VB sample but not in your code, leaving the complete line as:

AXCreateObject("{3E9848A7-C355-43EA-9E8A-DFBC10F00516}#1.0#0",usb1)

but this didn't make any change. Still the program can't find the OCX.

I then searched the registry. This big number appears as "typelib" parameter for USB.OCX in the registry. It appears without those "#1.0#0" characters. The root of the tree for the USB.OCX in the registry has the key

{67DC04D0-356C-4D85-BFB1-0B6CE962FDAD}

I then copied that key into the program, instead of the "3E9...etc". Now the program no longer reports missing the OCX file. Instead now it says:

find usb=
Press any key

So that means it's getting no return from the driver program. The return of that "Find_USB_Device" function should be a text string saying either "TRUE" or "FALSE".

It seems to me that we still have no communication with the USB.OCX, or at least no correct communication with it, and surely my blind swapping of registry keys in the program is nonsense.

What now?

At least there is progress! No compiling errors! :-)
Loe
Posts: 323
Joined: Apr 30, 2006 14:49

Post by Loe »

hi manfred,
if you extracted axsuite2pkg.zip, youl find axsuite.exe in the root.
it is a typelibrary browser.
there is 4 column listview in the first tab, find usb.ocx in File column, and select it. you will then switch to 2nd tab (tree). there is enum, module etc.
if interface branch not empty, goto menu code then select vtable.
or goto menu code and select invoke.
goto menu code and select save. please paste generated code to discuss.
Manfred
Posts: 11
Joined: Jul 04, 2010 0:20
Contact:

Post by Manfred »

OK, here is what I got! Needless to say that I don't understand most of that...


'================================================================================
'CLSID - USB ActiveX for Ds1620?{3E9848A7-C355-43EA-9E8A-DFBC10F00516}
'================================================================================
Const CLSID_USB="{67DC04D0-356C-4D85-BFB1-0B6CE962FDAD}" '

'================================================================================
'ProgID - USB ActiveX for Ds1620?{3E9848A7-C355-43EA-9E8A-DFBC10F00516}
'================================================================================
Const ProgID_USB="USB_ActiveX.USB"

'================================================================================
'Alias Interface vTable - USB ActiveX for Ds1620?{3E9848A7-C355-43EA-9E8A-DFBC10F00516}
'================================================================================
Type _USB As _USB_ Ptr

'================================================================================
'vTable - USB ActiveX for Ds1620?{3E9848A7-C355-43EA-9E8A-DFBC10F00516}
'================================================================================
'================================================================================
'Interface _USB ?
Const IID__USB="{83A51DA8-5CED-4B9A-B386-E8B2E76C34B6}"
'================================================================================
Type _USBvTbl
QueryInterface As Function (pThis As Any ptr,riid As GUID ptr,ppvObj As Any ptr) As hResult
AddRef As Function (pThis As Any ptr) As hResult
Release As Function (pThis As Any ptr) As hResult
GetTypeInfoCount As Function(pThis As Any Ptr,pctinfo As UINT Ptr) As HRESULT
GetTypeInfo As Function(pThis As Any Ptr,itinfo As UINT,lcid As ULONG,pptinfo As lpvoid Ptr) As HRESULT
GetIDsOfNames As Function(pThis As Any Ptr,riid As GUID Ptr,rgszNames As BYTE Ptr Ptr,cNames As UINT,lcid As ULONG,rgdispid As long Ptr) As HRESULT
Invoke As Function(pThis As Any Ptr,dispidMember As long,riid As GUID Ptr,lcid As ULONG,wFlags As USHORT,pdispparams As DISPPARAMS Ptr,pvarResult As VARIANT Ptr,pexcepinfo As EXCEPINFO Ptr,puArgErr As UINT Ptr) As HRESULT
Offset1956(1927) As Byte
RD_P0 As Function(pThis As Any Ptr, As VARIANT Ptr) As HRESULT '
RD_P1 As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
WR_P1 As Function(pThis As Any Ptr,Data As short Ptr) As HRESULT '
Find_USB_Device As Function(pThis As Any Ptr, As long Ptr) As HRESULT '
WR_P0 As Function(pThis As Any Ptr,Data As short Ptr) As HRESULT '
VOLT_CH4 As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
VOLT_CH3 As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
VOLT_CH2 As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
VOLT_CH1 As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
RD_Port0 As Function(pThis As Any Ptr) As HRESULT '
Temperature As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
Azimuth As Function(pThis As Any Ptr, As short Ptr) As HRESULT '
ShutDown As Function(pThis As Any Ptr) As HRESULT '
End Type

Type _USB_
lpvtbl As _USBvTbl Ptr
End Type
Post Reply