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