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

📄 cdevice.cpp

📁 QLandkarte - use your Garmin GPS with Linux Requirements: * > Qt 4.2.x (Qt 4.1.x will not wo
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************************************    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.  LvD: Comparison of this driver with a SnoopyPro log of MapSource for       Windows communication with the unit:       Mapsource transmits an undocumented PL (physical layer) package       with Pid equal to 16 immediately after receipt of the       Pid_Session_started PL package and receives a PL package with       Pid 17 and a payload of 4 bytes in return.  Without       documentation of what info is in the returned package, there       does not seem a reason to reproduce it.       More interestingly, immediately before sending a Pid_Records       package, Mapsource transmits a similar package, but with       Pid_Records (27) replaced by 28, and that reports zero packages       to follow.  The suspicion is obviously that there are Garmin       units out there that have chips with Pid_Records mistyped as 28       instead of 27.  Logic seems to say that Garmin knows best what       bugs there are in their firmware and should be followed.       Transmitting a packet with a Pid of 28 in general may not be a       problem since the specification says to ignore packages you do       not understand.  However, it is not quite clear whether this       extends only to the host or also to Garmin devices.  I assume       however it does.  See 5.1, "Undocumented application packets"       and 6.3       It is not clear to me in some cases how many packets are to be       send in a Pid_Records/Pid_Xfer_Cmplt sequence.  So I am making it       then to be one packet.  I am not aware that Garmin devices       actually "monitor the progress" of the transfers.  LvD: EOT**********************************************************************************************/#include "CDevice.h"#include <Garmin.h>#include <iostream>#include <sstream>#include <QtGui>using namespace EtrexLegendCx;using namespace Garmin;using namespace std;CDevice::CDevice()    : usb(0){    copyright = "<h1>QLandkarte Device Driver for EtrexLegendCx</h1>"                "<h2>Driver I/F Ver. " INTERFACE_VERSION "</h2>"                "<p>&#169; 2007 by Oliver Eichler (oliver.eichler@gmx.de)</p>"		"<p>&#169; 2007 eTrex Legend Cx specific portions Bob Heise (heise2k@gmail.com)</p>"		"<p>&#169; 2007 Edits by Leon van Dommelen (dommelen@eng.fsu.edu)</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>";}CDevice::~CDevice(){}void CDevice::_acquire(){    // activate the driver    usb = new CUSB();    usb->open();    usb->syncup();    // check the product ID    if(usb->getProductId() != 0x01a5 &&       usb->getProductId() != 0x0124 &&       usb->getProductId() != 0x0312 &&       usb->getProductId() != 0x02b6){        throw exce_t(errSync,"No eTrex LegendCx compatible unit detected. Please retry to select other device driver.");    }    // Terminate if the requirements are not met    if (usb->getDataType(0,'A',(uint16_t)100) != 110 ||	usb->getDataType(0,'A',(uint16_t)400) != 110 ||	usb->getDataType(0,'A',(uint16_t)301) != 312 ||	usb->getDataType(1,'A',(uint16_t)301) != 302) {        if(strncmp(usb->getProductString().c_str(), "eTrex LegendCx", 14) == 0){            throw exce_t(errSync,"This eTrex LegendCx unit does not support the expected protocols?! Please try to select another device driver.");	}	else{	    throw exce_t(errSync,"This unit is not eTrex LegendCx compatible. Please try to select another device driver.");	}    }}void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * key, void (*callback)(uint32_t,uint32_t,void*), void* data){    if(usb == 0) return;    Packet_t command;    Packet_t response;    // We do not know whether this will work    if(strncmp(usb->getProductString().c_str(), "eTrex LegendCx", 14) != 0 &&       strncmp(usb->getProductString().c_str(), "GPSMap76CSX", 11) != 0 &&       strncmp(usb->getProductString().c_str(), "GPSMap76CX", 10) != 0 &&       strncmp(usb->getProductString().c_str(), "GPSMap60CSX", 11) != 0 &&       strncmp(usb->getProductString().c_str(), "GPSMap60CX", 10) != 0 &&       strncmp(usb->getProductString().c_str(), "eTrex VentureCx", 15) != 0 &&       strncmp(usb->getProductString().c_str(), "eTrex VistaCx", 13) != 0 &&       strncmp(usb->getProductString().c_str(), "eTrex Venture HC", 16) != 0 &&       strncmp(usb->getProductString().c_str(), "eTrex Vista HCx", 15) != 0){	    int res = QMessageBox::question(0,QObject::tr("Map upload is unverified"),QObject::tr("Map upload is unverified for this device and may damage it!  Proceed at your own risk?"),QMessageBox::Yes|QMessageBox::No,QMessageBox::No);	    if(res == QMessageBox::No){		throw exce_t(errRuntime,"Upload aborted.");	    }    }    // ask for SD Ram capacity    command.type = GUSB_APPLICATION_LAYER;    command.id   = Pid_Command_Data;    command.size = 2;    *(uint16_t*)command.payload = Cmnd_Transfer_Mem;    usb->write(command);    // try to read SD Ram capacity    uint32_t memory = 0;    while(usb->read(response)){        if(response.id == Pid_Capacity_Data){            cout << "free memory: " << dec << (((uint32_t*)response.payload)[1] / (1024*1024)) << " MB" << endl;            memory = ((uint32_t*)response.payload)[1];        }    }    if(memory < size){        stringstream msg;        msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";        throw exce_t(errRuntime,msg.str());    }    // send unlock key if present    if(key){        command.type = GUSB_APPLICATION_LAYER;        command.id   = Pid_Tx_Unlock_Key;        command.size = strlen(key) + 1;        memcpy(command.payload,key,command.size);        usb->write(command);        while(usb->read(response)){            if(response.id == Pid_Ack_Unlock_key){                //TODO read data            }        }    }    // switch to map transfer mode erase old map(?)    command.type = GUSB_APPLICATION_LAYER;    command.id   = 75;    command.size = 2;    *(uint16_t*)command.payload = 0x000A;    usb->write(command);    // read incoming data    while(usb->read(response)){        if(response.id == 74){            //TODO read data        }    }    // transfer file    uint32_t total  = size;    uint32_t offset = 0, chunkSize;    command.type = GUSB_APPLICATION_LAYER;    command.id   = 36;    // transfer file by chunks of 0x1000 - 0x0000C - sizeof(offset) = 0x0FF0 bytes    while(size){        chunkSize       = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - 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;        usb->write(command);        if(callback) callback(total - size, total, data);    }    // terminate map transfer mode (?)    command.type = GUSB_APPLICATION_LAYER;    command.id   = 45;    command.size = 2;    *(uint16_t*)command.payload = 0x000A;    usb->write(command);}void CDevice::_queryMap(std::list<Map_t>& maps){    maps.clear();    if(usb == 0) return;    Packet_t command;    Packet_t response;    // Request map overview table    command.type = GUSB_APPLICATION_LAYER;    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");    usb->write(command);    uint32_t size   = 1024;    uint32_t fill   = 0;    char * pData    = (char*)calloc(1,size);    while(usb->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);}

⌨️ 快捷键说明

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