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