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