Coverage Report

Created: 2026-06-04 06:21

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
0
#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
0
#define IO1_ECEF 1
46
0
#define IO1_LLA 2
47
0
#define IO1_MSL 4
48
0
#define IO1_DP 0x10
49
// IO1_8F20 not in SMT 360
50
0
#define IO1_8F20 0x20
51
// byte 2 Velocity
52
0
#define IO2_VECEF 1
53
0
#define IO2_ENU 2
54
// byte 3 Timing
55
#define IO3_UTC 1
56
// byte 4 Aux/Reserved
57
#define IO4_RAW 1
58
0
#define IO4_DBHZ 8
59
60
0
#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
0
{
659
    // initialized to shut up clang
660
0
    unsigned char gnssid = 0;
661
662
0
    *svid = 0;
663
664
0
    switch (svtype) {
665
0
    case 0:
666
0
        if (0 < prn && 33 > prn) {
667
0
            gnssid = GNSSID_GPS;
668
0
            *svid = prn;
669
0
        } else if (32 < prn && 55 > prn) {
670
            // RES SMT 360 and ICM SMT 360 put SBAS in 33-54
671
0
            gnssid = GNSSID_SBAS;
672
0
            *svid = prn + 87;
673
0
        } else if (64 < prn && 97 > prn) {
674
            // RES SMT 360 and ICM SMT 360 put GLONASS in 65-96
675
0
            gnssid = GNSSID_GLO;
676
0
            *svid = prn - 64;
677
0
        } else if (96 < prn && 134 > prn) {
678
            // RES SMT 360 and ICM SMT 360 put Galileo in 97-133
679
0
            gnssid = GNSSID_GAL;
680
0
            *svid = prn - 96;
681
0
        } else if (119 < prn && 139 > prn) {
682
            // Copernicus (II) put SBAS in 120-138
683
0
            gnssid = GNSSID_SBAS;
684
0
            *svid = prn + 87;
685
0
        } else if (183 == prn) {
686
0
            gnssid = GNSSID_QZSS;
687
0
            *svid = 1;
688
0
        } else if (192 <= prn && 193 >= prn) {
689
0
            gnssid = GNSSID_QZSS;
690
0
            *svid = prn - 190;
691
0
        } else if (200 == prn) {
692
0
            gnssid = GNSSID_QZSS;
693
0
            *svid = 4;
694
0
        } else if (200 < prn && 238 > prn) {
695
            // BeidDou in 201-237
696
0
            gnssid = GNSSID_BD;
697
0
            *svid = prn - 200;
698
0
        }
699
        // else: huh?
700
0
        break;
701
0
    case 1:
702
0
        gnssid = GNSSID_GLO;  // GLONASS
703
0
        *svid = prn - 64;
704
0
        break;
705
0
    case 2:
706
0
        gnssid = GNSSID_BD;  // BeiDou
707
0
        *svid = prn - 200;
708
0
        break;
709
0
    case 3:
710
0
        gnssid = GNSSID_GAL;  // Galileo
711
0
        *svid = prn - 96;
712
0
        break;
713
0
    case 5:
714
0
        gnssid = GNSSID_QZSS;  // QZSS
715
0
        switch (prn) {
716
0
        case 183:
717
0
            *svid = 1;
718
0
            break;
719
0
        case 192:
720
0
            *svid = 2;
721
0
            break;
722
0
        case 193:
723
0
            *svid = 3;
724
0
            break;
725
0
        case 200:
726
0
            *svid = 4;
727
0
            break;
728
0
        default:
729
0
            *svid = prn;
730
0
            break;
731
0
        }
732
0
        break;
733
0
    case 4:
734
0
        FALLTHROUGH
735
0
    case 6:
736
0
        FALLTHROUGH
737
0
    case 7:
738
0
        FALLTHROUGH
739
0
    default:
740
0
        *svid = 0;
741
0
        gnssid = 0;
742
0
        break;
743
0
    }
744
0
    return gnssid;
745
0
}
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
0
{
754
0
    char checksum = 0;
755
0
    size_t index;
756
757
0
    for(index = 0; index < len; index++) {
758
0
        checksum ^= buf[index];
759
0
    }
760
0
    return checksum;
761
0
}
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
0
{
775
0
    char *ep, *cp;
776
0
    char obuf[100];
777
0
    size_t olen = len;
778
779
0
    if (session->context->readonly) {
780
0
        return 0;
781
0
    }
782
0
    if ((NULL == buf) ||
783
0
        0 == len ||
784
0
        (sizeof(session->msgbuf) / 2) < len) {
785
        // could over run, do not chance it
786
0
        return -1;
787
0
    }
788
0
    session->msgbuf[0] = '\x10';
789
0
    ep = session->msgbuf + 1;
790
0
    for (cp = buf; olen-- > 0; cp++) {
791
0
        if ('\x10' == *cp) {
792
0
            *ep++ = '\x10';
793
0
        }
794
0
        *ep++ = *cp;
795
0
    }
796
0
    *ep++ = '\x10';
797
0
    *ep++ = '\x03';
798
0
    session->msgbuflen = (size_t)(ep - session->msgbuf);
799
    // Don't bore the user with the header (DLE) or trailer (DLE, STX).
800
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
801
0
             "TSIP: tsip_write1(0x%s)\n",
802
0
             gps_hexdump(obuf, sizeof(obuf),
803
0
                         (unsigned char *)&session->msgbuf[1], len));
804
0
    if (gpsd_write(session, session->msgbuf, session->msgbuflen) !=
805
0
        (ssize_t) session->msgbuflen)
806
0
        return -1;
807
808
0
    return 0;
809
0
}
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
0
{
875
0
        char buf[100];
876
877
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
878
0
                 "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
0
        buf[0] = 0x35;
883
        // Time: enable: 0x42, 0x43, 0x4a, disable: 0x83, 0x84, 0x56
884
0
        buf[1] = IO1_8F20|IO1_DP|IO1_LLA;
885
        // Velocity: enable: ENU, disable ECEF
886
0
        buf[2] = IO2_ENU;
887
0
        buf[3] = 0x00;
888
0
        buf[4] = IO4_DBHZ;    // Aux: enable: 0x5A, dBHz
889
0
        (void)tsip_write1(session, buf, 5);
890
891
        // Request Software Version (0x1f), returns 0x45
892
0
        (void)tsip_write1(session, "\x1f", 1);
893
894
        // Current Time Request (0x21), returns 0x41
895
0
        (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
0
        buf[0] = 0x2c;
906
0
        buf[1] = 0x01;
907
        // elevation mask, 10 degrees is a common default, TSIP default is 15
908
0
        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
0
        putbef32(buf, 6, (float)06.0);
911
        // PDOP mask default is 12. 5.0 to 6.0 for high accuracy
912
0
        putbef32(buf, 10, (float)8.0);
913
        // PDOP switch, default is 8.0
914
0
        putbef32(buf, 14, (float)6.0);
915
0
        (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
0
        (void)tsip_write1(session, "\x22\x00", 2);
920
921
        /* Request GPS System Message (0x48)
922
         * not supported on model RES SMT 360 */
923
0
        (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
0
        (void)tsip_write1(session, "\x37", 1);
928
929
        // 0x8e-15 request output datum
930
0
        (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
0
        (void)tsip_write1(session, "\xbb\x00", 2);
935
0
}
936
937
// configure Acutime Gold to a known state
938
static void configuration_packets_acutime_gold(struct gps_device_t *session)
939
0
{
940
0
        char buf[100];
941
942
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
943
0
                 "TSIP: configuration_packets_acutime_gold()\n");
944
945
        /* Request Firmware Version (0x1c-01)
946
         * returns Firmware component version information (0x1x-81) */
947
0
        (void)tsip_write1(session, "\x1c\x01", 2);
948
949
0
        buf[0] = 0x8e;          // Set Self-Survey Parameters (0x8e-a9)
950
0
        buf[1] = 0xa9;          // Subcode
951
0
        buf[2] = 0x01;          // Self-Survey Enable = enable
952
0
        buf[3] = 0x01;          // Position Save Flag = save position
953
0
        putbe32(buf, 4, 2000);  // Self-Survey Length = 2000 fixes, default 2000
954
        // Horizontal Uncertainty, 1-100, 1=best, 100=worst, default 100
955
0
        putbef32(buf, 8, 100);
956
        // Vertical Uncertainty, 1-100, 1=best, 100=worst, default 100
957
0
        putbef32(buf, 12, 100);
958
0
        (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
0
        (void)tsip_write1(session, "\x8e\x4e\x02", 3);
964
965
0
        buf[0] = 0xbb;  // Set Primary Receiver Configuration (0xbb-00)
966
0
        buf[1] = 0x00;  // 00 =  Subcode
967
0
        buf[2] = 0x07;  // Receiver mode, 7 = Force Overdetermined clock
968
0
        buf[3] = 0xff;  // Not enabled = unchanged, must be 0xff on RES SMT 360
969
0
        buf[4] = 0x01;  // Dynamics code = default must be 0xff on RES SMT 360
970
0
        buf[5] = 0x01;  // Solution Mode = default must be 0xff on RES SMT 360
971
        // Elevation Mask = 10 deg
972
0
        putbef32((char *)buf, 6, (float)10.0 * DEG_2_RAD);
973
        // AMU Mask. 0 to 55. default is 4.0
974
0
        putbef32((char *)buf, 10, (float)4.0);
975
        // PDOP Mask = 8.0, default = 6
976
0
        putbef32((char *)buf, 14, (float)8.0);
977
        // PDOP Switch = 6.0, ignored in RES SMT 360
978
0
        putbef32((char *)buf, 18, (float)6.0);
979
0
        buf[22] = 0xff;  // must be 0xff
980
0
        buf[23] = 0x0;   // Anti-Jam Mode, 0=Off, 1=On
981
0
        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
0
        putbe16(buf, 26, 0x0000);
985
        /* 27 is Constellation on RES SMT 360.
986
         * 1 = GPS, 2=GLONASS, 8=BeiDou, 0x10=Galileo, 5=QZSS */
987
0
        putbe32(buf, 28, 0xffffffff);   // Reserved
988
0
        putbe32(buf, 32, 0xffffffff);   // Reserved
989
0
        putbe32(buf, 36, 0xffffffff);   // Reserved
990
0
        putbe32(buf, 40, 0xffffffff);   // Reserved
991
0
        (void)tsip_write1(session, buf, 44);
992
993
0
        buf[0] = 0x8e;   // Set Packet Broadcast Mask (0x8e-a5)
994
0
        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
0
        putbe16(buf, 2, 0x32e1);
999
0
        buf[4] = 0x00;   // not used
1000
0
        buf[5] = 0x00;   // not used
1001
0
        (void)tsip_write1(session, buf, 6);
1002
0
}
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
0
{
1007
0
    char buf[100];
1008
1009
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1010
0
             "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
0
    (void)tsip_write1(session, "\x8e\xa9", 2);
1016
1017
0
    if (session->context->passive) {
1018
        // request I/O Options (0x55)
1019
0
        (void)tsip_write1(session, "\x35", 1);
1020
1021
        // request Receiver Configuration (0xbb)
1022
0
        (void)tsip_write1(session, "\xbb\x00", 2);
1023
1024
        // Request Packet Broadcast Mask (0x8e-a5)
1025
0
        (void)tsip_write1(session, "\x8e\xa5", 2);
1026
1027
0
    } else {
1028
        // PPS Output Option (0x8e-4e) is default on
1029
1030
0
        buf[0] = 0x8e;  // Set Packet Broadcast Mask (0x8e-a5)
1031
0
        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
0
        buf[2] = 0;        // reserved
1035
0
        buf[3] = 0x45;
1036
0
        buf[4] = 0;        // reserved
1037
0
        buf[5] = 0;        // reserved
1038
0
        (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
0
        buf[0] = 0x35;  // set I/O Options
1046
        // position and velocity only sent during self-survey.
1047
        // Position
1048
0
        buf[1] =  IO1_DP|IO1_LLA|IO1_ECEF;
1049
        // Velocity
1050
0
        buf[2] = IO2_VECEF|IO2_ENU;
1051
        // Timing
1052
0
        buf[3] = 0x01;          // Use 0x8e-a2
1053
        // Auxiliary
1054
0
        buf[4] = 0x08;         // Packet 0x5a off, dBHz
1055
0
        (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
0
    }
1064
0
}
1065
1066
/* send the next TSIPv1 query
1067
 * Return: void
1068
 */
1069
static void tsipv1_query(struct gps_device_t *session)
1070
0
{
1071
0
    char snd_buf[24];         // send buffer
1072
1073
    // advance to next queue item.
1074
0
    session->queue++;
1075
    // allow it to repeat every x1000 packets
1076
0
    session->queue &= 0x0ffff;
1077
1078
0
    if (0 != (session->queue % 4)) {
1079
        // once every 4 messages
1080
0
        return;
1081
0
    }
1082
0
    switch (session->queue / 4) {
1083
0
    case 1:
1084
        // x90-00, query protocol version
1085
0
        snd_buf[0] = 0x90;             // id
1086
0
        snd_buf[1] = 0x00;             // sub id
1087
0
        putbe16(snd_buf, 2, 2);        // length
1088
0
        snd_buf[4] = 0;                // mode: query
1089
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1090
0
        (void)tsip_write1(session, snd_buf, 6);
1091
0
        break;
1092
0
    case 2:
1093
        // x90-01, query GNSS config version
1094
0
        snd_buf[0] = 0x90;             // id
1095
0
        snd_buf[1] = 0x01;             // sub id
1096
0
        putbe16(snd_buf, 2, 2);        // length
1097
0
        snd_buf[4] = 0;                // mode: query
1098
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1099
0
        (void)tsip_write1(session, snd_buf, 6);
1100
0
        break;
1101
0
    case 3:
1102
        // x91-00, Port config
1103
0
        snd_buf[0] = 0x91;             // id
1104
0
        snd_buf[1] = 0x00;             // sub id
1105
0
        putbe16(snd_buf, 2, 3);        // length
1106
0
        snd_buf[4] = 0;                // mode: query
1107
0
        snd_buf[5] = 0;                // current port
1108
0
        snd_buf[6] = tsip1_checksum(snd_buf, 6);   // checksum
1109
0
        (void)tsip_write1(session, snd_buf, 7);
1110
0
        break;
1111
0
    case 4:
1112
        // x81-01, GNSS config
1113
0
        snd_buf[0] = 0x91;             // id
1114
0
        snd_buf[1] = 0x01;             // sub id
1115
0
        putbe16(snd_buf, 2, 2);        // length
1116
0
        snd_buf[4] = 0;                // mode: query
1117
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1118
0
        (void)tsip_write1(session, snd_buf, 6);
1119
0
        break;
1120
0
    case 5:
1121
        // x91-03, query timing config
1122
0
        snd_buf[0] = 0x91;             // id
1123
0
        snd_buf[1] = 0x03;             // sub id
1124
0
        putbe16(snd_buf, 2, 2);        // length
1125
0
        snd_buf[4] = 0;                // mode: query
1126
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1127
0
        (void)tsip_write1(session, snd_buf, 6);
1128
0
        break;
1129
0
    case 6:
1130
        // x91-04, self survey config
1131
0
        snd_buf[0] = 0x91;             // id
1132
0
        snd_buf[1] = 0x04;             // sub id
1133
0
        putbe16(snd_buf, 2, 2);        // length
1134
0
        snd_buf[4] = 0;                // mode: query
1135
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1136
0
        (void)tsip_write1(session, snd_buf, 6);
1137
0
        break;
1138
0
    case 7:
1139
0
        if (session->context->passive) {
1140
            // x91-05, query current periodic messages
1141
0
            snd_buf[0] = 0x91;             // id
1142
0
            snd_buf[1] = 0x05;             // sub id
1143
0
            putbe16(snd_buf, 2, 3);        // length
1144
0
            snd_buf[4] = 0;                // mode: query
1145
0
            snd_buf[5] = 0xff;             // port: current port
1146
0
            snd_buf[6] = tsip1_checksum(snd_buf, 6);   // checksum
1147
0
            (void)tsip_write1(session, snd_buf, 7);
1148
0
        } else {
1149
            /* request periodic  messages, x91-05
1150
             * little harm at 115.2 kbps, this also responses as a query */
1151
0
            snd_buf[0] = 0x91;             // id
1152
0
            snd_buf[1] = 0x05;             // sub id
1153
0
            putbe16(snd_buf, 2, 19);       // length
1154
0
            snd_buf[4] = 0x01;             // mode: set
1155
0
            snd_buf[5] = 0xff;             // port: current port
1156
            // 0xaaaaa, everything preiodic
1157
0
            putbe32(snd_buf, 6, 0xaaaaa);
1158
0
            putbe32(snd_buf, 10, 0);       // reserved
1159
0
            putbe32(snd_buf, 14, 0);       // reserved
1160
0
            putbe32(snd_buf, 18, 0);       // reserved
1161
0
            snd_buf[22] = tsip1_checksum(snd_buf, 22);   // checksum
1162
0
            (void)tsip_write1(session, snd_buf, 23);
1163
0
        }
1164
0
        break;
1165
0
    case 8:
1166
        // x93-00, production info
1167
0
        snd_buf[0] = 0x93;             // id
1168
0
        snd_buf[1] = 0x00;             // sub id
1169
0
        putbe16(snd_buf, 2, 2);        // length
1170
0
        snd_buf[4] = 0;                // mode: query
1171
0
        snd_buf[5] = tsip1_checksum(snd_buf, 5);   // checksum
1172
0
        (void)tsip_write1(session, snd_buf, 6);
1173
0
        break;
1174
0
    default:
1175
        // nothing to do
1176
0
        break;
1177
0
    }
1178
0
}
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
0
{
1190
1191
0
    unsigned char gnssid;
1192
1193
0
    switch (svtype) {
1194
0
    case 1:  // GPS L1C
1195
0
       gnssid =  GNSSID_GPS;
1196
0
       *sigid = 0;
1197
0
       break;
1198
0
    case 2:  // GPS L2.  CL or CM?
1199
0
       gnssid =  GNSSID_GPS;
1200
0
       *sigid = 3;         // or, maybe 4
1201
0
       break;
1202
0
    case 3:  // GPS L5.  I or Q?
1203
0
       gnssid =  GNSSID_GPS;
1204
0
       *sigid = 6;         // or maybe 7
1205
0
       break;
1206
0
    case 5:  // GLONASS G1
1207
0
       gnssid =  GNSSID_GLO;
1208
0
       *sigid = 0;
1209
0
       break;
1210
0
    case 6:  // GLONASS G2
1211
0
       gnssid =  GNSSID_GLO;
1212
0
       *sigid = 2;
1213
0
       break;
1214
0
    case 9:  // SBAS, assume L1
1215
0
       gnssid =  GNSSID_SBAS;
1216
0
       *sigid = 0;
1217
0
       break;
1218
0
    case 13:  // Beidou B1, D1 or D2?
1219
0
       gnssid =  GNSSID_BD;
1220
0
       *sigid = 0;   // or maybe 1
1221
0
       break;
1222
0
    case 14:  // Beidou B2i
1223
0
       gnssid =  GNSSID_BD;
1224
0
       *sigid = 2;
1225
0
       break;
1226
0
    case 15:  // Beidou B2a
1227
0
       gnssid =  GNSSID_BD;
1228
0
       *sigid = 3;
1229
0
       break;
1230
0
    case 17:  // Galileo E1, C or B?
1231
0
       gnssid =  GNSSID_GAL;
1232
0
       *sigid = 0;    // or maybe 1
1233
0
       break;
1234
0
    case 18:  // Galileo E5a, aI or aQ?
1235
0
       gnssid =  GNSSID_GAL;
1236
0
       *sigid = 3;    // or maybe 4?
1237
0
       break;
1238
0
    case 19:  // Galileo E5b, bI or bQ?
1239
0
       gnssid =  GNSSID_GAL;
1240
0
       *sigid = 5;    // or maybe 6
1241
0
       break;
1242
0
    case 20:  // Galileo E6
1243
0
       gnssid =  GNSSID_GAL;
1244
0
       *sigid = 8;     // no idea
1245
0
       break;
1246
0
    case 22:  // QZSS L1
1247
0
       gnssid =  GNSSID_QZSS;
1248
0
       *sigid = 0;
1249
0
       break;
1250
0
    case 23:  // QZSS L2C
1251
0
       gnssid =  GNSSID_QZSS;
1252
0
       *sigid = 4;    // or maybe 5
1253
0
       break;
1254
0
    case 24:  // QZSS L5
1255
0
       gnssid =  GNSSID_QZSS;
1256
0
       *sigid = 8;     // no idea
1257
0
       break;
1258
0
    case 26:  // IRNSS L5
1259
0
       gnssid =  GNSSID_IRNSS;
1260
0
       *sigid = 8;     // no idea
1261
0
       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
0
    default:
1281
0
        *sigid = 0xff;
1282
0
        return 0xff;
1283
0
    }
1284
0
    return gnssid;
1285
0
}
1286
1287
// decode Packet x13
1288
static gps_mask_t decode_x13(struct gps_device_t *session, const char *buf,
1289
                             int len)
1290
0
{
1291
0
    gps_mask_t mask = 0;
1292
0
    unsigned u1 = getub(buf, 0);         // Packet ID of non-parsable packet
1293
0
    unsigned u2 = 0;
1294
1295
0
    if (2 <= len) {
1296
0
        u2 = getub(buf, 1);     // Data byte 0 of non-parsable packet
1297
0
    }
1298
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
1299
0
             "TSIP x13: Report Packet: request x%02x %02x "
1300
0
             "cannot be parsed\n",
1301
0
             u1, u2);
1302
    // ignore the rest of the bad data
1303
0
    if (0x8e == (int)u1 &&
1304
0
        0x23 == (int)u2) {
1305
        // no Compact Super Packet 0x8e-23
1306
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
1307
0
                 "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
0
        (void)tsip_write1(session, "\x8e\x20\x01", 3);
1312
0
    }
1313
0
    return mask;
1314
0
}
1315
// decode Superpacket x1c-81
1316
static gps_mask_t decode_x1c_81(struct gps_device_t *session, const char *buf,
1317
                                int len)
1318
0
{
1319
0
    gps_mask_t mask = 0;
1320
0
    char buf2[BUFSIZ];
1321
1322
    // byte 1, reserved
1323
0
    unsigned maj = getub(buf, 2);        // Major version
1324
0
    unsigned min = getub(buf, 3);        // Minor version
1325
0
    unsigned bnum = getub(buf, 4);       // Build number
1326
0
    unsigned bmon = getub(buf, 5);       // Build Month
1327
0
    unsigned bday = getub(buf, 6);       // Build Day
1328
0
    unsigned byr = getbeu16(buf, 7);     // Build Year
1329
0
    unsigned plen = getub(buf, 9);       // Length of product name
1330
1331
    // check for valid module name length
1332
0
    if (40 < plen) {
1333
0
        plen = 40;
1334
0
    }
1335
    // check for valid module name length, again
1336
0
    if ((unsigned)(len - 10) < plen) {
1337
0
        plen = len - 10;
1338
0
    }
1339
    // Product name in ASCII
1340
0
    memcpy(buf2, &buf[10], plen);
1341
0
    buf2[plen] = '\0';
1342
1343
0
    (void)snprintf(session->subtype, sizeof(session->subtype),
1344
0
                   "fw %u.%u %u %02u/%02u/%04u %.40s",
1345
0
                   min, maj, bnum, bmon, bday, byr, buf2);
1346
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1347
0
             "TSIP x1c-81: Firmware version: %s\n",
1348
0
             session->subtype);
1349
1350
0
    mask |= DEVICEID_SET;
1351
0
    if ('\0' == session->subtype1[0]) {
1352
        // request actual subtype1 from 0x1c-83
1353
0
        (void)tsip_write1(session, "\x1c\x03", 2);
1354
0
    }
1355
0
    return mask;
1356
0
}
1357
1358
// decode Superpacket x1c-83
1359
static gps_mask_t decode_x1c_83(struct gps_device_t *session, const char *buf,
1360
                                int len)
1361
0
{
1362
0
    gps_mask_t mask = 0;
1363
0
    char buf2[BUFSIZ];
1364
0
    unsigned long ul1 = getbeu32(buf, 1);  // Serial number
1365
0
    unsigned bday = getub(buf, 5);         // Build day
1366
0
    unsigned bmon = getub(buf, 6);         // Build month
1367
0
    unsigned byr = getbeu16(buf, 7);       // Build year
1368
0
    unsigned u4 = getub(buf, 9);           // Build hour
1369
0
    unsigned u5 = getub(buf, 12);          // Length of Hardware ID
1370
1371
    // Hardware Code
1372
0
    session->driver.tsip.hardware_code = getbeu16(buf, 10);
1373
1374
    // check for valid module name length
1375
    // copernicus ii is 27 long
1376
0
    if (40 < u5) {
1377
0
        u5 = 40;
1378
0
    }
1379
    // check for valid module name length, again
1380
0
    if ((unsigned)(len - 13) < u5) {
1381
0
        u5 = len - 13;
1382
0
    }
1383
0
    memcpy(buf2, &buf[13], u5);
1384
0
    buf2[u5] = '\0';
1385
1386
0
    (void)snprintf(session->gpsdata.dev.sernum,
1387
0
                   sizeof(session->gpsdata.dev.sernum),
1388
0
                   "%lx", ul1);
1389
0
    (void)snprintf(session->subtype1, sizeof(session->subtype1),
1390
0
                   "hw %02u/%02u/%04u %02u %04u %.40s",
1391
0
                   bmon, bday, byr, u4,
1392
0
                   session->driver.tsip.hardware_code,
1393
0
                   buf2);
1394
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1395
0
             "TSIP x1c-83: Hardware vers %s Sernum %s\n",
1396
0
             session->subtype1,
1397
0
             session->gpsdata.dev.sernum);
1398
1399
0
    mask |= DEVICEID_SET;
1400
0
    session->driver.tsip.subtype =
1401
0
        session->driver.tsip.hardware_code;
1402
1403
    // Detecting device by Hardware Code
1404
0
    switch (session->driver.tsip.hardware_code) {
1405
0
    case 3001:            // Acutime Gold
1406
0
        configuration_packets_acutime_gold(session);
1407
0
        break;
1408
1409
    // RES look-alikes
1410
0
    case 3002:            // TSIP_REST
1411
0
        FALLTHROUGH
1412
0
    case 3009:            // TSIP_RESSMT, Model 66266
1413
0
        FALLTHROUGH
1414
0
    case 3017:            // Resolution SMTx,  Model 99889
1415
0
        FALLTHROUGH
1416
0
    case 3023:            // RES SMT 360
1417
0
        FALLTHROUGH
1418
0
    case 3026:            // ICM SMT 360
1419
0
        FALLTHROUGH
1420
0
    case 3031:            // RES360 17x22
1421
0
        FALLTHROUGH
1422
0
    case 3100:            // TSIP_RES720
1423
0
        configuration_packets_res360(session);
1424
0
        break;
1425
1426
    // Unknown
1427
0
    default:
1428
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
1429
0
                 "TSIP x1c-83: Unknown hw code %x\n",
1430
0
                 session->driver.tsip.hardware_code);
1431
0
        FALLTHROUGH
1432
0
    case 1001:            // Lassen iQ
1433
0
        FALLTHROUGH
1434
0
    case 1002:            // Copernicus
1435
0
        FALLTHROUGH
1436
0
    case 1003:            // Copernicus II
1437
0
        FALLTHROUGH
1438
0
    case 3007:            // Thunderbolt E
1439
0
        FALLTHROUGH
1440
0
    case 3032:            // Acutime 360
1441
0
        configuration_packets_generic(session);
1442
0
        break;
1443
0
    }
1444
0
    return mask;
1445
0
}
1446
1447
// decode Superpackets x1c-XX
1448
static gps_mask_t decode_x1c(struct gps_device_t *session, const char *buf,
1449
                             int len, int *pbad_len)
1450
0
{
1451
0
    gps_mask_t mask = 0;
1452
0
    int bad_len = 0;
1453
0
    unsigned u1 = getub(buf, 0);
1454
1455
    // decode by sub-code
1456
0
    switch (u1) {
1457
0
    case 0x81:
1458
        /* Firmware component version information (0x1c-81)
1459
         * polled by 0x1c-01
1460
         * Present in:
1461
         *   Copernicus II (2009)
1462
         */
1463
0
        if (10 > len) {
1464
0
            bad_len = 10;
1465
0
            break;
1466
0
        }
1467
0
        mask = decode_x1c_81(session, buf, len);
1468
0
        break;
1469
1470
0
    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
0
        if (13 > len) {
1480
0
            bad_len = 13;
1481
0
            break;
1482
0
        }
1483
0
        mask = decode_x1c_83(session, buf, len);
1484
0
        break;
1485
0
    default:
1486
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
1487
0
                 "TSIP x1c-%02x: Unhandled subpacket\n", u1);
1488
0
        break;
1489
0
    }
1490
0
    *pbad_len = bad_len;
1491
    // request x8f-42 Stored Production Parameters
1492
0
    (void)tsip_write1(session, "\x8e\x42", 2);
1493
0
    return mask;
1494
0
}
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
0
{
1500
0
    gps_mask_t mask = 0;
1501
0
    timespec_t ts_tow;
1502
0
    char ts_buf[TIMESPEC_LEN];
1503
0
    double ftow = getbef32(buf, 0);                // gpstime
1504
0
    unsigned week = getbes16(buf, 4);              // week, yes, signed!
1505
0
    double f2 = getbef32(buf, 6);                  // leap seconds, fractional!
1506
1507
0
    if (0.0 <= ftow &&
1508
0
        10.0 < f2) {
1509
0
        session->context->leap_seconds = (int)round(f2);
1510
0
        session->context->valid |= LEAP_SECOND_VALID;
1511
0
        DTOTS(&ts_tow, ftow);
1512
0
        session->newdata.time =
1513
0
            gpsd_gpstime_resolv(session, week, ts_tow);
1514
0
        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
0
    }
1519
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1520
0
             "TSIP x41: GPS Time: tow %.3f week %u ls %.1f %s\n",
1521
0
             ftow, week, f2,
1522
0
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)));
1523
0
    GPSD_LOG(LOG_IO, &session->context->errout,
1524
0
             "TSIP: %s",
1525
0
             ctime(&session->newdata.time.tv_sec));
