Wed Jan 8 2020 09:50:04

Asterisk developer's documentation


chan_phone.c File Reference

Generic Linux Telephony Interface driver. More...

#include "asterisk.h"
#include <ctype.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <linux/telephony.h>
#include <linux/version.h>
#include <linux/ixjuser.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
#include "chan_phone.h"

Go to the source code of this file.

Data Structures

struct  phone_pvt
 

Macros

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

Functions

static void __reg_module (void)
 
static int __unload_module (void)
 
static void __unreg_module (void)
 
static void * do_monitor (void *data)
 
static int load_module (void)
 
static struct phone_pvtmkif (const char *iface, int mode, int txgain, int rxgain)
 
static int parse_gain_value (const char *gain_type, const char *value)
 
static int phone_answer (struct ast_channel *ast)
 
static int phone_call (struct ast_channel *ast, char *dest, int timeout)
 
static void phone_check_exception (struct phone_pvt *i)
 
static int phone_digit_begin (struct ast_channel *ast, char digit)
 
static int phone_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static struct ast_framephone_exception (struct ast_channel *ast)
 
static int phone_fixup (struct ast_channel *old, struct ast_channel *new)
 
static int phone_hangup (struct ast_channel *ast)
 
static int phone_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
 
static void phone_mini_packet (struct phone_pvt *i)
 
static struct ast_channelphone_new (struct phone_pvt *i, int state, char *cntx, const char *linkedid)
 
static struct ast_framephone_read (struct ast_channel *ast)
 
static struct ast_channelphone_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
 
static int phone_send_text (struct ast_channel *ast, const char *text)
 
static int phone_setup (struct ast_channel *ast)
 
static int phone_write (struct ast_channel *ast, struct ast_frame *frame)
 
