| /****************************************************************************** |
| |
| 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 |
| } |