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