Coverage Report

Created: 2026-10-17 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_ais.c
Line
Count
Source
1
/*
2
 * Driver for AIS messages.
3
 *
4
 * See the file AIVDM.txt on the GPSD website for documentation and references.
5
 * AIVDM de-armoring is handled elsewhere; this is the binary-packet driver.
6
 *
7
 * Code for message types 1-15, 18-21, and 24 has been tested against
8
 * live data with known-good decodings. Code for message types 16-17,
9
 * 22-23, and 25-27 has not.
10
 * For the special IMO messages (types 6 and 8), only the following have been
11
 * tested against known-good decodings:
12
 *  - IMO236 met/hydro message: Type=8, DAC=1, FI=11
13
 *  - IMO289 met/hydro message: Type=8, DAC=1, FI=31
14
 *
15
 * This file is Copyright 2010 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 <ctype.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "../include/gpsd.h"
26
#include "../include/bits.h"
27
28
/*
29
 * Parse the data from the device
30
 */
31
32
// beginning at bitvec bit start, unpack count sixbit characters
33
static void from_sixbit_untrimmed(const struct gpsd_errout_t *errout,
34
                                  const unsigned char *bitvec,
35
                                  const size_t bitlen,
36
                                  const unsigned start,
37
                                  unsigned count, char *to,
38
                                  const size_t to_sz)
39
9.81k
{
40
9.81k
    const char sixchr[65] =
41
9.81k
        "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?";
42
9.81k
    unsigned i;
43
44
9.81k
    if (bitlen <= start) {
45
79
        GPSD_LOG(LOG_WARN, errout, "AIVDM bitlen %zu <=  start %u\n",
46
79
                 bitlen, start);
47
79
        to[0] = '\0';
48
79
        return;
49
79
    }
50
9.73k
    if (to_sz <= count) {
51
0
        count = to_sz - 1;
52
0
    }
53
54
    // six-bit to ASCII
55
79.1k
    for (i = 0; i < count; i++) {
56
74.0k
        char newchar = sixchr[ubits(bitvec, start + 6 * i, 6U, false)];
57
58
74.0k
        if ('@' == newchar) {
59
4.66k
            break;
60
4.66k
        }
61
69.4k
        to[i] = newchar;
62
69.4k
    }
63
9.73k
    to[i] = '\0';
64
9.73k
}
65
66
// trim spaces on right end
67
static void trim_spaces_on_right_end(char *to, size_t max)
68
9.81k
{
69
9.81k
    long long i;
70
71
    // pacify Coverity 498043, overflow
72
15.4k
    for (i = strnlen(to, max) - 1; i >= 0; i--) {
73
13.3k
        if (' ' == to[i] ||
74
7.67k
            '@' == to[i]) {
75
5.65k
            to[i] = '\0';
76
7.67k
        } else {
77
7.67k
            break;
78
7.67k
        }
79
13.3k
    }
80
9.81k
}
81
82
/* beginning at bitvec bit start, unpack count sixbit characters
83
 * and remove trailing spaces */
84
static void from_sixbit(const struct gpsd_errout_t *errout,
85
                        const unsigned char *bitvec, const size_t bitlen,
86
                        const unsigned start,
87
                        const unsigned count, char *to, const size_t to_sz)
88
9.45k
{
89
9.45k
    from_sixbit_untrimmed(errout, bitvec, bitlen, start, count, to, to_sz);
90
9.45k
    trim_spaces_on_right_end(to, count);
91
9.45k
}
92
93
137k
#define UBITS(s, l)     ubits(bits, s, l, false)
94
11.2k
#define SBITS(s, l)     sbits(bits, s, l, false)
95
#define UCHARS(start, to)  \
96
9.01k
        from_sixbit(errout, bits, bitlen, start, sizeof(to) - 1, \
97
9.01k
                    to, sizeof(to))
98
99
#define ENDCHARS(start, to, to_sz)  \
100
436
        from_sixbit(errout, bits, bitlen, start, (bitlen - start) / 6, \
101
436
                    to, to_sz)
102
103
/* decode an AIS binary packet
104
 *
105
 * Return: True on success
106
 *         False on failure
107
 */
108
bool ais_binary_decode(const struct gpsd_errout_t *errout,
109
                       struct ais_t *ais,
110
                       const unsigned char *bits, size_t bitlen,
111
                       struct ais_type24_queue_t *type24_queue)
