Sat Feb 11 06:34:41 2012

Asterisk developer's documentation


chan_phone.c File Reference

Generic Linux Telephony Interface driver. More...

#include "asterisk.h"
#include <ctype.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <linux/telephony.h>
#include <linux/version.h>
#include <linux/ixjuser.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
#include "chan_phone.h"

Include dependency graph for chan_phone.c:

Go to the source code of this file.

Data Structures

struct  phone_pvt

Defines

#define DEFAULT_CALLER_ID   "Unknown"
#define DEFAULT_GAIN   0x100
#define IXJ_PHONE_RING_START(x)   ioctl(p->fd, PHONE_RING_START, &x);
#define MODE_DIALTONE   1
#define MODE_FXO   3
#define MODE_FXS   4
#define MODE_IMMEDIATE   2
#define MODE_SIGMA   5
#define PHONE_MAX_BUF   480
#define QNDRV_VER   100

Functions

static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static void * do_monitor (void *data)
static int load_module (void)
static struct phone_pvtmkif (const char *iface, int mode, int txgain, int rxgain)
static int parse_gain_value (const char *gain_type, const char *value)
static int phone_answer (struct ast_channel *ast)
static int phone_call (struct ast_channel *ast, const char *dest, int timeout)
static void phone_check_exception (struct phone_pvt *i)
static int phone_digit_begin (struct ast_channel *ast, char digit)
static int phone_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static struct ast_framephone_exception (struct ast_channel *ast)
static int phone_fixup (struct ast_channel *old, struct ast_channel *new)
static int phone_hangup (struct ast_channel *ast)
static int phone_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void phone_mini_packet (struct phone_pvt *i)
static struct ast_channelphone_new (struct phone_pvt *i, int state, char *cntx, const char *linkedid)
static struct ast_framephone_read (struct ast_channel *ast)
static struct ast_channelphone_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
static int phone_send_text (struct ast_channel *ast, const char *text)
static int phone_setup (struct ast_channel *ast)
static int phone_write (struct ast_channel *ast, struct ast_frame *frame)
static int phone_write_buf (struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
static int restart_monitor (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Linux Telephony API Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static struct ast_module_infoast_module_info = &__mod_info
static char cid_name [AST_MAX_EXTENSION]
static char cid_num [AST_MAX_EXTENSION]
static const char config [] = "phone.conf"
static char context [AST_MAX_EXTENSION] = "default"
static struct ast_channel_techcur_tech
static int echocancel = AEC_OFF
static struct phone_pvtiflist
static ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static char language [MAX_LANGUAGE] = ""
static unsigned int monitor
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct ast_channel_tech phone_tech
static struct ast_channel_tech phone_tech_fxs
static struct ast_format_capprefcap
static int silencesupression = 0
static const char tdesc [] = "Standard Linux Telephony API Driver"


Detailed Description

Generic Linux Telephony Interface driver.

Author:
Mark Spencer <markster@digium.com>

Definition in file chan_phone.c.


Define Documentation

#define DEFAULT_CALLER_ID   "Unknown"

Definition at line 81 of file chan_phone.c.

Referenced by phone_call().

#define DEFAULT_GAIN   0x100

Definition at line 83 of file chan_phone.c.

Referenced by load_module(), and parse_gain_value().

#define IXJ_PHONE_RING_START (  )     ioctl(p->fd, PHONE_RING_START, &x);

Definition at line 78 of file chan_phone.c.

Referenced by phone_call().

#define MODE_DIALTONE   1

Definition at line 119 of file chan_phone.c.

Referenced by load_module(), and phone_check_exception().

#define MODE_FXO   3

Definition at line 121 of file chan_phone.c.

Referenced by load_module(), mkif(), phone_answer(), phone_exception(), and phone_hangup().

#define MODE_FXS   4

#define MODE_IMMEDIATE   2

Definition at line 120 of file chan_phone.c.

Referenced by load_module(), and phone_check_exception().

#define MODE_SIGMA   5

Definition at line 123 of file chan_phone.c.

Referenced by do_monitor(), load_module(), and phone_check_exception().

#define PHONE_MAX_BUF   480

Definition at line 82 of file chan_phone.c.

Referenced by phone_read().

#define QNDRV_VER   100

Definition at line 68 of file chan_phone.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1496 of file chan_phone.c.

static int __unload_module ( void   )  [static]

Definition at line 1295 of file chan_phone.c.

References ast_channel_unregister(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_channel_tech::capabilities, phone_pvt::fd, iflist, iflock, LOG_WARNING, monlock, phone_pvt::next, and phone_pvt::owner.

01296 {
01297    struct phone_pvt *p, *pl;
01298    /* First, take us out of the channel loop */
01299    if (cur_tech)
01300       ast_channel_unregister(cur_tech);
01301    if (!ast_mutex_lock(&iflock)) {
01302       /* Hangup all interfaces if they have an owner */
01303       p = iflist;
01304       while(p) {
01305          if (p->owner)
01306             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01307          p = p->next;
01308       }
01309       iflist = NULL;
01310       ast_mutex_unlock(&iflock);
01311    } else {
01312       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01313       return -1;
01314    }
01315    if (!ast_mutex_lock(&monlock)) {
01316       if (monitor_thread > AST_PTHREADT_NULL) {
01317          monitor = 0;
01318          while (pthread_kill(monitor_thread, SIGURG) == 0)
01319             sched_yield();
01320          pthread_join(monitor_thread, NULL);
01321       }
01322       monitor_thread = AST_PTHREADT_STOP;
01323       ast_mutex_unlock(&monlock);
01324    } else {
01325       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01326       return -1;
01327    }
01328 
01329    if (!ast_mutex_lock(&iflock)) {
01330       /* Destroy all the interfaces and free their memory */
01331       p = iflist;
01332       while(p) {
01333          /* Close the socket, assuming it's real */
01334          if (p->fd > -1)
01335             close(p->fd);
01336          pl = p;
01337          p = p->next;
01338          /* Free associated memory */
01339          ast_free(pl);
01340       }
01341       iflist = NULL;
01342       ast_mutex_unlock(&iflock);
01343    } else {
01344       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01345       return -1;
01346    }
01347 
01348    phone_tech.capabilities = ast_format_cap_destroy(phone_tech.capabilities);
01349    phone_tech_fxs.capabilities = ast_format_cap_destroy(phone_tech_fxs.capabilities);
01350    prefcap = ast_format_cap_destroy(prefcap);
01351    return 0;
01352 }

static void __unreg_module ( void   )  [static]

Definition at line 1496 of file chan_phone.c.

static void* do_monitor ( void *  data  )  [static]

Definition at line 1014 of file chan_phone.c.

References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_poll, ast_poll2(), ast_realloc, ast_tv(), ast_tvzero(), DialTone, phone_pvt::dialtone, errno, phone_pvt::fd, iflist, iflock, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, phone_pvt::owner, phone_check_exception(), and phone_mini_packet().

01015 {
01016    struct pollfd *fds = NULL;
01017    int nfds = 0, inuse_fds = 0, res;
01018    struct phone_pvt *i;
01019    int tonepos = 0;
01020    /* The tone we're playing this round */
01021    struct timeval tv = { 0, 0 };
01022    int dotone;
01023    /* This thread monitors all the frame relay interfaces which are not yet in use
01024       (and thus do not have a separate thread) indefinitely */
01025    while (monitor) {
01026       /* Don't let anybody kill us right away.  Nobody should lock the interface list
01027          and wait for the monitor list, but the other way around is okay. */
01028       /* Lock the interface list */
01029       if (ast_mutex_lock(&iflock)) {
01030          ast_log(LOG_ERROR, "Unable to grab interface lock\n");
01031          return NULL;
01032       }
01033       /* Build the stuff we're going to select on, that is the socket of every
01034          phone_pvt that does not have an associated owner channel */
01035       i = iflist;
01036       dotone = 0;
01037       inuse_fds = 0;
01038       for (i = iflist; i; i = i->next) {
01039          if (!i->owner) {
01040             /* This needs to be watched, as it lacks an owner */
01041             if (inuse_fds == nfds) {
01042                void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
01043                if (!tmp) {
01044                   /* Avoid leaking */
01045                   continue;
01046                }
01047                fds = tmp;
01048                nfds++;
01049             }
01050             fds[inuse_fds].fd = i->fd;
01051             fds[inuse_fds].events = POLLIN | POLLERR;
01052             fds[inuse_fds].revents = 0;
01053             inuse_fds++;
01054 
01055             if (i->dialtone && i->mode != MODE_SIGMA) {
01056                /* Remember we're going to have to come back and play
01057                   more dialtones */
01058                if (ast_tvzero(tv)) {
01059                   /* If we're due for a dialtone, play one */
01060                   if (write(i->fd, DialTone + tonepos, 240) != 240) {
01061                      ast_log(LOG_WARNING, "Dial tone write error\n");
01062                   }
01063                }
01064                dotone++;
01065             }
01066          }
01067       }
01068       /* Okay, now that we know what to do, release the interface lock */
01069       ast_mutex_unlock(&iflock);
01070 
01071       /* Wait indefinitely for something to happen */
01072       if (dotone && i && i->mode != MODE_SIGMA) {
01073          /* If we're ready to recycle the time, set it to 30 ms */
01074          tonepos += 240;
01075          if (tonepos >= sizeof(DialTone)) {
01076             tonepos = 0;
01077          }
01078          if (ast_tvzero(tv)) {
01079             tv = ast_tv(0, 30000);
01080          }
01081          res = ast_poll2(fds, inuse_fds, &tv);
01082       } else {
01083          res = ast_poll(fds, inuse_fds, -1);
01084          tv = ast_tv(0, 0);
01085          tonepos = 0;
01086       }
01087       /* Okay, select has finished.  Let's see what happened.  */
01088       if (res < 0) {
01089          ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
01090          continue;
01091       }
01092       /* If there are no fd's changed, just continue, it's probably time
01093          to play some more dialtones */
01094       if (!res) {
01095          continue;
01096       }
01097       /* Alright, lock the interface list again, and let's look and see what has
01098          happened */
01099       if (ast_mutex_lock(&iflock)) {
01100          ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01101          continue;
01102       }
01103 
01104       for (i = iflist; i; i = i->next) {
01105          int j;
01106          /* Find the record */
01107          for (j = 0; j < inuse_fds; j++) {
01108             if (fds[j].fd == i->fd) {
01109                break;
01110             }
01111          }
01112 
01113          /* Not found? */
01114          if (j == inuse_fds) {
01115             continue;
01116          }
01117 
01118          if (fds[j].revents & POLLIN) {
01119             if (i->owner) {
01120                continue;
01121             }
01122             phone_mini_packet(i);
01123          }
01124          if (fds[j].revents & POLLERR) {
01125             if (i->owner) {
01126                continue;
01127             }
01128             phone_check_exception(i);
01129          }
01130       }
01131       ast_mutex_unlock(&iflock);
01132    }
01133    return NULL;
01134 }

static int load_module ( void   )  [static]

Definition at line 1359 of file chan_phone.c.

References __unload_module(), ast_callerid_split(), ast_channel_register(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_format_cap_add(), ast_format_cap_alloc(), ast_format_cap_copy(), ast_format_cap_remove_bytype(), ast_format_cap_set(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_lock, ast_mutex_unlock, ast_true(), ast_variable_browse(), ast_channel_tech::capabilities, CONFIG_STATUS_FILEINVALID, DEFAULT_GAIN, iflist, iflock, LOG_ERROR, LOG_WARNING, mkif(), phone_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, ast_variable::name, ast_variable::next, phone_pvt::next, parse_gain_value(), restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.

01360 {
01361    struct ast_config *cfg;
01362    struct ast_variable *v;
01363    struct phone_pvt *tmp;
01364    int mode = MODE_IMMEDIATE;
01365    int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
01366    struct ast_flags config_flags = { 0 };
01367    struct ast_format tmpfmt;
01368 
01369    if (!(phone_tech.capabilities = ast_format_cap_alloc())) {
01370       return AST_MODULE_LOAD_DECLINE;
01371    }
01372    ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
01373    ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
01374    ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
01375    ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
01376 
01377    if (!(prefcap = ast_format_cap_alloc())) {
01378       return AST_MODULE_LOAD_DECLINE;
01379    }
01380    ast_format_cap_copy(prefcap, phone_tech.capabilities);
01381    if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc())) {
01382       return AST_MODULE_LOAD_DECLINE;
01383    }
01384 
01385    if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
01386       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
01387       return AST_MODULE_LOAD_DECLINE;
01388    }
01389 
01390    /* We *must* have a config file otherwise stop immediately */
01391    if (!cfg) {
01392       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01393       return AST_MODULE_LOAD_DECLINE;
01394    }
01395    if (ast_mutex_lock(&iflock)) {
01396       /* It's a little silly to lock it, but we mind as well just to be sure */
01397       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01398       return AST_MODULE_LOAD_FAILURE;
01399    }
01400    v = ast_variable_browse(cfg, "interfaces");
01401    while(v) {
01402       /* Create the interface list */
01403       if (!strcasecmp(v->name, "device")) {
01404             tmp = mkif(v->value, mode, txgain, rxgain);
01405             if (tmp) {
01406                tmp->next = iflist;
01407                iflist = tmp;
01408                
01409             } else {
01410                ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01411                ast_config_destroy(cfg);
01412                ast_mutex_unlock(&iflock);
01413                __unload_module();
01414                return AST_MODULE_LOAD_FAILURE;
01415             }
01416       } else if (!strcasecmp(v->name, "silencesupression")) {
01417          silencesupression = ast_true(v->value);
01418       } else if (!strcasecmp(v->name, "language")) {
01419          ast_copy_string(language, v->value, sizeof(language));
01420       } else if (!strcasecmp(v->name, "callerid")) {
01421          ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01422       } else if (!strcasecmp(v->name, "mode")) {
01423          if (!strncasecmp(v->value, "di", 2)) 
01424             mode = MODE_DIALTONE;
01425          else if (!strncasecmp(v->value, "sig", 3))
01426             mode = MODE_SIGMA;
01427          else if (!strncasecmp(v->value, "im", 2))
01428             mode = MODE_IMMEDIATE;
01429          else if (!strncasecmp(v->value, "fxs", 3)) {
01430             mode = MODE_FXS;
01431             ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */
01432          }
01433          else if (!strncasecmp(v->value, "fx", 2))
01434             mode = MODE_FXO;
01435          else
01436             ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01437       } else if (!strcasecmp(v->name, "context")) {
01438          ast_copy_string(context, v->value, sizeof(context));
01439       } else if (!strcasecmp(v->name, "format")) {
01440          struct ast_format tmpfmt;
01441          if (!strcasecmp(v->value, "g729")) {
01442             ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0));
01443          } else if (!strcasecmp(v->value, "g723.1")) {
01444             ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0));
01445          } else if (!strcasecmp(v->value, "slinear")) {
01446             ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0);
01447             if (mode == MODE_FXS) {
01448                ast_format_cap_add(prefcap, &tmpfmt);
01449             } else {
01450                ast_format_cap_set(prefcap, &tmpfmt);
01451             }
01452          } else if (!strcasecmp(v->value, "ulaw")) {
01453             ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
01454          } else
01455             ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01456       } else if (!strcasecmp(v->name, "echocancel")) {
01457          if (!strcasecmp(v->value, "off")) {
01458             echocancel = AEC_OFF;
01459          } else if (!strcasecmp(v->value, "low")) {
01460             echocancel = AEC_LOW;
01461          } else if (!strcasecmp(v->value, "medium")) {
01462             echocancel = AEC_MED;
01463          } else if (!strcasecmp(v->value, "high")) {
01464             echocancel = AEC_HIGH;
01465          } else 
01466             ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01467       } else if (!strcasecmp(v->name, "txgain")) {
01468          txgain = parse_gain_value(v->name, v->value);
01469       } else if (!strcasecmp(v->name, "rxgain")) {
01470          rxgain = parse_gain_value(v->name, v->value);
01471       }  
01472       v = v->next;
01473    }
01474    ast_mutex_unlock(&iflock);
01475 
01476    if (mode == MODE_FXS) {
01477       ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap);
01478       cur_tech = &phone_tech_fxs;
01479    } else
01480       cur_tech = (struct ast_channel_tech *) &phone_tech;
01481 
01482    /* Make sure we can register our Adtranphone channel type */
01483 
01484    if (ast_channel_register(cur_tech)) {
01485       ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
01486       ast_config_destroy(cfg);
01487       __unload_module();
01488       return AST_MODULE_LOAD_FAILURE;
01489    }
01490    ast_config_destroy(cfg);
01491    /* And start the monitor for the first time */
01492    restart_monitor();
01493    return AST_MODULE_LOAD_SUCCESS;
01494 }

