Coverage Report

Created: 2026-03-03 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/gpsd/pseudoais.c
Line
Count
Source
1
/*
2
 * Encode AIS messages.
3
 *
4
 * See the file AIVDM.txt on the GPSD website for documentation and references.
5
 *
6
 * This file is build from driver_ais.c
7
 *
8
 * This file is Copyright 2013 by the GPSD project
9
 * SPDX-License-Identifier: BSD-2-clause
10
 */
11
12
#include "../include/gpsd_config.h"   // must be before all includes
13
14
#include <stdlib.h>
15
#include <string.h>
16
#include <ctype.h>
17
18
#include "../include/gpsd.h"
19
#include "../include/bits.h"
20
#include <stdint.h>
21
22
#ifdef AIVDM_ENABLE
23
24
0
#define AIS_MSG_PART2_FLAG 0x100
25
26
static unsigned char convtab[] = {
27
    "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW`abcdefghijklmnopqrstuvw"};
28
static unsigned char contab1[] = {
29
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
30
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
31
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
34
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
35
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
36
    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
37
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
38
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
39
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
40
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
41
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
45
46
static void ais_addbits(unsigned char *bits,
47
                        unsigned int   start,
48
                        unsigned int   len,
49
                        uint64_t       data)
50
0
{
51
0
    unsigned int  l;
52
0
    unsigned int  pos;
53
0
    uint64_t      mask;
54
0
    unsigned int  mask1;
55
56
0
    mask  = 0x1;
57
0
    pos   = (start + len - 1) / 6;
58
0
    mask1 = 0x20;
59
0
    mask1 = mask1 >> ((start + len - 1) % 6);
60
61
0
    if (0 == len) {
62
0
        return;
63
0
    }
64
65
0
    for(l = 0; l < len; l++) {
66
0
        if (data & mask) {
67
0
            bits[pos] |= mask1;
68
0
        }
69
0
        mask  <<= 1;
70
0
        mask1 <<= 1;
71
0
        if (0x40 == mask1) {
72
0
            pos   -= 1;
73
0
            mask1  = 0x1;
74
0
        }
75
0
    }
76
0
    return;
77
0
}
78
79
80
static void ais_addchar(unsigned char *bits,
81
                        unsigned int   start,
82
                        unsigned int   len,
83
                        char          *data)
84
0
{
85
0
    unsigned int l;
86
0
    unsigned int flag;
87
88
0
    for(l = 0, flag = 0; l < len; l++) {
89
0
        unsigned char a, b;
90
91
0
        a = (unsigned char) data[l];
92
0
        if ((unsigned char)'\0' == a) {
93
0
            flag = 1;
94
0
        }
95
0
        if (0 == flag) {
96
0
            b = contab1[a & 0x7f];
97
0
        } else {
98
0
            b = (unsigned char)'\0';
99
0
        }
100
0
        ais_addbits(bits, start+6*l, 6, (uint64_t)b);
101
0
    }
102
0
    return;
103
0
}
104
105
106
static void ais_adddata(unsigned char *bits,
107
                   unsigned int   start,
108
                   unsigned int   len,
109
                   char          *data)
110
0
{
111
0
    unsigned int l;
112
113
0
    for(l = 0; l < len; l++) {
114
0
        ais_addbits(bits, start+6*l, 6, (uint64_t)data[l]);
115
0
    }
116
0
    return;
117
0
}
118
119
120
static void ais_binary_to_ascii(unsigned char *bits, unsigned int len)
121
0
{
122
0
    unsigned int l;
123
124
0
    if (0 == len) {
125
0
        bits[0] = '\0';
126
0
        return;
127
0
    }
128
129
0
    for (l = 0; l < len;l += 6) {
130
0
        bits[l/6] = convtab[bits[l/6] & 0x3f];
131
0
    }
132
0
    return;
133
0
}
134
135
136
unsigned int ais_binary_encode(struct ais_t *ais,
137
                               unsigned char *bits,
138
                               int flag)
139
0
{
140
0
    unsigned int len;
141
0
    size_t slen;
142
143
0
    len = 0;
144
145
0
    if (0 != flag) {
146
0
        flag = AIS_MSG_PART2_FLAG;
147
0
    }
148
0
    ais_addbits(bits,  0,  6, (uint64_t)ais->type);
149
0
    ais_addbits(bits,  6,  2, (uint64_t)ais->repeat);
150
0
    ais_addbits(bits,  8, 30, (uint64_t)ais->mmsi);
151
0
    switch (flag | ais->type) {
152
0
    case 1:     // Position Report
153
0
        FALLTHROUGH
154
0
    case 2:
155
0
        FALLTHROUGH
156
0
    case 3:
157
0
        ais_addbits(bits,  38,  4, (uint64_t)ais->type1.status);
158
0
        ais_addbits(bits,  42,  8, (uint64_t)ais->type1.turn);
159
0
        ais_addbits(bits,  50, 10, (uint64_t)ais->type1.speed);
160
0
        ais_addbits(bits,  60,  1, (uint64_t)ais->type1.accuracy);
161
0
        ais_addbits(bits,  61, 28, (uint64_t)ais->type1.lon);
162
0
        ais_addbits(bits,  89, 27, (uint64_t)ais->type1.lat);
163
0
        ais_addbits(bits, 116, 12, (uint64_t)ais->type1.course);
164
0
        ais_addbits(bits, 128,  9, (uint64_t)ais->type1.heading);
165
0
        ais_addbits(bits, 137,  6, (uint64_t)ais->type1.second);
166
0
        ais_addbits(bits, 143,  2, (uint64_t)ais->type1.maneuver);
167
        // ais_addbits(bits, 145,  3, (uint64_t)ais->type1.spare);
168
0
        ais_addbits(bits, 148,  1, (uint64_t)ais->type1.raim);
169
0
        ais_addbits(bits, 149, 19, (uint64_t)ais->type1.radio);
170
0
        len = 149 + 19;
171
0
        break;
172
0
    case 4:     // Base Station Report
173
0
        FALLTHROUGH
174
0
    case 11:    // UTC/Date Response
175
0
        ais_addbits(bits,  38, 14, (uint64_t)ais->type4.year);
176
0
        ais_addbits(bits,  52,  4, (uint64_t)ais->type4.month);
177
0
        ais_addbits(bits,  56,  5, (uint64_t)ais->type4.day);
178
0
        ais_addbits(bits,  61,  5, (uint64_t)ais->type4.hour);
179
0
        ais_addbits(bits,  66,  6, (uint64_t)ais->type4.minute);
180
0
        ais_addbits(bits,  72,  6, (uint64_t)ais->type4.second);
181
0
        ais_addbits(bits,  78,  1, (uint64_t)ais->type4.accuracy);
182
0
        ais_addbits(bits,  79, 28, (uint64_t)ais->type4.lon);
183
0
        ais_addbits(bits, 107, 27, (uint64_t)ais->type4.lat);
184
0
        ais_addbits(bits, 134,  4, (uint64_t)ais->type4.epfd);
185
        // ais_addbits(bits, 138, 10, (uint64_t)ais->type4.spare);
186
0
        ais_addbits(bits, 148,  1, (uint64_t)ais->type4.raim);
187
0
        ais_addbits(bits, 149, 19, (uint64_t)ais->type4.radio);
188
0
        len = 149 + 19;
189
0
        break;
190
0
    case 5:     // Ship static and voyage related data
191
0
        ais_addbits(bits,  38,  2, (uint64_t)ais->type5.ais_version);
192
0
        ais_addbits(bits,  40, 30, (uint64_t)ais->type5.imo);
193
0
        ais_addchar(bits,  70,  7,           ais->type5.callsign);
194
0
        ais_addchar(bits, 112, 20,           ais->type5.shipname);
195
0
        ais_addbits(bits, 232,  8, (uint64_t)ais->type5.shiptype);
196
0
        ais_addbits(bits, 240,  9, (uint64_t)ais->type5.to_bow);
197
0
        ais_addbits(bits, 249,  9, (uint64_t)ais->type5.to_stern);
198
0
        ais_addbits(bits, 258,  6, (uint64_t)ais->type5.to_port);
199
0
        ais_addbits(bits, 264,  6, (uint64_t)ais->type5.to_starboard);
200
0
        ais_addbits(bits, 270,  4, (uint64_t)ais->type5.epfd);
201
0
        ais_addbits(bits, 274,  4, (uint64_t)ais->type5.month);
202
0
        ais_addbits(bits, 278,  5, (uint64_t)ais->type5.day);
203
0
        ais_addbits(bits, 283,  5, (uint64_t)ais->type5.hour);
204
0
        ais_addbits(bits, 288,  6, (uint64_t)ais->type5.minute);
205
0
        ais_addbits(bits, 294,  8, (uint64_t)ais->type5.draught);
206
0
        ais_addchar(bits, 302, 20,           ais->type5.destination);
207
0
        ais_addbits(bits, 422,  1, (uint64_t)ais->type5.dte);
208
        // ais_addbits(bits, 423,  1, (uint64_t)ais->type5.spare);
209
0
        len = 423 + 1;
210
0
        break;
211
0
    case 9:     // Standard SAR Aircraft Position Report
212
0
        ais_addbits(bits,  38, 12, (uint64_t)ais->type9.alt);
213
0
        ais_addbits(bits,  50, 10, (uint64_t)ais->type9.speed);
214
0
        ais_addbits(bits,  60,  1, (uint64_t)ais->type9.accuracy);
215
0
        ais_addbits(bits,  61, 28, (uint64_t)ais->type9.lon);
216
0
        ais_addbits(bits,  89, 27, (uint64_t)ais->type9.lat);
217
0
        ais_addbits(bits, 116, 12, (uint64_t)ais->type9.course);
218
0
        ais_addbits(bits, 128,  6, (uint64_t)ais->type9.second);
219
0
        ais_addbits(bits, 134,  8, (uint64_t)ais->type9.regional);
220
0
        ais_addbits(bits, 142,  1, (uint64_t)ais->type9.dte);
221
        // ais_addbits(bits, 143,  3, (uint64_t)ais->type9.spare);
222
0
        ais_addbits(bits, 146,  1, (uint64_t)ais->type9.assigned);
223
0
        ais_addbits(bits, 147,  1, (uint64_t)ais->type9.raim);
224
0
        ais_addbits(bits, 148, 19, (uint64_t)ais->type9.radio);
225
0
        len = 148 + 19;
226
0
        break;
227
0
    case 18:    // Standard Class B CS Position Report
228
0
        ais_addbits(bits,  38,  8, (uint64_t)ais->type18.reserved);
229
0
        ais_addbits(bits,  46, 10, (uint64_t)ais->type18.speed);
230
0
        ais_addbits(bits,  56,  1, (uint64_t)ais->type18.accuracy);
231
0
        ais_addbits(bits,  57, 28, (uint64_t)ais->type18.lon);
232
0
        ais_addbits(bits,  85, 27, (uint64_t)ais->type18.lat);
233
0
        ais_addbits(bits, 112, 12, (uint64_t)ais->type18.course);
234
0
        ais_addbits(bits, 124,  9, (uint64_t)ais->type18.heading);
235
0
        ais_addbits(bits, 133,  6, (uint64_t)ais->type18.second);
236
0
        ais_addbits(bits, 139,  2, (uint64_t)ais->type18.regional);
237
0
        ais_addbits(bits, 141,  1, (uint64_t)ais->type18.cs);
238
0
        ais_addbits(bits, 142,  1, (uint64_t)ais->type18.display);
239
0
        ais_addbits(bits, 143,  1, (uint64_t)ais->type18.dsc);
240
0
        ais_addbits(bits, 144,  1, (uint64_t)ais->type18.band);
241
0
        ais_addbits(bits, 145,  1, (uint64_t)ais->type18.msg22);
242
0
        ais_addbits(bits, 146,  1, (uint64_t)ais->type18.assigned);
243
0
        ais_addbits(bits, 147,  1, (uint64_t)ais->type18.raim);
244
0
        ais_addbits(bits, 148, 20, (uint64_t)ais->type18.radio);
245
0
        len = 148 + 20;
246
0
        break;
247
0
    case 19:    // Extended Class B CS Position Report
248
0
        ais_addbits(bits,  38,  8, (uint64_t)ais->type19.reserved);
249
0
        ais_addbits(bits,  46, 10, (uint64_t)ais->type19.speed);
250
0
        ais_addbits(bits,  56,  1, (uint64_t)ais->type19.accuracy);
251
0
        ais_addbits(bits,  57, 28, (uint64_t)ais->type19.lon);
252
0
        ais_addbits(bits,  85, 27, (uint64_t)ais->type19.lat);
253
0
        ais_addbits(bits, 112, 12, (uint64_t)ais->type19.course);
254
0
        ais_addbits(bits, 124,  9, (uint64_t)ais->type19.heading);
255
0
        ais_addbits(bits, 133,  6, (uint64_t)ais->type19.second);
256
0
        ais_addbits(bits, 139,  4, (uint64_t)ais->type19.regional);
257
0
        ais_addchar(bits, 143, 20,           ais->type19.shipname);
258
0
        ais_addbits(bits, 263,  8, (uint64_t)ais->type19.shiptype);
259
0
        ais_addbits(bits, 271,  9, (uint64_t)ais->type19.to_bow);
260
0
        ais_addbits(bits, 280,  9, (uint64_t)ais->type19.to_stern);
261
0
        ais_addbits(bits, 289,  6, (uint64_t)ais->type19.to_port);
262
0
        ais_addbits(bits, 295,  6, (uint64_t)ais->type19.to_starboard);
263
0
        ais_addbits(bits, 299,  4, (uint64_t)ais->type19.epfd);
264
0
        ais_addbits(bits, 302,  1, (uint64_t)ais->type19.raim);
265
0
        ais_addbits(bits, 305,  1, (uint64_t)ais->type19.dte);
266
0
        ais_addbits(bits, 306,  1, (uint64_t)ais->type19.assigned);
267
        // ais_addbits(bits, 307,  5, (uint64_t)ais->type19.spare);
268
0
        len = 307 + 5;
269
0
        break;
270
0
    case 21:    // Aid-to-Navigation Report
271
0
        ais_addbits(bits,  38,  5, (uint64_t)ais->type21.aid_type);
272
0
        ais_addchar(bits,  43, 20,           ais->type21.name);
273
0
        ais_addbits(bits, 163,  1, (uint64_t)ais->type21.accuracy);
274
0
        ais_addbits(bits, 164, 28, (uint64_t)ais->type21.lon);
275
0
        ais_addbits(bits, 192, 27, (uint64_t)ais->type21.lat);
276
0
        ais_addbits(bits, 219,  9, (uint64_t)ais->type21.to_bow);
277
0
        ais_addbits(bits, 228,  9, (uint64_t)ais->type21.to_stern);
278
0
        ais_addbits(bits, 237,  6, (uint64_t)ais->type21.to_port);
279
0
        ais_addbits(bits, 243,  6, (uint64_t)ais->type21.to_starboard);
280
0
        ais_addbits(bits, 249,  4, (uint64_t)ais->type21.epfd);
281
0
        ais_addbits(bits, 253,  6, (uint64_t)ais->type21.second);
282
0
        ais_addbits(bits, 259,  1, (uint64_t)ais->type21.off_position);
283
0
        ais_addbits(bits, 260,  8, (uint64_t)ais->type21.regional);
284
0
        ais_addbits(bits, 268,  1, (uint64_t)ais->type21.raim);
285
0
        ais_addbits(bits, 269,  1, (uint64_t)ais->type21.virtual_aid);
286
0
        ais_addbits(bits, 270,  1, (uint64_t)ais->type21.assigned);
287
        // ais_addbits(bits, 271,  1, (uint64_t)ais->type21.spare);
288
0
        len = 271 + 1;
289
0
        slen = strnlen(ais->type21.name, sizeof(ais->type21.name));
290
0
        if (20 < slen) {
291
0
            unsigned int extralen;
292
293
0
            extralen = (unsigned int)(slen - 20);
294
0
            ais_addchar(bits, 272, extralen, ais->type21.name + 20);
295
0
            len += extralen * 6;
296
0
        }
297
0
        break;
298
0
    case 24:    // Class B CS Static Data Report Part 1
299
0
        if (ais->type24.part == part_a) {
300
0
            ais_addbits(bits,  38,  2, (uint64_t)0);
301
0
            ais_addchar(bits,  40, 20,           ais->type24.shipname);
302
            // ais_addbits(bits, 160,  8, (uint64_t)ais->type24.a.spare);
303
0
            len = 160;
304
0
        }
305
0
        break;
306
0
    case 24 | AIS_MSG_PART2_FLAG:  // Class B CS Static Data Report Part 2
307
0
        if ((ais->type24.part == part_b) || (ais->type24.part == both)) {
308
0
            ais_addbits(bits,  38,  2, (uint64_t)1);
309
0
            ais_addbits(bits,  40,  8, (uint64_t)ais->type24.shiptype);
310
0
            ais_addchar(bits,  48,  3,          &ais->type24.vendorid[0]);
311
0
            ais_adddata(bits,  66,  3,          &ais->type24.vendorid[3]);
312
0
            ais_addchar(bits,  90,  7,          ais->type24.callsign);
313
0
            if (AIS_AUXILIARY_MMSI(ais->mmsi)) {
314
0
                ais_addbits(bits, 132, 30,
315
0
                            (uint64_t)ais->type24.mothership_mmsi);
316
0
            } else {
317
0
                ais_addbits(bits, 132,  9, (uint64_t)ais->type24.dim.to_bow);
318
0
                ais_addbits(bits, 141,  9, (uint64_t)ais->type24.dim.to_stern);
319
0
                ais_addbits(bits, 150,  6, (uint64_t)ais->type24.dim.to_port);
320
0
                ais_addbits(bits, 156,  6,
321
0
                            (uint64_t)ais->type24.dim.to_starboard);
322
0
            }
323
            // ais_addbits(bits, 162,  6, ais->type24.b.spare);
324
0
            len = 162 + 6;
325
0
        }
326
0
        break;
327
0
    case 27:    // Long Range AIS Broadcast message
328
0
        ais_addbits(bits,  38,  1, (uint64_t)ais->type27.accuracy);
329
0
        ais_addbits(bits,  39,  1, (uint64_t)ais->type27.raim);
330
0
        ais_addbits(bits,  40,  4, (uint64_t)ais->type27.status);
331
0
        ais_addbits(bits,  44, 18, (uint64_t)ais->type27.lon);
332
0
        ais_addbits(bits,  62, 17, (uint64_t)ais->type27.lat);
333
0
        ais_addbits(bits,  79,  6, (uint64_t)ais->type27.speed);
334
0
        ais_addbits(bits,  85,  9, (uint64_t)ais->type27.course);
335
0
        ais_addbits(bits,  94,  1, (uint64_t)ais->type27.gnss);
336
0
        break;
337
0
    }
338
0
    ais_binary_to_ascii(bits, len);
339
0
    return len;
340
0
}
341
#endif  // AIVDM_ENABLE
342
// vim: set expandtab shiftwidth=4