1526
0
    return mask;
1527
0
}
1528
1529
// decode Packet x42
1530
static gps_mask_t decode_x42(struct gps_device_t *session, const char *buf)
1531
0
{
1532
0
    gps_mask_t mask = 0;
1533
0
    timespec_t ts_tow;
1534
0
    double ecefx = getbef32(buf, 0);                  // X
1535
0
    double ecefy = getbef32(buf, 4);                  // Y
1536
0
    double ecefz = getbef32(buf, 8);                  // Z
1537
0
    double ftow = getbef32(buf, 12);           // time-of-fix
1538
1539
0
    session->newdata.ecef.x = ecefx;
1540
0
    session->newdata.ecef.y = ecefy;
1541
0
    session->newdata.ecef.z = ecefz;
1542
0
    DTOTS(&ts_tow, ftow);
1543
0
    session->newdata.time = gpsd_gpstime_resolv(session,
1544
0
                                                session->context->gps_week,
1545
0
                                                ts_tow);
1546
0
    mask = ECEF_SET | TIME_SET | NTPTIME_IS;
1547
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1548
0
        mask |= CLEAR_IS;
1549
0
        session->driver.tsip.last_tow = ts_tow;
1550
0
    }
1551
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1552
0
             "TSIP x42: SP-XYZ: %f %f %f ftow %f\n",
1553
0
             session->newdata.ecef.x,
1554
0
             session->newdata.ecef.y,
1555
0
             session->newdata.ecef.z,
1556
0
             ftow);
1557
0
    return mask;
1558
0
}
1559
1560
// Decode Protocol Version: x43
1561
static gps_mask_t decode_x43(struct gps_device_t *session, const char *buf)
1562
0
{
1563
0
    gps_mask_t mask = 0;
1564
0
    timespec_t ts_tow;
1565
0
    double vx = getbef32(buf, 0);               // X velocity, m/s
1566
0
    double vy = getbef32(buf, 4);               // Y velocity, m/s
1567
0
    double vz = getbef32(buf, 8);               // Z velocity, m/s
1568
0
    double bias_rate = getbef32(buf, 12);       // bias rate, m/s
1569
0
    double ftow = getbef32(buf, 16);            // time-of-fix
1570
1571
0
    session->newdata.ecef.vx = vx;
1572
0
    session->newdata.ecef.vy = vy;
1573
0
    session->newdata.ecef.vz = vz;
1574
1575
    // short circuit to gpsdata. Convert m/s to ns/s
1576
0
    session->gpsdata.fix.clockdrift = 1e9 * bias_rate / CLIGHT;
1577
1578
0
    DTOTS(&ts_tow, ftow);
1579
0
    session->newdata.time = gpsd_gpstime_resolv(session,
1580
0
                                                session->context->gps_week,
1581
0
                                                ts_tow);
1582
0
    mask = VECEF_SET | TIME_SET | NTPTIME_IS;
1583
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1584
0
        mask |= CLEAR_IS;
1585
0
        session->driver.tsip.last_tow = ts_tow;
1586
0
    }
1587
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1588
0
             "TSIP x43: Vel XYZ: %f %f %f %f ftow %f\n",
1589
0
             session->newdata.ecef.vx,
1590
0
             session->newdata.ecef.vy,
1591
0
             session->newdata.ecef.vz,
1592
0
             bias_rate, ftow);
1593
0
    return mask;
1594
0
}
1595
1596
// Decode x45
1597
static gps_mask_t decode_x45(struct gps_device_t *session, const char *buf)
1598
0
{
1599
0
    gps_mask_t mask = 0;
1600
0
    unsigned nmaj = getub(buf, 0);
1601
0
    unsigned nmin = getub(buf, 1);
1602
0
    unsigned nmon = getub(buf, 2);
1603
0
    unsigned nday = getub(buf, 3);
1604
0
    unsigned nyr = getub(buf, 4) + 1900;
1605
0
    unsigned fmaj = getub(buf, 5);
1606
0
    unsigned fmin = getub(buf, 6);
1607
0
    unsigned fmon = getub(buf, 7);
1608
0
    unsigned fday = getub(buf, 8);
1609
0
    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
0
    (void)snprintf(session->subtype, sizeof(session->subtype),
1616
0
                   "sw %u.%u %02u/%02u/%04u hw %u.%u %02u/%02u/%04u",
1617
0
                   nmaj, nmin, nmon, nday, nyr,
1618
0
                   fmaj, fmin, fmon, fday, fyr);
1619
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1620
0
             "TSIP x45: Software version: %s\n", session->subtype);
1621
0
    mask |= DEVICEID_SET;
1622
1623
    // request I/O Options (0x55)
1624
0
    (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
0
    (void)tsip_write1(session, "\x1c\x01", 2);
1630
0
    return mask;
1631
0
}
1632
1633
// Decode Health of Receiver, x46
1634
static gps_mask_t decode_x46(struct gps_device_t *session, const char *buf)
1635
0
{
1636
0
    gps_mask_t mask = 0;
1637
0
    char buf2[80];
1638
    // Status code, see vgnss_decode_status
1639
0
    unsigned status = getub(buf, 0);
1640
0
    unsigned ec = getub(buf, 1);      // error codes
1641
1642
0
    switch (status) {
1643
0
    case 0:         //  "Doing Fixes"
1644
        // could be 2D or 3D.  So check the last setting.
1645
0
        if (MODE_2D >= session->oldfix.mode) {
1646
0
            session->newdata.mode = MODE_2D;  // At least 2D
1647
0
        } else {
1648
0
            session->newdata.mode = MODE_3D;
1649
0
        }
1650
0
        break;
1651
0
    case 9:          // "1 usable sat"
1652
0
        session->newdata.mode = MODE_2D;
1653
0
        break;
1654
0
    case 10:         // "2 usable sats"
1655
0
        session->newdata.mode = MODE_2D;
1656
0
        break;
1657
0
    case 11:         // "3 usable sats"
1658
0
        session->newdata.mode = MODE_2D;
1659
0
        break;
1660
0
    case 1:          // "No GPS time"
1661
0
        FALLTHROUGH
1662
0
    case 2:          // "Needs Init"
1663
0
        FALLTHROUGH
1664
0
    case 3:          // "PDOP too high"
1665
0
        FALLTHROUGH
1666
0
    case 8:          // "0 usable sats"
1667
0
        FALLTHROUGH
1668
0
    case 12:         // "chosen sat unusable"
1669
0
        FALLTHROUGH
1670
0
    case 16:         // "TRAIM rejected"
1671
0
        session->newdata.mode = MODE_NO_FIX;
1672
0
        break;
1673
0
    case 0xbb:       // "GPS Time Fix (OD mode)"
1674
        // Always on after survey, so no info here.
1675
0
        break;
1676
0
    }
1677
0
    if (MODE_NOT_SEEN != session->newdata.mode) {
1678
0
        mask |= MODE_SET;
1679
0
    }
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
0
    switch (ec & 0x30) {
1687
0
    case 0x10:
1688
0
        session->newdata.ant_stat = ANT_OPEN;
1689
0
        break;
1690
0
    case 0x30:
1691
0
        session->newdata.ant_stat = ANT_SHORT;
1692
0
        break;
1693
0
    default:
1694
0
        session->newdata.ant_stat = ANT_OK;
1695
0
        break;
1696
0
    }
1697
1698
0
    if (STATUS_UNK != session->newdata.status) {
1699
0
        mask |= STATUS_SET;
1700
0
    }
1701
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1702
0
             "TSIP x46: Receiver Health: mode %d status %d  gds:x%x "
1703
0
             "ec:x%x\n",
1704
0
            session->newdata.mode,
1705
0
            session->newdata.status,
1706
0
            status, ec);
1707
0
    GPSD_LOG(LOG_IO, &session->context->errout,
1708
0
             "TSIP: gds:%s ec:%s\n",
1709
0
             val2str(status, vgnss_decode_status),
1710
0
             flags2str(ec, verr_codes, buf2, sizeof(buf2)));
1711
0
    return mask;
1712
0
}
1713
1714
// Decode x47
1715
static gps_mask_t decode_x47(struct gps_device_t *session, const char *buf,
1716
                             int len, int *pbad_len)
1717
0
{
1718
0
    gps_mask_t mask = 0;
1719
0
    char buf2[BUFSIZ];
1720
0
    int i;
1721
1722
    // satellite count, RES SMT 360 doc says 12 max
1723
0
    int count = getub(buf, 0);
1724
1725
0
    if (count < TSIP_CHANNELS) {
1726
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
1727
0
                 "TSIP x47: Too many satellites %d\n", count);
1728
0
        return 0;
1729
0
    }
1730
1731
    // Status code, see vgnss_decode_status
1732
0
    gpsd_zero_satellites(&session->gpsdata);
1733
1734
    // packet too short?
1735
0
    if ((5 * count + 1) > len) {
1736
0
        *pbad_len = 5 * count + 1;
1737
0
        return mask;
1738
0
    }
1739
0
    *pbad_len = 0;
1740
0
    buf2[0] = '\0';
1741
0
    for (i = 0; i < count; i++) {
1742
0
        unsigned j;
1743
0
        int PRN = getub(buf, 5 * i + 1);
1744
0
        double snr = getbef32(buf, 5 * i + 2);
1745
1746
0
        if (0 > snr) {
1747
0
            snr = 0.0;
1748
0
        }
1749
0
        for (j = 0; j < TSIP_CHANNELS; j++) {
1750
0
            if (session->gpsdata.skyview[j].PRN == PRN) {
1751
0
                session->gpsdata.skyview[j].ss = snr;
1752
0
                break;
1753
0
            }
1754
0
        }
1755
0
        str_appendf(buf2, sizeof(buf2), " %u=%.1f", PRN, snr);
1756
0
    }
1757
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1758
0
             "TSIP x47: Signal Levels: (%d):%s\n", count, buf2);
1759
0
    mask |= SATELLITE_SET;
1760
0
    return mask;
1761
0
}
1762
1763
// Decode x4a
1764
static gps_mask_t decode_x4a(struct gps_device_t *session, const char *buf)
1765
0
{
1766
0
    gps_mask_t mask = 0;
1767
0
    timespec_t ts_tow;
1768
0
    char ts_buf[TIMESPEC_LEN];
1769
0
    double lat = getbef32(buf, 0) * RAD_2_DEG;   // lat
1770
0
    double lon = getbef32(buf, 4) * RAD_2_DEG;   // lon
1771
0
    double alt = getbef32(buf, 8);               // alt
1772
0
    double clock_bias = getbef32(buf, 12);       // clock bias, m/s
1773
0
    double ftow = getbef32(buf, 16);             // time-of-fix
1774
1775
0
    session->newdata.latitude = lat;
1776
0
    session->newdata.longitude = lon;
1777
    // depending on GPS config, could be either WGS84 or MSL
1778
0
    if (0 == session->driver.tsip.alt_is_msl) {
1779
0
        session->newdata.altHAE = alt;
1780
0
    } else {
1781
0
        session->newdata.altMSL = alt;
1782
0
    }
1783
    // short circuit to gpsdata. COnvert m/s to ns
1784
0
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
1785
1786
0
    if (0 != (session->context->valid & GPS_TIME_VALID)) {
1787
0
        DTOTS(&ts_tow, ftow);
1788
0
        session->newdata.time =
1789
0
            gpsd_gpstime_resolv(session, session->context->gps_week,
1790
0
                                ts_tow);
1791
0
        mask |= TIME_SET | NTPTIME_IS;
1792
0
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1793
0
            mask |= CLEAR_IS;
1794
0
            session->driver.tsip.last_tow = ts_tow;
1795
0
        }
1796
0
    }
1797
    // this seems to be often first in cycle
1798
    // REPORT_IS here breaks reports in read-only mode
1799
0
    mask |= LATLON_SET | ALTITUDE_SET;
1800
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1801
0
             "TSIP x4a: SP-LLA: time=%s lat=%.2f lon=%.2f "
1802
0
             "alt=%.2f cbias %.2f\n",
1803
0
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
1804
0
             session->newdata.latitude,
1805
0
             session->newdata.longitude, alt, clock_bias);
1806
0
    return mask;
