#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"
Include dependency graph for chan_phone.c:
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 int | __unload_module (void) |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Linux Telephony API Support") | |
AST_MUTEX_DEFINE_STATIC (monlock) | |
AST_MUTEX_DEFINE_STATIC (iflock) | |
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 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 char | language [MAX_LANGUAGE] = "" |
static unsigned int | monitor |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
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 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, LOG_WARNING, 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 }
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Linux Telephony API Support" | ||||
) |
AST_MUTEX_DEFINE_STATIC | ( | monlock | ) |
AST_MUTEX_DEFINE_STATIC | ( | iflock | ) |
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(), phone_pvt::dev, DialTone, phone_pvt::dialtone, errno, phone_pvt::fd, iflist, 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_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, 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_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, "%f", &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, 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_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, 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_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, 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, 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_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(), 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, 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 + 4, 0, sizeof(tmpbuf) - 4); 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, phone_pvt::obuflen, and space.
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(), LOG_ERROR, and LOG_WARNING.
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 }
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.
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.
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.