fd2625fbe4f8dadd3062fd37956fdb7bb3ed702d
[lcr.git] / mISDN.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN port abstraction for dss1 and sip                                   **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13 #ifndef SOCKET_MISDN
14 extern "C" {
15 #include <mISDNuser/net_l2.h>
16 }
17
18 #ifndef CMX_TXDATA_ON
19 #define OLD_MISDN
20 #endif
21 #ifndef CMX_TXDATA_OFF
22 #define OLD_MISDN
23 #endif
24 #ifndef CMX_DELAY
25 #define OLD_MISDN
26 #endif
27 #ifndef PIPELINE_CFG
28 #define OLD_MISDN
29 #endif
30 #ifndef CMX_TX_DATA
31 #define OLD_MISDN
32 #endif
33
34 #ifdef OLD_MISDN
35 #warning
36 #warning *********************************************************
37 #warning *
38 #warning * It seems that you use an older version of mISDN.
39 #warning * Features like voice recording or echo will not work.
40 #warning * Also it causes problems with loading modules and may
41 #warning * not work at all.
42 #warning *
43 #warning * Please upgrade to newer version. A working version can
44 #warning * be found at www.linux-call-router.de.
45 #warning *
46 #warning * Do not use the mISDN_1_1 branch, it does not have all
47 #warning * the features that are required. Use the master branch
48 #warning * instead.
49 #warning *
50 #warning *********************************************************
51 #warning
52 #error
53 #endif
54
55 #ifndef ISDN_PID_L4_B_USER
56 #define ISDN_PID_L4_B_USER 0x440000ff
57 #endif
58 #endif
59
60 // timeouts if activating/deactivating response from mISDN got lost
61 #define B_TIMER_ACTIVATING 1 // seconds
62 #define B_TIMER_DEACTIVATING 1 // seconds
63
64 /* list of mISDN ports */
65 struct mISDNport *mISDNport_first;
66
67 /* noise randomizer */
68 unsigned char mISDN_rand[256];
69 int mISDN_rand_count = 0;
70
71 #ifdef SOCKET_MISDN
72 int mISDNsocket = -1;
73
74 int mISDN_initialize(void)
75 {
76         /* try to open raw socket to check kernel */
77         mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
78         if (mISDNsocket < 0)
79         {
80                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
81                 return(-1);
82         }
83
84         /* open debug, if enabled and not only stack debugging */
85         if (options.deb && (options.deb != DEBUG_STACK))
86         {
87                 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
88                 debug_fp = fopen(debug_log, "a");
89         }
90
91         if (options.deb & DEBUG_STACK)
92         {
93                 SPRINT(debug_stack, "%s/debug_mISDN.log", INSTALL_DATA);
94                 mISDN_debug_init(DBGM_ALL, debug_stack, debug_stack, debug_stack);
95         } else
96                 mISDN_debug_init(0, NULL, NULL, NULL);
97
98         /* init mlayer3 */
99         init_layer3(4); // buffer of 4
100
101         return(0);
102 }
103
104 void mISDN_deinitialize(void)
105 {
106         cleanup_layer3();
107
108         mISDN_debug_close();
109
110         if (debug_fp)
111                 fclose(debug_fp);
112         debug_fp = NULL;
113
114         if (mISDNsocket > -1)
115                 close(mISDNsocket);
116 }
117 #else
118 int entity = 0; /* used for udevice */
119 int mISDNdevice = -1; /* the device handler and port list */
120
121 int mISDN_initialize(void)
122 {
123         char debug_log[128];
124         unsigned char buff[1025];
125         iframe_t *frm = (iframe_t *)buff;
126         int ret;
127
128         /* initialize stuff of the NT lib */
129         if (options.deb & DEBUG_STACK)
130         {
131                 global_debug = 0xffffffff & ~DBGM_MSG;
132 //              global_debug = DBGM_L3DATA;
133         } else
134                 global_debug = DBGM_MAN;
135         SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
136         if (options.deb & DEBUG_LOG)
137                 debug_init(global_debug, debug_log, debug_log, debug_log);
138         else
139                 debug_init(global_debug, NULL, NULL, NULL);
140         msg_init();
141
142         /* open mISDNdevice if not already open */
143         if (mISDNdevice < 0)
144         {
145                 ret = mISDN_open();
146                 if (ret < 0)
147                 {
148                         fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
149                         return(-1);
150                 }
151                 mISDNdevice = ret;
152                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
153
154                 /* create entity for layer 3 TE-mode */
155                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
156                 ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
157                 if (ret < (int)mISDN_HEADER_LEN)
158                 {
159                         noentity:
160                         FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
161                 }
162                 entity = frm->dinfo & 0xffff;
163                 if (!entity)
164                         goto noentity;
165                 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
166         }
167         return(0);
168 }
169
170 void mISDN_deinitialize(void)
171 {
172         unsigned char buff[1025];
173
174         debug_close();
175         global_debug = 0;
176
177         if (mISDNdevice >= 0)
178         {
179                 /* free entity */
180                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
181                 /* close device */
182                 mISDN_close(mISDNdevice);
183                 mISDNdevice = -1;
184                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
185         }
186 }
187 #endif
188
189 /*
190  * constructor
191  */
192 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
193 {
194         p_m_mISDNport = mISDNport;
195         p_m_portnum = mISDNport->portnum;
196         p_m_b_index = -1;
197         p_m_b_channel = 0;
198         p_m_b_exclusive = 0;
199         p_m_b_reserve = 0;
200         p_m_delete = 0;
201         p_m_hold = 0;
202         p_m_tx_gain = mISDNport->ifport->interface->tx_gain;
203         p_m_rx_gain = mISDNport->ifport->interface->rx_gain;
204         p_m_conf = 0;
205         p_m_txdata = 0;
206         p_m_delay = 0;
207         p_m_echo = 0;
208         p_m_tone = 0;
209         p_m_rxoff = 0;
210         p_m_joindata = 0;
211         p_m_dtmf = !mISDNport->ifport->nodtmf;
212         p_m_timeout = 0;
213         p_m_timer = 0;
214         p_m_remote_ref = 0; /* channel shall be exported to given remote */
215         p_m_remote_id = 0; /* channel shall be exported to given remote */
216         SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
217         
218         /* audio */
219         p_m_load = 0;
220         p_m_last_tv_sec = 0;
221
222         /* crypt */
223         p_m_crypt = 0;
224         p_m_crypt_listen = 0;
225         p_m_crypt_msg_loops = 0;
226         p_m_crypt_msg_loops = 0;
227         p_m_crypt_msg_len = 0;
228         p_m_crypt_msg[0] = '\0';
229         p_m_crypt_msg_current = 0;
230         p_m_crypt_key_len = 0;
231         p_m_crypt_listen = 0;
232         p_m_crypt_listen_state = 0;
233         p_m_crypt_listen_len = 0;
234         p_m_crypt_listen_msg[0] = '\0';
235         p_m_crypt_listen_crc = 0;
236         if (mISDNport->ifport->interface->bf_len >= 4 && mISDNport->ifport->interface->bf_len <= 56)
237         {
238                 memcpy(p_m_crypt_key, mISDNport->ifport->interface->bf_key, p_m_crypt_key_len);
239                 p_m_crypt_key_len = mISDNport->ifport->interface->bf_len;
240                 p_m_crypt = 1;
241         }
242
243         /* if any channel requested by constructor */
244         if (channel == CHANNEL_ANY)
245         {
246                 /* reserve channel */
247                 p_m_b_reserve = 1;
248                 mISDNport->b_reserved++;
249         }
250
251         /* reserve channel */
252         if (channel > 0) // only if constructor was called with a channel resevation
253                 seize_bchannel(channel, exclusive);
254
255         /* we increase the number of objects: */
256         mISDNport->use++;
257         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
258 }
259
260
261 /*
262  * destructor
263  */
264 PmISDN::~PmISDN()
265 {
266         struct message *message;
267
268         /* remove bchannel relation */
269         drop_bchannel();
270
271         /* release epoint */
272         while (p_epointlist)
273         {
274                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
275                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
276                 message->param.disconnectinfo.cause = 16;
277                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
278                 message_put(message);
279                 /* remove from list */
280                 free_epointlist(p_epointlist);
281         }
282
283         /* we decrease the number of objects: */
284         p_m_mISDNport->use--;
285         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
286 }
287
288
289 /*
290  * trace
291  */
292 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
293 {
294         /* init trace with given values */
295         start_trace(mISDNport?mISDNport->portnum:0,
296                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
297                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
298                     port?port->p_dialinginfo.id:NULL,
299                     direction,
300                     CATEGORY_CH,
301                     port?port->p_serial:0,
302                     msgtext);
303 }
304
305
306 /*
307  * layer trace header
308  */
309 static struct isdn_message {
310         char *name;
311         unsigned long value;
312 } isdn_message[] = {
313         {"PH_ACTIVATE", L1_ACTIVATE_REQ},
314         {"PH_DEACTIVATE", L1_DEACTIVATE_REQ},
315         {"DL_ESTABLISH", L2_ESTABLISH_REQ},
316         {"DL_RELEASE", L2_RELEASE_REQ},
317         {"UNKNOWN", L3_UNKNOWN},
318         {"MT_TIMEOUT", L3_TIMEOUT_REQ},
319         {"MT_SETUP", L3_SETUP_REQ},
320         {"MT_SETUP_ACK", L3_SETUP_ACKNOWLEDGE_REQ},
321         {"MT_PROCEEDING", L3_PROCEEDING_REQ},
322         {"MT_ALERTING", L3_ALERTING_REQ},
323         {"MT_CONNECT", L3_CONNECT_REQ},
324         {"MT_CONNECT_ACK", L3_CONNECT_ACKNOWLEDGE_REQ},
325         {"MT_DISCONNECT", L3_DISCONNECT_REQ},
326         {"MT_RELEASE", L3_RELEASE_REQ},
327         {"MT_RELEASE_COMP", L3_RELEASE_COMPLETE_REQ},
328         {"MT_INFORMATION", L3_INFORMATION_REQ},
329         {"MT_PROGRESS", L3_PROGRESS_REQ},
330         {"MT_NOTIFY", L3_NOTIFY_REQ},
331         {"MT_SUSPEND", L3_SUSPEND_REQ},
332         {"MT_SUSPEND_ACK", L3_SUSPEND_ACKNOWLEDGE_REQ},
333         {"MT_SUSPEND_REJ", L3_SUSPEND_REJECT_REQ},
334         {"MT_RESUME", L3_RESUME_REQ},
335         {"MT_RESUME_ACK", L3_RESUME_ACKNOWLEDGE_REQ},
336         {"MT_RESUME_REJ", L3_RESUME_REJECT_REQ},
337         {"MT_HOLD", L3_HOLD_REQ},
338         {"MT_HOLD_ACK", L3_HOLD_ACKNOWLEDGE_REQ},
339         {"MT_HOLD_REJ", L3_HOLD_REJECT_REQ},
340         {"MT_RETRIEVE", L3_RETRIEVE_REQ},
341         {"MT_RETRIEVE_ACK", L3_RETRIEVE_ACKNOWLEDGE_REQ},
342         {"MT_RETRIEVE_REJ", L3_RETRIEVE_REJECT_REQ},
343         {"MT_FACILITY", L3_FACILITY_REQ},
344         {"MT_STATUS", L3_STATUS_REQ},
345         {"MT_RESTART", L3_RESTART_REQ},
346 #ifdef SOCKET_MISDN
347         {"MT_ASSIGN", L3_ASSIGN_REQ},
348         {"MT_FREE", L3_FREE_REQ},
349 #else
350         {"MT_NEW_CR", L3_NEW_CR_REQ},
351         {"MT_RELEASE_CR", L3_RELEASE_CR_REQ},
352 #endif
353
354         {NULL, 0},
355 };
356 static char *isdn_prim[4] = {
357         " REQUEST",
358         " CONFIRM",
359         " INDICATION",
360         " RESPONSE",
361 };
362 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long msg, int direction)
363 {
364         int i;
365         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
366
367         /* select message and primitive text */
368         i = 0;
369         while(isdn_message[i].name)
370         {
371                 if (isdn_message[i].value == (msg&0xffffff00))
372                 {
373                         SCPY(msgtext, isdn_message[i].name);
374                         break;
375                 }
376                 i++;
377         }
378         SCAT(msgtext, isdn_prim[msg&0x00000003]);
379
380         /* add direction */
381         if (direction && (msg&0xffffff00)!=L3_NEW_CR_REQ && (msg&0xffffff00)!=L3_RELEASE_CR_REQ)
382         {
383                 if (mISDNport)
384                 {
385                         if (mISDNport->ntmode)
386                         {
387                                 if (direction == DIRECTION_OUT)
388                                         SCAT(msgtext, " N->U");
389                                 else
390                                         SCAT(msgtext, " N<-U");
391                         } else
392                         {
393                                 if (direction == DIRECTION_OUT)
394                                         SCAT(msgtext, " U->N");
395                                 else
396                                         SCAT(msgtext, " U<-N");
397                         }
398                 }
399         }
400
401         /* init trace with given values */
402         start_trace(mISDNport?mISDNport->portnum:0,
403                     mISDNport?mISDNport->ifport->interface:NULL,
404                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
405                     port?port->p_dialinginfo.id:NULL,
406                     direction,
407                     CATEGORY_CH,
408                     port?port->p_serial:0,
409                     msgtext);
410 }
411
412
413 /*
414  * send control information to the channel (dsp-module)
415  */
416 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, unsigned long c2, char *trace_name, int trace_value)
417 {
418 #ifdef SOCKET_MISDN
419         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
420         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
421         unsigned long *d = buffer+MISDN_HEADER_LEN;
422         int ret;
423
424         ctrl->prim = PH_CONTROL_REQ;
425         ctrl->id = 0;
426         *d++ = c1;
427         *d++ = c2;
428         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
429         if (!ret)
430                 PERROR("Failed to send to socket %d\n", handle);
431 #else
432         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
433         iframe_t *ctrl = (iframe_t *)buffer; 
434         unsigned long *d = (unsigned long *)&ctrl->data.p;
435
436         ctrl->prim = PH_CONTROL | REQUEST;
437         ctrl->addr = handle | FLG_MSG_DOWN;
438         ctrl->dinfo = 0;
439         ctrl->len = sizeof(int)*2;
440         *d++ = c1;
441         *d++ = c2;
442         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
443 #endif
444         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
445         if (c1 == CMX_CONF_JOIN)
446                 add_trace(trace_name, NULL, "0x%08x", trace_value);
447         else
448                 add_trace(trace_name, NULL, "%d", trace_value);
449         end_trace();
450 }
451
452 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
453 {
454 #ifdef SOCKET_MISDN
455         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
456         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
457         unsigned long *d = buffer+MISDN_HEADER_LEN;
458         int ret;
459
460         ctrl->prim = PH_CONTROL_REQ;
461         ctrl->id = 0;
462         *d++ = c1;
463         memcpy(d, c2, c2_len);
464         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
465         if (!ret)
466                 PERROR("Failed to send to socket %d\n", handle);
467 #else
468         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
469         iframe_t *ctrl = (iframe_t *)buffer;
470         unsigned long *d = (unsigned long *)&ctrl->data.p;
471
472         ctrl->prim = PH_CONTROL | REQUEST;
473         ctrl->addr = handle | FLG_MSG_DOWN;
474         ctrl->dinfo = 0;
475         ctrl->len = sizeof(int)+c2_len;
476         *d++ = c1;
477         memcpy(d, c2, c2_len);
478         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
479 #endif
480         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
481         add_trace(trace_name, NULL, "%d", trace_value);
482         end_trace();
483 }
484
485
486 /*
487  * subfunction for bchannel_event
488  * create stack
489  */
490 static int _bchannel_create(struct mISDNport *mISDNport, int i)
491 {
492         unsigned char buff[1024];
493         int ret;
494 #ifdef SOCKET_MISDN
495         unsigned long on = 1;
496         struct sockadd_mISDN addr;
497
498         if (mISDNport->b_socket[i])
499         {
500                 PERROR("Error: Socket already created for index %d\n", i);
501                 return(0);
502         }
503
504         /* open socket */
505         mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
506         if (mISDNport->b_socket[i] < 0)
507         {
508                 PERROR("Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
509                 return(0);
510         }
511         
512         /* set nonblocking io */
513         ret = ioctl(mISDNport->b_socket[i], FIONBIO, &on);
514         if (ret < 0)
515         {
516                 PERROR("Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
517                 close(mISDNport->b_socket[i]);
518                 mISDNport->b_socket[i] = -1;
519                 return(0);
520         }
521
522         /* bind socket to bchannel */
523         addr.family = AF_ISDN;
524         addr.dev = mISDNport->port-1;
525         addr.channel = i+1+(i>=15);
526         ret = bind(di->bchan, (struct sockaddr *)&addr, sizeof(addr));
527         if (ret < 0)
528         {
529                 PERROR("Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
530                 close(mISDNport->b_socket[i]);
531                 mISDNport->b_socket[i] = -1;
532                 return(0);
533         }
534
535         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
536         add_trace("channel", NULL, "%d", i+1+(i>=15));
537         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
538         end_trace();
539 #else
540         layer_info_t li;
541         mISDN_pid_t pid;
542
543         if (!mISDNport->b_stid[i])
544         {
545                 PERROR("Error: no stack for index %d\n", i);
546                 return(0);
547         }
548         if (mISDNport->b_addr[i])
549         {
550                 PERROR("Error: stack already created for index %d\n", i);
551                 return(0);
552         }
553
554         /* create new layer */
555         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
556         memset(&li, 0, sizeof(li));
557         memset(&pid, 0, sizeof(pid));
558         li.object_id = -1;
559         li.extentions = 0;
560         li.st = mISDNport->b_stid[i];
561         UCPY(li.name, "B L4");
562         li.pid.layermask = ISDN_LAYER((4));
563         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
564         ret = mISDN_new_layer(mISDNdevice, &li);
565         if (ret)
566         {
567                 failed_new_layer:
568                 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
569                 goto failed;
570         }
571         mISDNport->b_addr[i] = li.id;
572         if (!li.id)
573         {
574                 goto failed_new_layer;
575         }
576         PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
577
578         /* create new stack */
579         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
580         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
581         pid.protocol[3] = ISDN_PID_L3_B_DSP;
582         pid.protocol[4] = ISDN_PID_L4_B_USER;
583         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
584         ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
585         if (ret)
586         {
587                 stack_error:
588                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
589                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
590                 goto failed;
591         }
592         ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
593         if (ret)
594                 goto stack_error;
595
596         /* get layer id */
597         mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
598         if (!mISDNport->b_addr[i])
599                 goto stack_error;
600         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
601         add_trace("channel", NULL, "%d", i+1+(i>=15));
602         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
603         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
604         end_trace();
605 #endif
606
607         return(1);
608
609 failed:
610         mISDNport->b_addr[i] = 0;
611         return(0);
612 }
613
614
615 /*
616  * subfunction for bchannel_event
617  * activate / deactivate request
618  */
619 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
620 {
621 #ifdef SOCKET_MISDN
622         struct mISDNhead act;
623         int ret;
624
625         act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ; 
626         act.id = 0;
627         ret = sendto(mISDNport->b_socket[i], &act, MISDN_HEADER_LEN, 0, NULL, 0);
628         if (!ret)
629                 PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
630 #else
631         iframe_t act;
632
633         /* activate bchannel */
634         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
635         act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
636         act.dinfo = 0;
637         act.len = 0;
638         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
639 #endif
640
641         /* trace */
642         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
643         add_trace("channel", NULL, "%d", i+1+(i>=15));
644         if (mISDNport->b_timer[i])
645                 add_trace("event", NULL, "timeout recovery");
646         end_trace();
647 }
648
649
650 /*
651  * subfunction for bchannel_event
652  * set features
653  */
654 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
655 {
656         struct PmISDN *port;
657 #ifdef SOCKET_MISDN
658         int handle;
659
660         handle = mISDNport->b_socket[i];
661 #else
662         unsigned long handle;
663
664         handle = mISDNport->b_addr[i];
665 #endif
666         port = mISDNport->b_port[i];
667         if (!port)
668         {
669                 PERROR("bchannel index i=%d not associated with a port object\n", i);
670                 return;
671         }
672
673         /* set dsp features */
674 #ifndef OLD_MISDN
675         if (port->p_m_txdata)
676                 ph_control(mISDNport, port, handle, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
677         if (port->p_m_delay)
678                 ph_control(mISDNport, port, handle, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
679 #endif
680         if (port->p_m_tx_gain)
681                 ph_control(mISDNport, port, handle, VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
682         if (port->p_m_rx_gain)
683                 ph_control(mISDNport, port, handle, VOL_CHANGE_RX, port->p_m_rx_gain, "DSP-RX_GAIN", port->p_m_rx_gain);
684 #ifndef OLD_MISDN
685         if (port->p_m_pipeline[0])
686                 ph_control_block(mISDNport, port, handle, PIPELINE_CFG, port->p_m_pipeline, strlen(port->p_m_pipeline)+1, "DSP-PIPELINE", 0);
687 #endif
688         if (port->p_m_conf)
689                 ph_control(mISDNport, port, handle, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
690         if (port->p_m_echo)
691                 ph_control(mISDNport, port, handle, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
692         if (port->p_m_tone)
693                 ph_control(mISDNport, port, handle, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
694         if (port->p_m_rxoff)
695                 ph_control(mISDNport, port, handle, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
696 //      if (port->p_m_txmix)
697 //              ph_control(mISDNport, port, handle, CMX_MIX_ON, 0, "DSP-MIX", 1);
698         if (port->p_m_dtmf)
699                 ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
700         if (port->p_m_crypt)
701                 ph_control_block(mISDNport, port, handle, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
702 }
703
704 /*
705  * subfunction for bchannel_event
706  * destroy stack
707  */
708 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
709 {
710 #ifdef SOCKET_MISDN
711         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
712         add_trace("channel", NULL, "%d", i+1+(i>=15));
713         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
714         end_trace();
715         if (mISDNport->b_socket[i] > -1)
716         {
717                 close(mISDNport->b_socket[i]);
718                 mISDNport->b_socket[i] = -1;
719         }
720 #else
721         unsigned char buff[1024];
722
723         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
724         add_trace("channel", NULL, "%d", i+1+(i>=15));
725         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
726         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
727         end_trace();
728         /* remove our stack only if set */
729         if (mISDNport->b_addr[i])
730         {
731                 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
732                 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
733                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
734                 mISDNport->b_addr[i] = 0;
735         }
736 #endif
737 }
738
739
740 /*
741 bchannel procedure
742 ------------------
743
744 A bchannel goes through the following states in this order:
745
746 - B_STATE_IDLE
747 No one is using the bchannel.
748 It is available and not linked to Port class, nor reserved.
749
750 - B_STATE_ACTIVATING
751 The bchannel stack is created and an activation request is sent.
752 It MAY be linked to Port class, but already unlinked due to Port class removal.
753
754 - B_STATE_ACTIVE
755 The bchannel is active and cofigured to the Port class needs.
756 Also it is linked to a Port class, otherwhise it would be deactivated.
757
758 - B_STATE_DEACTIVATING
759 The bchannel is in deactivating state, due to deactivation request.
760 It may be linked to a Port class, that likes to reactivate it.
761
762 - B_STATE_IDLE
763 See above.
764 After deactivating bchannel, and if not used, the bchannel becomes idle again.
765
766 Also the bchannel may be exported, but only if the state is or becomes idle:
767
768 - B_STATE_EXPORTING
769 The bchannel assignment has been sent to the remove application.
770
771 - B_STATE_REMOTE
772 The bchannel assignment is acknowledged by the remote application.
773
774 - B_STATE_IMPORTING
775 The bchannel is re-imported by mISDN port object.
776
777 - B_STATE_IDLE
778 See above.
779 After re-importing bchannel, and if not used, the bchannel becomes idle again.
780
781
782 A bchannel can have the following events:
783
784 - B_EVENT_USE
785 A bchannel is required by a Port class.
786 The bchannel shall be exported to the remote application.
787
788 - B_EVENT_ACTIVATED
789 The bchannel beomes active.
790
791 - B_EVENT_DROP
792 The bchannel is not required by Port class anymore
793
794 - B_EVENT_DEACTIVATED
795 The bchannel becomes inactive.
796
797 - B_EVENT_EXPORTED
798 The bchannel is now used by remote application.
799
800 - B_EVENT_IMPORTED
801 The bchannel is not used by remote application.
802
803 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
804
805 if an export request is receive by remote application, p_m_remote_* is set.
806 the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
807 - set on export request from remote application (if port is assigned)
808 - set on channel use, if requested by remote application (p_m_remote_*)
809 - cleared on drop request
810
811 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
812 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
813 the bchannel import/export is acknowledged with stack given.
814
815 if exporting, b_remote_*[index] is set to the remote socket id.
816 if importing has been acknowledged. b_remote_*[index] is cleared.
817
818 */
819
820 /*
821  * process bchannel events
822  * - mISDNport is a pointer to the port's structure
823  * - i is the index of the bchannel
824  * - event is the B_EVENT_* value
825  * - port is the PmISDN class pointer
826  */
827 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
828 {
829         class PmISDN *b_port = mISDNport->b_port[i];
830         int state = mISDNport->b_state[i];
831         double timer = mISDNport->b_timer[i];
832         unsigned long p_m_remote_ref = 0;
833         unsigned long p_m_remote_id = 0;
834         int p_m_tx_gain = 0;
835         int p_m_rx_gain = 0;
836         char *p_m_pipeline = NULL;
837         unsigned char *p_m_crypt_key = NULL;
838         int p_m_crypt_key_len = 0;
839         int p_m_crypt_key_type = 0;
840 #ifdef SOCKET_MISDN
841         unsigned long portid = (mISDNport->portnum<<8) + i+1+(i>=15);
842 #else
843         unsigned long portid = mISDNport->b_stid[i];
844 #endif
845
846         if (b_port)
847         {
848                 p_m_remote_id = b_port->p_m_remote_id;
849                 p_m_remote_ref = b_port->p_m_remote_ref;
850                 p_m_tx_gain = b_port->p_m_tx_gain;
851                 p_m_rx_gain = b_port->p_m_rx_gain;
852                 p_m_pipeline = b_port->p_m_pipeline;
853                 p_m_crypt_key = b_port->p_m_crypt_key;
854                 p_m_crypt_key_len = b_port->p_m_crypt_key_len;
855                 p_m_crypt_key_type = /*b_port->p_m_crypt_key_type*/1;
856         }
857
858         switch(event)
859         {
860                 case B_EVENT_USE:
861                 /* port must be linked in order to allow activation */
862                 if (!b_port)
863                         FATAL("bchannel must be linked to a Port class\n");
864                 switch(state)
865                 {
866                         case B_STATE_IDLE:
867                         if (p_m_remote_ref)
868                         {
869                                 /* export bchannel */
870                                 message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
871                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
872                                 add_trace("type", NULL, "assign");
873 #ifdef SOCKET_MISDN
874                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
875 #else
876                                 add_trace("socket", "id", "%d", portid);
877 #endif
878                                 end_trace();
879                                 state = B_STATE_EXPORTING;
880                                 mISDNport->b_remote_id[i] = p_m_remote_id;
881                                 mISDNport->b_remote_ref[i] = p_m_remote_ref;
882                         } else
883                         {
884                                 /* create stack and send activation request */
885                                 if (_bchannel_create(mISDNport, i))
886                                 {
887                                         _bchannel_activate(mISDNport, i, 1);
888                                         state = B_STATE_ACTIVATING;
889                                         timer = now_d + B_TIMER_ACTIVATING;
890                                 }
891                         }
892                         break;
893
894                         case B_STATE_ACTIVATING:
895                         case B_STATE_EXPORTING:
896                         /* do nothing, because it is already activating */
897                         break;
898
899                         case B_STATE_DEACTIVATING:
900                         case B_STATE_IMPORTING:
901                         /* do nothing, because we must wait until we can reactivate */
902                         break;
903
904                         default:
905                         /* problems that might ocurr:
906                          * B_EVENT_USE is received when channel already in use.
907                          * bchannel exported, but not freed by other port
908                          */
909                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
910                 }
911                 break;
912
913                 case B_EVENT_EXPORTREQUEST:
914                 /* special case where the bchannel is requested by remote */
915                 if (!p_m_remote_ref)
916                 {
917                         PERROR("export request without remote channel set, please correct.\n");
918                         break;
919                 }
920                 switch(state)
921                 {
922                         case B_STATE_IDLE:
923                         /* in case, the bchannel is exported right after seize_bchannel */
924                         /* export bchannel */
925                         /* p_m_remote_id is set, when this event happens. */
926                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
927                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
928                         add_trace("type", NULL, "assign");
929 #ifdef SOCKET_MISDN
930                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
931 #else
932                         add_trace("socket", "id", "%d", portid);
933 #endif
934                         end_trace();
935                         state = B_STATE_EXPORTING;
936                         mISDNport->b_remote_id[i] = p_m_remote_id;
937                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
938                         break;
939
940                         case B_STATE_ACTIVATING:
941                         case B_STATE_EXPORTING:
942                         /* do nothing, because it is already activating */
943                         break;
944
945                         case B_STATE_DEACTIVATING:
946                         case B_STATE_IMPORTING:
947                         /* do nothing, because we must wait until we can reactivate */
948                         break;
949
950                         case B_STATE_ACTIVE:
951                         /* bchannel is active, so we deactivate */
952                         _bchannel_activate(mISDNport, i, 0);
953                         state = B_STATE_DEACTIVATING;
954                         timer = now_d + B_TIMER_DEACTIVATING;
955                         break;
956
957                         default:
958                         /* problems that might ocurr:
959                          * ... when channel already in use.
960                          * bchannel exported, but not freed by other port
961                          */
962                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
963                 }
964                 break;
965
966                 case B_EVENT_ACTIVATED:
967                 timer = 0;
968                 switch(state)
969                 {
970                         case B_STATE_ACTIVATING:
971                         if (b_port && !p_m_remote_id)
972                         {
973                                 /* bchannel is active and used by Port class, so we configure bchannel */
974                                 _bchannel_configure(mISDNport, i);
975                                 state = B_STATE_ACTIVE;
976                         } else
977                         {
978                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
979                                 _bchannel_activate(mISDNport, i, 0);
980                                 state = B_STATE_DEACTIVATING;
981                                 timer = now_d + B_TIMER_DEACTIVATING;
982                         }
983                         break;
984
985                         default:
986                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
987                 }
988                 break;
989
990                 case B_EVENT_EXPORTED:
991                 switch(state)
992                 {
993                         case B_STATE_EXPORTING:
994                         if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i])
995                         {
996                                 /* remote export done */
997                                 state = B_STATE_REMOTE;
998                         } else
999                         {
1000                                 /* bchannel is now exported, but we need bchannel back
1001                                  * OR bchannel is not used anymore
1002                                  * OR bchannel has been exported to an obsolete ref,
1003                                  * so reimport, to later export to new remote */
1004                                 message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
1005                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1006                                 add_trace("type", NULL, "remove");
1007 #ifdef SOCKET_MISDN
1008                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1009 #else
1010                                 add_trace("socket", "id", "%d", portid);
1011 #endif
1012                                 end_trace();
1013                                 state = B_STATE_IMPORTING;
1014                         }
1015                         break;
1016
1017                         default:
1018                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1019                 }
1020                 break;
1021
1022                 case B_EVENT_DROP:
1023                 if (!b_port)
1024                         FATAL("bchannel must be linked to a Port class\n");
1025                 switch(state)
1026                 {
1027                         case B_STATE_IDLE:
1028                         /* bchannel is idle due to an error, so we do nothing */
1029                         break;
1030
1031                         case B_STATE_ACTIVATING:
1032                         case B_STATE_EXPORTING:
1033                         /* do nothing because we must wait until bchanenl is active before deactivating */
1034                         break;
1035
1036                         case B_STATE_ACTIVE:
1037                         /* bchannel is active, so we deactivate */
1038                         _bchannel_activate(mISDNport, i, 0);
1039                         state = B_STATE_DEACTIVATING;
1040                         timer = now_d + B_TIMER_DEACTIVATING;
1041                         break;
1042
1043                         case B_STATE_REMOTE:
1044                         /* bchannel is exported, so we re-import */
1045                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
1046                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1047                         add_trace("type", NULL, "remove");
1048 #ifdef SOCKET_MISDN
1049                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1050 #else
1051                         add_trace("socket", "id", "%d", portid);
1052 #endif
1053                         end_trace();
1054                         state = B_STATE_IMPORTING;
1055                         break;
1056
1057                         case B_STATE_DEACTIVATING:
1058                         case B_STATE_IMPORTING:
1059                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
1060                         break;
1061
1062                         default:
1063                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1064                 }
1065                 break;
1066
1067                 case B_EVENT_DEACTIVATED:
1068                 timer = 0;
1069                 switch(state)
1070                 {
1071                         case B_STATE_IDLE:
1072                         /* ignore due to deactivation confirm after unloading */
1073                         break;
1074
1075                         case B_STATE_DEACTIVATING:
1076                         _bchannel_destroy(mISDNport, i);
1077                         state = B_STATE_IDLE;
1078                         if (b_port)
1079                         {
1080                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
1081                                 if (p_m_remote_ref)
1082                                 {
1083                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
1084                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1085                                         add_trace("type", NULL, "assign");
1086 #ifdef SOCKET_MISDN
1087                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1088 #else
1089                                         add_trace("socket", "id", "%d", portid);
1090 #endif
1091                                         end_trace();
1092                                         state = B_STATE_EXPORTING;
1093                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1094                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1095                                 } else
1096                                 {
1097                                         if (_bchannel_create(mISDNport, i))
1098                                         {
1099                                                 _bchannel_activate(mISDNport, i, 1);
1100                                                 state = B_STATE_ACTIVATING;
1101                                                 timer = now_d + B_TIMER_ACTIVATING;
1102                                         }
1103                                 }
1104                         }
1105                         break;
1106
1107                         default:
1108                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1109                 }
1110                 break;
1111
1112                 case B_EVENT_IMPORTED:
1113                 switch(state)
1114                 {
1115                         case B_STATE_IMPORTING:
1116                         state = B_STATE_IDLE;
1117                         mISDNport->b_remote_id[i] = 0;
1118                         mISDNport->b_remote_ref[i] = 0;
1119                         if (b_port)
1120                         {
1121                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
1122                                 if (p_m_remote_ref)
1123                                 {
1124                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
1125                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1126                                         add_trace("type", NULL, "assign");
1127 #ifdef SOCKET_MISDN
1128                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1129 #else
1130                                         add_trace("socket", "id", "%d", portid);
1131 #endif
1132                                         end_trace();
1133                                         state = B_STATE_EXPORTING;
1134                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1135                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1136                                 } else
1137                                 {
1138                                         if (_bchannel_create(mISDNport, i))
1139                                         {
1140                                                 _bchannel_activate(mISDNport, i, 1);
1141                                                 state = B_STATE_ACTIVATING;
1142                                                 timer = now_d + B_TIMER_ACTIVATING;
1143                                         }
1144                                 }
1145                         }
1146                         break;
1147
1148                         default:
1149                         /* ignore, because not assigned */
1150                         ;
1151                 }
1152                 break;
1153
1154                 case B_EVENT_TIMEOUT:
1155                 timer = 0;
1156                 switch(state)
1157                 {
1158                         case B_STATE_IDLE:
1159                         /* ignore due to deactivation confirm after unloading */
1160                         break;
1161
1162                         case B_STATE_ACTIVATING:
1163                         _bchannel_activate(mISDNport, i, 1);
1164                         timer = now_d + B_TIMER_ACTIVATING;
1165                         break;
1166
1167                         case B_STATE_DEACTIVATING:
1168                         _bchannel_activate(mISDNport, i, 0);
1169                         timer = now_d + B_TIMER_DEACTIVATING;
1170                         break;
1171
1172                         default:
1173                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1174                 }
1175                 break;
1176
1177                 default:
1178                 PERROR("Illegal event %d, please correct.\n", event);
1179         }
1180
1181         mISDNport->b_state[i] = state;
1182         mISDNport->b_timer[i] = timer;
1183 }
1184
1185
1186
1187
1188 /*
1189  * check for available channel and reserve+set it.
1190  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
1191  * give exclusiv flag
1192  * returns -(cause value) or x = channel x or 0 = no channel
1193  * NOTE: no activation is done here
1194  */
1195 int PmISDN::seize_bchannel(int channel, int exclusive)
1196 {
1197         int i;
1198
1199         /* the channel is what we have */
1200         if (p_m_b_channel == channel)
1201                 return(channel);
1202
1203         /* if channel already in use, release it */
1204         if (p_m_b_channel)
1205                 drop_bchannel();
1206
1207         /* if CHANNEL_NO */
1208         if (channel==CHANNEL_NO || channel==0)
1209                 return(0);
1210         
1211         /* is channel in range ? */
1212         if (channel==16
1213          || (channel>p_m_mISDNport->b_num && channel<16)
1214          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
1215                 return(-6); /* channel unacceptable */
1216
1217         /* request exclusive channel */
1218         if (exclusive && channel>0)
1219         {
1220                 i = channel-1-(channel>16);
1221                 if (p_m_mISDNport->b_port[i])
1222                         return(-44); /* requested channel not available */
1223                 goto seize;
1224         }
1225
1226         /* ask for channel */
1227         if (channel>0)
1228         {
1229                 i = channel-1-(channel>16);
1230                 if (p_m_mISDNport->b_port[i] == NULL)
1231                         goto seize;
1232         }
1233
1234         /* search for channel */
1235         i = 0;
1236         while(i < p_m_mISDNport->b_num)
1237         {
1238                 if (!p_m_mISDNport->b_port[i])
1239                 {
1240                         channel = i+1+(i>=15);
1241                         goto seize;
1242                 }
1243                 i++;
1244         }
1245         return(-34); /* no free channel */
1246
1247 seize:
1248         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
1249
1250         /* link Port */
1251         p_m_mISDNport->b_port[i] = this;
1252         p_m_b_index = i;
1253         p_m_b_channel = channel;
1254         p_m_b_exclusive = exclusive;
1255
1256         /* reserve channel */
1257         if (!p_m_b_reserve)
1258         {
1259                 p_m_b_reserve = 1;
1260                 p_m_mISDNport->b_reserved++;
1261         }
1262
1263         return(channel);
1264 }
1265
1266 /*
1267  * drop reserved channel and unset it.
1268  * deactivation is also done
1269  */
1270 void PmISDN::drop_bchannel(void)
1271 {
1272         /* unreserve channel */
1273         if (p_m_b_reserve)
1274                 p_m_mISDNport->b_reserved--;
1275         p_m_b_reserve = 0;
1276
1277         /* if not in use */
1278         if (p_m_b_index < 0)
1279                 return;
1280         if (!p_m_b_channel)
1281                 return;
1282
1283         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1284
1285         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1286                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1287         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1288         p_m_b_index = -1;
1289         p_m_b_channel = 0;
1290         p_m_b_exclusive = 0;
1291 }
1292
1293 /* process bchannel export/import message from join */
1294 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
1295 {
1296         class Endpoint *epoint;
1297         class Port *port;
1298         class PmISDN *isdnport;
1299         struct mISDNport *mISDNport;
1300         int i, ii;
1301
1302         switch(type)
1303         {
1304                 case BCHANNEL_REQUEST:
1305                 /* find the port object for the join object ref */
1306                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1307                 {
1308                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1309                         return;
1310                 }
1311                 if (!epoint->ep_portlist)
1312                 {
1313                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1314                         return;
1315                 }
1316                 if (epoint->ep_portlist->next)
1317                 {
1318                         PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
1319                 }
1320                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1321                 {
1322                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1323                         return;
1324                 }
1325                 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1326                 {
1327                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1328                 }
1329                 isdnport = (class PmISDN *)port;
1330
1331                 /* assign */
1332                 if (isdnport->p_m_remote_id)
1333                 {
1334                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1335                         break;
1336                 }
1337                 mISDNport = isdnport->p_m_mISDNport;
1338                 i = isdnport->p_m_b_index;
1339                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1340                 add_trace("type", NULL, "export request");
1341                 isdnport->p_m_remote_ref = joinremote->j_serial;
1342                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1343                 if (mISDNport && i>=0)
1344                 {
1345                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1346                 }
1347                 end_trace();
1348                 break;
1349
1350                 case BCHANNEL_ASSIGN_ACK:
1351                 case BCHANNEL_REMOVE_ACK:
1352                 /* find mISDNport for stack ID */
1353                 mISDNport = mISDNport_first;
1354                 while(mISDNport)
1355                 {
1356                         i = 0;
1357                         ii = mISDNport->b_num;
1358                         while(i < ii)
1359                         {
1360 #ifdef SOCKET_MISDN
1361                                 if (mISDNport->b_socket[i] == handle)
1362 #else
1363                                 if ((unsigned long)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1364 #endif
1365                                         break;
1366                                 i++;
1367                         }
1368                         if (i != ii)
1369                                 break;
1370                         mISDNport = mISDNport->next;
1371                 }
1372                 if (!mISDNport)
1373                 {
1374                         PERROR("received assign/remove ack for handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1375                         break;
1376                 }
1377                 /* mISDNport may now be set or NULL */
1378                 
1379                 /* set */
1380                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1381                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1382                 if (mISDNport && i>=0)
1383                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1384                 end_trace();
1385                 break;
1386                 default:
1387                 PERROR("received wrong bchannel message type %d from remote\n", type);
1388         }
1389 }
1390
1391
1392 /*
1393  * handler
1394
1395 audio transmission procedure:
1396 -----------------------------
1397
1398 * priority
1399 three sources of audio transmission:
1400 - crypto-data high priority
1401 - tones high priority (also high)
1402 - remote-data low priority
1403
1404 * elapsed
1405 a variable that temporarily shows the number of samples elapsed since last transmission process.
1406 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1407
1408 * load
1409 a variable that is increased whenever data is transmitted.
1410 it is decreased while time elapses. it stores the number of samples that
1411 are currently loaded to dsp module.
1412 since clock in dsp module is the same clock for user space process, these 
1413 times have no skew.
1414
1415 * levels
1416 there are two levels:
1417 ISDN_LOAD will give the load that have to be kept in dsp.
1418 ISDN_MAXLOAD will give the maximum load before dropping.
1419
1420 * procedure for low priority data
1421 see txfromup() for procedure
1422 in short: remote data is ignored during high priority tones
1423
1424 * procedure for high priority data
1425 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1426 if no more data is available, load becomes empty again.
1427
1428 'load' variable:
1429 0                    ISDN_LOAD           ISDN_MAXLOAD
1430 +--------------------+----------------------+
1431 |                    |                      |
1432 +--------------------+----------------------+
1433
1434 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1435 0                    ISDN_LOAD           ISDN_MAXLOAD
1436 +--------------------+----------------------+
1437 |TTTTTTTTTTTTTTTTTTTT|                      |
1438 +--------------------+----------------------+
1439
1440 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1441 0                    ISDN_LOAD           ISDN_MAXLOAD
1442 +--------------------+----------------------+
1443 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1444 +--------------------+----------------------+
1445
1446  */
1447 int PmISDN::handler(void)
1448 {
1449         struct message *message;
1450         int elapsed = 0;
1451         int ret;
1452
1453         if ((ret = Port::handler()))
1454                 return(ret);
1455
1456         /* get elapsed */
1457         if (p_m_last_tv_sec)
1458         {
1459                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1460                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1461         } else
1462         {
1463                 /* set clock of first process ever in this instance */
1464                 p_m_last_tv_sec = now_tv.tv_sec;
1465                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1466         }
1467         /* process only if we have a minimum of samples, to make packets not too small */
1468         if (elapsed >= ISDN_TRANSMIT)
1469         {
1470                 /* set clock of last process! */
1471                 p_m_last_tv_sec = now_tv.tv_sec;
1472                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1473
1474                 /* update load */
1475                 if (elapsed < p_m_load)
1476                         p_m_load -= elapsed;
1477                 else
1478                         p_m_load = 0;
1479
1480                 /* to send data, tone must be active OR crypt messages must be on */
1481                 if ((p_tone_name[0] || p_m_crypt_msg_loops)
1482                  && (p_m_load < ISDN_LOAD)
1483                  && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones))
1484                 {
1485                         int tosend = ISDN_LOAD - p_m_load, length; 
1486 #ifdef SOCKET_MISDN
1487                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1488                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1489                         unsigned long *d = buf+MISDN_HEADER_LEN;
1490 #else
1491                         unsigned char buf[mISDN_HEADER_LEN+tosend];
1492                         iframe_t *frm = (iframe_t *)buf;
1493                         unsigned char *p = buf+mISDN_HEADER_LEN;
1494 #endif
1495
1496                         /* copy crypto loops */
1497                         while (p_m_crypt_msg_loops && tosend)
1498                         {
1499                                 /* how much do we have to send */
1500                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1501
1502                                 /* clip tosend */
1503                                 if (length > tosend)
1504                                         length = tosend;
1505
1506                                 /* copy message (part) to buffer */
1507                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1508
1509                                 /* new position */
1510                                 p_m_crypt_msg_current += length;
1511                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1512                                 {
1513                                         /* next loop */
1514                                         p_m_crypt_msg_current = 0;
1515                                         p_m_crypt_msg_loops--;
1516 //                                      puts("eine loop weniger");
1517                                 }
1518
1519                                 /* new length */
1520                                 tosend -= length;
1521                         }
1522
1523                         /* copy tones */
1524                         if (p_tone_name[0] && tosend)
1525                         {
1526                                 tosend -= read_audio(p, tosend);
1527                         }
1528
1529                         /* send data */
1530 #ifdef SOCKET_MISDN
1531                         frm->prim = DL_DATA_REQ;
1532                         frm->id = 0;
1533                         ret = sendto(handle, buffer, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1534                         if (!ret)
1535                                 PERROR("Failed to send to socket %d\n", handle);
1536 #else
1537                         frm->prim = DL_DATA | REQUEST; 
1538                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1539                         frm->dinfo = 0;
1540                         frm->len = ISDN_LOAD - p_m_load - tosend;
1541 #endif
1542                         if (frm->len)
1543                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1544                         p_m_load += frm->len;
1545                 }
1546         }
1547
1548         // NOTE: deletion is done by the child class
1549
1550         /* handle timeouts */
1551         if (p_m_timeout)
1552         {
1553                 if (p_m_timer+p_m_timeout < now_d)
1554                 {
1555                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1556                         p_m_timeout = 0;
1557                         /* send timeout to endpoint */
1558                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1559                         message->param.state = p_state;
1560                         message_put(message);
1561                         return(1);
1562                 }
1563         }
1564         
1565         return(0); /* nothing done */
1566 }
1567
1568
1569 /*
1570  * whenever we get audio data from bchannel, we process it here
1571  */
1572 #ifdef SOCKET_MISDN
1573 void PmISDN::bchannel_receive(mISDNhead *hh, unsigned char *data, int len)
1574 {
1575         unsigned long cont = *((unsigned long *)data);
1576 #else
1577 void PmISDN::bchannel_receive(iframe_t *frm)
1578 {
1579         int len = frm->len;
1580         unsigned long cont = *((unsigned long *)&frm->data.p);
1581         unsigned char *data =(unsigned char *)&frm->data.p;
1582 #endif
1583         unsigned char *data_temp;
1584         unsigned long length_temp;
1585         struct message *message;
1586         unsigned char *p;
1587         int l;
1588
1589 #ifdef SOCKET_MISDN
1590         if (hh->prim == PH_CONTROL_IND)
1591 #else
1592         if (frm->prim == (PH_CONTROL | INDICATION))
1593 #endif
1594         {
1595                 if (len < 4)
1596                 {
1597                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1598                         return;
1599                 }
1600                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1601                 {
1602                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1603                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1604                         end_trace();
1605                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1606                         message->param.dtmf = cont & DTMF_TONE_MASK;
1607                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1608                         message_put(message);
1609                         return;
1610                 }
1611                 switch(cont)
1612                 {
1613                         case BF_REJECT:
1614                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1615                         add_trace("DSP-CRYPT", NULL, "error");
1616                         end_trace();
1617                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1618                         message->param.crypt.type = CC_ERROR_IND;
1619                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1620                         message_put(message);
1621                         break;
1622
1623                         case BF_ACCEPT:
1624                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1625                         add_trace("DSP-CRYPT", NULL, "ok");
1626                         end_trace();
1627                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1628                         message->param.crypt.type = CC_ACTBF_CONF;
1629                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1630                         message_put(message);
1631                         break;
1632
1633                         default:
1634                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1635                         add_trace("unknown", NULL, "0x%x", cont);
1636                         end_trace();
1637                 }
1638                 return;
1639         }
1640 #ifdef SOCKET_MISDN
1641         if (hh->prim == PH_SIGNAL_IND)
1642 #else
1643         if (frm->prim == (PH_SIGNAL | INDICATION))
1644 #endif
1645         {
1646                 switch(frm->dinfo)
1647                 {
1648 #ifndef OLD_MISDN
1649                         case CMX_TX_DATA:
1650                         if (!p_m_txdata)
1651                         {
1652                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1653                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1654                                 return;
1655                         }
1656                         /* see below (same condition) */
1657                         if (p_state!=PORT_STATE_CONNECT
1658                                  && !p_m_mISDNport->tones)
1659                                 break;
1660 //                      printf(".");fflush(stdout);return;
1661                         if (p_record)
1662                                 record(data, len, 1); // from up
1663                         break;
1664 #endif
1665
1666                         default:
1667                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL signal", DIRECTION_IN);
1668                         add_trace("unknown", NULL, "0x%x", frm->dinfo);
1669                         end_trace();
1670                 }
1671                 return;
1672         }
1673 #ifdef SOCKET_MISDN
1674         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1675         {
1676                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1677 #else
1678         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1679         {
1680                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1681 #endif
1682                 return;
1683         }
1684         /* calls will not process any audio data unless
1685          * the call is connected OR interface features audio during call setup.
1686          */
1687 //printf("%d -> %d prim=%x joindata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_joindata, p_m_mISDNport->earlyb);     
1688 #ifndef DEBUG_COREBRIDGE
1689         if (p_state!=PORT_STATE_CONNECT
1690          && !p_m_mISDNport->tones)
1691                 return;
1692 #endif
1693
1694         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1695         if (p_m_rxoff)
1696         {
1697                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1698                 return;
1699         }
1700
1701         /* record data */
1702         if (p_record)
1703                 record(data, len, 0); // from down
1704
1705         /* randomize and listen to crypt message if enabled */
1706         if (p_m_crypt_listen)
1707         {
1708                 /* the noisy randomizer */
1709                 p = data;
1710                 l = len;
1711                 while(l--)
1712                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1713
1714                 cryptman_listen_bch(data, len);
1715         }
1716
1717         p = data;
1718
1719         /* send data to epoint */
1720         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1721         {
1722                 length_temp = len;
1723                 data_temp = p;
1724                 while(length_temp)
1725                 {
1726                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1727                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1728                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1729                         message_put(message);
1730                         if (length_temp <= sizeof(message->param.data.data))
1731                                 break;
1732                         data_temp += sizeof(message->param.data.data);
1733                         length_temp -= sizeof(message->param.data.data);
1734                 }
1735         }
1736 }
1737
1738
1739 /*
1740  * set echotest
1741  */
1742 void PmISDN::set_echotest(int echo)
1743 {
1744         if (p_m_echo != echo)
1745         {
1746                 p_m_echo = echo;
1747                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1748                 if (p_m_b_channel)
1749                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1750 #ifdef SOCKET_MISDN
1751                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1752 #else
1753                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1754 #endif
1755         }
1756 }
1757
1758 /*
1759  * set tone
1760  */
1761 void PmISDN::set_tone(char *dir, char *tone)
1762 {
1763         int id;
1764
1765         if (!tone)
1766                 tone = "";
1767         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1768         if (!tone[0])
1769         {
1770                 id = TONE_OFF;
1771                 goto setdsp;
1772         }
1773
1774         /* check if we NOT really have to use a dsp-tone */
1775         if (!options.dsptones)
1776         {
1777                 nodsp:
1778                 if (p_m_tone)
1779                 if (p_m_b_index >= 0)
1780                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1781                 {
1782                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1783 #ifdef SOCKET_MISDN
1784                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1785 #else
1786                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1787 #endif
1788                 }
1789                 p_m_tone = 0;
1790                 Port::set_tone(dir, tone);
1791                 return;
1792         }
1793         if (p_tone_dir[0])
1794                 goto nodsp;
1795
1796         /* now we USE dsp-tone, convert name */
1797         else if (!strcmp(tone, "dialtone"))
1798         {
1799                 switch(options.dsptones) {
1800                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1801                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1802                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1803                 }
1804         } else if (!strcmp(tone, "dialpbx"))
1805         {
1806                 switch(options.dsptones) {
1807                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1808                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1809                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1810                 }
1811         } else if (!strcmp(tone, "ringing"))
1812         {
1813                 switch(options.dsptones) {
1814                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1815                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1816                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1817                 }
1818         } else if (!strcmp(tone, "ringpbx"))
1819         {
1820                 switch(options.dsptones) {
1821                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1822                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1823                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1824                 }
1825         } else if (!strcmp(tone, "busy"))
1826         {
1827                 busy:
1828                 switch(options.dsptones) {
1829                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1830                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1831                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1832                 }
1833         } else if (!strcmp(tone, "release"))
1834         {
1835                 hangup:
1836                 switch(options.dsptones) {
1837                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1838                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1839                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1840                 }
1841         } else if (!strcmp(tone, "cause_10"))
1842                 goto hangup;
1843         else if (!strcmp(tone, "cause_11"))
1844                 goto busy;
1845         else if (!strcmp(tone, "cause_22"))
1846         {
1847                 switch(options.dsptones) {
1848                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1849                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1850                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1851                 }
1852         } else if (!strncmp(tone, "cause_", 6))
1853                 id = TONE_SPECIAL_INFO;
1854         else
1855                 id = TONE_OFF;
1856
1857         /* if we have a tone that is not supported by dsp */
1858         if (id==TONE_OFF && tone[0])
1859                 goto nodsp;
1860
1861         setdsp:
1862         if (p_m_tone != id)
1863         {
1864                 /* set new tone */
1865                 p_m_tone = id;
1866                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1867                 if (p_m_b_index >= 0)
1868                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1869 #ifdef SOCKET_MISDN
1870                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1871 #else
1872                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1873 #endif
1874         }
1875         /* turn user-space tones off in cases of no tone OR dsp tone */
1876         Port::set_tone("",NULL);
1877 }
1878
1879
1880 /* MESSAGE_mISDNSIGNAL */
1881 //extern struct message *dddebug;
1882 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1883 {
1884         switch(param->mISDNsignal.message)
1885         {
1886                 case mISDNSIGNAL_VOLUME:
1887                 if (p_m_tx_gain != param->mISDNsignal.tx_gain)
1888                 {
1889                         p_m_tx_gain = param->mISDNsignal.tx_gain;
1890                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_tx_gain);
1891                         if (p_m_b_index >= 0)
1892                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1893 #ifdef SOCKET_MISDN
1894                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_TX, p_m_tx_gain, "DSP-TX_GAIN", p_m_tx_gain);
1895 #else
1896                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_TX, p_m_tx_gain, "DSP-TX_GAIN", p_m_tx_gain);
1897 #endif
1898                 } else
1899                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rx_gain);
1900                 if (p_m_rx_gain != param->mISDNsignal.rx_gain)
1901                 {
1902                         p_m_rx_gain = param->mISDNsignal.rx_gain;
1903                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rx_gain);
1904                         if (p_m_b_index >= 0)
1905                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1906 #ifdef SOCKET_MISDN
1907                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_RX, p_m_rx_gain, "DSP-RX_GAIN", p_m_rx_gain);
1908 #else
1909                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_RX, p_m_rx_gain, "DSP-RX_GAIN", p_m_rx_gain);
1910 #endif
1911                 } else
1912                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rx_gain);
1913                 break;
1914
1915                 case mISDNSIGNAL_CONF:
1916 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1917 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1918                 if (p_m_conf != param->mISDNsignal.conf)
1919                 {
1920                         p_m_conf = param->mISDNsignal.conf;
1921                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1922                         if (p_m_b_index >= 0)
1923                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1924 #ifdef SOCKET_MISDN
1925                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1926 #else
1927                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1928 #endif
1929                 } else
1930                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1931                 /* we must set, even if currently tone forbids conf */
1932                 p_m_conf = param->mISDNsignal.conf;
1933 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1934                 break;
1935
1936                 case mISDNSIGNAL_JOINDATA:
1937                 if (p_m_joindata != param->mISDNsignal.joindata)
1938                 {
1939                         p_m_joindata = param->mISDNsignal.joindata;
1940                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1941                 } else
1942                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1943                 break;
1944                 
1945                 case mISDNSIGNAL_DELAY:
1946                 if (p_m_delay != param->mISDNsignal.delay)
1947                 {
1948                         p_m_delay = param->mISDNsignal.delay;
1949                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1950 #ifndef OLD_MISDN
1951                         if (p_m_b_index >= 0)
1952                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1953 #ifdef SOCKET_MISDN
1954                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1955 #else
1956                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1957 #endif
1958 #endif
1959                 } else
1960                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1961                 break;
1962
1963                 default:
1964                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1965         }
1966 }
1967
1968 /* MESSAGE_CRYPT */
1969 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1970 {
1971         struct message *message;
1972
1973         switch(param->crypt.type)
1974         {
1975                 case CC_ACTBF_REQ:           /* activate blowfish */
1976                 p_m_crypt = 1;
1977                 p_m_crypt_key_len = param->crypt.len;
1978                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1979                 {
1980                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1981                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1982                         message->param.crypt.type = CC_ERROR_IND;
1983                         message_put(message);
1984                         break;
1985                 }
1986                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1987                 crypt_off:
1988                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1989                 if (p_m_b_index >= 0)
1990                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1991 #ifdef SOCKET_MISDN
1992                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_crypt?BF_ENABLE_KEY:BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1993 #else
1994                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_crypt?BF_ENABLE_KEY:BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1995 #endif
1996                 break;
1997
1998                 case CC_DACT_REQ:            /* deactivate session encryption */
1999                 p_m_crypt = 0;
2000                 goto crypt_off;
2001                 break;
2002
2003                 case CR_LISTEN_REQ:          /* start listening to messages */
2004                 p_m_crypt_listen = 1;
2005                 p_m_crypt_listen_state = 0;
2006                 break;
2007
2008                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
2009                 p_m_crypt_listen = 0;
2010                 break;
2011
2012                 case CR_MESSAGE_REQ:         /* send message */
2013                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
2014                 if (!p_m_crypt_msg_len)
2015                 {
2016                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
2017                         break;
2018                 }
2019                 p_m_crypt_msg_current = 0; /* reset */
2020                 p_m_crypt_msg_loops = 6; /* enable */
2021 #if 0
2022                 /* disable txmix, or we get corrupt data due to audio process */
2023                 if (p_m_txmix && p_m_b_index>=0)
2024                 {
2025                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
2026 #ifdef SOCKET_MISDN
2027                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
2028 #else
2029                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
2030 #endif
2031                 }
2032 #endif
2033                 break;
2034
2035                 default:
2036                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
2037         }
2038
2039 }
2040
2041 /*
2042  * endpoint sends messages to the port
2043  */
2044 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
2045 {
2046         if (Port::message_epoint(epoint_id, message_id, param))
2047                 return(1);
2048
2049         switch(message_id)
2050         {
2051                 case MESSAGE_DATA: /* tx-data from upper layer */
2052                 txfromup(param->data.data, param->data.len);
2053                 return(1);
2054
2055                 case MESSAGE_mISDNSIGNAL: /* user command */
2056                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
2057                 message_mISDNsignal(epoint_id, message_id, param);
2058                 return(1);
2059
2060                 case MESSAGE_CRYPT: /* crypt control command */
2061                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
2062                 message_crypt(epoint_id, message_id, param);
2063                 return(1);
2064         }
2065
2066         return(0);
2067 }
2068
2069
2070 /*
2071  * main loop for processing messages from mISDN
2072  */
2073 #ifdef SOCKET_MISDN
2074 int mISDN_handler(void)
2075 {
2076         int ret, work = 0;
2077         struct mISDNport *mISDNport;
2078         class PmISDN *isdnport;
2079         int i;
2080         char buffer[2048+MISDN_HEADER_LEN];
2081         struct mISDNhead *hh = (struct mISDNhead *)buffer;
2082
2083         /* process all ports */
2084         mISDNport = mISDNport_first;
2085         while(mISDNport)
2086         {
2087                 /* process all bchannels */
2088                 i = 0;
2089                 while(i < mISDNport->b_num)
2090                 {
2091                         /* process timer events for bchannel handling */
2092                         if (mISDNport->b_timer[i])
2093                         {
2094                                 if (mISDNport->b_timer[i] <= now_d)
2095                                         bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
2096                         }
2097                         /* handle port of bchannel */
2098                         isdnport=mISDNport->b_port[i];
2099                         if (isdnport)
2100                         {
2101                                 /* call bridges in user space OR crypto OR recording */
2102                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2103                                 {
2104                                         /* rx IS required */
2105                                         if (isdnport->p_m_rxoff)
2106                                         {
2107                                                 /* turn on RX */
2108                                                 isdnport->p_m_rxoff = 0;
2109                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2110                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2111                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2112                                                 return(1);
2113                                         }
2114                                 } else
2115                                 {
2116                                         /* rx NOT required */
2117                                         if (!isdnport->p_m_rxoff)
2118                                         {
2119                                                 /* turn off RX */
2120                                                 isdnport->p_m_rxoff = 1;
2121                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2122                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2123                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2124                                                 return(1);
2125                                         }
2126                                 }
2127                                 /* recording */
2128                                 if (isdnport->p_record)
2129                                 {
2130                                         /* txdata IS required */
2131                                         if (!isdnport->p_m_txdata)
2132                                         {
2133                                                 /* turn on RX */
2134                                                 isdnport->p_m_txdata = 1;
2135                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2136                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2137                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2138                                                 return(1);
2139                                         }
2140                                 } else
2141                                 {
2142                                         /* txdata NOT required */
2143                                         if (isdnport->p_m_txdata)
2144                                         {
2145                                                 /* turn off RX */
2146                                                 isdnport->p_m_txdata = 0;
2147                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2148                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2149                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2150                                                 return(1);
2151                                         }
2152                                 }
2153                         }
2154
2155                         /* handle message from bchannel */
2156                         if (mISDNport->b_stack[i] > -1)
2157                         {
2158                                 ret = recv(mISDNport->b_stack[i], buffer, sizeof(buffer), 0);
2159                                 if (ret >= MISDN_HEADER_LEN)
2160                                 {
2161                                         work = 1;
2162                                         switch(hh->prim)
2163                                         {
2164                                                 /* we don't care about confirms, we use rx data to sync tx */
2165                                                 case PH_DATA_CONF:
2166                                                 case DL_DATA_CONF:
2167                                                 break;
2168
2169                                                 /* we receive audio data, we respond to it AND we send tones */
2170                                                 case PH_DATA_IND:
2171                                                 case DL_DATA_IND:
2172                                                 case PH_SIGNAL_IND:
2173                                                 case PH_CONTROL_IND:
2174                                                 if (mISDNport->b_port[i])
2175                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
2176                                                 else
2177                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_stack[i]);
2178                                                 break;
2179
2180                                                 case PH_ACTIVATE_IND:
2181                                                 case DL_ESTABLISH_IND:
2182                                                 case PH_ACTIVATE_CONF:
2183                                                 case DL_ESTABLISH_CONF:
2184                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
2185                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2186                                                 break;
2187
2188                                                 case PH_DEACTIVATE_IND:
2189                                                 case DL_RELEASE_IND:
2190                                                 case PH_DEACTIVATE_CONF:
2191                                                 case DL_RELEASE_CONF:
2192                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
2193                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2194                                                 break;
2195
2196                                                 default:
2197                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], msg->len);
2198                                         }
2199                                 } else
2200                                 {
2201                                         if (ret < 0 && errno != EWOULDBLOCK)
2202                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
2203                                 }
2204                         }
2205                         
2206                         i++;
2207                 }
2208 #if 0
2209                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2210                 { ---}
2211                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2212                         mISDNport->l1timeout = 0;
2213 #endif
2214
2215                 /* layer 2 establish timer */
2216                 if (mISDNport->l2establish)
2217                 {
2218                         if (now-mISDNport->l2establish > 5)
2219                         {
2220
2221                                 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2222                                 mISDNport->ml3->to_layer2(mISDNport->ml3, DL_ESTABLISH_REQ);
2223                                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2224                                 end_trace();
2225                                 return(1);
2226                         }
2227                 }
2228
2229
2230                 mISDNport = mISDNport->next;
2231         }
2232
2233         /* if we received at least one b-frame, we will return 1 */
2234         return(work);
2235 }
2236 #else
2237 int mISDN_handler(void)
2238 {
2239         int ret;
2240         struct mISDNport *mISDNport;
2241         class PmISDN *isdnport;
2242         int i;
2243         msg_t *msg;
2244         iframe_t *frm;
2245         msg_t *dmsg;
2246         mISDNuser_head_t *hh;
2247         net_stack_t *nst;
2248
2249         /* the que avoids loopbacks when replying to stack after receiving
2250          * from stack. */
2251         mISDNport = mISDNport_first;
2252         while(mISDNport)
2253         {
2254                 /* process turning on/off rx */
2255                 i = 0;
2256                 while(i < mISDNport->b_num)
2257                 {
2258                         /* process timer events for bchannel handling */
2259                         if (mISDNport->b_timer[i])
2260                         {
2261                                 if (mISDNport->b_timer[i] <= now_d)
2262                                         bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
2263                         }
2264                         isdnport=mISDNport->b_port[i];
2265                         if (isdnport)
2266                         {
2267                                 /* call bridges in user space OR crypto OR recording */
2268                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2269                                 {
2270                                         /* rx IS required */
2271                                         if (isdnport->p_m_rxoff)
2272                                         {
2273                                                 /* turn on RX */
2274                                                 isdnport->p_m_rxoff = 0;
2275                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2276                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2277                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2278                                                 return(1);
2279                                         }
2280                                 } else
2281                                 {
2282                                         /* rx NOT required */
2283                                         if (!isdnport->p_m_rxoff)
2284                                         {
2285                                                 /* turn off RX */
2286                                                 isdnport->p_m_rxoff = 1;
2287                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2288                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2289                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2290                                                 return(1);
2291                                         }
2292                                 }
2293                                 /* recording */
2294                                 if (isdnport->p_record)
2295                                 {
2296                                         /* txdata IS required */
2297                                         if (!isdnport->p_m_txdata)
2298                                         {
2299                                                 /* turn on RX */
2300                                                 isdnport->p_m_txdata = 1;
2301                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2302 #ifndef OLD_MISDN
2303                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2304                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2305 #endif
2306                                                 return(1);
2307                                         }
2308                                 } else
2309                                 {
2310                                         /* txdata NOT required */
2311                                         if (isdnport->p_m_txdata)
2312                                         {
2313                                                 /* turn off RX */
2314                                                 isdnport->p_m_txdata = 0;
2315                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2316 #ifndef OLD_MISDN
2317                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2318                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2319 #endif
2320                                                 return(1);
2321                                         }
2322                                 }
2323                         }
2324                         i++;
2325                 }
2326 #if 0
2327                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2328                 { ---}
2329                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2330                         mISDNport->l1timeout = 0;
2331 #endif
2332
2333                 if (mISDNport->l2establish)
2334                 {
2335                         if (now-mISDNport->l2establish > 5)
2336                         {
2337                                 if (mISDNport->ntmode)
2338                                 {
2339                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
2340                                         time(&mISDNport->l2establish);
2341                                         /* establish */
2342                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2343                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2344                                                 free_msg(dmsg);
2345                                 } else {
2346                                         iframe_t act;
2347
2348                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
2349                                         time(&mISDNport->l2establish);
2350                                         /* establish */
2351                                         act.prim = DL_ESTABLISH | REQUEST; 
2352                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
2353                                         act.dinfo = 0;
2354                                         act.len = 0;
2355                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2356                                 }
2357                                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2358                                 end_trace();
2359                                 return(1);
2360                         }
2361                 }
2362                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
2363                 {
2364                         if (mISDNport->ntmode)
2365                         {
2366                                 hh = (mISDNuser_head_t *)dmsg->data;
2367                                 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);
2368                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2369                                         free_msg(dmsg);
2370                         } else
2371                         {
2372                                 frm = (iframe_t *)dmsg->data;
2373                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
2374                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
2375                                 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);
2376                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
2377                                 free_msg(dmsg);
2378                         }
2379                         return(1);
2380                 }
2381                 mISDNport = mISDNport->next;
2382         } 
2383
2384         /* no device, no read */
2385         if (mISDNdevice < 0)
2386                 return(0);
2387
2388         /* get message from kernel */
2389         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
2390                 return(1);
2391         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
2392         if (ret < 0)
2393         {
2394                 free_msg(msg);
2395                 if (errno == EAGAIN)
2396                         return(0);
2397                 FATAL("Failed to do mISDN_read()\n");
2398         }
2399         if (!ret)
2400         {
2401                 free_msg(msg);
2402 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
2403                 return(0);
2404         }
2405         msg->len = ret;
2406         frm = (iframe_t *)msg->data;
2407
2408         /* global prim */
2409         switch(frm->prim)
2410         {
2411                 case MGR_DELLAYER | CONFIRM:
2412                 case MGR_INITTIMER | CONFIRM:
2413                 case MGR_ADDTIMER | CONFIRM:
2414                 case MGR_DELTIMER | CONFIRM:
2415                 case MGR_REMOVETIMER | CONFIRM:
2416                 free_msg(msg);
2417                 return(1);
2418         }
2419
2420         /* handle timer events from mISDN for NT-stack
2421          * note: they do not associate with a stack */
2422         if (frm->prim == (MGR_TIMER | INDICATION))
2423         {
2424                 itimer_t *it;
2425
2426                 /* find mISDNport */
2427                 mISDNport = mISDNport_first;
2428                 while(mISDNport)
2429                 {
2430                         /* nt mode only */
2431                         if (mISDNport->ntmode)
2432                         {
2433                                 it = mISDNport->nst.tlist;
2434                                 /* find timer */
2435                                 while(it)
2436                                 {
2437                                         if (it->id == (int)frm->addr)
2438                                                 break;
2439                                         it = it->next;
2440                                 }
2441                                 if (it)
2442                                         break;
2443                         }
2444                         mISDNport = mISDNport->next;
2445                 }
2446                 if (mISDNport)
2447                 {
2448                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
2449                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
2450
2451                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
2452                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
2453                         ret = it->function(it->data);
2454                 } else
2455                 {
2456                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
2457                 }
2458                 goto out;
2459         }
2460
2461         /* find the mISDNport that belongs to the stack */
2462         mISDNport = mISDNport_first;
2463         while(mISDNport)
2464         {
2465                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
2466                         break;
2467                 mISDNport = mISDNport->next;
2468         } 
2469         if (!mISDNport)
2470         {
2471                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2472                 // show a list of all mISDNports and their address
2473 #if 0
2474                 mISDNport = mISDNport_first;
2475                 while(mISDNport)
2476                 {
2477                         PERROR(" port %s  %x -> %x\n", mISDNport->name, (frm->addr&MASTER_ID_MASK), (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK));
2478                         mISDNport = mISDNport->next;
2479                 } 
2480 #endif
2481                 goto out;
2482         }
2483
2484         /* master stack */
2485         if (!(frm->addr&FLG_CHILD_STACK))
2486         {
2487                 /* d-message */
2488                 switch(frm->prim)
2489                 {
2490                         case MGR_SHORTSTATUS | INDICATION:
2491                         case MGR_SHORTSTATUS | CONFIRM:
2492                         switch(frm->dinfo) {
2493                                 case SSTATUS_L1_ACTIVATED:
2494                                 l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2495                                 end_trace();
2496                                 goto ss_act;
2497                                 case SSTATUS_L1_DEACTIVATED:
2498                                 l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2499                                 end_trace();
2500                                 goto ss_deact;
2501                                 case SSTATUS_L2_ESTABLISHED:
2502                                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ | (frm->prim & 0x3), DIRECTION_IN);
2503                                 end_trace();
2504                                 goto ss_estab;
2505                                 case SSTATUS_L2_RELEASED:
2506                                 l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2507                                 end_trace();
2508                                 goto ss_rel;
2509                         }
2510                         break;
2511
2512                         case PH_ACTIVATE | CONFIRM:
2513                         case PH_ACTIVATE | INDICATION:
2514                         l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2515                         end_trace();
2516                         if (mISDNport->ntmode)
2517                         {
2518                                 mISDNport->l1link = 1;
2519                                 setup_queue(mISDNport, 1);
2520                                 goto l1_msg;
2521                         }
2522                         ss_act:
2523                         mISDNport->l1link = 1;
2524                         setup_queue(mISDNport, 1);
2525                         break;
2526
2527                         case PH_DEACTIVATE | CONFIRM:
2528                         case PH_DEACTIVATE | INDICATION:
2529                         l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2530                         end_trace();
2531                         if (mISDNport->ntmode)
2532                         {
2533                                 mISDNport->l1link = 0;
2534                                 setup_queue(mISDNport, 0);
2535                                 goto l1_msg;
2536                         }
2537                         ss_deact:
2538                         mISDNport->l1link = 0;
2539                         setup_queue(mISDNport, 0);
2540                         break;
2541
2542                         case PH_CONTROL | CONFIRM:
2543                         case PH_CONTROL | INDICATION:
2544                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2545                         break;
2546
2547                         case DL_ESTABLISH | INDICATION:
2548                         case DL_ESTABLISH | CONFIRM:
2549                         l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_REQ | (frm->prim & 0x3), DIRECTION_IN);
2550                         end_trace();
2551                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2552                         ss_estab:
2553                         if (mISDNport->l2establish)
2554                         {
2555                                 mISDNport->l2establish = 0;
2556                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2557                         }
2558                         mISDNport->l2link = 1;
2559                         break;
2560
2561                         case DL_RELEASE | INDICATION:
2562                         case DL_RELEASE | CONFIRM:
2563                         l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE_REQ | (frm->prim & 0x3), DIRECTION_IN);
2564                         end_trace();
2565                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2566                         ss_rel:
2567                         mISDNport->l2link = 0;
2568                         if (mISDNport->ptp)
2569                         {
2570                                 time(&mISDNport->l2establish);
2571                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2572                         }
2573                         break;
2574
2575                         default:
2576                         l1_msg:
2577                         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);
2578                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2579                         {
2580                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2581                         }
2582                         /* d-message */
2583                         if (mISDNport->ntmode)
2584                         {
2585                                 /* l1-data enters the nt-mode library */
2586                                 nst = &mISDNport->nst;
2587                                 if (nst->l1_l2(nst, msg))
2588                                         free_msg(msg);
2589                                 return(1);
2590                         } else
2591                         {
2592                                 /* l3-data is sent to pbx */
2593                                 if (stack2manager_te(mISDNport, msg))
2594                                         free_msg(msg);
2595                                 return(1);
2596                         }
2597                 }
2598         } else
2599         /* child stack */
2600         {
2601                 /* b-message */
2602                 switch(frm->prim)
2603                 {
2604                         /* we don't care about confirms, we use rx data to sync tx */
2605                         case PH_DATA | CONFIRM:
2606                         case DL_DATA | CONFIRM:
2607                         break;
2608
2609                         /* we receive audio data, we respond to it AND we send tones */
2610                         case PH_DATA | INDICATION:
2611                         case DL_DATA | INDICATION:
2612                         case PH_CONTROL | INDICATION:
2613                         case PH_SIGNAL | INDICATION:
2614                         i = 0;
2615                         while(i < mISDNport->b_num)
2616                         {
2617                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2618                                         break;
2619                                 i++;
2620                         }
2621                         if (i == mISDNport->b_num)
2622                         {
2623                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2624                                 break;
2625                         }
2626                         if (mISDNport->b_port[i])
2627                         {
2628 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2629                                 mISDNport->b_port[i]->bchannel_receive(frm);
2630                         } else
2631                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2632                         break;
2633
2634                         case PH_ACTIVATE | INDICATION:
2635                         case DL_ESTABLISH | INDICATION:
2636                         case PH_ACTIVATE | CONFIRM:
2637                         case DL_ESTABLISH | CONFIRM:
2638                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2639                         i = 0;
2640                         while(i < mISDNport->b_num)
2641                         {
2642                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2643                                         break;
2644                                 i++;
2645                         }
2646                         if (i == mISDNport->b_num)
2647                         {
2648                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2649                                 break;
2650                         }
2651                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2652                         break;
2653
2654                         case PH_DEACTIVATE | INDICATION:
2655                         case DL_RELEASE | INDICATION:
2656                         case PH_DEACTIVATE | CONFIRM:
2657                         case DL_RELEASE | CONFIRM:
2658                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2659                         i = 0;
2660                         while(i < mISDNport->b_num)
2661                         {
2662                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2663                                         break;
2664                                 i++;
2665                         }
2666                         if (i == mISDNport->b_num)
2667                         {
2668                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2669                                 break;
2670                         }
2671                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2672                         break;
2673
2674                         default:
2675                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2676                 }
2677         }
2678
2679         out:
2680         free_msg(msg);
2681         return(1);
2682 }
2683 #endif
2684
2685 #ifdef SOCKET_MISDN
2686 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2687 {
2688         struct mISDNport *mISDNport = ml3->private;
2689
2690         if (cmd == MT_ASSIGN)
2691         {
2692                 if (angeforderte, dann schreiben, weil wir )
2693                 ueberdenken!!!
2694         }
2695         
2696         /* lock LCR */
2697         pthread_mutex_lock(&mutex_lcr);
2698         achtung MT_ASSIGN kommt hier an
2699
2700         /* d-message */
2701         switch(cmd)
2702         {
2703 #warning shortstatus
2704 #if 0
2705                 case MGR_SHORTSTATUS_IND:
2706                 case MGR_SHORTSTATUS_CONF:
2707                 switch(frm->dinfo) {
2708                         case SSTATUS_L1_ACTIVATED:
2709                         l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
2710                         end_trace();
2711                         goto ss_act;
2712                         case SSTATUS_L1_DEACTIVATED:
2713                         l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
2714                         end_trace();
2715                         goto ss_deact;
2716                         case SSTATUS_L2_ESTABLISHED:
2717                         l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
2718                         end_trace();
2719                         goto ss_estab;
2720                         case SSTATUS_L2_RELEASED:
2721                         l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
2722                         end_trace();
2723                         goto ss_rel;
2724                 }
2725                 break;
2726 #endif
2727
2728                 case MT_L1ACTIVATE:
2729                 l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
2730                 end_trace();
2731 //              ss_act:
2732                 mISDNport->l1link = 1;
2733 #if 0
2734                 if (mISDNport->ntmode)
2735                         setup_queue(mISDNport, 1);
2736 #endif
2737                 break;
2738
2739                 case MT_L1DEACTIVATE:
2740                 l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
2741                 end_trace();
2742 //              ss_deact:
2743                 mISDNport->l1link = 0;
2744 raus mit der setup-queue, da dies im stack geschieht
2745 #if 0
2746                 if (mISDNport->ntmode)
2747                         setup_queue(mISDNport, 0);
2748 #endif
2749                 break;
2750
2751                 case MT_L1CONTROL:
2752                 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2753                 // special config commands for interface (ip-address/LOS/AIS/RDI/SLIP)
2754                 break;
2755
2756                 case MT_L2ESTABLISH:
2757                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
2758                 end_trace();
2759 //              ss_estab:
2760                 if (mISDNport->l2establish)
2761                 {
2762                         mISDNport->l2establish = 0;
2763                         PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2764                 }
2765                 mISDNport->l2link = 1;
2766                 break;
2767
2768                 case MT_L2RELEASE:
2769                 l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
2770                 end_trace();
2771 //              ss_rel:
2772                 mISDNport->l2link = 0;
2773                 if (mISDNport->ptp)
2774                 {
2775                         time(&mISDNport->l2establish);
2776                         PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2777                 }
2778                 break;
2779
2780                 default:
2781                 /* l3-data is sent to LCR */
2782                 stack2manager(mISDNport, cmd, pid, l3m);
2783         }
2784
2785         /* free message */
2786         if (l3m)
2787                 free_l3_msg(l3m);
2788
2789         /* unlock LCR */
2790         pthread_mutex_unlock(&mutex_lcr);
2791
2792         return(0);
2793
2794 }
2795 #endif
2796
2797
2798 /*
2799  * global function to add a new card (port)
2800  */
2801 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, int force_nt, struct interface *interface)
2802 {
2803         int ret;
2804         unsigned char buff[1025];
2805         iframe_t *frm = (iframe_t *)buff;
2806         struct mISDNport *mISDNport, **mISDNportp;
2807         int i, cnt;
2808         int pri, bri, ports;
2809         int nt, te;
2810 #ifdef SOCKET_MISDN
2811         struct mlayer3 *ml3;
2812         struct mISDN_devinfo devinfo;
2813
2814         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2815         if (ret < 0)
2816         {
2817                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2818                 return(NULL);
2819         }
2820 #else
2821 //      interface_info_t ii;
2822         net_stack_t *nst;
2823         manager_t *mgr;
2824         layer_info_t li;
2825         stack_info_t *stinf;
2826
2827         /* query port's requirements */
2828         cnt = mISDN_get_stack_count(mISDNdevice);
2829 #endif
2830
2831         if (cnt <= 0)
2832         {
2833                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2834                 return(NULL);
2835         }
2836         if (port>cnt || port<1)
2837         {
2838                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2839                 return(NULL);
2840         }
2841
2842         pri = bri = ports = nt = te = 0;
2843 #ifdef SOCKET_MISDN
2844         devinfo.id = port - 1;
2845         ret = ioctl(socket, IMGETDEVINFO, &devinfo);
2846         if (ret <= 0)
2847         {
2848                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2849                 break;
2850         }
2851         /* output the port info */
2852         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2853         {
2854                 bri = 1;
2855                 te = 1;
2856         }
2857         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2858         {
2859                 bri = 1;
2860                 nt = 1;
2861         }
2862 #ifdef ISDN_P_TE_E1
2863         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2864         {
2865                 pri = 1;
2866                 te = 1;
2867         }
2868 #endif
2869 #ifdef ISDN_P_NT_E1
2870         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2871         {
2872                 pri = 1;
2873                 nt = 1;
2874         }
2875 #endif
2876 #ifdef ISDN_P_FXS
2877         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2878         {
2879                 pots = 1;
2880                 te = 1;
2881         }
2882 #endif
2883 #ifdef ISDN_P_FXO
2884         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2885         {
2886                 pots = 1;
2887                 nt = 1;
2888         }
2889 #endif
2890         if (force_nt && !nt)
2891         {
2892                 PERROR_RUNTIME("Port %d does not support NT-mode.\n", port);
2893                 return(NULL);
2894         }
2895         if (bri && pri)
2896         {
2897                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2898                 return(NULL);
2899         }
2900         if (pots && !bri && !pri)
2901         {
2902                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2903                 return(NULL);
2904         }
2905         if (!bri && !pri)
2906         {
2907                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2908                 return(NULL);
2909         }
2910         if (!nt && !te)
2911         {
2912                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2913                 return(NULL);
2914         }
2915         /* force nt, by turning off TE */
2916         if (force_nt && nt)
2917                 te = 0;
2918         /* if TE an NT is supported (and not forced to NT), turn off NT */
2919         if (te && nt)
2920                 nt = 0;
2921 #else
2922         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2923         if (ret < 0)
2924         {
2925                 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2926                 return(NULL);
2927         }
2928         stinf = (stack_info_t *)&frm->data.p;
2929         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2930         {
2931                 case ISDN_PID_L0_TE_S0:
2932                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2933                 break;
2934                 case ISDN_PID_L0_NT_S0:
2935                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2936                 nt = 1;
2937                 break;
2938                 case ISDN_PID_L0_TE_E1:
2939                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
2940                 pri = 1;
2941                 break;
2942                 case ISDN_PID_L0_NT_E1:
2943                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
2944                 pri = 1;
2945                 nt = 1;
2946                 break;
2947                 default:
2948                 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2949                 return(NULL);
2950         }
2951         if (nt)
2952         {
2953                 /* NT */
2954                 if (stinf->pid.protocol[1] == 0)
2955                 {
2956                         PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2957                         return(NULL);
2958                 }
2959                 if (stinf->pid.protocol[2])
2960                 {
2961                         PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2962                         return(NULL);
2963                 }
2964         }
2965         if (te)
2966         {
2967                 /* TE */
2968                 if (stinf->pid.protocol[1] == 0)
2969                 {
2970                         PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2971                         return(NULL);
2972                 }
2973                 if (stinf->pid.protocol[2] == 0)
2974                 {
2975                         PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2976                         return(NULL);
2977                 }
2978                 if (stinf->pid.protocol[3] == 0)
2979                 {
2980                         PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2981                         return(NULL);
2982                 } else
2983                 {
2984                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2985                         {
2986                                 case ISDN_PID_L3_DSS1USER:
2987                                 break;
2988
2989                                 default:
2990                                 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2991                                 return(NULL);
2992                         }
2993                 }
2994                 if (stinf->pid.protocol[4])
2995                 {
2996                         PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2997                         return(NULL);
2998                 }
2999         }
3000 #endif
3001
3002         /* add mISDNport structure */
3003         mISDNportp = &mISDNport_first;
3004         while(*mISDNportp)
3005                 mISDNportp = &((*mISDNportp)->next);
3006         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
3007         pmemuse++;
3008         *mISDNportp = mISDNport;
3009
3010         /* allocate ressources of port */
3011 #ifdef SOCKET_MISDN
3012         /* open layer 3 */
3013         protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
3014         prop = 0;
3015         if (ptp)
3016                prop |= FLG_PTP;
3017         if (ptmp && pri)
3018                prop |= FLG_FORCE_PTMP;
3019         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
3020         if (!mISDNport->ml3)
3021         {
3022                 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
3023                 return(NULL);
3024         }
3025
3026 #if 0
3027         /* if ntmode, establish L1 to send the tei removal during start */
3028         if (mISDNport->ntmode)
3029         {
3030                 iframe_t act;
3031                 /* L1 */
3032                 act.prim = PH_ACTIVATE | REQUEST; 
3033                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
3034                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
3035                 act.dinfo = 0;
3036                 act.len = 0;
3037                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3038                 usleep(10000); /* to be sure, that l1 is up */
3039         }
3040 #endif
3041
3042         SCPY(mISDNport->name, devinfo.name);
3043         mISDNport->b_num = devinfo.nrbchan;
3044 #else
3045         msg_queue_init(&mISDNport->downqueue);
3046         mISDNport->d_stid = stinf->id;
3047         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
3048         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
3049         {
3050                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
3051                 ptp = 1;
3052                 if (ptmp && nt)
3053                 {
3054                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
3055                         ptp = 0;
3056                 }
3057         }
3058
3059         /* create layer intance */
3060         memset(&li, 0, sizeof(li));
3061         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
3062         li.object_id = -1;
3063         li.extentions = 0;
3064         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
3065         li.pid.layermask = ISDN_LAYER((nt?2:4));
3066         li.st = mISDNport->d_stid;
3067         ret = mISDN_new_layer(mISDNdevice, &li);
3068         if (ret)
3069         {
3070                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
3071                 closeport:
3072                 mISDNport_close(mISDNport);
3073                 return(NULL);
3074         }
3075         mISDNport->upper_id = li.id;
3076         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
3077         if (ret)
3078         {
3079                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
3080                 goto closeport;
3081         }
3082         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
3083         if (mISDNport->lower_id < 0)
3084         {
3085                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
3086                 goto closeport;
3087         }
3088         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
3089         if (mISDNport->upper_id < 0)
3090         {
3091                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
3092                 goto closeport;
3093         }
3094         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
3095
3096         /* if ntmode, establish L1 to send the tei removal during start */
3097         if (mISDNport->ntmode)
3098         {
3099                 iframe_t act;
3100                 /* L1 */
3101                 act.prim = PH_ACTIVATE | REQUEST; 
3102                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
3103                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
3104                 act.dinfo = 0;
3105                 act.len = 0;
3106                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3107                 usleep(10000); /* to be sure, that l1 is up */
3108         }
3109
3110         /* create nst (nt-mode only) */
3111         if (nt)
3112         {
3113                 mgr = &mISDNport->mgr;
3114                 nst = &mISDNport->nst;
3115
3116                 mgr->nst = nst;
3117                 nst->manager = mgr;
3118
3119                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
3120                 nst->device = mISDNdevice;
3121                 nst->cardnr = port;
3122                 nst->d_stid = mISDNport->d_stid;
3123
3124                 nst->feature = FEATURE_NET_HOLD;
3125                 if (ptp)
3126                         nst->feature |= FEATURE_NET_PTP;
3127                 if (pri)
3128                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
3129 #if 0
3130                 i = 0;
3131                 while(i < mISDNport->b_num)
3132                 {
3133                         nst->b_stid[i] = mISDNport->b_stid[i];
3134                         i++;
3135                 }
3136 #endif
3137                 nst->l1_id = mISDNport->lower_id;
3138                 nst->l2_id = mISDNport->upper_id;
3139
3140                 /* phd */       
3141                 msg_queue_init(&nst->down_queue);
3142
3143                 Isdnl2Init(nst);
3144                 Isdnl3Init(nst);
3145         }
3146
3147         mISDNport->b_num = stinf->childcnt;
3148 #endif
3149         mISDNport->portnum = port;
3150         mISDNport->ntmode = nt;
3151         mISDNport->pri = pri;
3152         mISDNport->ptp = ptp;
3153         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
3154         i = 0;
3155         while(i < mISDNport->b_num)
3156         {
3157                 mISDNport->b_state[i] = B_STATE_IDLE;
3158 #ifdef SOCKET_MISDN
3159                 mISDNport->b_socket = -1;
3160 #else
3161                 mISDNport->b_stid[i] = stinf->child[i];
3162                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
3163 #endif
3164                 i++;
3165         }
3166
3167         /* if te-mode, query state link */
3168         if (!mISDNport->ntmode)
3169         {
3170                 iframe_t act;
3171                 /* L2 */
3172                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
3173                 act.prim = MGR_SHORTSTATUS | REQUEST; 
3174                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
3175                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
3176                 act.len = 0;
3177                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3178         }
3179         /* if ptp AND te-mode, pull up the link */
3180         if (mISDNport->ptp && !mISDNport->ntmode)
3181         {
3182                 iframe_t act;
3183                 /* L2 */
3184                 act.prim = DL_ESTABLISH | REQUEST; 
3185                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
3186                 act.dinfo = 0;
3187                 act.len = 0;
3188                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3189         }
3190         /* if ptp AND nt-mode, pull up the link */
3191         if (mISDNport->ptp && mISDNport->ntmode)
3192         {
3193                 msg_t *dmsg;
3194                 /* L2 */
3195                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
3196                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
3197                         free_msg(dmsg);
3198         }
3199         /* initially, we assume that the link is down, exept for nt-ptmp */
3200         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
3201
3202         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
3203
3204         start_trace(mISDNport->portnum,
3205                     interface,
3206                     NULL,
3207                     NULL,
3208                     DIRECTION_NONE,
3209                     CATEGORY_CH,
3210                     0,
3211                     "PORT (open)");
3212         add_trace("channels", NULL, "%d", mISDNport->b_num);
3213         end_trace();
3214         return(mISDNport);
3215 }
3216
3217
3218 /*
3219  * function to free ALL cards (ports)
3220  */
3221 void mISDNport_close_all(void)
3222 {
3223         /* free all ports */
3224         while(mISDNport_first)
3225                 mISDNport_close(mISDNport_first);
3226 }
3227
3228 /*
3229  * free only one port
3230  */
3231 void mISDNport_close(struct mISDNport *mISDNport)
3232 {
3233         struct mISDNport **mISDNportp;
3234         class Port *port;
3235         class PmISDN *isdnport;
3236         net_stack_t *nst;
3237         unsigned char buf[32];
3238         int i;
3239
3240         /* remove all port instance that are linked to this mISDNport */
3241         port = port_first;
3242         while(port)
3243         {
3244                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
3245                 {
3246                         isdnport = (class PmISDN *)port;
3247                         if (isdnport->p_m_mISDNport)
3248                         {
3249                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
3250                                 delete isdnport;
3251                         }
3252                 }
3253                 port = port->next;
3254         }
3255
3256         /* only if we are already part of interface */
3257         if (mISDNport->ifport)
3258         {
3259                 start_trace(mISDNport->portnum,
3260                             mISDNport->ifport->interface,
3261                             NULL,
3262                             NULL,
3263                             DIRECTION_NONE,
3264                             CATEGORY_CH,
3265                             0,
3266                             "PORT (close)");
3267                 end_trace();
3268         }
3269
3270         /* free bchannels */
3271         i = 0;
3272         while(i < mISDNport->b_num)
3273         {
3274                 if (mISDNport->b_addr[i])
3275                 {
3276                         _bchannel_destroy(mISDNport, i);
3277                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
3278                 }
3279                 i++;
3280         }
3281
3282 #ifdef SOCKET_MISDN
3283         close_layer3(mISDNport->ml3);
3284 #else
3285         /* free ressources of port */
3286         msg_queue_purge(&mISDNport->downqueue);
3287
3288         /* free stacks */
3289         if (mISDNport->ntmode)
3290         {
3291                 nst = &mISDNport->nst;
3292                 if (nst->manager) /* to see if initialized */
3293                 {
3294                         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");
3295                         cleanup_Isdnl3(nst);
3296                         cleanup_Isdnl2(nst);
3297
3298                         /* phd */
3299                         msg_queue_purge(&nst->down_queue);
3300                         if (nst->phd_down_msg)
3301                                 FREE(nst->phd_down_msg, 0);
3302                 }
3303         }
3304
3305         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
3306         if (mISDNport->d_stid)
3307         {
3308                 if (mISDNport->upper_id)
3309                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
3310         }
3311 #endif
3312
3313         /* remove from list */
3314         mISDNportp = &mISDNport_first;
3315         while(*mISDNportp)
3316         {
3317                 if (*mISDNportp == mISDNport)
3318                 {
3319                         *mISDNportp = (*mISDNportp)->next;
3320                         mISDNportp = NULL;
3321                         break;
3322                 }
3323                 mISDNportp = &((*mISDNportp)->next);
3324         }
3325
3326         if (mISDNportp)
3327                 FATAL("mISDNport not in list\n");
3328         
3329         FREE(mISDNport, sizeof(struct mISDNport));
3330         pmemuse--;
3331
3332 }
3333
3334
3335 /*
3336  * global function to show all available isdn ports
3337  */
3338 void mISDN_port_info(void)
3339 {
3340         int ret;
3341         int i, ii, p;
3342         int useable, nt, te, pri, bri, pots;
3343         unsigned char buff[1025];
3344         iframe_t *frm = (iframe_t *)buff;
3345 #ifdef SOCKET_MISDN
3346         struct mISDN_devinfo devinfo;
3347         int socket;
3348
3349         /* open mISDN */
3350         socket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
3351         if (socket < 0)
3352         {
3353                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
3354                 exit(EXIT_FAILURE);
3355         }
3356
3357         /* get number of stacks */
3358         i = 1;
3359         ret = ioctl(socket, IMGETCOUNT, &ii);
3360         if (ret < 0)
3361         {
3362                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
3363                 goto done;
3364         }
3365 #else
3366         stack_info_t *stinf;
3367         int device;
3368
3369         /* open mISDN */
3370         if ((device = mISDN_open()) < 0)
3371         {
3372                 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));
3373                 exit(EXIT_FAILURE);
3374         }
3375
3376         /* get number of stacks */
3377         i = 1;
3378         ii = mISDN_get_stack_count(device);
3379 #endif
3380         printf("\n");
3381         if (ii <= 0)
3382         {
3383                 printf("Found no card. Please be sure to load card drivers.\n");
3384                 goto done;
3385         }
3386
3387         /* loop the number of cards and get their info */
3388         while(i <= ii)
3389         {
3390                 nt = te = bri = pri = pots = 0;
3391                 useable = 0;
3392
3393 #ifdef SOCKET_MISDN
3394                 devinfo.id = i - 1;
3395                 ret = ioctl(socket, IMGETDEVINFO, &devinfo);
3396                 if (ret <= 0)
3397                 {
3398                         fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
3399                         break;
3400                 }
3401
3402                 /* output the port info */
3403                 printf("Port %2d name='%s': ", i, devinfo.name);
3404                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
3405                 {
3406                         bri = 1;
3407                         te = 1;
3408                 }
3409                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
3410                 {
3411                         bri = 1;
3412                         nt = 1;
3413                 }
3414 #ifdef ISDN_P_TE_E1
3415                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
3416                 {
3417                         pri = 1;
3418                         te = 1;
3419                 }
3420 #endif
3421 #ifdef ISDN_P_NT_E1
3422                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
3423                 {
3424                         pri = 1;
3425                         nt = 1;
3426                 }
3427 #endif
3428 #ifdef ISDN_P_FXS
3429                 if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
3430                 {
3431                         pots = 1;
3432                         te = 1;
3433                 }
3434 #endif
3435 #ifdef ISDN_P_FXO
3436                 if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
3437                 {
3438                         pots = 1;
3439                         nt = 1;
3440                 }
3441 #endif
3442                 if ((te || nt) && (bri || pri || ports))
3443                         usable = 1;
3444
3445                 if (te && bri)
3446                         printf("TE-mode BRI S/T interface line (for phone lines)");
3447                 if (nt && bri)
3448                         printf("NT-mode BRI S/T interface port (for phones)");
3449                 if (te && pri)
3450                         printf("TE-mode PRI E1  interface line (for phone lines)");
3451                 if (nt && pri)
3452                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3453                 if (te && pots)
3454                         printf("FXS     POTS    interface port (for analog lines)");
3455                 if (nt && pots)
3456                         printf("FXO     POTS    interface port (for analog phones)");
3457                 if (ports)
3458                 {
3459                         usable = 0;
3460                         printf("\n -> Analog interfaces are not supported.");
3461                 } else
3462                 if (!usable)
3463                 {
3464                         printf("unsupported interface protocol bits 0x%016x", devinfo.Dprotocols);
3465                 }
3466                 printf("\n");
3467
3468                 printf("  - %d B-channels\n", devinfo.nfbchan);
3469 #else
3470                 ret = mISDN_get_stack_info(device, i, buff, sizeof(buff));
3471                 if (ret <= 0)
3472                 {
3473                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d error=%d\n", i, ret);
3474                         break;
3475                 }
3476                 stinf = (stack_info_t *)&frm->data.p;
3477
3478                 /* output the port info */
3479                 printf("Port %2d: ", i);
3480                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
3481                 {
3482                         case ISDN_PID_L0_TE_S0:
3483                         useable = 1;
3484                         te = 1;
3485                         bri = 1;
3486                         printf("TE-mode BRI S/T interface line (for phone lines)");
3487                         break;
3488                         case ISDN_PID_L0_NT_S0:
3489                         useable = 1;
3490                         nt = 1;
3491                         bri = 1;
3492                         printf("NT-mode BRI S/T interface port (for phones)");
3493                         break;
3494                         case ISDN_PID_L0_TE_E1:
3495                         useable = 1;
3496                         te = 1;
3497                         pri = 1;
3498                         printf("TE-mode PRI E1  interface line (for phone lines)");
3499                         break;
3500                         case ISDN_PID_L0_NT_E1:
3501                         useable = 1;
3502                         nt = 1;
3503                         pri = 1;
3504                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3505                         break;
3506                         default:
3507                         useable = 0;
3508                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
3509                 }
3510                 printf("\n");
3511
3512                 if (nt)
3513                 {
3514                         if (stinf->pid.protocol[1] == 0)
3515                         {
3516                                 useable = 0;
3517                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
3518                         }
3519                         p = 2;
3520                         while(p <= MAX_LAYER_NR) {
3521                                 if (stinf->pid.protocol[p])
3522                                 {
3523                                         useable = 0;
3524                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3525                                 }
3526                                 p++;
3527                         }
3528                         if (useable)
3529                         {
3530                                 if (pri)
3531                                         printf(" -> Interface is Point-To-Point (PRI).\n");
3532                                 else
3533                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
3534                         }
3535                 }
3536                 if (te)
3537                 {
3538                         if (stinf->pid.protocol[1] == 0)
3539                         {
3540                                 useable = 0;
3541                                 printf(" -> Missing layer 1 protocol.\n");
3542                         }
3543                         if (stinf->pid.protocol[2] == 0)
3544                         {
3545                                 useable = 0;
3546                                 printf(" -> Missing layer 2 protocol.\n");
3547                         }
3548                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
3549                         {
3550                                 printf(" -> Interface is Poin-To-Point.\n");
3551                         }
3552                         if (stinf->pid.protocol[3] == 0)
3553                         {
3554                                 useable = 0;
3555                                 printf(" -> Missing layer 3 protocol.\n");
3556                         } else
3557                         {
3558                                 printf(" -> Protocol: ");
3559                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
3560                                 {
3561                                         case ISDN_PID_L3_DSS1USER:
3562                                         printf("DSS1 (Euro ISDN)");
3563                                         break;
3564
3565                                         default:
3566                                         useable = 0;
3567                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
3568                                 }
3569                                 printf("\n");
3570                         }
3571                         p = 4;
3572                         while(p <= MAX_LAYER_NR) {
3573                                 if (stinf->pid.protocol[p])
3574                                 {
3575                                         useable = 0;
3576                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3577                                 }
3578                                 p++;
3579                         }
3580                 }
3581                 printf("  - %d B-channels\n", stinf->childcnt);
3582 #endif
3583
3584                 if (!useable)
3585                         printf(" * Port NOT useable for LCR\n");
3586
3587                 printf("--------\n");
3588
3589                 i++;
3590         }
3591         printf("\n");
3592
3593 done:
3594 #ifdef SOCKET_MISDN
3595         close(sd);
3596 #else
3597         /* close mISDN */
3598         if ((ret = mISDN_close(device)))
3599                 FATAL("mISDN_close() failed: err=%d '%s'\n", ret, strerror(ret));
3600 #endif
3601 }
3602
3603
3604 /*
3605  * enque data from upper buffer
3606  */
3607 void PmISDN::txfromup(unsigned char *data, int length)
3608 {
3609 #ifdef SOCKET_MISDN
3610         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3611         struct mISDNhead *frm = (struct mISDNhead *)buf;
3612
3613         if (p_m_b_index < 0)
3614                 return;
3615         if (!p_m_mISDNport->b_socket[p_m_b_index])
3616                 return;
3617 #else
3618         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3619         iframe_t *frm = (iframe_t *)buf;
3620
3621         if (p_m_b_index < 0)
3622                 return;
3623         if (!p_m_mISDNport->b_addr[p_m_b_index])
3624                 return;
3625 #endif
3626
3627         /* check if high priority tones exist
3628          * ignore data in this case
3629          */
3630         if (p_tone_name[0] || p_m_crypt_msg_loops)
3631                 return;
3632
3633         /* preload procedure
3634          * if transmit buffer in DSP module is empty,
3635          * preload it to DSP_LOAD to prevent jitter gaps.
3636          */
3637         if (p_m_load==0 && ISDN_LOAD>0)
3638         {
3639
3640                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
3641                 frm->len = ISDN_LOAD;
3642                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3643                 p_m_load += frm->len;
3644         }
3645
3646         /* drop if load would exceed ISDN_MAXLOAD
3647          * this keeps the delay not too high
3648          */
3649         if (p_m_load+length > ISDN_MAXLOAD)
3650                 return;
3651
3652         /* make and send frame */
3653 #ifdef SOCKET_MISDN
3654         frm->prim = DL_DATA_REQ;
3655         frm->id = 0;
3656         memcpy(buf+MISDN_HEADER_LEN, data, length);
3657         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
3658         if (!ret)
3659                 PERROR("Failed to send to socket %d\n", handle);
3660 #else
3661         frm->prim = DL_DATA | REQUEST; 
3662         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
3663         frm->dinfo = 0;
3664         frm->len = length;
3665         memcpy(buf+mISDN_HEADER_LEN, data, length);
3666         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3667 #endif
3668         p_m_load += length;
3669 }
3670