garmindev-0.3.4+svn3432/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake0000644000175000017500000000122712002232271024276 0ustar miramira# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) if (_insource) message(SEND_ERROR "${_errorMessage}") message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") endif (_insource) endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) garmindev-0.3.4+svn3432/cmake/Modules/DefineCompilerFlags.cmake0000644000175000017500000000053112002232271022574 0ustar miramira# define system dependent compiler flags include(CheckCXXCompilerFlag) # with -fPIC if(UNIX AND NOT WIN32) if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") check_cxx_compiler_flag("-fPIC" WITH_FPIC) if(WITH_FPIC) ADD_DEFINITIONS(-fPIC) endif(WITH_FPIC) endif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") endif(UNIX AND NOT WIN32) garmindev-0.3.4+svn3432/cmake/Modules/DefineCMakeDefaults.cmake0000644000175000017500000000161112002232271022515 0ustar miramira# Always include srcdir and builddir in include path # This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in # about every subdir # since cmake 2.4.0 set(CMAKE_INCLUDE_CURRENT_DIR ON) # Put the include dirs which are in the source or build tree # before all other include dirs, so the headers in the sources # are prefered over the already installed ones # since cmake 2.4.1 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # Use colored output # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here set(GENERIC_LIB_VERSION "0.1.0") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE ) endif (NOT CMAKE_BUILD_TYPE) garmindev-0.3.4+svn3432/cmake/Modules/FindGDAL.cmake0000644000175000017500000000371712002232271020253 0ustar miramira# - Try to find GDAL # Once done this will define # # GDAL_FOUND - system has GDAL # GDAL_INCLUDE_DIRS - the GDAL include directory # GDAL_LIBRARIES - Link these to use GDAL # GDAL_DEFINITIONS - Compiler switches required for using GDAL # # Copyright (c) 2006 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (GDAL_LIBRARIES AND GDAL_INCLUDE_DIRS) # in cache already set(GDAL_FOUND TRUE) else (GDAL_LIBRARIES AND GDAL_INCLUDE_DIRS) find_path(GDAL_INCLUDE_DIR NAMES gdal.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include /usr/include/gdal /usr/local/include/gdal /opt/local/include/gdal /sw/include/gdal C:/Progra~1/FWTools2.2.8/include C:/Progra~1/FWTools2.1.0/include ) # debian uses version suffixes # add suffix evey new release find_library(GDAL_LIBRARY NAMES gdal gdal1.3.2 gdal1.4.0 gdal1.5.0 gdal gdal_i PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib C:/Progra~1/FWTools2.2.8/lib C:/Progra~1/FWTools2.1.0/lib ) set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR} ) set(GDAL_LIBRARIES ${GDAL_LIBRARY} ) if (GDAL_INCLUDE_DIRS AND GDAL_LIBRARIES) set(GDAL_FOUND TRUE) endif (GDAL_INCLUDE_DIRS AND GDAL_LIBRARIES) if (GDAL_FOUND) if (NOT GDAL_FIND_QUIETLY) message(STATUS "Found GDAL: ${GDAL_LIBRARIES}") endif (NOT GDAL_FIND_QUIETLY) else (GDAL_FOUND) if (GDAL_FIND_REQUIRED) message(FATAL_ERROR "Could not find GDAL") endif (GDAL_FIND_REQUIRED) endif (GDAL_FOUND) # show the GDAL_INCLUDE_DIRS and GDAL_LIBRARIES variables only in the advanced view mark_as_advanced(GDAL_INCLUDE_DIRS GDAL_LIBRARIES) endif (GDAL_LIBRARIES AND GDAL_INCLUDE_DIRS) garmindev-0.3.4+svn3432/cmake/Modules/FindUSB.cmake0000644000175000017500000000354612002232271020175 0ustar miramira# - Try to find USB # Once done this will define # # USB_FOUND - system has USB # USB_INCLUDE_DIRS - the USB include directory # USB_LIBRARIES - Link these to use USB # USB_DEFINITIONS - Compiler switches required for using USB # # Copyright (c) 2009 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIRS) # in cache already set(LIBUSB_FOUND TRUE) elseif (APPLE) # use system libraries set(LIBUSB_FOUND FALSE) else (LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIRS) find_path(LIBUSB_INCLUDE_DIR NAMES usb.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include /usr/include/gdal /usr/local/include/gdal /opt/local/include/gdal /sw/include/gdal ) # debian uses version suffixes # add suffix evey new release find_library(LIBUSB_LIBRARY NAMES usb PATHS /usr/lib /usr/lib64 /usr/local/lib /opt/local/lib /sw/lib ) set(LIBUSB_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIR} ) set(LIBUSB_LIBRARIES ${LIBUSB_LIBRARY} ) if (LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES) set(LIBUSB_FOUND TRUE) endif (LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES) if (LIBUSB_FOUND) if (NOT LIBUSB_FIND_QUIETLY) message(STATUS "Found LIBUSB: ${LIBUSB_LIBRARIES}") endif (NOT LIBUSB_FIND_QUIETLY) else (LIBUSB_FOUND) if (LIBUSB_FIND_REQUIRED) message(FATAL_ERROR "Could not find LIBUSB") endif (LIBUSB_FIND_REQUIRED) endif (LIBUSB_FOUND) # show the LIBUSB_INCLUDE_DIRS and LIBUSB_LIBRARIES variables only in the advanced view mark_as_advanced(LIBUSB_INCLUDE_DIRS LIBUSB_LIBRARIES) endif (LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIRS) garmindev-0.3.4+svn3432/cmake/Modules/FindPROJ.cmake0000644000175000017500000000377712002232271020324 0ustar miramira# - Try to find PROJ # Once done this will define # # PROJ_FOUND - system has PROJ # PROJ_INCLUDE_DIRS - the PROJ include directory # PROJ_LIBRARIES - Link these to use PROJ # PROJ_DEFINITIONS - Compiler switches required for using PROJ # # Copyright (c) 2009 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (PROJ_LIBRARIES AND PROJ_INCLUDE_DIRS) # in cache already set(PROJ_FOUND TRUE) else (PROJ_LIBRARIES AND PROJ_INCLUDE_DIRS) find_path(PROJ_INCLUDE_DIR NAMES projects.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include C:/Progra~1/FWTools2.2.8/include C:/Progra~1/FWTools2.1.0/include PATH_SUFFIXES proj4 ) mark_as_advanced(PROJ_INCLUDE_DIR) find_library(LIBPROJ_LIBRARY NAMES proj proj proj_i PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib C:/Progra~1/FWTools2.2.8/lib C:/Progra~1/FWTools2.1.0/lib ) mark_as_advanced(LIBPROJ_LIBRARY) if (LIBPROJ_LIBRARY) set(LIBPROJ_FOUND TRUE) endif (LIBPROJ_LIBRARY) set(PROJ_INCLUDE_DIRS ${PROJ_INCLUDE_DIR} ) if (LIBPROJ_FOUND) set(PROJ_LIBRARIES ${PROJ_LIBRARIES} ${LIBPROJ_LIBRARY} ) endif (LIBPROJ_FOUND) if (PROJ_INCLUDE_DIRS AND PROJ_LIBRARIES) set(PROJ_FOUND TRUE) endif (PROJ_INCLUDE_DIRS AND PROJ_LIBRARIES) if (PROJ_FOUND) if (NOT PROJ_FIND_QUIETLY) message(STATUS "Found PROJ: ${PROJ_LIBRARIES}") endif (NOT PROJ_FIND_QUIETLY) else (PROJ_FOUND) if (PROJ_FIND_REQUIRED) message(FATAL_ERROR "Could not find PROJ") endif (PROJ_FIND_REQUIRED) endif (PROJ_FOUND) # show the PROJ_INCLUDE_DIRS and PROJ_LIBRARIES variables only in the advanced view mark_as_advanced(PROJ_INCLUDE_DIRS PROJ_LIBRARIES) endif (PROJ_LIBRARIES AND PROJ_INCLUDE_DIRS) garmindev-0.3.4+svn3432/cmake/Modules/COPYING-CMAKE-SCRIPTS0000644000175000017500000000245712002232271020737 0ustar miramiraRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. garmindev-0.3.4+svn3432/cmake/Modules/DefineInstallationPaths.cmake0000644000175000017500000000713212002232271023512 0ustar miramiraif (UNIX) IF (NOT APPLICATION_NAME) MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") SET(APPLICATION_NAME ${PROJECT_NAME}) ENDIF (NOT APPLICATION_NAME) STRING(TOLOWER ${APPLICATION_NAME} _APPLICATION_NAME) # Suffix for Linux SET(LIB_SUFFIX CACHE STRING "Define suffix of directory name (32/64)" ) SET(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries" FORCE ) SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Base directory for files which go to share/" FORCE ) SET(DATA_INSTALL_PREFIX "${SHARE_INSTALL_PREFIX}/" CACHE PATH "The parent directory where applications can install their data" FORCE) # The following are directories where stuff will be installed to SET(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "The ${_APPLICATION_NAME} binary install dir (default prefix/bin)" FORCE ) SET(SBIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/sbin" CACHE PATH "The ${_APPLICATION_NAME} sbin install dir (default prefix/sbin)" FORCE ) SET(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" FORCE ) SET(LIBEXEC_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/libexec" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" FORCE ) SET(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/${_APPLICATION_NAME}" CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${_APPLICATION_NAME})" FORCE ) SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix (default prefix/include)" FORCE ) SET(DATA_INSTALL_DIR "${DATA_INSTALL_PREFIX}" CACHE PATH "The parent directory where applications can install their data (default prefix/share/${_APPLICATION_NAME})" FORCE ) SET(HTML_INSTALL_DIR "${DATA_INSTALL_PREFIX}/doc/HTML" CACHE PATH "The HTML install dir for documentation (default data/doc/html)" FORCE ) SET(ICON_INSTALL_DIR "${DATA_INSTALL_PREFIX}/icons" CACHE PATH "The icon install dir (default data/icons/)" FORCE ) SET(SOUND_INSTALL_DIR "${DATA_INSTALL_PREFIX}/sounds" CACHE PATH "The install dir for sound files (default data/sounds)" FORCE ) SET(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale" CACHE PATH "The install dir for translations (default prefix/share/locale)" FORCE ) SET(XDG_APPS_DIR "${SHARE_INSTALL_PREFIX}/applications/" CACHE PATH "The XDG apps dir" FORCE ) SET(XDG_DIRECTORY_DIR "${SHARE_INSTALL_PREFIX}/desktop-directories" CACHE PATH "The XDG directory" FORCE ) SET(SYSCONF_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/etc" CACHE PATH "The ${_APPLICATION_NAME} sysconfig install dir (default prefix/etc)" FORCE ) SET(MAN_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/man" CACHE PATH "The ${_APPLICATION_NAME} man install dir (default prefix/man)" FORCE ) SET(INFO_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/info" CACHE PATH "The ${_APPLICATION_NAME} info install dir (default prefix/info)" FORCE ) endif (UNIX) if (WIN32) # Same same SET(BIN_INSTALL_DIR .) SET(SBIN_INSTALL_DIR .) SET(LIB_INSTALL_DIR .) SET(PLUGIN_INSTALL_DIR plugins) SET(HTML_INSTALL_DIR doc/HTML) SET(ICON_INSTALL_DIR .) SET(SOUND_INSTALL_DIR .) SET(LOCALE_INSTALL_DIR lang) endif (WIN32) garmindev-0.3.4+svn3432/cmake/Modules/MacroCopyFile.cmake0000644000175000017500000000215712002232271021434 0ustar miramira# - macro_copy_file(_src _dst) # Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst} # # Example: # macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.) # Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory # # Copyright (c) 2006-2007 Wengo # Copyright (c) 2006-2008 Andreas Schneider # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING file. macro (macro_copy_file _src _dst) # Removes all path containing .svn or CVS or CMakeLists.txt during the copy if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*") if (CMAKE_VERBOSE_MAKEFILE) message(STATUS "Copy file from ${_src} to ${_dst}") endif (CMAKE_VERBOSE_MAKEFILE) # Creates directory if necessary get_filename_component(_path ${_dst} PATH) file(MAKE_DIRECTORY ${_path}) execute_process( COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst} OUTPUT_QUIET ) endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*") endmacro (macro_copy_file) garmindev-0.3.4+svn3432/cmake/Modules/FindXercesC.cmake0000644000175000017500000000477512002232271021105 0ustar miramira# - Try to find XercesC # Once done this will define # # XERCESC_FOUND - system has XercesC # XERCESC_INCLUDE_DIRS - the XercesC include directory # XERCESC_LIBRARIES - Link these to use XercesC # XERCESC_DEFINITIONS - Compiler switches required for using XercesC # # Copyright (c) 2009 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (XERCESC_LIBRARIES AND XERCESC_INCLUDE_DIRS) # in cache already set(XERCESC_FOUND TRUE) else (XERCESC_LIBRARIES AND XERCESC_INCLUDE_DIRS) find_path(XERCESC_INCLUDE_DIR NAMES xercesc/util/XercesVersion.hpp PATHS /usr/include /usr/local/include /opt/local/include /sw/include C:/progra~1/xerces-c_2_8_0/include ) mark_as_advanced(XERCESC_INCLUDE_DIR) find_library(XERCES-C_LIBRARY NAMES xerces-c xerces-c_2 PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib C:/progra~1/xerces-c_2_8_0/lib ) mark_as_advanced(XERCES-C_LIBRARY) find_library(XERCES-DEPDOM_LIBRARY NAMES xerces-depdom xerces-depdom_2 PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib C:/progra~1/xerces-c_2_8_0/lib ) mark_as_advanced(XERCES-DEPDOM_LIBRARY) if (XERCES-C_LIBRARY) set(XERCES-C_FOUND TRUE) endif (XERCES-C_LIBRARY) if (XERCES-DEPDOM_LIBRARY) set(XERCES-DEPDOM_FOUND TRUE) endif (XERCES-DEPDOM_LIBRARY) set(XERCESC_INCLUDE_DIRS ${XERCESC_INCLUDE_DIR} ) if (XERCES-C_FOUND) set(XERCESC_LIBRARIES ${XERCESC_LIBRARIES} ${XERCES-C_LIBRARY} ) endif (XERCES-C_FOUND) if (XERCES-DEPDOM_FOUND) set(XERCESC_LIBRARIES ${XERCESC_LIBRARIES} ${XERCES-DEPDOM_LIBRARY} ) endif (XERCES-DEPDOM_FOUND) if (XERCESC_INCLUDE_DIRS AND XERCESC_LIBRARIES) set(XERCESC_FOUND TRUE) endif (XERCESC_INCLUDE_DIRS AND XERCESC_LIBRARIES) if (XERCESC_FOUND) if (NOT XercesC_FIND_QUIETLY) message(STATUS "Found XercesC: ${XERCESC_LIBRARIES}") endif (NOT XercesC_FIND_QUIETLY) else (XERCESC_FOUND) if (XercesC_FIND_REQUIRED) message(FATAL_ERROR "Could not find XercesC") endif (XercesC_FIND_REQUIRED) endif (XERCESC_FOUND) # show the XERCESC_INCLUDE_DIRS and XERCESC_LIBRARIES variables only in the advanced view mark_as_advanced(XERCESC_INCLUDE_DIRS XERCESC_LIBRARIES) endif (XERCESC_LIBRARIES AND XERCESC_INCLUDE_DIRS) garmindev-0.3.4+svn3432/cmake/Modules/CMakeLists.txt0000644000175000017500000000155512002232271020477 0ustar miramira# install the cmake files file(GLOB cmakeFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.cmake") set(module_install_dir ${DATA_INSTALL_DIR}/cmake/modules ) install( FILES ${cmakeFiles} DESTINATION ${module_install_dir} ) # the files listed here will be removed by remove_obsoleted_cmake_files.cmake, Alex set(FILES_TO_REMOVE ) install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/remove_files.cmake ) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/remove_files.cmake "#generated by cmake, dont edit\n\n") foreach ( _current_FILE ${FILES_TO_REMOVE}) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/remove_files.cmake "message(STATUS \"Removing ${module_install_dir}/${_current_FILE}\" )\n" ) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/remove_files.cmake "exec_program( ${CMAKE_COMMAND} ARGS -E remove ${module_install_dir}/${_current_FILE} OUTPUT_VARIABLE _dummy)\n" ) endforeach ( _current_FILE) garmindev-0.3.4+svn3432/src/ForeRunner/CDevice.cpp0000644000175000017500000004533012002232271020130 0ustar miramira/********************************************************************************************** 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 "../Platform.h" #include "CDevice.h" #include #include #include #include #include #include using namespace FR305; using namespace Garmin; using namespace std; #if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED) # define DBG_SHOW_WAYPOINT # define UNTESTED throw exce_t(errSync, "This function has not yet been tested on your platform.") #else # define UNTESTED #endif namespace FR305 { 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 = gar_endian(uint16_t, 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 = gar_endian(uint16_t, 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() : devname("Forerunner305") ,devid(0) ,usb(0) ,doRealtimeThread(false) ,skip_if_no_signal(true) { pthread_mutex_init(&dataMutex, NULL); } CDevice::~CDevice() { //if(pScreen) delete [] pScreen; } const string& CDevice::getCopyright() { copyright = "

QLandkarte Device Driver for Garmin " + devname + "

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Oliver Eichler (oliver.eichler@gmx.de)

" "

© Venture HC Screenshot support by Torsten Reuschel (me@fuesika.de)

" "

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.

