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