Fri Jun 19 12:10:18 2009

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)
static struct ast_framephone_read (struct ast_channel *ast)
static struct ast_channelphone_request (const char *type, int format, 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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char language [MAX_LANGUAGE] = ""
static unsigned int monitor
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct ast_channel_tech phone_tech
static struct ast_channel_tech phone_tech_fxs
static int 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 1453 of file chan_phone.c.

static int __unload_module ( void   )  [static]

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

01280 {
01281    struct phone_pvt *p, *pl;
01282    /* First, take us out of the channel loop */
01283    if (cur_tech)
01284       ast_channel_unregister(cur_tech);
01285    if (!ast_mutex_lock(&iflock)) {
01286       /* Hangup all interfaces if they have an owner */
01287       p = iflist;
01288       while(p) {
01289          if (p->owner)
01290             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01291          p = p->next;
01292       }
01293       iflist = NULL;
01294       ast_mutex_unlock(&iflock);
01295    } else {
01296       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01297       return -1;
01298    }
01299    if (!ast_mutex_lock(&monlock)) {
01300       if (monitor_thread > AST_PTHREADT_NULL) {
01301          monitor = 0;
01302          while (pthread_kill(monitor_thread, SIGURG) == 0)
01303             sched_yield();
01304          pthread_join(monitor_thread, NULL);
01305       }
01306       monitor_thread = AST_PTHREADT_STOP;
01307       ast_mutex_unlock(&monlock);
01308    } else {
01309       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01310       return -1;
01311    }
01312 
01313    if (!ast_mutex_lock(&iflock)) {
01314       /* Destroy all the interfaces and free their memory */
01315       p = iflist;
01316       while(p) {
01317          /* Close the socket, assuming it's real */
01318          if (p->fd > -1)
01319             close(p->fd);
01320          pl = p;
01321          p = p->next;
01322          /* Free associated memory */
01323          ast_free(pl);
01324       }
01325       iflist = NULL;
01326       ast_mutex_unlock(&iflock);
01327    } else {
01328       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01329       return -1;
01330    }
01331       
01332    return 0;
01333 }

static void __unreg_module ( void   )  [static]

Definition at line 1453 of file chan_phone.c.

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

Definition at line 1013 of file chan_phone.c.

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

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

static int load_module ( void   )  [static]

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

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

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

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

01155 {
01156    /* Make a phone_pvt structure for this interface */
01157    struct phone_pvt *tmp;
01158    int flags;  
01159    
01160    tmp = ast_calloc(1, sizeof(*tmp));
01161    if (tmp) {
01162       tmp->fd = open(iface, O_RDWR);
01163       if (tmp->fd < 0) {
01164          ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01165          ast_free(tmp);
01166          return NULL;
01167       }
01168       if (mode == MODE_FXO) {
01169          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
01170             ast_debug(1, "Unable to set port to PSTN\n");
01171          }
01172       } else {
01173          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 
01174              if (mode != MODE_FXS)
01175                   ast_debug(1, "Unable to set port to POTS\n");
01176       }
01177       ioctl(tmp->fd, PHONE_PLAY_STOP);
01178       ioctl(tmp->fd, PHONE_REC_STOP);
01179       ioctl(tmp->fd, PHONE_RING_STOP);
01180       ioctl(tmp->fd, PHONE_CPT_STOP);
01181       if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01182          ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01183       if (echocancel != AEC_OFF)
01184          ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01185       if (silencesupression) 
01186          tmp->silencesupression = 1;
01187 #ifdef PHONE_VAD
01188       ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01189 #endif
01190       tmp->mode = mode;
01191       flags = fcntl(tmp->fd, F_GETFL);
01192       fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01193       tmp->owner = NULL;
01194       tmp->lastformat = -1;
01195       tmp->lastinput = -1;
01196       tmp->ministate = 0;
01197       memset(tmp->ext, 0, sizeof(tmp->ext));
01198       ast_copy_string(tmp->language, language, sizeof(tmp->language));
01199       ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01200       ast_copy_string(tmp->context, context, sizeof(tmp->context));
01201       tmp->next = NULL;
01202       tmp->obuflen = 0;
01203       tmp->dialtone = 0;
01204       tmp->cpt = 0;
01205       ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01206       ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01207       tmp->txgain = txgain;
01208       ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01209       tmp->rxgain = rxgain;
01210       ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01211    }
01212    return tmp;
01213 }

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

