[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, ®_type, ®_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