summaryrefslogtreecommitdiff
path: root/gpsd.h-tail
blob: 75c868cc9671f1d31263e9ba2cf6610ae7f3d94e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
/* Feature configuration switches end here */

/* $Id$ */

/* Some internal capabilities depend on which drivers we're compiling. */
#ifdef EARTHMATE_ENABLE
#define ZODIAC_ENABLE	
#endif
#if defined(ZODIAC_ENABLE) || defined(SIRF_ENABLE) || defined(GARMIN_ENABLE) || defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(ITRAX_ENABLE) || defined(UBX_ENABLE) || defined(SUPERSTAR2_ENABLE) || defined(ONCORE_ENABLE)
#define BINARY_ENABLE	
#endif
#if defined(TRIPMATE_ENABLE) || defined(BINARY_ENABLE)
#define NON_NMEA_ENABLE	
#endif

/* First, declarations for the packet layer... */

/* XXX Some receivers (TN-200, GSW 2.3.2) emit oversized sentences (>82) */
#define NMEA_MAX	86		/* max length of NMEA sentence */
#define NMEA_BIG_BUF	(2*NMEA_MAX+1)	/* longer than longest NMEA sentence */

/* a few bits of ISGPS magic */
enum isgpsstat_t {
    ISGPS_NO_SYNC, ISGPS_SYNC, ISGPS_SKIP, ISGPS_MESSAGE,
};
#define ISGPS_ERRLEVEL_BASE	5

#define RTCM_MAX	(RTCM2_WORDS_MAX * sizeof(isgps30bits_t))

/*
 * The packet buffers need to be as long than the longest packet we
 * expect to see in any protocol, because we have to be able to hold
 * an entire packet for checksumming...
 * First we thought it had to be big enough for a SiRF Measured Tracker
 * Data packet (188 bytes). Then it had to be big enough for a UBX SVINFO
 * packet (206 bytes). Now it turns out that a couple of ITALK messages are
 * over 512 bytes. I know we like verbose output, but this is ridiculous.
 */
#define MAX_PACKET_LENGTH	516	/* 7 + 506 + 3 */

struct gps_packet_t {
    /* packet-getter internals */
    int	type;
#define BAD_PACKET	-1
#define COMMENT_PACKET	0
#define NMEA_PACKET	1
#define SIRF_PACKET	2
#define ZODIAC_PACKET	3
#define TSIP_PACKET	4
#define EVERMORE_PACKET	5
#define ITALK_PACKET	6
#define GARMIN_PACKET	7
#define NAVCOM_PACKET	8
#define RTCM2_PACKET	9
#define RTCM3_PACKET	10
#define UBX_PACKET	11
#define GARMINTXT_PACKET	12
#define SUPERSTAR2_PACKET	13
#define AIVDM_PACKET	14
#define ONCORE_PACKET	15
#define TEXTUAL_PACKET_TYPE(n)	((n)==NMEA_PACKET||(n)==GARMINTXT_PACKET||(n)==COMMENT_PACKET||(n)==AIVDM_PACKET)
    unsigned int state;
    size_t length;
    unsigned char inbuffer[MAX_PACKET_LENGTH*2+1];
    size_t inbuflen;
    unsigned /*@observer@*/char *inbufptr;
    /* outbuffer needs to be able to hold 4 GPGSV records at once */
    unsigned char outbuffer[MAX_PACKET_LENGTH*2+1];
    size_t outbuflen;
    unsigned long char_counter;		/* count characters processed */
    unsigned long retry_counter;	/* count sniff retries */
    unsigned counter;			/* packets since last driver switch */
    /*
     * This is not conditionalized on RTCM104_ENABLE because we need to
     * be able to build gpsdecode even when RTCM support is not
     * configured in the daemon.
     */
    struct {
	/* ISGPS200 decoding */
	bool            locked;
	int             curr_offset;
	isgps30bits_t   curr_word;
	isgps30bits_t   buf[RTCM2_WORDS_MAX];
	unsigned int    bufindex;
    } isgps;
};

extern void packet_reset(struct gps_packet_t *);
extern void packet_pushback(struct gps_packet_t *);
extern void packet_parse(struct gps_packet_t *);
extern ssize_t packet_get(int, struct gps_packet_t *);
extern int packet_sniff(struct gps_packet_t *);
#define packet_buffered_input(lexer) ((lexer)->inbuffer + (lexer)->inbuflen - (lexer)->inbufptr)