static struct phone_pvt* mkif ( const char *  iface,
int  mode,
int  txgain,
int  rxgain 
) [static, read]

Definition at line 1173 of file chan_phone.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_format_clear(), ast_free, ast_log(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::dialtone, errno, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, MODE_FXS, phone_pvt::next, phone_pvt::obuflen, phone_pvt::owner, phone_pvt::rxgain, phone_pvt::silencesupression, and phone_pvt::txgain.

Referenced by load_module().

01174 {
01175    /* Make a phone_pvt structure for this interface */
01176    struct phone_pvt *tmp;
01177    int flags;  
01178    
01179    tmp = ast_calloc(1, sizeof(*tmp));
01180    if (tmp) {
01181       tmp->fd = open(iface, O_RDWR);
01182       if (tmp->fd < 0) {
01183          ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01184          ast_free(tmp);
01185          return NULL;
01186       }
01187       if (mode == MODE_FXO) {
01188          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
01189             ast_debug(1, "Unable to set port to PSTN\n");
01190          }
01191       } else {
01192          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 
01193              if (mode != MODE_FXS)
01194                   ast_debug(1, "Unable to set port to POTS\n");
01195       }
01196       ioctl(tmp->fd, PHONE_PLAY_STOP);
01197       ioctl(tmp->fd, PHONE_REC_STOP);
01198       ioctl(tmp->fd, PHONE_RING_STOP);
01199       ioctl(tmp->fd, PHONE_CPT_STOP);
01200       if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01201          ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01202       if (echocancel != AEC_OFF)
01203          ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01204       if (silencesupression) 
01205          tmp->silencesupression = 1;
01206 #ifdef PHONE_VAD
01207       ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01208 #endif
01209       tmp->mode = mode;
01210       flags = fcntl(tmp->fd, F_GETFL);
01211       fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01212       tmp->owner = NULL;
01213       ast_format_clear(&tmp->lastformat);
01214       ast_format_clear(&tmp->lastinput);
01215       tmp->ministate = 0;
01216       memset(tmp->ext, 0, sizeof(tmp->ext));
01217       ast_copy_string(tmp->language, language, sizeof(tmp->language));
01218       ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01219       ast_copy_string(tmp->context, context, sizeof(tmp->context));
01220       tmp->next = NULL;
01221       tmp->obuflen = 0;
01222       tmp->dialtone = 0;
01223       tmp->cpt = 0;
01224       ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01225       ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01226       tmp->txgain = txgain;
01227       ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01228       tmp->rxgain = rxgain;
01229       ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01230    }
01231    return tmp;
01232 }

