1 /********************************************************************
2 ** @source JEEPS packet reading and acknowledging functions
3 **
4 ** @author Copyright (C) 1999 Alan Bleasby
5 ** @version 1.0
6 ** @modified Dec 28 1999 Alan Bleasby. First version
7 ** @modified Copyright (C) 2006 Robert Lipe
8 ** @@
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Library General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** Library General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Library General Public
21 ** License along with this library; if not, write to the
22 ** Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ** Boston, MA 02110-1301, USA.
24 ********************************************************************/
25 #include "garmin_gps.h"
26 #include "gpsserial.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <time.h>
30 #include <errno.h>
31
32 #if defined (__WIN32__)
33 #include <windows.h>
34 #endif
35
36 #ifdef USE_WX_LOGGING
37 #include "gps_wx_logging.h"
38 #endif
39
40 /* @func GPS_Time_Now ***********************************************
41 **
42 ** Get current time
43 **
44 ** @return [time_t] number of bytes read
45 **********************************************************************/
46
GPS_Time_Now(void)47 time_t GPS_Time_Now(void)
48 {
49 time_t secs;
50
51 if(time(&secs)==-1)
52 {
53 perror("time");
54 GPS_Error("GPS_Time_Now: Error reading time");
55 gps_errno = HARDWARE_ERROR;
56 return 0;
57 }
58
59 return secs;
60 }
61
62
63
64
65
66
67
68 /* @func GPS_Serial_Packet_Read ***********************************************
69 **
70 ** Read a packet
71 **
72 ** @param [r] fd [int32] file descriptor
73 ** @param [w] packet [GPS_PPacket *] packet string
74 **
75 ** @return [int32] number of bytes read
76 **********************************************************************/
77
GPS_Serial_Packet_Read(gpsdevh * fd,GPS_PPacket * packet)78 int32 GPS_Serial_Packet_Read(gpsdevh *fd, GPS_PPacket *packet)
79 {
80 time_t start;
81 int32 n;
82 int32 len;
83 UC u;
84 int32 isDLE;
85 UC *p;
86 uint32 i;
87 UC chk=0, chk_read;
88 const char *m1;
89 const char *m2;
90
91 len = 0;
92 isDLE = gpsFalse;
93 p = (*packet)->data;
94
95 start = GPS_Time_Now();
96 GPS_Diag("Rx Data:");
97 while(GPS_Time_Now() < start+GPS_TIME_OUT)
98 {
99 if((n=GPS_Serial_Chars_Ready(fd)))
100 {
101 if(GPS_Serial_Read(fd,&u,1)==-1)
102 {
103 perror("read");
104 GPS_Error("GPS_Packet_Read: Read error");
105 gps_errno = FRAMING_ERROR;
106 return 0;
107 }
108
109 GPS_Diag("%02x ", u);
110
111 if(!len)
112 {
113 if(u != DLE)
114 {
115 GPS_Error(
116 "GPS_Packet_Read: No DLE. Data received, but probably not a garmin packet.\n");
117 return 0;
118 }
119 ++len;
120 continue;
121 }
122
123 if(len==1)
124 {
125 (*packet)->type = u;
126 ++len;
127 continue;
128 }
129
130 if(u == DLE)
131 {
132 if(isDLE)
133 {
134 isDLE = gpsFalse;
135 continue;
136 }
137 isDLE = gpsTrue;
138 }
139
140 if(len == 2)
141 {
142 (*packet)->n = u;
143 len = -1;
144 continue;
145 }
146
147 if(u == ETX)
148 if(isDLE)
149 {
150 if(p-(*packet)->data-2 != (*packet)->n)
151 {
152 GPS_Error("GPS_Packet_Read: Bad count");
153 gps_errno = FRAMING_ERROR;
154 return 0;
155 }
156 chk_read = *(p-2);
157
158 for(i=0,p=(*packet)->data;i<(*packet)->n;++i)
159 chk -= *p++;
160 chk -= (*packet)->type;
161 chk -= (UC)((*packet)->n);
162 if(chk != chk_read)
163 {
164 GPS_Error("CHECKSUM: Read error\n");
165 gps_errno = FRAMING_ERROR;
166 return 0;
167 }
168
169 m1 = Get_Pkt_Type((*packet)->type, (*packet)->data[0], &m2);
170 if (gps_show_bytes) {
171 GPS_Diag(" ");
172 for (i = 0; i < (*packet)->n; i++) {
173 char c = (*packet)->data[i];
174 GPS_Diag("%c", c); //isalnum(c) ? c : '.');
175 }
176 GPS_Diag(" ");
177 }
178 GPS_Diag("(%-8s%s)\n", m1, m2 ? m2 : "");
179 return (*packet)->n;
180 }
181
182 if (p - (*packet)->data >= MAX_GPS_PACKET_SIZE)
183 {
184 GPS_Error("GPS_Serial_Packet_Read: Bad payload size/no ETX found");
185 gps_errno = FRAMING_ERROR;
186 return 0;
187 }
188 *p++ = u;
189 }
190 #if defined (__WIN32__)
191 if( !GPS_Serial_Chars_Ready(fd) )
192 Sleep(1);
193 #endif
194 }
195
196
197 GPS_Error("GPS_Packet_Read: Timeout. No data received.");
198 gps_errno = SERIAL_ERROR;
199
200 return 0;
201 }
202
203
204
205 /* @func GPS_Get_Ack *************************************************
206 **
207 ** Check that returned packet is an ack for the packet sent
208 **
209 ** @param [r] fd [int32] file descriptor
210 ** @param [r] tra [GPS_PPacket *] packet just transmitted
211 ** @param [r] rec [GPS_PPacket *] packet to receive
212 **
213 ** @return [int32] true if ACK
214 **********************************************************************/
215
GPS_Serial_Get_Ack(gpsdevh * fd,GPS_PPacket * tra,GPS_PPacket * rec)216 int32 GPS_Serial_Get_Ack(gpsdevh *fd, GPS_PPacket *tra, GPS_PPacket *rec)
217 {
218 if(!GPS_Serial_Packet_Read(fd, rec)) {
219 gps_errno = INPUT_ERROR;
220 return 0;
221 }
222 if(LINK_ID[0].Pid_Ack_Byte != (*rec)->type)
223 {
224 gps_errno = PROTOCOL_ERROR;
225 /* rjl return 0; */
226 }
227
228 if(*(*rec)->data != (*tra)->type)
229 {
230 gps_errno = FRAMING_ERROR;
231 return 0;
232 }
233
234 return 1;
235 }
236