![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_phone.c File Reference
Definition in file chan_phone.c.
#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) |
| Start the channel monitor thread. | |
| 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 const struct ast_channel_tech | phone_tech |
| static struct ast_channel_tech | phone_tech_fxs |
| static int | 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" |
|
|
Definition at line 84 of file chan_phone.c. Referenced by phone_call(). |
|
|
Definition at line 86 of file chan_phone.c. Referenced by load_module(), and parse_gain_value(). |
|
|
Definition at line 81 of file chan_phone.c. Referenced by phone_call(). |
|
|
Definition at line 122 of file chan_phone.c. Referenced by load_module(), and phone_check_exception(). |
|
|
Definition at line 124 of file chan_phone.c. Referenced by load_module(), mkif(), phone_answer(), phone_exception(), and phone_hangup(). |
|
|
Definition at line 125 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(). |
|
|
Definition at line 123 of file chan_phone.c. Referenced by load_module(), and phone_check_exception(). |
|
|
Definition at line 126 of file chan_phone.c. Referenced by do_monitor(), load_module(), and phone_check_exception(). |
|
|
Definition at line 85 of file chan_phone.c. Referenced by phone_read(). |
|
|
Definition at line 71 of file chan_phone.c. |
|
|
Definition at line 1304 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. 01305 { 01306 struct phone_pvt *p, *pl; 01307 /* First, take us out of the channel loop */ 01308 ast_channel_unregister(cur_tech); 01309 if (!ast_mutex_lock(&iflock)) { 01310 /* Hangup all interfaces if they have an owner */ 01311 p = iflist; 01312 while(p) { 01313 if (p->owner) 01314 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01315 p = p->next; 01316 } 01317 iflist = NULL; 01318 ast_mutex_unlock(&iflock); 01319 } else { 01320 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01321 return -1; 01322 } 01323 if (!ast_mutex_lock(&monlock)) { 01324 if (monitor_thread > AST_PTHREADT_NULL) { 01325 monitor = 0; 01326 while (pthread_kill(monitor_thread, SIGURG) == 0) 01327 sched_yield(); 01328 pthread_join(monitor_thread, NULL); 01329 } 01330 monitor_thread = AST_PTHREADT_STOP; 01331 ast_mutex_unlock(&monlock); 01332 } else { 01333 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01334 return -1; 01335 } 01336 01337 if (!ast_mutex_lock(&iflock)) { 01338 /* Destroy all the interfaces and free their memory */ 01339 p = iflist; 01340 while(p) { 01341 /* Close the socket, assuming it's real */ 01342 if (p->fd > -1) 01343 close(p->fd); 01344 pl = p; 01345 p = p->next; 01346 /* Free associated memory */ 01347 free(pl); 01348 } 01349 iflist = NULL; 01350 ast_mutex_unlock(&iflock); 01351 } else { 01352 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01353 return -1; 01354 } 01355 01356 return 0; 01357 }
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
Definition at line 1034 of file chan_phone.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), phone_pvt::dev, DialTone, phone_pvt::dialtone, phone_pvt::fd, iflist, LOG_DEBUG, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, option_debug, phone_pvt::owner, and phone_mini_packet(). 01035 { 01036 fd_set rfds, efds; 01037 int n, res; 01038 struct phone_pvt *i; 01039 int tonepos = 0; 01040 /* The tone we're playing this round */ 01041 struct timeval tv = {0,0}; 01042 int dotone; 01043 /* This thread monitors all the frame relay interfaces which are not yet in use 01044 (and thus do not have a separate thread) indefinitely */ 01045 while (monitor) { 01046 /* Don't let anybody kill us right away. Nobody should lock the interface list 01047 and wait for the monitor list, but the other way around is okay. */ 01048 /* Lock the interface list */ 01049 if (ast_mutex_lock(&iflock)) { 01050 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 01051 return NULL; 01052 } 01053 /* Build the stuff we're going to select on, that is the socket of every 01054 phone_pvt that does not have an associated owner channel */ 01055 n = -1; 01056 FD_ZERO(&rfds); 01057 FD_ZERO(&efds); 01058 i = iflist; 01059 dotone = 0; 01060 while (i) { 01061 if (FD_ISSET(i->fd, &rfds)) 01062 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 01063 if (!i->owner) { 01064 /* This needs to be watched, as it lacks an owner */ 01065 FD_SET(i->fd, &rfds); 01066 FD_SET(i->fd, &efds); 01067 if (i->fd > n) 01068 n = i->fd; 01069 if (i->dialtone && i->mode != MODE_SIGMA) { 01070 /* Remember we're going to have to come back and play 01071 more dialtones */ 01072 if (ast_tvzero(tv)) { 01073 /* If we're due for a dialtone, play one */ 01074 if (write(i->fd, DialTone + tonepos, 240) != 240) 01075 ast_log(LOG_WARNING, "Dial tone write error\n"); 01076 } 01077 dotone++; 01078 } 01079 } 01080 01081 i = i->next; 01082 } 01083 /* Okay, now that we know what to do, release the interface lock */ 01084 ast_mutex_unlock(&iflock); 01085 01086 /* Wait indefinitely for something to happen */ 01087 if (dotone && i->mode != MODE_SIGMA) { 01088 /* If we're ready to recycle the time, set it to 30 ms */ 01089 tonepos += 240; 01090 if (tonepos >= sizeof(DialTone)) 01091 tonepos = 0; 01092 if (ast_tvzero(tv)) { 01093 tv = ast_tv(30000, 0); 01094 } 01095 res = ast_select(n + 1, &rfds, NULL, &efds, &tv); 01096 } else { 01097 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 01098 tv = ast_tv(0,0); 01099 tonepos = 0; 01100 } 01101 /* Okay, select has finished. Let's see what happened. */ 01102 if (res < 0) { 01103 if (option_debug) 01104 ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno)); 01105 continue; 01106 } 01107 /* If there are no fd's changed, just continue, it's probably time 01108 to play some more dialtones */ 01109 if (!res) 01110 continue; 01111 /* Alright, lock the interface list again, and let's look and see what has 01112 happened */ 01113 if (ast_mutex_lock(&iflock)) { 01114 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01115 continue; 01116 } 01117 01118 i = iflist; 01119 for(; i; i=i->next) { 01120 if (FD_ISSET(i->fd, &rfds)) { 01121 if (i->owner) { 01122 continue; 01123 } 01124 phone_mini_packet(i); 01125 } 01126 if (FD_ISSET(i->fd, &efds)) { 01127 if (i->owner) { 01128 continue; 01129 } 01130 phone_check_exception(i); 01131 } 01132 } 01133 ast_mutex_unlock(&iflock); 01134 } 01135 return NULL; 01136 01137 }
|
|
|
Definition at line 1364 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_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, 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. 01365 { 01366 struct ast_config *cfg; 01367 struct ast_variable *v; 01368 struct phone_pvt *tmp; 01369 int mode = MODE_IMMEDIATE; 01370 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01371 cfg = ast_config_load(config); 01372 01373 /* We *must* have a config file otherwise stop immediately */ 01374 if (!cfg) { 01375 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01376 return AST_MODULE_LOAD_DECLINE; 01377 } 01378 if (ast_mutex_lock(&iflock)) { 01379 /* It's a little silly to lock it, but we mind as well just to be sure */ 01380 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01381 return -1; 01382 } 01383 v = ast_variable_browse(cfg, "interfaces"); 01384 while(v) { 01385 /* Create the interface list */ 01386 if (!strcasecmp(v->name, "device")) { 01387 tmp = mkif(v->value, mode, txgain, rxgain); 01388 if (tmp) { 01389 tmp->next = iflist; 01390 iflist = tmp; 01391 01392 } else { 01393 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01394 ast_config_destroy(cfg); 01395 ast_mutex_unlock(&iflock); 01396 __unload_module(); 01397 return -1; 01398 } 01399 } else if (!strcasecmp(v->name, "silencesupression")) { 01400 silencesupression = ast_true(v->value); 01401 } else if (!strcasecmp(v->name, "language")) { 01402 ast_copy_string(language, v->value, sizeof(language)); 01403 } else if (!strcasecmp(v->name, "callerid")) { 01404 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01405 } else if (!strcasecmp(v->name, "mode")) { 01406 if (!strncasecmp(v->value, "di", 2)) 01407 mode = MODE_DIALTONE; 01408 else if (!strncasecmp(v->value, "sig", 3)) 01409 mode = MODE_SIGMA; 01410 else if (!strncasecmp(v->value, "im", 2)) 01411 mode = MODE_IMMEDIATE; 01412 else if (!strncasecmp(v->value, "fxs", 3)) { 01413 mode = MODE_FXS; 01414 prefformat = 0x01ff0000; /* All non-voice */ 01415 } 01416 else if (!strncasecmp(v->value, "fx", 2)) 01417 mode = MODE_FXO; 01418 else 01419 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01420 } else if (!strcasecmp(v->name, "context")) { 01421 ast_copy_string(context, v->value, sizeof(context)); 01422 } else if (!strcasecmp(v->name, "format")) { 01423 if (!strcasecmp(v->value, "g729")) { 01424 prefformat = AST_FORMAT_G729A; 01425 } else if (!strcasecmp(v->value, "g723.1")) { 01426 prefformat = AST_FORMAT_G723_1; 01427 } else if (!strcasecmp(v->value, "slinear")) { 01428 if (mode == MODE_FXS) 01429 prefformat |= AST_FORMAT_SLINEAR; 01430 else prefformat = AST_FORMAT_SLINEAR; 01431 } else if (!strcasecmp(v->value, "ulaw")) { 01432 prefformat = AST_FORMAT_ULAW; 01433 } else 01434 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01435 } else if (!strcasecmp(v->name, "echocancel")) { 01436 if (!strcasecmp(v->value, "off")) { 01437 echocancel = AEC_OFF; 01438 } else if (!strcasecmp(v->value, "low")) { 01439 echocancel = AEC_LOW; 01440 } else if (!strcasecmp(v->value, "medium")) { 01441 echocancel = AEC_MED; 01442 } else if (!strcasecmp(v->value, "high")) { 01443 echocancel = AEC_HIGH; 01444 } else 01445 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01446 } else if (!strcasecmp(v->name, "txgain")) { 01447 txgain = parse_gain_value(v->name, v->value); 01448 } else if (!strcasecmp(v->name, "rxgain")) { 01449 rxgain = parse_gain_value(v->name, v->value); 01450 } 01451 v = v->next; 01452 } 01453 ast_mutex_unlock(&iflock); 01454 01455 if (mode == MODE_FXS) { 01456 phone_tech_fxs.capabilities = prefformat; 01457 cur_tech = &phone_tech_fxs; 01458 } else 01459 cur_tech = (struct ast_channel_tech *) &phone_tech; 01460 01461 /* Make sure we can register our Adtranphone channel type */ 01462 01463 if (ast_channel_register(cur_tech)) { 01464 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n"); 01465 ast_config_destroy(cfg); 01466 __unload_module(); 01467 return -1; 01468 } 01469 ast_config_destroy(cfg); 01470 /* And start the monitor for the first time */ 01471 restart_monitor(); 01472 return 0; 01473 }
|
|
||||||||||||||||||||
|
Definition at line 1176 of file chan_phone.c. References ast_log(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, free, phone_pvt::language, phone_pvt::lastformat, phone_pvt::lastinput, LOG_DEBUG, LOG_WARNING, malloc, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, MODE_FXS, phone_pvt::next, phone_pvt::obuflen, option_debug, phone_pvt::owner, phone_pvt::rxgain, phone_pvt::silencesupression, and phone_pvt::txgain. Referenced by load_module(). 01177 { 01178 /* Make a phone_pvt structure for this interface */ 01179 struct phone_pvt *tmp; 01180 int flags; 01181 01182 tmp = malloc(sizeof(struct phone_pvt)); 01183 if (tmp) { 01184 tmp->fd = open(iface, O_RDWR); 01185 if (tmp->fd < 0) { 01186 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 01187 free(tmp); 01188 return NULL; 01189 } 01190 if (mode == MODE_FXO) { 01191 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) { 01192 if (option_debug) 01193 ast_log(LOG_DEBUG, "Unable to set port to PSTN\n"); 01194 } 01195 } else { 01196 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01197 if (mode != MODE_FXS) 01198 ast_log(LOG_DEBUG, "Unable to set port to POTS\n"); 01199 } 01200 ioctl(tmp->fd, PHONE_PLAY_STOP); 01201 ioctl(tmp->fd, PHONE_REC_STOP); 01202 ioctl(tmp->fd, PHONE_RING_STOP); 01203 ioctl(tmp->fd, PHONE_CPT_STOP); 01204 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) { 01205 if (option_debug) 01206 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01207 } 01208 if (echocancel != AEC_OFF) 01209 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01210 if (silencesupression) 01211 tmp->silencesupression = 1; 01212 #ifdef PHONE_VAD 01213 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01214 #endif 01215 tmp->mode = mode; 01216 flags = fcntl(tmp->fd, F_GETFL); 01217 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01218 tmp->owner = NULL; 01219 tmp->lastformat = -1; 01220 tmp->lastinput = -1; 01221 tmp->ministate = 0; 01222 memset(tmp->ext, 0, sizeof(tmp->ext)); 01223 ast_copy_string(tmp->language, language, sizeof(tmp->language)); 01224 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev)); 01225 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01226 tmp->next = NULL; 01227 tmp->obuflen = 0; 01228 tmp->dialtone = 0; 01229 tmp->cpt = 0; 01230 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num)); 01231 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name)); 01232 tmp->txgain = txgain; 01233 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01234 tmp->rxgain = rxgain; 01235 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01236 } 01237 return tmp; 01238 }
|
|
||||||||||||
|
Definition at line 1282 of file chan_phone.c. References ast_log(), DEFAULT_GAIN, and LOG_ERROR. Referenced by load_module(). 01283 { 01284 float gain; 01285 01286 /* try to scan number */ 01287 if (sscanf(value, "%f", &gain) != 1) 01288 { 01289 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01290 value, gain_type, config); 01291 return DEFAULT_GAIN; 01292 } 01293 01294 /* multiplicate gain by 1.0 gain value */ 01295 gain = gain * (float)DEFAULT_GAIN; 01296 01297 /* percentage? */ 01298 if (value[strlen(value) - 1] == '%') 01299 return (int)(gain / (float)100); 01300 01301 return (int)gain; 01302 }
|
|
|
Definition at line 464 of file chan_phone.c. References ast_log(), ast_setstate(), AST_STATE_UP, phone_pvt::fd, LOG_DEBUG, phone_pvt::mode, MODE_FXO, option_debug, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt. 00465 { 00466 struct phone_pvt *p; 00467 p = ast->tech_pvt; 00468 /* In case it's a LineJack, take it off hook */ 00469 if (p->mode == MODE_FXO) { 00470 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) { 00471 if (option_debug) 00472 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno)); 00473 } 00474 else { 00475 if (option_debug) 00476 ast_log(LOG_DEBUG, "Took linejack off hook\n"); 00477 } 00478 } 00479 phone_setup(ast); 00480 if (option_debug) 00481 ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name); 00482 ast->rings = 0; 00483 ast_setstate(ast, AST_STATE_UP); 00484 return 0; 00485 }
|
|
||||||||||||||||
|
Definition at line 289 of file chan_phone.c. References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, DEFAULT_CALLER_ID, ast_channel::fds, IXJ_PHONE_RING_START, LOG_DEBUG, LOG_WARNING, phone_pvt::mode, MODE_FXS, option_debug, phone_digit_end(), and ast_channel::tech_pvt. 00290 { 00291 struct phone_pvt *p; 00292 00293 PHONE_CID cid; 00294 time_t UtcTime; 00295 struct tm tm; 00296 int start; 00297 00298 time(&UtcTime); 00299 localtime_r(&UtcTime,&tm); 00300 00301 memset(&cid, 0, sizeof(PHONE_CID)); 00302 if(&tm != NULL) { 00303 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1)); 00304 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday); 00305 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour); 00306 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min); 00307 } 00308 /* the standard format of ast->callerid is: "name" <number>, but not always complete */ 00309 if (ast_strlen_zero(ast->cid.cid_name)) 00310 strcpy(cid.name, DEFAULT_CALLER_ID); 00311 else 00312 ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name)); 00313 00314 if (ast->cid.cid_num) 00315 ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number)); 00316 00317 p = ast->tech_pvt; 00318 00319 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00320 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); 00321 return -1; 00322 } 00323 if (option_debug) 00324 ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); 00325 00326 start = IXJ_PHONE_RING_START(cid); 00327 if (start == -1) 00328 return -1; 00329 00330 if (p->mode == MODE_FXS) { 00331 char *digit = strchr(dest, '/'); 00332 if (digit) 00333 { 00334 digit++; 00335 while (*digit) 00336 phone_digit_end(ast, *digit++, 0); 00337 } 00338 } 00339 00340 ast_setstate(ast, AST_STATE_RINGING); 00341 ast_queue_control(ast, AST_CONTROL_RINGING); 00342 return 0; 00343 }
|
|
|
Definition at line 939 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(). 00940 { 00941 int offhook=0; 00942 char digit[2] = {0 , 0}; 00943 union telephony_exception phonee; 00944 /* XXX Do something XXX */ 00945 #if 0 00946 if (option_debug) 00947 ast_log(LOG_DEBUG, "Exception!\n"); 00948 #endif 00949 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00950 if (phonee.bits.dtmf_ready) { 00951 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00952 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) { 00953 ioctl(i->fd, PHONE_PLAY_STOP); 00954 ioctl(i->fd, PHONE_REC_STOP); 00955 ioctl(i->fd, PHONE_CPT_STOP); 00956 i->dialtone = 0; 00957 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00958 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00959 if ((i->mode != MODE_FXS || 00960 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00961 !phonee.bits.dtmf_ready) && 00962 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00963 /* It's a valid extension in its context, get moving! */ 00964 phone_new(i, AST_STATE_RING, i->context); 00965 /* No need to restart monitor, we are the monitor */ 00966 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00967 /* There is nothing in the specified extension that can match anymore. 00968 Try the default */ 00969 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00970 /* Check the default, too... */ 00971 phone_new(i, AST_STATE_RING, "default"); 00972 /* XXX This should probably be justified better XXX */ 00973 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00974 /* It's not a valid extension, give a busy signal */ 00975 if (option_debug) 00976 ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context); 00977 ioctl(i->fd, PHONE_BUSY); 00978 i->cpt = 1; 00979 } 00980 } 00981 #if 0 00982 ast_verbose("Extension is %s\n", i->ext); 00983 #endif 00984 } 00985 } 00986 if (phonee.bits.hookstate) { 00987 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00988 if (offhook) { 00989 if (i->mode == MODE_IMMEDIATE) { 00990 phone_new(i, AST_STATE_RING, i->context); 00991 } else if (i->mode == MODE_DIALTONE) { 00992 ast_module_ref(ast_module_info->self); 00993 /* Reset the extension */ 00994 i->ext[0] = '\0'; 00995 /* Play the dialtone */ 00996 i->dialtone++; 00997 ioctl(i->fd, PHONE_PLAY_STOP); 00998 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00999 ioctl(i->fd, PHONE_PLAY_START); 01000 i->lastformat = -1; 01001 } else if (i->mode == MODE_SIGMA) { 01002 ast_module_ref(ast_module_info->self); 01003 /* Reset the extension */ 01004 i->ext[0] = '\0'; 01005 /* Play the dialtone */ 01006 i->dialtone++; 01007 ioctl(i->fd, PHONE_DIALTONE); 01008 } 01009 } else |