static int parse_gain_value ( const char *  gain_type,
const char *  value 
) [static]

Definition at line 1273 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

01274 {
01275    float gain;
01276 
01277    /* try to scan number */
01278    if (sscanf(value, "%30f", &gain) != 1)
01279    {
01280       ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01281          value, gain_type, config);
01282       return DEFAULT_GAIN;
01283    }
01284 
01285    /* multiplicate gain by 1.0 gain value */ 
01286    gain = gain * (float)DEFAULT_GAIN;
01287 
01288    /* percentage? */
01289    if (value[strlen(value) - 1] == '%')
01290       return (int)(gain / (float)100);
01291 
01292    return (int)gain;
01293 }

static int phone_answer ( struct ast_channel ast  )  [static]

Definition at line 456 of file chan_phone.c.

References ast_channel_name(), ast_debug, ast_setstate(), AST_STATE_UP, errno, phone_pvt::fd, phone_pvt::mode, MODE_FXO, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt.

00457 {
00458    struct phone_pvt *p;
00459    p = ast->tech_pvt;
00460    /* In case it's a LineJack, take it off hook */
00461    if (p->mode == MODE_FXO) {
00462       if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
00463          ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast_channel_name(ast), strerror(errno));
00464       else
00465          ast_debug(1, "Took linejack off hook\n");
00466    }
00467    phone_setup(ast);
00468    ast_debug(1, "phone_answer(%s)\n", ast_channel_name(ast));
00469    ast->rings = 0;
00470    ast_setstate(ast, AST_STATE_UP);
00471    return 0;
00472 }

static int phone_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
) [static]

Definition at line 287 of file chan_phone.c.

References ast_channel::_state, ast_channel_name(), AST_CONTROL_RINGING, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_tvnow(), ast_channel::connected, DEFAULT_CALLER_ID, ast_channel::fds, ast_party_connected_line::id, IXJ_PHONE_RING_START, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_party_id::name, ast_party_id::number, phone_digit_end(), ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_party_number::valid, and ast_party_name::valid.

