#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 |
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 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_pvt * | mkif (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_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 *cntx, const char *linkedid) |
static struct ast_frame * | phone_read (struct ast_channel *ast) |
static struct ast_channel * | phone_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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
static struct ast_module_info * | ast_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_tech * | cur_tech |
static int | echocancel = AEC_OFF |
static struct phone_pvt * | iflist |
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" |
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 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 |
Definition at line 122 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 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 |
#define QNDRV_VER 100 |
Definition at line 68 of file chan_phone.c.
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, cur_tech, phone_pvt::fd, iflist, iflock, LOG_WARNING, monlock, phone_pvt::next, and phone_pvt::owner.
01303 { 01304 struct phone_pvt *p, *pl; 01305 /* First, take us out of the channel loop */ 01306 if (cur_tech) 01307 ast_channel_unregister(cur_tech); 01308 if (!ast_mutex_lock(&iflock)) { 01309 /* Hangup all interfaces if they have an owner */ 01310 p = iflist; 01311 while(p) { 01312 if (p->owner) 01313 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01314 p = p->next; 01315 } 01316 iflist = NULL; 01317 ast_mutex_unlock(&iflock); 01318 } else { 01319 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01320 return -1; 01321 } 01322 if (!ast_mutex_lock(&monlock)) { 01323 if (monitor_thread > AST_PTHREADT_NULL) { 01324 monitor = 0; 01325 while (pthread_kill(monitor_thread, SIGURG) == 0) 01326 sched_yield(); 01327 pthread_join(monitor_thread, NULL); 01328 } 01329 monitor_thread = AST_PTHREADT_STOP; 01330 ast_mutex_unlock(&monlock); 01331 } else { 01332 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01333 return -1; 01334 } 01335 01336 if (!ast_mutex_lock(&iflock)) { 01337 /* Destroy all the interfaces and free their memory */ 01338 p = iflist; 01339 while(p) { 01340 /* Close the socket, assuming it's real */ 01341 if (p->fd > -1) 01342 close(p->fd); 01343 pl = p; 01344 p = p->next; 01345 /* Free associated memory */ 01346 ast_free(pl); 01347 } 01348 iflist = NULL; 01349 ast_mutex_unlock(&iflock); 01350 } else { 01351 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01352 return -1; 01353 } 01354 01355 return 0; 01356 }
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_log(), ast_mutex_lock, ast_realloc, ast_tvzero(), DialTone, phone_pvt::dialtone, phone_pvt::fd, iflist, iflock, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, and phone_pvt::owner.
01018 { 01019 struct pollfd *fds = NULL; 01020 int nfds = 0, inuse_fds = 0, res; 01021 struct phone_pvt *i; 01022 int tonepos = 0; 01023 /* The tone we're playing this round */ 01024 struct timeval tv = { 0, 0 }; 01025 int dotone; 01026 /* This thread monitors all the frame relay interfaces which are not yet in use 01027 (and thus do not have a separate thread) indefinitely */ 01028 while (monitor) { 01029 /* Don't let anybody kill us right away. Nobody should lock the interface list 01030 and wait for the monitor list, but the other way around is okay. */ 01031 /* Lock the interface list */ 01032 if (ast_mutex_lock(&iflock)) { 01033 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 01034 return NULL; 01035 } 01036 /* Build the stuff we're going to select on, that is the socket of every 01037 phone_pvt that does not have an associated owner channel */ 01038 i = iflist; 01039 dotone = 0; 01040 inuse_fds = 0; 01041 for (i = iflist; i; i = i->next) { 01042 if (!i->owner) { 01043 /* This needs to be watched, as it lacks an owner */ 01044 if (inuse_fds == nfds) { 01045 void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds)); 01046 if (!tmp) { 01047 /* Avoid leaking */ 01048 continue; 01049 } 01050 fds = tmp; 01051 nfds++; 01052 } 01053 fds[inuse_fds].fd = i->fd; 01054 fds[inuse_fds].events = POLLIN | POLLERR; 01055 fds[inuse_fds].revents = 0; 01056 inuse_fds++; 01057 01058 if (i->dialtone && i->mode != MODE_SIGMA) { 01059 /* Remember we're going to have to come back and play 01060 more dialtones */ 01061 if (ast_tvzero(tv)) { 01062 /* If we're due for a dialtone, play one */ 01063 if (write(i->fd, DialTone + tonepos, 240) != 240) { 01064 ast_log(LOG_WARNING, "Dial tone write error\n"); 01065 } 01066 } 01067 dotone++; 01068 } 01069 } 01070 } 01071 /* Okay, now that we know what to do, release the interface lock */ 01072 ast_mutex_unlock(&iflock); 01073 01074 /* Wait indefinitely for something to happen */ 01075 if (dotone && i && i->mode != MODE_SIGMA) { 01076 /* If we're ready to recycle the time, set it to 30 ms */ 01077 tonepos += 240; 01078 if (tonepos >= sizeof(DialTone)) { 01079 tonepos = 0; 01080 } 01081 if (ast_tvzero(tv)) { 01082 tv = ast_tv(0, 30000); 01083 } 01084 res = ast_poll2(fds, inuse_fds, &tv); 01085 } else { 01086 res = ast_poll(fds, inuse_fds, -1); 01087 tv = ast_tv(0, 0); 01088 tonepos = 0; 01089 } 01090 /* Okay, select has finished. Let's see what happened. */ 01091 if (res < 0) { 01092 ast_debug(1, "poll returned %d: %s\n", res, strerror(errno)); 01093 continue; 01094 } 01095 /* If there are no fd's changed, just continue, it's probably time 01096 to play some more dialtones */ 01097 if (!res) { 01098 continue; 01099 } 01100 /* Alright, lock the interface list again, and let's look and see what has 01101 happened */ 01102 if (ast_mutex_lock(&iflock)) { 01103 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01104 continue; 01105 } 01106 01107 for (i = iflist; i; i = i->next) { 01108 int j; 01109 /* Find the record */ 01110 for (j = 0; j < inuse_fds; j++) { 01111 if (fds[j].fd == i->fd) { 01112 break; 01113 } 01114 } 01115 01116 /* Not found? */ 01117 if (j == inuse_fds) { 01118 continue; 01119 } 01120 01121 if (fds[j].revents & POLLIN) { 01122 if (i->owner) { 01123 continue; 01124 } 01125 phone_mini_packet(i); 01126 } 01127 if (fds[j].revents & POLLERR) { 01128 if (i->owner) { 01129 continue; 01130 } 01131 phone_check_exception(i); 01132 } 01133 } 01134 ast_mutex_unlock(&iflock); 01135 } 01136 return NULL; 01137 }
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_flags, CONFIG_STATUS_FILEINVALID, cur_tech, 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, phone_tech_fxs, restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.
01364 { 01365 struct ast_config *cfg; 01366 struct ast_variable *v; 01367 struct phone_pvt *tmp; 01368 int mode = MODE_IMMEDIATE; 01369 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01370 struct ast_flags config_flags = { 0 }; 01371 01372 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { 01373 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 01374 return AST_MODULE_LOAD_DECLINE; 01375 } 01376 01377 /* We *must* have a config file otherwise stop immediately */ 01378 if (!cfg) { 01379 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01380 return AST_MODULE_LOAD_DECLINE; 01381 } 01382 if (ast_mutex_lock(&iflock)) { 01383 /* It's a little silly to lock it, but we mind as well just to be sure */ 01384 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01385 return AST_MODULE_LOAD_FAILURE; 01386 } 01387 v = ast_variable_browse(cfg, "interfaces"); 01388 while(v) { 01389 /* Create the interface list */ 01390 if (!strcasecmp(v->name, "device")) { 01391 tmp = mkif(v->value, mode, txgain, rxgain); 01392 if (tmp) { 01393 tmp->next = iflist; 01394 iflist = tmp; 01395 01396 } else { 01397 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01398 ast_config_destroy(cfg); 01399 ast_mutex_unlock(&iflock); 01400 __unload_module(); 01401 return AST_MODULE_LOAD_FAILURE; 01402 } 01403 } else if (!strcasecmp(v->name, "silencesupression")) { 01404 silencesupression = ast_true(v->value); 01405 } else if (!strcasecmp(v->name, "language")) { 01406 ast_copy_string(language, v->value, sizeof(language)); 01407 } else if (!strcasecmp(v->name, "callerid")) { 01408 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01409 } else if (!strcasecmp(v->name, "mode")) { 01410 if (!strncasecmp(v->value, "di", 2)) 01411 mode = MODE_DIALTONE; 01412 else if (!strncasecmp(v->value, "sig", 3)) 01413 mode = MODE_SIGMA; 01414 else if (!strncasecmp(v->value, "im", 2)) 01415 mode = MODE_IMMEDIATE; 01416 else if (!strncasecmp(v->value, "fxs", 3)) { 01417 mode = MODE_FXS; 01418 prefformat = 0x01ff0000; /* All non-voice */ 01419 } 01420 else if (!strncasecmp(v->value, "fx", 2)) 01421 mode = MODE_FXO; 01422 else 01423 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01424 } else if (!strcasecmp(v->name, "context")) { 01425 ast_copy_string(context, v->value, sizeof(context)); 01426 } else if (!strcasecmp(v->name, "format")) { 01427 if (!strcasecmp(v->value, "g729")) { 01428 prefformat = AST_FORMAT_G729A; 01429 } else if (!strcasecmp(v->value, "g723.1")) { 01430 prefformat = AST_FORMAT_G723_1; 01431 } else if (!strcasecmp(v->value, "slinear")) { 01432 if (mode == MODE_FXS) 01433 prefformat |= AST_FORMAT_SLINEAR; 01434 else prefformat = AST_FORMAT_SLINEAR; 01435 } else if (!strcasecmp(v->value, "ulaw")) { 01436 prefformat = AST_FORMAT_ULAW; 01437 } else 01438 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01439 } else if (!strcasecmp(v->name, "echocancel")) { 01440 if (!strcasecmp(v->value, "off")) { 01441 echocancel = AEC_OFF; 01442 } else if (!strcasecmp(v->value, "low")) { 01443 echocancel = AEC_LOW; 01444 } else if (!strcasecmp(v->value, "medium")) { 01445 echocancel = AEC_MED; 01446 } else if (!strcasecmp(v->value, "high")) { 01447 echocancel = AEC_HIGH; 01448 } else 01449 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01450 } else if (!strcasecmp(v->name, "txgain")) { 01451 txgain = parse_gain_value(v->name, v->value); 01452 } else if (!strcasecmp(v->name, "rxgain")) { 01453 rxgain = parse_gain_value(v->name, v->value); 01454 } 01455 v = v->next; 01456 } 01457 ast_mutex_unlock(&iflock); 01458 01459 if (mode == MODE_FXS) { 01460 phone_tech_fxs.capabilities = prefformat; 01461 cur_tech = &phone_tech_fxs; 01462 } else 01463 cur_tech = (struct ast_channel_tech *) &phone_tech; 01464 01465 /* Make sure we can register our Adtranphone channel type */ 01466 01467 if (ast_channel_register(cur_tech)) { 01468 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n"); 01469 ast_config_destroy(cfg); 01470 __unload_module(); 01471 return AST_MODULE_LOAD_FAILURE; 01472 } 01473 ast_config_destroy(cfg); 01474 /* And start the monitor for the first time */ 01475 restart_monitor(); 01476 return AST_MODULE_LOAD_SUCCESS; 01477 }
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(), errno, LOG_WARNING, MODE_FXO, and MODE_FXS.
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 = ast_calloc(1, sizeof(*tmp)); 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 ast_free(tmp); 01188 return NULL; 01189 } 01190 if (mode == MODE_FXO) { 01191 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) { 01192 ast_debug(1, "Unable to set port to PSTN\n"); 01193 } 01194 } else { 01195 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01196 if (mode != MODE_FXS) 01197 ast_debug(1, "Unable to set port to POTS\n"); 01198 } 01199 ioctl(tmp->fd, PHONE_PLAY_STOP); 01200 ioctl(tmp->fd, PHONE_REC_STOP); 01201 ioctl(tmp->fd, PHONE_RING_STOP); 01202 ioctl(tmp->fd, PHONE_CPT_STOP); 01203 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 01204 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01205 if (echocancel != AEC_OFF) 01206 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01207 if (silencesupression) 01208 tmp->silencesupression = 1; 01209 #ifdef PHONE_VAD 01210 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01211 #endif 01212 tmp->mode = mode; 01213 flags = fcntl(tmp->fd, F_GETFL); 01214 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01215 tmp->owner = NULL; 01216 tmp->lastformat = -1; 01217 tmp->lastinput = -1; 01218 tmp->ministate = 0; 01219 memset(tmp->ext, 0, sizeof(tmp->ext)); 01220 ast_copy_string(tmp->language, language, sizeof(tmp->language)); 01221 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev)); 01222 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01223 tmp->next = NULL; 01224 tmp->obuflen = 0; 01225 tmp->dialtone = 0; 01226 tmp->cpt = 0; 01227 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num)); 01228 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name)); 01229 tmp->txgain = txgain; 01230 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01231 tmp->rxgain = rxgain; 01232 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01233 } 01234 return tmp; 01235 }
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().
01281 { 01282 float gain; 01283 01284 /* try to scan number */ 01285 if (sscanf(value, "%30f", &gain) != 1) 01286 { 01287 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01288 value, gain_type, config); 01289 return DEFAULT_GAIN; 01290 } 01291 01292 /* multiplicate gain by 1.0 gain value */ 01293 gain = gain * (float)DEFAULT_GAIN; 01294 01295 /* percentage? */ 01296 if (value[strlen(value) - 1] == '%') 01297 return (int)(gain / (float)100); 01298 01299 return (int)gain; 01300 }
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.
00458 { 00459 struct phone_pvt *p; 00460 p = ast->tech_pvt; 00461 /* In case it's a LineJack, take it off hook */ 00462 if (p->mode == MODE_FXO) { 00463 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 00464 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno)); 00465 else 00466 ast_debug(1, "Took linejack off hook\n"); 00467 } 00468 phone_setup(ast); 00469 ast_debug(1, "phone_answer(%s)\n", ast->name); 00470 ast->rings = 0; 00471 ast_setstate(ast, AST_STATE_UP); 00472 return 0; 00473 }
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_channel::name, ast_party_id::name, ast_party_id::number, phone_digit_end(), ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_party_number::valid, and ast_party_name::valid.
00289 { 00290 struct phone_pvt *p; 00291 00292 PHONE_CID cid; 00293 struct timeval UtcTime = ast_tvnow(); 00294 struct ast_tm tm; 00295 int start; 00296 00297 ast_localtime(&UtcTime, &tm, NULL); 00298 00299 memset(&cid, 0, sizeof(PHONE_CID)); 00300 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1)); 00301 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday); 00302 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour); 00303 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min); 00304 /* the standard format of ast->callerid is: "name" <number>, but not always complete */ 00305 if (!ast->connected.id.name.valid 00306 || ast_strlen_zero(ast->connected.id.name.str)) { 00307 strcpy(cid.name, DEFAULT_CALLER_ID); 00308 } else { 00309 ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name)); 00310 } 00311 00312 if (ast->connected.id.number.valid && ast->connected.id.number.str) { 00313 ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number)); 00314 } 00315 00316 p = ast->tech_pvt; 00317 00318 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00319 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); 00320 return -1; 00321 } 00322 ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); 00323 00324 start = IXJ_PHONE_RING_START(cid); 00325 if (start == -1) 00326 return -1; 00327 00328 if (p->mode == MODE_FXS) { 00329 char *digit = strchr(dest, '/'); 00330 if (digit) 00331 { 00332 digit++; 00333 while (*digit) 00334 phone_digit_end(ast, *digit++, 0); 00335 } 00336 } 00337 00338 ast_setstate(ast, AST_STATE_RINGING); 00339 ast_queue_control(ast, AST_CONTROL_RINGING); 00340 return 0; 00341 }
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, and phone_new().
00925 { 00926 int offhook=0; 00927 char digit[2] = {0 , 0}; 00928 union telephony_exception phonee; 00929 /* XXX Do something XXX */ 00930 #if 0 00931 ast_debug(1, "Exception!\n"); 00932 #endif 00933 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00934 if (phonee.bits.dtmf_ready) { 00935 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00936 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) { 00937 ioctl(i->fd, PHONE_PLAY_STOP); 00938 ioctl(i->fd, PHONE_REC_STOP); 00939 ioctl(i->fd, PHONE_CPT_STOP); 00940 i->dialtone = 0; 00941 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00942 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00943 if ((i->mode != MODE_FXS || 00944 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00945 !phonee.bits.dtmf_ready) && 00946 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00947 /* It's a valid extension in its context, get moving! */ 00948 phone_new(i, AST_STATE_RING, i->context, NULL); 00949 /* No need to restart monitor, we are the monitor */ 00950 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00951 /* There is nothing in the specified extension that can match anymore. 00952 Try the default */ 00953 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00954 /* Check the default, too... */ 00955 phone_new(i, AST_STATE_RING, "default", NULL); 00956 /* XXX This should probably be justified better XXX */ 00957 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00958 /* It's not a valid extension, give a busy signal */ 00959 ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context); 00960 ioctl(i->fd, PHONE_BUSY); 00961 i->cpt = 1; 00962 } 00963 } 00964 #if 0 00965 ast_verbose("Extension is %s\n", i->ext); 00966 #endif 00967 } 00968 } 00969 if (phonee.bits.hookstate) { 00970 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00971 if (offhook) { 00972 if (i->mode == MODE_IMMEDIATE) { 00973 phone_new(i, AST_STATE_RING, i->context, NULL); 00974 } else if (i->mode == MODE_DIALTONE) { 00975 ast_module_ref(ast_module_info->self); 00976 /* Reset the extension */ 00977 i->ext[0] = '\0'; 00978 /* Play the dialtone */ 00979 i->dialtone++; 00980 ioctl(i->fd, PHONE_PLAY_STOP); 00981 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00982 ioctl(i->fd, PHONE_PLAY_START); 00983 i->lastformat = -1; 00984 } else if (i->mode == MODE_SIGMA) { 00985 ast_module_ref(ast_module_info->self); 00986 /* Reset the extension */ 00987 i->ext[0] = '\0'; 00988 /* Play the dialtone */ 00989 i->dialtone++; 00990 ioctl(i->fd, PHONE_DIALTONE); 00991 } 00992 } else { 00993 if (i->dialtone) 00994 ast_module_unref(ast_module_info->self); 00995 memset(i->ext, 0, sizeof(i->ext)); 00996 if (i->cpt) 00997 { 00998 ioctl(i->fd, PHONE_CPT_STOP); 00999 i->cpt = 0; 01000 } 01001 ioctl(i->fd, PHONE_PLAY_STOP); 01002 ioctl(i->fd, PHONE_REC_STOP); 01003 i->dialtone = 0; 01004 i->lastformat = -1; 01005 } 01006 } 01007 if (phonee.bits.pstn_ring) { 01008 ast_verbose("Unit is ringing\n"); 01009 phone_new(i, AST_STATE_RING, i->context, NULL); 01010 } 01011 if (phonee.bits.caller_id) 01012 ast_verbose("We have caller ID\n"); 01013 01014 01015 }
static int phone_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 240 of file chan_phone.c.
00241 { 00242 /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */ 00243 return 0; 00244 }
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().
00247 { 00248 struct phone_pvt *p; 00249 int outdigit; 00250 p = ast->tech_pvt; 00251 ast_debug(1, "Dialed %c\n", digit); 00252 switch(digit) { 00253 case '0': 00254 case '1': 00255 case '2': 00256 case '3': 00257 case '4': 00258 case '5': 00259 case '6': 00260 case '7': 00261 case '8': 00262 case '9': 00263 outdigit = digit - '0'; 00264 break; 00265 case '*': 00266 outdigit = 11; 00267 break; 00268 case '#': 00269 outdigit = 12; 00270 break; 00271 case 'f': /*flash*/ 00272 case 'F': 00273 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK); 00274 usleep(320000); 00275 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK); 00276 p->lastformat = -1; 00277 return 0; 00278 default: 00279 ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit); 00280 return -1; 00281 } 00282 ast_debug(1, "Dialed %d\n", outdigit); 00283 ioctl(p->fd, PHONE_PLAY_TONE, outdigit); 00284 p->lastformat = -1; 00285 return 0; 00286 }
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.
00490 { 00491 int res; 00492 union telephony_exception phonee; 00493 struct phone_pvt *p = ast->tech_pvt; 00494 char digit; 00495 00496 /* Some nice norms */ 00497 p->fr.datalen = 0; 00498 p->fr.samples = 0; 00499 p->fr.data.ptr = NULL; 00500 p->fr.src = "Phone"; 00501 p->fr.offset = 0; 00502 p->fr.mallocd=0; 00503 p->fr.delivery = ast_tv(0,0); 00504 00505 phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION); 00506 if (phonee.bits.dtmf_ready) { 00507 ast_debug(1, "phone_exception(): DTMF\n"); 00508 00509 /* We've got a digit -- Just handle this nicely and easily */ 00510 digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII); 00511 p->fr.subclass.integer = digit; 00512 p->fr.frametype = AST_FRAME_DTMF; 00513 return &p->fr; 00514 } 00515 if (phonee.bits.hookstate) { 00516 ast_debug(1, "Hookstate changed\n"); 00517 res = ioctl(p->fd, PHONE_HOOKSTATE); 00518 /* See if we've gone on hook, if so, notify by returning NULL */ 00519 ast_debug(1, "New hookstate: %d\n", res); 00520 if (!res && (p->mode != MODE_FXO)) 00521 return NULL; 00522 else { 00523 if (ast->_state == AST_STATE_RINGING) { 00524 /* They've picked up the phone */ 00525 p->fr.frametype = AST_FRAME_CONTROL; 00526 p->fr.subclass.integer = AST_CONTROL_ANSWER; 00527 phone_setup(ast); 00528 ast_setstate(ast, AST_STATE_UP); 00529 return &p->fr; 00530 } else 00531 ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state); 00532 } 00533 } 00534 #if 1 00535 if (phonee.bits.pstn_ring) 00536 ast_verbose("Unit is ringing\n"); 00537 if (phonee.bits.caller_id) { 00538 ast_verbose("We have caller ID\n"); 00539 } 00540 if (phonee.bits.pstn_wink) 00541 ast_verbose("Detected Wink\n"); 00542 #endif 00543 /* Strange -- nothing there.. */ 00544 p->fr.frametype = AST_FRAME_NULL; 00545 p->fr.subclass.integer = 0; 00546 return &p->fr; 00547 }
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.
00233 { 00234 struct phone_pvt *pvt = old->tech_pvt; 00235 if (pvt && pvt->owner == old) 00236 pvt->owner = new; 00237 return 0; 00238 }
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(), and ast_channel::tech_pvt.
00344 { 00345 struct phone_pvt *p; 00346 p = ast->tech_pvt; 00347 ast_debug(1, "phone_hangup(%s)\n", ast->name); 00348 if (!ast->tech_pvt) { 00349 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00350 return 0; 00351 } 00352 /* XXX Is there anything we can do to really hang up except stop recording? */ 00353 ast_setstate(ast, AST_STATE_DOWN); 00354 if (ioctl(p->fd, PHONE_REC_STOP)) 00355 ast_log(LOG_WARNING, "Failed to stop recording\n"); 00356 if (ioctl(p->fd, PHONE_PLAY_STOP)) 00357 ast_log(LOG_WARNING, "Failed to stop playing\n"); 00358 if (ioctl(p->fd, PHONE_RING_STOP)) 00359 ast_log(LOG_WARNING, "Failed to stop ringing\n"); 00360 if (ioctl(p->fd, PHONE_CPT_STOP)) 00361 ast_log(LOG_WARNING, "Failed to stop sounds\n"); 00362 00363 /* If it's an FXO, hang them up */ 00364 if (p->mode == MODE_FXO) { 00365 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 00366 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno)); 00367 } 00368 00369 /* If they're off hook, give a busy signal */ 00370 if (ioctl(p->fd, PHONE_HOOKSTATE)) { 00371 ast_debug(1, "Got hunghup, giving busy signal\n"); 00372 ioctl(p->fd, PHONE_BUSY); 00373 p->cpt = 1; 00374 } 00375 p->lastformat = -1; 00376 p->lastinput = -1; 00377 p->ministate = 0; 00378 p->obuflen = 0; 00379 p->dialtone = 0; 00380 memset(p->ext, 0, sizeof(p->ext)); 00381 ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL; 00382 ast_module_unref(ast_module_info->self); 00383 ast_verb(3, "Hungup '%s'\n", ast->name); 00384 ast->tech_pvt = NULL; 00385 ast_setstate(ast, AST_STATE_DOWN); 00386 restart_monitor(); 00387 return 0; 00388 }
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.
00205 { 00206 struct phone_pvt *p = chan->tech_pvt; 00207 int res=-1; 00208 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 00209 switch(condition) { 00210 case AST_CONTROL_FLASH: 00211 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK); 00212 usleep(320000); 00213 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK); 00214 p->lastformat = -1; 00215 res = 0; 00216 break; 00217 case AST_CONTROL_HOLD: 00218 ast_moh_start(chan, data, NULL); 00219 break; 00220 case AST_CONTROL_UNHOLD: 00221 ast_moh_stop(chan); 00222 break; 00223 case AST_CONTROL_SRCUPDATE: 00224 res = 0; 00225 break; 00226 default: 00227 ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name); 00228 } 00229 return res; 00230 }
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.
00913 { 00914 int res; 00915 char buf[1024]; 00916 /* Ignore stuff we read... */ 00917 res = read(i->fd, buf, sizeof(buf)); 00918 if (res < 1) { 00919 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno)); 00920 return; 00921 } 00922 }
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, and phone_pvt::owner.
Referenced by phone_check_exception(), and phone_request().
00849 { 00850 struct ast_channel *tmp; 00851 struct phone_codec_data queried_codec; 00852 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5); 00853 if (tmp) { 00854 tmp->tech = cur_tech; 00855 ast_channel_set_fd(tmp, 0, i->fd); 00856 /* XXX Switching formats silently causes kernel panics XXX */ 00857 if (i->mode == MODE_FXS && 00858 ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) { 00859 if (queried_codec.type == LINEAR16) 00860 tmp->nativeformats = 00861 tmp->rawreadformat = 00862 tmp->rawwriteformat = 00863 AST_FORMAT_SLINEAR; 00864 else { 00865 tmp->nativeformats = 00866 tmp->rawreadformat = 00867 tmp->rawwriteformat = 00868 prefformat & ~AST_FORMAT_SLINEAR; 00869 } 00870 } 00871 else { 00872 tmp->nativeformats = prefformat; 00873 tmp->rawreadformat = prefformat; 00874 tmp->rawwriteformat = prefformat; 00875 } 00876 /* no need to call ast_setstate: the channel_alloc already did its job */ 00877 if (state == AST_STATE_RING) 00878 tmp->rings = 1; 00879 tmp->tech_pvt = i; 00880 ast_copy_string(tmp->context, cntx, sizeof(tmp->context)); 00881 if (!ast_strlen_zero(i->ext)) 00882 ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten)); 00883 else 00884 strcpy(tmp->exten, "s"); 00885 if (!ast_strlen_zero(i->language)) 00886 ast_string_field_set(tmp, language, i->language); 00887 00888 /* Don't use ast_set_callerid() here because it will 00889 * generate a NewCallerID event before the NewChannel event */ 00890 if (!ast_strlen_zero(i->cid_num)) { 00891 tmp->caller.ani.number.valid = 1; 00892 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 00893 } 00894 00895 i->owner = tmp; 00896 ast_module_ref(ast_module_info->self); 00897 if (state != AST_STATE_DOWN) { 00898 if (state == AST_STATE_RING) { 00899 ioctl(tmp->fds[0], PHONE_RINGBACK); 00900 i->cpt = 1; 00901 } 00902 if (ast_pbx_start(tmp)) { 00903 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00904 ast_hangup(tmp); 00905 } 00906 } 00907 } else 00908 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00909 return tmp; 00910 }
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.
00550 { 00551 int res; 00552 struct phone_pvt *p = ast->tech_pvt; 00553 00554 00555 /* Some nice norms */ 00556 p->fr.datalen = 0; 00557 p->fr.samples = 0; 00558 p->fr.data.ptr = NULL; 00559 p->fr.src = "Phone"; 00560 p->fr.offset = 0; 00561 p->fr.mallocd=0; 00562 p->fr.delivery = ast_tv(0,0); 00563 00564 /* Try to read some data... */ 00565 CHECK_BLOCKING(ast); 00566 res = read(p->fd, p->buf, PHONE_MAX_BUF); 00567 ast_clear_flag(ast, AST_FLAG_BLOCKING); 00568 if (res < 0) { 00569 #if 0 00570 if (errno == EAGAIN) { 00571 ast_log(LOG_WARNING, "Null frame received\n"); 00572 p->fr.frametype = AST_FRAME_NULL; 00573 p->fr.subclass = 0; 00574 return &p->fr; 00575 } 00576 #endif 00577 ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno)); 00578 return NULL; 00579 } 00580 p->fr.data.ptr = p->buf; 00581 if (p->mode != MODE_FXS) 00582 switch(p->buf[0] & 0x3) { 00583 case '0': 00584 case '1': 00585 /* Normal */ 00586 break; 00587 case '2': 00588 case '3': 00589 /* VAD/CNG, only send two words */ 00590 res = 4; 00591 break; 00592 } 00593 p->fr.samples = 240; 00594 p->fr.datalen = res; 00595 p->fr.frametype = p->lastinput <= AST_FORMAT_AUDIO_MASK ? 00596 AST_FRAME_VOICE : 00597 p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE 00598 : AST_FRAME_VIDEO; 00599 p->fr.subclass.codec = p->lastinput; 00600 p->fr.offset = AST_FRIENDLY_OFFSET; 00601 /* Byteswap from little-endian to native-endian */ 00602 if (p->fr.subclass.codec == AST_FORMAT_SLINEAR) 00603 ast_frame_byteswap_le(&p->fr); 00604 return &p->fr; 00605 }
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, phone_pvt::dev, 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().
01238 { 01239 format_t oldformat; 01240 struct phone_pvt *p; 01241 struct ast_channel *tmp = NULL; 01242 char *name = data; 01243 01244 /* Search for an unowned channel */ 01245 if (ast_mutex_lock(&iflock)) { 01246 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01247 return NULL; 01248 } 01249 p = iflist; 01250 while(p) { 01251 if (p->mode == MODE_FXS || 01252 format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { 01253 size_t length = strlen(p->dev + 5); 01254 if (strncmp(name, p->dev + 5, length) == 0 && 01255 !isalnum(name[length])) { 01256 if (!p->owner) { 01257 tmp = phone_new(p, AST_STATE_DOWN, p->context, requestor ? requestor->linkedid : NULL); 01258 break; 01259 } else 01260 *cause = AST_CAUSE_BUSY; 01261 } 01262 } 01263 p = p->next; 01264 } 01265 ast_mutex_unlock(&iflock); 01266 restart_monitor(); 01267 if (tmp == NULL) { 01268 oldformat = format; 01269 format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); 01270 if (!format) { 01271 char buf[256]; 01272 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat)); 01273 return NULL; 01274 } 01275 } 01276 return tmp; 01277 }
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.
00642 { 00643 int length = strlen(text); 00644 return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 00645 length ? 0 : -1; 00646 }
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().
00391 { 00392 struct phone_pvt *p; 00393 p = ast->tech_pvt; 00394 ioctl(p->fd, PHONE_CPT_STOP); 00395 /* Nothing to answering really, just start recording */ 00396 if (ast->rawreadformat == AST_FORMAT_G729A) { 00397 /* Prefer g729 */ 00398 ioctl(p->fd, PHONE_REC_STOP); 00399 if (p->lastinput != AST_FORMAT_G729A) { 00400 p->lastinput = AST_FORMAT_G729A; 00401 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { 00402 ast_log(LOG_WARNING, "Failed to set codec to g729\n"); 00403 return -1; 00404 } 00405 } 00406 } else if (ast->rawreadformat == AST_FORMAT_G723_1) { 00407 ioctl(p->fd, PHONE_REC_STOP); 00408 if (p->lastinput != AST_FORMAT_G723_1) { 00409 p->lastinput = AST_FORMAT_G723_1; 00410 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { 00411 ast_log(LOG_WARNING, "Failed to set codec to g723.1\n"); 00412 return -1; 00413 } 00414 } 00415 } else if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 00416 ioctl(p->fd, PHONE_REC_STOP); 00417 if (p->lastinput != AST_FORMAT_SLINEAR) { 00418 p->lastinput = AST_FORMAT_SLINEAR; 00419 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { 00420 ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n"); 00421 return -1; 00422 } 00423 } 00424 } else if (ast->rawreadformat == AST_FORMAT_ULAW) { 00425 ioctl(p->fd, PHONE_REC_STOP); 00426 if (p->lastinput != AST_FORMAT_ULAW) { 00427 p->lastinput = AST_FORMAT_ULAW; 00428 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { 00429 ast_log(LOG_WARNING, "Failed to set codec to uLaw\n"); 00430 return -1; 00431 } 00432 } 00433 } else if (p->mode == MODE_FXS) { 00434 ioctl(p->fd, PHONE_REC_STOP); 00435 if (p->lastinput != ast->rawreadformat) { 00436 p->lastinput = ast->rawreadformat; 00437 if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) { 00438 ast_log(LOG_WARNING, "Failed to set codec to %s\n", 00439 ast_getformatname(ast->rawreadformat)); 00440 return -1; 00441 } 00442 } 00443 } else { 00444 ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat)); 00445 return -1; 00446 } 00447 if (ioctl(p->fd, PHONE_REC_START)) { 00448 ast_log(LOG_WARNING, "Failed to start recording\n"); 00449 return -1; 00450 } 00451 /* set the DTMF times (the default is too short) */ 00452 ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300); 00453 ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200); 00454 return 0; 00455 }
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.
00649 { 00650 struct phone_pvt *p = ast->tech_pvt; 00651 int res; 00652 int maxfr=0; 00653 char *pos; 00654 int sofar; 00655 int expected; 00656 int codecset = 0; 00657 char tmpbuf[4]; 00658 /* Write a frame of (presumably voice) data */ 00659 if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) { 00660 if (frame->frametype != AST_FRAME_IMAGE) 00661 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 00662 return 0; 00663 } 00664 if (!(frame->subclass.codec & 00665 (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && 00666 p->mode != MODE_FXS) { 00667 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec)); 00668 return -1; 00669 } 00670 #if 0 00671 /* If we're not in up mode, go into up mode now */ 00672 if (ast->_state != AST_STATE_UP) { 00673 ast_setstate(ast, AST_STATE_UP); 00674 phone_setup(ast); 00675 } 00676 #else 00677 if (ast->_state != AST_STATE_UP) { 00678 /* Don't try tos end audio on-hook */ 00679 return 0; 00680 } 00681 #endif 00682 if (frame->subclass.codec == AST_FORMAT_G729A) { 00683 if (p->lastformat != AST_FORMAT_G729A) { 00684 ioctl(p->fd, PHONE_PLAY_STOP); 00685 ioctl(p->fd, PHONE_REC_STOP); 00686 if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) { 00687 ast_log(LOG_WARNING, "Unable to set G729 mode\n"); 00688 return -1; 00689 } 00690 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { 00691 ast_log(LOG_WARNING, "Unable to set G729 mode\n"); 00692 return -1; 00693 } 00694 p->lastformat = AST_FORMAT_G729A; 00695 p->lastinput = AST_FORMAT_G729A; 00696 /* Reset output buffer */ 00697 p->obuflen = 0; 00698 codecset = 1; 00699 } 00700 if (frame->datalen > 80) { 00701 ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen); 00702 return -1; 00703 } 00704 maxfr = 80; 00705 } else if (frame->subclass.codec == AST_FORMAT_G723_1) { 00706 if (p->lastformat != AST_FORMAT_G723_1) { 00707 ioctl(p->fd, PHONE_PLAY_STOP); 00708 ioctl(p->fd, PHONE_REC_STOP); 00709 if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) { 00710 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n"); 00711 return -1; 00712 } 00713 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { 00714 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n"); 00715 return -1; 00716 } 00717 p->lastformat = AST_FORMAT_G723_1; 00718 p->lastinput = AST_FORMAT_G723_1; 00719 /* Reset output buffer */ 00720 p->obuflen = 0; 00721 codecset = 1; 00722 } 00723 if (frame->datalen > 24) { 00724 ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen); 00725 return -1; 00726 } 00727 maxfr = 24; 00728 } else if (frame->subclass.codec == AST_FORMAT_SLINEAR) { 00729 if (p->lastformat != AST_FORMAT_SLINEAR) { 00730 ioctl(p->fd, PHONE_PLAY_STOP); 00731 ioctl(p->fd, PHONE_REC_STOP); 00732 if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) { 00733 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n"); 00734 return -1; 00735 } 00736 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { 00737 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n"); 00738 return -1; 00739 } 00740 p->lastformat = AST_FORMAT_SLINEAR; 00741 p->lastinput = AST_FORMAT_SLINEAR; 00742 codecset = 1; 00743 /* Reset output buffer */ 00744 p->obuflen = 0; 00745 } 00746 maxfr = 480; 00747 } else if (frame->subclass.codec == AST_FORMAT_ULAW) { 00748 if (p->lastformat != AST_FORMAT_ULAW) { 00749 ioctl(p->fd, PHONE_PLAY_STOP); 00750 ioctl(p->fd, PHONE_REC_STOP); 00751 if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) { 00752 ast_log(LOG_WARNING, "Unable to set uLaw mode\n"); 00753 return -1; 00754 } 00755 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { 00756 ast_log(LOG_WARNING, "Unable to set uLaw mode\n"); 00757 return -1; 00758 } 00759 p->lastformat = AST_FORMAT_ULAW; 00760 p->lastinput = AST_FORMAT_ULAW; 00761 codecset = 1; 00762 /* Reset output buffer */ 00763 p->obuflen = 0; 00764 } 00765 maxfr = 240; 00766 } else { 00767 if (p->lastformat != frame->subclass.codec) { 00768 ioctl(p->fd, PHONE_PLAY_STOP); 00769 ioctl(p->fd, PHONE_REC_STOP); 00770 if (ioctl(p->fd, PHONE_PLAY_CODEC, (int) frame->subclass.codec)) { 00771 ast_log(LOG_WARNING, "Unable to set %s mode\n", 00772 ast_getformatname(frame->subclass.codec)); 00773 return -1; 00774 } 00775 if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.codec)) { 00776 ast_log(LOG_WARNING, "Unable to set %s mode\n", 00777 ast_getformatname(frame->subclass.codec)); 00778 return -1; 00779 } 00780 p->lastformat = frame->subclass.codec; 00781 p->lastinput = frame->subclass.codec; 00782 codecset = 1; 00783 /* Reset output buffer */ 00784 p->obuflen = 0; 00785 } 00786 maxfr = 480; 00787 } 00788 if (codecset) { 00789 ioctl(p->fd, PHONE_REC_DEPTH, 3); 00790 ioctl(p->fd, PHONE_PLAY_DEPTH, 3); 00791 if (ioctl(p->fd, PHONE_PLAY_START)) { 00792 ast_log(LOG_WARNING, "Failed to start playback\n"); 00793 return -1; 00794 } 00795 if (ioctl(p->fd, PHONE_REC_START)) { 00796 ast_log(LOG_WARNING, "Failed to start recording\n"); 00797 return -1; 00798 } 00799 } 00800 /* If we get here, we have a frame of Appropriate data */ 00801 sofar = 0; 00802 pos = frame->data.ptr; 00803 while(sofar < frame->datalen) { 00804 /* Write in no more than maxfr sized frames */ 00805 expected = frame->datalen - sofar; 00806 if (maxfr < expected) 00807 expected = maxfr; 00808 /* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX 00809 we have to pad it to 24 bytes still. */ 00810 if (frame->datalen == 4) { 00811 if (p->silencesupression) { 00812 memcpy(tmpbuf, frame->data.ptr, 4); 00813 expected = 24; 00814 res = phone_write_buf(p, tmpbuf, expected, maxfr, 0); 00815 } 00816 res = 4; 00817 expected=4; 00818 } else { 00819 int swap = 0; 00820 #if __BYTE_ORDER == __BIG_ENDIAN 00821 if (frame->subclass.codec == AST_FORMAT_SLINEAR) 00822 swap = 1; /* Swap big-endian samples to little-endian as we copy */ 00823 #endif 00824 res = phone_write_buf(p, pos, expected, maxfr, swap); 00825 } 00826 if (res != expected) { 00827 if ((errno != EAGAIN) && (errno != EINTR)) { 00828 if (res < 0) 00829 ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno)); 00830 /* 00831 * Card is in non-blocking mode now and it works well now, but there are 00832 * lot of messages like this. So, this message is temporarily disabled. 00833 */ 00834 #if 0 00835 else 00836 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen); 00837 #endif 00838 return -1; 00839 } else /* Pretend it worked */ 00840 res = expected; 00841 } 00842 sofar += res; 00843 pos += res; 00844 } 00845 return 0; 00846 }
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, LOG_WARNING, phone_pvt::obuf, and phone_pvt::obuflen.
Referenced by phone_send_text(), and phone_write().
00608 { 00609 int res; 00610 /* Store as much of the buffer as we can, then write fixed frames */ 00611 int space = sizeof(p->obuf) - p->obuflen; 00612 /* Make sure we have enough buffer space to store the frame */ 00613 if (space < len) 00614 len = space; 00615 if (swap) 00616 ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2); 00617 else 00618 memcpy(p->obuf + p->obuflen, buf, len); 00619 p->obuflen += len; 00620 while(p->obuflen > frlen) { 00621 res = write(p->fd, p->obuf, frlen); 00622 if (res != frlen) { 00623 if (res < 1) { 00624 /* 00625 * Card is in non-blocking mode now and it works well now, but there are 00626 * lot of messages like this. So, this message is temporarily disabled. 00627 */ 00628 return 0; 00629 } else { 00630 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen); 00631 } 00632 } 00633 p->obuflen -= frlen; 00634 /* Move memory if necessary */ 00635 if (p->obuflen) 00636 memmove(p->obuf, p->obuf + frlen, p->obuflen); 00637 } 00638 return len; 00639 }
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.
01140 { 01141 /* If we're supposed to be stopped -- stay stopped */ 01142 if (monitor_thread == AST_PTHREADT_STOP) 01143 return 0; 01144 if (ast_mutex_lock(&monlock)) { 01145 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 01146 return -1; 01147 } 01148 if (monitor_thread == pthread_self()) { 01149 ast_mutex_unlock(&monlock); 01150 ast_log(LOG_WARNING, "Cannot kill myself\n"); 01151 return -1; 01152 } 01153 if (monitor_thread != AST_PTHREADT_NULL) { 01154 if (ast_mutex_lock(&iflock)) { 01155 ast_mutex_unlock(&monlock); 01156 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01157 return -1; 01158 } 01159 monitor = 0; 01160 while (pthread_kill(monitor_thread, SIGURG) == 0) 01161 sched_yield(); 01162 pthread_join(monitor_thread, NULL); 01163 ast_mutex_unlock(&iflock); 01164 } 01165 monitor = 1; 01166 /* Start a new monitor */ 01167 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 01168 ast_mutex_unlock(&monlock); 01169 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 01170 return -1; 01171 } 01172 ast_mutex_unlock(&monlock); 01173 return 0; 01174 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1358 of file chan_phone.c.
References __unload_module().
01359 { 01360 return __unload_module(); 01361 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 1479 of file chan_phone.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
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 __unload_module(), load_module(), and phone_new().
int echocancel = AEC_OFF [static] |
Definition at line 94 of file chan_phone.c.
ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 101 of file chan_phone.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 92 of file chan_phone.c.
unsigned int monitor [static] |
Definition at line 108 of file chan_phone.c.
Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_available_timer_expire(), ast_cc_call_init(), ast_cc_extension_monitor_add_dialstring(), ast_handle_cc_control_frame(), ast_monitor_start(), cc_cli_print_monitor_stats(), cc_device_monitor_init(), cc_extension_monitor_init(), cc_generic_monitor_cancel_available_timer(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), cc_monitor_destroy(), create_new_generic_list(), sig_pri_call(), sig_pri_cc_available(), sig_pri_cc_generic_check(), sig_pri_cc_link_canceled(), sig_pri_cc_monitor_req_cc(), sig_pri_cc_monitor_status_rsp(), sig_pri_cc_monitor_suspend(), sig_pri_cc_monitor_unsuspend(), sig_pri_handle_cis_subcmds(), sip_cc_monitor_cancel_available_timer(), sip_cc_monitor_request_cc(), sip_cc_monitor_suspend(), and sip_cc_monitor_unsuspend().
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.
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] |
Definition at line 98 of file chan_phone.c.
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.