Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:52 2009

## Asterisk developer's documentation

# chan_vpb.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 2003, Paul Bagyenda
    00005  * Paul Bagyenda <bagyenda@dsmagic.com>
    00006  * Copyright (C) 2004 - 2005, Ben Kramer
    00007  * Ben Kramer <ben@voicetronix.com.au>
    00008  *
    00009  * Daniel Bichara <daniel@bichara.com.br> - Brazilian CallerID detection (c)2004
    00010  *
    00011  * Welber Silveira - welberms@magiclink.com.br - (c)2004
    00012  * Copying CLID string to propper structure after detection
    00013  *
    00014  * See http://www.asterisk.org for more information about
    00015  * the Asterisk project. Please do not directly contact
    00016  * any of the maintainers of this project for assistance;
    00017  * the project provides a web site, mailing lists and IRC
    00018  * channels for your use.
    00019  *
    00020  * This program is free software, distributed under the terms of
    00021  * the GNU General Public License Version 2. See the LICENSE file
    00022  * at the top of the source tree.
    00023  */
    00024
    00025 /*! \file
    00026  *
    00027  * \brief VoiceTronix Interface driver
    00028  *
    00029  * \ingroup channel_drivers
    00030  */
    00031
    00032
    00033 extern "C" {
    00034
    00035 #include <stdio.h>
    00036 #include <string.h>
    00037
    00038 #include "asterisk.h"
    00039
    00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
    00041
    00042 #include "asterisk/lock.h"
    00043 #include "asterisk/utils.h"
    00044 #include "asterisk/channel.h"
    00045 #include "asterisk/config.h"
    00046 #include "asterisk/logger.h"
    00047 #include "asterisk/module.h"
    00048 #include "asterisk/pbx.h"
    00049 #include "asterisk/options.h"
    00050 #include "asterisk/callerid.h"
    00051 #include "asterisk/dsp.h"
    00052 #include "asterisk/features.h"
    00053 }
    00054
    00055 #include <sys/socket.h>
    00056 #include <sys/time.h>
    00057 #include <errno.h>
    00058 #include <unistd.h>
    00059 #include <stdlib.h>
    00060 #include <arpa/inet.h>
    00061 #include <fcntl.h>
    00062 #include <sys/ioctl.h>
    00063 #include <ctype.h>
    00064
    00065 #include <vpbapi.h>
    00066 #include <assert.h>
    00067
    00068 #ifdef pthread_create
    00069 #undef pthread_create
    00070 #endif
    00071
    00072 #define DEFAULT_GAIN 0
    00073 #define DEFAULT_ECHO_CANCEL 1
    00074
    00075 #define VPB_SAMPLES 160
    00076 #define VPB_MAX_BUF VPB_SAMPLES*4 + AST_FRIENDLY_OFFSET
    00077
    00078 #define VPB_NULL_EVENT 200
    00079
    00080 #define VPB_WAIT_TIMEOUT 4000
    00081
    00082 #define MAX_VPB_GAIN 12.0
    00083 #define MIN_VPB_GAIN -12.0
    00084
    00085 #define DTMF_CALLERID
    00086 #define DTMF_CID_START 'D'
    00087 #define DTMF_CID_STOP 'C'
    00088
    00089 /**/
    00090 #if defined(__cplusplus) || defined(c_plusplus)
    00091  extern "C" {
    00092 #endif
    00093 /**/
    00094
    00095 static const char desc[] = "VoiceTronix V6PCI/V12PCI/V4PCI  API Support";
    00096 static const char type[] = "vpb";
    00097 static const char tdesc[] = "Standard VoiceTronix API Driver";
    00098 static const char config[] = "vpb.conf";
    00099
    00100 /* Default context for dialtone mode */
    00101 static char context[AST_MAX_EXTENSION] = "default";
    00102
    00103 /* Default language */
    00104 static char language[MAX_LANGUAGE] = "";
    00105 static int usecnt =0;
    00106
    00107 static int gruntdetect_timeout = 3600000; /* Grunt detect timeout is 1hr. */
    00108
    00109 static const int prefformat = AST_FORMAT_SLINEAR;
    00110
    00111 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
    00112
    00113 /* Protect the interface list (of vpb_pvt's) */
    00114 AST_MUTEX_DEFINE_STATIC(iflock);
    00115
    00116 /* Protect the monitoring thread, so only one process can kill or start it, and not
    00117    when it's doing something critical. */
    00118 AST_MUTEX_DEFINE_STATIC(monlock);
    00119
    00120 /* This is the thread for the monitor which checks for input on the channels
    00121    which are not currently in use.  */
    00122 static pthread_t monitor_thread;
    00123
    00124 static int mthreadactive = -1; /* Flag for monitoring monitorthread.*/
    00125
    00126
    00127 static int restart_monitor(void);
    00128
    00129 /* The private structures of the VPB channels are
    00130    linked for selecting outgoing channels */
    00131
    00132 #define MODE_DIALTONE   1
    00133 #define MODE_IMMEDIATE  2
    00134 #define MODE_FXO  3
    00135
    00136 /* Pick a country or add your own! */
    00137 /* These are the tones that are played to the user */
    00138 #define TONES_AU
    00139 /* #define TONES_USA */
    00140
    00141 #ifdef TONES_AU
    00142 static VPB_TONE Dialtone     = {440,      440,  440,  -10,     -10,  -10,  5000, 0   };
    00143 static VPB_TONE Busytone     = {470,      0,    0,    -10,     -100,    -100,   5000,  0 };
    00144 static VPB_TONE Ringbacktone = {400,      50,      440,  -10,     -10,  -10,     1400,    800 };
    00145 #endif
    00146 #ifdef TONES_USA
    00147 static VPB_TONE Dialtone     = {350, 440,   0, -16,   -16, -100, 10000,    0};
    00148 static VPB_TONE Busytone     = {480, 620,   0, -10,   -10, -100,   500,  500};
    00149 static VPB_TONE Ringbacktone = {440, 480,   0, -20,   -20, -100,  2000, 4000};
    00150 #endif
    00151
    00152 /* grunt tone defn's */
    00153 static VPB_DETECT toned_grunt = { 3, VPB_GRUNT, 1, 2000, 3000, 0, 0, -40, 0, 0, 0, 40, { { VPB_DELAY, 1000, 0, 0 }, { VPB_RISING, 0, 40, 0 }, { 0, 100, 0, 0 } } };
    00154 static VPB_DETECT toned_ungrunt = { 2, VPB_GRUNT, 1, 2000, 1, 0, 0, -40, 0, 0, 30, 40, { { 0, 0, 0, 0 } } };
    00155
    00156 /* Use loop polarity detection for CID */
    00157 static int UsePolarityCID=0;
    00158
    00159 /* Use loop drop detection */
    00160 static int UseLoopDrop=1;
    00161
    00162 /* To use or not to use Native bridging */
    00163 static int UseNativeBridge=1;
    00164
    00165 /* Use Asterisk Indication or VPB */
    00166 static int use_ast_ind=0;
    00167
    00168 /* Use Asterisk DTMF detection or VPB */
    00169 static int use_ast_dtmfdet=0;
    00170
    00171 static int relaxdtmf=0;
    00172
    00173 /* Use Asterisk DTMF play back or VPB */
    00174 static int use_ast_dtmf=0;
    00175
    00176 /* Break for DTMF on native bridge ? */
    00177 static int break_for_dtmf=1;
    00178
    00179 /* Set EC suppression threshold */
    00180 static int ec_supp_threshold=-1;
    00181
    00182 /* Inter Digit Delay for collecting DTMF's */
    00183 static int dtmf_idd = 3000;
    00184
    00185 #define TIMER_PERIOD_RINGBACK 2000
    00186 #define TIMER_PERIOD_BUSY 700
    00187 #define TIMER_PERIOD_RING 4000
    00188 static int timer_period_ring = TIMER_PERIOD_RING;
    00189
    00190 #define VPB_EVENTS_ALL (VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
    00191          |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
    00192          |VPB_MRING_OFF|VPB_MDROP|VPB_MSTATION_FLASH)
    00193 #define VPB_EVENTS_NODROP (VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
    00194          |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
    00195          |VPB_MRING_OFF|VPB_MSTATION_FLASH)
    00196 #define VPB_EVENTS_NODTMF (VPB_MRING|VPB_MDIGIT|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
    00197          |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
    00198          |VPB_MRING_OFF|VPB_MDROP|VPB_MSTATION_FLASH)
    00199 #define VPB_EVENTS_STAT (VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
    00200          |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
    00201          |VPB_MRING_OFF|VPB_MSTATION_FLASH)
    00202
    00203
    00204 /* Dialing parameters for Australia */
    00205 /* #define DIAL_WITH_CALL_PROGRESS */
    00206 VPB_TONE_MAP DialToneMap[] = {   { VPB_BUSY_AUST, VPB_CALL_DISCONNECT, 0 },
    00207             { VPB_DIAL, VPB_CALL_DIALTONE, 0 },
    00208             { VPB_RINGBACK_308, VPB_CALL_RINGBACK, 0 },
    00209             { VPB_BUSY_AUST, VPB_CALL_BUSY, 0 },
    00210             { VPB_GRUNT, VPB_CALL_GRUNT, 0 },
    00211             { 0, 0, 1 } };
    00212 #define VPB_DIALTONE_WAIT 2000 /* Wait up to 2s for a dialtone */
    00213 #define VPB_RINGWAIT 4000 /* Wait up to 4s for ring tone after dialing */
    00214 #define VPB_CONNECTED_WAIT 4000 /* If no ring tone detected for 4s then consider call connected */
    00215 #define TIMER_PERIOD_NOANSWER 120000 /* Let it ring for 120s before deciding theres noone there */
    00216
    00217 #define MAX_BRIDGES_V4PCI 2
    00218 #define MAX_BRIDGES_V12PCI 128
    00219
    00220 /* port states */
    00221 #define VPB_STATE_ONHOOK   0
    00222 #define VPB_STATE_OFFHOOK  1
    00223 #define VPB_STATE_DIALLING 2
    00224 #define VPB_STATE_JOINED   3
    00225 #define VPB_STATE_GETDTMF  4
    00226 #define VPB_STATE_PLAYDIAL 5
    00227 #define VPB_STATE_PLAYBUSY 6
    00228 #define VPB_STATE_PLAYRING 7
    00229
    00230 #define VPB_GOT_RXHWG      1
    00231 #define VPB_GOT_TXHWG      2
    00232 #define VPB_GOT_RXSWG      4
    00233 #define VPB_GOT_TXSWG      8
    00234
    00235 typedef struct  {
    00236    int inuse;
    00237    struct ast_channel *c0, *c1, **rc;
    00238    struct ast_frame **fo;
    00239    int flags;
    00240    ast_mutex_t lock;
    00241    ast_cond_t cond;
    00242    int endbridge;
    00243 } vpb_bridge_t;
    00244
    00245 static vpb_bridge_t * bridges;
    00246 static int max_bridges = MAX_BRIDGES_V4PCI;
    00247
    00248 AST_MUTEX_DEFINE_STATIC(bridge_lock);
    00249
    00250 typedef enum {
    00251    vpb_model_unknown = 0,
    00252    vpb_model_v4pci,
    00253    vpb_model_v12pci
    00254 } vpb_model_t;
    00255
    00256 static struct vpb_pvt {
    00257
    00258    ast_mutex_t owner_lock;       /* Protect blocks that expect ownership to remain the same */
    00259    struct ast_channel *owner;    /* Channel who owns us, possibly NULL */
    00260
    00261    int golock;          /* Got owner lock ? */
    00262
    00263    int mode;            /* fxo/imediate/dialtone*/
    00264    int handle;          /* Handle for vpb interface */
    00265
    00266    int state;           /* used to keep port state (internal to driver) */
    00267
    00268    int group;           /* Which group this port belongs to */
    00269    ast_group_t callgroup;                  /* Call group */
    00270    ast_group_t pickupgroup;                /* Pickup group */
    00271
    00272
    00273    char dev[256];          /* Device name, eg vpb/1-1 */
    00274    vpb_model_t vpb_model;        /* card model */
    00275
    00276    struct ast_frame f, fr;       /* Asterisk frame interface */
    00277    char buf[VPB_MAX_BUF];        /* Static buffer for reading frames */
    00278
    00279    int dialtone;           /* NOT USED */
    00280    float txgain, rxgain;         /* Hardware gain control */
    00281    float txswgain, rxswgain;     /* Software gain control */
    00282
    00283    int wantdtmf;           /* Waiting for DTMF. */
    00284    char context[AST_MAX_EXTENSION]; /* The context for this channel */
    00285
    00286    char ext[AST_MAX_EXTENSION];     /* DTMF buffer for the ext[ens] */
    00287    char language[MAX_LANGUAGE];     /* language being used */
    00288    char callerid[AST_MAX_EXTENSION];   /* CallerId used for directly connected phone */
    00289    int  callerid_type;        /* Caller ID type: 0=>none 1=>vpb 2=>AstV23 3=>AstBell */
    00290    char cid_num[AST_MAX_EXTENSION];
    00291    char cid_name[AST_MAX_EXTENSION];
    00292
    00293    int dtmf_caller_pos;       /* DTMF CallerID detection (Brazil)*/
    00294
    00295    int lastoutput;            /* Holds the last Audio format output'ed */
    00296    int lastinput;          /* Holds the last Audio format input'ed */
    00297    int last_ignore_dtmf;
    00298
    00299    void *busy_timer;       /* Void pointer for busy vpb_timer */
    00300    int busy_timer_id;         /* unique timer ID for busy timer */
    00301
    00302    void *ringback_timer;         /* Void pointer for ringback vpb_timer */
    00303    int ringback_timer_id;        /* unique timer ID for ringback timer */
    00304
    00305    void *ring_timer;       /* Void pointer for ring vpb_timer */
    00306    int ring_timer_id;         /* unique timer ID for ring timer */
    00307
    00308    void *dtmfidd_timer;       /* Void pointer for DTMF IDD vpb_timer */
    00309    int dtmfidd_timer_id;         /* unique timer ID for DTMF IDD timer */
    00310
    00311    struct ast_dsp *vad;       /* AST  Voice Activation Detection dsp */
    00312
    00313    struct timeval lastgrunt;        /* time stamp of last grunt event */
    00314
    00315    ast_mutex_t lock;       /* This one just protects bridge ptr below */
    00316    vpb_bridge_t *bridge;
    00317
    00318    int stopreads;             /* Stop reading...*/
    00319    int read_state;            /* Read state */
    00320    int chuck_count;        /* a count of packets weve chucked away!*/
    00321    pthread_t readthread;         /* For monitoring read channel. One per owned channel. */
    00322
    00323    ast_mutex_t record_lock;      /* This one prevents reentering a record_buf block */
    00324    ast_mutex_t play_lock;        /* This one prevents reentering a play_buf block */
    00325    int  play_buf_time;        /* How long the last play_buf took */
    00326    struct timeval lastplay;      /* Last play time */
    00327
    00328    ast_mutex_t play_dtmf_lock;
    00329    char play_dtmf[16];
    00330
    00331    int faxhandled;            /* has a fax tone been handled ? */
    00332
    00333    struct vpb_pvt *next;         /* Next channel in list */
    00334
    00335 } *iflist = NULL;
    00336
    00337 static struct ast_channel *vpb_new(struct vpb_pvt *i, int state, char *context);
    00338 static void *do_chanreads(void *pvt);
    00339
    00340 static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause);
    00341 static int vpb_digit(struct ast_channel *ast, char digit);
    00342 static int vpb_call(struct ast_channel *ast, char *dest, int timeout);
    00343 static int vpb_hangup(struct ast_channel *ast);
    00344 static int vpb_answer(struct ast_channel *ast);
    00345 static struct ast_frame *vpb_read(struct ast_channel *ast);
    00346 static int vpb_write(struct ast_channel *ast, struct ast_frame *frame);
    00347 static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
    00348 static int vpb_indicate(struct ast_channel *ast, int condition);
    00349 static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
    00350
    00351 static struct ast_channel_tech vpb_tech = {
    00352    type: type,
    00353    description: tdesc,
    00354    capabilities: AST_FORMAT_SLINEAR,
    00355    properties: NULL,
    00356    requester: vpb_request,
    00357    devicestate: NULL,
    00358    send_digit: vpb_digit,
    00359    call: vpb_call,
    00360    hangup: vpb_hangup,
    00361    answer: vpb_answer,
    00362    read: vpb_read,
    00363    write: vpb_write,
    00364    send_text: NULL,
    00365    send_image: NULL,
    00366    send_html: NULL,
    00367    exception: NULL,
    00368    bridge: vpb_bridge,
    00369    indicate: vpb_indicate,
    00370    fixup: vpb_fixup,
    00371    setoption: NULL,
    00372    queryoption: NULL,
    00373    transfer: NULL,
    00374    write_video: NULL,
    00375    bridged_channel: NULL
    00376 };
    00377
    00378 static struct ast_channel_tech vpb_tech_indicate = {
    00379    type: type,
    00380    description: tdesc,
    00381    capabilities: AST_FORMAT_SLINEAR,
    00382    properties: NULL,
    00383    requester: vpb_request,
    00384    devicestate: NULL,
    00385    send_digit: vpb_digit,
    00386    call: vpb_call,
    00387    hangup: vpb_hangup,
    00388    answer: vpb_answer,
    00389    read: vpb_read,
    00390    write: vpb_write,
    00391    send_text: NULL,
    00392    send_image: NULL,
    00393    send_html: NULL,
    00394    exception: NULL,
    00395    bridge: vpb_bridge,
    00396    indicate: NULL,
    00397    fixup: vpb_fixup,
    00398    setoption: NULL,
    00399    queryoption: NULL,
    00400    transfer: NULL,
    00401    write_video: NULL,
    00402    bridged_channel: NULL
    00403 };
    00404
    00405 /* Can't get vpb_bridge() working on v4pci without either a horrible
    00406 *  high pitched feedback noise or bad hiss noise depending on gain settings
    00407 *  Get asterisk to do the bridging
    00408 */
    00409 #define BAD_V4PCI_BRIDGE
    00410
    00411 /* This one enables a half duplex bridge which may be required to prevent high pitched
    00412  * feedback when getting asterisk to do the bridging and when using certain gain settings.
    00413  */
    00414 /* #define HALF_DUPLEX_BRIDGE */
    00415
    00416 /* This is the Native bridge code, which Asterisk will try before using its own bridging code */
    00417 static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
    00418 {
    00419    struct vpb_pvt *p0 = (struct vpb_pvt *)c0->tech_pvt;
    00420    struct vpb_pvt *p1 = (struct vpb_pvt *)c1->tech_pvt;
    00421    int i;
    00422    int res;
    00423    struct ast_channel *cs[3];
    00424    struct ast_channel *who;
    00425    struct ast_frame *f;
    00426
    00427    cs[0] = c0;
    00428    cs[1] = c1;
    00429
    00430    #ifdef BAD_V4PCI_BRIDGE
    00431    if(p0->vpb_model==vpb_model_v4pci)
    00432       return AST_BRIDGE_FAILED_NOWARN;
    00433    #endif
    00434    if ( UseNativeBridge != 1){
    00435       return AST_BRIDGE_FAILED_NOWARN;
    00436    }
    00437
    00438 /*
    00439    ast_mutex_lock(&p0->lock);
    00440    ast_mutex_lock(&p1->lock);
    00441 */
    00442
    00443    /* Bridge channels, check if we can.  I believe we always can, so find a slot.*/
    00444
    00445    ast_mutex_lock(&bridge_lock); {
    00446       for (i = 0; i < max_bridges; i++)
    00447          if (!bridges[i].inuse)
    00448             break;
    00449       if (i < max_bridges) {
    00450          bridges[i].inuse = 1;
    00451          bridges[i].endbridge = 0;
    00452          bridges[i].flags = flags;
    00453          bridges[i].rc = rc;
    00454          bridges[i].fo = fo;
    00455          bridges[i].c0 = c0;
    00456          bridges[i].c1 = c1;
    00457       }
    00458    } ast_mutex_unlock(&bridge_lock);
    00459
    00460    if (i == max_bridges) {
    00461       ast_log(LOG_WARNING, "%s: vpb_bridge: Failed to bridge %s and %s!\n", p0->dev, c0->name, c1->name);
    00462       ast_mutex_unlock(&p0->lock);
    00463       ast_mutex_unlock(&p1->lock);
    00464       return AST_BRIDGE_FAILED_NOWARN;
    00465    } else {
    00466       /* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
    00467       ast_mutex_lock(&p0->lock); {
    00468          p0->bridge = &bridges[i];
    00469       } ast_mutex_unlock(&p0->lock);
    00470
    00471       ast_mutex_lock(&p1->lock); {
    00472          p1->bridge = &bridges[i];
    00473       } ast_mutex_unlock(&p1->lock);
    00474
    00475       if (option_verbose>1)
    00476          ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Bridging call entered with [%s, %s]\n",p0->dev, c0->name, c1->name);
    00477    }
    00478
    00479    #ifdef HALF_DUPLEX_BRIDGE
    00480
    00481    if (option_verbose>1)
    00482       ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Starting half-duplex bridge [%s, %s]\n",p0->dev, c0->name, c1->name);
    00483
    00484    int dir = 0;
    00485
    00486    memset(p0->buf, 0, sizeof p0->buf);
    00487    memset(p1->buf, 0, sizeof p1->buf);
    00488
    00489    vpb_record_buf_start(p0->handle, VPB_ALAW);
    00490    vpb_record_buf_start(p1->handle, VPB_ALAW);
    00491
    00492    vpb_play_buf_start(p0->handle, VPB_ALAW);
    00493    vpb_play_buf_start(p1->handle, VPB_ALAW);
    00494
    00495    while( !bridges[i].endbridge ) {
    00496       struct vpb_pvt *from, *to;
    00497       if(++dir%2) {
    00498          from = p0;
    00499          to = p1;
    00500       } else {
    00501          from = p1;
    00502          to = p0;
    00503       }
    00504       vpb_record_buf_sync(from->handle, from->buf, VPB_SAMPLES);
    00505       vpb_play_buf_sync(to->handle, from->buf, VPB_SAMPLES);
    00506    }
    00507
    00508    vpb_record_buf_finish(p0->handle);
    00509    vpb_record_buf_finish(p1->handle);
    00510
    00511    vpb_play_buf_finish(p0->handle);
    00512    vpb_play_buf_finish(p1->handle);
    00513
    00514    if (option_verbose>1)
    00515       ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Finished half-duplex bridge [%s, %s]\n",p0->dev, c0->name, c1->name);
    00516
    00517    res = VPB_OK;
    00518
    00519    #else
    00520
    00521    res = vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_ON, i+1 /* resource 1 & 2 only for V4PCI*/ );
    00522    if (res == VPB_OK) {
    00523       /* pthread_cond_wait(&bridges[i].cond, &bridges[i].lock);*/ /* Wait for condition signal. */
    00524       while( !bridges[i].endbridge ) {
    00525          /* Are we really ment to be doing nothing ?!?! */
    00526          who = ast_waitfor_n(cs, 2, &timeoutms);
    00527          if (!who) {
    00528             if (!timeoutms) {
    00529                res = AST_BRIDGE_RETRY;
    00530                break;
    00531             }
    00532             ast_log(LOG_DEBUG, "%s: vpb_bridge: Empty frame read...\n",p0->dev);
    00533             /* check for hangup / whentohangup */
    00534             if (ast_check_hangup(c0) || ast_check_hangup(c1))
    00535                break;
    00536             continue;
    00537          }
    00538          f = ast_read(who);
    00539          if (!f || ((f->frametype == AST_FRAME_DTMF) &&
    00540                   (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
    00541                    ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
    00542             *fo = f;
    00543             *rc = who;
    00544             ast_log(LOG_DEBUG, "%s: vpb_bridge: Got a [%s]\n",p0->dev, f ? "digit" : "hangup");
    00545 /*
    00546             if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
    00547                if (pr0->set_rtp_peer(c0, NULL, NULL, 0))
    00548                   ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
    00549             }
    00550             if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
    00551                if (pr1->set_rtp_peer(c1, NULL, NULL, 0))
    00552                   ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
    00553             }
    00554 */
    00555             /* That's all we needed */
    00556             /*return 0; */
    00557             /* Check if we need to break */
    00558             if (break_for_dtmf){
    00559                break;
    00560             }
    00561             else if ((f->frametype == AST_FRAME_DTMF) && ((f->subclass == '#')||(f->subclass == '*'))){
    00562                break;
    00563             }
    00564          } else {
    00565             if ((f->frametype == AST_FRAME_DTMF) ||
    00566                (f->frametype == AST_FRAME_VOICE) ||
    00567                (f->frametype == AST_FRAME_VIDEO))
    00568                {
    00569                /* Forward voice or DTMF frames if they happen upon us */
    00570                /* Actually I dont think we want to forward on any frames!
    00571                if (who == c0) {
    00572                   ast_write(c1, f);
    00573                } else if (who == c1) {
    00574                   ast_write(c0, f);
    00575                }
    00576                */
    00577             }
    00578             ast_frfree(f);
    00579          }
    00580          /* Swap priority not that it's a big deal at this point */
    00581          cs[2] = cs[0];
    00582          cs[0] = cs[1];
    00583          cs[1] = cs[2];
    00584       };
    00585       vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_OFF, i+1 /* resource 1 & 2 only for V4PCI*/ );
    00586    }
    00587
    00588    #endif
    00589
    00590    ast_mutex_lock(&bridge_lock); {
    00591       bridges[i].inuse = 0;
    00592    } ast_mutex_unlock(&bridge_lock);
    00593
    00594    p0->bridge = NULL;
    00595    p1->bridge = NULL;
    00596
    00597
    00598    if (option_verbose>1)
    00599       ast_verbose(VERBOSE_PREFIX_2 "Bridging call done with [%s, %s] => %d\n", c0->name, c1->name, res);
    00600
    00601 /*
    00602    ast_mutex_unlock(&p0->lock);
    00603    ast_mutex_unlock(&p1->lock);
    00604 */
    00605    return (res==VPB_OK) ? AST_BRIDGE_COMPLETE : AST_BRIDGE_FAILED;
    00606 }
    00607
    00608 /* Caller ID can be located in different positions between the rings depending on your Telco
    00609  * Australian (Telstra) callerid starts 700ms after 1st ring and finishes 1.5s after first ring
    00610  * Use ANALYSE_CID to record rings and determine location of callerid
    00611  */
    00612 /* #define ANALYSE_CID */
    00613 #define RING_SKIP 300
    00614 #define CID_MSECS 2000
    00615
    00616 static void get_callerid(struct vpb_pvt *p)
    00617 {
    00618    short buf[CID_MSECS*8]; /* 8kHz sampling rate */
    00619    struct timeval cid_record_time;
    00620    int rc;
    00621    struct ast_channel *owner = p->owner;
    00622 /*
    00623    char callerid[AST_MAX_EXTENSION] = "";
    00624 */
    00625 #ifdef ANALYSE_CID
    00626    void * ws;
    00627    char * file="cidsams.wav";
    00628 #endif
    00629
    00630
    00631    if( ast_mutex_trylock(&p->record_lock) == 0 ) {
    00632
    00633       cid_record_time = ast_tvnow();
    00634       if (option_verbose>3)
    00635          ast_verbose(VERBOSE_PREFIX_4 "CID record - start\n");
    00636
    00637       /* Skip any trailing ringtone */
    00638       if (UsePolarityCID != 1){
    00639          vpb_sleep(RING_SKIP);
    00640       }
    00641
    00642       if (option_verbose>3)
    00643          ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %ldms trailing ring\n",
    00644              ast_tvdiff_ms(ast_tvnow(), cid_record_time));
    00645       cid_record_time = ast_tvnow();
    00646
    00647       /* Record bit between the rings which contains the callerid */
    00648       vpb_record_buf_start(p->handle, VPB_LINEAR);
    00649       rc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
    00650       vpb_record_buf_finish(p->handle);
    00651 #ifdef ANALYSE_CID
    00652       vpb_wave_open_write(&ws, file, VPB_LINEAR);
    00653       vpb_wave_write(ws,(char*)buf,sizeof(buf));
    00654       vpb_wave_close_write(ws);
    00655 #endif
    00656
    00657       if (option_verbose>3)
    00658          ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %ldms between rings\n",
    00659              ast_tvdiff_ms(ast_tvnow(), cid_record_time));
    00660
    00661       ast_mutex_unlock(&p->record_lock);
    00662
    00663       if( rc != VPB_OK ) {
    00664          ast_log(LOG_ERROR, "Failed to record caller id sample on %s\n", p->dev );
    00665          return;
    00666       }
    00667
    00668       VPB_CID *cli_struct = new VPB_CID;
    00669       cli_struct->ra_cldn[0]=0;
    00670       cli_struct->ra_cn[0]=0;
    00671       /* This decodes FSK 1200baud type callerid */
    00672       if ((rc=vpb_cid_decode2(cli_struct, buf, CID_MSECS*8)) == VPB_OK ) {
    00673          /*
    00674          if (owner->cid.cid_num)
    00675             free(owner->cid.cid_num);
    00676          owner->cid.cid_num=NULL;
    00677          if (owner->cid.cid_name)
    00678             free(owner->cid.cid_name);
    00679          owner->cid.cid_name=NULL;
    00680          */
    00681
    00682          if (cli_struct->ra_cldn[0]=='\0'){
    00683             /*
    00684             owner->cid.cid_num = strdup(cli_struct->cldn);
    00685             owner->cid.cid_name = strdup(cli_struct->cn);
    00686             */
    00687             if (owner){
    00688                ast_set_callerid(owner, cli_struct->cldn, cli_struct->cn, cli_struct->cldn);
    00689             } else {
    00690                strcpy(p->cid_num, cli_struct->cldn);
    00691                strcpy(p->cid_name, cli_struct->cn);
    00692
    00693             }
    00694             if (option_verbose>3)
    00695                ast_verbose(VERBOSE_PREFIX_4 "CID record - got [%s] [%s]\n",owner->cid.cid_num,owner->cid.cid_name );
    00696             snprintf(p->callerid,sizeof(p->callerid)-1,"%s %s",cli_struct->cldn,cli_struct->cn);
    00697          }
    00698          else {
    00699             ast_log(LOG_ERROR,"CID record - No caller id avalable on %s \n", p->dev);
    00700          }
    00701
    00702       } else {
    00703          ast_log(LOG_ERROR, "CID record - Failed to decode caller id on %s - %s\n", p->dev, vpb_strerror(rc) );
    00704          strncpy(p->callerid,"unknown", sizeof(p->callerid) - 1);
    00705       }
    00706       delete cli_struct;
    00707
    00708    } else
    00709       ast_log(LOG_ERROR, "CID record - Failed to set record mode for caller id on %s\n", p->dev );
    00710 }
    00711
    00712 static void get_callerid_ast(struct vpb_pvt *p)
    00713 {
    00714    struct callerid_state *cs;
    00715    char buf[1024];
    00716    char *name=NULL, *number=NULL;
    00717    int flags;
    00718    int rc=0,vrc;
    00719    int sam_count=0;
    00720    struct ast_channel *owner = p->owner;
    00721    int which_cid;
    00722 /*
    00723    float old_gain;
    00724 */
    00725 #ifdef ANALYSE_CID
    00726    void * ws;
    00727    char * file="cidsams.wav";
    00728 #endif
    00729
    00730    if(p->callerid_type == 1) {
    00731    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collected caller ID already\n");
    00732       return;
    00733    }
    00734    else if(p->callerid_type == 2 ) {
    00735       which_cid=CID_SIG_V23;
    00736    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID v23...\n");
    00737    }
    00738    else if(p->callerid_type == 3) {
    00739       which_cid=CID_SIG_BELL;
    00740    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID bell...\n");
    00741    }
    00742    else {
    00743       if (option_verbose>3)
    00744          ast_verbose(VERBOSE_PREFIX_4 "Caller ID disabled\n");
    00745       return;
    00746    }
    00747 /* vpb_sleep(RING_SKIP); */
    00748 /* vpb_record_get_gain(p->handle, &old_gain); */
    00749    cs = callerid_new(which_cid);
    00750    if (cs){
    00751 #ifdef ANALYSE_CID
    00752       vpb_wave_open_write(&ws, file, VPB_MULAW);
    00753       vpb_record_set_gain(p->handle, 3.0);
    00754       vpb_record_set_hw_gain(p->handle,12.0);
    00755 #endif
    00756       vpb_record_buf_start(p->handle, VPB_MULAW);
    00757       while((rc == 0)&&(sam_count<8000*3)){
    00758          vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
    00759          if (vrc != VPB_OK)
    00760             ast_log(LOG_ERROR, "%s: Caller ID couldnt read audio buffer!\n",p->dev);
    00761          rc = callerid_feed(cs,(unsigned char *)buf,sizeof(buf),AST_FORMAT_ULAW);
    00762 #ifdef ANALYSE_CID
    00763          vpb_wave_write(ws,(char*)buf,sizeof(buf));
    00764 #endif
    00765          sam_count+=sizeof(buf);
    00766          if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID samples [%d][%d]...\n",sam_count,rc);
    00767       }
    00768       vpb_record_buf_finish(p->handle);
    00769 #ifdef ANALYSE_CID
    00770       vpb_wave_close_write(ws);
    00771 #endif
    00772       if (rc == 1){
    00773          callerid_get(cs, &name, &number, &flags);
    00774          if (option_verbose>0)
    00775             ast_verbose(VERBOSE_PREFIX_1 "%s: Caller ID name [%s] number [%s] flags [%d]\n",p->dev,name, number,flags);
    00776       }
    00777       else {
    00778          ast_log(LOG_ERROR, "%s: Failed to decode Caller ID \n", p->dev );
    00779       }
    00780 /*    vpb_record_set_gain(p->handle, old_gain); */
    00781 /*    vpb_record_set_hw_gain(p->handle,6.0); */
    00782    }
    00783    else {
    00784       ast_log(LOG_ERROR, "%s: Failed to create Caller ID struct\n", p->dev );
    00785    }
    00786    if (owner->cid.cid_num) {
    00787       free(owner->cid.cid_num);
    00788       owner->cid.cid_num = NULL;
    00789    }
    00790    if (owner->cid.cid_name) {
    00791       free(owner->cid.cid_name);
    00792       owner->cid.cid_name = NULL;
    00793    }
    00794    if (number)
    00795       ast_shrink_phone_number(number);
    00796    if (!ast_strlen_zero(number)) {
    00797       owner->cid.cid_num = strdup(number);
    00798       owner->cid.cid_ani = strdup(number);
    00799       if (!ast_strlen_zero(name)){
    00800          owner->cid.cid_name = strdup(name);
    00801          snprintf(p->callerid,(sizeof(p->callerid)-1),"%s %s",number,name);
    00802       }
    00803       else {
    00804          snprintf(p->callerid,(sizeof(p->callerid)-1),"%s",number);
    00805       }
    00806    }
    00807
    00808    if (cs)
    00809       callerid_free(cs);
    00810 }
    00811
    00812 /* Terminate any tones we are presently playing */
    00813 static void stoptone( int handle)
    00814 {
    00815    int ret;
    00816    VPB_EVENT je;
    00817    while(vpb_playtone_state(handle)!=VPB_OK){
    00818       vpb_tone_terminate(handle);
    00819       ret = vpb_get_event_ch_async(handle,&je);
    00820       if ((ret == VPB_OK)&&(je.type != VPB_DIALEND)){
    00821          if (option_verbose > 3){
    00822                ast_verbose(VERBOSE_PREFIX_4 "Stop tone collected a wrong event!![%d]\n",je.type);
    00823          }
    00824 /*       vpb_put_event(&je); */
    00825       }
    00826       vpb_sleep(10);
    00827    }
    00828 }
    00829
    00830 /* Safe vpb_playtone_async */
    00831 static int playtone( int handle, VPB_TONE *tone)
    00832 {
    00833    int ret=VPB_OK;
    00834    stoptone(handle);
    00835    if (option_verbose > 3)
    00836       ast_verbose(VERBOSE_PREFIX_4 "[%02d]: Playing tone\n", handle);
    00837    ret = vpb_playtone_async(handle, tone);
    00838    return ret;
    00839 }
    00840
    00841 static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
    00842 {
    00843    struct ast_frame f = {AST_FRAME_CONTROL}; /* default is control, Clear rest. */
    00844    int endbridge = 0;
    00845    int res=0;
    00846
    00847    if (option_verbose > 3)
    00848       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: got event: [%d=>%d]\n", p->dev, e->type, e->data);
    00849
    00850    f.src = (char *)type;
    00851    switch (e->type) {
    00852       case VPB_RING:
    00853          if (p->mode == MODE_FXO) {
    00854             f.subclass = AST_CONTROL_RING;
    00855             vpb_timer_stop(p->ring_timer);
    00856             vpb_timer_start(p->ring_timer);
    00857          } else
    00858             f.frametype = -1; /* ignore ring on station port. */
    00859          break;
    00860
    00861       case VPB_RING_OFF:
    00862          f.frametype = -1;
    00863          break;
    00864
    00865       case VPB_TIMEREXP:
    00866          if (e->data == p->busy_timer_id) {
    00867             playtone(p->handle,&Busytone);
    00868             p->state = VPB_STATE_PLAYBUSY;
    00869             vpb_timer_stop(p->busy_timer);
    00870             vpb_timer_start(p->busy_timer);
    00871             f.frametype = -1;
    00872          } else if (e->data == p->ringback_timer_id) {
    00873             playtone(p->handle, &Ringbacktone);
    00874             vpb_timer_stop(p->ringback_timer);
    00875             vpb_timer_start(p->ringback_timer);
    00876             f.frametype = -1;
    00877          } else if (e->data == p->ring_timer_id) {
    00878             /* We didnt get another ring in time! */
    00879             if (p->owner->_state != AST_STATE_UP)  {
    00880                 /* Assume caller has hung up */
    00881                vpb_timer_stop(p->ring_timer);
    00882                f.subclass = AST_CONTROL_HANGUP;
    00883             } else {
    00884                vpb_timer_stop(p->ring_timer);
    00885                f.frametype = -1;
    00886             }
    00887
    00888          } else {
    00889             f.frametype = -1; /* Ignore. */
    00890          }
    00891          break;
    00892
    00893       case VPB_DTMF_DOWN:
    00894       case VPB_DTMF:
    00895          if (use_ast_dtmfdet){
    00896             f.frametype = -1;
    00897          } else if (p->owner->_state == AST_STATE_UP) {
    00898                f.frametype = AST_FRAME_DTMF;
    00899                f.subclass = e->data;
    00900          } else
    00901             f.frametype = -1;
    00902          break;
    00903
    00904       case VPB_TONEDETECT:
    00905          if (e->data == VPB_BUSY || e->data == VPB_BUSY_308 || e->data == VPB_BUSY_AUST ) {
    00906             if (option_verbose > 3)
    00907                ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: got event: BUSY\n", p->dev);
    00908             if (p->owner->_state == AST_STATE_UP) {
    00909                f.subclass = AST_CONTROL_HANGUP;
    00910             }
    00911             else {
    00912                f.subclass = AST_CONTROL_BUSY;
    00913             }
    00914          }
    00915          else if (e->data == VPB_FAX){
    00916             if (!p->faxhandled){
    00917                if (strcmp(p->owner->exten, "fax")) {
    00918                   const char *target_context = ast_strlen_zero(p->owner->macrocontext) ? p->owner->context : p->owner->macrocontext;
    00919
    00920                   if (ast_exists_extension(p->owner, target_context, "fax", 1, p->owner->cid.cid_num)) {
    00921                      if (option_verbose > 2)
    00922                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", p->owner->name);
    00923                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
    00924                      pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten);
    00925                      if (ast_async_goto(p->owner, target_context, "fax", 1))
    00926                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name, target_context);
    00927                   } else
    00928                      ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
    00929                } else
    00930                   ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
    00931             } else
    00932                ast_log(LOG_DEBUG, "Fax already handled\n");
    00933
    00934          }
    00935          else if (e->data == VPB_GRUNT) {
    00936             if ( ast_tvdiff_ms(ast_tvnow(), p->lastgrunt) > gruntdetect_timeout ) {
    00937                /* Nothing heard on line for a very long time
    00938                 * Timeout connection */
    00939                if (option_verbose > 2)
    00940                   ast_verbose(VERBOSE_PREFIX_3 "grunt timeout\n");
    00941                ast_log(LOG_NOTICE,"%s: Line hangup due of lack of conversation\n",p->dev);
    00942                f.subclass = AST_CONTROL_HANGUP;
    00943             } else {
    00944                p->lastgrunt = ast_tvnow();
    00945                f.frametype = -1;
    00946             }
    00947          }
    00948          else {
    00949             f.frametype = -1;
    00950          }
    00951          break;
    00952
    00953       case VPB_CALLEND:
    00954          #ifdef DIAL_WITH_CALL_PROGRESS
    00955          if (e->data == VPB_CALL_CONNECTED)
    00956             f.subclass = AST_CONTROL_ANSWER;
    00957          else if (e->data == VPB_CALL_NO_DIAL_TONE || e->data == VPB_CALL_NO_RING_BACK)
    00958             f.subclass =  AST_CONTROL_CONGESTION;
    00959          else if (e->data == VPB_CALL_NO_ANSWER || e->data == VPB_CALL_BUSY)
    00960             f.subclass = AST_CONTROL_BUSY;
    00961          else if (e->data  == VPB_CALL_DISCONNECTED)
    00962             f.subclass = AST_CONTROL_HANGUP;
    00963          #else
    00964          ast_log(LOG_NOTICE,"%s: Got call progress callback but blind dialing \n", p->dev);
    00965          f.frametype = -1;
    00966          #endif
    00967          break;
    00968
    00969       case VPB_STATION_OFFHOOK:
    00970          f.subclass = AST_CONTROL_ANSWER;
    00971          break;
    00972
    00973       case VPB_DROP:
    00974          if ((p->mode == MODE_FXO)&&(UseLoopDrop)){ /* ignore loop drop on stations */
    00975             if (p->owner->_state == AST_STATE_UP)
    00976                f.subclass = AST_CONTROL_HANGUP;
    00977             else
    00978                f.frametype = -1;
    00979          }
    00980          break;
    00981       case VPB_LOOP_ONHOOK:
    00982          if (p->owner->_state == AST_STATE_UP)
    00983             f.subclass = AST_CONTROL_HANGUP;
    00984          else
    00985             f.frametype = -1;
    00986          break;
    00987       case VPB_STATION_ONHOOK:
    00988          f.subclass = AST_CONTROL_HANGUP;
    00989          break;
    00990
    00991       case VPB_STATION_FLASH:
    00992          f.subclass = AST_CONTROL_FLASH;
    00993          break;
    00994
    00995       /* Called when dialing has finished and ringing starts
    00996        * No indication that call has really been answered when using blind dialing
    00997        */
    00998       case VPB_DIALEND:
    00999          if (p->state < 5){
    01000             f.subclass = AST_CONTROL_ANSWER;
    01001             if (option_verbose > 1)
    01002                ast_verbose(VERBOSE_PREFIX_2 "%s: Dialend\n", p->dev);
    01003          } else {
    01004             f.frametype = -1;
    01005          }
    01006          break;
    01007
    01008       case VPB_PLAY_UNDERFLOW:
    01009          f.frametype = -1;
    01010          vpb_reset_play_fifo_alarm(p->handle);
    01011          break;
    01012
    01013       case VPB_RECORD_OVERFLOW:
    01014          f.frametype = -1;
    01015          vpb_reset_record_fifo_alarm(p->handle);
    01016          break;
    01017
    01018       default:
    01019          f.frametype = -1;
    01020          break;
    01021    }
    01022
    01023 /*
    01024    if (option_verbose > 3) ast_verbose("%s: LOCKING in handle_owned [%d]\n", p->dev,res);
    01025    res = ast_mutex_lock(&p->lock);
    01026    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01027 */
    01028    {
    01029       if (p->bridge) { /* Check what happened, see if we need to report it. */
    01030          switch (f.frametype) {
    01031             case AST_FRAME_DTMF:
    01032                if (  !(p->bridge->c0 == p->owner &&
    01033                      (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_0) ) &&
    01034                   !(p->bridge->c1 == p->owner &&
    01035                      (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_1) ))
    01036                   /* Kill bridge, this is interesting. */
    01037                   endbridge = 1;
    01038                break;
    01039
    01040             case AST_FRAME_CONTROL:
    01041                if (!(p->bridge->flags & AST_BRIDGE_IGNORE_SIGS))
    01042                #if 0
    01043                if (f.subclass == AST_CONTROL_BUSY ||
    01044                f.subclass == AST_CONTROL_CONGESTION ||
    01045                f.subclass == AST_CONTROL_HANGUP ||
    01046                f.subclass == AST_CONTROL_FLASH)
    01047                #endif
    01048                   endbridge = 1;
    01049                break;
    01050
    01051             default:
    01052                break;
    01053          }
    01054          if (endbridge) {
    01055             if (p->bridge->fo)
    01056                *p->bridge->fo = ast_frisolate(&f);
    01057             if (p->bridge->rc)
    01058                *p->bridge->rc = p->owner;
    01059
    01060             ast_mutex_lock(&p->bridge->lock); {
    01061                p->bridge->endbridge = 1;
    01062                ast_cond_signal(&p->bridge->cond);
    01063             } ast_mutex_unlock(&p->bridge->lock);
    01064          }
    01065       }
    01066    }
    01067
    01068    if (endbridge){
    01069       res = ast_mutex_unlock(&p->lock);
    01070 /*
    01071       if (option_verbose > 3) ast_verbose("%s: unLOCKING in handle_owned [%d]\n", p->dev,res);
    01072 */
    01073       return 0;
    01074    }
    01075
    01076    if (option_verbose > 3)
    01077       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: Prepared frame type[%d]subclass[%d], bridge=%p owner=[%s]\n",
    01078          p->dev, f.frametype, f.subclass, (void *)p->bridge, p->owner->name);
    01079
    01080    /* Trylock used here to avoid deadlock that can occur if we
    01081     * happen to be in here handling an event when hangup is called
    01082     * Problem is that hangup holds p->owner->lock
    01083     */
    01084    if ((f.frametype >= 0)&& (f.frametype != AST_FRAME_NULL)&&(p->owner)) {
    01085       if (ast_mutex_trylock(&p->owner->lock)==0)  {
    01086          ast_queue_frame(p->owner, &f);
    01087          ast_mutex_unlock(&p->owner->lock);
    01088          if (option_verbose > 3)
    01089             ast_verbose(VERBOSE_PREFIX_4 "%s: handled_owned: Queued Frame to [%s]\n", p->dev,p->owner->name);
    01090       } else {
    01091          ast_verbose("%s: handled_owned: Missed event %d/%d \n",
    01092             p->dev,f.frametype, f.subclass);
    01093       }
    01094    }
    01095    res = ast_mutex_unlock(&p->lock);
    01096 /*
    01097    if (option_verbose > 3) ast_verbose("%s: unLOCKING in handle_owned [%d]\n", p->dev,res);
    01098 */
    01099
    01100    return 0;
    01101 }
    01102
    01103 static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e)
    01104 {
    01105    char s[2] = {0};
    01106    struct ast_channel *owner = p->owner;
    01107    char cid_num[256];
    01108    char cid_name[256];
    01109 /*
    01110    struct ast_channel *c;
    01111 */
    01112
    01113    if (option_verbose > 3) {
    01114       char str[VPB_MAX_STR];
    01115       vpb_translate_event(e, str);
    01116       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, event[%d][%s]=[%d]\n",
    01117          p->dev, p->mode, e->type,str, e->data);
    01118    }
    01119
    01120    switch(e->type) {
    01121       case VPB_LOOP_ONHOOK:
    01122       case VPB_LOOP_POLARITY:
    01123          if (UsePolarityCID == 1){
    01124             if (option_verbose>3)
    01125                ast_verbose(VERBOSE_PREFIX_4 "Polarity reversal\n");
    01126             if(p->callerid_type == 1) {
    01127                if (option_verbose>3)
    01128                   ast_verbose(VERBOSE_PREFIX_4 "Using VPB Caller ID\n");
    01129                get_callerid(p);        /* UK CID before 1st ring*/
    01130             }
    01131 /*          get_callerid_ast(p);    /* Caller ID using the ast functions */
    01132          }
    01133          break;
    01134       case VPB_RING:
    01135          if (p->mode == MODE_FXO) /* FXO port ring, start * */ {
    01136             vpb_new(p, AST_STATE_RING, p->context);
    01137             if (UsePolarityCID != 1){
    01138                if(p->callerid_type == 1) {
    01139                   if (option_verbose>3)
    01140                      ast_verbose(VERBOSE_PREFIX_4 "Using VPB Caller ID\n");
    01141                   get_callerid(p);        /* Australian CID only between 1st and 2nd ring  */
    01142                }
    01143                get_callerid_ast(p);    /* Caller ID using the ast functions */
    01144             }
    01145             else {
    01146                ast_log(LOG_ERROR, "Setting caller ID: %s %s\n",p->cid_num, p->cid_name);
    01147                ast_set_callerid(p->owner, p->cid_num, p->cid_name, p->cid_num);
    01148                p->cid_num[0]=0;
    01149                p->cid_name[0]=0;
    01150             }
    01151
    01152             vpb_timer_stop(p->ring_timer);
    01153             vpb_timer_start(p->ring_timer);
    01154          }
    01155          break;
    01156
    01157       case VPB_RING_OFF:
    01158          break;
    01159
    01160       case VPB_STATION_OFFHOOK:
    01161          if (p->mode == MODE_IMMEDIATE)
    01162             vpb_new(p,AST_STATE_RING, p->context);
    01163          else {
    01164             ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: playing dialtone\n",p->dev);
    01165             playtone(p->handle, &Dialtone);
    01166             p->state=VPB_STATE_PLAYDIAL;
    01167             p->wantdtmf = 1;
    01168             p->ext[0] = 0; /* Just to be sure & paranoid.*/
    01169          }
    01170          break;
    01171
    01172       case VPB_DIALEND:
    01173          if (p->mode == MODE_DIALTONE){
    01174             if (p->state == VPB_STATE_PLAYDIAL) {
    01175                playtone(p->handle, &Dialtone);
    01176                p->wantdtmf = 1;
    01177                p->ext[0] = 0; /* Just to be sure & paranoid. */
    01178             }
    01179             /* These are not needed as they have timers to restart them
    01180             else if (p->state == VPB_STATE_PLAYBUSY) {
    01181                playtone(p->handle, &Busytone);
    01182                p->wantdtmf = 1;
    01183                p->ext[0] = 0;
    01184             }
    01185             else if (p->state == VPB_STATE_PLAYRING) {
    01186                playtone(p->handle, &Ringbacktone);
    01187                p->wantdtmf = 1;
    01188                p->ext[0] = 0;
    01189             }
    01190             */
    01191          } else {
    01192             ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Got a DIALEND when not really expected\n",p->dev);
    01193          }
    01194          break;
    01195
    01196       case VPB_STATION_ONHOOK:   /* clear ext */
    01197          stoptone(p->handle);
    01198          p->wantdtmf = 1 ;
    01199          p->ext[0] = 0;
    01200          p->state=VPB_STATE_ONHOOK;
    01201          break;
    01202       case VPB_TIMEREXP:
    01203          if (e->data == p->dtmfidd_timer_id) {
    01204             if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)){
    01205                if (option_verbose > 3)
    01206                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: DTMF IDD timer out, matching on [%s] in [%s]\n", p->dev,p->ext , p->context);
    01207
    01208                vpb_new(p,AST_STATE_RING, p->context);
    01209             }
    01210          } else if (e->data == p->ring_timer_id) {
    01211             /* We didnt get another ring in time! */
    01212             if (p->owner){
    01213                if (p->owner->_state != AST_STATE_UP)  {
    01214                    /* Assume caller has hung up */
    01215                   vpb_timer_stop(p->ring_timer);
    01216                }
    01217             } else {
    01218                 /* No owner any more, Assume caller has hung up */
    01219                vpb_timer_stop(p->ring_timer);
    01220             }
    01221          }
    01222          break;
    01223
    01224       case VPB_DTMF:
    01225          if (p->state == VPB_STATE_ONHOOK){
    01226             /* DTMF's being passed while on-hook maybe Caller ID */
    01227             if ( p->mode == MODE_FXO ) {
    01228                if ( e->data == DTMF_CID_START ) { /* CallerID Start signal */
    01229                   p->dtmf_caller_pos = 0; /* Leaves the first digit out */
    01230                   memset(p->callerid,0,AST_MAX_EXTENSION);
    01231                }
    01232                else if ( e->data == DTMF_CID_STOP ) { /* CallerID End signal */
    01233                   p->callerid[p->dtmf_caller_pos] = '\0';
    01234                   if (option_verbose > 2)
    01235                      ast_verbose(VERBOSE_PREFIX_3 " %s: DTMF CallerID %s\n",p->dev,p->callerid);
    01236                   if (owner){
    01237                      /*
    01238                      if (owner->cid.cid_num)
    01239                         free(owner->cid.cid_num);
    01240                      owner->cid.cid_num=NULL;
    01241                      if (owner->cid.cid_name)
    01242                         free(owner->cid.cid_name);
    01243                      owner->cid.cid_name=NULL;
    01244                      owner->cid.cid_num = strdup(p->callerid);
    01245                      */
    01246                      cid_name[0] = '\0';
    01247                      cid_num[0] = '\0';
    01248                      ast_callerid_split(p->callerid, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
    01249                      ast_set_callerid(owner, cid_num, cid_name, cid_num);
    01250
    01251                   }
    01252                   else {
    01253                      if (option_verbose > 2)
    01254                         ast_verbose(VERBOSE_PREFIX_3 " %s: DTMF CallerID: no owner to assign CID \n",p->dev);
    01255                   }
    01256                } else if ( p->dtmf_caller_pos < AST_MAX_EXTENSION ) {
    01257                   if ( p->dtmf_caller_pos >= 0 )
    01258                      p->callerid[p->dtmf_caller_pos] = e->data;
    01259                   p->dtmf_caller_pos++;
    01260                }
    01261             }
    01262             break;
    01263          }
    01264          if (p->wantdtmf == 1) {
    01265             stoptone(p->handle);
    01266             p->wantdtmf = 0;
    01267          }
    01268          p->state=VPB_STATE_GETDTMF;
    01269          s[0] = e->data;
    01270          strncat(p->ext, s, sizeof(p->ext) - strlen(p->ext) - 1);
    01271          #if 0
    01272          if (!strcmp(p->ext,ast_pickup_ext())) {
    01273             /* Call pickup has been dialled! */
    01274             if (ast_pickup_call(c)) {
    01275                /* Call pickup wasnt possible */
    01276             }
    01277          }
    01278          else
    01279          #endif
    01280          if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)){
    01281             if ( ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)){
    01282                if (option_verbose > 3)
    01283                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Multiple matches on [%s] in [%s]\n", p->dev,p->ext , p->context);
    01284                /* Start DTMF IDD timer */
    01285                vpb_timer_stop(p->dtmfidd_timer);
    01286                vpb_timer_start(p->dtmfidd_timer);
    01287             }
    01288             else {
    01289                if (option_verbose > 3)
    01290                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Matched on [%s] in [%s]\n", p->dev,p->ext , p->context);
    01291                vpb_new(p,AST_STATE_UP, p->context);
    01292             }
    01293          } else if (!ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)){
    01294             if (ast_exists_extension(NULL, "default", p->ext, 1, p->callerid)) {
    01295                vpb_new(p,AST_STATE_UP, "default");
    01296             } else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) {
    01297                if (option_verbose > 3) {
    01298                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: can't match anything in %s or default\n", p->dev, p->context);
    01299                }
    01300                playtone(p->handle, &Busytone);
    01301                vpb_timer_stop(p->busy_timer);
    01302                vpb_timer_start(p->busy_timer);
    01303                p->state = VPB_STATE_PLAYBUSY;
    01304             }
    01305          }
    01306          break;
    01307
    01308       default:
    01309          /* Ignore.*/
    01310          break;
    01311    }
    01312
    01313    if (option_verbose > 3)
    01314       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, [%d=>%d]\n",
    01315          p->dev, p->mode, e->type, e->data);
    01316
    01317    return 0;
    01318 }
    01319
    01320 static void *do_monitor(void *unused)
    01321 {
    01322
    01323    /* Monitor thread, doesn't die until explicitly killed. */
    01324
    01325    if (option_verbose > 1)
    01326       ast_verbose(VERBOSE_PREFIX_2 "Starting vpb monitor thread[%ld]\n",
    01327    pthread_self());
    01328
    01329    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    01330
    01331    for(;;) {
    01332       VPB_EVENT e;
    01333       VPB_EVENT je;
    01334       char str[VPB_MAX_STR];
    01335       struct vpb_pvt *p;
    01336
    01337       /*
    01338       if (option_verbose > 3)
    01339            ast_verbose(VERBOSE_PREFIX_4 "Monitor waiting for event\n");
    01340       */
    01341
    01342       int res = vpb_get_event_sync(&e, VPB_WAIT_TIMEOUT);
    01343       if( (res==VPB_NO_EVENTS) || (res==VPB_TIME_OUT) ){
    01344          /*
    01345          if (option_verbose > 3){
    01346             if (res ==  VPB_NO_EVENTS){
    01347                ast_verbose(VERBOSE_PREFIX_4 "No events....\n");
    01348             } else {
    01349                ast_verbose(VERBOSE_PREFIX_4 "No events, timed out....\n");
    01350             }
    01351          }
    01352          */
    01353          continue;
    01354       }
    01355
    01356       if (res != VPB_OK) {
    01357          ast_log(LOG_ERROR,"Monitor get event error %s\n", vpb_strerror(res) );
    01358          ast_verbose("Monitor get event error %s\n", vpb_strerror(res) );
    01359          continue;
    01360       }
    01361
    01362       str[0] = 0;
    01363
    01364       p = NULL;
    01365
    01366       ast_mutex_lock(&monlock); {
    01367
    01368          if (e.type == VPB_NULL_EVENT) {
    01369             if (option_verbose > 3)
    01370                ast_verbose(VERBOSE_PREFIX_4 "Monitor got null event\n");
    01371          }
    01372          else {
    01373             vpb_translate_event(&e, str);
    01374             if (strlen(str)>1){
    01375                str[(strlen(str)-1)]='\0';
    01376             }
    01377
    01378             ast_mutex_lock(&iflock); {
    01379                p = iflist;
    01380                while (p && p->handle != e.handle)
    01381                   p = p->next;
    01382             } ast_mutex_unlock(&iflock);
    01383
    01384             if (p && (option_verbose > 3))
    01385                ast_verbose(VERBOSE_PREFIX_4 "%s: Event [%d=>%s] \n",
    01386                   p ? p->dev : "null", e.type, str );
    01387          }
    01388
    01389       } ast_mutex_unlock(&monlock);
    01390
    01391       if (!p) {
    01392          if (e.type != VPB_NULL_EVENT){
    01393             ast_log(LOG_WARNING, "Got event [%s][%d], no matching iface!\n", str,e.type);
    01394             if (option_verbose > 3){
    01395                ast_verbose(VERBOSE_PREFIX_4 "vpb/ERR: No interface for Event [%d=>%s] \n",e.type,str );
    01396             }
    01397          }
    01398          continue;
    01399       }
    01400
    01401       /* flush the event from the channel event Q */
    01402       vpb_get_event_ch_async(e.handle,&je);
    01403       if (option_verbose > 4){
    01404          vpb_translate_event(&je, str);
    01405          ast_verbose("%s: Flushing event [%d]=>%s\n",p->dev,je.type,str);
    01406       }
    01407
    01408       /* Check for ownership and locks */
    01409       if ((p->owner)&&(!p->golock)){
    01410          /* Need to get owner lock */
    01411          /* Safely grab both p->lock and p->owner->lock so that there
    01412          cannot be a race with something from the other side */
    01413          /*
    01414          ast_mutex_lock(&p->lock);
    01415          while(ast_mutex_trylock(&p->owner->lock)) {
    01416             ast_mutex_unlock(&p->lock);
    01417             usleep(1);
    01418             ast_mutex_lock(&p->lock);
    01419             if (!p->owner)
    01420                break;
    01421          }
    01422          if (p->owner)
    01423             p->golock=1;
    01424          */
    01425       }
    01426       /* Two scenarios: Are you owned or not. */
    01427       if (p->owner) {
    01428          monitor_handle_owned(p, &e);
    01429       } else {
    01430          monitor_handle_notowned(p, &e);
    01431       }
    01432       /* if ((!p->owner)&&(p->golock)){
    01433          ast_mutex_unlock(&p->owner->lock);
    01434          ast_mutex_unlock(&p->lock);
    01435       }
    01436       */
    01437
    01438    }
    01439
    01440    return NULL;
    01441 }
    01442
    01443 static int restart_monitor(void)
    01444 {
    01445    int error = 0;
    01446
    01447    /* If we're supposed to be stopped -- stay stopped */
    01448    if (mthreadactive == -2)
    01449       return 0;
    01450
    01451    if (option_verbose > 3)
    01452       ast_verbose(VERBOSE_PREFIX_4 "Restarting monitor\n");
    01453
    01454    ast_mutex_lock(&monlock); {
    01455       if (monitor_thread == pthread_self()) {
    01456          ast_log(LOG_WARNING, "Cannot kill myself\n");
    01457          error = -1;
    01458          if (option_verbose > 3)
    01459             ast_verbose(VERBOSE_PREFIX_4 "Monitor trying to kill monitor\n");
    01460       }
    01461       else {
    01462          if (mthreadactive != -1) {
    01463             /* Why do other drivers kill the thread? No need says I, simply awake thread with event. */
    01464             VPB_EVENT e;
    01465             e.handle = 0;
    01466             e.type = VPB_NULL_EVENT;
    01467             e.data = 0;
    01468
    01469             if (option_verbose > 3)
    01470                ast_verbose(VERBOSE_PREFIX_4 "Trying to reawake monitor\n");
    01471
    01472             vpb_put_event(&e);
    01473          } else {
    01474             /* Start a new monitor */
    01475             int pid = ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL);
    01476             if (option_verbose > 3)
    01477                ast_verbose(VERBOSE_PREFIX_4 "Created new monitor thread %d\n",pid);
    01478             if (pid < 0) {
    01479                ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
    01480                error = -1;
    01481             } else
    01482                mthreadactive = 0; /* Started the thread!*/
    01483          }
    01484       }
    01485    } ast_mutex_unlock(&monlock);
    01486
    01487    if (option_verbose > 3)
    01488       ast_verbose(VERBOSE_PREFIX_4 "Monitor restarted\n");
    01489
    01490    return error;
    01491 }
    01492
    01493 /* Per board config that must be called after vpb_open() */
    01494 static void mkbrd(vpb_model_t model, int echo_cancel)
    01495 {
    01496    if(!bridges) {
    01497       if(model==vpb_model_v4pci)
    01498          max_bridges = MAX_BRIDGES_V4PCI;
    01499       bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) );
    01500       if(!bridges)
    01501          ast_log(LOG_ERROR, "Failed to initialize bridges\n");
    01502       else {
    01503          memset(bridges,0,max_bridges * sizeof(vpb_bridge_t));
    01504          for(int i = 0; i < max_bridges; i++ ) {
    01505             ast_mutex_init(&bridges[i].lock);
    01506             ast_cond_init(&bridges[i].cond, NULL);
    01507          }
    01508       }
    01509    }
    01510    if(!echo_cancel) {
    01511       if (model==vpb_model_v4pci) {
    01512          vpb_echo_canc_disable();
    01513          ast_log(LOG_NOTICE, "Voicetronix echo cancellation OFF\n");
    01514       }
    01515       else {
    01516       /* need to it port by port for OpenSwitch*/
    01517       }
    01518    } else {
    01519       if (model==vpb_model_v4pci) {
    01520          vpb_echo_canc_enable();
    01521          ast_log(LOG_NOTICE, "Voicetronix echo cancellation ON\n");
    01522          if (ec_supp_threshold > -1){
    01523             #ifdef VPB_PRI
    01524             vpb_echo_canc_set_sup_thresh(0,(short *)&ec_supp_threshold);
    01525             #else
    01526             vpb_echo_canc_set_sup_thresh((short *)&ec_supp_threshold);
    01527             #endif
    01528             ast_log(LOG_NOTICE, "Voicetronix EC Sup Thres set\n");
    01529          }
    01530       }
    01531       else {
    01532       /* need to it port by port for OpenSwitch*/
    01533       }
    01534    }
    01535 }
    01536
    01537 static struct vpb_pvt *mkif(int board, int channel, int mode, int gains, float txgain, float rxgain,
    01538           float txswgain, float rxswgain, int bal1, int bal2, int bal3,
    01539           char * callerid, int echo_cancel, int group, ast_group_t callgroup, ast_group_t pickupgroup )
    01540 {
    01541    struct vpb_pvt *tmp;
    01542    char buf[64];
    01543
    01544    tmp = (struct vpb_pvt *)calloc(1, sizeof *tmp);
    01545
    01546    if (!tmp)
    01547       return NULL;
    01548
    01549    tmp->handle = vpb_open(board, channel);
    01550
    01551    if (tmp->handle < 0) {
    01552       ast_log(LOG_WARNING, "Unable to create channel vpb/%d-%d: %s\n",
    01553                board, channel, strerror(errno));
    01554       free(tmp);
    01555       return NULL;
    01556    }
    01557
    01558    snprintf(tmp->dev, sizeof(tmp->dev), "vpb/%d-%d", board, channel);
    01559
    01560    tmp->mode = mode;
    01561
    01562    tmp->group = group;
    01563    tmp->callgroup = callgroup;
    01564    tmp->pickupgroup = pickupgroup;
    01565
    01566    /* Initilize dtmf caller ID position variable */
    01567    tmp->dtmf_caller_pos=0;
    01568
    01569    strncpy(tmp->language, language, sizeof(tmp->language) - 1);
    01570    strncpy(tmp->context, context, sizeof(tmp->context) - 1);
    01571
    01572    tmp->callerid_type=0;
    01573    if(callerid) {
    01574       if (strcasecmp(callerid,"on")==0){
    01575          tmp->callerid_type =1;
    01576          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
    01577       }
    01578       else if (strcasecmp(callerid,"v23")==0){
    01579          tmp->callerid_type =2;
    01580          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
    01581       }
    01582       else if (strcasecmp(callerid,"bell")==0){
    01583          tmp->callerid_type =3;
    01584          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
    01585       }
    01586       else {
    01587          strncpy(tmp->callerid, callerid, sizeof(tmp->callerid) - 1);
    01588       }
    01589    } else {
    01590       strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
    01591    }
    01592
    01593    /* check if codec balances have been set in the config file */
    01594    if (bal3>=0) {
    01595       if ((bal1>=0) && !(bal1 & 32)) bal1 |= 32;
    01596          vpb_set_codec_reg(tmp->handle, 0x42, bal3);
    01597    }
    01598    if(bal1>=0) vpb_set_codec_reg(tmp->handle, 0x32, bal1);
    01599    if(bal2>=0) vpb_set_codec_reg(tmp->handle, 0x3a, bal2);
    01600
    01601    if (gains & VPB_GOT_TXHWG){
    01602       if (txgain > MAX_VPB_GAIN){
    01603          tmp->txgain = MAX_VPB_GAIN;
    01604       }
    01605       else if (txgain < MIN_VPB_GAIN){
    01606          tmp->txgain = MIN_VPB_GAIN;
    01607       }
    01608       else {
    01609          tmp->txgain = txgain;
    01610       }
    01611
    01612       ast_log(LOG_NOTICE,"VPB setting Tx Hw gain to [%f]\n",tmp->txgain);
    01613       vpb_play_set_hw_gain(tmp->handle, tmp->txgain);
    01614    }
    01615
    01616    if (gains & VPB_GOT_RXHWG){
    01617       if (rxgain > MAX_VPB_GAIN){
    01618          tmp->rxgain = MAX_VPB_GAIN;
    01619       }
    01620       else if (rxgain < MIN_VPB_GAIN){
    01621          tmp->rxgain = MIN_VPB_GAIN;
    01622       }
    01623       else {
    01624          tmp->rxgain = rxgain;
    01625       }
    01626       ast_log(LOG_NOTICE,"VPB setting Rx Hw gain to [%f]\n",tmp->rxgain);
    01627       vpb_record_set_hw_gain(tmp->handle,tmp->rxgain);
    01628    }
    01629
    01630    if (gains & VPB_GOT_TXSWG){
    01631       tmp->txswgain = txswgain;
    01632       ast_log(LOG_NOTICE,"VPB setting Tx Sw gain to [%f]\n",tmp->txswgain);
    01633       vpb_play_set_gain(tmp->handle, tmp->txswgain);
    01634    }
    01635
    01636    if (gains & VPB_GOT_RXSWG){
    01637       tmp->rxswgain = rxswgain;
    01638       ast_log(LOG_NOTICE,"VPB setting Rx Sw gain to [%f]\n",tmp->rxswgain);
    01639       vpb_record_set_gain(tmp->handle, tmp->rxswgain);
    01640    }
    01641
    01642    tmp->vpb_model = vpb_model_unknown;
    01643    if( vpb_get_model(buf) == VPB_OK ) {
    01644       if(strcmp(buf,"V12PCI")==0)
    01645          tmp->vpb_model = vpb_model_v12pci;
    01646       else if(strcmp(buf,"VPB4")==0)
    01647          tmp->vpb_model = vpb_model_v4pci;
    01648    }
    01649
    01650    ast_mutex_init(&tmp->owner_lock);
    01651    ast_mutex_init(&tmp->lock);
    01652    ast_mutex_init(&tmp->record_lock);
    01653    ast_mutex_init(&tmp->play_lock);
    01654    ast_mutex_init(&tmp->play_dtmf_lock);
    01655
    01656    /* set default read state */
    01657    tmp->read_state = 0;
    01658
    01659    tmp->golock=0;
    01660
    01661    tmp->busy_timer_id = vpb_timer_get_unique_timer_id();
    01662    vpb_timer_open(&tmp->busy_timer, tmp->handle, tmp->busy_timer_id, TIMER_PERIOD_BUSY);
    01663
    01664    tmp->ringback_timer_id = vpb_timer_get_unique_timer_id();
    01665    vpb_timer_open(&tmp->ringback_timer, tmp->handle, tmp->ringback_timer_id, TIMER_PERIOD_RINGBACK);
    01666
    01667    tmp->ring_timer_id = vpb_timer_get_unique_timer_id();
    01668    vpb_timer_open(&tmp->ring_timer, tmp->handle, tmp->ring_timer_id, timer_period_ring);
    01669
    01670    tmp->dtmfidd_timer_id = vpb_timer_get_unique_timer_id();
    01671    vpb_timer_open(&tmp->dtmfidd_timer, tmp->handle, tmp->dtmfidd_timer_id, dtmf_idd);
    01672
    01673    if (mode == MODE_FXO){
    01674       if (use_ast_dtmfdet)
    01675          vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF );
    01676       else
    01677          vpb_set_event_mask(tmp->handle, VPB_EVENTS_ALL );
    01678    }
    01679    else {
    01680 /*
    01681       if (use_ast_dtmfdet)
    01682          vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF );
    01683       else
    01684 */
    01685          vpb_set_event_mask(tmp->handle, VPB_EVENTS_STAT );
    01686    }
    01687
    01688    if ((tmp->vpb_model == vpb_model_v12pci) && (echo_cancel)){
    01689       vpb_hostecho_on(tmp->handle);
    01690    }
    01691    if (use_ast_dtmfdet) {
    01692       tmp->vad = ast_dsp_new();
    01693       ast_dsp_set_features(tmp->vad, DSP_FEATURE_DTMF_DETECT);
    01694       ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF);
    01695       if (relaxdtmf)
    01696          ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF|DSP_DIGITMODE_RELAXDTMF);
    01697    }
    01698    else {
    01699       tmp->vad = NULL;
    01700    }
    01701
    01702    /* define grunt tone */
    01703    vpb_settonedet(tmp->handle,&toned_ungrunt);
    01704
    01705    ast_log(LOG_NOTICE,"Voicetronix %s channel %s initialized (rxsg=%f/txsg=%f/rxhg=%f/txhg=%f)(0x%x/0x%x/0x%x)\n",
    01706       (tmp->vpb_model==vpb_model_v4pci)?"V4PCI": (tmp->vpb_model==vpb_model_v12pci)?"V12PCI":"[Unknown model]",
    01707       tmp->dev, tmp->rxswgain, tmp->txswgain, tmp->rxgain, tmp->txgain, bal1, bal2, bal3 );
    01708
    01709    return tmp;
    01710 }
    01711
    01712 static int vpb_indicate(struct ast_channel *ast, int condition)
    01713 {
    01714    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    01715    int res = 0;
    01716    int tmp = 0;
    01717
    01718    if (use_ast_ind == 1) {
    01719       if (option_verbose > 3)
    01720          ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate called when using Ast Indications !?!\n", p->dev);
    01721       return 0;
    01722    }
    01723
    01724    if (option_verbose > 3)
    01725       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate [%d] state[%d]\n", p->dev, condition,ast->_state);
    01726 /*
    01727    if (ast->_state != AST_STATE_UP) {
    01728       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate Not in AST_STATE_UP\n", p->dev, condition,ast->_state);
    01729       return res;
    01730    }
    01731 */
    01732
    01733 /*
    01734    if (option_verbose > 3) ast_verbose("%s: LOCKING in indicate \n", p->dev);
    01735    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01736 */
    01737    ast_mutex_lock(&p->lock);
    01738    switch(condition) {
    01739       case AST_CONTROL_BUSY:
    01740       case AST_CONTROL_CONGESTION:
    01741          if (ast->_state == AST_STATE_UP) {
    01742             playtone(p->handle, &Busytone);
    01743             p->state = VPB_STATE_PLAYBUSY;
    01744             vpb_timer_stop(p->busy_timer);
    01745             vpb_timer_start(p->busy_timer);
    01746          }
    01747          break;
    01748       case AST_CONTROL_RINGING:
    01749          if (ast->_state == AST_STATE_UP) {
    01750             playtone(p->handle, &Ringbacktone);
    01751             p->state = VPB_STATE_PLAYRING;
    01752             if (option_verbose > 3)
    01753                ast_verbose(VERBOSE_PREFIX_4 "%s: vpb indicate: setting ringback timer [%d]\n", p->dev,p->ringback_timer_id);
    01754
    01755             vpb_timer_stop(p->ringback_timer);
    01756             vpb_timer_start(p->ringback_timer);
    01757          }
    01758          break;
    01759       case AST_CONTROL_ANSWER:
    01760       case -1: /* -1 means stop playing? */
    01761          vpb_timer_stop(p->ringback_timer);
    01762          vpb_timer_stop(p->busy_timer);
    01763          stoptone(p->handle);
    01764          break;
    01765       case AST_CONTROL_HANGUP:
    01766          if (ast->_state == AST_STATE_UP) {
    01767             playtone(p->handle, &Busytone);
    01768             p->state = VPB_STATE_PLAYBUSY;
    01769             vpb_timer_stop(p->busy_timer);
    01770             vpb_timer_start(p->busy_timer);
    01771          }
    01772          break;
    01773
    01774       default:
    01775          res = 0;
    01776          break;
    01777    }
    01778    tmp = ast_mutex_unlock(&p->lock);
    01779 /*
    01780    if (option_verbose > 3) ast_verbose("%s: unLOCKING in indicate [%d]\n", p->dev,tmp);
    01781 */
    01782    return res;
    01783 }
    01784
    01785 static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
    01786 {
    01787    struct vpb_pvt *p = (struct vpb_pvt *)newchan->tech_pvt;
    01788    int res = 0;
    01789
    01790 /*
    01791    if (option_verbose > 3) ast_verbose("%s: LOCKING in fixup \n", p->dev);
    01792    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01793 */
    01794    ast_mutex_lock(&p->lock);
    01795    ast_log(LOG_DEBUG, "New owner for channel %s is %s\n", p->dev, newchan->name);
    01796
    01797    if (p->owner == oldchan) {
    01798       p->owner = newchan;
    01799    }
    01800
    01801    if (newchan->_state == AST_STATE_RINGING){
    01802       if (use_ast_ind == 1) {
    01803          if (option_verbose > 3)
    01804             ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_fixup Calling ast_indicate\n", p->dev);
    01805          ast_indicate(newchan, AST_CONTROL_RINGING);
    01806       }
    01807       else {
    01808          if (option_verbose > 3)
    01809             ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_fixup Calling vpb_indicate\n", p->dev);
    01810          vpb_indicate(newchan, AST_CONTROL_RINGING);
    01811       }
    01812    }
    01813
    01814    res= ast_mutex_unlock(&p->lock);
    01815 /*
    01816    if (option_verbose > 3) ast_verbose("%s: unLOCKING in fixup [%d]\n", p->dev,res);
    01817 */
    01818    return 0;
    01819 }
    01820
    01821 static int vpb_digit(struct ast_channel *ast, char digit)
    01822 {
    01823    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    01824    char s[2];
    01825    int res = 0;
    01826
    01827    if (use_ast_dtmf){
    01828       if (option_verbose > 3)
    01829          ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_digit: asked to play digit[%c] but we are using asterisk dtmf play back?!\n", p->dev, digit);
    01830       return 0;
    01831    }
    01832
    01833 /*
    01834    if (option_verbose > 3) ast_verbose("%s: LOCKING in digit \n", p->dev);
    01835    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01836 */
    01837    ast_mutex_lock(&p->lock);
    01838
    01839
    01840    s[0] = digit;
    01841    s[1] = '\0';
    01842
    01843    if (option_verbose > 3)
    01844       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_digit: asked to play digit[%s]\n", p->dev, s);
    01845
    01846    ast_mutex_lock(&p->play_dtmf_lock);
    01847    strncat(p->play_dtmf,s,sizeof(*p->play_dtmf));
    01848    ast_mutex_unlock(&p->play_dtmf_lock);
    01849
    01850    res = ast_mutex_unlock(&p->lock);
    01851 /*
    01852    if (option_verbose > 3) ast_verbose("%s: unLOCKING in digit [%d]\n", p->dev,res);
    01853 */
    01854    return 0;
    01855 }
    01856
    01857 /* Places a call out of a VPB channel */
    01858 static int vpb_call(struct ast_channel *ast, char *dest, int timeout)
    01859 {
    01860    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    01861    int res = 0,i;
    01862    char *s = strrchr(dest, '/');
    01863    char dialstring[254] = "";
    01864    int tmp = 0;
    01865
    01866 /*
    01867    if (option_verbose > 3) ast_verbose("%s: LOCKING in call \n", p->dev);
    01868    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01869 */
    01870    ast_mutex_lock(&p->lock);
    01871    if (option_verbose > 3)
    01872       ast_verbose(VERBOSE_PREFIX_4 "%s: starting call to [%s]\n", p->dev,dest);
    01873
    01874    if (s)
    01875       s = s + 1;
    01876    else
    01877       s = dest;
    01878    strncpy(dialstring, s, sizeof(dialstring) - 1);
    01879    for (i=0; dialstring[i] != '\0' ; i++) {
    01880       if ((dialstring[i] == 'w') || (dialstring[i] == 'W'))
    01881          dialstring[i] = ',';
    01882       else if ((dialstring[i] == 'f') || (dialstring[i] == 'F'))
    01883          dialstring[i] = '&';
    01884    }
    01885
    01886    if (ast->_state != AST_STATE_DOWN && ast->_state != AST_STATE_RESERVED) {
    01887       ast_log(LOG_WARNING, "vpb_call on %s neither down nor reserved!\n", ast->name);
    01888       tmp = ast_mutex_unlock(&p->lock);
    01889 /*
    01890       if (option_verbose > 3) ast_verbose("%s: unLOCKING in call [%d]\n", p->dev,tmp);
    01891 */
    01892       return -1;
    01893    }
    01894    if (p->mode != MODE_FXO)  /* Station port, ring it. */
    01895       res = vpb_ring_station_async(p->handle, VPB_RING_STATION_ON,0);
    01896    else {
    01897       VPB_CALL call;
    01898
    01899       /* Dial must timeout or it can leave channels unuseable */
    01900       if( timeout == 0 )
    01901          timeout = TIMER_PERIOD_NOANSWER;
    01902       else
    01903          timeout = timeout * 1000; /* convert from secs to ms. */
    01904
    01905       /* These timeouts are only used with call progress dialing */
    01906       call.dialtones = 1; /* Number of dialtones to get outside line */
    01907       call.dialtone_timeout = VPB_DIALTONE_WAIT; /* Wait this long for dialtone (ms) */
    01908       call.ringback_timeout = VPB_RINGWAIT; /* Wait this long for ringing after dialing (ms) */
    01909       call.inter_ringback_timeout = VPB_CONNECTED_WAIT; /* If ringing stops for this long consider it connected (ms) */
    01910       call.answer_timeout = timeout; /* Time to wait for answer after ringing starts (ms) */
    01911       memcpy( &call.tone_map,  DialToneMap, sizeof(DialToneMap) );
    01912       vpb_set_call(p->handle, &call);
    01913
    01914       if (option_verbose > 1)
    01915          ast_verbose(VERBOSE_PREFIX_2 "%s: Calling %s on %s \n",p->dev, dialstring, ast->name);
    01916
    01917       if (option_verbose > 2) {
    01918          int j;
    01919          ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s %d/%dms/%dms/%dms/%dms\n", p->dev
    01920             , ast->name, call.dialtones, call.dialtone_timeout
    01921             , call.ringback_timeout, call.inter_ringback_timeout
    01922             , call.answer_timeout );
    01923          for( j=0; !call.tone_map[j].terminate; j++ )
    01924             ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s tone %d->%d\n", p->dev,
    01925                ast->name, call.tone_map[j].tone_id, call.tone_map[j].call_id);
    01926       }
    01927
    01928       if (option_verbose > 3)
    01929             ast_verbose("%s: Disabling Loop Drop detection\n",p->dev);
    01930       vpb_disable_event(p->handle, VPB_MDROP);
    01931       vpb_sethook_sync(p->handle,VPB_OFFHOOK);
    01932       p->state=VPB_STATE_OFFHOOK;
    01933
    01934       #ifndef DIAL_WITH_CALL_PROGRESS
    01935       vpb_sleep(300);
    01936       if (option_verbose > 3)
    01937             ast_verbose("%s: Enabling Loop Drop detection\n",p->dev);
    01938       vpb_enable_event(p->handle, VPB_MDROP);
    01939       res = vpb_dial_async(p->handle, dialstring);
    01940       #else
    01941       if (option_verbose > 3)
    01942             ast_verbose("%s: Enabling Loop Drop detection\n",p->dev);
    01943       vpb_enable_event(p->handle, VPB_MDROP);
    01944       res = vpb_call_async(p->handle, dialstring);
    01945       #endif
    01946
    01947       if (res != VPB_OK) {
    01948          ast_log(LOG_DEBUG, "Call on %s to %s failed: %s\n", ast->name, s, vpb_strerror(res));
    01949          res = -1;
    01950       } else
    01951          res = 0;
    01952    }
    01953
    01954    if (option_verbose > 2)
    01955       ast_verbose(VERBOSE_PREFIX_3 "%s: VPB Calling %s [t=%d] on %s returned %d\n",p->dev , s, timeout, ast->name, res);
    01956    if (res == 0) {
    01957       ast_setstate(ast, AST_STATE_RINGING);
    01958       ast_queue_control(ast,AST_CONTROL_RINGING);
    01959    }
    01960
    01961    if (!p->readthread){
    01962       ast_pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
    01963    }
    01964
    01965    tmp = ast_mutex_unlock(&p->lock);
    01966 /*
    01967    if (option_verbose > 3) ast_verbose("%s: unLOCKING in call [%d]\n", p->dev,tmp);
    01968 */
    01969    return res;
    01970 }
    01971
    01972 static int vpb_hangup(struct ast_channel *ast)
    01973 {
    01974    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    01975    VPB_EVENT je;
    01976    char str[VPB_MAX_STR];
    01977    int res =0 ;
    01978
    01979 /*
    01980    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup \n", p->dev);
    01981    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    01982    if (option_verbose > 3) ast_verbose("%s: LOCKING pthread_self(%d)\n", p->dev,pthread_self());
    01983    ast_mutex_lock(&p->lock);
    01984 */
    01985    if (option_verbose > 1)
    01986       ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup requested\n", ast->name);
    01987
    01988    if (!ast->tech || !ast->tech_pvt) {
    01989       ast_log(LOG_WARNING, "%s: channel not connected?\n", ast->name);
    01990       res = ast_mutex_unlock(&p->lock);
    01991 /*
    01992       if (option_verbose > 3) ast_verbose("%s: unLOCKING in hangup [%d]\n", p->dev,res);
    01993 */
    01994       /* Free up ast dsp if we have one */
    01995       if ((use_ast_dtmfdet)&&(p->vad)) {
    01996          ast_dsp_free(p->vad);
    01997          p->vad = NULL;
    01998       }
    01999       return 0;
    02000    }
    02001
    02002
    02003
    02004    /* Stop record */
    02005    p->stopreads = 1;
    02006    if( p->readthread ){
    02007       pthread_join(p->readthread, NULL);
    02008       if(option_verbose>3)
    02009          ast_verbose( VERBOSE_PREFIX_4 "%s: stopped record thread \n",ast->name);
    02010    }
    02011
    02012    /* Stop play */
    02013    if (p->lastoutput != -1) {
    02014       if(option_verbose>1)
    02015          ast_verbose( VERBOSE_PREFIX_2 "%s: Ending play mode \n",ast->name);
    02016       vpb_play_terminate(p->handle);
    02017       ast_mutex_lock(&p->play_lock); {
    02018          vpb_play_buf_finish(p->handle);
    02019       } ast_mutex_unlock(&p->play_lock);
    02020    }
    02021
    02022    if(option_verbose>3)
    02023       ast_verbose( VERBOSE_PREFIX_4 "%s: Setting state down\n",ast->name);
    02024    ast_setstate(ast,AST_STATE_DOWN);
    02025
    02026
    02027 /*
    02028    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup \n", p->dev);
    02029    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    02030    if (option_verbose > 3) ast_verbose("%s: LOCKING pthread_self(%d)\n", p->dev,pthread_self());
    02031 */
    02032    ast_mutex_lock(&p->lock);
    02033
    02034    if (p->mode != MODE_FXO) {
    02035       /* station port. */
    02036       vpb_ring_station_async(p->handle, VPB_RING_STATION_OFF,0);
    02037       if(p->state!=VPB_STATE_ONHOOK){
    02038          /* This is causing a "dial end" "play tone" loop
    02039          playtone(p->handle, &Busytone);
    02040          p->state = VPB_STATE_PLAYBUSY;
    02041          if(option_verbose>4)
    02042             ast_verbose( VERBOSE_PREFIX_4 "%s: Station offhook[%d], playing busy tone\n",
    02043                         ast->name,p->state);
    02044          */
    02045       }
    02046       else {
    02047          stoptone(p->handle);
    02048       }
    02049       #ifdef VPB_PRI
    02050       vpb_setloop_async(p->handle, VPB_OFFHOOK);
    02051       vpb_sleep(100);
    02052       vpb_setloop_async(p->handle, VPB_ONHOOK);
    02053       #endif
    02054    } else {
    02055       stoptone(p->handle); /* Terminates any dialing */
    02056       vpb_sethook_sync(p->handle, VPB_ONHOOK);
    02057       p->state=VPB_STATE_ONHOOK;
    02058    }
    02059    while (VPB_OK==vpb_get_event_ch_async(p->handle,&je)){
    02060       if(option_verbose>3) {
    02061          vpb_translate_event(&je, str);
    02062          ast_verbose( VERBOSE_PREFIX_4 "%s: Flushing event [%d]=>%s\n",ast->name,je.type,str);
    02063       }
    02064    }
    02065
    02066    p->readthread = 0;
    02067    p->lastoutput = -1;
    02068    p->lastinput = -1;
    02069    p->last_ignore_dtmf = 1;
    02070    p->ext[0]  = 0;
    02071    p->dialtone = 0;
    02072
    02073    p->owner = NULL;
    02074    ast->tech_pvt=NULL;
    02075
    02076    /* Free up ast dsp if we have one */
    02077    if ((use_ast_dtmfdet)&&(p->vad)) {
    02078       ast_dsp_free(p->vad);
    02079       p->vad = NULL;
    02080    }
    02081
    02082    ast_mutex_lock(&usecnt_lock); {
    02083       usecnt--;
    02084    } ast_mutex_unlock(&usecnt_lock);
    02085    ast_update_use_count();
    02086
    02087    if (option_verbose > 1)
    02088       ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup complete\n", ast->name);
    02089
    02090    restart_monitor();
    02091 /*
    02092    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    02093 */
    02094    res = ast_mutex_unlock(&p->lock);
    02095 /*
    02096    if (option_verbose > 3) ast_verbose("%s: unLOCKING in hangup [%d]\n", p->dev,res);
    02097    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    02098 */
    02099    return 0;
    02100 }
    02101
    02102 static int vpb_answer(struct ast_channel *ast)
    02103 {
    02104    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    02105    int res = 0;
    02106 /*
    02107    VPB_EVENT je;
    02108    int ret;
    02109    if (option_verbose > 3) ast_verbose("%s: LOCKING in answer \n", p->dev);
    02110    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
    02111 */
    02112    ast_mutex_lock(&p->lock);
    02113
    02114    if (option_verbose > 3)
    02115          ast_verbose(VERBOSE_PREFIX_4 "%s: Answering channel\n",p->dev);
    02116
    02117    if (p->mode == MODE_FXO){
    02118       if (option_verbose > 3)
    02119             ast_verbose("%s: Disabling Loop Drop detection\n",p->dev);
    02120       vpb_disable_event(p->handle, VPB_MDROP);
    02121    }
    02122
    02123    if (ast->_state != AST_STATE_UP) {
    02124       if (p->mode == MODE_FXO){
    02125          vpb_sethook_sync(p->handle, VPB_OFFHOOK);
    02126          p->state=VPB_STATE_OFFHOOK;
    02127 /*       vpb_sleep(500);
    02128          ret = vpb_get_event_ch_async(p->handle,&je);
    02129          if ((ret == VPB_OK)&&((je.type != VPB_DROP)&&(je.type != VPB_RING))){
    02130             if (option_verbose > 3){
    02131                   ast_verbose(VERBOSE_PREFIX_4 "%s: Answer collected a wrong event!!\n",p->dev);
    02132             }
    02133             vpb_put_event(&je);
    02134          }
    02135 */
    02136       }
    02137       ast_setstate(ast, AST_STATE_UP);
    02138
    02139       if(option_verbose>1)
    02140 /*
    02141          ast_verbose( VERBOSE_PREFIX_2 "%s: Answered call from %s on %s [%s]\n", p->dev,
    02142                p->owner->callerid, ast->name,(p->mode == MODE_FXO)?"FXO":"FXS");
    02143 */
    02144          ast_verbose( VERBOSE_PREFIX_2 "%s: Answered call on %s [%s]\n", p->dev,
    02145                 ast->name,(p->mode == MODE_FXO)?"FXO":"FXS");
    02146
    02147       ast->rings = 0;
    02148       if( !p->readthread ){
    02149    /*    res = ast_mutex_unlock(&p->lock); */
    02150    /*    ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
    02151          ast_pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
    02152       } else {
    02153          if(option_verbose>3)
    02154             ast_verbose(VERBOSE_PREFIX_4 "%s: Record thread already running!!\n",p->dev);
    02155       }
    02156    } else {
    02157       if(option_verbose>3) {
    02158          ast_verbose(VERBOSE_PREFIX_4 "%s: Answered state is up\n",p->dev);
    02159       }
    02160    /* res = ast_mutex_unlock(&p->lock); */
    02161    /* ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
    02162    }
    02163    vpb_sleep(500);
    02164    if (p->mode == MODE_FXO){
    02165       if (option_verbose > 3)
    02166             ast_verbose("%s: Re-enabling Loop Drop detection\n",p->dev);
    02167       vpb_enable_event(p->handle,VPB_MDROP);
    02168    }
    02169    res = ast_mutex_unlock(&p->lock);
    02170 /*
    02171    if(option_verbose>3) ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res);
    02172 */
    02173    return 0;
    02174 }
    02175
    02176 static struct ast_frame  *vpb_read(struct ast_channel *ast)
    02177 {
    02178    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    02179    static struct ast_frame f = {AST_FRAME_NULL};
    02180
    02181    f.src = (char *)type;
    02182    ast_log(LOG_NOTICE, "%s: vpb_read: should never be called!\n", p->dev);
    02183    ast_verbose("%s: vpb_read: should never be called!\n", p->dev);
    02184
    02185    return &f;
    02186 }
    02187
    02188 static inline int ast2vpbformat(int ast_format)
    02189 {
    02190    switch(ast_format) {
    02191       case AST_FORMAT_ALAW:
    02192          return VPB_ALAW;
    02193       case AST_FORMAT_SLINEAR:
    02194          return VPB_LINEAR;
    02195       case AST_FORMAT_ULAW:
    02196          return VPB_MULAW;
    02197       case AST_FORMAT_ADPCM:
    02198          return VPB_OKIADPCM;
    02199       default:
    02200          return -1;
    02201    }
    02202 }
    02203
    02204 static inline char * ast2vpbformatname(int ast_format)
    02205 {
    02206    switch(ast_format) {
    02207       case AST_FORMAT_ALAW:
    02208          return "AST_FORMAT_ALAW:VPB_ALAW";
    02209       case AST_FORMAT_SLINEAR:
    02210          return "AST_FORMAT_SLINEAR:VPB_LINEAR";
    02211       case AST_FORMAT_ULAW:
    02212          return "AST_FORMAT_ULAW:VPB_MULAW";
    02213       case AST_FORMAT_ADPCM:
    02214          return "AST_FORMAT_ADPCM:VPB_OKIADPCM";
    02215       default:
    02216          return "UNKN:UNKN";
    02217    }
    02218 }
    02219
    02220 static inline int astformatbits(int ast_format)
    02221 {
    02222    switch(ast_format) {
    02223       case AST_FORMAT_ALAW:
    02224       case AST_FORMAT_ULAW:
    02225          return 8;
    02226       case AST_FORMAT_SLINEAR:
    02227          return 16;
    02228       case AST_FORMAT_ADPCM:
    02229          return 4;
    02230       default:
    02231          return 8;
    02232    }
    02233 }
    02234
    02235 int a_gain_vector(float g, short *v, int n)
    02236 {
    02237    int i;
    02238    float tmp;
    02239    for ( i = 0; i<n; i++) {
    02240       tmp = g*v[i];
    02241       if (tmp > 32767.0)
    02242          tmp = 32767.0;
    02243       if (tmp < -32768.0)
    02244          tmp = -32768.0;
    02245       v[i] = (short)tmp;
    02246    }
    02247    return(i);
    02248 }
    02249
    02250 /* Writes a frame of voice data to a VPB channel */
    02251 static int vpb_write(struct ast_channel *ast, struct ast_frame *frame)
    02252 {
    02253    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
    02254    int res = 0, fmt = 0;
    02255    struct timeval play_buf_time_start;
    02256    struct ast_frame *nextf;
    02257    int tdiff;
    02258
    02259 /* ast_mutex_lock(&p->lock); */
    02260    if(option_verbose>5)
    02261       ast_verbose("%s: vpb_write: Writing to channel\n", p->dev);
    02262
    02263    if (frame->frametype != AST_FRAME_VOICE) {
    02264       if(option_verbose>3)
    02265          ast_verbose("%s: vpb_write: Don't know how to handle from type %d\n", ast->name, frame->frametype);
    02266 /*    ast_mutex_unlock(&p->lock); */
    02267       return 0;
    02268    } else if (ast->_state != AST_STATE_UP) {
    02269       if(option_verbose>3)
    02270          ast_verbose("%s: vpb_write: Attempt to Write frame type[%d]subclass[%d] on not up chan(state[%d])\n",ast->name, frame->frametype, frame->subclass,ast->_state);
    02271       p->lastoutput = -1;
    02272 /*    ast_mutex_unlock(&p->lock); */
    02273       return 0;
    02274    }
    02275 /* ast_log(LOG_DEBUG, "%s: vpb_write: Checked frame type..\n", p->dev); */
    02276
    02277
    02278    fmt = ast2vpbformat(frame->subclass);
    02279    if (fmt < 0) {
    02280       ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %d format!\n",ast->name, frame->subclass);
    02281       return -1;
    02282    }
    02283
    02284    tdiff = ast_tvdiff_ms(ast_tvnow(), p->lastplay);
    02285    ast_log(LOG_DEBUG, "%s: vpb_write: time since last play(%d) \n", p->dev, tdiff);
    02286    if (tdiff < (VPB_SAMPLES/8 - 1)){
    02287       ast_log(LOG_DEBUG, "%s: vpb_write: Asked to play too often (%d) (%d)\n", p->dev, tdiff,frame->datalen);
    02288 //    return 0;
    02289    }
    02290    p->lastplay = ast_tvnow();
    02291 /*
    02292    ast_log(LOG_DEBUG, "%s: vpb_write: Checked frame format..\n", p->dev);
    02293 */
    02294
    02295    ast_mutex_lock(&p->play_lock);
    02296
    02297 /*
    02298    ast_log(LOG_DEBUG, "%s: vpb_write: Got play lock..\n", p->dev);
    02299 */
    02300
    02301    /* Check if we have set up the play_buf */
    02302    if (p->lastoutput == -1) {
    02303       vpb_play_buf_start(p->handle, fmt);
    02304       if(option_verbose>1) {
    02305          ast_verbose("%s: vpb_write: Starting play mode (codec=%d)[%s]\n",p->dev,fmt,ast2vpbformatname(frame->subclass));
    02306       }
    02307       p->lastoutput = fmt;
    02308       ast_mutex_unlock(&p->play_lock);
    02309       return 0;
    02310    } else if (p->lastoutput != fmt) {
    02311       vpb_play_buf_finish(p->handle);
    02312       vpb_play_buf_start(p->handle, fmt);
    02313       if(option_verbose>1)
    02314          ast_verbose("%s: vpb_write: Changed play format (%d=>%d)\n",p->dev,p->lastoutput,fmt);
    02315       ast_mutex_unlock(&p->play_lock);
    02316       return 0;
    02317    }
    02318    p->lastoutput = fmt;
    02319
    02320
    02321
    02322    /* Apply extra gain ! */
    02323    if( p->txswgain > MAX_VPB_GAIN )
    02324       a_gain_vector(p->txswgain - MAX_VPB_GAIN , (short*)frame->data, frame->datalen/sizeof(short));
    02325
    02326 /* ast_log(LOG_DEBUG, "%s: vpb_write: Applied gain..\n", p->dev); */
    02327 /* ast_log(LOG_DEBUG, "%s: vpb_write: play_buf_time %d\n", p->dev, p->play_buf_time); */
    02328
    02329    if ((p->read_state == 1)&&(p->play_buf_time<5)){
    02330       play_buf_time_start = ast_tvnow();
    02331 /*    res = vpb_play_buf_sync(p->handle, (char*)frame->data, tdiff*8*2); */
    02332       res = vpb_play_buf_sync(p->handle, (char*)frame->data, frame->datalen);
    02333       if( res == VPB_OK && option_verbose > 5 ) {
    02334          short * data = (short*)frame->data;
    02335          ast_verbose("%s: vpb_write: Wrote chan (codec=%d) %d %d\n", p->dev, fmt, data[0],data[1]);
    02336       }
    02337       p->play_buf_time = ast_tvdiff_ms(ast_tvnow(), play_buf_time_start);
    02338    }
    02339    else {
    02340       p->chuck_count++;
    02341       ast_log(LOG_DEBUG, "%s: vpb_write: Tossed data away, tooooo much data!![%d]\n", p->dev,p->chuck_count);
    02342       p->play_buf_time=0;
    02343    }
    02344
    02345    ast_mutex_unlock(&p->play_lock);
    02346 /* ast_mutex_unlock(&p->lock); */
    02347    if(option_verbose>5)
    02348       ast_verbose("%s: vpb_write: Done Writing to channel\n", p->dev);
    02349    return 0;
    02350 }
    02351
    02352 /* Read monitor thread function. */
    02353 static void *do_chanreads(void *pvt)
    02354 {
    02355    struct vpb_pvt *p = (struct vpb_pvt *)pvt;
    02356    struct ast_frame *fr = &p->fr;
    02357    char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET;
    02358    int bridgerec = 0;
    02359    int afmt, readlen, res, fmt, trycnt=0;
    02360    int ignore_dtmf;
    02361    char * getdtmf_var = NULL;
    02362
    02363    fr->frametype = AST_FRAME_VOICE;
    02364    fr->src = (char *)type;
    02365    fr->mallocd = 0;
    02366    fr->delivery.tv_sec = 0;
    02367    fr->delivery.tv_usec = 0;
    02368    fr->samples = VPB_SAMPLES;
    02369    fr->offset = AST_FRIENDLY_OFFSET;
    02370    memset(p->buf, 0, sizeof p->buf);
    02371
    02372    if (option_verbose > 2) {
    02373       ast_verbose("%s: chanreads: starting thread\n", p->dev);
    02374    }
    02375    ast_mutex_lock(&p->record_lock);
    02376
    02377    p->stopreads = 0;
    02378    p->read_state = 1;
    02379    while (!p->stopreads && p->owner) {
    02380
    02381       if (option_verbose > 4)
    02382          ast_verbose("%s: chanreads: Starting cycle ...\n", p->dev);
    02383       if (option_verbose > 4)
    02384          ast_verbose("%s: chanreads: Checking bridge \n", p->dev);
    02385       if (p->bridge) {
    02386          if (p->bridge->c0 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_0))
    02387             bridgerec = 1;
    02388          else if (p->bridge->c1 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_1))
    02389             bridgerec = 1;
    02390          else
    02391             bridgerec = 0;
    02392       } else {
    02393          if (option_verbose > 4)
    02394             ast_verbose("%s: chanreads: No native bridge.\n", p->dev);
    02395          if (p->owner->_bridge){
    02396             if (option_verbose > 4){
    02397                ast_verbose("%s: chanreads: Got Asterisk bridge with [%s].\n", p->dev,p->owner->_bridge->name);
    02398             }
    02399             bridgerec = 1;
    02400          }
    02401          else {
    02402             bridgerec = 0;
    02403          }
    02404       }
    02405
    02406 /*    if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) */
    02407       if ( (p->owner->_state != AST_STATE_UP) )
    02408       {
    02409          if (option_verbose > 4) {
    02410             if (p->owner->_state != AST_STATE_UP)
    02411                ast_verbose("%s: chanreads: Im not up[%d]\n", p->dev,p->owner->_state);
    02412             else
    02413                ast_verbose("%s: chanreads: No bridgerec[%d]\n", p->dev,bridgerec);
    02414          }
    02415          vpb_sleep(10);
    02416          continue;
    02417       }
    02418
    02419       /* Voicetronix DTMF detection can be triggered off ordinary speech
    02420        * This leads to annoying beeps during the conversation
    02421        * Avoid this problem by just setting VPB_GETDTMF when you want to listen for DTMF
    02422        */
    02423       /* ignore_dtmf = 1; */
    02424       ignore_dtmf = 0; /* set this to 1 to turn this feature on */
    02425       getdtmf_var = pbx_builtin_getvar_helper(p->owner,"VPB_GETDTMF");
    02426       if( getdtmf_var && ( strcasecmp( getdtmf_var, "yes" ) == 0 ) )
    02427          ignore_dtmf = 0;
    02428
    02429       if(( ignore_dtmf != p->last_ignore_dtmf ) &&(!use_ast_dtmfdet)){
    02430          if(option_verbose>1)
    02431             ast_verbose( VERBOSE_PREFIX_2 "%s:Now %s DTMF \n",
    02432                p->dev, ignore_dtmf ? "ignoring" : "listening for");
    02433          vpb_set_event_mask(p->handle, ignore_dtmf ? VPB_EVENTS_NODTMF : VPB_EVENTS_ALL );
    02434       }
    02435       p->last_ignore_dtmf = ignore_dtmf;
    02436
    02437       /* Play DTMF digits here to avoid problem you get if playing a digit during
    02438        * a record operation
    02439        */
    02440       if (option_verbose > 5) {
    02441          ast_verbose("%s: chanreads: Checking dtmf's \n", p->dev);
    02442       }
    02443       ast_mutex_lock(&p->play_dtmf_lock);
    02444       if( p->play_dtmf[0] ) {
    02445          /* Try to ignore DTMF event we get after playing digit */
    02446          /* This DTMF is played by asterisk and leads to an annoying trailing beep on CISCO phones */
    02447          if( !ignore_dtmf)
    02448             vpb_set_event_mask(p->handle, VPB_EVENTS_NODTMF );
    02449          if (p->bridge == NULL){
    02450             vpb_dial_sync(p->handle,p->play_dtmf);
    02451             if(option_verbose>1)
    02452                ast_verbose( VERBOSE_PREFIX_2 "%s: chanreads: Played DTMF %s\n",p->dev,p->play_dtmf);
    02453          }
    02454          else {
    02455             if (option_verbose > 1)
    02456                ast_verbose(VERBOSE_PREFIX_2 "%s: chanreads: Not playing DTMF frame on native bridge\n", p->dev);
    02457          }
    02458          p->play_dtmf[0] = '\0';
    02459          ast_mutex_unlock(&p->play_dtmf_lock);
    02460          vpb_sleep(700); /* Long enough to miss echo and DTMF event */
    02461          if( !ignore_dtmf)
    02462             vpb_set_event_mask(p->handle, VPB_EVENTS_ALL );
    02463          continue;
    02464       }
    02465       ast_mutex_unlock(&p->play_dtmf_lock);
    02466
    02467 /*    afmt = (p->owner) ? p->owner->rawreadformat : AST_FORMAT_SLINEAR; */
    02468       if (p->owner){
    02469          afmt = p->owner->rawreadformat;
    02470 /*       ast_log(LOG_DEBUG,"%s: Record using owner format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
    02471       }
    02472       else {
    02473          afmt = AST_FORMAT_SLINEAR;
    02474 /*       ast_log(LOG_DEBUG,"%s: Record using default format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
    02475       }
    02476       fmt = ast2vpbformat(afmt);
    02477       if (fmt < 0) {
    02478          ast_log(LOG_WARNING,"%s: Record failure (unsupported format %d)\n", p->dev, afmt);
    02479          return NULL;
    02480       }
    02481       readlen = VPB_SAMPLES * astformatbits(afmt) / 8;
    02482
    02483       if (p->lastinput == -1) {
    02484          vpb_record_buf_start(p->handle, fmt);
    02485          vpb_reset_record_fifo_alarm(p->handle);
    02486          p->lastinput = fmt;
    02487          if(option_verbose>1)
    02488             ast_verbose( VERBOSE_PREFIX_2 "%s: Starting record mode (codec=%d)[%s]\n",p->dev,fmt,ast2vpbformatname(afmt));
    02489          continue;
    02490       } else if (p->lastinput != fmt) {
    02491          vpb_record_buf_finish(p->handle);
    02492          vpb_record_buf_start(p->handle, fmt);
    02493          p->lastinput = fmt;
    02494          if(option_verbose>1)
    02495             ast_verbose( VERBOSE_PREFIX_2 "%s: Changed record format (%d=>%d)\n",p->dev,p->lastinput,fmt);
    02496          continue;
    02497       }
    02498
    02499       /* Read only if up and not bridged, or a bridge for which we can read. */
    02500       if (option_verbose > 5) {
    02501          ast_verbose("%s: chanreads: getting buffer!\n", p->dev);
    02502       }
    02503       if( (res = vpb_record_buf_sync(p->handle, readbuf, readlen) ) == VPB_OK ) {
    02504          if (option_verbose > 5) {
    02505             ast_verbose("%s: chanreads: got buffer!\n", p->dev);
    02506          }
    02507          /* Apply extra gain ! */
    02508          if( p->rxswgain > MAX_VPB_GAIN )
    02509             a_gain_vector(p->rxswgain - MAX_VPB_GAIN , (short*)readbuf, readlen/sizeof(short));
    02510          if (option_verbose > 5) {
    02511             ast_verbose("%s: chanreads: applied gain\n", p->dev);
    02512          }
    02513
    02514          fr->subclass = afmt;
    02515          fr->data = readbuf;
    02516          fr->datalen = readlen;
    02517          fr->frametype = AST_FRAME_VOICE;
    02518
    02519          if ((use_ast_dtmfdet)&&(p->vad)){
    02520             fr = ast_dsp_process(p->owner,p->vad,fr);
    02521             if (fr && (fr->frametype == AST_FRAME_DTMF))
    02522                ast_log(LOG_DEBUG, "%s: chanreads: Detected DTMF '%c'\n",p->dev, fr->subclass);
    02523             if (fr->subclass == 'm'){
    02524                /* conf mute request */
    02525                fr->frametype = AST_FRAME_NULL;
    02526                fr->subclass = 0;
    02527             }
    02528             else if (fr->subclass == 'u'){
    02529                /* Unmute */
    02530                fr->frametype = AST_FRAME_NULL;
    02531                fr->subclass = 0;
    02532             }
    02533             else if (fr->subclass == 'f'){
    02534             }
    02535          }
    02536          /* Using trylock here to prevent deadlock when channel is hungup
    02537           * (ast_hangup() immediately gets lock)
    02538           */
    02539          if (p->owner && !p->stopreads ) {
    02540             if (option_verbose > 5) {
    02541                ast_verbose("%s: chanreads: queueing buffer on read frame q (state[%d])\n", p->dev,p->owner->_state);
    02542             }
    02543             do {
    02544                res = ast_mutex_trylock(&p->owner->lock);
    02545                trycnt++;
    02546             } while((res !=0)&&(trycnt<300));
    02547             if (res==0)  {
    02548                ast_queue_frame(p->owner, fr);
    02549                ast_mutex_unlock(&p->owner->lock);
    02550             } else {
    02551                if (option_verbose > 4)
    02552                   ast_verbose("%s: chanreads: Couldnt get lock after %d tries!\n", p->dev,trycnt);
    02553             }
    02554             trycnt=0;
    02555
    02556 /*
    02557             res = ast_mutex_trylock(&p->owner->lock);
    02558             if (res==0)  {
    02559                ast_queue_frame(p->owner, fr);
    02560                ast_mutex_unlock(&p->owner->lock);
    02561             } else {
    02562                if (res == EINVAL )
    02563                   if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EINVAL[%d]\n", p->dev,res);
    02564                else if (res == EBUSY )
    02565                   if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EBUSY[%d]\n", p->dev,res);
    02566                while(res !=0){
    02567                res = ast_mutex_trylock(&p->owner->lock);
    02568                }
    02569                if (res==0)  {
    02570                   ast_queue_frame(p->owner, fr);
    02571                   ast_mutex_unlock(&p->owner->lock);
    02572                }
    02573                else {
    02574                   if (res == EINVAL )
    02575                      if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EINVAL[%d]\n", p->dev,res);
    02576                   else if (res == EBUSY )
    02577                      if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EBUSY[%d]\n", p->dev,res);
    02578                   if (option_verbose > 4) ast_verbose("%s: chanreads: Couldnt get lock on owner[%s][%d][%d] channel to send frame!\n", p->dev,p->owner->name,(int)p->owner->lock.__m_owner,(int)p->owner->lock.__m_count);
    02579                }
    02580             }
    02581 */
    02582             if (option_verbose > 6) {
    02583                short * data = (short*)readbuf;
    02584                ast_verbose("%s: Read channel (codec=%d) %d %d\n", p->dev, fmt, data[0], data[1] );
    02585             }
    02586          }
    02587          else {
    02588             if (option_verbose > 4) {
    02589                ast_verbose("%s: p->stopreads[%d] p->owner[%p]\n", p->dev, p->stopreads,(void *)p->owner);
    02590             }
    02591          }
    02592       }
    02593       if (option_verbose > 4)
    02594          ast_verbose("%s: chanreads: Finished cycle...\n", p->dev);
    02595    }
    02596    p->read_state=0;
    02597
    02598    /* When stopreads seen, go away! */
    02599    vpb_record_buf_finish(p->handle);
    02600    p->read_state=0;
    02601    ast_mutex_unlock(&p->record_lock);
    02602
    02603    if (option_verbose > 1)
    02604       ast_verbose(VERBOSE_PREFIX_2 "%s: Ending record mode (%d/%s)\n",
    02605           p->dev, p->stopreads, p->owner? "yes" : "no");
    02606    return NULL;
    02607 }
    02608
    02609 static struct ast_channel *vpb_new(struct vpb_pvt *me, int state, char *context)
    02610 {
    02611    struct ast_channel *tmp;
    02612    char cid_num[256];
    02613    char cid_name[256];
    02614
    02615    if (me->owner) {
    02616        ast_log(LOG_WARNING, "Called vpb_new on owned channel (%s) ?!\n", me->dev);
    02617        return NULL;
    02618    }
    02619    if (option_verbose > 3)
    02620       ast_verbose("%s: New call for context [%s]\n",me->dev,context);
    02621
    02622    tmp = ast_channel_alloc(1);
    02623    if (tmp) {
    02624       if (use_ast_ind == 1){
    02625          tmp->tech = &vpb_tech_indicate;
    02626       }
    02627       else {
    02628          tmp->tech = &vpb_tech;
    02629       }
    02630
    02631       strncpy(tmp->name, me->dev, sizeof(tmp->name) - 1);
    02632       tmp->type = type;
    02633
    02634       tmp->callgroup = me->callgroup;
    02635       tmp->pickupgroup = me->pickupgroup;
    02636
    02637       /* Linear is the preferred format. Although Voicetronix supports other formats
    02638        * they are all converted to/from linear in the vpb code. Best for us to use
    02639        * linear since we can then adjust volume in this modules.
    02640        */
    02641       tmp->nativeformats = prefformat;
    02642       tmp->rawreadformat = AST_FORMAT_SLINEAR;
    02643       tmp->rawwriteformat =  AST_FORMAT_SLINEAR;
    02644       ast_setstate(tmp, state);
    02645       if (state == AST_STATE_RING) {
    02646          tmp->rings = 1;
    02647          cid_name[0] = '\0';
    02648          cid_num[0] = '\0';
    02649          ast_callerid_split(me->callerid, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
    02650          if (!ast_strlen_zero(cid_num)) {
    02651             tmp->cid.cid_num = strdup(cid_num);
    02652             tmp->cid.cid_ani = strdup(cid_num);
    02653          }
    02654          if (!ast_strlen_zero(cid_name))
    02655             tmp->cid.cid_name = strdup(cid_name);
    02656       }
    02657       tmp->tech_pvt = me;
    02658
    02659       strncpy(tmp->context, context, sizeof(tmp->context)-1);
    02660       if (strlen(me->ext))
    02661          strncpy(tmp->exten, me->ext, sizeof(tmp->exten)-1);
    02662       else
    02663          strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
    02664       if (strlen(me->language))
    02665          strncpy(tmp->language, me->language, sizeof(tmp->language)-1);
    02666
    02667       me->owner = tmp;
    02668
    02669          me->bridge = NULL;
    02670       me->lastoutput = -1;
    02671       me->lastinput = -1;
    02672       me->last_ignore_dtmf = 1;
    02673       me->readthread = 0;
    02674       me->play_dtmf[0] = '\0';
    02675       me->faxhandled =0;
    02676
    02677       me->lastgrunt  = ast_tvnow(); /* Assume at least one grunt tone seen now. */
    02678       me->lastplay  = ast_tvnow(); /* Assume at least one grunt tone seen now. */
    02679
    02680       ast_mutex_lock(&usecnt_lock);
    02681       usecnt++;
    02682       ast_mutex_unlock(&usecnt_lock);
    02683       ast_update_use_count();
    02684       if (state != AST_STATE_DOWN) {
    02685          if ((me->mode != MODE_FXO)&&(state != AST_STATE_UP)){
    02686             vpb_answer(tmp);
    02687          }
    02688          if (ast_pbx_start(tmp)) {
    02689             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
    02690             ast_hangup(tmp);
    02691             }
    02692       }
    02693    } else {
    02694       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
    02695    }
    02696    return tmp;
    02697 }
    02698
    02699 static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause)
    02700 {
    02701    int oldformat;
    02702    struct vpb_pvt *p;
    02703    struct ast_channel *tmp = NULL;
    02704    char *name = strdup(data ? (char *)data : "");
    02705    char *s, *sepstr;
    02706    int group=-1;
    02707
    02708    oldformat = format;
    02709    format &= prefformat;
    02710    if (!format) {
    02711       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
    02712       return NULL;
    02713    }
    02714
    02715    sepstr = name;
    02716    s = strsep(&sepstr, "/"); /* Handle / issues */
    02717    if (!s)
    02718       s = "";
    02719    /* Check if we are looking for a group */
    02720    if (toupper(name[0]) == 'G' || toupper(name[0])=='R') {
    02721       group=atoi(name+1);
    02722    }
    02723    /* Search for an unowned channel */
    02724    ast_mutex_lock(&iflock); {
    02725       p = iflist;
    02726       while(p) {
    02727          if (group == -1){
    02728             if (strncmp(s, p->dev + 4, sizeof p->dev) == 0) {
    02729                if (!p->owner) {
    02730                   tmp = vpb_new(p, AST_STATE_DOWN, p->context);
    02731                   break;
    02732                }
    02733             }
    02734          }
    02735          else {
    02736             if ((p->group == group) && (!p->owner)) {
    02737                tmp = vpb_new(p, AST_STATE_DOWN, p->context);
    02738                break;
    02739             }
    02740          }
    02741          p = p->next;
    02742       }
    02743    } ast_mutex_unlock(&iflock);
    02744
    02745
    02746    if (option_verbose > 1)
    02747       ast_verbose(VERBOSE_PREFIX_2 " %s requested, got: [%s]\n",
    02748       name, tmp ? tmp->name : "None");
    02749
    02750    free(name);
    02751
    02752    restart_monitor();
    02753    return tmp;
    02754 }
    02755
    02756 static float parse_gain_value(char *gain_type, char *value)
    02757 {
    02758    float gain;
    02759
    02760    /* try to scan number */
    02761    if (sscanf(value, "%30f", &gain) != 1)
    02762    {
    02763       ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", value, gain_type, config);
    02764       return DEFAULT_GAIN;
    02765    }
    02766
    02767
    02768    /* percentage? */
    02769    /*if (value[strlen(value) - 1] == '%') */
    02770    /* return gain / (float)100; */
    02771
    02772    return gain;
    02773 }
    02774
    02775 int load_module()
    02776 {
    02777    struct ast_config *cfg;
    02778    struct ast_variable *v;
    02779    struct vpb_pvt *tmp;
    02780    int board = 0, group = 0;
    02781    ast_group_t callgroup = 0;
    02782    ast_group_t pickupgroup = 0;
    02783    int mode = MODE_IMMEDIATE;
    02784    float txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN;
    02785    float txswgain = 0, rxswgain = 0;
    02786    int got_gain=0;
    02787    int first_channel = 1;
    02788    int echo_cancel = DEFAULT_ECHO_CANCEL;
    02789    int error = 0; /* Error flag */
    02790    int bal1 = -1; /* Special value - means do not set */
    02791    int bal2 = -1;
    02792    int bal3 = -1;
    02793    char * callerid = NULL;
    02794
    02795    cfg = ast_config_load(config);
    02796
    02797    /* We *must* have a config file otherwise stop immediately */
    02798    if (!cfg) {
    02799       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
    02800       return -1;
    02801    }
    02802
    02803    vpb_seterrormode(VPB_ERROR_CODE);
    02804
    02805    ast_mutex_lock(&iflock); {
    02806       v = ast_variable_browse(cfg, "general");
    02807       while (v){
    02808          if (strcasecmp(v->name, "cards") == 0) {
    02809             ast_log(LOG_NOTICE,"VPB Driver configured to use [%d] cards\n",atoi(v->value));
    02810          }
    02811          else if (strcasecmp(v->name, "indication") == 0) {
    02812             use_ast_ind = 1;
    02813             ast_log(LOG_NOTICE,"VPB driver using Asterisk Indication functions!\n");
    02814          }
    02815          else if (strcasecmp(v->name, "break-for-dtmf") == 0) {
    02816             if (ast_true(v->value)){
    02817                break_for_dtmf = 1;
    02818             }
    02819             else {
    02820                break_for_dtmf = 0;
    02821                ast_log(LOG_NOTICE,"VPB driver not stopping for DTMF's in native bridge\n");
    02822             }
    02823          }
    02824          else if (strcasecmp(v->name, "ast-dtmf") == 0) {
    02825             use_ast_dtmf = 1;
    02826             ast_log(LOG_NOTICE,"VPB driver using Asterisk DTMF play functions!\n");
    02827          }
    02828          else if (strcasecmp(v->name, "ast-dtmf-det") == 0) {
    02829             use_ast_dtmfdet = 1;
    02830             ast_log(LOG_NOTICE,"VPB driver using Asterisk DTMF detection functions!\n");
    02831          }
    02832          else if (strcasecmp(v->name, "relaxdtmf") == 0) {
    02833             relaxdtmf = 1;
    02834             ast_log(LOG_NOTICE,"VPB driver using Relaxed DTMF with Asterisk DTMF detections functions!\n");
    02835          }
    02836          else if (strcasecmp(v->name, "timer_period_ring") ==0) {
    02837             timer_period_ring = atoi(v->value);
    02838          }
    02839          else if (strcasecmp(v->name, "ecsuppthres") ==0) {
    02840             ec_supp_threshold = atoi(v->value);
    02841          }
    02842          else if (strcasecmp(v->name, "dtmfidd") ==0) {
    02843             dtmf_idd = atoi(v->value);
    02844             ast_log(LOG_NOTICE,"VPB Driver setting DTMF IDD to [%d]ms\n",dtmf_idd);
    02845          }
    02846          v = v->next;
    02847       }
    02848
    02849       v = ast_variable_browse(cfg, "interfaces");
    02850       while(v) {
    02851          /* Create the interface list */
    02852          if (strcasecmp(v->name, "board") == 0) {
    02853             board = atoi(v->value);
    02854          } else  if (strcasecmp(v->name, "group") == 0){
    02855             group = atoi(v->value);
    02856          } else  if (strcasecmp(v->name, "callgroup") == 0){
    02857             callgroup = ast_get_group(v->value);
    02858          } else  if (strcasecmp(v->name, "pickupgroup") == 0){
    02859             pickupgroup = ast_get_group(v->value);
    02860          } else  if (strcasecmp(v->name, "usepolaritycid") == 0){
    02861             UsePolarityCID = atoi(v->value);
    02862          } else  if (strcasecmp(v->name, "useloopdrop") == 0){
    02863             UseLoopDrop = atoi(v->value);
    02864          } else  if (strcasecmp(v->name, "usenativebridge") == 0){
    02865             UseNativeBridge = atoi(v->value);
    02866          } else if (strcasecmp(v->name, "channel") == 0) {
    02867             int channel = atoi(v->value);
    02868             tmp = mkif(board, channel, mode, got_gain, txgain, rxgain, txswgain, rxswgain, bal1, bal2, bal3, callerid, echo_cancel,group,callgroup,pickupgroup);
    02869             if (tmp) {
    02870                if(first_channel) {
    02871                   mkbrd( tmp->vpb_model, echo_cancel );
    02872                   first_channel = 0;
    02873                }
    02874                tmp->next = iflist;
    02875                iflist = tmp;
    02876             } else {
    02877                ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
    02878                error = -1;
    02879                goto done;
    02880             }
    02881          } else if (strcasecmp(v->name, "language") == 0) {
    02882             strncpy(language, v->value, sizeof(language)-1);
    02883          } else if (strcasecmp(v->name, "callerid") == 0) {
    02884             callerid = strdup(v->value);
    02885          } else if (strcasecmp(v->name, "mode") == 0) {
    02886             if (strncasecmp(v->value, "di", 2) == 0)
    02887                mode = MODE_DIALTONE;
    02888             else if (strncasecmp(v->value, "im", 2) == 0)
    02889                mode = MODE_IMMEDIATE;
    02890             else if (strncasecmp(v->value, "fx", 2) == 0)
    02891                mode = MODE_FXO;
    02892             else
    02893                ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
    02894          } else if (!strcasecmp(v->name, "context")) {
    02895             strncpy(context, v->value, sizeof(context)-1);
    02896          } else if (!strcasecmp(v->name, "echocancel")) {
    02897             if (!strcasecmp(v->value, "off"))
    02898                echo_cancel = 0;
    02899          } else if (strcasecmp(v->name, "txgain") == 0) {
    02900             txswgain = parse_gain_value(v->name, v->value);
    02901             got_gain |=VPB_GOT_TXSWG;
    02902          } else if (strcasecmp(v->name, "rxgain") == 0) {
    02903             rxswgain = parse_gain_value(v->name, v->value);
    02904             got_gain |=VPB_GOT_RXSWG;
    02905          } else if (strcasecmp(v->name, "txhwgain") == 0) {
    02906             txgain = parse_gain_value(v->name, v->value);
    02907             got_gain |=VPB_GOT_TXHWG;
    02908          } else if (strcasecmp(v->name, "rxhwgain") == 0) {
    02909             rxgain = parse_gain_value(v->name, v->value);
    02910             got_gain |=VPB_GOT_RXHWG;
    02911          } else if (strcasecmp(v->name, "bal1") == 0) {
    02912             bal1 = strtol(v->value, NULL, 16);
    02913             if(bal1<0 || bal1>255) {
    02914                ast_log(LOG_WARNING, "Bad bal1 value: %d\n", bal1);
    02915                bal1 = -1;
    02916             }
    02917          } else if (strcasecmp(v->name, "bal2") == 0) {
    02918             bal2 = strtol(v->value, NULL, 16);
    02919             if(bal2<0 || bal2>255) {
    02920                ast_log(LOG_WARNING, "Bad bal2 value: %d\n", bal2);
    02921                bal2 = -1;
    02922             }
    02923          } else if (strcasecmp(v->name, "bal3") == 0) {
    02924             bal3 = strtol(v->value, NULL, 16);
    02925             if(bal3<0 || bal3>255) {
    02926                ast_log(LOG_WARNING, "Bad bal3 value: %d\n", bal3);
    02927                bal3 = -1;
    02928             }
    02929          } else if (strcasecmp(v->name, "grunttimeout") == 0) {
    02930             gruntdetect_timeout = 1000*atoi(v->value);
    02931          }
    02932          v = v->next;
    02933       }
    02934
    02935       if (gruntdetect_timeout < 1000)
    02936          gruntdetect_timeout = 1000;
    02937
    02938       done: (void)0;
    02939    } ast_mutex_unlock(&iflock);
    02940
    02941    ast_config_destroy(cfg);
    02942
    02943    if (use_ast_ind == 1){
    02944       if (!error && ast_channel_register(&vpb_tech_indicate) != 0) {
    02945          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    02946          error = -1;
    02947       }
    02948       else {
    02949          ast_log(LOG_NOTICE,"VPB driver Registered (w/AstIndication)\n");
    02950       }
    02951    }
    02952    else {
    02953       if (!error && ast_channel_register(&vpb_tech) != 0) {
    02954          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    02955          error = -1;
    02956       }
    02957       else {
    02958          ast_log(LOG_NOTICE,"VPB driver Registered )\n");
    02959       }
    02960    }
    02961
    02962
    02963    if (error)
    02964       unload_module();
    02965    else
    02966       restart_monitor(); /* And start the monitor for the first time */
    02967
    02968    return error;
    02969 }
    02970
    02971
    02972 int unload_module()
    02973 {
    02974    struct vpb_pvt *p;
    02975    /* First, take us out of the channel loop */
    02976    if (use_ast_ind == 1){
    02977       ast_channel_unregister(&vpb_tech_indicate);
    02978    }
    02979    else {
    02980       ast_channel_unregister(&vpb_tech);
    02981    }
    02982
    02983    ast_mutex_lock(&iflock); {
    02984       /* Hangup all interfaces if they have an owner */
    02985       p = iflist;
    02986       while(p) {
    02987          if (p->owner)
    02988             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
    02989          p = p->next;
    02990       }
    02991       iflist = NULL;
    02992    } ast_mutex_unlock(&iflock);
    02993
    02994    ast_mutex_lock(&monlock); {
    02995       if (mthreadactive > -1) {
    02996          pthread_cancel(monitor_thread);
    02997          pthread_join(monitor_thread, NULL);
    02998       }
    02999       mthreadactive = -2;
    03000    } ast_mutex_unlock(&monlock);
    03001
    03002    ast_mutex_lock(&iflock); {
    03003       /* Destroy all the interfaces and free their memory */
    03004
    03005       while(iflist) {
    03006          p = iflist;
    03007          ast_mutex_destroy(&p->lock);
    03008          pthread_cancel(p->readthread);
    03009          ast_mutex_destroy(&p->owner_lock);
    03010          ast_mutex_destroy(&p->record_lock);
    03011          ast_mutex_destroy(&p->play_lock);
    03012          ast_mutex_destroy(&p->play_dtmf_lock);
    03013          p->readthread = 0;
    03014
    03015          vpb_close(p->handle);
    03016
    03017          iflist = iflist->next;
    03018
    03019          free(p);
    03020       }
    03021       iflist = NULL;
    03022    } ast_mutex_unlock(&iflock);
    03023
    03024    ast_mutex_lock(&bridge_lock); {
    03025       memset(bridges, 0, sizeof bridges);
    03026    } ast_mutex_unlock(&bridge_lock);
    03027    ast_mutex_destroy(&bridge_lock);
    03028    for(int i = 0; i < max_bridges; i++ ) {
    03029       ast_mutex_destroy(&bridges[i].lock);
    03030       ast_cond_destroy(&bridges[i].cond);
    03031    }
    03032    free(bridges);
    03033
    03034    return 0;
    03035 }
    03036
    03037 int usecount()
    03038 {
    03039    return usecnt;
    03040 }
    03041
    03042 char *description()
    03043 {
    03044    return (char *) desc;
    03045 }
    03046
    03047 char *key()
    03048 {
    03049    return ASTERISK_GPL_KEY;
    03050 }
    03051
    03052 /**/
    03053 #if defined(__cplusplus) || defined(c_plusplus)
    03054  }
    03055 #endif
    03056 /**/