Commit dcb32a3b authored by Robert Karlsson's avatar Robert Karlsson

Profibus/Profinet fixes, added rt_elog_dump utility

parent 95ad1973
...@@ -52,3 +52,7 @@ ...@@ -52,3 +52,7 @@
120615 cs profinet Profinet configurator, sorting of moduletypes and iodata length settings 120615 cs profinet Profinet configurator, sorting of moduletypes and iodata length settings
120813 cs profibus Profibus configurator in xtt, bugfix in errorhandling for empty gsd-file (refs #112) 120813 cs profibus Profibus configurator in xtt, bugfix in errorhandling for empty gsd-file (refs #112)
120813 cs profibus Profibus device Janitza umg961 added 120813 cs profibus Profibus device Janitza umg961 added
120829 rk profinet IO offset caclulation bugfix for modules with both in- and output.
121130 rk profibus Handling of large prm data areas.
121130 rk profibus Moved event handling to separate thread. Not dependant on io-read cycle time.
...@@ -72,6 +72,11 @@ ...@@ -72,6 +72,11 @@
#include "rt_io_profiboard.h" #include "rt_io_profiboard.h"
typedef struct _agent_args {
void *local;
io_sAgent *ap;
} agent_args;
typedef struct { typedef struct {
int hServiceReadDevice; // Handle for Service device int hServiceReadDevice; // Handle for Service device
int hServiceWriteDevice; // Handle for Service device int hServiceWriteDevice; // Handle for Service device
...@@ -81,6 +86,9 @@ typedef struct { ...@@ -81,6 +86,9 @@ typedef struct {
unsigned char CurrentBoardNumber; unsigned char CurrentBoardNumber;
int slave_diag_requested; int slave_diag_requested;
int hDpsBoardDevice; // Handle for DP-Slave Output-Data device int hDpsBoardDevice; // Handle for DP-Slave Output-Data device
pthread_t events;
pthread_mutex_t mutex;
agent_args args;
} io_sAgentLocal; } io_sAgentLocal;
#define DP_MAX_SERVICE_RETRY 10 #define DP_MAX_SERVICE_RETRY 10
...@@ -441,6 +449,94 @@ static void dp_get_slave_diag_con(T_DP_GET_SLAVE_DIAG_CON * get_slave_diag_con_p ...@@ -441,6 +449,94 @@ static void dp_get_slave_diag_con(T_DP_GET_SLAVE_DIAG_CON * get_slave_diag_con_p
} /* diag_data_len */ } /* diag_data_len */
} }
/*----------------------------------------------------------------------------*\
Starts download sequence of prm data to one slave
\*----------------------------------------------------------------------------*/
static pwr_tStatus start_download_seq (
T_PROFI_DEVICE_HANDLE *hDevice,
pwr_sClass_Pb_DP_Slave *op
)
{
T_PROFI_SERVICE_DESCR sdb;
T_DP_START_SEQ_REQ ssrp;
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
USIGN16 timeout = 400;
T_PROFI_SERVICE_DESCR con_ind_sdb;
INT16 result; /* !!! local result variable !!! */
sdb.comm_ref = 0;
sdb.layer = DP;
sdb.service = DP_START_SEQ_LOC;
sdb.primitive = REQ;
sdb.invoke_id = 0;
sdb.result = 0;
ssrp.rem_add = 0;
ssrp.area_code = op->SlaveAddress;
ssrp.timeout = timeout;
profi_snd_req_res(hDevice, &sdb, &ssrp, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_START_SEQ_LOC) &&
(con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN;
return (PB_TRUE);
}
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
/*----------------------------------------------------------------------------*\
Starts download sequence of prm data to one slave
\*----------------------------------------------------------------------------*/
static pwr_tStatus end_download_seq (
T_PROFI_DEVICE_HANDLE *hDevice,
pwr_sClass_Pb_DP_Slave *op
)
{
T_PROFI_SERVICE_DESCR sdb;
T_DP_END_SEQ_REQ esrp;
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
INT16 result; /* !!! local result variable !!! */
sdb.comm_ref = 0;
sdb.layer = DP;
sdb.service = DP_END_SEQ_LOC;
sdb.primitive = REQ;
sdb.invoke_id = 0;
sdb.result = 0;
esrp.rem_add = 0;
esrp.dummy = 0;
profi_snd_req_res(hDevice, &sdb, &esrp, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_END_SEQ_LOC) &&
(con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN;
return (PB_TRUE);
}
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
/*----------------------------------------------------------------------------*\ /*----------------------------------------------------------------------------*\
Initializes one DP slave in the master card Initializes one DP slave in the master card
\*----------------------------------------------------------------------------*/ \*----------------------------------------------------------------------------*/
...@@ -457,12 +553,15 @@ static pwr_tStatus dp_download_slave ( ...@@ -457,12 +553,15 @@ static pwr_tStatus dp_download_slave (
unsigned char param[512]; unsigned char param[512];
} slave_data; } slave_data;
char *send_buf;
T_DP_SLAVE_PARA_SET prm_head; T_DP_SLAVE_PARA_SET prm_head;
T_DP_PRM_DATA prm_data; T_DP_PRM_DATA prm_data;
T_DP_AAT_DATA aat_data; T_DP_AAT_DATA aat_data;
T_DP_SLAVE_USER_DATA user_data; T_DP_SLAVE_USER_DATA user_data;
USIGN16 download_data_size; USIGN16 download_data_size;
USIGN16 data_len; USIGN16 data_len;
pwr_tBoolean failure = FALSE;
USIGN8 con_ind_buffer [256]; USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256; USIGN16 con_ind_buffer_len = 256;
...@@ -475,7 +574,7 @@ static pwr_tStatus dp_download_slave ( ...@@ -475,7 +574,7 @@ static pwr_tStatus dp_download_slave (
op->PrmUserDataLen + op->ConfigDataLen + op->PrmUserDataLen + op->ConfigDataLen +
sizeof(aat_data) + sizeof(user_data); sizeof(aat_data) + sizeof(user_data);
data_len = sizeof(slave_data.drp) + download_data_size; data_len = download_data_size;
sdb.comm_ref = 0; sdb.comm_ref = 0;
sdb.layer = DP; sdb.layer = DP;
...@@ -484,11 +583,6 @@ static pwr_tStatus dp_download_slave ( ...@@ -484,11 +583,6 @@ static pwr_tStatus dp_download_slave (
sdb.invoke_id = 0; sdb.invoke_id = 0;
sdb.result = 0; sdb.result = 0;
slave_data.drp.data_len = download_data_size;
slave_data.drp.rem_add = 0;
slave_data.drp.area_code = op->SlaveAddress;
slave_data.drp.add_offset = 0;
prm_head.slave_para_len = swap16(download_data_size); prm_head.slave_para_len = swap16(download_data_size);
prm_head.sl_flag = DP_SL_NEW_PRM | DP_SL_ACTIVE; prm_head.sl_flag = DP_SL_NEW_PRM | DP_SL_ACTIVE;
prm_head.slave_type = DP_SLAVE_TYPE_DP; prm_head.slave_type = DP_SLAVE_TYPE_DP;
...@@ -529,20 +623,58 @@ static pwr_tStatus dp_download_slave ( ...@@ -529,20 +623,58 @@ static pwr_tStatus dp_download_slave (
memcpy(&slave_data.param[i], &user_data, sizeof(user_data)); memcpy(&slave_data.param[i], &user_data, sizeof(user_data));
i += sizeof(user_data); i += sizeof(user_data);
slave_data.drp.rem_add = 0;
slave_data.drp.area_code = op->SlaveAddress;
slave_data.drp.add_offset = 0;
send_buf = (char *) slave_data.param;
if (data_len > DP_MAX_DOWNLOAD_DATA_LEN) {
if (!start_download_seq(hDevice, op)) {
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
}
while (download_data_size > 0) {
slave_data.drp.data_len = MIN(download_data_size, DP_MAX_DOWNLOAD_DATA_LEN);
profi_snd_req_res(hDevice, &sdb, &slave_data, PB_FALSE); profi_snd_req_res(hDevice, &sdb, &slave_data, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result); try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_DOWNLOAD_LOC) && if (con_ind_sdb.service == DP_DOWNLOAD_LOC) {
(con_ind_sdb.primitive == CON ) && if ((con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) { (con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN; op->Status = PB__NOCONN;
return (PB_TRUE); } else {
op->Status = PB__INITFAIL;
failure = TRUE;
break;
}
} }
if (download_data_size > DP_MAX_DOWNLOAD_DATA_LEN) {
download_data_size -= DP_MAX_DOWNLOAD_DATA_LEN;
slave_data.drp.add_offset += DP_MAX_DOWNLOAD_DATA_LEN;
send_buf += DP_MAX_DOWNLOAD_DATA_LEN;
memcpy(slave_data.param, send_buf, MIN(download_data_size, DP_MAX_DOWNLOAD_DATA_LEN));
}
else
download_data_size = 0;
}
if (data_len > DP_MAX_DOWNLOAD_DATA_LEN) {
if (!end_download_seq(hDevice, op)) {
op->Status = PB__INITFAIL; op->Status = PB__INITFAIL;
return (PB_FALSE);
}
}
if (failure)
return (PB_FALSE); return (PB_FALSE);
else
return (PB_TRUE);
} }
...@@ -601,6 +733,215 @@ static pwr_tStatus dp_io_offsets ( ...@@ -601,6 +733,215 @@ static pwr_tStatus dp_io_offsets (
return (PB_FALSE); return (PB_FALSE);
} }
/* Supervision thread */
void *handle_events(void *ptr) {
agent_args *args;
io_sAgentLocal *local;
io_sAgent *ap;
short sts;
T_PROFI_DEVICE_HANDLE *hDevice;
pwr_sClass_Pb_Profiboard *op;
char s [128];
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
T_DP_GET_SLAVE_DIAG_CON *get_slave_diag_con_ptr;
struct timespec rqtp = {0, 10000000}; // 10 ms
args = (agent_args *) ptr;
local = (io_sAgentLocal *) args->local;
ap = args->ap;
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op;
/* If everything is fine we should be in state OPERATE
Make a poll to see if there are diagnostics, the answer also tell us
if there are any hardware faults. In that case, make a reset and a new init. */
while (1) {
if (op->DisableBus) exit(0);
pthread_mutex_lock(&local->mutex);
con_ind_buffer_len = 256;
sts = profi_rcv_con_ind ( hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len);
if (sts == CON_IND_RECEIVED) {
if (con_ind_sdb.primitive == CON) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
if (op->Status == PB__NOTINIT) {
op->Status = PB__STOPPED;
errh_Info( "Profibus DP Master %s to state STOPPED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (op->Status == PB__STOPPED) {
op->Status = PB__CLEARED;
errh_Info( "Profibus DP Master %s to state CLEARED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_OPERATE);
}
else if (op->Status == PB__CLEARED) {
errh_Info( "Profibus DP Master %s to state OPERATE", ap->Name);
op->Status = PB__NORMAL;
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[2]++;
local->slave_diag_requested = op->Diag[3] = PB_FALSE;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if (get_slave_diag_con_ptr->diag_entries) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
dp_get_slave_diag (hDevice);
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %x neg con rec", ap->Name, *((unsigned short *) con_ind_buffer) );
} /* else POS */
} /* if CON */
else if (con_ind_sdb.primitive == IND) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
case FMB_FM2_EVENT: {
switch (((T_FMB_FM2_EVENT_IND FAR*) con_ind_buffer)->reason) {
case FM2_FAULT_ADDRESS : sprintf (s, "Duplicate address recognized"); break;
case FM2_FAULT_PHY : sprintf (s, "Phys.layer is malfunctioning"); break;
case FM2_FAULT_TTO : sprintf (s, "Time out on bus detected "); break;
case FM2_FAULT_SYN : sprintf (s, "No receiver synchronization "); break;
case FM2_FAULT_OUT_OF_RING : sprintf (s, "Station out of ring "); break;
case FM2_GAP_EVENT : sprintf (s, "New station in ring "); break;
default : sprintf (s, "Unknown reason code received");
} /* switch reason */
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
break;
} /* case FMB_FM2_EVENT */
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
USIGN8 usif_state;
usif_state = ((T_DP_ACT_PARAM_IND FAR*) con_ind_buffer)->activate;
switch (usif_state) {
case DP_OP_MODE_STOP : {
op->Status = PB__STOPPED;
sprintf (s, "Mode changed to STOP");
break;
}
case DP_OP_MODE_CLEAR : {
op->Status = PB__CLEARED;
sprintf (s, "Mode changed to CLEAR");
break;
}
case DP_OP_MODE_OPERATE: {
op->Status = PB__NORMAL;
sprintf (s, "Mode changed to OPERATE");
break;
}
}
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
if (usif_state == DP_OP_MODE_STOP) {
usif_state = DP_OP_MODE_CLEAR;
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (usif_state == DP_OP_MODE_CLEAR) {
usif_state = DP_OP_MODE_OPERATE;
dp_act_param_loc (hDevice, DP_OP_MODE_OPERATE);
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[0]++;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if ( (get_slave_diag_con_ptr->diag_entries) &&
(! local->slave_diag_requested ) ) {
if (dp_get_slave_diag(hDevice)) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
} else {
errh_Warning( "Profibus - Request for diag failed.");
}
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %x neg ind rec", ap->Name, *((unsigned short *) con_ind_buffer) );
} /* else POS */
} /* if IND */
} else if (sts != NO_CON_IND_RECEIVED) {
op->Status = PB__NOTINIT;
} else {
if (local->slave_diag_requested) {
errh_Info( "Profibus - Diag re-request");
dp_get_slave_diag(hDevice);
}
}
pthread_mutex_unlock(&local->mutex);
nanosleep(&rqtp, NULL);
}
}
/*----------------------------------------------------------------------------*\ /*----------------------------------------------------------------------------*\
Init method for the Pb_profiboard agent Init method for the Pb_profiboard agent
\*----------------------------------------------------------------------------*/ \*----------------------------------------------------------------------------*/
...@@ -613,6 +954,8 @@ static pwr_tStatus IoAgentInit ( ...@@ -613,6 +954,8 @@ static pwr_tStatus IoAgentInit (
pwr_tUInt16 sts; pwr_tUInt16 sts;
pwr_tStatus status; pwr_tStatus status;
T_PROFI_DEVICE_HANDLE *hDevice; T_PROFI_DEVICE_HANDLE *hDevice;
io_sAgentLocal *local;
char ok; char ok;
pwr_tObjid slave_objid; pwr_tObjid slave_objid;
...@@ -635,6 +978,9 @@ static pwr_tStatus IoAgentInit ( ...@@ -635,6 +978,9 @@ static pwr_tStatus IoAgentInit (
} }
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local; hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
local = (io_sAgentLocal *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op; op = (pwr_sClass_Pb_Profiboard *) ap->op;
op->Status = PB__NOTINIT; op->Status = PB__NOTINIT;
...@@ -775,6 +1121,21 @@ static pwr_tStatus IoAgentInit ( ...@@ -775,6 +1121,21 @@ static pwr_tStatus IoAgentInit (
return IO__ERRINIDEVICE; return IO__ERRINIDEVICE;
} }
} */ } */
/* Active supervision thread */
pthread_attr_t attr;
pthread_mutexattr_t mutexattr;
local->args.local = local;
local->args.ap = ap;
pthread_mutexattr_init(&mutexattr);
pthread_mutex_init(&local->mutex, &mutexattr);
pthread_mutexattr_destroy(&mutexattr);
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
pthread_create(&local->events, &attr, handle_events, &local->args);
} }
else else
op->Status = PB__DISABLED; op->Status = PB__DISABLED;
...@@ -846,13 +1207,6 @@ static pwr_tStatus IoAgentRead ( ...@@ -846,13 +1207,6 @@ static pwr_tStatus IoAgentRead (
T_PROFI_DEVICE_HANDLE *hDevice; T_PROFI_DEVICE_HANDLE *hDevice;
pwr_sClass_Pb_Profiboard *op; pwr_sClass_Pb_Profiboard *op;
pwr_tUInt16 sts; pwr_tUInt16 sts;
static int count;
char s [128];
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
T_DP_GET_SLAVE_DIAG_CON FAR *get_slave_diag_con_ptr;
pwr_sClass_Pb_Profiboard *mp; pwr_sClass_Pb_Profiboard *mp;
pwr_sClass_Pb_DP_Slave *sp; pwr_sClass_Pb_DP_Slave *sp;
...@@ -863,6 +1217,8 @@ static pwr_tStatus IoAgentRead ( ...@@ -863,6 +1217,8 @@ static pwr_tStatus IoAgentRead (
local = (io_sAgentLocal *) ap->Local; local = (io_sAgentLocal *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op; op = (pwr_sClass_Pb_Profiboard *) ap->op;
pthread_mutex_lock(&local->mutex);
/* Iterate over the slaves. */ /* Iterate over the slaves. */
for (slave_list = ap->racklist; slave_list != NULL; for (slave_list = ap->racklist; slave_list != NULL;
slave_list = slave_list->next) { slave_list = slave_list->next) {
...@@ -879,202 +1235,7 @@ static pwr_tStatus IoAgentRead ( ...@@ -879,202 +1235,7 @@ static pwr_tStatus IoAgentRead (
} }
pthread_mutex_unlock(&local->mutex);
/* If everything is fine we should be in state OPERATE
Make a poll to see if there are diagnostics, the answer also tell us
if there are any hardware faults. In that case, make a reset and a new init. */
count++;
if ((op->Process & io_mProcess_Profibus) && (ctx->Process != io_mProcess_Profibus))
return IO__SUCCESS;
if (op->DisableBus != 1) {
switch (op->Status) {
case PB__NORMAL:
case PB__STOPPED:
case PB__CLEARED:
case PB__NOTINIT:
sts = profi_rcv_con_ind ( hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len);
if (sts == CON_IND_RECEIVED) {
if (con_ind_sdb.primitive == CON) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
if (op->Status == PB__NOTINIT) {
op->Status = PB__STOPPED;
errh_Info( "Profibus DP Master %s to state STOPPED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (op->Status == PB__STOPPED) {
op->Status = PB__CLEARED;
errh_Info( "Profibus DP Master %s to state CLEARED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_OPERATE);
}
else if (op->Status == PB__CLEARED) {
errh_Info( "Profibus DP Master %s to state OPERATE", ap->Name);
op->Status = PB__NORMAL;
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[0]);
op->Diag[2]++;
local->slave_diag_requested = op->Diag[3] = PB_FALSE;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if (get_slave_diag_con_ptr->diag_entries) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
dp_get_slave_diag (hDevice);
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %d neg con rec", ap->Name, count );
} /* else POS */
} /* if CON */
else if (con_ind_sdb.primitive == IND) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
case FMB_FM2_EVENT: {
switch (((T_FMB_FM2_EVENT_IND FAR*) con_ind_buffer)->reason) {
case FM2_FAULT_ADDRESS : sprintf (s, "Duplicate address recognized"); break;
case FM2_FAULT_PHY : sprintf (s, "Phys.layer is malfunctioning"); break;
case FM2_FAULT_TTO : sprintf (s, "Time out on bus detected "); break;
case FM2_FAULT_SYN : sprintf (s, "No receiver synchronization "); break;
case FM2_FAULT_OUT_OF_RING : sprintf (s, "Station out of ring "); break;
case FM2_GAP_EVENT : sprintf (s, "New station in ring "); break;
default : sprintf (s, "Unknown reason code received");
} /* switch reason */
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
break;
} /* case FMB_FM2_EVENT */
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
USIGN8 usif_state;
usif_state = ((T_DP_ACT_PARAM_IND FAR*) con_ind_buffer)->activate;
switch (usif_state) {
case DP_OP_MODE_STOP : {
op->Status = PB__STOPPED;
sprintf (s, "Mode changed to STOP");
break;
}
case DP_OP_MODE_CLEAR : {
op->Status = PB__CLEARED;
sprintf (s, "Mode changed to CLEAR");
break;
}
case DP_OP_MODE_OPERATE: {
op->Status = PB__NORMAL;
sprintf (s, "Mode changed to OPERATE");
break;
}
}
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
if (usif_state == DP_OP_MODE_STOP) {
usif_state = DP_OP_MODE_CLEAR;
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (usif_state == DP_OP_MODE_CLEAR) {
usif_state = DP_OP_MODE_OPERATE;
dp_act_param_loc (hDevice, DP_OP_MODE_OPERATE);
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[0]++;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if ( (get_slave_diag_con_ptr->diag_entries) &&
(! local->slave_diag_requested ) ) {
if (dp_get_slave_diag(hDevice)) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
} else {
errh_Warning( "Profibus - Request for diag failed.");
}
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %d neg ind rec", ap->Name, count );
} /* else POS */
} /* if IND */
} else if (sts != NO_CON_IND_RECEIVED) {
op->Status = PB__NOTINIT;
} else {
if (local->slave_diag_requested) {
errh_Info( "Profibus - Diag re-request");
dp_get_slave_diag(hDevice);
}
}
break;
default:
op->Status = PB__NOTINIT;
errh_Error( "Reconfig of Profibus DP Master %s - %d", ap->Name, count );
IoAgentClose(ctx, ap);
IoAgentInit(ctx, ap);
break;
}
}
return IO__SUCCESS; return IO__SUCCESS;
} }
...@@ -1088,6 +1249,7 @@ static pwr_tStatus IoAgentWrite ( ...@@ -1088,6 +1249,7 @@ static pwr_tStatus IoAgentWrite (
io_sAgent *ap io_sAgent *ap
) )
{ {
io_sAgentLocal *local;
T_PROFI_DEVICE_HANDLE *hDevice; T_PROFI_DEVICE_HANDLE *hDevice;
pwr_tUInt16 sts; pwr_tUInt16 sts;
...@@ -1096,6 +1258,9 @@ static pwr_tStatus IoAgentWrite ( ...@@ -1096,6 +1258,9 @@ static pwr_tStatus IoAgentWrite (
io_sRack *slave_list; io_sRack *slave_list;
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local; hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
local = (io_sAgentLocal *) ap->Local;
pthread_mutex_lock(&local->mutex);
/* Iterate over the slaves. */ /* Iterate over the slaves. */
for (slave_list = ap->racklist; slave_list != NULL; for (slave_list = ap->racklist; slave_list != NULL;
...@@ -1119,6 +1284,8 @@ static pwr_tStatus IoAgentWrite ( ...@@ -1119,6 +1284,8 @@ static pwr_tStatus IoAgentWrite (
} }
pthread_mutex_unlock(&local->mutex);
return IO__SUCCESS; return IO__SUCCESS;
} }
...@@ -1145,6 +1312,10 @@ static pwr_tStatus IoAgentClose ( ...@@ -1145,6 +1312,10 @@ static pwr_tStatus IoAgentClose (
local = (io_sAgentLocal *) ap->Local; local = (io_sAgentLocal *) ap->Local;
if ( !local) return IO__SUCCESS; if ( !local) return IO__SUCCESS;
pthread_cancel(local->events);
pthread_mutex_lock(&local->mutex);
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local; hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
sdb.comm_ref = 0; sdb.comm_ref = 0;
sdb.layer = DP; sdb.layer = DP;
...@@ -1170,6 +1341,8 @@ static pwr_tStatus IoAgentClose ( ...@@ -1170,6 +1341,8 @@ static pwr_tStatus IoAgentClose (
close(local->hDpsOutputDataDevice); close(local->hDpsOutputDataDevice);
close(local->hDpsBoardDevice); close(local->hDpsBoardDevice);
pthread_mutex_unlock(&local->mutex);
free( (char *)local); free( (char *)local);
return sts; return sts;
......
...@@ -276,20 +276,20 @@ static pwr_tStatus IoAgentInit ( ...@@ -276,20 +276,20 @@ static pwr_tStatus IoAgentInit (
for (ll = 0; ll < local->device_data[ii]->module_data[kk]->submodule_data.size(); ll++) { for (ll = 0; ll < local->device_data[ii]->module_data[kk]->submodule_data.size(); ll++) {
PnSubmoduleData *submodule; PnSubmoduleData *submodule;
submodule = local->device_data[ii]->module_data[kk]->submodule_data[ll]; submodule = local->device_data[ii]->module_data[kk]->submodule_data[ll];
if (submodule->type & type) { if ((type == PROFINET_IO_CR_TYPE_INPUT) &&
if ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT) || ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT)) { (submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT))) {
submodule->offset_clean_io_in = offset_inputs; submodule->offset_clean_io_in = offset_inputs;
offset_inputs += submodule->io_in_data_length; offset_inputs += submodule->io_in_data_length;
} }
if ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_OUTPUT) || else if ((type == PROFINET_IO_CR_TYPE_OUTPUT) &&
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT)) { ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_OUTPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT))) {
submodule->offset_clean_io_out = offset_outputs; submodule->offset_clean_io_out = offset_outputs;
offset_outputs += submodule->io_out_data_length; offset_outputs += submodule->io_out_data_length;
} }
} }
} }
}
local->device_data[ii]->iocr_data[jj]->clean_io_data = (unsigned char *) calloc(1, offset_inputs + offset_outputs); local->device_data[ii]->iocr_data[jj]->clean_io_data = (unsigned char *) calloc(1, offset_inputs + offset_outputs);
local->device_data[ii]->iocr_data[jj]->clean_io_data_length = offset_inputs + offset_outputs; local->device_data[ii]->iocr_data[jj]->clean_io_data_length = offset_inputs + offset_outputs;
} }
......
...@@ -221,3 +221,5 @@ ...@@ -221,3 +221,5 @@
120823 cs plc Plc, serveral processes, handling of error log and process status 120823 cs plc Plc, serveral processes, handling of error log and process status
120824 cs plc Plc, several plc processes, signal handling with rt_ini at start and restart 120824 cs plc Plc, several plc processes, signal handling with rt_ini at start and restart
120926 cs neth Size check in subscription client message to avoid rt_neth crash at bad network 120926 cs neth Size check in subscription client message to avoid rt_neth crash at bad network
121203 rk elog Added executable rt_elog_dump that will dump historical event log to text-file.
ifndef link_rule_mk
link_rule_mk := 1
link = $(ld) $(linkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_objs) \
$(pwr_obj)/rt_io_user.o \
$(pwre_conf_libdir) $(pwre_conf_libpwrrt) $(pwre_conf_lib)
endif
/* rt_elog_dump.c -- <short description>
Author Jonas Nylund.
Dumps the rt_eventlog.db to a file.
If the eventlog doesn't exist a errormess will appear.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <db.h>
#include "co_time.h"
#include "rt_mh_def.h"
#include "co_dcli.h"
#include "rt_elog.h"
void ReadFromDBAndPutInFile(FILE *outFile);
void Init(char *fname);
void WriteColumnNames(FILE *outFile);
int Write(sEvent *sp, FILE *outFile);
void printMess(sEvent *sp, FILE *outFile);
void printAck(sEvent *sp, FILE *outFile);
void printRet(sEvent *sp, FILE *outFile);
void printBlock(sEvent *sp, FILE *outFile);
void printMsgInfo(mh_sMsgInfo *mp, FILE *outFile);
void printEventFlags(FILE *outFile, int flags);
void convertEventType(int type, char *ret);
void convertEventPrio(int prio, char *ret);
DB *dataBaseP = NULL;
int
main (int argc, char *argv[])
{
FILE *outFile;
pwr_tInt32 ret;
if(argc == 3)
{
if(argv[2] != NULL)
outFile = fopen(argv[2], "w");
}
else
outFile = fopen(DUMPFILE, "w");
if(outFile == NULL)
{
printf("kunde ej skapa fil, avslutar");
exit(1);
}
if(argc > 1)
Init(argv[1]);
else
Init(DATABASE);
ReadFromDBAndPutInFile(outFile);
fclose(outFile);
if((ret = dataBaseP->close(dataBaseP,0) != 0))
{
printf("error db_close: %s\n", db_strerror(ret));
}
if(argc == 3)
printf("Programmet klart resultatet finns i filen %s\n", argv[2]);
else
printf("Programmet klart resultatet finns i filen %s\n", DUMPFILE);
return 0;
}
void
Init (char *fname)
{
pwr_tInt32 ret;
char dbName[200];
dcli_translate_filename( dbName, fname);
/*create the database if it's not already created*/
if((ret = db_create(&dataBaseP, NULL, 0)) != 0)
{
/*error creating db-handle send the mess to errh, then exit*/
printf("error db_create: %s\n", db_strerror(ret));
printf(" Fel vid skapande av databashandtag avslutar\n");
exit(1);
}
#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
ret = dataBaseP->open(dataBaseP, NULL, dbName, NULL, DATABASETYPE, DB_RDONLY, 0);
#else
ret = dataBaseP->open(dataBaseP, dbName, NULL, DATABASETYPE, DB_RDONLY, 0);
#endif
if(ret != 0)
{
/*error opening/creating db send the mess to errh, then exit*/
printf("error db_open: %s\n", db_strerror(ret));
exit(1);
}
}
void ReadFromDBAndPutInFile(FILE *outFile)
{
pwr_tInt32 ret, sts;
pwr_tUInt32 nrOfEvents = 0;
sEvent *eventp;
DBT data, key;
DBC *dbcp;
WriteColumnNames(outFile);
/* Acquire a cursor for the database. */
if ((ret = dataBaseP->cursor(dataBaseP, NULL, &dbcp, 0)) != 0)
{
printf("error dataBaseP->cursor: %s\n", db_strerror(ret));
exit(1);
}
/* Initialize the key/data return pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
if((ret = dbcp->c_get(dbcp, &key, &data, DB_FIRST)) == 0)
{
eventp = data.data;
sts = Write(eventp, outFile);
nrOfEvents++;
}
while((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
{
eventp = data.data;
sts = Write(eventp, outFile);
nrOfEvents++;
}
if(ret != DB_NOTFOUND)
{
printf("error dbcp->c_get: %s\n", db_strerror(ret));
printf("Fel vid frsk att lsa post nr %u, avslutar\n", nrOfEvents);
exit(1);
}
printf("Antal hndelser skrivna till fil: %u\n", nrOfEvents);
/*Close the cursor*/
if((ret = dbcp->c_close(dbcp)) != 0)
{
printf("Error dbcp->c_close(): %s\n", db_strerror(ret));
}
}
void WriteColumnNames(FILE *outFile)
{
fprintf(outFile, "Nid\t");
fprintf(outFile, "BirthTime\t");
fprintf(outFile, "Idx\t");
fprintf(outFile, "EventFlags\t");
fprintf(outFile, "EventTime\t");
fprintf(outFile, "EventName\t");
fprintf(outFile, "EventType\t");
fprintf(outFile, "EventPrio\t");
fprintf(outFile, "EventText\t");
//fprintf(outFile, "Status\t");
fprintf(outFile, "TargetIdx\t");
fprintf(outFile, "DetectTime\t");
fprintf(outFile, "AValue\t");
fprintf(outFile, "CtrlLimit\t");
fprintf(outFile, "Hysteres\t");
fprintf(outFile, "Unit\t");
fprintf(outFile, "DValue\t");
fprintf(outFile, "High\t");
fprintf(outFile, "\n");
}
int
Write (
sEvent *sp,
FILE *outFile
)
{
switch (sp->EventType) {
case mh_eEvent_Alarm:
case mh_eEvent_Info:
printMess(sp, outFile);
break;
case mh_eEvent_Ack:
printAck(sp, outFile);
break;
case mh_eEvent_Cancel:
case mh_eEvent_Return:
printRet(sp, outFile);
break;
case mh_eEvent_Block:
case mh_eEvent_Unblock:
case mh_eEvent_Reblock:
case mh_eEvent_CancelBlock:
printBlock(sp, outFile);
break;
default:
printf("rt_elog_dump: Error in Write unknown EventType");
break;
}
fprintf(outFile, "\n");
return 1;
}
void
printMess (
sEvent *sp,
FILE *outFile
)
{
printMsgInfo(&(sp->Mess.message.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile, "%s\t", sp->Mess.message.EventText);
fprintf(outFile,"\t");
fprintf(outFile,"\t");
switch (sp->Mess.message.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printAck (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
printMsgInfo(&(sp->Mess.ack.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.TargetId.Idx);
event_time = net_NetTimeToTime(&(sp->Mess.ack.DetectTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
switch (sp->Mess.ack.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printRet (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
printMsgInfo(&(sp->Mess.ret.Info), outFile);
pwr_tTime event_time;
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile, "%s\t", sp->Mess.ret.EventText);
fprintf(outFile, "%u\t", sp->Mess.ret.TargetId.Idx);
event_time = net_NetTimeToTime(&(sp->Mess.ret.DetectTime));
time_AtoAscii( &event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
switch (sp->Mess.ret.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printBlock (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
printMsgInfo(&(sp->Mess.block.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.block.TargetId.Idx);
event_time = net_NetTimeToTime( &(sp->Mess.block.DetectTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
}
void
printMsgInfo (
mh_sMsgInfo *mp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
fprintf(outFile, "%d\t", mp->Id.Nix);
event_time = net_NetTimeToTime(&(mp->Id.BirthTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile, "%d\t",mp->Id.Idx);
/*
sp->Object
sp->SupObject
*/
printEventFlags(outFile, mp->EventFlags);
fprintf(outFile, "\t");
event_time = net_NetTimeToTime(&(mp->EventTime));
time_AtoAscii( &event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile, "%s\t",mp->EventName_V3);
convertEventType(mp->EventType, time_str);
fprintf(outFile, "%s\t", time_str);
convertEventPrio(mp->EventPrio, time_str);
fprintf(outFile, "%s\t",time_str);
}
void printEventFlags(FILE *outFile, int flags)
{
if(flags & mh_mEventFlags_Return)
{
fprintf(outFile,"Return/");
}
if(flags & mh_mEventFlags_Ack)
{
fprintf(outFile,"Ack/");
}
if(flags & mh_mEventFlags_Bell)
{
fprintf(outFile,"Bell/");
}
if(flags & mh_mEventFlags_Force)
{
fprintf(outFile,"Force/");
}
if(flags & mh_mEventFlags_InfoWindow)
{
fprintf(outFile,"InfoWind");
}
if(flags & mh_mEventFlags_Returned)
{
fprintf(outFile,"Returned/");
}
if(flags & mh_mEventFlags_NoObject)
{
fprintf(outFile,"NoObject");
}
}
void convertEventType(int type, char *ret)
{
switch (type) {
case mh_eEvent_Alarm:
strcpy(ret, "Alarm");
break;
case mh_eEvent_Info:
strcpy(ret, "Info");
break;
case mh_eEvent_Ack:
strcpy(ret, "Ack");
break;
case mh_eEvent_Cancel:
strcpy(ret, "Cancel");
break;
case mh_eEvent_Return:
strcpy(ret, "Return");
break;
case mh_eEvent_Block:
strcpy(ret, "Block");
break;
case mh_eEvent_Unblock:
strcpy(ret, "Unblock");
break;
case mh_eEvent_Reblock:
strcpy(ret, "Reblock");
break;
case mh_eEvent_CancelBlock:
strcpy(ret, "CancelBlock");
break;
default:
strcpy(ret, " ");
break;
}
}
void convertEventPrio(int prio, char *ret)
{
switch (prio) {
case mh_eEventPrio_A:
strcpy(ret, "A");
break;
case mh_eEventPrio_B:
strcpy(ret, "B");
break;
case mh_eEventPrio_C:
strcpy(ret, "C");
break;
case mh_eEventPrio_D:
strcpy(ret, "D");
break;
default:
strcpy(ret, " ");
break;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment