Mon Mar 20 08:20:20 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

chan_modem.c File Reference

A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others). More...

#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

int __unload_module (void)
int ast_modem_expect (struct ast_modem_pvt *p, char *result, int timeout)
ast_channelast_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.
void * do_monitor (void *data)
ast_modem_driverfind_capability (char *ident)
ast_modem_driverfind_driver (char *drv)
ast_group_t get_group (char *s)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module ()
 Initialize the module.
ast_modem_pvtmkif (char *iface)
int modem_answer (struct ast_channel *ast)
int modem_call (struct ast_channel *ast, char *idest, int timeout)
int modem_digit (struct ast_channel *ast, char digit)
int modem_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
int modem_hangup (struct ast_channel *ast)
void modem_mini_packet (struct ast_modem_pvt *i)
ast_framemodem_read (struct ast_channel *)
ast_channelmodem_request (const char *type, int format, void *data, int *cause)
int modem_setup (struct ast_modem_pvt *p, int baudrate)
int modem_write (struct ast_channel *ast, struct ast_frame *frame)
int restart_monitor (void)
void stty (struct ast_modem_pvt *p)
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

int baudrate = 115200
const char config [] = "modem.conf"
char context [AST_MAX_EXTENSION] = "default"
ast_group_t cur_group = 0
int dep_warning = 0
const char desc [] = "Generic Voice Modem Driver"
char dialtype = 'T'
ast_modem_driverdrivers = NULL
ast_dspdsp = NULL
int dtmfmode = MODEM_DTMF_AST
int dtmfmodegen = MODEM_DTMF_AST
int gmode = MODEM_MODE_IMMEDIATE
ast_modem_pvtiflist = NULL
char incomingmsn [AST_MAX_EXTENSION] = ""
char initstr [AST_MAX_INIT_STR] = "ATE0Q0"
char language [MAX_LANGUAGE] = ""
const struct ast_channel_tech modem_tech
pthread_t monitor_thread = AST_PTHREADT_NULL
char msn [AST_MAX_EXTENSION] = ""
char mtype [80] = "autodetect"
char outgoingmsn [AST_MAX_EXTENSION] = ""
int stripmsd = 0
const char tdesc [] = "Generic Voice Modem Channel Driver"
const char type [] = "Modem"
int usecnt = 0


Detailed Description

A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others).

Definition in file chan_modem.c.


Define Documentation

#define ECHO_TIMEOUT   10
 

Definition at line 55 of file chan_modem.c.

Referenced by modem_setup().


Function Documentation

int __unload_module void   )  [static]
 

Definition at line 924 of file chan_modem.c.

References ast_channel_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_modem_pvt::fd, free, iflist, LOG_WARNING, modem_tech, monitor_thread, ast_modem_pvt::next, and ast_modem_pvt::owner.

00925 {
00926    struct ast_modem_pvt *p, *pl;
00927    /* First, take us out of the channel loop */
00928    ast_channel_unregister(&modem_tech);
00929    if (!ast_mutex_lock(&iflock)) {
00930       /* Hangup all interfaces if they have an owner */
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       /* Destroy all the interfaces and free their memory */
00957       p = iflist;
00958       while(p) {
00959          /* Close the socket, assuming it's real */
00960          if (p->fd > -1)
00961             close(p->fd);
00962          pl = p;
00963          p = p->next;
00964          /* Free associated memory */
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 }

int ast_modem_expect struct ast_modem_pvt p,
char *  result,
int  timeout
 

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, ast_modem_pvt::response, and result.

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   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 }

struct ast_channel* ast_modem_new struct ast_modem_pvt i,
int  state
 

Used by modem drivers to start up the PBX on a RING

Definition at line 563 of file chan_modem.c.

References ast_channel_alloc(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), ast_strlen_zero(), ast_update_use_count(), ast_channel::cid, ast_callerid::cid_name, ast_modem_pvt::cid_name, ast_callerid::cid_num, ast_modem_pvt::cid_num, ast_modem_pvt::context, ast_channel::context, ast_modem_pvt::dev, ast_modem_pvt::dnid, ast_channel::exten, ast_modem_pvt::fd, ast_channel::fds, ast_modem_driver::formats, ast_channel::language, ast_modem_pvt::language, LOG_WARNING, ast_modem_pvt::mc, ast_modem_driver::name, ast_channel::name, ast_channel::nativeformats, ast_modem_pvt::owner, ast_channel::rings, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, and usecnt.

Referenced by modem_mini_packet(), and modem_request().

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 }

