/*
EIBD eib bus access and management daemon
Copyright (C) 2005-2007 Martin Koegler <mkoegler@auto.tuwien.ac.at>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "apdu.h"
#include "layer7.h"
Layer7_Broadcast::Layer7_Broadcast (Layer3 * l3, Trace * tr)
{
t = tr;
TRACEPRINTF (t, 5, this, "L7Broadcast Open");
l4 = new T_Broadcast (l3, tr, 0);
}
Layer7_Broadcast::~Layer7_Broadcast ()
{
TRACEPRINTF (t, 5, this, "L7Broadcast Close");
delete l4;
}
void
Layer7_Broadcast::A_IndividualAddress_Write (eibaddr_t addr)
{
A_IndividualAddress_Write_PDU a;
a.addr = addr;
l4->Send (a.ToPacket ());
}
Array < eibaddr_t >
Layer7_Broadcast::A_IndividualAddress_Read (unsigned timeout)
{
Array < eibaddr_t > addrs;
A_IndividualAddress_Read_PDU r;
APDU *a;
l4->Send (r.ToPacket ());
pth_event_t t = pth_event (PTH_EVENT_TIME, pth_timeout (timeout, 0));
while (pth_event_status (t) != PTH_STATUS_OCCURRED)
{
BroadcastComm *c = l4->Get (t);
if (c)
{
a = APDU::fromPacket (c->data);
if (a->isResponse (&r))
{
addrs.resize (addrs () + 1);
addrs[addrs () - 1] = c->src;
}
delete a;
delete c;
}
}
pth_event_free (t, PTH_FREE_THIS);
return addrs;
}
Layer7_Connection::Layer7_Connection (Layer3 * l3, Trace * tr, eibaddr_t d)
{
t = tr;
dest = d;
l4 = 0;
try
{
l4 = new T_Connection (l3, tr, d);
}
catch (Exception e)
{
if (l4)
delete l4;
l4 = 0;
throw e;
}
}
Layer7_Connection::~Layer7_Connection ()
{
delete l4;
}
void
Layer7_Connection::A_Restart ()
{
A_Restart_PDU a;
l4->Send (a.ToPacket ());
}
APDU *
Layer7_Connection::Request_Response (APDU * r)
{
APDU *a;
CArray *c;
l4->Send (r->ToPacket ());
pth_event_t t = pth_event (PTH_EVENT_TIME, pth_timeout (6, 100));
while (pth_event_status (t) != PTH_STATUS_OCCURRED)
{
c = l4->Get (t);
if (c)
{
if (c->len () == 0)
{
delete c;
pth_event_free (t, PTH_FREE_THIS);
return 0;
}
a = APDU::fromPacket (*c);
delete c;
if (a->isResponse (r))
{
pth_event_free (t, PTH_FREE_THIS);
return a;
}
delete a;
pth_event_free (t, PTH_FREE_THIS);
return 0;
}
}
pth_event_free (t, PTH_FREE_THIS);
return 0;
}
int
Layer7_Connection::A_Property_Read (uchar obj, uchar propertyid,
uint16_t start, uchar count, CArray & erg)
{
A_PropertyValue_Read_PDU r;
r.obj = obj;
r.prop = propertyid;
r.start = start & 0x0fff;
r.count = count & 0x0f;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
erg = a1->data;
delete a;
return 0;
}
int
Layer7_Connection::A_Property_Write (uchar obj, uchar propertyid,
uint16_t start, uchar count,
const CArray & data, CArray & result)
{
A_PropertyValue_Write_PDU r;
r.obj = obj;
r.prop = propertyid;
r.start = start & 0x0fff;
r.count = count & 0x0f;
r.data = data;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_PropertyValue_Response_PDU *a1 = (A_PropertyValue_Response_PDU *) a;
result = a1->data;
delete a;
return 0;
}
int
Layer7_Connection::A_Property_Desc (uchar obj, uchar & property,
uchar property_index, uchar & type,
uint16_t & max_nr_elements,
uchar & access)
{
A_PropertyDescription_Read_PDU r;
r.obj = obj;
r.prop = property;
r.property_index = property_index;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_PropertyDescription_Response_PDU *a1 =
(A_PropertyDescription_Response_PDU *) a;
type = a1->type;
max_nr_elements = a1->count;
access = a1->access;
property = a1->prop;
delete a;
return 0;
}
int
Layer7_Connection::A_Device_Descriptor_Read (uint16_t & maskver, uchar type)
{
A_DeviceDescriptor_Read_PDU r;
r.type = type & 0x3f;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_DeviceDescriptor_Response_PDU *a1 = (A_DeviceDescriptor_Response_PDU *) a;
maskver = a1->descriptor;
delete a;
return 0;
}
int
Layer7_Connection::A_ADC_Read (uchar channel, uchar readcount,
int16_t & value)
{
A_ADC_Read_PDU r;
r.channel = channel & 0x3f;
r.count = readcount;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_ADC_Response_PDU *a1 = (A_ADC_Response_PDU *) a;
value = a1->val;
delete a;
return 0;
}
int
Layer7_Connection::A_Memory_Read (memaddr_t addr, uchar len, CArray & data)
{
A_Memory_Read_PDU r;
r.addr = addr;
r.count = len & 0x0f;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_Memory_Response_PDU *a1 = (A_Memory_Response_PDU *) a;
data = a1->data;
delete a;
return 0;
}
int
Layer7_Connection::A_Memory_Write (memaddr_t addr, const CArray & data)
{
A_Memory_Write_PDU r;
r.addr = addr;
r.count = data () & 0x0f;
r.data.set (data.array (), data () & 0x0f);
l4->Send (r.ToPacket ());
return 0;
}
int
Layer7_Connection::A_Authorize (eibkey_type key, uchar & level)
{
A_Authorize_Request_PDU r;
r.key = key;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_Authorize_Response_PDU *a1 = (A_Authorize_Response_PDU *) a;
level = a1->level;
delete a;
return 0;
}
int
Layer7_Connection::A_KeyWrite (eibkey_type key, uchar & level)
{
A_Key_Write_PDU r;
r.key = key;
r.level = level;
APDU *a = Request_Response (&r);
if (!a)
return -1;
A_Key_Response_PDU *a1 = (A_Key_Response_PDU *) a;
level = a1->level;
delete a;
return 0;
}
int
Layer7_Connection::X_Property_Write (uchar obj, uchar propertyid,
uint16_t start, uchar count,
const CArray & data)
{
CArray d1;
if (A_Property_Write (obj, propertyid, start, count, data, d1) == -1)
return -1;
if (A_Property_Read (obj, propertyid, start, count, d1) == -1)
return -1;
if (d1 != data)
return -1;
return 0;
}
int
Layer7_Connection::X_Memory_Write (memaddr_t addr, const CArray & data)
{
CArray d1;
if (A_Memory_Write (addr, data) == -1)
return -1;
if (A_Memory_Read (addr, data (), d1) == -1)
return -1;
if (d1 != data)
return -2;
return 0;
}
int
Layer7_Connection::X_Memory_Write_Block (memaddr_t addr, const CArray & data)
{
CArray prev;
int i, j, k, res = 0;
const unsigned blocksize = 12;
if (X_Memory_Read_Block (addr, data (), prev) == -1)
return -1;
for (i = 0; i < data (); i++)
{
if (data[i] == prev[i])
continue;
j = 0;
while (data[i + j] != prev[i + j] && j < blocksize && i + j < data ())
j++;
k = X_Memory_Write (addr + i, CArray (data.array () + i, j));
if (k == -1)
return -1;
if (k == -2)
res = -2;
i += j - 1;
}
return res;
}
int
Layer7_Connection::X_Memory_Read_Block (memaddr_t addr, int len, CArray & erg)
{
unsigned blocksize = 12;
CArray e;
erg.resize (len);
for (unsigned i = 0; i < len; i += blocksize)
{
rt:
if (A_Memory_Read
(addr + i, (len - i > blocksize ? blocksize : len - i), e) == -1)
{
if (blocksize == 12)
{
blocksize = 2;
goto rt;
}
return -1;
}
erg.setpart (e, i);
}
return 0;
}
int
Layer7_Connection::A_Memory_Write_Block (memaddr_t addr, const CArray & data)
{
CArray prev;
int i, j, k, res = 0;
const unsigned blocksize = 12;
for (i = 0; i < data (); i += blocksize)
{
j = blocksize;
if (i + j > data ())
j = data () - i;
k = A_Memory_Write (addr + i, CArray (data.array () + i, j));
if (k == -1)
return -1;
}
return res;
}
syntax highlighted by Code2HTML, v. 0.9.1