"; return copyright; } void CDevice::_acquire() { usb = new CUSB(); usb->open(); usb->syncup(); //std::cout<< usb->getProductString()<getProductString().c_str(), devname.c_str(), devname.size()) != 0) { string msg = "No " + devname + " unit detected. Please retry to select other device driver."; //std::cerr<& 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 = gar_endian(uint16_t, 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:" << gar_ptr_load(uint16_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 = gar_endian(uint16_t, 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:" << gar_ptr_load(uint16_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::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 } void CDevice::_uploadWaypoints(std::list& waypoints) { if(usb == 0) return; // count number of proximity waypoints uint16_t prx_wpt_cnt = 0; list::const_iterator wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) ++prx_wpt_cnt; ++wpt; } 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); // transmit proximity waypoints first if(prx_wpt_cnt) { //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, prx_wpt_cnt); usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Prx_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); } ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Prx); usb->write(command); } //transmit _all_ waypoints //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, waypoints.size()); usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Wpt); usb->write(command); } void CDevice::_downloadTracks(std::list& tracks) { tracks.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); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Trk); usb->write(command); int trackidx = 0; string name; Track_t * track = 0; int cancel = 0; int npts = 0; int ntotal = 65535; callback(0,0,&cancel,"Download tracks ...",0); while(!cancel) { if(!usb->read(response)) continue; //read track header if(response.id == Pid_Trk_Hdr) { trackidx = 0; D311_Trk_Hdr_t * hdr = (D311_Trk_Hdr_t*)response.payload; tracks.push_back(Track_t()); track = &tracks.back(); *track << *hdr; name = hdr->ident; } if(response.id == Pid_Records) { ntotal = gar_ptr_load(uint16_t, response.payload); } if(response.id == Pid_Trk_Data) { D304_Trk_t * data = (D304_Trk_t*)response.payload; TrkPt_t pt; pt << *data; if( data->lat==int32_t(2147483647) && data->lon==int32_t(2147483647)) { if(!skip_if_no_signal) track->track.push_back(pt); } else { track->track.push_back(pt); } if (++npts % 100 == 0) { double progress = (npts * 100.0) / ntotal; callback(progress,0,&cancel,0,"Transferring track data."); } } if(response.id == Pid_Xfer_Cmplt) { break; } } if (cancel) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Abort_Transfer); usb->write(command); } callback(100,0,&cancel,0,"done"); } void CDevice::_downloadRoutes(std::list& routes) { routes.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); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Rte); usb->write(command); int routeidx = 0; string name; Route_t * route = 0; int cancel = 0; int npts = 0; int ntotal = 65535; callback(0,0,&cancel,"Download routes ...",0); while(!cancel) { if(!usb->read(response)) continue; if(response.id == Pid_Rte_Hdr) { routeidx = 0; D202_Rte_Hdr_t * hdr = (D202_Rte_Hdr_t*)response.payload; routes.push_back(Route_t()); route = &routes.back(); *route << *hdr; name = hdr->ident; } if(response.id == Pid_Records) { ntotal = gar_ptr_load(uint16_t, response.payload); } if(response.id == Pid_Rte_Wpt_Data) { D110_Wpt_t * p = (D110_Wpt_t*)response.payload; route->route.push_back(RtePt_t()); RtePt_t& rtept = route->route.back(); rtept << *p; if (++npts % 50 == 0) { double progress = (npts * 100.0) / ntotal; callback(progress,0,&cancel,0,"Transferring route data."); } } if(response.id == Pid_Rte_Link_Data) { D210_Rte_Link_t * l = (D210_Rte_Link_t*)response.payload; RtePt_t& rtept = route->route.back(); rtept << *l; } if(response.id == Pid_Xfer_Cmplt) { break; } } if (cancel) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Abort_Transfer); usb->write(command); } callback(100,0,&cancel,0,"done"); } void CDevice::_uploadRoutes(list& routes) { if(usb == 0) return; if(devid == 0x0231) return IDeviceDefault::_uploadRoutes(routes); // count number of proximity waypoints 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); list::const_iterator route = routes.begin(); while(route != routes.end()) { //announce number of records // D202_Rte_Hdr_t + (D110_Wpt_t + D210_Rte_Link_t) * number of route points uint16_t nrec = 1 + route->route.size() * 2; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, nrec); usb->write(command); // write route header command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Hdr; D202_Rte_Hdr_t * r = (D202_Rte_Hdr_t *)command.payload; command.size = *route >> *r; usb->write(command); vector::const_iterator rtept = route->route.begin(); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; while(rtept != route->route.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Link_Data; D210_Rte_Link_t * l = (D210_Rte_Link_t *)command.payload; command.size = *rtept >> *l; usb->write(command); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; } // finish block command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Rte); usb->write(command); ++route; } } void CDevice::_setRealTimeMode(bool on) { CMutexLocker lock(dataMutex); if(doRealtimeThread == on) return; doRealtimeThread = on; if(doRealtimeThread) { pthread_create(&thread,NULL,rtThread, this); } } void CDevice::_getRealTimePos(Garmin::Pvt_t& pvt) { if(pthread_mutex_trylock(&mutex) != EBUSY) { pthread_mutex_unlock(&mutex); throw exce_t(errRuntime,lasterror); } CMutexLocker lock(dataMutex); pvt = PositionVelocityTime; } void CDevice::_release() { if(usb == 0) return; usb->close2(); delete usb; usb = 0; } void CDevice::_getDevProperties(Garmin::DevProperties_t& dev_properties) { if(usb == 0) return; Packet_t command; Packet_t response; // ask for SD Ram capacity command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Mem); usb->write(command); // try to read SD Ram capacity uint32_t memory = 0; uint16_t tile_limit = 0; while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = gar_ptr_load(uint16_t, response.payload + 2); memory = gar_ptr_load(uint32_t, response.payload + 4); } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } garmindev-0.3.4+svn3432/src/ForeRunner/cmake_install.cmake0000644000175000017500000000222612002232271021727 0ustar miramira# Install script for directory: /home/all/PP/usb/GarminDev/src/FR305 # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "1") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) garmindev-0.3.4+svn3432/src/ForeRunner/loader.cpp0000644000175000017500000000405412002232271020072 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace FR305 { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initForerunner305(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(FR305::device == 0) { FR305::device = new FR305::CDevice(); } FR305::device->devname = "Forerunner305"; // FR305::device->screenwidth = 160; // FR305::device->screenheight = 240; return FR305::device; } extern "C" WIN_EXPORT Garmin::IDevice * initForerunner205(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(FR305::device == 0) { FR305::device = new FR305::CDevice(); } FR305::device->devname = "Forerunner205"; // FR305::device->screenwidth = 160; // FR305::device->screenheight = 240; return FR305::device; } garmindev-0.3.4+svn3432/src/ForeRunner/CDevice.h0000644000175000017500000000514212002232271017572 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CDEVICE_H_FR305 #define CDEVICE_H_FR305 #include "IDeviceDefault.h" #include "CUSB.h" namespace FR305 { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); std::string devname; uint32_t devid; const std::string& getCopyright(); private: friend void * rtThread(void *ptr); void _acquire(); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); //void _uploadTracks(std::list& tracks); void _downloadRoutes(std::list& routes); void _uploadRoutes(std::list& routes); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _setRealTimeMode(bool on); void _getRealTimePos(Garmin::Pvt_t& pvt); void _release(); Garmin::CUSB * usb; /// realtime mode thread pthread_t thread; /// mutex to serialize any data access pthread_mutex_t dataMutex; /// keep alive flag for the realtime mode thread bool doRealtimeThread; Garmin::Pvt_t PositionVelocityTime; // Skip Trackpoint if no GPS signal when downloading the tracks bool skip_if_no_signal; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/ForeRunner/CMakeLists.txt0000644000175000017500000000120612002232271020654 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(Forerunner305 SHARED ${SRCS} ${HDRS}) target_link_libraries(Forerunner305 garmin ${LIBUSB_LIBRARIES} pthread) set(ALIASES Forerunner205 ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET Forerunner305 POST_BUILD COMMAND ln ARGS -sf libForerunner305${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/ForeRunner/Makefile0000644000175000017500000002060212002232271017555 0ustar miramira# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canoncical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Produce verbose output by default. VERBOSE = 1 # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/all/PP/usb/GarminDev # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/all/PP/usb/GarminDev #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target install/strip install/strip: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake .PHONY : install/strip # Special rule for the target install/strip install/strip/fast: install/strip .PHONY : install/strip/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/all/PP/usb/GarminDev && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/all/PP/usb/GarminDev && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/all/PP/usb/GarminDev/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # The main all target all: cmake_check_build_system cd /home/all/PP/usb/GarminDev && $(CMAKE_COMMAND) -E cmake_progress_start /home/all/PP/usb/GarminDev/CMakeFiles /home/all/PP/usb/GarminDev/src/FR305/CMakeFiles/progress.marks cd /home/all/PP/usb/GarminDev && $(MAKE) -f CMakeFiles/Makefile2 src/FR305/all $(CMAKE_COMMAND) -E cmake_progress_start /home/all/PP/usb/GarminDev/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/all/PP/usb/GarminDev && $(MAKE) -f CMakeFiles/Makefile2 src/FR305/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/all/PP/usb/GarminDev && $(MAKE) -f CMakeFiles/Makefile2 src/FR305/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/all/PP/usb/GarminDev && $(MAKE) -f CMakeFiles/Makefile2 src/FR305/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/all/PP/usb/GarminDev && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Convenience name for target. src/FR305/CMakeFiles/FR305.dir/rule: cd /home/all/PP/usb/GarminDev && $(MAKE) -f CMakeFiles/Makefile2 src/FR305/CMakeFiles/FR305.dir/rule .PHONY : src/FR305/CMakeFiles/FR305.dir/rule # Convenience name for target. FR305: src/FR305/CMakeFiles/FR305.dir/rule .PHONY : FR305 # fast build rule for target. FR305/fast: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/build .PHONY : FR305/fast CDevice.o: CDevice.cpp.o .PHONY : CDevice.o # target to build an object file CDevice.cpp.o: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/CDevice.cpp.o .PHONY : CDevice.cpp.o CDevice.i: CDevice.cpp.i .PHONY : CDevice.i # target to preprocess a source file CDevice.cpp.i: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/CDevice.cpp.i .PHONY : CDevice.cpp.i CDevice.s: CDevice.cpp.s .PHONY : CDevice.s # target to generate assembly for a file CDevice.cpp.s: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/CDevice.cpp.s .PHONY : CDevice.cpp.s loader.o: loader.cpp.o .PHONY : loader.o # target to build an object file loader.cpp.o: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/loader.cpp.o .PHONY : loader.cpp.o loader.i: loader.cpp.i .PHONY : loader.i # target to preprocess a source file loader.cpp.i: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/loader.cpp.i .PHONY : loader.cpp.i loader.s: loader.cpp.s .PHONY : loader.s # target to generate assembly for a file loader.cpp.s: cd /home/all/PP/usb/GarminDev && $(MAKE) -f src/FR305/CMakeFiles/FR305.dir/build.make src/FR305/CMakeFiles/FR305.dir/loader.cpp.s .PHONY : loader.cpp.s # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... FR305" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... install/strip" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... CDevice.o" @echo "... CDevice.i" @echo "... CDevice.s" @echo "... loader.o" @echo "... loader.i" @echo "... loader.s" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/all/PP/usb/GarminDev && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system garmindev-0.3.4+svn3432/src/Oregon/Oregon.h0000644000175000017500000000473112002232271016670 0ustar miramira/********************************************************************************************** Copyright (C) 2010 Thilo Fromm 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. **********************************************************************************************/ #ifndef OREGON_H #define OREGON_H #include #include #include "IDeviceDefault.h" #include "CUSB.h" #define OREGON_450_DEVID 896 namespace Garmin { class Oregon : public IDeviceDefault { public: Oregon(); virtual ~Oregon(); std::string devname; uint32_t devid; /* public API spec see IDeviceDefault.cpp. */ protected: Garmin::CUSB* usb; void _acquire(); void _usb_syncup(); void _parse_tracks(std::list& tracks, std::list & raw); friend void * _rt_pvt_thread(void * ctx); Pvt_t _rt_pvt_data; pthread_t _rt_pvt_thread_handle; pthread_mutex_t _rt_pvt_thread_mutex; void _downloadTracks(std::list& tracks); void _setRealTimeMode(bool on); void _getRealTimePos(Garmin::Pvt_t& pvt); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _release(); /// the copyright information std::string copyright; /// error message of last error std::string lasterror; /// serial port string std::string port; /// device properties Garmin::DevProperties_t properties; }; } #endif //OREGON_H garmindev-0.3.4+svn3432/src/Oregon/Oregon.txt0000644000175000017500000000716112002232271017260 0ustar miramira qLandkarte plugin for Garmin Oregon (tested on model 450) ========================================================= Thilo Fromm, July 2010 ---------------------- TOC 1. Status 2. Problems 3. Plans Appendix: Oregon 450 "whatGarmin" scan protocol dump ---------------------- 1. Status ######### Some of the (basic) protocols the Oregon supports are documented by Garmin; see . As far as things are documented they will get implemented. Major things, like map upload, or waypoint or route exchange are not documented. Here is what's implemented and working (which isn't much): ---------------------------------------------------------- * The Oregon is recognized and initialised. * Downloading tracks from the device into qLandkarte works. * Real Time PVT data works (aka "Live Log"). 1.1. Connecting the Garmin -------------------------- - Configure the device's USB interface mode to "Garmin Spanner" (Setup->System->Interface on the device) - Connect the device to the computer - Select "No" when the Garmin asks you whether you'd like to go mass storage - fire up qLandkarte - download tracks to the computer !?#@?! If you encounter problems, please report to the qLandkarte mailing list !?#@?! !?#@?! at . !?#@?! 2. Problems ########### A lot of the protocols the Oregon supports are undocumented. The most current Garmin specification dates back to May 2006. 3. Plans ######## In order to fully support the Oregon in qLandkarte the operation semantics of the undocumented protocols need to be reverse engineered. The Oregon should be fully supported by qLandkarte. Appendix ######## Oregon 450 "whatGarmin" scan protocol dump ========================================== Protocol: P0 Protocol: L1 Protocol: A10 <- A 10: Device command protocol #1 Protocol: T1 Protocol: A301 <- A 301: track log transfer protocol Protocol: D312 Protocol: D302 Protocol: A500 <- A 500: Almanac transport protocol Protocol: D501 Protocol: A600 <- A 600: Date and Time initialisation Protocol Protocol: D600 Protocol: A601 <- A 601: ??? Protocol: D601 Protocol: A700 <- A 700: Position initialisation protocol Protocol: D700 Protocol: A800 <- A 800: PVT Protocol: D800 Protocol: A900 <- A 900: ??? Protocol: A902 <- A 902: ??? Protocol: A903 <- A 903: ??? Protocol: A904 <- A 904: ??? Protocol: A905 <- A 905: ??? Protocol: D900 Protocol: A908 <- A 908: ??? Protocol: D911 Protocol: A912 <- A 912: ??? Protocol: D912 Protocol: A913 <- A 913: ??? Protocol: D913 Protocol: A916 <- A 916: ??? Protocol: A917 <- A 917: ??? Protocol: D917 Protocol: A919 <- A 919: ??? Protocol: A1010 <- A 1010: ??? Protocol: A918 <- A 918: ??? Protocol: D918 Product name: Oregon 450 Software Version 3.30 product ID: 896 supports link protocol L001 supports command protocol A010 supports track log transfer protocol A301 with D0=312 D1=302 supports Position/Velocity/Time protocol A800 with D0=800 Product Data End: Oregon 450 Software Version 3.30 Oregon 450 Software Version 3.30 product ID: 896 link protocol L001 command protocol A010 track log protocol A301 D312 D302 PVT protocol A800 D800 garmindev-0.3.4+svn3432/src/Oregon/loader.cpp0000644000175000017500000000366312002232271017243 0ustar miramira/********************************************************************************************** Copyright (C) 2010 Thilo Fromm 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 "config.h" #include "Oregon.h" namespace Garmin { static Oregon * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initOregon(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(Garmin::device == 0) { Garmin::device = new Garmin::Oregon(); } Garmin::device->devname = "Oregon 450"; Garmin::device->devid = OREGON_450_DEVID; return Garmin::device; } extern "C" WIN_EXPORT Garmin::IDevice * initOregon450(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(Garmin::device == 0) { Garmin::device = new Garmin::Oregon(); } Garmin::device->devname = "Oregon 450"; Garmin::device->devid = OREGON_450_DEVID; return Garmin::device; } garmindev-0.3.4+svn3432/src/Oregon/Oregon.cpp0000644000175000017500000001734612002232271017231 0ustar miramira/********************************************************************************************** Copyright (C) 2010 Thilo Fromm 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 "config.h" #include "Oregon.h" #include "CUSB.h" #include #include #include #include #ifdef WIN32 #include #endif #include #define GUSB_DATA_AVAILABLE 2 #define GUSB_SESSION_START 5 #define GUSB_SESSION_STARTED 6 #define USB_INTERRUPT_TIMEOUT 3000 #define USB_BULK_TIMEOUT 30000 using namespace Garmin; using namespace std; namespace Garmin { Oregon::Oregon() : usb(0), devid(0), _rt_pvt_thread_handle(0) { pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&_rt_pvt_thread_mutex, NULL); memset(&_rt_pvt_data, 0x00, sizeof(_rt_pvt_data)); } Oregon::~Oregon() { } /* public API implementation see IDeviceDefault.cpp. */ /* ------------------------------- * private methods * --------------- */ void Oregon::_acquire() { usb = new Garmin::CUSB(); usb->open(); usb->syncup(); if(strncmp(usb->getProductString().c_str(), devname.c_str(), devname.size()) != 0) { string msg = "No " + devname + " unit detected; found \"" + usb->getProductString().c_str() + "\" instead. Please retry to select other device driver."; throw exce_t(errSync,msg); } } /* -- */ void Oregon::_release() { if (!usb) return; usb->close2(); delete usb; usb = 0; } /* -- */ void Oregon::_parse_tracks(std::list& tracks, std::list & raw) { std::list::iterator i; unsigned total = 0, num_tracks = 0; Garmin::Track_t * curr; for (i = raw.begin(); i != raw.end(); i++) { if(i->id == Pid_Records) total = gar_ptr_load(uint16_t, i->payload); if(i->id == Pid_Trk_Hdr) { D312_Trk_Hdr_t * hdr = (D312_Trk_Hdr_t*)i->payload; tracks.push_back(Track_t()); curr = &tracks.back(); *curr << *hdr; } if(i->id == Pid_Trk_Data) { D302_Trk_t * data = (D302_Trk_t*)i->payload; if(data->new_trk) { tracks.push_back(Track_t()); Track_t& new_track = tracks.back(); new_track.color = curr->color; new_track.dspl = curr->dspl; char str[256]; snprintf(str, sizeof(str), "%s_%d", curr->ident.c_str(), num_tracks++); new_track.ident = str; } TrkPt_t pt; pt << *data; curr->track.push_back(pt); if (total && (num_tracks % 50 == 0)) { double progress = (num_tracks * 100.0) / total; callback(progress,0, 0,0,"Transferring tracks."); } } if(i->id == Pid_Xfer_Cmplt) break; } return; } /* -- */ void Oregon::_downloadTracks(std::list& tracks) { if(usb == 0) return; std::list ret; int cancel = 0; // FIXME: Caancel currently does nothing. tracks.clear(); callback(0,0, &cancel, 0,"Transferring tracks."); if (0 > usb->run_app_command(Cmnd_Transfer_Trk, ret) ) throw exce_t(errRead, "Error downloading track data."); _parse_tracks(tracks, ret); callback(100,0, &cancel,0,"done"); } /* -- */ void * _rt_pvt_thread(void * ctx) { Oregon * dev = (Oregon*) ctx; try { CMutexLocker lock(dev->mutex); dev->_acquire(); if (0 > dev->usb->run_app_command(Cmnd_Start_Pvt_Data, 0, 0) ) throw exce_t(errRuntime, "START PVT DATA command to device failed."); while (dev->_rt_pvt_thread_handle == pthread_self()) { Packet_t pvt; if( (0 < dev->usb->read(pvt)) && (pvt.id == Pid_Pvt_Data) ) { dev->_rt_pvt_data << *(D800_Pvt_Data_t*) pvt.payload; cout << "PVT data received." << endl; } } if (0 > dev->usb->run_app_command(Cmnd_Stop_Pvt_Data, 0, 0) ) throw exce_t(errRuntime, "STOP PVT DATA command to device failed."); dev->_release(); } catch(exce_t& e) { dev->lasterror = "Realtime thread failed. " + e.msg; } dev->_rt_pvt_thread_handle = 0; } /* -- */ void Oregon::_setRealTimeMode(bool mode) { CMutexLocker lock2(_rt_pvt_thread_mutex); if (_rt_pvt_thread_handle && !mode) _rt_pvt_thread_handle = 0; else if (!_rt_pvt_thread_handle && mode) { CMutexLocker lock(mutex); _acquire(); // check for device presence. The public IF doesn't do this. _release(); pthread_create(&_rt_pvt_thread_handle, NULL, _rt_pvt_thread, this); } } /* -- */ void Oregon::_getRealTimePos(Garmin::Pvt_t& pvt) { if (ESRCH == pthread_kill(_rt_pvt_thread_handle, 0)) { /* thread already dead */ throw exce_t(errRuntime,lasterror); } pvt = _rt_pvt_data; } /* -- */ void Oregon::_getDevProperties(Garmin::DevProperties_t& dev_properties) { // mark all properties as not having been set to meaningful values properties.set.all = (uint32_t) 0; if(usb == 0) return; Packet_t command; Packet_t response; // ask for SD Ram capacity command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Mem); usb->write(command); // try to read SD Ram capacity uint32_t memory = 0; uint16_t tile_limit = 0; while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = gar_ptr_load(uint16_t, response.payload + 2); memory = gar_ptr_load(uint32_t, response.payload + 4); } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } } garmindev-0.3.4+svn3432/src/Oregon/CMakeLists.txt0000644000175000017500000000114512002232271020022 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp Oregon.cpp ) set(HDRS Oregon.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(Oregon SHARED ${SRCS} ${LIBUSB_LIBRARIES} ${HDRS}) target_link_libraries(Oregon garmin pthread) set(ALIASES Oregon450 ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET Oregon POST_BUILD COMMAND ln ARGS -sf libOregon${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/EtrexH/EHSerial.h0000644000175000017500000000262412002232271017040 0ustar miramira/********************************************************************************************** Copyright (C) 2008 Frank Seidel 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 "CSerial.h" #include #include #include "Garmin.h" #ifndef EHSERIAL_H #define EHSERIAL_H namespace Garmin { class EHSerial : public CSerial { public: EHSerial(const std::string& port); ~EHSerial(); void syncup(void); }; } #endif //EHSERIAL_H garmindev-0.3.4+svn3432/src/EtrexH/CDevice.cpp0000644000175000017500000004407412002232271017246 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Frank Seidel 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 "../Platform.h" #include #include #include #include using namespace EtrexH; using namespace Garmin; using namespace std; #define GARMIN_EH_DFLTBITRATE 9600 #define GARMIN_EH_HIBITRATE 57600 #define CMD_TRANSFER_SCREEN 32 #define PID_SCREENDATA 69 #define PROGR_CALLBACK(state,message) \ callback ( state,0,0,0,message ) #define PROGR_CANCEL_CALLBACK(state,message,cancel) \ callback ( state,0,cancel,0,message ) namespace EtrexH { static const char _clrtbl[1024]= { -127,-127,-127,0,-60,-60,-60,0,90,90,90,0,0,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 }; } CDevice::CDevice(uint16_t id) : serial ( 0 ), pScreen ( 0 ), devId ( 0 ) { if ( id == GARMIN_ETREXEURO ) { copyright = "

QLandkarte Device Driver for Etrex Euro

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Frank Seidel (frank@f-seidel.de)

" "

Info for Etrex Euro support by Martin Ereth (martin.ereth@arcor.de)

" "

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.

"; } else { copyright = "

QLandkarte Device Driver for Etrex H

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Frank Seidel (frank@f-seidel.de)

" "

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.

"; } //set ProductId devId = id; } CDevice::~CDevice() { if ( pScreen ) delete[] pScreen; } void CDevice::_acquire() { int foundProducts = 0; uint16_t myid = 0; #if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED) throw exce_t(errSync, "This device has not yet been ported to your platform."); #endif PROGR_CALLBACK ( 0,"acquiring" ); serial = new EHSerial ( port ); PROGR_CALLBACK ( 1,"acquiring ..."); serial->open(); serial->syncup(); serial->setBitrate(GARMIN_EH_DFLTBITRATE); //ProductID myid = serial->getProductId(); //Etrex H product string if ( strncmp ( serial->getProductString().c_str(), "eTrex H Software", 16 ) == 0 ) { if ( myid == GARMIN_ETREXH && devId == GARMIN_ETREXH ) { foundProducts++; } } //Etrex Euro product string if ( strncmp ( serial->getProductString().c_str(), "eTrex Euro Software", 19 ) == 0 ) { if ( myid == GARMIN_ETREXEURO && devId == GARMIN_ETREXEURO ) { foundProducts++; } } //check if ( foundProducts != 1 ) { PROGR_CALLBACK ( 100,"error occured" ); throw exce_t ( errSync,"Error while probing for eTrex H and eTrex Euro unit detected, according to ProductString and Id. Please retry to select other device driver." ); } } void CDevice::_downloadWaypoints ( list& waypoints ) { waypoints.clear(); if ( serial == 0 ) return; PROGR_CALLBACK ( 2,"Downloading waypoints ..." ); Packet_t command; Packet_t response; unsigned int nwpts = 0; unsigned int cnt = 0; command.id = Pid_Command_Data; command.size = 2; command.payload[0] = Cmnd_Transfer_Wpt; command.payload[1] = 0x00; serial->write ( command ); PROGR_CALLBACK ( 5,"Downloading waypoints ..." ); while ( 1 ) { if ( !serial->read ( response ) ) { cout << "No response from Garmin eTrex H unit. repeating..." << endl; continue; } if ( response.id == Pid_Records ) nwpts = *(uint16_t*)response.payload; 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; ++cnt; if (nwpts) PROGR_CALLBACK ( 5 + ( cnt * 94 / nwpts ),"Downloading waypoints ..." ); } if ( response.id == Pid_Xfer_Cmplt ) break; } PROGR_CALLBACK( 100,"Download complete" ); } void CDevice::_uploadWaypoints ( std::list& waypoints ) { if ( serial == 0 ) return; PROGR_CALLBACK ( 2,"Uploading waypoints ..." ); list::const_iterator wpt = waypoints.begin(); Packet_t command; Packet_t response; unsigned int packcntr = 0; unsigned int npacks = waypoints.size(); //transmit waypoints //announce number of records command.id = Pid_Records; command.size = 2; * ( uint16_t* ) command.payload = waypoints.size(); serial->write ( command ); PROGR_CALLBACK ( 5,"Uploading waypoints ..." ); wpt = waypoints.begin(); while ( wpt != waypoints.end() ) { ++packcntr; command.id = Pid_Wpt_Data; D108_Wpt_t * p = ( D108_Wpt_t * ) command.payload; command.size = *wpt >> *p; serial->write ( command ); ++wpt; if ( npacks ) PROGR_CALLBACK ( 5 + (packcntr * 94 / npacks),"Uploading waypoints ..." ); } //announce number of records command.id = Pid_Xfer_Cmplt; command.size = 2; command.payload[0] = Cmnd_Transfer_Wpt; command.payload[1] = 0x00; serial->write ( command ); PROGR_CALLBACK ( 100,"Upload complete" ); } void CDevice::_downloadTracks ( std::list& tracks ) { tracks.clear(); if ( serial == 0 ) return; PROGR_CALLBACK ( 2,"Downloading tracks ..." ); serial->setBitrate(GARMIN_EH_HIBITRATE); Packet_t command; Packet_t response; unsigned int npacks = 0; unsigned int packcntr = 0; command.id = Pid_Command_Data; command.size = 2; command.payload[0] = Cmnd_Transfer_Trk; command.payload[1] = 0x00; serial->write ( command ); PROGR_CALLBACK ( 3,"Downloading tracks ..." ); int trackidx = 0; string name; Track_t * track = 0; while ( 1 ) { if ( !serial->read ( response ) ) { cout << "No response from Garmin eTrex H unit. repeating..." << endl; continue; } if ( response.id == Pid_Records ) npacks = *(uint16_t*)response.payload; if ( response.id == Pid_Trk_Hdr ) { ++packcntr; 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 ) { ++packcntr; 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[512]; sprintf ( str,"%s_%d",name.c_str(),trackidx++ ); t.ident = str; track = &t; } else { ++trackidx; } } pt << *data; track->track.push_back ( pt ); } if ( npacks ) PROGR_CALLBACK ( 3 + (packcntr * 96 / npacks),"Downloading tracks ..." ); if ( response.id == Pid_Xfer_Cmplt ) break; } serial->setBitrate(GARMIN_EH_DFLTBITRATE); PROGR_CALLBACK ( 100,"Download complete" ); } void CDevice::_uploadRoutes(list& routes) { if (serial == 0) return; int canceled = 0; PROGR_CANCEL_CALLBACK ( 0,"Uploading Routes ...",&canceled ); Packet_t command; Packet_t response; list::const_iterator route = routes.begin(); unsigned int nroutes = routes.size(); unsigned int ncntr = 0; PROGR_CANCEL_CALLBACK ( 1,"Uploading Routes ...",&canceled ); while(route != routes.end() && !canceled) { ++ncntr; //announce number of records uint16_t nrec = route->route.size() * 2; uint16_t recsent = 0; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = nrec; serial->write(command); // write route header command.id = Pid_Rte_Hdr; D202_Rte_Hdr_t * r = (D202_Rte_Hdr_t *)command.payload; command.size = *route >> *r; serial->write(command); ++recsent; vector::const_iterator rtept = route->route.begin(); command.id = Pid_Rte_Wpt_Data; D108_Wpt_t * p = (D108_Wpt_t *)command.payload; command.size = *rtept >> *p; serial->write(command); ++recsent; ++rtept; if ( nroutes && nrec ) PROGR_CANCEL_CALLBACK ( 2+(ncntr-1)*97/nroutes+(recsent*97)/(nrec*nroutes), "Uploading Routes ...", &canceled ); while (rtept != route->route.end() && !canceled) { command.id = Pid_Rte_Link_Data; D210_Rte_Link_t * l = (D210_Rte_Link_t *)command.payload; command.size = *rtept >> *l; serial->write(command); ++recsent; command.id = Pid_Rte_Wpt_Data; D108_Wpt_t * p = (D108_Wpt_t *)command.payload; command.size = *rtept >> *p; serial->write(command); ++recsent; ++rtept; if ( nroutes && nrec ) PROGR_CANCEL_CALLBACK ( 2+(ncntr-1)*97/nroutes+(recsent*97)/(nrec*nroutes), "Uploading Routes ...",&canceled ); } // finish block command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Rte; serial->write(command); ++route; if ( nroutes ) PROGR_CALLBACK ( 2 + ncntr * 97 / nroutes,"Uploading routes ..." ); } PROGR_CANCEL_CALLBACK ( 100,"Uploading routes ...",&canceled ); } void CDevice::_screenshot ( char *& clrtbl, char *& data, int& width, int& height ) { if ( serial == 0 ) return; PROGR_CALLBACK ( 2,"Downloading screenshot ..." ); Packet_t command; Packet_t response; int bperpixel = 0; int pixperpacket = 0; int slines = 0; int swidth = 0; int spackets = 0; long screenbytes = 0; int fetchedpackets = 0; unsigned long rawoffset = 0; char *rawbuffer = NULL; memcpy ( aClrtbl,_clrtbl,sizeof ( aClrtbl ) ); command.id = Pid_Command_Data; command.size = 2; command.payload[0] = CMD_TRANSFER_SCREEN; command.payload[1] = 0x00; serial->write ( command ); PROGR_CALLBACK ( 3,"Downloading screenshot ..." ); //collect data from unit while ( serial->read ( response ) ) { if ( response.id == PID_SCREENDATA ) { if ( response.payload[0] == 0 ) { //get meta-data with payload size 40 bperpixel = response.payload[12]; slines = response.payload[20]; swidth = response.payload[16]; pixperpacket = response.payload[8]; screenbytes = ( bperpixel * swidth * slines ) / 8L; spackets = ( swidth * slines ) / ( pixperpacket * ( 8 / bperpixel ) ); rawbuffer = new char[screenbytes]; if ( rawbuffer == NULL ) { PROGR_CALLBACK ( 100,"error occured" ); throw exce_t ( errSync,"Could not allocate memory for raw display data from unit." ); return; } PROGR_CALLBACK ( 5,"Downloading screenshot ..." ); } else { //get image-data ++fetchedpackets; rawoffset = response.payload[4] + ( response.payload[5] << 8 ) + ( response.payload[6] << 16 ) + ( response.payload[7] << 24 ); memcpy ( rawbuffer + rawoffset, response.payload + 8, pixperpacket ); PROGR_CALLBACK ( 5 + (fetchedpackets * 85 / spackets),"Downloading screenshot ..." ); if ( fetchedpackets == spackets ) break; } } } if ( pScreen ) delete[] pScreen; pScreen = new char[swidth * slines]; //reorder and extract pixel data unsigned long mask = 0x03L; char pcolor = 0; int pX = 63; int pY = 127; for ( int bnum=0; bnum < screenbytes; bnum += ( pixperpacket / 8 ) ) { unsigned long curdat = * ( ( unsigned long* ) ( rawbuffer + bnum ) ); for ( int bitshift = 0; bitshift < pixperpacket; bitshift += bperpixel ) { pcolor = ( ( curdat & mask ) >> bitshift ) & 3; pScreen[pX + ( pY * slines ) ] = pcolor; --pY; if ( pY < 0 ) { --pX; pY = 127; PROGR_CALLBACK ( 90 + ((63 - pX) * 9 / 63),"Processing data ..." ); } mask <<= 2; } mask = 0x03L; } clrtbl = aClrtbl; data = pScreen; width = slines; height = swidth; if ( rawbuffer ) delete[] rawbuffer; PROGR_CALLBACK ( 100,"Completed screenshot" ); } void CDevice::_release() { if ( serial == 0 ) return; serial->close(); delete serial; serial = 0; } garmindev-0.3.4+svn3432/src/EtrexH/loader.cpp0000644000175000017500000000377312002232271017213 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Frank Seidel 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 "config.h" #include "CDevice.h" namespace EtrexH { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initEtrexH(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexH::device == 0) { EtrexH::device = new EtrexH::CDevice(GARMIN_ETREXH); } else { delete EtrexH::device; EtrexH::device = new EtrexH::CDevice(GARMIN_ETREXH); } return EtrexH::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexEuro(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexH::device == 0) { EtrexH::device = new EtrexH::CDevice(GARMIN_ETREXEURO); } else { delete EtrexH::device; EtrexH::device = new EtrexH::CDevice(GARMIN_ETREXEURO); } return EtrexH::device; } garmindev-0.3.4+svn3432/src/EtrexH/CDevice.h0000644000175000017500000000402212002232271016700 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Frank Seidel 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "EHSerial.h" #include "IDeviceDefault.h" #define GARMIN_ETREXH 696 #define GARMIN_ETREXEURO 156 namespace EtrexH { class CDevice : public Garmin::IDeviceDefault { public: CDevice(uint16_t id); virtual ~CDevice(); private: void _acquire(); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); void _uploadRoutes(std::list& routes); void _screenshot(char *& clrtbl, char *& data, int& width, int& height); void _release(); Garmin::EHSerial *serial; char aClrtbl[0x100 * 4]; char *pScreen; //extension for multimodels (first Etrex Euro) uint16_t devId; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/EtrexH/CMakeLists.txt0000644000175000017500000000115712002232271017773 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp EHSerial.cpp ) set(HDRS CDevice.h EHSerial.h ) include_directories(../) add_library(EtrexH SHARED ${SRCS} ${HDRS}) target_link_libraries(EtrexH garmin ${LIBUSB_LIBRARIES} pthread) set(ALIASES EtrexEuro ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET EtrexH POST_BUILD COMMAND ln ARGS -sf libEtrexH${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/EtrexH/EHSerial.cpp0000644000175000017500000000422712002232271017374 0ustar miramira/********************************************************************************************** Copyright (C) 2008 Frank Seidel 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 "EHSerial.h" using namespace Garmin; using namespace std; EHSerial::EHSerial(const std::string& port) : CSerial(port) { } EHSerial::~EHSerial() { EHSerial::close(); } void EHSerial::syncup() { Packet_t command; Packet_t response; static int last_response = 2;//only right for current etrex h int counter = 0; command.type = 0; command.id = Pid_Product_Rqst; command.size = 0; EHSerial::write(command); while(EHSerial::read(response)) { if(response.id == Pid_Product_Data) { Product_Data_t * pData = (Product_Data_t*)response.payload; productId = pData->product_id; softwareVersion = pData->software_version; productString = pData->str; } if(response.id == Pid_Protocol_Array) { Protocol_Data_t * pData = (Protocol_Data_t*)response.payload; for(uint32_t i = 0; i < response.size; i += sizeof(Protocol_Data_t)) { ++pData; } } ++counter; if (last_response && counter == last_response) break; } } garmindev-0.3.4+svn3432/src/whatGarmin/CDevice.cpp0000644000175000017500000001616512002232271020150 0ustar miramira/********************************************************************************************** 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: whatGarmin is a query version that tries to find info about the device and writes it to the terminal screen. This assumes that the connected unit is a Garmin one and that the basic USB syncup can be achieved. Tell the user to download waypoints to use this, then turn off the unit. LvD: EOT **********************************************************************************************/ #include "../Platform.h" #include "CDevice.h" #include #include #include #include #include using namespace whatGarmin; using namespace Garmin; using namespace std; CDevice::CDevice() : usb(0) { copyright = "

QLandkarte Dummy Device Driver whatGarmin

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Oliver Eichler (oliver.eichler@gmx.de)

" "

© 2007 by Leon van Dommelen (dommelen@eng.fsu.edu)

" "

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.

"; } CDevice::~CDevice() { } void CDevice::_acquire() { // activate the driver usb = new CUSB(); usb->open(); usb->syncup(); // product data ostringstream note; // output the product name cout << "Product name: " << usb->getProductString().c_str() << endl; note << "\n\n" << usb->getProductString().c_str(); // output the product ID cout << " product ID: " << usb->getProductId(); note << "\nproduct ID: " << usb->getProductId(); // See what protocols are there // link protocol if (usb->getDataType(-1,'L',(uint16_t)1)) { cout << " supports link protocol L001" << endl; note << "\nlink protocol L001"; } if (usb->getDataType(-1,'L',(uint16_t)2)) { cout << " supports link protocol L002" << endl; note << "\nlink protocol L002"; } // command protocol if (usb->getDataType(-1,'A',(uint16_t)10)) { cout << " supports command protocol A010" << endl; note << "\ncommand protocol A010"; } if (usb->getDataType(-1,'A',(uint16_t)11)) { cout << " supports command protocol A011" << endl; note << "\ncommand protocol A011"; } // waypoint transfer protocol if (usb->getDataType(0,'A',(uint16_t)100)) { cout << " supports waypoint transfer protocol A100 with D0=" << usb->getDataType(0,'A',(uint16_t)100) << endl; note << "\nwaypoint protocol A100 D" << usb->getDataType(0,'A',(uint16_t)100); } if (usb->getDataType(0,'A',(uint16_t)101)) { cout << " supports waypoint transfer protocol A101 with D0=" << usb->getDataType(0,'A',(uint16_t)101) << endl; note << "\nwaypoint protocol A101 D" << usb->getDataType(0,'A',(uint16_t)101); } // proximity waypoint transfer protocol if (usb->getDataType(0,'A',(uint16_t)400)) { cout << " supports proximity waypoint transfer protocol A400 with D0=" << usb->getDataType(0,'A',(uint16_t)400) << endl; note << "\nproximity waypoint protocol A400 D" << usb->getDataType(0,'A',(uint16_t)400); } // track log transfer protocol if (usb->getDataType(0,'A',(uint16_t)300)) { cout << " supports track log transfer protocol A300 with D0=" << usb->getDataType(0,'A',(uint16_t)300) << endl; note << "\ntrack log protocol A300 D" << usb->getDataType(0,'A',(uint16_t)300); } if (usb->getDataType(0,'A',(uint16_t)301)) { cout << " supports track log transfer protocol A301 with D0=" << usb->getDataType(0,'A',(uint16_t)301) << " D1=" << usb->getDataType(1,'A',(uint16_t)301) << endl; note << "\ntrack log protocol A301 D" << usb->getDataType(0,'A',(uint16_t)301) << " D" << usb->getDataType(1,'A',(uint16_t)301); } if (usb->getDataType(0,'A',(uint16_t)302)) { cout << " supports track log transfer protocol A302 with D0=" << usb->getDataType(0,'A',(uint16_t)302) << " D1=" << usb->getDataType(1,'A',(uint16_t)302) << endl; note << "\ntrack log protocol A302 D" << usb->getDataType(0,'A',(uint16_t)302) << " D" << usb->getDataType(1,'A',(uint16_t)302); } // route transfer protocol if (usb->getDataType(0,'A',(uint16_t)200)) { cout << " supports route transfer protocol A200 with D0=" << usb->getDataType(0,'A',(uint16_t)200) << " D1=" << usb->getDataType(1,'A',(uint16_t)200) << endl; note << "\nroute protocol A200 D" << usb->getDataType(0,'A',(uint16_t)200) << " D" << usb->getDataType(1,'A',(uint16_t)200); } if (usb->getDataType(0,'A',(uint16_t)201)) { cout << " supports route transfer protocol A201 with D0=" << usb->getDataType(0,'A',(uint16_t)201) << " D1=" << usb->getDataType(1,'A',(uint16_t)201) << " D2=" << usb->getDataType(2,'A',(uint16_t)201) << endl; note << "\nroute protocol A201 D" << usb->getDataType(0,'A',(uint16_t)201) << " D" << usb->getDataType(1,'A',(uint16_t)201) << " D" << usb->getDataType(2,'A',(uint16_t)201); } // PVT protocol if (usb->getDataType(0,'A',(uint16_t)800)) { cout << " supports Position/Velocity/Time protocol A800 with D0=" << usb->getDataType(0,'A',(uint16_t)800) << endl; note << "\nPVT protocol A800 D" << usb->getDataType(0,'A',(uint16_t)800); } // end of data cout << "Product Data End: " << usb->getProductString().c_str() << endl; // abort any action cout << note.str() << endl; throw exce_t(errSync,note.str()); } void CDevice::_getDevProperties(Garmin::DevProperties_t& /*dev_properties*/) { throw exce_t(errSync,"This method is not implemented for whatGarmin."); } void CDevice::_release() { if(usb == 0) return; // close by resetting device usb->close2(); delete usb; usb = 0; } const std::string& CDevice::getCopyright() { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Protocol dump: " + e.msg; throw (int)e.err; } return copyright; } garmindev-0.3.4+svn3432/src/whatGarmin/loader.cpp0000644000175000017500000000265412002232271020112 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace whatGarmin { static CDevice * device = 0; } extern "C" Garmin::IDevice * initwhatGarmin(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(whatGarmin::device == 0) { whatGarmin::device = new whatGarmin::CDevice(); } return whatGarmin::device; } garmindev-0.3.4+svn3432/src/whatGarmin/CDevice.h0000644000175000017500000000310212002232271017600 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "IDeviceDefault.h" #include "CUSB.h" namespace whatGarmin { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); const std::string& getCopyright(); private: void _acquire(); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _release(); Garmin::CUSB * usb; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/whatGarmin/CMakeLists.txt0000644000175000017500000000041412002232271020670 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(whatGarmin SHARED ${SRCS} ${HDRS}) target_link_libraries(whatGarmin garmin ${LIBUSB_LIBRARIES} pthread) garmindev-0.3.4+svn3432/src/GPSMap76/CDevice.cpp0000644000175000017500000005316112002232271017310 0ustar miramira/********************************************************************************************** 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 "../Platform.h" #include "CDevice.h" #include #include #include #include using namespace GPSMap76; using namespace Garmin; using namespace std; #define MAP_UPLOAD_BITRATE 115200// or 57600, 38400, 19200, 9600 #define WAYPOINT_DL_BITRATE 57600 #define TRACK_DL_BITRATE 57600 #define GRMN_DEFAULT_BITRATE 9600 #define PROGR_CALLBACK(state,message) \ callback ( state,0,0,0,message ) #define PROGR_CANCEL_CALLBACK(state,message,cancel) \ callback ( state,0,cancel,0,message ) CDevice::CDevice() : serial(0) { } CDevice::~CDevice() { } const string& CDevice::getCopyright() { copyright = "

