Use Makefile variables for Python paths
[bcusdk.git] / eibd / backend / ft12.cpp
blob82585aac25b8d47e971971efc173cf9fe9a95555
1 /*
2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2007 Martin Koegler <mkoegler@auto.tuwien.ac.at>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
24 #include "ft12.h"
26 FT12LowLevelDriver::FT12LowLevelDriver (const char *dev, Trace * tr)
28 struct termios t1;
29 t = tr;
31 TRACEPRINTF (t, 1, this, "Open");
32 fd = open (dev, O_RDWR | O_NOCTTY);
33 if (fd == -1)
34 throw Exception (DEV_OPEN_FAIL);
35 tcgetattr (fd, &old);
37 tcgetattr (fd, &t1);
38 t1.c_cflag = CS8 | PARENB | CLOCAL | CREAD;
39 t1.c_iflag = IGNBRK | INPCK | ISIG;
40 t1.c_oflag = 0;
41 t1.c_lflag = 0;
42 t1.c_cc[VTIME] = 1;
43 t1.c_cc[VMIN] = 0;
44 cfsetospeed (&t1, B19200);
45 cfsetispeed (&t1, 0);
47 tcsetattr (fd, TCSAFLUSH, &t1);
48 sendflag = 0;
49 recvflag = 0;
50 repeatcount = 0;
51 mode = 0;
52 pth_sem_init (&in_signal);
53 pth_sem_init (&out_signal);
54 pth_sem_init (&send_empty);
55 pth_sem_set_value (&send_empty, 1);
56 getwait = pth_event (PTH_EVENT_SEM, &out_signal);
57 Start ();
58 TRACEPRINTF (t, 1, this, "Opened");
61 FT12LowLevelDriver::~FT12LowLevelDriver ()
63 Stop ();
64 pth_event_free (getwait, PTH_FREE_THIS);
66 while (!outqueue.isempty ())
67 delete outqueue.get ();
69 TRACEPRINTF (t, 1, this, "Close");
70 if (fd != -1)
72 tcsetattr (fd, TCSAFLUSH, &old);
73 close (fd);
77 void
78 FT12LowLevelDriver::Send_Packet (CArray l)
80 CArray pdu;
81 uchar c;
82 unsigned i;
83 t->TracePacket (1, this, "Send", l);
85 assert (l () <= 32);
86 pdu.resize (l () + 7);
87 pdu[0] = 0x68;
88 pdu[1] = l () + 1;
89 pdu[2] = l () + 1;
90 pdu[3] = 0x68;
91 if (sendflag)
92 pdu[4] = 0x53;
93 else
94 pdu[4] = 0x73;
95 sendflag = !sendflag;
97 pdu.setpart (l.array (), 5, l ());
98 c = pdu[4];
99 for (i = 0; i < l (); i++)
100 c += l[i];
101 pdu[pdu () - 2] = c;
102 pdu[pdu () - 1] = 0x16;
104 inqueue.put (pdu);
105 pth_sem_set_value (&send_empty, 0);
106 pth_sem_inc (&in_signal, TRUE);
109 void
110 FT12LowLevelDriver::SendReset ()
112 CArray pdu;
113 TRACEPRINTF (t, 1, this, "SendReset");
114 pdu.resize (4);
115 pdu[0] = 0x10;
116 pdu[1] = 0x40;
117 pdu[2] = 0x40;
118 pdu[3] = 0x16;
119 sendflag = 0;
120 recvflag = 0;
121 inqueue.put (pdu);
122 pth_sem_set_value (&send_empty, 0);
123 pth_sem_inc (&in_signal, TRUE);
126 bool
127 FT12LowLevelDriver::Send_Queue_Empty ()
129 return inqueue.isempty ();
132 pth_sem_t *
133 FT12LowLevelDriver::Send_Queue_Empty_Cond ()
135 return &send_empty;
138 CArray *
139 FT12LowLevelDriver::Get_Packet (pth_event_t stop)
141 if (stop != NULL)
142 pth_event_concat (getwait, stop, NULL);
144 pth_wait (getwait);
146 if (stop)
147 pth_event_isolate (getwait);
149 if (pth_event_status (getwait) == PTH_STATUS_OCCURRED)
151 pth_sem_dec (&out_signal);
152 CArray *c = outqueue.get ();
153 t->TracePacket (1, this, "Recv", *c);
154 return c;
156 else
157 return 0;
160 bool
161 FT12LowLevelDriver::Connection_Lost ()
163 return repeatcount > 10;
166 void
167 FT12LowLevelDriver::Run (pth_sem_t * stop1)
169 CArray last;
170 int i;
171 uchar buf[255];
173 pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
174 pth_event_t input = pth_event (PTH_EVENT_SEM, &in_signal);
175 pth_event_t timeout = pth_event (PTH_EVENT_TIME, pth_timeout (0, 100000));
176 while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
178 pth_event_isolate (input);
179 pth_event_isolate (timeout);
180 if (mode == 0)
181 pth_event_concat (stop, input, NULL);
182 if (mode == 1)
183 pth_event_concat (stop, timeout, NULL);
185 i = pth_read_ev (fd, buf, sizeof (buf), stop);
186 if (i > 0)
188 t->TracePacket (0, this, "Recv", i, buf);
189 akt.setpart (buf, akt (), i);
192 while (akt.len () > 0)
194 if (akt[0] == 0xE5 && mode == 1)
196 pth_sem_dec (&in_signal);
197 inqueue.get ();
198 if (inqueue.isempty ())
199 pth_sem_set_value (&send_empty, 1);
200 akt.deletepart (0, 1);
201 mode = 0;
202 repeatcount = 0;
204 else if (akt[0] == 0x10)
206 if (akt () < 4)
207 break;
208 if (akt[1] == akt[2] && akt[3] == 0x16)
210 uchar c1 = 0xE5;
211 t->TracePacket (0, this, "Send Ack", 1, &c1);
212 write (fd, &c1, 1);
213 if ((akt[1] == 0xF3 && !recvflag) ||
214 (akt[1] == 0xD3 && recvflag))
216 //right sequence number
217 recvflag = !recvflag;
220 akt.deletepart (0, 4);
222 else if (akt[0] == 0x68)
224 int len;
225 uchar c1;
226 if (akt () < 7)
227 break;
228 if (akt[1] != akt[2] || akt[3] != 0x68)
230 //receive error, try to resume
231 akt.deletepart (0, 1);
232 continue;
234 if (akt () < akt[1] + 6)
235 break;
237 c1 = 0;
238 for (i = 4; i < akt[1] + 4; i++)
239 c1 += akt[i];
240 if (akt[akt[1] + 4] != c1 || akt[akt[1] + 5] != 0x16)
242 len = akt[1] + 6;
243 //Forget wrong short frame
244 akt.deletepart (0, len);
245 continue;
248 c1 = 0xE5;
249 t->TracePacket (0, this, "Send Ack", 1, &c1);
250 i = write (fd, &c1, 1);
252 if ((akt[4] == 0xF3 && recvflag) ||
253 (akt[4] == 0xD3 && !recvflag))
255 if (CArray (akt.array () + 5, akt[1] - 1) != last)
257 TRACEPRINTF (t, 0, this, "Sequence jump");
258 recvflag = !recvflag;
260 else
261 TRACEPRINTF (t, 0, this, "Wrong Sequence");
264 if ((akt[4] == 0xF3 && !recvflag) ||
265 (akt[4] == 0xD3 && recvflag))
267 recvflag = !recvflag;
268 CArray *c = new CArray;
269 len = akt[1] + 6;
270 c->setpart (akt.array () + 5, 0, len - 7);
271 last = *c;
272 outqueue.put (c);
273 pth_sem_inc (&out_signal, TRUE);
275 akt.deletepart (0, len);
277 else
278 //Forget unknown byte
279 akt.deletepart (0, 1);
282 if (mode == 1 && pth_event_status (timeout) == PTH_STATUS_OCCURRED)
283 mode = 0;
285 if (mode == 0 && !inqueue.isempty ())
287 const CArray & c = inqueue.top ();
288 t->TracePacket (0, this, "Send", c);
289 repeatcount++;
290 i = pth_write_ev (fd, c.array (), c (), stop);
291 if (i == c ())
293 mode = 1;
294 timeout =
295 pth_event (PTH_EVENT_TIME | PTH_MODE_REUSE, timeout,
296 pth_timeout (0, 100000));
300 pth_event_free (stop, PTH_FREE_THIS);
301 pth_event_free (timeout, PTH_FREE_THIS);
302 pth_event_free (input, PTH_FREE_THIS);
305 LowLevelDriverInterface::EMIVer FT12LowLevelDriver::getEMIVer ()
307 return vEMI2;