Page 1 of 1

When issuing CSAFE commands I always get USB time out errors

Posted: February 22nd, 2015, 5:34 pm
by nick_a
Hi All.
I've just started work on an application which will provide a speaking interface to the PM so that blind users are better able to use the functions.
I'm developing this application on windows using C++ and MFC.
I'm using a PM5 to test with and I've had no problems getting it connected and getting my software to detected however all the CSAFE commands i have tried to send result in a USB time out error. the message reads:
Unable to initialize PM Interface Libraries. The USB read operation did not complete within the timeout period
Some calls are working fine, these are the calls to get the hw, fw versions and serial number.
Below I've copied my initialization code and commands that demonstrate the issue.

Anyone have any ideas how i fix this?
Using windows 7 64 bit and VS2008 as my IDE. I've not installed any extra drivers and haven't changed any USB settings. The PM auto detected with out problems.
Thanks.
Nick.

Code: Select all

// connect code. this works fine.
{ // attempt a connection
		tkcmdsetUSB_init();
		tkcmdsetDDI_init();
		/* Discover and get count of all discovered PM3s or PM4s.  Tell DLL to start numbering at 0. */
		UINT16 numUnits( 0 );

		tkcmdsetDDI_discover_pm3s(TKCMDSET_PM3_PRODUCT_NAME2, 0, &numUnits);
		tkcmdsetDDI_discover_pm3s(TKCMDSET_PM4_PRODUCT_NAME, 0, &numUnits);
		tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor 5 (PM5)", 0, &numUnits);
		if (numUnits > 0)
		{/* Initialize the CSAFE protocol engine.  Leave timeout at default. */
			ERRCODE_T result = tkcmdsetCSAFE_init_protocol( 1000 );
			if (result != 0)
			{
				CString error = L"Unable to inicialise PM Interface Libraries. ";
				char message[200]; 
				tkcmdsetDDI_get_error_text( result, &message[0], 200);
				error.Append( CharToWChar( &message[0] ) );
				m_window->MessageBox( error, L"ERG Jabber", IDOK);
			}
			else
			{
				m_isConnected = true;
				m_window->PmConnected();
			}
		}
	}

// query function. this results in the error above.
bool CPmInterfaceWrapper::QueryPM()
{
	bool finalResult = true;
	// return true if you get any data at all from the PM.
	// false should be returned only if we think the connection has been lost.
	const UINT16_T CMD_SIZE = 1;
	const UINT16_T RESPONSE_SIZE = 10;

	UINT32_T command[ CMD_SIZE ];
	UINT32_T response[ RESPONSE_SIZE ];
	UINT16_T responseSize( RESPONSE_SIZE );

	command[0] = CSAFE_GETTWORK_CMD;
	for (UINT16 i = 0; i < RESPONSE_SIZE; i++)
	{
		response[ i ] = 0xFFFFFFFF;
	}

	ERRCODE_T result = 	tkcmdsetCSAFE_command(0, 
		CMD_SIZE, 
		&command[0], 
		&responseSize,
		&response[0] ); 
	if (result != 0)
	{
		CString error = L"Unable to inicialise PM Interface Libraries. ";
		char message[200]; 
		tkcmdsetCSAFE_get_error_text( result, &message[0], 200);
		error.Append( CharToWChar( &message[0] ) );
		m_window->UpdateStatus( error );
	}
	else
	{
		finalResult = true;
		WCHAR cText[32];
		wsprintf(cText, L"%d:%02d:%02d", response[0], response[1], response[2] );
		m_time = cText;
	}
	return finalResult;
}

Re: When issuing CSAFE commands I always get USB time out er

Posted: April 1st, 2015, 12:50 pm
by haboustak
Hopefully you are no longer stuck on this, but in case you are not... I am not able to replicate your issue exactly. I'm running Dlls from 3/26/2008.

When I use the code below in a C++ console app complied using VS 2013 (no ATL, no MFC) I get an error related to CSafe framing when my response buffer size is set to 10. If I use a response buffer size of 11, everything is fine. It could be that more than 10 bytes are required for the underlying transaction and CSAFE parsing or it could be a bug.