112
16.4k
{
113
16.4k
    unsigned int u;
114
16.4k
    size_t bytelen = BITS_TO_BYTES(bitlen);
115
116
16.4k
    ais->type = UBITS(0, 6);
117
16.4k
    ais->repeat = UBITS(6, 2);
118
16.4k
    ais->mmsi = UBITS(8, 30);
119
16.4k
    GPSD_LOG(LOG_INF, errout,
120
16.4k
             "AIVDM message type %d, MMSI %09d bitlen %zu bytelen %zu\n",
121
16.4k
             ais->type, ais->mmsi, bitlen, bytelen);
122
123
16.4k
#define PERMISSIVE_LENGTH_CHECK(correct) \
124
16.4k
        if (bitlen < correct) { \
125
667
            GPSD_LOG(LOG_ERROR, errout, \
126
667
                     "AIVDM message type %d size < %d bits (%zd).\n",   \
127
667
                     ais->type, correct, bitlen);                       \
128
667
            return false; \
129
1.68k
        } else if (bitlen > correct) { \
130
695
            GPSD_LOG(LOG_WARN, errout, \
131
695
                     "AIVDM message type %d size > %d bits (%zd).\n",   \
132
695
                     ais->type, correct, bitlen);                       \
133
695
        }
134
135
16.4k
#define RANGE_CHECK(min, max) \
136
16.4k
        if (bitlen < min || \
137
9.97k
            bitlen > max) { \
138
2.25k
            GPSD_LOG(LOG_ERROR, errout, \
139
2.25k
                     "AIVDM message type %d size is out of range: " \
140
2.25k
                     " %u <= (%zu) <= %u.\n", \
141
2.25k
                     ais->type, min, bitlen, max);  \
142
2.25k
            return false; \
143
2.25k
        }
144
145
16.4k
#define RANGE_CHECK6(min, max) \
146
16.4k
        if (bitlen < min || \
147
3.28k
            bitlen > max) { \
148
1.28k
            GPSD_LOG(LOG_ERROR, errout, \
149
1.28k
                     "AIVDM message type %d dac %u fid %u size is out of " \
150
1.28k
                     "range %u <= (%zu) <= %u.\n", \
151
1.28k
                     ais->type, ais->type6.dac, ais->type6.fid, \
152
1.28k
                     min, bitlen, max);  \
153
1.28k
            return false; \
154
1.28k
        }
155
156
16.4k
#define RANGE_CHECK8(min, max) \
157
16.4k
        if (bitlen < min || \
158
6.72k
            bitlen > max) { \
159
1.56k
            GPSD_LOG(LOG_ERROR, errout, \
160
1.56k
                     "AIVDM message type %d dac %u fid %u size is out of " \
161
1.56k
                     "range %u <= (%zu) <= %u.\n", \
162
1.56k
                     ais->type, ais->type8.dac, ais->type8.fid, \
163
1.56k
                     min, bitlen, max);  \
164
1.56k
            return false; \
165
1.56k
        }
166
167
    /*
168
     * Something about the shape of this switch statement confuses
169
     * GNU indent so badly that there is no point in trying to be
170
     * finer-grained than leaving it all alone.
171
     */
172
173
// calculate offset into array
174
16.4k
#define OFF(index) (ARRAY_BASE + (ELEMENT_SIZE * index))
175
176
16.4k
    switch (ais->type) {
177
150
    case 1:  // Position Report
178
150
        FALLTHROUGH
179
282
    case 2:
180
282
        FALLTHROUGH
181
414
    case 3:
182
        // per https://www.navcen.uscg.gov/ais-class-a-reports
183
        // In 2023, most of our samples are 168, but some are 163 and 204.
184
414
        RANGE_CHECK(163, 204)
185
140
        ais->type1.status = UBITS(38, 4);
186
140
        ais->type1.turn = SBITS(42, 8);
187
140
        ais->type1.speed = UBITS(50, 10);
188
140
        ais->type1.accuracy = UBITS(60, 1) != 0;
189
140
        ais->type1.lon = SBITS(61, 28);
190
140
        ais->type1.lat = SBITS(89, 27);
191
140
        ais->type1.course = UBITS(116, 12);
192
140
        ais->type1.heading = UBITS(128, 9);
193
140
        ais->type1.second = UBITS(137, 6);
194
140
        ais->type1.maneuver = UBITS(143, 2);
195
        // ais->type1.spare     = UBITS(145, 3);
196
140
        ais->type1.raim = UBITS(148, 1) != 0;
197
140
        if (bitlen >= 168) {
198
73
            ais->type1.radio = UBITS(149, 19);
199
73
        } else {
200
            // less than 168, as of 2023 we have no examples of this.
201
67
            ais->type1.radio = UBITS(149, bitlen - 149);
202
67
        }
203
140
        break;
204
149
    case 4:  // Base Station Report
205
149
        FALLTHROUGH
206
274
    case 11: // UTC/Date Response
207
274
        PERMISSIVE_LENGTH_CHECK(168)
208
134
        ais->type4.year = UBITS(38, 14);
209
134
        ais->type4.month = UBITS(52, 4);
210
134
        ais->type4.day = UBITS(56, 5);
211
134
        ais->type4.hour = UBITS(61, 5);
212
134
        ais->type4.minute = UBITS(66, 6);
213
134
        ais->type4.second = UBITS(72, 6);
214
134
        ais->type4.accuracy = UBITS(78, 1) != 0;
215
134
        ais->type4.lon = SBITS(79, 28);
216
134
        ais->type4.lat = SBITS(107, 27);
217
134
        ais->type4.epfd = UBITS(134, 4);
218
        // ais->type4.spare      = UBITS(138, 10);
219
134
        ais->type4.raim = UBITS(148, 1) != 0;
220
134
        ais->type4.radio = UBITS(149, 19);
221
134
        break;
222
292
    case 5:  // Ship static and voyage related data
223
292
        if (424 != bitlen) {
224
226
            GPSD_LOG(LOG_WARN, errout,
225
226
                     "AIVDM message type 5 size not 424 bits (%zd).\n",
226
226
                     bitlen);
227
            /*
228
             * For unknown reasons, a lot of transmitters in the wild ship
229
             * with a length of 420 or 422.  This is a recoverable error.
230
             */
231
226
            if (420 > bitlen) {
232
93
                return false;
233
93
            }
234
226
        }
235
199
        ais->type5.ais_version = UBITS(38, 2);
236
199
        ais->type5.imo = UBITS(40, 30);
237
199
        UCHARS(70, ais->type5.callsign);
238
199
        UCHARS(112, ais->type5.shipname);
239
199
        ais->type5.shiptype = UBITS(232, 8);
240
199
        ais->type5.to_bow = UBITS(240, 9);
241
199
        ais->type5.to_stern = UBITS(249, 9);
242
199
        ais->type5.to_port = UBITS(258, 6);
243
199
        ais->type5.to_starboard = UBITS(264, 6);
244
199
        ais->type5.epfd = UBITS(270, 4);
245
199
        ais->type5.month = UBITS(274, 4);
246
199
        ais->type5.day = UBITS(278, 5);
247
199
        ais->type5.hour = UBITS(283, 5);
248
199
        ais->type5.minute = UBITS(288, 6);
249
199
        ais->type5.draught = UBITS(294, 8);
250
199
        UCHARS(302, ais->type5.destination);
251
199
        if (423 <= bitlen) {
252
113
            ais->type5.dte = UBITS(422, 1);
253
113
        }
254
        // ais->type5.spare        = UBITS(423, 1);
255
199
        break;
256
3.63k
    case 6:  // Addressed Binary Message
257
3.63k
        RANGE_CHECK(88, 1008);
258
3.45k
        ais->type6.seqno = UBITS(38, 2);
259
3.45k
        ais->type6.dest_mmsi = UBITS(40, 30);
260
3.45k
        ais->type6.retransmit = UBITS(70, 1) != 0;
261
        // ais->type6.spare        = UBITS(71, 1);
262
3.45k
        ais->type6.dac = UBITS(72, 10);
263
3.45k
        ais->type6.fid = UBITS(82, 6);
264
3.45k
        ais->type6.bitcount = bitlen - 88;
265
        // not strictly required - helps stability in testing
266
3.45k
        (void)memset(ais->type6.bitdata, '\0', sizeof(ais->type6.bitdata));
267
3.45k
        ais->type6.structured = false;
268
        // Inland AIS
269
3.45k
        GPSD_LOG(LOG_PROG, errout,
270
3.45k
                 "AIVDM: type 6 dac %u fid %u bitlen %zu\n",
271
3.45k
                 ais->type6.dac, ais->type6.fid, bitlen);
272
3.45k
        switch (ais->type6.dac) {
273
2.22k
        case 1:
274
            // International
275
2.22k
            switch (ais->type6.fid) {
276
334
            case 12:  // IMO236 - Dangerous cargo indication
277
334
                RANGE_CHECK6(144, 360);
278
199
                UCHARS(88, ais->type6.dac1fid12.lastport);
279
199
                ais->type6.dac1fid12.lmonth = UBITS(118, 4);
280
199
                ais->type6.dac1fid12.lday = UBITS(122, 5);
281
199
                ais->type6.dac1fid12.lhour = UBITS(127, 5);
282
199
                ais->type6.dac1fid12.lminute = UBITS(132, 6);
283
199
                if (144 < bitlen) {
284
133
                    RANGE_CHECK6(360, 360);
285
66
                    UCHARS(138, ais->type6.dac1fid12.nextport);
286
66
                    ais->type6.dac1fid12.nmonth = UBITS(168, 4);
287
66
                    ais->type6.dac1fid12.nday = UBITS(172, 5);
288
66
                    ais->type6.dac1fid12.nhour = UBITS(177, 5);
289
66
                    ais->type6.dac1fid12.nminute = UBITS(182, 6);
290
66
                    UCHARS(188, ais->type6.dac1fid12.dangerous);
291
66
                    UCHARS(308, ais->type6.dac1fid12.imdcat);
292
66
                    ais->type6.dac1fid12.unid = UBITS(332, 13);
293
66
                    ais->type6.dac1fid12.amount = UBITS(345, 10);
294
66
                    ais->type6.dac1fid12.unit = UBITS(355, 2);
295
                    // skip 3 bits
296
66
                }
297
132
                ais->type6.structured = true;
298
132
                break;
299
234
            case 14:
300
                // IMO236 - Tidal Window
301
                // similar to fid 32.
302
234
                RANGE_CHECK6(87, 1008);
303
234
                ais->type6.dac1fid32.month = UBITS(88, 4);
304
234
                ais->type6.dac1fid32.day = UBITS(92, 5);
305
603
#define ARRAY_BASE 97
306
603
#define ELEMENT_SIZE 93
307
603
                for (u = 0; ; u++) {
308
603
                    size_t off = OFF(u);
309
603
                    struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u];
310
603
                    if (off >= bitlen ||
311
437
                        ROWS(ais->type6.dac1fid32.tidals) <= u) {
312
234
                        break;
313
234
                    }
314
369
                    tp->lat = SBITS(off + 0, 27);
315
369
                    tp->lon = SBITS(off + 27, 28);
316
369
                    tp->from_hour = UBITS(off + 55, 5);
317
369
                    tp->from_min = UBITS(off + 60, 6);
318
369
                    tp->to_hour = UBITS(off + 66, 5);
319
369
                    tp->to_min = UBITS(off + 71, 6);
320
369
                    tp->cdir = UBITS(off + 77, 9);
321
369
                    tp->cspeed = UBITS(off + 86, 7);
322
369
                }
323
234
                ais->type6.dac1fid32.ntidals = u;
324
234
#undef ARRAY_BASE
325
234
#undef ELEMENT_SIZE
326
234
                ais->type6.structured = true;
327
234
                break;
328
67
            case 15:
329
                // IMO236 - Extended Ship Static and Voyage Related Data
330
67
                RANGE_CHECK6(67, 1008);
331
67
                ais->type6.dac1fid15.airdraught = UBITS(56, 11);
332
67
                ais->type6.structured = true;
333
67
                break;
334
202
            case 16:
335
                // IMO236 - Number of persons on board
336
202
                RANGE_CHECK6(236, 289);
337
66
                if (136 == ais->type6.bitcount) {
338
0
                    ais->type6.dac1fid16.persons = UBITS(88, 13);  // 289
339
66
                } else {
340
66
                    ais->type6.dac1fid16.persons = UBITS(55, 13);  // 236
341
66
                }
342
66
                ais->type6.structured = true;
343
66
                break;
344
205
            case 18:
345
                // IMO289 - Clearance time to enter port
346
                // sometimes bitlen == 168!
347
205
                RANGE_CHECK6(168, 1008);
348
138
                ais->type6.dac1fid18.linkage = UBITS(88, 10);
349
138
                ais->type6.dac1fid18.month = UBITS(98, 4);
350
138
                ais->type6.dac1fid18.day = UBITS(102, 5);
351
138
                ais->type6.dac1fid18.hour = UBITS(107, 5);
352
138
                ais->type6.dac1fid18.minute = UBITS(112, 6);
353
138
                UCHARS(118, ais->type6.dac1fid18.portname);
354
138
                if (318 <= bitlen) {
355
66
                    UCHARS(238, ais->type6.dac1fid18.destination);
356
66
                    ais->type6.dac1fid18.lon = SBITS(268, 25);
357
66
                    ais->type6.dac1fid18.lat = SBITS(293, 24);
358
                    // skip 43 bits
359
66
                }
360
138
                ais->type6.structured = true;
361
138
                break;
362
142
            case 20:  // IMO289 - Berthing data - addressed
363
142
                RANGE_CHECK6(360, 1008);
364
66
                ais->type6.dac1fid20.linkage = UBITS(88, 10);
365
66
                ais->type6.dac1fid20.berth_length = UBITS(98, 9);
366
66
                ais->type6.dac1fid20.berth_depth = UBITS(107, 8);
367
66
                ais->type6.dac1fid20.position = UBITS(115, 3);
368
66
                ais->type6.dac1fid20.month = UBITS(118, 4);
369
66
                ais->type6.dac1fid20.day = UBITS(122, 5);
370
66
                ais->type6.dac1fid20.hour = UBITS(127, 5);
371
66
                ais->type6.dac1fid20.minute = UBITS(132, 6);
372
66
                ais->type6.dac1fid20.availability = UBITS(138, 1);
373
66
                ais->type6.dac1fid20.agent = UBITS(139, 2);
374
66
                ais->type6.dac1fid20.fuel = UBITS(141, 2);
375
66
                ais->type6.dac1fid20.chandler = UBITS(143, 2);
376
66
                ais->type6.dac1fid20.stevedore = UBITS(145, 2);
377
66
                ais->type6.dac1fid20.electrical = UBITS(147, 2);
378
66
                ais->type6.dac1fid20.water = UBITS(149, 2);
379
66
                ais->type6.dac1fid20.customs = UBITS(151, 2);
380
66
                ais->type6.dac1fid20.cartage = UBITS(153, 2);
381
66
                ais->type6.dac1fid20.crane = UBITS(155, 2);
382
66
                ais->type6.dac1fid20.lift = UBITS(157, 2);
383
66
                ais->type6.dac1fid20.medical = UBITS(159, 2);
384
66
                ais->type6.dac1fid20.navrepair = UBITS(161, 2);
385
66
                ais->type6.dac1fid20.provisions = UBITS(163, 2);
386
66
                ais->type6.dac1fid20.shiprepair = UBITS(165, 2);
387
66
                ais->type6.dac1fid20.surveyor = UBITS(167, 2);
388
66
                ais->type6.dac1fid20.steam = UBITS(169, 2);
389
66
                ais->type6.dac1fid20.tugs = UBITS(171, 2);
390
66
                ais->type6.dac1fid20.solidwaste = UBITS(173, 2);
391
66
                ais->type6.dac1fid20.liquidwaste = UBITS(175, 2);
392
66
                ais->type6.dac1fid20.hazardouswaste = UBITS(177, 2);
393
66
                ais->type6.dac1fid20.ballast = UBITS(179, 2);
394
66
                ais->type6.dac1fid20.additional = UBITS(181, 2);
395
66
                ais->type6.dac1fid20.regional1 = UBITS(183, 2);
396
66
                ais->type6.dac1fid20.regional2 = UBITS(185, 2);
397
66
                ais->type6.dac1fid20.future1 = UBITS(187, 2);
398
66
                ais->type6.dac1fid20.future2 = UBITS(189, 2);
399
66
                UCHARS(191, ais->type6.dac1fid20.berth_name);
400
66
                ais->type6.dac1fid20.berth_lon = SBITS(311, 25);
401
66
                ais->type6.dac1fid20.berth_lat = SBITS(336, 24);
402
66
                ais->type6.structured = true;
403
66
                break;
404
0
            case 23:  // IMO289 - Area notice - addressed
405
0
                break;
406
218
            case 25:  // IMO289 - Dangerous cargo indication
407
546
#define ARRAY_BASE 100
408
546
#define ELEMENT_SIZE 17
409
218
                RANGE_CHECK6(100, 1008);
410
152
                ais->type6.dac1fid25.unit = UBITS(88, 2);
411
152
                ais->type6.dac1fid25.amount = UBITS(90, 10);
412
546
                for (u = 0; ; u++) {
413
546
                    size_t off = OFF(u);
414
546
                    if (off >= bitlen ||
415
397
                        ROWS(ais->type6.dac1fid25.cargos) <= u) {
416
152
                        break;
417
152
                    }
418
394
                    ais->type6.dac1fid25.cargos[u].code = UBITS(off, 4);
419
394
                    ais->type6.dac1fid25.cargos[u].subtype =
420
394
                        UBITS(off + 4, 13);
421
394
                }
422
152
                ais->type6.dac1fid25.ncargos = u;
423
152
                ais->type6.structured = true;
424
152
#undef ARRAY_BASE
425
152
#undef ELEMENT_SIZE
426
152
                break;
427
312
            case 28:  // IMO289 - Route info - addressed
428
312
                RANGE_CHECK6(149, 1008);
429
244
                ais->type6.dac1fid28.linkage = UBITS(88, 10);
430
244
                ais->type6.dac1fid28.sender = UBITS(98, 3);
431
244
                ais->type6.dac1fid28.rtype = UBITS(101, 5);
432
244
                ais->type6.dac1fid28.month = UBITS(106, 4);
433
244
                ais->type6.dac1fid28.day = UBITS(110, 5);
434
244
                ais->type6.dac1fid28.hour = UBITS(115, 5);
435
244
                ais->type6.dac1fid28.minute = UBITS(120, 6);
436
244
                ais->type6.dac1fid28.duration = UBITS(126, 18);
437
244
                ais->type6.dac1fid28.waycount = UBITS(144, 5);
438
740
#define ARRAY_BASE 149
439
740
#define ELEMENT_SIZE 55
440
740
                for (u = 0; ; u++) {
441
740
                    size_t off = OFF(u);
442
740
                    if (off >= bitlen ||
443
563
                        ROWS(ais->type6.dac1fid28.waypoints) <= u ||
444
563
                        u >= ais->type6.dac1fid28.waycount) {
445
244
                        break;
446
244
                    }
447
496
                    ais->type6.dac1fid28.waypoints[u].lon = SBITS(off + 0, 28);
448
496
                    ais->type6.dac1fid28.waypoints[u].lat = SBITS(off + 28, 27);
449
496
                }
450
244
#undef ARRAY_BASE
451
244
#undef ELEMENT_SIZE
452
244
                ais->type6.structured = true;
453
244
                break;
454
135
            case 30:  // IMO289 - Text description - addressed
455
135
                RANGE_CHECK6(98, 1008);
456
69
                ais->type6.dac1fid30.linkage = UBITS(88, 10);
457
69
                ENDCHARS(98, ais->type6.dac1fid30.text,
458
69
                         sizeof(ais->type6.dac1fid30.text));
459
69
                ais->type6.structured = true;
460
69
                break;
461
304
            case 32:  // IMO289 - Tidal Window
462
                // similar to fid 14.
463
304
                RANGE_CHECK6(97, 1008);
464
238
                ais->type6.dac1fid32.month = UBITS(88, 4);
465
238
                ais->type6.dac1fid32.day = UBITS(92, 5);
466
617
#define ARRAY_BASE 97
467
617
#define ELEMENT_SIZE 88
468
617
                for (u = 0; ; u++) {
469
617
                    size_t off = OFF(u);
470
617
                    if (off >= bitlen ||
471
434
                        ROWS(ais->type6.dac1fid32.tidals) <= u) {
472
238
                        break;
473
238
                    }
474
379
                    struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u];
475
476
379
                    tp->lon = SBITS(off + 0, 25);
477
379
                    tp->lat = SBITS(off + 25, 24);
478
379
                    tp->from_hour = UBITS(off + 49, 5);
479
379
                    tp->from_min = UBITS(off + 54, 6);
480
379
                    tp->to_hour = UBITS(off + 60, 5);
481
379
                    tp->to_min = UBITS(off + 65, 6);
482
379
                    tp->cdir = UBITS(off + 71, 9);
483
379
                    tp->cspeed = UBITS(off + 80, 8);
484
379
                }
485
238
                ais->type6.dac1fid32.ntidals = u;
486
238
#undef ARRAY_BASE
487
238
#undef ELEMENT_SIZE
488
238
                ais->type6.structured = true;
489
238
                break;
490
2.22k
            }
491
1.47k
            break;
492
1.47k
        case  200:
493
818
            switch (ais->type6.fid) {
494
201
            case 21:  // ETA at lock/bridge/terminal
495
201
                RANGE_CHECK6(248, 248);
496
66
                UCHARS(88, ais->type6.dac200fid21.country);
497
66
                UCHARS(100, ais->type6.dac200fid21.locode);
498
66
                UCHARS(118, ais->type6.dac200fid21.section);
499
66
                UCHARS(148, ais->type6.dac200fid21.terminal);
500
66
                UCHARS(178, ais->type6.dac200fid21.hectometre);
501
66
                ais->type6.dac200fid21.month = UBITS(208, 4);
502
66
                ais->type6.dac200fid21.day = UBITS(212, 5);
503
66
                ais->type6.dac200fid21.hour = UBITS(217, 5);
504
66
                ais->type6.dac200fid21.minute = UBITS(222, 6);
505
66
                ais->type6.dac200fid21.tugs = UBITS(228, 3);
506
66
                ais->type6.dac200fid21.airdraught = UBITS(231, 12);
507
                // skip 5 bits
508
66
                ais->type6.structured = true;
509
66
                break;
510
353
            case 22:  // RTA at lock/bridge/terminal
511
353
                RANGE_CHECK6(232, 232);
512
219
                UCHARS(88, ais->type6.dac200fid22.country);
513
219
                UCHARS(100, ais->type6.dac200fid22.locode);
514
219
                UCHARS(118, ais->type6.dac200fid22.section);
515
219
                UCHARS(148, ais->type6.dac200fid22.terminal);
516
219
                UCHARS(178, ais->type6.dac200fid22.hectometre);
517
219
                ais->type6.dac200fid22.month = UBITS(208, 4);
518
219
                ais->type6.dac200fid22.day = UBITS(212, 5);
519
219
                ais->type6.dac200fid22.hour = UBITS(217, 5);
520
219
                ais->type6.dac200fid22.minute = UBITS(222, 6);
521
219
                ais->type6.dac200fid22.status = UBITS(228, 2);
522
                // skip 2 bits
523
219
                ais->type6.structured = true;
524
219
                break;
525
198
            case 55:
526
                // Number of Persons On Board
527
198
                RANGE_CHECK6(168, 168);
528
66
                ais->type6.dac200fid55.crew = UBITS(88, 8);
529
66
                ais->type6.dac200fid55.passengers = UBITS(96, 13);
530
66
                ais->type6.dac200fid55.personnel = UBITS(109, 8);
531
                // skip 51 bits
532
66
                ais->type6.structured = true;
533
66
                break;
534
818
            }
535
417
            break;
536
417
        case 235:
537
66
            FALLTHROUGH
538
319
        case 250:
539
            // UK and Republic Of Ireland
540
319
            switch (ais->type6.fid) {
541
247
            case 10:  // GLA - AtoN monitoring data
542
247
                RANGE_CHECK6(136, 136);
543
108
                ais->type6.dac235fid10.ana_int = UBITS(88, 10);
544
108
                ais->type6.dac235fid10.ana_ext1 = UBITS(98, 10);
545
108
                ais->type6.dac235fid10.ana_ext2 = UBITS(108, 10);
546
108
                ais->type6.dac235fid10.racon = UBITS(118, 2);
547
108
                ais->type6.dac235fid10.light = UBITS(120, 2);
548
108
                ais->type6.dac235fid10.alarm = UBITS(122, 1);
549
108
                ais->type6.dac235fid10.stat_ext = UBITS(123, 8);
550
108
                ais->type6.dac235fid10.off_pos = UBITS(131, 1);
551
                // skip 4 bits
552
108
                ais->type6.structured = true;
553
108
                break;
554
319
            }
555
180
            break;
556
180
        default:
557
95
            break;
558
3.45k
        }
