Esempio n. 1
0
// Break received audio data into manageable chunks, forward them to decoder
void FaxTerminal::rxData(const DataBlock& data, unsigned long tStamp)
{
    unsigned int pos = 0;
    while (pos < data.length())
    {
	// feed the decoder with small chunks of data (16 bytes/ms)
	int len = data.length() - pos;
	if (len > FAX_DATA_CHUNK)
	    len = FAX_DATA_CHUNK;
	rxBlock(((char *)data.data())+pos, len);
	pos += len;
    }
}
Esempio n. 2
0
// Convert endiannes
bool RadioDataFile::fixEndian(DataBlock& buf, unsigned int bytes)
{
    if (!bytes)
	return false;
    unsigned int n = buf.length() / bytes;
    if (bytes == 2) {
	for (uint16_t* p = (uint16_t*)buf.data(); n; n--, p++)
#ifdef LITTLE_ENDIAN
	    *p = be16toh(*p);
#else
	    *p = le16toh(*p);
#endif
	return true;
    }
    if (bytes == 4) {
	for (uint32_t* p = (uint32_t*)buf.data(); n; n--, p++)
#ifdef LITTLE_ENDIAN
	    *p = be32toh(*p);
#else
	    *p = le32toh(*p);
#endif
	return true;
    }
    if (bytes == 8) {
	for (uint64_t* p = (uint64_t*)buf.data(); n; n--, p++)
#ifdef LITTLE_ENDIAN
	    *p = be64toh(*p);
#else
	    *p = le64toh(*p);
#endif
	return true;
    }
    return false;
}
Esempio n. 3
0
    virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags)
	{
	    if (!ref())
		return 0;
	    unsigned long len = 0;
	    if (m_valid && getTransSource() && m_buffer.convert(data,m_sFmt,m_dFmt)) {
		if (tStamp == invalidStamp()) {
		    unsigned int delta = data.length();
		    if (delta > m_buffer.length())
			delta = m_buffer.length();
		    tStamp = m_timestamp + delta;
		}
		m_timestamp = tStamp;
		len = getTransSource()->Forward(m_buffer,tStamp,flags);
	    }
	    deref();
	    return len;
	}
