Subversion Repositories public

Rev

Rev 101 | Rev 142 | 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
 
295
  return d;
296
}
297
 
298
 
299
/* Read a Pid_Records, (pid1, (pid2)+)+, Pid_Xfer_Cmplt sequence. */
300
 
301
static garmin_data *
302
garmin_read_records2 ( garmin_unit *     garmin,
303
		       garmin_pid        pid1,
304
		       garmin_datatype   type1,
305
		       garmin_pid        pid2,
306
		       garmin_datatype   type2 )
307
{
308
  garmin_data *     d         = NULL;
309
  garmin_list *     l         = NULL;
310
  garmin_packet     p;
311
  link_protocol     link      = garmin->protocol.link;
312
  int               expected  = 0;
313
  int               got       = 0;
314
  int               state     = 0;
315
  garmin_pid        ppid;
136 andreas 316
  char              hv0[256];
93 andreas 317
 
318
  if ( garmin_read(garmin,&p) > 0 ) {
319
    ppid = garmin_gpid(link,garmin_packet_id(&p));
320
    if ( ppid == Pid_Records ) {
321
      expected = get_uint16(p.packet.data);
322
 
323
      if ( garmin->verbose != 0 ) {
136 andreas 324
	sprintf(hv0, "[garmin] Pid_Records indicates %d packets to follow!",
93 andreas 325
	       expected);
136 andreas 326
	garmin_queue_error(hv0, err_info);
93 andreas 327
      }
101 andreas 328
 
93 andreas 329
      /* Allocate a list for the records. */
330
 
331
      d = garmin_alloc_data(data_Dlist);
332
      l = (garmin_list *)d->data;
333
 
334
      while ( state >= 0 && garmin_read(garmin,&p) > 0 ) {
335
	ppid = garmin_gpid(link,garmin_packet_id(&p));
336
	if ( ppid == Pid_Xfer_Cmplt ) {
337
	  /* transfer complete! */
338
	  if ( got != expected ) {
339
	    /* wrong number of packets received! */
136 andreas 340
	    sprintf(hv0, "garmin_read_records2: expected %d packets, got %d!",
93 andreas 341
		   expected,got);
136 andreas 342
	    garmin_queue_error(hv0, err_error);
93 andreas 343
	  } else if ( garmin->verbose != 0 ) {
136 andreas 344
	    sprintf(hv0, "[garmin] all %d expected packets received!",got);
345
	    garmin_queue_error(hv0, err_info);
93 andreas 346
	  }
347
	  break;
348
	}
349
	switch ( state ) {
350
	case 0:  /* want pid1 */
351
	  if ( ppid == pid1 ) {
352
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
353
	    state = 1;
354
	    got++;
355
	  } else {
356
	    state = -1;
357
	  }
358
	  break;
359
	case 1:  /* want pid2 */
360
	  if ( ppid == pid2 ) {
361
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
362
	    state = 2;
363
	    got++;
364
	  } else {
365
	    state = -1;
366
	  }
367
	  break;
368
	case 2: /* want pid2 or pid1 */
369
	  if ( ppid == pid1 ) {
370
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
371
	    state = 1;
372
	    got++;
373
	  } else if ( ppid == pid2 ) {
374
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
375
	    state = 2;
376
	    got++;
377
	  } else {
378
	    state = -1;
379
	  }
380
	  break;
381
	default:
382
	  state = -1;
383
	  break;
384
	}
385
      }
386
      if ( state < 0 ) {
387
	/* Unexpected packet received. */
136 andreas 388
	sprintf(hv0, "garmin_read_records2: unexpected packet %d received!",ppid);
389
        garmin_queue_error(hv0, err_error);
93 andreas 390
      }
391
    } else {
392
      /* Expected Pid_Records but got something else. */
136 andreas 393
      sprintf(hv0, "garmin_read_records2: expected Pid_Records, got %d!",ppid);
394
      garmin_queue_error(hv0, err_error);
93 andreas 395
    }
396
  } else {
397
    /* Failed to read the Pid_Records packet off the link. */
136 andreas 398
    sprintf(hv0, "garmin_read_records2: failed to read Pid_Records packet!");
399
    garmin_queue_error(hv0, err_error);
93 andreas 400
  }
401
 
402
  return d;
403
}
404
 
