#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/signal.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/vmodem.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Defines | |
#define | ECHO_TIMEOUT 10 |
Functions | |
static int | __unload_module (void) |
int | ast_modem_expect (struct ast_modem_pvt *p, char *result, int timeout) |
ast_channel * | ast_modem_new (struct ast_modem_pvt *i, int state) |
int | ast_modem_read_response (struct ast_modem_pvt *p, int timeout) |
int | ast_modem_send (struct ast_modem_pvt *p, char *cmd, int len) |
void | ast_modem_trim (char *s) |
AST_MUTEX_DEFINE_STATIC (monlock) | |
AST_MUTEX_DEFINE_STATIC (iflock) | |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
int | ast_register_modem_driver (struct ast_modem_driver *mc) |
int | ast_unregister_modem_driver (struct ast_modem_driver *mc) |
char * | description () |
Provides a description of the module. | |
static void * | do_monitor (void *data) |
static struct ast_modem_driver * | find_capability (char *ident) |
static struct ast_modem_driver * | find_driver (char *drv) |
static ast_group_t | get_group (char *s) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
static struct ast_modem_pvt * | mkif (char *iface) |
static int | modem_answer (struct ast_channel *ast) |
static int | modem_call (struct ast_channel *ast, char *idest, int timeout) |
static int | modem_digit (struct ast_channel *ast, char digit) |
static int | modem_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | modem_hangup (struct ast_channel *ast) |
static void | modem_mini_packet (struct ast_modem_pvt *i) |
static struct ast_frame * | modem_read (struct ast_channel *) |
static struct ast_channel * | modem_request (const char *type, int format, void *data, int *cause) |
static int | modem_setup (struct ast_modem_pvt *p, int baudrate) |
static int | modem_write (struct ast_channel *ast, struct ast_frame *frame) |
static int | restart_monitor (void) |
static void | stty (struct ast_modem_pvt *p) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static int | baudrate = 115200 |
static const char | config [] = "modem.conf" |
static char | context [AST_MAX_EXTENSION] = "default" |
static ast_group_t | cur_group = 0 |
int | dep_warning = 0 |
static const char | desc [] = "Generic Voice Modem Driver" |
static char | dialtype = 'T' |
static struct ast_modem_driver * | drivers = NULL |
ast_dsp * | dsp = NULL |
static int | dtmfmode = MODEM_DTMF_AST |
static int | dtmfmodegen = MODEM_DTMF_AST |
static int | gmode = MODEM_MODE_IMMEDIATE |
static struct ast_modem_pvt * | iflist = NULL |
static char | incomingmsn [AST_MAX_EXTENSION] = "" |
static char | initstr [AST_MAX_INIT_STR] = "ATE0Q0" |
static char | language [MAX_LANGUAGE] = "" |
static const struct ast_channel_tech | modem_tech |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
static char | msn [AST_MAX_EXTENSION] = "" |
static char | mtype [80] = "autodetect" |
static char | outgoingmsn [AST_MAX_EXTENSION] = "" |
static int | stripmsd = 0 |
static const char | tdesc [] = "Generic Voice Modem Channel Driver" |
static const char | type [] = "Modem" |
static int | usecnt = 0 |
Definition in file chan_modem.c.
|
Definition at line 55 of file chan_modem.c. Referenced by modem_setup(). |
|
Definition at line 923 of file chan_modem.c. References ast_channel_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_modem_pvt::fd, free, iflist, LOG_WARNING, modem_tech, ast_modem_pvt::next, and ast_modem_pvt::owner. 00924 { 00925 struct ast_modem_pvt *p, *pl; 00926 /* First, take us out of the channel loop */ 00927 ast_channel_unregister(&modem_tech); 00928 if (!ast_mutex_lock(&iflock)) { 00929 /* Hangup all interfaces if they have an owner */ 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 /* Destroy all the interfaces and free their memory */ 00956 p = iflist; 00957 while(p) { 00958 /* Close the socket, assuming it's real */ 00959 if (p->fd > -1) 00960 close(p->fd); 00961 pl = p; 00962 p = p->next; 00963 /* Free associated memory */ 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 }
|
|
Wait for result to occur. Return non-zero if times out or error, last response is stored in p->response Definition at line 345 of file chan_modem.c. References ast_waitfor_n_fd(), ast_modem_pvt::f, ast_modem_pvt::fd, and ast_modem_pvt::response. Referenced by aopen_answer(), aopen_break(), aopen_dialdigit(), aopen_hangup(), aopen_identify(), aopen_init(), aopen_setdev(), aopen_startrec(), bestdata_answer(), bestdata_break(), bestdata_dialdigit(), bestdata_hangup(), bestdata_identify(), bestdata_init(), bestdata_startplay(), bestdata_startrec(), i4l_answer(), i4l_break(), i4l_hangup(), i4l_init(), i4l_setdev(), i4l_startrec(), and modem_setup(). 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 /* Read a response */ 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 }
|
|
|
Wait for result to occur. response is stored in p->response Definition at line 296 of file chan_modem.c. References ast_waitfor_n_fd(), ast_modem_pvt::f, ast_modem_pvt::fd, and ast_modem_pvt::response. Referenced by aopen_break(), aopen_identify(), aopen_setdev(), bestdata_break(), bestdata_handle_escape(), bestdata_identify(), i4l_break(), i4l_setdev(), and modem_setup(). 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 /* get no more then buffer length */ 00309 while(i < sizeof(p->response) - 1) 00310 { 00311 c = fgetc(p->f); /* get a char */ 00312 if (c < 1) /* if error */ 00313 { 00314 /* if nothing in buffer, go back into timeout stuff */ 00315 if (errno == EWOULDBLOCK) break; 00316 /* return as error */ 00317 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00318 return -1; 00319 } 00320 /* save char */ 00321 p->response[i++] = c; 00322 p->response[i] = 0; 00323 /* if end of input */ 00324 if (c == '\n') break; 00325 } 00326 if (c >= 0) /* if input terminated normally */ 00327 { 00328 /* ignore just CR/LF */ 00329 if (!strcmp(p->response,"\r\n")) 00330 { 00331 /* reset input buffer stuff */ 00332 i = 0; 00333 p->response[0] = 0; 00334 } 00335 else /* otherwise return with info in buffer */ 00336 { 00337 return 0; 00338 } 00339 } 00340 } while(timeout > 0); 00341 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00342 return -1; 00343 }
|
|
Send the command cmd (length len, or 0 if pure ascii) on modem Definition at line 272 of file chan_modem.c. References ast_modem_pvt::f. Referenced by aopen_answer(), aopen_break(), aopen_dial(), aopen_dialdigit(), aopen_handle_escape(), aopen_hangup(), aopen_identify(), aopen_init(), aopen_setdev(), aopen_startrec(), bestdata_answer(), bestdata_break(), bestdata_dialdigit(), bestdata_handle_escape(), bestdata_hangup(), bestdata_identify(), bestdata_init(), bestdata_startplay(), bestdata_startrec(), i4l_answer(), i4l_break(), i4l_dial(), i4l_handle_escape(), i4l_hangup(), i4l_init(), i4l_setdev(), i4l_startrec(), and modem_setup(). 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 }
|
|
Trim off trailing mess Definition at line 363 of file chan_modem.c. Referenced by aopen_identify(), aopen_read(), aopen_setdev(), bestdata_handle_escape(), bestdata_identify(), bestdata_read(), i4l_read(), i4l_setdev(), and modem_setup(). 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 }
|
|
|
|
|
|
|
|
Register a driver Definition at line 194 of file chan_modem.c. References drivers, and ast_modem_driver::next. Referenced by load_module().
|
|
Unregister a driver Definition at line 201 of file chan_modem.c. References drivers, last, and ast_modem_driver::next. Referenced by unload_module(). 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 }
|
|
Provides a description of the module.
Definition at line 1107 of file chan_modem.c. 01108 { 01109 return (char *) desc; 01110 }
|
|
Definition at line 616 of file chan_modem.c. References ast_log(), ast_mutex_lock(), LOG_ERROR, LOG_WARNING, and n. 00617 { 00618 fd_set rfds, efds; 00619 int n, res; 00620 struct ast_modem_pvt *i; 00621 /* This thread monitors all the frame relay interfaces which are not yet in use 00622 (and thus do not have a separate thread) indefinitely */ 00623 /* From here on out, we die whenever asked */ 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 /* Don't let anybody kill us right away. Nobody should lock the interface list 00632 and wait for the monitor list, but the other way around is okay. */ 00633 if (ast_mutex_lock(&monlock)) { 00634 ast_log(LOG_ERROR, "Unable to grab monitor lock\n"); 00635 return NULL; 00636 } 00637 /* Lock the interface list */ 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 /* Build the stuff we're going to select on, that is the socket of every 00644 ast_modem_pvt that does not have an associated owner channel */ 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 /* This needs to be watched, as it lacks an owner */ 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 /* Okay, now that we know what to do, release the interface lock */ 00663 ast_mutex_unlock(&iflock); 00664 00665 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 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 /* Wait indefinitely for something to happen */ 00671 pthread_testcancel(); 00672 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 00673 pthread_testcancel(); 00674 /* Okay, select has finished. Let's see what happened. */ 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 /* Alright, lock the interface list again, and let's look and see what has 00681 happened */ 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 /* Never reached */ 00701 return NULL; 00702 00703 }
|
|
Definition at line 157 of file chan_modem.c. References drivers, ast_modem_driver::idents, and ast_modem_driver::next. Referenced by modem_setup(). 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 }
|
|
Definition at line 178 of file chan_modem.c. References drivers, ast_modem_driver::incusecnt, ast_modem_driver::name, and ast_modem_driver::next. Referenced by modem_setup(). 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 }
|
|
Definition at line 887 of file chan_modem.c. References ast_log(), ast_strdupa, copy(), group, LOG_ERROR, LOG_WARNING, and strsep(). Referenced by load_module(). 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 /* Range */ 00903 } else if (sscanf(piece, "%d", &start)) { 00904 /* Just one */ 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 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 1112 of file chan_modem.c. References ASTERISK_GPL_KEY. 01113 { 01114 return ASTERISK_GPL_KEY; 01115 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 981 of file chan_modem.c. References __unload_module(), ast_channel_register(), ast_config_destroy(), ast_config_load(), ast_load_resource(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), ast_verbose(), cfg, get_group(), iflist, LOG_ERROR, LOG_WARNING, mkif(), MODEM_DTMF_AST, MODEM_DTMF_I4L, MODEM_DTMF_NONE, MODEM_MODE_IMMEDIATE, MODEM_MODE_WAIT_ANSWER, MODEM_MODE_WAIT_RING, modem_tech, ast_variable::name, ast_variable::next, ast_modem_pvt::next, option_verbose, restart_monitor(), ast_variable::value, and VERBOSE_PREFIX_2. 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 /* We *must* have a config file otherwise stop immediately */ 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 /* It's a little silly to lock it, but we mind as well just to be sure */ 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 /* Create the interface list */ 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 /* And start the monitor for the first time */ 01098 restart_monitor(); 01099 return 0; 01100 }
|
|
Definition at line 760 of file chan_modem.c. References ast_log(), free, LOG_WARNING, malloc, modem_setup(), and stty(). Referenced by load_module(). 00761 { 00762 /* Make a ast_modem_pvt structure for this interface */ 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 /* Maybe in the future we want to allow variable 00785 serial settings */ 00786 stty(tmp); 00787 tmp->f = fdopen(tmp->fd, "w+"); 00788 /* Disable buffering */ 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 }
|
|
Definition at line 485 of file chan_modem.c. References ast_modem_driver::answer, ast_log(), ast_setstate(), AST_STATE_UP, LOG_DEBUG, ast_modem_pvt::mc, ast_channel::name, option_debug, ast_channel::rings, and ast_channel::tech_pvt. 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 }
|
|
Definition at line 218 of file chan_modem.c. References ast_channel::_state, ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_waitfor(), ast_modem_driver::dial, LOG_WARNING, ast_modem_pvt::mc, MODEM_DEV_HANDSET, MODEM_DEV_TELCO_SPK, modem_read(), ast_channel::name, ast_modem_driver::setdev, ast_modem_pvt::stripmsd, strsep(), and ast_channel::tech_pvt. 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 /* if not a transfer or just sending tones, must be in correct state */ 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")) /* if a transfer, put in transfer stuff */ 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 /* Should be immediately up */ 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 /* Just read packets and watch what happens */ 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 }
|
|
Definition at line 145 of file chan_modem.c. References ast_log(), ast_modem_driver::dialdigit, LOG_DEBUG, ast_modem_pvt::mc, ast_channel::name, and ast_channel::tech_pvt. 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 }
|
|
Definition at line 548 of file chan_modem.c. References ast_log(), LOG_WARNING, ast_modem_pvt::owner, and ast_channel::tech_pvt. 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 }
|
|
|
Definition at line 604 of file chan_modem.c. References AST_CONTROL_RING, AST_FRAME_CONTROL, ast_modem_new(), AST_STATE_RING, ast_frame::frametype, ast_modem_pvt::mc, ast_modem_driver::read, and ast_frame::subclass. 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 }
|
|
Definition at line 515 of file chan_modem.c. References ast_modem_pvt::mc, ast_modem_driver::read, and ast_channel::tech_pvt. Referenced by modem_call(). 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 }
|
|
Definition at line 817 of file chan_modem.c. References ast_getformatname(), ast_log(), ast_modem_new(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_modem_pvt::dev, ast_modem_driver::formats, ast_modem_pvt::group, group, iflist, LOG_ERROR, LOG_WARNING, ast_modem_pvt::mc, ast_modem_pvt::next, ast_modem_pvt::owner, restart_monitor(), and strsep(). 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 /* Retrieve the group number */ 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 /* Search for an unowned channel */ 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 /* if it belongs to the proper group, and the format matches 00854 * and it is not in use, we found a candidate! */ 00855 if (p->group & group && 00856 p->mc->formats & format && 00857 !p->owner) { 00858 /* XXX Not quite sure that not having an owner is 00859 * sufficient evidence of beeing a free device XXX */ 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 }
|
|
Definition at line 375 of file chan_modem.c. References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), ast_modem_driver::decusecnt, ast_modem_pvt::dev, ECHO_TIMEOUT, find_capability(), find_driver(), ast_modem_driver::init, ast_modem_pvt::initstr, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, ast_modem_driver::name, option_debug, and ast_modem_pvt::response. Referenced by mkif(). 00376 { 00377 00378 /* Make sure there's a modem there and that it's in a reasonable 00379 mode. Set the baud rate, etc. */ 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 /* Read any outstanding stuff */ 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 }
|
|
Definition at line 524 of file chan_modem.c. References ast_channel::_state, AST_STATE_UP, ast_channel::fds, ast_modem_pvt::mc, ast_channel::tech_pvt, and ast_modem_driver::write. 00525 { 00526 int res=0; 00527 long flags; 00528 struct ast_modem_pvt *p = ast->tech_pvt; 00529 00530 /* Modems tend to get upset when they receive data whilst in 00531 * command mode. This makes esp. dial commands short lived. 00532 * Pauline Middelink - 2002-09-24 */ 00533 if (ast->_state != AST_STATE_UP) 00534 return 0; 00535 00536 /* Temporarily make non-blocking */ 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 /* Block again */ 00544 fcntl(ast->fds[0], F_SETFL, flags); 00545 return res; 00546 }
|
|
Definition at line 705 of file chan_modem.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING. 00706 { 00707 /* If we're supposed to be stopped -- stay stopped */ 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 /* Start a new monitor */ 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 }
|
|
Definition at line 734 of file chan_modem.c. References ast_log(), ast_modem_pvt::dev, ECHO, ast_modem_pvt::fd, and LOG_WARNING. Referenced by mkif(). 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 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 976 of file chan_modem.c. References __unload_module(). 00977 { 00978 return __unload_module(); 00979 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 1102 of file chan_modem.c. 01103 { 01104 return usecnt; 01105 }
|
|
Definition at line 96 of file chan_modem.c. |
|
Definition at line 60 of file chan_modem.c. |
|
Definition at line 67 of file chan_modem.c. |
|
Definition at line 92 of file chan_modem.c. |
|
Definition at line 115 of file chan_modem.c. Referenced by curl_exec(), cut_exec(), dundi_lookup_exec(), enumlookup_exec(), eval_exec(), get_exec(), hasvoicemail_exec(), load_moh_classes(), md5_exec(), md5check_exec(), put_exec(), sip_getheader(), sort_exec(), and txtcidname_exec(). |
|
Definition at line 57 of file chan_modem.c. |
|
Definition at line 61 of file chan_modem.c. |
|
Definition at line 155 of file chan_modem.c. Referenced by ast_register_modem_driver(), ast_unregister_modem_driver(), find_capability(), and find_driver(). |
|
|
Definition at line 82 of file chan_modem.c. |
|
Definition at line 84 of file chan_modem.c. |
|
Definition at line 62 of file chan_modem.c. |
|
Definition at line 143 of file chan_modem.c. |
|
Definition at line 79 of file chan_modem.c. |
|
Definition at line 73 of file chan_modem.c. |
|
Definition at line 70 of file chan_modem.c. |
|
Definition at line 126 of file chan_modem.c. Referenced by __unload_module(), ast_modem_new(), and load_module(). |
|
Definition at line 111 of file chan_modem.c. |
|
Definition at line 76 of file chan_modem.c. |
|
Definition at line 65 of file chan_modem.c. |
|
Definition at line 89 of file chan_modem.c. |
|
Definition at line 98 of file chan_modem.c. |
|
Definition at line 58 of file chan_modem.c. |
|
Definition at line 59 of file chan_modem.c. |
|
Definition at line 94 of file chan_modem.c. |