Subversion Repositories public

Rev

Rev 136 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
93 andreas 1
#include "config.h"
2
#include <string.h>
3
#include <stdlib.h>
4
#include "garmin.h"
5
 
6
 
7
/* ------------------------------------------------------------------------- */
8
/* Assign an application protocol to the Garmin unit.                        */
9
/* ------------------------------------------------------------------------- */
10
 
11
static void
12
garmin_assign_protocol ( garmin_unit *  garmin, 
13
			 uint16         protocol,
14
			 uint16 *       datatypes )
15
{
16
  /* Unknown protocols and their data types are ignored. */
17
 
18
  switch ( protocol ) {
19
  case appl_A010:
20
  case appl_A011:
21
    garmin->protocol.command             = protocol;
22
    break;
23
 
24
  case appl_A100:
25
    garmin->protocol.waypoint.waypoint   = protocol;  
26
    garmin->datatype.waypoint.waypoint   = datatypes[0];
27
    break;
28
 
29
  case appl_A101:
30
    garmin->protocol.waypoint.category   = protocol;
31
    garmin->datatype.waypoint.category   = datatypes[0];
32
    break;
33
 
34
  case appl_A200:
35
    garmin->protocol.route               = protocol;
36
    garmin->datatype.route.header        = datatypes[0];
37
    garmin->datatype.route.waypoint      = datatypes[1];
38
 
39
  case appl_A201:
40
    garmin->protocol.route               = protocol;
41
    garmin->datatype.route.header        = datatypes[0];
42
    garmin->datatype.route.waypoint      = datatypes[1];
43
    garmin->datatype.route.link          = datatypes[2];
44
    break;
45
 
46
  case appl_A300:
47
    garmin->protocol.track               = protocol;
48
    garmin->datatype.track.data          = datatypes[0];
49
    break;
50
 
51
  case appl_A301:
52
  case appl_A302:
53
    garmin->protocol.track               = protocol;
54
    garmin->datatype.track.header        = datatypes[0];
55
    garmin->datatype.track.data          = datatypes[1];
56
    break;
57
 
58
  case appl_A400:
59
    garmin->protocol.waypoint.proximity  = protocol;
60
    garmin->datatype.waypoint.proximity  = datatypes[0];
61
    break;
62
 
63
  case appl_A500:
64
    garmin->protocol.almanac             = protocol;
65
    garmin->datatype.almanac             = datatypes[0];
66
    break;
67
 
68
  case appl_A600:
69
    garmin->protocol.date_time           = protocol;
70
    garmin->datatype.date_time           = datatypes[0];
71
    break;
72
 
73
  case appl_A601:
74
    /* --- UNDOCUMENTED --- */
75
    break;
76
 
77
  case appl_A650:
78
    garmin->protocol.flightbook          = protocol;
79
    garmin->datatype.flightbook          = datatypes[0];
80
    break;
81
 
82
  case appl_A700:
83
    garmin->protocol.position            = protocol;
84
    garmin->datatype.position            = datatypes[0];
85
    break;
86
 
87
  case appl_A800:
88
    garmin->protocol.pvt                 = protocol;
89
    garmin->datatype.pvt                 = datatypes[0];
90
    break;
91
 
92
  case appl_A801:
93
    /* --- UNDOCUMENTED --- */
94
    break;
95
 
96
  case appl_A902:
97
    /* --- UNDOCUMENTED --- */
98
    break;
99
 
100
  case appl_A903:
101
    /* --- UNDOCUMENTED --- */
102
    break;
103
 
104
  case appl_A906:
105
    garmin->protocol.lap                 = protocol;
106
    garmin->datatype.lap                 = datatypes[0];
107
    break;
108
 
109
  case appl_A907:
110
    /* --- UNDOCUMENTED --- */
111
    break;
112
 
113
  case appl_A1000:
114
    garmin->protocol.run                 = protocol;
115
    garmin->datatype.run                 = datatypes[0];
116
    break;
117
 
118
  case appl_A1002:
119
    garmin->protocol.workout.workout     = protocol;
120
    garmin->datatype.workout.workout     = datatypes[0];
121
    break;
122
 
123
  case appl_A1003:
124
    garmin->protocol.workout.occurrence  = protocol;
125
    garmin->datatype.workout.occurrence  = datatypes[0];
126
    break;
127
 
128
  case appl_A1004:
129
    garmin->protocol.fitness             = protocol;
130
    garmin->datatype.fitness             = datatypes[0];
131
    break;
132
 
133
  case appl_A1005:
134
    garmin->protocol.workout.limits      = protocol;
135
    garmin->datatype.workout.limits      = datatypes[0];
136
    break;
137
 
138
  case appl_A1006:
139
    garmin->protocol.course.course       = protocol;
140
    garmin->datatype.course.course       = datatypes[0];
141
    break;
142
 
143
  case appl_A1007:
144
    garmin->protocol.course.lap          = protocol;
145
    garmin->datatype.course.lap          = datatypes[0];
146
    break;
147
 
148
  case appl_A1008:
149
    garmin->protocol.course.point        = protocol;
150
    garmin->datatype.course.point        = datatypes[0];
151
 
152
  case appl_A1009:
153
    garmin->protocol.course.limits       = protocol;
154
    garmin->datatype.course.limits       = datatypes[0];
155
    break;
156
 
157
  case appl_A1012:
158
    garmin->protocol.course.track        = protocol;
159
    garmin->datatype.course.track.header = datatypes[0];
160
    garmin->datatype.course.track.data   = datatypes[1];
161
    break;
162
 
163
  default:
164
    break;
165
  }
166
}
167
 
