static int FXO_card_init(xbus_t *xbus, xpd_t *xpd) { struct FXO_priv_data *priv; int i; BUG_ON(!xpd); priv = xpd->priv; // Hanghup all lines for_each_line(xpd, i) { do_sethook(xpd, i, 0); /* will be updated on next battery sample */ priv->polarity[i] = POL_UNKNOWN; priv->polarity_debounce[i] = 0; /* will be updated on next battery sample */ priv->battery[i] = BATTERY_UNKNOWN; /* will be updated on next battery sample */ priv->power[i] = POWER_UNKNOWN; switch (caller_id_style) { case CID_STYLE_ETSI_DTMF: case CID_STYLE_PASSTHROUGH: oht_pcm(xpd, i, 1); break; } priv->polarity_last_interval[i] = POLARITY_LAST_INTERVAL_NONE; }
static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) { unsigned long flags; xbus_t *xbus; struct FXO_priv_data *priv; int ret = 0; __u8 value; BUG_ON(!xpd); /* We can SETHOOK state only on PSTN */ BUG_ON(PHONEDEV(xpd).direction == TO_PHONE); xbus = xpd->xbus; priv = xpd->priv; BUG_ON(!priv); if (priv->battery[pos] != BATTERY_ON && to_offhook) { LINE_NOTICE(xpd, pos, "Cannot take offhook while battery is off!\n"); return -EINVAL; } spin_lock_irqsave(&xpd->lock, flags); mark_ring(xpd, pos, 0, 0); // No more rings value = REG_DAA_CONTROL1_ONHM; /* Bit 3 is for CID */ if (to_offhook) value |= REG_DAA_CONTROL1_OH; LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value, (to_offhook) ? "OFFHOOK" : "ONHOOK"); if (to_offhook) MARK_ON(priv, pos, LED_GREEN); else MARK_OFF(priv, pos, LED_GREEN); ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1, value); mark_offhook(xpd, pos, to_offhook); switch (caller_id_style) { case CID_STYLE_ETSI_DTMF: case CID_STYLE_PASSTHROUGH: break; default: oht_pcm(xpd, pos, 0); break; } #ifdef WITH_METERING priv->metering_count[pos] = 0; priv->metering_tone_state = 0L; DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_METERING, 0x2D); #endif /* unstable during hook changes */ reset_battery_readings(xpd, pos); if (to_offhook) { priv->power_denial_safezone[pos] = power_denial_safezone; } else { priv->power_denial_length[pos] = 0; priv->power_denial_safezone[pos] = 0; } priv->cidtimer[pos] = xpd->timer_count; spin_unlock_irqrestore(&xpd->lock, flags); return ret; }
static void update_dahdi_ring(xpd_t *xpd, int pos, bool on) { BUG_ON(!xpd); if (caller_id_style == CID_STYLE_BELL) oht_pcm(xpd, pos, !on); /* * We should not spinlock before calling dahdi_hooksig() as * it may call back into our xpp_hooksig() and cause * a nested spinlock scenario */ notify_rxsig(xpd, pos, (on) ? DAHDI_RXSIG_RING : DAHDI_RXSIG_OFFHOOK); }
static int FXO_card_init(xbus_t *xbus, xpd_t *xpd) { struct FXO_priv_data *priv; int i; BUG_ON(!xpd); priv = xpd->priv; // Hanghup all lines for_each_line(xpd, i) { do_sethook(xpd, i, 0); /* will be updated on next battery sample */ priv->polarity[i] = POL_UNKNOWN; priv->polarity_debounce[i] = 0; /* will be updated on next battery sample */ priv->battery[i] = BATTERY_UNKNOWN; /* will be updated on next battery sample */ priv->power[i] = POWER_UNKNOWN; if (caller_id_style == CID_STYLE_ETSI_DTMF) oht_pcm(xpd, i, 1); }