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