Sat Mar 24 22:56:03 2007

Asterisk developer's documentation


chan_phone.c File Reference

Generic Linux Telephony Interface driver. More...

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/telephony.h>
#include <linux/version.h>
#include <linux/ixjuser.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "DialTone.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 PHONE_MAX_BUF   480
#define QNDRV_VER   100

Functions

static int __unload_module (void)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_MUTEX_DEFINE_STATIC (iflock)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
char * description ()
 Provides a description of the module.
static void * do_monitor (void *data)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module ()
 Initialize the module.
static struct phone_pvtmkif (char *iface, int mode, int txgain, int rxgain)
static int parse_gain_value (char *gain_type, 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 (struct ast_channel *ast, char digit)
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 void phone_mini_packet (struct phone_pvt *i)
static struct ast_channelphone_new (struct phone_pvt *i, int state, char *context)
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)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.

Variables

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 const char desc [] = "Linux Telephony API Support"
static int echocancel = AEC_OFF
static struct phone_pvtiflist
static char language [MAX_LANGUAGE] = ""
static pthread_t monitor_thread = AST_PTHREADT_NULL
static struct ast_channel_tech phone_tech
static struct ast_channel_tech phone_tech_fxs
static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW
static int silencesupression = 0
static const char tdesc [] = "Standard Linux Telephony API Driver"
static const char type [] = "Phone"
static int usecnt = 0


Detailed Description

Generic Linux Telephony Interface driver.

Definition in file chan_phone.c.


Define Documentation

#define DEFAULT_CALLER_ID   "Unknown"

Definition at line 74 of file chan_phone.c.

Referenced by phone_call().

#define DEFAULT_GAIN   0x100

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

Referenced by phone_call().

#define MODE_DIALTONE   1

Definition at line 114 of file chan_phone.c.

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

#define MODE_FXO   3

Definition at line 116 of file chan_phone.c.

Referenced by load_module(), mkif(), monitor_handle_notowned(), monitor_handle_owned(), phone_answer(), phone_exception(), phone_hangup(), vpb_answer(), vpb_hangup(), and vpb_new().

#define MODE_FXS   4

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

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

#define PHONE_MAX_BUF   480

Definition at line 75 of file chan_phone.c.

Referenced by phone_read().

#define QNDRV_VER   100

Definition at line 61 of file chan_phone.c.


Function Documentation

static int __unload_module ( void   )  [static]

Definition at line 1235 of file chan_phone.c.

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

01236 {
01237    struct phone_pvt *p, *pl;
01238    /* First, take us out of the channel loop */
01239    ast_channel_unregister(cur_tech);
01240    if (!ast_mutex_lock(&iflock)) {
01241       /* Hangup all interfaces if they have an owner */
01242       p = iflist;
01243       while(p) {
01244          if (p->owner)
01245             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01246          p = p->next;
01247       }
01248       iflist = NULL;
01249       ast_mutex_unlock(&iflock);
01250    } else {
01251       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01252       return -1;
01253    }
01254    if (!ast_mutex_lock(&monlock)) {
01255       if (monitor_thread > AST_PTHREADT_NULL) {
01256          pthread_cancel(monitor_thread);
01257          pthread_join(monitor_thread, NULL);
01258       }
01259       monitor_thread = AST_PTHREADT_STOP;
01260       ast_mutex_unlock(&monlock);
01261    } else {
01262       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01263       return -1;
01264    }
01265 
01266    if (!ast_mutex_lock(&iflock)) {
01267       /* Destroy all the interfaces and free their memory */
01268       p = iflist;
01269       while(p) {
01270          /* Close the socket, assuming it's real */
01271          if (p->fd > -1)
01272             close(p->fd);
01273          pl = p;
01274          p = p->next;
01275          /* Free associated memory */
01276          free(pl);
01277       }
01278       iflist = NULL;
01279       ast_mutex_unlock(&iflock);
01280    } else {
01281       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01282       return -1;
01283    }
01284       
01285    return 0;
01286 }

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

AST_MUTEX_DEFINE_STATIC ( usecnt_lock   ) 

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 1405 of file chan_phone.c.

01406 {
01407    return (char *) desc;
01408 }

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

Definition at line 957 of file chan_phone.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), phone_pvt::dev, DialTone, phone_pvt::dialtone, phone_pvt::fd, iflist, LOG_ERROR, LOG_WARNING, n, phone_pvt::next, phone_pvt::owner, phone_check_exception(), and phone_mini_packet().

