#include "asterisk.h"
#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 <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/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 "asterisk/stringfields.h"
#include "asterisk/musiconhold.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 | MODE_SIGMA 5 |
| #define | PHONE_MAX_BUF 480 |
| #define | QNDRV_VER 100 |
Functions | |
| static int | __unload_module (void) |
| AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Linux Telephony API Support") | |
| AST_MUTEX_DEFINE_STATIC (monlock) | |
| AST_MUTEX_DEFINE_STATIC (iflock) | |
| static void * | do_monitor (void *data) |
| static int | load_module (void) |
| static struct phone_pvt * | mkif (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_begin (struct ast_channel *ast, char digit) |
| static int | phone_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static struct ast_frame * | phone_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_channel * | phone_new (struct phone_pvt *i, int state, char *context) |
| static struct ast_frame * | phone_read (struct ast_channel *ast) |
| static struct ast_channel * | phone_request (const char *type, int format, void *data, int *cause) |
| static int | phone_send_text (struct ast_channel *ast, const char *text) |
| static int | phone_setup (struct ast_channel *ast) |
| static int | phone_write (struct ast_channel *ast, struct ast_frame *frame) |
| static int | phone_write_buf (struct phone_pvt *p, const char *buf, int len, int frlen, int swap) |
| static int | restart_monitor (void) |
| static int | unload_module (void) |
Variables | |
| static 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_tech * | cur_tech |
| static int | echocancel = AEC_OFF |
| static struct phone_pvt * | iflist |
| static char | language [MAX_LANGUAGE] = "" |
| static unsigned int | monitor |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| static struct ast_channel_tech | phone_tech |
| static struct ast_channel_tech | phone_tech_fxs |
| static int | prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW |
| static int | silencesupression = 0 |
| static const char | tdesc [] = "Standard Linux Telephony API Driver" |
Definition in file chan_phone.c.
| #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 |
Definition at line 125 of file chan_phone.c.
Referenced by load_module(), and phone_check_exception().
| #define MODE_FXO 3 |
Definition at line 127 of file chan_phone.c.
Referenced by load_module(), mkif(), phone_answer(), phone_exception(), and phone_hangup().
| #define MODE_FXS 4 |
Definition at line 128 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 126 of file chan_phone.c.
Referenced by load_module(), and phone_check_exception().
| #define MODE_SIGMA 5 |
Definition at line 129 of file chan_phone.c.
Referenced by do_monitor(), load_module(), and phone_check_exception().
| #define PHONE_MAX_BUF 480 |
| #define QNDRV_VER 100 |
Definition at line 74 of file chan_phone.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 1263 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.
01264 { 01265 struct phone_pvt *p, *pl; 01266 /* First, take us out of the channel loop */ 01267 if (cur_tech) 01268 ast_channel_unregister(cur_tech); 01269 if (!ast_mutex_lock(&iflock)) { 01270 /* Hangup all interfaces if they have an owner */ 01271 p = iflist; 01272 while(p) { 01273 if (p->owner) 01274 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01275 p = p->next; 01276 } 01277 iflist = NULL; 01278 ast_mutex_unlock(&iflock); 01279 } else { 01280 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01281 return -1; 01282 } 01283 if (!ast_mutex_lock(&monlock)) { 01284 if (monitor_thread > AST_PTHREADT_NULL) { 01285 monitor = 0; 01286 while (pthread_kill(monitor_thread, SIGURG) == 0) 01287 sched_yield(); 01288 pthread_join(monitor_thread, NULL); 01289 } 01290 monitor_thread = AST_PTHREADT_STOP; 01291 ast_mutex_unlock(&monlock); 01292 } else { 01293 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01294 return -1; 01295 } 01296 01297 if (!ast_mutex_lock(&iflock)) { 01298 /* Destroy all the interfaces and free their memory */ 01299 p = iflist; 01300 while(p) { 01301 /* Close the socket, assuming it's real */ 01302 if (p->fd > -1) 01303 close(p->fd); 01304 pl = p; 01305 p = p->next; 01306 /* Free associated memory */ 01307 free(pl); 01308 } 01309 iflist = NULL; 01310 ast_mutex_unlock(&iflock); 01311 } else { 01312 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01313 return -1; 01314 } 01315 01316 return 0; 01317 }
| AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
| "Linux Telephony API Support" | ||||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | monlock | ) |
| AST_MUTEX_DEFINE_STATIC | ( | iflock | ) |
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 998 of file chan_phone.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), phone_pvt::dev, DialTone, phone_pvt::dialtone, errno, phone_pvt::fd, iflist, LOG_DEBUG, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, phone_pvt::owner, phone_check_exception(), and phone_mini_packet().
00999 { 01000 fd_set rfds, efds; 01001 int n, res; 01002 struct phone_pvt *i; 01003 int tonepos = 0; 01004 /* The tone we're playing this round */ 01005 struct timeval tv = {0,0}; 01006 int dotone; 01007 /* This thread monitors all the frame relay interfaces which are not yet in use 01008 (and thus do not have a separate thread) indefinitely */ 01009 while (monitor) { 01010 /* Don't let anybody kill us right away. Nobody should lock the interface list 01011 and wait for the monitor list, but the other way around is okay. */ 01012 /* Lock the interface list */ 01013 if (ast_mutex_lock(&iflock)) { 01014 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 01015 return NULL; 01016 } 01017 /* Build the stuff we're going to select on, that is the socket of every 01018 phone_pvt that does not have an associated owner channel */ 01019 n = -1; 01020 FD_ZERO(&rfds); 01021 FD_ZERO(&efds); 01022 i = iflist; 01023 dotone = 0; 01024 while (i) { 01025 if (FD_ISSET(i->fd, &rfds)) 01026 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 01027 if (!i->owner) { 01028 /* This needs to be watched, as it lacks an owner */ 01029 FD_SET(i->fd, &rfds); 01030 FD_SET(i->fd, &efds); 01031 if (i->fd > n) 01032 n = i->fd; 01033 if (i->dialtone && i->mode != MODE_SIGMA) { 01034 /* Remember we're going to have to come back and play 01035 more dialtones */ 01036 if (ast_tvzero(tv)) { 01037 /* If we're due for a dialtone, play one */ 01038 if (write(i->fd, DialTone + tonepos, 240) != 240) 01039 ast_log(LOG_WARNING, "Dial tone write error\n"); 01040 } 01041 dotone++; 01042 } 01043 } 01044 01045 i = i->next; 01046 } 01047 /* Okay, now that we know what to do, release the interface lock */ 01048 ast_mutex_unlock(&iflock); 01049 01050 /* Wait indefinitely for something to happen */ 01051 if (dotone && i && i->mode != MODE_SIGMA) { 01052 /* If we're ready to recycle the time, set it to 30 ms */ 01053 tonepos += 240; 01054 if (tonepos >= sizeof(DialTone)) 01055 tonepos = 0; 01056 if (ast_tvzero(tv)) { 01057 tv = ast_tv(30000, 0); 01058 } 01059 res = ast_select(n + 1, &rfds, NULL, &efds, &tv); 01060 } else { 01061 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 01062 tv = ast_tv(0,0); 01063 tonepos = 0; 01064 } 01065 /* Okay, select has finished. Let's see what happened. */ 01066 if (res < 0) { 01067 ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno)); 01068 continue; 01069 } 01070 /* If there are no fd's changed, just continue, it's probably time 01071 to play some more dialtones */ 01072 if (!res) 01073 continue; 01074 /* Alright, lock the interface list again, and let's look and see what has 01075 happened */ 01076 if (ast_mutex_lock(&iflock)) { 01077 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01078 continue; 01079 } 01080 01081 i = iflist; 01082 for(; i; i=i->next) { 01083 if (FD_ISSET(i->fd, &rfds)) { 01084 if (i->owner) { 01085 continue; 01086 } 01087 phone_mini_packet(i); 01088 } 01089 if (FD_ISSET(i->fd, &efds)) { 01090 if (i->owner) { 01091 continue; 01092 } 01093 phone_check_exception(i); 01094 } 01095 } 01096 ast_mutex_unlock(&iflock); 01097 } 01098 return NULL; 01099 01100 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1324 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_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, cur_tech, DEFAULT_GAIN, iflist, 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, phone_tech_fxs, restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.
01325 { 01326 struct ast_config *cfg; 01327 struct ast_variable *v; 01328 struct phone_pvt *tmp; 01329 int mode = MODE_IMMEDIATE; 01330 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01331 cfg = ast_config_load(config); 01332 01333 /* We *must* have a config file otherwise stop immediately */ 01334 if (!cfg) { 01335 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01336 return AST_MODULE_LOAD_DECLINE; 01337 } 01338 if (ast_mutex_lock(&iflock)) { 01339 /* It's a little silly to lock it, but we mind as well just to be sure */ 01340 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01341 return AST_MODULE_LOAD_FAILURE; 01342 } 01343 v = ast_variable_browse(cfg, "interfaces"); 01344 while(v) { 01345 /* Create the interface list */ 01346 if (!strcasecmp(v->name, "device")) { 01347 tmp = mkif(v->value, mode, txgain, rxgain); 01348 if (tmp) { 01349 tmp->next = iflist; 01350 iflist = tmp; 01351 01352 } else { 01353 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01354 ast_config_destroy(cfg); 01355 ast_mutex_unlock(&iflock); 01356 __unload_module(); 01357 return AST_MODULE_LOAD_FAILURE; 01358 } 01359 } else if (!strcasecmp(v->name, "silencesupression")) { 01360 silencesupression = ast_true(v->value); 01361 } else if (!strcasecmp(v->name, "language")) { 01362 ast_copy_string(language, v->value, sizeof(language)); 01363 } else if (!strcasecmp(v->name, "callerid")) { 01364 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01365 } else if (!strcasecmp(v->name, "mode")) { 01366 if (!strncasecmp(v->value, "di", 2)) 01367 mode = MODE_DIALTONE; 01368 else if (!strncasecmp(v->value, "sig", 3)) 01369 mode = MODE_SIGMA; 01370 else if (!strncasecmp(v->value, "im", 2)) 01371 mode = MODE_IMMEDIATE; 01372 else if (!strncasecmp(v->value, "fxs", 3)) { 01373 mode = MODE_FXS; 01374 prefformat = 0x01ff0000; /* All non-voice */ 01375 } 01376 else if (!strncasecmp(v->value, "fx", 2)) 01377 mode = MODE_FXO; 01378 else 01379 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01380 } else if (!strcasecmp(v->name, "context")) { 01381 ast_copy_string(context, v->value, sizeof(context)); 01382 } else if (!strcasecmp(v->name, "format")) { 01383 if (!strcasecmp(v->value, "g723.1")) { 01384 prefformat = AST_FORMAT_G723_1; 01385 } else if (!strcasecmp(v->value, "slinear")) { 01386 if (mode == MODE_FXS) 01387 prefformat |= AST_FORMAT_SLINEAR; 01388 else prefformat = AST_FORMAT_SLINEAR; 01389 } else if (!strcasecmp(v->value, "ulaw")) { 01390 prefformat = AST_FORMAT_ULAW; 01391 } else 01392 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01393 } else if (!strcasecmp(v->name, "echocancel")) { 01394 if (!strcasecmp(v->value, "off")) { 01395 echocancel = AEC_OFF; 01396 } else if (!strcasecmp(v->value, "low")) { 01397 echocancel = AEC_LOW; 01398 } else if (!strcasecmp(v->value, "medium")) { 01399 echocancel = AEC_MED; 01400 } else if (!strcasecmp(v->value, "high")) { 01401 echocancel = AEC_HIGH; 01402 } else 01403 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01404 } else if (!strcasecmp(v->name, "txgain")) { 01405 txgain = parse_gain_value(v->name, v->value); 01406 } else if (!strcasecmp(v->name, "rxgain")) { 01407 rxgain = parse_gain_value(v->name, v->value); 01408 } 01409 v = v->next; 01410 } 01411 ast_mutex_unlock(&iflock); 01412 01413 if (mode == MODE_FXS) { 01414 phone_tech_fxs.capabilities = prefformat; 01415 cur_tech = &phone_tech_fxs; 01416 } else 01417 cur_tech = (struct ast_channel_tech *) &phone_tech; 01418 01419 /* Make sure we can register our Adtranphone channel type */ 01420 01421 if (ast_channel_register(cur_tech)) { 01422 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n"); 01423 ast_config_destroy(cfg); 01424 __unload_module(); 01425 return AST_MODULE_LOAD_FAILURE; 01426 } 01427 ast_config_destroy(cfg); 01428 /* And start the monitor for the first time */ 01429 restart_monitor(); 01430 return AST_MODULE_LOAD_SUCCESS; 01431 }
| static struct phone_pvt* mkif | ( | char * | iface, | |
| int | mode, | |||
| int | txgain, | |||
| int | rxgain | |||
| ) | [static] |
Definition at line 1139 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, errno, 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.
Referenced by load_module().
01140 { 01141 /* Make a phone_pvt structure for this interface */ 01142 struct phone_pvt *tmp; 01143 int flags; 01144 01145 tmp = malloc(sizeof(struct phone_pvt)); 01146 if (tmp) { 01147 tmp->fd = open(iface, O_RDWR); 01148 if (tmp->fd < 0) { 01149 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 01150 free(tmp); 01151 return NULL; 01152 } 01153 if (mode == MODE_FXO) { 01154 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) 01155 ast_log(LOG_DEBUG, "Unable to set port to PSTN\n"); 01156 } else { 01157 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01158 if (mode != MODE_FXS) 01159 ast_log(LOG_DEBUG, "Unable to set port to POTS\n"); 01160 } 01161 ioctl(tmp->fd, PHONE_PLAY_STOP); 01162 ioctl(tmp->fd, PHONE_REC_STOP); 01163 ioctl(tmp->fd, PHONE_RING_STOP); 01164 ioctl(tmp->fd, PHONE_CPT_STOP); 01165 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 01166 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01167 if (echocancel != AEC_OFF) 01168 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01169 if (silencesupression) 01170 tmp->silencesupression = 1; 01171 #ifdef PHONE_VAD 01172 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01173 #endif 01174 tmp->mode = mode; 01175 flags = fcntl(tmp->fd, F_GETFL); 01176 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01177 tmp->owner = NULL; 01178 tmp->lastformat = -1; 01179 tmp->lastinput = -1; 01180 tmp->ministate = 0; 01181 memset(tmp->ext, 0, sizeof(tmp->ext)); 01182 ast_copy_string(tmp->language, language, sizeof(tmp->language)); 01183 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev)); 01184 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01185 tmp->next = NULL; 01186 tmp->obuflen = 0; 01187 tmp->dialtone = 0; 01188 tmp->cpt = 0; 01189 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num)); 01190 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name)); 01191 tmp->txgain = txgain; 01192 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01193 tmp->rxgain = rxgain; 01194 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01195 } 01196 return tmp; 01197 }
| static int parse_gain_value | ( | char * | gain_type, | |
| char * | value | |||
| ) | [static] |
Definition at line 1241 of file chan_phone.c.
References ast_log(), DEFAULT_GAIN, and LOG_ERROR.
Referenced by load_module().
01242 { 01243 float gain; 01244 01245 /* try to scan number */ 01246 if (sscanf(value, "%f", &gain) != 1) 01247 { 01248 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01249 value, gain_type, config); 01250 return DEFAULT_GAIN; 01251 } 01252 01253 /* multiplicate gain by 1.0 gain value */ 01254 gain = gain * (float)DEFAULT_GAIN; 01255 01256 /* percentage? */ 01257 if (value[strlen(value) - 1] == '%') 01258 return (int)(gain / (float)100); 01259 01260 return (int)gain; 01261 }
| static int phone_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 458 of file chan_phone.c.
References ast_log(), ast_setstate(), AST_STATE_UP, errno, phone_pvt::fd, LOG_DEBUG, phone_pvt::mode, MODE_FXO, option_debug, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt.
00459 { 00460 struct phone_pvt *p; 00461 p = ast->tech_pvt; 00462 /* In case it's a LineJack, take it off hook */ 00463 if (p->mode == MODE_FXO) { 00464 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 00465 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno)); 00466 else 00467 ast_log(LOG_DEBUG, "Took linejack off hook\n"); 00468 } 00469 phone_setup(ast); 00470 if (option_debug) 00471 ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name); 00472 ast->rings = 0; 00473 ast_setstate(ast, AST_STATE_UP); 00474 return 0; 00475 }
| static int phone_call | ( | struct ast_channel * | ast, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 294 of file chan_phone.c.
References ast_channel::_state, AST_CONTROL_RINGING, ast_localtime(), 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, option_debug, phone_digit_end(), and ast_channel::tech_pvt.
00295 { 00296 struct phone_pvt *p; 00297 00298 PHONE_CID cid; 00299 time_t UtcTime; 00300 struct tm tm; 00301 int start; 00302 00303 time(&UtcTime); 00304 ast_localtime(&UtcTime, &tm, NULL); 00305 00306 memset(&cid, 0, sizeof(PHONE_CID)); 00307 if(&tm != NULL) { 00308 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1)); 00309 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday); 00310 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour); 00311 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min); 00312 } 00313 /* the standard format of ast->callerid is: "name" <number>, but not always complete */ 00314 if (ast_strlen_zero(ast->cid.cid_name)) 00315 strcpy(cid.name, DEFAULT_CALLER_ID); 00316 else 00317 ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name)); 00318 00319 if (ast->cid.cid_num) 00320 ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number)); 00321 00322 p = ast->tech_pvt; 00323 00324 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00325 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); 00326 return -1; 00327 } 00328 if (option_debug) 00329 ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); 00330 00331 start = IXJ_PHONE_RING_START(cid); 00332 if (start == -1) 00333 return -1; 00334 00335 if (p->mode == MODE_FXS) { 00336 char *digit = strchr(dest, '/'); 00337 if (digit) 00338 { 00339 digit++; 00340 while (*digit) 00341 phone_digit_end(ast, *digit++, 0); 00342 } 00343 } 00344 00345 ast_setstate(ast, AST_STATE_RINGING); 00346 ast_queue_control(ast, AST_CONTROL_RINGING); 00347 return 0; 00348 }
| static void phone_check_exception | ( | struct phone_pvt * | i | ) | [static] |
Definition at line 904 of file chan_phone.c.
References ast_canmatch_extension(), ast_exists_extension(), ast_log(), 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, LOG_DEBUG, phone_pvt::mode, MODE_DIALTONE, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, option_debug, and phone_new().
Referenced by do_monitor().
00905 { 00906 int offhook=0; 00907 char digit[2] = {0 , 0}; 00908 union telephony_exception phonee; 00909 /* XXX Do something XXX */ 00910 #if 0 00911 ast_log(LOG_DEBUG, "Exception!\n"); 00912 #endif 00913 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00914 if (phonee.bits.dtmf_ready) { 00915 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00916 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) { 00917 ioctl(i->fd, PHONE_PLAY_STOP); 00918 ioctl(i->fd, PHONE_REC_STOP); 00919 ioctl(i->fd, PHONE_CPT_STOP); 00920 i->dialtone = 0; 00921 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00922 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00923 if ((i->mode != MODE_FXS || 00924 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00925 !phonee.bits.dtmf_ready) && 00926 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00927 /* It's a valid extension in its context, get moving! */ 00928 phone_new(i, AST_STATE_RING, i->context); 00929 /* No need to restart monitor, we are the monitor */ 00930 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00931 /* There is nothing in the specified extension that can match anymore. 00932 Try the default */ 00933 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00934 /* Check the default, too... */ 00935 phone_new(i, AST_STATE_RING, "default"); 00936 /* XXX This should probably be justified better XXX */ 00937 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00938 /* It's not a valid extension, give a busy signal */ 00939 if (option_debug) 00940 ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context); 00941 ioctl(i->fd, PHONE_BUSY); 00942 i->cpt = 1; 00943 } 00944 } 00945 #if 0 00946 ast_verbose("Extension is %s\n", i->ext); 00947 #endif 00948 } 00949 } 00950 if (phonee.bits.hookstate) { 00951 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00952 if (offhook) { 00953 if (i->mode == MODE_IMMEDIATE) { 00954 phone_new(i, AST_STATE_RING, i->context); 00955 } else if (i->mode == MODE_DIALTONE) { 00956 ast_module_ref(ast_module_info->self); 00957 /* Reset the extension */ 00958 i->ext[0] = '\0'; 00959 /* Play the dialtone */ 00960 i->dialtone++; 00961 ioctl(i->fd, PHONE_PLAY_STOP); 00962 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00963 ioctl(i->fd, PHONE_PLAY_START); 00964 i->lastformat = -1; 00965 } else if (i->mode == MODE_SIGMA) { 00966 ast_module_ref(ast_module_info->self); 00967 /* Reset the extension */ 00968 i->ext[0] = '\0'; 00969 /* Play the dialtone */ 00970 i->dialtone++; 00971 ioctl(i->fd, PHONE_DIALTONE); 00972 } 00973 } else { 00974 if (i->dialtone) 00975 ast_module_unref(ast_module_info->self); 00976 memset(i->ext, 0, sizeof(i->ext)); 00977 if (i->cpt) 00978 { 00979 ioctl(i->fd, PHONE_CPT_STOP); 00980 i->cpt = 0; 00981 } 00982 ioctl(i->fd, PHONE_PLAY_STOP); 00983 ioctl(i->fd, PHONE_REC_STOP); 00984 i->dialtone = 0; 00985 i->lastformat = -1; 00986 } 00987 } 00988 if (phonee.bits.pstn_ring) { 00989 ast_verbose("Unit is ringing\n"); 00990 phone_new(i, AST_STATE_RING, i->context); 00991 } 00992 if (phonee.bits.caller_id) 00993 ast_verbose("We have caller ID\n"); 00994 00995 00996 }
| static int phone_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 246 of file chan_phone.c.
00247 { 00248 /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */ 00249 return 0; 00250 }
| static int phone_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 252 of file chan_phone.c.
References ast_log(), phone_pvt::fd, phone_pvt::lastformat, LOG_DEBUG, LOG_WARNING, and ast_channel::tech_pvt.
Referenced by phone_call().