00001 /***************************************************************************** 00002 * 00003 * $RCSfile: DataExchange_8c-source.html,v $ 00004 * 00005 * GPS4Palm Data Exchange using Garmin Protocol 00006 * 00007 * 00008 * This program is Copyright (C) 12/2002 Matthias Prinke 00009 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00010 * In particular, this program is free software and comes WITHOUT 00011 * ANY WARRANTY. 00012 * 00013 * $Author: mp $ 00014 * 00015 * $Date: 2007-10-08 20:40:32 $ 00016 * 00017 * $Revision: 1.7.2.1 $ 00018 * 00019 * $Log: DataExchange_8c-source.html,v $ 00019 * Revision 1.7.2.1 2007-10-08 20:40:32 mp 00019 * updated for gps4palm V0.9.5 beta 00019 * 00020 * Revision 1.12 2004-12-14 20:10:47 mp 00021 * fixed alert 00022 * 00023 * Revision 1.11 2004/12/08 20:51:52 mp 00024 * removed debug output 00025 * 00026 * Revision 1.10 2004/12/06 21:11:53 mp 00027 * implemented get_next_trk() 00028 * 00029 * Revision 1.9 2004/12/04 13:35:06 mp 00030 * implemented NumTrkPackets() and store_trk() 00031 * 00032 * Revision 1.8 2004/11/27 10:16:08 mp 00033 * replaced ErrFatalDisplay() by Die() for memory allocation failures 00034 * 00035 * Revision 1.7 2004/11/24 21:05:24 mp 00036 * moved static function declarations from header to implementation file 00037 * 00038 * Revision 1.6 2004/11/23 17:54:06 mp 00039 * removed unused variables 00040 * 00041 * Revision 1.5 2004/11/17 19:46:33 mp 00042 * modified interface to Data.c ( PackWaypoint(), PackRouteHdr(), and 00043 * PackRouteWpt() ), removed debug output, added exception handling for 00044 * creation of new route/waypoint 00045 * 00046 * Revision 1.4 2004/11/11 18:48:47 mp 00047 * fixed triggering of table update, added TermStr() 00048 * 00049 * Revision 1.3 2004/06/23 18:32:16 mp 00050 * updated comments 00051 * 00052 * Revision 1.2 2004/06/23 18:25:39 mp 00053 * added NumRtePackets(), fixed Route transfers 00054 * 00055 * Revision 1.1 2004/04/29 20:11:35 mp 00056 * initial version 00057 * 00058 * 00059 ****************************************************************************/ 00060 #define DO_NOT_ALLOW_ACCESS_TO_INTERNALS_OF_STRUCTS 00061 #include <BuildDefines.h> 00062 #ifdef DEBUG_BUILD 00063 #define ERROR_CHECK_LEVEL ERROR_CHECK_FULL 00064 #endif 00065 #include <PalmOS.h> 00066 #include <SerialMgrOld.h> 00067 #include "ResourceDefines.h" 00068 #include "gpslib.h" 00069 #include "Data.h" 00070 #include "DataExchange.h" 00071 #include "WaypointForm.h" 00072 #include "RouteForm.h" 00073 #include "TrackForm.h" 00074 #include "Utils.h" 00075 #include "Serial.h" 00076 #include "Utils.h" 00077 #include "common.h" 00078 00079 /* Global Variables */ 00080 extern PrefsType gPrefs; /* application preferences */ 00081 00082 /* Static Functions */ 00083 static void TermStr(char *str, UInt16 len) DATAEXCHANGE_SECTION; 00084 00085 00086 /****************************************************************************/ 00087 /** 00088 * \brief Callback function to retrieve waypoint from database 00089 * for transmission to host. 00090 * 00091 * 00092 * \param current current waypoint count (zero-based) 00093 * \param format Garmin Object format ID 00094 * (only G104Type supported) 00095 * \param size size of structure returned by get_next_wpt 00096 * 00097 * \note The function's prototype is defined by gpslib 00098 * (GetNextWptCallbackProc). 00099 * 00100 * \return Pointer to Waypoint Object structure, 00101 * NULL if waypoint transfer done or wrong protocol ID. 00102 ****************************************************************************/ 00103 GarminObject *get_next_wpt(UInt16 current, LocalFormatID format, 00104 unsigned char *size) 00105 { 00106 static GarminObject wpt; /* waypoint (Garmin packet) */ 00107 UInt16 rec = 0; /* record nr */ 00108 static MemHandle waypointDBEntry = NULL; /* record handle */ 00109 waypoint_t waypoint; /* unpacked waypoint */ 00110 packed_waypoint_t *packed_waypoint; /* packed waypoint (ptr) */ 00111 Int16 i = 0; /* loop index */ 00112 UInt32 tmp; /* var. for conversion */ 00113 00114 if (format == G104Type) { 00115 /* Init waypoint */ 00116 MemSet((Char *)&wpt.d104.ident, 6, 0); 00117 MemSet((Char *)&wpt.d104.dst, sizeof(wpt.d104.dst), 0); 00118 MemSet((Char *)&wpt.d104.cmnt, sizeof(wpt.d104.cmnt), 0); 00119 00120 /* seek to record */ 00121 DmSeekRecordInCategory(gWaypointDB, &rec /* index */, current /* offset */, 00122 dmSeekForward, dmAllCategories); 00123 00124 if (waypointDBEntry) { 00125 MemHandleUnlock(waypointDBEntry); 00126 waypointDBEntry = NULL; 00127 } 00128 00129 /* get record */ 00130 waypointDBEntry = DmQueryNextInCategory(gWaypointDB, &rec, 00131 dmAllCategories); 00132 00133 /* unpack record */ 00134 packed_waypoint = (packed_waypoint_t *)MemHandleLock(waypointDBEntry); 00135 UnpackWaypoint(&waypoint, packed_waypoint); 00136 00137 /* Copy Identifier */ 00138 StrNCopy(wpt.d104.ident, waypoint.ident, 6); 00139 00140 /* Copy Latitude and Longitude */ 00141 tmp = waypoint.posn.lat; 00142 for (i=0; i<sizeof(wpt.d104.lat); i++) { 00143 wpt.d104.lat[i] = (G_byte)(tmp & 0xFF); 00144 tmp >>= 8; 00145 } 00146 00147 tmp = waypoint.posn.lon; 00148 for (i=0; i<sizeof(wpt.d104.lon); i++) { 00149 wpt.d104.lon[i] = (G_byte)(tmp & 0xFF); 00150 tmp >>= 8; 00151 } 00152 00153 /* 00154 * Note: Proxmity Distance only valid during 00155 * Proximity Waypoint Transfer Protocol 00156 */ 00157 00158 /* Copy Symbol */ 00159 tmp = waypoint.smbl; 00160 for (i=0; i<sizeof(wpt.d104.smbl); i++) { 00161 wpt.d104.smbl[i] = (G_byte)(tmp & 0xFF); 00162 tmp >>= 8; 00163 } 00164 00165 /* Copy Display Mode */ 00166 wpt.d104.dspl = (G_byte)waypoint.dspl; 00167 00168 /* Copy Comment */ 00169 StrNCopy(wpt.d104.cmnt, waypoint.cmnt, 40); 00170 00171 } else { 00172 /* unknown protocol */ 00173 return NULL; 00174 } 00175 00176 *size = sizeof(wpt.d104); 00177 00178 /* last waypoint sent? */ 00179 if (current == DmNumRecordsInCategory(gWaypointDB, dmAllCategories)) 00180 return NULL; 00181 00182 return &wpt; 00183 } 00184 00185 00186 /****************************************************************************/ 00187 /** 00188 * \brief Callback function to retrieve route from database 00189 * for transmission to host. 00190 * 00191 * 00192 * \param current current item number (header or waypoint, 00193 * first=0) 00194 * \param format Garmin Object format ID 00195 * (only G104Type and G201Type supported) 00196 * \param size size of structure returned by get_next_rte 00197 * \param h True if current packet is a Route Header, 00198 * else false 00199 * \param eor True if current Route Waypoint is the end of 00200 * the current route, else false 00201 * 00202 * \note The function's prototype is defined by gpslib 00203 * (GetNextRteCallbackProc). 00204 * 00205 * \return Pointer to Waypoint/Route Object structure, 00206 * NULL if transfer done or wrong protocol ID. 00207 ****************************************************************************/ 00208 GarminObject *get_next_rte(UInt16 current, LocalFormatID format, 00209 unsigned char *size, Boolean * h, Boolean * eor) 00210 { 00211 Err err; /* error code */ 00212 static GarminObject wpt; /* waypoint (Garmin packet) */ 00213 static GarminObject rte; /* route (Garmin packet) */ 00214 static route_t *route; /* route */ 00215 static MemHandle waypointDBEntry = NULL; /* waypoint record handle */ 00216 static MemHandle routeDBEntry = NULL; /* route record handle */ 00217 static UInt16 rte_nr = 0; /* route number */ 00218 static UInt16 wpt_nr = 0; /* waypoint number */ 00219 UInt16 rec = 0; /* record nr */ 00220 waypoint_t waypoint; /* unpacked waypoint */ 00221 packed_waypoint_t *packed_waypoint; /* packed waypoint (ptr) */ 00222 Int16 i = 0; /* loop index */ 00223 UInt32 tmp; /* var. for conversion */ 00224 00225 if (format == G104Type) { 00226 /* 00227 * StrPrintF(buf, "%d/%d ", wpt_nr, route->items); 00228 * WinDrawChars(buf, StrLen(buf), cnt * 20, 15); 00229 * cnt++; 00230 */ 00231 00232 /* Init waypoint */ 00233 MemSet((Char *)&wpt.d104.ident, 6, 0); 00234 MemSet((Char *)&wpt.d104.dst, sizeof(wpt.d104.dst), 0); 00235 MemSet((Char *)&wpt.d104.cmnt, sizeof(wpt.d104.cmnt), 0); 00236 00237 if (waypointDBEntry) { 00238 /* unlock old record handle */ 00239 MemHandleUnlock(waypointDBEntry); 00240 waypointDBEntry = NULL; 00241 } 00242 00243 err = DmFindRecordByID(gWaypointDB, 00244 route->wpt_rec_id[wpt_nr], &rec); 00245 00246 if (err) { 00247 /* unique ID not found */ 00248 *eor = false; 00249 return NULL; 00250 } 00251 00252 /* get record */ 00253 waypointDBEntry = DmQueryNextInCategory(gWaypointDB, &rec, 00254 dmAllCategories); 00255 00256 /* unpack record */ 00257 packed_waypoint = (packed_waypoint_t *)MemHandleLock(waypointDBEntry); 00258 UnpackWaypoint(&waypoint, packed_waypoint); 00259 00260 /* Copy Identifier */ 00261 StrNCopy(wpt.d104.ident, waypoint.ident, 6); 00262 00263 /* Copy Latitude and Longitude */ 00264 tmp = waypoint.posn.lat; 00265 for (i=0; i<sizeof(wpt.d104.lat); i++) { 00266 wpt.d104.lat[i] = (G_byte)(tmp & 0xFF); 00267 tmp >>= 8; 00268 } 00269 00270 tmp = waypoint.posn.lon; 00271 for (i=0; i<sizeof(wpt.d104.lon); i++) { 00272 wpt.d104.lon[i] = (G_byte)(tmp & 0xFF); 00273 tmp >>= 8; 00274 } 00275 00276 /* 00277 * Note: Proxmity Distance only valid during 00278 * Proximity Waypoint Transfer Protocol 00279 */ 00280 00281 /* Copy Symbol */ 00282 tmp = waypoint.smbl; 00283 for (i=0; i<sizeof(wpt.d104.smbl); i++) { 00284 wpt.d104.smbl[i] = (G_byte)(tmp & 0xFF); 00285 tmp >>= 8; 00286 } 00287 00288 /* Copy Display Mode */ 00289 wpt.d104.dspl = (G_byte)waypoint.dspl; 00290 00291 /* Copy Comment */ 00292 StrNCopy(wpt.d104.cmnt, waypoint.cmnt, 40); 00293 00294 /* size of waypoint struct */ 00295 *size = sizeof(wpt.d104); 00296 00297 /* last waypoint sent? set end-of-route flag */ 00298 *eor = (wpt_nr == route->items-1) ? true : false; 00299 00300 /* protocol error: past end of last waypoint */ 00301 if (wpt_nr == route->items) { 00302 *h = false; 00303 return NULL; 00304 } 00305 00306 /* increment waypoint count */ 00307 wpt_nr++; 00308 00309 /* current packet is a Route Waypoint */ 00310 *h = false; 00311 00312 return &wpt; 00313 00314 } else if (format == G201Type) { 00315 /* route header, reset waypoint count */ 00316 wpt_nr = 0; 00317 00318 if (current == 0) { 00319 /* start of route transfer */ 00320 rte_nr = 0; 00321 } 00322 /* 00323 * StrPrintF(buf, "%d ", rte_nr); 00324 * WinDrawChars(buf, StrLen(buf), cnt * 15, 30); 00325 * cnt++; 00326 */ 00327 /* Init route */ 00328 MemSet((Char *)&rte.d201.cmnt, sizeof(rte.d201.cmnt), 0); 00329 00330 /* seek to record */ 00331 DmSeekRecordInCategory(gRouteDB, &rec /* index */, rte_nr /* offset */, 00332 dmSeekForward, dmAllCategories); 00333 00334 if (routeDBEntry) { 00335 /* unlock old record handle */ 00336 MemHandleUnlock(routeDBEntry); 00337 routeDBEntry = NULL; 00338 } 00339 00340 /* get record */ 00341 routeDBEntry = DmQueryNextInCategory(gRouteDB, &rec, 00342 dmAllCategories); 00343 00344 route = MemHandleLock(routeDBEntry); 00345 00346 /* Copy Route Number */ 00347 rte.d201.nmbr = route->nmbr; 00348 00349 /* Copy Comment */ 00350 StrNCopy(rte.d201.cmnt, route->cmnt, 20); 00351 00352 /* size of route struct */ 00353 *size = sizeof(rte.d201); 00354 00355 /* last route sent? */ 00356 if (rte_nr == DmNumRecordsInCategory(gRouteDB, dmAllCategories)) { 00357 return NULL; 00358 } 00359 00360 /* increment route counter */ 00361 rte_nr++; 00362 00363 /* current packet is a Route Header */ 00364 *h = true; 00365 00366 /* no End of Route */ 00367 *eor = false; 00368 00369 return &rte; 00370 00371 } else { 00372 /* unknown protocol */ 00373 return NULL; 00374 } 00375 00376 } 00377 00378 /****************************************************************************/ 00379 /** 00380 * \brief Callback function to to retrieve track from database 00381 * for transmission to host. 00382 * 00383 * \param current index of current element (first=0) 00384 * \param format format of element requested 00385 * \param size pointer to store size of element returned 00386 * \param eot true if the current item is the 00387 * last element of current track 00388 * 00389 * \return pointer on element returned (Garmin format) 00390 ****************************************************************************/ 00391 GarminObject *get_next_trk(UInt16 current, LocalFormatID format, 00392 byte *size, Boolean * eot) 00393 { 00394 static GarminObject trkh; /* track header (Garmin) */ 00395 static GarminObject trkp; /* track point (Garmin) */ 00396 trk_point_t *trkpoint; /* track point */ 00397 trk_header_t *trkheader; /* track header */ 00398 static UInt16 trkh_index; /* track header index */ 00399 static UInt16 trkp_index; /* track point index */ 00400 static DmOpenRef db_ref; /* data base reference */ 00401 static UInt16 num_points; /* number of track points */ 00402 static UInt16 point = 0; /* track point number */ 00403 static UInt16 track; /* track number */ 00404 MemHandle trkhDBEntry; /* trk. header record handle */ 00405 MemHandle trkpDBEntry; /* trk. point record handle */ 00406 Char dbname[dmDBNameLength]; /* data base name */ 00407 UInt32 trackID; /* track ID */ 00408 static UInt16 num_tracks; /* number of tracks */ 00409 UInt32 tmp; /* var. for conversion */ 00410 UInt16 i; /* loop index */ 00411 00412 if ((format != G300Type) && (format != G310Type)) { 00413 /* unknown protocol */ 00414 return NULL; 00415 } 00416 00417 if ((format == G310Type) || (current == 0) || (point == 0)) { 00418 /* track header */ 00419 00420 if (current == 0) { 00421 /* get number of all tracks in Track Header DB */ 00422 num_tracks = DmNumRecordsInCategory(gTrackHdrDB, dmAllCategories); 00423 00424 trkh_index = 0; 00425 point = 0; 00426 track = 0; 00427 } 00428 00429 /* loop until non-empty track DB found */ 00430 do { 00431 if (track == num_tracks) { 00432 *eot = true; 00433 *size = 0; 00434 return NULL; 00435 } 00436 00437 trkp_index = 0; 00438 00439 /* query next track */ 00440 trkhDBEntry = DmQueryNextInCategory(gTrackHdrDB, &trkh_index, 00441 dmAllCategories); 00442 00443 trkhDBEntry = DmQueryRecord(gTrackHdrDB, trkh_index); 00444 00445 /* get unique Track ID */ 00446 DmRecordInfo(gTrackHdrDB, trkh_index, NULL /* *attrP */, 00447 &trackID /* *uniqueIDP */, NULL /* *chunkIDP */); 00448 00449 /* create track data base name */ 00450 TrackDBName(dbname, trackID); 00451 00452 /* open track point data base */ 00453 db_ref = DmOpenDatabase(0 /* cardNo */, 00454 DmFindDatabase(0 /* cardNo */, dbname), dmModeReadOnly); 00455 00456 trkh_index++; 00457 track++; 00458 00459 if (db_ref) { 00460 /* open succeeded, get number of track points */ 00461 num_points = DmNumRecordsInCategory(db_ref, dmAllCategories); 00462 00463 if (num_points == 0) { 00464 /* close track point data base */ 00465 DmCloseDatabase(db_ref); 00466 } 00467 00468 } /* if (db_ref) */ 00469 } while (num_points == 0); 00470 00471 if (format == G310Type) { 00472 trkheader = (trk_header_t *)MemHandleLock(trkhDBEntry); 00473 00474 /* copy track header for transfer to host */ 00475 trkh.d310.dspl = trkheader->dspl; 00476 trkh.d310.color = trkheader->color; 00477 StrNCopy(trkh.d310.trk_ident, trkheader->trk_ident, 49); 00478 00479 MemHandleUnlock(trkhDBEntry); 00480 *size = sizeof(trkh.d310); 00481 return &trkh; 00482 } 00483 } 00484 00485 if (format == G300Type) { 00486 /* track point */ 00487 00488 /* query next track point */ 00489 trkpDBEntry = DmQueryNextInCategory(db_ref, &trkp_index, 00490 dmAllCategories); 00491 00492 trkpDBEntry = DmQueryRecord(db_ref, trkp_index); 00493 00494 trkpoint = (trk_point_t *)MemHandleLock(trkpDBEntry); 00495 00496 /* Copy Latitude and Longitude */ 00497 tmp = trkpoint->posn.lat; 00498 for (i=0; i<sizeof(trkp.d300.lat); i++) { 00499 trkp.d300.lat[i] = (G_byte)(tmp & 0xFF); 00500 tmp >>= 8; 00501 } 00502 00503 tmp = trkpoint->posn.lon; 00504 for (i=0; i<sizeof(trkp.d300.lon); i++) { 00505 trkp.d300.lon[i] = (G_byte)(tmp & 0xFF); 00506 tmp >>= 8; 00507 } 00508 00509 /* Copy Time */ 00510 tmp = trkpoint->time; 00511 for (i=0; i<sizeof(trkp.d300.time); i++) { 00512 trkp.d300.time[i] = (G_byte)(tmp & 0xFF); 00513 tmp >>= 8; 00514 } 00515 00516 trkp.d300.new_trk = trkpoint->new_trk; 00517 00518 /* unlock record handle */ 00519 MemHandleUnlock(trkpDBEntry); 00520 00521 trkp_index++; 00522 00523 /* last track point sent? */ 00524 if (point == num_points-1) { 00525 /* close track point data base */ 00526 DmCloseDatabase(db_ref); 00527 00528 /* set end-of-track flag */ 00529 *eot = true; 00530 point = 0; 00531 00532 } else { 00533 *eot = false; 00534 point++; 00535 } 00536 00537 *size = sizeof(trkp.d300); 00538 return &trkp; 00539 00540 } 00541 00542 return NULL; 00543 } 00544 00545 00546 /****************************************************************************/ 00547 /** 00548 * \brief Callback function to store waypoint to database upon 00549 * reception from host. 00550 * 00551 * If a waypoint with the same waypoint ID already exists, 00552 * it is modified if required. 00553 * 00554 * \param wpt ptr to GarminObject 00555 * \param total total number of packets 00556 * \param current packet number (one-based), for the 00557 * D104 protocol, this can also be used as the 00558 * number of the current waypoint 00559 * \param format Garmin Object format ID 00560 * (only G104Type supported) 00561 * \param size size of structure pointed to by wpt 00562 * 00563 * \note The function's prototype is defined by gpslib 00564 * (StoreWptCallbackProc). 00565 * 00566 * \return 0 - success, 00567 * 1 - failure 00568 ****************************************************************************/ 00569 Err store_wpt(GarminObject* wpt, UInt16 total, UInt16 current, 00570 LocalFormatID format, byte size) 00571 { 00572 waypoint_t waypoint; /* unpacked waypoint */ 00573 UInt16 index; /* record index */ 00574 Int16 i; /* loop index */ 00575 MemHandle h; /* memory handle */ 00576 Boolean wpt_exists = false; /* flag: waypoint already exists */ 00577 00578 if (format == G104Type) { 00579 /* Init waypoint */ 00580 MemSet((Char *)waypoint.ident, 6, 0); 00581 waypoint.posn.lat = 0; 00582 waypoint.posn.lon = 0; 00583 waypoint.dst = 0.0; 00584 waypoint.smbl = 0; 00585 00586 /* Copy Identifier */ 00587 StrNCopy(waypoint.ident, wpt->d104.ident, 6); 00588 00589 /* Copy Latitude and Longitude */ 00590 for (i=sizeof(waypoint.posn.lat)-1; i>=0; i--) { 00591 waypoint.posn.lat <<= 8; 00592 waypoint.posn.lat |= (G_byte)wpt->d104.lat[i]; 00593 waypoint.posn.lon <<= 8; 00594 waypoint.posn.lon |= (G_byte)wpt->d104.lon[i]; 00595 } 00596 00597 /* 00598 * Note: Proxmity Distance only valid during 00599 * Proximity Waypoint Transfer Protocol 00600 */ 00601 00602 /* Copy Symbol */ 00603 for (i=sizeof(waypoint.smbl)-1; i>=0; i--) { 00604 waypoint.smbl <<= 8; 00605 waypoint.smbl |= (G_byte)wpt->d104.smbl[i]; 00606 } 00607 00608 /* Copy Display Mode */ 00609 waypoint.dspl = (G_byte)wpt->d104.dspl; 00610 00611 /* Copy Comment */ 00612 for (i=0; i<40; i++) { 00613 waypoint.cmnt[i] = wpt->d104.cmnt[i]; 00614 } 00615 TermStr(waypoint.cmnt, 40); 00616 00617 /* Find sort position of new record in waypoint DB */ 00618 index = DmFindSortPosition(gWaypointDB, &waypoint, 0 /* newRecordInfo */, 00619 (DmComparF *)CompareWayptIdent /* DmComparF *compar */, 0 /* other */); 00620 00621 if (index > 0) { 00622 /* check if waypoint with same ID already exists */ 00623 packed_waypoint_t *packed_waypoint; /* packed waypoint (ptr) */ 00624 00625 h = DmQueryRecord(gWaypointDB, index - 1); 00626 packed_waypoint = MemHandleLock(h); 00627 if (StrNCompare(waypoint.ident, packed_waypoint->ident, 6) == 0) { 00628 wpt_exists = true; 00629 /* preserve proximity distance */ 00630 waypoint.dst = packed_waypoint->dst; 00631 /* overwrite waypoint */ 00632 index--; 00633 } 00634 MemHandleUnlock(h); 00635 } 00636 00637 if (!wpt_exists) { 00638 h = DmNewRecord(gWaypointDB, &index, 00639 1 /* size, will be set by PackWaypoint() */); 00640 00641 if (h) { 00642 DmReleaseRecord(gWaypointDB, index, false /* dirty */); 00643 } else { 00644 Die("Cannot create waypoint record!"); 00645 } 00646 } 00647 00648 /* Pack Waypoint and store it in Database */ 00649 PackWaypoint(&waypoint, index); 00650 00651 /* redraw the table */ 00652 if ((current == total) && (FrmGetActiveFormID() == RouteForm)) 00653 routeDrawTable(); 00654 00655 if ((current == total) && (FrmGetActiveFormID() == WaypointForm)) 00656 wayptDrawTable(); 00657 00658 /* success */ 00659 return 0; 00660 } else { 00661 /* failure (wrong protocol) */ 00662 return gpslibErrParamErr; 00663 } 00664 } 00665 00666 00667 /****************************************************************************/ 00668 /** 00669 * \brief Callback function to store route to database upon 00670 * reception from host. 00671 * 00672 * \param obj ptr to GarminObject 00673 * \param total total count of items sent as indicated by gps 00674 * \param current current item number (first=1) 00675 * \param format Garmin Object format ID 00676 * (only G104Type and G201Type supported) 00677 * \param size size of structure pointed to by rte 00678 * 00679 * \note The function's prototype is defined by gpslib 00680 * (StoreRteCallbackProc). 00681 * 00682 * \return 0 - success, 00683 * 1 - failure 00684 ****************************************************************************/ 00685 Err store_rte(GarminObject* obj, UInt16 total, UInt16 current, 00686 LocalFormatID format, byte size) 00687 { 00688 Err err; 00689 waypoint_t waypoint; /* unpacked waypoint */ 00690 UInt32 wpt_rec_id; /* unique wpt DB record ID */ 00691 UInt16 wpt_index; /* waypoint record index */ 00692 static UInt16 rte_index; /* route record index */ 00693 route_t route; /* route */ 00694 MemHandle rteH; /* route record handle */ 00695 route_t *rteP; /* ptr to route record */ 00696 MemHandle h; /* memory handle */ 00697 UInt16 i; /* loop index */ 00698 Boolean wpt_exists = false; /* flag: waypoint exists */ 00699 Boolean rte_exists = false; /* flag: route exists */ 00700 00701 if (format == G104Type) { 00702 /* store waypoint (as part of route) */ 00703 00704 /* Init waypoint */ 00705 MemSet((Char *)waypoint.ident, 6, 0); 00706 waypoint.posn.lat = 0; 00707 waypoint.posn.lon = 0; 00708 waypoint.dst = 0.0; 00709 waypoint.smbl = 0; 00710 00711 /* Copy Identifier */ 00712 StrNCopy(waypoint.ident, obj->d104.ident, 6); 00713 00714 /* Find sort position of new record in waypoint DB */ 00715 wpt_index = DmFindSortPosition(gWaypointDB, &waypoint, 00716 0 /* newRecordInfo */, 00717 (DmComparF *)CompareWayptIdent /* DmComparF *compar */, 0 /* other */); 00718 00719 if (wpt_index > 0) { 00720 /* check if waypoint with same ID already exists */ 00721 packed_waypoint_t *packed_waypoint; /* packed waypoint (ptr) */ 00722 00723 h = DmQueryRecord(gWaypointDB, wpt_index - 1); 00724 packed_waypoint = MemHandleLock(h); 00725 if (StrNCompare(waypoint.ident, packed_waypoint->ident, 6) == 0) { 00726 wpt_exists = true; 00727 /* preserve proximity distance */ 00728 waypoint.dst = packed_waypoint->dst; 00729 /* overwrite waypoint */ 00730 wpt_index--; 00731 } 00732 MemHandleUnlock(h); 00733 } 00734 00735 if (!wpt_exists) { 00736 /* Copy Latitude and Longitude */ 00737 for (i=sizeof(waypoint.posn.lat)-1; i>=0; i--) { 00738 waypoint.posn.lat <<= 8; 00739 waypoint.posn.lat |= (G_byte)obj->d104.lat[i]; 00740 waypoint.posn.lon <<= 8; 00741 waypoint.posn.lon |= (G_byte)obj->d104.lon[i]; 00742 } 00743 00744 /* Copy Symbol */ 00745 for (i=sizeof(waypoint.smbl)-1; i>=0; i--) { 00746 waypoint.smbl <<= 8; 00747 waypoint.smbl |= (G_byte)obj->d104.smbl[i]; 00748 } 00749 00750 /* Copy Display Mode */ 00751 waypoint.dspl = (G_byte)obj->d104.dspl; 00752 00753 /* Copy Comment */ 00754 for (i=0; i<40; i++) { 00755 waypoint.cmnt[i] = obj->d104.cmnt[i]; 00756 } 00757 TermStr(waypoint.cmnt, 40); 00758 00759 /* create new waypoint record */ 00760 h = DmNewRecord(gWaypointDB, &wpt_index, 00761 1 /* size, will be set by PackWaypoint() */); 00762 00763 if (h) { 00764 DmReleaseRecord(gWaypointDB, wpt_index, false /* dirty */); 00765 } else { 00766 Die("Cannot create waypoint record!"); 00767 } 00768 00769 /* Pack Waypoint and store it in Database */ 00770 PackWaypoint(&waypoint, wpt_index); 00771 00772 } 00773 00774 /* get record ID of waypoint */ 00775 err = DmRecordInfo(gWaypointDB, wpt_index, NULL, &wpt_rec_id, NULL); 00776 00777 /* add waypoint record ID to route record */ 00778 PackRouteWpt(wpt_rec_id, rte_index); 00779 00780 /* redraw the table */ 00781 if ((current == total) && (FrmGetActiveFormID() == RouteForm)) 00782 routeDrawTable(); 00783 00784 if ((current == total) && (FrmGetActiveFormID() == WaypointForm)) 00785 wayptDrawTable(); 00786 00787 /* success */ 00788 return 0; 00789 } else if (format == G201Type) { 00790 /* receiving route header */ 00791 00792 /* copy route number */ 00793 route.nmbr = obj->d201.nmbr; 00794 00795 /* copy route comment */ 00796 MemSet((Char *)route.cmnt, 21, 0); 00797 StrNCopy(route.cmnt, obj->d201.cmnt, 20); 00798 TermStr(route.cmnt, 20); 00799 00800 /* clear number of items (waypoints) */ 00801 route.items = 0; 00802 00803 /* Find sort position of new record in route DB */ 00804 rte_index = DmFindSortPosition(gRouteDB, &route, 0 /* newRecordInfo */, 00805 (DmComparF *)CompareRteNmbr /* DmComparF *compar */, 0 /* other */); 00806 00807 if (rte_index > 0) { 00808 /* check if route with same number already exists */ 00809 00810 rteH = DmQueryRecord(gRouteDB, rte_index - 1); 00811 rteP = MemHandleLock(rteH); 00812 if (route.nmbr == rteP->nmbr) { 00813 rte_exists = true; 00814 /* overwrite route */ 00815 rte_index--; 00816 } 00817 MemHandleUnlock(rteH); 00818 } 00819 00820 if (!rte_exists) { 00821 /* create new route record */ 00822 rteH = DmNewRecord(gRouteDB, &rte_index, 00823 1 /* size, will be set by PackRoute() */); 00824 00825 if (rteH) { 00826 DmReleaseRecord(gRouteDB, rte_index, false /* dirty */); 00827 } else { 00828 Die("Cannot create route record!"); 00829 } 00830 00831 } 00832 00833 /* Store Route Header in Database */ 00834 PackRouteHdr(&route, rte_index); 00835 00836 /* success */ 00837 return 0; 00838 } else { 00839 /* failure (wrong protocol) */ 00840 return gpslibErrParamErr; 00841 } 00842 } 00843 00844 00845 /****************************************************************************/ 00846 /** 00847 * \brief Callback function called when a track is received 00848 * 00849 * \param trk pointer on a raw track point or track header 00850 * received from gps 00851 * \param total total count of items sent as indicated by gps 00852 * \param current current item number (first=1) 00853 * \param format format of the object received 00854 * \param size size of object 00855 * 00856 * \return error code (0 if no error) 00857 ****************************************************************************/ 00858 Err store_trk(GarminObject * trk, UInt16 total, UInt16 current, 00859 LocalFormatID format, byte size) 00860 { 00861 UInt16 index; /* track record index */ 00862 MemHandle trkhDBEntry; /* track header record handle */ 00863 trk_header_t trkh; /* track header */ 00864 MemHandle trkpDBEntry; /* track point record handle */ 00865 trk_point_t trkp; /* track point */ 00866 UInt32 trackID; /* track ID (unique) */ 00867 Err err; /* error code */ 00868 static DmOpenRef db_ref; /* track point DB reference */ 00869 Char dbname[dmDBNameLength]; /* data base name */ 00870 Int16 i = 0; /* loop index */ 00871 00872 if ((format != G300Type) && (format != G310Type)) { 00873 /* failure (wrong protocol) */ 00874 return gpslibErrParamErr; 00875 } 00876 00877 if ((format == G310Type) || (current == 1)) { 00878 /* create and store track header */ 00879 00880 /* Limit number of Tracks */ 00881 if ( DmNumRecordsInCategory(gTrackHdrDB, dmAllCategories) == 0x100 ) { 00882 FrmAlert(TrackCreateAlert); 00883 return gpslibErrBusy; 00884 } 00885 00886 /* No particular order - add at the end of the database */ 00887 index = dmMaxRecordIndex; 00888 00889 trkhDBEntry = DmNewRecord(gTrackHdrDB, &index, sizeof(trk_header_t)); 00890 00891 if (!trkhDBEntry) { 00892 /* error occurred - fatal! */ 00893 Die("Cannot create track header record!"); 00894 return gpslibErrBusy; 00895 } 00896 00897 /* release new record */ 00898 DmReleaseRecord(gTrackHdrDB, index, false /* dirty */); 00899 00900 if (format == G310Type) { 00901 00902 if (current > 1) { 00903 /* not the first header, close previous track point DB */ 00904 DmCloseDatabase(db_ref); 00905 } 00906 00907 /* received track header */ 00908 trkh.dspl = trk->d310.dspl; 00909 trkh.color = trk->d310.color; 00910 StrNCopy(trkh.trk_ident, trk->d310.trk_ident, 49); 00911 } else { 00912 /* received track point without preceeding header */ 00913 /* create header */ 00914 trkh.dspl = true; 00915 trkh.color = Default_Color; 00916 TrackIdent(trkh.trk_ident); 00917 } 00918 00919 /* store track header to data base */ 00920 StoreTrkHdr(&trkh, index); 00921 00922 DmRecordInfo(gTrackHdrDB, index, NULL /* *attrP */, 00923 &trackID /* *uniqueIDP */, NULL /* *chunkIDP */); 00924 00925 /* create data base name */ 00926 TrackDBName(dbname, trackID); 00927 00928 /* create track point data base */ 00929 err = DmCreateDatabase(0 /* cardNo */, dbname, 00930 kCreatorId /* creator */, kTrkDBType /* type */, false /* resDB */); 00931 00932 if (current != total) { 00933 /* track points will follow */ 00934 db_ref = DmOpenDatabase(0 /* cardNo */, 00935 DmFindDatabase(0 /* cardNo */, dbname), dmModeReadWrite); 00936 } 00937 00938 if (current == total) { 00939 /* close track point data base */ 00940 DmCloseDatabase(db_ref); 00941 00942 /* update Track Table */ 00943 if (FrmGetActiveFormID() == TrackForm) { 00944 TablePtr tblP; /* table ptr */ 00945 UInt16 track_top = 0; /* track table top */ 00946 00947 /* set top table row to ensure selected item is visible */ 00948 tblP = (TablePtr)GetObjectFromActiveForm(TrackTable); 00949 00950 if (index > TblGetNumberOfRows(tblP)-1) 00951 track_top = index-TblGetNumberOfRows(tblP)+1; 00952 00953 trackDrawTable(track_top /* top */, &index); 00954 } 00955 } 00956 00957 /* success */ 00958 if (format == G310Type) 00959 return 0; 00960 } /* if ((format == G310Type) || (current == 1)) */ 00961 00962 if (format == G300Type) { 00963 /* receiving track point */ 00964 00965 /* copy track point */ 00966 for (i=sizeof(trkp.posn.lat)-1; i>=0; i--) { 00967 trkp.posn.lat <<= 8; 00968 trkp.posn.lat |= (G_byte)trk->d300.lat[i]; 00969 trkp.posn.lon <<= 8; 00970 trkp.posn.lon |= (G_byte)trk->d300.lon[i]; 00971 } 00972 trkp.time = 0; 00973 trkp.new_trk = trk->d300.new_trk; 00974 00975 /* add at the end of the database */ 00976 index = dmMaxRecordIndex; 00977 00978 /* create new track point record */ 00979 trkpDBEntry = DmNewRecord(db_ref, &index, sizeof(trk_point_t)); 00980 00981 if (!trkpDBEntry) { 00982 Die("Cannot create track point record!"); 00983 return gpslibErrBusy; 00984 } 00985 00986 /* release new record */ 00987 DmReleaseRecord(db_ref, index, false /* dirty */); 00988 00989 /* store track point to data base */ 00990 StoreTrkPoint(&trkp, index); 00991 00992 /* update Track Table */ 00993 if ((current == total) && (FrmGetActiveFormID() == TrackForm)) { 00994 TablePtr tblP; /* table ptr */ 00995 Int32 track_top = 0; /* track table top */ 00996 00997 /* set top table row to ensure selected item is visible */ 00998 tblP = (TablePtr)GetObjectFromActiveForm(TrackTable); 00999 01000 if (index > TblGetNumberOfRows(tblP)-1) 01001 track_top = index-TblGetNumberOfRows(tblP)+1; 01002 01003 trackDrawTable(track_top /* top */, &index); 01004 } 01005 01006 /* success */ 01007 return 0; 01008 } /* if (format == G300Type) */ 01009 01010 return gpslibErrParamErr; 01011 } 01012 01013 01014 /****************************************************************************/ 01015 /** 01016 * \brief Get number of data packets for route transfer using 01017 * Garmin protocol 01018 * 01019 * \return Number of data packets (Route Headers + Route Waypoints) 01020 * 01021 ****************************************************************************/ 01022 UInt16 NumRtePackets(void) 01023 { 01024 UInt16 num_routes; /* nr. of routes */ 01025 UInt16 num_packets; /* nr. of packets */ 01026 MemHandle routeDBEntry; /* record handle */ 01027 route_t *route; /* route */ 01028 UInt16 rec; /* record nr */ 01029 UInt16 i; /* loop index */ 01030 01031 /* get number of all routes in Route DB */ 01032 num_routes = DmNumRecordsInCategory(gRouteDB, dmAllCategories); 01033 01034 num_packets = num_routes; 01035 01036 rec = 0; 01037 01038 /* seek to first record in Route DB */ 01039 DmSeekRecordInCategory(gRouteDB, &rec /* index */, 0 /* offset */, 01040 dmSeekForward, dmAllCategories); 01041 01042 /* get number of waypoints of all routes */ 01043 for (i=0; i<num_routes; i++) { 01044 01045 /* query next route */ 01046 routeDBEntry = DmQueryNextInCategory(gRouteDB, &rec, 01047 dmAllCategories); 01048 01049 /* lock record */ 01050 route = (route_t *)MemHandleLock(routeDBEntry); 01051 01052 /* add number of route waypoints to packet count */ 01053 num_packets += route->items; 01054 01055 /* unlock record */ 01056 MemHandleUnlock(routeDBEntry); 01057 } 01058 01059 return num_packets; 01060 } 01061 01062 01063 /****************************************************************************/ 01064 /** 01065 * \brief Get number of data packets for track transfer using 01066 * Garmin protocol 01067 * 01068 * \return Number of data packets (Track Headers + Track Waypoints) 01069 * 01070 ****************************************************************************/ 01071 UInt16 NumTrkPackets(void) 01072 { 01073 UInt16 num_tracks; /* nr. of tracks */ 01074 UInt16 num_packets; /* nr. of packets */ 01075 DmOpenRef db_ref; /* data base reference */ 01076 MemHandle trkhDBEntry; /* record handle */ 01077 Char dbname[dmDBNameLength]; /* data base name */ 01078 UInt32 trackID; /* track ID */ 01079 UInt16 rec; /* record nr */ 01080 UInt16 i; /* loop index */ 01081 01082 /* get number of all tracks in Track Header DB */ 01083 num_tracks = DmNumRecordsInCategory(gTrackHdrDB, dmAllCategories); 01084 01085 /* 01086 * Note: 01087 * G310 Track Header currently not supported by emulated GARMIN device; 01088 * #packets = #track_points 01089 * 01090 * num_packets = num_tracks; 01091 */ 01092 01093 num_packets = 0; 01094 01095 rec = 0; 01096 01097 /* get number of track points of all tracks */ 01098 for (i=0; i<num_tracks; i++) { 01099 01100 /* query next route */ 01101 trkhDBEntry = DmQueryNextInCategory(gTrackHdrDB, &rec, 01102 dmAllCategories); 01103 01104 trkhDBEntry = DmQueryRecord(gTrackHdrDB, rec); 01105 01106 /* get unique Track ID */ 01107 DmRecordInfo(gTrackHdrDB, rec, NULL /* *attrP */, 01108 &trackID /* *uniqueIDP */, NULL /* *chunkIDP */); 01109 01110 /* create track data base name */ 01111 TrackDBName(dbname, trackID); 01112 01113 /* open track point data base */ 01114 db_ref = DmOpenDatabase(0 /* cardNo */, 01115 DmFindDatabase(0 /* cardNo */, dbname), dmModeReadOnly); 01116 01117 rec++; 01118 01119 if (db_ref) { 01120 /* open succeeded, get number of track points */ 01121 num_packets += DmNumRecordsInCategory(db_ref, dmAllCategories); 01122 01123 /* close DB */ 01124 DmCloseDatabase(db_ref); 01125 01126 } /* if (db_ref) */ 01127 01128 } /* for (i=0; i<num_tracks; i++) */ 01129 01130 return num_packets; 01131 } 01132 01133 01134 /****************************************************************************/ 01135 /** 01136 * \brief Terminate string with null characters ('\0'). 01137 * 01138 * GPSMan seems to pad strings with spaces, which prevents 01139 * proper packing of database records. 01140 * 01141 * \param str String pointer 01142 * 01143 * \param len String length 01144 * 01145 ****************************************************************************/ 01146 static void TermStr(char *str, UInt16 len) 01147 { 01148 UInt16 i; 01149 01150 for (i = len-1; i>=0; i--) { 01151 if (str[i] == ' ' || str[i] == '\0') { 01152 str[i] = '\0'; 01153 } else { 01154 break; 01155 } 01156 } 01157 }