Reusing MFC libraries in a new driver for OV

Making & changing hardware drivers in Acquisition Server
Post Reply
Jeff_B
Posts: 37
Joined: Wed Apr 11, 2012 1:31 pm
Location: Nice - Alpes Maritimes

Reusing MFC libraries in a new driver for OV

Post by Jeff_B »

Hello there,
I am trying to code a driver (non configurable for now) to connect a low cost unit by Symtop (UE-16A, 16 canaux) to the OpenVibe acquisition server.

I compiled a 1st time all the OV sources (openvibe-0.13.1-svn3210-src with the OS Vista SP1 and VC++ 2010) using the provided scripts to set the environment, to install the dependencies and to build provided in... /scripts.

I then generated a skeleton driver to code mine and put all the stuff in: C:\OpenVibeProj\openvibe-applications\acquisition-server\trunc\src\SymtopProducts
I also generated a project to later work under the visual 2010 IDE.

-I started to code ovasCDriverSymtop and ovasCConfigurationSymtop (.h and .cpp),
-I included EEGAMP.dll, EEGAMP.h in the same folder (and EEGAMP.obj in C:\OpenVibeProj\openvibe-applications\acquisition-server\trunc\lib),
-I modofied ovasCAcquisitionServerGUI.cpp to include:

// include Symtop's CDriver
#include "SymtopProducts/ovasCDriverSymtop.h"
and:
// initializes Symtop's driver class
if(l_bShowUnstable) m_vDriver.push_back(new CDriverSymtop(m_pAcquisitionServer->getDriverContext()));

To include EEGAMP.h (the UE-16A EEG driver's header) in ovasCDriverSymtop.h and ovasCConfigurationSymtop.h , I have to include beforehand the MFC header stdafx.h since EEGAMP.h seems to be a precompiled header (PCH) as said in EEGAMP.h:

//
// EEGAMP.h : main header file for the EEGAMP DLL
//

#if !defined(AFX_EEGAMP_H__10A9D1B8_19AE_41DE_AE91_791C3A9A3FA5__INCLUDED_)
#define AFX_EEGAMP_H__10A9D1B8_19AE_41DE_AE91_791C3A9A3FA5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

(début de EEGAMP.h)

... After the inclusion of stdafx.h in ovasCDriverSymtop.h and ovasCConfigurationSymtop.h,
when I try to build "OpenViBE-acquisition-server-dynamic" (using the Win32build script and a "build order" restricted to "OpenViBE_application_acquisition_server")

I get the following error when the compiler tries to build the ovasCAcquisitionServerGUI.obj (where I included my stuff, see above):

[ 80%] Building CXX object CMakeFiles/OpenViBE-acquisition-server-dynamic.dir/src/ovasCAcquisitionServerGUI.obj
cl : Command line warning D9002 : ignoring unknown option '-mms-bitfields'
cl : Command line warning D9002 : ignoring unknown option '-mms-bitfields'
ovasCAcquisitionServerGUI.cpp
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afx.h(24) : fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]

I do what the compiler says and I insert in the CMakeLists.txt of the related folder C:\OpenVibeProj\openvibe-applications\acquisition-server\trunc:

# shared MFC dll precompiler directive
SET(CMAKE_MFC_FLAG 2) # use MFC as a shared dll
ADD_DEFINITIONS(-D_AFXDLL) # add the AFXDLL definition


and I try to rebuild... the previous error vanishes but multiple errors related to afxwin.h (included in stdafx.h) appears:

[ 80%] Building CXX object CMakeFiles/OpenViBE-acquisition-server-dynamic.dir/src/ovasCAcquisitionServerGUI.obj
cl : Command line warning D9002 : ignoring unknown option '-mms-bitfields'
cl : Command line warning D9002 : ignoring unknown option '-mms-bitfields'
ovasCAcquisitionServerGUI.cpp
_WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2208) : error C2146: syntax error : missing ';' before identifier 'm_pConfigs'
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2208) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2135) : error C2065: 'GID_ZOOM' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2135) : error C2065: 'GC_ZOOM' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2135) : error C2065: 'GC_ZOOM' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2141) : error C2065: 'GID_ROTATE' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2141) : error C2065: 'GC_ROTATE' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2141) : error C2065: 'GC_ROTATE' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2147) : error C2065: 'GID_TWOFINGERTAP' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2147) : error C2065: 'GC_TWOFINGERTAP' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2147) : error C2065: 'GC_TWOFINGERTAP' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2161) : error C2065: 'GID_PAN' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2161) : error C2065: 'GC_PAN' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2161) : error C2065: 'GC_PAN' : undeclared identifier
c:\Program Files\Microsoft Visual Studio 10.0\VC\ATLMFC\INCLUDE\afxwin.h(2167) : error C2065: 'GID_PAN' : undeclared identifier
etc....

