GPS4Palm

Source Code Documentation


DataExchange.c

Go to the documentation of this file.
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 }

Created: Mon, 08 Oct 2007 22:33:16 +0200
Copyright ©2004 M. Prinke