QLandkarte Device Driver for GPSMap76 (EXPERIMENTAL)

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Oliver Eichler (oliver.eichler@gmx.de)

" "

modified 2008 by Andreas Stenglein to work with serial GPSMap76

" "

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.

"; return copyright; } void CDevice::_acquire() { #if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED) throw exce_t(errSync, "This device has not yet been ported to your platform."); #endif PROGR_CALLBACK ( 0,"acquiring" ); serial = new CSerial(port); PROGR_CALLBACK ( 1,"acquiring ..."); 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*/) { if(serial == 0) return; int ready= 0; int cancel = 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); // FIXME: while(serial->read(response) > 0) { 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 enough memory (available/needed): " << memory << "/" << size << " bytes"; throw exce_t(errBlocked,msg.str()); } } } #ifdef EXPERIMENTAL // 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); // FIXME: while(serial->read(response) > 0 ) { if(response.id == Pid_Ack_Unlock_key) { //TODO read data } } } #endif 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; serial->readTimeout( 5000); while(!ready && serial->read(response) > 0) { if(response.id == 74) { ready= 1; //TODO read data } } serial->readTimeout( 1000); callback(0,0,&cancel,"Upload maps ...",0); 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 && !cancel) { 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); // set progress double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.id = 45; command.size = 2; *(uint16_t*)command.payload = 0x000A; serial->write(command); } void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key) { if(serial == 0) return; Packet_t command; Packet_t response; int cancel = 0; int ready= 0; // ??? 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) { 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 enough memory (available/needed): " << memory << "/" << size << " bytes"; throw exce_t(errRuntime,msg.str()); } } } #ifdef EXPERIMENTAL // 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) { if(response.id == Pid_Ack_Unlock_key) { //TODO read data } } } #endif 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; serial->readTimeout( 5000); while(!ready && serial->read(response) > 0) { if(response.id == 74) { ready = 1; //TODO read data } } serial->readTimeout( 1000); callback(0,0,&cancel,"Upload maps ...",0); FILE *fid = fopen(filename,"r"); if(fid == NULL) { stringstream msg; msg << "Failed to send map: Can't open " << filename; throw exce_t(errRuntime,msg.str()); } uint32_t total = size; uint32_t offset = 0, chunkSize; uint8_t buffer[GUSB_PAYLOAD_SIZE - sizeof(offset)]; size_t chunks_read; 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 && !cancel) { chunkSize = (size < (254 - sizeof(offset))) ? size : (254 - sizeof(offset)); command.size = chunkSize + sizeof(offset); chunks_read = fread(buffer, chunkSize, 1, fid); if (chunks_read != 1) { stringstream msg; msg << "Failed to read chunk from map " << filename; throw exce_t(errRuntime,msg.str()); } *(uint32_t*)command.payload = offset; memcpy(command.payload + sizeof(offset),buffer,chunkSize); size -= chunkSize; offset += chunkSize; serial->write(command); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.id = 45; command.size = 2; *(uint16_t*)command.payload = 0x000A; serial->write(command); } void CDevice::_queryMap(std::list& 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& waypoints) { waypoints.clear(); if(serial == 0) return; PROGR_CALLBACK ( 2,"Downloading waypoints ..." ); Packet_t command; Packet_t response; unsigned int nwpts = 0; unsigned int cnt = 0; // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( WAYPOINT_DL_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif // request waypoints command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; serial->write(command); PROGR_CALLBACK ( 5,"Downloading waypoints ..." ); while(1) { if(!serial->read(response)) continue; if(response.id == Pid_Records) { nwpts = *(uint16_t*)response.payload; #ifdef DBG_SHOW_WAYPOINT cout << "number of waypoints:" << *(int16_t*)response.payload << endl; #endif } if(response.id == Pid_Wpt_Data) { D109_Wpt_t * srcWpt = (D109_Wpt_t*)response.payload; waypoints.push_back(Wpt_t()); Wpt_t& tarWpt = waypoints.back(); tarWpt << *srcWpt; ++cnt; if (nwpts) PROGR_CALLBACK ( 5 + ( cnt * 94 / nwpts ),"Downloading waypoints ..." ); } 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) { D109_Wpt_t * srcWpt = (D109_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::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 #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK( 100,"Download complete" ); } void CDevice::_uploadWaypoints(std::list& waypoints) { if(serial == 0) return; PROGR_CALLBACK ( 2,"Uploading waypoints ..." ); uint16_t prx_wpt_cnt = 0; list::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; unsigned int packcntr = 0; unsigned int npacks = waypoints.size(); // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( WAYPOINT_DL_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif // 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; D109_Wpt_t * p = (D109_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); PROGR_CALLBACK ( 5,"Uploading waypoints ..." ); wpt = waypoints.begin(); while(wpt != waypoints.end()) { ++packcntr; command.id = Pid_Wpt_Data; D109_Wpt_t * p = (D109_Wpt_t *)command.payload; command.size = *wpt >> *p; serial->write(command); ++wpt; if ( npacks ) PROGR_CALLBACK ( 5 + (packcntr * 94 / npacks),"Uploading waypoints ..." ); } //announce number of records command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK ( 100,"Upload complete" ); } void CDevice::_downloadTracks(std::list& tracks) { tracks.clear(); if(serial == 0) return; PROGR_CALLBACK ( 2,"Downloading tracks ..." ); Packet_t command; Packet_t response; unsigned int npacks = 0; unsigned int packcntr = 0; // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( TRACK_DL_BITRATE)) { throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second"); } #endif command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Trk; serial->write(command); PROGR_CALLBACK ( 3,"Downloading tracks ..." ); int trackidx = 0; string name; Track_t * track = 0; while(1) { if(!serial->read(response)) continue; if ( response.id == Pid_Records ) npacks = *(uint16_t*)response.payload; if(response.id == Pid_Trk_Hdr) { ++packcntr; 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) { ++packcntr; 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 ( npacks ) PROGR_CALLBACK ( 3 + (packcntr * 96 / npacks),"Downloading tracks ..." ); if(response.id == Pid_Xfer_Cmplt) { break; } } #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK ( 100,"Download complete" ); } void CDevice::_release() { if(serial == 0) return; serial->close(); delete serial; serial = 0; } // just copied from GPSMAP60CSX driver, 20081006 void CDevice::_getDevProperties(Garmin::DevProperties_t& dev_properties) { if(serial == 0) return; Packet_t command; Packet_t response; // ask for SD Ram capacity command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Mem; serial->write(command); // try to read SD Ram capacity uint32_t memory = 0; uint16_t tile_limit = 0; while(serial->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = ((uint16_t*)response.payload)[1]; memory = ((uint32_t*)response.payload)[1]; } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } garmindev-0.3.4+svn3432/src/GPSMap76/loader.cpp0000644000175000017500000000443212002232271017251 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace GPSMap76 { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap76::device == 0) { GPSMap76::device = new GPSMap76::CDevice(); } GPSMap76::device->devname = "GPSMAP 76"; GPSMap76::device->devid = 439; return GPSMap76::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76S(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap76::device == 0) { GPSMap76::device = new GPSMap76::CDevice(); } GPSMap76::device->devname = "GPSMAP 76S"; GPSMap76::device->devid = 194; return GPSMap76::device; } extern "C" WIN_EXPORT Garmin::IDevice * initRino120(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap76::device == 0) { GPSMap76::device = new GPSMap76::CDevice(); } GPSMap76::device->devname = "Rino 120"; GPSMap76::device->devid = 264; return GPSMap76::device; } garmindev-0.3.4+svn3432/src/GPSMap76/CDevice.h0000644000175000017500000000411012002232271016743 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "IDeviceDefault.h" #include "CSerial.h" namespace GPSMap76 { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); std::string devname; uint32_t devid; const std::string& getCopyright(); private: void _acquire(); void _uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); void _uploadMap(const char * filename, uint32_t size, const char * key); void _queryMap(std::list& maps); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _release(); Garmin::CSerial * serial; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/GPSMap76/CMakeLists.txt0000644000175000017500000000112012002232271020026 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../) add_library(GPSMap76 SHARED ${SRCS} ${HDRS}) target_link_libraries(GPSMap76 garmin pthread) set(ALIASES GPSMap76S Rino120 ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET GPSMap76 POST_BUILD COMMAND ln ARGS -sf libGPSMap76${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/EtrexLegend/CDevice.cpp0000644000175000017500000005327512002232271020260 0ustar miramira/********************************************************************************************** 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 "../Platform.h" #include "CDevice.h" #include #include #include #include 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 9600 #define PROGR_CALLBACK(state,message) \ callback ( state,0,0,0,message ) #define PROGR_CANCEL_CALLBACK(state,message,cancel) \ callback ( state,0,cancel,0,message ) CDevice::CDevice() : serial(0) { supportsMaps = true; } CDevice::~CDevice() { } const string& CDevice::getCopyright() { copyright = "

QLandkarte Device Driver for EtrexLegend (EXPERIMENTAL)

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Oliver Eichler (oliver.eichler@gmx.de)

" "

modified 2007 by Andreas Stenglein to work with serial eTrex Legend

" "

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.

"; return copyright; } void CDevice::_acquire() { #if defined(WORDS_BIGENDIAN) || !defined(CAN_UNALIGNED) throw exce_t(errSync, "This device has not yet been ported to your platform."); #endif PROGR_CALLBACK ( 0,"acquiring" ); serial = new CSerial(port); PROGR_CALLBACK ( 1,"acquiring ..."); 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); } } void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * key) { if(supportsMaps == false) { IDeviceDefault::_uploadMap(mapdata, size, key); return; } if(serial == 0) return; int ready= 0; int cancel = 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); // FIXME: while(serial->read(response) > 0) { 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 enough memory (available/needed): " << memory << "/" << size << " bytes"; throw exce_t(errBlocked,msg.str()); } } } #ifdef EXPERIMENTAL // 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); // FIXME: while(serial->read(response) > 0 ) { if(response.id == Pid_Ack_Unlock_key) { //TODO read data } } } #endif 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; serial->readTimeout( 5000); while(!ready && serial->read(response) > 0) { if(response.id == 74) { ready= 1; //TODO read data } } serial->readTimeout( 1000); callback(0,0,&cancel,"Upload maps ...",0); 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 && !cancel) { 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); // set progress double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.id = 45; command.size = 2; *(uint16_t*)command.payload = 0x000A; serial->write(command); } void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key) { if(supportsMaps == false) { IDeviceDefault::_uploadMap( filename, size, key); return; } if(serial == 0) return; Packet_t command; Packet_t response; int cancel = 0; int ready= 0; // ??? 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) { 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 enough memory (available/needed): " << memory << "/" << size << " bytes"; throw exce_t(errRuntime,msg.str()); } } } #ifdef EXPERIMENTAL // 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) { if(response.id == Pid_Ack_Unlock_key) { //TODO read data } } } #endif 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; serial->readTimeout( 5000); while(!ready && serial->read(response) > 0) { if(response.id == 74) { ready = 1; //TODO read data } } serial->readTimeout( 1000); callback(0,0,&cancel,"Upload maps ...",0); FILE *fid = fopen(filename,"r"); if(fid == NULL) { stringstream msg; msg << "Failed to send map: Can't open " << filename; throw exce_t(errRuntime,msg.str()); } uint32_t total = size; uint32_t offset = 0, chunkSize; uint8_t buffer[GUSB_PAYLOAD_SIZE - sizeof(offset)]; size_t chunks_read; 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 && !cancel) { chunkSize = (size < (254 - sizeof(offset))) ? size : (254 - sizeof(offset)); command.size = chunkSize + sizeof(offset); chunks_read = fread(buffer, chunkSize, 1, fid); if (chunks_read != 1) { stringstream msg; msg << "Failed to read chunk from map " << filename; throw exce_t(errRuntime,msg.str()); } *(uint32_t*)command.payload = offset; memcpy(command.payload + sizeof(offset),buffer,chunkSize); size -= chunkSize; offset += chunkSize; serial->write(command); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.id = 45; command.size = 2; *(uint16_t*)command.payload = 0x000A; serial->write(command); } void CDevice::_queryMap(std::list& maps) { maps.clear(); if(supportsMaps == false) { IDeviceDefault::_queryMap(maps); return; } 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& waypoints) { waypoints.clear(); if(serial == 0) return; PROGR_CALLBACK ( 2,"Downloading waypoints ..." ); Packet_t command; Packet_t response; unsigned int nwpts = 0; unsigned int cnt = 0; // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( WAYPOINT_DL_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif // request waypoints command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; serial->write(command); PROGR_CALLBACK ( 5,"Downloading waypoints ..." ); while(1) { if(!serial->read(response)) continue; if(response.id == Pid_Records) { nwpts = *(uint16_t*)response.payload; #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; ++cnt; if (nwpts) PROGR_CALLBACK ( 5 + ( cnt * 94 / nwpts ),"Downloading waypoints ..." ); } if(response.id == Pid_Xfer_Cmplt) { break; } } #if 0 // etrex Legend doesn't have a beeper // unsupported by etrex Legend ? // 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::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 #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK( 100,"Download complete" ); } void CDevice::_uploadWaypoints(std::list& waypoints) { if(serial == 0) return; PROGR_CALLBACK ( 2,"Uploading waypoints ..." ); // uint16_t prx_wpt_cnt = 0; list::const_iterator wpt = waypoints.begin(); // does etrex Legend support prx waypoints? while(wpt != waypoints.end()) { #if 0 if(wpt->dist != 1e25f) ++prx_wpt_cnt; #endif ++wpt; } Packet_t command; Packet_t response; unsigned int packcntr = 0; unsigned int npacks = waypoints.size(); // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( WAYPOINT_DL_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif #if 0 // 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); } #endif //transmit _all_ waypoints //announce number of records command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = waypoints.size(); serial->write(command); PROGR_CALLBACK ( 5,"Uploading waypoints ..." ); wpt = waypoints.begin(); while(wpt != waypoints.end()) { ++packcntr; command.id = Pid_Wpt_Data; D108_Wpt_t * p = (D108_Wpt_t *)command.payload; command.size = *wpt >> *p; serial->write(command); ++wpt; if ( npacks ) PROGR_CALLBACK ( 5 + (packcntr * 94 / npacks),"Uploading waypoints ..." ); } //announce number of records command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked,"Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK ( 100,"Upload complete" ); } void CDevice::_downloadTracks(std::list& tracks) { tracks.clear(); if(serial == 0) return; PROGR_CALLBACK ( 2,"Downloading tracks ..." ); Packet_t command; Packet_t response; unsigned int npacks = 0; unsigned int packcntr = 0; // ??? command.id = 0x1C; command.size = 2; *(uint16_t*)command.payload = 0x0000; serial->write(command); #ifdef EXPERIMENTAL if (serial->setBitrate( TRACK_DL_BITRATE)) { throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second"); } #endif command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Trk; serial->write(command); PROGR_CALLBACK ( 3,"Downloading tracks ..." ); int trackidx = 0; string name; Track_t * track = 0; while(1) { if(!serial->read(response)) continue; if ( response.id == Pid_Records ) npacks = *(uint16_t*)response.payload; if(response.id == Pid_Trk_Hdr) { ++packcntr; 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) { ++packcntr; 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 ( npacks ) PROGR_CALLBACK ( 3 + (packcntr * 96 / npacks),"Downloading tracks ..." ); if(response.id == Pid_Xfer_Cmplt) { break; } } #ifdef EXPERIMENTAL if (serial->setBitrate( GRMN_DEFAULT_BITRATE)) { throw exce_t(errBlocked, "Failed to change serial link to xxx bit per second"); } #endif PROGR_CALLBACK ( 100,"Download complete" ); } void CDevice::_release() { if(serial == 0) return; serial->close(); delete serial; serial = 0; } // just copied from GPSMAP60CSX driver, 20081006 void CDevice::_getDevProperties(Garmin::DevProperties_t& dev_properties) { if(serial == 0) return; Packet_t command; Packet_t response; // ask for SD Ram capacity command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Mem; serial->write(command); // try to read SD Ram capacity uint32_t memory = 0; uint16_t tile_limit = 0; while(serial->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = ((uint16_t*)response.payload)[1]; memory = ((uint32_t*)response.payload)[1]; } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } garmindev-0.3.4+svn3432/src/EtrexLegend/loader.cpp0000644000175000017500000000543612002232271020220 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace EtrexLegend { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegend(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegend::device == 0) { EtrexLegend::device = new EtrexLegend::CDevice(); } EtrexLegend::device->devname = "eTrex Legend"; EtrexLegend::device->devid = 411; return EtrexLegend::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVista(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegend::device == 0) { EtrexLegend::device = new EtrexLegend::CDevice(); } EtrexLegend::device->devname = "eTrex Vista"; EtrexLegend::device->devid = 169; return EtrexLegend::device; } // I went back-and-forth on where to put the eTrex Classic // (https://buy.garmin.com/shop/shop.do?cID=167&pID=6403). Visually, // and feature capabilities, it is probably close to the eTrex H. However, // 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" WIN_EXPORT Garmin::IDevice * const initEtrexClassic(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegend::device == 0) { EtrexLegend::device = new EtrexLegend::CDevice(); } EtrexLegend::device->devname = "eTrex"; EtrexLegend::device->devid = 130; EtrexLegend::device->supportsMaps = false; return EtrexLegend::device; } garmindev-0.3.4+svn3432/src/EtrexLegend/CDevice.h0000644000175000017500000000423412002232271017714 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "IDeviceDefault.h" #include "CSerial.h" namespace EtrexLegend { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); std::string devname; uint32_t devid; bool supportsMaps; // Does this device support map upload/download const std::string& getCopyright(); private: void _acquire(); void _uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); void _uploadMap(const char * filename, uint32_t size, const char * key); void _queryMap(std::list& maps); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _release(); Garmin::CSerial * serial; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/EtrexLegend/CMakeLists.txt0000644000175000017500000000121512002232271020775 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(EtrexLegend SHARED ${SRCS} ${HDRS}) target_link_libraries(EtrexLegend garmin ${LIBUSB_LIBRARIES} pthread) set(ALIASES EtrexVista EtrexClassic ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET EtrexLegend POST_BUILD COMMAND ln ARGS -sf libEtrexLegend${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/EtrexLegendC/CDevice.cpp0000644000175000017500000007720112002232272020357 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de bzrudi (bzrudi@users.sourceforge.net) 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 "../Platform.h" #include "CDevice.h" #include #include #include #include #include #include using namespace EtrexLegendC; using namespace Garmin; using namespace std; namespace EtrexLegendC { 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) { pthread_mutex_init(&dataMutex, NULL); } CDevice::~CDevice() { } const string& CDevice::getCopyright() { copyright = "

QLandkarte Device Driver for Garmin " + devname + "

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by bzrudi (bzrudi@users.sourceforge.net)

" "

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.

"; return copyright; } void CDevice::_acquire() { #if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED) throw exce_t(errSync, "This device has not yet been ported to your platform."); #endif usb = new CUSB(); usb->open(); /** Workaround for faulty Etrex Legend C session start. Needs to be called 3 times. Please refer to GPSBabel gusb_reset_toggles() function in gpslibusb.c. **/ 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); /** Now we call syncup() which takes care of the third try in session start **/ 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); } } void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * key) { if(usb == 0) return; Packet_t command; Packet_t response; int cancel = 0; // ??? 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); 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 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); while(usb->read(response)) { if(response.id == 74) { //TODO read data } } callback(0,0,&cancel,"Upload maps ...",0); 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 && !cancel) { 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); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // 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::_uploadMap(const char * filename, uint32_t size, const char * key) { if(usb == 0) return; Packet_t command; Packet_t response; int cancel = 0; // ??? 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); 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 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); while(usb->read(response)) { if(response.id == 74) { //TODO read data } } callback(0,0,&cancel,"Upload maps ...",0); FILE *fid = fopen(filename,"r"); if(fid == NULL) { stringstream msg; msg << "Failed to send map: Can't open " << filename; throw exce_t(errRuntime,msg.str()); } uint32_t total = size; uint32_t offset = 0, chunkSize; uint8_t buffer[GUSB_PAYLOAD_SIZE - sizeof(offset)]; size_t chunks_read; command.type = GUSB_APPLICATION_LAYER; command.id = 36; // transfer file by chunks of 0x1000 - 0x0000C - sizeof(offset) = 0x0FF0 bytes while(size && !cancel) { chunkSize = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - sizeof(offset)); command.size = chunkSize + sizeof(offset); chunks_read = fread(buffer, chunkSize, 1, fid); if (chunks_read != 1) { stringstream msg; msg << "Failed to read chunk from map " << filename; throw exce_t(errRuntime,msg.str()); } *(uint32_t*)command.payload = offset; memcpy(command.payload + sizeof(offset),buffer,chunkSize); size -= chunkSize; offset += chunkSize; usb->write(command); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transfering map data."); } callback(100,0,&cancel,0,"done"); // 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& 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); 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); } void CDevice::_downloadWaypoints(list& 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) { D109_Wpt_t * srcWpt = (D109_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) { D109_Wpt_t * srcWpt = (D109_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::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 } void CDevice::_uploadWaypoints(std::list& waypoints) { if(usb == 0) return; // count number of proximity waypoints uint16_t prx_wpt_cnt = 0; list::const_iterator wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) ++prx_wpt_cnt; ++wpt; } 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); // transmit proximity waypoints first if(prx_wpt_cnt) { //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = prx_wpt_cnt; usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Prx_Wpt_Data; D109_Wpt_t * p = (D109_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); } ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Prx; usb->write(command); } //transmit _all_ waypoints //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = waypoints.size(); usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Wpt_Data; D109_Wpt_t * p = (D109_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Wpt; usb->write(command); } void CDevice::_downloadTracks(std::list& tracks) { tracks.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); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Trk; usb->write(command); int trackidx = 0; string name; Track_t * track = 0; while(1) { if(!usb->read(response)) continue; if(response.id == Pid_Trk_Hdr) { trackidx = 0; D312_Trk_Hdr_t * hdr = (D312_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; } } } void CDevice::_uploadRoutes(list& routes) { if(usb == 0) return; // count number of proximity waypoints 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); list::const_iterator route = routes.begin(); while(route != routes.end()) { //announce number of records // D202_Rte_Hdr_t + (D110_Wpt_t + D210_Tre_Link_t) * number of route points uint16_t nrec = 1 + route->route.size() * 2; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = nrec; usb->write(command); // write route header command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Hdr; D202_Rte_Hdr_t * r = (D202_Rte_Hdr_t *)command.payload; command.size = *route >> *r; usb->write(command); vector::const_iterator rtept = route->route.begin(); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D109_Wpt_t * p = (D109_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; while(rtept != route->route.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Link_Data; D210_Rte_Link_t * l = (D210_Rte_Link_t *)command.payload; command.size = *rtept >> *l; usb->write(command); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D109_Wpt_t * p = (D109_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; } // finish block command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = Cmnd_Transfer_Rte; usb->write(command); ++route; } } void CDevice::_uploadCustomIcons(list& icons) { 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); list::const_iterator icon = icons.begin(); while(icon != icons.end()) { uint32_t tan = 0; // get tan command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Icon_Id; command.size = 2; *(uint16_t*)command.payload = icon->idx + 1; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Id) { tan = *(uint32_t*)response.payload; } } // request color table command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Clr_Tbl; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Clr_Tbl) { // send back color table command = response; } } usb->write(command); while(usb->read(response)) { if(response.id == Pid_Req_Clr_Tbl) { // TODO: ignore? } } // send icon data command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Icon_Data; command.size = 0x104; *(uint32_t*)command.payload = tan; memcpy(command.payload + sizeof(tan),icon->data,sizeof(icon->data)); usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Data) { // TODO: ignore? } } ++icon; } } void CDevice::_screenshot(char *& clrtbl, char *& data, int& width, int& height) { 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); uint32_t tan = 0; // get tan command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Icon_Id; command.size = 2; *(uint16_t*)command.payload = 0; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Id) { tan = *(uint32_t*)response.payload; } } // request color table command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Clr_Tbl; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Clr_Tbl) { // send back color table memcpy(aClrtbl,_clrtbl,sizeof(aClrtbl)); command = response; } } usb->write(command); while(usb->read(response)) { if(response.id == Pid_Req_Clr_Tbl) { // TODO: ignore? } } char buffer[SCREEN_WIDTH * SCREEN_HEIGHT]; char * pData = buffer; uint32_t byteCnt; uint32_t byteCntTotal = 0; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Ack_Icon_Data; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); // loop will end after reception of Pid_Icon_Data with length of 4 (tan only) // or too much data while(1) { if(!usb->read(response)) { usb->write(command); continue; } if(response.id == Pid_Icon_Data) { if(response.size == sizeof(tan)) break; byteCnt = response.size - sizeof(tan); memcpy(pData,response.payload + sizeof(tan), byteCnt); pData += byteCnt; byteCntTotal += byteCnt; if(byteCntTotal > sizeof(buffer)) break; } } command.type = GUSB_APPLICATION_LAYER; command.id = 0x373; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); for(int r = 0; r < SCREEN_HEIGHT; ++r) { for(int c = 0; c < SCREEN_WIDTH; ++c) { aScreen[r * SCREEN_WIDTH + c] = buffer[(SCREEN_HEIGHT - 1 - r)*SCREEN_WIDTH + c]; } } clrtbl = aClrtbl; data = aScreen; width = SCREEN_WIDTH; height = SCREEN_HEIGHT; } void CDevice::_setRealTimeMode(bool on) { CMutexLocker lock(dataMutex); if(doRealtimeThread == on) return; doRealtimeThread = on; if(doRealtimeThread) { pthread_create(&thread,NULL,rtThread, this); } } void CDevice::_getRealTimePos(Garmin::Pvt_t& pvt) { if(pthread_mutex_trylock(&mutex) != EBUSY) { pthread_mutex_unlock(&mutex); throw exce_t(errRuntime,lasterror); } CMutexLocker lock(dataMutex); pvt = PositionVelocityTime; } void CDevice::_release() { if(usb == 0) return; usb->close(); delete usb; usb = 0; } void CDevice::_getDevProperties(Garmin::DevProperties_t& dev_properties) { if(usb == 0) return; Packet_t command; Packet_t response; // 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; uint16_t tile_limit = 0; while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = ((uint16_t*)response.payload)[1]; memory = ((uint32_t*)response.payload)[1]; } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } garmindev-0.3.4+svn3432/src/EtrexLegendC/loader.cpp0000644000175000017500000000621612002232272020321 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace EtrexLegendC { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegendC(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegendC::device == 0) { EtrexLegendC::device = new EtrexLegendC::CDevice(); } EtrexLegendC::device->devname = "Etrex Legend C"; EtrexLegendC::device->devid = 0x013b; return EtrexLegendC::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap60C(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegendC::device == 0) { EtrexLegendC::device = new EtrexLegendC::CDevice(); } EtrexLegendC::device->devname = "GPSMap60C"; EtrexLegendC::device->devid = 0x0123; return EtrexLegendC::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap60CS(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegendC::device == 0) { EtrexLegendC::device = new EtrexLegendC::CDevice(); } EtrexLegendC::device->devname = "GPSMap60CS"; EtrexLegendC::device->devid = 0x0123; return EtrexLegendC::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76CS(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegendC::device == 0) { EtrexLegendC::device = new EtrexLegendC::CDevice(); } EtrexLegendC::device->devname = "GPSMap76CS"; EtrexLegendC::device->devid = 0x0123; return EtrexLegendC::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVistaC(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(EtrexLegendC::device == 0) { EtrexLegendC::device = new EtrexLegendC::CDevice(); } EtrexLegendC::device->devname = "Etrex Vista C"; EtrexLegendC::device->devid = 0x013b; return EtrexLegendC::device; } garmindev-0.3.4+svn3432/src/EtrexLegendC/CDevice.h0000644000175000017500000000566412002232272020030 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de bzrudi (bzrudi@users.sourceforge.net) 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "IDeviceDefault.h" #include "CUSB.h" #define SCREEN_WIDTH 176 #define SCREEN_HEIGHT 220 namespace EtrexLegendC { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); std::string devname; uint32_t devid; const std::string& getCopyright(); private: friend void * rtThread(void *ptr); void _acquire(); void _uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); void _uploadMap(const char * filename, uint32_t size, const char * key); void _queryMap(std::list& maps); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); void _uploadRoutes(std::list& routes); void _uploadCustomIcons(std::list& icons); void _screenshot(char *& clrtbl, char *& data, int& width, int& height); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _setRealTimeMode(bool on); void _getRealTimePos(Garmin::Pvt_t& pvt); void _release(); Garmin::CUSB * usb; /// realtime mode thread pthread_t thread; /// mutex to serialize any data access pthread_mutex_t dataMutex; /// keep alive flag for the realtime mode thread bool doRealtimeThread; Garmin::Pvt_t PositionVelocityTime; char aClrtbl[0x100 * 4]; char aScreen[SCREEN_WIDTH * SCREEN_HEIGHT]; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/EtrexLegendC/CMakeLists.txt0000644000175000017500000000125412002232272021104 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(EtrexLegendC SHARED ${SRCS} ${HDRS}) target_link_libraries(EtrexLegendC garmin ${LIBUSB_LIBRARIES} pthread) set(ALIASES EtrexVistaC GPSMap60CS GPSMap60C GPSMap76CS ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET EtrexLegendC POST_BUILD COMMAND ln ARGS -sf libEtrexLegendC${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/src/GPSMap60CSx/CDevice.cpp0000644000175000017500000011537412002232272017725 0ustar miramira/********************************************************************************************** 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 "../Platform.h" #include "CDevice.h" #include #include #include #include #include #include using namespace GPSMap60CSx; using namespace Garmin; using namespace std; #if !defined(CAN_UNALIGNED) # define DBG_SHOW_WAYPOINT # define UNTESTED throw exce_t(errSync, "This function has not yet been tested on your platform.") #else # define UNTESTED #endif 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 = gar_endian(uint16_t, 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 = gar_endian(uint16_t, 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) , screenhflip(false) , screenvflip(false) , usb(0) , doRealtimeThread(false) , pScreen(0) { pthread_mutex_init(&dataMutex, NULL); } CDevice::~CDevice() { if(pScreen) delete [] pScreen; } const string& CDevice::getCopyright() { copyright = "

