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