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