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