int ast_modem_read_response struct ast_modem_pvt p,
int  timeout
 

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 }

int ast_modem_send struct ast_modem_pvt p,
char *  cmd,
int  len
 

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_dial(), 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 }

void ast_modem_trim char *  s  ) 
 

Trim off trailing mess

Definition at line 366 of file chan_modem.c.

References s.

Referenced by aopen_identify(), aopen_read(), aopen_setdev(), bestdata_handle_escape(), bestdata_identify(), bestdata_read(), i4l_read(), i4l_setdev(), and modem_setup().

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 }

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  ) 
 

Register a driver

Definition at line 194 of file chan_modem.c.

References drivers, and ast_modem_driver::next.

Referenced by load_module().

00195 {
00196    mc->next = drivers;
00197    drivers = mc;
00198    return 0;
00199 }

int ast_unregister_modem_driver struct ast_modem_driver mc  ) 
 

Unregister a driver

Definition at line 201 of file chan_modem.c.

References drivers, 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 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 1108 of file chan_modem.c.

01109 {
01110    return (char *) desc;
01111 }

void* do_monitor void *  data  )  [static]
 

Definition at line 617 of file chan_modem.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), ast_modem_pvt::dev, ast_modem_pvt::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, modem_mini_packet(), ast_modem_pvt::next, and ast_modem_pvt::owner.

Referenced by restart_monitor().

00618 {
00619    fd_set rfds, efds;
00620    int n, res;
00621    struct ast_modem_pvt *i;
00622    /* This thread monitors all the frame relay interfaces which are not yet in use
00623       (and thus do not have a separate thread) indefinitely */
00624    /* From here on out, we die whenever asked */
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       /* Don't let anybody kill us right away.  Nobody should lock the interface list
00633          and wait for the monitor list, but the other way around is okay. */
00634       if (ast_mutex_lock(&monlock)) {
00635          ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
00636          return NULL;
00637       }
00638       /* Lock the interface list */
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       /* Build the stuff we're going to select on, that is the socket of every
00645          ast_modem_pvt that does not have an associated owner channel */
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             /* This needs to be watched, as it lacks an owner */
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       /* Okay, now that we know what to do, release the interface lock */
00664       ast_mutex_unlock(&iflock);
00665       
00666       /* And from now on, we're okay to be killed, so release the monitor lock as well */
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       /* Wait indefinitely for something to happen */
00672       pthread_testcancel();
00673       res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
00674       pthread_testcancel();
00675       /* Okay, select has finished.  Let's see what happened.  */
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       /* Alright, lock the interface list again, and let's look and see what has
00682          happened */
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    /* Never reached */
00702    return NULL;
00703    
00704 }

struct ast_modem_driver* find_capability char *  ident  )  [static]
 

Definition at line 157 of file chan_modem.c.

References ast_modem_driver::idents, ast_modem_driver::incusecnt, 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 }

struct ast_modem_driver* find_driver char *  drv  )  [static]
 

Definition at line 178 of file chan_modem.c.

References 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 }

ast_group_t get_group char *  s  )  [static]
 

Definition at line 888 of file chan_modem.c.

References ast_group_t, ast_log(), ast_strdupa, LOG_ERROR, LOG_WARNING, s, and strsep().