559
2.16k
        if (!ais->type6.structured) {
560
300
            u = BITS_TO_BYTES(ais->type6.bitcount);
561
300
            if (sizeof(ais->type6.bitdata) < u) {
562
0
                u = sizeof(ais->type6.bitdata);
563
0
                ais->type6.bitcount = u * 8;
564
0
            }
565
300
            (void)memcpy(ais->type6.bitdata, bits + (88 / CHAR_BIT), u);
566
300
            GPSD_LOG(LOG_WARN, errout,
567
300
                     "AIVDM: type 6 unknown dac %u fid %u bitlen %zu\n",
568
300
                     ais->type6.dac, ais->type6.fid, bitlen);
569
300
        }
570
2.16k
        break;
571
296
    case 7:  // Binary acknowledge
572
296
        FALLTHROUGH
573
525
    case 13: // Safety Related Acknowledge
574
525
    {
575
525
        unsigned int mmsi[4];
576
525
        unsigned seqno[4];
577
525
        RANGE_CHECK(72, 168);
578
1.22k
#define ARRAY_BASE 40
579
1.22k
#define ELEMENT_SIZE 32
580
1.53k
        for (u = 0; u < ROWS(mmsi); u++) {
581
1.22k
            size_t off = OFF(u);
582
583
1.22k
            if (off < bitlen) {
584
821
                mmsi[u] = UBITS(off, 30);
585
821
                seqno[u] = UBITS(off + 32, 2);
586
821
            } else {
587
407
                mmsi[u] = 0;
588
407
                seqno[u] = 0;
589
407
            }
590
1.22k
        }
591
307
#undef ARRAY_BASE
592
307
#undef ELEMENT_SIZE
593
307
        ais->type7.mmsi1 = mmsi[0];
594
307
        ais->type7.seqno1 = seqno[0];
595
307
        ais->type7.mmsi2 = mmsi[1];
596
307
        ais->type7.seqno2 = seqno[1];
597
307
        ais->type7.mmsi3 = mmsi[2];
598
307
        ais->type7.seqno3 = seqno[2];
599
307
        ais->type7.mmsi4 = mmsi[3];
600
307
        ais->type7.seqno4 = seqno[3];
601
307
        break;
602
525
    }