00288 {
00289    struct phone_pvt *p;
00290 
00291    PHONE_CID cid;
00292    struct timeval UtcTime = ast_tvnow();
00293    struct ast_tm tm;
00294    int start;
00295 
00296    ast_localtime(&UtcTime, &tm, NULL);
00297 
00298    memset(&cid, 0, sizeof(PHONE_CID));
00299     snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1));
00300     snprintf(cid.day, sizeof(cid.day),     "%02d", tm.tm_mday);
00301     snprintf(cid.hour, sizeof(cid.hour),   "%02d", tm.tm_hour);
00302     snprintf(cid.min, sizeof(cid.min),     "%02d", tm.tm_min);
00303    /* the standard format of ast->callerid is:  "name" <number>, but not always complete */
00304    if (!ast->connected.id.name.valid
00305       || ast_strlen_zero(ast->connected.id.name.str)) {
00306       strcpy(cid.name, DEFAULT_CALLER_ID);
00307    } else {
00308       ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name));
00309    }
00310 
00311    if (ast->connected.id.number.valid && ast->connected.id.number.str) {
00312       ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number));
00313    }
00314 
00315    p = ast->tech_pvt;
00316 
00317    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00318       ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
00319       return -1;
00320    }
00321    ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast_channel_name(ast), ast->fds[0]);
00322 
00323    start = IXJ_PHONE_RING_START(cid);
00324    if (start == -1)
00325       return -1;
00326    
00327    if (p->mode == MODE_FXS) {
00328       const char *digit = strchr(dest, '/');
00329       if (digit)
00330       {
00331         digit++;
00332         while (*digit)
00333           phone_digit_end(ast, *digit++, 0);
00334       }
00335    }
00336  
00337    ast_setstate(ast, AST_STATE_RINGING);
00338    ast_queue_control(ast, AST_CONTROL_RINGING);
00339    return 0;
00340 }

static void phone_check_exception ( struct phone_pvt i  )  [static]

Definition at line 921 of file chan_phone.c.

References ast_canmatch_extension(), ast_debug, ast_exists_extension(), ast_format_clear(), AST_MAX_EXTENSION, ast_module_ref(), ast_module_unref(), AST_STATE_RING, ast_verbose, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, phone_pvt::mode, MODE_DIALTONE, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, and phone_new().

Referenced by do_monitor().

00922 {
00923    int offhook=0;
00924    char digit[2] = {0 , 0};
00925    union telephony_exception phonee;
00926    /* XXX Do something XXX */
00927 #if 0
00928    ast_debug(1, "Exception!\n");
00929 #endif
00930    phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
00931    if (phonee.bits.dtmf_ready)  {
00932       digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
00933       if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
00934          ioctl(i->fd, PHONE_PLAY_STOP);
00935          ioctl(i->fd, PHONE_REC_STOP);
00936          ioctl(i->fd, PHONE_CPT_STOP);
00937          i->dialtone = 0;
00938          if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
00939             strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
00940          if ((i->mode != MODE_FXS ||
00941               !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
00942               !phonee.bits.dtmf_ready) &&
00943              ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00944             /* It's a valid extension in its context, get moving! */
00945             phone_new(i, AST_STATE_RING, i->context, NULL);
00946             /* No need to restart monitor, we are the monitor */
00947          } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00948             /* There is nothing in the specified extension that can match anymore.
00949                Try the default */
00950             if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00951                /* Check the default, too... */
00952                phone_new(i, AST_STATE_RING, "default", NULL);
00953                /* XXX This should probably be justified better XXX */
00954             }  else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00955                /* It's not a valid extension, give a busy signal */
00956                ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context);
00957                ioctl(i->fd, PHONE_BUSY);
00958                i->cpt = 1;
00959             }
00960          }
00961 #if 0
00962          ast_verbose("Extension is %s\n", i->ext);
00963 #endif
00964       }
00965    }
00966    if (phonee.bits.hookstate) {
00967       offhook = ioctl(i->fd, PHONE_HOOKSTATE);
00968       if (offhook) {
00969          if (i->mode == MODE_IMMEDIATE) {
00970             phone_new(i, AST_STATE_RING, i->context, NULL);
00971          } else if (i->mode == MODE_DIALTONE) {
00972             ast_module_ref(ast_module_info->self);
00973             /* Reset the extension */
00974             i->ext[0] = '\0';
00975             /* Play the dialtone */
00976             i->dialtone++;
00977             ioctl(i->fd, PHONE_PLAY_STOP);
00978             ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
00979             ioctl(i->fd, PHONE_PLAY_START);
00980             ast_format_clear(&i->lastformat);
00981          } else if (i->mode == MODE_SIGMA) {
00982             ast_module_ref(ast_module_info->self);
00983             /* Reset the extension */
00984             i->ext[0] = '\0';
00985             /* Play the dialtone */
00986             i->dialtone++;
00987             ioctl(i->fd, PHONE_DIALTONE);
00988          }
00989       } else {
00990          if (i->dialtone)
00991             ast_module_unref(ast_module_info->self);
00992          memset(i->ext, 0, sizeof(i->ext));
00993          if (i->cpt)
00994          {
00995             ioctl(i->fd, PHONE_CPT_STOP);
00996             i->cpt = 0;
00997          }
00998          ioctl(i->fd, PHONE_PLAY_STOP);
00999          ioctl(i->fd, PHONE_REC_STOP);
01000          i->dialtone = 0;
01001          ast_format_clear(&i->lastformat);
01002       }
01003    }
01004    if (phonee.bits.pstn_ring) {
01005       ast_verbose("Unit is ringing\n");
01006       phone_new(i, AST_STATE_RING, i->context, NULL);
01007    }
01008    if (phonee.bits.caller_id)
01009       ast_verbose("We have caller ID\n");
01010    
01011    
01012 }

static int phone_digit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 239 of file chan_phone.c.

00240 {
00241    /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */
00242    return 0;
00243 }

static int phone_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 245 of file chan_phone.c.

References ast_debug, ast_format_clear(), ast_log(), phone_pvt::fd, phone_pvt::lastformat, LOG_WARNING, and ast_channel::tech_pvt.

Referenced by phone_call().

00246 {
00247    struct phone_pvt *p;
00248    int outdigit;
00249    p = ast->tech_pvt;
00250    ast_debug(1, "Dialed %c\n", digit);
00251    switch(digit) {
00252    case '0':
00253    case '1':
00254    case '2':
00255    case '3':
00256    case '4':
00257    case '5':
00258    case '6':
00259    case '7':
00260    case '8':
00261    case '9':
00262       outdigit = digit - '0';
00263       break;
00264    case '*':
00265       outdigit = 11;
00266       break;
00267    case '#':
00268       outdigit = 12;
00269       break;
00270    case 'f':   /*flash*/
00271    case 'F':
00272       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00273       usleep(320000);
00274       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00275       ast_format_clear(&p->lastformat);
00276       return 0;
00277    default:
00278       ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
00279       return -1;
00280    }
00281    ast_debug(1, "Dialed %d\n", outdigit);
00282    ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
00283    ast_format_clear(&p->lastformat);
00284    return 0;
00285 }

static struct ast_frame * phone_exception ( struct ast_channel ast  )  [static, read]

Definition at line 488 of file chan_phone.c.

