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: 284593 $")
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 struct pollfd *fds = NULL;
01015 int nfds = 0, inuse_fds = 0, res;
01016 struct phone_pvt *i;
01017 int tonepos = 0;
01018
01019 struct timeval tv = { 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 i = iflist;
01034 dotone = 0;
01035 inuse_fds = 0;
01036 for (i = iflist; i; i = i->next) {
01037 if (!i->owner) {
01038
01039 if (inuse_fds == nfds) {
01040 void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
01041 if (!tmp) {
01042
01043 continue;
01044 }
01045 fds = tmp;
01046 nfds++;
01047 }
01048 fds[inuse_fds].fd = i->fd;
01049 fds[inuse_fds].events = POLLIN | POLLERR;
01050 fds[inuse_fds].revents = 0;
01051 inuse_fds++;
01052
01053 if (i->dialtone && i->mode != MODE_SIGMA) {
01054
01055
01056 if (ast_tvzero(tv)) {
01057
01058 if (write(i->fd, DialTone + tonepos, 240) != 240) {
01059 ast_log(LOG_WARNING, "Dial tone write error\n");
01060 }
01061 }
01062 dotone++;
01063 }
01064 }
01065 }
01066
01067 ast_mutex_unlock(&iflock);
01068
01069
01070 if (dotone && i && i->mode != MODE_SIGMA) {
01071
01072 tonepos += 240;
01073 if (tonepos >= sizeof(DialTone)) {
01074 tonepos = 0;
01075 }
01076 if (ast_tvzero(tv)) {
01077 tv = ast_tv(0, 30000);
01078 }
01079 res = ast_poll2(fds, inuse_fds, &tv);
01080 } else {
01081 res = ast_poll(fds, inuse_fds, -1);
01082 tv = ast_tv(0, 0);
01083 tonepos = 0;
01084 }
01085
01086 if (res < 0) {
01087 ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
01088 continue;
01089 }
01090
01091
01092 if (!res) {
01093 continue;
01094 }
01095
01096
01097 if (ast_mutex_lock(&iflock)) {
01098 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01099 continue;
01100 }
01101
01102 for (i = iflist; i; i = i->next) {
01103 int j;
01104
01105 for (j = 0; j < inuse_fds; j++) {
01106 if (fds[j].fd == i->fd) {
01107 break;
01108 }
01109 }
01110
01111
01112 if (j == inuse_fds) {
01113 continue;
01114 }
01115
01116 if (fds[j].revents & POLLIN) {
01117 if (i->owner) {
01118 continue;
01119 }
01120 phone_mini_packet(i);
01121 }
01122 if (fds[j].revents & POLLERR) {
01123 if (i->owner) {
01124 continue;
01125 }
01126 phone_check_exception(i);
01127 }
01128 }
01129 ast_mutex_unlock(&iflock);
01130 }
01131 return NULL;
01132 }
01133
01134 static int restart_monitor()
01135 {
01136
01137 if (monitor_thread == AST_PTHREADT_STOP)
01138 return 0;
01139 if (ast_mutex_lock(&monlock)) {
01140 ast_log(LOG_WARNING, "Unable to lock monitor\n");
01141 return -1;
01142 }
01143 if (monitor_thread == pthread_self()) {
01144 ast_mutex_unlock(&monlock);
01145 ast_log(LOG_WARNING, "Cannot kill myself\n");
01146 return -1;
01147 }
01148 if (monitor_thread != AST_PTHREADT_NULL) {
01149 if (ast_mutex_lock(&iflock)) {
01150 ast_mutex_unlock(&monlock);
01151 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
01152 return -1;
01153 }
01154 monitor = 0;
01155 while (pthread_kill(monitor_thread, SIGURG) == 0)
01156 sched_yield();
01157 pthread_join(monitor_thread, NULL);
01158 ast_mutex_unlock(&iflock);
01159 }
01160 monitor = 1;
01161
01162 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
01163 ast_mutex_unlock(&monlock);
01164 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01165 return -1;
01166 }
01167 ast_mutex_unlock(&monlock);
01168 return 0;
01169 }
01170
01171 static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgain)
01172 {
01173
01174 struct phone_pvt *tmp;
01175 int flags;
01176
01177 tmp = ast_calloc(1, sizeof(*tmp));
01178 if (tmp) {
01179 tmp->fd = open(iface, O_RDWR);
01180 if (tmp->fd < 0) {
01181 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
01182 ast_free(tmp);
01183 return NULL;
01184 }
01185 if (mode == MODE_FXO) {
01186 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) {
01187 ast_debug(1, "Unable to set port to PSTN\n");
01188 }
01189 } else {
01190 if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
01191 if (mode != MODE_FXS)
01192 ast_debug(1, "Unable to set port to POTS\n");
01193 }
01194 ioctl(tmp->fd, PHONE_PLAY_STOP);
01195 ioctl(tmp->fd, PHONE_REC_STOP);
01196 ioctl(tmp->fd, PHONE_RING_STOP);
01197 ioctl(tmp->fd, PHONE_CPT_STOP);
01198 if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
01199 ast_debug(1, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));
01200 if (echocancel != AEC_OFF)
01201 ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
01202 if (silencesupression)
01203 tmp->silencesupression = 1;
01204 #ifdef PHONE_VAD
01205 ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
01206 #endif
01207 tmp->mode = mode;
01208 flags = fcntl(tmp->fd, F_GETFL);
01209 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
01210 tmp->owner = NULL;
01211 tmp->lastformat = -1;
01212 tmp->lastinput = -1;
01213 tmp->ministate = 0;
01214 memset(tmp->ext, 0, sizeof(tmp->ext));
01215 ast_copy_string(tmp->language, language, sizeof(tmp->language));
01216 ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));
01217 ast_copy_string(tmp->context, context, sizeof(tmp->context));
01218 tmp->next = NULL;
01219 tmp->obuflen = 0;
01220 tmp->dialtone = 0;
01221 tmp->cpt = 0;
01222 ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
01223 ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
01224 tmp->txgain = txgain;
01225 ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);
01226 tmp->rxgain = rxgain;
01227 ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);
01228 }
01229 return tmp;
01230 }
01231
01232 static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause)
01233 {
01234 int oldformat;
01235 struct phone_pvt *p;
01236 struct ast_channel *tmp = NULL;
01237 char *name = data;
01238
01239
01240 if (ast_mutex_lock(&iflock)) {
01241 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01242 return NULL;
01243 }
01244 p = iflist;
01245 while(p) {
01246 if (p->mode == MODE_FXS ||
01247 format & (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {
01248 size_t length = strlen(p->dev + 5);
01249 if (strncmp(name, p->dev + 5, length) == 0 &&
01250 !isalnum(name[length])) {
01251 if (!p->owner) {
01252 tmp = phone_new(p, AST_STATE_DOWN, p->context);
01253 break;
01254 } else
01255 *cause = AST_CAUSE_BUSY;
01256 }
01257 }
01258 p = p->next;
01259 }
01260 ast_mutex_unlock(&iflock);
01261 restart_monitor();
01262 if (tmp == NULL) {
01263 oldformat = format;
01264 format &= (AST_FORMAT_G729A | AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
01265 if (!format) {
01266 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
01267 return NULL;
01268 }
01269 }
01270 return tmp;
01271 }
01272
01273
01274 static int parse_gain_value(const char *gain_type, const char *value)
01275 {
01276 float gain;
01277
01278
01279 if (sscanf(value, "%30f", &gain) != 1)
01280 {
01281 ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",
01282 value, gain_type, config);
01283 return DEFAULT_GAIN;
01284 }
01285
01286
01287 gain = gain * (float)DEFAULT_GAIN;
01288
01289
01290 if (value[strlen(value) - 1] == '%')
01291 return (int)(gain / (float)100);
01292
01293 return (int)gain;
01294 }
01295
01296 static int __unload_module(void)
01297 {
01298 struct phone_pvt *p, *pl;
01299
01300 if (cur_tech)
01301 ast_channel_unregister(cur_tech);
01302 if (!ast_mutex_lock(&iflock)) {
01303
01304 p = iflist;
01305 while(p) {
01306 if (p->owner)
01307 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01308 p = p->next;
01309 }
01310 iflist = NULL;
01311 ast_mutex_unlock(&iflock);
01312 } else {
01313 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01314 return -1;
01315 }
01316 if (!ast_mutex_lock(&monlock)) {
01317 if (monitor_thread > AST_PTHREADT_NULL) {
01318 monitor = 0;
01319 while (pthread_kill(monitor_thread, SIGURG) == 0)
01320 sched_yield();
01321 pthread_join(monitor_thread, NULL);
01322 }
01323 monitor_thread = AST_PTHREADT_STOP;
01324 ast_mutex_unlock(&monlock);
01325 } else {
01326 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01327 return -1;
01328 }
01329
01330 if (!ast_mutex_lock(&iflock)) {
01331
01332 p = iflist;
01333 while(p) {
01334
01335 if (p->fd > -1)
01336 close(p->fd);
01337 pl = p;
01338 p = p->next;
01339
01340 ast_free(pl);
01341 }
01342 iflist = NULL;
01343 ast_mutex_unlock(&iflock);
01344 } else {
01345 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01346 return -1;
01347 }
01348
01349 return 0;
01350 }
01351
01352 static int unload_module(void)
01353 {
01354 return __unload_module();
01355 }
01356
01357 static int load_module(void)
01358 {
01359 struct ast_config *cfg;
01360 struct ast_variable *v;
01361 struct phone_pvt *tmp;
01362 int mode = MODE_IMMEDIATE;
01363 int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN;
01364 struct ast_flags config_flags = { 0 };
01365
01366 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
01367 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
01368 return AST_MODULE_LOAD_DECLINE;
01369 }
01370
01371
01372 if (!cfg) {
01373 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
01374 return AST_MODULE_LOAD_DECLINE;
01375 }
01376 if (ast_mutex_lock(&iflock)) {
01377
01378 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
01379 return AST_MODULE_LOAD_FAILURE;
01380 }
01381 v = ast_variable_browse(cfg, "interfaces");
01382 while(v) {
01383
01384 if (!strcasecmp(v->name, "device")) {
01385 tmp = mkif(v->value, mode, txgain, rxgain);
01386 if (tmp) {
01387 tmp->next = iflist;
01388 iflist = tmp;
01389
01390 } else {
01391 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01392 ast_config_destroy(cfg);
01393 ast_mutex_unlock(&iflock);
01394 __unload_module();
01395 return AST_MODULE_LOAD_FAILURE;
01396 }
01397 } else if (!strcasecmp(v->name, "silencesupression")) {
01398 silencesupression = ast_true(v->value);
01399 } else if (!strcasecmp(v->name, "language")) {
01400 ast_copy_string(language, v->value, sizeof(language));
01401 } else if (!strcasecmp(v->name, "callerid")) {
01402 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01403 } else if (!strcasecmp(v->name, "mode")) {
01404 if (!strncasecmp(v->value, "di", 2))
01405 mode = MODE_DIALTONE;
01406 else if (!strncasecmp(v->value, "sig", 3))
01407 mode = MODE_SIGMA;
01408 else if (!strncasecmp(v->value, "im", 2))
01409 mode = MODE_IMMEDIATE;
01410 else if (!strncasecmp(v->value, "fxs", 3)) {
01411 mode = MODE_FXS;
01412 prefformat = 0x01ff0000;
01413 }
01414 else if (!strncasecmp(v->value, "fx", 2))
01415 mode = MODE_FXO;
01416 else
01417 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01418 } else if (!strcasecmp(v->name, "context")) {
01419 ast_copy_string(context, v->value, sizeof(context));
01420 } else if (!strcasecmp(v->name, "format")) {
01421 if (!strcasecmp(v->value, "g729")) {
01422 prefformat = AST_FORMAT_G729A;
01423 } else if (!strcasecmp(v->value, "g723.1")) {
01424 prefformat = AST_FORMAT_G723_1;
01425 } else if (!strcasecmp(v->value, "slinear")) {
01426 if (mode == MODE_FXS)
01427 prefformat |= AST_FORMAT_SLINEAR;
01428 else prefformat = AST_FORMAT_SLINEAR;
01429 } else if (!strcasecmp(v->value, "ulaw")) {
01430 prefformat = AST_FORMAT_ULAW;
01431 } else
01432 ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
01433 } else if (!strcasecmp(v->name, "echocancel")) {
01434 if (!strcasecmp(v->value, "off")) {
01435 echocancel = AEC_OFF;
01436 } else if (!strcasecmp(v->value, "low")) {
01437 echocancel = AEC_LOW;
01438 } else if (!strcasecmp(v->value, "medium")) {
01439 echocancel = AEC_MED;
01440 } else if (!strcasecmp(v->value, "high")) {
01441 echocancel = AEC_HIGH;
01442 } else
01443 ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
01444 } else if (!strcasecmp(v->name, "txgain")) {
01445 txgain = parse_gain_value(v->name, v->value);
01446 } else if (!strcasecmp(v->name, "rxgain")) {
01447 rxgain = parse_gain_value(v->name, v->value);
01448 }
01449 v = v->next;
01450 }
01451 ast_mutex_unlock(&iflock);
01452
01453 if (mode == MODE_FXS) {
01454 phone_tech_fxs.capabilities = prefformat;
01455 cur_tech = &phone_tech_fxs;
01456 } else
01457 cur_tech = (struct ast_channel_tech *) &phone_tech;
01458
01459
01460
01461 if (ast_channel_register(cur_tech)) {
01462 ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
01463 ast_config_destroy(cfg);
01464 __unload_module();
01465 return AST_MODULE_LOAD_FAILURE;
01466 }
01467 ast_config_destroy(cfg);
01468
01469 restart_monitor();
01470 return AST_MODULE_LOAD_SUCCESS;
01471 }
01472
01473 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");