603
3.54k
    case 8:  // Binary Broadcast Message
604
3.54k
        RANGE_CHECK8(56, 1008);
605
        // ais->type8.spare        = UBITS(38, 2);
606
3.40k
        ais->type8.dac = UBITS(40, 10);
607
3.40k
        ais->type8.fid = UBITS(50, 6);
608
3.40k
        ais->type8.bitcount = bitlen - 56;
609
        // not strictly required - helps stability in testing
610
3.40k
        (void)memset(ais->type8.bitdata, '\0', sizeof(ais->type8.bitdata));
611
3.40k
        ais->type8.structured = false;
612
3.40k
        GPSD_LOG(LOG_PROG, errout, "AIVDM: type 8 dac %u fid %u bitlen %zu\n",
613
3.40k
                 ais->type8.dac, ais->type8.fid, bitlen);
614
3.40k
        switch (ais->type8.dac) {
615
2.37k
        case 1:
616
            // International
617
2.37k
            switch (ais->type8.fid) {
618
202
            case 11:  // IMO236 - Meteorological/Hydrological data
619
                // layout is almost identical to FID=31 from IMO289
620
                // FIXME: we get length 352??
621
202
                RANGE_CHECK8(346, 352);
622
66
                ais->type8.dac1fid11.lat = SBITS(56, 24);
623
66
                ais->type8.dac1fid11.lon = SBITS(80, 25);
624
66
                ais->type8.dac1fid11.day = UBITS(105, 5);
625
66
                ais->type8.dac1fid11.hour = UBITS(110, 5);
626
66
                ais->type8.dac1fid11.minute = UBITS(115, 6);
627
66
                ais->type8.dac1fid11.wspeed = UBITS(121, 7);
628
66
                ais->type8.dac1fid11.wgust = UBITS(128, 7);
629
66
                ais->type8.dac1fid11.wdir = UBITS(135, 9);
630
66
                ais->type8.dac1fid11.wgustdir = UBITS(144, 9);
631
66
                ais->type8.dac1fid11.airtemp = UBITS(153, 11);
632
66
                ais->type8.dac1fid11.humidity = UBITS(164, 7);
633
66
                ais->type8.dac1fid11.dewpoint = UBITS(171, 10);
634
66
                ais->type8.dac1fid11.pressure = UBITS(181, 9);
635
66
                ais->type8.dac1fid11.pressuretend = UBITS(190, 2);
636
66
                ais->type8.dac1fid11.visibility = UBITS(192, 8);
637
66
                ais->type8.dac1fid11.waterlevel = UBITS(200, 9);
638
66
                ais->type8.dac1fid11.leveltrend = UBITS(209, 2);
639
66
                ais->type8.dac1fid11.cspeed = UBITS(211, 8);
640
66
                ais->type8.dac1fid11.cdir = UBITS(219, 9);
641
66
                ais->type8.dac1fid11.cspeed2 = UBITS(228, 8);
642
66
                ais->type8.dac1fid11.cdir2 = UBITS(236, 9);
643
66
                ais->type8.dac1fid11.cdepth2 = UBITS(245, 5);
644
66
                ais->type8.dac1fid11.cspeed3 = UBITS(250, 8);
645
66
                ais->type8.dac1fid11.cdir3 = UBITS(258, 9);
646
66
                ais->type8.dac1fid11.cdepth3 = UBITS(267, 5);
647
66
                ais->type8.dac1fid11.waveheight = UBITS(272, 8);
648
66
                ais->type8.dac1fid11.waveperiod = UBITS(280, 6);
649
66
                ais->type8.dac1fid11.wavedir = UBITS(286, 9);
650
66
                ais->type8.dac1fid11.swellheight = UBITS(295, 8);
651
66
                ais->type8.dac1fid11.swellperiod = UBITS(303, 6);
652
66
                ais->type8.dac1fid11.swelldir = UBITS(309, 9);
653
66
                ais->type8.dac1fid11.seastate = UBITS(318, 4);
654
66
                ais->type8.dac1fid11.watertemp = UBITS(322, 10);
655
66
                ais->type8.dac1fid11.preciptype = UBITS(332, 3);
656
66
                ais->type8.dac1fid11.salinity = UBITS(335, 9);
657
66
                ais->type8.dac1fid11.ice = UBITS(344, 2);
658
66
                ais->type8.structured = true;
659
66
                break;
660
211
            case 13:  // IMO236 - Fairway closed
661
211
                RANGE_CHECK8(468, 468);
662
66
                UCHARS(56, ais->type8.dac1fid13.reason);
663
66
                UCHARS(176, ais->type8.dac1fid13.closefrom);
664
66
                UCHARS(296, ais->type8.dac1fid13.closeto);
665
66
                ais->type8.dac1fid13.radius = UBITS(416, 10);
666
66
                ais->type8.dac1fid13.extunit = UBITS(426, 2);
667
66
                ais->type8.dac1fid13.fday = UBITS(428, 5);
668
66
                ais->type8.dac1fid13.fmonth = UBITS(433, 4);
669
66
                ais->type8.dac1fid13.fhour = UBITS(437, 5);
670
66
                ais->type8.dac1fid13.fminute = UBITS(442, 6);
671
66
                ais->type8.dac1fid13.tday = UBITS(448, 5);
672
66
                ais->type8.dac1fid13.tmonth = UBITS(453, 4);
673
66
                ais->type8.dac1fid13.thour = UBITS(457, 5);
674
66
                ais->type8.dac1fid13.tminute = UBITS(462, 6);
675
                // skip 4 bits
676
66
                ais->type8.structured = true;
677
66
                break;
678
198
            case 15:  // IMO236 -
679
                      // Extended
680
                      // ship and
681
                      // voyage
682
198
                RANGE_CHECK8(67, 72);
683
66
                ais->type8.dac1fid15.airdraught = UBITS(56, 11);
684
                // skip 5 bits
685
66
                ais->type8.structured = true;
686
66
                break;
687
339
            case 16:
688
                // Number of Persons On Board
689
                // dac 1, fid 18.  bitlen = 776 ???
690
339
                RANGE_CHECK8(72, 776);
691
205
                if (136 == ais->type8.bitcount) {
692
66
                    ais->type8.dac1fid16.persons = UBITS(88, 13);  // 289
693
66
                    ais->type8.structured = true;
694
139
                } else if (72 == ais->type8.bitcount) {
695
66
                    ais->type8.dac1fid16.persons = UBITS(55, 13);  // 236
696
66
                    ais->type8.structured = true;
697
66
                }
698
205
                break;
699
589
            case 17:
700
                // IMO289 - VTS-generated/synthetic targets
701
589
                RANGE_CHECK8(56, 1008);
702
1.74k
#define ARRAY_BASE 56
703
1.74k
#define ELEMENT_SIZE 122
704
1.74k
                for (u = 0; ; u++) {
705
1.74k
                    struct target_t *tp;
706
1.74k
                    size_t off = OFF(u);
707
1.74k
                    if (off >= bitlen ||
708
1.25k
                        ROWS(ais->type8.dac1fid17.targets) <= u) {
709
589
                        break;
710
589
                    }
711
1.15k
                    tp = &ais->type8.dac1fid17.targets[u];
712
1.15k
                    tp->idtype = UBITS(off + 0, 2);
713
1.15k
                    switch (tp->idtype) {
714
176
                    case DAC1FID17_IDTYPE_MMSI:
715
176
                        tp->id.mmsi = UBITS(off + 2, 42);
716
176
                        break;
717
374
                    case DAC1FID17_IDTYPE_IMO:
718
374
                        tp->id.imo = UBITS(off + 2, 42);
719
374
                        break;
720
339
                    case DAC1FID17_IDTYPE_CALLSIGN:
721
339
                        UCHARS(off + 2, tp->id.callsign);
722
339
                        break;
723
264
                    default:
724
264
                        UCHARS(off + 2, tp->id.other);
725
264
                        break;
726
1.15k
                    }
727
                    // skip 4 bits
728
1.15k
                    tp->lat = SBITS(off + 48, 24);
729
1.15k
                    tp->lon = SBITS(off + 72, 25);
730
1.15k
                    tp->course = UBITS(off + 97, 9);
731
1.15k
                    tp->second = UBITS(off + 106, 6);
732
1.15k
                    tp->speed = UBITS(off + 112, 10);
733
1.15k
                }
734
589
                ais->type8.dac1fid17.ntargets = u;
735
589
#undef ARRAY_BASE
736
589
#undef ELEMENT_SIZE
737
589
                ais->type8.structured = true;
738
589
                break;
739
132
            case 19:  // IMO289 - Marine Traffic Signal
740
132
                RANGE_CHECK8(258, 1008);
741
66
                ais->type8.dac1fid19.linkage = UBITS(56, 10);
742
66
                UCHARS(66, ais->type8.dac1fid19.station);
743
66
                ais->type8.dac1fid19.lon = SBITS(186, 25);
744
66
                ais->type8.dac1fid19.lat = SBITS(211, 24);
745
66
                ais->type8.dac1fid19.status = UBITS(235, 2);
746
66
                ais->type8.dac1fid19.signal = UBITS(237, 5);
747
66
                ais->type8.dac1fid19.hour = UBITS(242, 5);
748
66
                ais->type8.dac1fid19.minute = UBITS(247, 6);
749
66
                ais->type8.dac1fid19.nextsignal = UBITS(253, 5);
750
                // skip 102 bits
751
66
                ais->type8.structured = true;
752
66
                break;
753
0
            case 21:  // IMO289 - Weather obs. report from ship
754
0
                break;
755
0
            case 22:  // IMO289 - Area notice - broadcast
756
0
                break;
757
56
            case 24:
758
                // IMO289 - Extended ship static & voyage-related data
759
56
                break;
760
0
            case 26:  // IMO289 - Environmental
761
0
                break;
762
295
            case 27:  // IMO289 - Route information - broadcast
763
295
                RANGE_CHECK8(117, 1008);
764
229
                ais->type8.dac1fid27.linkage = UBITS(56, 10);
765
229
                ais->type8.dac1fid27.sender = UBITS(66, 3);
766
229
                ais->type8.dac1fid27.rtype = UBITS(69, 5);
767
229
                ais->type8.dac1fid27.month = UBITS(74, 4);
768
229
                ais->type8.dac1fid27.day = UBITS(78, 5);
769
229
                ais->type8.dac1fid27.hour = UBITS(83, 5);
770
229
                ais->type8.dac1fid27.minute = UBITS(88, 6);
771
229
                ais->type8.dac1fid27.duration = UBITS(94, 18);
772
229
                ais->type8.dac1fid27.waycount = UBITS(112, 5);
773
635
#define ARRAY_BASE 117
774
635
#define ELEMENT_SIZE 55
775
768
                for (u = 0; u < ais->type8.dac1fid27.waycount; u++) {
776
635
                    size_t off = OFF(u);
777
635
                    if (off >= bitlen ||
778
539
                        ROWS(ais->type8.dac1fid27.waypoints) <= u) {
779
96
                        break;
780
96
                    }
781
539
                    ais->type8.dac1fid27.waypoints[u].lon = SBITS(off + 0, 28);
782
539
                    ais->type8.dac1fid27.waypoints[u].lat = SBITS(off + 28, 27);
783
539
                }
784
229
#undef ARRAY_BASE
785
229
#undef ELEMENT_SIZE
786
229
                ais->type8.structured = true;
787
229
                break;
788
132
            case 29:  // IMO289 - Text Description - broadcast
789
132
                RANGE_CHECK8(66, 1008);
790
66
                ais->type8.dac1fid29.linkage = UBITS(56, 10);
791
66
                ENDCHARS(66, ais->type8.dac1fid29.text,
792
66
                         sizeof(ais->type8.dac1fid29.text));
793
66
                ais->type8.structured = true;
794
66
                break;
795
199
            case 31:  // IMO289 - Meteorological/Hydrological data
796
                // 368??
797
199
                RANGE_CHECK8(340, 368);
798
66
                ais->type8.dac1fid31.lon = SBITS(56, 25);
799
66
                ais->type8.dac1fid31.lat = SBITS(81, 24);
800
66
                ais->type8.dac1fid31.accuracy = (bool)UBITS(105, 1);
801
66
                ais->type8.dac1fid31.day = UBITS(106, 5);
802
66
                ais->type8.dac1fid31.hour = UBITS(111, 5);
803
66
                ais->type8.dac1fid31.minute = UBITS(116, 6);
804
66
                ais->type8.dac1fid31.wspeed = UBITS(122, 7);
805
66
                ais->type8.dac1fid31.wgust = UBITS(129, 7);
806
66
                ais->type8.dac1fid31.wdir = UBITS(136, 9);
807
66
                ais->type8.dac1fid31.wgustdir = UBITS(145, 9);
808
66
                ais->type8.dac1fid31.airtemp = SBITS(154, 11);
809
66
                ais->type8.dac1fid31.humidity = UBITS(165, 7);
810
66
                ais->type8.dac1fid31.dewpoint = SBITS(172, 10);
811
66
                ais->type8.dac1fid31.pressure = UBITS(182, 9);
812
66
                ais->type8.dac1fid31.pressuretend = UBITS(191, 2);
813
66
                ais->type8.dac1fid31.visgreater = UBITS(193, 1);
814
66
                ais->type8.dac1fid31.visibility = UBITS(194, 7);
815
66
                ais->type8.dac1fid31.waterlevel = UBITS(201, 12);
816
66
                ais->type8.dac1fid31.leveltrend = UBITS(213, 2);
817
66
                ais->type8.dac1fid31.cspeed = UBITS(215, 8);
818
66
                ais->type8.dac1fid31.cdir = UBITS(223, 9);
819
66
                ais->type8.dac1fid31.cspeed2 = UBITS(232, 8);
820
66
                ais->type8.dac1fid31.cdir2 = UBITS(240, 9);
821
66
                ais->type8.dac1fid31.cdepth2 = UBITS(249, 5);
822
66
                ais->type8.dac1fid31.cspeed3 = UBITS(254, 8);
823
66
                ais->type8.dac1fid31.cdir3 = UBITS(262, 9);
824
66
                ais->type8.dac1fid31.cdepth3 = UBITS(271, 5);
825
66
                ais->type8.dac1fid31.waveheight = UBITS(276, 8);
826
66
                ais->type8.dac1fid31.waveperiod = UBITS(284, 6);
827
66
                ais->type8.dac1fid31.wavedir = UBITS(290, 9);
828
66
                ais->type8.dac1fid31.swellheight = UBITS(299, 8);
829
66
                ais->type8.dac1fid31.swellperiod = UBITS(307, 6);
830
66
                ais->type8.dac1fid31.swelldir = UBITS(313, 9);
831
66
                ais->type8.dac1fid31.seastate = UBITS(322, 4);
832
66
                ais->type8.dac1fid31.watertemp = SBITS(326, 10);
833
66
                ais->type8.dac1fid31.preciptype = UBITS(336, 3);
834
66
                ais->type8.dac1fid31.salinity = UBITS(339, 9);
835
66
                ais->type8.dac1fid31.ice = UBITS(348, 2);
836
66
                ais->type8.structured = true;
837
66
                break;
838
2.37k
            }
839
1.49k
            break;
840
1.49k
        case 200:
841
951
            switch (ais->type8.fid) {
842
274
            case 10:  // Inland ship static and voyage related data
843
                // bitlen = 424??
844
274
                RANGE_CHECK8(168, 424);
845
139
                UCHARS(56, ais->type8.dac200fid10.vin);
846
139
                ais->type8.dac200fid10.length = UBITS(104, 13);
847
139
                ais->type8.dac200fid10.beam = UBITS(117, 10);
848
139
                ais->type8.dac200fid10.shiptype = UBITS(127, 14);
849
139
                ais->type8.dac200fid10.hazard = UBITS(141, 3);
850
139
                ais->type8.dac200fid10.draught = UBITS(144, 11);
851
139
                ais->type8.dac200fid10.loaded = UBITS(155, 2);
852
139
                ais->type8.dac200fid10.speed_q = (bool)UBITS(157, 1);
853
139
                ais->type8.dac200fid10.course_q = (bool)UBITS(158, 1);
854
139
                ais->type8.dac200fid10.heading_q = (bool)UBITS(159, 1);
855
                // skip 8 bits
856
                /*
857
                 * Attempt to prevent false matches with this message type
858
                 * by range-checking certain fields.
859
                 */
860
139
                if (DAC200FID10_HAZARD_MAX < ais->type8.dac200fid10.hazard ||
861
70
                    !isascii((int)ais->type8.dac200fid10.vin[0])) {
862
70
                    ais->type8.structured = false;
863
70
                } else {
864
69
                    ais->type8.structured = true;
865
69
                }
866
139
                break;
867
203
            case 23:  // EMMA warning
868
203
                RANGE_CHECK8(256, 256);
869
66
                ais->type8.dac200fid23.start_year = UBITS(56, 8);
870
66
                ais->type8.dac200fid23.start_month = UBITS(64, 4);
871
66
                ais->type8.dac200fid23.start_day = UBITS(68, 5);
872
66
                ais->type8.dac200fid23.end_year = UBITS(73, 8);
873
66
                ais->type8.dac200fid23.end_month = UBITS(81, 4);
874
66
                ais->type8.dac200fid23.end_day = UBITS(85, 5);
875
66
                ais->type8.dac200fid23.start_hour = UBITS(90, 5);
876
66
                ais->type8.dac200fid23.start_minute = UBITS(95, 6);
877
66
                ais->type8.dac200fid23.end_hour = UBITS(101, 5);
878
66
                ais->type8.dac200fid23.end_minute = UBITS(106, 6);
879
66
                ais->type8.dac200fid23.start_lon = SBITS(112, 28);
880
66
                ais->type8.dac200fid23.start_lat = SBITS(140, 27);
881
66
                ais->type8.dac200fid23.end_lon = SBITS(167, 28);
882
66
                ais->type8.dac200fid23.end_lat = SBITS(195, 27);
883
66
                ais->type8.dac200fid23.type = UBITS(222, 4);
884
66
                ais->type8.dac200fid23.min = SBITS(226, 9);
885
66
                ais->type8.dac200fid23.max = SBITS(235, 9);
886
66
                ais->type8.dac200fid23.intensity = UBITS(244, 2);
887
66
                ais->type8.dac200fid23.wind = UBITS(246, 4);
888
                // skip 6 bits
889
66
                ais->type8.structured = true;
890
66
                break;
891
203
            case 24:  // Water level
892
203
                RANGE_CHECK8(168, 168);
893
66
                UCHARS(56, ais->type8.dac200fid24.country);
894
330
#define ARRAY_BASE 68
895
330
#define ELEMENT_SIZE 25
896
330
                for (u = 0; ; u++) {
897
330
                    size_t off = OFF(u);
898
330
                    if (off >= bitlen ||
899
264
                        ROWS(ais->type8.dac200fid24.gauges) <= u) {
900
66
                        break;
901
66
                    }
902
264
                    ais->type8.dac200fid24.gauges[u].id = UBITS(off + 0,  11);
903
264
                    ais->type8.dac200fid24.gauges[u].level = SBITS(off + 11,
904
264
                                                                   14);
905
264
                }
906
66
                ais->type8.dac200fid24.ngauges = u;
907
66
#undef ARRAY_BASE
908
66
#undef ELEMENT_SIZE
909
                // skip 6 bits
910
66
                ais->type8.structured = true;
911
66
                break;
912
203
            case 40:  // Signal status
913
203
                RANGE_CHECK8(168, 168);
914
66
                ais->type8.dac200fid40.lon = SBITS(56, 28);
915
66
                ais->type8.dac200fid40.lat = SBITS(84, 27);
916
66
                ais->type8.dac200fid40.form = UBITS(111, 4);
917
66
                ais->type8.dac200fid40.facing = UBITS(115, 9);
918
66
                ais->type8.dac200fid40.direction = UBITS(124, 3);
919
66
                ais->type8.dac200fid40.status = UBITS(127, 30);
920
                // skip 11 bits
921
66
                ais->type8.structured = true;
922
66
                break;
923
951
            }
924
405
            break;
925
405
        default:
926
82
            break;
927
3.40k
        }
