/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 |