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