static int phone_write_buf (struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
 
static int restart_monitor (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Linux Telephony API Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static char cid_name [AST_MAX_EXTENSION]
 
static char cid_num [AST_MAX_EXTENSION]
 
static const char config [] = "phone.conf"
 
static char context [AST_MAX_EXTENSION] = "default"
 
static struct ast_channel_techcur_tech
 
static int echocancel = AEC_OFF
 
static struct phone_pvtiflist = NULL
 
static ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 
static char language [MAX_LANGUAGE] = ""
 
static unsigned int monitor
 
static pthread_t monitor_thread = AST_PTHREADT_NULL
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 
static struct ast_channel_tech phone_tech
 
static struct ast_channel_tech phone_tech_fxs
 
static format_t prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW
 
static int silencesupression = 0
 
static const char tdesc [] = "Standard Linux Telephony API Driver"
 

Detailed Description

Generic Linux Telephony Interface driver.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file chan_phone.c.

Macro Definition Documentation

#define DEFAULT_CALLER_ID   "Unknown"

Definition at line 81 of file chan_phone.c.

Referenced by phone_call().

#define DEFAULT_GAIN   0x100

Definition at line 83 of file chan_phone.c.

Referenced by load_module(), and parse_gain_value().

#define IXJ_PHONE_RING_START (   x)    ioctl(p->fd, PHONE_RING_START, &x);

Definition at line 78 of file chan_phone.c.

Referenced by phone_call().

#define MODE_DIALTONE   1

Definition at line 119 of file chan_phone.c.

Referenced by load_module(), and phone_check_exception().

#define MODE_FXO   3

Definition at line 121 of file chan_phone.c.

Referenced by load_module(), mkif(), phone_answer(), phone_exception(), and phone_hangup().

#define MODE_FXS   4
#define MODE_IMMEDIATE   2

Definition at line 120 of file chan_phone.c.

Referenced by load_module(), and phone_check_exception().

#define MODE_SIGMA   5

Definition at line 123 of file chan_phone.c.

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

#define PHONE_MAX_BUF   480

Definition at line 82 of file chan_phone.c.

Referenced by phone_read().

#define QNDRV_VER   100

Definition at line 68 of file chan_phone.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 1479 of file chan_phone.c.

static int __unload_module ( void  )
static

Definition at line 1302 of file chan_phone.c.

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

Referenced by load_module(), and unload_module().

1303 {
1304  struct phone_pvt *p, *pl;
1305  /* First, take us out of the channel loop */
1306  if (cur_tech)
1308  if (!ast_mutex_lock(&iflock)) {
1309  /* Hangup all interfaces if they have an owner */
1310  p = iflist;
1311  while(p) {
1312  if (p->owner)
1314  p = p->next;
1315  }
1316  iflist = NULL;
1318  } else {
1319  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1320  return -1;
1321  }
1322  if (!ast_mutex_lock(&monlock)) {
1324  monitor = 0;
1325  while (pthread_kill(monitor_thread, SIGURG) == 0)
1326  sched_yield();
1327  pthread_join(monitor_thread, NULL);
1328  }
1331  } else {
1332  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1333  return -1;
1334  }
1335 
1336  if (!ast_mutex_lock(&iflock)) {
1337  /* Destroy all the interfaces and free their memory */
1338  p = iflist;
1339  while(p) {
1340  /* Close the socket, assuming it's real */
1341  if (p->fd > -1)
1342  close(p->fd);
1343  pl = p;
1344  p = p->next;
1345  /* Free associated memory */
1346  ast_free(pl);
1347  }
1348  iflist = NULL;
1350  } else {
1351  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1352  return -1;
1353  }
1354 
1355  return 0;
1356 }
static pthread_t monitor_thread
Definition: chan_phone.c:112
static ast_mutex_t iflock
Definition: chan_phone.c:101
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
#define LOG_WARNING
Definition: logger.h:144
struct phone_pvt * next
Definition: chan_phone.c:133
#define ast_mutex_lock(a)
Definition: lock.h:155
static ast_mutex_t monlock
Definition: chan_phone.c:105
static struct ast_channel_tech * cur_tech
Definition: chan_phone.c:202
struct ast_channel * owner
Definition: chan_phone.c:127
#define AST_PTHREADT_NULL
Definition: lock.h:65
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
static unsigned int monitor
Definition: chan_phone.c:108
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
static struct phone_pvt * iflist
#define AST_PTHREADT_STOP
Definition: lock.h:66
#define ast_mutex_unlock(a)
Definition: lock.h:156
static void __unreg_module ( void  )
static

Definition at line 1479 of file chan_phone.c.

static void* do_monitor ( void *  data)
static

Definition at line 1017 of file chan_phone.c.

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

Referenced by restart_monitor().

1018 {
1019  struct pollfd *fds = NULL;
1020  int nfds = 0, inuse_fds = 0, res;
1021  struct phone_pvt *i;
1022  int tonepos = 0;
1023  /* The tone we're playing this round */
1024  struct timeval tv = { 0, 0 };
1025  int dotone;
1026  /* This thread monitors all the frame relay interfaces which are not yet in use
1027  (and thus do not have a separate thread) indefinitely */
1028  while (monitor) {
1029  /* Don't let anybody kill us right away. Nobody should lock the interface list
1030  and wait for the monitor list, but the other way around is okay. */
1031  /* Lock the interface list */
1032  if (ast_mutex_lock(&iflock)) {
1033  ast_log(LOG_ERROR, "Unable to grab interface lock\n");
1034  return NULL;
1035  }
1036  /* Build the stuff we're going to select on, that is the socket of every
1037  phone_pvt that does not have an associated owner channel */
1038  i = iflist;
1039  dotone = 0;
1040  inuse_fds = 0;
1041  for (i = iflist; i; i = i->next) {
1042  if (!i->owner) {
1043  /* This needs to be watched, as it lacks an owner */
1044  if (inuse_fds == nfds) {
1045  void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
1046  if (!tmp) {
1047  /* Avoid leaking */
1048  continue;
1049  }
1050  fds = tmp;
1051  nfds++;
1052  }
1053  fds[inuse_fds].fd = i->fd;
1054  fds[inuse_fds].events = POLLIN | POLLERR;
1055  fds[inuse_fds].revents = 0;
1056  inuse_fds++;
1057 
1058  if (i->dialtone && i->mode != MODE_SIGMA) {
1059  /* Remember we're going to have to come back and play
1060  more dialtones */
1061  if (ast_tvzero(tv)) {
1062  /* If we're due for a dialtone, play one */
1063  if (write(i->fd, DialTone + tonepos, 240) != 240) {
1064  ast_log(LOG_WARNING, "Dial tone write error\n");
1065  }
1066  }
1067  dotone++;
1068  }
1069  }
1070  }
1071  /* Okay, now that we know what to do, release the interface lock */
1073 
1074  /* Wait indefinitely for something to happen */
1075  if (dotone && i && i->mode != MODE_SIGMA) {
1076  /* If we're ready to recycle the time, set it to 30 ms */
1077  tonepos += 240;
1078  if (tonepos >= sizeof(DialTone)) {
1079  tonepos = 0;
1080  }
1081  if (ast_tvzero(tv)) {
1082  tv = ast_tv(0, 30000);
1083  }
1084  res = ast_poll2(fds, inuse_fds, &tv);
1085  } else {
1086  res = ast_poll(fds, inuse_fds, -1);
1087  tv = ast_tv(0, 0);
1088  tonepos = 0;
1089  }
1090  /* Okay, select has finished. Let's see what happened. */
1091  if (res < 0) {
1092  ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
1093  continue;
1094  }
1095  /* If there are no fd's changed, just continue, it's probably time
1096  to play some more dialtones */
1097  if (!res) {
1098  continue;
1099  }
1100  /* Alright, lock the interface list again, and let's look and see what has
1101  happened */
1102  if (ast_mutex_lock(&iflock)) {
1103  ast_log(LOG_WARNING, "Unable to lock the interface list\n");
1104  continue;
1105  }
1106 
1107  for (i = iflist; i; i = i->next) {
1108  int j;
1109  /* Find the record */
1110  for (j = 0; j < inuse_fds; j++) {
1111  if (fds[j].fd == i->fd) {
1112  break;
1113  }
1114  }
1115 
1116  /* Not found? */
1117  if (j == inuse_fds) {
1118  continue;
1119  }
1120 
1121  if (fds[j].revents & POLLIN) {
1122  if (i->owner) {
1123  continue;
1124  }
1125  phone_mini_packet(i);
1126  }
1127  if (fds[j].revents & POLLERR) {
1128  if (i->owner) {
1129  continue;
1130  }
1132  }
1133  }
1135  }
1136  return NULL;
1137 }
static void phone_mini_packet(struct phone_pvt *i)
Definition: chan_phone.c:912
static ast_mutex_t iflock
Definition: chan_phone.c:101
int dialtone
Definition: chan_phone.c:138
#define LOG_WARNING
Definition: logger.h:144
struct phone_pvt * next
Definition: chan_phone.c:133
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
static unsigned char DialTone[]
Definition: chan_phone.h:17
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_channel * owner
Definition: chan_phone.c:127
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
#define LOG_ERROR
Definition: logger.h:155
static unsigned int monitor
Definition: chan_phone.c:108
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define MODE_SIGMA
Definition: chan_phone.c:123
static struct phone_pvt * iflist
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
#define ast_realloc(a, b)
Definition: astmm.h:103
struct timeval tv
static void phone_check_exception(struct phone_pvt *i)
Definition: chan_phone.c:924
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
Same as poll(2), except the time is specified in microseconds and the tv argument is modified to indi...
Definition: poll.c:268
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int load_module ( void  )
static

Definition at line 1363 of file chan_phone.c.

References __unload_module(), ast_callerid_split(), ast_channel_register(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_lock, ast_mutex_unlock, ast_true(), ast_variable_browse(), ast_channel_tech::capabilities, CONFIG_STATUS_FILEINVALID, DEFAULT_GAIN, iflist, iflock, LOG_ERROR, LOG_WARNING, mkif(), phone_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, ast_variable::name, ast_variable::next, phone_pvt::next, parse_gain_value(), phone_tech_fxs, prefformat, restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.

1364 {
1365  struct ast_config *cfg;
1366  struct ast_variable *v;
1367  struct phone_pvt *tmp;
1368  int mode = MODE_IMMEDIATE;
1369  int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */
1370  struct ast_flags config_flags = { 0 };
1371 
1372  if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
1373  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
1374  return AST_MODULE_LOAD_DECLINE;
1375  }
1376 
1377  /* We *must* have a config file otherwise stop immediately */
1378  if (!cfg) {
1379  ast_log(LOG_ERROR, "Unable to load config %s\n", config);
1380  return AST_MODULE_LOAD_DECLINE;
1381  }
1382  if (ast_mutex_lock(&iflock)) {
1383  /* It's a little silly to lock it, but we mind as well just to be sure */
1384  ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1385  return AST_MODULE_LOAD_FAILURE;
1386  }
1387  v = ast_variable_browse(cfg, "interfaces");
1388  while(v) {
1389  /* Create the interface list */
1390  if (!strcasecmp(v->name, "device")) {
1391  tmp = mkif(v->value, mode, txgain, rxgain);
1392  if (tmp) {
1393  tmp->next = iflist;
1394  iflist = tmp;
1395 
1396  } else {
1397  ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
1398  ast_config_destroy(cfg);
1400  __unload_module();
1401  return AST_MODULE_LOAD_FAILURE;
1402  }
1403  } else if (!strcasecmp(v->name, "silencesupression")) {
1405  } else if (!strcasecmp(v->name, "language")) {
1406  ast_copy_string(language, v->value, sizeof(language));
1407  } else if (!strcasecmp(v->name, "callerid")) {
1408  ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
1409  } else if (!strcasecmp(v->name, "mode")) {
1410  if (!strncasecmp(v->value, "di", 2))
1411  mode = MODE_DIALTONE;
1412  else if (!strncasecmp(v->value, "sig", 3))
1413  mode = MODE_SIGMA;
1414  else if (!strncasecmp(v->value, "im", 2))
1415  mode = MODE_IMMEDIATE;
1416  else if (!strncasecmp(v->value, "fxs", 3)) {
1417  mode = MODE_FXS;
1418  prefformat = 0x01ff0000; /* All non-voice */
1419  }
1420  else if (!strncasecmp(v->value, "fx", 2))
1421  mode = MODE_FXO;
1422  else
1423  ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
1424  } else if (!strcasecmp(v->name, "context")) {
1425  ast_copy_string(context, v->value, sizeof(context));
1426  } else if (!strcasecmp(v->name, "format")) {
1427  if (!strcasecmp(v->value, "g729")) {
1429  } else if (!strcasecmp(v->value, "g723.1")) {
1431  } else if (!strcasecmp(v->value, "slinear")) {
1432  if (mode == MODE_FXS)
1435  } else if (!strcasecmp(v->value, "ulaw")) {
1437  } else
1438  ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
1439  } else if (!strcasecmp(v->name, "echocancel")) {
1440  if (!strcasecmp(v->value, "off")) {
1441  echocancel = AEC_OFF;
1442  } else if (!strcasecmp(v->value, "low")) {
1443  echocancel = AEC_LOW;
1444  } else if (!strcasecmp(v->value, "medium")) {
1445  echocancel = AEC_MED;
1446  } else if (!strcasecmp(v->value, "high")) {
1447  echocancel = AEC_HIGH;
1448  } else
1449  ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
1450  } else if (!strcasecmp(v->name, "txgain")) {
1451  txgain = parse_gain_value(v->name, v->value);
1452  } else if (!strcasecmp(v->name, "rxgain")) {
1453  rxgain = parse_gain_value(v->name, v->value);
1454  }
1455  v = v->next;
1456  }
1458 
1459  if (mode == MODE_FXS) {
1462  } else
1463  cur_tech = (struct ast_channel_tech *) &phone_tech;
1464 
1465  /* Make sure we can register our Adtranphone channel type */
1466 
1468  ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
1469  ast_config_destroy(cfg);
1470  __unload_module();
1471  return AST_MODULE_LOAD_FAILURE;
1472  }
1473  ast_config_destroy(cfg);
1474  /* And start the monitor for the first time */
1475  restart_monitor();
1476  return AST_MODULE_LOAD_SUCCESS;
1477 }
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_phone.c:151
static int parse_gain_value(const char *gain_type, const char *value)
Definition: chan_phone.c:1280
static const char config[]
Definition: chan_phone.c:86
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1093
format_t capabilities
Definition: channel.h:511
static ast_mutex_t iflock
Definition: chan_phone.c:101
#define AST_FORMAT_G723_1
Definition: frame.h:242
#define MODE_IMMEDIATE
Definition: chan_phone.c:120
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
struct phone_pvt * next
Definition: chan_phone.c:133
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static int restart_monitor(void)
Definition: chan_phone.c:1139
static char language[MAX_LANGUAGE]
Definition: chan_phone.c:92
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_phone.c:152
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
static struct ast_channel_tech phone_tech
Definition: chan_phone.c:167
static struct ast_channel_tech * cur_tech
Definition: chan_phone.c:202
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define AST_FORMAT_G729A
Definition: frame.h:258
int txgain
Definition: chan_phone.c:139
const char * value
Definition: config.h:79
int rxgain
Definition: chan_phone.c:139
static struct ast_channel_tech phone_tech_fxs
Definition: chan_phone.c:184
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static int echocancel
Definition: chan_phone.c:94
const char * name
Definition: config.h:77
static int __unload_module(void)
Definition: chan_phone.c:1302
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
#define MODE_DIALTONE
Definition: chan_phone.c:119
#define AST_FORMAT_ULAW
Definition: frame.h:246
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define MODE_FXS
Definition: chan_phone.c:122
#define MODE_SIGMA
Definition: chan_phone.c:123
static struct phone_pvt * mkif(const char *iface, int mode, int txgain, int rxgain)
Definition: chan_phone.c:1176
Structure used to handle boolean flags.
Definition: utils.h:200
static struct phone_pvt * iflist
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:89
#define DEFAULT_GAIN
Definition: chan_phone.c:83
static int silencesupression
Definition: chan_phone.c:96
struct ast_variable * next
Definition: config.h:82
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define MODE_FXO
Definition: chan_phone.c:121
static format_t prefformat
Definition: chan_phone.c:98
#define ast_mutex_unlock(a)
Definition: lock.h:156
static struct phone_pvt* mkif ( const char *  iface,
int  mode,
int  txgain,
int  rxgain 
)
static

