Sat Apr 26 2014 22:03:16

Asterisk developer's documentation


sig_analog.h File Reference

Interface header for analog signaling module. More...

#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/smdi.h"
Include dependency graph for sig_analog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  analog_callback
struct  analog_dialoperation
struct  analog_pvt
struct  analog_subchannel

Defines

#define ANALOG_MAX_CID   300
#define ANALOG_SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */
#define READ_SIZE   160
#define RING_PATTERNS   3

Enumerations

enum  analog_cid_start { ANALOG_CID_START_POLARITY = 1, ANALOG_CID_START_POLARITY_IN, ANALOG_CID_START_RING, ANALOG_CID_START_DTMF_NOALERT }
enum  analog_dsp_digitmode { ANALOG_DIGITMODE_DTMF = 1, ANALOG_DIGITMODE_MF }
enum  analog_event {
  ANALOG_EVENT_NONE = 0, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_WINKFLASH,
  ANALOG_EVENT_ALARM, ANALOG_EVENT_NOALARM, ANALOG_EVENT_DIALCOMPLETE, ANALOG_EVENT_RINGERON,
  ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_PULSE_START, ANALOG_EVENT_POLARITY,
  ANALOG_EVENT_RINGBEGIN, ANALOG_EVENT_EC_DISABLED, ANALOG_EVENT_REMOVED, ANALOG_EVENT_NEONMWI_ACTIVE,
  ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_TX_CED_DETECTED, ANALOG_EVENT_RX_CED_DETECTED, ANALOG_EVENT_EC_NLP_DISABLED,
  ANALOG_EVENT_EC_NLP_ENABLED, ANALOG_EVENT_ERROR, ANALOG_EVENT_DTMFCID, ANALOG_EVENT_PULSEDIGIT = (1 << 16),
  ANALOG_EVENT_DTMFDOWN = (1 << 17), ANALOG_EVENT_DTMFUP = (1 << 18)
}
enum  analog_sigtype {
  ANALOG_SIG_NONE = -1, ANALOG_SIG_FXOLS = 1, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOGS,
  ANALOG_SIG_FXSLS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSGS, ANALOG_SIG_EMWINK,
  ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF,
  ANALOG_SIG_E911, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FEATB,
  ANALOG_SIG_SFWINK, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF,
  ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_SF_FEATB
}
enum  analog_sub { ANALOG_SUB_REAL = 0, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY }
enum  analog_tone {
  ANALOG_TONE_RINGTONE = 0, ANALOG_TONE_STUTTER, ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALTONE,
  ANALOG_TONE_DIALRECALL, ANALOG_TONE_INFO
}
enum  dialop { ANALOG_DIAL_OP_REPLACE = 2 }

Functions

