Mon Oct 8 12:39:15 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"

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, 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, format_t format, const struct ast_channel *requestor, void *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 = "ac1f6a56484a8820659555499174e588" , .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_RECURSIVE_MUTEX_INITIALIZER_NP , 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_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static struct ast_channel_tech phone_tech
static struct ast_channel_tech phone_tech_fxs
static format_t prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW
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

Definition at line 122 of file chan_phone.c.

Referenced by load_module(), mkif(), phone_call(), phone_check_exception(), phone_new(), phone_read(), phone_request(), phone_setup(), and phone_write().

#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 1479 of file chan_phone.c.

static int __unload_module ( void   )  [static]

Definition at line 1302 of file chan_phone.c.

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

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

static void __unreg_module ( void   )  [static]

Definition at line 1479 of file chan_phone.c.

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

Definition at line 1017 of file chan_phone.c.

References ast_log(), ast_mutex_lock, ast_realloc, ast_tvzero(), DialTone, phone_pvt::dialtone, phone_pvt::fd, iflist, iflock, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, and phone_pvt::owner.

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

static int load_module ( void   )  [static]

Definition at line 1363 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_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, 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, cur_tech, 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(), phone_tech, phone_tech_fxs, restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.

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

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

Definition at line 1176 of file chan_phone.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), errno, LOG_WARNING, MODE_FXO, and MODE_FXS.

Referenced by load_module().

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

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

Definition at line 1280 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

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

static int phone_answer ( struct ast_channel ast  )  [static]

Definition at line 457 of file chan_phone.c.

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

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

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

Definition at line 288 of file chan_phone.c.

References ast_channel::_state, 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_channel::name, 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.

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

static void phone_check_exception ( struct phone_pvt i  )  [static]

Definition at line 924 of file chan_phone.c.

References ast_canmatch_extension(), ast_debug, ast_exists_extension(), 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().

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

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

Definition at line 240 of file chan_phone.c.

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

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

Definition at line 246 of file chan_phone.c.

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

Referenced by phone_call().

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

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

Definition at line 489 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.

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

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

Definition at line 232 of file chan_phone.c.

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

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

static int phone_hangup ( struct ast_channel ast  )  [static]

Definition at line 343 of file chan_phone.c.

References ast_debug, 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, ast_channel::name, phone_pvt::obuflen, phone_pvt::owner, restart_monitor(), and ast_channel::tech_pvt.

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

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

Definition at line 204 of file chan_phone.c.

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

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

static void phone_mini_packet ( struct phone_pvt i  )  [static]

Definition at line 912 of file chan_phone.c.

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

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

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

Definition at line 848 of file chan_phone.c.

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

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

Definition at line 549 of file chan_phone.c.

References ast_clear_flag, AST_FLAG_BLOCKING, AST_FORMAT_AUDIO_MASK, AST_FORMAT_PNG, AST_FORMAT_SLINEAR, 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_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, phone_pvt::fd, phone_pvt::fr, ast_frame::frametype, 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.

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

static struct ast_channel * phone_request ( const char *  type,
format_t  format,
const struct ast_channel requestor,
void *  data,
int *  cause 
) [static]

Definition at line 1237 of file chan_phone.c.

References AST_CAUSE_BUSY, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, phone_pvt::context, phone_pvt::dev, iflist, iflock, ast_channel::linkedid, LOG_ERROR, LOG_NOTICE, phone_pvt::mode, MODE_FXS, name, phone_pvt::next, phone_pvt::owner, phone_new(), and restart_monitor().

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

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

Definition at line 641 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

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

static int phone_setup ( struct ast_channel ast  )  [static]

Definition at line 390 of file chan_phone.c.

References AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_getformatname(), ast_log(), phone_pvt::fd, 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().

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

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

Definition at line 648 of file chan_phone.c.

References ast_channel::_state, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_setstate(), AST_STATE_UP, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, errno, phone_pvt::fd, ast_frame::frametype, 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.

