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;
162 p_m_exportremote = 0; /* channel shall be exported to given remote */
170 p_m_crypt_listen = 0;
171 p_m_crypt_msg_loops = 0;
172 p_m_crypt_msg_loops = 0;
173 p_m_crypt_msg_len = 0;
174 p_m_crypt_msg[0] = '\0';
175 p_m_crypt_msg_current = 0;
176 p_m_crypt_key[0] = '\0';
177 p_m_crypt_key_len = 0;
178 p_m_crypt_listen = 0;
179 p_m_crypt_listen_state = 0;
180 p_m_crypt_listen_len = 0;
181 p_m_crypt_listen_msg[0] = '\0';
182 p_m_crypt_listen_crc = 0;
184 /* if any channel requested by constructor */
185 if (channel == CHANNEL_ANY)
187 /* reserve channel */
189 mISDNport->b_reserved++;
192 /* reserve channel */
193 if (channel > 0) // only if constructor was called with a channel resevation
194 seize_bchannel(channel, exclusive);
196 /* we increase the number of objects: */
198 PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
207 struct message *message;
209 /* remove bchannel relation */
215 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
216 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
217 message->param.disconnectinfo.cause = 16;
218 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
219 message_put(message);
220 /* remove from list */
221 free_epointlist(p_epointlist);
224 /* we decrease the number of objects: */
225 p_m_mISDNport->use--;
226 PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
233 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
235 /* init trace with given values */
236 start_trace(mISDNport?mISDNport->portnum:0,
237 (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
238 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
239 port?port->p_dialinginfo.id:NULL,
242 port?port->p_serial:0,
250 static struct isdn_message {
254 {"TIMEOUT", CC_TIMEOUT},
256 {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
257 {"PROCEEDING", CC_PROCEEDING},
258 {"ALERTING", CC_ALERTING},
259 {"CONNECT", CC_CONNECT},
260 {"CONNECT RES", CC_CONNECT},
261 {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
262 {"DISCONNECT", CC_DISCONNECT},
263 {"RELEASE", CC_RELEASE},
264 {"RELEASE_COMP", CC_RELEASE_COMPLETE},
265 {"INFORMATION", CC_INFORMATION},
266 {"PROGRESS", CC_PROGRESS},
267 {"NOTIFY", CC_NOTIFY},
268 {"SUSPEND", CC_SUSPEND},
269 {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
270 {"SUSPEND_REJ", CC_SUSPEND_REJECT},
271 {"RESUME", CC_RESUME},
272 {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
273 {"RESUME_REJ", CC_RESUME_REJECT},
275 {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
276 {"HOLD_REJ", CC_HOLD_REJECT},
277 {"RETRIEVE", CC_RETRIEVE},
278 {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
279 {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
280 {"FACILITY", CC_FACILITY},
281 {"STATUS", CC_STATUS},
282 {"RESTART", CC_RESTART},
283 {"RELEASE_CR", CC_RELEASE_CR},
284 {"NEW_CR", CC_NEW_CR},
285 {"DL_ESTABLISH", DL_ESTABLISH},
286 {"DL_RELEASE", DL_RELEASE},
287 {"PH_ACTIVATE", PH_ACTIVATE},
288 {"PH_DEACTIVATE", PH_DEACTIVATE},
292 static char *isdn_prim[4] = {
298 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
301 char msgtext[64] = "<<UNKNOWN MESSAGE>>";
303 /* select message and primitive text */
305 while(isdn_message[i].name)
307 if (isdn_message[i].value == (prim&0xffffff00))
309 SCPY(msgtext, isdn_message[i].name);
314 SCAT(msgtext, isdn_prim[prim&0x00000003]);
317 if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
321 if (mISDNport->ntmode)
323 if (direction == DIRECTION_OUT)
324 SCAT(msgtext, " N->U");
326 SCAT(msgtext, " N<-U");
329 if (direction == DIRECTION_OUT)
330 SCAT(msgtext, " U->N");
332 SCAT(msgtext, " U<-N");
337 /* init trace with given values */
338 start_trace(mISDNport?mISDNport->portnum:0,
339 mISDNport?mISDNport->ifport->interface:NULL,
340 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
341 port?port->p_dialinginfo.id:NULL,
344 port?port->p_serial:0,
350 * send control information to the channel (dsp-module)
352 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, int c2, char *trace_name, int trace_value)
354 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
355 iframe_t *ctrl = (iframe_t *)buffer;
356 unsigned long *d = (unsigned long *)&ctrl->data.p;
358 ctrl->prim = PH_CONTROL | REQUEST;
359 ctrl->addr = b_addr | FLG_MSG_DOWN;
361 ctrl->len = sizeof(int)*2;
364 mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
365 chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
366 if (c1 == CMX_CONF_JOIN)
367 add_trace(trace_name, NULL, "0x%08x", trace_value);
369 add_trace(trace_name, NULL, "%d", trace_value);
373 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)
375 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
376 iframe_t *ctrl = (iframe_t *)buffer;
377 unsigned long *d = (unsigned long *)&ctrl->data.p;
379 ctrl->prim = PH_CONTROL | REQUEST;
380 ctrl->addr = b_addr | FLG_MSG_DOWN;
382 ctrl->len = sizeof(int)+c2_len;
384 memcpy(d, c2, c2_len);
385 mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
386 chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
387 add_trace(trace_name, NULL, "%d", trace_value);
393 * subfunction for bchannel_event
396 static int _bchannel_create(struct mISDNport *mISDNport, int i)
398 unsigned char buff[1024];
403 if (!mISDNport->b_stid[i])
405 PERROR("Error: no stack for index %d\n", i);
408 if (mISDNport->b_addr[i])
410 PERROR("Error: stack already created for index %d\n", i);
414 /* create new layer */
415 PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
416 memset(&li, 0, sizeof(li));
417 memset(&pid, 0, sizeof(pid));
420 li.st = mISDNport->b_stid[i];
421 UCPY(li.name, "B L4");
422 li.pid.layermask = ISDN_LAYER((4));
423 li.pid.protocol[4] = ISDN_PID_L4_B_USER;
424 ret = mISDN_new_layer(mISDNdevice, &li);
428 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
431 mISDNport->b_addr[i] = li.id;
434 goto failed_new_layer;
436 PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
438 /* create new stack */
439 pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
440 pid.protocol[2] = ISDN_PID_L2_B_TRANS;
441 pid.protocol[3] = ISDN_PID_L3_B_DSP;
442 pid.protocol[4] = ISDN_PID_L4_B_USER;
443 pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
444 ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
448 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
449 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
452 ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
457 mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
458 if (!mISDNport->b_addr[i])
460 chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
461 add_trace("channel", NULL, "%d", i+1+(i>=15));
462 add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
463 add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
469 mISDNport->b_addr[i] = 0;
475 * subfunction for bchannel_event
476 * activate / deactivate request
478 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
482 /* activate bchannel */
483 chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
484 add_trace("channel", NULL, "%d", i+1+(i>=15));
486 act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST;
487 act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
490 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
495 * subfunction for bchannel_event
498 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
503 port = mISDNport->b_port[i];
504 addr = mISDNport->b_addr[i];
507 PERROR("bchannel index i=%d not associated with a port object\n", i);
511 /* set dsp features */
512 if (port->p_m_txdata)
513 ph_control(mISDNport, port, addr, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
515 ph_control(mISDNport, port, addr, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
517 ph_control(mISDNport, port, addr, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
519 ph_control(mISDNport, port, addr, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
521 ph_control(mISDNport, port, addr, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
523 ph_control(mISDNport, port, addr, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
525 ph_control(mISDNport, port, addr, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
527 ph_control(mISDNport, port, addr, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
528 // if (port->p_m_txmix)
529 // ph_control(mISDNport, port, addr, CMX_MIX_ON, 0, "DSP-MIX", 1);
531 ph_control(mISDNport, port, addr, DTMF_TONE_START, 0, "DSP-DTMF", 1);
533 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);
537 * subfunction for bchannel_event
540 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
542 unsigned char buff[1024];
544 chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
545 add_trace("channel", NULL, "%d", i+1+(i>=15));
546 add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
547 add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
549 /* remove our stack only if set */
550 if (mISDNport->b_addr[i])
552 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
553 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
554 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
555 mISDNport->b_addr[i] = 0;
564 A bchannel goes through the following states in this order:
567 No one is using the bchannel.
568 It is available and not linked to Port class, nor reserved.
571 The bchannel stack is created and an activation request is sent.
572 It MAY be linked to Port class, but already unlinked due to Port class removal.
575 The bchannel is active and cofigured to the Port class needs.
576 Also it is linked to a Port class, otherwhise it would be deactivated.
578 - B_STATE_DEACTIVATING
579 The bchannel is in deactivating state, due to deactivation request.
580 It may be linked to a Port class, that likes to reactivate it.
584 After deactivating bchannel, and if not used, the bchannel becomes idle again.
586 Also the bchannel may be exported, but only if the state is or becomes idle:
589 The bchannel assignment has been sent to the remove application.
592 The bchannel assignment is acknowledged by the remote application.
595 The bchannel is re-imported by mISDN port object.
599 After re-importing bchannel, and if not used, the bchannel becomes idle again.
602 A bchannel can have the following events:
605 A bchannel is required by a Port class.
606 The bchannel shall be exported to the remote application.
609 The bchannel beomes active.
612 The bchannel is not required by Port class anymore
614 - B_EVENT_DEACTIVATED
615 The bchannel becomes inactive.
618 The bchannel is now used by remote application.
621 The bchannel is not used by remote application.
623 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
628 * process bchannel events
629 * - mISDNport is a pointer to the port's structure
630 * - i is the index of the bchannel
631 * - event is the B_EVENT_* value
632 * - port is the PmISDN class pointer
634 void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long to_remote)
636 class PmISDN *b_port = mISDNport->b_port[i];
637 int state = mISDNport->b_state[i];
638 unsigned long remote = mISDNport->b_remote[i];
639 unsigned long addr = mISDNport->b_addr[i];
644 /* port must be linked in order to allow activation */
646 FATAL("bchannel must be linked to a Port class\n");
651 PDEBUG(DEBUG_BCHANNEL, "idle channels don't have remote link.\n");
654 /* export bchannel */
655 mISDNport->b_remote[i] = remote = to_remote;
657 message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
658 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
659 add_trace("type", NULL, "assign");
660 add_trace("stack", "address", "%x", addr);
662 state = B_STATE_EXPORTING;
665 /* create stack and send activation request */
666 if (_bchannel_create(mISDNport, i))
668 _bchannel_activate(mISDNport, i, 1);
669 state = B_STATE_ACTIVATING;
674 case B_STATE_ACTIVATING:
675 case B_STATE_EXPORTING:
676 /* do nothing, because it is already activating */
679 case B_STATE_DEACTIVATING:
680 case B_STATE_IMPORTING:
681 /* do nothing, because we must wait until we can reactivate */
685 /* problems that might ocurr:
686 * B_EVENT_USE is received when channel already in use.
687 * bchannel exported, but not freed by other port
689 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
693 case B_EVENT_EXPORTREQUEST:
694 /* special case where the bchannel is requested by remote */
697 PERROR("channel for join %d already exported to join %d, please correct.\n", to_remote, remote);
699 mISDNport->b_remote[i] = remote = to_remote;
704 /* export bchannel */
705 message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
706 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
707 add_trace("type", NULL, "assign");
708 add_trace("stack", "address", "%x", addr);
710 state = B_STATE_EXPORTING;
713 case B_STATE_ACTIVATING:
714 case B_STATE_EXPORTING:
715 /* do nothing, because it is already activating */
718 case B_STATE_DEACTIVATING:
719 case B_STATE_IMPORTING:
720 /* do nothing, because we must wait until we can reactivate */
724 /* bchannel is active, so we deactivate */
725 _bchannel_activate(mISDNport, i, 0);
726 state = B_STATE_DEACTIVATING;
730 /* problems that might ocurr:
731 * ... when channel already in use.
732 * bchannel exported, but not freed by other port
734 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
738 case B_EVENT_ACTIVATED:
741 case B_STATE_ACTIVATING:
742 if (b_port && !remote)
744 /* bchannel is active and used by Port class, so we configure bchannel */
745 _bchannel_configure(mISDNport, i);
746 state = B_STATE_ACTIVE;
749 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
750 _bchannel_activate(mISDNport, i, 0);
751 state = B_STATE_DEACTIVATING;
756 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
760 case B_EVENT_EXPORTED:
763 case B_STATE_EXPORTING:
764 if (b_port && remote && to_remote==remote)
766 /* remote export done */
767 state = B_STATE_REMOTE;
770 /* bchannel is now exported, but we need bchannel back OR bchannel is not used anymore OR remote has changed, so reimport, to later export to new remote */
771 message_bchannel_to_join(remote, BCHANNEL_REMOVE, addr);
772 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
773 add_trace("type", NULL, "remove");
774 add_trace("stack", "address", "%x", addr);
776 state = B_STATE_IMPORTING;
781 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
787 FATAL("bchannel must be linked to a Port class\n");
788 mISDNport->b_remote[i] = 0;
792 /* bchannel is idle due to an error, so we do nothing */
795 case B_STATE_ACTIVATING:
796 case B_STATE_EXPORTING:
797 /* do nothing because we must wait until bchanenl is active before deactivating */
801 /* bchannel is active, so we deactivate */
802 _bchannel_activate(mISDNport, i, 0);
803 state = B_STATE_DEACTIVATING;
807 /* bchannel is exported, so we re-import */
808 message_bchannel_to_join(remote, BCHANNEL_REMOVE, addr);
809 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
810 add_trace("type", NULL, "remove");
811 add_trace("stack", "address", "%x", addr);
813 state = B_STATE_IMPORTING;
816 case B_STATE_DEACTIVATING:
817 case B_STATE_IMPORTING:
818 /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
822 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
826 case B_EVENT_DEACTIVATED:
830 /* ignore due to deactivation confirm after unloading */
833 case B_STATE_DEACTIVATING:
834 _bchannel_destroy(mISDNport, i);
835 state = B_STATE_IDLE;
838 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
841 message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
842 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
843 add_trace("type", NULL, "assign");
844 add_trace("stack", "address", "%x", addr);
846 state = B_STATE_EXPORTING;
849 if (_bchannel_create(mISDNport, i))
851 _bchannel_activate(mISDNport, i, 1);
852 state = B_STATE_ACTIVATING;
859 PERROR("Illegal event %d at state %d, please correct.\n", event, state);
863 case B_EVENT_IMPORTED:
866 case B_STATE_IMPORTING:
867 state = B_STATE_IDLE;
870 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
873 message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
874 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
875 add_trace("type", NULL, "assign");
876 add_trace("stack", "address", "%x", addr);
878 state = B_STATE_EXPORTING;
881 if (_bchannel_create(mISDNport, i))
883 _bchannel_activate(mISDNport, i, 1);
884 state = B_STATE_ACTIVATING;
891 /* ignore, because not assigned */
897 PERROR("Illegal event %d, please correct.\n", event);
900 mISDNport->b_state[i] = state;
907 * check for available channel and reserve+set it.
908 * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
910 * returns -(cause value) or x = channel x or 0 = no channel
911 * NOTE: no activation is done here
913 int PmISDN::seize_bchannel(int channel, int exclusive)
917 /* the channel is what we have */
918 if (p_m_b_channel == channel)
921 /* if channel already in use, release it */
926 if (channel==CHANNEL_NO || channel==0)
929 /* is channel in range ? */
931 || (channel>p_m_mISDNport->b_num && channel<16)
932 || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
933 return(-6); /* channel unacceptable */
935 /* request exclusive channel */
936 if (exclusive && channel>0)
938 i = channel-1-(channel>16);
939 if (p_m_mISDNport->b_port[i])
940 return(-44); /* requested channel not available */
944 /* ask for channel */
947 i = channel-1-(channel>16);
948 if (p_m_mISDNport->b_port[i] == NULL)
952 /* search for channel */
954 while(i < p_m_mISDNport->b_num)
956 if (!p_m_mISDNport->b_port[i])
958 channel = i+1+(i>=15);
963 return(-34); /* no free channel */
966 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
969 p_m_mISDNport->b_port[i] = this;
970 p_m_mISDNport->b_remote[i] = p_m_exportremote;
972 p_m_b_channel = channel;
973 p_m_b_exclusive = exclusive;
975 /* reserve channel */
979 p_m_mISDNport->b_reserved++;
986 * drop reserved channel and unset it.
987 * deactivation is also done
989 void PmISDN::drop_bchannel(void)
994 /* unreserve channel */
996 p_m_mISDNport->b_reserved--;
1003 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1005 if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1006 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP, 0);
1007 p_m_mISDNport->b_port[p_m_b_index] = NULL;
1008 p_m_mISDNport->b_remote[p_m_b_index] = 0;
1011 p_m_b_exclusive = 0;
1014 /* process bchannel export/import message from join */
1015 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long addr)
1017 class Endpoint *epoint;
1019 class PmISDN *isdnport;
1020 struct mISDNport *mISDNport;
1025 case BCHANNEL_REQUEST:
1026 /* find the port object for the join object ref */
1027 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1029 PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1032 if (!epoint->ep_portlist)
1034 PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1037 if (epoint->ep_portlist->next)
1039 PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
1041 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1043 PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1046 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1048 PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1050 isdnport = (class PmISDN *)port;
1053 if (isdnport->p_m_exportremote)
1055 PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1058 chan_trace_header(isdnport->p_m_mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1059 add_trace("type", NULL, "export request");
1060 isdnport->p_m_exportremote = joinremote->j_serial;
1061 if (isdnport->p_m_mISDNport && isdnport->p_m_b_index>=0)
1062 bchannel_event(isdnport->p_m_mISDNport, isdnport->p_m_b_index, B_EVENT_EXPORTREQUEST, joinremote->j_serial);
1066 case BCHANNEL_ASSIGN_ACK:
1067 case BCHANNEL_REMOVE_ACK:
1068 /* find mISDNport for stack ID */
1069 mISDNport = mISDNport_first;
1073 ii = mISDNport->b_num;
1076 if (mISDNport->b_addr[i] == addr)
1082 mISDNport = mISDNport->next;
1084 /* mISDNport may now be set or NULL */
1087 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1088 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1089 if (mISDNport && i>=0)
1090 bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED, 0);
1094 PERROR("received wrong bchannel message type %d from remote\n", type);
1102 audio transmission procedure:
1103 -----------------------------
1106 three sources of audio transmission:
1107 - crypto-data high priority
1108 - tones high priority (also high)
1109 - remote-data low priority
1112 a variable that temporarily shows the number of samples elapsed since last transmission process.
1113 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1116 a variable that is increased whenever data is transmitted.
1117 it is decreased while time elapses. it stores the number of samples that
1118 are currently loaded to dsp module.
1119 since clock in dsp module is the same clock for user space process, these
1123 there are two levels:
1124 ISDN_LOAD will give the load that have to be kept in dsp.
1125 ISDN_MAXLOAD will give the maximum load before dropping.
1127 * procedure for low priority data
1128 see txfromup() for procedure
1129 in short: remote data is ignored during high priority tones
1131 * procedure for high priority data
1132 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1133 if no more data is available, load becomes empty again.
1136 0 ISDN_LOAD ISDN_MAXLOAD
1137 +--------------------+----------------------+
1139 +--------------------+----------------------+
1141 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1142 0 ISDN_LOAD ISDN_MAXLOAD
1143 +--------------------+----------------------+
1144 |TTTTTTTTTTTTTTTTTTTT| |
1145 +--------------------+----------------------+
1147 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1148 0 ISDN_LOAD ISDN_MAXLOAD
1149 +--------------------+----------------------+
1150 |TTTTTTTTTTTTTTTTTTTTRRRRR |
1151 +--------------------+----------------------+
1154 int PmISDN::handler(void)
1156 struct message *message;
1160 if ((ret = Port::handler()))
1164 if (p_m_last_tv_sec)
1166 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1167 + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1170 /* set clock of first process ever in this instance */
1171 p_m_last_tv_sec = now_tv.tv_sec;
1172 p_m_last_tv_msec = now_tv.tv_usec/1000;
1174 /* process only if we have a minimum of samples, to make packets not too small */
1175 if (elapsed >= ISDN_TRANSMIT)
1177 /* set clock of last process! */
1178 p_m_last_tv_sec = now_tv.tv_sec;
1179 p_m_last_tv_msec = now_tv.tv_usec/1000;
1182 if (elapsed < p_m_load)
1183 p_m_load -= elapsed;
1187 /* to send data, tone must be active OR crypt messages must be on */
1188 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
1190 int tosend = ISDN_LOAD - p_m_load, length;
1191 unsigned char buf[mISDN_HEADER_LEN+tosend];
1192 iframe_t *frm = (iframe_t *)buf;
1193 unsigned char *p = buf+mISDN_HEADER_LEN;
1195 /* copy crypto loops */
1196 while (p_m_crypt_msg_loops && tosend)
1198 /* how much do we have to send */
1199 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1202 if (length > tosend)
1205 /* copy message (part) to buffer */
1206 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1209 p_m_crypt_msg_current += length;
1210 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1213 p_m_crypt_msg_current = 0;
1214 p_m_crypt_msg_loops--;
1222 if (p_tone_name[0] && tosend)
1224 tosend -= read_audio(p, tosend);
1228 frm->prim = DL_DATA | REQUEST;
1229 frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1231 frm->len = ISDN_LOAD - p_m_load - tosend;
1233 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1234 p_m_load += frm->len;
1238 // NOTE: deletion is done by the child class
1240 /* handle timeouts */
1243 if (p_m_timer+p_m_timeout < now_d)
1245 PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1247 /* send timeout to endpoint */
1248 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1249 message->param.state = p_state;
1250 message_put(message);
1255 return(0); /* nothing done */
1260 * whenever we get audio data from bchannel, we process it here
1262 void PmISDN::bchannel_receive(iframe_t *frm)
1264 unsigned char *data_temp;
1265 unsigned long length_temp;
1266 struct message *message;
1271 if (frm->prim == (PH_CONTROL | INDICATION))
1275 PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1278 cont = *((unsigned long *)&frm->data.p);
1279 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1281 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1282 add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1284 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1285 message->param.dtmf = cont & DTMF_TONE_MASK;
1286 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c'\n", p_name, message->param.dtmf);
1287 message_put(message);
1293 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1294 add_trace("DSP-CRYPT", NULL, "error");
1296 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1297 message->param.crypt.type = CC_ERROR_IND;
1298 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION reject of blowfish.\n", p_name);
1299 message_put(message);
1303 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1304 add_trace("DSP-CRYPT", NULL, "ok");
1306 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1307 message->param.crypt.type = CC_ACTBF_CONF;
1308 PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION accept of blowfish.\n", p_name);
1309 message_put(message);
1315 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1316 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1320 record((unsigned char *)(cont+1), frm->len - 4, 1); // from up
1324 chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1325 add_trace("unknown", NULL, "0x%x", cont);
1330 if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1332 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1336 /* calls will not process any audio data unless
1337 * the call is connected OR interface features audio during call setup.
1339 //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);
1340 #ifndef DEBUG_COREBRIDGE
1341 if (p_state!=PORT_STATE_CONNECT
1342 && !p_m_mISDNport->earlyb)
1346 /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1349 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1355 record((unsigned char *)&frm->data.p, frm->len, 0); // from down
1357 /* randomize and listen to crypt message if enabled */
1358 if (p_m_crypt_listen)
1360 /* the noisy randomizer */
1361 p = (unsigned char *)&frm->data.p;
1364 mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1366 cryptman_listen_bch((unsigned char *)&frm->data.p, frm->len);
1369 p = (unsigned char *)&frm->data.p;
1371 /* send data to epoint */
1372 if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1374 length_temp = frm->len;
1378 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1379 message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1380 memcpy(message->param.data.data, data_temp, message->param.data.len);
1381 message_put(message);
1382 if (length_temp <= sizeof(message->param.data.data))
1384 data_temp += sizeof(message->param.data.data);
1385 length_temp -= sizeof(message->param.data.data);
1394 void PmISDN::set_echotest(int echo)
1396 if (p_m_echo != echo)
1399 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1401 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1402 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);
1409 void PmISDN::set_tone(char *dir, char *tone)
1415 PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1422 /* check if we NOT really have to use a dsp-tone */
1423 if (!options.dsptones)
1427 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1429 PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1430 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1433 Port::set_tone(dir, tone);
1439 /* now we USE dsp-tone, convert name */
1440 else if (!strcmp(tone, "dialtone"))
1442 switch(options.dsptones) {
1443 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1444 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1445 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1447 } else if (!strcmp(tone, "dialpbx"))
1449 switch(options.dsptones) {
1450 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1451 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1452 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1454 } else if (!strcmp(tone, "ringing"))
1456 switch(options.dsptones) {
1457 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1458 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1459 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1461 } else if (!strcmp(tone, "ringpbx"))
1463 switch(options.dsptones) {
1464 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1465 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1466 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1468 } else if (!strcmp(tone, "busy"))
1471 switch(options.dsptones) {
1472 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1473 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1474 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1476 } else if (!strcmp(tone, "release"))
1479 switch(options.dsptones) {
1480 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1481 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1482 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1484 } else if (!strcmp(tone, "cause_10"))
1486 else if (!strcmp(tone, "cause_11"))
1488 else if (!strcmp(tone, "cause_22"))
1490 switch(options.dsptones) {
1491 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1492 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1493 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1495 } else if (!strncmp(tone, "cause_", 6))
1496 id = TONE_SPECIAL_INFO;
1500 /* if we have a tone that is not supported by dsp */
1501 if (id==TONE_OFF && tone[0])
1509 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1511 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1512 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);
1514 /* turn user-space tones off in cases of no tone OR dsp tone */
1515 Port::set_tone("",NULL);
1519 /* MESSAGE_mISDNSIGNAL */
1520 //extern struct message *dddebug;
1521 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1523 switch(param->mISDNsignal.message)
1525 case mISDNSIGNAL_VOLUME:
1526 if (p_m_txvol != param->mISDNsignal.txvol)
1528 p_m_txvol = param->mISDNsignal.txvol;
1529 PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1531 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1532 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);
1534 PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1535 if (p_m_rxvol != param->mISDNsignal.rxvol)
1537 p_m_rxvol = param->mISDNsignal.rxvol;
1538 PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1540 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1541 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);
1543 PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1546 case mISDNSIGNAL_CONF:
1547 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1548 //tone if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1549 if (p_m_conf != param->mISDNsignal.conf)
1551 p_m_conf = param->mISDNsignal.conf;
1552 PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1554 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1555 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);
1557 PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1558 /* we must set, even if currently tone forbids conf */
1559 p_m_conf = param->mISDNsignal.conf;
1560 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1563 case mISDNSIGNAL_JOINDATA:
1564 if (p_m_joindata != param->mISDNsignal.joindata)
1566 p_m_joindata = param->mISDNsignal.joindata;
1567 PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1569 PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1572 case mISDNSIGNAL_DELAY:
1573 if (p_m_delay != param->mISDNsignal.delay)
1575 p_m_delay = param->mISDNsignal.delay;
1576 PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1578 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1579 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);
1581 PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1585 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1590 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1592 struct message *message;
1594 switch(param->crypt.type)
1596 case CC_ACTBF_REQ: /* activate blowfish */
1598 p_m_crypt_key_len = param->crypt.len;
1599 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1601 PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1602 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1603 message->param.crypt.type = CC_ERROR_IND;
1604 message_put(message);
1607 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1609 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1611 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1612 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);
1615 case CC_DACT_REQ: /* deactivate session encryption */
1620 case CR_LISTEN_REQ: /* start listening to messages */
1621 p_m_crypt_listen = 1;
1622 p_m_crypt_listen_state = 0;
1625 case CR_UNLISTEN_REQ: /* stop listening to messages */
1626 p_m_crypt_listen = 0;
1629 case CR_MESSAGE_REQ: /* send message */
1630 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1631 if (!p_m_crypt_msg_len)
1633 PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1636 p_m_crypt_msg_current = 0; /* reset */
1637 p_m_crypt_msg_loops = 3; /* enable */
1639 /* disable txmix, or we get corrupt data due to audio process */
1642 PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1643 ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1649 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1655 * endpoint sends messages to the port
1657 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1659 if (Port::message_epoint(epoint_id, message_id, param))
1664 case MESSAGE_DATA: /* tx-data from upper layer */
1665 txfromup(param->data.data, param->data.len);
1668 case MESSAGE_mISDNSIGNAL: /* user command */
1669 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1670 message_mISDNsignal(epoint_id, message_id, param);
1673 case MESSAGE_CRYPT: /* crypt control command */
1674 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1675 message_crypt(epoint_id, message_id, param);
1684 * main loop for processing messages from mISDN device
1686 int mISDN_handler(void)
1691 struct mISDNport *mISDNport;
1692 class PmISDN *isdnport;
1695 mISDNuser_head_t *hh;
1698 /* the que avoids loopbacks when replying to stack after receiving
1700 mISDNport = mISDNport_first;
1703 /* process turning on/off rx */
1705 while(i < mISDNport->b_num)
1707 isdnport=mISDNport->b_port[i];
1710 /* call bridges in user space OR crypto OR recording */
1711 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1713 /* rx IS required */
1714 if (isdnport->p_m_rxoff)
1717 isdnport->p_m_rxoff = 0;
1718 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
1719 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1720 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1725 /* rx NOT required */
1726 if (!isdnport->p_m_rxoff)
1729 isdnport->p_m_rxoff = 1;
1730 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
1731 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1732 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1737 if (isdnport->p_record)
1739 /* txdata IS required */
1740 if (!isdnport->p_m_txdata)
1743 isdnport->p_m_txdata = 1;
1744 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
1745 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1746 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
1751 /* txdata NOT required */
1752 if (isdnport->p_m_txdata)
1755 isdnport->p_m_txdata = 0;
1756 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
1757 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1758 ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1766 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
1768 PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
1769 mISDNport->l1timeout = 0;
1772 if (mISDNport->l2establish)
1774 if (now-mISDNport->l2establish > 5)
1776 if (mISDNport->ntmode)
1778 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
1779 time(&mISDNport->l2establish);
1781 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
1782 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1785 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
1786 time(&mISDNport->l2establish);
1789 act.prim = DL_ESTABLISH | REQUEST;
1790 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
1793 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
1795 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
1800 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
1802 if (mISDNport->ntmode)
1804 hh = (mISDNuser_head_t *)dmsg->data;
1805 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);
1806 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1810 frm = (iframe_t *)dmsg->data;
1811 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
1812 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
1813 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);
1814 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
1819 mISDNport = mISDNport->next;
1822 /* no device, no read */
1823 if (mISDNdevice < 0)
1826 /* get message from kernel */
1827 if (!(msg = alloc_msg(MAX_MSG_SIZE)))
1829 ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
1833 if (errno == EAGAIN)
1835 FATAL("Failed to do mISDN_read()\n");
1840 // printf("%s: ERROR: mISDN_read() returns nothing\n");
1844 frm = (iframe_t *)msg->data;
1849 case MGR_DELLAYER | CONFIRM:
1850 case MGR_INITTIMER | CONFIRM:
1851 case MGR_ADDTIMER | CONFIRM:
1852 case MGR_DELTIMER | CONFIRM:
1853 case MGR_REMOVETIMER | CONFIRM:
1858 /* handle timer events from mISDN for NT-stack
1859 * note: they do not associate with a stack */
1860 if (frm->prim == (MGR_TIMER | INDICATION))
1864 /* find mISDNport */
1865 mISDNport = mISDNport_first;
1869 if (mISDNport->ntmode)
1871 it = mISDNport->nst.tlist;
1875 if (it->id == (int)frm->addr)
1882 mISDNport = mISDNport->next;
1886 mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
1887 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
1889 PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
1890 test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
1891 ret = it->function(it->data);
1894 PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
1899 /* find the mISDNport that belongs to the stack */
1900 mISDNport = mISDNport_first;
1903 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
1905 mISDNport = mISDNport->next;
1909 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1914 if (!(frm->addr&FLG_CHILD_STACK))
1919 case MGR_SHORTSTATUS | INDICATION:
1920 case MGR_SHORTSTATUS | CONFIRM:
1921 switch(frm->dinfo) {
1922 case SSTATUS_L1_ACTIVATED:
1923 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1926 case SSTATUS_L1_DEACTIVATED:
1927 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1930 case SSTATUS_L2_ESTABLISHED:
1931 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
1934 case SSTATUS_L2_RELEASED:
1935 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
1941 case PH_ACTIVATE | CONFIRM:
1942 case PH_ACTIVATE | INDICATION:
1943 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1945 if (mISDNport->ntmode)
1947 mISDNport->l1link = 1;
1948 setup_queue(mISDNport, 1);
1952 mISDNport->l1link = 1;
1953 setup_queue(mISDNport, 1);
1956 case PH_DEACTIVATE | CONFIRM:
1957 case PH_DEACTIVATE | INDICATION:
1958 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1960 if (mISDNport->ntmode)
1962 mISDNport->l1link = 0;
1963 setup_queue(mISDNport, 0);
1967 mISDNport->l1link = 0;
1968 setup_queue(mISDNport, 0);
1971 case PH_CONTROL | CONFIRM:
1972 case PH_CONTROL | INDICATION:
1973 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
1976 case DL_ESTABLISH | INDICATION:
1977 case DL_ESTABLISH | CONFIRM:
1978 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1980 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1982 if (mISDNport->l2establish)
1984 mISDNport->l2establish = 0;
1985 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
1987 mISDNport->l2link = 1;
1990 case DL_RELEASE | INDICATION:
1991 case DL_RELEASE | CONFIRM:
1992 l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1994 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1996 mISDNport->l2link = 0;
1999 time(&mISDNport->l2establish);
2000 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2006 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);
2007 if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2009 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2012 if (mISDNport->ntmode)
2014 /* l1-data enters the nt-mode library */
2015 nst = &mISDNport->nst;
2016 if (nst->l1_l2(nst, msg))
2021 /* l3-data is sent to pbx */
2022 if (stack2manager_te(mISDNport, msg))
2033 /* we don't care about confirms, we use rx data to sync tx */
2034 case PH_DATA | CONFIRM:
2035 case DL_DATA | CONFIRM:
2038 /* we receive audio data, we respond to it AND we send tones */
2039 case PH_DATA | INDICATION:
2040 case DL_DATA | INDICATION:
2041 case PH_CONTROL | INDICATION:
2043 while(i < mISDNport->b_num)
2045 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2049 if (i == mISDNport->b_num)
2051 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2054 if (mISDNport->b_port[i])
2056 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2057 mISDNport->b_port[i]->bchannel_receive(frm);
2059 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2062 case PH_ACTIVATE | INDICATION:
2063 case DL_ESTABLISH | INDICATION:
2064 case PH_ACTIVATE | CONFIRM:
2065 case DL_ESTABLISH | CONFIRM:
2066 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2068 while(i < mISDNport->b_num)
2070 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2074 if (i == mISDNport->b_num)
2076 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2079 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED, 0);
2082 case PH_DEACTIVATE | INDICATION:
2083 case DL_RELEASE | INDICATION:
2084 case PH_DEACTIVATE | CONFIRM:
2085 case DL_RELEASE | CONFIRM:
2086 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2088 while(i < mISDNport->b_num)
2090 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2094 if (i == mISDNport->b_num)
2096 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2099 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED, 0);
2103 PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2114 * global function to add a new card (port)
2116 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface *interface)
2119 unsigned char buff[1025];
2120 iframe_t *frm = (iframe_t *)buff;
2121 struct mISDNport *mISDNport, **mISDNportp;
2126 // struct mlayer3 *layer3;
2128 // interface_info_t ii;
2132 stack_info_t *stinf;
2135 /* query port's requirements */
2136 cnt = mISDN_get_stack_count(mISDNdevice);
2139 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2142 if (port>cnt || port<1)
2144 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2147 ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2150 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2153 stinf = (stack_info_t *)&frm->data.p;
2154 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2156 case ISDN_PID_L0_TE_S0:
2157 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2159 case ISDN_PID_L0_NT_S0:
2160 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2163 case ISDN_PID_L0_TE_E1:
2164 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1 interface line\n");
2167 case ISDN_PID_L0_NT_E1:
2168 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1 interface port\n");
2173 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2179 if (stinf->pid.protocol[1] == 0)
2181 PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2184 if (stinf->pid.protocol[2])
2186 PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2192 if (stinf->pid.protocol[1] == 0)
2194 PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2197 if (stinf->pid.protocol[2] == 0)
2199 PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2202 if (stinf->pid.protocol[3] == 0)
2204 PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2208 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2210 case ISDN_PID_L3_DSS1USER:
2214 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2218 if (stinf->pid.protocol[4])
2220 PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2225 /* add mISDNport structure */
2226 mISDNportp = &mISDNport_first;
2228 mISDNportp = &((*mISDNportp)->next);
2229 mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2231 *mISDNportp = mISDNport;
2233 /* allocate ressources of port */
2236 protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
2241 prop |= FLG_FORCE_PTMP;
2242 mISDNport->layer3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
2243 if (!mISDNport->layer3)
2245 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2249 #warning KKEIL: braucht man das noch?
2250 /* if ntmode, establish L1 to send the tei removal during start */
2251 if (mISDNport->ntmode)
2255 act.prim = PH_ACTIVATE | REQUEST;
2256 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2257 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2260 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2261 usleep(10000); /* to be sure, that l1 is up */
2265 msg_queue_init(&mISDNport->downqueue);
2266 mISDNport->d_stid = stinf->id;
2267 PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2268 if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2270 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2274 PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2279 /* create layer intance */
2280 memset(&li, 0, sizeof(li));
2281 UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
2284 li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
2285 li.pid.layermask = ISDN_LAYER((nt?2:4));
2286 li.st = mISDNport->d_stid;
2287 ret = mISDN_new_layer(mISDNdevice, &li);
2290 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
2292 mISDNport_close(mISDNport);
2295 mISDNport->upper_id = li.id;
2296 ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
2299 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
2302 mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
2303 if (mISDNport->lower_id < 0)
2305 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
2308 mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
2309 if (mISDNport->upper_id < 0)
2311 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2314 PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
2316 /* if ntmode, establish L1 to send the tei removal during start */
2317 if (mISDNport->ntmode)
2321 act.prim = PH_ACTIVATE | REQUEST;
2322 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2323 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2326 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2327 usleep(10000); /* to be sure, that l1 is up */
2330 /* create nst (nt-mode only) */
2333 mgr = &mISDNport->mgr;
2334 nst = &mISDNport->nst;
2339 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
2340 nst->device = mISDNdevice;
2342 nst->d_stid = mISDNport->d_stid;
2344 nst->feature = FEATURE_NET_HOLD;
2346 nst->feature |= FEATURE_NET_PTP;
2348 nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2351 while(i < mISDNport->b_num)
2353 nst->b_stid[i] = mISDNport->b_stid[i];
2357 nst->l1_id = mISDNport->lower_id;
2358 nst->l2_id = mISDNport->upper_id;
2361 msg_queue_init(&nst->down_queue);
2368 // SCPY(mISDNport->name, "noname");
2369 mISDNport->portnum = port;
2370 mISDNport->ntmode = nt;
2371 mISDNport->pri = pri;
2372 mISDNport->ptp = ptp;
2373 mISDNport->b_num = stinf->childcnt;
2374 PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2376 while(i < stinf->childcnt)
2378 mISDNport->b_stid[i] = stinf->child[i];
2379 mISDNport->b_state[i] = B_STATE_IDLE;
2380 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
2384 /* if te-mode, query state link */
2385 if (!mISDNport->ntmode)
2389 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
2390 act.prim = MGR_SHORTSTATUS | REQUEST;
2391 act.addr = mISDNport->upper_id | MSG_BROADCAST;
2392 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
2394 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2396 /* if ptp AND te-mode, pull up the link */
2397 if (mISDNport->ptp && !mISDNport->ntmode)
2401 act.prim = DL_ESTABLISH | REQUEST;
2402 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
2405 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2407 /* if ptp AND nt-mode, pull up the link */
2408 if (mISDNport->ptp && mISDNport->ntmode)
2412 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2413 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2416 /* initially, we assume that the link is down, exept for nt-ptmp */
2417 mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2419 PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2421 start_trace(mISDNport->portnum,
2429 add_trace("channels", NULL, "%d", mISDNport->b_num);
2436 * function to free ALL cards (ports)
2438 void mISDNport_close_all(void)
2440 /* free all ports */
2441 while(mISDNport_first)
2442 mISDNport_close(mISDNport_first);
2446 * free only one port
2448 void mISDNport_close(struct mISDNport *mISDNport)
2450 struct mISDNport **mISDNportp;
2452 class PmISDN *isdnport;
2454 unsigned char buf[32];
2457 /* remove all port instance that are linked to this mISDNport */
2461 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2463 isdnport = (class PmISDN *)port;
2464 if (isdnport->p_m_mISDNport)
2466 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2473 /* only if we are already part of interface */
2474 if (mISDNport->ifport)
2476 start_trace(mISDNport->portnum,
2477 mISDNport->ifport->interface,
2487 /* free bchannels */
2489 while(i < mISDNport->b_num)
2491 if (mISDNport->b_addr[i])
2493 _bchannel_destroy(mISDNport, i);
2494 PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2499 /* free ressources of port */
2500 msg_queue_purge(&mISDNport->downqueue);
2503 if (mISDNport->ntmode)
2505 nst = &mISDNport->nst;
2506 if (nst->manager) /* to see if initialized */
2508 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");
2509 cleanup_Isdnl3(nst);
2510 cleanup_Isdnl2(nst);
2513 msg_queue_purge(&nst->down_queue);
2514 if (nst->phd_down_msg)
2515 FREE(nst->phd_down_msg, 0);
2519 PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
2520 if (mISDNport->d_stid)
2522 if (mISDNport->upper_id)
2523 mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
2526 /* remove from list */
2527 mISDNportp = &mISDNport_first;
2530 if (*mISDNportp == mISDNport)
2532 *mISDNportp = (*mISDNportp)->next;
2536 mISDNportp = &((*mISDNportp)->next);
2540 FATAL("mISDNport not in list\n");
2542 FREE(mISDNport, sizeof(struct mISDNport));
2549 * global function to show all available isdn ports
2551 void mISDN_port_info(void)
2555 int useable, nt, pri;
2556 unsigned char buff[1025];
2557 iframe_t *frm = (iframe_t *)buff;
2558 stack_info_t *stinf;
2562 if ((device = mISDN_open()) < 0)
2564 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));
2568 /* get number of stacks */
2570 ii = mISDN_get_stack_count(device);
2574 printf("Found no card. Please be sure to load card drivers.\n");
2577 /* loop the number of cards and get their info */
2580 err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
2583 fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
2586 stinf = (stack_info_t *)&frm->data.p;
2591 /* output the port info */
2592 printf("Port %2d: ", i);
2593 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2595 case ISDN_PID_L0_TE_S0:
2596 printf("TE-mode BRI S/T interface line (for phone lines)");
2598 if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
2599 printf(" HFC multiport card");
2602 case ISDN_PID_L0_NT_S0:
2604 printf("NT-mode BRI S/T interface port (for phones)");
2606 if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
2607 printf(" HFC multiport card");
2610 case ISDN_PID_L0_TE_E1:
2612 printf("TE-mode PRI E1 interface line (for phone lines)");
2614 if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
2615 printf(" HFC-E1 card");
2618 case ISDN_PID_L0_NT_E1:
2621 printf("NT-mode PRI E1 interface port (for phones)");
2623 if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
2624 printf(" HFC-E1 card");
2629 printf("unknown type 0x%08x",stinf->pid.protocol[0]);
2635 if (stinf->pid.protocol[1] == 0)
2638 printf(" -> Missing layer 1 NT-mode protocol.\n");
2641 while(p <= MAX_LAYER_NR) {
2642 if (stinf->pid.protocol[p])
2645 printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2652 printf(" -> Interface is Point-To-Point (PRI).\n");
2654 printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
2658 if (stinf->pid.protocol[1] == 0)
2661 printf(" -> Missing layer 1 protocol.\n");
2663 if (stinf->pid.protocol[2] == 0)
2666 printf(" -> Missing layer 2 protocol.\n");
2668 if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
2670 printf(" -> Interface is Poin-To-Point.\n");
2672 if (stinf->pid.protocol[3] == 0)
2675 printf(" -> Missing layer 3 protocol.\n");
2678 printf(" -> Protocol: ");
2679 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2681 case ISDN_PID_L3_DSS1USER:
2682 printf("DSS1 (Euro ISDN)");
2687 printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
2692 while(p <= MAX_LAYER_NR) {
2693 if (stinf->pid.protocol[p])
2696 printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2701 printf(" - %d B-channels\n", stinf->childcnt);
2704 printf(" * Port NOT useable for LCR\n");
2706 printf("--------\n");
2713 if ((err = mISDN_close(device)))
2714 FATAL("mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
2719 * enque data from upper buffer
2721 void PmISDN::txfromup(unsigned char *data, int length)
2723 unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2724 iframe_t *frm = (iframe_t *)buf;
2726 /* configure frame */
2727 frm->prim = DL_DATA | REQUEST;
2728 frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
2731 /* check if high priority tones exist
2732 * ignore data in this case
2734 if (p_tone_name[0] || p_m_crypt_msg_loops)
2737 /* preload procedure
2738 * if transmit buffer in DSP module is empty,
2739 * preload it to DSP_LOAD to prevent jitter gaps.
2741 if (p_m_load==0 && ISDN_LOAD>0)
2744 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
2745 frm->len = ISDN_LOAD;
2746 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2747 p_m_load += frm->len;
2750 /* drop if load would exceed ISDN_MAXLOAD
2751 * this keeps the delay not too high
2753 if (p_m_load+length > ISDN_MAXLOAD)
2756 /* load data to buffer
2758 memcpy(buf+mISDN_HEADER_LEN, data, length);
2760 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2761 p_m_load += frm->len;