168
 
169
static char **
170
merge_strings ( char ** one, char ** two )
171
{
172
  int     i;
173
  int     n1;
174
  int     n2;
175
  char ** pos;
176
  char ** ret = NULL;
177
 
178
  for ( pos = one, n1 = 0; pos && *pos; pos++, n1++ );
179
  for ( pos = two, n2 = 0; pos && *pos; pos++, n2++ );
180
 
181
  if ( n1 + n2 > 0 ) {
182
    ret = calloc(n1+n2+1,sizeof(char *));
183
    for ( i = 0; i < n1; i++ ) ret[i]    = one[i];
184
    for ( i = 0; i < n2; i++ ) ret[n1+i] = two[i];
185
    if ( one != NULL ) free(one);
186
    if ( two != NULL ) free(two);
187
  }
188
 
189
  return ret;
190
}
191
 
192
 
193
/* Read a single packet with an expected packet ID and data type. */
194
 
195
static garmin_data *
196
garmin_read_singleton ( garmin_unit *     garmin,
197
			garmin_pid        pid,
198
			garmin_datatype   type )
199
{
200
  garmin_data *     d = NULL;
201
  garmin_packet     p;
202
  link_protocol     link = garmin->protocol.link;
203
  garmin_pid        ppid;
136 andreas 204
  char              hv0[256];
93 andreas 205
 
206
  if ( garmin_read(garmin,&p) > 0 ) {
207
    ppid = garmin_gpid(link,garmin_packet_id(&p));
208
    if ( ppid == pid ) {
209
      d = garmin_unpack_packet(&p,type);
210
    } else {
211
      /* Expected pid but got something else. */
136 andreas 212
      sprintf(hv0, "garmin_read_singleton: expected %d, got %d!",pid,ppid);
213
      garmin_queue_error(hv0, err_warning);
93 andreas 214
    }
215
  } else {
216
    /* Failed to read the packet off the link. */
136 andreas 217
    sprintf(hv0, "garmin_read_singleton: failed to read Pid_Records packet!");
218
    garmin_queue_error(hv0, err_warning);
93 andreas 219
  }
220
 
221
  return d;
222
}
223
 
224
 
225
/* Read a Pid_Records, (pid)+, Pid_Xfer_Cmplt sequence. */
226
 
227
static garmin_data *
228
garmin_read_records ( garmin_unit *     garmin,
229
		      garmin_pid        pid,
230
		      garmin_datatype   type )
231
{
232
  garmin_data *     d         = NULL;
233
  garmin_list *     l         = NULL;
234
  garmin_packet     p;
235
  link_protocol     link      = garmin->protocol.link;
236
  int               done      = 0;
237
  int               expected  = 0;
238
  int               got       = 0;
239
  garmin_pid        ppid;
136 andreas 240
  char              hv0[256];
93 andreas 241
 
242
  if ( garmin_read(garmin,&p) > 0 ) {
243
    ppid = garmin_gpid(link,garmin_packet_id(&p));
244
    if ( ppid == Pid_Records ) {
245
      expected = get_uint16(p.packet.data);
246
 
247
      if ( garmin->verbose != 0 ) {
136 andreas 248
	sprintf(hv0, "[garmin] Pid_Records indicates %d packets to follow!",
93 andreas 249
	       expected);
136 andreas 250
        garmin_queue_error(hv0, err_info);
93 andreas 251
      }
252
 
253
      /* Allocate a list for the records. */
254
 
255
      d = garmin_alloc_data(data_Dlist);
256
      l = (garmin_list *)d->data;
257
 
258
      /* 
259
	 Now we expect packets with the given packet_id and datatype, up
260
	 until the final packet, which is a Pid_Xfer_Cmplt.
261
      */
262
 
263
      while ( !done && garmin_read(garmin,&p) > 0 ) {
264
	ppid = garmin_gpid(link,garmin_packet_id(&p));
265
	if ( ppid == Pid_Xfer_Cmplt ) {
266
	  if ( got != expected ) {
267
	    /* Incorrect number of packets received. */
136 andreas 268
	    sprintf(hv0, "garmin_read_records: expected %d packets, got %d!",
93 andreas 269
		   expected,got);
136 andreas 270
	    garmin_queue_error(hv0, err_error);
93 andreas 271
	  } else if ( garmin->verbose != 0 ) {
136 andreas 272
	    sprintf(hv0, "[garmin] all %d expected packets received!",got);
273
	    garmin_queue_error(hv0, err_info);
93 andreas 274
	  }
275
	  done = 1;
276
	} else if ( ppid == pid ) {
277
	  garmin_list_append(l,garmin_unpack_packet(&p,type));
278
	  got++;
279
	} else {
280
	  /* Unexpected packet ID! */
281
	  done = 1;
282
	}
283
      }
284
    } else {
285
      /* Expected Pid_Records but got something else. */
136 andreas 286
      sprintf(hv0, "garmin_read_records: expected Pid_Records, got %d!",ppid);
287
      garmin_queue_error(hv0, err_error);
93 andreas 288
    }
289
  } else {
290
    /* Failed to read the Pid_Records packet off the link. */
136 andreas 291
    sprintf(hv0, "garmin_read_records: failed to read Pid_Records packet!");
292
    garmin_queue_error(hv0, err_error);
93 andreas 293
  }
294
 
142 andreas 295
  garmin_callback("read_records");
93 andreas 296
  return d;
297
}
298
 
299
 
300
/* Read a Pid_Records, (pid1, (pid2)+)+, Pid_Xfer_Cmplt sequence. */
301
 
