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: 37419 $")
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 ast_set_callerid(tmp, i->cid_num, i->cid_name, i->cid_num);
00577
00578 if (!ast_strlen_zero(i->language))
00579 strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
00580 if (!ast_strlen_zero(i->dnid))
00581 strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
00582 i->owner = tmp;
00583 ast_mutex_lock(&usecnt_lock);
00584 usecnt++;
00585 ast_mutex_unlock(&usecnt_lock);
00586 ast_update_use_count();
00587 if (state != AST_STATE_DOWN) {
00588 if (ast_pbx_start(tmp)) {
00589 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00590 ast_hangup(tmp);
00591 tmp = NULL;
00592 }
00593 }
00594 } else
00595 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00596 return tmp;
00597 }
00598
00599 static void modem_mini_packet(struct ast_modem_pvt *i)
00600 {
00601 struct ast_frame *fr;
00602 fr = i->mc->read(i);
00603 if (!fr) return;
00604 if (fr->frametype == AST_FRAME_CONTROL) {
00605 if (fr->subclass == AST_CONTROL_RING) {
00606 ast_modem_new(i, AST_STATE_RING);
00607 }
00608 }
00609 }
00610
00611 static void *do_monitor(void *data)
00612 {
00613 fd_set rfds, efds;
00614 int n, res;
00615 struct ast_modem_pvt *i;
00616
00617
00618
00619 #if 0
00620 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
00621 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
00622 return NULL;
00623 }
00624 #endif
00625 for(;;) {
00626
00627
00628 if (ast_mutex_lock(&monlock)) {
00629 ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
00630 return NULL;
00631 }
00632
00633 if (ast_mutex_lock(&iflock)) {
00634 ast_log(LOG_ERROR, "Unable to grab interface lock\n");
00635 ast_mutex_unlock(&monlock);
00636 return NULL;
00637 }
00638
00639
00640 n = -1;
00641 FD_ZERO(&rfds);
00642 FD_ZERO(&efds);
00643 i = iflist;
00644 while(i) {
00645 if (FD_ISSET(i->fd, &rfds))
00646 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
00647 if (!i->owner) {
00648
00649 FD_SET(i->fd, &rfds);
00650 FD_SET(i->fd, &efds);
00651 if (i->fd > n)
00652 n = i->fd;
00653 }
00654
00655 i = i->next;
00656 }
00657
00658 ast_mutex_unlock(&iflock);
00659
00660
00661 ast_mutex_unlock(&monlock);
00662 #if 0
00663 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
00664 #endif
00665
00666 pthread_testcancel();
00667 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
00668 pthread_testcancel();
00669
00670 if (res < 1) {
00671 if ((errno != EINTR) && (errno != EAGAIN))
00672 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
00673 continue;
00674 }
00675
00676
00677 if (ast_mutex_lock(&iflock)) {
00678 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
00679 continue;
00680 }
00681 i = iflist;
00682 while(i) {
00683 if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
00684 if (i->owner) {
00685 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev);
00686 i = i->next;
00687 continue;
00688 }
00689 modem_mini_packet(i);
00690 }
00691 i=i->next;
00692 }
00693 ast_mutex_unlock(&iflock);
00694 }
00695
00696 return NULL;
00697
00698 }
00699
00700 static int restart_monitor()
00701 {
00702
00703 if (monitor_thread == AST_PTHREADT_STOP)
00704 return 0;
00705 if (ast_mutex_lock(&monlock)) {
00706 ast_log(LOG_WARNING, "Unable to lock monitor\n");
00707 return -1;
00708 }
00709 if (monitor_thread == pthread_self()) {
00710 ast_mutex_unlock(&monlock);
00711 ast_log(LOG_WARNING, "Cannot kill myself\n");
00712 return -1;
00713 }
00714 if (monitor_thread != AST_PTHREADT_NULL) {
00715 pthread_kill(monitor_thread, SIGURG);
00716 pthread_join(monitor_thread, NULL);
00717 } else {
00718
00719 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
00720 ast_mutex_unlock(&monlock);
00721 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
00722 return -1;
00723 }
00724 }
00725 ast_mutex_unlock(&monlock);
00726 return 0;
00727 }
00728
00729 static void stty(struct ast_modem_pvt *p)
00730 {
00731 struct termios mode;
00732 memset(&mode, 0, sizeof(mode));
00733 if (tcgetattr(p->fd, &mode)) {
00734 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
00735 return;
00736 }
00737 #ifndef SOLARIS
00738 cfmakeraw(&mode);
00739 #else
00740 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
00741 |INLCR|IGNCR|ICRNL|IXON);
00742 mode.c_oflag &= ~OPOST;
00743 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
00744 mode.c_cflag &= ~(CSIZE|PARENB);
00745 mode.c_cflag |= CS8;
00746 #endif
00747
00748 cfsetispeed(&mode, B115200);
00749 cfsetospeed(&mode, B115200);
00750 if (tcsetattr(p->fd, TCSANOW, &mode))
00751 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
00752
00753 }
00754
00755 static struct ast_modem_pvt *mkif(char *iface)
00756 {
00757
00758 struct ast_modem_pvt *tmp;
00759 #if 0
00760 int flags;
00761 #endif
00762
00763 tmp = malloc(sizeof(struct ast_modem_pvt));
00764 if (tmp) {
00765 memset(tmp, 0, sizeof(struct ast_modem_pvt));
00766 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
00767 if (tmp->fd < 0) {
00768 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
00769 free(tmp);
00770 return NULL;
00771 }
00772 strncpy(tmp->language, language, sizeof(tmp->language)-1);
00773 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
00774 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
00775 tmp->dtmfmode = dtmfmode;
00776 tmp->dtmfmodegen = dtmfmodegen;
00777 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn);
00778 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
00779
00780
00781 stty(tmp);
00782 tmp->f = fdopen(tmp->fd, "w+");
00783
00784 setvbuf(tmp->f, NULL, _IONBF,0);
00785 if (tmp->f < 0) {
00786 ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
00787 free(tmp);
00788 return NULL;
00789 }
00790 tmp->owner = NULL;
00791 tmp->ministate = 0;
00792 tmp->stripmsd = stripmsd;
00793 tmp->dialtype = dialtype;
00794 tmp->mode = gmode;
00795 tmp->group = cur_group;
00796 memset(tmp->cid_num, 0, sizeof(tmp->cid_num));
00797 memset(tmp->cid_name, 0, sizeof(tmp->cid_name));
00798 strncpy(tmp->context, context, sizeof(tmp->context)-1);
00799 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
00800 tmp->next = NULL;
00801 tmp->obuflen = 0;
00802
00803 if (modem_setup(tmp, baudrate) < 0) {
00804 ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
00805 free(tmp);
00806 return NULL;
00807 }
00808 }
00809 return tmp;
00810 }
00811
00812 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause)
00813 {
00814 int oldformat;
00815 struct ast_modem_pvt *p;
00816 struct ast_channel *tmp = NULL;
00817 char dev[80];
00818 ast_group_t group = 0;
00819 int groupint;
00820 char *stringp=NULL;
00821 strncpy(dev, (char *)data, sizeof(dev)-1);
00822 stringp=dev;
00823 strsep(&stringp, ":");
00824 oldformat = format;
00825
00826 if (!dep_warning) {
00827 ast_log(LOG_WARNING, "This channel driver is deprecated. Please see the UPGRADE.txt file.\n");
00828 dep_warning = 1;
00829 }
00830
00831 if (dev[0]=='g' && isdigit(dev[1])) {
00832
00833 if (sscanf(dev+1, "%u", &groupint) < 1) {
00834 ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data);
00835 return NULL;
00836 }
00837 group = 1 << groupint;
00838 }
00839
00840
00841 if (ast_mutex_lock(&iflock)) {
00842 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00843 return NULL;
00844 }
00845 p = iflist;
00846 while(p) {
00847 if (group) {
00848
00849
00850 if (p->group & group &&
00851 p->mc->formats & format &&
00852 !p->owner) {
00853
00854
00855 tmp = ast_modem_new(p, AST_STATE_DOWN);
00856 restart_monitor();
00857 break;
00858 }
00859 } else {
00860 if (!strcmp(dev, p->dev + 5)) {
00861 if (p->mc->formats & format) {
00862 if (!p->owner) {
00863 tmp = ast_modem_new(p, AST_STATE_DOWN);
00864 restart_monitor();
00865 break;
00866 } else
00867 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
00868 } else
00869 ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev);
00870 break;
00871 }
00872 }
00873 p = p->next;
00874 }
00875 if (!p)
00876 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
00877
00878 ast_mutex_unlock(&iflock);
00879 return tmp;
00880 }
00881
00882 static ast_group_t get_group(char *s)
00883 {
00884 char *piece;
00885 int start, finish,x;
00886 ast_group_t group = 0;
00887 char *copy = ast_strdupa(s);
00888 char *stringp=NULL;
00889 if (!copy) {
00890 ast_log(LOG_ERROR, "Out of memory\n");
00891 return 0;
00892 }
00893 stringp=copy;
00894 piece = strsep(&stringp, ",");
00895 while(piece) {
00896 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
00897
00898 } else if (sscanf(piece, "%d", &start)) {
00899
00900 finish = start;
00901 } else {
00902 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece);
00903 return 0;
00904 }
00905 piece = strsep(&stringp, ",");
00906
00907 for (x=start;x<=finish;x++) {
00908 if ((x > 63) || (x < 0)) {
00909 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x);
00910 break;
00911 }
00912 group |= (1 << x);
00913 }
00914 }
00915 return group;
00916 }
00917
00918 static int __unload_module(void)
00919 {
00920 struct ast_modem_pvt *p, *pl;
00921
00922 ast_channel_unregister(&modem_tech);
00923 if (!ast_mutex_lock(&iflock)) {
00924
00925 p = iflist;
00926 while(p) {
00927 if (p->owner)
00928 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
00929 p = p->next;
00930 }
00931 iflist = NULL;
00932 ast_mutex_unlock(&iflock);
00933 } else {
00934 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00935 return -1;
00936 }
00937 if (!ast_mutex_lock(&monlock)) {
00938 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) {
00939 pthread_cancel(monitor_thread);
00940 pthread_join(monitor_thread, NULL);
00941 }
00942 monitor_thread = AST_PTHREADT_STOP;
00943 ast_mutex_unlock(&monlock);
00944 } else {
00945 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00946 return -1;
00947 }
00948
00949 if (!ast_mutex_lock(&iflock)) {
00950
00951 p = iflist;
00952 while(p) {
00953
00954 if (p->fd > -1)
00955 close(p->fd);
00956 pl = p;
00957 p = p->next;
00958
00959 free(pl);
00960 }
00961 iflist = NULL;
00962 ast_mutex_unlock(&iflock);
00963 } else {
00964 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00965 return -1;
00966 }
00967
00968 return 0;
00969 }
00970
00971 int unload_module()
00972 {
00973 return __unload_module();
00974 }
00975
00976 int load_module()
00977 {
00978 struct ast_config *cfg;
00979 struct ast_variable *v;
00980 struct ast_modem_pvt *tmp;
00981 char driver[80];
00982 cfg = ast_config_load(config);
00983
00984
00985 if (!cfg) {
00986 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
00987 return -1;
00988 }
00989 if (ast_mutex_lock(&iflock)) {
00990
00991 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
00992 return -1;
00993 }
00994 v = ast_variable_browse(cfg, "interfaces");
00995 while(v) {
00996
00997 if (!strcasecmp(v->name, "device")) {
00998 tmp = mkif(v->value);
00999 if (tmp) {
01000 tmp->next = iflist;
01001 iflist = tmp;
01002
01003 } else {
01004 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
01005 ast_config_destroy(cfg);
01006 ast_mutex_unlock(&iflock);
01007 __unload_module();
01008 return -1;
01009 }
01010 } else if (!strcasecmp(v->name, "driver")) {
01011 snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
01012 if (option_verbose > 1)
01013 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
01014
01015 if (ast_load_resource(driver)) {
01016 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
01017 ast_config_destroy(cfg);
01018 ast_mutex_unlock(&iflock);
01019 __unload_module();
01020 return -1;
01021 }
01022 } else if (!strcasecmp(v->name, "mode")) {
01023 if (!strncasecmp(v->value, "ri", 2))
01024 gmode = MODEM_MODE_WAIT_RING;
01025 else if (!strncasecmp(v->value, "im", 2))
01026 gmode = MODEM_MODE_IMMEDIATE;
01027 else if (!strncasecmp(v->value, "an", 2))
01028 gmode = MODEM_MODE_WAIT_ANSWER;
01029 else
01030 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
01031 } else if (!strcasecmp(v->name, "stripmsd")) {
01032 stripmsd = atoi(v->value);
01033 } else if (!strcasecmp(v->name, "type")) {
01034 strncpy(mtype, v->value, sizeof(mtype)-1);
01035 } else if (!strcasecmp(v->name, "initstr")) {
01036 strncpy(initstr, v->value, sizeof(initstr)-1);
01037 } else if (!strcasecmp(v->name, "dialtype")) {
01038 dialtype = toupper(v->value[0]);
01039 } else if (!strcasecmp(v->name, "context")) {
01040 strncpy(context, v->value, sizeof(context)-1);
01041 } else if (!strcasecmp(v->name, "msn")) {
01042 strncpy(msn, v->value, sizeof(msn)-1);
01043 } else if (!strcasecmp(v->name, "incomingmsn")) {
01044 strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
01045 } else if (!strcasecmp(v->name, "dtmfmode")) {
01046 char tmp[80];
01047 char *alt;
01048 strncpy(tmp, v->value, sizeof(tmp) - 1);
01049 alt = strchr(tmp, '/');
01050 if (!strcasecmp(tmp, "none"))
01051 dtmfmode=MODEM_DTMF_NONE;
01052 else if (!strcasecmp(tmp, "asterisk"))
01053 dtmfmode = MODEM_DTMF_AST;
01054 else if (!strcasecmp(tmp, "i4l"))
01055 dtmfmode = MODEM_DTMF_I4L;
01056 else {
01057 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value);
01058 dtmfmode = MODEM_DTMF_AST;
01059 }
01060 if (alt) {
01061 if (!strcasecmp(alt, "none"))
01062 dtmfmodegen=MODEM_DTMF_NONE;
01063 else if (!strcasecmp(alt, "asterisk"))
01064 dtmfmodegen = MODEM_DTMF_AST;
01065 else if (!strcasecmp(alt, "i4l"))
01066 dtmfmodegen = MODEM_DTMF_I4L;
01067 else if (!strcasecmp(alt, "both"))
01068 dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST;
01069 else {
01070 ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value);
01071 dtmfmodegen = MODEM_DTMF_AST;
01072 }
01073 } else
01074 dtmfmodegen = dtmfmode;
01075 } else if (!strcasecmp(v->name, "outgoingmsn")) {
01076 strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1);
01077 } else if (!strcasecmp(v->name, "language")) {
01078 strncpy(language, v->value, sizeof(language)-1);
01079 } else if (!strcasecmp(v->name, "group")) {
01080 cur_group = get_group(v->value);
01081 }
01082 v = v->next;
01083 }
01084 ast_mutex_unlock(&iflock);
01085 if (ast_channel_register(&modem_tech)) {
01086 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
01087 ast_config_destroy(cfg);
01088 __unload_module();
01089 return -1;
01090 }
01091 ast_config_destroy(cfg);
01092
01093 restart_monitor();
01094 return 0;
01095 }
01096
01097 int usecount(void)
01098 {
01099 return usecnt;
01100 }
01101
01102 char *description()
01103 {
01104 return (char *) desc;
01105 }
01106
01107 char *key()
01108 {
01109 return ASTERISK_GPL_KEY;
01110 }
01111