extern void isgps_init(/*@out@*/struct gps_packet_t *);
enum isgpsstat_t isgps_decode(struct gps_packet_t *, 
			      bool (*preamble_match)(isgps30bits_t *),
			      bool (*length_check)(struct gps_packet_t *),
			      size_t,
			      unsigned int);
extern unsigned int isgps_parity(isgps30bits_t);
extern void isgps_output_magnavox(isgps30bits_t *, unsigned int, FILE *);

extern enum isgpsstat_t rtcm2_decode(struct gps_packet_t *, unsigned int);
extern void rtcm2_dump(struct rtcm2_t *, /*@out@*/char[], size_t);
extern int rtcm2_undump(/*@out@*/struct rtcm2_t *, char *);
extern void rtcm2_unpack(/*@out@*/struct rtcm2_t *, char *);
extern bool rtcm2_repack(struct rtcm2_t *, isgps30bits_t *);
extern void rtcm2_output_magnavox(isgps30bits_t *, FILE *);

extern void rtcm3_unpack(/*@out@*/struct rtcm3_t *, char *);
extern void rtcm3_dump(struct rtcm3_t *rtcm, FILE *);

/* Next, declarations for the core library... */

/* factors for converting among confidence interval units */
#define CEP50_SIGMA	1.18
#define DRMS_SIGMA	1.414
#define CEP95_SIGMA	2.45

/* this is where we choose the confidence level to use in reports */
#define GPSD_CONFIDENCE	CEP95_SIGMA

#define NTPSHMSEGS	4		/* number of NTP SHM segments */

struct subscriber_t {
    int fd;			/* client file descriptor. -1 if unused */
    double active;		/* when subscriber last polled for data */
    bool tied;				/* client set device with F */
    bool watcher;			/* is client in watcher mode? */
    int raw;				/* is client in raw mode? */
    enum {GPS,RTCM104v2,ANY} requires;	/* type of device requested */
    struct gps_fix_t fixbuffer;		/* info to report to the client */
    struct gps_fix_t oldfix;		/* previous fix for error modeling */
    enum {casoc=0, nocasoc=1} buffer_policy;	/* buffering policy */
    struct gps_device_t *device;	/* device subscriber listens to */
};

struct gps_context_t {
    int valid;				/* member validity flags */
    bool readonly;			/* if true, never write to device */
#define LEAP_SECOND_VALID	0x01	/* we have or don't need correction */
    /* DGPSIP status */
    bool sentdgps;			/* have we sent a DGPS report? */
    enum { netgnss_none, netgnss_dgpsip, netgnss_ntrip, netgnss_remotegpsd } netgnss_service;	/* type of GNSS service */
    int fixcnt;				/* count of good fixes seen */
    int dsock;			        /* socket to DGPSIP server/Ntrip caster */
    void *netgnss_privdata;		/* DGNSS service specific data */
    ssize_t rtcmbytes;			/* byte count of last RTCM104 report */
    char rtcmbuf[RTCM_MAX];		/* last RTCM104 report */
    double rtcmtime;			/* timestamp of last RTCM104 report */ 
    /* timekeeping */
    int leap_seconds;			/* Unix seconds to UTC */
    int century;			/* for NMEA-only devices without ZDA */
#ifdef NTPSHM_ENABLE
    bool enable_ntpshm;
    /*@reldef@*/struct shmTime *shmTime[NTPSHMSEGS];
    bool shmTimeInuse[NTPSHMSEGS];
# ifdef PPS_ENABLE
    bool shmTimePPS;
# endif /* PPS_ENABLE */
#endif /* NTPSHM_ENABLE */
};

struct aivdm_context_t {
    /* hold context for decoding AIDVM packet sequences */
    int part, await;		/* for tracking AIDVM parts in a multipart sequence */
    unsigned char *field[NMEA_MAX];
    unsigned char fieldcopy[NMEA_MAX+1];
    unsigned char bits[2048];
    size_t bitlen;
    struct ais_t decoded;
};

struct gps_device_t;

#if defined (HAVE_SYS_TERMIOS_H)
#include <sys/termios.h>
#else
#if defined (HAVE_TERMIOS_H)
#include <termios.h>
#endif
#endif

#define MODE_NMEA	0
#define MODE_BINARY	1