405
 
406
/* Read a Pid_Records, (pid1, (pid2, pid3)+)+, Pid_Xfer_Cmplt sequence. */
407
 
408
static garmin_data *
409
garmin_read_records3 ( garmin_unit *     garmin,
410
		       garmin_pid        pid1,
411
		       garmin_datatype   type1,
412
		       garmin_pid        pid2,
413
		       garmin_datatype   type2,
414
		       garmin_pid        pid3,
415
		       garmin_datatype   type3 )
416
{
417
  garmin_data *     d         = NULL;
418
  garmin_list *     l         = NULL;
419
  garmin_packet     p;
420
  link_protocol     link      = garmin->protocol.link;
421
  int               expected  = 0;
422
  int               got       = 0;
423
  garmin_pid        ppid;
424
  int               state     = 0;
136 andreas 425
  char              hv0[256];
93 andreas 426
 
427
  if ( garmin_read(garmin,&p) > 0 ) {
428
    ppid = garmin_gpid(link,garmin_packet_id(&p));
429
    if ( ppid == Pid_Records ) {
430
      expected = get_uint16(p.packet.data);
431
 
432
      if ( garmin->verbose != 0 ) {
136 andreas 433
	sprintf(hv0, "[garmin] Pid_Records indicates %d packets to follow!",
93 andreas 434
	       expected);
136 andreas 435
	garmin_queue_error(hv0, err_info);
93 andreas 436
      }
437
 
438
      /* Allocate a list for the records. */
439
 
440
      d = garmin_alloc_data(data_Dlist);
441
      l = (garmin_list *)d->data;
442
 
443
      while ( state >= 0 && garmin_read(garmin,&p) > 0 ) {
444
	ppid = garmin_gpid(link,garmin_packet_id(&p));
445
	if ( ppid == Pid_Xfer_Cmplt ) {
446
	  /* transfer complete! */
447
	  if ( got != expected ) {
448
	    /* wrong number of packets received! */
136 andreas 449
	    sprintf(hv0, "garmin_read_records3: expected %d packets, got %d!",
93 andreas 450
		   expected,got);
136 andreas 451
	    garmin_queue_error(hv0, err_error);
93 andreas 452
	  } else if ( garmin->verbose != 0 ) {
136 andreas 453
	    sprintf(hv0, "[garmin] all %d expected packets received!",got);
454
	    garmin_queue_error(hv0, err_info);
93 andreas 455
	  }
456
	  break;
457
	}
458
	switch ( state ) {
459
	case 0:  /* want pid1 */
460
	  if ( ppid == pid1 ) {
461
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
462
	    state = 1;
463
	    got++;
464
	  } else {
465
	    state = -1;
466
	  }
467
	  break;
468
	case 1:  /* want pid2 */
469
	  if ( ppid == pid2 ) {
470
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
471
	    state = 2;
472
	    got++;
473
	  } else {
474
	    state = -1;
475
	  }
476
	  break;
477
	case 2: /* want pid3 */
478
	  if ( ppid == pid3 ) {
479
	    garmin_list_append(l,garmin_unpack_packet(&p,type3));
480
	    state = 3;
481
	    got++;
482
	  } else {
483
	    state = -1;
484
	  }
485
	  break;
486
	case 3: /* want pid2 or pid1 */
487
	  if ( ppid == pid1 ) {
488
	    garmin_list_append(l,garmin_unpack_packet(&p,type1));
489
	    state = 1;
490
	    got++;
491
	  } else if ( ppid == pid2 ) {
492
	    garmin_list_append(l,garmin_unpack_packet(&p,type2));
493
	    state = 2;
494
	    got++;
495
	  } else {
496
	    state = -1;
497
	  }
498
	  break;
499
	default:
500
	  state = -1;
501
	  break;
502
	}
503
      }
504
      if ( state < 0 ) {
505
	/* Unexpected packet received. */
136 andreas 506
	sprintf(hv0, "garmin_read_records3: unexpected packet %d received!",ppid);
507
        garmin_queue_error(hv0, err_error);
93 andreas 508
      }
509
    } else {
510
      /* Expected Pid_Records but got something else. */
136 andreas 511
      sprintf(hv0, "garmin_read_records3: expected Pid_Records, got %d!",ppid);
512
      garmin_queue_error(hv0, err_error);
93 andreas 513
    }
514
  } else {
515
    /* Failed to read the Pid_Records packet off the link. */
136 andreas 516
    sprintf(hv0, "garmin_read_records3: failed to read Pid_Records packet!");
517
    garmin_queue_error(hv0, err_error);
93 andreas 518
  }
519
 
520
  return d;
521
}
522
 