int analog_answer (struct analog_pvt *p, struct ast_channel *ast)
int analog_available (struct analog_pvt *p)
int analog_call (struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
const char * analog_cidstart_to_str (enum analog_cid_start cid_start)
const char * analog_cidtype_to_str (unsigned int cid_type)
int analog_config_complete (struct analog_pvt *p)
void analog_delete (struct analog_pvt *doomed)
 Delete the analog private structure.
int analog_dnd (struct analog_pvt *p, int flag)
struct ast_frameanalog_exception (struct analog_pvt *p, struct ast_channel *ast)
int analog_fixup (struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
void analog_free (struct analog_pvt *p)
void analog_handle_dtmf (struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest)
void * analog_handle_init_event (struct analog_pvt *i, int event)
int analog_hangup (struct analog_pvt *p, struct ast_channel *ast)
struct analog_pvtanalog_new (enum analog_sigtype signallingtype, void *private_data)
struct ast_channelanalog_request (struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
const char * analog_sigtype_to_str (enum analog_sigtype sigtype)
int analog_ss_thread_start (struct analog_pvt *p, struct ast_channel *ast)
enum analog_cid_start analog_str_to_cidstart (const char *value)
unsigned int analog_str_to_cidtype (const char *name)
enum analog_sigtype analog_str_to_sigtype (const char *name)

Variables

struct analog_callback analog_callbacks

Detailed Description

Interface header for analog signaling module.

Author:
Matthew Fredrickson <creslin@digium.com>

Definition in file sig_analog.h.


Define Documentation

#define ANALOG_MAX_CID   300

Definition at line 33 of file sig_analog.h.

Referenced by __analog_ss_thread(), and my_get_callerid().

#define ANALOG_SMDI_MD_WAIT_TIMEOUT   1500 /* 1.5 seconds */

Definition at line 32 of file sig_analog.h.

Referenced by __analog_ss_thread().

#define READ_SIZE   160

Definition at line 34 of file sig_analog.h.

#define RING_PATTERNS   3

Definition at line 35 of file sig_analog.h.

Referenced by __analog_ss_thread(), and my_distinctive_ring().


Enumeration Type Documentation

Enumerator:
ANALOG_CID_START_POLARITY 
ANALOG_CID_START_POLARITY_IN 
ANALOG_CID_START_RING 
ANALOG_CID_START_DTMF_NOALERT 

Definition at line 112 of file sig_analog.h.

Enumerator:
ANALOG_DIGITMODE_DTMF 
ANALOG_DIGITMODE_MF 

Definition at line 107 of file sig_analog.h.

Enumerator:
ANALOG_EVENT_NONE 
ANALOG_EVENT_ONHOOK 
ANALOG_EVENT_RINGOFFHOOK 
ANALOG_EVENT_WINKFLASH 
ANALOG_EVENT_ALARM 
ANALOG_EVENT_NOALARM 
ANALOG_EVENT_DIALCOMPLETE 
ANALOG_EVENT_RINGERON 
ANALOG_EVENT_RINGEROFF 
ANALOG_EVENT_HOOKCOMPLETE 
ANALOG_EVENT_PULSE_START 
ANALOG_EVENT_POLARITY 
ANALOG_EVENT_RINGBEGIN 
ANALOG_EVENT_EC_DISABLED 
ANALOG_EVENT_REMOVED 
ANALOG_EVENT_NEONMWI_ACTIVE 
ANALOG_EVENT_NEONMWI_INACTIVE 
ANALOG_EVENT_TX_CED_DETECTED 
ANALOG_EVENT_RX_CED_DETECTED 
ANALOG_EVENT_EC_NLP_DISABLED 
ANALOG_EVENT_EC_NLP_ENABLED 
ANALOG_EVENT_ERROR 
ANALOG_EVENT_DTMFCID 
ANALOG_EVENT_PULSEDIGIT 
ANALOG_EVENT_DTMFDOWN 
ANALOG_EVENT_DTMFUP 

Definition at line 72 of file sig_analog.h.

Enumerator:
ANALOG_SIG_NONE 
ANALOG_SIG_FXOLS 
ANALOG_SIG_FXOKS 
ANALOG_SIG_FXOGS 
ANALOG_SIG_FXSLS 
ANALOG_SIG_FXSKS 
ANALOG_SIG_FXSGS 
ANALOG_SIG_EMWINK 
ANALOG_SIG_EM 
ANALOG_SIG_EM_E1 
ANALOG_SIG_FEATD 
ANALOG_SIG_FEATDMF 
ANALOG_SIG_E911 
ANALOG_SIG_FGC_CAMA 
ANALOG_SIG_FGC_CAMAMF 
ANALOG_SIG_FEATB 
ANALOG_SIG_SFWINK 
ANALOG_SIG_SF 
ANALOG_SIG_SF_FEATD 
ANALOG_SIG_SF_FEATDMF 
ANALOG_SIG_FEATDMF_TA 
ANALOG_SIG_SF_FEATB 

Definition at line 38 of file sig_analog.h.

enum analog_sub
Enumerator:
ANALOG_SUB_REAL 

Active call

ANALOG_SUB_CALLWAIT 

Call-Waiting call on hold

ANALOG_SUB_THREEWAY 

Three-way call

Definition at line 101 of file sig_analog.h.

                {
   ANALOG_SUB_REAL = 0,       /*!< Active call */
   ANALOG_SUB_CALLWAIT,       /*!< Call-Waiting call on hold */
   ANALOG_SUB_THREEWAY,       /*!< Three-way call */
};
Enumerator:
ANALOG_TONE_RINGTONE 
ANALOG_TONE_STUTTER 
ANALOG_TONE_CONGESTION 
ANALOG_TONE_DIALTONE 
ANALOG_TONE_DIALRECALL 
ANALOG_TONE_INFO 

Definition at line 63 of file sig_analog.h.

enum dialop
Enumerator:
ANALOG_DIAL_OP_REPLACE 

Definition at line 119 of file sig_analog.h.


Function Documentation

int analog_answer ( struct analog_pvt p,
struct ast_channel ast 
)

Definition at line 1491 of file sig_analog.c.

References analog_answer_polarityswitch(), analog_get_index, analog_off_hook(), analog_play_tone(), analog_set_dialing(), analog_set_echocanceller(), analog_set_new_owner(), analog_set_ringtimeout(), ANALOG_SIG_E911, ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATB, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, analog_swap_subs(), analog_train_echocanceller(), ast_channel_name(), ast_debug, ast_log(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, analog_pvt::channel, analog_pvt::hanguponpolarityswitch, analog_subchannel::inthreeway, LOG_WARNING, analog_subchannel::owner, analog_pvt::polaritydelaytv, analog_pvt::sig, and analog_pvt::subs.

Referenced by dahdi_answer().

{
   int res = 0;
   int idx;
   int oldstate = ast_channel_state(ast);

   ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
   ast_setstate(ast, AST_STATE_UP);
   idx = analog_get_index(ast, p, 1);
   if (idx < 0) {
      idx = ANALOG_SUB_REAL;
   }
   switch (p->sig) {
   case ANALOG_SIG_FXSLS:
   case ANALOG_SIG_FXSGS:
   case ANALOG_SIG_FXSKS:
      analog_set_ringtimeout(p, 0);
      /* Fall through */
   case ANALOG_SIG_EM:
   case ANALOG_SIG_EM_E1:
   case ANALOG_SIG_EMWINK:
   case ANALOG_SIG_FEATD:
   case ANALOG_SIG_FEATDMF:
   case ANALOG_SIG_FEATDMF_TA:
   case ANALOG_SIG_E911:
   case ANALOG_SIG_FGC_CAMA:
   case ANALOG_SIG_FGC_CAMAMF:
   case ANALOG_SIG_FEATB:
   case ANALOG_SIG_SF:
   case ANALOG_SIG_SFWINK:
   case ANALOG_SIG_SF_FEATD:
   case ANALOG_SIG_SF_FEATDMF:
   case ANALOG_SIG_SF_FEATB:
   case ANALOG_SIG_FXOLS:
   case ANALOG_SIG_FXOGS:
   case ANALOG_SIG_FXOKS:
      /* Pick up the line */
      ast_debug(1, "Took %s off hook\n", ast_channel_name(ast));
      if (p->hanguponpolarityswitch) {
         gettimeofday(&p->polaritydelaytv, NULL);
      }
      res = analog_off_hook(p);
      analog_play_tone(p, idx, -1);
      analog_set_dialing(p, 0);
      if ((idx == ANALOG_SUB_REAL) && p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
         if (oldstate == AST_STATE_RINGING) {
            ast_debug(1, "Finally swapping real and threeway\n");
            analog_play_tone(p, ANALOG_SUB_THREEWAY, -1);
            analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
            analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
         }
      }

      switch (p->sig) {
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSKS:
      case ANALOG_SIG_FXSGS:
         analog_set_echocanceller(p, 1);
         analog_train_echocanceller(p);
         break;
      case ANALOG_SIG_FXOLS:
      case ANALOG_SIG_FXOKS:
      case ANALOG_SIG_FXOGS:
         analog_answer_polarityswitch(p);
         break;
      default:
         break;
      }
      break;
   default:
      ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
      res = -1;
      break;
   }
   ast_setstate(ast, AST_STATE_UP);
   return res;
}
int analog_available ( struct analog_pvt p)

Definition at line 816 of file sig_analog.c.

References analog_subchannel::allocd, analog_is_off_hook(), ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY, ast_debug, AST_STATE_RINGING, AST_STATE_UP, analog_pvt::callwaiting, analog_pvt::channel, analog_pvt::dnd, analog_pvt::guardtime, analog_subchannel::inthreeway, analog_pvt::outgoing, analog_subchannel::owner, analog_pvt::owner, analog_pvt::sig, and analog_pvt::subs.

Referenced by available().

{
   int offhook;

   ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);

   /* If do not disturb, definitely not */
   if (p->dnd) {
      return 0;
   }
   /* If guard time, definitely not */
   if (p->guardtime && (time(NULL) < p->guardtime)) {
      return 0;
   }

   /* If no owner definitely available */
   if (!p->owner) {
      offhook = analog_is_off_hook(p);

      /* TDM FXO card, "onhook" means out of service (no battery on the line) */
      if ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || (p->sig == ANALOG_SIG_FXSGS)) {
#ifdef DAHDI_CHECK_HOOKSTATE
         if (offhook) {
            return 1;
         }
         return 0;
#endif
      /* TDM FXS card, "offhook" means someone took the hook off so it's unavailable! */
      } else if (offhook) {
         ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
         /* Not available when the other end is off hook */
         return 0;
      }
      return 1;
   }

   /* If it's not an FXO, forget about call wait */
   if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS)) {
      return 0;
   }

   if (!p->callwaiting) {
      /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
      return 0;
   }

   if (p->subs[ANALOG_SUB_CALLWAIT].allocd) {
      /* If there is already a call waiting call, then we can't take a second one */
      return 0;
   }

   if ((ast_channel_state(p->owner) != AST_STATE_UP) &&
       ((ast_channel_state(p->owner) != AST_STATE_RINGING) || p->outgoing)) {
      /* If the current call is not up, then don't allow the call */
      return 0;
   }
   if ((p->subs[ANALOG_SUB_THREEWAY].owner) && (!p->subs[ANALOG_SUB_THREEWAY].inthreeway)) {
      /* Can't take a call wait when the three way calling hasn't been merged yet. */
      return 0;
   }
   /* We're cool */
   return 1;
}
int analog_call ( struct analog_pvt p,
struct ast_channel ast,
const char *  rdest,
int  timeout 
)

Definition at line 1008 of file sig_analog.c.