struct gps_type_t {
/* GPS method table, describes how to talk to a particular GPS type */
    /*@observer@*/char *type_name;
    int packet_type;
    /*@observer@*//*@null@*/char *trigger;
    int channels;
    /*@null@*/bool (*probe_detect)(struct gps_device_t *session);
    /*@null@*/void (*probe_wakeup)(struct gps_device_t *session);
    /*@null@*/void (*probe_subtype)(struct gps_device_t *session, unsigned int seq);
    /*@null@*/ssize_t (*get_packet)(struct gps_device_t *session);
    /*@null@*/gps_mask_t (*parse_packet)(struct gps_device_t *session);
    /*@null@*/ssize_t (*rtcm_writer)(struct gps_device_t *session, char *rtcmbuf, size_t rtcmbytes);
#ifdef ALLOW_CONTROLSEND
    /*@null@*/ssize_t (*control_send)(struct gps_device_t *session, char *buf, size_t buflen);
#endif /* ALLOW_CONTROLSEND */
#ifdef ALLOW_RECONFIGURE 
    /*@null@*/void (*configurator)(struct gps_device_t *session, unsigned int seq);
    /*@null@*/bool (*speed_switcher)(struct gps_device_t *session, 
				     speed_t speed, char parity, int stopbits);
    /*@null@*/void (*mode_switcher)(struct gps_device_t *session, int mode);
    /*@null@*/bool (*rate_switcher)(struct gps_device_t *session, double rate);
    double min_cycle;
    /*@null@*/void (*revert)(struct gps_device_t *session);
#endif /* ALLOW_RECONFIGURE */
    /*@null@*/void (*wrapup)(struct gps_device_t *session);
};

