Connectionless layer 7 access function
[bcusdk.git] / eibd / libserver / layer7.cpp
blob80eedcdb35b47d14a8abab53103a1ee349007621
1 /*
2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2009 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 "apdu.h"
21 #include "layer7.h"
23 Layer7_Broadcast::Layer7_Broadcast (Layer3 * l3, Trace * tr)
25 t = tr;
26 TRACEPRINTF (t, 5, this, "L7Broadcast Open");
27 l4 = new T_Broadcast (l3, tr, 0);
28 if (!l4->init ())
30 delete l4;
31 l4 = 0;
35 Layer7_Broadcast::~Layer7_Broadcast ()
37 TRACEPRINTF (t, 5, this, "L7Broadcast Close");
38 if (l4)
39 delete l4;
42 bool Layer7_Broadcast::init ()
44 return l4 != 0;
47 void
48 Layer7_Broadcast::A_IndividualAddress_Write (eibaddr_t addr)
50 A_IndividualAddress_Write_PDU a;
51 a.addr = addr;
52 l4->Send (a.ToPacket ());
55 Array < eibaddr_t >
56 Layer7_Broadcast::A_IndividualAddress_Read (unsigned timeout)
58 Array < eibaddr_t > addrs;
59 A_IndividualAddress_Read_PDU r;
60 APDU *a;
61 l4->Send (r.ToPacket ());
62 pth_event_t t = pth_event (PTH_EVENT_TIME, pth_timeout (timeout, 0));
63 while (pth_event_status (t) != PTH_STATUS_OCCURRED)
65 BroadcastComm *c = l4->Get (t);
66 if (c)
68 a = APDU::fromPacket (c->data);
69 if (a->isResponse (&r))
71 addrs.resize (addrs () + 1);
72 addrs[addrs () - 1] = c->src;
74 delete a;
75 delete c;
78 pth_event_free (t, PTH_FREE_THIS);
79 return addrs;
82 Layer7_Connection::Layer7_Connection (Layer3 * l3, Trace * tr, eibaddr_t d)
84 t = tr;
85 dest = d;
86 l4 = new T_Connection (l3, tr, d);
87 if (!l4->init ())
89 delete l4;
90 l4 = 0;
94 Layer7_Connection::~Layer7_Connection ()
96 if (l4)
97 delete l4;
100 bool Layer7_Connection::init ()
102 return l4 != 0;
105 void
106 Layer7_Connection::A_Restart ()
108 A_Restart_PDU a;
109 l4->Send (a.ToPacket ());
112 APDU *
113 Layer7_Connection::Request_Response (APDU * r)
115 APDU *a;
116 CArray *c;
117 l4->Send (r->ToPacket ());
118 pth_event_t t = pth_event (PTH_EVENT_TIME, pth_timeout (6, 100));
119 while (pth_event_status (t) != PTH_STATUS_OCCURRED)
121 c = l4->Get (t);
122 if (c)
124 if (c->len () == 0)
126 delete c;
127 pth_event_free (t, PTH_FREE_THIS);
128 return 0;
130 a = APDU::fromPacket (*c);
131 delete c;
132 if (a->isResponse (r))
134 pth_event_free (t, PTH_FREE_THIS);
135 return a;
137 delete a;
138 pth_event_free (t, PTH_FREE_THIS);
139 return 0;
142 pth_event_free (t, PTH_FREE_THIS);
143 return 0;
147 Layer7_Connection::A_Property_Read (uchar obj, uchar propertyid,
148 uint16_t start, uchar count, CArray & erg)
150 A_PropertyValue_Read_PDU r;
151 r.obj = obj;
152 r.prop = propertyid;
153 r.start = start & 0x0fff;
154 r.count = count & 0x0f;
155 APDU *a = Request_Response (&r);
156 if (!a)
157 return -1;
158 A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
159 erg = a1->data;
160 delete a;
161 return 0;
165 Layer7_Connection::A_Property_Write (uchar obj, uchar propertyid,
166 uint16_t start, uchar count,
167 const CArray & data, CArray & result)
169 A_PropertyValue_Write_PDU r;
170 r.obj = obj;
171 r.prop = propertyid;
172 r.start = start & 0x0fff;
173 r.count = count & 0x0f;
174 r.data = data;
175 APDU *a = Request_Response (&r);
176 if (!a)
177 return -1;
178 A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
179 result = a1->data;
180 delete a;
181 return 0;
185 Layer7_Connection::A_Property_Desc (uchar obj, uchar & property,
186 uchar property_index, uchar & type,
187 uint16_t & max_nr_elements,
188 uchar & access)
190 A_PropertyDescription_Read_PDU r;
191 r.obj = obj;
192 r.prop = property;
193 r.property_index = property_index;
194 APDU *a = Request_Response (&r);
195 if (!a)
196 return -1;
197 A_PropertyDescription_Response_PDU *a1 =
198 (A_PropertyDescription_Response_PDU *) a;
199 type = a1->type;
200 max_nr_elements = a1->count;
201 access = a1->access;
202 property = a1->prop;
203 delete a;
204 return 0;
208 Layer7_Connection::A_Device_Descriptor_Read (uint16_t & maskver, uchar type)
210 A_DeviceDescriptor_Read_PDU r;
211 r.type = type & 0x3f;
212 APDU *a = Request_Response (&r);
213 if (!a)
214 return -1;
215 A_DeviceDescriptor_Response_PDU *a1 = (A_DeviceDescriptor_Response_PDU *) a;
216 maskver = a1->descriptor;
217 delete a;
218 return 0;
222 Layer7_Connection::A_ADC_Read (uchar channel, uchar readcount,
223 int16_t & value)
225 A_ADC_Read_PDU r;
226 r.channel = channel & 0x3f;
227 r.count = readcount;
228 APDU *a = Request_Response (&r);
229 if (!a)
230 return -1;
231 A_ADC_Response_PDU *a1 = (A_ADC_Response_PDU *) a;
232 value = a1->val;
233 delete a;
234 return 0;
238 Layer7_Connection::A_Memory_Read (memaddr_t addr, uchar len, CArray & data)
240 A_Memory_Read_PDU r;
241 r.addr = addr;
242 r.count = len & 0x0f;
243 APDU *a = Request_Response (&r);
244 if (!a)
245 return -1;
246 A_Memory_Response_PDU *a1 = (A_Memory_Response_PDU *) a;
247 data = a1->data;
248 delete a;
249 return 0;
253 Layer7_Connection::A_Memory_Write (memaddr_t addr, const CArray & data)
255 A_Memory_Write_PDU r;
256 r.addr = addr;
257 r.count = data () & 0x0f;
258 r.data.set (data.array (), data () & 0x0f);
259 l4->Send (r.ToPacket ());
260 return 0;
264 Layer7_Connection::A_Authorize (eibkey_type key, uchar & level)
266 A_Authorize_Request_PDU r;
267 r.key = key;
268 APDU *a = Request_Response (&r);
269 if (!a)
270 return -1;
271 A_Authorize_Response_PDU *a1 = (A_Authorize_Response_PDU *) a;
272 level = a1->level;
273 delete a;
274 return 0;
278 Layer7_Connection::A_KeyWrite (eibkey_type key, uchar & level)
280 A_Key_Write_PDU r;
281 r.key = key;
282 r.level = level;
283 APDU *a = Request_Response (&r);
284 if (!a)
285 return -1;
286 A_Key_Response_PDU *a1 = (A_Key_Response_PDU *) a;
287 level = a1->level;
288 delete a;
289 return 0;
293 Layer7_Connection::X_Property_Write (uchar obj, uchar propertyid,
294 uint16_t start, uchar count,
295 const CArray & data)
297 CArray d1;
298 if (A_Property_Write (obj, propertyid, start, count, data, d1) == -1)
299 return -1;
300 if (A_Property_Read (obj, propertyid, start, count, d1) == -1)
301 return -1;
302 if (d1 != data)
303 return -1;
304 return 0;
308 Layer7_Connection::X_Memory_Write (memaddr_t addr, const CArray & data)
310 CArray d1;
311 if (A_Memory_Write (addr, data) == -1)
312 return -1;
313 if (A_Memory_Read (addr, data (), d1) == -1)
314 return -1;
315 if (d1 != data)
316 return -2;
317 return 0;
321 Layer7_Connection::X_Memory_Write_Block (memaddr_t addr, const CArray & data)
323 CArray prev;
324 int i, j, k, res = 0;
325 const unsigned blocksize = 12;
326 if (X_Memory_Read_Block (addr, data (), prev) == -1)
327 return -1;
328 for (i = 0; i < data (); i++)
330 if (data[i] == prev[i])
331 continue;
332 j = 0;
333 while (data[i + j] != prev[i + j] && j < blocksize && i + j < data ())
334 j++;
335 k = X_Memory_Write (addr + i, CArray (data.array () + i, j));
336 if (k == -1)
337 return -1;
338 if (k == -2)
339 res = -2;
340 i += j - 1;
343 return res;
347 Layer7_Connection::X_Memory_Read_Block (memaddr_t addr, int len, CArray & erg)
349 unsigned blocksize = 12;
350 CArray e;
351 erg.resize (len);
352 for (unsigned i = 0; i < len; i += blocksize)
355 if (A_Memory_Read
356 (addr + i, (len - i > blocksize ? blocksize : len - i), e) == -1)
358 if (blocksize == 12)
360 blocksize = 2;
361 goto rt;
363 return -1;
365 erg.setpart (e, i);
367 return 0;
371 Layer7_Connection::A_Memory_Write_Block (memaddr_t addr, const CArray & data)
373 CArray prev;
374 int i, j, k, res = 0;
375 const unsigned blocksize = 12;
377 for (i = 0; i < data (); i += blocksize)
379 j = blocksize;
380 if (i + j > data ())
381 j = data () - i;
382 k = A_Memory_Write (addr + i, CArray (data.array () + i, j));
383 if (k == -1)
384 return -1;
387 return res;
390 Layer7_Individual::Layer7_Individual (Layer3 * l3, Trace * tr, eibaddr_t d)
392 t = tr;
393 dest = d;
394 l4 = new T_Individual (l3, tr, d, false);
395 if (!l4->init ())
397 delete l4;
398 l4 = 0;
402 Layer7_Individual::~Layer7_Individual ()
404 if (l4)
405 delete l4;
408 bool Layer7_Individual::init ()
410 return l4 != 0;
413 APDU *
414 Layer7_Individual::Request_Response (APDU * r)
416 APDU *a;
417 CArray *c;
418 l4->Send (r->ToPacket ());
419 pth_event_t t = pth_event (PTH_EVENT_TIME, pth_timeout (6, 100));
420 while (pth_event_status (t) != PTH_STATUS_OCCURRED)
422 c = l4->Get (t);
423 if (c)
425 if (c->len () == 0)
427 delete c;
428 pth_event_free (t, PTH_FREE_THIS);
429 return 0;
431 a = APDU::fromPacket (*c);
432 delete c;
433 if (a->isResponse (r))
435 pth_event_free (t, PTH_FREE_THIS);
436 return a;
438 delete a;
439 pth_event_free (t, PTH_FREE_THIS);
440 return 0;
443 pth_event_free (t, PTH_FREE_THIS);
444 return 0;
448 Layer7_Individual::A_Property_Read (uchar obj, uchar propertyid,
449 uint16_t start, uchar count, CArray & erg)
451 A_PropertyValue_Read_PDU r;
452 r.obj = obj;
453 r.prop = propertyid;
454 r.start = start & 0x0fff;
455 r.count = count & 0x0f;
456 APDU *a = Request_Response (&r);
457 if (!a)
458 return -1;
459 A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
460 erg = a1->data;
461 delete a;
462 return 0;
466 Layer7_Individual::A_Property_Write (uchar obj, uchar propertyid,
467 uint16_t start, uchar count,
468 const CArray & data, CArray & result)
470 A_PropertyValue_Write_PDU r;
471 r.obj = obj;
472 r.prop = propertyid;
473 r.start = start & 0x0fff;
474 r.count = count & 0x0f;
475 r.data = data;
476 APDU *a = Request_Response (&r);
477 if (!a)
478 return -1;
479 A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
480 result = a1->data;
481 delete a;
482 return 0;