brintos

brintos / linux-shallow public Read only

0
0
Text · 33.0 KiB · 753232e Raw
1228 lines · c
1/*2 * Author       Andreas Eversberg (jolly@eversberg.eu)3 * Based on source code structure by4 *		Karsten Keil (keil@isdn4linux.de)5 *6 *		This file is (c) under GNU PUBLIC LICENSE7 *8 * Thanks to    Karsten Keil (great drivers)9 *              Cologne Chip (great chips)10 *11 * This module does:12 *		Real-time tone generation13 *		DTMF detection14 *		Real-time cross-connection and conferrence15 *		Compensate jitter due to system load and hardware fault.16 *		All features are done in kernel space and will be realized17 *		using hardware, if available and supported by chip set.18 *		Blowfish encryption/decryption19 */20 21/* STRUCTURE:22 *23 * The dsp module provides layer 2 for b-channels (64kbit). It provides24 * transparent audio forwarding with special digital signal processing:25 *26 * - (1) generation of tones27 * - (2) detection of dtmf tones28 * - (3) crossconnecting and conferences (clocking)29 * - (4) echo generation for delay test30 * - (5) volume control31 * - (6) disable receive data32 * - (7) pipeline33 * - (8) encryption/decryption34 *35 * Look:36 *             TX            RX37 *         ------upper layer------38 *             |             ^39 *             |             |(6)40 *             v             |41 *       +-----+-------------+-----+42 *       |(3)(4)                   |43 *       |           CMX           |44 *       |                         |45 *       |           +-------------+46 *       |           |       ^47 *       |           |       |48 *       |+---------+|  +----+----+49 *       ||(1)      ||  |(2)      |50 *       ||         ||  |         |51 *       ||  Tones  ||  |  DTMF   |52 *       ||         ||  |         |53 *       ||         ||  |         |54 *       |+----+----+|  +----+----+55 *       +-----+-----+       ^56 *             |             |57 *             v             |58 *        +----+----+   +----+----+59 *        |(5)      |   |(5)      |60 *        |         |   |         |61 *        |TX Volume|   |RX Volume|62 *        |         |   |         |63 *        |         |   |         |64 *        +----+----+   +----+----+65 *             |             ^66 *             |             |67 *             v             |68 *        +----+-------------+----+69 *        |(7)                    |70 *        |                       |71 *        |  Pipeline Processing  |72 *        |                       |73 *        |                       |74 *        +----+-------------+----+75 *             |             ^76 *             |             |77 *             v             |78 *        +----+----+   +----+----+79 *        |(8)      |   |(8)      |80 *        |         |   |         |81 *        | Encrypt |   | Decrypt |82 *        |         |   |         |83 *        |         |   |         |84 *        +----+----+   +----+----+85 *             |             ^86 *             |             |87 *             v             |88 *         ------card  layer------89 *             TX            RX90 *91 * Above you can see the logical data flow. If software is used to do the92 * process, it is actually the real data flow. If hardware is used, data93 * may not flow, but hardware commands to the card, to provide the data flow94 * as shown.95 *96 * NOTE: The channel must be activated in order to make dsp work, even if97 * no data flow to the upper layer is intended. Activation can be done98 * after and before controlling the setting using PH_CONTROL requests.99 *100 * DTMF: Will be detected by hardware if possible. It is done before CMX101 * processing.102 *103 * Tones: Will be generated via software if endless looped audio fifos are104 * not supported by hardware. Tones will override all data from CMX.105 * It is not required to join a conference to use tones at any time.106 *107 * CMX: Is transparent when not used. When it is used, it will do108 * crossconnections and conferences via software if not possible through109 * hardware. If hardware capability is available, hardware is used.110 *111 * Echo: Is generated by CMX and is used to check performance of hard and112 * software CMX.113 *114 * The CMX has special functions for conferences with one, two and more115 * members. It will allow different types of data flow. Receive and transmit116 * data to/form upper layer may be switched on/off individually without losing117 * features of CMX, Tones and DTMF.118 *119 * Echo Cancellation: Sometimes we like to cancel echo from the interface.120 * Note that a VoIP call may not have echo caused by the IP phone. The echo121 * is generated by the telephone line connected to it. Because the delay122 * is high, it becomes an echo. RESULT: Echo Cachelation is required if123 * both echo AND delay is applied to an interface.124 * Remember that software CMX always generates a more or less delay.125 *126 * If all used features can be realized in hardware, and if transmit and/or127 * receive data ist disabled, the card may not send/receive any data at all.128 * Not receiving is useful if only announcements are played. Not sending is129 * useful if an answering machine records audio. Not sending and receiving is130 * useful during most states of the call. If supported by hardware, tones131 * will be played without cpu load. Small PBXs and NT-Mode applications will132 * not need expensive hardware when processing calls.133 *134 *135 * LOCKING:136 *137 * When data is received from upper or lower layer (card), the complete dsp138 * module is locked by a global lock.  This lock MUST lock irq, because it139 * must lock timer events by DSP poll timer.140 * When data is ready to be transmitted down, the data is queued and sent141 * outside lock and timer event.142 * PH_CONTROL must not change any settings, join or split conference members143 * during process of data.144 *145 * HDLC:146 *147 * It works quite the same as transparent, except that HDLC data is forwarded148 * to all other conference members if no hardware bridging is possible.149 * Send data will be writte to sendq. Sendq will be sent if confirm is received.150 * Conference cannot join, if one member is not hdlc.151 *152 */153 154#include <linux/delay.h>155#include <linux/gfp.h>156#include <linux/mISDNif.h>157#include <linux/mISDNdsp.h>158#include <linux/module.h>159#include <linux/vmalloc.h>160#include "core.h"161#include "dsp.h"162 163static const char *mISDN_dsp_revision = "2.0";164 165static int debug;166static int options;167static int poll;168static int dtmfthreshold = 100;169 170MODULE_AUTHOR("Andreas Eversberg");171module_param(debug, uint, S_IRUGO | S_IWUSR);172module_param(options, uint, S_IRUGO | S_IWUSR);173module_param(poll, uint, S_IRUGO | S_IWUSR);174module_param(dtmfthreshold, uint, S_IRUGO | S_IWUSR);175MODULE_DESCRIPTION("mISDN driver for Digital Audio Processing of transparent data");176MODULE_LICENSE("GPL");177 178/*int spinnest = 0;*/179 180DEFINE_SPINLOCK(dsp_lock); /* global dsp lock */181LIST_HEAD(dsp_ilist);182LIST_HEAD(conf_ilist);183int dsp_debug;184int dsp_options;185int dsp_poll, dsp_tics;186 187/* check if rx may be turned off or must be turned on */188static void189dsp_rx_off_member(struct dsp *dsp)190{191	struct mISDN_ctrl_req	cq;192	int rx_off = 1;193 194	memset(&cq, 0, sizeof(cq));195 196	if (!dsp->features_rx_off)197		return;198 199	/* not disabled */200	if (!dsp->rx_disabled)201		rx_off = 0;202	/* software dtmf */203	else if (dsp->dtmf.software)204		rx_off = 0;205	/* echo in software */206	else if (dsp->echo.software)207		rx_off = 0;208	/* bridge in software */209	else if (dsp->conf && dsp->conf->software)210		rx_off = 0;211	/* data is not required by user space and not required212	 * for echo dtmf detection, soft-echo, soft-bridging */213 214	if (rx_off == dsp->rx_is_off)215		return;216 217	if (!dsp->ch.peer) {218		if (dsp_debug & DEBUG_DSP_CORE)219			printk(KERN_DEBUG "%s: no peer, no rx_off\n",220			       __func__);221		return;222	}223	cq.op = MISDN_CTRL_RX_OFF;224	cq.p1 = rx_off;225	if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {226		printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n",227		       __func__);228		return;229	}230	dsp->rx_is_off = rx_off;231	if (dsp_debug & DEBUG_DSP_CORE)232		printk(KERN_DEBUG "%s: %s set rx_off = %d\n",233		       __func__, dsp->name, rx_off);234}235static void236dsp_rx_off(struct dsp *dsp)237{238	struct dsp_conf_member	*member;239 240	if (dsp_options & DSP_OPT_NOHARDWARE)241		return;242 243	/* no conf */244	if (!dsp->conf) {245		dsp_rx_off_member(dsp);246		return;247	}248	/* check all members in conf */249	list_for_each_entry(member, &dsp->conf->mlist, list) {250		dsp_rx_off_member(member->dsp);251	}252}253 254/* enable "fill empty" feature */255static void256dsp_fill_empty(struct dsp *dsp)257{258	struct mISDN_ctrl_req	cq;259 260	memset(&cq, 0, sizeof(cq));261 262	if (!dsp->ch.peer) {263		if (dsp_debug & DEBUG_DSP_CORE)264			printk(KERN_DEBUG "%s: no peer, no fill_empty\n",265			       __func__);266		return;267	}268	cq.op = MISDN_CTRL_FILL_EMPTY;269	cq.p1 = 1;270	cq.p2 = dsp_silence;271	if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {272		printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",273		       __func__);274		return;275	}276	if (dsp_debug & DEBUG_DSP_CORE)277		printk(KERN_DEBUG "%s: %s set fill_empty = 1\n",278		       __func__, dsp->name);279}280 281static int282dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)283{284	struct sk_buff	*nskb;285	int ret = 0;286	int cont;287	u8 *data;288	int len;289 290	if (skb->len < sizeof(int)) {291		printk(KERN_ERR "%s: PH_CONTROL message too short\n", __func__);292		return -EINVAL;293	}294	cont = *((int *)skb->data);295	len = skb->len - sizeof(int);296	data = skb->data + sizeof(int);297 298	switch (cont) {299	case DTMF_TONE_START: /* turn on DTMF */300		if (dsp->hdlc) {301			ret = -EINVAL;302			break;303		}304		if (dsp_debug & DEBUG_DSP_CORE)305			printk(KERN_DEBUG "%s: start dtmf\n", __func__);306		if (len == sizeof(int)) {307			if (dsp_debug & DEBUG_DSP_CORE)308				printk(KERN_NOTICE "changing DTMF Threshold "309				       "to %d\n", *((int *)data));310			dsp->dtmf.treshold = (*(int *)data) * 10000;311		}312		dsp->dtmf.enable = 1;313		/* init goertzel */314		dsp_dtmf_goertzel_init(dsp);315 316		/* check dtmf hardware */317		dsp_dtmf_hardware(dsp);318		dsp_rx_off(dsp);319		break;320	case DTMF_TONE_STOP: /* turn off DTMF */321		if (dsp_debug & DEBUG_DSP_CORE)322			printk(KERN_DEBUG "%s: stop dtmf\n", __func__);323		dsp->dtmf.enable = 0;324		dsp->dtmf.hardware = 0;325		dsp->dtmf.software = 0;326		break;327	case DSP_CONF_JOIN: /* join / update conference */328		if (len < sizeof(int)) {329			ret = -EINVAL;330			break;331		}332		if (*((u32 *)data) == 0)333			goto conf_split;334		if (dsp_debug & DEBUG_DSP_CORE)335			printk(KERN_DEBUG "%s: join conference %d\n",336			       __func__, *((u32 *)data));337		ret = dsp_cmx_conf(dsp, *((u32 *)data));338		/* dsp_cmx_hardware will also be called here */339		dsp_rx_off(dsp);340		if (dsp_debug & DEBUG_DSP_CMX)341			dsp_cmx_debug(dsp);342		break;343	case DSP_CONF_SPLIT: /* remove from conference */344	conf_split:345		if (dsp_debug & DEBUG_DSP_CORE)346			printk(KERN_DEBUG "%s: release conference\n", __func__);347		ret = dsp_cmx_conf(dsp, 0);348		/* dsp_cmx_hardware will also be called here */349		if (dsp_debug & DEBUG_DSP_CMX)350			dsp_cmx_debug(dsp);351		dsp_rx_off(dsp);352		break;353	case DSP_TONE_PATT_ON: /* play tone */354		if (dsp->hdlc) {355			ret = -EINVAL;356			break;357		}358		if (len < sizeof(int)) {359			ret = -EINVAL;360			break;361		}362		if (dsp_debug & DEBUG_DSP_CORE)363			printk(KERN_DEBUG "%s: turn tone 0x%x on\n",364			       __func__, *((int *)skb->data));365		ret = dsp_tone(dsp, *((int *)data));366		if (!ret) {367			dsp_cmx_hardware(dsp->conf, dsp);368			dsp_rx_off(dsp);369		}370		if (!dsp->tone.tone)371			goto tone_off;372		break;373	case DSP_TONE_PATT_OFF: /* stop tone */374		if (dsp->hdlc) {375			ret = -EINVAL;376			break;377		}378		if (dsp_debug & DEBUG_DSP_CORE)379			printk(KERN_DEBUG "%s: turn tone off\n", __func__);380		dsp_tone(dsp, 0);381		dsp_cmx_hardware(dsp->conf, dsp);382		dsp_rx_off(dsp);383		/* reset tx buffers (user space data) */384	tone_off:385		dsp->rx_W = 0;386		dsp->rx_R = 0;387		break;388	case DSP_VOL_CHANGE_TX: /* change volume */389		if (dsp->hdlc) {390			ret = -EINVAL;391			break;392		}393		if (len < sizeof(int)) {394			ret = -EINVAL;395			break;396		}397		dsp->tx_volume = *((int *)data);398		if (dsp_debug & DEBUG_DSP_CORE)399			printk(KERN_DEBUG "%s: change tx vol to %d\n",400			       __func__, dsp->tx_volume);401		dsp_cmx_hardware(dsp->conf, dsp);402		dsp_dtmf_hardware(dsp);403		dsp_rx_off(dsp);404		break;405	case DSP_VOL_CHANGE_RX: /* change volume */406		if (dsp->hdlc) {407			ret = -EINVAL;408			break;409		}410		if (len < sizeof(int)) {411			ret = -EINVAL;412			break;413		}414		dsp->rx_volume = *((int *)data);415		if (dsp_debug & DEBUG_DSP_CORE)416			printk(KERN_DEBUG "%s: change rx vol to %d\n",417			       __func__, dsp->tx_volume);418		dsp_cmx_hardware(dsp->conf, dsp);419		dsp_dtmf_hardware(dsp);420		dsp_rx_off(dsp);421		break;422	case DSP_ECHO_ON: /* enable echo */423		dsp->echo.software = 1; /* soft echo */424		if (dsp_debug & DEBUG_DSP_CORE)425			printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__);426		dsp_cmx_hardware(dsp->conf, dsp);427		dsp_rx_off(dsp);428		if (dsp_debug & DEBUG_DSP_CMX)429			dsp_cmx_debug(dsp);430		break;431	case DSP_ECHO_OFF: /* disable echo */432		dsp->echo.software = 0;433		dsp->echo.hardware = 0;434		if (dsp_debug & DEBUG_DSP_CORE)435			printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__);436		dsp_cmx_hardware(dsp->conf, dsp);437		dsp_rx_off(dsp);438		if (dsp_debug & DEBUG_DSP_CMX)439			dsp_cmx_debug(dsp);440		break;441	case DSP_RECEIVE_ON: /* enable receive to user space */442		if (dsp_debug & DEBUG_DSP_CORE)443			printk(KERN_DEBUG "%s: enable receive to user "444			       "space\n", __func__);445		dsp->rx_disabled = 0;446		dsp_rx_off(dsp);447		break;448	case DSP_RECEIVE_OFF: /* disable receive to user space */449		if (dsp_debug & DEBUG_DSP_CORE)450			printk(KERN_DEBUG "%s: disable receive to "451			       "user space\n", __func__);452		dsp->rx_disabled = 1;453		dsp_rx_off(dsp);454		break;455	case DSP_MIX_ON: /* enable mixing of tx data */456		if (dsp->hdlc) {457			ret = -EINVAL;458			break;459		}460		if (dsp_debug & DEBUG_DSP_CORE)461			printk(KERN_DEBUG "%s: enable mixing of "462			       "tx-data with conf members\n", __func__);463		dsp->tx_mix = 1;464		dsp_cmx_hardware(dsp->conf, dsp);465		dsp_rx_off(dsp);466		if (dsp_debug & DEBUG_DSP_CMX)467			dsp_cmx_debug(dsp);468		break;469	case DSP_MIX_OFF: /* disable mixing of tx data */470		if (dsp->hdlc) {471			ret = -EINVAL;472			break;473		}474		if (dsp_debug & DEBUG_DSP_CORE)475			printk(KERN_DEBUG "%s: disable mixing of "476			       "tx-data with conf members\n", __func__);477		dsp->tx_mix = 0;478		dsp_cmx_hardware(dsp->conf, dsp);479		dsp_rx_off(dsp);480		if (dsp_debug & DEBUG_DSP_CMX)481			dsp_cmx_debug(dsp);482		break;483	case DSP_TXDATA_ON: /* enable txdata */484		dsp->tx_data = 1;485		if (dsp_debug & DEBUG_DSP_CORE)486			printk(KERN_DEBUG "%s: enable tx-data\n", __func__);487		dsp_cmx_hardware(dsp->conf, dsp);488		dsp_rx_off(dsp);489		if (dsp_debug & DEBUG_DSP_CMX)490			dsp_cmx_debug(dsp);491		break;492	case DSP_TXDATA_OFF: /* disable txdata */493		dsp->tx_data = 0;494		if (dsp_debug & DEBUG_DSP_CORE)495			printk(KERN_DEBUG "%s: disable tx-data\n", __func__);496		dsp_cmx_hardware(dsp->conf, dsp);497		dsp_rx_off(dsp);498		if (dsp_debug & DEBUG_DSP_CMX)499			dsp_cmx_debug(dsp);500		break;501	case DSP_DELAY: /* use delay algorithm instead of dynamic502			   jitter algorithm */503		if (dsp->hdlc) {504			ret = -EINVAL;505			break;506		}507		if (len < sizeof(int)) {508			ret = -EINVAL;509			break;510		}511		dsp->cmx_delay = (*((int *)data)) << 3;512		/* milliseconds to samples */513		if (dsp->cmx_delay >= (CMX_BUFF_HALF >> 1))514			/* clip to half of maximum usable buffer515			   (half of half buffer) */516			dsp->cmx_delay = (CMX_BUFF_HALF >> 1) - 1;517		if (dsp_debug & DEBUG_DSP_CORE)518			printk(KERN_DEBUG "%s: use delay algorithm to "519			       "compensate jitter (%d samples)\n",520			       __func__, dsp->cmx_delay);521		break;522	case DSP_JITTER: /* use dynamic jitter algorithm instead of523			    delay algorithm */524		if (dsp->hdlc) {525			ret = -EINVAL;526			break;527		}528		dsp->cmx_delay = 0;529		if (dsp_debug & DEBUG_DSP_CORE)530			printk(KERN_DEBUG "%s: use jitter algorithm to "531			       "compensate jitter\n", __func__);532		break;533	case DSP_TX_DEJITTER: /* use dynamic jitter algorithm for tx-buffer */534		if (dsp->hdlc) {535			ret = -EINVAL;536			break;537		}538		dsp->tx_dejitter = 1;539		if (dsp_debug & DEBUG_DSP_CORE)540			printk(KERN_DEBUG "%s: use dejitter on TX "541			       "buffer\n", __func__);542		break;543	case DSP_TX_DEJ_OFF: /* use tx-buffer without dejittering*/544		if (dsp->hdlc) {545			ret = -EINVAL;546			break;547		}548		dsp->tx_dejitter = 0;549		if (dsp_debug & DEBUG_DSP_CORE)550			printk(KERN_DEBUG "%s: use TX buffer without "551			       "dejittering\n", __func__);552		break;553	case DSP_PIPELINE_CFG:554		if (dsp->hdlc) {555			ret = -EINVAL;556			break;557		}558		if (len > 0 && ((char *)data)[len - 1]) {559			printk(KERN_DEBUG "%s: pipeline config string "560			       "is not NULL terminated!\n", __func__);561			ret = -EINVAL;562		} else {563			dsp->pipeline.inuse = 1;564			dsp_cmx_hardware(dsp->conf, dsp);565			ret = dsp_pipeline_build(&dsp->pipeline,566						 len > 0 ? data : NULL);567			dsp_cmx_hardware(dsp->conf, dsp);568			dsp_rx_off(dsp);569		}570		break;571	case DSP_BF_ENABLE_KEY: /* turn blowfish on */572		if (dsp->hdlc) {573			ret = -EINVAL;574			break;575		}576		if (len < 4 || len > 56) {577			ret = -EINVAL;578			break;579		}580		if (dsp_debug & DEBUG_DSP_CORE)581			printk(KERN_DEBUG "%s: turn blowfish on (key "582			       "not shown)\n", __func__);583		ret = dsp_bf_init(dsp, (u8 *)data, len);584		/* set new cont */585		if (!ret)586			cont = DSP_BF_ACCEPT;587		else588			cont = DSP_BF_REJECT;589		/* send indication if it worked to set it */590		nskb = _alloc_mISDN_skb(PH_CONTROL_IND, MISDN_ID_ANY,591					sizeof(int), &cont, GFP_ATOMIC);592		if (nskb) {593			if (dsp->up) {594				if (dsp->up->send(dsp->up, nskb))595					dev_kfree_skb(nskb);596			} else597				dev_kfree_skb(nskb);598		}599		if (!ret) {600			dsp_cmx_hardware(dsp->conf, dsp);601			dsp_dtmf_hardware(dsp);602			dsp_rx_off(dsp);603		}604		break;605	case DSP_BF_DISABLE: /* turn blowfish off */606		if (dsp->hdlc) {607			ret = -EINVAL;608			break;609		}610		if (dsp_debug & DEBUG_DSP_CORE)611			printk(KERN_DEBUG "%s: turn blowfish off\n", __func__);612		dsp_bf_cleanup(dsp);613		dsp_cmx_hardware(dsp->conf, dsp);614		dsp_dtmf_hardware(dsp);615		dsp_rx_off(dsp);616		break;617	default:618		if (dsp_debug & DEBUG_DSP_CORE)619			printk(KERN_DEBUG "%s: ctrl req %x unhandled\n",620			       __func__, cont);621		ret = -EINVAL;622	}623	return ret;624}625 626static void627get_features(struct mISDNchannel *ch)628{629	struct dsp		*dsp = container_of(ch, struct dsp, ch);630	struct mISDN_ctrl_req	cq;631 632	if (!ch->peer) {633		if (dsp_debug & DEBUG_DSP_CORE)634			printk(KERN_DEBUG "%s: no peer, no features\n",635			       __func__);636		return;637	}638	memset(&cq, 0, sizeof(cq));639	cq.op = MISDN_CTRL_GETOP;640	if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq) < 0) {641		printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",642		       __func__);643		return;644	}645	if (cq.op & MISDN_CTRL_RX_OFF)646		dsp->features_rx_off = 1;647	if (cq.op & MISDN_CTRL_FILL_EMPTY)648		dsp->features_fill_empty = 1;649	if (dsp_options & DSP_OPT_NOHARDWARE)650		return;651	if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) {652		cq.op = MISDN_CTRL_HW_FEATURES;653		*((u_long *)&cq.p1) = (u_long)&dsp->features;654		if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq)) {655			printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n",656			       __func__);657		}658	} else659		if (dsp_debug & DEBUG_DSP_CORE)660			printk(KERN_DEBUG "%s: features not supported for %s\n",661			       __func__, dsp->name);662}663 664static int665dsp_function(struct mISDNchannel *ch,  struct sk_buff *skb)666{667	struct dsp		*dsp = container_of(ch, struct dsp, ch);668	struct mISDNhead	*hh;669	int			ret = 0;670	u8			*digits = NULL;671	u_long			flags;672 673	hh = mISDN_HEAD_P(skb);674	switch (hh->prim) {675		/* FROM DOWN */676	case (PH_DATA_CNF):677		dsp->data_pending = 0;678		/* trigger next hdlc frame, if any */679		if (dsp->hdlc) {680			spin_lock_irqsave(&dsp_lock, flags);681			if (dsp->b_active)682				schedule_work(&dsp->workq);683			spin_unlock_irqrestore(&dsp_lock, flags);684		}685		break;686	case (PH_DATA_IND):687	case (DL_DATA_IND):688		if (skb->len < 1) {689			ret = -EINVAL;690			break;691		}692		if (dsp->rx_is_off) {693			if (dsp_debug & DEBUG_DSP_CORE)694				printk(KERN_DEBUG "%s: rx-data during rx_off"695				       " for %s\n",696				       __func__, dsp->name);697		}698		if (dsp->hdlc) {699			/* hdlc */700			spin_lock_irqsave(&dsp_lock, flags);701			dsp_cmx_hdlc(dsp, skb);702			spin_unlock_irqrestore(&dsp_lock, flags);703			if (dsp->rx_disabled) {704				/* if receive is not allowed */705				break;706			}707			hh->prim = DL_DATA_IND;708			if (dsp->up)709				return dsp->up->send(dsp->up, skb);710			break;711		}712 713		spin_lock_irqsave(&dsp_lock, flags);714 715		/* decrypt if enabled */716		if (dsp->bf_enable)717			dsp_bf_decrypt(dsp, skb->data, skb->len);718		/* pipeline */719		if (dsp->pipeline.inuse)720			dsp_pipeline_process_rx(&dsp->pipeline, skb->data,721						skb->len, hh->id);722		/* change volume if requested */723		if (dsp->rx_volume)724			dsp_change_volume(skb, dsp->rx_volume);725		/* check if dtmf soft decoding is turned on */726		if (dsp->dtmf.software) {727			digits = dsp_dtmf_goertzel_decode(dsp, skb->data,728							  skb->len, (dsp_options & DSP_OPT_ULAW) ? 1 : 0);729		}730		/* we need to process receive data if software */731		if (dsp->conf && dsp->conf->software) {732			/* process data from card at cmx */733			dsp_cmx_receive(dsp, skb);734		}735 736		spin_unlock_irqrestore(&dsp_lock, flags);737 738		/* send dtmf result, if any */739		if (digits) {740			while (*digits) {741				int k;742				struct sk_buff *nskb;743				if (dsp_debug & DEBUG_DSP_DTMF)744					printk(KERN_DEBUG "%s: digit"745					       "(%c) to layer %s\n",746					       __func__, *digits, dsp->name);747				k = *digits | DTMF_TONE_VAL;748				nskb = _alloc_mISDN_skb(PH_CONTROL_IND,749							MISDN_ID_ANY, sizeof(int), &k,750							GFP_ATOMIC);751				if (nskb) {752					if (dsp->up) {753						if (dsp->up->send(754							    dsp->up, nskb))755							dev_kfree_skb(nskb);756					} else757						dev_kfree_skb(nskb);758				}759				digits++;760			}761		}762		if (dsp->rx_disabled) {763			/* if receive is not allowed */764			break;765		}766		hh->prim = DL_DATA_IND;767		if (dsp->up)768			return dsp->up->send(dsp->up, skb);769		break;770	case (PH_CONTROL_IND):771		if (dsp_debug & DEBUG_DSP_DTMFCOEFF)772			printk(KERN_DEBUG "%s: PH_CONTROL INDICATION "773			       "received: %x (len %d) %s\n", __func__,774			       hh->id, skb->len, dsp->name);775		switch (hh->id) {776		case (DTMF_HFC_COEF): /* getting coefficients */777			if (!dsp->dtmf.hardware) {778				if (dsp_debug & DEBUG_DSP_DTMFCOEFF)779					printk(KERN_DEBUG "%s: ignoring DTMF "780					       "coefficients from HFC\n",781					       __func__);782				break;783			}784			digits = dsp_dtmf_goertzel_decode(dsp, skb->data,785							  skb->len, 2);786			while (*digits) {787				int k;788				struct sk_buff *nskb;789				if (dsp_debug & DEBUG_DSP_DTMF)790					printk(KERN_DEBUG "%s: digit"791					       "(%c) to layer %s\n",792					       __func__, *digits, dsp->name);793				k = *digits | DTMF_TONE_VAL;794				nskb = _alloc_mISDN_skb(PH_CONTROL_IND,795							MISDN_ID_ANY, sizeof(int), &k,796							GFP_ATOMIC);797				if (nskb) {798					if (dsp->up) {799						if (dsp->up->send(800							    dsp->up, nskb))801							dev_kfree_skb(nskb);802					} else803						dev_kfree_skb(nskb);804				}805				digits++;806			}807			break;808		case (HFC_VOL_CHANGE_TX): /* change volume */809			if (skb->len != sizeof(int)) {810				ret = -EINVAL;811				break;812			}813			spin_lock_irqsave(&dsp_lock, flags);814			dsp->tx_volume = *((int *)skb->data);815			if (dsp_debug & DEBUG_DSP_CORE)816				printk(KERN_DEBUG "%s: change tx volume to "817				       "%d\n", __func__, dsp->tx_volume);818			dsp_cmx_hardware(dsp->conf, dsp);819			dsp_dtmf_hardware(dsp);820			dsp_rx_off(dsp);821			spin_unlock_irqrestore(&dsp_lock, flags);822			break;823		default:824			if (dsp_debug & DEBUG_DSP_CORE)825				printk(KERN_DEBUG "%s: ctrl ind %x unhandled "826				       "%s\n", __func__, hh->id, dsp->name);827			ret = -EINVAL;828		}829		break;830	case (PH_ACTIVATE_IND):831	case (PH_ACTIVATE_CNF):832		if (dsp_debug & DEBUG_DSP_CORE)833			printk(KERN_DEBUG "%s: b_channel is now active %s\n",834			       __func__, dsp->name);835		/* bchannel now active */836		spin_lock_irqsave(&dsp_lock, flags);837		dsp->b_active = 1;838		dsp->data_pending = 0;839		dsp->rx_init = 1;840		/* rx_W and rx_R will be adjusted on first frame */841		dsp->rx_W = 0;842		dsp->rx_R = 0;843		memset(dsp->rx_buff, 0, sizeof(dsp->rx_buff));844		dsp_cmx_hardware(dsp->conf, dsp);845		dsp_dtmf_hardware(dsp);846		dsp_rx_off(dsp);847		spin_unlock_irqrestore(&dsp_lock, flags);848		if (dsp_debug & DEBUG_DSP_CORE)849			printk(KERN_DEBUG "%s: done with activation, sending "850			       "confirm to user space. %s\n", __func__,851			       dsp->name);852		/* send activation to upper layer */853		hh->prim = DL_ESTABLISH_CNF;854		if (dsp->up)855			return dsp->up->send(dsp->up, skb);856		break;857	case (PH_DEACTIVATE_IND):858	case (PH_DEACTIVATE_CNF):859		if (dsp_debug & DEBUG_DSP_CORE)860			printk(KERN_DEBUG "%s: b_channel is now inactive %s\n",861			       __func__, dsp->name);862		/* bchannel now inactive */863		spin_lock_irqsave(&dsp_lock, flags);864		dsp->b_active = 0;865		dsp->data_pending = 0;866		dsp_cmx_hardware(dsp->conf, dsp);867		dsp_rx_off(dsp);868		spin_unlock_irqrestore(&dsp_lock, flags);869		hh->prim = DL_RELEASE_CNF;870		if (dsp->up)871			return dsp->up->send(dsp->up, skb);872		break;873		/* FROM UP */874	case (DL_DATA_REQ):875	case (PH_DATA_REQ):876		if (skb->len < 1) {877			ret = -EINVAL;878			break;879		}880		if (dsp->hdlc) {881			/* hdlc */882			if (!dsp->b_active) {883				ret = -EIO;884				break;885			}886			hh->prim = PH_DATA_REQ;887			spin_lock_irqsave(&dsp_lock, flags);888			skb_queue_tail(&dsp->sendq, skb);889			schedule_work(&dsp->workq);890			spin_unlock_irqrestore(&dsp_lock, flags);891			return 0;892		}893		/* send data to tx-buffer (if no tone is played) */894		if (!dsp->tone.tone) {895			spin_lock_irqsave(&dsp_lock, flags);896			dsp_cmx_transmit(dsp, skb);897			spin_unlock_irqrestore(&dsp_lock, flags);898		}899		break;900	case (PH_CONTROL_REQ):901		spin_lock_irqsave(&dsp_lock, flags);902		ret = dsp_control_req(dsp, hh, skb);903		spin_unlock_irqrestore(&dsp_lock, flags);904		break;905	case (DL_ESTABLISH_REQ):906	case (PH_ACTIVATE_REQ):907		if (dsp_debug & DEBUG_DSP_CORE)908			printk(KERN_DEBUG "%s: activating b_channel %s\n",909			       __func__, dsp->name);910		if (dsp->dtmf.hardware || dsp->dtmf.software)911			dsp_dtmf_goertzel_init(dsp);912		get_features(ch);913		/* enable fill_empty feature */914		if (dsp->features_fill_empty)915			dsp_fill_empty(dsp);916		/* send ph_activate */917		hh->prim = PH_ACTIVATE_REQ;918		if (ch->peer)919			return ch->recv(ch->peer, skb);920		break;921	case (DL_RELEASE_REQ):922	case (PH_DEACTIVATE_REQ):923		if (dsp_debug & DEBUG_DSP_CORE)924			printk(KERN_DEBUG "%s: releasing b_channel %s\n",925			       __func__, dsp->name);926		spin_lock_irqsave(&dsp_lock, flags);927		dsp->tone.tone = 0;928		dsp->tone.hardware = 0;929		dsp->tone.software = 0;930		if (timer_pending(&dsp->tone.tl))931			del_timer(&dsp->tone.tl);932		if (dsp->conf)933			dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be934						 called here */935		skb_queue_purge(&dsp->sendq);936		spin_unlock_irqrestore(&dsp_lock, flags);937		hh->prim = PH_DEACTIVATE_REQ;938		if (ch->peer)939			return ch->recv(ch->peer, skb);940		break;941	default:942		if (dsp_debug & DEBUG_DSP_CORE)943			printk(KERN_DEBUG "%s: msg %x unhandled %s\n",944			       __func__, hh->prim, dsp->name);945		ret = -EINVAL;946	}947	if (!ret)948		dev_kfree_skb(skb);949	return ret;950}951 952static int953dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)954{955	struct dsp		*dsp = container_of(ch, struct dsp, ch);956	u_long		flags;957 958	if (debug & DEBUG_DSP_CTRL)959		printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);960 961	switch (cmd) {962	case OPEN_CHANNEL:963		break;964	case CLOSE_CHANNEL:965		if (dsp->ch.peer)966			dsp->ch.peer->ctrl(dsp->ch.peer, CLOSE_CHANNEL, NULL);967 968		/* wait until workqueue has finished,969		 * must lock here, or we may hit send-process currently970		 * queueing. */971		spin_lock_irqsave(&dsp_lock, flags);972		dsp->b_active = 0;973		spin_unlock_irqrestore(&dsp_lock, flags);974		/* MUST not be locked, because it waits until queue is done. */975		cancel_work_sync(&dsp->workq);976		spin_lock_irqsave(&dsp_lock, flags);977		if (timer_pending(&dsp->tone.tl))978			del_timer(&dsp->tone.tl);979		skb_queue_purge(&dsp->sendq);980		if (dsp_debug & DEBUG_DSP_CTRL)981			printk(KERN_DEBUG "%s: releasing member %s\n",982			       __func__, dsp->name);983		dsp->b_active = 0;984		dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be called985					 here */986		dsp_pipeline_destroy(&dsp->pipeline);987 988		if (dsp_debug & DEBUG_DSP_CTRL)989			printk(KERN_DEBUG "%s: remove & destroy object %s\n",990			       __func__, dsp->name);991		list_del(&dsp->list);992		spin_unlock_irqrestore(&dsp_lock, flags);993 994		if (dsp_debug & DEBUG_DSP_CTRL)995			printk(KERN_DEBUG "%s: dsp instance released\n",996			       __func__);997		vfree(dsp);998		module_put(THIS_MODULE);999		break;1000	}1001	return 0;1002}1003 1004static void1005dsp_send_bh(struct work_struct *work)1006{1007	struct dsp *dsp = container_of(work, struct dsp, workq);1008	struct sk_buff *skb;1009	struct mISDNhead	*hh;1010 1011	if (dsp->hdlc && dsp->data_pending)1012		return; /* wait until data has been acknowledged */1013 1014	/* send queued data */1015	while ((skb = skb_dequeue(&dsp->sendq))) {1016		/* in locked date, we must have still data in queue */1017		if (dsp->data_pending) {1018			if (dsp_debug & DEBUG_DSP_CORE)1019				printk(KERN_DEBUG "%s: fifo full %s, this is "1020				       "no bug!\n", __func__, dsp->name);1021			/* flush transparent data, if not acked */1022			dev_kfree_skb(skb);1023			continue;1024		}1025		hh = mISDN_HEAD_P(skb);1026		if (hh->prim == DL_DATA_REQ) {1027			/* send packet up */1028			if (dsp->up) {1029				if (dsp->up->send(dsp->up, skb))1030					dev_kfree_skb(skb);1031			} else1032				dev_kfree_skb(skb);1033		} else {1034			/* send packet down */1035			if (dsp->ch.peer) {1036				dsp->data_pending = 1;1037				if (dsp->ch.recv(dsp->ch.peer, skb)) {1038					dev_kfree_skb(skb);1039					dsp->data_pending = 0;1040				}1041			} else1042				dev_kfree_skb(skb);1043		}1044	}1045}1046 1047static int1048dspcreate(struct channel_req *crq)1049{1050	struct dsp		*ndsp;1051	u_long		flags;1052 1053	if (crq->protocol != ISDN_P_B_L2DSP1054	    && crq->protocol != ISDN_P_B_L2DSPHDLC)1055		return -EPROTONOSUPPORT;1056	ndsp = vzalloc(sizeof(struct dsp));1057	if (!ndsp) {1058		printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);1059		return -ENOMEM;1060	}1061	if (dsp_debug & DEBUG_DSP_CTRL)1062		printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);1063 1064	/* default enabled */1065	INIT_WORK(&ndsp->workq, (void *)dsp_send_bh);1066	skb_queue_head_init(&ndsp->sendq);1067	ndsp->ch.send = dsp_function;1068	ndsp->ch.ctrl = dsp_ctrl;1069	ndsp->up = crq->ch;1070	crq->ch = &ndsp->ch;1071	if (crq->protocol == ISDN_P_B_L2DSP) {1072		crq->protocol = ISDN_P_B_RAW;1073		ndsp->hdlc = 0;1074	} else {1075		crq->protocol = ISDN_P_B_HDLC;1076		ndsp->hdlc = 1;1077	}1078	if (!try_module_get(THIS_MODULE))1079		printk(KERN_WARNING "%s:cannot get module\n",1080		       __func__);1081 1082	sprintf(ndsp->name, "DSP_C%x(0x%p)",1083		ndsp->up->st->dev->id + 1, ndsp);1084	/* set frame size to start */1085	ndsp->features.hfc_id = -1; /* current PCM id */1086	ndsp->features.pcm_id = -1; /* current PCM id */1087	ndsp->pcm_slot_rx = -1; /* current CPM slot */1088	ndsp->pcm_slot_tx = -1;1089	ndsp->pcm_bank_rx = -1;1090	ndsp->pcm_bank_tx = -1;1091	ndsp->hfc_conf = -1; /* current conference number */1092	/* set tone timer */1093	timer_setup(&ndsp->tone.tl, dsp_tone_timeout, 0);1094 1095	if (dtmfthreshold < 20 || dtmfthreshold > 500)1096		dtmfthreshold = 200;1097	ndsp->dtmf.treshold = dtmfthreshold * 10000;1098 1099	/* init pipeline append to list */1100	spin_lock_irqsave(&dsp_lock, flags);1101	dsp_pipeline_init(&ndsp->pipeline);1102	list_add_tail(&ndsp->list, &dsp_ilist);1103	spin_unlock_irqrestore(&dsp_lock, flags);1104 1105	return 0;1106}1107 1108 1109static struct Bprotocol DSP = {1110	.Bprotocols = (1 << (ISDN_P_B_L2DSP & ISDN_P_B_MASK))1111	| (1 << (ISDN_P_B_L2DSPHDLC & ISDN_P_B_MASK)),1112	.name = "dsp",1113	.create = dspcreate1114};1115 1116static int __init dsp_init(void)1117{1118	int err;1119	int tics;1120 1121	printk(KERN_INFO "DSP module %s\n", mISDN_dsp_revision);1122 1123	dsp_options = options;1124	dsp_debug = debug;1125 1126	/* set packet size */1127	dsp_poll = poll;1128	if (dsp_poll) {1129		if (dsp_poll > MAX_POLL) {1130			printk(KERN_ERR "%s: Wrong poll value (%d), use %d "1131			       "maximum.\n", __func__, poll, MAX_POLL);1132			err = -EINVAL;1133			return err;1134		}1135		if (dsp_poll < 8) {1136			printk(KERN_ERR "%s: Wrong poll value (%d), use 8 "1137			       "minimum.\n", __func__, dsp_poll);1138			err = -EINVAL;1139			return err;1140		}1141		dsp_tics = poll * HZ / 8000;1142		if (dsp_tics * 8000 != poll * HZ) {1143			printk(KERN_INFO "mISDN_dsp: Cannot clock every %d "1144			       "samples (0,125 ms). It is not a multiple of "1145			       "%d HZ.\n", poll, HZ);1146			err = -EINVAL;1147			return err;1148		}1149	} else {1150		poll = 8;1151		while (poll <= MAX_POLL) {1152			tics = (poll * HZ) / 8000;1153			if (tics * 8000 == poll * HZ) {1154				dsp_tics = tics;1155				dsp_poll = poll;1156				if (poll >= 64)1157					break;1158			}1159			poll++;1160		}1161	}1162	if (dsp_poll == 0) {1163		printk(KERN_INFO "mISDN_dsp: There is no multiple of kernel "1164		       "clock that equals exactly the duration of 8-256 "1165		       "samples. (Choose kernel clock speed like 100, 250, "1166		       "300, 1000)\n");1167		err = -EINVAL;1168		return err;1169	}1170	printk(KERN_INFO "mISDN_dsp: DSP clocks every %d samples. This equals "1171	       "%d jiffies.\n", dsp_poll, dsp_tics);1172 1173	/* init conversion tables */1174	dsp_audio_generate_law_tables();1175	dsp_silence = (dsp_options & DSP_OPT_ULAW) ? 0xff : 0x2a;1176	dsp_audio_law_to_s32 = (dsp_options & DSP_OPT_ULAW) ?1177		dsp_audio_ulaw_to_s32 : dsp_audio_alaw_to_s32;1178	dsp_audio_generate_s2law_table();1179	dsp_audio_generate_seven();1180	dsp_audio_generate_mix_table();1181	if (dsp_options & DSP_OPT_ULAW)1182		dsp_audio_generate_ulaw_samples();1183	dsp_audio_generate_volume_changes();1184 1185	err = dsp_pipeline_module_init();1186	if (err) {1187		printk(KERN_ERR "mISDN_dsp: Can't initialize pipeline, "1188		       "error(%d)\n", err);1189		return err;1190	}1191 1192	err = mISDN_register_Bprotocol(&DSP);1193	if (err) {1194		printk(KERN_ERR "Can't register %s error(%d)\n", DSP.name, err);1195		return err;1196	}1197 1198	/* set sample timer */1199	timer_setup(&dsp_spl_tl, dsp_cmx_send, 0);1200	dsp_spl_tl.expires = jiffies + dsp_tics;1201	dsp_spl_jiffies = dsp_spl_tl.expires;1202	add_timer(&dsp_spl_tl);1203 1204	return 0;1205}1206 1207 1208static void __exit dsp_cleanup(void)1209{1210	mISDN_unregister_Bprotocol(&DSP);1211 1212	del_timer_sync(&dsp_spl_tl);1213 1214	if (!list_empty(&dsp_ilist)) {1215		printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not "1216		       "empty.\n");1217	}1218	if (!list_empty(&conf_ilist)) {1219		printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not "1220		       "all memory freed.\n");1221	}1222 1223	dsp_pipeline_module_exit();1224}1225 1226module_init(dsp_init);1227module_exit(dsp_cleanup);1228