References analog_callwait(), analog_defaultcic, analog_defaultozz, analog_dial_digits(), ANALOG_DIAL_OP_REPLACE, analog_get_index, analog_get_orig_dialstring(), analog_on_hook(), analog_play_tone(), analog_ring(), analog_set_cadence(), analog_set_dialing(), analog_set_outgoing(), analog_set_waitingfordt(), ANALOG_SIG_E911, ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATB, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, analog_start(), ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE, analog_pvt::answeronpolarityswitch, AST_CC_CCNR, AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, ast_channel_connected(), ast_channel_get_cc_config_params(), ast_channel_name(), AST_CONTROL_BUSY, AST_CONTROL_RINGING, ast_copy_string(), ast_debug, ast_get_cc_monitor_policy(), ast_log(), ast_queue_cc_frame(), ast_queue_control(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_tvnow(), analog_pvt::caller, analog_pvt::callwait_name, analog_pvt::callwait_num, analog_pvt::channel, analog_pvt::dialdest, analog_pvt::dialednone, analog_dialoperation::dialstr, analog_pvt::dop, analog_pvt::echobreak, analog_pvt::echorest, analog_pvt::echotraining, errno, analog_pvt::finaldial, analog_pvt::hanguponpolarityswitch, ast_party_caller::id, ast_party_connected_line::id, analog_pvt::lastcid_name, analog_pvt::lastcid_num, LOG_WARNING, name, ast_party_id::name, ast_party_id::number, analog_dialoperation::op, analog_pvt::outsigmod, analog_subchannel::owner, analog_pvt::owner, pbx_builtin_getvar_helper(), analog_pvt::polaritydelaytv, analog_pvt::pulse, S_COR, analog_pvt::sig, ast_party_name::str, ast_party_number::str, analog_pvt::stripmsd, analog_pvt::subs, analog_pvt::use_callerid, ast_party_name::valid, ast_party_number::valid, and analog_pvt::whichwink.

Referenced by dahdi_call().

{
   int res, idx, mysig;
   char *c, *n, *l;
   char dest[256]; /* must be same length as p->dialdest */

   ast_debug(1, "CALLING CID_NAME: %s CID_NUM:: %s\n",
      S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""),
      S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""));

   ast_copy_string(dest, rdest, sizeof(dest));
   ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));

   if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
      ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_BUSY);
      return 0;
   }

   if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
      ast_log(LOG_WARNING, "analog_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
      return -1;
   }

   p->dialednone = 0;
   analog_set_outgoing(p, 1);

   mysig = p->sig;
   if (p->outsigmod > -1) {
      mysig = p->outsigmod;
   }

   switch (mysig) {
   case ANALOG_SIG_FXOLS:
   case ANALOG_SIG_FXOGS:
   case ANALOG_SIG_FXOKS:
      if (p->owner == ast) {
         /* Normal ring, on hook */

         /* Don't send audio while on hook, until the call is answered */
         analog_set_dialing(p, 1);
         analog_set_cadence(p, ast); /* and set p->cidrings */

         /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
         c = strchr(dest, '/');
         if (c) {
            c++;
         }
         if (c && (strlen(c) < p->stripmsd)) {
            ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
            c = NULL;
         }
         if (c) {
            p->dop.op = ANALOG_DIAL_OP_REPLACE;
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
            ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
         } else {
            p->dop.dialstr[0] = '\0';
         }

         if (analog_ring(p)) {
            ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
            return -1;
         }
         analog_set_dialing(p, 1);
      } else {
         /* Call waiting call */
         if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
            ast_copy_string(p->callwait_num, ast_channel_connected(ast)->id.number.str, sizeof(p->callwait_num));
         } else {
            p->callwait_num[0] = '\0';
         }
         if (ast_channel_connected(ast)->id.name.valid && ast_channel_connected(ast)->id.name.str) {
            ast_copy_string(p->callwait_name, ast_channel_connected(ast)->id.name.str, sizeof(p->callwait_name));
         } else {
            p->callwait_name[0] = '\0';
         }

         /* Call waiting tone instead */
         if (analog_callwait(p)) {
            return -1;
         }
         /* Make ring-back */
         if (analog_play_tone(p, ANALOG_SUB_CALLWAIT, ANALOG_TONE_RINGTONE)) {
            ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast_channel_name(ast));
         }

      }
      n = ast_channel_connected(ast)->id.name.valid ? ast_channel_connected(ast)->id.name.str : NULL;
      l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
      if (l) {
         ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
      } else {
         p->lastcid_num[0] = '\0';
      }
      if (n) {
         ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
      } else {
         p->lastcid_name[0] = '\0';
      }

      if (p->use_callerid) {
         p->caller.id.name.str = p->lastcid_name;
         p->caller.id.number.str = p->lastcid_num;
      }

      ast_setstate(ast, AST_STATE_RINGING);
      idx = analog_get_index(ast, p, 0);
      if (idx > -1) {
         struct ast_cc_config_params *cc_params;

         /* This is where the initial ringing frame is queued for an analog call.
          * As such, this is a great time to offer CCNR to the caller if it's available.
          */
         cc_params = ast_channel_get_cc_config_params(p->subs[idx].owner);
         if (cc_params) {
            switch (ast_get_cc_monitor_policy(cc_params)) {
            case AST_CC_MONITOR_NEVER:
               break;
            case AST_CC_MONITOR_NATIVE:
            case AST_CC_MONITOR_ALWAYS:
            case AST_CC_MONITOR_GENERIC:
               ast_queue_cc_frame(p->subs[idx].owner, AST_CC_GENERIC_MONITOR_TYPE,
                  analog_get_orig_dialstring(p), AST_CC_CCNR, NULL);
               break;
            }
         }
         ast_queue_control(p->subs[idx].owner, AST_CONTROL_RINGING);
      }
      break;
   case ANALOG_SIG_FXSLS:
   case ANALOG_SIG_FXSGS:
   case ANALOG_SIG_FXSKS:
      if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
         ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
         p->polaritydelaytv = ast_tvnow();
      }
      /* fall through */
   case ANALOG_SIG_EMWINK:
   case ANALOG_SIG_EM:
   case ANALOG_SIG_EM_E1:
   case ANALOG_SIG_FEATD:
   case ANALOG_SIG_FEATDMF:
   case ANALOG_SIG_E911:
   case ANALOG_SIG_FGC_CAMA:
   case ANALOG_SIG_FGC_CAMAMF:
   case ANALOG_SIG_FEATB:
   case ANALOG_SIG_SFWINK:
   case ANALOG_SIG_SF:
   case ANALOG_SIG_SF_FEATD:
   case ANALOG_SIG_SF_FEATDMF:
   case ANALOG_SIG_FEATDMF_TA:
   case ANALOG_SIG_SF_FEATB:
      c = strchr(dest, '/');
      if (c) {
         c++;
      } else {
         c = "";
      }
      if (strlen(c) < p->stripmsd) {
         ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
         return -1;
      }
      res = analog_start(p);
      if (res < 0) {
         if (errno != EINPROGRESS) {
            return -1;
         }
      }
      ast_debug(1, "Dialing '%s'\n", c);
      p->dop.op = ANALOG_DIAL_OP_REPLACE;

      c += p->stripmsd;

      switch (mysig) {
      case ANALOG_SIG_FEATD:
         l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
         if (l) {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
         } else {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
         }
         break;
      case ANALOG_SIG_FEATDMF:
         l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
         if (l) {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
         } else {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
         }
         break;
      case ANALOG_SIG_FEATDMF_TA:
      {
         const char *cic = "", *ozz = "";

         /* If you have to go through a Tandem Access point you need to use this */
#ifndef STANDALONE
         ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
         if (!ozz) {
            ozz = analog_defaultozz;
         }
         cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
         if (!cic) {
            cic = analog_defaultcic;
         }
#endif
         if (!ozz || !cic) {
            ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
            return -1;
         }
         snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
         snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
         p->whichwink = 0;
      }
         break;
      case ANALOG_SIG_E911:
         ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
         break;
      case ANALOG_SIG_FGC_CAMA:
         snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
         break;
      case ANALOG_SIG_FGC_CAMAMF:
      case ANALOG_SIG_FEATB:
         snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
         break;
      default:
         if (p->pulse) {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
         } else {
            snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
         }
         break;
      }

      if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
         memset(p->echorest, 'w', sizeof(p->echorest) - 1);
         strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
         p->echorest[sizeof(p->echorest) - 1] = '\0';
         p->echobreak = 1;
         p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
      } else {
         p->echobreak = 0;
      }
      analog_set_waitingfordt(p, ast);
      if (!res) {
         if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
            int saveerr = errno;

            analog_on_hook(p);
            ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
            return -1;
         }
      } else {
         ast_debug(1, "Deferring dialing...\n");
      }
      analog_set_dialing(p, 1);
      if (ast_strlen_zero(c)) {
         p->dialednone = 1;
      }
      ast_setstate(ast, AST_STATE_DIALING);
      break;
   default:
      ast_debug(1, "not yet implemented\n");
      return -1;
   }
   return 0;
}
const char* analog_cidstart_to_str ( enum analog_cid_start  cid_start)

