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: 81523 $")
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 *dest, const char *text, int ispdu);
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 *dest, const char *text, int ispdu)
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_ani = ast_strdup(i->cid_num);
00871
00872 i->owner = tmp;
00873 ast_module_ref(ast_module_info->self);
00874 if (state != AST_STATE_DOWN) {
00875 if (state == AST_STATE_RING) {
00876 ioctl(tmp->fds[0], PHONE_RINGBACK);
00877 i->cpt = 1;
00878 }
00879 if (ast_pbx_start(tmp)) {
00880 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00881 ast_hangup(tmp);
00882 }
00883 }
00884 } else
00885 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00886 return tmp;
00887 }
00888
00889 static void phone_mini_packet(struct phone_pvt *i)
00890 {
00891 int res;
00892 char buf[1024];
00893
00894 res = read(i->fd, buf, sizeof(buf));
00895 if (res < 1) {
00896 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
00897 return;
00898 }
00899 }
00900
00901 static void phone_check_exception(struct phone_pvt *i)
00902 {
00903 int offhook=0;
00904 char digit[2] = {0 , 0};
00905 union telephony_exception phonee;
00906
00907 #if 0
00908 ast_log(LOG_DEBUG, "Exception!\n");
00909 #endif
00910 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
00911 if (phonee.bits.dtmf_ready) {
00912 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
00913 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
00914 ioctl(i->fd, PHONE_PLAY_STOP);
00915 ioctl(i->fd, PHONE_REC_STOP);
00916 ioctl(i->fd, PHONE_CPT_STOP);
00917 i->dialtone = 0;
00918 if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
00919 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
00920 if ((i->mode != MODE_FXS ||
00921 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
00922 !phonee.bits.dtmf_ready) &&
00923 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00924
00925 phone_new(i, AST_STATE_RING, i->context);
00926
00927 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00928
00929
00930 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00931
00932 phone_new(i, AST_STATE_RING, "default");
00933
00934 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00935
00936 if (option_debug)
00937 ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
00938 ioctl(i->fd, PHONE_BUSY);
00939 i->cpt = 1;
00940 }
00941 }
00942 #if 0
00943 ast_verbose("Extension is %s\n", i->ext);
00944 #endif
00945 }
00946 }
00947 if (phonee.bits.hookstate) {
00948 offhook = ioctl(i->fd, PHONE_HOOKSTATE);
00949 if (offhook) {
00950 if (i->mode == MODE_IMMEDIATE) {
00951 phone_new(i, AST_STATE_RING, i->context);
00952 } else if (i->mode == MODE_DIALTONE) {
00953 ast_module_ref(ast_module_info->self);
00954
00955 i->ext[0] = '\0';
00956
00957 i->dialtone++;
00958 ioctl(i->fd, PHONE_PLAY_STOP);
00959 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
00960 ioctl(i->fd, PHONE_PLAY_START);
00961 i->lastformat = -1;
00962 } else if (i->mode == MODE_SIGMA) {
00963 ast_module_ref(ast_module_info->self);
00964
00965 i->ext[0] = '\0';
00966
00967 i->dialtone++;
00968 ioctl(i->fd, PHONE_DIALTONE);
00969 }
00970 } else {
00971 if (i->dialtone)
00972 ast_module_unref(ast_module_info->self);
00973 memset(i->ext, 0, sizeof(i->ext));
00974 if (i->cpt)
00975 {
00976 ioctl(i->fd, PHONE_CPT_STOP);
00977 i->cpt = 0;
00978 }
00979 ioctl(i->fd, PHONE_PLAY_STOP);
00980 ioctl(i->fd, PHONE_REC_STOP);
00981 i->dialtone = 0;
00982 i->lastformat = -1;
00983 }
00984 }
00985 if (phonee.bits.pstn_ring) {
00986 ast_verbose("Unit is ringing\n");
00987 phone_new(i, AST_STATE_RING, i->context);
00988 }
00989 if (phonee.bits.caller_id)
00990 ast_verbose("We have caller ID\n");
00991
00992
00993 }
00994
00995 static void *do_monitor(void *data)
00996 {
00997 fd_set rfds, efds;
00998 int n, res;
00999 struct phone_pvt *i;
01000 int tonepos = 0;
01001
01002 struct timeval tv = {0,0};
01003 int dotone;
01004
01005
01006 while (monitor) {
01007
01008
01009
01010 if (ast_mutex_lock(&iflock)) {
01011 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
01012 return NULL;
01013 }
01014
01015
01016 n = -1;
01017 FD_ZERO(&rfds);
01018 FD_ZERO(&efds);
01019 i = iflist;
01020 dotone = 0;
01021 while (i) {
01022 if (FD_ISSET(i->fd, &rfds))
01023 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
01024 if (!i->owner) {
01025
01026 FD_SET(i->fd, &rfds);
01027 FD_SET(i->fd, &efds);
01028 if (i->fd > n)
01029 n = i->fd;
01030 if (i->dialtone && i->mode != MODE_SIGMA) {
01031
01032
01033 if (ast_tvzero(tv)) {
01034
01035 if (write(i->fd, DialTone + tonepos, 240) != 240)
01036 ast_log(LOG_WARNING, "Dial tone write error\n");
01037 }
01038 dotone++;
01039 }
01040 }
01041
01042 i = i->next;
01043 }
01044
01045 ast_mutex_unlock(&iflock);
01046
01047
01048 if (dotone && i && i->mode != MODE_SIGMA) {
01049
01050 tonepos += 240;
01051 if (tonepos >= sizeof(DialTone))
01052 tonepos = 0;
01053 if (ast_tvzero(tv)) {
01054 tv = ast_tv(30000, 0);
01055 }
01056 res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
01057 } else {
01058 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
01059 tv = ast_tv(0,0);
01060 tonepos = 0;
01061 }
01062
01063 if (res < 0) {
01064 ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));
01065 continue;
01066 }
01067
01068
01069 if (!res)
01070 continue;
01071
01072
01073 if (ast_mutex_lock(&iflock)) {
01074 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01075 continue;
01076 }
01077
01078 i = iflist;
01079 for(; i; i=i->next) {
01080 if (FD_ISSET(i->fd, &rfds)) {
01081 if (i->owner) {
01082 continue;
01083 }
01084 phone_mini_packet(i);
01085 }
01086 if (FD_ISSET(i->fd, &efds)) {
01087 if (i->owner) {
01088 continue;
01089 }
01090 phone_check_exception(i);
01091 }
01092 }
01093 ast_mutex_unlock(&iflock);
01094 }
01095 return NULL;
01096
01097 }
01098
01099 static int restart_monitor()
01100 {
01101
01102 if (monitor_thread == AST_PTHREADT_STOP)
01103 return 0;
01104 if (ast_mutex_lock(&monlock)) {
01105 ast_log(LOG_WARNING, "Unable to lock monitor\n");
01106 return -1;
01107 }
01108 if (monitor_thread == pthread_self()) {
01109 ast_mutex_unlock(&monlock);
01110 ast_log(LOG_WARNING, "Cannot kill myself\n");
01111 return -1;
01112 }
01113 if (monitor_thread != AST_PTHREADT_NULL) {
01114 if (ast_mutex_lock(&iflock)) {
01115 ast_mutex_unlock(&monlock);
01116 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01117 return -1;
01118 }
01119 monitor = 0;
01120 while (pthread_kill(monitor_thread, SIGURG) == 0)
01121 sched_yield();
01122 pthread_join(monitor_thread, NULL);
01123 ast_mutex_unlock(&iflock);
01124 }
01125 monitor = 1;
01126
01127 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01128 ast_mutex_unlock(&monlock);
01129 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01130 return -1;
01131 }
01132 ast_mutex_unlock(&monlock);
01133 return 0;
01134 }
01135
01136 static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
01137 {
01138
01139 struct phone_pvt *tmp;
01140 int flags;
01141
01142 tmp = malloc(sizeof(struct phone_pvt));
01143 if (tmp) {
01144 tmp->fd = open(iface, O_RDWR);
01145 if (tmp->fd < 0) {
01146 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01147 free(tmp);
01148 return NULL;
01149 }
01150 if (mode == MODE_FXO) {
01151 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN))
01152 ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
01153 } else {
01154 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
01155 if (mode != MODE_FXS)
01156 ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
01157 }
01158 ioctl(tmp->fd, PHONE_PLAY_STOP);
01159 ioctl(tmp->fd, PHONE_REC_STOP);
01160 ioctl(tmp->fd, PHONE_RING_STOP);
01161 ioctl(tmp->fd, PHONE_CPT_STOP);
01162 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01163 ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01164 if (echocancel != AEC_OFF)
01165 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01166 if (silencesupression)
01167 tmp->silencesupression = 1;
01168 #ifdef PHONE_VAD
01169 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01170 #endif
01171 tmp->mode = mode;
01172 flags = fcntl(tmp->fd, F_GETFL);
01173 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01174 tmp->owner = NULL;
01175 tmp->lastformat = -1;
01176 tmp->lastinput = -1;
01177 tmp->ministate = 0;
01178 memset(tmp->ext, 0, sizeof(tmp->ext));
01179 ast_copy_string(tmp->language, language, sizeof(tmp->language));
01180 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01181 ast_copy_string(tmp->context, context, sizeof(tmp->context));
01182 tmp->next = NULL;
01183 tmp->obuflen = 0;
01184 tmp->dialtone = 0;
01185 tmp->cpt = 0;
01186 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01187 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01188 tmp->txgain = txgain;
01189 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01190 tmp->rxgain = rxgain;
01191 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01192 }
01193 return tmp;
01194 }
01195
01196 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause)
01197 {
01198 int oldformat;
01199 struct phone_pvt *p;
01200 struct ast_channel *tmp = NULL;
01201 char *name = data;
01202
01203
01204 if (ast_mutex_lock(&iflock)) {
01205 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01206 return NULL;
01207 }
01208 p = iflist;
01209 while(p) {
01210 if (p->mode == MODE_FXS ||
01211 format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01212 size_t length = strlen(p->dev + 5);
01213 if (strncmp(name, p->dev + 5, length) == 0 &&
01214 !isalnum(name[length])) {
01215 if (!p->owner) {
01216 tmp = phone_new(p, AST_STATE_DOWN, p->context);
01217 break;
01218 } else
01219 *cause = AST_CAUSE_BUSY;
01220 }
01221 }
01222 p = p->next;
01223 }
01224 ast_mutex_unlock(&iflock);
01225 restart_monitor();
01226 if (tmp == NULL) {
01227 oldformat = format;
01228 format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01229 if (!format) {
01230 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01231 return NULL;
01232 }
01233 }
01234 return tmp;
01235 }
01236
01237
01238 static int parse_gain_value(char *gain_type, char *value)
01239 {
01240 float gain;
01241
01242
01243 if (sscanf(value, "%f", &gain) != 1)
01244 {
01245 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01246 value, gain_type, config);
01247 return DEFAULT_GAIN;
01248 }
01249
01250
01251 gain = gain * (float)DEFAULT_GAIN;
01252
01253
01254 if (value[strlen(value) - 1] == '%')
01255 return (int)(gain / (float)100);
01256
01257 return (int)gain;
01258 }
01259
01260 static int __unload_module(void)
01261 {
01262 struct phone_pvt *p, *pl;
01263
01264 if (cur_tech)
01265 ast_channel_unregister(cur_tech);
01266 if (!ast_mutex_lock(&iflock)) {
01267
01268 p = iflist;
01269 while(p) {
01270 if (p->owner)
01271 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01272 p = p->next;
01273 }
01274 iflist = NULL;
01275 ast_mutex_unlock(&iflock);
01276 } else {
01277 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01278 return -1;
01279 }
01280 if (!ast_mutex_lock(&monlock)) {
01281 if (monitor_thread > AST_PTHREADT_NULL) {
01282 monitor = 0;
01283 while (pthread_kill(monitor_thread, SIGURG) == 0)
01284 sched_yield();
01285 pthread_join(monitor_thread, NULL);
01286 }
01287 monitor_thread = AST_PTHREADT_STOP;
01288 ast_mutex_unlock(&monlock);
01289 } else {
01290 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01291 return -1;
01292 }
01293
01294 if (!ast_mutex_lock(&iflock)) {
01295
01296 p = iflist;
01297 while(p) {
01298
01299 if (p->fd > -1)
01300 close(p->fd);
01301 pl = p;
01302 p = p->next;
01303
01304 free(pl);
01305 }
01306 iflist = NULL;
01307 ast_mutex_unlock(&iflock);
01308 } else {
01309 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01310 return -1;
01311 }
01312
01313 return 0;
01314 }
01315
01316 static int unload_module(void)
01317 {
01318 return __unload_module();
01319 }
01320
01321 static int load_module(void)
01322 {
01323 struct ast_config *cfg;
01324 struct ast_variable *v;
01325 struct phone_pvt *tmp;
01326 int mode = MODE_IMMEDIATE;
01327 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN;
01328 cfg = ast_config_load(config);
01329
01330
01331 if (!cfg) {
01332 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01333 return AST_MODULE_LOAD_DECLINE;
01334 }
01335 if (ast_mutex_lock(&iflock)) {
01336
01337 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01338 return AST_MODULE_LOAD_FAILURE;
01339 }
01340 v = ast_variable_browse(cfg, "interfaces");
01341 while(v) {
01342
01343 if (!strcasecmp(v->name, "device")) {
01344 tmp = mkif(v->value, mode, txgain, rxgain);
01345 if (tmp) {
01346 tmp->next = iflist;
01347 iflist = tmp;
01348
01349 } else {
01350 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01351 ast_config_destroy(cfg);
01352 ast_mutex_unlock(&iflock);
01353 __unload_module();
01354 return AST_MODULE_LOAD_FAILURE;
01355 }
01356 } else if (!strcasecmp(v->name, "silencesupression")) {
01357 silencesupression = ast_true(v->value);
01358 } else if (!strcasecmp(v->name, "language")) {
01359 ast_copy_string(language, v->value, sizeof(language));
01360 } else if (!strcasecmp(v->name, "callerid")) {
01361 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01362 } else if (!strcasecmp(v->name, "mode")) {
01363 if (!strncasecmp(v->value, "di", 2))
01364 mode = MODE_DIALTONE;
01365 else if (!strncasecmp(v->value, "sig", 3))
01366 mode = MODE_SIGMA;
01367 else if (!strncasecmp(v->value, "im", 2))
01368 mode = MODE_IMMEDIATE;
01369 else if (!strncasecmp(v->value, "fxs", 3)) {
01370 mode = MODE_FXS;
01371 prefformat = 0x01ff0000;
01372 }
01373 else if (!strncasecmp(v->value, "fx", 2))
01374 mode = MODE_FXO;
01375 else
01376 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01377 } else if (!strcasecmp(v->name, "context")) {
01378 ast_copy_string(context, v->value, sizeof(context));
01379 } else if (!strcasecmp(v->name, "format")) {
01380 if (!strcasecmp(v->value, "g723.1")) {
01381 prefformat = AST_FORMAT_G723_1;
01382 } else if (!strcasecmp(v->value, "slinear")) {
01383 if (mode == MODE_FXS)
01384 prefformat |= AST_FORMAT_SLINEAR;
01385 else prefformat = AST_FORMAT_SLINEAR;
01386 } else if (!strcasecmp(v->value, "ulaw")) {
01387 prefformat = AST_FORMAT_ULAW;
01388 } else
01389 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01390 } else if (!strcasecmp(v->name, "echocancel")) {
01391 if (!strcasecmp(v->value, "off")) {
01392 echocancel = AEC_OFF;
01393 } else if (!strcasecmp(v->value, "low")) {
01394 echocancel = AEC_LOW;
01395 } else if (!strcasecmp(v->value, "medium")) {
01396 echocancel = AEC_MED;
01397 } else if (!strcasecmp(v->value, "high")) {
01398 echocancel = AEC_HIGH;
01399 } else
01400 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01401 } else if (!strcasecmp(v->name, "txgain")) {
01402 txgain = parse_gain_value(v->name, v->value);
01403 } else if (!strcasecmp(v->name, "rxgain")) {
01404 rxgain = parse_gain_value(v->name, v->value);
01405 }
01406 v = v->next;
01407 }
01408 ast_mutex_unlock(&iflock);
01409
01410 if (mode == MODE_FXS) {
01411 phone_tech_fxs.capabilities = prefformat;
01412 cur_tech = &phone_tech_fxs;
01413 } else
01414 cur_tech = (struct ast_channel_tech *) &phone_tech;
01415
01416
01417
01418 if (ast_channel_register(cur_tech)) {
01419 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
01420 ast_config_destroy(cfg);
01421 __unload_module();
01422 return AST_MODULE_LOAD_FAILURE;
01423 }
01424 ast_config_destroy(cfg);
01425
01426 restart_monitor();
01427 return AST_MODULE_LOAD_SUCCESS;
01428 }
01429
01430 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");