struct gps_device_t {
/* session object, encapsulates all global state */
    struct gps_data_t gpsdata;
    /*@relnull@*/const struct gps_type_t *device_type;
    struct gps_context_t	*context;
#ifdef ALLOW_RECONFIGURE
    bool enable_reconfigure;		/* OK to hack GPS settings? */ 
#endif /* ALLOW_RECONFIGURE */
    double rtcmtime;	/* timestamp of last RTCM104 correction to GPS */
    struct termios ttyset, ttyset_old;
    unsigned int baudindex;
    int saved_baud;
    struct gps_packet_t packet;
    char subtype[64];			/* firmware version or subtype ID */
    double poll_times[FD_SETSIZE];	/* last daemon poll time */
    double releasetime;
#ifdef NTPSHM_ENABLE
    int shmindex;
    double last_fixtime;		/* so updates happen once */
# ifdef PPS_ENABLE
    int shmTimeP;
# endif /* PPS_ENABLE */
#endif /* NTPSHM_ENABLE */
    double mag_var;			/* Magnetic variation in degrees */  
    bool back_to_nmea;			/* back to NMEA on revert? */
    char msgbuf[MAX_PACKET_LENGTH*2+1];	/* command message buffer for sends */
    size_t msgbuflen;
    /*
     * The rest of this structure is driver-specific private storage.
     * Because the Garmin driver uses a long buffer, you can have
     * up to 4096+12 bytes of private storage in your own union member
     * without making this structure larger or changing the API at all.
     */
    union {
#ifdef NMEA_ENABLE
	struct {
	    int part, await;		/* for tracking GSV parts */
	    struct tm date;
	    double subseconds;
	    char *field[NMEA_MAX];
	    unsigned char fieldcopy[NMEA_MAX+1];
#ifdef GPSCLOCK_ENABLE
	    bool ignore_trailing_edge;
#endif /* GPSCLOCK_ENABLE */
	} nmea;
#endif /* NMEA_ENABLE */
#ifdef AIVDM_ENABLE
	struct aivdm_context_t aivdm;
#endif /* AIVDM_ENABLE */
#ifdef BINARY_ENABLE
#ifdef SIRF_ENABLE
	struct {
	    unsigned int driverstate;	/* for private use */
#define SIRF_LT_231	0x01		/* SiRF at firmware rev < 231 */
#define SIRF_EQ_231     0x02            /* SiRF at firmware rev == 231 */
#define SIRF_GE_232     0x04            /* SiRF at firmware rev >= 232 */
#define UBLOX   	0x08		/* uBlox firmware with packet 0x62 */
	    unsigned long satcounter;
	    unsigned int time_seen;
#define TIME_SEEN_GPS_1	0x01	/* Seen GPS time variant 1? */
#define TIME_SEEN_GPS_2	0x02	/* Seen GPS time variant 2? */
#define TIME_SEEN_UTC_1	0x04	/* Seen UTC time variant 1? */
#define TIME_SEEN_UTC_2	0x08	/* Seen UTC time variant 2? */
#ifdef ALLOW_RECONFIGURE
	    /* fields from Navigation Parameters message */
	    bool nav_parameters_seen;	/* have we seen one? */
	    unsigned char altitude_hold_mode;
	    unsigned char altitude_hold_source;
	    int16_t altitude_source_input;
	    unsigned char degraded_mode;
	    unsigned char degraded_timeout;
	    unsigned char dr_timeout;
	    unsigned char track_smooth_mode;
#endif /* ALLOW_RECONFIGURE */
	} sirf;
#endif /* SIRF_ENABLE */
#ifdef SUPERSTAR2_ENABLE
	struct {
	    unsigned short gps_week;
	    time_t last_iono;
	} superstar2;
#endif /* SUPERSTAR2_ENABLE */
#ifdef TSIP_ENABLE
	struct {
	    int16_t gps_week;		/* Current GPS week number */
	    bool superpkt;		/* Super Packet mode requested */
	    time_t last_41;		/* Timestamps for packet requests */
	    time_t last_48;
	    time_t last_5c;
	    time_t last_6d;
	    time_t last_46;
	    unsigned int parity, stopbits; /* saved RS232 link parameters */
	} tsip;
#endif /* TSIP_ENABLE */
#ifdef GARMIN_ENABLE	/* private housekeeping stuff for the Garmin driver */
	struct {
	    unsigned char Buffer[4096+12];	/* Garmin packet buffer */
	    size_t BufferLen;		/* current GarminBuffer Length */
	} garmin;
#endif /* GARMIN_ENABLE */
#ifdef ZODIAC_ENABLE	/* private housekeeping stuff for the Zodiac driver */
	struct {
	    unsigned short sn;		/* packet sequence number */
	    /*
	     * Zodiac chipset channel status from PRWIZCH. Keep it so
	     * raw-mode translation of Zodiac binary protocol can send
	     * it up to the client.
	     */
#define ZODIAC_CHANNELS	12
	    unsigned int Zs[ZODIAC_CHANNELS];	/* satellite PRNs */
	    unsigned int Zv[ZODIAC_CHANNELS];	/* signal values (0-7) */
	} zodiac;
#endif /* ZODIAC_ENABLE */
#ifdef UBX_ENABLE
	struct {
            unsigned int gps_week;
    	} ubx;
#endif /* UBX_ENABLE */
#ifdef NAVCOM_ENABLE
	struct {
	    u_int8_t physical_port;
	    bool warned;
	} navcom;
#endif /* NAVCOM_ENABLE */
	/*
	 * This is not conditionalized on RTCM104_ENABLE because we need to
	 * be able to build gpsdecode even when RTCM support is not
	 * configured in the daemon.  It doesn't take up extra space.
	 */
	struct {
	    /* ISGPS200 decoding */
	    bool            locked;
	    int             curr_offset;
	    isgps30bits_t   curr_word;
	    isgps30bits_t   buf[RTCM2_WORDS_MAX];
	    unsigned int    bufindex;
	} isgps;
#endif /* BINARY_ENABLE */
    } driver;
};

/* logging levels */
#define LOG_ERROR 	0	/* errors, display always */
#define LOG_SHOUT	0	/* not an error but we should always see it */
#define LOG_WARN	1	/* not errors but may indicate a problem */
#define LOG_INF 	2	/* key informative messages */
#define LOG_PROG	3	/* progress messages */
#define LOG_IO  	4	/* IO to and from devices */
#define LOG_RAW 	5	/* raw low-level I/O */

#define IS_HIGHEST_BIT(v,m)	(v & ~((m<<1)-1))==0
/*
 * This hackery is intended to support SBCs that are resource-limited
 * and only need to support one or a few devices each.  It avoids the
 * space overhead of allocating thousands of unused device structures.
 * This array fills from the bottom, so as an extreme case you could
 * reduce LIMITED_MAX_DEVICES to 1.
 */
#ifdef LIMITED_MAX_DEVICES
#define MAXDEVICES	LIMITED_MAX_DEVICES
#else
/* we used to make this FD_SETSIZE, but that cost 14MB of wasted core! */
#define MAXDEVICES	4
#endif