Definition at line 234 of file sig_analog.c.

References ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, and ANALOG_CID_START_RING.

{
   switch (cid_start) {
   case ANALOG_CID_START_RING:
      return "Ring";
   case ANALOG_CID_START_POLARITY:
      return "Polarity";
   case ANALOG_CID_START_POLARITY_IN:
      return "Polarity_In";
   case ANALOG_CID_START_DTMF_NOALERT:
      return "DTMF";
   }

   return "Unknown";
}
const char* analog_cidtype_to_str ( unsigned int  cid_type)

Definition at line 149 of file sig_analog.c.

References ARRAY_LEN, and cidtypes.

{
   int i;

   for (i = 0; i < ARRAY_LEN(cidtypes); i++) {
      if (cid_type == cidtypes[i].cid_type) {
         return cidtypes[i].name;
      }
   }

   return "Unknown";
}
int analog_config_complete ( struct analog_pvt p)

Definition at line 3972 of file sig_analog.c.

References analog_set_callwaiting(), ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, analog_pvt::permcallwaiting, and analog_pvt::sig.

Referenced by mkintf().

{
   /* No call waiting on non FXS channels */
   if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS)) {
      p->permcallwaiting = 0;
   }

   analog_set_callwaiting(p, p->permcallwaiting);

   return 0;
}
void analog_delete ( struct analog_pvt doomed)

Delete the analog private structure.

Since:
1.8
Parameters:
doomedAnalog private structure to delete.
Returns:
Nothing

Definition at line 3967 of file sig_analog.c.

References ast_free.

Referenced by destroy_dahdi_pvt().

{
   ast_free(doomed);
}
int analog_dnd ( struct analog_pvt p,
int  flag 
)

Definition at line 4008 of file sig_analog.c.

References ast_verb, analog_pvt::channel, analog_pvt::dnd, EVENT_FLAG_SYSTEM, and manager_event.

Referenced by __analog_ss_thread(), and dahdi_dnd().

{
   if (flag == -1) {
      return p->dnd;
   }

   p->dnd = flag;

   ast_verb(3, "%s DND on channel %d\n",
         flag ? "Enabled" : "Disabled",
         p->channel);
   /*** DOCUMENTATION
      <managerEventInstance>
         <synopsis>Raised when the Do Not Disturb state is changed on an Analog channel.</synopsis>
         <syntax>
            <parameter name="Status">
               <enumlist>
                  <enum name="enabled"/>
                  <enum name="disabled"/>
               </enumlist>
            </parameter>
         </syntax>
      </managerEventInstance>
   ***/
   manager_event(EVENT_FLAG_SYSTEM, "DNDState",
         "Channel: DAHDI/%d\r\n"
         "Status: %s\r\n", p->channel,
         flag ? "enabled" : "disabled");

   return 0;
}
struct ast_frame* analog_exception ( struct analog_pvt p,
struct ast_channel ast 
) [read]

Definition at line 3559 of file sig_analog.c.

References __analog_handle_event(), analog_event2str(), ANALOG_EVENT_HOOKCOMPLETE, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_RINGEROFF, ANALOG_EVENT_RINGERON, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_WINKFLASH, analog_get_event(), analog_get_index, analog_lock_private(), analog_off_hook(), analog_ring(), analog_set_dialing(), analog_set_echocanceller(), analog_set_new_owner(), analog_stop_callwait(), ANALOG_SUB_REAL, analog_unlock_private(), analog_update_conf(), ast_bridged_channel(), ast_channel_fd(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verb, analog_pvt::channel, ast_frame::data, ast_frame::datalen, ast_frame::delivery, f, analog_subchannel::f, analog_pvt::flashtime, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::mallocd, name, ast_frame::offset, analog_subchannel::owner, analog_pvt::owner, ast_frame::ptr, ast_frame::samples, ast_frame::src, ast_frame::subclass, and analog_pvt::subs.

Referenced by dahdi_exception(), and dahdi_read().

{
   int res;
   int idx;
   struct ast_frame *f;

   ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);

   idx = analog_get_index(ast, p, 1);
   if (idx < 0) {
      idx = ANALOG_SUB_REAL;
   }

   p->subs[idx].f.frametype = AST_FRAME_NULL;
   p->subs[idx].f.datalen = 0;
   p->subs[idx].f.samples = 0;
   p->subs[idx].f.mallocd = 0;
   p->subs[idx].f.offset = 0;
   p->subs[idx].f.subclass.integer = 0;
   p->subs[idx].f.delivery = ast_tv(0,0);
   p->subs[idx].f.src = "dahdi_exception";
   p->subs[idx].f.data.ptr = NULL;

   if (!p->owner) {
      /* If nobody owns us, absorb the event appropriately, otherwise
         we loop indefinitely.  This occurs when, during call waiting, the
         other end hangs up our channel so that it no longer exists, but we
         have neither FLASH'd nor ONHOOK'd to signify our desire to
         change to the other channel. */
      res = analog_get_event(p);

      /* Switch to real if there is one and this isn't something really silly... */
      if ((res != ANALOG_EVENT_RINGEROFF) && (res != ANALOG_EVENT_RINGERON) &&
         (res != ANALOG_EVENT_HOOKCOMPLETE)) {
         ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
         analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
         if (p->owner && ast != p->owner) {
            /*
             * Could this even happen?
             * Possible deadlock because we do not have the real-call lock.
             */
            ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
               analog_event2str(res), ast_channel_name(ast), ast_channel_name(p->owner));
         }
         if (p->owner && ast_bridged_channel(p->owner)) {
            ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
         }
      }
      switch (res) {
      case ANALOG_EVENT_ONHOOK:
         analog_set_echocanceller(p, 0);
         if (p->owner) {
            ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
            analog_ring(p);
            analog_stop_callwait(p);
         } else {
            ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
               analog_event2str(res));
         }
         analog_update_conf(p);
         break;
      case ANALOG_EVENT_RINGOFFHOOK:
         analog_set_echocanceller(p, 1);
         analog_off_hook(p);
         if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
            ast_queue_control(p->owner, AST_CONTROL_ANSWER);
            analog_set_dialing(p, 0);
         }
         break;
      case ANALOG_EVENT_HOOKCOMPLETE:
      case ANALOG_EVENT_RINGERON:
      case ANALOG_EVENT_RINGEROFF:
         /* Do nothing */
         break;
      case ANALOG_EVENT_WINKFLASH:
         gettimeofday(&p->flashtime, NULL);
         if (p->owner) {
            ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
            if (ast_channel_state(p->owner) != AST_STATE_UP) {
               /* Answer if necessary */
               ast_queue_control(p->owner, AST_CONTROL_ANSWER);
               ast_setstate(p->owner, AST_STATE_UP);
            }
            analog_stop_callwait(p);
            if (ast_bridged_channel(p->owner)) {
               ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
            }
         } else {
            ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
               analog_event2str(res));
         }
         analog_update_conf(p);
         break;
      default:
         ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", analog_event2str(res));
         break;
      }
      f = &p->subs[idx].f;
      return f;
   }
   ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
   /* If it's not us, return NULL immediately */
   if (ast != p->owner) {
      ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
      f = &p->subs[idx].f;
      return f;
   }

   f = __analog_handle_event(p, ast);
   if (!f) {
      const char *name = ast_strdupa(ast_channel_name(ast));

      /* Tell the CDR this DAHDI device hung up */
      analog_unlock_private(p);
      ast_channel_unlock(ast);
      ast_set_hangupsource(ast, name, 0);
      ast_channel_lock(ast);
      analog_lock_private(p);
   }
   return f;
}
int analog_fixup ( struct ast_channel oldchan,
struct ast_channel newchan,
void *  newp 
)

