aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN/dsp_cmx.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_cmx.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_cmx.c')
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c1886
1 files changed, 1886 insertions, 0 deletions
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
new file mode 100644
index 000000000000..e92b1ba4b45e
--- /dev/null
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -0,0 +1,1886 @@
1/*
2 * Audio crossconnecting/conferrencing (hardware level).
3 *
4 * Copyright 2002 by Andreas Eversberg (jolly@eversberg.eu)
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 */
10
11/*
12 * The process of adding and removing parties to/from a conference:
13 *
14 * There is a chain of struct dsp_conf which has one or more members in a chain
15 * of struct dsp_conf_member.
16 *
17 * After a party is added, the conference is checked for hardware capability.
18 * Also if a party is removed, the conference is checked again.
19 *
20 * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
21 * 1-n = hardware-conference. The n will give the conference number.
22 *
23 * Depending on the change after removal or insertion of a party, hardware
24 * commands are given.
25 *
26 * The current solution is stored within the struct dsp_conf entry.
27 */
28
29/*
30 * HOW THE CMX WORKS:
31 *
32 * There are 3 types of interaction: One member is alone, in this case only
33 * data flow from upper to lower layer is done.
34 * Two members will also exchange their data so they are crossconnected.
35 * Three or more members will be added in a conference and will hear each
36 * other but will not receive their own speech (echo) if not enabled.
37 *
38 * Features of CMX are:
39 * - Crossconnecting or even conference, if more than two members are together.
40 * - Force mixing of transmit data with other crossconnect/conference members.
41 * - Echo generation to benchmark the delay of audio processing.
42 * - Use hardware to minimize cpu load, disable FIFO load and minimize delay.
43 * - Dejittering and clock generation.
44 *
45 * There are 2 buffers:
46 *
47 *
48 * RX-Buffer
49 * R W
50 * | |
51 * ----------------+-------------+-------------------
52 *
53 * The rx-buffer is a ring buffer used to store the received data for each
54 * individual member. This is only the case if data needs to be dejittered
55 * or in case of a conference where different clocks require reclocking.
56 * The transmit-clock (R) will read the buffer.
57 * If the clock overruns the write-pointer, we will have a buffer underrun.
58 * If the write pointer always has a certain distance from the transmit-
59 * clock, we will have a delay. The delay will dynamically be increased and
60 * reduced.
61 *
62 *
63 * TX-Buffer
64 * R W
65 * | |
66 * -----------------+--------+-----------------------
67 *
68 * The tx-buffer is a ring buffer to queue the transmit data from user space
69 * until it will be mixed or sent. There are two pointers, R and W. If the write
70 * pointer W would reach or overrun R, the buffer would overrun. In this case
71 * (some) data is dropped so that it will not overrun.
72 * Additionally a dynamic dejittering can be enabled. this allows data from
73 * user space that have jitter and different clock source.
74 *
75 *
76 * Clock:
77 *
78 * A Clock is not required, if the data source has exactly one clock. In this
79 * case the data source is forwarded to the destination.
80 *
81 * A Clock is required, because the data source
82 * - has multiple clocks.
83 * - has no usable clock due to jitter or packet loss (VoIP).
84 * In this case the system's clock is used. The clock resolution depends on
85 * the jiffie resolution.
86 *
87 * If a member joins a conference:
88 *
89 * - If a member joins, its rx_buff is set to silence and change read pointer
90 * to transmit clock.
91 *
92 * The procedure of received data from card is explained in cmx_receive.
93 * The procedure of received data from user space is explained in cmx_transmit.
94 * The procedure of transmit data to card is cmx_send.
95 *
96 *
97 * Interaction with other features:
98 *
99 * DTMF:
100 * DTMF decoding is done before the data is crossconnected.
101 *
102 * Volume change:
103 * Changing rx-volume is done before the data is crossconnected. The tx-volume
104 * must be changed whenever data is transmitted to the card by the cmx.
105 *
106 * Tones:
107 * If a tone is enabled, it will be processed whenever data is transmitted to
108 * the card. It will replace the tx-data from the user space.
109 * If tones are generated by hardware, this conference member is removed for
110 * this time.
111 *
112 * Disable rx-data:
113 * If cmx is realized in hardware, rx data will be disabled if requested by
114 * the upper layer. If dtmf decoding is done by software and enabled, rx data
115 * will not be diabled but blocked to the upper layer.
116 *
117 * HFC conference engine:
118 * If it is possible to realize all features using hardware, hardware will be
119 * used if not forbidden by control command. Disabling rx-data provides
120 * absolutely traffic free audio processing. (except for the quick 1-frame
121 * upload of a tone loop, only once for a new tone)
122 *
123 */
124
125/* delay.h is required for hw_lock.h */
126
127#include <linux/delay.h>
128#include <linux/mISDNif.h>
129#include <linux/mISDNdsp.h>
130#include "core.h"
131#include "dsp.h"
132/*
133 * debugging of multi party conference,
134 * by using conference even with two members
135 */
136
137/* #define CMX_CONF_DEBUG */
138
139/*#define CMX_DEBUG * massive read/write pointer output */
140/*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */
141
142static inline int
143count_list_member(struct list_head *head)
144{
145 int cnt = 0;
146 struct list_head *m;
147
148 list_for_each(m, head)
149 cnt++;
150 return cnt;
151}
152
153/*
154 * debug cmx memory structure
155 */
156void
157dsp_cmx_debug(struct dsp *dsp)
158{
159 struct dsp_conf *conf;
160 struct dsp_conf_member *member;
161 struct dsp *odsp;
162
163 printk(KERN_DEBUG "-----Current DSP\n");
164 list_for_each_entry(odsp, &dsp_ilist, list) {
165 printk(KERN_DEBUG "* %s echo=%d txmix=%d",
166 odsp->name, odsp->echo, odsp->tx_mix);
167 if (odsp->conf)
168 printk(" (Conf %d)", odsp->conf->id);
169 if (dsp == odsp)
170 printk(" *this*");
171 printk("\n");
172 }
173 printk(KERN_DEBUG "-----Current Conf:\n");
174 list_for_each_entry(conf, &conf_ilist, list) {
175 printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf);
176 list_for_each_entry(member, &conf->mlist, list) {
177 printk(KERN_DEBUG
178 " - member = %s (slot_tx %d, bank_tx %d, "
179 "slot_rx %d, bank_rx %d hfc_conf %d)%s\n",
180 member->dsp->name, member->dsp->pcm_slot_tx,
181 member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
182 member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
183 (member->dsp == dsp) ? " *this*" : "");
184 }
185 }
186 printk(KERN_DEBUG "-----end\n");
187}
188
189/*
190 * search conference
191 */
192static struct dsp_conf *
193dsp_cmx_search_conf(u32 id)
194{
195 struct dsp_conf *conf;
196
197 if (!id) {
198 printk(KERN_WARNING "%s: conference ID is 0.\n", __func__);
199 return NULL;
200 }
201
202 /* search conference */
203 list_for_each_entry(conf, &conf_ilist, list)
204 if (conf->id == id)
205 return conf;
206
207 return NULL;
208}
209
210
211/*
212 * add member to conference
213 */
214static int
215dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf)
216{
217 struct dsp_conf_member *member;
218
219 if (!conf || !dsp) {
220 printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__);
221 return -EINVAL;
222 }
223 if (dsp->member) {
224 printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
225 __func__);
226 return -EINVAL;
227 }
228
229 if (dsp->conf) {
230 printk(KERN_WARNING "%s: dsp is already in a conf.\n",
231 __func__);
232 return -EINVAL;
233 }
234
235 member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
236 if (!member) {
237 printk(KERN_ERR "kmalloc struct dsp_conf_member failed\n");
238 return -ENOMEM;
239 }
240 member->dsp = dsp;
241 /* clear rx buffer */
242 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
243 dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */
244 dsp->rx_W = 0;
245 dsp->rx_R = 0;
246
247 list_add_tail(&member->list, &conf->mlist);
248
249 dsp->conf = conf;
250 dsp->member = member;
251
252 return 0;
253}
254
255
256/*
257 * del member from conference
258 */
259int
260dsp_cmx_del_conf_member(struct dsp *dsp)
261{
262 struct dsp_conf_member *member;
263
264 if (!dsp) {
265 printk(KERN_WARNING "%s: dsp is 0.\n",
266 __func__);
267 return -EINVAL;
268 }
269
270 if (!dsp->conf) {
271 printk(KERN_WARNING "%s: dsp is not in a conf.\n",
272 __func__);
273 return -EINVAL;
274 }
275
276 if (list_empty(&dsp->conf->mlist)) {
277 printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
278 __func__);
279 return -EINVAL;
280 }
281
282 /* find us in conf */
283 list_for_each_entry(member, &dsp->conf->mlist, list) {
284 if (member->dsp == dsp) {
285 list_del(&member->list);
286 dsp->conf = NULL;
287 dsp->member = NULL;
288 kfree(member);
289 return 0;
290 }
291 }
292 printk(KERN_WARNING
293 "%s: dsp is not present in its own conf_meber list.\n",
294 __func__);
295
296 return -EINVAL;
297}
298
299
300/*
301 * new conference
302 */
303static struct dsp_conf
304*dsp_cmx_new_conf(u32 id)
305{
306 struct dsp_conf *conf;
307
308 if (!id) {
309 printk(KERN_WARNING "%s: id is 0.\n",
310 __func__);
311 return NULL;
312 }
313
314 conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
315 if (!conf) {
316 printk(KERN_ERR "kmalloc struct dsp_conf failed\n");
317 return NULL;
318 }
319 INIT_LIST_HEAD(&conf->mlist);
320 conf->id = id;
321
322 list_add_tail(&conf->list, &conf_ilist);
323
324 return conf;
325}
326
327
328/*
329 * del conference
330 */
331int
332dsp_cmx_del_conf(struct dsp_conf *conf)
333{
334 if (!conf) {
335 printk(KERN_WARNING "%s: conf is null.\n",
336 __func__);
337 return -EINVAL;
338 }
339
340 if (!list_empty(&conf->mlist)) {
341 printk(KERN_WARNING "%s: conf not empty.\n",
342 __func__);
343 return -EINVAL;
344 }
345 list_del(&conf->list);
346 kfree(conf);
347
348 return 0;
349}
350
351
352/*
353 * send HW message to hfc card
354 */
355static void
356dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2,
357 u32 param3, u32 param4)
358{
359 struct mISDN_ctrl_req cq;
360
361 memset(&cq, 0, sizeof(cq));
362 cq.op = message;
363 cq.p1 = param1 | (param2 << 8);
364 cq.p2 = param3 | (param4 << 8);
365 if (dsp->ch.peer)
366 dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq);
367}
368
369
370/*
371 * do hardware update and set the software/hardware flag
372 *
373 * either a conference or a dsp instance can be given
374 * if only dsp instance is given, the instance is not associated with a conf
375 * and therefore removed. if a conference is given, the dsp is expected to
376 * be member of that conference.
377 */
378void
379dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
380{
381 struct dsp_conf_member *member, *nextm;
382 struct dsp *finddsp;
383 int memb = 0, i, ii, i1, i2;
384 int freeunits[8];
385 u_char freeslots[256];
386 int same_hfc = -1, same_pcm = -1, current_conf = -1,
387 all_conf = 1;
388
389 /* dsp gets updated (no conf) */
390 if (!conf) {
391 if (!dsp)
392 return;
393 if (dsp_debug & DEBUG_DSP_CMX)
394 printk(KERN_DEBUG "%s checking dsp %s\n",
395 __func__, dsp->name);
396one_member:
397 /* remove HFC conference if enabled */
398 if (dsp->hfc_conf >= 0) {
399 if (dsp_debug & DEBUG_DSP_CMX)
400 printk(KERN_DEBUG
401 "%s removing %s from HFC conf %d "
402 "because dsp is split\n", __func__,
403 dsp->name, dsp->hfc_conf);
404 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT,
405 0, 0, 0, 0);
406 dsp->hfc_conf = -1;
407 }
408 /* process hw echo */
409 if (dsp->features.pcm_banks < 1)
410 return;
411 if (!dsp->echo) {
412 /* NO ECHO: remove PCM slot if assigned */
413 if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
414 if (dsp_debug & DEBUG_DSP_CMX)
415 printk(KERN_DEBUG "%s removing %s from"
416 " PCM slot %d (TX) %d (RX) because"
417 " dsp is split (no echo)\n",
418 __func__, dsp->name,
419 dsp->pcm_slot_tx, dsp->pcm_slot_rx);
420 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC,
421 0, 0, 0, 0);
422 dsp->pcm_slot_tx = -1;
423 dsp->pcm_bank_tx = -1;
424 dsp->pcm_slot_rx = -1;
425 dsp->pcm_bank_rx = -1;
426 }
427 return;
428 }
429 /* ECHO: already echo */
430 if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
431 dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2)
432 return;
433 /* ECHO: if slot already assigned */
434 if (dsp->pcm_slot_tx >= 0) {
435 dsp->pcm_slot_rx = dsp->pcm_slot_tx;
436 dsp->pcm_bank_tx = 2; /* 2 means loop */
437 dsp->pcm_bank_rx = 2;
438 if (dsp_debug & DEBUG_DSP_CMX)
439 printk(KERN_DEBUG
440 "%s refresh %s for echo using slot %d\n",
441 __func__, dsp->name,
442 dsp->pcm_slot_tx);
443 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
444 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
445 return;
446 }
447 /* ECHO: find slot */
448 dsp->pcm_slot_tx = -1;
449 dsp->pcm_slot_rx = -1;
450 memset(freeslots, 1, sizeof(freeslots));
451 list_for_each_entry(finddsp, &dsp_ilist, list) {
452 if (finddsp->features.pcm_id == dsp->features.pcm_id) {
453 if (finddsp->pcm_slot_rx >= 0 &&
454 finddsp->pcm_slot_rx < sizeof(freeslots))
455 freeslots[finddsp->pcm_slot_tx] = 0;
456 if (finddsp->pcm_slot_tx >= 0 &&
457 finddsp->pcm_slot_tx < sizeof(freeslots))
458 freeslots[finddsp->pcm_slot_rx] = 0;
459 }
460 }
461 i = 0;
462 ii = dsp->features.pcm_slots;
463 while (i < ii) {
464 if (freeslots[i])
465 break;
466 i++;
467 }
468 if (i == ii) {
469 if (dsp_debug & DEBUG_DSP_CMX)
470 printk(KERN_DEBUG
471 "%s no slot available for echo\n",
472 __func__);
473 /* no more slots available */
474 return;
475 }
476 /* assign free slot */
477 dsp->pcm_slot_tx = i;
478 dsp->pcm_slot_rx = i;
479 dsp->pcm_bank_tx = 2; /* loop */
480 dsp->pcm_bank_rx = 2;
481 if (dsp_debug & DEBUG_DSP_CMX)
482 printk(KERN_DEBUG
483 "%s assign echo for %s using slot %d\n",
484 __func__, dsp->name, dsp->pcm_slot_tx);
485 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
486 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
487 return;
488 }
489
490 /* conf gets updated (all members) */
491 if (dsp_debug & DEBUG_DSP_CMX)
492 printk(KERN_DEBUG "%s checking conference %d\n",
493 __func__, conf->id);
494
495 if (list_empty(&conf->mlist)) {
496 printk(KERN_ERR "%s: conference whithout members\n",
497 __func__);
498 return;
499 }
500 member = list_entry(conf->mlist.next, struct dsp_conf_member, list);
501 same_hfc = member->dsp->features.hfc_id;
502 same_pcm = member->dsp->features.pcm_id;
503 /* check all members in our conference */
504 list_for_each_entry(member, &conf->mlist, list) {
505 /* check if member uses mixing */
506 if (member->dsp->tx_mix) {
507 if (dsp_debug & DEBUG_DSP_CMX)
508 printk(KERN_DEBUG
509 "%s dsp %s cannot form a conf, because "
510 "tx_mix is turned on\n", __func__,
511 member->dsp->name);
512conf_software:
513 list_for_each_entry(member, &conf->mlist, list) {
514 dsp = member->dsp;
515 /* remove HFC conference if enabled */
516 if (dsp->hfc_conf >= 0) {
517 if (dsp_debug & DEBUG_DSP_CMX)
518 printk(KERN_DEBUG
519 "%s removing %s from HFC "
520 "conf %d because not "
521 "possible with hardware\n",
522 __func__,
523 dsp->name,
524 dsp->hfc_conf);
525 dsp_cmx_hw_message(dsp,
526 MISDN_CTRL_HFC_CONF_SPLIT,
527 0, 0, 0, 0);
528 dsp->hfc_conf = -1;
529 }
530 /* remove PCM slot if assigned */
531 if (dsp->pcm_slot_tx >= 0 ||
532 dsp->pcm_slot_rx >= 0) {
533 if (dsp_debug & DEBUG_DSP_CMX)
534 printk(KERN_DEBUG "%s removing "
535 "%s from PCM slot %d (TX)"
536 " slot %d (RX) because not"
537 " possible with hardware\n",
538 __func__,
539 dsp->name,
540 dsp->pcm_slot_tx,
541 dsp->pcm_slot_rx);
542 dsp_cmx_hw_message(dsp,
543 MISDN_CTRL_HFC_PCM_DISC,
544 0, 0, 0, 0);
545 dsp->pcm_slot_tx = -1;
546 dsp->pcm_bank_tx = -1;
547 dsp->pcm_slot_rx = -1;
548 dsp->pcm_bank_rx = -1;
549 }
550 }
551 conf->hardware = 0;
552 conf->software = 1;
553 return;
554 }
555 /* check if member has echo turned on */
556 if (member->dsp->echo) {
557 if (dsp_debug & DEBUG_DSP_CMX)
558 printk(KERN_DEBUG
559 "%s dsp %s cannot form a conf, because "
560 "echo is turned on\n", __func__,
561 member->dsp->name);
562 goto conf_software;
563 }
564 /* check if member has tx_mix turned on */
565 if (member->dsp->tx_mix) {
566 if (dsp_debug & DEBUG_DSP_CMX)
567 printk(KERN_DEBUG
568 "%s dsp %s cannot form a conf, because "
569 "tx_mix is turned on\n",
570 __func__, member->dsp->name);
571 goto conf_software;
572 }
573 /* check if member changes volume at an not suppoted level */
574 if (member->dsp->tx_volume) {
575 if (dsp_debug & DEBUG_DSP_CMX)
576 printk(KERN_DEBUG
577 "%s dsp %s cannot form a conf, because "
578 "tx_volume is changed\n",
579 __func__, member->dsp->name);
580 goto conf_software;
581 }
582 if (member->dsp->rx_volume) {
583 if (dsp_debug & DEBUG_DSP_CMX)
584 printk(KERN_DEBUG
585 "%s dsp %s cannot form a conf, because "
586 "rx_volume is changed\n",
587 __func__, member->dsp->name);
588 goto conf_software;
589 }
590 /* check if tx-data turned on */
591 if (member->dsp->tx_data) {
592 if (dsp_debug & DEBUG_DSP_CMX)
593 printk(KERN_DEBUG
594 "%s dsp %s cannot form a conf, because "
595 "tx_data is turned on\n",
596 __func__, member->dsp->name);
597 goto conf_software;
598 }
599 /* check if pipeline exists */
600 if (member->dsp->pipeline.inuse) {
601 if (dsp_debug & DEBUG_DSP_CMX)
602 printk(KERN_DEBUG
603 "%s dsp %s cannot form a conf, because "
604 "pipeline exists\n", __func__,
605 member->dsp->name);
606 goto conf_software;
607 }
608 /* check if encryption is enabled */
609 if (member->dsp->bf_enable) {
610 if (dsp_debug & DEBUG_DSP_CMX)
611 printk(KERN_DEBUG "%s dsp %s cannot form a "
612 "conf, because encryption is enabled\n",
613 __func__, member->dsp->name);
614 goto conf_software;
615 }
616 /* check if member is on a card with PCM support */
617 if (member->dsp->features.pcm_id < 0) {
618 if (dsp_debug & DEBUG_DSP_CMX)
619 printk(KERN_DEBUG
620 "%s dsp %s cannot form a conf, because "
621 "dsp has no PCM bus\n",
622 __func__, member->dsp->name);
623 goto conf_software;
624 }
625 /* check if relations are on the same PCM bus */
626 if (member->dsp->features.pcm_id != same_pcm) {
627 if (dsp_debug & DEBUG_DSP_CMX)
628 printk(KERN_DEBUG
629 "%s dsp %s cannot form a conf, because "
630 "dsp is on a different PCM bus than the "
631 "first dsp\n",
632 __func__, member->dsp->name);
633 goto conf_software;
634 }
635 /* determine if members are on the same hfc chip */
636 if (same_hfc != member->dsp->features.hfc_id)
637 same_hfc = -1;
638 /* if there are members already in a conference */
639 if (current_conf < 0 && member->dsp->hfc_conf >= 0)
640 current_conf = member->dsp->hfc_conf;
641 /* if any member is not in a conference */
642 if (member->dsp->hfc_conf < 0)
643 all_conf = 0;
644
645 memb++;
646 }
647
648 /* if no member, this is an error */
649 if (memb < 1)
650 return;
651
652 /* one member */
653 if (memb == 1) {
654 if (dsp_debug & DEBUG_DSP_CMX)
655 printk(KERN_DEBUG
656 "%s conf %d cannot form a HW conference, "
657 "because dsp is alone\n", __func__, conf->id);
658 conf->hardware = 0;
659 conf->software = 0;
660 member = list_entry(conf->mlist.next, struct dsp_conf_member,
661 list);
662 dsp = member->dsp;
663 goto one_member;
664 }
665
666 /*
667 * ok, now we are sure that all members are on the same pcm.
668 * now we will see if we have only two members, so we can do
669 * crossconnections, which don't have any limitations.
670 */
671
672 /* if we have only two members */
673 if (memb == 2) {
674 member = list_entry(conf->mlist.next, struct dsp_conf_member,
675 list);
676 nextm = list_entry(member->list.next, struct dsp_conf_member,
677 list);
678 /* remove HFC conference if enabled */
679 if (member->dsp->hfc_conf >= 0) {
680 if (dsp_debug & DEBUG_DSP_CMX)
681 printk(KERN_DEBUG
682 "%s removing %s from HFC conf %d because "
683 "two parties require only a PCM slot\n",
684 __func__, member->dsp->name,
685 member->dsp->hfc_conf);
686 dsp_cmx_hw_message(member->dsp,
687 MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
688 member->dsp->hfc_conf = -1;
689 }
690 if (nextm->dsp->hfc_conf >= 0) {
691 if (dsp_debug & DEBUG_DSP_CMX)
692 printk(KERN_DEBUG
693 "%s removing %s from HFC conf %d because "
694 "two parties require only a PCM slot\n",
695 __func__, nextm->dsp->name,
696 nextm->dsp->hfc_conf);
697 dsp_cmx_hw_message(nextm->dsp,
698 MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
699 nextm->dsp->hfc_conf = -1;
700 }
701 /* if members have two banks (and not on the same chip) */
702 if (member->dsp->features.pcm_banks > 1 &&
703 nextm->dsp->features.pcm_banks > 1 &&
704 member->dsp->features.hfc_id !=
705 nextm->dsp->features.hfc_id) {
706 /* if both members have same slots with crossed banks */
707 if (member->dsp->pcm_slot_tx >= 0 &&
708 member->dsp->pcm_slot_rx >= 0 &&
709 nextm->dsp->pcm_slot_tx >= 0 &&
710 nextm->dsp->pcm_slot_rx >= 0 &&
711 nextm->dsp->pcm_slot_tx ==
712 member->dsp->pcm_slot_rx &&
713 nextm->dsp->pcm_slot_rx ==
714 member->dsp->pcm_slot_tx &&
715 nextm->dsp->pcm_slot_tx ==
716 member->dsp->pcm_slot_tx &&
717 member->dsp->pcm_bank_tx !=
718 member->dsp->pcm_bank_rx &&
719 nextm->dsp->pcm_bank_tx !=
720 nextm->dsp->pcm_bank_rx) {
721 /* all members have same slot */
722 if (dsp_debug & DEBUG_DSP_CMX)
723 printk(KERN_DEBUG
724 "%s dsp %s & %s stay joined on "
725 "PCM slot %d bank %d (TX) bank %d "
726 "(RX) (on different chips)\n",
727 __func__,
728 member->dsp->name,
729 nextm->dsp->name,
730 member->dsp->pcm_slot_tx,
731 member->dsp->pcm_bank_tx,
732 member->dsp->pcm_bank_rx);
733 conf->hardware = 0;
734 conf->software = 1;
735 return;
736 }
737 /* find a new slot */
738 memset(freeslots, 1, sizeof(freeslots));
739 list_for_each_entry(dsp, &dsp_ilist, list) {
740 if (dsp != member->dsp &&
741 dsp != nextm->dsp &&
742 member->dsp->features.pcm_id ==
743 dsp->features.pcm_id) {
744 if (dsp->pcm_slot_rx >= 0 &&
745 dsp->pcm_slot_rx <
746 sizeof(freeslots))
747 freeslots[dsp->pcm_slot_tx] = 0;
748 if (dsp->pcm_slot_tx >= 0 &&
749 dsp->pcm_slot_tx <
750 sizeof(freeslots))
751 freeslots[dsp->pcm_slot_rx] = 0;
752 }
753 }
754 i = 0;
755 ii = member->dsp->features.pcm_slots;
756 while (i < ii) {
757 if (freeslots[i])
758 break;
759 i++;
760 }
761 if (i == ii) {
762 if (dsp_debug & DEBUG_DSP_CMX)
763 printk(KERN_DEBUG
764 "%s no slot available for "
765 "%s & %s\n", __func__,
766 member->dsp->name,
767 nextm->dsp->name);
768 /* no more slots available */
769 goto conf_software;
770 }
771 /* assign free slot */
772 member->dsp->pcm_slot_tx = i;
773 member->dsp->pcm_slot_rx = i;
774 nextm->dsp->pcm_slot_tx = i;
775 nextm->dsp->pcm_slot_rx = i;
776 member->dsp->pcm_bank_rx = 0;
777 member->dsp->pcm_bank_tx = 1;
778 nextm->dsp->pcm_bank_rx = 1;
779 nextm->dsp->pcm_bank_tx = 0;
780 if (dsp_debug & DEBUG_DSP_CMX)
781 printk(KERN_DEBUG
782 "%s adding %s & %s to new PCM slot %d "
783 "(TX and RX on different chips) because "
784 "both members have not same slots\n",
785 __func__,
786 member->dsp->name,
787 nextm->dsp->name,
788 member->dsp->pcm_slot_tx);
789 dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
790 member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
791 member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
792 dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
793 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
794 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
795 conf->hardware = 1;
796 conf->software = 0;
797 return;
798 /* if members have one bank (or on the same chip) */
799 } else {
800 /* if both members have different crossed slots */
801 if (member->dsp->pcm_slot_tx >= 0 &&
802 member->dsp->pcm_slot_rx >= 0 &&
803 nextm->dsp->pcm_slot_tx >= 0 &&
804 nextm->dsp->pcm_slot_rx >= 0 &&
805 nextm->dsp->pcm_slot_tx ==
806 member->dsp->pcm_slot_rx &&
807 nextm->dsp->pcm_slot_rx ==
808 member->dsp->pcm_slot_tx &&
809 member->dsp->pcm_slot_tx !=
810 member->dsp->pcm_slot_rx &&
811 member->dsp->pcm_bank_tx == 0 &&
812 member->dsp->pcm_bank_rx == 0 &&
813 nextm->dsp->pcm_bank_tx == 0 &&
814 nextm->dsp->pcm_bank_rx == 0) {
815 /* all members have same slot */
816 if (dsp_debug & DEBUG_DSP_CMX)
817 printk(KERN_DEBUG
818 "%s dsp %s & %s stay joined on PCM "
819 "slot %d (TX) %d (RX) on same chip "
820 "or one bank PCM)\n", __func__,
821 member->dsp->name,
822 nextm->dsp->name,
823 member->dsp->pcm_slot_tx,
824 member->dsp->pcm_slot_rx);
825 conf->hardware = 0;
826 conf->software = 1;
827 return;
828 }
829 /* find two new slot */
830 memset(freeslots, 1, sizeof(freeslots));
831 list_for_each_entry(dsp, &dsp_ilist, list) {
832 if (dsp != member->dsp &&
833 dsp != nextm->dsp &&
834 member->dsp->features.pcm_id ==
835 dsp->features.pcm_id) {
836 if (dsp->pcm_slot_rx >= 0 &&
837 dsp->pcm_slot_rx <
838 sizeof(freeslots))
839 freeslots[dsp->pcm_slot_tx] = 0;
840 if (dsp->pcm_slot_tx >= 0 &&
841 dsp->pcm_slot_tx <
842 sizeof(freeslots))
843 freeslots[dsp->pcm_slot_rx] = 0;
844 }
845 }
846 i1 = 0;
847 ii = member->dsp->features.pcm_slots;
848 while (i1 < ii) {
849 if (freeslots[i1])
850 break;
851 i1++;
852 }
853 if (i1 == ii) {
854 if (dsp_debug & DEBUG_DSP_CMX)
855 printk(KERN_DEBUG
856 "%s no slot available "
857 "for %s & %s\n", __func__,
858 member->dsp->name,
859 nextm->dsp->name);
860 /* no more slots available */
861 goto conf_software;
862 }
863 i2 = i1+1;
864 while (i2 < ii) {
865 if (freeslots[i2])
866 break;
867 i2++;
868 }
869 if (i2 == ii) {
870 if (dsp_debug & DEBUG_DSP_CMX)
871 printk(KERN_DEBUG
872 "%s no slot available "
873 "for %s & %s\n",
874 __func__,
875 member->dsp->name,
876 nextm->dsp->name);
877 /* no more slots available */
878 goto conf_software;
879 }
880 /* assign free slots */
881 member->dsp->pcm_slot_tx = i1;
882 member->dsp->pcm_slot_rx = i2;
883 nextm->dsp->pcm_slot_tx = i2;
884 nextm->dsp->pcm_slot_rx = i1;
885 member->dsp->pcm_bank_rx = 0;
886 member->dsp->pcm_bank_tx = 0;
887 nextm->dsp->pcm_bank_rx = 0;
888 nextm->dsp->pcm_bank_tx = 0;
889 if (dsp_debug & DEBUG_DSP_CMX)
890 printk(KERN_DEBUG
891 "%s adding %s & %s to new PCM slot %d "
892 "(TX) %d (RX) on same chip or one bank "
893 "PCM, because both members have not "
894 "crossed slots\n", __func__,
895 member->dsp->name,
896 nextm->dsp->name,
897 member->dsp->pcm_slot_tx,
898 member->dsp->pcm_slot_rx);
899 dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
900 member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
901 member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
902 dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
903 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
904 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
905 conf->hardware = 1;
906 conf->software = 0;
907 return;
908 }
909 }
910
911 /*
912 * if we have more than two, we may check if we have a conference
913 * unit available on the chip. also all members must be on the same
914 */
915
916 /* if not the same HFC chip */
917 if (same_hfc < 0) {
918 if (dsp_debug & DEBUG_DSP_CMX)
919 printk(KERN_DEBUG
920 "%s conference %d cannot be formed, because "
921 "members are on different chips or not "
922 "on HFC chip\n",
923 __func__, conf->id);
924 goto conf_software;
925 }
926
927 /* for more than two members.. */
928
929 /* in case of hdlc, we change to software */
930 if (dsp->hdlc)
931 goto conf_software;
932
933 /* if all members already have the same conference */
934 if (all_conf)
935 return;
936
937 /*
938 * if there is an existing conference, but not all members have joined
939 */
940 if (current_conf >= 0) {
941join_members:
942 list_for_each_entry(member, &conf->mlist, list) {
943 /* join to current conference */
944 if (member->dsp->hfc_conf == current_conf)
945 continue;
946 /* get a free timeslot first */
947 memset(freeslots, 1, sizeof(freeslots));
948 list_for_each_entry(dsp, &dsp_ilist, list) {
949 /*
950 * not checking current member, because
951 * slot will be overwritten.
952 */
953 if (
954 dsp != member->dsp &&
955 /* dsp must be on the same PCM */
956 member->dsp->features.pcm_id ==
957 dsp->features.pcm_id) {
958 /* dsp must be on a slot */
959 if (dsp->pcm_slot_tx >= 0 &&
960 dsp->pcm_slot_tx <
961 sizeof(freeslots))
962 freeslots[dsp->pcm_slot_tx] = 0;
963 if (dsp->pcm_slot_rx >= 0 &&
964 dsp->pcm_slot_rx <
965 sizeof(freeslots))
966 freeslots[dsp->pcm_slot_rx] = 0;
967 }
968 }
969 i = 0;
970 ii = member->dsp->features.pcm_slots;
971 while (i < ii) {
972 if (freeslots[i])
973 break;
974 i++;
975 }
976 if (i == ii) {
977 /* no more slots available */
978 if (dsp_debug & DEBUG_DSP_CMX)
979 printk(KERN_DEBUG
980 "%s conference %d cannot be formed,"
981 " because no slot free\n",
982 __func__, conf->id);
983 goto conf_software;
984 }
985 if (dsp_debug & DEBUG_DSP_CMX)
986 printk(KERN_DEBUG
987 "%s changing dsp %s to HW conference "
988 "%d slot %d\n", __func__,
989 member->dsp->name, current_conf, i);
990 /* assign free slot & set PCM & join conf */
991 member->dsp->pcm_slot_tx = i;
992 member->dsp->pcm_slot_rx = i;
993 member->dsp->pcm_bank_tx = 2; /* loop */
994 member->dsp->pcm_bank_rx = 2;
995 member->dsp->hfc_conf = current_conf;
996 dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
997 i, 2, i, 2);
998 dsp_cmx_hw_message(member->dsp,
999 MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
1000 }
1001 return;
1002 }
1003
1004 /*
1005 * no member is in a conference yet, so we find a free one
1006 */
1007 memset(freeunits, 1, sizeof(freeunits));
1008 list_for_each_entry(dsp, &dsp_ilist, list) {
1009 /* dsp must be on the same chip */
1010 if (dsp->features.hfc_id == same_hfc &&
1011 /* dsp must have joined a HW conference */
1012 dsp->hfc_conf >= 0 &&
1013 /* slot must be within range */
1014 dsp->hfc_conf < 8)
1015 freeunits[dsp->hfc_conf] = 0;
1016 }
1017 i = 0;
1018 ii = 8;
1019 while (i < ii) {
1020 if (freeunits[i])
1021 break;
1022 i++;
1023 }
1024 if (i == ii) {
1025 /* no more conferences available */
1026 if (dsp_debug & DEBUG_DSP_CMX)
1027 printk(KERN_DEBUG
1028 "%s conference %d cannot be formed, because "
1029 "no conference number free\n",
1030 __func__, conf->id);
1031 goto conf_software;
1032 }
1033 /* join all members */
1034 current_conf = i;
1035 goto join_members;
1036}
1037
1038
1039/*
1040 * conf_id != 0: join or change conference
1041 * conf_id == 0: split from conference if not already
1042 */
1043int
1044dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
1045{
1046 int err;
1047 struct dsp_conf *conf;
1048 struct dsp_conf_member *member;
1049
1050 /* if conference doesn't change */
1051 if (dsp->conf_id == conf_id)
1052 return 0;
1053
1054 /* first remove us from current conf */
1055 if (dsp->conf_id) {
1056 if (dsp_debug & DEBUG_DSP_CMX)
1057 printk(KERN_DEBUG "removing us from conference %d\n",
1058 dsp->conf->id);
1059 /* remove us from conf */
1060 conf = dsp->conf;
1061 err = dsp_cmx_del_conf_member(dsp);
1062 if (err)
1063 return err;
1064 dsp->conf_id = 0;
1065
1066 /* update hardware */
1067 dsp_cmx_hardware(NULL, dsp);
1068
1069 /* conf now empty? */
1070 if (list_empty(&conf->mlist)) {
1071 if (dsp_debug & DEBUG_DSP_CMX)
1072 printk(KERN_DEBUG
1073 "conference is empty, so we remove it.\n");
1074 err = dsp_cmx_del_conf(conf);
1075 if (err)
1076 return err;
1077 } else {
1078 /* update members left on conf */
1079 dsp_cmx_hardware(conf, NULL);
1080 }
1081 }
1082
1083 /* if split */
1084 if (!conf_id)
1085 return 0;
1086
1087 /* now add us to conf */
1088 if (dsp_debug & DEBUG_DSP_CMX)
1089 printk(KERN_DEBUG "searching conference %d\n",
1090 conf_id);
1091 conf = dsp_cmx_search_conf(conf_id);
1092 if (!conf) {
1093 if (dsp_debug & DEBUG_DSP_CMX)
1094 printk(KERN_DEBUG
1095 "conference doesn't exist yet, creating.\n");
1096 /* the conference doesn't exist, so we create */
1097 conf = dsp_cmx_new_conf(conf_id);
1098 if (!conf)
1099 return -EINVAL;
1100 } else if (!list_empty(&conf->mlist)) {
1101 member = list_entry(conf->mlist.next, struct dsp_conf_member,
1102 list);
1103 if (dsp->hdlc && !member->dsp->hdlc) {
1104 if (dsp_debug & DEBUG_DSP_CMX)
1105 printk(KERN_DEBUG
1106 "cannot join transparent conference.\n");
1107 return -EINVAL;
1108 }
1109 if (!dsp->hdlc && member->dsp->hdlc) {
1110 if (dsp_debug & DEBUG_DSP_CMX)
1111 printk(KERN_DEBUG
1112 "cannot join hdlc conference.\n");
1113 return -EINVAL;
1114 }
1115 }
1116 /* add conference member */
1117 err = dsp_cmx_add_conf_member(dsp, conf);
1118 if (err)
1119 return err;
1120 dsp->conf_id = conf_id;
1121
1122 /* if we are alone, we do nothing! */
1123 if (list_empty(&conf->mlist)) {
1124 if (dsp_debug & DEBUG_DSP_CMX)
1125 printk(KERN_DEBUG
1126 "we are alone in this conference, so exit.\n");
1127 /* update hardware */
1128 dsp_cmx_hardware(NULL, dsp);
1129 return 0;
1130 }
1131
1132 /* update members on conf */
1133 dsp_cmx_hardware(conf, NULL);
1134
1135 return 0;
1136}
1137
1138
1139/*
1140 * audio data is received from card
1141 */
1142void
1143dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1144{
1145 u8 *d, *p;
1146 int len = skb->len;
1147 struct mISDNhead *hh = mISDN_HEAD_P(skb);
1148 int w, i, ii;
1149
1150 /* check if we have sompen */
1151 if (len < 1)
1152 return;
1153
1154 /* half of the buffer should be larger than maximum packet size */
1155 if (len >= CMX_BUFF_HALF) {
1156 printk(KERN_ERR
1157 "%s line %d: packet from card is too large (%d bytes). "
1158 "please make card send smaller packets OR increase "
1159 "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
1160 return;
1161 }
1162
1163 /*
1164 * initialize pointers if not already -
1165 * also add delay if requested by PH_SIGNAL
1166 */
1167 if (dsp->rx_init) {
1168 dsp->rx_init = 0;
1169 if (dsp->features.unordered) {
1170 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1171 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1172 & CMX_BUFF_MASK;
1173 } else {
1174 dsp->rx_R = 0;
1175 dsp->rx_W = dsp->cmx_delay;
1176 }
1177 }
1178 /* if frame contains time code, write directly */
1179 if (dsp->features.unordered) {
1180 dsp->rx_W = (hh->id & CMX_BUFF_MASK);
1181 /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */
1182 }
1183 /*
1184 * if we underrun (or maybe overrun),
1185 * we set our new read pointer, and write silence to buffer
1186 */
1187 if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
1188 if (dsp_debug & DEBUG_DSP_CMX)
1189 printk(KERN_DEBUG
1190 "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
1191 "maximum delay), adjusting read pointer! "
1192 "(inst %s)\n", (u_long)dsp, dsp->name);
1193 /* flush buffer */
1194 if (dsp->features.unordered) {
1195 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1196 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1197 & CMX_BUFF_MASK;
1198 } else {
1199 dsp->rx_R = 0;
1200 dsp->rx_W = dsp->cmx_delay;
1201 }
1202 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1203 }
1204 /* if we have reached double delay, jump back to middle */
1205 if (dsp->cmx_delay)
1206 if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
1207 (dsp->cmx_delay << 1)) {
1208 if (dsp_debug & DEBUG_DSP_CMX)
1209 printk(KERN_DEBUG
1210 "cmx_receive(dsp=%lx): OVERRUN (because "
1211 "twice the delay is reached), adjusting "
1212 "read pointer! (inst %s)\n",
1213 (u_long)dsp, dsp->name);
1214 /* flush buffer */
1215 if (dsp->features.unordered) {
1216 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1217 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1218 & CMX_BUFF_MASK;
1219 } else {
1220 dsp->rx_R = 0;
1221 dsp->rx_W = dsp->cmx_delay;
1222 }
1223 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1224 }
1225
1226 /* show where to write */
1227#ifdef CMX_DEBUG
1228 printk(KERN_DEBUG
1229 "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n",
1230 (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name);
1231#endif
1232
1233 /* write data into rx_buffer */
1234 p = skb->data;
1235 d = dsp->rx_buff;
1236 w = dsp->rx_W;
1237 i = 0;
1238 ii = len;
1239 while (i < ii) {
1240 d[w++ & CMX_BUFF_MASK] = *p++;
1241 i++;
1242 }
1243
1244 /* increase write-pointer */
1245 dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK);
1246}
1247
1248
1249/*
1250 * send (mixed) audio data to card and control jitter
1251 */
1252static void
1253dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1254{
1255 struct dsp_conf *conf = dsp->conf;
1256 struct dsp *member, *other;
1257 register s32 sample;
1258 u8 *d, *p, *q, *o_q;
1259 struct sk_buff *nskb, *txskb;
1260 int r, rr, t, tt, o_r, o_rr;
1261 int preload = 0;
1262 struct mISDNhead *hh, *thh;
1263
1264 /* don't process if: */
1265 if (!dsp->b_active) { /* if not active */
1266 dsp->last_tx = 0;
1267 return;
1268 }
1269 if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */
1270 dsp->tx_R == dsp->tx_W && /* AND no tx-data */
1271 !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
1272 dsp->last_tx = 0;
1273 return;
1274 }
1275
1276#ifdef CMX_DEBUG
1277 printk(KERN_DEBUG
1278 "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n",
1279 members, dsp->name, conf, dsp->rx_R, dsp->rx_W);
1280#endif
1281
1282 /* preload if we have delay set */
1283 if (dsp->cmx_delay && !dsp->last_tx) {
1284 preload = len;
1285 if (preload < 128)
1286 preload = 128;
1287 }
1288
1289 /* PREPARE RESULT */
1290 nskb = mI_alloc_skb(len + preload, GFP_ATOMIC);
1291 if (!nskb) {
1292 printk(KERN_ERR
1293 "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n",
1294 len + preload);
1295 return;
1296 }
1297 hh = mISDN_HEAD_P(nskb);
1298 hh->prim = PH_DATA_REQ;
1299 hh->id = 0;
1300 dsp->last_tx = 1;
1301
1302 /* set pointers, indexes and stuff */
1303 member = dsp;
1304 p = dsp->tx_buff; /* transmit data */
1305 q = dsp->rx_buff; /* received data */
1306 d = skb_put(nskb, preload + len); /* result */
1307 t = dsp->tx_R; /* tx-pointers */
1308 tt = dsp->tx_W;
1309 r = dsp->rx_R; /* rx-pointers */
1310 rr = (r + len) & CMX_BUFF_MASK;
1311
1312 /* preload with silence, if required */
1313 if (preload) {
1314 memset(d, dsp_silence, preload);
1315 d += preload;
1316 }
1317
1318 /* PROCESS TONES/TX-DATA ONLY */
1319 if (dsp->tone.tone && dsp->tone.software) {
1320 /* -> copy tone */
1321 dsp_tone_copy(dsp, d, len);
1322 dsp->tx_R = 0; /* clear tx buffer */
1323 dsp->tx_W = 0;
1324 goto send_packet;
1325 }
1326 /* if we have tx-data but do not use mixing */
1327 if (!dsp->tx_mix && t != tt) {
1328 /* -> send tx-data and continue when not enough */
1329#ifdef CMX_TX_DEBUG
1330 sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p);
1331#endif
1332 while (r != rr && t != tt) {
1333#ifdef CMX_TX_DEBUG
1334 if (strlen(debugbuf) < 48)
1335 sprintf(debugbuf+strlen(debugbuf), " %02x", p[t]);
1336#endif
1337 *d++ = p[t]; /* write tx_buff */
1338 t = (t+1) & CMX_BUFF_MASK;
1339 r = (r+1) & CMX_BUFF_MASK;
1340 }
1341 if (r == rr) {
1342 dsp->tx_R = t;
1343#ifdef CMX_TX_DEBUG
1344 printk(KERN_DEBUG "%s\n", debugbuf);
1345#endif
1346 goto send_packet;
1347 }
1348 }
1349#ifdef CMX_TX_DEBUG
1350 printk(KERN_DEBUG "%s\n", debugbuf);
1351#endif
1352
1353 /* PROCESS DATA (one member / no conf) */
1354 if (!conf || members <= 1) {
1355 /* -> if echo is NOT enabled */
1356 if (!dsp->echo) {
1357 /* -> send tx-data if available or use 0-volume */
1358 while (r != rr && t != tt) {
1359 *d++ = p[t]; /* write tx_buff */
1360 t = (t+1) & CMX_BUFF_MASK;
1361 r = (r+1) & CMX_BUFF_MASK;
1362 }
1363 if (r != rr)
1364 memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
1365 /* -> if echo is enabled */
1366 } else {
1367 /*
1368 * -> mix tx-data with echo if available,
1369 * or use echo only
1370 */
1371 while (r != rr && t != tt) {
1372 *d++ = dsp_audio_mix_law[(p[t]<<8)|q[r]];
1373 t = (t+1) & CMX_BUFF_MASK;
1374 r = (r+1) & CMX_BUFF_MASK;
1375 }
1376 while (r != rr) {
1377 *d++ = q[r]; /* echo */
1378 r = (r+1) & CMX_BUFF_MASK;
1379 }
1380 }
1381 dsp->tx_R = t;
1382 goto send_packet;
1383 }
1384 /* PROCESS DATA (two members) */
1385#ifdef CMX_CONF_DEBUG
1386 if (0) {
1387#else
1388 if (members == 2) {
1389#endif
1390 /* "other" becomes other party */
1391 other = (list_entry(conf->mlist.next,
1392 struct dsp_conf_member, list))->dsp;
1393 if (other == member)
1394 other = (list_entry(conf->mlist.prev,
1395 struct dsp_conf_member, list))->dsp;
1396 o_q = other->rx_buff; /* received data */
1397 o_rr = (other->rx_R + len) & CMX_BUFF_MASK;
1398 /* end of rx-pointer */
1399 o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
1400 /* start rx-pointer at current read position*/
1401 /* -> if echo is NOT enabled */
1402 if (!dsp->echo) {
1403 /*
1404 * -> copy other member's rx-data,
1405 * if tx-data is available, mix
1406 */
1407 while (o_r != o_rr && t != tt) {
1408 *d++ = dsp_audio_mix_law[(p[t]<<8)|o_q[o_r]];
1409 t = (t+1) & CMX_BUFF_MASK;
1410 o_r = (o_r+1) & CMX_BUFF_MASK;
1411 }
1412 while (o_r != o_rr) {
1413 *d++ = o_q[o_r];
1414 o_r = (o_r+1) & CMX_BUFF_MASK;
1415 }
1416 /* -> if echo is enabled */
1417 } else {
1418 /*
1419 * -> mix other member's rx-data with echo,
1420 * if tx-data is available, mix
1421 */
1422 while (r != rr && t != tt) {
1423 sample = dsp_audio_law_to_s32[p[t]] +
1424 dsp_audio_law_to_s32[q[r]] +
1425 dsp_audio_law_to_s32[o_q[o_r]];
1426 if (sample < -32768)
1427 sample = -32768;
1428 else if (sample > 32767)
1429 sample = 32767;
1430 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1431 /* tx-data + rx_data + echo */
1432 t = (t+1) & CMX_BUFF_MASK;
1433 r = (r+1) & CMX_BUFF_MASK;
1434 o_r = (o_r+1) & CMX_BUFF_MASK;
1435 }
1436 while (r != rr) {
1437 *d++ = dsp_audio_mix_law[(q[r]<<8)|o_q[o_r]];
1438 r = (r+1) & CMX_BUFF_MASK;
1439 o_r = (o_r+1) & CMX_BUFF_MASK;
1440 }
1441 }
1442 dsp->tx_R = t;
1443 goto send_packet;
1444 }
1445#ifdef DSP_NEVER_DEFINED
1446 }
1447#endif
1448 /* PROCESS DATA (three or more members) */
1449 /* -> if echo is NOT enabled */
1450 if (!dsp->echo) {
1451 /*
1452 * -> substract rx-data from conf-data,
1453 * if tx-data is available, mix
1454 */
1455 while (r != rr && t != tt) {
1456 sample = dsp_audio_law_to_s32[p[t]] + *c++ -
1457 dsp_audio_law_to_s32[q[r]];
1458 if (sample < -32768)
1459 sample = -32768;
1460 else if (sample > 32767)
1461 sample = 32767;
1462 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1463 /* conf-rx+tx */
1464 r = (r+1) & CMX_BUFF_MASK;
1465 t = (t+1) & CMX_BUFF_MASK;
1466 }
1467 while (r != rr) {
1468 sample = *c++ - dsp_audio_law_to_s32[q[r]];
1469 if (sample < -32768)
1470 sample = -32768;
1471 else if (sample > 32767)
1472 sample = 32767;
1473 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1474 /* conf-rx */
1475 r = (r+1) & CMX_BUFF_MASK;
1476 }
1477 /* -> if echo is enabled */
1478 } else {
1479 /*
1480 * -> encode conf-data, if tx-data
1481 * is available, mix
1482 */
1483 while (r != rr && t != tt) {
1484 sample = dsp_audio_law_to_s32[p[t]] + *c++;
1485 if (sample < -32768)
1486 sample = -32768;
1487 else if (sample > 32767)
1488 sample = 32767;
1489 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1490 /* conf(echo)+tx */
1491 t = (t+1) & CMX_BUFF_MASK;
1492 r = (r+1) & CMX_BUFF_MASK;
1493 }
1494 while (r != rr) {
1495 sample = *c++;
1496 if (sample < -32768)
1497 sample = -32768;
1498 else if (sample > 32767)
1499 sample = 32767;
1500 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1501 /* conf(echo) */
1502 r = (r+1) & CMX_BUFF_MASK;
1503 }
1504 }
1505 dsp->tx_R = t;
1506 goto send_packet;
1507
1508send_packet:
1509 /*
1510 * send tx-data if enabled - don't filter,
1511 * becuase we want what we send, not what we filtered
1512 */
1513 if (dsp->tx_data) {
1514 /* PREPARE RESULT */
1515 txskb = mI_alloc_skb(len, GFP_ATOMIC);
1516 if (!txskb) {
1517 printk(KERN_ERR
1518 "FATAL ERROR in mISDN_dsp.o: "
1519 "cannot alloc %d bytes\n", len);
1520 } else {
1521 thh = mISDN_HEAD_P(txskb);
1522 thh->prim = DL_DATA_REQ;
1523 thh->id = 0;
1524 memcpy(skb_put(txskb, len), nskb->data+preload, len);
1525 /* queue (trigger later) */
1526 skb_queue_tail(&dsp->sendq, txskb);
1527 }
1528 }
1529 /* adjust volume */
1530 if (dsp->tx_volume)
1531 dsp_change_volume(nskb, dsp->tx_volume);
1532 /* pipeline */
1533 if (dsp->pipeline.inuse)
1534 dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len);
1535 /* crypt */
1536 if (dsp->bf_enable)
1537 dsp_bf_encrypt(dsp, nskb->data, nskb->len);
1538 /* queue and trigger */
1539 skb_queue_tail(&dsp->sendq, nskb);
1540 schedule_work(&dsp->workq);
1541}
1542
1543u32 samplecount;
1544struct timer_list dsp_spl_tl;
1545u32 dsp_spl_jiffies; /* calculate the next time to fire */
1546u32 dsp_start_jiffies; /* jiffies at the time, the calculation begins */
1547struct timeval dsp_start_tv; /* time at start of calculation */
1548
1549void
1550dsp_cmx_send(void *arg)
1551{
1552 struct dsp_conf *conf;
1553 struct dsp_conf_member *member;
1554 struct dsp *dsp;
1555 int mustmix, members;
1556 s32 mixbuffer[MAX_POLL+100], *c;
1557 u8 *p, *q;
1558 int r, rr;
1559 int jittercheck = 0, delay, i;
1560 u_long flags;
1561 struct timeval tv;
1562 u32 elapsed;
1563 s16 length;
1564
1565 /* lock */
1566 spin_lock_irqsave(&dsp_lock, flags);
1567
1568 if (!dsp_start_tv.tv_sec) {
1569 do_gettimeofday(&dsp_start_tv);
1570 length = dsp_poll;
1571 } else {
1572 do_gettimeofday(&tv);
1573 elapsed = ((tv.tv_sec - dsp_start_tv.tv_sec) * 8000)
1574 + ((s32)(tv.tv_usec / 125) - (dsp_start_tv.tv_usec / 125));
1575 dsp_start_tv.tv_sec = tv.tv_sec;
1576 dsp_start_tv.tv_usec = tv.tv_usec;
1577 length = elapsed;
1578 }
1579 if (length > MAX_POLL + 100)
1580 length = MAX_POLL + 100;
1581/* printk(KERN_DEBUG "len=%d dsp_count=0x%x.%04x dsp_poll_diff=0x%x.%04x\n",
1582 length, dsp_count >> 16, dsp_count & 0xffff, dsp_poll_diff >> 16,
1583 dsp_poll_diff & 0xffff);
1584 */
1585
1586 /*
1587 * check if jitter needs to be checked
1588 * (this is about every second = 8192 samples)
1589 */
1590 samplecount += length;
1591 if ((samplecount & 8191) < length)
1592 jittercheck = 1;
1593
1594 /* loop all members that do not require conference mixing */
1595 list_for_each_entry(dsp, &dsp_ilist, list) {
1596 if (dsp->hdlc)
1597 continue;
1598 conf = dsp->conf;
1599 mustmix = 0;
1600 members = 0;
1601 if (conf) {
1602 members = count_list_member(&conf->mlist);
1603#ifdef CMX_CONF_DEBUG
1604 if (conf->software && members > 1)
1605#else
1606 if (conf->software && members > 2)
1607#endif
1608 mustmix = 1;
1609 }
1610
1611 /* transmission required */
1612 if (!mustmix) {
1613 dsp_cmx_send_member(dsp, length, mixbuffer, members);
1614
1615 /*
1616 * unused mixbuffer is given to prevent a
1617 * potential null-pointer-bug
1618 */
1619 }
1620 }
1621
1622 /* loop all members that require conference mixing */
1623 list_for_each_entry(conf, &conf_ilist, list) {
1624 /* count members and check hardware */
1625 members = count_list_member(&conf->mlist);
1626#ifdef CMX_CONF_DEBUG
1627 if (conf->software && members > 1) {
1628#else
1629 if (conf->software && members > 2) {
1630#endif
1631 /* check for hdlc conf */
1632 member = list_entry(conf->mlist.next,
1633 struct dsp_conf_member, list);
1634 if (member->dsp->hdlc)
1635 continue;
1636 /* mix all data */
1637 memset(mixbuffer, 0, length*sizeof(s32));
1638 list_for_each_entry(member, &conf->mlist, list) {
1639 dsp = member->dsp;
1640 /* get range of data to mix */
1641 c = mixbuffer;
1642 q = dsp->rx_buff;
1643 r = dsp->rx_R;
1644 rr = (r + length) & CMX_BUFF_MASK;
1645 /* add member's data */
1646 while (r != rr) {
1647 *c++ += dsp_audio_law_to_s32[q[r]];
1648 r = (r+1) & CMX_BUFF_MASK;
1649 }
1650 }
1651
1652 /* process each member */
1653 list_for_each_entry(member, &conf->mlist, list) {
1654 /* transmission */
1655 dsp_cmx_send_member(member->dsp, length,
1656 mixbuffer, members);
1657 }
1658 }
1659 }
1660
1661 /* delete rx-data, increment buffers, change pointers */
1662 list_for_each_entry(dsp, &dsp_ilist, list) {
1663 if (dsp->hdlc)
1664 continue;
1665 p = dsp->rx_buff;
1666 q = dsp->tx_buff;
1667 r = dsp->rx_R;
1668 /* move receive pointer when receiving */
1669 if (!dsp->rx_is_off) {
1670 rr = (r + length) & CMX_BUFF_MASK;
1671 /* delete rx-data */
1672 while (r != rr) {
1673 p[r] = dsp_silence;
1674 r = (r+1) & CMX_BUFF_MASK;
1675 }
1676 /* increment rx-buffer pointer */
1677 dsp->rx_R = r; /* write incremented read pointer */
1678 }
1679
1680 /* check current rx_delay */
1681 delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK;
1682 if (delay >= CMX_BUFF_HALF)
1683 delay = 0; /* will be the delay before next write */
1684 /* check for lower delay */
1685 if (delay < dsp->rx_delay[0])
1686 dsp->rx_delay[0] = delay;
1687 /* check current tx_delay */
1688 delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK;
1689 if (delay >= CMX_BUFF_HALF)
1690 delay = 0; /* will be the delay before next write */
1691 /* check for lower delay */
1692 if (delay < dsp->tx_delay[0])
1693 dsp->tx_delay[0] = delay;
1694 if (jittercheck) {
1695 /* find the lowest of all rx_delays */
1696 delay = dsp->rx_delay[0];
1697 i = 1;
1698 while (i < MAX_SECONDS_JITTER_CHECK) {
1699 if (delay > dsp->rx_delay[i])
1700 delay = dsp->rx_delay[i];
1701 i++;
1702 }
1703 /*
1704 * remove rx_delay only if we have delay AND we
1705 * have not preset cmx_delay
1706 */
1707 if (delay && !dsp->cmx_delay) {
1708 if (dsp_debug & DEBUG_DSP_CMX)
1709 printk(KERN_DEBUG
1710 "%s lowest rx_delay of %d bytes for"
1711 " dsp %s are now removed.\n",
1712 __func__, delay,
1713 dsp->name);
1714 r = dsp->rx_R;
1715 rr = (r + delay) & CMX_BUFF_MASK;
1716 /* delete rx-data */
1717 while (r != rr) {
1718 p[r] = dsp_silence;
1719 r = (r+1) & CMX_BUFF_MASK;
1720 }
1721 /* increment rx-buffer pointer */
1722 dsp->rx_R = r;
1723 /* write incremented read pointer */
1724 }
1725 /* find the lowest of all tx_delays */
1726 delay = dsp->tx_delay[0];
1727 i = 1;
1728 while (i < MAX_SECONDS_JITTER_CHECK) {
1729 if (delay > dsp->tx_delay[i])
1730 delay = dsp->tx_delay[i];
1731 i++;
1732 }
1733 /*
1734 * remove delay only if we have delay AND we
1735 * have enabled tx_dejitter
1736 */
1737 if (delay && dsp->tx_dejitter) {
1738 if (dsp_debug & DEBUG_DSP_CMX)
1739 printk(KERN_DEBUG
1740 "%s lowest tx_delay of %d bytes for"
1741 " dsp %s are now removed.\n",
1742 __func__, delay,
1743 dsp->name);
1744 r = dsp->tx_R;
1745 rr = (r + delay) & CMX_BUFF_MASK;
1746 /* delete tx-data */
1747 while (r != rr) {
1748 q[r] = dsp_silence;
1749 r = (r+1) & CMX_BUFF_MASK;
1750 }
1751 /* increment rx-buffer pointer */
1752 dsp->tx_R = r;
1753 /* write incremented read pointer */
1754 }
1755 /* scroll up delays */
1756 i = MAX_SECONDS_JITTER_CHECK - 1;
1757 while (i) {
1758 dsp->rx_delay[i] = dsp->rx_delay[i-1];
1759 dsp->tx_delay[i] = dsp->tx_delay[i-1];
1760 i--;
1761 }
1762 dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1763 dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1764 }
1765 }
1766
1767 /* if next event would be in the past ... */
1768 if ((s32)(dsp_spl_jiffies+dsp_tics-jiffies) <= 0)
1769 dsp_spl_jiffies = jiffies + 1;
1770 else
1771 dsp_spl_jiffies += dsp_tics;
1772
1773 dsp_spl_tl.expires = dsp_spl_jiffies;
1774 add_timer(&dsp_spl_tl);
1775
1776 /* unlock */
1777 spin_unlock_irqrestore(&dsp_lock, flags);
1778}
1779
1780/*
1781 * audio data is transmitted from upper layer to the dsp
1782 */
1783void
1784dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
1785{
1786 u_int w, ww;
1787 u8 *d, *p;
1788 int space; /* todo: , l = skb->len; */
1789#ifdef CMX_TX_DEBUG
1790 char debugbuf[256] = "";
1791#endif
1792
1793 /* check if there is enough space, and then copy */
1794 w = dsp->tx_W;
1795 ww = dsp->tx_R;
1796 p = dsp->tx_buff;
1797 d = skb->data;
1798 space = ww-w;
1799 if (space <= 0)
1800 space += CMX_BUFF_SIZE;
1801 /* write-pointer should not overrun nor reach read pointer */
1802 if (space-1 < skb->len)
1803 /* write to the space we have left */
1804 ww = (ww - 1) & CMX_BUFF_MASK;
1805 else
1806 /* write until all byte are copied */
1807 ww = (w + skb->len) & CMX_BUFF_MASK;
1808 dsp->tx_W = ww;
1809
1810 /* show current buffer */
1811#ifdef CMX_DEBUG
1812 printk(KERN_DEBUG
1813 "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n",
1814 (u_long)dsp, (ww-w)&CMX_BUFF_MASK, w, ww, dsp->name);
1815#endif
1816
1817 /* copy transmit data to tx-buffer */
1818#ifdef CMX_TX_DEBUG
1819 sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p);
1820#endif
1821 while (w != ww) {
1822#ifdef CMX_TX_DEBUG
1823 if (strlen(debugbuf) < 48)
1824 sprintf(debugbuf+strlen(debugbuf), " %02x", *d);
1825#endif
1826 p[w] = *d++;
1827 w = (w+1) & CMX_BUFF_MASK;
1828 }
1829#ifdef CMX_TX_DEBUG
1830 printk(KERN_DEBUG "%s\n", debugbuf);
1831#endif
1832
1833}
1834
1835/*
1836 * hdlc data is received from card and sent to all members.
1837 */
1838void
1839dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1840{
1841 struct sk_buff *nskb = NULL;
1842 struct dsp_conf_member *member;
1843 struct mISDNhead *hh;
1844
1845 /* not if not active */
1846 if (!dsp->b_active)
1847 return;
1848
1849 /* check if we have sompen */
1850 if (skb->len < 1)
1851 return;
1852
1853 /* no conf */
1854 if (!dsp->conf) {
1855 /* in case of hardware (echo) */
1856 if (dsp->pcm_slot_tx >= 0)
1857 return;
1858 if (dsp->echo)
1859 nskb = skb_clone(skb, GFP_ATOMIC);
1860 if (nskb) {
1861 hh = mISDN_HEAD_P(nskb);
1862 hh->prim = PH_DATA_REQ;
1863 hh->id = 0;
1864 skb_queue_tail(&dsp->sendq, nskb);
1865 schedule_work(&dsp->workq);
1866 }
1867 return;
1868 }
1869 /* in case of hardware conference */
1870 if (dsp->conf->hardware)
1871 return;
1872 list_for_each_entry(member, &dsp->conf->mlist, list) {
1873 if (dsp->echo || member->dsp != dsp) {
1874 nskb = skb_clone(skb, GFP_ATOMIC);
1875 if (nskb) {
1876 hh = mISDN_HEAD_P(nskb);
1877 hh->prim = PH_DATA_REQ;
1878 hh->id = 0;
1879 skb_queue_tail(&member->dsp->sendq, nskb);
1880 schedule_work(&member->dsp->workq);
1881 }
1882 }
1883 }
1884}
1885
1886