523
 
524
/* ------------------------------------------------------------------------- */
525
/* 6.1  A000 - Product Data Protocol                                         */
526
/* 6.2  A001 - Protocol Capability Protocol                                  */
527
/* ------------------------------------------------------------------------- */
528
 
529
void
530
garmin_read_a000_a001 ( garmin_unit * garmin )
531
{
532
  garmin_packet          p;
533
  garmin_product *       r;
534
  garmin_extended_data * e;
535
  int                    done = 0;
536
  int                    pos;
537
  int                    size;
538
  int                    i;
539
  int                    j;
540
  uint8                  tag;
541
  uint16                 data;
542
  uint16 *               datatypes;
543
 
544
  /* Send the product request */
545
  garmin_packetize(&p,L000_Pid_Product_Rqst,0,NULL);
546
  garmin_write(garmin,&p);
547
 
548
  /* Read the response. */
549
 
550
  while ( !done && garmin_read(garmin,&p) > 0 ) {
551
    switch ( garmin_packet_id(&p) ) {
552
    case L000_Pid_Product_Data:
553
      r = &garmin->product;
554
      /* product ID, software version, product description, additional data. */
555
      r->product_id = get_uint16(p.packet.data);
556
      r->software_version = get_sint16(p.packet.data+2);
557
      pos = 4;
558
      if ( r->product_description != NULL ) {
559
	free(r->product_description);
560
      }
561
      r->product_description = get_string(&p,&pos);      
562
      r->additional_data = merge_strings(r->additional_data,
563
					 get_strings(&p,&pos));
564
      break;
565
 
566
    case L000_Pid_Ext_Product_Data:
567
      e = &garmin->extended;
568
      /* These strings should be ignored, but we save them anyway. */
569
      pos = 0;
570
      e->ext_data = merge_strings(e->ext_data,get_strings(&p,&pos));
571
      break;
572
 
573
    case L000_Pid_Protocol_Array:
574
      /* This is the A001 protocol, initiated by the device. */
575
      size = garmin_packet_size(&p) / 3;
576
      datatypes = calloc(size,sizeof(uint16));
577
      for ( i = 0; i < size; i++ ) {
578
	tag  = p.packet.data[3*i];
579
	data = get_uint16(p.packet.data + 3*i + 1);	
580
	switch ( tag ) {
581
	case Tag_Phys_Prot_Id:  
582
	  garmin->protocol.physical = data;
583
	  break;
584
	case Tag_Link_Prot_Id:
585
	  garmin->protocol.link = data;
586
	  break;
587
	case Tag_Appl_Prot_Id:
588
	  memset(datatypes,0,size * sizeof(uint16));
589
	  for ( j = i+1; p.packet.data[3*j] == Tag_Data_Type_Id; j++ ) {
590
	    datatypes[j-i-1] = get_uint16(p.packet.data + 3*j + 1);
591
	  }
592
	  garmin_assign_protocol(garmin,data,datatypes);
593
	  break;
594
	case Tag_Data_Type_Id:
595
	  /* Skip, since we should already have handled them. */
596
	default:
597
	  break;
598
	}
599
      }
600
      free(datatypes);
601
      done = 1;
602
      break;
603
 
604
    default:
605
      /* Ignore any other packets sent from the device. */
606
      break;
607
    }
608
  }
136 andreas 609
 
610
  garmin_callback("product_request");
93 andreas 611
}
612
 
613
 
614
/* ------------------------------------------------------------------------- */
615
/* 6.4  A100 - Waypoint Transfer Protocol                                    */
616
/* ------------------------------------------------------------------------- */
617
 
618
garmin_data *
619
garmin_read_a100 ( garmin_unit * garmin )
620
{
621
  garmin_data * d = NULL;
622
 
623
  if ( garmin_send_command(garmin,Cmnd_Transfer_Wpt) != 0 ) {
624
    d = garmin_read_records(garmin,
625
			    Pid_Wpt_Data,
626
			    garmin->datatype.waypoint.waypoint);
627
  }
628
 
629
  return d;
630
}
631
 
