summaryrefslogtreecommitdiff
path: root/xivovp
diff options
context:
space:
mode:
authorNoe Rubinstein <nrubinstein@proformatique.com>2010-09-24 14:15:55 +0200
committerNoe Rubinstein <nrubinstein@proformatique.com>2010-09-24 14:15:55 +0200
commitba840a7aa6178133f4e7697225f0ace4c353e8a4 (patch)
treef57d2ce9f69d92956e53db93435c1f2ab9337f7d /xivovp
parent966533f27dfd378548f4fa4da0b46e093e812bff (diff)
clean up + introduce new bugs
Diffstat (limited to 'xivovp')
-rw-r--r--xivovp/base.c370
1 files changed, 217 insertions, 153 deletions
diff --git a/xivovp/base.c b/xivovp/base.c
index 4f0b703..2875d96 100644
--- a/xivovp/base.c
+++ b/xivovp/base.c
@@ -10,11 +10,11 @@
#include "vp_api.h"
#include "EVB_Le71HR8921G_rev_E_2M048.h"
-#define 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 KBUILD_BASENAME
+#define DRV_NAME "xivovp"
#define TRACES_VANISH_DEFAULT 2000
#define TXQUEUE_LEN 5
@@ -27,8 +27,11 @@ MODULE_PARM_DESC(traces_vanish,
"ERROR/WARNING/INFO (default: " __stringify(TRACES_VANISH_DEFAULT) ")");
-#define NB_LINES 1 //XXX
-#define TICK_JIFFIES DIV_ROUND_UP(TICK_MS * HZ, 1000)
+#define NB_LINES 1 //XXX
+#define TICK_JIFFIES(n) DIV_ROUND_UP(n * HZ, 1000)
+#define VP_TICK_JIFFIES TICK_JIFFIES(VP_TICK_MS)
+#define RXTX_TICK_JIFFIES TICK_JIDDIES(1)
+
#define DEBUG_SELECT_RUNNING (VP_DBG_ERROR \
| VP_DBG_WARNING \
| VP_DBG_INFO)
@@ -63,20 +66,36 @@ static struct xivovp {
VpDevCtxType dev_ctx;
} xivovp;
-static int
-xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig);
+struct timer_list rxtx_timer;
+
+static void xivovp_rxtx(unsigned long data)
+{
+ (void) data;
+ dahdi_receive(&xivovp.span)
+ dahdi_transmit(&xivovp.span)
+ dahdi_ec_span(&xivovp.span)
+
+ mod_timer(&xivovp.vp_tick_timer, jiffies + RXTX_TICK_JIFFIES);
+}
/* Shouldn't there be something better there? TOTHINK */
static struct xivovp_line* xivovp_line_from_ctx(VpLineCtxType* line_ctx)
{
- Vp890LineObjectType* line_obj = line_ctx->pLineObj;
+ Vp890LineObjectType* line_obj;
int i;
+ if(!line_ctx) {
+ printk(KERN_ERR DRV_NAME ": LineCtx == NULL\n");
+ return NULL;
+ }
+
+ line_obj = line_ctx->pLineObj;
+
for(i = 0; i < ARRAY_SIZE(xivovp.line); i++)
if(&xivovp.line[i].line_obj == line_obj)
return &xivovp.line[i];
- printk(KERN_ERR DRV_NAME ": a FX line we don't know of? This certainly shouldn't happen.\n");
+ printk(KERN_ERR DRV_NAME ": unknown FX line, this shouldn't happen\n");
return NULL;
}
@@ -87,28 +106,191 @@ static void vp_set_debug_select_running(void)
for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) {
debug_select = DEBUG_SELECT_RUNNING;
- VpSetOption(&xivovp.line[i].vp_ctx, NULL, VP_OPTION_ID_DEBUG_SELECT,
- &debug_select);
+ VpSetOption(&xivovp.line[i].vp_ctx, NULL,
+ VP_OPTION_ID_DEBUG_SELECT,
+ &debug_select);
}
debug_select = DEBUG_SELECT_RUNNING;
- VpSetOption(NULL, &xivovp.dev_ctx, VP_OPTION_ID_DEBUG_SELECT, &debug_select);
+ VpSetOption(NULL, &xivovp.dev_ctx, VP_OPTION_ID_DEBUG_SELECT,
+ &debug_select);
debug_select = DEBUG_SELECT_RUNNING;
VpSetOption(NULL, NULL, VP_OPTION_ID_DEBUG_SELECT, &debug_select);
}
-static void vp_tick(const unsigned long data)
+static int xivovp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
+{
+ struct xivovp_line* line = chan->pvt;
+
+ if(line->txsig_queue_len >= ARRAY_SIZE(line->txsig_queue)) {
+ printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun", chan->chanpos);
+ return -1;
+ }
+
+ line->txsig_queue[line->txsig_queue_len++] = txsig;
+ return 0;
+}
+
+/*
+ * hooksig transmits sig from DAHDI to VP.
+ * sig from VP is handled in vp_tick and transmitted to DAHDI with
+ * dahdi_hooksig
+ */
+static void xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig)
+{
+ int chanpos = line->chan.chanpos;
+ if(line->type == FXO_LINE) {
+ 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");
+ 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);
+ 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);
+ }
+ } else /* FXS */ {
+ switch(txsig) {
+ case DAHDI_TXSIG_START:
+ 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);
+ 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);
+ 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);
+ //VpSetLineState(line->vp_ctx, );
+ break;
+ default:
+ printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXS: %d\n", chanpos, txsig);
+ }
+ }
+}
+
+static void xivovp_handle_txsig_queue(void)
{
+ static int said;
int i, j;
+
+ for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) {
+ if(xivovp.line[i].ready) {
+ for(j = 0; j < xivovp.line[i].txsig_queue_len; j++) {
+ xivovp_hooksig_pvt(&xivovp.line[i],
+ xivovp.line[i].txsig_queue[j]);
+ }
+ xivovp.line[i].txsig_queue_len = 0;
+ } else if(!said) {
+ said = 1;
+ printk(KERN_WARNING DRV_NAME ": txsig pending but calibration not done yet! Waiting...\n");
+ }
+ }
+}
+
+static bool count_and_stop_traces = FALSE;
+
+static void vp_post_init(VpEventType *event)
+{
+ VpStatusType vpst;
+
+ VpOptionTimeslotType timeslot = {
+ .tx = 12,
+ .rx = 12,
+ };
+ VpOptionEventMaskType event_mask = {
+ .faults = 0,
+ .signaling = 0,
+ .response = 0,
+ .test = 0,
+ .process = 0,
+ .fxo = 0,
+ };
+
+ printk(KERN_INFO DRV_NAME ": vp dev init complete\n");
+
+ 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);
+ return;
+ }
+ vpst = VpSetOption(NULL, event->pDevCtx,
+ VP_OPTION_ID_TIMESLOT,
+ &timeslot);
+ if (vpst != VP_STATUS_SUCCESS) {
+ printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_TIMESLOT returned %d\n",
+ (int)vpst);
+ return;
+ }
+
+ 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);
+ return;
+ }
+
+ //TODO: VpSetLineState for FXO_LINE
+ //TODO: VpCalLine for FXO_LINE
+ // What happens if lines aren't connected?
+
+ vpst = VpCalLine(&xivovp.line[FXS_LINE].vp_ctx);
+ if (vpst != VP_STATUS_SUCCESS) {
+ printk(KERN_ERR DRV_NAME ": VpCalLine returned %d\n",
+ (int)vpst);
+ return;
+ }
+
+ mod_timer(&xivovp.vp_tick_timer, jiffies + RXTX_TICK_JIFFIES);
+ count_and_stop_traces = TRUE;
+}
+
+static void event_calibration_complete(VpEventType *event)
+{
+ printk(KERN_INFO DRV_NAME ": calibration succeeded\n");
+ xivovp_line_from_ctx(event->pLineCtx)->ready = 1;
+ vp_set_debug_select_running();
+}
+
+static void event_calibration_fail(VpEventType *event)
+{
+ (void) event;
+ 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);
+ dahdi_hooksig(&line->chan, DAHDI_RXSIG_OFFHOOK);
+}
+
+static void event_hook_on(VpEventType *event)
+{
+ struct xivovp_line *line = xivovp_line_from_ctx(event->pLineCtx);
+ dahdi_hooksig(&line->chan, DAHDI_RXSIG_ONHOOK);
+}
+
+static void vp_tick(const unsigned long data)
+{
static VpEventType event;
static VpResultsType result;
- struct xivovp_line* line;
bool ev_pending;
VpStatusType vpst;
- static bool count_and_stop_traces = FALSE;
- (void)data;
+ (void) data;
vpst = VpApiTick(&xivovp.dev_ctx, &ev_pending);
if (vpst != VP_STATUS_SUCCESS) {
@@ -133,84 +315,27 @@ static void vp_tick(const unsigned long data)
switch ((int)event.eventCategory) {
case VP_EVCAT_RESPONSE:
switch (event.eventId) {
- case VP_DEV_EVID_DEV_INIT_CMP: {
- VpOptionTimeslotType timeslot = {
- .tx = 12,
- .rx = 12,
- };
- VpOptionEventMaskType event_mask = {
- .faults = 0,
- .signaling = 0,
- .response = 0,
- .test = 0,
- .process = 0,
- .fxo = 0,
- };
- printk(KERN_INFO DRV_NAME ": vp dev init complete\n");
- 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);
- return;
- }
- vpst = VpSetOption(NULL, event.pDevCtx,
- VP_OPTION_ID_TIMESLOT,
- &timeslot);
- if (vpst != VP_STATUS_SUCCESS) {
- printk(KERN_ERR DRV_NAME ": VpSetOption VP_OPTION_ID_TIMESLOT returned %d\n",
- (int)vpst);
- return;
- }
-
- 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);
- return;
- }
-
- //TODO: VpSetLineState for FXO_LINE
- //TODO: VpCalLine for FXO_LINE
- // What happens if lines aren't connected?
-
- vpst = VpCalLine(&xivovp.line[FXS_LINE].vp_ctx);
- if (vpst != VP_STATUS_SUCCESS) {
- printk(KERN_ERR DRV_NAME ": VpCalLine returned %d\n",
- (int)vpst);
- return;
- }
- count_and_stop_traces = TRUE;
+ case VP_DEV_EVID_DEV_INIT_CMP:
+ vp_post_init(&event);
break;
- }
-
case VP_EVID_CAL_CMP:
- printk(KERN_INFO DRV_NAME ": calibration succeeded\n");
- xivovp_line_from_ctx(event.pLineCtx)->ready = 1;
- vp_set_debug_select_running();
+ event_calibration_complete(&event);
break;
case VP_EVID_CAL_BUSY:
- printk(KERN_WARNING DRV_NAME ": calibration failed (returned VP_EVID_CAL_BUSY)\n");
- vp_set_debug_select_running();
+ event_calibration_fail(&event);
break;
}
break;
case VP_EVCAT_FAULT:
break;
case VP_EVCAT_SIGNALING:
- if(!(line = xivovp_line_from_ctx(event.pLineCtx)))
- break;
-
switch (event.eventId) {
case VP_LINE_EVID_HOOK_OFF:
- dahdi_hooksig(&line->chan,
- DAHDI_RXSIG_OFFHOOK);
+ event_hook_off(&event);
break;
case VP_LINE_EVID_HOOK_ON:
- dahdi_hooksig(&line->chan,
- DAHDI_RXSIG_ONHOOK);
+ event_hook_on(&event);
break;
}
break;
@@ -233,88 +358,16 @@ static void vp_tick(const unsigned long data)
}
}
-
- for(i = 0; i < ARRAY_SIZE(xivovp.line); i++) {
- if(xivovp.line[i].ready) {
- for(j = 0; j < xivovp.line[i].txsig_queue_len; j++) {
- xivovp_hooksig_pvt(&xivovp.line[i],
- xivovp.line[i].txsig_queue[j]);
- }
- xivovp.line[i].txsig_queue_len = 0;
- }
- }
+ xivovp_handle_txsig_queue();
if (count_and_stop_traces) {
if (traces_vanish >= 0 && --traces_vanish < 0)
vp_set_debug_select_running();
}
- mod_timer(&xivovp.vp_tick_timer, jiffies + TICK_JIFFIES);
+ mod_timer(&xivovp.vp_tick_timer, jiffies + VP_TICK_JIFFIES);
}
-static int
-xivovp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
-{
- struct xivovp_line* line = chan->pvt;
-
- if(line->txsig_queue_len >= ARRAY_SIZE(line->txsig_queue)) {
- printk(KERN_WARNING DRV_NAME "(chan %d): txsig overrun", chan->chanpos);
- return -1;
- }
-
- line->txsig_queue[line->txsig_queue_len++] = txsig;
- return 0;
-}
-
-/*
- * hooksig transmits sig from DAHDI to VP.
- * sig from VP is handled in vp_tick and transmitted to DAHDI with
- * dahdi_hooksig
- */
-static int
-xivovp_hooksig_pvt(struct xivovp_line* line, enum dahdi_txsig txsig)
-{
- int chanpos = line->chan.chanpos;
- if(line->type == FXO_LINE) {
- 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");
- 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);
- 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);
- }
- } else /* FXS */ {
- switch(txsig) {
- case DAHDI_TXSIG_START:
- 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);
- 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);
- 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);
- //VpSetLineState(line->vp_ctx, );
- return -1;
- default:
- printk(KERN_WARNING DRV_NAME "(chan %d): unsupported tx state for FXS: %d\n", chanpos, txsig);
- return -1;
- }
- }
-
- return 0;
-}
static const struct dahdi_span_ops xivovp_span_ops = {
.owner = THIS_MODULE,
@@ -336,6 +389,11 @@ span_init(void)
init_waitqueue_head(&xivovp.span.maintq); /* still dunno what this is */
+ if(dahdi_register(&xivovp.span, /*prefmaster*/ 0)) {
+ printk(KERN_WARNING DRV_NAME ": couldn't register span.\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -349,6 +407,10 @@ xivovp_init(void)
xivovp.vp_tick_timer.function = vp_tick;
xivovp.vp_tick_timer.data = 42;
+ init_timer(&rxtx_timer);
+ rxtx_timer.function = xivovp_rxtx();
+ rxtx_timer.data = 1337;
+
xivovp.line[FXS_LINE].type = FXS_LINE;
xivovp.line[FXO_LINE].type = FXO_LINE;
@@ -456,7 +518,7 @@ test_evb_ve890_init(void)
goto err_dahdi_init;
}
- mod_timer(&xivovp.vp_tick_timer, jiffies + TICK_JIFFIES);
+ mod_timer(&xivovp.vp_tick_timer, jiffies + VP_TICK_JIFFIES);
return 0;
@@ -475,6 +537,8 @@ test_evb_ve890_exit(void)
{
printk(KERN_INFO DRV_NAME ": %s\n", __func__);
+ dahdi_unregister(&xivovp.span);
+
del_timer_sync(&xivovp.vp_tick_timer); /* XXX : TODO update upstream Linux doc of del_timer_sync */
tlp_spidev_exit();