00958 {
00959    fd_set rfds, efds;
00960    int n, res;
00961    struct phone_pvt *i;
00962    int tonepos = 0;
00963    /* The tone we're playing this round */
00964    struct timeval tv = {0,0};
00965    int dotone;
00966    /* This thread monitors all the frame relay interfaces which are not yet in use
00967       (and thus do not have a separate thread) indefinitely */
00968    /* From here on out, we die whenever asked */
00969    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
00970       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
00971       return NULL;
00972    }
00973    for(;;) {
00974       /* Don't let anybody kill us right away.  Nobody should lock the interface list
00975          and wait for the monitor list, but the other way around is okay. */
00976       if (ast_mutex_lock(&monlock)) {
00977          ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
00978          return NULL;
00979       }
00980       /* Lock the interface list */
00981       if (ast_mutex_lock(&iflock)) {
00982          ast_log(LOG_ERROR, "Unable to grab interface lock\n");
00983          ast_mutex_unlock(&monlock);
00984          return NULL;
00985       }
00986       /* Build the stuff we're going to select on, that is the socket of every
00987          phone_pvt that does not have an associated owner channel */
00988       n = -1;
00989       FD_ZERO(&rfds);
00990       FD_ZERO(&efds);
00991       i = iflist;
00992       dotone = 0;
00993       while(i) {
00994          if (FD_ISSET(i->fd, &rfds)) 
00995             ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
00996          if (!i->owner) {
00997             /* This needs to be watched, as it lacks an owner */
00998             FD_SET(i->fd, &rfds);
00999             FD_SET(i->fd, &efds);
01000             if (i->fd > n)
01001                n = i->fd;
01002             if (i->dialtone) {
01003                /* Remember we're going to have to come back and play
01004                   more dialtones */
01005                if (ast_tvzero(tv)) {
01006                   /* If we're due for a dialtone, play one */
01007                   if (write(i->fd, DialTone + tonepos, 240) != 240)
01008                      ast_log(LOG_WARNING, "Dial tone write error\n");
01009                }
01010                dotone++;
01011             }
01012          }
01013          
01014          i = i->next;
01015       }
01016       /* Okay, now that we know what to do, release the interface lock */
01017       ast_mutex_unlock(&iflock);
01018 
01019       /* And from now on, we're okay to be killed, so release the monitor lock as well */
01020       ast_mutex_unlock(&monlock);
01021 
01022       /* Wait indefinitely for something to happen */
01023       if (dotone) {
01024          /* If we're ready to recycle the time, set it to 30 ms */
01025          tonepos += 240;
01026          if (tonepos >= sizeof(DialTone))
01027                tonepos = 0;
01028          if (ast_tvzero(tv)) {
01029             tv = ast_tv(30000, 0);
01030          }
01031          res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
01032       } else {
01033          res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
01034          tv = ast_tv(0,0);
01035          tonepos = 0;
01036       }
01037       /* Okay, select has finished.  Let's see what happened.  */
01038       if (res < 0) {
01039          ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
01040          continue;
01041       }
01042       /* If there are no fd's changed, just continue, it's probably time
01043          to play some more dialtones */
01044       if (!res)
01045          continue;
01046       /* Alright, lock the interface list again, and let's look and see what has
01047          happened */
01048       if (ast_mutex_lock(&iflock)) {
01049          ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01050          continue;
01051       }
01052 
01053       i = iflist;
01054       for(; i; i=i->next) {
01055          if (FD_ISSET(i->fd, &rfds)) {
01056             if (i->owner) {
01057                continue;
01058             }
01059             phone_mini_packet(i);
01060          }
01061          if (FD_ISSET(i->fd, &efds)) {
01062             if (i->owner) {
01063                continue;
01064             }
01065             phone_check_exception(i);
01066          }
01067       }
01068       ast_mutex_unlock(&iflock);
01069    }
01070    /* Never reached */
01071    return NULL;
01072    
01073 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 1410 of file chan_phone.c.

References ASTERISK_GPL_KEY.

01411 {
01412    return ASTERISK_GPL_KEY;
01413 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 1293 of file chan_phone.c.

References __unload_module(), ast_callerid_split(), ast_channel_register(), ast_config_destroy(), ast_config_load(), AST_FORMAT_G723_1, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), ast_channel_tech::capabilities, cfg, cur_tech, DEFAULT_GAIN, iflist, LOG_ERROR, LOG_WARNING, mkif(), phone_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_FXS, MODE_IMMEDIATE, ast_variable::name, ast_variable::next, phone_pvt::next, parse_gain_value(), phone_tech, phone_tech_fxs, restart_monitor(), rxgain, txgain, and ast_variable::value.

01294 {
01295    struct ast_config *cfg;
01296    struct ast_variable *v;
01297    struct phone_pvt *tmp;
01298    int mode = MODE_IMMEDIATE;
01299    int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
01300    cfg = ast_config_load(config);
01301 
01302    /* We *must* have a config file otherwise stop immediately */
01303    if (!cfg) {
01304       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01305       return -1;
01306    }
01307    if (ast_mutex_lock(&iflock)) {
01308       /* It's a little silly to lock it, but we mind as well just to be sure */
01309       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01310       return -1;
01311    }
01312    v = ast_variable_browse(cfg, "interfaces");
01313    while(v) {
01314       /* Create the interface list */
01315       if (!strcasecmp(v->name, "device")) {
01316             tmp = mkif(v->value, mode, txgain, rxgain);
01317             if (tmp) {
01318                tmp->next = iflist;
01319                iflist = tmp;
01320                
01321             } else {
01322                ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01323                ast_config_destroy(cfg);
01324                ast_mutex_unlock(&iflock);
01325                __unload_module();
01326                return -1;
01327             }
01328       } else if (!strcasecmp(v->name, "silencesupression")) {
01329          silencesupression = ast_true(v->value);
01330       } else if (!strcasecmp(v->name, "language")) {
01331          strncpy(language, v->value, sizeof(language)-1);
01332       } else if (!strcasecmp(v->name, "callerid")) {
01333          ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01334       } else if (!strcasecmp(v->name, "mode")) {
01335          if (!strncasecmp(v->value, "di", 2)) 
01336             mode = MODE_DIALTONE;
01337          else if (!strncasecmp(v->value, "im", 2))
01338             mode = MODE_IMMEDIATE;
01339          else if (!strncasecmp(v->value, "fxs", 3)) {
01340             mode = MODE_FXS;
01341             prefformat = 0x01ff0000; /* All non-voice */
01342          }
01343          else if (!strncasecmp(v->value, "fx", 2))
01344             mode = MODE_FXO;
01345          else
01346             ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01347       } else if (!strcasecmp(v->name, "context")) {
01348          strncpy(context, v->value, sizeof(context)-1);
01349       } else if (!strcasecmp(v->name, "format")) {
01350          if (!strcasecmp(v->value, "g723.1")) {
01351             prefformat = AST_FORMAT_G723_1;
01352          } else if (!strcasecmp(v->value, "slinear")) {
01353             if (mode == MODE_FXS)
01354                 prefformat |= AST_FORMAT_SLINEAR;
01355             else prefformat = AST_FORMAT_SLINEAR;
01356          } else if (!strcasecmp(v->value, "ulaw")) {
01357             prefformat = AST_FORMAT_ULAW;
01358          } else
01359             ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01360       } else if (!strcasecmp(v->name, "echocancel")) {
01361          if (!strcasecmp(v->value, "off")) {
01362             echocancel = AEC_OFF;
01363          } else if (!strcasecmp(v->value, "low")) {
01364             echocancel = AEC_LOW;
01365          } else if (!strcasecmp(v->value, "medium")) {
01366             echocancel = AEC_MED;
01367          } else if (!strcasecmp(v->value, "high")) {
01368             echocancel = AEC_HIGH;
01369          } else 
01370             ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01371       } else if (!strcasecmp(v->name, "txgain")) {
01372          txgain = parse_gain_value(v->name, v->value);
01373       } else if (!strcasecmp(v->name, "rxgain")) {
01374          rxgain = parse_gain_value(v->name, v->value);
01375       }  
01376       v = v->next;
01377    }
01378    ast_mutex_unlock(&iflock);
01379 
01380    if (mode == MODE_FXS) {
01381       phone_tech_fxs.capabilities = prefformat;
01382       cur_tech = &phone_tech_fxs;
01383    } else
01384       cur_tech = (struct ast_channel_tech *) &phone_tech;
01385 
01386    /* Make sure we can register our Adtranphone channel type */
01387 
01388    if (ast_channel_register(cur_tech)) {
01389       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
01390       ast_config_destroy(cfg);
01391       __unload_module();
01392       return -1;
01393    }
01394    ast_config_destroy(cfg);
01395    /* And start the monitor for the first time */
01396    restart_monitor();
01397    return 0;
01398 }

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