632
 
633
/* ------------------------------------------------------------------------- */
634
/* 6.5  A101 - Waypoint Category Transfer Protocol                           */
635
/* ------------------------------------------------------------------------- */
636
 
637
garmin_data *
638
garmin_read_a101 ( garmin_unit * garmin )
639
{
640
  garmin_data * d = NULL;
641
 
642
  if ( garmin_send_command(garmin,Cmnd_Transfer_Wpt_Cats) != 0 ) {
643
    d = garmin_read_records(garmin,
644
			    Pid_Wpt_Cat,
645
			    garmin->datatype.waypoint.category);
646
  }
647
 
648
  return d;
649
}
650
 
651
 
652
/* ------------------------------------------------------------------------- */
653
/* 6.6.2  A200 - Route Transfer Protocol                                     */
654
/* ------------------------------------------------------------------------- */
655
 
656
garmin_data *
657
garmin_read_a200 ( garmin_unit * garmin )
658
{
659
  garmin_data * d = NULL;
660
 
661
  if ( garmin_send_command(garmin,Cmnd_Transfer_Rte) != 0 ) {
662
    d = garmin_read_records2(garmin,
663
			     Pid_Rte_Hdr,
664
			     garmin->datatype.route.header,
665
			     Pid_Rte_Wpt_Data,
666
			     garmin->datatype.waypoint.waypoint);
667
  }
668
 
669
  return d;
670
}
671
 
672
 
673
/* ------------------------------------------------------------------------- */
674
/* 6.6.3  A201 - Route Transfer Protocol                                     */
675
/* ------------------------------------------------------------------------- */
676
 
677
garmin_data *
678
garmin_read_a201 ( garmin_unit * garmin )
679
{
680
  garmin_data * d = NULL;
681
 
682
  if ( garmin_send_command(garmin,Cmnd_Transfer_Rte) != 0 ) {
683
    d = garmin_read_records3(garmin,
684
			     Pid_Rte_Hdr,
685
			     garmin->datatype.route.header,
686
			     Pid_Rte_Wpt_Data,
687
			     garmin->datatype.route.waypoint,
688
			     Pid_Rte_Link_Data,
689
			     garmin->datatype.route.link);
690
  }
691
 
692
  return d;
693
}
694
 
695
 
696
/* ------------------------------------------------------------------------- */
697
/* 6.7.2  A300 - Track Log Transfer Protocol                                 */
698
/* ------------------------------------------------------------------------- */
699
 
700
garmin_data *
701
garmin_read_a300 ( garmin_unit * garmin )
702
{
703
  garmin_data * d = NULL;
704
 
705
  if ( garmin_send_command(garmin,Cmnd_Transfer_Trk) != 0 ) {
706
    d = garmin_read_records(garmin,
707
			    Pid_Trk_Data,
708
			    garmin->datatype.track.data);
709
  }
710
 
711
  return d;
712
}
713
 
714
 
715
/* ------------------------------------------------------------------------- */
716
/* 6.7.3  A301 - Track Log Transfer Protocol                                 */
717
/* ------------------------------------------------------------------------- */
718
 
719
garmin_data *
720
garmin_read_a301 ( garmin_unit * garmin )
721
{
722
  garmin_data * d = NULL;
723
 
724
  if ( garmin_send_command(garmin,Cmnd_Transfer_Trk) != 0 ) {
725
    d = garmin_read_records2(garmin,
726
			     Pid_Trk_Hdr,
727
			     garmin->datatype.track.header,
728
			     Pid_Trk_Data,
729
			     garmin->datatype.track.data);
730
  }
731
 
732
  return d;
733
}
734
 
735
 
736
/* ------------------------------------------------------------------------- */
737
/* 6.7.4  A302 - Track Log Transfer Protocol                                 */
738
/* ------------------------------------------------------------------------- */
739
 
740
garmin_data *
741
garmin_read_a302 ( garmin_unit * garmin )
742
{
743
  return garmin_read_a301(garmin);
744
}
745
 
746
 