Definition at line 1176 of file chan_phone.c.

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

Referenced by load_module().

1177 {
1178  /* Make a phone_pvt structure for this interface */
1179  struct phone_pvt *tmp;
1180  int flags;
1181 
1182  tmp = ast_calloc(1, sizeof(*tmp));
1183  if (tmp) {
1184  tmp->fd = open(iface, O_RDWR);
1185  if (tmp->fd < 0) {
1186  ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
1187  ast_free(tmp);
1188  return NULL;
1189  }
1190  if (mode == MODE_FXO) {
1191  if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
1192  ast_debug(1, "Unable to set port to PSTN\n");
1193  }
1194  } else {
1195  if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
1196  if (mode != MODE_FXS)
1197  ast_debug(1, "Unable to set port to POTS\n");
1198  }
1199  ioctl(tmp->fd, PHONE_PLAY_STOP);
1200  ioctl(tmp->fd, PHONE_REC_STOP);
1201  ioctl(tmp->fd, PHONE_RING_STOP);
1202  ioctl(tmp->fd, PHONE_CPT_STOP);
1203  if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
1204  ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
1205  if (echocancel != AEC_OFF)
1206  ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
1207  if (silencesupression)
1208  tmp->silencesupression = 1;
1209 #ifdef PHONE_VAD
1210  ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
1211 #endif
1212  tmp->mode = mode;
1213  flags = fcntl(tmp->fd, F_GETFL);
1214  fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
1215  tmp->owner = NULL;
1216  tmp->lastformat = -1;
1217  tmp->lastinput = -1;
1218  tmp->ministate = 0;
1219  memset(tmp->ext, 0, sizeof(tmp->ext));
1220  ast_copy_string(tmp->language, language, sizeof(tmp->language));
1221  ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
1222  ast_copy_string(tmp->context, context, sizeof(tmp->context));
1223  tmp->next = NULL;
1224  tmp->obuflen = 0;
1225  tmp->dialtone = 0;
1226  tmp->cpt = 0;
1227  ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
1228  ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
1229  tmp->txgain = txgain;
1230  ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
1231  tmp->rxgain = rxgain;
1232  ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
1233  }
1234  return tmp;
1235 }
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_phone.c:151
int ministate
Definition: chan_phone.c:131
int dialtone
Definition: chan_phone.c:138
int silencesupression
Definition: chan_phone.c:142
#define LOG_WARNING
Definition: logger.h:144
struct phone_pvt * next
Definition: chan_phone.c:133
static char language[MAX_LANGUAGE]
Definition: chan_phone.c:92
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_phone.c:152
format_t lastinput
Definition: chan_phone.c:130
int txgain
Definition: chan_phone.c:139
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_channel * owner
Definition: chan_phone.c:127
int rxgain
Definition: chan_phone.c:139
static int echocancel
Definition: chan_phone.c:94
char language[MAX_LANGUAGE]
Definition: chan_phone.c:146
char ext[AST_MAX_EXTENSION]
Definition: chan_phone.c:145
char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:143
char dev[256]
Definition: chan_phone.c:132
char cid_num[AST_MAX_EXTENSION]
Definition: chan_phone.c:147
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define ast_free(a)
Definition: astmm.h:97
#define MODE_FXS
Definition: chan_phone.c:122
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:89
format_t lastformat
Definition: chan_phone.c:129
static int silencesupression
Definition: chan_phone.c:96
char cid_name[AST_MAX_EXTENSION]
Definition: chan_phone.c:148
int obuflen
Definition: chan_phone.c:137
#define MODE_FXO
Definition: chan_phone.c:121
static int parse_gain_value ( const char *  gain_type,
const char *  value 
)
static

Definition at line 1280 of file chan_phone.c.

References ast_log(), DEFAULT_GAIN, and LOG_ERROR.

Referenced by load_module().

1281 {
1282  float gain;
1283 
1284  /* try to scan number */
1285  if (sscanf(value, "%30f", &gain) != 1)
1286  {
1287  ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
1288  value, gain_type, config);
1289  return DEFAULT_GAIN;
1290  }
1291 
1292  /* multiplicate gain by 1.0 gain value */
1293  gain = gain * (float)DEFAULT_GAIN;
1294 
1295  /* percentage? */
1296  if (value[strlen(value) - 1] == '%')
1297  return (int)(gain / (float)100);
1298 
1299  return (int)gain;
1300 }
static const char config[]
Definition: chan_phone.c:86
int value
Definition: syslog.c:39
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define DEFAULT_GAIN
Definition: chan_phone.c:83
static int phone_answer ( struct ast_channel ast)
static

Definition at line 457 of file chan_phone.c.

References ast_debug, ast_setstate(), AST_STATE_UP, errno, phone_pvt::fd, phone_pvt::mode, MODE_FXO, ast_channel::name, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt.

458 {
459  struct phone_pvt *p;
460  p = ast->tech_pvt;
461  /* In case it's a LineJack, take it off hook */
462  if (p->mode == MODE_FXO) {
463  if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
464  ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
465  else
466  ast_debug(1, "Took linejack off hook\n");
467  }
468  phone_setup(ast);
469  ast_debug(1, "phone_answer(%s)\n", ast->name);
470  ast->rings = 0;
472  return 0;
473 }
int rings
Definition: channel.h:840
static int phone_setup(struct ast_channel *ast)
Definition: chan_phone.c:390
void * tech_pvt
Definition: channel.h:744
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const ast_string_field name
Definition: channel.h:787
int errno
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
#define MODE_FXO
Definition: chan_phone.c:121
static int phone_call ( struct ast_channel ast,
char *  dest,
int  timeout 
)
static