Definition at line 3990 of file sig_analog.c.

References analog_set_new_owner(), analog_update_conf(), ast_channel_name(), ast_debug, analog_pvt::channel, analog_subchannel::owner, analog_pvt::owner, and analog_pvt::subs.

Referenced by dahdi_fixup().

{
   struct analog_pvt *new_pvt = newp;
   int x;
   ast_debug(1, "New owner for channel %d is %s\n", new_pvt->channel, ast_channel_name(newchan));
   if (new_pvt->owner == oldchan) {
      analog_set_new_owner(new_pvt, newchan);
   }
   for (x = 0; x < 3; x++) {
      if (new_pvt->subs[x].owner == oldchan) {
         new_pvt->subs[x].owner = newchan;
      }
   }

   analog_update_conf(new_pvt);
   return 0;
}
void analog_free ( struct analog_pvt p)

Definition at line 3984 of file sig_analog.c.

References ast_free.

{
   ast_free(p);
}
void analog_handle_dtmf ( struct analog_pvt p,
struct ast_channel ast,
enum analog_sub  index,
struct ast_frame **  dest 
)

Definition at line 1594 of file sig_analog.c.

References analog_cb_handle_dtmf(), analog_check_confirmanswer(), analog_handles_digit(), analog_send_callerid(), analog_set_confirmanswer(), ast_channel_name(), AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, analog_pvt::caller, analog_pvt::callwait_name, analog_pvt::callwait_num, analog_pvt::callwaitcas, f, analog_subchannel::f, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, ast_party_id::name, ast_party_id::number, ast_party_name::str, ast_party_number::str, ast_frame::subclass, and analog_pvt::subs.

Referenced by __analog_handle_event(), and dahdi_read().

{
   struct ast_frame *f = *dest;

   ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
      f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
      f->subclass.integer, f->subclass.integer, ast_channel_name(ast));

   if (analog_check_confirmanswer(p)) {
      if (f->frametype == AST_FRAME_DTMF_END) {
         ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
         /* Upon receiving a DTMF digit, consider this an answer confirmation instead
         of a DTMF digit */
         p->subs[idx].f.frametype = AST_FRAME_CONTROL;
         p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
         /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
         analog_set_confirmanswer(p, 0);
      } else {
         p->subs[idx].f.frametype = AST_FRAME_NULL;
         p->subs[idx].f.subclass.integer = 0;
      }
      *dest = &p->subs[idx].f;
   } else if (p->callwaitcas) {
      if (f->frametype == AST_FRAME_DTMF_END) {
         if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
            ast_debug(1, "Got some DTMF, but it's for the CAS\n");
            p->caller.id.name.str = p->callwait_name;
            p->caller.id.number.str = p->callwait_num;
            analog_send_callerid(p, 1, &p->caller);
         }
         if (analog_handles_digit(f)) {
            p->callwaitcas = 0;
         }
      }
      p->subs[idx].f.frametype = AST_FRAME_NULL;
      p->subs[idx].f.subclass.integer = 0;
      *dest = &p->subs[idx].f;
   } else {
      analog_cb_handle_dtmf(p, ast, idx, dest);
   }
}
void* analog_handle_init_event ( struct analog_pvt i,
int  event 
)

Definition at line 3681 of file sig_analog.c.

References __analog_ss_thread(), analog_cancel_cidspill(), ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, analog_event2str(), ANALOG_EVENT_ALARM, ANALOG_EVENT_DTMFCID, ANALOG_EVENT_NEONMWI_ACTIVE, ANALOG_EVENT_NEONMWI_INACTIVE, ANALOG_EVENT_NOALARM, ANALOG_EVENT_ONHOOK, ANALOG_EVENT_POLARITY, ANALOG_EVENT_REMOVED, ANALOG_EVENT_RINGOFFHOOK, ANALOG_EVENT_WINKFLASH, analog_get_and_handle_alarms(), analog_handle_notify_message(), analog_has_voicemail(), analog_new_ast_channel(), analog_off_hook(), analog_on_hook(), analog_play_tone(), analog_set_alarm(), analog_set_echocanceller(), analog_set_ringtimeout(), ANALOG_SIG_E911, ANALOG_SIG_EM, ANALOG_SIG_EM_E1, ANALOG_SIG_EMWINK, ANALOG_SIG_FEATB, ANALOG_SIG_FEATD, ANALOG_SIG_FEATDMF, ANALOG_SIG_FEATDMF_TA, ANALOG_SIG_FGC_CAMA, ANALOG_SIG_FGC_CAMAMF, ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, ANALOG_SIG_SF, ANALOG_SIG_SF_FEATB, ANALOG_SIG_SF_FEATD, ANALOG_SIG_SF_FEATDMF, ANALOG_SIG_SFWINK, analog_sigtype_to_str(), analog_start_polarityswitch(), ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION, ANALOG_TONE_DIALTONE, ANALOG_TONE_RINGTONE, ANALOG_TONE_STUTTER, ast_callid_threadstorage_auto(), ast_callid_threadstorage_auto_clean(), ast_debug, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, analog_pvt::chan_pvt, analog_pvt::channel, analog_pvt::cid_start, errno, EVENT_FLAG_SYSTEM, analog_pvt::fxsoffhookstate, analog_pvt::hanguponpolarityswitch, analog_pvt::immediate, analog_pvt::inalarm, LOG_NOTICE, LOG_WARNING, manager_event, analog_pvt::polarity, POLARITY_REV, analog_pvt::ringt_base, analog_pvt::sig, and analog_pvt::ss_astchan.

Referenced by do_monitor().

