提交 5c7c204a 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6:
  Add layer1 over IP support
  Add mISDN HFC multiport driver
  Add mISDN HFC PCI driver
  Add mISDN DSP
  Add mISDN core files
  Define AF_ISDN and PF_ISDN
  Add mISDN driver
mISDN is a new modular ISDN driver, in the long term it should replace
the old I4L driver architecture for passiv ISDN cards.
It was designed to allow a broad range of applications and interfaces
but only have the basic function in kernel, the interface to the user
space is based on sockets with a own address family AF_ISDN.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
menuconfig ISDN menuconfig ISDN
tristate "ISDN support" bool "ISDN support"
depends on NET depends on NET
depends on !S390 depends on !S390
---help--- ---help---
...@@ -21,6 +21,8 @@ menuconfig ISDN ...@@ -21,6 +21,8 @@ menuconfig ISDN
if ISDN if ISDN
source "drivers/isdn/mISDN/Kconfig"
menuconfig ISDN_I4L menuconfig ISDN_I4L
tristate "Old ISDN4Linux (deprecated)" tristate "Old ISDN4Linux (deprecated)"
---help--- ---help---
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_ISDN_I4L) += i4l/
obj-$(CONFIG_ISDN_CAPI) += capi/ obj-$(CONFIG_ISDN_CAPI) += capi/
obj-$(CONFIG_MISDN) += mISDN/
obj-$(CONFIG_ISDN_CAPI) += hardware/ obj-$(CONFIG_ISDN_CAPI) += hardware/
obj-$(CONFIG_ISDN_DIVERSION) += divert/ obj-$(CONFIG_ISDN_DIVERSION) += divert/
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/ obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/
......
...@@ -4,3 +4,4 @@ ...@@ -4,3 +4,4 @@
obj-$(CONFIG_CAPI_AVM) += avm/ obj-$(CONFIG_CAPI_AVM) += avm/
obj-$(CONFIG_CAPI_EICON) += eicon/ obj-$(CONFIG_CAPI_EICON) += eicon/
obj-$(CONFIG_MISDN) += mISDN/
#
# Hardware for mISDN
#
comment "mISDN hardware drivers"
config MISDN_HFCPCI
tristate "Support for HFC PCI cards"
depends on MISDN
depends on PCI
help
Enable support for cards with Cologne Chip AG's
HFC PCI chip.
config MISDN_HFCMULTI
tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
depends on PCI
depends on MISDN
help
Enable support for cards with Cologne Chip AG's HFC multiport
chip. There are three types of chips that are quite similar,
but the interface is different:
* HFC-4S (4 S/T interfaces on one chip)
* HFC-8S (8 S/T interfaces on one chip)
* HFC-E1 (E1 interface for 2Mbit ISDN)
#
# Makefile for the modular ISDN hardware drivers
#
#
obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o
obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o
此差异已折叠。
/*
* specific defines for CCD's HFC 2BDS0 PCI chips
*
* Author Werner Cornelius (werner@isdn4linux.de)
*
* Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
*
* 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, 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.
*
*/
/*
* thresholds for transparent B-channel mode
* change mask and threshold simultaneously
*/
#define HFCPCI_BTRANS_THRESHOLD 128
#define HFCPCI_BTRANS_MAX 256
#define HFCPCI_BTRANS_THRESMASK 0x00
/* defines for PCI config */
#define PCI_ENA_MEMIO 0x02
#define PCI_ENA_MASTER 0x04
/* GCI/IOM bus monitor registers */
#define HCFPCI_C_I 0x08
#define HFCPCI_TRxR 0x0C
#define HFCPCI_MON1_D 0x28
#define HFCPCI_MON2_D 0x2C
/* GCI/IOM bus timeslot registers */
#define HFCPCI_B1_SSL 0x80
#define HFCPCI_B2_SSL 0x84
#define HFCPCI_AUX1_SSL 0x88
#define HFCPCI_AUX2_SSL 0x8C
#define HFCPCI_B1_RSL 0x90
#define HFCPCI_B2_RSL 0x94
#define HFCPCI_AUX1_RSL 0x98
#define HFCPCI_AUX2_RSL 0x9C
/* GCI/IOM bus data registers */
#define HFCPCI_B1_D 0xA0
#define HFCPCI_B2_D 0xA4
#define HFCPCI_AUX1_D 0xA8
#define HFCPCI_AUX2_D 0xAC
/* GCI/IOM bus configuration registers */
#define HFCPCI_MST_EMOD 0xB4
#define HFCPCI_MST_MODE 0xB8
#define HFCPCI_CONNECT 0xBC
/* Interrupt and status registers */
#define HFCPCI_FIFO_EN 0x44
#define HFCPCI_TRM 0x48
#define HFCPCI_B_MODE 0x4C
#define HFCPCI_CHIP_ID 0x58
#define HFCPCI_CIRM 0x60
#define HFCPCI_CTMT 0x64
#define HFCPCI_INT_M1 0x68
#define HFCPCI_INT_M2 0x6C
#define HFCPCI_INT_S1 0x78
#define HFCPCI_INT_S2 0x7C
#define HFCPCI_STATUS 0x70
/* S/T section registers */
#define HFCPCI_STATES 0xC0
#define HFCPCI_SCTRL 0xC4
#define HFCPCI_SCTRL_E 0xC8
#define HFCPCI_SCTRL_R 0xCC
#define HFCPCI_SQ 0xD0
#define HFCPCI_CLKDEL 0xDC
#define HFCPCI_B1_REC 0xF0
#define HFCPCI_B1_SEND 0xF0
#define HFCPCI_B2_REC 0xF4
#define HFCPCI_B2_SEND 0xF4
#define HFCPCI_D_REC 0xF8
#define HFCPCI_D_SEND 0xF8
#define HFCPCI_E_REC 0xFC
/* bits in status register (READ) */
#define HFCPCI_PCI_PROC 0x02
#define HFCPCI_NBUSY 0x04
#define HFCPCI_TIMER_ELAP 0x10
#define HFCPCI_STATINT 0x20
#define HFCPCI_FRAMEINT 0x40
#define HFCPCI_ANYINT 0x80
/* bits in CTMT (Write) */
#define HFCPCI_CLTIMER 0x80
#define HFCPCI_TIM3_125 0x04
#define HFCPCI_TIM25 0x10
#define HFCPCI_TIM50 0x14
#define HFCPCI_TIM400 0x18
#define HFCPCI_TIM800 0x1C
#define HFCPCI_AUTO_TIMER 0x20
#define HFCPCI_TRANSB2 0x02
#define HFCPCI_TRANSB1 0x01
/* bits in CIRM (Write) */
#define HFCPCI_AUX_MSK 0x07
#define HFCPCI_RESET 0x08
#define HFCPCI_B1_REV 0x40
#define HFCPCI_B2_REV 0x80
/* bits in INT_M1 and INT_S1 */
#define HFCPCI_INTS_B1TRANS 0x01
#define HFCPCI_INTS_B2TRANS 0x02
#define HFCPCI_INTS_DTRANS 0x04
#define HFCPCI_INTS_B1REC 0x08
#define HFCPCI_INTS_B2REC 0x10
#define HFCPCI_INTS_DREC 0x20
#define HFCPCI_INTS_L1STATE 0x40
#define HFCPCI_INTS_TIMER 0x80
/* bits in INT_M2 */
#define HFCPCI_PROC_TRANS 0x01
#define HFCPCI_GCI_I_CHG 0x02
#define HFCPCI_GCI_MON_REC 0x04
#define HFCPCI_IRQ_ENABLE 0x08
#define HFCPCI_PMESEL 0x80
/* bits in STATES */
#define HFCPCI_STATE_MSK 0x0F
#define HFCPCI_LOAD_STATE 0x10
#define HFCPCI_ACTIVATE 0x20
#define HFCPCI_DO_ACTION 0x40
#define HFCPCI_NT_G2_G3 0x80
/* bits in HFCD_MST_MODE */
#define HFCPCI_MASTER 0x01
#define HFCPCI_SLAVE 0x00
#define HFCPCI_F0IO_POSITIV 0x02
#define HFCPCI_F0_NEGATIV 0x04
#define HFCPCI_F0_2C4 0x08
/* remaining bits are for codecs control */
/* bits in HFCD_SCTRL */
#define SCTRL_B1_ENA 0x01
#define SCTRL_B2_ENA 0x02
#define SCTRL_MODE_TE 0x00
#define SCTRL_MODE_NT 0x04
#define SCTRL_LOW_PRIO 0x08
#define SCTRL_SQ_ENA 0x10
#define SCTRL_TEST 0x20
#define SCTRL_NONE_CAP 0x40
#define SCTRL_PWR_DOWN 0x80
/* bits in SCTRL_E */
#define HFCPCI_AUTO_AWAKE 0x01
#define HFCPCI_DBIT_1 0x04
#define HFCPCI_IGNORE_COL 0x08
#define HFCPCI_CHG_B1_B2 0x80
/* bits in FIFO_EN register */
#define HFCPCI_FIFOEN_B1 0x03
#define HFCPCI_FIFOEN_B2 0x0C
#define HFCPCI_FIFOEN_DTX 0x10
#define HFCPCI_FIFOEN_B1TX 0x01
#define HFCPCI_FIFOEN_B1RX 0x02
#define HFCPCI_FIFOEN_B2TX 0x04
#define HFCPCI_FIFOEN_B2RX 0x08
/* definitions of fifo memory area */
#define MAX_D_FRAMES 15
#define MAX_B_FRAMES 31
#define B_SUB_VAL 0x200
#define B_FIFO_SIZE (0x2000 - B_SUB_VAL)
#define D_FIFO_SIZE 512
#define D_FREG_MASK 0xF
struct zt {
unsigned short z1; /* Z1 pointer 16 Bit */
unsigned short z2; /* Z2 pointer 16 Bit */
};
struct dfifo {
u_char data[D_FIFO_SIZE]; /* FIFO data space */
u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
u_char f1, f2; /* f pointers */
u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
/* mask index with D_FREG_MASK for access */
struct zt za[MAX_D_FRAMES+1];
u_char fill3[0x4000-0x2100]; /* align 16K */
};
struct bzfifo {
struct zt za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */
u_char f1, f2; /* f pointers */
u_char fill[0x2100-0x2082]; /* alignment */
};
union fifo_area {
struct {
struct dfifo d_tx; /* D-send channel */
struct dfifo d_rx; /* D-receive channel */
} d_chan;
struct {
u_char fill1[0x200];
u_char txdat_b1[B_FIFO_SIZE];
struct bzfifo txbz_b1;
struct bzfifo txbz_b2;
u_char txdat_b2[B_FIFO_SIZE];
u_char fill2[D_FIFO_SIZE];
u_char rxdat_b1[B_FIFO_SIZE];
struct bzfifo rxbz_b1;
struct bzfifo rxbz_b2;
u_char rxdat_b2[B_FIFO_SIZE];
} b_chans;
u_char fill[32768];
};
#define Write_hfc(a, b, c) (writeb(c, (a->hw.pci_io)+b))
#define Read_hfc(a, b) (readb((a->hw.pci_io)+b))
此差异已折叠。
此差异已折叠。
#
# modularer ISDN driver
#
menuconfig MISDN
tristate "Modular ISDN driver"
help
Enable support for the modular ISDN driver.
if MISDN != n
config MISDN_DSP
tristate "Digital Audio Processing of transparent data"
depends on MISDN
help
Enable support for digital audio processing capability.
This module may be used for special applications that require
cross connecting of bchannels, conferencing, dtmf decoding
echo cancelation, tone generation, and Blowfish encryption and
decryption.
It may use hardware features if available.
E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu
and get more informations about this module and it's usage.
If unsure, say 'N'.
config MISDN_L1OIP
tristate "ISDN over IP tunnel"
depends on MISDN
help
Enable support for ISDN over IP tunnel.
It features:
- dynamic IP exchange, if one or both peers have dynamic IPs
- BRI (S0) and PRI (S2M) interface
- layer 1 control via network keepalive frames
- direct tunneling of physical interface via IP
NOTE: This protocol is called 'Layer 1 over IP' and is not
compatible with ISDNoIP (Agfeo) or TDMoIP. Protocol description is
provided in the source code.
source "drivers/isdn/hardware/mISDN/Kconfig"
endif #MISDN
#
# Makefile for the modular ISDN driver
#
obj-$(CONFIG_MISDN) += mISDN_core.o
obj-$(CONFIG_MISDN_DSP) += mISDN_dsp.o
obj-$(CONFIG_MISDN_L1OIP) += l1oip.o
# multi objects
mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
l1oip-objs := l1oip_core.o l1oip_codec.o
/*
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mISDNif.h>
#include "core.h"
static u_int debug;
MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
module_param(debug, uint, S_IRUGO | S_IWUSR);
static LIST_HEAD(devices);
DEFINE_RWLOCK(device_lock);
static u64 device_ids;
#define MAX_DEVICE_ID 63
static LIST_HEAD(Bprotocols);
DEFINE_RWLOCK(bp_lock);
struct mISDNdevice
*get_mdevice(u_int id)
{
struct mISDNdevice *dev;
read_lock(&device_lock);
list_for_each_entry(dev, &devices, D.list)
if (dev->id == id) {
read_unlock(&device_lock);
return dev;
}
read_unlock(&device_lock);
return NULL;
}
int
get_mdevice_count(void)
{
struct mISDNdevice *dev;
int cnt = 0;
read_lock(&device_lock);
list_for_each_entry(dev, &devices, D.list)
cnt++;
read_unlock(&device_lock);
return cnt;
}
static int
get_free_devid(void)
{
u_int i;
for (i = 0; i <= MAX_DEVICE_ID; i++)
if (!test_and_set_bit(i, (u_long *)&device_ids))
return i;
return -1;
}
int
mISDN_register_device(struct mISDNdevice *dev, char *name)
{
u_long flags;
int err;
dev->id = get_free_devid();
if (dev->id < 0)
return -EBUSY;
if (name && name[0])
strcpy(dev->name, name);
else
sprintf(dev->name, "mISDN%d", dev->id);
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "mISDN_register %s %d\n",
dev->name, dev->id);
err = create_stack(dev);
if (err)
return err;
write_lock_irqsave(&device_lock, flags);
list_add_tail(&dev->D.list, &devices);
write_unlock_irqrestore(&device_lock, flags);
return 0;
}
EXPORT_SYMBOL(mISDN_register_device);
void
mISDN_unregister_device(struct mISDNdevice *dev) {
u_long flags;
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "mISDN_unregister %s %d\n",
dev->name, dev->id);
write_lock_irqsave(&device_lock, flags);
list_del(&dev->D.list);
write_unlock_irqrestore(&device_lock, flags);
test_and_clear_bit(dev->id, (u_long *)&device_ids);
delete_stack(dev);
}
EXPORT_SYMBOL(mISDN_unregister_device);
u_int
get_all_Bprotocols(void)
{
struct Bprotocol *bp;
u_int m = 0;
read_lock(&bp_lock);
list_for_each_entry(bp, &Bprotocols, list)
m |= bp->Bprotocols;
read_unlock(&bp_lock);
return m;
}
struct Bprotocol *
get_Bprotocol4mask(u_int m)
{
struct Bprotocol *bp;
read_lock(&bp_lock);
list_for_each_entry(bp, &Bprotocols, list)
if (bp->Bprotocols & m) {
read_unlock(&bp_lock);
return bp;
}
read_unlock(&bp_lock);
return NULL;
}
struct Bprotocol *
get_Bprotocol4id(u_int id)
{
u_int m;
if (id < ISDN_P_B_START || id > 63) {
printk(KERN_WARNING "%s id not in range %d\n",
__func__, id);
return NULL;
}
m = 1 << (id & ISDN_P_B_MASK);
return get_Bprotocol4mask(m);
}
int
mISDN_register_Bprotocol(struct Bprotocol *bp)
{
u_long flags;
struct Bprotocol *old;
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "%s: %s/%x\n", __func__,
bp->name, bp->Bprotocols);
old = get_Bprotocol4mask(bp->Bprotocols);
if (old) {
printk(KERN_WARNING
"register duplicate protocol old %s/%x new %s/%x\n",
old->name, old->Bprotocols, bp->name, bp->Bprotocols);
return -EBUSY;
}
write_lock_irqsave(&bp_lock, flags);
list_add_tail(&bp->list, &Bprotocols);
write_unlock_irqrestore(&bp_lock, flags);
return 0;
}
EXPORT_SYMBOL(mISDN_register_Bprotocol);
void
mISDN_unregister_Bprotocol(struct Bprotocol *bp)
{
u_long flags;
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
bp->Bprotocols);
write_lock_irqsave(&bp_lock, flags);
list_del(&bp->list);
write_unlock_irqrestore(&bp_lock, flags);
}
EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
int
mISDNInit(void)
{
int err;
printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
mISDN_initstack(&debug);
err = mISDN_inittimer(&debug);
if (err)
goto error;
err = l1_init(&debug);
if (err) {
mISDN_timer_cleanup();
goto error;
}
err = Isdnl2_Init(&debug);
if (err) {
mISDN_timer_cleanup();
l1_cleanup();
goto error;
}
err = misdn_sock_init(&debug);
if (err) {
mISDN_timer_cleanup();
l1_cleanup();
Isdnl2_cleanup();
}
error:
return err;
}
void mISDN_cleanup(void)
{
misdn_sock_cleanup();
mISDN_timer_cleanup();
l1_cleanup();
Isdnl2_cleanup();
if (!list_empty(&devices))
printk(KERN_ERR "%s devices still registered\n", __func__);
if (!list_empty(&Bprotocols))
printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
printk(KERN_DEBUG "mISDNcore unloaded\n");
}
module_init(mISDNInit);
module_exit(mISDN_cleanup);
/*
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef mISDN_CORE_H
#define mISDN_CORE_H
extern struct mISDNdevice *get_mdevice(u_int);
extern int get_mdevice_count(void);
/* stack status flag */
#define mISDN_STACK_ACTION_MASK 0x0000ffff
#define mISDN_STACK_COMMAND_MASK 0x000f0000
#define mISDN_STACK_STATUS_MASK 0xfff00000
/* action bits 0-15 */
#define mISDN_STACK_WORK 0
#define mISDN_STACK_SETUP 1
#define mISDN_STACK_CLEARING 2
#define mISDN_STACK_RESTART 3
#define mISDN_STACK_WAKEUP 4
#define mISDN_STACK_ABORT 15
/* command bits 16-19 */
#define mISDN_STACK_STOPPED 16
#define mISDN_STACK_INIT 17
#define mISDN_STACK_THREADSTART 18
/* status bits 20-31 */
#define mISDN_STACK_BCHANNEL 20
#define mISDN_STACK_ACTIVE 29
#define mISDN_STACK_RUNNING 30
#define mISDN_STACK_KILLED 31
/* manager options */
#define MGR_OPT_USER 24
#define MGR_OPT_NETWORK 25
extern int connect_Bstack(struct mISDNdevice *, struct mISDNchannel *,
u_int, struct sockaddr_mISDN *);
extern int connect_layer1(struct mISDNdevice *, struct mISDNchannel *,
u_int, struct sockaddr_mISDN *);
extern int create_l2entity(struct mISDNdevice *, struct mISDNchannel *,
u_int, struct sockaddr_mISDN *);
extern int create_stack(struct mISDNdevice *);
extern int create_teimanager(struct mISDNdevice *);
extern void delete_teimanager(struct mISDNchannel *);
extern void delete_channel(struct mISDNchannel *);
extern void delete_stack(struct mISDNdevice *);
extern void mISDN_initstack(u_int *);
extern int misdn_sock_init(u_int *);
extern void misdn_sock_cleanup(void);
extern void add_layer2(struct mISDNchannel *, struct mISDNstack *);
extern void __add_layer2(struct mISDNchannel *, struct mISDNstack *);
extern u_int get_all_Bprotocols(void);
struct Bprotocol *get_Bprotocol4mask(u_int);
struct Bprotocol *get_Bprotocol4id(u_int);
extern int mISDN_inittimer(u_int *);
extern void mISDN_timer_cleanup(void);
extern int l1_init(u_int *);
extern void l1_cleanup(void);
extern int Isdnl2_Init(u_int *);
extern void Isdnl2_cleanup(void);
#endif
/*
* Audio support data for ISDN4Linux.
*
* Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define DEBUG_DSP_CTRL 0x0001
#define DEBUG_DSP_CORE 0x0002
#define DEBUG_DSP_DTMF 0x0004
#define DEBUG_DSP_CMX 0x0010
#define DEBUG_DSP_TONE 0x0020
#define DEBUG_DSP_BLOWFISH 0x0040
#define DEBUG_DSP_DELAY 0x0100
#define DEBUG_DSP_DTMFCOEFF 0x8000 /* heavy output */
/* options may be:
*
* bit 0 = use ulaw instead of alaw
* bit 1 = enable hfc hardware accelleration for all channels
*
*/
#define DSP_OPT_ULAW (1<<0)
#define DSP_OPT_NOHARDWARE (1<<1)
#include <linux/timer.h>
#include <linux/workqueue.h>
#include "dsp_ecdis.h"
extern int dsp_options;
extern int dsp_debug;
extern int dsp_poll;
extern int dsp_tics;
extern spinlock_t dsp_lock;
extern struct work_struct dsp_workq;
extern u32 dsp_poll_diff; /* calculated fix-comma corrected poll value */
/***************
* audio stuff *
***************/
extern s32 dsp_audio_alaw_to_s32[256];
extern s32 dsp_audio_ulaw_to_s32[256];
extern s32 *dsp_audio_law_to_s32;
extern u8 dsp_audio_s16_to_law[65536];
extern u8 dsp_audio_alaw_to_ulaw[256];
extern u8 dsp_audio_mix_law[65536];
extern u8 dsp_audio_seven2law[128];
extern u8 dsp_audio_law2seven[256];
extern void dsp_audio_generate_law_tables(void);
extern void dsp_audio_generate_s2law_table(void);
extern void dsp_audio_generate_seven(void);
extern void dsp_audio_generate_mix_table(void);
extern void dsp_audio_generate_ulaw_samples(void);
extern void dsp_audio_generate_volume_changes(void);
extern u8 dsp_silence;
/*************
* cmx stuff *
*************/
#define MAX_POLL 256 /* maximum number of send-chunks */
#define CMX_BUFF_SIZE 0x8000 /* must be 2**n (0x1000 about 1/2 second) */
#define CMX_BUFF_HALF 0x4000 /* CMX_BUFF_SIZE / 2 */
#define CMX_BUFF_MASK 0x7fff /* CMX_BUFF_SIZE - 1 */
/* how many seconds will we check the lowest delay until the jitter buffer
is reduced by that delay */
#define MAX_SECONDS_JITTER_CHECK 5
extern struct timer_list dsp_spl_tl;
extern u32 dsp_spl_jiffies;
/* the structure of conferences:
*
* each conference has a unique number, given by user space.
* the conferences are linked in a chain.
* each conference has members linked in a chain.
* each dsplayer points to a member, each member points to a dsplayer.
*/
/* all members within a conference (this is linked 1:1 with the dsp) */
struct dsp;
struct dsp_conf_member {
struct list_head list;
struct dsp *dsp;
};
/* the list of all conferences */
struct dsp_conf {
struct list_head list;
u32 id;
/* all cmx stacks with the same ID are
connected */
struct list_head mlist;
int software; /* conf is processed by software */
int hardware; /* conf is processed by hardware */
/* note: if both unset, has only one member */
};
/**************
* DTMF stuff *
**************/
#define DSP_DTMF_NPOINTS 102
#define ECHOCAN_BUFLEN (4*128)
struct dsp_dtmf {
int treshold; /* above this is dtmf (square of) */
int software; /* dtmf uses software decoding */
int hardware; /* dtmf uses hardware decoding */
int size; /* number of bytes in buffer */
signed short buffer[DSP_DTMF_NPOINTS];
/* buffers one full dtmf frame */
u8 lastwhat, lastdigit;
int count;
u8 digits[16]; /* just the dtmf result */
};
/******************
* pipeline stuff *
******************/
struct dsp_pipeline {
rwlock_t lock;
struct list_head list;
int inuse;
};
/***************
* tones stuff *
***************/
struct dsp_tone {
int software; /* tones are generated by software */
int hardware; /* tones are generated by hardware */
int tone;
void *pattern;
int count;
int index;
struct timer_list tl;
};
/*****************
* general stuff *
*****************/
struct dsp {
struct list_head list;
struct mISDNchannel ch;
struct mISDNchannel *up;
unsigned char name[64];
int b_active;
int echo; /* echo is enabled */
int rx_disabled; /* what the user wants */
int rx_is_off; /* what the card is */
int tx_mix;
struct dsp_tone tone;
struct dsp_dtmf dtmf;
int tx_volume, rx_volume;
/* queue for sending frames */
struct work_struct workq;
struct sk_buff_head sendq;
int hdlc; /* if mode is hdlc */
int data_pending; /* currently an unconfirmed frame */
/* conference stuff */
u32 conf_id;
struct dsp_conf *conf;
struct dsp_conf_member
*member;
/* buffer stuff */
int rx_W; /* current write pos for data without timestamp */
int rx_R; /* current read pos for transmit clock */
int rx_init; /* if set, pointers will be adjusted first */
int tx_W; /* current write pos for transmit data */
int tx_R; /* current read pos for transmit clock */
int rx_delay[MAX_SECONDS_JITTER_CHECK];
int tx_delay[MAX_SECONDS_JITTER_CHECK];
u8 tx_buff[CMX_BUFF_SIZE];
u8 rx_buff[CMX_BUFF_SIZE];
int last_tx; /* if set, we transmitted last poll interval */
int cmx_delay; /* initial delay of buffers,
or 0 for dynamic jitter buffer */
int tx_dejitter; /* if set, dejitter tx buffer */
int tx_data; /* enables tx-data of CMX to upper layer */
/* hardware stuff */
struct dsp_features features;
int features_rx_off; /* set if rx_off is featured */
int pcm_slot_rx; /* current PCM slot (or -1) */
int pcm_bank_rx;
int pcm_slot_tx;
int pcm_bank_tx;
int hfc_conf; /* unique id of current conference (or -1) */
/* encryption stuff */
int bf_enable;
u32 bf_p[18];
u32 bf_s[1024];
int bf_crypt_pos;
u8 bf_data_in[9];
u8 bf_crypt_out[9];
int bf_decrypt_in_pos;
int bf_decrypt_out_pos;
u8 bf_crypt_inring[16];
u8 bf_data_out[9];
int bf_sync;
struct dsp_pipeline
pipeline;
};
/* functions */
extern void dsp_change_volume(struct sk_buff *skb, int volume);
extern struct list_head dsp_ilist;
extern struct list_head conf_ilist;
extern void dsp_cmx_debug(struct dsp *dsp);
extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp);
extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
extern void dsp_cmx_send(void *arg);
extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
extern int dsp_cmx_del_conf_member(struct dsp *dsp);
extern int dsp_cmx_del_conf(struct dsp_conf *conf);
extern void dsp_dtmf_goertzel_init(struct dsp *dsp);
extern void dsp_dtmf_hardware(struct dsp *dsp);
extern u8 *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len,
int fmt);
extern int dsp_tone(struct dsp *dsp, int tone);
extern void dsp_tone_copy(struct dsp *dsp, u8 *data, int len);
extern void dsp_tone_timeout(void *arg);
extern void dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len);
extern void dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len);
extern int dsp_bf_init(struct dsp *dsp, const u8 *key, unsigned int keylen);
extern void dsp_bf_cleanup(struct dsp *dsp);
extern int dsp_pipeline_module_init(void);
extern void dsp_pipeline_module_exit(void);
extern int dsp_pipeline_init(struct dsp_pipeline *pipeline);
extern void dsp_pipeline_destroy(struct dsp_pipeline *pipeline);
extern int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg);
extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
int len);
extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
int len);
/*
* Audio support data for mISDN_dsp.
*
* Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
* Rewritten by Peter
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/delay.h>
#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
#include "core.h"
#include "dsp.h"
/* ulaw[unsigned char] -> signed 16-bit */
s32 dsp_audio_ulaw_to_s32[256];
/* alaw[unsigned char] -> signed 16-bit */
s32 dsp_audio_alaw_to_s32[256];
s32 *dsp_audio_law_to_s32;
EXPORT_SYMBOL(dsp_audio_law_to_s32);
/* signed 16-bit -> law */
u8 dsp_audio_s16_to_law[65536];
EXPORT_SYMBOL(dsp_audio_s16_to_law);
/* alaw -> ulaw */
u8 dsp_audio_alaw_to_ulaw[256];
/* ulaw -> alaw */
u8 dsp_audio_ulaw_to_alaw[256];
u8 dsp_silence;
/*****************************************************
* generate table for conversion of s16 to alaw/ulaw *
*****************************************************/
#define AMI_MASK 0x55
static inline unsigned char linear2alaw(short int linear)
{
int mask;
int seg;
int pcm_val;
static int seg_end[8] = {
0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
};
pcm_val = linear;
if (pcm_val >= 0) {
/* Sign (7th) bit = 1 */
mask = AMI_MASK | 0x80;
} else {
/* Sign bit = 0 */
mask = AMI_MASK;
pcm_val = -pcm_val;
}
/* Convert the scaled magnitude to segment number. */
for (seg = 0; seg < 8; seg++) {
if (pcm_val <= seg_end[seg])
break;
}
/* Combine the sign, segment, and quantization bits. */
return ((seg << 4) |
((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
}
static inline short int alaw2linear(unsigned char alaw)
{
int i;
int seg;
alaw ^= AMI_MASK;
i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
seg = (((int) alaw & 0x70) >> 4);
if (seg)
i = (i + 0x100) << (seg - 1);
return (short int) ((alaw & 0x80) ? i : -i);
}
static inline short int ulaw2linear(unsigned char ulaw)
{
short mu, e, f, y;
static short etab[] = {0, 132, 396, 924, 1980, 4092, 8316, 16764};
mu = 255 - ulaw;
e = (mu & 0x70) / 16;
f = mu & 0x0f;
y = f * (1 << (e + 3));
y += etab[e];
if (mu & 0x80)
y = -y;
return y;
}
#define BIAS 0x84 /*!< define the add-in bias for 16 bit samples */
static unsigned char linear2ulaw(short sample)
{
static int exp_lut[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
int sign, exponent, mantissa;
unsigned char ulawbyte;
/* Get the sample into sign-magnitude. */
sign = (sample >> 8) & 0x80; /* set aside the sign */
if (sign != 0)
sample = -sample; /* get magnitude */
/* Convert from 16 bit linear to ulaw. */
sample = sample + BIAS;
exponent = exp_lut[(sample >> 7) & 0xFF];
mantissa = (sample >> (exponent + 3)) & 0x0F;
ulawbyte = ~(sign | (exponent << 4) | mantissa);
return ulawbyte;
}
static int reverse_bits(int i)
{
int z, j;
z = 0;
for (j = 0; j < 8; j++) {
if ((i & (1 << j)) != 0)
z |= 1 << (7 - j);
}
return z;
}
void dsp_audio_generate_law_tables(void)
{
int i;
for (i = 0; i < 256; i++)
dsp_audio_alaw_to_s32[i] = alaw2linear(reverse_bits(i));
for (i = 0; i < 256; i++)
dsp_audio_ulaw_to_s32[i] = ulaw2linear(reverse_bits(i));
for (i = 0; i < 256; i++) {
dsp_audio_alaw_to_ulaw[i] =
linear2ulaw(dsp_audio_alaw_to_s32[i]);
dsp_audio_ulaw_to_alaw[i] =
linear2alaw(dsp_audio_ulaw_to_s32[i]);
}
}
void
dsp_audio_generate_s2law_table(void)
{
int i;
if (dsp_options & DSP_OPT_ULAW) {
/* generating ulaw-table */
for (i = -32768; i < 32768; i++) {
dsp_audio_s16_to_law[i & 0xffff] =
reverse_bits(linear2ulaw(i));
}
} else {
/* generating alaw-table */
for (i = -32768; i < 32768; i++) {
dsp_audio_s16_to_law[i & 0xffff] =
reverse_bits(linear2alaw(i));
}
}
}
/*
* the seven bit sample is the number of every second alaw-sample ordered by
* aplitude. 0x00 is negative, 0x7f is positive amplitude.
*/
u8 dsp_audio_seven2law[128];
u8 dsp_audio_law2seven[256];
/********************************************************************
* generate table for conversion law from/to 7-bit alaw-like sample *
********************************************************************/
void
dsp_audio_generate_seven(void)
{
int i, j, k;
u8 spl;
u8 sorted_alaw[256];
/* generate alaw table, sorted by the linear value */
for (i = 0; i < 256; i++) {
j = 0;
for (k = 0; k < 256; k++) {
if (dsp_audio_alaw_to_s32[k]
< dsp_audio_alaw_to_s32[i]) {
j++;
}
}
sorted_alaw[j] = i;
}
/* generate tabels */
for (i = 0; i < 256; i++) {
/* spl is the source: the law-sample (converted to alaw) */
spl = i;
if (dsp_options & DSP_OPT_ULAW)
spl = dsp_audio_ulaw_to_alaw[i];
/* find the 7-bit-sample */
for (j = 0; j < 256; j++) {
if (sorted_alaw[j] == spl)
break;
}
/* write 7-bit audio value */
dsp_audio_law2seven[i] = j >> 1;
}
for (i = 0; i < 128; i++) {
spl = sorted_alaw[i << 1];
if (dsp_options & DSP_OPT_ULAW)
spl = dsp_audio_alaw_to_ulaw[spl];
dsp_audio_seven2law[i] = spl;
}
}
/* mix 2*law -> law */
u8 dsp_audio_mix_law[65536];
/******************************************************
* generate mix table to mix two law samples into one *
******************************************************/
void
dsp_audio_generate_mix_table(void)
{
int i, j;
s32 sample;
i = 0;
while (i < 256) {
j = 0;
while (j < 256) {
sample = dsp_audio_law_to_s32[i];
sample += dsp_audio_law_to_s32[j];
if (sample > 32767)
sample = 32767;
if (sample < -32768)
sample = -32768;
dsp_audio_mix_law[(i<<8)|j] =
dsp_audio_s16_to_law[sample & 0xffff];
j++;
}
i++;
}
}
/*************************************
* generate different volume changes *
*************************************/
static u8 dsp_audio_reduce8[256];
static u8 dsp_audio_reduce7[256];
static u8 dsp_audio_reduce6[256];
static u8 dsp_audio_reduce5[256];
static u8 dsp_audio_reduce4[256];
static u8 dsp_audio_reduce3[256];
static u8 dsp_audio_reduce2[256];
static u8 dsp_audio_reduce1[256];
static u8 dsp_audio_increase1[256];
static u8 dsp_audio_increase2[256];
static u8 dsp_audio_increase3[256];
static u8 dsp_audio_increase4[256];
static u8 dsp_audio_increase5[256];
static u8 dsp_audio_increase6[256];
static u8 dsp_audio_increase7[256];
static u8 dsp_audio_increase8[256];
static u8 *dsp_audio_volume_change[16] = {
dsp_audio_reduce8,
dsp_audio_reduce7,
dsp_audio_reduce6,
dsp_audio_reduce5,
dsp_audio_reduce4,
dsp_audio_reduce3,
dsp_audio_reduce2,
dsp_audio_reduce1,
dsp_audio_increase1,
dsp_audio_increase2,
dsp_audio_increase3,
dsp_audio_increase4,
dsp_audio_increase5,
dsp_audio_increase6,
dsp_audio_increase7,
dsp_audio_increase8,
};
void
dsp_audio_generate_volume_changes(void)
{
register s32 sample;
int i;
int num[] = { 110, 125, 150, 175, 200, 300, 400, 500 };
int denum[] = { 100, 100, 100, 100, 100, 100, 100, 100 };
i = 0;
while (i < 256) {
dsp_audio_reduce8[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[7] / num[7]) & 0xffff];
dsp_audio_reduce7[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[6] / num[6]) & 0xffff];
dsp_audio_reduce6[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[5] / num[5]) & 0xffff];
dsp_audio_reduce5[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[4] / num[4]) & 0xffff];
dsp_audio_reduce4[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[3] / num[3]) & 0xffff];
dsp_audio_reduce3[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[2] / num[2]) & 0xffff];
dsp_audio_reduce2[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[1] / num[1]) & 0xffff];
dsp_audio_reduce1[i] = dsp_audio_s16_to_law[
(dsp_audio_law_to_s32[i] * denum[0] / num[0]) & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[0] / denum[0];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase1[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[1] / denum[1];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase2[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[2] / denum[2];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase3[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[3] / denum[3];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase4[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[4] / denum[4];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase5[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[5] / denum[5];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase6[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[6] / denum[6];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase7[i] = dsp_audio_s16_to_law[sample & 0xffff];
sample = dsp_audio_law_to_s32[i] * num[7] / denum[7];
if (sample < -32768)
sample = -32768;
else if (sample > 32767)
sample = 32767;
dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff];
i++;
}
}
/**************************************
* change the volume of the given skb *
**************************************/
/* this is a helper function for changing volume of skb. the range may be
* -8 to 8, which is a shift to the power of 2. 0 == no volume, 3 == volume*8
*/
void
dsp_change_volume(struct sk_buff *skb, int volume)
{
u8 *volume_change;
int i, ii;
u8 *p;
int shift;
if (volume == 0)
return;
/* get correct conversion table */
if (volume < 0) {
shift = volume + 8;
if (shift < 0)
shift = 0;
} else {
shift = volume + 7;
if (shift > 15)
shift = 15;
}
volume_change = dsp_audio_volume_change[shift];
i = 0;
ii = skb->len;
p = skb->data;
/* change volume */
while (i < ii) {
*p = volume_change[*p];
p++;
i++;
}
}
/*
* SpanDSP - a series of DSP components for telephony
*
* biquad.h - General telephony bi-quad section routines (currently this just
* handles canonic/type 2 form)
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2001 Steve Underwood
*
* 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.
*
*/
struct biquad2_state {
int32_t gain;
int32_t a1;
int32_t a2;
int32_t b1;
int32_t b2;
int32_t z1;
int32_t z2;
};
static inline void biquad2_init(struct biquad2_state *bq,
int32_t gain, int32_t a1, int32_t a2, int32_t b1, int32_t b2)
{
bq->gain = gain;
bq->a1 = a1;
bq->a2 = a2;
bq->b1 = b1;
bq->b2 = b2;
bq->z1 = 0;
bq->z2 = 0;
}
static inline int16_t biquad2(struct biquad2_state *bq, int16_t sample)
{
int32_t y;
int32_t z0;
z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2;
y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2;
bq->z2 = bq->z1;
bq->z1 = z0 >> 15;
y >>= 15;
return y;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* dsp_hwec.h
*/
extern struct mISDN_dsp_element *dsp_hwec;
extern void dsp_hwec_enable(struct dsp *dsp, const char *arg);
extern void dsp_hwec_disable(struct dsp *dsp);
extern int dsp_hwec_init(void);
extern void dsp_hwec_exit(void);
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
*
* Author Karsten Keil <kkeil@novell.com>
*
* Thanks to Jan den Ouden
* Fritz Elfert
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef _MISDN_FSM_H
#define _MISDN_FSM_H
#include <linux/timer.h>
/* Statemachine */
struct FsmInst;
typedef void (*FSMFNPTR)(struct FsmInst *, int, void *);
struct Fsm {
FSMFNPTR *jumpmatrix;
int state_count, event_count;
char **strEvent, **strState;
};
struct FsmInst {
struct Fsm *fsm;
int state;
int debug;
void *userdata;
int userint;
void (*printdebug) (struct FsmInst *, char *, ...);
};
struct FsmNode {
int state, event;
void (*routine) (struct FsmInst *, int, void *);
};
struct FsmTimer {
struct FsmInst *fi;
struct timer_list tl;
int event;
void *arg;
};
extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int);
extern void mISDN_FsmFree(struct Fsm *);
extern int mISDN_FsmEvent(struct FsmInst *, int , void *);
extern void mISDN_FsmChangeState(struct FsmInst *, int);
extern void mISDN_FsmInitTimer(struct FsmInst *, struct FsmTimer *);
extern int mISDN_FsmAddTimer(struct FsmTimer *, int, int, void *, int);
extern void mISDN_FsmRestartTimer(struct FsmTimer *, int, int, void *, int);
extern void mISDN_FsmDelTimer(struct FsmTimer *, int);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
*
* Layer 1 defines
*
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
*/
#define FLG_L1_ACTIVATING 1
#define FLG_L1_ACTIVATED 2
#define FLG_L1_DEACTTIMER 3
#define FLG_L1_ACTTIMER 4
#define FLG_L1_T3RUN 5
#define FLG_L1_PULL_REQ 6
#define FLG_L1_UINT 7
#define FLG_L1_DBLOCKED 8
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册