928
        // land here if we failed to match a known DAC/FID
929
1.97k
        if (!ais->type8.structured) {
930
366
            u = BITS_TO_BYTES(ais->type8.bitcount);
931
366
            if (sizeof(ais->type8.bitdata) < u) {
932
0
                u = sizeof(ais->type8.bitdata);
933
0
                ais->type8.bitcount = u * 8;
934
0
            }
935
366
            (void)memcpy(ais->type8.bitdata, bits + (56 / CHAR_BIT), u);
936
937
366
            size_t valid_bits_in_last_byte = ais->type8.bitcount % CHAR_BIT;
938
366
            if (valid_bits_in_last_byte > 0) {
939
                // huh??
940
208
                ais->type8.bitdata[u - 1] &=
941
208
                    (0xFF << (8 - valid_bits_in_last_byte));
942
208
            }
943
366
            GPSD_LOG(LOG_WARN, errout,
944
366
                     "AIVDM: type 8 unknown dac %u fid %u bitlen %zu\n",
945
366
                     ais->type8.dac, ais->type8.fid, bitlen);
946
366
        }
947
1.97k
        break;
948
213
    case 9:  // Standard SAR Aircraft Position Report
949
213
        PERMISSIVE_LENGTH_CHECK(168);
950
137
        ais->type9.alt = UBITS(38, 12);
951
137
        ais->type9.speed = UBITS(50, 10);
952
137
        ais->type9.accuracy = (bool)UBITS(60, 1);
953
137
        ais->type9.lon = SBITS(61, 28);
954
137
        ais->type9.lat = SBITS(89, 27);
955
137
        ais->type9.course = UBITS(116, 12);
956
137
        ais->type9.second = UBITS(128, 6);
957
137
        ais->type9.regional = UBITS(134, 8);
958
137
        ais->type9.dte = UBITS(142, 1);
959
        // ais->type9.spare      = UBITS(143, 3);
960
137
        ais->type9.assigned = UBITS(146, 1) != 0;
961
137
        ais->type9.raim = UBITS(147, 1) != 0;
962
137
        ais->type9.radio = UBITS(148, 20);
963
137
        break;
964
219
    case 10:  // UTC/Date inquiry
965
219
        PERMISSIVE_LENGTH_CHECK(72);
966
        // ais->type10.spare        = UBITS(38, 2);
967
134
        ais->type10.dest_mmsi = UBITS(40, 30);
968
        // ais->type10.spare2       = UBITS(70, 2);
969
134
        break;
970
223
    case 12:  // Safety Related Message
971
223
        RANGE_CHECK(72, 1008);
972
79
        ais->type12.seqno = UBITS(38, 2);
973
79
        ais->type12.dest_mmsi = UBITS(40, 30);
974
79
        ais->type12.retransmit = (bool)UBITS(70, 1);
975
        // ais->type12.spare        = UBITS(71, 1);
976
79
        ENDCHARS(72, ais->type12.text, sizeof(ais->type12.text));
977
79
        break;
978
235
    case 14:  // Safety Related Broadcast Message
979
235
        RANGE_CHECK(40, 960);
980
        // ais->type14.spare          = UBITS(38, 2);
981
100
        ENDCHARS(40, ais->type14.text, sizeof(ais->type14.text));
982
100
        break;
983
337
    case 15:
984
        // Interrogation
985
337
        RANGE_CHECK(88, 168);
986
198
        (void)memset(&ais->type15, '\0', sizeof(ais->type15));
987
        // ais->type14.spare         = UBITS(38, 2);
988
198
        ais->type15.mmsi1 = UBITS(40, 30);
989
198
        ais->type15.type1_1 = UBITS(70, 6);
990
198
        ais->type15.offset1_1 = UBITS(76, 12);
991
        // ais->type14.spare2        = UBITS(88, 2);
992
198
        if (90 < bitlen) {
993
132
            ais->type15.type1_2 = UBITS(90, 6);
994
132
            ais->type15.offset1_2 = UBITS(96, 12);
995
            // ais->type14.spare3      = UBITS(108, 2);
996
132
            if (110 < bitlen) {
997
66
                ais->type15.mmsi2 = UBITS(110, 30);
998
66
                ais->type15.type2_1 = UBITS(140, 6);
999
66
                ais->type15.offset2_1 = UBITS(146, 12);
1000
                // ais->type14.spare4    = UBITS(158, 2);
1001
66
            }
1002
132
        }
1003
198
        break;
1004
308
    case 16:
1005
        // Assigned Mode Command
1006
308
        RANGE_CHECK(96, 168);
1007
141
        ais->type16.mmsi1 = UBITS(40, 30);
1008
141
        ais->type16.offset1 = UBITS(70, 12);
1009
141
        ais->type16.increment1 = UBITS(82, 10);
1010
141
        if (144 > bitlen) {
1011
74
            ais->type16.mmsi2 = ais->type16.offset2 = 0;
1012
74
            ais->type16.increment2 = 0;
1013
74
        } else {
1014
67
            ais->type16.mmsi2 = UBITS(92, 30);
1015
67
            ais->type16.offset2 = UBITS(122, 12);
1016
67
            ais->type16.increment2 = UBITS(134, 10);
1017
67
        }
1018
141
        break;
1019
221
    case 17:
1020
        // GNSS Broadcast Binary Message
1021
        // ITU-R M1371-5 Table 68
1022
221
        RANGE_CHECK(80, 816);
1023
        // ais->type17.spare     = UBITS(38, 2);
1024
82
        ais->type17.lon = SBITS(40, 18);
1025
82
        ais->type17.lat = SBITS(58, 17);
1026
        // ais->type17.spare     = UBITS(75, 5);
1027
82
        ais->type17.bitcount = bitlen - 80;
1028
82
        if (736 < ais->type17.bitcount) {
1029
0
            ais->type17.bitcount = 736;
1030
0
        }
1031
82
        u = BITS_TO_BYTES(ais->type17.bitcount);
1032
82
        if (sizeof(ais->type17.bitdata) < u) {
1033
0
            u = sizeof(ais->type17.bitdata);
1034
0
            ais->type17.bitcount = u * 8;
1035
0
        }
1036
82
        (void)memcpy(ais->type17.bitdata, bits + (80 / CHAR_BIT), u);
1037
82
        break;
1038
204
    case 18:  // Standard Class B CS Position Report
1039
        // Per https://www.navcen.uscg.gov/ais-class-b-reports
1040
204
        PERMISSIVE_LENGTH_CHECK(168)
1041
135
        ais->type18.reserved = UBITS(38, 8);
1042
135
        ais->type18.speed = UBITS(46, 10);
1043
135
        ais->type18.accuracy = UBITS(56, 1) != 0;
1044
135
        ais->type18.lon = SBITS(57, 28);
1045
135
        ais->type18.lat = SBITS(85, 27);
1046
135
        ais->type18.course = UBITS(112, 12);
1047
135
        ais->type18.heading = UBITS(124, 9);
1048
135
        ais->type18.second = UBITS(133, 6);
1049
135
        ais->type18.regional = UBITS(139, 2);
1050
135
        ais->type18.cs = UBITS(141, 1) != 0;
1051
135
        ais->type18.display = UBITS(142, 1) != 0;
1052
135
        ais->type18.dsc = UBITS(143, 1) != 0;
1053
135
        ais->type18.band = UBITS(144, 1) != 0;
1054
135
        ais->type18.msg22 = UBITS(145, 1) != 0;
1055
135
        ais->type18.assigned = UBITS(146, 1) != 0;
1056
135
        ais->type18.raim = UBITS(147, 1) != 0;
1057
135
        ais->type18.radio = UBITS(148, 20);
1058
135
        break;
1059
211
    case 19:  // Extended Class B CS Position Report
1060
211
        PERMISSIVE_LENGTH_CHECK(312)
1061
135
        ais->type19.reserved = UBITS(38, 8);
1062
135
        ais->type19.speed = UBITS(46, 10);
1063
135
        ais->type19.accuracy = UBITS(56, 1) != 0;
1064
135
        ais->type19.lon = SBITS(57, 28);
1065
135
        ais->type19.lat = SBITS(85, 27);
1066
135
        ais->type19.course = UBITS(112, 12);
1067
135
        ais->type19.heading = UBITS(124, 9);
1068
135
        ais->type19.second = UBITS(133, 6);
1069
135
        ais->type19.regional = UBITS(139, 4);
1070
135
        UCHARS(143, ais->type19.shipname);
1071
135
        ais->type19.shiptype = UBITS(263, 8);
1072
135
        ais->type19.to_bow = UBITS(271, 9);
1073
135
        ais->type19.to_stern = UBITS(280, 9);
1074
135
        ais->type19.to_port = UBITS(289, 6);
1075
135
        ais->type19.to_starboard = UBITS(295, 6);
1076
135
        ais->type19.epfd = UBITS(301, 4);
1077
135
        ais->type19.raim = UBITS(305, 1) != 0;
1078
135
        ais->type19.dte = UBITS(306, 1) != 0;
1079
135
        ais->type19.assigned = UBITS(307, 1) != 0;
1080
        // ais->type19.spare      = UBITS(308, 4);
1081
135
        break;
1082
210
    case 20:  // Data Link Management Message
1083
210
        RANGE_CHECK(72, 186);
1084
        // ais->type20.spare     = UBITS(38, 2);
1085
69
        ais->type20.offset1 = UBITS(40, 12);
1086
69
        ais->type20.number1 = UBITS(52, 4);
1087
69
        ais->type20.timeout1 = UBITS(56, 3);
1088
69
        ais->type20.increment1 = UBITS(59, 11);
1089
69
        ais->type20.offset2 = UBITS(70, 12);
1090
69
        ais->type20.number2 = UBITS(82, 4);
1091
69
        ais->type20.timeout2 = UBITS(86, 3);
1092
69
        ais->type20.increment2 = UBITS(89, 11);
1093
69
        ais->type20.offset3 = UBITS(100, 12);
1094
69
        ais->type20.number3 = UBITS(112, 4);
1095
69
        ais->type20.timeout3 = UBITS(116, 3);
1096
69
        ais->type20.increment3 = UBITS(119, 11);
1097
69
        ais->type20.offset4 = UBITS(130, 12);
1098
69
        ais->type20.number4 = UBITS(142, 4);
1099
69
        ais->type20.timeout4 = UBITS(146, 3);
1100
69
        ais->type20.increment4 = UBITS(149, 11);
1101
69
        break;
1102
503
    case 21:  // Aid-to-Navigation Report
1103
        // Per https://www.navcen.uscg.gov/ais-class-b-reports
1104
503
        RANGE_CHECK(272, 368);
1105
361
        ais->type21.aid_type = UBITS(38, 5);
1106
361
        from_sixbit_untrimmed(errout, bits, bitlen, 43, 20, ais->type21.name,
1107
361
                              sizeof(ais->type21.name));
1108
361
        ais->type21.accuracy = UBITS(163, 1);
1109
361
        ais->type21.lon = SBITS(164, 28);
1110
361
        ais->type21.lat = SBITS(192, 27);
1111
361
        ais->type21.to_bow = UBITS(219, 9);
1112
361
        ais->type21.to_stern = UBITS(228, 9);
1113
361
        ais->type21.to_port = UBITS(237, 6);
1114
361
        ais->type21.to_starboard = UBITS(243, 6);
1115
361
        ais->type21.epfd = UBITS(249, 4);
1116
361
        ais->type21.second = UBITS(253, 6);
1117
361
        ais->type21.off_position = UBITS(259, 1) != 0;
1118
361
        ais->type21.regional = UBITS(260, 8);
1119
361
        ais->type21.raim = UBITS(268, 1) != 0;
1120
361
        ais->type21.virtual_aid = UBITS(269, 1) != 0;
1121
361
        ais->type21.assigned = UBITS(270, 1) != 0;
1122
        // ais->type21.spare      = UBITS(271, 1);
1123
361
        if (20 == strnlen(ais->type21.name, 21) &&
1124
190
            272 < bitlen) {
1125
122
            ENDCHARS(272, ais->type21.name + 20,
1126
122
                     sizeof(ais->type21.name) - 20);
1127
122
        }
1128
361
        trim_spaces_on_right_end(ais->type21.name, sizeof(ais->type21.name));
1129
361
        break;
1130
290
    case 22:  // Channel Management
1131
290
        PERMISSIVE_LENGTH_CHECK(168)
1132
209
        ais->type22.channel_a = UBITS(40, 12);
1133
209
        ais->type22.channel_b = UBITS(52, 12);
1134
209
        ais->type22.txrx = UBITS(64, 4);
1135
209
        ais->type22.power = UBITS(68, 1);
1136
209
        ais->type22.addressed = UBITS(139, 1);
1137
209
        if (!ais->type22.addressed) {
1138
136
            ais->type22.area.ne_lon = SBITS(69, 18);
1139
136
            ais->type22.area.ne_lat = SBITS(87, 17);
1140
136
            ais->type22.area.sw_lon = SBITS(104, 18);
1141
136
            ais->type22.area.sw_lat = SBITS(122, 17);
1142
136
        } else {
1143
73
            ais->type22.mmsi.dest1 = UBITS(69, 30);
1144
73
            ais->type22.mmsi.dest2 = UBITS(104, 30);
1145
73
        }
1146
209
        ais->type22.band_a = UBITS(140, 1);
1147
209
        ais->type22.band_b = UBITS(141, 1);
1148
209
        ais->type22.zonesize = UBITS(142, 3);
1149
209
        break;
1150
204
    case 23:  // Group Assignment Command
1151
204
        PERMISSIVE_LENGTH_CHECK(160)
1152
137
        ais->type23.ne_lon = SBITS(40, 18);
1153
137
        ais->type23.ne_lat = SBITS(58, 17);
1154
137
        ais->type23.sw_lon = SBITS(75, 18);
1155
137
        ais->type23.sw_lat = SBITS(93, 17);
1156
137
        ais->type23.stationtype = UBITS(110, 4);
1157
137
        ais->type23.shiptype = UBITS(114, 8);
1158
137
        ais->type23.txrx = UBITS(144, 4);
1159
137
        ais->type23.interval = UBITS(146, 4);
1160
137
        ais->type23.quiet = UBITS(150, 4);
1161
137
        break;
1162
2.84k
    case 24:  // Class B CS Static Data Report
1163
2.84k
        switch (UBITS(38, 2)) {
1164
2.04k
        case 0:
1165
2.04k
            RANGE_CHECK(160, 168);
1166
            // save incoming 24A shipname/MMSI pairs in a circular queue
1167
1.89k
            {
1168
1.89k
                struct ais_type24a_t *saveptr =
1169
1.89k
                    &type24_queue->ships[type24_queue->index];
1170
1171
1.89k
                GPSD_LOG(LOG_PROG, errout, "AIVDM: 24A from %09u stashed.\n",
1172
1.89k
                         ais->mmsi);
1173
1.89k
                saveptr->mmsi = ais->mmsi;
1174
1.89k
                UCHARS(40, saveptr->shipname);
1175
1.89k
                ++type24_queue->index;
1176
1.89k
                type24_queue->index %= MAX_TYPE24_INTERLEAVE;
1177
1.89k
            }
1178
            // ais->type24.a.spare       = UBITS(160, 8);
1179
1180
1.89k
            UCHARS(40, ais->type24.shipname);
1181
1.89k
            ais->type24.part = part_a;
1182
1.89k
            return true;
1183
736
        case 1:
1184
736
            PERMISSIVE_LENGTH_CHECK(168)
1185
663
            ais->type24.shiptype = UBITS(40, 8);
1186
            /*
1187
             * In ITU-R 1371-4, there are new model and serial fields
1188
             * carved out of the right-hand end of vendorid, which is
1189
             * reduced from 7 chars to 3.  To cope with older AIS
1190
             * implementations conforming to revision 3 and older,
1191
             * unpack the trailing bits *both* ways; truly
1192
             * revision-4-conformant implementations will have up to
1193
             * four characters of trailing garbage on the vendorid,
1194
             * and older implementations will have garbafe in the
1195
             * model and serial fields.
1196
             */
1197
663
            UCHARS(48, ais->type24.vendorid);
1198
663
            ais->type24.model = UBITS(66, 4);
1199
663
            ais->type24.serial = UBITS(70, 20);
1200
663
            UCHARS(90, ais->type24.callsign);
1201
663
            if (AIS_AUXILIARY_MMSI(ais->mmsi)) {
1202
118
                ais->type24.mothership_mmsi = UBITS(132, 30);
1203
545
            } else {
1204
545
                ais->type24.dim.to_bow = UBITS(132, 9);
1205
545
                ais->type24.dim.to_stern = UBITS(141, 9);
1206
545
                ais->type24.dim.to_port = UBITS(150, 6);
1207
545
                ais->type24.dim.to_starboard = UBITS(156, 6);
1208
545
            }
1209
            // ais->type24.b.spare           = UBITS(162, 8);
1210
1211
            // search the 24A queue for a matching MMSI
1212
4.98k
            for (u = 0; u < MAX_TYPE24_INTERLEAVE; u++) {
1213
4.53k
                if (type24_queue->ships[u].mmsi == ais->mmsi) {
1214
213
                    (void)strlcpy(ais->type24.shipname,
1215
213
                                  type24_queue->ships[u].shipname,
1216
213
                                  sizeof(ais->type24.shipname));
1217
213
                    GPSD_LOG(LOG_PROG, errout,
1218
213
                             "AIVDM 24B from %09u matches a 24A.\n",
1219
213
                             ais->mmsi);
1220
                    // prevent false match if a 24B is repeated
1221
213
                    type24_queue->ships[u].mmsi = 0;
1222
213
                    ais->type24.part = both;
1223
213
                    return true;
1224
213
                }
1225
4.53k
            }
1226
1227
            // no match, return Part B
1228
450
            ais->type24.part = part_b;
1229
450
            return true;
1230
69
        default:
1231
69
            GPSD_LOG(LOG_WARN, errout,
1232
69
                     "AIVDM message type 24 of subtype unknown.\n");
1233
69
            return false;
1234
2.84k
        }
1235
    // break;
1236
437
    case 25:
1237
        // Binary Message, Single Slot
1238
        // this check and the following ones reject line noise
1239
        // ITU-R M1371-5 Table 80
1240
437
        RANGE_CHECK(80, 168);
1241
296
        ais->type25.addressed = (bool)UBITS(38, 1);
1242
296
        ais->type25.structured = (bool)UBITS(39, 1);  // binary data flag
1243
1244
296
        u = 40U + (32U * ais->type25.addressed) +
1245
296
            (16U * ais->type25.structured);
1246
296
        if (bitlen < u) {
1247
69
            GPSD_LOG(LOG_WARN, errout,
1248
69
                     "AIVDM type 25 bitlen %zu wrong want %u.\n",
1249
69
                     bitlen, u);
1250
69
            return false;
1251
69
        }
1252
227
        ais->type25.bitcount = bitlen - 40 - 16 * ais->type25.structured;
1253
227
        if (ais->type25.addressed) {
1254
150
            ais->type25.bitcount -= 32;
1255
150
            ais->type25.dest_mmsi = UBITS(40, 30);
1256
            // plus 2 bits of padding
1257
150
            if (98 < ais->type25.bitcount) {
1258
                // ITU-R M.1371-5 Table 80
1259
0
                ais->type25.bitcount = 98;
1260
0
            }
1261
150
        } else {
1262
77
            if (128 < ais->type25.bitcount) {
1263
                // ITU-R M.1371-5 Table 80
1264
0
                ais->type25.bitcount = 128;
1265
0
            }
1266
77
        }
1267
227
        if (ais->type25.structured) {
1268
119
            ais->type25.bitcount -= 16;
1269
119
            ais->type25.app_id = UBITS(40 + ais->type25.addressed * 32, 16);
1270
119
        }
1271
227
        u = BITS_TO_BYTES(ais->type25.bitcount);
1272
227
        if (sizeof(ais->type25.bitdata) < u) {
1273
85
            u = sizeof(ais->type25.bitdata);
1274
85
            ais->type25.bitcount = u * 8;
1275
85
        }
1276
        // bit 40 is exactly 5 bytes in; 2 bytes is 16 bits
1277
227
        (void)memcpy(ais->type25.bitdata,
1278
227
                     bits + 5 + 2 * ais->type25.structured +
1279
227
                     4 * ais->type25.addressed, u);
1280
227
        break;
1281
617
    case 26:
1282
        // Binary Message, Multiple Slot
1283
        // ITU-R M1371-5 Tables 28 and 82
1284
617
        RANGE_CHECK(96, 1064);
1285
460
        ais->type26.addressed = (bool)UBITS(38, 1);
1286
460
        ais->type26.structured = (bool)UBITS(39, 1);  // binary data flag
1287
460
        u = 40U + (16U * ais->type26.structured) +
1288
460
            (32U * ais->type26.addressed) + 20;
1289
460
        if (bitlen < u) {
1290
68
            GPSD_LOG(LOG_WARN, errout,
1291
68
                     "AIVDM type 26 %zu wrong, want %u.\n", bitlen, u);
1292
68
            return false;
1293
68
        }
1294
392
        ais->type26.bitcount = bitlen - 60 - 16 * ais->type26.structured;
1295
392
        if (ais->type26.addressed) {
1296
227
            ais->type26.bitcount -= 30;
1297
227
            ais->type26.dest_mmsi = UBITS(40, 30);
1298
227
            if (72 < ais->type26.bitcount) {
1299
                // ITU-R M.1371-5 Table 28
1300
81
                ais->type26.bitcount = 72;
1301
81
            }
1302
227
        } else {
1303
            // broadcast
1304
165
            if (104 < ais->type26.bitcount) {
1305
                // ITU-R M.1371-5 Table 28
1306
70
                ais->type26.bitcount = 104;
1307
70
            }
1308
165
        }
1309
392
        if (ais->type26.structured) {
1310
184
            ais->type26.bitcount -= 16;
1311
184
            ais->type26.app_id = UBITS(40 + ais->type26.addressed * 32, 16);
1312
184
        }
1313
392
        u = BITS_TO_BYTES(ais->type26.bitcount);
1314
392
        if (sizeof(ais->type26.bitdata) < u) {
1315
74
            u = sizeof(ais->type26.bitdata);
1316
74
            ais->type26.bitcount = 8 * u;
1317
74
        }
1318
        // bit 40 is exactly 5 bytes in; 2 bytes is 16 bits
1319
392
        (void)memcpy(ais->type26.bitdata,
1320
392
                     bits + 5 + 2 * ais->type26.structured +
1321
392
                     4 * ais->type26.addressed, u);
1322
392
        break;
1323
277
    case 27:  // Long Range AIS Broadcast message
1324
277
        RANGE_CHECK(96, 168);
1325
139
        if (96 != bitlen) {
1326
            /*
1327
             * This is an implementation error observed in the wild,
1328
             * sending a full 168-bit slot rather than just 96 bits.
1329
             */
1330
73
            GPSD_LOG(LOG_WARN, errout,
1331
73
                     "oversized 168-bit AIVDM message type 27.\n");
1332
73
        }
1333
139
        ais->type27.accuracy = (bool)UBITS(38, 1);
1334
139
        ais->type27.raim = UBITS(39, 1) != 0;
1335
139
        ais->type27.status = UBITS(40, 4);
1336
139
        ais->type27.lon = SBITS(44, 18);
1337
139
        ais->type27.lat = SBITS(62, 17);
1338
139
        ais->type27.speed = UBITS(79, 6);
1339
139
        ais->type27.course = UBITS(85, 9);
1340
139
        ais->type27.gnss = (bool)UBITS(94, 1);
1341
139
        break;
1342
213
    default:
1343
213
        GPSD_LOG(LOG_ERROR, errout,
1344
213
                 "Unparsed AIVDM message type %d.\n",ais->type);
1345
213
        return false;
1346
16.4k
    }
1347
7.59k
#undef UCHARS
1348
7.59k
#undef SBITS
1349
7.59k
#undef UBITS
1350
1351
    // data is fully decoded
1352
7.59k
    return true;
1353
16.4k
}
1354
// vim: set expandtab shiftwidth=4