{
   int res;
   pthread_t threadid;
   struct ast_channel *chan;
   struct ast_callid *callid = NULL;
   int callid_created;

   ast_debug(1, "channel (%d) - signaling (%d) - event (%s)\n",
            i->channel, i->sig, analog_event2str(event));

   /* Handle an event on a given channel for the monitor thread. */
   switch (event) {
   case ANALOG_EVENT_WINKFLASH:
   case ANALOG_EVENT_RINGOFFHOOK:
      if (i->inalarm) {
         break;
      }
      /* Got a ring/answer.  What kind of channel are we? */
      switch (i->sig) {
      case ANALOG_SIG_FXOLS:
      case ANALOG_SIG_FXOGS:
      case ANALOG_SIG_FXOKS:
         res = analog_off_hook(i);
         i->fxsoffhookstate = 1;
         if (res && (errno == EBUSY)) {
            break;
         }
         callid_created = ast_callid_threadstorage_auto(&callid);

         /* Cancel VMWI spill */
         analog_cancel_cidspill(i);

         if (i->immediate) {
            analog_set_echocanceller(i, 1);
            /* The channel is immediately up.  Start right away */
            res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
            chan = analog_new_ast_channel(i, AST_STATE_RING, 1, ANALOG_SUB_REAL, NULL);
            if (!chan) {
               ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
               res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
               if (res < 0) {
                  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
               }
            }
         } else {
            /* Check for callerid, digits, etc */
            chan = analog_new_ast_channel(i, AST_STATE_RESERVED, 0, ANALOG_SUB_REAL, NULL);
            i->ss_astchan = chan;
            if (chan) {
               if (analog_has_voicemail(i)) {
                  res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_STUTTER);
               } else {
                  res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_DIALTONE);
               }
               if (res < 0)
                  ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);

               if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
                  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                  res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
                  if (res < 0) {
                     ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
                  }
                  ast_hangup(chan);
               }
            } else
               ast_log(LOG_WARNING, "Unable to create channel\n");
         }
         ast_callid_threadstorage_auto_clean(callid, callid_created);
         break;
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSGS:
      case ANALOG_SIG_FXSKS:
         analog_set_ringtimeout(i, i->ringt_base);
         /* Fall through */
      case ANALOG_SIG_EMWINK:
      case ANALOG_SIG_FEATD:
      case ANALOG_SIG_FEATDMF:
      case ANALOG_SIG_FEATDMF_TA:
      case ANALOG_SIG_E911:
      case ANALOG_SIG_FGC_CAMA:
      case ANALOG_SIG_FGC_CAMAMF:
      case ANALOG_SIG_FEATB:
      case ANALOG_SIG_EM:
      case ANALOG_SIG_EM_E1:
      case ANALOG_SIG_SFWINK:
      case ANALOG_SIG_SF_FEATD:
      case ANALOG_SIG_SF_FEATDMF:
      case ANALOG_SIG_SF_FEATB:
      case ANALOG_SIG_SF:
         callid_created = ast_callid_threadstorage_auto(&callid);
         /* Check for callerid, digits, etc */
         if (i->cid_start == ANALOG_CID_START_POLARITY_IN || i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
            chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
         } else {
            chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL);
         }
         i->ss_astchan = chan;
         if (!chan) {
            ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
         } else if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
            ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
            res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
            if (res < 0) {
               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
            }
            ast_hangup(chan);
         }
         ast_callid_threadstorage_auto_clean(callid, callid_created);
         break;
      default:
         ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
         res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
         if (res < 0) {
            ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
         }
         return NULL;
      }
      break;
   case ANALOG_EVENT_NOALARM:
      analog_set_alarm(i, 0);
      ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
      manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
         "Channel: %d\r\n", i->channel);
      break;
   case ANALOG_EVENT_ALARM:
      analog_set_alarm(i, 1);
      analog_get_and_handle_alarms(i);
      /* fall thru intentionally */
   case ANALOG_EVENT_ONHOOK:
      /* Back on hook.  Hang up. */
      switch (i->sig) {
      case ANALOG_SIG_FXOLS:
      case ANALOG_SIG_FXOGS:
         i->fxsoffhookstate = 0;
         analog_start_polarityswitch(i);
         /* Fall through */
      case ANALOG_SIG_FEATD:
      case ANALOG_SIG_FEATDMF:
      case ANALOG_SIG_FEATDMF_TA:
      case ANALOG_SIG_E911:
      case ANALOG_SIG_FGC_CAMA:
      case ANALOG_SIG_FGC_CAMAMF:
      case ANALOG_SIG_FEATB:
      case ANALOG_SIG_EM:
      case ANALOG_SIG_EM_E1:
      case ANALOG_SIG_EMWINK:
      case ANALOG_SIG_SF_FEATD:
      case ANALOG_SIG_SF_FEATDMF:
      case ANALOG_SIG_SF_FEATB:
      case ANALOG_SIG_SF:
      case ANALOG_SIG_SFWINK:
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSGS:
      case ANALOG_SIG_FXSKS:
         analog_set_echocanceller(i, 0);
         res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
         analog_on_hook(i);
         break;
      case ANALOG_SIG_FXOKS:
         i->fxsoffhookstate = 0;
         analog_start_polarityswitch(i);
         analog_set_echocanceller(i, 0);
         /* Diddle the battery for the zhone */
#ifdef ZHONE_HACK
         analog_off_hook(i);
         usleep(1);
#endif
         res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
         analog_on_hook(i);
         break;
      default:
         ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
         res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
         return NULL;
      }
      break;
   case ANALOG_EVENT_POLARITY:
      switch (i->sig) {
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSKS:
      case ANALOG_SIG_FXSGS:
         callid_created = ast_callid_threadstorage_auto(&callid);
         /* We have already got a PR before the channel was
            created, but it wasn't handled. We need polarity
            to be REV for remote hangup detection to work.
            At least in Spain */
         if (i->hanguponpolarityswitch) {
            i->polarity = POLARITY_REV;
         }
         if (i->cid_start == ANALOG_CID_START_POLARITY || i->cid_start == ANALOG_CID_START_POLARITY_IN) {
            i->polarity = POLARITY_REV;
            ast_verb(2, "Starting post polarity "
               "CID detection on channel %d\n",
               i->channel);
            chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
            i->ss_astchan = chan;
            if (!chan) {
               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
            } else if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
               ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
               ast_hangup(chan);
            }
         }
         ast_callid_threadstorage_auto_clean(callid, callid_created);
         break;
      default:
         ast_log(LOG_WARNING, "handle_init_event detected "
            "polarity reversal on non-FXO (ANALOG_SIG_FXS) "
            "interface %d\n", i->channel);
         break;
      }
      break;
   case ANALOG_EVENT_DTMFCID:
      switch (i->sig) {
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSKS:
      case ANALOG_SIG_FXSGS:
         callid_created = ast_callid_threadstorage_auto(&callid);
         if (i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
            ast_verb(2, "Starting DTMF CID detection on channel %d\n",
               i->channel);
            chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
            i->ss_astchan = chan;
            if (!chan) {
               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
            } else if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
               ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
               ast_hangup(chan);
            }
         }
         ast_callid_threadstorage_auto_clean(callid, callid_created);
         break;
      default:
         ast_log(LOG_WARNING, "handle_init_event detected "
            "dtmfcid generation event on non-FXO (ANALOG_SIG_FXS) "
            "interface %d\n", i->channel);
         break;
      }
      break;
   case ANALOG_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
      ast_log(LOG_NOTICE, "Got ANALOG_EVENT_REMOVED. Destroying channel %d\n",
         i->channel);
      return i->chan_pvt;
   case ANALOG_EVENT_NEONMWI_ACTIVE:
      analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE);
      break;
   case ANALOG_EVENT_NEONMWI_INACTIVE:
      analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_INACTIVE);
      break;
   }
   return NULL;
}
int analog_hangup ( struct analog_pvt p,
struct ast_channel ast 
)

Definition at line 1275 of file sig_analog.c.