Definition at line 1257 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

01258 {
01259    float gain;
01260 
01261    /* try to scan number */
01262    if (sscanf(value, "%f", &gain) != 1)
01263    {
01264       ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01265          value, gain_type, config);
01266       return DEFAULT_GAIN;
01267    }
01268 
01269    /* multiplicate gain by 1.0 gain value */ 
01270    gain = gain * (float)DEFAULT_GAIN;
01271 
01272    /* percentage? */
01273    if (value[strlen(value) - 1] == '%')
01274       return (int)(gain / (float)100);
01275 
01276    return (int)gain;
01277 }

static int phone_answer ( struct ast_channel ast  )  [static]

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

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

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::cid, ast_callerid::cid_name, ast_callerid::cid_num, DEFAULT_CALLER_ID, ast_channel::fds, IXJ_PHONE_RING_START, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_channel::name, phone_digit_end(), ast_channel::tech_pvt, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, and ast_tm::tm_mon.

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

static void phone_check_exception ( struct phone_pvt i  )  [static]

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

Referenced by do_monitor().

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

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 487 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, 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.

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

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

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

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(), chan, 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 908 of file chan_phone.c.

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

Referenced by do_monitor().

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

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

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

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

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

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

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

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

Definition at line 1215 of file chan_phone.c.

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

01216 {
01217    int oldformat;
01218    struct phone_pvt *p;
01219    struct ast_channel *tmp = NULL;
01220    char *name = data;
01221 
01222    /* Search for an unowned channel */
01223    if (ast_mutex_lock(&iflock)) {
01224       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01225       return NULL;
01226    }
01227    p = iflist;
01228    while(p) {
01229       if (p->mode == MODE_FXS ||
01230           format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01231           size_t length = strlen(p->dev + 5);
01232          if (strncmp(name, p->dev + 5, length) == 0 &&
01233              !isalnum(name[length])) {
01234              if (!p->owner) {
01235                      tmp = phone_new(p, AST_STATE_DOWN, p->context);
01236                      break;
01237                 } else
01238                      *cause = AST_CAUSE_BUSY;
01239             }
01240       }
01241       p = p->next;
01242    }
01243    ast_mutex_unlock(&iflock);
01244    restart_monitor();
01245    if (tmp == NULL) {
01246       oldformat = format;
01247       format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01248       if (!format) {
01249          ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01250          return NULL;
01251       }
01252    }
01253    return tmp;
01254 }

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

Definition at line 639 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

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

static int phone_setup ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 646 of file chan_phone.c.

References ast_channel::_state, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_setstate(), AST_STATE_UP, 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.

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

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

Definition at line 605 of file chan_phone.c.

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

Referenced by phone_send_text(), and phone_write().

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

static int restart_monitor ( void   )  [static]

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

01118 {
01119    /* If we're supposed to be stopped -- stay stopped */
01120    if (monitor_thread == AST_PTHREADT_STOP)
01121       return 0;
01122    if (ast_mutex_lock(&monlock)) {
01123       ast_log(LOG_WARNING, "Unable to lock monitor\n");
01124       return -1;
01125    }
01126    if (monitor_thread == pthread_self()) {
01127       ast_mutex_unlock(&monlock);
01128       ast_log(LOG_WARNING, "Cannot kill myself\n");
01129       return -1;
01130    }
01131    if (monitor_thread != AST_PTHREADT_NULL) {
01132       if (ast_mutex_lock(&iflock)) {
01133          ast_mutex_unlock(&monlock);
01134          ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01135          return -1;
01136       }
01137       monitor = 0;
01138       while (pthread_kill(monitor_thread, SIGURG) == 0)
01139          sched_yield();
01140       pthread_join(monitor_thread, NULL);
01141       ast_mutex_unlock(&iflock);
01142    }
01143    monitor = 1;
01144    /* Start a new monitor */
01145    if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01146       ast_mutex_unlock(&monlock);
01147       ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01148       return -1;
01149    }
01150    ast_mutex_unlock(&monlock);
01151    return 0;
01152 }

static int unload_module ( void   )  [static]

Definition at line 1335 of file chan_phone.c.

References __unload_module().

01336 {
01337    return __unload_module();
01338 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1453 of file chan_phone.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1453 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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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_monitor_start().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 111 of file chan_phone.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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().

int 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 Fri Jun 19 12:10:18 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7