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 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029 #include <string.h>
00030 #include <sys/time.h>
00031 #include <errno.h>
00032 #include <netinet/in.h>
00033 #include <arpa/inet.h>
00034 #include <sys/socket.h>
00035 #include <fcntl.h>
00036 #include <sys/ioctl.h>
00037 #include <sys/termios.h>
00038 #include <sys/signal.h>
00039
00040 #include "asterisk.h"
00041
00042 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 38904 $")
00043
00044 #include "asterisk/lock.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/module.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/options.h"
00051 #include "asterisk/vmodem.h"
00052 #include "asterisk/utils.h"
00053
00054
00055 #define ECHO_TIMEOUT 10
00056
00057 static const char desc[] = "Generic Voice Modem Driver";
00058 static const char tdesc[] = "Generic Voice Modem Channel Driver";
00059 static const char type[] = "Modem";
00060 static const char config[] = "modem.conf";
00061 static char dialtype = 'T';
00062 static int gmode = MODEM_MODE_IMMEDIATE;
00063
00064
00065 static char mtype[80] = "autodetect";
00066
00067 static char context[AST_MAX_EXTENSION]= "default";
00068
00069
00070 static char language[MAX_LANGUAGE] = "";
00071
00072
00073 static char initstr[AST_MAX_INIT_STR] = "ATE0Q0";
00074
00075
00076 static char msn[AST_MAX_EXTENSION]="";
00077
00078
00079 static char incomingmsn[AST_MAX_EXTENSION]="";
00080
00081
00082 static int dtmfmode = MODEM_DTMF_AST;
00083
00084 static int dtmfmodegen = MODEM_DTMF_AST;
00085
00086 struct ast_dsp *dsp = NULL;
00087
00088
00089 static char outgoingmsn[AST_MAX_EXTENSION]="";
00090
00091
00092 static ast_group_t cur_group = 0;
00093
00094 static int usecnt =0;
00095
00096 static int baudrate = 115200;
00097
00098 static int stripmsd = 0;
00099
00100 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00101
00102
00103 AST_MUTEX_DEFINE_STATIC(iflock);
00104
00105
00106
00107 AST_MUTEX_DEFINE_STATIC(monlock);
00108
00109
00110
00111 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00112
00113 static int restart_monitor(void);
00114
00115 int dep_warning = 0;
00116
00117 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause);
00118 static int modem_digit(struct ast_channel *ast, char digit);
00119 static int modem_call(struct ast_channel *ast, char *idest, int timeout);
00120 static int modem_hangup(struct ast_channel *ast);
00121 static int modem_answer(struct ast_channel *ast);
00122 static struct ast_frame *modem_read(struct ast_channel *);
00123 static int modem_write(struct ast_channel *ast, struct ast_frame *frame);
00124 static int modem_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00125
00126 static const struct ast_channel_tech modem_tech = {
00127 .type = type,
00128 .description = tdesc,
00129 .capabilities = AST_FORMAT_SLINEAR,
00130 .requester = modem_request,
00131 .send_digit = modem_digit,
00132 .call = modem_call,
00133 .hangup = modem_hangup,
00134 .answer = modem_answer,
00135 .read = modem_read,
00136 .write = modem_write,
00137 .fixup = modem_fixup,
00138 };
00139
00140
00141
00142
00143 static struct ast_modem_pvt *iflist = NULL;
00144
00145 static int modem_digit(struct ast_channel *ast, char digit)
00146 {
00147 struct ast_modem_pvt *p;
00148 p = ast->tech_pvt;
00149 if (p->mc->dialdigit)
00150 return p->mc->dialdigit(p, digit);
00151 ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n", ast->name);
00152 return -1;
00153 }
00154
00155 static struct ast_modem_driver *drivers = NULL;
00156
00157 static struct ast_modem_driver *find_capability(char *ident)
00158 {
00159 struct ast_modem_driver *mc;
00160 int x;
00161 mc = drivers;
00162 while(mc) {
00163 for (x=0;mc->idents[x];x++) {
00164 if (!strcmp(ident, mc->idents[x]))
00165 break;
00166 }
00167 if (mc->idents[x])
00168 break;
00169 mc = mc->next;
00170 }
00171 if (mc) {
00172 if (mc->incusecnt)
00173 mc->incusecnt();
00174 }
00175 return mc;
00176 }
00177
00178 static struct ast_modem_driver *find_driver(char *drv)
00179 {
00180 struct ast_modem_driver *mc;
00181 mc = drivers;
00182 while(mc) {
00183 if (!strcasecmp(mc->name, drv))
00184 break;
00185 mc = mc->next;
00186 }
00187 if (mc) {
00188 if (mc->incusecnt)
00189 mc->incusecnt();
00190 }
00191 return mc;
00192 }
00193
00194 int ast_register_modem_driver(struct ast_modem_driver *mc)
00195 {
00196 mc->next = drivers;
00197 drivers = mc;
00198 return 0;
00199 }
00200
00201 int ast_unregister_modem_driver(struct ast_modem_driver *mc)
00202 {
00203 struct ast_modem_driver *last = NULL, *cur;
00204 cur = drivers;
00205 while(cur) {
00206 if (cur == mc) {
00207 if (last)
00208 last->next = mc->next;
00209 else
00210 drivers = mc->next;
00211 return 0;
00212 }
00213 cur = cur->next;
00214 }
00215 return -1;
00216 }
00217
00218 static int modem_call(struct ast_channel *ast, char *idest, int timeout)
00219 {
00220 struct ast_modem_pvt *p;
00221 int ms = timeout;
00222 char rdest[80], *where, dstr[100] = "";
00223 char *stringp=NULL;
00224 strncpy(rdest, idest, sizeof(rdest)-1);
00225 stringp=rdest;
00226 strsep(&stringp, ":");
00227 where = strsep(&stringp, ":");
00228 if (!where) {
00229 ast_log(LOG_WARNING, "Destination %s requres a real destination (device:destination)\n", idest);
00230 return -1;
00231 }
00232 p = ast->tech_pvt;
00233 strncpy(dstr, where + p->stripmsd, sizeof(dstr) - 1);
00234
00235 if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) {
00236 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00237 ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
00238 return -1;
00239 }
00240 }
00241 if (!strcasecmp(rdest,"transfer"))
00242 {
00243 snprintf(dstr, sizeof(dstr), "!,%s", where + p->stripmsd);
00244 }
00245 if (!strcasecmp(where, "handset")) {
00246 if (p->mc->setdev)
00247 if (p->mc->setdev(p, MODEM_DEV_HANDSET))
00248 return -1;
00249
00250 ast_setstate(ast, AST_STATE_UP);
00251 } else {
00252 if (p->mc->setdev)
00253 if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
00254 return -1;
00255 if (p->mc->dial)
00256 p->mc->dial(p, dstr);
00257 ast_setstate(ast, AST_STATE_DIALING);
00258 while((ast->_state != AST_STATE_UP) && (ms > 0)) {
00259 ms = ast_waitfor(ast, ms);
00260
00261 if (ms > 0) {
00262 if (!modem_read(ast))
00263 return -1;
00264 }
00265 }
00266 if (ms < 0)
00267 return -1;
00268 }
00269 return 0;
00270 }
00271
00272 int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
00273 {
00274 int i;
00275 usleep(5000);
00276 if (!len) {
00277 for(i = 0; cmd[i];)
00278 {
00279 if (fwrite(cmd + i,1,1,p->f) != 1)
00280 {
00281 if (errno == EWOULDBLOCK) continue;
00282 return -1;
00283 }
00284 i++;
00285 }
00286 tcdrain(fileno(p->f));
00287 fprintf(p->f,"\r\n");
00288 return 0;
00289 } else {
00290 if (fwrite(cmd, 1, len, p->f) < len)
00291 return -1;
00292 return 0;
00293 }
00294 }
00295
00296 int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
00297 {
00298 int res = -1,c,i;
00299 timeout *= 1000;
00300 p->response[0] = 0;
00301 c = i = 0;
00302 do {
00303 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
00304 if (res < 0) {
00305 strncpy(p->response, "(No Response)", sizeof(p->response)-1);
00306 return -1;
00307 }
00308
00309 while(i < sizeof(p->response) - 1)
00310 {
00311 c = fgetc(p->f);
00312 if (c < 1)
00313 {
00314
00315 if (errno == EWOULDBLOCK) break;
00316
00317 strncpy(p->response, "(No Response)", sizeof(p->response)-1);
00318 return -1;
00319 }
00320
00321 p->response[i++] = c;
00322 p->response[i] = 0;
00323
00324 if (c == '\n') break;
00325 }
00326 if (c >= 0)
00327 {
00328
00329 if (!strcmp(p->response,"\r\n"))
00330 {
00331
00332 i = 0;
00333 p->response[0] = 0;
00334 }
00335 else
00336 {
00337 return 0;
00338 }
00339 }
00340 } while(timeout > 0);
00341 strncpy(p->response, "(No Response)", sizeof(p->response)-1);
00342 return -1;
00343 }
00344
00345 int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
00346 {
00347 int res = -1;
00348 timeout *= 1000;
00349 strncpy(p->response, "(No Response)", sizeof(p->response)-1);
00350 do {
00351 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
00352 if (res < 0) {
00353 return -1;
00354 }
00355
00356 fgets(p->response, sizeof(p->response), p->f);
00357 if (!strncasecmp(p->response, result, strlen(result)))
00358 return 0;
00359 } while(timeout > 0);
00360 return -1;
00361 }
00362
00363 void ast_modem_trim(char *s)
00364 {
00365 int x;
00366 x = strlen(s) - 1;
00367 while(x >= 0) {
00368 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' '))
00369 break;
00370 s[x] = '\0';
00371 x--;
00372 }
00373 }
00374
00375 static int modem_setup(struct ast_modem_pvt *p, int baudrate)
00376 {
00377
00378
00379
00380 char identity[256];
00381 char *ident = NULL;
00382 char etx[2] = { 0x10, '!' };
00383 if (option_debug)
00384 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
00385 if (ast_modem_send(p, etx, 2)) {
00386 ast_log(LOG_WARNING, "Failed to send ETX?\n");
00387 return -1;
00388 }
00389 if (ast_modem_send(p, "\r\n", 2)) {
00390 ast_log(LOG_WARNING, "Failed to send enter?\n");
00391 return -1;
00392 }
00393 usleep(10000);
00394
00395 while(!ast_modem_read_response(p, 0));
00396 if (ast_modem_send(p, "ATZ", 0)) {
00397 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00398 return -1;
00399 }
00400 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00401 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response);
00402 return -1;
00403 }
00404 if (ast_modem_send(p, p->initstr, 0)) {
00405 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00406 return -1;
00407 }
00408 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00409 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response);
00410 return -1;
00411 }
00412 if (ast_modem_send(p, "ATI3", 0)) {
00413 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00414 return -1;
00415 }
00416 if (ast_modem_read_response(p, ECHO_TIMEOUT)) {
00417 ast_log(LOG_WARNING, "Modem did not provide identification\n");
00418 return -1;
00419 }
00420 strncpy(identity, p->response, sizeof(identity)-1);
00421 ast_modem_trim(identity);
00422 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00423 ast_log(LOG_WARNING, "Modem did not provide identification\n");
00424 return -1;
00425 }
00426 if (!strcasecmp(mtype, "autodetect")) {
00427 p->mc = find_capability(identity);
00428 if (!p->mc) {
00429 ast_log(LOG_WARNING, "Unable to autodetect modem. You'll need to specify a driver in modem.conf. Please report modem identification (%s) and which driver works to markster@linux-support.net.\n", identity);
00430 return -1;
00431 }
00432 } else {
00433 p->mc = find_driver(mtype);
00434 if (!p->mc) {
00435 ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype);
00436 return -1;
00437 }
00438 }
00439 if (p->mc->init) {
00440 if (p->mc->init(p)) {
00441 ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name);
00442 p->mc->decusecnt();
00443 return -1;
00444 }
00445 }
00446 if (option_verbose > 2) {
00447 ast_verbose(VERBOSE_PREFIX_3 "Configured modem %s with driver %s (%s)\n", p->dev, p->mc->name, p->mc->identify ? (ident = p->mc->identify(p)) : "No identification");
00448 }
00449 if (ident)
00450 free(ident);
00451 return 0;
00452 }
00453
00454 static int modem_hangup(struct ast_channel *ast)
00455 {
00456 struct ast_modem_pvt *p;
00457 if (option_debug)
00458 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
00459 p = ast->tech_pvt;
00460
00461 if (p->mc->hangup)
00462 p->mc->hangup(p);
00463
00464 if (p->mc->init)
00465 p->mc->init(p);
00466 ast_setstate(ast, AST_STATE_DOWN);
00467 memset(p->cid_num, 0, sizeof(p->cid_num));
00468 memset(p->cid_name, 0, sizeof(p->cid_name));
00469 memset(p->dnid, 0, sizeof(p->dnid));
00470 ((struct ast_modem_pvt *)(ast->tech_pvt))->owner = NULL;
00471 ast_mutex_lock(&usecnt_lock);
00472 usecnt--;
00473 if (usecnt < 0)
00474 ast_log(LOG_WARNING, "Usecnt < 0???\n");
00475 ast_mutex_unlock(&usecnt_lock);
00476 ast_update_use_count();
00477 if (option_verbose > 2)
00478 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
00479 ast->tech_pvt = NULL;
00480 ast_setstate(ast, AST_STATE_DOWN);
00481 restart_monitor();
00482 return 0;
00483 }
00484
00485 static int modem_answer(struct ast_channel *ast)
00486 {
00487 struct ast_modem_pvt *p;
00488 int res=0;
00489 if (option_debug)
00490 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
00491 p = ast->tech_pvt;
00492 if (p->mc->answer) {
00493 res = p->mc->answer(p);
00494 }
00495 if (!res) {
00496 ast->rings = 0;
00497 ast_setstate(ast, AST_STATE_UP);
00498 }
00499 return res;
00500 }
00501
00502 #if 0
00503 static char modem_2digit(char c)
00504 {
00505 if (c == 12)
00506 return '#';
00507 else if (c == 11)
00508 return '*';
00509 else if ((c < 10) && (c >= 0))
00510 return '0' + c - 1;
00511 else
00512 return '?';
00513 }
00514 #endif
00515 static struct ast_frame *modem_read(struct ast_channel *ast)
00516 {
00517 struct ast_modem_pvt *p = ast->tech_pvt;
00518 struct ast_frame *fr=NULL;
00519 if (p->mc->read)
00520 fr = p->mc->read(p);
00521 return fr;
00522 }
00523
00524 static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
00525 {
00526 int res=0;
00527 long flags;
00528 struct ast_modem_pvt *p = ast->tech_pvt;
00529
00530
00531
00532
00533 if (ast->_state != AST_STATE_UP)
00534 return 0;
00535
00536
00537 flags = fcntl(ast->fds[0], F_GETFL);
00538 fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK);
00539
00540 if (p->mc->write)
00541 res = p->mc->write(p, frame);
00542
00543
00544 fcntl(ast->fds[0], F_SETFL, flags);
00545 return res;
00546 }
00547
00548 static int modem_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00549 {
00550 struct ast_modem_pvt *p = newchan->tech_pvt;
00551 ast_log(LOG_WARNING, "fixup called\n");
00552 if (p->owner!=oldchan) {
00553 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n",oldchan,p->owner);
00554 return -1;
00555 }
00556 p->owner = newchan;
00557 return 0;
00558 }
00559
00560 struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
00561 {
00562 struct ast_channel *tmp;
00563 tmp = ast_channel_alloc(1);
00564 if (tmp) {
00565 tmp->tech = &modem_tech;
00566 snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
00567 tmp->type = type;
00568 tmp->fds[0] = i->fd;
00569 tmp->nativeformats = i->mc->formats;
00570 ast_setstate(tmp, state);
00571 if (state == AST_STATE_RING)
00572 tmp->rings = 1;
00573 tmp->tech_pvt = i;
00574 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
00575
00576 if (!ast_strlen_zero(i->cid_num)) {
00577 tmp->cid.cid_num = strdup(i->cid_num);
00578 tmp->cid.cid_ani = strdup(i->cid_num);
00579 }
00580 if (!ast_strlen_zero(i->cid_name))
00581 tmp->cid.cid_name = strdup(i->cid_name);
00582
00583 if (!ast_strlen_zero(i->language))
00584 strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
00585 if (!ast_strlen_zero(i->dnid))
00586 strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
00587 i->owner = tmp;
00588 ast_mutex_lock(&usecnt_lock);
00589 usecnt++;
00590 ast_mutex_unlock(&usecnt_lock);
00591 ast_update_use_count();
00592 if (state != AST_STATE_DOWN) {
00593 if (ast_pbx_start(tmp)) {
00594 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00595 ast_hangup(tmp);
00596 tmp = NULL;
00597 }
00598 }
00599 } else
00600 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00601 return tmp;
00602 }
00603
00604 static void modem_mini_packet(struct ast_modem_pvt *i)
00605 {
00606 struct ast_frame *fr;
00607 fr = i->mc->read(i);
00608 if (!fr) return;
00609 if (fr->frametype == AST_FRAME_CONTROL) {
00610 if (fr->subclass == AST_CONTROL_RING) {
00611 ast_modem_new(i, AST_STATE_RING);
00612 }
00613 }
00614 }
00615
00616 static void *do_monitor(void *data)
00617 {
00618 fd_set rfds, efds;
00619 int n, res;
00620 struct ast_modem_pvt *i;
00621
00622
00623
00624 #if 0
00625 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
00626 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
00627 return NULL;
00628 }
00629 #endif
00630 for(;;) {
00631
00632
00633 if (ast_mutex_lock(&monlock)) {
00634 ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
00635 return NULL;
00636 }
00637
00638 if (ast_mutex_lock(&iflock)) {
00639 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
00640 ast_mutex_unlock(&monlock);
00641 return NULL;
00642 }
00643
00644
00645 n = -1;
00646 FD_ZERO(&rfds);
00647 FD_ZERO(&efds);
00648 i = iflist;
00649 while(i) {
00650 if (FD_ISSET(i->fd, &rfds))
00651 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
00652 if (!i->owner) {
00653
00654 FD_SET(i->fd, &rfds);
00655 FD_SET(i->fd, &efds);
00656 if (i->fd > n)
00657 n = i->fd;
00658 }
00659
00660 i = i->next;
00661 }
00662
00663 ast_mutex_unlock(&iflock);
00664
00665
00666 ast_mutex_unlock(&monlock);
00667 #if 0
00668 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
00669 #endif
00670
00671 pthread_testcancel();
00672 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
00673 pthread_testcancel();
00674
00675 if (res < 1) {
00676 if ((errno != EINTR) && (errno != EAGAIN))
00677 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
00678 continue;
00679 }
00680
00681
00682 if (ast_mutex_lock(&iflock)) {
00683 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
00684 continue;
00685 }
00686 i = iflist;
00687 while(i) {
00688 if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
00689 if (i->owner) {
00690 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev);
00691 i = i->next;
00692 continue;
00693 }
00694 modem_mini_packet(i);
00695 }
00696 i=i->next;
00697 }
00698 ast_mutex_unlock(&iflock);
00699 }
00700
00701 return NULL;
00702
00703 }
00704
00705 static int restart_monitor()
00706 {
00707
00708 if (monitor_thread == AST_PTHREADT_STOP)
00709 return 0;
00710 if (ast_mutex_lock(&monlock)) {
00711 ast_log(LOG_WARNING, "Unable to lock monitor\n");
00712 return -1;
00713 }
00714 if (monitor_thread == pthread_self()) {
00715 ast_mutex_unlock(&monlock);
00716 ast_log(LOG_WARNING, "Cannot kill myself\n");
00717 return -1;
00718 }
00719 if (monitor_thread != AST_PTHREADT_NULL) {
00720 pthread_kill(monitor_thread, SIGURG);
00721 pthread_join(monitor_thread, NULL);
00722 } else {
00723
00724 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
00725 ast_mutex_unlock(&monlock);
00726 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
00727 return -1;
00728 }
00729 }
00730 ast_mutex_unlock(&monlock);
00731 return 0;
00732 }
00733
00734 static void stty(struct ast_modem_pvt *p)
00735 {
00736 struct termios mode;
00737 memset(&mode, 0, sizeof(mode));
00738 if (tcgetattr(p->fd, &mode)) {
00739 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
00740 return;
00741 }
00742 #ifndef SOLARIS
00743 cfmakeraw(&mode);
00744 #else
00745 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
00746 |INLCR|IGNCR|ICRNL|IXON);
00747 mode.c_oflag &= ~OPOST;
00748 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
00749 mode.c_cflag &= ~(CSIZE|PARENB);
00750 mode.c_cflag |= CS8;
00751 #endif
00752
00753 cfsetispeed(&mode, B115200);
00754 cfsetospeed(&mode, B115200);
00755 if (tcsetattr(p->fd, TCSANOW, &mode))
00756 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
00757
00758 }
00759
00760 static struct ast_modem_pvt *mkif(char *iface)
00761 {
00762
00763 struct ast_modem_pvt *tmp;
00764 #if 0
00765 int flags;
00766 #endif
00767
00768 tmp = malloc(sizeof(struct ast_modem_pvt));
00769 if (tmp) {
00770 memset(tmp, 0, sizeof(struct ast_modem_pvt));
00771 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
00772 if (tmp->fd < 0) {
00773 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
00774 free(tmp);
00775 return NULL;
00776 }
00777 strncpy(tmp->language, language, sizeof(tmp->language)-1);
00778 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
00779 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
00780 tmp->dtmfmode = dtmfmode;
00781 tmp->dtmfmodegen = dtmfmodegen;
00782 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn);
00783 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
00784
00785
00786 stty(tmp);
00787 tmp->f = fdopen(tmp->fd, "w+");
00788
00789 setvbuf(tmp->f, NULL, _IONBF,0);
00790 if (tmp->f < 0) {
00791 ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
00792 free(tmp);
00793 return NULL;
00794 }
00795 tmp->owner = NULL;
00796 tmp->ministate = 0;
00797 tmp->stripmsd = stripmsd;
00798 tmp->dialtype = dialtype;
00799 tmp->mode = gmode;
00800 tmp->group = cur_group;
00801 memset(tmp->cid_num, 0, sizeof(tmp->cid_num));
00802 memset(tmp->cid_name, 0, sizeof(tmp->cid_name));
00803 strncpy(tmp->context, context, sizeof(tmp->context)-1);
00804 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
00805 tmp->next = NULL;
00806 tmp->obuflen = 0;
00807
00808 if (modem_setup(tmp, baudrate) < 0) {
00809 ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
00810 free(tmp);
00811 return NULL;
00812 }
00813 }
00814 return tmp;
00815 }
00816
00817 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause)
00818 {
00819 int oldformat;
00820 struct ast_modem_pvt *p;
00821 struct ast_channel *tmp = NULL;
00822 char dev[80];
00823 ast_group_t group = 0;
00824 int groupint;
00825 char *stringp=NULL;
00826 strncpy(dev, (char *)data, sizeof(dev)-1);
00827 stringp=dev;
00828 strsep(&stringp, ":");
00829 oldformat = format;
00830
00831 if (!dep_warning) {
00832 ast_log(LOG_WARNING, "This channel driver is deprecated. Please see the UPGRADE.txt file.\n");
00833 dep_warning = 1;
00834 }
00835
00836 if (dev[0]=='g' && isdigit(dev[1])) {
00837
00838 if (sscanf(dev+1, "%u", &groupint) < 1) {
00839 ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data);
00840 return NULL;
00841 }
00842 group = 1 << groupint;
00843 }
00844
00845
00846 if (ast_mutex_lock(&iflock)) {
00847 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00848 return NULL;
00849 }
00850 p = iflist;
00851 while(p) {
00852 if (group) {
00853
00854
00855 if (p->group & group &&
00856 p->mc->formats & format &&
00857 !p->owner) {
00858
00859
00860 tmp = ast_modem_new(p, AST_STATE_DOWN);
00861 restart_monitor();
00862 break;
00863 }
00864 } else {
00865 if (!strcmp(dev, p->dev + 5)) {
00866 if (p->mc->formats & format) {
00867 if (!p->owner) {
00868 tmp = ast_modem_new(p, AST_STATE_DOWN);
00869 restart_monitor();
00870 break;
00871 } else
00872 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
00873 } else
00874 ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev);
00875 break;
00876 }
00877 }
00878 p = p->next;
00879 }
00880 if (!p)
00881 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
00882
00883 ast_mutex_unlock(&iflock);
00884 return tmp;
00885 }
00886
00887 static ast_group_t get_group(char *s)
00888 {
00889 char *piece;
00890 int start, finish,x;
00891 ast_group_t group = 0;
00892 char *copy = ast_strdupa(s);
00893 char *stringp=NULL;
00894 if (!copy) {
00895 ast_log(LOG_ERROR, "Out of memory\n");
00896 return 0;
00897 }
00898 stringp=copy;
00899 piece = strsep(&stringp, ",");
00900 while(piece) {
00901 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
00902
00903 } else if (sscanf(piece, "%d", &start)) {
00904
00905 finish = start;
00906 } else {
00907 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece);
00908 return 0;
00909 }
00910 piece = strsep(&stringp, ",");
00911
00912 for (x=start;x<=finish;x++) {
00913 if ((x > 63) || (x < 0)) {
00914 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x);
00915 break;
00916 }
00917 group |= (1 << x);
00918 }
00919 }
00920 return group;
00921 }
00922
00923 static int __unload_module(void)
00924 {
00925 struct ast_modem_pvt *p, *pl;
00926
00927 ast_channel_unregister(&modem_tech);
00928 if (!ast_mutex_lock(&iflock)) {
00929
00930 p = iflist;
00931 while(p) {
00932 if (p->owner)
00933 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
00934 p = p->next;
00935 }
00936 iflist = NULL;
00937 ast_mutex_unlock(&iflock);
00938 } else {
00939 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00940 return -1;
00941 }
00942 if (!ast_mutex_lock(&monlock)) {
00943 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) {
00944 pthread_cancel(monitor_thread);
00945 pthread_join(monitor_thread, NULL);
00946 }
00947 monitor_thread = AST_PTHREADT_STOP;
00948 ast_mutex_unlock(&monlock);
00949 } else {
00950 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00951 return -1;
00952 }
00953
00954 if (!ast_mutex_lock(&iflock)) {
00955
00956 p = iflist;
00957 while(p) {
00958
00959 if (p->fd > -1)
00960 close(p->fd);
00961 pl = p;
00962 p = p->next;
00963
00964 free(pl);
00965 }
00966 iflist = NULL;
00967 ast_mutex_unlock(&iflock);
00968 } else {
00969 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00970 return -1;
00971 }
00972
00973 return 0;
00974 }
00975
00976 int unload_module()
00977 {
00978 return __unload_module();
00979 }
00980
00981 int load_module()
00982 {
00983 struct ast_config *cfg;
00984 struct ast_variable *v;
00985 struct ast_modem_pvt *tmp;
00986 char driver[80];
00987 cfg = ast_config_load(config);
00988
00989
00990 if (!cfg) {
00991 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
00992 return -1;
00993 }
00994 if (ast_mutex_lock(&iflock)) {
00995
00996 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00997 return -1;
00998 }
00999 v = ast_variable_browse(cfg, "interfaces");
01000 while(v) {
01001
01002 if (!strcasecmp(v->name, "device")) {
01003 tmp = mkif(v->value);
01004 if (tmp) {
01005 tmp->next = iflist;
01006 iflist = tmp;
01007
01008 } else {
01009 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01010 ast_config_destroy(cfg);
01011 ast_mutex_unlock(&iflock);
01012 __unload_module();
01013 return -1;
01014 }
01015 } else if (!strcasecmp(v->name, "driver")) {
01016 snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
01017 if (option_verbose > 1)
01018 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
01019
01020 if (ast_load_resource(driver)) {
01021 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
01022 ast_config_destroy(cfg);
01023 ast_mutex_unlock(&iflock);
01024 __unload_module();
01025 return -1;
01026 }
01027 } else if (!strcasecmp(v->name, "mode")) {
01028 if (!strncasecmp(v->value, "ri", 2))
01029 gmode = MODEM_MODE_WAIT_RING;
01030 else if (!strncasecmp(v->value, "im", 2))
01031 gmode = MODEM_MODE_IMMEDIATE;
01032 else if (!strncasecmp(v->value, "an", 2))
01033 gmode = MODEM_MODE_WAIT_ANSWER;
01034 else
01035 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01036 } else if (!strcasecmp(v->name, "stripmsd")) {
01037 stripmsd = atoi(v->value);
01038 } else if (!strcasecmp(v->name, "type")) {
01039 strncpy(mtype, v->value, sizeof(mtype)-1);
01040 } else if (!strcasecmp(v->name, "initstr")) {
01041 strncpy(initstr, v->value, sizeof(initstr)-1);
01042 } else if (!strcasecmp(v->name, "dialtype")) {
01043 dialtype = toupper(v->value[0]);
01044 } else if (!strcasecmp(v->name, "context")) {
01045 strncpy(context, v->value, sizeof(context)-1);
01046 } else if (!strcasecmp(v->name, "msn")) {
01047 strncpy(msn, v->value, sizeof(msn)-1);
01048 } else if (!strcasecmp(v->name, "incomingmsn")) {
01049 strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
01050 } else if (!strcasecmp(v->name, "dtmfmode")) {
01051 char tmp[80];
01052 char *alt;
01053 strncpy(tmp, v->value, sizeof(tmp) - 1);
01054 alt = strchr(tmp, '/');
01055 if (!strcasecmp(tmp, "none"))
01056 dtmfmode=MODEM_DTMF_NONE;
01057 else if (!strcasecmp(tmp, "asterisk"))
01058 dtmfmode = MODEM_DTMF_AST;
01059 else if (!strcasecmp(tmp, "i4l"))
01060 dtmfmode = MODEM_DTMF_I4L;
01061 else {
01062 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value);
01063 dtmfmode = MODEM_DTMF_AST;
01064 }
01065 if (alt) {
01066 if (!strcasecmp(alt, "none"))
01067 dtmfmodegen=MODEM_DTMF_NONE;
01068 else if (!strcasecmp(alt, "asterisk"))
01069 dtmfmodegen = MODEM_DTMF_AST;
01070 else if (!strcasecmp(alt, "i4l"))
01071 dtmfmodegen = MODEM_DTMF_I4L;
01072 else if (!strcasecmp(alt, "both"))
01073 dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST;
01074 else {
01075 ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value);
01076 dtmfmodegen = MODEM_DTMF_AST;
01077 }
01078 } else
01079 dtmfmodegen = dtmfmode;
01080 } else if (!strcasecmp(v->name, "outgoingmsn")) {
01081 strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1);
01082 } else if (!strcasecmp(v->name, "language")) {
01083 strncpy(language, v->value, sizeof(language)-1);
01084 } else if (!strcasecmp(v->name, "group")) {
01085 cur_group = get_group(v->value);
01086 }
01087 v = v->next;
01088 }
01089 ast_mutex_unlock(&iflock);
01090 if (ast_channel_register(&modem_tech)) {
01091 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
01092 ast_config_destroy(cfg);
01093 __unload_module();
01094 return -1;
01095 }
01096 ast_config_destroy(cfg);
01097
01098 restart_monitor();
01099 return 0;
01100 }
01101
01102 int usecount(void)
01103 {
01104 return usecnt;
01105 }
01106
01107 char *description()
01108 {
01109 return (char *) desc;
01110 }
01111
01112 char *key()
01113 {
01114 return ASTERISK_GPL_KEY;
01115 }
01116