Referenced by load_module().

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          /* Range */
00904       } else if (sscanf(piece, "%d", &start)) {
00905          /* Just one */
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 }

char* key void   ) 
 

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;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 1113 of file chan_modem.c.

01114 {
01115    return ASTERISK_GPL_KEY;
01116 }

int load_module void   ) 
 

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.

Returns:
int Always 0.

Definition at line 982 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, config, context, cur_group, dialtype, dtmfmode, dtmfmodegen, get_group(), gmode, iflist, incomingmsn, initstr, language, LOG_ERROR, LOG_WARNING, mkif(), MODEM_DTMF_I4L, modem_tech, msn, mtype, ast_variable::name, ast_variable::next, ast_modem_pvt::next, option_verbose, outgoingmsn, restart_monitor(), stripmsd, type, ast_variable::value, and VERBOSE_PREFIX_2.

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    /* We *must* have a config file otherwise stop immediately */
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       /* It's a little silly to lock it, but we mind as well just to be sure */
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       /* Create the interface list */
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    /* And start the monitor for the first time */
01099    restart_monitor();
01100    return 0;
01101 }

struct ast_modem_pvt* mkif char *  iface  )  [static]
 

Definition at line 761 of file chan_modem.c.

References ast_log(), baudrate, ast_modem_pvt::cid_name, ast_modem_pvt::cid_num, context, ast_modem_pvt::context, ast_modem_pvt::dev, ast_modem_pvt::dialtype, ast_modem_pvt::dtmfmode, ast_modem_pvt::dtmfmodegen, ast_modem_pvt::f, ast_modem_pvt::fd, free, ast_modem_pvt::group, incomingmsn, ast_modem_pvt::incomingmsn, initstr, ast_modem_pvt::initstr, language, ast_modem_pvt::language, LOG_WARNING, malloc, ast_modem_pvt::ministate, ast_modem_pvt::mode, modem_setup(), msn, ast_modem_pvt::msn, ast_modem_pvt::next, ast_modem_pvt::obuflen, outgoingmsn, ast_modem_pvt::outgoingmsn, ast_modem_pvt::owner, ast_modem_pvt::stripmsd, and stty().

00762 {
00763    /* Make a ast_modem_pvt structure for this interface */
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       /* Maybe in the future we want to allow variable
00786          serial settings */
00787       stty(tmp);
00788       tmp->f = fdopen(tmp->fd, "w+");
00789       /* Disable buffering */
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 }

int modem_answer struct ast_channel ast  )  [static]
 

Definition at line 488 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, ast_channel::rings, and ast_channel::tech_pvt.

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 }

int modem_call struct ast_channel ast,
char *  idest,
int  timeout
[static]
 

Definition at line 218 of file chan_modem.c.

References ast_channel::_state, ast_log(), ast_setstate(), AST_STATE_DIALING, 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 }

int modem_digit struct ast_channel ast,
char  digit
[static]
 

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 }

int modem_fixup struct ast_channel oldchan,
struct ast_channel newchan
[static]
 

Definition at line 551 of file chan_modem.c.

References ast_log(), LOG_WARNING, ast_modem_pvt::owner, and ast_channel::tech_pvt.

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 }

int modem_hangup struct ast_channel ast  )  [static]
 

Definition at line 457 of file chan_modem.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, ast_update_use_count(), ast_verbose(), ast_modem_pvt::cid_name, ast_modem_pvt::cid_num, ast_modem_pvt::dnid, ast_modem_driver::hangup, ast_modem_driver::init, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, ast_channel::name, option_verbose, restart_monitor(), ast_channel::tech_pvt, usecnt, and VERBOSE_PREFIX_3.

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    /* Hang up */
00464    if (p->mc->hangup)
00465       p->mc->hangup(p);
00466    /* Re-initialize */
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 }

void modem_mini_packet struct ast_modem_pvt i  )  [static]
 