Definition at line 1111 of file chan_phone.c.

References ast_log(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, free, phone_pvt::language, phone_pvt::lastformat, phone_pvt::lastinput, LOG_DEBUG, LOG_WARNING, malloc, 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.

01112 {
01113    /* Make a phone_pvt structure for this interface */
01114    struct phone_pvt *tmp;
01115    int flags;  
01116    
01117    tmp = malloc(sizeof(struct phone_pvt));
01118    if (tmp) {
01119       tmp->fd = open(iface, O_RDWR);
01120       if (tmp->fd < 0) {
01121          ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01122          free(tmp);
01123          return NULL;
01124       }
01125       if (mode == MODE_FXO) {
01126          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) 
01127             ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
01128       } else {
01129          if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 
01130              if (mode != MODE_FXS)
01131                   ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
01132       }
01133       ioctl(tmp->fd, PHONE_PLAY_STOP);
01134       ioctl(tmp->fd, PHONE_REC_STOP);
01135       ioctl(tmp->fd, PHONE_RING_STOP);
01136       ioctl(tmp->fd, PHONE_CPT_STOP);
01137       if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 
01138          ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01139       if (echocancel != AEC_OFF)
01140          ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01141       if (silencesupression) 
01142          tmp->silencesupression = 1;
01143 #ifdef PHONE_VAD
01144       ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01145 #endif
01146       tmp->mode = mode;
01147       flags = fcntl(tmp->fd, F_GETFL);
01148       fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01149       tmp->owner = NULL;
01150       tmp->lastformat = -1;
01151       tmp->lastinput = -1;
01152       tmp->ministate = 0;
01153       memset(tmp->ext, 0, sizeof(tmp->ext));
01154       strncpy(tmp->language, language, sizeof(tmp->language)-1);
01155       strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
01156       strncpy(tmp->context, context, sizeof(tmp->context)-1);
01157       tmp->next = NULL;
01158       tmp->obuflen = 0;
01159       tmp->dialtone = 0;
01160       tmp->cpt = 0;
01161       strncpy(tmp->cid_num, cid_num, sizeof(tmp->cid_num)-1);
01162       strncpy(tmp->cid_name, cid_name, sizeof(tmp->cid_name)-1);
01163       tmp->txgain = txgain;
01164       ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01165       tmp->rxgain = rxgain;
01166       ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01167    }
01168    return tmp;
01169 }

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

Definition at line 1213 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

01214 {
01215    float gain;
01216 
01217    /* try to scan number */
01218    if (sscanf(value, "%f", &gain) != 1)
01219    {
01220       ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01221          value, gain_type, config);
01222       return DEFAULT_GAIN;
01223    }
01224 
01225    /* multiplicate gain by 1.0 gain value */ 
01226    gain = gain * (float)DEFAULT_GAIN;
01227 
01228    /* percentage? */
01229    if (value[strlen(value) - 1] == '%')
01230       return (int)(gain / (float)100);
01231 
01232    return (int)gain;
01233 }

static int phone_answer ( struct ast_channel ast  )  [static]

Definition at line 411 of file chan_phone.c.

References ast_log(), ast_setstate(), AST_STATE_UP, phone_pvt::fd, LOG_DEBUG, phone_pvt::mode, MODE_FXO, ast_channel::name, option_debug, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt.

00412 {
00413    struct phone_pvt *p;
00414    p = ast->tech_pvt;
00415    /* In case it's a LineJack, take it off hook */
00416    if (p->mode == MODE_FXO) {
00417       if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 
00418          ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
00419       else
00420          ast_log(LOG_DEBUG, "Took linejack off hook\n");
00421    }
00422    phone_setup(ast);
00423    if (option_debug)
00424       ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name);
00425    ast->rings = 0;
00426    ast_setstate(ast, AST_STATE_UP);
00427    return 0;
00428 }

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

Definition at line 242 of file chan_phone.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, DEFAULT_CALLER_ID, ast_channel::fds, IXJ_PHONE_RING_START, LOG_DEBUG, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_channel::name, option_debug, phone_digit(), and ast_channel::tech_pvt.

00243 {
00244    struct phone_pvt *p;
00245 
00246    PHONE_CID cid;
00247    time_t UtcTime;
00248    struct tm tm;
00249    int start;
00250 
00251    time(&UtcTime);
00252    localtime_r(&UtcTime,&tm);
00253 
00254    memset(&cid, 0, sizeof(PHONE_CID));
00255    if(&tm != NULL) {
00256       snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1));
00257       snprintf(cid.day, sizeof(cid.day),     "%02d", tm.tm_mday);
00258       snprintf(cid.hour, sizeof(cid.hour),   "%02d", tm.tm_hour);
00259       snprintf(cid.min, sizeof(cid.min),     "%02d", tm.tm_min);
00260    }
00261    /* the standard format of ast->callerid is:  "name" <number>, but not always complete */
00262    if (ast_strlen_zero(ast->cid.cid_name))
00263       strncpy(cid.name, DEFAULT_CALLER_ID, sizeof(cid.name) - 1);
00264    else
00265       strncpy(cid.name, ast->cid.cid_name, sizeof(cid.name) - 1);
00266 
00267    if (ast->cid.cid_num) 
00268       strncpy(cid.number, ast->cid.cid_num, sizeof(cid.number) - 1);
00269 
00270    p = ast->tech_pvt;
00271 
00272    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00273       ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
00274       return -1;
00275    }
00276    if (option_debug)
00277       ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
00278 
00279    start = IXJ_PHONE_RING_START(cid);
00280    if (start == -1)
00281       return -1;
00282    
00283    if (p->mode == MODE_FXS) {
00284       char *digit = strchr(dest, '/');
00285       if (digit)
00286       {
00287         digit++;
00288         while (*digit)
00289           phone_digit(ast, *digit++);
00290       }
00291    }
00292  
00293    ast_setstate(ast, AST_STATE_RINGING);
00294    ast_queue_control(ast, AST_CONTROL_RINGING);
00295    return 0;
00296 }