302
static garmin_data *
303
garmin_read_records2 ( garmin_unit *     garmin,
304
		       garmin_pid        pid1,
305
		       garmin_datatype   type1,
306
		       garmin_pid        pid2,
307
		       garmin_datatype   type2 )
308
{
309
  garmin_data *     d         = NULL;
310
  garmin_list *     l         = NULL;
311
  garmin_packet     p;
312
  link_protocol     link      = garmin->protocol.link;
313
  int               expected  = 0;
314
  int               got       = 0;
315
  int               state     = 0;
316
  garmin_pid        ppid;
136 andreas 317
  char              hv0[256];
93 andreas 318
 
319
  if ( garmin_read(garmin,&p) > 0 ) {
320
    ppid = garmin_gpid(link,garmin_packet_id(&p));
321
    if ( ppid == Pid_Records ) {
322
      expected = get_uint16(p.packet.data);
323
 
324
      if ( garmin->verbose != 0 ) {
136 andreas 325
	sprintf(hv0, "[garmin] Pid_Records indicates %d packets to follow!",
93 andreas 326
	       expected);
136 andreas 327
	garmin_queue_error(hv0, err_info);
93 andreas 328
      }
101 andreas 329
 
93 andreas 330
      /* Allocate a list for the records. */
331
 
332
      d = garmin_alloc_data(data_Dlist);
333
      l = (garmin_list *)d->data;
334
 
335
      while ( state >= 0 && garmin_read(garmin,&p) > 0 ) {
336
	ppid = garmin_gpid(link,garmin_packet_id(&p));
337
	if ( ppid == Pid_Xfer_Cmplt ) {
338
	  /* transfer complete! */
339
	  if ( got != expected ) {
340
	    /* wrong number of packets received! */
136 andreas 341
	    sprintf(hv0, "garmin_read_records2: expected %d packets, got %d!",
93 andreas 342
		   expected,got);
136 andreas 343
	    garmin_queue_error(hv0, err_error);
93 andreas 344
	  } else if ( garmin->verbose != 0 ) {
136 andreas 345
	    sprintf(hv0, "[garmin] all %d expected packets received!",got);
346
	    garmin_queue_error(hv0, err_info);
93 andreas 347
	  }
348
	  break;
349
	}
350
	switch ( state ) {
351
	case 0:  /* want pid1 */
352
	  if ( ppid == pid1 ) {
353
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
354
	    state = 1;
355
	    got++;
356
	  } else {
357
	    state = -1;
358
	  }
359
	  break;
360
	case 1:  /* want pid2 */
361
	  if ( ppid == pid2 ) {
362
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
363
	    state = 2;
364
	    got++;
365
	  } else {
366
	    state = -1;
367
	  }
368
	  break;
369
	case 2: /* want pid2 or pid1 */
370
	  if ( ppid == pid1 ) {
371
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
372
	    state = 1;
373
	    got++;
374
	  } else if ( ppid == pid2 ) {
375
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
376
	    state = 2;
377
	    got++;
378
	  } else {
379
	    state = -1;
380
	  }
381
	  break;
382
	default:
383
	  state = -1;
384
	  break;
385
	}
386
      }
387
      if ( state < 0 ) {
388
	/* Unexpected packet received. */
136 andreas 389
	sprintf(hv0, "garmin_read_records2: unexpected packet %d received!",ppid);
390
        garmin_queue_error(hv0, err_error);
93 andreas 391
      }
392
    } else {
393
      /* Expected Pid_Records but got something else. */
136 andreas 394
      sprintf(hv0, "garmin_read_records2: expected Pid_Records, got %d!",ppid);
395
      garmin_queue_error(hv0, err_error);
93 andreas 396
    }
397
  } else {
398
    /* Failed to read the Pid_Records packet off the link. */
136 andreas 399
    sprintf(hv0, "garmin_read_records2: failed to read Pid_Records packet!");
400
    garmin_queue_error(hv0, err_error);
93 andreas 401
  }
402
 
142 andreas 403
  garmin_callback("read_records2");
93 andreas 404
  return d;
405
}
406
 
407
 
408
/* Read a Pid_Records, (pid1, (pid2, pid3)+)+, Pid_Xfer_Cmplt sequence. */
409
 
410
static garmin_data *
411
garmin_read_records3 ( garmin_unit *     garmin,
412
		       garmin_pid        pid1,
413
		       garmin_datatype   type1,
414
		       garmin_pid        pid2,
415
		       garmin_datatype   type2,
416
		       garmin_pid        pid3,
417
		       garmin_datatype   type3 )
