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