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