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: 9404 $")
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 0
00358 fprintf(stderr, "Modem said: %s", p->response);
00359 #endif
00360 if (!strncasecmp(p->response, result, strlen(result)))
00361 return 0;
00362 } while(timeout > 0);
00363 return -1;
00364 }
00365
00366 void ast_modem_trim(char *s)
00367 {
00368 int x;
00369 x = strlen(s) - 1;
00370 while(x >= 0) {
00371 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' '))
00372 break;
00373 s[x] = '\0';
00374 x--;
00375 }
00376 }
00377
00378 static int modem_setup(struct ast_modem_pvt *p, int baudrate)
00379 {
00380
00381
00382
00383 char identity[256];
00384 char *ident = NULL;
00385 char etx[2] = { 0x10, '!' };
00386 if (option_debug)
00387 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
00388 if (ast_modem_send(p, etx, 2)) {
00389 ast_log(LOG_WARNING, "Failed to send ETX?\n");
00390 return -1;
00391 }
00392 if (ast_modem_send(p, "\r\n", 2)) {
00393 ast_log(LOG_WARNING, "Failed to send enter?\n");
00394 return -1;
00395 }
00396 usleep(10000);
00397
00398 while(!ast_modem_read_response(p, 0));
00399 if (ast_modem_send(p, "ATZ", 0)) {
00400 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00401 return -1;
00402 }
00403 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00404 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response);
00405 return -1;
00406 }
00407 if (ast_modem_send(p, p->initstr, 0)) {
00408 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00409 return -1;
00410 }
00411 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00412 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response);
00413 return -1;
00414 }
00415 if (ast_modem_send(p, "ATI3", 0)) {
00416 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
00417 return -1;
00418 }
00419 if (ast_modem_read_response(p, ECHO_TIMEOUT)) {
00420 ast_log(LOG_WARNING, "Modem did not provide identification\n");
00421 return -1;
00422 }
00423 strncpy(identity, p->response, sizeof(identity)-1);
00424 ast_modem_trim(identity);
00425 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
00426 ast_log(LOG_WARNING, "Modem did not provide identification\n");
00427 return -1;
00428 }
00429 if (!strcasecmp(mtype, "autodetect")) {
00430 p->mc = find_capability(identity);
00431 if (!p->mc) {
00432 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);
00433 return -1;
00434 }
00435 } else {
00436 p->mc = find_driver(mtype);
00437 if (!p->mc) {
00438 ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype);
00439 return -1;
00440 }
00441 }
00442 if (p->mc->init) {
00443 if (p->mc->init(p)) {
00444 ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name);
00445 p->mc->decusecnt();
00446 return -1;
00447 }
00448 }
00449 if (option_verbose > 2) {
00450 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");
00451 }
00452 if (ident)
00453 free(ident);
00454 return 0;
00455 }
00456
00457 static int modem_hangup(struct ast_channel *ast)
00458 {
00459 struct ast_modem_pvt *p;
00460 if (option_debug)
00461 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
00462 p = ast->tech_pvt;
00463
00464 if (p->mc->hangup)
00465 p->mc->hangup(p);
00466
00467 if (p->mc->init)
00468 p->mc->init(p);
00469 ast_setstate(ast, AST_STATE_DOWN);
00470 memset(p->cid_num, 0, sizeof(p->cid_num));
00471 memset(p->cid_name, 0, sizeof(p->cid_name));
00472 memset(p->dnid, 0, sizeof(p->dnid));
00473 ((struct ast_modem_pvt *)(ast->tech_pvt))->owner = NULL;
00474 ast_mutex_lock(&usecnt_lock);
00475 usecnt--;
00476 if (usecnt < 0)
00477 ast_log(LOG_WARNING, "Usecnt < 0???\n");
00478 ast_mutex_unlock(&usecnt_lock);
00479 ast_update_use_count();
00480 if (option_verbose > 2)
00481 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
00482 ast->tech_pvt = NULL;
00483 ast_setstate(ast, AST_STATE_DOWN);
00484 restart_monitor();
00485 return 0;
00486 }
00487
00488 static int modem_answer(struct ast_channel *ast)
00489 {
00490 struct ast_modem_pvt *p;
00491 int res=0;
00492 if (option_debug)
00493 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
00494 p = ast->tech_pvt;
00495 if (p->mc->answer) {
00496 res = p->mc->answer(p);
00497 }
00498 if (!res) {
00499 ast->rings = 0;
00500 ast_setstate(ast, AST_STATE_UP);
00501 }
00502 return res;
00503 }
00504
00505 #if 0
00506 static char modem_2digit(char c)
00507 {
00508 if (c == 12)
00509 return '#';
00510 else if (c == 11)
00511 return '*';
00512 else if ((c < 10) && (c >= 0))
00513 return '0' + c - 1;
00514 else
00515 return '?';
00516 }
00517 #endif
00518 static struct ast_frame *modem_read(struct ast_channel *ast)
00519 {
00520 struct ast_modem_pvt *p = ast->tech_pvt;
00521 struct ast_frame *fr=NULL;
00522 if (p->mc->read)
00523 fr = p->mc->read(p);
00524 return fr;
00525 }
00526
00527 static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
00528 {
00529 int res=0;
00530 long flags;
00531 struct ast_modem_pvt *p = ast->tech_pvt;
00532
00533
00534
00535
00536 if (ast->_state != AST_STATE_UP)
00537 return 0;
00538
00539
00540 flags = fcntl(ast->fds[0], F_GETFL);
00541 fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK);
00542
00543 if (p->mc->write)
00544 res = p->mc->write(p, frame);
00545
00546
00547 fcntl(ast->fds[0], F_SETFL, flags);
00548 return res;
00549 }
00550
00551 static int modem_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00552 {
00553 struct ast_modem_pvt *p = newchan->tech_pvt;
00554 ast_log(LOG_WARNING, "fixup called\n");
00555 if (p->owner!=oldchan) {
00556 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n",oldchan,p->owner);
00557 return -1;
00558 }
00559 p->owner = newchan;
00560 return 0;
00561 }
00562
00563 struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
00564 {
00565 struct ast_channel *tmp;
00566 tmp = ast_channel_alloc(1);
00567 if (tmp) {
00568 tmp->tech = &modem_tech;
00569 snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
00570 tmp->type = type;
00571 tmp->fds[0] = i->fd;
00572 tmp->nativeformats = i->mc->formats;
00573 ast_setstate(tmp, state);
00574 if (state == AST_STATE_RING)
00575 tmp->rings = 1;
00576 tmp->tech_pvt = i;
00577 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
00578
00579 if (!ast_strlen_zero(i->cid_num))
00580 tmp->cid.cid_num = strdup(i->cid_num);
00581 if (!ast_strlen_zero(i->cid_name))
00582 tmp->cid.cid_name = strdup(i->cid_name);
00583
00584 if (!ast_strlen_zero(i->language))
00585 strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
00586 if (!ast_strlen_zero(i->dnid))
00587 strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
00588 i->owner = tmp;
00589 ast_mutex_lock(&usecnt_lock);
00590 usecnt++;
00591 ast_mutex_unlock(&usecnt_lock);
00592 ast_update_use_count();
00593 if (state != AST_STATE_DOWN) {
00594 if (ast_pbx_start(tmp)) {
00595 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00596 ast_hangup(tmp);
00597 tmp = NULL;
00598 }
00599 }
00600 } else
00601 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00602 return tmp;
00603 }
00604
00605 static void modem_mini_packet(struct ast_modem_pvt *i)
00606 {
00607 struct ast_frame *fr;
00608 fr = i->mc->read(i);
00609 if (!fr) return;
00610 if (fr->frametype == AST_FRAME_CONTROL) {
00611 if (fr->subclass == AST_CONTROL_RING) {
00612 ast_modem_new(i, AST_STATE_RING);
00613 }
00614 }
00615 }
00616
00617 static void *do_monitor(void *data)
00618 {
00619 fd_set rfds, efds;
00620 int n, res;
00621 struct ast_modem_pvt *i;
00622
00623
00624
00625 #if 0
00626 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
00627 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
00628 return NULL;
00629 }
00630 #endif
00631 for(;;) {
00632
00633
00634 if (ast_mutex_lock(&monlock)) {
00635 ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
00636 return NULL;
00637 }
00638
00639 if (ast_mutex_lock(&iflock)) {
00640 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
00641 ast_mutex_unlock(&monlock);
00642 return NULL;
00643 }
00644
00645
00646 n = -1;
00647 FD_ZERO(&rfds);
00648 FD_ZERO(&efds);
00649 i = iflist;
00650 while(i) {
00651 if (FD_ISSET(i->fd, &rfds))
00652 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
00653 if (!i->owner) {
00654
00655 FD_SET(i->fd, &rfds);
00656 FD_SET(i->fd, &efds);
00657 if (i->fd > n)
00658 n = i->fd;
00659 }
00660
00661 i = i->next;
00662 }
00663
00664 ast_mutex_unlock(&iflock);
00665
00666
00667 ast_mutex_unlock(&monlock);
00668 #if 0
00669 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
00670 #endif
00671
00672 pthread_testcancel();
00673 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
00674 pthread_testcancel();
00675
00676 if (res < 1) {
00677 if ((errno != EINTR) && (errno != EAGAIN))
00678 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
00679 continue;
00680 }
00681
00682
00683 if (ast_mutex_lock(&iflock)) {
00684 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
00685 continue;
00686 }
00687 i = iflist;
00688 while(i) {
00689 if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
00690 if (i->owner) {
00691 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev);
00692 i = i->next;
00693 continue;
00694 }
00695 modem_mini_packet(i);
00696 }
00697 i=i->next;
00698 }
00699 ast_mutex_unlock(&iflock);
00700 }
00701
00702 return NULL;
00703
00704 }
00705
00706 static int restart_monitor()
00707 {
00708
00709 if (monitor_thread == AST_PTHREADT_STOP)
00710 return 0;
00711 if (ast_mutex_lock(&monlock)) {
00712 ast_log(LOG_WARNING, "Unable to lock monitor\n");
00713 return -1;
00714 }
00715 if (monitor_thread == pthread_self()) {
00716 ast_mutex_unlock(&monlock);
00717 ast_log(LOG_WARNING, "Cannot kill myself\n");
00718 return -1;
00719 }
00720 if (monitor_thread != AST_PTHREADT_NULL) {
00721 pthread_kill(monitor_thread, SIGURG);
00722 pthread_join(monitor_thread, NULL);
00723 } else {
00724
00725 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
00726 ast_mutex_unlock(&monlock);
00727 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
00728 return -1;
00729 }
00730 }
00731 ast_mutex_unlock(&monlock);
00732 return 0;
00733 }
00734
00735 static void stty(struct ast_modem_pvt *p)
00736 {
00737 struct termios mode;
00738 memset(&mode, 0, sizeof(mode));
00739 if (tcgetattr(p->fd, &mode)) {
00740 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
00741 return;
00742 }
00743 #ifndef SOLARIS
00744 cfmakeraw(&mode);
00745 #else
00746 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
00747 |INLCR|IGNCR|ICRNL|IXON);
00748 mode.c_oflag &= ~OPOST;
00749 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
00750 mode.c_cflag &= ~(CSIZE|PARENB);
00751 mode.c_cflag |= CS8;
00752 #endif
00753
00754 cfsetispeed(&mode, B115200);
00755 cfsetospeed(&mode, B115200);
00756 if (tcsetattr(p->fd, TCSANOW, &mode))
00757 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
00758
00759 }
00760
00761 static struct ast_modem_pvt *mkif(char *iface)
00762 {
00763
00764 struct ast_modem_pvt *tmp;
00765 #if 0
00766 int flags;
00767 #endif
00768
00769 tmp = malloc(sizeof(struct ast_modem_pvt));
00770 if (tmp) {
00771 memset(tmp, 0, sizeof(struct ast_modem_pvt));
00772 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
00773 if (tmp->fd < 0) {
00774 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
00775 free(tmp);
00776 return NULL;
00777 }
00778 strncpy(tmp->language, language, sizeof(tmp->language)-1);
00779 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
00780 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
00781 tmp->dtmfmode = dtmfmode;
00782 tmp->dtmfmodegen = dtmfmodegen;
00783 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn);
00784 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
00785
00786
00787 stty(tmp);
00788 tmp->f = fdopen(tmp->fd, "w+");
00789
00790 setvbuf(tmp->f, NULL, _IONBF,0);
00791 if (tmp->f < 0) {
00792 ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
00793 free(tmp);
00794 return NULL;
00795 }
00796 tmp->owner = NULL;
00797 tmp->ministate = 0;
00798 tmp->stripmsd = stripmsd;
00799 tmp->dialtype = dialtype;
00800 tmp->mode = gmode;
00801 tmp->group = cur_group;
00802 memset(tmp->cid_num, 0, sizeof(tmp->cid_num));
00803 memset(tmp->cid_name, 0, sizeof(tmp->cid_name));
00804 strncpy(tmp->context, context, sizeof(tmp->context)-1);
00805 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
00806 tmp->next = NULL;
00807 tmp->obuflen = 0;
00808
00809 if (modem_setup(tmp, baudrate) < 0) {
00810 ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
00811 free(tmp);
00812 return NULL;
00813 }
00814 }
00815 return tmp;
00816 }
00817
00818 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause)
00819 {
00820 int oldformat;
00821 struct ast_modem_pvt *p;
00822 struct ast_channel *tmp = NULL;
00823 char dev[80];
00824 ast_group_t group = 0;
00825 int groupint;
00826 char *stringp=NULL;
00827 strncpy(dev, (char *)data, sizeof(dev)-1);
00828 stringp=dev;
00829 strsep(&stringp, ":");
00830 oldformat = format;
00831
00832 if (!dep_warning) {
00833 ast_log(LOG_WARNING, "This channel driver is deprecated. Please see the UPGRADE.txt file.\n");
00834 dep_warning = 1;
00835 }
00836
00837 if (dev[0]=='g' && isdigit(dev[1])) {
00838
00839 if (sscanf(dev+1, "%u", &groupint) < 1) {
00840 ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data);
00841 return NULL;
00842 }
00843 group = 1 << groupint;
00844 }
00845
00846
00847 if (ast_mutex_lock(&iflock)) {
00848 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00849 return NULL;
00850 }
00851 p = iflist;
00852 while(p) {
00853 if (group) {
00854
00855
00856 if (p->group & group &&
00857 p->mc->formats & format &&
00858 !p->owner) {
00859
00860
00861 tmp = ast_modem_new(p, AST_STATE_DOWN);
00862 restart_monitor();
00863 break;
00864 }
00865 } else {
00866 if (!strcmp(dev, p->dev + 5)) {
00867 if (p->mc->formats & format) {
00868 if (!p->owner) {
00869 tmp = ast_modem_new(p, AST_STATE_DOWN);
00870 restart_monitor();
00871 break;
00872 } else
00873 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
00874 } else
00875 ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev);
00876 break;
00877 }
00878 }
00879 p = p->next;
00880 }
00881 if (!p)
00882 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
00883
00884 ast_mutex_unlock(&iflock);
00885 return tmp;
00886 }
00887
00888 static ast_group_t get_group(char *s)
00889 {
00890 char *piece;
00891 int start, finish,x;
00892 ast_group_t group = 0;
00893 char *copy = ast_strdupa(s);
00894 char *stringp=NULL;
00895 if (!copy) {
00896 ast_log(LOG_ERROR, "Out of memory\n");
00897 return 0;
00898 }
00899 stringp=copy;
00900 piece = strsep(&stringp, ",");
00901 while(piece) {
00902 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
00903
00904 } else if (sscanf(piece, "%d", &start)) {
00905
00906 finish = start;
00907 } else {
00908 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece);
00909 return 0;
00910 }
00911 piece = strsep(&stringp, ",");
00912
00913 for (x=start;x<=finish;x++) {
00914 if ((x > 63) || (x < 0)) {
00915 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x);
00916 break;
00917 }
00918 group |= (1 << x);
00919 }
00920 }
00921 return group;
00922 }
00923
00924 static int __unload_module(void)
00925 {
00926 struct ast_modem_pvt *p, *pl;
00927
00928 ast_channel_unregister(&modem_tech);
00929 if (!ast_mutex_lock(&iflock)) {
00930
00931 p = iflist;
00932 while(p) {
00933 if (p->owner)
00934 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
00935 p = p->next;
00936 }
00937 iflist = NULL;
00938 ast_mutex_unlock(&iflock);
00939 } else {
00940 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00941 return -1;
00942 }
00943 if (!ast_mutex_lock(&monlock)) {
00944 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) {
00945 pthread_cancel(monitor_thread);
00946 pthread_join(monitor_thread, NULL);
00947 }
00948 monitor_thread = AST_PTHREADT_STOP;
00949 ast_mutex_unlock(&monlock);
00950 } else {
00951 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00952 return -1;
00953 }
00954
00955 if (!ast_mutex_lock(&iflock)) {
00956
00957 p = iflist;
00958 while(p) {
00959
00960 if (p->fd > -1)
00961 close(p->fd);
00962 pl = p;
00963 p = p->next;
00964
00965 free(pl);
00966 }
00967 iflist = NULL;
00968 ast_mutex_unlock(&iflock);
00969 } else {
00970 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00971 return -1;
00972 }
00973
00974 return 0;
00975 }
00976
00977 int unload_module()
00978 {
00979 return __unload_module();
00980 }
00981
00982 int load_module()
00983 {
00984 struct ast_config *cfg;
00985 struct ast_variable *v;
00986 struct ast_modem_pvt *tmp;
00987 char driver[80];
00988 cfg = ast_config_load(config);
00989
00990
00991 if (!cfg) {
00992 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
00993 return -1;
00994 }
00995 if (ast_mutex_lock(&iflock)) {
00996
00997 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00998 return -1;
00999 }
01000 v = ast_variable_browse(cfg, "interfaces");
01001 while(v) {
01002
01003 if (!strcasecmp(v->name, "device")) {
01004 tmp = mkif(v->value);
01005 if (tmp) {
01006 tmp->next = iflist;
01007 iflist = tmp;
01008
01009 } else {
01010 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01011 ast_config_destroy(cfg);
01012 ast_mutex_unlock(&iflock);
01013 __unload_module();
01014 return -1;
01015 }
01016 } else if (!strcasecmp(v->name, "driver")) {
01017 snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
01018 if (option_verbose > 1)
01019 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
01020
01021 if (ast_load_resource(driver)) {
01022 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
01023 ast_config_destroy(cfg);
01024 ast_mutex_unlock(&iflock);
01025 __unload_module();
01026 return -1;
01027 }
01028 } else if (!strcasecmp(v->name, "mode")) {
01029 if (!strncasecmp(v->value, "ri", 2))
01030 gmode = MODEM_MODE_WAIT_RING;
01031 else if (!strncasecmp(v->value, "im", 2))
01032 gmode = MODEM_MODE_IMMEDIATE;
01033 else if (!strncasecmp(v->value, "an", 2))
01034 gmode = MODEM_MODE_WAIT_ANSWER;
01035 else
01036 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01037 } else if (!strcasecmp(v->name, "stripmsd")) {
01038 stripmsd = atoi(v->value);
01039 } else if (!strcasecmp(v->name, "type")) {
01040 strncpy(mtype, v->value, sizeof(mtype)-1);
01041 } else if (!strcasecmp(v->name, "initstr")) {
01042 strncpy(initstr, v->value, sizeof(initstr)-1);
01043 } else if (!strcasecmp(v->name, "dialtype")) {
01044 dialtype = toupper(v->value[0]);
01045 } else if (!strcasecmp(v->name, "context")) {
01046 strncpy(context, v->value, sizeof(context)-1);
01047 } else if (!strcasecmp(v->name, "msn")) {
01048 strncpy(msn, v->value, sizeof(msn)-1);
01049 } else if (!strcasecmp(v->name, "incomingmsn")) {
01050 strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
01051 } else if (!strcasecmp(v->name, "dtmfmode")) {
01052 char tmp[80];
01053 char *alt;
01054 strncpy(tmp, v->value, sizeof(tmp) - 1);
01055 alt = strchr(tmp, '/');
01056 if (!strcasecmp(tmp, "none"))
01057 dtmfmode=MODEM_DTMF_NONE;
01058 else if (!strcasecmp(tmp, "asterisk"))
01059 dtmfmode = MODEM_DTMF_AST;
01060 else if (!strcasecmp(tmp, "i4l"))
01061 dtmfmode = MODEM_DTMF_I4L;
01062 else {
01063 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value);
01064 dtmfmode = MODEM_DTMF_AST;
01065 }
01066 if (alt) {
01067 if (!strcasecmp(alt, "none"))
01068 dtmfmodegen=MODEM_DTMF_NONE;
01069 else if (!strcasecmp(alt, "asterisk"))
01070 dtmfmodegen = MODEM_DTMF_AST;
01071 else if (!strcasecmp(alt, "i4l"))
01072 dtmfmodegen = MODEM_DTMF_I4L;
01073 else if (!strcasecmp(alt, "both"))
01074 dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST;
01075 else {
01076 ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value);
01077 dtmfmodegen = MODEM_DTMF_AST;
01078 }
01079 } else
01080 dtmfmodegen = dtmfmode;
01081 } else if (!strcasecmp(v->name, "outgoingmsn")) {
01082 strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1);
01083 } else if (!strcasecmp(v->name, "language")) {
01084 strncpy(language, v->value, sizeof(language)-1);
01085 } else if (!strcasecmp(v->name, "group")) {
01086 cur_group = get_group(v->value);
01087 }
01088 v = v->next;
01089 }
01090 ast_mutex_unlock(&iflock);
01091 if (ast_channel_register(&modem_tech)) {
01092 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
01093 ast_config_destroy(cfg);
01094 __unload_module();
01095 return -1;
01096 }
01097 ast_config_destroy(cfg);
01098
01099 restart_monitor();
01100 return 0;
01101 }
01102
01103 int usecount(void)
01104 {
01105 return usecnt;
01106 }
01107
01108 char *description()
01109 {
01110 return (char *) desc;
01111 }
01112
01113 char *key()
01114 {
01115 return ASTERISK_GPL_KEY;
01116 }
01117