static void phone_check_exception ( struct phone_pvt i  )  [static]

Definition at line 863 of file chan_phone.c.

References ast_canmatch_extension(), ast_exists_extension(), ast_log(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_update_use_count(), ast_verbose(), phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, LOG_DEBUG, phone_pvt::mode, MODE_DIALTONE, MODE_FXS, MODE_IMMEDIATE, option_debug, phone_new(), and usecnt_lock.

Referenced by do_monitor().

00864 {
00865    int offhook=0;
00866    char digit[2] = {0 , 0};
00867    union telephony_exception phonee;
00868    /* XXX Do something XXX */
00869 #if 0
00870    ast_log(LOG_DEBUG, "Exception!\n");
00871 #endif
00872    phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
00873    if (phonee.bits.dtmf_ready)  {
00874       digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
00875       if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS) {
00876          ioctl(i->fd, PHONE_PLAY_STOP);
00877          ioctl(i->fd, PHONE_REC_STOP);
00878          ioctl(i->fd, PHONE_CPT_STOP);
00879          i->dialtone = 0;
00880          if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
00881             strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
00882          if ((i->mode != MODE_FXS ||
00883               !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
00884               !phonee.bits.dtmf_ready) &&
00885              ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00886             /* It's a valid extension in its context, get moving! */
00887             phone_new(i, AST_STATE_RING, i->context);
00888             /* No need to restart monitor, we are the monitor */
00889          } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00890             /* There is nothing in the specified extension that can match anymore.
00891                Try the default */
00892             if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00893                /* Check the default, too... */
00894                phone_new(i, AST_STATE_RING, "default");
00895                /* XXX This should probably be justified better XXX */
00896             }  else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00897                /* It's not a valid extension, give a busy signal */
00898                if (option_debug)
00899                   ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
00900                ioctl(i->fd, PHONE_BUSY);
00901                i->cpt = 1;
00902             }
00903          }
00904 #if 0
00905          ast_verbose("Extension is %s\n", i->ext);
00906 #endif
00907       }
00908    }
00909    if (phonee.bits.hookstate) {
00910       offhook = ioctl(i->fd, PHONE_HOOKSTATE);
00911       if (offhook) {
00912          if (i->mode == MODE_IMMEDIATE) {
00913             phone_new(i, AST_STATE_RING, i->context);
00914          } else if (i->mode == MODE_DIALTONE) {
00915             ast_mutex_lock(&usecnt_lock);
00916             usecnt++;
00917             ast_mutex_unlock(&usecnt_lock);
00918             ast_update_use_count();
00919             /* Reset the extension */
00920             i->ext[0] = '\0';
00921             /* Play the dialtone */
00922             i->dialtone++;
00923             ioctl(i->fd, PHONE_PLAY_STOP);
00924             ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
00925             ioctl(i->fd, PHONE_PLAY_START);
00926             i->lastformat = -1;
00927          }
00928       } else {
00929          if (i->dialtone) {
00930             ast_mutex_lock(&usecnt_lock);
00931             usecnt--;
00932             ast_mutex_unlock(&usecnt_lock);
00933             ast_update_use_count();
00934          }
00935          memset(i->ext, 0, sizeof(i->ext));
00936          if (i->cpt)
00937          {
00938             ioctl(i->fd, PHONE_CPT_STOP);
00939             i->cpt = 0;
00940          }
00941          ioctl(i->fd, PHONE_PLAY_STOP);
00942          ioctl(i->fd, PHONE_REC_STOP);
00943          i->dialtone = 0;
00944          i->lastformat = -1;
00945       }
00946    }
00947    if (phonee.bits.pstn_ring) {
00948       ast_verbose("Unit is ringing\n");
00949       phone_new(i, AST_STATE_RING, i->context);
00950    }
00951    if (phonee.bits.caller_id)
00952       ast_verbose("We have caller ID\n");
00953    
00954    
00955 }

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

Definition at line 200 of file chan_phone.c.

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

Referenced by phone_call().

00201 {
00202    struct phone_pvt *p;
00203    int outdigit;
00204    p = ast->tech_pvt;
00205    ast_log(LOG_NOTICE, "Dialed %c\n", digit);
00206    switch(digit) {
00207    case '0':
00208    case '1':
00209    case '2':
00210    case '3':
00211    case '4':
00212    case '5':
00213    case '6':
00214    case '7':
00215    case '8':
00216    case '9':
00217       outdigit = digit - '0';
00218       break;
00219    case '*':
00220       outdigit = 11;
00221       break;
00222    case '#':
00223       outdigit = 12;
00224       break;
00225    case 'f':   /*flash*/
00226    case 'F':
00227       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00228       usleep(320000);
00229       ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00230       p->lastformat = -1;
00231       return 0;
00232    default:
00233       ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
00234       return -1;
00235    }
00236    ast_log(LOG_NOTICE, "Dialed %d\n", outdigit);
00237    ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
00238    p->lastformat = -1;
00239    return 0;
00240 }

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

Definition at line 444 of file chan_phone.c.

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