1807
0
}
1808
1809
// Decode x4b
1810
static gps_mask_t decode_x4b(struct gps_device_t *session, const char *buf)
1811
0
{
1812
0
    gps_mask_t mask = 0;
1813
0
    char buf2[80];
1814
0
    char buf3[80];
1815
0
    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
0
    unsigned u2 = getub(buf, 1);     // status 1
1820
0
    unsigned u3 = getub(buf, 2);     // Status 2/Superpacket Support
1821
1822
0
    session->driver.tsip.machine_id = u1;  // Machine ID
1823
1824
0
    if ('\0' == session->subtype[0]) {
1825
0
        const char *name;
1826
        // better than nothing
1827
0
        switch (session->driver.tsip.machine_id) {
1828
0
        case 1:
1829
            // should use better name from superpacket
1830
0
            name = " SMT 360";
1831
            /* request actual subtype from 0x1c-81
1832
             * which in turn requests 0x1c-83 */
1833
0
            (void)tsip_write1(session, "\x1c\x01", 2);
1834
0
            break;
1835
0
        case 0x32:
1836
0
            name = " Acutime 360";
1837
0
            break;
1838
0
        case 0x5a:
1839
0
            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
0
            (void)tsip_write1(session, "\x1c\x01", 2);
1844
0
            break;
1845
0
        case 0x61:
1846
0
            name = " Acutime 2000";
1847
0
            break;
1848
0
        case 0x62:
1849
0
            name = " ACE UTC";
1850
0
            break;
1851
0
        case 0x96:
1852
            // Also Copernicus II
1853
0
            name = " Copernicus, Thunderbolt E";
1854
            /* so request actual subtype from 0x1c-81
1855
             * which in turn requests 0x1c-83 */
1856
0
            (void)tsip_write1(session, "\x1c\x01", 2);
1857
0
            break;
1858
0
        case 0:
1859
            // Resolution SMTx
1860
0
            FALLTHROUGH
1861
0
        default:
1862
0
             name = "";
1863
0
        }
1864
0
        (void)snprintf(session->subtype, sizeof(session->subtype),
1865
0
                       "Machine ID x%x(%s)",
1866
0
                       session->driver.tsip.machine_id, name);
1867
0
    }
1868
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1869
0
             "TSIP x4b: Machine ID: %02x %02x %02x\n",
1870
0
             session->driver.tsip.machine_id,
1871
0
             u2, u3);
1872
0
    GPSD_LOG(LOG_IO, &session->context->errout,
1873
0
             "TSIP: stat1:%s stat2:%s\n",
1874
0
             flags2str(u2, vstat1, buf2, sizeof(buf2)),
1875
0
             flags2str(u3, vstat2, buf3, sizeof(buf3)));
1876
1877
0
    if (u3 != session->driver.tsip.superpkt) {
1878
0
        session->driver.tsip.superpkt = u3;
1879
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
1880
0
                 "TSIP: Switching to Super Packet mode %d\n", u3);
1881
0
        switch (u3){
1882
0
        default:
1883
0
            FALLTHROUGH
1884
0
        case 0:
1885
            // old Trimble, no superpackets
1886
0
            break;
1887
0
        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
0
            buf2[0] = 0x35;
1893
0
            buf2[1] = IO1_8F20|IO1_DP|IO1_ECEF;
1894
0
            buf2[2] = 0x00;          // Velocity: none (via SP)
1895
0
            buf2[3] = 0x00;          // Time: GPS
1896
0
            buf2[4] = IO4_DBHZ;      // Aux: dBHz
1897
0
            (void)tsip_write1(session, buf2, 5);
1898
0
            break;
1899
0
        case 2:
1900
            /* 2 == SMT 360, or Resolution SMTx
1901
             * no 0x8f-20, or x8f-23.
1902
             * request x8f-a5 */
1903
0
            (void)tsip_write1(session, "\x8e\xa5", 2);
1904
0
            break;
1905
0
        }
1906
0
    }
1907
1908
0
    return mask;
1909
0
}
1910
1911
// Decode x4c
1912
static gps_mask_t decode_x4c(struct gps_device_t *session, const char *buf)
1913
0
{
1914
0
    gps_mask_t mask = 0;
1915
0
    unsigned u1 = getub(buf, 0);                  // Dynamics Code
1916
0
    double f1 = getbef32(buf, 1) * RAD_2_DEG;     // Elevation Mask
1917
0
    double f2 = getbef32(buf, 5);                 // Signal Level Mask
1918
0
    double f3 = getbef32(buf, 9);                 // PDOP Mask
1919
0
    double f4 = getbef32(buf, 13);                // PDOP Switch
1920
1921
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1922
0
             "TSIP x4c: OP: Dyn x%02x El %f Sig %f PDOP %f %f\n",
1923
0
             u1, f1, f2, f3, f4);
1924
0
    GPSD_LOG(LOG_IO, &session->context->errout,
1925
0
             "TSIP: Dynamics:%s\n",
1926
0
             val2str(u1, vx4c_dyncode));
1927
0
    return mask;
1928
0
}
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
0
{
1942
0
    gps_mask_t mask = 0;
1943
0
    timespec_t ts_tow;
1944
0
    double clock_bias = getbef32(buf, 0);         // clock Bias, m
1945
0
    double clock_rate = getbef32(buf, 4);         // clock Bias rate, m/s
1946
0
    double ftow = getbef32(buf, 8);               // tow
1947
1948
0
    DTOTS(&ts_tow, ftow);
1949
0
    session->newdata.time =
1950
0
        gpsd_gpstime_resolv(session, session->context->gps_week, ts_tow);
1951
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
1952
0
        mask |= CLEAR_IS;
1953
0
        session->driver.tsip.last_tow = ts_tow;
1954
0
    }
1955
    // short circuit to gpsdata. Convert m to ns
1956
0
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
1957
0
    session->gpsdata.fix.clockdrift = 1e9 * clock_rate / CLIGHT;
1958
1959
0
    mask |= TIME_SET | NTPTIME_IS;
1960
1961
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1962
0
            "TSIP x54: BBRR: Bias %f brate %f tow %f\n",
1963
0
            clock_bias, clock_rate, ftow);
1964
0
    return mask;
1965
0
}
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
0
{
1971
0
    gps_mask_t mask = 0;
1972
0
    char buf2[80];
1973
0
    char buf3[80];
1974
0
    char buf4[80];
1975
0
    char buf5[80];
1976
1977
0
    unsigned u1 = getub(buf, 0);     // Position
1978
0
    unsigned u2 = getub(buf, 1);     // Velocity
1979
    /* Timing
1980
     * bit 0 - reserved use 0x8e-a2 ?
1981
     */
1982
0
    unsigned u3 = getub(buf, 2);
1983
    /* Aux
1984
     * bit 0 - packet 0x5a (raw data)
1985
     * bit 3 -- Output dbHz
1986
     */
1987
0
    unsigned u4 = getub(buf, 3);
1988
1989
    // decode HAE/MSL from Position byte
1990
0
    if (IO1_MSL == (IO1_MSL & u1)) {
1991
0
        session->driver.tsip.alt_is_msl = 1;
1992
0
    } else {
1993
0
        session->driver.tsip.alt_is_msl = 0;
1994
0
    }
1995
1996
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
1997
0
             "TSIP x55: IO Options: %02x %02x %02x %02x\n",
1998
0
             u1, u2, u3, u4);
1999
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2000
0
             "TSIPv1: pos:%s vel:%s timing:%s aux:%s\n",
2001
0
             flags2str(u1, vx55_pos, buf2, sizeof(buf2)),
2002
0
             flags2str(u2, vx55_vel, buf3, sizeof(buf3)),
2003
0
             flags2str(u3, vx55_timing, buf4, sizeof(buf4)),
2004
0
             flags2str(u4, vx55_aux, buf5, sizeof(buf5)));
2005
0
    if ((u1 & 0x20) != (uint8_t) 0) {
2006
        /* Try to get Super Packets
2007
         * Turn off 0x8f-20 LFwEI Super Packet */
2008
0
        (void)tsip_write1(session, "\x8e\x20\x00", 3);
2009
2010
        // Turn on Compact Super Packet 0x8f-23
2011
0
        (void)tsip_write1(session, "\x8e\x23\x01", 3);
2012
0
        session->driver.tsip.req_compact = now;
2013
0
    }
2014
0
    return mask;
2015
0
}
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
0
{
2020
0
    gps_mask_t mask = 0;
2021
0
    timespec_t ts_tow;
2022
2023
0
    float f1 = getbef32(buf, 0);        // East velocity
2024
0
    float f2 = getbef32(buf, 4);        // North velocity
2025
0
    float f3 = getbef32(buf, 8);        // Up velocity
2026
0
    float cbias = getbef32(buf, 12);    // clock bias rate, m/s
2027
0
    float ftow = getbef32(buf, 16);     // time-of-fix
2028
2029
    // Could be GPS, or UTC...
2030
0
    DTOTS(&ts_tow, ftow);
2031
0
    session->newdata.time = gpsd_gpstime_resolv(session,
2032
0
                                                session->context->gps_week,
2033
0
                                                ts_tow);
2034
0
    session->newdata.NED.velN = f2;
2035
0
    session->newdata.NED.velE = f1;
2036
0
    session->newdata.NED.velD = -f3;
2037
    // short circuit to gpsdata. Convert m to ns
2038
0
    session->gpsdata.fix.clockdrift = 1e9 * cbias / CLIGHT;
2039
2040
0
    mask |= VNED_SET | TIME_SET | NTPTIME_IS;
2041
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2042
0
        mask |= CLEAR_IS;
2043
0
        session->driver.tsip.last_tow = ts_tow;
2044
0
    }
2045
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2046
0
             "TSIP x56: Vel ENU: %f %f %f cbias %f ftow %f\n",
2047
0
             f1, f2, f3, cbias, ftow);
2048
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2049
0
             "TSIP: %s",
2050
0
             ctime(&session->newdata.time.tv_sec));
2051
0
    return mask;
2052
0
}
2053
2054
// Decode x57
2055
static gps_mask_t decode_x57(struct gps_device_t *session, const char *buf)
2056
0
{
2057
0
    gps_mask_t mask = 0;
2058
0
    timespec_t ts_tow;
2059
0
    char buf2[80];
2060
0
    unsigned u1 = getub(buf, 0);                     // Source of information
2061
0
    unsigned u2 = getub(buf, 1);                     // Mfg. diagnostic
2062
0
    double ftow = getbef32(buf, 2);                  // gps_time
2063
0
    unsigned week = getbeu16(buf, 6);                // tsip.gps_week
2064
2065
0
    if (0x01 == u1) {
2066
        // good current fix
2067
0
        DTOTS(&ts_tow, ftow);
2068
0
        (void)gpsd_gpstime_resolv(session, week, ts_tow);
2069
0
        mask |= TIME_SET | NTPTIME_IS;
2070
0
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2071
0
            mask |= CLEAR_IS;
2072
0
            session->driver.tsip.last_tow = ts_tow;
2073
0
        }
2074
0
    }
2075
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2076
0
             "TSIP x57: Fix info: %02x %02x %u %f\n",
2077
0
             u1, u2, week, ftow);
2078
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2079
0
             "TSIP: info:%s fmode:%s\n",
2080
0
             flags2str(u1, vx57_info, buf2, sizeof(buf2)),
2081
0
             val2str(u1, vx57_fmode));
2082
0
    return mask;
2083
0
}
2084
2085
// Decode x5a
2086
static gps_mask_t decode_x5a(struct gps_device_t *session, const char *buf)
2087
0
{
2088
0
    gps_mask_t mask = 0;
2089
    // Useless without the pseudorange...
2090
0
    unsigned u1 = getub(buf, 0);             // PRN 1-237
2091
0
    float f1 = getbef32(buf, 1);             // sample length
2092
0
    float f2 = getbef32(buf, 5);             // Signal Level, dbHz
2093
0
    float f3 = getbef32(buf, 9);             // Code phase, 1/16th chip
2094
0
    float f4 = getbef32(buf, 13);            // Doppler, Hz @ L1
2095
0
    double d1 = getbed64(buf, 17);           // Time of Measurement
2096
2097
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2098
0
             "TSIP x5a: Raw Measurement Data: PRN %d len %f SNR %f chip %f "
2099
0
             "doppler %f tom %f\n",
2100
0
             u1, f1, f2, f3, f4, d1);
2101
0
    return mask;
2102
0
}
2103
2104
// Decode Satellite Tracking Status, packet x5c
2105
static gps_mask_t decode_x5c(struct gps_device_t *session, const char *buf)
2106
0
{
2107
0
    gps_mask_t mask = 0;
2108
0
    timespec_t ts_tow;
2109
0
    int i;
2110
    // Useless without the pseudorange...
2111
0
    int PRN = getub(buf, 0);                     // PRN 1-32
2112
    // slot unused in Lassen IQ
2113
0
    unsigned u2 = getub(buf, 1);                 // slot:chan
2114
0
    unsigned acq = getub(buf, 2);                // Acquisition flag
2115
0
    unsigned eflag = getub(buf, 3);              // Ephemeris flag
2116
0
    double snr = getbef32(buf, 4);               // Signal level
2117
    // time of skyview, not current time, nor time of fix
2118
0
    double ftow = getbef32(buf, 8);
2119
2120
0
    double el = getbef32(buf, 12) * RAD_2_DEG;   // Elevation
2121
0
    double az = getbef32(buf, 16) * RAD_2_DEG;   // Azimuth
2122
2123
    // Old Measurement flag, unused in Lassen IQ
2124
0
    unsigned omf = getub(buf, 20);
2125
2126
0
    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
0
    i = (int)(u2 >> 3);     // channel number, starting at 0
2133
0
    if (0 == i) {
2134
        // start of new cycle, save last count
2135
0
        session->gpsdata.satellites_visible =
2136
0
            session->driver.tsip.last_chan_seen;
2137
0
    } 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
0
    } else if (0 == PRN ||
2142
0
               32 < PRN) {
2143
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2144
0
                "TSIPv1 x5c: invalid prn %d\n", PRN);
2145
0
        return 0;
2146
0
    }
2147
0
    session->driver.tsip.last_chan_seen = i;
2148
2149
0
    session->gpsdata.skyview[i].PRN = PRN;
2150
0
    session->gpsdata.skyview[i].svid = PRN;
2151
0
    session->gpsdata.skyview[i].gnssid = GNSSID_GPS;
2152
0
    session->gpsdata.skyview[i].ss = snr;
2153
0
    session->gpsdata.skyview[i].elevation = el;
2154
0
    session->gpsdata.skyview[i].azimuth = az;
2155
0
    session->gpsdata.skyview[i].gnssid = tsip_gnssid(0, PRN,
2156
0
        &session->gpsdata.skyview[i].svid);
2157
0
    if (2 == (2 & eflag)) {
2158
0
        session->gpsdata.skyview[i].health = SAT_HEALTH_OK;
2159
0
    } else if (1 == eflag) {
2160
0
        session->gpsdata.skyview[i].health = SAT_HEALTH_BAD;
2161
0
    } // else, unknown
2162
2163
0
    if (0x10 == (0x10 & eflag)) {
2164
0
        session->gpsdata.skyview[i].used = true;
2165
0
        if (51 == eflag) {
2166
0
            session->newdata.status = STATUS_DGPS;
2167
0
            mask |= STATUS_SET;
2168
0
        }
2169
0
    } else {
2170
0
        session->gpsdata.skyview[i].used = false;
2171
0
    }
2172
    /* when polled by 0x3c, all the skyview times will be the same
2173
     * in one cluster */
2174
0
    if (0.0 < ftow) {
2175
0
        DTOTS(&ts_tow, ftow);
2176
0
        session->gpsdata.skyview_time =
2177
0
            gpsd_gpstime_resolv(session, session->context->gps_week,
2178
0
                                ts_tow);
2179
        /* do not save in session->driver.tsip.last_tow
2180
         * as this is skyview time, not fix time */
2181
0
    }
2182
0
    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
0
        mask |= SATELLITE_SET;
2187
0
        session->gpsdata.satellites_visible = i + 1;
2188
0
    }
2189
0
    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
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2198
0
             "TSIP x5c: Satellite Tracking Status: Ch %2d PRN %3d "
2199
0
             "es %d Acq %d Eph %2d SNR %4.1f LMT %.04f El %.1f Az %.1f "
2200
0
             "omf %u hlth %u\n",
2201
0
             i, PRN, u2 & 7, acq, eflag, snr, ftow, el, az, omf,
2202
0
            session->gpsdata.skyview[i].health);
2203
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2204
0
             "TSIP: acq:%s eflag:%s\n",
2205
0
             val2str(acq, vx5c_acq),
2206
0
             val2str(eflag, vx5c_eflag));
2207
2208
0
    return mask;
2209
0
}
2210
2211
// Decode x5d
2212
static gps_mask_t decode_x5d(struct gps_device_t *session, const char *buf)
2213
0
{
2214
0
    gps_mask_t mask = 0;
2215
0
    timespec_t ts_tow;
2216
0
    char buf2[BUFSIZ];
2217
0
    unsigned char u1 = getub(buf, 0);           // PRN
2218
0
    int i = getub(buf, 1);                      // chan
2219
0
    unsigned u3 = getub(buf, 2);                // Acquisition flag
2220
0
    unsigned u4 = getub(buf, 3);                // used?
2221
0
    double f1 = getbef32(buf, 4);               // SNR
2222
    // This can be one second behind the TPV on RES SMT 360
2223
0
    double ftow = getbef32(buf, 8);             // time of Last measurement
2224
0
    double d1 = getbef32(buf, 12) * RAD_2_DEG;  // Elevation
2225
0
    double d2 = getbef32(buf, 16) * RAD_2_DEG;  // Azimuth
2226
0
    unsigned u5 = getub(buf, 20);               // old measurement flag
2227
0
    unsigned u6 = getub(buf, 21);               // integer msec flag
2228
0
    unsigned u7 = getub(buf, 22);               // bad data flag
2229
0
    unsigned u8 = getub(buf, 23);               // data collection flag
2230
0
    unsigned u9 = getub(buf, 24);               // Used flags
2231
0
    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
0
    if (0 == i) {
2239
        // start of new cycle, save last count
2240
0
        session->gpsdata.satellites_visible =
2241
0
            session->driver.tsip.last_chan_seen;
2242
0
    } else if (i >= TSIP_CHANNELS) {
2243
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2244
0
                 "TSIP x5d: Satellite Tracking Status: Too many chans %d\n", i);
2245
0
        return 0;
2246
0
    }
2247
0
    session->driver.tsip.last_chan_seen = i;
2248
2249
0
    session->gpsdata.skyview[i].PRN = u1;
2250
0
    session->gpsdata.skyview[i].ss = f1;
2251
0
    session->gpsdata.skyview[i].elevation = d1;
2252
0
    session->gpsdata.skyview[i].azimuth = d2;
2253
0
    session->gpsdata.skyview[i].used = (bool)u4;
2254
0
    session->gpsdata.skyview[i].gnssid = tsip_gnssid(u10, u1,
2255
0
        &session->gpsdata.skyview[i].svid);
2256
0
    if (0 == u7) {
2257
0
        session->gpsdata.skyview[i].health = SAT_HEALTH_OK;
2258
0
    } else {
2259
0
        session->gpsdata.skyview[i].health = SAT_HEALTH_BAD;
2260
0
    }
2261
2262
    /* when polled by 0x3c, all the skyview times will be the same
2263
     * in one cluster */
2264
0
    if (0.0 < ftow) {
2265
0
        DTOTS(&ts_tow, ftow);
2266
0
        session->gpsdata.skyview_time =
2267
0
            gpsd_gpstime_resolv(session, session->context->gps_week,
2268
0
                                ts_tow);
2269
        /* do not save in session->driver.tsip.last_tow
2270
         * as this is skyview time, not fix time */
2271
0
    }
2272
0
    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
0
        mask |= SATELLITE_SET;
2277
0
        session->gpsdata.satellites_visible = i;
2278
0
    }
2279
    /* If this series has fewer than last series there will
2280
     * be no SKY, unless the cycle ender pushes the SKY */
2281
2282
0
    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
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2289
0
            "TSIP x5d: Satellite Tracking Status: Ch %2d Con %d PRN %3d "
2290
0
            "Acq %d Use %d SNR %4.1f LMT %.04f El %4.1f Az %5.1f Old %d "
2291
0
            "Int %d Bad %d Col %d TPF %d SVT %d\n",
2292
0
            i, u10, u1, u3, u4, f1, ftow, d1, d2, u5, u6, u7, u8, u9, u10);
2293
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2294
0
             "TSIP: bad:%s uflags:%s scons:%s\n",
2295
0
             val2str(u7, vsv_bad),
2296
0
             flags2str(u9, vsv_used_flags, buf2, sizeof(buf2)),
2297
0
             val2str(u10, vsv_type));
2298
0
    return mask;
2299
0
}
2300
2301
// Decode x6c
2302
static gps_mask_t decode_x6c(struct gps_device_t *session, const char *buf,
2303
                             int len, int *pbad_len)
