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