#ifdef LIMITED_MAX_CLIENTS
#define MAXSUBSCRIBERS LIMITED_MAX_CLIENTS
#else
/* subscriber structure is small enough that there's no need to limit this */
#define MAXSUBSCRIBERS	FD_SETSIZE
#endif
#define sub_index(s) (int)(s - subscribers)
#define allocated_channel(chp)	 ((chp)->gpsdata.gps_device[0] != '\0')
#define free_channel(chp)	 (chp)->gpsdata.gps_device[0] = '\0'
#define initialized_channel(chp) ((chp)->context != NULL)


/* here are the available GPS drivers */
extern const struct gps_type_t **gpsd_drivers;

/* gpsd library internal prototypes */
extern gps_mask_t nmea_parse_input(struct gps_device_t *);
extern gps_mask_t nmea_parse(char *, struct gps_device_t *);
extern ssize_t nmea_write(struct gps_device_t *session, char *buf, size_t len);
extern ssize_t nmea_send(struct gps_device_t *session, const char *, ... );
extern void nmea_add_checksum(char *);

ssize_t generic_get(struct gps_device_t *);
ssize_t pass_rtcm(struct gps_device_t *, char *, size_t);

extern gps_mask_t sirf_parse(struct gps_device_t *, unsigned char *, size_t);
extern gps_mask_t evermore_parse(struct gps_device_t *, unsigned char *, size_t);
extern gps_mask_t navcom_parse(struct gps_device_t *, unsigned char *, size_t);
extern gps_mask_t garmin_ser_parse(struct gps_device_t *);
extern gps_mask_t garmintxt_parse(struct gps_device_t *);
extern gps_mask_t aivdm_parse(struct gps_device_t *);

extern bool netgnss_uri_check(char *);
extern int netgnss_uri_open(struct gps_context_t *, char *);
extern int netgnss_poll(struct gps_context_t *);
extern void netgnss_report(struct gps_device_t *);
extern void netgnss_autoconnect(struct gps_context_t *, double, double);

extern void rtcm_relay(struct gps_device_t *);
extern void rtcm2_output_mag(isgps30bits_t *, FILE *);

extern int dgpsip_open(struct gps_context_t *, const char *);
extern void dgpsip_report(struct gps_device_t *);
extern void dgpsip_autoconnect(struct gps_context_t *, 
			       double, double, const char *);
extern int ntrip_open(struct gps_context_t *, char *);
extern void ntrip_report(struct gps_device_t *);
extern int remotegpsd_open(struct gps_context_t *, char *);
extern void remotegpsd_report(struct gps_device_t *);

extern void gpsd_tty_init(struct gps_device_t *);
extern int gpsd_open(struct gps_device_t *);
extern bool gpsd_set_raw(struct gps_device_t *);
extern ssize_t gpsd_write(struct gps_device_t *, void const *, size_t);
extern bool gpsd_next_hunt_setting(struct gps_device_t *);
extern int gpsd_switch_driver(struct gps_device_t *, char *);
extern void gpsd_set_speed(struct gps_device_t *, speed_t, unsigned char, unsigned int);
extern speed_t gpsd_get_speed(struct termios *);
extern void gpsd_assert_sync(struct gps_device_t *);
extern void gpsd_close(struct gps_device_t *);

extern void gpsd_zero_satellites(/*@out@*/struct gps_data_t *sp)/*@modifies sp@*/;
extern void gpsd_interpret_subframe(struct gps_device_t *, unsigned int[]);
extern int gpsd_hexdump_level;
extern /*@ observer @*/ char *gpsd_hexdump(/*@null@*/const void *, size_t);
extern /*@ observer @*/ char *gpsd_hexdump_wrapper(/*@null@*/const void *, size_t, int);
extern int gpsd_hexpack(/*@in@*/char *, /*@out@*/char *, size_t);
extern int hex2bin(char *);
extern ssize_t hex_escapes(/*@out@*/char *cooked, const char *raw);
extern void ntpd_link_activate(struct gps_device_t *session);
extern char /*@observer@*/ *gpsd_id(/*@in@*/struct gps_device_t *);
extern void gpsd_position_fix_dump(struct gps_device_t *, /*@out@*/char[], size_t);
extern void gpsd_error_model(struct gps_device_t *, struct gps_fix_t *, struct gps_fix_t *);
extern void gpsd_clear_data(struct gps_device_t *);
extern int netlib_connectsock(const char *, const char *, const char *);
extern char /*@observer@*/ *sock2ip(int);

