Coverage Report

Created: 2026-10-17 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_tsip.c
Line
Count
Source
1
/*
2
 * Handle the Trimble TSIP packet format
3
 * by Rob Janssen, PE1CHL.
4
 * Acutime Gold support by Igor Socec <igorsocec@gmail.com>
5
 * Trimble RES multi-constellation support by Nuno Goncalves <nunojpg@gmail.com>
6
 *
7
 * Week counters are not limited to 10 bits. It's unknown what
8
 * the firmware is doing to disambiguate them, if anything; it might just
9
 * be adding a fixed offset based on a hidden epoch value, in which case
10
 * unhappy things will occur on the next rollover.
11
 *
12
 * TSIPv1n RES270 Resolution SMTx support added by:
13
 *     Gary E. Miller <gem@rellim.com>
14
 *
15
 * This file is Copyright by the GPSD project
16
 * SPDX-License-Identifier: BSD-2-clause
17
 */
18
19
#include "../include/gpsd_config.h"   // must be before all includes
20
21
#include <math.h>
22
#include <stdbool.h>
23
#include <stdio.h>
24
#include <stdlib.h>           // For llabs()
25
#include <string.h>
26
#include <time.h>
27
#include <unistd.h>
28
29
#include "../include/compiler.h"   // for FALLTHROUGH
30
#include "../include/gpsd.h"
31
#include "../include/bits.h"
32
#include "../include/strfuncs.h"
33
#include "../include/timespec.h"
34
35
#ifdef TSIP_ENABLE
36
// RES SMT 360 has 32 max channels, use 64 for next gen
37
39.4k
#define TSIP_CHANNELS  64
38
#if MAXCHANNELS < TSIP_CHANNELS
39
    #error "MACHANNELS < TSIP_CHANNELS"
40
#endif
41
42
/* defines for Set or Request I/O Options (0x35)
43
 * SMT 360 default: IO1_DP|IO1_LLA, IO2_ENU, 0, IO4_DBHZ */
44
// byte 1 Position
45
322
#define IO1_ECEF 1
46
829
#define IO1_LLA 2
47
730
#define IO1_MSL 4
48
920
#define IO1_DP 0x10
49
// IO1_8F20 not in SMT 360
50
689
#define IO1_8F20 0x20
51
// byte 2 Velocity
52
231
#define IO2_VECEF 1
53
829
#define IO2_ENU 2
54
// byte 3 Timing
55
#define IO3_UTC 1
56
// byte 4 Aux/Reserved
57
#define IO4_RAW 1
58
689
#define IO4_DBHZ 8
59
60
2.15k
#define SEMI_2_DEG      (180.0 / 2147483647L)    // 2^-31 semicircle to deg
61
62
// Start TSIPv1 values and flags
63
64
/* Data Bits v1
65
 * Used in x91-00 */
66
static struct vlist_t vdbits1[] = {
67
    {3, "8 bits"},
68
    {0, NULL},
69
};
70
71
/* Error Code Flags
72
 * Used in xa3-21 */
73
static struct vlist_t verr_codes1[] = {
74
    {1, "Parameter Error"},
75
    {2, "Length Error"},
76
    {3, "Invalid Parket Format"},
77
    {4, "Invalid Checksum"},
78
    {5, "Bad TNL/User mode"},
79
    {6, "Invalid Packet ID"},
80
    {7, "Invalid Subacket ID"},
81
    {8, "Update in Progress"},
82
    {9, "Internal Error (div by 0)"},
83
    {10, "Internal Error (failed queuing)"},
84
    {0, NULL},
85
};
86
87
/* Fix Type v1
88
 * Used in xa1-11 */
89
static struct vlist_t vfix_type1[] = {
90
    {0, "No Fix"},
91
    {1, "1D"},
92
    {2, "3D"},
93
    {0, NULL},
94
};
95
96
/* GNSS Decoding Status to string
97
 * Used in xa3-11 */
98
static struct vlist_t vgnss_decode_status1[] = {
99
    {0, "Doing Fixes"},
100
    {1, "No GPS time"},
101
    {2, "PDOP too high"},
102
    {3, "0 usable sats"},
103
    {4, "1 usable sat"},
104
    {5, "2 usable sats"},
105
    {6, "3 usable sats"},
106
    {0xff, "GPS Time Fix (OD mode)"},
107
    {0, NULL},
108
};
109
110
/* Major Alarm Flags v1
111
 * Used in xa3-00 */
112
static struct flist_t vmajor_alarms1[] = {
113
    {1, 1, "Not tracking sats"},
114
    {2, 2, "PPS bad"},
115
    {4, 4, "PPS not generated"},
116
    {0x80, 0x80, "Spoofing/Multipath"},
117
    {0x100, 0x100, "Jamming"},
118
    {0, 0, NULL},
119
};
120
121
/* Minor Alarm Flags v1
122
 * Used in xa3-00 */
123
static struct flist_t vminor_alarms1[] = {
124
    {1, 1, "Ant Open"},
125
    {2, 2, "Ant Short"},
126
    {4, 4, "Leap Pending"},
127
    {8, 8, "Almanac Incomplete"},
128
    {0x10, 0x10, "Survey in Progress"},
129
    {0x20, 0x20, "GPS Almanac Incomplete"},
130
    {0x20, 0x20, "GLO Almanac Incomplete"},
131
    {0x40, 0x40, "BDS Almanac Incomplete"},
132
    {0x80, 0x80, "GAL Almanac Incomplete"},
133
    {0x100, 0x100, "Leap Second Insertion"},
134
    {0x200, 0x200, "Leap Second Deletion"},
135
    {0, 0, NULL},
136
};
137
138
/* Parity v1
139
 * Used in x91-00 */
140
static struct vlist_t vparity1[] = {
141
    {0, "None bits"},
142
    {1, "Odd"},
143
    {2, "Even"},
144
    {255, "Ignore"},
145
    {0, NULL},
146
};
147
148
/* Port Name v1
149
 * Used in x91-00 */
150
static struct vlist_t vport_name1[] = {
151
    {0, "Port A"},
152
    {1, "Port B"},
153
    {255, "Current Port"},
154
    {0, NULL},
155
};
156
157
/* Port Type v1
158
 * Used in x91-00 */
159
static struct vlist_t vport_type1[] = {
160
    {0, "UART"},
161
    {0, NULL},
162
};
163
164
/* Position Mask
165
 * Used in xa1-11 */
166
static struct flist_t vpos_mask1[] = {
167
    {0, 1, "Real Time Position"},
168
    {1, 1, "Surveyed Position"},
169
    {0, 2, "LLA Position"},
170
    {2, 2, "XYZ ECEF"},
171
    {0, 4, "HAE"},
172
    {4, 4, "MSL"},
173
    {0, 8, "Velocity ENU"},
174
    {8, 8, "Velocity ECEF"},
175
    {0, 0, NULL},
176
};
177
178
/* PPS Mask v1
179
 * Used in x91-03 */
180
static struct vlist_t vpps_mask1[] = {
181
    {0, "Off"},
182
    {1, "On"},
183
    {2, "Fix Based"},
184
    {3, "When Valid"},
185
    {4, "Off"},
186
    {5, "On/Negative"},
187
    {6, "Fix Based/Negative"},
188
    {7, "When Valid/Negative"},
189
    {0, NULL},
190
};
191
192
/* Protocol v1
193
 * Used in x91-00 */
194
static struct vlist_t vprotocol1[] = {
195
    {2, "TSIP"},
196
    {4, "NMEA"},
197
    {255, "Ignore"},
198
    {0, NULL},
199
};
200
201
/* Receiver Mode v1
202
 * Used in xa3-11 */
203
static struct vlist_t vrec_mode1[] = {
204
    {0, "2D"},
205
    {1, "(3D) Time Only"},
206
    {3, "Automatic"},
207
    {6, "Overdetermined"},
208
    {0, NULL},
209
};
210
211
/* Reset Type, Reset Cause
212
 * Used in x92-00, x92-01 */
213
static struct vlist_t vreset_type1[] = {
214
    {1, "No Reset"},           // x92-01 only
215
    {1, "Cold Reset"},
216
    {2, "Hot Reset"},
217
    {3, "Warm Reset"},
218
    {4, "Factory Reset"},
219
    {5, "System Reset"},
220
    {6, "Power Cycle"},        // x92-01 only
221
    {7, "Watchdog"},           // x92-01 only
222
    {8, "Hardfault"},          // x92-01 only
223
    {0, NULL},
224
};
225
226
/* Satellite Flags v1
227
 * Used in xa2-00 */
228
static struct flist_t vsflags1[] = {
229
    {1, 1, "Acquired"},
230
    {2, 2, "Used in Position"},
231
    {4, 4, "Used in PPS"},
232
    // Bits 8 - 15 "Satellite Status, otherwise undocumented.
233
    {0, 0, NULL},
234
};
235
236
/* Speed v1
237
 * Used in x91-00 */
238
static struct vlist_t vspeed1[] = {
239
    {11, "115200"},
240
    {12, "230400"},
241
    {13, "460800"},
242
    {14, "1821600"},
243
    {255, "Ignore"},
244
    {0, NULL},
245
};
246
247
/* Self-Survey Mask v1
248
 * Used in x91-04 */
249
static struct flist_t vss_mask1[] = {
250
    {1, 1, "SS restarted"},
251
    {0, 2, "SS Disabled"},
252
    {2, 2, "SS Enabled"},
253
    {0, 8, "Don't save position"},
254
    {8, 8, "Save position"},
255
    {0, 0, NULL},
256
};
257
258
/* Stop Bits v1
259
 * Used in x91-00 */
260
static struct vlist_t vstop1[] = {
261
    {0, "1 bit"},
262
    {1, "2 bit"},
263
    {255, "Ignore"},
264
    {0, NULL},
265
};
266
267
/* SV Type v1
268
 * Used in xa2-00 */
269
static struct vlist_t vsv_type1[] = {
270
    {1, "GPS L1C"},
271
    {2, "GPS L2"},
272
    {3, "GPS L5"},
273
    {5, "GLO G1"},
274
    {6, "GLO G2"},
275
    {9, "SBAS"},
276
    {13, "BDS B1"},
277
    {14, "BDS B2i"},
278
    {15, "BDS B2a"},
279
    {17, "GAL E1"},
280
    {18, "GAL E5a"},
281
    {19, "GAL E5b"},
282
    {20, "GAL E6"},
283
    {22, "QZSS L1"},
284
    {23, "QZSS L2C"},
285
    {24, "QZSS L5"},
286
    {26, "IRNSS L5"},
287
    {0, NULL},
288
};
289
290
/* SV Types v1
291
 * Used in x91-01 */
292
static struct flist_t vsv_types1[] = {
293
    {1, 1, "GPS L1C"},
294
    {2, 2, "GPS L2"},
295
    {4, 3, "GPS L5"},
296
    {0x20, 0x20, "GLO G1"},
297
    {0x40, 0x40, "GLO G2"},
298
    {0x100, 0x100, "SBAS"},
299
    {0x1000, 0x1000, "BDS B1"},
300
    {0x2000, 0x2000, "BDS B2i"},
301
    {0x4000, 0x4000, "BDS B2a"},
302
    {0x10000, 0x10000, "GAL E1"},
303
    {0x20000, 0x20000, "GAL E5a"},
304
    {0x40000, 0x40000, "GAL E5b"},
305
    {0x80000, 0x80000, "GAL E6"},
306
    {0x100000, 0x100000, "QZSS L1"},
307
    {0x200000, 0x200000, "QZSS L2C"},
308
    {0x400000, 0x400000, "QZSS L5"},
309
    {0x1000000, 0x1000000, "IRNSS L5"},
310
    {0, 0, NULL},
311
};
312
313
/* Time Base v1
314
 * Used in x91-03, xa1-00 */
315
static struct vlist_t vtime_base1[] = {
316
    {0, "GPS"},
317
    {1, "GLO"},
318
    {2, "BDS"},
319
    {3, "GAL"},
320
    {4, "GPS/UTC"},
321
    {6, "GLO/UTC"},
322
    {6, "BDS/UTC"},
323
    {7, "GAL/UTC"},
324
    {0, NULL},
325
};
326
327
/* Time Flags v1
328
 * Used in xa1-00 */
329
static struct flist_t vtime_flags1[] = {
330
    {0, 1, "UTC Invalid"},
331
    {1, 1, "UTC Valid"},
332
    {0, 2, "Time Invalid"},
333
    {2, 2, "Time Valid"},
334
    {0, 0, NULL},
335
};
336
337
// End TSIPv1 values and flags
338
339
// Start TSIP values and flags
340
341
/* Error Code Flags
342
 * Used in x46 */
343
static struct flist_t verr_codes[] = {
344
    {1, 1, "No Bat"},
345
    {0x10, 0x30, "Ant Open"},
346
    {0x30, 0x30, "Ant Short"},
347
    {0, 0, NULL},
348
};
349
350
/* GNSS Decoding Status to string
351
 * Used in x46, x8f-ac */
352
static struct vlist_t vgnss_decode_status[] = {
353
    {0, "Doing Fixes"},
354
    {1, "No GPS time"},
355
    {2, "Needs Init"},                      // ACE II, LassenSQ
356
    {3, "PDOP too high"},
357
    {8, "0 usable sats"},
358
    {9, "1 usable sat"},
359
    {10, "2 usable sats"},
360
    {11, "3 usable sats"},
361
    {12, "chosen sat unusable"},
362
    {16, "TRAIM rejected"},                 // Thunderbolt E
363
    {0xbb, "GPS Time Fix (OD mode)"},       // Acutime 360
364
    {0, NULL},
365
};
366
367
/* Disciplining Activity
368
 * Used in x46, x8f-ac */
369
static struct vlist_t vdisc_act[] = {
370
    {0, "Phase Locking"},
371
    {1, "OSC Wrm-up"},
372
    {2, "Freq lokgin"},
373
    {3, "Placing PPS"},
374
    {4, "Init Loop FIlter"},
375
    {5, "Comp OCXO"},
376
    {6, "Inactive"},
377
    {7, "Not used"},
378
    {8, "REcovery Mode"},
379
    {0, NULL},
380
};
381
382
/* PPS indication
383
 * Used in x46, x8f-ac */
384
static struct vlist_t vpps_ind[] = {
385
    {0, "PPS Good"},
386
    {1, "PPS Ungood"},
387
    {0, NULL},
388
};
389
390
/* PPS Reference
391
 * Used in x46, x8f-ac */
392
static struct vlist_t vpps_ref[] = {
393
    {0, "GNSS"},
394
    {1, "Externa;"},
395
    {0xff, "None;"},
396
    {0, NULL},
397
};
398
399
/* Packet Broadcast Mask
400
 * Used in x8f-a3 */
401
static struct flist_t vpbm_mask0[] = {
402
    {1, 1, "x8f-ab"},
403
    {4, 4, "x8f-ac"},
404
    {0x40, 0x40, "Automatic"},
405
    {0, 0, NULL},
406
};
407
408
/* Receiver Mode
409
 * Used in xbb, x8f-ac */
410
static struct vlist_t vrec_mode[] = {
411
    {0, "Autonomous (2D/3D)"},
412
    {1, "Time Only (1-SV)"},    // Accutime 2000, Tbolt
413
    {3, "2D"},                  // Accutime 2000, Tbolt
414
    {4, "3D"},                  // Accutime 2000, Tbolt
415
    {5, "DGPS"},                // Accutime 2000, Tbolt
416
    {6, "2D Clock hold"},       // Accutime 2000, Tbolt
417
    {7, "Overdetermined"},      // Stationary Timing, surveyed
418
    {0, NULL},
419
};
420
421
/* Save Status
422
 * Used in x91-02 */
423
static struct flist_t vsave_status1[] = {
424
    {0, 1, "Save failed"},
425
    {1, 1, "Save OK"},
426
    {0, 0, NULL},
427
};
428
429
/* Self-Survey Enable
430
 * Used in x8f-a9 */
431
static struct vlist_t vss_enable[] = {
432
    {0, "SS Disabled"},
433
    {1, "SS Enabled"},
434
    {0, NULL},
435
};
436
437
/* Self-Survey Save
438
 * Used in x8f-a9 */
439
static struct vlist_t vss_save[] = {
440
    {0, "Don't Save"},
441
    {1, "Save at end"},
442
    {0, NULL},
443
};
444
445
/* Status 1
446
 * Used in x4b */
447
static struct flist_t vstat1[] = {
448
    {2, 2, "RTC invalid"},
449
    {8, 8, "No Almanac"},
450
    {0, 0, NULL},
451
};
452
453
/* Status 2
454
 * Used in x4b */
455
static struct flist_t vstat2[] = {
456
    {1, 1, "Superpackets"},      // x8f-20 (LFwEI)
457
    {2, 2, "Superpackets 2"},    // x8f-1b, x8f-ac
458
    {0, 0, NULL},
459
};
460
461
/* SV Bad
462
 * Used in x5d */
463
static struct vlist_t vsv_bad[] = {
464
    {0, "OK"},
465
    {1, "Bad Parity"},
466
    {2, "Bad Health"},
467
    {0, NULL},
468
};
469
470
/* SV Type
471
 * Used in x5d */
472
static struct vlist_t vsv_type[] = {
473
    {0, "GPS"},
474
    {1, "GLO"},
475
    {2, "BDS"},
476
    {3, "GAL"},
477
    {6, "QZSS"},
478
    {0, NULL},
479
};
480
481
/* SV Used Flags
482
 * Used in x5d */
483
static struct flist_t vsv_used_flags[] = {
484
    {1, 1, "Used in Timing"},
485
    {2, 2, "Used in Position"},
486
    {0, 0, NULL},
487
};
488
489
/* x4c Dynamics Code
490
 * Used in x4c */
491
static struct vlist_t vx4c_dyncode[] = {
492
    {1, "Land"},             // < 120 knots
493
    {2, "Sea"},              // < 50 knots
494
    {3, "Air"},              // > 800 knots
495
    {0,NULL},
496
};
497
498
/* x55 auxiliary
499
 * Used in x55 */
500
static struct flist_t vx55_aux[] = {
501
    {0, 1, "x5a Off"},
502
    {1, 1, "x5a On"},
503
    {0, 0, NULL},
504
};
505
506
/* x55 Position
507
 * Used in x55 */
508
static struct flist_t vx55_pos[] = {
509
    {1, 1, "ECEF On"},
510
    {2, 2, "LLA On"},
511
    {0, 4, "HAE"},
512
    {4, 4, "MSL"},
513
    {0, 0x10, "Single Precision"},
514
    {0x10, 0x104, "Double Position"},
515
    {0, 0, NULL},
516
};
517
518
/* x55 Timing
519
 * Used in x55 */
520
static struct flist_t vx55_timing[] = {
521
    {1, 1, "Use x8e-a2"},
522
    {0, 0, NULL},
523
};
524
525
/* x55 Velocity
526
 * Used in x55 */
527
static struct flist_t vx55_vel[] = {
528
    {1, 1, "ECEF On"},
529
    {2, 2, "ENU On"},
530
    {0, 0, NULL},
531
};
532
533
/* x57 Source of Info
534
 * Used in x57 */
535
static struct flist_t vx57_info[] = {
536
    {0, 1, "Old Fix"},
537
    {1, 1, "New Fix"},
538
    {0, 0, NULL},
539
};
540
541
/* x57 Fix Mode
542
 * Used in x6c, x57, yet another decode of the same data... */
543
static struct vlist_t vx57_fmode[] = {
544
    {0, "No Fix"},
545
    {1, "Time"},             // Time only 1SV/2D
546
    {3, "2D Fix"},
547
    {4, "3D Fix"},
548
    {5, "OD Fix"},
549
    {0,NULL},
550
};
551
552
/* x5c Acquisition Flag
553
 * Used in x5c */
554
static struct vlist_t vx5c_acq[] = {
555
    {0, "Never"},
556
    {1, "Yes"},
557
    {2, "Search"},
558
    {0,NULL},
559
};
560
561
/* x5c Ephemeris Flag
562
 * Used in x5c */
563
static struct vlist_t vx5c_eflag[] = {
564
    {0, "none"},
565
    {1, "Decoded"},
566
    {3, "Decoded/Healthy"},
567
    {19, "Used"},
568
    {51, "Used/DGPS"},
569
    {0,NULL},
570
};
571
572
/* x82 Mode Timing
573
 * Used in x82 */
574
static struct vlist_t vx82_mode[] = {
575
    {0, "Man DGPS Off"},      // No DPGS ever
576
    {1, "Man DGPS OOn"},      // Only DPGS ever
577
    {2, "Auto DGPS Off"},     // DGPS unavailable
578
    {3, "Auto DGPS On"},      // DGPS available, and in use
579
    {4, NULL},
580
};
581
582
/* x8f-20 Fix Flags
583
 * Used in x8f-20 */
584
static struct flist_t vx8f_20_fflags[] = {
585
    {0, 1, "Fix Yes"},
586
    {2, 2, "DGPS"},
587
    {0, 4, "3D"},
588
    {4, 4, "2D"},
589
    {8, 8, "Alt Holdt"},
590
    {0x10, 0x10, "Filtered"},
591
    {0, 0, NULL},
592
};
593
594
/* Fis Dimension, Fix Mode
595
 * Used in x6c, x6d */
596
static struct flist_t vfix[] = {
597
    // Accutime calls 0 "Auto"
598
    {0, 7, "No Fix"},       // not in ResSMT360
599
    // in x6d, Thunderbolt E calls 1 "1D Time Fix", not an OD Fix
600
    {1, 7, "1D/OD Fix"},
601
    // Accutime calls 3 "2D Clock Hold"
602
    {3, 7, "2D Fix"},
603
    {4, 7, "3D Fix"},
604
    {5, 7, "OD Fix"},       // in Thunderbolt E, x6d, others
605
    {6, 7, "DGPS"},         // in Accutime
606
    {0, 8, "Auto"},
607
    {8, 8, "Manual"},       // aka surveyed
608
    {0, 0, NULL},
609
};
610
611
/* Timing Flags
612
 * Used in x8f-ab */
613
static struct flist_t vtiming[] = {
614
    {0, 1, "GPS time"},
615
    {1, 1, "UTC time"},
616
    {0, 2, "GPS PPS"},
617
    {1, 2, "UTC PPS"},
618
    {4, 4, "Time not set"},
619
    {8, 8,  "no UTC info"},
620
    {0x10, 0x10, "time from user"},
621
    {0, 0, NULL},
622
};
623
624
/* Critical Alarm Flags
625
 * Used in x8f-ac */
626
static struct flist_t vcrit_alarms[] = {
627
    {1, 1, "ROM error"},               // Thunderbolt
628
    {2, 2, "RAM error"},               // Thunderbolt
629
    {4, 4, "FPGA error"},              // Thunderbolt
630
    {8, 8, "Power error"},             // Thunderbolt
631
    {0x10, 0x10, "OSC error"},         // Thunderbolt
632
    {0, 0, NULL},
633
};
634
635
/* Minor Alarm Flags
636
 * Used in x8f-ac */
637
static struct flist_t vminor_alarms[] = {
638
    {1, 1, "OSC warning"},                   // Thunderbolt
639
    {2, 2, "Ant Open"},
640
    {4, 4, "Ant Short"},
641
    {8, 8, "Not tracking Sats"},
642
    {0x10, 0x10, "Osc unlocked"},            // Thunderbolt
643
    {0x20, 0x20, "Survey in progress"},
644
    {0x40, 0x40, "No stored Position"},
645
    {0x80, 0x80, "Leap Sec Pending"},
646
    {0x100, 0x100, "Test Mode"},
647
    {0x200, 0x200, "Position questionable"},
648
    {0x400, 0x400, "EEROM corrupt"},         // Thunderbolt
649
    {0x800, 0x800, "Almanac Incomplete"},
650
    {0x1000, 0x1000, "PPS generated"},
651
    {0, 0, NULL},
652
};
653
654
/* convert TSIP SV Type to satellite_t.gnssid and satellite_t.svid
655
 * return gnssid directly, svid indirectly through pointer */
656
static unsigned char tsip_gnssid(unsigned svtype, short prn,
657
                                 unsigned char *svid)
658
1.63k
{
659
    // initialized to shut up clang
660
1.63k
    unsigned char gnssid = 0;
661
662
1.63k
    *svid = 0;
663
664
1.63k
    switch (svtype) {
665
1.29k
    case 0:
666
1.29k
        if (0 < prn && 33 > prn) {
667
112
            gnssid = GNSSID_GPS;
668
112
            *svid = prn;
669
1.17k
        } else if (32 < prn && 55 > prn) {
670
            // RES SMT 360 and ICM SMT 360 put SBAS in 33-54
671
74
            gnssid = GNSSID_SBAS;
672
74
            *svid = prn + 87;
673
1.10k
        } else if (64 < prn && 97 > prn) {
674
            // RES SMT 360 and ICM SMT 360 put GLONASS in 65-96
675
94
            gnssid = GNSSID_GLO;
676
94
            *svid = prn - 64;
677
1.01k
        } else if (96 < prn && 134 > prn) {
678
            // RES SMT 360 and ICM SMT 360 put Galileo in 97-133
679
128
            gnssid = GNSSID_GAL;
680
128
            *svid = prn - 96;
681
882
        } else if (119 < prn && 139 > prn) {
682
            // Copernicus (II) put SBAS in 120-138
683
71
            gnssid = GNSSID_SBAS;
684
71
            *svid = prn + 87;
685
811
        } else if (183 == prn) {
686
68
            gnssid = GNSSID_QZSS;
687
68
            *svid = 1;
688
743
        } else if (192 <= prn && 193 >= prn) {
689
101
            gnssid = GNSSID_QZSS;
690
101
            *svid = prn - 190;
691
642
        } else if (200 == prn) {
692
100
            gnssid = GNSSID_QZSS;
693
100
            *svid = 4;
694
542
        } else if (200 < prn && 238 > prn) {
695
            // BeidDou in 201-237
696
86
            gnssid = GNSSID_BD;
697
86
            *svid = prn - 200;
698
86
        }
699
        // else: huh?
700
1.29k
        break;
701
35
    case 1:
702
35
        gnssid = GNSSID_GLO;  // GLONASS
703
35
        *svid = prn - 64;
704
35
        break;
705
34
    case 2:
706
34
        gnssid = GNSSID_BD;  // BeiDou
707
34
        *svid = prn - 200;
708
34
        break;
709
34
    case 3:
710
34
        gnssid = GNSSID_GAL;  // Galileo
711
34
        *svid = prn - 96;
712
34
        break;
713
173
    case 5:
714
173
        gnssid = GNSSID_QZSS;  // QZSS
715
173
        switch (prn) {
716
34
        case 183:
717
34
            *svid = 1;
718
34
            break;
719
34
        case 192:
720
34
            *svid = 2;
721
34
            break;
722
34
        case 193:
723
34
            *svid = 3;
724
34
            break;
725
34
        case 200:
726
34
            *svid = 4;
727
34
            break;
728
37
        default:
729
37
            *svid = prn;
730
37
            break;
731
173
        }
732
173
        break;
733
173
    case 4:
734
0
        FALLTHROUGH
735
0
    case 6:
736
0
        FALLTHROUGH
737
0
    case 7:
738
0
        FALLTHROUGH
739
65
    default:
740
65
        *svid = 0;
741
65
        gnssid = 0;
742
65
        break;
743
1.63k
    }
744
1.63k
    return gnssid;
745
1.63k
}
746
747
/* tsip1_checksum()
748
 * compute TSIP version 1 checksum
749
 *
750
 * Return: checksum
751
 */
752
static char tsip1_checksum(const char *buf, size_t len)
753
496
{
754
496
    char checksum = 0;
755
496
    size_t index;
756
757
3.43k
    for(index = 0; index < len; index++) {
758
2.94k
        checksum ^= buf[index];
759
2.94k
    }
760
496
    return checksum;
761
496
}
762
763
/* tsip_write1() - send old style TSIP message, improved tsip_write()
764
 * buf - the packet
765
 * len - length of buf
766
 *
767
 * Adds leading DLE, and the trailing DLE, ETX
768
 *
769
 * Return: 0 == OK
770
 *         -1 == write fail
771
 */
772
static ssize_t tsip_write1(struct gps_device_t *session,
773
                           char *buf, size_t len)
774
37.4k
{
775
37.4k
    char *ep, *cp;
776
37.4k
    char obuf[100];
777
37.4k
    size_t olen = len;
778
779
37.4k
    if (session->context->readonly) {
780
17.0k
        return 0;
781
17.0k
    }
782
20.3k
    if ((NULL == buf) ||
783
20.3k
        0 == len ||
784
20.3k
        (sizeof(session->msgbuf) / 2) < len) {
785
        // could over run, do not chance it
786
0
        return -1;
787
0
    }
788
20.3k
    session->msgbuf[0] = '\x10';
789
20.3k
    ep = session->msgbuf + 1;
790
61.6k
    for (cp = buf; olen-- > 0; cp++) {
791
41.2k
        if ('\x10' == *cp) {
792
0
            *ep++ = '\x10';
793
0
        }
794
41.2k
        *ep++ = *cp;
795
41.2k
    }
796
20.3k
    *ep++ = '\x10';
797
20.3k
    *ep++ = '\x03';
798
20.3k
    session->msgbuflen = (size_t)(ep - session->msgbuf);
799
    // Don't bore the user with the header (DLE) or trailer (DLE, STX).
800
20.3k
    GPSD_LOG(LOG_PROG, &session->context->errout,
801
20.3k
             "TSIP: tsip_write1(0x%s)\n",
802
20.3k
             gps_hexdump(obuf, sizeof(obuf),
803
20.3k
                         (unsigned char *)&session->msgbuf[1], len));
804
20.3k
    if (gpsd_write(session, session->msgbuf, session->msgbuflen) !=
805
20.3k
        (ssize_t) session->msgbuflen)
806
20.3k
        return -1;
807
808
0
    return 0;
809
20.3k
}
810
811
/* tsip_detect()
812
 *
813
 * see if it looks like a TSIP device (speaking 9600O81) is listening and
814
 * return 1 if found, 0 if not
815
 */