References ast_channel::_state, AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, ast_log(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose, ast_frame::data, ast_frame::datalen, ast_frame::delivery, phone_pvt::fd, phone_pvt::fr, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::mallocd, phone_pvt::mode, MODE_FXO, ast_frame::offset, phone_setup(), ast_frame::ptr, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_channel::tech_pvt.

00489 {
00490    int res;
00491    union telephony_exception phonee;
00492    struct phone_pvt *p = ast->tech_pvt;
00493    char digit;
00494 
00495    /* Some nice norms */
00496    p->fr.datalen = 0;
00497    p->fr.samples = 0;
00498    p->fr.data.ptr =  NULL;
00499    p->fr.src = "Phone";
00500    p->fr.offset = 0;
00501    p->fr.mallocd=0;
00502    p->fr.delivery = ast_tv(0,0);
00503    
00504    phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
00505    if (phonee.bits.dtmf_ready)  {
00506       ast_debug(1, "phone_exception(): DTMF\n");
00507    
00508       /* We've got a digit -- Just handle this nicely and easily */
00509       digit =  ioctl(p->fd, PHONE_GET_DTMF_ASCII);
00510       p->fr.subclass.integer = digit;
00511       p->fr.frametype = AST_FRAME_DTMF;
00512       return &p->fr;
00513    }
00514    if (phonee.bits.hookstate) {
00515       ast_debug(1, "Hookstate changed\n");
00516       res = ioctl(p->fd, PHONE_HOOKSTATE);
00517       /* See if we've gone on hook, if so, notify by returning NULL */
00518       ast_debug(1, "New hookstate: %d\n", res);
00519       if (!res && (p->mode != MODE_FXO))
00520          return NULL;
00521       else {
00522          if (ast->_state == AST_STATE_RINGING) {
00523             /* They've picked up the phone */
00524             p->fr.frametype = AST_FRAME_CONTROL;
00525             p->fr.subclass.integer = AST_CONTROL_ANSWER;
00526             phone_setup(ast);
00527             ast_setstate(ast, AST_STATE_UP);
00528             return &p->fr;
00529          }  else 
00530             ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state);
00531       }
00532    }
00533 #if 1
00534    if (phonee.bits.pstn_ring)
00535       ast_verbose("Unit is ringing\n");
00536    if (phonee.bits.caller_id) {
00537       ast_verbose("We have caller ID\n");
00538    }
00539    if (phonee.bits.pstn_wink)
00540       ast_verbose("Detected Wink\n");
00541 #endif
00542    /* Strange -- nothing there.. */
00543    p->fr.frametype = AST_FRAME_NULL;
00544    p->fr.subclass.integer = 0;
00545    return &p->fr;
00546 }

static int phone_fixup ( struct ast_channel old,
struct ast_channel new 
) [static]

Definition at line 231 of file chan_phone.c.

References phone_pvt::owner, and ast_channel::tech_pvt.

00232 {
00233    struct phone_pvt *pvt = old->tech_pvt;
00234    if (pvt && pvt->owner == old)
00235       pvt->owner = new;
00236    return 0;
00237 }

static int phone_hangup ( struct ast_channel ast  )  [static]

Definition at line 342 of file chan_phone.c.

References ast_channel_name(), ast_debug, ast_format_clear(), ast_log(), ast_module_unref(), ast_setstate(), AST_STATE_DOWN, ast_verb, phone_pvt::cpt, phone_pvt::dialtone, errno, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, phone_pvt::obuflen, phone_pvt::owner, restart_monitor(), and ast_channel::tech_pvt.

00343 {
00344    struct phone_pvt *p;
00345    p = ast->tech_pvt;
00346    ast_debug(1, "phone_hangup(%s)\n", ast_channel_name(ast));
00347    if (!ast->tech_pvt) {
00348       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00349       return 0;
00350    }
00351    /* XXX Is there anything we can do to really hang up except stop recording? */
00352    ast_setstate(ast, AST_STATE_DOWN);
00353    if (ioctl(p->fd, PHONE_REC_STOP))
00354       ast_log(LOG_WARNING, "Failed to stop recording\n");
00355    if (ioctl(p->fd, PHONE_PLAY_STOP))
00356       ast_log(LOG_WARNING, "Failed to stop playing\n");
00357    if (ioctl(p->fd, PHONE_RING_STOP))
00358       ast_log(LOG_WARNING, "Failed to stop ringing\n");
00359    if (ioctl(p->fd, PHONE_CPT_STOP))
00360       ast_log(LOG_WARNING, "Failed to stop sounds\n");
00361 
00362    /* If it's an FXO, hang them up */
00363    if (p->mode == MODE_FXO) {
00364       if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
00365          ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast_channel_name(ast), strerror(errno));
00366    }
00367 
00368    /* If they're off hook, give a busy signal */
00369    if (ioctl(p->fd, PHONE_HOOKSTATE)) {
00370       ast_debug(1, "Got hunghup, giving busy signal\n");
00371       ioctl(p->fd, PHONE_BUSY);
00372       p->cpt = 1;
00373    }
00374    ast_format_clear(&p->lastformat);
00375    ast_format_clear(&p->lastinput);
00376    p->ministate = 0;
00377    p->obuflen = 0;
00378    p->dialtone = 0;
00379    memset(p->ext, 0, sizeof(p->ext));
00380    ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
00381    ast_module_unref(ast_module_info->self);
00382    ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
00383    ast->tech_pvt = NULL;
00384    ast_setstate(ast, AST_STATE_DOWN);
00385    restart_monitor();
00386    return 0;
00387 }

static int phone_indicate ( struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 203 of file chan_phone.c.

References ast_channel_name(), AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_format_clear(), ast_log(), ast_moh_start(), ast_moh_stop(), phone_pvt::fd, phone_pvt::lastformat, LOG_WARNING, and ast_channel::tech_pvt.

00204 {
00205    struct phone_pvt *p = chan->tech_pvt;
00206    int res=-1;
00207    ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
00208    switch(condition) {
00209    case AST_CONTROL_FLASH:
00210       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00211       usleep(320000);
00212       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00213       ast_format_clear(&p->lastformat);
00214       res = 0;
00215       break;
00216    case AST_CONTROL_HOLD:
00217       ast_moh_start(chan, data, NULL);
00218       break;
00219    case AST_CONTROL_UNHOLD:
00220       ast_moh_stop(chan);
00221       break;
00222    case AST_CONTROL_SRCUPDATE:
00223       res = 0;
00224       break;
00225    default:
00226       ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, ast_channel_name(chan));
00227    }
00228    return res;
00229 }

static void phone_mini_packet ( struct phone_pvt i  )  [static]

Definition at line 909 of file chan_phone.c.

References ast_log(), errno, phone_pvt::fd, and LOG_WARNING.

Referenced by do_monitor().

00910 {
00911    int res;
00912    char buf[1024];
00913    /* Ignore stuff we read... */
00914    res = read(i->fd, buf, sizeof(buf));
00915    if (res < 1) {
00916       ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
00917       return;
00918    }
00919 }

static struct ast_channel* phone_new ( struct phone_pvt i,
int  state,
char *  cntx,
const char *  linkedid 
) [static, read]

Definition at line 848 of file chan_phone.c.

References ast_best_codec(), ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_copy_string(), ast_format_cap_add(), ast_format_cap_copy(), ast_format_cap_remove(), ast_format_copy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, LOG_WARNING, phone_pvt::mode, MODE_FXS, and phone_pvt::owner.

