summaryrefslogtreecommitdiff
path: root/xpp/card_fxs.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/card_fxs.c')
-rw-r--r--xpp/card_fxs.c223
1 files changed, 108 insertions, 115 deletions
diff --git a/xpp/card_fxs.c b/xpp/card_fxs.c
index 8392e73..359591d 100644
--- a/xpp/card_fxs.c
+++ b/xpp/card_fxs.c
@@ -52,13 +52,9 @@ DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl
#define FXS_DEFAULT_SIGCAP (ZT_SIG_SF | ZT_SIG_EM)
#endif
-#define LINES_REGULAR 8
#define LINES_DIGI_OUT 2
#define LINES_DIGI_INP 4
-#define MASK_DIGI_OUT (BITMASK(LINES_DIGI_OUT) << LINES_REGULAR)
-#define MASK_DIGI_INP (BITMASK(LINES_DIGI_INP) << (LINES_REGULAR + LINES_DIGI_OUT))
-
enum fxs_leds {
LED_GREEN,
LED_RED,
@@ -127,8 +123,8 @@ struct FXS_priv_data {
struct proc_dir_entry *fxs_info;
xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */
+ xpp_line_t search_fsk_pattern;
xpp_line_t found_fsk_pattern;
- xpp_line_t msg_waiting;
xpp_line_t update_offhook_state;
xpp_line_t dtmf_keypressed;
int led_counter[NUM_LEDS][CHANNELS_PERXPD];
@@ -156,7 +152,7 @@ static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_st
struct FXS_priv_data *priv;
priv = xpd->priv;
- DBG("%s/%s/%d: value=0x%02X\n", xbus->busname, xpd->xpdname, chan, value);
+ LINE_DBG(xpd, chan, "value=0x%02X\n", value);
priv->lasttxhook[chan] = value;
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
}
@@ -167,7 +163,7 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
BUG_ON(!xbus);
BUG_ON(!xpd);
- DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, chan, (on) ? "up" : "down");
+ LINE_DBG(xpd, chan, "%s\n", (on) ? "up" : "down");
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x42, value);
}
@@ -226,7 +222,7 @@ static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
BIT_CLR(priv->ledstate[which], chan);
}
}
- DBG("%s/%s/%d: LED: which=%d -- %s\n", xbus->busname, xpd->xpdname, chan, which, (on) ? "on" : "off");
+ LINE_DBG(xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off");
value = BIT(2) | BIT(3);
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
if(on)
@@ -258,8 +254,7 @@ static void handle_fxs_leds(xpd_t *xpd)
mod_value = DEFAULT_LED_PERIOD; /* safety value */
// led state is toggled
if((timer_count % mod_value) == 0) {
- DBG("%s/%s/%d ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i,
- (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
+ LINE_DBG(xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
if(!IS_SET(priv->ledstate[color], i)) {
do_led(xpd, i, color, 1);
} else {
@@ -295,29 +290,33 @@ static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
{
byte value = (on) ? 0x94 : 0x00;
- DBG("%s/%s/%d: METERING Generate: %s\n",
- xpd->xbus->busname, xpd->xpdname, chan,
- (on)?"ON":"OFF");
+ LINE_DBG(xpd, chan, "METERING Generate: %s\n", (on)?"ON":"OFF");
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, value);
}
#endif
/*---------------- FXS: Methods -------------------------------------------*/
-static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte revision)
+static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision)
{
xpd_t *xpd = NULL;
- int channels = min(8, CHANNELS_PERXPD);
-
+ int channels;
+ int regular_channels;
+
+ if(subtype == 2)
+ regular_channels = min(6, CHANNELS_PERXPD);
+ else
+ regular_channels = min(8, CHANNELS_PERXPD);
+ channels = regular_channels;
if(unit == 0)
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
xpd = xpd_alloc(sizeof(struct FXS_priv_data), proto_table, channels);
if(!xpd)
return NULL;
if(unit == 0) {
- DBG("First XPD on %s detected. Initialize digital outputs/inputs\n", xbus->busname);
- xpd->digital_outputs = MASK_DIGI_OUT;
- xpd->digital_inputs = MASK_DIGI_INP;
+ XBUS_DBG(xbus, "First XPD detected. Initialize digital outputs/inputs\n");
+ xpd->digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels;
+ xpd->digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT);
}
xpd->direction = TO_PHONE;
xpd->revision = revision;
@@ -333,21 +332,21 @@ static void clean_proc(xbus_t *xbus, xpd_t *xpd)
priv = xpd->priv;
#ifdef CONFIG_PROC_FS
if(priv->regfile) {
- DBG("Removing xpd SLIC file %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Removing xpd SLIC file\n");
priv->regfile->data = NULL;
remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir);
priv->regfile = NULL;
}
#ifdef WITH_METERING
if(priv->meteringfile) {
- DBG("Removing xpd metering tone file %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Removing xpd metering tone file\n");
priv->meteringfile->data = NULL;
remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
priv->meteringfile = NULL;
}
#endif
if(priv->fxs_info) {
- DBG("Removing xpd FXS_INFO file %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Removing xpd FXS_INFO file\n");
remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir);
priv->fxs_info = NULL;
}
@@ -363,19 +362,19 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xpd);
priv = xpd->priv;
#ifdef CONFIG_PROC_FS
- DBG("Creating FXS_INFO file for %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Creating FXS_INFO file\n");
priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd);
if(!priv->fxs_info) {
- ERR("Failed to create proc '%s' for %s/%s\n", PROC_FXS_INFO_FNAME, xbus->busname, xpd->xpdname);
+ XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXS_INFO_FNAME);
ret = -ENOENT;
goto err;
}
priv->fxs_info->owner = THIS_MODULE;
#ifdef WITH_METERING
- DBG("Creating Metering tone file for %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Creating Metering tone file\n");
priv->meteringfile = create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir);
if(!priv->meteringfile) {
- ERR("Failed to create proc file for SLICs of %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME);
ret = -ENOENT;
goto err;
}
@@ -384,10 +383,10 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
priv->meteringfile->read_proc = NULL;
priv->meteringfile->data = xpd;
#endif
- DBG("Creating SLICs file for %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "Creating SLICs file\n");
priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir);
if(!priv->regfile) {
- ERR("Failed to create proc file for SLICs of %s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME);
ret = -ENOENT;
goto err;
}
@@ -409,7 +408,7 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_CHANS, SLIC_WRITE, 0x22, 0x00); /* Ringing Oscilator Control */
if(ret < 0)
goto err;
- DBG("%s/%s: done\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "done\n");
for_each_line(xpd, i) {
do_led(xpd, i, LED_GREEN, 0);
do_led(xpd, i, LED_RED, 0);
@@ -423,11 +422,11 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
msleep(50);
}
restore_leds(xpd);
- pcm_recompute(xpd);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on);
return 0;
err:
clean_proc(xbus, xpd);
- ERR("%s/%s: Failed initializing registers (%d)\n", xbus->busname, xpd->xpdname, ret);
+ XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret);
return ret;
}
@@ -437,7 +436,7 @@ static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xpd);
priv = xpd->priv;
- DBG("%s/%s\n", xbus->busname, xpd->xpdname);
+ XPD_DBG(xpd, "\n");
clean_proc(xbus, xpd);
return 0;
}
@@ -453,11 +452,11 @@ static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on)
BUG_ON(!xbus);
priv = xpd->priv;
BUG_ON(!priv);
- DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
+ XPD_DBG(xpd, "%s\n", (on)?"on":"off");
for_each_line(xpd, i) {
struct zt_chan *cur_chan = &xpd->chans[i];
- DBG("setting FXS channel %d\n", i);
+ XPD_DBG(xpd, "setting FXS channel %d\n", i);
if(IS_SET(xpd->digital_outputs, i)) {
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d",
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
@@ -490,7 +489,7 @@ static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on)
BUG_ON(!xbus);
priv = xpd->priv;
BUG_ON(!priv);
- DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
+ XPD_DBG(xpd, "%s\n", (on)?"on":"off");
for_each_line(xpd, i) {
MARK_OFF(priv, i, LED_GREEN);
msleep(2);
@@ -508,11 +507,11 @@ int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
struct zt_chan *chan = NULL;
enum fxs_state txhook;
- DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
+ LINE_DBG(xpd, pos, "%s\n", txsig2str(txsig));
priv = xpd->priv;
BUG_ON(xpd->direction != TO_PHONE);
if (IS_SET(xpd->digital_inputs, pos)) {
- DBG("Ignoring signal sent to digital input line\n");
+ LINE_DBG(xpd, pos, "Ignoring signal sent to digital input line\n");
return 0;
}
if(SPAN_REGISTERED(xpd))
@@ -521,9 +520,10 @@ int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
case ZT_TXSIG_ONHOOK:
xpd->ringing[pos] = 0;
BIT_CLR(xpd->cid_on, pos);
- pcm_recompute(xpd);
+ BIT_CLR(priv->search_fsk_pattern, pos);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on);
if(IS_SET(xpd->digital_outputs, pos)) {
- DBG("%s/%s/%d: digital output OFF\n", xbus->busname, xpd->xpdname, pos);
+ LINE_DBG(xpd, pos, "digital output OFF\n");
ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
return ret;
}
@@ -531,8 +531,7 @@ int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
/*
* Restore state after KEWL hangup.
*/
- DBG("%s/%s/%d: KEWL STOP\n",
- xbus->busname, xpd->xpdname, pos);
+ LINE_DBG(xpd, pos, "KEWL STOP\n");
linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE);
if(IS_SET(xpd->offhook, pos))
MARK_ON(priv, pos, LED_GREEN);
@@ -559,7 +558,7 @@ int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
txhook = priv->lasttxhook[pos];
if(xpd->ringing[pos]) {
BIT_SET(xpd->cid_on, pos);
- pcm_recompute(xpd);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on);
txhook = FXS_LINE_OHTRANS;
}
xpd->ringing[pos] = 0;
@@ -578,21 +577,23 @@ int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
case ZT_TXSIG_START:
xpd->ringing[pos] = 1;
BIT_CLR(xpd->cid_on, pos);
- pcm_recompute(xpd);
+ BIT_CLR(priv->search_fsk_pattern, pos);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on);
if(IS_SET(xpd->digital_outputs, pos)) {
- DBG("%s/%s/%d: %s digital output ON\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
+ LINE_DBG(xpd, pos, "%s digital output ON\n", txsig2str(txsig));
ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
return ret;
}
ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on
break;
case ZT_TXSIG_KEWL:
- DBG("%s/%s/%d: KEWL START\n", xbus->busname, xpd->xpdname, pos);
+ LINE_DBG(xpd, pos, "KEWL START\n");
linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN);
MARK_OFF(priv, pos, LED_GREEN);
break;
default:
- NOTICE("%s: Can't set tx state to %s (%d)\n", __FUNCTION__, txsig2str(txsig), txsig);
+ XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n",
+ __FUNCTION__, txsig2str(txsig), txsig);
ret = -EINVAL;
}
return ret;
@@ -615,7 +616,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
BUG_ON(!xbus);
if (pos < 0 || pos >= xpd->channels) {
- NOTICE("%s/%s: Bad channel number %d in %s(), cmd=%u\n", xbus->busname, xpd->xpdname, pos, __FUNCTION__, cmd);
+ XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n",
+ pos, __FUNCTION__, cmd);
return -EINVAL;
}
@@ -623,19 +625,20 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
case ZT_ONHOOKTRANSFER:
if (get_user(val, (int __user *)arg))
return -EFAULT;
- DBG("%s/%s/%d: ZT_ONHOOKTRANSFER (%d millis)\n",
- xbus->busname, xpd->xpdname, pos, val);
+ LINE_DBG(xpd, pos, "ZT_ONHOOKTRANSFER (%d millis)\n", val);
BUG_ON(pos == ALL_CHANS);
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
return 0; /* Nothing to do */
+ BIT_CLR(xpd->cid_on, pos);
+ BIT_SET(priv->search_fsk_pattern, pos);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on | priv->search_fsk_pattern);
if(!IS_SET(xpd->offhook, pos))
start_stop_vm_led(xbus, xpd, pos);
return 0;
case ZT_TONEDETECT:
if (get_user(val, (int __user *)arg))
return -EFAULT;
- DBG("%s/%s/%d: ZT_TONEDETECT: %s %s (dtmf_detection=%s)\n",
- xbus->busname, xpd->xpdname, pos,
+ LINE_DBG(xpd, pos, "ZT_TONEDETECT: %s %s (dtmf_detection=%s)\n",
(val & ZT_TONEDETECT_ON) ? "ON" : "OFF",
(val & ZT_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE",
(dtmf_detection ? "YES" : "NO"));
@@ -645,17 +648,16 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
if (get_user(val, (int __user *)arg))
return -EFAULT;
if(!vmwi_ioctl) {
- NOTICE("%s/%s/%d: Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n",
- xbus->busname, xpd->xpdname, pos);
+ LINE_NOTICE(xpd, pos, "Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n");
return 0;
}
/* Digital inputs/outputs don't have VM leds */
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
return 0;
if (val)
- BIT_SET(priv->msg_waiting, pos);
+ BIT_SET(xpd->msg_waiting, pos);
else
- BIT_CLR(priv->msg_waiting, pos);
+ BIT_CLR(xpd->msg_waiting, pos);
return 0;
#endif
}
@@ -668,9 +670,9 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on)
BUG_ON(!xbus);
BUG_ON(!xpd);
+ LINE_DBG(xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)");
if (!vmwineon)
return 0;
-
if (on) {
/* A write to register 0x40 will now turn on/off the VM led */
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
@@ -709,8 +711,8 @@ static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
return;
priv = xpd->priv;
- on = IS_SET(((struct FXS_priv_data *)xpd->priv)->msg_waiting, pos);
- DBG("%s/%s/%d %s\n", xbus->busname, xpd->xpdname, pos, (on)?"ON":"OFF");
+ on = IS_SET(xpd->msg_waiting, pos);
+ LINE_DBG(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]);
@@ -724,8 +726,7 @@ static int FXS_card_open(xpd_t *xpd, lineno_t chan)
BUG_ON(!xpd);
priv = xpd->priv;
is_offhook = IS_SET(xpd->offhook, chan);
- DBG("%s/%s:%d (is %shook)\n", xpd->xbus->busname, xpd->xpdname,
- chan, (is_offhook)?"off":"on");
+ LINE_DBG(xpd, chan, "(is %shook)\n", (is_offhook)?"off":"on");
/*
* Delegate updating zaptel to FXS_card_tick():
* The problem is that zt_hooksig() is spinlocking the channel and
@@ -741,7 +742,7 @@ static int FXS_card_close(xpd_t *xpd, lineno_t chan)
struct FXS_priv_data *priv;
BUG_ON(!xpd);
- DBG("%s/%s:%d\n", xpd->xbus->busname, xpd->xpdname, chan);
+ LINE_DBG(xpd, chan, "\n");
priv = xpd->priv;
priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE;
return 0;
@@ -801,7 +802,7 @@ void handle_linefeed(xpd_t *xpd)
enum fxs_state txhook = FXS_LINE_POL_ACTIVE;
/* Apply the change if appropriate */
BIT_CLR(xpd->cid_on, i);
- pcm_recompute(xpd);
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on);
linefeed_control(xpd->xbus, xpd, i, txhook);
}
}
@@ -837,25 +838,26 @@ static void detect_vmwi(xpd_t *xpd)
int i;
BUG_ON(!xpd);
- if (!vmwineon)
- return;
xbus = xpd->xbus;
priv = xpd->priv;
BUG_ON(!priv);
for_each_line(xpd, i) {
- byte *writechunk = xpd->span.chans[i].writechunk;
+ struct zt_chan *chan = &xpd->span.chans[i];
+ byte *writechunk = chan->writechunk;
if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i))
continue;
#if 0
- if(i == 0 && writechunk[0] != 0x7F) {
+ if(writechunk[0] != 0x7F && writechunk[0] != 0) {
int j;
- DBG("%s/%s/%d: MSG:", xbus->busname, xpd->xpdname, i);
+ LINE_DBG(xpd, pos, "MSG:");
for(j = 0; j < ZT_CHUNKSIZE; j++) {
- printk(" %02X", writechunk[j]);
+ if(print_dbg)
+ printk(" %02X", writechunk[j]);
}
- printk("\n");
+ if(print_dbg)
+ printk("\n");
}
#endif
if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE)))
@@ -863,17 +865,17 @@ static void detect_vmwi(xpd_t *xpd)
else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) {
BIT_CLR(priv->found_fsk_pattern, i);
if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, ZT_CHUNKSIZE))) {
- DBG("%s/%s/%d: MSG WAITING ON\n", xbus->busname, xpd->xpdname, i);
- BIT_SET(priv->msg_waiting, i);
+ LINE_DBG(xpd, i, "MSG WAITING ON\n");
+ BIT_SET(xpd->msg_waiting, i);
start_stop_vm_led(xbus, xpd, i);
} else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, ZT_CHUNKSIZE))) {
- DBG("%s/%s/%d: MSG WAITING OFF\n", xbus->busname, xpd->xpdname, i);
- BIT_CLR(priv->msg_waiting, i);
+ LINE_DBG(xpd, i, "MSG WAITING OFF\n");
+ BIT_CLR(xpd->msg_waiting, i);
start_stop_vm_led(xbus, xpd, i);
} else {
int j;
- NOTICE("%s/%s/%d: MSG WAITING Unexpected:", xbus->busname, xpd->xpdname, i);
+ LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:");
for(j = 0; j < ZT_CHUNKSIZE; j++) {
printk(" %02X", writechunk[j]);
}
@@ -908,8 +910,7 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
* Update LEDs and zaptel with current state of line.
*/
if(IS_SET(xpd->offhook, i)) {
- NOTICE("%s/%s/%d: Already offhook during open. OK.\n",
- xbus->busname, xpd->xpdname, i);
+ LINE_NOTICE(xpd, i, "Already offhook during open. OK.\n");
MARK_ON(priv, i, LED_GREEN);
update_line_status(xpd, i, 1);
} else {
@@ -920,8 +921,8 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
}
}
if(SPAN_REGISTERED(xpd)) {
- if(!vmwi_ioctl)
- detect_vmwi(xpd);
+ if(vmwineon && !vmwi_ioctl)
+ detect_vmwi(xpd); /* Detect via FSK modulation */
if(dtmf_detection &&
(xpd->timer_count % POLL_DTMF_INTERVAL) == 0)
poll_dtmf(xpd);
@@ -944,8 +945,7 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
}
XFRAME_NEW(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx);
#if 0
- DBG("%s/%s/%d: %c%c R%02X S%02X %02X %02X\n",
- xbus->busname, xpd->xpdname, chipsel,
+ LINE_DBG(xpd, chipsel, "%c%c R%02X S%02X %02X %02X\n",
(writing)?'W':'R',
(do_subreg)?'S':'D',
regnum, subreg, data_low, data_high);
@@ -974,7 +974,7 @@ static /* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on)
BUG_ON(!xpd);
priv = xpd->priv;
spin_lock_irqsave(&xpd->lock, flags);
- DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on) ? "on" : "off");
+ XPD_DBG(xpd, "%s\n", (on)?"on":"off");
for_each_line(xpd, i)
linefeed_control(xbus, xpd, i, value);
if(on) {
@@ -994,7 +994,7 @@ static /* 0x0F */ HOSTCMD(FXS, RING, lineno_t chan, bool on)
BUG_ON(!xbus);
BUG_ON(!xpd);
- DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, chan, (on) ? "on" : "off");
+ LINE_DBG(xpd, chan, "%s\n", (on)?"on":"off");
priv = xpd->priv;
set_vm_led_mode(xbus, xpd, chan, 0);
do_chan_power(xbus, xpd, chan, on); // Power up (for ring)
@@ -1015,7 +1015,7 @@ static /* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on)
BUG_ON(!xbus);
BUG_ON(!xpd);
- DBG("RELAY_OUT: which=%d -- %s\n", which, (on) ? "on" : "off");
+ XPD_DBG(xpd, "RELAY_OUT: which=%d -- %s\n", which, (on) ? "on" : "off");
which = which % ARRAY_SIZE(relay_channels);
value = BIT(2) | BIT(3);
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
@@ -1037,7 +1037,7 @@ HANDLER_DEF(FXS, SIG_CHANGED)
BUG_ON(!xpd);
BUG_ON(xpd->direction != TO_PHONE);
priv = xpd->priv;
- DBG("%s/%s: (PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", xbus->busname, xpd->xpdname, sig_toggles, sig_status);
+ XPD_DBG(xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status);
#if 0
Is this needed?
for_each_line(xpd, i) {
@@ -1057,18 +1057,18 @@ HANDLER_DEF(FXS, SIG_CHANGED)
#endif
MARK_BLINK(priv, i, LED_GREEN, 0);
if(IS_SET(sig_status, i)) {
- DBG("%s/%s/%d: OFFHOOK\n", xbus->busname, xpd->xpdname, i);
+ LINE_DBG(xpd, i, "OFFHOOK\n");
MARK_ON(priv, i, LED_GREEN);
update_line_status(xpd, i, 1);
} else {
- DBG("%s/%s/%d: ONHOOK\n", xbus->busname, xpd->xpdname, i);
+ LINE_DBG(xpd, i, "ONHOOK\n");
MARK_OFF(priv, i, LED_GREEN);
update_line_status(xpd, i, 0);
}
}
}
spin_unlock_irqrestore(&xpd->lock, flags);
- pcm_recompute(xpd); /* it's spinlocked */
+ pcm_recompute(xpd, xpd->offhook | xpd->cid_on); /* it's spinlocked */
return 0;
}
@@ -1084,15 +1084,15 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
int newchanno;
if(IS_SET(lines, channo)) {
- newchanno = LINES_REGULAR + LINES_DIGI_OUT + i;
+ newchanno = xpd->channels - LINES_DIGI_INP + i;
BIT_CLR(lines, channo);
BIT_SET(lines, newchanno);
xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs.
if(offhook && !IS_SET(xpd->offhook, newchanno)) { // OFFHOOK
- DBG("%s/%s/%d: OFFHOOK\n", xpd->xbus->busname, xpd->xpdname, newchanno);
+ LINE_DBG(xpd, newchanno, "OFFHOOK\n");
update_line_status(xpd, newchanno, 1);
} else if(!offhook && IS_SET(xpd->offhook, newchanno)) { // ONHOOK
- DBG("%s/%s/%d: ONHOOK\n", xpd->xbus->busname, xpd->xpdname, newchanno);
+ LINE_DBG(xpd, newchanno, "ONHOOK\n");
update_line_status(xpd, newchanno, 0);
}
}
@@ -1116,8 +1116,7 @@ void process_dtmf(xpd_t *xpd, const reg_cmd_t *info)
val &= 0xF;
if(val <= 0) {
if(on)
- NOTICE("%s/%s: Bad DTMF value %d. Ignored\n",
- xpd->xbus->busname, xpd->xpdname, val);
+ XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", val);
return;
}
val--;
@@ -1125,14 +1124,12 @@ void process_dtmf(xpd_t *xpd, const reg_cmd_t *info)
for_each_line(xpd, i) {
if(IS_SET(lines, i)) {
if(on && !IS_SET(priv->dtmf_keypressed, i)) {
- DBG("%s/%s/%d: DTMF digit %2d PRESSED (%d)\n",
- xpd->xbus->busname, xpd->xpdname, i, digit, val);
+ LINE_DBG(xpd, i, "DTMF digit %2d PRESSED (%d)\n", digit, val);
BIT_SET(priv->dtmf_keypressed, i);
if(dtmf_detection)
zt_qevent_lock(&xpd->chans[i], ZT_EVENT_DTMFDOWN | digit);
} else if(!on && IS_SET(priv->dtmf_keypressed, i)) {
- DBG("%s/%s/%d: DTMF digit %2d RELEASED\n",
- xpd->xbus->busname, xpd->xpdname, i, digit);
+ LINE_DBG(xpd, i, "DTMF digit %2d RELEASED\n", digit);
BIT_CLR(priv->dtmf_keypressed, i);
if(dtmf_detection)
zt_qevent_lock(&xpd->chans[i], ZT_EVENT_DTMFUP | digit);
@@ -1160,8 +1157,8 @@ HANDLER_DEF(FXS, REGISTER_REPLY)
indirect = (REG_FIELD(info, regnum) == 0x1E);
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
#if 0
- DBG("REGISTER_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
- xpd->xbus_idx, (indirect)?"I":"D",
+ XPD_DBG(xpd, "REGISTER_REPLY: %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
+ (indirect)?"I":"D",
regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
#endif
if(!SPAN_REGISTERED(xpd))
@@ -1402,7 +1399,7 @@ static int handle_register_command(xpd_t *xpd, char *cmdline)
BUG_ON(!xpd);
xbus = xpd->xbus;
if(!down_read_trylock(&xbus->in_use)) {
- DBG("Dropped packet. %s is in_use\n", xbus->busname);
+ XBUS_DBG(xbus, "Dropped packet. Is in_use\n");
return -EBUSY;
}
xpd->requested_reply = regcmd;
@@ -1498,8 +1495,7 @@ static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
if(!xpd)
return -ENODEV;
if(count >= MAX_PROC_WRITE - 1) {
- ERR("%s/%s: Metering string too long (%lu)\n",
- xpd->xbus->busname, xpd->xpdname, count);
+ XPD_ERR(xpd, "Metering string too long (%lu)\n", count);
return -EINVAL;
}
if(copy_from_user(&buf, buffer, count))
@@ -1507,19 +1503,16 @@ static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
buf[count] = '\0';
ret = sscanf(buf, "%d", &num);
if(ret != 1) {
- ERR("%s/%s: Metering value should be number. Got '%s'\n",
- xpd->xbus->busname, xpd->xpdname, buf);
+ XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf);
return -EINVAL;
}
chan = num;
if(chan != ALL_CHANS && chan > xpd->channels) {
- ERR("%s/%s: Metering tone: bad channel number %d\n",
- xpd->xbus->busname, xpd->xpdname, chan);
+ XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan);
return -EINVAL;
}
if((ret = metering_gen(xpd, chan, 1)) < 0) {
- ERR("%s/%s: Failed sending metering tone\n",
- xpd->xbus->busname, xpd->xpdname);
+ XPD_ERR(xpd, "Failed sending metering tone\n");
return ret;
}
return count;
@@ -1528,22 +1521,22 @@ static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
int __init card_fxs_startup(void)
{
- INFO("%s revision %s\n", THIS_MODULE->name, XPP_VERSION);
+ INFO("revision %s\n", XPP_VERSION);
#ifdef POLL_DIGITAL_INPUTS
- INFO("FEATURE: %s with DIGITAL INPUTS support (polled every %d msec)\n",
- THIS_MODULE->name, poll_digital_inputs);
+ INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n",
+ poll_digital_inputs);
#else
- INFO("FEATURE: %s without DIGITAL INPUTS support\n", THIS_MODULE->name);
+ INFO("FEATURE: without DIGITAL INPUTS support\n");
#endif
#ifdef ZT_VMWI
- INFO("FEATURE: %s ZT_VMWI\n", THIS_MODULE->name);
+ INFO("FEATURE: ZT_VMWI\n");
#else
- INFO("FEATURE: %s NO ZT_VMWI\n", THIS_MODULE->name);
+ INFO("FEATURE: NO ZT_VMWI\n");
#endif
#ifdef WITH_METERING
- INFO("FEATURE: %s WITH METERING Generation\n", THIS_MODULE->name);
+ INFO("FEATURE: WITH METERING Generation\n");
#else
- INFO("FEATURE: %s NO METERING Generation\n", THIS_MODULE->name);
+ INFO("FEATURE: NO METERING Generation\n");
#endif
xproto_register(&PROTO_TABLE(FXS));
return 0;