1 /*
2 
3     Track reader for "Dell Axim Navigation System" GPB files,
4 
5     Copyright (C) 2006 Olaf Klein, o.b.klein@gpsbabel.org
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21  */
22 
23 #include <ctype.h>
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include "defs.h"
29 
30 #define MYNAME "axim_gpb"
31 
32 #define RECORD_LEN	344
33 
34 static gbfile* fin;
35 
36 static
37 arglist_t axim_gpb_args[] = {
38   ARG_TERMINATOR
39 };
40 
41 static float
le_read32_float(const void * src)42 le_read32_float(const void* src)
43 {
44   float f;
45   int32_t i;
46 
47   i = le_read32(src);
48   memcpy(&f, &i, 4);
49 
50   return f;
51 }
52 
53 static void
decode_buff(const char * buff,route_head * track)54 decode_buff(const char* buff, route_head* track)
55 {
56   struct tm tm;
57   double lat, lon, alt, dir;
58   float vdop, hdop, pdop, spd, Uf1;
59   int sats;
60   waypoint* wpt;
61 
62   wpt = waypt_new();
63 
64   memset(&tm, '\0', sizeof(tm));
65 
66   tm.tm_year = le_read16((void*)(buff + 16));
67   tm.tm_mon = le_read16((void*)(buff + 18));
68   tm.tm_mday = le_read16((void*)(buff + 22));
69   tm.tm_hour = le_read16((void*)(buff + 24));
70   tm.tm_min = le_read16((void*)(buff + 26));
71   tm.tm_sec = le_read16((void*)(buff + 28));
72   lat = le_read_double((void*)(buff + 32));
73   lon = le_read_double((void*)(buff + 40));
74   spd = le_read32_float((void*)(buff + 48));
75   dir = le_read32_float((void*)(buff + 52));
76 
77   alt = le_read32_float((void*)(buff + 64));
78   Uf1 = le_read32_float((void*)(buff + 68));
79 
80   hdop = le_read32_float((void*)(buff + 84));
81   vdop = le_read32_float((void*)(buff + 88));
82   pdop = le_read32_float((void*)(buff + 92));
83   sats = le_read16((void*)(buff + 96));
84 
85   wpt->latitude = lat;
86   wpt->longitude = lon;
87   wpt->altitude = alt;
88 #if 0
89   /* These values can be, but must not be right. */
90   /* Further checks are needed to verify that. */
91   /*         (!!! reference data !!!)          */
92   WAYPT_SET(wpt, course, dir);
93   wpt->hdop = hdop;
94   wpt->vdop = vdop;
95   wpt->pdop = pdop;
96   wpt->sat = sats;
97   WAYPT_SET(wpt, speed, spd * 10);
98 #endif
99   /* We don't have a header with some magic fixed numbers or strings. */
100   /* So let us check the range for some basic values */
101 
102   is_fatal(
103     (tm.tm_year < 2005) ||
104     (tm.tm_mon < 1) || (tm.tm_mon > 12) ||
105     (tm.tm_mday < 1) || (tm.tm_mday > 31) ||
106     (tm.tm_hour > 23) || (tm.tm_min > 60) || (tm.tm_sec > 60),
107     MYNAME ": Invalid or unsupported file (invalid time-stamp).");
108   is_fatal(
109     (fabs(wpt->latitude) > 90) ||
110     (fabs(wpt->longitude) > 180),
111     MYNAME ": Invalid or unsupported file (lat or/and lon out of range).");
112 
113   /* post work */
114 
115   tm.tm_year-=1900;
116   tm.tm_mon--;
117   wpt->SetCreationTime(mkgmtime(&tm));
118 
119   track_add_wpt(track, wpt);
120 }
121 
122 /*******************************************************************************
123 * %%%        global callbacks called by gpsbabel main process              %%% *
124 *******************************************************************************/
125 
126 static void
axim_gpb_rd_init(const char * fname)127 axim_gpb_rd_init(const char* fname)
128 {
129   fin = gbfopen(fname, "rb", MYNAME);
130 }
131 
132 static void
axim_gpb_rd_deinit(void)133 axim_gpb_rd_deinit(void)
134 {
135   gbfclose(fin);
136 }
137 
138 static void
axim_gpb_read(void)139 axim_gpb_read(void)
140 {
141   char buff[RECORD_LEN];
142   route_head* track = NULL;
143   size_t bytes;
144 
145   while ((bytes = gbfread(buff, 1, RECORD_LEN, fin))) {
146     is_fatal((bytes != RECORD_LEN), MYNAME ": Invalid or unsupported file (filesize).");
147     if (track == NULL) {
148       track = route_head_alloc();
149       track_add_head(track);
150     }
151     decode_buff(buff, track);
152   }
153 }
154 
155 /**************************************************************************/
156 
157 ff_vecs_t axim_gpb_vecs = {
158   ff_type_file,
159   {
160     ff_cap_none 	/* waypoints */,
161     ff_cap_read 	/* tracks */,
162     ff_cap_none 	/* routes */,
163   },
164   axim_gpb_rd_init,
165   NULL,
166   axim_gpb_rd_deinit,
167   NULL,
168   axim_gpb_read,
169   NULL,
170   NULL,
171   axim_gpb_args,
172   CET_CHARSET_ASCII, 0
173 };
174 /**************************************************************************/
175