Hello,
I fiddled around a bit and was able to made a patch for initial win32 support
for serial EtrexLegend.
It is based on Krzysztofs patch since that made it easier.
It is against old qlandkarte svn, since building and testing was easier this
way.
It also contains an intermediate fix for possible buffer overflow when
receiving NMEA data.
I build with mingw tools.
Since -DUNICODE is set, CreateFile() wants the device as WCHAR*. I just
#undef-ed it for WIN32 for know.
Is there a better solution?
@Frank, Krzysztof, Oliver:
Do you have any objections?
Some pitfalls remain in the driver code of serial devices:
1) disconnecting the cable while receiving waypoints/tracks might put
qlandkarte into endless loop.
best regards,
Andreas Stenglein
Index: qlandkarte/trunk/QLandkarte.pro
===================================================================
--- qlandkarte/trunk/QLandkarte.pro (Revision 518)
+++ qlandkarte/trunk/QLandkarte.pro (Arbeitskopie)
@@ -25,7 +25,8 @@
win32 {
SUBDIRS += sub_WinGarminUSB \
sub_NMEATcp \
- sub_whatGarmin
+ sub_whatGarmin \
+ sub_EtrexLegend
}
sub_src.subdir = src
Index: qlandkarte/trunk/src/CDlgDevice.cpp
===================================================================
--- qlandkarte/trunk/src/CDlgDevice.cpp (Revision 518)
+++ qlandkarte/trunk/src/CDlgDevice.cpp (Arbeitskopie)
@@ -55,6 +55,7 @@
comboDev->addItem("EtrexVistaCx");
comboDev->addItem("NMEATcp");
comboDev->addItem("infoAboutMyGarmin");
+ comboDev->addItem("EtrexLegend");
comboDev->setCurrentIndex(0);
// Die folgende Zeile funktioniert nicht, da m_DeviceName zu diesem Zeitpunkt leer ist
Index: qlandkarte/trunk/src/device/CTcp.h
===================================================================
--- qlandkarte/trunk/src/device/CTcp.h (Revision 518)
+++ qlandkarte/trunk/src/device/CTcp.h (Arbeitskopie)
@@ -44,23 +44,18 @@
namespace Garmin
{
- class CTcp : public ILink
+ class CTcp
{
public:
CTcp(const std::string& port);
virtual ~CTcp();
- /// see ILink::open()
void open();
- /// see ILink::close()
void close();
- /// see ILink::read()
int read(char *data);
- /// see ILink::write()
void write(char *data);
int read(Packet_t& data){data=data;return -1;};
- /// see ILink::write()
void write(const Packet_t& /*data*/){;return;};
uint16_t getProductId(){return productId;}
Index: qlandkarte/trunk/src/device/Emap/CDevice.cpp
===================================================================
--- qlandkarte/trunk/src/device/Emap/CDevice.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/Emap/CDevice.cpp (Arbeitskopie)
@@ -170,7 +170,7 @@
serial->write(command);
ready= 0;
- while(!ready && serial->read(response) > 0) {
+ while(!ready && serial->read(response, 5000) > 0) {
if(response.id == 74) {
ready= 1;
//TODO read data
Index: qlandkarte/trunk/src/device/CUSB.h
===================================================================
--- qlandkarte/trunk/src/device/CUSB.h (Revision 518)
+++ qlandkarte/trunk/src/device/CUSB.h (Arbeitskopie)
@@ -50,20 +50,16 @@
if your device does not fit into the protocol implementation
at all, subclass it and make your fixes.
*/
- class CUSB : public ILink
+ class CUSB
{
public:
CUSB();
virtual ~CUSB();
- /// see ILink::open()
void open();
- /// see ILink::close()
void close();
void close2();
- /// see ILink::read()
int read(Packet_t& data);
- /// see ILink::write()
void write(const Packet_t& data);
/// sync. up sequence
/**
Index: qlandkarte/trunk/src/device/ILink.cpp
===================================================================
--- qlandkarte/trunk/src/device/ILink.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/ILink.cpp (Arbeitskopie)
@@ -1,35 +0,0 @@
-/**********************************************************************************************
- Copyright (C) 2007 Oliver Eichler [EMAIL PROTECTED]
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
-
- Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd.
- or one of its subsidiaries.
-
-**********************************************************************************************/
-#include "ILink.h"
-
-using namespace Garmin;
-
-ILink::ILink()
-{
-
-}
-
-
-ILink::~ILink()
-{
-
-}
Index: qlandkarte/trunk/src/device/ILink.h
===================================================================
--- qlandkarte/trunk/src/device/ILink.h (Revision 518)
+++ qlandkarte/trunk/src/device/ILink.h (Arbeitskopie)
@@ -49,32 +49,5 @@
};
#pragma pack(0)
- /// Base class for all link objects
- /**
- Use CUSB and CSerial to exchange messages with your
- device.
-
- Do not forget that you communicate to a plug-n-play device.
- The user might disconnect without notice. Another
- application might access the device, too. Thus open the link for
- each exchange and close it after the exchange. The _acquire() and
- _release() method of the driver implementation shoud be a good
- place to use open() and close().
-
- */
- class ILink
- {
- public:
- ILink();
- virtual ~ILink();
-
- virtual void open() = 0;
- virtual void close() = 0;
-
- virtual int read(Packet_t& data) = 0;
- virtual void write(const Packet_t& data) = 0;
-
- };
-
}
#endif //ILINK_H
Index: qlandkarte/trunk/src/device/device.pro
===================================================================
--- qlandkarte/trunk/src/device/device.pro (Revision 518)
+++ qlandkarte/trunk/src/device/device.pro (Arbeitskopie)
@@ -12,8 +12,7 @@
IDeviceDefault.h \
CTcp.h
-SOURCES += ILink.cpp \
- Garmin.cpp \
+SOURCES += Garmin.cpp \
IDeviceDefault.cpp \
CTcp.cpp
@@ -23,8 +22,12 @@
SOURCES += CSerial.cpp
HEADERS += CSerial.h
}
-win32:SOURCES += CUSB_win32.cpp
-
+win32: {
+ SOURCES += CUSB_win32.cpp
+ SOURCES += CSerial.cpp
+ HEADERS += CSerial.h
+}
+
OBJECTS_DIR = .tmp
win32:INCLUDEPATH += ../../libs/mingw/include
Index: qlandkarte/trunk/src/device/CSerial.cpp
===================================================================
--- qlandkarte/trunk/src/device/CSerial.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/CSerial.cpp (Arbeitskopie)
@@ -20,6 +20,11 @@
or one of its subsidiaries.
**********************************************************************************************/
+#ifdef WIN32
+// because of filename of com-port
+#undef UNICODE
+#endif
+
#include "CSerial.h"
#include "IDevice.h"
#include "../Platform.h"
@@ -31,10 +36,12 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
-#include <sys/time.h>
#include <unistd.h>
-#include <time.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
using namespace Garmin;
using namespace std;
@@ -45,18 +52,22 @@
#define SERIAL_PACKET_MAX_SIZE 255
#define DLE 16
#define ETX 3
-#define START_TIMEOUT 5
-#define MIN_TIMEOUT 2
CSerial::CSerial(const std::string& port)
+#ifdef WIN32
+: hCom(0)
+#else
: port_fd(-1)
+#endif
, productId(0)
, softwareVersion(0)
, protocolArraySize(-1)
, port(port)
{
+#ifdef WIN32
+#else
FD_ZERO(&fds_read);
- timerclear(&typmax_rsptimetv);
+#endif
}
@@ -66,11 +77,79 @@
}
+#ifdef WIN32
void CSerial::open()
{
#if defined(WORDS_BIGENDIAN) || !defined(CAN_UNALIGNED)
throw exce_t(errOpen, "The serial driver still needs to be ported to your platform.");
#endif
+ DCB dcb;
+ WCHAR comname[100];
+ COMMTIMEOUTS timeouts;
+
+ if( hCom > 0 && hCom != INVALID_HANDLE_VALUE) {
+ return;
+ }
+
+// on my system this one didn't work when make debug was done, so I just #undef-ed UNICODE at top of file
+// MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, port.c_str(), strlen(port.c_str()),
+// comname, 100);
+// hCom= CreateFile( comname, //port.c_str(), // use for example \\.\COM10 for higher ports
+ hCom= CreateFile( port.c_str(), // use for example \\.\COM10 for higher ports
+ GENERIC_READ | GENERIC_WRITE,
+ 0, // exclusive access
+ NULL, // no security
+ OPEN_EXISTING,
+ 0, // no overlapped I/O
+ NULL); // null template
+ if( hCom == INVALID_HANDLE_VALUE) {
+ stringstream msg;
+ msg << "Failed to open serial device " << port.c_str() << " Errorcode: " <<
+ GetLastError();
+ throw exce_t(errOpen,msg.str());
+ }
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ if (!SetCommTimeouts( hCom, &timeouts)) {
+ stringstream msg;
+ msg << "Failed to SetCommTimeouts for " << port.c_str();
+ throw exce_t(errOpen,msg.str());
+ }
+ if( !SetupComm( hCom, 600, 600)) {// set buffer sizes
+ stringstream msg;
+ msg << "Failed to set buffersize for " << port.c_str();
+ throw exce_t(errOpen,msg.str());
+ }
+ if( !GetCommState( hCom, &dcb)) { // get default values
+ stringstream msg;
+ msg << "Failed to get parameters for " << port.c_str();
+ throw exce_t(errOpen,msg.str());
+ }
+ dcb.BaudRate= 9600;
+ dcb.fOutxCtsFlow= 0;
+ dcb.fOutxDsrFlow= 0;
+ dcb.fOutX= 0;
+ dcb.fInX= 0;
+ dcb.ByteSize= 8;
+ dcb.Parity= NOPARITY;
+ dcb.StopBits= ONESTOPBIT;
+ dcb.fAbortOnError= TRUE;
+ if( !SetCommState( hCom, &dcb)) {
+ stringstream msg;
+ msg << "Failed to set parameters for " << port.c_str();
+ throw exce_t(errOpen,msg.str());
+ }
+}
+#else
+// UNIX:
+void CSerial::open()
+{
+#if defined(WORDS_BIGENDIAN) || !defined(CAN_UNALIGNED)
+ throw exce_t(errOpen, "The serial driver still needs to be ported to your platform.");
+#endif
struct termios tty;
if (port_fd >= 0)
return;
@@ -99,9 +178,9 @@
tty.c_cc[VTIME] = 0;
if ( cfsetispeed( &tty, B9600 ) == -1 )
- cout << "WARNING: CSerial could not set initial input baudot rate" << endl;
+ cout << "WARNING: CSerial could not set initial input baud rate" << endl;
if ( cfsetospeed( &tty, B9600 ) == -1 )
- cout << "WARNING: CSerial could not set initial output baudot rate" << endl;
+ cout << "WARNING: CSerial could not set initial output baud rate" << endl;
if(tcsetattr(port_fd, TCSANOW, &tty) < 0) {
stringstream msg;
@@ -116,18 +195,28 @@
// syncup();
}
+#endif
+#ifdef WIN32
void CSerial::close()
{
+ CloseHandle( hCom);
+ // FIXME: don't care for now resetting up previous bitrate etc...
+ hCom= 0;
+}
+#else
+// UNIX
+void CSerial::close()
+{
if (port_fd >= 0) {
tcsetattr(port_fd, TCSAFLUSH, &gps_ttysave);
}
::close(port_fd);
port_fd = -1;
FD_ZERO(&fds_read);
- timerclear(&typmax_rsptimetv);
}
+#endif
void CSerial::debug(const char * /*mark*/, const Packet_t& /*data*/)
@@ -175,7 +264,7 @@
// input: packet
// returns: <0 error, 0= nothing received, >0 count of data 0..255
-int CSerial::read(Packet_t& data)
+int CSerial::read(Packet_t& data, unsigned milliseconds)
{
int res;
@@ -183,15 +272,10 @@
data.id = 0;
data.size = 0;
- res = serial_read(data);
+ res = serial_read(data, milliseconds);
- if (res < 0) {
- serial_send_nak(0); // FIXME: this is almost useless at the moment...
- res = serial_read(data); // try only once again (for now)
- }
- else if (res > 0) {
+ if (res > 0)
serial_send_ack(data.id);
- } // else if 0 send nothing
return res;
}
@@ -199,52 +283,22 @@
// input: packet
// returns: <0 error, 0= nothing received, >0 count of data 0..255
-int CSerial::read(char* data)
+int CSerial::read(char* data, unsigned milliseconds)
{
- time_t starttime;
- time_t read_timeout = START_TIMEOUT;
- struct timeval starttv, responsetv, durationtv;
uint8_t byte;
- int ready = 0;
int bytes_received = 0;
- if (timerisset(&typmax_rsptimetv)) {
- //taking double typical max response rounded to nxt sec
- read_timeout = (2 * typmax_rsptimetv.tv_sec) + 1;
- if (read_timeout < MIN_TIMEOUT)
- read_timeout = MIN_TIMEOUT;
- }
-
- starttime = ::time(NULL);
-
- while ((::time(NULL) < starttime + read_timeout) && !ready) {
- if (gettimeofday( &starttv, NULL ) == -1)
- timerclear( & starttv );
- if (serial_chars_ready()) {
- if (::read(port_fd, &byte, 1) != 1) {
- cerr << "Serial read failed" << endl;
- return -1;
- }
- if (gettimeofday( &responsetv, NULL ) == -1)
- timerclear( &responsetv );
- if (timerisset(&starttv) && timerisset(&responsetv)) {
- timersub( &responsetv, &starttv, &durationtv );
- if (timercmp( &typmax_rsptimetv, &durationtv, < )) {
- typmax_rsptimetv.tv_sec = durationtv.tv_sec;
- typmax_rsptimetv.tv_usec = durationtv.tv_usec;
- }
- }
- data[bytes_received] = byte;
+ while (serial_char_read( &byte, milliseconds)) {
+ data[bytes_received++] = byte;
if (byte == 10) //read until carriage return
- ready = 1;
- bytes_received++;
- } //chars ready
- } //while
+ break;
+ if (bytes_received > 255) // buffer full
+ break;
+ } //chars ready
return bytes_received;
}
-
// FIXME: needs better error handling!
// input: packet
void CSerial::write(const Packet_t& data)
@@ -252,7 +306,8 @@
serial_write(data);
if (serial_check_ack(data.id)) {
- serial_write(data); // just try again
+ cout << endl << "Serial: resending packet\n";
+ serial_write(data); // just try again
if (serial_check_ack(data.id))
throw exce_t(errWrite,"serial_send_packet failed");
}
@@ -265,12 +320,15 @@
{
// pid_change_bitrate ?
Packet_t gpack_change_bitrate(0, 0x30);
+ static Packet_t test_packet(0, Pid_Command_Data);
static Packet_t pingpacket(0, Pid_Command_Data);
Packet_t response;
uint32_t device_bitrate = 0;
pingpacket.size = 2;
*(uint16_t*)pingpacket.payload = 0x003a;
- int ready = 0;
+#ifdef WIN32
+ DCB dcb;
+#else
struct termios tty;
speed_t speed = B9600;
@@ -284,17 +342,26 @@
return -1;
break;
}
+#endif
*(uint32_t*)gpack_change_bitrate.payload = bitrate;
gpack_change_bitrate.size = 4;
+ test_packet.size = 2;
+ *test_packet.payload = 14;
+ CSerial::write(test_packet);
+ //read units response
+ while (CSerial::read(response))
+ if (response.id == 38 && response.size == 4)
+ break;
+
//send change bitrate request
CSerial::write(gpack_change_bitrate);
//read units response to speed request
- while (!ready && CSerial::read(response)) {
+ while (CSerial::read(response)) {
if (response.id == 0x31 && response.size == 4) {
device_bitrate = *(uint32_t*)response.payload;
- ready = 1;
+ break;
}
}
@@ -305,51 +372,41 @@
cout << "please report this problem to the author of your units driver" << endl;
return -1; // FIXME: throw warning
}
+#ifdef WIN32
+ Sleep( 100);
+ if( !GetCommState( hCom, &dcb)) { // get default values
+ cerr << "error getting port state" << endl;
+ return( -1);
+ }
+ dcb.BaudRate= bitrate;
- //wait 500 millisecs here (like GPSexplorer does)
- usleep(500000);
+ if( !SetCommState( hCom, &dcb)) {
+ cerr << "error setting up bitrate " << bitrate << endl;
+ return( -1);
+ }
+#else
+// UNIX
+ //wait 100 millisecs here, just in case TCSADRAIN doesn't work
+ usleep(100000);
if (tcgetattr(port_fd, &tty) < 0) {
// throw "Failed to get parameters for serial port";
return -1;
}
cfsetispeed(&tty, speed);
cfsetospeed(&tty, speed);
- if(tcsetattr(port_fd, TCSANOW, &tty) < 0) {
+
+ cerr << "Changing speed to " << bitrate << endl;
+ if(tcsetattr(port_fd, TCSADRAIN, &tty) < 0) {
// throw "Failed to set parameters/bitrate for serial port";
return -1;
}
- // FIXME: we should read tty and check if bitrate changed
+#endif
- //wait 100 millisecs here again (like GPSexplorer does)
- usleep(100000);
-
- int i =0;
- ready = 0;
- serial_write(pingpacket);
- while (i < 100 && !ready) {
- ready = serial_chars_ready();
- i++;
- }
- if (!ready) {
- i = 0;
- serial_write(pingpacket);
- while (i < 500 && !ready) {
- ready = serial_chars_ready();
- i++;
- }
- }
- if (serial_check_ack(pingpacket.id)) {
- // throw "changeToBitrate failed";
- return -1;
- }
-
CSerial::write(pingpacket);
CSerial::write(pingpacket);
+ CSerial::write(pingpacket);
- //unset typical response time
- timerclear( &typmax_rsptimetv );
-
return 0;
}
@@ -431,6 +488,9 @@
int res,i;
uint8_t checksum = 0;
int bindex = 3;
+#ifdef WIN32
+ DWORD bytes_written = 0;
+#endif
if (data.id > 255 || data.size > 255) {
cerr << "data.id or data.size to big " << data.id << " " << data.size << endl;
@@ -465,7 +525,17 @@
buff[bindex++] = (uint8_t) DLE;
buff[bindex++] = (uint8_t) ETX;
+#ifdef WIN32
+ res = WriteFile( hCom, buff, bindex, &bytes_written, NULL);
+ if (res) {
+ res = bytes_written;
+ }
+ else {
+ res = -1;
+ }
+#else
res = ::write(port_fd, buff, bindex);
+#endif
debug("s <<",data);
@@ -495,22 +565,49 @@
#endif
}
+#ifdef WIN32
+int CSerial::serial_char_read( uint8_t *byte, unsigned milliseconds)
+{
+ DWORD result;
+ DWORD BytesRead;
-// check if data available
-int CSerial::serial_chars_ready(void)
+ int tries = milliseconds / 20;
+
+ while (tries > 0) {
+ tries--;
+ result= ReadFile( hCom, byte, 1, &BytesRead, NULL);
+ if (BytesRead == 1) {
+ return (1);
+ break;
+ }
+ Sleep( 20);
+
+ }
+ return (0);
+}
+#else
+// UNIX
+// check if data available and read one byte
+int CSerial::serial_char_read( uint8_t *byte, unsigned milliseconds)
{
//fds_read has always set port_fd
+ struct timeval stimeout;
- struct timeval stimeout = {
- 0, //tv_sec
- 180000 //tv_usec .. default delay jeeps uses
- };
+ // according to man select: the timeout structure might be modified after select()
+ stimeout.tv_sec = milliseconds / 1000;
+ stimeout.tv_usec = (milliseconds % 1000) * 1000;
select(port_fd+1, &fds_read, NULL, NULL, &stimeout);
- if (FD_ISSET(port_fd, &fds_read))
+ if (FD_ISSET(port_fd, &fds_read)) {
//ready in time
- return 1;
+ if (::read(port_fd, byte, 1) != 1) {
+ cerr << "Serial read char failed" << endl;
+ return 0;
+ } else {
+ return 1;
+ }
+ }
else
//timed out
//set port_fd again
@@ -518,27 +615,30 @@
return 0;
}
+#endif
-// ack checken for command cmd
-// 0= success, <0 = error
+// check for ack for command cmd
+// 0 = success, <0 = error
int CSerial::serial_check_ack(uint8_t cmd)
{
Packet_t response;
int count;
- count= serial_read( response);
- if (count > 0) {
- if (response.id == Pid_Ack_Byte && response.payload[0] == cmd) {
- return 0;
- } else {
- cout << endl << "serial_check_ack failed: pid sent = $" << hex << (unsigned)cmd;
- cout << " response id = $" << (unsigned)response.id << " pid acked: $" << (unsigned)response.payload[0] << endl;
- return -1;
- }
+ while ((count = serial_read(response)) > 0) {
+ if (response.id == Pid_Ack_Byte && response.payload[0] == cmd)
+ return 0;
+ else if (response.id == Pid_Nak_Byte && response.payload[0] == cmd) {
+ cerr << "CMD " << cmd << ": got NAK, ignoring\n";
+ } else {
+ cerr << "Got unexpected packet: id=" << response.id;
+ for (unsigned n = 0; n < response.size; n++)
+ cerr << ' ' << response.payload[n];
+ cerr << '\n';
+ }
}
- cout << endl << "serial_check_ack failed: no bytes received" << endl;
- return -1;
+
+ return -1; // no input data
}
@@ -570,11 +670,8 @@
// garmin daten entsprechend linkprotokoll auspacken:
// returns received bytecount of data (0..255)
-int CSerial::serial_read(Packet_t& data)
+int CSerial::serial_read(Packet_t& data, unsigned milliseconds)
{
- time_t starttime;
- time_t read_timeout = START_TIMEOUT;
- struct timeval starttv, responsetv, durationtv;
uint8_t byte;
int check_for_dledle = 0; // next byte should be DLE
// without inserted "double" DLEs
@@ -587,32 +684,7 @@
data.id = 0;
data.size = 0;
- if (timerisset(&typmax_rsptimetv)) {
- //taking double typical max response rounded to nxt sec
- read_timeout = (2 * typmax_rsptimetv.tv_sec) + 1;
- if (read_timeout < MIN_TIMEOUT)
- read_timeout = MIN_TIMEOUT;
- }
-
- starttime = ::time(NULL);
-
- while ((::time(NULL) < starttime + read_timeout) && !ready) {
- if (gettimeofday( &starttv, NULL ) == -1)
- timerclear( & starttv );
- if (serial_chars_ready()) {
- if (::read(port_fd, &byte, 1) != 1) {
- cerr << "Serial read failed" << endl;
- return -1;
- }
- if (gettimeofday( &responsetv, NULL ) == -1)
- timerclear( &responsetv );
- if (timerisset(&starttv) && timerisset(&responsetv)) {
- timersub( &responsetv, &starttv, &durationtv );
- if (timercmp( &typmax_rsptimetv, &durationtv, < )) {
- typmax_rsptimetv.tv_sec = durationtv.tv_sec;
- typmax_rsptimetv.tv_usec = durationtv.tv_usec;
- }
- }
+ while (serial_char_read( &byte, milliseconds)) {
// this one first
if (check_for_dledle) {
if (DLE == byte) {
@@ -677,14 +749,14 @@
if (byte == ETX) {
bytes_received++;
ready = 1;
+ break;
}
else {
cout << endl << "ERROR: end byte2 isn't ETX" << endl;
return -1; // FIXME: protocol error
}
}
- } //chars ready
- } //while
+ } //chars ready
debug("r >>", data);
Index: qlandkarte/trunk/src/device/GPSMap76/CDevice.cpp
===================================================================
--- qlandkarte/trunk/src/device/GPSMap76/CDevice.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/GPSMap76/CDevice.cpp (Arbeitskopie)
@@ -171,7 +171,7 @@
serial->write(command);
ready= 0;
- while(!ready && serial->read(response) > 0) {
+ while(!ready && serial->read(response, 5000) > 0) {
if(response.id == 74) {
ready= 1;
//TODO read data
Index: qlandkarte/trunk/src/device/EtrexLegend/CDevice.cpp
===================================================================
--- qlandkarte/trunk/src/device/EtrexLegend/CDevice.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/EtrexLegend/CDevice.cpp (Arbeitskopie)
@@ -177,10 +177,8 @@
*(uint16_t*)command.payload = 0x000A;
serial->write(command);
- sleep(10);
-
- ready= 0;
- while(!ready && serial->read(response) > 0) {
+ ready = 0;
+ while(!ready && serial->read(response, 5000) > 0) {
if(response.id == 74) {
ready= 1;
//TODO read data
Index: qlandkarte/trunk/src/device/EtrexLegend/EtrexLegend.pro
===================================================================
--- qlandkarte/trunk/src/device/EtrexLegend/EtrexLegend.pro (Revision 518)
+++ qlandkarte/trunk/src/device/EtrexLegend/EtrexLegend.pro (Arbeitskopie)
@@ -9,7 +9,9 @@
target.path = $${QLANDKARTE_LIBDIR}
TARGETDEPS += ../../../src/device/libgarmin.a
LIBS += ../../../src/device/libgarmin.a
+win32:LIBS += -L../../../libs/mingw -lpthreadGC2 -lsetupapi
INCLUDEPATH += ../../../src/device
+win32:INCLUDEPATH += ../../../libs/mingw/include
MOC_DIR = .tmp
OBJECTS_DIR = .tmp
TARGET = EtrexLegend
Index: qlandkarte/trunk/src/device/EtrexLegend/loader.cpp
===================================================================
--- qlandkarte/trunk/src/device/EtrexLegend/loader.cpp (Revision 518)
+++ qlandkarte/trunk/src/device/EtrexLegend/loader.cpp (Arbeitskopie)
@@ -27,8 +27,13 @@
static CDevice * device = 0;
}
+#ifdef WIN32
+#define WIN_EXPORT __declspec(dllexport)
+#else
+#define WIN_EXPORT
+#endif
-extern "C" Garmin::IDevice * initEtrexLegend(const char * version)
+extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegend(const char * version)
{
if(strncmp(version,INTERFACE_VERSION,5) != 0) {
return 0;
@@ -42,7 +47,7 @@
}
-extern "C" Garmin::IDevice * initEtrexVista(const char * version)
+extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVista(const char * version)
{
if(strncmp(version,INTERFACE_VERSION,5) != 0) {
return 0;
@@ -61,7 +66,7 @@
// the eTrex Classic is of the same vintage as the eTrex Legend and eTrex Vista.
// So, as far as firmware (and serial communications go), it is closer to those.
// Therefore, I put it here.
-extern "C" Garmin::IDevice * const initEtrexClassic(const char * version)
+extern "C" WIN_EXPORT Garmin::IDevice * const initEtrexClassic(const char * version)
{
if(strncmp(version,INTERFACE_VERSION,5) != 0) {
return 0;
Index: qlandkarte/trunk/src/device/CSerial.h
===================================================================
--- qlandkarte/trunk/src/device/CSerial.h (Revision 518)
+++ qlandkarte/trunk/src/device/CSerial.h (Arbeitskopie)
@@ -23,7 +23,11 @@
#define CSERIAL_H
#include <string>
+#ifdef WIN32
+#include <windows.h>
+#else
#include <termios.h>
+#endif
#include <time.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -39,19 +43,15 @@
if your device does not fit into the protocol implementation
at all, subclass it and make your fixes.
*/
- class CSerial : public ILink
+ class CSerial
{
public:
CSerial(const std::string& port);
virtual ~CSerial();
- /// see ILink::open()
void open();
- /// see ILink::close()
void close();
- /// see ILink::read()
- int read(Packet_t& data);
- /// see ILink::write()
+ int read(Packet_t& data, unsigned milliseconds = 1000);
void write(const Packet_t& data);
/// sync. up sequence
/**
@@ -62,9 +62,8 @@
@return Actual retrieved number of response packets to product_request
*/
virtual int syncup(int responseCount = 0);
+ int read(char *data, unsigned milliseconds = 1000);
- int read(char *data);
-
uint16_t getProductId(){return productId;}
int16_t getSoftwareVersion(){return softwareVersion;}
const std::string& getProductString(){return productString;}
@@ -76,8 +75,8 @@
protected:
- int serial_chars_ready( void);
- int serial_read(Packet_t& data);
+ int serial_char_read( uint8_t *byte, unsigned milliseconds);
+ int serial_read(Packet_t& data, unsigned milliseconds = 1000);
void serial_write(const Packet_t& data);
int serial_check_ack( uint8_t cmd);
@@ -86,15 +85,15 @@
virtual void debug(const char * mark, const Garmin::Packet_t& data);
+#ifdef WIN32
+ HANDLE hCom;
+#else
// file descripor for serial port
int port_fd;
struct termios gps_ttysave;
fd_set fds_read;
- //typical max response time
- struct timeval typmax_rsptimetv;
-
int interface;
-
+#endif
uint16_t productId;
int16_t softwareVersion;
std::string productString;
Index: qlandkarte/trunk/src/CCentralResources.cpp
===================================================================
--- qlandkarte/trunk/src/CCentralResources.cpp (Revision 518)
+++ qlandkarte/trunk/src/CCentralResources.cpp (Arbeitskopie)
@@ -478,6 +478,10 @@
libname = QString("%1/whatGarmin.dll").arg(path);
funcname = QString("initwhatGarmin");
}
+ else if ( m_DeviceName == "EtrexLegend" ) {
+ libname = QString("%1/EtrexLegend.dll").arg(path);
+ funcname = QString("initEtrexLegend");
+ }
else {
libname = QString("%1/GPSMap60CSx.dll").arg(path);
funcname = QString("init%1").arg(m_DeviceName);
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
QLandkarte-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qlandkarte-users