747
/* ------------------------------------------------------------------------- */
748
/* 6.8  A400 - Proximity Waypoint Transfer Protocol                          */
749
/* ------------------------------------------------------------------------- */
750
 
751
garmin_data *
752
garmin_read_a400 ( garmin_unit * garmin )
753
{
754
  garmin_data * d = NULL;
755
 
756
  if ( garmin_send_command(garmin,Cmnd_Transfer_Prx) != 0 ) {
757
    d = garmin_read_records(garmin,
758
			    Pid_Prx_Wpt_Data,
759
			    garmin->datatype.waypoint.proximity);
760
  }
761
 
762
  return d;
763
}
764
 
765
 
766
/* ------------------------------------------------------------------------- */
767
/* 6.9  A500 - Almanac Transfer Protocol                                     */
768
/* ------------------------------------------------------------------------- */
769
 
770
garmin_data *
771
garmin_read_a500 ( garmin_unit * garmin )
772
{
773
  garmin_data * d = NULL;
774
 
775
  if ( garmin_send_command(garmin,Cmnd_Transfer_Alm) != 0 ) {
776
    d = garmin_read_records(garmin,
777
			    Pid_Almanac_Data,
778
			    garmin->datatype.almanac);
779
  }
780
 
781
  return d;
782
}
783
 
784
 
785
/* ------------------------------------------------------------------------- */
786
/* 6.10  A600 - Date and Time Initialization Protocol                        */
787
/* ------------------------------------------------------------------------- */
788
 
789
garmin_data *
790
garmin_read_a600 ( garmin_unit * garmin )
791
{
792
  garmin_data * d = NULL;
793
 
794
  d = garmin_read_singleton(garmin,
795
			    Pid_Date_Time_Data,
796
			    garmin->datatype.date_time);
797
 
798
  return d;
799
}
800
 
801
 
802
/* ------------------------------------------------------------------------- */
803
/* 6.11  A650 - FlightBook Transfer Protocol                                 */
804
/* ------------------------------------------------------------------------- */
805
 
806
garmin_data *
807
garmin_read_a650 ( garmin_unit * garmin )
808
{
809
  garmin_data * d = NULL;
810
 
811
  if ( garmin_send_command(garmin,Cmnd_FlightBook_Transfer) ) {
812
    d = garmin_read_records(garmin,
813
			    Pid_FlightBook_Record,
814
			    garmin->datatype.flightbook);
815
  }
816
 
817
  return d;
818
}
819
 
820
 
821
/* ------------------------------------------------------------------------- */
822
/* 6.12  A700 - Position Initialization Protocol                             */
823
/* ------------------------------------------------------------------------- */
824
 
825
garmin_data *
826
garmin_read_a700 ( garmin_unit * garmin )
827
{
828
  garmin_data * d;
829
 
830
  d = garmin_read_singleton(garmin,
831
			    Pid_Position_Data,
832
			    garmin->datatype.position);
833
 
834
  return d;
835
}
836
 
837
 
838
/* ------------------------------------------------------------------------- */
839
/* 6.13  A800 - PVT Protocol                                                 */
840
/* ------------------------------------------------------------------------- */
841
 
842
garmin_data *
843
garmin_read_a800 ( garmin_unit * garmin )
844
{
845
  garmin_data * d;
846
 
847
  d = garmin_read_singleton(garmin,
848
			    Pid_Pvt_Data,
849
			    garmin->datatype.pvt);
850
 
851
  return d;
852
}
853
 
854
 
855
/* ------------------------------------------------------------------------- */
856
/* 6.14  A906 - Lap Transfer Protocol                                        */
857
/* ------------------------------------------------------------------------- */
858
 
859
garmin_data *
860
garmin_read_a906 ( garmin_unit * garmin )
861
{
862
  garmin_data * d = NULL;
863
 
864
  if ( garmin_send_command(garmin,Cmnd_Transfer_Laps) != 0 ) {
865
    d = garmin_read_records(garmin,Pid_Lap,garmin->datatype.lap);
866
  }
867
 
868
  return d;
869
}
870
 
871
 
872
/* ------------------------------------------------------------------------- */
873
/* 6.15  A1000 - Run Transfer Protocol                                       */
874
/* ------------------------------------------------------------------------- */
875
 
