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