00445 {
00446    int res;
00447    union telephony_exception phonee;
00448    struct phone_pvt *p = ast->tech_pvt;
00449    char digit;
00450 
00451    /* Some nice norms */
00452    p->fr.datalen = 0;
00453    p->fr.samples = 0;
00454    p->fr.data =  NULL;
00455    p->fr.src = type;
00456    p->fr.offset = 0;
00457    p->fr.mallocd=0;
00458    p->fr.delivery = ast_tv(0,0);
00459    
00460    phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
00461    if (phonee.bits.dtmf_ready)  {
00462       if (option_debug)
00463          ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");
00464    
00465       /* We've got a digit -- Just handle this nicely and easily */
00466       digit =  ioctl(p->fd, PHONE_GET_DTMF_ASCII);
00467       p->fr.subclass = digit;
00468       p->fr.frametype = AST_FRAME_DTMF;
00469       return &p->fr;
00470    }
00471    if (phonee.bits.hookstate) {
00472       if (option_debug)
00473          ast_log(LOG_DEBUG, "Hookstate changed\n");
00474       res = ioctl(p->fd, PHONE_HOOKSTATE);
00475       /* See if we've gone on hook, if so, notify by returning NULL */
00476       if (option_debug)
00477          ast_log(LOG_DEBUG, "New hookstate: %d\n", res);
00478       if (!res && (p->mode != MODE_FXO))
00479          return NULL;
00480       else {
00481          if (ast->_state == AST_STATE_RINGING) {
00482             /* They've picked up the phone */
00483             p->fr.frametype = AST_FRAME_CONTROL;
00484             p->fr.subclass = AST_CONTROL_ANSWER;
00485             phone_setup(ast);
00486             ast_setstate(ast, AST_STATE_UP);
00487             return &p->fr;
00488          }  else 
00489             ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state);
00490       }
00491    }
00492 #if 1
00493    if (phonee.bits.pstn_ring)
00494       ast_verbose("Unit is ringing\n");
00495    if (phonee.bits.caller_id) {
00496       ast_verbose("We have caller ID\n");
00497    }
00498    if (phonee.bits.pstn_wink)
00499       ast_verbose("Detected Wink\n");
00500 #endif
00501    /* Strange -- nothing there.. */
00502    p->fr.frametype = AST_FRAME_NULL;
00503    p->fr.subclass = 0;
00504    return &p->fr;
00505 }

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

Definition at line 192 of file chan_phone.c.

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

00193 {
00194    struct phone_pvt *pvt = old->tech_pvt;
00195    if (pvt && pvt->owner == old)
00196       pvt->owner = new;
00197    return 0;
00198 }

static int phone_hangup ( struct ast_channel ast  )  [static]

Definition at line 298 of file chan_phone.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, ast_update_use_count(), ast_verbose(), phone_pvt::cpt, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, phone_pvt::lastinput, LOG_DEBUG, LOG_WARNING, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, ast_channel::name, phone_pvt::obuflen, option_debug, option_verbose, phone_pvt::owner, restart_monitor(), ast_channel::tech_pvt, usecnt_lock, and VERBOSE_PREFIX_3.

00299 {
00300    struct phone_pvt *p;
00301    p = ast->tech_pvt;
00302    if (option_debug)
00303       ast_log(LOG_DEBUG, "phone_hangup(%s)\n", ast->name);
00304    if (!ast->tech_pvt) {
00305       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00306       return 0;
00307    }
00308    /* XXX Is there anything we can do to really hang up except stop recording? */
00309    ast_setstate(ast, AST_STATE_DOWN);
00310    if (ioctl(p->fd, PHONE_REC_STOP))
00311       ast_log(LOG_WARNING, "Failed to stop recording\n");
00312    if (ioctl(p->fd, PHONE_PLAY_STOP))
00313       ast_log(LOG_WARNING, "Failed to stop playing\n");
00314    if (ioctl(p->fd, PHONE_RING_STOP))
00315       ast_log(LOG_WARNING, "Failed to stop ringing\n");
00316    if (ioctl(p->fd, PHONE_CPT_STOP))
00317       ast_log(LOG_WARNING, "Failed to stop sounds\n");
00318 
00319    /* If it's an FXO, hang them up */
00320    if (p->mode == MODE_FXO) {
00321       if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 
00322          ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
00323    }
00324 
00325    /* If they're off hook, give a busy signal */
00326    if (ioctl(p->fd, PHONE_HOOKSTATE)) {
00327       if (option_debug)
00328          ast_log(LOG_DEBUG, "Got hunghup, giving busy signal\n");
00329       ioctl(p->fd, PHONE_BUSY);
00330       p->cpt = 1;
00331    }
00332    p->lastformat = -1;
00333    p->lastinput = -1;
00334    p->ministate = 0;
00335    p->obuflen = 0;
00336    p->dialtone = 0;
00337    memset(p->ext, 0, sizeof(p->ext));
00338    ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
00339    ast_mutex_lock(&usecnt_lock);
00340    usecnt--;
00341    if (usecnt < 0) 
00342       ast_log(LOG_WARNING, "Usecnt < 0???\n");
00343    ast_mutex_unlock(&usecnt_lock);
00344    ast_update_use_count();
00345    if (option_verbose > 2) 
00346       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
00347    ast->tech_pvt = NULL;
00348    ast_setstate(ast, AST_STATE_DOWN);
00349    restart_monitor();
00350    return 0;
00351 }

static void phone_mini_packet ( struct phone_pvt i  )  [static]

Definition at line 851 of file chan_phone.c.

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

Referenced by do_monitor().

00852 {
00853    int res;
00854    char buf[1024];
00855    /* Ignore stuff we read... */
00856    res = read(i->fd, buf, sizeof(buf));
00857    if (res < 1) {
00858       ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
00859       return;
00860    }
00861 }

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

Definition at line 784 of file chan_phone.c.

