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
26 FT12LowLevelDriver::FT12LowLevelDriver (const char *dev
, Trace
* tr
)
31 TRACEPRINTF (t
, 1, this, "Open");
32 fd
= open (dev
, O_RDWR
| O_NOCTTY
);
34 throw Exception (DEV_OPEN_FAIL
);
38 t1
.c_cflag
= CS8
| PARENB
| CLOCAL
| CREAD
;
39 t1
.c_iflag
= IGNBRK
| INPCK
| ISIG
;
44 cfsetospeed (&t1
, B19200
);
47 tcsetattr (fd
, TCSAFLUSH
, &t1
);
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
);
58 TRACEPRINTF (t
, 1, this, "Opened");
61 FT12LowLevelDriver::~FT12LowLevelDriver ()
64 pth_event_free (getwait
, PTH_FREE_THIS
);
66 while (!outqueue
.isempty ())
67 delete outqueue
.get ();
69 TRACEPRINTF (t
, 1, this, "Close");
72 tcsetattr (fd
, TCSAFLUSH
, &old
);
78 FT12LowLevelDriver::Send_Packet (CArray l
)
83 t
->TracePacket (1, this, "Send", l
);
86 pdu
.resize (l () + 7);
97 pdu
.setpart (l
.array (), 5, l ());
99 for (i
= 0; i
< l (); i
++)
102 pdu
[pdu () - 1] = 0x16;
105 pth_sem_set_value (&send_empty
, 0);
106 pth_sem_inc (&in_signal
, TRUE
);
110 FT12LowLevelDriver::SendReset ()
113 TRACEPRINTF (t
, 1, this, "SendReset");
122 pth_sem_set_value (&send_empty
, 0);
123 pth_sem_inc (&in_signal
, TRUE
);
127 FT12LowLevelDriver::Send_Queue_Empty ()
129 return inqueue
.isempty ();
133 FT12LowLevelDriver::Send_Queue_Empty_Cond ()
139 FT12LowLevelDriver::Get_Packet (pth_event_t stop
)
142 pth_event_concat (getwait
, stop
, NULL
);
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
);
161 FT12LowLevelDriver::Connection_Lost ()
163 return repeatcount
> 10;
167 FT12LowLevelDriver::Run (pth_sem_t
* stop1
)
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
);
181 pth_event_concat (stop
, input
, NULL
);
183 pth_event_concat (stop
, timeout
, NULL
);
185 i
= pth_read_ev (fd
, buf
, sizeof (buf
), stop
);
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
);
198 if (inqueue
.isempty ())
199 pth_sem_set_value (&send_empty
, 1);
200 akt
.deletepart (0, 1);
204 else if (akt
[0] == 0x10)
208 if (akt
[1] == akt
[2] && akt
[3] == 0x16)
211 t
->TracePacket (0, this, "Send Ack", 1, &c1
);
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)
228 if (akt
[1] != akt
[2] || akt
[3] != 0x68)
230 //receive error, try to resume
231 akt
.deletepart (0, 1);
234 if (akt () < akt
[1] + 6)
238 for (i
= 4; i
< akt
[1] + 4; i
++)
240 if (akt
[akt
[1] + 4] != c1
|| akt
[akt
[1] + 5] != 0x16)
243 //Forget wrong short frame
244 akt
.deletepart (0, len
);
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
;
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
;
270 c
->setpart (akt
.array () + 5, 0, len
- 7);
273 pth_sem_inc (&out_signal
, TRUE
);
275 akt
.deletepart (0, len
);
278 //Forget unknown byte
279 akt
.deletepart (0, 1);
282 if (mode
== 1 && pth_event_status (timeout
) == PTH_STATUS_OCCURRED
)
285 if (mode
== 0 && !inqueue
.isempty ())
287 const CArray
& c
= inqueue
.top ();
288 t
->TracePacket (0, this, "Send", c
);
290 i
= pth_write_ev (fd
, c
.array (), c (), stop
);
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 ()