Definition at line 288 of file chan_phone.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_tvnow(), ast_channel::connected, DEFAULT_CALLER_ID, ast_channel::fds, ast_party_connected_line::id, IXJ_PHONE_RING_START, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_party_id::name, ast_channel::name, ast_party_id::number, phone_digit_end(), ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_party_name::valid, and ast_party_number::valid.

289 {
290  struct phone_pvt *p;
291 
292  PHONE_CID cid;
293  struct timeval UtcTime = ast_tvnow();
294  struct ast_tm tm;
295  int start;
296 
297  ast_localtime(&UtcTime, &tm, NULL);
298 
299  memset(&cid, 0, sizeof(PHONE_CID));
300  snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1));
301  snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday);
302  snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour);
303  snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
304  /* the standard format of ast->callerid is: "name" <number>, but not always complete */
305  if (!ast->connected.id.name.valid
306  || ast_strlen_zero(ast->connected.id.name.str)) {
307  strcpy(cid.name, DEFAULT_CALLER_ID);
308  } else {
309  ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name));
310  }
311 
312  if (ast->connected.id.number.valid && ast->connected.id.number.str) {
313  ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number));
314  }
315 
316  p = ast->tech_pvt;
317 
318  if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
319  ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
320  return -1;
321  }
322  ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
323 
324  start = IXJ_PHONE_RING_START(cid);
325  if (start == -1)
326  return -1;
327 
328  if (p->mode == MODE_FXS) {
329  char *digit = strchr(dest, '/');
330  if (digit)
331  {
332  digit++;
333  while (*digit)
334  phone_digit_end(ast, *digit++, 0);
335  }
336  }
337 
340  return 0;
341 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
char * str
Subscriber name (Malloced)
Definition: channel.h:214
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int fds[AST_MAX_FDS]
Definition: channel.h:829
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define IXJ_PHONE_RING_START(x)
Definition: chan_phone.c:78
#define MODE_FXS
Definition: chan_phone.c:122
#define DEFAULT_CALLER_ID
Definition: chan_phone.c:81
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_phone.c:246
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void phone_check_exception ( struct phone_pvt i)
static

Definition at line 924 of file chan_phone.c.

References ast_canmatch_extension(), ast_debug, ast_exists_extension(), AST_MAX_EXTENSION, ast_module_ref(), ast_module_unref(), AST_STATE_RING, ast_verbose(), phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, phone_pvt::mode, MODE_DIALTONE, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, phone_new(), and ast_module_info::self.

Referenced by do_monitor().

925 {
926  int offhook=0;
927  char digit[2] = {0 , 0};
928  union telephony_exception phonee;
929  /* XXX Do something XXX */
930 #if 0
931  ast_debug(1, "Exception!\n");
932 #endif
933  phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
934  if (phonee.bits.dtmf_ready) {
935  digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
936  if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
937  ioctl(i->fd, PHONE_PLAY_STOP);
938  ioctl(i->fd, PHONE_REC_STOP);
939  ioctl(i->fd, PHONE_CPT_STOP);
940  i->dialtone = 0;
941  if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
942  strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
943  if ((i->mode != MODE_FXS ||
944  !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
945  !phonee.bits.dtmf_ready) &&
946  ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
947  /* It's a valid extension in its context, get moving! */
948  phone_new(i, AST_STATE_RING, i->context, NULL);
949  /* No need to restart monitor, we are the monitor */
950  } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
951  /* There is nothing in the specified extension that can match anymore.
952  Try the default */
953  if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
954  /* Check the default, too... */
955  phone_new(i, AST_STATE_RING, "default", NULL);
956  /* XXX This should probably be justified better XXX */
957  } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
958  /* It's not a valid extension, give a busy signal */
959  ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context);
960  ioctl(i->fd, PHONE_BUSY);
961  i->cpt = 1;
962  }
963  }
964 #if 0
965  ast_verbose("Extension is %s\n", i->ext);
966 #endif
967  }
968  }
969  if (phonee.bits.hookstate) {
970  offhook = ioctl(i->fd, PHONE_HOOKSTATE);
971  if (offhook) {
972  if (i->mode == MODE_IMMEDIATE) {
973  phone_new(i, AST_STATE_RING, i->context, NULL);
974  } else if (i->mode == MODE_DIALTONE) {
976  /* Reset the extension */
977  i->ext[0] = '\0';
978  /* Play the dialtone */
979  i->dialtone++;
980  ioctl(i->fd, PHONE_PLAY_STOP);
981  ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
982  ioctl(i->fd, PHONE_PLAY_START);
983  i->lastformat = -1;
984  } else if (i->mode == MODE_SIGMA) {
986  /* Reset the extension */
987  i->ext[0] = '\0';
988  /* Play the dialtone */
989  i->dialtone++;
990  ioctl(i->fd, PHONE_DIALTONE);
991  }
992  } else {
993  if (i->dialtone)
995  memset(i->ext, 0, sizeof(i->ext));
996  if (i->cpt)
997  {
998  ioctl(i->fd, PHONE_CPT_STOP);
999  i->cpt = 0;
1000  }
1001  ioctl(i->fd, PHONE_PLAY_STOP);
1002  ioctl(i->fd, PHONE_REC_STOP);
1003  i->dialtone = 0;
1004  i->lastformat = -1;
1005  }
1006  }
1007  if (phonee.bits.pstn_ring) {
1008  ast_verbose("Unit is ringing\n");
1009  phone_new(i, AST_STATE_RING, i->context, NULL);
1010  }
1011  if (phonee.bits.caller_id)
1012  ast_verbose("We have caller ID\n");
1013 
1014 
1015 }
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
#define MODE_IMMEDIATE
Definition: chan_phone.c:120
int dialtone
Definition: chan_phone.c:138
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_module * self
Definition: module.h:227
#define AST_MAX_EXTENSION
Definition: channel.h:135
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
char ext[AST_MAX_EXTENSION]
Definition: chan_phone.c:145
char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:143
#define MODE_DIALTONE
Definition: chan_phone.c:119
char cid_num[AST_MAX_EXTENSION]
Definition: chan_phone.c:147
#define MODE_FXS
Definition: chan_phone.c:122
#define MODE_SIGMA
Definition: chan_phone.c:123
format_t lastformat
Definition: chan_phone.c:129
static struct ast_channel * phone_new(struct phone_pvt *i, int state, char *cntx, const char *linkedid)
Definition: chan_phone.c:848
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static int phone_digit_begin ( struct ast_channel ast,
char  digit 
)
static

Definition at line 240 of file chan_phone.c.

241 {
242  /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */
243  return 0;
244 }
static int phone_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
)
static

Definition at line 246 of file chan_phone.c.

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

Referenced by phone_call().

247 {
248  struct phone_pvt *p;
249  int outdigit;
250  p = ast->tech_pvt;
251  ast_debug(1, "Dialed %c\n", digit);
252  switch(digit) {
253  case '0':
254  case '1':
255  case '2':
256  case '3':
257  case '4':
258  case '5':
259  case '6':
260  case '7':
261  case '8':
262  case '9':
263  outdigit = digit - '0';
264  break;
265  case '*':
266  outdigit = 11;
267  break;
268  case '#':
269  outdigit = 12;
270  break;
271  case 'f': /*flash*/
272  case 'F':
273  ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
274  usleep(320000);
275  ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
276  p->lastformat = -1;
277  return 0;
278  default:
279  ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
280  return -1;
281  }
282  ast_debug(1, "Dialed %d\n", outdigit);
283  ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
284  p->lastformat = -1;
285  return 0;
286 }
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
format_t lastformat
Definition: chan_phone.c:129
static struct ast_frame * phone_exception ( struct ast_channel ast)
static

Definition at line 489 of file chan_phone.c.

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