2304
0
{
2305
0
    gps_mask_t mask = 0;
2306
0
    char buf2[80];
2307
0
    int i, count;
2308
0
    unsigned fixdm = getub(buf, 0);          // fix dimension, mode
2309
0
    double pdop = getbef32(buf, 1);
2310
0
    double hdop = getbef32(buf, 5);
2311
0
    double vdop = getbef32(buf, 9);
2312
    // RES SMT 360 and ICM SMT 360 always report tdop == 1
2313
0
    double tdop = getbef32(buf, 13);
2314
2315
0
    if (IN(0.01, pdop, 89.99)) {
2316
        // why not to newdata?
2317
0
        session->gpsdata.dop.pdop = pdop;
2318
0
        mask |= DOP_SET;
2319
0
    }
2320
0
    if (IN(0.01, hdop, 89.99)) {
2321
        // why not to newdata?
2322
0
        session->gpsdata.dop.hdop = hdop;
2323
0
        mask |= DOP_SET;
2324
0
    }
2325
0
    if (IN(0.01, vdop, 89.99)) {
2326
        // why not to newdata?
2327
0
        session->gpsdata.dop.vdop = vdop;
2328
0
        mask |= DOP_SET;
2329
0
    }
2330
0
    if (IN(0.01, tdop, 89.99)) {
2331
        // why not to newdata?
2332
0
        session->gpsdata.dop.tdop = tdop;
2333
0
        mask |= DOP_SET;
2334
0
    }
2335
2336
0
    count = getub(buf, 17);
2337
2338
0
    if ((18 + count) > len) {
2339
0
        *pbad_len = 18 + count;
2340
0
        return mask;
2341
0
    }
2342
2343
0
    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
0
    *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
0
    switch (fixdm & 7) {       // dimension
2360
0
    case 1:       // clock fix (surveyed in)
2361
0
        FALLTHROUGH
2362
0
    case 5:       // Overdetermined clock fix
2363
0
        session->newdata.status = STATUS_TIME;
2364
0
        session->newdata.mode = MODE_3D;
2365
0
        break;
2366
0
    case 3:
2367
0
        session->newdata.mode = MODE_2D;
2368
0
        break;
2369
0
    case 4:
2370
0
        session->newdata.mode = MODE_3D;
2371
0
        break;
2372
0
    case 6:
2373
        // Accutime
2374
0
        session->newdata.status = STATUS_DGPS;
2375
0
        session->newdata.mode = MODE_3D;
2376
0
        break;
2377
0
    case 0:
2378
        // Sometimes this is No Fix, sometimes Auto....
2379
0
        FALLTHROUGH
2380
0
    case 2:
2381
0
        FALLTHROUGH
2382
0
    case 7:
2383
0
        FALLTHROUGH
2384
0
    default:
2385
0
        session->newdata.mode = MODE_NO_FIX;
2386
0
        break;
2387
0
    }
2388
0
    if (8 == (fixdm & 8)) {      // fix mode
2389
        // Manual (Surveyed in)
2390
0
        if (count) {
2391
0
            session->newdata.status = STATUS_TIME;
2392
0
        } else {
2393
            // no saats, must be DR
2394
0
            session->newdata.status = STATUS_DR;
2395
0
        }
2396
0
    }
2397
0
    if (STATUS_UNK < session->newdata.status) {
2398
0
        mask |= STATUS_SET;
2399
0
    }
2400
0
    mask |= MODE_SET;
2401
2402
0
    session->gpsdata.satellites_used = count;
2403
2404
0
    memset(session->driver.tsip.sats_used, 0,
2405
0
            sizeof(session->driver.tsip.sats_used));
2406
0
    buf2[0] = '\0';
2407
0
    for (i = 0; i < count; i++) {
2408
        // negative PRN means sat unhealthy why use an unhealthy sat??
2409
0
        session->driver.tsip.sats_used[i] = getsb(buf, 18 + i);
2410
0
        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
0
    }
2415
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2416
0
             "TSIP x6c: AIVSS: mode %d status %d used %d "
2417
0
             "pdop %.1f hdop %.1f vdop %.1f tdop %.1f Used %s fixdm x%x\n",
2418
0
             session->newdata.mode,
2419
0
             session->newdata.status,
2420
0
             session->gpsdata.satellites_used,
2421
0
             pdop, hdop, vdop, tdop, buf2, fixdm);
2422
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2423
0
             "TSIP: fixd:%s\n",
2424
0
             flags2str(fixdm, vfix, buf2, sizeof(buf2)));
2425
0
    mask |= USED_IS;
2426
0
    return mask;
2427
0
}
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
                             int len, int *pbad_len)
2432
0
{
2433
0
    gps_mask_t mask = 0;
2434
0
    int i;
2435
0
    char buf2[BUFSIZ];
2436
2437
0
    unsigned fix_dim = getub(buf, 0);     // nsvs/dimension
2438
0
    int count = (int)((fix_dim >> 4) & 0x0f);
2439
0
    double pdop = getbef32(buf, 1);
2440
0
    double hdop = getbef32(buf, 5);
2441
0
    double vdop = getbef32(buf, 9);
2442
0
    double tdop = getbef32(buf, 13);
2443
2444
0
    if ((17 + count) > len) {
2445
0
        *pbad_len = 17 + count;
2446
0
        return 0;
2447
0
    }
2448
0
    *pbad_len = 0;
2449
2450
0
    session->gpsdata.satellites_used = count;
2451
0
    if (IN(0.01, pdop, 89.99)) {
2452
        // why not to newdata?
2453
0
        session->gpsdata.dop.pdop = pdop;
2454
0
        mask |= DOP_SET;
2455
0
    }
2456
0
    if (IN(0.01, hdop, 89.99)) {
2457
        // why not to newdata?
2458
0
        session->gpsdata.dop.hdop = hdop;
2459
0
        mask |= DOP_SET;
2460
0
    }
2461
0
    if (IN(0.01, vdop, 89.99)) {
2462
        // why not to newdata?
2463
0
        session->gpsdata.dop.vdop = vdop;
2464
0
        mask |= DOP_SET;
2465
0
    }
2466
0
    if (IN(0.01, tdop, 89.99)) {
2467
        // why not to newdata?
2468
0
        session->gpsdata.dop.tdop = tdop;
2469
0
        mask |= DOP_SET;
2470
0
    }
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
0
    switch (fix_dim & 7) {   // dimension
2481
0
    case 1:
2482
        // clock fix (surveyed in), not in Lassen IQ
2483
0
        FALLTHROUGH
2484
0
    case 5:       // Overdetermined clock fix, not in Lassen IQ
2485
0
        session->newdata.status = STATUS_TIME;
2486
0
        session->newdata.mode = MODE_3D;
2487
0
        break;
2488
0
    case 3:
2489
        // Copernicus ii can output this for OD mode.
2490
0
        session->newdata.mode = MODE_2D;
2491
0
        break;
2492
0
    case 4:
2493
        // SMTx can output this for OD mode.
2494
0
        session->newdata.mode = MODE_3D;
2495
0
        break;
2496
0
    case 6:
2497
        // Accutime, not in Lassen IQ
2498
0
        session->newdata.status = STATUS_DGPS;
2499
0
        session->newdata.mode = MODE_3D;
2500
0
        break;
2501
0
    case 2:              // not in Lassen IQ
2502
0
        FALLTHROUGH
2503
0
    case 7:              // not in Lassen IQ
2504
0
        FALLTHROUGH
2505
0
    default:             // huh?
2506
0
        session->newdata.mode = MODE_NO_FIX;
2507
0
        break;
2508
0
    }
2509
0
    if (0 >= count &&
2510
0
        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
0
        session->newdata.status = STATUS_DR;
2515
0
    }
2516
0
    if (STATUS_UNK < session->newdata.status) {
2517
0
        mask |= STATUS_SET;
2518
0
    }
2519
0
    mask |= MODE_SET;
2520
2521
0
    memset(session->driver.tsip.sats_used, 0,
2522
0
           sizeof(session->driver.tsip.sats_used));
2523
0
    buf2[0] = '\0';
2524
0
    for (i = 0; i < count; i++) {
2525
        // negative PRN means sat unhealthy why use an unhealthy sat??
2526
2527
0
        session->driver.tsip.sats_used[i] = getsb(buf, 17 + i);
2528
0
        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
0
    }
2533
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2534
0
             "TSIP x6d: AIVSS: fix_dim=x%x status=%d mode=%d used=%d "
2535
0
             "pdop=%.1f hdop=%.1f vdop=%.1f tdop=%.1f used >%s<\n",
2536
0
             fix_dim,
2537
0
             session->newdata.status,
2538
0
             session->newdata.mode,
2539
0
             session->gpsdata.satellites_used,
2540
0
             pdop, hdop, vdop, tdop, buf2);
2541
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2542
0
             "TSIP: fix::%s\n",
2543
0
             flags2str(fix_dim, vfix, buf2, sizeof(buf2)));
2544
0
    mask |= USED_IS;
2545
2546
0
    return mask;
2547
0
}
2548
2549
// decode packet x82
2550
static gps_mask_t decode_x82(struct gps_device_t *session, const char *buf)
2551
0
{
2552
0
    gps_mask_t mask = 0;
2553
    // differential position fix mode
2554
0
    unsigned mode = getub(buf, 0);
2555
0
    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
0
        session->newdata.status = STATUS_DGPS;
2560
0
        mask |= STATUS_SET;
2561
0
    }
2562
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2563
0
             "TSIP x82: DPFM: mode %d status=%d\n",
2564
0
             mode, session->newdata.status);
2565
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2566
0
             "TSIP: mode:%s\n",
2567
0
             val2str(mode, vx82_mode));
2568
0
    return mask;
2569
0
}
2570
2571
// decode packet x83
2572
static gps_mask_t decode_x83(struct gps_device_t *session, const char *buf)
2573
0
{
2574
0
    gps_mask_t mask = 0;
2575
0
    timespec_t ts_tow;
2576
    // differential position fix mode
2577
0
    double ecefx = getbed64(buf, 0);            // X, m
2578
0
    double ecefy = getbed64(buf, 8);            // Y, m
2579
0
    double ecefz = getbed64(buf, 16);           // Z, m
2580
0
    double clock_bias = getbed64(buf, 24);      // clock bias, m
2581
0
    double ftow = getbef32(buf, 32);            // time-of-fix, s
2582
2583
0
    session->newdata.ecef.x = ecefx;
2584
0
    session->newdata.ecef.y = ecefy;
2585
0
    session->newdata.ecef.z = ecefz;
2586
    // short circuit to gpsdata. Convert m to ns
2587
0
    session->gpsdata.fix.clockbias = 1e9 * clock_bias / CLIGHT;
2588
2589
0
    DTOTS(&ts_tow, ftow);
2590
0
    session->newdata.time = gpsd_gpstime_resolv(session,
2591
0
                                                session->context->gps_week,
2592
0
                                                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
0
    session->newdata.status = session->lastfix.status;
2600
0
    if (MODE_2D > session->oldfix.mode) {
2601
0
        session->newdata.mode = MODE_2D;  // At least 2D
2602
0
    } else {
2603
0
        session->newdata.mode = session->lastfix.mode;
2604
0
    }
2605
0
    mask |= STATUS_SET | MODE_SET | ECEF_SET | TIME_SET | NTPTIME_IS;
2606
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2607
        // New time, so new fix.
2608
0
        mask |= CLEAR_IS;
2609
0
        session->driver.tsip.last_tow = ts_tow;
2610
0
    }
2611
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2612
0
             "TSIP x83: DP-XYZ: %f %f %f cbias %f tow %f mode %u\n",
2613
0
             session->newdata.ecef.x,
2614
0
             session->newdata.ecef.y,
2615
0
             session->newdata.ecef.z,
2616
0
             clock_bias, ftow,
2617
0
             session->newdata.mode);
2618
0
    return mask;
2619
0
}
2620
2621
// decode packet x84
2622
static gps_mask_t decode_x84(struct gps_device_t *session, const char *buf)
2623
0
{
2624
0
    gps_mask_t mask = 0;
2625
0
    timespec_t ts_tow;
2626
0
    char ts_buf[TIMESPEC_LEN];
2627
0
    double lat = getbed64(buf, 0) * RAD_2_DEG;   // lat, radians
2628
0
    double lon = getbed64(buf, 8) * RAD_2_DEG;   // lon, radians
2629
    // depending on GPS config, could be either WGS84 or MSL
2630
0
    double d1 = getbed64(buf, 16);               // altitude, m
2631
0
    double cbias = getbed64(buf, 16);            // clock bias, meters
2632
0
    double ftow = getbef32(buf, 32);             // time-of-fix, s
2633
2634
0
    session->newdata.latitude = lat;
2635
0
    session->newdata.longitude =lon;
2636
0
    if (0 == session->driver.tsip.alt_is_msl) {
2637
0
        session->newdata.altHAE = d1;
2638
0
    } else {
2639
0
        session->newdata.altMSL = d1;
2640
0
    }
2641
0
    mask |= ALTITUDE_SET;
2642
2643
    // short circuit to gpsdata. Convert m to ns
2644
0
    session->gpsdata.fix.clockbias = 1e9 * cbias / CLIGHT;
2645
2646
0
    if (0 != (session->context->valid & GPS_TIME_VALID)) {
2647
        // fingers crossed receiver set to UTC, not GPS.
2648
0
        DTOTS(&ts_tow, ftow);
2649
0
        session->newdata.time =
2650
0
            gpsd_gpstime_resolv(session, session->context->gps_week,
2651
0
                                ts_tow);
2652
0
        mask |= TIME_SET | NTPTIME_IS;
2653
0
        if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2654
0
            mask |= CLEAR_IS;
2655
0
            session->driver.tsip.last_tow = ts_tow;
2656
0
        }
2657
0
    }
2658
0
    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
0
    session->newdata.status = session->oldfix.status;
2665
0
    session->newdata.mode = session->oldfix.mode;
2666
0
    mask |= STATUS_SET | MODE_SET;
2667
2668
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2669
0
             "TSIP x84: DP-LLA: time=%s lat=%.2f lon=%.2f alt=%.2f %s "
2670
0
             "cbias %.2f\n",
2671
0
             timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
2672
0
             session->newdata.latitude,
2673
0
             session->newdata.longitude, d1,
2674
0
             session->driver.tsip.alt_is_msl ? "MSL" : "HAE", cbias);
2675
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2676
0
             "TSIP: mode:%s status:%s\n",
2677
0
             val2str(session->newdata.mode, vmode_str),
2678
0
             val2str(session->newdata.status, vstatus_str));
2679
0
    return mask;
2680
0
}
2681
2682
/* decode Superpacket x8f-15
2683
*/
2684
static gps_mask_t decode_x8f_15(struct gps_device_t *session, const char *buf)
2685
0
{
2686
0
    gps_mask_t mask = 0;
2687
0
    int s1 = getbes16(buf, 1);                 // Datum Index
2688
0
    double d1 = getbed64(buf, 3);              // DX
2689
0
    double d2 = getbed64(buf, 11);             // DY
2690
0
    double d3 = getbed64(buf, 19);             // DZ
2691
0
    double d4 = getbed64(buf, 27);             // A-axis
2692
0
    double d5 = getbed64(buf, 35);             // Eccentricity Squared
2693
2694
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2695
0
             "TSIP x8f-15: Current Datum: %d %f %f %f %f %f\n",
2696
0
             s1, d1, d2, d3, d4, d5);
2697
0
    return mask;
2698
0
}
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 int length)
2704
0
{
2705
0
    gps_mask_t mask = 0;
2706
0
    double d1, d2, d3, d4;
2707
0
    timespec_t ts_tow;
2708
0
    char buf2[80];
2709
0
    char buf3[160];
2710
0
    char ts_buf[TIMESPEC_LEN];
2711
0
    int i;
2712
2713
0
    int s1 = getbes16(buf, 2);                // east velocity
2714
0
    int s2 = getbes16(buf, 4);                // north velocity
2715
0
    int s3 = getbes16(buf, 6);                // up velocity
2716
0
    unsigned long tow = getbeu32(buf, 8);     // time in ms
2717
0
    long lat = getbes32(buf, 12);             // latitude
2718
0
    unsigned long lon = getbeu32(buf, 16);    // longitude
2719
    // Lassen iQ, and copernicus (ii) doc says this is always altHAE
2720
0
    long alt = getbes32(buf, 20);             // altitude
2721
0
    unsigned u1 = getub(buf, 24);             // velocity scaling
2722
0
    unsigned datum = getub(buf, 26);          // Datum + 1
2723
0
    unsigned fflags = getub(buf, 27);         // fix flags
2724
0
    int numSV = getub(buf, 28);               // num svs
2725
0
    unsigned ls = getub(buf, 29);             // utc offset (leap seconds)
2726
0
    unsigned week = getbeu16(buf, 30);        // tsip.gps_week
2727
2728
    // PRN/IODE data follows
2729
2730
0
    if (0 != (u1 & 0x01)) {     // check velocity scaling
2731
0
        d4 = 0.02;
2732
0
    } else {
2733
0
        d4 = 0.005;
2734
0
    }
2735
2736
    // 0x8000 is over-range
2737
0
    if ((int)0x8000 != s2) {
2738
0
        d2 = (double)s2 * d4;   // north velocity m/s
2739
0
        session->newdata.NED.velN = d2;
2740
0
    }
2741
0
    if ((int16_t)0x8000 != s1) {
2742
0
        d1 = (double)s1 * d4;   // east velocity m/s
2743
0
        session->newdata.NED.velE = d1;
2744
0
    }
2745
0
    if ((int16_t)0x8000 != s3) {
2746
0
        d3 = (double)s3 * d4;       // up velocity m/s
2747
0
        session->newdata.NED.velD = -d3;
2748
0
    }
2749
2750
0
    session->newdata.latitude = (double)lat * SEMI_2_DEG;
2751
0
    session->newdata.longitude = (double)lon * SEMI_2_DEG;
2752
2753
0
    if (180.0 < session->newdata.longitude) {
2754
0
        session->newdata.longitude -= 360.0;
2755
0
    }
2756
    // Lassen iQ doc says this is always altHAE in mm
2757
0
    session->newdata.altHAE = (double)alt * 1e-3;
2758
0
    mask |= ALTITUDE_SET;
2759
2760
0
    session->newdata.status = STATUS_UNK;
2761
0
    session->newdata.mode = MODE_NO_FIX;
2762
0
    if ((uint8_t)0 == (fflags & 0x01)) {          // Fix Available
2763
0
        session->newdata.status = STATUS_GPS;
2764
0
        if ((uint8_t)0 != (fflags & 0x02)) {      // DGPS Corrected
2765
0
            session->newdata.status = STATUS_DGPS;
2766
0
        }
2767
0
        if ((uint8_t)0 != (fflags & 0x04)) {      // Fix Dimension
2768
0
            session->newdata.mode = MODE_2D;
2769
0
        } else {
2770
0
            session->newdata.mode = MODE_3D;
2771
0
        }
2772
0
    }
2773
0
    session->gpsdata.satellites_used = numSV;
2774
0
    if (10 < ls) {
2775
0
        session->context->leap_seconds = ls;
2776
0
        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
0
        if (17 < ls &&
2784
0
            1930 > week) {
2785
            // leap second 18 added in gps week 1930
2786
0
            week += 1024;
2787
0
            if (1930 > week) {
2788
                // and again?
2789
0
                week += 1024;
2790
0
            }
2791
0
        }
2792
0
    }
2793
0
    MSTOTS(&ts_tow, tow);
2794
0
    session->newdata.time = gpsd_gpstime_resolv(session, week,
2795
0
                                                ts_tow);
2796
0
    mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
2797
0
            STATUS_SET | MODE_SET | VNED_SET;
2798
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2799
0
        mask |= CLEAR_IS;
2800
0
        session->driver.tsip.last_tow = ts_tow;
2801
0
    }
2802
2803
0
    memset(session->driver.tsip.sats_used, 0,
2804
0
           sizeof(session->driver.tsip.sats_used));
2805
0
    buf3[0] = '\0';
2806
0
    if (MAXCHANNELS < numSV) {
2807
        // should not happen, pacify Coverity 493012
2808
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
2809
0
                 "TSIP x8f-20: MAXCHANNELS < numSV (%d)\n", numSV);
2810
0
        return 0;
2811
0
    }
2812
0
    for (i = 0; i < numSV; i++) {
2813
0
        if (length < (33 + (i * 2))) {
2814
            // too short
2815
0
            break;
2816
0
        }
2817
        // bits 0 to 5, junk in 5 to 7
2818
0
        int PRN = getub(buf, 32 + (i * 2)) & 0x1f;
2819
0
        int IODE = getub(buf, 33 + (i * 2));
2820
2821
0
        session->driver.tsip.sats_used[i] = PRN;
2822
0
        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
0
    }
2827
2828
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2829
0
             "TSIP x8f-20: LFwEI: %d %d %d tow %lu %ld "
2830
0
             " %lu %lu %x fflags %x numSV %u ls %u week %d datum %u used:%s\n",
2831
0
             s1, s2, s3, tow, lat, lon, alt, u1, fflags, numSV,
2832
0
             ls, week, datum, buf3);
2833
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2834
0
             "TSIP x8f-20: LFwEI: time=%s lat=%.2f lon=%.2f "
2835
0
             "altHAE=%.2f mode=%d status=%d\n",
2836
0
             timespec_str(&session->newdata.time, ts_buf,
2837
0
                          sizeof(ts_buf)),
2838
0
             session->newdata.latitude, session->newdata.longitude,
2839
0
             session->newdata.altHAE,
2840
0
             session->newdata.mode, session->newdata.status);
2841
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2842
0
             "TSIP: flags:%s\n",
2843
0
             flags2str(fflags, vx8f_20_fflags, buf2, sizeof(buf2)));
2844
0
    return mask;