And I cant' get rid of these ! I strongly doubt that these errors really exist as such (afxwin being a pilar of MFC ! not my own code) so where is the flaw ?
Any help really appreciated as I am not a c++ specialist !
Jeff B.

Jeff_B
Posts: 37
Joined: Wed Apr 11, 2012 1:31 pm
Location: Nice - Alpes Maritimes

Re: Reusing MFC libraries in a new driver for OV

Post by Jeff_B »

Hello there,
As suggested by Yann and Laurent, OpenVibe is not welcoming the linking with the MFC libraries, so the best option is to get rid of these. Thus I don't use anymore the EEGAMP.h header provided in the Symtop SDK and to try to import directly the EEGAMP.dll functions (no DelayLoad) in the OvasCDriverSymtop.cpp:

/* Direct import of EEGAMP.dll's functions */
HMODULE hDLL = LoadLibrary("EEGAMP.dll");

//HANDLE OpenDevice();
typedef HANDLE (*DLL_Function_OpenDevice)(void);
DLL_Function_OpenDevice FcOpenDevice = (DLL_Function_OpenDevice)GetProcAddress(hDLL,"OpenDevice");
//bool ReadData(HANDLE hDevice,short* pBuffer,ULONG *nCounts);
typedef bool (*DLL_Function_ReadData)(HANDLE,short*,ULONG *);
DLL_Function_ReadData FcReadData = (DLL_Function_ReadData)GetProcAddress(hDLL,"ReadData");
etc...

I don't know if it is the proper thing to do in such a case, but I have just built he acquisition-server with the Symtop driver and at 1st trial, the Symtop UE-16A device appears in the list (flagged as "unstable" though), the acquisition server can connect to it, but the data acquisition seems to be a problem (failing). Digging into it...
Cheers,
Jean-François B.

Jeff_B
Posts: 37
Joined: Wed Apr 11, 2012 1:31 pm
Location: Nice - Alpes Maritimes

Re: Reusing MFC libraries in a new driver for OV

Post by Jeff_B »

Hello there,
The Symtop driver seems to be able to:
- open the UE-16A device and get a handle on it
- read its device info (ID, port, ...)
- read/write its parameters (mode EEG/generator, low pass filter frequency, notch filter frequency, time constant,...)
- close the device
its main function, namely ReadData:

typedef BOOL (*DLL_Function_ReadData)(HANDLE,short*,ULONG *);
DLL_Function_ReadData FcReadData = (DLL_Function_ReadData)GetProcAddress(hDLL,"ReadData");

where:
- HANDLE is the device handle obtained via SymtopHandle=OpenDevice();
- short* gm_pBuffer[Nsamples] is the buffer to be filled by the UE-16A
- PULONG gm_nCounts is the number of bytes to be sampled by the UE-16A.

This ReadData function seems to read 160 samples (16 channels times 10 samples per channel) whatever the gm_nCounts value and the gm_pBuffer size, which could be a problem since it would be not configurable, and it is not a divider of the m_ui32SampleCountPerSentBlock values (2, 4, 8, 16, 32, 64, 128, 256 and 512) ? (lost samples).
Anyway, I can get the time plots of the 16 channels via the O.V. designer application showing that the Symtop driver correctly fills the m_pSample buffer (channel 1 sample 1, channel 1 sample 2,....channel 1, sample CountPerSentBlock, channel 2 sample 1, channel 2 sample 2,...etc).
So I mailed Symtop to get some precision about the ReadData function, and in the meantime I added a value of 10 for the m_ui32SampleCountPerSentBlock in the acquisition-server interface.ui.
Take care,
Jean-François B.

Jeff_B
Posts: 37
Joined: Wed Apr 11, 2012 1:31 pm
Location: Nice - Alpes Maritimes

Re: Reusing MFC libraries in a new driver for OV

Post by Jeff_B »

Hello there,
Still waiting a new reply from Symtop about the possibility for the ReadData function to acquire an arbitrary number of samples (mine crashes below 10 samples per channel, so it is protected at the configuration GUI level).
The Symtop driver is now configurable (the basic header: identifier, age, gender, number of channels, sampling frequency + number of samples to acquire, low pass filter frequency, notch filter frequency, time constant).
For a still unknown reason, the acquisition server GUI freezes when I push the button disconnect (the CloseDevice function return a true though). The only remaining point is to find another Symtop user than me :lol:
Take care,
Jean-François

jlegeny
Posts: 239
Joined: Tue Nov 02, 2010 8:51 am
Location: Mensia Technologies Paris FR
Contact:

Re: Reusing MFC libraries in a new driver for OV

Post by jlegeny »

Hello Jean-François,

a freeze in the GUI could be caused in the uninitialize method which is called when you press the disconnect button. In my experience hogs are often caused while waiting to open sockets (which could be weird during disconnection, but if your driver does auto-reconnect for example it could be possible)

Thank you very much for your contribution
Jozef

Post Reply