490 {
491  int res;
492  union telephony_exception phonee;
493  struct phone_pvt *p = ast->tech_pvt;
494  char digit;
495 
496  /* Some nice norms */
497  p->fr.datalen = 0;
498  p->fr.samples = 0;
499  p->fr.data.ptr = NULL;
500  p->fr.src = "Phone";
501  p->fr.offset = 0;
502  p->fr.mallocd=0;
503  p->fr.delivery = ast_tv(0,0);
504 
505  phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
506  if (phonee.bits.dtmf_ready) {
507  ast_debug(1, "phone_exception(): DTMF\n");
508 
509  /* We've got a digit -- Just handle this nicely and easily */
510  digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
511  p->fr.subclass.integer = digit;
513  return &p->fr;
514  }
515  if (phonee.bits.hookstate) {
516  ast_debug(1, "Hookstate changed\n");
517  res = ioctl(p->fd, PHONE_HOOKSTATE);
518  /* See if we've gone on hook, if so, notify by returning NULL */
519  ast_debug(1, "New hookstate: %d\n", res);
520  if (!res && (p->mode != MODE_FXO))
521  return NULL;
522  else {
523  if (ast->_state == AST_STATE_RINGING) {
524  /* They've picked up the phone */
527  phone_setup(ast);
529  return &p->fr;
530  } else
531  ast_log(LOG_WARNING, "Got off hook in weird state %u\n", ast->_state);
532  }
533  }
534 #if 1
535  if (phonee.bits.pstn_ring)
536  ast_verbose("Unit is ringing\n");
537  if (phonee.bits.caller_id) {
538  ast_verbose("We have caller ID\n");
539  }
540  if (phonee.bits.pstn_wink)
541  ast_verbose("Detected Wink\n");
542 #endif
543  /* Strange -- nothing there.. */
545  p->fr.subclass.integer = 0;
546  return &p->fr;
547 }
union ast_frame_subclass subclass
Definition: frame.h:146
int offset
Definition: frame.h:156
static int phone_setup(struct ast_channel *ast)
Definition: chan_phone.c:390
void * ptr
Definition: frame.h:160
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame fr
Definition: chan_phone.c:134
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * src
Definition: frame.h:158
int datalen
Definition: frame.h:148
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct timeval delivery
Definition: frame.h:162
int mallocd
Definition: frame.h:152
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
enum ast_frame_type frametype
Definition: frame.h:144
union ast_frame::@172 data
#define MODE_FXO
Definition: chan_phone.c:121
int samples
Definition: frame.h:150
static int phone_fixup ( struct ast_channel old,
struct ast_channel new 
)
static

Definition at line 232 of file chan_phone.c.

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

233 {
234  struct phone_pvt *pvt = old->tech_pvt;
235  if (pvt && pvt->owner == old)
236  pvt->owner = new;
237  return 0;
238 }
void * tech_pvt
Definition: channel.h:744
struct ast_channel * owner
Definition: chan_phone.c:127
static int phone_hangup ( struct ast_channel ast)
static

Definition at line 343 of file chan_phone.c.

References ast_debug, ast_log(), ast_module_unref(), ast_setstate(), AST_STATE_DOWN, ast_verb, phone_pvt::cpt, phone_pvt::dialtone, errno, phone_pvt::ext, phone_pvt::fd, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, ast_channel::name, phone_pvt::obuflen, phone_pvt::owner, restart_monitor(), ast_module_info::self, and ast_channel::tech_pvt.

344 {
345  struct phone_pvt *p;
346  p = ast->tech_pvt;
347  ast_debug(1, "phone_hangup(%s)\n", ast->name);
348  if (!ast->tech_pvt) {
349  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
350  return 0;
351  }
352  /* XXX Is there anything we can do to really hang up except stop recording? */
354  if (ioctl(p->fd, PHONE_REC_STOP))
355  ast_log(LOG_WARNING, "Failed to stop recording\n");
356  if (ioctl(p->fd, PHONE_PLAY_STOP))
357  ast_log(LOG_WARNING, "Failed to stop playing\n");
358  if (ioctl(p->fd, PHONE_RING_STOP))
359  ast_log(LOG_WARNING, "Failed to stop ringing\n");
360  if (ioctl(p->fd, PHONE_CPT_STOP))
361  ast_log(LOG_WARNING, "Failed to stop sounds\n");
362 
363  /* If it's an FXO, hang them up */
364  if (p->mode == MODE_FXO) {
365  if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
366  ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
367  }
368 
369  /* If they're off hook, give a busy signal */
370  if (ioctl(p->fd, PHONE_HOOKSTATE)) {
371  ast_debug(1, "Got hunghup, giving busy signal\n");
372  ioctl(p->fd, PHONE_BUSY);
373  p->cpt = 1;
374  }
375  p->lastformat = -1;
376  p->lastinput = -1;
377  p->ministate = 0;
378  p->obuflen = 0;
379  p->dialtone = 0;
380  memset(p->ext, 0, sizeof(p->ext));
381  ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
383  ast_verb(3, "Hungup '%s'\n", ast->name);
384  ast->tech_pvt = NULL;
386  restart_monitor();
387  return 0;
388 }
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
int ministate
Definition: chan_phone.c:131
void * tech_pvt
Definition: channel.h:744
int dialtone
Definition: chan_phone.c:138
#define LOG_WARNING
Definition: logger.h:144
static int restart_monitor(void)
Definition: chan_phone.c:1139
format_t lastinput
Definition: chan_phone.c:130
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_channel * owner
Definition: chan_phone.c:127
struct ast_module * self
Definition: module.h:227
char ext[AST_MAX_EXTENSION]
Definition: chan_phone.c:145
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
format_t lastformat
Definition: chan_phone.c:129
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
int obuflen
Definition: chan_phone.c:137
#define MODE_FXO
Definition: chan_phone.c:121
static int phone_indicate ( struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
)
static

Definition at line 204 of file chan_phone.c.

References AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), phone_pvt::fd, phone_pvt::lastformat, LOG_WARNING, ast_channel::name, and ast_channel::tech_pvt.

205 {
206  struct phone_pvt *p = chan->tech_pvt;
207  int res=-1;
208  ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
209  switch(condition) {
210  case AST_CONTROL_FLASH:
211  ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
212  usleep(320000);
213  ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
214  p->lastformat = -1;
215  res = 0;
216  break;
217  case AST_CONTROL_HOLD:
218  ast_moh_start(chan, data, NULL);
219  break;
220  case AST_CONTROL_UNHOLD:
221  ast_moh_stop(chan);
222  break;
224  res = 0;
225  break;
226  default:
227  ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name);
228  }
229  return res;
230 }
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
format_t lastformat
Definition: chan_phone.c:129
static void phone_mini_packet ( struct phone_pvt i)
static

Definition at line 912 of file chan_phone.c.

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

Referenced by do_monitor().

913 {
914  int res;
915  char buf[1024];
916  /* Ignore stuff we read... */
917  res = read(i->fd, buf, sizeof(buf));
918  if (res < 1) {
919  ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
920  return;
921  }
922 }
#define LOG_WARNING
Definition: logger.h:144
char buf[PHONE_MAX_BUF]
Definition: chan_phone.c:136
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
static struct ast_channel* phone_new ( struct phone_pvt i,
int  state,
char *  cntx,
const char *  linkedid 
)
static

Definition at line 848 of file chan_phone.c.

