fix
[lcr.git] / mISDN.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN port abstraction for dss1 and sip                                   **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12
13 #include "main.h"
14 #include <poll.h>
15 #include <errno.h>
16 #include <sys/ioctl.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #ifdef SOCKET_MISDN
21 #include <netinet/udp.h>
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #include <sys/socket.h>
25 #include <pthread.h>
26 #include <linux/mISDNif.h>
27 #include <q931.h>
28 #include <mlayer3.h>
29 #else
30 extern "C" {
31 #include <net_l2.h>
32 }
33 #endif
34
35 #ifndef ISDN_PID_L4_B_USER
36 #define ISDN_PID_L4_B_USER 0x440000ff
37 #endif
38
39 /* list of mISDN ports */
40 struct mISDNport *mISDNport_first;
41
42 /* noise randomizer */
43 unsigned char mISDN_rand[256];
44 int mISDN_rand_count = 0;
45
46 #ifdef MISDN_SOCKET
47 int mISDN_initialize(void)
48 {
49         /* try to open raw socket to check kernel */
50         ret = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
51         if (ret < 0)
52         {
53                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
54                 return(-1);
55         }
56         close(ret);
57
58         init_layer3(4); // buffer of 4
59
60         return(0);
61 }
62
63 void mISDN_deinitialize(void)
64 {
65         cleanup_layer3();
66 }
67 #else
68 int entity = 0; /* used for udevice */
69 int mISDNdevice = -1; /* the device handler and port list */
70
71 int mISDN_initialize(void)
72 {
73         char debug_log[128];
74         unsigned char buff[1025];
75         iframe_t *frm = (iframe_t *)buff;
76         int ret;
77
78         /* initialize stuff of the NT lib */
79         if (options.deb & DEBUG_STACK)
80         {
81                 global_debug = 0xffffffff & ~DBGM_MSG;
82 //              global_debug = DBGM_L3DATA;
83         } else
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);
88         else
89                 debug_init(global_debug, NULL, NULL, NULL);
90         msg_init();
91
92         /* open mISDNdevice if not already open */
93         if (mISDNdevice < 0)
94         {
95                 ret = mISDN_open();
96                 if (ret < 0)
97                 {
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));
99                         return(-1);
100                 }
101                 mISDNdevice = ret;
102                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
103
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)
108                 {
109                         noentity:
110                         FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
111                 }
112                 entity = frm->dinfo & 0xffff;
113                 if (!entity)
114                         goto noentity;
115                 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
116         }
117         return(0);
118 }
119
120 void mISDN_deinitialize(void)
121 {
122         unsigned char buff[1025];
123
124         debug_close();
125
126         if (mISDNdevice >= 0)
127         {
128                 /* free entity */
129                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
130                 /* close device */
131                 mISDN_close(mISDNdevice);
132                 mISDNdevice = -1;
133                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
134         }
135 }
136 #endif
137
138 /*
139  * constructor
140  */
141 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
142 {
143         p_m_mISDNport = mISDNport;
144         p_m_portnum = mISDNport->portnum;
145         p_m_b_index = -1;
146         p_m_b_channel = 0;
147         p_m_b_exclusive = 0;
148         p_m_b_reserve = 0;
149         p_m_delete = 0;
150         p_m_hold = 0;
151         p_m_txvol = p_m_rxvol = 0;
152         p_m_conf = 0;
153         p_m_txdata = 0;
154         p_m_delay = 0;
155         p_m_echo = 0;
156         p_m_tone = 0;
157         p_m_rxoff = 0;
158         p_m_joindata = 0;
159         p_m_dtmf = !mISDNport->ifport->nodtmf;
160         p_m_timeout = 0;
161         p_m_timer = 0;
162         p_m_remote_ref = 0; /* channel shall be exported to given remote */
163         p_m_remote_id = 0; /* channel shall be exported to given remote */
164
165         /* audio */
166         p_m_load = 0;
167         p_m_last_tv_sec = 0;
168
169         /* crypt */
170         p_m_crypt = 0;
171         p_m_crypt_listen = 0;
172         p_m_crypt_msg_loops = 0;
173         p_m_crypt_msg_loops = 0;
174         p_m_crypt_msg_len = 0;
175         p_m_crypt_msg[0] = '\0';
176         p_m_crypt_msg_current = 0;
177         p_m_crypt_key[0] = '\0';
178         p_m_crypt_key_len = 0;
179         p_m_crypt_listen = 0;
180         p_m_crypt_listen_state = 0;
181         p_m_crypt_listen_len = 0;
182         p_m_crypt_listen_msg[0] = '\0';
183         p_m_crypt_listen_crc = 0;
184
185         /* if any channel requested by constructor */
186         if (channel == CHANNEL_ANY)
187         {
188                 /* reserve channel */
189                 p_m_b_reserve = 1;
190                 mISDNport->b_reserved++;
191         }
192
193         /* reserve channel */
194         if (channel > 0) // only if constructor was called with a channel resevation
195                 seize_bchannel(channel, exclusive);
196
197         /* we increase the number of objects: */
198         mISDNport->use++;
199         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
200 }
201
202
203 /*
204  * destructor
205  */
206 PmISDN::~PmISDN()
207 {
208         struct message *message;
209
210         /* remove bchannel relation */
211         drop_bchannel();
212
213         /* release epoint */
214         while (p_epointlist)
215         {
216                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
217                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
218                 message->param.disconnectinfo.cause = 16;
219                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
220                 message_put(message);
221                 /* remove from list */
222                 free_epointlist(p_epointlist);
223         }
224
225         /* we decrease the number of objects: */
226         p_m_mISDNport->use--;
227         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
228 }
229
230
231 /*
232  * trace
233  */
234 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
235 {
236         /* init trace with given values */
237         start_trace(mISDNport?mISDNport->portnum:0,
238                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
239                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
240                     port?port->p_dialinginfo.id:NULL,
241                     direction,
242                     CATEGORY_CH,
243                     port?port->p_serial:0,
244                     msgtext);
245 }
246
247
248 /*
249  * layer trace header
250  */
251 static struct isdn_message {
252         char *name;
253         unsigned long value;
254 } isdn_message[] = {
255         {"TIMEOUT", CC_TIMEOUT},
256         {"SETUP", CC_SETUP},
257         {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
258         {"PROCEEDING", CC_PROCEEDING},
259         {"ALERTING", CC_ALERTING},
260         {"CONNECT", CC_CONNECT},
261         {"CONNECT RES", CC_CONNECT},
262         {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
263         {"DISCONNECT", CC_DISCONNECT},
264         {"RELEASE", CC_RELEASE},
265         {"RELEASE_COMP", CC_RELEASE_COMPLETE},
266         {"INFORMATION", CC_INFORMATION},
267         {"PROGRESS", CC_PROGRESS},
268         {"NOTIFY", CC_NOTIFY},
269         {"SUSPEND", CC_SUSPEND},
270         {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
271         {"SUSPEND_REJ", CC_SUSPEND_REJECT},
272         {"RESUME", CC_RESUME},
273         {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
274         {"RESUME_REJ", CC_RESUME_REJECT},
275         {"HOLD", CC_HOLD},
276         {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
277         {"HOLD_REJ", CC_HOLD_REJECT},
278         {"RETRIEVE", CC_RETRIEVE},
279         {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
280         {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
281         {"FACILITY", CC_FACILITY},
282         {"STATUS", CC_STATUS},
283         {"RESTART", CC_RESTART},
284         {"RELEASE_CR", CC_RELEASE_CR},
285         {"NEW_CR", CC_NEW_CR},
286         {"DL_ESTABLISH", DL_ESTABLISH},
287         {"DL_RELEASE", DL_RELEASE},
288         {"PH_ACTIVATE", PH_ACTIVATE},
289         {"PH_DEACTIVATE", PH_DEACTIVATE},
290
291         {NULL, 0},
292 };
293 static char *isdn_prim[4] = {
294         " REQUEST",
295         " CONFIRM",
296         " INDICATION",
297         " RESPONSE",
298 };
299 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
300 {
301         int i;
302         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
303
304         /* select message and primitive text */
305         i = 0;
306         while(isdn_message[i].name)
307         {
308                 if (isdn_message[i].value == (prim&0xffffff00))
309                 {
310                         SCPY(msgtext, isdn_message[i].name);
311                         break;
312                 }
313                 i++;
314         }
315         SCAT(msgtext, isdn_prim[prim&0x00000003]);
316
317         /* add direction */
318         if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
319         {
320                 if (mISDNport)
321                 {
322                         if (mISDNport->ntmode)
323                         {
324                                 if (direction == DIRECTION_OUT)
325                                         SCAT(msgtext, " N->U");
326                                 else
327                                         SCAT(msgtext, " N<-U");
328                         } else
329                         {
330                                 if (direction == DIRECTION_OUT)
331                                         SCAT(msgtext, " U->N");
332                                 else
333                                         SCAT(msgtext, " U<-N");
334                         }
335                 }
336         }
337
338         /* init trace with given values */
339         start_trace(mISDNport?mISDNport->portnum:0,
340                     mISDNport?mISDNport->ifport->interface:NULL,
341                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
342                     port?port->p_dialinginfo.id:NULL,
343                     direction,
344                     CATEGORY_CH,
345                     port?port->p_serial:0,
346                     msgtext);
347 }
348
349
350 /*
351  * send control information to the channel (dsp-module)
352  */
353 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, int c2, char *trace_name, int trace_value)
354 {
355         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
356         iframe_t *ctrl = (iframe_t *)buffer; 
357         unsigned long *d = (unsigned long *)&ctrl->data.p;
358
359         ctrl->prim = PH_CONTROL | REQUEST;
360         ctrl->addr = b_addr | FLG_MSG_DOWN;
361         ctrl->dinfo = 0;
362         ctrl->len = sizeof(int)*2;
363         *d++ = c1;
364         *d++ = c2;
365         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
366         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
367         if (c1 == CMX_CONF_JOIN)
368                 add_trace(trace_name, NULL, "0x%08x", trace_value);
369         else
370                 add_trace(trace_name, NULL, "%d", trace_value);
371         end_trace();
372 }
373
374 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 {
376         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
377         iframe_t *ctrl = (iframe_t *)buffer;
378         unsigned long *d = (unsigned long *)&ctrl->data.p;
379
380         ctrl->prim = PH_CONTROL | REQUEST;
381         ctrl->addr = b_addr | FLG_MSG_DOWN;
382         ctrl->dinfo = 0;
383         ctrl->len = sizeof(int)+c2_len;
384         *d++ = c1;
385         memcpy(d, c2, c2_len);
386         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
387         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
388         add_trace(trace_name, NULL, "%d", trace_value);
389         end_trace();
390 }
391
392
393 /*
394  * subfunction for bchannel_event
395  * create stack
396  */
397 static int _bchannel_create(struct mISDNport *mISDNport, int i)
398 {
399         unsigned char buff[1024];
400         layer_info_t li;
401         mISDN_pid_t pid;
402         int ret;
403
404         if (!mISDNport->b_stid[i])
405         {
406                 PERROR("Error: no stack for index %d\n", i);
407                 return(0);
408         }
409         if (mISDNport->b_addr[i])
410         {
411                 PERROR("Error: stack already created for index %d\n", i);
412                 return(0);
413         }
414
415         /* create new layer */
416         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
417         memset(&li, 0, sizeof(li));
418         memset(&pid, 0, sizeof(pid));
419         li.object_id = -1;
420         li.extentions = 0;
421         li.st = mISDNport->b_stid[i];
422         UCPY(li.name, "B L4");
423         li.pid.layermask = ISDN_LAYER((4));
424         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
425         ret = mISDN_new_layer(mISDNdevice, &li);
426         if (ret)
427         {
428                 failed_new_layer:
429                 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
430                 goto failed;
431         }
432         mISDNport->b_addr[i] = li.id;
433         if (!li.id)
434         {
435                 goto failed_new_layer;
436         }
437         PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
438
439         /* create new stack */
440         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
441         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
442         pid.protocol[3] = ISDN_PID_L3_B_DSP;
443         pid.protocol[4] = ISDN_PID_L4_B_USER;
444         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
445         ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
446         if (ret)
447         {
448                 stack_error:
449                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
450                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
451                 goto failed;
452         }
453         ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
454         if (ret)
455                 goto stack_error;
456
457         /* get layer id */
458         mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
459         if (!mISDNport->b_addr[i])
460                 goto stack_error;
461         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
462         add_trace("channel", NULL, "%d", i+1+(i>=15));
463         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
464         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
465         end_trace();
466
467         return(1);
468
469 failed:
470         mISDNport->b_addr[i] = 0;
471         return(0);
472 }
473
474
475 /*
476  * subfunction for bchannel_event
477  * activate / deactivate request
478  */
479 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
480 {
481         iframe_t act;
482
483         /* activate bchannel */
484         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
485         add_trace("channel", NULL, "%d", i+1+(i>=15));
486         end_trace();
487         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
488         act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
489         act.dinfo = 0;
490         act.len = 0;
491         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
492 }
493
494
495 /*
496  * subfunction for bchannel_event
497  * set features
498  */
499 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
500 {
501         struct PmISDN *port;
502         int addr;
503
504         port = mISDNport->b_port[i];
505         addr = mISDNport->b_addr[i];
506         if (!port)
507         {
508                 PERROR("bchannel index i=%d not associated with a port object\n", i);
509                 return;
510         }
511
512         /* set dsp features */
513         if (port->p_m_txdata)
514                 ph_control(mISDNport, port, addr, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
515         if (port->p_m_delay)
516                 ph_control(mISDNport, port, addr, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
517         if (port->p_m_txvol)
518                 ph_control(mISDNport, port, addr, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
519         if (port->p_m_rxvol)
520                 ph_control(mISDNport, port, addr, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
521         if (port->p_m_conf)
522                 ph_control(mISDNport, port, addr, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
523         if (port->p_m_echo)
524                 ph_control(mISDNport, port, addr, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
525         if (port->p_m_tone)
526                 ph_control(mISDNport, port, addr, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
527         if (port->p_m_rxoff)
528                 ph_control(mISDNport, port, addr, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
529 //      if (port->p_m_txmix)
530 //              ph_control(mISDNport, port, addr, CMX_MIX_ON, 0, "DSP-MIX", 1);
531         if (port->p_m_dtmf)
532                 ph_control(mISDNport, port, addr, DTMF_TONE_START, 0, "DSP-DTMF", 1);
533         if (port->p_m_crypt)
534                 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);
535 }
536
537 /*
538  * subfunction for bchannel_event
539  * destroy stack
540  */
541 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
542 {
543         unsigned char buff[1024];
544
545         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
546         add_trace("channel", NULL, "%d", i+1+(i>=15));
547         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
548         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
549         end_trace();
550         /* remove our stack only if set */
551         if (mISDNport->b_addr[i])
552         {
553                 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
554                 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
555                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
556                 mISDNport->b_addr[i] = 0;
557         }
558 }
559
560
561 /*
562 bchannel procedure
563 ------------------
564
565 A bchannel goes through the following states in this order:
566
567 - B_STATE_IDLE
568 No one is using the bchannel.
569 It is available and not linked to Port class, nor reserved.
570
571 - B_STATE_ACTIVATING
572 The bchannel stack is created and an activation request is sent.
573 It MAY be linked to Port class, but already unlinked due to Port class removal.
574
575 - B_STATE_ACTIVE
576 The bchannel is active and cofigured to the Port class needs.
577 Also it is linked to a Port class, otherwhise it would be deactivated.
578
579 - B_STATE_DEACTIVATING
580 The bchannel is in deactivating state, due to deactivation request.
581 It may be linked to a Port class, that likes to reactivate it.
582
583 - B_STATE_IDLE
584 See above.
585 After deactivating bchannel, and if not used, the bchannel becomes idle again.
586
587 Also the bchannel may be exported, but only if the state is or becomes idle:
588
589 - B_STATE_EXPORTING
590 The bchannel assignment has been sent to the remove application.
591
592 - B_STATE_REMOTE
593 The bchannel assignment is acknowledged by the remote application.
594
595 - B_STATE_IMPORTING
596 The bchannel is re-imported by mISDN port object.
597
598 - B_STATE_IDLE
599 See above.
600 After re-importing bchannel, and if not used, the bchannel becomes idle again.
601
602
603 A bchannel can have the following events:
604
605 - B_EVENT_USE
606 A bchannel is required by a Port class.
607 The bchannel shall be exported to the remote application.
608
609 - B_EVENT_ACTIVATED
610 The bchannel beomes active.
611
612 - B_EVENT_DROP
613 The bchannel is not required by Port class anymore
614
615 - B_EVENT_DEACTIVATED
616 The bchannel becomes inactive.
617
618 - B_EVENT_EXPORTED
619 The bchannel is now used by remote application.
620
621 - B_EVENT_IMPORTED
622 The bchannel is not used by remote application.
623
624 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
625
626 if an export request is receive by remote application, p_m_exportremote is set.
627 the b_remotejoin[index] indicates if linked port shall be exported.
628 - set on export request from remote application (if port is assigned)
629 - set on channel use, if requested by remote application (p_m_exportremote)
630 - cleared on drop request
631
632 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
633 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
634 the bchannel import/export is acknowledged with stack given.
635
636 if exporting, b_remotesocket[index] is set to the remote socket id.
637 if importing has been acknowledged. b_remotesockt[index] is cleared.
638
639 */
640
641 /*
642  * process bchannel events
643  * - mISDNport is a pointer to the port's structure
644  * - i is the index of the bchannel
645  * - event is the B_EVENT_* value
646  * - port is the PmISDN class pointer
647  */
648 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
649 {
650         class PmISDN *b_port = mISDNport->b_port[i];
651         int state = mISDNport->b_state[i];
652         unsigned long p_m_remote_ref = 0;
653         unsigned long p_m_remote_id = 0;
654         unsigned long addr = mISDNport->b_addr[i];
655
656         if (b_port)
657         {
658                 p_m_remote_id = b_port->p_m_remote_id;
659                 p_m_remote_ref = b_port->p_m_remote_ref;
660         }
661
662         switch(event)
663         {
664                 case B_EVENT_USE:
665                 /* port must be linked in order to allow activation */
666                 if (!b_port)
667                         FATAL("bchannel must be linked to a Port class\n");
668                 switch(state)
669                 {
670                         case B_STATE_IDLE:
671                         if (p_m_remote_id)
672                         {
673                                 /* export bchannel */
674                                 message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
675                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
676                                 add_trace("type", NULL, "assign");
677                                 add_trace("stack", "address", "%x", addr);
678                                 end_trace();
679                                 state = B_STATE_EXPORTING;
680                                 mISDNport->b_remote_id[i] = p_m_remote_id;
681                         } else
682                         {
683                                 /* create stack and send activation request */
684                                 if (_bchannel_create(mISDNport, i))
685                                 {
686                                         _bchannel_activate(mISDNport, i, 1);
687                                         state = B_STATE_ACTIVATING;
688                                 }
689                         }
690                         break;
691
692                         case B_STATE_ACTIVATING:
693                         case B_STATE_EXPORTING:
694                         /* do nothing, because it is already activating */
695                         break;
696
697                         case B_STATE_DEACTIVATING:
698                         case B_STATE_IMPORTING:
699                         /* do nothing, because we must wait until we can reactivate */
700                         break;
701
702                         default:
703                         /* problems that might ocurr:
704                          * B_EVENT_USE is received when channel already in use.
705                          * bchannel exported, but not freed by other port
706                          */
707                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
708                 }
709                 break;
710
711                 case B_EVENT_EXPORTREQUEST:
712                 /* special case where the bchannel is requested by remote */
713                 if (!p_m_remote_id)
714                 {
715                         PERROR("export request without remote channel set, please correct.\n");
716                         break;
717                 }
718                 switch(state)
719                 {
720                         case B_STATE_IDLE:
721                         /* in case, the bchannel is exported right after seize_bchannel */
722                         /* export bchannel */
723                         /* p_m_remote_id is set, when this event happens. */
724                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
725                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
726                         add_trace("type", NULL, "assign");
727                         add_trace("stack", "address", "%x", addr);
728                         end_trace();
729                         state = B_STATE_EXPORTING;
730                         mISDNport->b_remote_id[i] = p_m_remote_id;
731                         break;
732
733                         case B_STATE_ACTIVATING:
734                         case B_STATE_EXPORTING:
735                         /* do nothing, because it is already activating */
736                         break;
737
738                         case B_STATE_DEACTIVATING:
739                         case B_STATE_IMPORTING:
740                         /* do nothing, because we must wait until we can reactivate */
741                         break;
742
743                         case B_STATE_ACTIVE:
744                         /* bchannel is active, so we deactivate */
745                         _bchannel_activate(mISDNport, i, 0);
746                         state = B_STATE_DEACTIVATING;
747                         break;
748
749                         default:
750                         /* problems that might ocurr:
751                          * ... when channel already in use.
752                          * bchannel exported, but not freed by other port
753                          */
754                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
755                 }
756                 break;
757
758                 case B_EVENT_ACTIVATED:
759                 switch(state)
760                 {
761                         case B_STATE_ACTIVATING:
762                         if (b_port && !p_m_remote_id)
763                         {
764                                 /* bchannel is active and used by Port class, so we configure bchannel */
765                                 _bchannel_configure(mISDNport, i);
766                                 state = B_STATE_ACTIVE;
767                         } else
768                         {
769                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
770                                 _bchannel_activate(mISDNport, i, 0);
771                                 state = B_STATE_DEACTIVATING;
772                         }
773                         break;
774
775                         default:
776                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
777                 }
778                 break;
779
780                 case B_EVENT_EXPORTED:
781                 switch(state)
782                 {
783                         case B_STATE_EXPORTING:
784                         if (b_port && p_m_remote_id)
785                         {
786                                 /* remote export done */
787                                 state = B_STATE_REMOTE;
788                         } else
789                         {
790                                 /* bchannel is now exported, but we need bchannel back OR bchannel is not used anymore, so reimport, to later export to new remote */
791                                 message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, addr);
792                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
793                                 add_trace("type", NULL, "remove");
794                                 add_trace("stack", "address", "%x", addr);
795                                 end_trace();
796                                 state = B_STATE_IMPORTING;
797                         }
798                         break;
799
800                         default:
801                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
802                 }
803                 break;
804
805                 case B_EVENT_DROP:
806                 if (!b_port)
807                         FATAL("bchannel must be linked to a Port class\n");
808                 switch(state)
809                 {
810                         case B_STATE_IDLE:
811                         /* bchannel is idle due to an error, so we do nothing */
812                         break;
813
814                         case B_STATE_ACTIVATING:
815                         case B_STATE_EXPORTING:
816                         /* do nothing because we must wait until bchanenl is active before deactivating */
817                         break;
818
819                         case B_STATE_ACTIVE:
820                         /* bchannel is active, so we deactivate */
821                         _bchannel_activate(mISDNport, i, 0);
822                         state = B_STATE_DEACTIVATING;
823                         break;
824
825                         case B_STATE_REMOTE:
826                         /* bchannel is exported, so we re-import */
827                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, addr);
828                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
829                         add_trace("type", NULL, "remove");
830                         add_trace("stack", "address", "%x", addr);
831                         end_trace();
832                         state = B_STATE_IMPORTING;
833                         break;
834
835                         case B_STATE_DEACTIVATING:
836                         case B_STATE_IMPORTING:
837                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
838                         break;
839
840                         default:
841                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
842                 }
843                 break;
844
845                 case B_EVENT_DEACTIVATED:
846                 switch(state)
847                 {
848                         case B_STATE_IDLE:
849                         /* ignore due to deactivation confirm after unloading */
850                         break;
851
852                         case B_STATE_DEACTIVATING:
853                         _bchannel_destroy(mISDNport, i);
854                         state = B_STATE_IDLE;
855                         if (b_port)
856                         {
857                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
858                                 if (p_m_remote_id)
859                                 {
860                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
861                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
862                                         add_trace("type", NULL, "assign");
863                                         add_trace("stack", "address", "%x", addr);
864                                         end_trace();
865                                         state = B_STATE_EXPORTING;
866                                         mISDNport->b_remote_id[i] = p_m_remote_id;
867                                 } else
868                                 {
869                                         if (_bchannel_create(mISDNport, i))
870                                         {
871                                                 _bchannel_activate(mISDNport, i, 1);
872                                                 state = B_STATE_ACTIVATING;
873                                         }
874                                 }
875                         }
876                         break;
877
878                         default:
879                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
880                 }
881                 break;
882
883                 case B_EVENT_IMPORTED:
884                 switch(state)
885                 {
886                         case B_STATE_IMPORTING:
887                         state = B_STATE_IDLE;
888                         mISDNport->b_remote_id[i] = 0;
889                         if (b_port)
890                         {
891                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
892                                 if (p_m_remote_id)
893                                 {
894                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
895                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
896                                         add_trace("type", NULL, "assign");
897                                         add_trace("stack", "address", "%x", addr);
898                                         end_trace();
899                                         state = B_STATE_EXPORTING;
900                                         mISDNport->b_remote_id[i] = p_m_remote_id;
901                                 } else
902                                 {
903                                         if (_bchannel_create(mISDNport, i))
904                                         {
905                                                 _bchannel_activate(mISDNport, i, 1);
906                                                 state = B_STATE_ACTIVATING;
907                                         }
908                                 }
909                         }
910                         break;
911
912                         default:
913                         /* ignore, because not assigned */
914                         ;
915                 }
916                 break;
917
918                 default:
919                 PERROR("Illegal event %d, please correct.\n", event);
920         }
921
922         mISDNport->b_state[i] = state;
923 }
924
925
926
927
928 /*
929  * check for available channel and reserve+set it.
930  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
931  * give exclusiv flag
932  * returns -(cause value) or x = channel x or 0 = no channel
933  * NOTE: no activation is done here
934  */
935 int PmISDN::seize_bchannel(int channel, int exclusive)
936 {
937         int i;
938
939         /* the channel is what we have */
940         if (p_m_b_channel == channel)
941                 return(channel);
942
943         /* if channel already in use, release it */
944         if (p_m_b_channel)
945                 drop_bchannel();
946
947         /* if CHANNEL_NO */
948         if (channel==CHANNEL_NO || channel==0)
949                 return(0);
950         
951         /* is channel in range ? */
952         if (channel==16
953          || (channel>p_m_mISDNport->b_num && channel<16)
954          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
955                 return(-6); /* channel unacceptable */
956
957         /* request exclusive channel */
958         if (exclusive && channel>0)
959         {
960                 i = channel-1-(channel>16);
961                 if (p_m_mISDNport->b_port[i])
962                         return(-44); /* requested channel not available */
963                 goto seize;
964         }
965
966         /* ask for channel */
967         if (channel>0)
968         {
969                 i = channel-1-(channel>16);
970                 if (p_m_mISDNport->b_port[i] == NULL)
971                         goto seize;
972         }
973
974         /* search for channel */
975         i = 0;
976         while(i < p_m_mISDNport->b_num)
977         {
978                 if (!p_m_mISDNport->b_port[i])
979                 {
980                         channel = i+1+(i>=15);
981                         goto seize;
982                 }
983                 i++;
984         }
985         return(-34); /* no free channel */
986
987 seize:
988         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
989
990         /* link Port */
991         p_m_mISDNport->b_port[i] = this;
992         p_m_b_index = i;
993         p_m_b_channel = channel;
994         p_m_b_exclusive = exclusive;
995
996         /* reserve channel */
997         if (!p_m_b_reserve)
998         {
999                 p_m_b_reserve = 1;
1000                 p_m_mISDNport->b_reserved++;
1001         }
1002
1003         return(channel);
1004 }
1005
1006 /*
1007  * drop reserved channel and unset it.
1008  * deactivation is also done
1009  */
1010 void PmISDN::drop_bchannel(void)
1011 {
1012         if (p_m_b_index < 0)
1013                 return;
1014
1015         /* unreserve channel */
1016         if (p_m_b_reserve)
1017                 p_m_mISDNport->b_reserved--;
1018         p_m_b_reserve = 0;
1019
1020         /* if not in use */
1021         if (!p_m_b_channel)
1022                 return;
1023
1024         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1025
1026         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1027                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1028         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1029         p_m_b_index = -1;
1030         p_m_b_channel = 0;
1031         p_m_b_exclusive = 0;
1032 }
1033
1034 /* process bchannel export/import message from join */
1035 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long addr)
1036 {
1037         class Endpoint *epoint;
1038         class Port *port;
1039         class PmISDN *isdnport;
1040         struct mISDNport *mISDNport;
1041         int i, ii;
1042
1043         switch(type)
1044         {
1045                 case BCHANNEL_REQUEST:
1046                 /* find the port object for the join object ref */
1047                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1048                 {
1049                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1050                         return;
1051                 }
1052                 if (!epoint->ep_portlist)
1053                 {
1054                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1055                         return;
1056                 }
1057                 if (epoint->ep_portlist->next)
1058                 {
1059                         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);
1060                 }
1061                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1062                 {
1063                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1064                         return;
1065                 }
1066                 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1067                 {
1068                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1069                 }
1070                 isdnport = (class PmISDN *)port;
1071
1072                 /* assign */
1073                 if (isdnport->p_m_remote_id)
1074                 {
1075                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1076                         break;
1077                 }
1078                 mISDNport = isdnport->p_m_mISDNport;
1079                 i = isdnport->p_m_b_index;
1080                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1081                 add_trace("type", NULL, "export request");
1082                 isdnport->p_m_remote_ref = joinremote->j_serial;
1083                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1084                 if (mISDNport && i>=0)
1085                 {
1086                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1087                 }
1088                 end_trace();
1089                 break;
1090
1091                 case BCHANNEL_ASSIGN_ACK:
1092                 case BCHANNEL_REMOVE_ACK:
1093                 /* find mISDNport for stack ID */
1094                 mISDNport = mISDNport_first;
1095                 while(mISDNport)
1096                 {
1097                         i = 0;
1098                         ii = mISDNport->b_num;
1099                         while(i < ii)
1100                         {
1101                                 if (mISDNport->b_addr[i] == addr)
1102                                         break;
1103                                 i++;
1104                         }
1105                         if (i != ii)
1106                                 break;
1107                         mISDNport = mISDNport->next;
1108                 }
1109                 if (!mISDNport)
1110                 {
1111                         PERROR("received assign/remove ack for addr=%x, but address does not exist.\n", addr);
1112                         break;
1113                 }
1114                 /* mISDNport may now be set or NULL */
1115                 
1116                 /* set */
1117                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1118                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1119                 if (mISDNport && i>=0)
1120                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1121                 end_trace();
1122                 break;
1123                 default:
1124                 PERROR("received wrong bchannel message type %d from remote\n", type);
1125         }
1126 }
1127
1128
1129 /*
1130  * handler
1131
1132 audio transmission procedure:
1133 -----------------------------
1134
1135 * priority
1136 three sources of audio transmission:
1137 - crypto-data high priority
1138 - tones high priority (also high)
1139 - remote-data low priority
1140
1141 * elapsed
1142 a variable that temporarily shows the number of samples elapsed since last transmission process.
1143 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1144
1145 * load
1146 a variable that is increased whenever data is transmitted.
1147 it is decreased while time elapses. it stores the number of samples that
1148 are currently loaded to dsp module.
1149 since clock in dsp module is the same clock for user space process, these 
1150 times have no skew.
1151
1152 * levels
1153 there are two levels:
1154 ISDN_LOAD will give the load that have to be kept in dsp.
1155 ISDN_MAXLOAD will give the maximum load before dropping.
1156
1157 * procedure for low priority data
1158 see txfromup() for procedure
1159 in short: remote data is ignored during high priority tones
1160
1161 * procedure for high priority data
1162 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1163 if no more data is available, load becomes empty again.
1164
1165 'load' variable:
1166 0                    ISDN_LOAD           ISDN_MAXLOAD
1167 +--------------------+----------------------+
1168 |                    |                      |
1169 +--------------------+----------------------+
1170
1171 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1172 0                    ISDN_LOAD           ISDN_MAXLOAD
1173 +--------------------+----------------------+
1174 |TTTTTTTTTTTTTTTTTTTT|                      |
1175 +--------------------+----------------------+
1176
1177 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1178 0                    ISDN_LOAD           ISDN_MAXLOAD
1179 +--------------------+----------------------+
1180 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1181 +--------------------+----------------------+
1182
1183  */
1184 int PmISDN::handler(void)
1185 {
1186         struct message *message;
1187         int elapsed = 0;
1188         int ret;
1189
1190         if ((ret = Port::handler()))
1191                 return(ret);
1192
1193         /* get elapsed */
1194         if (p_m_last_tv_sec)
1195         {
1196                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1197                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1198         } else
1199         {
1200                 /* set clock of first process ever in this instance */
1201                 p_m_last_tv_sec = now_tv.tv_sec;
1202                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1203         }
1204         /* process only if we have a minimum of samples, to make packets not too small */
1205         if (elapsed >= ISDN_TRANSMIT)
1206         {
1207                 /* set clock of last process! */
1208                 p_m_last_tv_sec = now_tv.tv_sec;
1209                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1210
1211                 /* update load */
1212                 if (elapsed < p_m_load)
1213                         p_m_load -= elapsed;
1214                 else
1215                         p_m_load = 0;
1216
1217                 /* to send data, tone must be active OR crypt messages must be on */
1218                 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
1219                 {
1220                         int tosend = ISDN_LOAD - p_m_load, length; 
1221                         unsigned char buf[mISDN_HEADER_LEN+tosend];
1222                         iframe_t *frm = (iframe_t *)buf;
1223                         unsigned char *p = buf+mISDN_HEADER_LEN;
1224
1225                         /* copy crypto loops */
1226                         while (p_m_crypt_msg_loops && tosend)
1227                         {
1228                                 /* how much do we have to send */
1229                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1230
1231                                 /* clip tosend */
1232                                 if (length > tosend)
1233                                         length = tosend;
1234
1235                                 /* copy message (part) to buffer */
1236                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1237
1238                                 /* new position */
1239                                 p_m_crypt_msg_current += length;
1240                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1241                                 {
1242                                         /* next loop */
1243                                         p_m_crypt_msg_current = 0;
1244                                         p_m_crypt_msg_loops--;
1245                                 }
1246
1247                                 /* new length */
1248                                 tosend -= length;
1249                         }
1250
1251                         /* copy tones */
1252                         if (p_tone_name[0] && tosend)
1253                         {
1254                                 tosend -= read_audio(p, tosend);
1255                         }
1256
1257                         /* send data */
1258                         frm->prim = DL_DATA | REQUEST; 
1259                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1260                         frm->dinfo = 0;
1261                         frm->len = ISDN_LOAD - p_m_load - tosend;
1262                         if (frm->len)
1263                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1264                         p_m_load += frm->len;
1265                 }
1266         }
1267
1268         // NOTE: deletion is done by the child class
1269
1270         /* handle timeouts */
1271         if (p_m_timeout)
1272         {
1273                 if (p_m_timer+p_m_timeout < now_d)
1274                 {
1275                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1276                         p_m_timeout = 0;
1277                         /* send timeout to endpoint */
1278                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1279                         message->param.state = p_state;
1280                         message_put(message);
1281                         return(1);
1282                 }
1283         }
1284         
1285         return(0); /* nothing done */
1286 }
1287
1288
1289 /*
1290  * whenever we get audio data from bchannel, we process it here
1291  */
1292 void PmISDN::bchannel_receive(iframe_t *frm)
1293 {
1294         unsigned char *data_temp;
1295         unsigned long length_temp;
1296         struct message *message;
1297         unsigned char *p;
1298         int l;
1299         unsigned long cont;
1300
1301         if (frm->prim == (PH_CONTROL | INDICATION))
1302         {
1303                 if (frm->len < 4)
1304                 {
1305                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1306                         return;
1307                 }
1308                 cont = *((unsigned long *)&frm->data.p);
1309                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1310                 {
1311                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1312                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1313                         end_trace();
1314                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1315                         message->param.dtmf = cont & DTMF_TONE_MASK;
1316                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1317                         message_put(message);
1318                         return;
1319                 }
1320                 switch(cont)
1321                 {
1322                         case BF_REJECT:
1323                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1324                         add_trace("DSP-CRYPT", NULL, "error");
1325                         end_trace();
1326                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1327                         message->param.crypt.type = CC_ERROR_IND;
1328                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1329                         message_put(message);
1330                         break;
1331
1332                         case BF_ACCEPT:
1333                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1334                         add_trace("DSP-CRYPT", NULL, "ok");
1335                         end_trace();
1336                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1337                         message->param.crypt.type = CC_ACTBF_CONF;
1338                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1339                         message_put(message);
1340                         break;
1341
1342                         case CMX_TX_DATA:
1343                         if (!p_m_txdata)
1344                         {
1345                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1346                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1347                                 return;
1348                         }
1349                         if (p_record)
1350                                 record((unsigned char *)(cont+1), frm->len - 4, 1); // from up
1351                         break;
1352
1353                         default:
1354                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1355                         add_trace("unknown", NULL, "0x%x", cont);
1356                         end_trace();
1357                 }
1358                 return;
1359         }
1360         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1361         {
1362                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1363                 return;
1364         }
1365
1366         /* calls will not process any audio data unless
1367          * the call is connected OR interface features audio during call setup.
1368          */
1369 //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);     
1370 #ifndef DEBUG_COREBRIDGE
1371         if (p_state!=PORT_STATE_CONNECT
1372          && !p_m_mISDNport->earlyb)
1373                 return;
1374 #endif
1375
1376         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1377         if (p_m_rxoff)
1378         {
1379                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1380                 return;
1381         }
1382
1383         /* record data */
1384         if (p_record)
1385                 record((unsigned char *)&frm->data.p, frm->len, 0); // from down
1386
1387         /* randomize and listen to crypt message if enabled */
1388         if (p_m_crypt_listen)
1389         {
1390                 /* the noisy randomizer */
1391                 p = (unsigned char *)&frm->data.p;
1392                 l = frm->len;
1393                 while(l--)
1394                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1395
1396                 cryptman_listen_bch((unsigned char *)&frm->data.p, frm->len);
1397         }
1398
1399         p = (unsigned char *)&frm->data.p;
1400
1401         /* send data to epoint */
1402         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1403         {
1404                 length_temp = frm->len;
1405                 data_temp = p;
1406                 while(length_temp)
1407                 {
1408                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1409                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1410                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1411                         message_put(message);
1412                         if (length_temp <= sizeof(message->param.data.data))
1413                                 break;
1414                         data_temp += sizeof(message->param.data.data);
1415                         length_temp -= sizeof(message->param.data.data);
1416                 }
1417         }
1418 }
1419
1420
1421 /*
1422  * set echotest
1423  */
1424 void PmISDN::set_echotest(int echo)
1425 {
1426         if (p_m_echo != echo)
1427         {
1428                 p_m_echo = echo;
1429                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1430                 if (p_m_b_channel)
1431                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1432                                 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);
1433         }
1434 }
1435
1436 /*
1437  * set tone
1438  */
1439 void PmISDN::set_tone(char *dir, char *tone)
1440 {
1441         int id;
1442
1443         if (!tone)
1444                 tone = "";
1445         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1446         if (!tone[0])
1447         {
1448                 id = TONE_OFF;
1449                 goto setdsp;
1450         }
1451
1452         /* check if we NOT really have to use a dsp-tone */
1453         if (!options.dsptones)
1454         {
1455                 nodsp:
1456                 if (p_m_tone)
1457                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1458                 {
1459                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1460                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1461                 }
1462                 p_m_tone = 0;
1463                 Port::set_tone(dir, tone);
1464                 return;
1465         }
1466         if (p_tone_dir[0])
1467                 goto nodsp;
1468
1469         /* now we USE dsp-tone, convert name */
1470         else if (!strcmp(tone, "dialtone"))
1471         {
1472                 switch(options.dsptones) {
1473                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1474                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1475                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1476                 }
1477         } else if (!strcmp(tone, "dialpbx"))
1478         {
1479                 switch(options.dsptones) {
1480                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1481                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1482                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1483                 }
1484         } else if (!strcmp(tone, "ringing"))
1485         {
1486                 switch(options.dsptones) {
1487                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1488                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1489                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1490                 }
1491         } else if (!strcmp(tone, "ringpbx"))
1492         {
1493                 switch(options.dsptones) {
1494                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1495                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1496                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1497                 }
1498         } else if (!strcmp(tone, "busy"))
1499         {
1500                 busy:
1501                 switch(options.dsptones) {
1502                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1503                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1504                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1505                 }
1506         } else if (!strcmp(tone, "release"))
1507         {
1508                 hangup:
1509                 switch(options.dsptones) {
1510                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1511                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1512                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1513                 }
1514         } else if (!strcmp(tone, "cause_10"))
1515                 goto hangup;
1516         else if (!strcmp(tone, "cause_11"))
1517                 goto busy;
1518         else if (!strcmp(tone, "cause_22"))
1519         {
1520                 switch(options.dsptones) {
1521                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1522                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1523                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1524                 }
1525         } else if (!strncmp(tone, "cause_", 6))
1526                 id = TONE_SPECIAL_INFO;
1527         else
1528                 id = TONE_OFF;
1529
1530         /* if we have a tone that is not supported by dsp */
1531         if (id==TONE_OFF && tone[0])
1532                 goto nodsp;
1533
1534         setdsp:
1535         if (p_m_tone != id)
1536         {
1537                 /* set new tone */
1538                 p_m_tone = id;
1539                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1540                 if (p_m_b_channel)
1541                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1542                                 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);
1543         }
1544         /* turn user-space tones off in cases of no tone OR dsp tone */
1545         Port::set_tone("",NULL);
1546 }
1547
1548
1549 /* MESSAGE_mISDNSIGNAL */
1550 //extern struct message *dddebug;
1551 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1552 {
1553         switch(param->mISDNsignal.message)
1554         {
1555                 case mISDNSIGNAL_VOLUME:
1556                 if (p_m_txvol != param->mISDNsignal.txvol)
1557                 {
1558                         p_m_txvol = param->mISDNsignal.txvol;
1559                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1560                         if (p_m_b_channel)
1561                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1562                                         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);
1563                 } else
1564                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1565                 if (p_m_rxvol != param->mISDNsignal.rxvol)
1566                 {
1567                         p_m_rxvol = param->mISDNsignal.rxvol;
1568                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1569                         if (p_m_b_channel)
1570                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1571                                         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);
1572                 } else
1573                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1574                 break;
1575
1576                 case mISDNSIGNAL_CONF:
1577 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1578 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1579                 if (p_m_conf != param->mISDNsignal.conf)
1580                 {
1581                         p_m_conf = param->mISDNsignal.conf;
1582                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1583                         if (p_m_b_channel)
1584                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1585                                         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);
1586                 } else
1587                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1588                 /* we must set, even if currently tone forbids conf */
1589                 p_m_conf = param->mISDNsignal.conf;
1590 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1591                 break;
1592
1593                 case mISDNSIGNAL_JOINDATA:
1594                 if (p_m_joindata != param->mISDNsignal.joindata)
1595                 {
1596                         p_m_joindata = param->mISDNsignal.joindata;
1597                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1598                 } else
1599                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1600                 break;
1601                 
1602                 case mISDNSIGNAL_DELAY:
1603                 if (p_m_delay != param->mISDNsignal.delay)
1604                 {
1605                         p_m_delay = param->mISDNsignal.delay;
1606                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1607                         if (p_m_b_channel)
1608                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1609                                         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);
1610                 } else
1611                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1612                 break;
1613
1614                 default:
1615                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1616         }
1617 }
1618
1619 /* MESSAGE_CRYPT */
1620 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1621 {
1622         struct message *message;
1623
1624         switch(param->crypt.type)
1625         {
1626                 case CC_ACTBF_REQ:           /* activate blowfish */
1627                 p_m_crypt = 1;
1628                 p_m_crypt_key_len = param->crypt.len;
1629                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1630                 {
1631                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1632                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1633                         message->param.crypt.type = CC_ERROR_IND;
1634                         message_put(message);
1635                         break;
1636                 }
1637                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1638                 crypt_off:
1639                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1640                 if (p_m_b_channel)
1641                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1642                                 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);
1643                 break;
1644
1645                 case CC_DACT_REQ:            /* deactivate session encryption */
1646                 p_m_crypt = 0;
1647                 goto crypt_off;
1648                 break;
1649
1650                 case CR_LISTEN_REQ:          /* start listening to messages */
1651                 p_m_crypt_listen = 1;
1652                 p_m_crypt_listen_state = 0;
1653                 break;
1654
1655                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1656                 p_m_crypt_listen = 0;
1657                 break;
1658
1659                 case CR_MESSAGE_REQ:         /* send message */
1660                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1661                 if (!p_m_crypt_msg_len)
1662                 {
1663                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1664                         break;
1665                 }
1666                 p_m_crypt_msg_current = 0; /* reset */
1667                 p_m_crypt_msg_loops = 3; /* enable */
1668 #if 0
1669                 /* disable txmix, or we get corrupt data due to audio process */
1670                 if (p_m_txmix)
1671                 {
1672                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1673                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1674                 }
1675 #endif
1676                 break;
1677
1678                 default:
1679                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1680         }
1681
1682 }
1683
1684 /*
1685  * endpoint sends messages to the port
1686  */
1687 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1688 {
1689         if (Port::message_epoint(epoint_id, message_id, param))
1690                 return(1);
1691
1692         switch(message_id)
1693         {
1694                 case MESSAGE_DATA: /* tx-data from upper layer */
1695                 txfromup(param->data.data, param->data.len);
1696                 return(1);
1697
1698                 case MESSAGE_mISDNSIGNAL: /* user command */
1699                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1700                 message_mISDNsignal(epoint_id, message_id, param);
1701                 return(1);
1702
1703                 case MESSAGE_CRYPT: /* crypt control command */
1704                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1705                 message_crypt(epoint_id, message_id, param);
1706                 return(1);
1707         }
1708
1709         return(0);
1710 }
1711
1712
1713 /*
1714  * main loop for processing messages from mISDN device
1715  */
1716 int mISDN_handler(void)
1717 {
1718         int ret;
1719         msg_t *msg;
1720         iframe_t *frm;
1721         struct mISDNport *mISDNport;
1722         class PmISDN *isdnport;
1723         net_stack_t *nst;
1724         msg_t *dmsg;
1725         mISDNuser_head_t *hh;
1726         int i;
1727
1728         /* the que avoids loopbacks when replying to stack after receiving
1729          * from stack. */
1730         mISDNport = mISDNport_first;
1731         while(mISDNport)
1732         {
1733                 /* process turning on/off rx */
1734                 i = 0;
1735                 while(i < mISDNport->b_num)
1736                 {
1737                         isdnport=mISDNport->b_port[i];
1738                         if (isdnport)
1739                         {
1740                                 /* call bridges in user space OR crypto OR recording */
1741                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1742                                 {
1743                                         /* rx IS required */
1744                                         if (isdnport->p_m_rxoff)
1745                                         {
1746                                                 /* turn on RX */
1747                                                 isdnport->p_m_rxoff = 0;
1748                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
1749                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1750                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1751                                                 return(1);
1752                                         }
1753                                 } else
1754                                 {
1755                                         /* rx NOT required */
1756                                         if (!isdnport->p_m_rxoff)
1757                                         {
1758                                                 /* turn off RX */
1759                                                 isdnport->p_m_rxoff = 1;
1760                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
1761                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1762                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1763                                                 return(1);
1764                                         }
1765                                 }
1766                                 /* recording */
1767                                 if (isdnport->p_record)
1768                                 {
1769                                         /* txdata IS required */
1770                                         if (!isdnport->p_m_txdata)
1771                                         {
1772                                                 /* turn on RX */
1773                                                 isdnport->p_m_txdata = 1;
1774                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
1775                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1776                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
1777                                                 return(1);
1778                                         }
1779                                 } else
1780                                 {
1781                                         /* txdata NOT required */
1782                                         if (isdnport->p_m_txdata)
1783                                         {
1784                                                 /* turn off RX */
1785                                                 isdnport->p_m_txdata = 0;
1786                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
1787                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1788                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1789                                                 return(1);
1790                                         }
1791                                 }
1792                         }
1793                         i++;
1794                 }
1795 #if 0
1796                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
1797                 {
1798                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
1799                         mISDNport->l1timeout = 0;
1800 #endif
1801
1802                 if (mISDNport->l2establish)
1803                 {
1804                         if (now-mISDNport->l2establish > 5)
1805                         {
1806                                 if (mISDNport->ntmode)
1807                                 {
1808                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
1809                                         time(&mISDNport->l2establish);
1810                                         /* establish */
1811                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
1812                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1813                                                 free_msg(dmsg);
1814                                 } else {
1815                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
1816                                         time(&mISDNport->l2establish);
1817                                         /* establish */
1818                                         iframe_t act;
1819                                         act.prim = DL_ESTABLISH | REQUEST; 
1820                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
1821                                         act.dinfo = 0;
1822                                         act.len = 0;
1823                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
1824                                 }
1825                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
1826                                 end_trace();
1827                                 return(1);
1828                         }
1829                 }
1830                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
1831                 {
1832                         if (mISDNport->ntmode)
1833                         {
1834                                 hh = (mISDNuser_head_t *)dmsg->data;
1835                                 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);
1836                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1837                                         free_msg(dmsg);
1838                         } else
1839                         {
1840                                 frm = (iframe_t *)dmsg->data;
1841                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
1842                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
1843                                 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);
1844                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
1845                                 free_msg(dmsg);
1846                         }
1847                         return(1);
1848                 }
1849                 mISDNport = mISDNport->next;
1850         } 
1851
1852         /* no device, no read */
1853         if (mISDNdevice < 0)
1854                 return(0);
1855
1856         /* get message from kernel */
1857         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
1858                 return(1);
1859         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
1860         if (ret < 0)
1861         {
1862                 free_msg(msg);
1863                 if (errno == EAGAIN)
1864                         return(0);
1865                 FATAL("Failed to do mISDN_read()\n");
1866         }
1867         if (!ret)
1868         {
1869                 free_msg(msg);
1870 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
1871                 return(0);
1872         }
1873         msg->len = ret;
1874         frm = (iframe_t *)msg->data;
1875
1876         /* global prim */
1877         switch(frm->prim)
1878         {
1879                 case MGR_DELLAYER | CONFIRM:
1880                 case MGR_INITTIMER | CONFIRM:
1881                 case MGR_ADDTIMER | CONFIRM:
1882                 case MGR_DELTIMER | CONFIRM:
1883                 case MGR_REMOVETIMER | CONFIRM:
1884                 free_msg(msg);
1885                 return(1);
1886         }
1887
1888         /* handle timer events from mISDN for NT-stack
1889          * note: they do not associate with a stack */
1890         if (frm->prim == (MGR_TIMER | INDICATION))
1891         {
1892                 itimer_t *it;
1893
1894                 /* find mISDNport */
1895                 mISDNport = mISDNport_first;
1896                 while(mISDNport)
1897                 {
1898                         /* nt mode only */
1899                         if (mISDNport->ntmode)
1900                         {
1901                                 it = mISDNport->nst.tlist;
1902                                 /* find timer */
1903                                 while(it)
1904                                 {
1905                                         if (it->id == (int)frm->addr)
1906                                                 break;
1907                                         it = it->next;
1908                                 }
1909                                 if (it)
1910                                         break;
1911                         }
1912                         mISDNport = mISDNport->next;
1913                 }
1914                 if (mISDNport)
1915                 {
1916                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
1917                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
1918
1919                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
1920                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
1921                         ret = it->function(it->data);
1922                 } else
1923                 {
1924                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
1925                 }
1926                 goto out;
1927         }
1928
1929         /* find the mISDNport that belongs to the stack */
1930         mISDNport = mISDNport_first;
1931         while(mISDNport)
1932         {
1933                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
1934                         break;
1935                 mISDNport = mISDNport->next;
1936         } 
1937         if (!mISDNport)
1938         {
1939                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1940                 goto out;
1941         }
1942
1943         /* master stack */
1944         if (!(frm->addr&FLG_CHILD_STACK))
1945         {
1946                 /* d-message */
1947                 switch(frm->prim)
1948                 {
1949                         case MGR_SHORTSTATUS | INDICATION:
1950                         case MGR_SHORTSTATUS | CONFIRM:
1951                         switch(frm->dinfo) {
1952                                 case SSTATUS_L1_ACTIVATED:
1953                                 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1954                                 end_trace();
1955                                 goto ss_act;
1956                                 case SSTATUS_L1_DEACTIVATED:
1957                                 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1958                                 end_trace();
1959                                 goto ss_deact;
1960                                 case SSTATUS_L2_ESTABLISHED:
1961                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
1962                                 end_trace();
1963                                 goto ss_estab;
1964                                 case SSTATUS_L2_RELEASED:
1965                                 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
1966                                 end_trace();
1967                                 goto ss_rel;
1968                         }
1969                         break;
1970
1971                         case PH_ACTIVATE | CONFIRM:
1972                         case PH_ACTIVATE | INDICATION:
1973                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1974                         end_trace();
1975                         if (mISDNport->ntmode)
1976                         {
1977                                 mISDNport->l1link = 1;
1978                                 setup_queue(mISDNport, 1);
1979                                 goto l1_msg;
1980                         }
1981                         ss_act:
1982                         mISDNport->l1link = 1;
1983                         setup_queue(mISDNport, 1);
1984                         break;
1985
1986                         case PH_DEACTIVATE | CONFIRM:
1987                         case PH_DEACTIVATE | INDICATION:
1988                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1989                         end_trace();
1990                         if (mISDNport->ntmode)
1991                         {
1992                                 mISDNport->l1link = 0;
1993                                 setup_queue(mISDNport, 0);
1994                                 goto l1_msg;
1995                         }
1996                         ss_deact:
1997                         mISDNport->l1link = 0;
1998                         setup_queue(mISDNport, 0);
1999                         break;
2000
2001                         case PH_CONTROL | CONFIRM:
2002                         case PH_CONTROL | INDICATION:
2003                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2004                         break;
2005
2006                         case DL_ESTABLISH | INDICATION:
2007                         case DL_ESTABLISH | CONFIRM:
2008                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2009                         end_trace();
2010                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2011                         ss_estab:
2012                         if (mISDNport->l2establish)
2013                         {
2014                                 mISDNport->l2establish = 0;
2015                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2016                         }
2017                         mISDNport->l2link = 1;
2018                         break;
2019
2020                         case DL_RELEASE | INDICATION:
2021                         case DL_RELEASE | CONFIRM:
2022                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2023                         end_trace();
2024                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2025                         ss_rel:
2026                         mISDNport->l2link = 0;
2027                         if (mISDNport->ptp)
2028                         {
2029                                 time(&mISDNport->l2establish);
2030                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2031                         }
2032                         break;
2033
2034                         default:
2035                         l1_msg:
2036                         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);
2037                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2038                         {
2039                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2040                         }
2041                         /* d-message */
2042                         if (mISDNport->ntmode)
2043                         {
2044                                 /* l1-data enters the nt-mode library */
2045                                 nst = &mISDNport->nst;
2046                                 if (nst->l1_l2(nst, msg))
2047                                         free_msg(msg);
2048                                 return(1);
2049                         } else
2050                         {
2051                                 /* l3-data is sent to pbx */
2052                                 if (stack2manager_te(mISDNport, msg))
2053                                         free_msg(msg);
2054                                 return(1);
2055                         }
2056                 }
2057         } else
2058         /* child stack */
2059         {
2060                 /* b-message */
2061                 switch(frm->prim)
2062                 {
2063                         /* we don't care about confirms, we use rx data to sync tx */
2064                         case PH_DATA | CONFIRM:
2065                         case DL_DATA | CONFIRM:
2066                         break;
2067
2068                         /* we receive audio data, we respond to it AND we send tones */
2069                         case PH_DATA | INDICATION:
2070                         case DL_DATA | INDICATION:
2071                         case PH_CONTROL | INDICATION:
2072                         i = 0;
2073                         while(i < mISDNport->b_num)
2074                         {
2075                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2076                                         break;
2077                                 i++;
2078                         }
2079                         if (i == mISDNport->b_num)
2080                         {
2081                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2082                                 break;
2083                         }
2084                         if (mISDNport->b_port[i])
2085                         {
2086 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2087                                 mISDNport->b_port[i]->bchannel_receive(frm);
2088                         } else
2089                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2090                         break;
2091
2092                         case PH_ACTIVATE | INDICATION:
2093                         case DL_ESTABLISH | INDICATION:
2094                         case PH_ACTIVATE | CONFIRM:
2095                         case DL_ESTABLISH | CONFIRM:
2096                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2097                         i = 0;
2098                         while(i < mISDNport->b_num)
2099                         {
2100                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2101                                         break;
2102                                 i++;
2103                         }
2104                         if (i == mISDNport->b_num)
2105                         {
2106                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2107                                 break;
2108                         }
2109                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2110                         break;
2111
2112                         case PH_DEACTIVATE | INDICATION:
2113                         case DL_RELEASE | INDICATION:
2114                         case PH_DEACTIVATE | CONFIRM:
2115                         case DL_RELEASE | CONFIRM:
2116                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2117                         i = 0;
2118                         while(i < mISDNport->b_num)
2119                         {
2120                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2121                                         break;
2122                                 i++;
2123                         }
2124                         if (i == mISDNport->b_num)
2125                         {
2126                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2127                                 break;
2128                         }
2129                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2130                         break;
2131
2132                         default:
2133                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2134                 }
2135         }
2136
2137         out:
2138         free_msg(msg);
2139         return(1);
2140 }
2141
2142
2143 /*
2144  * global function to add a new card (port)
2145  */
2146 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface *interface)
2147 {
2148         int ret;
2149         unsigned char buff[1025];
2150         iframe_t *frm = (iframe_t *)buff;
2151         struct mISDNport *mISDNport, **mISDNportp;
2152         int i, cnt;
2153         int pri = 0;
2154         int nt = 0;
2155 #ifdef SOCKET_MISDN
2156 //      struct mlayer3 *layer3;
2157 #else
2158 //      interface_info_t ii;
2159         net_stack_t *nst;
2160         manager_t *mgr;
2161         layer_info_t li;
2162         stack_info_t *stinf;
2163 #endif
2164
2165         /* query port's requirements */
2166         cnt = mISDN_get_stack_count(mISDNdevice);
2167         if (cnt <= 0)
2168         {
2169                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2170                 return(NULL);
2171         }
2172         if (port>cnt || port<1)
2173         {
2174                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2175                 return(NULL);
2176         }
2177         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2178         if (ret < 0)
2179         {
2180                 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2181                 return(NULL);
2182         }
2183         stinf = (stack_info_t *)&frm->data.p;
2184         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2185         {
2186                 case ISDN_PID_L0_TE_S0:
2187                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2188                 break;
2189                 case ISDN_PID_L0_NT_S0:
2190                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2191                 nt = 1;
2192                 break;
2193                 case ISDN_PID_L0_TE_E1:
2194                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
2195                 pri = 1;
2196                 break;
2197                 case ISDN_PID_L0_NT_E1:
2198                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
2199                 pri = 1;
2200                 nt = 1;
2201                 break;
2202                 default:
2203                 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2204                 return(NULL);
2205         }
2206         if (nt)
2207         {
2208                 /* NT */
2209                 if (stinf->pid.protocol[1] == 0)
2210                 {
2211                         PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2212                         return(NULL);
2213                 }
2214                 if (stinf->pid.protocol[2])
2215                 {
2216                         PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2217                         return(NULL);
2218                 }
2219         } else
2220         {
2221                 /* TE */
2222                 if (stinf->pid.protocol[1] == 0)
2223                 {
2224                         PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2225                         return(NULL);
2226                 }
2227                 if (stinf->pid.protocol[2] == 0)
2228                 {
2229                         PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2230                         return(NULL);
2231                 }
2232                 if (stinf->pid.protocol[3] == 0)
2233                 {
2234                         PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2235                         return(NULL);
2236                 } else
2237                 {
2238                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2239                         {
2240                                 case ISDN_PID_L3_DSS1USER:
2241                                 break;
2242
2243                                 default:
2244                                 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2245                                 return(NULL);
2246                         }
2247                 }
2248                 if (stinf->pid.protocol[4])
2249                 {
2250                         PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2251                         return(NULL);
2252                 }
2253         }
2254
2255         /* add mISDNport structure */
2256         mISDNportp = &mISDNport_first;
2257         while(*mISDNportp)
2258                 mISDNportp = &((*mISDNportp)->next);
2259         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2260         pmemuse++;
2261         *mISDNportp = mISDNport;
2262
2263         /* allocate ressources of port */
2264 #ifdef SOCKET_MISDN
2265         /* open layer 3 */
2266         protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
2267         prop = 0;
2268         if (ptp)
2269                prop |= FLG_PTP;
2270         if (ptp)
2271                prop |= FLG_FORCE_PTMP;
2272         mISDNport->layer3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
2273         if (!mISDNport->layer3)
2274         {
2275                 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2276                 return(NULL);
2277         }
2278
2279 #warning KKEIL: braucht man das noch?
2280         /* if ntmode, establish L1 to send the tei removal during start */
2281         if (mISDNport->ntmode)
2282         {
2283                 iframe_t act;
2284                 /* L1 */
2285                 act.prim = PH_ACTIVATE | REQUEST; 
2286                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2287                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2288                 act.dinfo = 0;
2289                 act.len = 0;
2290                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2291                 usleep(10000); /* to be sure, that l1 is up */
2292         }
2293
2294 #else
2295         msg_queue_init(&mISDNport->downqueue);
2296         mISDNport->d_stid = stinf->id;
2297         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2298         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2299         {
2300                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2301                 ptp = 1;
2302                 if (ptmp && nt)
2303                 {
2304                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2305                         ptp = 0;
2306                 }
2307         }
2308
2309         /* create layer intance */
2310         memset(&li, 0, sizeof(li));
2311         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
2312         li.object_id = -1;
2313         li.extentions = 0;
2314         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
2315         li.pid.layermask = ISDN_LAYER((nt?2:4));
2316         li.st = mISDNport->d_stid;
2317         ret = mISDN_new_layer(mISDNdevice, &li);
2318         if (ret)
2319         {
2320                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
2321                 closeport:
2322                 mISDNport_close(mISDNport);
2323                 return(NULL);
2324         }
2325         mISDNport->upper_id = li.id;
2326         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
2327         if (ret)
2328         {
2329                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
2330                 goto closeport;
2331         }
2332         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
2333         if (mISDNport->lower_id < 0)
2334         {
2335                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
2336                 goto closeport;
2337         }
2338         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
2339         if (mISDNport->upper_id < 0)
2340         {
2341                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2342                 goto closeport;
2343         }
2344         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
2345
2346         /* if ntmode, establish L1 to send the tei removal during start */
2347         if (mISDNport->ntmode)
2348         {
2349                 iframe_t act;
2350                 /* L1 */
2351                 act.prim = PH_ACTIVATE | REQUEST; 
2352                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2353                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2354                 act.dinfo = 0;
2355                 act.len = 0;
2356                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2357                 usleep(10000); /* to be sure, that l1 is up */
2358         }
2359
2360         /* create nst (nt-mode only) */
2361         if (nt)
2362         {
2363                 mgr = &mISDNport->mgr;
2364                 nst = &mISDNport->nst;
2365
2366                 mgr->nst = nst;
2367                 nst->manager = mgr;
2368
2369                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
2370                 nst->device = mISDNdevice;
2371                 nst->cardnr = port;
2372                 nst->d_stid = mISDNport->d_stid;
2373
2374                 nst->feature = FEATURE_NET_HOLD;
2375                 if (ptp)
2376                         nst->feature |= FEATURE_NET_PTP;
2377                 if (pri)
2378                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2379 #if 0
2380                 i = 0;
2381                 while(i < mISDNport->b_num)
2382                 {
2383                         nst->b_stid[i] = mISDNport->b_stid[i];
2384                         i++;
2385                 }
2386 #endif
2387                 nst->l1_id = mISDNport->lower_id;
2388                 nst->l2_id = mISDNport->upper_id;
2389
2390                 /* phd */       
2391                 msg_queue_init(&nst->down_queue);
2392
2393                 Isdnl2Init(nst);
2394                 Isdnl3Init(nst);
2395         }
2396
2397 #endif
2398 //      SCPY(mISDNport->name, "noname");
2399         mISDNport->portnum = port;
2400         mISDNport->ntmode = nt;
2401         mISDNport->pri = pri;
2402         mISDNport->ptp = ptp;
2403         mISDNport->b_num = stinf->childcnt;
2404         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2405         i = 0;
2406         while(i < stinf->childcnt)
2407         {
2408                 mISDNport->b_stid[i] = stinf->child[i];
2409                 mISDNport->b_state[i] = B_STATE_IDLE;
2410                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
2411                 i++;
2412         }
2413
2414         /* if te-mode, query state link */
2415         if (!mISDNport->ntmode)
2416         {
2417                 iframe_t act;
2418                 /* L2 */
2419                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
2420                 act.prim = MGR_SHORTSTATUS | REQUEST; 
2421                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
2422                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
2423                 act.len = 0;
2424                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2425         }
2426         /* if ptp AND te-mode, pull up the link */
2427         if (mISDNport->ptp && !mISDNport->ntmode)
2428         {
2429                 iframe_t act;
2430                 /* L2 */
2431                 act.prim = DL_ESTABLISH | REQUEST; 
2432                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
2433                 act.dinfo = 0;
2434                 act.len = 0;
2435                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2436         }
2437         /* if ptp AND nt-mode, pull up the link */
2438         if (mISDNport->ptp && mISDNport->ntmode)
2439         {
2440                 msg_t *dmsg;
2441                 /* L2 */
2442                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2443                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2444                         free_msg(dmsg);
2445         }
2446         /* initially, we assume that the link is down, exept for nt-ptmp */
2447         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2448
2449         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2450
2451         start_trace(mISDNport->portnum,
2452                     interface,
2453                     NULL,
2454                     NULL,
2455                     DIRECTION_NONE,
2456                     CATEGORY_CH,
2457                     0,
2458                     "PORT (open)");
2459         add_trace("channels", NULL, "%d", mISDNport->b_num);
2460         end_trace();
2461         return(mISDNport);
2462 }
2463
2464
2465 /*
2466  * function to free ALL cards (ports)
2467  */
2468 void mISDNport_close_all(void)
2469 {
2470         /* free all ports */
2471         while(mISDNport_first)
2472                 mISDNport_close(mISDNport_first);
2473 }
2474
2475 /*
2476  * free only one port
2477  */
2478 void mISDNport_close(struct mISDNport *mISDNport)
2479 {
2480         struct mISDNport **mISDNportp;
2481         class Port *port;
2482         class PmISDN *isdnport;
2483         net_stack_t *nst;
2484         unsigned char buf[32];
2485         int i;
2486
2487         /* remove all port instance that are linked to this mISDNport */
2488         port = port_first;
2489         while(port)
2490         {
2491                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2492                 {
2493                         isdnport = (class PmISDN *)port;
2494                         if (isdnport->p_m_mISDNport)
2495                         {
2496                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2497                                 delete isdnport;
2498                         }
2499                 }
2500                 port = port->next;
2501         }
2502
2503         /* only if we are already part of interface */
2504         if (mISDNport->ifport)
2505         {
2506                 start_trace(mISDNport->portnum,
2507                             mISDNport->ifport->interface,
2508                             NULL,
2509                             NULL,
2510                             DIRECTION_NONE,
2511                             CATEGORY_CH,
2512                             0,
2513                             "PORT (close)");
2514                 end_trace();
2515         }
2516
2517         /* free bchannels */
2518         i = 0;
2519         while(i < mISDNport->b_num)
2520         {
2521                 if (mISDNport->b_addr[i])
2522                 {
2523                         _bchannel_destroy(mISDNport, i);
2524                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2525                 }
2526                 i++;
2527         }
2528
2529         /* free ressources of port */
2530         msg_queue_purge(&mISDNport->downqueue);
2531
2532         /* free stacks */
2533         if (mISDNport->ntmode)
2534         {
2535                 nst = &mISDNport->nst;
2536                 if (nst->manager) /* to see if initialized */
2537                 {
2538                         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");
2539                         cleanup_Isdnl3(nst);
2540                         cleanup_Isdnl2(nst);
2541
2542                         /* phd */
2543                         msg_queue_purge(&nst->down_queue);
2544                         if (nst->phd_down_msg)
2545                                 FREE(nst->phd_down_msg, 0);
2546                 }
2547         }
2548
2549         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
2550         if (mISDNport->d_stid)
2551         {
2552                 if (mISDNport->upper_id)
2553                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
2554         }
2555
2556         /* remove from list */
2557         mISDNportp = &mISDNport_first;
2558         while(*mISDNportp)
2559         {
2560                 if (*mISDNportp == mISDNport)
2561                 {
2562                         *mISDNportp = (*mISDNportp)->next;
2563                         mISDNportp = NULL;
2564                         break;
2565                 }
2566                 mISDNportp = &((*mISDNportp)->next);
2567         }
2568
2569         if (mISDNportp)
2570                 FATAL("mISDNport not in list\n");
2571         
2572         FREE(mISDNport, sizeof(struct mISDNport));
2573         pmemuse--;
2574
2575 }
2576
2577
2578 /*
2579  * global function to show all available isdn ports
2580  */
2581 void mISDN_port_info(void)
2582 {
2583         int err;
2584         int i, ii, p;
2585         int useable, nt, pri;
2586         unsigned char buff[1025];
2587         iframe_t *frm = (iframe_t *)buff;
2588         stack_info_t *stinf;
2589         int device;
2590
2591         /* open mISDN */
2592         if ((device = mISDN_open()) < 0)
2593         {
2594                 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));
2595                 exit(EXIT_FAILURE);
2596         }
2597
2598         /* get number of stacks */
2599         i = 1;
2600         ii = mISDN_get_stack_count(device);
2601         printf("\n");
2602         if (ii <= 0)
2603         {
2604                 printf("Found no card. Please be sure to load card drivers.\n");
2605         }
2606
2607         /* loop the number of cards and get their info */
2608         while(i <= ii)
2609         {
2610                 err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
2611                 if (err <= 0)
2612                 {
2613                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
2614                         break;
2615                 }
2616                 stinf = (stack_info_t *)&frm->data.p;
2617
2618                 nt = pri = 0;
2619                 useable = 1;
2620
2621                 /* output the port info */
2622                 printf("Port %2d: ", i);
2623                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2624                 {
2625                         case ISDN_PID_L0_TE_S0:
2626                         printf("TE-mode BRI S/T interface line (for phone lines)");
2627 #if 0
2628                         if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
2629                                 printf(" HFC multiport card");
2630 #endif
2631                         break;
2632                         case ISDN_PID_L0_NT_S0:
2633                         nt = 1;
2634                         printf("NT-mode BRI S/T interface port (for phones)");
2635 #if 0
2636                         if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
2637                                 printf(" HFC multiport card");
2638 #endif
2639                         break;
2640                         case ISDN_PID_L0_TE_E1:
2641                         pri = 1;
2642                         printf("TE-mode PRI E1  interface line (for phone lines)");
2643 #if 0
2644                         if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
2645                                 printf(" HFC-E1 card");
2646 #endif
2647                         break;
2648                         case ISDN_PID_L0_NT_E1:
2649                         nt = 1;
2650                         pri = 1;
2651                         printf("NT-mode PRI E1  interface port (for phones)");
2652 #if 0
2653                         if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
2654                                 printf(" HFC-E1 card");
2655 #endif
2656                         break;
2657                         default:
2658                         useable = 0;
2659                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
2660                 }
2661                 printf("\n");
2662
2663                 if (nt)
2664                 {
2665                         if (stinf->pid.protocol[1] == 0)
2666                         {
2667                                 useable = 0;
2668                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
2669                         }
2670                         p = 2;
2671                         while(p <= MAX_LAYER_NR) {
2672                                 if (stinf->pid.protocol[p])
2673                                 {
2674                                         useable = 0;
2675                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2676                                 }
2677                                 p++;
2678                         }
2679                         if (useable)
2680                         {
2681                                 if (pri)
2682                                         printf(" -> Interface is Point-To-Point (PRI).\n");
2683                                 else
2684                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
2685                         }
2686                 } else
2687                 {
2688                         if (stinf->pid.protocol[1] == 0)
2689                         {
2690                                 useable = 0;
2691                                 printf(" -> Missing layer 1 protocol.\n");
2692                         }
2693                         if (stinf->pid.protocol[2] == 0)
2694                         {
2695                                 useable = 0;
2696                                 printf(" -> Missing layer 2 protocol.\n");
2697                         }
2698                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
2699                         {
2700                                 printf(" -> Interface is Poin-To-Point.\n");
2701                         }
2702                         if (stinf->pid.protocol[3] == 0)
2703                         {
2704                                 useable = 0;
2705                                 printf(" -> Missing layer 3 protocol.\n");
2706                         } else
2707                         {
2708                                 printf(" -> Protocol: ");
2709                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2710                                 {
2711                                         case ISDN_PID_L3_DSS1USER:
2712                                         printf("DSS1 (Euro ISDN)");
2713                                         break;
2714
2715                                         default:
2716                                         useable = 0;
2717                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
2718                                 }
2719                                 printf("\n");
2720                         }
2721                         p = 4;
2722                         while(p <= MAX_LAYER_NR) {
2723                                 if (stinf->pid.protocol[p])
2724                                 {
2725                                         useable = 0;
2726                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2727                                 }
2728                                 p++;
2729                         }
2730                 }
2731                 printf("  - %d B-channels\n", stinf->childcnt);
2732
2733                 if (!useable)
2734                         printf(" * Port NOT useable for LCR\n");
2735
2736                 printf("--------\n");
2737
2738                 i++;
2739         }
2740         printf("\n");
2741
2742         /* close mISDN */
2743         if ((err = mISDN_close(device)))
2744                 FATAL("mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
2745 }
2746
2747
2748 /*
2749  * enque data from upper buffer
2750  */
2751 void PmISDN::txfromup(unsigned char *data, int length)
2752 {
2753         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2754         iframe_t *frm = (iframe_t *)buf;
2755
2756         /* configure frame */
2757         frm->prim = DL_DATA | REQUEST; 
2758         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
2759         frm->dinfo = 0;
2760
2761         /* check if high priority tones exist
2762          * ignore data in this case
2763          */
2764         if (p_tone_name[0] || p_m_crypt_msg_loops)
2765                 return;
2766
2767         /* preload procedure
2768          * if transmit buffer in DSP module is empty,
2769          * preload it to DSP_LOAD to prevent jitter gaps.
2770          */
2771         if (p_m_load==0 && ISDN_LOAD>0)
2772         {
2773
2774                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
2775                 frm->len = ISDN_LOAD;
2776                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2777                 p_m_load += frm->len;
2778         }
2779
2780         /* drop if load would exceed ISDN_MAXLOAD
2781          * this keeps the delay not too high
2782          */
2783         if (p_m_load+length > ISDN_MAXLOAD)
2784                 return;
2785
2786         /* load data to buffer
2787          */
2788         memcpy(buf+mISDN_HEADER_LEN, data, length);
2789         frm->len = length;
2790         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2791         p_m_load += frm->len;
2792 }
2793