diff --git a/ascon.c b/ascon.c index 59e12eb3..c46d4f2a 100644 --- a/ascon.c +++ b/ascon.c @@ -313,7 +313,7 @@ int AsconBaseHandler(Ascon * a) } else if (ret > 0) { a->state = AsconConnectDone; /* success */ } else if (ret < 0) { - AsconError(a, "ASC3", errno); + AsconError(a, "ASC3", errno); } break; case AsconWriteStart: @@ -584,6 +584,23 @@ void AsconDisconnect(Ascon * a) { if (a->fd > 0) { close(a->fd); + lastClose = DoubleTime(); + } + a->fd = -1; + a->state = AsconNotConnected; +} + +void AsconReconnect(Ascon * a, char * hostport) +{ + if (a->fd > 0) { + close(a->fd); + lastClose = DoubleTime(); + } + if (hostport != NULL && hostport[0] != '\0') { + if (a->hostport) { + free(a->hostport); + } + a->hostport = strdup(hostport); } a->fd = -1; a->state = AsconConnectStart; diff --git a/ascon.h b/ascon.h index 46372191..c1b3dc75 100644 --- a/ascon.h +++ b/ascon.h @@ -35,11 +35,17 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[]); * \param a the connection to be killed */ void AsconKill(Ascon * a); -/** \brief Disconnect function +/** \brief disconnect and disable * \param a the connection to disconnect */ void AsconDisconnect(Ascon * a); +/** \brief Reconnect function + * \param a the connection to reconnect + * \param hostport : to reconnect to (empty for reconnecting to the same port) + */ +void AsconReconnect(Ascon * a, char *hostport); + /** \brief the task handler. To be called repeatedly. * \param a the connection * \return the state of the connection diff --git a/devser.c b/devser.c index 115b2d45..6c8d1c40 100644 --- a/devser.c +++ b/devser.c @@ -2,6 +2,7 @@ #include #include "ascon.h" #include "devser.h" +#include "dynstring.h" typedef struct DevAction { struct DevAction *next; @@ -11,6 +12,7 @@ typedef struct DevAction { DevKillActionData *kill; double interval; /* -1 for a queued action */ double timeDue; /* 0 for a queued action */ + DevInfoFunc *infoFunc; } DevAction; struct DevSer { @@ -207,11 +209,8 @@ void DevDebugMode(DevSer * devser, int steps) devser->steps = steps; } -void DevKill(DevSer * devser) +static void DevReset(DevSer * devser) { - if (devser->ascon) { - AsconKill(devser->ascon); - } DevFreeActionList(devser->actions); DevFreeActionList(devser->toKill); if (devser->killCurrent) { @@ -221,17 +220,34 @@ void DevKill(DevSer * devser) devser->killCurrent = 0; free(devser->current); } +} + +void DevKill(DevSer * devser) +{ + if (devser->ascon) { + AsconKill(devser->ascon); + } + DevReset(devser); TaskRemove(pServ->pTasker, DevQueueTask, devser); free(devser); } void DevDisconnect(DevSer * devser) { + DevReset(devser); if (devser->ascon) { AsconDisconnect(devser->ascon); } } +void DevReconnect(DevSer * devser, char *hostport) +{ + DevReset(devser); + if (devser->ascon) { + AsconReconnect(devser->ascon, hostport); + } +} + int DevUnschedule(DevSer * devser, void *callData, DevActionHandler * hdl, DevActionMatch * matchFunc) { @@ -264,7 +280,7 @@ int DevUnschedule(DevSer * devser, void *callData, int DevSchedule(DevSer * devser, void *actionData, DevPrio prio, double interval, DevActionHandler * hdl, DevActionMatch * matchFunc, - DevKillActionData * killFunc) + DevKillActionData * killFunc, DevInfoFunc * infoFunc) { DevAction *action; DevAction *foundAction = NULL; @@ -272,6 +288,7 @@ int DevSchedule(DevSer * devser, void *actionData, DevAction **ptr2insertPos = NULL; int ret; + assert(killFunc == NULL || actionData != NULL); if (prio <= NullPRIO) { prio = NullPRIO + 1; } @@ -293,10 +310,10 @@ int DevSchedule(DevSer * devser, void *actionData, && matchFunc(actionData, action->data)) { if (prio == action->prio && interval < 0) { /* do not move an action with equal prio */ - if(killFunc != NULL && actionData != NULL){ - killFunc(actionData); - } - return 0; + if (killFunc) { + killFunc(actionData); + } + return 0; /* not queued */ } /* remove action from list */ *ptr2prev = action->next; @@ -320,6 +337,7 @@ int DevSchedule(DevSer * devser, void *actionData, action->data = actionData; action->hdl = hdl; action->kill = killFunc; + action->infoFunc = infoFunc; action->timeDue = 0; ret = 1; } @@ -348,9 +366,10 @@ int DevSchedule(DevSer * devser, void *actionData, int DevQueue(DevSer * devser, void *actionData, DevPrio prio, DevActionHandler * hdl, DevActionMatch * matchFunc, - DevKillActionData * killFunc) + DevKillActionData * killFunc, DevInfoFunc *infoFunc) { - return DevSchedule(devser, actionData, prio, -1.0, hdl, matchFunc, killFunc); + return DevSchedule(devser, actionData, prio, -1.0, hdl + , matchFunc, killFunc, infoFunc); } int DevRemoveAction(DevSer * devser, void *actionData) @@ -359,7 +378,6 @@ int DevRemoveAction(DevSer * devser, void *actionData) DevAction *action = NULL; int cnt = 0; - /* Remove current action, if matched. If a reply is pending, the next action will get the reply. But as in the inital state no reply is expected, this should not harm. */ @@ -403,3 +421,35 @@ int DevIsPending(DevSer * devser, void *callData, return 0; } +char * DevList(DevSer * devser) { + DevAction * action; + pDynString result, info; + char text[80]; + char *str; + + result = CreateDynString(63,64); + for (action = devser->actions; action != NULL; action = action->next) { + if (action->interval < 0) { + snprintf(text, sizeof text, "%-8s queued ", DevPrio2Text(action->prio)); + } else { + snprintf(text, sizeof text, "%-8s %8.3g %14.3f ", + DevPrio2Text(action->prio), action->interval, action->timeDue); + } + DynStringConcat(result, text); + if (action == devser->current) { + DynStringConcat(result, "ACTIVE "); + } + if (action->infoFunc) { + str = action->infoFunc(action->data); + DynStringConcat(result, str); + free(str); + } else { + snprintf(text, sizeof text, "%8.8x", (unsigned int)action->data); + DynStringConcat(result, text); + } + DynStringConcat(result, "\n"); + } + str = strdup(GetCharArray(result)); + DeleteDynString(result); + return str; +} diff --git a/devser.h b/devser.h index 9de4d7dc..4c30bc23 100644 --- a/devser.h +++ b/devser.h @@ -29,6 +29,13 @@ typedef int DevActionMatch(void *callData, void *actionData); */ typedef void DevKillActionData(void *actionData); +/** \brief ActionData info function + * \param actionData action data + * \return textual information about action for listing + * the result is an allocated string and has to be freed after use + */ +typedef char * DevInfoFunc(void *actionData); + /** \brief possible priorities. * NullPRIO and NumberOfPRIO must not be used as priority * if an action with StartPRIO is scheduled, all other activities @@ -59,11 +66,16 @@ void DevDebugMode(DevSer * devser, int steps); * \param devser the device serializer */ void DevKill(DevSer * devser); -/** \brief Disconnect +/** \brief disconnect and disable the serializer * \param devser The device serializer to disconnect */ void DevDisconnect(DevSer * devser); - +/** \brief reconnect the serializer + * \param devser The device serializer to reconnect + * \param hostport : to reconnect to another port + * ar an empty string to reconnect to the same port + */ +void DevReconnect(DevSer * devser, char *hostport); /** \brief Queue an action * * If a matching action with the same action handler @@ -76,12 +88,14 @@ void DevDisconnect(DevSer * devser); * \param killFunc the action data kill function (called from DevKill and * after the action has finished, i.e. when hdl returned NULL) * or NULL if no kill function is needed. + * \param infoFunc the actions info function or NULL if no info function + * is defined. * \return 1 when this was a new action, 0 when an action was overwritten * in the second case the actionData's kill Function is immediately called */ int DevQueue(DevSer * devser, void *actionData, DevPrio prio, DevActionHandler * hdl, DevActionMatch * matchFunc, - DevKillActionData * killFunc); + DevKillActionData * killFunc, DevInfoFunc * infoFunc); /** \brief Schedule a periodic action * @@ -94,13 +108,15 @@ int DevQueue(DevSer * devser, void *actionData, DevPrio prio, * \param hdl the action handler * \param matchFunc a match function with two arguments of the same type * \param killFunc the action data kill function or NULL if no kill function is needed. + * \param infoFunc the actions info function or NULL if no info function + * is defined. * \return 1 when this was a new action, 0 when an action was overwritten * in the second case the actionData's kill Function is immediately called */ int DevSchedule(DevSer * devser, void *actionData, DevPrio prio, double interval, DevActionHandler * hdl, DevActionMatch * matchFunc, - DevKillActionData * killFunc); + DevKillActionData * killFunc, DevInfoFunc * infoFunc); /** \brief Unschedule matching actions * \param devser the device serializer @@ -140,4 +156,10 @@ char *DevPrio2Text(DevPrio prio); */ DevPrio DevText2Prio(char *text); +/** \brief List registered actions + * \param devser the device serializer + * \return the listing text + */ +char * DevList(DevSer * devser); + #endif