References ast_channel_alloc(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::cpt, cur_tech, phone_pvt::dev, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, LOG_WARNING, phone_pvt::mode, MODE_FXS, phone_pvt::owner, strdup, and usecnt_lock.

Referenced by phone_check_exception(), and phone_request().

00785 {
00786    struct ast_channel *tmp;
00787    struct phone_codec_data codec;
00788    tmp = ast_channel_alloc(1);
00789    if (tmp) {
00790       tmp->tech = cur_tech;
00791       snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
00792       tmp->type = type;
00793       tmp->fds[0] = i->fd;
00794       /* XXX Switching formats silently causes kernel panics XXX */
00795       if (i->mode == MODE_FXS &&
00796           ioctl(i->fd, PHONE_QUERY_CODEC, &codec) == 0) {
00797          if (codec.type == LINEAR16)
00798             tmp->nativeformats =
00799             tmp->rawreadformat =
00800             tmp->rawwriteformat =
00801             AST_FORMAT_SLINEAR;
00802          else {
00803             tmp->nativeformats =
00804             tmp->rawreadformat =
00805             tmp->rawwriteformat =
00806             prefformat & ~AST_FORMAT_SLINEAR;
00807          }
00808       }
00809       else {
00810          tmp->nativeformats = prefformat;
00811          tmp->rawreadformat = prefformat;
00812          tmp->rawwriteformat = prefformat;
00813       }
00814       ast_setstate(tmp, state);
00815       if (state == AST_STATE_RING)
00816          tmp->rings = 1;
00817       tmp->tech_pvt = i;
00818       strncpy(tmp->context, context, sizeof(tmp->context)-1);
00819       if (!ast_strlen_zero(i->ext))
00820          strncpy(tmp->exten, i->ext, sizeof(tmp->exten)-1);
00821       else
00822          strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
00823       if (!ast_strlen_zero(i->language))
00824          strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
00825 
00826       if (!ast_strlen_zero(i->cid_num))
00827          tmp->cid.cid_num = strdup(i->cid_num);
00828       if (!ast_strlen_zero(i->cid_name))
00829          tmp->cid.cid_name = strdup(i->cid_name);
00830 
00831       i->owner = tmp;
00832       ast_mutex_lock(&usecnt_lock);
00833       usecnt++;
00834       ast_mutex_unlock(&usecnt_lock);
00835       ast_update_use_count();
00836       if (state != AST_STATE_DOWN) {
00837          if (state == AST_STATE_RING) {
00838             ioctl(tmp->fds[0], PHONE_RINGBACK);
00839             i->cpt = 1;
00840          }
00841          if (ast_pbx_start(tmp)) {
00842             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00843             ast_hangup(tmp);
00844          }
00845       }
00846    } else
00847       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00848    return tmp;
00849 }

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

Definition at line 507 of file chan_phone.c.

References ast_clear_flag, AST_FLAG_BLOCKING, AST_FORMAT_MAX_AUDIO, 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(), phone_pvt::buf, CHECK_BLOCKING, ast_frame::data, ast_frame::datalen, ast_frame::delivery, 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::samples, ast_frame::src, ast_frame::subclass, and ast_channel::tech_pvt.

00508 {
00509    int res;
00510    struct phone_pvt *p = ast->tech_pvt;
00511    
00512 
00513    /* Some nice norms */
00514    p->fr.datalen = 0;
00515    p->fr.samples = 0;
00516    p->fr.data =  NULL;
00517    p->fr.src = type;
00518    p->fr.offset = 0;
00519    p->fr.mallocd=0;
00520    p->fr.delivery = ast_tv(0,0);
00521 
00522    /* Try to read some data... */
00523    CHECK_BLOCKING(ast);
00524    res = read(p->fd, p->buf, PHONE_MAX_BUF);
00525    ast_clear_flag(ast, AST_FLAG_BLOCKING);
00526    if (res < 0) {
00527 #if 0
00528       if (errno == EAGAIN) {
00529          ast_log(LOG_WARNING, "Null frame received\n");
00530          p->fr.frametype = AST_FRAME_NULL;
00531          p->fr.subclass = 0;
00532          return &p->fr;
00533       }
00534 #endif
00535       ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));
00536       return NULL;
00537    }
00538    p->fr.data = p->buf;
00539    if (p->mode != MODE_FXS)
00540    switch(p->buf[0] & 0x3) {
00541    case '0':
00542    case '1':
00543       /* Normal */
00544       break;
00545    case '2':
00546    case '3':
00547       /* VAD/CNG, only send two words */
00548       res = 4;
00549       break;
00550    }
00551    p->fr.samples = 240;
00552    p->fr.datalen = res;
00553    p->fr.frametype = p->lastinput <= AST_FORMAT_MAX_AUDIO ?
00554                           AST_FRAME_VOICE : 
00555            p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE 
00556            : AST_FRAME_VIDEO;
00557    p->fr.subclass = p->lastinput;
00558    p->fr.offset = AST_FRIENDLY_OFFSET;
00559    /* Byteswap from little-endian to native-endian */
00560    if (p->fr.subclass == AST_FORMAT_SLINEAR)
00561       ast_frame_byteswap_le(&p->fr);
00562    return &p->fr;
00563 }

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

Definition at line 1171 of file chan_phone.c.

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

01172 {
01173    int oldformat;
01174    struct phone_pvt *p;
01175    struct ast_channel *tmp = NULL;
01176    char *name = data;
01177 
01178    /* Search for an unowned channel */
01179    if (ast_mutex_lock(&iflock)) {
01180       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01181       return NULL;
01182    }
01183    p = iflist;
01184    while(p) {
01185       if (p->mode == MODE_FXS ||
01186           format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01187           size_t length = strlen(p->dev + 5);
01188          if (strncmp(name, p->dev + 5, length) == 0 &&
01189              !isalnum(name[length])) {
01190              if (!p->owner) {
01191                      tmp = phone_new(p, AST_STATE_DOWN, p->context);
01192                      break;
01193                 } else
01194                      *cause = AST_CAUSE_BUSY;
01195             }
01196       }
01197       p = p->next;
01198    }
01199    ast_mutex_unlock(&iflock);
01200    restart_monitor();
01201    if (tmp == NULL) {
01202       oldformat = format;
01203       format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01204       if (!format) {
01205          ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01206          return NULL;
01207       }
01208    }
01209    return tmp;
01210 }

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

Definition at line 599 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

00600 {
00601     int length = strlen(text);
00602     return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 
00603            length ? 0 : -1;
00604 }

static int phone_setup ( struct ast_channel ast  )  [static]

Definition at line 353 of file chan_phone.c.

References AST_FORMAT_G723_1, 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().

