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