816
static bool tsip_detect(struct gps_device_t *session)
817
0
{
818
0
    bool ret = false;
819
0
    int myfd;
820
0
    speed_t old_baudrate;
821
0
    char old_parity;
822
0
    unsigned int old_stopbits;
823
0
    bool override = true;
824
825
0
    if ((speed_t)0 == session->context->fixed_port_speed &&
826
0
        '\0' == session->context->fixed_port_framing[0]) {
827
        // Only try 9600 8O1 is no speed or framing override
828
0
        old_baudrate = session->gpsdata.dev.baudrate;
829
0
        old_parity = session->gpsdata.dev.parity;
830
0
        old_stopbits = session->gpsdata.dev.stopbits;
831
0
        gpsd_set_speed(session, 9600, 'O', 1);
832
0
        override = false;
833
0
    }
834
835
    /* request firmware revision and look for a valid response
836
     * send 0x1f, expect 0x45.  TSIPv1 does not have this, but it
837
     * will respond with a TSIPv1 error message, so all good. */
838
0
    if (0 == tsip_write1(session, "\x1f", 1)) {
839
0
        unsigned int n;
840
0
        struct timespec to;
841
842
0
        myfd = session->gpsdata.gps_fd;
843
844
        // FIXME: this holds the main loop from running...
845
0
        for (n = 0; n < 3; n++) {
846
            // wait 100 milli second
847
0
            to.tv_sec = 0;
848
0
            to.tv_nsec = 100000000;
849
0
            if (!nanowait(myfd, &to)) {
850
0
                break;
851
0
            }
852
0
            if (0 <= packet_get1(session)) {
853
0
                if (TSIP_PACKET == session->lexer.type) {
854
0
                    GPSD_LOG(LOG_RAW, &session->context->errout,
855
0
                             "TSIP: tsip_detect found\n");
856
0
                    ret = true;
857
0
                    break;
858
0
                }
859
0
            }
860
0
        }
861
0
    }
862
863
0
    if (!ret &&
864
0
        !override) {
865
        // return serial port to original settings
866
0
        gpsd_set_speed(session, old_baudrate, old_parity, old_stopbits);
867
0
    }
868
869
0
    return ret;
870
0
}
871
872
// configure generic Trimble TSIP device to a known state
873
static void configuration_packets_generic(struct gps_device_t *session)
874
598
{
875
598
        char buf[100];
876
877
598
        GPSD_LOG(LOG_PROG, &session->context->errout,
878
598
                 "TSIP: configuration_packets_generic()\n");
879
880
        // Set basic configuration, using Set or Request I/O Options (0x35).
881
        // Position: enable: Double Precision, LLA, disable: ECEF
882
598
        buf[0] = 0x35;
883
        // Time: enable: 0x42, 0x43, 0x4a, disable: 0x83, 0x84, 0x56
884
598
        buf[1] = IO1_8F20|IO1_DP|IO1_LLA;
885
        // Velocity: enable: ENU, disable ECEF
886
598
        buf[2] = IO2_ENU;
887
598
        buf[3] = 0x00;
888
598
        buf[4] = IO4_DBHZ;    // Aux: enable: 0x5A, dBHz
889
598
        (void)tsip_write1(session, buf, 5);
890
891
        // Request Software Version (0x1f), returns 0x45
892
598
        (void)tsip_write1(session, "\x1f", 1);
893
894
        // Current Time Request (0x21), returns 0x41
895
598
        (void)tsip_write1(session, "\x21", 1);
896
897
        /* Set Operating Parameters (0x2c)
898
         * not present in:
899
         *   Lassen SQ (2002)
900
         *   Lassen iQ (2005)
901
         *   RES SMT 360 */
902
        /* dynamics code: enabled: 1=land
903
         *   disabled: 2=sea, 3=air, 4=static
904
         *   default is land */
905
598
        buf[0] = 0x2c;
906
598
        buf[1] = 0x01;
907
        // elevation mask, 10 degrees is a common default, TSIP default is 15
908
598
        putbef32(buf, 2, (float)10.0 * DEG_2_RAD);
909
        // signal level mask, default is 2.0 AMU. 5.0 to 6.0 for high accuracy
910
598
        putbef32(buf, 6, (float)06.0);
911
        // PDOP mask default is 12. 5.0 to 6.0 for high accuracy
912
598
        putbef32(buf, 10, (float)8.0);
913
        // PDOP switch, default is 8.0
914
598
        putbef32(buf, 14, (float)6.0);
915
598
        (void)tsip_write1(session, buf, 18);
916
917
        /* Set Position Fix Mode (0x22)
918
         * 0=auto 2D/3D, 1=time only, 3=2D, 4=3D, 10=Overdetermined clock */
919
598
        (void)tsip_write1(session, "\x22\x00", 2);
920
921
        /* Request GPS System Message (0x48)
922
         * not supported on model RES SMT 360 */
923
598
        (void)tsip_write1(session, "\x28", 1);
924
925
        /* Last Position and Velocity Request (0x37)
926
         * returns 0x57 and (0x42, 0x4a, 0x83, or 0x84) and (0x43 or 0x56)  */
927
598
        (void)tsip_write1(session, "\x37", 1);
928
929
        // 0x8e-15 request output datum
930
598
        (void)tsip_write1(session, "\x8e\x15", 2);
931
932
        /* Primary Receiver Configuration Parameters Request (0xbb-00)
933
         * returns  Primary Receiver Configuration Block (0xbb-00) */
934
598
        (void)tsip_write1(session, "\xbb\x00", 2);
935
598
}
936
937
// configure Acutime Gold to a known state
938
static void configuration_packets_acutime_gold(struct gps_device_t *session)
939
135
{
940
135
        char buf[100];
941
942
135
        GPSD_LOG(LOG_PROG, &session->context->errout,
943
135
                 "TSIP: configuration_packets_acutime_gold()\n");
944
945
        /* Request Firmware Version (0x1c-01)
946
         * returns Firmware component version information (0x1x-81) */
947
135
        (void)tsip_write1(session, "\x1c\x01", 2);
948
949
135
        buf[0] = 0x8e;          // Set Self-Survey Parameters (0x8e-a9)
950
135
        buf[1] = 0xa9;          // Subcode
951
135
        buf[2] = 0x01;          // Self-Survey Enable = enable
952
135
        buf[3] = 0x01;          // Position Save Flag = save position
953
135
        putbe32(buf, 4, 2000);  // Self-Survey Length = 2000 fixes, default 2000
954
        // Horizontal Uncertainty, 1-100, 1=best, 100=worst, default 100
955
135
        putbef32(buf, 8, 100);
956
        // Vertical Uncertainty, 1-100, 1=best, 100=worst, default 100
957
135
        putbef32(buf, 12, 100);
958
135
        (void)tsip_write1(session, buf, 16);
959
960
        /* Set PPS Output Option (0x8e-4e)
961
         * 0x4e Subcode
962
         * 2 == PPS driver switch (PPS is always output) */
963
135
        (void)tsip_write1(session, "\x8e\x4e\x02", 3);
964
965
135
        buf[0] = 0xbb;  // Set Primary Receiver Configuration (0xbb-00)
966
135
        buf[1] = 0x00;  // 00 =  Subcode
967
135
        buf[2] = 0x07;  // Receiver mode, 7 = Force Overdetermined clock
968
135
        buf[3] = 0xff;  // Not enabled = unchanged, must be 0xff on RES SMT 360
969
135
        buf[4] = 0x01;  // Dynamics code = default must be 0xff on RES SMT 360
970
135
        buf[5] = 0x01;  // Solution Mode = default must be 0xff on RES SMT 360
971
        // Elevation Mask = 10 deg
972
135
        putbef32((char *)buf, 6, (float)10.0 * DEG_2_RAD);
973
        // AMU Mask. 0 to 55. default is 4.0
974
135
        putbef32((char *)buf, 10, (float)4.0);
975
        // PDOP Mask = 8.0, default = 6
976
135
        putbef32((char *)buf, 14, (float)8.0);
977
        // PDOP Switch = 6.0, ignored in RES SMT 360
978
135
        putbef32((char *)buf, 18, (float)6.0);
979
135
        buf[22] = 0xff;  // must be 0xff
980
135
        buf[23] = 0x0;   // Anti-Jam Mode, 0=Off, 1=On
981
135
        putbe16(buf, 24, 0xffff);  // Reserved.  Must be 0xffff
982
        /* Measurement Rate and Position Fix Rate = default
983
         * must be 0xffff on res smt 360 */
984
135
        putbe16(buf, 26, 0x0000);
985
        /* 27 is Constellation on RES SMT 360.
986
         * 1 = GPS, 2=GLONASS, 8=BeiDou, 0x10=Galileo, 5=QZSS */
987
135
        putbe32(buf, 28, 0xffffffff);   // Reserved
988
135
        putbe32(buf, 32, 0xffffffff);   // Reserved
989
135
        putbe32(buf, 36, 0xffffffff);   // Reserved
990
135
        putbe32(buf, 40, 0xffffffff);   // Reserved
991
135
        (void)tsip_write1(session, buf, 44);
992
993
135
        buf[0] = 0x8e;   // Set Packet Broadcast Mask (0x8e-a5)
994
135
        buf[1] = 0xa5;   // Subcode a5
995
        /* Packets bit field = default + Primary timing,
996
         *  Supplemental timing 32e1
997
         *  1=0x8f-ab, 4=0x8f-ac, 0x40=Automatic Output Packets */
998
135
        putbe16(buf, 2, 0x32e1);
999
135
        buf[4] = 0x00;   // not used
1000
135
        buf[5] = 0x00;   // not used
1001
135
        (void)tsip_write1(session, buf, 6);
1002
135
}
1003
1004
// configure RES 360, Resolution SMTx, and similar to a known state
1005
static void configuration_packets_res360(struct gps_device_t *session)
1006
531
{
1007
531
    char buf[100];
1008
1009
531
    GPSD_LOG(LOG_PROG, &session->context->errout,
1010
531
             "TSIP: configuration_packets_res360()\n");
1011
1012
    // should already have versions 0x8f-81 and 0x8f-83.
1013
1014
    // Request Self Survey Parameters (0x8e-a9)
1015
531
    (void)tsip_write1(session, "\x8e\xa9", 2);
1016
1017
531
    if (session->context->passive) {
1018
        // request I/O Options (0x55)
1019
300
        (void)tsip_write1(session, "\x35", 1);
1020
1021
        // request Receiver Configuration (0xbb)
1022
300
        (void)tsip_write1(session, "\xbb\x00", 2);
1023
1024
        // Request Packet Broadcast Mask (0x8e-a5)
1025
300
        (void)tsip_write1(session, "\x8e\xa5", 2);
1026
1027
300
    } else {
1028
        // PPS Output Option (0x8e-4e) is default on
1029
1030
231
        buf[0] = 0x8e;  // Set Packet Broadcast Mask (0x8e-a5)
1031
231
        buf[1] = 0xa5;  // a5 = Subcode
1032
        /* Packets bit field = default + Auto output packets
1033
         *  1=0x8f-ab, 4=0x8f-ac, 0x40=Automatic Output Packets */
1034
231
        buf[2] = 0;        // reserved
1035
231
        buf[3] = 0x45;
1036
231
        buf[4] = 0;        // reserved
1037
231
        buf[5] = 0;        // reserved
1038
231
        (void)tsip_write1(session, buf, 6);
1039
1040
        /* IO Options defaults:
1041
         *   Lassen iQ:       02 02 00 00
1042
         *   RES SMT 360:     12 02 00 08
1043
         *   Resolution SMTx: 12 02 00 08
1044
         */
1045
231
        buf[0] = 0x35;  // set I/O Options
1046
        // position and velocity only sent during self-survey.
1047
        // Position
1048
231
        buf[1] =  IO1_DP|IO1_LLA|IO1_ECEF;
1049
        // Velocity
1050
231
        buf[2] = IO2_VECEF|IO2_ENU;
1051
        // Timing
1052
231
        buf[3] = 0x01;          // Use 0x8e-a2
1053
        // Auxiliary
1054
231
        buf[4] = 0x08;         // Packet 0x5a off, dBHz
1055
231
        (void)tsip_write1(session, buf, 5);
1056
1057
#ifdef __UNUSED__
1058
// #if 1
1059
        // Restart Self-Survey (0x8e-a6)
1060
        // which gives us 2,000 normal fixes, before going quiet again.
1061
        (void)tsip_write1(session, "\x8e\xa6\x00", 3);
1062
#endif // __UNUSED__
1063
231
    }
1064
531
}
1065
1066
/* send the next TSIPv1 query
1067
 * Return: void
1068
 */
1069
static void tsipv1_query(struct gps_device_t *session)
1070
3.41k
{
1071
3.41k
    char snd_buf[24];         // send buffer
1072
1073
    // advance to next queue item.
1074
3.41k
    session->queue++;
1075
    // allow it to repeat every x1000 packets
1076
3.41k
    session->queue &= 0x0ffff;
1077
1078
3.41k
    if (0 != (session->queue % 4)) {
1079
        // once every 4 messages
1080
2.56k
        return;
1081
2.56k
    }
1082
858
    switch (session->queue / 4) {
1083
105
    case 1:
1084
        // x90-00, query protocol version
1085
105
        snd_buf[0] = 0x90;             // id
1086
105
        snd_buf[1] = 0x00;             // sub id
1087
105
        putbe16(snd_buf, 2, 2);        // length
1088
105
        snd_buf[4] = 0;                // mode: query
1089
105
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1090
105
        (void)tsip_write1(session, snd_buf, 6);
1091
105
        break;
1092
97
    case 2:
1093
        // x90-01, query GNSS config version
1094
97
        snd_buf[0] = 0x90;             // id
1095
97
        snd_buf[1] = 0x01;             // sub id
1096
97
        putbe16(snd_buf, 2, 2);        // length
1097
97
        snd_buf[4] = 0;                // mode: query
1098
97
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1099
97
        (void)tsip_write1(session, snd_buf, 6);
1100
97
        break;
1101
67
    case 3:
1102
        // x91-00, Port config
1103
67
        snd_buf[0] = 0x91;             // id
1104
67
        snd_buf[1] = 0x00;             // sub id
1105
67
        putbe16(snd_buf, 2, 3);        // length
1106
67
        snd_buf[4] = 0;                // mode: query
1107
67
        snd_buf[5] = 0;                // current port
1108
67
        snd_buf[6] = tsip1_checksum(snd_buf, 6);   // checksum
1109
67
        (void)tsip_write1(session, snd_buf, 7);
1110
67
        break;
1111
52
    case 4:
1112
        // x81-01, GNSS config
1113
52
        snd_buf[0] = 0x91;             // id
1114
52
        snd_buf[1] = 0x01;             // sub id
1115
52
        putbe16(snd_buf, 2, 2);        // length
1116
52
        snd_buf[4] = 0;                // mode: query
1117
52
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1118
52
        (void)tsip_write1(session, snd_buf, 6);
1119
52
        break;
1120
47
    case 5:
1121
        // x91-03, query timing config
1122
47
        snd_buf[0] = 0x91;             // id
1123
47
        snd_buf[1] = 0x03;             // sub id
1124
47
        putbe16(snd_buf, 2, 2);        // length
1125
47
        snd_buf[4] = 0;                // mode: query
1126
47
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1127
47
        (void)tsip_write1(session, snd_buf, 6);
1128
47
        break;
1129
45
    case 6:
1130
        // x91-04, self survey config
1131
45
        snd_buf[0] = 0x91;             // id
1132
45
        snd_buf[1] = 0x04;             // sub id
1133
45
        putbe16(snd_buf, 2, 2);        // length
1134
45
        snd_buf[4] = 0;                // mode: query
1135
45
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1136
45
        (void)tsip_write1(session, snd_buf, 6);
1137
45
        break;
1138
43
    case 7:
1139
43
        if (session->context->passive) {
1140
            // x91-05, query current periodic messages
1141
21
            snd_buf[0] = 0x91;             // id
1142
21
            snd_buf[1] = 0x05;             // sub id
1143
21
            putbe16(snd_buf, 2, 3);        // length
1144
21
            snd_buf[4] = 0;                // mode: query
1145
21
            snd_buf[5] = 0xff;             // port: current port
1146
21
            snd_buf[6] = tsip1_checksum(snd_buf, 6);   // checksum
1147
21
            (void)tsip_write1(session, snd_buf, 7);
1148
22
        } else {
1149
            /* request periodic  messages, x91-05
1150
             * little harm at 115.2 kbps, this also responses as a query */
1151
22
            snd_buf[0] = 0x91;             // id
1152
22
            snd_buf[1] = 0x05;             // sub id
1153
22
            putbe16(snd_buf, 2, 19);       // length
1154
22
            snd_buf[4] = 0x01;             // mode: set
1155
22
            snd_buf[5] = 0xff;             // port: current port
1156
            // 0xaaaaa, everything preiodic
1157
22
            putbe32(snd_buf, 6, 0xaaaaa);
1158
22
            putbe32(snd_buf, 10, 0);       // reserved
1159
22
            putbe32(snd_buf, 14, 0);       // reserved
1160
22
            putbe32(snd_buf, 18, 0);       // reserved
1161
22
            snd_buf[22] = tsip1_checksum(snd_buf, 22);   // checksum
1162
22
            (void)tsip_write1(session, snd_buf, 23);
1163
22
        }
1164
43
        break;
1165
40
    case 8:
1166
        // x93-00, production info
1167
40
        snd_buf[0] = 0x93;             // id
1168
40
        snd_buf[1] = 0x00;             // sub id
1169
40
        putbe16(snd_buf, 2, 2);        // length
1170
40
        snd_buf[4] = 0;                // mode: query
1171
40
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1172
40
        (void)tsip_write1(session, snd_buf, 6);
1173
40
        break;
1174
362
    default:
1175
        // nothing to do
1176
362
        break;
1177
858
    }
1178
858
}
1179
1180
/* tsipv1_svtype()
1181
 * convert TSIPv1 SV Type to satellite_t.gnssid and satellite_t.sigid
1182
 * PRN is already GNSS specific (1-99)
1183
 * return gnssid directly, sigid indirectly through pointer
1184
 *
1185
 * Return: gnssid
1186
 *         0xff on error
1187
 */
1188
static unsigned char tsipv1_svtype(unsigned svtype, unsigned char *sigid)
1189
304
{
1190
1191
304
    unsigned char gnssid;
1192
1193
304
    switch (svtype) {
1194
18
    case 1:  // GPS L1C
1195
18
       gnssid =  GNSSID_GPS;
1196
18
       *sigid = 0;
1197
18
       break;
1198
25
    case 2:  // GPS L2.  CL or CM?
1199
25
       gnssid =  GNSSID_GPS;
1200
25
       *sigid = 3;         // or, maybe 4
1201
25
       break;
1202
7
    case 3:  // GPS L5.  I or Q?
1203
7
       gnssid =  GNSSID_GPS;
1204
7
       *sigid = 6;         // or maybe 7
1205
7
       break;
1206
36
    case 5:  // GLONASS G1
1207
36
       gnssid =  GNSSID_GLO;
1208
36
       *sigid = 0;
1209
36
       break;
1210
9
    case 6:  // GLONASS G2
1211
9
       gnssid =  GNSSID_GLO;
1212
9
       *sigid = 2;
1213
9
       break;
1214
10
    case 9:  // SBAS, assume L1
1215
10
       gnssid =  GNSSID_SBAS;
1216
10
       *sigid = 0;
1217
10
       break;
1218
34
    case 13:  // Beidou B1, D1 or D2?
1219
34
       gnssid =  GNSSID_BD;
1220
34
       *sigid = 0;   // or maybe 1
1221
34
       break;
1222
1
    case 14:  // Beidou B2i
1223
1
       gnssid =  GNSSID_BD;
1224
1
       *sigid = 2;
1225
1
       break;
1226
1
    case 15:  // Beidou B2a
1227
1
       gnssid =  GNSSID_BD;
1228
1
       *sigid = 3;
1229
1
       break;
1230
1
    case 17:  // Galileo E1, C or B?
1231
1
       gnssid =  GNSSID_GAL;
1232
1
       *sigid = 0;    // or maybe 1
1233
1
       break;
1234
1
    case 18:  // Galileo E5a, aI or aQ?
1235
1
       gnssid =  GNSSID_GAL;
1236
1
       *sigid = 3;    // or maybe 4?
1237
1
       break;
1238
2
    case 19:  // Galileo E5b, bI or bQ?
1239
2
       gnssid =  GNSSID_GAL;
1240
2
       *sigid = 5;    // or maybe 6
1241
2
       break;
1242
3
    case 20:  // Galileo E6
1243
3
       gnssid =  GNSSID_GAL;
1244
3
       *sigid = 8;     // no idea
1245
3
       break;
1246
10
    case 22:  // QZSS L1
1247
10
       gnssid =  GNSSID_QZSS;
1248
10
       *sigid = 0;
1249
10
       break;
1250
36
    case 23:  // QZSS L2C
1251
36
       gnssid =  GNSSID_QZSS;
1252
36
       *sigid = 4;    // or maybe 5
1253
36
       break;
1254
28
    case 24:  // QZSS L5
1255
28
       gnssid =  GNSSID_QZSS;
1256
28
       *sigid = 8;     // no idea
1257
28
       break;
1258
16
    case 26:  // IRNSS L5
1259
16
       gnssid =  GNSSID_IRNSS;
1260
16
       *sigid = 8;     // no idea
1261
16
       break;
1262
0
    case 4:  // Reserved
1263
0
        FALLTHROUGH
1264
0
    case 7:  // Reserved
1265
0
        FALLTHROUGH
1266
0
    case 8:  // Reserved
1267
0
        FALLTHROUGH
1268
0
    case 10:  // Reservced
1269
0
        FALLTHROUGH
1270
0
    case 11:  // Reservced
1271
0
        FALLTHROUGH
1272
0
    case 12:  // Reservced
1273
0
        FALLTHROUGH
1274
0
    case 16:  // Reserved
1275
0
        FALLTHROUGH
1276
0
    case 21:  // Reserved
1277
0
        FALLTHROUGH
1278
0
    case 25:  // Reserved
1279
0
        FALLTHROUGH
1280
66
    default:
1281
66
        *sigid = 0xff;
1282
66
        return 0xff;
1283
304
    }
1284
238
    return gnssid;
1285
304
}
1286
1287
// decode Packet x13
1288
static gps_mask_t decode_x13(struct gps_device_t *session, const char *buf,
1289
                             unsigned len)
1290
233
{
1291
233
    gps_mask_t mask = 0;
1292
233
    unsigned u1 = getub(buf, 0);         // Packet ID of non-parsable packet
1293
233
    unsigned u2 = 0;
1294
1295
233
    if (2 <= len) {
1296
83
        u2 = getub(buf, 1);     // Data byte 0 of non-parsable packet
1297
83
    }
1298
233
    GPSD_LOG(LOG_WARN, &session->context->errout,
1299
233
             "TSIP x13: Report Packet: request x%02x %02x "
1300
233
             "cannot be parsed\n",
1301
233
             u1, u2);
1302
    // ignore the rest of the bad data
1303
233
    if (0x8e == (int)u1 &&
1304
140
        0x23 == (int)u2) {
1305
        // no Compact Super Packet 0x8e-23
1306
68
        GPSD_LOG(LOG_WARN, &session->context->errout,
1307
68
                 "TSIP x8e-23: not available, use LFwEI (0x8f-20)\n");
1308
1309
        /* Request LFwEI Super Packet instead
1310
         * SMT 360 does not support 0x8e-20 either */
1311
68
        (void)tsip_write1(session, "\x8e\x20\x01", 3);
1312
68
    }
1313
233
    return mask;
1314
233
}
1315
// decode Superpacket x1c-81
1316
static gps_mask_t decode_x1c_81(struct gps_device_t *session, const char *buf,
1317
                                unsigned len)
1318
153
{
1319
153
    gps_mask_t mask = 0;
1320
153
    char buf2[BUFSIZ];
1321
1322
    // byte 1, reserved
1323
153
    unsigned maj = getub(buf, 2);        // Major version
1324
153
    unsigned min = getub(buf, 3);        // Minor version
1325
153
    unsigned bnum = getub(buf, 4);       // Build number
1326
153
    unsigned bmon = getub(buf, 5);       // Build Month
1327
153
    unsigned bday = getub(buf, 6);       // Build Day
1328
153
    unsigned byr = getbeu16(buf, 7);     // Build Year
1329
153
    unsigned plen = getub(buf, 9);       // Length of product name
1330
1331
    // check for valid module name length
1332
153
    if (40 < plen) {
1333
75
        plen = 40;
1334
75
    }
1335
    // check for valid module name length, again
1336
153
    if ((unsigned)(len - 10) < plen) {
1337
74
        plen = len - 10;
1338
74
    }
1339
    // Product name in ASCII
1340
153
    memcpy(buf2, &buf[10], plen);
1341
153
    buf2[plen] = '\0';
1342
1343
153
    (void)snprintf(session->subtype, sizeof(session->subtype),
1344
153
                   "fw %u.%u %u %02u/%02u/%04u %.40s",
1345
153
                   min, maj, bnum, bmon, bday, byr, buf2);
1346
153
    GPSD_LOG(LOG_PROG, &session->context->errout,
1347
153
             "TSIP x1c-81: Firmware version: %s\n",
1348
153
             session->subtype);
1349
1350
153
    mask |= DEVICEID_SET;
1351
153
    if ('\0' == session->subtype1[0]) {
1352
        // request actual subtype1 from 0x1c-83
1353
20
        (void)tsip_write1(session, "\x1c\x03", 2);
1354
20
    }
1355
153
    return mask;
1356
153
}
1357
1358
// decode Superpacket x1c-83
1359
static gps_mask_t decode_x1c_83(struct gps_device_t *session, const char *buf,
1360
                                unsigned len)
1361
1.26k
{
1362
1.26k
    gps_mask_t mask = 0;
1363
1.26k
    char buf2[BUFSIZ];
1364
1.26k
    unsigned long ul1 = getbeu32(buf, 1);  // Serial number
1365
1.26k
    unsigned bday = getub(buf, 5);         // Build day
1366
1.26k
    unsigned bmon = getub(buf, 6);         // Build month
1367
1.26k
    unsigned byr = getbeu16(buf, 7);       // Build year
1368
1.26k
    unsigned u4 = getub(buf, 9);           // Build hour
1369
1.26k
    unsigned u5 = getub(buf, 12);          // Length of Hardware ID
1370
1371
    // Hardware Code
1372
1.26k
    session->driver.tsip.hardware_code = getbeu16(buf, 10);
1373
1374
    // check for valid module name length
1375
    // copernicus ii is 27 long
1376
1.26k
    if (40 < u5) {
1377
719
        u5 = 40;
1378
719
    }
1379
    // check for valid module name length, again
1380
1.26k
    if ((unsigned)(len - 13) < u5) {
1381
904
        u5 = len - 13;
1382
904
    }
1383
1.26k
    memcpy(buf2, &buf[13], u5);
1384
1.26k
    buf2[u5] = '\0';
1385
1386
1.26k
    (void)snprintf(session->gpsdata.dev.sernum,
1387
1.26k
                   sizeof(session->gpsdata.dev.sernum),
1388
1.26k
                   "%lx", ul1);
1389
1.26k
    (void)snprintf(session->subtype1, sizeof(session->subtype1),
1390
1.26k
                   "hw %02u/%02u/%04u %02u %04u %.40s",
1391
1.26k
                   bmon, bday, byr, u4,
1392
1.26k
                   session->driver.tsip.hardware_code,
1393
1.26k
                   buf2);
1394
1.26k
    GPSD_LOG(LOG_PROG, &session->context->errout,
1395
1.26k
             "TSIP x1c-83: Hardware vers %s Sernum %s\n",
1396
1.26k
             session->subtype1,
1397
1.26k
             session->gpsdata.dev.sernum);
1398
1399
1.26k
    mask |= DEVICEID_SET;
1400
1.26k
    session->driver.tsip.subtype =
1401
1.26k
        session->driver.tsip.hardware_code;
1402
1403
    // Detecting device by Hardware Code
1404
1.26k
    switch (session->driver.tsip.hardware_code) {
1405
135
    case 3001:            // Acutime Gold
1406
135
        configuration_packets_acutime_gold(session);
1407
135
        break;
1408
1409
    // RES look-alikes
1410
66
    case 3002:            // TSIP_REST
1411
66
        FALLTHROUGH
1412
170
    case 3009:            // TSIP_RESSMT, Model 66266
1413
170
        FALLTHROUGH
1414
240
    case 3017:            // Resolution SMTx,  Model 99889
1415
240
        FALLTHROUGH
1416
306
    case 3023:            // RES SMT 360
1417
306
        FALLTHROUGH
1418
372
    case 3026:            // ICM SMT 360
1419
372
        FALLTHROUGH
1420
465
    case 3031:            // RES360 17x22
1421
465
        FALLTHROUGH
1422
531
    case 3100:            // TSIP_RES720
1423
531
        configuration_packets_res360(session);
1424
531
        break;
1425
1426
    // Unknown
1427
258
    default:
1428
258
        GPSD_LOG(LOG_WARN, &session->context->errout,
1429
258
                 "TSIP x1c-83: Unknown hw code %x\n",
1430
258
                 session->driver.tsip.hardware_code);
1431
258
        FALLTHROUGH
1432
324
    case 1001:            // Lassen iQ
1433
324
        FALLTHROUGH
1434
390
    case 1002:            // Copernicus
1435
390
        FALLTHROUGH
1436
456
    case 1003:            // Copernicus II
1437
456
        FALLTHROUGH
1438
522
    case 3007:            // Thunderbolt E
1439
522
        FALLTHROUGH
1440
598
    case 3032:            // Acutime 360
1441
598
        configuration_packets_generic(session);
1442
598
        break;
1443
1.26k
    }
1444
1.26k
    return mask;
1445
1.26k
}
1446
1447
// decode Superpackets x1c-XX
1448
static gps_mask_t decode_x1c(struct gps_device_t *session, const char *buf,
1449
                             unsigned len, int *pbad_len)
1450
1.64k
{
1451
1.64k
    gps_mask_t mask = 0;
1452
1.64k
    int bad_len = 0;
1453
1.64k
    unsigned u1 = getub(buf, 0);
1454
1455
    // decode by sub-code
1456
1.64k
    switch (u1) {
1457
220
    case 0x81:
1458
        /* Firmware component version information (0x1c-81)
1459
         * polled by 0x1c-01
1460
         * Present in:
1461
         *   Copernicus II (2009)
1462
         */
1463
220
        if (10 > len) {
1464
67
            bad_len = 10;
1465
67
            break;
1466
67
        }
1467
153
        mask = decode_x1c_81(session, buf, len);
1468
153
        break;
1469
1470
1.34k
    case 0x83:
1471
        /* Hardware component version information (0x1c-83)
1472
         * polled by 0x1c-03
1473
         * Present in:
1474
         *   Resolution SMTx
1475
         * Not Present in:
1476
         *   LassenSQ (2002)
1477
         *   Copernicus II (2009)
1478
         */
1479
1.34k
        if (13 > len) {
1480
76
            bad_len = 13;
1481
76
            break;
1482
76
        }
1483
1.26k
        mask = decode_x1c_83(session, buf, len);
1484
1.26k
        break;
1485
80
    default:
1486
80
        GPSD_LOG(LOG_WARN, &session->context->errout,
1487
80
                 "TSIP x1c-%02x: Unhandled subpacket\n", u1);
1488
80
        break;
1489
1.64k
    }
1490
1.64k
    *pbad_len = bad_len;
1491
    // request x8f-42 Stored Production Parameters
1492
1.64k
    (void)tsip_write1(session, "\x8e\x42", 2);
1493
1.64k
    return mask;
1494
1.64k
}
1495
1496
/* decode GPS Time, Packet x41
1497
 * This is "current" time, not the time of a fix */
1498
static gps_mask_t decode_x41(struct gps_device_t *session, const char *buf)
1499
316
{
1500
316
    gps_mask_t mask = 0;
1501
316
    timespec_t ts_tow;
1502
316
    char ts_buf[TIMESPEC_LEN];
1503
316
    double ftow = getbef32(buf, 0);                // gpstime
1504
316
    unsigned week = getbes16(buf, 4);              // week, yes, signed!
1505
316
    double f2 = getbef32(buf, 6);                  // leap seconds, fractional!
1506
1507
316
    if (0.0 <= ftow &&
1508
248
        10.0 < f2) {
1509
181
        session->context->leap_seconds = (int)round(f2);
1510
181
        session->context->valid |= LEAP_SECOND_VALID;
1511
181
        DTOTS(&ts_tow, ftow);
1512
181
        session->newdata.time =
1513
181
            gpsd_gpstime_resolv(session, week, ts_tow);
1514
181
        mask |= TIME_SET | NTPTIME_IS | CLEAR_IS;
1515
        /* Note: this is not the time of current fix. So we do a clear
1516
         * so the previous fix data does not get attached to this time.
1517
         * Do not use in tsip.last_tow */
1518
181
    }
1519
316
    GPSD_LOG(LOG_PROG, &session->context->errout,
1520
316
             "TSIP x41: GPS Time: tow %.3f week %u ls %.1f %s\n",
1521
316
             ftow, week, f2,
1522
316
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)));
1523
316
    GPSD_LOG(LOG_IO, &session->context->errout,
1524
316
             "TSIP: %s",
1525
316
             ctime(&session->newdata.time.tv_sec));
1526
316
    return mask;
1527
316
}
1528
1529
// decode Packet x42
1530
static gps_mask_t decode_x42(struct gps_device_t *session, const char *buf)
1531
1.10k
{
1532
1.10k
    gps_mask_t mask = 0;
1533
1.10k
    timespec_t ts_tow;
1534
1.10k
    double ecefx = getbef32(buf, 0);                  // X
1535
1.10k
    double ecefy = getbef32(buf, 4);                  // Y
1536
1.10k
    double ecefz = getbef32(buf, 8);                  // Z
1537
1.10k
    double ftow = getbef32(buf, 12);           // time-of-fix
1538
1539
1.10k
    session->newdata.ecef.x = ecefx;
1540
1.10k
    session->newdata.ecef.y = ecefy;
1541
1.10k
    session->newdata.ecef.z = ecefz;
1542
1.10k
    DTOTS(&ts_tow, ftow);
1543
1.10k
    session->newdata.time = gpsd_gpstime_resolv(session,
1544
1.10k
                                                session->context->gps_week,
1545
1.10k
                                                ts_tow);
1546
1.10k
    mask = ECEF_SET | TIME_SET | NTPTIME_IS;
1547
1.10k
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1548
874
        mask |= CLEAR_IS;
1549
874
        session->driver.tsip.last_tow = ts_tow;
1550
874
    }
1551
1.10k
    GPSD_LOG(LOG_PROG, &session->context->errout,
1552
1.10k
             "TSIP x42: SP-XYZ: %f %f %f ftow %f\n",
1553
1.10k
             session->newdata.ecef.x,
1554
1.10k
             session->newdata.ecef.y,
1555
1.10k
             session->newdata.ecef.z,
1556
1.10k
             ftow);
1557
1.10k
    return mask;
1558
1.10k
}
1559
1560
// Decode Protocol Version: x43
1561
static gps_mask_t decode_x43(struct gps_device_t *session, const char *buf)
1562
408
{
1563
408
    gps_mask_t mask = 0;
1564
408
    timespec_t ts_tow;
1565
408
    double vx = getbef32(buf, 0);               // X velocity, m/s
1566
408
    double vy = getbef32(buf, 4);               // Y velocity, m/s
1567
408
    double vz = getbef32(buf, 8);               // Z velocity, m/s
1568
408
    double bias_rate = getbef32(buf, 12);       // bias rate, m/s
1569
408
    double ftow = getbef32(buf, 16);            // time-of-fix
1570
1571
408
    session->newdata.ecef.vx = vx;
1572
408
    session->newdata.ecef.vy = vy;
1573
408
    session->newdata.ecef.vz = vz;
1574
1575
    // short circuit to gpsdata. Convert m/s to ns/s
1576
408
    session->gpsdata.fix.clockdrift = 1e9 * bias_rate / CLIGHT;
1577
1578
408
    DTOTS(&ts_tow, ftow);
1579
408
    session->newdata.time = gpsd_gpstime_resolv(session,
1580
408
                                                session->context->gps_week,
1581
408
                                                ts_tow);
1582
408
    mask = VECEF_SET | TIME_SET | NTPTIME_IS;
1583
408
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1584
288
        mask |= CLEAR_IS;
1585
288
        session->driver.tsip.last_tow = ts_tow;
1586
288
    }
1587
408
    GPSD_LOG(LOG_PROG, &session->context->errout,
1588
408
             "TSIP x43: Vel XYZ: %f %f %f %f ftow %f\n",
1589
408
             session->newdata.ecef.vx,
1590
408
             session->newdata.ecef.vy,
1591
408
             session->newdata.ecef.vz,
1592
408
             bias_rate, ftow);
1593
408
    return mask;
1594
408
}
1595
1596
// Decode x45
1597
static gps_mask_t decode_x45(struct gps_device_t *session, const char *buf)
1598
69
{
1599
69
    gps_mask_t mask = 0;
1600
69
    unsigned nmaj = getub(buf, 0);
1601
69
    unsigned nmin = getub(buf, 1);
1602
69
    unsigned nmon = getub(buf, 2);
1603
69
    unsigned nday = getub(buf, 3);
1604
69
    unsigned nyr = getub(buf, 4) + 1900;
1605
69
    unsigned fmaj = getub(buf, 5);
1606
69
    unsigned fmin = getub(buf, 6);
1607
69
    unsigned fmon = getub(buf, 7);
1608
69
    unsigned fday = getub(buf, 8);
1609
69
    unsigned fyr = getub(buf, 9) + 2000;
1610
1611
    /* ACE calls these "NAV processor firmware" and
1612
     * "SIG processor firmware".
1613
     * RES SMT 360 calls these "application" and "GPS core".
1614
     */
1615
69
    (void)snprintf(session->subtype, sizeof(session->subtype),
1616
69
                   "sw %u.%u %02u/%02u/%04u hw %u.%u %02u/%02u/%04u",
1617
69
                   nmaj, nmin, nmon, nday, nyr,
1618
69
                   fmaj, fmin, fmon, fday, fyr);
1619
69
    GPSD_LOG(LOG_PROG, &session->context->errout,
1620
69
             "TSIP x45: Software version: %s\n", session->subtype);
1621
69
    mask |= DEVICEID_SET;
1622
1623
    // request I/O Options (0x55)
1624
69
    (void)tsip_write1(session, "\x35", 1);
1625
1626
    /* request actual subtype using x1c-01, returns x1c-81
1627
     * which in turn requests 0x1c-83
1628
     * then requests x8f-42 */
1629
69
    (void)tsip_write1(session, "\x1c\x01", 2);
1630
69
    return mask;
1631
69
}
1632
1633
// Decode Health of Receiver, x46
1634
static gps_mask_t decode_x46(struct gps_device_t *session, const char *buf)
1635
942
{
1636
942
    gps_mask_t mask = 0;
1637
942
    char buf2[80];
1638
    // Status code, see vgnss_decode_status
1639
942
    unsigned status = getub(buf, 0);
1640
942
    unsigned ec = getub(buf, 1);      // error codes
1641
1642
942
    switch (status) {
1643
217
    case 0:         //  "Doing Fixes"
1644
        // could be 2D or 3D.  So check the last setting.
1645
217
        if (MODE_2D >= session->oldfix.mode) {
1646
87
            session->newdata.mode = MODE_2D;  // At least 2D
1647
130
        } else {
1648
130
            session->newdata.mode = MODE_3D;
1649
130
        }
1650
217
        break;
1651
66
    case 9:          // "1 usable sat"
1652
66
        session->newdata.mode = MODE_2D;
1653
66
        break;
1654
87
    case 10:         // "2 usable sats"
1655
87
        session->newdata.mode = MODE_2D;
1656
87
        break;
1657
66
    case 11:         // "3 usable sats"
1658
66
        session->newdata.mode = MODE_2D;
1659
66
        break;
1660
66
    case 1:          // "No GPS time"
1661
66
        FALLTHROUGH
1662
150
    case 2:          // "Needs Init"
1663
150
        FALLTHROUGH
1664
217
    case 3:          // "PDOP too high"
1665
217
        FALLTHROUGH
1666
286
    case 8:          // "0 usable sats"
1667
286
        FALLTHROUGH
1668
352
    case 12:         // "chosen sat unusable"
1669
352
        FALLTHROUGH
1670
418
    case 16:         // "TRAIM rejected"
1671
418
        session->newdata.mode = MODE_NO_FIX;
1672
418
        break;
1673
0
    case 0xbb:       // "GPS Time Fix (OD mode)"
1674
        // Always on after survey, so no info here.
1675
0
        break;
1676
942
    }
1677
942
    if (MODE_NOT_SEEN != session->newdata.mode) {
1678
854
        mask |= MODE_SET;
1679
854
    }
1680
1681
    /* Error codes, model dependent
1682
     * 0x01 -- no battery, always set on RES SMT 360
1683
     * 0x10 -- antenna is open
1684
     * 0x30 -- antenna is shorted
1685
     */
1686
942
    switch (ec & 0x30) {
1687
340
    case 0x10:
1688
340
        session->newdata.ant_stat = ANT_OPEN;
1689
340
        break;
1690
161
    case 0x30:
1691
161
        session->newdata.ant_stat = ANT_SHORT;
1692
161
        break;
1693
441
    default:
1694
441
        session->newdata.ant_stat = ANT_OK;
1695
441
        break;
1696
942
    }
1697
1698
942
    if (STATUS_UNK != session->newdata.status) {
1699
0
        mask |= STATUS_SET;
1700
0
    }
1701
942
    GPSD_LOG(LOG_PROG, &session->context->errout,
1702
942
             "TSIP x46: Receiver Health: mode %d status %d  gds:x%x "
1703
942
             "ec:x%x\n",
1704
942
            session->newdata.mode,
1705
942
            session->newdata.status,
1706
942
            status, ec);
1707
942
    GPSD_LOG(LOG_IO, &session->context->errout,
1708
942
             "TSIP: gds:%s ec:%s\n",
1709
942
             val2str(status, vgnss_decode_status),
1710
942
             flags2str(ec, verr_codes, buf2, sizeof(buf2)));
1711
942
    return mask;
1712
942
}
1713
1714
// Decode x47
1715
static gps_mask_t decode_x47(struct gps_device_t *session, const char *buf,
1716
                             unsigned len, int *pbad_len)
1717
435
{
1718
435
    gps_mask_t mask = 0;
1719
435
    char buf2[BUFSIZ];
1720
435
    unsigned i;
1721
1722
    // satellite count, RES SMT 360 doc says 12 max
1723
435
    unsigned count = getub(buf, 0);
1724
1725
435
    if (count > TSIP_CHANNELS) {
1726
72
        GPSD_LOG(LOG_WARN, &session->context->errout,
1727
72
                 "TSIP x47: Too many satellites %u\n", count);
1728
72
        return 0;
1729
72
    }
1730
1731
    // Status code, see vgnss_decode_status
1732
363
    gpsd_zero_satellites(&session->gpsdata);
1733
1734
    // packet too short?
1735
363
    if ((5 * count + 1) > len) {
1736
179
        *pbad_len = 5 * count + 1;
1737
179
        return mask;
1738
179
    }
1739
184
    *pbad_len = 0;
1740
184
    buf2[0] = '\0';
1741
865
    for (i = 0; i < count; i++) {
1742
681
        unsigned j;
1743
681
        int PRN = getub(buf, 5 * i + 1);
1744
681
        double snr = getbef32(buf, 5 * i + 2);
1745
1746
681
        if (0 > snr) {
1747
239
            snr = 0.0;
1748
239
        }
1749
37.7k
        for (j = 0; j < TSIP_CHANNELS; j++) {
1750
37.1k
            if (session->gpsdata.skyview[j].PRN == PRN) {
1751
102
                session->gpsdata.skyview[j].ss = snr;
1752
102
                break;
1753
102
            }
1754
37.1k
        }
1755
681
        str_appendf(buf2, sizeof(buf2), " %u=%.1f", PRN, snr);
1756
681
    }
1757
184
    GPSD_LOG(LOG_PROG, &session->context->errout,
1758
184
             "TSIP x47: Signal Levels: (%d):%s\n", count, buf2);
1759
184
    mask |= SATELLITE_SET;
1760
184
    return mask;
1761
363
}
1762
1763
// Decode x4a
1764
static gps_mask_t decode_x4a(struct gps_device_t *session, const char *buf)
1765
495
{
1766
495
    gps_mask_t mask = 0;
1767
495
    timespec_t ts_tow;
1768
495
    char ts_buf[TIMESPEC_LEN];
1769
495
    double lat = getbef32(buf, 0) * RAD_2_DEG;   // lat
1770
495
    double lon = getbef32(buf, 4) * RAD_2_DEG;   // lon
1771
495
    double alt = getbef32(buf, 8);               // alt
1772
495
    double clock_bias = getbef32(buf, 12);       // clock bias, m/s
1773
495
    double ftow = getbef32(buf, 16);             // time-of-fix
1774
1775
495
    session->newdata.latitude = lat;
1776
495
    session->newdata.longitude = lon;
1777
    // depending on GPS config, could be either WGS84 or MSL
1778
495
    if (0 == session->driver.tsip.alt_is_msl) {
1779
389
        session->newdata.altHAE = alt;
1780
389
    } else {
1781
106
        session->newdata.altMSL = alt;
1782
106
    }
1783
    // short circuit to gpsdata. COnvert m/s to ns
1784
495
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
1785
1786
495
    if (0 != (session->context->valid & GPS_TIME_VALID)) {
1787
378
        DTOTS(&ts_tow, ftow);
1788
378
        session->newdata.time =
1789
378
            gpsd_gpstime_resolv(session, session->context->gps_week,
1790
378
                                ts_tow);
1791
378
        mask |= TIME_SET | NTPTIME_IS;
1792
378
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1793
272
            mask |= CLEAR_IS;
1794
272
            session->driver.tsip.last_tow = ts_tow;
1795
272
        }
1796
378
    }
1797
    // this seems to be often first in cycle
1798
    // REPORT_IS here breaks reports in read-only mode
1799
495
    mask |= LATLON_SET | ALTITUDE_SET;
1800
495
    GPSD_LOG(LOG_PROG, &session->context->errout,
1801
495
             "TSIP x4a: SP-LLA: time=%s lat=%.2f lon=%.2f "
1802
495
             "alt=%.2f cbias %.2f\n",
1803
495
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
1804
495
             session->newdata.latitude,
1805
495
             session->newdata.longitude, alt, clock_bias);
1806
495
    return mask;
1807
495
}
1808
1809
// Decode x4b
1810
static gps_mask_t decode_x4b(struct gps_device_t *session, const char *buf)
1811
993
{
1812
993
    gps_mask_t mask = 0;
1813
993
    char buf2[80];
1814
993
    char buf3[80];
1815
993
    unsigned u1 = getub(buf, 0);  // Machine ID
1816
    /* Status 1
1817
     * bit 1 -- No RTC at power up
1818
     * bit 3 -- almanac not complete and current */
1819
993
    unsigned u2 = getub(buf, 1);     // status 1
1820
993
    unsigned u3 = getub(buf, 2);     // Status 2/Superpacket Support
1821
1822
993
    session->driver.tsip.machine_id = u1;  // Machine ID
1823
1824
993
    if ('\0' == session->subtype[0]) {
1825
455
        const char *name;
1826
        // better than nothing
1827
455
        switch (session->driver.tsip.machine_id) {
1828
67
        case 1:
1829
            // should use better name from superpacket
1830
67
            name = " SMT 360";
1831
            /* request actual subtype from 0x1c-81
1832
             * which in turn requests 0x1c-83 */
1833
67
            (void)tsip_write1(session, "\x1c\x01", 2);
1834
67
            break;
1835
67
        case 0x32:
1836
67
            name = " Acutime 360";
1837
67
            break;
1838
66
        case 0x5a:
1839
66
            name = " Lassen iQ";
1840
            /* request actual subtype from 0x1c-81
1841
             * which in turn requests 0x1c-83.
1842
             * Only later firmware Lassen iQ supports this */
1843
66
            (void)tsip_write1(session, "\x1c\x01", 2);
1844
66
            break;
1845
67
        case 0x61:
1846
67
            name = " Acutime 2000";
1847
67
            break;
1848
34
        case 0x62:
1849
34
            name = " ACE UTC";
1850
34
            break;
1851
86
        case 0x96:
1852
            // Also Copernicus II
1853
86
            name = " Copernicus, Thunderbolt E";
1854
            /* so request actual subtype from 0x1c-81
1855
             * which in turn requests 0x1c-83 */
1856
86
            (void)tsip_write1(session, "\x1c\x01", 2);
1857
86
            break;
1858
0
        case 0:
1859
            // Resolution SMTx
1860
0
            FALLTHROUGH
1861
68
        default:
1862
68
             name = "";
1863
455
        }
1864
455
        (void)snprintf(session->subtype, sizeof(session->subtype),
1865
455
                       "Machine ID x%x(%s)",
1866
455
                       session->driver.tsip.machine_id, name);
1867
455
    }
1868
993
    GPSD_LOG(LOG_PROG, &session->context->errout,
1869
993
             "TSIP x4b: Machine ID: %02x %02x %02x\n",
1870
993
             session->driver.tsip.machine_id,
1871
993
             u2, u3);
1872
993
    GPSD_LOG(LOG_IO, &session->context->errout,
1873
993
             "TSIP: stat1:%s stat2:%s\n",
1874
993
             flags2str(u2, vstat1, buf2, sizeof(buf2)),
1875
993
             flags2str(u3, vstat2, buf3, sizeof(buf3)));
1876
1877
993
    if (u3 != session->driver.tsip.superpkt) {
1878
493
        session->driver.tsip.superpkt = u3;
1879
493
        GPSD_LOG(LOG_PROG, &session->context->errout,
1880
493
                 "TSIP: Switching to Super Packet mode %d\n", u3);
1881
493
        switch (u3){
1882
298
        default:
1883
298
            FALLTHROUGH
1884
324
        case 0:
1885
            // old Trimble, no superpackets
1886
324
            break;
1887
91
        case 1:
1888
            // 1 == superpacket is acutime 360, support 0x8f-20
1889
1890
            /* set I/O Options for Super Packet output
1891
             * Position: 8F20, ECEF, DP */
1892
91
            buf2[0] = 0x35;
1893
91
            buf2[1] = IO1_8F20|IO1_DP|IO1_ECEF;
1894
91
            buf2[2] = 0x00;          // Velocity: none (via SP)
1895
91
            buf2[3] = 0x00;          // Time: GPS
1896
91
            buf2[4] = IO4_DBHZ;      // Aux: dBHz
1897
91
            (void)tsip_write1(session, buf2, 5);
1898
91
            break;
1899
78
        case 2:
1900
            /* 2 == SMT 360, or Resolution SMTx
1901
             * no 0x8f-20, or x8f-23.
1902
             * request x8f-a5 */
1903
78
            (void)tsip_write1(session, "\x8e\xa5", 2);
1904
78
            break;
1905
493
        }
1906
493
    }
1907
1908
993
    return mask;
1909
993
}
1910
1911
// Decode x4c
1912
static gps_mask_t decode_x4c(struct gps_device_t *session, const char *buf)
1913
66
{
1914
66
    gps_mask_t mask = 0;
1915
66
    unsigned u1 = getub(buf, 0);                  // Dynamics Code
1916
66
    double f1 = getbef32(buf, 1) * RAD_2_DEG;     // Elevation Mask
1917
66
    double f2 = getbef32(buf, 5);                 // Signal Level Mask
1918
66
    double f3 = getbef32(buf, 9);                 // PDOP Mask
1919
66
    double f4 = getbef32(buf, 13);                // PDOP Switch
1920
1921
66
    GPSD_LOG(LOG_PROG, &session->context->errout,
1922
66
             "TSIP x4c: OP: Dyn x%02x El %f Sig %f PDOP %f %f\n",
1923
66
             u1, f1, f2, f3, f4);
1924
66
    GPSD_LOG(LOG_IO, &session->context->errout,
1925
66
             "TSIP: Dynamics:%s\n",
1926
66
             val2str(u1, vx4c_dyncode));
1927
66
    return mask;
1928
66
}
1929
1930
/* Decode  Bias and Bias Rate Report (0x54)
1931
 * Present in:
1932
 *   pre-2000 models
1933
 *   Acutime 360
1934
 *   ICM SMT 360  (undocumented)
1935
 *   RES SMT 360  (undocumented)
1936
 * Not Present in:
1937
 *   Copernicus II (2009)
1938
 *   Resolution SMTx
1939
 */
1940
static gps_mask_t decode_x54(struct gps_device_t *session, const char *buf)
1941
634
{
1942
634
    gps_mask_t mask = 0;
1943
634
    timespec_t ts_tow;
1944
634
    double clock_bias = getbef32(buf, 0);         // clock Bias, m
1945
634
    double clock_rate = getbef32(buf, 4);         // clock Bias rate, m/s
1946
634
    double ftow = getbef32(buf, 8);               // tow
1947
1948
634
    DTOTS(&ts_tow, ftow);
1949
634
    session->newdata.time =
1950
634
        gpsd_gpstime_resolv(session, session->context->gps_week, ts_tow);
1951
634
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1952
564
        mask |= CLEAR_IS;
1953
564
        session->driver.tsip.last_tow = ts_tow;
1954
564
    }
1955
    // short circuit to gpsdata. Convert m to ns
1956
634
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
1957
634
    session->gpsdata.fix.clockdrift = 1e9 * clock_rate / CLIGHT;
1958
1959
634
    mask |= TIME_SET | NTPTIME_IS;
1960
1961
634
    GPSD_LOG(LOG_PROG, &session->context->errout,
1962
634
            "TSIP x54: BBRR: Bias %f brate %f tow %f\n",
1963
634
            clock_bias, clock_rate, ftow);
1964
634
    return mask;
1965
634
}
1966
1967
// Decode Protocol Version: x55
1968
static gps_mask_t decode_x55(struct gps_device_t *session, const char *buf,
1969
                             time_t now)
1970
365
{
1971
365
    gps_mask_t mask = 0;
1972
365
    char buf2[80];
1973
365
    char buf3[80];
1974
365
    char buf4[80];
1975
365
    char buf5[80];
1976
1977
365
    unsigned u1 = getub(buf, 0);     // Position
1978
365
    unsigned u2 = getub(buf, 1);     // Velocity
1979
    /* Timing
1980
     * bit 0 - reserved use 0x8e-a2 ?
1981
     */
1982
365
    unsigned u3 = getub(buf, 2);
1983
    /* Aux
1984
     * bit 0 - packet 0x5a (raw data)
1985
     * bit 3 -- Output dbHz
1986
     */
1987
365
    unsigned u4 = getub(buf, 3);
1988
1989
    // decode HAE/MSL from Position byte
1990
365
    if (IO1_MSL == (IO1_MSL & u1)) {
1991
198
        session->driver.tsip.alt_is_msl = 1;
1992
198
    } else {
1993
167
        session->driver.tsip.alt_is_msl = 0;
1994
167
    }
1995
1996
365
    GPSD_LOG(LOG_PROG, &session->context->errout,
1997
365
             "TSIP x55: IO Options: %02x %02x %02x %02x\n",
1998
365
             u1, u2, u3, u4);
1999
365
    GPSD_LOG(LOG_IO, &session->context->errout,
2000
365
             "TSIPv1: pos:%s vel:%s timing:%s aux:%s\n",
2001
365
             flags2str(u1, vx55_pos, buf2, sizeof(buf2)),
2002
365
             flags2str(u2, vx55_vel, buf3, sizeof(buf3)),
2003
365
             flags2str(u3, vx55_timing, buf4, sizeof(buf4)),
2004
365
             flags2str(u4, vx55_aux, buf5, sizeof(buf5)));
2005
365
    if ((u1 & 0x20) != (uint8_t) 0) {
2006
        /* Try to get Super Packets
2007
         * Turn off 0x8f-20 LFwEI Super Packet */
2008
238
        (void)tsip_write1(session, "\x8e\x20\x00", 3);
2009
2010
        // Turn on Compact Super Packet 0x8f-23
2011
238
        (void)tsip_write1(session, "\x8e\x23\x01", 3);
2012
238
        session->driver.tsip.req_compact = now;
2013
238
    }
2014
365
    return mask;
2015
365
}
2016
2017
// Decode Velocity Fix, Easst-North-Up, packet x56
2018
static gps_mask_t decode_x56(struct gps_device_t *session, const char *buf)
2019
429
{
2020
429
    gps_mask_t mask = 0;
2021
429
    timespec_t ts_tow;
2022
2023
429
    float f1 = getbef32(buf, 0);        // East velocity
2024
429
    float f2 = getbef32(buf, 4);        // North velocity
2025
429
    float f3 = getbef32(buf, 8);        // Up velocity
2026
429
    float cbias = getbef32(buf, 12);    // clock bias rate, m/s
2027
429
    float ftow = getbef32(buf, 16);     // time-of-fix
2028
2029
    // Could be GPS, or UTC...
2030
429
    DTOTS(&ts_tow, ftow);
2031
429
    session->newdata.time = gpsd_gpstime_resolv(session,
2032
429
                                                session->context->gps_week,
2033
429
                                                ts_tow);
2034
429
    session->newdata.NED.velN = f2;
2035
429
    session->newdata.NED.velE = f1;
2036
429
    session->newdata.NED.velD = -f3;
2037
    // short circuit to gpsdata. Convert m to ns
2038
429
    session->gpsdata.fix.clockdrift = 1e9 * cbias / CLIGHT;
2039
2040
429
    mask |= VNED_SET | TIME_SET | NTPTIME_IS;
2041
429
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2042
351
        mask |= CLEAR_IS;
2043
351
        session->driver.tsip.last_tow = ts_tow;
2044
351
    }
2045
429
    GPSD_LOG(LOG_PROG, &session->context->errout,
2046
429
             "TSIP x56: Vel ENU: %f %f %f cbias %f ftow %f\n",
2047
429
             f1, f2, f3, cbias, ftow);
2048
429
    GPSD_LOG(LOG_IO, &session->context->errout,
2049
429
             "TSIP: %s",
2050
429
             ctime(&session->newdata.time.tv_sec));
2051
429
    return mask;
2052
429
}
2053
2054
// Decode x57
2055
static gps_mask_t decode_x57(struct gps_device_t *session, const char *buf)
2056
542
{
2057
542
    gps_mask_t mask = 0;
2058
542
    timespec_t ts_tow;
2059
542
    char buf2[80];
2060
542
    unsigned u1 = getub(buf, 0);                     // Source of information
2061
542
    unsigned u2 = getub(buf, 1);                     // Mfg. diagnostic
2062
542
    double ftow = getbef32(buf, 2);                  // gps_time
2063
542
    unsigned week = getbeu16(buf, 6);                // tsip.gps_week
2064
2065
542
    if (0x01 == u1) {
2066
        // good current fix
2067
473
        DTOTS(&ts_tow, ftow);
2068
473
        (void)gpsd_gpstime_resolv(session, week, ts_tow);
2069
473
        mask |= TIME_SET | NTPTIME_IS;
2070
473
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2071
404
            mask |= CLEAR_IS;
2072
404
            session->driver.tsip.last_tow = ts_tow;
2073
404
        }
2074
473
    }
2075
542
    GPSD_LOG(LOG_PROG, &session->context->errout,
2076
542
             "TSIP x57: Fix info: %02x %02x %u %f\n",
2077
542
             u1, u2, week, ftow);
2078
542
    GPSD_LOG(LOG_IO, &session->context->errout,
2079
542
             "TSIP: info:%s fmode:%s\n",
2080
542
             flags2str(u1, vx57_info, buf2, sizeof(buf2)),
2081
542
             val2str(u1, vx57_fmode));
2082
542
    return mask;
2083
542
}
2084
2085
// Decode x5a
2086
static gps_mask_t decode_x5a(struct gps_device_t *session, const char *buf)
2087
34
{
2088
34
    gps_mask_t mask = 0;
2089
    // Useless without the pseudorange...
2090
34
    unsigned u1 = getub(buf, 0);             // PRN 1-237
2091
34
    float f1 = getbef32(buf, 1);             // sample length
2092
34
    float f2 = getbef32(buf, 5);             // Signal Level, dbHz
2093
34
    float f3 = getbef32(buf, 9);             // Code phase, 1/16th chip
2094
34
    float f4 = getbef32(buf, 13);            // Doppler, Hz @ L1
2095
34
    double d1 = getbed64(buf, 17);           // Time of Measurement
2096
2097
34
    GPSD_LOG(LOG_PROG, &session->context->errout,
2098
34
             "TSIP x5a: Raw Measurement Data: PRN %d len %f SNR %f chip %f "
2099
34
             "doppler %f tom %f\n",
2100
34
             u1, f1, f2, f3, f4, d1);
2101
34
    return mask;
2102
34
}
2103
2104
// Decode Satellite Tracking Status, packet x5c
2105
static gps_mask_t decode_x5c(struct gps_device_t *session, const char *buf)
2106
742
{
2107
742
    gps_mask_t mask = 0;
2108
742
    timespec_t ts_tow;
2109
742
    unsigned i;
2110
    // Useless without the pseudorange...
2111
742
    int PRN = getub(buf, 0);                     // PRN 1-32
2112
    // slot unused in Lassen IQ
2113
742
    unsigned u2 = getub(buf, 1);                 // slot:chan
2114
742
    unsigned acq = getub(buf, 2);                // Acquisition flag
2115
742
    unsigned eflag = getub(buf, 3);              // Ephemeris flag
2116
742
    double snr = getbef32(buf, 4);               // Signal level
2117
    // time of skyview, not current time, nor time of fix
2118
742
    double ftow = getbef32(buf, 8);
2119
2120
742
    double el = getbef32(buf, 12) * RAD_2_DEG;   // Elevation
2121
742
    double az = getbef32(buf, 16) * RAD_2_DEG;   // Azimuth
2122
2123
    // Old Measurement flag, unused in Lassen IQ
2124
742
    unsigned omf = getub(buf, 20);
2125
2126
742
    DTOTS(&session->gpsdata.skyview_time, ftow);
2127
    /* Channel number, bits 0-2 reserved/unused as of 1999.
2128
     * Seems to always start series at zero and increment to last one.
2129
     * No way to know how many there will be.
2130
     * Save current channel to check for last 0x5c message
2131
     */
2132
742
    i = (int)(u2 >> 3);     // channel number, starting at 0
2133
742
    if (0 == i) {
2134
        // start of new cycle, save last count
2135
603
        session->gpsdata.satellites_visible =
2136
603
            session->driver.tsip.last_chan_seen;
2137
603
    } else if (i > TSIP_CHANNELS) {
2138
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2139
0
                 "TSIP x5c: Satellite Tracking Status: Too many chans %d\n", i);
2140
0
        return 0;
2141
139
    } else if (0 == PRN ||
2142
105
               32 < PRN) {
2143
71
        GPSD_LOG(LOG_WARN, &session->context->errout,
2144
71
                "TSIPv1 x5c: invalid prn %d\n", PRN);
2145
71
        return 0;
2146
71
    }
2147
671
    session->driver.tsip.last_chan_seen = i;
2148
2149
671
    session->gpsdata.skyview[i].PRN = PRN;
2150
671
    session->gpsdata.skyview[i].svid = PRN;
2151
671
    session->gpsdata.skyview[i].gnssid = GNSSID_GPS;
2152
671
    session->gpsdata.skyview[i].ss = snr;
2153
671
    session->gpsdata.skyview[i].elevation = el;
2154
671
    session->gpsdata.skyview[i].azimuth = az;
2155
671
    session->gpsdata.skyview[i].gnssid = tsip_gnssid(0, PRN,
2156
671
        &session->gpsdata.skyview[i].svid);
2157
671
    if (2 == (2 & eflag)) {
2158
332
        session->gpsdata.skyview[i].health = SAT_HEALTH_OK;
2159
339
    } else if (1 == eflag) {
2160
37
        session->gpsdata.skyview[i].health = SAT_HEALTH_BAD;
2161
37
    } // else, unknown
2162
2163
671
    if (0x10 == (0x10 & eflag)) {
2164
273
        session->gpsdata.skyview[i].used = true;
2165
273
        if (51 == eflag) {
2166
94
            session->newdata.status = STATUS_DGPS;
2167
94
            mask |= STATUS_SET;
2168
94
        }
2169
398
    } else {
2170
398
        session->gpsdata.skyview[i].used = false;
2171
398
    }
2172
    /* when polled by 0x3c, all the skyview times will be the same
2173
     * in one cluster */
2174
671
    if (0.0 < ftow) {
2175
466
        DTOTS(&ts_tow, ftow);
2176
466
        session->gpsdata.skyview_time =
2177
466
            gpsd_gpstime_resolv(session, session->context->gps_week,
2178
466
                                ts_tow);
2179
        /* do not save in session->driver.tsip.last_tow
2180
         * as this is skyview time, not fix time */
2181
466
    }
2182
671
    if ((i + 1) >= session->gpsdata.satellites_visible) {
2183
        /* Last of the series?
2184
         * This will cause extra SKY if this set has more
2185
         * sats than the last set */
2186
616
        mask |= SATELLITE_SET;
2187
616
        session->gpsdata.satellites_visible = i + 1;
2188
616
    }
2189
671
    if (MAXCHANNELS < session->gpsdata.satellites_visible) {
2190
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2191
0
                "TSIP x5c: too many satellites %d\n",
2192
0
                 session->gpsdata.satellites_visible);
2193
0
        session->gpsdata.satellites_visible = MAXCHANNELS;
2194
0
    }
2195
    /* If this series has fewer than last series there will
2196
     * be no SKY, unless the cycle ender pushes the SKY */
2197
671
    GPSD_LOG(LOG_PROG, &session->context->errout,
2198
671
             "TSIP x5c: Satellite Tracking Status: Ch %2d PRN %3d "
2199
671
             "es %d Acq %d Eph %2d SNR %4.1f LMT %.04f El %.1f Az %.1f "
2200
671
             "omf %u hlth %u\n",
2201
671
             i, PRN, u2 & 7, acq, eflag, snr, ftow, el, az, omf,
2202
671
            session->gpsdata.skyview[i].health);
2203
671
    GPSD_LOG(LOG_IO, &session->context->errout,
2204
671
             "TSIP: acq:%s eflag:%s\n",
2205
671
             val2str(acq, vx5c_acq),
2206
671
             val2str(eflag, vx5c_eflag));
2207
2208
671
    return mask;
2209
742
}
2210
2211
// Decode x5d
2212
static gps_mask_t decode_x5d(struct gps_device_t *session, const char *buf)
2213
995
{
2214
995
    gps_mask_t mask = 0;
2215
995
    timespec_t ts_tow;
2216
995
    char buf2[BUFSIZ];
2217
995
    unsigned char u1 = getub(buf, 0);           // PRN
2218
995
    unsigned i = getub(buf, 1);                 // chan
2219
995
    unsigned u3 = getub(buf, 2);                // Acquisition flag
2220
995
    unsigned u4 = getub(buf, 3);                // used?
2221
995
    double f1 = getbef32(buf, 4);               // SNR
2222
    // This can be one second behind the TPV on RES SMT 360
2223
995
    double ftow = getbef32(buf, 8);             // time of Last measurement
2224
995
    double d1 = getbef32(buf, 12) * RAD_2_DEG;  // Elevation
2225
995
    double d2 = getbef32(buf, 16) * RAD_2_DEG;  // Azimuth
2226
995
    unsigned u5 = getub(buf, 20);               // old measurement flag
2227
995
    unsigned u6 = getub(buf, 21);               // integer msec flag
2228
995
    unsigned u7 = getub(buf, 22);               // bad data flag
2229
995
    unsigned u8 = getub(buf, 23);               // data collection flag
2230
995
    unsigned u9 = getub(buf, 24);               // Used flags
2231
995
    unsigned u10 = getub(buf, 25);              // SV Type
2232
2233
    /* Channel number, bits 0-2 reserved/unused as of 1999.
2234
     * Seems to always start series at zero and increment to last one.
2235
     * No way to know how many there will be.
2236
     * Save current channel to check for last 0x5d message
2237
     */
2238
995
    if (0 == i) {
2239
        // start of new cycle, save last count
2240
241
        session->gpsdata.satellites_visible =
2241
241
            session->driver.tsip.last_chan_seen;
2242
754
    } else if (i >= TSIP_CHANNELS) {
2243
35
        GPSD_LOG(LOG_WARN, &session->context->errout,
2244
35
                 "TSIP x5d: Satellite Tracking Status: Too many chans %d\n", i);
2245
35
        return 0;
2246
35
    }
2247
960
    session->driver.tsip.last_chan_seen = i;
2248
2249
960
    session->gpsdata.skyview[i].PRN = u1;
2250
960
    session->gpsdata.skyview[i].ss = f1;
2251
960
    session->gpsdata.skyview[i].elevation = d1;
2252
960
    session->gpsdata.skyview[i].azimuth = d2;
2253
960
    session->gpsdata.skyview[i].used = (bool)u4;
2254
960
    session->gpsdata.skyview[i].gnssid = tsip_gnssid(u10, u1,
2255
960
        &session->gpsdata.skyview[i].svid);
2256
960
    if (0 == u7) {
2257
286
        session->gpsdata.skyview[i].health = SAT_HEALTH_OK;
2258
674
    } else {
2259
674
        session->gpsdata.skyview[i].health = SAT_HEALTH_BAD;
2260
674
    }
2261
2262
    /* when polled by 0x3c, all the skyview times will be the same
2263
     * in one cluster */
2264
960
    if (0.0 < ftow) {
2265
619
        DTOTS(&ts_tow, ftow);
2266
619
        session->gpsdata.skyview_time =
2267
619
            gpsd_gpstime_resolv(session, session->context->gps_week,
2268
619
                                ts_tow);
2269
        /* do not save in session->driver.tsip.last_tow
2270
         * as this is skyview time, not fix time */
2271
619
    }
2272
960
    if (++i >= session->gpsdata.satellites_visible) {
2273
        /* Last of the series?
2274
         * This will cause extra SKY if this set has more
2275
         * sats than the last set */
2276
834
        mask |= SATELLITE_SET;
2277
834
        session->gpsdata.satellites_visible = i;
2278
834
    }
2279
    /* If this series has fewer than last series there will
2280
     * be no SKY, unless the cycle ender pushes the SKY */
2281
2282
960
    if (MAXCHANNELS < session->gpsdata.satellites_visible) {
2283
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2284
0
                "TSIP x5d: too many satellites %d\n",
2285
0
                 session->gpsdata.satellites_visible);
2286
0
        session->gpsdata.satellites_visible = MAXCHANNELS;
2287
0
    }
2288
960
    GPSD_LOG(LOG_PROG, &session->context->errout,
2289
960
            "TSIP x5d: Satellite Tracking Status: Ch %2d Con %d PRN %3d "
2290
960
            "Acq %d Use %d SNR %4.1f LMT %.04f El %4.1f Az %5.1f Old %d "
2291
960
            "Int %d Bad %d Col %d TPF %d SVT %d\n",
2292
960
            i, u10, u1, u3, u4, f1, ftow, d1, d2, u5, u6, u7, u8, u9, u10);
2293
960
    GPSD_LOG(LOG_IO, &session->context->errout,
2294
960
             "TSIP: bad:%s uflags:%s scons:%s\n",
2295
960
             val2str(u7, vsv_bad),
2296
960
             flags2str(u9, vsv_used_flags, buf2, sizeof(buf2)),
2297
960
             val2str(u10, vsv_type));
2298
960
    return mask;
2299
995
}
2300
2301
// Decode x6c
2302
static gps_mask_t decode_x6c(struct gps_device_t *session, const char *buf,
2303
                             unsigned len, int *pbad_len)
2304
982
{
2305
982
    gps_mask_t mask = 0;
2306
982
    char buf2[80];
2307
982
    unsigned i, count;
2308
982
    unsigned fixdm = getub(buf, 0);          // fix dimension, mode
2309
982
    double pdop = getbef32(buf, 1);
2310
982
    double hdop = getbef32(buf, 5);
2311
982
    double vdop = getbef32(buf, 9);
2312
    // RES SMT 360 and ICM SMT 360 always report tdop == 1
2313
982
    double tdop = getbef32(buf, 13);
2314
2315
982
    if (IN(0.01, pdop, 89.99)) {
2316
        // why not to newdata?
2317
174
        session->gpsdata.dop.pdop = pdop;
2318
174
        mask |= DOP_SET;
2319
174
    }
2320
982
    if (IN(0.01, hdop, 89.99)) {
2321
        // why not to newdata?
2322
224
        session->gpsdata.dop.hdop = hdop;
2323
224
        mask |= DOP_SET;
2324
224
    }
2325
982
    if (IN(0.01, vdop, 89.99)) {
2326
        // why not to newdata?
2327
201
        session->gpsdata.dop.vdop = vdop;
2328
201
        mask |= DOP_SET;
2329
201
    }
2330
982
    if (IN(0.01, tdop, 89.99)) {
2331
        // why not to newdata?
2332
228
        session->gpsdata.dop.tdop = tdop;
2333
228
        mask |= DOP_SET;
2334
228
    }
2335
2336
982
    count = getub(buf, 17);
2337
2338
982
    if ((18 + count) > len) {
2339
260
        *pbad_len = 18 + count;
2340
260
        return mask;
2341
260
    }
2342
2343
722
    if (MAXCHANNELS < count) {
2344
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2345
0
                 "TSIP x6c: too many used satellites %d\n", count);
2346
0
        *pbad_len = 18 + count;
2347
0
        return mask;
2348
0
    }
2349
722
    *pbad_len = 0;
