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