+ /* set dsp features */
+ if (port->p_m_txdata)
+ ph_control(mISDNport, port, handle, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
+ if (port->p_m_delay)
+ ph_control(mISDNport, port, handle, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
+ if (port->p_m_txvol)
+ ph_control(mISDNport, port, handle, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
+ if (port->p_m_rxvol)
+ ph_control(mISDNport, port, handle, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
+ if (port->p_m_conf)
+ ph_control(mISDNport, port, handle, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
+ if (port->p_m_echo)
+ ph_control(mISDNport, port, handle, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
+ if (port->p_m_tone)
+ ph_control(mISDNport, port, handle, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
+ if (port->p_m_rxoff)
+ ph_control(mISDNport, port, handle, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
+// if (port->p_m_txmix)
+// ph_control(mISDNport, port, handle, CMX_MIX_ON, 0, "DSP-MIX", 1);
+ if (port->p_m_dtmf)
+ ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
+ if (port->p_m_crypt)
+ ph_control_block(mISDNport, port, handle, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
+}
+
+/*
+ * subfunction for bchannel_event
+ * destroy stack
+ */
+static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
+{
+#ifdef SOCKET_MISDN
+ chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
+ add_trace("channel", NULL, "%d", i+1+(i>=15));
+ add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
+ end_trace();
+ if (mISDNport->b_socket[i] > -1)
+ {
+ close(mISDNport->b_socket[i]);
+ mISDNport->b_socket[i] = -1;
+ }
+#else
+ unsigned char buff[1024];
+
+ chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
+ add_trace("channel", NULL, "%d", i+1+(i>=15));
+ add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
+ add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
+ end_trace();
+ /* remove our stack only if set */
+ if (mISDNport->b_addr[i])
+ {
+ PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
+ mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
+ mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+ mISDNport->b_addr[i] = 0;
+ }
+#endif
+}
+
+
+/*
+bchannel procedure
+------------------
+
+A bchannel goes through the following states in this order:
+
+- B_STATE_IDLE
+No one is using the bchannel.
+It is available and not linked to Port class, nor reserved.
+
+- B_STATE_ACTIVATING
+The bchannel stack is created and an activation request is sent.
+It MAY be linked to Port class, but already unlinked due to Port class removal.
+
+- B_STATE_ACTIVE
+The bchannel is active and cofigured to the Port class needs.
+Also it is linked to a Port class, otherwhise it would be deactivated.
+
+- B_STATE_DEACTIVATING
+The bchannel is in deactivating state, due to deactivation request.
+It may be linked to a Port class, that likes to reactivate it.
+
+- B_STATE_IDLE
+See above.
+After deactivating bchannel, and if not used, the bchannel becomes idle again.
+
+Also the bchannel may be exported, but only if the state is or becomes idle:
+
+- B_STATE_EXPORTING
+The bchannel assignment has been sent to the remove application.
+
+- B_STATE_REMOTE
+The bchannel assignment is acknowledged by the remote application.
+
+- B_STATE_IMPORTING
+The bchannel is re-imported by mISDN port object.
+
+- B_STATE_IDLE
+See above.
+After re-importing bchannel, and if not used, the bchannel becomes idle again.
+
+
+A bchannel can have the following events:
+
+- B_EVENT_USE
+A bchannel is required by a Port class.
+The bchannel shall be exported to the remote application.
+
+- B_EVENT_ACTIVATED
+The bchannel beomes active.
+
+- B_EVENT_DROP
+The bchannel is not required by Port class anymore
+
+- B_EVENT_DEACTIVATED
+The bchannel becomes inactive.
+
+- B_EVENT_EXPORTED
+The bchannel is now used by remote application.
+
+- B_EVENT_IMPORTED
+The bchannel is not used by remote application.
+
+All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
+
+if an export request is receive by remote application, p_m_remote_* is set.
+the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
+- set on export request from remote application (if port is assigned)
+- set on channel use, if requested by remote application (p_m_remote_*)
+- cleared on drop request
+
+the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
+the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
+the bchannel import/export is acknowledged with stack given.
+
+if exporting, b_remote_*[index] is set to the remote socket id.
+if importing has been acknowledged. b_remote_*[index] is cleared.
+
+*/
+
+/*
+ * process bchannel events
+ * - mISDNport is a pointer to the port's structure
+ * - i is the index of the bchannel
+ * - event is the B_EVENT_* value
+ * - port is the PmISDN class pointer
+ */
+void bchannel_event(struct mISDNport *mISDNport, int i, int event)
+{
+ class PmISDN *b_port = mISDNport->b_port[i];
+ int state = mISDNport->b_state[i];
+ unsigned long p_m_remote_ref = 0;
+ unsigned long p_m_remote_id = 0;
+#ifdef SOCKET_MISDN
+ unsigned long portid = (mISDNport->portnum<<8) + i+1+(i>=15);
+#else
+ unsigned long portid = mISDNport->b_addr[i];
+#endif
+
+ if (b_port)