876
garmin_data *
877
garmin_read_a1000 ( garmin_unit * garmin )
878
{
879
  garmin_data * d  = NULL;
880
  garmin_list * l  = NULL;
881
 
882
  /* Read the runs, then the laps, then the track log. */
883
 
884
  if ( garmin_send_command(garmin,Cmnd_Transfer_Runs) != 0 ) {
885
    d = garmin_alloc_data(data_Dlist);
886
    l = d->data;
887
    garmin_list_append(l,garmin_read_records(garmin,Pid_Run,
888
					     garmin->datatype.run));
889
    garmin_list_append(l,garmin_read_a906(garmin));
890
    garmin_list_append(l,garmin_read_a302(garmin));
891
  }
892
 
893
  return d;
894
}
895
 
896
 
897
/* ------------------------------------------------------------------------- */
898
/* 6.16  A1002 - Workout Transfer Protocol                                   */
899
/* ------------------------------------------------------------------------- */
900
 
901
garmin_data *
902
garmin_read_a1002 ( garmin_unit * garmin )
903
{
904
  garmin_data * d  = NULL;
905
  garmin_list * l  = NULL;
906
 
907
  /* Read the workouts, then the workout occurrences */
908
 
909
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workouts) != 0 ) {
910
    d = garmin_alloc_data(data_Dlist);
911
    l = d->data;
912
    garmin_list_append(l,
913
		       garmin_read_records(garmin,
914
					   Pid_Workout,
915
					   garmin->datatype.workout.workout));
916
    garmin_list_append(l,garmin_read_a1003(garmin));
917
  }
918
 
919
  return d;
920
}
921
 
922
 
923
/* ------------------------------------------------------------------------- */
924
/* --- UNDOCUMENTED ---  A1003 - Workout Occurrence Transfer Protocol        */
925
/* ------------------------------------------------------------------------- */
926
 
927
garmin_data *
928
garmin_read_a1003 ( garmin_unit * garmin )
929
{
930
  garmin_data * d = NULL;
931
 
932
  /* Read the workouts, then the workout occurrences */
933
 
934
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workout_Occurrences) != 0 ) {
935
    d = garmin_read_records(garmin,
936
			    Pid_Workout_Occurrence,
937
			    garmin->datatype.workout.occurrence);
938
  }
939
 
940
  return d;
941
}
942
 
943
 
944
/* ------------------------------------------------------------------------- */
945
/* 6.17  A1004 - Fitness User Profile Transfer Protocol                      */
946
/* ------------------------------------------------------------------------- */
947
 
948
garmin_data *
949
garmin_read_a1004 ( garmin_unit * garmin )
950
{
951
  garmin_data * d = NULL;
952
 
953
  if ( garmin_send_command(garmin,Cmnd_Transfer_Fitness_User_Profile) != 0 ) {
954
    d = garmin_read_singleton(garmin,
955
			      Pid_Fitness_User_Profile,
956
			      garmin->datatype.fitness);
957
  }
958
 
959
  return d;
960
}
961
 
962
 
963
/* ------------------------------------------------------------------------- */
964
/* 6.18  A1005 - Workout Limits Transfer Protocol                            */
965
/* ------------------------------------------------------------------------- */
966
 
967
garmin_data *
968
garmin_read_a1005 ( garmin_unit * garmin )
969
{
970
  garmin_data * d = NULL;
971
 
972
  if ( garmin_send_command(garmin,Cmnd_Transfer_Workout_Limits) != 0 ) {
973
    d = garmin_read_singleton(garmin,
974
			      Pid_Workout_Limits,
975
			      garmin->datatype.workout.limits);
976
  }
977
 
978
  return d;
979
}
980
 
981
 
982
/* ------------------------------------------------------------------------- */
983
/* 6.19  A1006 - Course Transfer Protocol                                    */
984
/* ------------------------------------------------------------------------- */
985
 
