📄 cdevice.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 <errno.h>#include <iostream>#include <sstream>using namespace GPSMap60CSx;using namespace Garmin;using namespace std;namespace GPSMap60CSx{ static const char _clrtbl[1024]={ 0,0,0,0,32,0,0,0,65,0,0,0,106,0,0,0,-117,0,0,0, -76,0,0,0,-43,0,0,0,-1,0,0,0,0,48,0,0,32,48,0,0, 65,48,0,0,106,48,0,0,-117,48,0,0,-76,48,0,0,-43,48,0,0, -1,48,0,0,0,101,0,0,32,101,0,0,65,101,0,0,106,101,0,0, -117,101,0,0,-76,101,0,0,-43,101,0,0,-1,101,0,0,0,-107,0,0, 32,-107,0,0,65,-107,0,0,106,-107,0,0,-117,-107,0,0,-76,-107,0,0, -43,-107,0,0,-1,-107,0,0,0,-54,0,0,32,-54,0,0,65,-54,0,0, 106,-54,0,0,-117,-54,0,0,-76,-54,0,0,-43,-54,0,0,-1,-54,0,0, 0,-1,0,0,32,-1,0,0,65,-1,0,0,106,-1,0,0,-117,-1,0,0, -76,-1,0,0,-43,-1,0,0,-1,-1,0,0,0,0,57,0,32,0,57,0, 65,0,57,0,106,0,57,0,-117,0,57,0,-76,0,57,0,-43,0,57,0, -1,0,57,0,0,48,57,0,32,48,57,0,65,48,57,0,106,48,57,0, -117,48,57,0,-76,48,57,0,-43,48,57,0,-1,48,57,0,0,101,57,0, 32,101,57,0,65,101,57,0,106,101,57,0,-117,101,57,0,-76,101,57,0, -43,101,57,0,-1,101,57,0,0,-107,57,0,32,-107,57,0,65,-107,57,0, 106,-107,57,0,-117,-107,57,0,-76,-107,57,0,-43,-107,57,0,-1,-107,57,0, 0,-54,57,0,32,-54,57,0,65,-54,57,0,106,-54,57,0,-117,-54,57,0, -76,-54,57,0,-43,-54,57,0,-1,-54,57,0,0,-1,57,0,32,-1,57,0, 65,-1,57,0,106,-1,57,0,-117,-1,57,0,-76,-1,57,0,-43,-1,57,0, -1,-1,57,0,0,0,123,0,32,0,123,0,65,0,123,0,106,0,123,0, -117,0,123,0,-76,0,123,0,-43,0,123,0,-1,0,123,0,0,48,123,0, 32,48,123,0,65,48,123,0,106,48,123,0,-117,48,123,0,-76,48,123,0, -43,48,123,0,-1,48,123,0,0,101,123,0,32,101,123,0,65,101,123,0, 106,101,123,0,-117,101,123,0,-76,101,123,0,-43,101,123,0,-1,101,123,0, 0,-107,123,0,32,-107,123,0,65,-107,123,0,106,-107,123,0,-117,-107,123,0, -76,-107,123,0,-43,-107,123,0,-1,-107,123,0,0,-54,123,0,32,-54,123,0, 65,-54,123,0,106,-54,123,0,-117,-54,123,0,-76,-54,123,0,-43,-54,123,0, -1,-54,123,0,0,-1,123,0,32,-1,123,0,65,-1,123,0,106,-1,123,0, -117,-1,123,0,-76,-1,123,0,-43,-1,123,0,-1,-1,123,0,0,0,-67,0, 32,0,-67,0,65,0,-67,0,106,0,-67,0,-117,0,-67,0,-76,0,-67,0, -43,0,-67,0,-1,0,-67,0,0,48,-67,0,32,48,-67,0,65,48,-67,0, 106,48,-67,0,-117,48,-67,0,-76,48,-67,0,-43,48,-67,0,-1,48,-67,0, 0,101,-67,0,32,101,-67,0,65,101,-67,0,106,101,-67,0,-117,101,-67,0, -76,101,-67,0,-43,101,-67,0,-1,101,-67,0,0,-107,-67,0,32,-107,-67,0, 65,-107,-67,0,106,-107,-67,0,-117,-107,-67,0,-76,-107,-67,0,-43,-107,-67,0, -1,-107,-67,0,0,-54,-67,0,32,-54,-67,0,65,-54,-67,0,106,-54,-67,0, -117,-54,-67,0,-76,-54,-67,0,-43,-54,-67,0,-1,-54,-67,0,0,-1,-67,0, 32,-1,-67,0,65,-1,-67,0,106,-1,-67,0,-117,-1,-67,0,-76,-1,-67,0, -43,-1,-67,0,-1,-1,-67,0,0,0,-1,0,32,0,-1,0,65,0,-1,0, 106,0,-1,0,-117,0,-1,0,-76,0,-1,0,-43,0,-1,0,-1,0,-1,0, 0,48,-1,0,32,48,-1,0,65,48,-1,0,106,48,-1,0,-117,48,-1,0, -76,48,-1,0,-43,48,-1,0,-1,48,-1,0,0,101,-1,0,32,101,-1,0, 65,101,-1,0,106,101,-1,0,-117,101,-1,0,-76,101,-1,0,-43,101,-1,0, -1,101,-1,0,0,-107,-1,0,32,-107,-1,0,65,-107,-1,0,106,-107,-1,0, -117,-107,-1,0,-76,-107,-1,0,-43,-107,-1,0,-1,-107,-1,0,0,-54,-1,0, 32,-54,-1,0,65,-54,-1,0,106,-54,-1,0,-117,-54,-1,0,-76,-54,-1,0, -43,-54,-1,0,-1,-54,-1,0,0,-1,-1,0,32,-1,-1,0,65,-1,-1,0, 106,-1,-1,0,-117,-1,-1,0,-76,-1,-1,0,-43,-1,-1,0,-1,-1,-1,0, -1,-1,-1,0,-26,-26,-26,0,-43,-43,-43,0,-59,-59,-59,0,-76,-76,-76,0, -92,-92,-92,0,-108,-108,-108,0,-125,-125,-125,0,115,115,115,0,98,98,98,0, 82,82,82,0,65,65,65,0,49,49,49,0,32,32,32,0,16,16,16,0, 0,0,0,0}; class CMutexLocker { public: CMutexLocker(pthread_mutex_t& mutex) : mutex(mutex) { pthread_mutex_lock(&mutex); } ~CMutexLocker() { pthread_mutex_unlock(&mutex); } private: pthread_mutex_t& mutex; }; void * rtThread(void *ptr) { cout << "start thread" << endl; Packet_t command; Packet_t response; CDevice * dev = (CDevice*)ptr; CMutexLocker lock(dev->mutex); try{ pthread_mutex_lock(&dev->dataMutex); dev->_acquire(); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Start_Pvt_Data; dev->usb->write(command); while(dev->doRealtimeThread){ pthread_mutex_unlock(&dev->dataMutex); if(dev->usb->read(response)){ if(response.id == Pid_Pvt_Data){ D800_Pvt_Data_t * srcPvt = (D800_Pvt_Data_t*)response.payload; pthread_mutex_lock(&dev->dataMutex); dev->PositionVelocityTime << *srcPvt; pthread_mutex_unlock(&dev->dataMutex); } } pthread_mutex_lock(&dev->dataMutex); } command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Stop_Pvt_Data; dev->usb->write(command); dev->_release(); pthread_mutex_unlock(&dev->dataMutex); } catch(exce_t& e){ pthread_mutex_trylock(&dev->dataMutex); dev->lasterror = "Realtime thread failed. " + e.msg; dev->doRealtimeThread = false; pthread_mutex_unlock(&dev->dataMutex); } cout << "stop thread" << endl; return 0; }}CDevice::CDevice() : devid(0) , usb(0) , doRealtimeThread(false) , pScreen(0){ pthread_mutex_init(&dataMutex, NULL);}CDevice::~CDevice(){ if(pScreen) delete [] pScreen;}const string& CDevice::getCopyright(){ copyright = "<h1>QLandkarte Device Driver for Garmin " + devname + "</h1>" "<h2>Driver I/F Ver. " INTERFACE_VERSION "</h2>" "<p>© 2007 by Oliver Eichler (oliver.eichler@gmx.de)</p>" "<p>© Venture HC Screenshot support by Torsten Reuschel (me@fuesika.de)</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(){ usb = new CUSB(); usb->open(); if(devid == 0x01a5){ Packet_t command; command.type = GUSB_PROTOCOL_LAYER; command.id = GUSB_SESSION_START; command.size = 0; *(uint16_t*)command.payload = 0x0000; usb->write(command); usb->write(command); } usb->syncup(); if(strncmp(usb->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(usb->getProductId() != devid){ string msg = "No " + devname + " unit detected. Please retry to select other device driver."; throw exce_t(errSync,msg); } } else{ if(usb->getProductId() != 0x0124 && usb->getProductId() != 0x0272){ 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(usb == 0) return; Packet_t command; Packet_t response; // ??? command.type = GUSB_APPLICATION_LAYER; command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; usb->write(command); // read 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); bool started = false; while(usb->read(response)){ 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(errRuntime,msg.str()); } started = true; } if(response.type == 0 && response.id == 0 && started ){ break; // no bytes returned, so I guess we are done } } // 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); started = false; while(usb->read(response)){ if(response.id == 74){ //TODO read data started = true; } if(response.type == 0 && response.id == 0 && started ){ break; // no bytes returned, so I guess we are done } } 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; // ??? command.type = GUSB_APPLICATION_LAYER; command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; usb->write(command); // 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);// usb->setBulkRead( false); bool started = false; 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; started = true; } if(response.type == 0 && response.id == 0 && started ){// usb->setBulkRead( true); break; // no bytes returned, so I guess we are done } } 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(usb == 0) return; Packet_t command; Packet_t response; // ??? command.type = GUSB_APPLICATION_LAYER; command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; usb->write(command); // request waypoints command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; usb->write(command); while(1){ if(!usb->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){ D110_Wpt_t * srcWpt = (D110_Wpt_t*)response.payload; waypoints.push_back(Wpt_t()); Wpt_t& tarWpt = waypoints.back(); tarWpt << *srcWpt; } if(response.id == Pid_Xfer_Cmplt){ break; } } // request proximity waypoints command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Prx; usb->write(command); while(1){ if(!usb->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){ D110_Wpt_t * srcWpt = (D110_Wpt_t*)response.payload; waypoints.push_back(Wpt_t()); Wpt_t& tarWpt = waypoints.back(); tarWpt << *srcWpt; } if(response.id == Pid_Xfer_Cmplt){ break; } }#ifdef DBG_SHOW_WAYPOINT list<Wpt_t>::const_iterator wpt = waypoints.begin(); while(wpt != waypoints.end()){ cout << "-------------------------" << endl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -