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