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