⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdevice.cpp

📁 QLandkarte - use your Garmin GPS with Linux Requirements: * > Qt 4.2.x (Qt 4.1.x will not wo
💻 CPP
字号:
/**********************************************************************************************    Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de    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 "CDevice.h"#include <Garmin.h>#include <iostream>#include <sstream>using namespace EtrexLegend;using namespace Garmin;using namespace std;#define GRMN_ETREX_LEGEND  411#define MAP_UPLOAD_BITRATE 115200  // or 57600, 38400, 19200, 9600#define WAYPOINT_DL_BITRATE 57600#define TRACK_DL_BITRATE 57600#define GRMN_DEFAULT_BITRATE 9600CDevice::CDevice()    : serial(0){}CDevice::~CDevice(){}const string& CDevice::getCopyright(){    copyright = "<h1>QLandkarte Device Driver for EtrexLegend (EXPERIMENTAL)</h1>"                "<h2>Driver I/F Ver. " INTERFACE_VERSION "</h2>"                "<p>&#169; 2007 by Oliver Eichler (oliver.eichler@gmx.de)</p>"                "<p>modified 2007 by Andreas Stenglein to work with serial eTrex Legend</p>"                "<p>This driver 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. </p>";    return copyright;}void CDevice::_acquire(){    serial = new CSerial(port);    //serial = new CSerial();    serial->open();    serial->syncup();    if(strncmp(serial->getProductString().c_str(), devname.c_str(), devname.size()) != 0){        string msg = "No " + devname + " unit detected. Please retry to select other device driver.";        throw exce_t(errSync,msg);    }    if(devid){        if(serial->getProductId() != devid){            string msg = "No " + devname + " unit detected. Please retry to select other device driver.";            throw exce_t(errSync,msg);        }    }    else{            string msg = "No " + devname + " unit detected. Please retry to select other device driver.";            throw exce_t(errSync,msg);    }}void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * key, void (*callback)(uint32_t,uint32_t,void*), void* data){    if(serial == 0) return;    int ready= 0;    Packet_t command;    Packet_t response;    // ???    command.id   = 0x1C;    command.size = 2;    *(uint16_t*)command.payload = 0x0000;    serial->write(command);    // read SD Ram capacity    command.id   = Pid_Command_Data;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Mem;    serial->write(command);    while(serial->read(response) > 0){ // FIXME:        if(response.id == Pid_Capacity_Data){            cout << "free memory: " << dec << (((uint32_t*)response.payload)[1] / (1024*1024)) << " MB" << endl;            uint32_t memory = ((uint32_t*)response.payload)[1];            if(memory < size){                stringstream msg;                msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";                throw exce_t(errBlocked,msg.str());            }        }    }// KEY_UPLOAD: UNTESTED: someone should check how/if this works    // send unlock key if present    if(key){        command.id   = Pid_Tx_Unlock_Key;        command.size = strlen(key) + 1;        memcpy(command.payload,key,command.size);        serial->write(command);        while(serial->read(response) > 0 ){ // FIXME:            if(response.id == Pid_Ack_Unlock_key){                //TODO read data            }        }    }    if (serial->setBitrate( MAP_UPLOAD_BITRATE)) {        throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second");    }    // switch to map transfer mode erase old map(?)    command.id   = 75;    command.size = 2;    *(uint16_t*)command.payload = 0x000A;    serial->write(command);    ready= 0;    while(!ready && serial->read(response) > 0){        if(response.id == 74){          ready= 1;            //TODO read data        }    }    uint32_t total  = size;    uint32_t offset = 0, chunkSize;    command.id   = 36;    // USB:    transfer file by chunks of 0x1000 - 0x0000C - sizeof(offset) = 0x0FF0 bytes    // Serial: transfer file by chunks of 0xfe - sizeof(offset) =  0xfa = 250 bytes    while(size){        chunkSize       = (size < (254 - sizeof(offset))) ? size : (254 - sizeof(offset));        command.size    = chunkSize + sizeof(offset);        *(uint32_t*)command.payload = offset;        memcpy(command.payload + sizeof(offset),mapdata,chunkSize);        size    -= chunkSize;        mapdata += chunkSize;        offset  += chunkSize;        serial->write(command);        if(callback) callback(total - size, total, data);    }    // terminate map transfer mode (?)    command.id   = 45;    command.size = 2;    *(uint16_t*)command.payload = 0x000A;    serial->write(command);}void CDevice::_queryMap(std::list<Map_t>& maps){    maps.clear();    if(serial == 0) return;    Packet_t command;    Packet_t response;    // ???    command.id   = 0x1C;    command.size = 2;    *(uint16_t*)command.payload = 0x0000;    serial->write(command);    // Request map overview table    command.id   = 0x59;    command.size = 19;    Map_Request_t * req = (Map_Request_t*)command.payload;    req->dummy1 = 0;    req->dummy2 = 10;    strcpy(req->section,"MAPSOURC.MPS");    serial->write(command);    uint32_t size   = 1024;    uint32_t fill   = 0;    char * pData    = (char*)calloc(1,size);    while(serial->read(response)){        // acknowledge request (???)        if(response.id == 0x5B){            //TODO: read data        }        // chunk of MAPSOURC.MPS section        // Each chunk is prepended by a chunk counter of type uint8_t.        // This has to be skipped. That's why the peculiar math.        if(response.id == 0x5A){            // realloc memory if chunk does not fit            if((fill +  response.size - 1) > size){                size += size;                pData = (char*)realloc(pData,size);            }            memcpy(&pData[fill], response.payload + 1, response.size - 1);            fill += response.size - 1;        }    }    Map_Info_t * pInfo = (Map_Info_t*)pData;    while(pInfo->tok == 0x4C){        Map_t m;        char * pStr = pInfo->name1;        m.mapName = pStr;        pStr += strlen(pStr) + 1;        m.tileName = pStr;        maps.push_back(m);        pInfo =  (Map_Info_t*)(((char*)pInfo) + pInfo->size + sizeof(pInfo->tok) + sizeof(pInfo->size));    }    free(pData);}void CDevice::_downloadWaypoints(list<Garmin::Wpt_t>& waypoints){    waypoints.clear();    if(serial == 0) return;    Packet_t command;    Packet_t response;    // ???    command.id   = 0x1C;    command.size = 2;    *(uint16_t*)command.payload = 0x0000;    serial->write(command);    if (serial->setBitrate( WAYPOINT_DL_BITRATE)) {        throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second");    }    // request waypoints    command.id   = Pid_Command_Data;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Wpt;    serial->write(command);    while(1){        if(!serial->read(response)) continue;        if(response.id == Pid_Records){#ifdef DBG_SHOW_WAYPOINT            cout << "number of waypoints:" << *(int16_t*)response.payload << endl;#endif        }        if(response.id == Pid_Wpt_Data){            D108_Wpt_t * srcWpt = (D108_Wpt_t*)response.payload;            waypoints.push_back(Wpt_t());            Wpt_t& tarWpt = waypoints.back();            tarWpt << *srcWpt;        }        if(response.id == Pid_Xfer_Cmplt){            break;        }    }// unsupported by etrex Legend ?#if 1    // request proximity waypoints    command.id   = Pid_Command_Data;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Prx;    serial->write(command);    while(1){        if(!serial->read(response)) continue;        if(response.id == Pid_Records){            //TODO read data#ifdef DBG_SHOW_WAYPOINT            cout << "number of proximity waypoints:" << *(int16_t*)response.payload << endl;#endif        }        if(response.id == Pid_Prx_Wpt_Data){            D108_Wpt_t * srcWpt = (D108_Wpt_t*)response.payload;            waypoints.push_back(Wpt_t());            Wpt_t& tarWpt = waypoints.back();            tarWpt << *srcWpt;        }        if(response.id == Pid_Xfer_Cmplt){            break;        }    }#endif#ifdef DBG_SHOW_WAYPOINT    list<Wpt_t>::const_iterator wpt = waypoints.begin();    while(wpt != waypoints.end()){        cout << "-------------------------" << endl;        cout << "class      " << hex << (int)wpt->wpt_class << endl;        cout << "dspl_color " << hex << (int)wpt->dspl_color << endl;        cout << "dspl_attr  " << hex << (int)wpt->dspl_attr << endl;        cout << "smbl       " << dec <<(int)wpt->smbl << endl;        cout << "lat        " << wpt->lat << endl;        cout << "lon        " << wpt->lon << endl;        cout << "alt        " << wpt->alt << endl;        cout << "dpth       " << wpt->dpth << endl;        cout << "dist       " << wpt->dist << endl;        cout << "state      " << wpt->state << endl;        cout << "cc         " << wpt->cc << endl;        cout << "ete        " << wpt->ete << endl;        cout << "temp       " << wpt->temp << endl;        cout << "time       " << wpt->time << endl;        cout << "category   " << wpt->wpt_cat << endl;        cout << "ident      " << wpt->ident << endl;        cout << "comment    " << wpt->comment << endl;        cout << "facility   " << wpt->facility << endl;        cout << "city       " << wpt->city << endl;        cout << "addr       " << wpt->addr << endl;        cout << "crossroad  " << wpt->crossroad << endl;        ++wpt;    }#endif    if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) {        throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second");    }}void CDevice::_uploadWaypoints(std::list<Garmin::Wpt_t>& waypoints){    if(serial == 0) return;    uint16_t prx_wpt_cnt = 0;    list<Wpt_t>::const_iterator wpt = waypoints.begin();// does etrex Legend support prx waypoints?    while(wpt != waypoints.end()){        if(wpt->dist != 1e25f) ++prx_wpt_cnt;        ++wpt;    }    Packet_t command;    Packet_t response;    // ???    command.id   = 0x1C;    command.size = 2;    *(uint16_t*)command.payload = 0x0000;    serial->write(command);    if (serial->setBitrate( WAYPOINT_DL_BITRATE)) {        throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second");    }    // transmit proximity waypoints first    if(prx_wpt_cnt){        //announce number of records        command.id   = Pid_Records;        command.size = 2;        *(uint16_t*)command.payload = prx_wpt_cnt;        serial->write(command);        wpt = waypoints.begin();        while(wpt != waypoints.end()){            if(wpt->dist != 1e25f){                command.id   = Pid_Prx_Wpt_Data;                D108_Wpt_t * p = (D108_Wpt_t *)command.payload;                command.size = *wpt >> *p;                serial->write(command);            }            ++wpt;        }        //announce number of records        command.id   = Pid_Xfer_Cmplt;        command.size = 2;        *(uint16_t*)command.payload = Cmnd_Transfer_Prx;        serial->write(command);    }    //transmit _all_ waypoints    //announce number of records    command.id   = Pid_Records;    command.size = 2;    *(uint16_t*)command.payload = waypoints.size();    serial->write(command);    wpt = waypoints.begin();    while(wpt != waypoints.end()){        command.id   = Pid_Wpt_Data;        D108_Wpt_t * p = (D108_Wpt_t *)command.payload;        command.size = *wpt >> *p;        serial->write(command);        ++wpt;    }    //announce number of records    command.id   = Pid_Xfer_Cmplt;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Wpt;    serial->write(command);    if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) {        throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second");    }}void CDevice::_downloadTracks(std::list<Garmin::Track_t>& tracks){    tracks.clear();    if(serial == 0) return;    Packet_t command;    Packet_t response;    // ???    command.id   = 0x1C;    command.size = 2;    *(uint16_t*)command.payload = 0x0000;    serial->write(command);    if (serial->setBitrate( TRACK_DL_BITRATE)) {        throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second");    }    command.id   = Pid_Command_Data;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Trk;    serial->write(command);    int         trackidx = 0;    string      name;    Track_t *   track = 0;    while(1){        if(!serial->read(response)) continue;        if(response.id == Pid_Trk_Hdr){            trackidx = 0;            D310_Trk_Hdr_t * hdr = (D310_Trk_Hdr_t*)response.payload;            tracks.push_back(Track_t());            track = &tracks.back();            *track << *hdr;            name  = hdr->ident;        }        if(response.id == Pid_Trk_Data){            D301_Trk_t * data = (D301_Trk_t*)response.payload;            TrkPt_t pt;            if(data->new_trk){                if(trackidx){                    tracks.push_back(Track_t());                    Track_t& t = tracks.back();                    t.color = track->color;                    t.dspl = track->dspl;                    char str[256];                    sprintf(str,"%s_%d",name.c_str(),trackidx++);                    t.ident = str;                    track = &t;                }                else{                    ++trackidx;                }            }            pt << *data;            track->track.push_back(pt);        }        if(response.id == Pid_Xfer_Cmplt){            break;        }    }    if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) {        throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second");    }}void CDevice::_release(){    if(serial == 0) return;    serial->close();    delete serial;    serial = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -