/src/gpsd/gpsd-3.27.6~dev/drivers/driver_italk.c
Line | Count | Source |
1 | | /* |
2 | | * Driver for the iTalk binary protocol used by FasTrax |
3 | | * |
4 | | * Week counters are not limited to 10 bits. It's unknown what |
5 | | * the firmware is doing to disambiguate them, if anything; it might just |
6 | | * be adding a fixed offset based on a hidden epoch value, in which case |
7 | | * unhappy things will occur on the next rollover. |
8 | | * |
9 | | * This file is Copyright 2010 by the GPSD project |
10 | | * SPDX-License-Identifier: BSD-2-clause |
11 | | * |
12 | | */ |
13 | | |
14 | | #include "../include/gpsd_config.h" // must be before all includes |
15 | | |
16 | | #include <math.h> |
17 | | #include <stdbool.h> |
18 | | #include <stdio.h> |
19 | | #include <string.h> |
20 | | #include <unistd.h> |
21 | | |
22 | | #include "../include/gpsd.h" |
23 | | #if defined(ITRAX_ENABLE) |
24 | | |
25 | | #include "../include/bits.h" |
26 | | #include "../include/driver_italk.h" |
27 | | #include "../include/timespec.h" |
28 | | |
29 | | static gps_mask_t italk_parse(struct gps_device_t *, unsigned char *, size_t); |
30 | | static gps_mask_t decode_itk_navfix(struct gps_device_t *, unsigned char *, |
31 | | size_t); |
32 | | static gps_mask_t decode_itk_prnstatus(struct gps_device_t *, unsigned char *, |
33 | | size_t); |
34 | | static gps_mask_t decode_itk_utcionomodel(struct gps_device_t *, |
35 | | unsigned char *, size_t); |
36 | | static gps_mask_t decode_itk_subframe(struct gps_device_t *, unsigned char *, |
37 | | size_t); |
38 | | |
39 | | // NAVIGATION_MSG, message id 7 |
40 | | static gps_mask_t decode_itk_navfix(struct gps_device_t *session, |
41 | | unsigned char *buf, size_t len) |
42 | 669 | { |
43 | 669 | unsigned short flags, pflags; |
44 | 669 | timespec_t ts_tow; |
45 | 669 | uint32_t tow; // Time of week [ms] |
46 | 669 | char ts_buf[TIMESPEC_LEN]; |
47 | | |
48 | 669 | gps_mask_t mask = 0; |
49 | 669 | if (296 != len) { |
50 | 500 | GPSD_LOG(LOG_PROG, &session->context->errout, |
51 | 500 | "ITALK: bad NAV_FIX (len %zu, should be 296)\n", |
52 | 500 | len); |
53 | 500 | return -1; |
54 | 500 | } |
55 | | |
56 | 169 | flags = (unsigned short) getleu16(buf, 7 + 4); |
57 | | //cflags = (unsigned short) getleu16(buf, 7 + 6); |
58 | 169 | pflags = (unsigned short) getleu16(buf, 7 + 8); |
59 | | |
60 | 169 | session->newdata.status = STATUS_UNK; |
61 | 169 | session->newdata.mode = MODE_NO_FIX; |
62 | 169 | mask = ONLINE_SET | MODE_SET | STATUS_SET | CLEAR_IS; |
63 | | |
64 | | // just bail out if this fix is not marked valid |
65 | 169 | if (0 != (pflags & FIX_FLAG_MASK_INVALID) |
66 | 137 | || 0 == (flags & FIXINFO_FLAG_VALID)) { |
67 | 48 | return mask; |
68 | 48 | } |
69 | | |
70 | 121 | tow = getleu32(buf, 7 + 84); // tow in ms |
71 | 121 | MSTOTS(&ts_tow, tow); |
72 | 121 | session->newdata.time = gpsd_gpstime_resolv(session, |
73 | 121 | (unsigned short) getles16(buf, 7 + 82), ts_tow); |
74 | 121 | mask |= TIME_SET | NTPTIME_IS; |
75 | | |
76 | 121 | session->newdata.ecef.x = (double)(getles32(buf, 7 + 96) / 100.0); |
77 | 121 | session->newdata.ecef.y = (double)(getles32(buf, 7 + 100) / 100.0); |
78 | 121 | session->newdata.ecef.z = (double)(getles32(buf, 7 + 104) / 100.0); |
79 | 121 | session->newdata.ecef.vx = (double)(getles32(buf, 7 + 186) / 1000.0); |
80 | 121 | session->newdata.ecef.vy = (double)(getles32(buf, 7 + 190) / 1000.0); |
81 | 121 | session->newdata.ecef.vz = (double)(getles32(buf, 7 + 194) / 1000.0); |
82 | 121 | mask |= ECEF_SET | VECEF_SET; |
83 | | /* this eph does not look right, badly documented. |
84 | | * let gpsd_error_model() handle it |
85 | | * session->newdata.eph = (double)(getles32(buf, 7 + 252) / 100.0); |
86 | | */ |
87 | 121 | session->newdata.eps = (double)(getles32(buf, 7 + 254) / 100.0); |
88 | | // compute epx/epy in gpsd_error_model(), not here |
89 | 121 | mask |= HERR_SET; |
90 | | |
91 | 121 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) |
92 | 121 | session->gpsdata.satellites_used = |
93 | 121 | (int)MAX(getleu16(buf, 7 + 12), getleu16(buf, 7 + 14)); |
94 | 121 | mask |= USED_IS; |
95 | | |
96 | 121 | if (flags & FIX_CONV_DOP_VALID) { |
97 | 34 | session->gpsdata.dop.hdop = (double)(getleu16(buf, 7 + 56) / 100.0); |
98 | 34 | session->gpsdata.dop.gdop = (double)(getleu16(buf, 7 + 58) / 100.0); |
99 | 34 | session->gpsdata.dop.pdop = (double)(getleu16(buf, 7 + 60) / 100.0); |
100 | 34 | session->gpsdata.dop.vdop = (double)(getleu16(buf, 7 + 62) / 100.0); |
101 | 34 | session->gpsdata.dop.tdop = (double)(getleu16(buf, 7 + 64) / 100.0); |
102 | 34 | mask |= DOP_SET; |
103 | 34 | } |
104 | | |
105 | 121 | if (0 == (pflags & FIX_FLAG_MASK_INVALID) && |
106 | 121 | 0 != (flags & FIXINFO_FLAG_VALID)) { |
107 | 121 | if (pflags & FIX_FLAG_3DFIX) { |
108 | 53 | session->newdata.mode = MODE_3D; |
109 | 68 | } else { |
110 | 68 | session->newdata.mode = MODE_2D; |
111 | 68 | } |
112 | | |
113 | 121 | if (pflags & FIX_FLAG_DGPS_CORRECTION) { |
114 | 84 | session->newdata.status = STATUS_DGPS; |
115 | 84 | } else { |
116 | 37 | session->newdata.status = STATUS_GPS; |
117 | 37 | } |
118 | 121 | } |
119 | | |
120 | 121 | GPSD_LOG(LOG_DATA, &session->context->errout, |
121 | 121 | "NAV_FIX: time=%s, ecef x:%.2f y:%.2f z:%.2f altHAE=%.2f " |
122 | 121 | "speed=%.2f track=%.2f climb=%.2f mode=%d status=%d gdop=%.2f " |
123 | 121 | "pdop=%.2f hdop=%.2f vdop=%.2f tdop=%.2f\n", |
124 | 121 | timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)), |
125 | 121 | session->newdata.ecef.x, |
126 | 121 | session->newdata.ecef.y, session->newdata.ecef.z, |
127 | 121 | session->newdata.altHAE, session->newdata.speed, |
128 | 121 | session->newdata.track, session->newdata.climb, |
129 | 121 | session->newdata.mode, session->newdata.status, |
130 | 121 | session->gpsdata.dop.gdop, session->gpsdata.dop.pdop, |
131 | 121 | session->gpsdata.dop.hdop, session->gpsdata.dop.vdop, |
132 | 121 | session->gpsdata.dop.tdop); |
133 | 121 | return mask; |
134 | 169 | } |
135 | | |
136 | | static gps_mask_t decode_itk_prnstatus(struct gps_device_t *session, |
137 | | unsigned char *buf, size_t len) |
138 | 506 | { |
139 | 506 | gps_mask_t mask = 0; |
140 | 506 | unsigned int i, nsv, nchan, st; |
141 | 506 | uint32_t msec; |
142 | 506 | timespec_t ts_tow; |
143 | 506 | char ts_buf[TIMESPEC_LEN]; |
144 | | |
145 | 506 | if (62 > len) { |
146 | 93 | GPSD_LOG(LOG_PROG, &session->context->errout, |
147 | 93 | "ITALK: runt PRN_STATUS (len=%zu)\n", len); |
148 | 93 | return mask; |
149 | 93 | } |
150 | | |
151 | 413 | msec = getleu32(buf, 7 + 6); |
152 | | |
153 | 413 | MSTOTS(&ts_tow, msec); |
154 | | |
155 | 413 | session->gpsdata.skyview_time = gpsd_gpstime_resolv(session, |
156 | 413 | (unsigned short)getleu16(buf, 7 + 4), ts_tow); |
157 | 413 | gpsd_zero_satellites(&session->gpsdata); |
158 | 413 | nchan = (unsigned int)getleu16(buf, 7 + 50); |
159 | 413 | if (nchan > MAX_NR_VISIBLE_PRNS) { |
160 | 254 | nchan = MAX_NR_VISIBLE_PRNS; |
161 | 254 | } |
162 | 4.71k | for (i = st = nsv = 0; i < nchan; i++) { |
163 | 4.29k | unsigned int off = 7 + 52 + 10 * i; |
164 | 4.29k | unsigned short flags; |
165 | 4.29k | bool used; |
166 | | |
167 | 4.29k | flags = (unsigned short) getleu16(buf, off); |
168 | 4.29k | used = (bool)(flags & PRN_FLAG_USE_IN_NAV); |
169 | 4.29k | session->gpsdata.skyview[st].PRN = |
170 | 4.29k | (short)(getleu16(buf, off + 4) & 0xff); |
171 | 4.29k | session->gpsdata.skyview[st].elevation = |
172 | 4.29k | (double)(getles16(buf, off + 6) & 0xff); |
173 | 4.29k | session->gpsdata.skyview[st].azimuth = |
174 | 4.29k | (double)(getles16(buf, off + 8) & 0xff); |
175 | 4.29k | session->gpsdata.skyview[st].ss = |
176 | 4.29k | (double)(getleu16(buf, off + 2) & 0xff); |
177 | 4.29k | session->gpsdata.skyview[st].used = used; |
178 | 4.29k | if (session->gpsdata.skyview[st].PRN > 0) { |
179 | 1.87k | st++; |
180 | 1.87k | if (used) { |
181 | 959 | nsv++; |
182 | 959 | } |
183 | 1.87k | } |
184 | 4.29k | } |
185 | 413 | session->gpsdata.satellites_visible = (int)st; |
186 | 413 | if (MAXCHANNELS < session->gpsdata.satellites_visible) { |
187 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
188 | 0 | "PRN_STTUS: too many satellites %d\n", |
189 | 0 | session->gpsdata.satellites_visible); |
190 | 0 | session->gpsdata.satellites_visible = MAXCHANNELS; |
191 | 0 | } |
192 | 413 | session->gpsdata.satellites_used = (int)nsv; |
193 | 413 | mask = USED_IS | SATELLITE_SET; |
194 | | |
195 | 413 | GPSD_LOG(LOG_DATA, &session->context->errout, |
196 | 413 | "PRN_STATUS: time=%s visible=%d used=%d " |
197 | 413 | "mask={USED|SATELLITE}\n", |
198 | 413 | timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)), |
199 | 413 | session->gpsdata.satellites_visible, |
200 | 413 | session->gpsdata.satellites_used); |
201 | | |
202 | 413 | return mask; |
203 | 506 | } |
204 | | |
205 | | static gps_mask_t decode_itk_utcionomodel(struct gps_device_t *session, |
206 | | unsigned char *buf, size_t len) |
207 | 664 | { |
208 | 664 | int leap; |
209 | 664 | unsigned short flags; |
210 | 664 | timespec_t ts_tow; |
211 | 664 | uint32_t tow; // Time of week [ms] |
212 | 664 | char ts_buf[TIMESPEC_LEN]; |
213 | | |
214 | 664 | if (64 != len) { |
215 | 415 | GPSD_LOG(LOG_PROG, &session->context->errout, |
216 | 415 | "ITALK: bad UTC_IONO_MODEL (len %zu, should be 64)\n", |
217 | 415 | len); |
218 | 415 | return 0; |
219 | 415 | } |
220 | | |
221 | 249 | flags = (unsigned short) getleu16(buf, 7); |
222 | 249 | if (0 == (flags & UTC_IONO_MODEL_UTCVALID)) { |
223 | 61 | return 0; |
224 | 61 | } |
225 | | |
226 | 188 | leap = (int)getleu16(buf, 7 + 24); |
227 | 188 | if (session->context->leap_seconds < leap) { |
228 | 50 | session->context->leap_seconds = leap; |
229 | 50 | } |
230 | | |
231 | 188 | tow = getleu32(buf, 7 + 38); // in ms |
232 | 188 | MSTOTS(&ts_tow, tow); |
233 | 188 | session->newdata.time = gpsd_gpstime_resolv(session, |
234 | 188 | (unsigned short) getleu16(buf, 7 + 36), ts_tow); |
235 | 188 | GPSD_LOG(LOG_DATA, &session->context->errout, |
236 | 188 | "UTC_IONO_MODEL: time=%s mask={TIME}\n", |
237 | 188 | timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf))); |
238 | 188 | return TIME_SET | NTPTIME_IS; |
239 | 249 | } |
240 | | |
241 | | static gps_mask_t decode_itk_subframe(struct gps_device_t *session, |
242 | | unsigned char *buf, size_t len) |
243 | 2.26k | { |
244 | 2.26k | unsigned short flags, prn, sf; |
245 | 2.26k | unsigned int i; |
246 | 2.26k | uint32_t words[10]; |
247 | | |
248 | 2.26k | if (64 != len) { |
249 | 119 | GPSD_LOG(LOG_PROG, &session->context->errout, |
250 | 119 | "ITALK: bad SUBFRAME (len %zu, should be 64)\n", len); |
251 | 119 | return 0; |
252 | 119 | } |
253 | | |
254 | 2.15k | flags = (unsigned short) getleu16(buf, 7 + 4); |
255 | 2.15k | prn = (unsigned short) getleu16(buf, 7 + 6); |
256 | 2.15k | sf = (unsigned short) getleu16(buf, 7 + 8); |
257 | 2.15k | GPSD_LOG(LOG_PROG, &session->context->errout, |
258 | 2.15k | "iTalk 50B SUBFRAME prn %u sf %u - decode %s %s\n", |
259 | 2.15k | prn, sf, |
260 | 2.15k | (flags & SUBFRAME_WORD_FLAG_MASK) ? "error" : "ok", |
261 | 2.15k | (flags & SUBFRAME_GPS_PREAMBLE_INVERTED) ? "(inverted)" : ""); |
262 | 2.15k | if (flags & SUBFRAME_WORD_FLAG_MASK) { |
263 | 67 | return 0; // don't try decode an erroneous packet |
264 | 67 | } |
265 | | |
266 | | /* |
267 | | * Timo says "SUBRAME message contains decoded navigation message subframe |
268 | | * words with parity checking done but parity bits still present." |
269 | | */ |
270 | 22.9k | for (i = 0; i < 10; i++) { |
271 | 20.8k | words[i] = (uint32_t)(getleu32(buf, 7 + 14 + 4 * i) >> 6) & 0xffffff; |
272 | 20.8k | } |
273 | | |
274 | 2.08k | return gpsd_interpret_subframe(session, GNSSID_GPS, prn, words); |
275 | 2.15k | } |
276 | | |
277 | | static gps_mask_t decode_itk_pseudo(struct gps_device_t *session, |
278 | | unsigned char *buf, size_t len) |
279 | 335 | { |
280 | 335 | unsigned short flags, n, i; |
281 | 335 | unsigned int tow; // time of week, in ms |
282 | 335 | timespec_t ts_tow; |
283 | | |
284 | 335 | n = (unsigned short) getleu16(buf, 7 + 4); |
285 | 335 | if (1 > n || |
286 | 256 | MAXCHANNELS < n ) { |
287 | 170 | GPSD_LOG(LOG_INF, &session->context->errout, |
288 | 170 | "ITALK: bad PSEUDO channel count\n"); |
289 | 170 | return 0; |
290 | 170 | } |
291 | | |
292 | 165 | if ((size_t)((n + 1) * 36) != len) { |
293 | 165 | GPSD_LOG(LOG_WARN, &session->context->errout, |
294 | 165 | "ITALK: bad PSEUDO len %zu\n", len); |
295 | 165 | return 0; |
296 | 165 | } |
297 | | |
298 | 0 | GPSD_LOG(LOG_PROG, &session->context->errout, "iTalk PSEUDO [%u]\n", n); |
299 | 0 | flags = getleu16(buf, 7 + 6); |
300 | 0 | if ((flags & 0x3) != 0x3) { |
301 | 0 | return 0; // bail if measurement time not valid. |
302 | 0 | } |
303 | | |
304 | 0 | tow = getleu32(buf, 7 + 38); |
305 | 0 | MSTOTS(&ts_tow, tow); |
306 | 0 | session->newdata.time = gpsd_gpstime_resolv(session, |
307 | 0 | (unsigned short)getleu16((char *)buf, 7 + 8), ts_tow); |
308 | |
|
309 | 0 | session->gpsdata.raw.mtime = session->newdata.time; |
310 | | |
311 | | // this is so we can tell which never got set |
312 | 0 | for (i = 0; i < MAXCHANNELS; i++) { |
313 | 0 | session->gpsdata.raw.meas[i].svid = 0; |
314 | 0 | } |
315 | 0 | for (i = 0; i < n; i++){ |
316 | 0 | session->gpsdata.skyview[i].PRN = |
317 | 0 | getleu16(buf, 7 + 26 + (i*36)) & 0xff; |
318 | 0 | session->gpsdata.skyview[i].ss = |
319 | 0 | getleu16(buf, 7 + 26 + (i*36 + 2)) & 0x3f; |
320 | 0 | session->gpsdata.raw.meas[i].satstat = |
321 | 0 | getleu32(buf, 7 + 26 + (i*36 + 4)); |
322 | 0 | session->gpsdata.raw.meas[i].pseudorange = |
323 | 0 | getled64((char *)buf, 7 + 26 + (i*36 + 8)); |
324 | 0 | session->gpsdata.raw.meas[i].doppler = |
325 | 0 | getled64((char *)buf, 7 + 26 + (i*36 + 16)); |
326 | 0 | session->gpsdata.raw.meas[i].carrierphase = |
327 | 0 | getleu16(buf, 7 + 26 + (i*36 + 28)); |
328 | |
|
329 | 0 | session->gpsdata.raw.meas[i].codephase = NAN; |
330 | 0 | session->gpsdata.raw.meas[i].deltarange = NAN; |
331 | 0 | } |
332 | | // return RAW_IS; The above decode does not give reasonable results |
333 | 0 | return 0; // do not report valid until decode is fixed |
334 | 0 | } |
335 | | |
336 | | static gps_mask_t italk_parse(struct gps_device_t *session, |
337 | | unsigned char *buf, size_t len) |
338 | 7.97k | { |
339 | 7.97k | unsigned int type; |
340 | 7.97k | gps_mask_t mask = 0; |
341 | | |
342 | 7.97k | if (0 == len) { |
343 | 0 | return 0; |
344 | 0 | } |
345 | | |
346 | 7.97k | type = (unsigned int) getub(buf, 4); |
347 | | // we may need to dump the raw packet |
348 | 7.97k | GPSD_LOG(LOG_RAW, &session->context->errout, |
349 | 7.97k | "raw italk packet type 0x%02x\n", type); |
350 | | |
351 | 7.97k | session->cycle_end_reliable = true; |
352 | | |
353 | 7.97k | switch (type) { |
354 | 669 | case ITALK_NAV_FIX: |
355 | 669 | GPSD_LOG(LOG_DATA, &session->context->errout, |
356 | 669 | "iTalk NAV_FIX len %zu\n", len); |
357 | 669 | mask = decode_itk_navfix(session, buf, len) | (CLEAR_IS | REPORT_IS); |
358 | 669 | break; |
359 | 506 | case ITALK_PRN_STATUS: |
360 | 506 | GPSD_LOG(LOG_DATA, &session->context->errout, |
361 | 506 | "iTalk PRN_STATUS len %zu\n", len); |
362 | 506 | mask = decode_itk_prnstatus(session, buf, len); |
363 | 506 | break; |
364 | 664 | case ITALK_UTC_IONO_MODEL: |
365 | 664 | GPSD_LOG(LOG_DATA, &session->context->errout, |
366 | 664 | "iTalk UTC_IONO_MODEL len %zu\n", len); |
367 | 664 | mask = decode_itk_utcionomodel(session, buf, len); |
368 | 664 | break; |
369 | | |
370 | 67 | case ITALK_ACQ_DATA: |
371 | 67 | GPSD_LOG(LOG_DATA, &session->context->errout, |
372 | 67 | "iTalk ACQ_DATA len %zu\n", len); |
373 | 67 | break; |
374 | 153 | case ITALK_TRACK: |
375 | 153 | GPSD_LOG(LOG_DATA, &session->context->errout, |
376 | 153 | "iTalk TRACK len %zu\n", len); |
377 | 153 | break; |
378 | 335 | case ITALK_PSEUDO: |
379 | 335 | GPSD_LOG(LOG_DATA, &session->context->errout, |
380 | 335 | "iTalk PSEUDO len %zu\n", len); |
381 | 335 | mask = decode_itk_pseudo(session, buf, len); |
382 | 335 | break; |
383 | 116 | case ITALK_RAW_ALMANAC: |
384 | 116 | GPSD_LOG(LOG_DATA, &session->context->errout, |
385 | 116 | "iTalk RAW_ALMANAC len %zu\n", len); |
386 | 116 | break; |
387 | 71 | case ITALK_RAW_EPHEMERIS: |
388 | 71 | GPSD_LOG(LOG_DATA, &session->context->errout, |
389 | 71 | "iTalk RAW_EPHEMERIS len %zu\n", len); |
390 | 71 | break; |
391 | 2.26k | case ITALK_SUBFRAME: |
392 | 2.26k | mask = decode_itk_subframe(session, buf, len); |
393 | 2.26k | break; |
394 | 64 | case ITALK_BIT_STREAM: |
395 | 64 | GPSD_LOG(LOG_DATA, &session->context->errout, |
396 | 64 | "iTalk BIT_STREAM len %zu\n", len); |
397 | 64 | break; |
398 | | |
399 | 66 | case ITALK_AGC: |
400 | 191 | case ITALK_SV_HEALTH: |
401 | 275 | case ITALK_PRN_PRED: |
402 | 345 | case ITALK_FREQ_PRED: |
403 | 420 | case ITALK_DBGTRACE: |
404 | 515 | case ITALK_START: |
405 | 582 | case ITALK_STOP: |
406 | 671 | case ITALK_SLEEP: |
407 | 746 | case ITALK_STATUS: |
408 | 822 | case ITALK_ITALK_CONF: |
409 | 917 | case ITALK_SYSINFO: |
410 | 1.00k | case ITALK_ITALK_TASK_ROUTE: |
411 | 1.08k | case ITALK_PARAM_CTRL: |
412 | 1.15k | case ITALK_PARAMS_CHANGED: |
413 | 1.20k | case ITALK_START_COMPLETED: |
414 | 1.27k | case ITALK_STOP_COMPLETED: |
415 | 1.34k | case ITALK_LOG_CMD: |
416 | 1.52k | case ITALK_SYSTEM_START: |
417 | 1.67k | case ITALK_STOP_SEARCH: |
418 | 1.81k | case ITALK_SEARCH: |
419 | 1.93k | case ITALK_PRED_SEARCH: |
420 | 2.01k | case ITALK_SEARCH_DONE: |
421 | 2.08k | case ITALK_TRACK_DROP: |
422 | 2.15k | case ITALK_TRACK_STATUS: |
423 | 2.22k | case ITALK_HANDOVER_DATA: |
424 | 2.29k | case ITALK_CORE_SYNC: |
425 | 2.37k | case ITALK_WAAS_RAWDATA: |
426 | 2.45k | case ITALK_ASSISTANCE: |
427 | 2.53k | case ITALK_PULL_FIX: |
428 | 2.62k | case ITALK_MEMCTRL: |
429 | 2.69k | case ITALK_STOP_TASK: |
430 | 2.69k | GPSD_LOG(LOG_DATA, &session->context->errout, |
431 | 2.69k | "iTalk not processing packet: id 0x%02x length %zu\n", |
432 | 2.69k | type, len); |
433 | 2.69k | break; |
434 | 369 | default: |
435 | 369 | GPSD_LOG(LOG_DATA, &session->context->errout, |
436 | 7.97k | "iTalk unknown packet: id 0x%02x length %zu\n", |
437 | 7.97k | type, len); |
438 | 7.97k | } |
439 | | |
440 | 7.97k | return mask | ONLINE_SET; |
441 | 7.97k | } |
442 | | |
443 | | |
444 | | static gps_mask_t italk_parse_input(struct gps_device_t *session) |
445 | 7.97k | { |
446 | 7.97k | if (ITALK_PACKET == session->lexer.type) { |
447 | 7.97k | return italk_parse(session, session->lexer.outbuffer, |
448 | 7.97k | session->lexer.outbuflen); |
449 | 7.97k | } |
450 | 0 | if (NMEA_PACKET == session->lexer.type) { |
451 | 0 | return nmea_parse((char *)session->lexer.outbuffer, session); |
452 | 0 | } |
453 | 0 | return 0; |
454 | 0 | } |
455 | | |
456 | | #ifdef __UNUSED__ |
457 | | // send a "ping". it may help us detect an itrax more quickly |
458 | | static void italk_ping(struct gps_device_t *session) |
459 | | { |
460 | | char *ping = "<?>"; |
461 | | (void)gpsd_write(session, ping, 3); |
462 | | } |
463 | | #endif // __UNUSED__ |
464 | | |
465 | | // *INDENT-OFF* |
466 | | const struct gps_type_t driver_italk = |
467 | | { |
468 | | .type_name = "iTalk", // full name of type |
469 | | .packet_type = ITALK_PACKET, // associated lexer packet type |
470 | | .flags = DRIVER_STICKY, // no rollover or other flags |
471 | | .trigger = NULL, // recognize the type |
472 | | .channels = 12, // consumer-grade GPS |
473 | | .probe_detect = NULL, // how to detect at startup time |
474 | | .get_packet = packet_get1, // use generic packet grabber |
475 | | .parse_packet = italk_parse_input,// parse message packets |
476 | | .rtcm_writer = gpsd_write, // send RTCM data straight |
477 | | .init_query = NULL, // non-perturbing initial query |
478 | | .event_hook = NULL, // lifetime event handler |
479 | | .speed_switcher = NULL, // no speed switcher |
480 | | .mode_switcher = NULL, // no mode switcher |
481 | | .rate_switcher = NULL, // no sample-rate switcher |
482 | | .min_cycle.tv_sec = 1, // not relevant, no rate switch |
483 | | .min_cycle.tv_nsec = 0, // not relevant, no rate switch |
484 | | .control_send = NULL, // no control string sender |
485 | | .time_offset = NULL, // no method for NTP fudge factor |
486 | | }; |
487 | | // *INDENT-ON* |
488 | | #endif // defined(ITRAX_ENABLE) |
489 | | // vim: set expandtab shiftwidth=4 |