Esempio n. 4
0
// Feed samples to the filter(s)
unsigned long ToneConsumer::Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags)
{
    unsigned int samp = data.length() / 2;
    if (m_mode != Mono)
	samp /= 2;
    if (!samp)
	return 0;
    const int16_t* s = (const int16_t*)data.data();
    if (!s)
	return 0;
    while (samp--) {
	m_xv[0] = m_xv[1]; m_xv[1] = m_xv[2];
	switch (m_mode) {
	    case Left:
		// use 1st sample, skip 2nd
		m_xv[2] = *s++;
		s++;
		break;
	    case Right:
		// skip 1st sample, use 2nd
		s++;
		m_xv[2] = *s++;
		break;
	    case Mixed:
		// add together samples
		m_xv[2] = s[0]+(int)s[1];
		s+=2;
		break;
	    default:
		m_xv[2] = *s++;
	}
	double dx = m_xv[2] - m_xv[0];
	updatePwr(m_pwr,m_xv[2]);

	// update all active detectors
	if (m_detFax)
	    m_fax.update(dx);
	if (m_detCont)
	    m_cont.update(dx);
	if (m_detDtmf || m_detDnis) {
	    for (int j = 0; j < 4; j++) {
		m_dtmfL[j].update(dx);
		m_dtmfH[j].update(dx);
	    }
	}
	// only do checks every millisecond
	if (samp % 8)
	    continue;
	// is it enough total power to accept a signal?
	if (m_pwr >= THRESHOLD2_ABS) {
	    if (m_detDtmf || m_detDnis)
		checkDtmf();
	    if (m_detFax)
		checkFax();
	    if (m_detCont)
		checkCont();
	}
	else {
	    m_dtmfTone = '\0';
	    m_dtmfCount = 0;
	}
    }
    XDebug(&plugin,DebugAll,"Fax detector on %s: signal=%0.1f, total=%0.1f",
	m_id.c_str(),m_fax.value(),m_pwr);
    return invalidStamp();
}
Esempio n. 5
0
// Create a buffer containing the byte representation of a message to be sent
//  and another one with the header
bool ETSIModem::createMsg(NamedList& params, DataBlock& data)
{
    int type = lookup(params,s_msg);
    switch (type) {
	case MsgCallSetup:
	    break;
	case MsgMWI:
	case MsgCharge:
	case MsgSMS:
	    Debug(this,DebugStub,"Create message '%s' not implemented [%p]",
		params.c_str(),this);
	    return false;
	default:
	    Debug(this,DebugNote,"Can't create unknown message '%s' [%p]",
		params.c_str(),this);
	    return false;
    }

    ObjList msg;
    bool fail = !params.getBoolValue("force-send",true);

    // DateTime - ETSI EN 300 659-3 - 5.4.1
    String datetime = params.getValue("datetime");
    unsigned char dt[4];
    bool ok = false;
    if (datetime.isBoolean())
	if (datetime.toBoolean())
	    ok = getDateTime(dt);
	else ;
    else
	ok = getDateTime(dt,&datetime);
    if (ok) {
	DataBlock* dtParam = new DataBlock(0,10);
	unsigned char* d = (unsigned char*)dtParam->data();
	d[0] = DateTime;
	d[1] = 8;
	// Set date and time: %.2d%.2d%.2d%.2d month:day:hour:minute
	for (int i = 0, j = 2; i < 4; i++, j += 2) {
	    d[j] = '0' + dt[i] / 10;
	    d[j+1] = '0' + dt[i] % 10;
	}
	msg.append(dtParam);
    }
    else
	DDebug(this,DebugInfo,"Can't set datetime parameter from '%s' [%p]",
	    datetime.c_str(),this);

    // CallerId/CallerIdReason - ETSI EN 300 659-3 - 5.4.2: Max caller id 20
    // Parameter is missing: append reason (default caller absence: 0x4f: unavailable)
    int res = appendParam(msg,params,CallerId,20,fail);
    if (res == -1)
	return false;
    if (!res)
	appendParam(msg,params,CallerIdReason,s_dict_callerAbsence,0x4f);

    // CallerName/CallerNameReason - ETSI EN 300 659-3 - 5.4.5: Max caller name 50
    // Parameter is missing: append reason (default callername absence: 0x4f: unavailable)
    res = appendParam(msg,params,CallerName,50,fail);
    if (res == -1)
	return false;
    if (!res)
	appendParam(msg,params,CallerNameReason,s_dict_callerAbsence,0x4f);

    // Build message
    unsigned char len = 0;
    unsigned char hdr[2] = {type};
    data.assign(&hdr,sizeof(hdr));

    for (ObjList* o = msg.skipNull(); o; o = o->skipNext()) {
	DataBlock* msgParam = static_cast<DataBlock*>(o->get());
	if (len + msgParam->length() > 255) {
	    if (!fail) {
		Debug(this,DebugNote,"Trucating %s message length to %u bytes [%p]",
		    params.c_str(),data.length(),this);
		break;
	    }
	    params.setParam("error","message-too-long");
	    return false;
	}
	len += msgParam->length();
	data += *msgParam;
    }
    if (!len) {
	params.setParam("error","empty-message");
	return false;
    }

    unsigned char* buf = ((unsigned char*)(data.data()));
    buf[1] = len;
    m_chksum = 0;
    for (unsigned int i = 0; i < data.length(); i++)
	m_chksum += buf[i];
    unsigned char crcVal = 256 - (m_chksum & 0xff);
    FSKModem::addRaw(data,&crcVal,1);
    return true;
}
Esempio n. 6
0
// Process (decode) a valid received buffer. Call recvParams() after decoding the message
// Return false to stop processing data
bool ETSIModem::decode(MsgType msg, const DataBlock& buffer)
{
    NamedList params("");
    DDebug(this,DebugAll,"Decoding message %s [%p]",lookup(msg,s_msg),this);

    unsigned char* data = (unsigned char*)buffer.data();
    for (unsigned int i = 0; i < buffer.length();) {
	unsigned char param = data[i++];                                // Param type
	const char* pname = lookup(param,s_msgParams);
	unsigned int len = data[i++];                                   // Param length (non 0)
	unsigned char* pdata = data + i;
	// End of buffer: Force index outside the end of buffer
	if (i < buffer.length())
	    i += data[i-1];
	else
	    i++;
	if (i > buffer.length()) {
	    Debug(this,DebugWarn,"Unexpected end of %s parameter [%p]",pname,this);
	    return UART::error(UART::EInvalidData);
	}

	String tmp;

#define CHECK_LEN(expected) \
	if (len != expected) { \
	    Debug(this,DebugNote,"Invalid len=%u (expected %u) for %s parameter [%p]",len,expected,pname,this); \
	    continue; \
	}
#define SET_PARAM_FROM_DATA(paramname) \
	tmp.assign((char*)pdata,len); \
	params.addParam(paramname,tmp);
#define SET_PARAM_FROM_DICT(paramname,dict) \
	tmp = lookup(*pdata,dict,"unknown"); \
	params.addParam(paramname,tmp);
	// Process parameters
	// References are the sections from ETSI EN 300 659-3
	switch (param) {
	    case CallerId:               // 5.4.2
		SET_PARAM_FROM_DATA("caller")
		break;
	    case CallerName:             // 5.4.5
		SET_PARAM_FROM_DATA("callername")
		break;
	    case CallerIdReason:         // 5.4.4
		CHECK_LEN(1)
		SET_PARAM_FROM_DICT("callerpres",s_dict_callerAbsence)
		break;
	    case CallerNameReason:       // 5.4.6
		CHECK_LEN(1)
		SET_PARAM_FROM_DICT("callernamepres",s_dict_callerAbsence)
		break;
	    case DateTime:               // 5.4.1
		CHECK_LEN(8)
		setDateTime(tmp,(char*)pdata,8);
		params.addParam("datetime",tmp);
		break;
	    case CompDateTime:           // 5.4.10
		if (param == CompDateTime && len != 8 && len != 10) {
		    Debug(this,DebugNote,
			"Invalid len=%u (expected 8 or 10) for %s parameter [%p]",len,pname,this);
		    continue;
		}
		setDateTime(tmp,(char*)pdata,len);
		params.addParam("service_datetime",tmp);
		break;
	    case CalledId:               // 5.4.3
		SET_PARAM_FROM_DATA("called")
		break;
	    case CallType:               // 5.4.12
		CHECK_LEN(1)
		SET_PARAM_FROM_DICT("calltype",s_dict_callType)
		break;
	    case CallerType:             // 5.4.16
		CHECK_LEN(1)
		SET_PARAM_FROM_DICT("originator_type",s_dict_callerType)
		break;
	    case VisualIndicator:        // 5.4.7
		CHECK_LEN(1)
		if (*pdata == 0 || *pdata == 255)
		    tmp = String::boolText(*pdata != 0);
		else
		    tmp = (int)(*pdata);
		params.addParam("visualindicator",tmp);
		break;
	    case MessageId:              // 5.4.8
		CHECK_LEN(3)
		SET_PARAM_FROM_DICT("message_status",s_dict_mwiStatus)
		params.addParam("message_ref",String(net2short(pdata + 1)));
		DDebug(this,DebugInfo,
		    "Decoded %s parameter (status=%s ref=%d) [%p]",
		    pname,tmp.c_str(),net2short(pdata + 1),this);
		continue;
	    case LastMsgCLI:             // 5.4.9
		SET_PARAM_FROM_DATA("message_caller")
		break;
	    case CompCallerId:           // 5.4.11
		SET_PARAM_FROM_DATA("caller_networkprovided")
		break;
	    case FirstCalledId:          // 5.4.13
		SET_PARAM_FROM_DATA("ffwd_first")
		break;
	    case MWICount:               // 5.4.14
		CHECK_LEN(1)
		tmp = (int)(*pdata);
		params.addParam("message_count",tmp);
		break;
	    case FwdCallType:            // 5.4.15
		CHECK_LEN(1)
		SET_PARAM_FROM_DICT("ffwd_reason",s_dict_ffwdReason)
		break;
	    case RedirNumber:            // 5.4.17
		SET_PARAM_FROM_DATA("ffwd_last")
		break;
	    case Charge:                 // 5.4.18
	        Debug(this,DebugStub,"Skipping %s parameter [%p]",pname,this);
		continue;
	    case AdditionalCharge:       // 5.4.19
	        Debug(this,DebugStub,"Skipping %s parameter [%p]",pname,this);
		continue;
	    case Duration:               // 5.4.20
		CHECK_LEN(6)
		setDateTime(tmp,(char*)pdata,6);
		params.addParam("duration",tmp);
		break;
	    case NetworkID:              // 5.4.21
		SET_PARAM_FROM_DATA("netid")
		break;
	    case CarrierId:              // 5.4.22
		SET_PARAM_FROM_DATA("carrierid")
		break;
	    case SelectFunction:         // 5.4.23
	        Debug(this,DebugStub,"Skipping %s parameter [%p]",pname,this);
		continue;
	    case Display:                // 5.4.24
	        Debug(this,DebugStub,"Skipping %s parameter [%p]",pname,this);
		continue;
	    case ServiceInfo:            // 5.4.25
		CHECK_LEN(1)
		if (*pdata > 1)
		    tmp = (int)(*pdata);
		else
		    tmp = *pdata ? "active" : "not-active";
		params.addParam("service_info",tmp);
		break;
	    case Extension:              // 5.4.26
	        Debug(this,DebugStub,"Skipping %s parameter [%p]",pname,this);
		continue;
	}
#undef SET_PARAM_FROM_DATA
#undef SET_PARAM_FROM_DICT
#undef CHECK_LEN

	DDebug(this,DebugAll,"Decoded %s=%s [%p]",pname,tmp.c_str(),this);
    }
    if (recvParams(msg,params))
	return true;
    return UART::error(EStopped);
}
Esempio n. 7
0
// Handle received digital data
void T38Terminal::rxData(const DataBlock& data, unsigned long tStamp)
{
    t38_core_rx_ifp_packet(t38_get_t38_state(&m_t38),(uint8_t*)data.data(),data.length(),tStamp & 0xffff);
}