1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** mISDN port abstraction for dss1 and sip **
10 \*****************************************************************************/
16 #include <sys/ioctl.h>
17 #include <sys/types.h>
21 #include <netinet/udp.h>
22 #include <netinet/in.h>
24 #include <sys/socket.h>
26 #include <linux/mISDNif.h>
35 #ifndef ISDN_PID_L4_B_USER
36 #define ISDN_PID_L4_B_USER 0x440000ff
39 /* list of mISDN ports */
40 struct mISDNport *mISDNport_first;
42 /* noise randomizer */
43 unsigned char mISDN_rand[256];
44 int mISDN_rand_count = 0;
47 int mISDN_initialize(void)
49 /* try to open raw socket to check kernel */
50 ret = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
53 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
58 init_layer3(4); // buffer of 4
63 void mISDN_deinitialize(void)
68 int entity = 0; /* used for udevice */
69 int mISDNdevice = -1; /* the device handler and port list */
71 int mISDN_initialize(void)
74 unsigned char buff[1025];
75 iframe_t *frm = (iframe_t *)buff;
78 /* initialize stuff of the NT lib */
79 if (options.deb & DEBUG_STACK)
81 global_debug = 0xffffffff & ~DBGM_MSG;
82 // global_debug = DBGM_L3DATA;
84 global_debug = DBGM_MAN;
85 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
86 if (options.deb & DEBUG_LOG)
87 debug_init(global_debug, debug_log, debug_log, debug_log);
89 debug_init(global_debug, NULL, NULL, NULL);
92 /* open mISDNdevice if not already open */
98 fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
102 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
104 /* create entity for layer 3 TE-mode */
105 mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
106 ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
107 if (ret < (int)mISDN_HEADER_LEN)
110 FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
112 entity = frm->dinfo & 0xffff;
115 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
120 void mISDN_deinitialize(void)
122 unsigned char buff[1025];
126 if (mISDNdevice >= 0)
129 mISDN_write_frame(mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
131 mISDN_close(mISDNdevice);
133 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
141 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
143 p_m_mISDNport = mISDNport;
144 p_m_portnum = mISDNport->portnum;
151 p_m_txvol = p_m_rxvol = 0;
159 p_m_dtmf = !mISDNport->ifport->nodtmf;
169 p_m_crypt_listen = 0;
170 p_m_crypt_msg_loops = 0;
171 p_m_crypt_msg_loops = 0;
172 p_m_crypt_msg_len = 0;
173 p_m_crypt_msg[0] = '\0';
174 p_m_crypt_msg_current = 0;
175 p_m_crypt_key[0] = '\0';
176 p_m_crypt_key_len = 0;
177 p_m_crypt_listen = 0;
178 p_m_crypt_listen_state = 0;
179 p_m_crypt_listen_len = 0;
180 p_m_crypt_listen_msg[0] = '\0';
181 p_m_crypt_listen_crc = 0;
183 /* if any channel requested by constructor */
184 if (channel == CHANNEL_ANY)
186 /* reserve channel */
188 mISDNport->b_reserved++;
191 /* reserve channel */
192 if (channel > 0) // only if constructor was called with a channel resevation
193 seize_bchannel(channel, exclusive);
195 /* we increase the number of objects: */
197 PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
206 struct message *message;
208 /* remove bchannel relation */
214 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
215 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
216 message->param.disconnectinfo.cause = 16;
217 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
218 message_put(message);
219 /* remove from list */
220 free_epointlist(p_epointlist);
223 /* we decrease the number of objects: */
224 p_m_mISDNport->use--;
225 PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
232 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
234 /* init trace with given values */
235 start_trace(mISDNport?mISDNport->portnum:0,
236 (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
237 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
238 port?port->p_dialinginfo.id:NULL,
241 port?port->p_serial:0,
249 static struct isdn_message {
253 {"TIMEOUT", CC_TIMEOUT},
255 {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
256 {"PROCEEDING", CC_PROCEEDING},
257 {"ALERTING", CC_ALERTING},
258 {"CONNECT", CC_CONNECT},
259 {"CONNECT RES", CC_CONNECT},
260 {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
261 {"DISCONNECT", CC_DISCONNECT},
262 {"RELEASE", CC_RELEASE},
263 {"RELEASE_COMP", CC_RELEASE_COMPLETE},
264 {"INFORMATION", CC_INFORMATION},
265 {"PROGRESS", CC_PROGRESS},
266 {"NOTIFY", CC_NOTIFY},
267 {"SUSPEND", CC_SUSPEND},
268 {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
269 {"SUSPEND_REJ", CC_SUSPEND_REJECT},
270 {"RESUME", CC_RESUME},
271 {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
272 {"RESUME_REJ", CC_RESUME_REJECT},
274 {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
275 {"HOLD_REJ", CC_HOLD_REJECT},
276 {"RETRIEVE", CC_RETRIEVE},
277 {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
278 {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
279 {"FACILITY", CC_FACILITY},
280 {"STATUS", CC_STATUS},
281 {"RESTART", CC_RESTART},
282 {"RELEASE_CR", CC_RELEASE_CR},
283 {"NEW_CR", CC_NEW_CR},
284 {"DL_ESTABLISH", DL_ESTABLISH},
285 {"DL_RELEASE", DL_RELEASE},
286 {"PH_ACTIVATE", PH_ACTIVATE},
287 {"PH_DEACTIVATE", PH_DEACTIVATE},
291 static char *isdn_prim[4] = {
297 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
300 char msgtext[64] = "<<UNKNOWN MESSAGE>>";
302 /* select message and primitive text */
304 while(isdn_message[i].name)
306 if (isdn_message[i].value == (prim&0xffffff00))
308 SCPY(msgtext, isdn_message[i].name);
313 SCAT(msgtext, isdn_prim[prim&0x00000003]);
316 if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
320 if (mISDNport->ntmode)
322 if (direction == DIRECTION_OUT)
323 SCAT(msgtext, " N->U");
325 SCAT(msgtext, " N<-U");
328 if (direction == DIRECTION_OUT)
329 SCAT(msgtext, " U->N");
331 SCAT(msgtext, " U<-N");
336 /* init trace with given values */
337 start_trace(mISDNport?mISDNport->portnum:0,
338 mISDNport?mISDNport->ifport->interface:NULL,
339 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
340 port?port->p_dialinginfo.id:NULL,
343 port?port->p_serial:0,
349 * send control information to the channel (dsp-module)
351 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, int c2, char *trace_name, int trace_value)
353 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
354 iframe_t *ctrl = (iframe_t *)buffer;
355 unsigned long *d = (unsigned long *)&ctrl->data.p;
357 ctrl->prim = PH_CONTROL | REQUEST;
358 ctrl->addr = b_addr | FLG_MSG_DOWN;
360 ctrl->len = sizeof(int)*2;
363 mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
364 chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
365 if (c1 == CMX_CONF_JOIN)
366 add_trace(trace_name, NULL, "0x%08x", trace_value);
368 add_trace(trace_name, NULL, "%d", trace_value);
372 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, void *c2, int c2_len, char *trace_name, int trace_value)
374 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
375 iframe_t *ctrl = (iframe_t *)buffer;
376 unsigned long *d = (unsigned long *)&ctrl->data.p;
378 ctrl->prim = PH_CONTROL | REQUEST;
379 ctrl->addr = b_addr | FLG_MSG_DOWN;
381 ctrl->len = sizeof(int)+c2_len;
383 memcpy(d, c2, c2_len);
384 mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
385 chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
386 add_trace(trace_name, NULL, "%d", trace_value);
392 * subfunction for bchannel_event
395 static int _bchannel_create(struct mISDNport *mISDNport, int i)
397 unsigned char buff[1024];
402 if (!mISDNport->b_stid[i])
404 PERROR("Error: no stack for index %d\n", i);
407 if (mISDNport->b_addr[i])
409 PERROR("Error: stack already created for index %d\n", i);
413 /* create new layer */
414 PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
415 memset(&li, 0, sizeof(li));
416 memset(&pid, 0, sizeof(pid));
419 li.st = mISDNport->b_stid[i];
420 UCPY(li.name, "B L4");
421 li.pid.layermask = ISDN_LAYER((4));
422 li.pid.protocol[4] = ISDN_PID_L4_B_USER;
423 ret = mISDN_new_layer(mISDNdevice, &li);
427 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
430 mISDNport->b_addr[i] = li.id;
433 goto failed_new_layer;
435 PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
437 /* create new stack */
438 pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
439 pid.protocol[2] = ISDN_PID_L2_B_TRANS;
440 pid.protocol[3] = ISDN_PID_L3_B_DSP;
441 pid.protocol[4] = ISDN_PID_L4_B_USER;
442 pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
443 ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
447 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
448 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
451 ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
456 mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
457 if (!mISDNport->b_addr[i])
459 chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
460 add_trace("channel", NULL, "%d", i+1+(i>=15));
461 add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
462 add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
468 mISDNport->b_addr[i] = 0;
474 * subfunction for bchannel_event
477 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
481 /* activate bchannel */
482 chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
483 add_trace("channel", NULL, "%d", i+1+(i>=15));
485 act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST;
486 act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
489 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
494 * subfunction for bchannel_event
497 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
502 port = mISDNport->b_port[i];
503 addr = mISDNport->b_addr[i];
506 PERROR("bchannel index i=%d not associated with a port object\n", i);
510 /* set dsp features */
511 if (port->p_m_txdata)
512 ph_control(mISDNport, port, addr, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
514 ph_control(mISDNport, port, addr, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
516 ph_control(mISDNport, port, addr, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
518 ph_control(mISDNport, port, addr, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
520 ph_control(mISDNport, port, addr, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
522 ph_control(mISDNport, port, addr, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
524 ph_control(mISDNport, port, addr, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
526 ph_control(mISDNport, port, addr, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
527 // if (port->p_m_txmix)
528 // ph_control(mISDNport, port, addr, CMX_MIX_ON, 0, "DSP-MIX", 1);
530 ph_control(mISDNport, port, addr, DTMF_TONE_START, 0, "DSP-DTMF", 1);
532 ph_control_block(mISDNport, port, addr, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
536 * subfunction for bchannel_event
539 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
541 unsigned char buff[1024];
543 chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
544 add_trace("channel", NULL, "%d", i+1+(i>=15));
545 add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
546 add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
548 /* remove our stack only if set */
549 if (mISDNport->b_addr[i])
551 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
552 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
553 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
554 mISDNport->b_addr[i] = 0;
563 A bchannel goes through the following states in this order:
566 No one is using the bchannel.
567 It is available and not linked to Port class, nor reserved.
570 The bchannel stack is created and an activation request is sent.
571 It MAY be linked to Port class, but already unlinked due to Port class removal.
574 The bchannel is active and cofigured to the Port class needs.
575 Also it is linked to a Port class, otherwhise it would be deactivated.
577 - B_STATE_DEACTIVATING
578 The bchannel is in deactivating state, due to deactivation request.
579 It may be linked to a Port class, that likes to reactivate it.
583 After deactivating bchannel, and if not used, the bchannel becomes idle again.
586 A bchannel can have the following events:
589 A bchannel is required by a Port class.
592 The bchannel beomes active.
595 The bchannel is not required by Port class anymore
597 - B_EVENT_DEACTIVATED
598 The bchannel becomes inactive.
600 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
605 * process bchannel events
606 * - mISDNport is a pointer to the port's structure
607 * - i is the index of the bchannel
608 * - event is the B_EVENT_* value
609 * - port is the PmISDN class pointer
611 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
613 int state = mISDNport->b_state[i];
617 case B_EVENT_ACTIVATE:
618 /* port must be linked in order to allow activation */
619 if (!mISDNport->b_port[i])
620 FATAL("bchannel must be linked to a Port class\n");
624 /* create stack and send activation request */
625 if (_bchannel_create(mISDNport, i))
627 _bchannel_activate(mISDNport, i, 1);
628 state = B_STATE_ACTIVATING;
632 case B_STATE_ACTIVATING:
633 /* do nothing, because it is already activating */
636 case B_STATE_DEACTIVATING:
637 /* do nothing, because we must wait until we can reactivate */
641 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
645 case B_EVENT_ACTIVATED:
648 case B_STATE_ACTIVATING:
649 if (mISDNport->b_port[i])
651 /* bchannel is active and used by Port class, so we configure bchannel */
652 _bchannel_configure(mISDNport, i);
653 state = B_STATE_ACTIVE;
656 /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */
657 _bchannel_activate(mISDNport, i, 0);
658 state = B_STATE_DEACTIVATING;
663 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
667 case B_EVENT_DEACTIVATE:
668 if (!mISDNport->b_port[i])
669 FATAL("bchannel must be linked to a Port class\n");
673 /* bchannel is idle due to an error, so we do nothing */
676 case B_STATE_ACTIVATING:
677 /* do nothing because we must wait until bchanenl is active before deactivating */
681 /* bchannel is active, so we deactivate */
682 _bchannel_activate(mISDNport, i, 0);
683 state = B_STATE_DEACTIVATING;
686 case B_STATE_DEACTIVATING:
687 /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
691 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
695 case B_EVENT_DEACTIVATED:
699 /* ignore due to deactivation confirm after unloading */
702 case B_STATE_DEACTIVATING:
703 _bchannel_destroy(mISDNport, i);
704 state = B_STATE_IDLE;
705 if (mISDNport->b_port[i])
707 /* bchannel is now deactivate, but is requied by Port class, so we reactivate */
708 if (_bchannel_create(mISDNport, i))
710 _bchannel_activate(mISDNport, i, 1);
711 state = B_STATE_ACTIVATING;
717 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
722 PERROR("Illegal event %d, please correct.\n", event);
725 mISDNport->b_state[i] = state;
732 * check for available channel and reserve+set it.
733 * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
735 * returns -(cause value) or x = channel x or 0 = no channel
736 * NOTE: no activation is done here
738 int PmISDN::seize_bchannel(int channel, int exclusive)
742 /* the channel is what we have */
743 if (p_m_b_channel == channel)
746 /* if channel already in use, release it */
751 if (channel==CHANNEL_NO || channel==0)
754 /* is channel in range ? */
756 || (channel>p_m_mISDNport->b_num && channel<16)
757 || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
758 return(-6); /* channel unacceptable */
760 /* request exclusive channel */
761 if (exclusive && channel>0)
763 i = channel-1-(channel>16);
764 if (p_m_mISDNport->b_port[i])
765 return(-44); /* requested channel not available */
769 /* ask for channel */
772 i = channel-1-(channel>16);
773 if (p_m_mISDNport->b_port[i] == NULL)
777 /* search for channel */
779 while(i < p_m_mISDNport->b_num)
781 if (!p_m_mISDNport->b_port[i])
783 channel = i+1+(i>=15);
788 return(-34); /* no free channel */
791 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
794 p_m_mISDNport->b_port[i] = this;
796 p_m_b_channel = channel;
797 p_m_b_exclusive = exclusive;
799 /* reserve channel */
803 p_m_mISDNport->b_reserved++;
810 * drop reserved channel and unset it.
811 * deactivation is also done
813 void PmISDN::drop_bchannel(void)
818 /* unreserve channel */
820 p_m_mISDNport->b_reserved--;
827 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
829 if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
830 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DEACTIVATE);
831 p_m_mISDNport->b_port[p_m_b_index] = NULL;
841 audio transmission procedure:
842 -----------------------------
845 three sources of audio transmission:
846 - crypto-data high priority
847 - tones high priority (also high)
848 - remote-data low priority
851 a variable that temporarily shows the number of samples elapsed since last transmission process.
852 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
855 a variable that is increased whenever data is transmitted.
856 it is decreased while time elapses. it stores the number of samples that
857 are currently loaded to dsp module.
858 since clock in dsp module is the same clock for user space process, these
862 there are two levels:
863 ISDN_LOAD will give the load that have to be kept in dsp.
864 ISDN_MAXLOAD will give the maximum load before dropping.
866 * procedure for low priority data
867 see txfromup() for procedure
868 in short: remote data is ignored during high priority tones
870 * procedure for high priority data
871 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
872 if no more data is available, load becomes empty again.
875 0 ISDN_LOAD ISDN_MAXLOAD
876 +--------------------+----------------------+
878 +--------------------+----------------------+
880 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
881 0 ISDN_LOAD ISDN_MAXLOAD
882 +--------------------+----------------------+
883 |TTTTTTTTTTTTTTTTTTTT| |
884 +--------------------+----------------------+
886 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
887 0 ISDN_LOAD ISDN_MAXLOAD
888 +--------------------+----------------------+
889 |TTTTTTTTTTTTTTTTTTTTRRRRR |
890 +--------------------+----------------------+
893 int PmISDN::handler(void)
895 struct message *message;
899 if ((ret = Port::handler()))
905 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
906 + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
909 /* set clock of first process ever in this instance */
910 p_m_last_tv_sec = now_tv.tv_sec;
911 p_m_last_tv_msec = now_tv.tv_usec/1000;
913 /* process only if we have a minimum of samples, to make packets not too small */
914 if (elapsed >= ISDN_TRANSMIT)
916 /* set clock of last process! */
917 p_m_last_tv_sec = now_tv.tv_sec;
918 p_m_last_tv_msec = now_tv.tv_usec/1000;
921 if (elapsed < p_m_load)
926 /* to send data, tone must be active OR crypt messages must be on */
927 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
929 int tosend = ISDN_LOAD - p_m_load, length;
930 unsigned char buf[mISDN_HEADER_LEN+tosend];
931 iframe_t *frm = (iframe_t *)buf;
932 unsigned char *p = buf+mISDN_HEADER_LEN;
934 /* copy crypto loops */
935 while (p_m_crypt_msg_loops && tosend)
937 /* how much do we have to send */
938 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
944 /* copy message (part) to buffer */
945 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
948 p_m_crypt_msg_current += length;
949 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
952 p_m_crypt_msg_current = 0;
953 p_m_crypt_msg_loops--;
961 if (p_tone_name[0] && tosend)
963 tosend -= read_audio(p, tosend);
967 frm->prim = DL_DATA | REQUEST;
968 frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
970 frm->len = ISDN_LOAD - p_m_load - tosend;
972 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
973 p_m_load += frm->len;
977 // NOTE: deletion is done by the child class
979 /* handle timeouts */
982 if (p_m_timer+p_m_timeout < now_d)
984 PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
986 /* send timeout to endpoint */
987 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
988 message->param.state = p_state;
989 message_put(message);
994 return(0); /* nothing done */
999 * whenever we get audio data from bchannel, we process it here
1001 void PmISDN::bchannel_receive(iframe_t *frm)
1003 unsigned char *data_temp;
1004 unsigned long length_temp;
1005 struct message *message;
1010 if (frm->prim == (PH_CONTROL | INDICATION))
1014 PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1017 cont = *((unsigned long *)&frm->data.p);
1018 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1020 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1021 add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1023 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1024 message->param.dtmf = cont & DTMF_TONE_MASK;
1025 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c'\n", p_name, message->param.dtmf);
1026 message_put(message);
1032 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1033 add_trace("DSP-CRYPT", NULL, "error");
1035 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1036 message->param.crypt.type = CC_ERROR_IND;
1037 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION reject of blowfish.\n", p_name);
1038 message_put(message);
1042 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1043 add_trace("DSP-CRYPT", NULL, "ok");
1045 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1046 message->param.crypt.type = CC_ACTBF_CONF;
1047 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION accept of blowfish.\n", p_name);
1048 message_put(message);
1054 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1055 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1059 record((unsigned char *)(cont+1), frm->len - 4, 1); // from up
1063 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1064 add_trace("unknown", NULL, "0x%x", cont);
1069 if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1071 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1075 /* calls will not process any audio data unless
1076 * the call is connected OR interface features audio during call setup.
1078 //printf("%d -> %d prim=%x joindata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_joindata, p_m_mISDNport->earlyb);
1079 #ifndef DEBUG_COREBRIDGE
1080 if (p_state!=PORT_STATE_CONNECT
1081 && !p_m_mISDNport->earlyb)
1085 /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1088 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1094 record((unsigned char *)&frm->data.p, frm->len, 0); // from down
1096 /* randomize and listen to crypt message if enabled */
1097 if (p_m_crypt_listen)
1099 /* the noisy randomizer */
1100 p = (unsigned char *)&frm->data.p;
1103 mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1105 cryptman_listen_bch((unsigned char *)&frm->data.p, frm->len);
1108 p = (unsigned char *)&frm->data.p;
1110 /* send data to epoint */
1111 if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1113 length_temp = frm->len;
1117 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1118 message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1119 memcpy(message->param.data.data, data_temp, message->param.data.len);
1120 message_put(message);
1121 if (length_temp <= sizeof(message->param.data.data))
1123 data_temp += sizeof(message->param.data.data);
1124 length_temp -= sizeof(message->param.data.data);
1133 void PmISDN::set_echotest(int echo)
1135 if (p_m_echo != echo)
1138 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1140 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1141 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1148 void PmISDN::set_tone(char *dir, char *tone)
1154 PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1161 /* check if we NOT really have to use a dsp-tone */
1162 if (!options.dsptones)
1166 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1168 PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1169 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1172 Port::set_tone(dir, tone);
1178 /* now we USE dsp-tone, convert name */
1179 else if (!strcmp(tone, "dialtone"))
1181 switch(options.dsptones) {
1182 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1183 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1184 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1186 } else if (!strcmp(tone, "dialpbx"))
1188 switch(options.dsptones) {
1189 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1190 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1191 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1193 } else if (!strcmp(tone, "ringing"))
1195 switch(options.dsptones) {
1196 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1197 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1198 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1200 } else if (!strcmp(tone, "ringpbx"))
1202 switch(options.dsptones) {
1203 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1204 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1205 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1207 } else if (!strcmp(tone, "busy"))
1210 switch(options.dsptones) {
1211 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1212 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1213 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1215 } else if (!strcmp(tone, "release"))
1218 switch(options.dsptones) {
1219 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1220 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1221 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1223 } else if (!strcmp(tone, "cause_10"))
1225 else if (!strcmp(tone, "cause_11"))
1227 else if (!strcmp(tone, "cause_22"))
1229 switch(options.dsptones) {
1230 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1231 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1232 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1234 } else if (!strncmp(tone, "cause_", 6))
1235 id = TONE_SPECIAL_INFO;
1239 /* if we have a tone that is not supported by dsp */
1240 if (id==TONE_OFF && tone[0])
1248 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1250 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1251 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1253 /* turn user-space tones off in cases of no tone OR dsp tone */
1254 Port::set_tone("",NULL);
1258 /* MESSAGE_mISDNSIGNAL */
1259 //extern struct message *dddebug;
1260 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1262 switch(param->mISDNsignal.message)
1264 case mISDNSIGNAL_VOLUME:
1265 if (p_m_txvol != param->mISDNsignal.txvol)
1267 p_m_txvol = param->mISDNsignal.txvol;
1268 PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1270 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1271 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_TX, p_m_txvol, "DSP-TXVOL", p_m_txvol);
1273 PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1274 if (p_m_rxvol != param->mISDNsignal.rxvol)
1276 p_m_rxvol = param->mISDNsignal.rxvol;
1277 PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1279 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1280 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_RX, p_m_rxvol, "DSP-RXVOL", p_m_rxvol);
1282 PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1285 case mISDNSIGNAL_CONF:
1286 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1287 //tone if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1288 if (p_m_conf != param->mISDNsignal.conf)
1290 p_m_conf = param->mISDNsignal.conf;
1291 PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1293 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1294 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1296 PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1297 /* we must set, even if currently tone forbids conf */
1298 p_m_conf = param->mISDNsignal.conf;
1299 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1302 case mISDNSIGNAL_JOINDATA:
1303 if (p_m_joindata != param->mISDNsignal.joindata)
1305 p_m_joindata = param->mISDNsignal.joindata;
1306 PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1308 PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1311 case mISDNSIGNAL_DELAY:
1312 if (p_m_delay != param->mISDNsignal.delay)
1314 p_m_delay = param->mISDNsignal.delay;
1315 PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1317 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1318 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1320 PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1324 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1329 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1331 struct message *message;
1333 switch(param->crypt.type)
1335 case CC_ACTBF_REQ: /* activate blowfish */
1337 p_m_crypt_key_len = param->crypt.len;
1338 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1340 PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1341 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1342 message->param.crypt.type = CC_ERROR_IND;
1343 message_put(message);
1346 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1348 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1350 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1351 ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_crypt?BF_ENABLE_KEY:BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1354 case CC_DACT_REQ: /* deactivate session encryption */
1359 case CR_LISTEN_REQ: /* start listening to messages */
1360 p_m_crypt_listen = 1;
1361 p_m_crypt_listen_state = 0;
1364 case CR_UNLISTEN_REQ: /* stop listening to messages */
1365 p_m_crypt_listen = 0;
1368 case CR_MESSAGE_REQ: /* send message */
1369 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1370 if (!p_m_crypt_msg_len)
1372 PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1375 p_m_crypt_msg_current = 0; /* reset */
1376 p_m_crypt_msg_loops = 3; /* enable */
1378 /* disable txmix, or we get corrupt data due to audio process */
1381 PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1382 ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1388 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1394 * endpoint sends messages to the port
1396 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1398 if (Port::message_epoint(epoint_id, message_id, param))
1403 case MESSAGE_DATA: /* tx-data from upper layer */
1404 txfromup(param->data.data, param->data.len);
1407 case MESSAGE_mISDNSIGNAL: /* user command */
1408 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1409 message_mISDNsignal(epoint_id, message_id, param);
1412 case MESSAGE_CRYPT: /* crypt control command */
1413 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1414 message_crypt(epoint_id, message_id, param);
1423 * main loop for processing messages from mISDN device
1425 int mISDN_handler(void)
1430 struct mISDNport *mISDNport;
1431 class PmISDN *isdnport;
1434 mISDNuser_head_t *hh;
1437 /* the que avoids loopbacks when replying to stack after receiving
1439 mISDNport = mISDNport_first;
1442 /* process turning on/off rx */
1444 while(i < mISDNport->b_num)
1446 isdnport=mISDNport->b_port[i];
1449 /* call bridges in user space OR crypto OR recording */
1450 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1452 /* rx IS required */
1453 if (isdnport->p_m_rxoff)
1456 isdnport->p_m_rxoff = 0;
1457 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
1458 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1459 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1464 /* rx NOT required */
1465 if (!isdnport->p_m_rxoff)
1468 isdnport->p_m_rxoff = 1;
1469 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
1470 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1471 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1476 if (isdnport->p_record)
1478 /* txdata IS required */
1479 if (!isdnport->p_m_txdata)
1482 isdnport->p_m_txdata = 1;
1483 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
1484 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1485 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
1490 /* txdata NOT required */
1491 if (isdnport->p_m_txdata)
1494 isdnport->p_m_txdata = 0;
1495 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
1496 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1497 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1505 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
1507 PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
1508 mISDNport->l1timeout = 0;
1511 if (mISDNport->l2establish)
1513 if (now-mISDNport->l2establish > 5)
1515 if (mISDNport->ntmode)
1517 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
1518 time(&mISDNport->l2establish);
1520 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
1521 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1524 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
1525 time(&mISDNport->l2establish);
1528 act.prim = DL_ESTABLISH | REQUEST;
1529 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
1532 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
1534 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
1539 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
1541 if (mISDNport->ntmode)
1543 hh = (mISDNuser_head_t *)dmsg->data;
1544 PDEBUG(DEBUG_ISDN, "sending queued NT l3-down-message: prim(0x%x) dinfo(0x%x) msg->len(%d)\n", hh->prim, hh->dinfo, dmsg->len);
1545 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1549 frm = (iframe_t *)dmsg->data;
1550 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
1551 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
1552 PDEBUG(DEBUG_ISDN, "sending queued TE l3-down-message: prim(0x%x) dinfo(0x%x) msg->len(%d)\n", frm->prim, frm->dinfo, dmsg->len);
1553 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
1558 mISDNport = mISDNport->next;
1561 /* no device, no read */
1562 if (mISDNdevice < 0)
1565 /* get message from kernel */
1566 if (!(msg = alloc_msg(MAX_MSG_SIZE)))
1568 ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
1572 if (errno == EAGAIN)
1574 FATAL("Failed to do mISDN_read()\n");
1579 // printf("%s: ERROR: mISDN_read() returns nothing\n");
1583 frm = (iframe_t *)msg->data;
1588 case MGR_DELLAYER | CONFIRM:
1589 case MGR_INITTIMER | CONFIRM:
1590 case MGR_ADDTIMER | CONFIRM:
1591 case MGR_DELTIMER | CONFIRM:
1592 case MGR_REMOVETIMER | CONFIRM:
1597 /* handle timer events from mISDN for NT-stack
1598 * note: they do not associate with a stack */
1599 if (frm->prim == (MGR_TIMER | INDICATION))
1603 /* find mISDNport */
1604 mISDNport = mISDNport_first;
1608 if (mISDNport->ntmode)
1610 it = mISDNport->nst.tlist;
1614 if (it->id == (int)frm->addr)
1621 mISDNport = mISDNport->next;
1625 mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
1626 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
1628 PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
1629 test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
1630 ret = it->function(it->data);
1633 PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
1638 /* find the mISDNport that belongs to the stack */
1639 mISDNport = mISDNport_first;
1642 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
1644 mISDNport = mISDNport->next;
1648 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1653 if (!(frm->addr&FLG_CHILD_STACK))
1658 case MGR_SHORTSTATUS | INDICATION:
1659 case MGR_SHORTSTATUS | CONFIRM:
1660 switch(frm->dinfo) {
1661 case SSTATUS_L1_ACTIVATED:
1662 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1665 case SSTATUS_L1_DEACTIVATED:
1666 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1669 case SSTATUS_L2_ESTABLISHED:
1670 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
1673 case SSTATUS_L2_RELEASED:
1674 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
1680 case PH_ACTIVATE | CONFIRM:
1681 case PH_ACTIVATE | INDICATION:
1682 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1684 if (mISDNport->ntmode)
1686 mISDNport->l1link = 1;
1687 setup_queue(mISDNport, 1);
1691 mISDNport->l1link = 1;
1692 setup_queue(mISDNport, 1);
1695 case PH_DEACTIVATE | CONFIRM:
1696 case PH_DEACTIVATE | INDICATION:
1697 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1699 if (mISDNport->ntmode)
1701 mISDNport->l1link = 0;
1702 setup_queue(mISDNport, 0);
1706 mISDNport->l1link = 0;
1707 setup_queue(mISDNport, 0);
1710 case PH_CONTROL | CONFIRM:
1711 case PH_CONTROL | INDICATION:
1712 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
1715 case DL_ESTABLISH | INDICATION:
1716 case DL_ESTABLISH | CONFIRM:
1717 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1719 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1721 if (mISDNport->l2establish)
1723 mISDNport->l2establish = 0;
1724 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
1726 mISDNport->l2link = 1;
1729 case DL_RELEASE | INDICATION:
1730 case DL_RELEASE | CONFIRM:
1731 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1733 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1735 mISDNport->l2link = 0;
1738 time(&mISDNport->l2establish);
1739 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
1745 PDEBUG(DEBUG_STACK, "GOT d-msg from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, frm->prim, frm->dinfo, frm->addr);
1746 if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
1748 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
1751 if (mISDNport->ntmode)
1753 /* l1-data enters the nt-mode library */
1754 nst = &mISDNport->nst;
1755 if (nst->l1_l2(nst, msg))
1760 /* l3-data is sent to pbx */
1761 if (stack2manager_te(mISDNport, msg))
1772 /* we don't care about confirms, we use rx data to sync tx */
1773 case PH_DATA | CONFIRM:
1774 case DL_DATA | CONFIRM:
1777 /* we receive audio data, we respond to it AND we send tones */
1778 case PH_DATA | INDICATION:
1779 case DL_DATA | INDICATION:
1780 case PH_CONTROL | INDICATION:
1782 while(i < mISDNport->b_num)
1784 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1788 if (i == mISDNport->b_num)
1790 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1793 if (mISDNport->b_port[i])
1795 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
1796 mISDNport->b_port[i]->bchannel_receive(frm);
1798 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
1801 case PH_ACTIVATE | INDICATION:
1802 case DL_ESTABLISH | INDICATION:
1803 case PH_ACTIVATE | CONFIRM:
1804 case DL_ESTABLISH | CONFIRM:
1805 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
1807 while(i < mISDNport->b_num)
1809 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1813 if (i == mISDNport->b_num)
1815 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1818 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
1821 case PH_DEACTIVATE | INDICATION:
1822 case DL_RELEASE | INDICATION:
1823 case PH_DEACTIVATE | CONFIRM:
1824 case DL_RELEASE | CONFIRM:
1825 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
1827 while(i < mISDNport->b_num)
1829 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1833 if (i == mISDNport->b_num)
1835 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1838 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
1842 PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1853 * global function to add a new card (port)
1855 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface *interface)
1858 unsigned char buff[1025];
1859 iframe_t *frm = (iframe_t *)buff;
1860 struct mISDNport *mISDNport, **mISDNportp;
1865 // struct mlayer3 *layer3;
1867 // interface_info_t ii;
1871 stack_info_t *stinf;
1874 /* query port's requirements */
1875 cnt = mISDN_get_stack_count(mISDNdevice);
1878 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1881 if (port>cnt || port<1)
1883 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
1886 ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
1889 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
1892 stinf = (stack_info_t *)&frm->data.p;
1893 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
1895 case ISDN_PID_L0_TE_S0:
1896 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
1898 case ISDN_PID_L0_NT_S0:
1899 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
1902 case ISDN_PID_L0_TE_E1:
1903 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1 interface line\n");
1906 case ISDN_PID_L0_NT_E1:
1907 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1 interface port\n");
1912 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
1918 if (stinf->pid.protocol[1] == 0)
1920 PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
1923 if (stinf->pid.protocol[2])
1925 PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
1931 if (stinf->pid.protocol[1] == 0)
1933 PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
1936 if (stinf->pid.protocol[2] == 0)
1938 PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
1941 if (stinf->pid.protocol[3] == 0)
1943 PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
1947 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
1949 case ISDN_PID_L3_DSS1USER:
1953 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
1957 if (stinf->pid.protocol[4])
1959 PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
1964 /* add mISDNport structure */
1965 mISDNportp = &mISDNport_first;
1967 mISDNportp = &((*mISDNportp)->next);
1968 mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
1970 *mISDNportp = mISDNport;
1972 /* allocate ressources of port */
1975 protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
1980 prop |= FLG_FORCE_PTMP;
1981 mISDNport->layer3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
1982 if (!mISDNport->layer3)
1984 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
1988 #warning KKEIL: braucht man das noch?
1989 /* if ntmode, establish L1 to send the tei removal during start */
1990 if (mISDNport->ntmode)
1994 act.prim = PH_ACTIVATE | REQUEST;
1995 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
1996 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
1999 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2000 usleep(10000); /* to be sure, that l1 is up */
2004 msg_queue_init(&mISDNport->downqueue);
2005 mISDNport->d_stid = stinf->id;
2006 PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2007 if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2009 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2013 PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2018 /* create layer intance */
2019 memset(&li, 0, sizeof(li));
2020 UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
2023 li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
2024 li.pid.layermask = ISDN_LAYER((nt?2:4));
2025 li.st = mISDNport->d_stid;
2026 ret = mISDN_new_layer(mISDNdevice, &li);
2029 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
2031 mISDNport_close(mISDNport);
2034 mISDNport->upper_id = li.id;
2035 ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
2038 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
2041 mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
2042 if (mISDNport->lower_id < 0)
2044 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
2047 mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
2048 if (mISDNport->upper_id < 0)
2050 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2053 PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
2055 /* if ntmode, establish L1 to send the tei removal during start */
2056 if (mISDNport->ntmode)
2060 act.prim = PH_ACTIVATE | REQUEST;
2061 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2062 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2065 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2066 usleep(10000); /* to be sure, that l1 is up */
2069 /* create nst (nt-mode only) */
2072 mgr = &mISDNport->mgr;
2073 nst = &mISDNport->nst;
2078 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
2079 nst->device = mISDNdevice;
2081 nst->d_stid = mISDNport->d_stid;
2083 nst->feature = FEATURE_NET_HOLD;
2085 nst->feature |= FEATURE_NET_PTP;
2087 nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2090 while(i < mISDNport->b_num)
2092 nst->b_stid[i] = mISDNport->b_stid[i];
2096 nst->l1_id = mISDNport->lower_id;
2097 nst->l2_id = mISDNport->upper_id;
2100 msg_queue_init(&nst->down_queue);
2107 // SCPY(mISDNport->name, "noname");
2108 mISDNport->portnum = port;
2109 mISDNport->ntmode = nt;
2110 mISDNport->pri = pri;
2111 mISDNport->ptp = ptp;
2112 mISDNport->b_num = stinf->childcnt;
2113 PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2115 while(i < stinf->childcnt)
2117 mISDNport->b_stid[i] = stinf->child[i];
2118 mISDNport->b_state[i] = B_STATE_IDLE;
2119 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
2123 /* if te-mode, query state link */
2124 if (!mISDNport->ntmode)
2128 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
2129 act.prim = MGR_SHORTSTATUS | REQUEST;
2130 act.addr = mISDNport->upper_id | MSG_BROADCAST;
2131 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
2133 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2135 /* if ptp AND te-mode, pull up the link */
2136 if (mISDNport->ptp && !mISDNport->ntmode)
2140 act.prim = DL_ESTABLISH | REQUEST;
2141 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
2144 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2146 /* if ptp AND nt-mode, pull up the link */
2147 if (mISDNport->ptp && mISDNport->ntmode)
2151 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2152 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2155 /* initially, we assume that the link is down, exept for nt-ptmp */
2156 mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2158 PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2160 start_trace(mISDNport->portnum,
2168 add_trace("channels", NULL, "%d", mISDNport->b_num);
2175 * function to free ALL cards (ports)
2177 void mISDNport_close_all(void)
2179 /* free all ports */
2180 while(mISDNport_first)
2181 mISDNport_close(mISDNport_first);
2185 * free only one port
2187 void mISDNport_close(struct mISDNport *mISDNport)
2189 struct mISDNport **mISDNportp;
2191 class PmISDN *isdnport;
2193 unsigned char buf[32];
2196 /* remove all port instance that are linked to this mISDNport */
2200 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2202 isdnport = (class PmISDN *)port;
2203 if (isdnport->p_m_mISDNport)
2205 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2212 /* only if we are already part of interface */
2213 if (mISDNport->ifport)
2215 start_trace(mISDNport->portnum,
2216 mISDNport->ifport->interface,
2226 /* free bchannels */
2228 while(i < mISDNport->b_num)
2230 if (mISDNport->b_addr[i])
2232 _bchannel_destroy(mISDNport, i);
2233 PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2238 /* free ressources of port */
2239 msg_queue_purge(&mISDNport->downqueue);
2242 if (mISDNport->ntmode)
2244 nst = &mISDNport->nst;
2245 if (nst->manager) /* to see if initialized */
2247 PDEBUG(DEBUG_STACK, "the following messages are ok: one L3 process always exists (broadcast process) and some L2 instances (broadcast + current telephone's instances)\n");
2248 cleanup_Isdnl3(nst);
2249 cleanup_Isdnl2(nst);
2252 msg_queue_purge(&nst->down_queue);
2253 if (nst->phd_down_msg)
2254 FREE(nst->phd_down_msg, 0);
2258 PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
2259 if (mISDNport->d_stid)
2261 if (mISDNport->upper_id)
2262 mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
2265 /* remove from list */
2266 mISDNportp = &mISDNport_first;
2269 if (*mISDNportp == mISDNport)
2271 *mISDNportp = (*mISDNportp)->next;
2275 mISDNportp = &((*mISDNportp)->next);
2279 FATAL("mISDNport not in list\n");
2281 FREE(mISDNport, sizeof(struct mISDNport));
2288 * global function to show all available isdn ports
2290 void mISDN_port_info(void)
2294 int useable, nt, pri;
2295 unsigned char buff[1025];
2296 iframe_t *frm = (iframe_t *)buff;
2297 stack_info_t *stinf;
2301 if ((device = mISDN_open()) < 0)
2303 fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", device, errno, strerror(errno));
2307 /* get number of stacks */
2309 ii = mISDN_get_stack_count(device);
2313 printf("Found no card. Please be sure to load card drivers.\n");
2316 /* loop the number of cards and get their info */
2319 err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
2322 fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
2325 stinf = (stack_info_t *)&frm->data.p;
2330 /* output the port info */
2331 printf("Port %2d: ", i);
2332 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2334 case ISDN_PID_L0_TE_S0:
2335 printf("TE-mode BRI S/T interface line (for phone lines)");
2337 if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
2338 printf(" HFC multiport card");
2341 case ISDN_PID_L0_NT_S0:
2343 printf("NT-mode BRI S/T interface port (for phones)");
2345 if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
2346 printf(" HFC multiport card");
2349 case ISDN_PID_L0_TE_E1:
2351 printf("TE-mode PRI E1 interface line (for phone lines)");
2353 if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
2354 printf(" HFC-E1 card");
2357 case ISDN_PID_L0_NT_E1:
2360 printf("NT-mode PRI E1 interface port (for phones)");
2362 if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
2363 printf(" HFC-E1 card");
2368 printf("unknown type 0x%08x",stinf->pid.protocol[0]);
2374 if (stinf->pid.protocol[1] == 0)
2377 printf(" -> Missing layer 1 NT-mode protocol.\n");
2380 while(p <= MAX_LAYER_NR) {
2381 if (stinf->pid.protocol[p])
2384 printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2391 printf(" -> Interface is Point-To-Point (PRI).\n");
2393 printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
2397 if (stinf->pid.protocol[1] == 0)
2400 printf(" -> Missing layer 1 protocol.\n");
2402 if (stinf->pid.protocol[2] == 0)
2405 printf(" -> Missing layer 2 protocol.\n");
2407 if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
2409 printf(" -> Interface is Poin-To-Point.\n");
2411 if (stinf->pid.protocol[3] == 0)
2414 printf(" -> Missing layer 3 protocol.\n");
2417 printf(" -> Protocol: ");
2418 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2420 case ISDN_PID_L3_DSS1USER:
2421 printf("DSS1 (Euro ISDN)");
2426 printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
2431 while(p <= MAX_LAYER_NR) {
2432 if (stinf->pid.protocol[p])
2435 printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2440 printf(" - %d B-channels\n", stinf->childcnt);
2443 printf(" * Port NOT useable for LCR\n");
2445 printf("--------\n");
2452 if ((err = mISDN_close(device)))
2453 FATAL("mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
2458 * enque data from upper buffer
2460 void PmISDN::txfromup(unsigned char *data, int length)
2462 unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2463 iframe_t *frm = (iframe_t *)buf;
2465 /* configure frame */
2466 frm->prim = DL_DATA | REQUEST;
2467 frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
2470 /* check if high priority tones exist
2471 * ignore data in this case
2473 if (p_tone_name[0] || p_m_crypt_msg_loops)
2476 /* preload procedure
2477 * if transmit buffer in DSP module is empty,
2478 * preload it to DSP_LOAD to prevent jitter gaps.
2480 if (p_m_load==0 && ISDN_LOAD>0)
2483 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
2484 frm->len = ISDN_LOAD;
2485 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2486 p_m_load += frm->len;
2489 /* drop if load would exceed ISDN_MAXLOAD
2490 * this keeps the delay not too high
2492 if (p_m_load+length > ISDN_MAXLOAD)
2495 /* load data to buffer
2497 memcpy(buf+mISDN_HEADER_LEN, data, length);
2499 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2500 p_m_load += frm->len;