![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_phone.c File Reference
Definition in file chan_phone.c.
#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <linux/telephony.h>
#include <linux/version.h>
#include <linux/ixjuser.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/musiconhold.h"
#include "DialTone.h"
Include dependency graph for chan_phone.c:

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