/*
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 "managementclient.h"
#include "management.h"
#include "loadimage.h"
void
ReadIndividualAddresses (Layer3 * l3, Trace * t, ClientConnection * c,
pth_event_t stop)
{
try
{
Layer7_Broadcast b (l3, t);
CArray erg;
Array < eibaddr_t > e = b.A_IndividualAddress_Read ();
erg.resize (2 + 2 * e ());
EIBSETTYPE (erg, EIB_M_INDIVIDUAL_ADDRESS_READ);
for (unsigned i = 0; i < e (); i++)
{
erg[2 + i * 2] = (e[i] >> 8) & 0xff;
erg[2 + i * 2 + 1] = (e[i]) & 0xff;
}
c->sendmessage (erg (), erg.array (), stop);
}
catch (Exception e)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
}
}
void
ChangeProgMode (Layer3 * l3, Trace * t, ClientConnection * c,
pth_event_t stop)
{
try
{
eibaddr_t dest;
uchar res[3];
int i;
EIBSETTYPE (res, EIB_PROG_MODE);
res[2] = 0;
if (c->size < 5)
{
c->sendreject (stop);
return;
}
dest = (c->buf[2] << 8) | (c->buf[3]);
Management_Connection m (l3, t, dest);
switch (c->buf[4])
{
case 0:
if (m.X_Progmode_Off () == -1)
c->sendreject (stop);
else
c->sendmessage (3, res, stop);
break;
case 1:
if (m.X_Progmode_On () == -1)
c->sendreject (stop);
else
c->sendmessage (3, res, stop);
break;
case 2:
if (m.X_Progmode_Toggle () == -1)
c->sendreject (stop);
else
c->sendmessage (3, res, stop);
break;
case 3:
if ((i = m.X_Progmode_Status ()) == -1)
c->sendreject (stop);
else
{
res[2] = i;
c->sendmessage (3, res, stop);
}
break;
default:
c->sendreject (stop);
}
}
catch (Exception e)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
}
}
void
GetMaskVersion (Layer3 * l3, Trace * t, ClientConnection * c,
pth_event_t stop)
{
try
{
eibaddr_t dest;
uchar res[4];
uint16_t maskver;
EIBSETTYPE (res, EIB_MASK_VERSION);
res[2] = 0;
if (c->size < 4)
{
c->sendreject (stop);
return;
}
dest = (c->buf[2] << 8) | (c->buf[3]);
Management_Connection m (l3, t, dest);
if (m.A_Device_Descriptor_Read (maskver) == -1)
c->sendreject (stop);
else
{
res[2] = (maskver >> 8) & 0xff;
res[3] = (maskver) & 0xff;
c->sendmessage (4, res, stop);
}
}
catch (Exception e)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
}
}
void
WriteIndividualAddress (Layer3 * l3, Trace * t, ClientConnection * c,
pth_event_t stop)
{
try
{
eibaddr_t dest;
uint16_t maskver;
if (c->size < 4)
{
c->sendreject (stop);
return;
}
dest = (c->buf[2] << 8) | (c->buf[3]);
Layer7_Broadcast b (l3, t);
{
Management_Connection m (l3, t, dest);
if (m.A_Device_Descriptor_Read (maskver) != -1)
{
c->sendreject (stop, EIB_ERROR_ADDR_EXISTS);
return;
}
}
Array < eibaddr_t > addr = b.A_IndividualAddress_Read ();
if (addr () > 1)
{
c->sendreject (stop, EIB_ERROR_MORE_DEVICE);
return;
}
if (addr () == 0)
{
c->sendreject (stop, EIB_ERROR_TIMEOUT);
return;
}
b.A_IndividualAddress_Write (dest);
// wait 100ms
pth_usleep (100000);
Management_Connection m1 (l3, t, dest);
if (m1.A_Device_Descriptor_Read (maskver) == -1)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
return;
}
if (m1.X_Progmode_Off () == -1)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
return;
}
c->sendreject (stop, EIB_M_INDIVIDUAL_ADDRESS_WRITE);
}
catch (Exception e)
{
c->sendreject (stop, EIB_PROCESSING_ERROR);
}
}
void
ManagementConnection (Layer3 * l3, Trace * t, ClientConnection * c,
pth_event_t stop)
{
try
{
eibaddr_t dest;
uint16_t maskver;
int16_t val;
uchar buf[10];
int i;
eibkey_type key;
if (c->size < 4)
{
c->sendreject (stop);
return;
}
dest = (c->buf[2] << 8) | (c->buf[3]);
Management_Connection m (l3, t, dest);
if (m.A_Device_Descriptor_Read (maskver) == -1)
{
c->sendreject (stop);
return;
}
c->sendreject (stop, EIB_MC_CONNECTION);
do
{
i = c->readmessage (stop);
if (i != -1)
switch (EIBTYPE (c->buf))
{
case EIB_MC_PROG_MODE:
if (c->size < 3)
{
c->sendreject (stop);
break;
}
EIBSETTYPE (buf, EIB_MC_PROG_MODE);
buf[2] = 0;
switch (c->buf[2])
{
case 0:
if (m.X_Progmode_Off () == -1)
c->sendreject (stop);
else
c->sendmessage (3, buf, stop);
break;
case 1:
if (m.X_Progmode_On () == -1)
c->sendreject (stop);
else
c->sendmessage (3, buf, stop);
break;
case 2:
if (m.X_Progmode_Toggle () == -1)
c->sendreject (stop);
else
c->sendmessage (3, buf, stop);
break;
case 3:
if ((i = m.X_Progmode_Status ()) == -1)
c->sendreject (stop);
else
{
buf[2] = i;
c->sendmessage (3, buf, stop);
}
break;
default:
c->sendreject (stop);
}
break;
case EIB_MC_MASK_VERSION:
if (m.A_Device_Descriptor_Read (maskver) == -1)
c->sendreject (stop);
else
{
EIBSETTYPE (buf, EIB_MC_MASK_VERSION);
buf[2] = (maskver >> 8) & 0xff;
buf[3] = (maskver) & 0xff;
c->sendmessage (4, buf, stop);
}
break;
case EIB_MC_PEI_TYPE:
if (m.X_Get_PEIType (val) == -1)
c->sendreject (stop);
else
{
EIBSETTYPE (buf, EIB_MC_PEI_TYPE);
buf[2] = (val >> 8) & 0xff;
buf[3] = (val) & 0xff;
c->sendmessage (4, buf, stop);
}
break;
case EIB_MC_ADC_READ:
if (c->size < 4)
{
c->sendreject (stop);
break;
}
if (m.A_ADC_Read (c->buf[2], c->buf[3], val) == -1)
c->sendreject (stop);
else
{
EIBSETTYPE (buf, EIB_MC_ADC_READ);
buf[2] = (val >> 8) & 0xff;
buf[3] = (val) & 0xff;
c->sendmessage (4, buf, stop);
}
break;
case EIB_MC_READ:
if (c->size < 6)
{
c->sendreject (stop);
break;
}
{
memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]);
unsigned len = (c->buf[4] << 8) | (c->buf[5]);
CArray data, erg;
if (m.X_Memory_Read_Block (addr, len, data) == -1)
c->sendreject (stop);
else
{
erg.resize (6);
EIBSETTYPE (erg, EIB_MC_READ);
erg.setpart (data, 2);
c->sendmessage (erg (), erg.array (), stop);
}
}
break;
case EIB_MC_WRITE:
if (c->size < 6)
{
c->sendreject (stop);
break;
}
{
memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]);
unsigned len = (c->buf[4] << 8) | (c->buf[5]);
if (c->size < len + 6)
{
c->sendreject (stop);
break;
}
i = m.X_Memory_Write_Block (addr, CArray (c->buf + 6, len));
if (i == -2)
c->sendreject (stop, EIB_ERROR_VERIFY);
else if (i != 0)
c->sendreject (stop, EIB_PROCESSING_ERROR);
else
c->sendreject (stop, EIB_MC_WRITE);
}
break;
case EIB_MC_PROP_READ:
if (c->size < 7)
{
c->sendreject (stop);
break;
}
{
CArray data, erg;
if (m.
A_Property_Read (c->buf[2], c->buf[3],
(c->buf[4] << 8) | c->buf[5], c->buf[6],
data) == -1)
c->sendreject (stop);
else
{
erg.resize (2);
EIBSETTYPE (erg, EIB_MC_PROP_READ);
erg.setpart (data, 2);
c->sendmessage (erg (), erg.array (), stop);
}
}
break;
case EIB_MC_PROP_WRITE:
if (c->size < 7)
{
c->sendreject (stop);
break;
}
{
CArray data, erg;
if (m.
A_Property_Write (c->buf[2], c->buf[3],
(c->buf[4] << 8) | c->buf[5], c->buf[6],
CArray (c->buf + 7, c->size - 7),
erg) == -1)
c->sendreject (stop);
else
{
erg.resize (2);
EIBSETTYPE (erg, EIB_MC_PROP_WRITE);
erg.setpart (data, 2);
c->sendmessage (erg (), erg.array (), stop);
}
}
break;
case EIB_MC_AUTHORIZE:
if (c->size < 6)
{
c->sendreject (stop);
break;
}
EIBSETTYPE (buf, EIB_MC_AUTHORIZE);
key =
(c->buf[2] << 24) | (c->buf[3] << 16) | (c->
buf[4] << 8) | (c->
buf
[5]);
if (m.A_Authorize (key, buf[2]) == -1)
c->sendreject (stop);
else
c->sendmessage (3, buf, stop);
break;
case EIB_MC_KEY_WRITE:
if (c->size < 7)
{
c->sendreject (stop);
break;
}
key =
(c->buf[2] << 24) | (c->buf[3] << 16) | (c->
buf[4] << 8) | (c->
buf
[5]);
if (m.A_KeyWrite (key, *(c->buf + 6)) == -1)
c->sendreject (stop);
else
c->sendreject (stop, EIB_MC_KEY_WRITE);
break;
case EIB_MC_PROP_DESC:
if (c->size < 4)
{
c->sendreject (stop);
break;
}
if (m.
A_Property_Desc (c->buf[2], c->buf[3], 0, buf[2], maskver,
buf[5]) == -1)
c->sendreject (stop);
else
{
EIBSETTYPE (buf, EIB_MC_PROP_DESC);
buf[3] = (maskver >> 8) & 0xff;
buf[4] = (maskver) & 0xff;
c->sendmessage (6, buf, stop);
}
break;
case EIB_MC_PROP_SCAN:
{
Array < PropertyInfo > p;
if (m.X_PropertyScan (p) == -1)
c->sendreject (stop);
else
{
CArray erg;
erg.resize (2 + p () * 6);
EIBSETTYPE (erg, EIB_MC_PROP_SCAN);
for (unsigned i = 0; i < p (); i++)
{
erg[i * 6 + 2] = p[i].obj;
erg[i * 6 + 3] = p[i].property;
erg[i * 6 + 4] = p[i].type;
erg[i * 6 + 5] = (p[i].count >> 8) & 0xff;
erg[i * 6 + 6] = (p[i].count) & 0xff;
erg[i * 6 + 7] = p[i].access;
}
c->sendmessage (erg (), erg.array (), stop);
}
}
break;
case EIB_RESET_CONNECTION:
i = -1;
break;
case EIB_MC_RESTART:
m.A_Restart ();
c->sendreject (stop, EIB_MC_RESTART);
break;
case EIB_MC_WRITE_NOVERIFY:
if (c->size < 6)
{
c->sendreject (stop);
break;
}
{
memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]);
unsigned len = (c->buf[4] << 8) | (c->buf[5]);
if (c->size < len + 6)
{
c->sendreject (stop);
break;
}
i = m.A_Memory_Write_Block (addr, CArray (c->buf + 6, len));
if (i != 0)
c->sendreject (stop, EIB_PROCESSING_ERROR);
else
c->sendreject (stop, EIB_MC_WRITE_NOVERIFY);
}
break;
default:
c->sendreject (stop);
}
}
while (i != -1);
}
catch (Exception e)
{
c->sendreject (stop);
}
}
void
LoadImage (Layer3 * l3, Trace * t, ClientConnection * c, pth_event_t stop)
{
uchar buf[200];
CArray img (c->buf + 2, c->size - 2);
CArray erg;
int j;
BCUImage *i;
BCU_LOAD_RESULT r = PrepareLoadImage (img, i);
if (r != IMG_IMAGE_LOADABLE)
{
if (i)
delete i;
EIBSETTYPE (buf, EIB_LOAD_IMAGE);
buf[2] = (r >> 8) & 0xff;
buf[3] = (r) & 0xff;
c->sendmessage (4, buf, stop);
return;
}
try
{
uint16_t maskver;
uchar c;
r = IMG_NO_DEVICE_CONNECTION;
Management_Connection m (l3, t, i->addr);
r = IMG_MASK_READ_FAILED;
if (m.A_Device_Descriptor_Read (maskver) == -1)
goto out;
r = IMG_WRONG_MASK_VERSION;
if (i->BCUType == BCUImage::B_bcu1)
{
if (maskver != 0x0012)
goto out;
/* set error flags in BCU (0x10D = 0x00) */
r = IMG_CLEAR_ERROR;
c = 0;
if (m.X_Memory_Write_Block (0x010d, CArray (&c, 1)) != 0)
goto out;
/*set length of the address tab to 1 */
r = IMG_RESET_ADDR_TAB;
c = 0x01;
if (m.X_Memory_Write_Block (0x0116, CArray (&c, 1)) != 0)
goto out;
/*load the data from 0x100 to 0x100 */
r = IMG_LOAD_HEADER;
c = 0xff;
if (m.X_Memory_Write_Block (0x0100, CArray (&c, 1)) != 0)
goto out;
/*load the data from 0x103 to 0x10C */
if (m.
X_Memory_Write_Block (0x0103,
CArray (i->code.array () + 0x03, 10)) != 0)
goto out;
/*load the data from 0x10E to 0x115 */
if (m.
X_Memory_Write_Block (0x010E,
CArray (i->code.array () + 0x0E, 8)) != 0)
goto out;
/*load the data from 0x119H to eeprom end */
r = IMG_LOAD_MAIN;
if (m.
X_Memory_Write_Block (0x119,
CArray (i->code.array () + 0x19,
i->code () - 0x19)) != 0)
goto out;
if (m.X_Memory_Write_Block (0x0100, CArray (i->code.array (), 1)) !=
0)
goto out;
/*erase the user RAM (0x0CE to 0x0DF) */
r = IMG_ZERO_RAM;
uchar zero[18] = { 0 };
if (m.X_Memory_Write_Block (0x00ce, CArray (zero, 18)) != 0)
goto out;
/* set the length of the address table */
r = IMG_FINALIZE_ADDR_TAB;
if (m.
X_Memory_Write_Block (0x0116,
CArray (i->code.array () + 0x16, 1)) != 0)
goto out;
/* reset all error flags in the BCU (0x10D = 0xFF) */
r = IMG_PREPARE_RUN;
c = 0xff;
if (m.X_Memory_Write_Block (0x010d, CArray (&c, 1)) != 0)
goto out;
r = IMG_RESTART;
m.A_Restart ();
r = IMG_LOADED;
goto out;
}
if (i->BCUType == BCUImage::B_bcu20 || i->BCUType == BCUImage::B_bcu21)
{
if (maskver != 0x0020 && i->BCUType == BCUImage::B_bcu20)
goto out;
if (maskver != 0x0021 && i->BCUType == BCUImage::B_bcu21)
goto out;
uchar level;
r = IMG_AUTHORIZATION_FAILED;
if (m.A_Authorize (i->installkey, level) == -1)
goto out;
if (level)
goto out;
r = IMG_KEY_WRITE;
for (j = 0; j < 3; j++)
{
level = j;
if (m.A_KeyWrite (i->keys[level], level) == -1)
goto out;
if (j != level)
goto out;
}
for (j = 0; j < i->load (); j++)
{
r = i->load[j].error;
if (i->load[j].obj != 0xff)
{
if (m.A_Property_Write (i->load[j].obj, i->load[j].prop,
i->load[j].start, 1, i->load[j].req,
erg) == -1)
goto out;
if (erg != i->load[j].result)
goto out;
}
if (i->load[j].memaddr != 0xffff)
if (m.
X_Memory_Write_Block (i->load[j].memaddr,
CArray (i->code.array () +
i->load[j].memaddr - 0x100,
i->load[j].len)) != 0)
goto out;
}
r = IMG_RESTART;
m.A_Restart ();
r = IMG_LOADED;
goto out;
}
}
catch (Exception e)
{
}
out:
if (i)
delete i;
EIBSETTYPE (buf, EIB_LOAD_IMAGE);
buf[2] = (r >> 8) & 0xff;
buf[3] = (r) & 0xff;
c->sendmessage (4, buf, stop);
}
syntax highlighted by Code2HTML, v. 0.9.1