Definition at line 605 of file chan_modem.c.

References ast_modem_new(), AST_STATE_RING, ast_frame::frametype, ast_modem_pvt::mc, ast_modem_driver::read, and ast_frame::subclass.

Referenced by do_monitor().

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 }

struct ast_frame * modem_read struct ast_channel  )  [static]
 

Definition at line 518 of file chan_modem.c.

References ast_modem_pvt::mc, ast_modem_driver::read, and ast_channel::tech_pvt.

Referenced by modem_call().

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 }

struct ast_channel * modem_request const char *  type,
int  format,
void *  data,
int *  cause
[static]
 

Definition at line 818 of file chan_modem.c.

References ast_getformatname(), ast_group_t, ast_log(), ast_modem_new(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, dep_warning, ast_modem_pvt::dev, ast_modem_driver::formats, ast_modem_pvt::group, LOG_ERROR, LOG_WARNING, ast_modem_pvt::mc, ast_modem_pvt::next, ast_modem_pvt::owner, restart_monitor(), and strsep().

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       /* Retrieve the group number */
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    /* Search for an unowned channel */
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          /* if it belongs to the proper group, and the format matches
00855           * and it is not in use, we found a candidate! */
00856          if (p->group & group &&
00857              p->mc->formats & format &&
00858              !p->owner) {
00859             /* XXX Not quite sure that not having an owner is
00860              * sufficient evidence of beeing a free device XXX */
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 }

int modem_setup struct ast_modem_pvt p,
int  baudrate
[static]
 

Definition at line 378 of file chan_modem.c.

References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), ast_verbose(), ast_modem_driver::decusecnt, ast_modem_pvt::dev, ECHO_TIMEOUT, find_capability(), find_driver(), free, ast_modem_driver::identify, ast_modem_driver::init, ast_modem_pvt::initstr, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, mtype, ast_modem_driver::name, option_verbose, ast_modem_pvt::response, and VERBOSE_PREFIX_3.

Referenced by mkif().

00379 {
00380 
00381    /* Make sure there's a modem there and that it's in a reasonable 
00382       mode.  Set the baud rate, etc.  */
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    /* Read any outstanding stuff */
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 }

int modem_write struct ast_channel ast,
struct ast_frame frame
[static]
 

Definition at line 527 of file chan_modem.c.

References ast_channel::_state, ast_channel::fds, ast_modem_pvt::mc, ast_channel::tech_pvt, and ast_modem_driver::write.

00528 {
00529    int res=0;
00530    long flags;
00531    struct ast_modem_pvt *p = ast->tech_pvt;
00532 
00533    /* Modems tend to get upset when they receive data whilst in
00534     * command mode. This makes esp. dial commands short lived.
00535     *     Pauline Middelink - 2002-09-24 */
00536    if (ast->_state != AST_STATE_UP)
00537       return 0;
00538 
00539    /* Temporarily make non-blocking */
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    /* Block again */
00547    fcntl(ast->fds[0], F_SETFL, flags);
00548    return res;
00549 }

int restart_monitor void   )  [static]
 

Definition at line 706 of file chan_modem.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, do_monitor(), LOG_ERROR, LOG_WARNING, and monitor_thread.

00707 {
00708    /* If we're supposed to be stopped -- stay stopped */
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       /* Start a new monitor */
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 }

void stty struct ast_modem_pvt p  )  [static]
 

Definition at line 735 of file chan_modem.c.

References ast_log(), ast_modem_pvt::dev, ECHO, ast_modem_pvt::fd, and LOG_WARNING.

Referenced by mkif().

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 }

int unload_module void   ) 
 

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).

Returns:
Zero on success, or non-zero on error.

Definition at line 977 of file chan_modem.c.

References __unload_module().

00978 {
00979    return __unload_module();
00980 }

int usecount void   ) 
 

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.

Returns:
The module's usecount.

Definition at line 1103 of file chan_modem.c.