extern void ntpshm_init(struct gps_context_t *, bool);
extern int ntpshm_alloc(struct gps_context_t *);
extern bool ntpshm_free(struct gps_context_t *, int);
extern int ntpshm_put(struct gps_device_t *, double);
extern int ntpshm_pps(struct gps_device_t *,struct timeval *);

extern void ecef_to_wgs84fix(/*@out@*/struct gps_data_t *,
			     double, double, double, 
			     double, double, double);
extern gps_mask_t dop(struct gps_data_t *);

/* sharing between gpsd.c and gpsd_output.c */
bool privileged_user(struct subscriber_t *);
bool assign_channel(struct subscriber_t *);
bool have_fix(struct subscriber_t *);
char *snarfline(char *, char **);
int handle_oldstyle(struct subscriber_t *, char *, int);
int handle_gpsd_request(struct subscriber_t *, char *, int);
struct gps_device_t *find_device(char *);
ssize_t throttled_write(struct subscriber_t *, char *, ssize_t);

/* srecord.c */
extern void hexdump(size_t, unsigned char *, unsigned char *);
extern unsigned char sr_sum(unsigned int, unsigned int, unsigned char *);
extern int bin2srec(unsigned int, unsigned int, unsigned int, unsigned char *, unsigned char *);
extern int srec_hdr(unsigned int, unsigned char *, unsigned char *);
extern int srec_fin(unsigned int, unsigned char *);
extern unsigned char hc(unsigned char);

/* exported bits for the GPS flasher */
bool sirf_write(int fd, unsigned char *msg);

/* application interface */
extern void gpsd_init(struct gps_device_t *, 
		      struct gps_context_t *, 
		      /*@null@*/char *);
extern int gpsd_activate(struct gps_device_t *, bool);
extern void gpsd_deactivate(struct gps_device_t *);
extern gps_mask_t gpsd_poll(struct gps_device_t *);
extern void gpsd_wrap(struct gps_device_t *);

/* exceptional driver methods */
#ifdef UBX_ENABLE
extern gps_mask_t ubx_parse(struct gps_device_t *, unsigned char *, size_t);
extern bool ubx_write(struct gps_device_t *, unsigned int, unsigned int, 
		      /*@null@*/unsigned char *, unsigned short);
extern void ubx_catch_model(struct gps_device_t *,
			    unsigned char *, size_t);
#endif /* UBX_ENABLE */
#ifdef AIVDM_ENABLE
extern bool aivdm_decode(char *, size_t, struct aivdm_context_t *);
extern void  aivdm_dump(struct ais_t *, bool, bool, FILE *);
#endif /* AIVDM_ENABLE */
#ifdef MKT3301_ENABLE
    extern gps_mask_t processMKT3301(int c UNUSED, char *field[], struct gps_device_t *session);
#endif /* MKT3301_ENABLE */

/* caller should supply this */
# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
__attribute__((__format__(__printf__, 2, 3))) void gpsd_report(int, const char *, ...);
# else /* not a new enough GCC, use the unprotected prototype */
void gpsd_report(int, const char *, ...);
#endif

#ifdef S_SPLINT_S
extern bool finite(double);
extern struct protoent *getprotobyname(const char *);
extern /*@observer@*/char *strptime(const char *,const char *tp,/*@out@*/struct tm *)/*@modifies tp@*/;
extern struct tm *gmtime_r(const time_t *,/*@out@*/struct tm *tp)/*@modifies tp@*/;
extern struct tm *localtime_r(const time_t *,/*@out@*/struct tm *tp)/*@modifies tp@*/;
extern float roundf(float x);
#endif /* S_SPLINT_S */

/* some OSes don't have round(). fake it if need be */
#ifndef HAVE_ROUND
#define	round(x) ((double)rint(x))
#define roundf(x) ((float)rintf((double)x))
#endif /* !HAVE_ROUND */

/* OpenBSD and FreeBSD and Cygwin don't seem to have NAN, NetBSD does, others? */
/* XXX test for this in configure? */
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__CYGWIN__)
#ifndef NAN
#define NAN (0.0/0.0)
#endif /* !NAN */
#endif /* list of Operating Systems */

/* Cygwin, in addition to NAN, doesn't have cfmakeraw */
#if defined(__CYGWIN__)
void cfmakeraw(struct termios *);
#endif /* defined(__CYGWIN__) */

#endif /* _GPSD_H_ */
// Local variables:
// mode: c
// end: