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