> Mark Borgerson wrote:
>
>>If you want any more help, you're going to have to show us what is
>>going on inside your wrapper functions.
>
>
> Here are the functions from the Wrapper class:
>
> public class Wrapper
> {
> private static IntPtr m_USBhandler;
>
> [DllImport("FTD2XX.dll", EntryPoint="FT_Open")]
> public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle);
>
<snip>
I just finished solving a problem where I needed to call a vendor's dll
from VB6 and perl. And I was having all sorts of problems.
It turned out that the vendor's dll parameter passing used the _cdelc
('C' convention) for passing parameters instead of the _stdcall
parameter passing convention.
I ended up writing a wrapper dll in VC6 that used the _stdcall parameter
passing convention, and this solved all of my problems. Since I'm mainly
a hardware/VHDL guy, I've only dabbled in VC6, so it took lots of
googling before I was able to make my wrapper dll work. But, I did.
If FTDI supplies a C header file, you might be able to tell what
parameter passing convention is used.
I know that all of the Win32 API dlls, such as kernel32.dll, use the
_stdcall convention. It is my understanding that any non-C programs
linking to a dll require the _stdcall parameter passing convention.
BTW, the difference betweeen the two calling conventions is that when
using _cdecl, the calling program cleans up the stack after the call,
but with _stdcall, the called (dll) program does the cleanup.
Any of you real software guys out there, please feel free to chime in if
my info is inaccurate.
Urb
_______________________________________________________________________________
Posted Via Uncensored-News.Com - Accounts Starting At $6.95 - http://www.uncensored-news.com
<><><><><><><> The Worlds Uncensored News Source <><><><><><><><>
Reply by Andrew Jackson●February 15, 20062006-02-15
Kris
> [DllImport("FTD2XX.dll", EntryPoint="FT_Open")]
> public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle);
I'm not sure that it makes a difference but in my C# code I used out
rather than ref.
Are you certain that there is just the one FTDI device on your system?
> public static void PurgeAll()
> {
> FT_Status opResult;
>
> if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler,
> (uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX)))
> != FT_Status.Ok)
> {
> throw new USBException("Could not purge the buffers.",
> opResult);
> }
> }
Don't you mean or (|) rather than and (&) here? You won't be purging
anything otherwise.
Otherwise your functions look pretty reasonable.
Andrew
Reply by Mark Borgerson●February 15, 20062006-02-15
In article <1140017316.053269.264040@z14g2000cwz.googlegroups.com>,
kris.robin@gmail.com says...
> Excuse me for the repeat, but I badly need somebody's help.
> So, once again, just to draw attention:
>
> Mark Borgerson wrote:
> > If you want any more help, you're going to have to show us what is
> > going on inside your wrapper functions.
>
>
> Here are the functions from the Wrapper class:
>
> public class Wrapper
> {
> private static IntPtr m_USBhandler;
<<SNIP CODE>
>
>
> For me, it seems to be ok, but may be there is some problem.
>
It looks like you're doing the same things I do with the FT245, except
that I never use the Purge or GetQueueStatus calls. I purge buffers
by calling the Read function until there is no data left. I don't
use GetQueueStatus, but just read until there is nothing left.
in WinXP, I have set up and installed the FTDI driver using
their Vendor ID and the product ID for my device.
Here is the code to open the device:
void __fastcall TFormLink::BTOpenClick(TObject *Sender)
{ // try to find and open a CF-1 interface
char devstring[100];
DWORD numdevs, devindex = 0;
if(FTH != 0) { // if already open, close first
FT_Close(FTH);
FTH = 0;
}
fts = FT_ListDevices( &numdevs, NULL, FT_LIST_NUMBER_ONLY);
if(numdevs >0) fts = FT_Open(0, &FTH);
strcpy(devstring, "No CF-1 Interface Found" );
EDDevice->Text = (const char *)devstring; // assume no device
if(fts == FT_OK) { // if found change message, open device
FT_ResetDevice(FTH);
FT_SetTimeouts(FTH, 300,300);
EDDevice->Text = "CF-1 USB Interface";
}
}
The code which traverses a directory list and copies each file from the
data logger is this:
void __fastcall TFormLink::BTXferClick(TObject *Sender)
{ char *fullstring, fnstring[15], cmdstring[16];
int i,spos;
FILE *fp;
static char spbuff[4098];
long bytecount;
DWORD numwritten, num2read,numread;
AnsiString str;
char *fnp;
if(FTH == 0) return; // exit if not open
// transfer files that are selected
for(i= 0; i < LBoxdir->Items->Count; i++){
if(LBoxdir->Selected[i]){
str = LBoxdir->Items->Strings[i];
fullstring = str.c_str();
strcpy(cmdstring, "s");
strncpy(&fnstring[0],fullstring,13);
for(spos = 0; spos < 14; spos++){
if (fnstring[spos] == ' ') fnstring[spos] = 0;
} // truncate string at trailing spaces
strcat(cmdstring,fnstring);
strcat(cmdstring, "\n");
// now collect the data from USB port
bytecount = 0;
num2read = 256;
EDCount->Text = 0;
EDFolder->Text = TCDO1->Directory+"\\" + /
(const char *)fnstring;
fnp = EDFolder->Text.c_str();
fp = fopen( fnp, "wb"); // now send the command
//and file name to the cf-1
Application->ProcessMessages(); // catch up on windows
//message handling
FT_Write(FTH,cmdstring, strlen(cmdstring), &numwritten);
//send the file name
timeout = 50; // sets 5-second timeout to start file
while(timeout > 0){
fts = FT_GetQueueStatus(FTH, &num2read);
if((fts == FT_OK) && (num2read > 0)){
FT_Read(FTH,&spbuff[0],num2read,&numread);
if(numread > 0){
if(fp != NULL) fwrite(&spbuff[0],numread,1, fp);
bytecount+= numread;
EDCount->Text = bytecount;
timeout = 4; // reset timeout counter to 0.4
}
}
Application->ProcessMessages(); // catch up on windows
//message handling
}
if(fp!= NULL) fclose(fp);
} // end of if(selected...
} // end of for(i= 0 ....
}
As you can see, it's pretty simple: Send a command and read the
returned data until there is no more (as indicated by the timeout).
No need for purges or GetQueueStatus() (Which may not even be
valid for the FT245).
In your code you use the apparent global variable (or object field)
"m_USBhandler" in all your functions. I would suggest that you check
that this handle is valid before using it. I'm always suspicious of
object handles---especially if the handle is global. This
could be even more of a problem in a multi-threaded application
where another thread might be using the same handle.
if m_USBhandler is an object field, try making it a static global.
Can you simply link in the FTDI.sys driver and get the program working
with normal C code, rather than using DLLImport and the wrapper
functions? (I don't know C# well enough to know if this is possible.
My C# system is still in its unopened box--waiting for a lull in the
consulting schedule).
Mark Borgerson
Reply by Kris●February 15, 20062006-02-15
Excuse me for the repeat, but I badly need somebody's help.
So, once again, just to draw attention:
Mark Borgerson wrote:
> If you want any more help, you're going to have to show us what is
> going on inside your wrapper functions.
Here are the functions from the Wrapper class:
public class Wrapper
{
private static IntPtr m_USBhandler;
[DllImport("FTD2XX.dll", EntryPoint="FT_Open")]
public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle);
[DllImport("FTD2XX.dll", EntryPoint="FT_Close")]
public static extern uint FT_Close(IntPtr ftHandle);
[DllImport("FTD2XX.dll", EntryPoint="FT_Read")]
public static extern uint FT_Read(IntPtr ftHandle, byte[] lpBuffer,
uint dwBytesToRead, ref
uint
lpdwBytesReturned);
[DllImport("FTD2XX.dll", EntryPoint="FT_Write")]
public static extern uint FT_Write(IntPtr ftHandle, byte[] lpBuffer,
uint dwBytesToWrite,
ref uint
lpdwBytesWritten);
[DllImport("FTD2XX.dll", EntryPoint="FT_Purge")]
public static extern uint FT_Purge(IntPtr ftHandle, uint dwMask);
public static bool OpenDevice()
{
if (((FT_Status)Wrapper.FT_Open(1, ref m_USBhandler)) ==
FT_Status.Ok)
{
return true;
}
else
{
return false;
}
}
public static bool CloseDevice()
{
if (((FT_Status)Wrapper.FT_Close(m_USBhandler)) ==
FT_Status.Ok)
{
return true;
}
else
{
return false;
}
}
public static void PurgeAll()
{
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler,
(uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX)))
!= FT_Status.Ok)
{
throw new USBException("Could not purge the buffers.",
opResult);
}
}
public static uint CheckQueue()
{
uint bytesToReceiveNum = 0;
FT_Status opResult;
if ((opResult =
(FT_Status)Wrapper.FT_GetQueueStatus(m_USBhandler, ref
bytesToReceiveNum))
!= FT_Status.Ok)
{
throw new USBException("Could not check the USB device
queue status.", opResult);
}
else
{
return bytesToReceiveNum;
}
}
public static byte[] ReadData(uint bytesToReceiveNum)
{
uint readBytesNumber = 0;
byte[] receivedBytes = new byte[bytesToReceiveNum];
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Read(m_USBhandler,
receivedBytes, bytesToReceiveNum,
ref readBytesNumber)) !=
FT_Status.Ok)
{
throw new USBException("Could not read data from the
USB device.", opResult);
}
else if (bytesToReceiveNum != readBytesNumber)
{
throw new USBException("Could not retreive the full
data from the USB device.", FT_Status.OtherError);
}
else
{
return receivedBytes;
}
}
public static void WriteData(byte[] data)
{
uint bytesToWriteNum = (uint)data.Length;
uint writtenBytesNumber = 0;
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Write(m_USBhandler,
data, bytesToWriteNum, ref writtenBytesNumber))
!= FT_Status.Ok)
{
throw new USBException("Could not write the data into
the USB device.", opResult);
}
else if (bytesToWriteNum != writtenBytesNumber)
{
throw new USBException("Could not write the full data
into the USB device.", FT_Status.OtherError);
}
}
}
For me, it seems to be ok, but may be there is some problem.
Thank you in advance,
Kris
Reply by Kris●February 12, 20062006-02-12
Mark Borgerson wrote:
> If you want any more help, you're going to have to show us what is
> going on inside your wrapper functions.
Here are the functions from the Wrapper class:
public class Wrapper
{
private static IntPtr m_USBhandler;
[DllImport("FTD2XX.dll", EntryPoint="FT_Open")]
public static extern uint FT_Open(int iDevice, ref IntPtr ftHandle);
[DllImport("FTD2XX.dll", EntryPoint="FT_Close")]
public static extern uint FT_Close(IntPtr ftHandle);
[DllImport("FTD2XX.dll", EntryPoint="FT_Read")]
public static extern uint FT_Read(IntPtr ftHandle, byte[] lpBuffer,
uint dwBytesToRead, ref uint
lpdwBytesReturned);
[DllImport("FTD2XX.dll", EntryPoint="FT_Write")]
public static extern uint FT_Write(IntPtr ftHandle, byte[] lpBuffer,
uint dwBytesToWrite, ref uint
lpdwBytesWritten);
[DllImport("FTD2XX.dll", EntryPoint="FT_Purge")]
public static extern uint FT_Purge(IntPtr ftHandle, uint dwMask);
public static bool OpenDevice()
{
if (((FT_Status)Wrapper.FT_Open(1, ref m_USBhandler)) ==
FT_Status.Ok)
{
return true;
}
else
{
return false;
}
}
public static bool CloseDevice()
{
if (((FT_Status)Wrapper.FT_Close(m_USBhandler)) ==
FT_Status.Ok)
{
return true;
}
else
{
return false;
}
}
public static void PurgeAll()
{
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Purge(m_USBhandler,
(uint)FT_PurgeRXTX.TX & FT_PurgeRXTX.RX)))
!= FT_Status.Ok)
{
throw new USBException("Could not purge the buffers.",
opResult);
}
}
public static uint CheckQueue()
{
uint bytesToReceiveNum = 0;
FT_Status opResult;
if ((opResult =
(FT_Status)Wrapper.FT_GetQueueStatus(m_USBhandler, ref
bytesToReceiveNum))
!= FT_Status.Ok)
{
throw new USBException("Could not check the USB device
queue status.", opResult);
}
else
{
return bytesToReceiveNum;
}
}
public static byte[] ReadData(uint bytesToReceiveNum)
{
uint readBytesNumber = 0;
byte[] receivedBytes = new byte[bytesToReceiveNum];
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Read(m_USBhandler,
receivedBytes, bytesToReceiveNum,
ref readBytesNumber)) !=
FT_Status.Ok)
{
throw new USBException("Could not read data from the
USB device.", opResult);
}
else if (bytesToReceiveNum != readBytesNumber)
{
throw new USBException("Could not retreive the full
data from the USB device.", FT_Status.OtherError);
}
else
{
return receivedBytes;
}
}
public static void WriteData(byte[] data)
{
uint bytesToWriteNum = (uint)data.Length;
uint writtenBytesNumber = 0;
FT_Status opResult;
if ((opResult = (FT_Status)Wrapper.FT_Write(m_USBhandler,
data, bytesToWriteNum, ref writtenBytesNumber))
!= FT_Status.Ok)
{
throw new USBException("Could not write the data into
the USB device.", opResult);
}
else if (bytesToWriteNum != writtenBytesNumber)
{
throw new USBException("Could not write the full data
into the USB device.", FT_Status.OtherError);
}
}
}
For me, it seems to be ok, but may be there is some problem.
Kris
Reply by David Tweed●February 10, 20062006-02-10
Kris wrote:
> Your experience with the FT245BM chips is very relevant in this case, I
> think, because the DLP-2232PB module is based on FT2232C - "double"
> FT245BM with some additions.
> May be you can tell me, transfer of what amounts of data and at what
> rate is involved in your applications. It could be the key to solution.
We have implemented a message protocol on top of the raw "byte stream"
presented by the USB interface. Our primary traffic is a 38-byte message
200 times a second (about 8000 bytes/second) plus a few thousand bytes
of other miscellaneous messages each second. It ends up being about
10K bytes/second on the average. Windows XP generally does a pretty
good job of keeping up in real time, although we see occasional "hiccups"
when it gets busy with something else.
-- Dave Tweed
Reply by Andrew Jackson●February 9, 20062006-02-09
[Sorry for previous post, over hasty key press]
>> What is that, C#? Where did you get FTDIWrapper?
[deletia]
> Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that
> uses PInvoke for communication between managed code and unmanaged
> functions of the D2XX driver. These functions were tested before
> through a couple of loopback tests, and it was ok.
I've used the FTDI device with both C++ and C# without problems. It
would be useful to see what some of your wrapper functions look like.
The code that I wrote for C#, after finding and opening the device,
wrote a command and read a result back (similar to yours but without the
flush).
Andrew
Reply by Andrew Jackson●February 9, 20062006-02-09
Kris wrote:
> David Tweed wrote:
>> Kris wrote:
>>> host side:
>>>
>>> using System;
>>> using System.Collections.Generic;
>>> using System.Text;
>>> using FTDIWrapper;
>> What is that, C#? Where did you get FTDIWrapper?
>>
>> All I can tell you is that I've been using FTDI chips (FT245BM, mainly)
>> for a couple of years now in embedded projects. But on the host side,
>> we just use the D2XX driver from FTDI via Visual C++, and it works
>> pretty much the way the documentation says it does.
>>
>> I would also echo the thought that opening/closing the device on every
>> iteration is probably a bad idea.
>>
>> -- Dave Tweed
>
> Hello, Dave.
> Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that
> uses PInvoke for communication between managed code and unmanaged
> functions of the D2XX driver. These functions were tested before
> through a couple of loopback tests, and it was ok.
> Now, the "opening/closing" issue is addressed in the code snippet
> above. But, as I said before, this does not help - to leave the device
> open.
> Your experience with the FT245BM chips is very relevant in this case, I
> think, because the DLP-2232PB module is based on FT2232C - "double"
> FT245BM with some additions.
> May be you can tell me, transfer of what amounts of data and at what
> rate is involved in your applications. It could be the key to solution.
> Regards,
> Kris.
>
Reply by Mark Borgerson●February 9, 20062006-02-09
In article <1139496772.475156.255940@f14g2000cwb.googlegroups.com>,
kris.robin@gmail.com says...
> David Tweed wrote:
> > Kris wrote:
> > > host side:
> > >
> > > using System;
> > > using System.Collections.Generic;
> > > using System.Text;
> > > using FTDIWrapper;
> >
> > What is that, C#? Where did you get FTDIWrapper?
> >
> > All I can tell you is that I've been using FTDI chips (FT245BM, mainly)
> > for a couple of years now in embedded projects. But on the host side,
> > we just use the D2XX driver from FTDI via Visual C++, and it works
> > pretty much the way the documentation says it does.
> >
That's been my experience also. I haven't changed my host side software
in several years.
> > I would also echo the thought that opening/closing the device on every
> > iteration is probably a bad idea.
> >
> > -- Dave Tweed
>
> Hello, Dave.
> Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that
> uses PInvoke for communication between managed code and unmanaged
> functions of the D2XX driver. These functions were tested before
> through a couple of loopback tests, and it was ok.
> Now, the "opening/closing" issue is addressed in the code snippet
> above. But, as I said before, this does not help - to leave the device
> open.
> Your experience with the FT245BM chips is very relevant in this case, I
> think, because the DLP-2232PB module is based on FT2232C - "double"
> FT245BM with some additions.
> May be you can tell me, transfer of what amounts of data and at what
> rate is involved in your applications. It could be the key to solution.
> Regards,
> Kris.
The source code for my windows host program uses the following to read
a file transferred from the embedded system. The program is in
Borland C++ builder. FTH is the handle for the FTDI FT245 device:
void __fastcall TFormLink::BTXferClick(TObject *Sender)
{ char *fullstring, fnstring[15], cmdstring[16];
int i,spos;
FILE *fp;
static char spbuff[4098];
long bytecount;
DWORD numwritten, num2read,numread;
AnsiString str;
char *fnp;
if(FTH == 0) return; // exit if not open
/// Snipped file opening code
FT_Write(FTH,cmdstring, strlen(cmdstring), &numwritten); //
//send the file name
timeout = 50; // sets 5-second timeout to start file
// at this point, the logger starts sending the file data
while(timeout > 0){
fts = FT_GetQueueStatus(FTH, &num2read);
if((fts == FT_OK) && (num2read > 0)){
FT_Read(FTH,&spbuff[0],num2read,&numread);
if(numread > 0){
if(fp != NULL) fwrite(&spbuff[0], numread,1,fp);
bytecount+= numread;
EDCount->Text = bytecount; // show bytes sent
timeout = 4; // reset timeout counter to 0.4
}
}
Application->ProcessMessages(); // check windows msgs
}
if(fp!= NULL) fclose(fp);
}
If you want any more help, you're going to have to show us what is
going on inside your wrapper functions.
You can find the logger-side source code at www.oes.to. Look for
the USB-1 page.
Mark Borgerson
Reply by Kris●February 9, 20062006-02-09
David Tweed wrote:
> Kris wrote:
> > host side:
> >
> > using System;
> > using System.Collections.Generic;
> > using System.Text;
> > using FTDIWrapper;
>
> What is that, C#? Where did you get FTDIWrapper?
>
> All I can tell you is that I've been using FTDI chips (FT245BM, mainly)
> for a couple of years now in embedded projects. But on the host side,
> we just use the D2XX driver from FTDI via Visual C++, and it works
> pretty much the way the documentation says it does.
>
> I would also echo the thought that opening/closing the device on every
> iteration is probably a bad idea.
>
> -- Dave Tweed
Hello, Dave.
Yes, it's C#. FTDIWrapper is the namespace of my Wrapper class, that
uses PInvoke for communication between managed code and unmanaged
functions of the D2XX driver. These functions were tested before
through a couple of loopback tests, and it was ok.
Now, the "opening/closing" issue is addressed in the code snippet
above. But, as I said before, this does not help - to leave the device
open.
Your experience with the FT245BM chips is very relevant in this case, I
think, because the DLP-2232PB module is based on FT2232C - "double"
FT245BM with some additions.
May be you can tell me, transfer of what amounts of data and at what
rate is involved in your applications. It could be the key to solution.
Regards,
Kris.