/* * Audio crossconnecting/conferrencing (hardware level). * * Copyright 2002 by Andreas Eversberg ([email protected]) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */ /* * The process of adding and removing parties to/from a conference: * * There is a chain of struct dsp_conf which has one or more members in a chain * of struct dsp_conf_member. * * After a party is added, the conference is checked for hardware capability. * Also if a party is removed, the conference is checked again. * * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect * 1-n = hardware-conference. The n will give the conference number. * * Depending on the change after removal or insertion of a party, hardware * commands are given. * * The current solution is stored within the struct dsp_conf entry. */ /* * HOW THE CMX WORKS: * * There are 3 types of interaction: One member is alone, in this case only * data flow from upper to lower layer is done. * Two members will also exchange their data so they are crossconnected. * Three or more members will be added in a conference and will hear each * other but will not receive their own speech (echo) if not enabled. * * Features of CMX are: * - Crossconnecting or even conference, if more than two members are together. * - Force mixing of transmit data with other crossconnect/conference members. * - Echo generation to benchmark the delay of audio processing. * - Use hardware to minimize cpu load, disable FIFO load and minimize delay. * - Dejittering and clock generation. * * There are 2 buffers: * * * RX-Buffer * R W * | | * ----------------+-------------+------------------- * * The rx-buffer is a ring buffer used to store the received data for each * individual member. This is only the case if data needs to be dejittered * or in case of a conference where different clocks require reclocking. * The transmit-clock (R) will read the buffer. * If the clock overruns the write-pointer, we will have a buffer underrun. * If the write pointer always has a certain distance from the transmit- * clock, we will have a delay. The delay will dynamically be increased and * reduced. * * * TX-Buffer * R W * | | * -----------------+--------+----------------------- * * The tx-buffer is a ring buffer to queue the transmit data from user space * until it will be mixed or sent. There are two pointers, R and W. If the write * pointer W would reach or overrun R, the buffer would overrun. In this case * (some) data is dropped so that it will not overrun. * Additionally a dynamic dejittering can be enabled. this allows data from * user space that have jitter and different clock source. * * * Clock: * * A Clock is not required, if the data source has exactly one clock. In this * case the data source is forwarded to the destination. * * A Clock is required, because the data source * - has multiple clocks. * - has no usable clock due to jitter or packet loss (VoIP). * In this case the system's clock is used. The clock resolution depends on * the jiffy resolution. * * If a member joins a conference: * * - If a member joins, its rx_buff is set to silence and change read pointer * to transmit clock. * * The procedure of received data from card is explained in cmx_receive. * The procedure of received data from user space is explained in cmx_transmit. * The procedure of transmit data to card is cmx_send. * * * Interaction with other features: * * DTMF: * DTMF decoding is done before the data is crossconnected. * * Volume change: * Changing rx-volume is done before the data is crossconnected. The tx-volume * must be changed whenever data is transmitted to the card by the cmx. * * Tones: * If a tone is enabled, it will be processed whenever data is transmitted to * the card. It will replace the tx-data from the user space. * If tones are generated by hardware, this conference member is removed for * this time. * * Disable rx-data: * If cmx is realized in hardware, rx data will be disabled if requested by * the upper layer. If dtmf decoding is done by software and enabled, rx data * will not be disabled but blocked to the upper layer. * * HFC conference engine: * If it is possible to realize all features using hardware, hardware will be * used if not forbidden by control command. Disabling rx-data provides * absolutely traffic free audio processing. (except for the quick 1-frame * upload of a tone loop, only once for a new tone) * */ /* delay.h is required for hw_lock.h */ #include <linux/slab.h> #include <linux/delay.h> #include <linux/mISDNif.h> #include <linux/mISDNdsp.h> #include "core.h" #include "dsp.h" /* * debugging of multi party conference, * by using conference even with two members */ /* #define CMX_CONF_DEBUG */ /*#define CMX_DEBUG * massive read/write pointer output */ /*#define CMX_DELAY_DEBUG * gives rx-buffer delay overview */ /*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */ /* * debug cmx memory structure */ void dsp_cmx_debug(struct dsp *dsp) { … } /* * search conference */ static struct dsp_conf * dsp_cmx_search_conf(u32 id) { … } /* * add member to conference */ static int dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf) { … } /* * del member from conference */ int dsp_cmx_del_conf_member(struct dsp *dsp) { … } /* * new conference */ static struct dsp_conf *dsp_cmx_new_conf(u32 id) { … } /* * del conference */ int dsp_cmx_del_conf(struct dsp_conf *conf) { … } /* * send HW message to hfc card */ static void dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2, u32 param3, u32 param4) { … } /* * do hardware update and set the software/hardware flag * * either a conference or a dsp instance can be given * if only dsp instance is given, the instance is not associated with a conf * and therefore removed. if a conference is given, the dsp is expected to * be member of that conference. */ void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) { … } /* * conf_id != 0: join or change conference * conf_id == 0: split from conference if not already */ int dsp_cmx_conf(struct dsp *dsp, u32 conf_id) { … } #ifdef CMX_DELAY_DEBUG int delaycount; static void showdelay(struct dsp *dsp, int samples, int delay) { char bar[] = "--------------------------------------------------|"; int sdelay; delaycount += samples; if (delaycount < 8000) return; delaycount = 0; sdelay = delay * 50 / (dsp_poll << 2); printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay, sdelay > 50 ? "..." : bar + 50 - sdelay); } #endif /* * audio data is received from card */ void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) { … } /* * send (mixed) audio data to card and control jitter */ static void dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) { … } static u32 jittercount; /* counter for jitter check */ struct timer_list dsp_spl_tl; unsigned long dsp_spl_jiffies; /* calculate the next time to fire */ static u16 dsp_count; /* last sample count */ static int dsp_count_valid; /* if we have last sample count */ void dsp_cmx_send(struct timer_list *arg) { … } /* * audio data is transmitted from upper layer to the dsp */ void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb) { … } /* * hdlc data is received from card and sent to all members. */ void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb) { … }