summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c400
-rw-r--r--channels/sig_analog.c386
-rw-r--r--channels/sig_analog.h26
3 files changed, 454 insertions, 358 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 7e545d098..c1e8628d5 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -63,6 +63,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "sig_analog.h"
+/* Analog signaling is currently still present in chan_dahdi for use with
+ * radio. Sig_analog does not currently handle any radio operations. If
+ * radio only uses analog signaling, then the radio handling logic could
+ * be placed in sig_analog and the duplicated code could be removed.
+ */
#ifdef HAVE_PRI
#include "sig_pri.h"
@@ -364,6 +369,37 @@ static const char config[] = "chan_dahdi.conf";
#define CALLPROGRESS_FAX_INCOMING 4
#define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
+#define NUM_CADENCE_MAX 25
+static int num_cadence = 4;
+static int user_has_defined_cadences = 0;
+
+static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
+ { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
+ { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
+ { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
+ { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
+};
+
+/*! \brief cidrings says in which pause to transmit the cid information, where the first pause
+ * is 1, the second pause is 2 and so on.
+ */
+
+static int cidrings[NUM_CADENCE_MAX] = {
+ 2, /*!< Right after first long ring */
+ 4, /*!< Right after long part */
+ 3, /*!< After third chirp */
+ 2, /*!< Second spell */
+};
+
+/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
+static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
+
+#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
+ (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
+
+#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
+#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
+
static char defaultcic[64] = "";
static char defaultozz[64] = "";
@@ -1153,19 +1189,12 @@ static struct dahdi_pvt {
struct ast_event_sub *mwi_event_sub;
/*! \brief Delayed dialing for E911. Overlap digits for ISDN. */
char dialdest[256];
- /*! \brief Time the interface went on-hook. */
- int onhooktime;
- /*! \brief TRUE if the FXS port is off-hook */
- int fxsoffhookstate;
- /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
- int msgstate;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
struct dahdi_vmwi_info mwisend_setting; /*!< Which VMWI methods to use */
unsigned int mwisend_fsk: 1; /*! Variable for enabling FSK MWI handling in chan_dahdi */
unsigned int mwisend_rpas:1; /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
#endif
int distinctivering; /*!< Which distinctivering to use */
- int cidrings; /*!< Which ring to deliver CID on */
int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
/*! \brief Holding place for event injected from outside normal operation. */
int fake_event;
@@ -1177,7 +1206,7 @@ static struct dahdi_pvt {
/*! \brief Start delay time if polarityonanswerdelay is nonzero. */
struct timeval polaritydelaytv;
/*!
- * \brief Send caller ID after this many rings.
+ * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
* \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
*/
int sendcalleridafter;
@@ -1557,6 +1586,7 @@ static int my_stop_cid_detect(void *pvt)
static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
{
struct dahdi_pvt *p = pvt;
+ struct analog_pvt *analog_p = p->sig_pvt;
struct pollfd poller;
char *name, *num;
int index = SUB_REAL;
@@ -1578,9 +1608,9 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
if (poller.revents & POLLIN) {
/*** NOTES ***/
/* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
- * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
- * either a timeout occurss or CID is detected (returns 0). returning 1 should be event received, and -1 should be fail
- * and die */
+ * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
+ * either a timeout occurss or CID is detected (returns 0). returning 1 should be event received, and -1 should be
+ * a failure and die, and returning 2 means no event was received. */
res = read(p->subs[index].dfd, buf, sizeof(buf));
if (res < 0) {
if (errno != ELAST) {
@@ -1589,7 +1619,20 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
return -1;
}
}
- res = callerid_feed(p->cs, buf, res, AST_LAW(p));
+
+ if (analog_p->ringt) {
+ analog_p->ringt--;
+ }
+ if (analog_p->ringt == 1) {
+ return -1;
+ }
+
+ if (p->cid_signalling == CID_SIG_V23_JP) {
+ res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
+ } else {
+ res = callerid_feed(p->cs, buf, res, AST_LAW(p));
+ }
+
if (res < 0) {
ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
return -1;
@@ -1608,7 +1651,128 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e
}
*ev = ANALOG_EVENT_NONE;
- return 1;
+ return 2;
+}
+
+static const char *event2str(int event);
+static int restore_gains(struct dahdi_pvt *p);
+
+static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
+{
+ unsigned char buf[256];
+ int distMatches;
+ int curRingData[3];
+ int receivedRingT;
+ int counter1;
+ int counter;
+ int i;
+ int res;
+ int checkaftercid = 0;
+
+ struct dahdi_pvt *p = pvt;
+ struct analog_pvt *analog_p = p->sig_pvt;
+
+ if (ringdata == NULL) {
+ ringdata = curRingData;
+ } else {
+ checkaftercid = 1;
+ }
+
+ /* We must have a ring by now, so, if configured, lets try to listen for
+ * distinctive ringing */
+ if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
+ /* Clear the current ring data array so we dont have old data in it. */
+ for (receivedRingT = 0; receivedRingT < ARRAY_LEN(ringdata); receivedRingT++)
+ ringdata[receivedRingT] = 0;
+ receivedRingT = 0;
+ if (checkaftercid && distinctiveringaftercid)
+ ast_verb(3, "Detecting post-CID distinctive ring\n");
+ /* Check to see if context is what it should be, if not set to be. */
+ else if (strcmp(p->context,p->defcontext) != 0) {
+ ast_copy_string(p->context, p->defcontext, sizeof(p->context));
+ ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
+ }
+
+ for (;;) {
+ i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
+ if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
+ ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
+ ast_hangup(chan);
+ return 1;
+ }
+ if (i & DAHDI_IOMUX_SIGEVENT) {
+ res = dahdi_get_event(p->subs[idx].dfd);
+ ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
+ res = 0;
+ /* Let us detect distinctive ring */
+
+ ringdata[receivedRingT] = analog_p->ringt;
+
+ if (analog_p->ringt < analog_p->ringt_base/2)
+ break;
+ /* Increment the ringT counter so we can match it against
+ values in chan_dahdi.conf for distinctive ring */
+ if (++receivedRingT == ARRAY_LEN(ringdata))
+ break;
+ } else if (i & DAHDI_IOMUX_READ) {
+ res = read(p->subs[idx].dfd, buf, sizeof(buf));
+ if (res < 0) {
+ if (errno != ELAST) {
+ ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
+ ast_hangup(chan);
+ return 1;
+ }
+ break;
+ }
+ if (analog_p->ringt)
+ analog_p->ringt--;
+ if (analog_p->ringt == 1) {
+ res = -1;
+ break;
+ }
+ }
+ }
+ }
+ if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
+ /* this only shows up if you have n of the dring patterns filled in */
+ ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
+ for (counter = 0; counter < 3; counter++) {
+ /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
+ distMatches = 0;
+ /* this only shows up if you have n of the dring patterns filled in */
+ ast_verb(3, "Checking %d,%d,%d\n",
+ p->drings.ringnum[counter].ring[0],
+ p->drings.ringnum[counter].ring[1],
+ p->drings.ringnum[counter].ring[2]);
+ for (counter1 = 0; counter1 < 3; counter1++) {
+ ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
+ if (p->drings.ringnum[counter].ring[counter1] == -1) {
+ ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
+ ringdata[counter1]);
+ distMatches++;
+ } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
+ ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
+ ast_verb(3, "Ring pattern matched in range: %d to %d\n",
+ (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
+ (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
+ distMatches++;
+ }
+ }
+
+ if (distMatches == 3) {
+ /* The ring matches, set the context to whatever is for distinctive ring.. */
+ ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
+ ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
+ ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
+ break;
+ }
+ }
+ }
+ /* Restore linear mode (if appropriate) for Caller*ID processing */
+ dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
+ restore_gains(p);
+
+ return 0;
}
static int send_callerid(struct dahdi_pvt *p);
@@ -1656,7 +1820,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_callerid *cid)
{
struct dahdi_pvt *p = pvt;
- ast_log(LOG_ERROR, "Starting cid spill\n");
+ ast_debug(2, "Starting cid spill\n");
if (p->cidspill) {
ast_log(LOG_WARNING, "cidspill already exists??\n");
@@ -1809,17 +1973,66 @@ static void my_handle_dtmfup(void *pvt, struct ast_channel *ast, enum analog_sub
static void my_lock_private(void *pvt)
{
struct dahdi_pvt *p = pvt;
-
ast_mutex_lock(&p->lock);
}
static void my_unlock_private(void *pvt)
{
struct dahdi_pvt *p = pvt;
-
ast_mutex_unlock(&p->lock);
}
+static int my_set_linear_mode(void *pvt, int idx, int linear_mode)
+{
+ struct dahdi_pvt *p = pvt;
+ if (!linear_mode)
+ linear_mode = p->subs[idx].linear;
+ return dahdi_setlinear(p->subs[idx].dfd, linear_mode);
+}
+
+static int get_alarms(struct dahdi_pvt *p);
+static void handle_alarms(struct dahdi_pvt *p, int alms);
+static void my_get_and_handle_alarms(void *pvt)
+{
+ int res;
+ struct dahdi_pvt *p = pvt;
+
+ res = get_alarms(p);
+ handle_alarms(p, res);
+}
+
+static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
+{
+ struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
+ if (p)
+ return p->sig_pvt;
+ else
+ return NULL;
+}
+
+static int my_get_sub_fd(void *pvt, enum analog_sub sub)
+{
+ struct dahdi_pvt *p = pvt;
+ int dahdi_sub = analogsub_to_dahdisub(sub);
+ return p->subs[dahdi_sub].dfd;
+}
+
+static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
+{
+ struct dahdi_pvt *p = pvt;
+
+ /* Choose proper cadence */
+ if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
+ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
+ ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
+ *cidrings = cidrings[p->distinctivering - 1];
+ } else {
+ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
+ ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
+ *cidrings = p->sendcalleridafter;
+ }
+}
+
static void my_increase_ss_count(void)
{
ast_mutex_lock(&ss_thread_lock);
@@ -2189,6 +2402,13 @@ static int my_ring(void *pvt)
return dahdi_ring_phone(p);
}
+static int my_flash(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+ int func = DAHDI_FLASH;
+ return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
+}
+
static inline int dahdi_set_hook(int fd, int hs);
static int my_off_hook(void *pvt)
@@ -2263,9 +2483,7 @@ static int my_is_dialing(void *pvt, enum analog_sub sub)
static int my_on_hook(void *pvt)
{
struct dahdi_pvt *p = pvt;
- int x = DAHDI_ONHOOK;
-
- return ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_HOOK, &x);
+ return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
}
#ifdef HAVE_PRI
@@ -2317,8 +2535,6 @@ static int sig_pri_tone_to_dahditone(enum analog_tone tone)
}
}
-static const char *event2str(int event);
-
static void my_handle_dchan_exception(struct sig_pri_pri *pri, int index)
{
int x, res;
@@ -2433,6 +2649,7 @@ static struct analog_callback dahdi_analog_callbacks =
.is_off_hook = my_is_off_hook,
.set_echocanceller = my_set_echocanceller,
.ring = my_ring,
+ .flash = my_flash,
.off_hook = my_off_hook,
.dial_digits = my_dial_digits,
.train_echocanceller = my_train_echocanceller,
@@ -2464,6 +2681,12 @@ static struct analog_callback dahdi_analog_callbacks =
.handle_notify_message = my_handle_notify_message,
.increase_ss_count = my_increase_ss_count,
.decrease_ss_count = my_decrease_ss_count,
+ .distinctive_ring = my_distinctive_ring,
+ .set_linear_mode = my_set_linear_mode,
+ .get_and_handle_alarms = my_get_and_handle_alarms,
+ .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
+ .get_sub_fd = my_get_sub_fd,
+ .set_cadence = my_set_cadence,
};
static struct dahdi_pvt *round_robin[32];
@@ -2492,36 +2715,6 @@ static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
return 0;
}
#endif /* defined(HAVE_SS7) */
-#define NUM_CADENCE_MAX 25
-static int num_cadence = 4;
-static int user_has_defined_cadences = 0;
-
-static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
- { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
- { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
- { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
- { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
-};
-
-/*! \brief cidrings says in which pause to transmit the cid information, where the first pause
- * is 1, the second pause is 2 and so on.
- */
-
-static int cidrings[NUM_CADENCE_MAX] = {
- 2, /*!< Right after first long ring */
- 4, /*!< Right after long part */
- 3, /*!< After third chirp */
- 2, /*!< Second spell */
-};
-
-/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
-static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
-
-#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
- (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
-
-#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
-#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
{
@@ -2673,8 +2866,6 @@ static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
ast_log(LOG_NOTICE, "New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
}
-static int get_alarms(struct dahdi_pvt *p);
-static void handle_alarms(struct dahdi_pvt *p, int alms);
static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
{
int res;
@@ -3051,8 +3242,6 @@ static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
#endif /* HAVE_OPENR2 */
-static int restore_gains(struct dahdi_pvt *p);
-
static void swap_subs(struct dahdi_pvt *p, int a, int b)
{
int tchan;
@@ -4111,29 +4300,6 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
}
#endif
- /* Set the ring cadence */
- mysig = p->sig;
- if (p->outsigmod > -1)
- mysig = p->outsigmod;
- switch (mysig) {
- case SIG_FXOLS:
- case SIG_FXOGS:
- case SIG_FXOKS:
- if (p->owner == ast) {
- /* Choose proper cadence */
- if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
- if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
- ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
- p->cidrings = cidrings[p->distinctivering - 1];
- } else {
- if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
- ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
- p->cidrings = p->sendcalleridafter;
- }
- }
- break;
- }
-
/* If this is analog signalling we can exit here */
if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
p->callwaitrings = 0;
@@ -4142,6 +4308,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
return res;
}
+ mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
switch (mysig) {
case 0:
/* Special pseudo -- automatically up*/
@@ -4877,12 +5044,10 @@ static int dahdi_hangup(struct ast_channel *ast)
p->ringt = 0;
p->distinctivering = 0;
p->confirmanswer = 0;
- p->cidrings = 1;
p->outgoing = 0;
p->digital = 0;
p->faxhandled = 0;
p->pulsedial = 0;
- p->onhooktime = time(NULL);
#if defined(HAVE_PRI) || defined(HAVE_SS7)
p->proceeding = 0;
p->dialing = 0;
@@ -4970,6 +5135,7 @@ static int dahdi_hangup(struct ast_channel *ast)
memset(&par, 0, sizeof(par));
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
if (!res) {
+ struct analog_pvt *analog_p = p->sig_pvt;
#if 0
ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
#endif
@@ -4978,14 +5144,14 @@ static int dahdi_hangup(struct ast_channel *ast)
tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
else
tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
- p->fxsoffhookstate = par.rxisoffhook;
+ analog_p->fxsoffhookstate = par.rxisoffhook;
}
break;
case SIG_FXSGS:
case SIG_FXSLS:
case 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. */
+ we were actually used for an inbound or outbound call. */
if (ast->_state != AST_STATE_RESERVED) {
time(&p->guardtime);
p->guardtime += 2;
@@ -6371,9 +6537,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
- p->onhooktime = time(NULL);
- p->fxsoffhookstate = 0;
- p->msgstate = -1;
/* Check for some special conditions regarding call waiting */
if (idx == SUB_REAL) {
/* The normal line was hung up */
@@ -6524,7 +6687,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
- p->fxsoffhookstate = 1;
switch (ast->_state) {
case AST_STATE_RINGING:
dahdi_enable_ec(p);
@@ -7324,7 +7486,12 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
ast_mutex_unlock(&p->lock);
return &p->subs[idx].f;
} else if (errno == ELAST) {
- f = __dahdi_exception(ast);
+ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
+ struct analog_pvt *analog_p = p->sig_pvt;
+ f = analog_exception(analog_p, ast);
+ } else {
+ f = __dahdi_exception(ast);
+ }
} else
ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
}
@@ -7333,7 +7500,12 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
}
if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
- f = __dahdi_exception(ast);
+ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
+ struct analog_pvt *analog_p = p->sig_pvt;
+ f = analog_exception(analog_p, ast);
+ } else {
+ f = __dahdi_exception(ast);
+ }
ast_mutex_unlock(&p->lock);
return f;
}
@@ -7555,8 +7727,10 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
struct analog_pvt *ap = p->sig_pvt;
- if (ap->dialing)
+ if (ap->dialing) {
+ ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
return 0;
+ }
}
if (p->dialing) {
ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
@@ -8934,8 +9108,9 @@ static void *analog_ss_thread(void *data)
}
break;
}
- if (p->ringt)
+ if (p->ringt) {
p->ringt--;
+ }
if (p->ringt == 1) {
res = -1;
break;
@@ -9488,7 +9663,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
case SIG_FXOGS:
case SIG_FXOKS:
res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
- i->fxsoffhookstate = 1;
if (res && (errno == EBUSY))
break;
if (i->cidspill) {
@@ -9636,9 +9810,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
return -1;
}
- if (i->sig & __DAHDI_SIG_FXO) {
- i->fxsoffhookstate = 0;
- }
break;
case DAHDI_EVENT_POLARITY:
switch (i->sig) {
@@ -9801,12 +9972,13 @@ static void *do_monitor(void *data)
if (!found && ((i == last) || ((i == iflist) && !last))) {
last = i;
if (last) {
+ struct analog_pvt *analog_p = last->sig_pvt;
/* Only allow MWI to be initiated on a quiescent fxs port */
if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO &&
- !last->fxsoffhookstate && !last->owner &&
- !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
+ !analog_p->fxsoffhookstate && !last->owner &&
+ !ast_strlen_zero(last->mailbox) && (thispass - analog_p->onhooktime > 3)) {
res = has_voicemail(last);
- if (last->msgstate != res) {
+ if (analog_p->msgstate != res) {
/* Set driver resources for signalling VMWI */
res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
if (res2) {
@@ -9817,7 +9989,7 @@ static void *do_monitor(void *data)
if (mwi_send_init(last)) {
ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
}
- last->msgstate = res;
+ analog_p->msgstate = res;
found ++;
}
}
@@ -10746,23 +10918,12 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
}
- tmp->msgstate = -1;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
tmp->mwisend_setting = conf->chan.mwisend_setting;
tmp->mwisend_fsk = conf->chan.mwisend_fsk;
tmp->mwisend_rpas = conf->chan.mwisend_rpas;
#endif
- if (chan_sig & __DAHDI_SIG_FXO) {
- memset(&p, 0, sizeof(p));
- res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
- if (!res) {
- tmp->fxsoffhookstate = p.rxisoffhook;
- }
-#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
- res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
-#endif
- }
- tmp->onhooktime = time(NULL);
+
tmp->group = conf->chan.group;
tmp->callgroup = conf->chan.callgroup;
tmp->pickupgroup= conf->chan.pickupgroup;
@@ -10841,7 +11002,6 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
- analog_p->sendcalleridafter = conf->chan.sendcalleridafter;
analog_p->permcallwaiting = 1;
analog_p->callreturn = conf->chan.callreturn;
analog_p->cancallforward = conf->chan.cancallforward;
@@ -10860,7 +11020,23 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
analog_p->stripmsd = conf->chan.stripmsd;
analog_p->cid_start = ANALOG_CID_START_RING;
tmp->callwaitingcallerid = analog_p->callwaitingcallerid = 1;
-
+ analog_p->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
+ analog_p->ringt = conf->chan.ringt;
+ analog_p->ringt_base = ringt_base;
+ analog_p->chan_tech = &dahdi_tech;
+ analog_p->onhooktime = time(NULL);
+ if (chan_sig & __DAHDI_SIG_FXO) {
+ memset(&p, 0, sizeof(p));
+ res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
+ if (!res) {
+ analog_p->fxsoffhookstate = p.rxisoffhook;
+ }
+#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
+ res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
+#endif
+ }
+ analog_p->msgstate = -1;
+
ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index e397e5f4f..e62eb0443 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -38,6 +38,7 @@
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/cel.h"
+#include "asterisk/causes.h"
#include "sig_analog.h"
@@ -89,6 +90,9 @@ static const struct {
* way to do this in the dialplan now. */
};
+#define ISTRUNK(p) ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || \
+ (p->sig == ANALOG_SIG_FXSGS))
+
enum analog_sigtype analog_str_to_sigtype(const char *name)
{
int i;
@@ -397,6 +401,14 @@ static int analog_ring(struct analog_pvt *p)
return -1;
}
+static int analog_flash(struct analog_pvt *p)
+{
+ if (p->calls->flash)
+ return p->calls->flash(p->chan_pvt);
+ else
+ return -1;
+}
+
static int analog_start(struct analog_pvt *p)
{
if (p->calls->start)
@@ -676,6 +688,13 @@ static int analog_callwait(struct analog_pvt *p)
return 0;
}
+static void analog_set_cadence(struct analog_pvt *p, struct ast_channel *chan)
+{
+ if (p->calls->set_cadence) {
+ return p->calls->set_cadence(p->chan_pvt, &p->cidrings, chan);
+ }
+}
+
int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout)
{
int res, index,mysig;
@@ -712,20 +731,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
/* Don't send audio while on hook, until the call is answered */
p->dialing = 1;
- /* XXX */
-#if 0
- /* Choose proper cadence */
- if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
- if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
- ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
- p->cidrings = cidrings[p->distinctivering - 1];
- } else {
- if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
- ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
- p->cidrings = p->sendcalleridafter;
- }
-#endif
- p->cidrings = p->sendcalleridafter;
+ analog_set_cadence(p, ast); /* and set p->cidrings */
/* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
c = strchr(dest, '/');
@@ -1042,13 +1048,10 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
p->owner = NULL;
-#if 0
p->ringt = 0;
-#endif
-#if 0 /* Since we set it in _call */
- p->cidrings = 1;
-#endif
p->outgoing = 0;
+ p->onhooktime = time(NULL);
+ p->cidrings = 1;
/* Perform low level hangup if no owner left */
res = analog_on_hook(p);
@@ -1115,9 +1118,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
case ANALOG_SIG_FXSLS:
case ANALOG_SIG_FXSGS:
case ANALOG_SIG_FXSKS:
-#if 0
p->ringt = 0;
-#endif
/* Fall through */
case ANALOG_SIG_EM:
case ANALOG_SIG_EM_E1:
@@ -1259,13 +1260,47 @@ static int analog_decrease_ss_count(struct analog_pvt *p)
return -1;
}
+static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt *p, int idx, int *ringdata)
+{
+ if (p->calls->distinctive_ring) {
+ return p->calls->distinctive_ring(chan, p->chan_pvt, idx, ringdata);
+ } else
+ return -1;
+
+}
+
+static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode)
+{
+ if (p->calls->set_linear_mode) {
+ return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode);
+ } else
+ return -1;
+}
+
+static void analog_get_and_handle_alarms(struct analog_pvt *p)
+{
+ if (p->calls->get_and_handle_alarms)
+ return p->calls->get_and_handle_alarms(p->chan_pvt);
+}
+
+static void *analog_get_bridged_channel(struct analog_pvt *p, struct ast_channel *chan)
+{
+ if (p->calls->get_sigpvt_bridged_channel)
+ return p->calls->get_sigpvt_bridged_channel;
+ else
+ return NULL;
+}
+
+static int analog_get_sub_fd(struct analog_pvt *p, enum analog_sub sub)
+{
+ if (p->calls->get_sub_fd) {
+ return p->calls->get_sub_fd(p->chan_pvt, sub);
+ } else
+ return -1;
+}
+
#define ANALOG_NEED_MFDETECT(p) (((p)->sig == ANALOG_SIG_FEATDMF) || ((p)->sig == ANALOG_SIG_FEATDMF_TA) || ((p)->sig == ANALOG_SIG_E911) || ((p)->sig == ANALOG_SIG_FGC_CAMA) || ((p)->sig == ANALOG_SIG_FGC_CAMAMF) || ((p)->sig == ANALOG_SIG_FEATB))
-/* Note by jpeeler: This function has a rather large section of code ifdefed
- * away. I'd like to leave the code there until more testing is done and I
- * know for sure that nothing got left out. The plan is at the latest for this
- * comment and code below to be removed shortly after the merging of sig_pri.
- */
static void *__analog_ss_thread(void *data)
{
struct analog_pvt *p = data;
@@ -1279,16 +1314,6 @@ static void *__analog_ss_thread(void *data)
struct callerid_state *cs = NULL;
char *name = NULL, *number = NULL;
int flags;
-#if 0
- unsigned char buf[256];
- int distMatches;
- int curRingData[3];
- int receivedRingT;
- int samples = 0;
- int counter1;
- int counter;
- int i;
-#endif
int timeout;
int getforward = 0;
char *s1, *s2;
@@ -1794,21 +1819,19 @@ static void *__analog_ss_thread(void *data)
memset(exten, 0, sizeof(exten));
timeout = analog_firstdigittimeout;
} else if (!strcmp(exten, "*0")) {
-#ifdef XXX
struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner;
- struct dahdi_pvt *pbridge = NULL;
+ struct analog_pvt *pbridge = NULL;
/* set up the private struct of the bridged one, if any */
if (nbridge && ast_bridged_channel(nbridge))
- pbridge = ast_bridged_channel(nbridge)->tech_pvt;
+ pbridge = analog_get_bridged_channel(p, nbridge);
if (nbridge && pbridge &&
- (nbridge->tech == chan_tech) &&
- (ast_bridged_channel(nbridge)->tech == chan_tech) &&
+ (nbridge->tech == p->chan_tech) &&
+ (ast_bridged_channel(nbridge)->tech == p->chan_tech) &&
ISTRUNK(pbridge)) {
- int func = DAHDI_FLASH;
/* Clear out the dial buffer */
p->dop.dialstr[0] = '\0';
/* flash hookswitch */
- if ((ioctl(pbridge->subs[ANALOG_SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
+ if ((analog_flash(p) == -1) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
nbridge->name, strerror(errno));
}
@@ -1829,7 +1852,6 @@ static void *__analog_ss_thread(void *data)
ast_hangup(chan);
goto quit;
}
-#endif
} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
((exten[0] != '*') || (strlen(exten) > 2))) {
ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
@@ -1855,9 +1877,9 @@ static void *__analog_ss_thread(void *data)
cs = NULL;
ast_debug(1, "Receiving DTMF cid on "
"channel %s\n", chan->name);
-#if 0
- dahdi_setlinear(p->subs[index].dfd, 0);
-#endif
+
+ analog_set_linear_mode(p, index, 0);
+
res = 2000;
for (;;) {
struct ast_frame *f;
@@ -1868,8 +1890,7 @@ static void *__analog_ss_thread(void *data)
ast_hangup(chan);
goto quit;
}
- f = ast_read(chan);
- if (!f)
+ if (!(f = ast_read(chan)))
break;
if (f->frametype == AST_FRAME_DTMF) {
dtmfbuf[i++] = f->subclass;
@@ -1882,9 +1903,9 @@ static void *__analog_ss_thread(void *data)
break; /* Got ring */
}
dtmfbuf[i] = '\0';
-#if 0
- dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#endif
+
+ analog_set_linear_mode(p, index, 1);
+
/* Got cid and ring. */
ast_debug(1, "CID got string '%s'\n", dtmfbuf);
callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
@@ -1895,82 +1916,51 @@ static void *__analog_ss_thread(void *data)
number = dtmfcid;
else
number = NULL;
-#if 0
+
/* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
} else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
- cs = callerid_new(p->cid_signalling);
- if (cs) {
- samples = 0;
-#if 1
- bump_gains(p);
-#endif
- /* Take out of linear mode for Caller*ID processing */
- dahdi_setlinear(p->subs[index].dfd, 0);
-
- /* First we wait and listen for the Caller*ID */
- for (;;) {
- i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
- if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
- ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
- callerid_free(cs);
- ast_hangup(chan);
- goto quit;
+ int timeout = 10000; /* Ten seconds */
+ struct timeval start = ast_tvnow();
+ enum analog_event ev;
+
+ namebuf[0] = 0;
+ numbuf[0] = 0;
+
+ if (!analog_start_cid_detect(p, p->cid_signalling)) {
+ while (1) {
+ res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start));
+
+ if (res == 0) {
+ break;
}
- if (i & DAHDI_IOMUX_SIGEVENT) {
- res = dahdi_get_event(p->subs[index].dfd);
- ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
+ if (res == 1) {
if (p->cid_signalling == CID_SIG_V23_JP) {
-#ifdef DAHDI_EVENT_RINGBEGIN
- if (res == ANALOG_EVENT_RINGBEGIN) {
- res = analog_off_hook(p);
+ if (ev == ANALOG_EVENT_RINGBEGIN) {
+ analog_off_hook(p);
usleep(1);
- }
-#endif
+ }
} else {
- res = 0;
+ ev = ANALOG_EVENT_NONE;
break;
}
- } else if (i & DAHDI_IOMUX_READ) {
- res = read(p->subs[index].dfd, buf, sizeof(buf));
- if (res < 0) {
- if (errno != ELAST) {
- ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
- callerid_free(cs);
- ast_hangup(chan);
- goto quit;
- }
- break;
- }
- samples += res;
-
- if (p->cid_signalling == CID_SIG_V23_JP) {
- res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
- } else {
- res = callerid_feed(cs, buf, res, AST_LAW(p));
- }
-
- if (res < 0) {
- ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
- break;
- } else if (res)
- break;
- else if (samples > (8000 * 10))
- break;
}
+
+ if (ast_tvdiff_ms(ast_tvnow(), start) > timeout)
+ break;
+
}
- if (res == 1) {
- callerid_get(cs, &name, &number, &flags);
- ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
- }
+ name = namebuf;
+ number = numbuf;
+
+ analog_stop_cid_detect(p);
if (p->cid_signalling == CID_SIG_V23_JP) {
res = analog_on_hook(p);
usleep(1);
res = 4000;
} else {
-
- /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
+ /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
res = 2000;
}
@@ -1982,7 +1972,7 @@ static void *__analog_ss_thread(void *data)
"Exiting simple switch\n");
ast_hangup(chan);
goto quit;
- }
+ }
if (!(f = ast_read(chan))) {
ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
ast_hangup(chan);
@@ -1990,18 +1980,19 @@ static void *__analog_ss_thread(void *data)
}
ast_frfree(f);
if (chan->_state == AST_STATE_RING ||
- chan->_state == AST_STATE_RINGING)
+ chan->_state == AST_STATE_RINGING)
break; /* Got ring */
}
+
+ if (analog_distinctive_ring(chan, p, index, NULL))
+ goto quit;
- /* Restore linear mode (if appropriate) for Caller*ID processing */
- dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#if 1
- restore_gains(p);
-#endif
+ if (res < 0) {
+ ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
+ }
} else
- ast_log(LOG_WARNING, "Unable to get caller ID space\n");
-#endif
+ ast_log(LOG_WARNING, "Unable to get caller ID space\n");
+
} else {
ast_log(LOG_WARNING, "Channel %s in prering "
"state, but I have nothing to do. "
@@ -2015,6 +2006,8 @@ static void *__analog_ss_thread(void *data)
int timeout = 10000; /* Ten seconds */
struct timeval start = ast_tvnow();
enum analog_event ev;
+ int curRingData[3] = { 0 };
+ int receivedRingT = 0;
namebuf[0] = 0;
numbuf[0] = 0;
@@ -2027,19 +2020,33 @@ static void *__analog_ss_thread(void *data)
break;
}
- if (res == 1) {
+ if (res == 1 || res == 2) {
if (ev == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
p->polarity = POLARITY_IDLE;
ast_hangup(chan);
goto quit;
- } else if (ev != ANALOG_EVENT_NONE) {
+ } else if (ev != ANALOG_EVENT_NONE && ev != ANALOG_EVENT_RINGBEGIN && ev != ANALOG_EVENT_RINGOFFHOOK) {
break;
}
+ if (res != 2) {
+ /* Let us detect callerid when the telco uses distinctive ring */
+ curRingData[receivedRingT] = p->ringt;
+
+ if (p->ringt < p->ringt_base/2) {
+ break;
+ }
+ /* Increment the ringT counter so we can match it against
+ values in chan_dahdi.conf for distinctive ring */
+ if (++receivedRingT == ARRAY_LEN(curRingData)) {
+ break;
+ }
+ }
}
- if (ast_tvdiff_ms(ast_tvnow(), start) > timeout)
+ if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) {
break;
+ }
}
name = namebuf;
@@ -2047,108 +2054,14 @@ static void *__analog_ss_thread(void *data)
analog_stop_cid_detect(p);
-#if 0
- /* XXX */
- if (strcmp(p->context,p->defcontext) != 0) {
- ast_copy_string(p->context, p->defcontext, sizeof(p->context));
- ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
- }
-
- analog_get_callerid(p, name, number);
- /* FSK Bell202 callerID */
- cs = callerid_new(p->cid_signalling);
- if (cs) {
-#if 1
- bump_gains(p);
-#endif
- samples = 0;
- len = 0;
- distMatches = 0;
- /* Clear the current ring data array so we dont have old data in it. */
- for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
- curRingData[receivedRingT] = 0;
- receivedRingT = 0;
- counter = 0;
- counter1 = 0;
- /* Check to see if context is what it should be, if not set to be. */
-
- /* Take out of linear mode for Caller*ID processing */
- dahdi_setlinear(p->subs[index].dfd, 0);
- for (;;) {
- i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
- if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
- ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
- callerid_free(cs);
- ast_hangup(chan);
- goto quit;
- }
- if (i & DAHDI_IOMUX_SIGEVENT) {
- res = dahdi_get_event(p->subs[index].dfd);
- ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
- /* If we get a PR event, they hung up while processing calerid */
- if ( res == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
- ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
- p->polarity = POLARITY_IDLE;
- callerid_free(cs);
- ast_hangup(chan);
- goto quit;
- }
- res = 0;
- /* Let us detect callerid when the telco uses distinctive ring */
-
- curRingData[receivedRingT] = p->ringt;
+ if (analog_distinctive_ring(chan, p, index, curRingData))
+ goto quit;
- if (p->ringt < p->ringt_base/2)
- break;
- /* Increment the ringT counter so we can match it against
- values in chan_dahdi.conf for distinctive ring */
- if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
- break;
- } else if (i & DAHDI_IOMUX_READ) {
- res = read(p->subs[index].dfd, buf, sizeof(buf));
- if (res < 0) {
- if (errno != ELAST) {
- ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
- callerid_free(cs);
- ast_hangup(chan);
- goto quit;
- }
- break;
- }
- if (p->ringt)
- p->ringt--;
- if (p->ringt == 1) {
- res = -1;
- break;
- }
- samples += res;
- res = callerid_feed(cs, buf, res, AST_LAW(p));
- if (res < 0) {
- ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
- break;
- } else if (res)
- break;
- else if (samples > (8000 * 10))
- break;
- }
- }
- if (res == 1) {
- callerid_get(cs, &name, &number, &flags);
- ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
- }
- /* Restore linear mode (if appropriate) for Caller*ID processing */
- dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#if 1
- restore_gains(p);
-#endif
if (res < 0) {
ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
}
} else
ast_log(LOG_WARNING, "Unable to get caller ID space\n");
-#endif
- } else
- ast_log(LOG_WARNING, "Unable to get caller ID space\n");
}
else
cs = NULL;
@@ -2164,9 +2077,7 @@ static void *__analog_ss_thread(void *data)
ast_setstate(chan, AST_STATE_RING);
chan->rings = 1;
-#if 0
p->ringt = p->ringt_base;
-#endif
res = ast_pbx_run(chan);
if (res) {
ast_hangup(chan);
@@ -2287,15 +2198,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
break;
case ANALOG_EVENT_ALARM:
p->inalarm = 1;
-#if 0
- res = get_alarms(p);
- handle_alarms(p, res);
-#endif
+ analog_get_and_handle_alarms(p);
+
case ANALOG_EVENT_ONHOOK:
switch (p->sig) {
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
case ANALOG_SIG_FXOKS:
+ p->fxsoffhookstate = 0;
+ p->onhooktime = time(NULL);
+ p->msgstate = -1;
/* Check for some special conditions regarding call waiting */
if (index == ANALOG_SUB_REAL) {
/* The normal line was hung up */
@@ -2337,7 +2249,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
/* It hasn't been long enough since the last flashook. This is probably a bounce on
hanging up. Hangup both channels now */
if (p->subs[ANALOG_SUB_THREEWAY].owner)
- ast_queue_hangup(p->subs[ANALOG_SUB_THREEWAY].owner);
+ ast_queue_hangup_with_cause(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
@@ -2427,6 +2339,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
case ANALOG_SIG_FXOKS:
+ p->fxsoffhookstate = 1;
switch (ast->_state) {
case AST_STATE_RINGING:
analog_set_echocanceller(p, 1);
@@ -2484,11 +2397,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
case ANALOG_SIG_FXSLS:
case ANALOG_SIG_FXSGS:
case ANALOG_SIG_FXSKS:
-#if 0
if (ast->_state == AST_STATE_RING) {
p->ringt = p->ringt_base;
}
-#endif
/* Fall through */
case ANALOG_SIG_EM:
@@ -2530,11 +2441,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
case ANALOG_SIG_FXSLS:
case ANALOG_SIG_FXSGS:
case ANALOG_SIG_FXSKS:
-#if 0
if (ast->_state == AST_STATE_RING) {
p->ringt = p->ringt_base;
}
-#endif
break;
}
break;
@@ -2572,10 +2481,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
case ANALOG_SIG_FXOKS:
-#if 0
ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
- index, p->subs[ANALOG_SUB_REAL].dfd, p->subs[ANALOG_SUB_CALLWAIT].dfd, p->subs[ANALOG_SUB_THREEWAY].dfd);
-#endif
+ index, analog_get_sub_fd(p, ANALOG_SUB_REAL), analog_get_sub_fd(p, ANALOG_SUB_CALLWAIT), analog_get_sub_fd(p, ANALOG_SUB_THREEWAY));
+
p->callwaitcas = 0;
if (index != ANALOG_SUB_REAL) {
@@ -3045,6 +2953,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
case ANALOG_SIG_FXOGS:
case ANALOG_SIG_FXOKS:
res = analog_off_hook(i);
+ i->fxsoffhookstate = 1;
if (res && (errno == EBUSY))
break;
if (i->immediate) {
@@ -3083,9 +2992,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
case ANALOG_SIG_FXSLS:
case ANALOG_SIG_FXSGS:
case ANALOG_SIG_FXSKS:
-#if 0
i->ringt = i->ringt_base;
-#endif
/* Fall through */
case ANALOG_SIG_EMWINK:
case ANALOG_SIG_FEATD:
@@ -3139,16 +3046,15 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
break;
case ANALOG_EVENT_ALARM:
i->inalarm = 1;
-#if 0
- res = get_alarms(i);
- handle_alarms(i, res);
-#endif
+ 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;
case ANALOG_SIG_FEATD:
case ANALOG_SIG_FEATDMF:
case ANALOG_SIG_FEATDMF_TA:
@@ -3172,6 +3078,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
analog_on_hook(i);
break;
case ANALOG_SIG_FXOKS:
+ i->fxsoffhookstate = 0;
analog_set_echocanceller(i, 0);
/* Diddle the battery for the zhone */
#ifdef ZHONE_HACK
@@ -3244,7 +3151,6 @@ struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog
p->chan_pvt = private_data;
/* Some defaults for values */
- p->sendcalleridafter = 1;
p->cid_start = ANALOG_CID_START_RING;
p->cid_signalling = CID_SIG_BELL;
/* Sub real is assumed to always be alloc'd */
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index 661179881..89ac6b83d 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -185,6 +185,13 @@ struct analog_callback {
/* callbacks for increasing and decreasing ss_thread_count, will handle locking and condition signal */
void (* const increase_ss_count)(void);
void (* const decrease_ss_count)(void);
+
+ int (* const distinctive_ring)(struct ast_channel *chan, void *pvt, int idx, int *ringdata);
+ int (* const set_linear_mode)(void *pvt, int idx, int linear_mode);
+ void (* const get_and_handle_alarms)(void *pvt);
+ void * (* const get_sigpvt_bridged_channel)(struct ast_channel *chan);
+ int (* const get_sub_fd)(void *pvt, enum analog_sub sub);
+ void (* const set_cadence)(void *pvt, int *cidrings, struct ast_channel *chan);
};
@@ -210,8 +217,12 @@ struct analog_pvt {
/* All members after this are giong to be transient, and most will probably change */
struct ast_channel *owner; /*!< Our current active owner (if applicable) */
- struct analog_subchannel subs[3]; /*!< Sub-channels */
+ struct analog_subchannel subs[3]; /*!< Sub-channels */
struct analog_dialoperation dop;
+ int onhooktime; /*< Time the interface went on-hook. */
+ int fxsoffhookstate; /*< TRUE if the FXS port is off-hook */
+ /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
+ int msgstate;
/* XXX: Option Variables - Set by allocator of private structure */
unsigned int answeronpolarityswitch:1;
@@ -228,17 +239,22 @@ struct analog_pvt {
unsigned int transfer:1;
unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
+ const struct ast_channel_tech *chan_tech;
+ /*!
+ * \brief TRUE if distinctive rings are to be detected.
+ * \note For FXO lines
+ * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
+ */
+ unsigned int usedistinctiveringdetection:1;
/* Not used for anything but log messages. Could be just the TCID */
- int channel; /*!< Channel Number or CRV */
+ int channel; /*!< Channel Number */
enum analog_sigtype outsigmod;
int echotraining;
int cid_signalling; /*!< Asterisk callerid type we're using */
int polarityonanswerdelay;
int stripmsd;
enum analog_cid_start cid_start;
- /* Number of rings to wait to send callerid on FXS. Set to 1 for US */
- int sendcalleridafter;
int callwaitingcallerid;
char mohsuggest[MAX_MUSICCLASS];
char cid_num[AST_MAX_EXTENSION];
@@ -282,10 +298,8 @@ struct analog_pvt {
int callwaitcas;
-#if 0
int ringt;
int ringt_base;
-#endif
};
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog_callback *c, void *private_data);