Wed Oct 28 11:51:58 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"

Include dependency graph for chan_phone.c:

Go to the source code of this file.

Data Structures

struct  phone_pvt

Defines

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

Functions

static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static void * do_monitor (void *data)
static int load_module (void)
static struct phone_pvtmkif (const char *iface, int mode, int txgain, int rxgain)
static int parse_gain_value (const char *gain_type, const char *value)
static int phone_answer (struct ast_channel *ast)
static int phone_call (struct ast_channel *ast, 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 = AST_BUILDOPT_SUM, .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_MUTEX_INITIALIZER )
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_MUTEX_INITIALIZER )
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

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

static int __unload_module ( void   )  [static]

Definition at line 1278 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, phone_pvt::fd, iflist, iflock, LOG_WARNING, monlock, phone_pvt::next, and phone_pvt::owner.

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

static void __unreg_module ( void   )  [static]

Definition at line 1452 of file chan_phone.c.

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

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

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

static int load_module ( void   )  [static]

Definition at line 1339 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, DEFAULT_GAIN, iflist, iflock, LOG_ERROR, LOG_WARNING, mkif(), phone_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, ast_variable::name, ast_variable::next, phone_pvt::next, parse_gain_value(), restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.

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

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

Definition at line 1153 of file chan_phone.c.

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

Referenced by load_module().

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

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

Definition at line 1256 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

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

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

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

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, read]

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

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

Referenced by do_monitor().

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

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

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

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

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

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, read]

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

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

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             memcpy(tmpbuf, frame->data.ptr, 4);
00811             expected = 24;
00812             res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
00813          }
00814          res = 4;
00815          expected=4;
00816       } else {
00817          int swap = 0;
00818 #if __BYTE_ORDER == __BIG_ENDIAN
00819          if (frame->subclass == AST_FORMAT_SLINEAR)
00820             swap = 1; /* Swap big-endian samples to little-endian as we copy */
00821 #endif
00822          res = phone_write_buf(p, pos, expected, maxfr, swap);
00823       }
00824       if (res != expected) {
00825          if ((errno != EAGAIN) && (errno != EINTR)) {
00826             if (res < 0) 
00827                ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
00828    /*
00829     * Card is in non-blocking mode now and it works well now, but there are
00830     * lot of messages like this. So, this message is temporarily disabled.
00831     */
00832 #if 0
00833             else
00834                ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
00835 #endif
00836             return -1;
00837          } else /* Pretend it worked */
00838             res = expected;
00839       }
00840       sofar += res;
00841       pos += res;
00842    }
00843    return 0;
00844 }

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

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

static int unload_module ( void   )  [static]

Definition at line 1334 of file chan_phone.c.

References __unload_module().

01335 {
01336    return __unload_module();
01337 }


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 1452 of file chan_phone.c.

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

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_MUTEX_INITIALIZER ) [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_MUTEX_INITIALIZER ) [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.

Definition at line 183 of file chan_phone.c.

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 Wed Oct 28 11:51:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6