2845
0
}
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
0
{
2851
0
    gps_mask_t mask = 0;
2852
0
    double d1, d2, d3, d5;
2853
0
    timespec_t ts_tow;
2854
0
    char ts_buf[TIMESPEC_LEN];
2855
2856
0
    unsigned long tow = getbeu32(buf, 1);    // time in ms
2857
0
    unsigned week = getbeu16(buf, 5);        // tsip.gps_week
2858
0
    unsigned u1 = getub(buf, 7);             // utc offset
2859
0
    unsigned u2 = getub(buf, 8);             // fix flags
2860
0
    long lat = getbes32(buf, 9);             // latitude
2861
0
    unsigned long lon = getbeu32(buf, 13);   // longitude
2862
    // Copernicus (ii) doc says this is always altHAE in mm
2863
0
    long alt = getbes32(buf, 17);            // altitude
2864
    // set xNED here
2865
0
    int s2 = getbes16(buf, 21);              // east velocity
2866
0
    int s3 = getbes16(buf, 23);              // north velocity
2867
0
    int s4 = getbes16(buf, 25);              // up velocity
2868
2869
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2870
0
             "TSIP x8f-23: CSP: tow %lu week %u %u %u %ld %lu %ld "
2871
0
             " %d %d %d\n",
2872
0
             tow, week, u1, u2, lat, lon, alt, s2, s3, s4);
2873
0
    if (10 < (int)u1) {
2874
0
        session->context->leap_seconds = (int)u1;
2875
0
        session->context->valid |= LEAP_SECOND_VALID;
2876
0
    }
2877
0
    MSTOTS(&ts_tow, tow);
2878
0
    session->newdata.time =
2879
0
        gpsd_gpstime_resolv(session, week, ts_tow);
2880
0
    session->newdata.status = STATUS_UNK;
2881
0
    session->newdata.mode = MODE_NO_FIX;
2882
0
    if ((u2 & 0x01) == (uint8_t)0) {          // Fix Available
2883
0
        session->newdata.status = STATUS_GPS;
2884
0
        if ((u2 & 0x02) != (uint8_t)0) {      // DGPS Corrected
2885
0
            session->newdata.status = STATUS_DGPS;
2886
0
        }
2887
0
        if ((u2 & 0x04) != (uint8_t)0) {       // Fix Dimension
2888
0
            session->newdata.mode = MODE_2D;
2889
0
        } else {
2890
0
            session->newdata.mode = MODE_3D;
2891
0
        }
2892
0
    }
2893
0
    session->newdata.latitude = (double)lat * SEMI_2_DEG;
2894
0
    session->newdata.longitude = (double)lon * SEMI_2_DEG;
2895
0
    if (180.0 < session->newdata.longitude) {
2896
0
        session->newdata.longitude -= 360.0;
2897
0
    }
2898
    // Copernicus (ii) doc says this is always altHAE in mm
2899
0
    session->newdata.altHAE = (double)alt * 1e-3;
2900
0
    mask |= ALTITUDE_SET;
2901
0
    if ((u2 & 0x20) != (uint8_t)0) {     // check velocity scaling
2902
0
        d5 = 0.02;
2903
0
    } else {
2904
0
        d5 = 0.005;
2905
0
    }
2906
0
    d1 = (double)s2 * d5;       // east velocity m/s
2907
0
    d2 = (double)s3 * d5;       // north velocity m/s
2908
0
    d3 = (double)s4 * d5;       // up velocity m/s
2909
0
    session->newdata.NED.velN = d2;
2910
0
    session->newdata.NED.velE = d1;
2911
0
    session->newdata.NED.velD = -d3;
2912
2913
0
    mask |= TIME_SET | NTPTIME_IS | LATLON_SET |
2914
0
            STATUS_SET | MODE_SET | VNED_SET;
2915
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
2916
0
        mask |= CLEAR_IS;
2917
0
        session->driver.tsip.last_tow = ts_tow;
2918
0
    }
2919
0
    session->driver.tsip.req_compact = 0;
2920
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2921
0
             "TSIP x8f-23: SP-CSP: time %s lat %.2f lon %.2f "
2922
0
             "altHAE %.2f mode %d status %d\n",
2923
0
             timespec_str(&session->newdata.time, ts_buf,
2924
0
                          sizeof(ts_buf)),
2925
0
             session->newdata.latitude, session->newdata.longitude,
2926
0
             session->newdata.altHAE,
2927
0
             session->newdata.mode, session->newdata.status);
2928
0
    return mask;
2929
0
}
2930
2931
/* decode Superpacket x8f-42
2932
 */
2933
static gps_mask_t decode_x8f_42(struct gps_device_t *session, const char *buf)
2934
0
{
2935
0
    gps_mask_t mask = 0;
2936
2937
0
    unsigned u1 = getub(buf, 1);                 // Production Options Prefix
2938
0
    unsigned u2 = getub(buf, 2);                 // Production Number Extension
2939
0
    unsigned u3 = getbeu16(buf, 3);              // Case Sernum Prefix
2940
0
    unsigned long ul1 = getbeu32(buf, 5);        // Case Sernum
2941
0
    unsigned long ul2 = getbeu32(buf, 9);        // Production Number
2942
0
    unsigned long ul3 = getbeu32(buf, 13);       // Reserved
2943
0
    unsigned u4 = getbeu16(buf, 15);             // Machine ID
2944
0
    unsigned u5 = getbeu16(buf, 17);             // Reserved
2945
2946
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2947
0
             "TSIP x8f-42: SPP: Prod x%x-%x Sernum %x-%lx "
2948
0
             "Prod %lx  Res %lx ID %x Res %x\n",
2949
0
             u1, u2, u3, ul1, ul2, ul3, u4, u5);
2950
0
    return mask;
2951
0
}
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
0
{
2957
0
    gps_mask_t mask = 0;
2958
0
    uint16_t mask0, mask1;
2959
0
    char buf2[40];
2960
2961
0
    mask0 = getbeu16(buf, 1);    // Mask 0
2962
0
    mask1 = getbeu16(buf, 3);    // Mask 1, reserved in ResSMT 360
2963
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2964
0
             "TSIP x8f-a5: PBM: mask0 x%04x mask1 x%04x\n",
2965
0
             mask0, mask1);
2966
0
    GPSD_LOG(LOG_IO, &session->context->errout,
2967
0
             "TSIP: mask0::%s\n",
2968
0
             flags2str(mask0, vpbm_mask0, buf2, sizeof(buf2)));
2969
2970
0
    return mask;
2971
0
}
2972
2973
/* decode Superpacket x8f-a6
2974
 */
2975
static gps_mask_t decode_x8f_a6(struct gps_device_t *session, const char *buf)
2976
0
{
2977
0
    gps_mask_t mask = 0;
2978
0
    unsigned u1 = getub(buf, 1);          // Command
2979
0
    unsigned u2 = getub(buf, 2);          // Status
2980
2981
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
2982
0
             "TSIP x8f-a6: SSC: command x%x status x%x\n",
2983
0
             u1, u2);
2984
0
    return mask;
2985
0
}
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 int length)
2998
0
{
2999
0
    gps_mask_t mask = 0;
3000
3001
    // we assume the receiver not in some crazy mode, and is GPS time
3002
0
    unsigned long tow = getbeu32(buf, 2);         // gpstime in seconds
3003
0
    unsigned fmt = buf[1];                        // format, 0 Float, 1 Int
3004
3005
0
    if (0 == fmt) {
3006
        // floating point mode
3007
0
        double clock_bias = getbef32(buf, 6);    // clock bias (combined). s
3008
        // clock bias rate (combined), s/s
3009
0
        double clock_rate = getbef32(buf, 10);
3010
3011
        // short circuit to gpsdata
3012
0
        session->gpsdata.fix.clockbias = clock_bias / 1e9;
3013
0
        session->gpsdata.fix.clockdrift = clock_rate / 1e9;
3014
3015
        // FIXME: decode the individual biases
3016
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
3017
0
                 "TSIP x8f-a7: tow %llu fmt %u bias %e "
3018
0
                 "bias rate %e len %d\n",
3019
0
                 (long long unsigned)tow, fmt, clock_bias, clock_rate, length);
3020
0
    } else if (1 == fmt) {
3021
        // integer mode
3022
0
        int clock_bias = getbes16(buf, 6);   // Clock Bias (combined) 0.1ns
3023
0
        int clock_rate = getbes16(buf, 8);   // Clock Bias rate (combined) ps/s
3024
3025
        // short circuit to gpsdata
3026
0
        session->gpsdata.fix.clockbias = clock_bias / 10;
3027
0
        session->gpsdata.fix.clockdrift = clock_rate / 1000;
3028
3029
        // FIXME: decode the individual biases
3030
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
3031
0
                 "TSIP x8f-a7: tow %llu mode %u bias %ld "
3032
0
                 "bias rate %ld len %d\n",
3033
0
                 (long long unsigned)tow, fmt,
3034
0
                 session->gpsdata.fix.clockbias,
3035
0
                 session->gpsdata.fix.clockdrift, length);
3036
0
    } else {
3037
        // unknown mode
3038
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
3039
0
                 "TSIP x8f-a7: tow %llu fmt %u. Unknown mode len %d\n",
3040
0
                 (long long unsigned)tow, fmt, length);
3041
0
    }
3042
    // FIXME: loop over the individual sat data
3043
0
    return mask;
3044
0
}
3045
3046
/* decode Superpacket x8f-a9
3047
 */
3048
static gps_mask_t decode_x8f_a9(struct gps_device_t *session, const char *buf)
3049
0
{
3050
0
    gps_mask_t mask = 0;
3051
3052
0
    unsigned u1 = getub(buf, 1);              // Self Survey Enable
3053
0
    unsigned u2 = getub(buf, 2);              // Position Save Flag
3054
0
    unsigned long u3 = getbeu32(buf, 3);      // Self Survey Length
3055
0
    unsigned long u4 = getbeu32(buf, 7);      // Reserved
3056
3057
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
3058
0
             "TSIP x8f-a9 SSP: sse %u psf %u length %ld rex x%lx \n",
3059
0
             u1, u2, u3, u4);
3060
0
    GPSD_LOG(LOG_IO, &session->context->errout,
3061
0
             "TSIP: sse:%s sssave:%s\n",
3062
0
             val2str(u1, vss_enable),
3063
0
             val2str(u2, vss_save));
3064
0
    return mask;
3065
0
}
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
0
{
3072
0
    gps_mask_t mask = 0;
3073
0
    unsigned long tow;                 // time of week in milli seconds
3074
0
    timespec_t ts_tow;
3075
0
    unsigned short week;
3076
0
    char ts_buf[TIMESPEC_LEN];
3077
0
    unsigned time_flag;
3078
0
    char buf2[BUFSIZ];
3079
3080
    // we assume the receiver not in some crazy mode, and is GPS time
3081
0
    tow = getbeu32(buf, 1);             // gpstime in seconds
3082
0
    ts_tow.tv_sec = tow;
3083
0
    ts_tow.tv_nsec = 0;
3084
0
    week = getbeu16(buf, 5);            // week
3085
    // leap seconds
3086
0
    session->context->leap_seconds = (int)getbes16(buf, 7);
3087
0
    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
0
    if (1 == (time_flag & 1)) {
3092
        // time is UTC, have leap seconds.
3093
0
        session->context->valid |= LEAP_SECOND_VALID;
3094
0
    } else {
3095
        // time is GPS
3096
0
        if (0 == (time_flag & 8)) {
3097
            // have leap seconds.
3098
0
            session->context->valid |= LEAP_SECOND_VALID;
3099
0
        }
3100
0
    }
3101
0
    if (0 == (time_flag & 0x14)) {
3102
        // time it good, not in test mode
3103
0
        session->newdata.time = gpsd_gpstime_resolv(session, week,
3104
0
                                                    ts_tow);
3105
0
        mask |= TIME_SET | NTPTIME_IS;
3106
0
    } else {
3107
        // time is bad
3108
0
    }
3109
3110
0
    if (!TS_EQ(&ts_tow, &session->driver.tsip.last_tow)) {
3111
0
        mask |= CLEAR_IS;
3112
0
        session->driver.tsip.last_tow = ts_tow;
3113
0
    }
3114
3115
    /* since we compute time from weeks and tow, we ignore the
3116
     * supplied H:M:S M/D/Y */
3117
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
3118
0
             "TSIP x8f-ab: SP-TTS: tow %lu wk %u ls %d flag x%x "
3119
0
             "time %s mask %s\n",
3120
0
             tow, week, session->context->leap_seconds, time_flag,
3121
0
             timespec_str(&session->newdata.time, ts_buf,
3122
0
                          sizeof(ts_buf)),
3123
0
             gps_maskdump(mask));
3124
0
    GPSD_LOG(LOG_IO, &session->context->errout,
3125
0
             "TSIP: tf:%s\n",
3126
0
             flags2str(time_flag, vtiming, buf2, sizeof(buf2)));
3127
3128
0
    return mask;
3129
0
}
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
0
{
3144
0
    gps_mask_t mask = 0;
3145
0
    char buf2[BUFSIZ];
3146
0
    char buf3[BUFSIZ];
3147
3148
    // byte 0 is Subpacket ID
3149
0
    unsigned rec_mode = getub(buf, 1);         // Receiver Mode
3150
    // Disciplining Mode, ICM SMT 360 only
3151
0
    unsigned disc_mode = getub(buf, 2);
3152
    // Self-Survey Progress
3153
0
    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
0
    unsigned crit_alarm = getbeu16(buf, 8);
3157
    // Minor Alarms
3158
0
    unsigned minor_alarm = getbeu16(buf, 10);
3159
0
    unsigned decode_stat = getub(buf, 12);        // GNSS Decoding Status
3160
    // Disciplining Activity, ICM SMT 360 Only
3161
0
    unsigned disc_act = getub(buf, 13);
3162
    // PPS indication, RES SMT 360 Only
3163
0
    unsigned pps_ind = getub(buf, 14);
3164
0
    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
0
    double fqErr = getbef32(buf, 16);          // PPS Offset. positive is slow.
3169
    // Clock Offset (bias) ns. same as ppb
3170
0
    double clk_off = getbef32(buf, 20);
3171
    // ignore 24-27, DAC Value (ICM SMT 360 Only)
3172
0
    double dac_v = getbef32(buf, 28);          // DAC Voltage
3173
    // 32-35, Temperature degrees C
3174
0
    session->newdata.temp = getbef32(buf, 32);
3175
0
    session->newdata.latitude = getbed64(buf, 36) * RAD_2_DEG;
3176
0
    session->newdata.longitude = getbed64(buf, 44) * RAD_2_DEG;
3177
    // SMT 360 doc says this is always altHAE in meters
3178
0
    session->newdata.altHAE = getbed64(buf, 52);
3179
    // ignore 60-63, always zero, PPS Quanization error, ns ?
3180
    // ignore 64-67, reserved
3181
3182
0
    switch (minor_alarm & 6) {
3183
0
    case 2:
3184
0
        session->newdata.ant_stat = ANT_OPEN;
3185
0
        break;
3186
0
    case 4:
3187
0
        session->newdata.ant_stat = ANT_SHORT;
3188
0
        break;
3189
0
    default:
3190
0
        session->newdata.ant_stat = ANT_OK;
3191
0
        break;
3192
0
    }
3193
3194
0
    session->gpsdata.qErr = (long)(fqErr * 1000);
3195
    // short circuit to gpsdata.
3196
0
    session->gpsdata.fix.clockbias = clk_off;
3197
3198
    // PPS indication
3199
0
    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
0
    switch (rec_mode & 7) {
3207
0
    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
0
        switch (decode_stat) {
3216
0
        case 0:   // "Doing Fixes"
3217
0
            session->newdata.mode = MODE_3D;
3218
0
            break;
3219
0
        case 0x0B: // "Only 3 usable sats"
3220
0
            session->newdata.mode = MODE_2D;
3221
0
            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
0
        default:
3237
0
            session->newdata.mode = MODE_NO_FIX;
3238
0
            break;
3239
0
        }
3240
0
        break;
3241
0
    case 6:             // Clock Hold 2D
3242
        /* Not present:
3243
         *   SMT 360
3244
         *   Acutime 360
3245
         */
3246
0
        FALLTHROUGH
3247
0
    case 3:             // forced 2D Position Fix
3248
        // Does this mean STATUS_TIME?
3249
0
        session->newdata.mode = MODE_2D;
3250
0
        break;
3251
0
    case 1:             // Single Satellite Time
3252
        /* Present in:
3253
         *   Acutime 360
3254
         */
3255
0
        FALLTHROUGH
3256
0
    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
0
        session->newdata.status = STATUS_TIME;
3270
0
        switch (decode_stat) {
3271
0
        case 0:   // "Doing Fixes"
3272
0
            session->newdata.mode = MODE_3D;
3273
0
            break;
3274
0
        case 0x9:   // "Only 1 usable sat"
3275
0
            FALLTHROUGH
3276
0
        case 0x0A:  // "Only 2 usable sats
3277
0
            FALLTHROUGH
3278
0
        case 0x0B: // "Only 3 usable sats"
3279
0
            session->newdata.mode = MODE_2D;
3280
0
            break;
3281
0
        case 0x1:   // "Don't have GPS time"
3282
0
            FALLTHROUGH
3283
0
        case 0x3:   // "PDOP is too high"
3284
0
            FALLTHROUGH
3285
0
        case 0x8:   // "No usable sats"
3286
0
            FALLTHROUGH
3287
0
        case 0x0C:  // "The chosen sat is unusable"
3288
0
            FALLTHROUGH
3289
0
        case 0x10:  // TRAIM rejected the fix
3290
0
            FALLTHROUGH
3291
0
        default:
3292
0
            session->newdata.mode = MODE_NO_FIX;
3293
0
            break;
3294
0
        }
3295
0
        break;
3296
0
    case 4:             // forced 3D position Fix
3297
0
        session->newdata.mode = MODE_3D;
3298
0
        break;
3299
0
    default:
3300
0
        session->newdata.mode = MODE_NO_FIX;
3301
0
        break;
3302
0
    }
3303
0
    if (0 != (0x208 & minor_alarm) &&
3304
0
        7 == (rec_mode & 7)) {
3305
        // OD, No sats or position questionable, must be Dead reckoning
3306
0
        session->newdata.mode = MODE_3D;
3307
0
        session->newdata.status = STATUS_DR;
3308
0
    }
3309
0
    if (STATUS_UNK != session->newdata.status) {
3310
0
        mask |= STATUS_SET;
3311
0
    }
3312
3313
0
    mask |= LATLON_SET | ALTITUDE_SET | MODE_SET;
3314
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
3315
0
             "TSIP x8f-ac: SP-TPS: lat=%.2f lon=%.2f altHAE=%.2f "
3316
0
             "mode %d status %d  temp %.1f disc %u pps_ind %u pps_ref %u "
3317
0
             "fqErr %.4f clko %f DACV %f rm x%x dm %u "
3318
0
             "sp %u ca %x ma x%x gds x%x\n",
3319
0
             session->newdata.latitude,
3320
0
             session->newdata.longitude,
3321
0
             session->newdata.altHAE,
3322
0
             session->newdata.mode,
3323
0
             session->newdata.status,
3324
0
             session->newdata.temp,
3325
0
             disc_act, pps_ind, pps_ref, fqErr, clk_off, dac_v,  rec_mode,
3326
0
             disc_mode, survey_prog, crit_alarm,
3327
0
             minor_alarm, decode_stat);
3328
0
    GPSD_LOG(LOG_IO, &session->context->errout,
3329
0
             "TSIP: mode:%s status:%s rm:%s gds:%s ca:%s ma:%s disc_act %s "
3330
0
             "pps_ing %s pps_ref %s\n",
3331
0
             val2str(session->newdata.mode, vmode_str),
3332
0
             val2str(session->newdata.status, vstatus_str),
3333
0
             val2str(rec_mode, vrec_mode),
3334
0
             val2str(decode_stat, vgnss_decode_status),
3335
0
             flags2str(crit_alarm, vcrit_alarms, buf2,
3336
0
                       sizeof(buf2)),
3337
0
             flags2str(minor_alarm, vminor_alarms, buf3,
3338
0
                       sizeof(buf3)),
3339
0
             val2str(disc_act, vdisc_act),
3340
0
             val2str(pps_ind, vpps_ind),
3341
0
             val2str(pps_ref, vpps_ref));
3342
0
    return mask;
3343
0
}
3344
3345
// decode Superpackets x8f-XX
3346
static gps_mask_t decode_x8f(struct gps_device_t *session, const char *buf,
3347
                             int len, int *pbad_len, time_t now)
