[zaptel-commits] trunk r1204 - in /trunk/xpp: ./ utils/
zaptel-commits at lists.digium.com
zaptel-commits at lists.digium.com
Thu Jul 6 06:47:05 MST 2006
Author: tzafrir
Date: Thu Jul 6 08:47:05 2006
New Revision: 1204
URL: http://svn.digium.com/view/zaptel?rev=1204&view=rev
Log:
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.
Removed:
trunk/xpp/cmd2inc
Modified:
trunk/xpp/ (props changed)
trunk/xpp/Makefile
trunk/xpp/README.Astribank
trunk/xpp/card_fxo.c
trunk/xpp/card_fxo.h
trunk/xpp/card_fxs.c
trunk/xpp/card_fxs.h
trunk/xpp/card_global.c
trunk/xpp/card_global.h
trunk/xpp/init_data_3_19.cmd
trunk/xpp/init_data_3_20.cmd
trunk/xpp/init_data_4_20.cmd
trunk/xpp/slic.h
trunk/xpp/utils/FPGA_FXS.hex
trunk/xpp/utils/Makefile
trunk/xpp/utils/genzaptelconf
trunk/xpp/utils/hexfile.c
trunk/xpp/utils/xpp_fxloader
trunk/xpp/xbus-core.c
trunk/xpp/xbus-core.h
trunk/xpp/xdefs.h
trunk/xpp/xpd.h
trunk/xpp/xpp_usb.c
trunk/xpp/xpp_zap.c
trunk/xpp/xpp_zap.h
trunk/xpp/xproto.c
trunk/xpp/xproto.h
trunk/xpp/zap_debug.c
trunk/xpp/zap_debug.h
Propchange: trunk/xpp/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Jul 6 08:47:05 2006
@@ -3,4 +3,3 @@
*.o.cmd
*.ko.cmd
*.mod.c
-init_data_*.inc
Modified: trunk/xpp/Makefile
URL: http://svn.digium.com/view/zaptel/trunk/xpp/Makefile?rev=1204&r1=1203&r2=1204&view=diff
==============================================================================
--- trunk/xpp/Makefile (original)
+++ trunk/xpp/Makefile Thu Jul 6 08:47:05 2006
@@ -1,30 +1,9 @@
-EXTRA_CFLAGS = -I$(SUBDIRS) -DDEBUG -DWITH_ECHO_SUPPRESSION # -DHARD_CODED_INIT # -DOLD_CARD # -DWITH_RBS
+EXTRA_CFLAGS = -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION -DWITH_RBS -DSTANDALONE_ZAPATA
-obj-m = xpp.o xpd_fxs.o xpd_fxo.o xpp_usb.o
+obj-m = xpp.o xpp_usb.o xpd_fxs.o xpd_fxo.o
xpp-y += xbus-core.o xpp_zap.o xproto.o card_global.o
xpd_fxs-y += card_fxs.o slic.o
xpd_fxo-y += card_fxo.o slic.o
-GENERATE_INIT_DATA := 1
-INIT_DATA = init_data_3_19.inc init_data_3_20.inc init_data_4_19.inc init_data_4_20.inc
-clean-files := $(INIT_DATA)
-
-cmd2inc=$(src)/cmd2inc
-
-define run_cmd2inc
-if [ ! -x $(cmd2inc) ]; then chmod +x $(cmd2inc); fi
-$(cmd2inc) $^ $@
-endef
-
-ifeq ($(GENERATE_INIT_DATA),1)
-
-$(obj)/%.inc: $(src)/%.cmd
- @echo "Generating $@"
- @$(run_cmd2inc)
-
-init_data: $(INIT_DATA)
-
-$(obj)/card_fxs.o: $(obj)/init_data_3_19.inc $(obj)/init_data_3_20.inc
-$(obj)/card_fxo.o: $(obj)/init_data_4_19.inc $(obj)/init_data_4_20.inc
-
-endif
+ctags:
+ ctags *.[ch]
Modified: trunk/xpp/README.Astribank
URL: http://svn.digium.com/view/zaptel/trunk/xpp/README.Astribank?rev=1204&r1=1203&r2=1204&view=diff
==============================================================================
--- trunk/xpp/README.Astribank (original)
+++ trunk/xpp/README.Astribank Thu Jul 6 08:47:05 2006
@@ -35,6 +35,13 @@
Installation:
""""""""""""
+apart from the standard 'make install' in the zaptel directory,
+run:
+
+ make -C xpp/utils install
+
+Alternatively, do the following manually:
+
All firmware files should be copied to a new directory:
/usr/share/zaptel/
@@ -44,6 +51,14 @@
In addition, the file xpp/xpp_modprobe contains optional modprobe settings.
It may be copied verbatim into /etc/modprobe.conf or (better) copied to
/etc/modprobe.d/ .
+
+
+Note that loading through udev is not yet provided. Run
+
+ /etc/hotplug/usb/xpp_fxloader xppdetect
+
+to load firmware.
+
Loading Firmware Details:
""""""""""""""""""""""""
Modified: trunk/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxo.c?rev=1204&r1=1203&r2=1204&view=diff
==============================================================================
--- trunk/xpp/card_fxo.c (original)
+++ trunk/xpp/card_fxo.c Thu Jul 6 08:47:05 2006
@@ -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 @@
/*---------------- 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 @@
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 @@
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 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 @@
{
struct FXO_priv_data *priv;
int ret = 0;
+ int i;
BUG_ON(!xpd);
priv = xpd->priv;
@@ -237,41 +233,34 @@
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,12 +275,12 @@
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;
- int i;
BUG_ON(!xpd);
xbus = xpd->xbus;
@@ -299,42 +288,80 @@
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);
- }
- }
- return 0;
-}
-
+ 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);
+ xbus = xpd->xbus;
+ BUG_ON(!xbus);
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
+ 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 @@
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 @@
}
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
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)
Modified: trunk/xpp/card_fxo.h
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxo.h?rev=1204&r1=1203&r2=1204&view=diff
==============================================================================
--- trunk/xpp/card_fxo.h (original)
+++ trunk/xpp/card_fxo.h Thu Jul 6 08:47:05 2006
@@ -51,10 +51,6 @@
xpp_line_t lines;
slic_reply_t info;
);
-DEF_RPACKET_DATA(FXO, DAA_INIT,
- xpp_line_t lines;
- slic_data_t slic_data;
- );
DEF_RPACKET_DATA(FXO, DAA_WRITE,
slic_cmd_t slic_cmd;
);
Modified: trunk/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxs.c?rev=1204&r1=1203&r2=1204&view=diff
==============================================================================
--- trunk/xpp/card_fxs.c (original)
+++ trunk/xpp/card_fxs.c Thu Jul 6 08:47:05 2006
@@ -34,15 +34,21 @@
static const char rcsid[] = "$Id$";
DEF_PARM(int, print_dbg, 0, "Print DBG statements"); /* must be before zap_debug.h */
+DEF_PARM(bool, poll_digital_inputs, 1, "Poll Digital Inputs"); /* must be before zap_debug.h */
+
+/* Signaling is opposite (fxo signalling for fxs card) */
+#if 1
+#define FXS_DEFAULT_SIGCAP (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS)
+#else
+#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_BITS(b) ((1U << (b)) - 1)
-
-#define MASK_DIGI_OUT (MASK_BITS(LINES_DIGI_OUT) << LINES_REGULAR)
-#define MASK_DIGI_INP (MASK_BITS(LINES_DIGI_INP) << (LINES_REGULAR + LINES_DIGI_OUT))
+#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,
@@ -52,14 +58,27 @@
#define NUM_LEDS 2
+static int SLIC_DIRECT_REQUEST(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, byte reg, byte dL)
+{
+ xpacket_t *pack;
+ slic_cmd_t *sc;
+ int len;
+
+ XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
+ sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
+ len = slic_cmd_direct_write(sc, lines, reg, dL);
+ pack->datalen = len;
+ packet_send(xbus, pack);
+ return 0;
+}
+
/*---------------- FXS Protocol Commands ----------------------------------*/
static /* 0x0F */ DECLARE_CMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on);
-static /* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, xpp_line_t lines);
+static /* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, int pos);
static /* 0x0F */ DECLARE_CMD(FXS, RING, int pos, bool on);
static /* 0x0F */ DECLARE_CMD(FXS, SETHOOK, int pos, bool offhook);
static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on);
-static /* 0x0F */ DECLARE_CMD(FXS, SLIC_INIT);
static /* 0x0F */ DECLARE_CMD(FXS, SLIC_QUERY, int pos, byte reg_num);
static bool fxs_packet_is_valid(xpacket_t *pack);
@@ -67,26 +86,6 @@
static int proc_fxs_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_3_19.inc"
-#else
-#include "init_data_3_20.inc"
-#endif
-};
-#undef S_
#define PROC_SLIC_FNAME "slics"
#define PROC_FXS_INFO_FNAME "fxs_info"
@@ -111,7 +110,6 @@
BUG_ON(!xbus);
BUG_ON(!xpd);
- lines &= xpd->enabled_chans; // Ignore disabled channels
if(!lines) {
return 0;
}
@@ -132,8 +130,8 @@
}
#define IS_BLINKING(priv,pos,color) ((priv)->blinking[color][pos] != 0)
-#define DO_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val))
-#define DO_LED(priv,pos,color,val) ((val)?BIT_SET((priv)->ledcontrol[color],(pos)):BIT_CLR((priv)->ledcontrol[color],(pos)))
+#define MARK_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val))
+#define MARK_LED(priv,pos,color,val) ((val)?BIT_SET((priv)->ledcontrol[color],(pos)):BIT_CLR((priv)->ledcontrol[color],(pos)))
/*
* LED and RELAY control is done via SLIC register 0x06:
@@ -195,7 +193,7 @@
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");
value = BIT(2) | BIT(3);
@@ -222,11 +220,11 @@
struct FXS_priv_data *priv;
BUG_ON(!xpd);
- priv = xpd->priv;
spin_lock_irqsave(&xpd->lock, flags);
+ priv = xpd->priv;
timer_count = xpd->timer_count;
for(color = 0; color < ARRAY_SIZE(colors); color++) {
- 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)) { // Blinking
@@ -282,6 +280,7 @@
#ifdef CONFIG_PROC_FS
if(priv->xpd_slic) {
DBG("Removing xpd SLIC file %s/%s\n", xbus->busname, xpd->xpdname);
+ priv->xpd_slic->data = NULL;
remove_proc_entry(PROC_SLIC_FNAME, xpd->proc_xpd_dir);
}
if(priv->fxs_info) {
@@ -304,31 +303,45 @@
if(!priv->fxs_info) {
ERR("Failed to create proc '%s' for %s/%s\n", PROC_FXS_INFO_FNAME, xbus->busname, xpd->xpdname);
ret = -ENOENT;
- goto out;
- }
+ goto err;
+ }
+ priv->fxs_info->owner = THIS_MODULE;
DBG("Creating SLICs file for %s/%s\n", xbus->busname, xpd->xpdname);
priv->xpd_slic = create_proc_entry(PROC_SLIC_FNAME, 0644, xpd->proc_xpd_dir);
if(!priv->xpd_slic) {
ERR("Failed to create proc file for SLICs of %s/%s\n", xbus->busname, xpd->xpdname);
ret = -ENOENT;
- goto out;
- }
+ 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(FXS, SLIC_INIT, xbus, xpd);
+ ret = run_initialize_registers(xpd);
+ if(ret < 0)
+ goto err;
+ /*
+ * Setup ring timers
+ */
+#ifdef WITH_RBS
+ /* Software controled ringing (for CID) */
+ ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x00); /* Ringing Oscilator Control */
#else
- ret = run_initialize_registers(xpd);
-#endif
-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);
- }
+ /* Hardware controled ringing (no CID) */
+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x30, 0x80); /* Active timer low byte */
+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x31, 0x3E); /* Active timer high byte */
+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x32, 0x80); /* Inactive timer low byte */
+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x33, 0x3E); /* Inactive timer high byte */
+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x18); /* Ringing Oscilator Control */
+#endif
+ if(ret < 0)
+ goto err;
+ DBG("%s/%s: done\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;
}
@@ -343,46 +356,139 @@
return 0;
}
-static int FXS_card_zaptel_registration(xpd_t *xpd, bool on)
+static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on)
{
xbus_t *xbus;
struct FXS_priv_data *priv;
+ int i;
unsigned long flags;
- int i;
+ const enum fxs_leds color = (on) ? LED_GREEN : LED_RED;
BUG_ON(!xpd);
xbus = xpd->xbus;
- priv = xpd->priv;
BUG_ON(!xbus);
- DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on)?"on":"off");
- if(on) {
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF);
- spin_unlock_irqrestore(&xpd->lock, flags);
- for_each_enabled_line(xpd, i) {
- DO_LED(priv,i,LED_GREEN,LED_ON);
- mdelay(50);
+ 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: FXS", xbus->num, xpd->id);
+ for_each_line(xpd, i) {
+ struct zt_chan *cur_chan = &xpd->chans[i];
+
+ DBG("setting FXS channel %d\n", i);
+ if(IS_SET(xpd->digital_outputs, i)) {
+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%d/%d/%d", xbus->num, xpd->id, i);
+ } else if(IS_SET(xpd->digital_inputs, i)) {
+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%d/%d/%d", xbus->num, xpd->id, i);
+ } else {
+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%d/%d/%d", xbus->num, xpd->id, i);
}
- for_each_enabled_line(xpd, i) {
- DO_LED(priv,i,LED_GREEN,LED_OFF);
- mdelay(50);
- }
- } else {
- spin_lock_irqsave(&xpd->lock, flags);
- do_led(xpd, ALL_LINES, LED_RED, LED_OFF);
- spin_unlock_irqrestore(&xpd->lock, flags);
- for_each_enabled_line(xpd, i) {
- DO_LED(priv,i,LED_RED,LED_ON);
- mdelay(50);
- }
- for_each_enabled_line(xpd, i) {
- DO_LED(priv,i,LED_RED,LED_OFF);
- mdelay(50);
- }
+ cur_chan->chanpos = i + 1;
+ cur_chan->pvt = xpd;
+ cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
+ }
+ spin_lock_irqsave(&xpd->lock, flags);
+ do_led(xpd, ALL_LINES, color, LED_OFF);
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ for_each_line(xpd, i) {
+ MARK_LED(priv, i, color, LED_ON);
+ mdelay(50);
}
return 0;
}
+static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on)
+{
+ xbus_t *xbus;
+ struct FXS_priv_data *priv;
+ int i;
+ const enum fxs_leds color = (on) ? LED_GREEN : LED_RED;
+
+ 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);
+ for_each_line(xpd, i) {
+ MARK_LED(priv, i, color, LED_OFF);
+ mdelay(50);
+ }
+ return 0;
+}
+
+#ifdef WITH_RBS
+int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
+{
+ int ret = 0;
+
+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
+ BUG_ON(xpd->direction != TO_PHONE);
+ if (IS_SET(xpd->digital_inputs, pos)) {
+ DBG("Ignoring signal sent to digital input line\n");
+ return 0;
+ }
+ switch(txsig) {
+ case ZT_TXSIG_ONHOOK:
+ xpd->ringing[pos] = 0;
+ BIT_CLR(xpd->cid_on, pos);
+ if(IS_SET(xpd->digital_outputs, pos)) {
+ DBG("%s/%s/%d: digital output OFF\n", xbus->busname, xpd->xpdname, pos);
+ ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
+ return ret;
+ }
+ ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off
+#if 0
+ switch(chan->sig) {
+ case ZT_SIG_EM:
+ case ZT_SIG_FXOKS:
+ case ZT_SIG_FXOLS:
+ xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
+ break;
+ case ZT_SIG_FXOGS:
+ xpd->lasttxhook[pos] = FXS_LINE_TIPOPEN;
+ break;
+ }
+#endif
+ break;
+ case ZT_TXSIG_OFFHOOK:
+ if(xpd->ringing[pos]) {
+ BIT_SET(xpd->cid_on, pos);
+ ret = CALL_XMETHOD(CHAN_CID, xpd->xbus, xpd, pos); // CALLER ID
+ }
+ xpd->ringing[pos] = 0;
+#if 0
+ switch(chan->sig) {
+ case ZT_SIG_EM:
+ xpd->lasttxhook[pos] = FXS_LINE_REV_ACTIVE;
+ break;
+ default:
+ xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
+ break;
+ }
+#endif
+ break;
+ case ZT_TXSIG_START:
+ xpd->lasttxhook[pos] = FXS_LINE_RING;
+ xpd->ringing[pos] = 1;
+ BIT_CLR(xpd->cid_on, pos);
+ if(IS_SET(xpd->digital_outputs, pos)) {
+ DBG("%s/%s/%d: %s digital output ON\n", xbus->busname, xpd->xpdname, pos, 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:
+ xpd->lasttxhook[pos] = FXS_LINE_DISABLED;
+ break;
+ default:
+ NOTICE("%s: Can't set tx state to %s (%d)\n", __FUNCTION__, txsig2str(txsig), txsig);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+#else
int FXS_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
{
int ret = 0;
@@ -417,7 +523,7 @@
DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
// Fall through
case ZT_OFFHOOK:
- DBG("%s/%s/%d: ignoring (PHONE)\n", xbus->busname, xpd->xpdname, pos);
+ DBG("%s/%s/%d: ZT_OFFHOOK (ignoring for PHONES)\n", xbus->busname, xpd->xpdname, pos);
break;
case ZT_WINK:
WARN("No code yet\n");
@@ -426,7 +532,7 @@
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]);
if(IS_SET(xpd->digital_inputs, pos)) {
NOTICE("%s: Trying to RING a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
return -EINVAL;
@@ -448,6 +554,7 @@
}
return ret;
}
+#endif
/*
* INPUT polling is done via SLIC register 0x06 (same as LEDS):
@@ -463,6 +570,7 @@
{
int i;
+ BUG_ON(xpd->id != 0); // Only unit #0 has digital inputs
for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
int pos = input_channels[i];
@@ -478,9 +586,13 @@
BUG_ON(!xpd);
priv = xpd->priv;
BUG_ON(!priv);
- if((rate_limit++ % 1000) == 0) {
- poll_inputs(xbus, xpd);
- }
+#if POLL_DIGITAL_INPUTS
+ if(poll_digital_inputs && xpd->id == 0) {
+ if((rate_limit++ % 1000) == 0) {
+ poll_inputs(xbus, xpd);
+ }
+ }
+#endif
handle_fxs_leds(xpd);
return 0;
}
@@ -499,11 +611,14 @@
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");
+ // Make sure we use normal (low battery) power
+ for_each_line(xpd, i)
+ if (BIT_SET(lines,i))
+ do_chan_power(xbus, xpd, BIT(i), 0);
XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
len = slic_cmd_direct_write(sc, lines, 0x40, value);
@@ -522,20 +637,21 @@
return ret;
}
-static /* 0x0F */ HOSTCMD(FXS, CHAN_CID, xpp_line_t lines)
+static /* 0x0F */ HOSTCMD(FXS, CHAN_CID, int pos)
{
int ret = 0;
xpacket_t *pack;
slic_cmd_t *sc;
int i;
+ 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);
+ //do_chan_power(xbus, xpd, BIT(pos), 0); // Low battery for normal (non-ring) operation
XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
pack->datalen = slic_cmd_direct_write(sc, lines, 0x40, FXS_LINE_CID);
@@ -552,14 +668,13 @@
struct FXS_priv_data *priv;
xpacket_t *pack;
slic_cmd_t *sc;
- xpp_line_t mask = (1 << pos);
+ xpp_line_t mask = BIT(pos);
int len;
enum fxs_state value = (on) ? 0x04 : 0x01;
BUG_ON(!xbus);
BUG_ON(!xpd);
priv = xpd->priv;
- mask &= xpd->enabled_chans; // Ignore disabled channels
if(!mask) {
return 0;
}
@@ -573,10 +688,10 @@
packet_send(xbus, pack);
if(on) {
- DO_BLINK(priv,pos,LED_GREEN,LED_BLINK);
+ MARK_BLINK(priv,pos,LED_GREEN,LED_BLINK);
} else {
if(IS_BLINKING(priv, pos, LED_GREEN))
- DO_BLINK(priv,pos,LED_GREEN,0);
+ MARK_BLINK(priv,pos,LED_GREEN,0);
}
return ret;
}
@@ -617,33 +732,6 @@
return ret;
}
-static /* 0x0F */ HOSTCMD(FXS, SLIC_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 SLIC\n");
- for(i = 0; i < ARRAY_SIZE(slic_init_data); i++) {
- source = &slic_init_data[i];
- XPACKET_NEW(pack, xbus, FXS, SLIC_INIT, xpd->id);
- RPACKET_FIELD(pack, FXS, SLIC_INIT, lines) = source->lines;
-
- slic = &RPACKET_FIELD(pack, FXS, SLIC_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("SLIC", pack, print_dbg);
- packet_send(xbus, pack);
- mdelay(1); // FIXME: check with Dima
- }
- return ret;
-}
-
static /* 0x0F */ HOSTCMD(FXS, SLIC_QUERY, int pos, byte reg_num)
{
int ret = 0;
@@ -683,7 +771,7 @@
}
#if 0
Is this needed?
- for_each_enabled_line(xpd, i) {
+ for_each_line(xpd, i) {
if(IS_SET(sig_toggles, i))
do_chan_power(xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!)
}
@@ -695,15 +783,15 @@
struct zt_chan *chan = &xpd->span.chans[i];
xpd->ringing[i] = 0; // No more ringing...
- DO_BLINK(priv,i,LED_GREEN,0);
+ MARK_BLINK(priv,i,LED_GREEN,0);
if(IS_SET(sig_status, i)) {
DBG("OFFHOOK: channo=%d\n", chan->channo);
- DO_LED(priv,i,LED_GREEN,LED_ON);
+ MARK_LED(priv,i,LED_GREEN,LED_ON);
BIT_SET(xpd->hookstate, i);
zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
} else {
DBG("ONHOOK channo=%d\n", chan->channo);
- DO_LED(priv,i,LED_GREEN,LED_OFF);
+ MARK_LED(priv,i,LED_GREEN,LED_OFF);
BIT_CLR(xpd->hookstate, i);
zt_hooksig(chan, ZT_RXSIG_ONHOOK);
}
@@ -770,7 +858,6 @@
return 0;
}
-
xproto_table_t PROTO_TABLE(FXS) = {
.owner = THIS_MODULE,
.entries = {
@@ -784,8 +871,13 @@
.card_new = FXS_card_new,
.card_init = FXS_card_init,
.card_remove = FXS_card_remove,
- .card_zaptel_registration = FXS_card_zaptel_registration,
+ .card_zaptel_preregistration = FXS_card_zaptel_preregistration,
+ .card_zaptel_postregistration = FXS_card_zaptel_postregistration,
+#ifdef WITH_RBS
+ .card_hooksig = FXS_card_hooksig,
+#else
.card_sethook = FXS_card_sethook,
+#endif
.card_tick = FXS_card_tick,
.RING = XPROTO_CALLER(FXS, RING),
@@ -826,7 +918,8 @@
int i;
int led;
- BUG_ON(!xpd);
+ if(!xpd)
+ return -ENODEV;
spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv;
BUG_ON(!priv);
@@ -984,9 +1077,8 @@
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_SLIC", &sc);
@@ -1006,7 +1098,8 @@
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)
@@ -1032,6 +1125,12 @@
int __init card_fxs_startup(void)
{
INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
[... 3312 lines stripped ...]
More information about the zaptel-commits
mailing list