2350
2351
    /*
2352
     * This looks right, but it sets a spurious mode value when
2353
     * the satellite constellation looks good to the chip but no
2354
     * actual fix has yet been acquired.  We should set the mode
2355
     * field (which controls gpsd's fix reporting) only from sentences
2356
     * that convey actual fix information, like 0x8f-20, but some
2357
     * TSIP do not support 0x8f-20, and 0x6c may be all we got.
2358
     */
2359
722
    switch (fixdm & 7) {       // dimension
2360
111
    case 1:       // clock fix (surveyed in)
2361
111
        FALLTHROUGH
2362
185
    case 5:       // Overdetermined clock fix
2363
185
        session->newdata.status = STATUS_TIME;
2364
185
        session->newdata.mode = MODE_3D;
2365
185
        break;
2366
111
    case 3:
2367
111
        session->newdata.mode = MODE_2D;
2368
111
        break;
2369
77
    case 4:
2370
77
        session->newdata.mode = MODE_3D;
2371
77
        break;
2372
69
    case 6:
2373
        // Accutime
2374
69
        session->newdata.status = STATUS_DGPS;
2375
69
        session->newdata.mode = MODE_3D;
2376
69
        break;
2377
72
    case 0:
2378
        // Sometimes this is No Fix, sometimes Auto....
2379
72
        FALLTHROUGH
2380
161
    case 2:
2381
161
        FALLTHROUGH
2382
280
    case 7:
2383
280
        FALLTHROUGH
2384
280
    default:
2385
280
        session->newdata.mode = MODE_NO_FIX;
2386
280
        break;
2387
722
    }
2388
722
    if (8 == (fixdm & 8)) {      // fix mode
2389
        // Manual (Surveyed in)
2390
342
        if (count) {
2391
120
            session->newdata.status = STATUS_TIME;
2392
222
        } else {
2393
            // no saats, must be DR
2394
222
            session->newdata.status = STATUS_DR;
2395
222
        }
2396
342
    }
2397
722
    if (STATUS_UNK < session->newdata.status) {
2398
373
        mask |= STATUS_SET;
2399
373
    }
2400
722
    mask |= MODE_SET;
2401
2402
722
    session->gpsdata.satellites_used = count;
2403
2404
722
    memset(session->driver.tsip.sats_used, 0,
2405
722
            sizeof(session->driver.tsip.sats_used));
2406
722
    buf2[0] = '\0';
2407
2.23k
    for (i = 0; i < count; i++) {
2408
        // negative PRN means sat unhealthy why use an unhealthy sat??
2409
1.51k
        session->driver.tsip.sats_used[i] = getsb(buf, 18 + i);
2410
1.51k
        if (LOG_PROG <= session->context->errout.debug) {
2411
0
            str_appendf(buf2, sizeof(buf2),
2412
0
                           " %d", session->driver.tsip.sats_used[i]);
2413
0
        }
2414
1.51k
    }
2415
722
    GPSD_LOG(LOG_PROG, &session->context->errout,
2416
722
             "TSIP x6c: AIVSS: mode %d status %d used %d "
2417
722
             "pdop %.1f hdop %.1f vdop %.1f tdop %.1f Used %s fixdm x%x\n",
2418
722
             session->newdata.mode,
2419
722
             session->newdata.status,
2420
722
             session->gpsdata.satellites_used,
2421
722
             pdop, hdop, vdop, tdop, buf2, fixdm);
2422
722
    GPSD_LOG(LOG_IO, &session->context->errout,
2423
722
             "TSIP: fixd:%s\n",
2424
722
             flags2str(fixdm, vfix, buf2, sizeof(buf2)));
2425
722
    mask |= USED_IS;
2426
722
    return mask;
2427
722
}
2428
2429
// decode All-in-view Satellite Selection, x6d
2430
static gps_mask_t decode_x6d(struct gps_device_t *session, const char *buf,
2431
                             unsigned len, int *pbad_len)
2432
1.05k
{
2433
1.05k
    gps_mask_t mask = 0;
2434
1.05k
    unsigned i;
2435
1.05k
    char buf2[BUFSIZ];
2436
2437
1.05k
    unsigned fix_dim = getub(buf, 0);     // nsvs/dimension
2438
1.05k
    unsigned count = (fix_dim >> 4) & 0x0f;
2439
1.05k
    double pdop = getbef32(buf, 1);
2440
1.05k
    double hdop = getbef32(buf, 5);
2441
1.05k
    double vdop = getbef32(buf, 9);
2442
1.05k
    double tdop = getbef32(buf, 13);
2443
2444
1.05k
    if ((17 + count) > len) {
2445
71
        *pbad_len = 17 + count;
2446
71
        return 0;
2447
71
    }
2448
984
    *pbad_len = 0;
2449
2450
984
    session->gpsdata.satellites_used = count;
2451
984
    if (IN(0.01, pdop, 89.99)) {
2452
        // why not to newdata?
2453
202
        session->gpsdata.dop.pdop = pdop;
2454
202
        mask |= DOP_SET;
2455
202
    }
2456
984
    if (IN(0.01, hdop, 89.99)) {
2457
        // why not to newdata?
2458
184
        session->gpsdata.dop.hdop = hdop;
2459
184
        mask |= DOP_SET;
2460
184
    }
2461
984
    if (IN(0.01, vdop, 89.99)) {
2462
        // why not to newdata?
2463
144
        session->gpsdata.dop.vdop = vdop;
2464
144
        mask |= DOP_SET;
2465
144
    }
2466
984
    if (IN(0.01, tdop, 89.99)) {
2467
        // why not to newdata?
2468
175
        session->gpsdata.dop.tdop = tdop;
2469
175
        mask |= DOP_SET;
2470
175
    }
2471
2472
    /*
2473
     * This looks right, but it sets a spurious mode value when
2474
     * the satellite constellation looks good to the chip but no
2475
     * actual fix has yet been acquired.  We should set the mode
2476
     * field (which controls gpsd's fix reporting) only from sentences
2477
     * that convey actual fix information, like 0x8f-20, but some
2478
     * TSIP do not support 0x8f-20, and 0x6c may be all we got.
2479
     */
2480
984
    switch (fix_dim & 7) {   // dimension
2481
163
    case 1:
2482
        // clock fix (surveyed in), not in Lassen IQ
2483
163
        FALLTHROUGH
2484
235
    case 5:       // Overdetermined clock fix, not in Lassen IQ
2485
235
        session->newdata.status = STATUS_TIME;
2486
235
        session->newdata.mode = MODE_3D;
2487
235
        break;
2488
117
    case 3:
2489
        // Copernicus ii can output this for OD mode.
2490
117
        session->newdata.mode = MODE_2D;
2491
117
        break;
2492
129
    case 4:
2493
        // SMTx can output this for OD mode.
2494
129
        session->newdata.mode = MODE_3D;
2495
129
        break;
2496
71
    case 6:
2497
        // Accutime, not in Lassen IQ
2498
71
        session->newdata.status = STATUS_DGPS;
2499
71
        session->newdata.mode = MODE_3D;
2500
71
        break;
2501
173
    case 2:              // not in Lassen IQ
2502
173
        FALLTHROUGH
2503
265
    case 7:              // not in Lassen IQ
2504
265
        FALLTHROUGH
2505
432
    default:             // huh?
2506
432
        session->newdata.mode = MODE_NO_FIX;
2507
432
        break;
2508
984
    }
2509
984
    if (0 >= count &&
2510
719
        0 != isfinite(session->oldfix.longitude)) {
2511
        // use oldfix, as this may be the 1st message in an epoch.
2512
2513
        // reports a fix even ith no sats!
2514
291
        session->newdata.status = STATUS_DR;
2515
291
    }
2516
984
    if (STATUS_UNK < session->newdata.status) {
2517
429
        mask |= STATUS_SET;
2518
429
    }
2519
984
    mask |= MODE_SET;
2520
2521
984
    memset(session->driver.tsip.sats_used, 0,
2522
984
           sizeof(session->driver.tsip.sats_used));
2523
984
    buf2[0] = '\0';
2524
1.84k
    for (i = 0; i < count; i++) {
2525
        // negative PRN means sat unhealthy why use an unhealthy sat??
2526
2527
857
        session->driver.tsip.sats_used[i] = getsb(buf, 17 + i);
2528
857
        if (LOG_PROG <= session->context->errout.debug ) {
2529
0
            str_appendf(buf2, sizeof(buf2),
2530
0
                           " %u", session->driver.tsip.sats_used[i]);
2531
0
        }
2532
857
    }
2533
984
    GPSD_LOG(LOG_PROG, &session->context->errout,
2534
984
             "TSIP x6d: AIVSS: fix_dim=x%x status=%d mode=%d used=%d "
2535
984
             "pdop=%.1f hdop=%.1f vdop=%.1f tdop=%.1f used >%s<\n",
2536
984
             fix_dim,
2537
984
             session->newdata.status,
2538
984
             session->newdata.mode,
2539
984
             session->gpsdata.satellites_used,
2540
984
             pdop, hdop, vdop, tdop, buf2);
2541
984
    GPSD_LOG(LOG_IO, &session->context->errout,
2542
984
             "TSIP: fix::%s\n",
2543
984
             flags2str(fix_dim, vfix, buf2, sizeof(buf2)));
2544
984
    mask |= USED_IS;
2545
2546
984
    return mask;
2547
984
}
2548
2549
// decode packet x82
2550
static gps_mask_t decode_x82(struct gps_device_t *session, const char *buf)
2551
165
{
2552
165
    gps_mask_t mask = 0;
2553
    // differential position fix mode
2554
165
    unsigned mode = getub(buf, 0);
2555
165
    if (1 == (mode & 1)) {
2556
        /* mode 1 (manual DGPS), output fixes only w/ SGPS,
2557
         * or
2558
         * mode 3 (auto DGPS) and have DGPS */
2559
75
        session->newdata.status = STATUS_DGPS;
2560
75
        mask |= STATUS_SET;
2561
75
    }
2562
165
    GPSD_LOG(LOG_PROG, &session->context->errout,
2563
165
             "TSIP x82: DPFM: mode %d status=%d\n",
2564
165
             mode, session->newdata.status);
2565
165
    GPSD_LOG(LOG_IO, &session->context->errout,
2566
165
             "TSIP: mode:%s\n",
2567
165
             val2str(mode, vx82_mode));
2568
165
    return mask;
2569
165
}
2570
2571
// decode packet x83
2572
static gps_mask_t decode_x83(struct gps_device_t *session, const char *buf)
2573
305
{
2574
305
    gps_mask_t mask = 0;
2575
305
    timespec_t ts_tow;
2576
    // differential position fix mode
2577
305
    double ecefx = getbed64(buf, 0);            // X, m
2578
305
    double ecefy = getbed64(buf, 8);            // Y, m
2579
305
    double ecefz = getbed64(buf, 16);           // Z, m
2580
305
    double clock_bias = getbed64(buf, 24);      // clock bias, m
2581
305
    double ftow = getbef32(buf, 32);            // time-of-fix, s
2582
2583
305
    session->newdata.ecef.x = ecefx;
2584
305
    session->newdata.ecef.y = ecefy;
2585
305
    session->newdata.ecef.z = ecefz;
2586
    // short circuit to gpsdata. Convert m to ns
2587
305
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
2588
2589
305
    DTOTS(&ts_tow, ftow);
2590
305
    session->newdata.time = gpsd_gpstime_resolv(session,
2591
305
                                                session->context->gps_week,
2592
305
                                                ts_tow);
2593
    /* No fix mode info!! That comes later in 0x6d.
2594
     * This message only sent when there is 2D or 3D fix.
2595
     * This is a problem as gpsd will send a report with no mode.
2596
     * Steal mode from last fix.
2597
     * The last fix is likely lastfix, not oldfix, as this is likely
2598
     * a new time and starts a new cycle! */
2599
305
    session->newdata.status = session->lastfix.status;
2600
305
    if (MODE_2D > session->oldfix.mode) {
2601
91
        session->newdata.mode = MODE_2D;  // At least 2D
2602
214
    } else {
2603
214
        session->newdata.mode = session->lastfix.mode;
2604
214
    }
2605
305
    mask |= STATUS_SET | MODE_SET | ECEF_SET | TIME_SET | NTPTIME_IS;
2606
305
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2607
        // New time, so new fix.
2608
265
        mask |= CLEAR_IS;
2609
265
        session->driver.tsip.last_tow = ts_tow;
2610
265
    }
2611
305
    GPSD_LOG(LOG_PROG, &session->context->errout,
2612
305
             "TSIP x83: DP-XYZ: %f %f %f cbias %f tow %f mode %u\n",
2613
305
             session->newdata.ecef.x,
2614
305
             session->newdata.ecef.y,
2615
305
             session->newdata.ecef.z,
2616
305
             clock_bias, ftow,
2617
305
             session->newdata.mode);
2618
305
    return mask;
2619
305
}
2620
2621
// decode packet x84
2622
static gps_mask_t decode_x84(struct gps_device_t *session, const char *buf)
2623
321
{
2624
321
    gps_mask_t mask = 0;
2625
321
    timespec_t ts_tow;
2626
321
    char ts_buf[TIMESPEC_LEN];
2627
321
    double lat = getbed64(buf, 0) * RAD_2_DEG;   // lat, radians
2628
321
    double lon = getbed64(buf, 8) * RAD_2_DEG;   // lon, radians
2629
    // depending on GPS config, could be either WGS84 or MSL
2630
321
    double d1 = getbed64(buf, 16);               // altitude, m
2631
321
    double cbias = getbed64(buf, 16);            // clock bias, meters
2632
321
    double ftow = getbef32(buf, 32);             // time-of-fix, s
2633
2634
321
    session->newdata.latitude = lat;
2635
321
    session->newdata.longitude =lon;
2636
321
    if (0 == session->driver.tsip.alt_is_msl) {
2637
248
        session->newdata.altHAE = d1;
2638
248
    } else {
2639
73
        session->newdata.altMSL = d1;
2640
73
    }
2641
321
    mask |= ALTITUDE_SET;
2642
2643
    // short circuit to gpsdata. Convert m to ns
2644
321
    session->gpsdata.fix.clockbias = 1e9 * cbias / CLIGHT;
2645
2646
321
    if (0 != (session->context->valid & GPS_TIME_VALID)) {
2647
        // fingers crossed receiver set to UTC, not GPS.
2648
282
        DTOTS(&ts_tow, ftow);
2649
282
        session->newdata.time =
2650
282
            gpsd_gpstime_resolv(session, session->context->gps_week,
2651
282
                                ts_tow);
2652
282
        mask |= TIME_SET | NTPTIME_IS;
2653
282
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2654
226
            mask |= CLEAR_IS;
2655
226
            session->driver.tsip.last_tow = ts_tow;
2656
226
        }
2657
282
    }
2658
321
    mask |= LATLON_SET;
2659
    /* No fix mode info!! That comes later in 0x6d.
2660
     * Message sent when there is 2D or 3D fix.
2661
     * This is a problem as gpsd will send a report with no mode.
2662
     * This message only sent on 2D or 3D fix.
2663
     * Steal mode from last fix. */
2664
321
    session->newdata.status = session->oldfix.status;
2665
321
    session->newdata.mode = session->oldfix.mode;
2666
321
    mask |= STATUS_SET | MODE_SET;
2667
2668
321
    GPSD_LOG(LOG_PROG, &session->context->errout,
2669
321
             "TSIP x84: DP-LLA: time=%s lat=%.2f lon=%.2f alt=%.2f %s "
2670
321
             "cbias %.2f\n",
2671
321
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
2672
321
             session->newdata.latitude,
2673
321
             session->newdata.longitude, d1,
2674
321
             session->driver.tsip.alt_is_msl ? "MSL" : "HAE", cbias);
2675
321
    GPSD_LOG(LOG_IO, &session->context->errout,
2676
321
             "TSIP: mode:%s status:%s\n",
2677
321
             val2str(session->newdata.mode, vmode_str),
2678
321
             val2str(session->newdata.status, vstatus_str));
2679
321
    return mask;
2680
321
}
2681
2682
/* decode Superpacket x8f-15
2683
*/
2684
static gps_mask_t decode_x8f_15(struct gps_device_t *session, const char *buf)
2685
34
{
2686
34
    gps_mask_t mask = 0;
2687
34
    int s1 = getbes16(buf, 1);                 // Datum Index
2688
34
    double d1 = getbed64(buf, 3);              // DX
2689
34
    double d2 = getbed64(buf, 11);             // DY
2690
34
    double d3 = getbed64(buf, 19);             // DZ
2691
34
    double d4 = getbed64(buf, 27);             // A-axis
2692
34
    double d5 = getbed64(buf, 35);             // Eccentricity Squared
2693
2694
34
    GPSD_LOG(LOG_PROG, &session->context->errout,
2695
34
             "TSIP x8f-15: Current Datum: %d %f %f %f %f %f\n",
2696
34
             s1, d1, d2, d3, d4, d5);
2697
34
    return mask;
2698
34
}
2699
2700
/* decode Last Fix with Extra Information, Superpacket x8f-20
2701
 */
2702
static gps_mask_t decode_x8f_20(struct gps_device_t *session, const char *buf,
2703
                                const unsigned length)
2704
391
{
2705
391
    gps_mask_t mask = 0;
2706
391
    double d1, d2, d3, d4;
2707
391
    timespec_t ts_tow;
2708
391
    char buf2[80];
2709
391
    char buf3[160];
2710
391
    char ts_buf[TIMESPEC_LEN];
2711
391
    unsigned i;
2712
2713
391
    int s1 = getbes16(buf, 2);                // east velocity
2714
391
    int s2 = getbes16(buf, 4);                // north velocity
2715
391
    int s3 = getbes16(buf, 6);                // up velocity
2716
391
    unsigned long tow = getbeu32(buf, 8);     // time in ms
2717
391
    long lat = getbes32(buf, 12);             // latitude
2718
391
    unsigned long lon = getbeu32(buf, 16);    // longitude
2719
    // Lassen iQ, and copernicus (ii) doc says this is always altHAE
2720
391
    long alt = getbes32(buf, 20);             // altitude
2721
391
    unsigned u1 = getub(buf, 24);             // velocity scaling
2722
391
    unsigned datum = getub(buf, 26);          // Datum + 1
2723
391
    unsigned fflags = getub(buf, 27);         // fix flags
2724
391
    unsigned numSV = getub(buf, 28);          // num svs
2725
391
    unsigned ls = getub(buf, 29);             // utc offset (leap seconds)
2726
391
    unsigned week = getbeu16(buf, 30);        // tsip.gps_week
2727
2728
    // PRN/IODE data follows
2729
2730
391
    if (0 != (u1 & 0x01)) {     // check velocity scaling
2731
140
        d4 = 0.02;
2732
251
    } else {
2733
251
        d4 = 0.005;
2734
251
    }
2735
2736
    // 0x8000 is over-range
2737
391
    if ((int)0x8000 != s2) {
2738
391
        d2 = (double)s2 * d4;   // north velocity m/s
2739
391
        session->newdata.NED.velN = d2;
2740
391
    }
2741
391
    if ((int16_t)0x8000 != s1) {
2742
356
        d1 = (double)s1 * d4;   // east velocity m/s
2743
356
        session->newdata.NED.velE = d1;
2744
356
    }
2745
391
    if ((int16_t)0x8000 != s3) {
2746
369
        d3 = (double)s3 * d4;       // up velocity m/s
2747
369
        session->newdata.NED.velD = -d3;
2748
369
    }
2749
2750
391
    session->newdata.latitude = (double)lat * SEMI_2_DEG;
2751
391
    session->newdata.longitude = (double)lon * SEMI_2_DEG;
2752
2753
391
    if (180.0 < session->newdata.longitude) {
2754
136
        session->newdata.longitude -= 360.0;
2755
136
    }
2756
    // Lassen iQ doc says this is always altHAE in mm
2757
391
    session->newdata.altHAE = (double)alt * 1e-3;
2758
391
    mask |= ALTITUDE_SET;
2759
2760
391
    session->newdata.status = STATUS_UNK;
2761
391
    session->newdata.mode = MODE_NO_FIX;
2762
391
    if ((uint8_t)0 == (fflags & 0x01)) {          // Fix Available
2763
222
        session->newdata.status = STATUS_GPS;
2764
222
        if ((uint8_t)0 != (fflags & 0x02)) {      // DGPS Corrected
2765
57
            session->newdata.status = STATUS_DGPS;
2766
57
        }
2767
222
        if ((uint8_t)0 != (fflags & 0x04)) {      // Fix Dimension
2768
97
            session->newdata.mode = MODE_2D;
2769
125
        } else {
2770
125
            session->newdata.mode = MODE_3D;
2771
125
        }
2772
222
    }
2773
391
    session->gpsdata.satellites_used = numSV;
2774
391
    if (10 < ls) {
2775
310
        session->context->leap_seconds = ls;
2776
310
        session->context->valid |= LEAP_SECOND_VALID;
2777
        /* check for week rollover
2778
         * Trimble uses 15 bit weeks, but can guess the epoch wrong
2779
         * Can not be in gpsd_gpstime_resolv() because that
2780
         * may see BUILD_LEAPSECONDS instead of leap_seconds
2781
         * from receiver.
2782
         */
2783
310
        if (17 < ls &&
2784
276
            1930 > week) {
2785
            // leap second 18 added in gps week 1930
2786
104
            week += 1024;
2787
104
            if (1930 > week) {
2788
                // and again?
2789
62
                week += 1024;
2790
62
            }
2791
104
        }
2792
310
    }
2793
391
    MSTOTS(&ts_tow, tow);
2794
391
    session->newdata.time = gpsd_gpstime_resolv(session, week,
2795
391
                                                ts_tow);
2796
391
    mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
2797
391
            STATUS_SET | MODE_SET | VNED_SET;
2798
391
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2799
306
        mask |= CLEAR_IS;
2800
306
        session->driver.tsip.last_tow = ts_tow;
2801
306
    }
2802
2803
391
    memset(session->driver.tsip.sats_used, 0,
2804
391
           sizeof(session->driver.tsip.sats_used));
2805
391
    buf3[0] = '\0';
2806
391
    if (MAXCHANNELS < numSV) {
2807
        // should not happen, pacify Coverity 493012
2808
48
        GPSD_LOG(LOG_WARN, &session->context->errout,
2809
48
                 "TSIP x8f-20: MAXCHANNELS < numSV (%d)\n", numSV);
2810
48
        return 0;
2811
48
    }
2812
3.28k
    for (i = 0; i < numSV; i++) {
2813
3.14k
        if (length < (33 + (i * 2))) {
2814
            // too short
2815
209
            break;
2816
209
        }
2817
        // bits 0 to 5, junk in 5 to 7
2818
2.93k
        int PRN = getub(buf, 32 + (i * 2)) & 0x1f;
2819
2.93k
        int IODE = getub(buf, 33 + (i * 2));
2820
2821
2.93k
        session->driver.tsip.sats_used[i] = PRN;
2822
2.93k
        if (LOG_PROG <= session->context->errout.debug) {
2823
0
            str_appendf(buf3, sizeof(buf3),
2824
0
                           " %d (%d)", session->driver.tsip.sats_used[i], IODE);
2825
0
        }
2826
2.93k
    }
2827
2828
343
    GPSD_LOG(LOG_PROG, &session->context->errout,
2829
343
             "TSIP x8f-20: LFwEI: %d %d %d tow %lu %ld "
2830
343
             " %lu %lu %x fflags %x numSV %u ls %u week %d datum %u used:%s\n",
2831
343
             s1, s2, s3, tow, lat, lon, alt, u1, fflags, numSV,
2832
343
             ls, week, datum, buf3);
2833
343
    GPSD_LOG(LOG_PROG, &session->context->errout,
2834
343
             "TSIP x8f-20: LFwEI: time=%s lat=%.2f lon=%.2f "
2835
343
             "altHAE=%.2f mode=%d status=%d\n",
2836
343
             timespec_str(&session->newdata.time, ts_buf,
2837
343
                          sizeof(ts_buf)),
2838
343
             session->newdata.latitude, session->newdata.longitude,
2839
343
             session->newdata.altHAE,
2840
343
             session->newdata.mode, session->newdata.status);
2841
343
    GPSD_LOG(LOG_IO, &session->context->errout,
2842
343
             "TSIP: flags:%s\n",
2843
343
             flags2str(fflags, vx8f_20_fflags, buf2, sizeof(buf2)));
2844
343
    return mask;
2845
391
}
2846
2847
/* decode Packet Broadcast Mask: Superpacket x8f-23
2848
 */
2849
static gps_mask_t decode_x8f_23(struct gps_device_t *session, const char *buf)
2850
686
{
2851
686
    gps_mask_t mask = 0;
2852
686
    double d1, d2, d3, d5;
2853
686
    timespec_t ts_tow;
2854
686
    char ts_buf[TIMESPEC_LEN];
2855
2856
686
    unsigned long tow = getbeu32(buf, 1);    // time in ms
2857
686
    unsigned week = getbeu16(buf, 5);        // tsip.gps_week
2858
686
    unsigned u1 = getub(buf, 7);             // utc offset
2859
686
    unsigned u2 = getub(buf, 8);             // fix flags
2860
686
    long lat = getbes32(buf, 9);             // latitude
2861
686
    unsigned long lon = getbeu32(buf, 13);   // longitude
2862
    // Copernicus (ii) doc says this is always altHAE in mm
2863
686
    long alt = getbes32(buf, 17);            // altitude
2864
    // set xNED here
2865
686
    int s2 = getbes16(buf, 21);              // east velocity
2866
686
    int s3 = getbes16(buf, 23);              // north velocity
2867
686
    int s4 = getbes16(buf, 25);              // up velocity
2868
2869
686
    GPSD_LOG(LOG_PROG, &session->context->errout,
2870
686
             "TSIP x8f-23: CSP: tow %lu week %u %u %u %ld %lu %ld "
2871
686
             " %d %d %d\n",
2872
686
             tow, week, u1, u2, lat, lon, alt, s2, s3, s4);
2873
686
    if (10 < (int)u1) {
2874
439
        session->context->leap_seconds = (int)u1;
2875
439
        session->context->valid |= LEAP_SECOND_VALID;
2876
439
    }
2877
686
    MSTOTS(&ts_tow, tow);
2878
686
    session->newdata.time =
2879
686
        gpsd_gpstime_resolv(session, week, ts_tow);
2880
686
    session->newdata.status = STATUS_UNK;
2881
686
    session->newdata.mode = MODE_NO_FIX;
2882
686
    if ((u2 & 0x01) == (uint8_t)0) {          // Fix Available
2883
508
        session->newdata.status = STATUS_GPS;
2884
508
        if ((u2 & 0x02) != (uint8_t)0) {      // DGPS Corrected
2885
151
            session->newdata.status = STATUS_DGPS;
2886
151
        }
2887
508
        if ((u2 & 0x04) != (uint8_t)0) {       // Fix Dimension
2888
148
            session->newdata.mode = MODE_2D;
2889
360
        } else {
2890
360
            session->newdata.mode = MODE_3D;
2891
360
        }
2892
508
    }
2893
686
    session->newdata.latitude = (double)lat * SEMI_2_DEG;
2894
686
    session->newdata.longitude = (double)lon * SEMI_2_DEG;
2895
686
    if (180.0 < session->newdata.longitude) {
2896
193
        session->newdata.longitude -= 360.0;
2897
193
    }
2898
    // Copernicus (ii) doc says this is always altHAE in mm
2899
686
    session->newdata.altHAE = (double)alt * 1e-3;
2900
686
    mask |= ALTITUDE_SET;
2901
686
    if ((u2 & 0x20) != (uint8_t)0) {     // check velocity scaling
2902
260
        d5 = 0.02;
2903
426
    } else {
2904
426
        d5 = 0.005;
2905
426
    }
2906
686
    d1 = (double)s2 * d5;       // east velocity m/s
2907
686
    d2 = (double)s3 * d5;       // north velocity m/s
2908
686
    d3 = (double)s4 * d5;       // up velocity m/s
2909
686
    session->newdata.NED.velN = d2;
2910
686
    session->newdata.NED.velE = d1;
2911
686
    session->newdata.NED.velD = -d3;
2912
2913
686
    mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
2914
686
            STATUS_SET | MODE_SET | VNED_SET;
2915
686
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2916
587
        mask |= CLEAR_IS;
2917
587
        session->driver.tsip.last_tow = ts_tow;
2918
587
    }
2919
686
    session->driver.tsip.req_compact = 0;
2920
686
    GPSD_LOG(LOG_PROG, &session->context->errout,
2921
686
             "TSIP x8f-23: SP-CSP: time %s lat %.2f lon %.2f "
2922
686
             "altHAE %.2f mode %d status %d\n",
2923
686
             timespec_str(&session->newdata.time, ts_buf,
2924
686
                          sizeof(ts_buf)),
2925
686
             session->newdata.latitude, session->newdata.longitude,
2926
686
             session->newdata.altHAE,
2927
686
             session->newdata.mode, session->newdata.status);
2928
686
    return mask;
2929
686
}
2930
2931
/* decode Superpacket x8f-42
2932
 */
2933
static gps_mask_t decode_x8f_42(struct gps_device_t *session, const char *buf)
2934
67
{
2935
67
    gps_mask_t mask = 0;
2936
2937
67
    unsigned u1 = getub(buf, 1);                 // Production Options Prefix
2938
67
    unsigned u2 = getub(buf, 2);                 // Production Number Extension
2939
67
    unsigned u3 = getbeu16(buf, 3);              // Case Sernum Prefix
2940
67
    unsigned long ul1 = getbeu32(buf, 5);        // Case Sernum
2941
67
    unsigned long ul2 = getbeu32(buf, 9);        // Production Number
2942
67
    unsigned long ul3 = getbeu32(buf, 13);       // Reserved
2943
67
    unsigned u4 = getbeu16(buf, 15);             // Machine ID
2944
67
    unsigned u5 = getbeu16(buf, 17);             // Reserved
2945
2946
67
    GPSD_LOG(LOG_PROG, &session->context->errout,
2947
67
             "TSIP x8f-42: SPP: Prod x%x-%x Sernum %x-%lx "
2948
67
             "Prod %lx  Res %lx ID %x Res %x\n",
2949
67
             u1, u2, u3, ul1, ul2, ul3, u4, u5);
2950
67
    return mask;
2951
67
}
2952
2953
/* decode Packet Broadcast Mask: Superpacket x8f-ad
2954
 */
2955
static gps_mask_t decode_x8f_a5(struct gps_device_t *session, const char *buf)
2956
69
{
2957
69
    gps_mask_t mask = 0;
2958
69
    uint16_t mask0, mask1;
2959
69
    char buf2[40];
2960
2961
69
    mask0 = getbeu16(buf, 1);    // Mask 0
2962
69
    mask1 = getbeu16(buf, 3);    // Mask 1, reserved in ResSMT 360
2963
69
    GPSD_LOG(LOG_PROG, &session->context->errout,
2964
69
             "TSIP x8f-a5: PBM: mask0 x%04x mask1 x%04x\n",
2965
69
             mask0, mask1);
2966
69
    GPSD_LOG(LOG_IO, &session->context->errout,
2967
69
             "TSIP: mask0::%s\n",
2968
69
             flags2str(mask0, vpbm_mask0, buf2, sizeof(buf2)));
2969
2970
69
    return mask;
2971
69
}
2972
2973
/* decode Superpacket x8f-a6
2974
 */
2975
static gps_mask_t decode_x8f_a6(struct gps_device_t *session, const char *buf)
2976
71
{
2977
71
    gps_mask_t mask = 0;
2978
71
    unsigned u1 = getub(buf, 1);          // Command
2979
71
    unsigned u2 = getub(buf, 2);          // Status
2980
2981
71
    GPSD_LOG(LOG_PROG, &session->context->errout,
2982
71
             "TSIP x8f-a6: SSC: command x%x status x%x\n",
2983
71
             u1, u2);
2984
71
    return mask;
2985
71
}
2986
2987
/* decode Superpacket x8f-a7
2988
 * Individual Satellite Solutions
2989
 *
2990
 * Present in:
2991
 *   Thunderbolt
2992
 * Not present in:
2993
 *   THunderbolt E
2994
 *
2995
 */
2996
static gps_mask_t decode_x8f_a7(struct gps_device_t *session, const char *buf,
2997
                                const unsigned length)
2998
199
{
2999
199
    gps_mask_t mask = 0;
3000
3001
    // we assume the receiver not in some crazy mode, and is GPS time
3002
199
    unsigned long tow = getbeu32(buf, 2);         // gpstime in seconds
3003
199
    unsigned fmt = buf[1];                        // format, 0 Float, 1 Int
3004
3005
199
    if (0 == fmt) {
3006
        // floating point mode
3007
66
        double clock_bias = getbef32(buf, 6);    // clock bias (combined). s
3008
        // clock bias rate (combined), s/s
3009
66
        double clock_rate = getbef32(buf, 10);
3010
3011
        // short circuit to gpsdata
3012
66
        session->gpsdata.fix.clockbias = clock_bias / 1e9;
3013
66
        session->gpsdata.fix.clockdrift = clock_rate / 1e9;
3014
3015
        // FIXME: decode the individual biases
3016
66
        GPSD_LOG(LOG_PROG, &session->context->errout,
3017
66
                 "TSIP x8f-a7: tow %llu fmt %u bias %e "
3018
66
                 "bias rate %e len %d\n",
3019
66
                 (long long unsigned)tow, fmt, clock_bias, clock_rate, length);
3020
133
    } else if (1 == fmt) {
3021
        // integer mode
3022
66
        int clock_bias = getbes16(buf, 6);   // Clock Bias (combined) 0.1ns
3023
66
        int clock_rate = getbes16(buf, 8);   // Clock Bias rate (combined) ps/s
3024
3025
        // short circuit to gpsdata
3026
66
        session->gpsdata.fix.clockbias = clock_bias / 10;
3027
66
        session->gpsdata.fix.clockdrift = clock_rate / 1000;
3028
3029
        // FIXME: decode the individual biases
3030
66
        GPSD_LOG(LOG_PROG, &session->context->errout,
3031
66
                 "TSIP x8f-a7: tow %llu mode %u bias %ld "
3032
66
                 "bias rate %ld len %d\n",
3033
66
                 (long long unsigned)tow, fmt,
3034
66
                 session->gpsdata.fix.clockbias,
3035
66
                 session->gpsdata.fix.clockdrift, length);
3036
67
    } else {
3037
        // unknown mode
3038
67
        GPSD_LOG(LOG_WARN, &session->context->errout,
3039
67
                 "TSIP x8f-a7: tow %llu fmt %u. Unknown mode len %d\n",
3040
67
                 (long long unsigned)tow, fmt, length);
3041
67
    }
3042
    // FIXME: loop over the individual sat data
3043
199
    return mask;
3044
199
}
3045
3046
/* decode Superpacket x8f-a9
3047
 */