3348
0
{
3349
0
    gps_mask_t mask = 0;
3350
0
    int bad_len = 0;
3351
0
    unsigned u1 = getub(buf, 0);
3352
3353
0
    switch (u1) {           // sub-code ID
3354
0
    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
0
        if (43 > len) {
3363
0
            bad_len = 43;
3364
0
            break;
3365
0
        }
3366
0
        mask = decode_x8f_15(session, buf);
3367
0
        break;
3368
3369
0
    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
0
        if (56 != (len) &&
3382
0
            64 != (len)) {
3383
0
            bad_len = 56;
3384
0
            break;
3385
0
        }
3386
0
        mask = decode_x8f_20(session, buf, len);
3387
0
        break;
3388
0
    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
0
        if (29 > len) {
3400
0
            bad_len = 29;
3401
0
            break;
3402
0
        }
3403
0
        mask = decode_x8f_23(session, buf);
3404
0
        break;
3405
3406
0
    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
0
        if (19 > len) {
3417
0
            bad_len = 19;
3418
0
            break;
3419
0
        }
3420
0
        mask = decode_x8f_42(session, buf);
3421
0
        break;
3422
0
    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
0
        if (5 > len) {
3437
0
            bad_len = 5;
3438
0
            break;
3439
0
        }
3440
0
        mask = decode_x8f_a5(session, buf);
3441
0
        break;
3442
3443
0
    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
0
        if (3 > len) {
3454
0
            bad_len = 3;
3455
0
            break;
3456
0
        }
3457
0
        mask = decode_x8f_a6(session, buf);
3458
0
        break;
3459
3460
0
    case 0xa7:
3461
        /* Thunderbolt Individual Satellite Solutions
3462
         * partial decode
3463
         */
3464
0
        if (10 > len) {
3465
0
            bad_len = 10;
3466
0
            break;
3467
0
        }
3468
0
        mask = decode_x8f_a7(session, buf, len);
3469
0
        break;
3470
0
    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
0
        if (11 > len) {
3481
0
            bad_len = 11;
3482
0
            break;
3483
0
        }
3484
0
        mask = decode_x8f_a9(session, buf);
3485
0
        break;
3486
0
    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
0
        if (17 > len) {
3495
0
            bad_len = 17;
3496
0
            break;
3497
0
        }
3498
0
        session->driver.tsip.last_41 = now; // keep timestamp for request
3499
0
        mask = decode_x8f_ab(session, buf);
3500
0
        break;
3501
3502
0
    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
0
        if (68 > len) {
3515
0
            bad_len = 68;
3516
0
            break;
3517
0
        }
3518
0
        mask = decode_x8f_ac(session, buf);
3519
0
        break;
3520
3521
0
    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
0
        FALLTHROUGH
3531
0
    case 0x21:
3532
        /* Request accuracy information
3533
         * Present in:
3534
         *   Copernicus II (2009)
3535
         * Not Present in:
3536
         *   pre-2000 models
3537
         */
3538
0
        FALLTHROUGH
3539
0
    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
0
        FALLTHROUGH
3547
0
    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
0
        FALLTHROUGH
3555
0
    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
0
        FALLTHROUGH
3565
0
    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
0
        FALLTHROUGH
3575
0
    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
0
        FALLTHROUGH
3585
0
    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
0
        FALLTHROUGH
3595
0
    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
0
        FALLTHROUGH
3605
0
    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
0
        FALLTHROUGH
3615
0
    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
0
        FALLTHROUGH
3625
0
    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
0
        FALLTHROUGH
3635
0
    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
0
        FALLTHROUGH
3645
0
    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
0
        FALLTHROUGH
3655
0
    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
0
        FALLTHROUGH
3665
0
    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
0
        FALLTHROUGH
3675
0
    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
0
        FALLTHROUGH
3685
0
    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
0
        FALLTHROUGH
3695
0
    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
0
        FALLTHROUGH
3705
0
    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
0
        FALLTHROUGH
3715
0
    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
0
        FALLTHROUGH
3725
0
    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
0
        FALLTHROUGH
3735
0
    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
0
        FALLTHROUGH
3745
0
    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
0
        FALLTHROUGH
3755
0
    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
0
        FALLTHROUGH
3765
0
    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
0
        FALLTHROUGH
3775
0
    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
0
        FALLTHROUGH
3785
0
    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
0
        FALLTHROUGH
3795
0
    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
0
        FALLTHROUGH
3805
0
    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
0
        FALLTHROUGH
3815
0
    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
0
        FALLTHROUGH
3825
0
    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
0
        FALLTHROUGH
3835
0
    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
0
        FALLTHROUGH
3845
0
    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
0
        FALLTHROUGH
3855
0
    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
0
        FALLTHROUGH
3865
0
    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
0
        FALLTHROUGH
3875
0
    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
0
        FALLTHROUGH
3885
0
    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
0
        FALLTHROUGH
3895
0
    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
0
        FALLTHROUGH
3905
0
    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
0
        FALLTHROUGH
3915
0
    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
0
        FALLTHROUGH
3925
0
    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
0
        FALLTHROUGH
3935
0
    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
0
        FALLTHROUGH
3945
0
    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
0
        FALLTHROUGH
3955
0
    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
0
        FALLTHROUGH
3965
0
    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
0
        FALLTHROUGH
3975
0
    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
0
        FALLTHROUGH
3985
0
    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
0
        FALLTHROUGH
3995
0
    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
0
        FALLTHROUGH
4005
0
    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
0
        FALLTHROUGH
4015
0
    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
0
        FALLTHROUGH
4025
0
    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
0
        FALLTHROUGH
4035
0
    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
0
        FALLTHROUGH
4045
0
    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
0
        FALLTHROUGH
4055
0
    default:
4056
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4057
0
                 "TSIP x8f-%02x: Unhandled TSIP superpacket\n", u1);
4058
0
    }
4059
0
    *pbad_len = bad_len;
4060
4061
0
    return mask;
4062
0
}
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
0
{
4067
0
    gps_mask_t mask = 0;
4068
4069
0
    unsigned u1 = getub(buf, 4);              // NMEA Major version
4070
0
    unsigned u2 = getub(buf, 5);              // NMEA Minor version
4071
0
    unsigned u3 = getub(buf, 6);              // TSIP version
4072
0
    unsigned u4 = getub(buf, 7);              // Trimble NMEA version
4073
0
    unsigned long u6 = getbeu32(buf, 8);      // reserved
4074
0
    unsigned u7 = getub(buf, 12);             // reserved
4075
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4076
0
             "TSIPv1 x90-00: NMEA %u.%u TSIP %u TNMEA %u "
4077
0
             "res x%04lx x%02x \n",
4078
0
             u1, u2, u3, u4, u6, u7);
4079
0
    return mask;
4080
0
}
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
                                int len)
4087
0
{
4088
0
    gps_mask_t mask = 0;
4089
0
    char buf2[BUFSIZ];
4090
4091
0
    unsigned u1 = getub(buf, 4);               // Major version
4092
0
    unsigned u2 = getub(buf, 5);               // Minor version
4093
0
    unsigned u3 = getub(buf, 6);               // Build number
4094
0
    unsigned u4 = getub(buf, 7);               // Build month
4095
0
    unsigned u5 = getub(buf, 8);               // Build day
4096
0
    unsigned u6 = getbeu16(buf, 9);            // Build year
4097
0
    unsigned u7 = getbeu16(buf, 11);           // Hardware ID
4098
0
    unsigned u8 = getub(buf, 13);              // Product Name length
4099
4100
0
    session->driver.tsip.hardware_code = u7;
4101
    // check for valid module name length
4102
    // RES720 is 27 long
4103
0
    if ((int)u8 > (len - 13)) {
4104
0
        u8 = len - 13;
4105
0
    }
4106
    // check for valid module name length, again
4107
0
    if (40 < u8) {
4108
0
        u8 = 40;
4109
0
    }
4110
  
4111
0
    memcpy(buf2, &buf[14], u8);
4112
0
    buf2[u8] = '\0';
4113
0
    (void)snprintf(session->subtype, sizeof(session->subtype),
4114
0
                   "fw %u.%u %u %02u/%02u/%04u %.40s",
4115
0
                   u1, u2, u3, u6, u5, u4, buf2);
4116
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4117
0
             "TSIPv1 x90-01: Version %u.%u Build %u %u/%u/%u hwid %u, "
4118
0
             "%.*s[%u]\n",
4119
0
             u1, u2, u3, u6, u5, u4, u7, u8, buf2, u8);
4120
0
    mask |= DEVICEID_SET;
4121
0
    return mask;
4122
0
}
4123
4124
// Decode, Port Configuration: x91-00
4125
static gps_mask_t decode_x91_00(struct gps_device_t *session, const char *buf)
4126
0
{
4127
0
    gps_mask_t mask = 0;
4128
4129
0
    unsigned u1 = getub(buf, 4);               // port
4130
0
    unsigned u2 = getub(buf, 5);               // port type
4131
0
    unsigned u3 = getub(buf, 6);               // protocol
4132
0
    unsigned u4 = getub(buf, 7);               // baud rate
4133
0
    unsigned u5 = getub(buf, 8);               // data bits
4134
0
    unsigned u6 = getub(buf, 9);               // parity
4135
0
    unsigned u7 = getub(buf, 10);              // stop bits
4136
0
    unsigned long u8 = getbeu32(buf, 11);      // reserved
4137
0
    unsigned long u9 = getbeu32(buf, 12);      // reserved
4138
4139
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4140
0
             "TSIPv1 x91-00: port %u type %u proto %u baud %u bits %u "
4141
0
             "parity %u stop %u res x%04lx %04lx\n",
4142
0
             u1, u2, u3, u4, u5, u6, u7, u8, u9);
4143
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4144
0
             "TSIPv1: port:%s type:%s, proto:%s speed:%s bits:%s %s %s\n",
4145
0
             val2str(u1, vport_name1),
4146
0
             val2str(u2, vport_type1),
4147
0
             val2str(u3, vprotocol1),
4148
0
             val2str(u4, vspeed1),
4149
0
             val2str(u5, vdbits1),
4150
0
             val2str(u6, vparity1),
4151
0
             val2str(u6, vstop1));
4152
0
    return mask;
4153
0
}
4154
4155
// Decode GNSS COnfiguration: x91-01
4156
static gps_mask_t decode_x91_01(struct gps_device_t *session, const char *buf)
4157
0
{
4158
0
    gps_mask_t mask = 0;
4159
0
    char buf2[BUFSIZ];
4160
4161
    /* constellations, 0 to 26, mashup of constellation and signal
4162
     * ignore if 0xffffffff */
4163
0
    unsigned long cons = getbeu32(buf, 4);     // constellations
4164
0
    double d1 = getbef32(buf, 8);              // elevation mask
4165
0
    double d2 = getbef32(buf, 12);             // signal mask
4166
0
    double d3 = getbef32(buf, 16);             // PDOP mask
4167
    // anti-jamming, always enabled in RES 720
4168
0
    unsigned u2 = getub(buf, 20);
4169
0
    unsigned u3 = getub(buf, 21);              // fix rate
4170
0
    double d4 = getbef32(buf, 22);             // Antenna CAble delay, seconds
4171
0
    unsigned long u4 = getbeu32(buf, 26);      // reserved
4172
4173
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4174
0
             "TSIPv1 x91-01 cons x%lx el %f signal %f PDOP %f jam %u "
4175
0
             "frate %u delay %f res x%04lx\n",
4176
0
             cons, d1, d2, d3, u2, u3, d4, u4);
4177
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4178
0
             "TSIPv1: cons %s\n",
4179
0
             flags2str(cons, vsv_types1, buf2, sizeof(buf2)));
4180
0
    return mask;
4181
0
}
4182
4183
// Decode NVS Configuration, x91-02
4184
static gps_mask_t decode_x91_02(struct gps_device_t *session, const char *buf)
4185
0
{
4186
0
    gps_mask_t mask = 0;
4187
0
    char buf2[20];
4188
4189
0
    unsigned u1 = getub(buf, 6);               // status
4190
0
    unsigned long u2 = getbeu32(buf, 7);            // reserved
4191
4192
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4193
0
             "TSIPv1 x91-02: status %u res x%04lx\n",
4194
0
             u1, u2);
4195
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4196
0
             "TSIPv1: Status:%s\n",
4197
0
             flags2str(u1, vsave_status1, buf2, sizeof(buf2)));
4198
0
    return mask;
4199
0
}
4200
4201
// Decode Timing Configuration: x91-03
4202
static gps_mask_t decode_x91_03(struct gps_device_t *session, const char *buf)
4203
0
{
4204
0
    gps_mask_t mask = 0;
4205
4206
0
    unsigned tbase = getub(buf, 4);               // time base
4207
0
    unsigned pbase = getub(buf, 5);               // PPS base
4208
0
    unsigned pmask = getub(buf, 6);               // PPS mask
4209
0
    unsigned res = getbeu16(buf, 7);              // reserved
4210
0
    unsigned pwidth = getbeu16(buf, 9);           // PPS width
4211
0
    double  poffset = getbed64(buf, 11);          // PPS offset, in seconds
4212
4213
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4214
0
             "TSIPv1 x91-03: time base %u PPS base %u mask %u res x%04x "
4215
0
             "width %u offset %f\n",
4216
0
             tbase, pbase, pmask, res, pwidth, poffset);
4217
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4218
0
             "TSIPv1: time base:%s pps base:%s pps mask:%s\n",
4219
0
             val2str(tbase, vtime_base1),
4220
0
             val2str(pbase, vtime_base1),
4221
0
             val2str(pmask, vpps_mask1));
4222
0
    return mask;
4223
0
}
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
0
{
4228
0
    gps_mask_t mask = 0;
4229
0
    char buf2[BUFSIZ];
4230
4231
0
    unsigned u1 = getub(buf, 4);               // self-survey mask
4232
0
    unsigned long u2 = getbeu32(buf, 5);       // self-survey length, # fixes
4233
0
    unsigned u3 = getbeu16(buf, 9);            // horz uncertainty, meters
4234
0
    unsigned u4 = getbeu16(buf, 11);           // vert uncertainty, meters
4235
4236
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4237
0
             "TSIPv1 x91-04: mask x%x length %lu eph %u epv %u\n",
4238
0
             u1, u2, u3, u4);
4239
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4240
0
             "TSIPv1:ssmask %s\n",
4241
0
             flags2str(u1, vss_mask1, buf2, sizeof(buf2)));
4242
0
    return mask;
4243
0
}
4244
4245
// Decode Receiver COnfiguration: x91-05
4246
static gps_mask_t decode_x91_05(struct gps_device_t *session, const char *buf)
4247
0
{
4248
0
    gps_mask_t mask = 0;
4249
4250
0
    unsigned port = getub(buf, 4);              // port
4251
0
    unsigned long otype = getbeu32(buf, 5);     // type of output
4252
0
    unsigned long res1 = getbeu32(buf, 9);      // reserved
4253
0
    unsigned long res2 = getbeu32(buf, 13);     // reserved
4254
0
    unsigned long res3 = getbeu32(buf, 17);     // reserved
4255
4256
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4257
0
             "TSIPv1 x91-05: port %u type x%04lx res x%04lx x%04lx x%04lx\n",
4258
0
             port, otype, res1, res2, res3);
4259
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4260
0
             "TSIPv1: port %s xa1-00: %lu xa1-03: %lu xa1-11: %lu "
4261
0
             "xa1-00: %lu  xa3-00: %lu  xa3-11: %lu\n",
4262
0
             val2str(port, vport_name1),
4263
0
             otype & 3, (otype >> 2) & 3, (otype >> 4) & 3,
4264
0
            (otype >> 6) & 3, (otype >> 8) & 3, (otype >> 10) & 3);
4265
0
    return mask;
4266
0
}
4267
4268
// Decode Receiver Reset: x92-01
4269
static gps_mask_t decode_x92_01(struct gps_device_t *session, const char *buf)
4270
0
{
4271
0
    gps_mask_t mask = 0;
4272
0
    unsigned u1 = getub(buf, 6);               // reset cause
4273
4274
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
4275
0
             "TSIPv1 x92-01: cause %u\n", u1);
4276
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4277
0
             "TSIPv1: cause:%s\n",
4278
0
             val2str(u1, vreset_type1));
4279
0
    return mask;
4280
0
}
4281
4282
// Decode Production Information: x93-00
4283
static gps_mask_t decode_x93_00(struct gps_device_t *session, const char *buf)
4284
0
{
4285
0
    gps_mask_t mask = 0;
4286
0
    char buf2[BUFSIZ];
4287
0
    char buf3[BUFSIZ];
4288
4289
0
    unsigned u1 = getub(buf, 4);                // reserved. always 0xff
4290
0
    unsigned long u2 = getbeu32(buf, 5);        // serial number
4291
0
    unsigned long long u3 = getbeu64(buf, 9);   // extended serial number
4292
0
    unsigned long long u4 = getbeu64(buf, 17);  // extended serial number
4293
0
    unsigned u5 = getub(buf, 25);               // build day
4294
0
    unsigned u6 = getub(buf, 26);               // build month
4295
0
    unsigned u7 = getbeu16(buf, 27);            // build year
4296
0
    unsigned u8 = getub(buf, 29);               // build hour
4297
0
    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
0
    unsigned long u10 = getbeu32(buf, 64);       // premium options
4303
0
    unsigned long u11 = getbeu32(buf, 78);       // reserved
4304
    // ignore 77 Osc search range, and 78–81 Osc offset, always 0xff
4305
4306
0
    (void)snprintf(session->subtype1, sizeof(session->subtype1),
4307
0
                   "hw %u %02u/%02u/%04u",
4308
0
                   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
0
    (void)snprintf(session->gpsdata.dev.sernum,
4312
0
                   sizeof(session->gpsdata.dev.sernum),
4313
0
                   "%lx", u2);
4314
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
4315
0
             "TSIPv1 x93-00: res %u ser %s x%llx-%llx Build %u/%u/%u %u "
4316
0
             "machine %u hardware %s product %s "
4317
0
             "options x%04lx res x%04lx\n",
4318
0
             u1, session->gpsdata.dev.sernum,
4319
0
             u3, u4, u7, u6, u5, u8, u9,
4320
0
             gpsd_packetdump(buf2, sizeof(buf2),
4321
0
                            (const unsigned char *)&buf[32], 16),
4322
0
             gpsd_packetdump(buf3, sizeof(buf3),
4323
0
                            (const unsigned char *)&buf[48], 16),
4324
0
             u10, u11);
4325
0
    mask |= DEVICEID_SET;
4326
0
    return mask;
4327
0
}
4328
4329
// Decode xa0-00
4330
static gps_mask_t decode_xa0_00(struct gps_device_t *session, const char *buf,
4331
                                int 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
0
{
4362
0
    gps_mask_t mask = 0;
4363
0
    char buf2[BUFSIZ];
4364
0
    unsigned u1, u2, u3;
4365
0
    int s1;
4366
0
    double d1, d2, d3;
4367
0
    struct tm date = {0};
4368
4369
0
    unsigned tow = getbeu32(buf, 4);
4370
0
    unsigned week = getbeu16(buf, 8);
4371
4372
0
    session->context->gps_week = week;
4373
4374
0
    date.tm_hour = getub(buf, 10);               // hours 0 - 23
4375
0
    date.tm_min = getub(buf, 11);                // minutes 0 -59
4376
0
    date.tm_sec = getub(buf, 12);                // seconds 0 - 60
4377
0
    date.tm_mon = getub(buf, 13) - 1;            // month 1 - 12
4378
0
    date.tm_mday = getub(buf, 14);               // day of month 1 - 31
4379
0
    date.tm_year = getbeu16(buf, 15) - 1900;     // year
4380
4381
0
    u1 = getub(buf, 17);                // time base
4382
0
    u2 = getub(buf, 18);                // PPS base
4383
0
    u3 = getub(buf, 19);                // flags
4384
0
    s1 = getbes16(buf, 20);             // UTC Offset
4385
0
    d1 = getbef32(buf, 22);             // PPS Quantization Error
4386
0
    d2 = getbef32(buf, 26);             // Bias
4387
0
    d3 = getbef32(buf, 30);             // Bias Rate
4388
4389
    // convert seconds to pico seconds
4390
0
    session->gpsdata.qErr = (long)(d1 * 10e12);
4391
    // fix.time is w/o leap seconds...
4392
0
    session->newdata.time.tv_sec = mkgmtime(&date) - s1;
4393
0
    session->newdata.time.tv_nsec = 0;
4394
4395
0
    session->context->leap_seconds = s1;
4396
0
    session->context->valid |= LEAP_SECOND_VALID;
4397
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4398
0
             "TSIPv1 xa1-00: tow %u week %u %02u:%02u:%02u %4u/%02u/%02u "
4399
0
             "tbase %u/%u tflags x%x UTC offset %d qErr %f Bias %f/%f\n",
4400
0
             tow, week, date.tm_hour, date.tm_min, date.tm_sec,
4401
0
             date.tm_year + 1900, date.tm_mon, date.tm_mday,
4402
0
             u1, u2, u3, s1, d1, d2, d3);
4403
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4404
0
             "TSIPv1: tbase:%s pbase:%s tflags:%s\n",
4405
0
             val2str(u1, vtime_base1),
4406
0
             val2str(u2, vtime_base1),
4407
0
             flags2str(u3, vtime_flags1, buf2, sizeof(buf2)));
4408
4409
0
    if (2 == (u3 & 2)) {
4410
        // flags say we have good time
4411
        // if we have good time, can we guess at fix mode?
4412
0
        mask |= TIME_SET;
4413
0
        if (1 == (u3 & 1)) {
4414
            // good UTC
4415
0
            mask |= NTPTIME_IS;
4416
0
        }
4417
0
    }
4418
0
    if (0 == session->driver.tsip.hardware_code) {
4419
        // Query Receiver Version Information
4420
0
        (void)tsip_write1(session, "\x90\x01\x00\x02\x00\x93", 6);
4421
0
    }
4422
0
    mask |= CLEAR_IS;  // ssems to always be first. Time to clear.
4423
0
    return mask;
4424
0
}
4425
4426
// Decode packet xa1-02
4427
static gps_mask_t decode_xa1_02(struct gps_device_t *session, const char *buf)
4428
0
{
4429
0
    gps_mask_t mask = 0;
4430
4431
0
    double d1 = getbef32(buf, 6);               // DAC voltage
4432
0
    unsigned u1 = getbeu16(buf, 10);            // DAC value
4433
0
    unsigned u2 = getub(buf, 12);               // holdover status
4434
0
    unsigned u3 = getbeu32(buf, 13);            // holdover time
4435
4436
0
    session->newdata.temp = getbef32(buf, 17);  // Temperature, degrees C
4437
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4438
0
             "TSIPv1 xa1-02: DAC voltage %f value %u Holdover status %u "
4439
0
             "time %u temp %f\n",
4440
0
             d1, u1, u2, u3, session->newdata.temp);
