blob: e62e33205b538ee75332e3f18e8fdfd637b1553d [file] [log] [blame]
/******************************************************************************
Copyright (c) 2006-2015 Lantiq Deutschland GmbH
Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
Copyright 2018, Intel Corporation.
For licensing information, see the file 'LICENSE' in the root folder of
this software module.
******************************************************************************/
/**
\file dxs_event.c
Implementation of event handling functions.
*/
/* ========================================================================== */
/* Includes */
/* ========================================================================== */
#include <stdio.h>
#include <string.h>
#include "dxs.h"
#include "dxs_config.h"
#include "dxs_mempool.h"
#include "dxs_lib.h"
#include "dxs_errno.h"
#include "dxs_error.h"
#include "dxs_wait.h"
/* ========================================================================== */
/* Macro definitions */
/* ========================================================================== */
#define DXS_EVENTS_PER_DEVICE 10
/* ========================================================================== */
/* Type definitions */
/* ========================================================================== */
/* ========================================================================== */
/* Global variables */
/* ========================================================================== */
/** memory placeholder for the events, all devices */
static DXS_Event_t event_memory[DXS_MAX_DEVICES * DXS_EVENTS_PER_DEVICE];
/* ========================================================================== */
/* Function prototypes */
/* ========================================================================== */
/* ========================================================================== */
/* Function implementation */
/* ========================================================================== */
/**
Function dxs_event_bit_set
\param pCh - pointer to DXS channel structure
\param ev - event id
\return
none
*/
static void dxs_event_bit_set (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
{
/* the code assumes byte is 8 bits */
uint8_t bit = ev % (sizeof(uint32_t) << 3);
/* set event bit */
pCh->event_mask[ev/(sizeof(uint32_t) << 3)] |= (1UL << bit);
}
/**
Function dxs_event_bit_clear
\param pCh - pointer to DXS channel structure
\param ev - event id
\return
none
*/
static void dxs_event_bit_clear (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
{
/* the code assumes byte is 8 bits */
uint8_t bit = ev % (sizeof(uint32_t) << 3);
/* clear event bit */
pCh->event_mask[ev/(sizeof(uint32_t) << 3)] &= ~(1UL << bit);
}
/**
Function dxs_event_bit_test
\param pCh - pointer to DXS channel structure
\param ev - event id
\return
zero or non-zero value depending on bit setting
*/
static uint32_t dxs_event_bit_test (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
{
/* the code assumes byte is 8 bits */
uint8_t bit = ev % (sizeof(uint32_t) << 3);
return (pCh->event_mask[ev/(sizeof(uint32_t) << 3)] & (1UL << bit));
}
/**
Function dxs_event_pool_init
\param pDev - pointer to DXS device structure
\return
DXS_MPOOL_OK success
DXS_MPOOL_PARAMS invalid parameters
DXS_MPOOL_NOT_ENOUGH not enough memory for a pool
DXS_MPOOL_NO_FREE_POOLS cannot allocate a pool
*/
int32_t dxs_event_pool_init(DXS_DEVICE_t *pDev)
{
if (pDev->nDevNum < DXS_MAX_DEVICES)
{
return mempool_init(&event_memory[pDev->nDevNum * DXS_EVENTS_PER_DEVICE],
DXS_EVENTS_PER_DEVICE * sizeof (DXS_Event_t),
DXS_EVENTS_PER_DEVICE, sizeof(DXS_Event_t),
&pDev->event_pool);
}
else
return DXS_statusInvalidParam;
}
/**
Function dxs_event_pool_exit
\param pDev - pointer to DXS device structure
*/
void dxs_event_pool_exit(DXS_DEVICE_t *pDev)
{
return mempool_destroy(pDev->event_pool);
}
/**
Function dxs_event_get
\param pDev - pointer to DXS device structure
\param pEvent - pointer to event
\return
- the remaining element count of the fifo or DXS_statusError
*/
int32_t dxs_event_get(DXS_DEVICE_t *pDev, DXS_Event_t *pEvent)
{
/*
1) get one event buffer out of the event fifo and memcopy to pEvent
2) return event buffer to the event buffer pool
3) return the remaining element count of the fifo
*/
uint32_t size;
DXS_Event_t *pEvt;
if (0 < fifo_count(pDev->event_queue))
{
if (DXS_FIFO_OK == fifo_get(pDev->event_queue, (void **)(&pEvt), &size))
{
*pEvent=*pEvt;
mempool_put(pDev->event_pool, (void *)pEvt);
}
else
{
return DXS_statusError;
}
}
return fifo_count(pDev->event_queue);
}
/**
Function DXS_EventDispatch
\param pDev - pointer to DXS device structure
\param pEvent - pointer to event
*/
void DXS_EventDispatch (DXS_DEVICE_t *pDev, DXS_Event_t *pEvent)
{
DXS_Event_t *pEventBuffer;
DXS_CHANNEL_t *pCh = &pDev->pChannel[pEvent->ch];
/* check if the event is not masked */
if (!dxs_event_bit_test(pCh, pEvent->id))
return;
pEventBuffer = (DXS_Event_t *)mempool_get(pDev->event_pool);
if (pEventBuffer == NULL)
{
fprintf (stderr, "ERROR: Out of event memory. Event(id=%d) discarded.\n",
pEvent->id);
return;
}
/* copy event into the allocated buffer */
*pEventBuffer = *pEvent;
/* push the buffer to the event queue */
if (DXS_FIFO_OK == fifo_put(pDev->event_queue,
(void *)pEventBuffer, sizeof (*pEventBuffer)))
{
/* wake up user task */
dxs_wakeup(pDev);
}
else
{
fprintf (stderr, "ERROR: Cannot enqueue event(dev=%d ch=%d id=%d), discarding...\n",
pEventBuffer->dev, pEventBuffer->ch, pEventBuffer->id);
mempool_put(pDev->event_pool, (void *)pEventBuffer);
}
}
/**
Function DXS_EventEnable
\param pCh - pointer to DXS channel structure
\param ev - event id
\return
value of \ref DXS_status_t
*/
int32_t DXS_EventEnable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
{
if (ev <= DXS_EVENT_NONE || ev >= DXS_EVENT_MAX)
{
DXS_RETURN(DXS_statusEventEnableNotAllowed);
}
dxs_event_bit_set(pCh, ev);
return DXS_statusOk;
}
/**
Function DXS_EventDisable
\param pCh - pointer to DXS channel structure
\param ev - event id
\return
value of \ref DXS_status_t
*/
int32_t DXS_EventDisable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
{
if (ev <= DXS_EVENT_NONE || ev >= DXS_EVENT_MAX ||
/* error events cannot be disabled */
ev == DXS_EVENT_OVERTEMP || ev == DXS_EVENT_OVERTEMP_END ||
ev == DXS_EVENT_GROUND_FAULT || ev == DXS_EVENT_GROUND_FAULT_END ||
ev == DXS_EVENT_FAULT_FW_WATCHDOG ||
ev == DXS_EVENT_NLT_ABORT ||
ev == DXS_EVENT_DEBUG_CERR ||
ev == DXS_EVENT_CID_BUF_UNDERFLOW ||
ev == DXS_EVENT_CID_SEQ_ERROR)
{
DXS_RETURN(DXS_statusEventDisableNotAllowed);
}
dxs_event_bit_clear(pCh, ev);
return DXS_statusOk;
}
/**
Function DXS_EventMaskSetDefault
\param pCh - pointer to DXS channel structure
\return none
*/
void DXS_EventMaskSetDefault(DXS_CHANNEL_t *pCh)
{
/* events enabled by default: */
dxs_event_bit_set(pCh, DXS_EVENT_FXS_ONHOOK);
dxs_event_bit_set(pCh, DXS_EVENT_FXS_OFFHOOK);
dxs_event_bit_set(pCh, DXS_EVENT_FXS_FLASH);
dxs_event_bit_set(pCh, DXS_EVENT_NLT_END);
dxs_event_bit_set(pCh, DXS_EVENT_NLT_ABORT);
dxs_event_bit_set(pCh, DXS_EVENT_PULSE_DIGIT);
dxs_event_bit_set(pCh, DXS_EVENT_PULSE_START);
dxs_event_bit_set(pCh, DXS_EVENT_DTMF_DIGIT);
dxs_event_bit_set(pCh, DXS_EVENT_CALIBRATION_END);
dxs_event_bit_set(pCh, DXS_EVENT_METERING_END);
dxs_event_bit_set(pCh, DXS_EVENT_OVERTEMP);
dxs_event_bit_set(pCh, DXS_EVENT_OVERTEMP_END);
dxs_event_bit_set(pCh, DXS_EVENT_GROUND_FAULT);
dxs_event_bit_set(pCh, DXS_EVENT_GROUND_FAULT_END);
dxs_event_bit_set(pCh, DXS_EVENT_TONE_DET_CPT);
dxs_event_bit_set(pCh, DXS_EVENT_TONE_DET_CPT_END);
dxs_event_bit_set(pCh, DXS_EVENT_DEBUG_CERR);
dxs_event_bit_set(pCh, DXS_EVENT_CID_REQ_DATA);
dxs_event_bit_set(pCh, DXS_EVENT_CID_BUF_UNDERFLOW);
dxs_event_bit_set(pCh, DXS_EVENT_CID_END);
dxs_event_bit_set(pCh, DXS_EVENT_CID_SEQ_END);
dxs_event_bit_set(pCh, DXS_EVENT_CID_SEQ_ERROR);
dxs_event_bit_set(pCh, DXS_EVENT_GROUND_KEY);
dxs_event_bit_set(pCh, DXS_EVENT_GROUND_KEY_END);
dxs_event_bit_set(pCh, DXS_EVENT_FAULT_FW_WATCHDOG);
dxs_event_bit_set(pCh, DXS_EVENT_T2G_TIMER_EXPIRED);
/* events not enabled by default: */
#if 0
dxs_event_bit_set(pCh, DXS_EVENT_FXS_RAW_ONHOOK);
dxs_event_bit_set(pCh, DXS_EVENT_FXS_RAW_OFFHOOK);
#endif
}