summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2010-07-13 11:07:57 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2010-07-13 11:07:57 +0000
commitf957d246eec2b5617035407629adc78e30406d26 (patch)
treec9c0e9c80e43852056acfeeeb32a3c4a2103672a
parent3d5c42a871d30c4fb6ee6520b0c4c39ffa86fe18 (diff)
Basic support for DAHDI_VMWI_CONFIG
* Supports only our current NEON notification. * No more global 'vmwineon' parameter: - We expect asterisk to tell us by channel. - If 'vmwi_ioctl' is not set (it is by default), that we revert to FSK searching (expensive) and call directly our NEON code (as before). git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8887 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/xpp/card_fxs.c100
-rw-r--r--drivers/dahdi/xpp/xpd.h3
-rw-r--r--drivers/dahdi/xpp/xpp_dahdi.c2
3 files changed, 73 insertions, 32 deletions
diff --git a/drivers/dahdi/xpp/card_fxs.c b/drivers/dahdi/xpp/card_fxs.c
index c29e320..1629d4f 100644
--- a/drivers/dahdi/xpp/card_fxs.c
+++ b/drivers/dahdi/xpp/card_fxs.c
@@ -35,17 +35,12 @@ static const char rcsid[] = "$Id$";
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
static DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity");
-static DEF_PARM_BOOL(vmwineon, 0, 0644, "Indicate voicemail to a neon lamp");
static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
#ifdef POLL_DIGITAL_INPUTS
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
#endif
-#ifdef DAHDI_VMWI
-static DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl");
-#else
-#define vmwi_ioctl 0 /* not supported */
-#endif
+static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644, "Asterisk support VMWI notification via ioctl");
/* Signaling is opposite (fxo signalling for fxs card) */
#if 1
@@ -54,6 +49,10 @@ static DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification vi
#define FXS_DEFAULT_SIGCAP (DAHDI_SIG_SF | DAHDI_SIG_EM)
#endif
+#define VMWI_TYPE(priv, pos, type) \
+ ((priv)->vmwisetting[pos].vmwi_type & DAHDI_VMWI_HVAC)
+#define VMWI_NEON(priv, pos) VMWI_TYPE(priv, pos, HVAC)
+
#define LINES_DIGI_OUT 2
#define LINES_DIGI_INP 4
@@ -142,6 +141,7 @@ struct FXS_priv_data {
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
enum fxs_state idletxhookstate[CHANNELS_PERXPD]; /* IDLE changing hook state */
enum fxs_state lasttxhook[CHANNELS_PERXPD];
+ struct dahdi_vmwi_info vmwisetting[CHANNELS_PERXPD];
};
/*
@@ -183,7 +183,7 @@ static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
priv = xpd->priv;
BUG_ON(!xpd);
- if(vmwineon && on) {
+ if (VMWI_NEON(priv, pos) && on) {
LINE_DBG(SIGNAL, xpd, pos, "START\n");
BIT_SET(priv->search_fsk_pattern, pos);
} else {
@@ -559,13 +559,16 @@ static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0); /* already spinlocked */
}
-static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, bool msg_waiting)
+static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
+ unsigned int msg_waiting)
{
int ret = 0;
+ struct FXS_priv_data *priv;
BUG_ON(!xbus);
BUG_ON(!xpd);
- if (vmwineon && msg_waiting) {
+ priv = xpd->priv;
+ if (VMWI_NEON(priv, pos) && msg_waiting) {
/* A write to register 0x40 will now turn on/off the VM led */
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
@@ -598,17 +601,18 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, bool msg_waiting)
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
{
struct FXS_priv_data *priv;
- bool on;
+ unsigned int msgs;
BUG_ON(!xpd);
if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
return;
priv = xpd->priv;
- on = IS_SET(xpd->msg_waiting, pos);
- LINE_DBG(SIGNAL, xpd, pos, "%s\n", (on)?"ON":"OFF");
- set_vm_led_mode(xbus, xpd, pos, on);
- do_chan_power(xbus, xpd, pos, on);
- linefeed_control(xbus, xpd, pos, (on) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
+ msgs = xpd->msg_waiting[pos];
+ LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
+ set_vm_led_mode(xbus, xpd, pos, msgs);
+ do_chan_power(xbus, xpd, pos, msgs > 0);
+ linefeed_control(xbus, xpd, pos, (msgs > 0) ?
+ FXS_LINE_RING : priv->idletxhookstate[pos]);
}
static int relay_out(xpd_t *xpd, int pos, bool on)
@@ -763,6 +767,45 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
return ret;
}
+static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
+{
+ struct FXS_priv_data *priv;
+ struct dahdi_vmwi_info vmwisetting;
+ const int vmwi_flags = DAHDI_VMWI_LREV | DAHDI_VMWI_HVDC
+ | DAHDI_VMWI_HVAC;
+
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ if (copy_from_user(&vmwisetting, (__user void *)arg,
+ sizeof(vmwisetting)))
+ return -EFAULT;
+ if ((vmwisetting.vmwi_type & ~vmwi_flags) != 0) {
+ LINE_NOTICE(xpd, pos, "Bad DAHDI_VMWI_CONFIG: 0x%X\n",
+ vmwisetting.vmwi_type);
+ return -EINVAL;
+ }
+ LINE_DBG(SIGNAL, xpd, pos,
+ "DAHDI_VMWI_CONFIG: 0x%X\n",
+ vmwisetting.vmwi_type);
+ if (VMWI_TYPE(priv, pos, LREV)) {
+ LINE_NOTICE(xpd, pos,
+ "%s: VMWI(lrev) is not implemented yet. Ignored.\n",
+ __func__);
+ }
+ if (VMWI_TYPE(priv, pos, HVDC)) {
+ LINE_NOTICE(xpd, pos,
+ "%s: VMWI(hvdc) is not implemented yet. Ignored.\n",
+ __func__);
+ }
+ if (VMWI_TYPE(priv, pos, HVAC))
+ /* VMWI_NEON */
+ if (priv->vmwisetting[pos].vmwi_type == 0)
+ /* Disable VMWI */
+ priv->vmwisetting[pos] = vmwisetting;
+ set_vm_led_mode(xpd->xbus, xpd, pos, xpd->msg_waiting[pos]);
+ return 0;
+}
+
/*
* Private ioctl()
* We don't need it now, since we detect vmwi via FSK patterns
@@ -802,7 +845,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
CALL_XMETHOD(card_pcm_recompute, xbus, xpd, priv->search_fsk_pattern);
LINE_DBG(SIGNAL, xpd, pos, "Start OHT_TIMER. wanted_pcm_mask=0x%X\n", xpd->wanted_pcm_mask);
}
- if(vmwineon && !IS_OFFHOOK(xpd, pos))
+ if (VMWI_NEON(priv, pos) && !IS_OFFHOOK(xpd, pos))
start_stop_vm_led(xbus, xpd, pos);
return 0;
case DAHDI_TONEDETECT:
@@ -871,7 +914,10 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
priv->lasttxhook[pos] &= ~FXS_LINE_RING;
linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]);
return 0;
-#ifdef DAHDI_VMWI
+ case DAHDI_VMWI_CONFIG:
+ if (set_vmwi(xpd, pos, arg) < 0)
+ return -EINVAL;
+ return 0;
case DAHDI_VMWI: /* message-waiting led control */
if (get_user(val, (int __user *)arg))
return -EFAULT;
@@ -886,12 +932,10 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
/* Digital inputs/outputs don't have VM leds */
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
return 0;
- if (val)
- BIT_SET(xpd->msg_waiting, pos);
- else
- BIT_CLR(xpd->msg_waiting, pos);
+ xpd->msg_waiting[pos] = val;
+ LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n",
+ (val) ? "yes" : "no");
return 0;
-#endif
default:
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
}
@@ -1048,11 +1092,11 @@ static void detect_vmwi(xpd_t *xpd)
oht_pcm(xpd, i, 0);
if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) {
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
- BIT_SET(xpd->msg_waiting, i);
+ xpd->msg_waiting[i] = 1;
start_stop_vm_led(xbus, xpd, i);
} else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, DAHDI_CHUNKSIZE))) {
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
- BIT_CLR(xpd->msg_waiting, i);
+ xpd->msg_waiting[i] = 0;
start_stop_vm_led(xbus, xpd, i);
} else {
int j;
@@ -1102,7 +1146,7 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
}
}
if(SPAN_REGISTERED(xpd)) {
- if(vmwineon && !vmwi_ioctl && priv->search_fsk_pattern)
+ i f(!vmwi_ioctl && priv->search_fsk_pattern)
detect_vmwi(xpd); /* Detect via FSK modulation */
}
return 0;
@@ -1549,11 +1593,7 @@ static int __init card_fxs_startup(void)
#else
INFO("FEATURE: without DIGITAL INPUTS support\n");
#endif
-#ifdef DAHDI_VMWI
- INFO("FEATURE: DAHDI_VMWI\n");
-#else
- INFO("FEATURE: NO DAHDI_VMWI\n");
-#endif
+ INFO("FEATURE: DAHDI_VMWI (HVAC only)\n");
#ifdef WITH_METERING
INFO("FEATURE: WITH METERING Generation\n");
#else
diff --git a/drivers/dahdi/xpp/xpd.h b/drivers/dahdi/xpp/xpd.h
index d58b40a..a2c0d52 100644
--- a/drivers/dahdi/xpp/xpd.h
+++ b/drivers/dahdi/xpp/xpd.h
@@ -167,7 +167,8 @@ struct xpd {
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
- xpp_line_t msg_waiting; /* Voice Mail Waiting Indication */
+ /* Voice Mail Waiting Indication: */
+ unsigned int msg_waiting[CHANNELS_PERXPD];
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
xpp_line_t digital_signalling; /* BRI signalling channels */
diff --git a/drivers/dahdi/xpp/xpp_dahdi.c b/drivers/dahdi/xpp/xpp_dahdi.c
index 443885c..1f57878 100644
--- a/drivers/dahdi/xpp/xpp_dahdi.c
+++ b/drivers/dahdi/xpp/xpp_dahdi.c
@@ -362,7 +362,7 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
}
len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting");
for_each_line(xpd, i) {
- len += sprintf(page + len, "%d ", IS_SET(xpd->msg_waiting, i));
+ len += sprintf(page + len, "%d ", xpd->msg_waiting[i]);
}
len += sprintf(page + len, "\n\t%-17s: ", "ringing");
for_each_line(xpd, i) {