summaryrefslogtreecommitdiff
path: root/xpp/card_fxo.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-07-06 13:47:05 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-07-06 13:47:05 +0000
commit39a1812c1ef76b6a792f00087f1e507616bbbb25 (patch)
treee50633c999779c514ef16f4a2ce7a70fc7511c9e /xpp/card_fxo.c
parent70ef1183eba2d2fe4f00668fd3438b7f1c842c94 (diff)
Tons of updates to the Astribank (xpp) driver:
* xpd_fxo.ko (FXO span) is now operational * Remove obsolete .inc initialization files (we use user-space init) * Added an install target to the utils dir. * Updated README.Astribank accordingly. * Using RBS signalling, as caller ID did not work well otherwise. * Better handling of USB protocol errors. * Fixed some procfs-related races. * per-card-module ioctls. * fxotune support. * opermode support (set through /etc/default/zaptel for now) * Userspace initialization script can also read registers. * Power calibration works (and implemented in perl) * some fine-tuning to the regster initialization parameters. * Leds turn on before registration and turn off after it. git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1204 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/card_fxo.c')
-rw-r--r--xpp/card_fxo.c337
1 files changed, 193 insertions, 144 deletions
diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c
index bd3e141..d383e5d 100644
--- a/xpp/card_fxo.c
+++ b/xpp/card_fxo.c
@@ -34,6 +34,15 @@
static const char rcsid[] = "$Id$";
DEF_PARM(int, print_dbg, 0, "Print DBG statements"); /* must be before zap_debug.h */
+DEF_PARM(uint, poll_battery_interval, 100, "Poll battery interval in milliseconds");
+DEF_PARM(bool, report_battery, 0, "Report battery status to zaptel");
+
+/* Signaling is opposite (fxs signalling for fxo card) */
+#if 1
+#define FXO_DEFAULT_SIGCAP (ZT_SIG_FXSKS | ZT_SIG_FXSLS)
+#else
+#define FXO_DEFAULT_SIGCAP (ZT_SIG_SF)
+#endif
enum fxo_leds {
LED_GREEN,
@@ -44,39 +53,19 @@ enum fxo_leds {
/*---------------- FXO Protocol Commands ----------------------------------*/
-/* 0x0F */ DECLARE_CMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on);
-/* 0x0F */ DECLARE_CMD(FXO, CHAN_CID, xpp_line_t lines);
-/* 0x0F */ DECLARE_CMD(FXO, RING, int pos, bool on);
-/* 0x0F */ DECLARE_CMD(FXO, SETHOOK, int pos, bool offhook);
-/* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on);
-/* 0x0F */ DECLARE_CMD(FXO, DAA_INIT);
-/* 0x0F */ DECLARE_CMD(FXO, DAA_QUERY, int pos, byte reg_num);
+static /* 0x0F */ DECLARE_CMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on);
+static /* 0x0F */ DECLARE_CMD(FXO, CHAN_CID, int pos);
+static /* 0x0F */ DECLARE_CMD(FXO, RING, int pos, bool on);
+static /* 0x0F */ DECLARE_CMD(FXO, SETHOOK, int pos, bool offhook);
+static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on);
+static /* 0x0F */ DECLARE_CMD(FXO, DAA_QUERY, int pos, byte reg_num);
static bool fxo_packet_is_valid(xpacket_t *pack);
static void fxo_packet_dump(xpacket_t *pack);
static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
-
-#define S_(s,l,...) \
- { \
- .lines = s, \
- { \
- .len = l, \
- .data = { __VA_ARGS__ }, \
- } \
- }
-struct slic_init_data {
- xpp_line_t lines;
- slic_data_t slic_data;
-} slic_init_data[] = {
-#ifdef OLD_CARD
-#include "init_data_4_19.inc"
-#else
-#include "init_data_4_20.inc"
-#endif
-};
-#undef S_
+static int process_slic_cmdline(xpd_t *xpd, char *cmdline);
#define PROC_DAA_FNAME "slics"
#define PROC_FXO_INFO_FNAME "fxo_info"
@@ -126,7 +115,7 @@ static int do_led(xpd_t *xpd, lineno_t pos, byte which, bool on)
BIT_CLR(priv->ledstate[which], pos);
}
}
- if(!(lines & xpd->enabled_chans)) // Ignore disabled channels
+ if(!lines) // Nothing to do
goto out;
DBG("%s/%s: LED: lines=0x%04X which=%d -- %s\n", xbus->busname, xpd->xpdname, lines, which, (on) ? "on" : "off");
XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
@@ -151,7 +140,7 @@ static void handle_fxo_leds(xpd_t *xpd)
spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv;
timer_count = xpd->timer_count;
- for_each_enabled_line(xpd, i) {
+ for_each_line(xpd, i) {
if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
continue;
if(IS_BLINKING(priv,i,color)) {
@@ -172,10 +161,16 @@ static void handle_fxo_leds(xpd_t *xpd)
static void do_sethook(xpd_t *xpd, int pos, bool offhook)
{
- unsigned long flags;
+ unsigned long flags;
+ struct FXO_priv_data *priv;
BUG_ON(!xpd);
BUG_ON(xpd->direction == TO_PHONE); // We can SETHOOK state only on PSTN
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ if(!IS_SET(priv->battery, pos)) {
+ DBG("%s/%s/%d: WARNING: called while battery is off\n", xpd->xbus->busname, xpd->xpdname, pos);
+ }
spin_lock_irqsave(&xpd->lock, flags);
xpd->ringing[pos] = 0; // No more rings
CALL_XMETHOD(SETHOOK, xpd->xbus, xpd, pos, offhook);
@@ -228,6 +223,7 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
{
struct FXO_priv_data *priv;
int ret = 0;
+ int i;
BUG_ON(!xpd);
priv = xpd->priv;
@@ -237,41 +233,34 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
if(!priv->fxo_info) {
ERR("Failed to create proc '%s' for %s/%s\n", PROC_FXO_INFO_FNAME, xbus->busname, xpd->xpdname);
ret = -ENOENT;
- goto out;
+ goto err;
}
+ priv->fxo_info->owner = THIS_MODULE;
DBG("Creating DAAs file for %s/%s\n", xbus->busname, xpd->xpdname);
priv->xpd_slic = create_proc_entry(PROC_DAA_FNAME, 0644, xpd->proc_xpd_dir);
if(!priv->xpd_slic) {
ERR("Failed to create proc file for DAAs of %s/%s\n", xbus->busname, xpd->xpdname);
- goto out;
+ ret = -ENOENT;
+ goto err;
}
+ priv->xpd_slic->owner = THIS_MODULE;
priv->xpd_slic->write_proc = proc_xpd_slic_write;
priv->xpd_slic->read_proc = proc_xpd_slic_read;
priv->xpd_slic->data = xpd;
#endif
-#ifdef HARD_CODED_INIT
- CALL_PROTO(FXO, DAA_INIT, xbus, xpd);
-#else
ret = run_initialize_registers(xpd);
if(ret < 0)
- goto out;
-#endif
- if(xpd->direction == TO_PSTN) {
- int i;
-
- // Hanghup all lines
- for_each_enabled_line(xpd, i) {
- init_waitqueue_head(&xpd->txstateq[i]);
- do_sethook(xpd, i, 0);
- }
- }
-out:
- if(ret < 0) {
- clean_proc(xbus, xpd);
- ERR("%s/%s: Failed initializing registers (%d)\n", xbus->busname, xpd->xpdname, ret);
- } else {
- DBG("done: %s/%s\n", xbus->busname, xpd->xpdname);
+ goto err;
+ // Hanghup all lines
+ for_each_line(xpd, i) {
+ init_waitqueue_head(&xpd->txstateq[i]);
+ do_sethook(xpd, i, 0);
}
+ DBG("done: %s/%s\n", xbus->busname, xpd->xpdname);
+ return 0;
+err:
+ clean_proc(xbus, xpd);
+ ERR("%s/%s: Failed initializing registers (%d)\n", xbus->busname, xpd->xpdname, ret);
return ret;
}
@@ -286,11 +275,43 @@ static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd)
return 0;
}
-static int FXO_card_zaptel_registration(xpd_t *xpd, bool on)
+static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on)
{
xbus_t *xbus;
struct FXO_priv_data *priv;
+ int i;
unsigned long flags;
+
+ BUG_ON(!xpd);
+ xbus = xpd->xbus;
+ BUG_ON(!xbus);
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
+ snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%d/%d: FXO", xbus->num, xpd->id);
+ for_each_line(xpd, i) {
+ struct zt_chan *cur_chan = &xpd->chans[i];
+
+ DBG("setting FXO channel %d\n", i);
+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%d/%d/%d", xbus->num, xpd->id, i);
+ cur_chan->chanpos = i + 1;
+ cur_chan->pvt = xpd;
+ cur_chan->sigcap = FXO_DEFAULT_SIGCAP;
+ }
+ spin_lock_irqsave(&xpd->lock, flags);
+ do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF);
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ for_each_line(xpd, i) {
+ do_led(xpd, i, LED_GREEN, LED_ON);
+ mdelay(50);
+ }
+ return 0;
+}
+
+static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on)
+{
+ xbus_t *xbus;
+ struct FXO_priv_data *priv;
int i;
BUG_ON(!xpd);
@@ -299,42 +320,48 @@ static int FXO_card_zaptel_registration(xpd_t *xpd, bool on)
priv = xpd->priv;
BUG_ON(!priv);
DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
- if(on) {
- for_each_line(xpd, i) {
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, i, LED_GREEN, LED_ON);
- spin_unlock_irqrestore(&xpd->lock, flags);
- mdelay(50);
- }
- for_each_line(xpd, i) {
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, i, LED_GREEN, LED_OFF);
- spin_unlock_irqrestore(&xpd->lock, flags);
- mdelay(50);
- }
- } else {
- for_each_line(xpd, i) {
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, i, LED_GREEN, LED_ON);
- spin_unlock_irqrestore(&xpd->lock, flags);
- mdelay(100);
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, i, LED_GREEN, LED_OFF);
- spin_unlock_irqrestore(&xpd->lock, flags);
- }
+ for_each_line(xpd, i) {
+ do_led(xpd, i, LED_GREEN, LED_OFF);
+ mdelay(50);
+ }
+ return 0;
+}
+
+#ifdef WITH_RBS
+int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
+{
+ struct FXO_priv_data *priv;
+
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
+ BUG_ON(xpd->direction != TO_PSTN);
+ /* XXX Enable hooksig for FXO XXX */
+ switch(txsig) {
+ case ZT_TXSIG_START:
+ break;
+ case ZT_TXSIG_OFFHOOK:
+ do_sethook(xpd, pos, 1);
+ break;
+ case ZT_TXSIG_ONHOOK:
+ do_sethook(xpd, pos, 0);
+ break;
+ default:
+ NOTICE("Can't set tx state to %s (%d)\n", txsig2str(txsig), txsig);
+ return -EINVAL;
}
return 0;
}
+#else
int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
{
- int ret = 0;
+ int ret = 0;
+ struct FXO_priv_data *priv;
DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, hookstate2str(hookstate));
switch(hookstate) {
- /* On-hook, off-hook: The PBX is playing a phone on an FXO line.
- * Can be ignored for an FXS line
- */
+ /* On-hook, off-hook: The PBX is playing a phone on an FXO line. */
case ZT_ONHOOK:
do_sethook(xpd, pos, 0);
break;
@@ -353,7 +380,7 @@ int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
WARN("No code yet\n");
break;
case ZT_RING:
- DBG("%s/%s/%d: (ringing[%d]=%d)\n", xbus->busname, xpd->xpdname, pos, pos, xpd->ringing[pos]);
+ DBG("%s/%s/%d: ZT_RING: %d\n", xbus->busname, xpd->xpdname, pos, xpd->ringing[pos]);
break;
case ZT_RINGOFF:
WARN("No code yet\n");
@@ -361,12 +388,13 @@ int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
}
return ret;
}
+#endif
static void poll_battery(xbus_t *xbus, xpd_t *xpd)
{
int i;
- for_each_enabled_line(xpd, i) {
+ for_each_line(xpd, i) {
CALL_PROTO(FXO, DAA_QUERY, xbus, xpd, i, DAA_VBAT_REGISTER);
}
}
@@ -374,23 +402,75 @@ static void poll_battery(xbus_t *xbus, xpd_t *xpd)
static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
{
- static int rate_limit = 0;
+ static unsigned rate_limit = 0;
struct FXO_priv_data *priv;
BUG_ON(!xpd);
priv = xpd->priv;
BUG_ON(!priv);
rate_limit++;
- if((rate_limit % 100) == 0) {
+ if(poll_battery_interval != 0 && (rate_limit % poll_battery_interval) == 0) {
poll_battery(xbus, xpd);
}
handle_fxo_leds(xpd);
return 0;
}
+/* FIXME: based on data from from wctdm.h */
+#include <wctdm.h>
+static const int echotune_reg[] = {30,45,46,47,58,49,50,51,52};
+union echotune {
+ /* "coeff 0" is acim */
+ unsigned char coeff[sizeof(echotune_reg)];
+ struct wctdm_echo_coefs wctdm_struct;
+};
+
+static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
+{
+ union echotune echoregs;
+ int i,ret;
+
+ BUG_ON(!xpd);
+ DBG("cmd: 0x%x, expecting: 0x%x, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos);
+ switch (cmd) {
+ case WCTDM_SET_ECHOTUNE:
+ DBG("-- Setting echo registers: \n");
+ /* first off: check if this span is fxs. If not: -EINVALID */
+ if (copy_from_user(&echoregs.wctdm_struct,
+ (struct wctdm_echo_coefs*)arg, sizeof(echoregs.wctdm_struct)))
+ return -EFAULT;
+
+ /* Set the ACIM register */
+ /* quick and dirty registers writing: */
+ for (i=0; i<sizeof(echotune_reg); i++) {
+ char buf[22];
+ xpp_line_t lines = BIT(pos);
+ sprintf(buf, "%02X %02X %02X %02X WD %2X %2X",
+ (lines & 0xFF),
+ ((lines >> 8) & 0xFF),
+ ((lines >> 16) & 0xFF),
+ ((lines >> 24) & 0xFF),
+ echotune_reg[i],echoregs.coeff[i]
+ );
+ /* FIXME: code duplicated from proc_xpd_register_write */
+ ret = process_slic_cmdline(xpd, buf);
+ if(ret < 0)
+ return ret;
+ mdelay(1);
+ }
+
+ DBG("-- Set echo registers successfully\n");
+
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
/*---------------- FXO: HOST COMMANDS -------------------------------------*/
-/* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on)
+static /* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on)
{
unsigned long flags;
int ret = 0;
@@ -398,19 +478,18 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xbus);
BUG_ON(!xpd);
- lines &= xpd->enabled_chans; // Ignore disabled channels
if(!lines) {
return 0;
}
DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off");
if(on) {
- for_each_enabled_line(xpd, i) {
+ for_each_line(xpd, i) {
spin_lock_irqsave(&xpd->lock, flags);
do_led(xpd, i, LED_GREEN, LED_ON);
spin_unlock_irqrestore(&xpd->lock, flags);
mdelay(20);
}
- for_each_enabled_line(xpd, i) {
+ for_each_line(xpd, i) {
spin_lock_irqsave(&xpd->lock, flags);
do_led(xpd, i, LED_GREEN, LED_OFF);
spin_unlock_irqrestore(&xpd->lock, flags);
@@ -420,32 +499,31 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
return ret;
}
-/* 0x0F */ HOSTCMD(FXO, CHAN_CID, xpp_line_t lines)
+static /* 0x0F */ HOSTCMD(FXO, CHAN_CID, int pos)
{
int ret = 0;
+ xpp_line_t lines = BIT(pos);
BUG_ON(!xbus);
BUG_ON(!xpd);
- lines &= xpd->enabled_chans; // Ignore disabled channels
if(!lines) {
return 0;
}
- DBG("Channel CID: 0x%04X\n", lines);
+ DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, pos);
return ret;
}
-/* 0x0F */ HOSTCMD(FXO, RING, int pos, bool on)
+static /* 0x0F */ HOSTCMD(FXO, RING, int pos, bool on)
{
int ret = 0;
xpacket_t *pack;
slic_cmd_t *sc;
- xpp_line_t mask = (1 << pos);
+ xpp_line_t mask = BIT(pos);
int len;
BUG_ON(!xbus);
BUG_ON(!xpd);
- mask &= xpd->enabled_chans; // Ignore disabled channels
if(!mask) {
return 0;
}
@@ -459,7 +537,7 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
return ret;
}
-/* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook)
+static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook)
{
int ret = 0;
xpacket_t *pack;
@@ -470,56 +548,26 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xbus);
BUG_ON(!xpd);
- value = (offhook) ? 0x01 : 0x00;
+ value = (offhook) ? 0x09 : 0x08;
// value |= BIT(3); /* Bit 3 is for CID */
DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (offhook)?"OFFHOOK":"ONHOOK");
spin_lock_irqsave(&xpd->lock, flags);
- if(!IS_SET(xpd->enabled_chans, pos))
- goto out;
XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
len = slic_cmd_direct_write(sc, BIT(pos), 0x05, value);
pack->datalen = len;
packet_send(xbus, pack);
do_led(xpd, pos, LED_GREEN, (offhook)?LED_ON:LED_OFF);
-out:
spin_unlock_irqrestore(&xpd->lock, flags);
return ret;
}
-/* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on)
+static /* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on)
{
return -ENOSYS;
}
-/* 0x0F */ HOSTCMD(FXO, DAA_INIT)
-{
- int ret = 0;
- xpacket_t *pack;
- slic_data_t *slic;
- struct slic_init_data *source;
- int i;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
- DBG("INITIALIZING DAA\n");
- for(i = 0; i < ARRAY_SIZE(slic_init_data); i++) {
- source = &slic_init_data[i];
- XPACKET_NEW(pack, xbus, FXO, DAA_INIT, xpd->id);
- RPACKET_FIELD(pack, FXO, DAA_INIT, lines) = source->lines;
-
- slic = &RPACKET_FIELD(pack, FXO, DAA_INIT, slic_data);
- slic->len = source->slic_data.len;
- memcpy(slic->data, source->slic_data.data, source->slic_data.len);
- pack->datalen = sizeof(xpp_line_t) + slic->len + 1;
-// dump_packet("DAA", pack, print_dbg);
- packet_send(xbus, pack);
- mdelay(1); // FIXME: check with Dima
- }
- return ret;
-}
-
-/* 0x0F */ HOSTCMD(FXO, DAA_QUERY, int pos, byte reg_num)
+static /* 0x0F */ HOSTCMD(FXO, DAA_QUERY, int pos, byte reg_num)
{
int ret = 0;
xpacket_t *pack;
@@ -588,22 +636,16 @@ HANDLER_DEF(FXO, DAA_REPLY)
if(abs(info->data_low) < BAT_THRESHOLD) {
priv->battery &= ~lines;
- // DBG("BATTERY OFF (%04X) = %d\n", lines, info->data_low);
+ // DBG("%s/%s: BATTERY OFF (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
} else {
priv->battery |= lines;
- // DBG("BATTERY ON (%04X) = %d\n", lines, info->data_low);
+ // DBG("%s/%s: BATTERY ON (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
}
changed_lines = last_batt_on ^ priv->battery;
for_each_line(xpd, i) {
- if(!IS_SET(changed_lines, i) || IS_SET(xpd->hookstate, i))
- continue;
-#if 0
- /* FIXME: We don't want to affect the whole span */
- if(IS_SET(priv->battery, i))
- update_xpd_status(xpd, ZT_ALARM_NONE);
- else
- update_xpd_status(xpd, ZT_ALARM_RED);
-#endif
+ if(IS_SET(changed_lines, i)) {
+ update_line_status(xpd, i, IS_SET(priv->battery, i));
+ }
}
}
#if 0
@@ -635,9 +677,15 @@ xproto_table_t PROTO_TABLE(FXO) = {
.card_new = FXO_card_new,
.card_init = FXO_card_init,
.card_remove = FXO_card_remove,
- .card_zaptel_registration = FXO_card_zaptel_registration,
+ .card_zaptel_preregistration = FXO_card_zaptel_preregistration,
+ .card_zaptel_postregistration = FXO_card_zaptel_postregistration,
+#ifdef WITH_RBS
+ .card_hooksig = FXO_card_hooksig,
+#else
.card_sethook = FXO_card_sethook,
+#endif
.card_tick = FXO_card_tick,
+ .card_ioctl = FXO_card_ioctl,
.RING = XPROTO_CALLER(FXO, RING),
.SETHOOK = XPROTO_CALLER(FXO, SETHOOK),
@@ -676,7 +724,8 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
struct FXO_priv_data *priv;
int i;
- BUG_ON(!xpd);
+ if(!xpd)
+ return -ENODEV;
spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv;
BUG_ON(!priv);
@@ -830,9 +879,8 @@ static int process_slic_cmdline(xpd_t *xpd, char *cmdline)
len = parse_slic_cmd(p, &sc, &priv->requested_reply);
if(len < 0)
return len;
- sc.lines &= xpd->enabled_chans; // Ignore disabled channels
if(!sc.lines) {
- NOTICE("%s: no enabled channels are marked. Skip.\n", __FUNCTION__);
+ NOTICE("%s: no channels are marked. Skip.\n", __FUNCTION__);
return 0;
}
dump_slic_cmd("WRITE_DAA", &sc);
@@ -852,7 +900,8 @@ static int proc_xpd_slic_write(struct file *file, const char __user *buffer, uns
int i;
int ret;
- BUG_ON(!xpd);
+ if(!xpd)
+ return -ENODEV;
for(i = 0; i < count; /* noop */) {
for(p = buf; p < buf + LINE_LEN; p++) { /* read a line */
if(i >= count)