References ast_channel_alloc(), ast_channel_set_fd(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, cur_tech, phone_pvt::dev, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, LOG_WARNING, phone_pvt::mode, MODE_FXS, phone_pvt::owner, prefformat, and ast_module_info::self.

Referenced by phone_check_exception(), and phone_request().

849 {
850  struct ast_channel *tmp;
851  struct phone_codec_data queried_codec;
852  tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5);
853  if (tmp) {
854  tmp->tech = cur_tech;
855  ast_channel_set_fd(tmp, 0, i->fd);
856  /* XXX Switching formats silently causes kernel panics XXX */
857  if (i->mode == MODE_FXS &&
858  ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) {
859  if (queried_codec.type == LINEAR16)
860  tmp->nativeformats =
861  tmp->rawreadformat =
862  tmp->rawwriteformat =
864  else {
865  tmp->nativeformats =
866  tmp->rawreadformat =
867  tmp->rawwriteformat =
869  }
870  }
871  else {
872  tmp->nativeformats = prefformat;
873  tmp->rawreadformat = prefformat;
874  tmp->rawwriteformat = prefformat;
875  }
876  /* no need to call ast_setstate: the channel_alloc already did its job */
877  if (state == AST_STATE_RING)
878  tmp->rings = 1;
879  tmp->tech_pvt = i;
880  ast_copy_string(tmp->context, cntx, sizeof(tmp->context));
881  if (!ast_strlen_zero(i->ext))
882  ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
883  else
884  strcpy(tmp->exten, "s");
885  if (!ast_strlen_zero(i->language))
887 
888  /* Don't use ast_set_callerid() here because it will
889  * generate a NewCallerID event before the NewChannel event */
890  if (!ast_strlen_zero(i->cid_num)) {
891  tmp->caller.ani.number.valid = 1;
892  tmp->caller.ani.number.str = ast_strdup(i->cid_num);
893  }
894 
895  i->owner = tmp;
897  if (state != AST_STATE_DOWN) {
898  if (state == AST_STATE_RING) {
899  ioctl(tmp->fds[0], PHONE_RINGBACK);
900  i->cpt = 1;
901  }
902  if (ast_pbx_start(tmp)) {
903  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
904  ast_hangup(tmp);
905  }
906  }
907  } else
908  ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
909  return tmp;
910 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_strdup(a)
Definition: astmm.h:109
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
static char language[MAX_LANGUAGE]
Definition: chan_phone.c:92
static struct ast_channel_tech * cur_tech
Definition: chan_phone.c:202
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct ast_channel * owner
Definition: chan_phone.c:127
struct ast_module * self
Definition: module.h:227
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char language[MAX_LANGUAGE]
Definition: chan_phone.c:146
char ext[AST_MAX_EXTENSION]
Definition: chan_phone.c:145
char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:143
char dev[256]
Definition: chan_phone.c:132
char cid_num[AST_MAX_EXTENSION]
Definition: chan_phone.c:147
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define MODE_FXS
Definition: chan_phone.c:122
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char cid_name[AST_MAX_EXTENSION]
Definition: chan_phone.c:148
static format_t prefformat
Definition: chan_phone.c:98
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static struct ast_frame * phone_read ( struct ast_channel ast)
static

Definition at line 549 of file chan_phone.c.

References ast_clear_flag, AST_FLAG_BLOCKING, AST_FORMAT_AUDIO_MASK, AST_FORMAT_PNG, AST_FORMAT_SLINEAR, ast_frame_byteswap_le, AST_FRAME_IMAGE, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_tv(), phone_pvt::buf, CHECK_BLOCKING, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, phone_pvt::fd, phone_pvt::fr, ast_frame::frametype, phone_pvt::lastinput, LOG_WARNING, ast_frame::mallocd, phone_pvt::mode, MODE_FXS, ast_frame::offset, PHONE_MAX_BUF, ast_frame::ptr, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_channel::tech_pvt.

550 {
551  int res;
552  struct phone_pvt *p = ast->tech_pvt;
553 
554 
555  /* Some nice norms */
556  p->fr.datalen = 0;
557  p->fr.samples = 0;
558  p->fr.data.ptr = NULL;
559  p->fr.src = "Phone";
560  p->fr.offset = 0;
561  p->fr.mallocd=0;
562  p->fr.delivery = ast_tv(0,0);
563 
564  /* Try to read some data... */
565  CHECK_BLOCKING(ast);
566  res = read(p->fd, p->buf, PHONE_MAX_BUF);
568  if (res < 0) {
569 #if 0
570  if (errno == EAGAIN) {
571  ast_log(LOG_WARNING, "Null frame received\n");
573  p->fr.subclass = 0;
574  return &p->fr;
575  }
576 #endif
577  ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));
578  return NULL;
579  }
580  p->fr.data.ptr = p->buf;
581  if (p->mode != MODE_FXS)
582  switch(p->buf[0] & 0x3) {
583  case '0':
584  case '1':
585  /* Normal */
586  break;
587  case '2':
588  case '3':
589  /* VAD/CNG, only send two words */
590  res = 4;
591  break;
592  }
593  p->fr.samples = 240;
594  p->fr.datalen = res;
596  AST_FRAME_VOICE :
598  : AST_FRAME_VIDEO;
599  p->fr.subclass.codec = p->lastinput;
601  /* Byteswap from little-endian to native-endian */
604  return &p->fr;
605 }
union ast_frame_subclass subclass
Definition: frame.h:146
int offset
Definition: frame.h:156
void * ptr
Definition: frame.h:160
#define ast_frame_byteswap_le(fr)
Definition: frame.h:615
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
#define PHONE_MAX_BUF
Definition: chan_phone.c:82
format_t lastinput
Definition: chan_phone.c:130
format_t codec
Definition: frame.h:137
struct ast_frame fr
Definition: chan_phone.c:134
char buf[PHONE_MAX_BUF]
Definition: chan_phone.c:136
#define AST_FORMAT_PNG
Definition: frame.h:278
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
const char * src
Definition: frame.h:158
int datalen
Definition: frame.h:148
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define AST_FORMAT_AUDIO_MASK
Definition: frame.h:274
#define MODE_FXS
Definition: chan_phone.c:122
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct timeval delivery
Definition: frame.h:162
int mallocd
Definition: frame.h:152
#define CHECK_BLOCKING(c)
Definition: channel.h:2427
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
enum ast_frame_type frametype
Definition: frame.h:144
union ast_frame::@172 data
int samples
Definition: frame.h:150
static struct ast_channel * phone_request ( const char *  type,
format_t  format,
const struct ast_channel requestor,
void *  data,
int *  cause 
)
static

Definition at line 1237 of file chan_phone.c.

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

1238 {
1239  format_t oldformat;
1240  struct phone_pvt *p;
1241  struct ast_channel *tmp = NULL;
1242  char *name = data;
1243 
1244  /* Search for an unowned channel */
1245  if (ast_mutex_lock(&iflock)) {
1246  ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1247  return NULL;
1248  }
1249  p = iflist;
1250  while(p) {
1251  if (p->mode == MODE_FXS ||
1253  size_t length = strlen(p->dev + 5);
1254  if (strncmp(name, p->dev + 5, length) == 0 &&
1255  !isalnum(name[length])) {
1256  if (!p->owner) {
1257  tmp = phone_new(p, AST_STATE_DOWN, p->context, requestor ? requestor->linkedid : NULL);
1258  break;
1259  } else
1260  *cause = AST_CAUSE_BUSY;
1261  }
1262  }
1263  p = p->next;
1264  }
1266  restart_monitor();
1267  if (tmp == NULL) {
1268  oldformat = format;
1270  if (!format) {
1271  char buf[256];
1272  ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat));
1273  return NULL;
1274  }
1275  }
1276  return tmp;
1277 }
Main Channel structure associated with a channel.
Definition: channel.h:742
static ast_mutex_t iflock
Definition: chan_phone.c:101
#define AST_FORMAT_G723_1
Definition: frame.h:242
struct phone_pvt * next
Definition: chan_phone.c:133
static int restart_monitor(void)
Definition: chan_phone.c:1139
#define ast_mutex_lock(a)
Definition: lock.h:155
const char * data
Definition: channel.h:755
const ast_string_field linkedid
Definition: channel.h:787
#define AST_FORMAT_G729A
Definition: frame.h:258
struct ast_channel * owner
Definition: chan_phone.c:127
#define LOG_ERROR
Definition: logger.h:155
char context[AST_MAX_EXTENSION]
Definition: chan_phone.c:143
int64_t format_t
Definition: frame_defs.h:32
#define AST_FORMAT_ULAW
Definition: frame.h:246
char dev[256]
Definition: chan_phone.c:132
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static const char name[]
#define MODE_FXS
Definition: chan_phone.c:122
static struct phone_pvt * iflist
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
static struct ast_channel * phone_new(struct phone_pvt *i, int state, char *cntx, const char *linkedid)
Definition: chan_phone.c:848
#define AST_CAUSE_BUSY
Definition: causes.h:148
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
static snd_pcm_format_t format
Definition: chan_alsa.c:93
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int phone_send_text ( struct ast_channel ast,
const char *  text 
)
static

