summaryrefslogtreecommitdiff
path: root/italk.c
blob: 8c697e29a102e20acb974815b4acea5b0a9a9920 (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
/* $Id$ */
/*
 * Driver for the iTalk binary protocol used by FasTrax
 */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>

#include "gpsd_config.h"
#include "gpsd.h"
#if defined(ITRAX_ENABLE) && defined(BINARY_ENABLE)

#define LITTLE_ENDIAN_PROTOCOL
#include "bits.h"

/*@ +charint -usedef -compdef @*/
static bool italk_write(int fd, unsigned char *msg, size_t msglen) {
   bool      ok;

   /* CONSTRUCT THE MESSAGE */

   /* we may need to dump the message */
   gpsd_report(LOG_IO, "writing italk control type %02x:%s\n", 
	       msg[0], gpsd_hexdump(msg, msglen));
#ifdef ALLOW_RECONFIGURE
   ok = (write(fd, msg, msglen) == (ssize_t)msglen);
   (void)tcdrain(fd);
#else
   ok = 0;
#endif /* ALLOW_RECONFIGURE */
   return(ok);
}
/*@ -charint +usedef +compdef @*/

/*@ +charint @*/
static gps_mask_t italk_parse(struct gps_device_t *session, unsigned char *buf, size_t len)
{
    if (len == 0)
	return 0;

    /* we may need to dump the raw packet */
    gpsd_report(LOG_RAW, "raw italk packet type 0x%02x length %d: %s\n", buf[0], len, gpsd_hexdump(buf, len));

    (void)snprintf(session->gpsdata.tag, sizeof(session->gpsdata.tag),
		   "ITALK%d",(int)buf[0]);

    switch (getub(buf, 0))
    {
	/* DISPATCH ON FIRST BYTE OF PAYLOAD */

    default:
	gpsd_report(LOG_WARN, "unknown iTalk packet id %d length %d: %s\n", buf[0], len, gpsd_hexdump(buf, len));
	return 0;
    }
}
/*@ -charint @*/

static gps_mask_t italk_parse_input(struct gps_device_t *session)
{
    gps_mask_t st;

    if (session->packet.type == ITALK_PACKET){
	st = italk_parse(session, session->packet.outbuffer, session->packet.outbuflen);
	session->gpsdata.driver_mode = 1;	/* binary */
	return st;
#ifdef NMEA_ENABLE
    } else if (session->packet.type == NMEA_PACKET) {
	st = nmea_parse((char *)session->packet.outbuffer, session);
	session->gpsdata.driver_mode = 0;	/* NMEA */
	return st;
#endif /* NMEA_ENABLE */
    } else
	return 0;
}

static bool italk_set_mode(struct gps_device_t *session UNUSED, 
			      speed_t speed UNUSED, bool mode UNUSED)
{
    /*@ +charint @*/
    unsigned char msg[] = {0,};

    /* HACK THE MESSAGE */

    return italk_write(session->gpsdata.gps_fd, msg, sizeof(msg));
    /*@ +charint @*/
}

static bool italk_speed(struct gps_device_t *session, speed_t speed)
{
    return italk_set_mode(session, speed, true);
}

static void italk_mode(struct gps_device_t *session, int mode)
{
    if (mode == 0) {
	(void)gpsd_switch_driver(session, "Generic NMEA");
	(void)italk_set_mode(session, session->gpsdata.baudrate, false);
	session->gpsdata.driver_mode = 0;	/* NMEA */
    } else
	session->gpsdata.driver_mode = 1;	/* binary */
}

#ifdef ALLOW_RECONFIGURE
static void italk_configurator(struct gps_device_t *session, int seq)
{
    if (seq == 0 && session->packet.type == NMEA_PACKET)
	(void)italk_set_mode(session, session->gpsdata.baudrate, true);
}
#endif /* ALLOW_RECONFIGURE */

static void italk_ping(struct gps_device_t *session)
/* send a "ping". it may help us detect an itrax more quickly */
{
    char *ping = "<?>";
    (void)italk_write(session->gpsdata.gps_fd, ping, 3);
}

/* this is everything we export */
struct gps_type_t italk_binary =
{
    .typename       = "iTalk binary",	/* full name of type */
    .trigger        = NULL,		/* recognize the type */
    .channels       = 12,		/* consumer-grade GPS */
    .probe_wakeup   = italk_ping,	/* no wakeup to be done before hunt */
    .probe_detect   = NULL,        	/* how to detect at startup time */
    .probe_subtype  = NULL,        	/* initialize the device */
#ifdef ALLOW_RECONFIGURE
    .configurator   = italk_configurator,/* configure the device */
#endif /* ALLOW_RECONFIGURE */
    .get_packet     = generic_get,	/* use generic packet grabber */
    .parse_packet   = italk_parse_input,/* parse message packets */
    .rtcm_writer    = pass_rtcm,	/* send RTCM data straight */
    .speed_switcher = italk_speed,	/* we can change baud rates */
    .mode_switcher  = italk_mode,	/* there is a mode switcher */
    .rate_switcher  = NULL,		/* no sample-rate switcher */
    .cycle_chars    = -1,		/* not relevant, no rate switch */
#ifdef ALLOW_RECONFIGURE
    .revert         = NULL,		/* no setting-reversion method */
#endif /* ALLOW_RECONFIGURE */
    .wrapup         = NULL,		/* no close hook */
    .cycle          = 1,		/* updates every second */
};
#endif /* defined(ITRAX_ENABLE) && defined(BINARY_ENABLE) */