418
{
419
  garmin_data *     d         = NULL;
420
  garmin_list *     l         = NULL;
421
  garmin_packet     p;
422
  link_protocol     link      = garmin->protocol.link;
423
  int               expected  = 0;
424
  int               got       = 0;
425
  garmin_pid        ppid;
426
  int               state     = 0;
136 andreas 427
  char              hv0[256];
93 andreas 428
 
429
  if ( garmin_read(garmin,&p) > 0 ) {
430
    ppid = garmin_gpid(link,garmin_packet_id(&p));
431
    if ( ppid == Pid_Records ) {
432
      expected = get_uint16(p.packet.data);
433
 
434
      if ( garmin->verbose != 0 ) {
136 andreas 435
	sprintf(hv0, "[garmin] Pid_Records indicates %d packets to follow!",
93 andreas 436
	       expected);
136 andreas 437
	garmin_queue_error(hv0, err_info);
93 andreas 438
      }
439
 
440
      /* Allocate a list for the records. */
441
 
442
      d = garmin_alloc_data(data_Dlist);
443
      l = (garmin_list *)d->data;
444
 
445
      while ( state >= 0 && garmin_read(garmin,&p) > 0 ) {
446
	ppid = garmin_gpid(link,garmin_packet_id(&p));
447
	if ( ppid == Pid_Xfer_Cmplt ) {
448
	  /* transfer complete! */
449
	  if ( got != expected ) {
450
	    /* wrong number of packets received! */
136 andreas 451
	    sprintf(hv0, "garmin_read_records3: expected %d packets, got %d!",
93 andreas 452
		   expected,got);
136 andreas 453
	    garmin_queue_error(hv0, err_error);
93 andreas 454
	  } else if ( garmin->verbose != 0 ) {
136 andreas 455
	    sprintf(hv0, "[garmin] all %d expected packets received!",got);
456
	    garmin_queue_error(hv0, err_info);
93 andreas 457
	  }
458
	  break;
459
	}
460
	switch ( state ) {
461
	case 0:  /* want pid1 */
462
	  if ( ppid == pid1 ) {
463
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
464
	    state = 1;
465
	    got++;
466
	  } else {
467
	    state = -1;
468
	  }
469
	  break;
470
	case 1:  /* want pid2 */
471
	  if ( ppid == pid2 ) {
472
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
473
	    state = 2;
474
	    got++;
475
	  } else {
476
	    state = -1;
477
	  }
478
	  break;
479
	case 2: /* want pid3 */
480
	  if ( ppid == pid3 ) {
481
	    garmin_list_append(l,garmin_unpack_packet(&p,type3));
482
	    state = 3;
483
	    got++;
484
	  } else {
485
	    state = -1;
486
	  }
487
	  break;
488
	case 3: /* want pid2 or pid1 */
489
	  if ( ppid == pid1 ) {
490
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
491
	    state = 1;
492
	    got++;
493
	  } else if ( ppid == pid2 ) {
494
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
495
	    state = 2;
496
	    got++;
497
	  } else {
498
	    state = -1;
499
	  }
500
	  break;
501
	default:
502
	  state = -1;
503
	  break;
504
	}
505
      }
506
      if ( state < 0 ) {
507
	/* Unexpected packet received. */
136 andreas 508
	sprintf(hv0, "garmin_read_records3: unexpected packet %d received!",ppid);
509
        garmin_queue_error(hv0, err_error);
93 andreas 510
      }
511
    } else {
512
      /* Expected Pid_Records but got something else. */
136 andreas 513
      sprintf(hv0, "garmin_read_records3: expected Pid_Records, got %d!",ppid);
514
      garmin_queue_error(hv0, err_error);
93 andreas 515
    }
516
  } else {
517
    /* Failed to read the Pid_Records packet off the link. */
136 andreas 518
    sprintf(hv0, "garmin_read_records3: failed to read Pid_Records packet!");
519
    garmin_queue_error(hv0, err_error);
93 andreas 520
  }
521
 
142 andreas 522
  garmin_callback("read_records3");
93 andreas 523
  return d;
524
}
525
 
526
 
527
/* ------------------------------------------------------------------------- */
528
/* 6.1  A000 - Product Data Protocol                                         */
529
/* 6.2  A001 - Protocol Capability Protocol                                  */
530
/* ------------------------------------------------------------------------- */
531
 
532
void
533
garmin_read_a000_a001 ( garmin_unit * garmin )
534
{
535
  garmin_packet          p;
536
  garmin_product *       r;
537
  garmin_extended_data * e;
538
  int                    done = 0;
539
  int                    pos;
540
  int                    size;
541
  int                    i;
542
  int                    j;
543
  uint8                  tag;
544
  uint16                 data;
545
  uint16 *               datatypes;
546
 
547
  /* Send the product request */
548
  garmin_packetize(&p,L000_Pid_Product_Rqst,0,NULL);
549
  garmin_write(garmin,&p);
550
 
551
  /* Read the response. */
552
 
553
  while ( !done && garmin_read(garmin,&p) > 0 ) {
554
    switch ( garmin_packet_id(&p) ) {
555
    case L000_Pid_Product_Data:
556
      r = &garmin->product;
557
      /* product ID, software version, product description, additional data. */
558
      r->product_id = get_uint16(p.packet.data);
559
      r->software_version = get_sint16(p.packet.data+2);
560
      pos = 4;
561
      if ( r->product_description != NULL ) {
562
	free(r->product_description);
563
      }
564
      r->product_description = get_string(&p,&pos);      
565
      r->additional_data = merge_strings(r->additional_data,
566
					 get_strings(&p,&pos));
567
      break;
142 andreas 568
 
93 andreas 569
    case L000_Pid_Ext_Product_Data:
570
      e = &garmin->extended;
571
      /* These strings should be ignored, but we save them anyway. */
572
      pos = 0;
573
      e->ext_data = merge_strings(e->ext_data,get_strings(&p,&pos));
574
      break;
575
 
576
    case L000_Pid_Protocol_Array:
577
      /* This is the A001 protocol, initiated by the device. */
578
      size = garmin_packet_size(&p) / 3;
579
      datatypes = calloc(size,sizeof(uint16));
580
      for ( i = 0; i < size; i++ ) {
581
	tag  = p.packet.data[3*i];
582
	data = get_uint16(p.packet.data + 3*i + 1);	
583
	switch ( tag ) {
584
	case Tag_Phys_Prot_Id:  
585
	  garmin->protocol.physical = data;
586
	  break;
587
	case Tag_Link_Prot_Id:
588
	  garmin->protocol.link = data;
589
	  break;
590
	case Tag_Appl_Prot_Id:
591
	  memset(datatypes,0,size * sizeof(uint16));
592
	  for ( j = i+1; p.packet.data[3*j] == Tag_Data_Type_Id; j++ ) {
593
	    datatypes[j-i-1] = get_uint16(p.packet.data + 3*j + 1);
594
	  }
595
	  garmin_assign_protocol(garmin,data,datatypes);
596
	  break;
597
	case Tag_Data_Type_Id:
598
	  /* Skip, since we should already have handled them. */
599
	default:
600
	  break;
601
	}
602
      }
603
      free(datatypes);
604
      done = 1;
605
      break;
606
 
607
    default:
608
      /* Ignore any other packets sent from the device. */
609
      break;
610
    }
611
  }
136 andreas 612
 
613
  garmin_callback("product_request");
93 andreas 614
}
615
 
616
 
617
/* ------------------------------------------------------------------------- */
618
/* 6.4  A100 - Waypoint Transfer Protocol                                    */
619
/* ------------------------------------------------------------------------- */
620
 
621
garmin_data *
622
garmin_read_a100 ( garmin_unit * garmin )
623
{
624
  garmin_data * d = NULL;
625
 
626
  if ( garmin_send_command(garmin,Cmnd_Transfer_Wpt) != 0 ) {
627
    d = garmin_read_records(garmin,
628
			    Pid_Wpt_Data,
629
			    garmin->datatype.waypoint.waypoint);
630
  }
631
 
632
  return d;
633
}
634
 
635
 
636
/* ------------------------------------------------------------------------- */
637
/* 6.5  A101 - Waypoint Category Transfer Protocol                           */
638
/* ------------------------------------------------------------------------- */
639
 
640
garmin_data *
641
garmin_read_a101 ( garmin_unit * garmin )
642
{
643
  garmin_data * d = NULL;
644
 
645
  if ( garmin_send_command(garmin,Cmnd_Transfer_Wpt_Cats) != 0 ) {
646
    d = garmin_read_records(garmin,
647
			    Pid_Wpt_Cat,
648
			    garmin->datatype.waypoint.category);
649
  }
650
 
651
  return d;
652
}
653
 
654
 
655
/* ------------------------------------------------------------------------- */
656
/* 6.6.2  A200 - Route Transfer Protocol                                     */
657
/* ------------------------------------------------------------------------- */
658
 
659
garmin_data *
660
garmin_read_a200 ( garmin_unit * garmin )
661
{
662
  garmin_data * d = NULL;
663
 
664
  if ( garmin_send_command(garmin,Cmnd_Transfer_Rte) != 0 ) {
665
    d = garmin_read_records2(garmin,
666
			     Pid_Rte_Hdr,
667
			     garmin->datatype.route.header,
668
			     Pid_Rte_Wpt_Data,
669
			     garmin->datatype.waypoint.waypoint);
670
  }
671
 
672
  return d;
673
}
674
 
675
 
676
/* ------------------------------------------------------------------------- */
677
/* 6.6.3  A201 - Route Transfer Protocol                                     */
678
/* ------------------------------------------------------------------------- */
679
 
680
garmin_data *
681
garmin_read_a201 ( garmin_unit * garmin )
682
{
683
  garmin_data * d = NULL;
684
 
685
  if ( garmin_send_command(garmin,Cmnd_Transfer_Rte) != 0 ) {
686
    d = garmin_read_records3(garmin,
687
			     Pid_Rte_Hdr,
688
			     garmin->datatype.route.header,
689
			     Pid_Rte_Wpt_Data,
690
			     garmin->datatype.route.waypoint,
691
			     Pid_Rte_Link_Data,
692
			     garmin->datatype.route.link);
693
  }
694
 
695
  return d;
696
}
697
 
698
 
699
/* ------------------------------------------------------------------------- */
700
/* 6.7.2  A300 - Track Log Transfer Protocol                                 */
701
/* ------------------------------------------------------------------------- */
702
 
703
garmin_data *
704
garmin_read_a300 ( garmin_unit * garmin )
705
{
706
  garmin_data * d = NULL;
707
 
708
  if ( garmin_send_command(garmin,Cmnd_Transfer_Trk) != 0 ) {
709
    d = garmin_read_records(garmin,
710
			    Pid_Trk_Data,
711
			    garmin->datatype.track.data);
712
  }
713
 
714
  return d;
715
}
716
 
717
 
718
/* ------------------------------------------------------------------------- */
719
/* 6.7.3  A301 - Track Log Transfer Protocol                                 */
720
/* ------------------------------------------------------------------------- */
721
 
722
garmin_data *
723
garmin_read_a301 ( garmin_unit * garmin )
724
{
725
  garmin_data * d = NULL;
726
 
727
  if ( garmin_send_command(garmin,Cmnd_Transfer_Trk) != 0 ) {
728
    d = garmin_read_records2(garmin,
729
			     Pid_Trk_Hdr,
730
			     garmin->datatype.track.header,
731
			     Pid_Trk_Data,
732
			     garmin->datatype.track.data);
733
  }
734
 
735
  return d;
736
}
737
 
738
 
739
/* ------------------------------------------------------------------------- */
740
/* 6.7.4  A302 - Track Log Transfer Protocol                                 */
741
/* ------------------------------------------------------------------------- */
742
 
743
garmin_data *
744
garmin_read_a302 ( garmin_unit * garmin )
745
{
746
  return garmin_read_a301(garmin);
747
}
748
 
749
 
750
/* ------------------------------------------------------------------------- */
751
/* 6.8  A400 - Proximity Waypoint Transfer Protocol                          */
752
/* ------------------------------------------------------------------------- */
753
 
754
garmin_data *
755
garmin_read_a400 ( garmin_unit * garmin )
756
{
757
  garmin_data * d = NULL;
758
 
759
  if ( garmin_send_command(garmin,Cmnd_Transfer_Prx) != 0 ) {
760
    d = garmin_read_records(garmin,
761
			    Pid_Prx_Wpt_Data,
762
			    garmin->datatype.waypoint.proximity);
763
  }
764
 
765
  return d;
766
}
767
 
768
 
769
/* ------------------------------------------------------------------------- */
770
/* 6.9  A500 - Almanac Transfer Protocol                                     */
771
/* ------------------------------------------------------------------------- */
772
 
773
garmin_data *
774
garmin_read_a500 ( garmin_unit * garmin )
775
{
776
  garmin_data * d = NULL;
777
 
778
  if ( garmin_send_command(garmin,Cmnd_Transfer_Alm) != 0 ) {
779
    d = garmin_read_records(garmin,
780
			    Pid_Almanac_Data,
781
			    garmin->datatype.almanac);
782
  }
783
 
784
  return d;
785
}
786
 
787
 
788
/* ------------------------------------------------------------------------- */
789
/* 6.10  A600 - Date and Time Initialization Protocol                        */
790
/* ------------------------------------------------------------------------- */
791
 
792
garmin_data *
793
garmin_read_a600 ( garmin_unit * garmin )
794
{
795
  garmin_data * d = NULL;
796
 
797
  d = garmin_read_singleton(garmin,
798
			    Pid_Date_Time_Data,
799
			    garmin->datatype.date_time);
800
 
801
  return d;
802
}
803
 
804
 
805
/* ------------------------------------------------------------------------- */
806
/* 6.11  A650 - FlightBook Transfer Protocol                                 */
807
/* ------------------------------------------------------------------------- */
808
 
809
garmin_data *
810
garmin_read_a650 ( garmin_unit * garmin )
811
{
812
  garmin_data * d = NULL;
813
 
814
  if ( garmin_send_command(garmin,Cmnd_FlightBook_Transfer) ) {
815
    d = garmin_read_records(garmin,
816
			    Pid_FlightBook_Record,
817
			    garmin->datatype.flightbook);
818
  }
819
 
820
  return d;
821
}
822
 
823
 
824
/* ------------------------------------------------------------------------- */
825
/* 6.12  A700 - Position Initialization Protocol                             */
826
/* ------------------------------------------------------------------------- */
827
 
828
garmin_data *
829
garmin_read_a700 ( garmin_unit * garmin )
830
{
831
  garmin_data * d;
832
 
833
  d = garmin_read_singleton(garmin,
834
			    Pid_Position_Data,
835
			    garmin->datatype.position);
836
 
837
  return d;
838
}
839
 
840
 
841
/* ------------------------------------------------------------------------- */
842
/* 6.13  A800 - PVT Protocol                                                 */
843
/* ------------------------------------------------------------------------- */
844
 
845
garmin_data *
846
garmin_read_a800 ( garmin_unit * garmin )
847
{
848
  garmin_data * d;
849
 
850
  d = garmin_read_singleton(garmin,
851
			    Pid_Pvt_Data,
852
			    garmin->datatype.pvt);
853
 
854
  return d;
855
}
856
 
857
 
858
/* ------------------------------------------------------------------------- */
859
/* 6.14  A906 - Lap Transfer Protocol                                        */
860
/* ------------------------------------------------------------------------- */
861
 
862
garmin_data *
863
garmin_read_a906 ( garmin_unit * garmin )
864
{
865
  garmin_data * d = NULL;
866
 
867
  if ( garmin_send_command(garmin,Cmnd_Transfer_Laps) != 0 ) {
868
    d = garmin_read_records(garmin,Pid_Lap,garmin->datatype.lap);
869
  }
870
 
871
  return d;
872
}
873
 
874
 
875
/* ------------------------------------------------------------------------- */
876
/* 6.15  A1000 - Run Transfer Protocol                                       */
877
/* ------------------------------------------------------------------------- */
878
 
879
garmin_data *
880
garmin_read_a1000 ( garmin_unit * garmin )
881
{
882
  garmin_data * d  = NULL;
883
  garmin_list * l  = NULL;
884
 
885
  /* Read the runs, then the laps, then the track log. */
886
 
887
  if ( garmin_send_command(garmin,Cmnd_Transfer_Runs) != 0 ) {
888
    d = garmin_alloc_data(data_Dlist);
889
    l = d->data;
890
    garmin_list_append(l,garmin_read_records(garmin,Pid_Run,
891
					     garmin->datatype.run));
892
    garmin_list_append(l,garmin_read_a906(garmin));
893
    garmin_list_append(l,garmin_read_a302(garmin));
894
  }
895
 
896
  return d;
897
}
898
 
899
 
900
/* ------------------------------------------------------------------------- */
901
/* 6.16  A1002 - Workout Transfer Protocol                                   */
902
/* ------------------------------------------------------------------------- */
903
 
904
garmin_data *
905
garmin_read_a1002 ( garmin_unit * garmin )
906
{
907
  garmin_data * d  = NULL;
908
  garmin_list * l  = NULL;
909
 
910
  /* Read the workouts, then the workout occurrences */
911
 
912
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workouts) != 0 ) {
913
    d = garmin_alloc_data(data_Dlist);
914
    l = d->data;
915
    garmin_list_append(l,
916
		       garmin_read_records(garmin,
917
					   Pid_Workout,
918
					   garmin->datatype.workout.workout));
919
    garmin_list_append(l,garmin_read_a1003(garmin));
920
  }
921
 
922
  return d;
923
}
924
 
925
 
926
/* ------------------------------------------------------------------------- */
927
/* --- UNDOCUMENTED ---  A1003 - Workout Occurrence Transfer Protocol        */
928
/* ------------------------------------------------------------------------- */
929
 
930
garmin_data *
931
garmin_read_a1003 ( garmin_unit * garmin )
932
{
933
  garmin_data * d = NULL;
934
 
935
  /* Read the workouts, then the workout occurrences */
936
 
937
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workout_Occurrences) != 0 ) {
938
    d = garmin_read_records(garmin,
939
			    Pid_Workout_Occurrence,
940
			    garmin->datatype.workout.occurrence);
941
  }
942
 
943
  return d;
944
}
945
 
946
 
947
/* ------------------------------------------------------------------------- */
948
/* 6.17  A1004 - Fitness User Profile Transfer Protocol                      */
949
/* ------------------------------------------------------------------------- */
950
 
951
garmin_data *
952
garmin_read_a1004 ( garmin_unit * garmin )
953
{
954
  garmin_data * d = NULL;
955
 
956
  if ( garmin_send_command(garmin,Cmnd_Transfer_Fitness_User_Profile) != 0 ) {
957
    d = garmin_read_singleton(garmin,
958
			      Pid_Fitness_User_Profile,
959
			      garmin->datatype.fitness);
960
  }
961
 
962
  return d;
963
}
964
 
965
 
966
/* ------------------------------------------------------------------------- */
967
/* 6.18  A1005 - Workout Limits Transfer Protocol                            */
968
/* ------------------------------------------------------------------------- */
969
 
970
garmin_data *
971
garmin_read_a1005 ( garmin_unit * garmin )
972
{
973
  garmin_data * d = NULL;
974
 
975
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workout_Limits) != 0 ) {
976
    d = garmin_read_singleton(garmin,
977
			      Pid_Workout_Limits,
978
			      garmin->datatype.workout.limits);
979
  }
980
 
981
  return d;
982
}
983
 
984
 
985
/* ------------------------------------------------------------------------- */
986
/* 6.19  A1006 - Course Transfer Protocol                                    */
987
/* ------------------------------------------------------------------------- */
988
 
989
garmin_data *
990
garmin_read_a1006 ( garmin_unit * garmin )
991
{
992
  garmin_data * d  = NULL;
993
  garmin_list * l  = NULL;
994
 
995
  if ( garmin_send_command(garmin,Cmnd_Transfer_Courses) != 0 ) {
996
    d = garmin_alloc_data(data_Dlist);
997
    l = d->data;
998
    garmin_list_append(l,garmin_read_records(garmin,
999
					     Pid_Course,
1000
					     garmin->datatype.course.course));
1001
    garmin_list_append(l,garmin_read_a1007(garmin));
1002
    garmin_list_append(l,garmin_read_a1012(garmin));
1003
    garmin_list_append(l,garmin_read_a1008(garmin));
1004
  }
1005
 
1006
  return d;
1007
}
1008
 
1009
 
1010
/* ------------------------------------------------------------------------- */
1011
/* --- UNDOCUMENTED ---  A1007 - Course Lap Transfer Protocol                */
1012
/* ------------------------------------------------------------------------- */
1013
 
1014
garmin_data *
1015
garmin_read_a1007 ( garmin_unit * garmin )
1016
{
1017
  garmin_data * d = NULL;
1018
 
1019
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Laps) != 0 ) {
1020
    d = garmin_read_records(garmin,
1021
			    Pid_Course_Lap,
1022
			    (garmin->datatype.course.lap != data_Dnil) ?
1023
			    garmin->datatype.course.lap :
1024
			    garmin->datatype.lap);
1025
  }
1026
 
1027
  return d;
1028
}
1029
 
1030
 
1031
/* ------------------------------------------------------------------------- */
1032
/* --- UNDOCUMENTED ---  A1008 - Course Point Transfer Protocol              */
1033
/* ------------------------------------------------------------------------- */
1034
 
1035
garmin_data *
1036
garmin_read_a1008 ( garmin_unit * garmin )
1037
{
1038
  garmin_data * d = NULL;
1039
 
1040
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Points) != 0 ) {
1041
    d = garmin_read_records(garmin,
1042
			    Pid_Course_Point,
1043
			    garmin->datatype.course.point);
1044
  }
1045
 
1046
  return d;
1047
}
1048
 
1049
 
1050
/* ------------------------------------------------------------------------- */
1051
/* 6.20  A1009 - Course Limits Transfer Protocol                             */
1052
/* ------------------------------------------------------------------------- */
1053
 
1054
garmin_data *
1055
garmin_read_a1009 ( garmin_unit * garmin )
1056
{
1057
  garmin_data * d = NULL;
1058
 
1059
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Limits) != 0 ) {
1060
    d = garmin_read_singleton(garmin,
1061
			      Pid_Course_Limits,
1062
			      garmin->datatype.course.limits);
1063
  }
1064
 
1065
  return d;
1066
}
1067
 
1068
 
1069
/* ------------------------------------------------------------------------- */
1070
/* --- UNDOCUMENTED ---  A1012 - Course Track Transfer Protocol              */
1071
/* ------------------------------------------------------------------------- */
1072
 
