Sat Sep 16 07:28:14 2006

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/compiler.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"

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

Referenced by phone_call().

#define DEFAULT_GAIN   0x100

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

Referenced by phone_call().

#define MODE_DIALTONE   1

Definition at line 117 of file chan_phone.c.

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

#define MODE_FXO   3

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

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

#define PHONE_MAX_BUF   480

Definition at line 78 of file chan_phone.c.

Referenced by phone_read().

#define QNDRV_VER   100

Definition at line 64 of file chan_phone.c.


Function Documentation

static int __unload_module ( void   )  [static]

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

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

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

01409 {
01410    return (char *) desc;
01411 }

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

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

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

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

References ASTERISK_GPL_KEY.

01414 {
01415    return ASTERISK_GPL_KEY;
01416 }

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

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

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

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

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

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

Definition at line 1216 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

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

static int phone_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

static void phone_check_exception ( struct phone_pvt i  )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 195 of file chan_phone.c.

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

00196 {
00197    struct phone_pvt *pvt = old->tech_pvt;
00198    if (pvt && pvt->owner == old)
00199       pvt->owner = new;
00200    return 0;
00201 }

static int phone_hangup ( struct ast_channel ast  )  [static]

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

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

static void phone_mini_packet ( struct phone_pvt i  )  [static]

Definition at line 854 of file chan_phone.c.

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

Referenced by do_monitor().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 602 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

00603 {
00604     int length = strlen(text);
00605     return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 
00606            length ? 0 : -1;
00607 }

static int phone_setup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

static int restart_monitor ( void   )  [static]

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

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

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

References __unload_module().

01292 {
01293    return __unload_module();
01294 }

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

01404 {
01405    return usecnt;
01406 }


Variable Documentation

char cid_name[AST_MAX_EXTENSION] [static]

Definition at line 149 of file chan_phone.c.

char cid_num[AST_MAX_EXTENSION] [static]

Definition at line 148 of file chan_phone.c.

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

Definition at line 84 of file chan_phone.c.

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

Definition at line 87 of file chan_phone.c.

struct ast_channel_tech* cur_tech [static]

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

int echocancel = AEC_OFF [static]

Definition at line 93 of file chan_phone.c.

struct phone_pvt * iflist [static]

char language[MAX_LANGUAGE] = "" [static]

Definition at line 90 of file chan_phone.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 110 of file chan_phone.c.

struct ast_channel_tech phone_tech [static]

Definition at line 162 of file chan_phone.c.

Referenced by load_module().

struct ast_channel_tech phone_tech_fxs [static]

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

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

Definition at line 82 of file chan_phone.c.

int usecnt = 0 [static]

Definition at line 91 of file chan_phone.c.


Generated on Sat Sep 16 07:28:14 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7