4441
0
    return mask;
4442
0
}
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
0
{
4447
0
    gps_mask_t mask = 0;
4448
0
    char buf2[BUFSIZ];
4449
4450
0
    unsigned pmask = getub(buf, 4);            // position mask
4451
0
    unsigned ftype = getub(buf, 5);            // fix type
4452
0
    double d1 = getbed64(buf, 6);              // latitude or X
4453
0
    double d2  = getbed64(buf, 14);            // longitude or Y
4454
0
    double d3  = getbed64(buf, 22);            // altitude or Z
4455
0
    double d4  = getbef32(buf, 30);            // velocity X or E
4456
0
    double d5  = getbef32(buf, 34);            // velocity Y or N
4457
0
    double d6  = getbef32(buf, 38);            // velocity Z or U
4458
4459
0
    double pdop = getbef32(buf, 42);  // PDOP, surveyed/current
4460
4461
0
    if (IN(0.01, pdop, 89.99)) {
4462
        // why not to newdata?
4463
0
        session->gpsdata.dop.pdop = pdop;
4464
0
        mask |= DOP_SET;
4465
0
    }
4466
0
    session->newdata.eph = getbef32(buf, 46);  // eph, 0 - 100, unknown units
4467
0
    session->newdata.epv = getbef32(buf, 50);  // epv, 0 - 100, unknown units
4468
0
    mask |= DOP_SET;
4469
    // position mask bit 0 does not tell us if we are in OD mode
4470
0
    if (0 == (pmask & 2)) {
4471
        // LLA
4472
0
        session->newdata.latitude = d1;
4473
0
        session->newdata.longitude = d2;
4474
0
        if (0 == (pmask & 4)) {
4475
            // HAE
4476
0
            session->newdata.altHAE = d3;
4477
0
        } else {
4478
            // MSL
4479
0
            session->newdata.altMSL = d3;
4480
0
        }
4481
0
        mask |= LATLON_SET | ALTITUDE_SET;
4482
0
    } else {
4483
        // XYZ ECEF
4484
0
        session->newdata.ecef.x = d1;
4485
0
        session->newdata.ecef.y = d2;
4486
0
        session->newdata.ecef.z = d3;
4487
0
        mask |= ECEF_SET;
4488
0
    }
4489
0
    if (0 == (pmask & 1)) {
4490
        // valid velocity
4491
0
        if (0 == (pmask & 8)) {
4492
            // Velocity ENU
4493
0
            session->newdata.NED.velN = d5;
4494
0
            session->newdata.NED.velE = d4;
4495
0
            session->newdata.NED.velD = -d6;
4496
0
            mask |= VNED_SET;
4497
0
        } else {
4498
            // Velocity ECEF
4499
0
            session->newdata.ecef.vx = d4;
4500
0
            session->newdata.ecef.vy = d5;
4501
0
            session->newdata.ecef.vz = d6;
4502
0
            mask |= VECEF_SET;
4503
0
        }
4504
0
    }
4505
0
    switch (ftype) {
4506
0
    default:
4507
0
        FALLTHROUGH
4508
0
    case 0:
4509
0
        session->newdata.mode = MODE_NO_FIX;
4510
0
        break;
4511
0
    case 1:
4512
0
        session->newdata.mode = MODE_2D;
4513
0
        break;
4514
0
    case 2:
4515
0
        session->newdata.mode = MODE_3D;
4516
0
    }
4517
    // status NOT set
4518
0
    mask |= MODE_SET | DOP_SET | HERR_SET | VERR_SET;
4519
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4520
0
             "TSIPv1 xa1-11: mode %d status %d pmask %u fixt %u "
4521
0
             "Pos %f %f %f Vel %f %f %f PDOP %f eph %f epv %f\n",
4522
0
             session->newdata.mode,
4523
0
             session->newdata.status,
4524
0
             pmask, ftype, d1, d2, d3, d4, d5, d6,
4525
0
             pdop,
4526
0
             session->newdata.eph,
4527
0
             session->newdata.epv);
4528
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4529
0
             "TSIPv1: mode:%s status:%s pmask:%s fixt %s\n",
4530
0
             val2str(session->newdata.mode, vmode_str),
4531
0
             val2str(session->newdata.status, vstatus_str),
4532
0
             flags2str(pmask, vpos_mask1, buf2, sizeof(buf2)),
4533
0
             val2str(ftype, vfix_type1));
4534
0
    return mask;
4535
0
}
4536
4537
// decode packet xa2-00
4538
static gps_mask_t decode_xa2_00(struct gps_device_t *session, const char *buf)
4539
0
{
4540
0
    gps_mask_t mask = 0;
4541
0
    timespec_t ts_tow;
4542
0
    unsigned char gnssid, sigid;
4543
0
    char buf2[BUFSIZ];
4544
4545
0
    unsigned u1 = getub(buf, 4);               // message number, 1 to X
4546
4547
    // SV type, 0 to 26, mashup of constellation and signal
4548
0
    unsigned u2 = getub(buf, 5);
4549
0
    unsigned prn = getub(buf, 6);              // PRN (svid) 1 to 32 (99)
4550
0
    double az = getbef32(buf, 7);              // azimuth, degrees
4551
0
    double el = getbef32(buf, 11);             // elevation, degrees
4552
0
    double d3 = getbef32(buf, 15);             // signal level, db-Hz
4553
0
    unsigned u4 = getbeu32(buf, 19);           // Flags
4554
    // TOW of measurement, not current TOW!
4555
0
    unsigned tow = getbeu32(buf, 23);          // TOW, seconds
4556
4557
0
    if (0 == u1) {
4558
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4559
0
                "TSIPv1 xa2-00: invalid message number %u\n", u1);
4560
0
        return 0;
4561
0
    } else if (1 == u1) {
4562
        // message number starts at 1, no way to know last number
4563
0
        gpsd_zero_satellites(&session->gpsdata);
4564
        // start of new cycle, save last count
4565
0
        session->gpsdata.satellites_visible =
4566
0
            session->driver.tsip.last_chan_seen;
4567
0
    } else if (TSIP_CHANNELS < u1) {
4568
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4569
0
                "TSIPv1 xa2-00: too many satellites %d\n", u1);
4570
0
        return 0;
4571
0
    } else if (0 == prn ||
4572
0
               99 < prn) {
4573
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4574
0
                "TSIPv1 xa2-00: invalid prn %d\n", prn);
4575
0
        return 0;
4576
0
    }
4577
0
    session->driver.tsip.last_chan_seen = u1;
4578
0
    session->driver.tsip.last_a200 = tow;
4579
0
    ts_tow.tv_sec = tow;
4580
0
    ts_tow.tv_nsec = 0;
4581
0
    session->gpsdata.skyview_time =
4582
0
            gpsd_gpstime_resolv(session, session->context->gps_week,
4583
0
                                ts_tow);
4584
4585
    // convert svtype to gnssid and svid
4586
0
    gnssid = tsipv1_svtype(u2, &sigid);
4587
0
    session->gpsdata.skyview[u1 - 1].gnssid = gnssid;
4588
0
    session->gpsdata.skyview[u1 - 1].svid = prn;
4589
0
    session->gpsdata.skyview[u1 - 1].sigid = sigid;
4590
    // "real" NMEA 4.0 (not 4.10 ir 4.11) PRN
4591
0
    session->gpsdata.skyview[u1 - 1].PRN = ubx2_to_prn(gnssid, prn);
4592
0
    if (0 >= session->gpsdata.skyview[u1 - 1].PRN) {
4593
        // bad PRN??
4594
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4595
0
                 "TSIPv1 xa2-00(%u): Bad PRN: gnssid %u, prn %u PRN %d\n",
4596
0
                 u1, gnssid, prn, session->gpsdata.skyview[u1 - 1].PRN);
4597
0
    }
4598
0
    if (0 != (1 & u4)) {
4599
0
        if (90.0 >= fabs(el)) {
4600
0
            session->gpsdata.skyview[u1 - 1].elevation = el;
4601
0
        }
4602
0
        if (360.0 > az &&
4603
0
            0.0 <= az) {
4604
0
            session->gpsdata.skyview[u1 - 1].azimuth = az;
4605
0
        }
4606
0
    }
4607
0
    session->gpsdata.skyview[u1 - 1].ss = d3;
4608
0
    if (0 != (6 & u4)) {
4609
0
        session->gpsdata.skyview[u1 - 1].used = true;
4610
0
    }
4611
4612
0
    if ((int)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
0
        if (10 < llabs(session->driver.tsip.last_a311 -
4619
0
                       session->driver.tsip.last_a200)) {
4620
            // no xa3-11 in 10 seconds, so push out now
4621
0
            mask |= SATELLITE_SET;
4622
0
            session->driver.tsip.last_a200 = 0;
4623
0
        }
4624
0
    }
4625
0
    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
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4634
0
             "TSIPv1 xa2-00: num %u type %u (gnss %u sigid %u) PRN %u "
4635
0
             "az %f el %f snr %f sflags x%0x4 tow %u\n",
4636
0
             u1, u2, gnssid, sigid, prn, az, el, d3, u4, tow);
4637
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4638
0
             "TSIPv1: svtype:%s flags:%s\n",
4639
0
             val2str(u2, vsv_type1),
4640
0
             flags2str(u4, vsflags1, buf2, sizeof(buf2)));
4641
0
    return mask;
4642
0
}
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
0
{
4648
0
    gps_mask_t mask = 0;
4649
0
    char buf2[BUFSIZ];
4650
0
    char buf3[BUFSIZ];
4651
4652
0
    unsigned minor_alarm = getbeu32(buf, 4);            // Minor Alarms
4653
0
    unsigned res1 = getbeu32(buf, 8);                   // reserved
4654
0
    unsigned major_alarm = getbeu32(buf, 12);           // Major Alarms
4655
0
    unsigned res2 = getbeu32(buf, 16);                  // reserved
4656
4657
0
    if (1 & minor_alarm) {
4658
0
        session->newdata.ant_stat = ANT_OPEN;
4659
0
    } else if (2 & minor_alarm) {
4660
0
        session->newdata.ant_stat = ANT_SHORT;
4661
0
    } else {
4662
0
        session->newdata.ant_stat = ANT_OK;
4663
0
    }
4664
4665
0
    if (1 == (major_alarm & 1)) {
4666
        // not tracking sats, assume surveyed-in
4667
0
        session->newdata.status = STATUS_DR;
4668
0
    } else {
4669
0
        session->newdata.status = STATUS_GPS;
4670
0
    }
4671
0
    if (0x80 == (major_alarm & 0x80)) {
4672
        // jamming
4673
0
        session->newdata.jam = 255;
4674
0
    } else if (0x40 == (major_alarm & 0x40)) {
4675
        // spoofing/multipath
4676
0
        session->newdata.jam = 128;
4677
0
    }
4678
0
    mask |= STATUS_SET;
4679
4680
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4681
0
             "TSIPv1 xa3-00: Minor x%04x res x%04x Major x%04x "
4682
0
             "res x%04u status %d\n",
4683
0
             minor_alarm, res1, major_alarm, res2,
4684
0
             session->newdata.status);
4685
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4686
0
             "TSIPv1: minor:%s mojor:%s status:%s\n",
4687
0
             flags2str(minor_alarm, vminor_alarms1, buf2, sizeof(buf2)),
4688
0
             flags2str(major_alarm, vmajor_alarms1, buf3, sizeof(buf3)),
4689
0
             val2str(session->newdata.status, vstatus_str));
4690
0
    return mask;
4691
0
}
4692
4693
// decode packet xa3-11
4694
static gps_mask_t decode_xa3_11(struct gps_device_t *session, const char *buf)
4695
0
{
4696
0
    gps_mask_t mask = 0;
4697
4698
0
    unsigned rec_mode = getub(buf, 4);                // receiver mode
4699
0
    unsigned rec_status = getub(buf, 5);              // status
4700
0
    unsigned ssp = getub(buf, 6);              // self survey progress 0 - 100
4701
4702
0
    double pdop = getbef32(buf, 7);     // PDOP
4703
0
    double hdop = getbef32(buf, 11);    // HDOP
4704
0
    double vdop = getbef32(buf, 15);    // VDOP
4705
0
    double tdop = getbef32(buf, 19);    // TDOP
4706
4707
0
    session->newdata.temp = getbef32(buf, 23);        // Temperature, degrees C
4708
4709
0
    if (IN(0.01, pdop, 89.99)) {
4710
        // why not to newdata?
4711
0
        session->gpsdata.dop.pdop = pdop;
4712
0
        mask |= DOP_SET;
4713
0
    }
4714
0
    if (IN(0.01, hdop, 89.99)) {
4715
        // why not to newdata?
4716
0
        session->gpsdata.dop.hdop = hdop;
4717
0
        mask |= DOP_SET;
4718
0
    }
4719
0
    if (IN(0.01, vdop, 89.99)) {
4720
        // why not to newdata?
4721
0
        session->gpsdata.dop.vdop = vdop;
4722
0
        mask |= DOP_SET;
4723
0
    }
4724
0
    if (IN(0.01, tdop, 89.99)) {
4725
        // why not to newdata?
4726
0
        session->gpsdata.dop.tdop = tdop;
4727
0
        mask |= DOP_SET;
4728
0
    }
4729
4730
    // don't have tow, so use the one from xa2-00, if any
4731
0
    session->driver.tsip.last_a311 = session->driver.tsip.last_a200;
4732
4733
0
    if (0 < session->driver.tsip.last_a200) {
4734
0
        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
0
        mask |= SATELLITE_SET;
4738
0
    }
4739
0
    mask |= REPORT_IS;
4740
0
    switch (rec_status) {
4741
0
    case 0:         // 2D
4742
0
        session->newdata.mode = MODE_2D;
4743
0
        mask |= MODE_SET;
4744
0
        break;
4745
0
    case 1:         // 3D (time only)
4746
0
        session->newdata.mode = MODE_3D;
4747
0
        mask |= MODE_SET;
4748
0
        break;
4749
0
    case 3:         // Automatic (?)
4750
0
        break;
4751
0
    case 4:         // OD clock
4752
0
        session->newdata.status = STATUS_TIME;
4753
0
        mask |= STATUS_SET;
4754
0
        break;
4755
0
    default:        // Huh?
4756
0
        break;
4757
0
    }
4758
4759
0
    switch (rec_status) {
4760
0
    case 0:         // doing position fixes
4761
0
        FALLTHROUGH
4762
0
    case 4:         // using 1 sat
4763
0
        FALLTHROUGH
4764
0
    case 5:         // using 2 sat
4765
0
        FALLTHROUGH
4766
0
    case 6:         // using 3 sat
4767
0
        session->newdata.status = STATUS_GPS;
4768
0
        mask |= STATUS_SET;
4769
0
        break;
4770
0
    case 1:         // no GPS time
4771
0
        FALLTHROUGH
4772
0
    case 2:         // PDOP too high
4773
0
        FALLTHROUGH
4774
0
    case 3:         // no sats
4775
0
        session->newdata.status = STATUS_UNK;
4776
0
        mask |= STATUS_SET;
4777
0
        break;
4778
0
    case 255:
4779
0
        session->newdata.mode = MODE_3D;
4780
0
        session->newdata.status = STATUS_TIME;
4781
0
        mask |= STATUS_SET | MODE_SET;
4782
0
        break;
4783
0
    default:
4784
        // huh?
4785
0
        break;
4786
0
    }
4787
4788
0
    if (10.0 < pdop) {
4789
0
        session->newdata.status = STATUS_DR;
4790
0
        mask |= STATUS_SET;
4791
0
    }
4792
4793
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4794
0
             "TSIPv1 xa3-11: mode %d status %d rm %u stat %u survey %u "
4795
0
             "PDOP %f HDOP %f VDOP %f TDOP %f temp %f\n",
4796
0
             session->newdata.mode,
4797
0
             session->newdata.status,
4798
0
             rec_mode, rec_status, ssp,
4799
0
             pdop, hdop, vdop, tdop,
4800
0
             session->newdata.temp);
4801
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4802
0
             "TSIPv1: mode:%s status:%s rm:%s stat:%s\n",
4803
0
             val2str(session->newdata.mode, vmode_str),
4804
0
             val2str(session->newdata.status, vstatus_str),
4805
0
             val2str(rec_mode, vrec_mode1),
4806
0
             val2str(rec_status, vgnss_decode_status1));
4807
4808
0
    return mask;
4809
0
}
4810
4811
// decode packet xa3-21
4812
static gps_mask_t decode_xa3_21(struct gps_device_t *session, const char *buf)
4813
0
{
4814
0
    gps_mask_t mask = 0;
4815
4816
0
    unsigned u1 = getub(buf, 4);            // reference packet id
4817
0
    unsigned u2 = getub(buf, 5);            // reference sub packet id
4818
0
    unsigned u3 = getub(buf, 6);            // error code
4819
4820
0
    GPSD_LOG(LOG_WARN, &session->context->errout,
4821
0
             "TSIPv1 xa3-21: id x%02x-%02x error: %u\n",
4822
0
             u1, u2, u3);
4823
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4824
0
             "TSIPv1: ec:%s\n",
4825
0
             val2str(u3, verr_codes1));
4826
0
    return mask;
4827
0
}
4828
4829
// Decode xbb
4830
static gps_mask_t decode_xbb(struct gps_device_t *session, const char *buf)
4831
0
{
4832
0
    gps_mask_t mask = 0;
4833
0
    unsigned u1 = getub(buf, 0);        // Subcode, always zero?
4834
0
    unsigned u2 = getub(buf, 1);        // Operating Dimension (Receiver Mode)
4835
0
    unsigned u3 = getub(buf, 2);        // DGPS Mode (not in Acutime Gold)
4836
0
    unsigned u4 = getub(buf, 3);        // Dynamics Code
4837
0
    double f1 = getbef32(buf, 5);       // Elevation Mask
4838
0
    double f2 = getbef32(buf, 9);       // AMU Mask
4839
0
    double f3 = getbef32(buf, 13);      // DOP Mask
4840
0
    double f4 = getbef32(buf, 17);      // DOP Switch
4841
0
    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
0
    unsigned u6 = getub(buf, 27);
4854
4855
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
4856
0
             "TSIP xbb: Navigation Configuration: %u %u %u %u %f %f %f "
4857
0
             "%f %u x%x\n",
4858
0
             u1, u2, u3, u4, f1, f2, f3, f4, u5, u6);
4859
0
    GPSD_LOG(LOG_IO, &session->context->errout,
4860
0
             "TSIP: rm %s\n",
4861
0
             val2str(u1, vrec_mode));
4862
0
    return mask;
4863
0
}
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, int len)
4900
0
{
4901
0
    gps_mask_t mask = 0;
4902
0
    unsigned sub_id, length, mode;
4903
0
    unsigned u1;
4904
0
    bool bad_len = false;
4905
0
    unsigned char chksum;
4906
4907
0
    if (4 > len) {
4908
        // should never happen
4909
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4910
0
                 "TSIPv1 0x%02x: runt, got len %u\n",
4911
0
                 id, len);
4912
0
        return mask;
4913
0
    }
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
0
    sub_id = getub(buf, 0);
4917
0
    length = getbeu16(buf, 1);  // expected length
4918
0
    mode = getub(buf, 3);
4919
4920
0
    if ((length + 3) != (unsigned)len) {
4921
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4922
0
                 "TSIPv1 x%02x-%02x: Bad Length, "
4923
0
                 "length got %d expected %u mode %u\n",
4924
0
                 id, sub_id, len, length + 3, mode);
4925
0
        return mask;
4926
0
    }
4927
4928
    // checksum is id, sub id, length, mode, data, not including trailer
4929
    // length is mode + data + checksum
4930
0
    chksum = id;
4931
0
    for (u1 = 0; u1 < (length + 3); u1++ ) {
4932
0
        chksum ^= buf[u1];
4933
0
    }
4934
0
    if (0 != chksum) {
4935
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
4936
0
                 "TSIPv1 x%02x-%02x: Bad Checksum "
4937
0
                 "length %d/%u mode %u\n",
4938
0
                 id, sub_id, len, length + 3, mode);
4939
0
        return mask;
4940
0
    }
4941
4942
0
    GPSD_LOG(LOG_DATA, &session->context->errout,
4943
0
             "TSIPv1 x%02x-%02x: length %d/%u mode %u\n",
4944
0
             id, sub_id, len, length + 3, mode);
4945
4946
0
    if (2 != mode) {
4947
        /* Don't decode queries (mode 0) or set (mode 1).
4948
         * Why would we even see one? */
4949
0
        return mask;
4950
0
    }
4951
    // FIXME: check len/length