3048
static gps_mask_t decode_x8f_a9(struct gps_device_t *session, const char *buf)
3049
67
{
3050
67
    gps_mask_t mask = 0;
3051
3052
67
    unsigned u1 = getub(buf, 1);              // Self Survey Enable
3053
67
    unsigned u2 = getub(buf, 2);              // Position Save Flag
3054
67
    unsigned long u3 = getbeu32(buf, 3);      // Self Survey Length
3055
67
    unsigned long u4 = getbeu32(buf, 7);      // Reserved
3056
3057
67
    GPSD_LOG(LOG_WARN, &session->context->errout,
3058
67
             "TSIP x8f-a9 SSP: sse %u psf %u length %ld rex x%lx \n",
3059
67
             u1, u2, u3, u4);
3060
67
    GPSD_LOG(LOG_IO, &session->context->errout,
3061
67
             "TSIP: sse:%s sssave:%s\n",
3062
67
             val2str(u1, vss_enable),
3063
67
             val2str(u2, vss_save));
3064
67
    return mask;
3065
67
}
3066
3067
/* decode Superpacket x8f-ab
3068
 * Oddly, no flag to say if the time is valid...
3069
 */
3070
static gps_mask_t decode_x8f_ab(struct gps_device_t *session, const char *buf)
3071
513
{
3072
513
    gps_mask_t mask = 0;
3073
513
    unsigned long tow;                 // time of week in milli seconds
3074
513
    timespec_t ts_tow;
3075
513
    unsigned short week;
3076
513
    char ts_buf[TIMESPEC_LEN];
3077
513
    unsigned time_flag;
3078
513
    char buf2[BUFSIZ];
3079
3080
    // we assume the receiver not in some crazy mode, and is GPS time
3081
513
    tow = getbeu32(buf, 1);             // gpstime in seconds
3082
513
    ts_tow.tv_sec = tow;
3083
513
    ts_tow.tv_nsec = 0;
3084
513
    week = getbeu16(buf, 5);            // week
3085
    // leap seconds
3086
513
    session->context->leap_seconds = (int)getbes16(buf, 7);
3087
513
    time_flag = buf[9];                // Time Flag
3088
    /* ignore the broken down time, use the GNSS time.
3089
     * Hope it is not BeiDou time */
3090
3091
513
    if (1 == (time_flag & 1)) {
3092
        // time is UTC, have leap seconds.
3093
133
        session->context->valid |= LEAP_SECOND_VALID;
3094
380
    } else {
3095
        // time is GPS
3096
380
        if (0 == (time_flag & 8)) {
3097
            // have leap seconds.
3098
209
            session->context->valid |= LEAP_SECOND_VALID;
3099
209
        }
3100
380
    }
3101
513
    if (0 == (time_flag & 0x14)) {
3102
        // time it good, not in test mode
3103
205
        session->newdata.time = gpsd_gpstime_resolv(session, week,
3104
205
                                                    ts_tow);
3105
205
        mask |= TIME_SET | NTPTIME_IS;
3106
308
    } else {
3107
        // time is bad
3108
308
    }
3109
3110
513
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
3111
427
        mask |= CLEAR_IS;
3112
427
        session->driver.tsip.last_tow = ts_tow;
3113
427
    }
3114
3115
    /* since we compute time from weeks and tow, we ignore the
3116
     * supplied H:M:S M/D/Y */
3117
513
    GPSD_LOG(LOG_PROG, &session->context->errout,
3118
513
             "TSIP x8f-ab: SP-TTS: tow %lu wk %u ls %d flag x%x "
3119
513
             "time %s mask %s\n",
3120
513
             tow, week, session->context->leap_seconds, time_flag,
3121
513
             timespec_str(&session->newdata.time, ts_buf,
3122
513
                          sizeof(ts_buf)),
3123
513
             gps_maskdump(mask));
3124
513
    GPSD_LOG(LOG_IO, &session->context->errout,
3125
513
             "TSIP: tf:%s\n",
3126
513
             flags2str(time_flag, vtiming, buf2, sizeof(buf2)));
3127
3128
513
    return mask;
3129
513
}
3130
3131
/* decode Supplemental Timing Packet (0x8f-ac)
3132
 * present in:
3133
 *   ThunderboltE
3134
 *   ICM SMT 360
3135
 *   RES SMT 360
3136
 *   Resolution SMTx
3137
 * Not Present in:
3138
 *   pre-2000 models
3139
 *   Lassen iQ
3140
 *   Copernicus II (2009)
3141
 */
3142
static gps_mask_t decode_x8f_ac(struct gps_device_t *session, const char *buf)
3143
228
{
3144
228
    gps_mask_t mask = 0;
3145
228
    char buf2[BUFSIZ];
3146
228
    char buf3[BUFSIZ];
3147
3148
    // byte 0 is Subpacket ID
3149
228
    unsigned rec_mode = getub(buf, 1);         // Receiver Mode
3150
    // Disciplining Mode, ICM SMT 360 only
3151
228
    unsigned disc_mode = getub(buf, 2);
3152
    // Self-Survey Progress
3153
228
    unsigned survey_prog = getub(buf, 3);
3154
    // ignore 4-7, Holdover Duration, reserved on Resolution SMTx
3155
    // ignore 8-9, Critical Alarms, reserved on Resolution SMTx
3156
228
    unsigned crit_alarm = getbeu16(buf, 8);
3157
    // Minor Alarms
3158
228
    unsigned minor_alarm = getbeu16(buf, 10);
3159
228
    unsigned decode_stat = getub(buf, 12);        // GNSS Decoding Status
3160
    // Disciplining Activity, ICM SMT 360 Only
3161
228
    unsigned disc_act = getub(buf, 13);
3162
    // PPS indication, RES SMT 360 Only
3163
228
    unsigned pps_ind = getub(buf, 14);
3164
228
    unsigned pps_ref = getub(buf, 15);            // PPS reference
3165
    /* PPS Offset in ns
3166
     * save as (long)pico seconds
3167
     * can't really use it as it is not referenced to any PPS */
3168
228
    double fqErr = getbef32(buf, 16);          // PPS Offset. positive is slow.
3169
    // Clock Offset (bias) ns. same as ppb
3170
228
    double clk_off = getbef32(buf, 20);
3171
    // ignore 24-27, DAC Value (ICM SMT 360 Only)
3172
228
    double dac_v = getbef32(buf, 28);          // DAC Voltage
3173
    // 32-35, Temperature degrees C
3174
228
    session->newdata.temp = getbef32(buf, 32);
3175
228
    session->newdata.latitude = getbed64(buf, 36) * RAD_2_DEG;
3176
228
    session->newdata.longitude = getbed64(buf, 44) * RAD_2_DEG;
3177
    // SMT 360 doc says this is always altHAE in meters
3178
228
    session->newdata.altHAE = getbed64(buf, 52);
3179
    // ignore 60-63, always zero, PPS Quanization error, ns ?
3180
    // ignore 64-67, reserved
3181
3182
228
    switch (minor_alarm & 6) {
3183
21
    case 2:
3184
21
        session->newdata.ant_stat = ANT_OPEN;
3185
21
        break;
3186
46
    case 4:
3187
46
        session->newdata.ant_stat = ANT_SHORT;
3188
46
        break;
3189
161
    default:
3190
161
        session->newdata.ant_stat = ANT_OK;
3191
161
        break;
3192
228
    }
3193
3194
228
    session->gpsdata.qErr = (long)(fqErr * 1000);
3195
    // short circuit to gpsdata.
3196
228
    session->gpsdata.fix.clockbias = clk_off;
3197
3198
    // PPS indication
3199
228
    if (3026 == session->driver.tsip.hardware_code) {
3200
        // only ICM SMT 360 has disciplining activity
3201
        // disc_act = 10;
3202
0
    }
3203
    // We don;t know enough to set status, probably TIME_TIME
3204
3205
    // Decode Fix modes
3206
228
    switch (rec_mode & 7) {
3207
54
    case 0:     // Auto
3208
        /*
3209
        * According to the Thunderbolt Manual, the
3210
        * first byte of the supplemental timing packet
3211
        * simply indicates the configuration of the
3212
        * device, not the actual lock, so we need to
3213
        * look at the decode status.
3214
        */
3215
54
        switch (decode_stat) {
3216
18
        case 0:   // "Doing Fixes"
3217
18
            session->newdata.mode = MODE_3D;
3218
18
            break;
3219
18
        case 0x0B: // "Only 3 usable sats"
3220
18
            session->newdata.mode = MODE_2D;
3221
18
            break;
3222
0
        case 0x1:   // "Don't have GPS time"
3223
0
            FALLTHROUGH
3224
0
        case 0x3:   // "PDOP is too high"
3225
0
            FALLTHROUGH
3226
0
        case 0x8:   // "No usable sats"
3227
0
            FALLTHROUGH
3228
0
        case 0x9:   // "Only 1 usable sat"
3229
0
            FALLTHROUGH
3230
0
        case 0x0A:  // "Only 2 usable sats
3231
0
            FALLTHROUGH
3232
0
        case 0x0C:  // "The chosen sat is unusable"
3233
0
            FALLTHROUGH
3234
0
        case 0x10:  // TRAIM rejected the fix
3235
0
            FALLTHROUGH
3236
18
        default:
3237
18
            session->newdata.mode = MODE_NO_FIX;
3238
18
            break;
3239
54
        }
3240
54
        break;
3241
54
    case 6:             // Clock Hold 2D
3242
        /* Not present:
3243
         *   SMT 360
3244
         *   Acutime 360
3245
         */
3246
18
        FALLTHROUGH
3247
36
    case 3:             // forced 2D Position Fix
3248
        // Does this mean STATUS_TIME?
3249
36
        session->newdata.mode = MODE_2D;
3250
36
        break;
3251
73
    case 1:             // Single Satellite Time
3252
        /* Present in:
3253
         *   Acutime 360
3254
         */
3255
73
        FALLTHROUGH
3256
102
    case 7:             // overdetermined clock
3257
        /* Present in:
3258
         *   Acutiome 360
3259
         *   ResSMT360
3260
         *   Resolution SMTx
3261
         */
3262
        /*
3263
        * According to the Thunderbolt Manual, the
3264
        * first byte of the supplemental timing packet
3265
        * simply indicates the configuration of the
3266
        * device, not the actual lock, so we need to
3267
        * look at the decode status.
3268
        */
3269
102
        session->newdata.status = STATUS_TIME;
3270
102
        switch (decode_stat) {
3271
25
        case 0:   // "Doing Fixes"
3272
25
            session->newdata.mode = MODE_3D;
3273
25
            break;
3274
19
        case 0x9:   // "Only 1 usable sat"
3275
19
            FALLTHROUGH
3276
37
        case 0x0A:  // "Only 2 usable sats
3277
37
            FALLTHROUGH
3278
55
        case 0x0B: // "Only 3 usable sats"
3279
55
            session->newdata.mode = MODE_2D;
3280
55
            break;
3281
2
        case 0x1:   // "Don't have GPS time"
3282
2
            FALLTHROUGH
3283
2
        case 0x3:   // "PDOP is too high"
3284
2
            FALLTHROUGH
3285
2
        case 0x8:   // "No usable sats"
3286
2
            FALLTHROUGH
3287
2
        case 0x0C:  // "The chosen sat is unusable"
3288
2
            FALLTHROUGH
3289
2
        case 0x10:  // TRAIM rejected the fix
3290
2
            FALLTHROUGH
3291
22
        default:
3292
22
            session->newdata.mode = MODE_NO_FIX;
3293
22
            break;
3294
102
        }
3295
102
        break;
3296
102
    case 4:             // forced 3D position Fix
3297
18
        session->newdata.mode = MODE_3D;
3298
18
        break;
3299
18
    default:
3300
18
        session->newdata.mode = MODE_NO_FIX;
3301
18
        break;
3302
228
    }
3303
228
    if (0 != (0x208 & minor_alarm) &&
3304
142
        7 == (rec_mode & 7)) {
3305
        // OD, No sats or position questionable, must be Dead reckoning
3306
27
        session->newdata.mode = MODE_3D;
3307
27
        session->newdata.status = STATUS_DR;
3308
27
    }
3309
228
    if (STATUS_UNK != session->newdata.status) {
3310
102
        mask |= STATUS_SET;
3311
102
    }
3312
3313
228
    mask |= LATLON_SET | ALTITUDE_SET | MODE_SET;
3314
228
    GPSD_LOG(LOG_PROG, &session->context->errout,
3315
228
             "TSIP x8f-ac: SP-TPS: lat=%.2f lon=%.2f altHAE=%.2f "
3316
228
             "mode %d status %d  temp %.1f disc %u pps_ind %u pps_ref %u "
3317
228
             "fqErr %.4f clko %f DACV %f rm x%x dm %u "
3318
228
             "sp %u ca %x ma x%x gds x%x\n",
3319
228
             session->newdata.latitude,
3320
228
             session->newdata.longitude,
3321
228
             session->newdata.altHAE,
3322
228
             session->newdata.mode,
3323
228
             session->newdata.status,
3324
228
             session->newdata.temp,
3325
228
             disc_act, pps_ind, pps_ref, fqErr, clk_off, dac_v,  rec_mode,
3326
228
             disc_mode, survey_prog, crit_alarm,
3327
228
             minor_alarm, decode_stat);
3328
228
    GPSD_LOG(LOG_IO, &session->context->errout,
3329
228
             "TSIP: mode:%s status:%s rm:%s gds:%s ca:%s ma:%s disc_act %s "
3330
228
             "pps_ing %s pps_ref %s\n",
3331
228
             val2str(session->newdata.mode, vmode_str),
3332
228
             val2str(session->newdata.status, vstatus_str),
3333
228
             val2str(rec_mode, vrec_mode),
3334
228
             val2str(decode_stat, vgnss_decode_status),
3335
228
             flags2str(crit_alarm, vcrit_alarms, buf2,
3336
228
                       sizeof(buf2)),
3337
228
             flags2str(minor_alarm, vminor_alarms, buf3,
3338
228
                       sizeof(buf3)),
3339
228
             val2str(disc_act, vdisc_act),
3340
228
             val2str(pps_ind, vpps_ind),
3341
228
             val2str(pps_ref, vpps_ref));
3342
228
    return mask;
3343
228
}
3344
3345
// decode Superpackets x8f-XX
3346
static gps_mask_t decode_x8f(struct gps_device_t *session, const char *buf,
3347
                             unsigned len, int *pbad_len, time_t now)
3348
3.20k
{
3349
3.20k
    gps_mask_t mask = 0;
3350
3.20k
    int bad_len = 0;
3351
3.20k
    unsigned u1 = getub(buf, 0);
3352
3353
3.20k
    switch (u1) {           // sub-code ID
3354
100
    case 0x15:
3355
        /* Current Datum Values
3356
         * Not Present in:
3357
         *   pre-2000 models
3358
         *   Copernicus II (2009)
3359
         *   ICM SMT 360 (2018)
3360
         *   RES SMT 360 (2018)
3361
         */
3362
100
        if (43 > len) {
3363
66
            bad_len = 43;
3364
66
            break;
3365
66
        }
3366
34
        mask = decode_x8f_15(session, buf);
3367
34
        break;
3368
3369
466
    case 0x20:
3370
        /* Last Fix with Extra Information (binary fixed point) 0x8f-20
3371
         * Only output when fix is available.
3372
         * CSK sez "why does my Lassen SQ output oversize packets?"
3373
         * Present in:
3374
         *   pre-2000 models
3375
         *   ACE II
3376
         *   Copernicus, Copernicus II (64-bytes)
3377
         * Not present in:
3378
         *   ICM SMT 360
3379
         *   RES SMT 360
3380
         */
3381
466
        if (56 != (len) &&
3382
140
            64 != (len)) {
3383
75
            bad_len = 56;
3384
75
            break;
3385
75
        }
3386
391
        mask = decode_x8f_20(session, buf, len);
3387
391
        break;
3388
769
    case 0x23:
3389
        /* Compact Super Packet (0x8f-23)
3390
         * Present in:
3391
         *   Copernicus, Copernicus II
3392
         * Not present in:
3393
         *   pre-2000 models
3394
         *   Lassen iQ
3395
         *   ICM SMT 360
3396
         *   RES SMT 360
3397
         */
3398
        // CSK sez "i don't trust this to not be oversized either."
3399
769
        if (29 > len) {
3400
83
            bad_len = 29;
3401
83
            break;
3402
83
        }
3403
686
        mask = decode_x8f_23(session, buf);
3404
686
        break;
3405
3406
145
    case 0x42:
3407
        /* Stored production parameters
3408
         * Present in:
3409
         *   ICM SMT 360 (2018)
3410
         *   RES SMT 360 (2018)
3411
         *   Resolution SMTx (2013)
3412
         * Not Present in:
3413
         *   pre-2000 models
3414
         *   Copernicus II (2009)
3415
         */
3416
145
        if (19 > len) {
3417
78
            bad_len = 19;
3418
78
            break;
3419
78
        }
3420
67
        mask = decode_x8f_42(session, buf);
3421
67
        break;
3422
136
    case 0xa5:
3423
        /* Packet Broadcast Mask (0x8f-a5) polled by 0x8e-a5
3424
         *
3425
         * Present in:
3426
         *   ICM SMT 360
3427
         *   RES SMT 360
3428
         * Not Present in:
3429
         *   pre-2000 models
3430
         *   Copernicus II (2009)
3431
         *
3432
         * Defaults:
3433
         *   RES SMT 360: 05, 00
3434
         *   Resolution SMTx: 05 00
3435
         */
3436
136
        if (5 > len) {
3437
67
            bad_len = 5;
3438
67
            break;
3439
67
        }
3440
69
        mask = decode_x8f_a5(session, buf);
3441
69
        break;
3442
3443
164
    case 0xa6:
3444
        /* Self-Survey Command (0x8f-a6) polled by 0x8e-a6
3445
         *
3446
         * Present in:
3447
         *   ICM SMT 360
3448
         *   RES SMT 360
3449
         * Not Present in:
3450
         *   pre-2000 models
3451
         *   Copernicus II (2009)
3452
         */
3453
164
        if (3 > len) {
3454
93
            bad_len = 3;
3455
93
            break;
3456
93
        }
3457
71
        mask = decode_x8f_a6(session, buf);
3458
71
        break;
3459
3460
277
    case 0xa7:
3461
        /* Thunderbolt Individual Satellite Solutions
3462
         * partial decode
3463
         */
3464
277
        if (10 > len) {
3465
78
            bad_len = 10;
3466
78
            break;
3467
78
        }
3468
199
        mask = decode_x8f_a7(session, buf, len);
3469
199
        break;
3470
140
    case 0xa9:
3471
        /* Self Survey Parameters
3472
         * Present in:
3473
         *   ICM SMT 360 (2018)
3474
         *   RES SMT 360 (2018)
3475
         *   Resolution SMTx
3476
         * Not Present in:
3477
         *   pre-2000 models
3478
         *   Copernicus II (2009)
3479
         */
3480
140
        if (11 > len) {
3481
73
            bad_len = 11;
3482
73
            break;
3483
73
        }
3484
67
        mask = decode_x8f_a9(session, buf);
3485
67
        break;
3486
602
    case 0xab:
3487
        /* Thunderbolt Timing Superpacket
3488
         * Present in:
3489
         *   Resolution SMTx
3490
         * Not Present in:
3491
         *   pre-2000 models
3492
         *   Copernicus II (2009)
3493
         */
3494
602
        if (17 > len) {
3495
89
            bad_len = 17;
3496
89
            break;
3497
89
        }
3498
513
        session->driver.tsip.last_41 = now; // keep timestamp for request
3499
513
        mask = decode_x8f_ab(session, buf);
3500
513
        break;
3501
3502
296
    case 0xac:
3503
        /* Supplemental Timing Packet (0x8f-ac)
3504
         * present in:
3505
         *   ThunderboltE
3506
         *   ICM SMT 360
3507
         *   RES SMT 360
3508
         *   Resolution SMTx
3509
         * Not Present in:
3510
         *   pre-2000 models
3511
         *   Lassen iQ
3512
         *   Copernicus II (2009)
3513
         */
3514
296
        if (68 > len) {
3515
68
            bad_len = 68;
3516
68
            break;
3517
68
        }
3518
228
        mask = decode_x8f_ac(session, buf);
3519
228
        break;
3520
3521
30
    case 0x02:
3522
        /* UTC Information
3523
         * Present in:
3524
         *   ICM SMT 360 (2018)
3525
         *   RES SMT 360 (2018)
3526
         * Not Present in:
3527
         *   pre-2000 models
3528
         *   Copernicus II (2009)
3529
         */
3530
30
        FALLTHROUGH
3531
30
    case 0x21:
3532
        /* Request accuracy information
3533
         * Present in:
3534
         *   Copernicus II (2009)
3535
         * Not Present in:
3536
         *   pre-2000 models
3537
         */
3538
30
        FALLTHROUGH
3539
30
    case 0x2a:
3540
        /* Request Fix and Channel Tracking info, Type 1
3541
         * Present in:
3542
         *   Copernicus II (2009)
3543
         * Not Present in:
3544
         *   pre-2000 models
3545
         */
3546
30
        FALLTHROUGH
3547
30
    case 0x2b:
3548
        /* Request Fix and Channel Tracking info, Type 2
3549
         * Present in:
3550
         *   Copernicus II (2009)
3551
         * Not Present in:
3552
         *   pre-2000 models
3553
         */
3554
30
        FALLTHROUGH
3555
30
    case 0x41:
3556
        /* Stored manufacturing operating parameters x8f-41
3557
         * Present in:
3558
         *   ICM SMT 360 (2018)
3559
         *   RES SMT 360 (2018)
3560
         * Not Present in:
3561
         *   pre-2000 models
3562
         *   Copernicus II (2009)
3563
         */
3564
30
        FALLTHROUGH
3565
30
    case 0x4a:
3566
        /* PPS characteristics
3567
         * Present in:
3568
         *   ICM SMT 360 (2018)
3569
         *   RES SMT 360 (2018)
3570
         *   Copernicus II (2009)
3571
         * Not Present in:
3572
         *   pre-2000 models
3573
         */
3574
30
        FALLTHROUGH
3575
30
    case 0x4e:
3576
        /* PPS Output options
3577
         * Present in:
3578
         *   ICM SMT 360 (2018)
3579
         *   RES SMT 360 (2018)
3580
         * Not Present in:
3581
         *   pre-2000 models
3582
         *   Copernicus II (2009)
3583
         */
3584
30
        FALLTHROUGH
3585
30
    case 0x4f:
3586
        /* Set PPS Width
3587
         * Present in:
3588
         *   Copernicus II (2009)
3589
         * Not Present in:
3590
         *   pre-2000 models
3591
         *   ICM SMT 360 (2018)
3592
         *   RES SMT 360 (2018)
3593
         */
3594
30
        FALLTHROUGH
3595
30
    case 0x60:
3596
        /* DR Calibration and Status Report
3597
         * Present in:
3598
         *   pre-2000 models
3599
         * Not Present in:
3600
         *   Copernicus II (2009)
3601
         *   ICM SMT 360 (2018)
3602
         *   RES SMT 360 (2018)
3603
         */
3604
30
        FALLTHROUGH
3605
30
    case 0x62:
3606
        /* GPS/DR Position/Velocity Report
3607
         * Present in:
3608
         *   pre-2000 models
3609
         * Not Present in:
3610
         *   Copernicus II (2009)
3611
         *   ICM SMT 360 (2018)
3612
         *   RES SMT 360 (2018)
3613
         */
3614
30
        FALLTHROUGH
3615
30
    case 0x64:
3616
        /* Firmware Version and Configuration Report
3617
         * Present in:
3618
         *   pre-2000 models
3619
         * Not Present in:
3620
         *   Copernicus II (2009)
3621
         *   ICM SMT 360 (2018)
3622
         *   RES SMT 360 (2018)
3623
         */
3624
30
        FALLTHROUGH
3625
30
    case 0x6b:
3626
        /* Last Gyroscope Readings Report
3627
         * Present in:
3628
         *   pre-2000 models
3629
         * Not Present in:
3630
         *   Copernicus II (2009)
3631
         *   ICM SMT 360 (2018)
3632
         *   RES SMT 360 (2018)
3633
         */
3634
30
        FALLTHROUGH
3635
30
    case 0x6d:
3636
        /* Last Odometer Readings Report x8f-6d
3637
         * Present in:
3638
         *   pre-2000 models
3639
         * Not Present in:
3640
         *   Copernicus II (2009)
3641
         *   ICM SMT 360 (2018)
3642
         *   RES SMT 360 (2018)
3643
         */
3644
30
        FALLTHROUGH
3645
33
    case 0x6f:
3646
        /* Firmware Version Name Report
3647
         * Present in:
3648
         *   pre-2000 models
3649
         * Not Present in:
3650
         *   Copernicus II (2009)
3651
         *   ICM SMT 360 (2018)
3652
         *   RES SMT 360 (2018)
3653
         */
3654
33
        FALLTHROUGH
3655
33
    case 0x70:
3656
        /* Beacon Channel Status Report
3657
         * Present in:
3658
         *   pre-2000 models
3659
         * Not Present in:
3660
         *   Copernicus II (2009)
3661
         *   ICM SMT 360 (2018)
3662
         *   RES SMT 360 (2018)
3663
         */
3664
33
        FALLTHROUGH
3665
33
    case 0x71:
3666
        /* DGPS Station Database Reports
3667
         * Present in:
3668
         *   pre-2000 models
3669
         * Not Present in:
3670
         *   Copernicus II (2009)
3671
         *   ICM SMT 360 (2018)
3672
         *   RES SMT 360 (2018)
3673
         */
3674
33
        FALLTHROUGH
3675
33
    case 0x73:
3676
        /* Beacon Channel Control Acknowledgment
3677
         * Present in:
3678
         *   pre-2000 models
3679
         * Not Present in:
3680
         *   Copernicus II (2009)
3681
         *   ICM SMT 360 (2018)
3682
         *   RES SMT 360 (2018)
3683
         */
3684
33
        FALLTHROUGH
3685
33
    case 0x74:
3686
        /* Clear Beacon Database Acknowledgment
3687
         * Present in:
3688
         *   pre-2000 models
3689
         * Not Present in:
3690
         *   Copernicus II (2009)
3691
         *   ICM SMT 360 (2018)
3692
         *   RES SMT 360 (2018)
3693
         */
3694
33
        FALLTHROUGH
3695
33
    case 0x75:
3696
        /* FFT Start Acknowledgment
3697
         * Present in:
3698
         *   pre-2000 models
3699
         * Not Present in:
3700
         *   Copernicus II (2009)
3701
         *   ICM SMT 360 (2018)
3702
         *   RES SMT 360 (2018)
3703
         */
3704
33
        FALLTHROUGH
3705
33
    case 0x76:
3706
        /* FFT Stop Acknowledgment
3707
         * Present in:
3708
         *   pre-2000 models
3709
         * Not Present in:
3710
         *   Copernicus II (2009)
3711
         *   ICM SMT 360 (2018)
3712
         *   RES SMT 360 (2018)
3713
         */
3714
33
        FALLTHROUGH
3715
33
    case 0x77:
3716
        /* FFT Reports
3717
         * Present in:
3718
         *   pre-2000 models
3719
         * Not Present in:
3720
         *   Copernicus II (2009)
3721
         *   ICM SMT 360 (2018)
3722
         *   RES SMT 360 (2018)
3723
         */
3724
33
        FALLTHROUGH
3725
33
    case 0x78:
3726
        /* RTCM Reports
3727
         * Present in:
3728
         *   pre-2000 models
3729
         * Not Present in:
3730
         *   Copernicus II (2009)
3731
         *   ICM SMT 360 (2018)
3732
         *   RES SMT 360 (2018)
3733
         */
3734
33
        FALLTHROUGH
3735
33
    case 0x79:
3736
        /* Beacon Station Attributes Acknowledgment
3737
         * Present in:
3738
         *   pre-2000 models
3739
         * Not Present in:
3740
         *   Copernicus II (2009)
3741
         *   ICM SMT 360 (2018)
3742
         *   RES SMT 360 (2018)
3743
         */
3744
33
        FALLTHROUGH
3745
34
    case 0x7a:
3746
        /* Beacon Station Attributes Report
3747
         * Present in:
3748
         *   pre-2000 models
3749
         * Not Present in:
3750
         *   Copernicus II (2009)
3751
         *   ICM SMT 360 (2018)
3752
         *   RES SMT 360 (2018)
3753
         */
3754
34
        FALLTHROUGH
3755
34
    case 0x7b:
3756
        /* DGPS Receiver RAM Configuration Block Report
3757
         * Present in:
3758
         *   pre-2000 models
3759
         * Not Present in:
3760
         *   Copernicus II (2009)
3761
         *   ICM SMT 360 (2018)
3762
         *   RES SMT 360 (2018)
3763
         */
3764
34
        FALLTHROUGH
3765
34
    case 0x7c:
3766
        /* DGPS Receiver Configuration Block Acknowledgment
3767
         * Present in:
3768
         *   pre-2000 models
3769
         * Not Present in:
3770
         *   Copernicus II (2009)
3771
         *   ICM SMT 360 (2018)
3772
         *   RES SMT 360 (2018)
3773
         */
3774
34
        FALLTHROUGH
3775
34
    case 0x7e:
3776
        /* Satellite Line-of-Sight (LOS) Message
3777
         * Present in:
3778
         *   pre-2000 models
3779
         * Not Present in:
3780
         *   Copernicus II (2009)
3781
         *   ICM SMT 360 (2018)
3782
         *   RES SMT 360 (2018)
3783
         */
3784
34
        FALLTHROUGH
3785
34
    case 0x7f:
3786
        /* DGPS Receiver ROM Configuration Block Report
3787
         * Present in:
3788
         *   pre-2000 models
3789
         * Not Present in:
3790
         *   Copernicus II (2009)
3791
         *   ICM SMT 360 (2018)
3792
         *   RES SMT 360 (2018)
3793
         */
3794
34
        FALLTHROUGH
3795
35
    case 0x80:
3796
        /* DGPS Service Provider System Information Report
3797
         * Present in:
3798
         *   pre-2000 models
3799
         * Not Present in:
3800
         *   Copernicus II (2009)
3801
         *   ICM SMT 360 (2018)
3802
         *   RES SMT 360 (2018)
3803
         */
3804
35
        FALLTHROUGH
3805
35
    case 0x81:
3806
        /* Decoder Station Information Report and Selection Acknowledgment
3807
         * Present in:
3808
         *   pre-2000 models
3809
         * Not Present in:
3810
         *   Copernicus II (2009)
3811
         *   ICM SMT 360 (2018)
3812
         *   RES SMT 360 (2018)
3813
         */
3814
35
        FALLTHROUGH
3815
35
    case 0x82:
3816
        /* Decoder Diagnostic Information Report
3817
         * Present in:
3818
         *   pre-2000 models
3819
         * Not Present in:
3820
         *   Copernicus II (2009)
3821
         *   ICM SMT 360 (2018)
3822
         *   RES SMT 360 (2018)
3823
         */
3824
35
        FALLTHROUGH
3825
35
    case 0x84:
3826
        /* Satellite FFT Control Acknowledgment x8f-84
3827
         * Present in:
3828
         *   pre-2000 models
3829
         * Not Present in:
3830
         *   Copernicus II (2009)
3831
         *   ICM SMT 360 (2018)
3832
         *   RES SMT 360 (2018)
3833
         */
3834
35
        FALLTHROUGH
3835
35
    case 0x85:
3836
        /* DGPS Source Tracking Status Report
3837
         * Present in:
3838
         *   pre-2000 models
3839
         * Not Present in:
3840
         *   Copernicus II (2009)
3841
         *   ICM SMT 360 (2018)
3842
         *   RES SMT 360 (2018)
3843
         */
3844
35
        FALLTHROUGH
3845
35
    case 0x86:
3846
        /* Clear Satellite Database Acknowledgment
3847
         * Present in:
3848
         *   pre-2000 models
3849
         * Not Present in:
3850
         *   Copernicus II (2009)
3851
         *   ICM SMT 360 (2018)
3852
         *   RES SMT 360 (2018)
3853
         */
3854
35
        FALLTHROUGH
3855
35
    case 0x87:
3856
        /* Network Statistics Report
3857
         * Present in:
3858
         *   pre-2000 models
3859
         * Not Present in:
3860
         *   Copernicus II (2009)
3861
         *   ICM SMT 360 (2018)
3862
         *   RES SMT 360 (2018)
3863
         */
3864
35
        FALLTHROUGH
3865
35
    case 0x88:
3866
        /* Diagnostic Output Options Report
3867
         * Present in:
3868
         *   pre-2000 models
3869
         * Not Present in:
3870
         *   Copernicus II (2009)
3871
         *   ICM SMT 360 (2018)
3872
         *   RES SMT 360 (2018)
3873
         */
3874
35
        FALLTHROUGH
3875
35
    case 0x89:
3876
        /* DGPS Source Control Report /Acknowledgment
3877
         * Present in:
3878
         *   pre-2000 models
3879
         * Not Present in:
3880
         *   Copernicus II (2009)
3881
         *   ICM SMT 360 (2018)
3882
         *   RES SMT 360 (2018)
3883
         */
3884
35
        FALLTHROUGH
3885
36
    case 0x8a:
3886
        /* Service Provider Information Report and Acknowledgment
3887
         * Present in:
3888
         *   pre-2000 models
3889
         * Not Present in:
3890
         *   Copernicus II (2009)
3891
         *   ICM SMT 360 (2018)
3892
         *   RES SMT 360 (2018)
3893
         */
3894
36
        FALLTHROUGH
3895
36
    case 0x8b:
3896
        /* Service Provider Activation Information Report & Acknowledgment
3897
         * Present in:
3898
         *   pre-2000 models
3899
         * Not Present in:
3900
         *   Copernicus II (2009)
3901
         *   ICM SMT 360 (2018)
3902
         *   RES SMT 360 (2018)
3903
         */
3904
36
        FALLTHROUGH
3905
36
    case 0x8e:
3906
        /* Service Provider Data Load Report
3907
         * Present in:
3908
         *   pre-2000 models
3909
         * Not Present in:
3910
         *   Copernicus II (2009)
3911
         *   ICM SMT 360 (2018)
3912
         *   RES SMT 360 (2018)
3913
         */
3914
36
        FALLTHROUGH
3915
38
    case 0x8f:
3916
        /* Receiver Identity Report
3917
         * Present in:
3918
         *   pre-2000 models
3919
         * Not Present in:
3920
         *   Copernicus II (2009)
3921
         *   ICM SMT 360 (2018)
3922
         *   RES SMT 360 (2018)
3923
         */
3924
38
        FALLTHROUGH
3925
38
    case 0x90:
3926
        /* Guidance Status Report
3927
         * Present in:
3928
         *   pre-2000 models
3929
         * Not Present in:
3930
         *   Copernicus II (2009)
3931
         *   ICM SMT 360 (2018)
3932
         *   RES SMT 360 (2018)
3933
         */
3934
38
        FALLTHROUGH
3935
38
    case 0x91:
3936
        /* Guidance Configuration Report
3937
         * Present in:
3938
         *   pre-2000 models
3939
         * Not Present in:
3940
         *   Copernicus II (2009)
3941
         *   ICM SMT 360 (2018)
3942
         *   RES SMT 360 (2018)
3943
         */
3944
38
        FALLTHROUGH
3945
38
    case 0x92:
3946
        /* Lightbar Configuration Report
3947
         * Present in:
3948
         *   pre-2000 models
3949
         * Not Present in:
3950
         *   Copernicus II (2009)
3951
         *   ICM SMT 360 (2018)
3952
         *   RES SMT 360 (2018)
3953
         */
3954
38
        FALLTHROUGH
3955
38
    case 0x94:
3956
        /* Guidance Operation Acknowledgment
3957
         * Present in:
3958
         *   pre-2000 models
3959
         * Not Present in:
3960
         *   Copernicus II (2009)
3961
         *   ICM SMT 360 (2018)
3962
         *   RES SMT 360 (2018)
3963
         */
3964
38
        FALLTHROUGH
3965
38
    case 0x95:
3966
        /* Button Box Configuration Type Report
3967
         * Present in:
3968
         *   pre-2000 models
3969
         * Not Present in:
3970
         *   Copernicus II (2009)
3971
         *   ICM SMT 360 (2018)
3972
         *   RES SMT 360 (2018)
3973
         */
3974
38
        FALLTHROUGH
3975
38
    case 0x96:
3976
        /* Point Manipulation Report
3977
         * Present in:
3978
         *   pre-2000 models
3979
         * Not Present in:
3980
         *   Copernicus II (2009)
3981
         *   ICM SMT 360 (2018)
3982
         *   RES SMT 360 (2018)
3983
         */
3984
38
        FALLTHROUGH
3985
38
    case 0x97:
3986
        /* Utility Information Report
3987
         * Present in:
3988
         *   pre-2000 models
3989
         * Not Present in:
3990
         *   Copernicus II (2009)
3991
         *   ICM SMT 360 (2018)
3992
         *   RES SMT 360 (2018)
3993
         */
3994
38
        FALLTHROUGH
3995
38
    case 0x98:
3996
        /* Individual Button Configuration Report
3997
         * Present in:
3998
         *   pre-2000 models
3999
         * Not Present in:
4000
         *   Copernicus II (2009)
4001
         *   ICM SMT 360 (2018)
4002
         *   RES SMT 360 (2018)
4003
         */
4004
38
        FALLTHROUGH
4005
38
    case 0x9a:
4006
        /* Differential Correction Information Report
4007
         * Present in:
4008
         *   pre-2000 models
4009
         * Not Present in:
4010
         *   Copernicus II (2009)
4011
         *   ICM SMT 360 (2018)
4012
         *   RES SMT 360 (2018)
4013
         */
4014
38
        FALLTHROUGH
4015
39
    case 0xa0:
4016
        /* DAC value
4017
         * Present in:
4018
         *   ICM SMT 360 (2018)
4019
         *   RES SMT 360 (2018)
4020
         * Not Present in:
4021
         *   pre-2000 models
4022
         *   Copernicus II (2009)
4023
         */
4024
39
        FALLTHROUGH
4025
39
    case 0xa2:
4026
        /* UTC/GPS timing
4027
         * Present in:
4028
         *   ICM SMT 360 (2018)
4029
         *   RES SMT 360 (2018)
4030
         * Not Present in:
4031
         *   pre-2000 models
4032
         *   Copernicus II (2009)
4033
         */
4034
39
        FALLTHROUGH
4035
39
    case 0xa3:
4036
        /* Oscillator disciplining command
4037
         * Present in:
4038
         *   ICM SMT 360 (2018)
4039
         *   RES SMT 360 (2018)
4040
         * Not Present in:
4041
         *   pre-2000 models
4042
         *   Copernicus II (2009)
4043
         */
4044
39
        FALLTHROUGH
4045
39
    case 0xa8:
4046
        /* Oscillator disciplining parameters
4047
         * Present in:
4048
         *   ICM SMT 360 (2018)
4049
         *   RES SMT 360 (2018)
4050
         * Not Present in:
4051
         *   pre-2000 models
4052
         *   Copernicus II (2009)
4053
         */
4054
39
        FALLTHROUGH
4055
113
    default:
4056
113
        GPSD_LOG(LOG_WARN, &session->context->errout,
4057
3.20k
                 "TSIP x8f-%02x: Unhandled TSIP superpacket\n", u1);
4058
3.20k
    }
4059
3.20k
    *pbad_len = bad_len;
4060
4061
3.20k
    return mask;
4062
3.20k
}
4063
4064
// Decode Protocol Versi/on: x90-00
4065
static gps_mask_t decode_x90_00(struct gps_device_t *session, const char *buf)
4066
18
{
4067
18
    gps_mask_t mask = 0;
4068
4069
18
    unsigned u1 = getub(buf, 4);              // NMEA Major version
4070
18
    unsigned u2 = getub(buf, 5);              // NMEA Minor version
4071
18
    unsigned u3 = getub(buf, 6);              // TSIP version
4072
18
    unsigned u4 = getub(buf, 7);              // Trimble NMEA version
4073
18
    unsigned long u6 = getbeu32(buf, 8);      // reserved
4074
18
    unsigned u7 = getub(buf, 12);             // reserved
4075
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4076
18
             "TSIPv1 x90-00: NMEA %u.%u TSIP %u TNMEA %u "
4077
18
             "res x%04lx x%02x \n",
4078
18
             u1, u2, u3, u4, u6, u7);
