Mon Jun 27 16:51:07 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 80 of file chan_phone.c.

Referenced by phone_call().

#define DEFAULT_GAIN   0x100

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

Referenced by phone_call().

#define MODE_DIALTONE   1

Definition at line 118 of file chan_phone.c.

Referenced by load_module(), and phone_check_exception().

#define MODE_FXO   3

Definition at line 120 of file chan_phone.c.

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

#define MODE_FXS   4

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

Referenced by load_module(), and phone_check_exception().

#define MODE_SIGMA   5

Definition at line 122 of file chan_phone.c.

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

#define PHONE_MAX_BUF   480

Definition at line 81 of file chan_phone.c.

Referenced by phone_read().

#define QNDRV_VER   100

Definition at line 67 of file chan_phone.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1480 of file chan_phone.c.

static int __unload_module ( void   )  [static]

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

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

static void __unreg_module ( void   )  [static]

Definition at line 1480 of file chan_phone.c.

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

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

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

static int load_module ( void   )  [static]

Definition at line 1364 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_flags, 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.

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

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

Definition at line 1177 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().

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

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

Definition at line 1281 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

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

static int phone_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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    if(&tm != NULL) {
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    }
00305    /* the standard format of ast->callerid is:  "name" <number>, but not always complete */
00306    if (!ast->connected.id.name.valid
00307       || ast_strlen_zero(ast->connected.id.name.str)) {
00308       strcpy(cid.name, DEFAULT_CALLER_ID);
00309    } else {
00310       ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name));
00311    }
00312 
00313    if (ast->connected.id.number.valid && ast->connected.id.number.str) {
00314       ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number));
00315    }
00316 
00317    p = ast->tech_pvt;
00318 
00319    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00320       ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
00321       return -1;
00322    }
00323    ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
00324 
00325    start = IXJ_PHONE_RING_START(cid);
00326    if (start == -1)
00327       return -1;
00328    
00329    if (p->mode == MODE_FXS) {
00330       char *digit = strchr(dest, '/');
00331       if (digit)
00332       {
00333         digit++;
00334         while (*digit)
00335           phone_digit_end(ast, *digit++, 0);
00336       }
00337    }
00338  
00339    ast_setstate(ast, AST_STATE_RINGING);
00340    ast_queue_control(ast, AST_CONTROL_RINGING);
00341    return 0;
00342 }

static void phone_check_exception ( struct phone_pvt i  )  [static]

Definition at line 925 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().

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

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_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       p->lastformat = -1;
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    p->lastformat = -1;
00284    return 0;
00285 }

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

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

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

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 344 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.

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

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_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.

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, chan->name);
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          p->lastformat = -1;
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, chan->name);
00227    }
00228    return res;
00229 }

static void phone_mini_packet ( struct phone_pvt i  )  [static]

Definition at line 913 of file chan_phone.c.

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

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

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

Definition at line 849 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().

00850 {
00851    struct ast_channel *tmp;
00852    struct phone_codec_data queried_codec;
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             tmp->nativeformats =
00862             tmp->rawreadformat =
00863             tmp->rawwriteformat =
00864             AST_FORMAT_SLINEAR;
00865          else {
00866             tmp->nativeformats =
00867             tmp->rawreadformat =
00868             tmp->rawwriteformat =
00869             prefformat & ~AST_FORMAT_SLINEAR;
00870          }
00871       }
00872       else {
00873          tmp->nativeformats = prefformat;
00874          tmp->rawreadformat = prefformat;
00875          tmp->rawwriteformat = prefformat;
00876       }
00877       /* no need to call ast_setstate: the channel_alloc already did its job */
00878       if (state == AST_STATE_RING)
00879          tmp->rings = 1;
00880       tmp->tech_pvt = i;
00881       ast_copy_string(tmp->context, cntx, sizeof(tmp->context));
00882       if (!ast_strlen_zero(i->ext))
00883          ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
00884       else
00885          strcpy(tmp->exten, "s");
00886       if (!ast_strlen_zero(i->language))
00887          ast_string_field_set(tmp, language, i->language);
00888 
00889       /* Don't use ast_set_callerid() here because it will
00890        * generate a NewCallerID event before the NewChannel event */
00891       if (!ast_strlen_zero(i->cid_num)) {
00892          tmp->caller.ani.number.valid = 1;
00893          tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00894       }
00895 
00896       i->owner = tmp;
00897       ast_module_ref(ast_module_info->self);
00898       if (state != AST_STATE_DOWN) {
00899          if (state == AST_STATE_RING) {
00900             ioctl(tmp->fds[0], PHONE_RINGBACK);
00901             i->cpt = 1;
00902          }
00903          if (ast_pbx_start(tmp)) {
00904             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00905             ast_hangup(tmp);
00906          }
00907       }
00908    } else
00909       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00910    return tmp;
00911 }

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

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

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

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 1238 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().

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

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

Definition at line 642 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

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

static int phone_setup ( struct ast_channel ast  )  [static]

Definition at line 391 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().

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

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

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

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

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

Definition at line 608 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().

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

static int restart_monitor ( void   )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 1359 of file chan_phone.c.

References __unload_module().

01360 {
01361    return __unload_module();
01362 }


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

Definition at line 1480 of file chan_phone.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1480 of file chan_phone.c.

char cid_name[AST_MAX_EXTENSION] [static]

Definition at line 151 of file chan_phone.c.

char cid_num[AST_MAX_EXTENSION] [static]

Definition at line 150 of file chan_phone.c.

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

Definition at line 85 of file chan_phone.c.

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

Definition at line 88 of file chan_phone.c.

struct ast_channel_tech* cur_tech [static]

Definition at line 201 of file chan_phone.c.

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

int echocancel = AEC_OFF [static]

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

char language[MAX_LANGUAGE] = "" [static]

Definition at line 91 of file chan_phone.c.

unsigned int monitor [static]

Definition at line 107 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_generic_check(), 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 111 of file chan_phone.c.

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

Definition at line 104 of file chan_phone.c.

struct ast_channel_tech phone_tech [static]

Definition at line 166 of file chan_phone.c.

Referenced by load_module().

struct ast_channel_tech phone_tech_fxs [static]

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

int silencesupression = 0 [static]

Definition at line 95 of file chan_phone.c.

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

Definition at line 84 of file chan_phone.c.


Generated on Mon Jun 27 16:51:07 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7