00354 {
00355    struct phone_pvt *p;
00356    p = ast->tech_pvt;
00357    ioctl(p->fd, PHONE_CPT_STOP);
00358    /* Nothing to answering really, just start recording */
00359    if (ast->rawreadformat == AST_FORMAT_G723_1) {
00360       /* Prefer g723 */
00361       ioctl(p->fd, PHONE_REC_STOP);
00362       if (p->lastinput != AST_FORMAT_G723_1) {
00363          p->lastinput = AST_FORMAT_G723_1;
00364          if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00365             ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
00366             return -1;
00367          }
00368       }
00369    } else if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
00370       ioctl(p->fd, PHONE_REC_STOP);
00371       if (p->lastinput != AST_FORMAT_SLINEAR) {
00372          p->lastinput = AST_FORMAT_SLINEAR;
00373          if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00374             ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
00375             return -1;
00376          }
00377       }
00378    } else if (ast->rawreadformat == AST_FORMAT_ULAW) {
00379       ioctl(p->fd, PHONE_REC_STOP);
00380       if (p->lastinput != AST_FORMAT_ULAW) {
00381          p->lastinput = AST_FORMAT_ULAW;
00382          if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00383             ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
00384             return -1;
00385          }
00386       }
00387    } else if (p->mode == MODE_FXS) {
00388       ioctl(p->fd, PHONE_REC_STOP);
00389       if (p->lastinput != ast->rawreadformat) {
00390          p->lastinput = ast->rawreadformat;
00391          if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) {
00392             ast_log(LOG_WARNING, "Failed to set codec to %d\n", 
00393                ast->rawreadformat);
00394             return -1;
00395          }
00396       }
00397    } else {
00398       ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat));
00399       return -1;
00400    }
00401    if (ioctl(p->fd, PHONE_REC_START)) {
00402       ast_log(LOG_WARNING, "Failed to start recording\n");
00403       return -1;
00404    }
00405    /* set the DTMF times (the default is too short) */
00406    ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300);
00407    ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200);
00408    return 0;
00409 }

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

Definition at line 606 of file chan_phone.c.

References ast_channel::_state, AST_FORMAT_G723_1, 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, 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(), phone_pvt::silencesupression, ast_frame::subclass, and ast_channel::tech_pvt.

00607 {
00608    struct phone_pvt *p = ast->tech_pvt;
00609    int res;
00610    int maxfr=0;
00611    char *pos;
00612    int sofar;
00613    int expected;
00614    int codecset = 0;
00615    char tmpbuf[4];
00616    /* Write a frame of (presumably voice) data */
00617    if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {
00618       if (frame->frametype != AST_FRAME_IMAGE)
00619          ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
00620       return 0;
00621    }
00622    if (!(frame->subclass &
00623       (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) && 
00624        p->mode != MODE_FXS) {
00625       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
00626       return -1;
00627    }
00628 #if 0
00629    /* If we're not in up mode, go into up mode now */
00630    if (ast->_state != AST_STATE_UP) {
00631       ast_setstate(ast, AST_STATE_UP);
00632       phone_setup(ast);
00633    }
00634 #else
00635    if (ast->_state != AST_STATE_UP) {
00636       /* Don't try tos end audio on-hook */
00637       return 0;
00638    }
00639 #endif   
00640    if (frame->subclass == AST_FORMAT_G723_1) {
00641       if (p->lastformat != AST_FORMAT_G723_1) {
00642          ioctl(p->fd, PHONE_PLAY_STOP);
00643          ioctl(p->fd, PHONE_REC_STOP);
00644          if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
00645             ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00646             return -1;
00647          }
00648          if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00649             ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00650             return -1;
00651          }
00652          p->lastformat = AST_FORMAT_G723_1;
00653          p->lastinput = AST_FORMAT_G723_1;
00654          /* Reset output buffer */
00655          p->obuflen = 0;
00656          codecset = 1;
00657       }
00658       if (frame->datalen > 24) {
00659          ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
00660          return -1;
00661       }
00662       maxfr = 24;
00663    } else if (frame->subclass == AST_FORMAT_SLINEAR) {
00664       if (p->lastformat != AST_FORMAT_SLINEAR) {
00665          ioctl(p->fd, PHONE_PLAY_STOP);
00666          ioctl(p->fd, PHONE_REC_STOP);
00667          if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
00668             ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00669             return -1;
00670          }
00671          if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00672             ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00673             return -1;
00674          }
00675          p->lastformat = AST_FORMAT_SLINEAR;
00676          p->lastinput = AST_FORMAT_SLINEAR;
00677          codecset = 1;
00678          /* Reset output buffer */
00679          p->obuflen = 0;
00680       }
00681       maxfr = 480;
00682    } else if (frame->subclass == AST_FORMAT_ULAW) {
00683       if (p->lastformat != AST_FORMAT_ULAW) {
00684          ioctl(p->fd, PHONE_PLAY_STOP);
00685          ioctl(p->fd, PHONE_REC_STOP);
00686          if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
00687             ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00688             return -1;
00689          }
00690          if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00691             ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00692             return -1;
00693          }
00694          p->lastformat = AST_FORMAT_ULAW;
00695          p->lastinput = AST_FORMAT_ULAW;
00696          codecset = 1;
00697          /* Reset output buffer */
00698          p->obuflen = 0;
00699       }
00700       maxfr = 240;
00701    } else {
00702       if (p->lastformat != frame->subclass) {
00703          ioctl(p->fd, PHONE_PLAY_STOP);
00704          ioctl(p->fd, PHONE_REC_STOP);
00705          if (ioctl(p->fd, PHONE_PLAY_CODEC, frame->subclass)) {
00706             ast_log(LOG_WARNING, "Unable to set %d mode\n",
00707                frame->subclass);
00708             return -1;
00709          }
00710          if (ioctl(p->fd, PHONE_REC_CODEC, frame->subclass)) {
00711             ast_log(LOG_WARNING, "Unable to set %d mode\n",
00712                frame->subclass);
00713             return -1;
00714          }
00715          p->lastformat = frame->subclass;
00716          p->lastinput = frame->subclass;
00717          codecset = 1;
00718          /* Reset output buffer */
00719          p->obuflen = 0;
00720       }
00721       maxfr = 480;
00722    }
00723    if (codecset) {
00724       ioctl(p->fd, PHONE_REC_DEPTH, 3);
00725       ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
00726       if (ioctl(p->fd, PHONE_PLAY_START)) {
00727          ast_log(LOG_WARNING, "Failed to start playback\n");
00728          return -1;
00729       }
00730       if (ioctl(p->fd, PHONE_REC_START)) {
00731          ast_log(LOG_WARNING, "Failed to start recording\n");
00732          return -1;
00733       }
00734    }
00735    /* If we get here, we have a frame of Appropriate data */
00736    sofar = 0;
00737    pos = frame->data;
00738    while(sofar < frame->datalen) {
00739       /* Write in no more than maxfr sized frames */
00740       expected = frame->datalen - sofar;
00741       if (maxfr < expected)
00742          expected = maxfr;
00743       /* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX 
00744          we have to pad it to 24 bytes still.  */
00745       if (frame->datalen == 4) {
00746          if (p->silencesupression) {
00747             memset(tmpbuf + 4, 0, sizeof(tmpbuf) - 4);
00748             memcpy(tmpbuf, frame->data, 4);
00749             expected = 24;
00750             res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
00751          }
00752          res = 4;
00753          expected=4;
00754       } else {
00755          int swap = 0;
00756 #if __BYTE_ORDER == __BIG_ENDIAN
00757          if (frame->subclass == AST_FORMAT_SLINEAR)
00758             swap = 1; /* Swap big-endian samples to little-endian as we copy */
00759 #endif
00760          res = phone_write_buf(p, pos, expected, maxfr, swap);
00761       }
00762       if (res != expected) {
00763          if ((errno != EAGAIN) && (errno != EINTR)) {
00764             if (res < 0) 
00765                ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
00766    /*
00767     * Card is in non-blocking mode now and it works well now, but there are
00768     * lot of messages like this. So, this message is temporarily disabled.
00769     */
00770 #if 0
00771             else
00772                ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
00773 #endif
00774             return -1;
00775          } else /* Pretend it worked */
00776             res = expected;
00777       }
00778       sofar += res;
00779       pos += res;
00780    }
00781    return 0;
00782 }

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