4952
0
    switch ((id << 8) | sub_id) {
4953
0
    case 0x9000:
4954
        // Protocol Version, x90-00
4955
0
        if (11 > length) {
4956
0
            bad_len = true;
4957
0
            break;
4958
0
        }
4959
0
        mask = decode_x90_00(session, buf);
4960
0
        break;
4961
0
    case 0x9001:
4962
        /* Receiver Version Information, x90-01
4963
         * Received in response to the TSIPv1 probe */
4964
0
        if (13 > length) {
4965
0
            bad_len = true;
4966
0
            break;
4967
0
        }
4968
0
        mask = decode_x90_01(session, buf, len);
4969
0
        break;
4970
0
    case 0x9100:
4971
        // Port Configuration, x91-00
4972
0
        if (17 > length) {
4973
0
            bad_len = true;
4974
0
            break;
4975
0
        }
4976
0
        mask = decode_x91_00(session, buf);
4977
0
        break;
4978
0
    case 0x9101:
4979
        // GNSS Configuration, x91-01
4980
0
        if (28 > length) {
4981
0
            bad_len = true;
4982
0
            break;
4983
0
        }
4984
0
        mask = decode_x91_01(session, buf);
4985
0
        break;
4986
0
    case 0x9102:
4987
        // NVS Configuration, x91-02
4988
0
        if (8 > length) {
4989
0
            bad_len = true;
4990
0
            break;
4991
0
        }
4992
0
        mask = decode_x91_02(session, buf);
4993
0
        break;
4994
0
    case 0x9103:
4995
        // Timing Configuration, x91-03
4996
0
        if (19 > length) {
4997
0
            bad_len = true;
4998
0
            break;
4999
0
        }
5000
0
        mask = decode_x91_03(session, buf);
5001
0
        break;
5002
0
    case 0x9104:
5003
        // Self-Survey Configuration, x91-04
5004
0
        if (11 > length) {
5005
0
            bad_len = true;
5006
0
            break;
5007
0
        }
5008
0
        mask = decode_x91_04(session, buf);
5009
0
        break;
5010
0
    case 0x9105:
5011
        //  Receiver Configuration, xx91-05
5012
0
        if (19 > length) {
5013
0
            bad_len = true;
5014
0
            break;
5015
0
        }
5016
0
        mask = decode_x91_05(session, buf);
5017
0
        break;
5018
0
    case 0x9201:
5019
        // Reset Cause, x92-01
5020
0
        if (3 > length) {
5021
0
            bad_len = true;
5022
0
            break;
5023
0
        }
5024
0
        mask = decode_x92_01(session, buf);
5025
0
        break;
5026
0
    case 0x9300:
5027
        // Production Information, x93-00
5028
0
        if (78 > length) {
5029
0
            bad_len = true;
5030
0
            break;
5031
0
        }
5032
0
        mask = decode_x93_00(session, buf);
5033
0
        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
0
    case 0xa100:
5045
        // Timing Information. xa1-00
5046
        // the only message on by default
5047
0
        if (32 > length) {
5048
0
            bad_len = true;
5049
0
            break;
5050
0
        }
5051
0
        mask = decode_xa1_00(session, buf);
5052
0
        break;
5053
5054
0
    case 0xa102:
5055
        // Frequency Information, xa1-02
5056
0
        if (17 > length) {
5057
0
            bad_len = true;
5058
0
            break;
5059
0
        }
5060
0
        mask = decode_xa1_02(session, buf);
5061
0
        break;
5062
5063
0
    case 0xa111:
5064
        // Position Information, xa1-11
5065
0
        if (52 > length) {
5066
0
            bad_len = true;
5067
0
            break;
5068
0
        }
5069
0
        mask = decode_xa1_11(session, buf);
5070
0
        break;
5071
0
    case 0xa200:
5072
        // Satellite Information, xa2-00
5073
0
        if (25 > length) {
5074
0
            bad_len = true;
5075
0
            break;
5076
0
        }
5077
0
        mask = decode_xa2_00(session, buf);
5078
0
        break;
5079
5080
0
    case 0xa300:
5081
        // System Alarms, xa3-00
5082
0
        if (18 > length) {
5083
0
            bad_len = true;
5084
0
            break;
5085
0
        }
5086
0
        mask = decode_xa3_00(session, buf);
5087
0
        break;
5088
0
    case 0xa311:
5089
        /* Receiver Status, xa3-11
5090
         * RES 720
5091
         */
5092
0
        if (29 > length) {
5093
0
            bad_len = true;
5094
0
            break;
5095
0
        }
5096
        // usually the last message, except for A2-00 (sats)
5097
0
        mask = decode_xa3_11(session, buf);
5098
0
        break;
5099
0
    case 0xa321:
5100
        /* Error Report xa3-21
5101
         * expect errors for x1c-03 and x35-32 from TSIP probes
5102
         */
5103
0
        if (5 > length) {
5104
0
            bad_len = true;
5105
0
            break;
5106
0
        }
5107
0
        mask = decode_xa3_21(session, buf);
5108
0
        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
0
    default:
5146
        // Huh?
5147
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
5148
0
                 "TSIPv1 x%02x-%02x: unknown packet id/su-id\n",
5149
0
                 id, sub_id);
5150
0
        break;
5151
0
    }
5152
0
    if (bad_len) {
5153
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
5154
0
                 "TSIPv1 0x%02x-%02x: runt, got length %u\n",
5155
0
                 id, sub_id, length);
5156
0
        mask = 0;
5157
0
    }
5158
    // get next item off queue
5159
0
    tsipv1_query(session);
5160
5161
0
    return mask;
5162
0
}
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
0
{
5170
0
    int i, len;
5171
0
    gps_mask_t mask = 0;
5172
0
    unsigned int id;
5173
0
    time_t now;
5174
0
    char buf[sizeof(session->lexer.outbuffer)];
5175
0
    char buf2[BUFSIZ];
5176
0
    int bad_len = 0;
5177
0
    bool valid = false;
5178
5179
0
    if (TSIP_PACKET != session->lexer.type) {
5180
        // this should not happen
5181
0
        GPSD_LOG(LOG_INF, &session->context->errout,
5182
0
                 "TSIP: tsip_analyze packet type %d\n",
5183
0
                 session->lexer.type);
5184
0
        return 0;
5185
0
    }
5186
5187
0
    if (4 > session->lexer.outbuflen ||
5188
0
        0x10 != session->lexer.outbuffer[0]) {
5189
        // packet too short, or does not start with DLE
5190
0
        GPSD_LOG(LOG_INF, &session->context->errout,
5191
0
                 "TSIP: tsip_analyze packet bad packet\n");
5192
0
        return 0;
5193
0
    }
5194
5195
    /* get receive time, first
5196
     * using system time breaks regressions!
5197
     * so use latest from receiver */
5198
0
    if (0 != session->lastfix.time.tv_sec) {
5199
0
        now = session->lastfix.time.tv_sec;
5200
0
    } else if (0 != session->oldfix.time.tv_sec) {
5201
0
        now = session->oldfix.time.tv_sec;
5202
0
    } else {
5203
0
        now = 0;
5204
0
    }
5205
5206
    // put data part of message in buf
5207
5208
0
    memset(buf, 0, sizeof(buf));
5209
0
    len = 0;
5210
0
    for (i = 2; i < (int)session->lexer.outbuflen; i++) {
5211
0
        if (0x10 == session->lexer.outbuffer[i] &&
5212
0
            0x03 == session->lexer.outbuffer[++i]) {
5213
                // DLE, STX.  end of packet, we know the length
5214
0
                valid = true;
5215
0
                break;
5216
0
        }
5217
0
        buf[len++] = session->lexer.outbuffer[i];
5218
0
    }
5219
5220
0
    id = (unsigned)session->lexer.outbuffer[1];
5221
0
    if (valid &&
5222
0
        1024 > len) {
5223
0
        GPSD_LOG(LOG_DATA, &session->context->errout,
5224
0
                 "TSIP x%02x: length %d: %s\n",
5225
0
                 id, len, gps_hexdump(buf2, sizeof(buf2),
5226
0
                                      (unsigned char *)buf, len));
5227
0
    } else {
5228
        /* End of message not found, or too long, or both.
5229
         * Fuzzers gonna fuzz. */
5230
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
5231
0
                 "TSIP x%02x: Too long. length %d: %s\n",
5232
0
                 id, len, gps_hexdump(buf2, sizeof(buf2),
5233
0
                                      (unsigned char *)buf, len));
5234
0
        return mask;
5235
0
    }
5236
5237
    // session->cycle_end_reliable = true;
5238
0
    switch (id) {
5239
0
    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
0
        if (1 > len) {
5250
0
            bad_len = 1;
5251
0
            break;
5252
0
        }
5253
0
        mask = decode_x13(session, buf, len);
5254
0
        break;
5255
5256
0
    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
0
        mask = decode_x1c(session, buf, len, &bad_len);
5275
0
        break;
5276
0
    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
0
        if (10 > len) {
5287
0
            bad_len = 10;
5288
0
            break;
5289
0
        }
5290
0
        session->driver.tsip.last_41 = now;     // keep timestamp for request
5291
0
        mask = decode_x41(session, buf);
5292
0
        break;
5293
0
    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
0
        if (16 > len) {
5302
0
            bad_len = 16;
5303
0
            break;
5304
0
        }
5305
0
        mask = decode_x42(session, buf);
5306
0
        break;
5307
0
    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
0
        if (20 > len) {
5317
0
            bad_len = 20;
5318
0
            break;
5319
0
        }
5320
0
        mask = decode_x43(session, buf);
5321
0
        break;
5322
0
    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
0
        if (10 > len) {
5337
0
            bad_len = 10;
5338
0
            break;
5339
0
        }
5340
0
        mask = decode_x45(session, buf);
5341
0
        break;
5342
0
    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
0
        if (2 > len) {
5353
0
            bad_len = 2;
5354
0
            break;
5355
0
        }
5356
0
        session->driver.tsip.last_46 = now;
5357
0
        mask = decode_x46(session, buf);
5358
0
        break;
5359
0
    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
0
        if (1 > len) {
5368
0
            bad_len = 1;
5369
0
            break;
5370
0
        }
5371
0
        mask = decode_x47(session, buf, len, &bad_len);
5372
0
        break;
5373
0
    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
0
        buf[len] = '\0';
5383
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
5384
0
                 "TSIP x48: GPS System Message: %s\n", buf);
5385
0
        break;
5386
0
    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
0
        if (20 > len) {
5396
0
            bad_len = 20;
5397
0
            break;
5398
0
        }
5399
0
        mask = decode_x4a(session, buf);
5400
0
        break;
5401
0
    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
0
        if (3 > len) {
5417
0
            bad_len = 3;
5418
0
            break;
5419
0
        }
5420
0
        mask = decode_x4b(session, buf);
5421
0
        break;
5422
0
    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
0
        if (17 > len) {
5433
0
            bad_len = 17;
5434
0
            break;
5435
0
        }
5436
0
        mask = decode_x4c(session, buf);
5437
0
        break;
5438
0
    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
0
        if (12 > len) {
5450
0
            bad_len = 12;
5451
0
            break;
5452
0
        }
5453
0
         mask = decode_x54(session, buf);
5454
0
        break;
5455
0
    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
0
        if (4 > len) {
5470
0
            bad_len = 4;
5471
0
            break;
5472
0
        }
5473
0
        mask = decode_x55(session, buf, now);
5474
0
        break;
5475
0
    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
0
        if (20 > len) {
5484
0
            bad_len = 20;
5485
0
            break;
5486
0
        }
5487
0
        mask = decode_x56(session, buf);
5488
0
        break;
5489
0
    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
0
        if (8 > len) {
5498
0
            bad_len = 8;
5499
0
            break;
5500
0
        }
5501
0
        mask = decode_x57(session, buf);
5502
0
        break;
5503
0
    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
0
        if (25 > len) {
5512
0
            bad_len = 25;
5513
0
            break;
5514
0
        }
5515
0
        mask = decode_x5a(session, buf);
5516
0
        break;
5517
0
    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
0
        if (24 > len) {
5530
0
            bad_len = 24;
5531
0
            break;
5532
0
        }
5533
0
        mask = decode_x5c(session, buf);
5534
0
        break;
5535
5536
0
     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
0
        if (26 > len) {
5550
0
            bad_len = 26;
5551
0
            break;
5552
0
        }
5553
0
        mask = decode_x5d(session, buf);
5554
0
        break;
5555
0
    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
0
        if (18 > len) {
5568
0
            bad_len = 18;
5569
0
            break;
5570
0
        }
5571
        // why same as 6d?
5572
0
        session->driver.tsip.last_6d = now;     // keep timestamp for request
5573
0
        mask = decode_x6c(session, buf, len, &bad_len);
5574
0
        break;
5575
0
    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
0
        if (17 > len) {
5591
0
            bad_len = 17;
5592
0
            break;
5593
0
        }
5594
0
        session->driver.tsip.last_6d = now;     // keep timestamp for request
5595
0
        mask = decode_x6d(session, buf, len, &bad_len);
5596
0
        break;
5597
0
    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
0
        if (1 > len) {
5612
0
            bad_len = 1;
5613
0
            break;
5614
0
        }
5615
0
        mask = decode_x82(session, buf);
5616
0
        break;
5617
0
    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
0
        if (36 > len) {
5628
0
            bad_len = 36;
5629
0
            break;
5630
0
        }
5631
0
        mask = decode_x83(session, buf);
5632
0
        break;
5633
0
    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
0
        if (36 > len) {
5643
0
            bad_len = 36;
5644
0
            break;
5645
0
        }
5646
0
        mask = decode_x84(session, buf);
5647
0
        break;
5648
0
    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
0
        mask = decode_x8f(session, buf, len, &bad_len, now);
5660
0
        break;
5661
// Start of TSIP V1
5662
0
    case 0x90:
5663
        /* Version Information, TSIP v1
5664
         * Present in:
5665
         *   RES720
5666
         */
5667
0
        FALLTHROUGH
5668
0
    case 0x91:
5669
        /* Receiver Configuration, TSIP v1
5670
         * Present in:
5671
         *   RES720
5672
         */
5673
0
        FALLTHROUGH
5674
0
    case 0x92:
5675
        /* Resets, TSIP v1
5676
         * Present in:
5677
         *   RES720
5678
         */
5679
0
        FALLTHROUGH
5680
0
    case 0x93:
5681
        /* Production & Manufacturing, TSIP v1
5682
         * Present in:
5683
         *   RES720
5684
         */
5685
0
        FALLTHROUGH
5686
0
    case 0xa0:
5687
        /* Firmware Upload, TSIP v1
5688
         * Present in:
5689
         *   RES720
5690
         */
5691
0
        FALLTHROUGH
5692
0
    case 0xa1:
5693
        /* PVT, TSIP v1
5694
         * Present in:
5695
         *   RES720
5696
         */
5697
0
        FALLTHROUGH
5698
0
    case 0xa2:
5699
        /* GNSS Information, TSIP v1
5700
         * Present in:
5701
         *   RES720
5702
         */
5703
0
        FALLTHROUGH
5704
0
    case 0xa3:
5705
        /* Alarms % Status, TSIP v1
5706
         * Present in:
5707
         *   RES720
5708
         */
5709
0
        FALLTHROUGH
5710
0
    case 0xa4:
5711
        /* AGNSS, TSIP v1
5712
         * Present in:
5713
         *   RES720
5714
         */
5715
0
        FALLTHROUGH
5716
0
    case 0xa5:
5717
        /* Miscellaneous, TSIP v1
5718
         * Present in:
5719
         *   RES720
5720
         */
5721
0
        FALLTHROUGH
5722
0
    case 0xd0:
5723
        /* Debug & Logging, TSIP v1
5724
         * Present in:
5725
         *   RES720
5726
         */
5727
0
        return tsipv1_parse(session, id, buf, len);
5728
// end of TSIP V1
5729
0
    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
0
        if (40 != len &&
5738
0
            43 != len) {
5739
            // see packet.c for explamation
5740
0
            bad_len = 40;
5741
0
            break;
5742
0
        }
5743
0
        mask = decode_xbb(session, buf);
5744
0
        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
0
    case 0x49:
5807
        /* Almanac Health Page
5808
         * Present in:
5809
         *   pre-2000 models
5810
         * Not Present in:
5811
         *   Copernicus II (2009)
5812
         */
5813
0
        FALLTHROUGH
5814
0
    case 0x4d:
5815
        /* Oscillator Offset
5816
         * Present in:
5817
         *   pre-2000 models
5818
         *   Copernicus II (2009)
5819
         */
5820
0
        FALLTHROUGH
5821
0
    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
0
        FALLTHROUGH
5830
0
    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
0
        FALLTHROUGH
5840
0
    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
0
        FALLTHROUGH
5850
0
    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
0
        FALLTHROUGH
5859
0
    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
0
        FALLTHROUGH
5870
0
    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
0
        FALLTHROUGH
5880
0
    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
0
        FALLTHROUGH
5890
0
    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
0
        FALLTHROUGH
5900
0
    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
0
        FALLTHROUGH
5910
0
    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
0
        FALLTHROUGH
5920
0
    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
0
        FALLTHROUGH
5930
0
    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
0
        FALLTHROUGH
5940
0
    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
0
        FALLTHROUGH
5950
0
    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
0
        FALLTHROUGH
5960
0
    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
0
        FALLTHROUGH
5970
0
    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
0
        FALLTHROUGH
5980
0
    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
0
        FALLTHROUGH
5989
0
    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
0
        FALLTHROUGH
5999
0
    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
0
        FALLTHROUGH
6009
0
    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
0
        FALLTHROUGH
6019
0
    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
0
        FALLTHROUGH
6029
0
    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
0
        FALLTHROUGH
6039
0
    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
0
        FALLTHROUGH
6049
0
    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
0
        FALLTHROUGH
6059
0
    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
0
        FALLTHROUGH
6069
0
    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
0
        FALLTHROUGH
6079
0
    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
0
        FALLTHROUGH
6089
0
    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
0
        FALLTHROUGH
6099
0
    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
0
        FALLTHROUGH
6109
0
    default:
6110
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
6111
0
                 "TSIP x%02x: Unhandled packet type\n", id);
6112
0
        break;
6113
0
    }
6114
6115
#ifdef __UNUSED__
6116
// #if 1
6117
    // full reset
6118
    (void)tsip_write1(session, "\x1e\x46", 2);
6119
#endif
6120
6121
0
    if (bad_len) {
6122
0
        GPSD_LOG(LOG_WARNING, &session->context->errout,
6123
0
                 "TSIP x%02x: wrong len %d s/b >= %d \n", id, len, bad_len);
6124
0
    } else {
6125
0
        GPSD_LOG(LOG_IO, &session->context->errout,
6126
0
                 "TSIP x%02x: mask %s\n", id, gps_maskdump(mask));
6127
0
    }
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
0
    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
0
        (void)tsip_write1(session, "\x21", 1);
6136
0
        session->driver.tsip.last_41 = now;
6137
0
    }
6138
6139
0
    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
0
        (void)tsip_write1(session, "\x24", 1);
6145
0
        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
0
    }
6155
6156
0
    if (1 > session->driver.tsip.superpkt &&
6157
0
        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
0
        (void)tsip_write1(session, "\x28", 1);
6168
0
        session->driver.tsip.last_48 = now;
6169
0
    }
6170
6171
0
    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
0
        (void)tsip_write1(session, "\x3c\x00", 2);
6178
0
        session->driver.tsip.last_5c = now;
6179
0
    }
6180
6181
0
    if (5 < llabs(now - session->driver.tsip.last_46)) {
6182
        /* Request Health of Receiver
6183
         * Returns 0x46 and 0x4b. */
6184
0
        (void)tsip_write1(session, "\x26", 1);
6185
0
        session->driver.tsip.last_46 = now;
6186
0
    }
6187
0
    if ((0 < session->driver.tsip.req_compact) &&
6188
0
        (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
0
        session->driver.tsip.req_compact = 0;
6195
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
6196
0
                 "TSIP x8f-23: No Compact Super Packet, "
6197
0
                 "try LFwEI (0x8f-20)\n");
6198
6199
        // Request LFwEI Super Packet 0x8f-20, enabled
6200
0
        (void)tsip_write1(session, "\x8e\x20\x01", 3);
6201
0
    }
6202
6203
0
    return mask;
6204
0
}
6205
6206
static void tsip_init_query(struct gps_device_t *session)
6207
0
{
6208
    // Use 0x1C-03 to Request Hardware Version Information (0x1C-83)
6209
0
    (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
0
}
6215
6216
static void tsip_event_hook(struct gps_device_t *session, event_t event)
6217
0
{
6218
0
    GPSD_LOG(LOG_SPIN, &session->context->errout,
6219
0
             "TSIP: event_hook event %d ro %d\n",
6220
0
             event, session->context->readonly);
6221
6222
0
    if (session->context->readonly ||
6223
0
        session->context->passive) {
6224
0
        return;
6225
0
    }
6226
0
    switch (event) {
6227
0
    case EVENT_CONFIGURE:
6228
        // this seems to get called on every packet...
6229
0
        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
0
        }
6234
0
        break;
6235
0
    case EVENT_IDENTIFIED:
6236
0
        FALLTHROUGH
6237
0
    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
0
        (void)tsip_write1(session, "\x1f", 1);
6242
0
        break;
6243
0
    case EVENT_DRIVER_SWITCH:
6244
0
        FALLTHROUGH
6245
0
    case EVENT_TRIGGERMATCH:
6246
0
        FALLTHROUGH
6247
0
    case EVENT_WAKEUP:
6248
0
        FALLTHROUGH
6249
0
    case EVENT_DEACTIVATE:
6250
        // used to revert serial port params here.  No need for that.
6251
0
        FALLTHROUGH
6252
0
    default:
6253
0
        break;
6254
0
    }
6255
0
}
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