Example #1
0
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;
}
Example #2
0
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;
	byte			value;

	BUG_ON(!xpd);
	BUG_ON(xpd->direction == TO_PHONE);		// We can SETHOOK state only on PSTN
	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);
	if(to_offhook) {
		BIT_SET(xpd->offhook, pos);
	} else {
		BIT_CLR(xpd->offhook, pos);
	}
	if(caller_id_style != CID_STYLE_PASS_ALWAYS) {
		LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
		BIT_CLR(xpd->cid_on, pos);
	}
#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
	reset_battery_readings(xpd, pos);	/* unstable during hook changes */
	priv->power_denial_safezone[pos] = (to_offhook) ? POWER_DENIAL_SAFEZONE : 0;
	if(!to_offhook)
		priv->power[pos] = POWER_UNKNOWN;
	spin_unlock_irqrestore(&xpd->lock, flags);
	return ret;
}