Coverage Report

Created: 2026-02-26 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_spartn.c
Line
Count
Source
1
/*****************************************************************************
2
3
This is a stub  decoder for SPARTN Version 2 protocol.
4
5
The protocol does not play nice with other protocols.   Reliable
6
Packet detection is impossible whern miced with other protocols.
7
8
It is disabled by default.
9
10
This file is Copyright by the GPSD project
11
SPDX-License-Identifier: BSD-2-clause
12
13
*****************************************************************************/
14
15
#include "../include/gpsd_config.h"  // must be before all includes
16
17
#include "../include/gpsd.h"
18
#include "../include/bits.h"
19
#include "../include/crc24q.h"       // for crc24q_check()
20
21
0
#define ugrab(width)    (bitcount += width, ubits(buf, \
22
0
                         bitcount - width, width, false))
23
#define sgrab(width)    (bitcount += width, sbits(buf,  \
24
                         bitcount - width, width, false))
25
26
static const struct vlist_t vspartn_crc_type[] = {
27
    {0, "CRC-8-CCITT"},
28
    {1, "CRC-16-CCITT"},
29
    {2, "CRC-24-Radix-64"},
30
    {3, "CRC-32-CCITT"},
31
};
32
33
static const struct vlist_t vspartn_mtype[] = {
34
    {0, "Orbit"},
35
    {1, "HPAC"},
36
    {2, "GAD"},
37
    {3, "BDS"},
38
    {4, "QZSS"},
39
};
40
41
static const struct vlist_t vspartn_mstype[] = {
42
    {0, "GPS"},
43
    {1, "GLO"},
44
    {2, "GAL"},
45
    {3, "BDS"},
46
};
47
48
static const struct vlist_t vspartn_m120stype[] = {
49
    {0,  "In-house"},
50
    {1,  "u-blox"},
51
    {2,  "Swift"},
52
};
53
54
/* stub decoder for SPARTN
55
 *
56
 * Return: void
57
 */
58
gps_mask_t spartn_parse(struct gps_device_t *session)
59
0
{
60
0
    static gps_mask_t mask = ONLINE_SET;
61
0
    const unsigned char *buf =  session->lexer.outbuffer;
62
0
    int bitcount = 0;
63
0
    unsigned preamble;
64
0
    unsigned msg_type, msg_subtype;
65
0
    unsigned pay_length;
66
0
    unsigned eaf;
67
0
    unsigned crc_type;
68
0
    unsigned frame_crc;
69
0
    unsigned time_tag_type;
70
0
    unsigned long time_tag;
71
0
    unsigned sol_ID;
72
0
    unsigned sol_proc_ID;
73
0
    unsigned enc_ID = 0;
74
0
    unsigned enc_seq_num = 0;
75
0
    unsigned ai = 0;
76
0
    unsigned eal = 0;
77
0
    unsigned pay_offset;        // offset of payload
78
79
0
    preamble = ugrab(8);
80
0
    if (0x73 != preamble) {
81
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
82
0
                 "SPARTN: Invalid preamble x%x, s/b 0x73\n", preamble);
83
0
        return mask;
84
0
    }
85
0
    msg_type = ugrab(7);
86
0
    pay_length = ugrab(10);
87
0
    eaf = ugrab(1);
88
0
    crc_type = ugrab(2);
89
0
    frame_crc = ugrab(4);
90
0
    msg_subtype = ugrab(4);
91
0
    time_tag_type = ugrab(1);
92
0
    if (0 == time_tag_type) {
93
0
        time_tag = ugrab(16);
94
0
    } else {
95
0
        time_tag = ugrab(32);
96
0
    }
97
0
    sol_ID = ugrab(7);
98
0
    sol_proc_ID = ugrab(4);
99
0
    if (1 == eaf) {
100
0
        enc_ID = ugrab(4);
101
0
        enc_seq_num = ugrab(6);
102
0
        ai = ugrab(3);
103
0
        eal = ugrab(3);
104
0
    }
105
    // payload follows.
106
0
    pay_offset = bitcount / 8;  // should be even bytes Prolly 13 or 15.
107
108
    // assume, for now, no Embedded Auth data
109
110
    // 1 to 4 CRC bytes, usually 3
111
    //  CRC is all bytes after the leader 's'.
112
0
    if (2 != crc_type) {
113
        // we only know crc-24-radix64
114
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
115
0
                 "SPARTN: unsupported CRC  type %u\n", crc_type);
116
0
    } else if (!crc24q_check(&session->lexer.outbuffer[1],
117
0
                       pay_offset + pay_length + 3)) {
118
0
        GPSD_LOG(LOG_WARN, &session->context->errout,
119
0
                 "SPARTN: crc24 fail %x vs %02x %02x %02x \n "
120
0
                 "SPARTN: pay_offset %x pay-length %02x\n",
121
0
                 crc24q_hash(&session->lexer.outbuffer[1],
122
0
                             pay_offset + pay_length + 3),
123
0
                 session->lexer.outbuffer[pay_offset + pay_length + 1],
124
0
                 session->lexer.outbuffer[pay_offset + pay_length + 2],
125
0
                 session->lexer.outbuffer[pay_offset + pay_length + 3],
126
0
                 pay_offset, pay_length);
127
0
    }
128
129
0
    GPSD_LOG(LOG_PROG, &session->context->errout,
130
0
             "SPARTN: mtype %u msubtype %u len %u eaf %u crct %u fcrc %u "
131
0
             "tt %u tt %llu sol_ID %u, sol_proc_ID %u\n",
132
0
             msg_type, msg_subtype, pay_length, eaf, crc_type, frame_crc,
133
0
             time_tag_type, (unsigned long long)time_tag, sol_ID, sol_proc_ID);
134
135
0
    if (LOG_IO <= session->context->errout.debug) {
136
0
        const char *msg_subtype_s;
137
138
0
        msg_subtype_s = "TBD";
139
0
        switch (msg_type) {
140
0
        case 0:
141
0
            FALLTHROUGH
142
0
        case 1:
143
0
            msg_subtype_s = val2str(msg_subtype, vspartn_mstype);
144
0
            break;
145
0
        case 2:
146
            // GAD
147
0
            if (0 == msg_subtype) {
148
0
                msg_subtype_s = "GAD";
149
0
            }
150
0
            break;
151
0
        case 3:
152
            // BPAC
153
0
            if (0 == msg_subtype) {
154
0
                msg_subtype_s = "BPAC Polynomial";
155
0
            }
156
0
            break;
157
0
        case 120:
158
            // Prorietary
159
0
            msg_subtype_s = val2str(msg_subtype, vspartn_m120stype);
160
0
            break;
161
0
        default:
162
0
            break;
163
0
        }
164
165
0
        GPSD_LOG(LOG_IO, &session->context->errout,
166
0
                 "SPARTN: mtype %s msubtype %s crct %s\n",
167
0
                 val2str(msg_type, vspartn_mtype),
168
0
                 msg_subtype_s,
169
0
                 val2str(crc_type, vspartn_crc_type));
170
0
    }
171
172
0
    if (1 == eaf) {
173
0
        GPSD_LOG(LOG_PROG, &session->context->errout,
174
0
                 "SPARTN: enc_ID %u enc_seq_num %u ai %u eal %u\n",
175
0
                 enc_ID, enc_seq_num, ai, eal);
176
0
    }
177
178
0
    mask |= SPARTN_SET;
179
0
    return mask;
180
0
}
181
182
// vim: set expandtab shiftwidth=4