2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2007 Martin Kögler <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
)
292 pth_event_t stop
= pth_event (PTH_EVENT_SEM
, stop1
);
293 pth_event_t input
= pth_event (PTH_EVENT_SEM
, &in_signal
);
294 pth_event_t timeout
= pth_event (PTH_EVENT_TIME
, pth_timeout (0, 0));
295 pth_event_t sendtimeout
= pth_event (PTH_EVENT_TIME
, pth_timeout (0, 0));
296 while (pth_event_status (stop
) != PTH_STATUS_OCCURRED
)
298 if (in () == 0 && !waitconfirm
)
299 pth_event_concat (stop
, input
, NULL
);
301 pth_event_concat (stop
, timeout
, NULL
);
303 pth_event_concat (stop
, sendtimeout
, NULL
);
304 i
= pth_read_ev (fd
, buf
, sizeof (buf
), stop
);
305 pth_event_isolate (stop
);
306 pth_event_isolate (timeout
);
307 pth_event_isolate (sendtimeout
);
310 t
->TracePacket (0, this, "Recv", i
, buf
);
311 in
.setpart (buf
, in (), i
);
320 delete inqueue
.get ();
321 pth_sem_dec (&in_signal
);
324 in
.deletepart (0, 1);
326 else if (in
[0] == 0x0B)
332 TRACEPRINTF (t
, 0, this, "NACK");
335 TRACEPRINTF (t
, 0, this, "Drop NACK");
336 delete inqueue
.get ();
337 pth_sem_dec (&in_signal
);
341 in
.deletepart (0, 1);
343 else if (in
[0] == 0xCC || in
[0] == 0xC0 || in
[0] == 0x0C)
345 RecvLPDU (in
.array (), 1);
346 in
.deletepart (0, 1);
348 else if ((in
[0] & 0xD0) == 0x90)
355 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
356 pth_timeout (0, 300000));
358 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
360 TRACEPRINTF (t
, 0, this, "Remove1 %02X", in
[0]);
361 in
.deletepart (0, 1);
367 if ((in
[5] & 0x80) == 0)
369 for (unsigned i
= 0; i
< indaddr (); i
++)
370 if (indaddr
[i
] == (in
[3] << 8) | in
[4])
375 for (unsigned i
= 0; i
< groupaddr (); i
++)
376 if (groupaddr
[i
] == (in
[3] << 8) | in
[4])
379 TRACEPRINTF (t
, 0, this, "SendAck %02X", c
);
380 pth_write_ev (fd
, &c
, 1, stop
);
383 unsigned len
= in
[5] & 0x0f;
390 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
391 pth_timeout (0, 300000));
393 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
395 TRACEPRINTF (t
, 0, this, "Remove2 %02X", in
[0]);
396 in
.deletepart (0, 1);
400 RecvLPDU (in
.array (), len
);
401 in
.deletepart (0, len
);
403 else if ((in
[0] & 0xD0) == 0x10)
410 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
411 pth_timeout (0, 300000));
413 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
415 TRACEPRINTF (t
, 0, this, "Remove1 %02X", in
[0]);
416 in
.deletepart (0, 1);
422 if ((in
[1] & 0x80) == 0)
424 for (unsigned i
= 0; i
< indaddr (); i
++)
425 if (indaddr
[i
] == (in
[4] << 8) | in
[5])
430 for (unsigned i
= 0; i
< groupaddr (); i
++)
431 if (groupaddr
[i
] == (in
[4] << 8) | in
[5])
434 TRACEPRINTF (t
, 0, this, "SendAck %02X", c
);
435 pth_write_ev (fd
, &c
, 1, stop
);
438 unsigned len
= in
[6] & 0xff;
445 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, timeout
,
446 pth_timeout (0, 300000));
448 if (pth_event_status (timeout
) != PTH_STATUS_OCCURRED
)
450 TRACEPRINTF (t
, 0, this, "Remove2 %02X", in
[0]);
451 in
.deletepart (0, 1);
455 RecvLPDU (in
.array (), len
);
456 in
.deletepart (0, len
);
461 TRACEPRINTF (t
, 0, this, "Remove %02X", in
[0]);
462 in
.deletepart (0, 1);
467 && pth_event_status (sendtimeout
) == PTH_STATUS_OCCURRED
)
473 TRACEPRINTF (t
, 0, this, "Drop Send");
474 delete inqueue
.get ();
475 pth_sem_dec (&in_signal
);
478 if (in () == 0 && !inqueue
.isempty () && !waitconfirm
)
480 LPDU
*l
= (LPDU
*) inqueue
.top ();
481 CArray d
= l
->ToPacket ();
486 for (i
= 0; i
< d (); i
++)
488 w
[2 * i
] = 0x80 | (i
& 0x3f);
491 w
[(d () * 2) - 2] = (w
[(d () * 2) - 2] & 0x3f) | 0x40;
492 t
->TracePacket (0, this, "Write", w
);
493 j
= pth_write_ev (fd
, w
.array (), w (), stop
);
495 pth_event (PTH_EVENT_TIME
| PTH_MODE_REUSE
, sendtimeout
,
496 pth_timeout (0, 600000));
499 pth_event_free (stop
, PTH_FREE_THIS
);
500 pth_event_free (input
, PTH_FREE_THIS
);
501 pth_event_free (timeout
, PTH_FREE_THIS
);
502 pth_event_free (sendtimeout
, PTH_FREE_THIS
);