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