Definition at line 641 of file chan_phone.c.

References phone_write_buf(), and ast_channel::tech_pvt.

642 {
643  int length = strlen(text);
644  return phone_write_buf(ast->tech_pvt, text, length, length, 0) ==
645  length ? 0 : -1;
646 }
static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
Definition: chan_phone.c:607
void * tech_pvt
Definition: channel.h:744
char * text
Definition: app_queue.c:1091
static int phone_setup ( struct ast_channel ast)
static

Definition at line 390 of file chan_phone.c.

References AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_getformatname(), ast_log(), phone_pvt::fd, phone_pvt::lastinput, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_channel::rawreadformat, and ast_channel::tech_pvt.

Referenced by phone_answer(), phone_exception(), and phone_write().

391 {
392  struct phone_pvt *p;
393  p = ast->tech_pvt;
394  ioctl(p->fd, PHONE_CPT_STOP);
395  /* Nothing to answering really, just start recording */
396  if (ast->rawreadformat == AST_FORMAT_G729A) {
397  /* Prefer g729 */
398  ioctl(p->fd, PHONE_REC_STOP);
399  if (p->lastinput != AST_FORMAT_G729A) {
401  if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
402  ast_log(LOG_WARNING, "Failed to set codec to g729\n");
403  return -1;
404  }
405  }
406  } else if (ast->rawreadformat == AST_FORMAT_G723_1) {
407  ioctl(p->fd, PHONE_REC_STOP);
408  if (p->lastinput != AST_FORMAT_G723_1) {
410  if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
411  ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
412  return -1;
413  }
414  }
415  } else if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
416  ioctl(p->fd, PHONE_REC_STOP);
417  if (p->lastinput != AST_FORMAT_SLINEAR) {
419  if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
420  ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
421  return -1;
422  }
423  }
424  } else if (ast->rawreadformat == AST_FORMAT_ULAW) {
425  ioctl(p->fd, PHONE_REC_STOP);
426  if (p->lastinput != AST_FORMAT_ULAW) {
428  if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
429  ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
430  return -1;
431  }
432  }
433  } else if (p->mode == MODE_FXS) {
434  ioctl(p->fd, PHONE_REC_STOP);
435  if (p->lastinput != ast->rawreadformat) {
436  p->lastinput = ast->rawreadformat;
437  if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) {
438  ast_log(LOG_WARNING, "Failed to set codec to %s\n",
440  return -1;
441  }
442  }
443  } else {
444  ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat));
445  return -1;
446  }
447  if (ioctl(p->fd, PHONE_REC_START)) {
448  ast_log(LOG_WARNING, "Failed to start recording\n");
449  return -1;
450  }
451  /* set the DTMF times (the default is too short) */
452  ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300);
453  ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200);
454  return 0;
455 }
#define AST_FORMAT_G723_1
Definition: frame.h:242
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
format_t lastinput
Definition: chan_phone.c:130
format_t rawreadformat
Definition: channel.h:855
#define AST_FORMAT_G729A
Definition: frame.h:258
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define AST_FORMAT_ULAW
Definition: frame.h:246
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define MODE_FXS
Definition: chan_phone.c:122
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
static int phone_write ( struct ast_channel ast,
struct ast_frame frame 
)
static

Definition at line 648 of file chan_phone.c.

References ast_channel::_state, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_setstate(), AST_STATE_UP, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, errno, phone_pvt::fd, ast_frame::frametype, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::mode, MODE_FXS, phone_pvt::obuflen, phone_setup(), phone_write_buf(), ast_frame::ptr, phone_pvt::silencesupression, ast_frame::subclass, and ast_channel::tech_pvt.

649 {
650  struct phone_pvt *p = ast->tech_pvt;
651  int res;
652  int maxfr=0;
653  char *pos;
654  int sofar;
655  int expected;
656  int codecset = 0;
657  char tmpbuf[4];
658  /* Write a frame of (presumably voice) data */
659  if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {
660  if (frame->frametype != AST_FRAME_IMAGE)
661  ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
662  return 0;
663  }
664  if (!(frame->subclass.codec &
666  p->mode != MODE_FXS) {
667  ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
668  return -1;
669  }
670 #if 0
671  /* If we're not in up mode, go into up mode now */
672  if (ast->_state != AST_STATE_UP) {
674  phone_setup(ast);
675  }
676 #else
677  if (ast->_state != AST_STATE_UP) {
678  /* Don't try tos end audio on-hook */
679  return 0;
680  }
681 #endif
682  if (frame->subclass.codec == AST_FORMAT_G729A) {
683  if (p->lastformat != AST_FORMAT_G729A) {
684  ioctl(p->fd, PHONE_PLAY_STOP);
685  ioctl(p->fd, PHONE_REC_STOP);
686  if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
687  ast_log(LOG_WARNING, "Unable to set G729 mode\n");
688  return -1;
689  }
690  if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
691  ast_log(LOG_WARNING, "Unable to set G729 mode\n");
692  return -1;
693  }
696  /* Reset output buffer */
697  p->obuflen = 0;
698  codecset = 1;
699  }
700  if (frame->datalen > 80) {
701  ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen);
702  return -1;
703  }
704  maxfr = 80;
705  } else if (frame->subclass.codec == AST_FORMAT_G723_1) {
706  if (p->lastformat != AST_FORMAT_G723_1) {
707  ioctl(p->fd, PHONE_PLAY_STOP);
708  ioctl(p->fd, PHONE_REC_STOP);
709  if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
710  ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
711  return -1;
712  }
713  if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
714  ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
715  return -1;
716  }
719  /* Reset output buffer */
720  p->obuflen = 0;
721  codecset = 1;
722  }
723  if (frame->datalen > 24) {
724  ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
725  return -1;
726  }
727  maxfr = 24;
728  } else if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
729  if (p->lastformat != AST_FORMAT_SLINEAR) {
730  ioctl(p->fd, PHONE_PLAY_STOP);
731  ioctl(p->fd, PHONE_REC_STOP);
732  if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
733  ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
734  return -1;
735  }
736  if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
737  ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
738  return -1;
739  }
742  codecset = 1;
743  /* Reset output buffer */
744  p->obuflen = 0;
745  }
746  maxfr = 480;
747  } else if (frame->subclass.codec == AST_FORMAT_ULAW) {
748  if (p->lastformat != AST_FORMAT_ULAW) {
749  ioctl(p->fd, PHONE_PLAY_STOP);
750  ioctl(p->fd, PHONE_REC_STOP);
751  if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
752  ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
753  return -1;
754  }
755  if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
756  ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
757  return -1;
758  }
761  codecset = 1;
762  /* Reset output buffer */
763  p->obuflen = 0;
764  }
765  maxfr = 240;
766  } else {
767  if (p->lastformat != frame->subclass.codec) {
768  ioctl(p->fd, PHONE_PLAY_STOP);
769  ioctl(p->fd, PHONE_REC_STOP);
770  if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.codec)) {
771  ast_log(LOG_WARNING, "Unable to set %s mode\n",
773  return -1;
774  }
775  if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.codec)) {
776  ast_log(LOG_WARNING, "Unable to set %s mode\n",
778  return -1;
779  }
780  p->lastformat = frame->subclass.codec;
781  p->lastinput = frame->subclass.codec;
782  codecset = 1;
783  /* Reset output buffer */
784  p->obuflen = 0;
785  }
786  maxfr = 480;
787  }
788  if (codecset) {
789  ioctl(p->fd, PHONE_REC_DEPTH, 3);
790  ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
791  if (ioctl(p->fd, PHONE_PLAY_START)) {
792  ast_log(LOG_WARNING, "Failed to start playback\n");
793  return -1;
794  }
795  if (ioctl(p->fd, PHONE_REC_START)) {
796  ast_log(LOG_WARNING, "Failed to start recording\n");
797  return -1;
798  }
799  }
800  /* If we get here, we have a frame of Appropriate data */
801  sofar = 0;
802  pos = frame->data.ptr;
803  while(sofar < frame->datalen) {
804  /* Write in no more than maxfr sized frames */
805  expected = frame->datalen - sofar;
806  if (maxfr < expected)
807  expected = maxfr;
808  /* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX
809  we have to pad it to 24 bytes still. */
810  if (frame->datalen == 4) {
811  if (p->silencesupression) {
812  memcpy(tmpbuf, frame->data.ptr, 4);
813  expected = 24;
814  res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
815  }
816  res = 4;
817  expected=4;
818  } else {
819  int swap = 0;
820 #if __BYTE_ORDER == __BIG_ENDIAN
821  if (frame->subclass.codec == AST_FORMAT_SLINEAR)
822  swap = 1; /* Swap big-endian samples to little-endian as we copy */
823 #endif
824  res = phone_write_buf(p, pos, expected, maxfr, swap);
825  }
826  if (res != expected) {
827  if ((errno != EAGAIN) && (errno != EINTR)) {
828  if (res < 0)
829  ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
830  /*
831  * Card is in non-blocking mode now and it works well now, but there are
832  * lot of messages like this. So, this message is temporarily disabled.
833  */
834 #if 0
835  else
836  ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
837 #endif
838  return -1;
839  } else /* Pretend it worked */
840  res = expected;
841  }
842  sofar += res;
843  pos += res;
844  }
845  return 0;
846 }
union ast_frame_subclass subclass
Definition: frame.h:146
static int phone_setup(struct ast_channel *ast)
Definition: chan_phone.c:390
static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
Definition: chan_phone.c:607
#define AST_FORMAT_G723_1
Definition: frame.h:242
void * ptr
Definition: frame.h:160
void * tech_pvt
Definition: channel.h:744
int silencesupression
Definition: chan_phone.c:142
#define LOG_WARNING
Definition: logger.h:144
format_t lastinput
Definition: chan_phone.c:130
format_t codec
Definition: frame.h:137
#define AST_FORMAT_G729A
Definition: frame.h:258
int datalen
Definition: frame.h:148
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define AST_FORMAT_ULAW
Definition: frame.h:246
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define MODE_FXS
Definition: chan_phone.c:122
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
format_t lastformat
Definition: chan_phone.c:129
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
enum ast_frame_type frametype
Definition: frame.h:144
int obuflen
Definition: chan_phone.c:137
union ast_frame::@172 data
static int phone_write_buf ( struct phone_pvt p,
const char *  buf,
int  len,
int  frlen,
int  swap 
)
static

