[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