#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) |
static struct ast_frame * | phone_read (struct ast_channel *ast) |
static struct ast_channel * | phone_request (const char *type, int format, void *data, int *cause) |
static int | phone_send_text (struct ast_channel *ast, const char *text) |
static int | phone_setup (struct ast_channel *ast) |
static int | phone_write (struct ast_channel *ast, struct ast_frame *frame) |
static int | phone_write_buf (struct phone_pvt *p, const char *buf, int len, int frlen, int swap) |
static int | restart_monitor (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static char | language [MAX_LANGUAGE] = "" |
static unsigned int | monitor |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static struct ast_channel_tech | phone_tech |
static struct ast_channel_tech | phone_tech_fxs |
static int | prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW |
static int | silencesupression = 0 |
static const char | tdesc [] = "Standard Linux Telephony API Driver" |
Definition 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 1452 of file chan_phone.c.
static int __unload_module | ( | void | ) | [static] |
Definition at line 1278 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.
01279 { 01280 struct phone_pvt *p, *pl; 01281 /* First, take us out of the channel loop */ 01282 if (cur_tech) 01283 ast_channel_unregister(cur_tech); 01284 if (!ast_mutex_lock(&iflock)) { 01285 /* Hangup all interfaces if they have an owner */ 01286 p = iflist; 01287 while(p) { 01288 if (p->owner) 01289 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01290 p = p->next; 01291 } 01292 iflist = NULL; 01293 ast_mutex_unlock(&iflock); 01294 } else { 01295 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01296 return -1; 01297 } 01298 if (!ast_mutex_lock(&monlock)) { 01299 if (monitor_thread > AST_PTHREADT_NULL) { 01300 monitor = 0; 01301 while (pthread_kill(monitor_thread, SIGURG) == 0) 01302 sched_yield(); 01303 pthread_join(monitor_thread, NULL); 01304 } 01305 monitor_thread = AST_PTHREADT_STOP; 01306 ast_mutex_unlock(&monlock); 01307 } else { 01308 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01309 return -1; 01310 } 01311 01312 if (!ast_mutex_lock(&iflock)) { 01313 /* Destroy all the interfaces and free their memory */ 01314 p = iflist; 01315 while(p) { 01316 /* Close the socket, assuming it's real */ 01317 if (p->fd > -1) 01318 close(p->fd); 01319 pl = p; 01320 p = p->next; 01321 /* Free associated memory */ 01322 ast_free(pl); 01323 } 01324 iflist = NULL; 01325 ast_mutex_unlock(&iflock); 01326 } else { 01327 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01328 return -1; 01329 } 01330 01331 return 0; 01332 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1452 of file chan_phone.c.
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 1012 of file chan_phone.c.
References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), ast_tv(), ast_tvzero(), phone_pvt::dev, 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().
01013 { 01014 fd_set rfds, efds; 01015 int n, res; 01016 struct phone_pvt *i; 01017 int tonepos = 0; 01018 /* The tone we're playing this round */ 01019 struct timeval wait = {0,0}; 01020 int dotone; 01021 /* This thread monitors all the frame relay interfaces which are not yet in use 01022 (and thus do not have a separate thread) indefinitely */ 01023 while (monitor) { 01024 /* Don't let anybody kill us right away. Nobody should lock the interface list 01025 and wait for the monitor list, but the other way around is okay. */ 01026 /* Lock the interface list */ 01027 if (ast_mutex_lock(&iflock)) { 01028 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 01029 return NULL; 01030 } 01031 /* Build the stuff we're going to select on, that is the socket of every 01032 phone_pvt that does not have an associated owner channel */ 01033 n = -1; 01034 FD_ZERO(&rfds); 01035 FD_ZERO(&efds); 01036 i = iflist; 01037 dotone = 0; 01038 while (i) { 01039 if (FD_ISSET(i->fd, &rfds)) 01040 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 01041 if (!i->owner) { 01042 /* This needs to be watched, as it lacks an owner */ 01043 FD_SET(i->fd, &rfds); 01044 FD_SET(i->fd, &efds); 01045 if (i->fd > n) 01046 n = i->fd; 01047 if (i->dialtone && i->mode != MODE_SIGMA) { 01048 /* Remember we're going to have to come back and play 01049 more dialtones */ 01050 if (ast_tvzero(wait)) { 01051 /* If we're due for a dialtone, play one */ 01052 if (write(i->fd, DialTone + tonepos, 240) != 240) 01053 ast_log(LOG_WARNING, "Dial tone write error\n"); 01054 } 01055 dotone++; 01056 } 01057 } 01058 01059 i = i->next; 01060 } 01061 /* Okay, now that we know what to do, release the interface lock */ 01062 ast_mutex_unlock(&iflock); 01063 01064 /* Wait indefinitely for something to happen */ 01065 if (dotone && i && i->mode != MODE_SIGMA) { 01066 /* If we're ready to recycle the time, set it to 30 ms */ 01067 tonepos += 240; 01068 if (tonepos >= sizeof(DialTone)) 01069 tonepos = 0; 01070 if (ast_tvzero(wait)) { 01071 wait = ast_tv(30000, 0); 01072 } 01073 res = ast_select(n + 1, &rfds, NULL, &efds, &wait); 01074 } else { 01075 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 01076 wait = ast_tv(0,0); 01077 tonepos = 0; 01078 } 01079 /* Okay, select has finished. Let's see what happened. */ 01080 if (res < 0) { 01081 ast_debug(1, "select return %d: %s\n", res, strerror(errno)); 01082 continue; 01083 } 01084 /* If there are no fd's changed, just continue, it's probably time 01085 to play some more dialtones */ 01086 if (!res) 01087 continue; 01088 /* Alright, lock the interface list again, and let's look and see what has 01089 happened */ 01090 if (ast_mutex_lock(&iflock)) { 01091 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01092 continue; 01093 } 01094 01095 i = iflist; 01096 for(; i; i=i->next) { 01097 if (FD_ISSET(i->fd, &rfds)) { 01098 if (i->owner) { 01099 continue; 01100 } 01101 phone_mini_packet(i); 01102 } 01103 if (FD_ISSET(i->fd, &efds)) { 01104 if (i->owner) { 01105 continue; 01106 } 01107 phone_check_exception(i); 01108 } 01109 } 01110 ast_mutex_unlock(&iflock); 01111 } 01112 return NULL; 01113 01114 }
static int load_module | ( | void | ) | [static] |
Definition at line 1339 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, 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.
01340 { 01341 struct ast_config *cfg; 01342 struct ast_variable *v; 01343 struct phone_pvt *tmp; 01344 int mode = MODE_IMMEDIATE; 01345 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01346 struct ast_flags config_flags = { 0 }; 01347 01348 cfg = ast_config_load(config, config_flags); 01349 01350 /* We *must* have a config file otherwise stop immediately */ 01351 if (!cfg) { 01352 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01353 return AST_MODULE_LOAD_DECLINE; 01354 } 01355 if (ast_mutex_lock(&iflock)) { 01356 /* It's a little silly to lock it, but we mind as well just to be sure */ 01357 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01358 return AST_MODULE_LOAD_FAILURE; 01359 } 01360 v = ast_variable_browse(cfg, "interfaces"); 01361 while(v) { 01362 /* Create the interface list */ 01363 if (!strcasecmp(v->name, "device")) { 01364 tmp = mkif(v->value, mode, txgain, rxgain); 01365 if (tmp) { 01366 tmp->next = iflist; 01367 iflist = tmp; 01368 01369 } else { 01370 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01371 ast_config_destroy(cfg); 01372 ast_mutex_unlock(&iflock); 01373 __unload_module(); 01374 return AST_MODULE_LOAD_FAILURE; 01375 } 01376 } else if (!strcasecmp(v->name, "silencesupression")) { 01377 silencesupression = ast_true(v->value); 01378 } else if (!strcasecmp(v->name, "language")) { 01379 ast_copy_string(language, v->value, sizeof(language)); 01380 } else if (!strcasecmp(v->name, "callerid")) { 01381 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01382 } else if (!strcasecmp(v->name, "mode")) { 01383 if (!strncasecmp(v->value, "di", 2)) 01384 mode = MODE_DIALTONE; 01385 else if (!strncasecmp(v->value, "sig", 3)) 01386 mode = MODE_SIGMA; 01387 else if (!strncasecmp(v->value, "im", 2)) 01388 mode = MODE_IMMEDIATE; 01389 else if (!strncasecmp(v->value, "fxs", 3)) { 01390 mode = MODE_FXS; 01391 prefformat = 0x01ff0000; /* All non-voice */ 01392 } 01393 else if (!strncasecmp(v->value, "fx", 2)) 01394 mode = MODE_FXO; 01395 else 01396 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01397 } else if (!strcasecmp(v->name, "context")) { 01398 ast_copy_string(context, v->value, sizeof(context)); 01399 } else if (!strcasecmp(v->name, "format")) { 01400 if (!strcasecmp(v->value, "g729")) { 01401 prefformat = AST_FORMAT_G729A; 01402 } else if (!strcasecmp(v->value, "g723.1")) { 01403 prefformat = AST_FORMAT_G723_1; 01404 } else if (!strcasecmp(v->value, "slinear")) { 01405 if (mode == MODE_FXS) 01406 prefformat |= AST_FORMAT_SLINEAR; 01407 else prefformat = AST_FORMAT_SLINEAR; 01408 } else if (!strcasecmp(v->value, "ulaw")) { 01409 prefformat = AST_FORMAT_ULAW; 01410 } else 01411 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01412 } else if (!strcasecmp(v->name, "echocancel")) { 01413 if (!strcasecmp(v->value, "off")) { 01414 echocancel = AEC_OFF; 01415 } else if (!strcasecmp(v->value, "low")) { 01416 echocancel = AEC_LOW; 01417 } else if (!strcasecmp(v->value, "medium")) { 01418 echocancel = AEC_MED; 01419 } else if (!strcasecmp(v->value, "high")) { 01420 echocancel = AEC_HIGH; 01421 } else 01422 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01423 } else if (!strcasecmp(v->name, "txgain")) { 01424 txgain = parse_gain_value(v->name, v->value); 01425 } else if (!strcasecmp(v->name, "rxgain")) { 01426 rxgain = parse_gain_value(v->name, v->value); 01427 } 01428 v = v->next; 01429 } 01430 ast_mutex_unlock(&iflock); 01431 01432 if (mode == MODE_FXS) { 01433 phone_tech_fxs.capabilities = prefformat; 01434 cur_tech = &phone_tech_fxs; 01435 } else 01436 cur_tech = (struct ast_channel_tech *) &phone_tech; 01437 01438 /* Make sure we can register our Adtranphone channel type */ 01439 01440 if (ast_channel_register(cur_tech)) { 01441 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n"); 01442 ast_config_destroy(cfg); 01443 __unload_module(); 01444 return AST_MODULE_LOAD_FAILURE; 01445 } 01446 ast_config_destroy(cfg); 01447 /* And start the monitor for the first time */ 01448 restart_monitor(); 01449 return AST_MODULE_LOAD_SUCCESS; 01450 }
static struct phone_pvt* mkif | ( | const char * | iface, | |
int | mode, | |||
int | txgain, | |||
int | rxgain | |||
) | [static] |
Definition at line 1153 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().
01154 { 01155 /* Make a phone_pvt structure for this interface */ 01156 struct phone_pvt *tmp; 01157 int flags; 01158 01159 tmp = ast_calloc(1, sizeof(*tmp)); 01160 if (tmp) { 01161 tmp->fd = open(iface, O_RDWR); 01162 if (tmp->fd < 0) { 01163 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 01164 ast_free(tmp); 01165 return NULL; 01166 } 01167 if (mode == MODE_FXO) { 01168 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) { 01169 ast_debug(1, "Unable to set port to PSTN\n"); 01170 } 01171 } else { 01172 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01173 if (mode != MODE_FXS) 01174 ast_debug(1, "Unable to set port to POTS\n"); 01175 } 01176 ioctl(tmp->fd, PHONE_PLAY_STOP); 01177 ioctl(tmp->fd, PHONE_REC_STOP); 01178 ioctl(tmp->fd, PHONE_RING_STOP); 01179 ioctl(tmp->fd, PHONE_CPT_STOP); 01180 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 01181 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01182 if (echocancel != AEC_OFF) 01183 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01184 if (silencesupression) 01185 tmp->silencesupression = 1; 01186 #ifdef PHONE_VAD 01187 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01188 #endif 01189 tmp->mode = mode; 01190 flags = fcntl(tmp->fd, F_GETFL); 01191 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01192 tmp->owner = NULL; 01193 tmp->lastformat = -1; 01194 tmp->lastinput = -1; 01195 tmp->ministate = 0; 01196 memset(tmp->ext, 0, sizeof(tmp->ext)); 01197 ast_copy_string(tmp->language, language, sizeof(tmp->language)); 01198 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev)); 01199 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01200 tmp->next = NULL; 01201 tmp->obuflen = 0; 01202 tmp->dialtone = 0; 01203 tmp->cpt = 0; 01204 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num)); 01205 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name)); 01206 tmp->txgain = txgain; 01207 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01208 tmp->rxgain = rxgain; 01209 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01210 } 01211 return tmp; 01212 }
static int parse_gain_value | ( | const char * | gain_type, | |
const char * | value | |||
) | [static] |
Definition at line 1256 of file chan_phone.c.
References ast_log(), DEFAULT_GAIN, and LOG_ERROR.
Referenced by load_module().
01257 { 01258 float gain; 01259 01260 /* try to scan number */ 01261 if (sscanf(value, "%30f", &gain) != 1) 01262 { 01263 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01264 value, gain_type, config); 01265 return DEFAULT_GAIN; 01266 } 01267 01268 /* multiplicate gain by 1.0 gain value */ 01269 gain = gain * (float)DEFAULT_GAIN; 01270 01271 /* percentage? */ 01272 if (value[strlen(value) - 1] == '%') 01273 return (int)(gain / (float)100); 01274 01275 return (int)gain; 01276 }
static int phone_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 455 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.
00456 { 00457 struct phone_pvt *p; 00458 p = ast->tech_pvt; 00459 /* In case it's a LineJack, take it off hook */ 00460 if (p->mode == MODE_FXO) { 00461 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK)) 00462 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno)); 00463 else 00464 ast_debug(1, "Took linejack off hook\n"); 00465 } 00466 phone_setup(ast); 00467 ast_debug(1, "phone_answer(%s)\n", ast->name); 00468 ast->rings = 0; 00469 ast_setstate(ast, AST_STATE_UP); 00470 return 0; 00471 }
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::cid, ast_callerid::cid_name, ast_callerid::cid_num, DEFAULT_CALLER_ID, ast_channel::fds, IXJ_PHONE_RING_START, LOG_WARNING, phone_pvt::mode, MODE_FXS, ast_channel::name, phone_digit_end(), ast_channel::tech_pvt, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, and ast_tm::tm_mon.
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_strlen_zero(ast->cid.cid_name)) 00307 strcpy(cid.name, DEFAULT_CALLER_ID); 00308 else 00309 ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name)); 00310 00311 if (ast->cid.cid_num) 00312 ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number)); 00313 00314 p = ast->tech_pvt; 00315 00316 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00317 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); 00318 return -1; 00319 } 00320 ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); 00321 00322 start = IXJ_PHONE_RING_START(cid); 00323 if (start == -1) 00324 return -1; 00325 00326 if (p->mode == MODE_FXS) { 00327 char *digit = strchr(dest, '/'); 00328 if (digit) 00329 { 00330 digit++; 00331 while (*digit) 00332 phone_digit_end(ast, *digit++, 0); 00333 } 00334 } 00335 00336 ast_setstate(ast, AST_STATE_RINGING); 00337 ast_queue_control(ast, AST_CONTROL_RINGING); 00338 return 0; 00339 }
static void phone_check_exception | ( | struct phone_pvt * | i | ) | [static] |
Definition at line 919 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().
Referenced by do_monitor().
00920 { 00921 int offhook=0; 00922 char digit[2] = {0 , 0}; 00923 union telephony_exception phonee; 00924 /* XXX Do something XXX */ 00925 #if 0 00926 ast_debug(1, "Exception!\n"); 00927 #endif 00928 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00929 if (phonee.bits.dtmf_ready) { 00930 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00931 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) { 00932 ioctl(i->fd, PHONE_PLAY_STOP); 00933 ioctl(i->fd, PHONE_REC_STOP); 00934 ioctl(i->fd, PHONE_CPT_STOP); 00935 i->dialtone = 0; 00936 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00937 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00938 if ((i->mode != MODE_FXS || 00939 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00940 !phonee.bits.dtmf_ready) && 00941 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00942 /* It's a valid extension in its context, get moving! */ 00943 phone_new(i, AST_STATE_RING, i->context); 00944 /* No need to restart monitor, we are the monitor */ 00945 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00946 /* There is nothing in the specified extension that can match anymore. 00947 Try the default */ 00948 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00949 /* Check the default, too... */ 00950 phone_new(i, AST_STATE_RING, "default"); 00951 /* XXX This should probably be justified better XXX */ 00952 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00953 /* It's not a valid extension, give a busy signal */ 00954 ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context); 00955 ioctl(i->fd, PHONE_BUSY); 00956 i->cpt = 1; 00957 } 00958 } 00959 #if 0 00960 ast_verbose("Extension is %s\n", i->ext); 00961 #endif 00962 } 00963 } 00964 if (phonee.bits.hookstate) { 00965 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00966 if (offhook) { 00967 if (i->mode == MODE_IMMEDIATE) { 00968 phone_new(i, AST_STATE_RING, i->context); 00969 } else if (i->mode == MODE_DIALTONE) { 00970 ast_module_ref(ast_module_info->self); 00971 /* Reset the extension */ 00972 i->ext[0] = '\0'; 00973 /* Play the dialtone */ 00974 i->dialtone++; 00975 ioctl(i->fd, PHONE_PLAY_STOP); 00976 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00977 ioctl(i->fd, PHONE_PLAY_START); 00978 i->lastformat = -1; 00979 } else if (i->mode == MODE_SIGMA) { 00980 ast_module_ref(ast_module_info->self); 00981 /* Reset the extension */ 00982 i->ext[0] = '\0'; 00983 /* Play the dialtone */ 00984 i->dialtone++; 00985 ioctl(i->fd, PHONE_DIALTONE); 00986 } 00987 } else { 00988 if (i->dialtone) 00989 ast_module_unref(ast_module_info->self); 00990 memset(i->ext, 0, sizeof(i->ext)); 00991 if (i->cpt) 00992 { 00993 ioctl(i->fd, PHONE_CPT_STOP); 00994 i->cpt = 0; 00995 } 00996 ioctl(i->fd, PHONE_PLAY_STOP); 00997 ioctl(i->fd, PHONE_REC_STOP); 00998 i->dialtone = 0; 00999 i->lastformat = -1; 01000 } 01001 } 01002 if (phonee.bits.pstn_ring) { 01003 ast_verbose("Unit is ringing\n"); 01004 phone_new(i, AST_STATE_RING, i->context); 01005 } 01006 if (phonee.bits.caller_id) 01007 ast_verbose("We have caller ID\n"); 01008 01009 01010 }
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 487 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, 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.
00488 { 00489 int res; 00490 union telephony_exception phonee; 00491 struct phone_pvt *p = ast->tech_pvt; 00492 char digit; 00493 00494 /* Some nice norms */ 00495 p->fr.datalen = 0; 00496 p->fr.samples = 0; 00497 p->fr.data.ptr = NULL; 00498 p->fr.src = "Phone"; 00499 p->fr.offset = 0; 00500 p->fr.mallocd=0; 00501 p->fr.delivery = ast_tv(0,0); 00502 00503 phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION); 00504 if (phonee.bits.dtmf_ready) { 00505 ast_debug(1, "phone_exception(): DTMF\n"); 00506 00507 /* We've got a digit -- Just handle this nicely and easily */ 00508 digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII); 00509 p->fr.subclass = digit; 00510 p->fr.frametype = AST_FRAME_DTMF; 00511 return &p->fr; 00512 } 00513 if (phonee.bits.hookstate) { 00514 ast_debug(1, "Hookstate changed\n"); 00515 res = ioctl(p->fd, PHONE_HOOKSTATE); 00516 /* See if we've gone on hook, if so, notify by returning NULL */ 00517 ast_debug(1, "New hookstate: %d\n", res); 00518 if (!res && (p->mode != MODE_FXO)) 00519 return NULL; 00520 else { 00521 if (ast->_state == AST_STATE_RINGING) { 00522 /* They've picked up the phone */ 00523 p->fr.frametype = AST_FRAME_CONTROL; 00524 p->fr.subclass = AST_CONTROL_ANSWER; 00525 phone_setup(ast); 00526 ast_setstate(ast, AST_STATE_UP); 00527 return &p->fr; 00528 } else 00529 ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state); 00530 } 00531 } 00532 #if 1 00533 if (phonee.bits.pstn_ring) 00534 ast_verbose("Unit is ringing\n"); 00535 if (phonee.bits.caller_id) { 00536 ast_verbose("We have caller ID\n"); 00537 } 00538 if (phonee.bits.pstn_wink) 00539 ast_verbose("Detected Wink\n"); 00540 #endif 00541 /* Strange -- nothing there.. */ 00542 p->fr.frametype = AST_FRAME_NULL; 00543 p->fr.subclass = 0; 00544 return &p->fr; 00545 }
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 341 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.
00342 { 00343 struct phone_pvt *p; 00344 p = ast->tech_pvt; 00345 ast_debug(1, "phone_hangup(%s)\n", ast->name); 00346 if (!ast->tech_pvt) { 00347 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00348 return 0; 00349 } 00350 /* XXX Is there anything we can do to really hang up except stop recording? */ 00351 ast_setstate(ast, AST_STATE_DOWN); 00352 if (ioctl(p->fd, PHONE_REC_STOP)) 00353 ast_log(LOG_WARNING, "Failed to stop recording\n"); 00354 if (ioctl(p->fd, PHONE_PLAY_STOP)) 00355 ast_log(LOG_WARNING, "Failed to stop playing\n"); 00356 if (ioctl(p->fd, PHONE_RING_STOP)) 00357 ast_log(LOG_WARNING, "Failed to stop ringing\n"); 00358 if (ioctl(p->fd, PHONE_CPT_STOP)) 00359 ast_log(LOG_WARNING, "Failed to stop sounds\n"); 00360 00361 /* If it's an FXO, hang them up */ 00362 if (p->mode == MODE_FXO) { 00363 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 00364 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno)); 00365 } 00366 00367 /* If they're off hook, give a busy signal */ 00368 if (ioctl(p->fd, PHONE_HOOKSTATE)) { 00369 ast_debug(1, "Got hunghup, giving busy signal\n"); 00370 ioctl(p->fd, PHONE_BUSY); 00371 p->cpt = 1; 00372 } 00373 p->lastformat = -1; 00374 p->lastinput = -1; 00375 p->ministate = 0; 00376 p->obuflen = 0; 00377 p->dialtone = 0; 00378 memset(p->ext, 0, sizeof(p->ext)); 00379 ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL; 00380 ast_module_unref(ast_module_info->self); 00381 ast_verb(3, "Hungup '%s'\n", ast->name); 00382 ast->tech_pvt = NULL; 00383 ast_setstate(ast, AST_STATE_DOWN); 00384 restart_monitor(); 00385 return 0; 00386 }
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(), chan, 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 907 of file chan_phone.c.
References ast_log(), buf, errno, phone_pvt::fd, and LOG_WARNING.
Referenced by do_monitor().
00908 { 00909 int res; 00910 char buf[1024]; 00911 /* Ignore stuff we read... */ 00912 res = read(i->fd, buf, sizeof(buf)); 00913 if (res < 1) { 00914 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno)); 00915 return; 00916 } 00917 }
static struct ast_channel* phone_new | ( | struct phone_pvt * | i, | |
int | state, | |||
char * | cntx | |||
) | [static] |
Definition at line 846 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().
00847 { 00848 struct ast_channel *tmp; 00849 struct phone_codec_data queried_codec; 00850 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5); 00851 if (tmp) { 00852 tmp->tech = cur_tech; 00853 ast_channel_set_fd(tmp, 0, i->fd); 00854 /* XXX Switching formats silently causes kernel panics XXX */ 00855 if (i->mode == MODE_FXS && 00856 ioctl(i->fd, PHONE_QUERY_CODEC, &queried_codec) == 0) { 00857 if (queried_codec.type == LINEAR16) 00858 tmp->nativeformats = 00859 tmp->rawreadformat = 00860 tmp->rawwriteformat = 00861 AST_FORMAT_SLINEAR; 00862 else { 00863 tmp->nativeformats = 00864 tmp->rawreadformat = 00865 tmp->rawwriteformat = 00866 prefformat & ~AST_FORMAT_SLINEAR; 00867 } 00868 } 00869 else { 00870 tmp->nativeformats = prefformat; 00871 tmp->rawreadformat = prefformat; 00872 tmp->rawwriteformat = prefformat; 00873 } 00874 /* no need to call ast_setstate: the channel_alloc already did its job */ 00875 if (state == AST_STATE_RING) 00876 tmp->rings = 1; 00877 tmp->tech_pvt = i; 00878 ast_copy_string(tmp->context, cntx, sizeof(tmp->context)); 00879 if (!ast_strlen_zero(i->ext)) 00880 ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten)); 00881 else 00882 strcpy(tmp->exten, "s"); 00883 if (!ast_strlen_zero(i->language)) 00884 ast_string_field_set(tmp, language, i->language); 00885 00886 /* Don't use ast_set_callerid() here because it will 00887 * generate a NewCallerID event before the NewChannel event */ 00888 tmp->cid.cid_ani = ast_strdup(i->cid_num); 00889 00890 i->owner = tmp; 00891 ast_module_ref(ast_module_info->self); 00892 if (state != AST_STATE_DOWN) { 00893 if (state == AST_STATE_RING) { 00894 ioctl(tmp->fds[0], PHONE_RINGBACK); 00895 i->cpt = 1; 00896 } 00897 if (ast_pbx_start(tmp)) { 00898 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00899 ast_hangup(tmp); 00900 } 00901 } 00902 } else 00903 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00904 return tmp; 00905 }
static struct ast_frame * phone_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 547 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::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.
00548 { 00549 int res; 00550 struct phone_pvt *p = ast->tech_pvt; 00551 00552 00553 /* Some nice norms */ 00554 p->fr.datalen = 0; 00555 p->fr.samples = 0; 00556 p->fr.data.ptr = NULL; 00557 p->fr.src = "Phone"; 00558 p->fr.offset = 0; 00559 p->fr.mallocd=0; 00560 p->fr.delivery = ast_tv(0,0); 00561 00562 /* Try to read some data... */ 00563 CHECK_BLOCKING(ast); 00564 res = read(p->fd, p->buf, PHONE_MAX_BUF); 00565 ast_clear_flag(ast, AST_FLAG_BLOCKING); 00566 if (res < 0) { 00567 #if 0 00568 if (errno == EAGAIN) { 00569 ast_log(LOG_WARNING, "Null frame received\n"); 00570 p->fr.frametype = AST_FRAME_NULL; 00571 p->fr.subclass = 0; 00572 return &p->fr; 00573 } 00574 #endif 00575 ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno)); 00576 return NULL; 00577 } 00578 p->fr.data.ptr = p->buf; 00579 if (p->mode != MODE_FXS) 00580 switch(p->buf[0] & 0x3) { 00581 case '0': 00582 case '1': 00583 /* Normal */ 00584 break; 00585 case '2': 00586 case '3': 00587 /* VAD/CNG, only send two words */ 00588 res = 4; 00589 break; 00590 } 00591 p->fr.samples = 240; 00592 p->fr.datalen = res; 00593 p->fr.frametype = p->lastinput <= AST_FORMAT_AUDIO_MASK ? 00594 AST_FRAME_VOICE : 00595 p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE 00596 : AST_FRAME_VIDEO; 00597 p->fr.subclass = p->lastinput; 00598 p->fr.offset = AST_FRIENDLY_OFFSET; 00599 /* Byteswap from little-endian to native-endian */ 00600 if (p->fr.subclass == AST_FORMAT_SLINEAR) 00601 ast_frame_byteswap_le(&p->fr); 00602 return &p->fr; 00603 }
static struct ast_channel * phone_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 1214 of file chan_phone.c.
References AST_CAUSE_BUSY, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, 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().
01215 { 01216 int oldformat; 01217 struct phone_pvt *p; 01218 struct ast_channel *tmp = NULL; 01219 char *name = data; 01220 01221 /* Search for an unowned channel */ 01222 if (ast_mutex_lock(&iflock)) { 01223 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01224 return NULL; 01225 } 01226 p = iflist; 01227 while(p) { 01228 if (p->mode == MODE_FXS || 01229 format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { 01230 size_t length = strlen(p->dev + 5); 01231 if (strncmp(name, p->dev + 5, length) == 0 && 01232 !isalnum(name[length])) { 01233 if (!p->owner) { 01234 tmp = phone_new(p, AST_STATE_DOWN, p->context); 01235 break; 01236 } else 01237 *cause = AST_CAUSE_BUSY; 01238 } 01239 } 01240 p = p->next; 01241 } 01242 ast_mutex_unlock(&iflock); 01243 restart_monitor(); 01244 if (tmp == NULL) { 01245 oldformat = format; 01246 format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); 01247 if (!format) { 01248 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat); 01249 return NULL; 01250 } 01251 } 01252 return tmp; 01253 }
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 388 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().
00389 { 00390 struct phone_pvt *p; 00391 p = ast->tech_pvt; 00392 ioctl(p->fd, PHONE_CPT_STOP); 00393 /* Nothing to answering really, just start recording */ 00394 if (ast->rawreadformat == AST_FORMAT_G729A) { 00395 /* Prefer g729 */ 00396 ioctl(p->fd, PHONE_REC_STOP); 00397 if (p->lastinput != AST_FORMAT_G729A) { 00398 p->lastinput = AST_FORMAT_G729A; 00399 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { 00400 ast_log(LOG_WARNING, "Failed to set codec to g729\n"); 00401 return -1; 00402 } 00403 } 00404 } else if (ast->rawreadformat == AST_FORMAT_G723_1) { 00405 ioctl(p->fd, PHONE_REC_STOP); 00406 if (p->lastinput != AST_FORMAT_G723_1) { 00407 p->lastinput = AST_FORMAT_G723_1; 00408 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { 00409 ast_log(LOG_WARNING, "Failed to set codec to g723.1\n"); 00410 return -1; 00411 } 00412 } 00413 } else if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 00414 ioctl(p->fd, PHONE_REC_STOP); 00415 if (p->lastinput != AST_FORMAT_SLINEAR) { 00416 p->lastinput = AST_FORMAT_SLINEAR; 00417 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { 00418 ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n"); 00419 return -1; 00420 } 00421 } 00422 } else if (ast->rawreadformat == AST_FORMAT_ULAW) { 00423 ioctl(p->fd, PHONE_REC_STOP); 00424 if (p->lastinput != AST_FORMAT_ULAW) { 00425 p->lastinput = AST_FORMAT_ULAW; 00426 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { 00427 ast_log(LOG_WARNING, "Failed to set codec to uLaw\n"); 00428 return -1; 00429 } 00430 } 00431 } else if (p->mode == MODE_FXS) { 00432 ioctl(p->fd, PHONE_REC_STOP); 00433 if (p->lastinput != ast->rawreadformat) { 00434 p->lastinput = ast->rawreadformat; 00435 if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) { 00436 ast_log(LOG_WARNING, "Failed to set codec to %d\n", 00437 ast->rawreadformat); 00438 return -1; 00439 } 00440 } 00441 } else { 00442 ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat)); 00443 return -1; 00444 } 00445 if (ioctl(p->fd, PHONE_REC_START)) { 00446 ast_log(LOG_WARNING, "Failed to start recording\n"); 00447 return -1; 00448 } 00449 /* set the DTMF times (the default is too short) */ 00450 ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300); 00451 ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200); 00452 return 0; 00453 }
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_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_setstate(), AST_STATE_UP, 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.
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 & 00663 (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A)) && 00664 p->mode != MODE_FXS) { 00665 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 00666 return -1; 00667 } 00668 #if 0 00669 /* If we're not in up mode, go into up mode now */ 00670 if (ast->_state != AST_STATE_UP) { 00671 ast_setstate(ast, AST_STATE_UP); 00672 phone_setup(ast); 00673 } 00674 #else 00675 if (ast->_state != AST_STATE_UP) { 00676 /* Don't try tos end audio on-hook */ 00677 return 0; 00678 } 00679 #endif 00680 if (frame->subclass == AST_FORMAT_G729A) { 00681 if (p->lastformat != AST_FORMAT_G729A) { 00682 ioctl(p->fd, PHONE_PLAY_STOP); 00683 ioctl(p->fd, PHONE_REC_STOP); 00684 if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) { 00685 ast_log(LOG_WARNING, "Unable to set G729 mode\n"); 00686 return -1; 00687 } 00688 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) { 00689 ast_log(LOG_WARNING, "Unable to set G729 mode\n"); 00690 return -1; 00691 } 00692 p->lastformat = AST_FORMAT_G729A; 00693 p->lastinput = AST_FORMAT_G729A; 00694 /* Reset output buffer */ 00695 p->obuflen = 0; 00696 codecset = 1; 00697 } 00698 if (frame->datalen > 80) { 00699 ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen); 00700 return -1; 00701 } 00702 maxfr = 80; 00703 } else if (frame->subclass == AST_FORMAT_G723_1) { 00704 if (p->lastformat != AST_FORMAT_G723_1) { 00705 ioctl(p->fd, PHONE_PLAY_STOP); 00706 ioctl(p->fd, PHONE_REC_STOP); 00707 if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) { 00708 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n"); 00709 return -1; 00710 } 00711 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) { 00712 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n"); 00713 return -1; 00714 } 00715 p->lastformat = AST_FORMAT_G723_1; 00716 p->lastinput = AST_FORMAT_G723_1; 00717 /* Reset output buffer */ 00718 p->obuflen = 0; 00719 codecset = 1; 00720 } 00721 if (frame->datalen > 24) { 00722 ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen); 00723 return -1; 00724 } 00725 maxfr = 24; 00726 } else if (frame->subclass == AST_FORMAT_SLINEAR) { 00727 if (p->lastformat != AST_FORMAT_SLINEAR) { 00728 ioctl(p->fd, PHONE_PLAY_STOP); 00729 ioctl(p->fd, PHONE_REC_STOP); 00730 if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) { 00731 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n"); 00732 return -1; 00733 } 00734 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) { 00735 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n"); 00736 return -1; 00737 } 00738 p->lastformat = AST_FORMAT_SLINEAR; 00739 p->lastinput = AST_FORMAT_SLINEAR; 00740 codecset = 1; 00741 /* Reset output buffer */ 00742 p->obuflen = 0; 00743 } 00744 maxfr = 480; 00745 } else if (frame->subclass == AST_FORMAT_ULAW) { 00746 if (p->lastformat != AST_FORMAT_ULAW) { 00747 ioctl(p->fd, PHONE_PLAY_STOP); 00748 ioctl(p->fd, PHONE_REC_STOP); 00749 if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) { 00750 ast_log(LOG_WARNING, "Unable to set uLaw mode\n"); 00751 return -1; 00752 } 00753 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) { 00754 ast_log(LOG_WARNING, "Unable to set uLaw mode\n"); 00755 return -1; 00756 } 00757 p->lastformat = AST_FORMAT_ULAW; 00758 p->lastinput = AST_FORMAT_ULAW; 00759 codecset = 1; 00760 /* Reset output buffer */ 00761 p->obuflen = 0; 00762 } 00763 maxfr = 240; 00764 } else { 00765 if (p->lastformat != frame->subclass) { 00766 ioctl(p->fd, PHONE_PLAY_STOP); 00767 ioctl(p->fd, PHONE_REC_STOP); 00768 if (ioctl(p->fd, PHONE_PLAY_CODEC, frame->subclass)) { 00769 ast_log(LOG_WARNING, "Unable to set %d mode\n", 00770 frame->subclass); 00771 return -1; 00772 } 00773 if (ioctl(p->fd, PHONE_REC_CODEC, frame->subclass)) { 00774 ast_log(LOG_WARNING, "Unable to set %d mode\n", 00775 frame->subclass); 00776 return -1; 00777 } 00778 p->lastformat = frame->subclass; 00779 p->lastinput = frame->subclass; 00780 codecset = 1; 00781 /* Reset output buffer */ 00782 p->obuflen = 0; 00783 } 00784 maxfr = 480; 00785 } 00786 if (codecset) { 00787 ioctl(p->fd, PHONE_REC_DEPTH, 3); 00788 ioctl(p->fd, PHONE_PLAY_DEPTH, 3); 00789 if (ioctl(p->fd, PHONE_PLAY_START)) { 00790 ast_log(LOG_WARNING, "Failed to start playback\n"); 00791 return -1; 00792 } 00793 if (ioctl(p->fd, PHONE_REC_START)) { 00794 ast_log(LOG_WARNING, "Failed to start recording\n"); 00795 return -1; 00796 } 00797 } 00798 /* If we get here, we have a frame of Appropriate data */ 00799 sofar = 0; 00800 pos = frame->data.ptr; 00801 while(sofar < frame->datalen) { 00802 /* Write in no more than maxfr sized frames */ 00803 expected = frame->datalen - sofar; 00804 if (maxfr < expected) 00805 expected = maxfr; 00806 /* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX 00807 we have to pad it to 24 bytes still. */ 00808 if (frame->datalen == 4) { 00809 if (p->silencesupression) { 00810 memcpy(tmpbuf, frame->data.ptr, 4); 00811 expected = 24; 00812 res = phone_write_buf(p, tmpbuf, expected, maxfr, 0); 00813 } 00814 res = 4; 00815 expected=4; 00816 } else { 00817 int swap = 0; 00818 #if __BYTE_ORDER == __BIG_ENDIAN 00819 if (frame->subclass == AST_FORMAT_SLINEAR) 00820 swap = 1; /* Swap big-endian samples to little-endian as we copy */ 00821 #endif 00822 res = phone_write_buf(p, pos, expected, maxfr, swap); 00823 } 00824 if (res != expected) { 00825 if ((errno != EAGAIN) && (errno != EINTR)) { 00826 if (res < 0) 00827 ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno)); 00828 /* 00829 * Card is in non-blocking mode now and it works well now, but there are 00830 * lot of messages like this. So, this message is temporarily disabled. 00831 */ 00832 #if 0 00833 else 00834 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen); 00835 #endif 00836 return -1; 00837 } else /* Pretend it worked */ 00838 res = expected; 00839 } 00840 sofar += res; 00841 pos += res; 00842 } 00843 return 0; 00844 }
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 1116 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.
01117 { 01118 /* If we're supposed to be stopped -- stay stopped */ 01119 if (monitor_thread == AST_PTHREADT_STOP) 01120 return 0; 01121 if (ast_mutex_lock(&monlock)) { 01122 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 01123 return -1; 01124 } 01125 if (monitor_thread == pthread_self()) { 01126 ast_mutex_unlock(&monlock); 01127 ast_log(LOG_WARNING, "Cannot kill myself\n"); 01128 return -1; 01129 } 01130 if (monitor_thread != AST_PTHREADT_NULL) { 01131 if (ast_mutex_lock(&iflock)) { 01132 ast_mutex_unlock(&monlock); 01133 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01134 return -1; 01135 } 01136 monitor = 0; 01137 while (pthread_kill(monitor_thread, SIGURG) == 0) 01138 sched_yield(); 01139 pthread_join(monitor_thread, NULL); 01140 ast_mutex_unlock(&iflock); 01141 } 01142 monitor = 1; 01143 /* Start a new monitor */ 01144 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 01145 ast_mutex_unlock(&monlock); 01146 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 01147 return -1; 01148 } 01149 ast_mutex_unlock(&monlock); 01150 return 0; 01151 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1334 of file chan_phone.c.
References __unload_module().
01335 { 01336 return __unload_module(); 01337 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 1452 of file chan_phone.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1452 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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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] |
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
Definition at line 111 of file chan_phone.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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] |
int 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.