+ return 0;
+}
+
+void PmISDN::load_tx(void)
+{
+ int elapsed = 0;
+ int ret;
+ struct timeval current_time;
+
+ /* get elapsed */
+ gettimeofday(¤t_time, NULL);
+ if (p_m_last_tv_sec) {
+ elapsed = 8000 * (current_time.tv_sec - p_m_last_tv_sec)
+ + 8 * (current_time.tv_usec/1000 - p_m_last_tv_msec);
+ }
+ /* set clock of last process! */
+ p_m_last_tv_sec = current_time.tv_sec;
+ p_m_last_tv_msec = current_time.tv_usec/1000;
+
+ /* process only if we have samples and we are active */
+ if (elapsed && p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE) {
+ /* update load */
+ if (elapsed < p_m_load)
+ p_m_load -= elapsed;
+ else
+ p_m_load = 0;
+
+ /* to send data, tone must be on */
+ if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */
+ && (p_m_load < p_m_preload) /* not too much load? */
+ && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones || p_m_inband_send_on)) { /* connected or inband-tones? */
+ int tosend = p_m_preload - p_m_load, length;
+ unsigned char buf[MISDN_HEADER_LEN+tosend];
+ struct mISDNhead *frm = (struct mISDNhead *)buf;
+ unsigned char *p = buf+MISDN_HEADER_LEN;
+
+ /* copy inband signalling (e.g. used by ss5) */
+ if (p_m_inband_send_on && tosend) {
+ tosend -= inband_send(p, tosend);
+ }
+
+ /* copy crypto loops */
+ while (p_m_crypt_msg_loops && tosend) {
+ /* how much do we have to send */
+ length = p_m_crypt_msg_len - p_m_crypt_msg_current;
+
+ /* clip tosend */
+ if (length > tosend)
+ length = tosend;
+
+ /* copy message (part) to buffer */
+ memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
+
+ /* new position */
+ p_m_crypt_msg_current += length;
+ if (p_m_crypt_msg_current == p_m_crypt_msg_len) {
+ /* next loop */
+ p_m_crypt_msg_current = 0;
+ p_m_crypt_msg_loops--;
+ if (!p_m_crypt_msg_loops)
+ update_rxoff();
+// puts("eine loop weniger");
+ }
+
+ /* new length */
+ tosend -= length;
+ }
+
+ /* copy tones */
+ if (p_tone_name[0] && tosend) {
+ tosend -= read_audio(p, tosend);
+ }
+
+ /* send data */
+ if (p_m_preload - p_m_load - tosend > 0) {
+ frm->prim = PH_DATA_REQ;
+ frm->id = 0;
+ ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload-p_m_load-tosend, 0, NULL, 0);
+ if (ret <= 0)
+ PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, p_m_preload-p_m_load-tosend);
+ p_m_load += p_m_preload - p_m_load - tosend;
+ }
+ }
+ }
+
+ if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on || p_m_load) {
+ schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
+ }
+}
+
+/* handle timeouts */
+static int mISDN_timeout(struct lcr_timer *timer, void *instance, int i)
+{
+ class PmISDN *isdnport = (class PmISDN *)instance;
+ struct lcr_msg *message;
+
+ PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", isdnport->p_name, isdnport->p_m_timeout.timeout.tv_sec, isdnport->p_state);
+ /* send timeout to endpoint */
+ message = message_create(isdnport->p_serial, ACTIVE_EPOINT(isdnport->p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
+ message->param.state = isdnport->p_state;
+ message_put(message);
+
+ return 0;
+}
+
+
+/*
+ * whenever we get audio data from bchannel, we process it here
+ */
+void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+{
+ unsigned int cont = *((unsigned int *)data);
+ struct lcr_msg *message;
+ unsigned char *p;
+ int l;
+
+ if (hh->prim == PH_CONTROL_IND) {
+ if (len < 4) {
+ PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
+ return;
+ }
+ if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
+ chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
+ add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
+ if (!p_m_dtmf)
+ add_trace("info", NULL, "DTMF is disabled");
+ end_trace();
+ if (!p_m_dtmf)
+ return;
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
+ message->param.dtmf = cont & DTMF_TONE_MASK;
+ PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c'\n", p_name, message->param.dtmf);
+ message_put(message);
+ return;
+ }
+ switch(cont) {
+ case DSP_BF_REJECT:
+ chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
+ add_trace("DSP-CRYPT", NULL, "error");
+ end_trace();
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
+ message->param.crypt.type = CC_ERROR_IND;
+ PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION reject of blowfish.\n", p_name);
+ message_put(message);
+ break;
+
+ case DSP_BF_ACCEPT:
+ chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
+ add_trace("DSP-CRYPT", NULL, "ok");
+ end_trace();
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
+ message->param.crypt.type = CC_ACTBF_CONF;
+ PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION accept of blowfish.\n", p_name);
+ message_put(message);
+ break;
+
+ default:
+ chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
+ add_trace("unknown", NULL, "0x%x", cont);
+ end_trace();
+ }
+ return;
+ }
+ if (hh->prim == PH_CONTROL_IND) {
+ switch(hh->id) {
+ default:
+ chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
+ add_trace("unknown", NULL, "0x%x", hh->id);
+ end_trace();
+ }
+ return;
+ }
+ if (hh->prim == PH_DATA_REQ || hh->prim == DL_DATA_REQ) {
+ if (!p_m_txdata) {
+ /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
+ PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
+ return;
+ }
+ /* see below (same condition) */
+ if (p_state!=PORT_STATE_CONNECT
+ && !p_m_mISDNport->tones)
+ return;
+// printf(".");fflush(stdout);return;
+ if (p_record)
+ record(data, len, 1); // from up
+ return;
+ }
+ if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND) {
+ PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);