Referenced by phone_check_exception(), and phone_request().

00849 {
00850    struct ast_channel *tmp;
00851    struct phone_codec_data queried_codec;
00852    struct ast_format tmpfmt;
00853    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5);
00854    if (tmp) {
00855       tmp->tech = cur_tech;
00856       ast_channel_set_fd(tmp, 0, i->fd);
00857       /* XXX Switching formats silently causes kernel panics XXX */
00858       if (i->mode == MODE_FXS &&
00859           ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) {
00860          if (queried_codec.type == LINEAR16) {
00861             ast_format_cap_add(tmp->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
00862             ast_format_copy(&tmp->rawreadformat, &tmpfmt);
00863             ast_format_copy(&tmp->rawwriteformat, &tmpfmt);
00864          } else {
00865             ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
00866          }
00867       } else {
00868          ast_format_cap_copy(tmp->nativeformats, prefcap);
00869          ast_best_codec(tmp->nativeformats, &tmpfmt);
00870          ast_format_copy(&tmp->rawreadformat, &tmpfmt);
00871          ast_format_copy(&tmp->rawwriteformat, &tmpfmt);
00872       }
00873       /* no need to call ast_setstate: the channel_alloc already did its job */
00874       if (state == AST_STATE_RING)
00875          tmp->rings = 1;
00876       tmp->tech_pvt = i;
00877       ast_copy_string(tmp->context, cntx, sizeof(tmp->context));
00878       if (!ast_strlen_zero(i->ext))
00879          ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
00880       else
00881          strcpy(tmp->exten, "s");
00882       if (!ast_strlen_zero(i->language))
00883          ast_channel_language_set(tmp, i->language);
00884 
00885       /* Don't use ast_set_callerid() here because it will
00886        * generate a NewCallerID event before the NewChannel event */
00887       if (!ast_strlen_zero(i->cid_num)) {
00888          tmp->caller.ani.number.valid = 1;
00889          tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00890       }
00891 
00892       i->owner = tmp;
00893       ast_module_ref(ast_module_info->self);
00894       if (state != AST_STATE_DOWN) {
00895          if (state == AST_STATE_RING) {
00896             ioctl(tmp->fds[0], PHONE_RINGBACK);
00897             i->cpt = 1;
00898          }
00899          if (ast_pbx_start(tmp)) {
00900             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
00901             ast_hangup(tmp);
00902          }
00903       }
00904    } else
00905       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00906    return tmp;
00907 }

static struct ast_frame * phone_read ( struct ast_channel ast  )  [static, read]

Definition at line 548 of file chan_phone.c.

References ast_clear_flag, AST_FLAG_BLOCKING, ast_format_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_SLINEAR, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_IMAGE, ast_frame_byteswap_le, AST_FRAME_IMAGE, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_tv(), phone_pvt::buf, CHECK_BLOCKING, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, phone_pvt::fd, ast_frame_subclass::format, phone_pvt::fr, ast_frame::frametype, ast_format::id, phone_pvt::lastinput, LOG_WARNING, ast_frame::mallocd, phone_pvt::mode, MODE_FXS, ast_frame::offset, PHONE_MAX_BUF, ast_frame::ptr, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_channel::tech_pvt.

00549 {
00550    int res;
00551    struct phone_pvt *p = ast->tech_pvt;
00552    
00553 
00554    /* Some nice norms */
00555    p->fr.datalen = 0;
00556    p->fr.samples = 0;
00557    p->fr.data.ptr =  NULL;
00558    p->fr.src = "Phone";
00559    p->fr.offset = 0;
00560    p->fr.mallocd=0;
00561    p->fr.delivery = ast_tv(0,0);
00562 
00563    /* Try to read some data... */
00564    CHECK_BLOCKING(ast);
00565    res = read(p->fd, p->buf, PHONE_MAX_BUF);
00566    ast_clear_flag(ast, AST_FLAG_BLOCKING);
00567    if (res < 0) {
00568 #if 0
00569       if (errno == EAGAIN) {
00570          ast_log(LOG_WARNING, "Null frame received\n");
00571          p->fr.frametype = AST_FRAME_NULL;
00572          p->fr.subclass = 0;
00573          return &p->fr;
00574       }
00575 #endif
00576       ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));
00577       return NULL;
00578    }
00579    p->fr.data.ptr = p->buf;
00580    if (p->mode != MODE_FXS)
00581    switch(p->buf[0] & 0x3) {
00582    case '0':
00583    case '1':
00584       /* Normal */
00585       break;
00586    case '2':
00587    case '3':
00588       /* VAD/CNG, only send two words */
00589       res = 4;
00590       break;
00591    }
00592    p->fr.samples = 240;
00593    p->fr.datalen = res;
00594    p->fr.frametype = AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_AUDIO ?
00595       AST_FRAME_VOICE : AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_IMAGE ?
00596       AST_FRAME_IMAGE : AST_FRAME_VIDEO;
00597    ast_format_copy(&p->fr.subclass.format, &p->lastinput);
00598    p->fr.offset = AST_FRIENDLY_OFFSET;
00599    /* Byteswap from little-endian to native-endian */
00600    if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR)
00601       ast_frame_byteswap_le(&p->fr);
00602    return &p->fr;
00603 }

static struct ast_channel * phone_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  data,
int *  cause 
) [static, read]

Definition at line 1234 of file chan_phone.c.

References AST_CAUSE_BUSY, ast_channel_linkedid(), ast_format_cap_has_joint(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, ast_channel_tech::capabilities, phone_pvt::context, phone_pvt::dev, iflist, iflock, LOG_ERROR, LOG_NOTICE, phone_pvt::mode, MODE_FXS, name, phone_pvt::next, phone_pvt::owner, phone_new(), and restart_monitor().

01235 {
01236    struct phone_pvt *p;
01237    struct ast_channel *tmp = NULL;
01238    const char *name = data;
01239 
01240    /* Search for an unowned channel */
01241    if (ast_mutex_lock(&iflock)) {
01242       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01243       return NULL;
01244    }
01245    p = iflist;
01246    while(p) {
01247       if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
01248          size_t length = strlen(p->dev + 5);
01249          if (strncmp(name, p->dev + 5, length) == 0 &&
01250              !isalnum(name[length])) {
01251              if (!p->owner) {
01252                      tmp = phone_new(p, AST_STATE_DOWN, p->context, requestor ? ast_channel_linkedid(requestor) : NULL);
01253                      break;
01254                 } else
01255                      *cause = AST_CAUSE_BUSY;
01256             }
01257       }
01258       p = p->next;
01259    }
01260    ast_mutex_unlock(&iflock);
01261    restart_monitor();
01262    if (tmp == NULL) {
01263       if (!(ast_format_cap_has_joint(cap, phone_tech.capabilities))) {
01264          char buf[256];
01265          ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
01266          return NULL;
01267       }
01268    }
01269    return tmp;
01270 }

static int phone_send_text ( struct ast_channel ast,
const char *  text 
) [static]

Definition at line 639 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

00640 {
00641     int length = strlen(text);
00642     return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 
00643            length ? 0 : -1;
00644 }

static int phone_setup ( struct ast_channel ast  )  [static]

Definition at line 389 of file chan_phone.c.

References ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_getformatname(), ast_log(), phone_pvt::fd, ast_format::id, phone_pvt::lastinput, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_channel::rawreadformat, and ast_channel::tech_pvt.

Referenced by phone_answer(), phone_exception(), and phone_write().

00390 {
00391    struct phone_pvt *p;
00392    p = ast->tech_pvt;
00393    ioctl(p->fd, PHONE_CPT_STOP);
00394    /* Nothing to answering really, just start recording */
00395    if (ast->rawreadformat.id == AST_FORMAT_G729A) {
00396       /* Prefer g729 */
00397       ioctl(p->fd, PHONE_REC_STOP);
00398       if (p->lastinput.id != AST_FORMAT_G729A) {
00399          ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
00400          if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
00401             ast_log(LOG_WARNING, "Failed to set codec to g729\n");
00402             return -1;
00403          }
00404       }
00405         } else if (ast->rawreadformat.id == AST_FORMAT_G723_1) {
00406       ioctl(p->fd, PHONE_REC_STOP);
00407       if (p->lastinput.id != AST_FORMAT_G723_1) {
00408          ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
00409          if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00410             ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
00411             return -1;
00412          }
00413       }
00414    } else if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) {
00415       ioctl(p->fd, PHONE_REC_STOP);
00416       if (p->lastinput.id != AST_FORMAT_SLINEAR) {
00417          ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
00418          if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00419             ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
00420             return -1;
00421          }
00422       }
00423    } else if (ast->rawreadformat.id == AST_FORMAT_ULAW) {
00424       ioctl(p->fd, PHONE_REC_STOP);
00425       if (p->lastinput.id != AST_FORMAT_ULAW) {
00426          ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
00427          if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00428             ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
00429             return -1;
00430          }
00431       }
00432    } else if (p->mode == MODE_FXS) {
00433       ioctl(p->fd, PHONE_REC_STOP);
00434       if (ast_format_cmp(&p->lastinput, &ast->rawreadformat) == AST_FORMAT_CMP_NOT_EQUAL) {
00435          ast_format_copy(&p->lastinput, &ast->rawreadformat);
00436          if (ioctl(p->fd, PHONE_REC_CODEC, &ast->rawreadformat)) {
00437             ast_log(LOG_WARNING, "Failed to set codec to %s\n", 
00438                ast_getformatname(&ast->rawreadformat));
00439             return -1;
00440          }
00441       }
00442    } else {
00443       ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(&ast->rawreadformat));
00444       return -1;
00445    }
00446    if (ioctl(p->fd, PHONE_REC_START)) {
00447       ast_log(LOG_WARNING, "Failed to start recording\n");
00448       return -1;
00449    }
00450    /* set the DTMF times (the default is too short) */
00451    ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300);
00452    ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200);
00453    return 0;
00454 }

static int phone_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 646 of file chan_phone.c.

References ast_channel::_state, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_copy(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_setstate(), AST_STATE_UP, ast_frame::data, ast_frame::datalen, errno, phone_pvt::fd, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::mode, MODE_FXS, phone_pvt::obuflen, phone_setup(), phone_write_buf(), ast_frame::ptr, phone_pvt::silencesupression, ast_frame::subclass, and ast_channel::tech_pvt.

00647 {
00648    struct phone_pvt *p = ast->tech_pvt;
00649    int res;
00650    int maxfr=0;
00651    char *pos;
00652    int sofar;
00653    int expected;
00654    int codecset = 0;
00655    char tmpbuf[4];
00656    /* Write a frame of (presumably voice) data */
00657    if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {
00658       if (frame->frametype != AST_FRAME_IMAGE)
00659          ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
00660       return 0;
00661    }
00662    if (!(frame->subclass.format.id == AST_FORMAT_G723_1 ||
00663       frame->subclass.format.id == AST_FORMAT_SLINEAR ||
00664       frame->subclass.format.id == AST_FORMAT_ULAW ||
00665       frame->subclass.format.id == AST_FORMAT_G729A) &&
00666        p->mode != MODE_FXS) {
00667       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
00668       return -1;
00669    }
00670 #if 0
00671    /* If we're not in up mode, go into up mode now */
00672    if (ast->_state != AST_STATE_UP) {
00673       ast_setstate(ast, AST_STATE_UP);
00674       phone_setup(ast);
00675    }
00676 #else
00677    if (ast->_state != AST_STATE_UP) {
00678       /* Don't try tos end audio on-hook */
00679       return 0;
00680    }
00681 #endif   
00682    if (frame->subclass.format.id == AST_FORMAT_G729A) {
00683       if (p->lastformat.id != AST_FORMAT_G729A) {
00684          ioctl(p->fd, PHONE_PLAY_STOP);
00685          ioctl(p->fd, PHONE_REC_STOP);
00686          if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
00687             ast_log(LOG_WARNING, "Unable to set G729 mode\n");
00688             return -1;
00689          }
00690          if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
00691             ast_log(LOG_WARNING, "Unable to set G729 mode\n");
00692             return -1;
00693          }
00694          ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0);
00695          ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0);
00696          /* Reset output buffer */
00697          p->obuflen = 0;
00698          codecset = 1;
00699       }
00700       if (frame->datalen > 80) {
00701          ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen);
00702          return -1;
00703       }
00704       maxfr = 80;
00705         } else if (frame->subclass.format.id == AST_FORMAT_G723_1) {
00706       if (p->lastformat.id != AST_FORMAT_G723_1) {
00707          ioctl(p->fd, PHONE_PLAY_STOP);
00708          ioctl(p->fd, PHONE_REC_STOP);
00709          if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
00710             ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00711             return -1;
00712          }
00713          if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00714             ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00715             return -1;
00716          }
00717          ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0);
00718          ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0);
00719          /* Reset output buffer */
00720          p->obuflen = 0;
00721          codecset = 1;
00722       }
00723       if (frame->datalen > 24) {
00724          ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
00725          return -1;
00726       }
00727       maxfr = 24;
00728    } else if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
00729       if (p->lastformat.id != AST_FORMAT_SLINEAR) {
00730          ioctl(p->fd, PHONE_PLAY_STOP);
00731          ioctl(p->fd, PHONE_REC_STOP);
00732          if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
00733             ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00734             return -1;
00735          }
00736          if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00737             ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00738             return -1;
00739          }
00740          ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0);
00741          ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0);
00742          codecset = 1;
00743          /* Reset output buffer */
00744          p->obuflen = 0;
00745       }
00746       maxfr = 480;
00747    } else if (frame->subclass.format.id == AST_FORMAT_ULAW) {
00748       if (p->lastformat.id != AST_FORMAT_ULAW) {
00749          ioctl(p->fd, PHONE_PLAY_STOP);
00750          ioctl(p->fd, PHONE_REC_STOP);
00751          if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
00752             ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00753             return -1;
00754          }
00755          if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00756             ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00757             return -1;
00758          }
00759          ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0);
00760          ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0);
00761          codecset = 1;
00762          /* Reset output buffer */
00763          p->obuflen = 0;
00764       }
00765       maxfr = 240;
00766    } else {
00767       if (ast_format_cmp(&p->lastformat, &frame->subclass.format) != AST_FORMAT_CMP_EQUAL) {
00768          ioctl(p->fd, PHONE_PLAY_STOP);
00769          ioctl(p->fd, PHONE_REC_STOP);
00770          if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.format.id)) {
00771             ast_log(LOG_WARNING, "Unable to set %s mode\n",
00772                ast_getformatname(&frame->subclass.format));
00773             return -1;
00774          }
00775          if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) {
00776             ast_log(LOG_WARNING, "Unable to set %s mode\n",
00777                ast_getformatname(&frame->subclass.format));
00778             return -1;
00779          }
00780          ast_format_copy(&p->lastformat, &frame->subclass.format);
00781          ast_format_copy(&p->lastinput, &frame->subclass.format);
00782          codecset = 1;
00783          /* Reset output buffer */
00784          p->obuflen = 0;
00785       }
00786       maxfr = 480;
00787    }
00788    if (codecset) {
00789       ioctl(p->fd, PHONE_REC_DEPTH, 3);
00790       ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
00791       if (ioctl(p->fd, PHONE_PLAY_START)) {
00792          ast_log(LOG_WARNING, "Failed to start playback\n");
00793          return -1;
00794       }
00795       if (ioctl(p->fd, PHONE_REC_START)) {
00796          ast_log(LOG_WARNING, "Failed to start recording\n");
00797          return -1;
00798       }
00799    }
00800    /* If we get here, we have a frame of Appropriate data */
00801    sofar = 0;
00802    pos = frame->data.ptr;
00803    while(sofar < frame->datalen) {
00804       /* Write in no more than maxfr sized frames */
00805       expected = frame->datalen - sofar;
00806       if (maxfr < expected)
00807          expected = maxfr;
00808       /* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX 
00809          we have to pad it to 24 bytes still.  */
00810       if (frame->datalen == 4) {
00811          if (p->silencesupression) {
00812             memcpy(tmpbuf, frame->data.ptr, 4);
00813             expected = 24;
00814             res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
00815          }
00816          res = 4;
00817          expected=4;
00818       } else {
00819          int swap = 0;
00820 #if __BYTE_ORDER == __BIG_ENDIAN
00821          if (frame->subclass.format.id == AST_FORMAT_SLINEAR)
00822             swap = 1; /* Swap big-endian samples to little-endian as we copy */
00823 #endif
00824          res = phone_write_buf(p, pos, expected, maxfr, swap);
00825       }
00826       if (res != expected) {
00827          if ((errno != EAGAIN) && (errno != EINTR)) {
00828             if (res < 0) 
00829                ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
00830    /*
00831     * Card is in non-blocking mode now and it works well now, but there are
00832     * lot of messages like this. So, this message is temporarily disabled.
00833     */
00834 #if 0
00835             else
00836                ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
00837 #endif
00838             return -1;
00839          } else /* Pretend it worked */
00840             res = expected;
00841       }
00842       sofar += res;
00843       pos += res;
00844    }
00845    return 0;
00846 }

