Fri May 26 01:47:00 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"

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 const 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 1236 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.

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

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

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

static void* do_monitor void *  data  )  [static]
 

Definition at line 958 of file chan_phone.c.

References ast_log(), ast_mutex_lock(), LOG_ERROR, LOG_WARNING, and n.

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

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

References ASTERISK_GPL_KEY.

01412 {
01413    return ASTERISK_GPL_KEY;
01414 }

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

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

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

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

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

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

Definition at line 1214 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

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

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

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

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

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

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

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       if (!ast_strlen_zero(i->cid_num))
00829          tmp->cid.cid_num = strdup(i->cid_num);
00830       if (!ast_strlen_zero(i->cid_name))
00831          tmp->cid.cid_name = strdup(i->cid_name);
00832       i->owner = tmp;
00833       ast_mutex_lock(&usecnt_lock);
00834       usecnt++;
00835       ast_mutex_unlock(&usecnt_lock);
00836       ast_update_use_count();
00837       if (state != AST_STATE_DOWN) {
00838          if (state == AST_STATE_RING) {
00839             ioctl(tmp->fds[0], PHONE_RINGBACK);
00840             i->cpt = 1;
00841          }
00842          if (ast_pbx_start(tmp)) {
00843             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00844             ast_hangup(tmp);
00845          }
00846       }
00847    } else
00848       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00849    return tmp;
00850 }

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

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

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

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

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

References __unload_module().

01290 {
01291    return __unload_module();
01292 }

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

01402 {
01403    return usecnt;
01404 }


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.

Referenced by fill_defaults(), misdn_cfg_get(), and misdn_cfg_get_config_string().

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.

const 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 Fri May 26 01:47:00 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6