I recommend you use a response buffer size of exactly 64 for all transactions.

One other thing, I'm not sure your usage of num_units will work if you have multiple devices of different types connected. I think it will overwrite the value with the count of the last kind of unit detected.

Here's the all code required to send 0xA0 to a PM and get a response. I tried to stay as close to your example as I could. When I use response size 10 my error message is: "CSAFE frame missing end character". When I use 11, the command works fine.

Code: Select all

#include "stdafx.h"

#include "PM3CsafeCP.h"
#include "PM3DDICP.h"
#include "PM3USBCP.h"

int QueryPm();

int _tmain(int argc, _TCHAR* argv[])
{
	UINT16_T numUnits(0);

	tkcmdsetUSB_init();
	tkcmdsetDDI_init();

	/* The USB library uses a "starts with" search pattern... I think this grabs all monitor generations */
	tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor", 0, &numUnits);

	if (numUnits > 0)
	{/* Initialize the CSAFE protocol engine. Leave timeout at default. */
		ERRCODE_T result = tkcmdsetCSAFE_init_protocol(1000);
		if (result != 0)
		{
			char message[200];
			tkcmdsetDDI_get_error_text(result, &message[0], 200);
			printf("%s", message);
		}
	}
	QueryPm();
	return 0;
}

int QueryPm()
{
	bool finalResult = true;
	// return true if you get any data at all from the PM.
	// false should be returned only if we think the connection has been lost.
	const UINT16_T CMD_SIZE = 1;
	const UINT16_T RESPONSE_SIZE = 64;

	UINT32_T command[CMD_SIZE];
	UINT32_T response[RESPONSE_SIZE];
	UINT16_T responseSize(RESPONSE_SIZE);

	command[0] = 0xA0;
	for (UINT16_T i = 0; i < RESPONSE_SIZE; i++)
	{
		response[i] = 0xFFFFFFFF;
	}

	ERRCODE_T result = tkcmdsetCSAFE_command(0,
		CMD_SIZE,
		command,
		&responseSize,
		response);
	if (result != 0)
	{
		char message[200];
		tkcmdsetCSAFE_get_error_text(result, &message[0], 200);
		printf("%s", message);
	}
	else
	{
		finalResult = true;
		printf("%d:%02d:%02d", response[0], response[1], response[2]);
	}
	return finalResult;
}

Re: When issuing CSAFE commands I always get USB time out er

Posted: April 1st, 2015, 4:14 pm
by nick_a
Hi.
Thanks for your post.
I've copied your code above and I still get the same error i was getting before, USB timeout.
The code finds the PM5 no problems but the command errors.
The DLL's i've got have the same date as yours.
Clearly something is wrong with my setup here.

Is there anything i need to do on the PM to check its in the write mode or any drivers that need to be installed?
Are there any VS project settings I need to check?
Thanks again.
Nick.

Re: When issuing CSAFE commands I always get USB time out er

Posted: April 2nd, 2015, 10:07 am
by haboustak
Hmm, that's a tough one. There aren't any special VS settings or PM settings you need to make it work.

Does the C2 Utility find and function with your PM5? Can you export/upload a stored row? Make sure you have the latest firmware while you're at it.

There have been conflicts in the past with certain USB hosts and certain PM firmware versions. I am using a PM4 with FW29, I don't know much about the PM5, but being new, it may have a bug that affects your PC setup. Can you take the monitor to a different PC and try it out? If it works from another PC, I'm confident C2 would appreciate a bug report.


The C2 Utility uses DLLs similar to what's provided in the SDK. You could try generating an import library for them and see if the behavior changes (the exports and usage should be about the same as the old SDK docs). If the new DLLs work with your system, then it sounds like the Windows SDK needs a refresh for PM5 support.

http://stackoverflow.com/questions/9946 ... from-a-dll

Re: When issuing CSAFE commands I always get USB time out er

Posted: October 4th, 2015, 3:53 pm
by nick_a
Hi.
For anyone wondering this issue seemed to be caused by Visual Studio 2008. Upgrading to VS2015 fixed the issue.
Thanks.
Nick.