2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2008 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
22 #include <sys/ioctl.h>
23 #include "tpuartserial.h"
25 /** get serial status lines */
30 ioctl (fd
, TIOCMGET
, &s
);
34 /** set serial status lines */
36 setstat (int fd
, int s
)
38 ioctl (fd
, TIOCMSET
, &s
);
42 TPUARTSerialLayer2Driver::TPUARTSerialLayer2Driver (const char *dev
,
43 eibaddr_t a
, Trace
* tr
)
47 TRACEPRINTF (t
, 2, this, "Open");
49 fd
= open (dev
, O_RDWR
| O_NOCTTY
| O_NDELAY
| O_SYNC
);
51 throw Exception (DEV_OPEN_FAIL
);
52 set_low_latency (fd
, &sold
);
56 fd
= open (dev
, O_RDWR
| O_NOCTTY
| O_SYNC
);
58 throw Exception (DEV_OPEN_FAIL
);
61 t1
.c_cflag
= CS8
| CLOCAL
| CREAD
| PARENB
;
62 t1
.c_iflag
= IGNBRK
| INPCK
| ISIG
;
67 cfsetospeed (&t1
, B19200
);
70 tcsetattr (fd
, TCSAFLUSH
, &t1
);
72 setstat (fd
, (getstat (fd
) & ~TIOCM_RTS
) | TIOCM_DTR
);
80 pth_sem_init (&in_signal
);
81 pth_sem_init (&out_signal
);
83 getwait
= pth_event (PTH_EVENT_SEM
, &out_signal
);
86 TRACEPRINTF (t
, 2, this, "Openend");
89 TPUARTSerialLayer2Driver::~TPUARTSerialLayer2Driver ()
91 TRACEPRINTF (t
, 2, this, "Close");
93 pth_event_free (getwait
, PTH_FREE_THIS
);
95 while (!outqueue
.isempty ())
96 delete outqueue
.get ();
97 while (!inqueue
.isempty ())
98 delete inqueue
.get ();
102 setstat (fd
, (getstat (fd
) & ~TIOCM_RTS
) & ~TIOCM_DTR
);
103 tcsetattr (fd
, TCSAFLUSH
, &old
);
104 restore_low_latency (fd
, &sold
);
111 TPUARTSerialLayer2Driver::addAddress (eibaddr_t addr
)
114 for (i
= 0; i
< indaddr (); i
++)
115 if (indaddr
[i
] == addr
)
117 indaddr
.resize (indaddr () + 1);
118 indaddr
[indaddr () - 1] = addr
;
123 TPUARTSerialLayer2Driver::addGroupAddress (eibaddr_t addr
)
126 for (i
= 0; i
< groupaddr (); i
++)
127 if (groupaddr
[i
] == addr
)
129 groupaddr
.resize (groupaddr () + 1);
130 groupaddr
[groupaddr () - 1] = addr
;
135 TPUARTSerialLayer2Driver::removeAddress (eibaddr_t addr
)
138 for (i
= 0; i
< indaddr (); i
++)
139 if (indaddr
[i
] == addr
)
141 indaddr
.deletepart (i
, 1);
148 TPUARTSerialLayer2Driver::removeGroupAddress (eibaddr_t addr
)
151 for (i
= 0; i
< groupaddr (); i
++)
152 if (groupaddr
[i
] == addr
)
154 groupaddr
.deletepart (i
, 1);
160 bool TPUARTSerialLayer2Driver::openVBusmonitor ()
166 bool TPUARTSerialLayer2Driver::closeVBusmonitor ()
173 TPUARTSerialLayer2Driver::getDefaultAddr ()
179 TPUARTSerialLayer2Driver::Connection_Lost ()
185 TPUARTSerialLayer2Driver::Send_Queue_Empty ()
187 return inqueue
.isempty ();
191 TPUARTSerialLayer2Driver::Send_L_Data (LPDU
* l
)
193 TRACEPRINTF (t
, 2, this, "Send %s", l
->Decode ()());
195 pth_sem_inc (&in_signal
, 1);
199 TPUARTSerialLayer2Driver::Get_L_Data (pth_event_t stop
)
202 pth_event_concat (getwait
, stop
, NULL
);
207 pth_event_isolate (getwait
);
209 if (pth_event_status (getwait
) == PTH_STATUS_OCCURRED
)
211 pth_sem_dec (&out_signal
);
212 LPDU
*l
= outqueue
.get ();
213 TRACEPRINTF (t
, 2, this, "Recv %s", l
->Decode ()());
224 TPUARTSerialLayer2Driver::enterBusmonitor ()
227 t
->TracePacket (2, this, "openBusmonitor", 1, &c
);
234 TPUARTSerialLayer2Driver::leaveBusmonitor ()
237 t
->TracePacket (2, this, "leaveBusmonitor", 1, &c
);
244 TPUARTSerialLayer2Driver::Open ()
247 t
->TracePacket (2, this, "open-reset", 1, &c
);
253 TPUARTSerialLayer2Driver::Close ()
259 TPUARTSerialLayer2Driver::RecvLPDU (const uchar
* data
, int len
)
261 t
->TracePacket (1, this, "Recv", len
, data
);
264 L_Busmonitor_PDU
*l
= new L_Busmonitor_PDU
;
265 l
->pdu
.set (data
, len
);
267 pth_sem_inc (&out_signal
, 1);
271 LPDU
*l
= LPDU::fromPacket (CArray (data
, len
));
272 if (l
->getType () == L_Data
&& ((L_Data_PDU
*) l
)->valid_checksum
)
275 pth_sem_inc (&out_signal
, 1);
283 TPUARTSerialLayer2Driver::Run (pth_sem_t
* stop1
)
293 pth_event_t stop
= pth_event (PTH_EVENT_SEM
, stop1
);
294 pth_event_t input
= pth_event (PTH_EVENT_SEM
, &in_signal
);
295 pth_event_t timeout
= pth_event (PTH_EVENT_TIME
, pth_timeout (0, 0));
296 pth_event_t watchdog
= pth_event (PTH_EVENT_TIME
, pth_timeout (0, 0));
297 pth_event_t sendtimeout
= pth_event (PTH_EVENT_TIME
, pth_timeout (0, 0));
298 while (pth_event_status (stop
) != PTH_STATUS_OCCURRED
)
300 if (in () == 0 && !waitconfirm
)
301 pth_event_concat (stop
, input
, NULL
);
303 pth_event_concat (stop
, timeout
, NULL
);
305 pth_event_concat (stop
, sendtimeout
, NULL
);
307 pth_event_concat (stop
, watchdog
, NULL
);
308 i
= pth_read_ev (fd
, buf
, sizeof (buf
), stop
);
309 pth_event_isolate (stop
);
310 pth_event_isolate (timeout
);
311 pth_event_isolate (sendtimeout
);
312 pth_event_isolate (watchdog
);
315 t
->TracePacket (0, this, "Recv", i
, buf
);
316 in
.setpart (buf
, in (), i
);
324 const uchar pkt
[1] = { 0xCC };
330 delete inqueue
.get ();
331 pth_sem_dec (&in_signal
);
334 in
.deletepart (0, 1);
336 else if (in
[0] == 0x0B)
340 const uchar pkt
[1] = { 0x0C };
347 TRACEPRINTF (t
, 0, this, "NACK");
350 TRACEPRINTF (t
, 0, this, "Drop NACK");
351 delete inqueue
.get ();
352 pth_sem_dec (&in_signal
);
356 in
.deletepart (0, 1);
358 else if ((in
[0] & 0x07) == 0x07)
360 TRACEPRINTF (t
, 0, this, "RecvWatchdog: %02X", in
[0]);
362 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, watchdog
,
363 pth_timeout (10, 0));
364 in
.deletepart (0, 1);
366 else if (in
[0] == 0xCC || in
[0] == 0xC0 || in
[0] == 0x0C)
368 RecvLPDU (in
.array (), 1);
369 in
.deletepart (0, 1);
371 else if ((in
[0] & 0xD0) == 0x90)
378 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
379 pth_timeout (0, 300000));
381 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
383 TRACEPRINTF (t
, 0, this, "Remove1 %02X", in
[0]);
384 in
.deletepart (0, 1);
390 if ((in
[5] & 0x80) == 0)
392 for (unsigned i
= 0; i
< indaddr (); i
++)
393 if (indaddr
[i
] == (in
[3] << 8) | in
[4])
398 for (unsigned i
= 0; i
< groupaddr (); i
++)
399 if (groupaddr
[i
] == (in
[3] << 8) | in
[4])
402 TRACEPRINTF (t
, 0, this, "SendAck %02X", c
);
403 pth_write_ev (fd
, &c
, 1, stop
);
406 unsigned len
= in
[5] & 0x0f;
413 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
414 pth_timeout (0, 300000));
416 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
418 TRACEPRINTF (t
, 0, this, "Remove2 %02X", in
[0]);
419 in
.deletepart (0, 1);
423 RecvLPDU (in
.array (), len
);
424 in
.deletepart (0, len
);
426 else if ((in
[0] & 0xD0) == 0x10)
433 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
434 pth_timeout (0, 300000));
436 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
438 TRACEPRINTF (t
, 0, this, "Remove1 %02X", in
[0]);
439 in
.deletepart (0, 1);
445 if ((in
[1] & 0x80) == 0)
447 for (unsigned i
= 0; i
< indaddr (); i
++)
448 if (indaddr
[i
] == (in
[4] << 8) | in
[5])
453 for (unsigned i
= 0; i
< groupaddr (); i
++)
454 if (groupaddr
[i
] == (in
[4] << 8) | in
[5])
457 TRACEPRINTF (t
, 0, this, "SendAck %02X", c
);
458 pth_write_ev (fd
, &c
, 1, stop
);
461 unsigned len
= in
[6] & 0xff;
468 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
469 pth_timeout (0, 300000));
471 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
473 TRACEPRINTF (t
, 0, this, "Remove2 %02X", in
[0]);
474 in
.deletepart (0, 1);
478 RecvLPDU (in
.array (), len
);
479 in
.deletepart (0, len
);
484 TRACEPRINTF (t
, 0, this, "Remove %02X", in
[0]);
485 in
.deletepart (0, 1);
490 && pth_event_status (sendtimeout
) == PTH_STATUS_OCCURRED
)
496 TRACEPRINTF (t
, 0, this, "Drop Send");
497 delete inqueue
.get ();
498 pth_sem_dec (&in_signal
);
501 if (watch
== 1 && pth_event_status (watchdog
) == PTH_STATUS_OCCURRED
)
504 t
->TracePacket (2, this, "Watchdog Reset", 1, &c
);
508 if (watch
== 2 && pth_event_status (watchdog
) == PTH_STATUS_OCCURRED
)
510 if (in () == 0 && !inqueue
.isempty () && !waitconfirm
)
512 LPDU
*l
= (LPDU
*) inqueue
.top ();
513 CArray d
= l
->ToPacket ();
518 for (i
= 0; i
< d (); i
++)
520 w
[2 * i
] = 0x80 | (i
& 0x3f);
523 w
[(d () * 2) - 2] = (w
[(d () * 2) - 2] & 0x3f) | 0x40;
524 t
->TracePacket (0, this, "Write", w
);
525 j
= pth_write_ev (fd
, w
.array (), w (), stop
);
527 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, sendtimeout
,
528 pth_timeout (0, 600000));
530 else if (in () == 0 && !waitconfirm
&& !watch
&& mode
== 0 && !to
)
532 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, watchdog
,
533 pth_timeout (10, 0));
536 t
->TracePacket (2, this, "Watchdog Status", 1, &c
);
540 pth_event_free (stop
, PTH_FREE_THIS
);
541 pth_event_free (input
, PTH_FREE_THIS
);
542 pth_event_free (timeout
, PTH_FREE_THIS
);
543 pth_event_free (watchdog
, PTH_FREE_THIS
);
544 pth_event_free (sendtimeout
, PTH_FREE_THIS
);