Rev 218 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "garmin.h"
#define PUTU16(x) do { put_uint16(*pos,x); *pos += 2; } while ( 0 )
#define PUTS16(x) do { put_sint16(*pos,x); *pos += 2; } while ( 0 )
#define PUTU32(x) do { put_uint32(*pos,x); *pos += 4; } while ( 0 )
#define PUTS32(x) do { put_sint32(*pos,x); *pos += 4; } while ( 0 )
#define PUTF32(x) do { put_float32(*pos,x); *pos += 4; } while ( 0 )
#define PUTF64(x) do { put_float64(*pos,x); *pos += 8; } while ( 0 )
#define PUTPOS(x) do { PUTS32((x).lat); PUTS32((x).lon); } while ( 0 )
#define PUTRPT(x) do { PUTF64((x).lat); PUTF64((x).lon); } while ( 0 )
#define PUTVST(x) put_vstring(pos,x)
#define PUTU8(x) *(*pos)++ = x
#define SKIP(x) do { memset(*pos,0,x); *pos += x; } while ( 0 )
#define PUTSTR(x) \
do { \
memcpy(*pos,x,sizeof(x)-1); \
(*pos)[sizeof(x)-1] = 0; \
*pos += sizeof(x); \
} while ( 0 )
/* --------------------------------------------------------------------------*/
/* 7.4.1 D100 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d100 ( D100 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
}
/* --------------------------------------------------------------------------*/
/* 7.4.2 D101 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d101 ( D101 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTU8(wpt->smbl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.3 D102 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d102 ( D102 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTU16(wpt->smbl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.4 D103 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d103 ( D103 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTU8(wpt->smbl);
PUTU8(wpt->dspl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.5 D104 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d104 ( D104 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTU16(wpt->smbl);
PUTU8(wpt->dspl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.6 D105 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d105 ( D105 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTPOS(wpt->posn);
PUTU16(wpt->smbl);
PUTVST(wpt->wpt_ident);
}
/* --------------------------------------------------------------------------*/
/* 7.4.7 D106 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d106 ( D106 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTU8(wpt->wpt_class);
PUTSTR(wpt->subclass);
PUTPOS(wpt->posn);
PUTU16(wpt->smbl);
PUTVST(wpt->wpt_ident);
PUTVST(wpt->lnk_ident);
}
/* --------------------------------------------------------------------------*/
/* 7.4.8 D107 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d107 ( D107 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTU8(wpt->smbl);
PUTU8(wpt->dspl);
PUTF32(wpt->dst);
PUTU8(wpt->color);
}
/* --------------------------------------------------------------------------*/
/* 7.4.9 D108 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d108 ( D108 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTU8(wpt->wpt_class);
PUTU8(wpt->color);
PUTU8(wpt->dspl);
PUTU8(wpt->attr);
PUTU16(wpt->smbl);
PUTSTR(wpt->subclass);
PUTPOS(wpt->posn);
PUTF32(wpt->alt);
PUTF32(wpt->dpth);
PUTF32(wpt->dist);
PUTSTR(wpt->state);
PUTSTR(wpt->cc);
PUTVST(wpt->ident);
PUTVST(wpt->comment);
PUTVST(wpt->facility);
PUTVST(wpt->city);
PUTVST(wpt->addr);
PUTVST(wpt->cross_road);
}
/* --------------------------------------------------------------------------*/
/* 7.4.10 D109 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d109 ( D109 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTU8(wpt->dtyp);
PUTU8(wpt->wpt_class);
PUTU8(wpt->dspl_color);
PUTU8(wpt->attr);
PUTU16(wpt->smbl);
PUTSTR(wpt->subclass);
PUTPOS(wpt->posn);
PUTF32(wpt->alt);
PUTF32(wpt->dpth);
PUTF32(wpt->dist);
PUTSTR(wpt->state);
PUTSTR(wpt->cc);
PUTU32(wpt->ete);
PUTVST(wpt->ident);
PUTVST(wpt->comment);
PUTVST(wpt->facility);
PUTVST(wpt->city);
PUTVST(wpt->addr);
PUTVST(wpt->cross_road);
}
/* --------------------------------------------------------------------------*/
/* 7.4.11 D110 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d110 ( D110 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTU8(wpt->dtyp);
PUTU8(wpt->wpt_class);
PUTU8(wpt->dspl_color);
PUTU8(wpt->attr);
PUTU16(wpt->smbl);
PUTSTR(wpt->subclass);
PUTPOS(wpt->posn);
PUTF32(wpt->alt);
PUTF32(wpt->dpth);
PUTF32(wpt->dist);
PUTSTR(wpt->state);
PUTSTR(wpt->cc);
PUTU32(wpt->ete);
PUTF32(wpt->temp);
PUTU32(wpt->time);
PUTU16(wpt->wpt_cat);
PUTVST(wpt->ident);
PUTVST(wpt->comment);
PUTVST(wpt->facility);
PUTVST(wpt->city);
PUTVST(wpt->addr);
PUTVST(wpt->cross_road);
}
/* --------------------------------------------------------------------------*/
/* 7.4.12 D120 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d120 ( D120 * cat, uint8 ** pos )
{
if (!cat || !pos)
return;
PUTSTR(cat->name);
}
/* --------------------------------------------------------------------------*/
/* 7.4.13 D150 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d150 ( D150 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTSTR(wpt->cc);
PUTU8(wpt->wpt_class);
PUTPOS(wpt->posn);
PUTS16(wpt->alt);
PUTSTR(wpt->city);
PUTSTR(wpt->state);
PUTSTR(wpt->name);
PUTSTR(wpt->cmnt);
}
/* --------------------------------------------------------------------------*/
/* 7.4.14 D151 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d151 ( D151 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTSTR(wpt->name);
PUTSTR(wpt->city);
PUTSTR(wpt->state);
PUTS16(wpt->alt);
PUTSTR(wpt->cc);
SKIP(1);
PUTU8(wpt->wpt_class);
}
/* --------------------------------------------------------------------------*/
/* 7.4.15 D152 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d152 ( D152 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTSTR(wpt->name);
PUTSTR(wpt->city);
PUTSTR(wpt->state);
PUTS16(wpt->alt);
PUTSTR(wpt->cc);
SKIP(1);
PUTU8(wpt->wpt_class);
}
/* --------------------------------------------------------------------------*/
/* 7.4.16 D154 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d154 ( D154 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTSTR(wpt->name);
PUTSTR(wpt->city);
PUTSTR(wpt->state);
PUTS16(wpt->alt);
PUTSTR(wpt->cc);
SKIP(1);
PUTU8(wpt->wpt_class);
PUTU16(wpt->smbl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.17 D155 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d155 ( D155 * wpt, uint8 ** pos )
{
if (!wpt || !pos)
return;
PUTSTR(wpt->ident);
PUTPOS(wpt->posn);
SKIP(4);
PUTSTR(wpt->cmnt);
PUTF32(wpt->dst);
PUTSTR(wpt->name);
PUTSTR(wpt->city);
PUTSTR(wpt->state);
PUTS16(wpt->alt);
PUTSTR(wpt->cc);
SKIP(1);
PUTU8(wpt->wpt_class);
PUTU16(wpt->smbl);
PUTU8(wpt->dspl);
}
/* --------------------------------------------------------------------------*/
/* 7.4.18 D200 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d200 ( D200 * hdr, uint8 ** pos )
{
if (!hdr)
return;
PUTU8(*hdr);
}
/* --------------------------------------------------------------------------*/
/* 7.4.19 D201 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d201 ( D201 * hdr, uint8 ** pos )
{
if (!hdr || !pos)
return;
PUTU8(hdr->nmbr);
PUTSTR(hdr->cmnt);
}
/* --------------------------------------------------------------------------*/
/* 7.4.20 D202 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d202 ( D202 * hdr, uint8 ** pos )
{
if (!hdr || !pos)
return;
PUTVST(hdr->rte_ident);
}
/* --------------------------------------------------------------------------*/
/* 7.4.21 D210 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d210 ( D210 * link, uint8 ** pos )
{
if (!link || !pos)
return;
PUTU16(link->class);
PUTSTR(link->subclass);
PUTVST(link->ident);
}
/* --------------------------------------------------------------------------*/
/* 7.4.22 D300 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d300 ( D300 * point, uint8 ** pos )
{
if (!point || !pos)
return;
PUTPOS(point->posn);
PUTU32(point->time);
PUTU8(point->new_trk);
}
/* --------------------------------------------------------------------------*/
/* 7.4.23 D301 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d301 ( D301 * point, uint8 ** pos )
{
if (!point || !pos)
return;
PUTPOS(point->posn);
PUTU32(point->time);
PUTF32(point->alt);
PUTF32(point->dpth);
PUTU8(point->new_trk);
}
/* --------------------------------------------------------------------------*/
/* 7.4.24 D302 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d302 ( D302 * point, uint8 ** pos )
{
if (!point || !pos)
return;
PUTPOS(point->posn);
PUTU32(point->time);
PUTF32(point->alt);
PUTF32(point->dpth);
PUTF32(point->temp);
PUTU8(point->new_trk);
}
/* --------------------------------------------------------------------------*/
/* 7.4.25 D303 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d303 ( D303 * point, uint8 ** pos )
{
if (!point || !pos)
return;
PUTPOS(point->posn);
PUTU32(point->time);
PUTF32(point->alt);
PUTU8(point->heart_rate);
}
/* --------------------------------------------------------------------------*/
/* 7.4.26 D304 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d304 ( D304 * point, uint8 ** pos )
{
if (!point || !pos)
return;
PUTPOS(point->posn);
PUTU32(point->time);
PUTF32(point->alt);
PUTF32(point->distance);
PUTU8(point->heart_rate);
PUTU8(point->cadence);
PUTU8(point->sensor);
}
/* --------------------------------------------------------------------------*/
/* 7.4.27 D310 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d310 ( D310 * hdr, uint8 ** pos )
{
if (!hdr || !pos)
return;
PUTU8(hdr->dspl);
PUTU8(hdr->color);
PUTVST(hdr->trk_ident);
}
/* --------------------------------------------------------------------------*/
/* 7.4.28 D311 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d311 ( D311 * hdr, uint8 ** pos )
{
if (!hdr)
return;
PUTU16(hdr->index);
}
/* --------------------------------------------------------------------------*/
/* 7.4.29 D312 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d312 ( D312 * hdr, uint8 ** pos )
{
if (!hdr)
return;
PUTU8(hdr->dspl);
PUTU8(hdr->color);
PUTVST(hdr->trk_ident);
}
/* ------------------------------------------------------------------------- */
/* 7.4.30 D400 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d400 ( D400 * prx, uint8 ** pos )
{
if (!prx)
return;
garmin_pack_d100(&prx->wpt,pos);
SKIP(sizeof(D100));
PUTF32(prx->dst);
}
/* ------------------------------------------------------------------------- */
/* 7.4.31 D403 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d403 ( D403 * prx, uint8 ** pos )
{
if (!prx)
return;
garmin_pack_d103(&prx->wpt,pos);
SKIP(sizeof(D103));
PUTF32(prx->dst);
}
/* ------------------------------------------------------------------------- */
/* 7.4.32 D450 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d450 ( D450 * prx, uint8 ** pos )
{
if (!prx)
return;
PUTU32(prx->idx);
garmin_pack_d150(&prx->wpt,pos);
SKIP(sizeof(D150));
PUTF32(prx->dst);
}
/* ------------------------------------------------------------------------- */
/* 7.4.33 D500 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d500 ( D500 * alm, uint8 ** pos )
{
if (!alm)
return;
PUTU16(alm->wn);
PUTF32(alm->toa);
PUTF32(alm->af0);
PUTF32(alm->af1);
PUTF32(alm->e);
PUTF32(alm->sqrta);
PUTF32(alm->m0);
PUTF32(alm->w);
PUTF32(alm->omg0);
PUTF32(alm->odot);
PUTF32(alm->i);
}
/* ------------------------------------------------------------------------- */
/* 7.4.34 D501 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d501 ( D501 * alm, uint8 ** pos )
{
if (!alm)
return;
PUTU16(alm->wn);
PUTF32(alm->toa);
PUTF32(alm->af0);
PUTF32(alm->af1);
PUTF32(alm->e);
PUTF32(alm->sqrta);
PUTF32(alm->m0);
PUTF32(alm->w);
PUTF32(alm->omg0);
PUTF32(alm->odot);
PUTF32(alm->i);
PUTU8(alm->hlth);
}
/* ------------------------------------------------------------------------- */
/* 7.4.35 D550 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d550 ( D550 * alm, uint8 ** pos )
{
if (!alm)
return;
PUTU8(alm->svid);
PUTU16(alm->wn);
PUTF32(alm->toa);
PUTF32(alm->af0);
PUTF32(alm->af1);
PUTF32(alm->e);
PUTF32(alm->sqrta);
PUTF32(alm->m0);
PUTF32(alm->w);
PUTF32(alm->omg0);
PUTF32(alm->odot);
PUTF32(alm->i);
}
/* ------------------------------------------------------------------------- */
/* 7.4.36 D551 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d551 ( D551 * alm, uint8 ** pos )
{
if (!alm)
return;
PUTU8(alm->svid);
PUTU16(alm->wn);
PUTF32(alm->toa);
PUTF32(alm->af0);
PUTF32(alm->af1);
PUTF32(alm->e);
PUTF32(alm->sqrta);
PUTF32(alm->m0);
PUTF32(alm->w);
PUTF32(alm->omg0);
PUTF32(alm->odot);
PUTF32(alm->i);
PUTU8(alm->hlth);
}
/* ------------------------------------------------------------------------- */
/* 7.4.37 D600 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d600 ( D600 * dt, uint8 ** pos )
{
if (!dt)
return;
PUTU8(dt->month);
PUTU8(dt->day);
PUTU16(dt->year);
PUTU16(dt->hour);
PUTU8(dt->minute);
PUTU8(dt->second);
}
/* ------------------------------------------------------------------------- */
/* 7.4.38 D650 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d650 ( D650 * fbr, uint8 ** pos )
{
if (!fbr)
return;
PUTU32(fbr->takeoff_time);
PUTU32(fbr->landing_time);
PUTPOS(fbr->takeoff_posn);
PUTPOS(fbr->landing_posn);
PUTU32(fbr->night_time);
PUTU32(fbr->num_landings);
PUTF32(fbr->max_speed);
PUTF32(fbr->max_alt);
PUTF32(fbr->distance);
PUTU8(fbr->cross_country_flag);
PUTVST(fbr->departure_name);
PUTVST(fbr->departure_ident);
PUTVST(fbr->arrival_name);
PUTVST(fbr->arrival_ident);
PUTVST(fbr->ac_id);
}
/* ------------------------------------------------------------------------- */
/* 7.4.39 D700 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d700 ( D700 * pt, uint8 ** pos )
{
PUTRPT(*pt);
}
/* ------------------------------------------------------------------------- */
/* 7.4.40 D800 */
/* ------------------------------------------------------------------------- */
static void
garmin_pack_d800 ( D800 * pvt, uint8 ** pos )
{
if (!pvt)
return;
PUTF32(pvt->alt);
PUTF32(pvt->epe);
PUTF32(pvt->eph);
PUTF32(pvt->epv);
PUTU16(pvt->fix);
PUTF64(pvt->tow);
PUTRPT(pvt->posn);
PUTF32(pvt->east);
PUTF32(pvt->north);
PUTF32(pvt->up);
PUTF32(pvt->msl_hght);
PUTS16(pvt->leap_scnds);
PUTU32(pvt->wn_days);
}
/* --------------------------------------------------------------------------*/
/* 7.4.41 D906 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d906 ( D906 * lap, uint8 ** pos )
{
if (!lap)
return;
PUTU32(lap->start_time);
PUTU32(lap->total_time);
PUTF32(lap->total_distance);
PUTPOS(lap->begin);
PUTPOS(lap->end);
PUTU16(lap->calories);
PUTU8(lap->track_index);
}
/* --------------------------------------------------------------------------*/
/* 7.4.42 D1000 */
/* --------------------------------------------------------------------------*/
static void garmin_pack_d1002 ( D1002 * wkt, uint8 ** pos );
static void
garmin_pack_d1000 ( D1000 * run, uint8 ** pos )
{
if (!run)
return;
PUTU32(run->track_index);
PUTU32(run->first_lap_index);
PUTU32(run->last_lap_index);
PUTU8(run->sport_type);
PUTU8(run->program_type);
SKIP(2);
PUTU32(run->virtual_partner.time);
PUTF32(run->virtual_partner.distance);
garmin_pack_d1002(&run->workout,pos);
}
/* --------------------------------------------------------------------------*/
/* 7.4.43 D1001 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1001 ( D1001 * lap, uint8 ** pos )
{
if (!lap)
return;
PUTU32(lap->index);
PUTU32(lap->start_time);
PUTU32(lap->total_time);
PUTF32(lap->total_dist);
PUTF32(lap->max_speed);
PUTPOS(lap->begin);
PUTPOS(lap->end);
PUTU16(lap->calories);
PUTU8(lap->avg_heart_rate);
PUTU8(lap->max_heart_rate);
PUTU8(lap->intensity);
}
/* --------------------------------------------------------------------------*/
/* 7.4.44 D1002 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1002 ( D1002 * wkt, uint8 ** pos )
{
int i;
if (!wkt)
return;
PUTU32(wkt->num_valid_steps);
for ( i = 0; i < 20; i++ ) {
PUTSTR(wkt->steps[i].custom_name);
PUTF32(wkt->steps[i].target_custom_zone_low);
PUTF32(wkt->steps[i].target_custom_zone_high);
PUTU16(wkt->steps[i].duration_value);
PUTU8(wkt->steps[i].intensity);
PUTU8(wkt->steps[i].duration_type);
PUTU8(wkt->steps[i].target_type);
PUTU8(wkt->steps[i].target_value);
SKIP(2);
}
PUTSTR(wkt->name);
PUTU8(wkt->sport_type);
}
/* --------------------------------------------------------------------------*/
/* 7.4.45 D1003 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1003 ( D1003 * occ, uint8 ** pos )
{
if (!occ)
return;
PUTSTR(occ->workout_name);
PUTU32(occ->day);
}
/* --------------------------------------------------------------------------*/
/* 7.4.46 D1004 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1004 ( D1004 * prof, uint8 ** pos )
{
int i;
int j;
if (!prof)
return;
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 5; j++ ) {
PUTU8(prof->activities[i].heart_rate_zones[j].low_heart_rate);
PUTU8(prof->activities[i].heart_rate_zones[j].high_heart_rate);
SKIP(2);
}
for ( j = 0; j < 10; j++ ) {
PUTF32(prof->activities[i].speed_zones[j].low_speed);
PUTF32(prof->activities[i].speed_zones[j].high_speed);
PUTSTR(prof->activities[i].speed_zones[j].name);
}
PUTF32(prof->activities[i].gear_weight);
PUTU8(prof->activities[i].max_heart_rate);
SKIP(3);
}
PUTF32(prof->weight);
PUTU16(prof->birth_year);
PUTU8(prof->birth_month);
PUTU8(prof->birth_day);
PUTU8(prof->gender);
}
/* --------------------------------------------------------------------------*/
/* 7.4.47 D1005 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1005 ( D1005 * limits, uint8 ** pos )
{
if (!limits)
return;
PUTU32(limits->max_workouts);
PUTU32(limits->max_unscheduled_workouts);
PUTU32(limits->max_occurrences);
}
/* --------------------------------------------------------------------------*/
/* 7.4.48 D1006 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1006 ( D1006 * course, uint8 ** pos )
{
if (!course)
return;
PUTU16(course->index);
SKIP(2);
PUTSTR(course->course_name);
PUTU16(course->track_index);
}
/* --------------------------------------------------------------------------*/
/* 7.4.49 D1007 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1007 ( D1007 * lap, uint8 ** pos )
{
if (!lap)
return;
PUTU16(lap->course_index);
PUTU16(lap->lap_index);
PUTU32(lap->total_time);
PUTF32(lap->total_dist);
PUTPOS(lap->begin);
PUTPOS(lap->end);
PUTU8(lap->avg_heart_rate);
PUTU8(lap->max_heart_rate);
PUTU8(lap->intensity);
PUTU8(lap->avg_cadence);
}
/* --------------------------------------------------------------------------*/
/* 7.4.50 D1008 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1008 ( D1008 * wkt, uint8 ** pos )
{
if (!wkt)
return;
garmin_pack_d1002((D1002 *)wkt,pos);
}
/* --------------------------------------------------------------------------*/
/* 7.4.51 D1009 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1009 ( D1009 * run, uint8 ** pos )
{
if (!run)
return;
PUTU16(run->track_index);
PUTU16(run->first_lap_index);
PUTU16(run->last_lap_index);
PUTU8(run->sport_type);
PUTU8(run->program_type);
PUTU8(run->multisport);
SKIP(3);
PUTU32(run->quick_workout.time);
PUTF32(run->quick_workout.distance);
garmin_pack_d1008(&run->workout,pos);
}
/* --------------------------------------------------------------------------*/
/* 7.4.52 D1010 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1010 ( D1010 * run, uint8 ** pos )
{
if (!run)
return;
PUTU32(run->track_index);
PUTU32(run->first_lap_index);
PUTU32(run->last_lap_index);
PUTU8(run->sport_type);
PUTU8(run->program_type);
PUTU8(run->multisport);
SKIP(1);
PUTU32(run->virtual_partner.time);
PUTF32(run->virtual_partner.distance);
garmin_pack_d1002(&run->workout,pos);
}
/* --------------------------------------------------------------------------*/
/* 7.4.53 D1011 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1011 ( D1011 * lap, uint8 ** pos )
{
if (!lap)
return;
PUTU16(lap->index);
SKIP(2);
PUTU32(lap->start_time);
PUTU32(lap->total_time);
PUTF32(lap->total_dist);
PUTF32(lap->max_speed);
PUTPOS(lap->begin);
PUTPOS(lap->end);
PUTU16(lap->calories);
PUTU8(lap->avg_heart_rate);
PUTU8(lap->max_heart_rate);
PUTU8(lap->intensity);
PUTU8(lap->avg_cadence);
PUTU8(lap->trigger_method);
}
/* --------------------------------------------------------------------------*/
/* 7.4.54 D1012 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1012 ( D1012 * point, uint8 ** pos )
{
if (!point)
return;
PUTSTR(point->name);
SKIP(1);
PUTU16(point->course_index);
SKIP(2);
PUTU32(point->track_point_time);
PUTU8(point->point_type);
}
/* --------------------------------------------------------------------------*/
/* 7.4.55 D1013 */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1013 ( D1013 * limits, uint8 ** pos )
{
if (!limits)
return;
PUTU32(limits->max_courses);
PUTU32(limits->max_course_laps);
PUTU32(limits->max_course_pnt);
PUTU32(limits->max_course_trk_pnt);
}
/* --------------------------------------------------------------------------*/
/* 7.4.XX D1015 (Undocumented) */
/* --------------------------------------------------------------------------*/
static void
garmin_pack_d1015 ( D1015 * lap, uint8 ** pos )
{
if (!lap)
return;
PUTU16(lap->index);
SKIP(2);
PUTU32(lap->start_time);
PUTU32(lap->total_time);
PUTF32(lap->total_dist);
PUTF32(lap->max_speed);
PUTPOS(lap->begin);
PUTPOS(lap->end);
PUTU16(lap->calories);
PUTU8(lap->avg_heart_rate);
PUTU8(lap->max_heart_rate);
PUTU8(lap->intensity);
PUTU8(lap->avg_cadence);
PUTU8(lap->trigger_method);
/* Hopefully we'll know what this stuff actually is someday. */
PUTU8(lap->unknown[0]);
PUTU8(lap->unknown[1]);
PUTU8(lap->unknown[2]);
PUTU8(lap->unknown[3]);
PUTU8(lap->unknown[4]);
}
/* List */
static void
garmin_pack_dlist ( garmin_list * list, uint8 ** pos )
{
garmin_list_node * node;
if (!list)
return;
PUTU32(list->id);
PUTU32(list->elements);
for ( node = list->head; node != NULL; node = node->next ) {
PUTU32(list->id);
garmin_pack(node->data,pos);
}
}
/* make a directory path (may require creation of multiple directories) */
static int
mkpath ( const char *path )
{
struct stat sb;
char rpath[BUFSIZ];
int n = 0;
int j = 0;
int ok = 1;
uid_t owner = -1;
gid_t group = -1;
int already = 0;
mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
/* check for obvious errors */
if ( !path || *path != '/' ) return 0;
/*
if the path already exists, return 1 if it is a directory and 0
otherwise
*/
if ( stat(path,&sb) != -1 ) {
return (S_ISDIR(sb.st_mode)) ? 1 : 0;
}
/*
loop through the path, stopping at each slash to try and make the
directory.
*/
while ( path[n] ) {
rpath[j++] = path[n++];
if ( path[n] == '/' ) {
rpath[j] = 0;
if ( stat(rpath,&sb) != -1 ) { /* this part already exists */
if ( !S_ISDIR(sb.st_mode) ) { /* but is not a directory! */
char hv0[1024];
sprintf(&hv0[0], "mkpath: %s exists but is not a directory",rpath);
garmin_queue_error(hv0, err_error);
ok = 0;
break;
} else {
/* figure out who owns the directory, what permissions they have */
owner = sb.st_uid;
group = sb.st_gid;
mode = sb.st_mode;
already = 1;
}
} else {
if ( mkdir(rpath,mode) != -1 ) { /* have to make this part */
if ( already ) {
chown(rpath,owner,group);
}
} else {
char hv0[1024];
sprintf(hv0, "mkpath: mkdir(%s,%o): %s",path,mode,strerror(errno));
garmin_queue_error(hv0, err_error);
ok = 0;
break;
}
}
}
}
/* make the final path */
if ( mkdir(path,mode) != -1 ) {
if ( already ) {
chown(rpath,owner,group);
}
} else {
char hv0[1024];
sprintf(hv0, "mkpath: mkdir(%s,%o): %s",path,mode,strerror(errno));
garmin_queue_error(hv0, err_error);
ok = 0;
}
return ok;
}
/* ========================================================================= */
/* garmin_save */
/* ========================================================================= */
uint32
garmin_save ( garmin_data * data, const char * filename, const char * dir )
{
return garmin_save_all (data, filename, dir, 0);
}
uint32
garmin_save_all ( garmin_data * data, const char * filename, const char * dir, int flag )
{
int fd;
uint8 * buf;
uint8 * pos;
uint8 * marker;
uint32 bytes = 0;
uint32 packed = 0;
uint32 wrote = 0;
struct stat sb;
uid_t owner = -1;
gid_t group = -1;
char path[BUFSIZ];
if ( (bytes = garmin_data_size(data)) != 0 ) {
mkpath(dir);
if ( stat(dir,&sb) != -1 ) {
owner = sb.st_uid;
group = sb.st_gid;
}
snprintf(path,sizeof(path)-1,"%s/%s",dir,filename);
if ( stat(path,&sb) != -1 && !flag) {
/* Do NOT overwrite if the file is already there. */
return 0;
}
if ( (fd = creat(path,0664)) != -1 ) {
fchown(fd,owner,group);
/* Allocate the memory and write the file header */
if ( (buf = malloc(bytes + GARMIN_HEADER)) != NULL ) {
/* write GARMIN_MAGIC, GARMIN_VERSION, and bytes. */
pos = buf;
memset(pos,0,GARMIN_HEADER);
strncpy((char *)pos,GARMIN_MAGIC,11);
put_uint32(pos+12,GARMIN_VERSION);
marker = pos+16;
pos += GARMIN_HEADER;
packed = GARMIN_HEADER;
/* pack the rest of the data. */
packed += garmin_pack(data,&pos);
put_uint32(marker,packed-GARMIN_HEADER);
/* Now write the data to the file and close the file. */
if ( (wrote = write(fd,buf,packed)) != packed ) {
/* write error! */
char hv0[256];
sprintf(hv0, "write of %d bytes returned %d: %s",
packed,wrote,strerror(errno));
garmin_queue_error(hv0, err_error);
}
close(fd);
/* Free the buffer. */
free(buf);
} else {
/* malloc error */
char hv0[256];
sprintf(hv0, "malloc(%d): %s",bytes + GARMIN_HEADER, strerror(errno));
garmin_queue_error(hv0, err_error);
}
} else {
/* problem creating file. */
char hv0[1024];
sprintf(hv0, "creat: %s: %s",path,strerror(errno));
garmin_queue_error(hv0, err_error);
}
} else {
/* don't write empty data */
char hv0[1024];
printf("%s: garmin_data_size was 0",path);
garmin_queue_error(hv0, err_error);
}
return bytes;
}
/* ========================================================================= */
/* garmin_pack */
/* */
/* Take an arbitrary garmin_data and pack it into a buffer. The buffer is */
/* allocated with malloc, and the number of bytes allocated is returned. */
/* The buffer returned is suitable for transferring to a Garmin device or */
/* for writing to disk. */
/* ========================================================================= */
uint32
garmin_pack ( garmin_data * data, uint8 ** buf )
{
uint8 * start;
uint8 * finish;
uint8 * marker;
uint32 bytes = 0;
char hv0[256];
if ( !data || garmin_data_size(data) == 0 ) return 0;
/* OK, we must know how to serialize this data. Let's go for it. */
#define CASE_DATA(x) \
case data_D##x: \
{ \
put_uint32(*buf,data->type); \
*buf += 4; \
marker = *buf; \
*buf += 4; \
start = *buf; \
garmin_pack_d##x(data->data,buf); \
finish = *buf; \
bytes = finish-start; \
put_uint32(marker,bytes); \
bytes += 8; \
} \
break
switch ( data->type ) {
CASE_DATA(list);
CASE_DATA(100);
CASE_DATA(101);
CASE_DATA(102);
CASE_DATA(103);
CASE_DATA(104);
CASE_DATA(105);
CASE_DATA(106);
CASE_DATA(107);
CASE_DATA(108);
CASE_DATA(109);
CASE_DATA(110);
CASE_DATA(120);
CASE_DATA(150);
CASE_DATA(151);
CASE_DATA(152);
CASE_DATA(154);
CASE_DATA(155);
CASE_DATA(200);
CASE_DATA(201);
CASE_DATA(202);
CASE_DATA(210);
CASE_DATA(300);
CASE_DATA(301);
CASE_DATA(302);
CASE_DATA(303);
CASE_DATA(304);
CASE_DATA(310);
CASE_DATA(311);
CASE_DATA(312);
CASE_DATA(400);
CASE_DATA(403);
CASE_DATA(450);
CASE_DATA(500);
CASE_DATA(501);
CASE_DATA(550);
CASE_DATA(551);
CASE_DATA(600);
CASE_DATA(650);
CASE_DATA(700);
CASE_DATA(800);
CASE_DATA(906);
CASE_DATA(1000);
CASE_DATA(1001);
CASE_DATA(1002);
CASE_DATA(1003);
CASE_DATA(1004);
CASE_DATA(1005);
CASE_DATA(1006);
CASE_DATA(1007);
CASE_DATA(1008);
CASE_DATA(1009);
CASE_DATA(1010);
CASE_DATA(1011);
CASE_DATA(1012);
CASE_DATA(1013);
CASE_DATA(1015);
default:
sprintf(hv0, "garmin_pack: data type %d not supported",data->type);
garmin_queue_error(hv0, err_warning);
break;
}
#undef CASE_DATA
return bytes;
}