4079
18
    return mask;
4080
18
}
4081
4082
/* Receiver Version Information, x90-01
4083
 * Received in response to TSIPv1 probe
4084
 */
4085
static gps_mask_t decode_x90_01(struct gps_device_t *session, const char *buf,
4086
                                unsigned len)
4087
86
{
4088
86
    gps_mask_t mask = 0;
4089
86
    char buf2[BUFSIZ];
4090
4091
86
    unsigned u1 = getub(buf, 4);               // Major version
4092
86
    unsigned u2 = getub(buf, 5);               // Minor version
4093
86
    unsigned u3 = getub(buf, 6);               // Build number
4094
86
    unsigned u4 = getub(buf, 7);               // Build month
4095
86
    unsigned u5 = getub(buf, 8);               // Build day
4096
86
    unsigned u6 = getbeu16(buf, 9);            // Build year
4097
86
    unsigned u7 = getbeu16(buf, 11);           // Hardware ID
4098
86
    unsigned u8 = getub(buf, 13);              // Product Name length
4099
4100
86
    session->driver.tsip.hardware_code = u7;
4101
    // check for valid module name length
4102
    // RES720 is 27 long
4103
86
    if ((len - 13) < u8) {
4104
52
        u8 = len - 13;
4105
52
    }
4106
    // check for valid module name length, again
4107
86
    if (40 < u8) {
4108
18
        u8 = 40;
4109
18
    }
4110
  
4111
86
    memcpy(buf2, &buf[14], u8);
4112
86
    buf2[u8] = '\0';
4113
86
    (void)snprintf(session->subtype, sizeof(session->subtype),
4114
86
                   "fw %u.%u %u %02u/%02u/%04u %.40s",
4115
86
                   u1, u2, u3, u6, u5, u4, buf2);
4116
86
    GPSD_LOG(LOG_PROG, &session->context->errout,
4117
86
             "TSIPv1 x90-01: Version %u.%u Build %u %u/%u/%u hwid %u, "
4118
86
             "%.*s[%u]\n",
4119
86
             u1, u2, u3, u6, u5, u4, u7, u8, buf2, u8);
4120
86
    mask |= DEVICEID_SET;
4121
86
    return mask;
4122
86
}
4123
4124
// Decode, Port Configuration: x91-00
4125
static gps_mask_t decode_x91_00(struct gps_device_t *session, const char *buf)
4126
18
{
4127
18
    gps_mask_t mask = 0;
4128
4129
18
    unsigned u1 = getub(buf, 4);               // port
4130
18
    unsigned u2 = getub(buf, 5);               // port type
4131
18
    unsigned u3 = getub(buf, 6);               // protocol
4132
18
    unsigned u4 = getub(buf, 7);               // baud rate
4133
18
    unsigned u5 = getub(buf, 8);               // data bits
4134
18
    unsigned u6 = getub(buf, 9);               // parity
4135
18
    unsigned u7 = getub(buf, 10);              // stop bits
4136
18
    unsigned long u8 = getbeu32(buf, 11);      // reserved
4137
18
    unsigned long u9 = getbeu32(buf, 12);      // reserved
4138
4139
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4140
18
             "TSIPv1 x91-00: port %u type %u proto %u baud %u bits %u "
4141
18
             "parity %u stop %u res x%04lx %04lx\n",
4142
18
             u1, u2, u3, u4, u5, u6, u7, u8, u9);
4143
18
    GPSD_LOG(LOG_IO, &session->context->errout,
4144
18
             "TSIPv1: port:%s type:%s, proto:%s speed:%s bits:%s %s %s\n",
4145
18
             val2str(u1, vport_name1),
4146
18
             val2str(u2, vport_type1),
4147
18
             val2str(u3, vprotocol1),
4148
18
             val2str(u4, vspeed1),
4149
18
             val2str(u5, vdbits1),
4150
18
             val2str(u6, vparity1),
4151
18
             val2str(u6, vstop1));
4152
18
    return mask;
4153
18
}
4154
4155
// Decode GNSS COnfiguration: x91-01
4156
static gps_mask_t decode_x91_01(struct gps_device_t *session, const char *buf)
4157
18
{
4158
18
    gps_mask_t mask = 0;
4159
18
    char buf2[BUFSIZ];
4160
4161
    /* constellations, 0 to 26, mashup of constellation and signal
4162
     * ignore if 0xffffffff */
4163
18
    unsigned long cons = getbeu32(buf, 4);     // constellations
4164
18
    double d1 = getbef32(buf, 8);              // elevation mask
4165
18
    double d2 = getbef32(buf, 12);             // signal mask
4166
18
    double d3 = getbef32(buf, 16);             // PDOP mask
4167
    // anti-jamming, always enabled in RES 720
4168
18
    unsigned u2 = getub(buf, 20);
4169
18
    unsigned u3 = getub(buf, 21);              // fix rate
4170
18
    double d4 = getbef32(buf, 22);             // Antenna CAble delay, seconds
4171
18
    unsigned long u4 = getbeu32(buf, 26);      // reserved
4172
4173
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4174
18
             "TSIPv1 x91-01 cons x%lx el %f signal %f PDOP %f jam %u "
4175
18
             "frate %u delay %f res x%04lx\n",
4176
18
             cons, d1, d2, d3, u2, u3, d4, u4);
4177
18
    GPSD_LOG(LOG_IO, &session->context->errout,
4178
18
             "TSIPv1: cons %s\n",
4179
18
             flags2str(cons, vsv_types1, buf2, sizeof(buf2)));
4180
18
    return mask;
4181
18
}
4182
4183
// Decode NVS Configuration, x91-02
4184
static gps_mask_t decode_x91_02(struct gps_device_t *session, const char *buf)
4185
34
{
4186
34
    gps_mask_t mask = 0;
4187
34
    char buf2[20];
4188
4189
34
    unsigned u1 = getub(buf, 6);               // status
4190
34
    unsigned long u2 = getbeu32(buf, 7);            // reserved
4191
4192
34
    GPSD_LOG(LOG_PROG, &session->context->errout,
4193
34
             "TSIPv1 x91-02: status %u res x%04lx\n",
4194
34
             u1, u2);
4195
34
    GPSD_LOG(LOG_IO, &session->context->errout,
4196
34
             "TSIPv1: Status:%s\n",
4197
34
             flags2str(u1, vsave_status1, buf2, sizeof(buf2)));
4198
34
    return mask;
4199
34
}
4200
4201
// Decode Timing Configuration: x91-03
4202
static gps_mask_t decode_x91_03(struct gps_device_t *session, const char *buf)
4203
18
{
4204
18
    gps_mask_t mask = 0;
4205
4206
18
    unsigned tbase = getub(buf, 4);               // time base
4207
18
    unsigned pbase = getub(buf, 5);               // PPS base
4208
18
    unsigned pmask = getub(buf, 6);               // PPS mask
4209
18
    unsigned res = getbeu16(buf, 7);              // reserved
4210
18
    unsigned pwidth = getbeu16(buf, 9);           // PPS width
4211
18
    double  poffset = getbed64(buf, 11);          // PPS offset, in seconds
4212
4213
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4214
18
             "TSIPv1 x91-03: time base %u PPS base %u mask %u res x%04x "
4215
18
             "width %u offset %f\n",
4216
18
             tbase, pbase, pmask, res, pwidth, poffset);
4217
18
    GPSD_LOG(LOG_IO, &session->context->errout,
4218
18
             "TSIPv1: time base:%s pps base:%s pps mask:%s\n",
4219
18
             val2str(tbase, vtime_base1),
4220
18
             val2str(pbase, vtime_base1),
4221
18
             val2str(pmask, vpps_mask1));
4222
18
    return mask;
4223
18
}
4224
4225
// Decode Self Survey Copnfiguration: x91-04
4226
static gps_mask_t decode_x91_04(struct gps_device_t *session, const char *buf)
4227
18
{
4228
18
    gps_mask_t mask = 0;
4229
18
    char buf2[BUFSIZ];
4230
4231
18
    unsigned u1 = getub(buf, 4);               // self-survey mask
4232
18
    unsigned long u2 = getbeu32(buf, 5);       // self-survey length, # fixes
4233
18
    unsigned u3 = getbeu16(buf, 9);            // horz uncertainty, meters
4234
18
    unsigned u4 = getbeu16(buf, 11);           // vert uncertainty, meters
4235
4236
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4237
18
             "TSIPv1 x91-04: mask x%x length %lu eph %u epv %u\n",
4238
18
             u1, u2, u3, u4);
4239
18
    GPSD_LOG(LOG_IO, &session->context->errout,
4240
18
             "TSIPv1:ssmask %s\n",
4241
18
             flags2str(u1, vss_mask1, buf2, sizeof(buf2)));
4242
18
    return mask;
4243
18
}
4244
4245
// Decode Receiver COnfiguration: x91-05
4246
static gps_mask_t decode_x91_05(struct gps_device_t *session, const char *buf)
4247
34
{
4248
34
    gps_mask_t mask = 0;
4249
4250
34
    unsigned port = getub(buf, 4);              // port
4251
34
    unsigned long otype = getbeu32(buf, 5);     // type of output
4252
34
    unsigned long res1 = getbeu32(buf, 9);      // reserved
4253
34
    unsigned long res2 = getbeu32(buf, 13);     // reserved
4254
34
    unsigned long res3 = getbeu32(buf, 17);     // reserved
4255
4256
34
    GPSD_LOG(LOG_PROG, &session->context->errout,
4257
34
             "TSIPv1 x91-05: port %u type x%04lx res x%04lx x%04lx x%04lx\n",
4258
34
             port, otype, res1, res2, res3);
4259
34
    GPSD_LOG(LOG_IO, &session->context->errout,
4260
34
             "TSIPv1: port %s xa1-00: %lu xa1-03: %lu xa1-11: %lu "
4261
34
             "xa1-00: %lu  xa3-00: %lu  xa3-11: %lu\n",
4262
34
             val2str(port, vport_name1),
4263
34
             otype & 3, (otype >> 2) & 3, (otype >> 4) & 3,
4264
34
            (otype >> 6) & 3, (otype >> 8) & 3, (otype >> 10) & 3);
4265
34
    return mask;
4266
34
}
4267
4268
// Decode Receiver Reset: x92-01
4269
static gps_mask_t decode_x92_01(struct gps_device_t *session, const char *buf)
4270
66
{
4271
66
    gps_mask_t mask = 0;
4272
66
    unsigned u1 = getub(buf, 6);               // reset cause
4273
4274
66
    GPSD_LOG(LOG_WARN, &session->context->errout,
4275
66
             "TSIPv1 x92-01: cause %u\n", u1);
4276
66
    GPSD_LOG(LOG_IO, &session->context->errout,
4277
66
             "TSIPv1: cause:%s\n",
4278
66
             val2str(u1, vreset_type1));
4279
66
    return mask;
4280
66
}
4281
4282
// Decode Production Information: x93-00
4283
static gps_mask_t decode_x93_00(struct gps_device_t *session, const char *buf)
4284
1
{
4285
1
    gps_mask_t mask = 0;
4286
1
    char buf2[BUFSIZ];
4287
1
    char buf3[BUFSIZ];
4288
4289
1
    unsigned u1 = getub(buf, 4);                // reserved. always 0xff
4290
1
    unsigned long u2 = getbeu32(buf, 5);        // serial number
4291
1
    unsigned long long u3 = getbeu64(buf, 9);   // extended serial number
4292
1
    unsigned long long u4 = getbeu64(buf, 17);  // extended serial number
4293
1
    unsigned u5 = getub(buf, 25);               // build day
4294
1
    unsigned u6 = getub(buf, 26);               // build month
4295
1
    unsigned u7 = getbeu16(buf, 27);            // build year
4296
1
    unsigned u8 = getub(buf, 29);               // build hour
4297
1
    unsigned u9 = getbeu16(buf, 30);            // machine id
4298
    // getbeu64(buf, 32);             // hardware ID string
4299
    // getbeu64(buf, 40);             // hardware ID string
4300
    // getbeu64(buf, 48);             // product ID string
4301
    // getbeu64(buf, 56);             // product ID string
4302
1
    unsigned long u10 = getbeu32(buf, 64);       // premium options
4303
1
    unsigned long u11 = getbeu32(buf, 78);       // reserved
4304
    // ignore 77 Osc search range, and 78–81 Osc offset, always 0xff
4305
4306
1
    (void)snprintf(session->subtype1, sizeof(session->subtype1),
4307
1
                   "hw %u %02u/%02u/%04u",
4308
1
                   u9, u5, u6, u7);
4309
    // The sernum I get does not match the printed one on the device...
4310
    // extended sernum seems to be zeros...
4311
1
    (void)snprintf(session->gpsdata.dev.sernum,
4312
1
                   sizeof(session->gpsdata.dev.sernum),
4313
1
                   "%lx", u2);
4314
1
    GPSD_LOG(LOG_WARN, &session->context->errout,
4315
1
             "TSIPv1 x93-00: res %u ser %s x%llx-%llx Build %u/%u/%u %u "
4316
1
             "machine %u hardware %s product %s "
4317
1
             "options x%04lx res x%04lx\n",
4318
1
             u1, session->gpsdata.dev.sernum,
4319
1
             u3, u4, u7, u6, u5, u8, u9,
4320
1
             gpsd_packetdump(buf2, sizeof(buf2),
4321
1
                            (const unsigned char *)&buf[32], 16),
4322
1
             gpsd_packetdump(buf3, sizeof(buf3),
4323
1
                            (const unsigned char *)&buf[48], 16),
4324
1
             u10, u11);
4325
1
    mask |= DEVICEID_SET;
4326
1
    return mask;
4327
1
}
4328
4329
// Decode xa0-00
4330
static gps_mask_t decode_xa0_00(struct gps_device_t *session, const char *buf,
4331
                                unsigned len)
4332
0
{
4333
0
    gps_mask_t mask = 0;
4334
0
    unsigned u1, u2, u3;
4335
4336
0
    switch (len) {
4337
0
    case 3:
4338
0
        u1 = getub(buf, 6);               // command
4339
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
4340
0
                 "TSIPv1 xa0-00: command %u\n", u1);
4341
0
        break;
4342
0
    case 8:
4343
        // ACK/NAK
4344
0
        u1 = getub(buf, 6);               // command
4345
0
        u2 = getub(buf, 7);               // status
4346
0
        u3 = getbeu16(buf, 8);            // frame
4347
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
4348
0
                 "TSIPv1 xa0-00: command %u status %u frame %u\n",
4349
0
                 u1, u2, u3);
4350
0
        break;
4351
0
    default:
4352
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4353
0
                 "TSIPv1 xa0-00: bad length %d\n", len);
4354
0
        break;
4355
0
    }
4356
0
    return mask;
4357
0
}
4358
4359
// Decode xa1-00
4360
static gps_mask_t decode_xa1_00(struct gps_device_t *session, const char *buf)
4361
202
{
4362
202
    gps_mask_t mask = 0;
4363
202
    char buf2[BUFSIZ];
4364
202
    unsigned u1, u2, u3;
4365
202
    int s1;
4366
202
    double d1, d2, d3;
4367
202
    struct tm date = {0};
4368
4369
202
    unsigned tow = getbeu32(buf, 4);
4370
202
    unsigned week = getbeu16(buf, 8);
4371
4372
202
    session->context->gps_week = week;
4373
4374
202
    date.tm_hour = getub(buf, 10);               // hours 0 - 23
4375
202
    date.tm_min = getub(buf, 11);                // minutes 0 -59
4376
202
    date.tm_sec = getub(buf, 12);                // seconds 0 - 60
4377
202
    date.tm_mon = getub(buf, 13) - 1;            // month 1 - 12
4378
202
    date.tm_mday = getub(buf, 14);               // day of month 1 - 31
4379
202
    date.tm_year = getbeu16(buf, 15) - 1900;     // year
4380
4381
202
    u1 = getub(buf, 17);                // time base
4382
202
    u2 = getub(buf, 18);                // PPS base
4383
202
    u3 = getub(buf, 19);                // flags
4384
202
    s1 = getbes16(buf, 20);             // UTC Offset
4385
202
    d1 = getbef32(buf, 22);             // PPS Quantization Error
4386
202
    d2 = getbef32(buf, 26);             // Bias
4387
202
    d3 = getbef32(buf, 30);             // Bias Rate
4388
4389
    // convert seconds to pico seconds
4390
202
    session->gpsdata.qErr = (long)(d1 * 10e12);
4391
    // fix.time is w/o leap seconds...
4392
202
    session->newdata.time.tv_sec = mkgmtime(&date) - s1;
4393
202
    session->newdata.time.tv_nsec = 0;
4394
4395
202
    session->context->leap_seconds = s1;
4396
202
    session->context->valid |= LEAP_SECOND_VALID;
4397
202
    GPSD_LOG(LOG_PROG, &session->context->errout,
4398
202
             "TSIPv1 xa1-00: tow %u week %u %02u:%02u:%02u %4u/%02u/%02u "
4399
202
             "tbase %u/%u tflags x%x UTC offset %d qErr %f Bias %f/%f\n",
4400
202
             tow, week, date.tm_hour, date.tm_min, date.tm_sec,
4401
202
             date.tm_year + 1900, date.tm_mon, date.tm_mday,
4402
202
             u1, u2, u3, s1, d1, d2, d3);
4403
202
    GPSD_LOG(LOG_IO, &session->context->errout,
4404
202
             "TSIPv1: tbase:%s pbase:%s tflags:%s\n",
4405
202
             val2str(u1, vtime_base1),
4406
202
             val2str(u2, vtime_base1),
4407
202
             flags2str(u3, vtime_flags1, buf2, sizeof(buf2)));
4408
4409
202
    if (2 == (u3 & 2)) {
4410
        // flags say we have good time
4411
        // if we have good time, can we guess at fix mode?
4412
138
        mask |= TIME_SET;
4413
138
        if (1 == (u3 & 1)) {
4414
            // good UTC
4415
104
            mask |= NTPTIME_IS;
4416
104
        }
4417
138
    }
4418
202
    if (0 == session->driver.tsip.hardware_code) {
4419
        // Query Receiver Version Information
4420
153
        (void)tsip_write1(session, "\x90\x01\x00\x02\x00\x93", 6);
4421
153
    }
4422
202
    mask |= CLEAR_IS;  // ssems to always be first. Time to clear.
4423
202
    return mask;
4424
202
}
4425
4426
// Decode packet xa1-02
4427
static gps_mask_t decode_xa1_02(struct gps_device_t *session, const char *buf)
4428
18
{
4429
18
    gps_mask_t mask = 0;
4430
4431
18
    double d1 = getbef32(buf, 6);               // DAC voltage
4432
18
    unsigned u1 = getbeu16(buf, 10);            // DAC value
4433
18
    unsigned u2 = getub(buf, 12);               // holdover status
4434
18
    unsigned u3 = getbeu32(buf, 13);            // holdover time
4435
4436
18
    session->newdata.temp = getbef32(buf, 17);  // Temperature, degrees C
4437
18
    GPSD_LOG(LOG_PROG, &session->context->errout,
4438
18
             "TSIPv1 xa1-02: DAC voltage %f value %u Holdover status %u "
4439
18
             "time %u temp %f\n",
4440
18
             d1, u1, u2, u3, session->newdata.temp);
4441
18
    return mask;
4442
18
}
4443
4444
// Decode packet Position Information, xa1-11
4445
static gps_mask_t decode_xa1_11(struct gps_device_t *session, const char *buf)
4446
4
{
4447
4
    gps_mask_t mask = 0;
4448
4
    char buf2[BUFSIZ];
4449
4450
4
    unsigned pmask = getub(buf, 4);            // position mask
4451
4
    unsigned ftype = getub(buf, 5);            // fix type
4452
4
    double d1 = getbed64(buf, 6);              // latitude or X
4453
4
    double d2  = getbed64(buf, 14);            // longitude or Y
4454
4
    double d3  = getbed64(buf, 22);            // altitude or Z
4455
4
    double d4  = getbef32(buf, 30);            // velocity X or E
4456
4
    double d5  = getbef32(buf, 34);            // velocity Y or N
4457
4
    double d6  = getbef32(buf, 38);            // velocity Z or U
4458
4459
4
    double pdop = getbef32(buf, 42);  // PDOP, surveyed/current
4460
4461
4
    if (IN(0.01, pdop, 89.99)) {
4462
        // why not to newdata?
4463
1
        session->gpsdata.dop.pdop = pdop;
4464
1
        mask |= DOP_SET;
4465
1
    }
4466
4
    session->newdata.eph = getbef32(buf, 46);  // eph, 0 - 100, unknown units
4467
4
    session->newdata.epv = getbef32(buf, 50);  // epv, 0 - 100, unknown units
4468
4
    mask |= DOP_SET;
4469
    // position mask bit 0 does not tell us if we are in OD mode
4470
4
    if (0 == (pmask & 2)) {
4471
        // LLA
4472
2
        session->newdata.latitude = d1;
4473
2
        session->newdata.longitude = d2;
4474
2
        if (0 == (pmask & 4)) {
4475
            // HAE
4476
1
            session->newdata.altHAE = d3;
4477
1
        } else {
4478
            // MSL
4479
1
            session->newdata.altMSL = d3;
4480
1
        }
4481
2
        mask |= LATLON_SET | ALTITUDE_SET;
4482
2
    } else {
4483
        // XYZ ECEF
4484
2
        session->newdata.ecef.x = d1;
4485
2
        session->newdata.ecef.y = d2;
4486
2
        session->newdata.ecef.z = d3;
4487
2
        mask |= ECEF_SET;
4488
2
    }
4489
4
    if (0 == (pmask & 1)) {
4490
        // valid velocity
4491
2
        if (0 == (pmask & 8)) {
4492
            // Velocity ENU
4493
1
            session->newdata.NED.velN = d5;
4494
1
            session->newdata.NED.velE = d4;
4495
1
            session->newdata.NED.velD = -d6;
4496
1
            mask |= VNED_SET;
4497
1
        } else {
4498
            // Velocity ECEF
4499
1
            session->newdata.ecef.vx = d4;
4500
1
            session->newdata.ecef.vy = d5;
4501
1
            session->newdata.ecef.vz = d6;
4502
1
            mask |= VECEF_SET;
4503
1
        }
4504
2
    }
4505
4
    switch (ftype) {
4506
1
    default:
4507
1
        FALLTHROUGH
4508
2
    case 0:
4509
2
        session->newdata.mode = MODE_NO_FIX;
4510
2
        break;
4511
1
    case 1:
4512
1
        session->newdata.mode = MODE_2D;
4513
1
        break;
4514
1
    case 2:
4515
1
        session->newdata.mode = MODE_3D;
4516
4
    }
4517
    // status NOT set
4518
4
    mask |= MODE_SET | DOP_SET | HERR_SET | VERR_SET;
4519
4
    GPSD_LOG(LOG_PROG, &session->context->errout,
4520
4
             "TSIPv1 xa1-11: mode %d status %d pmask %u fixt %u "
4521
4
             "Pos %f %f %f Vel %f %f %f PDOP %f eph %f epv %f\n",
4522
4
             session->newdata.mode,
4523
4
             session->newdata.status,
4524
4
             pmask, ftype, d1, d2, d3, d4, d5, d6,
4525
4
             pdop,
4526
4
             session->newdata.eph,
4527
4
             session->newdata.epv);
4528
4
    GPSD_LOG(LOG_IO, &session->context->errout,
4529
4
             "TSIPv1: mode:%s status:%s pmask:%s fixt %s\n",
4530
4
             val2str(session->newdata.mode, vmode_str),
4531
4
             val2str(session->newdata.status, vstatus_str),
4532
4
             flags2str(pmask, vpos_mask1, buf2, sizeof(buf2)),
4533
4
             val2str(ftype, vfix_type1));
4534
4
    return mask;
4535
4
}
4536
4537
// decode packet xa2-00
4538
static gps_mask_t decode_xa2_00(struct gps_device_t *session, const char *buf)
4539
427
{
4540
427
    gps_mask_t mask = 0;
4541
427
    timespec_t ts_tow;
4542
427
    unsigned char gnssid, sigid;
4543
427
    char buf2[BUFSIZ];
4544
4545
427
    unsigned u1 = getub(buf, 4);               // message number, 1 to X
4546
4547
    // SV type, 0 to 26, mashup of constellation and signal
4548
427
    unsigned u2 = getub(buf, 5);
4549
427
    unsigned prn = getub(buf, 6);              // PRN (svid) 1 to 32 (99)
4550
427
    double az = getbef32(buf, 7);              // azimuth, degrees
4551
427
    double el = getbef32(buf, 11);             // elevation, degrees
4552
427
    double d3 = getbef32(buf, 15);             // signal level, db-Hz
4553
427
    unsigned u4 = getbeu32(buf, 19);           // Flags
4554
    // TOW of measurement, not current TOW!
4555
427
    unsigned tow = getbeu32(buf, 23);          // TOW, seconds
4556
4557
427
    if (0 == u1) {
4558
36
        GPSD_LOG(LOG_WARN, &session->context->errout,
4559
36
                "TSIPv1 xa2-00: invalid message number %u\n", u1);
4560
36
        return 0;
4561
391
    } else if (1 == u1) {
4562
        // message number starts at 1, no way to know last number
4563
44
        gpsd_zero_satellites(&session->gpsdata);
4564
        // start of new cycle, save last count
4565
44
        session->gpsdata.satellites_visible =
4566
44
            session->driver.tsip.last_chan_seen;
4567
347
    } else if (TSIP_CHANNELS < u1) {
4568
19
        GPSD_LOG(LOG_WARN, &session->context->errout,
4569
19
                "TSIPv1 xa2-00: too many satellites %d\n", u1);
4570
19
        return 0;
4571
328
    } else if (0 == prn ||
4572
294
               99 < prn) {
4573
68
        GPSD_LOG(LOG_WARN, &session->context->errout,
4574
68
                "TSIPv1 xa2-00: invalid prn %d\n", prn);
4575
68
        return 0;
4576
68
    }
4577
304
    session->driver.tsip.last_chan_seen = u1;
4578
304
    session->driver.tsip.last_a200 = tow;
4579
304
    ts_tow.tv_sec = tow;
4580
304
    ts_tow.tv_nsec = 0;
4581
304
    session->gpsdata.skyview_time =
4582
304
            gpsd_gpstime_resolv(session, session->context->gps_week,
4583
304
                                ts_tow);
4584
4585
    // convert svtype to gnssid and svid
4586
304
    gnssid = tsipv1_svtype(u2, &sigid);
4587
304
    session->gpsdata.skyview[u1 - 1].gnssid = gnssid;
4588
304
    session->gpsdata.skyview[u1 - 1].svid = prn;
4589
304
    session->gpsdata.skyview[u1 - 1].sigid = sigid;
4590
    // "real" NMEA 4.0 (not 4.10 ir 4.11) PRN
4591
304
    session->gpsdata.skyview[u1 - 1].PRN = ubx2_to_prn(gnssid, prn);
4592
304
    if (0 >= session->gpsdata.skyview[u1 - 1].PRN) {
4593
        // bad PRN??
4594
177
        GPSD_LOG(LOG_WARN, &session->context->errout,
4595
177
                 "TSIPv1 xa2-00(%u): Bad PRN: gnssid %u, prn %u PRN %d\n",
4596
177
                 u1, gnssid, prn, session->gpsdata.skyview[u1 - 1].PRN);
4597
177
    }
4598
304
    if (0 != (1 & u4)) {
4599
176
        if (90.0 >= fabs(el)) {
4600
113
            session->gpsdata.skyview[u1 - 1].elevation = el;
4601
113
        }
4602
176
        if (360.0 > az &&
4603
139
            0.0 <= az) {
4604
51
            session->gpsdata.skyview[u1 - 1].azimuth = az;
4605
51
        }
4606
176
    }
4607
304
    session->gpsdata.skyview[u1 - 1].ss = d3;
4608
304
    if (0 != (6 & u4)) {
4609
220
        session->gpsdata.skyview[u1 - 1].used = true;
4610
220
    }
4611
4612
304
    if (u1 >= session->gpsdata.satellites_visible) {
4613
        /* Last of the series? Assume same number of sats as
4614
         * last cycle.
4615
         * This will cause extra SKY if this set has more
4616
         * sats than the last set.  Will cause drop outs when
4617
         * number of sats decreases. */
4618
241
        if (10 < llabs(session->driver.tsip.last_a311 -
4619
241
                       session->driver.tsip.last_a200)) {
4620
            // no xa3-11 in 10 seconds, so push out now
4621
199
            mask |= SATELLITE_SET;
4622
199
            session->driver.tsip.last_a200 = 0;
4623
199
        }
4624
241
    }
4625
304
    if (MAXCHANNELS < session->gpsdata.satellites_visible) {
4626
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4627
0
                "TSIPv1 xa2-00: too many satellites %d\n",
4628
0
                 session->gpsdata.satellites_visible);
4629
0
        session->gpsdata.satellites_visible = MAXCHANNELS;
4630
0
    }
4631
    /* If this series has fewer than last series there will
4632
     * be no SKY, unless the cycle ender pushes the SKY */
