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