static int phone_write_buf ( struct phone_pvt p,
const char *  buf,
int  len,
int  frlen,
int  swap 
) [static]

Definition at line 605 of file chan_phone.c.

References ast_log(), ast_swapcopy_samples(), phone_pvt::fd, LOG_WARNING, phone_pvt::obuf, and phone_pvt::obuflen.

Referenced by phone_send_text(), and phone_write().

00606 {
00607    int res;
00608    /* Store as much of the buffer as we can, then write fixed frames */
00609    int space = sizeof(p->obuf) - p->obuflen;
00610    /* Make sure we have enough buffer space to store the frame */
00611    if (space < len)
00612       len = space;
00613    if (swap)
00614       ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2);
00615    else
00616       memcpy(p->obuf + p->obuflen, buf, len);
00617    p->obuflen += len;
00618    while(p->obuflen > frlen) {
00619       res = write(p->fd, p->obuf, frlen);
00620       if (res != frlen) {
00621          if (res < 1) {
00622 /*
00623  * Card is in non-blocking mode now and it works well now, but there are
00624  * lot of messages like this. So, this message is temporarily disabled.
00625  */
00626             return 0;
00627          } else {
00628             ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);
00629          }
00630       }
00631       p->obuflen -= frlen;
00632       /* Move memory if necessary */
00633       if (p->obuflen) 
00634          memmove(p->obuf, p->obuf + frlen, p->obuflen);
00635    }
00636    return len;
00637 }

static int restart_monitor ( void   )  [static]

Definition at line 1136 of file chan_phone.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), iflock, LOG_ERROR, LOG_WARNING, and monlock.

01137 {
01138    /* If we're supposed to be stopped -- stay stopped */
01139    if (monitor_thread == AST_PTHREADT_STOP)
01140       return 0;
01141    if (ast_mutex_lock(&monlock)) {
01142       ast_log(LOG_WARNING, "Unable to lock monitor\n");
01143       return -1;
01144    }
01145    if (monitor_thread == pthread_self()) {
01146       ast_mutex_unlock(&monlock);
01147       ast_log(LOG_WARNING, "Cannot kill myself\n");
01148       return -1;
01149    }
01150    if (monitor_thread != AST_PTHREADT_NULL) {
01151       if (ast_mutex_lock(&iflock)) {
01152          ast_mutex_unlock(&monlock);
01153          ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01154          return -1;
01155       }
01156       monitor = 0;
01157       while (pthread_kill(monitor_thread, SIGURG) == 0)
01158          sched_yield();
01159       pthread_join(monitor_thread, NULL);
01160       ast_mutex_unlock(&iflock);
01161    }
01162    monitor = 1;
01163    /* Start a new monitor */
01164    if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01165       ast_mutex_unlock(&monlock);
01166       ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01167       return -1;
01168    }
01169    ast_mutex_unlock(&monlock);
01170    return 0;
01171 }

static int unload_module ( void   )  [static]

Definition at line 1354 of file chan_phone.c.

References __unload_module().

01355 {
01356    return __unload_module();
01357 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Linux Telephony API Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 1496 of file chan_phone.c.

Definition at line 1496 of file chan_phone.c.

char cid_name[AST_MAX_EXTENSION] [static]

Definition at line 152 of file chan_phone.c.

char cid_num[AST_MAX_EXTENSION] [static]

Definition at line 151 of file chan_phone.c.

const char config[] = "phone.conf" [static]

Definition at line 86 of file chan_phone.c.

char context[AST_MAX_EXTENSION] = "default" [static]

Definition at line 89 of file chan_phone.c.

struct ast_channel_tech* cur_tech [static]

Definition at line 201 of file chan_phone.c.

int echocancel = AEC_OFF [static]

Definition at line 94 of file chan_phone.c.

struct phone_pvt * iflist [static]

ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 101 of file chan_phone.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 92 of file chan_phone.c.

unsigned int monitor [static]

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 112 of file chan_phone.c.

ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 105 of file chan_phone.c.

struct ast_channel_tech phone_tech [static]

Definition at line 167 of file chan_phone.c.

Definition at line 183 of file chan_phone.c.

struct ast_format_cap* prefcap [static]

Definition at line 98 of file chan_phone.c.

int silencesupression = 0 [static]

Definition at line 96 of file chan_phone.c.

const char tdesc[] = "Standard Linux Telephony API Driver" [static]

Definition at line 85 of file chan_phone.c.


Generated on Sat Feb 11 06:34:42 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6