4633
304
    GPSD_LOG(LOG_PROG, &session->context->errout,
4634
304
             "TSIPv1 xa2-00: num %u type %u (gnss %u sigid %u) PRN %u "
4635
304
             "az %f el %f snr %f sflags x%0x4 tow %u\n",
4636
304
             u1, u2, gnssid, sigid, prn, az, el, d3, u4, tow);
4637
304
    GPSD_LOG(LOG_IO, &session->context->errout,
4638
304
             "TSIPv1: svtype:%s flags:%s\n",
4639
304
             val2str(u2, vsv_type1),
4640
304
             flags2str(u4, vsflags1, buf2, sizeof(buf2)));
4641
304
    return mask;
4642
427
}
4643
4644
4645
// decode System Alarms,  packet xa3-00
4646
static gps_mask_t decode_xa3_00(struct gps_device_t *session, const char *buf)
4647
136
{
4648
136
    gps_mask_t mask = 0;
4649
136
    char buf2[BUFSIZ];
4650
136
    char buf3[BUFSIZ];
4651
4652
136
    unsigned minor_alarm = getbeu32(buf, 4);            // Minor Alarms
4653
136
    unsigned res1 = getbeu32(buf, 8);                   // reserved
4654
136
    unsigned major_alarm = getbeu32(buf, 12);           // Major Alarms
4655
136
    unsigned res2 = getbeu32(buf, 16);                  // reserved
4656
4657
136
    if (1 & minor_alarm) {
4658
35
        session->newdata.ant_stat = ANT_OPEN;
4659
101
    } else if (2 & minor_alarm) {
4660
61
        session->newdata.ant_stat = ANT_SHORT;
4661
61
    } else {
4662
40
        session->newdata.ant_stat = ANT_OK;
4663
40
    }
4664
4665
136
    if (1 == (major_alarm & 1)) {
4666
        // not tracking sats, assume surveyed-in
4667
69
        session->newdata.status = STATUS_DR;
4668
69
    } else {
4669
67
        session->newdata.status = STATUS_GPS;
4670
67
    }
4671
136
    if (0x80 == (major_alarm & 0x80)) {
4672
        // jamming
4673
34
        session->newdata.jam = 255;
4674
102
    } else if (0x40 == (major_alarm & 0x40)) {
4675
        // spoofing/multipath
4676
35
        session->newdata.jam = 128;
4677
35
    }
4678
136
    mask |= STATUS_SET;
4679
4680
136
    GPSD_LOG(LOG_PROG, &session->context->errout,
4681
136
             "TSIPv1 xa3-00: Minor x%04x res x%04x Major x%04x "
4682
136
             "res x%04u status %d\n",
4683
136
             minor_alarm, res1, major_alarm, res2,
4684
136
             session->newdata.status);
4685
136
    GPSD_LOG(LOG_IO, &session->context->errout,
4686
136
             "TSIPv1: minor:%s mojor:%s status:%s\n",
4687
136
             flags2str(minor_alarm, vminor_alarms1, buf2, sizeof(buf2)),
4688
136
             flags2str(major_alarm, vmajor_alarms1, buf3, sizeof(buf3)),
4689
136
             val2str(session->newdata.status, vstatus_str));
4690
136
    return mask;
4691
136
}
4692
4693
// decode packet xa3-11
4694
static gps_mask_t decode_xa3_11(struct gps_device_t *session, const char *buf)
4695
369
{
4696
369
    gps_mask_t mask = 0;
4697
4698
369
    unsigned rec_mode = getub(buf, 4);                // receiver mode
4699
369
    unsigned rec_status = getub(buf, 5);              // status
4700
369
    unsigned ssp = getub(buf, 6);              // self survey progress 0 - 100
4701
4702
369
    double pdop = getbef32(buf, 7);     // PDOP
4703
369
    double hdop = getbef32(buf, 11);    // HDOP
4704
369
    double vdop = getbef32(buf, 15);    // VDOP
4705
369
    double tdop = getbef32(buf, 19);    // TDOP
4706
4707
369
    session->newdata.temp = getbef32(buf, 23);        // Temperature, degrees C
4708
4709
369
    if (IN(0.01, pdop, 89.99)) {
4710
        // why not to newdata?
4711
34
        session->gpsdata.dop.pdop = pdop;
4712
34
        mask |= DOP_SET;
4713
34
    }
4714
369
    if (IN(0.01, hdop, 89.99)) {
4715
        // why not to newdata?
4716
38
        session->gpsdata.dop.hdop = hdop;
4717
38
        mask |= DOP_SET;
4718
38
    }
4719
369
    if (IN(0.01, vdop, 89.99)) {
4720
        // why not to newdata?
4721
96
        session->gpsdata.dop.vdop = vdop;
4722
96
        mask |= DOP_SET;
4723
96
    }
4724
369
    if (IN(0.01, tdop, 89.99)) {
4725
        // why not to newdata?
4726
144
        session->gpsdata.dop.tdop = tdop;
4727
144
        mask |= DOP_SET;
4728
144
    }
4729
4730
    // don't have tow, so use the one from xa2-00, if any
4731
369
    session->driver.tsip.last_a311 = session->driver.tsip.last_a200;
4732
4733
369
    if (0 < session->driver.tsip.last_a200) {
4734
29
        session->driver.tsip.last_a200 = 0;
4735
        // TSIPv1 seem to be sent in numerical order, so this
4736
        // is after xa2-00 and the sats.  Push out any lingering sats.
4737
29
        mask |= SATELLITE_SET;
4738
29
    }
4739
369
    mask |= REPORT_IS;
4740
369
    switch (rec_status) {
4741
48
    case 0:         // 2D
4742
48
        session->newdata.mode = MODE_2D;
4743
48
        mask |= MODE_SET;
4744
48
        break;
4745
34
    case 1:         // 3D (time only)
4746
34
        session->newdata.mode = MODE_3D;
4747
34
        mask |= MODE_SET;
4748
34
        break;
4749
34
    case 3:         // Automatic (?)
4750
34
        break;
4751
34
    case 4:         // OD clock
4752
34
        session->newdata.status = STATUS_TIME;
4753
34
        mask |= STATUS_SET;
4754
34
        break;
4755
219
    default:        // Huh?
4756
219
        break;
4757
369
    }
4758
4759
369
    switch (rec_status) {
4760
48
    case 0:         // doing position fixes
4761
48
        FALLTHROUGH
4762
82
    case 4:         // using 1 sat
4763
82
        FALLTHROUGH
4764
116
    case 5:         // using 2 sat
4765
116
        FALLTHROUGH
4766
150
    case 6:         // using 3 sat
4767
150
        session->newdata.status = STATUS_GPS;
4768
150
        mask |= STATUS_SET;
4769
150
        break;
4770
34
    case 1:         // no GPS time
4771
34
        FALLTHROUGH
4772
68
    case 2:         // PDOP too high
4773
68
        FALLTHROUGH
4774
102
    case 3:         // no sats
4775
102
        session->newdata.status = STATUS_UNK;
4776
102
        mask |= STATUS_SET;
4777
102
        break;
4778
35
    case 255:
4779
35
        session->newdata.mode = MODE_3D;
4780
35
        session->newdata.status = STATUS_TIME;
4781
35
        mask |= STATUS_SET | MODE_SET;
4782
35
        break;
4783
82
    default:
4784
        // huh?
4785
82
        break;
4786
369
    }
4787
4788
369
    if (10.0 < pdop) {
4789
74
        session->newdata.status = STATUS_DR;
4790
74
        mask |= STATUS_SET;
4791
74
    }
4792
4793
369
    GPSD_LOG(LOG_PROG, &session->context->errout,
4794
369
             "TSIPv1 xa3-11: mode %d status %d rm %u stat %u survey %u "
4795
369
             "PDOP %f HDOP %f VDOP %f TDOP %f temp %f\n",
4796
369
             session->newdata.mode,
4797
369
             session->newdata.status,
4798
369
             rec_mode, rec_status, ssp,
4799
369
             pdop, hdop, vdop, tdop,
4800
369
             session->newdata.temp);
4801
369
    GPSD_LOG(LOG_IO, &session->context->errout,
4802
369
             "TSIPv1: mode:%s status:%s rm:%s stat:%s\n",
4803
369
             val2str(session->newdata.mode, vmode_str),
4804
369
             val2str(session->newdata.status, vstatus_str),
4805
369
             val2str(rec_mode, vrec_mode1),
4806
369
             val2str(rec_status, vgnss_decode_status1));
4807
4808
369
    return mask;
4809
369
}
4810
4811
// decode packet xa3-21
4812
static gps_mask_t decode_xa3_21(struct gps_device_t *session, const char *buf)
4813
66
{
4814
66
    gps_mask_t mask = 0;
4815
4816
66
    unsigned u1 = getub(buf, 4);            // reference packet id
4817
66
    unsigned u2 = getub(buf, 5);            // reference sub packet id
4818
66
    unsigned u3 = getub(buf, 6);            // error code
4819
4820
66
    GPSD_LOG(LOG_WARN, &session->context->errout,
4821
66
             "TSIPv1 xa3-21: id x%02x-%02x error: %u\n",
4822
66
             u1, u2, u3);
4823
66
    GPSD_LOG(LOG_IO, &session->context->errout,
4824
66
             "TSIPv1: ec:%s\n",
4825
66
             val2str(u3, verr_codes1));
4826
66
    return mask;
4827
66
}
4828
4829
// Decode xbb
4830
static gps_mask_t decode_xbb(struct gps_device_t *session, const char *buf)
4831
68
{
4832
68
    gps_mask_t mask = 0;
4833
68
    unsigned u1 = getub(buf, 0);        // Subcode, always zero?
4834
68
    unsigned u2 = getub(buf, 1);        // Operating Dimension (Receiver Mode)
4835
68
    unsigned u3 = getub(buf, 2);        // DGPS Mode (not in Acutime Gold)
4836
68
    unsigned u4 = getub(buf, 3);        // Dynamics Code
4837
68
    double f1 = getbef32(buf, 5);       // Elevation Mask
4838
68
    double f2 = getbef32(buf, 9);       // AMU Mask
4839
68
    double f3 = getbef32(buf, 13);      // DOP Mask
4840
68
    double f4 = getbef32(buf, 17);      // DOP Switch
4841
68
    unsigned u5 = getub(buf, 21);       // DGPS Age Limit (not in Acutime Gold)
4842
    /* Constellation
4843
     * bit 0 - GPS
4844
     * bit 1 - GLONASS
4845
     * bit 2 - reserved
4846
     * bit 3 - BeiDou
4847
     * bit 4 - Galileo
4848
     * bit 5 - QZSS
4849
     * bit 6 - reserved
4850
     * bit 7 - reserved
4851
     */
4852
    // RES SMT 360 defaults to Mode 7, Constellation 3
4853
68
    unsigned u6 = getub(buf, 27);
4854
4855
68
    GPSD_LOG(LOG_PROG, &session->context->errout,
4856
68
             "TSIP xbb: Navigation Configuration: %u %u %u %u %f %f %f "
4857
68
             "%f %u x%x\n",
4858
68
             u1, u2, u3, u4, f1, f2, f3, f4, u5, u6);
4859
68
    GPSD_LOG(LOG_IO, &session->context->errout,
4860
68
             "TSIP: rm %s\n",
4861
68
             val2str(u1, vrec_mode));
4862
68
    return mask;
4863
68
}
4864
4865
// decode packet xd0-00
4866
static gps_mask_t decode_xd0_00(struct gps_device_t *session, const char *buf)
4867
0
{
4868
0
    gps_mask_t mask = 0;
4869
4870
0
    unsigned u1 = getub(buf, 6);               // debug output type
4871
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
4872
0
             "TSIPv1 xd0-00: debug %u\n", u1);
4873
4874
0
    return mask;
4875
0
}
4876
4877
// decode packet xd0-01
4878
static gps_mask_t decode_xd0_01(struct gps_device_t *session, const char *buf)
4879
0
{
4880
0
    gps_mask_t mask = 0;
4881
4882
0
    unsigned u1 = getub(buf, 6);               // debug type
4883
0
    unsigned u2 = getub(buf, 7);               // debug level
4884
4885
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
4886
0
             "TSIPv1 xd0-01: debug type %u level %u\n", u1, u2);
4887
4888
0
    return mask;
4889
0
}
4890
4891
/* parse TSIP v1 packages.
4892
* Currently only in RES720 devices, from 2020 onward.
4893
* buf: raw data, with DLE stuffing removed
4894
* len:  length of data in buf
4895
*
4896
* return: mask
4897
*/
4898
static gps_mask_t tsipv1_parse(struct gps_device_t *session, unsigned id,
4899
                                const char *buf, unsigned len)
4900
4.36k
{
4901
4.36k
    gps_mask_t mask = 0;
4902
4.36k
    unsigned sub_id, length, mode;
4903
4.36k
    unsigned u1;
4904
4.36k
    bool bad_len = false;
4905
4.36k
    unsigned char chksum;
4906
4907
4.36k
    if (4 > len) {
4908
        // should never happen
4909
545
        GPSD_LOG(LOG_WARN, &session->context->errout,
4910
545
                 "TSIPv1 0x%02x: runt, got len %u\n",
4911
545
                 id, len);
4912
545
        return mask;
4913
545
    }
4914
    /* Note: bug starts at sub id, offset 2 of the wire packet.
4915
     * So subtract 2 from the offsets in the Trimble doc. */
4916
3.82k
    sub_id = getub(buf, 0);
4917
3.82k
    length = getbeu16(buf, 1);  // expected length
4918
3.82k
    mode = getub(buf, 3);
4919
4920
3.82k
    if ((length + 3) != (unsigned)len) {
4921
187
        GPSD_LOG(LOG_WARN, &session->context->errout,
4922
187
                 "TSIPv1 x%02x-%02x: Bad Length, "
4923
187
                 "length got %d expected %u mode %u\n",
4924
187
                 id, sub_id, len, length + 3, mode);
4925
187
        return mask;
4926
187
    }
4927
4928
    // checksum is id, sub id, length, mode, data, not including trailer
4929
    // length is mode + data + checksum
4930
3.63k
    chksum = id;
4931
77.7k
    for (u1 = 0; u1 < (length + 3); u1++ ) {
4932
74.1k
        chksum ^= buf[u1];
4933
74.1k
    }
4934
3.63k
    if (0 != chksum) {
4935
146
        GPSD_LOG(LOG_WARN, &session->context->errout,
4936
146
                 "TSIPv1 x%02x-%02x: Bad Checksum "
4937
146
                 "length %d/%u mode %u\n",
4938
146
                 id, sub_id, len, length + 3, mode);
4939
146
        return mask;
4940
146
    }
4941
4942
3.48k
    GPSD_LOG(LOG_DATA, &session->context->errout,
4943
3.48k
             "TSIPv1 x%02x-%02x: length %d/%u mode %u\n",
4944
3.48k
             id, sub_id, len, length + 3, mode);
4945
4946
3.48k
    if (2 != mode) {
4947
        /* Don't decode queries (mode 0) or set (mode 1).
4948
         * Why would we even see one? */
4949
69
        return mask;
4950
69
    }
4951
    // FIXME: check len/length
4952
3.41k
    switch ((id << 8) | sub_id) {
4953
84
    case 0x9000:
4954
        // Protocol Version, x90-00
4955
84
        if (11 > length) {
4956
66
            bad_len = true;
4957
66
            break;
4958
66
        }
4959
18
        mask = decode_x90_00(session, buf);
4960
18
        break;
4961
635
    case 0x9001:
4962
        /* Receiver Version Information, x90-01
4963
         * Received in response to the TSIPv1 probe */
4964
635
        if (13 > length) {
4965
549
            bad_len = true;
4966
549
            break;
4967
549
        }
4968
86
        mask = decode_x90_01(session, buf, len);
4969
86
        break;
4970
84
    case 0x9100:
4971
        // Port Configuration, x91-00
4972
84
        if (17 > length) {
4973
66
            bad_len = true;
4974
66
            break;
4975
66
        }
4976
18
        mask = decode_x91_00(session, buf);
4977
18
        break;
4978
94
    case 0x9101:
4979
        // GNSS Configuration, x91-01
4980
94
        if (28 > length) {
4981
76
            bad_len = true;
4982
76
            break;
4983
76
        }
4984
18
        mask = decode_x91_01(session, buf);
4985
18
        break;
4986
100
    case 0x9102:
4987
        // NVS Configuration, x91-02
4988
100
        if (8 > length) {
4989
66
            bad_len = true;
4990
66
            break;
4991
66
        }
4992
34
        mask = decode_x91_02(session, buf);
4993
34
        break;
4994
86
    case 0x9103:
4995
        // Timing Configuration, x91-03
4996
86
        if (19 > length) {
4997
68
            bad_len = true;
4998
68
            break;
4999
68
        }
5000
18
        mask = decode_x91_03(session, buf);
5001
18
        break;
5002
84
    case 0x9104:
5003
        // Self-Survey Configuration, x91-04
5004
84
        if (11 > length) {
5005
66
            bad_len = true;
5006
66
            break;
5007
66
        }
5008
18
        mask = decode_x91_04(session, buf);
5009
18
        break;
5010
113
    case 0x9105:
5011
        //  Receiver Configuration, xx91-05
5012
113
        if (19 > length) {
5013
79
            bad_len = true;
5014
79
            break;
5015
79
        }
5016
34
        mask = decode_x91_05(session, buf);
5017
34
        break;
5018
132
    case 0x9201:
5019
        // Reset Cause, x92-01
5020
132
        if (3 > length) {
5021
66
            bad_len = true;
5022
66
            break;
5023
66
        }
5024
66
        mask = decode_x92_01(session, buf);
5025
66
        break;
5026
130
    case 0x9300:
5027
        // Production Information, x93-00
5028
130
        if (78 > length) {
5029
129
            bad_len = true;
5030
129
            break;
5031
129
        }
5032
1
        mask = decode_x93_00(session, buf);
5033
1
        break;
5034
0
    case 0xa000:
5035
        // Firmware Upload, xa0-00
5036
        // could be length 3, or 8, different data...
5037
0
        if (3 != length &&
5038
0
            8 != length) {
5039
0
            bad_len = true;
5040
0
            break;
5041
0
        }
5042
0
        mask = decode_xa0_00(session, buf, length);
5043
0
        break;
5044
315
    case 0xa100:
5045
        // Timing Information. xa1-00
5046
        // the only message on by default
5047
315
        if (32 > length) {
5048
113
            bad_len = true;
5049
113
            break;
5050
113
        }
5051
202
        mask = decode_xa1_00(session, buf);
5052
202
        break;
5053
5054
89
    case 0xa102:
5055
        // Frequency Information, xa1-02
5056
89
        if (17 > length) {
5057
71
            bad_len = true;
5058
71
            break;
5059
71
        }
5060
18
        mask = decode_xa1_02(session, buf);
5061
18
        break;
5062
5063
72
    case 0xa111:
5064
        // Position Information, xa1-11
5065
72
        if (52 > length) {
5066
68
            bad_len = true;
5067
68
            break;
5068
68
        }
5069
4
        mask = decode_xa1_11(session, buf);
5070
4
        break;
5071
493
    case 0xa200:
5072
        // Satellite Information, xa2-00
5073
493
        if (25 > length) {
5074
66
            bad_len = true;
5075
66
            break;
5076
66
        }
5077
427
        mask = decode_xa2_00(session, buf);
5078
427
        break;
5079
5080
202
    case 0xa300:
5081
        // System Alarms, xa3-00
5082
202
        if (18 > length) {
5083
66
            bad_len = true;
5084
66
            break;
5085
66
        }
5086
136
        mask = decode_xa3_00(session, buf);
5087
136
        break;
5088
501
    case 0xa311:
5089
        /* Receiver Status, xa3-11
5090
         * RES 720
5091
         */
5092
501
        if (29 > length) {
5093
132
            bad_len = true;
5094
132
            break;
5095
132
        }
5096
        // usually the last message, except for A2-00 (sats)
5097
369
        mask = decode_xa3_11(session, buf);
5098
369
        break;
5099
132
    case 0xa321:
5100
        /* Error Report xa3-21
5101
         * expect errors for x1c-03 and x35-32 from TSIP probes
5102
         */
5103
132
        if (5 > length) {
5104
66
            bad_len = true;
5105
66
            break;
5106
66
        }
5107
66
        mask = decode_xa3_21(session, buf);
5108
66
        break;
5109
0
    case 0xd000:
5110
        // Debug Output type packet, xd0-00
5111
0
        if (3 > length) {
5112
0
            bad_len = true;
5113
0
            break;
5114
0
        }
5115
0
        mask = decode_xd0_00(session, buf);
5116
0
        break;
5117
0
    case 0xd001:
5118
        // Trimble Debug config packet, xd0-01
5119
0
        if (4 > length) {
5120
0
            bad_len = true;
5121
0
            break;
5122
0
        }
5123
0
        mask = decode_xd0_01(session, buf);
5124
0
        break;
5125
0
    case 0xd040:
5126
        // Trimble Raw GNSS Debug Output packet. xd0-40
5127
        // length can be zero, contents undefined
5128
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
5129
0
                 "TSIPv1 xd0-40: raw GNSS data\n");
5130
0
        break;
5131
0
    case 0xd041:
5132
        // Trimble Raw GNSS Debug Output packet. xd0-41
5133
        // length can be zero, contents undefined
5134
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
5135
0
                 "TSIPv1 xd0-41: raw GNSS data\n");
5136
0
        break;
5137
5138
    // undecoded:
5139
0
    case 0x9200:
5140
        // Receiver Reset, send only, x92-00
5141
0
        FALLTHROUGH
5142
0
    case 0xa400:
5143
        // AGNSS, send only, xa4-00
5144
0
        FALLTHROUGH
5145
72
    default:
5146
        // Huh?
5147
72
        GPSD_LOG(LOG_WARN, &session->context->errout,
5148
72
                 "TSIPv1 x%02x-%02x: unknown packet id/su-id\n",
5149
72
                 id, sub_id);
5150
72
        break;
5151
3.41k
    }
5152
3.41k
    if (bad_len) {
5153
1.81k
        GPSD_LOG(LOG_WARN, &session->context->errout,
5154
1.81k
                 "TSIPv1 0x%02x-%02x: runt, got length %u\n",
5155
1.81k
                 id, sub_id, length);
5156
1.81k
        mask = 0;
5157
1.81k
    }
5158
    // get next item off queue
5159
3.41k
    tsipv1_query(session);
5160
5161
3.41k
    return mask;
5162
3.41k
}
5163
5164
/* This is the meat of parsing all the TSIP packets, except v1
5165
 *
5166
 * Return: mask
5167
 */
