/* * Author Andreas Eversberg ([email protected]) * Based on source code structure by * Karsten Keil ([email protected]) * * This file is (c) under GNU PUBLIC LICENSE * * Thanks to Karsten Keil (great drivers) * Cologne Chip (great chips) * * This module does: * Real-time tone generation * DTMF detection * Real-time cross-connection and conferrence * Compensate jitter due to system load and hardware fault. * All features are done in kernel space and will be realized * using hardware, if available and supported by chip set. * Blowfish encryption/decryption */ /* STRUCTURE: * * The dsp module provides layer 2 for b-channels (64kbit). It provides * transparent audio forwarding with special digital signal processing: * * - (1) generation of tones * - (2) detection of dtmf tones * - (3) crossconnecting and conferences (clocking) * - (4) echo generation for delay test * - (5) volume control * - (6) disable receive data * - (7) pipeline * - (8) encryption/decryption * * Look: * TX RX * ------upper layer------ * | ^ * | |(6) * v | * +-----+-------------+-----+ * |(3)(4) | * | CMX | * | | * | +-------------+ * | | ^ * | | | * |+---------+| +----+----+ * ||(1) || |(2) | * || || | | * || Tones || | DTMF | * || || | | * || || | | * |+----+----+| +----+----+ * +-----+-----+ ^ * | | * v | * +----+----+ +----+----+ * |(5) | |(5) | * | | | | * |TX Volume| |RX Volume| * | | | | * | | | | * +----+----+ +----+----+ * | ^ * | | * v | * +----+-------------+----+ * |(7) | * | | * | Pipeline Processing | * | | * | | * +----+-------------+----+ * | ^ * | | * v | * +----+----+ +----+----+ * |(8) | |(8) | * | | | | * | Encrypt | | Decrypt | * | | | | * | | | | * +----+----+ +----+----+ * | ^ * | | * v | * ------card layer------ * TX RX * * Above you can see the logical data flow. If software is used to do the * process, it is actually the real data flow. If hardware is used, data * may not flow, but hardware commands to the card, to provide the data flow * as shown. * * NOTE: The channel must be activated in order to make dsp work, even if * no data flow to the upper layer is intended. Activation can be done * after and before controlling the setting using PH_CONTROL requests. * * DTMF: Will be detected by hardware if possible. It is done before CMX * processing. * * Tones: Will be generated via software if endless looped audio fifos are * not supported by hardware. Tones will override all data from CMX. * It is not required to join a conference to use tones at any time. * * CMX: Is transparent when not used. When it is used, it will do * crossconnections and conferences via software if not possible through * hardware. If hardware capability is available, hardware is used. * * Echo: Is generated by CMX and is used to check performance of hard and * software CMX. * * The CMX has special functions for conferences with one, two and more * members. It will allow different types of data flow. Receive and transmit * data to/form upper layer may be switched on/off individually without losing * features of CMX, Tones and DTMF. * * Echo Cancellation: Sometimes we like to cancel echo from the interface. * Note that a VoIP call may not have echo caused by the IP phone. The echo * is generated by the telephone line connected to it. Because the delay * is high, it becomes an echo. RESULT: Echo Cachelation is required if * both echo AND delay is applied to an interface. * Remember that software CMX always generates a more or less delay. * * If all used features can be realized in hardware, and if transmit and/or * receive data ist disabled, the card may not send/receive any data at all. * Not receiving is useful if only announcements are played. Not sending is * useful if an answering machine records audio. Not sending and receiving is * useful during most states of the call. If supported by hardware, tones * will be played without cpu load. Small PBXs and NT-Mode applications will * not need expensive hardware when processing calls. * * * LOCKING: * * When data is received from upper or lower layer (card), the complete dsp * module is locked by a global lock. This lock MUST lock irq, because it * must lock timer events by DSP poll timer. * When data is ready to be transmitted down, the data is queued and sent * outside lock and timer event. * PH_CONTROL must not change any settings, join or split conference members * during process of data. * * HDLC: * * It works quite the same as transparent, except that HDLC data is forwarded * to all other conference members if no hardware bridging is possible. * Send data will be writte to sendq. Sendq will be sent if confirm is received. * Conference cannot join, if one member is not hdlc. * */ #include <linux/delay.h> #include <linux/gfp.h> #include <linux/mISDNif.h> #include <linux/mISDNdsp.h> #include <linux/module.h> #include <linux/vmalloc.h> #include "core.h" #include "dsp.h" static const char *mISDN_dsp_revision = …; static int debug; static int options; static int poll; static int dtmfthreshold = …; MODULE_AUTHOR(…) …; module_param(debug, uint, S_IRUGO | S_IWUSR); module_param(options, uint, S_IRUGO | S_IWUSR); module_param(poll, uint, S_IRUGO | S_IWUSR); module_param(dtmfthreshold, uint, S_IRUGO | S_IWUSR); MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /*int spinnest = 0;*/ DEFINE_SPINLOCK(…); /* global dsp lock */ LIST_HEAD(…); LIST_HEAD(…); int dsp_debug; int dsp_options; int dsp_poll, dsp_tics; /* check if rx may be turned off or must be turned on */ static void dsp_rx_off_member(struct dsp *dsp) { … } static void dsp_rx_off(struct dsp *dsp) { … } /* enable "fill empty" feature */ static void dsp_fill_empty(struct dsp *dsp) { … } static int dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) { … } static void get_features(struct mISDNchannel *ch) { … } static int dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) { … } static int dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) { … } static void dsp_send_bh(struct work_struct *work) { … } static int dspcreate(struct channel_req *crq) { … } static struct Bprotocol DSP = …; static int __init dsp_init(void) { … } static void __exit dsp_cleanup(void) { … } module_init(…) …; module_exit(dsp_cleanup);