QLandkarte Device Driver for Garmin " + devname + "

" "

Driver I/F Ver. " INTERFACE_VERSION "

" "

© 2007 by Oliver Eichler (oliver.eichler@gmx.de)

" "

© Venture HC Screenshot support by Torsten Reuschel (me@fuesika.de)

" "

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.

"; 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); } } void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * key) { if(usb == 0) return; UNTESTED; Packet_t command; Packet_t response; int cancel = 0; // ??? 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 = gar_endian(uint16_t, Cmnd_Transfer_Mem); usb->write(command); while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { uint32_t memory = gar_ptr_load(uint32_t, response.payload + 4); cout << "free memory: " << dec << memory / (1024*1024) << " MB" << endl; 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 = gar_endian(uint16_t, 0x000A); usb->write(command); while(usb->read(response)) { if(response.id == 74) { //TODO read data } } callback(0,0,&cancel,"Upload maps ...",0); 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 && !cancel) { chunkSize = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - sizeof(offset)); command.size = chunkSize + sizeof(offset); *(uint32_t*)command.payload = gar_endian(uint32_t, offset); memcpy(command.payload + sizeof(offset),mapdata,chunkSize); size -= chunkSize; mapdata += chunkSize; offset += chunkSize; usb->write(command); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transferring map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.type = GUSB_APPLICATION_LAYER; command.id = 45; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, 0x000A); usb->write(command); } void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key) { if(usb == 0) return; UNTESTED; Packet_t command; Packet_t response; int cancel = 0; // ??? 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 = gar_endian(uint16_t, Cmnd_Transfer_Mem); usb->write(command); while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { uint32_t memory = gar_ptr_load(uint32_t, response.payload + 4); cout << "free memory: " << dec << memory / (1024*1024) << " MB" << endl; 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 = gar_endian(uint16_t, 0x000A); usb->write(command); while(usb->read(response)) { if(response.id == 74) { //TODO read data } } callback(0,0,&cancel,"Upload maps ...",0); FILE *fid = fopen(filename,"r"); if(fid == NULL) { stringstream msg; msg << "Failed to send map: Can't open " << filename; throw exce_t(errRuntime,msg.str()); } uint32_t total = size; uint32_t offset = 0, chunkSize; uint8_t buffer[GUSB_PAYLOAD_SIZE - sizeof(offset)]; size_t chunks_read; command.type = GUSB_APPLICATION_LAYER; command.id = 36; // transfer file by chunks of 0x1000 - 0x0000C - sizeof(offset) = 0x0FF0 bytes while(size && !cancel) { chunkSize = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - sizeof(offset)); command.size = chunkSize + sizeof(offset); chunks_read = fread(buffer, chunkSize, 1, fid); if (chunks_read != 1) { stringstream msg; msg << "Failed to read chunk from map " << filename; throw exce_t(errRuntime,msg.str()); } *(uint32_t*)command.payload = gar_endian(uint32_t, offset); memcpy(command.payload + sizeof(offset),buffer,chunkSize); size -= chunkSize; offset += chunkSize; usb->write(command); double progress = ((total - size) * 100.0) / total; callback(progress,0,&cancel,0,"Transferring map data."); } callback(100,0,&cancel,0,"done"); // terminate map transfer mode (?) command.type = GUSB_APPLICATION_LAYER; command.id = 45; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, 0x000A); usb->write(command); } void CDevice::_queryMap(std::list& maps) { maps.clear(); if(usb == 0) return; UNTESTED; 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); 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); } void CDevice::_downloadWaypoints(list& 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 = gar_endian(uint16_t, 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:" << gar_ptr_load(uint16_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 = gar_endian(uint16_t, 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:" << gar_ptr_load(uint16_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::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 } void CDevice::_uploadWaypoints(std::list& waypoints) { if(usb == 0) return; // count number of proximity waypoints uint16_t prx_wpt_cnt = 0; list::const_iterator wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) ++prx_wpt_cnt; ++wpt; } 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); // transmit proximity waypoints first if(prx_wpt_cnt) { //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, prx_wpt_cnt); usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { if(wpt->dist != 1e25f) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Prx_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); } ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Prx); usb->write(command); } //transmit _all_ waypoints //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, waypoints.size()); usb->write(command); wpt = waypoints.begin(); while(wpt != waypoints.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *wpt >> *p; usb->write(command); ++wpt; } //announce number of records command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Wpt); usb->write(command); } void CDevice::_downloadTracks(std::list& tracks) { tracks.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); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Trk); usb->write(command); int trackidx = 0; string name; Track_t * track = 0; int cancel = 0; int npts = 0; int ntotal = 65535; callback(0,0,&cancel,"Download tracks ...",0); while(!cancel) { if(!usb->read(response)) continue; if(response.id == Pid_Trk_Hdr) { trackidx = 0; D312_Trk_Hdr_t * hdr = (D312_Trk_Hdr_t*)response.payload; tracks.push_back(Track_t()); track = &tracks.back(); *track << *hdr; name = hdr->ident; } if(response.id == Pid_Records) { ntotal = gar_ptr_load(uint16_t, response.payload); } if(response.id == Pid_Trk_Data) { D302_Trk_t * data = (D302_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 (++npts % 100 == 0) { double progress = (npts * 100.0) / ntotal; callback(progress,0,&cancel,0,"Transferring track data."); } } if(response.id == Pid_Xfer_Cmplt) { break; } } if (cancel) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Abort_Transfer); usb->write(command); } callback(100,0,&cancel,0,"done"); } void CDevice::_uploadTracks(std::list& tracks) { if(usb == 0) return; if(devid == 0x0231) return IDeviceDefault::_uploadTracks(tracks); 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); list::const_iterator track = tracks.begin(); while(track != tracks.end()) { //announce number of records // D312_Rte_Hdr_t + D302_Trk_t * number of track points uint16_t nrec = 1 + track->track.size() * 1; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, nrec); usb->write(command); // write track header command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Trk_Hdr; D312_Trk_Hdr_t * r = (D312_Trk_Hdr_t *)command.payload; command.size = *track >> *r; usb->write(command); vector::const_iterator trkpt = track->track.begin(); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Trk_Data; D302_Trk_t * p = (D302_Trk_t *)command.payload; command.size = *trkpt >> *p; // cout << "lat " << trkpt->lat << endl; // cout << "lon " << trkpt->lon << endl; // cout << "time " << trkpt->time << endl; // cout << "alt " << trkpt->alt << endl; // cout << "size " << command.size << endl; usb->write(command); ++trkpt; while(trkpt != track->track.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Trk_Data; D302_Trk_t * p = (D302_Trk_t *)command.payload; command.size = *trkpt >> *p; usb->write(command); ++trkpt; } // finish block command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Trk); usb->write(command); ++track; } } void CDevice::_downloadRoutes(std::list& routes) { routes.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); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Rte); usb->write(command); int routeidx = 0; string name; Route_t * route = 0; int cancel = 0; int npts = 0; int ntotal = 65535; callback(0,0,&cancel,"Download routes ...",0); while(!cancel) { if(!usb->read(response)) continue; if(response.id == Pid_Rte_Hdr) { routeidx = 0; D202_Rte_Hdr_t * hdr = (D202_Rte_Hdr_t*)response.payload; routes.push_back(Route_t()); route = &routes.back(); *route << *hdr; name = hdr->ident; } if(response.id == Pid_Records) { ntotal = gar_ptr_load(uint16_t, response.payload); } if(response.id == Pid_Rte_Wpt_Data) { D110_Wpt_t * p = (D110_Wpt_t*)response.payload; route->route.push_back(RtePt_t()); RtePt_t& rtept = route->route.back(); rtept << *p; if (++npts % 50 == 0) { double progress = (npts * 100.0) / ntotal; callback(progress,0,&cancel,0,"Transferring route data."); } } if(response.id == Pid_Rte_Link_Data) { D210_Rte_Link_t * l = (D210_Rte_Link_t*)response.payload; RtePt_t& rtept = route->route.back(); rtept << *l; } if(response.id == Pid_Xfer_Cmplt) { break; } } if (cancel) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Abort_Transfer); usb->write(command); } callback(100,0,&cancel,0,"done"); } void CDevice::_uploadRoutes(list& routes) { if(usb == 0) return; if(devid == 0x0231) return IDeviceDefault::_uploadRoutes(routes); // count number of proximity waypoints 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); list::const_iterator route = routes.begin(); while(route != routes.end()) { //announce number of records // D202_Rte_Hdr_t + (D110_Wpt_t + D210_Rte_Link_t) * number of route points uint16_t nrec = 1 + route->route.size() * 2; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Records; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, nrec); usb->write(command); // write route header command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Hdr; D202_Rte_Hdr_t * r = (D202_Rte_Hdr_t *)command.payload; command.size = *route >> *r; usb->write(command); vector::const_iterator rtept = route->route.begin(); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; while(rtept != route->route.end()) { command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Link_Data; D210_Rte_Link_t * l = (D210_Rte_Link_t *)command.payload; command.size = *rtept >> *l; usb->write(command); command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Rte_Wpt_Data; D110_Wpt_t * p = (D110_Wpt_t *)command.payload; command.size = *rtept >> *p; usb->write(command); ++rtept; } // finish block command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Xfer_Cmplt; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Rte); usb->write(command); ++route; } } void CDevice::_uploadCustomIcons(list& icons) { cout << "running uploadCustomIcons for device " << hex << devid << endl; if(usb == 0) return; if(devid == 0x0231) return IDeviceDefault::_uploadCustomIcons(icons); 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); list::const_iterator icon = icons.begin(); while(icon != icons.end()) { uint32_t tan = 0; // get tan command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Icon_Id; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, icon->idx + 1); usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Id) { tan = *(uint32_t*)response.payload; } } // request color table command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Clr_Tbl; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Clr_Tbl) { // send back color table memcpy(response.payload + 4, icon->clrtbl, sizeof(icon->clrtbl)); command = response; } } usb->write(command); while(usb->read(response)) { if(response.id == Pid_Req_Clr_Tbl) { // TODO: ignore? } } // send icon data command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Icon_Data; command.size = 0x104; *(uint32_t*)command.payload = tan; memcpy(command.payload + sizeof(tan),icon->data,sizeof(icon->data)); usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Data) { // TODO: ignore? } } ++icon; } } void CDevice::_screenshot(char *& clrtbl, char *& data, int& width, int& height) { if(usb == 0) return; if(devid == 0x0231) return IDeviceDefault::_screenshot(clrtbl, data, width, height); 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); uint32_t tan = 0; // get tan command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Icon_Id; command.size = 2; *(uint16_t*)command.payload = 0; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Icon_Id) { tan = *(uint32_t*)response.payload; } } // request color table command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Req_Clr_Tbl; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); while(usb->read(response)) { if(response.id == Pid_Ack_Clr_Tbl) { // send back color table memcpy(aClrtbl,_clrtbl,sizeof(aClrtbl)); command = response; } } usb->write(command); while(usb->read(response)) { if(response.id == Pid_Req_Clr_Tbl) { // TODO: ignore? } } char buffer[400 * 400]; char * pData = buffer; uint32_t byteCnt; uint32_t byteCntTotal = 0; if(pScreen == 0) { pScreen = new char[screenwidth * screenheight]; } command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Ack_Icon_Data; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); // loop will end after reception of Pid_Icon_Data with length of 4 (tan only) // or too much data while(1) { if(!usb->read(response)) { usb->write(command); continue; } if(response.id == Pid_Icon_Data) { if(response.size == sizeof(tan)) break; byteCnt = response.size - sizeof(tan); memcpy(pData,response.payload + sizeof(tan), byteCnt); pData += byteCnt; byteCntTotal += byteCnt; if(byteCntTotal > sizeof(buffer)) break; } } command.type = GUSB_APPLICATION_LAYER; command.id = 0x373; command.size = 4; *(uint32_t*)command.payload = tan; usb->write(command); cout << "device " << devname << " hor " << screenhflip << " vert " << screenvflip << endl; if(screenhflip) { // screen shot is horizontally flipped if(screenvflip) { // screen shot is also vertically flipped for(int r = 0; r < screenheight; ++r) { for(int c = 0; c < screenwidth; ++c) { pScreen[r * screenwidth + c] = buffer[(screenheight - r) * screenwidth - c - 1]; } } } else { // vertical organisation of the screen shot is fine for(int r = 0; r < screenheight; ++r) { for(int c = 0; c < screenwidth; ++c) { pScreen[r * screenwidth + c] = buffer[(r + 1) * screenwidth - c - 1]; } } } } else { // horizontal organisation of the screen shot is fine if(screenvflip) { // screen shot is vertically flipped for(int r = 0; r < screenheight; ++r) { memcpy(pScreen + r * screenwidth, buffer + (screenheight - 1 - r) * screenwidth, screenwidth); } } else { // vertical organisation of the screen shot is fine memcpy(pScreen, buffer, screenheight * screenwidth); } } clrtbl = aClrtbl; data = pScreen; width = screenwidth; height = screenheight; } void CDevice::_setRealTimeMode(bool on) { CMutexLocker lock(dataMutex); if(doRealtimeThread == on) return; doRealtimeThread = on; if(doRealtimeThread) { pthread_create(&thread,NULL,rtThread, this); } } void CDevice::_getRealTimePos(Garmin::Pvt_t& pvt) { if(pthread_mutex_trylock(&mutex) != EBUSY) { pthread_mutex_unlock(&mutex); throw exce_t(errRuntime,lasterror); } CMutexLocker lock(dataMutex); pvt = PositionVelocityTime; } void CDevice::_release() { if(usb == 0) return; usb->close2(); delete usb; usb = 0; } void CDevice::_getDevProperties(Garmin::DevProperties_t& dev_properties) { if(usb == 0) return; Packet_t command; Packet_t response; // ask for SD Ram capacity command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Command_Data; command.size = 2; *(uint16_t*)command.payload = gar_endian(uint16_t, Cmnd_Transfer_Mem); usb->write(command); // try to read SD Ram capacity uint32_t memory = 0; uint16_t tile_limit = 0; while(usb->read(response)) { if(response.id == Pid_Capacity_Data) { tile_limit = gar_ptr_load(uint16_t, response.payload + 2); memory = gar_ptr_load(uint32_t, response.payload + 4); } } if(tile_limit == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the tile limit of the GPS"); } if(memory == 0) { throw exce_t(errRuntime,"Failed to send map: Unable to find the available memory of the GPS"); } // add to the properties list properties.memory_limit = memory; properties.set.item.memory_limit = 1; properties.maps_limit = tile_limit; properties.set.item.maps_limit = 1; // return the properties dev_properties = properties; } garmindev-0.3.4+svn3432/src/GPSMap60CSx/loader.cpp0000644000175000017500000002067012002232272017663 0ustar miramira/********************************************************************************************** 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 "config.h" #include "CDevice.h" namespace GPSMap60CSx { static CDevice * device = 0; } #ifdef WIN32 #define WIN_EXPORT __declspec(dllexport) #else #define WIN_EXPORT #endif extern "C" WIN_EXPORT Garmin::IDevice * initQuest(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "Quest SYS"; GPSMap60CSx::device->devid = 0x0231; GPSMap60CSx::device->screenwidth = 240; GPSMap60CSx::device->screenheight = 160; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76CSx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "GPSMap76CSX"; GPSMap60CSx::device->devid = 0x0124; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 240; GPSMap60CSx::device->screenhflip = false; GPSMap60CSx::device->screenvflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76Cx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "GPSMap76CX"; GPSMap60CSx::device->devid = 0x0124; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 240; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap60CSx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "GPSMap60CSX"; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 240; GPSMap60CSx::device->screenhflip = false; GPSMap60CSx::device->screenvflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap60Cx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "GPSMap60CX"; GPSMap60CSx::device->devid = 0x0124; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 240; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap60(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "GPSMap60"; GPSMap60CSx::device->devid = 0x0134; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 240; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVentureCx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex VentureCx"; GPSMap60CSx::device->devid = 0x01a5; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVistaCx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex VistaCx"; GPSMap60CSx::device->devid = 0x01a5; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVentureHC(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex Venture HC"; // GPSMap60CSx::device->devid = 0x0312; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexVistaHCx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex Vista HCx"; GPSMap60CSx::device->devid = 0x02b6; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegendHCx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex Legend HCx"; GPSMap60CSx::device->devid = 0x0694; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexSummitHC(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex Summit HC"; // GPSMap60CSx::device->devid = 0x0694; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegendCx(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex LegendCx"; GPSMap60CSx::device->devid = 0x01A5; GPSMap60CSx::device->screenwidth = 176; GPSMap60CSx::device->screenheight = 220; GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegendH(const char * version) { if(strncmp(version,INTERFACE_VERSION,5) != 0) { return 0; } if(GPSMap60CSx::device == 0) { GPSMap60CSx::device = new GPSMap60CSx::CDevice(); } GPSMap60CSx::device->devname = "eTrex Legend H"; GPSMap60CSx::device->devid = 957; GPSMap60CSx::device->screenwidth = 160; GPSMap60CSx::device->screenheight = 288; // GPSMap60CSx::device->screenhflip = true; return GPSMap60CSx::device; } garmindev-0.3.4+svn3432/src/GPSMap60CSx/CDevice.h0000644000175000017500000000623512002232272017365 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CDEVICE_H #define CDEVICE_H #include "IDeviceDefault.h" #include "CUSB.h" namespace GPSMap60CSx { class CDevice : public Garmin::IDeviceDefault { public: CDevice(); virtual ~CDevice(); std::string devname; uint32_t devid; uint16_t screenwidth; uint16_t screenheight; bool screenvflip; bool screenhflip; const std::string& getCopyright(); private: friend void * rtThread(void *ptr); void _acquire(); void _uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); void _uploadMap(const char * filename, uint32_t size, const char * key); void _queryMap(std::list& maps); void _downloadWaypoints(std::list& waypoints); void _uploadWaypoints(std::list& waypoints); void _downloadTracks(std::list& tracks); void _uploadTracks(std::list& tracks); void _downloadRoutes(std::list& routes); void _uploadRoutes(std::list& routes); void _uploadCustomIcons(std::list& icons); void _screenshot(char *& clrtbl, char *& data, int& width, int& height); void _getDevProperties(Garmin::DevProperties_t& dev_properties); void _setRealTimeMode(bool on); void _getRealTimePos(Garmin::Pvt_t& pvt); void _release(); Garmin::CUSB * usb; /// realtime mode thread pthread_t thread; /// mutex to serialize any data access pthread_mutex_t dataMutex; /// keep alive flag for the realtime mode thread bool doRealtimeThread; Garmin::Pvt_t PositionVelocityTime; char aClrtbl[0x100 * 4]; //TODO: aScreen should be calculated from the actual screensize, this is just a static 400x400 char * pScreen; }; } #endif //CDEVICE_H garmindev-0.3.4+svn3432/src/GPSMap60CSx/CMakeLists.txt0000644000175000017500000000150212002232272020442 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS loader.cpp CDevice.cpp ) set(HDRS CDevice.h ) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) add_library(GPSMap60CSx SHARED ${SRCS} ${HDRS}) target_link_libraries(GPSMap60CSx garmin ${LIBUSB_LIBRARIES} pthread) set(ALIASES GPSMap60Cx GPSMap60 EtrexVentureCx EtrexVistaCx GPSMap76CSx EtrexVentureHC EtrexSummitHC EtrexVistaHCx EtrexLegendHCx EtrexLegendCx EtrexLegendH GPSMap76Cx Quest ) foreach(var ${ALIASES}) message(" ${var}") add_custom_command( TARGET GPSMap60CSx POST_BUILD COMMAND ln ARGS -sf libGPSMap60CSx${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} ) endforeach(var) garmindev-0.3.4+svn3432/cmake/CMakeLists.txt0000644000175000017500000000003212002232271017054 0ustar miramiraadd_subdirectory(Modules) garmindev-0.3.4+svn3432/src/CTcp.h0000644000175000017500000000530412002232272015035 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Juan Pablo Daniel Borgna jpdborgna@e-mips.com.ar 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. **********************************************************************************************/ #ifndef CTCP_H #define CTCP_H #include #include "ILink.h" #include "Garmin.h" #include #include #include #include #ifndef WIN32 #include #include #include #include #endif #ifdef WIN32 #include #else #include #include #include #include #endif namespace Garmin { class CTcp : public ILink { 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;} int16_t getSoftwareVersion(){return softwareVersion;} const std::string& getProductString(){return productString;} protected: struct in_addr * atoaddr(char *address); int sock_chars_ready( void); time_t time_now( void); int sock_read(char * data); void sock_write(const char * data); // file descripor for socket int sock_fd; uint16_t productId; int16_t softwareVersion; std::string productString; std::string port; }; } #endif //CSERIAL_H garmindev-0.3.4+svn3432/src/CUSB.h0000644000175000017500000001157412002232272014746 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CUSB_H #define CUSB_H #include #include #ifdef __APPLE__ # include # include # include #elif WIN32 # include #else # include #endif #include "ILink.h" #include "Garmin.h" #define GARMIN_VID 0x91e /// is this really special for the 60CSx or valid for all devices? #define G60CSX_PID 0x3 #define GUSB_PROTOCOL_LAYER 0 #define GUSB_APPLICATION_LAYER 20 #define GUSB_SESSION_START 5 namespace Garmin { /// Garmin's USB protocol /** This should be kept common to all USB devices. However if your device does not fit into the protocol implementation at all, subclass it and make your fixes. */ typedef int (*CUSB_cb_t)(Packet_t& incoming, void* cb_ctx); class CUSB : public ILink { 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 /** This must be called prior to any other request. */ virtual void syncup(); int run_transaction(uint8_t type, uint16_t id, uint8_t * payload, uint32_t p_size, CUSB_cb_t data_cb, void* cb_ctx); int run_app_command(unsigned command, CUSB_cb_t data_cb, void* cb_ctx); int run_app_command(unsigned command, std::list& result); int run_product_request(std::list& result); uint16_t getProductId(){return productId;} int16_t getSoftwareVersion(){return softwareVersion;} const std::string& getProductString(){return productString;} uint16_t getDataType(int data_no, char tag, uint16_t protocol); bool bulkReadActive(){return doBulkRead;} protected: #ifdef __APPLE__ virtual void start(void); #else virtual void start(struct usb_device *dev); #endif virtual void debug(const char * mark, const Garmin::Packet_t& data); #ifdef __APPLE__ UInt8 epBulkIn; UInt8 epBulkOut; UInt8 epIntrIn; #else /// pointer to all bus definitions struct usb_bus * busses; #ifdef WIN32 /// the device handler for the Garmin unit HANDLE udev; DWORD gUSBPacketSize; #else struct usb_dev_handle * udev; #endif int theInterface; int epBulkIn; int epBulkOut; int epIntrIn; #endif int max_tx_size; /// switch between interrupt or bulk endpoint during receive /** This is used by usb_read() internally */ bool doBulkRead; uint16_t productId; int16_t softwareVersion; std::string productString; int32_t protocolArraySize; Protocol_Data_t protocolArray[GUSB_PAYLOAD_SIZE]; #ifdef __APPLE__ private: friend void * readIntrPipe(void *); // use the IOKit framework USB implementation on MacOS X mach_port_t masterPort; io_service_t usbDevRef; IOUSBDeviceInterface **usbDev; io_service_t usbInterfaceRef; IOUSBInterfaceInterface182 **usbIntf; // run reads from the interrupt pipe in a separate thread pthread_t ir_thread; pthread_mutex_t ir_mutex; pthread_cond_t ir_cond; struct readIntrCmnd_t * readIntrCmnd; #endif int _bulk_read(Packet_t&); }; } #endif //CUSB_H garmindev-0.3.4+svn3432/src/CUSB_common.cpp0000644000175000017500000001036412002232272016645 0ustar miramira /********************************************************************************************** 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 "CUSB.h" #include "IDevice.h" #include "Platform.h" #include using namespace Garmin; using namespace std; static int _reduce(Packet_t& incoming, void * ctx); // This file contains common functions used by both the libusb and the Mac OS X (IOKit) USB code #define DBG_LINE_SIZE 16 #define DBG void CUSB::debug(const char * mark, const Packet_t& data) { #ifndef DBG return; #endif unsigned i; uint32_t size; unsigned bytes = DBG_LINE_SIZE; char buf[DBG_LINE_SIZE + 1]; memset(buf, 0x20, sizeof(buf)); buf[DBG_LINE_SIZE] = 0; cout << mark << endl << " "; const uint8_t * pData = (const uint8_t*) &data; size = gar_endian(uint32_t, data.size); if (size > GUSB_MAX_BUFFER_SIZE) { cerr << "WARNING! Data size " << data.size << " exceeds buffer size." << endl; cerr << "Truncate to " << GUSB_MAX_BUFFER_SIZE << "." << endl; size = GUSB_PAYLOAD_SIZE; } for (i = 0; i < (size + GUSB_HEADER_SIZE); ++i) { if (i && !(i % DBG_LINE_SIZE)) { cout << " " << buf << endl << " "; memset(buf, 0x20, sizeof(buf)); buf[DBG_LINE_SIZE] = 0; bytes = DBG_LINE_SIZE; } cout.width(2); cout.fill('0'); cout << hex << (unsigned) pData[i] << " "; if (isprint(pData[i])) buf[i % DBG_LINE_SIZE] = pData[i]; else buf[i % DBG_LINE_SIZE] = '.'; --bytes; } for (i = 0; i < bytes; i++) cout << " "; cout << " " << buf << dec << endl; } int CUSB::run_transaction(uint8_t type, uint16_t id, uint8_t * payload, uint32_t p_size, CUSB_cb_t data_cb, void* cb_ctx) { Packet_t req, resp; int ret=0, ret2; if (p_size > GUSB_PAYLOAD_SIZE) throw exce_t(errRuntime, "Trying to run a command with an illegal payload size."); req.type = type; req.id = id; req.size = p_size; memcpy(req.payload, payload, p_size); write(req); while (0 < (ret2 = read(resp)) ) { ret += ret2; if (data_cb) { ret2 = data_cb(resp, cb_ctx); if( 0 > ret2) ret = ret2; if (1 > ret2) break; } } return ret; } int CUSB::run_app_command(unsigned command, CUSB_cb_t data_cb, void* cb_ctx) { uint16_t cmd = gar_endian(uint16_t, command); return run_transaction(GUSB_APPLICATION_LAYER, Pid_Command_Data, (uint8_t *)&cmd, sizeof(cmd), data_cb, cb_ctx); } int CUSB::run_app_command(unsigned command, std::list& result) { uint16_t cmd = gar_endian(uint16_t, command); result.clear(); return run_transaction(GUSB_APPLICATION_LAYER, Pid_Command_Data, (uint8_t *)&cmd, sizeof(cmd), _reduce, &result); } int CUSB::run_product_request(std::list& result) { result.clear(); return run_transaction(GUSB_APPLICATION_LAYER, Pid_Product_Rqst, 0, 0, _reduce, &result); } static int _reduce(Packet_t& incoming, void * ctx) { std::list* cumulated = reinterpret_cast*>(ctx); cumulated->push_back(Packet_t()); Packet_t& n = cumulated->back(); memcpy(&n, &incoming, sizeof (n)); return sizeof(incoming); } garmindev-0.3.4+svn3432/src/ILink.cpp0000644000175000017500000000221512002232272015543 0ustar miramira/********************************************************************************************** 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 "ILink.h" using namespace Garmin; ILink::ILink() { } ILink::~ILink() { } garmindev-0.3.4+svn3432/src/CUSB_MacOSX.cpp0000644000175000017500000005217712002232272016457 0ustar miramira/* -*-mode:c++; c-basic-offset:4; -*- */ /********************************************************************************************** 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 USB Interface for MacOS X Written by (C) Albrecht Dre 2008 Based upon the CUSB.cpp source file and the examples provided by Apple with XCode Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd. or one of its subsidiaries. Apple is a registered trademark by Apple, Inc. **********************************************************************************************/ #include #include #include #include #include #include "CUSB.h" #include "IDevice.h" #include "Platform.h" #include #include #include #include #include using namespace Garmin; using namespace std; #define GUSB_DATA_AVAILABLE 2 #define GUSB_SESSION_START 5 #define GUSB_SESSION_STARTED 6 #undef DBG namespace Garmin { struct readIntrCmnd_t { void * data; UInt32 * size; IOReturn * result; }; void * readIntrPipe(void * ptr) { CUSB * usb = (CUSB *) ptr; do { // wait for a command pthread_mutex_lock(&usb->ir_mutex); while (usb->readIntrCmnd == 0) pthread_cond_wait(&usb->ir_cond, &usb->ir_mutex); // eject from the thread if requested if (usb->readIntrCmnd == (struct readIntrCmnd_t *) (-1)) { pthread_mutex_unlock(&usb->ir_mutex); return NULL; } // perform the read pthread_mutex_unlock(&usb->ir_mutex); *usb->readIntrCmnd->result = (*(usb->usbIntf))->ReadPipe(usb->usbIntf, usb->epIntrIn, usb->readIntrCmnd->data, usb->readIntrCmnd->size); // notify caller pthread_mutex_lock(&usb->ir_mutex); usb->readIntrCmnd = 0; pthread_cond_broadcast(&usb->ir_cond); pthread_mutex_unlock(&usb->ir_mutex); } while (1); // never reached } // Helper: create an IOKit error string class MacErrStr: public string { public: MacErrStr(IOReturn val) { if (val == kIOReturnSuccess) { assign("no error"); return; } assign("["); // get the system switch (val & system_emask) { case sys_iokit: append("IOKit"); break; default: stringstream msg; msg << "system " << hex << err_get_system(val); append(msg.str()); } // get the subsystem switch (val & sub_emask) { case sub_iokit_common: append("/common"); break; case sub_iokit_usb: append("/usb"); break; default: stringstream msg; msg << "/sub " << hex << err_get_sub(val); append(msg.str()); } // append the error code (too many to decode them - there should be a system function!) stringstream msg; msg << "] code 0x" << hex << err_get_code(val); append(msg.str()); } ~MacErrStr() {} }; } CUSB::CUSB() : epBulkIn(0), epBulkOut(0), epIntrIn(0), max_tx_size(-1), doBulkRead(false), productId(0), softwareVersion(0), protocolArraySize(-1), masterPort(0), usbDevRef(0), usbDev(0), usbInterfaceRef(0), usbIntf(0), ir_thread(0), readIntrCmnd(0) { kern_return_t err; // create the mutex and the condition for the interrupt pipe if (pthread_mutex_init(&ir_mutex, NULL) != 0) throw exce_t(errOpen, "Failed to initialise mutex."); if (pthread_cond_init(&ir_cond, NULL) != 0) throw exce_t(errOpen, "Failed to initialise condition variable."); // open the master port if ((err = IOMasterPort(MACH_PORT_NULL, &masterPort))) { stringstream msg; msg << "Error " << MacErrStr(err) << " creating master port."; throw exce_t(errOpen, msg.str()); } // launch the thread for reading from the interrupt pipe if (pthread_create(&ir_thread, NULL, &readIntrPipe, this) != 0) throw exce_t(errOpen, "Failed to launch read thread."); } CUSB::~CUSB() { close(); // terminate the interrupt pipe read thread if (ir_thread) { pthread_mutex_lock(&ir_mutex); readIntrCmnd = (struct readIntrCmnd_t *) (-1); pthread_cond_signal(&ir_cond); pthread_mutex_unlock(&ir_mutex); pthread_join(ir_thread, NULL); } pthread_cond_destroy(&ir_cond); pthread_mutex_destroy(&ir_mutex); if (masterPort) mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; } void CUSB::open() { CFMutableDictionaryRef matchingDict; SInt32 idVal; CFNumberRef numberRef; // create a matching dictionary if (!(matchingDict = IOServiceMatching(kIOUSBDeviceClassName))) throw exce_t(errOpen, "Cannot create matching dictionary."); // configure the dictionary idVal = GARMIN_VID; if (!(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idVal))) { CFRelease(matchingDict); throw exce_t(errOpen, "Cannot configure matching dictionary."); } CFDictionaryAddValue(matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); idVal = G60CSX_PID; if (!(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idVal))) { CFRelease(matchingDict); throw exce_t(errOpen, "Cannot configure matching dictionary."); } CFDictionaryAddValue(matchingDict, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); // get matching device (note: call consumes the matchingDict, so we must not unref it) // FIXME - at this point we get only the first Garmin... if ((usbDevRef = IOServiceGetMatchingService(masterPort, matchingDict))) start(); else throw exce_t(errOpen, "No Garmin device found, is the unit connected?"); } void CUSB::close() { // release interface if (usbIntf) { IOReturn err; if ((err = (*usbIntf)->USBInterfaceClose(usbIntf)) != kIOReturnSuccess) { #ifdef DBG cout << "Error " << MacErrStr(err) << " closing USB interface." << endl; #endif } if ((err = (*usbIntf)->Release(usbIntf)) != kIOReturnSuccess) { #ifdef DBG cout << "Error " << MacErrStr(err) << " releasing USB interface." << endl; #endif } } usbIntf = 0; if (usbInterfaceRef) IOObjectRelease(usbInterfaceRef); usbInterfaceRef = 0; // release USB device if (usbDev) { IOReturn err; if ((err = (*usbDev)->USBDeviceClose(usbDev)) != kIOReturnSuccess) { #ifdef DBG cout << "Error " << MacErrStr(err) << " closing USB device." << endl; #endif } if ((err = (*usbDev)->Release(usbDev)) != kIOReturnSuccess) { #ifdef DBG cout << "Error " << MacErrStr(err) << " releasing USB device." << endl; #endif } } usbDev = 0; // release matching device if (usbDevRef) IOObjectRelease(usbDevRef); usbDevRef = 0; } void CUSB::close2() { close(); } int CUSB::read(Packet_t& data) { IOReturn res; UInt32 size = sizeof(Packet_t); data.type = 0; data.id = 0; data.size = 0; if (doBulkRead) res = (*usbIntf)->ReadPipeTO(usbIntf, epBulkIn, (void *) &data, &size, 3000, 4000); else { // tell the thread to read from the interrupt pipe pthread_mutex_lock(&ir_mutex); struct readIntrCmnd_t readCmnd; readCmnd.data = (void *) &data; readCmnd.result = &res; readCmnd.size = &size; readIntrCmnd = &readCmnd; pthread_cond_broadcast(&ir_cond); pthread_mutex_unlock(&ir_mutex); // set the timeout - MacOS X doesn't have clock_gettime?!? That's against the POSIX standard! struct timeval tv; gettimeofday(&tv, 0); struct timespec wait_until; wait_until.tv_sec = tv.tv_sec + 3; wait_until.tv_nsec = tv.tv_usec * 1000; // wait for the thread, abort on timeout pthread_mutex_lock(&ir_mutex); while (readIntrCmnd != 0 && pthread_cond_timedwait(&ir_cond, &ir_mutex, &wait_until) == 0); if (readIntrCmnd != 0) { (*usbIntf)->AbortPipe(usbIntf, epIntrIn); (*usbIntf)->ClearPipeStall(usbIntf, epIntrIn); pthread_cond_wait(&ir_cond, &ir_mutex); } pthread_mutex_unlock(&ir_mutex); } if (res == kIOReturnSuccess && size > 0) { debug(doBulkRead ? "b >>" : "i >>", data); #if defined(HAVE_BIGENDIAN) // endian fix for id and size data.id = gar_endian(uint16_t, data.id); data.size = gar_endian(uint32_t, data.size); #endif // big endian platform // switch to bulk pipe if (size > 0 && data.id == GUSB_DATA_AVAILABLE) doBulkRead = true; } // switch to interrupt pipe on errors or zero size packages if (size == 0 || res != kIOReturnSuccess) doBulkRead = false; if (res != kIOReturnSuccess) { stringstream msg; msg << "USB read failed: error " << MacErrStr(res); throw exce_t(errRead, msg.str()); } return size; } void CUSB::write(const Packet_t& data) { UInt32 size = GUSB_HEADER_SIZE + data.size; IOReturn res; char * src; #if defined(HAVE_BIGENDIAN) // make a local copy for swapping the header Packet_t real_cmnd(data.type, gar_endian(uint16_t, data.id)); real_cmnd.size = gar_endian(uint32_t, data.size); // copy payload (if any) if (data.size > 0) memcpy(real_cmnd.payload, data.payload, data.size); // send the tweaked packet src = (char *) &real_cmnd; #else src = (char *) &data; #endif // big endian platform res = (*usbIntf)->WritePipeTO(usbIntf, epBulkOut, (void *) src, size, 3000, 4000); debug("b <<", (Packet_t &) *src); if (res != kIOReturnSuccess) { stringstream msg; msg << "USB bulk write failed: error " << MacErrStr(res); throw exce_t(errWrite, msg.str()); } /* The Garmin protocol requires that packets that are exactly a multiple of the max tx size be followed by a zero length packet. */ if (size && !(size % max_tx_size)) { (*usbIntf)->WritePipeTO(usbIntf, epBulkOut, (void *) src, 0, 1000, 2000); #ifdef DBG cout << "b << zero size packet to terminate" << endl; #endif } } void CUSB::start(void) { if (usbDev) return; // deal with the device: create plug-in IOReturn err; IOCFPlugInInterface **iodev; SInt32 score; err = IOCreatePlugInInterfaceForService(usbDevRef, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score); if ((err != kIOReturnSuccess) || !iodev) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " creating plugin."; throw exce_t(errOpen, msg.str()); } // query the interface err = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void **) &usbDev); IODestroyPlugInInterface(iodev); if ((err != kIOReturnSuccess) || !usbDev) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " creating device interface."; throw exce_t(errOpen, msg.str()); } // open the interface if ((err = (*usbDev)->USBDeviceOpen(usbDev)) != kIOReturnSuccess) { (*usbDev)->Release(usbDev); usbDev = 0; stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " opening USB device."; throw exce_t(errOpen, msg.str()); } // get configurations UInt8 numConf; err = (*usbDev)->GetNumberOfConfigurations(usbDev, &numConf); if ((err != kIOReturnSuccess) || !numConf) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " reading configurations."; throw exce_t(errOpen, msg.str()); } #ifdef DBG cout << "Garmin USB device: found " << unsigned(numConf) << " configurations" << endl; #endif // get the first configuration IOUSBConfigurationDescriptorPtr confDesc; if ((err = (*usbDev)->GetConfigurationDescriptorPtr(usbDev, 0, &confDesc)) != kIOReturnSuccess) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " reading first configuration."; throw exce_t(errOpen, msg.str()); } // set the first configuration if ((err = (*usbDev)->SetConfiguration(usbDev, confDesc->bConfigurationValue)) != kIOReturnSuccess) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " setting configuration."; throw exce_t(errOpen, msg.str()); } // find the interface IOUSBFindInterfaceRequest interfaceRequest; // requested class interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare; // requested subclass interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; // requested protocol interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; // requested alt setting interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare; io_iterator_t iterator; if ((err = (*usbDev)->CreateInterfaceIterator(usbDev, &interfaceRequest, &iterator)) != kIOReturnSuccess) { stringstream msg; msg << "Garmin USB device: error " << MacErrStr(err) << " creating interface iterator."; throw exce_t(errOpen, msg.str()); } if (!(usbInterfaceRef = IOIteratorNext(iterator))) { IOObjectRelease(iterator); throw exce_t(errOpen, "Garmin USB device: cannot find USB interface."); } IOObjectRelease(iterator); // deal with the interface: create interface plug-in err = IOCreatePlugInInterfaceForService(usbInterfaceRef, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score); if ((err != kIOReturnSuccess) || !iodev) { stringstream msg; msg << "Garmin USB device interface: error " << MacErrStr(err) << " creating plugin."; throw exce_t(errOpen, msg.str()); } // query interface err = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (void **) &usbIntf); IODestroyPlugInInterface(iodev); if ((err != kIOReturnSuccess) || !usbIntf) { stringstream msg; msg << "Garmin USB device interface: error " << MacErrStr(err) << " creating device interface."; throw exce_t(errOpen, msg.str()); } // open interface if ((err = (*usbIntf)->USBInterfaceOpen(usbIntf)) != kIOReturnSuccess) { (*usbIntf)->Release(usbIntf); usbIntf = 0; stringstream msg; msg << "Garmin USB device interface: error " << MacErrStr(err) << " opening USB device interface."; throw exce_t(errOpen, msg.str()); } // get endpoints UInt8 numEP; if ((err = (*usbIntf)->GetNumEndpoints(usbIntf, &numEP)) != kIOReturnSuccess) { stringstream msg; msg << "Garmin USB device interface: error " << MacErrStr(err) << " reading number of endpoints."; throw exce_t(errOpen, msg.str()); } #ifdef DBG cout << "Garmin USB device interface: found " << unsigned(numEP) << " endpoints." << endl; #endif // identify bulk in, bulk out and interrupt in endpoints int i; for (i = 1; i <= numEP; i++) { UInt8 direction; UInt8 number; UInt8 transferType; UInt8 interval; UInt16 maxPacketSize; if ((err = (*usbIntf)->GetPipeProperties(usbIntf, i, &direction, &number, &transferType, &maxPacketSize, &interval)) != kIOReturnSuccess) { stringstream msg; msg << "Garmin USB device interface: error " << MacErrStr(err) << " reading properties of endpoint " << i << "."; throw exce_t(errOpen, msg.str()); } #ifdef DBG cout << "endpoint " << i << ": dir 0x" << hex << unsigned(direction) << ", number 0x" << hex << unsigned(number) << ", type 0x" << hex << unsigned(transferType) << ", max size " << dec << maxPacketSize << ", interval 0x" << hex << unsigned(interval); #endif if (transferType == kUSBBulk) { switch (direction) { case kUSBIn: #ifdef DBG cout << " ---> use as BULK IN pipe" << endl; #endif epBulkIn = i; break; case kUSBOut: #ifdef DBG cout << " ---> use as BULK OUT pipe" << endl; #endif epBulkOut = i; max_tx_size = maxPacketSize; break; default: #ifdef DBG cout << " ---> no idea what I should do with it" << endl; #endif break; } } else if (transferType == kUSBInterrupt && (direction == kUSBIn)) { #ifdef DBG cout << " ---> use as INTR IN pipe" << endl; #endif epIntrIn = i; } else { #ifdef DBG cout << " ---> no idea what I should do with it" << endl; #endif } } if (!epBulkIn || !epBulkOut || !epIntrIn || max_tx_size <= 0) throw exce_t(errOpen,"Garmin USB device interface: failed to identify USB endpoints."); } void CUSB::syncup(void) { static const Packet_t gpack_session_start(GUSB_PROTOCOL_LAYER, GUSB_SESSION_START); Packet_t response; write(gpack_session_start); read(response); if (response.id == GUSB_SESSION_STARTED) { Packet_t command; Packet_t response; command.type = GUSB_APPLICATION_LAYER; command.id = Pid_Product_Rqst; command.size = 0; write(command); protocolArraySize = 0; while (read(response)) { if (response.id == Pid_Product_Data) { //TODO read data Product_Data_t * pData = (Product_Data_t*)response.payload; productId = gar_load(uint16_t, pData->product_id); softwareVersion = gar_load(int16_t, pData->software_version); productString = pData->str; #ifdef DBG cout << "Product: " << hex << productId << " " << dec << softwareVersion << " " << productString << endl; #endif } if (response.id == Pid_Ext_Product_Data) { //TODO read data } if (response.id == Pid_Protocol_Array) { // note: we cannot use a Protocol_Data_t here due to alignment issues // on some platforms... uint8_t * p = response.payload; for (uint32_t i = 0; i < response.size; i += sizeof(Protocol_Data_t)) { uint8_t pr_tag = *p++; uint16_t pr_data = gar_ptr_load(uint16_t, p); p += 2; #ifdef DBG cout << "Protocol: "<< (char)pr_tag << dec << pr_data << endl; #endif ++protocolArraySize; protocolArray[protocolArraySize].tag = pr_tag; protocolArray[protocolArraySize].data = pr_data; } ++protocolArraySize; #ifdef DBG cout << "protocolArraySize:" << protocolArraySize << endl; #endif // if (!doBulkRead) return; } } return; } throw exce_t(errSync,"Failed to sync. up with device"); } uint16_t CUSB::getDataType(int data_no, char tag, uint16_t protocol) { // Find the right tag D for for (uint32_t i = 0; i < protocolArraySize - 1 - data_no; i++) { if ((char) protocolArray[i].tag == tag) { if (protocolArray[i].data == protocol) { // accept data_no=-1 as a protocol verification only if (data_no == -1) return (uint16_t) 1; if ((char) protocolArray[i + 1 + data_no].tag == 'D') return protocolArray[i + 1 + data_no].data; } } } return (uint16_t) 0; } garmindev-0.3.4+svn3432/src/ILink.h0000644000175000017500000000520712002232272015214 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef ILINK_H #define ILINK_H #include "Platform.h" #define GUSB_MAX_BUFFER_SIZE 0x1000 #define GUSB_HEADER_SIZE 0x000C #define GUSB_PAYLOAD_SIZE (GUSB_MAX_BUFFER_SIZE - GUSB_HEADER_SIZE) namespace Garmin { #pragma pack(1) struct Packet_t { Packet_t(uint8_t type, uint16_t id) : type(type), b1(0), b2(0), b3(0), id(id), b6(0), b7(0), size(0){} Packet_t() : type(0), b1(0), b2(0), b3(0), id(0), b6(0), b7(0), size(0){} uint8_t type; uint8_t b1; uint8_t b2; uint8_t b3; uint16_t id; uint8_t b6; uint8_t b7; uint32_t size; uint8_t payload[GUSB_PAYLOAD_SIZE+4]; }; #ifdef WIN32 #pragma pack() #else #pragma pack(0) #endif /// 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 garmindev-0.3.4+svn3432/src/IDeviceDefault.cpp0000644000175000017500000002256312002232272017362 0ustar miramira/********************************************************************************************** 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 "config.h" #include "IDeviceDefault.h" #include using namespace Garmin; using namespace std; IDeviceDefault::IDeviceDefault() { pthread_mutex_init(&mutex, NULL); } IDeviceDefault::~IDeviceDefault() { } void IDeviceDefault::callback(int progress, int * ok, int * cancel, const char * title, const char * msg) { if(_callback_) { _callback_(progress,ok,cancel,title,msg,_self_); } } void IDeviceDefault::setPort(const char * p) { port = p; } void IDeviceDefault::uploadMap(const uint8_t * mapdata, uint32_t size, const char * key) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadMap(mapdata, size, key); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload maps. " + e.msg; throw (int)e.err; } } void IDeviceDefault::uploadMap(const char * filename, uint32_t size, const char * key) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadMap(filename, size, key); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload maps. " + e.msg; throw (int)e.err; } } void IDeviceDefault::queryMap(std::list& maps) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _queryMap(maps); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to query loaded maps. " + e.msg; throw (int)e.err; } } void IDeviceDefault::downloadWaypoints(std::list& waypoints) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _downloadWaypoints(waypoints); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to download waypoints. " + e.msg; throw (int)e.err; } } void IDeviceDefault::uploadWaypoints(std::list& waypoints) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadWaypoints(waypoints); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload waypoints. " + e.msg; throw (int)e.err; } } void IDeviceDefault::downloadTracks(std::list& tracks) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _downloadTracks(tracks); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to download tracks. " + e.msg; throw (int)e.err; } } void IDeviceDefault::uploadTracks(std::list& tracks) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadTracks(tracks); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload tracks. " + e.msg; throw (int)e.err; } } void IDeviceDefault::uploadRoutes(std::list& routes) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadRoutes(routes); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload routes. " + e.msg; throw (int)e.err; } } void IDeviceDefault::downloadRoutes(std::list& routes) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _downloadRoutes(routes); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to download routes. " + e.msg; throw (int)e.err; } } void IDeviceDefault::uploadCustomIcons(std::list& icons) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _uploadCustomIcons(icons); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to upload icons. " + e.msg; throw (int)e.err; } } void IDeviceDefault::screenshot(char *& clrtbl, char *& data, int& width, int& height) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _screenshot(clrtbl, data, width, height); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to download screenshot. " + e.msg; throw (int)e.err; } } void IDeviceDefault::setRealTimeMode(bool on) { lasterror = ""; try { _setRealTimeMode(on); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to change real time mode. " + e.msg; throw (int)e.err; } } void IDeviceDefault::getRealTimePos(Garmin::Pvt_t& pvt) { // don't reset last error because it might hold the reason, // why the realtime thread died. //lasterror = ""; try { _getRealTimePos(pvt); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to request real time position. " + e.msg; throw (int)e.err; } } void IDeviceDefault::getDevProperties(Garmin::DevProperties_t& dev_properties) { lasterror = ""; try { CMutexLocker lock(mutex); _acquire(); _getDevProperties(dev_properties); _release(); } catch(exce_t& e) { if(e.err != errBlocked) _release(); lasterror = "Failed to obtain GPS properties. " + e.msg; throw (int)e.err; } } const std::string& IDeviceDefault::getCopyright() { return copyright; } const std::string& IDeviceDefault::getLastError() { return lasterror; } void IDeviceDefault::_uploadMap(const uint8_t * , uint32_t , const char * ) { throw exce_t(errNotImpl,"uploadMap(): this method is not implemented for your device."); } void IDeviceDefault::_uploadMap(const char * , uint32_t , const char * ) { throw exce_t(errNotImpl,"uploadMap(): this method is not implemented for your device."); } void IDeviceDefault::_queryMap(std::list& ) { throw exce_t(errNotImpl,"queryMap(): this method is not implemented for your device."); } void IDeviceDefault::_downloadWaypoints(std::list& ) { throw exce_t(errNotImpl,"downloadWaypoints(): this method is not implemented for your device."); } void IDeviceDefault::_uploadWaypoints(std::list& ) { throw exce_t(errNotImpl,"uploadWaypoints(): this method is not implemented for your device."); } void IDeviceDefault::_downloadTracks(std::list& ) { throw exce_t(errNotImpl,"downloadTracks(): this method is not implemented for your device."); } void IDeviceDefault::_uploadTracks(std::list& ) { throw exce_t(errNotImpl,"uploadTracks(): this method is not implemented for your device."); } void IDeviceDefault::_downloadRoutes(std::list& ) { throw exce_t(errNotImpl,"downloadRoutes(): this method is not implemented for your device."); } void IDeviceDefault::_uploadRoutes(std::list& ) { throw exce_t(errNotImpl,"uploadRoutes(): this method is not implemented for your device."); } void IDeviceDefault::_uploadCustomIcons(std::list& ) { throw exce_t(errNotImpl,"uploadCustomIcons(): this method is not implemented for your device."); } void IDeviceDefault::_screenshot(char *& /*clrtbl*/, char *& /*data*/, int& /*width*/, int& /*height*/) { throw exce_t(errNotImpl,"screenshot(): this method is not implemented for your device."); } void IDeviceDefault::_setRealTimeMode(bool) { throw exce_t(errNotImpl,"setRealTimeMode(): this method is not implemented for your device."); } void IDeviceDefault::_getRealTimePos(Garmin::Pvt_t&) { throw exce_t(errNotImpl,"getRealTimePos(): this method is not implemented for your device."); } void IDeviceDefault::_getDevProperties(Garmin::DevProperties_t& dev_properties) { // mark all properties as not having been set to meaningful values properties.set.all = (uint32_t) 0; // return a copy of the device properties block dev_properties = properties; } garmindev-0.3.4+svn3432/src/IDevice.h0000644000175000017500000004707412002232272015526 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef IDEVICE_H #define IDEVICE_H // need integer type definitions with fixed width #ifdef HAVE_INTTYPES_H # include #elif HAVE_STDINT_H # include #elif WIN32 typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #else # error neither inttypes.h nor stdint.h are available #endif #include #include #include #include #include #ifndef _MKSTR_1 #define _MKSTR_1(x) #x #define _MKSTR(x) _MKSTR_1(x) #endif #define INTERFACE_VERSION "01.18" namespace Garmin { /// common waypoint structure application side /** This structure has to be used to exchange a waypoint to QLandkarte. If an item is missing you can simply add it. This structure must never be copied assuming a certain alignment. Most values are the same like the ones used in the waypoint data structures used by Garmin. */ struct Wpt_t { Wpt_t() : wpt_class(0) , dspl_color(0) , dspl_attr(0) , smbl(8287) , lat(1000.0f) , lon(1000.0f) , alt(1.0e25f) , dpth(1.0e25f) , dist(1.0e25f) , ete(0xFFFFFFFF) , temp(1.0e25f) , time(0xFFFFFFFF) , wpt_cat(0) { strncpy(state," ", 3); strncpy(cc," ",3); } /// same as Garmin spec. uint8_t wpt_class; /// bit 0..4 of dspl_color uint8_t dspl_color; /// bit 5..6 of dspl_color uint8_t dspl_attr; /// same as Garmin spec. uint16_t smbl; /// the latitude as degrees double lat; /// the longitude as degrees double lon; /// same as Garmin spec. float alt; /// same as Garmin spec. float dpth; /// same as Garmin spec. float dist; /// same as Garmin spec. char state[3]; /// same as Garmin spec. char cc[3]; /// same as Garmin spec. uint32_t ete; /// same as Garmin spec. float temp; /// same as Garmin spec. uint32_t time; /// same as Garmin spec. uint16_t wpt_cat; /// same as Garmin spec. std::string ident; /// same as Garmin spec. std::string comment; /// same as Garmin spec. std::string facility; /// same as Garmin spec. std::string city; /// same as Garmin spec. std::string addr; /// same as Garmin spec. std::string crossroad; }; /// common route point structure application side /** This structure has to be used to exchange a waypoint to QLandkarte. If an item is missing you can simply add it. This structure must never be copied assuming a certain alignment. Most values are the same like the ones used in the waypoint and route point data structures used by Garmin. It adds link information. For more complex route operations, it is critical to note that this refers to the link with the *previous* waypoint. For example, when a route is inverted, the link information must be transfered to the previous point first. */ struct RtePt_t : public Wpt_t { RtePt_t() : rte_class(3) , subclass_1(0x0000) , subclass_2(0x00000000) , subclass_3(0xFFFFFFFF) , subclass_4(0xFFFFFFFF) , subclass_5(0xFFFFFFFF) {} uint16_t rte_class; uint16_t subclass_1; uint32_t subclass_2; uint32_t subclass_3; uint32_t subclass_4; uint32_t subclass_5; std::string ident; }; /// common route structure application side /** This structure has to be used to exchange a track to QLandkarte. If an item is missing you can simply add it. This structure must never be copied assuming a certain alignment. Most values are the same like the ones used in the point data structures used by Garmin. */ struct Route_t { /// same as Garmin spec. std::string ident; /// route points std::vector route; }; /// common track point structure application side /** This structure has to be used to exchange a track point to QLandkarte. If an item is missing you can simply add it. This structure must never be copied assuming a certain alignment. Most values are the same like the ones used in the track point data structures used by Garmin. */ struct TrkPt_t { TrkPt_t() : lat(0.0) , lon(0.0) , time(0) , alt(1e25f) , dpth(1e25f) , distance(1e25f) , heart_rate(0xFF) , cadence(0xFF) , sensor(0xFF) { } /// the latitude as degrees double lat; /// the longitude as degrees double lon; /// the time in sec. as specified by Garmin uint32_t time; /// same as Garmin spec. float alt; /// same as Garmin spec. float dpth; float distance; uint8_t heart_rate; uint8_t cadence; uint8_t sensor; }; /// common track structure application side /** This structure has to be used to exchange a track to QLandkarte. If an item is missing you can simply add it. This structure must never be copied assuming a certain alignment. Most values are the same like the ones used in the point data structures used by Garmin. */ struct Track_t { Track_t() : dspl(true) , color(0xFF) { } /// same as Garmin spec. bool dspl; /// same as Garmin spec. uint8_t color; /// same as Garmin spec. std::string ident; /// trackpoints std::vector track; }; struct Map_t { std::string mapName; std::string tileName; }; struct Pvt_t { /// same as Garmin spec. float alt; /// same as Garmin spec. float epe; /// same as Garmin spec. float eph; /// same as Garmin spec. float epv; /// same as Garmin spec. uint16_t fix; /// same as Garmin spec. double tow; /// the latitude as degrees double lat; /// the longitude as degrees double lon; /// same as Garmin spec. float east; /// same as Garmin spec. float north; /// same as Garmin spec. float up; /// same as Garmin spec. float msl_hght; /// same as Garmin spec. int16_t leap_scnds; /// same as Garmin spec. uint32_t wn_days; }; struct Icon_t { Icon_t(){ memset(data,0,sizeof(data));} /// custom icon index (0..511) uint16_t idx; /// the bitmap's color table char clrtbl[0x400]; /// the bitmap's image data char data[0x100]; }; /// device property structure application side /** This structure is used to account for device properties such as the available memory and maximum number of maps. If a property is missing, it can be added. Both the item must be added and a still undefined bit in dev_property_list_t may have to be allocated to indicate that the property has indeed been set to a meaningful value. */ // boolean quantitities in the form of a bit field struct dev_property_list_t { uint32_t memory_limit: 1; uint32_t maps_limit: 1; uint32_t allow_duplicated_map_IDs: 1; uint32_t routes_limit: 1; uint32_t route_pts_limit: 1; uint32_t waypts_limit: 1; uint32_t tracks_limit: 1; uint32_t track_pts_limit: 1; uint32_t screen_size: 1; uint32_t pvt_requestable: 1; uint32_t custom_POI_limit: 1; uint32_t protocols_requestable: 1; uint32_t protocols_set: 1; uint32_t product_ID: 1; uint32_t product_string: 1; uint32_t read_trailing_packets: 1; uint32_t undefined: 15; uint32_t ext_dev_properties: 1; }; // make the bit field addressable as a single integer union device_properties_union_t { uint32_t all; dev_property_list_t item; }; // the device properties structure struct DevProperties_t { /// bit encoded list of properties that have been set by the driver device_properties_union_t set; /// maximum map upload (GMAPSUPP.IMG) size in bytes (0 for no upload) uint64_t memory_limit; /// maximum number of map tiles allowed for upload uint32_t maps_limit; /// maximum number of routes uint32_t routes_limit; /// maximum number of points in a route uint32_t route_pts_limit; /// maximum number of waypoints uint32_t waypts_limit; /// maximum number of tracks uint32_t tracks_limit; /// maximum number of track points uint32_t track_pts_limit; /// screen size uint32_t screenwidth, screenheight; /// screen pixel order uint32_t pixel_order; /// maximum number of POI uint32_t custom_POI_limit; /// official protocols uint32_t L_Link; uint32_t A_Cmd; uint32_t A_Wpt, D_Wpt[3]; uint32_t A_Prox_Wpt, D_Prox_Wpt[3]; uint32_t A_Rt, D_Rt[3]; uint32_t A_Trk, D_Trk[3]; uint32_t A_Pvt, D_Pvt[3]; /// inferred protocols uint32_t Q_Map_Limits; uint32_t Q_Map_Upload; uint32_t Q_Map_Info_Download; uint32_t Q_Screenshot; uint32_t Q_Custom_Icons; /// product_ID uint32_t product_ID; /// product_string const char * product_string; }; /// exception error code enum exce_e { errOpen ///< error during opening the link ,errSync ///< error during sync. up sequence ,errWrite ///< error during write access ,errRead ///< error during read access ,errNotImpl ///< error because of missing implementation ,errRuntime ///< error during operation ,errBlocked ///< error because access is blocked by another process }; /// exception type struct exce_t { exce_t(exce_e err, const std::string& msg) : err(err), msg(msg) {} exce_e err; std::string msg; }; /// interface class for device driver plugins /** This is the common interface to all devices. The application uses this definition to gain access to the plugin. Thus if you are an application programmer simply load the plugin, resolve and call the init function. The object you will get will be of type IDevice. There is no need to link against libgarmin.a. If you are a plugin programmer you will rather use IDeviceDefault, than IDevice. The inheritance chain will look like: IDevice -> IDefaultDevice -> CDevice Thus if you miss a public method you have to add it here as pure virtual and as a default implementation to IDeviceDefault. NOTE: If you change this interface you _must_ increment the version number defined by INTERFACE_VERSION. This is important to prevent crashes due to different interface definitions. Most likely your device driver will implement the protected methods with leading '_' of IDeviceDefault. */ class IDevice { public: IDevice() : _callback_(0), _self_(0){}; virtual ~IDevice(){}; /// setup gui callback for user interaction /** If you use the driver from a GUI you might want to react on some events or show the progress of the current operation. The registered callback will be for progress status as well as for user interaction depending on the parameters. The callback will require a progress dialog if the parameter "progress" is set to anthing else than -1. Developers using this callback to show a progress status should make sure: * The first call must have a progress of 0 and a title is set. * Subsequent calls have a progress from 0..100. The msg parameter can be set. * The last call must have a progress of 100. If you supply a pointer to a cancel variable from the first call on, you can cancel the operation if the value of the variable changes from 0 to 1. Developers implementing the callback function must make sure: * A progress of 0 will setup the progress dialog. Any subsequent progress of 0 is handled like any other progress. The dialog's title is set. If there is a pointer to a cancel variable the dialog should provide a way to cancel the operation. The dialog must make sure ther pointer is valid for subsequent calls. The operation is canceled if "*cancel = 1;" * Any subsequent call can have a message parameter, but it mustn't have one. * A progress of 100 should remove the progress dialog. There can be subsequent calls with a progress of 100. A progress of -1 will create a blocking message box. Depending on the pointers ok and cancel the dialog should show ok and cancel button. The integer variables will be set to true or false according to the button pressed. The supplied void pointer will be passed to every callback call and is free to be used by the GUI for what ever purpose it needs. */ void setGuiCallback(void (*func)(int /*progress*/, int * /*ok*/, int * /*cancel*/, const char * /*title*/, const char * /*msg*/, void * /*self*/), void * p) { _self_ = p; _callback_ = func; } /// upload a single map file to device /** This will handle just a single file. Map tiles must be concatenated into one big file (gmapsupp.img). If the file containes tiles with locked data an array of 25 ASCII digits has to be passed as key. @param mapdata pointer to the gmapsupp.img data array @param size the size of the gmapsupp.img data array @param key pointer to 25 digit key or 0 for no key */ virtual void uploadMap(const uint8_t * mapdata, uint32_t size, const char * key) = 0; /// alternative map uppload API /** This will handle just a single file. Map tiles must be concatenated into one big file (gmapsupp.img). If the file containes tiles with locked data an array of 25 ASCII digits has to be passed as key. @param mapdata pointer to the gmapsupp.img data array @param size the size of the gmapsupp.img data array @param key pointer to 25 digit key or 0 for no key */ virtual void uploadMap(const char * filename, uint32_t size, const char * key) = 0; /// query loaded map list /** This is not a real download of maps as just the information about the loaded maps is transfered. */ virtual void queryMap(std::list& maps) = 0; /// download waypoints from device /** @param waypoints list object to receive waypoints */ virtual void downloadWaypoints(std::list& waypoints) = 0; /// upload waypoints to device /** @param waypoints list of waypoints to send */ virtual void uploadWaypoints(std::list& waypoints) = 0; /// download track from device /** @param tracks list object to receive tracks */ virtual void downloadTracks(std::list& tracks) = 0; /// upload track to device /** @param tracks list of tracks to send */ virtual void uploadTracks(std::list& tracks) = 0; /// download routes from device /** @param routes list of routes */ virtual void downloadRoutes(std::list& routes) = 0; /// upload route to device /** @param routes list of routes */ virtual void uploadRoutes(std::list& routes) = 0; /// upload custom icons to device /** @param routes list of icons */ virtual void uploadCustomIcons(std::list& icons) = 0; /// download a screenshot from the device /** @param clrtbl a pointer reference to be set to the downloaded color table of size 0x100 @param data a pointer reference to be set to the downloaded image data array of size width x height @param width a integer reference to store the image width at @param height a integer reference to store the image height at */ virtual void screenshot(char *& clrtbl, char *& data, int& width, int& height) = 0; /// switch device into realtime position mode virtual void setRealTimeMode(bool on) = 0; /// request real time position virtual void getRealTimePos(Garmin::Pvt_t& pvt) = 0; /// get the device's properties. virtual void getDevProperties(Garmin::DevProperties_t& properties) = 0; /// get the copyright notice of this driver virtual const std::string& getCopyright() = 0; /// get reason string for last exception virtual const std::string& getLastError() = 0; /// set port string used for communication /** This should be called prior to an operation. As an operation will create a new ILink object, a changed port setting will apply imediately. If the ILink object does not need any port settings this value is ignored. */ virtual void setPort(const char * port) = 0; protected: /// see setGuiCallback() void (*_callback_)(int /*progress*/, int * /*ok*/, int * /*cancel*/, const char * /*title*/, const char * /*msg*/, void * /*self*/); /// see setGuiCallback() void * _self_; }; } #endif //IDEVICE_H garmindev-0.3.4+svn3432/src/Garmin.cpp0000644000175000017500000004150112002232272015753 0ustar miramira/* -*-mode:c++; c-style:k&r; c-basic-offset:4; -*- */ /********************************************************************************************** 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 #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #include "Garmin.h" #include "IDevice.h" #include #include #define INT32_TO_DEG(x) ((double)((int32_t)(x)) * 360.0 / 4294967296.0) #define DEG_TO_INT32(x) ((int32_t)((x) * 4294967296.0/360.0 + 0.5)) #define FLOAT64_TO_DEG(x) ((x) * 180.0/M_PI) namespace Garmin { // note: all D1xx_Wpt_t are properly aligned, so we can use the simple macros here void operator<<(Wpt_t& tar, const D108_Wpt_t& src) { tar.wpt_class = src.wpt_class; tar.dspl_color = src.color; tar.dspl_attr = src.dspl; tar.smbl = gar_endian(uint16_t, src.smbl); tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; tar.ete = 0; // not available const char* p = src.str; tar.ident = p; p += strlen(p) + 1; tar.comment = p; p += strlen(p) + 1; tar.facility = p; p += strlen(p) + 1; tar.city = p; p += strlen(p) + 1; tar.addr = p; p += strlen(p) + 1; tar.crossroad = p; } int operator>>(const Wpt_t& src, D108_Wpt_t& tar) { tar.wpt_class = src.wpt_class; tar.color = src.dspl_color; tar.dspl = src.dspl_attr; tar.attr = 0x60; // according to iop_spec.pdf tar.smbl = gar_endian(uint16_t, src.smbl); tar.subclass[0] = 0x00; tar.subclass[1] = 0x00; tar.subclass[2] = 0x00; tar.subclass[3] = 0x00; tar.subclass[4] = 0x00; tar.subclass[5] = 0x00; tar.subclass[6] = 0xFF; tar.subclass[7] = 0xFF; tar.subclass[8] = 0xFF; tar.subclass[9] = 0xFF; tar.subclass[10] = 0xFF; tar.subclass[11] = 0xFF; tar.subclass[12] = 0xFF; tar.subclass[13] = 0xFF; tar.subclass[14] = 0xFF; tar.subclass[15] = 0xFF; tar.subclass[16] = 0xFF; tar.subclass[17] = 0xFF; tar.lat = gar_endian(int32_t, DEG_TO_INT32(src.lat)); tar.lon = gar_endian(int32_t, DEG_TO_INT32(src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; char * pStr = tar.str; strcpy(pStr,src.ident.c_str()); pStr += src.ident.length() + 1; strcpy(pStr,src.comment.c_str()); pStr += src.comment.length() + 1; strcpy(pStr,src.facility.c_str()); pStr += src.facility.length() + 1; strcpy(pStr,src.city.c_str()); pStr += src.city.length() + 1; strcpy(pStr,src.addr.c_str()); pStr += src.addr.length() + 1; strcpy(pStr,src.crossroad.c_str()); pStr += src.crossroad.length() + 1; // size of packet return pStr - (char*)&tar.wpt_class; } void operator<<(Wpt_t& tar, const D109_Wpt_t& src) { tar.wpt_class = src.wpt_class; tar.dspl_color = src.dspl_color & 0x1F; tar.dspl_attr = (src.dspl_color & 0x70) >> 5; tar.smbl = gar_endian(uint16_t, src.smbl); tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; tar.ete = gar_endian(uint32_t, src.ete); const char* p = src.str; tar.ident = p; p += strlen(p) + 1; tar.comment = p; p += strlen(p) + 1; tar.facility = p; p += strlen(p) + 1; tar.city = p; p += strlen(p) + 1; tar.addr = p; p += strlen(p) + 1; tar.crossroad = p; } int operator>>(const Wpt_t& src, D109_Wpt_t& tar) { tar.dtyp = 0x01; tar.wpt_class = src.wpt_class; tar.dspl_color = (src.dspl_color | (src.dspl_attr << 5)) & 0x7F; tar.attr = 0x70; tar.smbl = gar_endian(uint16_t, src.smbl); tar.subclass[0] = 0x00; tar.subclass[1] = 0x00; tar.subclass[2] = 0x00; tar.subclass[3] = 0x00; tar.subclass[4] = 0x00; tar.subclass[5] = 0x00; tar.subclass[6] = 0xFF; tar.subclass[7] = 0xFF; tar.subclass[8] = 0xFF; tar.subclass[9] = 0xFF; tar.subclass[10] = 0xFF; tar.subclass[11] = 0xFF; tar.subclass[12] = 0xFF; tar.subclass[13] = 0xFF; tar.subclass[14] = 0xFF; tar.subclass[15] = 0xFF; tar.subclass[16] = 0xFF; tar.subclass[17] = 0xFF; tar.lat = gar_endian(int32_t, DEG_TO_INT32(src.lat)); tar.lon = gar_endian(int32_t, DEG_TO_INT32(src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; tar.ete = gar_endian(uint32_t, src.ete); char * pStr = tar.str; strcpy(pStr,src.ident.c_str()); pStr += src.ident.length() + 1; strcpy(pStr,src.comment.c_str()); pStr += src.comment.length() + 1; strcpy(pStr,src.facility.c_str()); pStr += src.facility.length() + 1; strcpy(pStr,src.city.c_str()); pStr += src.city.length() + 1; strcpy(pStr,src.addr.c_str()); pStr += src.addr.length() + 1; strcpy(pStr,src.crossroad.c_str()); pStr += src.crossroad.length() + 1; return pStr - (char*)&tar.dtyp; } void operator<<(Wpt_t& tar, const D110_Wpt_t& src) { tar.wpt_class = src.wpt_class; tar.dspl_color = src.dspl_color & 0x1F; tar.dspl_attr = (src.dspl_color & 0x60) >> 5; tar.smbl = gar_endian(uint16_t, src.smbl); tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; tar.ete = gar_endian(uint32_t, src.ete); tar.temp = gar_endian(float, src.temp); tar.time = gar_endian(uint32_t, src.time); tar.wpt_cat = gar_endian(uint16_t, src.wpt_cat); const char* p = src.str; tar.ident = p; p += strlen(p) + 1; tar.comment = p; p += strlen(p) + 1; tar.facility = p; p += strlen(p) + 1; tar.city = p; p += strlen(p) + 1; tar.addr = p; p += strlen(p) + 1; tar.crossroad = p; } int operator>>(const Wpt_t& src, D110_Wpt_t& tar) { tar.dtyp = 0x01; tar.wpt_class = src.wpt_class; tar.dspl_color = (src.dspl_color | (src.dspl_attr << 5)) & 0x7F; tar.attr = 0x80; tar.smbl = gar_endian(uint16_t, src.smbl); tar.subclass[0] = 0x00; tar.subclass[1] = 0x00; tar.subclass[2] = 0x00; tar.subclass[3] = 0x00; tar.subclass[4] = 0x00; tar.subclass[5] = 0x00; tar.subclass[6] = 0xFF; tar.subclass[7] = 0xFF; tar.subclass[8] = 0xFF; tar.subclass[9] = 0xFF; tar.subclass[10] = 0xFF; tar.subclass[11] = 0xFF; tar.subclass[12] = 0xFF; tar.subclass[13] = 0xFF; tar.subclass[14] = 0xFF; tar.subclass[15] = 0xFF; tar.subclass[16] = 0xFF; tar.subclass[17] = 0xFF; tar.lat = gar_endian(int32_t, DEG_TO_INT32(src.lat)); tar.lon = gar_endian(int32_t, DEG_TO_INT32(src.lon)); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); tar.dist = gar_endian(float, src.dist); tar.state[0] = src.state[0]; tar.state[1] = src.state[1]; tar.state[2] = 0; tar.cc[0] = src.cc[0]; tar.cc[1] = src.cc[1]; tar.cc[2] = 0; tar.ete = gar_endian(uint32_t, src.ete); tar.temp = gar_endian(float, src.temp); tar.time = gar_endian(uint32_t, src.time); tar.wpt_cat = gar_endian(uint16_t, src.wpt_cat); char * pStr = tar.str; strcpy(pStr,src.ident.c_str()); pStr += src.ident.length() + 1; strcpy(pStr,src.comment.c_str()); pStr += src.comment.length() + 1; strcpy(pStr,src.facility.c_str()); pStr += src.facility.length() + 1; strcpy(pStr,src.city.c_str()); pStr += src.city.length() + 1; strcpy(pStr,src.addr.c_str()); pStr += src.addr.length() + 1; strcpy(pStr,src.crossroad.c_str()); pStr += src.crossroad.length() + 1; return pStr - (char*)&tar.dtyp; } // same as D312, but without color=16=transparent void operator<<(Track_t& tar, const D310_Trk_Hdr_t& src) { tar.dspl = src.dspl; tar.color = src.color; tar.ident = src.ident; } void operator<<(Track_t& tar, const D311_Trk_Hdr_t& src) { std::stringstream strs; strs << int(src.ident); tar.ident = strs.str(); tar.ident= std::string(4-tar.ident.size(),'0')+tar.ident; //std::cout<<"track: "<< tar.ident<<" -- "<< tar.ident<>(const Track_t& src, D312_Trk_Hdr_t& tar) { tar.dspl = src.dspl; tar.color = src.color; char * pIdent = tar.ident; strcpy(pIdent,src.ident.c_str()); pIdent += src.ident.length() + 1; return pIdent - (char*)&tar.dspl; } void operator<<(TrkPt_t& tar, const D301_Trk_t& src) { tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.time = gar_endian(uint32_t, src.time); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); } void operator<<(TrkPt_t& tar, const D302_Trk_t& src) { tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.time = gar_endian(uint32_t, src.time); tar.alt = gar_endian(float, src.alt); tar.dpth = gar_endian(float, src.dpth); } int operator>>(const TrkPt_t& src, D302_Trk_t& tar) { tar.lat = gar_endian(int32_t, DEG_TO_INT32(src.lat)); tar.lon = gar_endian(int32_t, DEG_TO_INT32(src.lon)); tar.time = gar_endian(uint32_t, src.time); tar.alt = gar_endian(float, src.alt); // tar.dpth = gar_endian(float, src.dpth); return (char*)&tar.alt - (char*)&tar.lat + 1; } void operator<<(TrkPt_t& tar, const D304_Trk_t& src) { tar.lat = INT32_TO_DEG(gar_endian(int32_t, src.lat)); tar.lon = INT32_TO_DEG(gar_endian(int32_t, src.lon)); tar.time = gar_endian(uint32_t, src.time); tar.alt = gar_endian(float, src.alt); tar.distance = gar_endian(float, src.distance); tar.heart_rate = src.heart_rate; tar.cadence = src.cadence; //std::cout<< "----------src.lat:"<>(const Route_t& src, D202_Rte_Hdr_t& tar) { char * pStr = tar.ident; strcpy(pStr,src.ident.c_str()); return src.ident.size() + 1; } void operator<<(RtePt_t& tar, const D210_Rte_Link_t& src) { tar.rte_class = gar_endian(uint16_t, src.rte_class); tar.subclass_1 = gar_endian(uint16_t, src.subclass_1); tar.subclass_2 = gar_endian(uint32_t, src.subclass_2); tar.subclass_3 = gar_endian(uint32_t, src.subclass_3); tar.subclass_4 = gar_endian(uint32_t, src.subclass_4); tar.subclass_5 = gar_endian(uint32_t, src.subclass_5); tar.ident = src.ident; } int operator>>(const RtePt_t& src, D210_Rte_Link_t& tar) { tar.rte_class = gar_endian(uint16_t, src.rte_class); tar.subclass_1 = gar_endian(uint16_t, src.subclass_1); tar.subclass_2 = gar_endian(uint32_t, src.subclass_2); tar.subclass_3 = gar_endian(uint32_t, src.subclass_3); tar.subclass_4 = gar_endian(uint32_t, src.subclass_4); tar.subclass_5 = gar_endian(uint32_t, src.subclass_5); char * pStr = tar.ident; *pStr++ = 0; return pStr - (char*)&tar.rte_class; } int operator<<(Map_t& tar, const Map_Info_t& src) { const char * pStr = src.name1; tar.mapName = pStr; pStr += strlen(pStr) + 1; tar.tileName = pStr; // return the src record size uint16_t entry_size = gar_load(uint16_t, src.size); return sizeof(src.tok) + sizeof(src.size) + entry_size; } } garmindev-0.3.4+svn3432/src/CUSB_win32.cpp0000644000175000017500000002656312002232272016327 0ustar miramira/********************************************************************************************** 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 "CUSB.h" #include "IDevice.h" #include #include #include #include //#include #include #include // You may need to explicitly link with setupapi.lib #include // {2C9C45C2-8E7D-4C08-A12D-816BBAE722C0} DEFINE_GUID(GARMIN_GUID, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81, 0x6b, 0xba, 0xe7, 0x22, 0xc0); DEFINE_GUID(GUID_DEVINTERFACE_GRMNUSB, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81, 0x6b, 0xba, 0xe7, 0x22, 0xc0); #define IOCTL_ASYNC_IN CTL_CODE (FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_USB_PACKET_SIZE CTL_CODE (FILE_DEVICE_UNKNOWN, 0x851, METHOD_BUFFERED, FILE_ANY_ACCESS) #define MAX_BUFFER_SIZE 4096 #define ASYNC_DATA_SIZE 64 using namespace Garmin; using namespace std; #define GUSB_DATA_AVAILABLE 2 #define GUSB_SESSION_START 5 #define GUSB_SESSION_STARTED 6 #undef DBG #define DBG_LINE_SIZE 16 CUSB::CUSB() : busses(0) , udev(0) //, theInterface(-1) , max_tx_size(0) , epBulkIn(-1) , epBulkOut(-1) , epIntrIn(-1) , doBulkRead(false) , productId(0) , softwareVersion(0) { } CUSB::~CUSB() { close(); } void CUSB::open() { // Make all the necessary Windows calls to get a handle // to our USB device DWORD theBytesReturned = 0; PSP_INTERFACE_DEVICE_DETAIL_DATA theDevDetailData = 0; SP_DEVINFO_DATA theDevInfoData = { sizeof( SP_DEVINFO_DATA ) }; Packet_t theStartSessionPacket = Packet_t(0,5); Packet_t thePacket = Packet_t(); HDEVINFO theDevInfo; // SP_DEVICE_INTERFACE_DATA devinterface; theDevInfo = ::SetupDiGetClassDevs( (GUID *) &GARMIN_GUID, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if (theDevInfo == INVALID_HANDLE_VALUE) { throw exce_t(errOpen,"Is the Garmin USB driver installed?"); } SP_DEVICE_INTERFACE_DATA theInterfaceData; theInterfaceData.cbSize = sizeof( theInterfaceData ); if( !SetupDiEnumDeviceInterfaces( theDevInfo, NULL, (GUID*) &GUID_DEVINTERFACE_GRMNUSB, 0, &theInterfaceData ) && GetLastError() == ERROR_NO_MORE_ITEMS ) { udev = 0; return; } SetupDiGetDeviceInterfaceDetail( theDevInfo, &theInterfaceData, NULL, 0, &theBytesReturned, NULL ); theDevDetailData = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc( theBytesReturned ); theDevDetailData->cbSize = sizeof( SP_INTERFACE_DEVICE_DETAIL_DATA ); SetupDiGetDeviceInterfaceDetail( theDevInfo, &theInterfaceData, theDevDetailData, theBytesReturned, NULL, &theDevInfoData ); udev = CreateFile( theDevDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); free( theDevDetailData ); if(udev == NULL) { throw exce_t(errOpen,"Is the unit connected?"); } if(udev == INVALID_HANDLE_VALUE) { throw exce_t(errOpen,"The unit seems to be connected with something else?"); } // Get the USB packet size, which we need for sending packets gUSBPacketSize = 0; DeviceIoControl( udev, IOCTL_USB_PACKET_SIZE, 0, 0, &gUSBPacketSize, sizeof( gUSBPacketSize ), &theBytesReturned, NULL ); // Tell the device that we are starting a session. /* write( theStartSessionPacket ); // Wait until the device is ready to start the session for( ; ; ) { read( thePacket ); if( thePacket.type == 0 && thePacket.id == 6 ) { break; } // free( thePacket ); } // free( thePacket ); */ } void CUSB::close() { if(udev) { CloseHandle(udev); udev = 0; } } void CUSB::close2() { if(udev) { CloseHandle(udev); udev = 0; } } void CUSB::debug(const char * mark, const Packet_t& data) { #ifndef DBG return; #endif unsigned i; uint32_t size; unsigned bytes = DBG_LINE_SIZE; char buf[DBG_LINE_SIZE + 1]; memset(buf,0x20,sizeof(buf));buf[DBG_LINE_SIZE] = 0; cout << mark << endl << " "; const uint8_t * pData = (const uint8_t*)&data; size = data.size; if(size > GUSB_MAX_BUFFER_SIZE) { cerr << "WARNING! Data size " << data.size << " exceeds buffer size." << endl; cerr << "Truncate to " << GUSB_MAX_BUFFER_SIZE << "." << endl; size = GUSB_PAYLOAD_SIZE; } for(i = 0; i < (size + GUSB_HEADER_SIZE); ++i) { if(i && !(i % DBG_LINE_SIZE)) { cout << " " << buf << endl << " "; memset(buf,0x20,sizeof(buf));buf[DBG_LINE_SIZE] = 0; bytes = DBG_LINE_SIZE; } cout.width(2); cout.fill('0'); cout << hex << (unsigned)pData[i] << " "; if(isprint(pData[i])) { buf[i%DBG_LINE_SIZE] = pData[i]; } else { buf[i%DBG_LINE_SIZE] = '.'; } --bytes; } for(i=0; i < bytes; i++) cout << " "; cout << " " << buf << dec << endl; } int CUSB::read(Packet_t& data) { int res=0; data.type = 0; data.id = 0; data.size = 0; DWORD theBytesReturned = 0; BOOL ok = true; if(doBulkRead) { ok = ReadFile( udev, &data, MAX_BUFFER_SIZE, &theBytesReturned, NULL ); if ( theBytesReturned <= 0 ) doBulkRead = false; #ifdef WIN_DEBUG FILE *fp = NULL; fp = fopen( "report.txt","a"); if (fp != NULL) { fprintf(fp,"CUSB::read bulk type=%d, id=%d, ret=%d\n",data.type,data.id,theBytesReturned); fclose(fp); } #endif // WIN_DEBUG } else { DeviceIoControl( udev, IOCTL_ASYNC_IN, 0, 0, &data, ASYNC_DATA_SIZE, &theBytesReturned, NULL ); if( data.type == 0 && data.id == GUSB_DATA_AVAILABLE ) { doBulkRead = true; data.type = 0; data.id = 0; ok = ReadFile( udev, &data, MAX_BUFFER_SIZE, &theBytesReturned, NULL ); } } if ( !ok ) { stringstream msg; msg << "USB ReadFile failed:" ; throw exce_t(errRead,msg.str()); } /* // Some devices sending data on the interrupt pipe seem // to timeout occasionally. It seems to be save to ignore this // timeout. if(res == -ETIMEDOUT && !doBulkRead){ res = 0; } // switch to bulk pipe if((res > 0) && (data.id == GUSB_DATA_AVAILABLE)){ doBulkRead = true; } // switch to interrupt pipe on errors or zero size packages if(res <= 0){ doBulkRead = false; } */ res = 1; return res; } void CUSB::write(const Packet_t& data) { // unsigned l = sizeof(data); DWORD theBytesToWrite = GUSB_HEADER_SIZE + data.size; DWORD theBytesReturned = 0; WriteFile( udev, &data, theBytesToWrite, &theBytesReturned, NULL ); if ( theBytesReturned != theBytesToWrite ) { stringstream msg; msg << "USB bulk write failed:" ; throw exce_t(errWrite,msg.str()); } // If the packet size was an exact multiple of the USB packet // size, we must make a final write call with no data if( theBytesToWrite % gUSBPacketSize == 0 ) { WriteFile( udev, 0, 0, &theBytesReturned, NULL ); } } void CUSB::start(struct usb_device *dev) { if(udev) return; if(udev == 0) { stringstream msg; msg << "Failed to open USB device: " ; throw exce_t(errOpen,msg.str()); } } void CUSB::syncup(void) { static const Packet_t gpack_session_start(GUSB_PROTOCOL_LAYER,GUSB_SESSION_START); Packet_t response; protocolArraySize = 0; write(gpack_session_start); read(response); if(response.id == GUSB_SESSION_STARTED) { Packet_t command; Packet_t response; command.type = GUSB_APPLICATION_LAYER; command.b1 = 0; command.b2 = 0; command.b3 = 0; command.id = Pid_Product_Rqst; command.b6 = 0; command.b7 = 0; command.size = 0; write(command); while(read(response)) { if(response.id == Pid_Product_Data) { //TODO read data Product_Data_t * pData = (Product_Data_t*)response.payload; productId = pData->product_id; softwareVersion = pData->software_version; productString = pData->str; #ifdef DBG cout << hex << productId << " " << dec << softwareVersion << " " << productString << endl; #endif } if(response.id == Pid_Ext_Product_Data) { //TODO read data } // This should mark the end if(response.id == Pid_Protocol_Array) { //TODO read data Protocol_Data_t * pData = (Protocol_Data_t*)response.payload; for(uint32_t i = 0; i < response.size; i += sizeof(Protocol_Data_t)) { #ifdef WIN_DEBUG qDebug() << "Protocol: "<< (char)pData->tag << dec << pData->data << endl; #endif ++protocolArraySize; protocolArray[protocolArraySize].tag = pData->tag; protocolArray[protocolArraySize].data = pData->data; ++pData; } ++protocolArraySize; #ifdef WIN_DEBUG qDebug() << "protocolArraySize:" << protocolArraySize << endl; #endif return; // let's leave, even so it is a strange ending } } return; } throw exce_t(errSync,"Failed to sync. up with device"); } uint16_t CUSB::getDataType(int data_no, char tag, uint16_t protocol) { // Find the right tag D for for (uint32_t i=0; i < protocolArraySize-1-data_no; i++) { if ((char)protocolArray[i].tag == tag) { if (protocolArray[i].data == protocol) { // accept data_no=-1 as a protocol verification only if (data_no == -1) return (uint16_t) 1; if ((char)protocolArray[i+1+data_no].tag == 'D') { return protocolArray[i+1+data_no].data; } } } } return (uint16_t) 0; } garmindev-0.3.4+svn3432/src/Garmin.h0000644000175000017500000002157312002232272015427 0ustar miramira /********************************************************************************************** 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. **********************************************************************************************/ #ifndef GARMIN_H #define GARMIN_H #include #include "Platform.h" namespace Garmin { #pragma pack(1) /* * Important notice: The packed structs below contain data in little endian, and accessing * them directly may fail if the machine does not support unaligned accesses. Either use * the overloaded operators << and >> to move the data into the properly aligned internal * structures or access the data using the macros from ../Platform.h. */ // note: no << or >> operator available, be sure to access the fields properly struct Product_Data_t { uint16_t product_id; int16_t software_version; char str[1]; }; // note: no << or >> operator available, be sure to access the fields properly struct Protocol_Data_t { uint8_t tag; uint16_t data; }; struct D108_Wpt_t { uint8_t wpt_class; uint8_t color; uint8_t dspl; uint8_t attr; uint16_t smbl; uint8_t subclass[18]; int32_t lat; int32_t lon; float alt; float dpth; float dist; char state[2]; char cc[2]; char str[1]; }; struct D109_Wpt_t { uint8_t dtyp; uint8_t wpt_class; uint8_t dspl_color; uint8_t attr; uint16_t smbl; uint8_t subclass[18]; int32_t lat; int32_t lon; float alt; float dpth; float dist; char state[2]; char cc[2]; uint32_t ete; char str[1]; }; struct D110_Wpt_t { uint8_t dtyp; uint8_t wpt_class; uint8_t dspl_color; uint8_t attr; uint16_t smbl; uint8_t subclass[18]; int32_t lat; int32_t lon; float alt; float dpth; float dist; char state[2]; char cc[2]; uint32_t ete; float temp; uint32_t time; uint16_t wpt_cat; char str[1]; }; struct D202_Rte_Hdr_t { char ident[1]; }; struct D210_Rte_Link_t { uint16_t rte_class; uint16_t subclass_1; uint32_t subclass_2; uint32_t subclass_3; uint32_t subclass_4; uint32_t subclass_5; char ident[1]; }; struct D301_Trk_t { int32_t lat; int32_t lon; uint32_t time; float alt; float dpth; uint8_t new_trk; }; struct D302_Trk_t { int32_t lat; int32_t lon; uint32_t time; float alt; float dpth; float temp; uint8_t new_trk; }; struct D304_Trk_t { int32_t lat; int32_t lon; uint32_t time; float alt; // 32 float distance; uint8_t heart_rate; uint8_t cadence; uint8_t sensor; }; // same as D312, but without color=16=transparent struct D310_Trk_Hdr_t { uint8_t dspl; uint8_t color; char ident[1]; }; struct D311_Trk_Hdr_t { uint16_t ident; }; struct D312_Trk_Hdr_t { uint8_t dspl; uint8_t color; char ident[1]; }; // note: no << or >> operator available, be sure to access the fields properly struct Map_Request_t { uint32_t dummy1; uint16_t dummy2; char section[13]; }; struct Map_Info_t { uint8_t tok; ///< should be 0x4c uint16_t size; ///< total entry size will be size + sizeof(tok) + sizeof(size) uint16_t product; ///< product code as it can be found in the registry uint16_t dummy; ///< country / char. set? uint32_t mapId; ///< same id as in tdb and map filename char name1[1]; /* There are several 0 terminated strings: "map name" "tile name" */ }; /* quint32 ??? ///< the map id as it is used in the FAT table quint32 ??? ///< always 0x00000000 (end token?) */ struct D800_Pvt_Data_t { float alt; float epe; float eph; float epv; uint16_t fix; double tow; double lat; double lon; float east; float north; float up; float msl_hght; int16_t leap_scnds; uint32_t wn_days; }; #pragma pack() // --------------------------------------------------------------------------------------- enum serial_e { Pid_Ack_Byte = 6 ,Pid_Nak_Byte = 21 }; enum L000_e { Pid_Protocol_Array = 253 ,Pid_Product_Rqst = 254 ,Pid_Product_Data = 255 ,Pid_Ext_Product_Data = 248 }; enum L001_e { Pid_Command_Data = 10 //0x0C ,Pid_Xfer_Cmplt = 12 ,Pid_Prx_Wpt_Data = 19 ,Pid_Wpt_Data = 35 //0x1B ,Pid_Records = 27 //0x1D ,Pid_Rte_Hdr = 29 //0x1E ,Pid_Rte_Wpt_Data = 30 ,Pid_Trk_Data = 34 ,Pid_Pvt_Data = 51 //???? ,Pid_Capacity_Data = 95 //0x62 ,Pid_Rte_Link_Data = 98 ,Pid_Trk_Hdr = 99 //???? ,Pid_Tx_Unlock_Key = 108 //???? ,Pid_Ack_Unlock_key = 109 ,Pid_Req_Icon_Id = 0x371 ,Pid_Ack_Icon_Id = 0x372 ,Pid_Req_Clr_Tbl = 0x376 ,Pid_Ack_Clr_Tbl = 0x377 ,Pid_Icon_Data = 0x375 ,Pid_Ack_Icon_Data = 0x374 }; enum A010_e { Cmnd_Abort_Transfer = 0 ,Cmnd_Transfer_Prx = 3 ,Cmnd_Transfer_Rte = 4 ,Cmnd_Transfer_Trk = 6 ,Cmnd_Transfer_Wpt = 7 ,Cmnd_Transfer_Mem = 63 ,Cmnd_Start_Pvt_Data = 49 ,Cmnd_Stop_Pvt_Data = 50 }; struct Wpt_t; extern void operator<<(Wpt_t& tar, const D108_Wpt_t& src); extern int operator>>(const Wpt_t& src, D108_Wpt_t& tar); extern void operator<<(Wpt_t& tar, const D109_Wpt_t& src); extern int operator>>(const Wpt_t& src, D109_Wpt_t& tar); extern void operator<<(Wpt_t& tar, const D110_Wpt_t& src); extern int operator>>(const Wpt_t& src, D110_Wpt_t& tar); struct Track_t; struct TrkPt_t; extern void operator<<(Track_t& tar, const D310_Trk_Hdr_t& src); extern void operator<<(Track_t& tar, const D311_Trk_Hdr_t& src); extern void operator<<(Track_t& tar, const D312_Trk_Hdr_t& src); extern int operator>>(const Track_t& src, D312_Trk_Hdr_t& tar); extern void operator<<(TrkPt_t& tar, const D301_Trk_t& src); extern void operator<<(TrkPt_t& tar, const D302_Trk_t& src); extern void operator<<(TrkPt_t& tar, const D304_Trk_t& src); extern int operator>>(const TrkPt_t& src, D302_Trk_t& tar); struct Pvt_t; extern void operator<<(Pvt_t& tar, const D800_Pvt_Data_t& src); struct Route_t; extern void operator<<(Route_t& tar, const D202_Rte_Hdr_t& src); extern int operator>>(const Route_t& src, D202_Rte_Hdr_t& tar); struct RtePt_t; extern void operator<<(RtePt_t& tar, const D210_Rte_Link_t& src); extern int operator>>(const RtePt_t& src, D210_Rte_Link_t& tar); struct Map_t; extern int operator<<(Map_t& tar, const Map_Info_t& src); } #endif //GARMIN_H garmindev-0.3.4+svn3432/src/CSerial.cpp0000644000175000017500000005306112002232272016064 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de Cleanups and godparenthood by Frank Seidel (fseidel@suse.de, frank@f-seidel.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. **********************************************************************************************/ #ifdef WIN32 // because of filename of com-port #undef UNICODE #endif #include "CSerial.h" #include "IDevice.h" #include "Platform.h" #include #include #include #include #include #include #include #include #ifdef WIN32 #include #endif using namespace Garmin; using namespace std; #undef DBG #define DBG_LINE_SIZE 16 #define SERIAL_PACKET_MAX_SIZE 255 #define DLE 16 #define ETX 3 CSerial::CSerial(const std::string& port) #ifdef WIN32 : hCom(0) #else : port_fd(-1) #endif , productId(0) , softwareVersion(0) , protocolArraySize(-1) , port(port) , readtimeout_ms( 1000) { #ifdef WIN32 #else FD_ZERO(&fds_read); #endif } CSerial::~CSerial() { CSerial::close(); } #ifdef WIN32 void CSerial::open() { #if defined(HAVE_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 // use for example \\.\COM10 for higher ports hCom= CreateFile( port.c_str(), 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()); } // set buffer sizes if( !SetupComm( hCom, 600, 600)) { stringstream msg; msg << "Failed to set buffersize for " << port.c_str(); throw exce_t(errOpen,msg.str()); } // get default values if( !GetCommState( hCom, &dcb)) { 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(HAVE_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; port_fd = ::open(port.c_str(), O_RDWR); if (port_fd < 0) { stringstream msg; msg << "Failed to open serial device " << port.c_str(); throw exce_t(errOpen,msg.str()); } if (tcgetattr(port_fd, &gps_ttysave) < 0) { stringstream msg; msg << "Failed to get parameters for " << port.c_str(); throw exce_t(errOpen,msg.str()); } memset(&tty, 0, sizeof(tty)); tty.c_cflag &= ~CSIZE; tty.c_cflag |= ( CREAD | CS8 | CLOCAL ); tty.c_lflag = 0; tty.c_iflag = 0; tty.c_oflag = 0; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; if ( cfsetispeed( &tty, B9600 ) == -1 ) cout << "WARNING: CSerial could not set initial input baud rate" << endl; if ( cfsetospeed( &tty, B9600 ) == -1 ) cout << "WARNING: CSerial could not set initial output baud rate" << endl; if(tcsetattr(port_fd, TCSANOW, &tty) < 0) { stringstream msg; msg << "Failed to set parameters for " << port.c_str(); throw exce_t(errOpen,msg.str()); } FD_SET(port_fd, &fds_read); // tcgetattr, cfgetispeed, cfgetospeed should get called and every parameter checked! // 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); } #endif void CSerial::debug(const char * /*mark*/, const Packet_t& /*data*/) { #ifndef DBG return; #else unsigned i; unsigned bytes = DBG_LINE_SIZE; char buf[DBG_LINE_SIZE + 1]; memset(buf,0x20,sizeof(buf)); buf[DBG_LINE_SIZE] = 0; cout << mark << endl << " "; const uint8_t * pData = (const uint8_t*)&data; for(i = 0; i < (data.size + GUSB_HEADER_SIZE); ++i) { if(i && !(i % DBG_LINE_SIZE)) { cout << " " << buf << endl << " "; memset(buf,0x20,sizeof(buf));buf[DBG_LINE_SIZE] = 0; bytes = DBG_LINE_SIZE; } cout.width(2); cout.fill('0'); cout << hex << (unsigned)pData[i] << " "; if(isprint(pData[i])) { buf[i%DBG_LINE_SIZE] = pData[i]; } else { buf[i%DBG_LINE_SIZE] = '.'; } --bytes; } for(i = 0; i < bytes; i++) cout << " "; cout << " " << buf << dec << endl; #endif } // input: packet // returns: <0 error, 0= nothing received, >0 count of data 0..255 int CSerial::read(Packet_t& data) { int res; data.type = 0; data.id = 0; data.size = 0; res = serial_read(data, readtimeout_ms); if (res > 0) serial_send_ack(data.id); return res; } // input: packet // returns: <0 error, 0= nothing received, >0 count of data 0..255 int CSerial::read(char* data) { uint8_t byte; int bytes_received = 0; while (serial_char_read( &byte, readtimeout_ms)) { data[bytes_received++] = byte; if (byte == 10) //read until carriage return 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) { serial_write(data); if (serial_check_ack(data.id)) { 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"); } } // in: bitrate, example: 115200 // returns: 0=success, <0 error int CSerial::setBitrate(uint32_t bitrate) { // 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; #ifdef WIN32 DCB dcb; #else struct termios tty; speed_t speed = B9600; switch (bitrate) { case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: // throw "unsupported bitrate"; 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 (CSerial::read(response)) { if (response.id == 0x31 && response.size == 4) { device_bitrate = *(uint32_t*)response.payload; break; } } //check if speed is ok for unit if (bitrate * 1.02 < device_bitrate || bitrate > device_bitrate * 1.02) { cout << "WARNING: Bitrate not supported or differs too much" << endl; cout << bitrate << " chosen, device wants " << device_bitrate << endl; cout << "please report this problem to the author of your units driver" << endl; return -1; // FIXME: throw warning } #ifdef WIN32 Sleep( 100); // get default values if( !GetCommState( hCom, &dcb)) { cerr << "error getting port state" << endl; return( -1); } dcb.BaudRate= bitrate; 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); cerr << "Changing speed to " << bitrate << endl; if(tcsetattr(port_fd, TCSADRAIN, &tty) < 0) { // throw "Failed to set parameters/bitrate for serial port"; return -1; } #endif CSerial::write(pingpacket); CSerial::write(pingpacket); CSerial::write(pingpacket); return 0; } int CSerial::syncup(int responseCount) { Packet_t command; Packet_t response; /* speed improvement when remembering last numer of packets to this request as we will not run in long timeout if syncup should be called a second time */ static int last_response = 0; int counter = 0; if (!last_response && responseCount > 0) last_response = responseCount; command.type = 0; command.id = Pid_Product_Rqst; command.size = 0; CSerial::write(command); protocolArraySize = 0; while(CSerial::read(response)) { if(response.id == Pid_Product_Data) { //TODO read data Product_Data_t * pData = (Product_Data_t*)response.payload; productId = pData->product_id; softwareVersion = pData->software_version; productString = pData->str; #ifdef DBG cout << hex << productId << " " << dec << softwareVersion << " " << productString << endl; #endif } /* TODO if(response.id == Pid_Ext_Product_Data){ //TODO read data } */ if(response.id == Pid_Protocol_Array) { //TODO read data Protocol_Data_t * pData = (Protocol_Data_t*)response.payload; for(uint32_t i = 0; i < response.size; i += sizeof(Protocol_Data_t)) { #ifdef DBG cout << "Protocol: "<< (char)pData->tag << dec << pData->data << endl; #endif ++protocolArraySize; protocolArray[protocolArraySize].tag = pData->tag; protocolArray[protocolArraySize].data = pData->data; ++pData; } ++protocolArraySize; #ifdef DBG cout << "protocolArraySize:" << protocolArraySize << endl; #endif } ++counter; if (last_response && counter == last_response) break; } if (!last_response) last_response = counter; return counter; } //******************************************************************** // garmin daten entsprechend linkprotokoll verpacken: // DLE, packet_ID, Size, 0-255 bytes, checksum, DLE, ETX // If any byte in size/data/checksum is DLE (16dez) -> insert add DLE void CSerial::serial_write(const Packet_t& data) { static uint8_t buff[(SERIAL_PACKET_MAX_SIZE * 2) + 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; return; } buff[0] = (uint8_t) DLE; checksum -= (uint8_t) data.id; buff[1] = (uint8_t) data.id; // packet id // DLE stuffing not needed with packed id, according to iop_spec.pdf checksum -= (uint8_t) data.size; // packet size buff[2] = (uint8_t) data.size; if (buff[2] == DLE) { buff[3] = (uint8_t) DLE; bindex++; } for (i = 0; i < (int) data.size; ++i) { checksum -= (uint8_t) data.payload[i]; buff[bindex] = data.payload[i]; if (buff[bindex++] == DLE) buff[bindex++] = (uint8_t) DLE; } buff[bindex] = checksum; if (buff[bindex++] == DLE) buff[bindex++] = (uint8_t) DLE; 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); if (res < 0) cerr << "serial write failed" << endl; else if (res != bindex) cerr << "serial write was incomplete!" << endl; // FIXME: todo I don't know if this is applicable to serial connections #if 0 /* The Garmin protocol requires that packets that are exactly a multiple of the max tx size be followed by a zero length packet. */ if (size && !(size % max_tx_size)) { ::usb_bulk_write(udev,epBulkOut,(char*)&data,0,3000); #ifdef DBG cout << "b << zero size packet to terminate" << endl; #endif } if (res < 0) { stringstream msg; msg << "Serial write failed"; // FIXME: throw msg.str().c_str(); } #endif } #ifdef WIN32 int CSerial::serial_char_read( uint8_t *byte, unsigned milliseconds) { DWORD result; DWORD BytesRead; 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; // 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)) { //ready in time 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 FD_SET(port_fd, &fds_read); return 0; } #endif // check for ack for command cmd // 0 = success, <0 = error int CSerial::serial_check_ack(uint8_t cmd) { Packet_t response; int count; 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'; } } return -1; // no input data } // ack senden void CSerial::serial_send_ack(uint8_t cmd) { static Packet_t ack_packet(0,Pid_Ack_Byte); ack_packet.payload[0] = cmd; ack_packet.payload[1] = (uint8_t) 0; ack_packet.size = 2; serial_write(ack_packet); } // nak senden void CSerial::serial_send_nak(uint8_t cmd) { static Packet_t nak_packet(0,Pid_Nak_Byte); nak_packet.payload[0] = cmd; nak_packet.payload[1] = (uint8_t) 0; nak_packet.size = 2; serial_write(nak_packet); // FIXME: cout << endl << "sent nak_packet" << endl; } // garmin daten entsprechend linkprotokoll auspacken: // returns received bytecount of data (0..255) int CSerial::serial_read(Packet_t& data, unsigned milliseconds) { uint8_t byte; int check_for_dledle = 0; // next byte should be DLE // without inserted "double" DLEs unsigned int bytes_received = 0; uint8_t checksum = 0; int i = 0; int ready = 0; data.type = 0; data.id = 0; data.size = 0; while (serial_char_read( &byte, milliseconds)) { // this one first if (check_for_dledle) { if (DLE == byte) { check_for_dledle = 0; } else { cout << endl << "ERROR: DLE stuffing error" << endl; return -1; // FIXME: protocol error } } else if (0 == bytes_received) { if (byte == DLE) { bytes_received++; } else { cout << endl << "ERROR: start byte isn't DLE" << endl; return -1; // FIXME: protocol error } } else if (1 == bytes_received) { data.id = byte; bytes_received++; checksum -= byte; } else if (2 == bytes_received) { data.size = byte; bytes_received++; checksum -= byte; if (DLE == byte) { check_for_dledle = 1; } } // databytes else if (bytes_received < data.size + 3) { data.payload[i] = byte; i++; bytes_received++; checksum -= byte; if (DLE == byte) { check_for_dledle = 1; } } // checksum else if (bytes_received == data.size + 3) { bytes_received++; if (checksum != byte) { cout << endl << "ERROR: checksum wrong" << endl; return -1; // FIXME: checksum error } if (DLE == byte) { check_for_dledle = 1; } } // DLE else if (bytes_received == data.size + 4) { if (byte == DLE) { bytes_received++; } else { cout << endl << "ERROR: end byte1 isn't DLE" << endl; return -1; // FIXME: protocol error } } // ETX else if (bytes_received == data.size + 5) { 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 debug("r >>", data); if (!ready) { data.id = 0; data.size = 0; } return static_cast(data.size); } uint16_t CSerial::getDataType(int data_no, char tag, uint16_t protocol) { // Find the right tag D for for (uint32_t i=0; i < protocolArraySize-1-data_no; i++) { if ((char)protocolArray[i].tag == tag) { if (protocolArray[i].data == protocol) { // accept data_no=-1 as a protocol verification only if (data_no == -1) return (uint16_t) 1; if ((char)protocolArray[i+1+data_no].tag == 'D') { return protocolArray[i+1+data_no].data; } } } } return (uint16_t) 0; } void CSerial::readTimeout( uint32_t milliseconds) { readtimeout_ms= milliseconds; } garmindev-0.3.4+svn3432/src/IDeviceDefault.h0000644000175000017500000001330612002232272017022 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef IDEVICEDEFAULT_H #define IDEVICEDEFAULT_H #include #include #include "IDevice.h" namespace Garmin { /// default implementation of a device driver /** Please refer to IDevice for documentation on the public interface. The default implementation of all methods is to throw an exception, to signal that a real implementation is missing. If your device lacks a ceratin feature simply do not implement the corresponding '_' method. */ class IDeviceDefault : public IDevice { public: IDeviceDefault(); virtual ~IDeviceDefault(); /// see IDevice::uploadMap() virtual void uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); virtual void uploadMap(const char * filename, uint32_t size, const char * key); /// see IDevice::queryMap() virtual void queryMap(std::list& maps); /// see IDevice::downloadWaypoints() virtual void downloadWaypoints(std::list& waypoints); /// see IDevice::uploadWaypoints() virtual void uploadWaypoints(std::list& waypoints); /// see IDevice::downloadTracks() virtual void downloadTracks(std::list& tracks); /// see IDevice::uploadTracks() virtual void uploadTracks(std::list& tracks); /// see IDevice::downloadRoutes() virtual void downloadRoutes(std::list& routes); /// see IDevice::uploadRoutes() virtual void uploadRoutes(std::list& routes); /// see IDevice::uploadCustomIcons() virtual void uploadCustomIcons(std::list& icons); /// see IDevice::screenshot() virtual void screenshot(char *& clrtbl, char *& data, int& width, int& height); /// see IDevice::setRealTimeMode() virtual void setRealTimeMode(bool on); /// see IDevice::getRealTimePos() virtual void getRealTimePos(Garmin::Pvt_t& pvt); /// see IDevice::getDevProperties() virtual void getDevProperties(Garmin::DevProperties_t& dev_properties); /// see IDevice::getCopyright() virtual const std::string& getCopyright(); /// see IDevice::getLastError() virtual const std::string& getLastError(); /// see IDevice::setPort() virtual void setPort(const char * p); /// device interface access mutex pthread_mutex_t mutex; protected: virtual void _acquire() = 0; virtual void _uploadMap(const uint8_t * mapdata, uint32_t size, const char * key); virtual void _uploadMap(const char * filename, uint32_t size, const char * key); virtual void _queryMap(std::list& maps); virtual void _downloadWaypoints(std::list& waypoints); virtual void _uploadWaypoints(std::list& waypoints); virtual void _downloadTracks(std::list& tracks); virtual void _uploadTracks(std::list& tracks); virtual void _downloadRoutes(std::list& routes); virtual void _uploadRoutes(std::list& routes); virtual void _uploadCustomIcons(std::list& icons); virtual void _screenshot(char *& clrtbl, char *& data, int& width, int& height); virtual void _setRealTimeMode(bool on); virtual void _getRealTimePos(Garmin::Pvt_t& pvt); virtual void _getDevProperties(Garmin::DevProperties_t& dev_properties); virtual void _release() = 0; void callback(int progress, int * ok, int * cancel, const char * title, const char * msg); /// the copyright information std::string copyright; /// error message of last error std::string lasterror; /// serial port string std::string port; /// device properties Garmin::DevProperties_t properties; }; class CMutexLocker { public: CMutexLocker(pthread_mutex_t& mutex) : mutex(mutex) { if(pthread_mutex_trylock(&mutex) == EBUSY) throw exce_t(errBlocked,"Access is blocked by another function."); } ~CMutexLocker() { pthread_mutex_unlock(&mutex); } private: pthread_mutex_t& mutex; }; } #endif //IDEVICEDEFAULT_H garmindev-0.3.4+svn3432/src/CSerial.h0000644000175000017500000000736512002232272015537 0ustar miramira/********************************************************************************************** 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. **********************************************************************************************/ #ifndef CSERIAL_H #define CSERIAL_H #include #ifdef WIN32 #include #else #include #endif #include #include #include //#include #include "ILink.h" #include "Garmin.h" namespace Garmin { /// Garmin's serial protocol /** This should be kept common to all serial devices. However if your device does not fit into the protocol implementation at all, subclass it and make your fixes. */ class CSerial : public ILink { 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() void write(const Packet_t& data); /// sync. up sequence /** This must be called prior to any other request. @param responseCount Number of response packets to expect @return Actual retrieved number of response packets to product_request */ virtual int syncup(int responseCount = 0); int read(char *data); uint16_t getProductId(){return productId;} int16_t getSoftwareVersion(){return softwareVersion;} const std::string& getProductString(){return productString;} uint16_t getDataType(int data_no, char tag, uint16_t protocol); // in: bitrate, example: 115200 // returns: 0=success, <0 error int setBitrate( uint32_t bitrate); void readTimeout( uint32_t milliseconds); protected: 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); void serial_send_ack( uint8_t cmd); void serial_send_nak( uint8_t cmd); 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; int interface; #endif uint16_t productId; int16_t softwareVersion; std::string productString; uint32_t protocolArraySize; Protocol_Data_t protocolArray[GUSB_PAYLOAD_SIZE]; std::string port; uint32_t readtimeout_ms; }; } #endif //CSERIAL_H garmindev-0.3.4+svn3432/src/CTcp.cpp0000644000175000017500000001362312002232272015373 0ustar miramira/********************************************************************************************** Copyright (C) 2007 Juan Pablo Daniel Borgna jpdborgna@e-mips.com.ar 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 "CTcp.h" #include "IDevice.h" #include "Platform.h" #include #include #include #include #ifndef WIN32 #include #include #include #include #endif #include using namespace Garmin; using namespace std; #undef DBG #define DBG_LINE_SIZE 16 #define MAX_SIZE 255 #define TIMEOUT 5 static int my_close( int fd) { return( close( fd)); } static ssize_t my_read(int fd, void *buf, size_t count) { return( recv( fd, (char *) buf, count,0)); } static ssize_t my_write(int fd, const void *buf, size_t count) { return( send( fd, (char *) buf, count,0)); } CTcp::CTcp(const std::string& port) : sock_fd(-1) , productId(0) , softwareVersion(0) , port(port) { } CTcp::~CTcp() { close(); } struct in_addr * CTcp::atoaddr(char *address) { struct hostent *host; static struct in_addr saddr; /* First try it as aaa.bbb.ccc.ddd. */ saddr.s_addr = inet_addr(address); if ((int )saddr.s_addr != -1) { return &saddr; } host = gethostbyname(address); if (host != NULL) { return (struct in_addr *) *host->h_addr_list; } return NULL; } void CTcp::open() { #if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED) throw exce_t(errOpen, "The TCP driver still needs to be ported to your platform."); #endif uint16_t lport = -1; struct in_addr *addr; struct sockaddr_in address; char conn[255],*service,*errpos; #ifdef WIN32 WSADATA wsaData; WORD wVersionRequested; int err; // 2.0 and above version of WinSock wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { stringstream msg; msg << "Couldn't not find a usable WinSock DLL, WSAStartup, error= " << err; throw exce_t(errOpen,msg.str()); } #endif if (sock_fd >= 0) return; strcpy(conn,port.c_str()); service=strstr(conn,":")+1; lport = strtol(service,&errpos,0); if ( (errpos[0] != 0) || (lport == 0) ) { stringstream msg; msg << "Invalid port number " << port.c_str(); throw exce_t(errOpen,msg.str()); return; /* Invalid port address */ } lport = htons(lport); *(service-1)=0; addr = atoaddr(conn); if (addr == NULL) { stringstream msg; msg << "Failed to resolve addres " << port.c_str(); throw exce_t(errOpen,msg.str()); return; } memset((char *) &address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = (lport); address.sin_addr.s_addr = addr->s_addr; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (connect(sock_fd, (struct sockaddr *) &address, sizeof(address)) < 0) { stringstream msg; msg << "Couldn't connect to " << port.c_str(); throw exce_t(errOpen,msg.str()); return; } if (sock_fd < 0) { stringstream msg; msg << "Failed to open socket device " << port.c_str(); throw exce_t(errOpen,msg.str()); } } void CTcp::close() { #ifdef WIN32 WSACleanup(); #endif my_close (sock_fd); sock_fd= -1; } int CTcp::read(char * data) { int bytes_read; size_t total_count = 0; char *current_position; char last_read = 0; time_t starttime; starttime= time_now(); current_position = data; while (last_read != 10 && (time_now() < starttime + TIMEOUT)) { bytes_read = my_read(sock_fd, &last_read, 1); if (bytes_read <= 0) { return -1; } if ( (total_count < MAX_SIZE) && (last_read != 10) && (last_read !=13) ) { current_position[0] = last_read; current_position++; total_count++; } } current_position[0] = 0; return total_count; } void CTcp::write(char* data) { size_t bytes_sent = 0; int this_write; int count=strlen(data); if (data[count]!=10) { data[count]=10; data[count+1]=0; count++; } while (bytes_sent < (size_t) count) { do this_write = my_write(sock_fd, data, count - bytes_sent); while ( (this_write < 0) && (errno == EINTR) ); if (this_write <= 0) return; // this_write; bytes_sent += this_write; data += this_write; } return; } // check if data available int CTcp::sock_chars_ready( void) { fd_set fds_read; struct timeval time; FD_ZERO( &fds_read); FD_SET( sock_fd, &fds_read); time.tv_sec= 0; time.tv_usec= 1000; select( sock_fd+1, &fds_read, NULL, NULL, &time); if (FD_ISSET( sock_fd, &fds_read)) { return 1; } return 0; } time_t CTcp::time_now( void) { time_t seconds= 0; time( &seconds); // FIXME: handle error case return( seconds); } garmindev-0.3.4+svn3432/src/Platform.h0000644000175000017500000003420412002232272015771 0ustar miramira/* -*-mode:c++; c-style:k&r; c-basic-offset:4; -*- */ /********************************************************************************************** Copyright (C) 2008 Albrecht Dre This file contains macros for platform-independant access of data stored in little-endian format. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ============================================================= Why does this file exist, and what should hackers do with it? ------------------------------------------------------------- 1. Background Garmin stores data in map files and in their devices in little-endian format. The data is usually packed, i.e. it is not guaranteed that multi-byte data is aligned at 16, 32 or 64 bit boundaries. This is fine as long as you run QLandkarte (or any derived software) on a little-endian machine which accepts accessing unaligned data. The `configure' script in the top-level folder tries to detect if your machine is a little endian (like Intel or ARM) or a big endian (like PowerPC or Sparc). In the latter case, it defines the macro HAVE_BIGENDIAN. In an other test, it checks if your machine supports accessing unaligned memory (like Intel or PowerPC) or if such accesses would fail (as on ARM or Sparc). If unaligned accesses are supported, the macro CAN_UNALIGNED will be defined. Of course, the file config.h from the top-level folder has to be included. 2. How to access data To work around these problems, this file defines a number of access macros. On machines which do not need them, they always expand to nothing, but they are *absolutely* necessary on others. So *never* access multi-byte elements without using these macros. 2.1 Load data from Garmin The following rules apply if you want to access data in a source coming from a Garmin device or file: (a) the source is a constant or an aligned 16, 32 or 64-bit value Always use the macro gar_endian(, ) where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double. The returned value will explicitly be cast'ed to . (b) the source is an unaligned 16, 32 or 64-bit value Always use the macro gar_load(, ) where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double. The returned value will explicitly be cast'ed to . (c) the source is a pointer Always use the macro gar_ptr_load(, ) where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double or the special Garmin types int24_t or uint24_t. The returned value will be of type except for the Garmin types int24_t or uint24_t which will be int32_t or uint32_t, respectively, but have the uppermost 8 bits always set to 0. 2.2 Store data to Garmin (a) the destination is a variable For unaligned variables, use the macro gar_store(, , ) where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double. if the variable is aligned, use "destination = gar_endian(type, source)" which is faster. (b) the destination is a pointer For unaligned pointer destinations, use the macro gar_ptr_store(, , ) where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double or the special Garmin types int24_t or uint24_t. For a standard type and an aligned pointer destination, use "*(type *)(ptr) = gar_endian(type, source)" which is faster. **********************************************************************************************/ #ifndef __PLATFORM_H__ #define __PLATFORM_H__ // include platform setup (HAVE_BIGENDIAN, CAN_UNALIGNED) #include "config.h" // need integer type definitions with fixed width #ifdef HAVE_INTTYPES_H # include #elif HAVE_STDINT_H # include #elif WIN32 #include typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #define isnan(x) _isnan(x) #else # error neither inttypes.h nor stdint.h are available #endif #include // -------------------------------------------------------------------------------------------- // macros to fix the endianess of the constant or properly aligned argument x of type t #if !defined(HAVE_BIGENDIAN) // little endian platform: just return the argument #define gar_endian(t, x) (t)(x) #else // big endian platform #define gar_endian(t, x) (__gar_endian_ ## t(x)) // define swapping static inline uint16_t __gar_endian_uint16_t(uint16_t x) { return ((x >> 8) & 0xffu) | ((x & 0xffu) << 8); } static inline uint32_t __gar_endian_uint32_t(uint32_t x) { return (((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) | ((x & 0x0000ff00u) << 8) | ((x & 0x000000ffu) << 24)); } static inline uint64_t __gar_endian_uint64_t(uint64_t x) { return (((x & 0xff00000000000000ull) >> 56) | ((x & 0x00ff000000000000ull) >> 40) | ((x & 0x0000ff0000000000ull) >> 24) | ((x & 0x000000ff00000000ull) >> 8) | ((x & 0x00000000ff000000ull) << 8) | ((x & 0x0000000000ff0000ull) << 24) | ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56)); } static inline int16_t __gar_endian_int16_t(int16_t x) { return ((x >> 8) & 0xffu) | ((x & 0xffu) << 8); } static inline int32_t __gar_endian_int32_t(int32_t x) { return (((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) | ((x & 0x0000ff00u) << 8) | ((x & 0x000000ffu) << 24)); } static inline int64_t __gar_endian_int64_t(int64_t x) { return (((x & 0xff00000000000000ull) >> 56) | ((x & 0x00ff000000000000ull) >> 40) | ((x & 0x0000ff0000000000ull) >> 24) | ((x & 0x000000ff00000000ull) >> 8) | ((x & 0x00000000ff000000ull) << 8) | ((x & 0x0000000000ff0000ull) << 24) | ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56)); } static inline float __gar_endian_float(float x) { union { uint32_t _u; float _f; } _v; _v._f = x; _v._u = gar_endian(uint32_t, _v._u); return _v._f; } static inline double __gar_endian_double(double x) { union { uint64_t _u; double _d; } _v; _v._d = x; _v._u = gar_endian(uint64_t, _v._u); return _v._d; } #endif // HAVE_BIGENDIAN // -------------------------------------------------------------------------------------------- // macros to deal with pointers or unaligned arguments // load argument of type t from pointer p #define gar_ptr_load(t, p) __gar_ptr_load_ ## t((const uint8_t *)(p)) // store argument src of type t in in the location to which the pointer p points #define gar_ptr_store(t, p, src) __gar_ptr_store_ ## t((uint8_t *)(p), (src)) #if defined(CAN_UNALIGNED) && !defined(HAVE_BIGENDIAN) // load argument x of type t - noop with proper cast #define gar_load(t, x) (t)(x) // store argument src of type t in the variable dst of type t - just assign #define gar_store(t, dst, src) (dst) = (src) // load from pointer - simply map memory #define __gar_ptr_load_int16_t(p) (*((int16_t *)(p))) #define __gar_ptr_load_int32_t(p) (*((int32_t *)(p))) #define __gar_ptr_load_int64_t(p) (*((int64_t *)(p))) #define __gar_ptr_load_uint16_t(p) (*((uint16_t *)(p))) #define __gar_ptr_load_uint32_t(p) (*((uint32_t *)(p))) #define __gar_ptr_load_uint64_t(p) (*((uint64_t *)(p))) #define __gar_ptr_load_float(p) (*((float *)(p))) #define __gar_ptr_load_double(p) (*((double *)(p))) // special Garmin types - map memory and clear extra bits #define __gar_ptr_load_uint24_t(p) (__gar_ptr_load_uint32_t(p) & 0x00FFFFFFu) #define __gar_ptr_load_int24_t(p) (__gar_ptr_load_int32_t(p) & 0x00FFFFFFu) // store data to pointer - just assign after a proper cast #define __gar_ptr_store_int16_t(p, src) (*((int16_t *)(p))) = (src) #define __gar_ptr_store_int32_t(p, src) (*((int32_t *)(p))) = (src) #define __gar_ptr_store_int64_t(p, src) (*((int64_t *)(p))) = (src) #define __gar_ptr_store_uint16_t(p, src) (*((uint16_t *)(p))) = (src) #define __gar_ptr_store_uint32_t(p, src) (*((uint32_t *)(p))) = (src) #define __gar_ptr_store_uint64_t(p, src) (*((uint64_t *)(p))) = (src) #define __gar_ptr_store_float(p, src) (*((float *)(p))) = (src) #define __gar_ptr_store_double(p, src) (*((double *)(p))) = (src) // special Garmin types - use memcpy static inline void __gar_ptr_store_int24_t(uint8_t * p, int32_t src) { __gar_ptr_store_uint16_t(p, src & 0xffffu); p[2] = src >> 16; } static inline void __gar_ptr_store_uint24_t(uint8_t * p, uint32_t src) { __gar_ptr_store_uint16_t(p, src & 0xffffu); p[2] = src >> 16; } #else // machine is either Big Endian or does not support unaligned accesses // load argument x of type t - call pointer load macro #define gar_load(t, x) gar_ptr_load(t, (uint8_t *)&(x)) // store argument src of type t in the variable dst of type t - call pointer store macro #define gar_store(t, dst, src) gar_ptr_store(t, (uint8_t *)&(dst), src) // load from pointer - read'n'shift bytes // use Byte-Reverse operations for PowerPC static inline uint16_t __gar_ptr_load_uint16_t(const uint8_t *p) { #ifdef __powerpc__ register uint16_t temp; asm __volatile__ ("lhbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); return temp; #else return (uint16_t)(p[0] | (p[1] << 8)); #endif } static inline uint32_t __gar_ptr_load_uint24_t(const uint8_t *p) { #ifdef __powerpc__ register uint32_t temp; asm __volatile__ ("lwbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); asm __volatile__ ("rlwinm %0,%1,0,8,31" : "=r" (temp) : "r" (temp)); return temp; #else return (uint32_t)(p[0] | (p[1] << 8) | (p[2] << 16)); #endif } static inline uint32_t __gar_ptr_load_uint32_t(const uint8_t *p) { #ifdef __powerpc__ register uint32_t temp; asm __volatile__ ("lwbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); return temp; #else return (uint32_t)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); #endif } static inline uint64_t __gar_ptr_load_uint64_t(const uint8_t *p) { return ((uint64_t)__gar_ptr_load_uint32_t(p) | ((uint64_t)__gar_ptr_load_uint32_t(p + 4) << 32)); } static inline int16_t __gar_ptr_load_int16_t(const uint8_t *p) { #ifdef __powerpc__ register int16_t temp; asm __volatile__ ("lhbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); return temp; #else return (int16_t)(p[0] | (p[1] << 8)); #endif } static inline int32_t __gar_ptr_load_int24_t(const uint8_t *p) { #ifdef __powerpc__ register int32_t temp; asm __volatile__ ("lwbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); asm __volatile__ ("rlwinm %0,%1,0,8,31" : "=r" (temp) : "r" (temp)); return temp; #else return p[0] | (p[1] << 8) | (p[2] << 16); #endif } static inline int32_t __gar_ptr_load_int32_t(const uint8_t *p) { #ifdef __powerpc__ register int32_t temp; asm __volatile__ ("lwbrx %0,0,%1" : "=r" (temp) : "b" (p), "m" (*p)); return temp; #else return (int32_t)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); #endif } static inline int64_t __gar_ptr_load_int64_t(const uint8_t *p) { return ((int64_t)__gar_ptr_load_uint32_t(p) | ((int64_t)__gar_ptr_load_int32_t(p + 4) << 32)); } static inline float __gar_ptr_load_float(const uint8_t * p) { union { uint32_t _u; float _f; } _v; _v._u = gar_ptr_load(uint32_t, p); return _v._f; } static inline double __gar_ptr_load_double(const uint8_t * p) { union { uint64_t _u; double _d; } _v; _v._u = gar_ptr_load(uint64_t, p); return _v._d; } // macros to store data - use memcpy to store data to pointer static inline void __gar_ptr_store_uint16_t(uint8_t *p, uint16_t src) { p[0] = src & 0xffu; p[1] = (src >> 8) & 0xffu; } static inline void __gar_ptr_store_uint24_t(uint8_t *p, uint32_t src) { p[0] = src & 0xffu; p[1] = (src >> 8) & 0xffu; p[2] = (src >> 16) & 0xffu; } static inline void __gar_ptr_store_uint32_t(uint8_t *p, uint32_t src) { p[0] = src & 0xffu; p[1] = (src >> 8) & 0xffu; p[2] = (src >> 16) & 0xffu; p[3] = (src >> 24) & 0xffu; } static inline void __gar_ptr_store_uint64_t(uint8_t *p, uint64_t src) { __gar_ptr_store_uint32_t(p, src & 0xffffffffu); __gar_ptr_store_uint32_t(p + 4, src >> 32); } #define __gar_ptr_store_int16_t(p, src) __gar_ptr_store_uint16_t(p, (uint16_t)src) #define __gar_ptr_store_int24_t(p, src) __gar_ptr_store_uint24_t(p, (uint32_t)src) #define __gar_ptr_store_int32_t(p, src) __gar_ptr_store_uint32_t(p, (uint32_t)src) #define __gar_ptr_store_int64_t(p, src) __gar_ptr_store_uint64_t(p, (uint64_t)src) static inline void __gar_ptr_store_float(uint8_t *p, float src) { float __fv = gar_endian(float, src); memcpy(p, &__fv, 4); } static inline void __gar_ptr_store_double(uint8_t *p, double src) { double __dv = gar_endian(double, src); memcpy(p, &__dv, 8); } #endif // cannot unaligned or big endian #endif // __PLATFORM_H__ garmindev-0.3.4+svn3432/src/CUSB.cpp0000644000175000017500000002642712002232272015304 0ustar miramira/********************************************************************************************** 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 "CUSB.h" #include "IDevice.h" #include "Platform.h" #include #include #include #include using namespace Garmin; using namespace std; #ifndef ETIMEDOUT // included for windows by dr, copied from pthread.h # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif #define EA(x) (x & USB_ENDPOINT_ADDRESS_MASK) #define GUSB_DATA_AVAILABLE 2 #define GUSB_SESSION_START 5 #define GUSB_SESSION_STARTED 6 #define USB_INTERRUPT_TIMEOUT 3000 #define USB_BULK_TIMEOUT 30000 #define DBG CUSB::CUSB() : busses(0) , udev(0) , theInterface(-1) , epBulkIn(-1) , epBulkOut(-1) , epIntrIn(-1) , max_tx_size(0) , doBulkRead(false) , productId(0) , softwareVersion(0) , protocolArraySize(-1) { usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); } CUSB::~CUSB() { close(); } void CUSB::open() { assert(busses); usb_bus *bus = 0; for(bus = busses; bus; bus = bus->next) { struct usb_device * dev = 0; for (dev = bus->devices; dev; dev = dev->next) { #ifdef DBG cout << hex << dev->descriptor.idVendor << " " << dev->descriptor.idProduct << endl; #endif if(dev->descriptor.idVendor == GARMIN_VID) { if(dev->descriptor.idProduct == G60CSX_PID) { start(dev); break; } } } } if(udev == 0) { throw exce_t(errOpen,"Is the unit connected?"); } } void CUSB::close() { if(udev) { usb_release_interface(udev, theInterface); usb_close(udev); udev = 0; } } void CUSB::close2() { if(udev) { usb_release_interface(udev, theInterface); usb_reset(udev); usb_close(udev); udev = 0; } } int CUSB::_bulk_read(Packet_t& data) { int res; res = ::usb_bulk_read(udev,epBulkIn,(char*)&data,sizeof(data),USB_BULK_TIMEOUT); if (res > 0) { debug("b >>", data); return res; } if (res == 0) { Packet_t cont; res = ::usb_interrupt_read(udev,epIntrIn,(char*)&cont,sizeof(cont), 100); if (res > 0) { debug("i (cont) >>", cont); if (gar_endian(uint16_t, cont.id) == GUSB_DATA_AVAILABLE) return _bulk_read(data); } } doBulkRead = false; return res; } int CUSB::read(Packet_t& data) { int res; data.type = 0; data.id = 0; data.size = 0; if(doBulkRead) { res = _bulk_read(data); } else { res = ::usb_interrupt_read(udev,epIntrIn,(char*)&data,sizeof(data),USB_INTERRUPT_TIMEOUT); if (res > 0) { debug("i >>", data); if(gar_endian(uint16_t, data.id) == GUSB_DATA_AVAILABLE) { doBulkRead = true; res = _bulk_read(data); } } } // endian fix for id and size data.id = gar_endian(uint16_t, data.id); data.size = gar_endian(uint32_t, data.size); // Some devices sending data on the interrupt pipe seem // to timeout occasionally. It seems to be save to ignore this // timeout. if(res == -ETIMEDOUT && !doBulkRead) { res = 0; } if(res < 0) { stringstream msg; msg << "USB read failed:" << usb_strerror(); throw exce_t(errRead,msg.str()); } return res; } void CUSB::write(const Packet_t& data) { unsigned size = GUSB_HEADER_SIZE + data.size; char * src; #if defined(HAVE_BIGENDIAN) // make a local copy for swapping the header Packet_t real_cmnd(data.type, gar_endian(uint16_t, data.id)); real_cmnd.size = gar_endian(uint32_t, data.size); // copy payload (if any) if (data.size > 0) memcpy(real_cmnd.payload, data.payload, data.size); // send the tweaked packet src = (char *) &real_cmnd; #else src = (char *) &data; #endif // big endian platform int res = ::usb_bulk_write(udev,epBulkOut,src,size,USB_BULK_TIMEOUT); debug("b <<", (Packet_t &) *src); if(res < 0) { stringstream msg; msg << "USB bulk write failed:" << usb_strerror(); throw exce_t(errWrite,msg.str()); } /* The Garmin protocol requires that packets that are exactly a multiple of the max tx size be followed by a zero length packet. */ if (size && !(size % max_tx_size)) { ::usb_bulk_write(udev,epBulkOut,(char*)&data,0,USB_BULK_TIMEOUT); #ifdef DBG cout << "b << zero size packet to terminate" << endl; #endif } } void CUSB::start(struct usb_device *dev) { int i; if(udev) return; udev = usb_open(dev); if(udev == 0) { stringstream msg; msg << "Failed to open USB device: " << usb_strerror(); throw exce_t(errOpen,msg.str()); } if (dev->config == 0) { stringstream msg; msg << "USB device has no configuration: " << usb_strerror(); throw exce_t(errOpen,msg.str()); } if (usb_set_configuration(udev, dev->config->bConfigurationValue) < 0) { stringstream msg; #if __linux__ char drvnm[128]; drvnm[0] = 0; msg << "Failed to configure USB: " << usb_strerror(); usb_get_driver_np(udev, 0, drvnm, sizeof(drvnm)-1); if(strlen(drvnm) != 0) { msg << "\n\nThe kernel driver '" << drvnm << "' is blocking. " << "Please use 'rmmod " << drvnm << "' as root to remove it temporarily. " << "You might consider to add 'blacklist " << drvnm << "' to your " << "modeprobe.conf, to remove the module permanently."; } throw exce_t(errOpen,msg.str()); #endif msg << "Failed to configure USB: " << usb_strerror(); throw exce_t(errOpen,msg.str()); } theInterface = dev->config->interface->altsetting->bInterfaceNumber; if (usb_claim_interface(udev, theInterface) < 0) { stringstream msg; msg << "Failed to claim USB interface: " << usb_strerror(); throw exce_t(errOpen,msg.str()); } max_tx_size = dev->descriptor.bMaxPacketSize0; #ifdef DBG cout << " max. packet size:" << max_tx_size << endl; #endif for (i = 0; i < dev->config->interface->altsetting->bNumEndpoints; i++) { struct usb_endpoint_descriptor * ep; ep = &dev->config->interface->altsetting->endpoint[i]; switch (ep->bmAttributes & USB_ENDPOINT_TYPE_MASK) { case USB_ENDPOINT_TYPE_BULK: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { #ifdef DBG cout << " epBulkIn " << hex << EA(ep->bEndpointAddress) << endl; #endif epBulkIn = EA(ep->bEndpointAddress); } else { #ifdef DBG cout << " epBulkOut " << hex << EA(ep->bEndpointAddress) << endl; #endif epBulkOut = EA(ep->bEndpointAddress); } break; case USB_ENDPOINT_TYPE_INTERRUPT: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { #ifdef DBG cout << " epIntrIn " << hex << EA(ep->bEndpointAddress) << endl; #endif epIntrIn = EA(ep->bEndpointAddress); } break; } } if ((epBulkIn > 0) && (epBulkOut > 0) && (epIntrIn > 0)) { return; } throw exce_t(errOpen,"Failed to identify USB endpoints for this device."); } void CUSB::syncup(void) { static const Packet_t gpack_session_start(GUSB_PROTOCOL_LAYER,GUSB_SESSION_START); Packet_t response; int i, res; for(i=0; i<10; ++i) { write(gpack_session_start); if((res = read(response)) > 0) break; } if(res == 0 || response.id != GUSB_SESSION_STARTED) { throw exce_t(errSync,"Failed to sync. up with device. Initial session could not be started."); } std::list results; std::list::iterator ret; if (0 >= run_product_request( results )) throw exce_t(errSync,"Failed to sync. up with device. Product data request failed."); protocolArraySize = -1; for (ret = results.begin(); ret != results.end(); ret++) { if(ret->id == Pid_Product_Data) { //TODO read data Product_Data_t * pData = (Product_Data_t*)ret->payload; productId = gar_load(uint16_t, pData->product_id); softwareVersion = gar_load(int16_t, pData->software_version); productString = pData->str; #ifdef DBG cout << "Product: " << hex << productId << " " << dec << softwareVersion << " " << productString << endl; #endif } if(ret->id == Pid_Ext_Product_Data) { //TODO read data } if(ret->id == Pid_Protocol_Array) { // note: we cannot use a Protocol_Data_t here due to alignment issues // on some platforms... uint8_t * p = ret->payload; for(uint32_t i = 0; i < ret->size; i += sizeof(Protocol_Data_t)) { uint8_t pr_tag = *p++; uint16_t pr_data = gar_ptr_load(uint16_t, p); p += 2; #ifdef DBG cout << "Protocol: "<< (char)pr_tag << dec << pr_data << endl; #endif ++protocolArraySize; protocolArray[protocolArraySize].tag = pr_tag; protocolArray[protocolArraySize].data = pr_data; } #ifdef DBG cout << "protocolArraySize:" << protocolArraySize << endl; #endif // if(!doBulkRead) return; } } } uint16_t CUSB::getDataType(int data_no, char tag, uint16_t protocol) { if ( (protocolArraySize - 1 - data_no) < 0) { return 0; } // Find the right tag D for for (uint32_t i=0; i < protocolArraySize-1-data_no; i++) { if ((char)protocolArray[i].tag == tag) { if (protocolArray[i].data == protocol) { // accept data_no=-1 as a protocol verification only if (data_no == -1) return (uint16_t) 1; if (protocolArraySize < i + 1 + data_no) return 0; if ((char)protocolArray[i+1+data_no].tag == 'D') { return protocolArray[i+1+data_no].data; } } } } return (uint16_t) 0; } garmindev-0.3.4+svn3432/src/CMakeLists.txt0000644000175000017500000000177112002232272016577 0ustar miramira set(CMAKE_VERBOSE_MAKEFILE ON) set(SRCS # CTcp.cpp Garmin.cpp IDeviceDefault.cpp ILink.cpp CUSB_common.cpp ) set(HDRS Platform.h CSerial.h # CTcp.h CUSB.h Garmin.h IDeviceDefault.h IDevice.h ILink.h ) if(UNIX AND NOT APPLE) include_directories(../ ${LIBUSB_INCLUDE_DIRS}) set(SRCS ${SRCS} CUSB.cpp CSerial.cpp) endif(UNIX AND NOT APPLE) if(APPLE) set(SRCS ${SRCS} CUSB_MacOSX.cpp CSerial.cpp) endif(APPLE) if(WIN32) add_definitions(-D_CRT_SECURE_NO_DEPRECATE) set(SRCS ${SRCS} CUSB_win32.cpp) endif(WIN32) add_library(garmin STATIC ${SRCS} ${HDRS}) if(UNIX) if(APPLE) target_link_libraries( garmin "-F/Library/Frameworks -L/Library/Frameworks -framework IOKit -framework CoreFoundation") else(APPLE) target_link_libraries( garmin ${LIBUSB_LIBRARIES}) endif(APPLE) SET_TARGET_PROPERTIES( garmin PROPERTIES COMPILE_FLAGS -fPIC) install(FILES IDevice.h DESTINATION ${INCLUDE_INSTALL_DIR}/garmin/) endif(UNIX) garmindev-0.3.4+svn3432/ConfigureChecks.cmake0000644000175000017500000000135512002232272017312 0ustar miramirainclude(CheckIncludeFile) include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) include(CheckCXXSourceCompiles) include(TestBigEndian) set(PACKAGE ${APPLICATION_NAME}) set(VERSION ${APPLICATION_VERSION}) set(DATADIR ${DATA_INSTALL_DIR}) set(LIBDIR ${LIB_INSTALL_DIR}) set(PLUGINDIR "${PLUGIN_INSTALL_DIR}") set(SYSCONFDIR ${SYSCONF_INSTALL_DIR}) set(BINARYDIR ${CMAKE_BINARY_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR}) set(SHARED_LIB_EXT ".dll") if (UNIX AND NOT WIN32) set(SHARED_LIB_EXT ".so") endif (UNIX AND NOT WIN32) check_include_file(stdint.h HAVE_STDINT_H) check_include_file(inttypes.h HAVE_INTTYPES_H) check_include_file(byteswap.h HAVE_BYTESWAP_H) test_big_endian(HAVE_BIGENDIAN) garmindev-0.3.4+svn3432/LICENSE0000644000175000017500000003651012002232272014254 0ustar miramira

The GNU General Public License (GPL)

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

garmindev-0.3.4+svn3432/BCPP_HOWTO0000644000175000017500000000025512002232272014673 0ustar miramiraTo beautify all source code do: cd src find ./ -name "*.h" -exec bcpp -fnc ../bcpp.config -fi {} \; find ./ -name "*.cpp" -exec bcpp -fnc ../bcpp.config -fi {} \; rm *.origgarmindev-0.3.4+svn3432/DefineOptions.cmake0000644000175000017500000000023312002232272017010 0ustar miramiraoption(WITH_LOG4C "Build csync without log4c" ON) option(UNIT_TESTING "Build with unit tests" OFF) option(MEM_NULL_TESTS "Enable NULL memory testing" OFF) garmindev-0.3.4+svn3432/changelog.txt0000644000175000017500000000126012002232272015731 0ustar miramira--- 2010.06.06 --- Bug #11: Fix screenshot rotation for 60SCx Request #12: add driver for Forerunner 305 --- 2010.02.06 --- Request #10: Add support for GPSMap60C --- 2010.01.23 --- Bug #8: Fix drivers to compile and work on OSX and big endian systems Request #9: Add eTrex Legend Cx support --- 2009.12.21 --- Bug #6: Fixed detect libusb Request #7: Add download of routes (sofar GPSMap60SCx only) --- 2009.06.22 --- Request #4: Add support for Etrex Summit HC --- 2009.05.05 --- Request #3: GPSMap60SCx: Add track upload --- 2009.03.22 --- Request #2: Add dependency check for libusb --- 2009.03.09 --- Request #1: Initial Release garmindev-0.3.4+svn3432/CPackConfig.cmake0000644000175000017500000000152012002232272016351 0ustar miramirainclude(InstallRequiredSystemLibraries) # For help take a look at: # http://www.cmake.org/Wiki/CMake:CPackConfiguration ### general settings string(TOLOWER ${APPLICATION_NAME} CPACK_PACKAGE_NAME) set(CPACK_PACKAGE_VENDOR "GarminDev") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Garmin Device Pugins for QLandkarte (GT)") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_VERSION "${PACKAGE_VER_MAJOR}.${PACKAGE_VER_MINOR}.${PACKAGE_VER_PATCH}") set(CPACK_GENERATOR "TGZ") set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") ### source package settings set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") include(CPack) garmindev-0.3.4+svn3432/INSTALL0000644000175000017500000000270212002232272014274 0ustar miramiraTo compile the code make sure you meet the following dependencies: * cmake - a make file generator (>= Version 2.6) For the bleeding edge of development you have to use the SVN repository. For initial checkout: svn co https://qlandkartegt.svn.sourceforge.net/svnroot/qlandkartegt/GarminDev/trunk GarminDev To build (out of source build, start one level above source root directory)1: mkdir build_GarminDev cd build_GarminDev ccmake ../GarminDev CCmake can be controlled by keys. Watch out for key hints at the bottom. Especially the"c" and"g" key. Next you do: make The binary will be placed in ./bin. To catch up latest changes (in the source root directory): svn up To send a patch (in the source root directory): svn diff > patchname.diff As user you might want to do a sudo make install to copy all stuff into your system. Installation on Mac OS X ------------------------ On Mac OS X, you probably want to include the Garmin drivers in the bundle where QLandkarteGT searches for them. To this end, when running ccmake be sure to set the variable QLANDKARTEGT_BUILD_DIR to the folder where you built QLandkarteGT. The default is "../build_QLandkarteGT", assuming that you use an out-of-source build environment as suggested in the QLandkarteGT instructions. Then, after running make, simply say make mac-deploy which will copy all drivers to the bundle. You should not use "make install" on Mac OS X. garmindev-0.3.4+svn3432/bcpp.config0000644000175000017500000001306112002232272015356 0ustar miramira; This file contains configuration parameters that are used ; within the bcpp program. ; There are two types of parameter types : Boolean, and Integer. ; Boolean types can have only two valid values [On, Yes, or Off, No]. ; Integer types can have a valid range of 0 - 5000. ;------------------------------------------------------------------------ ; This parameter specifies how many lines separate between two ; functions. ;------------------------------------------------------------------------ function_spacing = 2 ; Integer ;------------------------------------------------------------------------ ; Specifies whether to use tabs in indenting code. ;------------------------------------------------------------------------ use_tabs = no ; Boolean ;------------------------------------------------------------------------ ; Specifies how many spaces to indent. This parameter is also used ; for tab indenting, as 1 tab may be worth 8 spaces if so desired. ; This parameter is used to position comments in TAB mode, and expanding ; of tabs within code! ;------------------------------------------------------------------------ indent_spacing = 4 ; Integer ;------------------------------------------------------------------------ ; Specifies whether to indent preprocessor controls to match the code ;------------------------------------------------------------------------ indent_preprocessor = no ; Boolean ;------------------------------------------------------------------------ ; Specifies whether to indent embedded SQL statements ;------------------------------------------------------------------------ indent_exec_sql = yes ; Boolean ;------------------------------------------------------------------------ ; Defines at what start position comments that have code on the ; same line to be placed. ;------------------------------------------------------------------------ comments_with_code = 33 ; Integer ;------------------------------------------------------------------------ ; Defines at what start position comments with no code start. ;------------------------------------------------------------------------ comments_with_nocode = 0 ; Integer ;------------------------------------------------------------------------ ; Set this option to ON turns off setting indentation position of parameter ; "comments_with_nocode". Indentation is then set according to code ; position. ;------------------------------------------------------------------------ leave_comments_nocode = yes ; Boolean ;------------------------------------------------------------------------ ; Use this option is used to change non-ascii (non-printable) chars to ; octal notation if they lie within quotes. Either ; Ascii_Chars_Only, XOR Leave_Graphic_Chars parameters need to be set ; as a True value for this parameter to take effect. ;------------------------------------------------------------------------ NonAscii_Quotes_to_Octal = yes ; Boolean ;------------------------------------------------------------------------ ; Setting this parameter to yes will strip non-printable characters ; from the source files, but leave any character that are IBM ; graphics alone. Any non-printable characters that lie within ; quotes will be transformed into octal/character notation, if ; NonAscii_Quotes_To_Octal parameter is set to True. ;------------------------------------------------------------------------ ; leave_graphic_chars = no ; Boolean ;------------------------------------------------------------------------ ; Setting this parameter to yes will strip any non-printable, ; non-ascii characters from the input file. Any non-printable ; octal/character notation if NonAscii_Quotes_To_Octal is set to ; True. Comment out this parameter if you are using ; Leave_Graphic_Chars parameter, as this parameter will override ; it. ;------------------------------------------------------------------------ ascii_chars_only = yes ; Boolean ;------------------------------------------------------------------------ ; This parameter will place open braces on a new line after it's ; associated code if set on/yes. Else the brace will be place on ; next above line if possible, with it's code. ;------------------------------------------------------------------------ place_brace_on_new_line = no ; Boolean ;------------------------------------------------------------------------ ; This parameter will stop output from the program corrupting output ; that may exit from the program via the standard output. ; If this parameter is set to off/no then no output is generated from ; the program, unless an error is encountered ;------------------------------------------------------------------------ program_output = yes ; Boolean ;------------------------------------------------------------------------ ; Specifies what the internal memory requirements will be in size of the ; line processing buffer. This essentially is used only for open brace ; relocation in kernighan/ritchie style. ;------------------------------------------------------------------------ Queue_Buffer = 1000 ; Integer ;------------------------------------------------------------------------ ; If this option is set to true then the input file will be backup into a ; another file with a ".bac" extension added to the end of the file ; name. ;------------------------------------------------------------------------ Backup_File = yes ; Boolean garmindev-0.3.4+svn3432/config.h.cmake0000644000175000017500000000110212002232272015731 0ustar miramira#cmakedefine PACKAGE ${APPLICATION_NAME} #cmakedefine VERSION ${APPLICATION_VERSION} #cmakedefine LOCALEDIR ${LOCALE_INSTALL_DIR} #cmakedefine DATADIR ${SHARE_INSTALL_PREFIX} #cmakedefine LIBDIR ${LIB_INSTALL_DIR} #cmakedefine PLUGINDIR ${PLUGINDIR} #cmakedefine SYSCONFDIR ${SYSCONFDIR} #cmakedefine BINARYDIR ${BINARYDIR} #cmakedefine SOURCEDIR ${SOURCEDIR} #cmakedefine SHARED_LIB_EXT ${SHARED_LIB_EXT} #cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_INTTYPES_H 1 #cmakedefine HAVE_BYTESWAP_H 1 #cmakedefine HAVE_BIGENDIAN 1 /* TODO add a check */ #define CAN_UNALIGNED 1 garmindev-0.3.4+svn3432/CMakeLists.txt0000644000175000017500000000442712002232272016011 0ustar miramiraproject(GarminDev) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/qlandkartegt) cmake_minimum_required(VERSION 2.6) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) #this one is for the API version check set(VER_MAJOR 01) set(VER_MINOR 18) #this one is for the release version set(PACKAGE_VER_MAJOR 0) set(PACKAGE_VER_MINOR 3) set(PACKAGE_VER_PATCH 5) add_definitions(-DVER_MAJOR=${VER_MAJOR} -DVER_MINOR=${VER_MINOR}) # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules ) # add definitions include(DefineCMakeDefaults) include(DefineCompilerFlags) include(DefineInstallationPaths) include(DefineOptions.cmake) include(CPackConfig.cmake) # disallow in-source build # include(MacroEnsureOutOfSourceBuild) # macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") # config.h generation include(ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) if(APPLE) set(SHARED_LIB_EXT ".dylib") set(QLANDKARTEGT_BUILD_DIR "../build_QLandkarteGT" CACHE PATH "location of the QLandkarteGT build folder") add_custom_target(mac-deploy COMMAND rm -rf "${QLANDKARTEGT_BUILD_DIR}/bin/QLandkarte\ GT.app/Contents/Resources/Drivers" && mkdir -p "${QLANDKARTEGT_BUILD_DIR}/bin/QLandkarte\ GT.app/Contents/Resources/Drivers" && tar -cpf - --exclude '*.a' -C ${LIBRARY_OUTPUT_PATH} . | tar -xpf - -C "${QLANDKARTEGT_BUILD_DIR}/bin/QLandkarte\ GT.app/Contents/Resources/Drivers" ) elseif(UNIX) set(SHARED_LIB_EXT ".so") endif (APPLE) find_package(USB REQUIRED) add_subdirectory(./src) add_subdirectory(./src/GPSMap60CSx) add_subdirectory(./src/GPSMap76) add_subdirectory(./src/EtrexLegendC) add_subdirectory(./src/EtrexLegend) add_subdirectory(./src/EtrexH) add_subdirectory(./src/whatGarmin) add_subdirectory(./src/ForeRunner) add_subdirectory(./src/Oregon) install( DIRECTORY ${LIBRARY_OUTPUT_PATH} DESTINATION ${LIB_INSTALL_DIR} ) garmindev-0.3.4+svn3432/cmake/Modules/0000755000175000017500000000000012002243320015726 5ustar miramiragarmindev-0.3.4+svn3432/src/ForeRunner/0000755000175000017500000000000012002243363016121 5ustar miramiragarmindev-0.3.4+svn3432/src/Oregon/0000755000175000017500000000000012002243403015260 5ustar miramiragarmindev-0.3.4+svn3432/src/EtrexH/0000755000175000017500000000000012002243341015227 5ustar miramiragarmindev-0.3.4+svn3432/src/whatGarmin/0000755000175000017500000000000012002243411016127 5ustar miramiragarmindev-0.3.4+svn3432/src/GPSMap76/0000755000175000017500000000000012002243376015304 5ustar miramiragarmindev-0.3.4+svn3432/src/EtrexLegend/0000755000175000017500000000000012002243346016243 5ustar miramiragarmindev-0.3.4+svn3432/src/EtrexLegendC/0000755000175000017500000000000012002243355016346 5ustar miramiragarmindev-0.3.4+svn3432/src/GPSMap60CSx/0000755000175000017500000000000012002243370015705 5ustar miramiragarmindev-0.3.4+svn3432/cmake/0000755000175000017500000000000012002243311014316 5ustar miramiragarmindev-0.3.4+svn3432/src/0000755000175000017500000000000012002243333014031 5ustar miramiragarmindev-0.3.4+svn3432/0000755000175000017500000000000012002243267013250 5ustar miramira