5168
static gps_mask_t tsip_parse_input(struct gps_device_t *session)
5169
21.8k
{
5170
21.8k
    unsigned i, len;
5171
21.8k
    gps_mask_t mask = 0;
5172
21.8k
    unsigned id;
5173
21.8k
    time_t now;
5174
21.8k
    char buf[sizeof(session->lexer.outbuffer)];
5175
21.8k
    char buf2[BUFSIZ];
5176
21.8k
    int bad_len = 0;
5177
21.8k
    bool valid = false;
5178
5179
21.8k
    if (TSIP_PACKET != session->lexer.type) {
5180
        // this should not happen
5181
68
        GPSD_LOG(LOG_INF, &session->context->errout,
5182
68
                 "TSIP: tsip_analyze packet type %d\n",
5183
68
                 session->lexer.type);
5184
68
        return 0;
5185
68
    }
5186
5187
21.8k
    if (4 > session->lexer.outbuflen ||
5188
21.8k
        0x10 != session->lexer.outbuffer[0]) {
5189
        // packet too short, or does not start with DLE
5190
70
        GPSD_LOG(LOG_INF, &session->context->errout,
5191
70
                 "TSIP: tsip_analyze packet bad packet\n");
5192
70
        return 0;
5193
70
    }
5194
5195
    /* get receive time, first
5196
     * using system time breaks regressions!
5197
     * so use latest from receiver */
5198
21.7k
    if (0 != session->lastfix.time.tv_sec) {
5199
21.6k
        now = session->lastfix.time.tv_sec;
5200
21.6k
    } else if (0 != session->oldfix.time.tv_sec) {
5201
0
        now = session->oldfix.time.tv_sec;
5202
121
    } else {
5203
121
        now = 0;
5204
121
    }
5205
5206
    // put data part of message in buf
5207
5208
21.7k
    memset(buf, 0, sizeof(buf));
5209
21.7k
    len = 0;
5210
417k
    for (i = 2; i < session->lexer.outbuflen; i++) {
5211
417k
        if (0x10 == session->lexer.outbuffer[i] &&
5212
30.4k
            0x03 == session->lexer.outbuffer[++i]) {
5213
                // DLE, STX.  end of packet, we know the length
5214
21.7k
                valid = true;
5215
21.7k
                break;
5216
21.7k
        }
5217
395k
        buf[len++] = session->lexer.outbuffer[i];
5218
395k
    }
5219
5220
21.7k
    id = (unsigned)session->lexer.outbuffer[1];
5221
21.7k
    if (valid &&
5222
21.7k
        1024 > len) {
5223
21.7k
        GPSD_LOG(LOG_DATA, &session->context->errout,
5224
21.7k
                 "TSIP x%02x: length %d: %s\n",
5225
21.7k
                 id, len, gps_hexdump(buf2, sizeof(buf2),
5226
21.7k
                                      (unsigned char *)buf, len));
5227
21.7k
    } else {
5228
        /* End of message not found, or too long, or both.
5229
         * Fuzzers gonna fuzz. */
5230
6
        GPSD_LOG(LOG_WARN, &session->context->errout,
5231
6
                 "TSIP x%02x: Too long. length %d: %s\n",
5232
6
                 id, len, gps_hexdump(buf2, sizeof(buf2),
5233
6
                                      (unsigned char *)buf, len));
5234
6
        return mask;
5235
6
    }
5236
5237
    // session->cycle_end_reliable = true;
5238
21.7k
    switch (id) {
5239
233
    case 0x13:
5240
        /* Packet Received
5241
         * Present in:
5242
         *   pre-2000 models
5243
         *   ICM SMT 360 (2018)
5244
         *   RES SMT 360 (2018)
5245
         *   Resolution SMTx
5246
         * Not present in:
5247
         *   Copernicus II
5248
         */
5249
233
        if (1 > len) {
5250
0
            bad_len = 1;
5251
0
            break;
5252
0
        }
5253
233
        mask = decode_x13(session, buf, len);
5254
233
        break;
5255
5256
1.64k
    case 0x1c:        // Hardware/Software Version Information
5257
        /* Present in:
5258
         *   Acutime Gold
5259
         *   Lassen iQ (2005) fw 1.16+
5260
         *   Copernicus (2006)
5261
         *   Copernicus II (2009)
5262
         *   Thunderbolt E (2012)
5263
         *   RES SMT 360 (2018)
5264
         *   ICM SMT 360 (2018)
5265
         *   RES360 17x22 (2018)
5266
         *   Acutime 360
5267
         * Not Present in:
5268
         *   pre-2000 models
5269
         *   ACE II (1999)
5270
         *   ACE III (2000)
5271
         *   Lassen SQ (2002)
5272
         *   Lassen iQ (2005) pre fw 1.16
5273
         */
5274
1.64k
        mask = decode_x1c(session, buf, len, &bad_len);
5275
1.64k
        break;
5276
350
    case 0x41:
5277
        /* GPS Time (0x41).  polled by 0x21
5278
         * Note: this is not the time of current fix
5279
         * Present in:
5280
         *   pre-2000 models
5281
         *   Copernicus II (2009)
5282
         *   ICM SMT 360 (2018)
5283
         *   RES SMT 360 (2018)
5284
         *   Resolution SMTx
5285
         */
5286
350
        if (10 > len) {
5287
34
            bad_len = 10;
5288
34
            break;
5289
34
        }
5290
316
        session->driver.tsip.last_41 = now;     // keep timestamp for request
5291
316
        mask = decode_x41(session, buf);
5292
316
        break;
5293
1.13k
    case 0x42:
5294
        /* Single-Precision Position Fix, XYZ ECEF
5295
         * Present in:
5296
         *   pre-2000 models
5297
         *   Copernicus II (2009)
5298
         *   ICM SMT 360 (2018)
5299
         *   RES SMT 360 (2018)
5300
         */
5301
1.13k
        if (16 > len) {
5302
34
            bad_len = 16;
5303
34
            break;
5304
34
        }
5305
1.10k
        mask = decode_x42(session, buf);
5306
1.10k
        break;
5307
426
    case 0x43:
5308
        /* Velocity Fix, XYZ ECEF
5309
         * Present in:
5310
         *   pre-2000 models
5311
         *   ICM SMT 360 (2018)
5312
         *   RES SMT 360 (2018)
5313
         * Not Present in:
5314
         *   Copernicus II (2009)
5315
         */
5316
426
        if (20 > len) {
5317
18
            bad_len = 20;
5318
18
            break;
5319
18
        }
5320
408
        mask = decode_x43(session, buf);
5321
408
        break;
5322
105
    case 0x45:
5323
        /* Software Version Information (0x45)
5324
         * Present in:
5325
         *   pre-2000 models
5326
         *   ACE II (1999)
5327
         *   ACE III (2000)
5328
         *   Lassen SQ (2002)
5329
         *   Lassen iQ (2005)
5330
         *   Copernicus II (2009)
5331
         *   ICM SMT 360
5332
         *   RES SMT 360
5333
         * Not present in:
5334
         *   RES 720
5335
         */
5336
105
        if (10 > len) {
5337
36
            bad_len = 10;
5338
36
            break;
5339
36
        }
5340
69
        mask = decode_x45(session, buf);
5341
69
        break;
5342
1.00k
    case 0x46:
5343
        /* Health of Receiver (0x46).  Poll with 0x26
5344
         * Present in:
5345
         *   pre-2000 models
5346
         *   Copernicus II (2009)
5347
         *   ICM SMT 360 (2018)
5348
         *   RES SMT 360 (2018) (deprecated, used x8f-ab or x8f-1c)
5349
         *   Resolution SMTx
5350
         *   all models?
5351
         */
5352
1.00k
        if (2 > len) {
5353
66
            bad_len = 2;
5354
66
            break;
5355
66
        }
5356
942
        session->driver.tsip.last_46 = now;
5357
942
        mask = decode_x46(session, buf);
5358
942
        break;
5359
435
    case 0x47:
5360
        /* Signal Levels for all Satellites
5361
         * Present in:
5362
         *   pre-2000 models
5363
         *   Copernicus II (2009)
5364
         *   ICM SMT 360 (2018)
5365
         *   RES SMT 360 (2018)
5366
         */
5367
435
        if (1 > len) {
5368
0
            bad_len = 1;
5369
0
            break;
5370
0
        }
5371
435
        mask = decode_x47(session, buf, len, &bad_len);
5372
435
        break;
5373
66
    case 0x48:
5374
        /* GPS System Message
5375
         * Present in:
5376
         *   pre-2000 models
5377
         * Not Present in:
5378
         *   Copernicus II (2009)
5379
         *   ICM SMT 360 (2018)
5380
         *   RES SMT 360 (2018)
5381
         */
5382
66
        buf[len] = '\0';
5383
66
        GPSD_LOG(LOG_PROG, &session->context->errout,
5384
66
                 "TSIP x48: GPS System Message: %s\n", buf);
5385
66
        break;
5386
513
    case 0x4a:
5387
        /* Single-Precision Position LLA
5388
         * Only sent when valid
5389
         * Present in:
5390
         *   pre-2000 models
5391
         *   Copernicus II (2009)
5392
         *   ICM SMT 360 (2018)
5393
         *   RES SMT 360 (2018)
5394
         */
5395
513
        if (20 > len) {
5396
18
            bad_len = 20;
5397
18
            break;
5398
18
        }
5399
495
        mask = decode_x4a(session, buf);
5400
495
        break;
5401
1.08k
    case 0x4b:
5402
        /* Machine/Code ID and Additional Status (0x4b)
5403
         * polled by 0x25 (soft reset) or 0x26 (request health).
5404
         * Sent with 0x46 (receiver health).
5405
         * Present in:
5406
         *   pre-2000 models
5407
         *   Copernicus II (2009)
5408
         *   ICM SMT 360 (2018)
5409
         *   RES SMT 360 (2018)
5410
         *   Resolution SMTx
5411
         * Deprecated in:
5412
         *   Resolution SMTx
5413
         * Not in:
5414
         *   Thunderbolt (2003)
5415
         */
5416
1.08k
        if (3 > len) {
5417
90
            bad_len = 3;
5418
90
            break;
5419
90
        }
5420
993
        mask = decode_x4b(session, buf);
5421
993
        break;
5422
84
    case 0x4c:
5423
        /* Operating Parameters Report (0x4c).  Polled by 0x2c
5424
         * Present in:
5425
         *   pre-2000 models
5426
         *   Lassen iQ, but not documented
5427
         * Not Present in:
5428
         *   Copernicus II (2009)
5429
         *   ICM SMT 360 (2018)
5430
         *   RES SMT 360 (2018)
5431
         */
5432
84
        if (17 > len) {
5433
18
            bad_len = 17;
5434
18
            break;
5435
18
        }
5436
66
        mask = decode_x4c(session, buf);
5437
66
        break;
5438
652
    case 0x54:
5439
        /* Bias and Bias Rate Report (0x54)
5440
         * Present in:
5441
         *   pre-2000 models
5442
         *   Acutime 360
5443
         *   ICM SMT 360  (undocumented)
5444
         *   RES SMT 360  (undocumented)
5445
         * Not Present in:
5446
         *   Copernicus II (2009)
5447
         *   Resolution SMTx
5448
         */
5449
652
        if (12 > len) {
5450
18
            bad_len = 12;
5451
18
            break;
5452
18
        }
5453
634
         mask = decode_x54(session, buf);
5454
634
        break;
5455
399
    case 0x55:
5456
        /* IO Options (0x55), polled by 0x35
5457
         * Present in:
5458
         *   pre-2000 models
5459
         *   ICM SMT 360 (2018)
5460
         *   RES SMT 360 (2018)
5461
         *   Resolution SMTx
5462
         *   all TSIP?
5463
         *
5464
         * Defaults:
5465
         *   Lassen iQ:       02 02 00 00
5466
         *   RES SMT 360:     12 02 00 08
5467
         *   Resolution SMTx: 12 02 00 08
5468
         */
5469
399
        if (4 > len) {
5470
34
            bad_len = 4;
5471
34
            break;
5472
34
        }
5473
365
        mask = decode_x55(session, buf, now);
5474
365
        break;
5475
463
    case 0x56:
5476
        /* Velocity Fix, East-North-Up (ENU)
5477
         * Present in:
5478
         *   pre-2000 models
5479
         *   Copernicus II (2009)
5480
         *   ICM SMT 360 (2018)
5481
         *   RES SMT 360 (2018)
5482
         */
5483
463
        if (20 > len) {
5484
34
            bad_len = 20;
5485
34
            break;
5486
34
        }
5487
429
        mask = decode_x56(session, buf);
5488
429
        break;
5489
608
    case 0x57:
5490
        /* Information About Last Computed Fix
5491
         * Present in:
5492
         *   pre-2000 models
5493
         *   Copernicus II (2009)
5494
         *   ICM SMT 360 (2018)
5495
         *   RES SMT 360 (2018)
5496
         */
5497
608
        if (8 > len) {
5498
66
            bad_len = 8;
5499
66
            break;
5500
66
        }
5501
542
        mask = decode_x57(session, buf);
5502
542
        break;
5503
52
    case 0x5a:
5504
        /* Raw Measurement Data
5505
         * Present in:
5506
         *   pre-2000 models
5507
         *   Copernicus II (2009)
5508
         *   ICM SMT 360 (2018)
5509
         *   RES SMT 360 (2018)
5510
         */
5511
52
        if (25 > len) {
5512
18
            bad_len = 25;
5513
18
            break;
5514
18
        }
5515
34
        mask = decode_x5a(session, buf);
5516
34
        break;
5517
777
    case 0x5c:
5518
        /* Satellite Tracking Status (0x5c) polled by 0x3c
5519
         *
5520
         * GPS only, no WAAS reported here or used in fix
5521
         * Present in:
5522
         *   pre-2000 models
5523
         *   Copernicus, Copernicus II
5524
         *   Thunderbold E
5525
         * Not Present in:
5526
         *   ICM SMT 360 (2018)
5527
         *   RES SMT 360 (2018)
5528
         */
5529
777
        if (24 > len) {
5530
35
            bad_len = 24;
5531
35
            break;
5532
35
        }
5533
742
        mask = decode_x5c(session, buf);
5534
742
        break;
5535
5536
1.01k
     case 0x5d:
5537
        /* GNSS Satellite Tracking Status (multi-GNSS operation) (0x5d)
5538
         * polled by 0x3c
5539
         *
5540
         * GNSS only, no WAAS reported here or used in fix
5541
         * Present in:
5542
         *   ICM SMT 360 (2018)
5543
         *   RES SMT 360 (2018)
5544
         * Not Present in:
5545
         *   pre-2000 models
5546
         *   Copernicus, Copernicus II
5547
         *   Thunderbold E
5548
         */
5549
1.01k
        if (26 > len) {
5550
18
            bad_len = 26;
5551
18
            break;
5552
18
        }
5553
995
        mask = decode_x5d(session, buf);
5554
995
        break;
5555
1.00k
    case 0x6c:
5556
        /* Satellite Selection List (0x6c) polled by 0x24
5557
         * Eeerily similar to 0x6d, the difference is where the sat count is.
5558
         *
5559
         * Present in:
5560
         *   ICM SMT 360 (2018)
5561
         *   RES SMT 360 (2018)
5562
         * Not present in:
5563
         *   pre-2000 models
5564
         *   Copernicus II (2009)
5565
         *   Lassen SQ (2002)
5566
         *   Lassen iQ (2005) */
5567
1.00k
        if (18 > len) {
5568
18
            bad_len = 18;
5569
18
            break;
5570
18
        }
5571
        // why same as 6d?
5572
982
        session->driver.tsip.last_6d = now;     // keep timestamp for request
5573
982
        mask = decode_x6c(session, buf, len, &bad_len);
5574
982
        break;
5575
1.07k
    case 0x6d:
5576
        /* All-In-View Satellite Selection (0x6d) polled by 0x24
5577
         * Sent after every fix
5578
         *
5579
         * Present in:
5580
         *   pre-2000 models
5581
         *   Copernicus II (2009)
5582
         *   Lassen SQ
5583
         *   Lassen iQ
5584
         * Deprecated in:
5585
         *   Resolution SMTx
5586
         * Not present in:
5587
         *   ICM SMT 360 (2018)
5588
         *   RES SMT 360 (2018)
5589
         */
5590
1.07k
        if (17 > len) {
5591
18
            bad_len = 17;
5592
18
            break;
5593
18
        }
5594
1.05k
        session->driver.tsip.last_6d = now;     // keep timestamp for request
5595
1.05k
        mask = decode_x6d(session, buf, len, &bad_len);
5596
1.05k
        break;
5597
165
    case 0x82:
5598
        /* Differential Position Fix Mode (0x82) poll with 0x62-ff
5599
         * Sent after every position fix in Auto GPS/DGPS,
5600
         * so potential cycle ender
5601
         *
5602
         * Present in:
5603
         *   pre-2000 models
5604
         *   Copernicus II (2009)
5605
         *   Lassen SQ
5606
         *   Lassen iQ, deprecated use 0xbb instead
5607
         * Not Present in:
5608
         *   ICM SMT 360 (2018)
5609
         *   RES SMT 360 (2018)
5610
         */
5611
165
        if (1 > len) {
5612
0
            bad_len = 1;
5613
0
            break;
5614
0
        }
5615
165
        mask = decode_x82(session, buf);
5616
165
        break;
5617
305
    case 0x83:
5618
        /* Double-Precision XYZ Position Fix and Bias Information
5619
         * Only sent when valid
5620
         * Present in:
5621
         *   pre-2000 models
5622
         *   LasenSQ (2002)
5623
         *   Copernicus II (2009)
5624
         *   ICM SMT 360 (2018)
5625
         *   RES SMT 360 (2018)
5626
         */
5627
305
        if (36 > len) {
5628
0
            bad_len = 36;
5629
0
            break;
5630
0
        }
5631
305
        mask = decode_x83(session, buf);
5632
305
        break;
5633
321
    case 0x84:
5634
        /* Double-Precision LLA Position Fix and Bias Information
5635
         * Present in:
5636
         *   pre-2000 models
5637
         *   Copernicus II (2009)
5638
         *   LassenSQ  (2002)
5639
         *   ICM SMT 360 (2018)
5640
         *   RES SMT 360 (2018)
5641
         */
5642
321
        if (36 > len) {
5643
0
            bad_len = 36;
5644
0
            break;
5645
0
        }
5646
321
        mask = decode_x84(session, buf);
5647
321
        break;
5648
3.20k
    case 0x8f:
5649
        /* Super Packet.
5650
         * Present in:
5651
         *   pre-2000 models
5652
         *   ACE II
5653
         *   ACE III
5654
         *   Copernicus II (2009)
5655
         *   ICM SMT 360
5656
         *   RES SMT 360
5657
         *   Resolution SMTx
5658
         */
5659
3.20k
        mask = decode_x8f(session, buf, len, &bad_len, now);
5660
3.20k
        break;
5661
// Start of TSIP V1
5662
970
    case 0x90:
5663
        /* Version Information, TSIP v1
5664
         * Present in:
5665
         *   RES720
5666
         */
5667
970
        FALLTHROUGH
5668
1.67k
    case 0x91:
5669
        /* Receiver Configuration, TSIP v1
5670
         * Present in:
5671
         *   RES720
5672
         */
5673
1.67k
        FALLTHROUGH
5674
1.95k
    case 0x92:
5675
        /* Resets, TSIP v1
5676
         * Present in:
5677
         *   RES720
5678
         */
5679
1.95k
        FALLTHROUGH
5680
2.13k
    case 0x93:
5681
        /* Production & Manufacturing, TSIP v1
5682
         * Present in:
5683
         *   RES720
5684
         */
5685
2.13k
        FALLTHROUGH
5686
2.13k
    case 0xa0:
5687
        /* Firmware Upload, TSIP v1
5688
         * Present in:
5689
         *   RES720
5690
         */
5691
2.13k
        FALLTHROUGH
5692
2.82k
    case 0xa1:
5693
        /* PVT, TSIP v1
5694
         * Present in:
5695
         *   RES720
5696
         */
5697
2.82k
        FALLTHROUGH
5698
3.39k
    case 0xa2:
5699
        /* GNSS Information, TSIP v1
5700
         * Present in:
5701
         *   RES720
5702
         */
5703
3.39k
        FALLTHROUGH
5704
4.36k
    case 0xa3:
5705
        /* Alarms % Status, TSIP v1
5706
         * Present in:
5707
         *   RES720
5708
         */
5709
4.36k
        FALLTHROUGH
5710
4.36k
    case 0xa4:
5711
        /* AGNSS, TSIP v1
5712
         * Present in:
5713
         *   RES720
5714
         */
5715
4.36k
        FALLTHROUGH
5716
4.36k
    case 0xa5:
5717
        /* Miscellaneous, TSIP v1
5718
         * Present in:
5719
         *   RES720
5720
         */
5721
4.36k
        FALLTHROUGH
5722
4.36k
    case 0xd0:
5723
        /* Debug & Logging, TSIP v1
5724
         * Present in:
5725
         *   RES720
5726
         */
5727
4.36k
        return tsipv1_parse(session, id, buf, len);
5728
// end of TSIP V1
5729
68
    case 0xbb:
5730
        /* Navigation Configuration
5731
         * Present in:
5732
         *   pre-2000 models
5733
         *   Copernicus II (2009)
5734
         *   ICM SMT 360 (2018)
5735
         *   RES SMT 360 (2018)
5736
         */
5737
68
        if (40 != len &&
5738
34
            43 != len) {
5739
            // see packet.c for explamation
5740
0
            bad_len = 40;
5741
0
            break;
5742
0
        }
5743
68
        mask = decode_xbb(session, buf);
5744
68
        break;
5745
5746
0
    case 0x1a:
5747
        /* TSIP RTCM Wrapper Command
5748
         * Present in:
5749
         *   pre-2000 models
5750
         * Not Present in:
5751
         *   ICM SMT 360 (2018)
5752
         *   RES SMT 360 (2018)
5753
         *   Copernicus II (2009)
5754
         */
5755
0
        FALLTHROUGH
5756
0
    case 0x2e:
5757
        /* Request GPS Time
5758
         * Present in:
5759
         *   ICM SMT 360 (2018)
5760
         *   RES SMT 360 (2018)
5761
         * Not Present in:
5762
         *   pre-2000 models
5763
         *   Copernicus II (2009)
5764
         */
5765
0
        FALLTHROUGH
5766
0
    case 0x32:
5767
        /* Request Unit Position
5768
         * Present in:
5769
         *   ICM SMT 360 (2018)
5770
         *   RES SMT 360 (2018)
5771
         * Not Present in:
5772
         *   pre-2000 models
5773
         *   Copernicus II (2009)
5774
         */
5775
0
        FALLTHROUGH
5776
0
    case 0x38:
5777
        /* Request SV System data
5778
         * Present in:
5779
         *   ICM SMT 360 (2018)
5780
         *   RES SMT 360 (2018)
5781
         * Not Present in:
5782
         *   pre-2000 models
5783
         *   Copernicus II (2009)
5784
         */
5785
0
        FALLTHROUGH
5786
0
    case 0x40:
5787
        /* Almanac Data for Single Satellite Report
5788
         * Present in:
5789
         *   pre-2000 models
5790
         * Not Present in:
5791
         *   ICM SMT 360 (2018)
5792
         *   RES SMT 360 (2018)
5793
         *   Copernicus II (2009)
5794
         */
5795
0
        FALLTHROUGH
5796
0
    case 0x44:
5797
        /* Non-Overdetermined Satellite Selection Report
5798
         * Present in:
5799
         *   pre-2000 models
5800
         * Not Present in:
5801
         *   ICM SMT 360 (2018)
5802
         *   RES SMT 360 (2018)
5803
         *   Copernicus II (2009)
5804
         */
5805
0
        FALLTHROUGH
5806
34
    case 0x49:
5807
        /* Almanac Health Page
5808
         * Present in:
5809
         *   pre-2000 models
5810
         * Not Present in:
5811
         *   Copernicus II (2009)
5812
         */
5813
34
        FALLTHROUGH
5814
34
    case 0x4d:
5815
        /* Oscillator Offset
5816
         * Present in:
5817
         *   pre-2000 models
5818
         *   Copernicus II (2009)
5819
         */
5820
34
        FALLTHROUGH
5821
34
    case 0x4e:
5822
        /* Response to set GPS time
5823
         * Present in:
5824
         *   pre-2000 models
5825
         *   Copernicus II (2009)
5826
         *   ICM SMT 360 (2018)
5827
         *   RES SMT 360 (2018)
5828
         */
5829
34
        FALLTHROUGH
5830
34
    case 0x4f:
5831
        /* UTC Parameters Report
5832
         * Present in:
5833
         *   pre-2000 models
5834
         * Not Present in:
5835
         *   ICM SMT 360 (2018)
5836
         *   RES SMT 360 (2018)
5837
         *   Copernicus II (2009)
5838
         */
5839
34
        FALLTHROUGH
5840
34
    case 0x53:
5841
        /* Analog-to-Digital Readings Report
5842
         * Present in:
5843
         *   pre-2000 models
5844
         * Not Present in:
5845
         *   ICM SMT 360 (2018)
5846
         *   RES SMT 360 (2018)
5847
         *   Copernicus II (2009)
5848
         */
5849
34
        FALLTHROUGH
5850
34
    case 0x58:
5851
        /* Satellite System Data/Acknowledge from Receiver
5852
         * Present in:
5853
         *   pre-2000 models
5854
         *   Copernicus II (2009)
5855
         *   ICM SMT 360 (2018)
5856
         *   RES SMT 360 (2018)
5857
         */
5858
34
        FALLTHROUGH
5859
34
    case 0x59:
5860
        /* Status of Satellite Disable or Ignore Health
5861
         * aka Satellite Attribute Database Status Report
5862
         * Present in:
5863
         *   pre-2000 models
5864
         *   ICM SMT 360 (2018)
5865
         *   RES SMT 360 (2018)
5866
         * Not Present in:
5867
         *   Copernicus II (2009)
5868
         */
5869
34
        FALLTHROUGH
5870
100
    case 0x5b:
5871
        /* Satellite Ephemeris Status
5872
         * Present in:
5873
         *   pre-2000 models
5874
         * Not Present in:
5875
         *   Copernicus II (2009)
5876
         *   ICM SMT 360 (2018)
5877
         *   RES SMT 360 (2018)
5878
         */
5879
100
        FALLTHROUGH
5880
166
    case 0x5e:
5881
        /* Additional Fix Status Report
5882
         * Present in:
5883
         *   pre-2000 models
5884
         * Not Present in:
5885
         *   Copernicus II (2009)
5886
         *   ICM SMT 360 (2018)
5887
         *   RES SMT 360 (2018)
5888
         */
5889
166
        FALLTHROUGH
5890
184
    case 0x5f:
5891
        /* Severe Failure Notification
5892
         * Present in:
5893
         *   pre-2000 models
5894
         * Not Present in:
5895
         *   ICM SMT 360 (2018)
5896
         *   RES SMT 360 (2018)
5897
         *   Copernicus II (2009)
5898
         */
5899
184
        FALLTHROUGH
5900
184
    case 0x60:
5901
        /* Differential GPS Pseudorange Corrections Report
5902
         * Present in:
5903
         *   pre-2000 models
5904
         * Not Present in:
5905
         *   ICM SMT 360 (2018)
5906
         *   RES SMT 360 (2018)
5907
         *   Copernicus II (2009)
5908
         */
5909
184
        FALLTHROUGH
5910
184
    case 0x61:
5911
        /* Differential GPS Delta Pseudorange Corrections Report
5912
         * Present in:
5913
         *   pre-2000 models
5914
         * Not Present in:
5915
         *   ICM SMT 360 (2018)
5916
         *   RES SMT 360 (2018)
5917
         *   Copernicus II (2009)
5918
         */
5919
184
        FALLTHROUGH
5920
184
    case 0x6a:
5921
        /* Differential Corrections Used in the Fix Repor
5922
         * Present in:
5923
         *   pre-2000 models
5924
         * Not Present in:
5925
         *   ICM SMT 360 (2018)
5926
         *   RES SMT 360 (2018)
5927
         *   Copernicus II (2009)
5928
         */
5929
184
        FALLTHROUGH
5930
184
    case 0x6e:
5931
        /* Synchronized Measurements
5932
         * Present in:
5933
         *   pre-2000 models
5934
         * Not Present in:
5935
         *   Copernicus II (2009)
5936
         *   ICM SMT 360 (2018)
5937
         *   RES SMT 360 (2018)
5938
         */
5939
184
        FALLTHROUGH
5940
184
    case 0x6f:
5941
        /* Synchronized Measurements Report
5942
         * Present in:
5943
         *   pre-2000 models
5944
         * Not Present in:
5945
         *   Copernicus II (2009)
5946
         *   ICM SMT 360 (2018)
5947
         *   RES SMT 360 (2018)
5948
         */
5949
184
        FALLTHROUGH
5950
184
    case 0x70:
5951
        /* Filter Report
5952
         * Present in:
5953
         *   pre-2000 models
5954
         * Not Present in:
5955
         *   Copernicus II (2009)
5956
         *   ICM SMT 360 (2018)
5957
         *   RES SMT 360 (2018)
5958
         */
5959
184
        FALLTHROUGH
5960
184
    case 0x76:
5961
        /* Overdetermined Mode Report
5962
         * Present in:
5963
         *   pre-2000 models
5964
         * Not Present in:
5965
         *   ICM SMT 360 (2018)
5966
         *   RES SMT 360 (2018)
5967
         *   Copernicus II (2009)
5968
         */
5969
184
        FALLTHROUGH
5970
184
    case 0x78:
5971
        /* Maximum PRC Age Report
5972
         * Present in:
5973
         *   pre-2000 models
5974
         * Not Present in:
5975
         *   ICM SMT 360 (2018)
5976
         *   RES SMT 360 (2018)
5977
         *   Copernicus II (2009)
5978
         */
5979
184
        FALLTHROUGH
5980
184
    case 0x7a:
5981
        /* NMEA settings
5982
         * Not Present in:
5983
         *   pre-2000 models
5984
         *   Copernicus II (2009)
5985
         *   ICM SMT 360 (2018)
5986
         *   RES SMT 360 (2018)
5987
         */
5988
184
        FALLTHROUGH
5989
184
    case 0x7b:
5990
        /* NMEA interval and message mask response
5991
         * Present in:
5992
         *   pre-2000 models
5993
         *   ICM SMT 360 (2018)
5994
         *   RES SMT 360 (2018)
5995
         * Not Present in:
5996
         *   Copernicus II (2009)
5997
         */
5998
184
        FALLTHROUGH
5999
184
    case 0x7d:
6000
        /* Position Fix Rate Configuration Reports
6001
         * Present in:
6002
         *   pre-2000 models
6003
         * Not Present in:
6004
         *   ICM SMT 360 (2018)
6005
         *   RES SMT 360 (2018)
6006
         *   Copernicus II (2009)
6007
         */
6008
184
        FALLTHROUGH
6009
184
    case 0x85:
6010
        /* Differential Correction Status Report
6011
         * Present in:
6012
         *   pre-2000 models
6013
         * Not Present in:
6014
         *   ICM SMT 360 (2018)
6015
         *   RES SMT 360 (2018)
6016
         *   Copernicus II (2009)
6017
         */
6018
184
        FALLTHROUGH
6019
184
    case 0x87:
6020
        /* Reference Station Parameters Report
6021
         * Present in:
6022
         *   pre-2000 models
6023
         * Not Present in:
6024
         *   ICM SMT 360 (2018)
6025
         *   RES SMT 360 (2018)
6026
         *   Copernicus II (2009)
6027
         */
6028
184
        FALLTHROUGH
6029
184
    case 0x89:
6030
        /* Receiver acquisition sensitivity mode
6031
         * Present in:
6032
         *   Copernicus II (2009)
6033
         * Not Present in:
6034
         *   pre-2000 models
6035
         *   ICM SMT 360 (2018)
6036
         *   RES SMT 360 (2018)
6037
         */
6038
184
        FALLTHROUGH
6039
184
    case 0x88:
6040
        /* Mobile Differential Parameters Report
6041
         * Present in:
6042
         *   pre-2000 models
6043
         * Not Present in:
6044
         *   ICM SMT 360 (2018)
6045
         *   RES SMT 360 (2018)
6046
         *   Copernicus II (2009)
6047
         */
6048
184
        FALLTHROUGH
6049
184
    case 0x8b:
6050
        /* QA/QC Reports
6051
         * Present in:
6052
         *   pre-2000 models
6053
         * Not Present in:
6054
         *   ICM SMT 360 (2018)
6055
         *   RES SMT 360 (2018)
6056
         *   Copernicus II (2009)
6057
         */
6058
184
        FALLTHROUGH
6059
184
    case 0x8d:
6060
        /* Average Position Reports
6061
         * Present in:
6062
         *   pre-2000 models
6063
         * Not Present in:
6064
         *   ICM SMT 360 (2018)
6065
         *   RES SMT 360 (2018)
6066
         *   Copernicus II (2009)
6067
         */
6068
184
        FALLTHROUGH
6069
184
    case 0xb0:
6070
        /* PPS and Event Report Packets
6071
         * Present in:
6072
         *   pre-2000 models
6073
         * Not Present in:
6074
         *   ICM SMT 360 (2018)
6075
         *   RES SMT 360 (2018)
6076
         *   Copernicus II (2009)
6077
         */
6078
184
        FALLTHROUGH
6079
184
    case 0xbc:
6080
        /* Receiver port configuration
6081
         * Present in:
6082
         *   pre-2000 models
6083
         *   Copernicus II (2009)
6084
         * Not Present in:
6085
         *   ICM SMT 360 (2018)
6086
         *   RES SMT 360 (2018)
6087
         */
6088
184
        FALLTHROUGH
6089
184
    case 0xc1:
6090
        /* Bit Mask for GPIOs in Standby Mode
6091
         * Present in:
6092
         *   Copernicus II (2009)
6093
         *   ICM SMT 360 (2018)
6094
         *   RES SMT 360 (2018)
6095
         * Not Present in:
6096
         *   pre-2000 models
6097
         */
6098
184
        FALLTHROUGH
6099
184
    case 0xc2:
6100
        /* SBAS SV Mask
6101
         * Present in:
6102
         *   Copernicus II (2009)
6103
         *   ICM SMT 360 (2018)
6104
         *   RES SMT 360 (2018)
6105
         * Not Present in:
6106
         *   pre-2000 models
6107
         */
6108
184
        FALLTHROUGH
6109
184
    default:
6110
184
        GPSD_LOG(LOG_WARN, &session->context->errout,
6111
184
                 "TSIP x%02x: Unhandled packet type\n", id);
6112
184
        break;
6113
21.7k
    }
6114
6115
#ifdef __UNUSED__
6116
// #if 1
6117
    // full reset
6118
    (void)tsip_write1(session, "\x1e\x46", 2);
6119
#endif
6120
6121
17.3k
    if (bad_len) {
6122
1.99k
        GPSD_LOG(LOG_WARNING, &session->context->errout,
6123
1.99k
                 "TSIP x%02x: wrong len %d s/b >= %d \n", id, len, bad_len);
6124
15.3k
    } else {
6125
15.3k
        GPSD_LOG(LOG_IO, &session->context->errout,
6126
15.3k
                 "TSIP x%02x: mask %s\n", id, gps_maskdump(mask));
6127
15.3k
    }
6128
    /* See if it is time to send some request packets for reports that.
6129
     * The receiver won't send at fixed intervals.
6130
     * Use llabs() as time sometimes goes backwards. */
6131
6132
17.3k
    if (5 < llabs(now - session->driver.tsip.last_41)) {
6133
        /* Request Current Time returns 0x41.
6134
         * Easiest way to get GPS weeks and current leap seconds */
6135
5.00k
        (void)tsip_write1(session, "\x21", 1);
6136
5.00k
        session->driver.tsip.last_41 = now;
6137
5.00k
    }
6138
6139
17.3k
    if (5 < llabs(now - session->driver.tsip.last_6d)) {
6140
        /* Request GPS Receiver Position Fix Mode
6141
         * Returns 0x44, 0x6c, or 0x6d
6142
         * We need one of those to get PDOP, HDOP, etc.
6143
         * At least on RexSMT360. */
6144
5.05k
        (void)tsip_write1(session, "\x24", 1);
6145
5.05k
        session->driver.tsip.last_6d = now;
6146
#ifdef __UNUSED__
6147
// #if 1
6148
        // request Receiver Configuration (0xbb)
6149
        (void)tsip_write1(session, "\xbb\x00", 2);
6150
6151
        // request Packet Broadcast Mask
6152
        (void)tsip_write1(session, "\x8e\xa5", 2);
6153
#endif // UNUSED
6154
5.05k
    }
6155
6156
17.3k
    if (1 > session->driver.tsip.superpkt &&
6157
16.2k
        60 < llabs(now - session->driver.tsip.last_48)) {
6158
        /* Request GPS System Message
6159
         * Returns 0x48.
6160
         * not supported on:
6161
         *  Lassen SQ (2002)
6162
         *  Lassen iQ (2005)
6163
         *  ICM SMT 360
6164
         *  RES SMT 360
6165
         *  and post 2005
6166
         * SuperPackets replaced 0x28 */
6167
5.16k
        (void)tsip_write1(session, "\x28", 1);
6168
5.16k
        session->driver.tsip.last_48 = now;
6169
5.16k
    }
6170
6171
17.3k
    if (5 < llabs(now - session->driver.tsip.last_5c)) {
6172
        /* Request Current Satellite Tracking Status
6173
         * Returns: 0x5c or 0x5d
6174
         *  5c from GPS only devices
6175
         *  5d from multi-gnss devices */
6176
        // 00 == All satellites
6177
5.33k
        (void)tsip_write1(session, "\x3c\x00", 2);
6178
5.33k
        session->driver.tsip.last_5c = now;
6179
5.33k
    }
6180
6181
17.3k
    if (5 < llabs(now - session->driver.tsip.last_46)) {
6182
        /* Request Health of Receiver
6183
         * Returns 0x46 and 0x4b. */
6184
5.20k
        (void)tsip_write1(session, "\x26", 1);
6185
5.20k
        session->driver.tsip.last_46 = now;
6186
5.20k
    }
6187
17.3k
    if ((0 < session->driver.tsip.req_compact) &&
6188
604
        (5 < llabs(now - session->driver.tsip.req_compact))) {
6189
        /* Compact Superpacket requested but no response
6190
         * Not in:
6191
         * ICM SMT 360
6192
         * RES SMT 360
6193
          */
6194
109
        session->driver.tsip.req_compact = 0;
6195
109
        GPSD_LOG(LOG_WARN, &session->context->errout,
6196
109
                 "TSIP x8f-23: No Compact Super Packet, "
6197
109
                 "try LFwEI (0x8f-20)\n");
6198
6199
        // Request LFwEI Super Packet 0x8f-20, enabled
6200
109
        (void)tsip_write1(session, "\x8e\x20\x01", 3);
6201
109
    }
6202
6203
17.3k
    return mask;
6204
21.7k
}
6205
6206
static void tsip_init_query(struct gps_device_t *session)
6207
200
{
6208
    // Use 0x1C-03 to Request Hardware Version Information (0x1C-83)
6209
200
    (void)tsip_write1(session, "\x1c\x03", 2);
6210
    /*
6211
     * After HW information packet is received, a
6212
     * decision is made how to configure the device.
6213
     */
6214
200
}
6215
6216
static void tsip_event_hook(struct gps_device_t *session, event_t event)
6217
25.6k
{
6218
25.6k
    GPSD_LOG(LOG_SPIN, &session->context->errout,
6219
25.6k
             "TSIP: event_hook event %d ro %d\n",
6220
25.6k
             event, session->context->readonly);
6221
6222
25.6k
    if (session->context->readonly ||
6223
17.2k
        session->context->passive) {
6224
17.2k
        return;
6225
17.2k
    }
6226
8.41k
    switch (event) {
6227
7.97k
    case EVENT_CONFIGURE:
6228
        // this seems to get called on every packet...
6229
7.97k
        if (0 == session->lexer.counter) {
6230
            /* but the above if() makes it never execute
6231
             * formerely tried to force 801 here, but luckily it
6232
             * never fired as some Trimble are 8N1 */
6233
79
        }
6234
7.97k
        break;
6235
79
    case EVENT_IDENTIFIED:
6236
79
        FALLTHROUGH
6237
79
    case EVENT_REACTIVATE:
6238
        /* reactivate style needs to depend on model
6239
         * So send Request Software Version (0x1f), which returns 0x45.
6240
         * Once we have the x45, we can decide how to configure */
6241
79
        (void)tsip_write1(session, "\x1f", 1);
6242
79
        break;
6243
361
    case EVENT_DRIVER_SWITCH:
6244
361
        FALLTHROUGH
6245
361
    case EVENT_TRIGGERMATCH:
6246
361
        FALLTHROUGH
6247
361
    case EVENT_WAKEUP:
6248
361
        FALLTHROUGH
6249
361
    case EVENT_DEACTIVATE:
6250
        // used to revert serial port params here.  No need for that.
6251
361
        FALLTHROUGH
6252
361
    default:
6253
361
        break;
6254
8.41k
    }
6255
8.41k
}
6256
6257
static bool tsip_speed_switch(struct gps_device_t *session,
6258
                              speed_t speed, char parity, int stopbits)
6259
0
{
6260
0
    char buf[100];
6261
6262
0
    switch (parity) {
6263
0
    case 'E':
6264
0
    case 2:
6265
0
        parity = (char)2;
6266
0
        break;
6267
0
    case 'O':
6268
0
    case 1:
6269
0
        parity = (char)1;
6270
0
        break;
6271
0
    case 'N':
6272
0
    case 0:
6273
0
    default:
6274
0
        parity = (char)0;
6275
0
        break;
6276
0
    }
6277
6278
0
    buf[0] = 0xbc;          // Set Port Configuration (0xbc)
6279
0
    buf[1] = 0xff;          // current port
6280
    // input dev.baudrate
6281
0
    buf[2] = (round(log((double)speed / 300) / GPS_LN2)) + 2;
6282
0
    buf[3] = buf[2];        // output baudrate
6283
0
    buf[4] = 3;             // character width (8 bits)
6284
0
    buf[5] = parity;        // parity (normally odd)
6285
0
    buf[6] = stopbits - 1;  // stop bits (normally 1 stopbit)
6286
0
    buf[7] = 0;             // flow control (none)
6287
0
    buf[8] = 0x02;          // input protocol (TSIP)
6288
0
    buf[9] = 0x02;          // output protocol (TSIP)
6289
0
    buf[10] = 0;            // reserved
6290
0
    (void)tsip_write1(session, buf, 11);
6291
6292
0
    return true;            // it would be nice to error-check this
6293
0
}
6294
6295
static void tsip_mode(struct gps_device_t *session, int mode)
6296
0
{
6297
0
    if (MODE_NMEA == mode) {
6298
0
        char buf[16];
6299
6300
        /* send NMEA Interval and Message Mask Command (0x7a)
6301
         * First turn on the NMEA messages we want */
6302
0
        buf[0] = 0x7a;
6303
0
        buf[1] = 0x00;  //  subcode 0
6304
0
        buf[2] = 0x01;  //  1-second fix interval
6305
0
        buf[3] = 0x00;  //  Reserved
6306
0
        buf[4] = 0x00;  //  Reserved
6307
0
        buf[5] = 0x01;  //  1=GST, Reserved
6308
        /* 1=GGA, 2=GGL, 4=VTG, 8=GSV,
6309
         * 0x10=GSA, 0x20=ZDA, 0x40=Reserved, 0x80=RMC  */
6310
0
        buf[6] = 0x19;
6311
6312
0
        (void)tsip_write1(session, buf, 7);
6313
6314
        // Now switch to NMEA mode
6315
0
        memset(buf, 0, sizeof(buf));
6316
6317
0
        buf[0] = 0x8c;     // Set Port Configuration (0xbc)
6318
0
        buf[1] = 0xff;     // current port
6319
0
        buf[2] = 0x06;     // 4800 bps input.  4800, really?
6320
0
        buf[3] = buf[2];   // output SAME AS INPUT
6321
0
        buf[4] = 0x03;     // 8 data bits
6322
0
        buf[5] = 0x00;     // No parity
6323
0
        buf[6] = 0x00;     // 1 stop bit
6324
0
        buf[7] = 0x00;     // No flow control
6325
0
        buf[8] = 0x02;     // Input protocol TSIP
6326
0
        buf[9] = 0x04;     // Output protocol NMEA
6327
0
        buf[10] = 0x00;    // Reserved
6328
6329
0
        (void)tsip_write1(session, buf, 11);
6330
6331
0
    } else if (MODE_BINARY == mode) {
6332
        /* The speed switcher also puts us back in TSIP, so call it
6333
         * with the default 9600 8O1. */
6334
        // FIXME: Should preserve the current speed.
6335
        // (void)tsip_speed_switch(session, 9600, 'O', 1);
6336
        // FIXME: should config TSIP binary!
6337
0
        ;
6338
6339
0
    } else {
6340
0
        GPSD_LOG(LOG_ERROR, &session->context->errout,
6341
0
                 "TSIP: unknown mode %i requested\n", mode);
6342
0
    }
6343
0
}
6344
6345
// this is everything we export
6346
// *INDENT-OFF*
6347
const struct gps_type_t driver_tsip =
6348
{
6349
    .type_name      = "Trimble TSIP",     // full name of type
6350
    .packet_type    = TSIP_PACKET,        // associated lexer packet type
6351
    .flags          = DRIVER_STICKY,      // remember this
6352
    .trigger        = NULL,               // no trigger
6353
    .channels       = TSIP_CHANNELS,      // consumer-grade GPS
6354
    .probe_detect   = tsip_detect,        // probe for 9600O81 device
6355
    .get_packet     = packet_get1,        // use the generic packet getter
6356
    .parse_packet   = tsip_parse_input,   // parse message packets
6357
    .rtcm_writer    = NULL,               // doesn't accept DGPS corrections
6358
    .init_query     = tsip_init_query,    // non-perturbing initial query
6359
    .event_hook     = tsip_event_hook,    // fire on various lifetime events
6360
    .speed_switcher = tsip_speed_switch,  // change baud rate
6361
    .mode_switcher  = tsip_mode,          // there is a mode switcher
6362
    .rate_switcher  = NULL,               // no rate switcher
6363
    .min_cycle.tv_sec  = 1,               // not relevant, no rate switch
6364
    .min_cycle.tv_nsec = 0,               // not relevant, no rate switch
6365
    .control_send   = tsip_write1,        // how to send commands
6366
    .time_offset     = NULL,
6367
};
6368
// *INDENT-ON*
6369
6370
#endif  // TSIP_ENABLE
6371
6372
// vim: set expandtab shiftwidth=4