986
garmin_data *
987
garmin_read_a1006 ( garmin_unit * garmin )
988
{
989
  garmin_data * d  = NULL;
990
  garmin_list * l  = NULL;
991
 
992
  if ( garmin_send_command(garmin,Cmnd_Transfer_Courses) != 0 ) {
993
    d = garmin_alloc_data(data_Dlist);
994
    l = d->data;
995
    garmin_list_append(l,garmin_read_records(garmin,
996
					     Pid_Course,
997
					     garmin->datatype.course.course));
998
    garmin_list_append(l,garmin_read_a1007(garmin));
999
    garmin_list_append(l,garmin_read_a1012(garmin));
1000
    garmin_list_append(l,garmin_read_a1008(garmin));
1001
  }
1002
 
1003
  return d;
1004
}
1005
 
1006
 
1007
/* ------------------------------------------------------------------------- */
1008
/* --- UNDOCUMENTED ---  A1007 - Course Lap Transfer Protocol                */
1009
/* ------------------------------------------------------------------------- */
1010
 
1011
garmin_data *
1012
garmin_read_a1007 ( garmin_unit * garmin )
1013
{
1014
  garmin_data * d = NULL;
1015
 
1016
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Laps) != 0 ) {
1017
    d = garmin_read_records(garmin,
1018
			    Pid_Course_Lap,
1019
			    (garmin->datatype.course.lap != data_Dnil) ?
1020
			    garmin->datatype.course.lap :
1021
			    garmin->datatype.lap);
1022
  }
1023
 
1024
  return d;
1025
}
1026
 
1027
 
1028
/* ------------------------------------------------------------------------- */
1029
/* --- UNDOCUMENTED ---  A1008 - Course Point Transfer Protocol              */
1030
/* ------------------------------------------------------------------------- */
1031
 
1032
garmin_data *
1033
garmin_read_a1008 ( garmin_unit * garmin )
1034
{
1035
  garmin_data * d = NULL;
1036
 
1037
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Points) != 0 ) {
1038
    d = garmin_read_records(garmin,
1039
			    Pid_Course_Point,
1040
			    garmin->datatype.course.point);
1041
  }
1042
 
1043
  return d;
1044
}
1045
 
1046
 
1047
/* ------------------------------------------------------------------------- */
1048
/* 6.20  A1009 - Course Limits Transfer Protocol                             */
1049
/* ------------------------------------------------------------------------- */
1050
 
1051
garmin_data *
1052
garmin_read_a1009 ( garmin_unit * garmin )
1053
{
1054
  garmin_data * d = NULL;
1055
 
1056
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Limits) != 0 ) {
1057
    d = garmin_read_singleton(garmin,
1058
			      Pid_Course_Limits,
1059
			      garmin->datatype.course.limits);
1060
  }
1061
 
1062
  return d;
1063
}
1064
 
1065
 
1066
/* ------------------------------------------------------------------------- */
1067
/* --- UNDOCUMENTED ---  A1012 - Course Track Transfer Protocol              */
1068
/* ------------------------------------------------------------------------- */
1069
 
1070
garmin_data *
1071
garmin_read_a1012 ( garmin_unit * garmin )
1072
{
1073
  garmin_datatype  header;
1074
  garmin_datatype  data;
1075
  garmin_data *    d = NULL;
1076
 
1077
  if ( garmin_send_command(garmin,Cmnd_Transfer_Course_Tracks) != 0 ) {
1078
 
1079
    if ( garmin->datatype.course.track.header != data_Dnil ) {
1080
      header = garmin->datatype.course.track.header;
1081
    } else {
1082
      header = garmin->datatype.track.header;
1083
    }
1084
 
1085
    if ( garmin->datatype.course.track.data != data_Dnil ) {
1086
      data = garmin->datatype.course.track.data;
1087
    } else {
1088
      data = garmin->datatype.track.data;
1089
    }
1090
 
1091
    d = garmin_read_records2(garmin,
1092
			     Pid_Course_Trk_Hdr,
1093
			     header,
1094
			     Pid_Course_Trk_Data,
1095
			     data);
1096
  }
1097
 
1098
  return d;
1099
}
1100
 
1101
 
1102
/* ------------------------------------------------------------------------- */
1103
/* Get data from the Garmin unit via a particular top-level protocol         */
1104
/* ------------------------------------------------------------------------- */
1105
 
