[zaptel-commits] trunk r1021 - in /trunk/xpp: ./ utils/

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Wed May 3 16:06:02 MST 2006


Author: tzafrir
Date: Wed May  3 18:06:02 2006
New Revision: 1021

URL: http://svn.digium.com/view/zaptel?rev=1021&view=rev
Log:
xpp driver release 1.1.0 (first part of commit)
* FPGA firmware now loaded from PC (for newer models)
* Driver for the FXO module
* Moved most userspace files to the subdirectory utils (see also next commit)
* Explicit license for firmware files
* Optionally avoid auto-registration
* Initializations parameters to chips given from userspace
* And did I mention bugfixes?

Added:
    trunk/xpp/LICENSE.firmware   (with props)
    trunk/xpp/card_fxo.c   (with props)
    trunk/xpp/card_fxo.h   (with props)
    trunk/xpp/cmd2inc   (with props)
    trunk/xpp/init_data_3_19.cmd   (with props)
    trunk/xpp/init_data_3_20.cmd   (with props)
    trunk/xpp/init_data_4_19.cmd   (with props)
    trunk/xpp/init_data_4_20.cmd   (with props)
    trunk/xpp/initialize_registers   (with props)
    trunk/xpp/utils/
    trunk/xpp/utils/xpp_fxloader
      - copied unchanged from r1020, trunk/xpp/xpp_fxloader
    trunk/xpp/utils/xpp_fxloader.usermap
      - copied unchanged from r1020, trunk/xpp/xpp_fxloader.usermap
    trunk/xpp/utils/xpp_modprobe
      - copied unchanged from r1020, trunk/xpp/xpp_modprobe
    trunk/xpp/xbus-core.c   (with props)
    trunk/xpp/xbus-core.h   (with props)
Removed:
    trunk/xpp/FPGA_XPD.hex
    trunk/xpp/cards.c
    trunk/xpp/cards.h
    trunk/xpp/gen_slic_init
    trunk/xpp/slic_init.inc
    trunk/xpp/sync.sh
    trunk/xpp/xpp_fxloader
    trunk/xpp/xpp_fxloader.usermap
    trunk/xpp/xpp_modprobe
    trunk/xpp/xpp_proto.c
    trunk/xpp/xpp_proto.h
Modified:
    trunk/xpp/Makefile
    trunk/xpp/README.Astribank
    trunk/xpp/card_fxs.c
    trunk/xpp/card_fxs.h
    trunk/xpp/card_global.c
    trunk/xpp/card_global.h
    trunk/xpp/slic.c
    trunk/xpp/slic.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

Added: trunk/xpp/LICENSE.firmware
URL: http://svn.digium.com/view/zaptel/trunk/xpp/LICENSE.firmware?rev=1021&view=auto
==============================================================================
--- trunk/xpp/LICENSE.firmware (added)
+++ trunk/xpp/LICENSE.firmware Wed May  3 18:06:02 2006
@@ -1,0 +1,37 @@
+The firmware files (*.hex) in this directory are software for the 
+Astribank itself and not intended to run on the Linux system itself. 
+They are generally freely distriributable (see exact terms below).
+
+/****************************************************************************/
+/*  Copyright (c) 2004-2006 Xorcom Inc. All Rights Reserved.                */
+/*  Redistribution and use of the microcode software ( Firmware ) is        */
+/*  permitted provided that the following conditions are met:               */
+/*                                                                          */
+/*          1. Firmware is redistributed verbatim without any modification; */
+/*          2. Any reproduction of Firmware must contain the above          */
+/*             copyright notice, this list of conditions and the below      */
+/*             disclaimer in the documentation and/or other materials       */
+/*             provided with the distribution; and                          */
+/*          3. The name of Xorcom may not be used to endorse or promote     */
+/*             products derived from this Firmware without specific prior   */
+/*             written consent.                                             */
+/*                                                                          */
+/*  Disclaimer: Xorcom provides this firmware "as is" with no warranties    */
+/*  or indemnities whatsoever. Xorcom expressly disclaims any express,      */
+/*  statutory or implied warranties, including, but not limited to, the     */
+/*  implied warranties of merchantability, fitness for a particular         */
+/*  purpose and non-infringement. In no event shall Xorcom be liable for    */
+/*  any direct, indirect, incidental, special, exemplary, or consequential  */
+/*  damages (including, but not limited to, procurement of substitute       */
+/*  goods or services; loss of use, data, or profits; or business           */
+/*  interruption) however caused and on any theory of liability, whether    */
+/*  in contract, strict liability, or tort (including negligence or         */
+/*  otherwise) arising in any way out of the use of this firmware, even     */
+/*  if advised of the possibility of such damage. User acknowledges and     */
+/*  agrees that the purchase or use of the firmware will not create or      */
+/*  give grounds for a license by implication, estoppel, or otherwise in    */
+/*  any intellectual property rights (patent, copyright, trade secret,      */
+/*  mask work, or other proprietary right) embodied in any other Xorcom     */
+/*  hardware or firmware either solely or in combination with the firmware. */
+/****************************************************************************/
+

