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: 160173 $")
00035
00036 #include <ctype.h>
00037 #include <sys/socket.h>
00038 #include <sys/time.h>
00039 #include <arpa/inet.h>
00040 #include <fcntl.h>
00041 #include <sys/ioctl.h>
00042 #include <signal.h>
00043 #ifdef HAVE_LINUX_COMPILER_H
00044 #include <linux/compiler.h>
00045 #endif
00046 #include <linux/telephony.h>
00047
00048 #include <linux/version.h>
00049 #include <linux/ixjuser.h>
00050
00051 #include "asterisk/lock.h"
00052 #include "asterisk/channel.h"
00053 #include "asterisk/config.h"
00054 #include "asterisk/module.h"
00055 #include "asterisk/pbx.h"
00056 #include "asterisk/utils.h"
00057 #include "asterisk/callerid.h"
00058 #include "asterisk/causes.h"
00059 #include "asterisk/stringfields.h"
00060 #include "asterisk/musiconhold.h"
00061
00062 #include "DialTone.h"
00063
00064 #ifdef QTI_PHONEJACK_TJ_PCI
00065 #define QNDRV_VER 310
00066 #else
00067 #define QNDRV_VER 100
00068 #endif
00069
00070 #if QNDRV_VER > 100
00071 #ifdef __linux__
00072 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x);
00073 #else
00074 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, x);
00075 #endif
00076 #else
00077 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x);
00078 #endif
00079
00080 #define DEFAULT_CALLER_ID "Unknown"
00081 #define PHONE_MAX_BUF 480
00082 #define DEFAULT_GAIN 0x100
00083
00084 static const char tdesc[] = "Standard Linux Telephony API Driver";
00085 static const char config[] = "phone.conf";
00086
00087
00088 static char context[AST_MAX_EXTENSION] = "default";
00089
00090
00091 static char language[MAX_LANGUAGE] = "";
00092
00093 static int echocancel = AEC_OFF;
00094
00095 static int silencesupression = 0;
00096
00097 static int prefformat = AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
00098
00099
00100 AST_MUTEX_DEFINE_STATIC(iflock);
00101
00102
00103
00104 AST_MUTEX_DEFINE_STATIC(monlock);
00105
00106
00107 static unsigned int monitor;
00108
00109
00110
00111 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00112
00113 static int restart_monitor(void);
00114
00115
00116
00117
00118 #define MODE_DIALTONE 1
00119 #define MODE_IMMEDIATE 2
00120 #define MODE_FXO 3
00121 #define MODE_FXS 4
00122 #define MODE_SIGMA 5
00123
00124 static struct phone_pvt {
00125 int fd;
00126 struct ast_channel *owner;
00127 int mode;
00128 int lastformat;
00129 int lastinput;
00130 int ministate;
00131 char dev[256];
00132 struct phone_pvt *next;
00133 struct ast_frame fr;
00134 char offset[AST_FRIENDLY_OFFSET];
00135 char buf[PHONE_MAX_BUF];
00136 int obuflen;
00137 int dialtone;
00138 int txgain, rxgain;
00139
00140 int cpt;
00141 int silencesupression;
00142 char context[AST_MAX_EXTENSION];
00143 char obuf[PHONE_MAX_BUF * 2];
00144 char ext[AST_MAX_EXTENSION];
00145 char language[MAX_LANGUAGE];
00146 char cid_num[AST_MAX_EXTENSION];
00147 char cid_name[AST_MAX_EXTENSION];
00148 } *iflist = NULL;
00149
00150 static char cid_num[AST_MAX_EXTENSION];
00151 static char cid_name[AST_MAX_EXTENSION];
00152
00153 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause);
00154 static int phone_digit_begin(struct ast_channel *ast, char digit);
00155 static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00156 static int phone_call(struct ast_channel *ast, char *dest, int timeout);
00157 static int phone_hangup(struct ast_channel *ast);
00158 static int phone_answer(struct ast_channel *ast);
00159 static struct ast_frame *phone_read(struct ast_channel *ast);
00160 static int phone_write(struct ast_channel *ast, struct ast_frame *frame);
00161 static struct ast_frame *phone_exception(struct ast_channel *ast);
00162 static int phone_send_text(struct ast_channel *ast, const char *text);
00163 static int phone_fixup(struct ast_channel *old, struct ast_channel *new);
00164 static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
00165
00166 static const struct ast_channel_tech phone_tech = {
00167 .type = "Phone",
00168 .description = tdesc,
00169 .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A,
00170 .requester = phone_request,
00171 .send_digit_begin = phone_digit_begin,
00172 .send_digit_end = phone_digit_end,
00173 .call = phone_call,
00174 .hangup = phone_hangup,
00175 .answer = phone_answer,
00176 .read = phone_read,
00177 .write = phone_write,
00178 .exception = phone_exception,
00179 .indicate = phone_indicate,
00180 .fixup = phone_fixup
00181 };
00182
00183 static struct ast_channel_tech phone_tech_fxs = {
00184 .type = "Phone",
00185 .description = tdesc,
00186 .requester = phone_request,
00187 .send_digit_begin = phone_digit_begin,
00188 .send_digit_end = phone_digit_end,
00189 .call = phone_call,
00190 .hangup = phone_hangup,
00191 .answer = phone_answer,
00192 .read = phone_read,
00193 .write = phone_write,
00194 .exception = phone_exception,
00195 .write_video = phone_write,
00196 .send_text = phone_send_text,
00197 .indicate = phone_indicate,
00198 .fixup = phone_fixup
00199 };
00200
00201 static struct ast_channel_tech *cur_tech;
00202
00203 static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
00204 {
00205 struct phone_pvt *p = chan->tech_pvt;
00206 int res=-1;
00207 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
00208 switch(condition) {
00209 case AST_CONTROL_FLASH:
00210 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
00211 usleep(320000);
00212 ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
00213 p->lastformat = -1;
00214 res = 0;
00215 break;
00216 case AST_CONTROL_HOLD:
00217 ast_moh_start(chan, data, NULL);
00218 break;
00219 case AST_CONTROL_UNHOLD:
00220 ast_moh_stop(chan);
00221 break;
00222 case AST_CONTROL_SRCUPDATE:
00223 res = 0;
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_debug(1, "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_debug(1, "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 struct timeval UtcTime = ast_tvnow();
00293 struct ast_tm tm;
00294 int start;
00295
00296 ast_localtime(&UtcTime, &tm, NULL);
00297
00298 memset(&cid, 0, sizeof(PHONE_CID));
00299 if(&tm != NULL) {
00300 snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1));
00301 snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday);
00302 snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour);
00303 snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
00304 }
00305
00306 if (ast_strlen_zero(ast->cid.cid_name))
00307 strcpy(cid.name, DEFAULT_CALLER_ID);
00308 else
00309 ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
00310
00311 if (ast->cid.cid_num)
00312 ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
00313
00314 p = ast->tech_pvt;
00315
00316 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00317 ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
00318 return -1;
00319 }
00320 ast_debug(1, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
00321
00322 start = IXJ_PHONE_RING_START(cid);
00323 if (start == -1)
00324 return -1;
00325
00326 if (p->mode == MODE_FXS) {
00327 char *digit = strchr(dest, '/');
00328 if (digit)
00329 {
00330 digit++;
00331 while (*digit)
00332 phone_digit_end(ast, *digit++, 0);
00333 }
00334 }
00335
00336 ast_setstate(ast, AST_STATE_RINGING);
00337 ast_queue_control(ast, AST_CONTROL_RINGING);
00338 return 0;
00339 }
00340
00341 static int phone_hangup(struct ast_channel *ast)
00342 {
00343 struct phone_pvt *p;
00344 p = ast->tech_pvt;
00345 ast_debug(1, "phone_hangup(%s)\n", ast->name);
00346 if (!ast->tech_pvt) {
00347 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00348 return 0;
00349 }
00350
00351 ast_setstate(ast, AST_STATE_DOWN);
00352 if (ioctl(p->fd, PHONE_REC_STOP))
00353 ast_log(LOG_WARNING, "Failed to stop recording\n");
00354 if (ioctl(p->fd, PHONE_PLAY_STOP))
00355 ast_log(LOG_WARNING, "Failed to stop playing\n");
00356 if (ioctl(p->fd, PHONE_RING_STOP))
00357 ast_log(LOG_WARNING, "Failed to stop ringing\n");
00358 if (ioctl(p->fd, PHONE_CPT_STOP))
00359 ast_log(LOG_WARNING, "Failed to stop sounds\n");
00360
00361
00362 if (p->mode == MODE_FXO) {
00363 if (ioctl(p->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
00364 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",ast->name, strerror(errno));
00365 }
00366
00367
00368 if (ioctl(p->fd, PHONE_HOOKSTATE)) {
00369 ast_debug(1, "Got hunghup, giving busy signal\n");
00370 ioctl(p->fd, PHONE_BUSY);
00371 p->cpt = 1;
00372 }
00373 p->lastformat = -1;
00374 p->lastinput = -1;
00375 p->ministate = 0;
00376 p->obuflen = 0;
00377 p->dialtone = 0;
00378 memset(p->ext, 0, sizeof(p->ext));
00379 ((struct phone_pvt *)(ast->tech_pvt))->owner = NULL;
00380 ast_module_unref(ast_module_info->self);
00381 ast_verb(3, "Hungup '%s'\n", ast->name);
00382 ast->tech_pvt = NULL;
00383 ast_setstate(ast, AST_STATE_DOWN);
00384 restart_monitor();
00385 return 0;
00386 }
00387
00388 static int phone_setup(struct ast_channel *ast)
00389 {
00390 struct phone_pvt *p;
00391 p = ast->tech_pvt;
00392 ioctl(p->fd, PHONE_CPT_STOP);
00393
00394 if (ast->rawreadformat == AST_FORMAT_G729A) {
00395
00396 ioctl(p->fd, PHONE_REC_STOP);
00397 if (p->lastinput != AST_FORMAT_G729A) {
00398 p->lastinput = AST_FORMAT_G729A;
00399 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
00400 ast_log(LOG_WARNING, "Failed to set codec to g729\n");
00401 return -1;
00402 }
00403 }
00404 } else if (ast->rawreadformat == AST_FORMAT_G723_1) {
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_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n", ast->name, strerror(errno));
00463 else
00464 ast_debug(1, "Took linejack off hook\n");
00465 }
00466 phone_setup(ast);
00467 ast_debug(1, "phone_answer(%s)\n", ast->name);
00468 ast->rings = 0;
00469 ast_setstate(ast, AST_STATE_UP);
00470 return 0;
00471 }
00472
00473 #if 0
00474 static char phone_2digit(char c)
00475 {
00476 if (c == 12)
00477 return '#';
00478 else if (c == 11)
00479 return '*';
00480 else if ((c < 10) && (c >= 0))
00481 return '0' + c - 1;
00482 else
00483 return '?';
00484 }
00485 #endif
00486
00487 static struct ast_frame *phone_exception(struct ast_channel *ast)
00488 {
00489 int res;
00490 union telephony_exception phonee;
00491 struct phone_pvt *p = ast->tech_pvt;
00492 char digit;
00493
00494
00495 p->fr.datalen = 0;
00496 p->fr.samples = 0;
00497 p->fr.data = NULL;
00498 p->fr.src = "Phone";
00499 p->fr.offset = 0;
00500 p->fr.mallocd=0;
00501 p->fr.delivery = ast_tv(0,0);
00502
00503 phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
00504 if (phonee.bits.dtmf_ready) {
00505 ast_debug(1, "phone_exception(): DTMF\n");
00506
00507
00508 digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
00509 p->fr.subclass = digit;
00510 p->fr.frametype = AST_FRAME_DTMF;
00511 return &p->fr;
00512 }
00513 if (phonee.bits.hookstate) {
00514 ast_debug(1, "Hookstate changed\n");
00515 res = ioctl(p->fd, PHONE_HOOKSTATE);
00516
00517 ast_debug(1, "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_AUDIO_MASK ?
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 | AST_FORMAT_G729A)) &&
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_G729A) {
00681 if (p->lastformat != AST_FORMAT_G729A) {
00682 ioctl(p->fd, PHONE_PLAY_STOP);
00683 ioctl(p->fd, PHONE_REC_STOP);
00684 if (ioctl(p->fd, PHONE_PLAY_CODEC, G729)) {
00685 ast_log(LOG_WARNING, "Unable to set G729 mode\n");
00686 return -1;
00687 }
00688 if (ioctl(p->fd, PHONE_REC_CODEC, G729)) {
00689 ast_log(LOG_WARNING, "Unable to set G729 mode\n");
00690 return -1;
00691 }
00692 p->lastformat = AST_FORMAT_G729A;
00693 p->lastinput = AST_FORMAT_G729A;
00694
00695 p->obuflen = 0;
00696 codecset = 1;
00697 }
00698 if (frame->datalen > 80) {
00699 ast_log(LOG_WARNING, "Frame size too large for G.729 (%d bytes)\n", frame->datalen);
00700 return -1;
00701 }
00702 maxfr = 80;
00703 } else if (frame->subclass == AST_FORMAT_G723_1) {
00704 if (p->lastformat != AST_FORMAT_G723_1) {
00705 ioctl(p->fd, PHONE_PLAY_STOP);
00706 ioctl(p->fd, PHONE_REC_STOP);
00707 if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
00708 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00709 return -1;
00710 }
00711 if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
00712 ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
00713 return -1;
00714 }
00715 p->lastformat = AST_FORMAT_G723_1;
00716 p->lastinput = AST_FORMAT_G723_1;
00717
00718 p->obuflen = 0;
00719 codecset = 1;
00720 }
00721 if (frame->datalen > 24) {
00722 ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);
00723 return -1;
00724 }
00725 maxfr = 24;
00726 } else if (frame->subclass == AST_FORMAT_SLINEAR) {
00727 if (p->lastformat != AST_FORMAT_SLINEAR) {
00728 ioctl(p->fd, PHONE_PLAY_STOP);
00729 ioctl(p->fd, PHONE_REC_STOP);
00730 if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
00731 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00732 return -1;
00733 }
00734 if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
00735 ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
00736 return -1;
00737 }
00738 p->lastformat = AST_FORMAT_SLINEAR;
00739 p->lastinput = AST_FORMAT_SLINEAR;
00740 codecset = 1;
00741
00742 p->obuflen = 0;
00743 }
00744 maxfr = 480;
00745 } else if (frame->subclass == AST_FORMAT_ULAW) {
00746 if (p->lastformat != AST_FORMAT_ULAW) {
00747 ioctl(p->fd, PHONE_PLAY_STOP);
00748 ioctl(p->fd, PHONE_REC_STOP);
00749 if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {
00750 ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00751 return -1;
00752 }
00753 if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
00754 ast_log(LOG_WARNING, "Unable to set uLaw mode\n");
00755 return -1;
00756 }
00757 p->lastformat = AST_FORMAT_ULAW;
00758 p->lastinput = AST_FORMAT_ULAW;
00759 codecset = 1;
00760
00761 p->obuflen = 0;
00762 }
00763 maxfr = 240;
00764 } else {
00765 if (p->lastformat != frame->subclass) {
00766 ioctl(p->fd, PHONE_PLAY_STOP);
00767 ioctl(p->fd, PHONE_REC_STOP);
00768 if (ioctl(p->fd, PHONE_PLAY_CODEC, frame->subclass)) {
00769 ast_log(LOG_WARNING, "Unable to set %d mode\n",
00770 frame->subclass);
00771 return -1;
00772 }
00773 if (ioctl(p->fd, PHONE_REC_CODEC, frame->subclass)) {
00774 ast_log(LOG_WARNING, "Unable to set %d mode\n",
00775 frame->subclass);
00776 return -1;
00777 }
00778 p->lastformat = frame->subclass;
00779 p->lastinput = frame->subclass;
00780 codecset = 1;
00781
00782 p->obuflen = 0;
00783 }
00784 maxfr = 480;
00785 }
00786 if (codecset) {
00787 ioctl(p->fd, PHONE_REC_DEPTH, 3);
00788 ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
00789 if (ioctl(p->fd, PHONE_PLAY_START)) {
00790 ast_log(LOG_WARNING, "Failed to start playback\n");
00791 return -1;
00792 }
00793 if (ioctl(p->fd, PHONE_REC_START)) {
00794 ast_log(LOG_WARNING, "Failed to start recording\n");
00795 return -1;
00796 }
00797 }
00798
00799 sofar = 0;
00800 pos = frame->data;
00801 while(sofar < frame->datalen) {
00802
00803 expected = frame->datalen - sofar;
00804 if (maxfr < expected)
00805 expected = maxfr;
00806
00807
00808 if (frame->datalen == 4) {
00809 if (p->silencesupression) {
00810 (void) memset(tmpbuf + 4, 0, sizeof(tmpbuf) - 4);
00811 memcpy(tmpbuf, frame->data, 4);
00812 expected = 24;
00813 res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);
00814 }
00815 res = 4;
00816 expected=4;
00817 } else {
00818 int swap = 0;
00819 #if __BYTE_ORDER == __BIG_ENDIAN
00820 if (frame->subclass == AST_FORMAT_SLINEAR)
00821 swap = 1;
00822 #endif
00823 res = phone_write_buf(p, pos, expected, maxfr, swap);
00824 }
00825 if (res != expected) {
00826 if ((errno != EAGAIN) && (errno != EINTR)) {
00827 if (res < 0)
00828 ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
00829
00830
00831
00832
00833 #if 0
00834 else
00835 ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
00836 #endif
00837 return -1;
00838 } else
00839 res = expected;
00840 }
00841 sofar += res;
00842 pos += res;
00843 }
00844 return 0;
00845 }
00846
00847 static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context)
00848 {
00849 struct ast_channel *tmp;
00850 struct phone_codec_data codec;
00851 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);
00852 if (tmp) {
00853 tmp->tech = cur_tech;
00854 ast_channel_set_fd(tmp, 0, i->fd);
00855
00856 if (i->mode == MODE_FXS &&
00857 ioctl(i->fd, PHONE_QUERY_CODEC, &codec) == 0) {
00858 if (codec.type == LINEAR16)
00859 tmp->nativeformats =
00860 tmp->rawreadformat =
00861 tmp->rawwriteformat =
00862 AST_FORMAT_SLINEAR;
00863 else {
00864 tmp->nativeformats =
00865 tmp->rawreadformat =
00866 tmp->rawwriteformat =
00867 prefformat & ~AST_FORMAT_SLINEAR;
00868 }
00869 }
00870 else {
00871 tmp->nativeformats = prefformat;
00872 tmp->rawreadformat = prefformat;
00873 tmp->rawwriteformat = prefformat;
00874 }
00875
00876 if (state == AST_STATE_RING)
00877 tmp->rings = 1;
00878 tmp->tech_pvt = i;
00879 ast_copy_string(tmp->context, context, sizeof(tmp->context));
00880 if (!ast_strlen_zero(i->ext))
00881 ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));
00882 else
00883 strcpy(tmp->exten, "s");
00884 if (!ast_strlen_zero(i->language))
00885 ast_string_field_set(tmp, language, i->language);
00886
00887
00888
00889 tmp->cid.cid_ani = ast_strdup(i->cid_num);
00890
00891 i->owner = tmp;
00892 ast_module_ref(ast_module_info->self);
00893 if (state != AST_STATE_DOWN) {
00894 if (state == AST_STATE_RING) {
00895 ioctl(tmp->fds[0], PHONE_RINGBACK);
00896 i->cpt = 1;
00897 }
00898 if (ast_pbx_start(tmp)) {
00899 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00900 ast_hangup(tmp);
00901 }
00902 }
00903 } else
00904 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00905 return tmp;
00906 }
00907
00908 static void phone_mini_packet(struct phone_pvt *i)
00909 {
00910 int res;
00911 char buf[1024];
00912
00913 res = read(i->fd, buf, sizeof(buf));
00914 if (res < 1) {
00915 ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));
00916 return;
00917 }
00918 }
00919
00920 static void phone_check_exception(struct phone_pvt *i)
00921 {
00922 int offhook=0;
00923 char digit[2] = {0 , 0};
00924 union telephony_exception phonee;
00925
00926 #if 0
00927 ast_debug(1, "Exception!\n");
00928 #endif
00929 phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
00930 if (phonee.bits.dtmf_ready) {
00931 digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
00932 if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {
00933 ioctl(i->fd, PHONE_PLAY_STOP);
00934 ioctl(i->fd, PHONE_REC_STOP);
00935 ioctl(i->fd, PHONE_CPT_STOP);
00936 i->dialtone = 0;
00937 if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
00938 strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);
00939 if ((i->mode != MODE_FXS ||
00940 !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||
00941 !phonee.bits.dtmf_ready) &&
00942 ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00943
00944 phone_new(i, AST_STATE_RING, i->context);
00945
00946 } else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {
00947
00948
00949 if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00950
00951 phone_new(i, AST_STATE_RING, "default");
00952
00953 } else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {
00954
00955 ast_debug(1, "%s can't match anything in %s or default\n", i->ext, i->context);
00956 ioctl(i->fd, PHONE_BUSY);
00957 i->cpt = 1;
00958 }
00959 }
00960 #if 0
00961 ast_verbose("Extension is %s\n", i->ext);
00962 #endif
00963 }
00964 }
00965 if (phonee.bits.hookstate) {
00966 offhook = ioctl(i->fd, PHONE_HOOKSTATE);
00967 if (offhook) {
00968 if (i->mode == MODE_IMMEDIATE) {
00969 phone_new(i, AST_STATE_RING, i->context);
00970 } else if (i->mode == MODE_DIALTONE) {
00971 ast_module_ref(ast_module_info->self);
00972
00973 i->ext[0] = '\0';
00974
00975 i->dialtone++;
00976 ioctl(i->fd, PHONE_PLAY_STOP);
00977 ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
00978 ioctl(i->fd, PHONE_PLAY_START);
00979 i->lastformat = -1;
00980 } else if (i->mode == MODE_SIGMA) {
00981 ast_module_ref(ast_module_info->self);
00982
00983 i->ext[0] = '\0';
00984
00985 i->dialtone++;
00986 ioctl(i->fd, PHONE_DIALTONE);
00987 }
00988 } else {
00989 if (i->dialtone)
00990 ast_module_unref(ast_module_info->self);
00991 memset(i->ext, 0, sizeof(i->ext));
00992 if (i->cpt)
00993 {
00994 ioctl(i->fd, PHONE_CPT_STOP);
00995 i->cpt = 0;
00996 }
00997 ioctl(i->fd, PHONE_PLAY_STOP);
00998 ioctl(i->fd, PHONE_REC_STOP);
00999 i->dialtone = 0;
01000 i->lastformat = -1;
01001 }
01002 }
01003 if (phonee.bits.pstn_ring) {
01004 ast_verbose("Unit is ringing\n");
01005 phone_new(i, AST_STATE_RING, i->context);
01006 }
01007 if (phonee.bits.caller_id)
01008 ast_verbose("We have caller ID\n");
01009
01010
01011 }
01012
01013 static void *do_monitor(void *data)
01014 {
01015 fd_set rfds, efds;
01016 int n, res;
01017 struct phone_pvt *i;
01018 int tonepos = 0;
01019
01020 struct timeval tv = {0,0};
01021 int dotone;
01022
01023
01024 while (monitor) {
01025
01026
01027
01028 if (ast_mutex_lock(&iflock)) {
01029 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
01030 return NULL;
01031 }
01032
01033
01034 n = -1;
01035 FD_ZERO(&rfds);
01036 FD_ZERO(&efds);
01037 i = iflist;
01038 dotone = 0;
01039 while (i) {
01040 if (FD_ISSET(i->fd, &rfds))
01041 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
01042 if (!i->owner) {
01043
01044 FD_SET(i->fd, &rfds);
01045 FD_SET(i->fd, &efds);
01046 if (i->fd > n)
01047 n = i->fd;
01048 if (i->dialtone && i->mode != MODE_SIGMA) {
01049
01050
01051 if (ast_tvzero(tv)) {
01052
01053 if (write(i->fd, DialTone + tonepos, 240) != 240)
01054 ast_log(LOG_WARNING, "Dial tone write error\n");
01055 }
01056 dotone++;
01057 }
01058 }
01059
01060 i = i->next;
01061 }
01062
01063 ast_mutex_unlock(&iflock);
01064
01065
01066 if (dotone && i && i->mode != MODE_SIGMA) {
01067
01068 tonepos += 240;
01069 if (tonepos >= sizeof(DialTone))
01070 tonepos = 0;
01071 if (ast_tvzero(tv)) {
01072 tv = ast_tv(30000, 0);
01073 }
01074 res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
01075 } else {
01076 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
01077 tv = ast_tv(0,0);
01078 tonepos = 0;
01079 }
01080
01081 if (res < 0) {
01082 ast_debug(1, "select return %d: %s\n", res, strerror(errno));
01083 continue;
01084 }
01085
01086
01087 if (!res)
01088 continue;
01089
01090
01091 if (ast_mutex_lock(&iflock)) {
01092 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01093 continue;
01094 }
01095
01096 i = iflist;
01097 for(; i; i=i->next) {
01098 if (FD_ISSET(i->fd, &rfds)) {
01099 if (i->owner) {
01100 continue;
01101 }
01102 phone_mini_packet(i);
01103 }
01104 if (FD_ISSET(i->fd, &efds)) {
01105 if (i->owner) {
01106 continue;
01107 }
01108 phone_check_exception(i);
01109 }
01110 }
01111 ast_mutex_unlock(&iflock);
01112 }
01113 return NULL;
01114
01115 }
01116
01117 static int restart_monitor()
01118 {
01119
01120 if (monitor_thread == AST_PTHREADT_STOP)
01121 return 0;
01122 if (ast_mutex_lock(&monlock)) {
01123 ast_log(LOG_WARNING, "Unable to lock monitor\n");
01124 return -1;
01125 }
01126 if (monitor_thread == pthread_self()) {
01127 ast_mutex_unlock(&monlock);
01128 ast_log(LOG_WARNING, "Cannot kill myself\n");
01129 return -1;
01130 }
01131 if (monitor_thread != AST_PTHREADT_NULL) {
01132 if (ast_mutex_lock(&iflock)) {
01133 ast_mutex_unlock(&monlock);
01134 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01135 return -1;
01136 }
01137 monitor = 0;
01138 while (pthread_kill(monitor_thread, SIGURG) == 0)
01139 sched_yield();
01140 pthread_join(monitor_thread, NULL);
01141 ast_mutex_unlock(&iflock);
01142 }
01143 monitor = 1;
01144
01145 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01146 ast_mutex_unlock(&monlock);
01147 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01148 return -1;
01149 }
01150 ast_mutex_unlock(&monlock);
01151 return 0;
01152 }
01153
01154 static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgain)
01155 {
01156
01157 struct phone_pvt *tmp;
01158 int flags;
01159
01160 tmp = ast_calloc(1, sizeof(*tmp));
01161 if (tmp) {
01162 tmp->fd = open(iface, O_RDWR);
01163 if (tmp->fd < 0) {
01164 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01165 ast_free(tmp);
01166 return NULL;
01167 }
01168 if (mode == MODE_FXO) {
01169 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
01170 ast_debug(1, "Unable to set port to PSTN\n");
01171 }
01172 } else {
01173 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
01174 if (mode != MODE_FXS)
01175 ast_debug(1, "Unable to set port to POTS\n");
01176 }
01177 ioctl(tmp->fd, PHONE_PLAY_STOP);
01178 ioctl(tmp->fd, PHONE_REC_STOP);
01179 ioctl(tmp->fd, PHONE_RING_STOP);
01180 ioctl(tmp->fd, PHONE_CPT_STOP);
01181 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01182 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01183 if (echocancel != AEC_OFF)
01184 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01185 if (silencesupression)
01186 tmp->silencesupression = 1;
01187 #ifdef PHONE_VAD
01188 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01189 #endif
01190 tmp->mode = mode;
01191 flags = fcntl(tmp->fd, F_GETFL);
01192 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01193 tmp->owner = NULL;
01194 tmp->lastformat = -1;
01195 tmp->lastinput = -1;
01196 tmp->ministate = 0;
01197 memset(tmp->ext, 0, sizeof(tmp->ext));
01198 ast_copy_string(tmp->language, language, sizeof(tmp->language));
01199 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01200 ast_copy_string(tmp->context, context, sizeof(tmp->context));
01201 tmp->next = NULL;
01202 tmp->obuflen = 0;
01203 tmp->dialtone = 0;
01204 tmp->cpt = 0;
01205 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01206 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01207 tmp->txgain = txgain;
01208 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01209 tmp->rxgain = rxgain;
01210 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01211 }
01212 return tmp;
01213 }
01214
01215 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause)
01216 {
01217 int oldformat;
01218 struct phone_pvt *p;
01219 struct ast_channel *tmp = NULL;
01220 char *name = data;
01221
01222
01223 if (ast_mutex_lock(&iflock)) {
01224 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01225 return NULL;
01226 }
01227 p = iflist;
01228 while(p) {
01229 if (p->mode == MODE_FXS ||
01230 format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01231 size_t length = strlen(p->dev + 5);
01232 if (strncmp(name, p->dev + 5, length) == 0 &&
01233 !isalnum(name[length])) {
01234 if (!p->owner) {
01235 tmp = phone_new(p, AST_STATE_DOWN, p->context);
01236 break;
01237 } else
01238 *cause = AST_CAUSE_BUSY;
01239 }
01240 }
01241 p = p->next;
01242 }
01243 ast_mutex_unlock(&iflock);
01244 restart_monitor();
01245 if (tmp == NULL) {
01246 oldformat = format;
01247 format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01248 if (!format) {
01249 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01250 return NULL;
01251 }
01252 }
01253 return tmp;
01254 }
01255
01256
01257 static int parse_gain_value(const char *gain_type, const char *value)
01258 {
01259 float gain;
01260
01261
01262 if (sscanf(value, "%f", &gain) != 1)
01263 {
01264 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01265 value, gain_type, config);
01266 return DEFAULT_GAIN;
01267 }
01268
01269
01270 gain = gain * (float)DEFAULT_GAIN;
01271
01272
01273 if (value[strlen(value) - 1] == '%')
01274 return (int)(gain / (float)100);
01275
01276 return (int)gain;
01277 }
01278
01279 static int __unload_module(void)
01280 {
01281 struct phone_pvt *p, *pl;
01282
01283 if (cur_tech)
01284 ast_channel_unregister(cur_tech);
01285 if (!ast_mutex_lock(&iflock)) {
01286
01287 p = iflist;
01288 while(p) {
01289 if (p->owner)
01290 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01291 p = p->next;
01292 }
01293 iflist = NULL;
01294 ast_mutex_unlock(&iflock);
01295 } else {
01296 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01297 return -1;
01298 }
01299 if (!ast_mutex_lock(&monlock)) {
01300 if (monitor_thread > AST_PTHREADT_NULL) {
01301 monitor = 0;
01302 while (pthread_kill(monitor_thread, SIGURG) == 0)
01303 sched_yield();
01304 pthread_join(monitor_thread, NULL);
01305 }
01306 monitor_thread = AST_PTHREADT_STOP;
01307 ast_mutex_unlock(&monlock);
01308 } else {
01309 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01310 return -1;
01311 }
01312
01313 if (!ast_mutex_lock(&iflock)) {
01314
01315 p = iflist;
01316 while(p) {
01317
01318 if (p->fd > -1)
01319 close(p->fd);
01320 pl = p;
01321 p = p->next;
01322
01323 ast_free(pl);
01324 }
01325 iflist = NULL;
01326 ast_mutex_unlock(&iflock);
01327 } else {
01328 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01329 return -1;
01330 }
01331
01332 return 0;
01333 }
01334
01335 static int unload_module(void)
01336 {
01337 return __unload_module();
01338 }
01339
01340 static int load_module(void)
01341 {
01342 struct ast_config *cfg;
01343 struct ast_variable *v;
01344 struct phone_pvt *tmp;
01345 int mode = MODE_IMMEDIATE;
01346 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN;
01347 struct ast_flags config_flags = { 0 };
01348
01349 cfg = ast_config_load(config, config_flags);
01350
01351
01352 if (!cfg) {
01353 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01354 return AST_MODULE_LOAD_DECLINE;
01355 }
01356 if (ast_mutex_lock(&iflock)) {
01357
01358 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01359 return AST_MODULE_LOAD_FAILURE;
01360 }
01361 v = ast_variable_browse(cfg, "interfaces");
01362 while(v) {
01363
01364 if (!strcasecmp(v->name, "device")) {
01365 tmp = mkif(v->value, mode, txgain, rxgain);
01366 if (tmp) {
01367 tmp->next = iflist;
01368 iflist = tmp;
01369
01370 } else {
01371 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01372 ast_config_destroy(cfg);
01373 ast_mutex_unlock(&iflock);
01374 __unload_module();
01375 return AST_MODULE_LOAD_FAILURE;
01376 }
01377 } else if (!strcasecmp(v->name, "silencesupression")) {
01378 silencesupression = ast_true(v->value);
01379 } else if (!strcasecmp(v->name, "language")) {
01380 ast_copy_string(language, v->value, sizeof(language));
01381 } else if (!strcasecmp(v->name, "callerid")) {
01382 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01383 } else if (!strcasecmp(v->name, "mode")) {
01384 if (!strncasecmp(v->value, "di", 2))
01385 mode = MODE_DIALTONE;
01386 else if (!strncasecmp(v->value, "sig", 3))
01387 mode = MODE_SIGMA;
01388 else if (!strncasecmp(v->value, "im", 2))
01389 mode = MODE_IMMEDIATE;
01390 else if (!strncasecmp(v->value, "fxs", 3)) {
01391 mode = MODE_FXS;
01392 prefformat = 0x01ff0000;
01393 }
01394 else if (!strncasecmp(v->value, "fx", 2))
01395 mode = MODE_FXO;
01396 else
01397 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01398 } else if (!strcasecmp(v->name, "context")) {
01399 ast_copy_string(context, v->value, sizeof(context));
01400 } else if (!strcasecmp(v->name, "format")) {
01401 if (!strcasecmp(v->value, "g729")) {
01402 prefformat = AST_FORMAT_G729A;
01403 } else if (!strcasecmp(v->value, "g723.1")) {
01404 prefformat = AST_FORMAT_G723_1;
01405 } else if (!strcasecmp(v->value, "slinear")) {
01406 if (mode == MODE_FXS)
01407 prefformat |= AST_FORMAT_SLINEAR;
01408 else prefformat = AST_FORMAT_SLINEAR;
01409 } else if (!strcasecmp(v->value, "ulaw")) {
01410 prefformat = AST_FORMAT_ULAW;
01411 } else
01412 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01413 } else if (!strcasecmp(v->name, "echocancel")) {
01414 if (!strcasecmp(v->value, "off")) {
01415 echocancel = AEC_OFF;
01416 } else if (!strcasecmp(v->value, "low")) {
01417 echocancel = AEC_LOW;
01418 } else if (!strcasecmp(v->value, "medium")) {
01419 echocancel = AEC_MED;
01420 } else if (!strcasecmp(v->value, "high")) {
01421 echocancel = AEC_HIGH;
01422 } else
01423 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01424 } else if (!strcasecmp(v->name, "txgain")) {
01425 txgain = parse_gain_value(v->name, v->value);
01426 } else if (!strcasecmp(v->name, "rxgain")) {
01427 rxgain = parse_gain_value(v->name, v->value);
01428 }
01429 v = v->next;
01430 }
01431 ast_mutex_unlock(&iflock);
01432
01433 if (mode == MODE_FXS) {
01434 phone_tech_fxs.capabilities = prefformat;
01435 cur_tech = &phone_tech_fxs;
01436 } else
01437 cur_tech = (struct ast_channel_tech *) &phone_tech;
01438
01439
01440
01441 if (ast_channel_register(cur_tech)) {
01442 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
01443 ast_config_destroy(cfg);
01444 __unload_module();
01445 return AST_MODULE_LOAD_FAILURE;
01446 }
01447 ast_config_destroy(cfg);
01448
01449 restart_monitor();
01450 return AST_MODULE_LOAD_SUCCESS;
01451 }
01452
01453 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");