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