References analog_subchannel::allocd, analog_all_subchannels_hungup(), ANALOG_DIGITMODE_DTMF, analog_dsp_set_digitmode(), analog_get_index, analog_hangup_polarityswitch(), analog_is_off_hook(), analog_lock_sub_owner(), analog_on_hook(), analog_play_tone(), analog_set_callwaiting(), analog_set_confirmanswer(), analog_set_dialing(), analog_set_echocanceller(), analog_set_inthreeway(), analog_set_linear_mode(), analog_set_new_owner(), analog_set_outgoing(), analog_set_pulsedial(), analog_set_ringtimeout(), ANALOG_SIG_FXOGS, ANALOG_SIG_FXOKS, ANALOG_SIG_FXOLS, ANALOG_SIG_FXSGS, ANALOG_SIG_FXSKS, ANALOG_SIG_FXSLS, analog_stop_callwait(), ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY, analog_swap_subs(), ANALOG_TONE_CONGESTION, analog_unalloc_sub(), analog_update_conf(), ast_bridged_channel(), ast_channel_name(), ast_channel_setoption(), ast_channel_tech_pvt(), ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_free, ast_log(), AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verb, analog_pvt::callwaitcas, analog_pvt::channel, analog_pvt::cid_name, analog_pvt::cid_num, analog_pvt::cidrings, analog_pvt::guardtime, analog_pvt::hidecallerid, analog_subchannel::inthreeway, LOG_ERROR, LOG_WARNING, analog_pvt::mohsuggest, analog_pvt::onhooktime, analog_pvt::origcid_name, analog_pvt::origcid_num, analog_subchannel::owner, analog_pvt::owner, analog_pvt::permcallwaiting, analog_pvt::permhidecallerid, analog_pvt::polarity, POLARITY_IDLE, S_OR, analog_pvt::sig, and analog_pvt::subs.

Referenced by dahdi_hangup().

{
   int res;
   int idx, x;

   ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
   if (!ast_channel_tech_pvt(ast)) {
      ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
      return 0;
   }

   idx = analog_get_index(ast, p, 1);

   x = 0;
   if (p->origcid_num) {
      ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
      ast_free(p->origcid_num);
      p->origcid_num = NULL;
   }
   if (p->origcid_name) {
      ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
      ast_free(p->origcid_name);
      p->origcid_name = NULL;
   }

   analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);

   ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
      p->channel, idx, p->subs[ANALOG_SUB_REAL].allocd, p->subs[ANALOG_SUB_CALLWAIT].allocd, p->subs[ANALOG_SUB_THREEWAY].allocd);
   if (idx > -1) {
      /* Real channel, do some fixup */
      p->subs[idx].owner = NULL;
      p->polarity = POLARITY_IDLE;
      analog_set_linear_mode(p, idx, 0);
      switch (idx) {
      case ANALOG_SUB_REAL:
         if (p->subs[ANALOG_SUB_CALLWAIT].allocd && p->subs[ANALOG_SUB_THREEWAY].allocd) {
            ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
            if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
               /* We had flipped over to answer a callwait and now it's gone */
               ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
               /* Move to the call-wait, but un-own us until they flip back. */
               analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
               analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
               analog_set_new_owner(p, NULL);
            } else {
               /* The three way hung up, but we still have a call wait */
               ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
               analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
               analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
               if (p->subs[ANALOG_SUB_REAL].inthreeway) {
                  /* This was part of a three way call.  Immediately make way for
                     another call */
                  ast_debug(1, "Call was complete, setting owner to former third call\n");
                  analog_set_inthreeway(p, ANALOG_SUB_REAL, 0);
                  analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
               } else {
                  /* This call hasn't been completed yet...  Set owner to NULL */
                  ast_debug(1, "Call was incomplete, setting owner to NULL\n");
                  analog_set_new_owner(p, NULL);
               }
            }
         } else if (p->subs[ANALOG_SUB_CALLWAIT].allocd) {
            /* Need to hold the lock for real-call, private, and call-waiting call */
            analog_lock_sub_owner(p, ANALOG_SUB_CALLWAIT);
            if (!p->subs[ANALOG_SUB_CALLWAIT].owner) {
               /* The call waiting call dissappeared. */
               analog_set_new_owner(p, NULL);
               break;
            }

            /* Move to the call-wait and switch back to them. */
            analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
            analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
            analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
            if (ast_channel_state(p->owner) != AST_STATE_UP) {
               ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
            }
            if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
               ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
            }
            /* Unlock the call-waiting call that we swapped to real-call. */
            ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner);
         } else if (p->subs[ANALOG_SUB_THREEWAY].allocd) {
            analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
            analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
            if (p->subs[ANALOG_SUB_REAL].inthreeway) {
               /* This was part of a three way call.  Immediately make way for
                  another call */
               ast_debug(1, "Call was complete, setting owner to former third call\n");
               analog_set_inthreeway(p, ANALOG_SUB_REAL, 0);
               analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
            } else {
               /* This call hasn't been completed yet...  Set owner to NULL */
               ast_debug(1, "Call was incomplete, setting owner to NULL\n");
               analog_set_new_owner(p, NULL);
            }
         }
         break;
      case ANALOG_SUB_CALLWAIT:
         /* Ditch the holding callwait call, and immediately make it available */
         if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
            /* Need to hold the lock for call-waiting call, private, and 3-way call */
            analog_lock_sub_owner(p, ANALOG_SUB_THREEWAY);

            /* This is actually part of a three way, placed on hold.  Place the third part
               on music on hold now */
            if (p->subs[ANALOG_SUB_THREEWAY].owner && ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
               ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD,
                  S_OR(p->mohsuggest, NULL),
                  !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
            }
            analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0);
            /* Make it the call wait now */
            analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY);
            analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
            if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
               /* Unlock the 3-way call that we swapped to call-waiting call. */
               ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
            }
         } else {
            analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
         }
         break;
      case ANALOG_SUB_THREEWAY:
         /* Need to hold the lock for 3-way call, private, and call-waiting call */
         analog_lock_sub_owner(p, ANALOG_SUB_CALLWAIT);
         if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
            /* The other party of the three way call is currently in a call-wait state.
               Start music on hold for them, and take the main guy out of the third call */
            analog_set_inthreeway(p, ANALOG_SUB_CALLWAIT, 0);
            if (p->subs[ANALOG_SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[ANALOG_SUB_CALLWAIT].owner)) {
               ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
                  S_OR(p->mohsuggest, NULL),
                  !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
            }
         }
         if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
            ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
         }
         analog_set_inthreeway(p, ANALOG_SUB_REAL, 0);
         /* If this was part of a three way call index, let us make
            another three way call */
         analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
         break;
      default:
         /*
          * Should never happen.
          * This wasn't any sort of call, so how are we an index?
          */
         ast_log(LOG_ERROR, "Index found but not any type of call?\n");
         break;
      }
   }

   if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
      analog_set_new_owner(p, NULL);
      analog_set_ringtimeout(p, 0);
      analog_set_confirmanswer(p, 0);
      analog_set_pulsedial(p, 0);
      analog_set_outgoing(p, 0);
      p->onhooktime = time(NULL);
      p->cidrings = 1;

      /* Perform low level hangup if no owner left */
      res = analog_on_hook(p);
      if (res < 0) {
         ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
      }
      switch (p->sig) {
      case ANALOG_SIG_FXOGS:
      case ANALOG_SIG_FXOLS:
      case ANALOG_SIG_FXOKS:
         /* If they're off hook, try playing congestion */
         if (analog_is_off_hook(p)) {
            analog_hangup_polarityswitch(p);
            analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
         } else {
            analog_play_tone(p, ANALOG_SUB_REAL, -1);
         }
         break;
      case ANALOG_SIG_FXSGS:
      case ANALOG_SIG_FXSLS:
      case ANALOG_SIG_FXSKS:
         /* Make sure we're not made available for at least two seconds assuming
            we were actually used for an inbound or outbound call. */
         if (ast_channel_state(ast) != AST_STATE_RESERVED) {
            time(&p->guardtime);
            p->guardtime += 2;
         }
         break;
      default:
         analog_play_tone(p, ANALOG_SUB_REAL, -1);
         break;
      }

      analog_set_echocanceller(p, 0);

      x = 0;
      ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
      ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
      p->callwaitcas = 0;
      analog_set_callwaiting(p, p->permcallwaiting);
      p->hidecallerid = p->permhidecallerid;
      analog_set_dialing(p, 0);
      analog_update_conf(p);
      analog_all_subchannels_hungup(p);
   }

   analog_stop_callwait(p);

   ast_verb(3, "Hanging up on '%s'\n", ast_channel_name(ast));

   return 0;
}
struct analog_pvt* analog_new ( enum analog_sigtype  signallingtype,
void *  private_data 
) [read]

