#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.
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 | 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_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 1236 of file chan_phone.c. References ast_channel_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cur_tech, phone_pvt::fd, free, iflist, LOG_WARNING, phone_pvt::next, and phone_pvt::owner. 01237 { 01238 struct phone_pvt *p, *pl; 01239 /* First, take us out of the channel loop */ 01240 ast_channel_unregister(cur_tech); 01241 if (!ast_mutex_lock(&iflock)) { 01242 /* Hangup all interfaces if they have an owner */ 01243 p = iflist; 01244 while(p) { 01245 if (p->owner) 01246 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 01247 p = p->next; 01248 } 01249 iflist = NULL; 01250 ast_mutex_unlock(&iflock); 01251 } else { 01252 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01253 return -1; 01254 } 01255 if (!ast_mutex_lock(&monlock)) { 01256 if (monitor_thread > AST_PTHREADT_NULL) { 01257 pthread_cancel(monitor_thread); 01258 pthread_join(monitor_thread, NULL); 01259 } 01260 monitor_thread = AST_PTHREADT_STOP; 01261 ast_mutex_unlock(&monlock); 01262 } else { 01263 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01264 return -1; 01265 } 01266 01267 if (!ast_mutex_lock(&iflock)) { 01268 /* Destroy all the interfaces and free their memory */ 01269 p = iflist; 01270 while(p) { 01271 /* Close the socket, assuming it's real */ 01272 if (p->fd > -1) 01273 close(p->fd); 01274 pl = p; 01275 p = p->next; 01276 /* Free associated memory */ 01277 free(pl); 01278 } 01279 iflist = NULL; 01280 ast_mutex_unlock(&iflock); 01281 } else { 01282 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01283 return -1; 01284 } 01285 01286 return 0; 01287 }
|
|
|
|
|
|
|
|
Provides a description of the module.
Definition at line 1406 of file chan_phone.c. 01407 { 01408 return (char *) desc; 01409 }
|
|
Definition at line 958 of file chan_phone.c. References ast_log(), ast_mutex_lock(), LOG_ERROR, LOG_WARNING, and n. 00959 { 00960 fd_set rfds, efds; 00961 int n, res; 00962 struct phone_pvt *i; 00963 int tonepos = 0; 00964 /* The tone we're playing this round */ 00965 struct timeval tv = {0,0}; 00966 int dotone; 00967 /* This thread monitors all the frame relay interfaces which are not yet in use 00968 (and thus do not have a separate thread) indefinitely */ 00969 /* From here on out, we die whenever asked */ 00970 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 00971 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 00972 return NULL; 00973 } 00974 for(;;) { 00975 /* Don't let anybody kill us right away. Nobody should lock the interface list 00976 and wait for the monitor list, but the other way around is okay. */ 00977 if (ast_mutex_lock(&monlock)) { 00978 ast_log(LOG_ERROR, "Unable to grab monitor lock\n"); 00979 return NULL; 00980 } 00981 /* Lock the interface list */ 00982 if (ast_mutex_lock(&iflock)) { 00983 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 00984 ast_mutex_unlock(&monlock); 00985 return NULL; 00986 } 00987 /* Build the stuff we're going to select on, that is the socket of every 00988 phone_pvt that does not have an associated owner channel */ 00989 n = -1; 00990 FD_ZERO(&rfds); 00991 FD_ZERO(&efds); 00992 i = iflist; 00993 dotone = 0; 00994 while(i) { 00995 if (FD_ISSET(i->fd, &rfds)) 00996 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 00997 if (!i->owner) { 00998 /* This needs to be watched, as it lacks an owner */ 00999 FD_SET(i->fd, &rfds); 01000 FD_SET(i->fd, &efds); 01001 if (i->fd > n) 01002 n = i->fd; 01003 if (i->dialtone) { 01004 /* Remember we're going to have to come back and play 01005 more dialtones */ 01006 if (ast_tvzero(tv)) { 01007 /* If we're due for a dialtone, play one */ 01008 if (write(i->fd, DialTone + tonepos, 240) != 240) 01009 ast_log(LOG_WARNING, "Dial tone write error\n"); 01010 } 01011 dotone++; 01012 } 01013 } 01014 01015 i = i->next; 01016 } 01017 /* Okay, now that we know what to do, release the interface lock */ 01018 ast_mutex_unlock(&iflock); 01019 01020 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 01021 ast_mutex_unlock(&monlock); 01022 01023 /* Wait indefinitely for something to happen */ 01024 if (dotone) { 01025 /* If we're ready to recycle the time, set it to 30 ms */ 01026 tonepos += 240; 01027 if (tonepos >= sizeof(DialTone)) 01028 tonepos = 0; 01029 if (ast_tvzero(tv)) { 01030 tv = ast_tv(30000, 0); 01031 } 01032 res = ast_select(n + 1, &rfds, NULL, &efds, &tv); 01033 } else { 01034 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 01035 tv = ast_tv(0,0); 01036 tonepos = 0; 01037 } 01038 /* Okay, select has finished. Let's see what happened. */ 01039 if (res < 0) { 01040 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno)); 01041 continue; 01042 } 01043 /* If there are no fd's changed, just continue, it's probably time 01044 to play some more dialtones */ 01045 if (!res) 01046 continue; 01047 /* Alright, lock the interface list again, and let's look and see what has 01048 happened */ 01049 if (ast_mutex_lock(&iflock)) { 01050 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01051 continue; 01052 } 01053 01054 i = iflist; 01055 for(; i; i=i->next) { 01056 if (FD_ISSET(i->fd, &rfds)) { 01057 if (i->owner) { 01058 continue; 01059 } 01060 phone_mini_packet(i); 01061 } 01062 if (FD_ISSET(i->fd, &efds)) { 01063 if (i->owner) { 01064 continue; 01065 } 01066 phone_check_exception(i); 01067 } 01068 } 01069 ast_mutex_unlock(&iflock); 01070 } 01071 /* Never reached */ 01072 return NULL; 01073 01074 }
|
|
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 1411 of file chan_phone.c. References ASTERISK_GPL_KEY. 01412 { 01413 return ASTERISK_GPL_KEY; 01414 }
|
|
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 1294 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, cur_tech, DEFAULT_GAIN, iflist, 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(), phone_tech, phone_tech_fxs, restart_monitor(), rxgain, txgain, and ast_variable::value. 01295 { 01296 struct ast_config *cfg; 01297 struct ast_variable *v; 01298 struct phone_pvt *tmp; 01299 int mode = MODE_IMMEDIATE; 01300 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ 01301 cfg = ast_config_load(config); 01302 01303 /* We *must* have a config file otherwise stop immediately */ 01304 if (!cfg) { 01305 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 01306 return -1; 01307 } 01308 if (ast_mutex_lock(&iflock)) { 01309 /* It's a little silly to lock it, but we mind as well just to be sure */ 01310 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01311 return -1; 01312 } 01313 v = ast_variable_browse(cfg, "interfaces"); 01314 while(v) { 01315 /* Create the interface list */ 01316 if (!strcasecmp(v->name, "device")) { 01317 tmp = mkif(v->value, mode, txgain, rxgain); 01318 if (tmp) { 01319 tmp->next = iflist; 01320 iflist = tmp; 01321 01322 } else { 01323 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01324 ast_config_destroy(cfg); 01325 ast_mutex_unlock(&iflock); 01326 __unload_module(); 01327 return -1; 01328 } 01329 } else if (!strcasecmp(v->name, "silencesupression")) { 01330 silencesupression = ast_true(v->value); 01331 } else if (!strcasecmp(v->name, "language")) { 01332 strncpy(language, v->value, sizeof(language)-1); 01333 } else if (!strcasecmp(v->name, "callerid")) { 01334 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 01335 } else if (!strcasecmp(v->name, "mode")) { 01336 if (!strncasecmp(v->value, "di", 2)) 01337 mode = MODE_DIALTONE; 01338 else if (!strncasecmp(v->value, "im", 2)) 01339 mode = MODE_IMMEDIATE; 01340 else if (!strncasecmp(v->value, "fxs", 3)) { 01341 mode = MODE_FXS; 01342 prefformat = 0x01ff0000; /* All non-voice */ 01343 } 01344 else if (!strncasecmp(v->value, "fx", 2)) 01345 mode = MODE_FXO; 01346 else 01347 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01348 } else if (!strcasecmp(v->name, "context")) { 01349 strncpy(context, v->value, sizeof(context)-1); 01350 } else if (!strcasecmp(v->name, "format")) { 01351 if (!strcasecmp(v->value, "g723.1")) { 01352 prefformat = AST_FORMAT_G723_1; 01353 } else if (!strcasecmp(v->value, "slinear")) { 01354 if (mode == MODE_FXS) 01355 prefformat |= AST_FORMAT_SLINEAR; 01356 else prefformat = AST_FORMAT_SLINEAR; 01357 } else if (!strcasecmp(v->value, "ulaw")) { 01358 prefformat = AST_FORMAT_ULAW; 01359 } else 01360 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value); 01361 } else if (!strcasecmp(v->name, "echocancel")) { 01362 if (!strcasecmp(v->value, "off")) { 01363 echocancel = AEC_OFF; 01364 } else if (!strcasecmp(v->value, "low")) { 01365 echocancel = AEC_LOW; 01366 } else if (!strcasecmp(v->value, "medium")) { 01367 echocancel = AEC_MED; 01368 } else if (!strcasecmp(v->value, "high")) { 01369 echocancel = AEC_HIGH; 01370 } else 01371 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value); 01372 } else if (!strcasecmp(v->name, "txgain")) { 01373 txgain = parse_gain_value(v->name, v->value); 01374 } else if (!strcasecmp(v->name, "rxgain")) { 01375 rxgain = parse_gain_value(v->name, v->value); 01376 } 01377 v = v->next; 01378 } 01379 ast_mutex_unlock(&iflock); 01380 01381 if (mode == MODE_FXS) { 01382 phone_tech_fxs.capabilities = prefformat; 01383 cur_tech = &phone_tech_fxs; 01384 } else 01385 cur_tech = (struct ast_channel_tech *) &phone_tech; 01386 01387 /* Make sure we can register our Adtranphone channel type */ 01388 01389 if (ast_channel_register(cur_tech)) { 01390 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 01391 ast_config_destroy(cfg); 01392 __unload_module(); 01393 return -1; 01394 } 01395 ast_config_destroy(cfg); 01396 /* And start the monitor for the first time */ 01397 restart_monitor(); 01398 return 0; 01399 }
|
|
Definition at line 1112 of file chan_phone.c. References ast_log(), phone_pvt::cid_name, phone_pvt::cid_num, phone_pvt::context, phone_pvt::cpt, phone_pvt::dev, phone_pvt::dialtone, phone_pvt::ext, phone_pvt::fd, free, phone_pvt::language, phone_pvt::lastformat, phone_pvt::lastinput, LOG_DEBUG, LOG_WARNING, malloc, phone_pvt::ministate, phone_pvt::mode, MODE_FXO, MODE_FXS, phone_pvt::next, phone_pvt::obuflen, phone_pvt::owner, phone_pvt::rxgain, phone_pvt::silencesupression, and phone_pvt::txgain. 01113 { 01114 /* Make a phone_pvt structure for this interface */ 01115 struct phone_pvt *tmp; 01116 int flags; 01117 01118 tmp = malloc(sizeof(struct phone_pvt)); 01119 if (tmp) { 01120 tmp->fd = open(iface, O_RDWR); 01121 if (tmp->fd < 0) { 01122 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 01123 free(tmp); 01124 return NULL; 01125 } 01126 if (mode == MODE_FXO) { 01127 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) 01128 ast_log(LOG_DEBUG, "Unable to set port to PSTN\n"); 01129 } else { 01130 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 01131 if (mode != MODE_FXS) 01132 ast_log(LOG_DEBUG, "Unable to set port to POTS\n"); 01133 } 01134 ioctl(tmp->fd, PHONE_PLAY_STOP); 01135 ioctl(tmp->fd, PHONE_REC_STOP); 01136 ioctl(tmp->fd, PHONE_RING_STOP); 01137 ioctl(tmp->fd, PHONE_CPT_STOP); 01138 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 01139 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno)); 01140 if (echocancel != AEC_OFF) 01141 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel); 01142 if (silencesupression) 01143 tmp->silencesupression = 1; 01144 #ifdef PHONE_VAD 01145 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); 01146 #endif 01147 tmp->mode = mode; 01148 flags = fcntl(tmp->fd, F_GETFL); 01149 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); 01150 tmp->owner = NULL; 01151 tmp->lastformat = -1; 01152 tmp->lastinput = -1; 01153 tmp->ministate = 0; 01154 memset(tmp->ext, 0, sizeof(tmp->ext)); 01155 strncpy(tmp->language, language, sizeof(tmp->language)-1); 01156 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1); 01157 strncpy(tmp->context, context, sizeof(tmp->context)-1); 01158 tmp->next = NULL; 01159 tmp->obuflen = 0; 01160 tmp->dialtone = 0; 01161 tmp->cpt = 0; 01162 strncpy(tmp->cid_num, cid_num, sizeof(tmp->cid_num)-1); 01163 strncpy(tmp->cid_name, cid_name, sizeof(tmp->cid_name)-1); 01164 tmp->txgain = txgain; 01165 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain); 01166 tmp->rxgain = rxgain; 01167 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain); 01168 } 01169 return tmp; 01170 }
|
|
Definition at line 1214 of file chan_phone.c. References ast_log(), DEFAULT_GAIN, and LOG_ERROR. Referenced by load_module(). 01215 { 01216 float gain; 01217 01218 /* try to scan number */ 01219 if (sscanf(value, "%f", &gain) != 1) 01220 { 01221 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", 01222 value, gain_type, config); 01223 return DEFAULT_GAIN; 01224 } 01225 01226 /* multiplicate gain by 1.0 gain value */ 01227 gain = gain * (float)DEFAULT_GAIN; 01228 01229 /* percentage? */ 01230 if (value[strlen(value) - 1] == '%') 01231 return (int)(gain / (float)100); 01232 01233 return (int)gain; 01234 }
|
|
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 864 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(), and usecnt_lock. 00865 { 00866 int offhook=0; 00867 char digit[2] = {0 , 0}; 00868 union telephony_exception phonee; 00869 /* XXX Do something XXX */ 00870 #if 0 00871 ast_log(LOG_DEBUG, "Exception!\n"); 00872 #endif 00873 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION); 00874 if (phonee.bits.dtmf_ready) { 00875 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII); 00876 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS) { 00877 ioctl(i->fd, PHONE_PLAY_STOP); 00878 ioctl(i->fd, PHONE_REC_STOP); 00879 ioctl(i->fd, PHONE_CPT_STOP); 00880 i->dialtone = 0; 00881 if (strlen(i->ext) < AST_MAX_EXTENSION - 1) 00882 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1); 00883 if ((i->mode != MODE_FXS || 00884 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) || 00885 !phonee.bits.dtmf_ready) && 00886 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00887 /* It's a valid extension in its context, get moving! */ 00888 phone_new(i, AST_STATE_RING, i->context); 00889 /* No need to restart monitor, we are the monitor */ 00890 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) { 00891 /* There is nothing in the specified extension that can match anymore. 00892 Try the default */ 00893 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00894 /* Check the default, too... */ 00895 phone_new(i, AST_STATE_RING, "default"); 00896 /* XXX This should probably be justified better XXX */ 00897 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) { 00898 /* It's not a valid extension, give a busy signal */ 00899 if (option_debug) 00900 ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context); 00901 ioctl(i->fd, PHONE_BUSY); 00902 i->cpt = 1; 00903 } 00904 } 00905 #if 0 00906 ast_verbose("Extension is %s\n", i->ext); 00907 #endif 00908 } 00909 } 00910 if (phonee.bits.hookstate) { 00911 offhook = ioctl(i->fd, PHONE_HOOKSTATE); 00912 if (offhook) { 00913 if (i->mode == MODE_IMMEDIATE) { 00914 phone_new(i, AST_STATE_RING, i->context); 00915 } else if (i->mode == MODE_DIALTONE) { 00916 ast_mutex_lock(&usecnt_lock); 00917 usecnt++; 00918 ast_mutex_unlock(&usecnt_lock); 00919 ast_update_use_count(); 00920 /* Reset the extension */ 00921 i->ext[0] = '\0'; 00922 /* Play the dialtone */ 00923 i->dialtone++; 00924 ioctl(i->fd, PHONE_PLAY_STOP); 00925 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW); 00926 ioctl(i->fd, PHONE_PLAY_START); 00927 i->lastformat = -1; 00928 } 00929 } else { 00930 if (i->dialtone) { 00931 ast_mutex_lock(&usecnt_lock); 00932 usecnt--; 00933 ast_mutex_unlock(&usecnt_lock); 00934 ast_update_use_count(); 00935 } 00936 memset(i->ext, 0, sizeof(i->ext)); 00937 if (i->cpt) 00938 { 00939 ioctl(i->fd, PHONE_CPT_STOP); 00940 i->cpt = 0; 00941 } 00942 ioctl(i->fd, PHONE_PLAY_STOP); 00943 ioctl(i->fd, PHONE_REC_STOP); 00944 i->dialtone = 0; 00945 i->lastformat = -1; 00946 } 00947 } 00948 if (phonee.bits.pstn_ring) { 00949 ast_verbose("Unit is ringing\n"); 00950 phone_new(i, AST_STATE_RING, i->context); 00951 } 00952 if (phonee.bits.caller_id) 00953 ast_verbose("We have caller ID\n"); 00954 00955 00956 }
|
|
Definition at line 203 of file chan_phone.c. References ast_log(), phone_pvt::fd, phone_pvt::lastformat, LOG_NOTICE, LOG_WARNING, and ast_channel::tech_pvt. 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, and ast_channel::tech_pvt. 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, phone_pvt::owner, restart_monitor(), ast_channel::tech_pvt, 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 852 of file chan_phone.c. References ast_log(), phone_pvt::fd, and LOG_WARNING. 00853 { 00854 int res; 00855 char buf[1024]; 00856 /* Ignore stuff we read... */ 00857 res = read(i->fd, buf, sizeof(buf)); 00858 if (res < 1) { 00859 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno)); 00860 return; 00861 } 00862 }
|
|
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_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, cur_tech, phone_pvt::dev, phone_pvt::ext, phone_pvt::fd, phone_pvt::language, LOG_WARNING, phone_pvt::mode, MODE_FXS, phone_pvt::owner, strdup, 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 if (!ast_strlen_zero(i->cid_num)) 00829 tmp->cid.cid_num = strdup(i->cid_num); 00830 if (!ast_strlen_zero(i->cid_name)) 00831 tmp->cid.cid_name = strdup(i->cid_name); 00832 i->owner = tmp; 00833 ast_mutex_lock(&usecnt_lock); 00834 usecnt++; 00835 ast_mutex_unlock(&usecnt_lock); 00836 ast_update_use_count(); 00837 if (state != AST_STATE_DOWN) { 00838 if (state == AST_STATE_RING) { 00839 ioctl(tmp->fds[0], PHONE_RINGBACK); 00840 i->cpt = 1; 00841 } 00842 if (ast_pbx_start(tmp)) { 00843 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00844 ast_hangup(tmp); 00845 } 00846 } 00847 } else 00848 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00849 return tmp; 00850 }
|
|
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, and ast_channel::tech_pvt. 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 1172 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(). 01173 { 01174 int oldformat; 01175 struct phone_pvt *p; 01176 struct ast_channel *tmp = NULL; 01177 char *name = data; 01178 01179 /* Search for an unowned channel */ 01180 if (ast_mutex_lock(&iflock)) { 01181 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 01182 return NULL; 01183 } 01184 p = iflist; 01185 while(p) { 01186 if (p->mode == MODE_FXS || 01187 format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) { 01188 size_t length = strlen(p->dev + 5); 01189 if (strncmp(name, p->dev + 5, length) == 0 && 01190 !isalnum(name[length])) { 01191 if (!p->owner) { 01192 tmp = phone_new(p, AST_STATE_DOWN, p->context); 01193 break; 01194 } else 01195 *cause = AST_CAUSE_BUSY; 01196 } 01197 } 01198 p = p->next; 01199 } 01200 ast_mutex_unlock(&iflock); 01201 restart_monitor(); 01202 if (tmp == NULL) { 01203 oldformat = format; 01204 format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW); 01205 if (!format) { 01206 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat); 01207 return NULL; 01208 } 01209 } 01210 return tmp; 01211 }
|
|
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 1076 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, and LOG_WARNING. 01077 { 01078 /* If we're supposed to be stopped -- stay stopped */ 01079 if (monitor_thread == AST_PTHREADT_STOP) 01080 return 0; 01081 if (ast_mutex_lock(&monlock)) { 01082 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 01083 return -1; 01084 } 01085 if (monitor_thread == pthread_self()) { 01086 ast_mutex_unlock(&monlock); 01087 ast_log(LOG_WARNING, "Cannot kill myself\n"); 01088 return -1; 01089 } 01090 if (monitor_thread != AST_PTHREADT_NULL) { 01091 if (ast_mutex_lock(&iflock)) { 01092 ast_mutex_unlock(&monlock); 01093 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 01094 return -1; 01095 } 01096 pthread_cancel(monitor_thread); 01097 #if 0 01098 pthread_join(monitor_thread, NULL); 01099 #endif 01100 ast_mutex_unlock(&iflock); 01101 } 01102 /* Start a new monitor */ 01103 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) { 01104 ast_mutex_unlock(&monlock); 01105 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 01106 return -1; 01107 } 01108 ast_mutex_unlock(&monlock); 01109 return 0; 01110 }
|
|
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 1289 of file chan_phone.c. References __unload_module(). 01290 { 01291 return __unload_module(); 01292 }
|
|
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 1401 of file chan_phone.c. 01402 { 01403 return usecnt; 01404 }
|
|
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. Referenced by __unload_module(), load_module(), and phone_new(). |
|
Definition at line 81 of file chan_phone.c. |
|
Definition at line 93 of file chan_phone.c. Referenced by fill_defaults(), misdn_cfg_get(), and misdn_cfg_get_config_string(). |
|
|
|
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. Referenced by load_module(). |
|
Definition at line 177 of file chan_phone.c. Referenced by load_module(). |
|
Definition at line 97 of file chan_phone.c. |
|
Definition at line 95 of file chan_phone.c. |
|
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. |