Propchange: trunk/xpp/LICENSE.firmware
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/xpp/LICENSE.firmware
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: trunk/xpp/LICENSE.firmware
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: trunk/xpp/Makefile
URL: http://svn.digium.com/view/zaptel/trunk/xpp/Makefile?rev=1021&r1=1020&r2=1021&view=diff
==============================================================================
--- trunk/xpp/Makefile (original)
+++ trunk/xpp/Makefile Wed May  3 18:06:02 2006
@@ -1,5 +1,30 @@
-EXTRA_CFLAGS	= -I$(src)/.. -DSOFT_SIMULATOR=0
+EXTRA_CFLAGS	= -I$(SUBDIRS) -DDEBUG # -DHARD_CODED_INIT # -DOLD_CARD # -DWITH_RBS
 
-obj-m		= xpd_fxs.o xpp.o xpp_usb.o
-xpp-y		+= xproto.o card_global.o xpp_zap.o zap_debug.o
-xpd_fxs-y	+= card_fxs.o slic.o
+obj-m			= xpp.o xpd_fxs.o xpd_fxo.o xpp_usb.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

Modified: trunk/xpp/README.Astribank
URL: http://svn.digium.com/view/zaptel/trunk/xpp/README.Astribank?rev=1021&r1=1020&r2=1021&view=diff
==============================================================================
--- trunk/xpp/README.Astribank (original)
+++ trunk/xpp/README.Astribank Wed May  3 18:06:02 2006
@@ -5,15 +5,48 @@
 Building and Installation:
 """""""""""""""""""""""""
 Building and installation is basically like the normal procedure of 
-installing Zaptel. Follow the rest of the documentation here.
+installing Zaptel with some additions.
 