Definition at line 3937 of file sig_analog.c.

References analog_subchannel::allocd, ANALOG_CID_START_RING, ANALOG_SIG_NONE, ANALOG_SUB_REAL, ast_calloc, analog_pvt::chan_pvt, CID_SIG_BELL, analog_pvt::cid_signalling, analog_pvt::cid_start, analog_pvt::outsigmod, analog_pvt::sig, and analog_pvt::subs.

Referenced by mkintf().

{
   struct analog_pvt *p;

   p = ast_calloc(1, sizeof(*p));
   if (!p) {
      return p;
   }

   p->outsigmod = ANALOG_SIG_NONE;
   p->sig = signallingtype;
   p->chan_pvt = private_data;

   /* Some defaults for values */
   p->cid_start = ANALOG_CID_START_RING;
   p->cid_signalling = CID_SIG_BELL;
   /* Sub real is assumed to always be alloc'd */
   p->subs[ANALOG_SUB_REAL].allocd = 1;

   return p;
}
struct ast_channel* analog_request ( struct analog_pvt p,
int *  callwait,
const struct ast_channel requestor 
) [read]

Definition at line 793 of file sig_analog.c.

References analog_alloc_sub(), analog_new_ast_channel(), analog_set_outgoing(), ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL, ast_debug, ast_log(), AST_STATE_RESERVED, analog_pvt::channel, LOG_ERROR, and analog_pvt::owner.

Referenced by dahdi_request().

{
   struct ast_channel *ast;

   ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
   *callwait = (p->owner != NULL);

   if (p->owner) {
      if (analog_alloc_sub(p, ANALOG_SUB_CALLWAIT)) {
         ast_log(LOG_ERROR, "Unable to alloc subchannel\n");
         return NULL;
      }
   }

   analog_set_outgoing(p, 1);
   ast = analog_new_ast_channel(p, AST_STATE_RESERVED, 0,
      p->owner ? ANALOG_SUB_CALLWAIT : ANALOG_SUB_REAL, requestor);
   if (!ast) {
      analog_set_outgoing(p, 0);
   }
   return ast;
}
const char* analog_sigtype_to_str ( enum analog_sigtype  sigtype)

Definition at line 123 of file sig_analog.c.

References ARRAY_LEN, and sigtypes.

Referenced by __analog_ss_thread(), and analog_handle_init_event().

{
   int i;

   for (i = 0; i < ARRAY_LEN(sigtypes); i++) {
      if (sigtype == sigtypes[i].sigtype) {
         return sigtypes[i].name;
      }
   }

   return "Unknown";
}
int analog_ss_thread_start ( struct analog_pvt p,
struct ast_channel ast 
)

Definition at line 2652 of file sig_analog.c.

References __analog_ss_thread(), and ast_pthread_create_detached.

Referenced by mwi_thread().

{
   pthread_t threadid;

   return ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p);
}
enum analog_cid_start analog_str_to_cidstart ( const char *  value)

Definition at line 219 of file sig_analog.c.

References ANALOG_CID_START_DTMF_NOALERT, ANALOG_CID_START_POLARITY, ANALOG_CID_START_POLARITY_IN, and ANALOG_CID_START_RING.

{
   if (!strcasecmp(value, "ring")) {
      return ANALOG_CID_START_RING;
   } else if (!strcasecmp(value, "polarity")) {
      return ANALOG_CID_START_POLARITY;
   } else if (!strcasecmp(value, "polarity_in")) {
      return ANALOG_CID_START_POLARITY_IN;
   } else if (!strcasecmp(value, "dtmf")) {
      return ANALOG_CID_START_DTMF_NOALERT;
   }

   return 0;
}
unsigned int analog_str_to_cidtype ( const char *  name)

Definition at line 136 of file sig_analog.c.

References ARRAY_LEN, and cidtypes.

{
   int i;

   for (i = 0; i < ARRAY_LEN(cidtypes); i++) {
      if (!strcasecmp(cidtypes[i].name, name)) {
         return cidtypes[i].cid_type;
      }
   }

   return 0;
}
enum analog_sigtype analog_str_to_sigtype ( const char *  name)

Definition at line 110 of file sig_analog.c.

References ARRAY_LEN, and sigtypes.

{
   int i;

   for (i = 0; i < ARRAY_LEN(sigtypes); i++) {
      if (!strcasecmp(sigtypes[i].name, name)) {
         return sigtypes[i].sigtype;
      }
   }

   return 0;
}

Variable Documentation

Global analog callbacks to the upper layer.

Definition at line 3781 of file chan_dahdi.c.

Referenced by analog_all_subchannels_hungup(), analog_alloc_sub(), analog_answer_polarityswitch(), analog_callwait(), analog_cancel_cidspill(), analog_cb_handle_dtmf(), analog_check_confirmanswer(), analog_check_for_conference(), analog_check_waitingfordt(), analog_confmute(), analog_deadlock_avoidance_private(), analog_decrease_ss_count(), analog_dial_digits(), analog_distinctive_ring(), analog_dsp_reset_and_flush_digits(), analog_dsp_set_digitmode(), analog_flash(), analog_get_and_handle_alarms(), analog_get_bridged_channel(), analog_get_callerid(), analog_get_event(), analog_get_orig_dialstring(), analog_get_sub_fd(), analog_handle_notify_message(), analog_hangup_polarityswitch(), analog_has_voicemail(), analog_have_progressdetect(), analog_increase_ss_count(), analog_is_dialing(), analog_is_off_hook(), analog_lock_private(), analog_new_ast_channel(), analog_off_hook(), analog_on_hook(), analog_play_tone(), analog_ring(), analog_send_callerid(), analog_set_alarm(), analog_set_cadence(), analog_set_callwaiting(), analog_set_confirmanswer(), analog_set_dialing(), analog_set_echocanceller(), analog_set_inthreeway(), analog_set_linear_mode(), analog_set_needringing(), analog_set_new_owner(), analog_set_outgoing(), analog_set_pulsedial(), analog_set_ringtimeout(), analog_set_waitingfordt(), analog_start(), analog_start_cid_detect(), analog_start_polarityswitch(), analog_stop_callwait(), analog_stop_cid_detect(), analog_swap_subs(), analog_train_echocanceller(), analog_unalloc_sub(), analog_unlock_private(), analog_update_conf(), analog_wait_event(), and analog_wink().