Definition at line 565 of file chan_phone.c.

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

Referenced by phone_send_text(), and phone_write().

00566 {
00567    int res;
00568    /* Store as much of the buffer as we can, then write fixed frames */
00569    int space = sizeof(p->obuf) - p->obuflen;
00570    /* Make sure we have enough buffer space to store the frame */
00571    if (space < len)
00572       len = space;
00573    if (swap)
00574       ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2);
00575    else
00576       memcpy(p->obuf + p->obuflen, buf, len);
00577    p->obuflen += len;
00578    while(p->obuflen > frlen) {
00579       res = write(p->fd, p->obuf, frlen);
00580       if (res != frlen) {
00581          if (res < 1) {
00582 /*
00583  * Card is in non-blocking mode now and it works well now, but there are
00584  * lot of messages like this. So, this message is temporarily disabled.
00585  */
00586             return 0;
00587          } else {
00588             ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);
00589          }
00590       }
00591       p->obuflen -= frlen;
00592       /* Move memory if necessary */
00593       if (p->obuflen) 
00594          memmove(p->obuf, p->obuf + frlen, p->obuflen);
00595    }
00596    return len;
00597 }

static int restart_monitor ( void   )  [static]

Definition at line 1075 of file chan_phone.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING.

01076 {
01077    /* If we're supposed to be stopped -- stay stopped */
01078    if (monitor_thread == AST_PTHREADT_STOP)
01079       return 0;
01080    if (ast_mutex_lock(&monlock)) {
01081       ast_log(LOG_WARNING, "Unable to lock monitor\n");
01082       return -1;
01083    }
01084    if (monitor_thread == pthread_self()) {
01085       ast_mutex_unlock(&monlock);
01086       ast_log(LOG_WARNING, "Cannot kill myself\n");
01087       return -1;
01088    }
01089    if (monitor_thread != AST_PTHREADT_NULL) {
01090       if (ast_mutex_lock(&iflock)) {
01091         ast_mutex_unlock(&monlock);
01092         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01093         return -1;
01094       }
01095       pthread_cancel(monitor_thread);
01096 #if 0
01097       pthread_join(monitor_thread, NULL);
01098 #endif
01099       ast_mutex_unlock(&iflock);
01100    }
01101    /* Start a new monitor */
01102    if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01103       ast_mutex_unlock(&monlock);
01104       ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01105       return -1;
01106    }
01107    ast_mutex_unlock(&monlock);
01108    return 0;
01109 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 1288 of file chan_phone.c.

References __unload_module().

01289 {
01290    return __unload_module();
01291 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 1400 of file chan_phone.c.

01401 {
01402    return usecnt;
01403 }


Variable Documentation

char cid_name[AST_MAX_EXTENSION] [static]

Definition at line 146 of file chan_phone.c.

char cid_num[AST_MAX_EXTENSION] [static]

Definition at line 145 of file chan_phone.c.

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

Definition at line 81 of file chan_phone.c.

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

Definition at line 84 of file chan_phone.c.

struct ast_channel_tech* cur_tech [static]

Definition at line 190 of file chan_phone.c.

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

const char desc[] = "Linux Telephony API Support" [static]

Definition at line 78 of file chan_phone.c.

int echocancel = AEC_OFF [static]

Definition at line 90 of file chan_phone.c.

struct phone_pvt * iflist [static]

char language[MAX_LANGUAGE] = "" [static]

Definition at line 87 of file chan_phone.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 107 of file chan_phone.c.

struct ast_channel_tech phone_tech [static]

Definition at line 159 of file chan_phone.c.

Referenced by load_module().

struct ast_channel_tech phone_tech_fxs [static]

Definition at line 174 of file chan_phone.c.

Referenced by load_module().

int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW [static]

Definition at line 94 of file chan_phone.c.

int silencesupression = 0 [static]

Definition at line 92 of file chan_phone.c.

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

Definition at line 80 of file chan_phone.c.

const char type[] = "Phone" [static]

Definition at line 79 of file chan_phone.c.

int usecnt = 0 [static]

Definition at line 88 of file chan_phone.c.


Generated on Sat Mar 24 22:56:03 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7