1106
garmin_data *
1107
garmin_read_via ( garmin_unit * garmin, appl_protocol protocol )
1108
{
1109
  garmin_data * data = NULL;
1110
 
1111
#define CASE_PROTOCOL(x)                                                      \
1112
  case appl_A##x:                                                             \
1113
    if ( garmin->verbose != 0 ) {                                             \
136 andreas 1114
      fprintf(stderr, "[garmin] -> garmin_read_a" #x "\n");                            \
93 andreas 1115
    }                                                                         \
1116
    data = garmin_read_a##x(garmin);                                          \
1117
    if ( garmin->verbose != 0 ) {                                             \
136 andreas 1118
      fprintf(stderr, "[garmin] <- garmin_read_a" #x "\n");                            \
93 andreas 1119
    }                                                                         \
1120
    break
1121
 
1122
  switch ( protocol ) {
1123
  CASE_PROTOCOL(100);   /* waypoints */
1124
  CASE_PROTOCOL(101);   /* waypoint categories */
1125
  CASE_PROTOCOL(200);   /* routes */
1126
  CASE_PROTOCOL(201);   /* routes */
1127
  CASE_PROTOCOL(300);   /* track log */
1128
  CASE_PROTOCOL(301);   /* track log */
1129
  CASE_PROTOCOL(302);   /* track log */
1130
  CASE_PROTOCOL(400);   /* proximity waypoints */
1131
  CASE_PROTOCOL(500);   /* almanac */
1132
  CASE_PROTOCOL(650);   /* flightbook */
1133
  CASE_PROTOCOL(1000);  /* runs */
1134
  CASE_PROTOCOL(1002);  /* workouts */
1135
  CASE_PROTOCOL(1004);  /* fitness user profile */
1136
  CASE_PROTOCOL(1005);  /* workout limits */
1137
  CASE_PROTOCOL(1006);  /* courses */
1138
  CASE_PROTOCOL(1009);  /* course limits */
1139
  default:
1140
    /* invalid top-level read protocol */
1141
    break;
1142
  }
1143
 
136 andreas 1144
  garmin_callback();
93 andreas 1145
  return data;
1146
}
1147
 
1148
 
1149
/* ------------------------------------------------------------------------- */
1150
/* Get data from the Garmin unit                                             */
1151
/* ------------------------------------------------------------------------- */
1152
 
1153
garmin_data *
1154
garmin_get ( garmin_unit * garmin, garmin_get_type what )
1155
{
1156
  garmin_data * data = NULL;
1157
 
1158
#define CASE_WHAT(x,y) \
1159
  case GET_##x: data = garmin_read_via(garmin,garmin->protocol.y); break
1160
 
1161
  switch ( what ) {
1162
  CASE_WHAT(WAYPOINTS,waypoint.waypoint);
1163
  CASE_WHAT(WAYPOINT_CATEGORIES,waypoint.category);
1164
  CASE_WHAT(ROUTES,route);
1165
  CASE_WHAT(TRACKLOG,track);
1166
  CASE_WHAT(PROXIMITY_WAYPOINTS,waypoint.proximity);
1167
  CASE_WHAT(ALMANAC,almanac);
1168
  CASE_WHAT(FLIGHTBOOK,flightbook);
1169
  CASE_WHAT(RUNS,run);
1170
  CASE_WHAT(WORKOUTS,workout.workout);
1171
  CASE_WHAT(FITNESS_USER_PROFILE,fitness);
1172
  CASE_WHAT(WORKOUT_LIMITS,workout.limits);
1173
  CASE_WHAT(COURSES,course.course);
1174
  CASE_WHAT(COURSE_LIMITS,course.limits);
1175
  default:
1176
    /* invalid garmin_get_type */
1177
    break;
1178
  }
1179
 
1180
  return data;
1181
}
1182
 
1183
 
1184
/* Initialize a connection with a Garmin unit. */
1185
 
101 andreas 1186
int garmin_init(garmin_unit *garmin, int verbose)
93 andreas 1187
{
101 andreas 1188
	memset(garmin, 0, sizeof(garmin_unit));
1189
	garmin->verbose = verbose;
1190
	garmin->usb.fd = -1;
93 andreas 1191
 
101 andreas 1192
	if ( garmin_open(garmin) != 0 )
1193
	{
1194
	   garmin_start_session(garmin);
1195
	   garmin_read_a000_a001(garmin);
1196
	   return 1;
1197
	}
1198
	else
1199
	{
1200
	   return 0;
1201
	}
93 andreas 1202
}
1203