-In addition, the file xpp/xpp_modprobe contains modprobe settings. It
-should be copied verbatim into /etc/modprobe.conf or (better) copied to
-/etc/modprobe.d/ . If you fail to do so, xpp_usb.ko will fail to load
-xpd_fxs.ko and as a result will not detect your Astribank.
+Building drivers:
+""""""""""""""""
+From the toplevel zaptel directory run a command similar to (I used line
+continuation to prevent line wrapping):
 
-Loading Firmware
-""""""""""""""""
+ $ make \
+        KSRC=/usr/src/kernel-headers-2.6.12-1-386       \
+        KVERS=2.6.12-1-386                              \
+        XPPMOD=xpp/                                     \
+        EC_TYPE=CAN_KB1
+
+ - The KSRC= points to a configured kernel source tree.
+ - The KVERS= should match the relevant tree version.
+ - The XPPMOD= instructs the Zaptel Makefile to descend into the xpp/
+   subdirectory. The slash (/) in the end is mandatory.
+ - The EC_TYPE= select the echo canceler.
+
+Building firmware utilities:
+"""""""""""""""""""""""""""
+Then you should compile the firmware loading utilities. Simply go
+to the zaptel/xpp/utils and run make.
+
+Those who don't use prepackaged drivers should make sure they also
+install the (externally available) fxload utility.
+
+Installation:
+""""""""""""
+
+All firmware files should be copied to a new directory:
+  /usr/share/zaptel/
+
+The xpp_fxloader and xpp_fxloader.usbmap should be copied to:
+ /etc/hotplug/usb/
+
+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/ .
+
+Loading Firmware Details:
+""""""""""""""""""""""""
 The Astribank needs a firmware loaded into it. Without the firmware, 
 the device will appear in lsusb with vendor ID 04b4 and product ID 8613
 The firmware is provided in the Intel hex format. It can be loaded using 
@@ -21,12 +54,11 @@
 'hotplug-utils' . 
 
 To load the firmware automatically using the standard hotplug script, 
-place xpp/xpp_fxloader and xpp/xpp_fxloader.usermap in /etc/hotplug/usb
-and place xpp/FPGA_XPD.hex in /etc/xortel (or edit xpp_fxloader
-accordingly). 
+place xpp/utils/xpp_fxloader and xpp/utils/xpp_fxloader.usermap in 
+/etc/hotplug/usb and place xpp/utils/*.hex in /usr/share/zaptel .
 
 Alternatively, xpp_fxloader when given the parameter 'xppdetect' will load 
-the firmware from /etc/xortel/FPGA_XPD.hex . You can use it to load the 
+the firmwares from /usr/share/zaptel/ . You can use it to load the 
 firmware manually.
 
 You should then get in lsusb the vendor ID e4e4 and device ID 2121
@@ -128,6 +160,25 @@
 (There are a bunch of other status files under /proc/xpp/ )
 
 
+Useful Module Parameters:
+""""""""""""""""""""""""
+zap_autoreg: (xpp)
+Register spans automatically (1) or not (0). Default: 1. 
+Unsetting this could be useful if you have several Astribanks and you 
+want to set their registration order manually using zt_registration in 
+the /proc interface.
+
+initialize_registers (xpd_fxs)
+The script that is run to initilize registers of the device. The default is 
+/usr/share/zaptel/initialize_registers . 
+Setting this value could be useful if that location is inconvient for you.
+
+print_dbg: (all modules)
+It will make the driver print tons of debugging messages. Can be sometime 
+even handy, but overly-verbose in the case of xpp_usb. Can be safely 
+set/unset at run-time using /sys/modules .
+
+
 
 BTW: XPP here does not stand for X Printing Panel, XML Pull Parser, 
 X-Windows Phase Plane or XML Professional Publisher. It is simply the 

Added: trunk/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxo.c?rev=1021&view=auto
==============================================================================
--- trunk/xpp/card_fxo.c (added)
+++ trunk/xpp/card_fxo.c Wed May  3 18:06:02 2006
@@ -1,0 +1,886 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2006, Xorcom
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <version.h>		/* For zaptel version */
+#include "xpd.h"
+#include "xproto.h"
+#include "xpp_zap.h"
+#include "card_fxo.h"
+#include "zap_debug.h"
+
+static const char rcsid[] = "$Id$";
+
+DEF_PARM(int, print_dbg, 0, "Print DBG statements");	/* must be before zap_debug.h */
+
+enum fxo_leds {
+	LED_GREEN,
+};
+
+#define	NUM_LEDS		1
+#define	DELAY_UNTIL_DIALTONE	3000
+
+/*---------------- 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 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_
+
+#define	PROC_DAA_FNAME		"slics"
+#define	PROC_FXO_INFO_FNAME	"fxo_info"
+
+struct FXO_priv_data {
+	struct proc_dir_entry		*xpd_slic;
+	struct proc_dir_entry		*fxo_info;
+	slic_reply_t			requested_reply;
+	slic_reply_t			last_reply;
+	xpp_line_t			battery;
+	xpp_line_t			ledstate[NUM_LEDS];	/* 0 - OFF, 1 - ON */
+	int				blinking[NUM_LEDS][CHANNELS_PERXPD];
+};
+
+/*---------------- FXO: Static functions ----------------------------------*/
+
+#define	IS_BLINKING(priv,pos,color)	((priv)->blinking[color][pos] != 0)
+#define	DO_BLINK(priv,pos,color,val)	((priv)->blinking[color][pos] = (val))
+
+/*
+ * LED control is done via DAA register 0x20
+ */
+static int do_led(xpd_t *xpd, lineno_t pos, byte which, bool on)
+{
+	unsigned long		flags;
+	int			ret = 0;
+	xpacket_t		*pack;
+	slic_cmd_t		*sc;
+	int			len;
+	struct FXO_priv_data	*priv;
+	xpp_line_t		lines;
+	xbus_t			*xbus;
+
+	BUG_ON(!xpd);
+	spin_lock_irqsave(&xpd->lock, flags);
+	xbus = xpd->xbus;
+	priv = xpd->priv;
+	which = which % NUM_LEDS;
+	if(IS_SET(xpd->digital_outputs, pos) || IS_SET(xpd->digital_inputs, pos))
+		goto out;
+	if(pos == ALL_LINES) {
+		lines = ~0;
+		priv->ledstate[which] = (on) ? ~0 : 0;
+	} else {
+		lines = BIT(pos);
+		if(on) {
+			BIT_SET(priv->ledstate[which], pos);
+		} else {
+			BIT_CLR(priv->ledstate[which], pos);
+		}
+	}
+	if(!(lines & xpd->enabled_chans))	// Ignore disabled channels
+		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);
+	sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
+	len = slic_cmd_direct_write(sc, lines, 0x20, on);
+	// DBG("LED pack: line=%d %s\n", i, (on)?"on":"off");
+	pack->datalen = len;
+	packet_send(xbus, pack);
+out:
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	return ret;
+}
+
+static void handle_fxo_leds(xpd_t *xpd)
+{
+	int		i;
+	unsigned long	flags;
+	const enum fxo_leds	color = LED_GREEN;
+	unsigned int	timer_count;
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	spin_lock_irqsave(&xpd->lock, flags);
+	priv = xpd->priv;
+	timer_count = xpd->timer_count;
+	for_each_enabled_line(xpd, i) {
+		if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
+			continue;
+		if(IS_BLINKING(priv,i,color)) {
+			// led state is toggled
+			if((timer_count % LED_BLINK_PERIOD) == 0) {
+				DBG("%s/%s/%d: led_state=%s\n", xpd->xbus->busname, xpd->xpdname, i,
+						(IS_SET(priv->ledstate[color], i))?"ON":"OFF");
+				if(!IS_SET(priv->ledstate[color], i)) {
+					do_led(xpd, i, color, 1);
+				} else {
+					do_led(xpd, i, color, 0);
+				}
+			}
+		}
+	}
+	spin_unlock_irqrestore(&xpd->lock, flags);
+}
+
+static void do_sethook(xpd_t *xpd, int pos, bool offhook)
+{
+	unsigned long	flags;
+
+	BUG_ON(!xpd);
+	BUG_ON(xpd->direction == TO_PHONE);		// We can SETHOOK state only on PSTN
+	spin_lock_irqsave(&xpd->lock, flags);
+	xpd->ringing[pos] = 0;				// No more rings
+	CALL_XMETHOD(SETHOOK, xpd->xbus, xpd, pos, offhook);
+	if(offhook) {
+		BIT_SET(xpd->hookstate, pos);
+	} else {
+		BIT_CLR(xpd->hookstate, pos);
+		xpd->delay_until_dialtone[pos] = 0;
+	}
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	if(offhook)
+		wake_up_interruptible(&xpd->txstateq[pos]);
+}
+
+/*---------------- FXO: Methods -------------------------------------------*/
+
+static xpd_t *FXO_card_new(xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, byte revision)
+{
+	xpd_t		*xpd = NULL;
+	int		channels = min(8, CHANNELS_PERXPD);
+
+	xpd = xpd_alloc(sizeof(struct FXO_priv_data), xbus, xpd_num, proto_table, channels, revision);
+	if(!xpd)
+		return NULL;
+	xpd->direction = TO_PSTN;
+	xpd->revision = revision;
+	return xpd;
+}
+
+static void clean_proc(xbus_t *xbus, xpd_t *xpd)
+{
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	DBG("%s/%s\n", xbus->busname, xpd->xpdname);
+#ifdef	CONFIG_PROC_FS
+	if(priv->xpd_slic) {
+		DBG("Removing xpd DAA file %s/%s\n", xbus->busname, xpd->xpdname);
+		remove_proc_entry(PROC_DAA_FNAME, xpd->proc_xpd_dir);
+	}
+	if(priv->fxo_info) {
+		DBG("Removing xpd FXO_INFO file %s/%s\n", xbus->busname, xpd->xpdname);
+		remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir);
+	}
+#endif
+}
+
+static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
+{
+	struct FXO_priv_data	*priv;
+	int			ret = 0;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+#ifdef	CONFIG_PROC_FS
+	DBG("Creating FXO_INFO file for %s/%s\n", xbus->busname, xpd->xpdname);
+	priv->fxo_info = create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxo_info_read, 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;
+	}
+	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;
+	}
+	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);
+	}
+	return ret;
+}
+
+static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd)
+{
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	DBG("%s/%s\n", xbus->busname, xpd->xpdname);
+	clean_proc(xbus, xpd);
+	return 0;
+}
+
+static int FXO_card_zaptel_registration(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);
+	if(on) {
+		for_each_line(xpd, i) {
+			do_led(xpd, i, LED_GREEN, LED_ON);
+			mdelay(50);
+		}
+		for_each_line(xpd, i) {
+			do_led(xpd, i, LED_GREEN, LED_OFF);
+			mdelay(50);
+		}
+	} else {
+		for_each_line(xpd, i) {
+			do_led(xpd, i, LED_GREEN, LED_ON);
+			mdelay(100);
+			do_led(xpd, i, LED_GREEN, LED_OFF);
+		}
+	}
+	return 0;
+}
+
+int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
+{
+	int	ret = 0;
+
+	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
+		 */
+		case ZT_ONHOOK:
+			do_sethook(xpd, pos, 0);
+			break;
+		case ZT_START:
+			DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
+			xpd->delay_until_dialtone[pos] = DELAY_UNTIL_DIALTONE;
+			// Fall through
+		case ZT_OFFHOOK:
+			do_sethook(xpd, pos, 1);
+			wait_event_interruptible(xpd->txstateq[pos], xpd->delay_until_dialtone[pos] <= 0);
+			break;
+		case ZT_WINK:
+			WARN("No code yet\n");
+			break;
+		case ZT_FLASH:
+			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]);
+			break;
+		case ZT_RINGOFF:
+			WARN("No code yet\n");
+			break;
+	}
+	return ret;
+}
+
+static void poll_battery(xbus_t *xbus, xpd_t *xpd)
+{
+	int	i;
+
+	for_each_enabled_line(xpd, i) {
+		CALL_PROTO(FXO, DAA_QUERY, xbus, xpd, i, DAA_VBAT_REGISTER);
+	}
+}
+
+
+static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
+{
+	static int		rate_limit = 0;
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	rate_limit++;
+	if((rate_limit % 100) == 0) {
+		poll_battery(xbus, xpd);
+	}
+	handle_fxo_leds(xpd);
+	return 0;
+}
+
+/*---------------- FXO: HOST COMMANDS -------------------------------------*/
+
+/* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on)
+{
+	int	ret = 0;
+	int	i;
+
+	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) {
+			do_led(xpd, i, LED_GREEN, LED_ON);
+			mdelay(20);
+		}
+		for_each_enabled_line(xpd, i) {
+			do_led(xpd, i, LED_GREEN, LED_OFF);
+			mdelay(20);
+		}
+	}
+	return ret;
+}
+
+/* 0x0F */ HOSTCMD(FXO, CHAN_CID, xpp_line_t lines)
+{
+	int		ret = 0;
+
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+	lines &= xpd->enabled_chans;	// Ignore disabled channels
+	if(!lines) {
+		return 0;
+	}
+	DBG("Channel CID: 0x%04X\n", lines);
+	return ret;
+}
+
+
+/* 0x0F */ HOSTCMD(FXO, RING, int pos, bool on)
+{
+	int		ret = 0;
+	xpacket_t	*pack;
+	slic_cmd_t	*sc;
+	xpp_line_t	mask = (1 << pos);
+	int		len;
+
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+	mask &= xpd->enabled_chans;	// Ignore disabled channels
+	if(!mask) {
+		return 0;
+	}
+	DBG("%s/%s/%d %s\n", xpd->xbus->busname, xpd->xpdname, pos, (on) ? "on" : "off");
+	XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
+	sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
+	len = slic_cmd_direct_write(sc, mask, 0x40, (on)?0x04:0x01);
+	pack->datalen = len;
+
+	packet_send(xbus, pack);
+	return ret;
+}
+
+/* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook)
+{
+	int		ret = 0;
+	xpacket_t	*pack;
+	slic_cmd_t	*sc;
+	int		len;
+	unsigned long	flags;
+	bool		value;
+
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+	value = (offhook) ? 0x01 : 0x00;
+	// 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)
+{
+	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)
+{
+	int	ret = 0;
+	xpacket_t	*pack;
+	slic_cmd_t	*sc;
+	int		len;
+
+	BUG_ON(!xbus);
+	BUG_ON(!xpd);
+	// DBG("\n");
+	XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
+	sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
+	len = slic_cmd_direct_read(sc, BIT(pos), reg_num);
+
+	pack->datalen = len;
+
+	packet_send(xbus, pack);
+	return ret;
+}
+
+/*---------------- FXO: Astribank Reply Handlers --------------------------*/
+
+HANDLER_DEF(FXO, SIG_CHANGED)
+{
+	xpp_line_t	sig_status = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status);
+	xpp_line_t	sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles);
+	unsigned long	flags;
+	int		i;
+
+	if(!xpd) {
+		NOTICE("%s: received %s for non-existing xpd: %d\n",
+				__FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
+		return -EPROTO;
+	}
+	DBG("%s/%s: (PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", xpd->xbus->busname, xpd->xpdname, sig_toggles, sig_status);
+	spin_lock_irqsave(&xpd->lock, flags);
+	for_each_line(xpd, i) {
+		if(IS_SET(sig_status, i)) {
+			xpd->ringing[i] = 1;
+		} else {
+			xpd->ringing[i] = 0;
+		}
+	}
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	return 0;
+}
+
+HANDLER_DEF(FXO, DAA_REPLY)
+{
+	slic_reply_t		*info = &RPACKET_FIELD(pack, FXO, DAA_REPLY, info);
+	xpp_line_t		lines = RPACKET_FIELD(pack, FXO, DAA_REPLY, lines);
+	unsigned long		flags;
+	struct FXO_priv_data	*priv;
+
+	if(!xpd) {
+		NOTICE("%s: received %s for non-existing xpd: %d\n",
+				__FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
+		return -EPROTO;
+	}
+	spin_lock_irqsave(&xpd->lock, flags);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if(!info->indirect && info->reg_num == DAA_VBAT_REGISTER) {
+		xpp_line_t	last_batt_on = priv->battery;
+		xpp_line_t	changed_lines;
+		int		i;
+
+		if(abs(info->data_low) < BAT_THRESHOLD) {
+			priv->battery &= ~lines;
+			// DBG("BATTERY OFF (%04X) = %d\n", lines, info->data_low);
+		} else {
+			priv->battery |= lines;
+			// DBG("BATTERY ON  (%04X) = %d\n", 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 0
+	DBG("DAA_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
+			xpd->id, (info->indirect)?"I":"D",
+			info->reg_num, info->data_low, info->data_high);
+#endif
+
+	/* Update /proc info only if reply relate to the last slic read request */
+	if(priv->requested_reply.indirect == info->indirect &&
+			priv->requested_reply.reg_num == info->reg_num) {
+		priv->last_reply = *info;
+	}
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	return 0;
+}
+
+
+xproto_table_t PROTO_TABLE(FXO) = {
+	.owner = THIS_MODULE,
+	.entries = {
+		/*	Card	Opcode		*/
+		XENTRY(	FXO,	SIG_CHANGED	),
+		XENTRY(	FXO,	DAA_REPLY	),
+	},
+	.name = "FXO",
+	.type = XPD_TYPE_FXO,
+	.xops = {
+		.card_new	= FXO_card_new,
+		.card_init	= FXO_card_init,
+		.card_remove	= FXO_card_remove,
+		.card_zaptel_registration	= FXO_card_zaptel_registration,
+		.card_sethook	= FXO_card_sethook,
+		.card_tick	= FXO_card_tick,
+
+		.RING		= XPROTO_CALLER(FXO, RING),
+		.SETHOOK	= XPROTO_CALLER(FXO, SETHOOK),
+		.RELAY_OUT	= XPROTO_CALLER(FXO, RELAY_OUT),
+		.CHAN_ENABLE	= XPROTO_CALLER(FXO, CHAN_ENABLE),
+		.CHAN_CID	= XPROTO_CALLER(FXO, CHAN_CID),
+
+		.SYNC_SOURCE	= XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
+		.PCM_WRITE	= XPROTO_CALLER(GLOBAL, PCM_WRITE),
+	},
+	.packet_is_valid = fxo_packet_is_valid,
+	.packet_dump = fxo_packet_dump,
+};
+
+static bool fxo_packet_is_valid(xpacket_t *pack)
+{
+	const xproto_entry_t	*xe;
+
+	//DBG("\n");
+	xe = xproto_card_entry(&PROTO_TABLE(FXO), pack->content.opcode);
+	return xe != NULL;
+}
+
+static void fxo_packet_dump(xpacket_t *pack)
+{
+	DBG("\n");
+}
+
+/*------------------------- DAA Handling --------------------------*/
+
+static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	int			len = 0;
+	unsigned long		flags;
+	xpd_t			*xpd = data;
+	struct FXO_priv_data	*priv;
+	int			i;
+
+	BUG_ON(!xpd);
+	spin_lock_irqsave(&xpd->lock, flags);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	len += sprintf(page + len, "\t%-17s: ", "Channel");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%d ", i % 10);
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[LED_GREEN], i));
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "blinking");
+	for_each_line(xpd, i) {
+		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
+			len += sprintf(page + len, "%d ", IS_BLINKING(priv,i,LED_GREEN));
+	}
+	len += sprintf(page + len, "\n\t%-17s: ", "battery");
+	for_each_line(xpd, i) {
+		len += sprintf(page + len, "%d ", IS_SET(priv->battery, i));
+	}
+	len += sprintf(page + len, "\n");
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	if (len <= off+count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+	return len;
+}
+
+
+static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	int			len = 0;
+	unsigned long		flags;
+	xpd_t			*xpd = data;
+	slic_reply_t		*info;
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	spin_lock_irqsave(&xpd->lock, flags);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	info = &priv->last_reply;
+	len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n");
+	len += sprintf(page + len, "# Consult firmware docs first\n");
+	len += sprintf(page + len, "DAA_REPLY: %s reg_num=0x%X, dataH=0x%X dataL=0x%X\n",
+			(info->indirect)?"I":"D",
+			info->reg_num, info->data_high, info->data_low);
+	spin_unlock_irqrestore(&xpd->lock, flags);
+	if (len <= off+count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+	return len;
+}
+
+/*
+ *        Direct/Indirect
+ *              v
+ * FF FF FF FF WD 06 1
+ * ^---------^ ^  Reg
+ *      | Write/Read
+ *      |
+ *    DAA #
+ */
+static int parse_slic_cmd(const char *buf, slic_cmd_t *sc, slic_reply_t *requested_reply)
+{
+	char		op;		/* [W]rite, [R]ead */
+	char		reg_type;	/* [D]irect, [I]ndirect */
+	int		s1, s2, s3, s4;
+	int		reg_num;
+	int		data_low, data_high;
+	xpp_line_t	lines;
+	int		ret;
+
+	ret = sscanf(buf, "%x %x %x %x %c%c %x %x %x",
+			&s1, &s2, &s3, &s4, &op, &reg_type, &reg_num, &data_high, &data_low);
+	lines = (s4 << 24) | (s3 << 16) | (s2 << 8) | (s1);
+	switch(op) {
+		case 'R':
+			if(reg_type == 'D' && ret == 7) {
+				// DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
+				ret = slic_cmd_direct_read(sc, lines, reg_num);
+				if(requested_reply) {
+					requested_reply->indirect = 0;
+					requested_reply->reg_num = reg_num;
+				}
+			} else if(reg_type == 'I' && ret == 7) {
+				// DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
+				ret = slic_cmd_indirect_read(sc, lines, reg_num);
+				if(requested_reply) {
+					requested_reply->indirect = 1;
+					requested_reply->reg_num = reg_num;
+				}
+			} else {
+				NOTICE("%s: Bad read input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
+				goto err;
+			}
+			break;
+		case 'W':
+			if(reg_type == 'D' && ret == 8) {
+				// DBG("0x%X 0x%X 0x%X 0x%X %c %x %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high);
+				ret = slic_cmd_direct_write(sc, lines, reg_num, data_high);
+			} else if(reg_type == 'I' && ret == 9) {
+				// DBG("0x%X 0x%X 0x%X 0x%X %c %x %X %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high, data_low);
+				ret = slic_cmd_indirect_write(sc, lines, reg_num, data_low, data_high);
+			} else {
+				NOTICE("%s: Bad write input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
+				goto err;
+			}
+			break;
+		default:
+			NOTICE("%s: Bad input: ret=%d buf='%s' op=%c\n", __FUNCTION__, ret, buf, op);
+			goto err;
+	}
+	return ret;
+err:
+	return -EINVAL;
+}
+
+static int process_slic_cmdline(xpd_t *xpd, char *cmdline)
+{
+	xbus_t			*xbus;
+	struct FXO_priv_data	*priv;
+	slic_cmd_t		sc;
+	xpacket_t		*pack;
+	char			*p;
+	int			len = strlen(cmdline);
+
+	BUG_ON(!xpd);
+	xbus = xpd->xbus;
+	priv = xpd->priv;
+	if((p = strchr(cmdline, '#')) != NULL)	/* Truncate comments */
+		*p = '\0';
+	if((p = strchr(cmdline, ';')) != NULL)	/* Truncate comments */
+		*p = '\0';
+	for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
+		;
+	if(*p == '\0')
+		return 0;
+	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__);
+		return 0;
+	}
+	dump_slic_cmd("WRITE_DAA", &sc);
+	XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
+	RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd) = sc;
+	pack->datalen = len;
+	packet_send(xbus, pack);
+	return 0;
+}
+
+static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
+{
+	xpd_t		*xpd = data;
+	const int	LINE_LEN = 500;
+	char		buf[LINE_LEN];
+	char		*p;
+	int		i;
+	int		ret;
+
+	BUG_ON(!xpd);
+	for(i = 0; i < count; /* noop */) {
+		for(p = buf; p < buf + LINE_LEN; p++) {	/* read a line */
+			if(i >= count)
+				break;
+			if(get_user(*p, buffer + i))
+				return -EFAULT;
+			i++;
+			if(*p == '\n' || *p == '\r')	/* whatever */
+				break;
+		}
+		if(p >= buf + LINE_LEN)
+			return -E2BIG;
+		*p = '\0';
+		ret = process_slic_cmdline(xpd, buf);
+		if(ret < 0)
+			return ret;
+		mdelay(1);
+	}
+	return count;
+}
+
+
+int __init card_fxo_startup(void)
+{
+	INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
+	xproto_register(&PROTO_TABLE(FXO));
+	return 0;
+}
+
+void __exit card_fxo_cleanup(void)
+{
+	xproto_unregister(&PROTO_TABLE(FXO));
+}
+
+MODULE_DESCRIPTION("XPP FXO Card Driver");
+MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ZAPTEL_VERSION);
+MODULE_ALIAS_XPD(XPD_TYPE_FXO);
+
+module_init(card_fxo_startup);
+module_exit(card_fxo_cleanup);

Propchange: trunk/xpp/card_fxo.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/xpp/card_fxo.c
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: trunk/xpp/card_fxo.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: trunk/xpp/card_fxo.h
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxo.h?rev=1021&view=auto
==============================================================================
--- trunk/xpp/card_fxo.h (added)
+++ trunk/xpp/card_fxo.h Wed May  3 18:06:02 2006
@@ -1,0 +1,65 @@
+#ifndef	CARD_FXO_H
+#define	CARD_FXO_H
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2006, Xorcom
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "xpd.h"
+#include "slic.h"
+
+enum fxo_opcodes {
+	XPROTO_NAME(FXO, SIG_CHANGED)		= 0x06,
+/**/
+	XPROTO_NAME(FXO, DAA_WRITE)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, CHAN_ENABLE)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, CHAN_CID)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, RING)			= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, SETHOOK)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, LED)			= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, RELAY_OUT)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, DAA_INIT)		= 0x0F,	/* Write to DAA */
+	XPROTO_NAME(FXO, DAA_QUERY)		= 0x0F,	/* Write to DAA */
+/**/
+	XPROTO_NAME(FXO, DAA_REPLY)		= 0x10,
+};
+
+
+DEF_RPACKET_DATA(FXO, SIG_CHANGED,
+	byte		type;		/* unused -- we have it from DEV_DESC */
+	xpp_line_t	sig_status;	/* channels: lsb=1, msb=8 */
+	xpp_line_t	sig_toggles;	/* channels: lsb=1, msb=8 */
+	);
+DEF_RPACKET_DATA(FXO, DAA_REPLY,	/* Get status of a single DAA (for debugging) */
+	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;
+	);
+
+#define	DAA_VBAT_REGISTER	29
+#define	BAT_THRESHOLD		3
+
+#endif	/* CARD_FXO_H */

Propchange: trunk/xpp/card_fxo.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/xpp/card_fxo.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: trunk/xpp/card_fxo.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: trunk/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/trunk/xpp/card_fxs.c?rev=1021&r1=1020&r2=1021&view=diff
==============================================================================
--- trunk/xpp/card_fxs.c (original)
+++ trunk/xpp/card_fxs.c Wed May  3 18:06:02 2006
@@ -1,6 +1,6 @@
 /*
  * Written by Oron Peled <oron at actcom.co.il>
- * Copyright (C) 2004-2005, Xorcom
+ * Copyright (C) 2004-2006, Xorcom
  *
  * All rights reserved.
  *
@@ -23,13 +23,15 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/delay.h>
+#include <version.h>		/* For zaptel version */
 #include "xpd.h"
 #include "xproto.h"
 #include "xpp_zap.h"
-#include <linux/delay.h>
+#include "card_fxo.h"
+#include "zap_debug.h"
 
 static const char rcsid[] = "$Id$";
-static const char revision[] = "$Revision$";
 
 DEF_PARM(int, print_dbg, 0, "Print DBG statements");	/* must be before zap_debug.h */
 
@@ -42,20 +44,27 @@
 #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))
 
+enum fxs_leds {
+	LED_GREEN,
+	LED_RED,

[... 6690 lines stripped ...]


More information about the zaptel-commits mailing list