00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211596 $")
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <ctype.h>
00039 #include <sys/socket.h>
00040 #include <sys/time.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 #include <stdlib.h>
00044 #include <arpa/inet.h>
00045 #include <fcntl.h>
00046 #include <sys/ioctl.h>
00047 #include <signal.h>
00048 #ifdef HAVE_LINUX_COMPILER_H
00049 #include <linux/compiler.h>
00050 #endif
00051 #include <linux/telephony.h>
00052
00053 #include <linux/version.h>
00054 #include "linux/ixjuser.h"
00055
00056 #include "asterisk/lock.h"
00057 #include "asterisk/channel.h"
00058 #include "asterisk/config.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/module.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/utils.h"
00064 #include "asterisk/callerid.h"
00065 #include "asterisk/causes.h"
00066 #include "asterisk/stringfields.h"
00067 #include "asterisk/musiconhold.h"
00068
00069 #include "DialTone.h"
00070
00071 #ifdef QTI_PHONEJACK_TJ_PCI
00072 #define QNDRV_VER 310
00073 #else
00074 #define QNDRV_VER 100
00075 #endif
00076
00077 #if QNDRV_VER > 100
00078 #ifdef __linux__
00079 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x);
00080 #else
00081 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, x);
00082 #endif
00083 #else
00084 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x);
00085 #endif
00086
00087 #define DEFAULT_CALLER_ID "Unknown"
00088 #define PHONE_MAX_BUF 480
00089 #define DEFAULT_GAIN 0x100
00090
00091 static const char tdesc[] = "Standard Linux Telephony API Driver";
00092 static const char config[] = "phone.conf";
00093
00094
00095 static char context[AST_MAX_EXTENSION] = "default";
00096
00097
00098 static char language[MAX_LANGUAGE] = "";
00099
00100 static int echocancel = AEC_OFF;
00101
00102 static int silencesupression = 0;
00103
00104 static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
00105
00106
00107 AST_MUTEX_DEFINE_STATIC(iflock);
00108
00109
00110
00111 AST_MUTEX_DEFINE_STATIC(monlock);
00112
00113
00114 static unsigned int monitor;
00115
00116
00117
00118 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00119
00120 static int restart_monitor(void);
00121
00122
00123
00124
00125 #define MODE_DIALTONE 1
00126 #define MODE_IMMEDIATE 2
00127 #define MODE_FXO 3
00128 #define MODE_FXS 4
00129 #define MODE_SIGMA 5
00130
00131 static struct phone_pvt {
00132 int fd;
00133 struct ast_channel *owner;
00134 int mode;
00135 int lastformat;
00136 int lastinput;
00137 int ministate;
00138 char dev[256];
00139 struct phone_pvt *next;
00140 struct ast_frame fr;
00141 char offset[AST_FRIENDLY_OFFSET];
00142 char buf[PHONE_MAX_BUF];
00143 int obuflen;
00144 int dialtone;
00145 int txgain, rxgain;
00146
00147 int cpt;
00148 int silencesupression;
00149 char context[AST_MAX_EXTENSION];
00150 char obuf[PHONE_MAX_BUF * 2];
00151 char ext[AST_MAX_EXTENSION];
00152 char language[MAX_LANGUAGE];
00153 char cid_num[AST_MAX_EXTENSION];
00154 char cid_name[AST_MAX_EXTENSION];
00155 } *iflist = NULL;
00156
00157 static char cid_num[AST_MAX_EXTENSION];
00158 static char cid_name[AST_MAX_EXTENSION];
00159
00160 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause);
00161 static int phone_digit_begin(struct ast_channel *ast, char digit);
00162 static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00163 static int phone_call(struct ast_channel *ast, char *dest, int timeout);
00164 static int phone_hangup(struct ast_channel *ast);
00165 static int phone_answer(struct ast_channel *ast);
00166 static struct ast_frame *phone_read(struct ast_channel *ast);
00167 static int phone_write(struct ast_channel *ast, struct ast_frame *frame);
00168 static struct ast_frame *phone_exception(struct ast_channel *ast);
00169 static int phone_send_text(struct ast_channel *ast, const char *text);
00170 static int phone_fixup(struct ast_channel *old, struct ast_channel *new);
00171 static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
00172
00173 static const struct ast_channel_tech phone_tech = {
00174 .type = "Phone",
00175 .description = tdesc,
00176 .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
00177 .requester = phone_request,
00178 .send_digit_begin = phone_digit_begin,
00179 .send_digit_end = phone_digit_end,
00180 .call = phone_call,
00181 .hangup = phone_hangup,
00182 .answer = phone_answer,
00183 .read = phone_read,
00184 .write = phone_write,
00185 .exception = phone_exception,
00186 .indicate = phone_indicate,
00187 .fixup = phone_fixup
00188 };
00189
00190 static struct ast_channel_tech phone_tech_fxs = {
00191 .type = "Phone",
00192 .description = tdesc,
00193 .requester = phone_request,
00194 .send_digit_begin = phone_digit_begin,
00195 .send_digit_end = phone_digit_end,
00196 .call = phone_call,
00197 .hangup = phone_hangup,
00198 .answer = phone_answer,
00199 .read = phone_read,
00200 .write = phone_write,
00201 .exception = phone_exception,
00202 .write_video = phone_write,
00203 .send_text = phone_send_text,
00204 .indicate = phone_indicate,
00205 .fixup = phone_fixup
00206 };
00207
00208 static struct ast_channel_tech *cur_tech;
00209
00210 static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
00211 {
00212 struct phone_pvt *p = chan->tech_pvt;
00213 int res=-1;
00214 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
00215 switch(condition) {
00216 case AST_CONTROL_FLASH:
00217 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00218 usleep(320000);
00219 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00220 p->lastformat = -1;
00221 res = 0;
00222 break;
00223 case AST_CONTROL_HOLD:
00224 ast_moh_start(chan, data, NULL);
00225 break;
00226 case AST_CONTROL_UNHOLD:
00227 ast_moh_stop(chan);
00228 break;
00229 case AST_CONTROL_SRCUPDATE:
00230 res = 0;
00231 break;
00232 default:
00233 ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name);
00234 }
00235 return res;
00236 }
00237
00238 static int phone_fixup(struct ast_channel *old, struct ast_channel *new)
00239 {
00240 struct phone_pvt *pvt = old->tech_pvt;
00241 if (pvt && pvt->owner == old)
00242 pvt->owner = new;
00243 return 0;
00244 }
00245
00246 static int phone_digit_begin(struct ast_channel *chan, char digit)
00247 {
00248
00249 return 0;
00250 }
00251
00252 static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
00253 {
00254 struct phone_pvt *p;
00255 int outdigit;
00256 p = ast->tech_pvt;
00257 ast_log(LOG_DEBUG, "Dialed %c\n", digit);
00258 switch(digit) {
00259 case '0':
00260 case '1':
00261 case '2':
00262 case '3':
00263 case '4':
00264 case '5':
00265 case '6':
00266 case '7':
00267 case '8':
00268 case '9':
00269 outdigit = digit - '0';
00270 break;
00271 case '*':
00272 outdigit = 11;
00273 break;
00274 case '#':
00275 outdigit = 12;
00276 break;
00277 case 'f':
00278 case 'F':
00279 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00280 usleep(320000);
00281 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00282 p->lastformat = -1;
00283 return 0;
00284 default:
00285 ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
00286 return -1;
00287 }
00288 ast_log(LOG_DEBUG, "Dialed %d\n", outdigit);
00289 ioctl(p->fd, PHONE_PLAY_TONE, outdigit);
00290 p->lastformat = -1;
00291 return 0;
00292 }
00293
00294 static int phone_call(struct ast_channel *ast, char *dest, int timeout)
00295 {
00296 struct phone_pvt *p;
00297
00298 PHONE_CID cid;
00299 time_t UtcTime;
00300 struct tm tm;
00301 int start;
00302
00303 time(&UtcTime);
00304 ast_localtime(&UtcTime, &tm, NULL);
00305
00306 memset(&cid, 0, sizeof(PHONE_CID));
00307 if(&tm != NULL) {
00308 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1));
00309 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday);
00310 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour);
00311 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
00312 }
00313
00314 if (ast_strlen_zero(ast->cid.cid_name))
00315 strcpy(cid.name, DEFAULT_CALLER_ID);
00316 else
00317 ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
00318
00319 if (ast->cid.cid_num)
00320 ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
00321
00322 p = ast->tech_pvt;
00323
00324 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00325 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
00326 return -1;
00327 }
00328 if (option_debug)
00329 ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
00330
00331 start = IXJ_PHONE_RING_START(cid);
00332 if (start == -1)
00333 return -1;
00334
00335 if (p->mode == MODE_FXS) {
00336 char *digit = strchr(dest, '/');
00337 if (digit)
00338 {
00339 digit++;
00340 while (*digit)
00341 phone_digit_end(ast, *digit++, 0);
00342 }
00343 }
00344
00345 ast_setstate(ast, AST_STATE_RINGING);
00346 ast_queue_control(ast, AST_CONTROL_RINGING);
00347 return 0;
00348 }
00349
00350 static int phone_hangup(struct ast_channel *ast)
00351 {
00352 struct phone_pvt *p;
00353 p = ast->tech_pvt;
00354 if (option_debug)
00355 ast_log(LOG_DEBUG, "phone_hangup(%s)\n", ast->name);
00356 if (!ast->tech_pvt) {
00357 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00358 return 0;
00359 }
00360
00361 ast_setstate(ast, AST_STATE_DOWN);
00362 if (ioctl(p->fd, PHONE_REC_STOP))
00363 ast_log(LOG_WARNING, "Failed to stop recording\n");
00364 if (ioctl(p->fd, PHONE_PLAY_STOP))
00365 ast_log(LOG_WARNING, "Failed to stop playing\n");
00366 if (ioctl(p->fd, PHONE_RING_STOP))
00367 ast_log(LOG_WARNING, "Failed to stop ringing\n");
00368 if (ioctl(p->fd, PHONE_CPT_STOP))
00369 ast_log(LOG_WARNING, "Failed to stop sounds\n");
00370
00371
00372 if (p->mode == MODE_FXO) {
00373 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
00374 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
00375 }
00376
00377
00378 if (ioctl(p->fd, PHONE_HOOKSTATE)) {
00379 if (option_debug)
00380 ast_log(LOG_DEBUG, "Got hunghup, giving busy signal\n");
00381 ioctl(p->fd, PHONE_BUSY);
00382 p->cpt = 1;
00383 }
00384 p->lastformat = -1;
00385 p->lastinput = -1;
00386 p->ministate = 0;
00387 p->obuflen = 0;
00388 p->dialtone = 0;
00389 memset(p->ext, 0, sizeof(p->ext));
00390 ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
00391 ast_module_unref(ast_module_info->self);
00392 if (option_verbose > 2)
00393 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
00394 ast->tech_pvt = NULL;
00395 ast_setstate(ast, AST_STATE_DOWN);
00396 restart_monitor();
00397 return 0;
00398 }
00399
00400 static int phone_setup(struct ast_channel *ast)
00401 {
00402 struct phone_pvt *p;
00403 p = ast->tech_pvt;
00404 ioctl(p->fd, PHONE_CPT_STOP);
00405
00406 if (ast->rawreadformat == AST_FORMAT_G723_1) {
00407
00408 ioctl(p->fd, PHONE_REC_STOP);
00409 if (p->lastinput != AST_FORMAT_G723_1) {
00410 p->lastinput = AST_FORMAT_G723_1;
00411 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00412 ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
00413 return -1;
00414 }
00415 }
00416 } else if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
00417 ioctl(p->fd, PHONE_REC_STOP);
00418 if (p->lastinput != AST_FORMAT_SLINEAR) {
00419 p->lastinput = AST_FORMAT_SLINEAR;
00420 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00421 ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
00422 return -1;
00423 }
00424 }
00425 } else if (ast->rawreadformat == AST_FORMAT_ULAW) {
00426 ioctl(p->fd, PHONE_REC_STOP);
00427 if (p->lastinput != AST_FORMAT_ULAW) {
00428 p->lastinput = AST_FORMAT_ULAW;
00429 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00430 ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
00431 return -1;
00432 }
00433 }
00434 } else if (p->mode == MODE_FXS) {
00435 ioctl(p->fd, PHONE_REC_STOP);
00436 if (p->lastinput != ast->rawreadformat) {
00437 p->lastinput = ast->rawreadformat;
00438 if (ioctl(p->fd, PHONE_REC_CODEC, ast->rawreadformat)) {
00439 ast_log(LOG_WARNING, "Failed to set codec to %d\n",
00440 ast->rawreadformat);
00441 return -1;
00442 }
00443 }
00444 } else {
00445 ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->rawreadformat));
00446 return -1;
00447 }
00448 if (ioctl(p->fd, PHONE_REC_START)) {
00449 ast_log(LOG_WARNING, "Failed to start recording\n");
00450 return -1;
00451 }
00452
00453 ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300);
00454 ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200);
00455 return 0;
00456 }
00457
00458 static int phone_answer(struct ast_channel *ast)
00459 {
00460 struct phone_pvt *p;
00461 p = ast->tech_pvt;
00462
00463 if (p->mode == MODE_FXO) {
00464 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
00465 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
00466 else
00467 ast_log(LOG_DEBUG, "Took linejack off hook\n");
00468 }
00469 phone_setup(ast);
00470 if (option_debug)
00471 ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name);
00472 ast->rings = 0;
00473 ast_setstate(ast, AST_STATE_UP);
00474 return 0;
00475 }
00476
00477 #if 0
00478 static char phone_2digit(char c)
00479 {
00480 if (c == 12)
00481 return '#';
00482 else if (c == 11)
00483 return '*';
00484 else if ((c < 10) && (c >= 0))
00485 return '0' + c - 1;
00486 else
00487 return '?';
00488 }
00489 #endif
00490
00491 static struct ast_frame *phone_exception(struct ast_channel *ast)
00492 {
00493 int res;
00494 union telephony_exception phonee;
00495 struct phone_pvt *p = ast->tech_pvt;
00496 char digit;
00497
00498
00499 p->fr.datalen = 0;
00500 p->fr.samples = 0;
00501 p->fr.data = NULL;
00502 p->fr.src = "Phone";
00503 p->fr.offset = 0;
00504 p->fr.mallocd=0;
00505 p->fr.delivery = ast_tv(0,0);
00506
00507 phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
00508 if (phonee.bits.dtmf_ready) {
00509 if (option_debug)
00510 ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");
00511
00512
00513 digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
00514 p->fr.subclass = digit;
00515 p->fr.frametype = AST_FRAME_DTMF;
00516 return &p->fr;
00517 }
00518 if (phonee.bits.hookstate) {
00519 if (option_debug)
00520 ast_log(LOG_DEBUG, "Hookstate changed\n");
00521 res = ioctl(p->fd, PHONE_HOOKSTATE);
00522
00523 if (option_debug)
00524 ast_log(LOG_DEBUG, "New hookstate: %d\n", res);
00525 if (!res && (p->mode != MODE_FXO))
00526 return NULL;
00527 else {
00528 if (ast->_state == AST_STATE_RINGING) {
00529
00530 p->fr.frametype = AST_FRAME_CONTROL;
00531 p->fr.subclass = AST_CONTROL_ANSWER;
00532 phone_setup(ast);
00533 ast_setstate(ast, AST_STATE_UP);
00534 return &p->fr;
00535 } else
00536 ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state);
00537 }
00538 }
00539 #if 1
00540 if (phonee.bits.pstn_ring)
00541 ast_verbose("Unit is ringing\n");
00542 if (phonee.bits.caller_id) {
00543 ast_verbose("We have caller ID\n");
00544 }
00545 if (phonee.bits.pstn_wink)
00546 ast_verbose("Detected Wink\n");
00547 #endif
00548
00549 p->fr.frametype = AST_FRAME_NULL;
00550 p->fr.subclass = 0;
00551 return &p->fr;
00552 }
00553
00554 static struct ast_frame *phone_read(struct ast_channel *ast)
00555 {
00556 int res;
00557 struct phone_pvt *p = ast->tech_pvt;
00558
00559
00560
00561 p->fr.datalen = 0;
00562 p->fr.samples = 0;
00563 p->fr.data = NULL;
00564 p->fr.src = "Phone";
00565 p->fr.offset = 0;
00566 p->fr.mallocd=0;
00567 p->fr.delivery = ast_tv(0,0);
00568
00569
00570 CHECK_BLOCKING(ast);
00571 res = read(p->fd, p->buf, PHONE_MAX_BUF);
00572 ast_clear_flag(ast, AST_FLAG_BLOCKING);
00573 if (res < 0) {
00574 #if 0
00575 if (errno == EAGAIN) {
00576 ast_log(LOG_WARNING, "Null frame received\n");
00577 p->fr.frametype = AST_FRAME_NULL;
00578 p->fr.subclass = 0;
00579 return &p->fr;
00580 }
00581 #endif
00582 ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));
00583 return NULL;
00584 }
00585 p->fr.data = p->buf;
00586 if (p->mode != MODE_FXS)
00587 switch(p->buf[0] & 0x3) {
00588 case '0':
00589 case '1':
00590
00591 break;
00592 case '2':
00593 case '3':
00594
00595 res = 4;
00596 break;
00597 }
00598 p->fr.samples = 240;
00599 p->fr.datalen = res;
00600 p->fr.frametype = p->lastinput <= AST_FORMAT_MAX_AUDIO ?
00601 AST_FRAME_VOICE :
00602 p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE
00603 : AST_FRAME_VIDEO;
00604 p->fr.subclass = p->lastinput;
00605 p->fr.offset = AST_FRIENDLY_OFFSET;
00606
00607 if (p->fr.subclass == AST_FORMAT_SLINEAR)
00608 ast_frame_byteswap_le(&p->fr);
00609 return &p->fr;
00610 }
00611
00612 static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
00613 {
00614 int res;
00615
00616 int space = sizeof(p->obuf) - p->obuflen;
00617
00618 if (space < len)
00619 len = space;
00620 if (swap)
00621 ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2);
00622 else
00623 memcpy(p->obuf + p->obuflen, buf, len);
00624 p->obuflen += len;
00625 while(p->obuflen > frlen) {
00626 res = write(p->fd, p->obuf, frlen);
00627 if (res != frlen) {
00628 if (res < 1) {
00629
00630
00631
00632
00633 return 0;
00634 } else {
00635 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);
00636 }
00637 }
00638 p->obuflen -= frlen;
00639
00640 if (p->obuflen)
00641 memmove(p->obuf, p->obuf + frlen, p->obuflen);
00642 }
00643 return len;
00644 }
00645
00646 static int phone_send_text(struct ast_channel *ast, const char *text)
00647 {
00648 int length = strlen(text);
00649 return phone_write_buf(ast->tech_pvt, text, length, length, 0) ==
00650 length ? 0 : -1;
00651 }
00652
00653 static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
00654 {
00655 struct phone_pvt *p = ast->tech_pvt;
00656 int res;
00657 int maxfr=0;
00658 char *pos;
00659 int sofar;
00660 int expected;
00661 int codecset = 0;
00662 char tmpbuf[4];
00663
00664 if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {
00665 if (frame->frametype != AST_FRAME_IMAGE)
00666 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
00667 return 0;
00668 }
00669 if (!(frame->subclass &
00670 (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) &&
00671 p->mode != MODE_FXS) {
00672 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
00673 return -1;
00674 }
00675 #if 0
00676
00677 if (ast->_state != AST_STATE_UP) {
00678 ast_setstate(ast, AST_STATE_UP);
00679 phone_setup(ast);
00680 }
00681 #else
00682 if (ast->_state != AST_STATE_UP) {
00683
00684 return 0;
00685 }
00686 #endif
00687 if (frame->subclass == AST_FORMAT_G723_1) {
00688 if (p->lastformat != AST_FORMAT_G723_1) {
00689 ioctl(p->fd, PHONE_PLAY_STOP);
00690 ioctl(p->fd, PHONE_REC_STOP);
00691 if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
00692 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00693 return -1;
00694 }
00695 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00696 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00697 return -1;
00698 }
00699 p->lastformat = AST_FORMAT_G723_1;
00700 p->lastinput = AST_FORMAT_G723_1;
00701
00702 p->obuflen = 0;
00703 codecset = 1;
00704 }
00705 if (frame->datalen > 24) {
00706 ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
00707 return -1;
00708 }
00709 maxfr = 24;
00710 } else if (frame->subclass == AST_FORMAT_SLINEAR) {
00711 if (p->lastformat != AST_FORMAT_SLINEAR) {
00712 ioctl(p->fd, PHONE_PLAY_STOP);
00713 ioctl(p->fd, PHONE_REC_STOP);
00714 if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
00715 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00716 return -1;
00717 }
00718 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00719 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00720 return -1;
00721 }
00722 p->lastformat = AST_FORMAT_SLINEAR;
00723 p->lastinput = AST_FORMAT_SLINEAR;
00724 codecset = 1;
00725
00726 p->obuflen = 0;
00727 }
00728 maxfr = 480;
00729 } else if (frame->subclass == AST_FORMAT_ULAW) {
00730 if (p->lastformat != AST_FORMAT_ULAW) {
00731 ioctl(p->fd, PHONE_PLAY_STOP);
00732 ioctl(p->fd, PHONE_REC_STOP);
00733 if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
00734 ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00735 return -1;
00736 }
00737 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00738 ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00739 return -1;
00740 }
00741 p->lastformat = AST_FORMAT_ULAW;
00742 p->lastinput = AST_FORMAT_ULAW;
00743 codecset = 1;
00744
00745 p->obuflen = 0;
00746 }
00747 maxfr = 240;
00748 } else {
00749 if (p->lastformat != frame->subclass) {
00750 ioctl(p->fd, PHONE_PLAY_STOP);
00751 ioctl(p->fd, PHONE_REC_STOP);
00752 if (ioctl(p->fd, PHONE_PLAY_CODEC, frame->subclass)) {
00753 ast_log(LOG_WARNING, "Unable to set %d mode\n",
00754 frame->subclass);
00755 return -1;
00756 }
00757 if (ioctl(p->fd, PHONE_REC_CODEC, frame->subclass)) {
00758 ast_log(LOG_WARNING, "Unable to set %d mode\n",
00759 frame->subclass);
00760 return -1;
00761 }
00762 p->lastformat = frame->subclass;
00763 p->lastinput = frame->subclass;
00764 codecset = 1;
00765
00766 p->obuflen = 0;
00767 }
00768 maxfr = 480;
00769 }
00770 if (codecset) {
00771 ioctl(p->fd, PHONE_REC_DEPTH, 3);
00772 ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
00773 if (ioctl(p->fd, PHONE_PLAY_START)) {
00774 ast_log(LOG_WARNING, "Failed to start playback\n");
00775 return -1;
00776 }
00777 if (ioctl(p->fd, PHONE_REC_START)) {
00778 ast_log(LOG_WARNING, "Failed to start recording\n");
00779 return -1;
00780 }
00781 }
00782
00783 sofar = 0;
00784 pos = frame->data;
00785 while(sofar < frame->datalen) {
00786
00787 expected = frame->datalen - sofar;
00788 if (maxfr < expected)
00789 expected = maxfr;
00790
00791
00792 if (frame->datalen == 4) {
00793 if (p->silencesupression) {
00794 memset(tmpbuf, 0, sizeof(tmpbuf));
00795 memcpy(tmpbuf, frame->data, 4);
00796 expected = 24;
00797 res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
00798 }
00799 res = 4;
00800 expected=4;
00801 } else {
00802 int swap = 0;
00803 #if __BYTE_ORDER == __BIG_ENDIAN
00804 if (frame->subclass == AST_FORMAT_SLINEAR)
00805 swap = 1;
00806 #endif
00807 res = phone_write_buf(p, pos, expected, maxfr, swap);
00808 }
00809 if (res != expected) {
00810 if ((errno != EAGAIN) && (errno != EINTR)) {
00811 if (res < 0)
00812 ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
00813
00814
00815
00816
00817 #if 0
00818 else
00819 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
00820 #endif
00821 return -1;
00822 } else
00823 res = expected;
00824 }
00825 sofar += res;
00826 pos += res;
00827 }
00828 return 0;
00829 }
00830
00831 static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context)
00832 {
00833 struct ast_channel *tmp;
00834 struct phone_codec_data codec;
00835 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);
00836 if (tmp) {
00837 tmp->tech = cur_tech;
00838 tmp->fds[0] = i->fd;
00839
00840 if (i->mode == MODE_FXS &&
00841 ioctl(i->fd, PHONE_QUERY_CODEC, &codec) == 0) {
00842 if (codec.type == LINEAR16)
00843 tmp->nativeformats =
00844 tmp->rawreadformat =
00845 tmp->rawwriteformat =
00846 AST_FORMAT_SLINEAR;
00847 else {
00848 tmp->nativeformats =
00849 tmp->rawreadformat =
00850 tmp->rawwriteformat =
00851 prefformat & ~AST_FORMAT_SLINEAR;
00852 }
00853 }
00854 else {
00855 tmp->nativeformats = prefformat;
00856 tmp->rawreadformat = prefformat;
00857 tmp->rawwriteformat = prefformat;
00858 }
00859
00860 if (state == AST_STATE_RING)
00861 tmp->rings = 1;
00862 tmp->tech_pvt = i;
00863 ast_copy_string(tmp->context, context, sizeof(tmp->context));
00864 if (!ast_strlen_zero(i->ext))
00865 ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
00866 else
00867 strcpy(tmp->exten, "s");
00868 if (!ast_strlen_zero(i->language))
00869 ast_string_field_set(tmp, language, i->language);
00870
00871
00872
00873 tmp->cid.cid_ani = ast_strdup(i->cid_num);
00874
00875 i->owner = tmp;
00876 ast_module_ref(ast_module_info->self);
00877 if (state != AST_STATE_DOWN) {
00878 if (state == AST_STATE_RING) {
00879 ioctl(tmp->fds[0], PHONE_RINGBACK);
00880 i->cpt = 1;
00881 }
00882 if (ast_pbx_start(tmp)) {
00883 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00884 ast_hangup(tmp);
00885 }
00886 }
00887 } else
00888 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00889 return tmp;
00890 }
00891
00892 static void phone_mini_packet(struct phone_pvt *i)
00893 {
00894 int res;
00895 char buf[1024];
00896
00897 res = read(i->fd, buf, sizeof(buf));
00898 if (res < 1) {
00899 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
00900 return;
00901 }
00902 }
00903
00904 static void phone_check_exception(struct phone_pvt *i)
00905 {
00906 int offhook=0;
00907 char digit[2] = {0 , 0};
00908 union telephony_exception phonee;
00909
00910 #if 0
00911 ast_log(LOG_DEBUG, "Exception!\n");
00912 #endif
00913 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
00914 if (phonee.bits.dtmf_ready) {
00915 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
00916 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
00917 ioctl(i->fd, PHONE_PLAY_STOP);
00918 ioctl(i->fd, PHONE_REC_STOP);
00919 ioctl(i->fd, PHONE_CPT_STOP);
00920 i->dialtone = 0;
00921 if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
00922 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
00923 if ((i->mode != MODE_FXS ||
00924 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
00925 !phonee.bits.dtmf_ready) &&
00926 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00927
00928 phone_new(i, AST_STATE_RING, i->context);
00929
00930 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00931
00932
00933 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00934
00935 phone_new(i, AST_STATE_RING, "default");
00936
00937 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00938
00939 if (option_debug)
00940 ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
00941 ioctl(i->fd, PHONE_BUSY);
00942 i->cpt = 1;
00943 }
00944 }
00945 #if 0
00946 ast_verbose("Extension is %s\n", i->ext);
00947 #endif
00948 }
00949 }
00950 if (phonee.bits.hookstate) {
00951 offhook = ioctl(i->fd, PHONE_HOOKSTATE);
00952 if (offhook) {
00953 if (i->mode == MODE_IMMEDIATE) {
00954 phone_new(i, AST_STATE_RING, i->context);
00955 } else if (i->mode == MODE_DIALTONE) {
00956 ast_module_ref(ast_module_info->self);
00957
00958 i->ext[0] = '\0';
00959
00960 i->dialtone++;
00961 ioctl(i->fd, PHONE_PLAY_STOP);
00962 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
00963 ioctl(i->fd, PHONE_PLAY_START);
00964 i->lastformat = -1;
00965 } else if (i->mode == MODE_SIGMA) {
00966 ast_module_ref(ast_module_info->self);
00967
00968 i->ext[0] = '\0';
00969
00970 i->dialtone++;
00971 ioctl(i->fd, PHONE_DIALTONE);
00972 }
00973 } else {
00974 if (i->dialtone)
00975 ast_module_unref(ast_module_info->self);
00976 memset(i->ext, 0, sizeof(i->ext));
00977 if (i->cpt)
00978 {
00979 ioctl(i->fd, PHONE_CPT_STOP);
00980 i->cpt = 0;
00981 }
00982 ioctl(i->fd, PHONE_PLAY_STOP);
00983 ioctl(i->fd, PHONE_REC_STOP);
00984 i->dialtone = 0;
00985 i->lastformat = -1;
00986 }
00987 }
00988 if (phonee.bits.pstn_ring) {
00989 ast_verbose("Unit is ringing\n");
00990 phone_new(i, AST_STATE_RING, i->context);
00991 }
00992 if (phonee.bits.caller_id)
00993 ast_verbose("We have caller ID\n");
00994
00995
00996 }
00997
00998 static void *do_monitor(void *data)
00999 {
01000 fd_set rfds, efds;
01001 int n, res;
01002 struct phone_pvt *i;
01003 int tonepos = 0;
01004
01005 struct timeval tv = {0,0};
01006 int dotone;
01007
01008
01009 while (monitor) {
01010
01011
01012
01013 if (ast_mutex_lock(&iflock)) {
01014 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
01015 return NULL;
01016 }
01017
01018
01019 n = -1;
01020 FD_ZERO(&rfds);
01021 FD_ZERO(&efds);
01022 i = iflist;
01023 dotone = 0;
01024 while (i) {
01025 if (FD_ISSET(i->fd, &rfds))
01026 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
01027 if (!i->owner) {
01028
01029 FD_SET(i->fd, &rfds);
01030 FD_SET(i->fd, &efds);
01031 if (i->fd > n)
01032 n = i->fd;
01033 if (i->dialtone && i->mode != MODE_SIGMA) {
01034
01035
01036 if (ast_tvzero(tv)) {
01037
01038 if (write(i->fd, DialTone + tonepos, 240) != 240)
01039 ast_log(LOG_WARNING, "Dial tone write error\n");
01040 }
01041 dotone++;
01042 }
01043 }
01044
01045 i = i->next;
01046 }
01047
01048 ast_mutex_unlock(&iflock);
01049
01050
01051 if (dotone && i && i->mode != MODE_SIGMA) {
01052
01053 tonepos += 240;
01054 if (tonepos >= sizeof(DialTone))
01055 tonepos = 0;
01056 if (ast_tvzero(tv)) {
01057 tv = ast_tv(30000, 0);
01058 }
01059 res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
01060 } else {
01061 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
01062 tv = ast_tv(0,0);
01063 tonepos = 0;
01064 }
01065
01066 if (res < 0) {
01067 ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));
01068 continue;
01069 }
01070
01071
01072 if (!res)
01073 continue;
01074
01075
01076 if (ast_mutex_lock(&iflock)) {
01077 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01078 continue;
01079 }
01080
01081 i = iflist;
01082 for(; i; i=i->next) {
01083 if (FD_ISSET(i->fd, &rfds)) {
01084 if (i->owner) {
01085 continue;
01086 }
01087 phone_mini_packet(i);
01088 }
01089 if (FD_ISSET(i->fd, &efds)) {
01090 if (i->owner) {
01091 continue;
01092 }
01093 phone_check_exception(i);
01094 }
01095 }
01096 ast_mutex_unlock(&iflock);
01097 }
01098 return NULL;
01099
01100 }
01101
01102 static int restart_monitor()
01103 {
01104
01105 if (monitor_thread == AST_PTHREADT_STOP)
01106 return 0;
01107 if (ast_mutex_lock(&monlock)) {
01108 ast_log(LOG_WARNING, "Unable to lock monitor\n");
01109 return -1;
01110 }
01111 if (monitor_thread == pthread_self()) {
01112 ast_mutex_unlock(&monlock);
01113 ast_log(LOG_WARNING, "Cannot kill myself\n");
01114 return -1;
01115 }
01116 if (monitor_thread != AST_PTHREADT_NULL) {
01117 if (ast_mutex_lock(&iflock)) {
01118 ast_mutex_unlock(&monlock);
01119 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01120 return -1;
01121 }
01122 monitor = 0;
01123 while (pthread_kill(monitor_thread, SIGURG) == 0)
01124 sched_yield();
01125 pthread_join(monitor_thread, NULL);
01126 ast_mutex_unlock(&iflock);
01127 }
01128 monitor = 1;
01129
01130 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01131 ast_mutex_unlock(&monlock);
01132 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01133 return -1;
01134 }
01135 ast_mutex_unlock(&monlock);
01136 return 0;
01137 }
01138
01139 static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
01140 {
01141
01142 struct phone_pvt *tmp;
01143 int flags;
01144
01145 tmp = malloc(sizeof(struct phone_pvt));
01146 if (tmp) {
01147 tmp->fd = open(iface, O_RDWR);
01148 if (tmp->fd < 0) {
01149 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01150 free(tmp);
01151 return NULL;
01152 }
01153 if (mode == MODE_FXO) {
01154 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN))
01155 ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
01156 } else {
01157 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
01158 if (mode != MODE_FXS)
01159 ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
01160 }
01161 ioctl(tmp->fd, PHONE_PLAY_STOP);
01162 ioctl(tmp->fd, PHONE_REC_STOP);
01163 ioctl(tmp->fd, PHONE_RING_STOP);
01164 ioctl(tmp->fd, PHONE_CPT_STOP);
01165 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01166 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01167 if (echocancel != AEC_OFF)
01168 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01169 if (silencesupression)
01170 tmp->silencesupression = 1;
01171 #ifdef PHONE_VAD
01172 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01173 #endif
01174 tmp->mode = mode;
01175 flags = fcntl(tmp->fd, F_GETFL);
01176 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01177 tmp->owner = NULL;
01178 tmp->lastformat = -1;
01179 tmp->lastinput = -1;
01180 tmp->ministate = 0;
01181 memset(tmp->ext, 0, sizeof(tmp->ext));
01182 ast_copy_string(tmp->language, language, sizeof(tmp->language));
01183 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01184 ast_copy_string(tmp->context, context, sizeof(tmp->context));
01185 tmp->next = NULL;
01186 tmp->obuflen = 0;
01187 tmp->dialtone = 0;
01188 tmp->cpt = 0;
01189 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01190 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01191 tmp->txgain = txgain;
01192 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01193 tmp->rxgain = rxgain;
01194 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01195 }
01196 return tmp;
01197 }
01198
01199 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause)
01200 {
01201 int oldformat;
01202 struct phone_pvt *p;
01203 struct ast_channel *tmp = NULL;
01204 char *name = data;
01205
01206
01207 if (ast_mutex_lock(&iflock)) {
01208 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01209 return NULL;
01210 }
01211 p = iflist;
01212 while(p) {
01213 if (p->mode == MODE_FXS ||
01214 format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01215 size_t length = strlen(p->dev + 5);
01216 if (strncmp(name, p->dev + 5, length) == 0 &&
01217 !isalnum(name[length])) {
01218 if (!p->owner) {
01219 tmp = phone_new(p, AST_STATE_DOWN, p->context);
01220 break;
01221 } else
01222 *cause = AST_CAUSE_BUSY;
01223 }
01224 }
01225 p = p->next;
01226 }
01227 ast_mutex_unlock(&iflock);
01228 restart_monitor();
01229 if (tmp == NULL) {
01230 oldformat = format;
01231 format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01232 if (!format) {
01233 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01234 return NULL;
01235 }
01236 }
01237 return tmp;
01238 }
01239
01240
01241 static int parse_gain_value(char *gain_type, char *value)
01242 {
01243 float gain;
01244
01245
01246 if (sscanf(value, "%30f", &gain) != 1)
01247 {
01248 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01249 value, gain_type, config);
01250 return DEFAULT_GAIN;
01251 }
01252
01253
01254 gain = gain * (float)DEFAULT_GAIN;
01255
01256
01257 if (value[strlen(value) - 1] == '%')
01258 return (int)(gain / (float)100);
01259
01260 return (int)gain;
01261 }
01262
01263 static int __unload_module(void)
01264 {
01265 struct phone_pvt *p, *pl;
01266
01267 if (cur_tech)
01268 ast_channel_unregister(cur_tech);
01269 if (!ast_mutex_lock(&iflock)) {
01270
01271 p = iflist;
01272 while(p) {
01273 if (p->owner)
01274 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01275 p = p->next;
01276 }
01277 iflist = NULL;
01278 ast_mutex_unlock(&iflock);
01279 } else {
01280 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01281 return -1;
01282 }
01283 if (!ast_mutex_lock(&monlock)) {
01284 if (monitor_thread > AST_PTHREADT_NULL) {
01285 monitor = 0;
01286 while (pthread_kill(monitor_thread, SIGURG) == 0)
01287 sched_yield();
01288 pthread_join(monitor_thread, NULL);
01289 }
01290 monitor_thread = AST_PTHREADT_STOP;
01291 ast_mutex_unlock(&monlock);
01292 } else {
01293 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01294 return -1;
01295 }
01296
01297 if (!ast_mutex_lock(&iflock)) {
01298
01299 p = iflist;
01300 while(p) {
01301
01302 if (p->fd > -1)
01303 close(p->fd);
01304 pl = p;
01305 p = p->next;
01306
01307 free(pl);
01308 }
01309 iflist = NULL;
01310 ast_mutex_unlock(&iflock);
01311 } else {
01312 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01313 return -1;
01314 }
01315
01316 return 0;
01317 }
01318
01319 static int unload_module(void)
01320 {
01321 return __unload_module();
01322 }
01323
01324 static int load_module(void)
01325 {
01326 struct ast_config *cfg;
01327 struct ast_variable *v;
01328 struct phone_pvt *tmp;
01329 int mode = MODE_IMMEDIATE;
01330 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN;
01331 cfg = ast_config_load(config);
01332
01333
01334 if (!cfg) {
01335 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01336 return AST_MODULE_LOAD_DECLINE;
01337 }
01338 if (ast_mutex_lock(&iflock)) {
01339
01340 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01341 return AST_MODULE_LOAD_FAILURE;
01342 }
01343 v = ast_variable_browse(cfg, "interfaces");
01344 while(v) {
01345
01346 if (!strcasecmp(v->name, "device")) {
01347 tmp = mkif(v->value, mode, txgain, rxgain);
01348 if (tmp) {
01349 tmp->next = iflist;
01350 iflist = tmp;
01351
01352 } else {
01353 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01354 ast_config_destroy(cfg);
01355 ast_mutex_unlock(&iflock);
01356 __unload_module();
01357 return AST_MODULE_LOAD_FAILURE;
01358 }
01359 } else if (!strcasecmp(v->name, "silencesupression")) {
01360 silencesupression = ast_true(v->value);
01361 } else if (!strcasecmp(v->name, "language")) {
01362 ast_copy_string(language, v->value, sizeof(language));
01363 } else if (!strcasecmp(v->name, "callerid")) {
01364 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01365 } else if (!strcasecmp(v->name, "mode")) {
01366 if (!strncasecmp(v->value, "di", 2))
01367 mode = MODE_DIALTONE;
01368 else if (!strncasecmp(v->value, "sig", 3))
01369 mode = MODE_SIGMA;
01370 else if (!strncasecmp(v->value, "im", 2))
01371 mode = MODE_IMMEDIATE;
01372 else if (!strncasecmp(v->value, "fxs", 3)) {
01373 mode = MODE_FXS;
01374 prefformat = 0x01ff0000;
01375 }
01376 else if (!strncasecmp(v->value, "fx", 2))
01377 mode = MODE_FXO;
01378 else
01379 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01380 } else if (!strcasecmp(v->name, "context")) {
01381 ast_copy_string(context, v->value, sizeof(context));
01382 } else if (!strcasecmp(v->name, "format")) {
01383 if (!strcasecmp(v->value, "g723.1")) {
01384 prefformat = AST_FORMAT_G723_1;
01385 } else if (!strcasecmp(v->value, "slinear")) {
01386 if (mode == MODE_FXS)
01387 prefformat |= AST_FORMAT_SLINEAR;
01388 else prefformat = AST_FORMAT_SLINEAR;
01389 } else if (!strcasecmp(v->value, "ulaw")) {
01390 prefformat = AST_FORMAT_ULAW;
01391 } else
01392 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01393 } else if (!strcasecmp(v->name, "echocancel")) {
01394 if (!strcasecmp(v->value, "off")) {
01395 echocancel = AEC_OFF;
01396 } else if (!strcasecmp(v->value, "low")) {
01397 echocancel = AEC_LOW;
01398 } else if (!strcasecmp(v->value, "medium")) {
01399 echocancel = AEC_MED;
01400 } else if (!strcasecmp(v->value, "high")) {
01401 echocancel = AEC_HIGH;
01402 } else
01403 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01404 } else if (!strcasecmp(v->name, "txgain")) {
01405 txgain = parse_gain_value(v->name, v->value);
01406 } else if (!strcasecmp(v->name, "rxgain")) {
01407 rxgain = parse_gain_value(v->name, v->value);
01408 }
01409 v = v->next;
01410 }
01411 ast_mutex_unlock(&iflock);
01412
01413 if (mode == MODE_FXS) {
01414 phone_tech_fxs.capabilities = prefformat;
01415 cur_tech = &phone_tech_fxs;
01416 } else
01417 cur_tech = (struct ast_channel_tech *) &phone_tech;
01418
01419
01420
01421 if (ast_channel_register(cur_tech)) {
01422 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
01423 ast_config_destroy(cfg);
01424 __unload_module();
01425 return AST_MODULE_LOAD_FAILURE;
01426 }
01427 ast_config_destroy(cfg);
01428
01429 restart_monitor();
01430 return AST_MODULE_LOAD_SUCCESS;
01431 }
01432
01433 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");