Subversion Repositories public

Rev

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