00649 {
00650    struct phone_pvt *p = ast->tech_pvt;
00651    int res;
00652    int maxfr=0;
00653    char *pos;
00654    int sofar;
00655    int expected;
00656    int codecset = 0;
00657    char tmpbuf[4];
00658    /* Write a frame of (presumably voice) data */
00659    if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {
00660       if (frame->frametype != AST_FRAME_IMAGE)
00661          ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
00662       return 0;
00663    }
00664    if (!(frame->subclass.codec &
00665       (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && 
00666        p->mode != MODE_FXS) {
00667       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
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.codec == AST_FORMAT_G729A) {
00683       if (p->lastformat != 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          p->lastformat = AST_FORMAT_G729A;
00695          p->lastinput = AST_FORMAT_G729A;
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.codec == AST_FORMAT_G723_1) {
00706       if (p->lastformat != 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          p->lastformat = AST_FORMAT_G723_1;
00718          p->lastinput = AST_FORMAT_G723_1;
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.codec == AST_FORMAT_SLINEAR) {
00729       if (p->lastformat != 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          p->lastformat = AST_FORMAT_SLINEAR;
00741          p->lastinput = AST_FORMAT_SLINEAR;
00742          codecset = 1;
00743          /* Reset output buffer */
00744          p->obuflen = 0;
00745       }
00746       maxfr = 480;
00747    } else if (frame->subclass.codec == AST_FORMAT_ULAW) {
00748       if (p->lastformat != 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          p->lastformat = AST_FORMAT_ULAW;
00760          p->lastinput = AST_FORMAT_ULAW;
00761          codecset = 1;
00762          /* Reset output buffer */
00763          p->obuflen = 0;
00764       }
00765       maxfr = 240;
00766    } else {
00767       if (p->lastformat != frame->subclass.codec) {
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.codec)) {
00771             ast_log(LOG_WARNING, "Unable to set %s mode\n",
00772                ast_getformatname(frame->subclass.codec));
00773             return -1;
00774          }
00775          if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.codec)) {
00776             ast_log(LOG_WARNING, "Unable to set %s mode\n",
00777                ast_getformatname(frame->subclass.codec));
00778             return -1;
00779          }
00780          p->lastformat = frame->subclass.codec;
00781          p->lastinput = frame->subclass.codec;
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.codec == 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 607 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().

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

static int restart_monitor ( void   )  [static]

Definition at line 1139 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.

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

static int unload_module ( void   )  [static]

Definition at line 1358 of file chan_phone.c.

References __unload_module().

01359 {
01360    return __unload_module();
01361 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 1479 of file chan_phone.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1479 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 202 of file chan_phone.c.

Referenced by __unload_module(), load_module(), and phone_new().

int echocancel = AEC_OFF [static]

Definition at line 94 of file chan_phone.c.

struct phone_pvt * iflist [static]

ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , 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]

Definition at line 108 of file chan_phone.c.

Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_available_timer_expire(), ast_cc_call_init(), ast_cc_extension_monitor_add_dialstring(), ast_handle_cc_control_frame(), ast_monitor_start(), cc_cli_print_monitor_stats(), cc_device_monitor_init(), cc_extension_monitor_init(), cc_generic_monitor_cancel_available_timer(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), cc_monitor_destroy(), create_new_generic_list(), sig_pri_call(), sig_pri_cc_available(), sig_pri_cc_generic_check(), sig_pri_cc_link_canceled(), sig_pri_cc_monitor_req_cc(), sig_pri_cc_monitor_status_rsp(), sig_pri_cc_monitor_suspend(), sig_pri_cc_monitor_unsuspend(), sig_pri_handle_cis_subcmds(), sip_cc_monitor_cancel_available_timer(), sip_cc_monitor_request_cc(), sip_cc_monitor_suspend(), and sip_cc_monitor_unsuspend().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 112 of file chan_phone.c.

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , 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.

Referenced by load_module().

struct ast_channel_tech phone_tech_fxs [static]

Definition at line 184 of file chan_phone.c.

Referenced by load_module().

format_t prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW [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 Mon Oct 8 12:39:15 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7