#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, const 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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *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 = AST_BUILDOPT_SUM, .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_MUTEX_INITIALIZER , 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_MUTEX_INITIALIZER , NULL, 1 } |
| static struct ast_channel_tech | phone_tech |
| static struct ast_channel_tech | phone_tech_fxs |
| static struct ast_format_cap * | prefcap |
| 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 1496 of file chan_phone.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 1295 of file chan_phone.c.
References ast_channel_unregister(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_channel_tech::capabilities, phone_pvt::fd, iflist, iflock, LOG_WARNING, monlock, phone_pvt::next, and phone_pvt::owner.
01296 { 01297 struct phone_pvt *p, *pl; 01298 /* First, take us out of the channel loop */ 01299 if (cur_tech) 01300 ast_channel_unregister(cur_tech); 01301 if (!ast_mutex_lock(&iflock)) { 01302 /* Hangup all interfaces if they have an owner */ 01303 p = iflist; 01304 while(p) { 01305 if (p->owner) 01306 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01307 p = p->next; 01308 } 01309 iflist = NULL; 01310 ast_mutex_unlock(&iflock); 01311 } else { 01312 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01313 return -1; 01314 } 01315 if (!ast_mutex_lock(&monlock)) { 01316 if (monitor_thread > AST_PTHREADT_NULL) { 01317 monitor = 0; 01318 while (pthread_kill(monitor_thread, SIGURG) == 0) 01319 sched_yield(); 01320 pthread_join(monitor_thread, NULL); 01321 } 01322 monitor_thread = AST_PTHREADT_STOP; 01323 ast_mutex_unlock(&monlock); 01324 } else { 01325 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01326 return -1; 01327 } 01328 01329 if (!ast_mutex_lock(&iflock)) { 01330 /* Destroy all the interfaces and free their memory */ 01331 p = iflist; 01332 while(p) { 01333 /* Close the socket, assuming it's real */ 01334 if (p->fd > -1) 01335 close(p->fd); 01336 pl = p; 01337 p = p->next; 01338 /* Free associated memory */ 01339 ast_free(pl); 01340 } 01341 iflist = NULL; 01342 ast_mutex_unlock(&iflock); 01343 } else { 01344 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01345 return -1; 01346 } 01347 01348 phone_tech.capabilities = ast_format_cap_destroy(phone_tech.capabilities); 01349 phone_tech_fxs.capabilities = ast_format_cap_destroy(phone_tech_fxs.capabilities); 01350 prefcap = ast_format_cap_destroy(prefcap); 01351 return 0; 01352 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1496 of file chan_phone.c.
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 1014 of file chan_phone.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_poll, ast_poll2(), ast_realloc, ast_tv(), ast_tvzero(), DialTone, phone_pvt::dialtone, errno, phone_pvt::fd, iflist, iflock, LOG_ERROR, LOG_WARNING, phone_pvt::mode, MODE_SIGMA, phone_pvt::next, phone_pvt::owner, phone_check_exception(), and phone_mini_packet().
01015 { 01016 struct pollfd *fds = NULL; 01017 int nfds = 0, inuse_fds = 0, res; 01018 struct phone_pvt *i; 01019 int tonepos = 0; 01020 /* The tone we're playing this round */ 01021 struct timeval tv = { 0, 0 }; 01022 int dotone; 01023 /* This thread monitors all the frame relay interfaces which are not yet in use 01024 (and thus do not have a separate thread) indefinitely */ 01025 while (monitor) { 01026 /* Don't let anybody kill us right away. Nobody should lock the interface list 01027 and wait for the monitor list, but the other way around is okay. */ 01028 /* Lock the interface list */ 01029 if (ast_mutex_lock(&iflock)) { 01030 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 01031 return NULL; 01032 } 01033 /* Build the stuff we're going to select on, that is the socket of every 01034 phone_pvt that does not have an associated owner channel */ 01035 i = iflist; 01036 dotone = 0; 01037 inuse_fds = 0; 01038 for (i = iflist; i; i = i->next) { 01039 if (!i->owner) { 01040 /* This needs to be watched, as it lacks an owner */ 01041 if (inuse_fds == nfds) { 01042 void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds)); 01043 if (!tmp) { 01044 /* Avoid leaking */ 01045 continue; 01046 } 01047 fds = tmp; 01048 nfds++; 01049 } 01050 fds[inuse_fds].fd = i->fd; 01051 fds[inuse_fds].events = POLLIN | POLLERR; 01052 fds[inuse_fds].revents = 0; 01053 inuse_fds++; 01054 01055 if (i->dialtone && i->mode != MODE_SIGMA) { 01056 /* Remember we're going to have to come back and play 01057 more dialtones */ 01058 if (ast_tvzero(tv)) { 01059 /* If we're due for a dialtone, play one */ 01060 if (write(i->fd, DialTone + tonepos, 240) != 240) { 01061 ast_log(LOG_WARNING, "Dial tone write error\n"); 01062 } 01063 } 01064 dotone++; 01065 } 01066 } 01067 } 01068 /* Okay, now that we know what to do, release the interface lock */ 01069 ast_mutex_unlock(&iflock); 01070 01071 /* Wait indefinitely for something to happen */ 01072 if (dotone && i && i->mode != MODE_SIGMA) { 01073 /* If we're ready to recycle the time, set it to 30 ms */ 01074 tonepos += 240; 01075 if (tonepos >= sizeof(DialTone)) { 01076 tonepos = 0; 01077 } 01078 if (ast_tvzero(tv)) { 01079 tv = ast_tv(0, 30000); 01080 } 01081 res = ast_poll2(fds, inuse_fds, &tv); 01082 } else { 01083 res = ast_poll(fds, inuse_fds, -1); 01084 tv = ast_tv(0, 0); 01085 tonepos = 0; 01086 } 01087 /* Okay, select has finished. Let's see what happened. */ 01088 if (res < 0) { 01089 ast_debug(1, "poll returned %d: %s\n", res, strerror(errno)); 01090 continue; 01091 } 01092 /* If there are no fd's changed, just continue, it's probably time 01093 to play some more dialtones */ 01094 if (!res) { 01095 continue; 01096 } 01097 /* Alright, lock the interface list again, and let's look and see what has 01098 happened */ 01099 if (ast_mutex_lock(&iflock)) { 01100 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01101 continue; 01102 } 01103 01104 for (i = iflist; i; i = i->next) { 01105 int j; 01106 /* Find the record */ 01107 for (j = 0; j < inuse_fds; j++) { 01108 if (fds[j].fd == i->fd) { 01109 break; 01110 } 01111 } 01112 01113 /* Not found? */ 01114 if (j == inuse_fds) { 01115 continue; 01116 } 01117 01118 if (fds[j].revents & POLLIN) { 01119 if (i->owner) { 01120 continue; 01121 } 01122 phone_mini_packet(i); 01123 } 01124 if (fds[j].revents & POLLERR) { 01125 if (i->owner) { 01126 continue; 01127 } 01128 phone_check_exception(i); 01129 } 01130 } 01131 ast_mutex_unlock(&iflock); 01132 } 01133 return NULL; 01134 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1359 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_cap_add(), ast_format_cap_alloc(), ast_format_cap_copy(), ast_format_cap_remove_bytype(), ast_format_cap_set(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_lock, ast_mutex_unlock, ast_true(), ast_variable_browse(), ast_channel_tech::capabilities, CONFIG_STATUS_FILEINVALID, DEFAULT_GAIN, iflist, iflock, LOG_ERROR, LOG_WARNING, mkif(), phone_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_FXS, MODE_IMMEDIATE, MODE_SIGMA, ast_variable::name, ast_variable::next, phone_pvt::next, parse_gain_value(), restart_monitor(), phone_pvt::rxgain, phone_pvt::txgain, and ast_variable::value.
01360 { 01361 struct ast_config *cfg; 01362 struct ast_variable *v; 01363 struct phone_pvt *tmp; 01364 int mode = MODE_IMMEDIATE; 01365 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01366 struct ast_flags config_flags = { 0 }; 01367 struct ast_format tmpfmt; 01368 01369 if (!(phone_tech.capabilities = ast_format_cap_alloc())) { 01370 return AST_MODULE_LOAD_DECLINE; 01371 } 01372 ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0)); 01373 ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 01374 ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 01375 ast_format_cap_add(phone_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0)); 01376 01377 if (!(prefcap = ast_format_cap_alloc())) { 01378 return AST_MODULE_LOAD_DECLINE; 01379 } 01380 ast_format_cap_copy(prefcap, phone_tech.capabilities); 01381 if (!(phone_tech_fxs.capabilities = ast_format_cap_alloc())) { 01382 return AST_MODULE_LOAD_DECLINE; 01383 } 01384 01385 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { 01386 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 01387 return AST_MODULE_LOAD_DECLINE; 01388 } 01389 01390 /* We *must* have a config file otherwise stop immediately */ 01391 if (!cfg) { 01392 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01393 return AST_MODULE_LOAD_DECLINE; 01394 } 01395 if (ast_mutex_lock(&iflock)) { 01396 /* It's a little silly to lock it, but we mind as well just to be sure */ 01397 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01398 return AST_MODULE_LOAD_FAILURE; 01399 } 01400 v = ast_variable_browse(cfg, "interfaces"); 01401 while(v) { 01402 /* Create the interface list */ 01403 if (!strcasecmp(v->name, "device")) { 01404 tmp = mkif(v->value, mode, txgain, rxgain); 01405 if (tmp) { 01406 tmp->next = iflist; 01407 iflist = tmp; 01408 01409 } else { 01410 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01411 ast_config_destroy(cfg); 01412 ast_mutex_unlock(&iflock); 01413 __unload_module(); 01414 return AST_MODULE_LOAD_FAILURE; 01415 } 01416 } else if (!strcasecmp(v->name, "silencesupression")) { 01417 silencesupression = ast_true(v->value); 01418 } else if (!strcasecmp(v->name, "language")) { 01419 ast_copy_string(language, v->value, sizeof(language)); 01420 } else if (!strcasecmp(v->name, "callerid")) { 01421 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01422 } else if (!strcasecmp(v->name, "mode")) { 01423 if (!strncasecmp(v->value, "di", 2)) 01424 mode = MODE_DIALTONE; 01425 else if (!strncasecmp(v->value, "sig", 3)) 01426 mode = MODE_SIGMA; 01427 else if (!strncasecmp(v->value, "im", 2)) 01428 mode = MODE_IMMEDIATE; 01429 else if (!strncasecmp(v->value, "fxs", 3)) { 01430 mode = MODE_FXS; 01431 ast_format_cap_remove_bytype(prefcap, AST_FORMAT_TYPE_AUDIO); /* All non-voice */ 01432 } 01433 else if (!strncasecmp(v->value, "fx", 2)) 01434 mode = MODE_FXO; 01435 else 01436 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01437 } else if (!strcasecmp(v->name, "context")) { 01438 ast_copy_string(context, v->value, sizeof(context)); 01439 } else if (!strcasecmp(v->name, "format")) { 01440 struct ast_format tmpfmt; 01441 if (!strcasecmp(v->value, "g729")) { 01442 ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G729A, 0)); 01443 } else if (!strcasecmp(v->value, "g723.1")) { 01444 ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_G723_1, 0)); 01445 } else if (!strcasecmp(v->value, "slinear")) { 01446 ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0); 01447 if (mode == MODE_FXS) { 01448 ast_format_cap_add(prefcap, &tmpfmt); 01449 } else { 01450 ast_format_cap_set(prefcap, &tmpfmt); 01451 } 01452 } else if (!strcasecmp(v->value, "ulaw")) { 01453 ast_format_cap_set(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 01454 } else 01455 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01456 } else if (!strcasecmp(v->name, "echocancel")) { 01457 if (!strcasecmp(v->value, "off")) { 01458 echocancel = AEC_OFF; 01459 } else if (!strcasecmp(v->value, "low")) { 01460 echocancel = AEC_LOW; 01461 } else if (!strcasecmp(v->value, "medium")) { 01462 echocancel = AEC_MED; 01463 } else if (!strcasecmp(v->value, "high")) { 01464 echocancel = AEC_HIGH; 01465 } else 01466 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01467 } else if (!strcasecmp(v->name, "txgain")) { 01468 txgain = parse_gain_value(v->name, v->value); 01469 } else if (!strcasecmp(v->name, "rxgain")) { 01470 rxgain = parse_gain_value(v->name, v->value); 01471 } 01472 v = v->next; 01473 } 01474 ast_mutex_unlock(&iflock); 01475 01476 if (mode == MODE_FXS) { 01477 ast_format_cap_copy(phone_tech_fxs.capabilities, prefcap); 01478 cur_tech = &phone_tech_fxs; 01479 } else 01480 cur_tech = (struct ast_channel_tech *) &phone_tech; 01481 01482 /* Make sure we can register our Adtranphone channel type */ 01483 01484 if (ast_channel_register(cur_tech)) { 01485 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n"); 01486 ast_config_destroy(cfg); 01487 __unload_module(); 01488 return AST_MODULE_LOAD_FAILURE; 01489 } 01490 ast_config_destroy(cfg); 01491 /* And start the monitor for the first time */ 01492 restart_monitor(); 01493 return AST_MODULE_LOAD_SUCCESS; 01494 }
| static struct phone_pvt* mkif | ( | const char * | iface, | |
| int | mode, | |||
| int | txgain, | |||
| int | rxgain | |||
| ) | [static, read] |
Definition at line 1173 of file chan_phone.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_format_clear(), ast_free, ast_log(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::dialtone, errno, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, phone_pvt::lastformat, phone_pvt::lastinput, LOG_WARNING, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, MODE_FXS, phone_pvt::next, phone_pvt::obuflen, phone_pvt::owner, phone_pvt::rxgain, phone_pvt::silencesupression, and phone_pvt::txgain.
Referenced by load_module().
01174 { 01175 /* Make a phone_pvt structure for this interface */ 01176 struct phone_pvt *tmp; 01177 int flags; 01178 01179 tmp = ast_calloc(1, sizeof(*tmp)); 01180 if (tmp) { 01181 tmp->fd = open(iface, O_RDWR); 01182 if (tmp->fd < 0) { 01183 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 01184 ast_free(tmp); 01185 return NULL; 01186 } 01187 if (mode == MODE_FXO) { 01188 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) { 01189 ast_debug(1, "Unable to set port to PSTN\n"); 01190 } 01191 } else { 01192 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01193 if (mode != MODE_FXS) 01194 ast_debug(1, "Unable to set port to POTS\n"); 01195 } 01196 ioctl(tmp->fd, PHONE_PLAY_STOP); 01197 ioctl(tmp->fd, PHONE_REC_STOP); 01198 ioctl(tmp->fd, PHONE_RING_STOP); 01199 ioctl(tmp->fd, PHONE_CPT_STOP); 01200 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 01201 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01202 if (echocancel != AEC_OFF) 01203 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01204 if (silencesupression) 01205 tmp->silencesupression = 1; 01206 #ifdef PHONE_VAD 01207 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01208 #endif 01209 tmp->mode = mode; 01210 flags = fcntl(tmp->fd, F_GETFL); 01211 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01212 tmp->owner = NULL; 01213 ast_format_clear(&tmp->lastformat); 01214 ast_format_clear(&tmp->lastinput); 01215 tmp->ministate = 0; 01216 memset(tmp->ext, 0, sizeof(tmp->ext)); 01217 ast_copy_string(tmp->language, language, sizeof(tmp->language)); 01218 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev)); 01219 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01220 tmp->next = NULL; 01221 tmp->obuflen = 0; 01222 tmp->dialtone = 0; 01223 tmp->cpt = 0; 01224 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num)); 01225 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name)); 01226 tmp->txgain = txgain; 01227 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01228 tmp->rxgain = rxgain; 01229 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01230 } 01231 return tmp; 01232 }
| static int parse_gain_value | ( | const char * | gain_type, | |
| const char * | value | |||
| ) | [static] |
Definition at line 1273 of file chan_phone.c.
References ast_log(), DEFAULT_GAIN, and LOG_ERROR.
Referenced by load_module().
01274 { 01275 float gain; 01276 01277 /* try to scan number */ 01278 if (sscanf(value, "%30f", &gain) != 1) 01279 { 01280 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01281 value, gain_type, config); 01282 return DEFAULT_GAIN; 01283 } 01284 01285 /* multiplicate gain by 1.0 gain value */ 01286 gain = gain * (float)DEFAULT_GAIN; 01287 01288 /* percentage? */ 01289 if (value[strlen(value) - 1] == '%') 01290 return (int)(gain / (float)100); 01291 01292 return (int)gain; 01293 }
| static int phone_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 456 of file chan_phone.c.
References ast_channel_name(), ast_debug, ast_setstate(), AST_STATE_UP, errno, phone_pvt::fd, phone_pvt::mode, MODE_FXO, phone_setup(), ast_channel::rings, and ast_channel::tech_pvt.
00457 { 00458 struct phone_pvt *p; 00459 p = ast->tech_pvt; 00460 /* In case it's a LineJack, take it off hook */ 00461 if (p->mode == MODE_FXO) { 00462 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 00463 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast_channel_name(ast), strerror(errno)); 00464 else 00465 ast_debug(1, "Took linejack off hook\n"); 00466 } 00467 phone_setup(ast); 00468 ast_debug(1, "phone_answer(%s)\n", ast_channel_name(ast)); 00469 ast->rings = 0; 00470 ast_setstate(ast, AST_STATE_UP); 00471 return 0; 00472 }
| static int phone_call | ( | struct ast_channel * | ast, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 287 of file chan_phone.c.
References ast_channel::_state, ast_channel_name(), AST_CONTROL_RINGING, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_tvnow(), ast_channel::connected, DEFAULT_CALLER_ID, ast_channel::fds, ast_party_connected_line::id, IXJ_PHONE_RING_START, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_party_id::name, ast_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 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1)); 00300 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday); 00301 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour); 00302 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min); 00303 /* the standard format of ast->callerid is: "name" <number>, but not always complete */ 00304 if (!ast->connected.id.name.valid 00305 || ast_strlen_zero(ast->connected.id.name.str)) { 00306 strcpy(cid.name, DEFAULT_CALLER_ID); 00307 } else { 00308 ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name)); 00309 } 00310 00311 if (ast->connected.id.number.valid && ast->connected.id.number.str) { 00312 ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number)); 00313 } 00314 00315 p = ast->tech_pvt; 00316 00317 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00318 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast_channel_name(ast)); 00319 return -1; 00320 } 00321 ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast_channel_name(ast), ast->fds[0]); 00322 00323 start = IXJ_PHONE_RING_START(cid); 00324 if (start == -1) 00325 return -1; 00326 00327 if (p->mode == MODE_FXS) { 00328 const char *digit = strchr(dest, '/'); 00329 if (digit) 00330 { 00331 digit++; 00332 while (*digit) 00333 phone_digit_end(ast, *digit++, 0); 00334 } 00335 } 00336 00337 ast_setstate(ast, AST_STATE_RINGING); 00338 ast_queue_control(ast, AST_CONTROL_RINGING); 00339 return 0; 00340 }
| static void phone_check_exception | ( | struct phone_pvt * | i | ) | [static] |
Definition at line 921 of file chan_phone.c.
References ast_canmatch_extension(), ast_debug, ast_exists_extension(), ast_format_clear(), 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().
Referenced by do_monitor().
00922 { 00923 int offhook=0; 00924 char digit[2] = {0 , 0}; 00925 union telephony_exception phonee; 00926 /* XXX Do something XXX */ 00927 #if 0 00928 ast_debug(1, "Exception!\n"); 00929 #endif 00930 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00931 if (phonee.bits.dtmf_ready) { 00932 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00933 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) { 00934 ioctl(i->fd, PHONE_PLAY_STOP); 00935 ioctl(i->fd, PHONE_REC_STOP); 00936 ioctl(i->fd, PHONE_CPT_STOP); 00937 i->dialtone = 0; 00938 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00939 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00940 if ((i->mode != MODE_FXS || 00941 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00942 !phonee.bits.dtmf_ready) && 00943 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00944 /* It's a valid extension in its context, get moving! */ 00945 phone_new(i, AST_STATE_RING, i->context, NULL); 00946 /* No need to restart monitor, we are the monitor */ 00947 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00948 /* There is nothing in the specified extension that can match anymore. 00949 Try the default */ 00950 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00951 /* Check the default, too... */ 00952 phone_new(i, AST_STATE_RING, "default", NULL); 00953 /* XXX This should probably be justified better XXX */ 00954 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00955 /* It's not a valid extension, give a busy signal */ 00956 ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context); 00957 ioctl(i->fd, PHONE_BUSY); 00958 i->cpt = 1; 00959 } 00960 } 00961 #if 0 00962 ast_verbose("Extension is %s\n", i->ext); 00963 #endif 00964 } 00965 } 00966 if (phonee.bits.hookstate) { 00967 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00968 if (offhook) { 00969 if (i->mode == MODE_IMMEDIATE) { 00970 phone_new(i, AST_STATE_RING, i->context, NULL); 00971 } else if (i->mode == MODE_DIALTONE) { 00972 ast_module_ref(ast_module_info->self); 00973 /* Reset the extension */ 00974 i->ext[0] = '\0'; 00975 /* Play the dialtone */ 00976 i->dialtone++; 00977 ioctl(i->fd, PHONE_PLAY_STOP); 00978 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00979 ioctl(i->fd, PHONE_PLAY_START); 00980 ast_format_clear(&i->lastformat); 00981 } else if (i->mode == MODE_SIGMA) { 00982 ast_module_ref(ast_module_info->self); 00983 /* Reset the extension */ 00984 i->ext[0] = '\0'; 00985 /* Play the dialtone */ 00986 i->dialtone++; 00987 ioctl(i->fd, PHONE_DIALTONE); 00988 } 00989 } else { 00990 if (i->dialtone) 00991 ast_module_unref(ast_module_info->self); 00992 memset(i->ext, 0, sizeof(i->ext)); 00993 if (i->cpt) 00994 { 00995 ioctl(i->fd, PHONE_CPT_STOP); 00996 i->cpt = 0; 00997 } 00998 ioctl(i->fd, PHONE_PLAY_STOP); 00999 ioctl(i->fd, PHONE_REC_STOP); 01000 i->dialtone = 0; 01001 ast_format_clear(&i->lastformat); 01002 } 01003 } 01004 if (phonee.bits.pstn_ring) { 01005 ast_verbose("Unit is ringing\n"); 01006 phone_new(i, AST_STATE_RING, i->context, NULL); 01007 } 01008 if (phonee.bits.caller_id) 01009 ast_verbose("We have caller ID\n"); 01010 01011 01012 }
| 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_format_clear(), 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 ast_format_clear(&p->lastformat); 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 ast_format_clear(&p->lastformat); 00284 return 0; 00285 }
| static struct ast_frame * phone_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 488 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.
00489 { 00490 int res; 00491 union telephony_exception phonee; 00492 struct phone_pvt *p = ast->tech_pvt; 00493 char digit; 00494 00495 /* Some nice norms */ 00496 p->fr.datalen = 0; 00497 p->fr.samples = 0; 00498 p->fr.data.ptr = NULL; 00499 p->fr.src = "Phone"; 00500 p->fr.offset = 0; 00501 p->fr.mallocd=0; 00502 p->fr.delivery = ast_tv(0,0); 00503 00504 phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION); 00505 if (phonee.bits.dtmf_ready) { 00506 ast_debug(1, "phone_exception(): DTMF\n"); 00507 00508 /* We've got a digit -- Just handle this nicely and easily */ 00509 digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII); 00510 p->fr.subclass.integer = digit; 00511 p->fr.frametype = AST_FRAME_DTMF; 00512 return &p->fr; 00513 } 00514 if (phonee.bits.hookstate) { 00515 ast_debug(1, "Hookstate changed\n"); 00516 res = ioctl(p->fd, PHONE_HOOKSTATE); 00517 /* See if we've gone on hook, if so, notify by returning NULL */ 00518 ast_debug(1, "New hookstate: %d\n", res); 00519 if (!res && (p->mode != MODE_FXO)) 00520 return NULL; 00521 else { 00522 if (ast->_state == AST_STATE_RINGING) { 00523 /* They've picked up the phone */ 00524 p->fr.frametype = AST_FRAME_CONTROL; 00525 p->fr.subclass.integer = AST_CONTROL_ANSWER; 00526 phone_setup(ast); 00527 ast_setstate(ast, AST_STATE_UP); 00528 return &p->fr; 00529 } else 00530 ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state); 00531 } 00532 } 00533 #if 1 00534 if (phonee.bits.pstn_ring) 00535 ast_verbose("Unit is ringing\n"); 00536 if (phonee.bits.caller_id) { 00537 ast_verbose("We have caller ID\n"); 00538 } 00539 if (phonee.bits.pstn_wink) 00540 ast_verbose("Detected Wink\n"); 00541 #endif 00542 /* Strange -- nothing there.. */ 00543 p->fr.frametype = AST_FRAME_NULL; 00544 p->fr.subclass.integer = 0; 00545 return &p->fr; 00546 }
| 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 342 of file chan_phone.c.
References ast_channel_name(), ast_debug, ast_format_clear(), 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, phone_pvt::obuflen, phone_pvt::owner, restart_monitor(), and ast_channel::tech_pvt.
00343 { 00344 struct phone_pvt *p; 00345 p = ast->tech_pvt; 00346 ast_debug(1, "phone_hangup(%s)\n", ast_channel_name(ast)); 00347 if (!ast->tech_pvt) { 00348 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00349 return 0; 00350 } 00351 /* XXX Is there anything we can do to really hang up except stop recording? */ 00352 ast_setstate(ast, AST_STATE_DOWN); 00353 if (ioctl(p->fd, PHONE_REC_STOP)) 00354 ast_log(LOG_WARNING, "Failed to stop recording\n"); 00355 if (ioctl(p->fd, PHONE_PLAY_STOP)) 00356 ast_log(LOG_WARNING, "Failed to stop playing\n"); 00357 if (ioctl(p->fd, PHONE_RING_STOP)) 00358 ast_log(LOG_WARNING, "Failed to stop ringing\n"); 00359 if (ioctl(p->fd, PHONE_CPT_STOP)) 00360 ast_log(LOG_WARNING, "Failed to stop sounds\n"); 00361 00362 /* If it's an FXO, hang them up */ 00363 if (p->mode == MODE_FXO) { 00364 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 00365 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast_channel_name(ast), strerror(errno)); 00366 } 00367 00368 /* If they're off hook, give a busy signal */ 00369 if (ioctl(p->fd, PHONE_HOOKSTATE)) { 00370 ast_debug(1, "Got hunghup, giving busy signal\n"); 00371 ioctl(p->fd, PHONE_BUSY); 00372 p->cpt = 1; 00373 } 00374 ast_format_clear(&p->lastformat); 00375 ast_format_clear(&p->lastinput); 00376 p->ministate = 0; 00377 p->obuflen = 0; 00378 p->dialtone = 0; 00379 memset(p->ext, 0, sizeof(p->ext)); 00380 ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL; 00381 ast_module_unref(ast_module_info->self); 00382 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast)); 00383 ast->tech_pvt = NULL; 00384 ast_setstate(ast, AST_STATE_DOWN); 00385 restart_monitor(); 00386 return 0; 00387 }
| 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_channel_name(), AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_format_clear(), ast_log(), ast_moh_start(), ast_moh_stop(), phone_pvt::fd, phone_pvt::lastformat, LOG_WARNING, 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, ast_channel_name(chan)); 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 ast_format_clear(&p->lastformat); 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, ast_channel_name(chan)); 00227 } 00228 return res; 00229 }
| static void phone_mini_packet | ( | struct phone_pvt * | i | ) | [static] |
Definition at line 909 of file chan_phone.c.
References ast_log(), errno, phone_pvt::fd, and LOG_WARNING.
Referenced by do_monitor().
00910 { 00911 int res; 00912 char buf[1024]; 00913 /* Ignore stuff we read... */ 00914 res = read(i->fd, buf, sizeof(buf)); 00915 if (res < 1) { 00916 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno)); 00917 return; 00918 } 00919 }
| static struct ast_channel* phone_new | ( | struct phone_pvt * | i, | |
| int | state, | |||
| char * | cntx, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Definition at line 848 of file chan_phone.c.
References ast_best_codec(), ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_copy_string(), ast_format_cap_add(), ast_format_cap_copy(), ast_format_cap_remove(), ast_format_copy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, 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 struct ast_format tmpfmt; 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 ast_format_cap_add(tmp->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 00862 ast_format_copy(&tmp->rawreadformat, &tmpfmt); 00863 ast_format_copy(&tmp->rawwriteformat, &tmpfmt); 00864 } else { 00865 ast_format_cap_remove(prefcap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 00866 } 00867 } else { 00868 ast_format_cap_copy(tmp->nativeformats, prefcap); 00869 ast_best_codec(tmp->nativeformats, &tmpfmt); 00870 ast_format_copy(&tmp->rawreadformat, &tmpfmt); 00871 ast_format_copy(&tmp->rawwriteformat, &tmpfmt); 00872 } 00873 /* no need to call ast_setstate: the channel_alloc already did its job */ 00874 if (state == AST_STATE_RING) 00875 tmp->rings = 1; 00876 tmp->tech_pvt = i; 00877 ast_copy_string(tmp->context, cntx, sizeof(tmp->context)); 00878 if (!ast_strlen_zero(i->ext)) 00879 ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten)); 00880 else 00881 strcpy(tmp->exten, "s"); 00882 if (!ast_strlen_zero(i->language)) 00883 ast_channel_language_set(tmp, i->language); 00884 00885 /* Don't use ast_set_callerid() here because it will 00886 * generate a NewCallerID event before the NewChannel event */ 00887 if (!ast_strlen_zero(i->cid_num)) { 00888 tmp->caller.ani.number.valid = 1; 00889 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 00890 } 00891 00892 i->owner = tmp; 00893 ast_module_ref(ast_module_info->self); 00894 if (state != AST_STATE_DOWN) { 00895 if (state == AST_STATE_RING) { 00896 ioctl(tmp->fds[0], PHONE_RINGBACK); 00897 i->cpt = 1; 00898 } 00899 if (ast_pbx_start(tmp)) { 00900 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); 00901 ast_hangup(tmp); 00902 } 00903 } 00904 } else 00905 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00906 return tmp; 00907 }
| static struct ast_frame * phone_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 548 of file chan_phone.c.
References ast_clear_flag, AST_FLAG_BLOCKING, ast_format_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_SLINEAR, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_IMAGE, 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::data, ast_frame::datalen, ast_frame::delivery, errno, phone_pvt::fd, ast_frame_subclass::format, phone_pvt::fr, ast_frame::frametype, ast_format::id, 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.
00549 { 00550 int res; 00551 struct phone_pvt *p = ast->tech_pvt; 00552 00553 00554 /* Some nice norms */ 00555 p->fr.datalen = 0; 00556 p->fr.samples = 0; 00557 p->fr.data.ptr = NULL; 00558 p->fr.src = "Phone"; 00559 p->fr.offset = 0; 00560 p->fr.mallocd=0; 00561 p->fr.delivery = ast_tv(0,0); 00562 00563 /* Try to read some data... */ 00564 CHECK_BLOCKING(ast); 00565 res = read(p->fd, p->buf, PHONE_MAX_BUF); 00566 ast_clear_flag(ast, AST_FLAG_BLOCKING); 00567 if (res < 0) { 00568 #if 0 00569 if (errno == EAGAIN) { 00570 ast_log(LOG_WARNING, "Null frame received\n"); 00571 p->fr.frametype = AST_FRAME_NULL; 00572 p->fr.subclass = 0; 00573 return &p->fr; 00574 } 00575 #endif 00576 ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno)); 00577 return NULL; 00578 } 00579 p->fr.data.ptr = p->buf; 00580 if (p->mode != MODE_FXS) 00581 switch(p->buf[0] & 0x3) { 00582 case '0': 00583 case '1': 00584 /* Normal */ 00585 break; 00586 case '2': 00587 case '3': 00588 /* VAD/CNG, only send two words */ 00589 res = 4; 00590 break; 00591 } 00592 p->fr.samples = 240; 00593 p->fr.datalen = res; 00594 p->fr.frametype = AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_AUDIO ? 00595 AST_FRAME_VOICE : AST_FORMAT_GET_TYPE(p->lastinput.id) == AST_FORMAT_TYPE_IMAGE ? 00596 AST_FRAME_IMAGE : AST_FRAME_VIDEO; 00597 ast_format_copy(&p->fr.subclass.format, &p->lastinput); 00598 p->fr.offset = AST_FRIENDLY_OFFSET; 00599 /* Byteswap from little-endian to native-endian */ 00600 if (p->fr.subclass.format.id == AST_FORMAT_SLINEAR) 00601 ast_frame_byteswap_le(&p->fr); 00602 return &p->fr; 00603 }
| static struct ast_channel * phone_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 1234 of file chan_phone.c.
References AST_CAUSE_BUSY, ast_channel_linkedid(), ast_format_cap_has_joint(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, ast_channel_tech::capabilities, phone_pvt::context, phone_pvt::dev, iflist, iflock, LOG_ERROR, LOG_NOTICE, phone_pvt::mode, MODE_FXS, name, phone_pvt::next, phone_pvt::owner, phone_new(), and restart_monitor().
01235 { 01236 struct phone_pvt *p; 01237 struct ast_channel *tmp = NULL; 01238 const char *name = data; 01239 01240 /* Search for an unowned channel */ 01241 if (ast_mutex_lock(&iflock)) { 01242 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01243 return NULL; 01244 } 01245 p = iflist; 01246 while(p) { 01247 if (p->mode == MODE_FXS || (ast_format_cap_has_joint(cap, phone_tech.capabilities))) { 01248 size_t length = strlen(p->dev + 5); 01249 if (strncmp(name, p->dev + 5, length) == 0 && 01250 !isalnum(name[length])) { 01251 if (!p->owner) { 01252 tmp = phone_new(p, AST_STATE_DOWN, p->context, requestor ? ast_channel_linkedid(requestor) : NULL); 01253 break; 01254 } else 01255 *cause = AST_CAUSE_BUSY; 01256 } 01257 } 01258 p = p->next; 01259 } 01260 ast_mutex_unlock(&iflock); 01261 restart_monitor(); 01262 if (tmp == NULL) { 01263 if (!(ast_format_cap_has_joint(cap, phone_tech.capabilities))) { 01264 char buf[256]; 01265 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); 01266 return NULL; 01267 } 01268 } 01269 return tmp; 01270 }
| static int phone_send_text | ( | struct ast_channel * | ast, | |
| const char * | text | |||
| ) | [static] |
Definition at line 639 of file chan_phone.c.
References phone_write_buf(), and ast_channel::tech_pvt.
00640 { 00641 int length = strlen(text); 00642 return phone_write_buf(ast->tech_pvt, text, length, length, 0) == 00643 length ? 0 : -1; 00644 }
| static int phone_setup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 389 of file chan_phone.c.
References ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_getformatname(), ast_log(), phone_pvt::fd, ast_format::id, 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().
00390 { 00391 struct phone_pvt *p; 00392 p = ast->tech_pvt; 00393 ioctl(p->fd, PHONE_CPT_STOP); 00394 /* Nothing to answering really, just start recording */ 00395 if (ast->rawreadformat.id == AST_FORMAT_G729A) { 00396 /* Prefer g729 */ 00397 ioctl(p->fd, PHONE_REC_STOP); 00398 if (p->lastinput.id != AST_FORMAT_G729A) { 00399 ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); 00400 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { 00401 ast_log(LOG_WARNING, "Failed to set codec to g729\n"); 00402 return -1; 00403 } 00404 } 00405 } else if (ast->rawreadformat.id == AST_FORMAT_G723_1) { 00406 ioctl(p->fd, PHONE_REC_STOP); 00407 if (p->lastinput.id != AST_FORMAT_G723_1) { 00408 ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); 00409 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { 00410 ast_log(LOG_WARNING, "Failed to set codec to g723.1\n"); 00411 return -1; 00412 } 00413 } 00414 } else if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) { 00415 ioctl(p->fd, PHONE_REC_STOP); 00416 if (p->lastinput.id != AST_FORMAT_SLINEAR) { 00417 ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); 00418 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { 00419 ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n"); 00420 return -1; 00421 } 00422 } 00423 } else if (ast->rawreadformat.id == AST_FORMAT_ULAW) { 00424 ioctl(p->fd, PHONE_REC_STOP); 00425 if (p->lastinput.id != AST_FORMAT_ULAW) { 00426 ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); 00427 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { 00428 ast_log(LOG_WARNING, "Failed to set codec to uLaw\n"); 00429 return -1; 00430 } 00431 } 00432 } else if (p->mode == MODE_FXS) { 00433 ioctl(p->fd, PHONE_REC_STOP); 00434 if (ast_format_cmp(&p->lastinput, &ast->rawreadformat) == AST_FORMAT_CMP_NOT_EQUAL) { 00435 ast_format_copy(&p->lastinput, &ast->rawreadformat); 00436 if (ioctl(p->fd, PHONE_REC_CODEC, &ast->rawreadformat)) { 00437 ast_log(LOG_WARNING, "Failed to set codec to %s\n", 00438 ast_getformatname(&ast->rawreadformat)); 00439 return -1; 00440 } 00441 } 00442 } else { 00443 ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(&ast->rawreadformat)); 00444 return -1; 00445 } 00446 if (ioctl(p->fd, PHONE_REC_START)) { 00447 ast_log(LOG_WARNING, "Failed to start recording\n"); 00448 return -1; 00449 } 00450 /* set the DTMF times (the default is too short) */ 00451 ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300); 00452 ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200); 00453 return 0; 00454 }
| static int phone_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 646 of file chan_phone.c.
References ast_channel::_state, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_copy(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_set(), AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_setstate(), AST_STATE_UP, ast_frame::data, ast_frame::datalen, errno, phone_pvt::fd, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, 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.
00647 { 00648 struct phone_pvt *p = ast->tech_pvt; 00649 int res; 00650 int maxfr=0; 00651 char *pos; 00652 int sofar; 00653 int expected; 00654 int codecset = 0; 00655 char tmpbuf[4]; 00656 /* Write a frame of (presumably voice) data */ 00657 if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) { 00658 if (frame->frametype != AST_FRAME_IMAGE) 00659 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 00660 return 0; 00661 } 00662 if (!(frame->subclass.format.id == AST_FORMAT_G723_1 || 00663 frame->subclass.format.id == AST_FORMAT_SLINEAR || 00664 frame->subclass.format.id == AST_FORMAT_ULAW || 00665 frame->subclass.format.id == AST_FORMAT_G729A) && 00666 p->mode != MODE_FXS) { 00667 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format)); 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.format.id == AST_FORMAT_G729A) { 00683 if (p->lastformat.id != 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 ast_format_set(&p->lastformat, AST_FORMAT_G729A, 0); 00695 ast_format_set(&p->lastinput, AST_FORMAT_G729A, 0); 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.format.id == AST_FORMAT_G723_1) { 00706 if (p->lastformat.id != 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 ast_format_set(&p->lastformat, AST_FORMAT_G723_1, 0); 00718 ast_format_set(&p->lastinput, AST_FORMAT_G723_1, 0); 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.format.id == AST_FORMAT_SLINEAR) { 00729 if (p->lastformat.id != 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 ast_format_set(&p->lastformat, AST_FORMAT_SLINEAR, 0); 00741 ast_format_set(&p->lastinput, AST_FORMAT_SLINEAR, 0); 00742 codecset = 1; 00743 /* Reset output buffer */ 00744 p->obuflen = 0; 00745 } 00746 maxfr = 480; 00747 } else if (frame->subclass.format.id == AST_FORMAT_ULAW) { 00748 if (p->lastformat.id != 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 ast_format_set(&p->lastformat, AST_FORMAT_ULAW, 0); 00760 ast_format_set(&p->lastinput, AST_FORMAT_ULAW, 0); 00761 codecset = 1; 00762 /* Reset output buffer */ 00763 p->obuflen = 0; 00764 } 00765 maxfr = 240; 00766 } else { 00767 if (ast_format_cmp(&p->lastformat, &frame->subclass.format) != AST_FORMAT_CMP_EQUAL) { 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.format.id)) { 00771 ast_log(LOG_WARNING, "Unable to set %s mode\n", 00772 ast_getformatname(&frame->subclass.format)); 00773 return -1; 00774 } 00775 if (ioctl(p->fd, PHONE_REC_CODEC, (int) frame->subclass.format.id)) { 00776 ast_log(LOG_WARNING, "Unable to set %s mode\n", 00777 ast_getformatname(&frame->subclass.format)); 00778 return -1; 00779 } 00780 ast_format_copy(&p->lastformat, &frame->subclass.format); 00781 ast_format_copy(&p->lastinput, &frame->subclass.format); 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.format.id == 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 605 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().
00606 { 00607 int res; 00608 /* Store as much of the buffer as we can, then write fixed frames */ 00609 int space = sizeof(p->obuf) - p->obuflen; 00610 /* Make sure we have enough buffer space to store the frame */ 00611 if (space < len) 00612 len = space; 00613 if (swap) 00614 ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2); 00615 else 00616 memcpy(p->obuf + p->obuflen, buf, len); 00617 p->obuflen += len; 00618 while(p->obuflen > frlen) { 00619 res = write(p->fd, p->obuf, frlen); 00620 if (res != frlen) { 00621 if (res < 1) { 00622 /* 00623 * Card is in non-blocking mode now and it works well now, but there are 00624 * lot of messages like this. So, this message is temporarily disabled. 00625 */ 00626 return 0; 00627 } else { 00628 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen); 00629 } 00630 } 00631 p->obuflen -= frlen; 00632 /* Move memory if necessary */ 00633 if (p->obuflen) 00634 memmove(p->obuf, p->obuf + frlen, p->obuflen); 00635 } 00636 return len; 00637 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 1136 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.
01137 { 01138 /* If we're supposed to be stopped -- stay stopped */ 01139 if (monitor_thread == AST_PTHREADT_STOP) 01140 return 0; 01141 if (ast_mutex_lock(&monlock)) { 01142 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 01143 return -1; 01144 } 01145 if (monitor_thread == pthread_self()) { 01146 ast_mutex_unlock(&monlock); 01147 ast_log(LOG_WARNING, "Cannot kill myself\n"); 01148 return -1; 01149 } 01150 if (monitor_thread != AST_PTHREADT_NULL) { 01151 if (ast_mutex_lock(&iflock)) { 01152 ast_mutex_unlock(&monlock); 01153 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01154 return -1; 01155 } 01156 monitor = 0; 01157 while (pthread_kill(monitor_thread, SIGURG) == 0) 01158 sched_yield(); 01159 pthread_join(monitor_thread, NULL); 01160 ast_mutex_unlock(&iflock); 01161 } 01162 monitor = 1; 01163 /* Start a new monitor */ 01164 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 01165 ast_mutex_unlock(&monlock); 01166 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 01167 return -1; 01168 } 01169 ast_mutex_unlock(&monlock); 01170 return 0; 01171 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1354 of file chan_phone.c.
References __unload_module().
01355 { 01356 return __unload_module(); 01357 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 1496 of file chan_phone.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1496 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 201 of file chan_phone.c.
int echocancel = AEC_OFF [static] |
Definition at line 94 of file chan_phone.c.
ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , 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_device_monitor_init(), cc_extension_monitor_init(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), and cc_monitor_destroy().
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
Definition at line 112 of file chan_phone.c.
ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Definition at line 105 of file chan_phone.c.
struct ast_channel_tech phone_tech [static] |
Definition at line 167 of file chan_phone.c.
struct ast_channel_tech phone_tech_fxs [static] |
Definition at line 183 of file chan_phone.c.
struct ast_format_cap* prefcap [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.
1.5.6