1073
garmin_data *
1074
garmin_read_a1012 ( garmin_unit * garmin )
1075
{
1076
  garmin_datatype  header;
1077
  garmin_datatype  data;
1078
  garmin_data *    d = NULL;
1079
 
1080
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Tracks) != 0 ) {
1081
 
1082
    if ( garmin->datatype.course.track.header != data_Dnil ) {
1083
      header = garmin->datatype.course.track.header;
1084
    } else {
1085
      header = garmin->datatype.track.header;
1086
    }
1087
 
1088
    if ( garmin->datatype.course.track.data != data_Dnil ) {
1089
      data = garmin->datatype.course.track.data;
1090
    } else {
1091
      data = garmin->datatype.track.data;
1092
    }
1093
 
1094
    d = garmin_read_records2(garmin,
1095
			     Pid_Course_Trk_Hdr,
1096
			     header,
1097
			     Pid_Course_Trk_Data,
1098
			     data);
1099
  }
1100
 
1101
  return d;
1102
}
1103
 
1104
 
1105
/* ------------------------------------------------------------------------- */
1106
/* Get data from the Garmin unit via a particular top-level protocol         */
1107
/* ------------------------------------------------------------------------- */
1108
 
1109
garmin_data *
1110
garmin_read_via ( garmin_unit * garmin, appl_protocol protocol )
1111
{
1112
  garmin_data * data = NULL;
1113
 
1114
#define CASE_PROTOCOL(x)                                                      \
1115
  case appl_A##x:                                                             \
1116
    if ( garmin->verbose != 0 ) {                                             \
136 andreas 1117
      fprintf(stderr, "[garmin] -> garmin_read_a" #x "\n");                            \
93 andreas 1118
    }                                                                         \
1119
    data = garmin_read_a##x(garmin);                                          \
1120
    if ( garmin->verbose != 0 ) {                                             \
136 andreas 1121
      fprintf(stderr, "[garmin] <- garmin_read_a" #x "\n");                            \
93 andreas 1122
    }                                                                         \
1123
    break
1124
 
1125
  switch ( protocol ) {
1126
  CASE_PROTOCOL(100);   /* waypoints */
1127
  CASE_PROTOCOL(101);   /* waypoint categories */
1128
  CASE_PROTOCOL(200);   /* routes */
1129
  CASE_PROTOCOL(201);   /* routes */
1130
  CASE_PROTOCOL(300);   /* track log */
1131
  CASE_PROTOCOL(301);   /* track log */
1132
  CASE_PROTOCOL(302);   /* track log */
1133
  CASE_PROTOCOL(400);   /* proximity waypoints */
1134
  CASE_PROTOCOL(500);   /* almanac */
1135
  CASE_PROTOCOL(650);   /* flightbook */
1136
  CASE_PROTOCOL(1000);  /* runs */
1137
  CASE_PROTOCOL(1002);  /* workouts */
1138
  CASE_PROTOCOL(1004);  /* fitness user profile */
1139
  CASE_PROTOCOL(1005);  /* workout limits */
1140
  CASE_PROTOCOL(1006);  /* courses */
1141
  CASE_PROTOCOL(1009);  /* course limits */
1142
  default:
1143
    /* invalid top-level read protocol */
1144
    break;
1145
  }
1146
 
142 andreas 1147
  garmin_callback("read_via");
93 andreas 1148
  return data;
1149
}
1150
 
1151
 
1152
/* ------------------------------------------------------------------------- */
1153
/* Get data from the Garmin unit                                             */
1154
/* ------------------------------------------------------------------------- */
1155
 
1156
garmin_data *
1157
garmin_get ( garmin_unit * garmin, garmin_get_type what )
1158
{
1159
  garmin_data * data = NULL;
1160
 
1161
#define CASE_WHAT(x,y) \
1162
  case GET_##x: data = garmin_read_via(garmin,garmin->protocol.y); break
1163
 
1164
  switch ( what ) {
1165
  CASE_WHAT(WAYPOINTS,waypoint.waypoint);
1166
  CASE_WHAT(WAYPOINT_CATEGORIES,waypoint.category);
1167
  CASE_WHAT(ROUTES,route);
1168
  CASE_WHAT(TRACKLOG,track);
1169
  CASE_WHAT(PROXIMITY_WAYPOINTS,waypoint.proximity);
1170
  CASE_WHAT(ALMANAC,almanac);
1171
  CASE_WHAT(FLIGHTBOOK,flightbook);
1172
  CASE_WHAT(RUNS,run);
1173
  CASE_WHAT(WORKOUTS,workout.workout);
1174
  CASE_WHAT(FITNESS_USER_PROFILE,fitness);
1175
  CASE_WHAT(WORKOUT_LIMITS,workout.limits);
1176
  CASE_WHAT(COURSES,course.course);
1177
  CASE_WHAT(COURSE_LIMITS,course.limits);
1178
  default:
1179
    /* invalid garmin_get_type */
1180
    break;
1181
  }
1182
 
1183
  return data;
1184
}
1185
 
1186
 
1187
/* Initialize a connection with a Garmin unit. */
1188
 
101 andreas 1189
int garmin_init(garmin_unit *garmin, int verbose)
93 andreas 1190
{
101 andreas 1191
	memset(garmin, 0, sizeof(garmin_unit));
1192
	garmin->verbose = verbose;
1193
	garmin->usb.fd = -1;
93 andreas 1194
 
101 andreas 1195
	if ( garmin_open(garmin) != 0 )
1196
	{
1197
	   garmin_start_session(garmin);
1198
	   garmin_read_a000_a001(garmin);
1199
	   return 1;
1200
	}
1201
	else
1202
	{
1203
	   return 0;
1204
	}
93 andreas 1205
}
1206