Definition at line 607 of file chan_phone.c.

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

Referenced by phone_send_text(), and phone_write().

608 {
609  int res;
610  /* Store as much of the buffer as we can, then write fixed frames */
611  int space = sizeof(p->obuf) - p->obuflen;
612  /* Make sure we have enough buffer space to store the frame */
613  if (space < len)
614  len = space;
615  if (swap)
617  else
618  memcpy(p->obuf + p->obuflen, buf, len);
619  p->obuflen += len;
620  while(p->obuflen > frlen) {
621  res = write(p->fd, p->obuf, frlen);
622  if (res != frlen) {
623  if (res < 1) {
624 /*
625  * Card is in non-blocking mode now and it works well now, but there are
626  * lot of messages like this. So, this message is temporarily disabled.
627  */
628  return 0;
629  } else {
630  ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);
631  }
632  }
633  p->obuflen -= frlen;
634  /* Move memory if necessary */
635  if (p->obuflen)
636  memmove(p->obuf, p->obuf + frlen, p->obuflen);
637  }
638  return len;
639 }
#define LOG_WARNING
Definition: logger.h:144
char buf[PHONE_MAX_BUF]
Definition: chan_phone.c:136
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
char obuf[PHONE_MAX_BUF *2]
Definition: chan_phone.c:144
int obuflen
Definition: chan_phone.c:137
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: frame.c:556
static int restart_monitor ( void  )
static

Definition at line 1139 of file chan_phone.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), iflock, LOG_ERROR, LOG_WARNING, and monlock.

Referenced by load_module(), phone_hangup(), and phone_request().

1140 {
1141  /* If we're supposed to be stopped -- stay stopped */
1143  return 0;
1144  if (ast_mutex_lock(&monlock)) {
1145  ast_log(LOG_WARNING, "Unable to lock monitor\n");
1146  return -1;
1147  }
1148  if (monitor_thread == pthread_self()) {
1150  ast_log(LOG_WARNING, "Cannot kill myself\n");
1151  return -1;
1152  }
1154  if (ast_mutex_lock(&iflock)) {
1156  ast_log(LOG_WARNING, "Unable to lock the interface list\n");
1157  return -1;
1158  }
1159  monitor = 0;
1160  while (pthread_kill(monitor_thread, SIGURG) == 0)
1161  sched_yield();
1162  pthread_join(monitor_thread, NULL);
1164  }
1165  monitor = 1;
1166  /* Start a new monitor */
1167  if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
1169  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
1170  return -1;
1171  }
1173  return 0;
1174 }
static pthread_t monitor_thread
Definition: chan_phone.c:112
static void * do_monitor(void *data)
Definition: chan_phone.c:1017
static ast_mutex_t iflock
Definition: chan_phone.c:101
#define LOG_WARNING
Definition: logger.h:144
#define ast_mutex_lock(a)
Definition: lock.h:155
static ast_mutex_t monlock
Definition: chan_phone.c:105
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define LOG_ERROR
Definition: logger.h:155
static unsigned int monitor
Definition: chan_phone.c:108
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_PTHREADT_STOP
Definition: lock.h:66
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int unload_module ( void  )
static

Definition at line 1358 of file chan_phone.c.

References __unload_module().

1359 {
1360  return __unload_module();
1361 }
static int __unload_module(void)
Definition: chan_phone.c:1302

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Linux Telephony API Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 1479 of file chan_phone.c.

Definition at line 1479 of file chan_phone.c.

char cid_name[AST_MAX_EXTENSION]
static

Definition at line 152 of file chan_phone.c.

char cid_num[AST_MAX_EXTENSION]
static

Definition at line 151 of file chan_phone.c.

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

Definition at line 86 of file chan_phone.c.

char context[AST_MAX_EXTENSION] = "default"
static

Definition at line 89 of file chan_phone.c.

struct ast_channel_tech* cur_tech
static

Definition at line 202 of file chan_phone.c.

Referenced by phone_new().

int echocancel = AEC_OFF
static

Definition at line 94 of file chan_phone.c.

struct phone_pvt * iflist = NULL
static
ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static
char language[MAX_LANGUAGE] = ""
static

Definition at line 92 of file chan_phone.c.

pthread_t monitor_thread = AST_PTHREADT_NULL
static

Definition at line 112 of file chan_phone.c.

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static

Definition at line 105 of file chan_phone.c.

Referenced by __unload_module(), and restart_monitor().

struct ast_channel_tech phone_tech
static

Definition at line 167 of file chan_phone.c.

struct ast_channel_tech phone_tech_fxs
static

Definition at line 184 of file chan_phone.c.

Referenced by load_module().

Definition at line 98 of file chan_phone.c.

Referenced by load_module(), and phone_new().

int silencesupression = 0
static

Definition at line 96 of file chan_phone.c.

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

Definition at line 85 of file chan_phone.c.