[garmindev] 09/12: Imported Upstream version 0.3.4+svn3432
Jaromír Mikeš
mira-guest at moszumanska.debian.org
Sat Apr 25 15:28:43 UTC 2015
This is an automated email from the git hooks/post-receive script.
mira-guest pushed a commit to branch master
in repository garmindev.
commit 46ec8642ed6c3bb0dc96241e7cb0f8baf8ccbfd8
Author: Jaromír Mikeš <mira.mikes at seznam.cz>
Date: Sat Apr 25 17:27:51 2015 +0200
Imported Upstream version 0.3.4+svn3432
---
.kdev4/GarminDev.kdev4 | 14 --
CMakeLists.txt | 3 +-
CMakeLists.txt.user | 164 -------------
GarminDev.kdev4 | 3 -
src/CMakeLists.txt | 1 +
src/CUSB.cpp | 184 ++++++---------
src/CUSB.h | 13 +-
src/CUSB_MacOSX.cpp | 55 +----
src/CUSB_common.cpp | 152 ++++++++++++
src/EtrexLegend/CDevice.cpp | 12 +-
src/EtrexLegendC/CDevice.cpp | 12 +-
src/ForeRunner/CMakeLists.txt | 2 +-
src/ForeRunner/loader.cpp | 16 ++
src/GPSMap60CSx/CDevice.cpp | 10 +-
src/GPSMap60CSx/CMakeLists.txt | 1 +
src/GPSMap60CSx/loader.cpp | 19 ++
src/GPSMap76/CDevice.cpp | 12 +-
src/{ForeRunner => Oregon}/CMakeLists.txt | 15 +-
src/Oregon/Oregon.cpp | 264 +++++++++++++++++++++
src/Oregon/Oregon.h | 78 +++++++
src/Oregon/Oregon.txt | 122 ++++++++++
src/{ForeRunner => Oregon}/loader.cpp | 35 ++-
src/Platform.h | 370 ++++++++++++++++++++----------
23 files changed, 1053 insertions(+), 504 deletions(-)
diff --git a/.kdev4/GarminDev.kdev4 b/.kdev4/GarminDev.kdev4
deleted file mode 100644
index 48e2c4c..0000000
--- a/.kdev4/GarminDev.kdev4
+++ /dev/null
@@ -1,14 +0,0 @@
-[Buildset]
-BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x00)
-
-[CMake]
-BuildDirs=/home/oeichler/data/cpp/build_GarminDev/
-CMakeDir=/usr/share/cmake/Modules
-Current CMake Binary=file:///usr/bin/cmake
-CurrentBuildDir=file:///home/oeichler/data/cpp/build_GarminDev/
-CurrentBuildType=
-CurrentInstallDir=
-ProjectRootRelative=./
-
-[Project]
-VersionControlSupport=kdevsubversion
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51b72e7..e702018 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,7 @@ 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 4)
+set(PACKAGE_VER_PATCH 5)
add_definitions(-DVER_MAJOR=${VER_MAJOR} -DVER_MINOR=${VER_MINOR})
@@ -68,6 +68,7 @@ add_subdirectory(./src/EtrexLegend)
add_subdirectory(./src/EtrexH)
add_subdirectory(./src/whatGarmin)
add_subdirectory(./src/ForeRunner)
+add_subdirectory(./src/Oregon)
install(
DIRECTORY
diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user
deleted file mode 100644
index 6dc6ee3..0000000
--- a/CMakeLists.txt.user
+++ /dev/null
@@ -1,164 +0,0 @@
-<!DOCTYPE QtCreatorProject>
-<qtcreator>
- <data>
- <variable>activeRunConfiguration</variable>
- <value type="int">0</value>
- </data>
- <data>
- <variable>activebuildconfiguration</variable>
- <value type="QString">all</value>
- </data>
- <data>
- <variable>buildConfiguration-all</variable>
- <valuemap type="QVariantMap">
- <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value>
- <value key="buildDirectory" type="QString">/home/oeichler/data/cpp/build_GarminDev</value>
- <value key="msvcVersion" type="QString"></value>
- </valuemap>
- </data>
- <data>
- <variable>buildconfiguration-all-buildstep0</variable>
- <valuemap type="QVariantMap">
- <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value>
- <valuelist key="abstractProcess.Environment" type="QVariantList">
- <value type="QString">COLORTERM=1</value>
- <value type="QString">CPU=x86_64</value>
- <value type="QString">CSHEDIT=emacs</value>
- <value type="QString">CVS_RSH=ssh</value>
- <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-MWaTkAosos,guid=81e4d1222652271161bd5b894befa52c</value>
- <value type="QString">DESKTOP_SESSION=default</value>
- <value type="QString">DISPLAY=:0</value>
- <value type="QString">DM_CONTROL=/var/run/xdmctl</value>
- <value type="QString">ENV=/etc/bash.bashrc</value>
- <value type="QString">FROM_HEADER=</value>
- <value type="QString">GPG_AGENT_INFO=/tmp/gpg-6GvjOy/S.gpg-agent:2023:1</value>
- <value type="QString">GS_LIB=/home/oeichler/.fonts</value>
- <value type="QString">GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/usr/share/themes//QtCurve/gtk-2.0/gtkrc:/home/oeichler/.gtkrc-2.0-qtengine:/home/oeichler/.gtkrc-2.0:/home/oeichler/.kde4/share/config/gtkrc-2.0</value>
- <value type="QString">GTK_IM_MODULE=cedilla</value>
- <value type="QString">GTK_RC_FILES=/etc/gtk/gtkrc:/home/oeichler/.gtkrc::/home/oeichler/.kde4/share/config/gtkrc</value>
- <value type="QString">G_BROKEN_FILENAMES=1</value>
- <value type="QString">G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-15,CP1252</value>
- <value type="QString">HISTSIZE=1000</value>
- <value type="QString">HOME=/home/oeichler</value>
- <value type="QString">HOST=linux-1jnh</value>
- <value type="QString">HOSTNAME=linux-1jnh</value>
- <value type="QString">HOSTTYPE=x86_64</value>
- <value type="QString">INPUTRC=/home/oeichler/.inputrc</value>
- <value type="QString">JAVA_BINDIR=/usr/lib64/jvm/java/bin</value>
- <value type="QString">JAVA_HOME=/usr/lib64/jvm/java</value>
- <value type="QString">JAVA_ROOT=/usr/lib64/jvm/java</value>
- <value type="QString">JDK_HOME=/usr/lib64/jvm/java</value>
- <value type="QString">JRE_HOME=/usr//jvm/jre</value>
- <value type="QString">KDE_FULL_SESSION=true</value>
- <value type="QString">KDE_MULTIHEAD=false</value>
- <value type="QString">KDE_SESSION_UID=1000</value>
- <value type="QString">KDE_SESSION_VERSION=4</value>
- <value type="QString">LANG=de_DE.UTF-8</value>
- <value type="QString">LANGUAGE=</value>
- <value type="QString">LD_LIBRARY_PATH=/opt/qtcreator-1.3.1/lib/qtcreator:/usr/lib64/mpi/gcc/openmpi/lib64</value>
- <value type="QString">LESS=-M -I</value>
- <value type="QString">LESSCLOSE=lessclose.sh %s %s</value>
- <value type="QString">LESSKEY=/etc/lesskey.bin</value>
- <value type="QString">LESSOPEN=lessopen.sh %s</value>
- <value type="QString">LESS_ADVANCED_PREPROCESSOR=no</value>
- <value type="QString">LOGNAME=oeichler</value>
- <value type="QString">LS_COLORS=no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.xz=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;3 [...]
- <value type="QString">LS_OPTIONS=-N --color=tty -T 0</value>
- <value type="QString">MACHTYPE=x86_64-suse-linux</value>
- <value type="QString">MAIL=/var/spool/mail/oeichler</value>
- <value type="QString">MANPATH=/usr/lib64/mpi/gcc/openmpi/share/man:/usr/local/man:/usr/local/share/man:/usr/share/man:/usr/man</value>
- <value type="QString">MINICOM=-c on</value>
- <value type="QString">MORE=-sl</value>
- <value type="QString">NNTPSERVER=news</value>
- <value type="QString">OSTYPE=linux</value>
- <value type="QString">PAGER=less</value>
- <value type="QString">PATH=/opt/qtcreator-1.3.1/bin/:/usr/lib64/mpi/gcc/openmpi/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/opt/kde3/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:/usr/lib/qt3/bin</value>
- <value type="QString">PROFILEREAD=true</value>
- <value type="QString">PWD=/home/oeichler</value>
- <value type="QString">PYTHONSTARTUP=/etc/pythonstart</value>
- <value type="QString">QTDIR=/usr/lib/qt3</value>
- <value type="QString">QT_IM_MODULE=xim</value>
- <value type="QString">QT_IM_SWITCHER=imsw-multi</value>
- <value type="QString">QT_PLUGIN_PATH=/home/oeichler/.kde4/lib64/kde4/plugins/:/usr/lib64/kde4/plugins/</value>
- <value type="QString">QT_SYSTEM_DIR=/usr/share/desktop-data</value>
- <value type="QString">SDK_HOME=/usr/lib64/jvm/java</value>
- <value type="QString">SESSION_MANAGER=local/linux-1jnh:@/tmp/.ICE-unix/2737,unix/linux-1jnh:/tmp/.ICE-unix/2737</value>
- <value type="QString">SHELL=/bin/bash</value>
- <value type="QString">SHLVL=1</value>
- <value type="QString">SSH_AGENT_PID=2024</value>
- <value type="QString">SSH_ASKPASS=/usr/lib64/ssh/x11-ssh-askpass</value>
- <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-prWUj1940/agent.1940</value>
- <value type="QString">TERM=xterm</value>
- <value type="QString">TMPDIR=/tmp</value>
- <value type="QString">USER=oeichler</value>
- <value type="QString">USE_FAM=</value>
- <value type="QString">WINDOWMANAGER=/usr/bin/startkde</value>
- <value type="QString">WINDOWPATH=7</value>
- <value type="QString">XAUTHLOCALHOSTNAME=linux-1jnh</value>
- <value type="QString">XCURSOR_THEME=Oxygen_Blue</value>
- <value type="QString">XDG_CONFIG_DIRS=/etc/xdg</value>
- <value type="QString">XDG_DATA_DIRS=/usr/local/share:/usr/share:/etc/opt/kde3/share:/opt/kde3/share</value>
- <value type="QString">XDG_SESSION_COOKIE=00ae16e1b7de5857b484b7014aef75cb-1273996585.770895-1731118709</value>
- <value type="QString">XDM_MANAGED=method=classic,auto</value>
- <value type="QString">XKEYSYMDB=/usr/share/X11/XKeysymDB</value>
- <value type="QString">XMODIFIERS=@im=local</value>
- <value type="QString">XNLSPATH=/usr/share/X11/nls</value>
- <value type="QString">XSESSION_IS_UP=yes</value>
- </valuelist>
- <value key="abstractProcess.IgnoreReturnValue" type="bool">false</value>
- <valuelist key="abstractProcess.arguments" type="QVariantList"/>
- <value key="abstractProcess.command" type="QString">make</value>
- <value key="abstractProcess.enabled" type="bool">true</value>
- <value key="abstractProcess.workingDirectory" type="QString">/home/oeichler/data/cpp/build_GarminDev</value>
- </valuemap>
- </data>
- <data>
- <variable>buildconfiguration-all-cleanstep0</variable>
- <valuemap type="QVariantMap">
- <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value>
- <valuelist key="additionalArguments" type="QVariantList">
- <value type="QString">clean</value>
- </valuelist>
- <value key="cleanConfig" type="bool">true</value>
- </valuemap>
- </data>
- <data>
- <variable>buildconfigurations</variable>
- <valuelist type="QVariantList">
- <value type="QString">all</value>
- </valuelist>
- </data>
- <data>
- <variable>buildstep0</variable>
- <valuemap type="QVariantMap">
- <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value>
- </valuemap>
- </data>
- <data>
- <variable>buildsteps</variable>
- <valuelist type="QVariantList">
- <value type="QString">CMakeProjectManager.MakeStep</value>
- </valuelist>
- </data>
- <data>
- <variable>cleanstep0</variable>
- <valuemap type="QVariantMap">
- <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value>
- <value key="clean" type="bool">true</value>
- </valuemap>
- </data>
- <data>
- <variable>cleansteps</variable>
- <valuelist type="QVariantList">
- <value type="QString">CMakeProjectManager.MakeStep</value>
- </valuelist>
- </data>
- <data>
- <variable>defaultFileEncoding</variable>
- <value type="QByteArray">UTF-8</value>
- </data>
- <data>
- <variable>project</variable>
- <valuemap type="QVariantMap"/>
- </data>
-</qtcreator>
diff --git a/GarminDev.kdev4 b/GarminDev.kdev4
deleted file mode 100644
index deeaa43..0000000
--- a/GarminDev.kdev4
+++ /dev/null
@@ -1,3 +0,0 @@
-[Project]
-Manager=KDevCMakeManager
-Name=GarminDev
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index def25f4..958320f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,7 @@ set(SRCS
Garmin.cpp
IDeviceDefault.cpp
ILink.cpp
+ CUSB_common.cpp
)
set(HDRS
diff --git a/src/CUSB.cpp b/src/CUSB.cpp
index ea04881..56c5420 100644
--- a/src/CUSB.cpp
+++ b/src/CUSB.cpp
@@ -44,9 +44,7 @@ using namespace std;
#define USB_INTERRUPT_TIMEOUT 3000
#define USB_BULK_TIMEOUT 30000
-#undef DBG
-
-#define DBG_LINE_SIZE 16
+#define DBG
CUSB::CUSB()
: busses(0)
@@ -123,55 +121,31 @@ void CUSB::close2()
}
-void CUSB::debug(const char * mark, const Packet_t& data)
+int CUSB::_bulk_read(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 << " ";
+ int res;
- const uint8_t * pData = (const uint8_t*)&data;
+ res = ::usb_bulk_read(udev,epBulkIn,(char*)&data,sizeof(data),USB_BULK_TIMEOUT);
- 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;
+ if (res > 0) {
+ debug("b >>", data);
+ return res;
}
- 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] = '.';
+ 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);
}
-
- --bytes;
-
}
- for(i=0; i < bytes; i++) cout << " ";
- cout << " " << buf << dec << endl;
+ doBulkRead = false;
+ return res;
}
-
int CUSB::read(Packet_t& data)
{
int res;
@@ -181,30 +155,22 @@ int CUSB::read(Packet_t& data)
data.size = 0;
if(doBulkRead) {
- res = ::usb_bulk_read(udev,epBulkIn,(char*)&data,sizeof(data),USB_BULK_TIMEOUT);
-
- if (res > 0)
- debug("b >>", 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
- }
- else {
+ res = _bulk_read(data);
+ } else {
res = ::usb_interrupt_read(udev,epIntrIn,(char*)&data,sizeof(data),USB_INTERRUPT_TIMEOUT);
-
- if (res > 0)
+ if (res > 0) {
debug("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
+ 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.
@@ -212,16 +178,6 @@ int CUSB::read(Packet_t& data)
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;
- }
-
if(res < 0) {
stringstream msg;
msg << "USB read failed:" << usb_strerror();
@@ -377,72 +333,61 @@ void CUSB::syncup(void)
write(gpack_session_start);
if((res = read(response)) > 0) break;
}
- if(res == 0) {
- throw exce_t(errSync,"Failed to sync. up with device");
+ if(res == 0 || response.id != GUSB_SESSION_STARTED) {
+ throw exce_t(errSync,"Failed to sync. up with device. Initial session could not be started.");
}
- 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;
+ std::list<Packet_t> results;
+ std::list<Packet_t>::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;
+ cout << "Product: " << hex << productId << " " << dec << softwareVersion << " " << productString << endl;
#endif
- }
+ }
- if(response.id == Pid_Ext_Product_Data) {
- //TODO read data
- }
+ if(ret->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;
+ 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;
+ cout << "Protocol: "<< (char)pr_tag << dec << pr_data << endl;
#endif
- ++protocolArraySize;
- protocolArray[protocolArraySize].tag = pr_tag;
- protocolArray[protocolArraySize].data = pr_data;
- }
++protocolArraySize;
+ protocolArray[protocolArraySize].tag = pr_tag;
+ protocolArray[protocolArraySize].data = pr_data;
+ }
#ifdef DBG
- cout << "protocolArraySize:" << protocolArraySize << endl;
+ cout << "protocolArraySize:" << protocolArraySize << endl;
#endif
- //
- if(!doBulkRead) return;
- }
+ //
+ 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)
{
- if (protocolArraySize == 0)
- {
+ if ( (protocolArraySize - 1 - data_no) < 0) {
return 0;
}
@@ -452,6 +397,7 @@ uint16_t CUSB::getDataType(int data_no, char tag, uint16_t protocol)
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;
}
diff --git a/src/CUSB.h b/src/CUSB.h
index 43df5a3..a282d06 100644
--- a/src/CUSB.h
+++ b/src/CUSB.h
@@ -23,6 +23,7 @@
#define CUSB_H
#include <string>
+#include <list>
#ifdef __APPLE__
# include <pthread.h>
# include <IOKit/IOTypes.h>
@@ -51,6 +52,8 @@ namespace Garmin
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:
@@ -72,6 +75,13 @@ namespace Garmin
*/
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<Packet_t>& result);
+ int run_product_request(std::list<Packet_t>& result);
+
uint16_t getProductId(){return productId;}
int16_t getSoftwareVersion(){return softwareVersion;}
const std::string& getProductString(){return productString;}
@@ -118,7 +128,7 @@ namespace Garmin
uint16_t productId;
int16_t softwareVersion;
std::string productString;
- uint32_t protocolArraySize;
+ int32_t protocolArraySize;
Protocol_Data_t protocolArray[GUSB_PAYLOAD_SIZE];
#ifdef __APPLE__
@@ -138,6 +148,7 @@ namespace Garmin
pthread_cond_t ir_cond;
struct readIntrCmnd_t * readIntrCmnd;
#endif
+ int _bulk_read(Packet_t&);
};
}
diff --git a/src/CUSB_MacOSX.cpp b/src/CUSB_MacOSX.cpp
index 0443369..20ef48a 100644
--- a/src/CUSB_MacOSX.cpp
+++ b/src/CUSB_MacOSX.cpp
@@ -49,10 +49,7 @@ using namespace std;
#define GUSB_SESSION_START 5
#define GUSB_SESSION_STARTED 6
-//#undef DBG
-#define DBG
-
-#define DBG_LINE_SIZE 16
+#undef DBG
namespace Garmin
{
@@ -285,56 +282,6 @@ void CUSB::close2()
}
-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::read(Packet_t& data)
{
IOReturn res;
diff --git a/src/CUSB_common.cpp b/src/CUSB_common.cpp
new file mode 100644
index 0000000..c7f26ff
--- /dev/null
+++ b/src/CUSB_common.cpp
@@ -0,0 +1,152 @@
+
+/**********************************************************************************************
+ Copyright (C) 2007 Oliver Eichler oliver.eichler at 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 <iostream>
+
+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<Packet_t>& 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<Packet_t>& 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<Packet_t>* cumulated = reinterpret_cast<std::list<Packet_t>*>(ctx);
+ cumulated->push_back(Packet_t());
+ Packet_t& n = cumulated->back();
+ memcpy(&n, &incoming, sizeof (n));
+ return sizeof(incoming);
+}
diff --git a/src/EtrexLegend/CDevice.cpp b/src/EtrexLegend/CDevice.cpp
index 1a552ac..15fc615 100644
--- a/src/EtrexLegend/CDevice.cpp
+++ b/src/EtrexLegend/CDevice.cpp
@@ -127,7 +127,7 @@ void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * ke
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errBlocked,msg.str());
}
}
@@ -238,7 +238,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errRuntime,msg.str());
}
}
@@ -295,6 +295,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
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
@@ -303,7 +304,12 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
chunkSize = (size < (254 - sizeof(offset))) ? size : (254 - sizeof(offset));
command.size = chunkSize + sizeof(offset);
- fread(buffer, chunkSize, 1, fid);
+ 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);
diff --git a/src/EtrexLegendC/CDevice.cpp b/src/EtrexLegendC/CDevice.cpp
index 0477593..f747896 100644
--- a/src/EtrexLegendC/CDevice.cpp
+++ b/src/EtrexLegendC/CDevice.cpp
@@ -249,7 +249,7 @@ void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * ke
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errRuntime,msg.str());
}
}
@@ -346,7 +346,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errRuntime,msg.str());
}
}
@@ -394,6 +394,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
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;
@@ -402,7 +403,12 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
chunkSize = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - sizeof(offset));
command.size = chunkSize + sizeof(offset);
- fread(buffer, chunkSize, 1, fid);
+ 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);
diff --git a/src/ForeRunner/CMakeLists.txt b/src/ForeRunner/CMakeLists.txt
index 140e4a9..43f4cf5 100644
--- a/src/ForeRunner/CMakeLists.txt
+++ b/src/ForeRunner/CMakeLists.txt
@@ -15,7 +15,7 @@ add_library(Forerunner305 SHARED ${SRCS} ${HDRS})
target_link_libraries(Forerunner305 garmin ${LIBUSB_LIBRARIES} pthread)
set(ALIASES
-
+ Forerunner205
)
foreach(var ${ALIASES})
diff --git a/src/ForeRunner/loader.cpp b/src/ForeRunner/loader.cpp
index 256efec..08e3f24 100644
--- a/src/ForeRunner/loader.cpp
+++ b/src/ForeRunner/loader.cpp
@@ -47,3 +47,19 @@ extern "C" WIN_EXPORT Garmin::IDevice * initForerunner305(const char * version)
// 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;
+}
diff --git a/src/GPSMap60CSx/CDevice.cpp b/src/GPSMap60CSx/CDevice.cpp
index 7dee617..96a0a45 100644
--- a/src/GPSMap60CSx/CDevice.cpp
+++ b/src/GPSMap60CSx/CDevice.cpp
@@ -33,7 +33,7 @@ using namespace GPSMap60CSx;
using namespace Garmin;
using namespace std;
-#if defined(HAVE_BIGENDIAN) || !defined(CAN_UNALIGNED)
+#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
@@ -397,6 +397,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
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;
@@ -405,7 +406,12 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
chunkSize = (size < (GUSB_PAYLOAD_SIZE - sizeof(offset))) ? size : (GUSB_PAYLOAD_SIZE - sizeof(offset));
command.size = chunkSize + sizeof(offset);
- fread(buffer, chunkSize, 1, fid);
+ 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);
diff --git a/src/GPSMap60CSx/CMakeLists.txt b/src/GPSMap60CSx/CMakeLists.txt
index d8a512b..5c5d3b6 100644
--- a/src/GPSMap60CSx/CMakeLists.txt
+++ b/src/GPSMap60CSx/CMakeLists.txt
@@ -25,6 +25,7 @@ set(ALIASES
EtrexVistaHCx
EtrexLegendHCx
EtrexLegendCx
+ EtrexLegendH
GPSMap76Cx
Quest
)
diff --git a/src/GPSMap60CSx/loader.cpp b/src/GPSMap60CSx/loader.cpp
index 88b6411..d49dd1d 100644
--- a/src/GPSMap60CSx/loader.cpp
+++ b/src/GPSMap60CSx/loader.cpp
@@ -62,6 +62,8 @@ extern "C" WIN_EXPORT Garmin::IDevice * initGPSMap76CSx(const char * version)
GPSMap60CSx::device->devid = 0x0124;
GPSMap60CSx::device->screenwidth = 160;
GPSMap60CSx::device->screenheight = 240;
+ GPSMap60CSx::device->screenhflip = false;
+ GPSMap60CSx::device->screenvflip = true;
return GPSMap60CSx::device;
}
@@ -233,6 +235,7 @@ extern "C" WIN_EXPORT Garmin::IDevice * initEtrexSummitHC(const char * version)
// GPSMap60CSx::device->devid = 0x0694;
GPSMap60CSx::device->screenwidth = 176;
GPSMap60CSx::device->screenheight = 220;
+ GPSMap60CSx::device->screenhflip = true;
return GPSMap60CSx::device;
}
@@ -253,3 +256,19 @@ extern "C" WIN_EXPORT Garmin::IDevice * initEtrexLegendCx(const char * version)
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;
+}
diff --git a/src/GPSMap76/CDevice.cpp b/src/GPSMap76/CDevice.cpp
index 5479898..7186081 100644
--- a/src/GPSMap76/CDevice.cpp
+++ b/src/GPSMap76/CDevice.cpp
@@ -133,7 +133,7 @@ void CDevice::_uploadMap(const uint8_t * mapdata, uint32_t size, const char * /*
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errBlocked,msg.str());
}
}
@@ -240,7 +240,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
uint32_t memory = ((uint32_t*)response.payload)[1];
if(memory < size) {
stringstream msg;
- msg << "Failed to send map: Unit has not enought memory (available/needed): " << memory << "/" << size << " bytes";
+ msg << "Failed to send map: Unit has not enough memory (available/needed): " << memory << "/" << size << " bytes";
throw exce_t(errRuntime,msg.str());
}
}
@@ -297,6 +297,7 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
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
@@ -305,7 +306,12 @@ void CDevice::_uploadMap(const char * filename, uint32_t size, const char * key)
chunkSize = (size < (254 - sizeof(offset))) ? size : (254 - sizeof(offset));
command.size = chunkSize + sizeof(offset);
- fread(buffer, chunkSize, 1, fid);
+ 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);
diff --git a/src/ForeRunner/CMakeLists.txt b/src/Oregon/CMakeLists.txt
similarity index 51%
copy from src/ForeRunner/CMakeLists.txt
copy to src/Oregon/CMakeLists.txt
index 140e4a9..c515f99 100644
--- a/src/ForeRunner/CMakeLists.txt
+++ b/src/Oregon/CMakeLists.txt
@@ -3,26 +3,27 @@ set(CMAKE_VERBOSE_MAKEFILE ON)
set(SRCS
loader.cpp
- CDevice.cpp
+ Oregon.cpp
)
set(HDRS
- CDevice.h
+ Oregon.h
)
include_directories(../ ${LIBUSB_INCLUDE_DIRS})
-add_library(Forerunner305 SHARED ${SRCS} ${HDRS})
-target_link_libraries(Forerunner305 garmin ${LIBUSB_LIBRARIES} pthread)
+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 Forerunner305
+ add_custom_command( TARGET Oregon
POST_BUILD
- COMMAND ln ARGS -sf libForerunner305${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT}
+ COMMAND ln ARGS -sf libOregon${SHARED_LIB_EXT} lib${var}${SHARED_LIB_EXT}
WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
)
endforeach(var)
diff --git a/src/Oregon/Oregon.cpp b/src/Oregon/Oregon.cpp
new file mode 100644
index 0000000..35869d6
--- /dev/null
+++ b/src/Oregon/Oregon.cpp
@@ -0,0 +1,264 @@
+/**********************************************************************************************
+ Copyright (C) 2010 Thilo Fromm <kontakt at thilo-fromm.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 "Oregon.h"
+#include "CUSB.h"
+
+#include <iostream>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <unistd.h>
+
+#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<Garmin::Track_t>& tracks, std::list<Packet_t> & raw) {
+ std::list<Packet_t>::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<Garmin::Track_t>& tracks)
+ {
+
+ if(usb == 0) return;
+
+ std::list<Packet_t> 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;
+
+ }
+}
+
diff --git a/src/Oregon/Oregon.h b/src/Oregon/Oregon.h
new file mode 100644
index 0000000..1946a72
--- /dev/null
+++ b/src/Oregon/Oregon.h
@@ -0,0 +1,78 @@
+/**********************************************************************************************
+ Copyright (C) 2010 Thilo Fromm <kontakt at thilo-fromm.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 OREGON_H
+#define OREGON_H
+#include <pthread.h>
+#include <errno.h>
+
+#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<Garmin::Track_t>& tracks, std::list<Packet_t> & 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<Garmin::Track_t>& 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
diff --git a/src/Oregon/Oregon.txt b/src/Oregon/Oregon.txt
new file mode 100644
index 0000000..4a1e401
--- /dev/null
+++ b/src/Oregon/Oregon.txt
@@ -0,0 +1,122 @@
+
+
+qLandkarte plugin for Garmin Oregon (tested on model 450)
+=========================================================
+
+ Thilo Fromm, July 2010
+ <kontakt at thilo-fromm.de>
+
+----------------------
+ 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
+ <http://www8.garmin.com/support/pdf/iop_spec.pdf>. 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 <qlandkartegt-users at lists.sourceforge.net>. !?#@?!
+
+
+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
+
+
diff --git a/src/ForeRunner/loader.cpp b/src/Oregon/loader.cpp
similarity index 61%
copy from src/ForeRunner/loader.cpp
copy to src/Oregon/loader.cpp
index 256efec..7c9830a 100644
--- a/src/ForeRunner/loader.cpp
+++ b/src/Oregon/loader.cpp
@@ -1,5 +1,5 @@
/**********************************************************************************************
- Copyright (C) 2007 Oliver Eichler oliver.eichler at gmx.de
+ Copyright (C) 2010 Thilo Fromm <kontakt at thilo-fromm.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
@@ -20,11 +20,11 @@
**********************************************************************************************/
#include "config.h"
-#include "CDevice.h"
+#include "Oregon.h"
-namespace FR305
+namespace Garmin
{
- static CDevice * device = 0;
+ static Oregon * device = 0;
}
@@ -34,16 +34,29 @@ namespace FR305
#define WIN_EXPORT
#endif
-extern "C" WIN_EXPORT Garmin::IDevice * initForerunner305(const char * version)
+extern "C" WIN_EXPORT Garmin::IDevice * initOregon(const char * version)
{
if(strncmp(version,INTERFACE_VERSION,5) != 0) {
return 0;
}
- if(FR305::device == 0) {
- FR305::device = new FR305::CDevice();
+ if(Garmin::device == 0) {
+ Garmin::device = new Garmin::Oregon();
}
- FR305::device->devname = "Forerunner305";
- // FR305::device->screenwidth = 160;
- // FR305::device->screenheight = 240;
- return FR305::device;
+ 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;
+}
+
diff --git a/src/Platform.h b/src/Platform.h
index d0f9dc0..743f892 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -17,7 +17,7 @@
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
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================
Why does this file exist, and what should hackers do with it?
@@ -34,7 +34,7 @@
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 an ARM or Sparc). If unaligned accesses are supported, the macro CAN_UNALIGNED will
+ (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
@@ -78,7 +78,7 @@
For unaligned variables, use the macro
gar_store(<type>, <destination>, <source>)
where type may be int16_t, int32_t, int64_t, uint16_t, uint32_t, uint64_t, float or double.
- if the valiable is aligned, use "destination = gar_endian(type, source)" which is faster.
+ if the variable is aligned, use "destination = gar_endian(type, source)" which is faster.
(b) the destination is a pointer
@@ -101,6 +101,8 @@
#elif HAVE_STDINT_H
# include <stdint.h>
#elif WIN32
+#include <windows.h>
+
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
@@ -110,6 +112,8 @@ 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
@@ -128,61 +132,88 @@ typedef unsigned __int64 uint64_t;
// big endian platform
#define gar_endian(t, x) (__gar_endian_ ## t(x))
-#if defined(HAVE_BYTESWAP_H)
+// define swapping
+static inline uint16_t
+__gar_endian_uint16_t(uint16_t x)
+{
+ return ((x >> 8) & 0xffu) | ((x & 0xffu) << 8);
+}
-// platform has byteswap.h
-#include <byteswap.h>
-#define __gar_endian_int16_t(x) (int16_t)(bswap_16(x))
-#define __gar_endian_int32_t(x) (int32_t)(bswap_32(x))
-#define __gar_endian_int64_t(x) (int64_t)(bswap_64(x))
-#define __gar_endian_uint16_t(x) (uint16_t)(bswap_16(x))
-#define __gar_endian_uint32_t(x) (uint32_t)(bswap_32(x))
-#define __gar_endian_uint64_t(x) (uint64_t)(bswap_64(x))
+static inline uint32_t
+__gar_endian_uint32_t(uint32_t x)
+{
+ return (((x & 0xff000000u) >> 24) |
+ ((x & 0x00ff0000u) >> 8) |
+ ((x & 0x0000ff00u) << 8) |
+ ((x & 0x000000ffu) << 24));
+}
-#else
+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));
+}
-// generic platform - define swapping
-#define __gar_endian_uint16_t(x) (uint16_t)((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))
-#define __gar_endian_uint32_t(x) (uint32_t)((((x) & 0xff000000u) >> 24) | \
-(((x) & 0x00ff0000u) >> 8) | \
-(((x) & 0x0000ff00u) << 8) | \
-(((x) & 0x000000ffu) << 24))
-#define __gar_endian_uint64_t(x) (uint64_t)((((x) & 0xff00000000000000ull) >> 56) | \
-(((x) & 0x00ff000000000000ull) >> 40) | \
-(((x) & 0x0000ff0000000000ull) >> 24) | \
-(((x) & 0x000000ff00000000ull) >> 8) | \
-(((x) & 0x00000000ff000000ull) << 8) | \
-(((x) & 0x0000000000ff0000ull) << 24) | \
-(((x) & 0x000000000000ff00ull) << 40) | \
-(((x) & 0x00000000000000ffull) << 56))
-#define __gar_endian_int16_t(x) (int16_t)((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))
-#define __gar_endian_int32_t(x) (int32_t)((((x) & 0xff000000u) >> 24) | \
-(((x) & 0x00ff0000u) >> 8) | \
-(((x) & 0x0000ff00u) << 8) | \
-(((x) & 0x000000ffu) << 24))
-#define __gar_endian_int64_t(x) (int64_t)((((x) & 0xff00000000000000ull) >> 56) | \
-(((x) & 0x00ff000000000000ull) >> 40) | \
-(((x) & 0x0000ff0000000000ull) >> 24) | \
-(((x) & 0x000000ff00000000ull) >> 8) | \
-(((x) & 0x00000000ff000000ull) << 8) | \
-(((x) & 0x0000000000ff0000ull) << 24) | \
-(((x) & 0x000000000000ff00ull) << 40) | \
-(((x) & 0x00000000000000ffull) << 56))
-#endif // !HAVE_BYTESWAP_H
+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)
{
- uint32_t __uv = gar_endian(uint32_t, *(uint32_t *)&x);
- return *(float *) &__uv;
+ 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)
{
- uint64_t __uv = gar_endian(uint64_t, *(uint64_t *)&x);
- return *(double *) &__uv;
+ union {
+ uint64_t _u;
+ double _d;
+ } _v;
+
+ _v._d = x;
+ _v._u = gar_endian(uint64_t, _v._u);
+ return _v._d;
}
#endif // HAVE_BIGENDIAN
@@ -190,10 +221,10 @@ __gar_endian_double(double x)
// 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((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((p), (src))
+#define gar_ptr_store(t, p, src) __gar_ptr_store_ ## t((uint8_t *)(p), (src))
#if defined(CAN_UNALIGNED) && !defined(HAVE_BIGENDIAN)
@@ -226,14 +257,19 @@ __gar_endian_double(double x)
#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
-#define __gar_ptr_store_uint24_t(p, src) \
-do \
-{ \
- __gar_ptr_store_uint16_t(p, src & 0xfffu); \
- p[2] = src >> 16; \
-} while (0)
-#define __gar_ptr_store_int24_t(p, src) \
-__gar_ptr_store_uint24_t(p, src)
+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
@@ -244,79 +280,177 @@ __gar_ptr_store_uint24_t(p, src)
#define gar_store(t, dst, src) gar_ptr_store(t, (uint8_t *)&(dst), src)
// load from pointer - read'n'shift bytes
-#define __gar_ptr_load_int16_t(p) ((int16_t)((p)[0] | ((p)[1] << 8)))
-#define __gar_ptr_load_int24_t(p) ((int32_t)((p)[0] | ((p)[1] << 8) | \
-((p)[2] << 16)))
-#define __gar_ptr_load_int32_t(p) ((int32_t)((p)[0] | ((p)[1] << 8) | \
-((p)[2] << 16) | ((p)[3] << 24)))
-#define __gar_ptr_load_int64_t(p) ((int64_t)gar_ptr_load_int32(p) | \
-(((int64_t)gar_ptr_load_int32((p) + 4)) << 32))
-#define __gar_ptr_load_uint16_t(p) ((uint16_t)((p)[0] | ((p)[1] << 8)))
-#define __gar_ptr_load_uint24_t(p) ((uint32_t)((p)[0] | ((p)[1] << 8) | \
-((p)[2] << 16)))
-#define __gar_ptr_load_uint32_t(p) ((uint32_t)((p)[0] | ((p)[1] << 8) | \
-((p)[2] << 16) | ((p)[3] << 24)))
-#define __gar_ptr_load_uint64_t(p) ((uint64_t)__gar_ptr_load_uint32_t(p) | \
-(((uint64_t)__gar_ptr_load_uint32_t((p) + 4)) << 32))
+// 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(uint8_t * p)
+__gar_ptr_load_float(const uint8_t * p)
{
- uint32_t __uv = gar_ptr_load(uint32_t, p);
- return *(float *) &__uv;
+ 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(uint8_t * p)
+__gar_ptr_load_double(const uint8_t * p)
{
- uint64_t __uv = gar_ptr_load(uint64_t, p);
- return *(double *) &__uv;
+ 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
-#define __gar_ptr_store_uint16_t(p, src) \
-do \
-{ \
- p[0] = src & 0xffu; \
- p[1] = (src >> 8) & 0xffu; \
-} while (0)
-#define __gar_ptr_store_uint24_t(p, src) \
-do \
-{ \
- p[0] = src & 0xffu; \
- p[1] = (src >> 8) & 0xffu; \
- p[2] = (src >> 16) & 0xffu; \
-} while (0)
-#define __gar_ptr_store_uint32_t(p, src) \
-do \
-{ \
- p[0] = src & 0xffu; \
- p[1] = (src >> 8) & 0xffu; \
- p[2] = (src >> 16) & 0xffu; \
- p[3] = (src >> 24) & 0xffu; \
-} while (0)
-#define __gar_ptr_store_uint64_t(p, src) \
-do \
-{ \
- __gar_ptr_store_uint32_t(p, src & 0xffffffffu); \
- __gar_ptr_store_uint32_t(p + 4, src >> 32); \
-} while (0)
-#define __gar_ptr_store_int16_t(p, src) __gar_ptr_store_uint16_t(p, src)
-#define __gar_ptr_store_int24_t(p, src) __gar_ptr_store_uint24_t(p, src)
-#define __gar_ptr_store_int32_t(p, src) __gar_ptr_store_uint32_t(p, src)
-#define __gar_ptr_store_int64_t(p, src) __gar_ptr_store_uint64_t(p, src)
-#define __gar_ptr_store_float(p, src) \
-do \
-{ \
- float __fv = gar_endian(float, src); \
- memcpy(p, &__fv, 4); \
-} while (0)
-#define __gar_ptr_store_double(p, src) \
-do \
-{ \
- _double __dv = gar_endian(double, src); \
- memcpy(p, &__dv, 8); \
-} while (0)
+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__
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/garmindev.git
More information about the Pkg-grass-devel
mailing list