01104 {
01105    return usecnt;
01106 }


Variable Documentation

int baudrate = 115200 [static]
 

Definition at line 96 of file chan_modem.c.

Referenced by mkif().

const char config[] = "modem.conf" [static]
 

Definition at line 60 of file chan_modem.c.

Referenced by load_module().

char context[AST_MAX_EXTENSION] = "default" [static]
 

Definition at line 67 of file chan_modem.c.

Referenced by load_module(), and mkif().

ast_group_t cur_group = 0 [static]
 

Definition at line 92 of file chan_modem.c.

Referenced by load_module().

int dep_warning = 0
 

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(), modem_request(), put_exec(), sip_getheader(), sort_exec(), and txtcidname_exec().

const char desc[] = "Generic Voice Modem Driver" [static]
 

Definition at line 57 of file chan_modem.c.

char dialtype = 'T' [static]
 

Definition at line 61 of file chan_modem.c.

Referenced by load_module().

struct ast_modem_driver* drivers = NULL [static]
 

Definition at line 155 of file chan_modem.c.

Referenced by ast_register_modem_driver(), and ast_unregister_modem_driver().

struct ast_dsp* dsp = NULL
 

Definition at line 86 of file chan_modem.c.

Referenced by __ast_dsp_call_progress(), __ast_dsp_digitdetect(), __ast_dsp_silence(), adsi_channel_restore(), adsi_load_session(), adsi_unload_session(), ast_dsp_busydetect(), ast_dsp_call_progress(), ast_dsp_digitdetect(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_get_tcount(), ast_dsp_get_tstate(), ast_dsp_getdigits(), ast_dsp_new(), ast_dsp_process(), ast_dsp_prog_reset(), ast_dsp_reset(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), ast_dsp_silence(), background_detect_exec(), and conf_run().

int dtmfmode = MODEM_DTMF_AST [static]
 

Definition at line 82 of file chan_modem.c.

Referenced by load_module().

int dtmfmodegen = MODEM_DTMF_AST [static]
 

Definition at line 84 of file chan_modem.c.

Referenced by load_module().

int gmode = MODEM_MODE_IMMEDIATE [static]
 

Definition at line 62 of file chan_modem.c.

Referenced by load_module().

struct ast_modem_pvt* iflist = NULL [static]
 

Definition at line 143 of file chan_modem.c.

char incomingmsn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 79 of file chan_modem.c.

Referenced by load_module(), and mkif().

char initstr[AST_MAX_INIT_STR] = "ATE0Q0" [static]
 

Definition at line 73 of file chan_modem.c.

Referenced by load_module(), and mkif().

char language[MAX_LANGUAGE] = "" [static]
 

Definition at line 70 of file chan_modem.c.

Referenced by load_module(), and mkif().

const struct ast_channel_tech modem_tech [static]
 

Definition at line 126 of file chan_modem.c.

Referenced by __unload_module(), and load_module().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]
 

Definition at line 111 of file chan_modem.c.

Referenced by __unload_module(), and restart_monitor().

char msn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 76 of file chan_modem.c.

Referenced by load_module(), and mkif().

char mtype[80] = "autodetect" [static]
 

Definition at line 65 of file chan_modem.c.

Referenced by load_module(), and modem_setup().

char outgoingmsn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 89 of file chan_modem.c.

Referenced by load_module(), and mkif().

int stripmsd = 0 [static]
 

Definition at line 98 of file chan_modem.c.

Referenced by load_module().

const char tdesc[] = "Generic Voice Modem Channel Driver" [static]
 

Definition at line 58 of file chan_modem.c.

const char type[] = "Modem" [static]
 

Definition at line 59 of file chan_modem.c.

int usecnt = 0 [static]
 

Definition at line 94 of file chan_modem.c.

Referenced by ast_modem_new(), and modem_hangup().


Generated on Mon Mar 20 08:20:21 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1