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