diff options
-rw-r--r-- | xivovp/base.c | 195 |
1 files changed, 139 insertions, 56 deletions
diff --git a/xivovp/base.c b/xivovp/base.c index 01f771a..470ccc2 100644 --- a/xivovp/base.c +++ b/xivovp/base.c @@ -16,20 +16,22 @@ #include "vp_api.h" #include "EVB_Le71HR8921G_rev_E_2M048.h" -#define VP_TICK_MS 5 /* matches with device profile configuration */ +#define VP_TICK_MS 5 /* matches with device profile + configuration */ #include "tolapai_spi.h" #define DRV_NAME "xivovp" +#define TXQUEUE_LEN 16 /* WARNING TOTHINK possible DoS attack + by overrunning this queue */ + #define TRACES_VANISH_DEFAULT 2000 -#define TXQUEUE_LEN 16 /* WARNING TOTHINK possible DoS attack by - overrunning this queue */ static int traces_vanish = TRACES_VANISH_DEFAULT; -static int alawoverride = 1; /* It's named like that in every DAHDI driver - except I prefer it to be 1 so the name doesn't - make much sense. */ +static int alawoverride = 1; /* It's named like that in every DAHDI driver + except I prefer it to be 1 so the name + doesn't make much sense. */ module_param(traces_vanish, int, 0444); module_param(alawoverride, int, 0600); MODULE_PARM_DESC(traces_vanish, @@ -138,10 +140,13 @@ static int xivovp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) unsigned long flags; if (line->txsig_queue_len >= TXQUEUE_LEN) { - printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun (%d)\n", chan->chanpos, txsig); + printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun (%d)\n", + chan->chanpos, txsig); return -1; } else { - printk(KERN_DEBUG DRV_NAME "(chan %d): queuing txsig (%d) in position %d\n", chan->chanpos, txsig, line->txsig_queue_len); + printk(KERN_DEBUG DRV_NAME "(chan %d): " + "queuing txsig (%d) in position %d\n", + chan->chanpos, txsig, line->txsig_queue_len); } spin_lock_irqsave(&line->lock, flags); @@ -162,37 +167,55 @@ static void xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig) switch (txsig) { case DAHDI_TXSIG_START: case DAHDI_TXSIG_OFFHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting %s state on FXO, setting to TALK.\n", chanpos, txsig == DAHDI_TXSIG_START ? "START" : "OFFHOOK"); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "transmitting %s state on FXO, " + "setting to TALK.\n", + chanpos, txsig == DAHDI_TXSIG_START ? + "START" : + "OFFHOOK"); VpSetLineState(&line->vp_ctx, VP_LINE_FXO_TALK); break; case DAHDI_TXSIG_ONHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXO, setting to OHT.\n", chanpos); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "transmitting ONHOOK on FXO, " + "setting to OHT.\n", chanpos); VpSetLineState(&line->vp_ctx, VP_LINE_FXO_OHT); break; default: - printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXO: %d\n", chanpos, txsig); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "unsupported tx state for FXO: %d\n", + chanpos, txsig); } } else /* FXS */ { switch (txsig) { case DAHDI_TXSIG_START: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting START on FXS, setting to RINGING.\n", chanpos); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "transmitting START on FXS, " + "setting to RINGING.\n", chanpos); VpSetLineState(&line->vp_ctx, VP_LINE_RINGING); break; case DAHDI_TXSIG_OFFHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting OFFHOOK on FXS, setting to TALK.\n", chanpos); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "transmitting OFFHOOK on FXS, " + "setting to TALK.\n", chanpos); VpSetLineState(&line->vp_ctx, VP_LINE_TALK); break; case DAHDI_TXSIG_ONHOOK: - printk(KERN_WARNING DRV_NAME "(chan %d): transmitting ONHOOK on FXS, setting to OHT.\n", chanpos); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "transmitting ONHOOK on FXS, " + "setting to OHT.\n", chanpos); VpSetLineState(&line->vp_ctx, VP_LINE_OHT); break; case DAHDI_TXSIG_KEWL: - printk(KERN_WARNING DRV_NAME "(chan %d): requested to transmit DAHDI_TXSIG_KEWL but I have no idea what it means.\n", chanpos); - // Something about battery drop when transmitting a hangup/ + printk(KERN_WARNING DRV_NAME "(chan %d): " + "trying to transmit remote disconnect," + "but not supported yet\n", chanpos); //VpSetLineState(line->vp_ctx, ); break; default: - printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXS: %d\n", chanpos, txsig); + printk(KERN_WARNING DRV_NAME "(chan %d): " + "unsupported tx state for FXS: %d\n", + chanpos, txsig); } } } @@ -217,7 +240,9 @@ static void xivovp_handle_txsig_queue(void) txsig_queue[k]); } else if (!said) { said = 1; - printk(KERN_WARNING DRV_NAME ": txsig pending but calibration not done yet! Waiting...\n"); + printk(KERN_WARNING DRV_NAME ": " + "txsig pending but calibration " + "not done yet! Waiting...\n"); } } } @@ -250,8 +275,9 @@ static void vp_post_init(VpEventType *event) vpst = VpSetOption(NULL, event->pDevCtx, VP_OPTION_ID_EVENT_MASK, &event_mask); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_EVENT_MASK returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpSetOption VP_OPTION_ID_EVENT_MASK " + "returned %d\n", (int)vpst); } /* FXS */ @@ -259,21 +285,22 @@ static void vp_post_init(VpEventType *event) VP_OPTION_ID_TIMESLOT, &fxs_timeslot); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetOption FXS VP_OPTION_ID_TIMESLOT returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpSetOption FXS VP_OPTION_ID_TIMESLOT " + "returned %d\n", (int)vpst); } vpst = VpSetLineState(&xivovp.line[FXS_LINE].vp_ctx, VP_LINE_OHT); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetLineState returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpSetLineState returned %d\n", (int)vpst); } vpst = VpCalLine(&xivovp.line[FXS_LINE].vp_ctx); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpCalLine returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpCalLine returned %d\n", (int)vpst); } /* FXO */ @@ -281,20 +308,20 @@ static void vp_post_init(VpEventType *event) VP_OPTION_ID_TIMESLOT, &fxo_timeslot); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetOption FXO VP_OPTION_ID_TIMESLOT returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpSetOption FXO VP_OPTION_ID_TIMESLOT " + "returned %d\n", (int)vpst); } vpst = VpSetLineState(&xivovp.line[FXO_LINE].vp_ctx, VP_LINE_FXO_OHT); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpSetLineState returned %d\n", - (int)vpst); + printk(KERN_ERR DRV_NAME ": " + "VpSetLineState returned %d\n", (int)vpst); } xivovp.line[FXO_LINE].ready = 1; /* No VpCalLine for FXO */ - // XXX What happens if lines aren't connected? count_and_stop_traces = TRUE; @@ -310,42 +337,83 @@ static void event_calibration_complete(VpEventType *event) static void event_calibration_fail(VpEventType *event) { (void) event; - printk(KERN_WARNING DRV_NAME ": calibration failed (returned VP_EVID_CAL_BUSY)\n"); + printk(KERN_WARNING DRV_NAME ": " + "calibration failed (returned VP_EVID_CAL_BUSY)\n"); vp_set_debug_select_running(); } static void event_hook_off(VpEventType *event) { struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); - printk(KERN_INFO DRV_NAME ": received hook off event on %s\n", line->chan.name); + printk(KERN_INFO DRV_NAME ": received hook off event on %s\n", + line->chan.name); dahdi_hooksig(&line->chan, DAHDI_RXSIG_OFFHOOK); } static void event_hook_on(VpEventType *event) { struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); - printk(KERN_INFO DRV_NAME ": received hook on event %s\n", line->chan.name); + printk(KERN_INFO DRV_NAME ": received hook on event %s\n", + line->chan.name); + dahdi_hooksig(&line->chan, DAHDI_RXSIG_ONHOOK); +} + +static void event_fxo_hook_off(VpEventType *event) +{ + struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); + + printk(KERN_INFO DRV_NAME ": %s on %s\n", + event->eventId == VP_LINE_EVID_LIU ? + "line in use" : + event->eventId == VP_LINE_EVID_FEED_DIS ? + "voltage no longer detected across the loop" : + event->eventId == VP_LINE_EVID_DISCONNECT ? + "loop current from FXS no longer detected" : + "???", + line->chan.name); + + dahdi_hooksig(&line->chan, DAHDI_RXSIG_OFFHOOK); +} + +static void event_fxo_hook_on(VpEventType *event) +{ + struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); + + printk(KERN_INFO DRV_NAME ": %s on %s\n", + event->eventId == VP_LINE_EVID_LNIU ? + "line not in use" : + event->eventId == VP_LINE_EVID_FEED_EN ? + "FXS has applied voltage accross the loop" : + event->eventId == VP_LINE_EVID_RECONNECT ? + "FXS has started driving loop current" : + "???", + line->chan.name); + dahdi_hooksig(&line->chan, DAHDI_RXSIG_ONHOOK); } static void event_ring_on(VpEventType *event) { struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); - printk(KERN_INFO DRV_NAME ": received ring on event on %s\n", line->chan.name); + printk(KERN_INFO DRV_NAME ": received ring on event on %s\n", + line->chan.name); dahdi_hooksig(&line->chan, DAHDI_RXSIG_RING); } static void event_ring_off(VpEventType *event) { struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); - printk(KERN_INFO DRV_NAME ": received ring off event on %s\n", line->chan.name); + printk(KERN_INFO DRV_NAME ": " + "received ring off event on %s\n", + line->chan.name); dahdi_hooksig(&line->chan, DAHDI_RXSIG_ONHOOK); } static void event_polarity_reversal(VpEventType *event) { struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx); - printk(KERN_INFO DRV_NAME ": received polarity reversal event on %s\n", line->chan.name); + printk(KERN_INFO DRV_NAME ": received polarity reversal event on %s\n", + line->chan.name); dahdi_qevent_lock(&line->chan, DAHDI_EVENT_POLARITY); } @@ -367,22 +435,23 @@ static void vp_tick(const unsigned long data) vpst = VpApiTick(&xivovp.dev_ctx, &ev_pending); if (vpst != VP_STATUS_SUCCESS) { printk(KERN_ERR DRV_NAME ": VpApiTick returned %d\n", - (int)vpst); + (int)vpst); return; } while (ev_pending) { ev_pending = VpGetEvent(&xivovp.dev_ctx, &event); if (event.status != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpGetEvent returned event.status == %d\n", - (int)event.status); + printk(KERN_ERR DRV_NAME ": VpGetEvent returned " + "event.status == %d\n", + (int)event.status); return; } if (ev_pending) { printk(KERN_DEBUG "vp evt: %d %d\n", - (int)event.eventCategory, - (int)event.eventId); + (int)event.eventCategory, + (int)event.eventId); switch ((int)event.eventCategory) { case VP_EVCAT_RESPONSE: @@ -444,12 +513,16 @@ static void vp_tick(const unsigned long data) case VP_LINE_EVID_POLREV: event_polarity_reversal(&event); break; - UNSUPPORTED(VP_LINE_EVID_LIU); - UNSUPPORTED(VP_LINE_EVID_LNIU); - UNSUPPORTED(VP_LINE_EVID_FEED_DIS); - UNSUPPORTED(VP_LINE_EVID_FEED_EN); - UNSUPPORTED(VP_LINE_EVID_DISCONNECT); - UNSUPPORTED(VP_LINE_EVID_RECONNECT); + case VP_LINE_EVID_LIU: + case VP_LINE_EVID_FEED_DIS: + case VP_LINE_EVID_DISCONNECT: + event_fxo_hook_off(&event); + break; + case VP_LINE_EVID_LNIU: + case VP_LINE_EVID_FEED_EN: + case VP_LINE_EVID_RECONNECT: + event_fxo_hook_on(&event); + break; UNSUPPORTED(VP_LINE_EVID_POH); UNSUPPORTED(VP_LINE_EVID_PNOH); } @@ -460,7 +533,9 @@ static void vp_tick(const unsigned long data) printk(KERN_INFO "VpGetResults\n"); vpst = VpGetResults(&event, &result); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpGetResults returned %d\n", (int) vpst); + printk(KERN_ERR DRV_NAME ": " + "VpGetResults returned " + "%d\n", (int) vpst); return; // TOTHINK } } @@ -483,8 +558,7 @@ static const struct dahdi_span_ops xivovp_span_ops = { .hooksig = xivovp_hooksig, }; -static int -span_init(void) +static int span_init(void) { int i; struct xivovp_line* l; @@ -518,7 +592,9 @@ span_init(void) l->chan.sigcap = DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS; } else { - printk(KERN_ERR DRV_NAME ": WTF?? Unsupported line type %d\n", l->type); + printk(KERN_ERR DRV_NAME ": " + "WTF?? Unsupported line type %d\n", + l->type); return -EINVAL; } @@ -577,7 +653,9 @@ vp_init(void) debug_select = init_dbg; VpSetOption(NULL, NULL, VP_OPTION_ID_DEBUG_SELECT, &debug_select); debug_select = init_dbg; - VpSetOption(NULL, NULL, VP_OPTION_ID_GLOBAL_DEBUG_SELECT, &debug_select); + VpSetOption(NULL, NULL, VP_OPTION_ID_GLOBAL_DEBUG_SELECT, + &debug_select); + vpst = VpMakeDeviceObject( VP_DEV_890_SERIES, @@ -585,7 +663,8 @@ vp_init(void) &xivovp.dev_ctx, (void*)&xivovp.ve890_dev_obj); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpMakeDeviceObject failed (%d)\n", vpst); + printk(KERN_ERR DRV_NAME ": VpMakeDeviceObject failed (%d)\n", + vpst); rc = -EIO; goto err_vp_make_device_object; } @@ -597,7 +676,8 @@ vp_init(void) (void*)&xivovp.line[FXS_LINE].line_obj, &xivovp.dev_ctx); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpMakeLineObject (FXS) failed (%d)\n", vpst); + printk(KERN_ERR DRV_NAME ": " + "VpMakeLineObject (FXS) failed (%d)\n", vpst); rc = -EIO; goto err_vp_make_line_object; } @@ -610,7 +690,8 @@ vp_init(void) (void*)&xivovp.line[FXO_LINE].line_obj, &xivovp.dev_ctx); if (vpst != VP_STATUS_SUCCESS) { - printk(KERN_ERR DRV_NAME ": VpMakeLineObject (FXO) failed (%d)\n", vpst); + printk(KERN_ERR DRV_NAME ": " + "VpMakeLineObject (FXO) failed (%d)\n", vpst); rc = -EIO; goto err_vp_make_line_object; } else { @@ -693,6 +774,7 @@ test_evb_ve890_init(void) return 0; err_vp_init: + dahdi_unregister(&xivovp.span); #endif err_dahdi_init: xivovp_cleanup(); @@ -733,6 +815,7 @@ xivovp_port0_configured_cb(void *data) return; err_vp_init: + dahdi_unregister(&xivovp.span); err_config_port: xivovp_cleanup(); tlp_spidev_exit(); |